diff options
author | Zhang Wei <wei.zhang@freescale.com> | 2008-04-18 16:33:44 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-04-29 05:40:29 -0400 |
commit | 61b269179df582bb363f871e88f732fe8af62a5e (patch) | |
tree | 30781b72103c54b7a8535014f647bfefac0e606f /arch/powerpc | |
parent | 182e143beeb3529208f805f1ac543606c1e2cc8c (diff) |
[RAPIDIO] Add serial RapidIO controller support, which includes MPC8548, MPC8641
Signed-off-by: Zhang Wei <wei.zhang@freescale.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/sysdev/fsl_rio.c | 75 |
1 files changed, 64 insertions, 11 deletions
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 14c106cf4aa2..935822a25030 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/rio.h> | 21 | #include <linux/rio.h> |
22 | #include <linux/rio_drv.h> | 22 | #include <linux/rio_drv.h> |
23 | #include <linux/of_platform.h> | 23 | #include <linux/of_platform.h> |
24 | #include <linux/delay.h> | ||
24 | 25 | ||
25 | #include <asm/io.h> | 26 | #include <asm/io.h> |
26 | 27 | ||
@@ -30,7 +31,12 @@ | |||
30 | #define IRQ_RIO_RX(m) (((struct rio_priv *)(m->priv))->rxirq) | 31 | #define IRQ_RIO_RX(m) (((struct rio_priv *)(m->priv))->rxirq) |
31 | 32 | ||
32 | #define RIO_ATMU_REGS_OFFSET 0x10c00 | 33 | #define RIO_ATMU_REGS_OFFSET 0x10c00 |
33 | #define RIO_MSG_REGS_OFFSET 0x11000 | 34 | #define RIO_P_MSG_REGS_OFFSET 0x11000 |
35 | #define RIO_S_MSG_REGS_OFFSET 0x13000 | ||
36 | #define RIO_ESCSR 0x158 | ||
37 | #define RIO_CCSR 0x15c | ||
38 | #define RIO_ISR_AACR 0x10120 | ||
39 | #define RIO_ISR_AACR_AA 0x1 /* Accept All ID */ | ||
34 | #define RIO_MAINT_WIN_SIZE 0x400000 | 40 | #define RIO_MAINT_WIN_SIZE 0x400000 |
35 | #define RIO_DBELL_WIN_SIZE 0x1000 | 41 | #define RIO_DBELL_WIN_SIZE 0x1000 |
36 | 42 | ||
@@ -69,7 +75,7 @@ | |||
69 | 75 | ||
70 | struct rio_atmu_regs { | 76 | struct rio_atmu_regs { |
71 | u32 rowtar; | 77 | u32 rowtar; |
72 | u32 pad1; | 78 | u32 rowtear; |
73 | u32 rowbar; | 79 | u32 rowbar; |
74 | u32 pad2; | 80 | u32 pad2; |
75 | u32 rowar; | 81 | u32 rowar; |
@@ -95,7 +101,15 @@ struct rio_msg_regs { | |||
95 | u32 ifqdpar; | 101 | u32 ifqdpar; |
96 | u32 pad6; | 102 | u32 pad6; |
97 | u32 ifqepar; | 103 | u32 ifqepar; |
98 | u32 pad7[250]; | 104 | u32 pad7[226]; |
105 | u32 odmr; | ||
106 | u32 odsr; | ||
107 | u32 res0[4]; | ||
108 | u32 oddpr; | ||
109 | u32 oddatr; | ||
110 | u32 res1[3]; | ||
111 | u32 odretcr; | ||
112 | u32 res2[12]; | ||
99 | u32 dmr; | 113 | u32 dmr; |
100 | u32 dsr; | 114 | u32 dsr; |
101 | u32 pad8; | 115 | u32 pad8; |
@@ -175,8 +189,22 @@ static int fsl_rio_doorbell_send(struct rio_mport *mport, | |||
175 | struct rio_priv *priv = mport->priv; | 189 | struct rio_priv *priv = mport->priv; |
176 | pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n", | 190 | pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n", |
177 | index, destid, data); | 191 | index, destid, data); |
178 | out_be32(&priv->dbell_atmu_regs->rowtar, destid << 22); | 192 | switch (mport->phy_type) { |
179 | out_be16(priv->dbell_win, data); | 193 | case RIO_PHY_PARALLEL: |
194 | out_be32(&priv->dbell_atmu_regs->rowtar, destid << 22); | ||
195 | out_be16(priv->dbell_win, data); | ||
196 | break; | ||
197 | case RIO_PHY_SERIAL: | ||
198 | /* In the serial version silicons, such as MPC8548, MPC8641, | ||
199 | * below operations is must be. | ||
200 | */ | ||
201 | out_be32(&priv->msg_regs->odmr, 0x00000000); | ||
202 | out_be32(&priv->msg_regs->odretcr, 0x00000004); | ||
203 | out_be32(&priv->msg_regs->oddpr, destid << 16); | ||
204 | out_be32(&priv->msg_regs->oddatr, data); | ||
205 | out_be32(&priv->msg_regs->odmr, 0x00000001); | ||
206 | break; | ||
207 | } | ||
180 | 208 | ||
181 | return 0; | 209 | return 0; |
182 | } | 210 | } |
@@ -342,11 +370,22 @@ rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, | |||
342 | memset(priv->msg_tx_ring.virt_buffer[priv->msg_tx_ring.tx_slot] | 370 | memset(priv->msg_tx_ring.virt_buffer[priv->msg_tx_ring.tx_slot] |
343 | + len, 0, RIO_MAX_MSG_SIZE - len); | 371 | + len, 0, RIO_MAX_MSG_SIZE - len); |
344 | 372 | ||
345 | /* Set mbox field for message */ | 373 | switch (mport->phy_type) { |
346 | desc->dport = mbox & 0x3; | 374 | case RIO_PHY_PARALLEL: |
375 | /* Set mbox field for message */ | ||
376 | desc->dport = mbox & 0x3; | ||
347 | 377 | ||
348 | /* Enable EOMI interrupt, set priority, and set destid */ | 378 | /* Enable EOMI interrupt, set priority, and set destid */ |
349 | desc->dattr = 0x28000000 | (rdev->destid << 2); | 379 | desc->dattr = 0x28000000 | (rdev->destid << 2); |
380 | break; | ||
381 | case RIO_PHY_SERIAL: | ||
382 | /* Set mbox field for message, and set destid */ | ||
383 | desc->dport = (rdev->destid << 16) | (mbox & 0x3); | ||
384 | |||
385 | /* Enable EOMI interrupt and priority */ | ||
386 | desc->dattr = 0x28000000; | ||
387 | break; | ||
388 | } | ||
350 | 389 | ||
351 | /* Set transfer size aligned to next power of 2 (in double words) */ | 390 | /* Set transfer size aligned to next power of 2 (in double words) */ |
352 | desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len); | 391 | desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len); |
@@ -920,6 +959,7 @@ int fsl_rio_setup(struct of_device *dev) | |||
920 | const u32 *dt_range, *cell; | 959 | const u32 *dt_range, *cell; |
921 | struct resource regs; | 960 | struct resource regs; |
922 | int rlen; | 961 | int rlen; |
962 | u32 ccsr; | ||
923 | u64 law_start, law_size; | 963 | u64 law_start, law_size; |
924 | int paw, aw, sw; | 964 | int paw, aw, sw; |
925 | 965 | ||
@@ -1008,6 +1048,14 @@ int fsl_rio_setup(struct of_device *dev) | |||
1008 | 1048 | ||
1009 | priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1); | 1049 | priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1); |
1010 | 1050 | ||
1051 | /* Probe the master port phy type */ | ||
1052 | ccsr = in_be32(priv->regs_win + RIO_CCSR); | ||
1053 | port->phy_type = (ccsr & 1) ? RIO_PHY_SERIAL : RIO_PHY_PARALLEL; | ||
1054 | dev_info(&dev->dev, "RapidIO PHY type: %s\n", | ||
1055 | (port->phy_type == RIO_PHY_PARALLEL) ? "parallel" : | ||
1056 | ((port->phy_type == RIO_PHY_SERIAL) ? "serial" : | ||
1057 | "unknown")); | ||
1058 | |||
1011 | port->sys_size = (in_be32((priv->regs_win + RIO_PEF_CAR)) | 1059 | port->sys_size = (in_be32((priv->regs_win + RIO_PEF_CAR)) |
1012 | & RIO_PEF_CTLS) >> 4; | 1060 | & RIO_PEF_CTLS) >> 4; |
1013 | dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", | 1061 | dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", |
@@ -1017,8 +1065,13 @@ int fsl_rio_setup(struct of_device *dev) | |||
1017 | + RIO_ATMU_REGS_OFFSET); | 1065 | + RIO_ATMU_REGS_OFFSET); |
1018 | priv->maint_atmu_regs = priv->atmu_regs + 1; | 1066 | priv->maint_atmu_regs = priv->atmu_regs + 1; |
1019 | priv->dbell_atmu_regs = priv->atmu_regs + 2; | 1067 | priv->dbell_atmu_regs = priv->atmu_regs + 2; |
1020 | priv->msg_regs = (struct rio_msg_regs *)(priv->regs_win | 1068 | priv->msg_regs = (struct rio_msg_regs *)(priv->regs_win + |
1021 | + RIO_MSG_REGS_OFFSET); | 1069 | ((port->phy_type == RIO_PHY_SERIAL) ? |
1070 | RIO_S_MSG_REGS_OFFSET : RIO_P_MSG_REGS_OFFSET)); | ||
1071 | |||
1072 | /* Set to receive any dist ID for serial RapidIO controller. */ | ||
1073 | if (port->phy_type == RIO_PHY_SERIAL) | ||
1074 | out_be32((priv->regs_win + RIO_ISR_AACR), RIO_ISR_AACR_AA); | ||
1022 | 1075 | ||
1023 | /* Configure maintenance transaction window */ | 1076 | /* Configure maintenance transaction window */ |
1024 | out_be32(&priv->maint_atmu_regs->rowbar, 0x000c0000); | 1077 | out_be32(&priv->maint_atmu_regs->rowbar, 0x000c0000); |