diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-06 16:30:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-06 16:30:06 -0400 |
commit | b4b50fd78b1e31989940dfc647e64453d0f7176a (patch) | |
tree | 1a55f110e021c02963b63759f3f18ea7ba3aa228 /drivers/bus | |
parent | dccfd1e439c11422d7aca0d834b0430d24650e85 (diff) | |
parent | f97c43bbdf8a1ea42477b1a804a48e7e368cb13c (diff) |
Merge tag 'soc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC platform changes from Olof Johansson:
"This branch contains mostly additions and changes to platform
enablement and SoC-level drivers. Since there's sometimes a
dependency on device-tree changes, there's also a fair amount of
those in this branch.
Pieces worth mentioning are:
- Mbus driver for Marvell platforms, allowing kernel configuration
and resource allocation of on-chip peripherals.
- Enablement of the mbus infrastructure from Marvell PCI-e drivers.
- Preparation of MSI support for Marvell platforms.
- Addition of new PCI-e host controller driver for Tegra platforms
- Some churn caused by sharing of macro names between i.MX 6Q and 6DL
platforms in the device tree sources and header files.
- Various suspend/PM updates for Tegra, including LP1 support.
- Versatile Express support for MCPM, part of big little support.
- Allwinner platform support for A20 and A31 SoCs (dual and quad
Cortex-A7)
- OMAP2+ support for DRA7, a new Cortex-A15-based SoC.
The code that touches other architectures are patches moving MSI
arch-specific functions over to weak symbols and removal of
ARCH_SUPPORTS_MSI, acked by PCI maintainers"
* tag 'soc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (266 commits)
tegra-cpuidle: provide stub when !CONFIG_CPU_IDLE
PCI: tegra: replace devm_request_and_ioremap by devm_ioremap_resource
ARM: tegra: Drop ARCH_SUPPORTS_MSI and sort list
ARM: dts: vf610-twr: enable i2c0 device
ARM: dts: i.MX51: Add one more I2C2 pinmux entry
ARM: dts: i.MX51: Move pins configuration under "iomuxc" label
ARM: dtsi: imx6qdl-sabresd: Add USB OTG vbus pin to pinctrl_hog
ARM: dtsi: imx6qdl-sabresd: Add USB host 1 VBUS regulator
ARM: dts: imx27-phytec-phycore-som: Enable AUDMUX
ARM: dts: i.MX27: Disable AUDMUX in the template
ARM: dts: wandboard: Add support for SDIO bcm4329
ARM: i.MX5 clocks: Remove optional clock setup (CKIH1) from i.MX51 template
ARM: dts: imx53-qsb: Make USBH1 functional
ARM i.MX6Q: dts: Enable I2C1 with EEPROM and PMIC on Phytec phyFLEX-i.MX6 Ouad module
ARM i.MX6Q: dts: Enable SPI NOR flash on Phytec phyFLEX-i.MX6 Ouad module
ARM: dts: imx6qdl-sabresd: Add touchscreen support
ARM: imx: add ocram clock for imx53
ARM: dts: imx: ocram size is different between imx6q and imx6dl
ARM: dts: imx27-phytec-phycore-som: Fix regulator settings
ARM: dts: i.MX27: Remove clock name from CPU node
...
Diffstat (limited to 'drivers/bus')
-rw-r--r-- | drivers/bus/Kconfig | 3 | ||||
-rw-r--r-- | drivers/bus/imx-weim.c | 129 | ||||
-rw-r--r-- | drivers/bus/mvebu-mbus.c | 441 |
3 files changed, 329 insertions, 244 deletions
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 1f70e84b442c..552373c4e362 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig | |||
@@ -8,10 +8,9 @@ config IMX_WEIM | |||
8 | bool "Freescale EIM DRIVER" | 8 | bool "Freescale EIM DRIVER" |
9 | depends on ARCH_MXC | 9 | depends on ARCH_MXC |
10 | help | 10 | help |
11 | Driver for i.MX6 WEIM controller. | 11 | Driver for i.MX WEIM controller. |
12 | The WEIM(Wireless External Interface Module) works like a bus. | 12 | The WEIM(Wireless External Interface Module) works like a bus. |
13 | You can attach many different devices on it, such as NOR, onenand. | 13 | You can attach many different devices on it, such as NOR, onenand. |
14 | But now, we only support the Parallel NOR. | ||
15 | 14 | ||
16 | config MVEBU_MBUS | 15 | config MVEBU_MBUS |
17 | bool | 16 | bool |
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c index 349f14e886b7..3ef58c8dbf11 100644 --- a/drivers/bus/imx-weim.c +++ b/drivers/bus/imx-weim.c | |||
@@ -12,52 +12,83 @@ | |||
12 | #include <linux/io.h> | 12 | #include <linux/io.h> |
13 | #include <linux/of_device.h> | 13 | #include <linux/of_device.h> |
14 | 14 | ||
15 | struct imx_weim { | 15 | struct imx_weim_devtype { |
16 | void __iomem *base; | 16 | unsigned int cs_count; |
17 | struct clk *clk; | 17 | unsigned int cs_regs_count; |
18 | unsigned int cs_stride; | ||
19 | }; | ||
20 | |||
21 | static const struct imx_weim_devtype imx1_weim_devtype = { | ||
22 | .cs_count = 6, | ||
23 | .cs_regs_count = 2, | ||
24 | .cs_stride = 0x08, | ||
25 | }; | ||
26 | |||
27 | static const struct imx_weim_devtype imx27_weim_devtype = { | ||
28 | .cs_count = 6, | ||
29 | .cs_regs_count = 3, | ||
30 | .cs_stride = 0x10, | ||
31 | }; | ||
32 | |||
33 | static const struct imx_weim_devtype imx50_weim_devtype = { | ||
34 | .cs_count = 4, | ||
35 | .cs_regs_count = 6, | ||
36 | .cs_stride = 0x18, | ||
37 | }; | ||
38 | |||
39 | static const struct imx_weim_devtype imx51_weim_devtype = { | ||
40 | .cs_count = 6, | ||
41 | .cs_regs_count = 6, | ||
42 | .cs_stride = 0x18, | ||
18 | }; | 43 | }; |
19 | 44 | ||
20 | static const struct of_device_id weim_id_table[] = { | 45 | static const struct of_device_id weim_id_table[] = { |
21 | { .compatible = "fsl,imx6q-weim", }, | 46 | /* i.MX1/21 */ |
22 | {} | 47 | { .compatible = "fsl,imx1-weim", .data = &imx1_weim_devtype, }, |
48 | /* i.MX25/27/31/35 */ | ||
49 | { .compatible = "fsl,imx27-weim", .data = &imx27_weim_devtype, }, | ||
50 | /* i.MX50/53/6Q */ | ||
51 | { .compatible = "fsl,imx50-weim", .data = &imx50_weim_devtype, }, | ||
52 | { .compatible = "fsl,imx6q-weim", .data = &imx50_weim_devtype, }, | ||
53 | /* i.MX51 */ | ||
54 | { .compatible = "fsl,imx51-weim", .data = &imx51_weim_devtype, }, | ||
55 | { } | ||
23 | }; | 56 | }; |
24 | MODULE_DEVICE_TABLE(of, weim_id_table); | 57 | MODULE_DEVICE_TABLE(of, weim_id_table); |
25 | 58 | ||
26 | #define CS_TIMING_LEN 6 | ||
27 | #define CS_REG_RANGE 0x18 | ||
28 | |||
29 | /* Parse and set the timing for this device. */ | 59 | /* Parse and set the timing for this device. */ |
30 | static int | 60 | static int __init weim_timing_setup(struct device_node *np, void __iomem *base, |
31 | weim_timing_setup(struct platform_device *pdev, struct device_node *np) | 61 | const struct imx_weim_devtype *devtype) |
32 | { | 62 | { |
33 | struct imx_weim *weim = platform_get_drvdata(pdev); | 63 | u32 cs_idx, value[devtype->cs_regs_count]; |
34 | u32 value[CS_TIMING_LEN]; | 64 | int i, ret; |
35 | u32 cs_idx; | ||
36 | int ret; | ||
37 | int i; | ||
38 | 65 | ||
39 | /* get the CS index from this child node's "reg" property. */ | 66 | /* get the CS index from this child node's "reg" property. */ |
40 | ret = of_property_read_u32(np, "reg", &cs_idx); | 67 | ret = of_property_read_u32(np, "reg", &cs_idx); |
41 | if (ret) | 68 | if (ret) |
42 | return ret; | 69 | return ret; |
43 | 70 | ||
44 | /* The weim has four chip selects. */ | 71 | if (cs_idx >= devtype->cs_count) |
45 | if (cs_idx > 3) | ||
46 | return -EINVAL; | 72 | return -EINVAL; |
47 | 73 | ||
48 | ret = of_property_read_u32_array(np, "fsl,weim-cs-timing", | 74 | ret = of_property_read_u32_array(np, "fsl,weim-cs-timing", |
49 | value, CS_TIMING_LEN); | 75 | value, devtype->cs_regs_count); |
50 | if (ret) | 76 | if (ret) |
51 | return ret; | 77 | return ret; |
52 | 78 | ||
53 | /* set the timing for WEIM */ | 79 | /* set the timing for WEIM */ |
54 | for (i = 0; i < CS_TIMING_LEN; i++) | 80 | for (i = 0; i < devtype->cs_regs_count; i++) |
55 | writel(value[i], weim->base + cs_idx * CS_REG_RANGE + i * 4); | 81 | writel(value[i], base + cs_idx * devtype->cs_stride + i * 4); |
82 | |||
56 | return 0; | 83 | return 0; |
57 | } | 84 | } |
58 | 85 | ||
59 | static int weim_parse_dt(struct platform_device *pdev) | 86 | static int __init weim_parse_dt(struct platform_device *pdev, |
87 | void __iomem *base) | ||
60 | { | 88 | { |
89 | const struct of_device_id *of_id = of_match_device(weim_id_table, | ||
90 | &pdev->dev); | ||
91 | const struct imx_weim_devtype *devtype = of_id->data; | ||
61 | struct device_node *child; | 92 | struct device_node *child; |
62 | int ret; | 93 | int ret; |
63 | 94 | ||
@@ -65,7 +96,7 @@ static int weim_parse_dt(struct platform_device *pdev) | |||
65 | if (!child->name) | 96 | if (!child->name) |
66 | continue; | 97 | continue; |
67 | 98 | ||
68 | ret = weim_timing_setup(pdev, child); | 99 | ret = weim_timing_setup(child, base, devtype); |
69 | if (ret) { | 100 | if (ret) { |
70 | dev_err(&pdev->dev, "%s set timing failed.\n", | 101 | dev_err(&pdev->dev, "%s set timing failed.\n", |
71 | child->full_name); | 102 | child->full_name); |
@@ -80,59 +111,47 @@ static int weim_parse_dt(struct platform_device *pdev) | |||
80 | return ret; | 111 | return ret; |
81 | } | 112 | } |
82 | 113 | ||
83 | static int weim_probe(struct platform_device *pdev) | 114 | static int __init weim_probe(struct platform_device *pdev) |
84 | { | 115 | { |
85 | struct imx_weim *weim; | ||
86 | struct resource *res; | 116 | struct resource *res; |
87 | int ret = -EINVAL; | 117 | struct clk *clk; |
88 | 118 | void __iomem *base; | |
89 | weim = devm_kzalloc(&pdev->dev, sizeof(*weim), GFP_KERNEL); | 119 | int ret; |
90 | if (!weim) { | ||
91 | ret = -ENOMEM; | ||
92 | goto weim_err; | ||
93 | } | ||
94 | platform_set_drvdata(pdev, weim); | ||
95 | 120 | ||
96 | /* get the resource */ | 121 | /* get the resource */ |
97 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 122 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
98 | weim->base = devm_ioremap_resource(&pdev->dev, res); | 123 | base = devm_ioremap_resource(&pdev->dev, res); |
99 | if (IS_ERR(weim->base)) { | 124 | if (IS_ERR(base)) |
100 | ret = PTR_ERR(weim->base); | 125 | return PTR_ERR(base); |
101 | goto weim_err; | ||
102 | } | ||
103 | 126 | ||
104 | /* get the clock */ | 127 | /* get the clock */ |
105 | weim->clk = devm_clk_get(&pdev->dev, NULL); | 128 | clk = devm_clk_get(&pdev->dev, NULL); |
106 | if (IS_ERR(weim->clk)) | 129 | if (IS_ERR(clk)) |
107 | goto weim_err; | 130 | return PTR_ERR(clk); |
108 | 131 | ||
109 | ret = clk_prepare_enable(weim->clk); | 132 | ret = clk_prepare_enable(clk); |
110 | if (ret) | 133 | if (ret) |
111 | goto weim_err; | 134 | return ret; |
112 | 135 | ||
113 | /* parse the device node */ | 136 | /* parse the device node */ |
114 | ret = weim_parse_dt(pdev); | 137 | ret = weim_parse_dt(pdev, base); |
115 | if (ret) { | 138 | if (ret) |
116 | clk_disable_unprepare(weim->clk); | 139 | clk_disable_unprepare(clk); |
117 | goto weim_err; | 140 | else |
118 | } | 141 | dev_info(&pdev->dev, "Driver registered.\n"); |
119 | |||
120 | dev_info(&pdev->dev, "WEIM driver registered.\n"); | ||
121 | return 0; | ||
122 | 142 | ||
123 | weim_err: | ||
124 | return ret; | 143 | return ret; |
125 | } | 144 | } |
126 | 145 | ||
127 | static struct platform_driver weim_driver = { | 146 | static struct platform_driver weim_driver = { |
128 | .driver = { | 147 | .driver = { |
129 | .name = "imx-weim", | 148 | .name = "imx-weim", |
130 | .of_match_table = weim_id_table, | 149 | .owner = THIS_MODULE, |
150 | .of_match_table = weim_id_table, | ||
131 | }, | 151 | }, |
132 | .probe = weim_probe, | ||
133 | }; | 152 | }; |
153 | module_platform_driver_probe(weim_driver, weim_probe); | ||
134 | 154 | ||
135 | module_platform_driver(weim_driver); | ||
136 | MODULE_AUTHOR("Freescale Semiconductor Inc."); | 155 | MODULE_AUTHOR("Freescale Semiconductor Inc."); |
137 | MODULE_DESCRIPTION("i.MX EIM Controller Driver"); | 156 | MODULE_DESCRIPTION("i.MX EIM Controller Driver"); |
138 | MODULE_LICENSE("GPL"); | 157 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index 33c6947eebec..19ab6ff53d59 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c | |||
@@ -35,13 +35,9 @@ | |||
35 | * | 35 | * |
36 | * - Provides an API for platform code or device drivers to | 36 | * - Provides an API for platform code or device drivers to |
37 | * dynamically add or remove address decoding windows for the CPU -> | 37 | * dynamically add or remove address decoding windows for the CPU -> |
38 | * device accesses. This API is mvebu_mbus_add_window(), | 38 | * device accesses. This API is mvebu_mbus_add_window_by_id(), |
39 | * mvebu_mbus_add_window_remap_flags() and | 39 | * mvebu_mbus_add_window_remap_by_id() and |
40 | * mvebu_mbus_del_window(). Since the (target, attribute) values | 40 | * mvebu_mbus_del_window(). |
41 | * differ from one SoC family to another, the API uses a 'const char | ||
42 | * *' string to identify devices, and this driver is responsible for | ||
43 | * knowing the mapping between the name of a device and its | ||
44 | * corresponding (target, attribute) in the current SoC family. | ||
45 | * | 41 | * |
46 | * - Provides a debugfs interface in /sys/kernel/debug/mvebu-mbus/ to | 42 | * - Provides a debugfs interface in /sys/kernel/debug/mvebu-mbus/ to |
47 | * see the list of CPU -> SDRAM windows and their configuration | 43 | * see the list of CPU -> SDRAM windows and their configuration |
@@ -97,33 +93,6 @@ | |||
97 | 93 | ||
98 | #define DOVE_DDR_BASE_CS_OFF(n) ((n) << 4) | 94 | #define DOVE_DDR_BASE_CS_OFF(n) ((n) << 4) |
99 | 95 | ||
100 | struct mvebu_mbus_mapping { | ||
101 | const char *name; | ||
102 | u8 target; | ||
103 | u8 attr; | ||
104 | u8 attrmask; | ||
105 | }; | ||
106 | |||
107 | /* | ||
108 | * Masks used for the 'attrmask' field of mvebu_mbus_mapping. They | ||
109 | * allow to get the real attribute value, discarding the special bits | ||
110 | * used to select a PCI MEM region or a PCI WA region. This allows the | ||
111 | * debugfs code to reverse-match the name of a device from its | ||
112 | * target/attr values. | ||
113 | * | ||
114 | * For all devices except PCI, all bits of 'attr' must be | ||
115 | * considered. For most SoCs, only bit 3 should be ignored (it allows | ||
116 | * to select between PCI MEM and PCI I/O). On Orion5x however, there | ||
117 | * is the special bit 5 to select a PCI WA region. | ||
118 | */ | ||
119 | #define MAPDEF_NOMASK 0xff | ||
120 | #define MAPDEF_PCIMASK 0xf7 | ||
121 | #define MAPDEF_ORIONPCIMASK 0xd7 | ||
122 | |||
123 | /* Macro used to define one mvebu_mbus_mapping entry */ | ||
124 | #define MAPDEF(__n, __t, __a, __m) \ | ||
125 | { .name = __n, .target = __t, .attr = __a, .attrmask = __m } | ||
126 | |||
127 | struct mvebu_mbus_state; | 96 | struct mvebu_mbus_state; |
128 | 97 | ||
129 | struct mvebu_mbus_soc_data { | 98 | struct mvebu_mbus_soc_data { |
@@ -133,7 +102,6 @@ struct mvebu_mbus_soc_data { | |||
133 | void (*setup_cpu_target)(struct mvebu_mbus_state *s); | 102 | void (*setup_cpu_target)(struct mvebu_mbus_state *s); |
134 | int (*show_cpu_target)(struct mvebu_mbus_state *s, | 103 | int (*show_cpu_target)(struct mvebu_mbus_state *s, |
135 | struct seq_file *seq, void *v); | 104 | struct seq_file *seq, void *v); |
136 | const struct mvebu_mbus_mapping *map; | ||
137 | }; | 105 | }; |
138 | 106 | ||
139 | struct mvebu_mbus_state { | 107 | struct mvebu_mbus_state { |
@@ -142,6 +110,8 @@ struct mvebu_mbus_state { | |||
142 | struct dentry *debugfs_root; | 110 | struct dentry *debugfs_root; |
143 | struct dentry *debugfs_sdram; | 111 | struct dentry *debugfs_sdram; |
144 | struct dentry *debugfs_devs; | 112 | struct dentry *debugfs_devs; |
113 | struct resource pcie_mem_aperture; | ||
114 | struct resource pcie_io_aperture; | ||
145 | const struct mvebu_mbus_soc_data *soc; | 115 | const struct mvebu_mbus_soc_data *soc; |
146 | int hw_io_coherency; | 116 | int hw_io_coherency; |
147 | }; | 117 | }; |
@@ -428,8 +398,7 @@ static int mvebu_devs_debug_show(struct seq_file *seq, void *v) | |||
428 | u64 wbase, wremap; | 398 | u64 wbase, wremap; |
429 | u32 wsize; | 399 | u32 wsize; |
430 | u8 wtarget, wattr; | 400 | u8 wtarget, wattr; |
431 | int enabled, i; | 401 | int enabled; |
432 | const char *name; | ||
433 | 402 | ||
434 | mvebu_mbus_read_window(mbus, win, | 403 | mvebu_mbus_read_window(mbus, win, |
435 | &enabled, &wbase, &wsize, | 404 | &enabled, &wbase, &wsize, |
@@ -440,18 +409,9 @@ static int mvebu_devs_debug_show(struct seq_file *seq, void *v) | |||
440 | continue; | 409 | continue; |
441 | } | 410 | } |
442 | 411 | ||
443 | 412 | seq_printf(seq, "[%02d] %016llx - %016llx : %04x:%04x", | |
444 | for (i = 0; mbus->soc->map[i].name; i++) | ||
445 | if (mbus->soc->map[i].target == wtarget && | ||
446 | mbus->soc->map[i].attr == | ||
447 | (wattr & mbus->soc->map[i].attrmask)) | ||
448 | break; | ||
449 | |||
450 | name = mbus->soc->map[i].name ?: "unknown"; | ||
451 | |||
452 | seq_printf(seq, "[%02d] %016llx - %016llx : %s", | ||
453 | win, (unsigned long long)wbase, | 413 | win, (unsigned long long)wbase, |
454 | (unsigned long long)(wbase + wsize), name); | 414 | (unsigned long long)(wbase + wsize), wtarget, wattr); |
455 | 415 | ||
456 | if (win < mbus->soc->num_remappable_wins) { | 416 | if (win < mbus->soc->num_remappable_wins) { |
457 | seq_printf(seq, " (remap %016llx)\n", | 417 | seq_printf(seq, " (remap %016llx)\n", |
@@ -576,62 +536,12 @@ mvebu_mbus_dove_setup_cpu_target(struct mvebu_mbus_state *mbus) | |||
576 | mvebu_mbus_dram_info.num_cs = cs; | 536 | mvebu_mbus_dram_info.num_cs = cs; |
577 | } | 537 | } |
578 | 538 | ||
579 | static const struct mvebu_mbus_mapping armada_370_map[] = { | 539 | static const struct mvebu_mbus_soc_data armada_370_xp_mbus_data = { |
580 | MAPDEF("bootrom", 1, 0xe0, MAPDEF_NOMASK), | ||
581 | MAPDEF("devbus-boot", 1, 0x2f, MAPDEF_NOMASK), | ||
582 | MAPDEF("devbus-cs0", 1, 0x3e, MAPDEF_NOMASK), | ||
583 | MAPDEF("devbus-cs1", 1, 0x3d, MAPDEF_NOMASK), | ||
584 | MAPDEF("devbus-cs2", 1, 0x3b, MAPDEF_NOMASK), | ||
585 | MAPDEF("devbus-cs3", 1, 0x37, MAPDEF_NOMASK), | ||
586 | MAPDEF("pcie0.0", 4, 0xe0, MAPDEF_PCIMASK), | ||
587 | MAPDEF("pcie1.0", 8, 0xe0, MAPDEF_PCIMASK), | ||
588 | {}, | ||
589 | }; | ||
590 | |||
591 | static const struct mvebu_mbus_soc_data armada_370_mbus_data = { | ||
592 | .num_wins = 20, | 540 | .num_wins = 20, |
593 | .num_remappable_wins = 8, | 541 | .num_remappable_wins = 8, |
594 | .win_cfg_offset = armada_370_xp_mbus_win_offset, | 542 | .win_cfg_offset = armada_370_xp_mbus_win_offset, |
595 | .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, | 543 | .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, |
596 | .show_cpu_target = mvebu_sdram_debug_show_orion, | 544 | .show_cpu_target = mvebu_sdram_debug_show_orion, |
597 | .map = armada_370_map, | ||
598 | }; | ||
599 | |||
600 | static const struct mvebu_mbus_mapping armada_xp_map[] = { | ||
601 | MAPDEF("bootrom", 1, 0x1d, MAPDEF_NOMASK), | ||
602 | MAPDEF("devbus-boot", 1, 0x2f, MAPDEF_NOMASK), | ||
603 | MAPDEF("devbus-cs0", 1, 0x3e, MAPDEF_NOMASK), | ||
604 | MAPDEF("devbus-cs1", 1, 0x3d, MAPDEF_NOMASK), | ||
605 | MAPDEF("devbus-cs2", 1, 0x3b, MAPDEF_NOMASK), | ||
606 | MAPDEF("devbus-cs3", 1, 0x37, MAPDEF_NOMASK), | ||
607 | MAPDEF("pcie0.0", 4, 0xe0, MAPDEF_PCIMASK), | ||
608 | MAPDEF("pcie0.1", 4, 0xd0, MAPDEF_PCIMASK), | ||
609 | MAPDEF("pcie0.2", 4, 0xb0, MAPDEF_PCIMASK), | ||
610 | MAPDEF("pcie0.3", 4, 0x70, MAPDEF_PCIMASK), | ||
611 | MAPDEF("pcie1.0", 8, 0xe0, MAPDEF_PCIMASK), | ||
612 | MAPDEF("pcie1.1", 8, 0xd0, MAPDEF_PCIMASK), | ||
613 | MAPDEF("pcie1.2", 8, 0xb0, MAPDEF_PCIMASK), | ||
614 | MAPDEF("pcie1.3", 8, 0x70, MAPDEF_PCIMASK), | ||
615 | MAPDEF("pcie2.0", 4, 0xf0, MAPDEF_PCIMASK), | ||
616 | MAPDEF("pcie3.0", 8, 0xf0, MAPDEF_PCIMASK), | ||
617 | {}, | ||
618 | }; | ||
619 | |||
620 | static const struct mvebu_mbus_soc_data armada_xp_mbus_data = { | ||
621 | .num_wins = 20, | ||
622 | .num_remappable_wins = 8, | ||
623 | .win_cfg_offset = armada_370_xp_mbus_win_offset, | ||
624 | .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, | ||
625 | .show_cpu_target = mvebu_sdram_debug_show_orion, | ||
626 | .map = armada_xp_map, | ||
627 | }; | ||
628 | |||
629 | static const struct mvebu_mbus_mapping kirkwood_map[] = { | ||
630 | MAPDEF("pcie0.0", 4, 0xe0, MAPDEF_PCIMASK), | ||
631 | MAPDEF("pcie1.0", 4, 0xd0, MAPDEF_PCIMASK), | ||
632 | MAPDEF("sram", 3, 0x01, MAPDEF_NOMASK), | ||
633 | MAPDEF("nand", 1, 0x2f, MAPDEF_NOMASK), | ||
634 | {}, | ||
635 | }; | 545 | }; |
636 | 546 | ||
637 | static const struct mvebu_mbus_soc_data kirkwood_mbus_data = { | 547 | static const struct mvebu_mbus_soc_data kirkwood_mbus_data = { |
@@ -640,16 +550,6 @@ static const struct mvebu_mbus_soc_data kirkwood_mbus_data = { | |||
640 | .win_cfg_offset = orion_mbus_win_offset, | 550 | .win_cfg_offset = orion_mbus_win_offset, |
641 | .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, | 551 | .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, |
642 | .show_cpu_target = mvebu_sdram_debug_show_orion, | 552 | .show_cpu_target = mvebu_sdram_debug_show_orion, |
643 | .map = kirkwood_map, | ||
644 | }; | ||
645 | |||
646 | static const struct mvebu_mbus_mapping dove_map[] = { | ||
647 | MAPDEF("pcie0.0", 0x4, 0xe0, MAPDEF_PCIMASK), | ||
648 | MAPDEF("pcie1.0", 0x8, 0xe0, MAPDEF_PCIMASK), | ||
649 | MAPDEF("cesa", 0x3, 0x01, MAPDEF_NOMASK), | ||
650 | MAPDEF("bootrom", 0x1, 0xfd, MAPDEF_NOMASK), | ||
651 | MAPDEF("scratchpad", 0xd, 0x0, MAPDEF_NOMASK), | ||
652 | {}, | ||
653 | }; | 553 | }; |
654 | 554 | ||
655 | static const struct mvebu_mbus_soc_data dove_mbus_data = { | 555 | static const struct mvebu_mbus_soc_data dove_mbus_data = { |
@@ -658,18 +558,6 @@ static const struct mvebu_mbus_soc_data dove_mbus_data = { | |||
658 | .win_cfg_offset = orion_mbus_win_offset, | 558 | .win_cfg_offset = orion_mbus_win_offset, |
659 | .setup_cpu_target = mvebu_mbus_dove_setup_cpu_target, | 559 | .setup_cpu_target = mvebu_mbus_dove_setup_cpu_target, |
660 | .show_cpu_target = mvebu_sdram_debug_show_dove, | 560 | .show_cpu_target = mvebu_sdram_debug_show_dove, |
661 | .map = dove_map, | ||
662 | }; | ||
663 | |||
664 | static const struct mvebu_mbus_mapping orion5x_map[] = { | ||
665 | MAPDEF("pcie0.0", 4, 0x51, MAPDEF_ORIONPCIMASK), | ||
666 | MAPDEF("pci0.0", 3, 0x51, MAPDEF_ORIONPCIMASK), | ||
667 | MAPDEF("devbus-boot", 1, 0x0f, MAPDEF_NOMASK), | ||
668 | MAPDEF("devbus-cs0", 1, 0x1e, MAPDEF_NOMASK), | ||
669 | MAPDEF("devbus-cs1", 1, 0x1d, MAPDEF_NOMASK), | ||
670 | MAPDEF("devbus-cs2", 1, 0x1b, MAPDEF_NOMASK), | ||
671 | MAPDEF("sram", 0, 0x00, MAPDEF_NOMASK), | ||
672 | {}, | ||
673 | }; | 561 | }; |
674 | 562 | ||
675 | /* | 563 | /* |
@@ -682,7 +570,6 @@ static const struct mvebu_mbus_soc_data orion5x_4win_mbus_data = { | |||
682 | .win_cfg_offset = orion_mbus_win_offset, | 570 | .win_cfg_offset = orion_mbus_win_offset, |
683 | .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, | 571 | .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, |
684 | .show_cpu_target = mvebu_sdram_debug_show_orion, | 572 | .show_cpu_target = mvebu_sdram_debug_show_orion, |
685 | .map = orion5x_map, | ||
686 | }; | 573 | }; |
687 | 574 | ||
688 | static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = { | 575 | static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = { |
@@ -691,21 +578,6 @@ static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = { | |||
691 | .win_cfg_offset = orion_mbus_win_offset, | 578 | .win_cfg_offset = orion_mbus_win_offset, |
692 | .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, | 579 | .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, |
693 | .show_cpu_target = mvebu_sdram_debug_show_orion, | 580 | .show_cpu_target = mvebu_sdram_debug_show_orion, |
694 | .map = orion5x_map, | ||
695 | }; | ||
696 | |||
697 | static const struct mvebu_mbus_mapping mv78xx0_map[] = { | ||
698 | MAPDEF("pcie0.0", 4, 0xe0, MAPDEF_PCIMASK), | ||
699 | MAPDEF("pcie0.1", 4, 0xd0, MAPDEF_PCIMASK), | ||
700 | MAPDEF("pcie0.2", 4, 0xb0, MAPDEF_PCIMASK), | ||
701 | MAPDEF("pcie0.3", 4, 0x70, MAPDEF_PCIMASK), | ||
702 | MAPDEF("pcie1.0", 8, 0xe0, MAPDEF_PCIMASK), | ||
703 | MAPDEF("pcie1.1", 8, 0xd0, MAPDEF_PCIMASK), | ||
704 | MAPDEF("pcie1.2", 8, 0xb0, MAPDEF_PCIMASK), | ||
705 | MAPDEF("pcie1.3", 8, 0x70, MAPDEF_PCIMASK), | ||
706 | MAPDEF("pcie2.0", 4, 0xf0, MAPDEF_PCIMASK), | ||
707 | MAPDEF("pcie3.0", 8, 0xf0, MAPDEF_PCIMASK), | ||
708 | {}, | ||
709 | }; | 581 | }; |
710 | 582 | ||
711 | static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = { | 583 | static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = { |
@@ -714,7 +586,6 @@ static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = { | |||
714 | .win_cfg_offset = mv78xx0_mbus_win_offset, | 586 | .win_cfg_offset = mv78xx0_mbus_win_offset, |
715 | .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, | 587 | .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, |
716 | .show_cpu_target = mvebu_sdram_debug_show_orion, | 588 | .show_cpu_target = mvebu_sdram_debug_show_orion, |
717 | .map = mv78xx0_map, | ||
718 | }; | 589 | }; |
719 | 590 | ||
720 | /* | 591 | /* |
@@ -725,9 +596,9 @@ static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = { | |||
725 | */ | 596 | */ |
726 | static const struct of_device_id of_mvebu_mbus_ids[] = { | 597 | static const struct of_device_id of_mvebu_mbus_ids[] = { |
727 | { .compatible = "marvell,armada370-mbus", | 598 | { .compatible = "marvell,armada370-mbus", |
728 | .data = &armada_370_mbus_data, }, | 599 | .data = &armada_370_xp_mbus_data, }, |
729 | { .compatible = "marvell,armadaxp-mbus", | 600 | { .compatible = "marvell,armadaxp-mbus", |
730 | .data = &armada_xp_mbus_data, }, | 601 | .data = &armada_370_xp_mbus_data, }, |
731 | { .compatible = "marvell,kirkwood-mbus", | 602 | { .compatible = "marvell,kirkwood-mbus", |
732 | .data = &kirkwood_mbus_data, }, | 603 | .data = &kirkwood_mbus_data, }, |
733 | { .compatible = "marvell,dove-mbus", | 604 | { .compatible = "marvell,dove-mbus", |
@@ -748,48 +619,27 @@ static const struct of_device_id of_mvebu_mbus_ids[] = { | |||
748 | /* | 619 | /* |
749 | * Public API of the driver | 620 | * Public API of the driver |
750 | */ | 621 | */ |
751 | int mvebu_mbus_add_window_remap_flags(const char *devname, phys_addr_t base, | 622 | int mvebu_mbus_add_window_remap_by_id(unsigned int target, |
752 | size_t size, phys_addr_t remap, | 623 | unsigned int attribute, |
753 | unsigned int flags) | 624 | phys_addr_t base, size_t size, |
625 | phys_addr_t remap) | ||
754 | { | 626 | { |
755 | struct mvebu_mbus_state *s = &mbus_state; | 627 | struct mvebu_mbus_state *s = &mbus_state; |
756 | u8 target, attr; | ||
757 | int i; | ||
758 | |||
759 | if (!s->soc->map) | ||
760 | return -ENODEV; | ||
761 | |||
762 | for (i = 0; s->soc->map[i].name; i++) | ||
763 | if (!strcmp(s->soc->map[i].name, devname)) | ||
764 | break; | ||
765 | |||
766 | if (!s->soc->map[i].name) { | ||
767 | pr_err("unknown device '%s'\n", devname); | ||
768 | return -ENODEV; | ||
769 | } | ||
770 | |||
771 | target = s->soc->map[i].target; | ||
772 | attr = s->soc->map[i].attr; | ||
773 | |||
774 | if (flags == MVEBU_MBUS_PCI_MEM) | ||
775 | attr |= 0x8; | ||
776 | else if (flags == MVEBU_MBUS_PCI_WA) | ||
777 | attr |= 0x28; | ||
778 | 628 | ||
779 | if (!mvebu_mbus_window_conflicts(s, base, size, target, attr)) { | 629 | if (!mvebu_mbus_window_conflicts(s, base, size, target, attribute)) { |
780 | pr_err("cannot add window '%s', conflicts with another window\n", | 630 | pr_err("cannot add window '%x:%x', conflicts with another window\n", |
781 | devname); | 631 | target, attribute); |
782 | return -EINVAL; | 632 | return -EINVAL; |
783 | } | 633 | } |
784 | 634 | ||
785 | return mvebu_mbus_alloc_window(s, base, size, remap, target, attr); | 635 | return mvebu_mbus_alloc_window(s, base, size, remap, target, attribute); |
786 | |||
787 | } | 636 | } |
788 | 637 | ||
789 | int mvebu_mbus_add_window(const char *devname, phys_addr_t base, size_t size) | 638 | int mvebu_mbus_add_window_by_id(unsigned int target, unsigned int attribute, |
639 | phys_addr_t base, size_t size) | ||
790 | { | 640 | { |
791 | return mvebu_mbus_add_window_remap_flags(devname, base, size, | 641 | return mvebu_mbus_add_window_remap_by_id(target, attribute, base, |
792 | MVEBU_MBUS_NO_REMAP, 0); | 642 | size, MVEBU_MBUS_NO_REMAP); |
793 | } | 643 | } |
794 | 644 | ||
795 | int mvebu_mbus_del_window(phys_addr_t base, size_t size) | 645 | int mvebu_mbus_del_window(phys_addr_t base, size_t size) |
@@ -804,6 +654,20 @@ int mvebu_mbus_del_window(phys_addr_t base, size_t size) | |||
804 | return 0; | 654 | return 0; |
805 | } | 655 | } |
806 | 656 | ||
657 | void mvebu_mbus_get_pcie_mem_aperture(struct resource *res) | ||
658 | { | ||
659 | if (!res) | ||
660 | return; | ||
661 | *res = mbus_state.pcie_mem_aperture; | ||
662 | } | ||
663 | |||
664 | void mvebu_mbus_get_pcie_io_aperture(struct resource *res) | ||
665 | { | ||
666 | if (!res) | ||
667 | return; | ||
668 | *res = mbus_state.pcie_io_aperture; | ||
669 | } | ||
670 | |||
807 | static __init int mvebu_mbus_debugfs_init(void) | 671 | static __init int mvebu_mbus_debugfs_init(void) |
808 | { | 672 | { |
809 | struct mvebu_mbus_state *s = &mbus_state; | 673 | struct mvebu_mbus_state *s = &mbus_state; |
@@ -830,14 +694,41 @@ static __init int mvebu_mbus_debugfs_init(void) | |||
830 | } | 694 | } |
831 | fs_initcall(mvebu_mbus_debugfs_init); | 695 | fs_initcall(mvebu_mbus_debugfs_init); |
832 | 696 | ||
697 | static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus, | ||
698 | phys_addr_t mbuswins_phys_base, | ||
699 | size_t mbuswins_size, | ||
700 | phys_addr_t sdramwins_phys_base, | ||
701 | size_t sdramwins_size) | ||
702 | { | ||
703 | int win; | ||
704 | |||
705 | mbus->mbuswins_base = ioremap(mbuswins_phys_base, mbuswins_size); | ||
706 | if (!mbus->mbuswins_base) | ||
707 | return -ENOMEM; | ||
708 | |||
709 | mbus->sdramwins_base = ioremap(sdramwins_phys_base, sdramwins_size); | ||
710 | if (!mbus->sdramwins_base) { | ||
711 | iounmap(mbus_state.mbuswins_base); | ||
712 | return -ENOMEM; | ||
713 | } | ||
714 | |||
715 | if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric")) | ||
716 | mbus->hw_io_coherency = 1; | ||
717 | |||
718 | for (win = 0; win < mbus->soc->num_wins; win++) | ||
719 | mvebu_mbus_disable_window(mbus, win); | ||
720 | |||
721 | mbus->soc->setup_cpu_target(mbus); | ||
722 | |||
723 | return 0; | ||
724 | } | ||
725 | |||
833 | int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base, | 726 | int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base, |
834 | size_t mbuswins_size, | 727 | size_t mbuswins_size, |
835 | phys_addr_t sdramwins_phys_base, | 728 | phys_addr_t sdramwins_phys_base, |
836 | size_t sdramwins_size) | 729 | size_t sdramwins_size) |
837 | { | 730 | { |
838 | struct mvebu_mbus_state *mbus = &mbus_state; | ||
839 | const struct of_device_id *of_id; | 731 | const struct of_device_id *of_id; |
840 | int win; | ||
841 | 732 | ||
842 | for (of_id = of_mvebu_mbus_ids; of_id->compatible; of_id++) | 733 | for (of_id = of_mvebu_mbus_ids; of_id->compatible; of_id++) |
843 | if (!strcmp(of_id->compatible, soc)) | 734 | if (!strcmp(of_id->compatible, soc)) |
@@ -848,25 +739,201 @@ int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base, | |||
848 | return -ENODEV; | 739 | return -ENODEV; |
849 | } | 740 | } |
850 | 741 | ||
851 | mbus->soc = of_id->data; | 742 | mbus_state.soc = of_id->data; |
852 | 743 | ||
853 | mbus->mbuswins_base = ioremap(mbuswins_phys_base, mbuswins_size); | 744 | return mvebu_mbus_common_init(&mbus_state, |
854 | if (!mbus->mbuswins_base) | 745 | mbuswins_phys_base, |
855 | return -ENOMEM; | 746 | mbuswins_size, |
747 | sdramwins_phys_base, | ||
748 | sdramwins_size); | ||
749 | } | ||
856 | 750 | ||
857 | mbus->sdramwins_base = ioremap(sdramwins_phys_base, sdramwins_size); | 751 | #ifdef CONFIG_OF |
858 | if (!mbus->sdramwins_base) { | 752 | /* |
859 | iounmap(mbus_state.mbuswins_base); | 753 | * The window IDs in the ranges DT property have the following format: |
754 | * - bits 28 to 31: MBus custom field | ||
755 | * - bits 24 to 27: window target ID | ||
756 | * - bits 16 to 23: window attribute ID | ||
757 | * - bits 0 to 15: unused | ||
758 | */ | ||
759 | #define CUSTOM(id) (((id) & 0xF0000000) >> 24) | ||
760 | #define TARGET(id) (((id) & 0x0F000000) >> 24) | ||
761 | #define ATTR(id) (((id) & 0x00FF0000) >> 16) | ||
762 | |||
763 | static int __init mbus_dt_setup_win(struct mvebu_mbus_state *mbus, | ||
764 | u32 base, u32 size, | ||
765 | u8 target, u8 attr) | ||
766 | { | ||
767 | if (!mvebu_mbus_window_conflicts(mbus, base, size, target, attr)) { | ||
768 | pr_err("cannot add window '%04x:%04x', conflicts with another window\n", | ||
769 | target, attr); | ||
770 | return -EBUSY; | ||
771 | } | ||
772 | |||
773 | if (mvebu_mbus_alloc_window(mbus, base, size, MVEBU_MBUS_NO_REMAP, | ||
774 | target, attr)) { | ||
775 | pr_err("cannot add window '%04x:%04x', too many windows\n", | ||
776 | target, attr); | ||
860 | return -ENOMEM; | 777 | return -ENOMEM; |
861 | } | 778 | } |
779 | return 0; | ||
780 | } | ||
862 | 781 | ||
863 | if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric")) | 782 | static int __init |
864 | mbus->hw_io_coherency = 1; | 783 | mbus_parse_ranges(struct device_node *node, |
784 | int *addr_cells, int *c_addr_cells, int *c_size_cells, | ||
785 | int *cell_count, const __be32 **ranges_start, | ||
786 | const __be32 **ranges_end) | ||
787 | { | ||
788 | const __be32 *prop; | ||
789 | int ranges_len, tuple_len; | ||
790 | |||
791 | /* Allow a node with no 'ranges' property */ | ||
792 | *ranges_start = of_get_property(node, "ranges", &ranges_len); | ||
793 | if (*ranges_start == NULL) { | ||
794 | *addr_cells = *c_addr_cells = *c_size_cells = *cell_count = 0; | ||
795 | *ranges_start = *ranges_end = NULL; | ||
796 | return 0; | ||
797 | } | ||
798 | *ranges_end = *ranges_start + ranges_len / sizeof(__be32); | ||
865 | 799 | ||
866 | for (win = 0; win < mbus->soc->num_wins; win++) | 800 | *addr_cells = of_n_addr_cells(node); |
867 | mvebu_mbus_disable_window(mbus, win); | ||
868 | 801 | ||
869 | mbus->soc->setup_cpu_target(mbus); | 802 | prop = of_get_property(node, "#address-cells", NULL); |
803 | *c_addr_cells = be32_to_cpup(prop); | ||
804 | |||
805 | prop = of_get_property(node, "#size-cells", NULL); | ||
806 | *c_size_cells = be32_to_cpup(prop); | ||
807 | |||
808 | *cell_count = *addr_cells + *c_addr_cells + *c_size_cells; | ||
809 | tuple_len = (*cell_count) * sizeof(__be32); | ||
810 | |||
811 | if (ranges_len % tuple_len) { | ||
812 | pr_warn("malformed ranges entry '%s'\n", node->name); | ||
813 | return -EINVAL; | ||
814 | } | ||
815 | return 0; | ||
816 | } | ||
817 | |||
818 | static int __init mbus_dt_setup(struct mvebu_mbus_state *mbus, | ||
819 | struct device_node *np) | ||
820 | { | ||
821 | int addr_cells, c_addr_cells, c_size_cells; | ||
822 | int i, ret, cell_count; | ||
823 | const __be32 *r, *ranges_start, *ranges_end; | ||
824 | |||
825 | ret = mbus_parse_ranges(np, &addr_cells, &c_addr_cells, | ||
826 | &c_size_cells, &cell_count, | ||
827 | &ranges_start, &ranges_end); | ||
828 | if (ret < 0) | ||
829 | return ret; | ||
830 | |||
831 | for (i = 0, r = ranges_start; r < ranges_end; r += cell_count, i++) { | ||
832 | u32 windowid, base, size; | ||
833 | u8 target, attr; | ||
834 | |||
835 | /* | ||
836 | * An entry with a non-zero custom field do not | ||
837 | * correspond to a static window, so skip it. | ||
838 | */ | ||
839 | windowid = of_read_number(r, 1); | ||
840 | if (CUSTOM(windowid)) | ||
841 | continue; | ||
842 | |||
843 | target = TARGET(windowid); | ||
844 | attr = ATTR(windowid); | ||
870 | 845 | ||
846 | base = of_read_number(r + c_addr_cells, addr_cells); | ||
847 | size = of_read_number(r + c_addr_cells + addr_cells, | ||
848 | c_size_cells); | ||
849 | ret = mbus_dt_setup_win(mbus, base, size, target, attr); | ||
850 | if (ret < 0) | ||
851 | return ret; | ||
852 | } | ||
871 | return 0; | 853 | return 0; |
872 | } | 854 | } |
855 | |||
856 | static void __init mvebu_mbus_get_pcie_resources(struct device_node *np, | ||
857 | struct resource *mem, | ||
858 | struct resource *io) | ||
859 | { | ||
860 | u32 reg[2]; | ||
861 | int ret; | ||
862 | |||
863 | /* | ||
864 | * These are optional, so we clear them and they'll | ||
865 | * be zero if they are missing from the DT. | ||
866 | */ | ||
867 | memset(mem, 0, sizeof(struct resource)); | ||
868 | memset(io, 0, sizeof(struct resource)); | ||
869 | |||
870 | ret = of_property_read_u32_array(np, "pcie-mem-aperture", reg, ARRAY_SIZE(reg)); | ||
871 | if (!ret) { | ||
872 | mem->start = reg[0]; | ||
873 | mem->end = mem->start + reg[1]; | ||
874 | mem->flags = IORESOURCE_MEM; | ||
875 | } | ||
876 | |||
877 | ret = of_property_read_u32_array(np, "pcie-io-aperture", reg, ARRAY_SIZE(reg)); | ||
878 | if (!ret) { | ||
879 | io->start = reg[0]; | ||
880 | io->end = io->start + reg[1]; | ||
881 | io->flags = IORESOURCE_IO; | ||
882 | } | ||
883 | } | ||
884 | |||
885 | int __init mvebu_mbus_dt_init(void) | ||
886 | { | ||
887 | struct resource mbuswins_res, sdramwins_res; | ||
888 | struct device_node *np, *controller; | ||
889 | const struct of_device_id *of_id; | ||
890 | const __be32 *prop; | ||
891 | int ret; | ||
892 | |||
893 | np = of_find_matching_node(NULL, of_mvebu_mbus_ids); | ||
894 | if (!np) { | ||
895 | pr_err("could not find a matching SoC family\n"); | ||
896 | return -ENODEV; | ||
897 | } | ||
898 | |||
899 | of_id = of_match_node(of_mvebu_mbus_ids, np); | ||
900 | mbus_state.soc = of_id->data; | ||
901 | |||
902 | prop = of_get_property(np, "controller", NULL); | ||
903 | if (!prop) { | ||
904 | pr_err("required 'controller' property missing\n"); | ||
905 | return -EINVAL; | ||
906 | } | ||
907 | |||
908 | controller = of_find_node_by_phandle(be32_to_cpup(prop)); | ||
909 | if (!controller) { | ||
910 | pr_err("could not find an 'mbus-controller' node\n"); | ||
911 | return -ENODEV; | ||
912 | } | ||
913 | |||
914 | if (of_address_to_resource(controller, 0, &mbuswins_res)) { | ||
915 | pr_err("cannot get MBUS register address\n"); | ||
916 | return -EINVAL; | ||
917 | } | ||
918 | |||
919 | if (of_address_to_resource(controller, 1, &sdramwins_res)) { | ||
920 | pr_err("cannot get SDRAM register address\n"); | ||
921 | return -EINVAL; | ||
922 | } | ||
923 | |||
924 | /* Get optional pcie-{mem,io}-aperture properties */ | ||
925 | mvebu_mbus_get_pcie_resources(np, &mbus_state.pcie_mem_aperture, | ||
926 | &mbus_state.pcie_io_aperture); | ||
927 | |||
928 | ret = mvebu_mbus_common_init(&mbus_state, | ||
929 | mbuswins_res.start, | ||
930 | resource_size(&mbuswins_res), | ||
931 | sdramwins_res.start, | ||
932 | resource_size(&sdramwins_res)); | ||
933 | if (ret) | ||
934 | return ret; | ||
935 | |||
936 | /* Setup statically declared windows in the DT */ | ||
937 | return mbus_dt_setup(&mbus_state, np); | ||
938 | } | ||
939 | #endif | ||