Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/upstream-linus

* 'upstream' of git://git.linux-mips.org/pub/scm/upstream-linus: (26 commits)
MIPS: Malta: enable Cirrus FB console
MIPS: add CONFIG_VIRTUALIZATION for virtio support
MIPS: Implement __read_mostly
MIPS: ath79: add common WMAC device for AR913X based boards
MIPS: ath79: Add initial support for the Atheros AP81 reference board
MIPS: ath79: add common SPI controller device
SPI: Add SPI controller driver for the Atheros AR71XX/AR724X/AR913X SoCs
MIPS: ath79: add common GPIO buttons device
MIPS: ath79: add common watchdog device
MIPS: ath79: add common GPIO LEDs device
MIPS: ath79: add initial support for the Atheros PB44 reference board
MIPS: ath79: utilize the MIPS multi-machine support
MIPS: ath79: add GPIOLIB support
MIPS: Add initial support for the Atheros AR71XX/AR724X/AR931X SoCs
MIPS: jump label: Add MIPS support.
MIPS: Use WARN() in uasm for better diagnostics.
MIPS: Optimize TLB handlers for Octeon CPUs
MIPS: Add LDX and LWX instructions to uasm.
MIPS: Use BBIT instructions in TLB handlers
MIPS: Declare uasm bbit0 and bbit1 functions.
...

