External serial 8250/16550
Hi,
I was called for help to add a external serial using a board based on at91sam9g45, was useded chip TL16c2550 conected on EBI1_D[0-7] for data and EBI_A[0-2] for address register.
There are two UART in this chip which will be select by EBI1_NCS1 and PC13/NCS2
I'm trying to register this uart in this way:
static struct plat_serial8250_port tms_serial_data[] = {
PORT(0x70000000, AT91_PIN_PC0),
PORT(0x80000000, AT91_PIN_PC1),
{ },
};static struct platform_device tms_serial_device = {
.name = "serial8250",
.id = -1,
.dev =
{
.platform_data = &tms_serial_data,
},
};static void tms_add_device_serial(void)
{
at91_sys_write(AT91_SMC_CSR(1),
AT91_SMC_ACSS_STD
| AT91_SMC_DBW_8
| AT91_SMC_BAT
| AT91_SMC_WSEN
| AT91_SMC_NWS_(32) /* wait states */
| AT91_SMC_RWSETUP_(6) /* setup time */
| AT91_SMC_RWHOLD_(4) /* hold time */
);
at91_sys_write(AT91_SMC_CSR(2),
AT91_SMC_ACSS_STD
| AT91_SMC_DBW_8
| AT91_SMC_BAT
| AT91_SMC_WSEN
| AT91_SMC_NWS_(32) /* wait states */
| AT91_SMC_RWSETUP_(6) /* setup time */
| AT91_SMC_RWHOLD_(4) /* hold time */
);
platform_device_register(&tms_serial_device);
}//#endif
static void __init ek_map_io(void)
{
/* Initialize processor: 12.000 MHz crystal */
at91sam9g45_initialize(12000000);
/* DGBU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
/* USART0 on ttyS2. (Rx, Tx, RTS, CTS) - Used by smartcard */
at91_register_uart(AT91SAM9G45_ID_US0, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
/* USART1 on ttyS1. (Rx, Tx, RTS, CTS) */
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
/* set serial console to ttyS0 (ie, DBGU) */
at91_set_serial_console(0);
/* antes: at91_init_serial(&tms_uart_config); */
/* how to map IO */
}static void __init ek_board_init(void)
{
/* Serial */
at91_add_device_serial();
...
/* External Serial */
tms_add_device_serial();
}But doesn't work, how to map correctly external serial port?
Is there any sample code for external uart using linux-2.6.36 and arm AT91SAM9?
Thanks.
Paulo.
hi Paulo,
Quoted 5 lines
I was called for help to add a external serial using a board based on at91sam9g45,
? ? ? ?at91_sys_write(AT91_SMC_CSR(1),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AT91_SMC_ACSS_STD
Quoted 8 lines
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| AT91_SMC_DBW_8 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| AT91_SMC_BAT ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| AT91_SMC_WSEN ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| AT91_SMC_NWS_(32) ? ? /* wait states */ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| AT91_SMC_RWSETUP_(6) ?/* setup time */ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| AT91_SMC_RWHOLD_(4) ? /* hold time */? ? ? ?);
Those AT91_SMC registers and bits only exist on the AT91RM9200, whereas you're using a SAM9-based processor.
You should be configuring the memory controller by:
#include <mach/at91sam9_smc.h>
#include "sam9_smc.h"
and declaring a "struct sam9_smc_config" with all the setting & timings, and then calling:
sam9_smc_configure(CHIP_SELECT_NUMBER, &your_smc_config_struct);
Quoted 1 line
But doesn't work, how to map correctly external serial port?
If you specify UPF_IOREMAP in the "struct plat_serial8250_port" flags, the serial-driver will automatically map the IO region for you.
Quoted 2 lines
Is there any sample code for external uart using linux-2.6.36 and arm AT91SAM9?
Not for a SAM9-based board. But for an AT91RM9200 example, look at board-tms.c in the AT91 patches on http://maxim.org.za/at91_26.html . SAM9 should be the same, except for the SMC memory-controller configuration (as described above).
Regards,
Andrew Victor
Em 26/04/2011 13:39, Andrew Victor escreveu:
Quoted 9 lines
Those
AT91_SMCregisters and bits only exist on the AT91RM9200, whereas you're using a SAM9-based processor.You should be configuring the memory controller by:
#include<mach/at91sam9_smc.h> #include "sam9_smc.h"and declaring a "struct
sam9_smc_config" with all the setting&
I changed the code following TL16C2550 datasheet and now I am using correct registers for AT91sam:
static struct sam9_smc_config tms_uart_smc_config = {
.ncs_read_setup = 0,
.nrd_setup = 2,
.ncs_write_setup = 0,
.nwe_setup = 2,
.ncs_read_pulse = 5,
.nrd_pulse = 4,
.ncs_write_pulse = 4,
.nwe_pulse = 3,
.read_cycle = 10,
.write_cycle = 9,
.mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE |
AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8 | AT91_SMC_BAT_WRITE,
.tdf_cycles = 3,
};Quoted 2 lines
timings, and then calling:
sam9_smc_configure(CHIP_SELECT_NUMBER,&your_smc_config_struct);
#define SERIAL_FLAGS (UPF_BOOT_AUTOCONF | UPF_IOREMAP| UPF_SHARE_IRQ)
#define SERIAL_CLK (1843200)
#define PORT(_base, _irq) \
{ \
.mapbase = _base, \
.irq = _irq, \
.uartclk = SERIAL_CLK, \
.iotype = UPIO_MEM, \
.regshift = 0, \
.flags = SERIAL_FLAGS, \
}static struct plat_serial8250_port tms_uart_data[] = {
PORT(AT91_CHIPSELECT_1, AT91_PIN_PC0),
PORT(AT91_CHIPSELECT_2, AT91_PIN_PC1),
{ },
};static struct platform_device tms_uart_device = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM,
.dev =
{
.platform_data = &tms_uart_data,
},
};Quoted 3 lines
If you specify
UPF_IOREMAPin the "structplat_serial8250_port" flags, the serial-driver will automatically map the IO region for you.
and I am trying init in this way:
static void __init ek_board_init(void)
{
/* Serial */
at91_add_device_serial();
/* USB HS Host */
at91_add_device_usbh_ohci(&ek_usbh_hs_data);
at91_add_device_usbh_ehci(&ek_usbh_hs_data);
/* USB HS Device */
at91_add_device_usba(&ek_usba_udc_data);...
/* External serial */ tms_add_device_uart(); }
Quoted 5 lines
Not for a SAM9-based board. But for an AT91RM9200 example, look at
board-tms.cin the AT91 patches on http://maxim.org.za/at91_26.html . SAM9 should be the same, except for the SMC memory-controller configuration (as described above).
I'm getting kernel opps yet! What is wrong in my code?
Entire code is here:
http://users.nlink.com.br/~paulo/TMS/20110504/board-sweda_tms2.c
Thanks,
Paulo.
Quoted 4 lines
Regards,
Andrew Victor
Quoted 26 lines · Paulo Fragoso
Em 26/04/2011 13:39, Andrew Victor escreveu:
Quoted 9 lines
Those
AT91_SMCregisters and bits only exist on the AT91RM9200, whereas you're using a SAM9-based processor.You should be configuring the memory controller by:
#include<mach/at91sam9_smc.h>
#include "sam9_smc.h"and declaring a "struct
sam9_smc_config" with all the setting&I changed the code following TL16C2550 datasheet and now I am using correct registers for AT91sam:
static struct
sam9_smc_configtms_uart_smc_config= { .ncs_read_setup = 0,
.nrd_setup = 2,
.ncs_write_setup = 0,
.nwe_setup = 2,.ncs_read_pulse = 5,
.nrd_pulse = 4,
.ncs_write_pulse = 4,
.nwe_pulse = 3,
Quoted 8 lines
.read_cycle = 10,
.write_cycle = 9,.mode =
AT91_SMC_READMODE|AT91_SMC_WRITEMODE|AT91_SMC_EXNWMODE_DISABLE|AT91_SMC_DBW_8|AT91_SMC_BAT_WRITE, .tdf_cycles = 3,
};
I found an error on sam9_smc_configure call, now first (or second) serial was detected:
Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled serial8250.0: ttyS0 at MMIO 0x30000000 (irq = 97) is a 16550A
Whole code is on:
http://users.nlink.com.br/~paulo/TMS/20110509/board-sweda_tms2.c
Many Thanks,
Paulo.
Quoted 29 lines · Paulo Fragoso
Quoted 26 lines · Paulo Fragoso
Em 26/04/2011 13:39, Andrew Victor escreveu:
Quoted 9 lines
Those
AT91_SMCregisters and bits only exist on the AT91RM9200, whereas you're using a SAM9-based processor.You should be configuring the memory controller by:
#include<mach/at91sam9_smc.h>
#include "sam9_smc.h"and declaring a "struct
sam9_smc_config" with all the setting&I changed the code following TL16C2550 datasheet and now I am using correct registers for AT91sam:
static struct
sam9_smc_configtms_uart_smc_config= { .ncs_read_setup = 0,
.nrd_setup = 2,
.ncs_write_setup = 0,
.nwe_setup = 2,.ncs_read_pulse = 5,
.nrd_pulse = 4,
.ncs_write_pulse = 4,
.nwe_pulse = 3,
Quoted 8 lines
Quoted 8 lines
.read_cycle = 10,
.write_cycle = 9,.mode =
AT91_SMC_READMODE|AT91_SMC_WRITEMODE|AT91_SMC_EXNWMODE_DISABLE|AT91_SMC_DBW_8|AT91_SMC_BAT_WRITE, .tdf_cycles = 3,
};
I have one doubt about new-style UART initialization, how can I initialize a board using AT91sam9 with two internal USART and two external 8250 UART at same time?
For example:
/* DGBU on ttyS0. (Rx & Tx only) */ at91_register_uart(0, 0, 0); /* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */ at91_register_uart(AT91SAM9G45_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS); /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */ at91_register_uart(AT91SAM9G45_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
If I wish to put two more 8250 external serial in sequence (ttyS3 and ttyS4) which ID will be used at at91_register_uart function?
Looking at91_register_uart function all structs pdev are defined internaly, how I will define serila8250 platform_device and pass at at91_register_uart function?
Paulo.
Em 11/05/2011 23:23, Paulo Fragoso escreveu:
Quoted 16 lines · Paulo Fragoso
I have one doubt about new-style UART initialization, how can I initialize a board using AT91sam9 with two internal USART and two external 8250 UART at same time?
For example:
/* DGBU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);/* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
at91_register_uart(AT91SAM9G45_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);/* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
at91_register_uart(AT91SAM9G45_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
Quoted 6 lines
If I wish to put two more 8250 external serial in sequence (ttyS3 and ttyS4) which ID will be used at
at91_register_uartfunction?Looking
at91_register_uartfunction all structs pdev are defined internaly, how I will define serila8250platform_deviceand pass atat91_register_uartfunction?
I discovered NCS1 is always on level 0 (selected) and NCS2 is always on level 1, those lines never change its state after boot, and they were configured correctly:
sam9_smc_configure(1, &tms_uart_smc_config);
sam9_smc_configure(2, &tms_uart_smc_config);Entire file is here:
http://users.nlink.com.br/~paulo/TMS/20110519/board-sweda_tms2.c
This explain constant output on COMA from TL16C2550 and COMB is detected at boot time but doesn't work.
I will research what can be happening but what can be wrong with NCS1 and NCS2?
Thanks,
Paulo.
Quoted 6 lines · Paulo Fragoso
This explain constant output on COMA from TL16C2550 and COMB is detected at boot time but doesn't work.
I will research what can be happening but what can be wrong with NCS1 and NCS2?
All is working at boot time and NCS1 was correctly programed in bootstrap.
But no data out at serial line I'm testing enabling getty in inittab.
NCS1, NCS2, IOW and IOR are working how expected by the SMC config:
static struct sam9_smc_config tms_uart_smc_config = {
.ncs_read_setup = 0,
.nrd_setup = 2,
.ncs_write_setup = 0,
.nwe_setup = 2, .ncs_read_pulse = 5,
.nrd_pulse = 4,
.ncs_write_pulse = 4,
.nwe_pulse = 3, .read_cycle = 10,
.write_cycle = 9,
.mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE |AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8 | AT91_SMC_BAT_WRITE,
.tdf_cycles = 3,
};
Why isn't there any data on TX for COMA or COMB?
Paulo.
Quoted 28 lines · Paulo Fragoso
Quoted 6 lines · Paulo Fragoso
This explain constant output on COMA from TL16C2550 and COMB is detected at boot time but doesn't work.
I will research what can be happening but what can be wrong with NCS1 and NCS2?
All is working at boot time and NCS1 was correctly programed in bootstrap.
But no data out at serial line I'm testing enabling getty in inittab.
NCS1, NCS2, IOW and IOR are working how expected by the SMC config:
static struct
sam9_smc_configtms_uart_smc_config= { .ncs_read_setup = 0,
.nrd_setup = 2,
.ncs_write_setup = 0,
.nwe_setup = 2,.ncs_read_pulse = 5,
.nrd_pulse = 4,
.ncs_write_pulse = 4,
.nwe_pulse = 3,.read_cycle = 10,
.write_cycle = 9,
Quoted 6 lines
.mode =
AT91_SMC_READMODE|AT91_SMC_WRITEMODE|AT91_SMC_EXNWMODE_DISABLE|AT91_SMC_DBW_8|AT91_SMC_BAT_WRITE, .tdf_cycles = 3,
};Why isn't there any data on TX for COMA or COMB?
Hi Paulo,
I will have soon to do the same job on a SAM9G20 (but with a Quad UART). Did you try to access the registers of the UART? (You can do that from userspace:
ftp://ftp.embeddedarm.com/ts-arm-sbc/ts-7260-linux/sources/peekpoke.tar.gz). I think The UART has a scratch register, you could test if you can write and read back the data. Do you have any error messages in your logs? Have you try to use the stty program on your serial port, eg: stty -F /dev/ttySXYZ raw -clocal.
Perhaps your problem is on the transceiver side, have you try to tie Tx and Rx together and then read write date to the serial port from your embedded system?
Chris
Quoted 8 lines
Paulo.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel