12b72c9e3SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
23edad321SEzequiel Garcia /*
33edad321SEzequiel Garcia * Marvell EBU SoC Device Bus Controller
43edad321SEzequiel Garcia * (memory controller for NOR/NAND/SRAM/FPGA devices)
53edad321SEzequiel Garcia *
6c4ec7430SThomas Petazzoni * Copyright (C) 2013-2014 Marvell
73edad321SEzequiel Garcia */
83edad321SEzequiel Garcia
93edad321SEzequiel Garcia #include <linux/kernel.h>
103edad321SEzequiel Garcia #include <linux/module.h>
113edad321SEzequiel Garcia #include <linux/slab.h>
123edad321SEzequiel Garcia #include <linux/err.h>
133edad321SEzequiel Garcia #include <linux/io.h>
143edad321SEzequiel Garcia #include <linux/clk.h>
153edad321SEzequiel Garcia #include <linux/mbus.h>
163edad321SEzequiel Garcia #include <linux/of_platform.h>
173edad321SEzequiel Garcia #include <linux/of_address.h>
183edad321SEzequiel Garcia #include <linux/platform_device.h>
193edad321SEzequiel Garcia
203edad321SEzequiel Garcia /* Register definitions */
218a33692eSThomas Petazzoni #define ARMADA_DEV_WIDTH_SHIFT 30
228a33692eSThomas Petazzoni #define ARMADA_BADR_SKEW_SHIFT 28
238a33692eSThomas Petazzoni #define ARMADA_RD_HOLD_SHIFT 23
248a33692eSThomas Petazzoni #define ARMADA_ACC_NEXT_SHIFT 17
258a33692eSThomas Petazzoni #define ARMADA_RD_SETUP_SHIFT 12
268a33692eSThomas Petazzoni #define ARMADA_ACC_FIRST_SHIFT 6
273edad321SEzequiel Garcia
288a33692eSThomas Petazzoni #define ARMADA_SYNC_ENABLE_SHIFT 24
298a33692eSThomas Petazzoni #define ARMADA_WR_HIGH_SHIFT 16
308a33692eSThomas Petazzoni #define ARMADA_WR_LOW_SHIFT 8
313edad321SEzequiel Garcia
3271e2e5d3SThomas Petazzoni #define ARMADA_READ_PARAM_OFFSET 0x0
3371e2e5d3SThomas Petazzoni #define ARMADA_WRITE_PARAM_OFFSET 0x4
343edad321SEzequiel Garcia
35c4ec7430SThomas Petazzoni #define ORION_RESERVED (0x2 << 30)
36c4ec7430SThomas Petazzoni #define ORION_BADR_SKEW_SHIFT 28
37c4ec7430SThomas Petazzoni #define ORION_WR_HIGH_EXT_BIT BIT(27)
38c4ec7430SThomas Petazzoni #define ORION_WR_HIGH_EXT_MASK 0x8
39c4ec7430SThomas Petazzoni #define ORION_WR_LOW_EXT_BIT BIT(26)
40c4ec7430SThomas Petazzoni #define ORION_WR_LOW_EXT_MASK 0x8
41c4ec7430SThomas Petazzoni #define ORION_ALE_WR_EXT_BIT BIT(25)
42c4ec7430SThomas Petazzoni #define ORION_ALE_WR_EXT_MASK 0x8
43c4ec7430SThomas Petazzoni #define ORION_ACC_NEXT_EXT_BIT BIT(24)
44c4ec7430SThomas Petazzoni #define ORION_ACC_NEXT_EXT_MASK 0x10
45c4ec7430SThomas Petazzoni #define ORION_ACC_FIRST_EXT_BIT BIT(23)
46c4ec7430SThomas Petazzoni #define ORION_ACC_FIRST_EXT_MASK 0x10
47c4ec7430SThomas Petazzoni #define ORION_TURN_OFF_EXT_BIT BIT(22)
48c4ec7430SThomas Petazzoni #define ORION_TURN_OFF_EXT_MASK 0x8
49c4ec7430SThomas Petazzoni #define ORION_DEV_WIDTH_SHIFT 20
50c4ec7430SThomas Petazzoni #define ORION_WR_HIGH_SHIFT 17
51c4ec7430SThomas Petazzoni #define ORION_WR_HIGH_MASK 0x7
52c4ec7430SThomas Petazzoni #define ORION_WR_LOW_SHIFT 14
53c4ec7430SThomas Petazzoni #define ORION_WR_LOW_MASK 0x7
54c4ec7430SThomas Petazzoni #define ORION_ALE_WR_SHIFT 11
55c4ec7430SThomas Petazzoni #define ORION_ALE_WR_MASK 0x7
56c4ec7430SThomas Petazzoni #define ORION_ACC_NEXT_SHIFT 7
57c4ec7430SThomas Petazzoni #define ORION_ACC_NEXT_MASK 0xF
58c4ec7430SThomas Petazzoni #define ORION_ACC_FIRST_SHIFT 3
59c4ec7430SThomas Petazzoni #define ORION_ACC_FIRST_MASK 0xF
60c4ec7430SThomas Petazzoni #define ORION_TURN_OFF_SHIFT 0
61c4ec7430SThomas Petazzoni #define ORION_TURN_OFF_MASK 0x7
62c4ec7430SThomas Petazzoni
633edad321SEzequiel Garcia struct devbus_read_params {
643edad321SEzequiel Garcia u32 bus_width;
653edad321SEzequiel Garcia u32 badr_skew;
663edad321SEzequiel Garcia u32 turn_off;
673edad321SEzequiel Garcia u32 acc_first;
683edad321SEzequiel Garcia u32 acc_next;
693edad321SEzequiel Garcia u32 rd_setup;
703edad321SEzequiel Garcia u32 rd_hold;
713edad321SEzequiel Garcia };
723edad321SEzequiel Garcia
733edad321SEzequiel Garcia struct devbus_write_params {
743edad321SEzequiel Garcia u32 sync_enable;
753edad321SEzequiel Garcia u32 wr_high;
763edad321SEzequiel Garcia u32 wr_low;
773edad321SEzequiel Garcia u32 ale_wr;
783edad321SEzequiel Garcia };
793edad321SEzequiel Garcia
803edad321SEzequiel Garcia struct devbus {
813edad321SEzequiel Garcia struct device *dev;
823edad321SEzequiel Garcia void __iomem *base;
833edad321SEzequiel Garcia unsigned long tick_ps;
843edad321SEzequiel Garcia };
853edad321SEzequiel Garcia
get_timing_param_ps(struct devbus * devbus,struct device_node * node,const char * name,u32 * ticks)863edad321SEzequiel Garcia static int get_timing_param_ps(struct devbus *devbus,
873edad321SEzequiel Garcia struct device_node *node,
883edad321SEzequiel Garcia const char *name,
893edad321SEzequiel Garcia u32 *ticks)
903edad321SEzequiel Garcia {
913edad321SEzequiel Garcia u32 time_ps;
923edad321SEzequiel Garcia int err;
933edad321SEzequiel Garcia
943edad321SEzequiel Garcia err = of_property_read_u32(node, name, &time_ps);
953edad321SEzequiel Garcia if (err < 0) {
96db749d17SRob Herring dev_err(devbus->dev, "%pOF has no '%s' property\n",
97db749d17SRob Herring node, name);
983edad321SEzequiel Garcia return err;
993edad321SEzequiel Garcia }
1003edad321SEzequiel Garcia
1013edad321SEzequiel Garcia *ticks = (time_ps + devbus->tick_ps - 1) / devbus->tick_ps;
1023edad321SEzequiel Garcia
1033edad321SEzequiel Garcia dev_dbg(devbus->dev, "%s: %u ps -> 0x%x\n",
1043edad321SEzequiel Garcia name, time_ps, *ticks);
1053edad321SEzequiel Garcia return 0;
1063edad321SEzequiel Garcia }
1073edad321SEzequiel Garcia
devbus_get_timing_params(struct devbus * devbus,struct device_node * node,struct devbus_read_params * r,struct devbus_write_params * w)10830bd30b6SThomas Petazzoni static int devbus_get_timing_params(struct devbus *devbus,
10930bd30b6SThomas Petazzoni struct device_node *node,
11030bd30b6SThomas Petazzoni struct devbus_read_params *r,
11130bd30b6SThomas Petazzoni struct devbus_write_params *w)
1123edad321SEzequiel Garcia {
1133edad321SEzequiel Garcia int err;
1143edad321SEzequiel Garcia
11530bd30b6SThomas Petazzoni err = of_property_read_u32(node, "devbus,bus-width", &r->bus_width);
1163edad321SEzequiel Garcia if (err < 0) {
1173edad321SEzequiel Garcia dev_err(devbus->dev,
118db749d17SRob Herring "%pOF has no 'devbus,bus-width' property\n",
119db749d17SRob Herring node);
1203edad321SEzequiel Garcia return err;
1213edad321SEzequiel Garcia }
122ce965c3dSThomas Petazzoni
123ce965c3dSThomas Petazzoni /*
124ce965c3dSThomas Petazzoni * The bus width is encoded into the register as 0 for 8 bits,
125ce965c3dSThomas Petazzoni * and 1 for 16 bits, so we do the necessary conversion here.
126ce965c3dSThomas Petazzoni */
127bf8fba45SKrzysztof Kozlowski if (r->bus_width == 8) {
12830bd30b6SThomas Petazzoni r->bus_width = 0;
129bf8fba45SKrzysztof Kozlowski } else if (r->bus_width == 16) {
13030bd30b6SThomas Petazzoni r->bus_width = 1;
131bf8fba45SKrzysztof Kozlowski } else {
13230bd30b6SThomas Petazzoni dev_err(devbus->dev, "invalid bus width %d\n", r->bus_width);
133ce965c3dSThomas Petazzoni return -EINVAL;
134ce965c3dSThomas Petazzoni }
1353edad321SEzequiel Garcia
1363edad321SEzequiel Garcia err = get_timing_param_ps(devbus, node, "devbus,badr-skew-ps",
13730bd30b6SThomas Petazzoni &r->badr_skew);
1383edad321SEzequiel Garcia if (err < 0)
1393edad321SEzequiel Garcia return err;
1403edad321SEzequiel Garcia
1413edad321SEzequiel Garcia err = get_timing_param_ps(devbus, node, "devbus,turn-off-ps",
14230bd30b6SThomas Petazzoni &r->turn_off);
1433edad321SEzequiel Garcia if (err < 0)
1443edad321SEzequiel Garcia return err;
1453edad321SEzequiel Garcia
1463edad321SEzequiel Garcia err = get_timing_param_ps(devbus, node, "devbus,acc-first-ps",
14730bd30b6SThomas Petazzoni &r->acc_first);
1483edad321SEzequiel Garcia if (err < 0)
1493edad321SEzequiel Garcia return err;
1503edad321SEzequiel Garcia
1513edad321SEzequiel Garcia err = get_timing_param_ps(devbus, node, "devbus,acc-next-ps",
15230bd30b6SThomas Petazzoni &r->acc_next);
1533edad321SEzequiel Garcia if (err < 0)
1543edad321SEzequiel Garcia return err;
1553edad321SEzequiel Garcia
156c4ec7430SThomas Petazzoni if (of_device_is_compatible(devbus->dev->of_node, "marvell,mvebu-devbus")) {
1573edad321SEzequiel Garcia err = get_timing_param_ps(devbus, node, "devbus,rd-setup-ps",
15830bd30b6SThomas Petazzoni &r->rd_setup);
1593edad321SEzequiel Garcia if (err < 0)
1603edad321SEzequiel Garcia return err;
1613edad321SEzequiel Garcia
1623edad321SEzequiel Garcia err = get_timing_param_ps(devbus, node, "devbus,rd-hold-ps",
16330bd30b6SThomas Petazzoni &r->rd_hold);
1643edad321SEzequiel Garcia if (err < 0)
1653edad321SEzequiel Garcia return err;
1663edad321SEzequiel Garcia
1673edad321SEzequiel Garcia err = of_property_read_u32(node, "devbus,sync-enable",
16830bd30b6SThomas Petazzoni &w->sync_enable);
1693edad321SEzequiel Garcia if (err < 0) {
1703edad321SEzequiel Garcia dev_err(devbus->dev,
171db749d17SRob Herring "%pOF has no 'devbus,sync-enable' property\n",
172db749d17SRob Herring node);
1733edad321SEzequiel Garcia return err;
1743edad321SEzequiel Garcia }
175c4ec7430SThomas Petazzoni }
1763edad321SEzequiel Garcia
1773edad321SEzequiel Garcia err = get_timing_param_ps(devbus, node, "devbus,ale-wr-ps",
17830bd30b6SThomas Petazzoni &w->ale_wr);
1793edad321SEzequiel Garcia if (err < 0)
1803edad321SEzequiel Garcia return err;
1813edad321SEzequiel Garcia
1823edad321SEzequiel Garcia err = get_timing_param_ps(devbus, node, "devbus,wr-low-ps",
18330bd30b6SThomas Petazzoni &w->wr_low);
1843edad321SEzequiel Garcia if (err < 0)
1853edad321SEzequiel Garcia return err;
1863edad321SEzequiel Garcia
1873edad321SEzequiel Garcia err = get_timing_param_ps(devbus, node, "devbus,wr-high-ps",
18830bd30b6SThomas Petazzoni &w->wr_high);
1893edad321SEzequiel Garcia if (err < 0)
1903edad321SEzequiel Garcia return err;
1913edad321SEzequiel Garcia
19230bd30b6SThomas Petazzoni return 0;
19330bd30b6SThomas Petazzoni }
19430bd30b6SThomas Petazzoni
devbus_orion_set_timing_params(struct devbus * devbus,struct device_node * node,struct devbus_read_params * r,struct devbus_write_params * w)195c4ec7430SThomas Petazzoni static void devbus_orion_set_timing_params(struct devbus *devbus,
196c4ec7430SThomas Petazzoni struct device_node *node,
197c4ec7430SThomas Petazzoni struct devbus_read_params *r,
198c4ec7430SThomas Petazzoni struct devbus_write_params *w)
199c4ec7430SThomas Petazzoni {
200c4ec7430SThomas Petazzoni u32 value;
201c4ec7430SThomas Petazzoni
202c4ec7430SThomas Petazzoni /*
203c4ec7430SThomas Petazzoni * The hardware designers found it would be a good idea to
204c4ec7430SThomas Petazzoni * split most of the values in the register into two fields:
205c4ec7430SThomas Petazzoni * one containing all the low-order bits, and another one
206c4ec7430SThomas Petazzoni * containing just the high-order bit. For all of those
207c4ec7430SThomas Petazzoni * fields, we have to split the value into these two parts.
208c4ec7430SThomas Petazzoni */
209c4ec7430SThomas Petazzoni value = (r->turn_off & ORION_TURN_OFF_MASK) << ORION_TURN_OFF_SHIFT |
210c4ec7430SThomas Petazzoni (r->acc_first & ORION_ACC_FIRST_MASK) << ORION_ACC_FIRST_SHIFT |
211c4ec7430SThomas Petazzoni (r->acc_next & ORION_ACC_NEXT_MASK) << ORION_ACC_NEXT_SHIFT |
212c4ec7430SThomas Petazzoni (w->ale_wr & ORION_ALE_WR_MASK) << ORION_ALE_WR_SHIFT |
213c4ec7430SThomas Petazzoni (w->wr_low & ORION_WR_LOW_MASK) << ORION_WR_LOW_SHIFT |
214c4ec7430SThomas Petazzoni (w->wr_high & ORION_WR_HIGH_MASK) << ORION_WR_HIGH_SHIFT |
215c4ec7430SThomas Petazzoni r->bus_width << ORION_DEV_WIDTH_SHIFT |
216c4ec7430SThomas Petazzoni ((r->turn_off & ORION_TURN_OFF_EXT_MASK) ? ORION_TURN_OFF_EXT_BIT : 0) |
217c4ec7430SThomas Petazzoni ((r->acc_first & ORION_ACC_FIRST_EXT_MASK) ? ORION_ACC_FIRST_EXT_BIT : 0) |
218c4ec7430SThomas Petazzoni ((r->acc_next & ORION_ACC_NEXT_EXT_MASK) ? ORION_ACC_NEXT_EXT_BIT : 0) |
219c4ec7430SThomas Petazzoni ((w->ale_wr & ORION_ALE_WR_EXT_MASK) ? ORION_ALE_WR_EXT_BIT : 0) |
220c4ec7430SThomas Petazzoni ((w->wr_low & ORION_WR_LOW_EXT_MASK) ? ORION_WR_LOW_EXT_BIT : 0) |
221c4ec7430SThomas Petazzoni ((w->wr_high & ORION_WR_HIGH_EXT_MASK) ? ORION_WR_HIGH_EXT_BIT : 0) |
222c4ec7430SThomas Petazzoni (r->badr_skew << ORION_BADR_SKEW_SHIFT) |
223c4ec7430SThomas Petazzoni ORION_RESERVED;
224c4ec7430SThomas Petazzoni
225c4ec7430SThomas Petazzoni writel(value, devbus->base);
226c4ec7430SThomas Petazzoni }
227c4ec7430SThomas Petazzoni
devbus_armada_set_timing_params(struct devbus * devbus,struct device_node * node,struct devbus_read_params * r,struct devbus_write_params * w)22830bd30b6SThomas Petazzoni static void devbus_armada_set_timing_params(struct devbus *devbus,
22930bd30b6SThomas Petazzoni struct device_node *node,
23030bd30b6SThomas Petazzoni struct devbus_read_params *r,
23130bd30b6SThomas Petazzoni struct devbus_write_params *w)
23230bd30b6SThomas Petazzoni {
23330bd30b6SThomas Petazzoni u32 value;
23430bd30b6SThomas Petazzoni
2353edad321SEzequiel Garcia /* Set read timings */
23630bd30b6SThomas Petazzoni value = r->bus_width << ARMADA_DEV_WIDTH_SHIFT |
23730bd30b6SThomas Petazzoni r->badr_skew << ARMADA_BADR_SKEW_SHIFT |
23830bd30b6SThomas Petazzoni r->rd_hold << ARMADA_RD_HOLD_SHIFT |
23930bd30b6SThomas Petazzoni r->acc_next << ARMADA_ACC_NEXT_SHIFT |
24030bd30b6SThomas Petazzoni r->rd_setup << ARMADA_RD_SETUP_SHIFT |
24130bd30b6SThomas Petazzoni r->acc_first << ARMADA_ACC_FIRST_SHIFT |
24230bd30b6SThomas Petazzoni r->turn_off;
2433edad321SEzequiel Garcia
2443edad321SEzequiel Garcia dev_dbg(devbus->dev, "read parameters register 0x%p = 0x%x\n",
24571e2e5d3SThomas Petazzoni devbus->base + ARMADA_READ_PARAM_OFFSET,
2463edad321SEzequiel Garcia value);
2473edad321SEzequiel Garcia
24871e2e5d3SThomas Petazzoni writel(value, devbus->base + ARMADA_READ_PARAM_OFFSET);
2493edad321SEzequiel Garcia
2503edad321SEzequiel Garcia /* Set write timings */
25130bd30b6SThomas Petazzoni value = w->sync_enable << ARMADA_SYNC_ENABLE_SHIFT |
25230bd30b6SThomas Petazzoni w->wr_low << ARMADA_WR_LOW_SHIFT |
25330bd30b6SThomas Petazzoni w->wr_high << ARMADA_WR_HIGH_SHIFT |
25430bd30b6SThomas Petazzoni w->ale_wr;
2553edad321SEzequiel Garcia
2563edad321SEzequiel Garcia dev_dbg(devbus->dev, "write parameters register: 0x%p = 0x%x\n",
25771e2e5d3SThomas Petazzoni devbus->base + ARMADA_WRITE_PARAM_OFFSET,
2583edad321SEzequiel Garcia value);
2593edad321SEzequiel Garcia
26071e2e5d3SThomas Petazzoni writel(value, devbus->base + ARMADA_WRITE_PARAM_OFFSET);
2613edad321SEzequiel Garcia }
2623edad321SEzequiel Garcia
mvebu_devbus_probe(struct platform_device * pdev)2633edad321SEzequiel Garcia static int mvebu_devbus_probe(struct platform_device *pdev)
2643edad321SEzequiel Garcia {
2653edad321SEzequiel Garcia struct device *dev = &pdev->dev;
2663edad321SEzequiel Garcia struct device_node *node = pdev->dev.of_node;
26730bd30b6SThomas Petazzoni struct devbus_read_params r;
26830bd30b6SThomas Petazzoni struct devbus_write_params w;
2693edad321SEzequiel Garcia struct devbus *devbus;
2703edad321SEzequiel Garcia struct clk *clk;
2713edad321SEzequiel Garcia unsigned long rate;
2729b6e4c0aSEzequiel Garcia int err;
2733edad321SEzequiel Garcia
2743edad321SEzequiel Garcia devbus = devm_kzalloc(&pdev->dev, sizeof(struct devbus), GFP_KERNEL);
2753edad321SEzequiel Garcia if (!devbus)
2763edad321SEzequiel Garcia return -ENOMEM;
2773edad321SEzequiel Garcia
2783edad321SEzequiel Garcia devbus->dev = dev;
279f3ba1c86SYangtao Li devbus->base = devm_platform_ioremap_resource(pdev, 0);
2803edad321SEzequiel Garcia if (IS_ERR(devbus->base))
2813edad321SEzequiel Garcia return PTR_ERR(devbus->base);
2823edad321SEzequiel Garcia
283*cb8fd6f7SGaosheng Cui clk = devm_clk_get_enabled(&pdev->dev, NULL);
2843edad321SEzequiel Garcia if (IS_ERR(clk))
2853edad321SEzequiel Garcia return PTR_ERR(clk);
2863edad321SEzequiel Garcia
2873edad321SEzequiel Garcia /*
2883edad321SEzequiel Garcia * Obtain clock period in picoseconds,
2893edad321SEzequiel Garcia * we need this in order to convert timing
2903edad321SEzequiel Garcia * parameters from cycles to picoseconds.
2913edad321SEzequiel Garcia */
2923edad321SEzequiel Garcia rate = clk_get_rate(clk) / 1000;
2933edad321SEzequiel Garcia devbus->tick_ps = 1000000000 / rate;
2943edad321SEzequiel Garcia
29530bd30b6SThomas Petazzoni dev_dbg(devbus->dev, "Setting timing parameter, tick is %lu ps\n",
29630bd30b6SThomas Petazzoni devbus->tick_ps);
29730bd30b6SThomas Petazzoni
2980456d330SThomas Petazzoni if (!of_property_read_bool(node, "devbus,keep-config")) {
29930bd30b6SThomas Petazzoni /* Read the Device Tree node */
30030bd30b6SThomas Petazzoni err = devbus_get_timing_params(devbus, node, &r, &w);
3013edad321SEzequiel Garcia if (err < 0)
3023edad321SEzequiel Garcia return err;
3033edad321SEzequiel Garcia
30430bd30b6SThomas Petazzoni /* Set the new timing parameters */
305c4ec7430SThomas Petazzoni if (of_device_is_compatible(node, "marvell,orion-devbus"))
306c4ec7430SThomas Petazzoni devbus_orion_set_timing_params(devbus, node, &r, &w);
307c4ec7430SThomas Petazzoni else
30830bd30b6SThomas Petazzoni devbus_armada_set_timing_params(devbus, node, &r, &w);
3090456d330SThomas Petazzoni }
31030bd30b6SThomas Petazzoni
3113edad321SEzequiel Garcia /*
3123edad321SEzequiel Garcia * We need to create a child device explicitly from here to
3133edad321SEzequiel Garcia * guarantee that the child will be probed after the timing
3143edad321SEzequiel Garcia * parameters for the bus are written.
3153edad321SEzequiel Garcia */
3163edad321SEzequiel Garcia err = of_platform_populate(node, NULL, NULL, dev);
3179b6e4c0aSEzequiel Garcia if (err < 0)
3183edad321SEzequiel Garcia return err;
3193edad321SEzequiel Garcia
3203edad321SEzequiel Garcia return 0;
3213edad321SEzequiel Garcia }
3223edad321SEzequiel Garcia
3233edad321SEzequiel Garcia static const struct of_device_id mvebu_devbus_of_match[] = {
3243edad321SEzequiel Garcia { .compatible = "marvell,mvebu-devbus" },
325c4ec7430SThomas Petazzoni { .compatible = "marvell,orion-devbus" },
3263edad321SEzequiel Garcia {},
3273edad321SEzequiel Garcia };
3283edad321SEzequiel Garcia MODULE_DEVICE_TABLE(of, mvebu_devbus_of_match);
3293edad321SEzequiel Garcia
3303edad321SEzequiel Garcia static struct platform_driver mvebu_devbus_driver = {
3313edad321SEzequiel Garcia .probe = mvebu_devbus_probe,
3323edad321SEzequiel Garcia .driver = {
3333edad321SEzequiel Garcia .name = "mvebu-devbus",
3343edad321SEzequiel Garcia .of_match_table = mvebu_devbus_of_match,
3353edad321SEzequiel Garcia },
3363edad321SEzequiel Garcia };
3373edad321SEzequiel Garcia
mvebu_devbus_init(void)3383edad321SEzequiel Garcia static int __init mvebu_devbus_init(void)
3393edad321SEzequiel Garcia {
3403edad321SEzequiel Garcia return platform_driver_register(&mvebu_devbus_driver);
3413edad321SEzequiel Garcia }
3423edad321SEzequiel Garcia module_init(mvebu_devbus_init);
3433edad321SEzequiel Garcia
3443edad321SEzequiel Garcia MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
3453edad321SEzequiel Garcia MODULE_DESCRIPTION("Marvell EBU SoC Device Bus controller");
346