diff options
Diffstat (limited to 'arch')
44 files changed, 2874 insertions, 116 deletions
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 0759dd2524bf..91b9d69f465c 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms | |||
| @@ -16,6 +16,7 @@ platforms += lasat | |||
| 16 | platforms += loongson | 16 | platforms += loongson |
| 17 | platforms += loongson1 | 17 | platforms += loongson1 |
| 18 | platforms += mti-malta | 18 | platforms += mti-malta |
| 19 | platforms += mti-sead3 | ||
| 19 | platforms += netlogic | 20 | platforms += netlogic |
| 20 | platforms += pmc-sierra | 21 | platforms += pmc-sierra |
| 21 | platforms += pnx833x | 22 | platforms += pnx833x |
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c0cbde6c1770..566462c358c5 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
| @@ -322,6 +322,36 @@ config MIPS_MALTA | |||
| 322 | This enables support for the MIPS Technologies Malta evaluation | 322 | This enables support for the MIPS Technologies Malta evaluation |
| 323 | board. | 323 | board. |
| 324 | 324 | ||
| 325 | config MIPS_SEAD3 | ||
| 326 | bool "MIPS SEAD3 board" | ||
| 327 | select BOOT_ELF32 | ||
| 328 | select BOOT_RAW | ||
| 329 | select CEVT_R4K | ||
| 330 | select CSRC_R4K | ||
| 331 | select CPU_MIPSR2_IRQ_VI | ||
| 332 | select CPU_MIPSR2_IRQ_EI | ||
| 333 | select DMA_NONCOHERENT | ||
| 334 | select IRQ_CPU | ||
| 335 | select IRQ_GIC | ||
| 336 | select MIPS_BOARDS_GEN | ||
| 337 | select MIPS_CPU_SCACHE | ||
| 338 | select MIPS_MSC | ||
| 339 | select SYS_HAS_CPU_MIPS32_R1 | ||
| 340 | select SYS_HAS_CPU_MIPS32_R2 | ||
| 341 | select SYS_HAS_CPU_MIPS64_R1 | ||
| 342 | select SYS_HAS_EARLY_PRINTK | ||
| 343 | select SYS_SUPPORTS_32BIT_KERNEL | ||
| 344 | select SYS_SUPPORTS_64BIT_KERNEL | ||
| 345 | select SYS_SUPPORTS_BIG_ENDIAN | ||
| 346 | select SYS_SUPPORTS_LITTLE_ENDIAN | ||
| 347 | select SYS_SUPPORTS_SMARTMIPS | ||
| 348 | select USB_ARCH_HAS_EHCI | ||
| 349 | select USB_EHCI_BIG_ENDIAN_DESC | ||
| 350 | select USB_EHCI_BIG_ENDIAN_MMIO | ||
| 351 | help | ||
| 352 | This enables support for the MIPS Technologies SEAD3 evaluation | ||
| 353 | board. | ||
| 354 | |||
| 325 | config NEC_MARKEINS | 355 | config NEC_MARKEINS |
| 326 | bool "NEC EMMA2RH Mark-eins board" | 356 | bool "NEC EMMA2RH Mark-eins board" |
| 327 | select SOC_EMMA2RH | 357 | select SOC_EMMA2RH |
| @@ -1732,7 +1762,6 @@ config HARDWARE_WATCHPOINTS | |||
| 1732 | menu "Kernel type" | 1762 | menu "Kernel type" |
| 1733 | 1763 | ||
| 1734 | choice | 1764 | choice |
| 1735 | |||
| 1736 | prompt "Kernel code model" | 1765 | prompt "Kernel code model" |
| 1737 | help | 1766 | help |
| 1738 | You should only select this option if you have a workload that | 1767 | You should only select this option if you have a workload that |
| @@ -1938,7 +1967,6 @@ config SCHED_SMT | |||
| 1938 | config SYS_SUPPORTS_SCHED_SMT | 1967 | config SYS_SUPPORTS_SCHED_SMT |
| 1939 | bool | 1968 | bool |
| 1940 | 1969 | ||
| 1941 | |||
| 1942 | config SYS_SUPPORTS_MULTITHREADING | 1970 | config SYS_SUPPORTS_MULTITHREADING |
| 1943 | bool | 1971 | bool |
| 1944 | 1972 | ||
diff --git a/arch/mips/configs/sead3_defconfig b/arch/mips/configs/sead3_defconfig new file mode 100644 index 000000000000..e3eec68d9132 --- /dev/null +++ b/arch/mips/configs/sead3_defconfig | |||
| @@ -0,0 +1,124 @@ | |||
| 1 | CONFIG_MIPS_SEAD3=y | ||
| 2 | CONFIG_CPU_LITTLE_ENDIAN=y | ||
| 3 | CONFIG_CPU_MIPS32_R2=y | ||
| 4 | CONFIG_HZ_100=y | ||
| 5 | CONFIG_EXPERIMENTAL=y | ||
| 6 | CONFIG_SYSVIPC=y | ||
| 7 | CONFIG_POSIX_MQUEUE=y | ||
| 8 | CONFIG_NO_HZ=y | ||
| 9 | CONFIG_HIGH_RES_TIMERS=y | ||
| 10 | CONFIG_IKCONFIG=y | ||
| 11 | CONFIG_IKCONFIG_PROC=y | ||
| 12 | CONFIG_LOG_BUF_SHIFT=15 | ||
| 13 | CONFIG_EMBEDDED=y | ||
| 14 | CONFIG_SLAB=y | ||
| 15 | CONFIG_PROFILING=y | ||
| 16 | CONFIG_OPROFILE=y | ||
| 17 | CONFIG_MODULES=y | ||
| 18 | # CONFIG_BLK_DEV_BSG is not set | ||
| 19 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set | ||
| 20 | CONFIG_NET=y | ||
| 21 | CONFIG_PACKET=y | ||
| 22 | CONFIG_UNIX=y | ||
| 23 | CONFIG_INET=y | ||
| 24 | CONFIG_IP_PNP=y | ||
| 25 | CONFIG_IP_PNP_DHCP=y | ||
| 26 | CONFIG_IP_PNP_BOOTP=y | ||
| 27 | # CONFIG_INET_XFRM_MODE_TRANSPORT is not set | ||
| 28 | # CONFIG_INET_XFRM_MODE_TUNNEL is not set | ||
| 29 | # CONFIG_INET_XFRM_MODE_BEET is not set | ||
| 30 | # CONFIG_INET_LRO is not set | ||
| 31 | # CONFIG_INET_DIAG is not set | ||
| 32 | # CONFIG_IPV6 is not set | ||
| 33 | # CONFIG_WIRELESS is not set | ||
| 34 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
| 35 | CONFIG_MTD=y | ||
| 36 | CONFIG_MTD_CHAR=y | ||
| 37 | CONFIG_MTD_BLOCK=y | ||
| 38 | CONFIG_MTD_CFI=y | ||
| 39 | CONFIG_MTD_CFI_INTELEXT=y | ||
| 40 | CONFIG_MTD_PHYSMAP=y | ||
| 41 | CONFIG_MTD_UBI=y | ||
| 42 | CONFIG_MTD_UBI_GLUEBI=y | ||
| 43 | CONFIG_BLK_DEV_LOOP=y | ||
| 44 | CONFIG_BLK_DEV_CRYPTOLOOP=m | ||
| 45 | CONFIG_SCSI=y | ||
| 46 | # CONFIG_SCSI_PROC_FS is not set | ||
| 47 | CONFIG_BLK_DEV_SD=y | ||
| 48 | CONFIG_CHR_DEV_SG=y | ||
| 49 | # CONFIG_SCSI_LOWLEVEL is not set | ||
| 50 | CONFIG_NETDEVICES=y | ||
| 51 | CONFIG_SMSC911X=y | ||
| 52 | # CONFIG_NET_VENDOR_WIZNET is not set | ||
| 53 | CONFIG_MARVELL_PHY=y | ||
| 54 | CONFIG_DAVICOM_PHY=y | ||
| 55 | CONFIG_QSEMI_PHY=y | ||
| 56 | CONFIG_LXT_PHY=y | ||
| 57 | CONFIG_CICADA_PHY=y | ||
| 58 | CONFIG_VITESSE_PHY=y | ||
| 59 | CONFIG_SMSC_PHY=y | ||
| 60 | CONFIG_BROADCOM_PHY=y | ||
| 61 | CONFIG_ICPLUS_PHY=y | ||
| 62 | # CONFIG_WLAN is not set | ||
| 63 | # CONFIG_INPUT_MOUSEDEV is not set | ||
| 64 | # CONFIG_INPUT_KEYBOARD is not set | ||
| 65 | # CONFIG_INPUT_MOUSE is not set | ||
| 66 | # CONFIG_SERIO is not set | ||
| 67 | # CONFIG_CONSOLE_TRANSLATIONS is not set | ||
| 68 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
| 69 | CONFIG_LEGACY_PTY_COUNT=32 | ||
| 70 | CONFIG_SERIAL_8250=y | ||
| 71 | CONFIG_SERIAL_8250_CONSOLE=y | ||
| 72 | CONFIG_SERIAL_8250_NR_UARTS=2 | ||
| 73 | CONFIG_SERIAL_8250_RUNTIME_UARTS=2 | ||
| 74 | # CONFIG_HW_RANDOM is not set | ||
| 75 | CONFIG_I2C=y | ||
| 76 | # CONFIG_I2C_COMPAT is not set | ||
| 77 | CONFIG_I2C_CHARDEV=y | ||
| 78 | # CONFIG_I2C_HELPER_AUTO is not set | ||
| 79 | CONFIG_SPI=y | ||
| 80 | CONFIG_SENSORS_ADT7475=y | ||
| 81 | CONFIG_BACKLIGHT_LCD_SUPPORT=y | ||
| 82 | CONFIG_LCD_CLASS_DEVICE=y | ||
| 83 | CONFIG_BACKLIGHT_CLASS_DEVICE=y | ||
| 84 | # CONFIG_VGA_CONSOLE is not set | ||
| 85 | CONFIG_USB=y | ||
| 86 | CONFIG_USB_ANNOUNCE_NEW_DEVICES=y | ||
| 87 | CONFIG_USB_EHCI_HCD=y | ||
| 88 | CONFIG_USB_EHCI_ROOT_HUB_TT=y | ||
| 89 | CONFIG_USB_STORAGE=y | ||
| 90 | CONFIG_MMC=y | ||
| 91 | CONFIG_MMC_DEBUG=y | ||
| 92 | CONFIG_MMC_SPI=y | ||
| 93 | CONFIG_NEW_LEDS=y | ||
| 94 | CONFIG_LEDS_CLASS=y | ||
| 95 | CONFIG_LEDS_TRIGGERS=y | ||
| 96 | CONFIG_LEDS_TRIGGER_HEARTBEAT=y | ||
| 97 | CONFIG_RTC_CLASS=y | ||
| 98 | CONFIG_RTC_DRV_M41T80=y | ||
| 99 | CONFIG_EXT3_FS=y | ||
| 100 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
| 101 | CONFIG_XFS_FS=y | ||
| 102 | CONFIG_XFS_QUOTA=y | ||
| 103 | CONFIG_XFS_POSIX_ACL=y | ||
| 104 | CONFIG_QUOTA=y | ||
| 105 | # CONFIG_PRINT_QUOTA_WARNING is not set | ||
| 106 | CONFIG_MSDOS_FS=m | ||
| 107 | CONFIG_VFAT_FS=m | ||
| 108 | CONFIG_TMPFS=y | ||
| 109 | CONFIG_JFFS2_FS=y | ||
| 110 | CONFIG_NFS_FS=y | ||
| 111 | CONFIG_ROOT_NFS=y | ||
| 112 | CONFIG_NLS_CODEPAGE_437=y | ||
| 113 | CONFIG_NLS_ASCII=y | ||
| 114 | CONFIG_NLS_ISO8859_1=y | ||
| 115 | CONFIG_NLS_ISO8859_15=y | ||
| 116 | CONFIG_NLS_UTF8=y | ||
| 117 | # CONFIG_FTRACE is not set | ||
| 118 | CONFIG_CRYPTO=y | ||
| 119 | CONFIG_CRYPTO_CBC=y | ||
| 120 | CONFIG_CRYPTO_ECB=y | ||
| 121 | CONFIG_CRYPTO_AES=y | ||
| 122 | CONFIG_CRYPTO_ARC4=y | ||
| 123 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | ||
| 124 | # CONFIG_CRYPTO_HW is not set | ||
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 1037d54f0597..554e2d29965d 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h | |||
| @@ -94,6 +94,7 @@ | |||
| 94 | #define PRID_IMP_24KE 0x9600 | 94 | #define PRID_IMP_24KE 0x9600 |
| 95 | #define PRID_IMP_74K 0x9700 | 95 | #define PRID_IMP_74K 0x9700 |
| 96 | #define PRID_IMP_1004K 0x9900 | 96 | #define PRID_IMP_1004K 0x9900 |
| 97 | #define PRID_IMP_1074K 0x9a00 | ||
| 97 | #define PRID_IMP_M14KC 0x9c00 | 98 | #define PRID_IMP_M14KC 0x9c00 |
| 98 | 99 | ||
| 99 | /* | 100 | /* |
diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h index 991b659e2548..37620db588be 100644 --- a/arch/mips/include/asm/gic.h +++ b/arch/mips/include/asm/gic.h | |||
| @@ -33,13 +33,13 @@ | |||
| 33 | REG32(_gic_base + segment##_##SECTION_OFS + offset) | 33 | REG32(_gic_base + segment##_##SECTION_OFS + offset) |
| 34 | 34 | ||
| 35 | #define GIC_ABS_REG(segment, offset) \ | 35 | #define GIC_ABS_REG(segment, offset) \ |
| 36 | (_gic_base + segment##_##SECTION_OFS + offset##_##OFS) | 36 | (_gic_base + segment##_##SECTION_OFS + offset##_##OFS) |
| 37 | #define GIC_REG_ABS_ADDR(segment, offset) \ | 37 | #define GIC_REG_ABS_ADDR(segment, offset) \ |
| 38 | (_gic_base + segment##_##SECTION_OFS + offset) | 38 | (_gic_base + segment##_##SECTION_OFS + offset) |
| 39 | 39 | ||
| 40 | #ifdef GICISBYTELITTLEENDIAN | 40 | #ifdef GICISBYTELITTLEENDIAN |
| 41 | #define GICREAD(reg, data) (data) = (reg), (data) = le32_to_cpu(data) | 41 | #define GICREAD(reg, data) ((data) = (reg), (data) = le32_to_cpu(data)) |
| 42 | #define GICWRITE(reg, data) (reg) = cpu_to_le32(data) | 42 | #define GICWRITE(reg, data) ((reg) = cpu_to_le32(data)) |
| 43 | #define GICBIS(reg, bits) \ | 43 | #define GICBIS(reg, bits) \ |
| 44 | ({unsigned int data; \ | 44 | ({unsigned int data; \ |
| 45 | GICREAD(reg, data); \ | 45 | GICREAD(reg, data); \ |
| @@ -48,9 +48,9 @@ | |||
| 48 | }) | 48 | }) |
| 49 | 49 | ||
| 50 | #else | 50 | #else |
| 51 | #define GICREAD(reg, data) (data) = (reg) | 51 | #define GICREAD(reg, data) ((data) = (reg)) |
| 52 | #define GICWRITE(reg, data) (reg) = (data) | 52 | #define GICWRITE(reg, data) ((reg) = (data)) |
| 53 | #define GICBIS(reg, bits) (reg) |= (bits) | 53 | #define GICBIS(reg, bits) ((reg) |= (bits)) |
| 54 | #endif | 54 | #endif |
| 55 | 55 | ||
| 56 | 56 | ||
| @@ -304,15 +304,15 @@ | |||
| 304 | GIC_SH_MAP_TO_VPE_REG_BIT(vpe)) | 304 | GIC_SH_MAP_TO_VPE_REG_BIT(vpe)) |
| 305 | 305 | ||
| 306 | struct gic_pcpu_mask { | 306 | struct gic_pcpu_mask { |
| 307 | DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS); | 307 | DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS); |
| 308 | }; | 308 | }; |
| 309 | 309 | ||
| 310 | struct gic_pending_regs { | 310 | struct gic_pending_regs { |
| 311 | DECLARE_BITMAP(pending, GIC_NUM_INTRS); | 311 | DECLARE_BITMAP(pending, GIC_NUM_INTRS); |
| 312 | }; | 312 | }; |
| 313 | 313 | ||
| 314 | struct gic_intrmask_regs { | 314 | struct gic_intrmask_regs { |
| 315 | DECLARE_BITMAP(intrmask, GIC_NUM_INTRS); | 315 | DECLARE_BITMAP(intrmask, GIC_NUM_INTRS); |
| 316 | }; | 316 | }; |
| 317 | 317 | ||
| 318 | /* | 318 | /* |
| @@ -341,15 +341,44 @@ struct gic_shared_intr_map { | |||
| 341 | unsigned int local_intr_mask; | 341 | unsigned int local_intr_mask; |
| 342 | }; | 342 | }; |
| 343 | 343 | ||
| 344 | /* GIC nomenclature for Core Interrupt Pins. */ | ||
| 345 | #define GIC_CPU_INT0 0 /* Core Interrupt 2 */ | ||
| 346 | #define GIC_CPU_INT1 1 /* . */ | ||
| 347 | #define GIC_CPU_INT2 2 /* . */ | ||
| 348 | #define GIC_CPU_INT3 3 /* . */ | ||
| 349 | #define GIC_CPU_INT4 4 /* . */ | ||
| 350 | #define GIC_CPU_INT5 5 /* Core Interrupt 5 */ | ||
| 351 | |||
| 352 | /* Local GIC interrupts. */ | ||
| 353 | #define GIC_INT_TMR (GIC_CPU_INT5) | ||
| 354 | #define GIC_INT_PERFCTR (GIC_CPU_INT5) | ||
| 355 | |||
| 356 | /* Add 2 to convert non-EIC hardware interrupt to EIC vector number. */ | ||
| 357 | #define GIC_CPU_TO_VEC_OFFSET (2) | ||
| 358 | |||
| 359 | /* Mapped interrupt to pin X, then GIC will generate the vector (X+1). */ | ||
| 360 | #define GIC_PIN_TO_VEC_OFFSET (1) | ||
| 361 | |||
| 362 | extern unsigned long _gic_base; | ||
| 363 | extern unsigned int gic_irq_base; | ||
| 364 | extern unsigned int gic_irq_flags[]; | ||
| 365 | extern struct gic_shared_intr_map gic_shared_intr_map[]; | ||
| 366 | |||
| 344 | extern void gic_init(unsigned long gic_base_addr, | 367 | extern void gic_init(unsigned long gic_base_addr, |
| 345 | unsigned long gic_addrspace_size, struct gic_intr_map *intrmap, | 368 | unsigned long gic_addrspace_size, struct gic_intr_map *intrmap, |
| 346 | unsigned int intrmap_size, unsigned int irqbase); | 369 | unsigned int intrmap_size, unsigned int irqbase); |
| 347 | 370 | ||
| 371 | extern void gic_clocksource_init(unsigned int); | ||
| 348 | extern unsigned int gic_get_int(void); | 372 | extern unsigned int gic_get_int(void); |
| 349 | extern void gic_send_ipi(unsigned int intr); | 373 | extern void gic_send_ipi(unsigned int intr); |
| 350 | extern unsigned int plat_ipi_call_int_xlate(unsigned int); | 374 | extern unsigned int plat_ipi_call_int_xlate(unsigned int); |
| 351 | extern unsigned int plat_ipi_resched_int_xlate(unsigned int); | 375 | extern unsigned int plat_ipi_resched_int_xlate(unsigned int); |
| 352 | extern void gic_bind_eic_interrupt(int irq, int set); | 376 | extern void gic_bind_eic_interrupt(int irq, int set); |
| 353 | extern unsigned int gic_get_timer_pending(void); | 377 | extern unsigned int gic_get_timer_pending(void); |
| 378 | extern void gic_enable_interrupt(int irq_vec); | ||
| 379 | extern void gic_disable_interrupt(int irq_vec); | ||
| 380 | extern void gic_irq_ack(struct irq_data *d); | ||
| 381 | extern void gic_finish_irq(struct irq_data *d); | ||
| 382 | extern void gic_platform_init(int irqs, struct irq_chip *irq_controller); | ||
| 354 | 383 | ||
| 355 | #endif /* _ASM_GICREGS_H */ | 384 | #endif /* _ASM_GICREGS_H */ |
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/maltaint.h b/arch/mips/include/asm/mips-boards/maltaint.h index 5447d9fc4219..669244815753 100644 --- a/arch/mips/include/asm/mips-boards/maltaint.h +++ b/arch/mips/include/asm/mips-boards/maltaint.h | |||
| @@ -1,31 +1,16 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Carsten Langgaard, carstenl@mips.com | 2 | * This file is subject to the terms and conditions of the GNU General Public |
| 3 | * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. | 3 | * License. See the file "COPYING" in the main directory of this archive |
| 4 | * | 4 | * for more details. |
| 5 | * ######################################################################## | ||
| 6 | * | ||
| 7 | * This program is free software; you can distribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License (Version 2) as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 14 | * for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
| 19 | * | ||
| 20 | * ######################################################################## | ||
| 21 | * | ||
| 22 | * Defines for the Malta interrupt controller. | ||
| 23 | * | 5 | * |
| 6 | * Copyright (C) 2000,2012 MIPS Technologies, Inc. All rights reserved. | ||
| 7 | * Carsten Langgaard <carstenl@mips.com> | ||
| 8 | * Steven J. Hill <sjhill@mips.com> | ||
| 24 | */ | 9 | */ |
| 25 | #ifndef _MIPS_MALTAINT_H | 10 | #ifndef _MIPS_MALTAINT_H |
| 26 | #define _MIPS_MALTAINT_H | 11 | #define _MIPS_MALTAINT_H |
| 27 | 12 | ||
| 28 | #include <irq.h> | 13 | #define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8) |
| 29 | 14 | ||
| 30 | /* | 15 | /* |
| 31 | * Interrupts 0..15 are used for Malta ISA compatible interrupts | 16 | * Interrupts 0..15 are used for Malta ISA compatible interrupts |
| @@ -78,26 +63,6 @@ | |||
| 78 | #define MSC01E_INT_PERFCTR 10 | 63 | #define MSC01E_INT_PERFCTR 10 |
| 79 | #define MSC01E_INT_CPUCTR 11 | 64 | #define MSC01E_INT_CPUCTR 11 |
| 80 | 65 | ||
| 81 | /* GIC's Nomenclature for Core Interrupt Pins on the Malta */ | ||
| 82 | #define GIC_CPU_INT0 0 /* Core Interrupt 2 */ | ||
| 83 | #define GIC_CPU_INT1 1 /* . */ | ||
| 84 | #define GIC_CPU_INT2 2 /* . */ | ||
| 85 | #define GIC_CPU_INT3 3 /* . */ | ||
| 86 | #define GIC_CPU_INT4 4 /* . */ | ||
| 87 | #define GIC_CPU_INT5 5 /* Core Interrupt 5 */ | ||
| 88 | |||
| 89 | /* MALTA GIC local interrupts */ | ||
| 90 | #define GIC_INT_TMR (GIC_CPU_INT5) | ||
| 91 | #define GIC_INT_PERFCTR (GIC_CPU_INT5) | ||
| 92 | |||
| 93 | /* GIC constants */ | ||
| 94 | /* Add 2 to convert non-eic hw int # to eic vector # */ | ||
| 95 | #define GIC_CPU_TO_VEC_OFFSET (2) | ||
| 96 | /* If we map an intr to pin X, GIC will actually generate vector X+1 */ | ||
| 97 | #define GIC_PIN_TO_VEC_OFFSET (1) | ||
| 98 | |||
| 99 | #define GIC_EXT_INTR(x) x | ||
| 100 | |||
| 101 | /* External Interrupts used for IPI */ | 66 | /* External Interrupts used for IPI */ |
| 102 | #define GIC_IPI_EXT_INTR_RESCHED_VPE0 16 | 67 | #define GIC_IPI_EXT_INTR_RESCHED_VPE0 16 |
| 103 | #define GIC_IPI_EXT_INTR_CALLFNC_VPE0 17 | 68 | #define GIC_IPI_EXT_INTR_CALLFNC_VPE0 17 |
| @@ -108,10 +73,4 @@ | |||
| 108 | #define GIC_IPI_EXT_INTR_RESCHED_VPE3 22 | 73 | #define GIC_IPI_EXT_INTR_RESCHED_VPE3 22 |
| 109 | #define GIC_IPI_EXT_INTR_CALLFNC_VPE3 23 | 74 | #define GIC_IPI_EXT_INTR_CALLFNC_VPE3 23 |
| 110 | 75 | ||
| 111 | #define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8) | ||
| 112 | |||
| 113 | #ifndef __ASSEMBLY__ | ||
| 114 | extern void maltaint_init(void); | ||
| 115 | #endif | ||
| 116 | |||
| 117 | #endif /* !(_MIPS_MALTAINT_H) */ | 76 | #endif /* !(_MIPS_MALTAINT_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/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 4199dd3f8d54..528fda1e957c 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h | |||
| @@ -597,6 +597,8 @@ | |||
| 597 | #define MIPS_CONF4_MMUEXTDEF (_ULCAST_(3) << 14) | 597 | #define MIPS_CONF4_MMUEXTDEF (_ULCAST_(3) << 14) |
| 598 | #define MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT (_ULCAST_(1) << 14) | 598 | #define MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT (_ULCAST_(1) << 14) |
| 599 | 599 | ||
| 600 | #define MIPS_CONF6_SYND (_ULCAST_(1) << 13) | ||
| 601 | |||
| 600 | #define MIPS_CONF7_WII (_ULCAST_(1) << 31) | 602 | #define MIPS_CONF7_WII (_ULCAST_(1) << 31) |
| 601 | 603 | ||
| 602 | #define MIPS_CONF7_RPS (_ULCAST_(1) << 2) | 604 | #define MIPS_CONF7_RPS (_ULCAST_(1) << 2) |
diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 3d9f75f7ffc9..7e0bf17c9324 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h | |||
| @@ -90,6 +90,8 @@ Ip_u2u1u3(_dsrl); | |||
| 90 | Ip_u2u1u3(_dsrl32); | 90 | Ip_u2u1u3(_dsrl32); |
| 91 | Ip_u3u1u2(_dsubu); | 91 | Ip_u3u1u2(_dsubu); |
| 92 | Ip_0(_eret); | 92 | Ip_0(_eret); |
| 93 | Ip_u2u1msbu3(_ext); | ||
| 94 | Ip_u2u1msbu3(_ins); | ||
| 93 | Ip_u1(_j); | 95 | Ip_u1(_j); |
| 94 | Ip_u1(_jal); | 96 | Ip_u1(_jal); |
| 95 | Ip_u1(_jr); | 97 | Ip_u1(_jr); |
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 51095dd9599d..75323925e537 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <asm/smtc_ipi.h> | 15 | #include <asm/smtc_ipi.h> |
| 16 | #include <asm/time.h> | 16 | #include <asm/time.h> |
| 17 | #include <asm/cevt-r4k.h> | 17 | #include <asm/cevt-r4k.h> |
| 18 | #include <asm/gic.h> | ||
| 18 | 19 | ||
| 19 | /* | 20 | /* |
| 20 | * The SMTC Kernel for the 34K, 1004K, et. al. replaces several | 21 | * The SMTC Kernel for the 34K, 1004K, et. al. replaces several |
| @@ -98,6 +99,10 @@ void mips_event_handler(struct clock_event_device *dev) | |||
| 98 | */ | 99 | */ |
| 99 | static int c0_compare_int_pending(void) | 100 | static int c0_compare_int_pending(void) |
| 100 | { | 101 | { |
| 102 | #ifdef CONFIG_IRQ_GIC | ||
| 103 | if (cpu_has_veic) | ||
| 104 | return gic_get_timer_pending(); | ||
| 105 | #endif | ||
| 101 | return (read_c0_cause() >> cp0_compare_irq_shift) & (1ul << CAUSEB_IP); | 106 | return (read_c0_cause() >> cp0_compare_irq_shift) & (1ul << CAUSEB_IP); |
| 102 | } | 107 | } |
| 103 | 108 | ||
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 0beb75fb3980..bc58bd10a607 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c | |||
| @@ -861,6 +861,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu) | |||
| 861 | c->cputype = CPU_1004K; | 861 | c->cputype = CPU_1004K; |
| 862 | __cpu_name[cpu] = "MIPS 1004Kc"; | 862 | __cpu_name[cpu] = "MIPS 1004Kc"; |
| 863 | break; | 863 | break; |
| 864 | case PRID_IMP_1074K: | ||
| 865 | c->cputype = CPU_74K; | ||
| 866 | __cpu_name[cpu] = "MIPS 1074Kc"; | ||
| 867 | break; | ||
| 864 | } | 868 | } |
| 865 | 869 | ||
| 866 | spram_config(); | 870 | spram_config(); |
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c index 0c527f652196..485e6a961b31 100644 --- a/arch/mips/kernel/irq-gic.c +++ b/arch/mips/kernel/irq-gic.c | |||
| @@ -1,5 +1,11 @@ | |||
| 1 | #undef DEBUG | 1 | /* |
| 2 | 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) 2008 Ralf Baechle (ralf@linux-mips.org) | ||
| 7 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
| 8 | */ | ||
| 3 | #include <linux/bitmap.h> | 9 | #include <linux/bitmap.h> |
| 4 | #include <linux/init.h> | 10 | #include <linux/init.h> |
| 5 | #include <linux/smp.h> | 11 | #include <linux/smp.h> |
| @@ -7,33 +13,80 @@ | |||
| 7 | 13 | ||
| 8 | #include <asm/io.h> | 14 | #include <asm/io.h> |
| 9 | #include <asm/gic.h> | 15 | #include <asm/gic.h> |
| 16 | #include <asm/setup.h> | ||
| 17 | #include <asm/traps.h> | ||
| 10 | #include <asm/gcmpregs.h> | 18 | #include <asm/gcmpregs.h> |
| 11 | #include <linux/hardirq.h> | 19 | #include <linux/hardirq.h> |
| 12 | #include <asm-generic/bitops/find.h> | 20 | #include <asm-generic/bitops/find.h> |
| 13 | 21 | ||
| 22 | unsigned long _gic_base; | ||
| 23 | unsigned int gic_irq_base; | ||
| 24 | unsigned int gic_irq_flags[GIC_NUM_INTRS]; | ||
| 14 | 25 | ||
| 15 | static unsigned long _gic_base; | 26 | /* The index into this array is the vector # of the interrupt. */ |
| 16 | static unsigned int _irqbase; | 27 | struct gic_shared_intr_map gic_shared_intr_map[GIC_NUM_INTRS]; |
| 17 | static unsigned int gic_irq_flags[GIC_NUM_INTRS]; | ||
| 18 | #define GIC_IRQ_FLAG_EDGE 0x0001 | ||
| 19 | 28 | ||
| 20 | struct gic_pcpu_mask pcpu_masks[NR_CPUS]; | 29 | static struct gic_pcpu_mask pcpu_masks[NR_CPUS]; |
| 21 | static struct gic_pending_regs pending_regs[NR_CPUS]; | 30 | static struct gic_pending_regs pending_regs[NR_CPUS]; |
| 22 | static struct gic_intrmask_regs intrmask_regs[NR_CPUS]; | 31 | static struct gic_intrmask_regs intrmask_regs[NR_CPUS]; |
| 23 | 32 | ||
| 33 | unsigned int gic_get_timer_pending(void) | ||
| 34 | { | ||
| 35 | unsigned int vpe_pending; | ||
| 36 | |||
| 37 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0); | ||
| 38 | GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_PEND), vpe_pending); | ||
| 39 | return (vpe_pending & GIC_VPE_PEND_TIMER_MSK); | ||
| 40 | } | ||
| 41 | |||
| 42 | void gic_bind_eic_interrupt(int irq, int set) | ||
| 43 | { | ||
| 44 | /* Convert irq vector # to hw int # */ | ||
| 45 | irq -= GIC_PIN_TO_VEC_OFFSET; | ||
| 46 | |||
| 47 | /* Set irq to use shadow set */ | ||
| 48 | GICWRITE(GIC_REG_ADDR(VPE_LOCAL, GIC_VPE_EIC_SS(irq)), set); | ||
| 49 | } | ||
| 50 | |||
| 24 | void gic_send_ipi(unsigned int intr) | 51 | void gic_send_ipi(unsigned int intr) |
| 25 | { | 52 | { |
| 26 | pr_debug("CPU%d: %s status %08x\n", smp_processor_id(), __func__, | ||
| 27 | read_c0_status()); | ||
| 28 | GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr); | 53 | GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr); |
| 29 | } | 54 | } |
| 30 | 55 | ||
| 31 | /* This is Malta specific and needs to be exported */ | 56 | static void gic_eic_irq_dispatch(void) |
| 57 | { | ||
| 58 | unsigned int cause = read_c0_cause(); | ||
| 59 | int irq; | ||
| 60 | |||
| 61 | irq = (cause & ST0_IM) >> STATUSB_IP2; | ||
| 62 | if (irq == 0) | ||
| 63 | irq = -1; | ||
| 64 | |||
| 65 | if (irq >= 0) | ||
| 66 | do_IRQ(gic_irq_base + irq); | ||
| 67 | else | ||
| 68 | spurious_interrupt(); | ||
| 69 | } | ||
| 70 | |||
| 32 | static void __init vpe_local_setup(unsigned int numvpes) | 71 | static void __init vpe_local_setup(unsigned int numvpes) |
| 33 | { | 72 | { |
| 34 | int i; | 73 | unsigned long timer_intr = GIC_INT_TMR; |
| 35 | unsigned long timer_interrupt = 5, perf_interrupt = 5; | 74 | unsigned long perf_intr = GIC_INT_PERFCTR; |
| 36 | unsigned int vpe_ctl; | 75 | unsigned int vpe_ctl; |
| 76 | int i; | ||
| 77 | |||
| 78 | if (cpu_has_veic) { | ||
| 79 | /* | ||
| 80 | * GIC timer interrupt -> CPU HW Int X (vector X+2) -> | ||
| 81 | * map to pin X+2-1 (since GIC adds 1) | ||
| 82 | */ | ||
| 83 | timer_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET); | ||
| 84 | /* | ||
| 85 | * GIC perfcnt interrupt -> CPU HW Int X (vector X+2) -> | ||
| 86 | * map to pin X+2-1 (since GIC adds 1) | ||
| 87 | */ | ||
| 88 | perf_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET); | ||
| 89 | } | ||
| 37 | 90 | ||
| 38 | /* | 91 | /* |
| 39 | * Setup the default performance counter timer interrupts | 92 | * Setup the default performance counter timer interrupts |
| @@ -46,11 +99,20 @@ static void __init vpe_local_setup(unsigned int numvpes) | |||
| 46 | GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl); | 99 | GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl); |
| 47 | if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK) | 100 | if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK) |
| 48 | GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), | 101 | GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), |
| 49 | GIC_MAP_TO_PIN_MSK | timer_interrupt); | 102 | GIC_MAP_TO_PIN_MSK | timer_intr); |
| 103 | if (cpu_has_veic) { | ||
| 104 | set_vi_handler(timer_intr + GIC_PIN_TO_VEC_OFFSET, | ||
| 105 | gic_eic_irq_dispatch); | ||
| 106 | gic_shared_intr_map[timer_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_TIMER_MSK; | ||
| 107 | } | ||
| 50 | 108 | ||
| 51 | if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK) | 109 | if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK) |
| 52 | GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), | 110 | GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), |
| 53 | GIC_MAP_TO_PIN_MSK | perf_interrupt); | 111 | GIC_MAP_TO_PIN_MSK | perf_intr); |
| 112 | if (cpu_has_veic) { | ||
| 113 | set_vi_handler(perf_intr + GIC_PIN_TO_VEC_OFFSET, gic_eic_irq_dispatch); | ||
| 114 | gic_shared_intr_map[perf_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_PERFCNT_MSK; | ||
| 115 | } | ||
| 54 | } | 116 | } |
| 55 | } | 117 | } |
| 56 | 118 | ||
| @@ -80,51 +142,30 @@ unsigned int gic_get_int(void) | |||
| 80 | bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS); | 142 | bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS); |
| 81 | bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS); | 143 | bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS); |
| 82 | 144 | ||
| 83 | i = find_first_bit(pending, GIC_NUM_INTRS); | 145 | return find_first_bit(pending, GIC_NUM_INTRS); |
| 84 | |||
| 85 | pr_debug("CPU%d: %s pend=%d\n", smp_processor_id(), __func__, i); | ||
| 86 | |||
| 87 | return i; | ||
| 88 | } | ||
| 89 | |||
| 90 | static void gic_irq_ack(struct irq_data *d) | ||
| 91 | { | ||
| 92 | unsigned int irq = d->irq - _irqbase; | ||
| 93 | |||
| 94 | pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); | ||
| 95 | GIC_CLR_INTR_MASK(irq); | ||
| 96 | |||
| 97 | if (gic_irq_flags[irq] & GIC_IRQ_FLAG_EDGE) | ||
| 98 | GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq); | ||
| 99 | } | 146 | } |
| 100 | 147 | ||
| 101 | static void gic_mask_irq(struct irq_data *d) | 148 | static void gic_mask_irq(struct irq_data *d) |
| 102 | { | 149 | { |
| 103 | unsigned int irq = d->irq - _irqbase; | 150 | GIC_CLR_INTR_MASK(d->irq - gic_irq_base); |
| 104 | pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); | ||
| 105 | GIC_CLR_INTR_MASK(irq); | ||
| 106 | } | 151 | } |
| 107 | 152 | ||
| 108 | static void gic_unmask_irq(struct irq_data *d) | 153 | static void gic_unmask_irq(struct irq_data *d) |
| 109 | { | 154 | { |
| 110 | unsigned int irq = d->irq - _irqbase; | 155 | GIC_SET_INTR_MASK(d->irq - gic_irq_base); |
| 111 | pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); | ||
| 112 | GIC_SET_INTR_MASK(irq); | ||
| 113 | } | 156 | } |
| 114 | 157 | ||
| 115 | #ifdef CONFIG_SMP | 158 | #ifdef CONFIG_SMP |
| 116 | |||
| 117 | static DEFINE_SPINLOCK(gic_lock); | 159 | static DEFINE_SPINLOCK(gic_lock); |
| 118 | 160 | ||
| 119 | static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, | 161 | static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, |
| 120 | bool force) | 162 | bool force) |
| 121 | { | 163 | { |
| 122 | unsigned int irq = d->irq - _irqbase; | 164 | unsigned int irq = (d->irq - gic_irq_base); |
| 123 | cpumask_t tmp = CPU_MASK_NONE; | 165 | cpumask_t tmp = CPU_MASK_NONE; |
| 124 | unsigned long flags; | 166 | unsigned long flags; |
| 125 | int i; | 167 | int i; |
| 126 | 168 | ||
| 127 | pr_debug("%s(%d) called\n", __func__, irq); | ||
| 128 | cpumask_and(&tmp, cpumask, cpu_online_mask); | 169 | cpumask_and(&tmp, cpumask, cpu_online_mask); |
| 129 | if (cpus_empty(tmp)) | 170 | if (cpus_empty(tmp)) |
| 130 | return -1; | 171 | return -1; |
| @@ -154,7 +195,7 @@ static struct irq_chip gic_irq_controller = { | |||
| 154 | .irq_mask = gic_mask_irq, | 195 | .irq_mask = gic_mask_irq, |
| 155 | .irq_mask_ack = gic_mask_irq, | 196 | .irq_mask_ack = gic_mask_irq, |
| 156 | .irq_unmask = gic_unmask_irq, | 197 | .irq_unmask = gic_unmask_irq, |
| 157 | .irq_eoi = gic_unmask_irq, | 198 | .irq_eoi = gic_finish_irq, |
| 158 | #ifdef CONFIG_SMP | 199 | #ifdef CONFIG_SMP |
| 159 | .irq_set_affinity = gic_set_affinity, | 200 | .irq_set_affinity = gic_set_affinity, |
| 160 | #endif | 201 | #endif |
| @@ -164,6 +205,8 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu, | |||
| 164 | unsigned int pin, unsigned int polarity, unsigned int trigtype, | 205 | unsigned int pin, unsigned int polarity, unsigned int trigtype, |
| 165 | unsigned int flags) | 206 | unsigned int flags) |
| 166 | { | 207 | { |
| 208 | struct gic_shared_intr_map *map_ptr; | ||
| 209 | |||
| 167 | /* Setup Intr to Pin mapping */ | 210 | /* Setup Intr to Pin mapping */ |
| 168 | if (pin & GIC_MAP_TO_NMI_MSK) { | 211 | if (pin & GIC_MAP_TO_NMI_MSK) { |
| 169 | GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin); | 212 | GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin); |
| @@ -178,6 +221,14 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu, | |||
| 178 | GIC_MAP_TO_PIN_MSK | pin); | 221 | GIC_MAP_TO_PIN_MSK | pin); |
| 179 | /* Setup Intr to CPU mapping */ | 222 | /* Setup Intr to CPU mapping */ |
| 180 | GIC_SH_MAP_TO_VPE_SMASK(intr, cpu); | 223 | GIC_SH_MAP_TO_VPE_SMASK(intr, cpu); |
| 224 | if (cpu_has_veic) { | ||
| 225 | set_vi_handler(pin + GIC_PIN_TO_VEC_OFFSET, | ||
| 226 | gic_eic_irq_dispatch); | ||
| 227 | map_ptr = &gic_shared_intr_map[pin + GIC_PIN_TO_VEC_OFFSET]; | ||
| 228 | if (map_ptr->num_shared_intr >= GIC_MAX_SHARED_INTR) | ||
| 229 | BUG(); | ||
| 230 | map_ptr->intr_list[map_ptr->num_shared_intr++] = intr; | ||
| 231 | } | ||
| 181 | } | 232 | } |
| 182 | 233 | ||
| 183 | /* Setup Intr Polarity */ | 234 | /* Setup Intr Polarity */ |
| @@ -191,26 +242,39 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu, | |||
| 191 | /* Initialise per-cpu Interrupt software masks */ | 242 | /* Initialise per-cpu Interrupt software masks */ |
| 192 | if (flags & GIC_FLAG_IPI) | 243 | if (flags & GIC_FLAG_IPI) |
| 193 | set_bit(intr, pcpu_masks[cpu].pcpu_mask); | 244 | set_bit(intr, pcpu_masks[cpu].pcpu_mask); |
| 194 | if (flags & GIC_FLAG_TRANSPARENT) | 245 | if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0)) |
| 195 | GIC_SET_INTR_MASK(intr); | 246 | GIC_SET_INTR_MASK(intr); |
| 196 | if (trigtype == GIC_TRIG_EDGE) | 247 | if (trigtype == GIC_TRIG_EDGE) |
| 197 | gic_irq_flags[intr] |= GIC_IRQ_FLAG_EDGE; | 248 | gic_irq_flags[intr] |= GIC_TRIG_EDGE; |
| 198 | } | 249 | } |
| 199 | 250 | ||
| 200 | static void __init gic_basic_init(int numintrs, int numvpes, | 251 | static void __init gic_basic_init(int numintrs, int numvpes, |
| 201 | struct gic_intr_map *intrmap, int mapsize) | 252 | struct gic_intr_map *intrmap, int mapsize) |
| 202 | { | 253 | { |
| 203 | unsigned int i, cpu; | 254 | unsigned int i, cpu; |
| 255 | unsigned int pin_offset = 0; | ||
| 256 | |||
| 257 | board_bind_eic_interrupt = &gic_bind_eic_interrupt; | ||
| 204 | 258 | ||
| 205 | /* Setup defaults */ | 259 | /* Setup defaults */ |
| 206 | for (i = 0; i < numintrs; i++) { | 260 | for (i = 0; i < numintrs; i++) { |
| 207 | GIC_SET_POLARITY(i, GIC_POL_POS); | 261 | GIC_SET_POLARITY(i, GIC_POL_POS); |
| 208 | GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL); | 262 | GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL); |
| 209 | GIC_CLR_INTR_MASK(i); | 263 | GIC_CLR_INTR_MASK(i); |
| 210 | if (i < GIC_NUM_INTRS) | 264 | if (i < GIC_NUM_INTRS) { |
| 211 | gic_irq_flags[i] = 0; | 265 | gic_irq_flags[i] = 0; |
| 266 | gic_shared_intr_map[i].num_shared_intr = 0; | ||
| 267 | gic_shared_intr_map[i].local_intr_mask = 0; | ||
| 268 | } | ||
| 212 | } | 269 | } |
| 213 | 270 | ||
| 271 | /* | ||
| 272 | * In EIC mode, the HW_INT# is offset by (2-1). Need to subtract | ||
| 273 | * one because the GIC will add one (since 0=no intr). | ||
| 274 | */ | ||
| 275 | if (cpu_has_veic) | ||
| 276 | pin_offset = (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET); | ||
| 277 | |||
| 214 | /* Setup specifics */ | 278 | /* Setup specifics */ |
| 215 | for (i = 0; i < mapsize; i++) { | 279 | for (i = 0; i < mapsize; i++) { |
| 216 | cpu = intrmap[i].cpunum; | 280 | cpu = intrmap[i].cpunum; |
| @@ -220,16 +284,13 @@ static void __init gic_basic_init(int numintrs, int numvpes, | |||
| 220 | continue; | 284 | continue; |
| 221 | gic_setup_intr(i, | 285 | gic_setup_intr(i, |
| 222 | intrmap[i].cpunum, | 286 | intrmap[i].cpunum, |
| 223 | intrmap[i].pin, | 287 | intrmap[i].pin + pin_offset, |
| 224 | intrmap[i].polarity, | 288 | intrmap[i].polarity, |
| 225 | intrmap[i].trigtype, | 289 | intrmap[i].trigtype, |
| 226 | intrmap[i].flags); | 290 | intrmap[i].flags); |
| 227 | } | 291 | } |
| 228 | 292 | ||
| 229 | vpe_local_setup(numvpes); | 293 | vpe_local_setup(numvpes); |
| 230 | |||
| 231 | for (i = _irqbase; i < (_irqbase + numintrs); i++) | ||
| 232 | irq_set_chip(i, &gic_irq_controller); | ||
| 233 | } | 294 | } |
| 234 | 295 | ||
| 235 | void __init gic_init(unsigned long gic_base_addr, | 296 | void __init gic_init(unsigned long gic_base_addr, |
| @@ -242,7 +303,7 @@ void __init gic_init(unsigned long gic_base_addr, | |||
| 242 | 303 | ||
| 243 | _gic_base = (unsigned long) ioremap_nocache(gic_base_addr, | 304 | _gic_base = (unsigned long) ioremap_nocache(gic_base_addr, |
| 244 | gic_addrspace_size); | 305 | gic_addrspace_size); |
| 245 | _irqbase = irqbase; | 306 | gic_irq_base = irqbase; |
| 246 | 307 | ||
| 247 | GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig); | 308 | GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig); |
| 248 | numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >> | 309 | numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >> |
| @@ -251,8 +312,9 @@ void __init gic_init(unsigned long gic_base_addr, | |||
| 251 | 312 | ||
| 252 | numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >> | 313 | numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >> |
| 253 | GIC_SH_CONFIG_NUMVPES_SHF; | 314 | GIC_SH_CONFIG_NUMVPES_SHF; |
| 254 | 315 | numvpes = numvpes + 1; | |
| 255 | pr_debug("%s called\n", __func__); | ||
| 256 | 316 | ||
| 257 | gic_basic_init(numintrs, numvpes, intr_map, intr_map_size); | 317 | gic_basic_init(numintrs, numvpes, intr_map, intr_map_size); |
| 318 | |||
| 319 | gic_platform_init(numintrs, &gic_irq_controller); | ||
| 258 | } | 320 | } |
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index f092c265dc63..4c32ede464b5 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c | |||
| @@ -786,6 +786,25 @@ static inline void rm7k_erratum31(void) | |||
| 786 | } | 786 | } |
| 787 | } | 787 | } |
| 788 | 788 | ||
| 789 | static inline void alias_74k_erratum(struct cpuinfo_mips *c) | ||
| 790 | { | ||
| 791 | /* | ||
| 792 | * Early versions of the 74K do not update the cache tags on a | ||
| 793 | * vtag miss/ptag hit which can occur in the case of KSEG0/KUSEG | ||
| 794 | * aliases. In this case it is better to treat the cache as always | ||
| 795 | * having aliases. | ||
| 796 | */ | ||
| 797 | if ((c->processor_id & 0xff) <= PRID_REV_ENCODE_332(2, 4, 0)) | ||
| 798 | c->dcache.flags |= MIPS_CACHE_VTAG; | ||
| 799 | if ((c->processor_id & 0xff) == PRID_REV_ENCODE_332(2, 4, 0)) | ||
| 800 | write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND); | ||
| 801 | if (((c->processor_id & 0xff00) == PRID_IMP_1074K) && | ||
| 802 | ((c->processor_id & 0xff) <= PRID_REV_ENCODE_332(1, 1, 0))) { | ||
| 803 | c->dcache.flags |= MIPS_CACHE_VTAG; | ||
| 804 | write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND); | ||
| 805 | } | ||
| 806 | } | ||
| 807 | |||
| 789 | static char *way_string[] __cpuinitdata = { NULL, "direct mapped", "2-way", | 808 | static char *way_string[] __cpuinitdata = { NULL, "direct mapped", "2-way", |
| 790 | "3-way", "4-way", "5-way", "6-way", "7-way", "8-way" | 809 | "3-way", "4-way", "5-way", "6-way", "7-way", "8-way" |
| 791 | }; | 810 | }; |
| @@ -1056,6 +1075,8 @@ static void __cpuinit probe_pcache(void) | |||
| 1056 | case CPU_34K: | 1075 | case CPU_34K: |
| 1057 | case CPU_74K: | 1076 | case CPU_74K: |
| 1058 | case CPU_1004K: | 1077 | case CPU_1004K: |
| 1078 | if (c->cputype == CPU_74K) | ||
| 1079 | alias_74k_erratum(c); | ||
| 1059 | if ((read_c0_config7() & (1 << 16))) { | 1080 | if ((read_c0_config7() & (1 << 16))) { |
| 1060 | /* effectively physically indexed dcache, | 1081 | /* effectively physically indexed dcache, |
| 1061 | thus no virtual aliases. */ | 1082 | thus no virtual aliases. */ |
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 1832f17e6be4..e09d49256908 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c | |||
| @@ -449,8 +449,20 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l, | |||
| 449 | } | 449 | } |
| 450 | 450 | ||
| 451 | if (cpu_has_mips_r2) { | 451 | if (cpu_has_mips_r2) { |
| 452 | if (cpu_has_mips_r2_exec_hazard) | 452 | /* |
| 453 | * The architecture spec says an ehb is required here, | ||
| 454 | * but a number of cores do not have the hazard and | ||
| 455 | * using an ehb causes an expensive pipeline stall. | ||
| 456 | */ | ||
| 457 | switch (current_cpu_type()) { | ||
| 458 | case CPU_M14KC: | ||
| 459 | case CPU_74K: | ||
| 460 | break; | ||
| 461 | |||
| 462 | default: | ||
| 453 | uasm_i_ehb(p); | 463 | uasm_i_ehb(p); |
| 464 | break; | ||
| 465 | } | ||
| 454 | tlbw(p); | 466 | tlbw(p); |
| 455 | return; | 467 | return; |
| 456 | } | 468 | } |
| @@ -921,6 +933,13 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) | |||
| 921 | #endif | 933 | #endif |
| 922 | uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */ | 934 | uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */ |
| 923 | uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr); | 935 | uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr); |
| 936 | |||
| 937 | if (cpu_has_mips_r2) { | ||
| 938 | uasm_i_ext(p, tmp, tmp, PGDIR_SHIFT, (32 - PGDIR_SHIFT)); | ||
| 939 | uasm_i_ins(p, ptr, tmp, PGD_T_LOG2, (32 - PGDIR_SHIFT)); | ||
| 940 | return; | ||
| 941 | } | ||
| 942 | |||
| 924 | uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */ | 943 | uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */ |
| 925 | uasm_i_sll(p, tmp, tmp, PGD_T_LOG2); | 944 | uasm_i_sll(p, tmp, tmp, PGD_T_LOG2); |
| 926 | uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */ | 945 | uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */ |
| @@ -956,6 +975,15 @@ static void __cpuinit build_adjust_context(u32 **p, unsigned int ctx) | |||
| 956 | 975 | ||
| 957 | static void __cpuinit build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) | 976 | static void __cpuinit build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) |
| 958 | { | 977 | { |
| 978 | if (cpu_has_mips_r2) { | ||
| 979 | /* PTE ptr offset is obtained from BadVAddr */ | ||
| 980 | UASM_i_MFC0(p, tmp, C0_BADVADDR); | ||
| 981 | UASM_i_LW(p, ptr, 0, ptr); | ||
| 982 | uasm_i_ext(p, tmp, tmp, PAGE_SHIFT+1, PGDIR_SHIFT-PAGE_SHIFT-1); | ||
| 983 | uasm_i_ins(p, ptr, tmp, PTE_T_LOG2+1, PGDIR_SHIFT-PAGE_SHIFT-1); | ||
| 984 | return; | ||
| 985 | } | ||
| 986 | |||
| 959 | /* | 987 | /* |
| 960 | * Bug workaround for the Nevada. It seems as if under certain | 988 | * Bug workaround for the Nevada. It seems as if under certain |
| 961 | * circumstances the move from cp0_context might produce a | 989 | * circumstances the move from cp0_context might produce a |
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 64a28e819064..39b891056227 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c | |||
| @@ -63,11 +63,12 @@ enum opcode { | |||
| 63 | insn_bne, insn_cache, insn_daddiu, insn_daddu, insn_dins, insn_dinsm, | 63 | insn_bne, insn_cache, insn_daddiu, insn_daddu, insn_dins, insn_dinsm, |
| 64 | insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll, | 64 | insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll, |
| 65 | insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, | 65 | insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, |
| 66 | insn_j, insn_jal, insn_jr, insn_ld, insn_ldx, insn_ll, insn_lld, | 66 | insn_ext, insn_ins, insn_j, insn_jal, insn_jr, insn_ld, insn_ldx, |
| 67 | insn_lui, insn_lw, insn_lwx, insn_mfc0, insn_mtc0, insn_or, insn_ori, | 67 | insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, insn_mtc0, |
| 68 | insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, | 68 | insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, |
| 69 | insn_sra, insn_srl, insn_subu, insn_sw, insn_syscall, insn_tlbp, | 69 | insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw, |
| 70 | insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, | 70 | insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, |
| 71 | insn_xori, | ||
| 71 | }; | 72 | }; |
| 72 | 73 | ||
| 73 | struct insn { | 74 | struct insn { |
| @@ -115,6 +116,9 @@ static struct insn insn_table[] __uasminitdata = { | |||
| 115 | { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE }, | 116 | { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE }, |
| 116 | { insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD }, | 117 | { insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD }, |
| 117 | { insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 }, | 118 | { insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 }, |
| 119 | { insn_ext, M(spec3_op, 0, 0, 0, 0, ext_op), RS | RT | RD | RE }, | ||
| 120 | { insn_ins, M(spec3_op, 0, 0, 0, 0, ins_op), RS | RT | RD | RE }, | ||
| 121 | { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, | ||
| 118 | { insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM }, | 122 | { insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM }, |
| 119 | { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, | 123 | { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, |
| 120 | { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS }, | 124 | { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS }, |
| @@ -341,6 +345,13 @@ Ip_u2u1msbu3(op) \ | |||
| 341 | } \ | 345 | } \ |
| 342 | UASM_EXPORT_SYMBOL(uasm_i##op); | 346 | UASM_EXPORT_SYMBOL(uasm_i##op); |
| 343 | 347 | ||
| 348 | #define I_u2u1msbdu3(op) \ | ||
| 349 | Ip_u2u1msbu3(op) \ | ||
| 350 | { \ | ||
| 351 | build_insn(buf, insn##op, b, a, d-1, c); \ | ||
| 352 | } \ | ||
| 353 | UASM_EXPORT_SYMBOL(uasm_i##op); | ||
| 354 | |||
| 344 | #define I_u1u2(op) \ | 355 | #define I_u1u2(op) \ |
| 345 | Ip_u1u2(op) \ | 356 | Ip_u1u2(op) \ |
| 346 | { \ | 357 | { \ |
| @@ -394,6 +405,8 @@ I_u2u1u3(_drotr) | |||
| 394 | I_u2u1u3(_drotr32) | 405 | I_u2u1u3(_drotr32) |
| 395 | I_u3u1u2(_dsubu) | 406 | I_u3u1u2(_dsubu) |
| 396 | I_0(_eret) | 407 | I_0(_eret) |
| 408 | I_u2u1msbdu3(_ext) | ||
| 409 | I_u2u1msbu3(_ins) | ||
| 397 | I_u1(_j) | 410 | I_u1(_j) |
| 398 | I_u1(_jal) | 411 | I_u1(_jal) |
| 399 | I_u1(_jr) | 412 | I_u1(_jr) |
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index fea823f18479..647b86383184 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c | |||
| @@ -750,3 +750,37 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup) | |||
| 750 | 750 | ||
| 751 | return retval; | 751 | return retval; |
| 752 | } | 752 | } |
| 753 | |||
| 754 | void gic_enable_interrupt(int irq_vec) | ||
| 755 | { | ||
| 756 | GIC_SET_INTR_MASK(irq_vec); | ||
| 757 | } | ||
| 758 | |||
| 759 | void gic_disable_interrupt(int irq_vec) | ||
| 760 | { | ||
| 761 | GIC_CLR_INTR_MASK(irq_vec); | ||
| 762 | } | ||
| 763 | |||
| 764 | void gic_irq_ack(struct irq_data *d) | ||
| 765 | { | ||
| 766 | int irq = (d->irq - gic_irq_base); | ||
| 767 | |||
| 768 | GIC_CLR_INTR_MASK(irq); | ||
| 769 | |||
| 770 | if (gic_irq_flags[irq] & GIC_TRIG_EDGE) | ||
| 771 | GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq); | ||
| 772 | } | ||
| 773 | |||
| 774 | void gic_finish_irq(struct irq_data *d) | ||
| 775 | { | ||
| 776 | /* Enable interrupts. */ | ||
| 777 | GIC_SET_INTR_MASK(d->irq - gic_irq_base); | ||
| 778 | } | ||
| 779 | |||
| 780 | void __init gic_platform_init(int irqs, struct irq_chip *irq_controller) | ||
| 781 | { | ||
| 782 | int i; | ||
| 783 | |||
| 784 | for (i = gic_irq_base; i < (gic_irq_base + irqs); i++) | ||
| 785 | irq_set_chip(i, irq_controller); | ||
| 786 | } | ||
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 | } | ||
