add new target 'oxnas'
[openwrt.git] / target / linux / oxnas / files / arch / arm / mach-oxnas / mach-ox820.c
1 #include <linux/init.h>
2 #include <linux/kernel.h>
3 #include <linux/bug.h>
4 #include <linux/of_platform.h>
5 #include <linux/clocksource.h>
6 #include <linux/clk-provider.h>
7 #include <linux/clk.h>
8 #include <linux/stmmac.h>
9 #include <linux/slab.h>
10 #include <linux/gfp.h>
11 #include <linux/reset.h>
12 #include <asm/mach-types.h>
13 #include <asm/mach/map.h>
14 #include <asm/mach/arch.h>
15 #include <asm/page.h>
16 #include <mach/iomap.h>
17 #include <mach/hardware.h>
18 #include <mach/utils.h>
19 #include <mach/smp.h>
20
21 static struct map_desc ox820_io_desc[] __initdata = {
22         {
23                 .virtual = (unsigned long)OXNAS_PERCPU_BASE_VA,
24                 .pfn = __phys_to_pfn(OXNAS_PERCPU_BASE),
25                 .length = OXNAS_PERCPU_SIZE,
26                 .type = MT_DEVICE,
27         },
28         {
29                 .virtual = (unsigned long)OXNAS_SYSCRTL_BASE_VA,
30                 .pfn = __phys_to_pfn(OXNAS_SYSCRTL_BASE),
31                 .length = OXNAS_SYSCRTL_SIZE,
32                 .type = MT_DEVICE,
33         },
34         {
35                 .virtual = (unsigned long)OXNAS_SECCRTL_BASE_VA,
36                 .pfn = __phys_to_pfn(OXNAS_SECCRTL_BASE),
37                 .length = OXNAS_SECCRTL_SIZE,
38                 .type = MT_DEVICE,
39         },
40         {
41                 .virtual = (unsigned long)OXNAS_RPSA_BASE_VA,
42                 .pfn = __phys_to_pfn(OXNAS_RPSA_BASE),
43                 .length = OXNAS_RPSA_SIZE,
44                 .type = MT_DEVICE,
45         },
46         {
47                 .virtual = (unsigned long)OXNAS_RPSC_BASE_VA,
48                 .pfn = __phys_to_pfn(OXNAS_RPSC_BASE),
49                 .length = OXNAS_RPSC_SIZE,
50                 .type = MT_DEVICE,
51         },
52 };
53
54 void __init ox820_map_common_io(void)
55 {
56         debug_ll_io_init();
57         iotable_init(ox820_io_desc, ARRAY_SIZE(ox820_io_desc));
58 }
59
60 struct plat_gmac_data {
61         struct plat_stmmacenet_data stmmac;
62         struct clk *clk;
63 };
64
65 void *ox820_gmac_setup(struct platform_device *pdev)
66 {
67         struct plat_gmac_data *pdata = pdev->dev.platform_data;
68
69         pdata->clk = clk_get(&pdev->dev, "gmac");
70         return (void *) pdata->clk;
71 };
72
73 int ox820_gmac_init(struct platform_device *pdev, void *priv)
74 {
75         int ret;
76         unsigned value;
77
78         ret = device_reset(&pdev->dev);
79         if (ret)
80                 return ret;
81
82         if (IS_ERR(priv))
83                 return PTR_ERR(priv);
84         clk_prepare_enable(priv);
85
86         value = readl(SYS_CTRL_GMAC_CTRL);
87
88         /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */
89         value |= BIT(SYS_CTRL_GMAC_CKEN_GTX);
90         /* Use simple mux for 25/125 Mhz clock switching */
91         value |= BIT(SYS_CTRL_GMAC_SIMPLE_MUX);
92         /* set auto switch tx clock source */
93         value |= BIT(SYS_CTRL_GMAC_AUTO_TX_SOURCE);
94         /* enable tx & rx vardelay */
95         value |= BIT(SYS_CTRL_GMAC_CKEN_TX_OUT);
96         value |= BIT(SYS_CTRL_GMAC_CKEN_TXN_OUT);
97         value |= BIT(SYS_CTRL_GMAC_CKEN_TX_IN);
98         value |= BIT(SYS_CTRL_GMAC_CKEN_RX_OUT);
99         value |= BIT(SYS_CTRL_GMAC_CKEN_RXN_OUT);
100         value |= BIT(SYS_CTRL_GMAC_CKEN_RX_IN);
101         writel(value, SYS_CTRL_GMAC_CTRL);
102
103         /* set tx & rx vardelay */
104         value = 0;
105         value |= SYS_CTRL_GMAC_TX_VARDELAY(4);
106         value |= SYS_CTRL_GMAC_TXN_VARDELAY(2);
107         value |= SYS_CTRL_GMAC_RX_VARDELAY(10);
108         value |= SYS_CTRL_GMAC_RXN_VARDELAY(8);
109         writel(value, SYS_CTRL_GMAC_DELAY_CTRL);
110
111         return 0;
112 }
113
114 void ox820_gmac_exit(struct platform_device *pdev, void *priv)
115 {
116         struct reset_control *rstc;
117
118         clk_disable_unprepare(priv);
119         clk_put(priv);
120
121         rstc = reset_control_get(&pdev->dev, NULL);
122         if (!IS_ERR(rstc)) {
123                 reset_control_assert(rstc);
124                 reset_control_put(rstc);
125         }
126 }
127
128 static int __init ox820_ether_init(void)
129 {
130         struct device_node *node;
131         struct platform_device *pdev;
132         struct plat_gmac_data *pdata;
133
134         node = of_find_compatible_node(NULL, NULL, "plxtech,nas782x-gmac");
135         if (!node)
136                 return -ENOENT;
137
138         pdev = of_find_device_by_node(node);
139         of_node_put(node);
140
141         if (!pdev)
142                 return -EINVAL;
143
144         pdata = kzalloc(sizeof(struct plat_gmac_data), GFP_KERNEL);
145         if (!pdata)
146                 return -ENOMEM;
147
148         pdata->stmmac.setup = ox820_gmac_setup;
149         pdata->stmmac.init = ox820_gmac_init;
150         pdata->stmmac.exit = ox820_gmac_exit;
151         pdev->dev.platform_data = pdata;
152
153         return 0;
154 }
155
156 static void __init ox820_dt_init(void)
157 {
158         int ret;
159
160         ret = of_platform_populate(NULL, of_default_bus_match_table, NULL,
161                                         NULL);
162
163         if (ret) {
164                 pr_err("of_platform_populate failed: %d\n", ret);
165                 BUG();
166         }
167
168         ret = ox820_ether_init();
169
170         if (ret)
171                 pr_info("ox820_ether_init failed: %d\n", ret);
172 }
173
174 static void __init ox820_timer_init(void)
175 {
176         of_clk_init(NULL);
177         clocksource_of_init();
178 }
179
180 void ox820_init_early(void)
181 {
182
183 }
184
185 void ox820_assert_system_reset(enum reboot_mode mode, const char *cmd)
186 {
187         u32 value;
188
189 /* Assert reset to cores as per power on defaults
190  * Don't touch the DDR interface as things will come to an impromptu stop
191  * NB Possibly should be asserting reset for PLLB, but there are timing
192  *    concerns here according to the docs */
193         value = BIT(SYS_CTRL_RST_COPRO)         |
194                 BIT(SYS_CTRL_RST_USBHS)         |
195                 BIT(SYS_CTRL_RST_USBHSPHYA)     |
196                 BIT(SYS_CTRL_RST_MACA)          |
197                 BIT(SYS_CTRL_RST_PCIEA)         |
198                 BIT(SYS_CTRL_RST_SGDMA)         |
199                 BIT(SYS_CTRL_RST_CIPHER)        |
200                 BIT(SYS_CTRL_RST_SATA)          |
201                 BIT(SYS_CTRL_RST_SATA_LINK)     |
202                 BIT(SYS_CTRL_RST_SATA_PHY)      |
203                 BIT(SYS_CTRL_RST_PCIEPHY)       |
204                 BIT(SYS_CTRL_RST_STATIC)        |
205                 BIT(SYS_CTRL_RST_UART1)         |
206                 BIT(SYS_CTRL_RST_UART2)         |
207                 BIT(SYS_CTRL_RST_MISC)          |
208                 BIT(SYS_CTRL_RST_I2S)           |
209                 BIT(SYS_CTRL_RST_SD)            |
210                 BIT(SYS_CTRL_RST_MACB)          |
211                 BIT(SYS_CTRL_RST_PCIEB)         |
212                 BIT(SYS_CTRL_RST_VIDEO)         |
213                 BIT(SYS_CTRL_RST_USBHSPHYB)     |
214                 BIT(SYS_CTRL_RST_USBDEV);
215
216         writel(value, SYS_CTRL_RST_SET_CTRL);
217
218         /* Release reset to cores as per power on defaults */
219         writel(BIT(SYS_CTRL_RST_GPIO), SYS_CTRL_RST_CLR_CTRL);
220
221         /* Disable clocks to cores as per power-on defaults - must leave DDR
222          * related clocks enabled otherwise we'll stop rather abruptly. */
223         value =
224                 BIT(SYS_CTRL_CLK_COPRO)         |
225                 BIT(SYS_CTRL_CLK_DMA)           |
226                 BIT(SYS_CTRL_CLK_CIPHER)        |
227                 BIT(SYS_CTRL_CLK_SD)            |
228                 BIT(SYS_CTRL_CLK_SATA)          |
229                 BIT(SYS_CTRL_CLK_I2S)           |
230                 BIT(SYS_CTRL_CLK_USBHS)         |
231                 BIT(SYS_CTRL_CLK_MAC)           |
232                 BIT(SYS_CTRL_CLK_PCIEA)         |
233                 BIT(SYS_CTRL_CLK_STATIC)        |
234                 BIT(SYS_CTRL_CLK_MACB)          |
235                 BIT(SYS_CTRL_CLK_PCIEB)         |
236                 BIT(SYS_CTRL_CLK_REF600)        |
237                 BIT(SYS_CTRL_CLK_USBDEV);
238
239         writel(value, SYS_CTRL_CLK_CLR_CTRL);
240
241         /* Enable clocks to cores as per power-on defaults */
242
243         /* Set sys-control pin mux'ing as per power-on defaults */
244         writel(0, SYS_CTRL_SECONDARY_SEL);
245         writel(0, SYS_CTRL_TERTIARY_SEL);
246         writel(0, SYS_CTRL_QUATERNARY_SEL);
247         writel(0, SYS_CTRL_DEBUG_SEL);
248         writel(0, SYS_CTRL_ALTERNATIVE_SEL);
249         writel(0, SYS_CTRL_PULLUP_SEL);
250
251         writel(0, SYS_CTRL_SECONDARY_SEL);
252         writel(0, SYS_CTRL_TERTIARY_SEL);
253         writel(0, SYS_CTRL_QUATERNARY_SEL);
254         writel(0, SYS_CTRL_DEBUG_SEL);
255         writel(0, SYS_CTRL_ALTERNATIVE_SEL);
256         writel(0, SYS_CTRL_PULLUP_SEL);
257
258         /* No need to save any state, as the ROM loader can determine whether
259          * reset is due to power cycling or programatic action, just hit the
260          * (self-clearing) CPU reset bit of the block reset register */
261         value =
262                 BIT(SYS_CTRL_RST_SCU) |
263                 BIT(SYS_CTRL_RST_ARM0) |
264                 BIT(SYS_CTRL_RST_ARM1);
265
266         writel(value, SYS_CTRL_RST_SET_CTRL);
267 }
268
269 static const char * const ox820_dt_board_compat[] = {
270         "plxtech,nas7820",
271         "plxtech,nas7821",
272         "plxtech,nas7825",
273         NULL
274 };
275
276 DT_MACHINE_START(OX820_DT, "PLXTECH NAS782X SoC (Flattened Device Tree)")
277         .map_io         = ox820_map_common_io,
278         .smp            = smp_ops(ox820_smp_ops),
279         .init_early     = ox820_init_early,
280         .init_time      = ox820_timer_init,
281         .init_machine   = ox820_dt_init,
282         .restart        = ox820_assert_system_reset,
283         .dt_compat      = ox820_dt_board_compat,
284 MACHINE_END