免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1455 | 回复: 0
打印 上一主题 下一主题

2440 uart [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-01-05 14:07 |只看该作者 |倒序浏览

/* module initialisation code */

Static int__init s3c24xx_serial_modinit(void)
{
       int ret;

       ret = uart_register_driver(&s3c24xx_uart_drv);
       if (ret
              printk(KERN_ERR "failed to register UART driver\n");
              return -1;
       }
2/           *
       s3c2400_serial_init();
       s3c2410_serial_init();
       s3c2412_serial_init();
       s3c2440_serial_init();

       return 0;
}


static struct uart_driver s3c24xx_uart_drv = {
       .owner           = THIS_MODULE,
       .dev_name      = "s3c2410_serial",
       .nr          = 3,
       .cons             = S3C24XX_SERIAL_CONSOLE,
       .driver_name   = S3C24XX_SERIAL_NAME,
       .major            = S3C24XX_SERIAL_MAJOR,
       .minor            = S3C24XX_SERIAL_MINOR,
};
int uart_register_driver(struct uart_driver *drv)
{
       struct tty_driver *normal = NULL;
       int i, retval;

       BUG_ON(drv->state);

       /*
        * Maybe we should be using a slab cache for this, especially if
        * we have a large number of ports to handle.
        */
       drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
       retval = -ENOMEM;
       if (!drv->state)
              goto out;

       normal  = alloc_tty_driver(drv->nr);
       if (!normal)
              goto out;

       drv->tty_driver = normal;

       normal->owner             = drv->owner;
       normal->driver_name     = drv->driver_name;
       normal->name        = drv->dev_name;
       normal->major              = drv->major;
       normal->minor_start      = drv->minor;
       normal->type         = TTY_DRIVER_TYPE_SERIAL;
       normal->subtype           = SERIAL_TYPE_NORMAL;
       normal->init_termios      = tty_std_termios;
       normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
       normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600;
       normal->flags        = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
       normal->driver_state    = drv;
       tty_set_operations(normal, &uart_ops);

       /*
        * Initialise the UART state(s).
        */
       for (i = 0; i nr; i++) {
              struct uart_state *state = drv->state + i;

              state->close_delay     = 500;     /* .5 seconds */
              state->closing_wait    = 30000;  /* 30 seconds */

              mutex_init(&state->mutex);
       }

       retval = tty_register_driver(normal);
out:
       if (retval
              put_tty_driver(normal);
              kfree(drv->state);
       }
       return retval;
}

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);
}

static struct platform_driver s3c2440_serial_drv = {
      .probe       = s3c2440_serial_probe,
      .remove          = s3c24xx_serial_remove,
      .suspend   = s3c24xx_serial_suspend,
      .resume           = s3c24xx_serial_resume,
      .driver       = {
           .name  = "s3c2440-uart",
           .owner = THIS_MODULE,
      },
};


static inline int s3c2440_serial_init(void)
{
       return s3c24xx_serial_init(&s3c2440_serial_drv, &s3c2440_uart_inf);
}

static int s3c24xx_serial_init(struct platform_driver *drv,
                            struct s3c24xx_uart_info *info)
{
       dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);
       return platform_driver_register(drv);

}
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);
}

static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
       [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 NR_PORTS > 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
};

static inline int s3c24xx_serial_resetport(struct uart_port * port,
                                      struct s3c2410_uartcfg *cfg)
{
       struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);

       return (info->reset_port)(port, cfg);
}

/* s3c24xx_serial_init_port
*
* initialise a single serial port from the platform device given
*/

static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
                                struct s3c24xx_uart_info *info,
                                struct platform_device *platdev)
{
       struct uart_port *port = &ourport->port;
       struct s3c2410_uartcfg *cfg;
       struct resource *res;

       dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev);

       if (platdev == NULL)
              return -ENODEV;

       cfg = s3c24xx_dev_to_cfg(&platdev->dev);

       if (port->mapbase != 0)
              return 0;

       if (cfg->hwport > 3)
              return -EINVAL;

       /* setup info for port */
       port->dev     = &platdev->dev;
       ourport->info      = info;

       /* copy the info in from provided structure */
       ourport->port.fifosize = info->fifosize;

       dbg("s3c24xx_serial_init_port: %p (hw %d)...\n", port, cfg->hwport);

       port->uartclk = 1;

       if (cfg->uart_flags & UPF_CONS_FLOW) {
              dbg("s3c24xx_serial_init_port: enabling flow control\n");
              port->flags |= UPF_CONS_FLOW;
       }

       /* sort our the physical and virtual addresses for each UART */

       res = platform_get_resource(platdev, IORESOURCE_MEM, 0);
       if (res == NULL) {
              printk(KERN_ERR "failed to find memory resource for uart\n");
              return -EINVAL;
       }

       dbg("resource %p (%lx..%lx)\n", res, res->start, res->end);

       port->mapbase   = res->start;
       port->membase  = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART);
       port->irq      = platform_get_irq(platdev, 0);
       if (port->irq
              port->irq = 0;

       ourport->clk       = clk_get(&platdev->dev, "uart");

       dbg("port: map=%08x, mem=%08x, irq=%d, clock=%ld\n",
           port->mapbase, port->membase, port->irq, port->uartclk);

       /* reset the fifos (and setup the uart) */
       s3c24xx_serial_resetport(port, cfg);
       return 0;
}
static int probe_index = 0;

static 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", __FUNCTION__, ourport);

       ret = s3c24xx_serial_init_port(ourport, info, dev);
       if (ret
              goto probe_err;

       dbg("%s: adding port\n", __FUNCTION__);
       uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
       platform_set_drvdata(dev, &ourport->port);

       return 0;

probe_err:
       return ret;
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/96265/showart_2139974.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP