xref: /openbmc/linux/arch/mips/bcm63xx/dev-enet.c (revision a09d2831)
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
7  */
8 
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/platform_device.h>
12 #include <bcm63xx_dev_enet.h>
13 #include <bcm63xx_io.h>
14 #include <bcm63xx_regs.h>
15 
16 static struct resource shared_res[] = {
17 	{
18 		.start		= -1, /* filled at runtime */
19 		.end		= -1, /* filled at runtime */
20 		.flags		= IORESOURCE_MEM,
21 	},
22 };
23 
24 static struct platform_device bcm63xx_enet_shared_device = {
25 	.name		= "bcm63xx_enet_shared",
26 	.id		= 0,
27 	.num_resources	= ARRAY_SIZE(shared_res),
28 	.resource	= shared_res,
29 };
30 
31 static int shared_device_registered;
32 
33 static struct resource enet0_res[] = {
34 	{
35 		.start		= -1, /* filled at runtime */
36 		.end		= -1, /* filled at runtime */
37 		.flags		= IORESOURCE_MEM,
38 	},
39 	{
40 		.start		= -1, /* filled at runtime */
41 		.flags		= IORESOURCE_IRQ,
42 	},
43 	{
44 		.start		= -1, /* filled at runtime */
45 		.flags		= IORESOURCE_IRQ,
46 	},
47 	{
48 		.start		= -1, /* filled at runtime */
49 		.flags		= IORESOURCE_IRQ,
50 	},
51 };
52 
53 static struct bcm63xx_enet_platform_data enet0_pd;
54 
55 static struct platform_device bcm63xx_enet0_device = {
56 	.name		= "bcm63xx_enet",
57 	.id		= 0,
58 	.num_resources	= ARRAY_SIZE(enet0_res),
59 	.resource	= enet0_res,
60 	.dev		= {
61 		.platform_data = &enet0_pd,
62 	},
63 };
64 
65 static struct resource enet1_res[] = {
66 	{
67 		.start		= -1, /* filled at runtime */
68 		.end		= -1, /* filled at runtime */
69 		.flags		= IORESOURCE_MEM,
70 	},
71 	{
72 		.start		= -1, /* filled at runtime */
73 		.flags		= IORESOURCE_IRQ,
74 	},
75 	{
76 		.start		= -1, /* filled at runtime */
77 		.flags		= IORESOURCE_IRQ,
78 	},
79 	{
80 		.start		= -1, /* filled at runtime */
81 		.flags		= IORESOURCE_IRQ,
82 	},
83 };
84 
85 static struct bcm63xx_enet_platform_data enet1_pd;
86 
87 static struct platform_device bcm63xx_enet1_device = {
88 	.name		= "bcm63xx_enet",
89 	.id		= 1,
90 	.num_resources	= ARRAY_SIZE(enet1_res),
91 	.resource	= enet1_res,
92 	.dev		= {
93 		.platform_data = &enet1_pd,
94 	},
95 };
96 
97 int __init bcm63xx_enet_register(int unit,
98 				 const struct bcm63xx_enet_platform_data *pd)
99 {
100 	struct platform_device *pdev;
101 	struct bcm63xx_enet_platform_data *dpd;
102 	int ret;
103 
104 	if (unit > 1)
105 		return -ENODEV;
106 
107 	if (!shared_device_registered) {
108 		shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
109 		shared_res[0].end = shared_res[0].start;
110 		if (BCMCPU_IS_6338())
111 			shared_res[0].end += (RSET_ENETDMA_SIZE / 2)  - 1;
112 		else
113 			shared_res[0].end += (RSET_ENETDMA_SIZE)  - 1;
114 
115 		ret = platform_device_register(&bcm63xx_enet_shared_device);
116 		if (ret)
117 			return ret;
118 		shared_device_registered = 1;
119 	}
120 
121 	if (unit == 0) {
122 		enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0);
123 		enet0_res[0].end = enet0_res[0].start;
124 		enet0_res[0].end += RSET_ENET_SIZE - 1;
125 		enet0_res[1].start = bcm63xx_get_irq_number(IRQ_ENET0);
126 		enet0_res[2].start = bcm63xx_get_irq_number(IRQ_ENET0_RXDMA);
127 		enet0_res[3].start = bcm63xx_get_irq_number(IRQ_ENET0_TXDMA);
128 		pdev = &bcm63xx_enet0_device;
129 	} else {
130 		enet1_res[0].start = bcm63xx_regset_address(RSET_ENET1);
131 		enet1_res[0].end = enet1_res[0].start;
132 		enet1_res[0].end += RSET_ENET_SIZE - 1;
133 		enet1_res[1].start = bcm63xx_get_irq_number(IRQ_ENET1);
134 		enet1_res[2].start = bcm63xx_get_irq_number(IRQ_ENET1_RXDMA);
135 		enet1_res[3].start = bcm63xx_get_irq_number(IRQ_ENET1_TXDMA);
136 		pdev = &bcm63xx_enet1_device;
137 	}
138 
139 	/* copy given platform data */
140 	dpd = pdev->dev.platform_data;
141 	memcpy(dpd, pd, sizeof(*pd));
142 
143 	/* adjust them in case internal phy is used */
144 	if (dpd->use_internal_phy) {
145 
146 		/* internal phy only exists for enet0 */
147 		if (unit == 1)
148 			return -ENODEV;
149 
150 		dpd->phy_id = 1;
151 		dpd->has_phy_interrupt = 1;
152 		dpd->phy_interrupt = bcm63xx_get_irq_number(IRQ_ENET_PHY);
153 	}
154 
155 	ret = platform_device_register(pdev);
156 	if (ret)
157 		return ret;
158 	return 0;
159 }
160