mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
6.2 KiB
250 lines
6.2 KiB
/* |
|
* Copyright 2011, Netlogic Microsystems. |
|
* Copyright 2004, Matt Porter <[email protected]> |
|
* |
|
* 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
|
|
|