| 
									
										
										
										
											2011-05-07 01:36:40 +05:30
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright 2011, Netlogic Microsystems. | 
					
						
							|  |  |  |  * Copyright 2004, Matt Porter <mporter@kernel.crashing.org> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This file is licensed under the terms of the GNU General Public | 
					
						
							|  |  |  |  * License version 2.  This program is licensed "as is" without any | 
					
						
							|  |  |  |  * warranty of any kind, whether express or implied. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/device.h>
 | 
					
						
							|  |  |  | #include <linux/platform_device.h>
 | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/init.h>
 | 
					
						
							|  |  |  | #include <linux/resource.h>
 | 
					
						
							|  |  |  | #include <linux/serial_8250.h>
 | 
					
						
							|  |  |  | #include <linux/serial_reg.h>
 | 
					
						
							| 
									
										
										
										
											2012-07-24 17:28:54 +02:00
										 |  |  | #include <linux/i2c.h>
 | 
					
						
							| 
									
										
										
										
											2012-10-08 15:11:19 +02:00
										 |  |  | #include <linux/usb/ehci_pdriver.h>
 | 
					
						
							| 
									
										
										
										
											2012-10-08 15:11:34 +02:00
										 |  |  | #include <linux/usb/ohci_pdriver.h>
 | 
					
						
							| 
									
										
										
										
											2011-05-07 01:36:40 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-11 17:08:29 +05:30
										 |  |  | #include <asm/netlogic/haldefs.h>
 | 
					
						
							| 
									
										
										
										
											2011-05-07 01:36:40 +05:30
										 |  |  | #include <asm/netlogic/xlr/iomap.h>
 | 
					
						
							|  |  |  | #include <asm/netlogic/xlr/pic.h>
 | 
					
						
							|  |  |  | #include <asm/netlogic/xlr/xlr.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | unsigned int nlm_xlr_uart_in(struct uart_port *p, int offset) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-11-11 17:08:29 +05:30
										 |  |  | 	uint64_t uartbase; | 
					
						
							| 
									
										
										
										
											2011-05-07 01:36:40 +05:30
										 |  |  | 	unsigned int value; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-11 17:08:29 +05:30
										 |  |  | 	/* sign extend to 64 bits, if needed */ | 
					
						
							|  |  |  | 	uartbase = (uint64_t)(long)p->membase; | 
					
						
							|  |  |  | 	value = nlm_read_reg(uartbase, offset); | 
					
						
							| 
									
										
										
										
											2011-05-07 01:36:40 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* See XLR/XLS errata */ | 
					
						
							|  |  |  | 	if (offset == UART_MSR) | 
					
						
							|  |  |  | 		value ^= 0xF0; | 
					
						
							|  |  |  | 	else if (offset == UART_MCR) | 
					
						
							|  |  |  | 		value ^= 0x3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return value; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void nlm_xlr_uart_out(struct uart_port *p, int offset, int value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-11-11 17:08:29 +05:30
										 |  |  | 	uint64_t uartbase; | 
					
						
							| 
									
										
										
										
											2011-05-07 01:36:40 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-11 17:08:29 +05:30
										 |  |  | 	/* sign extend to 64 bits, if needed */ | 
					
						
							|  |  |  | 	uartbase = (uint64_t)(long)p->membase; | 
					
						
							| 
									
										
										
										
											2011-05-07 01:36:40 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* See XLR/XLS errata */ | 
					
						
							|  |  |  | 	if (offset == UART_MSR) | 
					
						
							|  |  |  | 		value ^= 0xF0; | 
					
						
							|  |  |  | 	else if (offset == UART_MCR) | 
					
						
							|  |  |  | 		value ^= 0x3; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-11 17:08:29 +05:30
										 |  |  | 	nlm_write_reg(uartbase, offset, value); | 
					
						
							| 
									
										
										
										
											2011-05-07 01:36:40 +05:30
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define PORT(_irq)					\
 | 
					
						
							|  |  |  | 	{						\ | 
					
						
							|  |  |  | 		.irq		= _irq,			\ | 
					
						
							|  |  |  | 		.regshift	= 2,			\ | 
					
						
							|  |  |  | 		.iotype		= UPIO_MEM32,		\ | 
					
						
							|  |  |  | 		.flags		= (UPF_SKIP_TEST |	\ | 
					
						
							|  |  |  | 			 UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF),\ | 
					
						
							| 
									
										
										
										
											2013-01-14 15:11:57 +00:00
										 |  |  | 		.uartclk	= PIC_CLK_HZ,		\ | 
					
						
							| 
									
										
										
										
											2011-05-07 01:36:40 +05:30
										 |  |  | 		.type		= PORT_16550A,		\ | 
					
						
							|  |  |  | 		.serial_in	= nlm_xlr_uart_in,	\ | 
					
						
							|  |  |  | 		.serial_out	= nlm_xlr_uart_out,	\ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct plat_serial8250_port xlr_uart_data[] = { | 
					
						
							|  |  |  | 	PORT(PIC_UART_0_IRQ), | 
					
						
							|  |  |  | 	PORT(PIC_UART_1_IRQ), | 
					
						
							|  |  |  | 	{}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct platform_device uart_device = { | 
					
						
							|  |  |  | 	.name		= "serial8250", | 
					
						
							|  |  |  | 	.id		= PLAT8250_DEV_PLATFORM, | 
					
						
							|  |  |  | 	.dev = { | 
					
						
							|  |  |  | 		.platform_data = xlr_uart_data, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int __init nlm_uart_init(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-11-11 17:08:29 +05:30
										 |  |  | 	unsigned long uartbase; | 
					
						
							| 
									
										
										
										
											2011-05-07 01:36:40 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-11 17:08:29 +05:30
										 |  |  | 	uartbase = (unsigned long)nlm_mmio_base(NETLOGIC_IO_UART_0_OFFSET); | 
					
						
							|  |  |  | 	xlr_uart_data[0].membase = (void __iomem *)uartbase; | 
					
						
							|  |  |  | 	xlr_uart_data[0].mapbase = CPHYSADDR(uartbase); | 
					
						
							| 
									
										
										
										
											2011-05-07 01:36:40 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-11 17:08:29 +05:30
										 |  |  | 	uartbase = (unsigned long)nlm_mmio_base(NETLOGIC_IO_UART_1_OFFSET); | 
					
						
							|  |  |  | 	xlr_uart_data[1].membase = (void __iomem *)uartbase; | 
					
						
							|  |  |  | 	xlr_uart_data[1].mapbase = CPHYSADDR(uartbase); | 
					
						
							| 
									
										
										
										
											2011-05-07 01:36:40 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | 	return platform_device_register(&uart_device); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | arch_initcall(nlm_uart_init); | 
					
						
							| 
									
										
										
										
											2012-07-24 17:28:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_USB
 | 
					
						
							|  |  |  | /* Platform USB devices, only on XLS chips */ | 
					
						
							|  |  |  | static u64 xls_usb_dmamask = ~(u32)0; | 
					
						
							|  |  |  | #define USB_PLATFORM_DEV(n, i, irq)					\
 | 
					
						
							|  |  |  | 	{								\ | 
					
						
							|  |  |  | 		.name		= n,					\ | 
					
						
							|  |  |  | 		.id		= i,					\ | 
					
						
							|  |  |  | 		.num_resources	= 2,					\ | 
					
						
							|  |  |  | 		.dev		= {					\ | 
					
						
							|  |  |  | 			.dma_mask	= &xls_usb_dmamask,		\ | 
					
						
							|  |  |  | 			.coherent_dma_mask = 0xffffffff,		\ | 
					
						
							|  |  |  | 		},							\ | 
					
						
							|  |  |  | 		.resource	= (struct resource[]) {			\ | 
					
						
							|  |  |  | 			{						\ | 
					
						
							|  |  |  | 				.flags = IORESOURCE_MEM,		\ | 
					
						
							|  |  |  | 			},						\ | 
					
						
							|  |  |  | 			{						\ | 
					
						
							|  |  |  | 				.start	= irq,				\ | 
					
						
							|  |  |  | 				.end	= irq,				\ | 
					
						
							|  |  |  | 				.flags = IORESOURCE_IRQ,		\ | 
					
						
							|  |  |  | 			},						\ | 
					
						
							|  |  |  | 		},							\ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-08 15:11:19 +02:00
										 |  |  | static struct usb_ehci_pdata xls_usb_ehci_pdata = { | 
					
						
							|  |  |  | 	.caps_offset	= 0, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-08 15:11:34 +02:00
										 |  |  | static struct usb_ohci_pdata xls_usb_ohci_pdata; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-24 17:28:53 +02:00
										 |  |  | static struct platform_device xls_usb_ehci_device = | 
					
						
							| 
									
										
										
										
											2012-10-08 15:11:19 +02:00
										 |  |  | 			 USB_PLATFORM_DEV("ehci-platform", 0, PIC_USB_IRQ); | 
					
						
							| 
									
										
										
										
											2012-07-24 17:28:53 +02:00
										 |  |  | static struct platform_device xls_usb_ohci_device_0 = | 
					
						
							| 
									
										
										
										
											2012-10-08 15:11:34 +02:00
										 |  |  | 			 USB_PLATFORM_DEV("ohci-platform", 1, PIC_USB_IRQ); | 
					
						
							| 
									
										
										
										
											2012-07-24 17:28:53 +02:00
										 |  |  | static struct platform_device xls_usb_ohci_device_1 = | 
					
						
							| 
									
										
										
										
											2012-10-08 15:11:34 +02:00
										 |  |  | 			 USB_PLATFORM_DEV("ohci-platform", 2, PIC_USB_IRQ); | 
					
						
							| 
									
										
										
										
											2012-07-24 17:28:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static struct platform_device *xls_platform_devices[] = { | 
					
						
							|  |  |  | 	&xls_usb_ehci_device, | 
					
						
							|  |  |  | 	&xls_usb_ohci_device_0, | 
					
						
							|  |  |  | 	&xls_usb_ohci_device_1, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int xls_platform_usb_init(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	uint64_t usb_mmio, gpio_mmio; | 
					
						
							|  |  |  | 	unsigned long memres; | 
					
						
							|  |  |  | 	uint32_t val; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!nlm_chip_is_xls()) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gpio_mmio = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET); | 
					
						
							|  |  |  | 	usb_mmio  = nlm_mmio_base(NETLOGIC_IO_USB_1_OFFSET); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Clear Rogue Phy INTs */ | 
					
						
							|  |  |  | 	nlm_write_reg(usb_mmio, 49, 0x10000000); | 
					
						
							|  |  |  | 	/* Enable all interrupts */ | 
					
						
							|  |  |  | 	nlm_write_reg(usb_mmio, 50, 0x1f000000); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Enable ports */ | 
					
						
							| 
									
										
										
										
											2013-01-22 12:59:30 +01:00
										 |  |  | 	nlm_write_reg(usb_mmio,	 1, 0x07000500); | 
					
						
							| 
									
										
										
										
											2012-07-24 17:28:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	val = nlm_read_reg(gpio_mmio, 21); | 
					
						
							|  |  |  | 	if (((val >> 22) & 0x01) == 0) { | 
					
						
							|  |  |  | 		pr_info("Detected USB Device mode - Not supported!\n"); | 
					
						
							| 
									
										
										
										
											2013-01-22 12:59:30 +01:00
										 |  |  | 		nlm_write_reg(usb_mmio,	 0, 0x01000000); | 
					
						
							| 
									
										
										
										
											2012-07-24 17:28:53 +02:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pr_info("Detected USB Host mode - Adding XLS USB devices.\n"); | 
					
						
							|  |  |  | 	/* Clear reset, host mode */ | 
					
						
							| 
									
										
										
										
											2013-01-22 12:59:30 +01:00
										 |  |  | 	nlm_write_reg(usb_mmio,	 0, 0x02000000); | 
					
						
							| 
									
										
										
										
											2012-07-24 17:28:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Memory resource for various XLS usb ports */ | 
					
						
							|  |  |  | 	usb_mmio = nlm_mmio_base(NETLOGIC_IO_USB_0_OFFSET); | 
					
						
							|  |  |  | 	memres = CPHYSADDR((unsigned long)usb_mmio); | 
					
						
							|  |  |  | 	xls_usb_ehci_device.resource[0].start = memres; | 
					
						
							|  |  |  | 	xls_usb_ehci_device.resource[0].end = memres + 0x400 - 1; | 
					
						
							| 
									
										
										
										
											2012-10-08 15:11:19 +02:00
										 |  |  | 	xls_usb_ehci_device.dev.platform_data = &xls_usb_ehci_pdata; | 
					
						
							| 
									
										
										
										
											2012-07-24 17:28:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	memres += 0x400; | 
					
						
							|  |  |  | 	xls_usb_ohci_device_0.resource[0].start = memres; | 
					
						
							|  |  |  | 	xls_usb_ohci_device_0.resource[0].end = memres + 0x400 - 1; | 
					
						
							| 
									
										
										
										
											2012-10-08 15:11:34 +02:00
										 |  |  | 	xls_usb_ohci_device_0.dev.platform_data = &xls_usb_ohci_pdata; | 
					
						
							| 
									
										
										
										
											2012-07-24 17:28:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	memres += 0x400; | 
					
						
							|  |  |  | 	xls_usb_ohci_device_1.resource[0].start = memres; | 
					
						
							|  |  |  | 	xls_usb_ohci_device_1.resource[0].end = memres + 0x400 - 1; | 
					
						
							| 
									
										
										
										
											2012-10-08 15:11:34 +02:00
										 |  |  | 	xls_usb_ohci_device_1.dev.platform_data = &xls_usb_ohci_pdata; | 
					
						
							| 
									
										
										
										
											2012-07-24 17:28:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return platform_add_devices(xls_platform_devices, | 
					
						
							|  |  |  | 				ARRAY_SIZE(xls_platform_devices)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | arch_initcall(xls_platform_usb_init); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-07-24 17:28:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_I2C
 | 
					
						
							|  |  |  | static struct i2c_board_info nlm_i2c_board_info1[] __initdata = { | 
					
						
							|  |  |  | 	/* All XLR boards have this RTC and Max6657 Temp Chip */ | 
					
						
							|  |  |  | 	[0] = { | 
					
						
							|  |  |  | 		.type	= "ds1374", | 
					
						
							|  |  |  | 		.addr	= 0x68 | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	[1] = { | 
					
						
							|  |  |  | 		.type	= "lm90", | 
					
						
							|  |  |  | 		.addr	= 0x4c | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct resource i2c_resources[] = { | 
					
						
							|  |  |  | 	[0] = { | 
					
						
							|  |  |  | 		.start	= 0,	/* filled at init */ | 
					
						
							|  |  |  | 		.end	= 0, | 
					
						
							|  |  |  | 		.flags	= IORESOURCE_MEM, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct platform_device nlm_xlr_i2c_1 = { | 
					
						
							| 
									
										
										
										
											2013-01-22 12:59:30 +01:00
										 |  |  | 	.name		= "xlr-i2cbus", | 
					
						
							|  |  |  | 	.id		= 1, | 
					
						
							| 
									
										
										
										
											2012-07-24 17:28:54 +02:00
										 |  |  | 	.num_resources	= 1, | 
					
						
							|  |  |  | 	.resource	= i2c_resources, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int __init nlm_i2c_init(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int err = 0; | 
					
						
							|  |  |  | 	unsigned int offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* I2C bus 0 does not have any useful devices, configure only bus 1 */ | 
					
						
							|  |  |  | 	offset = NETLOGIC_IO_I2C_1_OFFSET; | 
					
						
							|  |  |  | 	nlm_xlr_i2c_1.resource[0].start = CPHYSADDR(nlm_mmio_base(offset)); | 
					
						
							|  |  |  | 	nlm_xlr_i2c_1.resource[0].end = nlm_xlr_i2c_1.resource[0].start + 0xfff; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	platform_device_register(&nlm_xlr_i2c_1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = i2c_register_board_info(1, nlm_i2c_board_info1, | 
					
						
							|  |  |  | 				ARRAY_SIZE(nlm_i2c_board_info1)); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		pr_err("nlm-i2c: cannot register board I2C devices\n"); | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | arch_initcall(nlm_i2c_init); | 
					
						
							|  |  |  | #endif
 |