diff options
author | Scott Wood <scottwood@freescale.com> | 2007-09-28 15:06:16 -0400 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2007-10-04 16:47:05 -0400 |
commit | 15f8c604a79c4840ed76eecf3af5d88b7c1dee9e (patch) | |
tree | d86815bc2daf835fee081ee7dac92cef8784f6a3 | |
parent | 3c5df5c26ed17828760945d59653a2e22e3fb63f (diff) |
[POWERPC] cpm: Describe multi-user ram in its own device node.
The way the current CPM binding describes available multi-user (a.k.a.
dual-ported) RAM doesn't work well when there are multiple free regions,
and it doesn't work at all if the region doesn't begin at the start of
the muram area (as the hardware needs to be programmed with offsets into
this area). The latter situation can happen with SMC UARTs on CPM2, as its
parameter RAM is relocatable, u-boot puts it at zero, and the kernel doesn't
support moving it.
It is now described with a muram node, similar to QE. The current CPM
binding is sufficiently recent (i.e. never appeared in an official release)
that compatibility with existing device trees is not an issue.
The code supporting the new binding is shared between cpm1 and cpm2, rather
than remain separated. QE should be able to use this code as well, once
minor fixes are made to its device trees.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
-rw-r--r-- | Documentation/powerpc/booting-without-of.txt | 40 | ||||
-rw-r--r-- | arch/powerpc/Kconfig.debug | 6 | ||||
-rw-r--r-- | arch/powerpc/boot/cpm-serial.c | 44 | ||||
-rw-r--r-- | arch/powerpc/boot/dts/ep88xc.dts | 13 | ||||
-rw-r--r-- | arch/powerpc/boot/dts/mpc8272ads.dts | 11 | ||||
-rw-r--r-- | arch/powerpc/boot/dts/mpc885ads.dts | 13 | ||||
-rw-r--r-- | arch/powerpc/boot/dts/pq2fads.dts | 13 | ||||
-rw-r--r-- | arch/powerpc/sysdev/commproc.c | 11 | ||||
-rw-r--r-- | arch/powerpc/sysdev/cpm2_common.c | 35 | ||||
-rw-r--r-- | arch/powerpc/sysdev/cpm_common.c | 159 | ||||
-rw-r--r-- | drivers/serial/cpm_uart/cpm_uart_cpm2.c | 4 | ||||
-rw-r--r-- | include/asm-powerpc/commproc.h | 12 | ||||
-rw-r--r-- | include/asm-powerpc/cpm.h | 14 | ||||
-rw-r--r-- | include/asm-powerpc/cpm2.h | 10 |
14 files changed, 337 insertions, 48 deletions
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index c36dcd2fbdc4..ce5d67f5cb5c 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt | |||
@@ -1861,9 +1861,7 @@ platforms are moved over to use the flattened-device-tree model. | |||
1861 | 1861 | ||
1862 | Properties: | 1862 | Properties: |
1863 | - compatible : "fsl,cpm1", "fsl,cpm2", or "fsl,qe". | 1863 | - compatible : "fsl,cpm1", "fsl,cpm2", or "fsl,qe". |
1864 | - reg : The first resource is a 48-byte region beginning with | 1864 | - reg : A 48-byte region beginning with CPCR. |
1865 | CPCR. The second is the available general-purpose | ||
1866 | DPRAM. | ||
1867 | 1865 | ||
1868 | Example: | 1866 | Example: |
1869 | cpm@119c0 { | 1867 | cpm@119c0 { |
@@ -1871,7 +1869,7 @@ platforms are moved over to use the flattened-device-tree model. | |||
1871 | #size-cells = <1>; | 1869 | #size-cells = <1>; |
1872 | #interrupt-cells = <2>; | 1870 | #interrupt-cells = <2>; |
1873 | compatible = "fsl,mpc8272-cpm", "fsl,cpm2"; | 1871 | compatible = "fsl,mpc8272-cpm", "fsl,cpm2"; |
1874 | reg = <119c0 30 0 2000>; | 1872 | reg = <119c0 30>; |
1875 | } | 1873 | } |
1876 | 1874 | ||
1877 | ii) Properties common to mulitple CPM/QE devices | 1875 | ii) Properties common to mulitple CPM/QE devices |
@@ -2017,6 +2015,40 @@ platforms are moved over to use the flattened-device-tree model. | |||
2017 | fsl,cpm-command = <2e600000>; | 2015 | fsl,cpm-command = <2e600000>; |
2018 | }; | 2016 | }; |
2019 | 2017 | ||
2018 | viii) Multi-User RAM (MURAM) | ||
2019 | |||
2020 | The multi-user/dual-ported RAM is expressed as a bus under the CPM node. | ||
2021 | |||
2022 | Ranges must be set up subject to the following restrictions: | ||
2023 | |||
2024 | - Children's reg nodes must be offsets from the start of all muram, even | ||
2025 | if the user-data area does not begin at zero. | ||
2026 | - If multiple range entries are used, the difference between the parent | ||
2027 | address and the child address must be the same in all, so that a single | ||
2028 | mapping can cover them all while maintaining the ability to determine | ||
2029 | CPM-side offsets with pointer subtraction. It is recommended that | ||
2030 | multiple range entries not be used. | ||
2031 | - A child address of zero must be translatable, even if no reg resources | ||
2032 | contain it. | ||
2033 | |||
2034 | A child "data" node must exist, compatible with "fsl,cpm-muram-data", to | ||
2035 | indicate the portion of muram that is usable by the OS for arbitrary | ||
2036 | purposes. The data node may have an arbitrary number of reg resources, | ||
2037 | all of which contribute to the allocatable muram pool. | ||
2038 | |||
2039 | Example, based on mpc8272: | ||
2040 | |||
2041 | muram@0 { | ||
2042 | #address-cells = <1>; | ||
2043 | #size-cells = <1>; | ||
2044 | ranges = <0 0 10000>; | ||
2045 | |||
2046 | data@0 { | ||
2047 | compatible = "fsl,cpm-muram-data"; | ||
2048 | reg = <0 2000 9800 800>; | ||
2049 | }; | ||
2050 | }; | ||
2051 | |||
2020 | m) Chipselect/Local Bus | 2052 | m) Chipselect/Local Bus |
2021 | 2053 | ||
2022 | Properties: | 2054 | Properties: |
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index f4e5d22312a0..464f9b4b3169 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug | |||
@@ -245,9 +245,9 @@ config PPC_EARLY_DEBUG_44x_PHYSHIGH | |||
245 | config PPC_EARLY_DEBUG_CPM_ADDR | 245 | config PPC_EARLY_DEBUG_CPM_ADDR |
246 | hex "CPM UART early debug transmit descriptor address" | 246 | hex "CPM UART early debug transmit descriptor address" |
247 | depends on PPC_EARLY_DEBUG_CPM | 247 | depends on PPC_EARLY_DEBUG_CPM |
248 | default "0xfa202808" if PPC_EP88XC | 248 | default "0xfa202008" if PPC_EP88XC |
249 | default "0xf0000808" if CPM2 | 249 | default "0xf0000008" if CPM2 |
250 | default "0xff002808" if CPM1 | 250 | default "0xff002008" if CPM1 |
251 | help | 251 | help |
252 | This specifies the address of the transmit descriptor | 252 | This specifies the address of the transmit descriptor |
253 | used for early debug output. Because it is needed before | 253 | used for early debug output. Because it is needed before |
diff --git a/arch/powerpc/boot/cpm-serial.c b/arch/powerpc/boot/cpm-serial.c index fcb8b5e956bd..28296facb2ae 100644 --- a/arch/powerpc/boot/cpm-serial.c +++ b/arch/powerpc/boot/cpm-serial.c | |||
@@ -56,7 +56,8 @@ static struct cpm_smc *smc; | |||
56 | static struct cpm_scc *scc; | 56 | static struct cpm_scc *scc; |
57 | struct cpm_bd *tbdf, *rbdf; | 57 | struct cpm_bd *tbdf, *rbdf; |
58 | static u32 cpm_cmd; | 58 | static u32 cpm_cmd; |
59 | static u8 *dpram_start; | 59 | static u8 *muram_start; |
60 | static u32 muram_offset; | ||
60 | 61 | ||
61 | static void (*do_cmd)(int op); | 62 | static void (*do_cmd)(int op); |
62 | static void (*enable_port)(void); | 63 | static void (*enable_port)(void); |
@@ -114,13 +115,12 @@ static void scc_enable_port(void) | |||
114 | 115 | ||
115 | static int cpm_serial_open(void) | 116 | static int cpm_serial_open(void) |
116 | { | 117 | { |
117 | int dpaddr = 0x800; | ||
118 | disable_port(); | 118 | disable_port(); |
119 | 119 | ||
120 | out_8(¶m->rfcr, 0x10); | 120 | out_8(¶m->rfcr, 0x10); |
121 | out_8(¶m->tfcr, 0x10); | 121 | out_8(¶m->tfcr, 0x10); |
122 | 122 | ||
123 | rbdf = (struct cpm_bd *)(dpram_start + dpaddr); | 123 | rbdf = (struct cpm_bd *)muram_start; |
124 | rbdf->addr = (u8 *)(rbdf + 2); | 124 | rbdf->addr = (u8 *)(rbdf + 2); |
125 | rbdf->sc = 0xa000; | 125 | rbdf->sc = 0xa000; |
126 | rbdf->len = 1; | 126 | rbdf->len = 1; |
@@ -131,8 +131,8 @@ static int cpm_serial_open(void) | |||
131 | tbdf->len = 1; | 131 | tbdf->len = 1; |
132 | 132 | ||
133 | sync(); | 133 | sync(); |
134 | out_be16(¶m->rbase, dpaddr); | 134 | out_be16(¶m->rbase, muram_offset); |
135 | out_be16(¶m->tbase, dpaddr + sizeof(struct cpm_bd)); | 135 | out_be16(¶m->tbase, muram_offset + sizeof(struct cpm_bd)); |
136 | 136 | ||
137 | do_cmd(CPM_CMD_INIT_RX_TX); | 137 | do_cmd(CPM_CMD_INIT_RX_TX); |
138 | 138 | ||
@@ -178,7 +178,7 @@ int cpm_console_init(void *devp, struct serial_console_data *scdp) | |||
178 | void *reg_virt[2]; | 178 | void *reg_virt[2]; |
179 | int is_smc = 0, is_cpm2 = 0, n; | 179 | int is_smc = 0, is_cpm2 = 0, n; |
180 | unsigned long reg_phys; | 180 | unsigned long reg_phys; |
181 | void *parent; | 181 | void *parent, *muram; |
182 | 182 | ||
183 | if (dt_is_compatible(devp, "fsl,cpm1-smc-uart")) { | 183 | if (dt_is_compatible(devp, "fsl,cpm1-smc-uart")) { |
184 | is_smc = 1; | 184 | is_smc = 1; |
@@ -229,16 +229,36 @@ int cpm_console_init(void *devp, struct serial_console_data *scdp) | |||
229 | 229 | ||
230 | n = getprop(parent, "virtual-reg", reg_virt, sizeof(reg_virt)); | 230 | n = getprop(parent, "virtual-reg", reg_virt, sizeof(reg_virt)); |
231 | if (n < (int)sizeof(reg_virt)) { | 231 | if (n < (int)sizeof(reg_virt)) { |
232 | for (n = 0; n < 2; n++) { | 232 | if (!dt_xlate_reg(parent, 0, ®_phys, NULL)) |
233 | if (!dt_xlate_reg(parent, n, ®_phys, NULL)) | 233 | return -1; |
234 | return -1; | ||
235 | 234 | ||
236 | reg_virt[n] = (void *)reg_phys; | 235 | reg_virt[0] = (void *)reg_phys; |
237 | } | ||
238 | } | 236 | } |
239 | 237 | ||
240 | cpcr = reg_virt[0]; | 238 | cpcr = reg_virt[0]; |
241 | dpram_start = reg_virt[1]; | 239 | |
240 | muram = finddevice("/soc/cpm/muram/data"); | ||
241 | if (!muram) | ||
242 | return -1; | ||
243 | |||
244 | /* For bootwrapper-compatible device trees, we assume that the first | ||
245 | * entry has at least 18 bytes, and that #address-cells/#data-cells | ||
246 | * is one for both parent and child. | ||
247 | */ | ||
248 | |||
249 | n = getprop(muram, "virtual-reg", reg_virt, sizeof(reg_virt)); | ||
250 | if (n < (int)sizeof(reg_virt)) { | ||
251 | if (!dt_xlate_reg(muram, 0, ®_phys, NULL)) | ||
252 | return -1; | ||
253 | |||
254 | reg_virt[0] = (void *)reg_phys; | ||
255 | } | ||
256 | |||
257 | muram_start = reg_virt[0]; | ||
258 | |||
259 | n = getprop(muram, "reg", &muram_offset, 4); | ||
260 | if (n < 4) | ||
261 | return -1; | ||
242 | 262 | ||
243 | scdp->open = cpm_serial_open; | 263 | scdp->open = cpm_serial_open; |
244 | scdp->putc = cpm_serial_putc; | 264 | scdp->putc = cpm_serial_putc; |
diff --git a/arch/powerpc/boot/dts/ep88xc.dts b/arch/powerpc/boot/dts/ep88xc.dts index 0406fc50b2af..02705f299790 100644 --- a/arch/powerpc/boot/dts/ep88xc.dts +++ b/arch/powerpc/boot/dts/ep88xc.dts | |||
@@ -142,9 +142,20 @@ | |||
142 | command-proc = <9c0>; | 142 | command-proc = <9c0>; |
143 | interrupts = <0>; // cpm error interrupt | 143 | interrupts = <0>; // cpm error interrupt |
144 | interrupt-parent = <&CPM_PIC>; | 144 | interrupt-parent = <&CPM_PIC>; |
145 | reg = <9c0 40 2000 1c00>; | 145 | reg = <9c0 40>; |
146 | ranges; | 146 | ranges; |
147 | 147 | ||
148 | muram@2000 { | ||
149 | #address-cells = <1>; | ||
150 | #size-cells = <1>; | ||
151 | ranges = <0 2000 2000>; | ||
152 | |||
153 | data@0 { | ||
154 | compatible = "fsl,cpm-muram-data"; | ||
155 | reg = <0 1c00>; | ||
156 | }; | ||
157 | }; | ||
158 | |||
148 | brg@9f0 { | 159 | brg@9f0 { |
149 | compatible = "fsl,mpc885-brg", | 160 | compatible = "fsl,mpc885-brg", |
150 | "fsl,cpm1-brg", | 161 | "fsl,cpm1-brg", |
diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts b/arch/powerpc/boot/dts/mpc8272ads.dts index 3fe991d4cb03..188179df0845 100644 --- a/arch/powerpc/boot/dts/mpc8272ads.dts +++ b/arch/powerpc/boot/dts/mpc8272ads.dts | |||
@@ -124,6 +124,17 @@ | |||
124 | reg = <119c0 30 0 2000>; | 124 | reg = <119c0 30 0 2000>; |
125 | ranges; | 125 | ranges; |
126 | 126 | ||
127 | muram@0 { | ||
128 | #address-cells = <1>; | ||
129 | #size-cells = <1>; | ||
130 | ranges = <0 0 10000>; | ||
131 | |||
132 | data@0 { | ||
133 | compatible = "fsl,cpm-muram-data"; | ||
134 | reg = <0 2000 9800 800>; | ||
135 | }; | ||
136 | }; | ||
137 | |||
127 | brg@119f0 { | 138 | brg@119f0 { |
128 | compatible = "fsl,mpc8272-brg", | 139 | compatible = "fsl,mpc8272-brg", |
129 | "fsl,cpm2-brg", | 140 | "fsl,cpm2-brg", |
diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts index cbcd16f74c45..8848e637293e 100644 --- a/arch/powerpc/boot/dts/mpc885ads.dts +++ b/arch/powerpc/boot/dts/mpc885ads.dts | |||
@@ -148,9 +148,20 @@ | |||
148 | command-proc = <9c0>; | 148 | command-proc = <9c0>; |
149 | interrupts = <0>; // cpm error interrupt | 149 | interrupts = <0>; // cpm error interrupt |
150 | interrupt-parent = <&CPM_PIC>; | 150 | interrupt-parent = <&CPM_PIC>; |
151 | reg = <9c0 40 2000 1c00>; | 151 | reg = <9c0 40>; |
152 | ranges; | 152 | ranges; |
153 | 153 | ||
154 | muram@2000 { | ||
155 | #address-cells = <1>; | ||
156 | #size-cells = <1>; | ||
157 | ranges = <0 2000 2000>; | ||
158 | |||
159 | data@0 { | ||
160 | compatible = "fsl,cpm-muram-data"; | ||
161 | reg = <0 1c00>; | ||
162 | }; | ||
163 | }; | ||
164 | |||
154 | brg@9f0 { | 165 | brg@9f0 { |
155 | compatible = "fsl,mpc885-brg", | 166 | compatible = "fsl,mpc885-brg", |
156 | "fsl,cpm1-brg", | 167 | "fsl,cpm1-brg", |
diff --git a/arch/powerpc/boot/dts/pq2fads.dts b/arch/powerpc/boot/dts/pq2fads.dts index 54e8bd1ae22f..2d564921897a 100644 --- a/arch/powerpc/boot/dts/pq2fads.dts +++ b/arch/powerpc/boot/dts/pq2fads.dts | |||
@@ -119,9 +119,20 @@ | |||
119 | #size-cells = <1>; | 119 | #size-cells = <1>; |
120 | #interrupt-cells = <2>; | 120 | #interrupt-cells = <2>; |
121 | compatible = "fsl,mpc8280-cpm", "fsl,cpm2"; | 121 | compatible = "fsl,mpc8280-cpm", "fsl,cpm2"; |
122 | reg = <119c0 30 0 2000>; | 122 | reg = <119c0 30>; |
123 | ranges; | 123 | ranges; |
124 | 124 | ||
125 | muram@0 { | ||
126 | #address-cells = <1>; | ||
127 | #size-cells = <1>; | ||
128 | ranges = <0 0 10000>; | ||
129 | |||
130 | data@0 { | ||
131 | compatible = "fsl,cpm-muram-data"; | ||
132 | reg = <0 2000 9800 800>; | ||
133 | }; | ||
134 | }; | ||
135 | |||
125 | brg@119f0 { | 136 | brg@119f0 { |
126 | compatible = "fsl,mpc8280-brg", | 137 | compatible = "fsl,mpc8280-brg", |
127 | "fsl,cpm2-brg", | 138 | "fsl,cpm2-brg", |
diff --git a/arch/powerpc/sysdev/commproc.c b/arch/powerpc/sysdev/commproc.c index 428eb8c151b9..f6a63780bbde 100644 --- a/arch/powerpc/sysdev/commproc.c +++ b/arch/powerpc/sysdev/commproc.c | |||
@@ -39,12 +39,15 @@ | |||
39 | #include <asm/tlbflush.h> | 39 | #include <asm/tlbflush.h> |
40 | #include <asm/rheap.h> | 40 | #include <asm/rheap.h> |
41 | #include <asm/prom.h> | 41 | #include <asm/prom.h> |
42 | #include <asm/cpm.h> | ||
42 | 43 | ||
43 | #include <asm/fs_pd.h> | 44 | #include <asm/fs_pd.h> |
44 | 45 | ||
45 | #define CPM_MAP_SIZE (0x4000) | 46 | #define CPM_MAP_SIZE (0x4000) |
46 | 47 | ||
48 | #ifndef CONFIG_PPC_CPM_NEW_BINDING | ||
47 | static void m8xx_cpm_dpinit(void); | 49 | static void m8xx_cpm_dpinit(void); |
50 | #endif | ||
48 | static uint host_buffer; /* One page of host buffer */ | 51 | static uint host_buffer; /* One page of host buffer */ |
49 | static uint host_end; /* end + 1 */ | 52 | static uint host_end; /* end + 1 */ |
50 | cpm8xx_t __iomem *cpmp; /* Pointer to comm processor space */ | 53 | cpm8xx_t __iomem *cpmp; /* Pointer to comm processor space */ |
@@ -193,7 +196,7 @@ end: | |||
193 | return sirq; | 196 | return sirq; |
194 | } | 197 | } |
195 | 198 | ||
196 | void cpm_reset(void) | 199 | void __init cpm_reset(void) |
197 | { | 200 | { |
198 | sysconf8xx_t __iomem *siu_conf; | 201 | sysconf8xx_t __iomem *siu_conf; |
199 | 202 | ||
@@ -229,8 +232,12 @@ void cpm_reset(void) | |||
229 | out_be32(&siu_conf->sc_sdcr, 1); | 232 | out_be32(&siu_conf->sc_sdcr, 1); |
230 | immr_unmap(siu_conf); | 233 | immr_unmap(siu_conf); |
231 | 234 | ||
235 | #ifdef CONFIG_PPC_CPM_NEW_BINDING | ||
236 | cpm_muram_init(); | ||
237 | #else | ||
232 | /* Reclaim the DP memory for our use. */ | 238 | /* Reclaim the DP memory for our use. */ |
233 | m8xx_cpm_dpinit(); | 239 | m8xx_cpm_dpinit(); |
240 | #endif | ||
234 | } | 241 | } |
235 | 242 | ||
236 | /* We used to do this earlier, but have to postpone as long as possible | 243 | /* We used to do this earlier, but have to postpone as long as possible |
@@ -296,6 +303,7 @@ cpm_setbrg(uint brg, uint rate) | |||
296 | CPM_BRG_EN | CPM_BRG_DIV16); | 303 | CPM_BRG_EN | CPM_BRG_DIV16); |
297 | } | 304 | } |
298 | 305 | ||
306 | #ifndef CONFIG_PPC_CPM_NEW_BINDING | ||
299 | /* | 307 | /* |
300 | * dpalloc / dpfree bits. | 308 | * dpalloc / dpfree bits. |
301 | */ | 309 | */ |
@@ -397,6 +405,7 @@ uint cpm_dpram_phys(u8 *addr) | |||
397 | return (dpram_pbase + (uint)(addr - dpram_vbase)); | 405 | return (dpram_pbase + (uint)(addr - dpram_vbase)); |
398 | } | 406 | } |
399 | EXPORT_SYMBOL(cpm_dpram_phys); | 407 | EXPORT_SYMBOL(cpm_dpram_phys); |
408 | #endif /* !CONFIG_PPC_CPM_NEW_BINDING */ | ||
400 | 409 | ||
401 | struct cpm_ioport16 { | 410 | struct cpm_ioport16 { |
402 | __be16 dir, par, sor, dat, intr; | 411 | __be16 dir, par, sor, dat, intr; |
diff --git a/arch/powerpc/sysdev/cpm2_common.c b/arch/powerpc/sysdev/cpm2_common.c index fc4c99565381..859362fecb7c 100644 --- a/arch/powerpc/sysdev/cpm2_common.c +++ b/arch/powerpc/sysdev/cpm2_common.c | |||
@@ -46,7 +46,10 @@ | |||
46 | 46 | ||
47 | #include <sysdev/fsl_soc.h> | 47 | #include <sysdev/fsl_soc.h> |
48 | 48 | ||
49 | #ifndef CONFIG_PPC_CPM_NEW_BINDING | ||
49 | static void cpm2_dpinit(void); | 50 | static void cpm2_dpinit(void); |
51 | #endif | ||
52 | |||
50 | cpm_cpm2_t __iomem *cpmp; /* Pointer to comm processor space */ | 53 | cpm_cpm2_t __iomem *cpmp; /* Pointer to comm processor space */ |
51 | 54 | ||
52 | /* We allocate this here because it is used almost exclusively for | 55 | /* We allocate this here because it is used almost exclusively for |
@@ -69,7 +72,11 @@ cpm2_reset(void) | |||
69 | 72 | ||
70 | /* Reclaim the DP memory for our use. | 73 | /* Reclaim the DP memory for our use. |
71 | */ | 74 | */ |
75 | #ifdef CONFIG_PPC_CPM_NEW_BINDING | ||
76 | cpm_muram_init(); | ||
77 | #else | ||
72 | cpm2_dpinit(); | 78 | cpm2_dpinit(); |
79 | #endif | ||
73 | 80 | ||
74 | /* Tell everyone where the comm processor resides. | 81 | /* Tell everyone where the comm processor resides. |
75 | */ | 82 | */ |
@@ -316,6 +323,7 @@ int cpm2_smc_clk_setup(enum cpm_clk_target target, int clock) | |||
316 | return ret; | 323 | return ret; |
317 | } | 324 | } |
318 | 325 | ||
326 | #ifndef CONFIG_PPC_CPM_NEW_BINDING | ||
319 | /* | 327 | /* |
320 | * dpalloc / dpfree bits. | 328 | * dpalloc / dpfree bits. |
321 | */ | 329 | */ |
@@ -328,28 +336,6 @@ static u8 __iomem *im_dprambase; | |||
328 | 336 | ||
329 | static void cpm2_dpinit(void) | 337 | static void cpm2_dpinit(void) |
330 | { | 338 | { |
331 | struct resource r; | ||
332 | |||
333 | #ifdef CONFIG_PPC_CPM_NEW_BINDING | ||
334 | struct device_node *np; | ||
335 | |||
336 | np = of_find_compatible_node(NULL, NULL, "fsl,cpm2"); | ||
337 | if (!np) | ||
338 | panic("Cannot find CPM2 node"); | ||
339 | |||
340 | if (of_address_to_resource(np, 1, &r)) | ||
341 | panic("Cannot get CPM2 resource 1"); | ||
342 | |||
343 | of_node_put(np); | ||
344 | #else | ||
345 | r.start = CPM_MAP_ADDR; | ||
346 | r.end = r.start + CPM_DATAONLY_BASE + CPM_DATAONLY_SIZE - 1; | ||
347 | #endif | ||
348 | |||
349 | im_dprambase = ioremap(r.start, r.end - r.start + 1); | ||
350 | if (!im_dprambase) | ||
351 | panic("Cannot map DPRAM"); | ||
352 | |||
353 | spin_lock_init(&cpm_dpmem_lock); | 339 | spin_lock_init(&cpm_dpmem_lock); |
354 | 340 | ||
355 | /* initialize the info header */ | 341 | /* initialize the info header */ |
@@ -358,13 +344,15 @@ static void cpm2_dpinit(void) | |||
358 | sizeof(cpm_boot_dpmem_rh_block[0]), | 344 | sizeof(cpm_boot_dpmem_rh_block[0]), |
359 | cpm_boot_dpmem_rh_block); | 345 | cpm_boot_dpmem_rh_block); |
360 | 346 | ||
347 | im_dprambase = cpm2_immr; | ||
348 | |||
361 | /* Attach the usable dpmem area */ | 349 | /* Attach the usable dpmem area */ |
362 | /* XXX: This is actually crap. CPM_DATAONLY_BASE and | 350 | /* XXX: This is actually crap. CPM_DATAONLY_BASE and |
363 | * CPM_DATAONLY_SIZE is only a subset of the available dpram. It | 351 | * CPM_DATAONLY_SIZE is only a subset of the available dpram. It |
364 | * varies with the processor and the microcode patches activated. | 352 | * varies with the processor and the microcode patches activated. |
365 | * But the following should be at least safe. | 353 | * But the following should be at least safe. |
366 | */ | 354 | */ |
367 | rh_attach_region(&cpm_dpmem_info, 0, r.end - r.start + 1); | 355 | rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE); |
368 | } | 356 | } |
369 | 357 | ||
370 | /* This function returns an index into the DPRAM area. | 358 | /* This function returns an index into the DPRAM area. |
@@ -422,6 +410,7 @@ void *cpm_dpram_addr(unsigned long offset) | |||
422 | return (void *)(im_dprambase + offset); | 410 | return (void *)(im_dprambase + offset); |
423 | } | 411 | } |
424 | EXPORT_SYMBOL(cpm_dpram_addr); | 412 | EXPORT_SYMBOL(cpm_dpram_addr); |
413 | #endif /* !CONFIG_PPC_CPM_NEW_BINDING */ | ||
425 | 414 | ||
426 | struct cpm2_ioports { | 415 | struct cpm2_ioports { |
427 | u32 dir, par, sor, odr, dat; | 416 | u32 dir, par, sor, odr, dat; |
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c index 9daa6ac67676..66c8ad4cfce6 100644 --- a/arch/powerpc/sysdev/cpm_common.c +++ b/arch/powerpc/sysdev/cpm_common.c | |||
@@ -5,15 +5,27 @@ | |||
5 | * | 5 | * |
6 | * Copyright 2007 Freescale Semiconductor, Inc. | 6 | * Copyright 2007 Freescale Semiconductor, Inc. |
7 | * | 7 | * |
8 | * Some parts derived from commproc.c/cpm2_common.c, which is: | ||
9 | * Copyright (c) 1997 Dan error_act (dmalek@jlc.net) | ||
10 | * Copyright (c) 1999-2001 Dan Malek <dan@embeddedalley.com> | ||
11 | * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com) | ||
12 | * 2006 (c) MontaVista Software, Inc. | ||
13 | * Vitaly Bordug <vbordug@ru.mvista.com> | ||
14 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | 15 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of version 2 of the GNU General Public License as | 16 | * it under the terms of version 2 of the GNU General Public License as |
10 | * published by the Free Software Foundation. | 17 | * published by the Free Software Foundation. |
11 | */ | 18 | */ |
12 | 19 | ||
13 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/of_device.h> | ||
22 | |||
14 | #include <asm/udbg.h> | 23 | #include <asm/udbg.h> |
15 | #include <asm/io.h> | 24 | #include <asm/io.h> |
16 | #include <asm/system.h> | 25 | #include <asm/system.h> |
26 | #include <asm/rheap.h> | ||
27 | #include <asm/cpm.h> | ||
28 | |||
17 | #include <mm/mmu_decl.h> | 29 | #include <mm/mmu_decl.h> |
18 | 30 | ||
19 | #ifdef CONFIG_PPC_EARLY_DEBUG_CPM | 31 | #ifdef CONFIG_PPC_EARLY_DEBUG_CPM |
@@ -41,6 +53,153 @@ void __init udbg_init_cpm(void) | |||
41 | setbat(1, 0xf0000000, 0xf0000000, 1024*1024, _PAGE_IO); | 53 | setbat(1, 0xf0000000, 0xf0000000, 1024*1024, _PAGE_IO); |
42 | #endif | 54 | #endif |
43 | udbg_putc = udbg_putc_cpm; | 55 | udbg_putc = udbg_putc_cpm; |
56 | udbg_putc('X'); | ||
44 | } | 57 | } |
45 | } | 58 | } |
46 | #endif | 59 | #endif |
60 | |||
61 | #ifdef CONFIG_PPC_CPM_NEW_BINDING | ||
62 | static spinlock_t cpm_muram_lock; | ||
63 | static rh_block_t cpm_boot_muram_rh_block[16]; | ||
64 | static rh_info_t cpm_muram_info; | ||
65 | static u8 __iomem *muram_vbase; | ||
66 | static phys_addr_t muram_pbase; | ||
67 | |||
68 | /* Max address size we deal with */ | ||
69 | #define OF_MAX_ADDR_CELLS 4 | ||
70 | |||
71 | int __init cpm_muram_init(void) | ||
72 | { | ||
73 | struct device_node *np; | ||
74 | struct resource r; | ||
75 | u32 zero[OF_MAX_ADDR_CELLS] = {}; | ||
76 | resource_size_t max = 0; | ||
77 | int i = 0; | ||
78 | int ret = 0; | ||
79 | |||
80 | printk("cpm_muram_init\n"); | ||
81 | |||
82 | spin_lock_init(&cpm_muram_lock); | ||
83 | /* initialize the info header */ | ||
84 | rh_init(&cpm_muram_info, 1, | ||
85 | sizeof(cpm_boot_muram_rh_block) / | ||
86 | sizeof(cpm_boot_muram_rh_block[0]), | ||
87 | cpm_boot_muram_rh_block); | ||
88 | |||
89 | np = of_find_compatible_node(NULL, NULL, "fsl,cpm-muram-data"); | ||
90 | if (!np) { | ||
91 | printk(KERN_ERR "Cannot find CPM muram data node"); | ||
92 | ret = -ENODEV; | ||
93 | goto out; | ||
94 | } | ||
95 | |||
96 | muram_pbase = of_translate_address(np, zero); | ||
97 | if (muram_pbase == (phys_addr_t)OF_BAD_ADDR) { | ||
98 | printk(KERN_ERR "Cannot translate zero through CPM muram node"); | ||
99 | ret = -ENODEV; | ||
100 | goto out; | ||
101 | } | ||
102 | |||
103 | while (of_address_to_resource(np, i++, &r) == 0) { | ||
104 | if (r.end > max) | ||
105 | max = r.end; | ||
106 | |||
107 | rh_attach_region(&cpm_muram_info, r.start - muram_pbase, | ||
108 | r.end - r.start + 1); | ||
109 | } | ||
110 | |||
111 | muram_vbase = ioremap(muram_pbase, max - muram_pbase + 1); | ||
112 | if (!muram_vbase) { | ||
113 | printk(KERN_ERR "Cannot map CPM muram"); | ||
114 | ret = -ENOMEM; | ||
115 | } | ||
116 | |||
117 | out: | ||
118 | of_node_put(np); | ||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * cpm_muram_alloc - allocate the requested size worth of multi-user ram | ||
124 | * @size: number of bytes to allocate | ||
125 | * @align: requested alignment, in bytes | ||
126 | * | ||
127 | * This function returns an offset into the muram area. | ||
128 | * Use cpm_dpram_addr() to get the virtual address of the area. | ||
129 | * Use cpm_muram_free() to free the allocation. | ||
130 | */ | ||
131 | unsigned long cpm_muram_alloc(unsigned long size, unsigned long align) | ||
132 | { | ||
133 | unsigned long start; | ||
134 | unsigned long flags; | ||
135 | |||
136 | spin_lock_irqsave(&cpm_muram_lock, flags); | ||
137 | cpm_muram_info.alignment = align; | ||
138 | start = rh_alloc(&cpm_muram_info, size, "commproc"); | ||
139 | spin_unlock_irqrestore(&cpm_muram_lock, flags); | ||
140 | |||
141 | return start; | ||
142 | } | ||
143 | EXPORT_SYMBOL(cpm_muram_alloc); | ||
144 | |||
145 | /** | ||
146 | * cpm_muram_free - free a chunk of multi-user ram | ||
147 | * @offset: The beginning of the chunk as returned by cpm_muram_alloc(). | ||
148 | */ | ||
149 | int cpm_muram_free(unsigned long offset) | ||
150 | { | ||
151 | int ret; | ||
152 | unsigned long flags; | ||
153 | |||
154 | spin_lock_irqsave(&cpm_muram_lock, flags); | ||
155 | ret = rh_free(&cpm_muram_info, offset); | ||
156 | spin_unlock_irqrestore(&cpm_muram_lock, flags); | ||
157 | |||
158 | return ret; | ||
159 | } | ||
160 | EXPORT_SYMBOL(cpm_muram_free); | ||
161 | |||
162 | /** | ||
163 | * cpm_muram_alloc_fixed - reserve a specific region of multi-user ram | ||
164 | * @offset: the offset into the muram area to reserve | ||
165 | * @size: the number of bytes to reserve | ||
166 | * | ||
167 | * This function returns "start" on success, -ENOMEM on failure. | ||
168 | * Use cpm_dpram_addr() to get the virtual address of the area. | ||
169 | * Use cpm_muram_free() to free the allocation. | ||
170 | */ | ||
171 | unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size) | ||
172 | { | ||
173 | unsigned long start; | ||
174 | unsigned long flags; | ||
175 | |||
176 | spin_lock_irqsave(&cpm_muram_lock, flags); | ||
177 | cpm_muram_info.alignment = 1; | ||
178 | start = rh_alloc_fixed(&cpm_muram_info, offset, size, "commproc"); | ||
179 | spin_unlock_irqrestore(&cpm_muram_lock, flags); | ||
180 | |||
181 | return start; | ||
182 | } | ||
183 | EXPORT_SYMBOL(cpm_muram_alloc_fixed); | ||
184 | |||
185 | /** | ||
186 | * cpm_muram_addr - turn a muram offset into a virtual address | ||
187 | * @offset: muram offset to convert | ||
188 | */ | ||
189 | void __iomem *cpm_muram_addr(unsigned long offset) | ||
190 | { | ||
191 | return muram_vbase + offset; | ||
192 | } | ||
193 | EXPORT_SYMBOL(cpm_muram_addr); | ||
194 | |||
195 | /** | ||
196 | * cpm_muram_phys - turn a muram virtual address into a DMA address | ||
197 | * @offset: virtual address from cpm_muram_addr() to convert | ||
198 | */ | ||
199 | dma_addr_t cpm_muram_dma(void __iomem *addr) | ||
200 | { | ||
201 | return muram_pbase + ((u8 __iomem *)addr - muram_vbase); | ||
202 | } | ||
203 | EXPORT_SYMBOL(cpm_muram_dma); | ||
204 | |||
205 | #endif /* CONFIG_PPC_CPM_NEW_BINDING */ | ||
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index 5bd4508ce3c1..882dbc17d590 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c | |||
@@ -235,7 +235,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo) | |||
235 | int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) | 235 | int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) |
236 | { | 236 | { |
237 | int dpmemsz, memsz; | 237 | int dpmemsz, memsz; |
238 | u8 *dp_mem; | 238 | u8 __iomem *dp_mem; |
239 | unsigned long dp_offset; | 239 | unsigned long dp_offset; |
240 | u8 *mem_addr; | 240 | u8 *mem_addr; |
241 | dma_addr_t dma_addr = 0; | 241 | dma_addr_t dma_addr = 0; |
@@ -278,7 +278,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) | |||
278 | pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos | 278 | pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos |
279 | * pinfo->rx_fifosize); | 279 | * pinfo->rx_fifosize); |
280 | 280 | ||
281 | pinfo->rx_bd_base = (cbd_t __iomem __force *)dp_mem; | 281 | pinfo->rx_bd_base = (cbd_t __iomem *)dp_mem; |
282 | pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos; | 282 | pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos; |
283 | 283 | ||
284 | return 0; | 284 | return 0; |
diff --git a/include/asm-powerpc/commproc.h b/include/asm-powerpc/commproc.h index 5dec32404fa2..0307c84a5c1d 100644 --- a/include/asm-powerpc/commproc.h +++ b/include/asm-powerpc/commproc.h | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <asm/8xx_immap.h> | 20 | #include <asm/8xx_immap.h> |
21 | #include <asm/ptrace.h> | 21 | #include <asm/ptrace.h> |
22 | #include <asm/cpm.h> | ||
22 | 23 | ||
23 | /* CPM Command register. | 24 | /* CPM Command register. |
24 | */ | 25 | */ |
@@ -54,6 +55,7 @@ | |||
54 | 55 | ||
55 | #define mk_cr_cmd(CH, CMD) ((CMD << 8) | (CH << 4)) | 56 | #define mk_cr_cmd(CH, CMD) ((CMD << 8) | (CH << 4)) |
56 | 57 | ||
58 | #ifndef CONFIG_PPC_CPM_NEW_BINDING | ||
57 | /* The dual ported RAM is multi-functional. Some areas can be (and are | 59 | /* The dual ported RAM is multi-functional. Some areas can be (and are |
58 | * being) used for microcode. There is an area that can only be used | 60 | * being) used for microcode. There is an area that can only be used |
59 | * as data ram for buffer descriptors, which is all we use right now. | 61 | * as data ram for buffer descriptors, which is all we use right now. |
@@ -62,17 +64,27 @@ | |||
62 | #define CPM_DATAONLY_BASE ((uint)0x0800) | 64 | #define CPM_DATAONLY_BASE ((uint)0x0800) |
63 | #define CPM_DATAONLY_SIZE ((uint)0x0700) | 65 | #define CPM_DATAONLY_SIZE ((uint)0x0700) |
64 | #define CPM_DP_NOSPACE ((uint)0x7fffffff) | 66 | #define CPM_DP_NOSPACE ((uint)0x7fffffff) |
67 | #endif | ||
65 | 68 | ||
66 | /* Export the base address of the communication processor registers | 69 | /* Export the base address of the communication processor registers |
67 | * and dual port ram. | 70 | * and dual port ram. |
68 | */ | 71 | */ |
69 | extern cpm8xx_t __iomem *cpmp; /* Pointer to comm processor */ | 72 | extern cpm8xx_t __iomem *cpmp; /* Pointer to comm processor */ |
73 | |||
74 | #ifdef CONFIG_PPC_CPM_NEW_BINDING | ||
75 | #define cpm_dpalloc cpm_muram_alloc | ||
76 | #define cpm_dpfree cpm_muram_free | ||
77 | #define cpm_dpram_addr cpm_muram_addr | ||
78 | #define cpm_dpram_phys cpm_muram_dma | ||
79 | #else | ||
70 | extern unsigned long cpm_dpalloc(uint size, uint align); | 80 | extern unsigned long cpm_dpalloc(uint size, uint align); |
71 | extern int cpm_dpfree(unsigned long offset); | 81 | extern int cpm_dpfree(unsigned long offset); |
72 | extern unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align); | 82 | extern unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align); |
73 | extern void cpm_dpdump(void); | 83 | extern void cpm_dpdump(void); |
74 | extern void *cpm_dpram_addr(unsigned long offset); | 84 | extern void *cpm_dpram_addr(unsigned long offset); |
75 | extern uint cpm_dpram_phys(u8* addr); | 85 | extern uint cpm_dpram_phys(u8* addr); |
86 | #endif | ||
87 | |||
76 | extern void cpm_setbrg(uint brg, uint rate); | 88 | extern void cpm_setbrg(uint brg, uint rate); |
77 | 89 | ||
78 | extern uint m8xx_cpm_hostalloc(uint size); | 90 | extern uint m8xx_cpm_hostalloc(uint size); |
diff --git a/include/asm-powerpc/cpm.h b/include/asm-powerpc/cpm.h new file mode 100644 index 000000000000..48df9f330e76 --- /dev/null +++ b/include/asm-powerpc/cpm.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef __CPM_H | ||
2 | #define __CPM_H | ||
3 | |||
4 | #include <linux/compiler.h> | ||
5 | #include <linux/types.h> | ||
6 | |||
7 | int cpm_muram_init(void); | ||
8 | unsigned long cpm_muram_alloc(unsigned long size, unsigned long align); | ||
9 | int cpm_muram_free(unsigned long offset); | ||
10 | unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size); | ||
11 | void __iomem *cpm_muram_addr(unsigned long offset); | ||
12 | dma_addr_t cpm_muram_dma(void __iomem *addr); | ||
13 | |||
14 | #endif | ||
diff --git a/include/asm-powerpc/cpm2.h b/include/asm-powerpc/cpm2.h index d7b57ac55892..e698b1d09dcf 100644 --- a/include/asm-powerpc/cpm2.h +++ b/include/asm-powerpc/cpm2.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #define __CPM2__ | 11 | #define __CPM2__ |
12 | 12 | ||
13 | #include <asm/immap_cpm2.h> | 13 | #include <asm/immap_cpm2.h> |
14 | #include <asm/cpm.h> | ||
14 | 15 | ||
15 | /* CPM Command register. | 16 | /* CPM Command register. |
16 | */ | 17 | */ |
@@ -82,6 +83,7 @@ | |||
82 | #define mk_cr_cmd(PG, SBC, MCN, OP) \ | 83 | #define mk_cr_cmd(PG, SBC, MCN, OP) \ |
83 | ((PG << 26) | (SBC << 21) | (MCN << 6) | OP) | 84 | ((PG << 26) | (SBC << 21) | (MCN << 6) | OP) |
84 | 85 | ||
86 | #ifndef CONFIG_PPC_CPM_NEW_BINDING | ||
85 | /* Dual Port RAM addresses. The first 16K is available for almost | 87 | /* Dual Port RAM addresses. The first 16K is available for almost |
86 | * any CPM use, so we put the BDs there. The first 128 bytes are | 88 | * any CPM use, so we put the BDs there. The first 128 bytes are |
87 | * used for SMC1 and SMC2 parameter RAM, so we start allocating | 89 | * used for SMC1 and SMC2 parameter RAM, so we start allocating |
@@ -97,6 +99,7 @@ | |||
97 | #define CPM_DATAONLY_SIZE ((uint)(16 * 1024) - CPM_DATAONLY_BASE) | 99 | #define CPM_DATAONLY_SIZE ((uint)(16 * 1024) - CPM_DATAONLY_BASE) |
98 | #define CPM_FCC_SPECIAL_BASE ((uint)0x0000b000) | 100 | #define CPM_FCC_SPECIAL_BASE ((uint)0x0000b000) |
99 | #endif | 101 | #endif |
102 | #endif | ||
100 | 103 | ||
101 | /* The number of pages of host memory we allocate for CPM. This is | 104 | /* The number of pages of host memory we allocate for CPM. This is |
102 | * done early in kernel initialization to get physically contiguous | 105 | * done early in kernel initialization to get physically contiguous |
@@ -109,11 +112,18 @@ | |||
109 | */ | 112 | */ |
110 | extern cpm_cpm2_t __iomem *cpmp; /* Pointer to comm processor */ | 113 | extern cpm_cpm2_t __iomem *cpmp; /* Pointer to comm processor */ |
111 | 114 | ||
115 | #ifdef CONFIG_PPC_CPM_NEW_BINDING | ||
116 | #define cpm_dpalloc cpm_muram_alloc | ||
117 | #define cpm_dpfree cpm_muram_free | ||
118 | #define cpm_dpram_addr cpm_muram_addr | ||
119 | #else | ||
112 | extern unsigned long cpm_dpalloc(uint size, uint align); | 120 | extern unsigned long cpm_dpalloc(uint size, uint align); |
113 | extern int cpm_dpfree(unsigned long offset); | 121 | extern int cpm_dpfree(unsigned long offset); |
114 | extern unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align); | 122 | extern unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align); |
115 | extern void cpm_dpdump(void); | 123 | extern void cpm_dpdump(void); |
116 | extern void *cpm_dpram_addr(unsigned long offset); | 124 | extern void *cpm_dpram_addr(unsigned long offset); |
125 | #endif | ||
126 | |||
117 | extern void cpm_setbrg(uint brg, uint rate); | 127 | extern void cpm_setbrg(uint brg, uint rate); |
118 | extern void cpm2_fastbrg(uint brg, uint rate, int div16); | 128 | extern void cpm2_fastbrg(uint brg, uint rate, int div16); |
119 | extern void cpm2_reset(void); | 129 | extern void cpm2_reset(void); |