diff options
author | Zhang Wei <wei.zhang@freescale.com> | 2008-04-18 16:33:41 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-04-29 05:40:28 -0400 |
commit | cc2bb6968a2c842149d285d77cb35200d2d37b15 (patch) | |
tree | 33349a2231af61b59bdf28312c385197f41a769f /arch/powerpc/sysdev | |
parent | ad1e9380b17addf112f89ce5a57d4d0bee129b7a (diff) |
[RAPIDIO] Add OF-tree support to RapidIO controller driver
This initializes the RapidIO controller driver using addresses and
interrupt numbers obtained from the firmware device tree, rather than
using hardcoded constants.
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/sysdev')
-rw-r--r-- | arch/powerpc/sysdev/fsl_rio.c | 110 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_rio.h | 20 |
2 files changed, 102 insertions, 28 deletions
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 80acc7940194..d2d14708e714 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
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 | 24 | ||
24 | #include <asm/io.h> | 25 | #include <asm/io.h> |
25 | 26 | ||
@@ -28,7 +29,6 @@ | |||
28 | #define IRQ_RIO_TX(m) (((struct rio_priv *)(m->priv))->txirq) | 29 | #define IRQ_RIO_TX(m) (((struct rio_priv *)(m->priv))->txirq) |
29 | #define IRQ_RIO_RX(m) (((struct rio_priv *)(m->priv))->rxirq) | 30 | #define IRQ_RIO_RX(m) (((struct rio_priv *)(m->priv))->rxirq) |
30 | 31 | ||
31 | #define RIO_REGS_BASE (CCSRBAR + 0xc0000) | ||
32 | #define RIO_ATMU_REGS_OFFSET 0x10c00 | 32 | #define RIO_ATMU_REGS_OFFSET 0x10c00 |
33 | #define RIO_MSG_REGS_OFFSET 0x11000 | 33 | #define RIO_MSG_REGS_OFFSET 0x11000 |
34 | #define RIO_MAINT_WIN_SIZE 0x400000 | 34 | #define RIO_MAINT_WIN_SIZE 0x400000 |
@@ -905,19 +905,66 @@ __setup("riohdid=", fsl_rio_get_cmdline); | |||
905 | 905 | ||
906 | /** | 906 | /** |
907 | * fsl_rio_setup - Setup MPC85xx RapidIO interface | 907 | * fsl_rio_setup - Setup MPC85xx RapidIO interface |
908 | * @law_start: Starting physical address of RapidIO LAW | 908 | * @fsl_rio_setup - Setup Freescale PowerPC RapidIO interface |
909 | * @law_size: Size of RapidIO LAW | ||
910 | * | 909 | * |
911 | * Initializes MPC85xx RapidIO hardware interface, configures | 910 | * Initializes MPC85xx RapidIO hardware interface, configures |
912 | * master port with system-specific info, and registers the | 911 | * master port with system-specific info, and registers the |
913 | * master port with the RapidIO subsystem. | 912 | * master port with the RapidIO subsystem. |
914 | */ | 913 | */ |
915 | void fsl_rio_setup(int law_start, int law_size) | 914 | int fsl_rio_setup(struct of_device *dev) |
916 | { | 915 | { |
917 | struct rio_ops *ops; | 916 | struct rio_ops *ops; |
918 | struct rio_mport *port; | 917 | struct rio_mport *port; |
919 | struct rio_priv *priv = NULL; | 918 | struct rio_priv *priv; |
920 | int rc; | 919 | int rc = 0; |
920 | const u32 *dt_range, *cell; | ||
921 | struct resource regs; | ||
922 | int rlen; | ||
923 | u64 law_start, law_size; | ||
924 | int paw, aw, sw; | ||
925 | |||
926 | if (!dev->node) { | ||
927 | dev_err(&dev->dev, "Device OF-Node is NULL"); | ||
928 | return -EFAULT; | ||
929 | } | ||
930 | |||
931 | rc = of_address_to_resource(dev->node, 0, ®s); | ||
932 | if (rc) { | ||
933 | dev_err(&dev->dev, "Can't get %s property 'reg'\n", | ||
934 | dev->node->full_name); | ||
935 | return -EFAULT; | ||
936 | } | ||
937 | dev_info(&dev->dev, "Of-device full name %s\n", dev->node->full_name); | ||
938 | dev_info(&dev->dev, "Regs start 0x%08x size 0x%08x\n", regs.start, | ||
939 | regs.end - regs.start + 1); | ||
940 | |||
941 | dt_range = of_get_property(dev->node, "ranges", &rlen); | ||
942 | if (!dt_range) { | ||
943 | dev_err(&dev->dev, "Can't get %s property 'ranges'\n", | ||
944 | dev->node->full_name); | ||
945 | return -EFAULT; | ||
946 | } | ||
947 | |||
948 | /* Get node address wide */ | ||
949 | cell = of_get_property(dev->node, "#address-cells", NULL); | ||
950 | if (cell) | ||
951 | aw = *cell; | ||
952 | else | ||
953 | aw = of_n_addr_cells(dev->node); | ||
954 | /* Get node size wide */ | ||
955 | cell = of_get_property(dev->node, "#size-cells", NULL); | ||
956 | if (cell) | ||
957 | sw = *cell; | ||
958 | else | ||
959 | sw = of_n_size_cells(dev->node); | ||
960 | /* Get parent address wide wide */ | ||
961 | paw = of_n_addr_cells(dev->node); | ||
962 | |||
963 | law_start = of_read_number(dt_range + aw, paw); | ||
964 | law_size = of_read_number(dt_range + aw + paw, sw); | ||
965 | |||
966 | dev_info(&dev->dev, "LAW start 0x%016llx, size 0x%016llx.\n", | ||
967 | law_start, law_size); | ||
921 | 968 | ||
922 | ops = kmalloc(sizeof(struct rio_ops), GFP_KERNEL); | 969 | ops = kmalloc(sizeof(struct rio_ops), GFP_KERNEL); |
923 | ops->lcread = fsl_local_config_read; | 970 | ops->lcread = fsl_local_config_read; |
@@ -942,6 +989,12 @@ void fsl_rio_setup(int law_start, int law_size) | |||
942 | port->iores.end = law_start + law_size; | 989 | port->iores.end = law_start + law_size; |
943 | port->iores.flags = IORESOURCE_MEM; | 990 | port->iores.flags = IORESOURCE_MEM; |
944 | 991 | ||
992 | priv->bellirq = irq_of_parse_and_map(dev->node, 2); | ||
993 | priv->txirq = irq_of_parse_and_map(dev->node, 3); | ||
994 | priv->rxirq = irq_of_parse_and_map(dev->node, 4); | ||
995 | dev_info(&dev->dev, "bellirq: %d, txirq: %d, rxirq %d\n", priv->bellirq, | ||
996 | priv->txirq, priv->rxirq); | ||
997 | |||
945 | rio_init_dbell_res(&port->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff); | 998 | rio_init_dbell_res(&port->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff); |
946 | rio_init_mbox_res(&port->riores[RIO_INB_MBOX_RESOURCE], 0, 0); | 999 | rio_init_mbox_res(&port->riores[RIO_INB_MBOX_RESOURCE], 0, 0); |
947 | rio_init_mbox_res(&port->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0); | 1000 | rio_init_mbox_res(&port->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0); |
@@ -953,7 +1006,7 @@ void fsl_rio_setup(int law_start, int law_size) | |||
953 | port->priv = priv; | 1006 | port->priv = priv; |
954 | rio_register_mport(port); | 1007 | rio_register_mport(port); |
955 | 1008 | ||
956 | priv->regs_win = ioremap(RIO_REGS_BASE, 0x20000); | 1009 | priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1); |
957 | priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win | 1010 | priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win |
958 | + RIO_ATMU_REGS_OFFSET); | 1011 | + RIO_ATMU_REGS_OFFSET); |
959 | priv->maint_atmu_regs = priv->atmu_regs + 1; | 1012 | priv->maint_atmu_regs = priv->atmu_regs + 1; |
@@ -972,10 +1025,51 @@ void fsl_rio_setup(int law_start, int law_size) | |||
972 | out_be32(&priv->dbell_atmu_regs->rowar, 0x8004200b); | 1025 | out_be32(&priv->dbell_atmu_regs->rowar, 0x8004200b); |
973 | fsl_rio_doorbell_init(port); | 1026 | fsl_rio_doorbell_init(port); |
974 | 1027 | ||
975 | return; | 1028 | return 0; |
976 | err: | 1029 | err: |
977 | if (priv) | 1030 | if (priv) |
978 | iounmap(priv->regs_win); | 1031 | iounmap(priv->regs_win); |
1032 | kfree(ops); | ||
979 | kfree(priv); | 1033 | kfree(priv); |
980 | kfree(port); | 1034 | kfree(port); |
1035 | return rc; | ||
981 | } | 1036 | } |
1037 | |||
1038 | /* The probe function for RapidIO peer-to-peer network. | ||
1039 | */ | ||
1040 | static int __devinit fsl_of_rio_rpn_probe(struct of_device *dev, | ||
1041 | const struct of_device_id *match) | ||
1042 | { | ||
1043 | int rc; | ||
1044 | printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n", | ||
1045 | dev->node->full_name); | ||
1046 | |||
1047 | rc = fsl_rio_setup(dev); | ||
1048 | if (rc) | ||
1049 | goto out; | ||
1050 | |||
1051 | /* Enumerate all registered ports */ | ||
1052 | rc = rio_init_mports(); | ||
1053 | out: | ||
1054 | return rc; | ||
1055 | }; | ||
1056 | |||
1057 | static const struct of_device_id fsl_of_rio_rpn_ids[] = { | ||
1058 | { | ||
1059 | .compatible = "fsl,rapidio-delta", | ||
1060 | }, | ||
1061 | {}, | ||
1062 | }; | ||
1063 | |||
1064 | static struct of_platform_driver fsl_of_rio_rpn_driver = { | ||
1065 | .name = "fsl-of-rio", | ||
1066 | .match_table = fsl_of_rio_rpn_ids, | ||
1067 | .probe = fsl_of_rio_rpn_probe, | ||
1068 | }; | ||
1069 | |||
1070 | static __init int fsl_of_rio_rpn_init(void) | ||
1071 | { | ||
1072 | return of_register_platform_driver(&fsl_of_rio_rpn_driver); | ||
1073 | } | ||
1074 | |||
1075 | subsys_initcall(fsl_of_rio_rpn_init); | ||
diff --git a/arch/powerpc/sysdev/fsl_rio.h b/arch/powerpc/sysdev/fsl_rio.h deleted file mode 100644 index 6d3ff30b1579..000000000000 --- a/arch/powerpc/sysdev/fsl_rio.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | /* | ||
2 | * MPC85xx RapidIO definitions | ||
3 | * | ||
4 | * Copyright 2005 MontaVista Software, Inc. | ||
5 | * Matt Porter <mporter@kernel.crashing.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #ifndef __PPC_SYSLIB_PPC85XX_RIO_H | ||
14 | #define __PPC_SYSLIB_PPC85XX_RIO_H | ||
15 | |||
16 | #include <linux/init.h> | ||
17 | |||
18 | extern void mpc85xx_rio_setup(int law_start, int law_size); | ||
19 | |||
20 | #endif /* __PPC_SYSLIB_PPC85XX_RIO_H */ | ||