Chinaunix首页 | 论坛 | 博客
  • 博客访问: 101400
  • 博文数量: 54
  • 博客积分: 1920
  • 博客等级: 上尉
  • 技术积分: 480
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-08 13:46
文章分类

全部博文(54)

文章存档

2011年(1)

2010年(8)

2009年(45)

我的朋友

分类: LINUX

2010-01-05 14:07:28

/* module initialisation code */

 

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;

       }

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 < drv->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 < 0) {

              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 < 0)

              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 < 0)

              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;

}

阅读(995) | 评论(0) | 转发(0) |
0

上一篇:2440 clock

下一篇:io_remap的实现

给主人留下些什么吧!~~