看了网上好多关于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",所以这里我没有安装,如果需要安装,又如何安装呢?