make menuconfig:


1.Device Drivers  ---> Character devices  ---> Serial drivers  ---> <*> Samsung Soc Serial support
obj-$(CONFIG_SERIAL_CORE) += serial_core.o   是串口核心
obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o    是串口具体实现

2.控制台终端
计算机显示器通常被称为控制台终端(console)。必须有一个(些)特殊文件与console相关联,比如虚拟终端tty1 tty2 串口ttySAC0 ttySAC1等。系统所发出的信息会发送到console对应的文件上。

如果不选此项,在启动kernel后就不输出了。

Starting kernel ...Uncompressing Linux......................................................................................................................................
................... done, booting the kernel.

uboot里设置的 console=ttySAC0 ,决定了使用ttySAC0作控制台终端。

在samsung.c中实现console。

/* s3c24xx_serial_initconsole** initialise the console from one of the uart drivers
*/static struct console s3c24xx_serial_console = {.name        = S3C24XX_SERIAL_NAME,.device      = uart_console_device,.flags       = CON_PRINTBUFFER,.index       = -1,.write        = s3c24xx_serial_console_write,.setup      = s3c24xx_serial_console_setup
};int s3c24xx_serial_initconsole(struct platform_driver *drv,struct s3c24xx_uart_info *info){struct platform_device *dev = s3c24xx_uart_devs[0];dbg("s3c24xx_serial_initconsole\n");/* select driver based on the cpu */if (dev == NULL) {printk(KERN_ERR "s3c24xx: no devices for console init\n");return 0;}if (strcmp(dev->name, drv->driver.name) != 0)return 0;s3c24xx_serial_console.data = &s3c24xx_uart_drv;s3c24xx_serial_init_ports(info);register_console(&s3c24xx_serial_console);return 0;
}

3.<*> Samsung S3C2440/S3C2442 Serial port support
普通串口 /dev/ttySAC*
obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o
1.串口的平台设备分散在mach-mini2440.c,arch/arm/plat-s3c/init.c等,在系统启动时注册.比如mach-mini2440.c

static struct s3c2410_uartcfg mini2440_uartcfgs[] __initdata = {[0] = {//串口0.hwport         = 0,.flags         = 0,.ucon         = 0x3c5,.ulcon         = 0x03,.ufcon         = 0x51,},[1] = {//串口1.hwport         = 1,.flags         = 0,.ucon         = 0x3c5,.ulcon         = 0x03,.ufcon         = 0x51,},[2] = {//串口2.hwport         = 2,.flags         = 0,.ucon         = 0x3c5,.ulcon         = 0x03,.ufcon         = 0x51,}
};

比如init.c
void __init s3c24xx_init_uartdevs(char *name,
                  struct s3c24xx_uart_resources *res,
                  struct s3c2410_uartcfg *cfg, int no)
{
    struct platform_device *platdev;
    struct s3c2410_uartcfg *cfgptr = uart_cfgs;
    struct s3c24xx_uart_resources *resp;
    int uart;

memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no);

for (uart = 0; uart < no; uart++, cfg++, cfgptr++) {
        platdev = s3c24xx_uart_src[cfgptr->hwport];

resp = res + cfgptr->hwport;

s3c24xx_uart_devs[uart] = platdev;

platdev->name = name;
        platdev->resource = resp->resources;
        platdev->num_resources = resp->nr_resources;

platdev->dev.platform_data = cfgptr;
    }

nr_uarts = no;
}

2.串口的平台驱动在
arch/arm/mach-s3c2440/s3c2440.c和samsung.c
初始化:
s3c2440.c初始化时注册了平台驱动

static int __init s3c2440_serial_init(void)
{return s3c24xx_serial_init(&s3c2440_serial_driver, &s3c2440_uart_inf);//见下面
}static void __exit s3c2440_serial_exit(void)
{platform_driver_unregister(&s3c2440_serial_driver);
}module_init(s3c2440_serial_init);
module_exit(s3c2440_serial_exit);
//samsung.c
int s3c24xx_serial_init(struct platform_driver *drv,struct s3c24xx_uart_info *info)
{dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);#ifdef CONFIG_PMdrv->suspend = s3c24xx_serial_suspend;drv->resume = s3c24xx_serial_resume;
#endifreturn platform_driver_register(drv);
}

samsung.c在初始化时就注册了串口驱动

static int __init s3c24xx_serial_modinit(void)
{int ret;ret = uart_register_driver(&s3c24xx_uart_drv);if (ret < 0) {printk(KERN_ERR "failed to register UART driver\n");return -1;}return 0;
}static void __exit s3c24xx_serial_modexit(void)
{uart_unregister_driver(&s3c24xx_uart_drv);
}module_init(s3c24xx_serial_modinit);
module_exit(s3c24xx_serial_modexit);

