mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	 194d315da8
			
		
	
	
		194d315da8
		
	
	
	
	
		
			
			The early serial code is not needed because we already have early printk support provided by common/earlycons.c This change also fixes the following build error that occurs when CONFIG_SERIAL_8250 is not configured for Netlogic XLR boards: arch/mips/built-in.o: In function `nlm_early_serial_setup': setup.c:(.init.text+0x274): undefined reference to `early_serial_setup' make: *** [vmlinux] Error 1 Reported-by: Markos Chandras <markos.chandras@imgtec.com> Signed-off-by: Jayachandran C <jchandra@broadcom.com> Signed-off-by: John Crispin <blogic@openwrt.org> Patchwork: http://patchwork.linux-mips.org/patch/6083/
		
			
				
	
	
		
			251 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			251 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * 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>
 | |
| #include <linux/i2c.h>
 | |
| #include <linux/usb/ehci_pdriver.h>
 | |
| #include <linux/usb/ohci_pdriver.h>
 | |
| 
 | |
| #include <asm/netlogic/haldefs.h>
 | |
| #include <asm/netlogic/xlr/iomap.h>
 | |
| #include <asm/netlogic/xlr/pic.h>
 | |
| #include <asm/netlogic/xlr/xlr.h>
 | |
| 
 | |
| static unsigned int nlm_xlr_uart_in(struct uart_port *p, int offset)
 | |
| {
 | |
| 	uint64_t uartbase;
 | |
| 	unsigned int value;
 | |
| 
 | |
| 	/* sign extend to 64 bits, if needed */
 | |
| 	uartbase = (uint64_t)(long)p->membase;
 | |
| 	value = nlm_read_reg(uartbase, offset);
 | |
| 
 | |
| 	/* See XLR/XLS errata */
 | |
| 	if (offset == UART_MSR)
 | |
| 		value ^= 0xF0;
 | |
| 	else if (offset == UART_MCR)
 | |
| 		value ^= 0x3;
 | |
| 
 | |
| 	return value;
 | |
| }
 | |
| 
 | |
| static void nlm_xlr_uart_out(struct uart_port *p, int offset, int value)
 | |
| {
 | |
| 	uint64_t uartbase;
 | |
| 
 | |
| 	/* sign extend to 64 bits, if needed */
 | |
| 	uartbase = (uint64_t)(long)p->membase;
 | |
| 
 | |
| 	/* See XLR/XLS errata */
 | |
| 	if (offset == UART_MSR)
 | |
| 		value ^= 0xF0;
 | |
| 	else if (offset == UART_MCR)
 | |
| 		value ^= 0x3;
 | |
| 
 | |
| 	nlm_write_reg(uartbase, offset, value);
 | |
| }
 | |
| 
 | |
| #define PORT(_irq)					\
 | |
| 	{						\
 | |
| 		.irq		= _irq,			\
 | |
| 		.regshift	= 2,			\
 | |
| 		.iotype		= UPIO_MEM32,		\
 | |
| 		.flags		= (UPF_SKIP_TEST |	\
 | |
| 			 UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF),\
 | |
| 		.uartclk	= PIC_CLK_HZ,		\
 | |
| 		.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)
 | |
| {
 | |
| 	unsigned long uartbase;
 | |
| 
 | |
| 	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);
 | |
| 
 | |
| 	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);
 | |
| 
 | |
| 	return platform_device_register(&uart_device);
 | |
| }
 | |
| 
 | |
| arch_initcall(nlm_uart_init);
 | |
| 
 | |
| #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,		\
 | |
| 			},						\
 | |
| 		},							\
 | |
| 	}
 | |
| 
 | |
| static struct usb_ehci_pdata xls_usb_ehci_pdata = {
 | |
| 	.caps_offset	= 0,
 | |
| };
 | |
| 
 | |
| static struct usb_ohci_pdata xls_usb_ohci_pdata;
 | |
| 
 | |
| static struct platform_device xls_usb_ehci_device =
 | |
| 			 USB_PLATFORM_DEV("ehci-platform", 0, PIC_USB_IRQ);
 | |
| static struct platform_device xls_usb_ohci_device_0 =
 | |
| 			 USB_PLATFORM_DEV("ohci-platform", 1, PIC_USB_IRQ);
 | |
| static struct platform_device xls_usb_ohci_device_1 =
 | |
| 			 USB_PLATFORM_DEV("ohci-platform", 2, PIC_USB_IRQ);
 | |
| 
 | |
| 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 */
 | |
| 	nlm_write_reg(usb_mmio,	 1, 0x07000500);
 | |
| 
 | |
| 	val = nlm_read_reg(gpio_mmio, 21);
 | |
| 	if (((val >> 22) & 0x01) == 0) {
 | |
| 		pr_info("Detected USB Device mode - Not supported!\n");
 | |
| 		nlm_write_reg(usb_mmio,	 0, 0x01000000);
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	pr_info("Detected USB Host mode - Adding XLS USB devices.\n");
 | |
| 	/* Clear reset, host mode */
 | |
| 	nlm_write_reg(usb_mmio,	 0, 0x02000000);
 | |
| 
 | |
| 	/* 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;
 | |
| 	xls_usb_ehci_device.dev.platform_data = &xls_usb_ehci_pdata;
 | |
| 
 | |
| 	memres += 0x400;
 | |
| 	xls_usb_ohci_device_0.resource[0].start = memres;
 | |
| 	xls_usb_ohci_device_0.resource[0].end = memres + 0x400 - 1;
 | |
| 	xls_usb_ohci_device_0.dev.platform_data = &xls_usb_ohci_pdata;
 | |
| 
 | |
| 	memres += 0x400;
 | |
| 	xls_usb_ohci_device_1.resource[0].start = memres;
 | |
| 	xls_usb_ohci_device_1.resource[0].end = memres + 0x400 - 1;
 | |
| 	xls_usb_ohci_device_1.dev.platform_data = &xls_usb_ohci_pdata;
 | |
| 
 | |
| 	return platform_add_devices(xls_platform_devices,
 | |
| 				ARRAY_SIZE(xls_platform_devices));
 | |
| }
 | |
| 
 | |
| arch_initcall(xls_platform_usb_init);
 | |
| #endif
 | |
| 
 | |
| #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 = {
 | |
| 	.name		= "xlr-i2cbus",
 | |
| 	.id		= 1,
 | |
| 	.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
 |