This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

基于AM3359总线如何利用TL16C554扩展串口?

Other Parts Discussed in Thread: TL16C554, AM3359

看了网上好多关于TL16C554芯片的驱动实现,发现都与AM3359无关,按找例子做,也发现不行。

现把我们的硬件原理大致说明一下:

串口芯片TL16C554的A0~A2连接到AM3359的GPMC_A4~GPMC_A6;

串口芯片INTA~INTD连接到GPMC_A0~GPMC_A3;

串口芯片CSA~CSD连接到GPMC_CS6,GPMC_CS1,GPMC_CS2,GPMC_CS3

串口芯片的数据总线连接到GPMC_AD0~GPMC_AD7

串口芯片的RESET连接到GPMC_CLK

串口芯片的RXRDY连接到mii1_crs,而TXRDY连接到mii1_rxerr。

而读写使能引脚连接到了gpmc_oen_ren和gpmc_wen,和NAND Flash复用。

请问这样设计有问题吗,我不懂硬件原理。

我按照ST16C554的做法修改程序:

(1)在板子文件board-am335xevm.c中注册引脚

static struct pinmux_config tl16c554_pin_mux[] =
{
 //AM33XX_PIN_OUTPUT,AM33XX_PIN_OUTPUT_PULLUP
 //AM33XX_PIN_INPUT,AM33XX_PIN_INPUT_PULLUP,AM33XX_PIN_INPUT_PULLDOWN
 //中断引脚定义
 {"gpmc_a0.gpio1_16", OMAP_MUX_MODE7 | AM33XX_PIN_INPUT},
 {"gpmc_a1.gpio1_17", OMAP_MUX_MODE7 | AM33XX_PIN_INPUT},
 {"gpmc_a2.gpio1_18", OMAP_MUX_MODE7 | AM33XX_PIN_INPUT},
 {"gpmc_a3.gpio1_19", OMAP_MUX_MODE7 | AM33XX_PIN_INPUT},
 //复位引脚定义
 {"gpmc_clk.gpio2_1", OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT},
 //读写使能引脚定义
 //{"gpmc_wen.gpmc_wen", OMAP_MUX_MODE0|AM33XX_PIN_OUTPUT},
 //{"gpmc_oen_ren.gpmc_oen_ren", OMAP_MUX_MODE0|AM33XX_PIN_OUTPUT},
 //片选引脚定义
 {"gpmc_ben1.gpmc_csn6", OMAP_MUX_MODE2 | AM33XX_PIN_OUTPUT},
 {"gpmc_csn1.gpmc_csn1", OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT},
 {"gpmc_csn2.gpmc_csn2", OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT},
 {"gpmc_csn3.gpmc_csn3", OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT},//AM33XX_PIN_OUTPUT
 //收发就绪引脚定义
 {"mii1_crs.gpio3_1", OMAP_MUX_MODE7 | AM33XX_PIN_INPUT},
 {"mii1_rxerr.gpio3_2", OMAP_MUX_MODE7 | AM33XX_PIN_INPUT},
 
 {NULL, 0},
};

(2)在8250_exar_st16c554.c中注册设备:

static struct plat_serial8250_port exar_data[5];

static struct platform_device exar_device = {
 .name   = "serial8250",
 .id   = PLAT8250_DEV_EXAR_ST16C554,
 .dev   = {
  .platform_data = exar_data,
 },
};

static void AM3359_SET_PORTDATA(struct plat_serial8250_port* pPort, unsigned int _base, int _irq)
{
 printk("tl16c554: irq:%d base:%d\n", _irq,_base);
 (pPort)->mapbase = _base;
 (pPort)->membase = ioremap_nocache(_base, 512);
 (pPort)->irq = _irq;
 (pPort)->uartclk = 1843200;
 (pPort)->iotype = UPIO_MEM;
 (pPort)->flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 (pPort)->regshift = 4;
 (pPort)->irqflags = IRQF_TRIGGER_RISING;
}

static void tl16c554_init()
{
 int i;
 unsigned long nBase;
 unsigned gpio;
 int cslist[]={6,1,2,3};
 
 printk("gpmc_init_tl16c554\n");
 
 memset(exar_data, 0, sizeof(exar_data));
 //tl16c554_set_timings();
 for(i=0; i<4; ++i)
 {
  gpmc_cs_configure(cslist[i], GPMC_CONFIG_DEV_SIZE, 0);
  gpmc_cs_configure(cslist[i], GPMC_CONFIG_DEV_TYPE, 1);//0=NOR FLASH,1=reserved;2=NAND Flash;3=reserved
  gpmc_cs_request(cslist[i], 4, &nBase);
  gpio = GPIO_TO_PIN(1, (16+i));
  AM3359_SET_PORTDATA(exar_data+i, nBase, gpio_to_irq(gpio));
  //gpmc_cs_set_timings(cslist[i], &tl16c554_timings);
  //gpmc_cs_configure(cslist[i], GPMC_CONFIG_RDY_BSY, 1);
  //gpmc_cs_configure(cslist[i], GPMC_ENABLE_IRQ, 0x0202);
 }
}

static int __init exar_init(void)
{
 int i;
 tl16c554_init();
 i = platform_device_register(&exar_device);
 printk("tl16c554: register result:%d\n", i);
 return 0;
}

有几个疑问:

(1)GPMC_CONFIG1中的设备类型只定义了0=NOR FLASH,1=reserved;2=NAND Flash;3=reserved,没有定义串口类型,我该设置什么值?

(2)TL16C554寄存器的寻址,regshift参数是何意?举例说明,如果CSA的基地址为base_a,那里串口A的寄存器LCR地址是否为base_a+(LCR<<regshift)。这里A0~A2连接到了GPMC_A4~GPMC_A6,是否可以认为regshift应该是4.

(3)现在还没有设置时隙,对于设备加载应该没问题吧?我想时隙只是影响数据的收发,对吗?

(4)引脚安装的选项对吗?

测试现象是:

(1)如果设置设备类型为0=NOR FLASH,或者安装引脚 {"gpmc_ben1.gpmc_csn6", OMAP_MUX_MODE2 | AM33XX_PIN_OUTPUT}, {"gpmc_csn1.gpmc_csn1", OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT}, {"gpmc_csn2.gpmc_csn2", OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT}, {"gpmc_csn3.gpmc_csn3", OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT}的话,就不会加载四个串口,当然设备注册是成功的。

(2)我把regshift改为0和4两种情况,对测试效果都一样,目前测试出来的芯片类型为16450,我想肯定不对。看了一下8250.c的代码,判断芯片类型:

//The IIR top two bits allows us to find out if it's 8250 or 16450, 16550, 16550A or later

 serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
 scratch = serial_in(up, UART_IIR) >> 6;

但取出来的scratch为0,tl16c554资料上显示当设置FCR为1时,将自动设置IIR6和IIR7,显然这里没有设上。就好像上述两句话在操作普通内存一样。

因而怀疑寄存器地址肯定不对。事实上我将regshift改为0和4效果一样,甚至我改为1,2,3也是一样的。难道A0~A2不应该连接到GPMC_A4~GPMC_A6呢?

(3)还是我们的硬件原理有问题?抑或是引脚安装选项错误,注意由于nand flash初始化时安装了引脚 "gpmc_wen.gpmc_wen", 和"gpmc_oen_ren.gpmc_oen_ren",所以这里我没有安装,如果需要安装,又如何安装呢?