i.MX6qSabreLite内核源码阅读笔记-----mx6q_sabrelite_init_uart 分析

内核uart初始化的启动代码如下:

static inline void mx6q_sabrelite_init_uart(void)
{
imx6q_add_imx_uart(0, NULL);
imx6q_add_imx_uart(1, NULL);
}

这个函数初始化了 uart 0 和1

 下面我们分析 imx6q_add_imx_uart

#define imx6q_add_imx_uart(id, pdata) \
imx_add_imx_uart_1irq(&imx6q_imx_uart_data[id], pdata)

struct platform_device *__init imx_add_imx_uart_1irq(
const struct imx_imx_uart_1irq_data *data,
const struct imxuart_platform_data *pdata)
{
struct resource res[] = {
{
.start = data->iobase,
.end = data->iobase + data->iosize - 1,
.flags = IORESOURCE_MEM,
}, {
.start = data->irq,
.end = data->irq,
.flags = IORESOURCE_IRQ,
},
}

//这个地方其实就是申请资源 io source 和irq source

return imx_add_platform_device("imx-uart", data->id, res, ARRAY_SIZE(res),
pdata, sizeof(*pdata));//添加平台设备驱动
}


imx6q_imx_uart_data[id]

#ifdef CONFIG_SOC_IMX6Q
const struct imx_imx_uart_1irq_data imx6q_imx_uart_data[] __initconst = {
#define imx6q_imx_uart_data_entry(_id, _hwid) \
imx_imx_uart_1irq_data_entry(MX6Q, _id, _hwid, SZ_4K)
imx6q_imx_uart_data_entry(0, 1),
imx6q_imx_uart_data_entry(1, 2),
imx6q_imx_uart_data_entry(2, 3),
imx6q_imx_uart_data_entry(3, 4),
imx6q_imx_uart_data_entry(4, 5),
};
#endif /*

最后调用到了这里。。

#define imx_imx_uart_1irq_data_entry(soc, _id, _hwid, _size) \
[_id] = { \
.id = _id, \
.iobase = soc ## _UART ## _hwid ## _BASE_ADDR, \

//比如id=0 iobase 就是MX6Q_UART1_BASE_ADDR
.iosize = _size, \
.irq = soc ## _INT_UART ## _hwid, \
}

这是uart平台驱动的注册

下面我看看他的驱动吧!

分析 drivers\tty\serial\Imx.c

linux的驱动程序一般从文件最后到文件前面分析。

static struct platform_driver serial_imx_driver = {
.probe = serial_imx_probe,//大部分的工作应该在这里。。。。
.remove = serial_imx_remove,


.suspend = serial_imx_suspend,
.resume = serial_imx_resume,
.driver = {
.name = "imx-uart",//这个地方匹配我们在上面文件中的那个 注册的名字,那里注册后 匹配这里,然后这里被调用。
.owner = THIS_MODULE,
},
};


static int __init imx_serial_init(void)
{
int ret;


printk(KERN_INFO "Serial: IMX driver\n");


ret = uart_register_driver(&imx_reg);//驱动的注册
if (ret)
return ret;


ret = platform_driver_register(&serial_imx_driver);//应该是平台设备吧!其实我有点分不清楚驱动和设备 不过我知道怎么用。。。。
if (ret != 0)
uart_unregister_driver(&imx_reg);


return 0;
}


static void __exit imx_serial_exit(void)
{
platform_driver_unregister(&serial_imx_driver);
uart_unregister_driver(&imx_reg);
}


module_init(imx_serial_init);//模块初始化
module_exit(imx_serial_exit);//退出


MODULE_AUTHOR("Sascha Hauer");
MODULE_DESCRIPTION("IMX generic serial port driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:imx-uart");

module_init()-->imx_serial_init()-->serial_imx_driver-->probe



static int serial_imx_probe(struct platform_device *pdev)
{
struct imx_port *sport;
struct imxuart_platform_data *pdata;
void __iomem *base;
int ret = 0;
struct resource *res;


sport = kzalloc(sizeof(*sport), GFP_KERNEL);
if (!sport)
return -ENOMEM;


res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
ret = -ENODEV;
goto free;
}


