diff options
Diffstat (limited to 'arch/arm/mach-orion5x/kurobox_pro-setup.c')
-rw-r--r-- | arch/arm/mach-orion5x/kurobox_pro-setup.c | 224 |
1 files changed, 183 insertions, 41 deletions
diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c index f5074b877b7f..84feac4a1fe2 100644 --- a/arch/arm/mach-orion5x/kurobox_pro-setup.c +++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c | |||
@@ -13,10 +13,12 @@ | |||
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
15 | #include <linux/irq.h> | 15 | #include <linux/irq.h> |
16 | #include <linux/delay.h> | ||
16 | #include <linux/mtd/physmap.h> | 17 | #include <linux/mtd/physmap.h> |
17 | #include <linux/mtd/nand.h> | 18 | #include <linux/mtd/nand.h> |
18 | #include <linux/mv643xx_eth.h> | 19 | #include <linux/mv643xx_eth.h> |
19 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/serial_reg.h> | ||
20 | #include <linux/ata_platform.h> | 22 | #include <linux/ata_platform.h> |
21 | #include <asm/mach-types.h> | 23 | #include <asm/mach-types.h> |
22 | #include <asm/gpio.h> | 24 | #include <asm/gpio.h> |
@@ -25,6 +27,7 @@ | |||
25 | #include <asm/arch/orion5x.h> | 27 | #include <asm/arch/orion5x.h> |
26 | #include <asm/plat-orion/orion_nand.h> | 28 | #include <asm/plat-orion/orion_nand.h> |
27 | #include "common.h" | 29 | #include "common.h" |
30 | #include "mpp.h" | ||
28 | 31 | ||
29 | /***************************************************************************** | 32 | /***************************************************************************** |
30 | * KUROBOX-PRO Info | 33 | * KUROBOX-PRO Info |
@@ -53,13 +56,11 @@ static struct mtd_partition kurobox_pro_nand_parts[] = { | |||
53 | .name = "uImage", | 56 | .name = "uImage", |
54 | .offset = 0, | 57 | .offset = 0, |
55 | .size = SZ_4M, | 58 | .size = SZ_4M, |
56 | }, | 59 | }, { |
57 | { | ||
58 | .name = "rootfs", | 60 | .name = "rootfs", |
59 | .offset = SZ_4M, | 61 | .offset = SZ_4M, |
60 | .size = SZ_64M, | 62 | .size = SZ_64M, |
61 | }, | 63 | }, { |
62 | { | ||
63 | .name = "extra", | 64 | .name = "extra", |
64 | .offset = SZ_4M + SZ_64M, | 65 | .offset = SZ_4M + SZ_64M, |
65 | .size = SZ_256M - (SZ_4M + SZ_64M), | 66 | .size = SZ_256M - (SZ_4M + SZ_64M), |
@@ -132,8 +133,6 @@ static int __init kurobox_pro_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | |||
132 | /* | 133 | /* |
133 | * PCI isn't used on the Kuro | 134 | * PCI isn't used on the Kuro |
134 | */ | 135 | */ |
135 | printk(KERN_ERR "kurobox_pro_pci_map_irq failed, unknown bus\n"); | ||
136 | |||
137 | return -1; | 136 | return -1; |
138 | } | 137 | } |
139 | 138 | ||
@@ -161,7 +160,6 @@ subsys_initcall(kurobox_pro_pci_init); | |||
161 | 160 | ||
162 | static struct mv643xx_eth_platform_data kurobox_pro_eth_data = { | 161 | static struct mv643xx_eth_platform_data kurobox_pro_eth_data = { |
163 | .phy_addr = 8, | 162 | .phy_addr = 8, |
164 | .force_phy_addr = 1, | ||
165 | }; | 163 | }; |
166 | 164 | ||
167 | /***************************************************************************** | 165 | /***************************************************************************** |
@@ -175,12 +173,169 @@ static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = { | |||
175 | * SATA | 173 | * SATA |
176 | ****************************************************************************/ | 174 | ****************************************************************************/ |
177 | static struct mv_sata_platform_data kurobox_pro_sata_data = { | 175 | static struct mv_sata_platform_data kurobox_pro_sata_data = { |
178 | .n_ports = 2, | 176 | .n_ports = 2, |
179 | }; | 177 | }; |
180 | 178 | ||
181 | /***************************************************************************** | 179 | /***************************************************************************** |
180 | * Kurobox Pro specific power off method via UART1-attached microcontroller | ||
181 | ****************************************************************************/ | ||
182 | |||
183 | #define UART1_REG(x) (UART1_VIRT_BASE + ((UART_##x) << 2)) | ||
184 | |||
185 | static int kurobox_pro_miconread(unsigned char *buf, int count) | ||
186 | { | ||
187 | int i; | ||
188 | int timeout; | ||
189 | |||
190 | for (i = 0; i < count; i++) { | ||
191 | timeout = 10; | ||
192 | |||
193 | while (!(readl(UART1_REG(LSR)) & UART_LSR_DR)) { | ||
194 | if (--timeout == 0) | ||
195 | break; | ||
196 | udelay(1000); | ||
197 | } | ||
198 | |||
199 | if (timeout == 0) | ||
200 | break; | ||
201 | buf[i] = readl(UART1_REG(RX)); | ||
202 | } | ||
203 | |||
204 | /* return read bytes */ | ||
205 | return i; | ||
206 | } | ||
207 | |||
208 | static int kurobox_pro_miconwrite(const unsigned char *buf, int count) | ||
209 | { | ||
210 | int i = 0; | ||
211 | |||
212 | while (count--) { | ||
213 | while (!(readl(UART1_REG(LSR)) & UART_LSR_THRE)) | ||
214 | barrier(); | ||
215 | writel(buf[i++], UART1_REG(TX)); | ||
216 | } | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static int kurobox_pro_miconsend(const unsigned char *data, int count) | ||
222 | { | ||
223 | int i; | ||
224 | unsigned char checksum = 0; | ||
225 | unsigned char recv_buf[40]; | ||
226 | unsigned char send_buf[40]; | ||
227 | unsigned char correct_ack[3]; | ||
228 | int retry = 2; | ||
229 | |||
230 | /* Generate checksum */ | ||
231 | for (i = 0; i < count; i++) | ||
232 | checksum -= data[i]; | ||
233 | |||
234 | do { | ||
235 | /* Send data */ | ||
236 | kurobox_pro_miconwrite(data, count); | ||
237 | |||
238 | /* send checksum */ | ||
239 | kurobox_pro_miconwrite(&checksum, 1); | ||
240 | |||
241 | if (kurobox_pro_miconread(recv_buf, sizeof(recv_buf)) <= 3) { | ||
242 | printk(KERN_ERR ">%s: receive failed.\n", __func__); | ||
243 | |||
244 | /* send preamble to clear the receive buffer */ | ||
245 | memset(&send_buf, 0xff, sizeof(send_buf)); | ||
246 | kurobox_pro_miconwrite(send_buf, sizeof(send_buf)); | ||
247 | |||
248 | /* make dummy reads */ | ||
249 | mdelay(100); | ||
250 | kurobox_pro_miconread(recv_buf, sizeof(recv_buf)); | ||
251 | } else { | ||
252 | /* Generate expected ack */ | ||
253 | correct_ack[0] = 0x01; | ||
254 | correct_ack[1] = data[1]; | ||
255 | correct_ack[2] = 0x00; | ||
256 | |||
257 | /* checksum Check */ | ||
258 | if ((recv_buf[0] + recv_buf[1] + recv_buf[2] + | ||
259 | recv_buf[3]) & 0xFF) { | ||
260 | printk(KERN_ERR ">%s: Checksum Error : " | ||
261 | "Received data[%02x, %02x, %02x, %02x]" | ||
262 | "\n", __func__, recv_buf[0], | ||
263 | recv_buf[1], recv_buf[2], recv_buf[3]); | ||
264 | } else { | ||
265 | /* Check Received Data */ | ||
266 | if (correct_ack[0] == recv_buf[0] && | ||
267 | correct_ack[1] == recv_buf[1] && | ||
268 | correct_ack[2] == recv_buf[2]) { | ||
269 | /* Interval for next command */ | ||
270 | mdelay(10); | ||
271 | |||
272 | /* Receive ACK */ | ||
273 | return 0; | ||
274 | } | ||
275 | } | ||
276 | /* Received NAK or illegal Data */ | ||
277 | printk(KERN_ERR ">%s: Error : NAK or Illegal Data " | ||
278 | "Received\n", __func__); | ||
279 | } | ||
280 | } while (retry--); | ||
281 | |||
282 | /* Interval for next command */ | ||
283 | mdelay(10); | ||
284 | |||
285 | return -1; | ||
286 | } | ||
287 | |||
288 | static void kurobox_pro_power_off(void) | ||
289 | { | ||
290 | const unsigned char watchdogkill[] = {0x01, 0x35, 0x00}; | ||
291 | const unsigned char shutdownwait[] = {0x00, 0x0c}; | ||
292 | const unsigned char poweroff[] = {0x00, 0x06}; | ||
293 | /* 38400 baud divisor */ | ||
294 | const unsigned divisor = ((ORION5X_TCLK + (8 * 38400)) / (16 * 38400)); | ||
295 | |||
296 | pr_info("%s: triggering power-off...\n", __func__); | ||
297 | |||
298 | /* hijack uart1 and reset into sane state (38400,8n1,even parity) */ | ||
299 | writel(0x83, UART1_REG(LCR)); | ||
300 | writel(divisor & 0xff, UART1_REG(DLL)); | ||
301 | writel((divisor >> 8) & 0xff, UART1_REG(DLM)); | ||
302 | writel(0x1b, UART1_REG(LCR)); | ||
303 | writel(0x00, UART1_REG(IER)); | ||
304 | writel(0x07, UART1_REG(FCR)); | ||
305 | writel(0x00, UART1_REG(MCR)); | ||
306 | |||
307 | /* Send the commands to shutdown the Kurobox Pro */ | ||
308 | kurobox_pro_miconsend(watchdogkill, sizeof(watchdogkill)) ; | ||
309 | kurobox_pro_miconsend(shutdownwait, sizeof(shutdownwait)) ; | ||
310 | kurobox_pro_miconsend(poweroff, sizeof(poweroff)); | ||
311 | } | ||
312 | |||
313 | /***************************************************************************** | ||
182 | * General Setup | 314 | * General Setup |
183 | ****************************************************************************/ | 315 | ****************************************************************************/ |
316 | static struct orion5x_mpp_mode kurobox_pro_mpp_modes[] __initdata = { | ||
317 | { 0, MPP_UNUSED }, | ||
318 | { 1, MPP_UNUSED }, | ||
319 | { 2, MPP_GPIO }, /* GPIO Micon */ | ||
320 | { 3, MPP_GPIO }, /* GPIO Rtc */ | ||
321 | { 4, MPP_UNUSED }, | ||
322 | { 5, MPP_UNUSED }, | ||
323 | { 6, MPP_NAND }, /* NAND Flash REn */ | ||
324 | { 7, MPP_NAND }, /* NAND Flash WEn */ | ||
325 | { 8, MPP_UNUSED }, | ||
326 | { 9, MPP_UNUSED }, | ||
327 | { 10, MPP_UNUSED }, | ||
328 | { 11, MPP_UNUSED }, | ||
329 | { 12, MPP_SATA_LED }, /* SATA 0 presence */ | ||
330 | { 13, MPP_SATA_LED }, /* SATA 1 presence */ | ||
331 | { 14, MPP_SATA_LED }, /* SATA 0 active */ | ||
332 | { 15, MPP_SATA_LED }, /* SATA 1 active */ | ||
333 | { 16, MPP_UART }, /* UART1 RXD */ | ||
334 | { 17, MPP_UART }, /* UART1 TXD */ | ||
335 | { 18, MPP_UART }, /* UART1 CTSn */ | ||
336 | { 19, MPP_UART }, /* UART1 RTSn */ | ||
337 | { -1 }, | ||
338 | }; | ||
184 | 339 | ||
185 | static void __init kurobox_pro_init(void) | 340 | static void __init kurobox_pro_init(void) |
186 | { | 341 | { |
@@ -189,46 +344,33 @@ static void __init kurobox_pro_init(void) | |||
189 | */ | 344 | */ |
190 | orion5x_init(); | 345 | orion5x_init(); |
191 | 346 | ||
192 | /* | 347 | orion5x_mpp_conf(kurobox_pro_mpp_modes); |
193 | * Setup the CPU address decode windows for our devices | ||
194 | */ | ||
195 | orion5x_setup_dev_boot_win(KUROBOX_PRO_NOR_BOOT_BASE, | ||
196 | KUROBOX_PRO_NOR_BOOT_SIZE); | ||
197 | orion5x_setup_dev0_win(KUROBOX_PRO_NAND_BASE, KUROBOX_PRO_NAND_SIZE); | ||
198 | 348 | ||
199 | /* | 349 | /* |
200 | * Open a special address decode windows for the PCIe WA. | 350 | * Configure peripherals. |
201 | */ | 351 | */ |
202 | orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE, | 352 | orion5x_ehci0_init(); |
203 | ORION5X_PCIE_WA_SIZE); | 353 | orion5x_ehci1_init(); |
204 | 354 | orion5x_eth_init(&kurobox_pro_eth_data); | |
205 | /* | 355 | orion5x_i2c_init(); |
206 | * Setup Multiplexing Pins -- | 356 | orion5x_sata_init(&kurobox_pro_sata_data); |
207 | * MPP[0-1] Not used | 357 | orion5x_uart0_init(); |
208 | * MPP[2] GPIO Micon | 358 | orion5x_uart1_init(); |
209 | * MPP[3] GPIO RTC | ||
210 | * MPP[4-5] Not used | ||
211 | * MPP[6] Nand Flash REn | ||
212 | * MPP[7] Nand Flash WEn | ||
213 | * MPP[8-11] Not used | ||
214 | * MPP[12] SATA 0 presence Indication | ||
215 | * MPP[13] SATA 1 presence Indication | ||
216 | * MPP[14] SATA 0 active Indication | ||
217 | * MPP[15] SATA 1 active indication | ||
218 | * MPP[16-19] Not used | ||
219 | */ | ||
220 | orion5x_write(MPP_0_7_CTRL, 0x44220003); | ||
221 | orion5x_write(MPP_8_15_CTRL, 0x55550000); | ||
222 | orion5x_write(MPP_16_19_CTRL, 0x0); | ||
223 | |||
224 | orion5x_gpio_set_valid_pins(0x0000000c); | ||
225 | 359 | ||
360 | orion5x_setup_dev_boot_win(KUROBOX_PRO_NOR_BOOT_BASE, | ||
361 | KUROBOX_PRO_NOR_BOOT_SIZE); | ||
226 | platform_device_register(&kurobox_pro_nor_flash); | 362 | platform_device_register(&kurobox_pro_nor_flash); |
227 | if (machine_is_kurobox_pro()) | 363 | |
364 | if (machine_is_kurobox_pro()) { | ||
365 | orion5x_setup_dev0_win(KUROBOX_PRO_NAND_BASE, | ||
366 | KUROBOX_PRO_NAND_SIZE); | ||
228 | platform_device_register(&kurobox_pro_nand_flash); | 367 | platform_device_register(&kurobox_pro_nand_flash); |
368 | } | ||
369 | |||
229 | i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1); | 370 | i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1); |
230 | orion5x_eth_init(&kurobox_pro_eth_data); | 371 | |
231 | orion5x_sata_init(&kurobox_pro_sata_data); | 372 | /* register Kurobox Pro specific power-off method */ |
373 | pm_power_off = kurobox_pro_power_off; | ||
232 | } | 374 | } |
233 | 375 | ||
234 | #ifdef CONFIG_MACH_KUROBOX_PRO | 376 | #ifdef CONFIG_MACH_KUROBOX_PRO |