看一下平台驱动的probe,可知是在probe函数里面添加串口
s3c2440.c

static struct s3c24xx_uart_info s3c2440_uart_inf = {.name     = "Samsung S3C2440 UART",.type       = PORT_S3C2440,.fifosize   = 64,.rx_fifomask  = S3C2440_UFSTAT_RXMASK,.rx_fifoshift  = S3C2440_UFSTAT_RXSHIFT,.rx_fifofull  = S3C2440_UFSTAT_RXFULL,.tx_fifofull   = S3C2440_UFSTAT_TXFULL,.tx_fifomask   = S3C2440_UFSTAT_TXMASK,.tx_fifoshift  = S3C2440_UFSTAT_TXSHIFT,.get_clksrc   = s3c2440_serial_getsource,.set_clksrc = s3c2440_serial_setsource,.reset_port = s3c2440_serial_resetport,
};/* device management */static int s3c2440_serial_probe(struct platform_device *dev)
{dbg("s3c2440_serial_probe: dev=%p\n", dev);return s3c24xx_serial_probe(dev, &s3c2440_uart_inf);//见下面
}
//samsung.c
static int probe_index;int s3c24xx_serial_probe(struct platform_device *dev,struct s3c24xx_uart_info *info)
{struct s3c24xx_uart_port *ourport;int ret;dbg("s3c24xx_serial_probe(%p, %p) %d\n", dev, info, probe_index);ourport = &s3c24xx_serial_ports[probe_index];probe_index++;dbg("%s: initialising port %p...\n", __func__, ourport);ret = s3c24xx_serial_init_port(ourport, info, dev);if (ret < 0)goto probe_err;dbg("%s: adding port\n", __func__);uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);platform_set_drvdata(dev, &ourport->port);ret = device_create_file(&dev->dev, &dev_attr_clock_source);if (ret < 0)printk(KERN_ERR "%s: failed to add clksrc attr.\n", __func__);ret = s3c24xx_serial_cpufreq_register(ourport);if (ret < 0)dev_err(&dev->dev, "failed to add cpufreq notifier\n");return 0;probe_err:return ret;
}

几个重要的结构体

