| /* | 
 |  * linux/arch/arm/mach-tcc8k/devices.c | 
 |  * | 
 |  * Copyright (C) Telechips, Inc. | 
 |  * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de> | 
 |  * | 
 |  * Licensed under the terms of GPL v2. | 
 |  * | 
 |  */ | 
 |  | 
 | #include <linux/dma-mapping.h> | 
 | #include <linux/init.h> | 
 | #include <linux/io.h> | 
 | #include <linux/kernel.h> | 
 | #include <linux/module.h> | 
 |  | 
 | #include <asm/mach/map.h> | 
 |  | 
 | #include <mach/tcc8k-regs.h> | 
 | #include <mach/irqs.h> | 
 |  | 
 | #include "common.h" | 
 |  | 
 | static u64 tcc8k_dmamask = DMA_BIT_MASK(32); | 
 |  | 
 | #ifdef CONFIG_MTD_NAND_TCC | 
 | /* NAND controller */ | 
 | static struct resource tcc_nand_resources[] = { | 
 | 	{ | 
 | 		.start	= (resource_size_t)NFC_BASE, | 
 | 		.end	= (resource_size_t)NFC_BASE + 0x7f, | 
 | 		.flags	= IORESOURCE_MEM, | 
 | 	}, { | 
 | 		.start	= INT_NFC, | 
 | 		.end	= INT_NFC, | 
 | 		.flags	= IORESOURCE_IRQ, | 
 | 	}, | 
 | }; | 
 |  | 
 | struct platform_device tcc_nand_device = { | 
 | 	.name = "tcc_nand", | 
 | 	.id = 0, | 
 | 	.num_resources = ARRAY_SIZE(tcc_nand_resources), | 
 | 	.resource = tcc_nand_resources, | 
 | }; | 
 | #endif | 
 |  | 
 | #ifdef CONFIG_MMC_TCC8K | 
 | /* MMC controller */ | 
 | static struct resource tcc8k_mmc0_resource[] = { | 
 | 	{ | 
 | 		.start = INT_SD0, | 
 | 		.end   = INT_SD0, | 
 | 		.flags = IORESOURCE_IRQ, | 
 | 	}, | 
 | }; | 
 |  | 
 | static struct resource tcc8k_mmc1_resource[] = { | 
 | 	{ | 
 | 		.start = INT_SD1, | 
 | 		.end   = INT_SD1, | 
 | 		.flags = IORESOURCE_IRQ, | 
 | 	}, | 
 | }; | 
 |  | 
 | struct platform_device tcc8k_mmc0_device = { | 
 | 	.name		= "tcc-mmc", | 
 | 	.id		= 0, | 
 | 	.num_resources	= ARRAY_SIZE(tcc8k_mmc0_resource), | 
 | 	.resource	= tcc8k_mmc0_resource, | 
 | 	.dev		= { | 
 | 		.dma_mask		= &tcc8k_dmamask, | 
 | 		.coherent_dma_mask	= DMA_BIT_MASK(32), | 
 | 	} | 
 | }; | 
 |  | 
 | struct platform_device tcc8k_mmc1_device = { | 
 | 	.name		= "tcc-mmc", | 
 | 	.id		= 1, | 
 | 	.num_resources	= ARRAY_SIZE(tcc8k_mmc1_resource), | 
 | 	.resource	= tcc8k_mmc1_resource, | 
 | 	.dev		= { | 
 | 		.dma_mask		= &tcc8k_dmamask, | 
 | 		.coherent_dma_mask	= DMA_BIT_MASK(32), | 
 | 	} | 
 | }; | 
 |  | 
 | static inline void tcc8k_init_mmc(void) | 
 | { | 
 | 	u32 reg = __raw_readl(GPIOPS_BASE + GPIOPS_FS1_OFFS); | 
 |  | 
 | 	reg |= GPIOPS_FS1_SDH0_BITS | GPIOPS_FS1_SDH1_BITS; | 
 | 	__raw_writel(reg, GPIOPS_BASE + GPIOPS_FS1_OFFS); | 
 |  | 
 | 	platform_device_register(&tcc8k_mmc0_device); | 
 | 	platform_device_register(&tcc8k_mmc1_device); | 
 | } | 
 | #else | 
 | static inline void tcc8k_init_mmc(void) { } | 
 | #endif | 
 |  | 
 | #ifdef CONFIG_USB_OHCI_HCD | 
 | static int tcc8k_ohci_init(struct device *dev) | 
 | { | 
 | 	u32 reg; | 
 |  | 
 | 	/* Use GPIO PK19 as VBUS control output */ | 
 | 	reg = __raw_readl(GPIOPK_BASE + GPIOPK_FS0_OFFS); | 
 | 	reg &= ~(1 << 19); | 
 | 	__raw_writel(reg, GPIOPK_BASE + GPIOPK_FS0_OFFS); | 
 | 	reg = __raw_readl(GPIOPK_BASE + GPIOPK_FS1_OFFS); | 
 | 	reg &= ~(1 << 19); | 
 | 	__raw_writel(reg, GPIOPK_BASE + GPIOPK_FS1_OFFS); | 
 |  | 
 | 	reg = __raw_readl(GPIOPK_BASE + GPIOPK_DOE_OFFS); | 
 | 	reg |= (1 << 19); | 
 | 	__raw_writel(reg, GPIOPK_BASE + GPIOPK_DOE_OFFS); | 
 | 	/* Turn on VBUS */ | 
 | 	reg = __raw_readl(GPIOPK_BASE + GPIOPK_DAT_OFFS); | 
 | 	reg |= (1 << 19); | 
 | 	__raw_writel(reg, GPIOPK_BASE + GPIOPK_DAT_OFFS); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static struct resource tcc8k_ohci0_resources[] = { | 
 | 	[0] = { | 
 | 		.start = (resource_size_t)USBH0_BASE, | 
 | 		.end   = (resource_size_t)USBH0_BASE + 0x5c, | 
 | 		.flags = IORESOURCE_MEM, | 
 | 	}, | 
 | 	[1] = { | 
 | 		.start = INT_USBH0, | 
 | 		.end   = INT_USBH0, | 
 | 		.flags = IORESOURCE_IRQ, | 
 | 	} | 
 | }; | 
 |  | 
 | static struct resource tcc8k_ohci1_resources[] = { | 
 | 	[0] = { | 
 | 		.start = (resource_size_t)USBH1_BASE, | 
 | 		.end   = (resource_size_t)USBH1_BASE + 0x5c, | 
 | 		.flags = IORESOURCE_MEM, | 
 | 	}, | 
 | 	[1] = { | 
 | 		.start = INT_USBH1, | 
 | 		.end   = INT_USBH1, | 
 | 		.flags = IORESOURCE_IRQ, | 
 | 	} | 
 | }; | 
 |  | 
 | static struct tccohci_platform_data tcc8k_ohci0_platform_data = { | 
 | 	.controller	= 0, | 
 | 	.port_mode	= PMM_PERPORT_MODE, | 
 | 	.init		= tcc8k_ohci_init, | 
 | }; | 
 |  | 
 | static struct tccohci_platform_data tcc8k_ohci1_platform_data = { | 
 | 	.controller	= 1, | 
 | 	.port_mode	= PMM_PERPORT_MODE, | 
 | 	.init		= tcc8k_ohci_init, | 
 | }; | 
 |  | 
 | static struct platform_device ohci0_device = { | 
 | 	.name = "tcc-ohci", | 
 | 	.id = 0, | 
 | 	.dev = { | 
 | 		.dma_mask = &tcc8k_dmamask, | 
 | 		.coherent_dma_mask = DMA_BIT_MASK(32), | 
 | 		.platform_data = &tcc8k_ohci0_platform_data, | 
 | 	}, | 
 | 	.num_resources  = ARRAY_SIZE(tcc8k_ohci0_resources), | 
 | 	.resource       = tcc8k_ohci0_resources, | 
 | }; | 
 |  | 
 | static struct platform_device ohci1_device = { | 
 | 	.name = "tcc-ohci", | 
 | 	.id = 1, | 
 | 	.dev = { | 
 | 		.dma_mask = &tcc8k_dmamask, | 
 | 		.coherent_dma_mask = DMA_BIT_MASK(32), | 
 | 		.platform_data = &tcc8k_ohci1_platform_data, | 
 | 	}, | 
 | 	.num_resources  = ARRAY_SIZE(tcc8k_ohci1_resources), | 
 | 	.resource       = tcc8k_ohci1_resources, | 
 | }; | 
 |  | 
 | static void __init tcc8k_init_usbhost(void) | 
 | { | 
 | 	platform_device_register(&ohci0_device); | 
 | 	platform_device_register(&ohci1_device); | 
 | } | 
 | #else | 
 | static void __init tcc8k_init_usbhost(void) { } | 
 | #endif | 
 |  | 
 | /* USB device controller*/ | 
 | #ifdef CONFIG_USB_GADGET_TCC8K | 
 | static struct resource udc_resources[] = { | 
 | 	[0] = { | 
 | 		.start = INT_USBD, | 
 | 		.end   = INT_USBD, | 
 | 		.flags = IORESOURCE_IRQ, | 
 | 	}, | 
 | 	[1] = { | 
 | 		.start = INT_UDMA, | 
 | 		.end   = INT_UDMA, | 
 | 		.flags = IORESOURCE_IRQ, | 
 | 	}, | 
 | }; | 
 |  | 
 | static struct platform_device tcc8k_udc_device = { | 
 | 	.name = "tcc-udc", | 
 | 	.id = 0, | 
 | 	.resource = udc_resources, | 
 | 	.num_resources = ARRAY_SIZE(udc_resources), | 
 | 	.dev = { | 
 | 		 .dma_mask = &tcc8k_dmamask, | 
 | 		 .coherent_dma_mask = DMA_BIT_MASK(32), | 
 | 	}, | 
 | }; | 
 |  | 
 | static void __init tcc8k_init_usb_gadget(void) | 
 | { | 
 | 	platform_device_register(&tcc8k_udc_device); | 
 | } | 
 | #else | 
 | static void __init tcc8k_init_usb_gadget(void) { } | 
 | #endif	/* CONFIG_USB_GADGET_TCC83X */ | 
 |  | 
 | static int __init tcc8k_init_devices(void) | 
 | { | 
 | 	tcc8k_init_mmc(); | 
 | 	tcc8k_init_usbhost(); | 
 | 	tcc8k_init_usb_gadget(); | 
 | 	return 0; | 
 | } | 
 |  | 
 | arch_initcall(tcc8k_init_devices); |