⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c2410.c.txt

📁 本源码是对三星S3C24xx系列的UART的驱动程序.
💻 TXT
📖 第 1 页 / 共 5 页
字号:
723                                 best = sptr;
724                                 deviation = calc_deviation;
725                         }
726                 }
727 
728                 printk(KERN_DEBUG "best %p (deviation %d)\n", best, deviation);
729         }
730 
731         printk(KERN_DEBUG "selected clock %p (%s) quot %d, calc %d\n",
732                best->clksrc, best->clksrc->name, best->quot, best->calc);
733 
734         /* store results to pass back */
735 
736         *clksrc = best->clksrc;
737         *clk    = best->src;
738 
739         return best->quot;
740 }
741 
742 static void s3c24xx_serial_set_termios(struct uart_port *port,
743                                        struct termios *termios,
744                                        struct termios *old)
745 {
746         struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
747         struct s3c24xx_uart_port *ourport = to_ourport(port);
748         struct s3c24xx_uart_clksrc *clksrc = NULL;
749         struct clk *clk = NULL;
750         unsigned long flags;
751         unsigned int baud, quot;
752         unsigned int ulcon;
753         unsigned int umcon;
754 
755         /*
756          * We don't support modem control lines.
757          */
758         termios->c_cflag &= ~(HUPCL | CMSPAR);
759         termios->c_cflag |= CLOCAL;
760 
761         /*
762          * Ask the core to calculate the divisor for us.
763          */
764 
765         baud = uart_get_baud_rate(port, termios, old, 0, 115200*8);
766 
767         if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
768                 quot = port->custom_divisor;
769         else
770                 quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud);
771 
772         /* check to see if we need  to change clock source */
773 
774         if (ourport->clksrc != clksrc || ourport->baudclk != clk) {
775                 s3c24xx_serial_setsource(port, clksrc);
776 
777                 if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
778                         clk_disable(ourport->baudclk);
779                         ourport->baudclk  = NULL;
780                 }
781 
782                 clk_enable(clk);
783 
784                 ourport->clksrc = clksrc;
785                 ourport->baudclk = clk;
786         }
787 
788         switch (termios->c_cflag & CSIZE) {
789         case CS5:
790                 dbg("config: 5bits/char\n");
791                 ulcon = S3C2410_LCON_CS5;
792                 break;
793         case CS6:
794                 dbg("config: 6bits/char\n");
795                 ulcon = S3C2410_LCON_CS6;
796                 break;
797         case CS7:
798                 dbg("config: 7bits/char\n");
799                 ulcon = S3C2410_LCON_CS7;
800                 break;
801         case CS8:
802         default:
803                 dbg("config: 8bits/char\n");
804                 ulcon = S3C2410_LCON_CS8;
805                 break;
806         }
807 
808         /* preserve original lcon IR settings */
809         ulcon |= (cfg->ulcon & S3C2410_LCON_IRM);
810 
811         if (termios->c_cflag & CSTOPB)
812                 ulcon |= S3C2410_LCON_STOPB;
813 
814         umcon = (termios->c_cflag & CRTSCTS) ? S3C2410_UMCOM_AFC : 0;
815 
816         if (termios->c_cflag & PARENB) {
817                 if (termios->c_cflag & PARODD)
818                         ulcon |= S3C2410_LCON_PODD;
819                 else
820                         ulcon |= S3C2410_LCON_PEVEN;
821         } else {
822                 ulcon |= S3C2410_LCON_PNONE;
823         }
824 
825         spin_lock_irqsave(&port->lock, flags);
826 
827         dbg("setting ulcon to %08x, brddiv to %d\n", ulcon, quot);
828 
829         wr_regl(port, S3C2410_ULCON, ulcon);
830         wr_regl(port, S3C2410_UBRDIV, quot);
831         wr_regl(port, S3C2410_UMCON, umcon);
832 
833         dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n",
834             rd_regl(port, S3C2410_ULCON),
835             rd_regl(port, S3C2410_UCON),
836             rd_regl(port, S3C2410_UFCON));
837 
838         /*
839          * Update the per-port timeout.
840          */
841         uart_update_timeout(port, termios->c_cflag, baud);
842 
843         /*
844          * Which character status flags are we interested in?
845          */
846         port->read_status_mask = S3C2410_UERSTAT_OVERRUN;
847         if (termios->c_iflag & INPCK)
848                 port->read_status_mask |= S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_PARITY;
849 
850         /*
851          * Which character status flags should we ignore?
852          */
853         port->ignore_status_mask = 0;
854         if (termios->c_iflag & IGNPAR)
855                 port->ignore_status_mask |= S3C2410_UERSTAT_OVERRUN;
856         if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)
857                 port->ignore_status_mask |= S3C2410_UERSTAT_FRAME;
858 
859         /*
860          * Ignore all characters if CREAD is not set.
861          */
862         if ((termios->c_cflag & CREAD) == 0)
863                 port->ignore_status_mask |= RXSTAT_DUMMY_READ;
864 
865         spin_unlock_irqrestore(&port->lock, flags);
866 }
867 
868 static const char *s3c24xx_serial_type(struct uart_port *port)
869 {
870         switch (port->type) {
871         case PORT_S3C2410:
872                 return "S3C2410";
873         case PORT_S3C2440:
874                 return "S3C2440";
875         default:
876                 return NULL;
877         }
878 }
879 
880 #define MAP_SIZE (0x100)
881 
882 static void s3c24xx_serial_release_port(struct uart_port *port)
883 {
884         release_mem_region(port->mapbase, MAP_SIZE);
885 }
886 
887 static int s3c24xx_serial_request_port(struct uart_port *port)
888 {
889         const char *name = s3c24xx_serial_portname(port);
890         return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY;
891 }
892 
893 static void s3c24xx_serial_config_port(struct uart_port *port, int flags)
894 {
895         struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
896 
897         if (flags & UART_CONFIG_TYPE &&
898             s3c24xx_serial_request_port(port) == 0)
899                 port->type = info->type;
900 }
901 
902 /*
903  * verify the new serial_struct (for TIOCSSERIAL).
904  */
905 static int
906 s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
907 {
908         struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
909 
910         if (ser->type != PORT_UNKNOWN && ser->type != info->type)
911                 return -EINVAL;
912 
913         return 0;
914 }
915 
916 
917 #ifdef CONFIG_SERIAL_S3C2410_CONSOLE
918 
919 static struct console s3c24xx_serial_console;
920 
921 #define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console
922 #else
923 #define S3C24XX_SERIAL_CONSOLE NULL
924 #endif
925 
926 static struct uart_ops s3c24xx_serial_ops = {
927         .pm             = s3c24xx_serial_pm,
928         .tx_empty       = s3c24xx_serial_tx_empty,
929         .get_mctrl      = s3c24xx_serial_get_mctrl,
930         .set_mctrl      = s3c24xx_serial_set_mctrl,
931         .stop_tx        = s3c24xx_serial_stop_tx,
932         .start_tx       = s3c24xx_serial_start_tx,
933         .stop_rx        = s3c24xx_serial_stop_rx,
934         .enable_ms      = s3c24xx_serial_enable_ms,
935         .break_ctl      = s3c24xx_serial_break_ctl,
936         .startup        = s3c24xx_serial_startup,
937         .shutdown       = s3c24xx_serial_shutdown,
938         .set_termios    = s3c24xx_serial_set_termios,
939         .type           = s3c24xx_serial_type,
940         .release_port   = s3c24xx_serial_release_port,
941         .request_port   = s3c24xx_serial_request_port,
942         .config_port    = s3c24xx_serial_config_port,
943         .verify_port    = s3c24xx_serial_verify_port,
944 };
945 
946 
947 static struct uart_driver s3c24xx_uart_drv = {
948         .owner          = THIS_MODULE,
949         .dev_name       = "s3c2410_serial",
950         .nr             = 3,
951         .cons           = S3C24XX_SERIAL_CONSOLE,
952         .driver_name    = S3C24XX_SERIAL_NAME,
953         .devfs_name     = S3C24XX_SERIAL_DEVFS,
954         .major          = S3C24XX_SERIAL_MAJOR,
955         .minor          = S3C24XX_SERIAL_MINOR,
956 };
957 
958 static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
959         [0] = {
960                 .port = {
961                         .lock           = SPIN_LOCK_UNLOCKED,
962                         .iotype         = UPIO_MEM,
963                         .irq            = IRQ_S3CUART_RX0,
964                         .uartclk        = 0,
965                         .fifosize       = 16,
966                         .ops            = &s3c24xx_serial_ops,
967                         .flags          = UPF_BOOT_AUTOCONF,
968                         .line           = 0,
969                 }
970         },
971         [1] = {
972                 .port = {
973                         .lock           = SPIN_LOCK_UNLOCKED,
974                         .iotype         = UPIO_MEM,
975                         .irq            = IRQ_S3CUART_RX1,
976                         .uartclk        = 0,
977                         .fifosize       = 16,
978                         .ops            = &s3c24xx_serial_ops,
979                         .flags          = UPF_BOOT_AUTOCONF,
980                         .line           = 1,
981                 }
982         },
983 #if NR_PORTS > 2
984 
985         [2] = {
986                 .port = {
987                         .lock           = SPIN_LOCK_UNLOCKED,
988                         .iotype         = UPIO_MEM,
989                         .irq            = IRQ_S3CUART_RX2,
990                         .uartclk        = 0,
991                         .fifosize       = 16,
992                         .ops            = &s3c24xx_serial_ops,
993                         .flags          = UPF_BOOT_AUTOCONF,
994                         .line           = 2,
995                 }
996         }
997 #endif
998 };
999 
1000 /* s3c24xx_serial_resetport
1001  *
1002  * wrapper to call the specific reset for this port (reset the fifos
1003  * and the settings)
1004 */
1005 
1006 static inline int s3c24xx_serial_resetport(struct uart_port * port,
1007                                            struct s3c2410_uartcfg *cfg)
1008 {
1009         struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
1010 
1011         return (info->reset_port)(port, cfg);
1012 }
1013 
1014 /* s3c24xx_serial_init_port
1015  *
1016  * initialise a single serial port from the platform device given
1017  */
1018 
1019 static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
1020                                     struct s3c24xx_uart_info *info,
1021                                     struct platform_device *platdev)
1022 {
1023         struct uart_port *port = &ourport->port;
1024         struct s3c2410_uartcfg *cfg;
1025         struct resource *res;
1026 
1027         dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev);
1028 
1029         if (platdev == NULL)
1030                 return -ENODEV;
1031 
1032         cfg = s3c24xx_dev_to_cfg(&platdev->dev);
1033 
1034         if (port->mapbase != 0)
1035                 return 0;
1036 
1037         if (cfg->hwport > 3)
1038                 return -EINVAL;
1039 
1040         /* setup info for port */
1041         port->dev       = &platdev->dev;
1042         ourport->info   = info;
1043 
1044         /* copy the info in from provided structure */
1045         ourport->port.fifosize = info->fifosize;
1046 
1047         dbg("s3c24xx_serial_init_port: %p (hw %d)...\n", port, cfg->hwport);
1048 
1049         port->uartclk = 1;
1050 
1051         if (cfg->uart_flags & UPF_CONS_FLOW) {
1052                 dbg("s3c24xx_serial_init_port: enabling flow control\n");
1053                 port->flags |= UPF_CONS_FLOW;
1054         }
1055 
1056         /* sort our the physical and virtual addresses for each UART */
1057 
1058         res = platform_get_resource(platdev, IORESOURCE_MEM, 0);
1059         if (res == NULL) {
1060                 printk(KERN_ERR "failed to find memory resource for uart\n");
1061                 return -EINVAL;
1062         }
1063 
1064         dbg("resource %p (%lx..%lx)\n", res, res->start, res->end);
1065 
1066         port->mapbase   = res->start;
1067         port->membase   = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART);
1068         port->irq       = platform_get_irq(platdev, 0);
1069         if (port->irq < 0)
1070                 port->irq = 0;
1071 
1072         ourport->clk    = clk_get(&platdev->dev, "uart");
1073 
1074         dbg("port: map=%08x, mem=%08x, irq=%d, clock=%ld\n",
1075             port->mapbase, port->membase, port->irq, port->uartclk);
1076 
1077         /* reset the fifos (and setup the uart) */
1078         s3c24xx_serial_resetport(port, cfg);
1079         return 0;
1080 }
1081 
1082 /* Device driver serial port probe */
1083 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -