aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2013-03-14 17:27:32 -0400
committerArnd Bergmann <arnd@arndb.de>2013-03-14 17:30:21 -0400
commit415f59142d9d9dd023deaeb3b4dfc1aecdd3983c (patch)
tree3d74c3a5b87dea625ca328897751c3253594ae68
parent15bc1fe67f66644c8093cc2d3304217d1c7de797 (diff)
ARM: cns3xxx: initial DT support
This adds very minimal support for booting cns3xxx using a device tree. It should support the same devices that cns3420vb provides but gets them from the DT. All devices that don't have their own binding are probed through auxdata. This is completely untested and likely incomplete. Booting through ATAGS is made optional, so it can be turned off by anybody who has a DTB file. Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--arch/arm/mach-cns3xxx/Kconfig1
-rw-r--r--arch/arm/mach-cns3xxx/Makefile8
-rw-r--r--arch/arm/mach-cns3xxx/core.c119
3 files changed, 125 insertions, 3 deletions
diff --git a/arch/arm/mach-cns3xxx/Kconfig b/arch/arm/mach-cns3xxx/Kconfig
index 5720f3df1af2..dbf0df8bb0ac 100644
--- a/arch/arm/mach-cns3xxx/Kconfig
+++ b/arch/arm/mach-cns3xxx/Kconfig
@@ -14,6 +14,7 @@ menu "CNS3XXX platform type"
14 14
15config MACH_CNS3420VB 15config MACH_CNS3420VB
16 bool "Support for CNS3420 Validation Board" 16 bool "Support for CNS3420 Validation Board"
17 depends on ATAGS
17 help 18 help
18 Include support for the Cavium Networks CNS3420 MPCore Platform 19 Include support for the Cavium Networks CNS3420 MPCore Platform
19 Baseboard. 20 Baseboard.
diff --git a/arch/arm/mach-cns3xxx/Makefile b/arch/arm/mach-cns3xxx/Makefile
index 11033f1c2e23..a1ff10848698 100644
--- a/arch/arm/mach-cns3xxx/Makefile
+++ b/arch/arm/mach-cns3xxx/Makefile
@@ -1,3 +1,5 @@
1obj-$(CONFIG_ARCH_CNS3XXX) += core.o pm.o devices.o 1obj-$(CONFIG_ARCH_CNS3XXX) += cns3xxx.o
2obj-$(CONFIG_PCI) += pcie.o 2cns3xxx-y += core.o pm.o
3obj-$(CONFIG_MACH_CNS3420VB) += cns3420vb.o 3cns3xxx-$(CONFIG_ATAGS) += devices.o
4cns3xxx-$(CONFIG_PCI) += pcie.o
5cns3xxx-$(CONFIG_MACH_CNS3420VB) += cns3420vb.o
diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c
index 012ffdb9e142..49e657c15067 100644
--- a/arch/arm/mach-cns3xxx/core.c
+++ b/arch/arm/mach-cns3xxx/core.c
@@ -13,12 +13,18 @@
13#include <linux/clockchips.h> 13#include <linux/clockchips.h>
14#include <linux/io.h> 14#include <linux/io.h>
15#include <linux/irqchip/arm-gic.h> 15#include <linux/irqchip/arm-gic.h>
16#include <linux/of_platform.h>
17#include <linux/platform_device.h>
18#include <linux/usb/ehci_pdriver.h>
19#include <linux/usb/ohci_pdriver.h>
20#include <asm/mach/arch.h>
16#include <asm/mach/map.h> 21#include <asm/mach/map.h>
17#include <asm/mach/time.h> 22#include <asm/mach/time.h>
18#include <asm/mach/irq.h> 23#include <asm/mach/irq.h>
19#include <asm/hardware/cache-l2x0.h> 24#include <asm/hardware/cache-l2x0.h>
20#include "cns3xxx.h" 25#include "cns3xxx.h"
21#include "core.h" 26#include "core.h"
27#include "pm.h"
22 28
23static struct map_desc cns3xxx_io_desc[] __initdata = { 29static struct map_desc cns3xxx_io_desc[] __initdata = {
24 { 30 {
@@ -276,3 +282,116 @@ void __init cns3xxx_l2x0_init(void)
276} 282}
277 283
278#endif /* CONFIG_CACHE_L2X0 */ 284#endif /* CONFIG_CACHE_L2X0 */
285
286static int csn3xxx_usb_power_on(struct platform_device *pdev)
287{
288 /*
289 * EHCI and OHCI share the same clock and power,
290 * resetting twice would cause the 1st controller been reset.
291 * Therefore only do power up at the first up device, and
292 * power down at the last down device.
293 *
294 * Set USB AHB INCR length to 16
295 */
296 if (atomic_inc_return(&usb_pwr_ref) == 1) {
297 cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
298 cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
299 cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
300 __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
301 MISC_CHIP_CONFIG_REG);
302 }
303
304 return 0;
305}
306
307static void csn3xxx_usb_power_off(struct platform_device *pdev)
308{
309 /*
310 * EHCI and OHCI share the same clock and power,
311 * resetting twice would cause the 1st controller been reset.
312 * Therefore only do power up at the first up device, and
313 * power down at the last down device.
314 */
315 if (atomic_dec_return(&usb_pwr_ref) == 0)
316 cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
317}
318
319static struct usb_ehci_pdata cns3xxx_usb_ehci_pdata = {
320 .power_on = csn3xxx_usb_power_on,
321 .power_off = csn3xxx_usb_power_off,
322};
323
324static struct usb_ohci_pdata cns3xxx_usb_ohci_pdata = {
325 .num_ports = 1,
326 .power_on = csn3xxx_usb_power_on,
327 .power_off = csn3xxx_usb_power_off,
328};
329
330static struct of_dev_auxdata cns3xxx_auxdata[] __initconst = {
331 { "intel,usb-ehci", CNS3XXX_USB_BASE, "ehci-platform", &cns3xxx_usb_ehci_pdata },
332 { "intel,usb-ohci", CNS3XXX_USB_OHCI_BASE, "ohci-platform", &cns3xxx_usb_ohci_pdata },
333 { "cavium,cns3420-ahci", CNS3XXX_SATA2_BASE, "ahci", NULL },
334 { "cavium,cns3420-sdhci", CNS3XXX_SDIO_BASE, "ahci", NULL },
335 {},
336};
337
338static void __init cns3xxx_init(void)
339{
340 struct device_node *dn;
341
342 cns3xxx_l2x0_init();
343
344 dn = of_find_compatible_node(NULL, NULL, "cavium,cns3420-ahci");
345 if (of_device_is_available(dn)) {
346 u32 tmp;
347
348 tmp = __raw_readl(MISC_SATA_POWER_MODE);
349 tmp |= 0x1 << 16; /* Disable SATA PHY 0 from SLUMBER Mode */
350 tmp |= 0x1 << 17; /* Disable SATA PHY 1 from SLUMBER Mode */
351 __raw_writel(tmp, MISC_SATA_POWER_MODE);
352
353 /* Enable SATA PHY */
354 cns3xxx_pwr_power_up(0x1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY0);
355 cns3xxx_pwr_power_up(0x1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY1);
356
357 /* Enable SATA Clock */
358 cns3xxx_pwr_clk_en(0x1 << PM_CLK_GATE_REG_OFFSET_SATA);
359
360 /* De-Asscer SATA Reset */
361 cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SATA));
362 }
363
364 dn = of_find_compatible_node(NULL, NULL, "cavium,cns3420-sdhci");
365 if (of_device_is_available(dn)) {
366 u32 __iomem *gpioa = IOMEM(CNS3XXX_MISC_BASE_VIRT + 0x0014);
367 u32 gpioa_pins = __raw_readl(gpioa);
368
369 /* MMC/SD pins share with GPIOA */
370 gpioa_pins |= 0x1fff0004;
371 __raw_writel(gpioa_pins, gpioa);
372
373 cns3xxx_pwr_clk_en(CNS3XXX_PWR_CLK_EN(SDIO));
374 cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SDIO));
375 }
376
377 pm_power_off = cns3xxx_power_off;
378
379 of_platform_populate(NULL, of_default_bus_match_table,
380 cns3xxx_auxdata, NULL);
381}
382
383static const char *cns3xxx_dt_compat[] __initdata = {
384 "cavium,cns3410",
385 "cavium,cns3420",
386 NULL,
387};
388
389DT_MACHINE_START(CNS3XXX_DT, "Cavium Networks CNS3xxx")
390 .dt_compat = cns3xxx_dt_compat,
391 .nr_irqs = NR_IRQS_CNS3XXX,
392 .map_io = cns3xxx_map_io,
393 .init_irq = cns3xxx_init_irq,
394 .init_time = cns3xxx_timer_init,
395 .init_machine = cns3xxx_init,
396 .restart = cns3xxx_restart,
397MACHINE_END