//uart_ops
static struct uart_ops s3c24xx_serial_ops = {.pm       = s3c24xx_serial_pm,.tx_empty  = s3c24xx_serial_tx_empty,.get_mctrl   = s3c24xx_serial_get_mctrl,.set_mctrl  = s3c24xx_serial_set_mctrl,.stop_tx    = s3c24xx_serial_stop_tx,.start_tx = s3c24xx_serial_start_tx,.stop_rx = s3c24xx_serial_stop_rx,.enable_ms    = s3c24xx_serial_enable_ms,.break_ctl  = s3c24xx_serial_break_ctl,.startup    = s3c24xx_serial_startup,.shutdown = s3c24xx_serial_shutdown,.set_termios = s3c24xx_serial_set_termios,.type     = s3c24xx_serial_type,.release_port    = s3c24xx_serial_release_port,.request_port    = s3c24xx_serial_request_port,.config_port = s3c24xx_serial_config_port,.verify_port  = s3c24xx_serial_verify_port,
};//uart_driver
static struct uart_driver s3c24xx_uart_drv = {.owner       = THIS_MODULE,.dev_name    = "s3c2410_serial",.nr       = CONFIG_SERIAL_SAMSUNG_UARTS,.cons        = S3C24XX_SERIAL_CONSOLE,.driver_name  = S3C24XX_SERIAL_NAME,.major       = S3C24XX_SERIAL_MAJOR,.minor      = S3C24XX_SERIAL_MINOR,
};//s3c24xx_uart_port
static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {[0] = {.port = {.lock       = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),.iotype      = UPIO_MEM,.irq        = IRQ_S3CUART_RX0,.uartclk = 0,.fifosize  = 16,.ops      = &s3c24xx_serial_ops,.flags       = UPF_BOOT_AUTOCONF,.line      = 0,}},[1] = {.port = {.lock     = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock),.iotype      = UPIO_MEM,.irq        = IRQ_S3CUART_RX1,.uartclk = 0,.fifosize  = 16,.ops      = &s3c24xx_serial_ops,.flags       = UPF_BOOT_AUTOCONF,.line      = 1,}},
#if CONFIG_SERIAL_SAMSUNG_UARTS > 2[2] = {.port = {.lock       = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock),.iotype      = UPIO_MEM,.irq        = IRQ_S3CUART_RX2,.uartclk = 0,.fifosize  = 16,.ops      = &s3c24xx_serial_ops,.flags       = UPF_BOOT_AUTOCONF,.line      = 2,}},
#endif
#if CONFIG_SERIAL_SAMSUNG_UARTS > 3[3] = {.port = {.lock       = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[3].port.lock),.iotype      = UPIO_MEM,.irq        = IRQ_S3CUART_RX3,.uartclk = 0,.fifosize  = 16,.ops      = &s3c24xx_serial_ops,.flags       = UPF_BOOT_AUTOCONF,.line      = 3,}}
#endif
};
//serial_core.h
struct uart_port {spinlock_t        lock;           /* port lock */unsigned long        iobase;         /* in/out[bwl] */unsigned char __iomem  *membase;       /* read/write[bwl] */unsigned int       (*serial_in)(struct uart_port *, int);void          (*serial_out)(struct uart_port *, int, int);unsigned int        irq;            /* irq number */unsigned long       irqflags;       /* irq flags  */unsigned int        uartclk;        /* base uart clock */unsigned int       fifosize;       /* tx fifo size */unsigned char     x_char;         /* xon/xoff char */unsigned char        regshift;       /* reg offset shift */unsigned char     iotype;         /* io access style */unsigned char      unused1;#define UPIO_PORT       (0)
#define UPIO_HUB6       (1)
#define UPIO_MEM        (2)
#define UPIO_MEM32      (3)
#define UPIO_AU         (4)         /* Au1x00 type IO */
#define UPIO_TSI        (5)         /* Tsi108/109 type IO */
#define UPIO_DWAPB      (6)         /* DesignWare APB UART */
#define UPIO_RM9000     (7)         /* RM9000 type IO */unsigned int        read_status_mask;   /* driver specific */unsigned int       ignore_status_mask; /* driver specific */struct uart_state  *state;         /* pointer to parent state */struct uart_icount icount;         /* statistics */struct console      *cons;          /* struct console, if any */
#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ)unsigned long      sysrq;          /* sysrq timeout */
#endifupf_t         flags;#define UPF_FOURPORT      ((__force upf_t) (1 << 1))
#define UPF_SAK         ((__force upf_t) (1 << 2))
#define UPF_SPD_MASK        ((__force upf_t) (0x1030))
#define UPF_SPD_HI      ((__force upf_t) (0x0010))
#define UPF_SPD_VHI     ((__force upf_t) (0x0020))
#define UPF_SPD_CUST        ((__force upf_t) (0x0030))
#define UPF_SPD_SHI     ((__force upf_t) (0x1000))
#define UPF_SPD_WARP        ((__force upf_t) (0x1010))
#define UPF_SKIP_TEST       ((__force upf_t) (1 << 6))
#define UPF_AUTO_IRQ        ((__force upf_t) (1 << 7))
#define UPF_HARDPPS_CD      ((__force upf_t) (1 << 11))
#define UPF_LOW_LATENCY     ((__force upf_t) (1 << 13))
#define UPF_BUGGY_UART      ((__force upf_t) (1 << 14))
#define UPF_NO_TXEN_TEST    ((__force upf_t) (1 << 15))
#define UPF_MAGIC_MULTIPLIER    ((__force upf_t) (1 << 16))
#define UPF_CONS_FLOW       ((__force upf_t) (1 << 23))
#define UPF_SHARE_IRQ       ((__force upf_t) (1 << 24))
/* The exact UART type is known and should not be probed.  */
#define UPF_FIXED_TYPE      ((__force upf_t) (1 << 27))
#define UPF_BOOT_AUTOCONF   ((__force upf_t) (1 << 28))
#define UPF_FIXED_PORT      ((__force upf_t) (1 << 29))
#define UPF_DEAD        ((__force upf_t) (1 << 30))
#define UPF_IOREMAP     ((__force upf_t) (1 << 31))#define UPF_CHANGE_MASK        ((__force upf_t) (0x17fff))
#define UPF_USR_MASK        ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))unsigned int        mctrl;          /* current modem ctrl settings */unsigned int       timeout;        /* character-based timeout */unsigned int       type;           /* port type */const struct uart_ops    *ops;unsigned int       custom_divisor;unsigned int     line;           /* port index */resource_size_t     mapbase;        /* for ioremap */struct device      *dev;           /* parent device */unsigned char        hub6;           /* this should be in the 8250 driver */unsigned char        suspended;unsigned char     unused[2];void          *private_data;      /* generic platform data pointer */
};

在probe中(s3c24xx_serial_probe(),samsung.c)用uart_add_one_port()将uart_port加入uart_driver

