[brcm63xx] add infrastructure to register gpio-input reset button
[openwrt.git] / target / linux / brcm63xx / files / arch / mips / bcm63xx / dev-enet.c
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 = 0;
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                 .start          = IRQ_ENET0_RXDMA,
46                 .flags          = IORESOURCE_IRQ,
47         },
48         {
49                 .start          = -1, /* filled at runtime */
50                 .start          = IRQ_ENET0_TXDMA,
51                 .flags          = IORESOURCE_IRQ,
52         },
53 };
54
55 static struct bcm63xx_enet_platform_data enet0_pd;
56
57 static struct platform_device bcm63xx_enet0_device = {
58         .name           = "bcm63xx_enet",
59         .id             = 0,
60         .num_resources  = ARRAY_SIZE(enet0_res),
61         .resource       = enet0_res,
62         .dev            = {
63                 .platform_data = &enet0_pd,
64         },
65 };
66
67 static struct resource enet1_res[] = {
68         {
69                 .start          = -1, /* filled at runtime */
70                 .end            = -1, /* filled at runtime */
71                 .flags          = IORESOURCE_MEM,
72         },
73         {
74                 .start          = -1, /* filled at runtime */
75                 .flags          = IORESOURCE_IRQ,
76         },
77         {
78                 .start          = -1, /* filled at runtime */
79                 .flags          = IORESOURCE_IRQ,
80         },
81         {
82                 .start          = -1, /* filled at runtime */
83                 .flags          = IORESOURCE_IRQ,
84         },
85 };
86
87 static struct bcm63xx_enet_platform_data enet1_pd;
88
89 static struct platform_device bcm63xx_enet1_device = {
90         .name           = "bcm63xx_enet",
91         .id             = 1,
92         .num_resources  = ARRAY_SIZE(enet1_res),
93         .resource       = enet1_res,
94         .dev            = {
95                 .platform_data = &enet1_pd,
96         },
97 };
98
99 int __init bcm63xx_enet_register(int unit,
100                                  const struct bcm63xx_enet_platform_data *pd)
101 {
102         struct platform_device *pdev;
103         struct bcm63xx_enet_platform_data *dpd;
104         int ret;
105
106         if (unit > 1)
107                 return -ENODEV;
108
109         if (!shared_device_registered) {
110                 shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
111                 shared_res[0].end = shared_res[0].start;
112                 if (BCMCPU_IS_6338())
113                         shared_res[0].end += (RSET_ENETDMA_SIZE / 2)  - 1;
114                 else
115                         shared_res[0].end += (RSET_ENETDMA_SIZE)  - 1;
116
117                 ret = platform_device_register(&bcm63xx_enet_shared_device);
118                 if (ret)
119                         return ret;
120                 shared_device_registered = 1;
121         }
122
123         if (unit == 0) {
124                 enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0);
125                 enet0_res[0].end = enet0_res[0].start;
126                 enet0_res[0].end += RSET_ENET_SIZE - 1;
127                 enet0_res[1].start = bcm63xx_get_irq_number(IRQ_ENET0);
128                 enet0_res[2].start = bcm63xx_get_irq_number(IRQ_ENET0_RXDMA);
129                 enet0_res[3].start = bcm63xx_get_irq_number(IRQ_ENET0_TXDMA);
130                 pdev = &bcm63xx_enet0_device;
131         } else {
132                 enet1_res[0].start = bcm63xx_regset_address(RSET_ENET1);
133                 enet1_res[0].end = enet1_res[0].start;
134                 enet1_res[0].end += RSET_ENET_SIZE - 1;
135                 enet1_res[1].start = bcm63xx_get_irq_number(IRQ_ENET1);
136                 enet1_res[2].start = bcm63xx_get_irq_number(IRQ_ENET1_RXDMA);
137                 enet1_res[3].start = bcm63xx_get_irq_number(IRQ_ENET1_TXDMA);
138                 pdev = &bcm63xx_enet1_device;
139         }
140
141         /* copy given platform data */
142         dpd = pdev->dev.platform_data;
143         memcpy(dpd, pd, sizeof (*pd));
144
145         /* adjust them in case internal phy is used */
146         if (dpd->use_internal_phy) {
147
148                 /* internal phy only exists for enet0 */
149                 if (unit == 1)
150                         return -ENODEV;
151
152                 dpd->phy_id = 1;
153                 dpd->has_phy_interrupt = 1;
154                 dpd->phy_interrupt = bcm63xx_get_irq_number(IRQ_ENET_PHY);
155         }
156
157         ret = platform_device_register(pdev);
158         if (ret)
159                 return ret;
160         return 0;
161 }