diff options
29 files changed, 2445 insertions, 0 deletions
diff --git a/arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h b/arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h new file mode 100644 index 000000000000..7f3e3f9bd23a --- /dev/null +++ b/arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2003, 2004 Chris Dearman | ||
| 7 | * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) | ||
| 8 | */ | ||
| 9 | #ifndef __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H | ||
| 10 | #define __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H | ||
| 11 | |||
| 12 | |||
| 13 | /* | ||
| 14 | * CPU feature overrides for MIPS boards | ||
| 15 | */ | ||
| 16 | #ifdef CONFIG_CPU_MIPS32 | ||
| 17 | #define cpu_has_tlb 1 | ||
| 18 | #define cpu_has_4kex 1 | ||
| 19 | #define cpu_has_4k_cache 1 | ||
| 20 | /* #define cpu_has_fpu ? */ | ||
| 21 | /* #define cpu_has_32fpr ? */ | ||
| 22 | #define cpu_has_counter 1 | ||
| 23 | /* #define cpu_has_watch ? */ | ||
| 24 | #define cpu_has_divec 1 | ||
| 25 | #define cpu_has_vce 0 | ||
| 26 | /* #define cpu_has_cache_cdex_p ? */ | ||
| 27 | /* #define cpu_has_cache_cdex_s ? */ | ||
| 28 | /* #define cpu_has_prefetch ? */ | ||
| 29 | #define cpu_has_mcheck 1 | ||
| 30 | /* #define cpu_has_ejtag ? */ | ||
| 31 | #ifdef CONFIG_CPU_HAS_LLSC | ||
| 32 | #define cpu_has_llsc 1 | ||
| 33 | #else | ||
| 34 | #define cpu_has_llsc 0 | ||
| 35 | #endif | ||
| 36 | /* #define cpu_has_vtag_icache ? */ | ||
| 37 | /* #define cpu_has_dc_aliases ? */ | ||
| 38 | /* #define cpu_has_ic_fills_f_dc ? */ | ||
| 39 | #define cpu_has_nofpuex 0 | ||
| 40 | /* #define cpu_has_64bits ? */ | ||
| 41 | /* #define cpu_has_64bit_zero_reg ? */ | ||
| 42 | /* #define cpu_has_inclusive_pcaches ? */ | ||
| 43 | #define cpu_icache_snoops_remote_store 1 | ||
| 44 | #endif | ||
| 45 | |||
| 46 | #ifdef CONFIG_CPU_MIPS64 | ||
| 47 | #define cpu_has_tlb 1 | ||
| 48 | #define cpu_has_4kex 1 | ||
| 49 | #define cpu_has_4k_cache 1 | ||
| 50 | /* #define cpu_has_fpu ? */ | ||
| 51 | /* #define cpu_has_32fpr ? */ | ||
| 52 | #define cpu_has_counter 1 | ||
| 53 | /* #define cpu_has_watch ? */ | ||
| 54 | #define cpu_has_divec 1 | ||
| 55 | #define cpu_has_vce 0 | ||
| 56 | /* #define cpu_has_cache_cdex_p ? */ | ||
| 57 | /* #define cpu_has_cache_cdex_s ? */ | ||
| 58 | /* #define cpu_has_prefetch ? */ | ||
| 59 | #define cpu_has_mcheck 1 | ||
| 60 | /* #define cpu_has_ejtag ? */ | ||
| 61 | #define cpu_has_llsc 1 | ||
| 62 | /* #define cpu_has_vtag_icache ? */ | ||
| 63 | /* #define cpu_has_dc_aliases ? */ | ||
| 64 | /* #define cpu_has_ic_fills_f_dc ? */ | ||
| 65 | #define cpu_has_nofpuex 0 | ||
| 66 | /* #define cpu_has_64bits ? */ | ||
| 67 | /* #define cpu_has_64bit_zero_reg ? */ | ||
| 68 | /* #define cpu_has_inclusive_pcaches ? */ | ||
| 69 | #define cpu_icache_snoops_remote_store 1 | ||
| 70 | #endif | ||
| 71 | |||
| 72 | #endif /* __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H */ | ||
diff --git a/arch/mips/include/asm/mach-sead3/irq.h b/arch/mips/include/asm/mach-sead3/irq.h new file mode 100644 index 000000000000..652ea4c38cda --- /dev/null +++ b/arch/mips/include/asm/mach-sead3/irq.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | #ifndef __ASM_MACH_MIPS_IRQ_H | ||
| 2 | #define __ASM_MACH_MIPS_IRQ_H | ||
| 3 | |||
| 4 | #define NR_IRQS 256 | ||
| 5 | |||
| 6 | |||
| 7 | #include_next <irq.h> | ||
| 8 | |||
| 9 | #endif /* __ASM_MACH_MIPS_IRQ_H */ | ||
diff --git a/arch/mips/include/asm/mach-sead3/kernel-entry-init.h b/arch/mips/include/asm/mach-sead3/kernel-entry-init.h new file mode 100644 index 000000000000..3dfbd8e7947f --- /dev/null +++ b/arch/mips/include/asm/mach-sead3/kernel-entry-init.h | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Chris Dearman (chris@mips.com) | ||
| 7 | * Copyright (C) 2007 Mips Technologies, Inc. | ||
| 8 | */ | ||
| 9 | #ifndef __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H | ||
| 10 | #define __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H | ||
| 11 | |||
| 12 | .macro kernel_entry_setup | ||
| 13 | #ifdef CONFIG_MIPS_MT_SMTC | ||
| 14 | mfc0 t0, CP0_CONFIG | ||
| 15 | bgez t0, 9f | ||
| 16 | mfc0 t0, CP0_CONFIG, 1 | ||
| 17 | bgez t0, 9f | ||
| 18 | mfc0 t0, CP0_CONFIG, 2 | ||
| 19 | bgez t0, 9f | ||
| 20 | mfc0 t0, CP0_CONFIG, 3 | ||
| 21 | and t0, 1<<2 | ||
| 22 | bnez t0, 0f | ||
| 23 | 9 : | ||
| 24 | /* Assume we came from YAMON... */ | ||
| 25 | PTR_LA v0, 0x9fc00534 /* YAMON print */ | ||
| 26 | lw v0, (v0) | ||
| 27 | move a0, zero | ||
| 28 | PTR_LA a1, nonmt_processor | ||
| 29 | jal v0 | ||
| 30 | |||
| 31 | PTR_LA v0, 0x9fc00520 /* YAMON exit */ | ||
| 32 | lw v0, (v0) | ||
| 33 | li a0, 1 | ||
| 34 | jal v0 | ||
| 35 | |||
| 36 | 1 : b 1b | ||
| 37 | |||
| 38 | __INITDATA | ||
| 39 | nonmt_processor : | ||
| 40 | .asciz "SMTC kernel requires the MT ASE to run\n" | ||
| 41 | __FINIT | ||
| 42 | 0 : | ||
| 43 | #endif | ||
| 44 | .endm | ||
| 45 | |||
| 46 | /* | ||
| 47 | * Do SMP slave processor setup necessary before we can safely execute C code. | ||
| 48 | */ | ||
| 49 | .macro smp_slave_setup | ||
| 50 | .endm | ||
| 51 | |||
| 52 | #endif /* __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H */ | ||
diff --git a/arch/mips/include/asm/mach-sead3/war.h b/arch/mips/include/asm/mach-sead3/war.h new file mode 100644 index 000000000000..7c6931d5f45f --- /dev/null +++ b/arch/mips/include/asm/mach-sead3/war.h | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> | ||
| 7 | */ | ||
| 8 | #ifndef __ASM_MIPS_MACH_MIPS_WAR_H | ||
| 9 | #define __ASM_MIPS_MACH_MIPS_WAR_H | ||
| 10 | |||
| 11 | #define R4600_V1_INDEX_ICACHEOP_WAR 0 | ||
| 12 | #define R4600_V1_HIT_CACHEOP_WAR 0 | ||
| 13 | #define R4600_V2_HIT_CACHEOP_WAR 0 | ||
| 14 | #define R5432_CP0_INTERRUPT_WAR 0 | ||
| 15 | #define BCM1250_M3_WAR 0 | ||
| 16 | #define SIBYTE_1956_WAR 0 | ||
| 17 | #define MIPS4K_ICACHE_REFILL_WAR 1 | ||
| 18 | #define MIPS_CACHE_SYNC_WAR 1 | ||
| 19 | #define TX49XX_ICACHE_INDEX_INV_WAR 0 | ||
| 20 | #define RM9000_CDEX_SMP_WAR 0 | ||
| 21 | #define ICACHE_REFILLS_WORKAROUND_WAR 1 | ||
| 22 | #define R10000_LLSC_WAR 0 | ||
| 23 | #define MIPS34K_MISSED_ITLB_WAR 0 | ||
| 24 | |||
| 25 | #endif /* __ASM_MIPS_MACH_MIPS_WAR_H */ | ||
diff --git a/arch/mips/include/asm/mips-boards/sead3int.h b/arch/mips/include/asm/mips-boards/sead3int.h new file mode 100644 index 000000000000..d634d9a807f6 --- /dev/null +++ b/arch/mips/include/asm/mips-boards/sead3int.h | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2000,2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | * Douglas Leung <douglas@mips.com> | ||
| 8 | * Steven J. Hill <sjhill@mips.com> | ||
| 9 | */ | ||
| 10 | #ifndef _MIPS_SEAD3INT_H | ||
| 11 | #define _MIPS_SEAD3INT_H | ||
| 12 | |||
| 13 | /* SEAD-3 GIC address space definitions. */ | ||
| 14 | #define GIC_BASE_ADDR 0x1b1c0000 | ||
| 15 | #define GIC_ADDRSPACE_SZ (128 * 1024) | ||
| 16 | |||
| 17 | #define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 0) | ||
| 18 | |||
| 19 | #endif /* !(_MIPS_SEAD3INT_H) */ | ||
diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile new file mode 100644 index 000000000000..626afeac4386 --- /dev/null +++ b/arch/mips/mti-sead3/Makefile | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | # | ||
| 2 | # Carsten Langgaard, carstenl@mips.com | ||
| 3 | # Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. | ||
| 4 | # | ||
| 5 | # Copyright (C) 2008 Wind River Systems, Inc. | ||
| 6 | # written by Ralf Baechle <ralf@linux-mips.org> | ||
| 7 | # | ||
| 8 | obj-y := sead3-lcd.o sead3-cmdline.o \ | ||
| 9 | sead3-display.o sead3-init.o sead3-int.o \ | ||
| 10 | sead3-mtd.o sead3-net.o \ | ||
| 11 | sead3-memory.o sead3-platform.o \ | ||
| 12 | sead3-reset.o sead3-setup.o sead3-time.o | ||
| 13 | |||
| 14 | obj-y += sead3-i2c-dev.o sead3-i2c.o \ | ||
| 15 | sead3-pic32-i2c-drv.o sead3-pic32-bus.o \ | ||
| 16 | leds-sead3.o sead3-leds.o | ||
| 17 | |||
| 18 | obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o | ||
| 19 | obj-$(CONFIG_USB_EHCI_HCD) += sead3-ehci.o | ||
diff --git a/arch/mips/mti-sead3/Platform b/arch/mips/mti-sead3/Platform new file mode 100644 index 000000000000..387092427145 --- /dev/null +++ b/arch/mips/mti-sead3/Platform | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | # | ||
| 2 | # MIPS SEAD-3 board | ||
| 3 | # | ||
| 4 | platform-$(CONFIG_MIPS_SEAD3) += mti-sead3/ | ||
| 5 | cflags-$(CONFIG_MIPS_SEAD3) += -I$(srctree)/arch/mips/include/asm/mach-sead3 | ||
| 6 | load-$(CONFIG_MIPS_SEAD3) += 0xffffffff80100000 | ||
| 7 | all-$(CONFIG_MIPS_SEAD3) := $(COMPRESSION_FNAME).srec | ||
diff --git a/arch/mips/mti-sead3/leds-sead3.c b/arch/mips/mti-sead3/leds-sead3.c new file mode 100644 index 000000000000..a95ac5985206 --- /dev/null +++ b/arch/mips/mti-sead3/leds-sead3.c | |||
| @@ -0,0 +1,128 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/kernel.h> | ||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/init.h> | ||
| 11 | #include <linux/platform_device.h> | ||
| 12 | #include <linux/leds.h> | ||
| 13 | #include <linux/err.h> | ||
| 14 | #include <linux/io.h> | ||
| 15 | |||
| 16 | #define DRVNAME "sead3-led" | ||
| 17 | |||
| 18 | static struct platform_device *pdev; | ||
| 19 | |||
| 20 | static void sead3_pled_set(struct led_classdev *led_cdev, | ||
| 21 | enum led_brightness value) | ||
| 22 | { | ||
| 23 | pr_debug("sead3_pled_set\n"); | ||
| 24 | writel(value, (void __iomem *)0xBF000210); /* FIXME */ | ||
| 25 | } | ||
| 26 | |||
| 27 | static void sead3_fled_set(struct led_classdev *led_cdev, | ||
| 28 | enum led_brightness value) | ||
| 29 | { | ||
| 30 | pr_debug("sead3_fled_set\n"); | ||
| 31 | writel(value, (void __iomem *)0xBF000218); /* FIXME */ | ||
| 32 | } | ||
| 33 | |||
| 34 | static struct led_classdev sead3_pled = { | ||
| 35 | .name = "sead3::pled", | ||
| 36 | .brightness_set = sead3_pled_set, | ||
| 37 | }; | ||
| 38 | |||
| 39 | static struct led_classdev sead3_fled = { | ||
| 40 | .name = "sead3::fled", | ||
| 41 | .brightness_set = sead3_fled_set, | ||
| 42 | }; | ||
| 43 | |||
| 44 | #ifdef CONFIG_PM | ||
| 45 | static int sead3_led_suspend(struct platform_device *dev, | ||
| 46 | pm_message_t state) | ||
| 47 | { | ||
| 48 | led_classdev_suspend(&sead3_pled); | ||
| 49 | led_classdev_suspend(&sead3_fled); | ||
| 50 | return 0; | ||
| 51 | } | ||
| 52 | |||
| 53 | static int sead3_led_resume(struct platform_device *dev) | ||
| 54 | { | ||
| 55 | led_classdev_resume(&sead3_pled); | ||
| 56 | led_classdev_resume(&sead3_fled); | ||
| 57 | return 0; | ||
| 58 | } | ||
| 59 | #else | ||
| 60 | #define sead3_led_suspend NULL | ||
| 61 | #define sead3_led_resume NULL | ||
| 62 | #endif | ||
| 63 | |||
| 64 | static int sead3_led_probe(struct platform_device *pdev) | ||
| 65 | { | ||
| 66 | int ret; | ||
| 67 | |||
| 68 | ret = led_classdev_register(&pdev->dev, &sead3_pled); | ||
| 69 | if (ret < 0) | ||
| 70 | return ret; | ||
| 71 | |||
| 72 | ret = led_classdev_register(&pdev->dev, &sead3_fled); | ||
| 73 | if (ret < 0) | ||
| 74 | led_classdev_unregister(&sead3_pled); | ||
| 75 | |||
| 76 | return ret; | ||
| 77 | } | ||
| 78 | |||
| 79 | static int sead3_led_remove(struct platform_device *pdev) | ||
| 80 | { | ||
| 81 | led_classdev_unregister(&sead3_pled); | ||
| 82 | led_classdev_unregister(&sead3_fled); | ||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | static struct platform_driver sead3_led_driver = { | ||
| 87 | .probe = sead3_led_probe, | ||
| 88 | .remove = sead3_led_remove, | ||
| 89 | .suspend = sead3_led_suspend, | ||
| 90 | .resume = sead3_led_resume, | ||
| 91 | .driver = { | ||
| 92 | .name = DRVNAME, | ||
| 93 | .owner = THIS_MODULE, | ||
| 94 | }, | ||
| 95 | }; | ||
| 96 | |||
| 97 | static int __init sead3_led_init(void) | ||
| 98 | { | ||
| 99 | int ret; | ||
| 100 | |||
| 101 | ret = platform_driver_register(&sead3_led_driver); | ||
| 102 | if (ret < 0) | ||
| 103 | goto out; | ||
| 104 | |||
| 105 | pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); | ||
| 106 | if (IS_ERR(pdev)) { | ||
| 107 | ret = PTR_ERR(pdev); | ||
| 108 | platform_driver_unregister(&sead3_led_driver); | ||
| 109 | goto out; | ||
| 110 | } | ||
| 111 | |||
| 112 | out: | ||
| 113 | return ret; | ||
| 114 | } | ||
| 115 | |||
| 116 | static void __exit sead3_led_exit(void) | ||
| 117 | { | ||
| 118 | platform_device_unregister(pdev); | ||
| 119 | platform_driver_unregister(&sead3_led_driver); | ||
| 120 | } | ||
| 121 | |||
| 122 | module_init(sead3_led_init); | ||
| 123 | module_exit(sead3_led_exit); | ||
| 124 | |||
| 125 | MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>"); | ||
| 126 | MODULE_DESCRIPTION("SEAD3 LED driver"); | ||
| 127 | MODULE_LICENSE("GPL"); | ||
| 128 | |||
diff --git a/arch/mips/mti-sead3/sead3-cmdline.c b/arch/mips/mti-sead3/sead3-cmdline.c new file mode 100644 index 000000000000..a2e6cec67f57 --- /dev/null +++ b/arch/mips/mti-sead3/sead3-cmdline.c | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/string.h> | ||
| 10 | |||
| 11 | #include <asm/bootinfo.h> | ||
| 12 | |||
| 13 | extern int prom_argc; | ||
| 14 | extern int *_prom_argv; | ||
| 15 | |||
| 16 | /* | ||
| 17 | * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer. | ||
| 18 | * This macro take care of sign extension. | ||
| 19 | */ | ||
| 20 | #define prom_argv(index) ((char *)(long)_prom_argv[(index)]) | ||
| 21 | |||
| 22 | char * __init prom_getcmdline(void) | ||
| 23 | { | ||
| 24 | return &(arcs_cmdline[0]); | ||
| 25 | } | ||
| 26 | |||
| 27 | void __init prom_init_cmdline(void) | ||
| 28 | { | ||
| 29 | char *cp; | ||
| 30 | int actr; | ||
| 31 | |||
| 32 | actr = 1; /* Always ignore argv[0] */ | ||
| 33 | |||
| 34 | cp = &(arcs_cmdline[0]); | ||
| 35 | while (actr < prom_argc) { | ||
| 36 | strcpy(cp, prom_argv(actr)); | ||
| 37 | cp += strlen(prom_argv(actr)); | ||
| 38 | *cp++ = ' '; | ||
| 39 | actr++; | ||
| 40 | } | ||
| 41 | if (cp != &(arcs_cmdline[0])) { | ||
| 42 | /* get rid of trailing space */ | ||
| 43 | --cp; | ||
| 44 | *cp = '\0'; | ||
| 45 | } | ||
| 46 | } | ||
diff --git a/arch/mips/mti-sead3/sead3-console.c b/arch/mips/mti-sead3/sead3-console.c new file mode 100644 index 000000000000..b36739108a0f --- /dev/null +++ b/arch/mips/mti-sead3/sead3-console.c | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/console.h> | ||
| 10 | #include <linux/serial_reg.h> | ||
| 11 | #include <linux/io.h> | ||
| 12 | |||
| 13 | #define SEAD_UART1_REGS_BASE 0xbf000800 /* ttyS1 = DB9 port */ | ||
| 14 | #define SEAD_UART0_REGS_BASE 0xbf000900 /* ttyS0 = USB port */ | ||
| 15 | #define PORT(base_addr, offset) ((unsigned int __iomem *)(base_addr+(offset)*4)) | ||
| 16 | |||
| 17 | static char console_port = 1; | ||
| 18 | |||
| 19 | static inline unsigned int serial_in(int offset, unsigned int base_addr) | ||
| 20 | { | ||
| 21 | return __raw_readl(PORT(base_addr, offset)) & 0xff; | ||
| 22 | } | ||
| 23 | |||
| 24 | static inline void serial_out(int offset, int value, unsigned int base_addr) | ||
| 25 | { | ||
| 26 | __raw_writel(value, PORT(base_addr, offset)); | ||
| 27 | } | ||
| 28 | |||
| 29 | void __init prom_init_early_console(char port) | ||
| 30 | { | ||
| 31 | console_port = port; | ||
| 32 | } | ||
| 33 | |||
| 34 | int prom_putchar(char c) | ||
| 35 | { | ||
| 36 | unsigned int base_addr; | ||
| 37 | |||
| 38 | base_addr = console_port ? SEAD_UART1_REGS_BASE : SEAD_UART0_REGS_BASE; | ||
| 39 | |||
| 40 | while ((serial_in(UART_LSR, base_addr) & UART_LSR_THRE) == 0) | ||
| 41 | ; | ||
| 42 | |||
| 43 | serial_out(UART_TX, c, base_addr); | ||
| 44 | |||
| 45 | return 1; | ||
| 46 | } | ||
diff --git a/arch/mips/mti-sead3/sead3-display.c b/arch/mips/mti-sead3/sead3-display.c new file mode 100644 index 000000000000..8308c7fc188a --- /dev/null +++ b/arch/mips/mti-sead3/sead3-display.c | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/timer.h> | ||
| 9 | #include <linux/io.h> | ||
| 10 | #include <asm/mips-boards/generic.h> | ||
| 11 | #include <asm/mips-boards/prom.h> | ||
| 12 | |||
| 13 | static unsigned int display_count; | ||
| 14 | static unsigned int max_display_count; | ||
| 15 | |||
| 16 | #define LCD_DISPLAY_POS_BASE 0x1f000400 | ||
| 17 | #define DISPLAY_LCDINSTRUCTION (0*2) | ||
| 18 | #define DISPLAY_LCDDATA (1*2) | ||
| 19 | #define DISPLAY_CPLDSTATUS (2*2) | ||
| 20 | #define DISPLAY_CPLDDATA (3*2) | ||
| 21 | #define LCD_SETDDRAM 0x80 | ||
| 22 | #define LCD_IR_BF 0x80 | ||
| 23 | |||
| 24 | const char display_string[] = " LINUX ON SEAD3 "; | ||
| 25 | |||
| 26 | static void scroll_display_message(unsigned long data); | ||
| 27 | static DEFINE_TIMER(mips_scroll_timer, scroll_display_message, HZ, 0); | ||
| 28 | |||
| 29 | static void lcd_wait(unsigned int __iomem *display) | ||
| 30 | { | ||
| 31 | /* Wait for CPLD state machine to become idle. */ | ||
| 32 | do { } while (__raw_readl(display + DISPLAY_CPLDSTATUS) & 1); | ||
| 33 | |||
| 34 | do { | ||
| 35 | __raw_readl(display + DISPLAY_LCDINSTRUCTION); | ||
| 36 | |||
| 37 | /* Wait for CPLD state machine to become idle. */ | ||
| 38 | do { } while (__raw_readl(display + DISPLAY_CPLDSTATUS) & 1); | ||
| 39 | } while (__raw_readl(display + DISPLAY_CPLDDATA) & LCD_IR_BF); | ||
| 40 | } | ||
| 41 | |||
| 42 | void mips_display_message(const char *str) | ||
| 43 | { | ||
| 44 | static unsigned int __iomem *display; | ||
| 45 | char ch; | ||
| 46 | int i; | ||
| 47 | |||
| 48 | if (unlikely(display == NULL)) | ||
| 49 | display = ioremap_nocache(LCD_DISPLAY_POS_BASE, | ||
| 50 | (8 * sizeof(int))); | ||
| 51 | |||
| 52 | for (i = 0; i < 16; i++) { | ||
| 53 | if (*str) | ||
| 54 | ch = *str++; | ||
| 55 | else | ||
| 56 | ch = ' '; | ||
| 57 | lcd_wait(display); | ||
| 58 | __raw_writel((LCD_SETDDRAM | i), | ||
| 59 | (display + DISPLAY_LCDINSTRUCTION)); | ||
| 60 | lcd_wait(display); | ||
| 61 | __raw_writel(ch, display + DISPLAY_LCDDATA); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | static void scroll_display_message(unsigned long data) | ||
| 66 | { | ||
| 67 | mips_display_message(&display_string[display_count++]); | ||
| 68 | if (display_count == max_display_count) | ||
| 69 | display_count = 0; | ||
| 70 | mod_timer(&mips_scroll_timer, jiffies + HZ); | ||
| 71 | } | ||
| 72 | |||
| 73 | void mips_scroll_message(void) | ||
| 74 | { | ||
| 75 | del_timer_sync(&mips_scroll_timer); | ||
| 76 | max_display_count = strlen(display_string) + 1 - 16; | ||
| 77 | mod_timer(&mips_scroll_timer, jiffies + 1); | ||
| 78 | } | ||
diff --git a/arch/mips/mti-sead3/sead3-ehci.c b/arch/mips/mti-sead3/sead3-ehci.c new file mode 100644 index 000000000000..772fc056a92d --- /dev/null +++ b/arch/mips/mti-sead3/sead3-ehci.c | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/module.h> | ||
| 9 | #include <linux/irq.h> | ||
| 10 | #include <linux/dma-mapping.h> | ||
| 11 | #include <linux/platform_device.h> | ||
| 12 | |||
| 13 | struct resource ehci_resources[] = { | ||
| 14 | { | ||
| 15 | .start = 0x1b200000, | ||
| 16 | .end = 0x1b200fff, | ||
| 17 | .flags = IORESOURCE_MEM | ||
| 18 | }, | ||
| 19 | { | ||
| 20 | .start = MIPS_CPU_IRQ_BASE + 2, | ||
| 21 | .flags = IORESOURCE_IRQ | ||
| 22 | } | ||
| 23 | }; | ||
| 24 | |||
| 25 | u64 sead3_usbdev_dma_mask = DMA_BIT_MASK(32); | ||
| 26 | |||
| 27 | static struct platform_device ehci_device = { | ||
| 28 | .name = "sead3-ehci", | ||
| 29 | .id = 0, | ||
| 30 | .dev = { | ||
| 31 | .dma_mask = &sead3_usbdev_dma_mask, | ||
| 32 | .coherent_dma_mask = DMA_BIT_MASK(32) | ||
| 33 | }, | ||
| 34 | .num_resources = ARRAY_SIZE(ehci_resources), | ||
| 35 | .resource = ehci_resources | ||
| 36 | }; | ||
| 37 | |||
| 38 | static int __init ehci_init(void) | ||
| 39 | { | ||
| 40 | return platform_device_register(&ehci_device); | ||
| 41 | } | ||
| 42 | |||
| 43 | module_init(ehci_init); | ||
| 44 | |||
| 45 | MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); | ||
| 46 | MODULE_LICENSE("GPL"); | ||
| 47 | MODULE_DESCRIPTION("EHCI probe driver for SEAD3"); | ||
diff --git a/arch/mips/mti-sead3/sead3-i2c-dev.c b/arch/mips/mti-sead3/sead3-i2c-dev.c new file mode 100644 index 000000000000..eca0b53a71dd --- /dev/null +++ b/arch/mips/mti-sead3/sead3-i2c-dev.c | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/i2c.h> | ||
| 10 | |||
| 11 | static struct i2c_board_info __initdata sead3_i2c_devices[] = { | ||
| 12 | { | ||
| 13 | I2C_BOARD_INFO("adt7476", 0x2c), | ||
| 14 | .irq = 0, | ||
| 15 | }, | ||
| 16 | { | ||
| 17 | I2C_BOARD_INFO("m41t80", 0x68), | ||
| 18 | .irq = 0, | ||
| 19 | }, | ||
| 20 | }; | ||
| 21 | |||
| 22 | static int __init sead3_i2c_init(void) | ||
| 23 | { | ||
| 24 | int err; | ||
| 25 | |||
| 26 | err = i2c_register_board_info(0, sead3_i2c_devices, | ||
| 27 | ARRAY_SIZE(sead3_i2c_devices)); | ||
| 28 | if (err < 0) | ||
| 29 | pr_err("sead3-i2c-dev: cannot register board I2C devices\n"); | ||
| 30 | return err; | ||
| 31 | } | ||
| 32 | |||
| 33 | arch_initcall(sead3_i2c_init); | ||
diff --git a/arch/mips/mti-sead3/sead3-i2c-drv.c b/arch/mips/mti-sead3/sead3-i2c-drv.c new file mode 100644 index 000000000000..0375ee66bca3 --- /dev/null +++ b/arch/mips/mti-sead3/sead3-i2c-drv.c | |||
| @@ -0,0 +1,405 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/slab.h> | ||
| 11 | #include <linux/delay.h> | ||
| 12 | #include <linux/i2c.h> | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | |||
| 15 | #define PIC32_I2CxCON 0x0000 | ||
| 16 | #define PIC32_I2CCON_ON (1<<15) | ||
| 17 | #define PIC32_I2CCON_ACKDT (1<<5) | ||
| 18 | #define PIC32_I2CCON_ACKEN (1<<4) | ||
| 19 | #define PIC32_I2CCON_RCEN (1<<3) | ||
| 20 | #define PIC32_I2CCON_PEN (1<<2) | ||
| 21 | #define PIC32_I2CCON_RSEN (1<<1) | ||
| 22 | #define PIC32_I2CCON_SEN (1<<0) | ||
| 23 | #define PIC32_I2CxCONCLR 0x0004 | ||
| 24 | #define PIC32_I2CxCONSET 0x0008 | ||
| 25 | #define PIC32_I2CxSTAT 0x0010 | ||
| 26 | #define PIC32_I2CxSTATCLR 0x0014 | ||
| 27 | #define PIC32_I2CSTAT_ACKSTAT (1<<15) | ||
| 28 | #define PIC32_I2CSTAT_TRSTAT (1<<14) | ||
| 29 | #define PIC32_I2CSTAT_BCL (1<<10) | ||
| 30 | #define PIC32_I2CSTAT_IWCOL (1<<7) | ||
| 31 | #define PIC32_I2CSTAT_I2COV (1<<6) | ||
| 32 | #define PIC32_I2CxBRG 0x0040 | ||
| 33 | #define PIC32_I2CxTRN 0x0050 | ||
| 34 | #define PIC32_I2CxRCV 0x0060 | ||
| 35 | |||
| 36 | static DEFINE_SPINLOCK(pic32_bus_lock); | ||
| 37 | |||
| 38 | static void __iomem *bus_xfer = (void __iomem *)0xbf000600; | ||
| 39 | static void __iomem *bus_status = (void __iomem *)0xbf000060; | ||
| 40 | |||
| 41 | #define DELAY() udelay(100) | ||
| 42 | |||
| 43 | static inline unsigned int ioready(void) | ||
| 44 | { | ||
| 45 | return readl(bus_status) & 1; | ||
| 46 | } | ||
| 47 | |||
| 48 | static inline void wait_ioready(void) | ||
| 49 | { | ||
| 50 | do { } while (!ioready()); | ||
| 51 | } | ||
| 52 | |||
| 53 | static inline void wait_ioclear(void) | ||
| 54 | { | ||
| 55 | do { } while (ioready()); | ||
| 56 | } | ||
| 57 | |||
| 58 | static inline void check_ioclear(void) | ||
| 59 | { | ||
| 60 | if (ioready()) { | ||
| 61 | do { | ||
| 62 | (void) readl(bus_xfer); | ||
| 63 | DELAY(); | ||
| 64 | } while (ioready()); | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | static u32 pic32_bus_readl(u32 reg) | ||
| 69 | { | ||
| 70 | unsigned long flags; | ||
| 71 | u32 status, val; | ||
| 72 | |||
| 73 | spin_lock_irqsave(&pic32_bus_lock, flags); | ||
| 74 | |||
| 75 | check_ioclear(); | ||
| 76 | writel((0x01 << 24) | (reg & 0x00ffffff), bus_xfer); | ||
| 77 | DELAY(); | ||
| 78 | wait_ioready(); | ||
| 79 | status = readl(bus_xfer); | ||
| 80 | DELAY(); | ||
| 81 | val = readl(bus_xfer); | ||
| 82 | wait_ioclear(); | ||
| 83 | |||
| 84 | spin_unlock_irqrestore(&pic32_bus_lock, flags); | ||
| 85 | |||
| 86 | return val; | ||
| 87 | } | ||
| 88 | |||
| 89 | static void pic32_bus_writel(u32 val, u32 reg) | ||
| 90 | { | ||
| 91 | unsigned long flags; | ||
| 92 | u32 status; | ||
| 93 | |||
| 94 | spin_lock_irqsave(&pic32_bus_lock, flags); | ||
| 95 | |||
| 96 | check_ioclear(); | ||
| 97 | writel((0x10 << 24) | (reg & 0x00ffffff), bus_xfer); | ||
| 98 | DELAY(); | ||
| 99 | writel(val, bus_xfer); | ||
| 100 | DELAY(); | ||
| 101 | wait_ioready(); | ||
| 102 | status = readl(bus_xfer); | ||
| 103 | wait_ioclear(); | ||
| 104 | |||
| 105 | spin_unlock_irqrestore(&pic32_bus_lock, flags); | ||
| 106 | } | ||
| 107 | |||
| 108 | struct pic32_i2c_platform_data { | ||
| 109 | u32 base; | ||
| 110 | struct i2c_adapter adap; | ||
| 111 | u32 xfer_timeout; | ||
| 112 | u32 ack_timeout; | ||
| 113 | u32 ctl_timeout; | ||
| 114 | }; | ||
| 115 | |||
| 116 | static inline void pic32_i2c_start(struct pic32_i2c_platform_data *adap) | ||
| 117 | { | ||
| 118 | pic32_bus_writel(PIC32_I2CCON_SEN, adap->base + PIC32_I2CxCONSET); | ||
| 119 | } | ||
| 120 | |||
| 121 | static inline void pic32_i2c_stop(struct pic32_i2c_platform_data *adap) | ||
| 122 | { | ||
| 123 | pic32_bus_writel(PIC32_I2CCON_PEN, adap->base + PIC32_I2CxCONSET); | ||
| 124 | } | ||
| 125 | |||
| 126 | static inline void pic32_i2c_ack(struct pic32_i2c_platform_data *adap) | ||
| 127 | { | ||
| 128 | pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR); | ||
| 129 | pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); | ||
| 130 | } | ||
| 131 | |||
| 132 | static inline void pic32_i2c_nack(struct pic32_i2c_platform_data *adap) | ||
| 133 | { | ||
| 134 | pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET); | ||
| 135 | pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); | ||
| 136 | } | ||
| 137 | |||
| 138 | static inline int pic32_i2c_idle(struct pic32_i2c_platform_data *adap) | ||
| 139 | { | ||
| 140 | int i; | ||
| 141 | |||
| 142 | for (i = 0; i < adap->ctl_timeout; i++) { | ||
| 143 | if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) & | ||
| 144 | (PIC32_I2CCON_ACKEN | PIC32_I2CCON_RCEN | | ||
| 145 | PIC32_I2CCON_PEN | PIC32_I2CCON_RSEN | | ||
| 146 | PIC32_I2CCON_SEN)) == 0) && | ||
| 147 | ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & | ||
| 148 | (PIC32_I2CSTAT_TRSTAT)) == 0)) | ||
| 149 | return 0; | ||
| 150 | udelay(1); | ||
| 151 | } | ||
| 152 | return -ETIMEDOUT; | ||
| 153 | } | ||
| 154 | |||
| 155 | static inline u32 pic32_i2c_master_write(struct pic32_i2c_platform_data *adap, | ||
| 156 | u32 byte) | ||
| 157 | { | ||
| 158 | pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN); | ||
| 159 | return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & | ||
| 160 | PIC32_I2CSTAT_IWCOL; | ||
| 161 | } | ||
| 162 | |||
| 163 | static inline u32 pic32_i2c_master_read(struct pic32_i2c_platform_data *adap) | ||
| 164 | { | ||
| 165 | pic32_bus_writel(PIC32_I2CCON_RCEN, adap->base + PIC32_I2CxCONSET); | ||
| 166 | while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & PIC32_I2CCON_RCEN) | ||
| 167 | ; | ||
| 168 | pic32_bus_writel(PIC32_I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR); | ||
| 169 | return pic32_bus_readl(adap->base + PIC32_I2CxRCV); | ||
| 170 | } | ||
| 171 | |||
| 172 | static int pic32_i2c_address(struct pic32_i2c_platform_data *adap, | ||
| 173 | unsigned int addr, int rd) | ||
| 174 | { | ||
| 175 | pic32_i2c_idle(adap); | ||
| 176 | pic32_i2c_start(adap); | ||
| 177 | pic32_i2c_idle(adap); | ||
| 178 | |||
| 179 | addr <<= 1; | ||
| 180 | if (rd) | ||
| 181 | addr |= 1; | ||
| 182 | |||
| 183 | if (pic32_i2c_master_write(adap, addr)) | ||
| 184 | return -EIO; | ||
| 185 | pic32_i2c_idle(adap); | ||
| 186 | if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & | ||
| 187 | PIC32_I2CSTAT_ACKSTAT) | ||
| 188 | return -EIO; | ||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | |||
| 192 | static int sead3_i2c_read(struct pic32_i2c_platform_data *adap, | ||
| 193 | unsigned char *buf, unsigned int len) | ||
| 194 | { | ||
| 195 | u32 data; | ||
| 196 | int i; | ||
| 197 | |||
| 198 | i = 0; | ||
| 199 | while (i < len) { | ||
| 200 | data = pic32_i2c_master_read(adap); | ||
| 201 | buf[i++] = data; | ||
| 202 | if (i < len) | ||
| 203 | pic32_i2c_ack(adap); | ||
| 204 | else | ||
| 205 | pic32_i2c_nack(adap); | ||
| 206 | } | ||
| 207 | |||
| 208 | pic32_i2c_stop(adap); | ||
| 209 | pic32_i2c_idle(adap); | ||
| 210 | return 0; | ||
| 211 | } | ||
| 212 | |||
| 213 | static int sead3_i2c_write(struct pic32_i2c_platform_data *adap, | ||
| 214 | unsigned char *buf, unsigned int len) | ||
| 215 | { | ||
| 216 | int i; | ||
| 217 | u32 data; | ||
| 218 | |||
| 219 | i = 0; | ||
| 220 | while (i < len) { | ||
| 221 | data = buf[i]; | ||
| 222 | if (pic32_i2c_master_write(adap, data)) | ||
| 223 | return -EIO; | ||
| 224 | pic32_i2c_idle(adap); | ||
| 225 | if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & | ||
| 226 | PIC32_I2CSTAT_ACKSTAT) | ||
| 227 | return -EIO; | ||
| 228 | i++; | ||
| 229 | } | ||
| 230 | |||
| 231 | pic32_i2c_stop(adap); | ||
| 232 | pic32_i2c_idle(adap); | ||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | static int sead3_pic32_platform_xfer(struct i2c_adapter *i2c_adap, | ||
| 237 | struct i2c_msg *msgs, int num) | ||
| 238 | { | ||
| 239 | struct pic32_i2c_platform_data *adap = i2c_adap->algo_data; | ||
| 240 | struct i2c_msg *p; | ||
| 241 | int i, err = 0; | ||
| 242 | |||
| 243 | for (i = 0; i < num; i++) { | ||
| 244 | #define __BUFSIZE 80 | ||
| 245 | int ii; | ||
| 246 | static char buf[__BUFSIZE]; | ||
| 247 | char *b = buf; | ||
| 248 | |||
| 249 | p = &msgs[i]; | ||
| 250 | b += sprintf(buf, " [%d bytes]", p->len); | ||
| 251 | if ((p->flags & I2C_M_RD) == 0) { | ||
| 252 | for (ii = 0; ii < p->len; ii++) { | ||
| 253 | if (b < &buf[__BUFSIZE-4]) { | ||
| 254 | b += sprintf(b, " %02x", p->buf[ii]); | ||
| 255 | } else { | ||
| 256 | strcat(b, "..."); | ||
| 257 | break; | ||
| 258 | } | ||
| 259 | } | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | for (i = 0; !err && i < num; i++) { | ||
| 264 | p = &msgs[i]; | ||
| 265 | err = pic32_i2c_address(adap, p->addr, p->flags & I2C_M_RD); | ||
| 266 | if (err || !p->len) | ||
| 267 | continue; | ||
| 268 | if (p->flags & I2C_M_RD) | ||
| 269 | err = sead3_i2c_read(adap, p->buf, p->len); | ||
| 270 | else | ||
| 271 | err = sead3_i2c_write(adap, p->buf, p->len); | ||
| 272 | } | ||
| 273 | |||
| 274 | /* Return the number of messages processed, or the error code. */ | ||
| 275 | if (err == 0) | ||
| 276 | err = num; | ||
| 277 | |||
| 278 | return err; | ||
| 279 | } | ||
| 280 | |||
| 281 | static u32 sead3_pic32_platform_func(struct i2c_adapter *adap) | ||
| 282 | { | ||
| 283 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
| 284 | } | ||
| 285 | |||
| 286 | static const struct i2c_algorithm sead3_platform_algo = { | ||
| 287 | .master_xfer = sead3_pic32_platform_xfer, | ||
| 288 | .functionality = sead3_pic32_platform_func, | ||
| 289 | }; | ||
| 290 | |||
| 291 | static void sead3_i2c_platform_setup(struct pic32_i2c_platform_data *priv) | ||
| 292 | { | ||
| 293 | pic32_bus_writel(500, priv->base + PIC32_I2CxBRG); | ||
| 294 | pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONCLR); | ||
| 295 | pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONSET); | ||
| 296 | pic32_bus_writel(PIC32_I2CSTAT_BCL | PIC32_I2CSTAT_IWCOL, | ||
| 297 | priv->base + PIC32_I2CxSTATCLR); | ||
| 298 | } | ||
| 299 | |||
| 300 | static int __devinit sead3_i2c_platform_probe(struct platform_device *pdev) | ||
| 301 | { | ||
| 302 | struct pic32_i2c_platform_data *priv; | ||
| 303 | struct resource *r; | ||
| 304 | int ret; | ||
| 305 | |||
| 306 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 307 | if (!r) { | ||
| 308 | ret = -ENODEV; | ||
| 309 | goto out; | ||
| 310 | } | ||
| 311 | |||
| 312 | priv = kzalloc(sizeof(struct pic32_i2c_platform_data), GFP_KERNEL); | ||
| 313 | if (!priv) { | ||
| 314 | ret = -ENOMEM; | ||
| 315 | goto out; | ||
| 316 | } | ||
| 317 | |||
| 318 | priv->base = r->start; | ||
| 319 | if (!priv->base) { | ||
| 320 | ret = -EBUSY; | ||
| 321 | goto out_mem; | ||
| 322 | } | ||
| 323 | |||
| 324 | priv->xfer_timeout = 200; | ||
| 325 | priv->ack_timeout = 200; | ||
| 326 | priv->ctl_timeout = 200; | ||
| 327 | |||
| 328 | priv->adap.nr = pdev->id; | ||
| 329 | priv->adap.algo = &sead3_platform_algo; | ||
| 330 | priv->adap.algo_data = priv; | ||
| 331 | priv->adap.dev.parent = &pdev->dev; | ||
| 332 | strlcpy(priv->adap.name, "SEAD3 PIC32", sizeof(priv->adap.name)); | ||
| 333 | |||
| 334 | sead3_i2c_platform_setup(priv); | ||
| 335 | |||
| 336 | ret = i2c_add_numbered_adapter(&priv->adap); | ||
| 337 | if (ret == 0) { | ||
| 338 | platform_set_drvdata(pdev, priv); | ||
| 339 | return 0; | ||
| 340 | } | ||
| 341 | |||
| 342 | out_mem: | ||
| 343 | kfree(priv); | ||
| 344 | out: | ||
| 345 | return ret; | ||
| 346 | } | ||
| 347 | |||
| 348 | static int __devexit sead3_i2c_platform_remove(struct platform_device *pdev) | ||
| 349 | { | ||
| 350 | struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); | ||
| 351 | |||
| 352 | platform_set_drvdata(pdev, NULL); | ||
| 353 | i2c_del_adapter(&priv->adap); | ||
| 354 | kfree(priv); | ||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | #ifdef CONFIG_PM | ||
| 359 | static int sead3_i2c_platform_suspend(struct platform_device *pdev, | ||
| 360 | pm_message_t state) | ||
| 361 | { | ||
| 362 | dev_dbg(&pdev->dev, "i2c_platform_disable\n"); | ||
| 363 | return 0; | ||
| 364 | } | ||
| 365 | |||
| 366 | static int sead3_i2c_platform_resume(struct platform_device *pdev) | ||
| 367 | { | ||
| 368 | struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); | ||
| 369 | |||
| 370 | dev_dbg(&pdev->dev, "sead3_i2c_platform_setup\n"); | ||
| 371 | sead3_i2c_platform_setup(priv); | ||
| 372 | |||
| 373 | return 0; | ||
| 374 | } | ||
| 375 | #else | ||
| 376 | #define sead3_i2c_platform_suspend NULL | ||
| 377 | #define sead3_i2c_platform_resume NULL | ||
| 378 | #endif | ||
| 379 | |||
| 380 | static struct platform_driver sead3_i2c_platform_driver = { | ||
| 381 | .driver = { | ||
| 382 | .name = "sead3-i2c", | ||
| 383 | .owner = THIS_MODULE, | ||
| 384 | }, | ||
| 385 | .probe = sead3_i2c_platform_probe, | ||
| 386 | .remove = __devexit_p(sead3_i2c_platform_remove), | ||
| 387 | .suspend = sead3_i2c_platform_suspend, | ||
| 388 | .resume = sead3_i2c_platform_resume, | ||
| 389 | }; | ||
| 390 | |||
| 391 | static int __init sead3_i2c_platform_init(void) | ||
| 392 | { | ||
| 393 | return platform_driver_register(&sead3_i2c_platform_driver); | ||
| 394 | } | ||
| 395 | module_init(sead3_i2c_platform_init); | ||
| 396 | |||
| 397 | static void __exit sead3_i2c_platform_exit(void) | ||
| 398 | { | ||
| 399 | platform_driver_unregister(&sead3_i2c_platform_driver); | ||
| 400 | } | ||
| 401 | module_exit(sead3_i2c_platform_exit); | ||
| 402 | |||
| 403 | MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC."); | ||
| 404 | MODULE_DESCRIPTION("SEAD3 PIC32 I2C driver"); | ||
| 405 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/mips/mti-sead3/sead3-i2c.c b/arch/mips/mti-sead3/sead3-i2c.c new file mode 100644 index 000000000000..f70d5fc58ef5 --- /dev/null +++ b/arch/mips/mti-sead3/sead3-i2c.c | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/module.h> | ||
| 9 | #include <linux/init.h> | ||
| 10 | #include <linux/platform_device.h> | ||
| 11 | #include <irq.h> | ||
| 12 | |||
| 13 | struct resource sead3_i2c_resources[] = { | ||
| 14 | { | ||
| 15 | .start = 0x805200, | ||
| 16 | .end = 0x8053ff, | ||
| 17 | .flags = IORESOURCE_MEM, | ||
| 18 | }, | ||
| 19 | }; | ||
| 20 | |||
| 21 | static struct platform_device sead3_i2c_device = { | ||
| 22 | .name = "sead3-i2c", | ||
| 23 | .id = 0, | ||
| 24 | .num_resources = ARRAY_SIZE(sead3_i2c_resources), | ||
| 25 | .resource = sead3_i2c_resources, | ||
| 26 | }; | ||
| 27 | |||
| 28 | static int __init sead3_i2c_init(void) | ||
| 29 | { | ||
| 30 | return platform_device_register(&sead3_i2c_device); | ||
| 31 | } | ||
| 32 | |||
| 33 | module_init(sead3_i2c_init); | ||
| 34 | |||
| 35 | MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); | ||
| 36 | MODULE_LICENSE("GPL"); | ||
| 37 | MODULE_DESCRIPTION("I2C probe driver for SEAD3"); | ||
diff --git a/arch/mips/mti-sead3/sead3-init.c b/arch/mips/mti-sead3/sead3-init.c new file mode 100644 index 000000000000..a958cad6fff6 --- /dev/null +++ b/arch/mips/mti-sead3/sead3-init.c | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/io.h> | ||
| 10 | |||
| 11 | #include <asm/bootinfo.h> | ||
| 12 | #include <asm/cacheflush.h> | ||
| 13 | #include <asm/traps.h> | ||
| 14 | #include <asm/mips-boards/generic.h> | ||
| 15 | #include <asm/mips-boards/prom.h> | ||
| 16 | |||
| 17 | extern void prom_init_early_console(char port); | ||
| 18 | |||
| 19 | extern char except_vec_nmi; | ||
| 20 | extern char except_vec_ejtag_debug; | ||
| 21 | |||
| 22 | int prom_argc; | ||
| 23 | int *_prom_argv, *_prom_envp; | ||
| 24 | |||
| 25 | #define prom_envp(index) ((char *)(long)_prom_envp[(index)]) | ||
| 26 | |||
| 27 | char *prom_getenv(char *envname) | ||
| 28 | { | ||
| 29 | /* | ||
| 30 | * Return a pointer to the given environment variable. | ||
| 31 | * In 64-bit mode: we're using 64-bit pointers, but all pointers | ||
| 32 | * in the PROM structures are only 32-bit, so we need some | ||
| 33 | * workarounds, if we are running in 64-bit mode. | ||
| 34 | */ | ||
| 35 | int i, index = 0; | ||
| 36 | |||
| 37 | i = strlen(envname); | ||
| 38 | |||
| 39 | while (prom_envp(index)) { | ||
| 40 | if (strncmp(envname, prom_envp(index), i) == 0) | ||
| 41 | return prom_envp(index+1); | ||
| 42 | index += 2; | ||
| 43 | } | ||
| 44 | |||
| 45 | return NULL; | ||
| 46 | } | ||
| 47 | |||
| 48 | static void __init mips_nmi_setup(void) | ||
| 49 | { | ||
| 50 | void *base; | ||
| 51 | |||
| 52 | base = cpu_has_veic ? | ||
| 53 | (void *)(CAC_BASE + 0xa80) : | ||
| 54 | (void *)(CAC_BASE + 0x380); | ||
| 55 | memcpy(base, &except_vec_nmi, 0x80); | ||
| 56 | flush_icache_range((unsigned long)base, (unsigned long)base + 0x80); | ||
| 57 | } | ||
| 58 | |||
| 59 | static void __init mips_ejtag_setup(void) | ||
| 60 | { | ||
| 61 | void *base; | ||
| 62 | |||
| 63 | base = cpu_has_veic ? | ||
| 64 | (void *)(CAC_BASE + 0xa00) : | ||
| 65 | (void *)(CAC_BASE + 0x300); | ||
| 66 | memcpy(base, &except_vec_ejtag_debug, 0x80); | ||
| 67 | flush_icache_range((unsigned long)base, (unsigned long)base + 0x80); | ||
| 68 | } | ||
| 69 | |||
| 70 | void __init prom_init(void) | ||
| 71 | { | ||
| 72 | prom_argc = fw_arg0; | ||
| 73 | _prom_argv = (int *) fw_arg1; | ||
| 74 | _prom_envp = (int *) fw_arg2; | ||
| 75 | |||
| 76 | board_nmi_handler_setup = mips_nmi_setup; | ||
| 77 | board_ejtag_handler_setup = mips_ejtag_setup; | ||
| 78 | |||
| 79 | prom_init_cmdline(); | ||
| 80 | prom_meminit(); | ||
| 81 | #ifdef CONFIG_EARLY_PRINTK | ||
| 82 | if ((strstr(prom_getcmdline(), "console=ttyS0")) != NULL) | ||
| 83 | prom_init_early_console(0); | ||
| 84 | else if ((strstr(prom_getcmdline(), "console=ttyS1")) != NULL) | ||
| 85 | prom_init_early_console(1); | ||
| 86 | #endif | ||
| 87 | #ifdef CONFIG_SERIAL_8250_CONSOLE | ||
| 88 | if ((strstr(prom_getcmdline(), "console=")) == NULL) | ||
| 89 | strcat(prom_getcmdline(), " console=ttyS0,38400n8r"); | ||
| 90 | #endif | ||
| 91 | } | ||
diff --git a/arch/mips/mti-sead3/sead3-int.c b/arch/mips/mti-sead3/sead3-int.c new file mode 100644 index 000000000000..e26e08274fc5 --- /dev/null +++ b/arch/mips/mti-sead3/sead3-int.c | |||
| @@ -0,0 +1,158 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/irq.h> | ||
| 10 | #include <linux/io.h> | ||
| 11 | |||
| 12 | #include <asm/gic.h> | ||
| 13 | #include <asm/irq_cpu.h> | ||
| 14 | #include <asm/setup.h> | ||
| 15 | |||
| 16 | #include <asm/mips-boards/sead3int.h> | ||
| 17 | |||
| 18 | #define SEAD_CONFIG_GIC_PRESENT_SHF 1 | ||
| 19 | #define SEAD_CONFIG_GIC_PRESENT_MSK (1 << SEAD_CONFIG_GIC_PRESENT_SHF) | ||
| 20 | #define SEAD_CONFIG_BASE 0x1b100110 | ||
| 21 | #define SEAD_CONFIG_SIZE 4 | ||
| 22 | |||
| 23 | int gic_present; | ||
| 24 | static unsigned long sead3_config_reg; | ||
| 25 | |||
| 26 | /* | ||
| 27 | * This table defines the setup for each external GIC interrupt. It is | ||
| 28 | * indexed by interrupt number. | ||
| 29 | */ | ||
| 30 | #define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK | ||
| 31 | static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = { | ||
| 32 | { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 33 | { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 34 | { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 35 | { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 36 | { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 37 | { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 38 | { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 39 | { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 40 | { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 41 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
| 42 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
| 43 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
| 44 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
| 45 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
| 46 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
| 47 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
| 48 | }; | ||
| 49 | |||
| 50 | asmlinkage void plat_irq_dispatch(void) | ||
| 51 | { | ||
| 52 | unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; | ||
| 53 | int irq; | ||
| 54 | |||
| 55 | irq = (fls(pending) - CAUSEB_IP - 1); | ||
| 56 | if (irq >= 0) | ||
| 57 | do_IRQ(MIPS_CPU_IRQ_BASE + irq); | ||
| 58 | else | ||
| 59 | spurious_interrupt(); | ||
| 60 | } | ||
| 61 | |||
| 62 | void __init arch_init_irq(void) | ||
| 63 | { | ||
| 64 | int i; | ||
| 65 | |||
| 66 | if (!cpu_has_veic) { | ||
| 67 | mips_cpu_irq_init(); | ||
| 68 | |||
| 69 | if (cpu_has_vint) { | ||
| 70 | /* install generic handler */ | ||
| 71 | for (i = 0; i < 8; i++) | ||
| 72 | set_vi_handler(i, plat_irq_dispatch); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | sead3_config_reg = (unsigned long)ioremap_nocache(SEAD_CONFIG_BASE, | ||
| 77 | SEAD_CONFIG_SIZE); | ||
| 78 | gic_present = (REG32(sead3_config_reg) & SEAD_CONFIG_GIC_PRESENT_MSK) >> | ||
| 79 | SEAD_CONFIG_GIC_PRESENT_SHF; | ||
| 80 | pr_info("GIC: %spresent\n", (gic_present) ? "" : "not "); | ||
| 81 | pr_info("EIC: %s\n", | ||
| 82 | (current_cpu_data.options & MIPS_CPU_VEIC) ? "on" : "off"); | ||
| 83 | |||
| 84 | if (gic_present) | ||
| 85 | gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, | ||
| 86 | ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE); | ||
| 87 | } | ||
| 88 | |||
| 89 | void gic_enable_interrupt(int irq_vec) | ||
| 90 | { | ||
| 91 | unsigned int i, irq_source; | ||
| 92 | |||
| 93 | /* enable all the interrupts associated with this vector */ | ||
| 94 | for (i = 0; i < gic_shared_intr_map[irq_vec].num_shared_intr; i++) { | ||
| 95 | irq_source = gic_shared_intr_map[irq_vec].intr_list[i]; | ||
| 96 | GIC_SET_INTR_MASK(irq_source); | ||
| 97 | } | ||
| 98 | /* enable all local interrupts associated with this vector */ | ||
| 99 | if (gic_shared_intr_map[irq_vec].local_intr_mask) { | ||
| 100 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0); | ||
| 101 | GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_SMASK), | ||
| 102 | gic_shared_intr_map[irq_vec].local_intr_mask); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | void gic_disable_interrupt(int irq_vec) | ||
| 107 | { | ||
| 108 | unsigned int i, irq_source; | ||
| 109 | |||
| 110 | /* disable all the interrupts associated with this vector */ | ||
| 111 | for (i = 0; i < gic_shared_intr_map[irq_vec].num_shared_intr; i++) { | ||
| 112 | irq_source = gic_shared_intr_map[irq_vec].intr_list[i]; | ||
| 113 | GIC_CLR_INTR_MASK(irq_source); | ||
| 114 | } | ||
| 115 | /* disable all local interrupts associated with this vector */ | ||
| 116 | if (gic_shared_intr_map[irq_vec].local_intr_mask) { | ||
| 117 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0); | ||
| 118 | GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), | ||
| 119 | gic_shared_intr_map[irq_vec].local_intr_mask); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | void gic_irq_ack(struct irq_data *d) | ||
| 124 | { | ||
| 125 | GIC_CLR_INTR_MASK(d->irq - gic_irq_base); | ||
| 126 | } | ||
| 127 | |||
| 128 | void gic_finish_irq(struct irq_data *d) | ||
| 129 | { | ||
| 130 | unsigned int irq = (d->irq - gic_irq_base); | ||
| 131 | unsigned int i, irq_source; | ||
| 132 | |||
| 133 | /* Clear edge detectors. */ | ||
| 134 | for (i = 0; i < gic_shared_intr_map[irq].num_shared_intr; i++) { | ||
| 135 | irq_source = gic_shared_intr_map[irq].intr_list[i]; | ||
| 136 | if (gic_irq_flags[irq_source] & GIC_TRIG_EDGE) | ||
| 137 | GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq_source); | ||
| 138 | } | ||
| 139 | |||
| 140 | /* Enable interrupts. */ | ||
| 141 | GIC_SET_INTR_MASK(irq); | ||
| 142 | } | ||
| 143 | |||
| 144 | void __init gic_platform_init(int irqs, struct irq_chip *irq_controller) | ||
| 145 | { | ||
| 146 | int i; | ||
| 147 | |||
| 148 | /* | ||
| 149 | * For non-EIC mode, we want to setup the GIC in pass-through | ||
| 150 | * mode, as if the GIC didn't exist. Do not map any interrupts | ||
| 151 | * for an external interrupt controller. | ||
| 152 | */ | ||
| 153 | if (!cpu_has_veic) | ||
| 154 | return; | ||
| 155 | |||
| 156 | for (i = gic_irq_base; i < (gic_irq_base + irqs); i++) | ||
| 157 | irq_set_chip_and_handler(i, irq_controller, handle_percpu_irq); | ||
| 158 | } | ||
diff --git a/arch/mips/mti-sead3/sead3-lcd.c b/arch/mips/mti-sead3/sead3-lcd.c new file mode 100644 index 000000000000..10b10ed21f77 --- /dev/null +++ b/arch/mips/mti-sead3/sead3-lcd.c | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/platform_device.h> | ||
| 10 | |||
| 11 | static struct resource __initdata sead3_lcd_resource = { | ||
| 12 | .start = 0x1f000400, | ||
| 13 | .end = 0x1f00041f, | ||
| 14 | .flags = IORESOURCE_MEM, | ||
| 15 | }; | ||
| 16 | |||
| 17 | static __init int sead3_lcd_add(void) | ||
| 18 | { | ||
| 19 | struct platform_device *pdev; | ||
| 20 | int retval; | ||
| 21 | |||
| 22 | /* SEAD-3 and Cobalt platforms use same display type. */ | ||
| 23 | pdev = platform_device_alloc("cobalt-lcd", -1); | ||
| 24 | if (!pdev) | ||
| 25 | return -ENOMEM; | ||
| 26 | |||
| 27 | retval = platform_device_add_resources(pdev, &sead3_lcd_resource, 1); | ||
| 28 | if (retval) | ||
| 29 | goto err_free_device; | ||
| 30 | |||
| 31 | retval = platform_device_add(pdev); | ||
| 32 | if (retval) | ||
| 33 | goto err_free_device; | ||
| 34 | |||
| 35 | return 0; | ||
| 36 | |||
| 37 | err_free_device: | ||
| 38 | platform_device_put(pdev); | ||
| 39 | |||
| 40 | return retval; | ||
| 41 | } | ||
| 42 | |||
| 43 | device_initcall(sead3_lcd_add); | ||
diff --git a/arch/mips/mti-sead3/sead3-leds.c b/arch/mips/mti-sead3/sead3-leds.c new file mode 100644 index 000000000000..20102a6d4141 --- /dev/null +++ b/arch/mips/mti-sead3/sead3-leds.c | |||
| @@ -0,0 +1,83 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/module.h> | ||
| 9 | #include <linux/leds.h> | ||
| 10 | #include <linux/platform_device.h> | ||
| 11 | |||
| 12 | #define LEDFLAGS(bits, shift) \ | ||
| 13 | ((bits << 8) | (shift << 8)) | ||
| 14 | |||
| 15 | #define LEDBITS(id, shift, bits) \ | ||
| 16 | .name = id #shift, \ | ||
| 17 | .flags = LEDFLAGS(bits, shift) | ||
| 18 | |||
| 19 | struct led_info led_data_info[] = { | ||
| 20 | { LEDBITS("bit", 0, 1) }, | ||
| 21 | { LEDBITS("bit", 1, 1) }, | ||
| 22 | { LEDBITS("bit", 2, 1) }, | ||
| 23 | { LEDBITS("bit", 3, 1) }, | ||
| 24 | { LEDBITS("bit", 4, 1) }, | ||
| 25 | { LEDBITS("bit", 5, 1) }, | ||
| 26 | { LEDBITS("bit", 6, 1) }, | ||
| 27 | { LEDBITS("bit", 7, 1) }, | ||
| 28 | { LEDBITS("all", 0, 8) }, | ||
| 29 | }; | ||
| 30 | |||
| 31 | static struct led_platform_data led_data = { | ||
| 32 | .num_leds = ARRAY_SIZE(led_data_info), | ||
| 33 | .leds = led_data_info | ||
| 34 | }; | ||
| 35 | |||
| 36 | static struct resource pled_resources[] = { | ||
| 37 | { | ||
| 38 | .start = 0x1f000210, | ||
| 39 | .end = 0x1f000217, | ||
| 40 | .flags = IORESOURCE_MEM | ||
| 41 | } | ||
| 42 | }; | ||
| 43 | |||
| 44 | static struct platform_device pled_device = { | ||
| 45 | .name = "sead3::pled", | ||
| 46 | .id = 0, | ||
| 47 | .dev = { | ||
| 48 | .platform_data = &led_data, | ||
| 49 | }, | ||
| 50 | .num_resources = ARRAY_SIZE(pled_resources), | ||
| 51 | .resource = pled_resources | ||
| 52 | }; | ||
| 53 | |||
| 54 | |||
| 55 | static struct resource fled_resources[] = { | ||
| 56 | { | ||
| 57 | .start = 0x1f000218, | ||
| 58 | .end = 0x1f00021f, | ||
| 59 | .flags = IORESOURCE_MEM | ||
| 60 | } | ||
| 61 | }; | ||
| 62 | |||
| 63 | static struct platform_device fled_device = { | ||
| 64 | .name = "sead3::fled", | ||
| 65 | .id = 0, | ||
| 66 | .dev = { | ||
| 67 | .platform_data = &led_data, | ||
| 68 | }, | ||
| 69 | .num_resources = ARRAY_SIZE(fled_resources), | ||
| 70 | .resource = fled_resources | ||
| 71 | }; | ||
| 72 | |||
| 73 | static int __init led_init(void) | ||
| 74 | { | ||
| 75 | platform_device_register(&pled_device); | ||
| 76 | return platform_device_register(&fled_device); | ||
| 77 | } | ||
| 78 | |||
| 79 | module_init(led_init); | ||
| 80 | |||
| 81 | MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); | ||
| 82 | MODULE_LICENSE("GPL"); | ||
| 83 | MODULE_DESCRIPTION("LED probe driver for SEAD-3"); | ||
diff --git a/arch/mips/mti-sead3/sead3-memory.c b/arch/mips/mti-sead3/sead3-memory.c new file mode 100644 index 000000000000..da9244106f86 --- /dev/null +++ b/arch/mips/mti-sead3/sead3-memory.c | |||
| @@ -0,0 +1,138 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/bootmem.h> | ||
| 9 | |||
| 10 | #include <asm/bootinfo.h> | ||
| 11 | #include <asm/sections.h> | ||
| 12 | #include <asm/mips-boards/prom.h> | ||
| 13 | |||
| 14 | enum yamon_memtypes { | ||
| 15 | yamon_dontuse, | ||
| 16 | yamon_prom, | ||
| 17 | yamon_free, | ||
| 18 | }; | ||
| 19 | |||
| 20 | static struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS]; | ||
| 21 | |||
| 22 | /* determined physical memory size, not overridden by command line args */ | ||
| 23 | unsigned long physical_memsize = 0L; | ||
| 24 | |||
| 25 | struct prom_pmemblock * __init prom_getmdesc(void) | ||
| 26 | { | ||
| 27 | char *memsize_str, *ptr; | ||
| 28 | unsigned int memsize; | ||
| 29 | static char cmdline[COMMAND_LINE_SIZE] __initdata; | ||
| 30 | long val; | ||
| 31 | int tmp; | ||
| 32 | |||
| 33 | /* otherwise look in the environment */ | ||
| 34 | memsize_str = prom_getenv("memsize"); | ||
| 35 | if (!memsize_str) { | ||
| 36 | pr_warn("memsize not set in boot prom, set to default 32Mb\n"); | ||
| 37 | physical_memsize = 0x02000000; | ||
| 38 | } else { | ||
| 39 | tmp = kstrtol(memsize_str, 0, &val); | ||
| 40 | physical_memsize = (unsigned long)val; | ||
| 41 | } | ||
| 42 | |||
| 43 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
| 44 | /* SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last | ||
| 45 | word of physical memory */ | ||
| 46 | physical_memsize -= PAGE_SIZE; | ||
| 47 | #endif | ||
| 48 | |||
| 49 | /* Check the command line for a memsize directive that overrides | ||
| 50 | the physical/default amount */ | ||
| 51 | strcpy(cmdline, arcs_cmdline); | ||
| 52 | ptr = strstr(cmdline, "memsize="); | ||
| 53 | if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' ')) | ||
| 54 | ptr = strstr(ptr, " memsize="); | ||
| 55 | |||
| 56 | if (ptr) | ||
| 57 | memsize = memparse(ptr + 8, &ptr); | ||
| 58 | else | ||
| 59 | memsize = physical_memsize; | ||
| 60 | |||
| 61 | memset(mdesc, 0, sizeof(mdesc)); | ||
| 62 | |||
| 63 | mdesc[0].type = yamon_dontuse; | ||
| 64 | mdesc[0].base = 0x00000000; | ||
| 65 | mdesc[0].size = 0x00001000; | ||
| 66 | |||
| 67 | mdesc[1].type = yamon_prom; | ||
| 68 | mdesc[1].base = 0x00001000; | ||
| 69 | mdesc[1].size = 0x000ef000; | ||
| 70 | |||
| 71 | /* | ||
| 72 | * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the | ||
| 73 | * south bridge and PCI access always forwarded to the ISA Bus and | ||
| 74 | * BIOSCS# is always generated. | ||
| 75 | * This mean that this area can't be used as DMA memory for PCI | ||
| 76 | * devices. | ||
| 77 | */ | ||
| 78 | mdesc[2].type = yamon_dontuse; | ||
| 79 | mdesc[2].base = 0x000f0000; | ||
| 80 | mdesc[2].size = 0x00010000; | ||
| 81 | |||
| 82 | mdesc[3].type = yamon_dontuse; | ||
| 83 | mdesc[3].base = 0x00100000; | ||
| 84 | mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) - | ||
| 85 | mdesc[3].base; | ||
| 86 | |||
| 87 | mdesc[4].type = yamon_free; | ||
| 88 | mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end)); | ||
| 89 | mdesc[4].size = memsize - mdesc[4].base; | ||
| 90 | |||
| 91 | return &mdesc[0]; | ||
| 92 | } | ||
| 93 | |||
| 94 | static int __init prom_memtype_classify(unsigned int type) | ||
| 95 | { | ||
| 96 | switch (type) { | ||
| 97 | case yamon_free: | ||
| 98 | return BOOT_MEM_RAM; | ||
| 99 | case yamon_prom: | ||
| 100 | return BOOT_MEM_ROM_DATA; | ||
| 101 | default: | ||
| 102 | return BOOT_MEM_RESERVED; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | void __init prom_meminit(void) | ||
| 107 | { | ||
| 108 | struct prom_pmemblock *p; | ||
| 109 | |||
| 110 | p = prom_getmdesc(); | ||
| 111 | |||
| 112 | while (p->size) { | ||
| 113 | long type; | ||
| 114 | unsigned long base, size; | ||
| 115 | |||
| 116 | type = prom_memtype_classify(p->type); | ||
| 117 | base = p->base; | ||
| 118 | size = p->size; | ||
| 119 | |||
| 120 | add_memory_region(base, size, type); | ||
| 121 | p++; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | void __init prom_free_prom_memory(void) | ||
| 126 | { | ||
| 127 | unsigned long addr; | ||
| 128 | int i; | ||
| 129 | |||
| 130 | for (i = 0; i < boot_mem_map.nr_map; i++) { | ||
| 131 | if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) | ||
| 132 | continue; | ||
| 133 | |||
| 134 | addr = boot_mem_map.map[i].addr; | ||
| 135 | free_init_pages("prom memory", | ||
| 136 | addr, addr + boot_mem_map.map[i].size); | ||
| 137 | } | ||
| 138 | } | ||
diff --git a/arch/mips/mti-sead3/sead3-mtd.c b/arch/mips/mti-sead3/sead3-mtd.c new file mode 100644 index 000000000000..ffa35f509789 --- /dev/null +++ b/arch/mips/mti-sead3/sead3-mtd.c | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/platform_device.h> | ||
| 10 | #include <linux/mtd/physmap.h> | ||
| 11 | |||
| 12 | static struct mtd_partition sead3_mtd_partitions[] = { | ||
| 13 | { | ||
| 14 | .name = "User FS", | ||
| 15 | .offset = 0x00000000, | ||
| 16 | .size = 0x01fc0000, | ||
| 17 | }, { | ||
| 18 | .name = "Board Config", | ||
| 19 | .offset = 0x01fc0000, | ||
| 20 | .size = 0x00040000, | ||
| 21 | .mask_flags = MTD_WRITEABLE | ||
| 22 | }, | ||
| 23 | }; | ||
| 24 | |||
| 25 | static struct physmap_flash_data sead3_flash_data = { | ||
| 26 | .width = 4, | ||
| 27 | .nr_parts = ARRAY_SIZE(sead3_mtd_partitions), | ||
| 28 | .parts = sead3_mtd_partitions | ||
| 29 | }; | ||
| 30 | |||
| 31 | static struct resource sead3_flash_resource = { | ||
| 32 | .start = 0x1c000000, | ||
| 33 | .end = 0x1dffffff, | ||
| 34 | .flags = IORESOURCE_MEM | ||
| 35 | }; | ||
| 36 | |||
| 37 | static struct platform_device sead3_flash = { | ||
| 38 | .name = "physmap-flash", | ||
| 39 | .id = 0, | ||
| 40 | .dev = { | ||
| 41 | .platform_data = &sead3_flash_data, | ||
| 42 | }, | ||
| 43 | .num_resources = 1, | ||
| 44 | .resource = &sead3_flash_resource, | ||
| 45 | }; | ||
| 46 | |||
| 47 | static int __init sead3_mtd_init(void) | ||
| 48 | { | ||
| 49 | platform_device_register(&sead3_flash); | ||
| 50 | |||
| 51 | return 0; | ||
| 52 | } | ||
| 53 | |||
| 54 | module_init(sead3_mtd_init) | ||
diff --git a/arch/mips/mti-sead3/sead3-net.c b/arch/mips/mti-sead3/sead3-net.c new file mode 100644 index 000000000000..04d704df6098 --- /dev/null +++ b/arch/mips/mti-sead3/sead3-net.c | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/module.h> | ||
| 9 | #include <linux/irq.h> | ||
| 10 | #include <linux/platform_device.h> | ||
| 11 | #include <linux/smsc911x.h> | ||
| 12 | |||
| 13 | static struct smsc911x_platform_config sead3_smsc911x_data = { | ||
| 14 | .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, | ||
| 15 | .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, | ||
| 16 | .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS, | ||
| 17 | .phy_interface = PHY_INTERFACE_MODE_MII, | ||
| 18 | }; | ||
| 19 | |||
| 20 | struct resource sead3_net_resourcess[] = { | ||
| 21 | { | ||
| 22 | .start = 0x1f010000, | ||
| 23 | .end = 0x1f01ffff, | ||
| 24 | .flags = IORESOURCE_MEM | ||
| 25 | }, | ||
| 26 | { | ||
| 27 | .start = MIPS_CPU_IRQ_BASE + 6, | ||
| 28 | .flags = IORESOURCE_IRQ | ||
| 29 | } | ||
| 30 | }; | ||
| 31 | |||
| 32 | static struct platform_device sead3_net_device = { | ||
| 33 | .name = "smsc911x", | ||
| 34 | .id = 0, | ||
| 35 | .dev = { | ||
| 36 | .platform_data = &sead3_smsc911x_data, | ||
| 37 | }, | ||
| 38 | .num_resources = ARRAY_SIZE(sead3_net_resourcess), | ||
| 39 | .resource = sead3_net_resourcess | ||
| 40 | }; | ||
| 41 | |||
| 42 | static int __init sead3_net_init(void) | ||
| 43 | { | ||
| 44 | return platform_device_register(&sead3_net_device); | ||
| 45 | } | ||
| 46 | |||
| 47 | module_init(sead3_net_init); | ||
| 48 | |||
| 49 | MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); | ||
| 50 | MODULE_LICENSE("GPL"); | ||
| 51 | MODULE_DESCRIPTION("Network probe driver for SEAD-3"); | ||
diff --git a/arch/mips/mti-sead3/sead3-pic32-bus.c b/arch/mips/mti-sead3/sead3-pic32-bus.c new file mode 100644 index 000000000000..9f0d89bc800e --- /dev/null +++ b/arch/mips/mti-sead3/sead3-pic32-bus.c | |||
| @@ -0,0 +1,103 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/delay.h> | ||
| 9 | #include <linux/kernel.h> | ||
| 10 | #include <linux/spinlock.h> | ||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/io.h> | ||
| 13 | #include <linux/errno.h> | ||
| 14 | |||
| 15 | #define PIC32_NULL 0x00 | ||
| 16 | #define PIC32_RD 0x01 | ||
| 17 | #define PIC32_SYSRD 0x02 | ||
| 18 | #define PIC32_WR 0x10 | ||
| 19 | #define PIC32_SYSWR 0x20 | ||
| 20 | #define PIC32_IRQ_CLR 0x40 | ||
| 21 | #define PIC32_STATUS 0x80 | ||
| 22 | |||
| 23 | #define DELAY() udelay(100) /* FIXME: needed? */ | ||
| 24 | |||
| 25 | /* spinlock to ensure atomic access to PIC32 */ | ||
| 26 | static DEFINE_SPINLOCK(pic32_bus_lock); | ||
| 27 | |||
| 28 | /* FIXME: io_remap these */ | ||
| 29 | static void __iomem *bus_xfer = (void __iomem *)0xbf000600; | ||
| 30 | static void __iomem *bus_status = (void __iomem *)0xbf000060; | ||
| 31 | |||
| 32 | static inline unsigned int ioready(void) | ||
| 33 | { | ||
| 34 | return readl(bus_status) & 1; | ||
| 35 | } | ||
| 36 | |||
| 37 | static inline void wait_ioready(void) | ||
| 38 | { | ||
| 39 | do { } while (!ioready()); | ||
| 40 | } | ||
| 41 | |||
| 42 | static inline void wait_ioclear(void) | ||
| 43 | { | ||
| 44 | do { } while (ioready()); | ||
| 45 | } | ||
| 46 | |||
| 47 | static inline void check_ioclear(void) | ||
| 48 | { | ||
| 49 | if (ioready()) { | ||
| 50 | pr_debug("ioclear: initially busy\n"); | ||
| 51 | do { | ||
| 52 | (void) readl(bus_xfer); | ||
| 53 | DELAY(); | ||
| 54 | } while (ioready()); | ||
| 55 | pr_debug("ioclear: cleared busy\n"); | ||
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | u32 pic32_bus_readl(u32 reg) | ||
| 60 | { | ||
| 61 | unsigned long flags; | ||
| 62 | u32 status, val; | ||
| 63 | |||
| 64 | spin_lock_irqsave(&pic32_bus_lock, flags); | ||
| 65 | |||
| 66 | check_ioclear(); | ||
| 67 | |||
| 68 | writel((PIC32_RD << 24) | (reg & 0x00ffffff), bus_xfer); | ||
| 69 | DELAY(); | ||
| 70 | wait_ioready(); | ||
| 71 | status = readl(bus_xfer); | ||
| 72 | DELAY(); | ||
| 73 | val = readl(bus_xfer); | ||
| 74 | wait_ioclear(); | ||
| 75 | |||
| 76 | pr_debug("pic32_bus_readl: *%x -> %x (status=%x)\n", reg, val, status); | ||
| 77 | |||
| 78 | spin_unlock_irqrestore(&pic32_bus_lock, flags); | ||
| 79 | |||
| 80 | return val; | ||
| 81 | } | ||
| 82 | |||
| 83 | void pic32_bus_writel(u32 val, u32 reg) | ||
| 84 | { | ||
| 85 | unsigned long flags; | ||
| 86 | u32 status; | ||
| 87 | |||
| 88 | spin_lock_irqsave(&pic32_bus_lock, flags); | ||
| 89 | |||
| 90 | check_ioclear(); | ||
| 91 | |||
| 92 | writel((PIC32_WR << 24) | (reg & 0x00ffffff), bus_xfer); | ||
| 93 | DELAY(); | ||
| 94 | writel(val, bus_xfer); | ||
| 95 | DELAY(); | ||
| 96 | wait_ioready(); | ||
| 97 | status = readl(bus_xfer); | ||
| 98 | wait_ioclear(); | ||
| 99 | |||
| 100 | pr_debug("pic32_bus_writel: *%x <- %x (status=%x)\n", reg, val, status); | ||
| 101 | |||
| 102 | spin_unlock_irqrestore(&pic32_bus_lock, flags); | ||
| 103 | } | ||
diff --git a/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c b/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c new file mode 100644 index 000000000000..46509b0a620d --- /dev/null +++ b/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c | |||
| @@ -0,0 +1,435 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/delay.h> | ||
| 9 | #include <linux/kernel.h> | ||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/spinlock.h> | ||
| 12 | #include <linux/platform_device.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/errno.h> | ||
| 15 | #include <linux/i2c.h> | ||
| 16 | #include <linux/slab.h> | ||
| 17 | |||
| 18 | #define PIC32_I2CxCON 0x0000 | ||
| 19 | #define PIC32_I2CxCONCLR 0x0004 | ||
| 20 | #define PIC32_I2CxCONSET 0x0008 | ||
| 21 | #define PIC32_I2CxCONINV 0x000C | ||
| 22 | #define I2CCON_ON (1<<15) | ||
| 23 | #define I2CCON_FRZ (1<<14) | ||
| 24 | #define I2CCON_SIDL (1<<13) | ||
| 25 | #define I2CCON_SCLREL (1<<12) | ||
| 26 | #define I2CCON_STRICT (1<<11) | ||
| 27 | #define I2CCON_A10M (1<<10) | ||
| 28 | #define I2CCON_DISSLW (1<<9) | ||
| 29 | #define I2CCON_SMEN (1<<8) | ||
| 30 | #define I2CCON_GCEN (1<<7) | ||
| 31 | #define I2CCON_STREN (1<<6) | ||
| 32 | #define I2CCON_ACKDT (1<<5) | ||
| 33 | #define I2CCON_ACKEN (1<<4) | ||
| 34 | #define I2CCON_RCEN (1<<3) | ||
| 35 | #define I2CCON_PEN (1<<2) | ||
| 36 | #define I2CCON_RSEN (1<<1) | ||
| 37 | #define I2CCON_SEN (1<<0) | ||
| 38 | |||
| 39 | #define PIC32_I2CxSTAT 0x0010 | ||
| 40 | #define PIC32_I2CxSTATCLR 0x0014 | ||
| 41 | #define PIC32_I2CxSTATSET 0x0018 | ||
| 42 | #define PIC32_I2CxSTATINV 0x001C | ||
| 43 | #define I2CSTAT_ACKSTAT (1<<15) | ||
| 44 | #define I2CSTAT_TRSTAT (1<<14) | ||
| 45 | #define I2CSTAT_BCL (1<<10) | ||
| 46 | #define I2CSTAT_GCSTAT (1<<9) | ||
| 47 | #define I2CSTAT_ADD10 (1<<8) | ||
| 48 | #define I2CSTAT_IWCOL (1<<7) | ||
| 49 | #define I2CSTAT_I2COV (1<<6) | ||
| 50 | #define I2CSTAT_DA (1<<5) | ||
| 51 | #define I2CSTAT_P (1<<4) | ||
| 52 | #define I2CSTAT_S (1<<3) | ||
| 53 | #define I2CSTAT_RW (1<<2) | ||
| 54 | #define I2CSTAT_RBF (1<<1) | ||
| 55 | #define I2CSTAT_TBF (1<<0) | ||
| 56 | |||
| 57 | #define PIC32_I2CxADD 0x0020 | ||
| 58 | #define PIC32_I2CxADDCLR 0x0024 | ||
| 59 | #define PIC32_I2CxADDSET 0x0028 | ||
| 60 | #define PIC32_I2CxADDINV 0x002C | ||
| 61 | #define PIC32_I2CxMSK 0x0030 | ||
| 62 | #define PIC32_I2CxMSKCLR 0x0034 | ||
| 63 | #define PIC32_I2CxMSKSET 0x0038 | ||
| 64 | #define PIC32_I2CxMSKINV 0x003C | ||
| 65 | #define PIC32_I2CxBRG 0x0040 | ||
| 66 | #define PIC32_I2CxBRGCLR 0x0044 | ||
| 67 | #define PIC32_I2CxBRGSET 0x0048 | ||
| 68 | #define PIC32_I2CxBRGINV 0x004C | ||
| 69 | #define PIC32_I2CxTRN 0x0050 | ||
| 70 | #define PIC32_I2CxTRNCLR 0x0054 | ||
| 71 | #define PIC32_I2CxTRNSET 0x0058 | ||
| 72 | #define PIC32_I2CxTRNINV 0x005C | ||
| 73 | #define PIC32_I2CxRCV 0x0060 | ||
| 74 | |||
| 75 | struct i2c_platform_data { | ||
| 76 | u32 base; | ||
| 77 | struct i2c_adapter adap; | ||
| 78 | u32 xfer_timeout; | ||
| 79 | u32 ack_timeout; | ||
| 80 | u32 ctl_timeout; | ||
| 81 | }; | ||
| 82 | |||
| 83 | extern u32 pic32_bus_readl(u32 reg); | ||
| 84 | extern void pic32_bus_writel(u32 val, u32 reg); | ||
| 85 | |||
| 86 | static inline void | ||
| 87 | StartI2C(struct i2c_platform_data *adap) | ||
| 88 | { | ||
| 89 | pr_debug("StartI2C\n"); | ||
| 90 | pic32_bus_writel(I2CCON_SEN, adap->base + PIC32_I2CxCONSET); | ||
| 91 | } | ||
| 92 | |||
| 93 | static inline void | ||
| 94 | StopI2C(struct i2c_platform_data *adap) | ||
| 95 | { | ||
| 96 | pr_debug("StopI2C\n"); | ||
| 97 | pic32_bus_writel(I2CCON_PEN, adap->base + PIC32_I2CxCONSET); | ||
| 98 | } | ||
| 99 | |||
| 100 | static inline void | ||
| 101 | AckI2C(struct i2c_platform_data *adap) | ||
| 102 | { | ||
| 103 | pr_debug("AckI2C\n"); | ||
| 104 | pic32_bus_writel(I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR); | ||
| 105 | pic32_bus_writel(I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); | ||
| 106 | } | ||
| 107 | |||
| 108 | static inline void | ||
| 109 | NotAckI2C(struct i2c_platform_data *adap) | ||
| 110 | { | ||
| 111 | pr_debug("NakI2C\n"); | ||
| 112 | pic32_bus_writel(I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET); | ||
| 113 | pic32_bus_writel(I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); | ||
| 114 | } | ||
| 115 | |||
| 116 | static inline int | ||
| 117 | IdleI2C(struct i2c_platform_data *adap) | ||
| 118 | { | ||
| 119 | int i; | ||
| 120 | |||
| 121 | pr_debug("IdleI2C\n"); | ||
| 122 | for (i = 0; i < adap->ctl_timeout; i++) { | ||
| 123 | if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) & | ||
| 124 | (I2CCON_ACKEN | I2CCON_RCEN | I2CCON_PEN | I2CCON_RSEN | | ||
| 125 | I2CCON_SEN)) == 0) && | ||
| 126 | ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & | ||
| 127 | (I2CSTAT_TRSTAT)) == 0)) | ||
| 128 | return 0; | ||
| 129 | udelay(1); | ||
| 130 | } | ||
| 131 | return -ETIMEDOUT; | ||
| 132 | } | ||
| 133 | |||
| 134 | static inline u32 | ||
| 135 | MasterWriteI2C(struct i2c_platform_data *adap, u32 byte) | ||
| 136 | { | ||
| 137 | pr_debug("MasterWriteI2C\n"); | ||
| 138 | |||
| 139 | pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN); | ||
| 140 | |||
| 141 | return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & I2CSTAT_IWCOL; | ||
| 142 | } | ||
| 143 | |||
| 144 | static inline u32 | ||
| 145 | MasterReadI2C(struct i2c_platform_data *adap) | ||
| 146 | { | ||
| 147 | pr_debug("MasterReadI2C\n"); | ||
| 148 | |||
| 149 | pic32_bus_writel(I2CCON_RCEN, adap->base + PIC32_I2CxCONSET); | ||
| 150 | |||
| 151 | while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & I2CCON_RCEN) | ||
| 152 | ; | ||
| 153 | |||
| 154 | pic32_bus_writel(I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR); | ||
| 155 | |||
| 156 | return pic32_bus_readl(adap->base + PIC32_I2CxRCV); | ||
| 157 | } | ||
| 158 | |||
| 159 | static int | ||
| 160 | do_address(struct i2c_platform_data *adap, unsigned int addr, int rd) | ||
| 161 | { | ||
| 162 | pr_debug("doaddress\n"); | ||
| 163 | |||
| 164 | IdleI2C(adap); | ||
| 165 | StartI2C(adap); | ||
| 166 | IdleI2C(adap); | ||
| 167 | |||
| 168 | addr <<= 1; | ||
| 169 | if (rd) | ||
| 170 | addr |= 1; | ||
| 171 | |||
| 172 | if (MasterWriteI2C(adap, addr)) | ||
| 173 | return -EIO; | ||
| 174 | IdleI2C(adap); | ||
| 175 | if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & I2CSTAT_ACKSTAT) | ||
| 176 | return -EIO; | ||
| 177 | return 0; | ||
| 178 | } | ||
| 179 | |||
| 180 | static int | ||
| 181 | i2c_read(struct i2c_platform_data *adap, unsigned char *buf, | ||
| 182 | unsigned int len) | ||
| 183 | { | ||
| 184 | int i; | ||
| 185 | u32 data; | ||
| 186 | |||
| 187 | pr_debug("i2c_read\n"); | ||
| 188 | |||
| 189 | i = 0; | ||
| 190 | while (i < len) { | ||
| 191 | data = MasterReadI2C(adap); | ||
| 192 | buf[i++] = data; | ||
| 193 | if (i < len) | ||
| 194 | AckI2C(adap); | ||
| 195 | else | ||
| 196 | NotAckI2C(adap); | ||
| 197 | } | ||
| 198 | |||
| 199 | StopI2C(adap); | ||
| 200 | IdleI2C(adap); | ||
| 201 | return 0; | ||
| 202 | } | ||
| 203 | |||
| 204 | static int | ||
| 205 | i2c_write(struct i2c_platform_data *adap, unsigned char *buf, | ||
| 206 | unsigned int len) | ||
| 207 | { | ||
| 208 | int i; | ||
| 209 | u32 data; | ||
| 210 | |||
| 211 | pr_debug("i2c_write\n"); | ||
| 212 | |||
| 213 | i = 0; | ||
| 214 | while (i < len) { | ||
| 215 | data = buf[i]; | ||
| 216 | if (MasterWriteI2C(adap, data)) | ||
| 217 | return -EIO; | ||
| 218 | IdleI2C(adap); | ||
| 219 | if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & | ||
| 220 | I2CSTAT_ACKSTAT) | ||
| 221 | return -EIO; | ||
| 222 | i++; | ||
| 223 | } | ||
| 224 | |||
| 225 | StopI2C(adap); | ||
| 226 | IdleI2C(adap); | ||
| 227 | return 0; | ||
| 228 | } | ||
| 229 | |||
| 230 | static int | ||
| 231 | platform_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) | ||
| 232 | { | ||
| 233 | struct i2c_platform_data *adap = i2c_adap->algo_data; | ||
| 234 | struct i2c_msg *p; | ||
| 235 | int i, err = 0; | ||
| 236 | |||
| 237 | pr_debug("platform_xfer\n"); | ||
| 238 | for (i = 0; i < num; i++) { | ||
| 239 | #define __BUFSIZE 80 | ||
| 240 | int ii; | ||
| 241 | static char buf[__BUFSIZE]; | ||
| 242 | char *b = buf; | ||
| 243 | |||
| 244 | p = &msgs[i]; | ||
| 245 | b += sprintf(buf, " [%d bytes]", p->len); | ||
| 246 | if ((p->flags & I2C_M_RD) == 0) { | ||
| 247 | for (ii = 0; ii < p->len; ii++) { | ||
| 248 | if (b < &buf[__BUFSIZE-4]) { | ||
| 249 | b += sprintf(b, " %02x", p->buf[ii]); | ||
| 250 | } else { | ||
| 251 | strcat(b, "..."); | ||
| 252 | break; | ||
| 253 | } | ||
| 254 | } | ||
| 255 | } | ||
| 256 | pr_debug("xfer%d: DevAddr: %04x Op:%s Data:%s\n", i, p->addr, | ||
| 257 | (p->flags & I2C_M_RD) ? "Rd" : "Wr", buf); | ||
| 258 | } | ||
| 259 | |||
| 260 | |||
| 261 | for (i = 0; !err && i < num; i++) { | ||
| 262 | p = &msgs[i]; | ||
| 263 | err = do_address(adap, p->addr, p->flags & I2C_M_RD); | ||
| 264 | if (err || !p->len) | ||
| 265 | continue; | ||
| 266 | if (p->flags & I2C_M_RD) | ||
| 267 | err = i2c_read(adap, p->buf, p->len); | ||
| 268 | else | ||
| 269 | err = i2c_write(adap, p->buf, p->len); | ||
| 270 | } | ||
| 271 | |||
| 272 | /* Return the number of messages processed, or the error code. */ | ||
| 273 | if (err == 0) | ||
| 274 | err = num; | ||
| 275 | |||
| 276 | return err; | ||
| 277 | } | ||
| 278 | |||
| 279 | static u32 | ||
| 280 | platform_func(struct i2c_adapter *adap) | ||
| 281 | { | ||
| 282 | pr_debug("platform_algo\n"); | ||
| 283 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
| 284 | } | ||
| 285 | |||
| 286 | static const struct i2c_algorithm platform_algo = { | ||
| 287 | .master_xfer = platform_xfer, | ||
| 288 | .functionality = platform_func, | ||
| 289 | }; | ||
| 290 | |||
| 291 | static void i2c_platform_setup(struct i2c_platform_data *priv) | ||
| 292 | { | ||
| 293 | pr_debug("i2c_platform_setup\n"); | ||
| 294 | |||
| 295 | pic32_bus_writel(500, priv->base + PIC32_I2CxBRG); | ||
| 296 | pic32_bus_writel(I2CCON_ON, priv->base + PIC32_I2CxCONCLR); | ||
| 297 | pic32_bus_writel(I2CCON_ON, priv->base + PIC32_I2CxCONSET); | ||
| 298 | pic32_bus_writel((I2CSTAT_BCL | I2CSTAT_IWCOL), | ||
| 299 | (priv->base + PIC32_I2CxSTATCLR)); | ||
| 300 | } | ||
| 301 | |||
| 302 | static void i2c_platform_disable(struct i2c_platform_data *priv) | ||
| 303 | { | ||
| 304 | pr_debug("i2c_platform_disable\n"); | ||
| 305 | } | ||
| 306 | |||
| 307 | static int __devinit | ||
| 308 | i2c_platform_probe(struct platform_device *pdev) | ||
| 309 | { | ||
| 310 | struct i2c_platform_data *priv; | ||
| 311 | struct resource *r; | ||
| 312 | int ret; | ||
| 313 | |||
| 314 | pr_debug("i2c_platform_probe\n"); | ||
| 315 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 316 | if (!r) { | ||
| 317 | ret = -ENODEV; | ||
| 318 | goto out; | ||
| 319 | } | ||
| 320 | |||
| 321 | priv = kzalloc(sizeof(struct i2c_platform_data), GFP_KERNEL); | ||
| 322 | if (!priv) { | ||
| 323 | ret = -ENOMEM; | ||
| 324 | goto out; | ||
| 325 | } | ||
| 326 | |||
| 327 | /* FIXME: need to allocate resource in PIC32 space */ | ||
| 328 | #if 0 | ||
| 329 | priv->base = bus_request_region(r->start, resource_size(r), | ||
| 330 | pdev->name); | ||
| 331 | #else | ||
| 332 | priv->base = r->start; | ||
| 333 | #endif | ||
| 334 | if (!priv->base) { | ||
| 335 | ret = -EBUSY; | ||
| 336 | goto out_mem; | ||
| 337 | } | ||
| 338 | |||
| 339 | priv->xfer_timeout = 200; | ||
| 340 | priv->ack_timeout = 200; | ||
| 341 | priv->ctl_timeout = 200; | ||
| 342 | |||
| 343 | priv->adap.nr = pdev->id; | ||
| 344 | priv->adap.algo = &platform_algo; | ||
| 345 | priv->adap.algo_data = priv; | ||
| 346 | priv->adap.dev.parent = &pdev->dev; | ||
| 347 | strlcpy(priv->adap.name, "PIC32 I2C", sizeof(priv->adap.name)); | ||
| 348 | |||
| 349 | i2c_platform_setup(priv); | ||
| 350 | |||
| 351 | ret = i2c_add_numbered_adapter(&priv->adap); | ||
| 352 | if (ret == 0) { | ||
| 353 | platform_set_drvdata(pdev, priv); | ||
| 354 | return 0; | ||
| 355 | } | ||
| 356 | |||
| 357 | i2c_platform_disable(priv); | ||
| 358 | |||
| 359 | out_mem: | ||
| 360 | kfree(priv); | ||
| 361 | out: | ||
| 362 | return ret; | ||
| 363 | } | ||
| 364 | |||
| 365 | static int __devexit | ||
| 366 | i2c_platform_remove(struct platform_device *pdev) | ||
| 367 | { | ||
| 368 | struct i2c_platform_data *priv = platform_get_drvdata(pdev); | ||
| 369 | |||
| 370 | pr_debug("i2c_platform_remove\n"); | ||
| 371 | platform_set_drvdata(pdev, NULL); | ||
| 372 | i2c_del_adapter(&priv->adap); | ||
| 373 | i2c_platform_disable(priv); | ||
| 374 | kfree(priv); | ||
| 375 | return 0; | ||
| 376 | } | ||
| 377 | |||
| 378 | #ifdef CONFIG_PM | ||
| 379 | static int | ||
| 380 | i2c_platform_suspend(struct platform_device *pdev, pm_message_t state) | ||
| 381 | { | ||
| 382 | struct i2c_platform_data *priv = platform_get_drvdata(pdev); | ||
| 383 | |||
| 384 | dev_dbg(&pdev->dev, "i2c_platform_disable\n"); | ||
| 385 | i2c_platform_disable(priv); | ||
| 386 | |||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | |||
| 390 | static int | ||
| 391 | i2c_platform_resume(struct platform_device *pdev) | ||
| 392 | { | ||
| 393 | struct i2c_platform_data *priv = platform_get_drvdata(pdev); | ||
| 394 | |||
| 395 | dev_dbg(&pdev->dev, "i2c_platform_setup\n"); | ||
| 396 | i2c_platform_setup(priv); | ||
| 397 | |||
| 398 | return 0; | ||
| 399 | } | ||
| 400 | #else | ||
| 401 | #define i2c_platform_suspend NULL | ||
| 402 | #define i2c_platform_resume NULL | ||
| 403 | #endif | ||
| 404 | |||
| 405 | static struct platform_driver i2c_platform_driver = { | ||
| 406 | .driver = { | ||
| 407 | .name = "i2c_pic32", | ||
| 408 | .owner = THIS_MODULE, | ||
| 409 | }, | ||
| 410 | .probe = i2c_platform_probe, | ||
| 411 | .remove = __devexit_p(i2c_platform_remove), | ||
| 412 | .suspend = i2c_platform_suspend, | ||
| 413 | .resume = i2c_platform_resume, | ||
| 414 | }; | ||
| 415 | |||
| 416 | static int __init | ||
| 417 | i2c_platform_init(void) | ||
| 418 | { | ||
| 419 | pr_debug("i2c_platform_init\n"); | ||
| 420 | return platform_driver_register(&i2c_platform_driver); | ||
| 421 | } | ||
| 422 | |||
| 423 | static void __exit | ||
| 424 | i2c_platform_exit(void) | ||
| 425 | { | ||
| 426 | pr_debug("i2c_platform_exit\n"); | ||
| 427 | platform_driver_unregister(&i2c_platform_driver); | ||
| 428 | } | ||
| 429 | |||
| 430 | MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC."); | ||
| 431 | MODULE_DESCRIPTION("PIC32 I2C driver"); | ||
| 432 | MODULE_LICENSE("GPL"); | ||
| 433 | |||
| 434 | module_init(i2c_platform_init); | ||
| 435 | module_exit(i2c_platform_exit); | ||
diff --git a/arch/mips/mti-sead3/sead3-platform.c b/arch/mips/mti-sead3/sead3-platform.c new file mode 100644 index 000000000000..6c3b33dbed18 --- /dev/null +++ b/arch/mips/mti-sead3/sead3-platform.c | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/module.h> | ||
| 9 | #include <linux/init.h> | ||
| 10 | #include <linux/serial_8250.h> | ||
| 11 | |||
| 12 | #define UART(base, int) \ | ||
| 13 | { \ | ||
| 14 | .mapbase = base, \ | ||
| 15 | .irq = int, \ | ||
| 16 | .uartclk = 14745600, \ | ||
| 17 | .iotype = UPIO_MEM32, \ | ||
| 18 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \ | ||
| 19 | .regshift = 2, \ | ||
| 20 | } | ||
| 21 | |||
| 22 | static struct plat_serial8250_port uart8250_data[] = { | ||
| 23 | UART(0x1f000900, MIPS_CPU_IRQ_BASE + 4), /* ttyS0 = USB */ | ||
| 24 | UART(0x1f000800, MIPS_CPU_IRQ_BASE + 4), /* ttyS1 = RS232 */ | ||
| 25 | { }, | ||
| 26 | }; | ||
| 27 | |||
| 28 | static struct platform_device uart8250_device = { | ||
| 29 | .name = "serial8250", | ||
| 30 | .id = PLAT8250_DEV_PLATFORM2, | ||
| 31 | .dev = { | ||
| 32 | .platform_data = uart8250_data, | ||
| 33 | }, | ||
| 34 | }; | ||
| 35 | |||
| 36 | static int __init uart8250_init(void) | ||
| 37 | { | ||
| 38 | return platform_device_register(&uart8250_device); | ||
| 39 | } | ||
| 40 | |||
| 41 | module_init(uart8250_init); | ||
| 42 | |||
| 43 | MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); | ||
| 44 | MODULE_LICENSE("GPL"); | ||
| 45 | MODULE_DESCRIPTION("8250 UART probe driver for SEAD3"); | ||
diff --git a/arch/mips/mti-sead3/sead3-reset.c b/arch/mips/mti-sead3/sead3-reset.c new file mode 100644 index 000000000000..20475c5e7b9c --- /dev/null +++ b/arch/mips/mti-sead3/sead3-reset.c | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/io.h> | ||
| 9 | #include <linux/pm.h> | ||
| 10 | |||
| 11 | #include <asm/reboot.h> | ||
| 12 | #include <asm/mips-boards/generic.h> | ||
| 13 | |||
| 14 | static void mips_machine_restart(char *command) | ||
| 15 | { | ||
| 16 | unsigned int __iomem *softres_reg = | ||
| 17 | ioremap(SOFTRES_REG, sizeof(unsigned int)); | ||
| 18 | |||
| 19 | __raw_writel(GORESET, softres_reg); | ||
| 20 | } | ||
| 21 | |||
| 22 | static void mips_machine_halt(void) | ||
| 23 | { | ||
| 24 | unsigned int __iomem *softres_reg = | ||
| 25 | ioremap(SOFTRES_REG, sizeof(unsigned int)); | ||
| 26 | |||
| 27 | __raw_writel(GORESET, softres_reg); | ||
| 28 | } | ||
| 29 | |||
| 30 | static int __init mips_reboot_setup(void) | ||
| 31 | { | ||
| 32 | _machine_restart = mips_machine_restart; | ||
| 33 | _machine_halt = mips_machine_halt; | ||
| 34 | pm_power_off = mips_machine_halt; | ||
| 35 | |||
| 36 | return 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | arch_initcall(mips_reboot_setup); | ||
diff --git a/arch/mips/mti-sead3/sead3-serial.c b/arch/mips/mti-sead3/sead3-serial.c new file mode 100644 index 000000000000..bc52705bbee4 --- /dev/null +++ b/arch/mips/mti-sead3/sead3-serial.c | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/module.h> | ||
| 9 | #include <linux/init.h> | ||
| 10 | #include <linux/serial_8250.h> | ||
| 11 | |||
| 12 | #define UART(base, int) \ | ||
| 13 | { \ | ||
| 14 | .mapbase = base, \ | ||
| 15 | .irq = int, \ | ||
| 16 | .uartclk = 14745600, \ | ||
| 17 | .iotype = UPIO_MEM32, \ | ||
| 18 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \ | ||
| 19 | .regshift = 2, \ | ||
| 20 | } | ||
| 21 | |||
| 22 | static struct plat_serial8250_port uart8250_data[] = { | ||
| 23 | UART(0x1f000900, MIPS_CPU_IRQ_BASE + 4), /* ttyS0 = USB */ | ||
| 24 | UART(0x1f000800, MIPS_CPU_IRQ_BASE + 4), /* ttyS1 = RS232 */ | ||
| 25 | { }, | ||
| 26 | }; | ||
| 27 | |||
| 28 | static struct platform_device uart8250_device = { | ||
| 29 | .name = "serial8250", | ||
| 30 | .id = PLAT8250_DEV_PLATFORM, | ||
| 31 | .dev = { | ||
| 32 | .platform_data = uart8250_data, | ||
| 33 | }, | ||
| 34 | }; | ||
| 35 | |||
| 36 | static int __init uart8250_init(void) | ||
| 37 | { | ||
| 38 | return platform_device_register(&uart8250_device); | ||
| 39 | } | ||
| 40 | |||
| 41 | module_init(uart8250_init); | ||
| 42 | |||
| 43 | MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); | ||
| 44 | MODULE_LICENSE("GPL"); | ||
| 45 | MODULE_DESCRIPTION("8250 UART probe driver for the SEAD-3 platform"); | ||
diff --git a/arch/mips/mti-sead3/sead3-setup.c b/arch/mips/mti-sead3/sead3-setup.c new file mode 100644 index 000000000000..8ad46ad31b49 --- /dev/null +++ b/arch/mips/mti-sead3/sead3-setup.c | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/init.h> | ||
| 9 | |||
| 10 | int coherentio; /* 0 => no DMA cache coherency (may be set by user) */ | ||
| 11 | int hw_coherentio; /* 0 => no HW DMA cache coherency (reflects real HW) */ | ||
| 12 | |||
| 13 | const char *get_system_type(void) | ||
| 14 | { | ||
| 15 | return "MIPS SEAD3"; | ||
| 16 | } | ||
| 17 | |||
| 18 | void __init plat_mem_setup(void) | ||
| 19 | { | ||
| 20 | } | ||
diff --git a/arch/mips/mti-sead3/sead3-time.c b/arch/mips/mti-sead3/sead3-time.c new file mode 100644 index 000000000000..048e781a17a0 --- /dev/null +++ b/arch/mips/mti-sead3/sead3-time.c | |||
| @@ -0,0 +1,117 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | */ | ||
| 8 | #include <linux/init.h> | ||
| 9 | |||
| 10 | #include <asm/setup.h> | ||
| 11 | #include <asm/time.h> | ||
| 12 | #include <asm/irq.h> | ||
| 13 | #include <asm/mips-boards/generic.h> | ||
| 14 | #include <asm/mips-boards/prom.h> | ||
| 15 | |||
| 16 | unsigned long cpu_khz; | ||
| 17 | |||
| 18 | static int mips_cpu_timer_irq; | ||
| 19 | static int mips_cpu_perf_irq; | ||
| 20 | |||
| 21 | static void mips_timer_dispatch(void) | ||
| 22 | { | ||
| 23 | do_IRQ(mips_cpu_timer_irq); | ||
| 24 | } | ||
| 25 | |||
| 26 | static void mips_perf_dispatch(void) | ||
| 27 | { | ||
| 28 | do_IRQ(mips_cpu_perf_irq); | ||
| 29 | } | ||
| 30 | |||
| 31 | static void __iomem *status_reg = (void __iomem *)0xbf000410; | ||
| 32 | |||
| 33 | /* | ||
| 34 | * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect. | ||
| 35 | */ | ||
| 36 | static unsigned int __init estimate_cpu_frequency(void) | ||
| 37 | { | ||
| 38 | unsigned int prid = read_c0_prid() & 0xffff00; | ||
| 39 | unsigned int tick = 0; | ||
| 40 | unsigned int freq; | ||
| 41 | unsigned int orig; | ||
| 42 | unsigned long flags; | ||
| 43 | |||
| 44 | local_irq_save(flags); | ||
| 45 | |||
| 46 | orig = readl(status_reg) & 0x2; /* get original sample */ | ||
| 47 | /* wait for transition */ | ||
| 48 | while ((readl(status_reg) & 0x2) == orig) | ||
| 49 | ; | ||
| 50 | orig = orig ^ 0x2; /* flip the bit */ | ||
| 51 | |||
| 52 | write_c0_count(0); | ||
| 53 | |||
| 54 | /* wait 1 second (the sampling clock transitions every 10ms) */ | ||
| 55 | while (tick < 100) { | ||
| 56 | /* wait for transition */ | ||
| 57 | while ((readl(status_reg) & 0x2) == orig) | ||
| 58 | ; | ||
| 59 | orig = orig ^ 0x2; /* flip the bit */ | ||
| 60 | tick++; | ||
| 61 | } | ||
| 62 | |||
| 63 | freq = read_c0_count(); | ||
| 64 | |||
| 65 | local_irq_restore(flags); | ||
| 66 | |||
| 67 | mips_hpt_frequency = freq; | ||
| 68 | |||
| 69 | /* Adjust for processor */ | ||
| 70 | if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) && | ||
| 71 | (prid != (PRID_COMP_MIPS | PRID_IMP_25KF))) | ||
| 72 | freq *= 2; | ||
| 73 | |||
| 74 | freq += 5000; /* rounding */ | ||
| 75 | freq -= freq%10000; | ||
| 76 | |||
| 77 | return freq ; | ||
| 78 | } | ||
| 79 | |||
| 80 | void read_persistent_clock(struct timespec *ts) | ||
| 81 | { | ||
| 82 | ts->tv_sec = 0; | ||
| 83 | ts->tv_nsec = 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | static void __init plat_perf_setup(void) | ||
| 87 | { | ||
| 88 | if (cp0_perfcount_irq >= 0) { | ||
| 89 | if (cpu_has_vint) | ||
| 90 | set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch); | ||
| 91 | mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | unsigned int __cpuinit get_c0_compare_int(void) | ||
| 96 | { | ||
| 97 | if (cpu_has_vint) | ||
| 98 | set_vi_handler(cp0_compare_irq, mips_timer_dispatch); | ||
| 99 | mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; | ||
| 100 | return mips_cpu_timer_irq; | ||
| 101 | } | ||
| 102 | |||
| 103 | void __init plat_time_init(void) | ||
| 104 | { | ||
| 105 | unsigned int est_freq; | ||
| 106 | |||
| 107 | est_freq = estimate_cpu_frequency(); | ||
| 108 | |||
| 109 | pr_debug("CPU frequency %d.%02d MHz\n", (est_freq / 1000000), | ||
| 110 | (est_freq % 1000000) * 100 / 1000000); | ||
| 111 | |||
| 112 | cpu_khz = est_freq / 1000; | ||
| 113 | |||
| 114 | mips_scroll_message(); | ||
| 115 | |||
| 116 | plat_perf_setup(); | ||
| 117 | } | ||