每一uart_port对应一个uart_ops,主要工作就是实现这些函数指针。

转载于:https://www.cnblogs.com/-song/archive/2011/12/17/3331900.html

serial driver 1相关推荐

  1. serial driver 2

    2440的串口结构和51的对比一下会更清楚一点 51 2440 image from http://blog.csdn.net/mr_raptor/article/details/6556133 51 ...

  2. kernel 下串口serial输入输出控制,屏蔽log的输出

    最近工作在调试usb虚拟串口,让其作为kernel启动的调试串口,以及user空间的输入输出控制台. 利用这个机会,学习下printk如何选择往哪个console输出以及user空间下控制台如何选择, ...

  3. linux 串口驱动 atmel_set_mctrl何时调用,linux uart serial使用驱动分析

    uart tty serial 驱动分析 内核版本3.14.23 以atmel为例: 起点: static int __init atmel_serial_init(void) { int ret; ...

  4. quot;《 Serial Drivers 》by Alessandro Rubiniquot; 学习笔记

    Introduction to "serial device driver"     (My study note) 膜拜大神的作品. Standing on the should ...

  5. WINCE Driver 心得总结

    一. Windows CE的驱动程序的区分 1.从加载以及接口方式来区分 可以分为本机设备驱动(Built-In Driver).可加载驱动(Loadable Driver)以及混合型驱动. (1)本 ...

  6. Android Qcom USB Driver学习(四)

    该系列文章总目录链接与各部分简介: Android Qcom USB Driver学习(零) VID/PID识别USB设备 CDC-ACM驱动介绍   CDC-ACM(Communication De ...

  7. Windows CE串口驱动简析(2)-PDD层实现:CReg2410Uart和TX部分(基于WinCE5.0 SMDK2410 BSP的Serial驱动)

    二.PDD层 1.PDD架构 现在我们就来看看SMDK2410中串口驱动的PDD部分. MDD层和PDD COMMON层都是由微软提供的,一般情况下我们基本无须改动.微软为开发者提供了一个CSeria ...

  8. RK3288 USB to Seria(PL2303)converter driver

    1.make ARCH=arm menuconfig 2.Device Drivers > USB support > USB Serial Converter support <* ...

  9. 4G模块 EC20 R2.0 USB Serial/GobiNet/QMI WWAN 驱动移植过程

    4G模块 EC20 R2.0 USB Serial/GobiNet/QMI WWAN 驱动移植过程 一.开发环境 二.确定 EC20 R2.0 的基本信息 三.USB Serial 驱动移植 opti ...

最新文章

  1. 什么是REST?以及RESTful的实现之二
  2. 5.10 程序示例--模型选择-机器学习笔记-斯坦福吴恩达教授
  3. Vue项目打包成桌面程序exe除了使用electron-vue你还可以这样
  4. Android 查看设备文件
  5. 自制仿360首页支持拼音输入全模糊搜索和自动换肤
  6. 使用 kube-bench 和 kube-hunter 对 Kubernetes 集群风险评估
  7. netty websocket 简单消息推送demo
  8. java 集合操作工具包_java之操作集合的工具类--Collections
  9. MIT6.830 lab4 SimpleDB Transactions 实验报告
  10. AI ProCon 2020第一天:40+大厂专家共话AI技术应用下一个十年!
  11. 计算机信息安全技术_第一章概述
  12. hadoop Configured Configrable Configuration Tool 源码详解
  13. 怎么下载卫星地图导出为离线包
  14. java正则表达式的语法详解及常用方法
  15. oracle中on和where的区别,Oracle里面的外连中where和on之后and有啥区别
  16. 电容器充放电的原理是什么?
  17. 梯度消失和爆炸原因以及解决方法
  18. 计算机专业的男生喜欢你,男生真心喜欢你的五个表现
  19. 解决:关于电脑访问百度很慢的问题
  20. 如果你的团队有这7个特性,那么你的团队就会战无不胜

热门文章

  1. 新装ubuntu10.04后的一些设置
  2. 关于cast类型转换后无法使用索引的优化
  3. android ListView 局部刷新
  4. Source Insight中查看文件显示全路径
  5. Chrome MessageLoop类分析
  6. 循环右移,要求时间复杂度为O(n)且尽可能的少使用辅助空间
  7. C++实现直接插入排序
  8. Tensorflow2.0(Keras)转换TFlite
  9. Sysnoise5.6安装教程
  10. Redis 学习笔记-NoSQL数据库 常用五大数据类型 Redis配置文件介绍 Redis的发布和订阅 Redis_事务_锁机制_秒杀 Redis应用问题解决 分布式锁