diff options
Diffstat (limited to 'drivers/serial/mpc52xx_uart.c')
-rw-r--r-- | drivers/serial/mpc52xx_uart.c | 353 |
1 files changed, 337 insertions, 16 deletions
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 8e24133166af..6dd579ed9777 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -16,7 +16,9 @@ | |||
16 | * Some of the code has been inspired/copied from the 2.4 code written | 16 | * Some of the code has been inspired/copied from the 2.4 code written |
17 | * by Dale Farnsworth <dfarnsworth@mvista.com>. | 17 | * by Dale Farnsworth <dfarnsworth@mvista.com>. |
18 | * | 18 | * |
19 | * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com> | 19 | * Copyright (C) 2006 Secret Lab Technologies Ltd. |
20 | * Grant Likely <grant.likely@secretlab.ca> | ||
21 | * Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com> | ||
20 | * Copyright (C) 2003 MontaVista, Software, Inc. | 22 | * Copyright (C) 2003 MontaVista, Software, Inc. |
21 | * | 23 | * |
22 | * This file is licensed under the terms of the GNU General Public License | 24 | * This file is licensed under the terms of the GNU General Public License |
@@ -42,7 +44,24 @@ | |||
42 | * will be mapped to. | 44 | * will be mapped to. |
43 | */ | 45 | */ |
44 | 46 | ||
45 | #include <linux/platform_device.h> | 47 | /* OF Platform device Usage : |
48 | * | ||
49 | * This driver is only used for PSCs configured in uart mode. The device | ||
50 | * tree will have a node for each PSC in uart mode w/ device_type = "serial" | ||
51 | * and "mpc52xx-psc-uart" in the compatible string | ||
52 | * | ||
53 | * By default, PSC devices are enumerated in the order they are found. However | ||
54 | * a particular PSC number can be forces by adding 'device_no = <port#>' | ||
55 | * to the device node. | ||
56 | * | ||
57 | * The driver init all necessary registers to place the PSC in uart mode without | ||
58 | * DCD. However, the pin multiplexing aren't changed and should be set either | ||
59 | * by the bootloader or in the platform init code. | ||
60 | */ | ||
61 | |||
62 | #undef DEBUG | ||
63 | |||
64 | #include <linux/device.h> | ||
46 | #include <linux/module.h> | 65 | #include <linux/module.h> |
47 | #include <linux/tty.h> | 66 | #include <linux/tty.h> |
48 | #include <linux/serial.h> | 67 | #include <linux/serial.h> |
@@ -52,6 +71,12 @@ | |||
52 | #include <asm/delay.h> | 71 | #include <asm/delay.h> |
53 | #include <asm/io.h> | 72 | #include <asm/io.h> |
54 | 73 | ||
74 | #if defined(CONFIG_PPC_MERGE) | ||
75 | #include <asm/of_platform.h> | ||
76 | #else | ||
77 | #include <linux/platform_device.h> | ||
78 | #endif | ||
79 | |||
55 | #include <asm/mpc52xx.h> | 80 | #include <asm/mpc52xx.h> |
56 | #include <asm/mpc52xx_psc.h> | 81 | #include <asm/mpc52xx_psc.h> |
57 | 82 | ||
@@ -78,6 +103,12 @@ static struct uart_port mpc52xx_uart_ports[MPC52xx_PSC_MAXNUM]; | |||
78 | * it's cleared, then a memset(...,0,...) should be added to | 103 | * it's cleared, then a memset(...,0,...) should be added to |
79 | * the console_init | 104 | * the console_init |
80 | */ | 105 | */ |
106 | #if defined(CONFIG_PPC_MERGE) | ||
107 | /* lookup table for matching device nodes to index numbers */ | ||
108 | static struct device_node *mpc52xx_uart_nodes[MPC52xx_PSC_MAXNUM]; | ||
109 | |||
110 | static void mpc52xx_uart_of_enumerate(void); | ||
111 | #endif | ||
81 | 112 | ||
82 | #define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase)) | 113 | #define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase)) |
83 | 114 | ||
@@ -94,6 +125,14 @@ static irqreturn_t mpc52xx_uart_int(int irq,void *dev_id); | |||
94 | #define uart_console(port) (0) | 125 | #define uart_console(port) (0) |
95 | #endif | 126 | #endif |
96 | 127 | ||
128 | #if defined(CONFIG_PPC_MERGE) | ||
129 | static struct of_device_id mpc52xx_uart_of_match[] = { | ||
130 | { .type = "serial", .compatible = "mpc52xx-psc-uart", }, | ||
131 | { .type = "serial", .compatible = "mpc5200-psc", }, /* Efika only! */ | ||
132 | {}, | ||
133 | }; | ||
134 | #endif | ||
135 | |||
97 | 136 | ||
98 | /* ======================================================================== */ | 137 | /* ======================================================================== */ |
99 | /* UART operations */ | 138 | /* UART operations */ |
@@ -330,7 +369,7 @@ mpc52xx_uart_release_port(struct uart_port *port) | |||
330 | port->membase = NULL; | 369 | port->membase = NULL; |
331 | } | 370 | } |
332 | 371 | ||
333 | release_mem_region(port->mapbase, MPC52xx_PSC_SIZE); | 372 | release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc)); |
334 | } | 373 | } |
335 | 374 | ||
336 | static int | 375 | static int |
@@ -339,12 +378,13 @@ mpc52xx_uart_request_port(struct uart_port *port) | |||
339 | int err; | 378 | int err; |
340 | 379 | ||
341 | if (port->flags & UPF_IOREMAP) /* Need to remap ? */ | 380 | if (port->flags & UPF_IOREMAP) /* Need to remap ? */ |
342 | port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE); | 381 | port->membase = ioremap(port->mapbase, |
382 | sizeof(struct mpc52xx_psc)); | ||
343 | 383 | ||
344 | if (!port->membase) | 384 | if (!port->membase) |
345 | return -EINVAL; | 385 | return -EINVAL; |
346 | 386 | ||
347 | err = request_mem_region(port->mapbase, MPC52xx_PSC_SIZE, | 387 | err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc), |
348 | "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY; | 388 | "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY; |
349 | 389 | ||
350 | if (err && (port->flags & UPF_IOREMAP)) { | 390 | if (err && (port->flags & UPF_IOREMAP)) { |
@@ -561,13 +601,18 @@ mpc52xx_console_get_options(struct uart_port *port, | |||
561 | struct mpc52xx_psc __iomem *psc = PSC(port); | 601 | struct mpc52xx_psc __iomem *psc = PSC(port); |
562 | unsigned char mr1; | 602 | unsigned char mr1; |
563 | 603 | ||
604 | pr_debug("mpc52xx_console_get_options(port=%p)\n", port); | ||
605 | |||
564 | /* Read the mode registers */ | 606 | /* Read the mode registers */ |
565 | out_8(&psc->command,MPC52xx_PSC_SEL_MODE_REG_1); | 607 | out_8(&psc->command,MPC52xx_PSC_SEL_MODE_REG_1); |
566 | mr1 = in_8(&psc->mode); | 608 | mr1 = in_8(&psc->mode); |
567 | 609 | ||
568 | /* CT{U,L}R are write-only ! */ | 610 | /* CT{U,L}R are write-only ! */ |
569 | *baud = __res.bi_baudrate ? | 611 | *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; |
570 | __res.bi_baudrate : CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; | 612 | #if !defined(CONFIG_PPC_MERGE) |
613 | if (__res.bi_baudrate) | ||
614 | *baud = __res.bi_baudrate; | ||
615 | #endif | ||
571 | 616 | ||
572 | /* Parse them */ | 617 | /* Parse them */ |
573 | switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) { | 618 | switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) { |
@@ -620,6 +665,7 @@ mpc52xx_console_write(struct console *co, const char *s, unsigned int count) | |||
620 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | 665 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); |
621 | } | 666 | } |
622 | 667 | ||
668 | #if !defined(CONFIG_PPC_MERGE) | ||
623 | static int __init | 669 | static int __init |
624 | mpc52xx_console_setup(struct console *co, char *options) | 670 | mpc52xx_console_setup(struct console *co, char *options) |
625 | { | 671 | { |
@@ -654,6 +700,78 @@ mpc52xx_console_setup(struct console *co, char *options) | |||
654 | return uart_set_options(port, co, baud, parity, bits, flow); | 700 | return uart_set_options(port, co, baud, parity, bits, flow); |
655 | } | 701 | } |
656 | 702 | ||
703 | #else | ||
704 | |||
705 | static int __init | ||
706 | mpc52xx_console_setup(struct console *co, char *options) | ||
707 | { | ||
708 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; | ||
709 | struct device_node *np = mpc52xx_uart_nodes[co->index]; | ||
710 | unsigned int ipb_freq; | ||
711 | struct resource res; | ||
712 | int ret; | ||
713 | |||
714 | int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; | ||
715 | int bits = 8; | ||
716 | int parity = 'n'; | ||
717 | int flow = 'n'; | ||
718 | |||
719 | pr_debug("mpc52xx_console_setup co=%p, co->index=%i, options=%s\n", | ||
720 | co, co->index, options); | ||
721 | |||
722 | if ((co->index < 0) || (co->index > MPC52xx_PSC_MAXNUM)) { | ||
723 | pr_debug("PSC%x out of range\n", co->index); | ||
724 | return -EINVAL; | ||
725 | } | ||
726 | |||
727 | if (!np) { | ||
728 | pr_debug("PSC%x not found in device tree\n", co->index); | ||
729 | return -EINVAL; | ||
730 | } | ||
731 | |||
732 | pr_debug("Console on ttyPSC%x is %s\n", | ||
733 | co->index, mpc52xx_uart_nodes[co->index]->full_name); | ||
734 | |||
735 | /* Fetch register locations */ | ||
736 | if ((ret = of_address_to_resource(np, 0, &res)) != 0) { | ||
737 | pr_debug("Could not get resources for PSC%x\n", co->index); | ||
738 | return ret; | ||
739 | } | ||
740 | |||
741 | /* Search for bus-frequency property in this node or a parent */ | ||
742 | if ((ipb_freq = mpc52xx_find_ipb_freq(np)) == 0) { | ||
743 | pr_debug("Could not find IPB bus frequency!\n"); | ||
744 | return -EINVAL; | ||
745 | } | ||
746 | |||
747 | /* Basic port init. Needed since we use some uart_??? func before | ||
748 | * real init for early access */ | ||
749 | spin_lock_init(&port->lock); | ||
750 | port->uartclk = ipb_freq / 2; | ||
751 | port->ops = &mpc52xx_uart_ops; | ||
752 | port->mapbase = res.start; | ||
753 | port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc)); | ||
754 | port->irq = irq_of_parse_and_map(np, 0); | ||
755 | |||
756 | if (port->membase == NULL) | ||
757 | return -EINVAL; | ||
758 | |||
759 | pr_debug("mpc52xx-psc uart at %lx, mapped to %p, irq=%x, freq=%i\n", | ||
760 | port->mapbase, port->membase, port->irq, port->uartclk); | ||
761 | |||
762 | /* Setup the port parameters accoding to options */ | ||
763 | if (options) | ||
764 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
765 | else | ||
766 | mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow); | ||
767 | |||
768 | pr_debug("Setting console parameters: %i %i%c1 flow=%c\n", | ||
769 | baud, bits, parity, flow); | ||
770 | |||
771 | return uart_set_options(port, co, baud, parity, bits, flow); | ||
772 | } | ||
773 | #endif /* defined(CONFIG_PPC_MERGE) */ | ||
774 | |||
657 | 775 | ||
658 | static struct uart_driver mpc52xx_uart_driver; | 776 | static struct uart_driver mpc52xx_uart_driver; |
659 | 777 | ||
@@ -671,6 +789,7 @@ static struct console mpc52xx_console = { | |||
671 | static int __init | 789 | static int __init |
672 | mpc52xx_console_init(void) | 790 | mpc52xx_console_init(void) |
673 | { | 791 | { |
792 | mpc52xx_uart_of_enumerate(); | ||
674 | register_console(&mpc52xx_console); | 793 | register_console(&mpc52xx_console); |
675 | return 0; | 794 | return 0; |
676 | } | 795 | } |
@@ -698,6 +817,7 @@ static struct uart_driver mpc52xx_uart_driver = { | |||
698 | }; | 817 | }; |
699 | 818 | ||
700 | 819 | ||
820 | #if !defined(CONFIG_PPC_MERGE) | ||
701 | /* ======================================================================== */ | 821 | /* ======================================================================== */ |
702 | /* Platform Driver */ | 822 | /* Platform Driver */ |
703 | /* ======================================================================== */ | 823 | /* ======================================================================== */ |
@@ -721,8 +841,6 @@ mpc52xx_uart_probe(struct platform_device *dev) | |||
721 | /* Init the port structure */ | 841 | /* Init the port structure */ |
722 | port = &mpc52xx_uart_ports[idx]; | 842 | port = &mpc52xx_uart_ports[idx]; |
723 | 843 | ||
724 | memset(port, 0x00, sizeof(struct uart_port)); | ||
725 | |||
726 | spin_lock_init(&port->lock); | 844 | spin_lock_init(&port->lock); |
727 | port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */ | 845 | port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */ |
728 | port->fifosize = 512; | 846 | port->fifosize = 512; |
@@ -731,6 +849,7 @@ mpc52xx_uart_probe(struct platform_device *dev) | |||
731 | ( uart_console(port) ? 0 : UPF_IOREMAP ); | 849 | ( uart_console(port) ? 0 : UPF_IOREMAP ); |
732 | port->line = idx; | 850 | port->line = idx; |
733 | port->ops = &mpc52xx_uart_ops; | 851 | port->ops = &mpc52xx_uart_ops; |
852 | port->dev = &dev->dev; | ||
734 | 853 | ||
735 | /* Search for IRQ and mapbase */ | 854 | /* Search for IRQ and mapbase */ |
736 | for (i=0 ; i<dev->num_resources ; i++, res++) { | 855 | for (i=0 ; i<dev->num_resources ; i++, res++) { |
@@ -787,6 +906,7 @@ mpc52xx_uart_resume(struct platform_device *dev) | |||
787 | } | 906 | } |
788 | #endif | 907 | #endif |
789 | 908 | ||
909 | |||
790 | static struct platform_driver mpc52xx_uart_platform_driver = { | 910 | static struct platform_driver mpc52xx_uart_platform_driver = { |
791 | .probe = mpc52xx_uart_probe, | 911 | .probe = mpc52xx_uart_probe, |
792 | .remove = mpc52xx_uart_remove, | 912 | .remove = mpc52xx_uart_remove, |
@@ -798,6 +918,184 @@ static struct platform_driver mpc52xx_uart_platform_driver = { | |||
798 | .name = "mpc52xx-psc", | 918 | .name = "mpc52xx-psc", |
799 | }, | 919 | }, |
800 | }; | 920 | }; |
921 | #endif /* !defined(CONFIG_PPC_MERGE) */ | ||
922 | |||
923 | |||
924 | #if defined(CONFIG_PPC_MERGE) | ||
925 | /* ======================================================================== */ | ||
926 | /* OF Platform Driver */ | ||
927 | /* ======================================================================== */ | ||
928 | |||
929 | static int __devinit | ||
930 | mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | ||
931 | { | ||
932 | int idx = -1; | ||
933 | unsigned int ipb_freq; | ||
934 | struct uart_port *port = NULL; | ||
935 | struct resource res; | ||
936 | int ret; | ||
937 | |||
938 | dev_dbg(&op->dev, "mpc52xx_uart_probe(op=%p, match=%p)\n", op, match); | ||
939 | |||
940 | /* Check validity & presence */ | ||
941 | for (idx = 0; idx < MPC52xx_PSC_MAXNUM; idx++) | ||
942 | if (mpc52xx_uart_nodes[idx] == op->node) | ||
943 | break; | ||
944 | if (idx >= MPC52xx_PSC_MAXNUM) | ||
945 | return -EINVAL; | ||
946 | pr_debug("Found %s assigned to ttyPSC%x\n", | ||
947 | mpc52xx_uart_nodes[idx]->full_name, idx); | ||
948 | |||
949 | /* Search for bus-frequency property in this node or a parent */ | ||
950 | if ((ipb_freq = mpc52xx_find_ipb_freq(op->node)) == 0) { | ||
951 | dev_dbg(&op->dev, "Could not find IPB bus frequency!\n"); | ||
952 | return -EINVAL; | ||
953 | } | ||
954 | |||
955 | /* Init the port structure */ | ||
956 | port = &mpc52xx_uart_ports[idx]; | ||
957 | |||
958 | spin_lock_init(&port->lock); | ||
959 | port->uartclk = ipb_freq / 2; | ||
960 | port->fifosize = 512; | ||
961 | port->iotype = UPIO_MEM; | ||
962 | port->flags = UPF_BOOT_AUTOCONF | | ||
963 | ( uart_console(port) ? 0 : UPF_IOREMAP ); | ||
964 | port->line = idx; | ||
965 | port->ops = &mpc52xx_uart_ops; | ||
966 | port->dev = &op->dev; | ||
967 | |||
968 | /* Search for IRQ and mapbase */ | ||
969 | if ((ret = of_address_to_resource(op->node, 0, &res)) != 0) | ||
970 | return ret; | ||
971 | |||
972 | port->mapbase = res.start; | ||
973 | port->irq = irq_of_parse_and_map(op->node, 0); | ||
974 | |||
975 | dev_dbg(&op->dev, "mpc52xx-psc uart at %lx, irq=%x, freq=%i\n", | ||
976 | port->mapbase, port->irq, port->uartclk); | ||
977 | |||
978 | if ((port->irq==NO_IRQ) || !port->mapbase) { | ||
979 | printk(KERN_ERR "Could not allocate resources for PSC\n"); | ||
980 | return -EINVAL; | ||
981 | } | ||
982 | |||
983 | /* Add the port to the uart sub-system */ | ||
984 | ret = uart_add_one_port(&mpc52xx_uart_driver, port); | ||
985 | if (!ret) | ||
986 | dev_set_drvdata(&op->dev, (void*)port); | ||
987 | |||
988 | return ret; | ||
989 | } | ||
990 | |||
991 | static int | ||
992 | mpc52xx_uart_of_remove(struct of_device *op) | ||
993 | { | ||
994 | struct uart_port *port = dev_get_drvdata(&op->dev); | ||
995 | dev_set_drvdata(&op->dev, NULL); | ||
996 | |||
997 | if (port) | ||
998 | uart_remove_one_port(&mpc52xx_uart_driver, port); | ||
999 | |||
1000 | return 0; | ||
1001 | } | ||
1002 | |||
1003 | #ifdef CONFIG_PM | ||
1004 | static int | ||
1005 | mpc52xx_uart_of_suspend(struct of_device *op, pm_message_t state) | ||
1006 | { | ||
1007 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); | ||
1008 | |||
1009 | if (port) | ||
1010 | uart_suspend_port(&mpc52xx_uart_driver, port); | ||
1011 | |||
1012 | return 0; | ||
1013 | } | ||
1014 | |||
1015 | static int | ||
1016 | mpc52xx_uart_of_resume(struct of_device *op) | ||
1017 | { | ||
1018 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); | ||
1019 | |||
1020 | if (port) | ||
1021 | uart_resume_port(&mpc52xx_uart_driver, port); | ||
1022 | |||
1023 | return 0; | ||
1024 | } | ||
1025 | #endif | ||
1026 | |||
1027 | static void | ||
1028 | mpc52xx_uart_of_assign(struct device_node *np, int idx) | ||
1029 | { | ||
1030 | int free_idx = -1; | ||
1031 | int i; | ||
1032 | |||
1033 | /* Find the first free node */ | ||
1034 | for (i = 0; i < MPC52xx_PSC_MAXNUM; i++) { | ||
1035 | if (mpc52xx_uart_nodes[i] == NULL) { | ||
1036 | free_idx = i; | ||
1037 | break; | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1041 | if ((idx < 0) || (idx >= MPC52xx_PSC_MAXNUM)) | ||
1042 | idx = free_idx; | ||
1043 | |||
1044 | if (idx < 0) | ||
1045 | return; /* No free slot; abort */ | ||
1046 | |||
1047 | /* If the slot is already occupied, then swap slots */ | ||
1048 | if (mpc52xx_uart_nodes[idx] && (free_idx != -1)) | ||
1049 | mpc52xx_uart_nodes[free_idx] = mpc52xx_uart_nodes[idx]; | ||
1050 | mpc52xx_uart_nodes[i] = np; | ||
1051 | } | ||
1052 | |||
1053 | static void | ||
1054 | mpc52xx_uart_of_enumerate(void) | ||
1055 | { | ||
1056 | static int enum_done = 0; | ||
1057 | struct device_node *np; | ||
1058 | const unsigned int *devno; | ||
1059 | int i; | ||
1060 | |||
1061 | if (enum_done) | ||
1062 | return; | ||
1063 | |||
1064 | for_each_node_by_type(np, "serial") { | ||
1065 | if (!of_match_node(mpc52xx_uart_of_match, np)) | ||
1066 | continue; | ||
1067 | |||
1068 | /* Is a particular device number requested? */ | ||
1069 | devno = get_property(np, "device_no", NULL); | ||
1070 | mpc52xx_uart_of_assign(of_node_get(np), devno ? *devno : -1); | ||
1071 | } | ||
1072 | |||
1073 | enum_done = 1; | ||
1074 | |||
1075 | for (i = 0; i < MPC52xx_PSC_MAXNUM; i++) { | ||
1076 | if (mpc52xx_uart_nodes[i]) | ||
1077 | pr_debug("%s assigned to ttyPSC%x\n", | ||
1078 | mpc52xx_uart_nodes[i]->full_name, i); | ||
1079 | } | ||
1080 | } | ||
1081 | |||
1082 | MODULE_DEVICE_TABLE(of, mpc52xx_uart_of_match); | ||
1083 | |||
1084 | static struct of_platform_driver mpc52xx_uart_of_driver = { | ||
1085 | .owner = THIS_MODULE, | ||
1086 | .name = "mpc52xx-psc-uart", | ||
1087 | .match_table = mpc52xx_uart_of_match, | ||
1088 | .probe = mpc52xx_uart_of_probe, | ||
1089 | .remove = mpc52xx_uart_of_remove, | ||
1090 | #ifdef CONFIG_PM | ||
1091 | .suspend = mpc52xx_uart_of_suspend, | ||
1092 | .resume = mpc52xx_uart_of_resume, | ||
1093 | #endif | ||
1094 | .driver = { | ||
1095 | .name = "mpc52xx-psc-uart", | ||
1096 | }, | ||
1097 | }; | ||
1098 | #endif /* defined(CONFIG_PPC_MERGE) */ | ||
801 | 1099 | ||
802 | 1100 | ||
803 | /* ======================================================================== */ | 1101 | /* ======================================================================== */ |
@@ -809,22 +1107,45 @@ mpc52xx_uart_init(void) | |||
809 | { | 1107 | { |
810 | int ret; | 1108 | int ret; |
811 | 1109 | ||
812 | printk(KERN_INFO "Serial: MPC52xx PSC driver\n"); | 1110 | printk(KERN_INFO "Serial: MPC52xx PSC UART driver\n"); |
813 | 1111 | ||
814 | ret = uart_register_driver(&mpc52xx_uart_driver); | 1112 | if ((ret = uart_register_driver(&mpc52xx_uart_driver)) != 0) { |
815 | if (ret == 0) { | 1113 | printk(KERN_ERR "%s: uart_register_driver failed (%i)\n", |
816 | ret = platform_driver_register(&mpc52xx_uart_platform_driver); | 1114 | __FILE__, ret); |
817 | if (ret) | 1115 | return ret; |
818 | uart_unregister_driver(&mpc52xx_uart_driver); | ||
819 | } | 1116 | } |
820 | 1117 | ||
821 | return ret; | 1118 | #if defined(CONFIG_PPC_MERGE) |
1119 | mpc52xx_uart_of_enumerate(); | ||
1120 | |||
1121 | ret = of_register_platform_driver(&mpc52xx_uart_of_driver); | ||
1122 | if (ret) { | ||
1123 | printk(KERN_ERR "%s: of_register_platform_driver failed (%i)\n", | ||
1124 | __FILE__, ret); | ||
1125 | uart_unregister_driver(&mpc52xx_uart_driver); | ||
1126 | return ret; | ||
1127 | } | ||
1128 | #else | ||
1129 | ret = platform_driver_register(&mpc52xx_uart_platform_driver); | ||
1130 | if (ret) { | ||
1131 | printk(KERN_ERR "%s: platform_driver_register failed (%i)\n", | ||
1132 | __FILE__, ret); | ||
1133 | uart_unregister_driver(&mpc52xx_uart_driver); | ||
1134 | return ret; | ||
1135 | } | ||
1136 | #endif | ||
1137 | |||
1138 | return 0; | ||
822 | } | 1139 | } |
823 | 1140 | ||
824 | static void __exit | 1141 | static void __exit |
825 | mpc52xx_uart_exit(void) | 1142 | mpc52xx_uart_exit(void) |
826 | { | 1143 | { |
1144 | #if defined(CONFIG_PPC_MERGE) | ||
1145 | of_unregister_platform_driver(&mpc52xx_uart_of_driver); | ||
1146 | #else | ||
827 | platform_driver_unregister(&mpc52xx_uart_platform_driver); | 1147 | platform_driver_unregister(&mpc52xx_uart_platform_driver); |
1148 | #endif | ||
828 | uart_unregister_driver(&mpc52xx_uart_driver); | 1149 | uart_unregister_driver(&mpc52xx_uart_driver); |
829 | } | 1150 | } |
830 | 1151 | ||