+3408 -129
+1
arch/mips/Kbuild.platforms
··· 2 2 3 3 platforms += alchemy 4 4 platforms += ar7 5 + platforms += ath79 5 6 platforms += bcm47xx 6 7 platforms += bcm63xx 7 8 platforms += cavium-octeon
+37
arch/mips/Kconfig
··· 21 21 select HAVE_DMA_API_DEBUG 22 22 select HAVE_GENERIC_HARDIRQS 23 23 select GENERIC_IRQ_PROBE 24 + select HAVE_ARCH_JUMP_LABEL 24 25 25 26 menu "Machine selection" 26 27 ··· 65 64 help 66 65 Support for the Texas Instruments AR7 System-on-a-Chip 67 66 family: TNETD7100, 7200 and 7300. 67 + 68 + config ATH79 69 + bool "Atheros AR71XX/AR724X/AR913X based boards" 70 + select ARCH_REQUIRE_GPIOLIB 71 + select BOOT_RAW 72 + select CEVT_R4K 73 + select CSRC_R4K 74 + select DMA_NONCOHERENT 75 + select IRQ_CPU 76 + select MIPS_MACHINE 77 + select SYS_HAS_CPU_MIPS32_R2 78 + select SYS_HAS_EARLY_PRINTK 79 + select SYS_SUPPORTS_32BIT_KERNEL 80 + select SYS_SUPPORTS_BIG_ENDIAN 81 + help 82 + Support for the Atheros AR71XX/AR724X/AR913X SoCs. 68 83 69 84 config BCM47XX 70 85 bool "Broadcom BCM47XX based boards" ··· 734 717 endchoice 735 718 736 719 source "arch/mips/alchemy/Kconfig" 720 + source "arch/mips/ath79/Kconfig" 737 721 source "arch/mips/bcm63xx/Kconfig" 738 722 source "arch/mips/jazz/Kconfig" 739 723 source "arch/mips/jz4740/Kconfig" ··· 900 882 901 883 config SYNC_R4K 902 884 bool 885 + 886 + config MIPS_MACHINE 887 + def_bool n 903 888 904 889 config NO_IOPORT 905 890 def_bool n ··· 2420 2399 source "security/Kconfig" 2421 2400 2422 2401 source "crypto/Kconfig" 2402 + 2403 + menuconfig VIRTUALIZATION 2404 + bool "Virtualization" 2405 + default n 2406 + ---help--- 2407 + Say Y here to get to see options for using your Linux host to run other 2408 + operating systems inside virtual machines (guests). 2409 + This option alone does not add any kernel code. 2410 + 2411 + If you say N, all options in this submenu will be skipped and disabled. 2412 + 2413 + if VIRTUALIZATION 2414 + 2415 + source drivers/virtio/Kconfig 2416 + 2417 + endif # VIRTUALIZATION 2423 2418 2424 2419 source "lib/Kconfig"
+50
arch/mips/ath79/Kconfig
··· 1 + if ATH79 2 + 3 + menu "Atheros AR71XX/AR724X/AR913X machine selection" 4 + 5 + config ATH79_MACH_AP81 6 + bool "Atheros AP81 reference board" 7 + select SOC_AR913X 8 + select ATH79_DEV_AR913X_WMAC 9 + select ATH79_DEV_GPIO_BUTTONS 10 + select ATH79_DEV_LEDS_GPIO 11 + select ATH79_DEV_SPI 12 + help 13 + Say 'Y' here if you want your kernel to support the 14 + Atheros AP81 reference board. 15 + 16 + config ATH79_MACH_PB44 17 + bool "Atheros PB44 reference board" 18 + select SOC_AR71XX 19 + select ATH79_DEV_GPIO_BUTTONS 20 + select ATH79_DEV_LEDS_GPIO 21 + select ATH79_DEV_SPI 22 + help 23 + Say 'Y' here if you want your kernel to support the 24 + Atheros PB44 reference board. 25 + 26 + endmenu 27 + 28 + config SOC_AR71XX 29 + def_bool n 30 + 31 + config SOC_AR724X 32 + def_bool n 33 + 34 + config SOC_AR913X 35 + def_bool n 36 + 37 + config ATH79_DEV_AR913X_WMAC 38 + depends on SOC_AR913X 39 + def_bool n 40 + 41 + config ATH79_DEV_GPIO_BUTTONS 42 + def_bool n 43 + 44 + config ATH79_DEV_LEDS_GPIO 45 + def_bool n 46 + 47 + config ATH79_DEV_SPI 48 + def_bool n 49 + 50 + endif
+28
arch/mips/ath79/Makefile
··· 1 + # 2 + # Makefile for the Atheros AR71XX/AR724X/AR913X specific parts of the kernel 3 + # 4 + # Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 5 + # Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + # 7 + # This program is free software; you can redistribute it and/or modify it 8 + # under the terms of the GNU General Public License version 2 as published 9 + # by the Free Software Foundation. 10 + 11 + obj-y := prom.o setup.o irq.o common.o clock.o gpio.o 12 + 13 + obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 14 + 15 + # 16 + # Devices 17 + # 18 + obj-y += dev-common.o 19 + obj-$(CONFIG_ATH79_DEV_AR913X_WMAC) += dev-ar913x-wmac.o 20 + obj-$(CONFIG_ATH79_DEV_GPIO_BUTTONS) += dev-gpio-buttons.o 21 + obj-$(CONFIG_ATH79_DEV_LEDS_GPIO) += dev-leds-gpio.o 22 + obj-$(CONFIG_ATH79_DEV_SPI) += dev-spi.o 23 + 24 + # 25 + # Machines 26 + # 27 + obj-$(CONFIG_ATH79_MACH_AP81) += mach-ap81.o 28 + obj-$(CONFIG_ATH79_MACH_PB44) += mach-pb44.o
+7
arch/mips/ath79/Platform
··· 1 + # 2 + # Atheros AR71xx/AR724x/AR913x 3 + # 4 + 5 + platform-$(CONFIG_ATH79) += ath79/ 6 + cflags-$(CONFIG_ATH79) += -I$(srctree)/arch/mips/include/asm/mach-ath79 7 + load-$(CONFIG_ATH79) = 0xffffffff80060000
+183
arch/mips/ath79/clock.c
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X common routines 3 + * 4 + * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License version 2 as published 8 + * by the Free Software Foundation. 9 + */ 10 + 11 + #include <linux/kernel.h> 12 + #include <linux/module.h> 13 + #include <linux/init.h> 14 + #include <linux/err.h> 15 + #include <linux/clk.h> 16 + 17 + #include <asm/mach-ath79/ath79.h> 18 + #include <asm/mach-ath79/ar71xx_regs.h> 19 + #include "common.h" 20 + 21 + #define AR71XX_BASE_FREQ 40000000 22 + #define AR724X_BASE_FREQ 5000000 23 + #define AR913X_BASE_FREQ 5000000 24 + 25 + struct clk { 26 + unsigned long rate; 27 + }; 28 + 29 + static struct clk ath79_ref_clk; 30 + static struct clk ath79_cpu_clk; 31 + static struct clk ath79_ddr_clk; 32 + static struct clk ath79_ahb_clk; 33 + static struct clk ath79_wdt_clk; 34 + static struct clk ath79_uart_clk; 35 + 36 + static void __init ar71xx_clocks_init(void) 37 + { 38 + u32 pll; 39 + u32 freq; 40 + u32 div; 41 + 42 + ath79_ref_clk.rate = AR71XX_BASE_FREQ; 43 + 44 + pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG); 45 + 46 + div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1; 47 + freq = div * ath79_ref_clk.rate; 48 + 49 + div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1; 50 + ath79_cpu_clk.rate = freq / div; 51 + 52 + div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1; 53 + ath79_ddr_clk.rate = freq / div; 54 + 55 + div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2; 56 + ath79_ahb_clk.rate = ath79_cpu_clk.rate / div; 57 + 58 + ath79_wdt_clk.rate = ath79_ahb_clk.rate; 59 + ath79_uart_clk.rate = ath79_ahb_clk.rate; 60 + } 61 + 62 + static void __init ar724x_clocks_init(void) 63 + { 64 + u32 pll; 65 + u32 freq; 66 + u32 div; 67 + 68 + ath79_ref_clk.rate = AR724X_BASE_FREQ; 69 + pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG); 70 + 71 + div = ((pll >> AR724X_PLL_DIV_SHIFT) & AR724X_PLL_DIV_MASK); 72 + freq = div * ath79_ref_clk.rate; 73 + 74 + div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK); 75 + freq *= div; 76 + 77 + ath79_cpu_clk.rate = freq; 78 + 79 + div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1; 80 + ath79_ddr_clk.rate = freq / div; 81 + 82 + div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2; 83 + ath79_ahb_clk.rate = ath79_cpu_clk.rate / div; 84 + 85 + ath79_wdt_clk.rate = ath79_ahb_clk.rate; 86 + ath79_uart_clk.rate = ath79_ahb_clk.rate; 87 + } 88 + 89 + static void __init ar913x_clocks_init(void) 90 + { 91 + u32 pll; 92 + u32 freq; 93 + u32 div; 94 + 95 + ath79_ref_clk.rate = AR913X_BASE_FREQ; 96 + pll = ath79_pll_rr(AR913X_PLL_REG_CPU_CONFIG); 97 + 98 + div = ((pll >> AR913X_PLL_DIV_SHIFT) & AR913X_PLL_DIV_MASK); 99 + freq = div * ath79_ref_clk.rate; 100 + 101 + ath79_cpu_clk.rate = freq; 102 + 103 + div = ((pll >> AR913X_DDR_DIV_SHIFT) & AR913X_DDR_DIV_MASK) + 1; 104 + ath79_ddr_clk.rate = freq / div; 105 + 106 + div = (((pll >> AR913X_AHB_DIV_SHIFT) & AR913X_AHB_DIV_MASK) + 1) * 2; 107 + ath79_ahb_clk.rate = ath79_cpu_clk.rate / div; 108 + 109 + ath79_wdt_clk.rate = ath79_ahb_clk.rate; 110 + ath79_uart_clk.rate = ath79_ahb_clk.rate; 111 + } 112 + 113 + void __init ath79_clocks_init(void) 114 + { 115 + if (soc_is_ar71xx()) 116 + ar71xx_clocks_init(); 117 + else if (soc_is_ar724x()) 118 + ar724x_clocks_init(); 119 + else if (soc_is_ar913x()) 120 + ar913x_clocks_init(); 121 + else 122 + BUG(); 123 + 124 + pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, " 125 + "Ref:%lu.%03luMHz", 126 + ath79_cpu_clk.rate / 1000000, 127 + (ath79_cpu_clk.rate / 1000) % 1000, 128 + ath79_ddr_clk.rate / 1000000, 129 + (ath79_ddr_clk.rate / 1000) % 1000, 130 + ath79_ahb_clk.rate / 1000000, 131 + (ath79_ahb_clk.rate / 1000) % 1000, 132 + ath79_ref_clk.rate / 1000000, 133 + (ath79_ref_clk.rate / 1000) % 1000); 134 + } 135 + 136 + /* 137 + * Linux clock API 138 + */ 139 + struct clk *clk_get(struct device *dev, const char *id) 140 + { 141 + if (!strcmp(id, "ref")) 142 + return &ath79_ref_clk; 143 + 144 + if (!strcmp(id, "cpu")) 145 + return &ath79_cpu_clk; 146 + 147 + if (!strcmp(id, "ddr")) 148 + return &ath79_ddr_clk; 149 + 150 + if (!strcmp(id, "ahb")) 151 + return &ath79_ahb_clk; 152 + 153 + if (!strcmp(id, "wdt")) 154 + return &ath79_wdt_clk; 155 + 156 + if (!strcmp(id, "uart")) 157 + return &ath79_uart_clk; 158 + 159 + return ERR_PTR(-ENOENT); 160 + } 161 + EXPORT_SYMBOL(clk_get); 162 + 163 + int clk_enable(struct clk *clk) 164 + { 165 + return 0; 166 + } 167 + EXPORT_SYMBOL(clk_enable); 168 + 169 + void clk_disable(struct clk *clk) 170 + { 171 + } 172 + EXPORT_SYMBOL(clk_disable); 173 + 174 + unsigned long clk_get_rate(struct clk *clk) 175 + { 176 + return clk->rate; 177 + } 178 + EXPORT_SYMBOL(clk_get_rate); 179 + 180 + void clk_put(struct clk *clk) 181 + { 182 + } 183 + EXPORT_SYMBOL(clk_put);
+97
arch/mips/ath79/common.c
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X common routines 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/kernel.h> 13 + #include <linux/module.h> 14 + #include <linux/types.h> 15 + #include <linux/spinlock.h> 16 + 17 + #include <asm/mach-ath79/ath79.h> 18 + #include <asm/mach-ath79/ar71xx_regs.h> 19 + #include "common.h" 20 + 21 + static DEFINE_SPINLOCK(ath79_device_reset_lock); 22 + 23 + u32 ath79_cpu_freq; 24 + EXPORT_SYMBOL_GPL(ath79_cpu_freq); 25 + 26 + u32 ath79_ahb_freq; 27 + EXPORT_SYMBOL_GPL(ath79_ahb_freq); 28 + 29 + u32 ath79_ddr_freq; 30 + EXPORT_SYMBOL_GPL(ath79_ddr_freq); 31 + 32 + enum ath79_soc_type ath79_soc; 33 + 34 + void __iomem *ath79_pll_base; 35 + void __iomem *ath79_reset_base; 36 + EXPORT_SYMBOL_GPL(ath79_reset_base); 37 + void __iomem *ath79_ddr_base; 38 + 39 + void ath79_ddr_wb_flush(u32 reg) 40 + { 41 + void __iomem *flush_reg = ath79_ddr_base + reg; 42 + 43 + /* Flush the DDR write buffer. */ 44 + __raw_writel(0x1, flush_reg); 45 + while (__raw_readl(flush_reg) & 0x1) 46 + ; 47 + 48 + /* It must be run twice. */ 49 + __raw_writel(0x1, flush_reg); 50 + while (__raw_readl(flush_reg) & 0x1) 51 + ; 52 + } 53 + EXPORT_SYMBOL_GPL(ath79_ddr_wb_flush); 54 + 55 + void ath79_device_reset_set(u32 mask) 56 + { 57 + unsigned long flags; 58 + u32 reg; 59 + u32 t; 60 + 61 + if (soc_is_ar71xx()) 62 + reg = AR71XX_RESET_REG_RESET_MODULE; 63 + else if (soc_is_ar724x()) 64 + reg = AR724X_RESET_REG_RESET_MODULE; 65 + else if (soc_is_ar913x()) 66 + reg = AR913X_RESET_REG_RESET_MODULE; 67 + else 68 + BUG(); 69 + 70 + spin_lock_irqsave(&ath79_device_reset_lock, flags); 71 + t = ath79_reset_rr(reg); 72 + ath79_reset_wr(reg, t | mask); 73 + spin_unlock_irqrestore(&ath79_device_reset_lock, flags); 74 + } 75 + EXPORT_SYMBOL_GPL(ath79_device_reset_set); 76 + 77 + void ath79_device_reset_clear(u32 mask) 78 + { 79 + unsigned long flags; 80 + u32 reg; 81 + u32 t; 82 + 83 + if (soc_is_ar71xx()) 84 + reg = AR71XX_RESET_REG_RESET_MODULE; 85 + else if (soc_is_ar724x()) 86 + reg = AR724X_RESET_REG_RESET_MODULE; 87 + else if (soc_is_ar913x()) 88 + reg = AR913X_RESET_REG_RESET_MODULE; 89 + else 90 + BUG(); 91 + 92 + spin_lock_irqsave(&ath79_device_reset_lock, flags); 93 + t = ath79_reset_rr(reg); 94 + ath79_reset_wr(reg, t & ~mask); 95 + spin_unlock_irqrestore(&ath79_device_reset_lock, flags); 96 + } 97 + EXPORT_SYMBOL_GPL(ath79_device_reset_clear);
+31
arch/mips/ath79/common.h
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X common definitions 3 + * 4 + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * Parts of this file are based on Atheros' 2.6.15 BSP 8 + * 9 + * This program is free software; you can redistribute it and/or modify it 10 + * under the terms of the GNU General Public License version 2 as published 11 + * by the Free Software Foundation. 12 + */ 13 + 14 + #ifndef __ATH79_COMMON_H 15 + #define __ATH79_COMMON_H 16 + 17 + #include <linux/types.h> 18 + #include <linux/init.h> 19 + 20 + #define ATH79_MEM_SIZE_MIN (2 * 1024 * 1024) 21 + #define ATH79_MEM_SIZE_MAX (128 * 1024 * 1024) 22 + 23 + void ath79_clocks_init(void); 24 + void ath79_ddr_wb_flush(unsigned int reg); 25 + 26 + void ath79_gpio_function_enable(u32 mask); 27 + void ath79_gpio_function_disable(u32 mask); 28 + void ath79_gpio_function_setup(u32 set, u32 clear); 29 + void ath79_gpio_init(void); 30 + 31 + #endif /* __ATH79_COMMON_H */
+60
arch/mips/ath79/dev-ar913x-wmac.c
··· 1 + /* 2 + * Atheros AR913X SoC built-in WMAC device support 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/init.h> 13 + #include <linux/delay.h> 14 + #include <linux/irq.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/ath9k_platform.h> 17 + 18 + #include <asm/mach-ath79/ath79.h> 19 + #include <asm/mach-ath79/ar71xx_regs.h> 20 + #include "dev-ar913x-wmac.h" 21 + 22 + static struct ath9k_platform_data ar913x_wmac_data; 23 + 24 + static struct resource ar913x_wmac_resources[] = { 25 + { 26 + .start = AR913X_WMAC_BASE, 27 + .end = AR913X_WMAC_BASE + AR913X_WMAC_SIZE - 1, 28 + .flags = IORESOURCE_MEM, 29 + }, { 30 + .start = ATH79_CPU_IRQ_IP2, 31 + .end = ATH79_CPU_IRQ_IP2, 32 + .flags = IORESOURCE_IRQ, 33 + }, 34 + }; 35 + 36 + static struct platform_device ar913x_wmac_device = { 37 + .name = "ath9k", 38 + .id = -1, 39 + .resource = ar913x_wmac_resources, 40 + .num_resources = ARRAY_SIZE(ar913x_wmac_resources), 41 + .dev = { 42 + .platform_data = &ar913x_wmac_data, 43 + }, 44 + }; 45 + 46 + void __init ath79_register_ar913x_wmac(u8 *cal_data) 47 + { 48 + if (cal_data) 49 + memcpy(ar913x_wmac_data.eeprom_data, cal_data, 50 + sizeof(ar913x_wmac_data.eeprom_data)); 51 + 52 + /* reset the WMAC */ 53 + ath79_device_reset_set(AR913X_RESET_AMBA2WMAC); 54 + mdelay(10); 55 + 56 + ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC); 57 + mdelay(10); 58 + 59 + platform_device_register(&ar913x_wmac_device); 60 + }
+17
arch/mips/ath79/dev-ar913x-wmac.h
··· 1 + /* 2 + * Atheros AR913X SoC built-in WMAC device support 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #ifndef _ATH79_DEV_AR913X_WMAC_H 13 + #define _ATH79_DEV_AR913X_WMAC_H 14 + 15 + void ath79_register_ar913x_wmac(u8 *cal_data); 16 + 17 + #endif /* _ATH79_DEV_AR913X_WMAC_H */
+77
arch/mips/ath79/dev-common.c
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X common devices 3 + * 4 + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * Parts of this file are based on Atheros' 2.6.15 BSP 8 + * 9 + * This program is free software; you can redistribute it and/or modify it 10 + * under the terms of the GNU General Public License version 2 as published 11 + * by the Free Software Foundation. 12 + */ 13 + 14 + #include <linux/kernel.h> 15 + #include <linux/init.h> 16 + #include <linux/platform_device.h> 17 + #include <linux/serial_8250.h> 18 + #include <linux/clk.h> 19 + #include <linux/err.h> 20 + 21 + #include <asm/mach-ath79/ath79.h> 22 + #include <asm/mach-ath79/ar71xx_regs.h> 23 + #include "common.h" 24 + #include "dev-common.h" 25 + 26 + static struct resource ath79_uart_resources[] = { 27 + { 28 + .start = AR71XX_UART_BASE, 29 + .end = AR71XX_UART_BASE + AR71XX_UART_SIZE - 1, 30 + .flags = IORESOURCE_MEM, 31 + }, 32 + }; 33 + 34 + #define AR71XX_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP) 35 + static struct plat_serial8250_port ath79_uart_data[] = { 36 + { 37 + .mapbase = AR71XX_UART_BASE, 38 + .irq = ATH79_MISC_IRQ_UART, 39 + .flags = AR71XX_UART_FLAGS, 40 + .iotype = UPIO_MEM32, 41 + .regshift = 2, 42 + }, { 43 + /* terminating entry */ 44 + } 45 + }; 46 + 47 + static struct platform_device ath79_uart_device = { 48 + .name = "serial8250", 49 + .id = PLAT8250_DEV_PLATFORM, 50 + .resource = ath79_uart_resources, 51 + .num_resources = ARRAY_SIZE(ath79_uart_resources), 52 + .dev = { 53 + .platform_data = ath79_uart_data 54 + }, 55 + }; 56 + 57 + void __init ath79_register_uart(void) 58 + { 59 + struct clk *clk; 60 + 61 + clk = clk_get(NULL, "uart"); 62 + if (IS_ERR(clk)) 63 + panic("unable to get UART clock, err=%ld", PTR_ERR(clk)); 64 + 65 + ath79_uart_data[0].uartclk = clk_get_rate(clk); 66 + platform_device_register(&ath79_uart_device); 67 + } 68 + 69 + static struct platform_device ath79_wdt_device = { 70 + .name = "ath79-wdt", 71 + .id = -1, 72 + }; 73 + 74 + void __init ath79_register_wdt(void) 75 + { 76 + platform_device_register(&ath79_wdt_device); 77 + }
+18
arch/mips/ath79/dev-common.h
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X common devices 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #ifndef _ATH79_DEV_COMMON_H 13 + #define _ATH79_DEV_COMMON_H 14 + 15 + void ath79_register_uart(void); 16 + void ath79_register_wdt(void); 17 + 18 + #endif /* _ATH79_DEV_COMMON_H */
+58
arch/mips/ath79/dev-gpio-buttons.c
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X GPIO button support 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #include "linux/init.h" 13 + #include "linux/slab.h" 14 + #include <linux/platform_device.h> 15 + 16 + #include "dev-gpio-buttons.h" 17 + 18 + void __init ath79_register_gpio_keys_polled(int id, 19 + unsigned poll_interval, 20 + unsigned nbuttons, 21 + struct gpio_keys_button *buttons) 22 + { 23 + struct platform_device *pdev; 24 + struct gpio_keys_platform_data pdata; 25 + struct gpio_keys_button *p; 26 + int err; 27 + 28 + p = kmalloc(nbuttons * sizeof(*p), GFP_KERNEL); 29 + if (!p) 30 + return; 31 + 32 + memcpy(p, buttons, nbuttons * sizeof(*p)); 33 + 34 + pdev = platform_device_alloc("gpio-keys-polled", id); 35 + if (!pdev) 36 + goto err_free_buttons; 37 + 38 + memset(&pdata, 0, sizeof(pdata)); 39 + pdata.poll_interval = poll_interval; 40 + pdata.nbuttons = nbuttons; 41 + pdata.buttons = p; 42 + 43 + err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); 44 + if (err) 45 + goto err_put_pdev; 46 + 47 + err = platform_device_add(pdev); 48 + if (err) 49 + goto err_put_pdev; 50 + 51 + return; 52 + 53 + err_put_pdev: 54 + platform_device_put(pdev); 55 + 56 + err_free_buttons: 57 + kfree(p); 58 + }
+23
arch/mips/ath79/dev-gpio-buttons.h
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X GPIO button support 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #ifndef _ATH79_DEV_GPIO_BUTTONS_H 13 + #define _ATH79_DEV_GPIO_BUTTONS_H 14 + 15 + #include <linux/input.h> 16 + #include <linux/gpio_keys.h> 17 + 18 + void ath79_register_gpio_keys_polled(int id, 19 + unsigned poll_interval, 20 + unsigned nbuttons, 21 + struct gpio_keys_button *buttons); 22 + 23 + #endif /* _ATH79_DEV_GPIO_BUTTONS_H */
+56
arch/mips/ath79/dev-leds-gpio.c
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X common GPIO LEDs support 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/init.h> 13 + #include <linux/slab.h> 14 + #include <linux/platform_device.h> 15 + 16 + #include "dev-leds-gpio.h" 17 + 18 + void __init ath79_register_leds_gpio(int id, 19 + unsigned num_leds, 20 + struct gpio_led *leds) 21 + { 22 + struct platform_device *pdev; 23 + struct gpio_led_platform_data pdata; 24 + struct gpio_led *p; 25 + int err; 26 + 27 + p = kmalloc(num_leds * sizeof(*p), GFP_KERNEL); 28 + if (!p) 29 + return; 30 + 31 + memcpy(p, leds, num_leds * sizeof(*p)); 32 + 33 + pdev = platform_device_alloc("leds-gpio", id); 34 + if (!pdev) 35 + goto err_free_leds; 36 + 37 + memset(&pdata, 0, sizeof(pdata)); 38 + pdata.num_leds = num_leds; 39 + pdata.leds = p; 40 + 41 + err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); 42 + if (err) 43 + goto err_put_pdev; 44 + 45 + err = platform_device_add(pdev); 46 + if (err) 47 + goto err_put_pdev; 48 + 49 + return; 50 + 51 + err_put_pdev: 52 + platform_device_put(pdev); 53 + 54 + err_free_leds: 55 + kfree(p); 56 + }
+21
arch/mips/ath79/dev-leds-gpio.h
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X common GPIO LEDs support 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #ifndef _ATH79_DEV_LEDS_GPIO_H 13 + #define _ATH79_DEV_LEDS_GPIO_H 14 + 15 + #include <linux/leds.h> 16 + 17 + void ath79_register_leds_gpio(int id, 18 + unsigned num_leds, 19 + struct gpio_led *leds); 20 + 21 + #endif /* _ATH79_DEV_LEDS_GPIO_H */
+38
arch/mips/ath79/dev-spi.c
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X SPI controller device 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/platform_device.h> 13 + #include <asm/mach-ath79/ar71xx_regs.h> 14 + #include "dev-spi.h" 15 + 16 + static struct resource ath79_spi_resources[] = { 17 + { 18 + .start = AR71XX_SPI_BASE, 19 + .end = AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1, 20 + .flags = IORESOURCE_MEM, 21 + }, 22 + }; 23 + 24 + static struct platform_device ath79_spi_device = { 25 + .name = "ath79-spi", 26 + .id = -1, 27 + .resource = ath79_spi_resources, 28 + .num_resources = ARRAY_SIZE(ath79_spi_resources), 29 + }; 30 + 31 + void __init ath79_register_spi(struct ath79_spi_platform_data *pdata, 32 + struct spi_board_info const *info, 33 + unsigned n) 34 + { 35 + spi_register_board_info(info, n); 36 + ath79_spi_device.dev.platform_data = pdata; 37 + platform_device_register(&ath79_spi_device); 38 + }
+22
arch/mips/ath79/dev-spi.h
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X SPI controller device 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #ifndef _ATH79_DEV_SPI_H 13 + #define _ATH79_DEV_SPI_H 14 + 15 + #include <linux/spi/spi.h> 16 + #include <asm/mach-ath79/ath79_spi_platform.h> 17 + 18 + void ath79_register_spi(struct ath79_spi_platform_data *pdata, 19 + struct spi_board_info const *info, 20 + unsigned n); 21 + 22 + #endif /* _ATH79_DEV_SPI_H */
+36
arch/mips/ath79/early_printk.c
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X SoC early printk support 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/io.h> 13 + #include <linux/serial_reg.h> 14 + #include <asm/addrspace.h> 15 + 16 + #include <asm/mach-ath79/ar71xx_regs.h> 17 + 18 + static inline void prom_wait_thre(void __iomem *base) 19 + { 20 + u32 lsr; 21 + 22 + do { 23 + lsr = __raw_readl(base + UART_LSR * 4); 24 + if (lsr & UART_LSR_THRE) 25 + break; 26 + } while (1); 27 + } 28 + 29 + void prom_putchar(unsigned char ch) 30 + { 31 + void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE)); 32 + 33 + prom_wait_thre(base); 34 + __raw_writel(ch, base + UART_TX * 4); 35 + prom_wait_thre(base); 36 + }
+197
arch/mips/ath79/gpio.c
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X GPIO API support 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/kernel.h> 13 + #include <linux/init.h> 14 + #include <linux/module.h> 15 + #include <linux/types.h> 16 + #include <linux/spinlock.h> 17 + #include <linux/io.h> 18 + #include <linux/ioport.h> 19 + #include <linux/gpio.h> 20 + 21 + #include <asm/mach-ath79/ar71xx_regs.h> 22 + #include <asm/mach-ath79/ath79.h> 23 + #include "common.h" 24 + 25 + static void __iomem *ath79_gpio_base; 26 + static unsigned long ath79_gpio_count; 27 + static DEFINE_SPINLOCK(ath79_gpio_lock); 28 + 29 + static void __ath79_gpio_set_value(unsigned gpio, int value) 30 + { 31 + void __iomem *base = ath79_gpio_base; 32 + 33 + if (value) 34 + __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET); 35 + else 36 + __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR); 37 + } 38 + 39 + static int __ath79_gpio_get_value(unsigned gpio) 40 + { 41 + return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1; 42 + } 43 + 44 + static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset) 45 + { 46 + return __ath79_gpio_get_value(offset); 47 + } 48 + 49 + static void ath79_gpio_set_value(struct gpio_chip *chip, 50 + unsigned offset, int value) 51 + { 52 + __ath79_gpio_set_value(offset, value); 53 + } 54 + 55 + static int ath79_gpio_direction_input(struct gpio_chip *chip, 56 + unsigned offset) 57 + { 58 + void __iomem *base = ath79_gpio_base; 59 + unsigned long flags; 60 + 61 + spin_lock_irqsave(&ath79_gpio_lock, flags); 62 + 63 + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset), 64 + base + AR71XX_GPIO_REG_OE); 65 + 66 + spin_unlock_irqrestore(&ath79_gpio_lock, flags); 67 + 68 + return 0; 69 + } 70 + 71 + static int ath79_gpio_direction_output(struct gpio_chip *chip, 72 + unsigned offset, int value) 73 + { 74 + void __iomem *base = ath79_gpio_base; 75 + unsigned long flags; 76 + 77 + spin_lock_irqsave(&ath79_gpio_lock, flags); 78 + 79 + if (value) 80 + __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET); 81 + else 82 + __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR); 83 + 84 + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset), 85 + base + AR71XX_GPIO_REG_OE); 86 + 87 + spin_unlock_irqrestore(&ath79_gpio_lock, flags); 88 + 89 + return 0; 90 + } 91 + 92 + static struct gpio_chip ath79_gpio_chip = { 93 + .label = "ath79", 94 + .get = ath79_gpio_get_value, 95 + .set = ath79_gpio_set_value, 96 + .direction_input = ath79_gpio_direction_input, 97 + .direction_output = ath79_gpio_direction_output, 98 + .base = 0, 99 + }; 100 + 101 + void ath79_gpio_function_enable(u32 mask) 102 + { 103 + void __iomem *base = ath79_gpio_base; 104 + unsigned long flags; 105 + 106 + spin_lock_irqsave(&ath79_gpio_lock, flags); 107 + 108 + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) | mask, 109 + base + AR71XX_GPIO_REG_FUNC); 110 + /* flush write */ 111 + __raw_readl(base + AR71XX_GPIO_REG_FUNC); 112 + 113 + spin_unlock_irqrestore(&ath79_gpio_lock, flags); 114 + } 115 + 116 + void ath79_gpio_function_disable(u32 mask) 117 + { 118 + void __iomem *base = ath79_gpio_base; 119 + unsigned long flags; 120 + 121 + spin_lock_irqsave(&ath79_gpio_lock, flags); 122 + 123 + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~mask, 124 + base + AR71XX_GPIO_REG_FUNC); 125 + /* flush write */ 126 + __raw_readl(base + AR71XX_GPIO_REG_FUNC); 127 + 128 + spin_unlock_irqrestore(&ath79_gpio_lock, flags); 129 + } 130 + 131 + void ath79_gpio_function_setup(u32 set, u32 clear) 132 + { 133 + void __iomem *base = ath79_gpio_base; 134 + unsigned long flags; 135 + 136 + spin_lock_irqsave(&ath79_gpio_lock, flags); 137 + 138 + __raw_writel((__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~clear) | set, 139 + base + AR71XX_GPIO_REG_FUNC); 140 + /* flush write */ 141 + __raw_readl(base + AR71XX_GPIO_REG_FUNC); 142 + 143 + spin_unlock_irqrestore(&ath79_gpio_lock, flags); 144 + } 145 + 146 + void __init ath79_gpio_init(void) 147 + { 148 + int err; 149 + 150 + if (soc_is_ar71xx()) 151 + ath79_gpio_count = AR71XX_GPIO_COUNT; 152 + else if (soc_is_ar724x()) 153 + ath79_gpio_count = AR724X_GPIO_COUNT; 154 + else if (soc_is_ar913x()) 155 + ath79_gpio_count = AR913X_GPIO_COUNT; 156 + else 157 + BUG(); 158 + 159 + ath79_gpio_base = ioremap_nocache(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE); 160 + ath79_gpio_chip.ngpio = ath79_gpio_count; 161 + 162 + err = gpiochip_add(&ath79_gpio_chip); 163 + if (err) 164 + panic("cannot add AR71xx GPIO chip, error=%d", err); 165 + } 166 + 167 + int gpio_get_value(unsigned gpio) 168 + { 169 + if (gpio < ath79_gpio_count) 170 + return __ath79_gpio_get_value(gpio); 171 + 172 + return __gpio_get_value(gpio); 173 + } 174 + EXPORT_SYMBOL(gpio_get_value); 175 + 176 + void gpio_set_value(unsigned gpio, int value) 177 + { 178 + if (gpio < ath79_gpio_count) 179 + __ath79_gpio_set_value(gpio, value); 180 + else 181 + __gpio_set_value(gpio, value); 182 + } 183 + EXPORT_SYMBOL(gpio_set_value); 184 + 185 + int gpio_to_irq(unsigned gpio) 186 + { 187 + /* FIXME */ 188 + return -EINVAL; 189 + } 190 + EXPORT_SYMBOL(gpio_to_irq); 191 + 192 + int irq_to_gpio(unsigned irq) 193 + { 194 + /* FIXME */ 195 + return -EINVAL; 196 + } 197 + EXPORT_SYMBOL(irq_to_gpio);
+187
arch/mips/ath79/irq.c
··· 1 + /* 2 + * Atheros AR71xx/AR724x/AR913x specific interrupt handling 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * Parts of this file are based on Atheros' 2.6.15 BSP 8 + * 9 + * This program is free software; you can redistribute it and/or modify it 10 + * under the terms of the GNU General Public License version 2 as published 11 + * by the Free Software Foundation. 12 + */ 13 + 14 + #include <linux/kernel.h> 15 + #include <linux/init.h> 16 + #include <linux/interrupt.h> 17 + #include <linux/irq.h> 18 + 19 + #include <asm/irq_cpu.h> 20 + #include <asm/mipsregs.h> 21 + 22 + #include <asm/mach-ath79/ath79.h> 23 + #include <asm/mach-ath79/ar71xx_regs.h> 24 + #include "common.h" 25 + 26 + static unsigned int ath79_ip2_flush_reg; 27 + static unsigned int ath79_ip3_flush_reg; 28 + 29 + static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc) 30 + { 31 + void __iomem *base = ath79_reset_base; 32 + u32 pending; 33 + 34 + pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) & 35 + __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 36 + 37 + if (pending & MISC_INT_UART) 38 + generic_handle_irq(ATH79_MISC_IRQ_UART); 39 + 40 + else if (pending & MISC_INT_DMA) 41 + generic_handle_irq(ATH79_MISC_IRQ_DMA); 42 + 43 + else if (pending & MISC_INT_PERFC) 44 + generic_handle_irq(ATH79_MISC_IRQ_PERFC); 45 + 46 + else if (pending & MISC_INT_TIMER) 47 + generic_handle_irq(ATH79_MISC_IRQ_TIMER); 48 + 49 + else if (pending & MISC_INT_OHCI) 50 + generic_handle_irq(ATH79_MISC_IRQ_OHCI); 51 + 52 + else if (pending & MISC_INT_ERROR) 53 + generic_handle_irq(ATH79_MISC_IRQ_ERROR); 54 + 55 + else if (pending & MISC_INT_GPIO) 56 + generic_handle_irq(ATH79_MISC_IRQ_GPIO); 57 + 58 + else if (pending & MISC_INT_WDOG) 59 + generic_handle_irq(ATH79_MISC_IRQ_WDOG); 60 + 61 + else 62 + spurious_interrupt(); 63 + } 64 + 65 + static void ar71xx_misc_irq_unmask(unsigned int irq) 66 + { 67 + void __iomem *base = ath79_reset_base; 68 + u32 t; 69 + 70 + irq -= ATH79_MISC_IRQ_BASE; 71 + 72 + t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 73 + __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE); 74 + 75 + /* flush write */ 76 + __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 77 + } 78 + 79 + static void ar71xx_misc_irq_mask(unsigned int irq) 80 + { 81 + void __iomem *base = ath79_reset_base; 82 + u32 t; 83 + 84 + irq -= ATH79_MISC_IRQ_BASE; 85 + 86 + t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 87 + __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE); 88 + 89 + /* flush write */ 90 + __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 91 + } 92 + 93 + static void ar724x_misc_irq_ack(unsigned int irq) 94 + { 95 + void __iomem *base = ath79_reset_base; 96 + u32 t; 97 + 98 + irq -= ATH79_MISC_IRQ_BASE; 99 + 100 + t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS); 101 + __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_STATUS); 102 + 103 + /* flush write */ 104 + __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS); 105 + } 106 + 107 + static struct irq_chip ath79_misc_irq_chip = { 108 + .name = "MISC", 109 + .unmask = ar71xx_misc_irq_unmask, 110 + .mask = ar71xx_misc_irq_mask, 111 + }; 112 + 113 + static void __init ath79_misc_irq_init(void) 114 + { 115 + void __iomem *base = ath79_reset_base; 116 + int i; 117 + 118 + __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE); 119 + __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS); 120 + 121 + if (soc_is_ar71xx() || soc_is_ar913x()) 122 + ath79_misc_irq_chip.mask_ack = ar71xx_misc_irq_mask; 123 + else if (soc_is_ar724x()) 124 + ath79_misc_irq_chip.ack = ar724x_misc_irq_ack; 125 + else 126 + BUG(); 127 + 128 + for (i = ATH79_MISC_IRQ_BASE; 129 + i < ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT; i++) { 130 + irq_desc[i].status = IRQ_DISABLED; 131 + set_irq_chip_and_handler(i, &ath79_misc_irq_chip, 132 + handle_level_irq); 133 + } 134 + 135 + set_irq_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler); 136 + } 137 + 138 + asmlinkage void plat_irq_dispatch(void) 139 + { 140 + unsigned long pending; 141 + 142 + pending = read_c0_status() & read_c0_cause() & ST0_IM; 143 + 144 + if (pending & STATUSF_IP7) 145 + do_IRQ(ATH79_CPU_IRQ_TIMER); 146 + 147 + else if (pending & STATUSF_IP2) { 148 + ath79_ddr_wb_flush(ath79_ip2_flush_reg); 149 + do_IRQ(ATH79_CPU_IRQ_IP2); 150 + } 151 + 152 + else if (pending & STATUSF_IP4) 153 + do_IRQ(ATH79_CPU_IRQ_GE0); 154 + 155 + else if (pending & STATUSF_IP5) 156 + do_IRQ(ATH79_CPU_IRQ_GE1); 157 + 158 + else if (pending & STATUSF_IP3) { 159 + ath79_ddr_wb_flush(ath79_ip3_flush_reg); 160 + do_IRQ(ATH79_CPU_IRQ_USB); 161 + } 162 + 163 + else if (pending & STATUSF_IP6) 164 + do_IRQ(ATH79_CPU_IRQ_MISC); 165 + 166 + else 167 + spurious_interrupt(); 168 + } 169 + 170 + void __init arch_init_irq(void) 171 + { 172 + if (soc_is_ar71xx()) { 173 + ath79_ip2_flush_reg = AR71XX_DDR_REG_FLUSH_PCI; 174 + ath79_ip3_flush_reg = AR71XX_DDR_REG_FLUSH_USB; 175 + } else if (soc_is_ar724x()) { 176 + ath79_ip2_flush_reg = AR724X_DDR_REG_FLUSH_PCIE; 177 + ath79_ip3_flush_reg = AR724X_DDR_REG_FLUSH_USB; 178 + } else if (soc_is_ar913x()) { 179 + ath79_ip2_flush_reg = AR913X_DDR_REG_FLUSH_WMAC; 180 + ath79_ip3_flush_reg = AR913X_DDR_REG_FLUSH_USB; 181 + } else 182 + BUG(); 183 + 184 + cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC; 185 + mips_cpu_irq_init(); 186 + ath79_misc_irq_init(); 187 + }
+98
arch/mips/ath79/mach-ap81.c
··· 1 + /* 2 + * Atheros AP81 board support 3 + * 4 + * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2009 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #include "machtypes.h" 13 + #include "dev-ar913x-wmac.h" 14 + #include "dev-gpio-buttons.h" 15 + #include "dev-leds-gpio.h" 16 + #include "dev-spi.h" 17 + 18 + #define AP81_GPIO_LED_STATUS 1 19 + #define AP81_GPIO_LED_AOSS 3 20 + #define AP81_GPIO_LED_WLAN 6 21 + #define AP81_GPIO_LED_POWER 14 22 + 23 + #define AP81_GPIO_BTN_SW4 12 24 + #define AP81_GPIO_BTN_SW1 21 25 + 26 + #define AP81_KEYS_POLL_INTERVAL 20 /* msecs */ 27 + #define AP81_KEYS_DEBOUNCE_INTERVAL (3 * AP81_KEYS_POLL_INTERVAL) 28 + 29 + #define AP81_CAL_DATA_ADDR 0x1fff1000 30 + 31 + static struct gpio_led ap81_leds_gpio[] __initdata = { 32 + { 33 + .name = "ap81:green:status", 34 + .gpio = AP81_GPIO_LED_STATUS, 35 + .active_low = 1, 36 + }, { 37 + .name = "ap81:amber:aoss", 38 + .gpio = AP81_GPIO_LED_AOSS, 39 + .active_low = 1, 40 + }, { 41 + .name = "ap81:green:wlan", 42 + .gpio = AP81_GPIO_LED_WLAN, 43 + .active_low = 1, 44 + }, { 45 + .name = "ap81:green:power", 46 + .gpio = AP81_GPIO_LED_POWER, 47 + .active_low = 1, 48 + } 49 + }; 50 + 51 + static struct gpio_keys_button ap81_gpio_keys[] __initdata = { 52 + { 53 + .desc = "sw1", 54 + .type = EV_KEY, 55 + .code = BTN_0, 56 + .debounce_interval = AP81_KEYS_DEBOUNCE_INTERVAL, 57 + .gpio = AP81_GPIO_BTN_SW1, 58 + .active_low = 1, 59 + } , { 60 + .desc = "sw4", 61 + .type = EV_KEY, 62 + .code = BTN_1, 63 + .debounce_interval = AP81_KEYS_DEBOUNCE_INTERVAL, 64 + .gpio = AP81_GPIO_BTN_SW4, 65 + .active_low = 1, 66 + } 67 + }; 68 + 69 + static struct spi_board_info ap81_spi_info[] = { 70 + { 71 + .bus_num = 0, 72 + .chip_select = 0, 73 + .max_speed_hz = 25000000, 74 + .modalias = "m25p64", 75 + } 76 + }; 77 + 78 + static struct ath79_spi_platform_data ap81_spi_data = { 79 + .bus_num = 0, 80 + .num_chipselect = 1, 81 + }; 82 + 83 + static void __init ap81_setup(void) 84 + { 85 + u8 *cal_data = (u8 *) KSEG1ADDR(AP81_CAL_DATA_ADDR); 86 + 87 + ath79_register_leds_gpio(-1, ARRAY_SIZE(ap81_leds_gpio), 88 + ap81_leds_gpio); 89 + ath79_register_gpio_keys_polled(-1, AP81_KEYS_POLL_INTERVAL, 90 + ARRAY_SIZE(ap81_gpio_keys), 91 + ap81_gpio_keys); 92 + ath79_register_spi(&ap81_spi_data, ap81_spi_info, 93 + ARRAY_SIZE(ap81_spi_info)); 94 + ath79_register_ar913x_wmac(cal_data); 95 + } 96 + 97 + MIPS_MACHINE(ATH79_MACH_AP81, "AP81", "Atheros AP81 reference board", 98 + ap81_setup);
+118
arch/mips/ath79/mach-pb44.c
··· 1 + /* 2 + * Atheros PB44 reference board support 3 + * 4 + * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License version 2 as published 8 + * by the Free Software Foundation. 9 + */ 10 + 11 + #include <linux/init.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/i2c.h> 14 + #include <linux/i2c-gpio.h> 15 + #include <linux/i2c/pcf857x.h> 16 + 17 + #include "machtypes.h" 18 + #include "dev-gpio-buttons.h" 19 + #include "dev-leds-gpio.h" 20 + #include "dev-spi.h" 21 + 22 + #define PB44_GPIO_I2C_SCL 0 23 + #define PB44_GPIO_I2C_SDA 1 24 + 25 + #define PB44_GPIO_EXP_BASE 16 26 + #define PB44_GPIO_SW_RESET (PB44_GPIO_EXP_BASE + 6) 27 + #define PB44_GPIO_SW_JUMP (PB44_GPIO_EXP_BASE + 8) 28 + #define PB44_GPIO_LED_JUMP1 (PB44_GPIO_EXP_BASE + 9) 29 + #define PB44_GPIO_LED_JUMP2 (PB44_GPIO_EXP_BASE + 10) 30 + 31 + #define PB44_KEYS_POLL_INTERVAL 20 /* msecs */ 32 + #define PB44_KEYS_DEBOUNCE_INTERVAL (3 * PB44_KEYS_POLL_INTERVAL) 33 + 34 + static struct i2c_gpio_platform_data pb44_i2c_gpio_data = { 35 + .sda_pin = PB44_GPIO_I2C_SDA, 36 + .scl_pin = PB44_GPIO_I2C_SCL, 37 + }; 38 + 39 + static struct platform_device pb44_i2c_gpio_device = { 40 + .name = "i2c-gpio", 41 + .id = 0, 42 + .dev = { 43 + .platform_data = &pb44_i2c_gpio_data, 44 + } 45 + }; 46 + 47 + static struct pcf857x_platform_data pb44_pcf857x_data = { 48 + .gpio_base = PB44_GPIO_EXP_BASE, 49 + }; 50 + 51 + static struct i2c_board_info pb44_i2c_board_info[] __initdata = { 52 + { 53 + I2C_BOARD_INFO("pcf8575", 0x20), 54 + .platform_data = &pb44_pcf857x_data, 55 + }, 56 + }; 57 + 58 + static struct gpio_led pb44_leds_gpio[] __initdata = { 59 + { 60 + .name = "pb44:amber:jump1", 61 + .gpio = PB44_GPIO_LED_JUMP1, 62 + .active_low = 1, 63 + }, { 64 + .name = "pb44:green:jump2", 65 + .gpio = PB44_GPIO_LED_JUMP2, 66 + .active_low = 1, 67 + }, 68 + }; 69 + 70 + static struct gpio_keys_button pb44_gpio_keys[] __initdata = { 71 + { 72 + .desc = "soft_reset", 73 + .type = EV_KEY, 74 + .code = KEY_RESTART, 75 + .debounce_interval = PB44_KEYS_DEBOUNCE_INTERVAL, 76 + .gpio = PB44_GPIO_SW_RESET, 77 + .active_low = 1, 78 + } , { 79 + .desc = "jumpstart", 80 + .type = EV_KEY, 81 + .code = KEY_WPS_BUTTON, 82 + .debounce_interval = PB44_KEYS_DEBOUNCE_INTERVAL, 83 + .gpio = PB44_GPIO_SW_JUMP, 84 + .active_low = 1, 85 + } 86 + }; 87 + 88 + static struct spi_board_info pb44_spi_info[] = { 89 + { 90 + .bus_num = 0, 91 + .chip_select = 0, 92 + .max_speed_hz = 25000000, 93 + .modalias = "m25p64", 94 + }, 95 + }; 96 + 97 + static struct ath79_spi_platform_data pb44_spi_data = { 98 + .bus_num = 0, 99 + .num_chipselect = 1, 100 + }; 101 + 102 + static void __init pb44_init(void) 103 + { 104 + i2c_register_board_info(0, pb44_i2c_board_info, 105 + ARRAY_SIZE(pb44_i2c_board_info)); 106 + platform_device_register(&pb44_i2c_gpio_device); 107 + 108 + ath79_register_leds_gpio(-1, ARRAY_SIZE(pb44_leds_gpio), 109 + pb44_leds_gpio); 110 + ath79_register_gpio_keys_polled(-1, PB44_KEYS_POLL_INTERVAL, 111 + ARRAY_SIZE(pb44_gpio_keys), 112 + pb44_gpio_keys); 113 + ath79_register_spi(&pb44_spi_data, pb44_spi_info, 114 + ARRAY_SIZE(pb44_spi_info)); 115 + } 116 + 117 + MIPS_MACHINE(ATH79_MACH_PB44, "PB44", "Atheros PB44 reference board", 118 + pb44_init);
+23
arch/mips/ath79/machtypes.h
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X machine type definitions 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #ifndef _ATH79_MACHTYPE_H 13 + #define _ATH79_MACHTYPE_H 14 + 15 + #include <asm/mips_machine.h> 16 + 17 + enum ath79_mach_type { 18 + ATH79_MACH_GENERIC = 0, 19 + ATH79_MACH_AP81, /* Atheros AP81 reference board */ 20 + ATH79_MACH_PB44, /* Atheros PB44 reference board */ 21 + }; 22 + 23 + #endif /* _ATH79_MACHTYPE_H */
+57
arch/mips/ath79/prom.c
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X specific prom routines 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/kernel.h> 13 + #include <linux/init.h> 14 + #include <linux/io.h> 15 + #include <linux/string.h> 16 + 17 + #include <asm/bootinfo.h> 18 + #include <asm/addrspace.h> 19 + 20 + #include "common.h" 21 + 22 + static inline int is_valid_ram_addr(void *addr) 23 + { 24 + if (((u32) addr > KSEG0) && 25 + ((u32) addr < (KSEG0 + ATH79_MEM_SIZE_MAX))) 26 + return 1; 27 + 28 + if (((u32) addr > KSEG1) && 29 + ((u32) addr < (KSEG1 + ATH79_MEM_SIZE_MAX))) 30 + return 1; 31 + 32 + return 0; 33 + } 34 + 35 + static __init void ath79_prom_init_cmdline(int argc, char **argv) 36 + { 37 + int i; 38 + 39 + if (!is_valid_ram_addr(argv)) 40 + return; 41 + 42 + for (i = 0; i < argc; i++) 43 + if (is_valid_ram_addr(argv[i])) { 44 + strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); 45 + strlcat(arcs_cmdline, argv[i], sizeof(arcs_cmdline)); 46 + } 47 + } 48 + 49 + void __init prom_init(void) 50 + { 51 + ath79_prom_init_cmdline(fw_arg0, (char **)fw_arg1); 52 + } 53 + 54 + void __init prom_free_prom_memory(void) 55 + { 56 + /* We do not have to prom memory to free */ 57 + }
+206
arch/mips/ath79/setup.c
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X specific setup 3 + * 4 + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * Parts of this file are based on Atheros' 2.6.15 BSP 8 + * 9 + * This program is free software; you can redistribute it and/or modify it 10 + * under the terms of the GNU General Public License version 2 as published 11 + * by the Free Software Foundation. 12 + */ 13 + 14 + #include <linux/kernel.h> 15 + #include <linux/init.h> 16 + #include <linux/bootmem.h> 17 + #include <linux/err.h> 18 + #include <linux/clk.h> 19 + 20 + #include <asm/bootinfo.h> 21 + #include <asm/time.h> /* for mips_hpt_frequency */ 22 + #include <asm/reboot.h> /* for _machine_{restart,halt} */ 23 + #include <asm/mips_machine.h> 24 + 25 + #include <asm/mach-ath79/ath79.h> 26 + #include <asm/mach-ath79/ar71xx_regs.h> 27 + #include "common.h" 28 + #include "dev-common.h" 29 + #include "machtypes.h" 30 + 31 + #define ATH79_SYS_TYPE_LEN 64 32 + 33 + #define AR71XX_BASE_FREQ 40000000 34 + #define AR724X_BASE_FREQ 5000000 35 + #define AR913X_BASE_FREQ 5000000 36 + 37 + static char ath79_sys_type[ATH79_SYS_TYPE_LEN]; 38 + 39 + static void ath79_restart(char *command) 40 + { 41 + ath79_device_reset_set(AR71XX_RESET_FULL_CHIP); 42 + for (;;) 43 + if (cpu_wait) 44 + cpu_wait(); 45 + } 46 + 47 + static void ath79_halt(void) 48 + { 49 + while (1) 50 + cpu_wait(); 51 + } 52 + 53 + static void __init ath79_detect_mem_size(void) 54 + { 55 + unsigned long size; 56 + 57 + for (size = ATH79_MEM_SIZE_MIN; size < ATH79_MEM_SIZE_MAX; 58 + size <<= 1) { 59 + if (!memcmp(ath79_detect_mem_size, 60 + ath79_detect_mem_size + size, 1024)) 61 + break; 62 + } 63 + 64 + add_memory_region(0, size, BOOT_MEM_RAM); 65 + } 66 + 67 + static void __init ath79_detect_sys_type(void) 68 + { 69 + char *chip = "????"; 70 + u32 id; 71 + u32 major; 72 + u32 minor; 73 + u32 rev = 0; 74 + 75 + id = ath79_reset_rr(AR71XX_RESET_REG_REV_ID); 76 + major = id & REV_ID_MAJOR_MASK; 77 + 78 + switch (major) { 79 + case REV_ID_MAJOR_AR71XX: 80 + minor = id & AR71XX_REV_ID_MINOR_MASK; 81 + rev = id >> AR71XX_REV_ID_REVISION_SHIFT; 82 + rev &= AR71XX_REV_ID_REVISION_MASK; 83 + switch (minor) { 84 + case AR71XX_REV_ID_MINOR_AR7130: 85 + ath79_soc = ATH79_SOC_AR7130; 86 + chip = "7130"; 87 + break; 88 + 89 + case AR71XX_REV_ID_MINOR_AR7141: 90 + ath79_soc = ATH79_SOC_AR7141; 91 + chip = "7141"; 92 + break; 93 + 94 + case AR71XX_REV_ID_MINOR_AR7161: 95 + ath79_soc = ATH79_SOC_AR7161; 96 + chip = "7161"; 97 + break; 98 + } 99 + break; 100 + 101 + case REV_ID_MAJOR_AR7240: 102 + ath79_soc = ATH79_SOC_AR7240; 103 + chip = "7240"; 104 + rev = (id & AR724X_REV_ID_REVISION_MASK); 105 + break; 106 + 107 + case REV_ID_MAJOR_AR7241: 108 + ath79_soc = ATH79_SOC_AR7241; 109 + chip = "7241"; 110 + rev = (id & AR724X_REV_ID_REVISION_MASK); 111 + break; 112 + 113 + case REV_ID_MAJOR_AR7242: 114 + ath79_soc = ATH79_SOC_AR7242; 115 + chip = "7242"; 116 + rev = (id & AR724X_REV_ID_REVISION_MASK); 117 + break; 118 + 119 + case REV_ID_MAJOR_AR913X: 120 + minor = id & AR913X_REV_ID_MINOR_MASK; 121 + rev = id >> AR913X_REV_ID_REVISION_SHIFT; 122 + rev &= AR913X_REV_ID_REVISION_MASK; 123 + switch (minor) { 124 + case AR913X_REV_ID_MINOR_AR9130: 125 + ath79_soc = ATH79_SOC_AR9130; 126 + chip = "9130"; 127 + break; 128 + 129 + case AR913X_REV_ID_MINOR_AR9132: 130 + ath79_soc = ATH79_SOC_AR9132; 131 + chip = "9132"; 132 + break; 133 + } 134 + break; 135 + 136 + default: 137 + panic("ath79: unknown SoC, id:0x%08x\n", id); 138 + } 139 + 140 + sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev); 141 + pr_info("SoC: %s\n", ath79_sys_type); 142 + } 143 + 144 + const char *get_system_type(void) 145 + { 146 + return ath79_sys_type; 147 + } 148 + 149 + unsigned int __cpuinit get_c0_compare_int(void) 150 + { 151 + return CP0_LEGACY_COMPARE_IRQ; 152 + } 153 + 154 + void __init plat_mem_setup(void) 155 + { 156 + set_io_port_base(KSEG1); 157 + 158 + ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE, 159 + AR71XX_RESET_SIZE); 160 + ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE, 161 + AR71XX_PLL_SIZE); 162 + ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE, 163 + AR71XX_DDR_CTRL_SIZE); 164 + 165 + ath79_detect_sys_type(); 166 + ath79_detect_mem_size(); 167 + ath79_clocks_init(); 168 + 169 + _machine_restart = ath79_restart; 170 + _machine_halt = ath79_halt; 171 + pm_power_off = ath79_halt; 172 + } 173 + 174 + void __init plat_time_init(void) 175 + { 176 + struct clk *clk; 177 + 178 + clk = clk_get(NULL, "cpu"); 179 + if (IS_ERR(clk)) 180 + panic("unable to get CPU clock, err=%ld", PTR_ERR(clk)); 181 + 182 + mips_hpt_frequency = clk_get_rate(clk) / 2; 183 + } 184 + 185 + static int __init ath79_setup(void) 186 + { 187 + ath79_gpio_init(); 188 + ath79_register_uart(); 189 + ath79_register_wdt(); 190 + 191 + mips_machine_setup(); 192 + 193 + return 0; 194 + } 195 + 196 + arch_initcall(ath79_setup); 197 + 198 + static void __init ath79_generic_init(void) 199 + { 200 + /* Nothing to do */ 201 + } 202 + 203 + MIPS_MACHINE(ATH79_MACH_GENERIC, 204 + "Generic", 205 + "Generic AR71XX/AR724X/AR913X based board", 206 + ath79_generic_init);
+3
arch/mips/configs/malta_defconfig
··· 369 369 CONFIG_SERIAL_8250=y 370 370 CONFIG_SERIAL_8250_CONSOLE=y 371 371 # CONFIG_HWMON is not set 372 + CONFIG_FB=y 373 + CONFIG_FB_CIRRUS=y 372 374 # CONFIG_VGA_CONSOLE is not set 375 + CONFIG_FRAMEBUFFER_CONSOLE=y 373 376 CONFIG_HID=m 374 377 CONFIG_LEDS_CLASS=m 375 378 CONFIG_LEDS_TRIGGER_TIMER=m
+2
arch/mips/include/asm/cache.h
··· 17 17 #define SMP_CACHE_SHIFT L1_CACHE_SHIFT 18 18 #define SMP_CACHE_BYTES L1_CACHE_BYTES 19 19 20 + #define __read_mostly __attribute__((__section__(".data.read_mostly"))) 21 + 20 22 #endif /* _ASM_CACHE_H */
+1
arch/mips/include/asm/cpu-info.h
··· 78 78 unsigned int watch_reg_use_cnt; /* Usable by ptrace */ 79 79 #define NUM_WATCH_REGS 4 80 80 u16 watch_reg_masks[NUM_WATCH_REGS]; 81 + unsigned int kscratch_mask; /* Usable KScratch mask. */ 81 82 } __attribute__((aligned(SMP_CACHE_BYTES))); 82 83 83 84 extern struct cpuinfo_mips cpu_data[];
+14
arch/mips/include/asm/inst.h
··· 72 72 enum spec3_op { 73 73 ext_op, dextm_op, dextu_op, dext_op, 74 74 ins_op, dinsm_op, dinsu_op, dins_op, 75 + lx_op = 0x0a, 75 76 bshfl_op = 0x20, 76 77 dbshfl_op = 0x24, 77 78 rdhwr_op = 0x3b ··· 177 176 enum mad_func { 178 177 madd_fp_op = 0x08, msub_fp_op = 0x0a, 179 178 nmadd_fp_op = 0x0c, nmsub_fp_op = 0x0e 179 + }; 180 + 181 + /* 182 + * func field for special3 lx opcodes (Cavium Octeon). 183 + */ 184 + enum lx_func { 185 + lwx_op = 0x00, 186 + lhx_op = 0x04, 187 + lbux_op = 0x06, 188 + ldx_op = 0x08, 189 + lwux_op = 0x10, 190 + lhux_op = 0x14, 191 + lbx_op = 0x16, 180 192 }; 181 193 182 194 /*
+48
arch/mips/include/asm/jump_label.h
··· 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) 2010 Cavium Networks, Inc. 7 + */ 8 + #ifndef _ASM_MIPS_JUMP_LABEL_H 9 + #define _ASM_MIPS_JUMP_LABEL_H 10 + 11 + #include <linux/types.h> 12 + 13 + #ifdef __KERNEL__ 14 + 15 + #define JUMP_LABEL_NOP_SIZE 4 16 + 17 + #ifdef CONFIG_64BIT 18 + #define WORD_INSN ".dword" 19 + #else 20 + #define WORD_INSN ".word" 21 + #endif 22 + 23 + #define JUMP_LABEL(key, label) \ 24 + do { \ 25 + asm goto("1:\tnop\n\t" \ 26 + "nop\n\t" \ 27 + ".pushsection __jump_table, \"a\"\n\t" \ 28 + WORD_INSN " 1b, %l[" #label "], %0\n\t" \ 29 + ".popsection\n\t" \ 30 + : : "i" (key) : : label); \ 31 + } while (0) 32 + 33 + 34 + #endif /* __KERNEL__ */ 35 + 36 + #ifdef CONFIG_64BIT 37 + typedef u64 jump_label_t; 38 + #else 39 + typedef u32 jump_label_t; 40 + #endif 41 + 42 + struct jump_entry { 43 + jump_label_t code; 44 + jump_label_t target; 45 + jump_label_t key; 46 + }; 47 + 48 + #endif /* _ASM_MIPS_JUMP_LABEL_H */
+233
arch/mips/include/asm/mach-ath79/ar71xx_regs.h
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X SoC register definitions 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * Parts of this file are based on Atheros' 2.6.15 BSP 8 + * 9 + * This program is free software; you can redistribute it and/or modify it 10 + * under the terms of the GNU General Public License version 2 as published 11 + * by the Free Software Foundation. 12 + */ 13 + 14 + #ifndef __ASM_MACH_AR71XX_REGS_H 15 + #define __ASM_MACH_AR71XX_REGS_H 16 + 17 + #include <linux/types.h> 18 + #include <linux/init.h> 19 + #include <linux/io.h> 20 + #include <linux/bitops.h> 21 + 22 + #define AR71XX_APB_BASE 0x18000000 23 + #define AR71XX_SPI_BASE 0x1f000000 24 + #define AR71XX_SPI_SIZE 0x01000000 25 + 26 + #define AR71XX_DDR_CTRL_BASE (AR71XX_APB_BASE + 0x00000000) 27 + #define AR71XX_DDR_CTRL_SIZE 0x100 28 + #define AR71XX_UART_BASE (AR71XX_APB_BASE + 0x00020000) 29 + #define AR71XX_UART_SIZE 0x100 30 + #define AR71XX_GPIO_BASE (AR71XX_APB_BASE + 0x00040000) 31 + #define AR71XX_GPIO_SIZE 0x100 32 + #define AR71XX_PLL_BASE (AR71XX_APB_BASE + 0x00050000) 33 + #define AR71XX_PLL_SIZE 0x100 34 + #define AR71XX_RESET_BASE (AR71XX_APB_BASE + 0x00060000) 35 + #define AR71XX_RESET_SIZE 0x100 36 + 37 + #define AR913X_WMAC_BASE (AR71XX_APB_BASE + 0x000C0000) 38 + #define AR913X_WMAC_SIZE 0x30000 39 + 40 + /* 41 + * DDR_CTRL block 42 + */ 43 + #define AR71XX_DDR_REG_PCI_WIN0 0x7c 44 + #define AR71XX_DDR_REG_PCI_WIN1 0x80 45 + #define AR71XX_DDR_REG_PCI_WIN2 0x84 46 + #define AR71XX_DDR_REG_PCI_WIN3 0x88 47 + #define AR71XX_DDR_REG_PCI_WIN4 0x8c 48 + #define AR71XX_DDR_REG_PCI_WIN5 0x90 49 + #define AR71XX_DDR_REG_PCI_WIN6 0x94 50 + #define AR71XX_DDR_REG_PCI_WIN7 0x98 51 + #define AR71XX_DDR_REG_FLUSH_GE0 0x9c 52 + #define AR71XX_DDR_REG_FLUSH_GE1 0xa0 53 + #define AR71XX_DDR_REG_FLUSH_USB 0xa4 54 + #define AR71XX_DDR_REG_FLUSH_PCI 0xa8 55 + 56 + #define AR724X_DDR_REG_FLUSH_GE0 0x7c 57 + #define AR724X_DDR_REG_FLUSH_GE1 0x80 58 + #define AR724X_DDR_REG_FLUSH_USB 0x84 59 + #define AR724X_DDR_REG_FLUSH_PCIE 0x88 60 + 61 + #define AR913X_DDR_REG_FLUSH_GE0 0x7c 62 + #define AR913X_DDR_REG_FLUSH_GE1 0x80 63 + #define AR913X_DDR_REG_FLUSH_USB 0x84 64 + #define AR913X_DDR_REG_FLUSH_WMAC 0x88 65 + 66 + /* 67 + * PLL block 68 + */ 69 + #define AR71XX_PLL_REG_CPU_CONFIG 0x00 70 + #define AR71XX_PLL_REG_SEC_CONFIG 0x04 71 + #define AR71XX_PLL_REG_ETH0_INT_CLOCK 0x10 72 + #define AR71XX_PLL_REG_ETH1_INT_CLOCK 0x14 73 + 74 + #define AR71XX_PLL_DIV_SHIFT 3 75 + #define AR71XX_PLL_DIV_MASK 0x1f 76 + #define AR71XX_CPU_DIV_SHIFT 16 77 + #define AR71XX_CPU_DIV_MASK 0x3 78 + #define AR71XX_DDR_DIV_SHIFT 18 79 + #define AR71XX_DDR_DIV_MASK 0x3 80 + #define AR71XX_AHB_DIV_SHIFT 20 81 + #define AR71XX_AHB_DIV_MASK 0x7 82 + 83 + #define AR724X_PLL_REG_CPU_CONFIG 0x00 84 + #define AR724X_PLL_REG_PCIE_CONFIG 0x18 85 + 86 + #define AR724X_PLL_DIV_SHIFT 0 87 + #define AR724X_PLL_DIV_MASK 0x3ff 88 + #define AR724X_PLL_REF_DIV_SHIFT 10 89 + #define AR724X_PLL_REF_DIV_MASK 0xf 90 + #define AR724X_AHB_DIV_SHIFT 19 91 + #define AR724X_AHB_DIV_MASK 0x1 92 + #define AR724X_DDR_DIV_SHIFT 22 93 + #define AR724X_DDR_DIV_MASK 0x3 94 + 95 + #define AR913X_PLL_REG_CPU_CONFIG 0x00 96 + #define AR913X_PLL_REG_ETH_CONFIG 0x04 97 + #define AR913X_PLL_REG_ETH0_INT_CLOCK 0x14 98 + #define AR913X_PLL_REG_ETH1_INT_CLOCK 0x18 99 + 100 + #define AR913X_PLL_DIV_SHIFT 0 101 + #define AR913X_PLL_DIV_MASK 0x3ff 102 + #define AR913X_DDR_DIV_SHIFT 22 103 + #define AR913X_DDR_DIV_MASK 0x3 104 + #define AR913X_AHB_DIV_SHIFT 19 105 + #define AR913X_AHB_DIV_MASK 0x1 106 + 107 + /* 108 + * RESET block 109 + */ 110 + #define AR71XX_RESET_REG_TIMER 0x00 111 + #define AR71XX_RESET_REG_TIMER_RELOAD 0x04 112 + #define AR71XX_RESET_REG_WDOG_CTRL 0x08 113 + #define AR71XX_RESET_REG_WDOG 0x0c 114 + #define AR71XX_RESET_REG_MISC_INT_STATUS 0x10 115 + #define AR71XX_RESET_REG_MISC_INT_ENABLE 0x14 116 + #define AR71XX_RESET_REG_PCI_INT_STATUS 0x18 117 + #define AR71XX_RESET_REG_PCI_INT_ENABLE 0x1c 118 + #define AR71XX_RESET_REG_GLOBAL_INT_STATUS 0x20 119 + #define AR71XX_RESET_REG_RESET_MODULE 0x24 120 + #define AR71XX_RESET_REG_PERFC_CTRL 0x2c 121 + #define AR71XX_RESET_REG_PERFC0 0x30 122 + #define AR71XX_RESET_REG_PERFC1 0x34 123 + #define AR71XX_RESET_REG_REV_ID 0x90 124 + 125 + #define AR913X_RESET_REG_GLOBAL_INT_STATUS 0x18 126 + #define AR913X_RESET_REG_RESET_MODULE 0x1c 127 + #define AR913X_RESET_REG_PERF_CTRL 0x20 128 + #define AR913X_RESET_REG_PERFC0 0x24 129 + #define AR913X_RESET_REG_PERFC1 0x28 130 + 131 + #define AR724X_RESET_REG_RESET_MODULE 0x1c 132 + 133 + #define MISC_INT_DMA BIT(7) 134 + #define MISC_INT_OHCI BIT(6) 135 + #define MISC_INT_PERFC BIT(5) 136 + #define MISC_INT_WDOG BIT(4) 137 + #define MISC_INT_UART BIT(3) 138 + #define MISC_INT_GPIO BIT(2) 139 + #define MISC_INT_ERROR BIT(1) 140 + #define MISC_INT_TIMER BIT(0) 141 + 142 + #define AR71XX_RESET_EXTERNAL BIT(28) 143 + #define AR71XX_RESET_FULL_CHIP BIT(24) 144 + #define AR71XX_RESET_CPU_NMI BIT(21) 145 + #define AR71XX_RESET_CPU_COLD BIT(20) 146 + #define AR71XX_RESET_DMA BIT(19) 147 + #define AR71XX_RESET_SLIC BIT(18) 148 + #define AR71XX_RESET_STEREO BIT(17) 149 + #define AR71XX_RESET_DDR BIT(16) 150 + #define AR71XX_RESET_GE1_MAC BIT(13) 151 + #define AR71XX_RESET_GE1_PHY BIT(12) 152 + #define AR71XX_RESET_USBSUS_OVERRIDE BIT(10) 153 + #define AR71XX_RESET_GE0_MAC BIT(9) 154 + #define AR71XX_RESET_GE0_PHY BIT(8) 155 + #define AR71XX_RESET_USB_OHCI_DLL BIT(6) 156 + #define AR71XX_RESET_USB_HOST BIT(5) 157 + #define AR71XX_RESET_USB_PHY BIT(4) 158 + #define AR71XX_RESET_PCI_BUS BIT(1) 159 + #define AR71XX_RESET_PCI_CORE BIT(0) 160 + 161 + #define AR724X_RESET_GE1_MDIO BIT(23) 162 + #define AR724X_RESET_GE0_MDIO BIT(22) 163 + #define AR724X_RESET_PCIE_PHY_SERIAL BIT(10) 164 + #define AR724X_RESET_PCIE_PHY BIT(7) 165 + #define AR724X_RESET_PCIE BIT(6) 166 + #define AR724X_RESET_OHCI_DLL BIT(3) 167 + 168 + #define AR913X_RESET_AMBA2WMAC BIT(22) 169 + 170 + #define REV_ID_MAJOR_MASK 0xfff0 171 + #define REV_ID_MAJOR_AR71XX 0x00a0 172 + #define REV_ID_MAJOR_AR913X 0x00b0 173 + #define REV_ID_MAJOR_AR7240 0x00c0 174 + #define REV_ID_MAJOR_AR7241 0x0100 175 + #define REV_ID_MAJOR_AR7242 0x1100 176 + 177 + #define AR71XX_REV_ID_MINOR_MASK 0x3 178 + #define AR71XX_REV_ID_MINOR_AR7130 0x0 179 + #define AR71XX_REV_ID_MINOR_AR7141 0x1 180 + #define AR71XX_REV_ID_MINOR_AR7161 0x2 181 + #define AR71XX_REV_ID_REVISION_MASK 0x3 182 + #define AR71XX_REV_ID_REVISION_SHIFT 2 183 + 184 + #define AR913X_REV_ID_MINOR_MASK 0x3 185 + #define AR913X_REV_ID_MINOR_AR9130 0x0 186 + #define AR913X_REV_ID_MINOR_AR9132 0x1 187 + #define AR913X_REV_ID_REVISION_MASK 0x3 188 + #define AR913X_REV_ID_REVISION_SHIFT 2 189 + 190 + #define AR724X_REV_ID_REVISION_MASK 0x3 191 + 192 + /* 193 + * SPI block 194 + */ 195 + #define AR71XX_SPI_REG_FS 0x00 /* Function Select */ 196 + #define AR71XX_SPI_REG_CTRL 0x04 /* SPI Control */ 197 + #define AR71XX_SPI_REG_IOC 0x08 /* SPI I/O Control */ 198 + #define AR71XX_SPI_REG_RDS 0x0c /* Read Data Shift */ 199 + 200 + #define AR71XX_SPI_FS_GPIO BIT(0) /* Enable GPIO mode */ 201 + 202 + #define AR71XX_SPI_CTRL_RD BIT(6) /* Remap Disable */ 203 + #define AR71XX_SPI_CTRL_DIV_MASK 0x3f 204 + 205 + #define AR71XX_SPI_IOC_DO BIT(0) /* Data Out pin */ 206 + #define AR71XX_SPI_IOC_CLK BIT(8) /* CLK pin */ 207 + #define AR71XX_SPI_IOC_CS(n) BIT(16 + (n)) 208 + #define AR71XX_SPI_IOC_CS0 AR71XX_SPI_IOC_CS(0) 209 + #define AR71XX_SPI_IOC_CS1 AR71XX_SPI_IOC_CS(1) 210 + #define AR71XX_SPI_IOC_CS2 AR71XX_SPI_IOC_CS(2) 211 + #define AR71XX_SPI_IOC_CS_ALL (AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1 | \ 212 + AR71XX_SPI_IOC_CS2) 213 + 214 + /* 215 + * GPIO block 216 + */ 217 + #define AR71XX_GPIO_REG_OE 0x00 218 + #define AR71XX_GPIO_REG_IN 0x04 219 + #define AR71XX_GPIO_REG_OUT 0x08 220 + #define AR71XX_GPIO_REG_SET 0x0c 221 + #define AR71XX_GPIO_REG_CLEAR 0x10 222 + #define AR71XX_GPIO_REG_INT_MODE 0x14 223 + #define AR71XX_GPIO_REG_INT_TYPE 0x18 224 + #define AR71XX_GPIO_REG_INT_POLARITY 0x1c 225 + #define AR71XX_GPIO_REG_INT_PENDING 0x20 226 + #define AR71XX_GPIO_REG_INT_ENABLE 0x24 227 + #define AR71XX_GPIO_REG_FUNC 0x28 228 + 229 + #define AR71XX_GPIO_COUNT 16 230 + #define AR724X_GPIO_COUNT 18 231 + #define AR913X_GPIO_COUNT 22 232 + 233 + #endif /* __ASM_MACH_AR71XX_REGS_H */
+96
arch/mips/include/asm/mach-ath79/ath79.h
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X common definitions 3 + * 4 + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * Parts of this file are based on Atheros' 2.6.15 BSP 8 + * 9 + * This program is free software; you can redistribute it and/or modify it 10 + * under the terms of the GNU General Public License version 2 as published 11 + * by the Free Software Foundation. 12 + */ 13 + 14 + #ifndef __ASM_MACH_ATH79_H 15 + #define __ASM_MACH_ATH79_H 16 + 17 + #include <linux/types.h> 18 + #include <linux/io.h> 19 + 20 + enum ath79_soc_type { 21 + ATH79_SOC_UNKNOWN, 22 + ATH79_SOC_AR7130, 23 + ATH79_SOC_AR7141, 24 + ATH79_SOC_AR7161, 25 + ATH79_SOC_AR7240, 26 + ATH79_SOC_AR7241, 27 + ATH79_SOC_AR7242, 28 + ATH79_SOC_AR9130, 29 + ATH79_SOC_AR9132 30 + }; 31 + 32 + extern enum ath79_soc_type ath79_soc; 33 + 34 + static inline int soc_is_ar71xx(void) 35 + { 36 + return (ath79_soc == ATH79_SOC_AR7130 || 37 + ath79_soc == ATH79_SOC_AR7141 || 38 + ath79_soc == ATH79_SOC_AR7161); 39 + } 40 + 41 + static inline int soc_is_ar724x(void) 42 + { 43 + return (ath79_soc == ATH79_SOC_AR7240 || 44 + ath79_soc == ATH79_SOC_AR7241 || 45 + ath79_soc == ATH79_SOC_AR7242); 46 + } 47 + 48 + static inline int soc_is_ar7240(void) 49 + { 50 + return (ath79_soc == ATH79_SOC_AR7240); 51 + } 52 + 53 + static inline int soc_is_ar7241(void) 54 + { 55 + return (ath79_soc == ATH79_SOC_AR7241); 56 + } 57 + 58 + static inline int soc_is_ar7242(void) 59 + { 60 + return (ath79_soc == ATH79_SOC_AR7242); 61 + } 62 + 63 + static inline int soc_is_ar913x(void) 64 + { 65 + return (ath79_soc == ATH79_SOC_AR9130 || 66 + ath79_soc == ATH79_SOC_AR9132); 67 + } 68 + 69 + extern void __iomem *ath79_ddr_base; 70 + extern void __iomem *ath79_pll_base; 71 + extern void __iomem *ath79_reset_base; 72 + 73 + static inline void ath79_pll_wr(unsigned reg, u32 val) 74 + { 75 + __raw_writel(val, ath79_pll_base + reg); 76 + } 77 + 78 + static inline u32 ath79_pll_rr(unsigned reg) 79 + { 80 + return __raw_readl(ath79_pll_base + reg); 81 + } 82 + 83 + static inline void ath79_reset_wr(unsigned reg, u32 val) 84 + { 85 + __raw_writel(val, ath79_reset_base + reg); 86 + } 87 + 88 + static inline u32 ath79_reset_rr(unsigned reg) 89 + { 90 + return __raw_readl(ath79_reset_base + reg); 91 + } 92 + 93 + void ath79_device_reset_set(u32 mask); 94 + void ath79_device_reset_clear(u32 mask); 95 + 96 + #endif /* __ASM_MACH_ATH79_H */
+23
arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
··· 1 + /* 2 + * Platform data definition for Atheros AR71XX/AR724X/AR913X SPI controller 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License version 2 as published 8 + * by the Free Software Foundation. 9 + */ 10 + 11 + #ifndef _ATH79_SPI_PLATFORM_H 12 + #define _ATH79_SPI_PLATFORM_H 13 + 14 + struct ath79_spi_platform_data { 15 + unsigned bus_num; 16 + unsigned num_chipselect; 17 + }; 18 + 19 + struct ath79_spi_controller_data { 20 + unsigned gpio; 21 + }; 22 + 23 + #endif /* _ATH79_SPI_PLATFORM_H */
+56
arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X specific CPU feature overrides 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This file was derived from: include/asm-mips/cpu-features.h 8 + * Copyright (C) 2003, 2004 Ralf Baechle 9 + * Copyright (C) 2004 Maciej W. Rozycki 10 + * 11 + * This program is free software; you can redistribute it and/or modify it 12 + * under the terms of the GNU General Public License version 2 as published 13 + * by the Free Software Foundation. 14 + * 15 + */ 16 + #ifndef __ASM_MACH_ATH79_CPU_FEATURE_OVERRIDES_H 17 + #define __ASM_MACH_ATH79_CPU_FEATURE_OVERRIDES_H 18 + 19 + #define cpu_has_tlb 1 20 + #define cpu_has_4kex 1 21 + #define cpu_has_3k_cache 0 22 + #define cpu_has_4k_cache 1 23 + #define cpu_has_tx39_cache 0 24 + #define cpu_has_sb1_cache 0 25 + #define cpu_has_fpu 0 26 + #define cpu_has_32fpr 0 27 + #define cpu_has_counter 1 28 + #define cpu_has_watch 1 29 + #define cpu_has_divec 1 30 + 31 + #define cpu_has_prefetch 1 32 + #define cpu_has_ejtag 1 33 + #define cpu_has_llsc 1 34 + 35 + #define cpu_has_mips16 1 36 + #define cpu_has_mdmx 0 37 + #define cpu_has_mips3d 0 38 + #define cpu_has_smartmips 0 39 + 40 + #define cpu_has_mips32r1 1 41 + #define cpu_has_mips32r2 1 42 + #define cpu_has_mips64r1 0 43 + #define cpu_has_mips64r2 0 44 + 45 + #define cpu_has_dsp 0 46 + #define cpu_has_mipsmt 0 47 + 48 + #define cpu_has_64bits 0 49 + #define cpu_has_64bit_zero_reg 0 50 + #define cpu_has_64bit_gp_regs 0 51 + #define cpu_has_64bit_addresses 0 52 + 53 + #define cpu_dcache_line_size() 32 54 + #define cpu_icache_line_size() 32 55 + 56 + #endif /* __ASM_MACH_ATH79_CPU_FEATURE_OVERRIDES_H */
+26
arch/mips/include/asm/mach-ath79/gpio.h
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X GPIO API definitions 3 + * 4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published 9 + * by the Free Software Foundation. 10 + * 11 + */ 12 + 13 + #ifndef __ASM_MACH_ATH79_GPIO_H 14 + #define __ASM_MACH_ATH79_GPIO_H 15 + 16 + #define ARCH_NR_GPIOS 64 17 + #include <asm-generic/gpio.h> 18 + 19 + int gpio_to_irq(unsigned gpio); 20 + int irq_to_gpio(unsigned irq); 21 + int gpio_get_value(unsigned gpio); 22 + void gpio_set_value(unsigned gpio, int value); 23 + 24 + #define gpio_cansleep __gpio_cansleep 25 + 26 + #endif /* __ASM_MACH_ATH79_GPIO_H */
+36
arch/mips/include/asm/mach-ath79/irq.h
··· 1 + /* 2 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 3 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 4 + * 5 + * This program is free software; you can redistribute it and/or modify it 6 + * under the terms of the GNU General Public License version 2 as published 7 + * by the Free Software Foundation. 8 + */ 9 + #ifndef __ASM_MACH_ATH79_IRQ_H 10 + #define __ASM_MACH_ATH79_IRQ_H 11 + 12 + #define MIPS_CPU_IRQ_BASE 0 13 + #define NR_IRQS 16 14 + 15 + #define ATH79_MISC_IRQ_BASE 8 16 + #define ATH79_MISC_IRQ_COUNT 8 17 + 18 + #define ATH79_CPU_IRQ_IP2 (MIPS_CPU_IRQ_BASE + 2) 19 + #define ATH79_CPU_IRQ_USB (MIPS_CPU_IRQ_BASE + 3) 20 + #define ATH79_CPU_IRQ_GE0 (MIPS_CPU_IRQ_BASE + 4) 21 + #define ATH79_CPU_IRQ_GE1 (MIPS_CPU_IRQ_BASE + 5) 22 + #define ATH79_CPU_IRQ_MISC (MIPS_CPU_IRQ_BASE + 6) 23 + #define ATH79_CPU_IRQ_TIMER (MIPS_CPU_IRQ_BASE + 7) 24 + 25 + #define ATH79_MISC_IRQ_TIMER (ATH79_MISC_IRQ_BASE + 0) 26 + #define ATH79_MISC_IRQ_ERROR (ATH79_MISC_IRQ_BASE + 1) 27 + #define ATH79_MISC_IRQ_GPIO (ATH79_MISC_IRQ_BASE + 2) 28 + #define ATH79_MISC_IRQ_UART (ATH79_MISC_IRQ_BASE + 3) 29 + #define ATH79_MISC_IRQ_WDOG (ATH79_MISC_IRQ_BASE + 4) 30 + #define ATH79_MISC_IRQ_PERFC (ATH79_MISC_IRQ_BASE + 5) 31 + #define ATH79_MISC_IRQ_OHCI (ATH79_MISC_IRQ_BASE + 6) 32 + #define ATH79_MISC_IRQ_DMA (ATH79_MISC_IRQ_BASE + 7) 33 + 34 + #include_next <irq.h> 35 + 36 + #endif /* __ASM_MACH_ATH79_IRQ_H */
+32
arch/mips/include/asm/mach-ath79/kernel-entry-init.h
··· 1 + /* 2 + * Atheros AR71XX/AR724X/AR913X specific kernel entry setup 3 + * 4 + * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License version 2 as published 8 + * by the Free Software Foundation. 9 + * 10 + */ 11 + #ifndef __ASM_MACH_ATH79_KERNEL_ENTRY_H 12 + #define __ASM_MACH_ATH79_KERNEL_ENTRY_H 13 + 14 + /* 15 + * Some bootloaders set the 'Kseg0 coherency algorithm' to 16 + * 'Cacheable, noncoherent, write-through, no write allocate' 17 + * and this cause performance issues. Let's go and change it to 18 + * 'Cacheable, noncoherent, write-back, write allocate' 19 + */ 20 + .macro kernel_entry_setup 21 + mfc0 t0, CP0_CONFIG 22 + li t1, ~CONF_CM_CMASK 23 + and t0, t1 24 + ori t0, CONF_CM_CACHABLE_NONCOHERENT 25 + mtc0 t0, CP0_CONFIG 26 + nop 27 + .endm 28 + 29 + .macro smp_slave_setup 30 + .endm 31 + 32 + #endif /* __ASM_MACH_ATH79_KERNEL_ENTRY_H */
+25
arch/mips/include/asm/mach-ath79/war.h
··· 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_MACH_ATH79_WAR_H 9 + #define __ASM_MACH_ATH79_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 0 18 + #define MIPS_CACHE_SYNC_WAR 0 19 + #define TX49XX_ICACHE_INDEX_INV_WAR 0 20 + #define RM9000_CDEX_SMP_WAR 0 21 + #define ICACHE_REFILLS_WORKAROUND_WAR 0 22 + #define R10000_LLSC_WAR 0 23 + #define MIPS34K_MISSED_ITLB_WAR 0 24 + 25 + #endif /* __ASM_MACH_ATH79_WAR_H */
+54
arch/mips/include/asm/mips_machine.h
··· 1 + /* 2 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published 6 + * by the Free Software Foundation. 7 + * 8 + */ 9 + 10 + #ifndef __ASM_MIPS_MACHINE_H 11 + #define __ASM_MIPS_MACHINE_H 12 + 13 + #include <linux/init.h> 14 + #include <linux/stddef.h> 15 + 16 + #include <asm/bootinfo.h> 17 + 18 + struct mips_machine { 19 + unsigned long mach_type; 20 + const char *mach_id; 21 + const char *mach_name; 22 + void (*mach_setup)(void); 23 + }; 24 + 25 + #define MIPS_MACHINE(_type, _id, _name, _setup) \ 26 + static const char machine_name_##_type[] __initconst \ 27 + __aligned(1) = _name; \ 28 + static const char machine_id_##_type[] __initconst \ 29 + __aligned(1) = _id; \ 30 + static struct mips_machine machine_##_type \ 31 + __used __section(.mips.machines.init) = \ 32 + { \ 33 + .mach_type = _type, \ 34 + .mach_id = machine_id_##_type, \ 35 + .mach_name = machine_name_##_type, \ 36 + .mach_setup = _setup, \ 37 + }; 38 + 39 + extern long __mips_machines_start; 40 + extern long __mips_machines_end; 41 + 42 + #ifdef CONFIG_MIPS_MACHINE 43 + int mips_machtype_setup(char *id) __init; 44 + void mips_machine_setup(void) __init; 45 + void mips_set_machine_name(const char *name) __init; 46 + char *mips_get_machine_name(void); 47 + #else 48 + static inline int mips_machtype_setup(char *id) { return 1; } 49 + static inline void mips_machine_setup(void) { } 50 + static inline void mips_set_machine_name(const char *name) { } 51 + static inline char *mips_get_machine_name(void) { return NULL; } 52 + #endif /* CONFIG_MIPS_MACHINE */ 53 + 54 + #endif /* __ASM_MIPS_MACHINE_H */
+1 -7
arch/mips/include/asm/mmu_context.h
··· 29 29 #define TLBMISS_HANDLER_SETUP_PGD(pgd) \ 30 30 tlbmiss_handler_setup_pgd((unsigned long)(pgd)) 31 31 32 - static inline void tlbmiss_handler_setup_pgd(unsigned long pgd) 33 - { 34 - /* Check for swapper_pg_dir and convert to physical address. */ 35 - if ((pgd & CKSEG3) == CKSEG0) 36 - pgd = CPHYSADDR(pgd); 37 - write_c0_context(pgd << 11); 38 - } 32 + extern void tlbmiss_handler_setup_pgd(unsigned long pgd); 39 33 40 34 #define TLBMISS_HANDLER_SETUP() \ 41 35 do { \
+7
arch/mips/include/asm/uasm.h
··· 115 115 Ip_u3u1u2(_xor); 116 116 Ip_u2u1u3(_xori); 117 117 Ip_u2u1msbu3(_dins); 118 + Ip_u2u1msbu3(_dinsm); 118 119 Ip_u1(_syscall); 120 + Ip_u1u2s3(_bbit0); 121 + Ip_u1u2s3(_bbit1); 122 + Ip_u3u1u2(_lwx); 123 + Ip_u3u1u2(_ldx); 119 124 120 125 /* Handle labels. */ 121 126 struct uasm_label { ··· 158 153 # define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_dsubu(buf, rs, rt, rd) 159 154 # define UASM_i_LL(buf, rs, rt, off) uasm_i_lld(buf, rs, rt, off) 160 155 # define UASM_i_SC(buf, rs, rt, off) uasm_i_scd(buf, rs, rt, off) 156 + # define UASM_i_LWX(buf, rs, rt, rd) uasm_i_ldx(buf, rs, rt, rd) 161 157 #else 162 158 # define UASM_i_LW(buf, rs, rt, off) uasm_i_lw(buf, rs, rt, off) 163 159 # define UASM_i_SW(buf, rs, rt, off) uasm_i_sw(buf, rs, rt, off) ··· 173 167 # define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_subu(buf, rs, rt, rd) 174 168 # define UASM_i_LL(buf, rs, rt, off) uasm_i_ll(buf, rs, rt, off) 175 169 # define UASM_i_SC(buf, rs, rt, off) uasm_i_sc(buf, rs, rt, off) 170 + # define UASM_i_LWX(buf, rs, rt, rd) uasm_i_lwx(buf, rs, rt, rd) 176 171 #endif 177 172 178 173 #define uasm_i_b(buf, off) uasm_i_beq(buf, 0, 0, off)
+3
arch/mips/kernel/Makefile
··· 95 95 obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o 96 96 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 97 97 obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o 98 + obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o 98 99 99 100 obj-$(CONFIG_OF) += prom.o 100 101 ··· 106 105 obj-$(CONFIG_MIPS_CPUFREQ) += cpufreq/ 107 106 108 107 obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o 108 + 109 + obj-$(CONFIG_JUMP_LABEL) += jump_label.o 109 110 110 111 CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS)
+2
arch/mips/kernel/cpu-probe.c
··· 739 739 && cpu_has_tlb) 740 740 c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40; 741 741 742 + c->kscratch_mask = (config4 >> 16) & 0xff; 743 + 742 744 return config4 & MIPS_CONF_M; 743 745 } 744 746
+54
arch/mips/kernel/jump_label.c
··· 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) 2010 Cavium Networks, Inc. 7 + */ 8 + 9 + #include <linux/jump_label.h> 10 + #include <linux/kernel.h> 11 + #include <linux/memory.h> 12 + #include <linux/mutex.h> 13 + #include <linux/types.h> 14 + #include <linux/cpu.h> 15 + 16 + #include <asm/cacheflush.h> 17 + #include <asm/inst.h> 18 + 19 + #ifdef HAVE_JUMP_LABEL 20 + 21 + #define J_RANGE_MASK ((1ul << 28) - 1) 22 + 23 + void arch_jump_label_transform(struct jump_entry *e, 24 + enum jump_label_type type) 25 + { 26 + union mips_instruction insn; 27 + union mips_instruction *insn_p = 28 + (union mips_instruction *)(unsigned long)e->code; 29 + 30 + /* Jump only works within a 256MB aligned region. */ 31 + BUG_ON((e->target & ~J_RANGE_MASK) != (e->code & ~J_RANGE_MASK)); 32 + 33 + /* Target must have 4 byte alignment. */ 34 + BUG_ON((e->target & 3) != 0); 35 + 36 + if (type == JUMP_LABEL_ENABLE) { 37 + insn.j_format.opcode = j_op; 38 + insn.j_format.target = (e->target & J_RANGE_MASK) >> 2; 39 + } else { 40 + insn.word = 0; /* nop */ 41 + } 42 + 43 + get_online_cpus(); 44 + mutex_lock(&text_mutex); 45 + *insn_p = insn; 46 + 47 + flush_icache_range((unsigned long)insn_p, 48 + (unsigned long)insn_p + sizeof(*insn_p)); 49 + 50 + mutex_unlock(&text_mutex); 51 + put_online_cpus(); 52 + } 53 + 54 + #endif /* HAVE_JUMP_LABEL */
+86
arch/mips/kernel/mips_machine.c
··· 1 + /* 2 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published 6 + * by the Free Software Foundation. 7 + * 8 + */ 9 + #include <linux/mm.h> 10 + #include <linux/string.h> 11 + #include <linux/slab.h> 12 + 13 + #include <asm/mips_machine.h> 14 + 15 + static struct mips_machine *mips_machine __initdata; 16 + static char *mips_machine_name = "Unknown"; 17 + 18 + #define for_each_machine(mach) \ 19 + for ((mach) = (struct mips_machine *)&__mips_machines_start; \ 20 + (mach) && \ 21 + (unsigned long)(mach) < (unsigned long)&__mips_machines_end; \ 22 + (mach)++) 23 + 24 + __init void mips_set_machine_name(const char *name) 25 + { 26 + char *p; 27 + 28 + if (name == NULL) 29 + return; 30 + 31 + p = kstrdup(name, GFP_KERNEL); 32 + if (!p) 33 + pr_err("MIPS: no memory for machine_name\n"); 34 + 35 + mips_machine_name = p; 36 + } 37 + 38 + char *mips_get_machine_name(void) 39 + { 40 + return mips_machine_name; 41 + } 42 + 43 + __init int mips_machtype_setup(char *id) 44 + { 45 + struct mips_machine *mach; 46 + 47 + for_each_machine(mach) { 48 + if (mach->mach_id == NULL) 49 + continue; 50 + 51 + if (strcmp(mach->mach_id, id) == 0) { 52 + mips_machtype = mach->mach_type; 53 + return 0; 54 + } 55 + } 56 + 57 + pr_err("MIPS: no machine found for id '%s', supported machines:\n", id); 58 + pr_err("%-24s %s\n", "id", "name"); 59 + for_each_machine(mach) 60 + pr_err("%-24s %s\n", mach->mach_id, mach->mach_name); 61 + 62 + return 1; 63 + } 64 + 65 + __setup("machtype=", mips_machtype_setup); 66 + 67 + __init void mips_machine_setup(void) 68 + { 69 + struct mips_machine *mach; 70 + 71 + for_each_machine(mach) { 72 + if (mips_machtype == mach->mach_type) { 73 + mips_machine = mach; 74 + break; 75 + } 76 + } 77 + 78 + if (!mips_machine) 79 + return; 80 + 81 + mips_set_machine_name(mips_machine->mach_name); 82 + pr_info("MIPS: machine is %s\n", mips_machine_name); 83 + 84 + if (mips_machine->mach_setup) 85 + mips_machine->mach_setup(); 86 + }
+5
arch/mips/kernel/module.c
··· 30 30 #include <linux/kernel.h> 31 31 #include <linux/module.h> 32 32 #include <linux/spinlock.h> 33 + #include <linux/jump_label.h> 34 + 33 35 #include <asm/pgtable.h> /* MODULE_START */ 34 36 35 37 struct mips_hi16 { ··· 383 381 { 384 382 const Elf_Shdr *s; 385 383 char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 384 + 385 + /* Make jump label nops. */ 386 + jump_label_apply_nops(me); 386 387 387 388 INIT_LIST_HEAD(&me->arch.dbe_list); 388 389 for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
+8 -1
arch/mips/kernel/proc.c
··· 12 12 #include <asm/cpu-features.h> 13 13 #include <asm/mipsregs.h> 14 14 #include <asm/processor.h> 15 + #include <asm/mips_machine.h> 15 16 16 17 unsigned int vced_count, vcei_count; 17 18 ··· 32 31 /* 33 32 * For the first processor also print the system type 34 33 */ 35 - if (n == 0) 34 + if (n == 0) { 36 35 seq_printf(m, "system type\t\t: %s\n", get_system_type()); 36 + if (mips_get_machine_name()) 37 + seq_printf(m, "machine\t\t\t: %s\n", 38 + mips_get_machine_name()); 39 + } 37 40 38 41 seq_printf(m, "processor\t\t: %ld\n", n); 39 42 sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n", ··· 74 69 ); 75 70 seq_printf(m, "shadow register sets\t: %d\n", 76 71 cpu_data[n].srsets); 72 + seq_printf(m, "kscratch registers\t: %d\n", 73 + hweight8(cpu_data[n].kscratch_mask)); 77 74 seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core); 78 75 79 76 sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
+1 -1
arch/mips/kernel/setup.c
··· 70 70 * mips_io_port_base is the begin of the address space to which x86 style 71 71 * I/O ports are mapped. 72 72 */ 73 - const unsigned long mips_io_port_base __read_mostly = -1; 73 + const unsigned long mips_io_port_base = -1; 74 74 EXPORT_SYMBOL(mips_io_port_base); 75 75 76 76 static struct resource code_resource = { .name = "Kernel code", };
+1 -1
arch/mips/kernel/traps.c
··· 1592 1592 #endif /* CONFIG_MIPS_MT_SMTC */ 1593 1593 1594 1594 cpu_data[cpu].asid_cache = ASID_FIRST_VERSION; 1595 - TLBMISS_HANDLER_SETUP(); 1596 1595 1597 1596 atomic_inc(&init_mm.mm_count); 1598 1597 current->active_mm = &init_mm; ··· 1613 1614 write_c0_wired(0); 1614 1615 } 1615 1616 #endif /* CONFIG_MIPS_MT_SMTC */ 1617 + TLBMISS_HANDLER_SETUP(); 1616 1618 } 1617 1619 1618 1620 /* Install CPU exception handler */
+7
arch/mips/kernel/vmlinux.lds.S
··· 98 98 INIT_TEXT_SECTION(PAGE_SIZE) 99 99 INIT_DATA_SECTION(16) 100 100 101 + . = ALIGN(4); 102 + .mips.machines.init : AT(ADDR(.mips.machines.init) - LOAD_OFFSET) { 103 + __mips_machines_start = .; 104 + *(.mips.machines.init) 105 + __mips_machines_end = .; 106 + } 107 + 101 108 /* .exit.text is discarded at runtime, not link time, to deal with 102 109 * references from .rodata 103 110 */
+503 -87
arch/mips/mm/tlbex.c
··· 26 26 #include <linux/smp.h> 27 27 #include <linux/string.h> 28 28 #include <linux/init.h> 29 + #include <linux/cache.h> 29 30 30 - #include <asm/mmu_context.h> 31 + #include <asm/cacheflush.h> 32 + #include <asm/pgtable.h> 31 33 #include <asm/war.h> 32 34 #include <asm/uasm.h> 33 35 ··· 65 63 return R10000_LLSC_WAR; 66 64 } 67 65 66 + static int use_bbit_insns(void) 67 + { 68 + switch (current_cpu_type()) { 69 + case CPU_CAVIUM_OCTEON: 70 + case CPU_CAVIUM_OCTEON_PLUS: 71 + case CPU_CAVIUM_OCTEON2: 72 + return 1; 73 + default: 74 + return 0; 75 + } 76 + } 77 + 78 + static int use_lwx_insns(void) 79 + { 80 + switch (current_cpu_type()) { 81 + case CPU_CAVIUM_OCTEON2: 82 + return 1; 83 + default: 84 + return 0; 85 + } 86 + } 87 + #if defined(CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE) && \ 88 + CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0 89 + static bool scratchpad_available(void) 90 + { 91 + return true; 92 + } 93 + static int scratchpad_offset(int i) 94 + { 95 + /* 96 + * CVMSEG starts at address -32768 and extends for 97 + * CAVIUM_OCTEON_CVMSEG_SIZE 128 byte cache lines. 98 + */ 99 + i += 1; /* Kernel use starts at the top and works down. */ 100 + return CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128 - (8 * i) - 32768; 101 + } 102 + #else 103 + static bool scratchpad_available(void) 104 + { 105 + return false; 106 + } 107 + static int scratchpad_offset(int i) 108 + { 109 + BUG(); 110 + } 111 + #endif 68 112 /* 69 113 * Found by experiment: At least some revisions of the 4kc throw under 70 114 * some circumstances a machine check exception, triggered by invalid ··· 221 173 static int check_for_high_segbits __cpuinitdata; 222 174 #endif 223 175 176 + static int check_for_high_segbits __cpuinitdata; 177 + 178 + static unsigned int kscratch_used_mask __cpuinitdata; 179 + 180 + static int __cpuinit allocate_kscratch(void) 181 + { 182 + int r; 183 + unsigned int a = cpu_data[0].kscratch_mask & ~kscratch_used_mask; 184 + 185 + r = ffs(a); 186 + 187 + if (r == 0) 188 + return -1; 189 + 190 + r--; /* make it zero based */ 191 + 192 + kscratch_used_mask |= (1 << r); 193 + 194 + return r; 195 + } 196 + 197 + static int scratch_reg __cpuinitdata; 198 + static int pgd_reg __cpuinitdata; 199 + enum vmalloc64_mode {not_refill, refill_scratch, refill_noscratch}; 200 + 224 201 #ifndef CONFIG_MIPS_PGD_C0_CONTEXT 202 + 225 203 /* 226 204 * CONFIG_MIPS_PGD_C0_CONTEXT implies 64 bit and lack of pgd_current, 227 205 * we cannot do r3000 under these circumstances. 206 + * 207 + * Declare pgd_current here instead of including mmu_context.h to avoid type 208 + * conflicts for tlbmiss_handler_setup_pgd 228 209 */ 210 + extern unsigned long pgd_current[]; 229 211 230 212 /* 231 213 * The R3000 TLB handler is simple. ··· 518 440 static __cpuinit void build_restore_pagemask(u32 **p, 519 441 struct uasm_reloc **r, 520 442 unsigned int tmp, 521 - enum label_id lid) 443 + enum label_id lid, 444 + int restore_scratch) 522 445 { 523 - /* Reset default page size */ 524 - if (PM_DEFAULT_MASK >> 16) { 525 - uasm_i_lui(p, tmp, PM_DEFAULT_MASK >> 16); 526 - uasm_i_ori(p, tmp, tmp, PM_DEFAULT_MASK & 0xffff); 527 - uasm_il_b(p, r, lid); 528 - uasm_i_mtc0(p, tmp, C0_PAGEMASK); 529 - } else if (PM_DEFAULT_MASK) { 530 - uasm_i_ori(p, tmp, 0, PM_DEFAULT_MASK); 531 - uasm_il_b(p, r, lid); 532 - uasm_i_mtc0(p, tmp, C0_PAGEMASK); 446 + if (restore_scratch) { 447 + /* Reset default page size */ 448 + if (PM_DEFAULT_MASK >> 16) { 449 + uasm_i_lui(p, tmp, PM_DEFAULT_MASK >> 16); 450 + uasm_i_ori(p, tmp, tmp, PM_DEFAULT_MASK & 0xffff); 451 + uasm_i_mtc0(p, tmp, C0_PAGEMASK); 452 + uasm_il_b(p, r, lid); 453 + } else if (PM_DEFAULT_MASK) { 454 + uasm_i_ori(p, tmp, 0, PM_DEFAULT_MASK); 455 + uasm_i_mtc0(p, tmp, C0_PAGEMASK); 456 + uasm_il_b(p, r, lid); 457 + } else { 458 + uasm_i_mtc0(p, 0, C0_PAGEMASK); 459 + uasm_il_b(p, r, lid); 460 + } 461 + if (scratch_reg > 0) 462 + UASM_i_MFC0(p, 1, 31, scratch_reg); 463 + else 464 + UASM_i_LW(p, 1, scratchpad_offset(0), 0); 533 465 } else { 534 - uasm_il_b(p, r, lid); 535 - uasm_i_mtc0(p, 0, C0_PAGEMASK); 466 + /* Reset default page size */ 467 + if (PM_DEFAULT_MASK >> 16) { 468 + uasm_i_lui(p, tmp, PM_DEFAULT_MASK >> 16); 469 + uasm_i_ori(p, tmp, tmp, PM_DEFAULT_MASK & 0xffff); 470 + uasm_il_b(p, r, lid); 471 + uasm_i_mtc0(p, tmp, C0_PAGEMASK); 472 + } else if (PM_DEFAULT_MASK) { 473 + uasm_i_ori(p, tmp, 0, PM_DEFAULT_MASK); 474 + uasm_il_b(p, r, lid); 475 + uasm_i_mtc0(p, tmp, C0_PAGEMASK); 476 + } else { 477 + uasm_il_b(p, r, lid); 478 + uasm_i_mtc0(p, 0, C0_PAGEMASK); 479 + } 536 480 } 537 481 } 538 482 ··· 562 462 struct uasm_label **l, 563 463 struct uasm_reloc **r, 564 464 unsigned int tmp, 565 - enum tlb_write_entry wmode) 465 + enum tlb_write_entry wmode, 466 + int restore_scratch) 566 467 { 567 468 /* Set huge page tlb entry size */ 568 469 uasm_i_lui(p, tmp, PM_HUGE_MASK >> 16); ··· 572 471 573 472 build_tlb_write_entry(p, l, r, wmode); 574 473 575 - build_restore_pagemask(p, r, tmp, label_leave); 474 + build_restore_pagemask(p, r, tmp, label_leave, restore_scratch); 576 475 } 577 476 578 477 /* ··· 583 482 unsigned int pmd, int lid) 584 483 { 585 484 UASM_i_LW(p, tmp, 0, pmd); 586 - uasm_i_andi(p, tmp, tmp, _PAGE_HUGE); 587 - uasm_il_bnez(p, r, tmp, lid); 485 + if (use_bbit_insns()) { 486 + uasm_il_bbit1(p, r, tmp, ilog2(_PAGE_HUGE), lid); 487 + } else { 488 + uasm_i_andi(p, tmp, tmp, _PAGE_HUGE); 489 + uasm_il_bnez(p, r, tmp, lid); 490 + } 588 491 } 589 492 590 493 static __cpuinit void build_huge_update_entries(u32 **p, ··· 637 532 UASM_i_SW(p, pte, 0, ptr); 638 533 #endif 639 534 build_huge_update_entries(p, pte, ptr); 640 - build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed); 535 + build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed, 0); 641 536 } 642 537 #endif /* CONFIG_HUGETLB_PAGE */ 643 538 ··· 678 573 /* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */ 679 574 680 575 #ifdef CONFIG_MIPS_PGD_C0_CONTEXT 681 - /* 682 - * &pgd << 11 stored in CONTEXT [23..63]. 683 - */ 684 - UASM_i_MFC0(p, ptr, C0_CONTEXT); 685 - uasm_i_dins(p, ptr, 0, 0, 23); /* Clear lower 23 bits of context. */ 686 - uasm_i_ori(p, ptr, ptr, 0x540); /* 1 0 1 0 1 << 6 xkphys cached */ 687 - uasm_i_drotr(p, ptr, ptr, 11); 576 + if (pgd_reg != -1) { 577 + /* pgd is in pgd_reg */ 578 + UASM_i_MFC0(p, ptr, 31, pgd_reg); 579 + } else { 580 + /* 581 + * &pgd << 11 stored in CONTEXT [23..63]. 582 + */ 583 + UASM_i_MFC0(p, ptr, C0_CONTEXT); 584 + 585 + /* Clear lower 23 bits of context. */ 586 + uasm_i_dins(p, ptr, 0, 0, 23); 587 + 588 + /* 1 0 1 0 1 << 6 xkphys cached */ 589 + uasm_i_ori(p, ptr, ptr, 0x540); 590 + uasm_i_drotr(p, ptr, ptr, 11); 591 + } 688 592 #elif defined(CONFIG_SMP) 689 593 # ifdef CONFIG_MIPS_MT_SMTC 690 594 /* ··· 734 620 #endif 735 621 } 736 622 737 - enum vmalloc64_mode {not_refill, refill}; 738 623 /* 739 624 * BVADDR is the faulting address, PTR is scratch. 740 625 * PTR will hold the pgd for vmalloc. ··· 751 638 752 639 uasm_l_vmalloc(l, *p); 753 640 754 - if (mode == refill && check_for_high_segbits) { 641 + if (mode != not_refill && check_for_high_segbits) { 755 642 if (single_insn_swpd) { 756 643 uasm_il_bltz(p, r, bvaddr, label_vmalloc_done); 757 644 uasm_i_lui(p, ptr, uasm_rel_hi(swpd)); ··· 774 661 uasm_i_daddiu(p, ptr, ptr, uasm_rel_lo(swpd)); 775 662 } 776 663 } 777 - if (mode == refill && check_for_high_segbits) { 664 + if (mode != not_refill && check_for_high_segbits) { 778 665 uasm_l_large_segbits_fault(l, *p); 779 666 /* 780 667 * We get here if we are an xsseg address, or if we are ··· 790 677 */ 791 678 UASM_i_LA(p, ptr, (unsigned long)tlb_do_page_fault_0); 792 679 uasm_i_jr(p, ptr); 793 - uasm_i_nop(p); 680 + 681 + if (mode == refill_scratch) { 682 + if (scratch_reg > 0) 683 + UASM_i_MFC0(p, 1, 31, scratch_reg); 684 + else 685 + UASM_i_LW(p, 1, scratchpad_offset(0), 0); 686 + } else { 687 + uasm_i_nop(p); 688 + } 794 689 } 795 690 } 796 691 ··· 955 834 #endif 956 835 } 957 836 837 + struct mips_huge_tlb_info { 838 + int huge_pte; 839 + int restore_scratch; 840 + }; 841 + 842 + static struct mips_huge_tlb_info __cpuinit 843 + build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, 844 + struct uasm_reloc **r, unsigned int tmp, 845 + unsigned int ptr, int c0_scratch) 846 + { 847 + struct mips_huge_tlb_info rv; 848 + unsigned int even, odd; 849 + int vmalloc_branch_delay_filled = 0; 850 + const int scratch = 1; /* Our extra working register */ 851 + 852 + rv.huge_pte = scratch; 853 + rv.restore_scratch = 0; 854 + 855 + if (check_for_high_segbits) { 856 + UASM_i_MFC0(p, tmp, C0_BADVADDR); 857 + 858 + if (pgd_reg != -1) 859 + UASM_i_MFC0(p, ptr, 31, pgd_reg); 860 + else 861 + UASM_i_MFC0(p, ptr, C0_CONTEXT); 862 + 863 + if (c0_scratch >= 0) 864 + UASM_i_MTC0(p, scratch, 31, c0_scratch); 865 + else 866 + UASM_i_SW(p, scratch, scratchpad_offset(0), 0); 867 + 868 + uasm_i_dsrl_safe(p, scratch, tmp, 869 + PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3); 870 + uasm_il_bnez(p, r, scratch, label_vmalloc); 871 + 872 + if (pgd_reg == -1) { 873 + vmalloc_branch_delay_filled = 1; 874 + /* Clear lower 23 bits of context. */ 875 + uasm_i_dins(p, ptr, 0, 0, 23); 876 + } 877 + } else { 878 + if (pgd_reg != -1) 879 + UASM_i_MFC0(p, ptr, 31, pgd_reg); 880 + else 881 + UASM_i_MFC0(p, ptr, C0_CONTEXT); 882 + 883 + UASM_i_MFC0(p, tmp, C0_BADVADDR); 884 + 885 + if (c0_scratch >= 0) 886 + UASM_i_MTC0(p, scratch, 31, c0_scratch); 887 + else 888 + UASM_i_SW(p, scratch, scratchpad_offset(0), 0); 889 + 890 + if (pgd_reg == -1) 891 + /* Clear lower 23 bits of context. */ 892 + uasm_i_dins(p, ptr, 0, 0, 23); 893 + 894 + uasm_il_bltz(p, r, tmp, label_vmalloc); 895 + } 896 + 897 + if (pgd_reg == -1) { 898 + vmalloc_branch_delay_filled = 1; 899 + /* 1 0 1 0 1 << 6 xkphys cached */ 900 + uasm_i_ori(p, ptr, ptr, 0x540); 901 + uasm_i_drotr(p, ptr, ptr, 11); 902 + } 903 + 904 + #ifdef __PAGETABLE_PMD_FOLDED 905 + #define LOC_PTEP scratch 906 + #else 907 + #define LOC_PTEP ptr 908 + #endif 909 + 910 + if (!vmalloc_branch_delay_filled) 911 + /* get pgd offset in bytes */ 912 + uasm_i_dsrl_safe(p, scratch, tmp, PGDIR_SHIFT - 3); 913 + 914 + uasm_l_vmalloc_done(l, *p); 915 + 916 + /* 917 + * tmp ptr 918 + * fall-through case = badvaddr *pgd_current 919 + * vmalloc case = badvaddr swapper_pg_dir 920 + */ 921 + 922 + if (vmalloc_branch_delay_filled) 923 + /* get pgd offset in bytes */ 924 + uasm_i_dsrl_safe(p, scratch, tmp, PGDIR_SHIFT - 3); 925 + 926 + #ifdef __PAGETABLE_PMD_FOLDED 927 + GET_CONTEXT(p, tmp); /* get context reg */ 928 + #endif 929 + uasm_i_andi(p, scratch, scratch, (PTRS_PER_PGD - 1) << 3); 930 + 931 + if (use_lwx_insns()) { 932 + UASM_i_LWX(p, LOC_PTEP, scratch, ptr); 933 + } else { 934 + uasm_i_daddu(p, ptr, ptr, scratch); /* add in pgd offset */ 935 + uasm_i_ld(p, LOC_PTEP, 0, ptr); /* get pmd pointer */ 936 + } 937 + 938 + #ifndef __PAGETABLE_PMD_FOLDED 939 + /* get pmd offset in bytes */ 940 + uasm_i_dsrl_safe(p, scratch, tmp, PMD_SHIFT - 3); 941 + uasm_i_andi(p, scratch, scratch, (PTRS_PER_PMD - 1) << 3); 942 + GET_CONTEXT(p, tmp); /* get context reg */ 943 + 944 + if (use_lwx_insns()) { 945 + UASM_i_LWX(p, scratch, scratch, ptr); 946 + } else { 947 + uasm_i_daddu(p, ptr, ptr, scratch); /* add in pmd offset */ 948 + UASM_i_LW(p, scratch, 0, ptr); 949 + } 950 + #endif 951 + /* Adjust the context during the load latency. */ 952 + build_adjust_context(p, tmp); 953 + 954 + #ifdef CONFIG_HUGETLB_PAGE 955 + uasm_il_bbit1(p, r, scratch, ilog2(_PAGE_HUGE), label_tlb_huge_update); 956 + /* 957 + * The in the LWX case we don't want to do the load in the 958 + * delay slot. It cannot issue in the same cycle and may be 959 + * speculative and unneeded. 960 + */ 961 + if (use_lwx_insns()) 962 + uasm_i_nop(p); 963 + #endif /* CONFIG_HUGETLB_PAGE */ 964 + 965 + 966 + /* build_update_entries */ 967 + if (use_lwx_insns()) { 968 + even = ptr; 969 + odd = tmp; 970 + UASM_i_LWX(p, even, scratch, tmp); 971 + UASM_i_ADDIU(p, tmp, tmp, sizeof(pte_t)); 972 + UASM_i_LWX(p, odd, scratch, tmp); 973 + } else { 974 + UASM_i_ADDU(p, ptr, scratch, tmp); /* add in offset */ 975 + even = tmp; 976 + odd = ptr; 977 + UASM_i_LW(p, even, 0, ptr); /* get even pte */ 978 + UASM_i_LW(p, odd, sizeof(pte_t), ptr); /* get odd pte */ 979 + } 980 + if (kernel_uses_smartmips_rixi) { 981 + uasm_i_dsrl_safe(p, even, even, ilog2(_PAGE_NO_EXEC)); 982 + uasm_i_dsrl_safe(p, odd, odd, ilog2(_PAGE_NO_EXEC)); 983 + uasm_i_drotr(p, even, even, 984 + ilog2(_PAGE_GLOBAL) - ilog2(_PAGE_NO_EXEC)); 985 + UASM_i_MTC0(p, even, C0_ENTRYLO0); /* load it */ 986 + uasm_i_drotr(p, odd, odd, 987 + ilog2(_PAGE_GLOBAL) - ilog2(_PAGE_NO_EXEC)); 988 + } else { 989 + uasm_i_dsrl_safe(p, even, even, ilog2(_PAGE_GLOBAL)); 990 + UASM_i_MTC0(p, even, C0_ENTRYLO0); /* load it */ 991 + uasm_i_dsrl_safe(p, odd, odd, ilog2(_PAGE_GLOBAL)); 992 + } 993 + UASM_i_MTC0(p, odd, C0_ENTRYLO1); /* load it */ 994 + 995 + if (c0_scratch >= 0) { 996 + UASM_i_MFC0(p, scratch, 31, c0_scratch); 997 + build_tlb_write_entry(p, l, r, tlb_random); 998 + uasm_l_leave(l, *p); 999 + rv.restore_scratch = 1; 1000 + } else if (PAGE_SHIFT == 14 || PAGE_SHIFT == 13) { 1001 + build_tlb_write_entry(p, l, r, tlb_random); 1002 + uasm_l_leave(l, *p); 1003 + UASM_i_LW(p, scratch, scratchpad_offset(0), 0); 1004 + } else { 1005 + UASM_i_LW(p, scratch, scratchpad_offset(0), 0); 1006 + build_tlb_write_entry(p, l, r, tlb_random); 1007 + uasm_l_leave(l, *p); 1008 + rv.restore_scratch = 1; 1009 + } 1010 + 1011 + uasm_i_eret(p); /* return from trap */ 1012 + 1013 + return rv; 1014 + } 1015 + 958 1016 /* 959 1017 * For a 64-bit kernel, we are using the 64-bit XTLB refill exception 960 1018 * because EXL == 0. If we wrap, we can also use the 32 instruction ··· 1149 849 struct uasm_reloc *r = relocs; 1150 850 u32 *f; 1151 851 unsigned int final_len; 852 + struct mips_huge_tlb_info htlb_info; 853 + enum vmalloc64_mode vmalloc_mode; 1152 854 1153 855 memset(tlb_handler, 0, sizeof(tlb_handler)); 1154 856 memset(labels, 0, sizeof(labels)); 1155 857 memset(relocs, 0, sizeof(relocs)); 1156 858 memset(final_handler, 0, sizeof(final_handler)); 1157 859 1158 - /* 1159 - * create the plain linear handler 1160 - */ 1161 - if (bcm1250_m3_war()) { 1162 - unsigned int segbits = 44; 860 + if (scratch_reg == 0) 861 + scratch_reg = allocate_kscratch(); 1163 862 1164 - uasm_i_dmfc0(&p, K0, C0_BADVADDR); 1165 - uasm_i_dmfc0(&p, K1, C0_ENTRYHI); 1166 - uasm_i_xor(&p, K0, K0, K1); 1167 - uasm_i_dsrl_safe(&p, K1, K0, 62); 1168 - uasm_i_dsrl_safe(&p, K0, K0, 12 + 1); 1169 - uasm_i_dsll_safe(&p, K0, K0, 64 + 12 + 1 - segbits); 1170 - uasm_i_or(&p, K0, K0, K1); 1171 - uasm_il_bnez(&p, &r, K0, label_leave); 1172 - /* No need for uasm_i_nop */ 1173 - } 863 + if ((scratch_reg > 0 || scratchpad_available()) && use_bbit_insns()) { 864 + htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1, 865 + scratch_reg); 866 + vmalloc_mode = refill_scratch; 867 + } else { 868 + htlb_info.huge_pte = K0; 869 + htlb_info.restore_scratch = 0; 870 + vmalloc_mode = refill_noscratch; 871 + /* 872 + * create the plain linear handler 873 + */ 874 + if (bcm1250_m3_war()) { 875 + unsigned int segbits = 44; 876 + 877 + uasm_i_dmfc0(&p, K0, C0_BADVADDR); 878 + uasm_i_dmfc0(&p, K1, C0_ENTRYHI); 879 + uasm_i_xor(&p, K0, K0, K1); 880 + uasm_i_dsrl_safe(&p, K1, K0, 62); 881 + uasm_i_dsrl_safe(&p, K0, K0, 12 + 1); 882 + uasm_i_dsll_safe(&p, K0, K0, 64 + 12 + 1 - segbits); 883 + uasm_i_or(&p, K0, K0, K1); 884 + uasm_il_bnez(&p, &r, K0, label_leave); 885 + /* No need for uasm_i_nop */ 886 + } 1174 887 1175 888 #ifdef CONFIG_64BIT 1176 - build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */ 889 + build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */ 1177 890 #else 1178 - build_get_pgde32(&p, K0, K1); /* get pgd in K1 */ 891 + build_get_pgde32(&p, K0, K1); /* get pgd in K1 */ 1179 892 #endif 1180 893 1181 894 #ifdef CONFIG_HUGETLB_PAGE 1182 - build_is_huge_pte(&p, &r, K0, K1, label_tlb_huge_update); 895 + build_is_huge_pte(&p, &r, K0, K1, label_tlb_huge_update); 1183 896 #endif 1184 897 1185 - build_get_ptep(&p, K0, K1); 1186 - build_update_entries(&p, K0, K1); 1187 - build_tlb_write_entry(&p, &l, &r, tlb_random); 1188 - uasm_l_leave(&l, p); 1189 - uasm_i_eret(&p); /* return from trap */ 1190 - 898 + build_get_ptep(&p, K0, K1); 899 + build_update_entries(&p, K0, K1); 900 + build_tlb_write_entry(&p, &l, &r, tlb_random); 901 + uasm_l_leave(&l, p); 902 + uasm_i_eret(&p); /* return from trap */ 903 + } 1191 904 #ifdef CONFIG_HUGETLB_PAGE 1192 905 uasm_l_tlb_huge_update(&l, p); 1193 - UASM_i_LW(&p, K0, 0, K1); 1194 - build_huge_update_entries(&p, K0, K1); 1195 - build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random); 906 + build_huge_update_entries(&p, htlb_info.huge_pte, K1); 907 + build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random, 908 + htlb_info.restore_scratch); 1196 909 #endif 1197 910 1198 911 #ifdef CONFIG_64BIT 1199 - build_get_pgd_vmalloc64(&p, &l, &r, K0, K1, refill); 912 + build_get_pgd_vmalloc64(&p, &l, &r, K0, K1, vmalloc_mode); 1200 913 #endif 1201 914 1202 915 /* ··· 1327 1014 u32 handle_tlbl[FASTPATH_SIZE] __cacheline_aligned; 1328 1015 u32 handle_tlbs[FASTPATH_SIZE] __cacheline_aligned; 1329 1016 u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned; 1017 + #ifdef CONFIG_MIPS_PGD_C0_CONTEXT 1018 + u32 tlbmiss_handler_setup_pgd[16] __cacheline_aligned; 1019 + 1020 + static void __cpuinit build_r4000_setup_pgd(void) 1021 + { 1022 + const int a0 = 4; 1023 + const int a1 = 5; 1024 + u32 *p = tlbmiss_handler_setup_pgd; 1025 + struct uasm_label *l = labels; 1026 + struct uasm_reloc *r = relocs; 1027 + 1028 + memset(tlbmiss_handler_setup_pgd, 0, sizeof(tlbmiss_handler_setup_pgd)); 1029 + memset(labels, 0, sizeof(labels)); 1030 + memset(relocs, 0, sizeof(relocs)); 1031 + 1032 + pgd_reg = allocate_kscratch(); 1033 + 1034 + if (pgd_reg == -1) { 1035 + /* PGD << 11 in c0_Context */ 1036 + /* 1037 + * If it is a ckseg0 address, convert to a physical 1038 + * address. Shifting right by 29 and adding 4 will 1039 + * result in zero for these addresses. 1040 + * 1041 + */ 1042 + UASM_i_SRA(&p, a1, a0, 29); 1043 + UASM_i_ADDIU(&p, a1, a1, 4); 1044 + uasm_il_bnez(&p, &r, a1, label_tlbl_goaround1); 1045 + uasm_i_nop(&p); 1046 + uasm_i_dinsm(&p, a0, 0, 29, 64 - 29); 1047 + uasm_l_tlbl_goaround1(&l, p); 1048 + UASM_i_SLL(&p, a0, a0, 11); 1049 + uasm_i_jr(&p, 31); 1050 + UASM_i_MTC0(&p, a0, C0_CONTEXT); 1051 + } else { 1052 + /* PGD in c0_KScratch */ 1053 + uasm_i_jr(&p, 31); 1054 + UASM_i_MTC0(&p, a0, 31, pgd_reg); 1055 + } 1056 + if (p - tlbmiss_handler_setup_pgd > ARRAY_SIZE(tlbmiss_handler_setup_pgd)) 1057 + panic("tlbmiss_handler_setup_pgd space exceeded"); 1058 + uasm_resolve_relocs(relocs, labels); 1059 + pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n", 1060 + (unsigned int)(p - tlbmiss_handler_setup_pgd)); 1061 + 1062 + dump_handler(tlbmiss_handler_setup_pgd, 1063 + ARRAY_SIZE(tlbmiss_handler_setup_pgd)); 1064 + } 1065 + #endif 1330 1066 1331 1067 static void __cpuinit 1332 1068 iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr) ··· 1462 1100 unsigned int pte, unsigned int ptr, enum label_id lid) 1463 1101 { 1464 1102 if (kernel_uses_smartmips_rixi) { 1465 - uasm_i_andi(p, pte, pte, _PAGE_PRESENT); 1466 - uasm_il_beqz(p, r, pte, lid); 1103 + if (use_bbit_insns()) { 1104 + uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid); 1105 + uasm_i_nop(p); 1106 + } else { 1107 + uasm_i_andi(p, pte, pte, _PAGE_PRESENT); 1108 + uasm_il_beqz(p, r, pte, lid); 1109 + iPTE_LW(p, pte, ptr); 1110 + } 1467 1111 } else { 1468 1112 uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ); 1469 1113 uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ); 1470 1114 uasm_il_bnez(p, r, pte, lid); 1115 + iPTE_LW(p, pte, ptr); 1471 1116 } 1472 - iPTE_LW(p, pte, ptr); 1473 1117 } 1474 1118 1475 1119 /* Make PTE valid, store result in PTR. */ ··· 1496 1128 build_pte_writable(u32 **p, struct uasm_reloc **r, 1497 1129 unsigned int pte, unsigned int ptr, enum label_id lid) 1498 1130 { 1499 - uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE); 1500 - uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE); 1501 - uasm_il_bnez(p, r, pte, lid); 1502 - iPTE_LW(p, pte, ptr); 1131 + if (use_bbit_insns()) { 1132 + uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid); 1133 + uasm_i_nop(p); 1134 + uasm_il_bbit0(p, r, pte, ilog2(_PAGE_WRITE), lid); 1135 + uasm_i_nop(p); 1136 + } else { 1137 + uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE); 1138 + uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE); 1139 + uasm_il_bnez(p, r, pte, lid); 1140 + iPTE_LW(p, pte, ptr); 1141 + } 1503 1142 } 1504 1143 1505 1144 /* Make PTE writable, update software status bits as well, then store ··· 1530 1155 build_pte_modifiable(u32 **p, struct uasm_reloc **r, 1531 1156 unsigned int pte, unsigned int ptr, enum label_id lid) 1532 1157 { 1533 - uasm_i_andi(p, pte, pte, _PAGE_WRITE); 1534 - uasm_il_beqz(p, r, pte, lid); 1535 - iPTE_LW(p, pte, ptr); 1158 + if (use_bbit_insns()) { 1159 + uasm_il_bbit0(p, r, pte, ilog2(_PAGE_WRITE), lid); 1160 + uasm_i_nop(p); 1161 + } else { 1162 + uasm_i_andi(p, pte, pte, _PAGE_WRITE); 1163 + uasm_il_beqz(p, r, pte, lid); 1164 + iPTE_LW(p, pte, ptr); 1165 + } 1536 1166 } 1537 1167 1538 1168 #ifndef CONFIG_MIPS_PGD_C0_CONTEXT 1169 + 1170 + 1539 1171 /* 1540 1172 * R3000 style TLB load/store/modify handlers. 1541 1173 */ ··· 1784 1402 * If the page is not _PAGE_VALID, RI or XI could not 1785 1403 * have triggered it. Skip the expensive test.. 1786 1404 */ 1787 - uasm_i_andi(&p, K0, K0, _PAGE_VALID); 1788 - uasm_il_beqz(&p, &r, K0, label_tlbl_goaround1); 1405 + if (use_bbit_insns()) { 1406 + uasm_il_bbit0(&p, &r, K0, ilog2(_PAGE_VALID), 1407 + label_tlbl_goaround1); 1408 + } else { 1409 + uasm_i_andi(&p, K0, K0, _PAGE_VALID); 1410 + uasm_il_beqz(&p, &r, K0, label_tlbl_goaround1); 1411 + } 1789 1412 uasm_i_nop(&p); 1790 1413 1791 1414 uasm_i_tlbr(&p); 1792 1415 /* Examine entrylo 0 or 1 based on ptr. */ 1793 - uasm_i_andi(&p, K0, K1, sizeof(pte_t)); 1794 - uasm_i_beqz(&p, K0, 8); 1416 + if (use_bbit_insns()) { 1417 + uasm_i_bbit0(&p, K1, ilog2(sizeof(pte_t)), 8); 1418 + } else { 1419 + uasm_i_andi(&p, K0, K1, sizeof(pte_t)); 1420 + uasm_i_beqz(&p, K0, 8); 1421 + } 1795 1422 1796 1423 UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/ 1797 1424 UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */ ··· 1808 1417 * If the entryLo (now in K0) is valid (bit 1), RI or 1809 1418 * XI must have triggered it. 1810 1419 */ 1811 - uasm_i_andi(&p, K0, K0, 2); 1812 - uasm_il_bnez(&p, &r, K0, label_nopage_tlbl); 1813 - 1814 - uasm_l_tlbl_goaround1(&l, p); 1815 - /* Reload the PTE value */ 1816 - iPTE_LW(&p, K0, K1); 1420 + if (use_bbit_insns()) { 1421 + uasm_il_bbit1(&p, &r, K0, 1, label_nopage_tlbl); 1422 + /* Reload the PTE value */ 1423 + iPTE_LW(&p, K0, K1); 1424 + uasm_l_tlbl_goaround1(&l, p); 1425 + } else { 1426 + uasm_i_andi(&p, K0, K0, 2); 1427 + uasm_il_bnez(&p, &r, K0, label_nopage_tlbl); 1428 + uasm_l_tlbl_goaround1(&l, p); 1429 + /* Reload the PTE value */ 1430 + iPTE_LW(&p, K0, K1); 1431 + } 1817 1432 } 1818 1433 build_make_valid(&p, &r, K0, K1); 1819 1434 build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); ··· 1839 1442 * If the page is not _PAGE_VALID, RI or XI could not 1840 1443 * have triggered it. Skip the expensive test.. 1841 1444 */ 1842 - uasm_i_andi(&p, K0, K0, _PAGE_VALID); 1843 - uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2); 1445 + if (use_bbit_insns()) { 1446 + uasm_il_bbit0(&p, &r, K0, ilog2(_PAGE_VALID), 1447 + label_tlbl_goaround2); 1448 + } else { 1449 + uasm_i_andi(&p, K0, K0, _PAGE_VALID); 1450 + uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2); 1451 + } 1844 1452 uasm_i_nop(&p); 1845 1453 1846 1454 uasm_i_tlbr(&p); 1847 1455 /* Examine entrylo 0 or 1 based on ptr. */ 1848 - uasm_i_andi(&p, K0, K1, sizeof(pte_t)); 1849 - uasm_i_beqz(&p, K0, 8); 1850 - 1456 + if (use_bbit_insns()) { 1457 + uasm_i_bbit0(&p, K1, ilog2(sizeof(pte_t)), 8); 1458 + } else { 1459 + uasm_i_andi(&p, K0, K1, sizeof(pte_t)); 1460 + uasm_i_beqz(&p, K0, 8); 1461 + } 1851 1462 UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/ 1852 1463 UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */ 1853 1464 /* 1854 1465 * If the entryLo (now in K0) is valid (bit 1), RI or 1855 1466 * XI must have triggered it. 1856 1467 */ 1857 - uasm_i_andi(&p, K0, K0, 2); 1858 - uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2); 1468 + if (use_bbit_insns()) { 1469 + uasm_il_bbit0(&p, &r, K0, 1, label_tlbl_goaround2); 1470 + } else { 1471 + uasm_i_andi(&p, K0, K0, 2); 1472 + uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2); 1473 + } 1859 1474 /* Reload the PTE value */ 1860 1475 iPTE_LW(&p, K0, K1); 1861 1476 ··· 1875 1466 * We clobbered C0_PAGEMASK, restore it. On the other branch 1876 1467 * it is restored in build_huge_tlb_write_entry. 1877 1468 */ 1878 - build_restore_pagemask(&p, &r, K0, label_nopage_tlbl); 1469 + build_restore_pagemask(&p, &r, K0, label_nopage_tlbl, 0); 1879 1470 1880 1471 uasm_l_tlbl_goaround2(&l, p); 1881 1472 } ··· 2032 1623 break; 2033 1624 2034 1625 default: 2035 - build_r4000_tlb_refill_handler(); 2036 1626 if (!run_once) { 1627 + #ifdef CONFIG_MIPS_PGD_C0_CONTEXT 1628 + build_r4000_setup_pgd(); 1629 + #endif 2037 1630 build_r4000_tlb_load_handler(); 2038 1631 build_r4000_tlb_store_handler(); 2039 1632 build_r4000_tlb_modify_handler(); 2040 1633 run_once++; 2041 1634 } 1635 + build_r4000_tlb_refill_handler(); 2042 1636 } 2043 1637 } 2044 1638 ··· 2053 1641 (unsigned long)handle_tlbs + sizeof(handle_tlbs)); 2054 1642 local_flush_icache_range((unsigned long)handle_tlbm, 2055 1643 (unsigned long)handle_tlbm + sizeof(handle_tlbm)); 1644 + #ifdef CONFIG_MIPS_PGD_C0_CONTEXT 1645 + local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd, 1646 + (unsigned long)tlbmiss_handler_setup_pgd + sizeof(handle_tlbm)); 1647 + #endif 2056 1648 }
+31 -25
arch/mips/mm/uasm.c
··· 68 68 insn_pref, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, 69 69 insn_sra, insn_srl, insn_rotr, insn_subu, insn_sw, insn_tlbp, 70 70 insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, 71 - insn_dins, insn_syscall, insn_bbit0, insn_bbit1 71 + insn_dins, insn_dinsm, insn_syscall, insn_bbit0, insn_bbit1, 72 + insn_lwx, insn_ldx 72 73 }; 73 74 74 75 struct insn { ··· 143 142 { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD }, 144 143 { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, 145 144 { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE }, 145 + { insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE }, 146 146 { insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM}, 147 147 { insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, 148 148 { insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, 149 + { insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD }, 150 + { insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD }, 149 151 { insn_invalid, 0, 0 } 150 152 }; 151 153 ··· 156 152 157 153 static inline __uasminit u32 build_rs(u32 arg) 158 154 { 159 - if (arg & ~RS_MASK) 160 - printk(KERN_WARNING "Micro-assembler field overflow\n"); 155 + WARN(arg & ~RS_MASK, KERN_WARNING "Micro-assembler field overflow\n"); 161 156 162 157 return (arg & RS_MASK) << RS_SH; 163 158 } 164 159 165 160 static inline __uasminit u32 build_rt(u32 arg) 166 161 { 167 - if (arg & ~RT_MASK) 168 - printk(KERN_WARNING "Micro-assembler field overflow\n"); 162 + WARN(arg & ~RT_MASK, KERN_WARNING "Micro-assembler field overflow\n"); 169 163 170 164 return (arg & RT_MASK) << RT_SH; 171 165 } 172 166 173 167 static inline __uasminit u32 build_rd(u32 arg) 174 168 { 175 - if (arg & ~RD_MASK) 176 - printk(KERN_WARNING "Micro-assembler field overflow\n"); 169 + WARN(arg & ~RD_MASK, KERN_WARNING "Micro-assembler field overflow\n"); 177 170 178 171 return (arg & RD_MASK) << RD_SH; 179 172 } 180 173 181 174 static inline __uasminit u32 build_re(u32 arg) 182 175 { 183 - if (arg & ~RE_MASK) 184 - printk(KERN_WARNING "Micro-assembler field overflow\n"); 176 + WARN(arg & ~RE_MASK, KERN_WARNING "Micro-assembler field overflow\n"); 185 177 186 178 return (arg & RE_MASK) << RE_SH; 187 179 } 188 180 189 181 static inline __uasminit u32 build_simm(s32 arg) 190 182 { 191 - if (arg > 0x7fff || arg < -0x8000) 192 - printk(KERN_WARNING "Micro-assembler field overflow\n"); 183 + WARN(arg > 0x7fff || arg < -0x8000, 184 + KERN_WARNING "Micro-assembler field overflow\n"); 193 185 194 186 return arg & 0xffff; 195 187 } 196 188 197 189 static inline __uasminit u32 build_uimm(u32 arg) 198 190 { 199 - if (arg & ~IMM_MASK) 200 - printk(KERN_WARNING "Micro-assembler field overflow\n"); 191 + WARN(arg & ~IMM_MASK, KERN_WARNING "Micro-assembler field overflow\n"); 201 192 202 193 return arg & IMM_MASK; 203 194 } 204 195 205 196 static inline __uasminit u32 build_bimm(s32 arg) 206 197 { 207 - if (arg > 0x1ffff || arg < -0x20000) 208 - printk(KERN_WARNING "Micro-assembler field overflow\n"); 198 + WARN(arg > 0x1ffff || arg < -0x20000, 199 + KERN_WARNING "Micro-assembler field overflow\n"); 209 200 210 - if (arg & 0x3) 211 - printk(KERN_WARNING "Invalid micro-assembler branch target\n"); 201 + WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n"); 212 202 213 203 return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff); 214 204 } 215 205 216 206 static inline __uasminit u32 build_jimm(u32 arg) 217 207 { 218 - if (arg & ~((JIMM_MASK) << 2)) 219 - printk(KERN_WARNING "Micro-assembler field overflow\n"); 208 + WARN(arg & ~(JIMM_MASK << 2), 209 + KERN_WARNING "Micro-assembler field overflow\n"); 220 210 221 211 return (arg >> 2) & JIMM_MASK; 222 212 } 223 213 224 214 static inline __uasminit u32 build_scimm(u32 arg) 225 215 { 226 - if (arg & ~SCIMM_MASK) 227 - printk(KERN_WARNING "Micro-assembler field overflow\n"); 216 + WARN(arg & ~SCIMM_MASK, 217 + KERN_WARNING "Micro-assembler field overflow\n"); 228 218 229 219 return (arg & SCIMM_MASK) << SCIMM_SH; 230 220 } 231 221 232 222 static inline __uasminit u32 build_func(u32 arg) 233 223 { 234 - if (arg & ~FUNC_MASK) 235 - printk(KERN_WARNING "Micro-assembler field overflow\n"); 224 + WARN(arg & ~FUNC_MASK, KERN_WARNING "Micro-assembler field overflow\n"); 236 225 237 226 return arg & FUNC_MASK; 238 227 } 239 228 240 229 static inline __uasminit u32 build_set(u32 arg) 241 230 { 242 - if (arg & ~SET_MASK) 243 - printk(KERN_WARNING "Micro-assembler field overflow\n"); 231 + WARN(arg & ~SET_MASK, KERN_WARNING "Micro-assembler field overflow\n"); 244 232 245 233 return arg & SET_MASK; 246 234 } ··· 336 340 } \ 337 341 UASM_EXPORT_SYMBOL(uasm_i##op); 338 342 343 + #define I_u2u1msb32u3(op) \ 344 + Ip_u2u1msbu3(op) \ 345 + { \ 346 + build_insn(buf, insn##op, b, a, c+d-33, c); \ 347 + } \ 348 + UASM_EXPORT_SYMBOL(uasm_i##op); 349 + 339 350 #define I_u1u2(op) \ 340 351 Ip_u1u2(op) \ 341 352 { \ ··· 425 422 I_u3u1u2(_xor) 426 423 I_u2u1u3(_xori) 427 424 I_u2u1msbu3(_dins); 425 + I_u2u1msb32u3(_dinsm); 428 426 I_u1(_syscall); 429 427 I_u1u2s3(_bbit0); 430 428 I_u1u2s3(_bbit1); 429 + I_u3u1u2(_lwx) 430 + I_u3u1u2(_ldx) 431 431 432 432 #ifdef CONFIG_CPU_CAVIUM_OCTEON 433 433 #include <asm/octeon/octeon.h>
+1 -2
arch/mips/sibyte/common/sb_tbprof.c
··· 410 410 return -EBUSY; 411 411 412 412 memset(&sbp, 0, sizeof(struct sbprof_tb)); 413 - sbp.sbprof_tbbuf = vmalloc(MAX_TBSAMPLE_BYTES); 413 + sbp.sbprof_tbbuf = vzalloc(MAX_TBSAMPLE_BYTES); 414 414 if (!sbp.sbprof_tbbuf) { 415 415 sbp.open = SB_CLOSED; 416 416 wmb(); 417 417 return -ENOMEM; 418 418 } 419 419 420 - memset(sbp.sbprof_tbbuf, 0, MAX_TBSAMPLE_BYTES); 421 420 init_waitqueue_head(&sbp.tb_sync); 422 421 init_waitqueue_head(&sbp.tb_read); 423 422 mutex_init(&sbp.lock);
+2 -5
arch/mips/txx9/generic/pci.c
··· 213 213 214 214 pcic->mem_offset = 0; /* busaddr == physaddr */ 215 215 216 - printk(KERN_INFO "PCI: IO 0x%08llx-0x%08llx MEM 0x%08llx-0x%08llx\n", 217 - (unsigned long long)pcic->mem_resource[1].start, 218 - (unsigned long long)pcic->mem_resource[1].end, 219 - (unsigned long long)pcic->mem_resource[0].start, 220 - (unsigned long long)pcic->mem_resource[0].end); 216 + printk(KERN_INFO "PCI: IO %pR MEM %pR\n", 217 + &pcic->mem_resource[1], &pcic->mem_resource[0]); 221 218 222 219 /* register_pci_controller() will request MEM resource */ 223 220 release_resource(&pcic->mem_resource[0]);
+8
drivers/spi/Kconfig
··· 53 53 54 54 comment "SPI Master Controller Drivers" 55 55 56 + config SPI_ATH79 57 + tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver" 58 + depends on ATH79 && GENERIC_GPIO 59 + select SPI_BITBANG 60 + help 61 + This enables support for the SPI controller present on the 62 + Atheros AR71XX/AR724X/AR913X SoCs. 63 + 56 64 config SPI_ATMEL 57 65 tristate "Atmel SPI Controller" 58 66 depends on (ARCH_AT91 || AVR32)
+1
drivers/spi/Makefile
··· 10 10 11 11 # SPI master controller drivers (bus) 12 12 obj-$(CONFIG_SPI_ATMEL) += atmel_spi.o 13 + obj-$(CONFIG_SPI_ATH79) += ath79_spi.o 13 14 obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx.o 14 15 obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o 15 16 obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
+292
drivers/spi/ath79_spi.c
··· 1 + /* 2 + * SPI controller driver for the Atheros AR71XX/AR724X/AR913X SoCs 3 + * 4 + * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> 5 + * 6 + * This driver has been based on the spi-gpio.c: 7 + * Copyright (C) 2006,2008 David Brownell 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License version 2 as 11 + * published by the Free Software Foundation. 12 + * 13 + */ 14 + 15 + #include <linux/kernel.h> 16 + #include <linux/init.h> 17 + #include <linux/delay.h> 18 + #include <linux/spinlock.h> 19 + #include <linux/workqueue.h> 20 + #include <linux/platform_device.h> 21 + #include <linux/io.h> 22 + #include <linux/spi/spi.h> 23 + #include <linux/spi/spi_bitbang.h> 24 + #include <linux/bitops.h> 25 + #include <linux/gpio.h> 26 + 27 + #include <asm/mach-ath79/ar71xx_regs.h> 28 + #include <asm/mach-ath79/ath79_spi_platform.h> 29 + 30 + #define DRV_NAME "ath79-spi" 31 + 32 + struct ath79_spi { 33 + struct spi_bitbang bitbang; 34 + u32 ioc_base; 35 + u32 reg_ctrl; 36 + void __iomem *base; 37 + }; 38 + 39 + static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg) 40 + { 41 + return ioread32(sp->base + reg); 42 + } 43 + 44 + static inline void ath79_spi_wr(struct ath79_spi *sp, unsigned reg, u32 val) 45 + { 46 + iowrite32(val, sp->base + reg); 47 + } 48 + 49 + static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi) 50 + { 51 + return spi_master_get_devdata(spi->master); 52 + } 53 + 54 + static void ath79_spi_chipselect(struct spi_device *spi, int is_active) 55 + { 56 + struct ath79_spi *sp = ath79_spidev_to_sp(spi); 57 + int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active; 58 + 59 + if (is_active) { 60 + /* set initial clock polarity */ 61 + if (spi->mode & SPI_CPOL) 62 + sp->ioc_base |= AR71XX_SPI_IOC_CLK; 63 + else 64 + sp->ioc_base &= ~AR71XX_SPI_IOC_CLK; 65 + 66 + ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); 67 + } 68 + 69 + if (spi->chip_select) { 70 + struct ath79_spi_controller_data *cdata = spi->controller_data; 71 + 72 + /* SPI is normally active-low */ 73 + gpio_set_value(cdata->gpio, cs_high); 74 + } else { 75 + if (cs_high) 76 + sp->ioc_base |= AR71XX_SPI_IOC_CS0; 77 + else 78 + sp->ioc_base &= ~AR71XX_SPI_IOC_CS0; 79 + 80 + ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); 81 + } 82 + 83 + } 84 + 85 + static int ath79_spi_setup_cs(struct spi_device *spi) 86 + { 87 + struct ath79_spi *sp = ath79_spidev_to_sp(spi); 88 + struct ath79_spi_controller_data *cdata; 89 + 90 + cdata = spi->controller_data; 91 + if (spi->chip_select && !cdata) 92 + return -EINVAL; 93 + 94 + /* enable GPIO mode */ 95 + ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO); 96 + 97 + /* save CTRL register */ 98 + sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL); 99 + sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC); 100 + 101 + /* TODO: setup speed? */ 102 + ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43); 103 + 104 + if (spi->chip_select) { 105 + int status = 0; 106 + 107 + status = gpio_request(cdata->gpio, dev_name(&spi->dev)); 108 + if (status) 109 + return status; 110 + 111 + status = gpio_direction_output(cdata->gpio, 112 + spi->mode & SPI_CS_HIGH); 113 + if (status) { 114 + gpio_free(cdata->gpio); 115 + return status; 116 + } 117 + } else { 118 + if (spi->mode & SPI_CS_HIGH) 119 + sp->ioc_base |= AR71XX_SPI_IOC_CS0; 120 + else 121 + sp->ioc_base &= ~AR71XX_SPI_IOC_CS0; 122 + ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); 123 + } 124 + 125 + return 0; 126 + } 127 + 128 + static void ath79_spi_cleanup_cs(struct spi_device *spi) 129 + { 130 + struct ath79_spi *sp = ath79_spidev_to_sp(spi); 131 + 132 + if (spi->chip_select) { 133 + struct ath79_spi_controller_data *cdata = spi->controller_data; 134 + gpio_free(cdata->gpio); 135 + } 136 + 137 + /* restore CTRL register */ 138 + ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl); 139 + /* disable GPIO mode */ 140 + ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); 141 + } 142 + 143 + static int ath79_spi_setup(struct spi_device *spi) 144 + { 145 + int status = 0; 146 + 147 + if (spi->bits_per_word > 32) 148 + return -EINVAL; 149 + 150 + if (!spi->controller_state) { 151 + status = ath79_spi_setup_cs(spi); 152 + if (status) 153 + return status; 154 + } 155 + 156 + status = spi_bitbang_setup(spi); 157 + if (status && !spi->controller_state) 158 + ath79_spi_cleanup_cs(spi); 159 + 160 + return status; 161 + } 162 + 163 + static void ath79_spi_cleanup(struct spi_device *spi) 164 + { 165 + ath79_spi_cleanup_cs(spi); 166 + spi_bitbang_cleanup(spi); 167 + } 168 + 169 + static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs, 170 + u32 word, u8 bits) 171 + { 172 + struct ath79_spi *sp = ath79_spidev_to_sp(spi); 173 + u32 ioc = sp->ioc_base; 174 + 175 + /* clock starts at inactive polarity */ 176 + for (word <<= (32 - bits); likely(bits); bits--) { 177 + u32 out; 178 + 179 + if (word & (1 << 31)) 180 + out = ioc | AR71XX_SPI_IOC_DO; 181 + else 182 + out = ioc & ~AR71XX_SPI_IOC_DO; 183 + 184 + /* setup MSB (to slave) on trailing edge */ 185 + ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out); 186 + ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK); 187 + 188 + word <<= 1; 189 + } 190 + 191 + return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS); 192 + } 193 + 194 + static __devinit int ath79_spi_probe(struct platform_device *pdev) 195 + { 196 + struct spi_master *master; 197 + struct ath79_spi *sp; 198 + struct ath79_spi_platform_data *pdata; 199 + struct resource *r; 200 + int ret; 201 + 202 + master = spi_alloc_master(&pdev->dev, sizeof(*sp)); 203 + if (master == NULL) { 204 + dev_err(&pdev->dev, "failed to allocate spi master\n"); 205 + return -ENOMEM; 206 + } 207 + 208 + sp = spi_master_get_devdata(master); 209 + platform_set_drvdata(pdev, sp); 210 + 211 + pdata = pdev->dev.platform_data; 212 + 213 + master->setup = ath79_spi_setup; 214 + master->cleanup = ath79_spi_cleanup; 215 + if (pdata) { 216 + master->bus_num = pdata->bus_num; 217 + master->num_chipselect = pdata->num_chipselect; 218 + } else { 219 + master->bus_num = -1; 220 + master->num_chipselect = 1; 221 + } 222 + 223 + sp->bitbang.master = spi_master_get(master); 224 + sp->bitbang.chipselect = ath79_spi_chipselect; 225 + sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0; 226 + sp->bitbang.setup_transfer = spi_bitbang_setup_transfer; 227 + sp->bitbang.flags = SPI_CS_HIGH; 228 + 229 + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 230 + if (r == NULL) { 231 + ret = -ENOENT; 232 + goto err_put_master; 233 + } 234 + 235 + sp->base = ioremap(r->start, r->end - r->start + 1); 236 + if (!sp->base) { 237 + ret = -ENXIO; 238 + goto err_put_master; 239 + } 240 + 241 + ret = spi_bitbang_start(&sp->bitbang); 242 + if (ret) 243 + goto err_unmap; 244 + 245 + return 0; 246 + 247 + err_unmap: 248 + iounmap(sp->base); 249 + err_put_master: 250 + platform_set_drvdata(pdev, NULL); 251 + spi_master_put(sp->bitbang.master); 252 + 253 + return ret; 254 + } 255 + 256 + static __devexit int ath79_spi_remove(struct platform_device *pdev) 257 + { 258 + struct ath79_spi *sp = platform_get_drvdata(pdev); 259 + 260 + spi_bitbang_stop(&sp->bitbang); 261 + iounmap(sp->base); 262 + platform_set_drvdata(pdev, NULL); 263 + spi_master_put(sp->bitbang.master); 264 + 265 + return 0; 266 + } 267 + 268 + static struct platform_driver ath79_spi_driver = { 269 + .probe = ath79_spi_probe, 270 + .remove = __devexit_p(ath79_spi_remove), 271 + .driver = { 272 + .name = DRV_NAME, 273 + .owner = THIS_MODULE, 274 + }, 275 + }; 276 + 277 + static __init int ath79_spi_init(void) 278 + { 279 + return platform_driver_register(&ath79_spi_driver); 280 + } 281 + module_init(ath79_spi_init); 282 + 283 + static __exit void ath79_spi_exit(void) 284 + { 285 + platform_driver_unregister(&ath79_spi_driver); 286 + } 287 + module_exit(ath79_spi_exit); 288 + 289 + MODULE_DESCRIPTION("SPI controller driver for Atheros AR71XX/AR724X/AR913X"); 290 + MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); 291 + MODULE_LICENSE("GPL v2"); 292 + MODULE_ALIAS("platform:" DRV_NAME);