aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bus
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-06 16:30:06 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-06 16:30:06 -0400
commitb4b50fd78b1e31989940dfc647e64453d0f7176a (patch)
tree1a55f110e021c02963b63759f3f18ea7ba3aa228 /drivers/bus
parentdccfd1e439c11422d7aca0d834b0430d24650e85 (diff)
parentf97c43bbdf8a1ea42477b1a804a48e7e368cb13c (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/Kconfig3
-rw-r--r--drivers/bus/imx-weim.c129
-rw-r--r--drivers/bus/mvebu-mbus.c441
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
16config MVEBU_MBUS 15config 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
15struct imx_weim { 15struct 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
21static const struct imx_weim_devtype imx1_weim_devtype = {
22 .cs_count = 6,
23 .cs_regs_count = 2,
24 .cs_stride = 0x08,
25};
26
27static const struct imx_weim_devtype imx27_weim_devtype = {
28 .cs_count = 6,
29 .cs_regs_count = 3,
30 .cs_stride = 0x10,
31};
32
33static const struct imx_weim_devtype imx50_weim_devtype = {
34 .cs_count = 4,
35 .cs_regs_count = 6,
36 .cs_stride = 0x18,
37};
38
39static 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
20static const struct of_device_id weim_id_table[] = { 45static 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};
24MODULE_DEVICE_TABLE(of, weim_id_table); 57MODULE_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. */
30static int 60static int __init weim_timing_setup(struct device_node *np, void __iomem *base,
31weim_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
59static int weim_parse_dt(struct platform_device *pdev) 86static 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
83static int weim_probe(struct platform_device *pdev) 114static 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
123weim_err:
124 return ret; 143 return ret;
125} 144}
126 145
127static struct platform_driver weim_driver = { 146static 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};
153module_platform_driver_probe(weim_driver, weim_probe);
134 154
135module_platform_driver(weim_driver);
136MODULE_AUTHOR("Freescale Semiconductor Inc."); 155MODULE_AUTHOR("Freescale Semiconductor Inc.");
137MODULE_DESCRIPTION("i.MX EIM Controller Driver"); 156MODULE_DESCRIPTION("i.MX EIM Controller Driver");
138MODULE_LICENSE("GPL"); 157MODULE_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
100struct 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
127struct mvebu_mbus_state; 96struct mvebu_mbus_state;
128 97
129struct mvebu_mbus_soc_data { 98struct 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
139struct mvebu_mbus_state { 107struct 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
579static const struct mvebu_mbus_mapping armada_370_map[] = { 539static 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
591static 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
600static 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
620static 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
629static 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
637static const struct mvebu_mbus_soc_data kirkwood_mbus_data = { 547static 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
646static 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
655static const struct mvebu_mbus_soc_data dove_mbus_data = { 555static 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
664static 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
688static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = { 575static 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
697static 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
711static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = { 583static 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 */
726static const struct of_device_id of_mvebu_mbus_ids[] = { 597static 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 */
751int mvebu_mbus_add_window_remap_flags(const char *devname, phys_addr_t base, 622int 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
789int mvebu_mbus_add_window(const char *devname, phys_addr_t base, size_t size) 638int 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
795int mvebu_mbus_del_window(phys_addr_t base, size_t size) 645int 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
657void mvebu_mbus_get_pcie_mem_aperture(struct resource *res)
658{
659 if (!res)
660 return;
661 *res = mbus_state.pcie_mem_aperture;
662}
663
664void mvebu_mbus_get_pcie_io_aperture(struct resource *res)
665{
666 if (!res)
667 return;
668 *res = mbus_state.pcie_io_aperture;
669}
670
807static __init int mvebu_mbus_debugfs_init(void) 671static __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}
831fs_initcall(mvebu_mbus_debugfs_init); 695fs_initcall(mvebu_mbus_debugfs_init);
832 696
697static 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
833int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base, 726int __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
763static 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")) 782static int __init
864 mbus->hw_io_coherency = 1; 783mbus_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
818static 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
856static 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
885int __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