diff options
-rw-r--r-- | arch/powerpc/Kconfig | 2 | ||||
-rw-r--r-- | arch/powerpc/boot/dts/mpc5121ads.dts | 122 | ||||
-rw-r--r-- | arch/powerpc/platforms/512x/Kconfig | 20 | ||||
-rw-r--r-- | arch/powerpc/platforms/512x/Makefile | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/512x/mpc5121_ads.c | 104 | ||||
-rw-r--r-- | arch/powerpc/platforms/Kconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/Kconfig.cputype | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/Makefile | 1 | ||||
-rw-r--r-- | drivers/serial/Kconfig | 12 | ||||
-rw-r--r-- | drivers/serial/mpc52xx_uart.c | 431 | ||||
-rw-r--r-- | include/asm-powerpc/mpc512x.h | 22 | ||||
-rw-r--r-- | include/asm-powerpc/mpc52xx_psc.h | 48 |
12 files changed, 694 insertions, 79 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index cf030b004415..1348bbc92510 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -512,7 +512,7 @@ config PCI | |||
512 | bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ | 512 | bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ |
513 | || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \ | 513 | || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \ |
514 | || PPC_PS3 || 44x | 514 | || PPC_PS3 || 44x |
515 | default y if !40x && !CPM2 && !8xx && !PPC_83xx \ | 515 | default y if !40x && !CPM2 && !8xx && !PPC_MPC512x && !PPC_83xx \ |
516 | && !PPC_85xx && !PPC_86xx | 516 | && !PPC_85xx && !PPC_86xx |
517 | default PCI_PERMEDIA if !4xx && !CPM2 && !8xx | 517 | default PCI_PERMEDIA if !4xx && !CPM2 && !8xx |
518 | default PCI_QSPAN if !4xx && !CPM2 && 8xx | 518 | default PCI_QSPAN if !4xx && !CPM2 && 8xx |
diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts new file mode 100644 index 000000000000..94ad7b2b241e --- /dev/null +++ b/arch/powerpc/boot/dts/mpc5121ads.dts | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * MPC5121E MDS Device Tree Source | ||
3 | * | ||
4 | * Copyright 2007 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | /dts-v1/; | ||
13 | |||
14 | / { | ||
15 | model = "mpc5121ads"; | ||
16 | compatible = "fsl,mpc5121ads"; | ||
17 | #address-cells = <1>; | ||
18 | #size-cells = <1>; | ||
19 | |||
20 | cpus { | ||
21 | #address-cells = <1>; | ||
22 | #size-cells = <0>; | ||
23 | |||
24 | PowerPC,5121@0 { | ||
25 | device_type = "cpu"; | ||
26 | reg = <0>; | ||
27 | d-cache-line-size = <0x20>; // 32 bytes | ||
28 | i-cache-line-size = <0x20>; // 32 bytes | ||
29 | d-cache-size = <0x8000>; // L1, 32K | ||
30 | i-cache-size = <0x8000>; // L1, 32K | ||
31 | timebase-frequency = <49500000>;// 49.5 MHz (csb/4) | ||
32 | bus-frequency = <198000000>; // 198 MHz csb bus | ||
33 | clock-frequency = <396000000>; // 396 MHz ppc core | ||
34 | }; | ||
35 | }; | ||
36 | |||
37 | memory { | ||
38 | device_type = "memory"; | ||
39 | reg = <0x00000000 0x10000000>; // 256MB at 0 | ||
40 | }; | ||
41 | |||
42 | localbus@80000020 { | ||
43 | compatible = "fsl,mpc5121ads-localbus"; | ||
44 | #address-cells = <2>; | ||
45 | #size-cells = <1>; | ||
46 | reg = <0x80000020 0x40>; | ||
47 | |||
48 | ranges = <0x0 0x0 0xfc000000 0x04000000 | ||
49 | 0x2 0x0 0x82000000 0x00008000>; | ||
50 | |||
51 | flash@0,0 { | ||
52 | compatible = "cfi-flash"; | ||
53 | reg = <0 0x0 0x4000000>; | ||
54 | bank-width = <4>; | ||
55 | device-width = <1>; | ||
56 | }; | ||
57 | |||
58 | board-control@2,0 { | ||
59 | compatible = "fsl,mpc5121ads-cpld"; | ||
60 | reg = <0x2 0x0 0x8000>; | ||
61 | }; | ||
62 | }; | ||
63 | |||
64 | soc@80000000 { | ||
65 | compatible = "fsl,mpc5121-immr"; | ||
66 | #address-cells = <1>; | ||
67 | #size-cells = <1>; | ||
68 | #interrupt-cells = <2>; | ||
69 | ranges = <0x0 0x80000000 0x400000>; | ||
70 | reg = <0x80000000 0x400000>; | ||
71 | bus-frequency = <66000000>; // 66 MHz ips bus | ||
72 | |||
73 | |||
74 | // IPIC | ||
75 | // interrupts cell = <intr #, sense> | ||
76 | // sense values match linux IORESOURCE_IRQ_* defines: | ||
77 | // sense == 8: Level, low assertion | ||
78 | // sense == 2: Edge, high-to-low change | ||
79 | // | ||
80 | ipic: interrupt-controller@c00 { | ||
81 | compatible = "fsl,mpc5121-ipic", "fsl,ipic"; | ||
82 | interrupt-controller; | ||
83 | #address-cells = <0>; | ||
84 | #interrupt-cells = <2>; | ||
85 | reg = <0xc00 0x100>; | ||
86 | }; | ||
87 | |||
88 | // 512x PSCs are not 52xx PSCs compatible | ||
89 | // PSC3 serial port A aka ttyPSC0 | ||
90 | serial@11300 { | ||
91 | device_type = "serial"; | ||
92 | compatible = "fsl,mpc5121-psc-uart"; | ||
93 | // Logical port assignment needed until driver | ||
94 | // learns to use aliases | ||
95 | port-number = <0>; | ||
96 | cell-index = <3>; | ||
97 | reg = <0x11300 0x100>; | ||
98 | interrupts = <0x28 0x8>; // actually the fifo irq | ||
99 | interrupt-parent = < &ipic >; | ||
100 | }; | ||
101 | |||
102 | // PSC4 serial port B aka ttyPSC1 | ||
103 | serial@11400 { | ||
104 | device_type = "serial"; | ||
105 | compatible = "fsl,mpc5121-psc-uart"; | ||
106 | // Logical port assignment needed until driver | ||
107 | // learns to use aliases | ||
108 | port-number = <1>; | ||
109 | cell-index = <4>; | ||
110 | reg = <0x11400 0x100>; | ||
111 | interrupts = <0x28 0x8>; // actually the fifo irq | ||
112 | interrupt-parent = < &ipic >; | ||
113 | }; | ||
114 | |||
115 | pscsfifo@11f00 { | ||
116 | compatible = "fsl,mpc5121-psc-fifo"; | ||
117 | reg = <0x11f00 0x100>; | ||
118 | interrupts = <0x28 0x8>; | ||
119 | interrupt-parent = < &ipic >; | ||
120 | }; | ||
121 | }; | ||
122 | }; | ||
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig new file mode 100644 index 000000000000..c6fa49e23dc0 --- /dev/null +++ b/arch/powerpc/platforms/512x/Kconfig | |||
@@ -0,0 +1,20 @@ | |||
1 | config PPC_MPC512x | ||
2 | bool | ||
3 | select FSL_SOC | ||
4 | select IPIC | ||
5 | default n | ||
6 | |||
7 | config PPC_MPC5121 | ||
8 | bool | ||
9 | select PPC_MPC512x | ||
10 | default n | ||
11 | |||
12 | config MPC5121_ADS | ||
13 | bool "Freescale MPC5121E ADS" | ||
14 | depends on PPC_MULTIPLATFORM && PPC32 | ||
15 | select DEFAULT_UIMAGE | ||
16 | select WANT_DEVICE_TREE | ||
17 | select PPC_MPC5121 | ||
18 | help | ||
19 | This option enables support for the MPC5121E ADS board. | ||
20 | default n | ||
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile new file mode 100644 index 000000000000..232c89f2039a --- /dev/null +++ b/arch/powerpc/platforms/512x/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | # | ||
2 | # Makefile for the Freescale PowerPC 512x linux kernel. | ||
3 | # | ||
4 | obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o | ||
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c new file mode 100644 index 000000000000..50bd3a319022 --- /dev/null +++ b/arch/powerpc/platforms/512x/mpc5121_ads.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * Author: John Rigby, <jrigby@freescale.com>, Thur Mar 29 2007 | ||
5 | * | ||
6 | * Description: | ||
7 | * MPC5121 ADS board setup | ||
8 | * | ||
9 | * This is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/of_platform.h> | ||
20 | |||
21 | #include <asm/machdep.h> | ||
22 | #include <asm/ipic.h> | ||
23 | #include <asm/prom.h> | ||
24 | #include <asm/time.h> | ||
25 | |||
26 | /** | ||
27 | * mpc512x_find_ips_freq - Find the IPS bus frequency for a device | ||
28 | * @node: device node | ||
29 | * | ||
30 | * Returns IPS bus frequency, or 0 if the bus frequency cannot be found. | ||
31 | */ | ||
32 | unsigned long | ||
33 | mpc512x_find_ips_freq(struct device_node *node) | ||
34 | { | ||
35 | struct device_node *np; | ||
36 | const unsigned int *p_ips_freq = NULL; | ||
37 | |||
38 | of_node_get(node); | ||
39 | while (node) { | ||
40 | p_ips_freq = of_get_property(node, "bus-frequency", NULL); | ||
41 | if (p_ips_freq) | ||
42 | break; | ||
43 | |||
44 | np = of_get_parent(node); | ||
45 | of_node_put(node); | ||
46 | node = np; | ||
47 | } | ||
48 | if (node) | ||
49 | of_node_put(node); | ||
50 | |||
51 | return p_ips_freq ? *p_ips_freq : 0; | ||
52 | } | ||
53 | EXPORT_SYMBOL(mpc512x_find_ips_freq); | ||
54 | |||
55 | static struct of_device_id __initdata of_bus_ids[] = { | ||
56 | { .name = "soc", }, | ||
57 | { .name = "localbus", }, | ||
58 | {}, | ||
59 | }; | ||
60 | |||
61 | static void __init mpc5121_ads_declare_of_platform_devices(void) | ||
62 | { | ||
63 | /* Find every child of the SOC node and add it to of_platform */ | ||
64 | if (of_platform_bus_probe(NULL, of_bus_ids, NULL)) | ||
65 | printk(KERN_ERR __FILE__ ": " | ||
66 | "Error while probing of_platform bus\n"); | ||
67 | } | ||
68 | |||
69 | static void __init mpc5121_ads_init_IRQ(void) | ||
70 | { | ||
71 | struct device_node *np; | ||
72 | |||
73 | np = of_find_compatible_node(NULL, NULL, "fsl,ipic"); | ||
74 | if (!np) | ||
75 | return; | ||
76 | |||
77 | ipic_init(np, 0); | ||
78 | of_node_put(np); | ||
79 | |||
80 | /* | ||
81 | * Initialize the default interrupt mapping priorities, | ||
82 | * in case the boot rom changed something on us. | ||
83 | */ | ||
84 | ipic_set_default_priority(); | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * Called very early, MMU is off, device-tree isn't unflattened | ||
89 | */ | ||
90 | static int __init mpc5121_ads_probe(void) | ||
91 | { | ||
92 | unsigned long root = of_get_flat_dt_root(); | ||
93 | |||
94 | return of_flat_dt_is_compatible(root, "fsl,mpc5121ads"); | ||
95 | } | ||
96 | |||
97 | define_machine(mpc5121_ads) { | ||
98 | .name = "MPC5121 ADS", | ||
99 | .probe = mpc5121_ads_probe, | ||
100 | .init = mpc5121_ads_declare_of_platform_devices, | ||
101 | .init_IRQ = mpc5121_ads_init_IRQ, | ||
102 | .get_irq = ipic_get_irq, | ||
103 | .calibrate_decr = generic_calibrate_decr, | ||
104 | }; | ||
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 045b8c80eeaf..fcedbec07f94 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -42,6 +42,7 @@ config CLASSIC32 | |||
42 | source "arch/powerpc/platforms/pseries/Kconfig" | 42 | source "arch/powerpc/platforms/pseries/Kconfig" |
43 | source "arch/powerpc/platforms/iseries/Kconfig" | 43 | source "arch/powerpc/platforms/iseries/Kconfig" |
44 | source "arch/powerpc/platforms/chrp/Kconfig" | 44 | source "arch/powerpc/platforms/chrp/Kconfig" |
45 | source "arch/powerpc/platforms/512x/Kconfig" | ||
45 | source "arch/powerpc/platforms/52xx/Kconfig" | 46 | source "arch/powerpc/platforms/52xx/Kconfig" |
46 | source "arch/powerpc/platforms/powermac/Kconfig" | 47 | source "arch/powerpc/platforms/powermac/Kconfig" |
47 | source "arch/powerpc/platforms/prep/Kconfig" | 48 | source "arch/powerpc/platforms/prep/Kconfig" |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index eea2e7049fed..69941ba70975 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
@@ -14,7 +14,7 @@ choice | |||
14 | There are five families of 32 bit PowerPC chips supported. | 14 | There are five families of 32 bit PowerPC chips supported. |
15 | The most common ones are the desktop and server CPUs (601, 603, | 15 | The most common ones are the desktop and server CPUs (601, 603, |
16 | 604, 740, 750, 74xx) CPUs from Freescale and IBM, with their | 16 | 604, 740, 750, 74xx) CPUs from Freescale and IBM, with their |
17 | embedded 52xx/82xx/83xx/86xx counterparts. | 17 | embedded 512x/52xx/82xx/83xx/86xx counterparts. |
18 | The other embeeded parts, namely 4xx, 8xx, e200 (55xx) and e500 | 18 | The other embeeded parts, namely 4xx, 8xx, e200 (55xx) and e500 |
19 | (85xx) each form a family of their own that is not compatible | 19 | (85xx) each form a family of their own that is not compatible |
20 | with the others. | 20 | with the others. |
@@ -22,7 +22,7 @@ choice | |||
22 | If unsure, select 52xx/6xx/7xx/74xx/82xx/83xx/86xx. | 22 | If unsure, select 52xx/6xx/7xx/74xx/82xx/83xx/86xx. |
23 | 23 | ||
24 | config 6xx | 24 | config 6xx |
25 | bool "52xx/6xx/7xx/74xx/82xx/83xx/86xx" | 25 | bool "512x/52xx/6xx/7xx/74xx/82xx/83xx/86xx" |
26 | select PPC_FPU | 26 | select PPC_FPU |
27 | 27 | ||
28 | config PPC_85xx | 28 | config PPC_85xx |
@@ -225,7 +225,7 @@ config NR_CPUS | |||
225 | 225 | ||
226 | config NOT_COHERENT_CACHE | 226 | config NOT_COHERENT_CACHE |
227 | bool | 227 | bool |
228 | depends on 4xx || 8xx || E200 | 228 | depends on 4xx || 8xx || E200 || PPC_MPC512x |
229 | default y | 229 | default y |
230 | 230 | ||
231 | config CHECK_CACHE_COHERENCY | 231 | config CHECK_CACHE_COHERENCY |
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index 6d9079da5f5a..a984894466d9 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile | |||
@@ -11,6 +11,7 @@ endif | |||
11 | obj-$(CONFIG_PPC_CHRP) += chrp/ | 11 | obj-$(CONFIG_PPC_CHRP) += chrp/ |
12 | obj-$(CONFIG_40x) += 40x/ | 12 | obj-$(CONFIG_40x) += 40x/ |
13 | obj-$(CONFIG_44x) += 44x/ | 13 | obj-$(CONFIG_44x) += 44x/ |
14 | obj-$(CONFIG_PPC_MPC512x) += 512x/ | ||
14 | obj-$(CONFIG_PPC_MPC52xx) += 52xx/ | 15 | obj-$(CONFIG_PPC_MPC52xx) += 52xx/ |
15 | obj-$(CONFIG_PPC_8xx) += 8xx/ | 16 | obj-$(CONFIG_PPC_8xx) += 8xx/ |
16 | obj-$(CONFIG_PPC_82xx) += 82xx/ | 17 | obj-$(CONFIG_PPC_82xx) += 82xx/ |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 4fa7927997ad..ddfb1eab7363 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -1138,17 +1138,17 @@ config SERIAL_SGI_L1_CONSOLE | |||
1138 | say Y. Otherwise, say N. | 1138 | say Y. Otherwise, say N. |
1139 | 1139 | ||
1140 | config SERIAL_MPC52xx | 1140 | config SERIAL_MPC52xx |
1141 | tristate "Freescale MPC52xx family PSC serial support" | 1141 | tristate "Freescale MPC52xx/MPC512x family PSC serial support" |
1142 | depends on PPC_MPC52xx | 1142 | depends on PPC_MPC52xx || PPC_MPC512x |
1143 | select SERIAL_CORE | 1143 | select SERIAL_CORE |
1144 | help | 1144 | help |
1145 | This drivers support the MPC52xx PSC serial ports. If you would | 1145 | This driver supports MPC52xx and MPC512x PSC serial ports. If you would |
1146 | like to use them, you must answer Y or M to this option. Not that | 1146 | like to use them, you must answer Y or M to this option. Note that |
1147 | for use as console, it must be included in kernel and not as a | 1147 | for use as console, it must be included in kernel and not as a |
1148 | module. | 1148 | module. |
1149 | 1149 | ||
1150 | config SERIAL_MPC52xx_CONSOLE | 1150 | config SERIAL_MPC52xx_CONSOLE |
1151 | bool "Console on a Freescale MPC52xx family PSC serial port" | 1151 | bool "Console on a Freescale MPC52xx/MPC512x family PSC serial port" |
1152 | depends on SERIAL_MPC52xx=y | 1152 | depends on SERIAL_MPC52xx=y |
1153 | select SERIAL_CORE_CONSOLE | 1153 | select SERIAL_CORE_CONSOLE |
1154 | help | 1154 | help |
@@ -1156,7 +1156,7 @@ config SERIAL_MPC52xx_CONSOLE | |||
1156 | of the Freescale MPC52xx family as a console. | 1156 | of the Freescale MPC52xx family as a console. |
1157 | 1157 | ||
1158 | config SERIAL_MPC52xx_CONSOLE_BAUD | 1158 | config SERIAL_MPC52xx_CONSOLE_BAUD |
1159 | int "Freescale MPC52xx family PSC serial port baud" | 1159 | int "Freescale MPC52xx/MPC512x family PSC serial port baud" |
1160 | depends on SERIAL_MPC52xx_CONSOLE=y | 1160 | depends on SERIAL_MPC52xx_CONSOLE=y |
1161 | default "9600" | 1161 | default "9600" |
1162 | help | 1162 | help |
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 3c4d29e59b2c..821facd10bbc 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -16,6 +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) 2008 Freescale Semiconductor Inc. | ||
20 | * John Rigby <jrigby@gmail.com> | ||
21 | * Added support for MPC5121 | ||
19 | * Copyright (C) 2006 Secret Lab Technologies Ltd. | 22 | * Copyright (C) 2006 Secret Lab Technologies Ltd. |
20 | * Grant Likely <grant.likely@secretlab.ca> | 23 | * Grant Likely <grant.likely@secretlab.ca> |
21 | * Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com> | 24 | * Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com> |
@@ -67,7 +70,6 @@ | |||
67 | #include <linux/serial.h> | 70 | #include <linux/serial.h> |
68 | #include <linux/sysrq.h> | 71 | #include <linux/sysrq.h> |
69 | #include <linux/console.h> | 72 | #include <linux/console.h> |
70 | |||
71 | #include <linux/delay.h> | 73 | #include <linux/delay.h> |
72 | #include <linux/io.h> | 74 | #include <linux/io.h> |
73 | 75 | ||
@@ -79,6 +81,7 @@ | |||
79 | #endif | 81 | #endif |
80 | 82 | ||
81 | #include <asm/mpc52xx.h> | 83 | #include <asm/mpc52xx.h> |
84 | #include <asm/mpc512x.h> | ||
82 | #include <asm/mpc52xx_psc.h> | 85 | #include <asm/mpc52xx_psc.h> |
83 | 86 | ||
84 | #if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | 87 | #if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
@@ -111,8 +114,8 @@ static struct device_node *mpc52xx_uart_nodes[MPC52xx_PSC_MAXNUM]; | |||
111 | static void mpc52xx_uart_of_enumerate(void); | 114 | static void mpc52xx_uart_of_enumerate(void); |
112 | #endif | 115 | #endif |
113 | 116 | ||
117 | |||
114 | #define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase)) | 118 | #define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase)) |
115 | #define FIFO(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1)) | ||
116 | 119 | ||
117 | 120 | ||
118 | /* Forward declaration of the interruption handling routine */ | 121 | /* Forward declaration of the interruption handling routine */ |
@@ -130,13 +133,324 @@ static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id); | |||
130 | 133 | ||
131 | #if defined(CONFIG_PPC_MERGE) | 134 | #if defined(CONFIG_PPC_MERGE) |
132 | static struct of_device_id mpc52xx_uart_of_match[] = { | 135 | static struct of_device_id mpc52xx_uart_of_match[] = { |
133 | { .type = "serial", .compatible = "fsl,mpc5200-psc-uart", }, | 136 | #ifdef CONFIG_PPC_MPC52xx |
134 | { .type = "serial", .compatible = "mpc5200-psc-uart", }, /* lite5200 */ | 137 | { .compatible = "fsl,mpc5200-psc-uart", .data = &mpc52xx_psc_ops, }, |
135 | { .type = "serial", .compatible = "mpc5200-serial", }, /* efika */ | 138 | /* binding used by old lite5200 device trees: */ |
139 | { .compatible = "mpc5200-psc-uart", .data = &mpc52xx_psc_ops, }, | ||
140 | /* binding used by efika: */ | ||
141 | { .compatible = "mpc5200-serial", .data = &mpc52xx_psc_ops, }, | ||
142 | #endif | ||
143 | #ifdef CONFIG_PPC_MPC512x | ||
144 | { .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, }, | ||
145 | {}, | ||
146 | #endif | ||
147 | }; | ||
148 | #if defined(CONFIG_PPC_MERGE) | ||
149 | static const struct of_device_id mpc52xx_uart_of_match[] = { | ||
150 | {.type = "serial", | ||
151 | .compatible = "mpc5200-psc-uart", | ||
152 | #endif | ||
136 | {}, | 153 | {}, |
137 | }; | 154 | }; |
138 | #endif | 155 | #endif |
139 | 156 | ||
157 | #endif | ||
158 | |||
159 | /* ======================================================================== */ | ||
160 | /* PSC fifo operations for isolating differences between 52xx and 512x */ | ||
161 | /* ======================================================================== */ | ||
162 | |||
163 | struct psc_ops { | ||
164 | void (*fifo_init)(struct uart_port *port); | ||
165 | int (*raw_rx_rdy)(struct uart_port *port); | ||
166 | int (*raw_tx_rdy)(struct uart_port *port); | ||
167 | int (*rx_rdy)(struct uart_port *port); | ||
168 | int (*tx_rdy)(struct uart_port *port); | ||
169 | int (*tx_empty)(struct uart_port *port); | ||
170 | void (*stop_rx)(struct uart_port *port); | ||
171 | void (*start_tx)(struct uart_port *port); | ||
172 | void (*stop_tx)(struct uart_port *port); | ||
173 | void (*rx_clr_irq)(struct uart_port *port); | ||
174 | void (*tx_clr_irq)(struct uart_port *port); | ||
175 | void (*write_char)(struct uart_port *port, unsigned char c); | ||
176 | unsigned char (*read_char)(struct uart_port *port); | ||
177 | void (*cw_disable_ints)(struct uart_port *port); | ||
178 | void (*cw_restore_ints)(struct uart_port *port); | ||
179 | unsigned long (*getuartclk)(void *p); | ||
180 | }; | ||
181 | |||
182 | #ifdef CONFIG_PPC_MPC52xx | ||
183 | #define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1)) | ||
184 | static void mpc52xx_psc_fifo_init(struct uart_port *port) | ||
185 | { | ||
186 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
187 | struct mpc52xx_psc_fifo __iomem *fifo = FIFO_52xx(port); | ||
188 | |||
189 | /* /32 prescaler */ | ||
190 | out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); | ||
191 | |||
192 | out_8(&fifo->rfcntl, 0x00); | ||
193 | out_be16(&fifo->rfalarm, 0x1ff); | ||
194 | out_8(&fifo->tfcntl, 0x07); | ||
195 | out_be16(&fifo->tfalarm, 0x80); | ||
196 | |||
197 | port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY; | ||
198 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
199 | } | ||
200 | |||
201 | static int mpc52xx_psc_raw_rx_rdy(struct uart_port *port) | ||
202 | { | ||
203 | return in_be16(&PSC(port)->mpc52xx_psc_status) | ||
204 | & MPC52xx_PSC_SR_RXRDY; | ||
205 | } | ||
206 | |||
207 | static int mpc52xx_psc_raw_tx_rdy(struct uart_port *port) | ||
208 | { | ||
209 | return in_be16(&PSC(port)->mpc52xx_psc_status) | ||
210 | & MPC52xx_PSC_SR_TXRDY; | ||
211 | } | ||
212 | |||
213 | |||
214 | static int mpc52xx_psc_rx_rdy(struct uart_port *port) | ||
215 | { | ||
216 | return in_be16(&PSC(port)->mpc52xx_psc_isr) | ||
217 | & port->read_status_mask | ||
218 | & MPC52xx_PSC_IMR_RXRDY; | ||
219 | } | ||
220 | |||
221 | static int mpc52xx_psc_tx_rdy(struct uart_port *port) | ||
222 | { | ||
223 | return in_be16(&PSC(port)->mpc52xx_psc_isr) | ||
224 | & port->read_status_mask | ||
225 | & MPC52xx_PSC_IMR_TXRDY; | ||
226 | } | ||
227 | |||
228 | static int mpc52xx_psc_tx_empty(struct uart_port *port) | ||
229 | { | ||
230 | return in_be16(&PSC(port)->mpc52xx_psc_status) | ||
231 | & MPC52xx_PSC_SR_TXEMP; | ||
232 | } | ||
233 | |||
234 | static void mpc52xx_psc_start_tx(struct uart_port *port) | ||
235 | { | ||
236 | port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; | ||
237 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
238 | } | ||
239 | |||
240 | static void mpc52xx_psc_stop_tx(struct uart_port *port) | ||
241 | { | ||
242 | port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY; | ||
243 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
244 | } | ||
245 | |||
246 | static void mpc52xx_psc_stop_rx(struct uart_port *port) | ||
247 | { | ||
248 | port->read_status_mask &= ~MPC52xx_PSC_IMR_RXRDY; | ||
249 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
250 | } | ||
251 | |||
252 | static void mpc52xx_psc_rx_clr_irq(struct uart_port *port) | ||
253 | { | ||
254 | } | ||
255 | |||
256 | static void mpc52xx_psc_tx_clr_irq(struct uart_port *port) | ||
257 | { | ||
258 | } | ||
259 | |||
260 | static void mpc52xx_psc_write_char(struct uart_port *port, unsigned char c) | ||
261 | { | ||
262 | out_8(&PSC(port)->mpc52xx_psc_buffer_8, c); | ||
263 | } | ||
264 | |||
265 | static unsigned char mpc52xx_psc_read_char(struct uart_port *port) | ||
266 | { | ||
267 | return in_8(&PSC(port)->mpc52xx_psc_buffer_8); | ||
268 | } | ||
269 | |||
270 | static void mpc52xx_psc_cw_disable_ints(struct uart_port *port) | ||
271 | { | ||
272 | out_be16(&PSC(port)->mpc52xx_psc_imr, 0); | ||
273 | } | ||
274 | |||
275 | static void mpc52xx_psc_cw_restore_ints(struct uart_port *port) | ||
276 | { | ||
277 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
278 | } | ||
279 | |||
280 | /* Search for bus-frequency property in this node or a parent */ | ||
281 | static unsigned long mpc52xx_getuartclk(void *p) | ||
282 | { | ||
283 | #if defined(CONFIG_PPC_MERGE) | ||
284 | /* | ||
285 | * 5200 UARTs have a / 32 prescaler | ||
286 | * but the generic serial code assumes 16 | ||
287 | * so return ipb freq / 2 | ||
288 | */ | ||
289 | return mpc52xx_find_ipb_freq(p) / 2; | ||
290 | #else | ||
291 | pr_debug("unexpected call to mpc52xx_getuartclk with arch/ppc\n"); | ||
292 | return NULL; | ||
293 | #endif | ||
294 | } | ||
295 | |||
296 | static struct psc_ops mpc52xx_psc_ops = { | ||
297 | .fifo_init = mpc52xx_psc_fifo_init, | ||
298 | .raw_rx_rdy = mpc52xx_psc_raw_rx_rdy, | ||
299 | .raw_tx_rdy = mpc52xx_psc_raw_tx_rdy, | ||
300 | .rx_rdy = mpc52xx_psc_rx_rdy, | ||
301 | .tx_rdy = mpc52xx_psc_tx_rdy, | ||
302 | .tx_empty = mpc52xx_psc_tx_empty, | ||
303 | .stop_rx = mpc52xx_psc_stop_rx, | ||
304 | .start_tx = mpc52xx_psc_start_tx, | ||
305 | .stop_tx = mpc52xx_psc_stop_tx, | ||
306 | .rx_clr_irq = mpc52xx_psc_rx_clr_irq, | ||
307 | .tx_clr_irq = mpc52xx_psc_tx_clr_irq, | ||
308 | .write_char = mpc52xx_psc_write_char, | ||
309 | .read_char = mpc52xx_psc_read_char, | ||
310 | .cw_disable_ints = mpc52xx_psc_cw_disable_ints, | ||
311 | .cw_restore_ints = mpc52xx_psc_cw_restore_ints, | ||
312 | .getuartclk = mpc52xx_getuartclk, | ||
313 | }; | ||
314 | |||
315 | #endif /* CONFIG_MPC52xx */ | ||
316 | |||
317 | #ifdef CONFIG_PPC_MPC512x | ||
318 | #define FIFO_512x(port) ((struct mpc512x_psc_fifo __iomem *)(PSC(port)+1)) | ||
319 | static void mpc512x_psc_fifo_init(struct uart_port *port) | ||
320 | { | ||
321 | out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_RESET_SLICE); | ||
322 | out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_ENABLE_SLICE); | ||
323 | out_be32(&FIFO_512x(port)->txalarm, 1); | ||
324 | out_be32(&FIFO_512x(port)->tximr, 0); | ||
325 | |||
326 | out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_RESET_SLICE); | ||
327 | out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_ENABLE_SLICE); | ||
328 | out_be32(&FIFO_512x(port)->rxalarm, 1); | ||
329 | out_be32(&FIFO_512x(port)->rximr, 0); | ||
330 | |||
331 | out_be32(&FIFO_512x(port)->tximr, MPC512x_PSC_FIFO_ALARM); | ||
332 | out_be32(&FIFO_512x(port)->rximr, MPC512x_PSC_FIFO_ALARM); | ||
333 | } | ||
334 | |||
335 | static int mpc512x_psc_raw_rx_rdy(struct uart_port *port) | ||
336 | { | ||
337 | return !(in_be32(&FIFO_512x(port)->rxsr) & MPC512x_PSC_FIFO_EMPTY); | ||
338 | } | ||
339 | |||
340 | static int mpc512x_psc_raw_tx_rdy(struct uart_port *port) | ||
341 | { | ||
342 | return !(in_be32(&FIFO_512x(port)->txsr) & MPC512x_PSC_FIFO_FULL); | ||
343 | } | ||
344 | |||
345 | static int mpc512x_psc_rx_rdy(struct uart_port *port) | ||
346 | { | ||
347 | return in_be32(&FIFO_512x(port)->rxsr) | ||
348 | & in_be32(&FIFO_512x(port)->rximr) | ||
349 | & MPC512x_PSC_FIFO_ALARM; | ||
350 | } | ||
351 | |||
352 | static int mpc512x_psc_tx_rdy(struct uart_port *port) | ||
353 | { | ||
354 | return in_be32(&FIFO_512x(port)->txsr) | ||
355 | & in_be32(&FIFO_512x(port)->tximr) | ||
356 | & MPC512x_PSC_FIFO_ALARM; | ||
357 | } | ||
358 | |||
359 | static int mpc512x_psc_tx_empty(struct uart_port *port) | ||
360 | { | ||
361 | return in_be32(&FIFO_512x(port)->txsr) | ||
362 | & MPC512x_PSC_FIFO_EMPTY; | ||
363 | } | ||
364 | |||
365 | static void mpc512x_psc_stop_rx(struct uart_port *port) | ||
366 | { | ||
367 | unsigned long rx_fifo_imr; | ||
368 | |||
369 | rx_fifo_imr = in_be32(&FIFO_512x(port)->rximr); | ||
370 | rx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM; | ||
371 | out_be32(&FIFO_512x(port)->rximr, rx_fifo_imr); | ||
372 | } | ||
373 | |||
374 | static void mpc512x_psc_start_tx(struct uart_port *port) | ||
375 | { | ||
376 | unsigned long tx_fifo_imr; | ||
377 | |||
378 | tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr); | ||
379 | tx_fifo_imr |= MPC512x_PSC_FIFO_ALARM; | ||
380 | out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr); | ||
381 | } | ||
382 | |||
383 | static void mpc512x_psc_stop_tx(struct uart_port *port) | ||
384 | { | ||
385 | unsigned long tx_fifo_imr; | ||
386 | |||
387 | tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr); | ||
388 | tx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM; | ||
389 | out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr); | ||
390 | } | ||
391 | |||
392 | static void mpc512x_psc_rx_clr_irq(struct uart_port *port) | ||
393 | { | ||
394 | out_be32(&FIFO_512x(port)->rxisr, in_be32(&FIFO_512x(port)->rxisr)); | ||
395 | } | ||
396 | |||
397 | static void mpc512x_psc_tx_clr_irq(struct uart_port *port) | ||
398 | { | ||
399 | out_be32(&FIFO_512x(port)->txisr, in_be32(&FIFO_512x(port)->txisr)); | ||
400 | } | ||
401 | |||
402 | static void mpc512x_psc_write_char(struct uart_port *port, unsigned char c) | ||
403 | { | ||
404 | out_8(&FIFO_512x(port)->txdata_8, c); | ||
405 | } | ||
406 | |||
407 | static unsigned char mpc512x_psc_read_char(struct uart_port *port) | ||
408 | { | ||
409 | return in_8(&FIFO_512x(port)->rxdata_8); | ||
410 | } | ||
411 | |||
412 | static void mpc512x_psc_cw_disable_ints(struct uart_port *port) | ||
413 | { | ||
414 | port->read_status_mask = | ||
415 | in_be32(&FIFO_512x(port)->tximr) << 16 | | ||
416 | in_be32(&FIFO_512x(port)->rximr); | ||
417 | out_be32(&FIFO_512x(port)->tximr, 0); | ||
418 | out_be32(&FIFO_512x(port)->rximr, 0); | ||
419 | } | ||
420 | |||
421 | static void mpc512x_psc_cw_restore_ints(struct uart_port *port) | ||
422 | { | ||
423 | out_be32(&FIFO_512x(port)->tximr, | ||
424 | (port->read_status_mask >> 16) & 0x7f); | ||
425 | out_be32(&FIFO_512x(port)->rximr, port->read_status_mask & 0x7f); | ||
426 | } | ||
427 | |||
428 | static unsigned long mpc512x_getuartclk(void *p) | ||
429 | { | ||
430 | return mpc512x_find_ips_freq(p); | ||
431 | } | ||
432 | |||
433 | static struct psc_ops mpc512x_psc_ops = { | ||
434 | .fifo_init = mpc512x_psc_fifo_init, | ||
435 | .raw_rx_rdy = mpc512x_psc_raw_rx_rdy, | ||
436 | .raw_tx_rdy = mpc512x_psc_raw_tx_rdy, | ||
437 | .rx_rdy = mpc512x_psc_rx_rdy, | ||
438 | .tx_rdy = mpc512x_psc_tx_rdy, | ||
439 | .tx_empty = mpc512x_psc_tx_empty, | ||
440 | .stop_rx = mpc512x_psc_stop_rx, | ||
441 | .start_tx = mpc512x_psc_start_tx, | ||
442 | .stop_tx = mpc512x_psc_stop_tx, | ||
443 | .rx_clr_irq = mpc512x_psc_rx_clr_irq, | ||
444 | .tx_clr_irq = mpc512x_psc_tx_clr_irq, | ||
445 | .write_char = mpc512x_psc_write_char, | ||
446 | .read_char = mpc512x_psc_read_char, | ||
447 | .cw_disable_ints = mpc512x_psc_cw_disable_ints, | ||
448 | .cw_restore_ints = mpc512x_psc_cw_restore_ints, | ||
449 | .getuartclk = mpc512x_getuartclk, | ||
450 | }; | ||
451 | #endif | ||
452 | |||
453 | static struct psc_ops *psc_ops; | ||
140 | 454 | ||
141 | /* ======================================================================== */ | 455 | /* ======================================================================== */ |
142 | /* UART operations */ | 456 | /* UART operations */ |
@@ -145,8 +459,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = { | |||
145 | static unsigned int | 459 | static unsigned int |
146 | mpc52xx_uart_tx_empty(struct uart_port *port) | 460 | mpc52xx_uart_tx_empty(struct uart_port *port) |
147 | { | 461 | { |
148 | int status = in_be16(&PSC(port)->mpc52xx_psc_status); | 462 | return psc_ops->tx_empty(port) ? TIOCSER_TEMT : 0; |
149 | return (status & MPC52xx_PSC_SR_TXEMP) ? TIOCSER_TEMT : 0; | ||
150 | } | 463 | } |
151 | 464 | ||
152 | static void | 465 | static void |
@@ -166,16 +479,14 @@ static void | |||
166 | mpc52xx_uart_stop_tx(struct uart_port *port) | 479 | mpc52xx_uart_stop_tx(struct uart_port *port) |
167 | { | 480 | { |
168 | /* port->lock taken by caller */ | 481 | /* port->lock taken by caller */ |
169 | port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY; | 482 | psc_ops->stop_tx(port); |
170 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
171 | } | 483 | } |
172 | 484 | ||
173 | static void | 485 | static void |
174 | mpc52xx_uart_start_tx(struct uart_port *port) | 486 | mpc52xx_uart_start_tx(struct uart_port *port) |
175 | { | 487 | { |
176 | /* port->lock taken by caller */ | 488 | /* port->lock taken by caller */ |
177 | port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; | 489 | psc_ops->start_tx(port); |
178 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
179 | } | 490 | } |
180 | 491 | ||
181 | static void | 492 | static void |
@@ -188,8 +499,7 @@ mpc52xx_uart_send_xchar(struct uart_port *port, char ch) | |||
188 | if (ch) { | 499 | if (ch) { |
189 | /* Make sure tx interrupts are on */ | 500 | /* Make sure tx interrupts are on */ |
190 | /* Truly necessary ??? They should be anyway */ | 501 | /* Truly necessary ??? They should be anyway */ |
191 | port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; | 502 | psc_ops->start_tx(port); |
192 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
193 | } | 503 | } |
194 | 504 | ||
195 | spin_unlock_irqrestore(&port->lock, flags); | 505 | spin_unlock_irqrestore(&port->lock, flags); |
@@ -199,8 +509,7 @@ static void | |||
199 | mpc52xx_uart_stop_rx(struct uart_port *port) | 509 | mpc52xx_uart_stop_rx(struct uart_port *port) |
200 | { | 510 | { |
201 | /* port->lock taken by caller */ | 511 | /* port->lock taken by caller */ |
202 | port->read_status_mask &= ~MPC52xx_PSC_IMR_RXRDY; | 512 | psc_ops->stop_rx(port); |
203 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
204 | } | 513 | } |
205 | 514 | ||
206 | static void | 515 | static void |
@@ -227,12 +536,12 @@ static int | |||
227 | mpc52xx_uart_startup(struct uart_port *port) | 536 | mpc52xx_uart_startup(struct uart_port *port) |
228 | { | 537 | { |
229 | struct mpc52xx_psc __iomem *psc = PSC(port); | 538 | struct mpc52xx_psc __iomem *psc = PSC(port); |
230 | struct mpc52xx_psc_fifo __iomem *fifo = FIFO(port); | ||
231 | int ret; | 539 | int ret; |
232 | 540 | ||
233 | /* Request IRQ */ | 541 | /* Request IRQ */ |
234 | ret = request_irq(port->irq, mpc52xx_uart_int, | 542 | ret = request_irq(port->irq, mpc52xx_uart_int, |
235 | IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "mpc52xx_psc_uart", port); | 543 | IRQF_DISABLED | IRQF_SAMPLE_RANDOM | IRQF_SHARED, |
544 | "mpc52xx_psc_uart", port); | ||
236 | if (ret) | 545 | if (ret) |
237 | return ret; | 546 | return ret; |
238 | 547 | ||
@@ -242,15 +551,7 @@ mpc52xx_uart_startup(struct uart_port *port) | |||
242 | 551 | ||
243 | out_be32(&psc->sicr, 0); /* UART mode DCD ignored */ | 552 | out_be32(&psc->sicr, 0); /* UART mode DCD ignored */ |
244 | 553 | ||
245 | out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); /* /16 prescaler on */ | 554 | psc_ops->fifo_init(port); |
246 | |||
247 | out_8(&fifo->rfcntl, 0x00); | ||
248 | out_be16(&fifo->rfalarm, 0x1ff); | ||
249 | out_8(&fifo->tfcntl, 0x07); | ||
250 | out_be16(&fifo->tfalarm, 0x80); | ||
251 | |||
252 | port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY; | ||
253 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
254 | 555 | ||
255 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); | 556 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); |
256 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); | 557 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); |
@@ -333,8 +634,7 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | |||
333 | * boot for the console, all stuff is not yet ready to receive at that | 634 | * boot for the console, all stuff is not yet ready to receive at that |
334 | * time and that just makes the kernel oops */ | 635 | * time and that just makes the kernel oops */ |
335 | /* while (j-- && mpc52xx_uart_int_rx_chars(port)); */ | 636 | /* while (j-- && mpc52xx_uart_int_rx_chars(port)); */ |
336 | while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && | 637 | while (!mpc52xx_uart_tx_empty(port) && --j) |
337 | --j) | ||
338 | udelay(1); | 638 | udelay(1); |
339 | 639 | ||
340 | if (!j) | 640 | if (!j) |
@@ -462,11 +762,9 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
462 | unsigned short status; | 762 | unsigned short status; |
463 | 763 | ||
464 | /* While we can read, do so ! */ | 764 | /* While we can read, do so ! */ |
465 | while ((status = in_be16(&PSC(port)->mpc52xx_psc_status)) & | 765 | while (psc_ops->raw_rx_rdy(port)) { |
466 | MPC52xx_PSC_SR_RXRDY) { | ||
467 | |||
468 | /* Get the char */ | 766 | /* Get the char */ |
469 | ch = in_8(&PSC(port)->mpc52xx_psc_buffer_8); | 767 | ch = psc_ops->read_char(port); |
470 | 768 | ||
471 | /* Handle sysreq char */ | 769 | /* Handle sysreq char */ |
472 | #ifdef SUPPORT_SYSRQ | 770 | #ifdef SUPPORT_SYSRQ |
@@ -481,6 +779,8 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
481 | flag = TTY_NORMAL; | 779 | flag = TTY_NORMAL; |
482 | port->icount.rx++; | 780 | port->icount.rx++; |
483 | 781 | ||
782 | status = in_be16(&PSC(port)->mpc52xx_psc_status); | ||
783 | |||
484 | if (status & (MPC52xx_PSC_SR_PE | | 784 | if (status & (MPC52xx_PSC_SR_PE | |
485 | MPC52xx_PSC_SR_FE | | 785 | MPC52xx_PSC_SR_FE | |
486 | MPC52xx_PSC_SR_RB)) { | 786 | MPC52xx_PSC_SR_RB)) { |
@@ -510,7 +810,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
510 | 810 | ||
511 | tty_flip_buffer_push(tty); | 811 | tty_flip_buffer_push(tty); |
512 | 812 | ||
513 | return in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY; | 813 | return psc_ops->raw_rx_rdy(port); |
514 | } | 814 | } |
515 | 815 | ||
516 | static inline int | 816 | static inline int |
@@ -520,7 +820,7 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port) | |||
520 | 820 | ||
521 | /* Process out of band chars */ | 821 | /* Process out of band chars */ |
522 | if (port->x_char) { | 822 | if (port->x_char) { |
523 | out_8(&PSC(port)->mpc52xx_psc_buffer_8, port->x_char); | 823 | psc_ops->write_char(port, port->x_char); |
524 | port->icount.tx++; | 824 | port->icount.tx++; |
525 | port->x_char = 0; | 825 | port->x_char = 0; |
526 | return 1; | 826 | return 1; |
@@ -533,8 +833,8 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port) | |||
533 | } | 833 | } |
534 | 834 | ||
535 | /* Send chars */ | 835 | /* Send chars */ |
536 | while (in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXRDY) { | 836 | while (psc_ops->raw_tx_rdy(port)) { |
537 | out_8(&PSC(port)->mpc52xx_psc_buffer_8, xmit->buf[xmit->tail]); | 837 | psc_ops->write_char(port, xmit->buf[xmit->tail]); |
538 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 838 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
539 | port->icount.tx++; | 839 | port->icount.tx++; |
540 | if (uart_circ_empty(xmit)) | 840 | if (uart_circ_empty(xmit)) |
@@ -560,7 +860,6 @@ mpc52xx_uart_int(int irq, void *dev_id) | |||
560 | struct uart_port *port = dev_id; | 860 | struct uart_port *port = dev_id; |
561 | unsigned long pass = ISR_PASS_LIMIT; | 861 | unsigned long pass = ISR_PASS_LIMIT; |
562 | unsigned int keepgoing; | 862 | unsigned int keepgoing; |
563 | unsigned short status; | ||
564 | 863 | ||
565 | spin_lock(&port->lock); | 864 | spin_lock(&port->lock); |
566 | 865 | ||
@@ -569,18 +868,12 @@ mpc52xx_uart_int(int irq, void *dev_id) | |||
569 | /* If we don't find anything to do, we stop */ | 868 | /* If we don't find anything to do, we stop */ |
570 | keepgoing = 0; | 869 | keepgoing = 0; |
571 | 870 | ||
572 | /* Read status */ | 871 | psc_ops->rx_clr_irq(port); |
573 | status = in_be16(&PSC(port)->mpc52xx_psc_isr); | 872 | if (psc_ops->rx_rdy(port)) |
574 | status &= port->read_status_mask; | ||
575 | |||
576 | /* Do we need to receive chars ? */ | ||
577 | /* For this RX interrupts must be on and some chars waiting */ | ||
578 | if (status & MPC52xx_PSC_IMR_RXRDY) | ||
579 | keepgoing |= mpc52xx_uart_int_rx_chars(port); | 873 | keepgoing |= mpc52xx_uart_int_rx_chars(port); |
580 | 874 | ||
581 | /* Do we need to send chars ? */ | 875 | psc_ops->tx_clr_irq(port); |
582 | /* For this, TX must be ready and TX interrupt enabled */ | 876 | if (psc_ops->tx_rdy(port)) |
583 | if (status & MPC52xx_PSC_IMR_TXRDY) | ||
584 | keepgoing |= mpc52xx_uart_int_tx_chars(port); | 877 | keepgoing |= mpc52xx_uart_int_tx_chars(port); |
585 | 878 | ||
586 | /* Limit number of iteration */ | 879 | /* Limit number of iteration */ |
@@ -647,36 +940,33 @@ static void | |||
647 | mpc52xx_console_write(struct console *co, const char *s, unsigned int count) | 940 | mpc52xx_console_write(struct console *co, const char *s, unsigned int count) |
648 | { | 941 | { |
649 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; | 942 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; |
650 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
651 | unsigned int i, j; | 943 | unsigned int i, j; |
652 | 944 | ||
653 | /* Disable interrupts */ | 945 | /* Disable interrupts */ |
654 | out_be16(&psc->mpc52xx_psc_imr, 0); | 946 | psc_ops->cw_disable_ints(port); |
655 | 947 | ||
656 | /* Wait the TX buffer to be empty */ | 948 | /* Wait the TX buffer to be empty */ |
657 | j = 5000000; /* Maximum wait */ | 949 | j = 5000000; /* Maximum wait */ |
658 | while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && | 950 | while (!mpc52xx_uart_tx_empty(port) && --j) |
659 | --j) | ||
660 | udelay(1); | 951 | udelay(1); |
661 | 952 | ||
662 | /* Write all the chars */ | 953 | /* Write all the chars */ |
663 | for (i = 0; i < count; i++, s++) { | 954 | for (i = 0; i < count; i++, s++) { |
664 | /* Line return handling */ | 955 | /* Line return handling */ |
665 | if (*s == '\n') | 956 | if (*s == '\n') |
666 | out_8(&psc->mpc52xx_psc_buffer_8, '\r'); | 957 | psc_ops->write_char(port, '\r'); |
667 | 958 | ||
668 | /* Send the char */ | 959 | /* Send the char */ |
669 | out_8(&psc->mpc52xx_psc_buffer_8, *s); | 960 | psc_ops->write_char(port, *s); |
670 | 961 | ||
671 | /* Wait the TX buffer to be empty */ | 962 | /* Wait the TX buffer to be empty */ |
672 | j = 20000; /* Maximum wait */ | 963 | j = 20000; /* Maximum wait */ |
673 | while (!(in_be16(&psc->mpc52xx_psc_status) & | 964 | while (!mpc52xx_uart_tx_empty(port) && --j) |
674 | MPC52xx_PSC_SR_TXEMP) && --j) | ||
675 | udelay(1); | 965 | udelay(1); |
676 | } | 966 | } |
677 | 967 | ||
678 | /* Restore interrupt state */ | 968 | /* Restore interrupt state */ |
679 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | 969 | psc_ops->cw_restore_ints(port); |
680 | } | 970 | } |
681 | 971 | ||
682 | #if !defined(CONFIG_PPC_MERGE) | 972 | #if !defined(CONFIG_PPC_MERGE) |
@@ -721,7 +1011,7 @@ mpc52xx_console_setup(struct console *co, char *options) | |||
721 | { | 1011 | { |
722 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; | 1012 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; |
723 | struct device_node *np = mpc52xx_uart_nodes[co->index]; | 1013 | struct device_node *np = mpc52xx_uart_nodes[co->index]; |
724 | unsigned int ipb_freq; | 1014 | unsigned int uartclk; |
725 | struct resource res; | 1015 | struct resource res; |
726 | int ret; | 1016 | int ret; |
727 | 1017 | ||
@@ -753,17 +1043,16 @@ mpc52xx_console_setup(struct console *co, char *options) | |||
753 | return ret; | 1043 | return ret; |
754 | } | 1044 | } |
755 | 1045 | ||
756 | /* Search for bus-frequency property in this node or a parent */ | 1046 | uartclk = psc_ops->getuartclk(np); |
757 | ipb_freq = mpc52xx_find_ipb_freq(np); | 1047 | if (uartclk == 0) { |
758 | if (ipb_freq == 0) { | 1048 | pr_debug("Could not find uart clock frequency!\n"); |
759 | pr_debug("Could not find IPB bus frequency!\n"); | ||
760 | return -EINVAL; | 1049 | return -EINVAL; |
761 | } | 1050 | } |
762 | 1051 | ||
763 | /* Basic port init. Needed since we use some uart_??? func before | 1052 | /* Basic port init. Needed since we use some uart_??? func before |
764 | * real init for early access */ | 1053 | * real init for early access */ |
765 | spin_lock_init(&port->lock); | 1054 | spin_lock_init(&port->lock); |
766 | port->uartclk = ipb_freq / 2; | 1055 | port->uartclk = uartclk; |
767 | port->ops = &mpc52xx_uart_ops; | 1056 | port->ops = &mpc52xx_uart_ops; |
768 | port->mapbase = res.start; | 1057 | port->mapbase = res.start; |
769 | port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc)); | 1058 | port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc)); |
@@ -949,7 +1238,7 @@ static int __devinit | |||
949 | mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | 1238 | mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) |
950 | { | 1239 | { |
951 | int idx = -1; | 1240 | int idx = -1; |
952 | unsigned int ipb_freq; | 1241 | unsigned int uartclk; |
953 | struct uart_port *port = NULL; | 1242 | struct uart_port *port = NULL; |
954 | struct resource res; | 1243 | struct resource res; |
955 | int ret; | 1244 | int ret; |
@@ -965,10 +1254,9 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | |||
965 | pr_debug("Found %s assigned to ttyPSC%x\n", | 1254 | pr_debug("Found %s assigned to ttyPSC%x\n", |
966 | mpc52xx_uart_nodes[idx]->full_name, idx); | 1255 | mpc52xx_uart_nodes[idx]->full_name, idx); |
967 | 1256 | ||
968 | /* Search for bus-frequency property in this node or a parent */ | 1257 | uartclk = psc_ops->getuartclk(op->node); |
969 | ipb_freq = mpc52xx_find_ipb_freq(op->node); | 1258 | if (uartclk == 0) { |
970 | if (ipb_freq == 0) { | 1259 | dev_dbg(&op->dev, "Could not find uart clock frequency!\n"); |
971 | dev_dbg(&op->dev, "Could not find IPB bus frequency!\n"); | ||
972 | return -EINVAL; | 1260 | return -EINVAL; |
973 | } | 1261 | } |
974 | 1262 | ||
@@ -976,7 +1264,7 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | |||
976 | port = &mpc52xx_uart_ports[idx]; | 1264 | port = &mpc52xx_uart_ports[idx]; |
977 | 1265 | ||
978 | spin_lock_init(&port->lock); | 1266 | spin_lock_init(&port->lock); |
979 | port->uartclk = ipb_freq / 2; | 1267 | port->uartclk = uartclk; |
980 | port->fifosize = 512; | 1268 | port->fifosize = 512; |
981 | port->iotype = UPIO_MEM; | 1269 | port->iotype = UPIO_MEM; |
982 | port->flags = UPF_BOOT_AUTOCONF | | 1270 | port->flags = UPF_BOOT_AUTOCONF | |
@@ -1080,15 +1368,19 @@ mpc52xx_uart_of_enumerate(void) | |||
1080 | static int enum_done; | 1368 | static int enum_done; |
1081 | struct device_node *np; | 1369 | struct device_node *np; |
1082 | const unsigned int *devno; | 1370 | const unsigned int *devno; |
1371 | const struct of_device_id *match; | ||
1083 | int i; | 1372 | int i; |
1084 | 1373 | ||
1085 | if (enum_done) | 1374 | if (enum_done) |
1086 | return; | 1375 | return; |
1087 | 1376 | ||
1088 | for_each_node_by_type(np, "serial") { | 1377 | for_each_node_by_type(np, "serial") { |
1089 | if (!of_match_node(mpc52xx_uart_of_match, np)) | 1378 | match = of_match_node(mpc52xx_uart_of_match, np); |
1379 | if (!match) | ||
1090 | continue; | 1380 | continue; |
1091 | 1381 | ||
1382 | psc_ops = match->data; | ||
1383 | |||
1092 | /* Is a particular device number requested? */ | 1384 | /* Is a particular device number requested? */ |
1093 | devno = of_get_property(np, "port-number", NULL); | 1385 | devno = of_get_property(np, "port-number", NULL); |
1094 | mpc52xx_uart_of_assign(np, devno ? *devno : -1); | 1386 | mpc52xx_uart_of_assign(np, devno ? *devno : -1); |
@@ -1149,6 +1441,7 @@ mpc52xx_uart_init(void) | |||
1149 | return ret; | 1441 | return ret; |
1150 | } | 1442 | } |
1151 | #else | 1443 | #else |
1444 | psc_ops = &mpc52xx_psc_ops; | ||
1152 | ret = platform_driver_register(&mpc52xx_uart_platform_driver); | 1445 | ret = platform_driver_register(&mpc52xx_uart_platform_driver); |
1153 | if (ret) { | 1446 | if (ret) { |
1154 | printk(KERN_ERR "%s: platform_driver_register failed (%i)\n", | 1447 | printk(KERN_ERR "%s: platform_driver_register failed (%i)\n", |
diff --git a/include/asm-powerpc/mpc512x.h b/include/asm-powerpc/mpc512x.h new file mode 100644 index 000000000000..c48a1658eeac --- /dev/null +++ b/include/asm-powerpc/mpc512x.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * Author: John Rigby, <jrigby@freescale.com>, Friday Apr 13 2007 | ||
5 | * | ||
6 | * Description: | ||
7 | * MPC5121 Prototypes and definitions | ||
8 | * | ||
9 | * This is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #ifndef __ASM_POWERPC_MPC512x_H__ | ||
17 | #define __ASM_POWERPC_MPC512x_H__ | ||
18 | |||
19 | extern unsigned long mpc512x_find_ips_freq(struct device_node *node); | ||
20 | |||
21 | #endif /* __ASM_POWERPC_MPC512x_H__ */ | ||
22 | |||
diff --git a/include/asm-powerpc/mpc52xx_psc.h b/include/asm-powerpc/mpc52xx_psc.h index bea42b95390f..710c5d36efaa 100644 --- a/include/asm-powerpc/mpc52xx_psc.h +++ b/include/asm-powerpc/mpc52xx_psc.h | |||
@@ -190,5 +190,53 @@ struct mpc52xx_psc_fifo { | |||
190 | u16 tflwfptr; /* PSC + 0x9e */ | 190 | u16 tflwfptr; /* PSC + 0x9e */ |
191 | }; | 191 | }; |
192 | 192 | ||
193 | #define MPC512x_PSC_FIFO_RESET_SLICE 0x80 | ||
194 | #define MPC512x_PSC_FIFO_ENABLE_SLICE 0x01 | ||
195 | #define MPC512x_PSC_FIFO_ENABLE_DMA 0x04 | ||
196 | |||
197 | #define MPC512x_PSC_FIFO_EMPTY 0x1 | ||
198 | #define MPC512x_PSC_FIFO_FULL 0x2 | ||
199 | #define MPC512x_PSC_FIFO_ALARM 0x4 | ||
200 | #define MPC512x_PSC_FIFO_URERR 0x8 | ||
201 | #define MPC512x_PSC_FIFO_ORERR 0x01 | ||
202 | #define MPC512x_PSC_FIFO_MEMERROR 0x02 | ||
203 | |||
204 | struct mpc512x_psc_fifo { | ||
205 | u32 reserved1[10]; | ||
206 | u32 txcmd; /* PSC + 0x80 */ | ||
207 | u32 txalarm; /* PSC + 0x84 */ | ||
208 | u32 txsr; /* PSC + 0x88 */ | ||
209 | u32 txisr; /* PSC + 0x8c */ | ||
210 | u32 tximr; /* PSC + 0x90 */ | ||
211 | u32 txcnt; /* PSC + 0x94 */ | ||
212 | u32 txptr; /* PSC + 0x98 */ | ||
213 | u32 txsz; /* PSC + 0x9c */ | ||
214 | u32 reserved2[7]; | ||
215 | union { | ||
216 | u8 txdata_8; | ||
217 | u16 txdata_16; | ||
218 | u32 txdata_32; | ||
219 | } txdata; /* PSC + 0xbc */ | ||
220 | #define txdata_8 txdata.txdata_8 | ||
221 | #define txdata_16 txdata.txdata_16 | ||
222 | #define txdata_32 txdata.txdata_32 | ||
223 | u32 rxcmd; /* PSC + 0xc0 */ | ||
224 | u32 rxalarm; /* PSC + 0xc4 */ | ||
225 | u32 rxsr; /* PSC + 0xc8 */ | ||
226 | u32 rxisr; /* PSC + 0xcc */ | ||
227 | u32 rximr; /* PSC + 0xd0 */ | ||
228 | u32 rxcnt; /* PSC + 0xd4 */ | ||
229 | u32 rxptr; /* PSC + 0xd8 */ | ||
230 | u32 rxsz; /* PSC + 0xdc */ | ||
231 | u32 reserved3[7]; | ||
232 | union { | ||
233 | u8 rxdata_8; | ||
234 | u16 rxdata_16; | ||
235 | u32 rxdata_32; | ||
236 | } rxdata; /* PSC + 0xfc */ | ||
237 | #define rxdata_8 rxdata.rxdata_8 | ||
238 | #define rxdata_16 rxdata.rxdata_16 | ||
239 | #define rxdata_32 rxdata.rxdata_32 | ||
240 | }; | ||
193 | 241 | ||
194 | #endif /* __ASM_MPC52xx_PSC_H__ */ | 242 | #endif /* __ASM_MPC52xx_PSC_H__ */ |