base = ioremap(res->start, PAGE_SIZE);
if (!base) {
ret = -ENOMEM;
goto free;
}


sport->port.dev = &pdev->dev;
sport->port.mapbase = res->start;
sport->port.membase = base;
sport->port.type = PORT_IMX,
sport->port.iotype = UPIO_MEM;
sport->port.irq = platform_get_irq(pdev, 0);
sport->rxirq = platform_get_irq(pdev, 0);
sport->txirq = platform_get_irq(pdev, 1);
sport->rtsirq = platform_get_irq(pdev, 2);
sport->port.fifosize = 32;
sport->port.ops = &imx_pops;
sport->port.flags = UPF_BOOT_AUTOCONF;
sport->port.line = pdev->id;
init_timer(&sport->timer);
sport->timer.function = imx_timeout;
sport->timer.data     = (unsigned long)sport;


sport->clk = clk_get(&pdev->dev, "uart");
if (IS_ERR(sport->clk)) {
ret = PTR_ERR(sport->clk);
goto unmap;
}
if (uart_at_24)
clk_set_parent(sport->clk, clk_get(NULL, "osc"));


clk_enable(sport->clk);


sport->port.uartclk = clk_get_rate(sport->clk);


imx_ports[pdev->id] = sport;


pdata = pdev->dev.platform_data;
if (pdata && (pdata->flags & IMXUART_HAVE_RTSCTS))
sport->have_rtscts = 1;
if (pdata && (pdata->flags & IMXUART_USE_DCEDTE))
sport->use_dcedte = 1;
if (pdata && (pdata->flags & IMXUART_SDMA))
sport->enable_dma = 1;


#ifdef CONFIG_IRDA
if (pdata && (pdata->flags & IMXUART_IRDA))
sport->use_irda = 1;
#endif


if (pdata && pdata->init) {
ret = pdata->init(pdev);
if (ret)
goto clkput;
}


ret = uart_add_one_port(&imx_reg, &sport->port);
if (ret)
goto deinit;
platform_set_drvdata(pdev, &sport->port);


clk_disable(sport->clk);
return 0;
deinit:
if (pdata && pdata->exit)
pdata->exit(pdev);
clkput:
clk_put(sport->clk);
clk_disable(sport->clk);
unmap:
iounmap(sport->port.membase);
free:
kfree(sport);


return ret;
}

这是probe函数,我们分析一下 参数pdev 从那里来的吧!

看了半天,应该就是

struct platform_device *__init imx_add_platform_device_dmamask(
const char *name, int id,
const struct resource *res, unsigned int num_resources,
const void *data, size_t size_data, u64 dmamask)
{
int ret = -ENOMEM;
struct platform_device *pdev;


pdev = platform_device_alloc(name, id);
if (!pdev)
goto err;


if (dmamask) {
/*
* This memory isn't freed when the device is put,
* I don't have a nice idea for that though.  Conceptually
* dma_mask in struct device should not be a pointer.
* See http://thread.gmane.org/gmane.linux.kernel.pci/9081
*/
pdev->dev.dma_mask =
kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
if (!pdev->dev.dma_mask)
/* ret is still -ENOMEM; */
goto err;


*pdev->dev.dma_mask = dmamask;
pdev->dev.coherent_dma_mask = dmamask;
}


if (res) {
ret = platform_device_add_resources(pdev, res, num_resources);
if (ret)
goto err;
}


if (data) {
ret = platform_device_add_data(pdev, data, size_data);
if (ret)
goto err;
}


ret = platform_device_add(pdev);
if (ret) {
err:
if (dmamask)
kfree(pdev->dev.dma_mask);
platform_device_put(pdev);
return ERR_PTR(ret);
}


return pdev;

}

pdev 应该就是从这里传进来的。在注册的时候。

这应该就是所有的串口的驱动函数了。。。。。

今天到此结束。。。。

一个人看代码真的很无聊。。。。不如边看边写。。。。。只是。。。。。时间不够。。。。。。。天天得上班。。。。。

猜你喜欢

转载自blog.csdn.net/haozhenghui10/article/details/37713201
今日推荐