diff options
Diffstat (limited to 'arch/mips/netlogic/xlr/platform.c')
| -rw-r--r-- | arch/mips/netlogic/xlr/platform.c | 250 | 
1 files changed, 250 insertions, 0 deletions
diff --git a/arch/mips/netlogic/xlr/platform.c b/arch/mips/netlogic/xlr/platform.c new file mode 100644 index 00000000000..4785932af24 --- /dev/null +++ b/arch/mips/netlogic/xlr/platform.c @@ -0,0 +1,250 @@ +/* + * 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  | 
