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 000000000..4785932af --- /dev/null +++ b/arch/mips/netlogic/xlr/platform.c | |||
@@ -0,0 +1,250 @@ | |||
1 | /* | ||
2 | * Copyright 2011, Netlogic Microsystems. | ||
3 | * Copyright 2004, Matt Porter <mporter@kernel.crashing.org> | ||
4 | * | ||
5 | * This file is licensed under the terms of the GNU General Public | ||
6 | * License version 2. This program is licensed "as is" without any | ||
7 | * warranty of any kind, whether express or implied. | ||
8 | */ | ||
9 | |||
10 | #include <linux/device.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/resource.h> | ||
15 | #include <linux/serial_8250.h> | ||
16 | #include <linux/serial_reg.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/usb/ehci_pdriver.h> | ||
19 | #include <linux/usb/ohci_pdriver.h> | ||
20 | |||
21 | #include <asm/netlogic/haldefs.h> | ||
22 | #include <asm/netlogic/xlr/iomap.h> | ||
23 | #include <asm/netlogic/xlr/pic.h> | ||
24 | #include <asm/netlogic/xlr/xlr.h> | ||
25 | |||
26 | static unsigned int nlm_xlr_uart_in(struct uart_port *p, int offset) | ||
27 | { | ||
28 | uint64_t uartbase; | ||
29 | unsigned int value; | ||
30 | |||
31 | /* sign extend to 64 bits, if needed */ | ||
32 | uartbase = (uint64_t)(long)p->membase; | ||
33 | value = nlm_read_reg(uartbase, offset); | ||
34 | |||
35 | /* See XLR/XLS errata */ | ||
36 | if (offset == UART_MSR) | ||
37 | value ^= 0xF0; | ||
38 | else if (offset == UART_MCR) | ||
39 | value ^= 0x3; | ||
40 | |||
41 | return value; | ||
42 | } | ||
43 | |||
44 | static void nlm_xlr_uart_out(struct uart_port *p, int offset, int value) | ||
45 | { | ||
46 | uint64_t uartbase; | ||
47 | |||
48 | /* sign extend to 64 bits, if needed */ | ||
49 | uartbase = (uint64_t)(long)p->membase; | ||
50 | |||
51 | /* See XLR/XLS errata */ | ||
52 | if (offset == UART_MSR) | ||
53 | value ^= 0xF0; | ||
54 | else if (offset == UART_MCR) | ||
55 | value ^= 0x3; | ||
56 | |||
57 | nlm_write_reg(uartbase, offset, value); | ||
58 | } | ||
59 | |||
60 | #define PORT(_irq) \ | ||
61 | { \ | ||
62 | .irq = _irq, \ | ||
63 | .regshift = 2, \ | ||
64 | .iotype = UPIO_MEM32, \ | ||
65 | .flags = (UPF_SKIP_TEST | \ | ||
66 | UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF),\ | ||
67 | .uartclk = PIC_CLK_HZ, \ | ||
68 | .type = PORT_16550A, \ | ||
69 | .serial_in = nlm_xlr_uart_in, \ | ||
70 | .serial_out = nlm_xlr_uart_out, \ | ||
71 | } | ||
72 | |||
73 | static struct plat_serial8250_port xlr_uart_data[] = { | ||
74 | PORT(PIC_UART_0_IRQ), | ||
75 | PORT(PIC_UART_1_IRQ), | ||
76 | {}, | ||
77 | }; | ||
78 | |||
79 | static struct platform_device uart_device = { | ||
80 | .name = "serial8250", | ||
81 | .id = PLAT8250_DEV_PLATFORM, | ||
82 | .dev = { | ||
83 | .platform_data = xlr_uart_data, | ||
84 | }, | ||
85 | }; | ||
86 | |||
87 | static int __init nlm_uart_init(void) | ||
88 | { | ||
89 | unsigned long uartbase; | ||
90 | |||
91 | uartbase = (unsigned long)nlm_mmio_base(NETLOGIC_IO_UART_0_OFFSET); | ||
92 | xlr_uart_data[0].membase = (void __iomem *)uartbase; | ||
93 | xlr_uart_data[0].mapbase = CPHYSADDR(uartbase); | ||
94 | |||
95 | uartbase = (unsigned long)nlm_mmio_base(NETLOGIC_IO_UART_1_OFFSET); | ||
96 | xlr_uart_data[1].membase = (void __iomem *)uartbase; | ||
97 | xlr_uart_data[1].mapbase = CPHYSADDR(uartbase); | ||
98 | |||
99 | return platform_device_register(&uart_device); | ||
100 | } | ||
101 | |||
102 | arch_initcall(nlm_uart_init); | ||
103 | |||
104 | #ifdef CONFIG_USB | ||
105 | /* Platform USB devices, only on XLS chips */ | ||
106 | static u64 xls_usb_dmamask = ~(u32)0; | ||
107 | #define USB_PLATFORM_DEV(n, i, irq) \ | ||
108 | { \ | ||
109 | .name = n, \ | ||
110 | .id = i, \ | ||
111 | .num_resources = 2, \ | ||
112 | .dev = { \ | ||
113 | .dma_mask = &xls_usb_dmamask, \ | ||
114 | .coherent_dma_mask = 0xffffffff, \ | ||
115 | }, \ | ||
116 | .resource = (struct resource[]) { \ | ||
117 | { \ | ||
118 | .flags = IORESOURCE_MEM, \ | ||
119 | }, \ | ||
120 | { \ | ||
121 | .start = irq, \ | ||
122 | .end = irq, \ | ||
123 | .flags = IORESOURCE_IRQ, \ | ||
124 | }, \ | ||
125 | }, \ | ||
126 | } | ||
127 | |||
128 | static struct usb_ehci_pdata xls_usb_ehci_pdata = { | ||
129 | .caps_offset = 0, | ||
130 | }; | ||
131 | |||
132 | static struct usb_ohci_pdata xls_usb_ohci_pdata; | ||
133 | |||
134 | static struct platform_device xls_usb_ehci_device = | ||
135 | USB_PLATFORM_DEV("ehci-platform", 0, PIC_USB_IRQ); | ||
136 | static struct platform_device xls_usb_ohci_device_0 = | ||
137 | USB_PLATFORM_DEV("ohci-platform", 1, PIC_USB_IRQ); | ||
138 | static struct platform_device xls_usb_ohci_device_1 = | ||
139 | USB_PLATFORM_DEV("ohci-platform", 2, PIC_USB_IRQ); | ||
140 | |||
141 | static struct platform_device *xls_platform_devices[] = { | ||
142 | &xls_usb_ehci_device, | ||
143 | &xls_usb_ohci_device_0, | ||
144 | &xls_usb_ohci_device_1, | ||
145 | }; | ||
146 | |||
147 | int xls_platform_usb_init(void) | ||
148 | { | ||
149 | uint64_t usb_mmio, gpio_mmio; | ||
150 | unsigned long memres; | ||
151 | uint32_t val; | ||
152 | |||
153 | if (!nlm_chip_is_xls()) | ||
154 | return 0; | ||
155 | |||
156 | gpio_mmio = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET); | ||
157 | usb_mmio = nlm_mmio_base(NETLOGIC_IO_USB_1_OFFSET); | ||
158 | |||
159 | /* Clear Rogue Phy INTs */ | ||
160 | nlm_write_reg(usb_mmio, 49, 0x10000000); | ||
161 | /* Enable all interrupts */ | ||
162 | nlm_write_reg(usb_mmio, 50, 0x1f000000); | ||
163 | |||
164 | /* Enable ports */ | ||
165 | nlm_write_reg(usb_mmio, 1, 0x07000500); | ||
166 | |||
167 | val = nlm_read_reg(gpio_mmio, 21); | ||
168 | if (((val >> 22) & 0x01) == 0) { | ||
169 | pr_info("Detected USB Device mode - Not supported!\n"); | ||
170 | nlm_write_reg(usb_mmio, 0, 0x01000000); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | pr_info("Detected USB Host mode - Adding XLS USB devices.\n"); | ||
175 | /* Clear reset, host mode */ | ||
176 | nlm_write_reg(usb_mmio, 0, 0x02000000); | ||
177 | |||
178 | /* Memory resource for various XLS usb ports */ | ||
179 | usb_mmio = nlm_mmio_base(NETLOGIC_IO_USB_0_OFFSET); | ||
180 | memres = CPHYSADDR((unsigned long)usb_mmio); | ||
181 | xls_usb_ehci_device.resource[0].start = memres; | ||
182 | xls_usb_ehci_device.resource[0].end = memres + 0x400 - 1; | ||
183 | xls_usb_ehci_device.dev.platform_data = &xls_usb_ehci_pdata; | ||
184 | |||
185 | memres += 0x400; | ||
186 | xls_usb_ohci_device_0.resource[0].start = memres; | ||
187 | xls_usb_ohci_device_0.resource[0].end = memres + 0x400 - 1; | ||
188 | xls_usb_ohci_device_0.dev.platform_data = &xls_usb_ohci_pdata; | ||
189 | |||
190 | memres += 0x400; | ||
191 | xls_usb_ohci_device_1.resource[0].start = memres; | ||
192 | xls_usb_ohci_device_1.resource[0].end = memres + 0x400 - 1; | ||
193 | xls_usb_ohci_device_1.dev.platform_data = &xls_usb_ohci_pdata; | ||
194 | |||
195 | return platform_add_devices(xls_platform_devices, | ||
196 | ARRAY_SIZE(xls_platform_devices)); | ||
197 | } | ||
198 | |||
199 | arch_initcall(xls_platform_usb_init); | ||
200 | #endif | ||
201 | |||
202 | #ifdef CONFIG_I2C | ||
203 | static struct i2c_board_info nlm_i2c_board_info1[] __initdata = { | ||
204 | /* All XLR boards have this RTC and Max6657 Temp Chip */ | ||
205 | [0] = { | ||
206 | .type = "ds1374", | ||
207 | .addr = 0x68 | ||
208 | }, | ||
209 | [1] = { | ||
210 | .type = "lm90", | ||
211 | .addr = 0x4c | ||
212 | }, | ||
213 | }; | ||
214 | |||
215 | static struct resource i2c_resources[] = { | ||
216 | [0] = { | ||
217 | .start = 0, /* filled at init */ | ||
218 | .end = 0, | ||
219 | .flags = IORESOURCE_MEM, | ||
220 | }, | ||
221 | }; | ||
222 | |||
223 | static struct platform_device nlm_xlr_i2c_1 = { | ||
224 | .name = "xlr-i2cbus", | ||
225 | .id = 1, | ||
226 | .num_resources = 1, | ||
227 | .resource = i2c_resources, | ||
228 | }; | ||
229 | |||
230 | static int __init nlm_i2c_init(void) | ||
231 | { | ||
232 | int err = 0; | ||
233 | unsigned int offset; | ||
234 | |||
235 | /* I2C bus 0 does not have any useful devices, configure only bus 1 */ | ||
236 | offset = NETLOGIC_IO_I2C_1_OFFSET; | ||
237 | nlm_xlr_i2c_1.resource[0].start = CPHYSADDR(nlm_mmio_base(offset)); | ||
238 | nlm_xlr_i2c_1.resource[0].end = nlm_xlr_i2c_1.resource[0].start + 0xfff; | ||
239 | |||
240 | platform_device_register(&nlm_xlr_i2c_1); | ||
241 | |||
242 | err = i2c_register_board_info(1, nlm_i2c_board_info1, | ||
243 | ARRAY_SIZE(nlm_i2c_board_info1)); | ||
244 | if (err < 0) | ||
245 | pr_err("nlm-i2c: cannot register board I2C devices\n"); | ||
246 | return err; | ||
247 | } | ||
248 | |||
249 | arch_initcall(nlm_i2c_init); | ||
250 | #endif | ||