summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/microblaze/Kconfig3
-rw-r--r--arch/microblaze/boot/dts/system.dts16
-rw-r--r--arch/microblaze/configs/mmu_defconfig22
-rw-r--r--arch/microblaze/configs/nommu_defconfig25
-rw-r--r--arch/microblaze/include/asm/io.h1
-rw-r--r--arch/microblaze/include/asm/uaccess.h42
-rw-r--r--arch/microblaze/kernel/reset.c87
-rw-r--r--arch/microblaze/mm/consistent.c221
8 files changed, 92 insertions, 325 deletions
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 632c9477a0f6..c9c4be822456 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -5,15 +5,18 @@ config MICROBLAZE
5 select ARCH_NO_SWAP 5 select ARCH_NO_SWAP
6 select ARCH_HAS_BINFMT_FLAT if !MMU 6 select ARCH_HAS_BINFMT_FLAT if !MMU
7 select ARCH_HAS_DMA_COHERENT_TO_PFN if MMU 7 select ARCH_HAS_DMA_COHERENT_TO_PFN if MMU
8 select ARCH_HAS_DMA_PREP_COHERENT
8 select ARCH_HAS_GCOV_PROFILE_ALL 9 select ARCH_HAS_GCOV_PROFILE_ALL
9 select ARCH_HAS_SYNC_DMA_FOR_CPU 10 select ARCH_HAS_SYNC_DMA_FOR_CPU
10 select ARCH_HAS_SYNC_DMA_FOR_DEVICE 11 select ARCH_HAS_SYNC_DMA_FOR_DEVICE
12 select ARCH_HAS_UNCACHED_SEGMENT if !MMU
11 select ARCH_MIGHT_HAVE_PC_PARPORT 13 select ARCH_MIGHT_HAVE_PC_PARPORT
12 select ARCH_WANT_IPC_PARSE_VERSION 14 select ARCH_WANT_IPC_PARSE_VERSION
13 select BUILDTIME_EXTABLE_SORT 15 select BUILDTIME_EXTABLE_SORT
14 select TIMER_OF 16 select TIMER_OF
15 select CLONE_BACKWARDS3 17 select CLONE_BACKWARDS3
16 select COMMON_CLK 18 select COMMON_CLK
19 select DMA_DIRECT_REMAP if MMU
17 select GENERIC_ATOMIC64 20 select GENERIC_ATOMIC64
18 select GENERIC_CLOCKEVENTS 21 select GENERIC_CLOCKEVENTS
19 select GENERIC_CPU_DEVICES 22 select GENERIC_CPU_DEVICES
diff --git a/arch/microblaze/boot/dts/system.dts b/arch/microblaze/boot/dts/system.dts
index 5a8a9d090c37..5b236527176e 100644
--- a/arch/microblaze/boot/dts/system.dts
+++ b/arch/microblaze/boot/dts/system.dts
@@ -18,7 +18,6 @@
18 #address-cells = <1>; 18 #address-cells = <1>;
19 #size-cells = <1>; 19 #size-cells = <1>;
20 compatible = "xlnx,microblaze"; 20 compatible = "xlnx,microblaze";
21 hard-reset-gpios = <&LEDs_8Bit 2 1>;
22 model = "testing"; 21 model = "testing";
23 DDR2_SDRAM: memory@90000000 { 22 DDR2_SDRAM: memory@90000000 {
24 device_type = "memory"; 23 device_type = "memory";
@@ -281,6 +280,21 @@
281 gpios = <&LEDs_8Bit 7 1>; 280 gpios = <&LEDs_8Bit 7 1>;
282 }; 281 };
283 } ; 282 } ;
283
284 gpio-restart {
285 compatible = "gpio-restart";
286 /*
287 * FIXME: is this active low or active high?
288 * the current flag (1) indicates active low.
289 * delay measures are templates, should be adjusted
290 * to datasheet or trial-and-error with real hardware.
291 */
292 gpios = <&LEDs_8Bit 2 1>;
293 active-delay = <100>;
294 inactive-delay = <10>;
295 wait-delay = <100>;
296 };
297
284 RS232_Uart_1: serial@84000000 { 298 RS232_Uart_1: serial@84000000 {
285 clock-frequency = <125000000>; 299 clock-frequency = <125000000>;
286 compatible = "xlnx,xps-uartlite-1.00.a"; 300 compatible = "xlnx,xps-uartlite-1.00.a";
diff --git a/arch/microblaze/configs/mmu_defconfig b/arch/microblaze/configs/mmu_defconfig
index 92fd4e95b488..654edfdc7867 100644
--- a/arch/microblaze/configs/mmu_defconfig
+++ b/arch/microblaze/configs/mmu_defconfig
@@ -5,15 +5,10 @@ CONFIG_IKCONFIG=y
5CONFIG_IKCONFIG_PROC=y 5CONFIG_IKCONFIG_PROC=y
6CONFIG_SYSFS_DEPRECATED=y 6CONFIG_SYSFS_DEPRECATED=y
7CONFIG_SYSFS_DEPRECATED_V2=y 7CONFIG_SYSFS_DEPRECATED_V2=y
8CONFIG_KALLSYMS_ALL=y
9# CONFIG_BASE_FULL is not set 8# CONFIG_BASE_FULL is not set
9CONFIG_KALLSYMS_ALL=y
10CONFIG_EMBEDDED=y 10CONFIG_EMBEDDED=y
11CONFIG_SLAB=y 11CONFIG_SLAB=y
12CONFIG_MODULES=y
13CONFIG_MODULE_UNLOAD=y
14# CONFIG_BLK_DEV_BSG is not set
15CONFIG_PARTITION_ADVANCED=y
16# CONFIG_EFI_PARTITION is not set
17CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1 12CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1
18CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1 13CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1
19CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1 14CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1
@@ -25,14 +20,19 @@ CONFIG_MMU=y
25CONFIG_CMDLINE_BOOL=y 20CONFIG_CMDLINE_BOOL=y
26CONFIG_CMDLINE_FORCE=y 21CONFIG_CMDLINE_FORCE=y
27CONFIG_HIGHMEM=y 22CONFIG_HIGHMEM=y
28CONFIG_PCI=y
29CONFIG_PCI_XILINX=y 23CONFIG_PCI_XILINX=y
24CONFIG_MODULES=y
25CONFIG_MODULE_UNLOAD=y
26# CONFIG_BLK_DEV_BSG is not set
27CONFIG_PARTITION_ADVANCED=y
28# CONFIG_EFI_PARTITION is not set
30CONFIG_NET=y 29CONFIG_NET=y
31CONFIG_PACKET=y 30CONFIG_PACKET=y
32CONFIG_UNIX=y 31CONFIG_UNIX=y
33CONFIG_INET=y 32CONFIG_INET=y
34# CONFIG_IPV6 is not set 33# CONFIG_IPV6 is not set
35CONFIG_BRIDGE=m 34CONFIG_BRIDGE=m
35CONFIG_PCI=y
36CONFIG_MTD=y 36CONFIG_MTD=y
37CONFIG_MTD_CFI=y 37CONFIG_MTD_CFI=y
38CONFIG_MTD_CFI_INTELEXT=y 38CONFIG_MTD_CFI_INTELEXT=y
@@ -41,6 +41,7 @@ CONFIG_BLK_DEV_RAM=y
41CONFIG_BLK_DEV_RAM_SIZE=8192 41CONFIG_BLK_DEV_RAM_SIZE=8192
42CONFIG_NETDEVICES=y 42CONFIG_NETDEVICES=y
43CONFIG_XILINX_EMACLITE=y 43CONFIG_XILINX_EMACLITE=y
44CONFIG_XILINX_AXI_EMAC=y
44CONFIG_XILINX_LL_TEMAC=y 45CONFIG_XILINX_LL_TEMAC=y
45# CONFIG_INPUT is not set 46# CONFIG_INPUT is not set
46# CONFIG_SERIO is not set 47# CONFIG_SERIO is not set
@@ -59,6 +60,8 @@ CONFIG_SPI_XILINX=y
59CONFIG_GPIOLIB=y 60CONFIG_GPIOLIB=y
60CONFIG_GPIO_SYSFS=y 61CONFIG_GPIO_SYSFS=y
61CONFIG_GPIO_XILINX=y 62CONFIG_GPIO_XILINX=y
63CONFIG_POWER_RESET=y
64CONFIG_POWER_RESET_GPIO_RESTART=y
62# CONFIG_HWMON is not set 65# CONFIG_HWMON is not set
63CONFIG_WATCHDOG=y 66CONFIG_WATCHDOG=y
64CONFIG_XILINX_WATCHDOG=y 67CONFIG_XILINX_WATCHDOG=y
@@ -74,8 +77,8 @@ CONFIG_CRAMFS=y
74CONFIG_ROMFS_FS=y 77CONFIG_ROMFS_FS=y
75CONFIG_NFS_FS=y 78CONFIG_NFS_FS=y
76CONFIG_CIFS=y 79CONFIG_CIFS=y
77CONFIG_CIFS_STATS=y
78CONFIG_CIFS_STATS2=y 80CONFIG_CIFS_STATS2=y
81CONFIG_ENCRYPTED_KEYS=y
79CONFIG_DEBUG_INFO=y 82CONFIG_DEBUG_INFO=y
80CONFIG_DEBUG_SLAB=y 83CONFIG_DEBUG_SLAB=y
81CONFIG_DETECT_HUNG_TASK=y 84CONFIG_DETECT_HUNG_TASK=y
@@ -83,6 +86,3 @@ CONFIG_DEBUG_SPINLOCK=y
83CONFIG_KGDB=y 86CONFIG_KGDB=y
84CONFIG_KGDB_TESTS=y 87CONFIG_KGDB_TESTS=y
85CONFIG_KGDB_KDB=y 88CONFIG_KGDB_KDB=y
86CONFIG_EARLY_PRINTK=y
87CONFIG_KEYS=y
88CONFIG_ENCRYPTED_KEYS=y
diff --git a/arch/microblaze/configs/nommu_defconfig b/arch/microblaze/configs/nommu_defconfig
index 06d69a6e192d..377de39ccb8c 100644
--- a/arch/microblaze/configs/nommu_defconfig
+++ b/arch/microblaze/configs/nommu_defconfig
@@ -7,15 +7,10 @@ CONFIG_IKCONFIG=y
7CONFIG_IKCONFIG_PROC=y 7CONFIG_IKCONFIG_PROC=y
8CONFIG_SYSFS_DEPRECATED=y 8CONFIG_SYSFS_DEPRECATED=y
9CONFIG_SYSFS_DEPRECATED_V2=y 9CONFIG_SYSFS_DEPRECATED_V2=y
10CONFIG_KALLSYMS_ALL=y
11# CONFIG_BASE_FULL is not set 10# CONFIG_BASE_FULL is not set
11CONFIG_KALLSYMS_ALL=y
12CONFIG_EMBEDDED=y 12CONFIG_EMBEDDED=y
13CONFIG_SLAB=y 13CONFIG_SLAB=y
14CONFIG_MODULES=y
15CONFIG_MODULE_UNLOAD=y
16# CONFIG_BLK_DEV_BSG is not set
17CONFIG_PARTITION_ADVANCED=y
18# CONFIG_EFI_PARTITION is not set
19CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1 14CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1
20CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1 15CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1
21CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1 16CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1
@@ -25,13 +20,18 @@ CONFIG_XILINX_MICROBLAZE0_USE_FPU=2
25CONFIG_HZ_100=y 20CONFIG_HZ_100=y
26CONFIG_CMDLINE_BOOL=y 21CONFIG_CMDLINE_BOOL=y
27CONFIG_CMDLINE_FORCE=y 22CONFIG_CMDLINE_FORCE=y
28CONFIG_PCI=y
29CONFIG_PCI_XILINX=y 23CONFIG_PCI_XILINX=y
24CONFIG_MODULES=y
25CONFIG_MODULE_UNLOAD=y
26# CONFIG_BLK_DEV_BSG is not set
27CONFIG_PARTITION_ADVANCED=y
28# CONFIG_EFI_PARTITION is not set
30CONFIG_NET=y 29CONFIG_NET=y
31CONFIG_PACKET=y 30CONFIG_PACKET=y
32CONFIG_UNIX=y 31CONFIG_UNIX=y
33CONFIG_INET=y 32CONFIG_INET=y
34# CONFIG_IPV6 is not set 33# CONFIG_IPV6 is not set
34CONFIG_PCI=y
35CONFIG_MTD=y 35CONFIG_MTD=y
36CONFIG_MTD_CMDLINE_PARTS=y 36CONFIG_MTD_CMDLINE_PARTS=y
37CONFIG_MTD_BLOCK=y 37CONFIG_MTD_BLOCK=y
@@ -62,6 +62,8 @@ CONFIG_SPI_XILINX=y
62CONFIG_GPIOLIB=y 62CONFIG_GPIOLIB=y
63CONFIG_GPIO_SYSFS=y 63CONFIG_GPIO_SYSFS=y
64CONFIG_GPIO_XILINX=y 64CONFIG_GPIO_XILINX=y
65CONFIG_POWER_RESET=y
66CONFIG_POWER_RESET_GPIO_RESTART=y
65# CONFIG_HWMON is not set 67# CONFIG_HWMON is not set
66CONFIG_WATCHDOG=y 68CONFIG_WATCHDOG=y
67CONFIG_XILINX_WATCHDOG=y 69CONFIG_XILINX_WATCHDOG=y
@@ -75,11 +77,6 @@ CONFIG_ROMFS_FS=y
75CONFIG_NFS_FS=y 77CONFIG_NFS_FS=y
76CONFIG_NFS_V3_ACL=y 78CONFIG_NFS_V3_ACL=y
77CONFIG_NLS=y 79CONFIG_NLS=y
78CONFIG_DEBUG_INFO=y
79CONFIG_DEBUG_SLAB=y
80CONFIG_DETECT_HUNG_TASK=y
81CONFIG_DEBUG_SPINLOCK=y
82CONFIG_EARLY_PRINTK=y
83CONFIG_KEYS=y 80CONFIG_KEYS=y
84CONFIG_ENCRYPTED_KEYS=y 81CONFIG_ENCRYPTED_KEYS=y
85CONFIG_CRYPTO_ECB=y 82CONFIG_CRYPTO_ECB=y
@@ -87,3 +84,7 @@ CONFIG_CRYPTO_MD4=y
87CONFIG_CRYPTO_MD5=y 84CONFIG_CRYPTO_MD5=y
88CONFIG_CRYPTO_ARC4=y 85CONFIG_CRYPTO_ARC4=y
89CONFIG_CRYPTO_DES=y 86CONFIG_CRYPTO_DES=y
87CONFIG_DEBUG_INFO=y
88CONFIG_DEBUG_SLAB=y
89CONFIG_DETECT_HUNG_TASK=y
90CONFIG_DEBUG_SPINLOCK=y
diff --git a/arch/microblaze/include/asm/io.h b/arch/microblaze/include/asm/io.h
index c7968139486f..86c95b2a1ce1 100644
--- a/arch/microblaze/include/asm/io.h
+++ b/arch/microblaze/include/asm/io.h
@@ -40,7 +40,6 @@ extern void iounmap(volatile void __iomem *addr);
40 40
41extern void __iomem *ioremap(phys_addr_t address, unsigned long size); 41extern void __iomem *ioremap(phys_addr_t address, unsigned long size);
42#define ioremap_nocache(addr, size) ioremap((addr), (size)) 42#define ioremap_nocache(addr, size) ioremap((addr), (size))
43#define ioremap_fullcache(addr, size) ioremap((addr), (size))
44#define ioremap_wc(addr, size) ioremap((addr), (size)) 43#define ioremap_wc(addr, size) ioremap((addr), (size))
45#define ioremap_wt(addr, size) ioremap((addr), (size)) 44#define ioremap_wt(addr, size) ioremap((addr), (size))
46 45
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h
index bff2a71c828a..a1f206b90753 100644
--- a/arch/microblaze/include/asm/uaccess.h
+++ b/arch/microblaze/include/asm/uaccess.h
@@ -163,44 +163,15 @@ extern long __user_bad(void);
163 * Returns zero on success, or -EFAULT on error. 163 * Returns zero on success, or -EFAULT on error.
164 * On error, the variable @x is set to zero. 164 * On error, the variable @x is set to zero.
165 */ 165 */
166#define get_user(x, ptr) \ 166#define get_user(x, ptr) ({ \
167 __get_user_check((x), (ptr), sizeof(*(ptr))) 167 const typeof(*(ptr)) __user *__gu_ptr = (ptr); \
168 168 access_ok(__gu_ptr, sizeof(*__gu_ptr)) ? \
169#define __get_user_check(x, ptr, size) \ 169 __get_user(x, __gu_ptr) : -EFAULT; \
170({ \
171 unsigned long __gu_val = 0; \
172 const typeof(*(ptr)) __user *__gu_addr = (ptr); \
173 int __gu_err = 0; \
174 \
175 if (access_ok(__gu_addr, size)) { \
176 switch (size) { \
177 case 1: \
178 __get_user_asm("lbu", __gu_addr, __gu_val, \
179 __gu_err); \
180 break; \
181 case 2: \
182 __get_user_asm("lhu", __gu_addr, __gu_val, \
183 __gu_err); \
184 break; \
185 case 4: \
186 __get_user_asm("lw", __gu_addr, __gu_val, \
187 __gu_err); \
188 break; \
189 default: \
190 __gu_err = __user_bad(); \
191 break; \
192 } \
193 } else { \
194 __gu_err = -EFAULT; \
195 } \
196 x = (__force typeof(*(ptr)))__gu_val; \
197 __gu_err; \
198}) 170})
199 171
200#define __get_user(x, ptr) \ 172#define __get_user(x, ptr) \
201({ \ 173({ \
202 unsigned long __gu_val = 0; \ 174 unsigned long __gu_val = 0; \
203 /*unsigned long __gu_ptr = (unsigned long)(ptr);*/ \
204 long __gu_err; \ 175 long __gu_err; \
205 switch (sizeof(*(ptr))) { \ 176 switch (sizeof(*(ptr))) { \
206 case 1: \ 177 case 1: \
@@ -212,6 +183,11 @@ extern long __user_bad(void);
212 case 4: \ 183 case 4: \
213 __get_user_asm("lw", (ptr), __gu_val, __gu_err); \ 184 __get_user_asm("lw", (ptr), __gu_val, __gu_err); \
214 break; \ 185 break; \
186 case 8: \
187 __gu_err = __copy_from_user(&__gu_val, ptr, 8); \
188 if (__gu_err) \
189 __gu_err = -EFAULT; \
190 break; \
215 default: \ 191 default: \
216 /* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\ 192 /* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\
217 } \ 193 } \
diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c
index fcbe1daf6316..5f4722908164 100644
--- a/arch/microblaze/kernel/reset.c
+++ b/arch/microblaze/kernel/reset.c
@@ -8,83 +8,9 @@
8 */ 8 */
9 9
10#include <linux/init.h> 10#include <linux/init.h>
11#include <linux/delay.h>
11#include <linux/of_platform.h> 12#include <linux/of_platform.h>
12 13#include <linux/reboot.h>
13/* Trigger specific functions */
14#ifdef CONFIG_GPIOLIB
15
16#include <linux/of_gpio.h>
17
18static int handle; /* reset pin handle */
19static unsigned int reset_val;
20
21static int of_platform_reset_gpio_probe(void)
22{
23 int ret;
24 handle = of_get_named_gpio(of_find_node_by_path("/"),
25 "hard-reset-gpios", 0);
26
27 if (!gpio_is_valid(handle)) {
28 pr_info("Skipping unavailable RESET gpio %d (%s)\n",
29 handle, "reset");
30 return -ENODEV;
31 }
32
33 ret = gpio_request(handle, "reset");
34 if (ret < 0) {
35 pr_info("GPIO pin is already allocated\n");
36 return ret;
37 }
38
39 /* get current setup value */
40 reset_val = gpio_get_value(handle);
41 /* FIXME maybe worth to perform any action */
42 pr_debug("Reset: Gpio output state: 0x%x\n", reset_val);
43
44 /* Setup GPIO as output */
45 ret = gpio_direction_output(handle, 0);
46 if (ret < 0)
47 goto err;
48
49 /* Setup output direction */
50 gpio_set_value(handle, 0);
51
52 pr_info("RESET: Registered gpio device: %d, current val: %d\n",
53 handle, reset_val);
54 return 0;
55err:
56 gpio_free(handle);
57 return ret;
58}
59device_initcall(of_platform_reset_gpio_probe);
60
61
62static void gpio_system_reset(void)
63{
64 if (gpio_is_valid(handle))
65 gpio_set_value(handle, 1 - reset_val);
66 else
67 pr_notice("Reset GPIO unavailable - halting!\n");
68}
69#else
70static void gpio_system_reset(void)
71{
72 pr_notice("No reset GPIO present - halting!\n");
73}
74
75void of_platform_reset_gpio_probe(void)
76{
77 return;
78}
79#endif
80
81void machine_restart(char *cmd)
82{
83 pr_notice("Machine restart...\n");
84 gpio_system_reset();
85 while (1)
86 ;
87}
88 14
89void machine_shutdown(void) 15void machine_shutdown(void)
90{ 16{
@@ -106,3 +32,12 @@ void machine_power_off(void)
106 while (1) 32 while (1)
107 ; 33 ;
108} 34}
35
36void machine_restart(char *cmd)
37{
38 do_kernel_restart(cmd);
39 /* Give the restart hook 1 s to take us down */
40 mdelay(1000);
41 pr_emerg("Reboot failed -- System halted\n");
42 while (1);
43}
diff --git a/arch/microblaze/mm/consistent.c b/arch/microblaze/mm/consistent.c
index bc7042209c57..8c5f0c332d8b 100644
--- a/arch/microblaze/mm/consistent.c
+++ b/arch/microblaze/mm/consistent.c
@@ -4,217 +4,56 @@
4 * Copyright (C) 2010 Michal Simek <monstr@monstr.eu> 4 * Copyright (C) 2010 Michal Simek <monstr@monstr.eu>
5 * Copyright (C) 2010 PetaLogix 5 * Copyright (C) 2010 PetaLogix
6 * Copyright (C) 2005 John Williams <jwilliams@itee.uq.edu.au> 6 * Copyright (C) 2005 John Williams <jwilliams@itee.uq.edu.au>
7 *
8 * Based on PowerPC version derived from arch/arm/mm/consistent.c
9 * Copyright (C) 2001 Dan Malek (dmalek@jlc.net)
10 * Copyright (C) 2000 Russell King
11 */ 7 */
12 8
13#include <linux/export.h>
14#include <linux/signal.h>
15#include <linux/sched.h>
16#include <linux/kernel.h> 9#include <linux/kernel.h>
17#include <linux/errno.h>
18#include <linux/string.h> 10#include <linux/string.h>
19#include <linux/types.h> 11#include <linux/types.h>
20#include <linux/ptrace.h>
21#include <linux/mman.h>
22#include <linux/mm.h> 12#include <linux/mm.h>
23#include <linux/swap.h>
24#include <linux/stddef.h>
25#include <linux/vmalloc.h>
26#include <linux/init.h> 13#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/memblock.h>
29#include <linux/highmem.h>
30#include <linux/pci.h>
31#include <linux/interrupt.h>
32#include <linux/gfp.h>
33#include <linux/dma-noncoherent.h> 14#include <linux/dma-noncoherent.h>
34
35#include <asm/pgalloc.h>
36#include <linux/io.h>
37#include <linux/hardirq.h>
38#include <linux/mmu_context.h>
39#include <asm/mmu.h>
40#include <linux/uaccess.h>
41#include <asm/pgtable.h>
42#include <asm/cpuinfo.h> 15#include <asm/cpuinfo.h>
43#include <asm/tlbflush.h> 16#include <asm/cacheflush.h>
44 17
45#ifndef CONFIG_MMU 18void arch_dma_prep_coherent(struct page *page, size_t size)
46/* I have to use dcache values because I can't relate on ram size */
47# define UNCACHED_SHADOW_MASK (cpuinfo.dcache_high - cpuinfo.dcache_base + 1)
48#endif
49
50/*
51 * Consistent memory allocators. Used for DMA devices that want to
52 * share uncached memory with the processor core.
53 * My crufty no-MMU approach is simple. In the HW platform we can optionally
54 * mirror the DDR up above the processor cacheable region. So, memory accessed
55 * in this mirror region will not be cached. It's alloced from the same
56 * pool as normal memory, but the handle we return is shifted up into the
57 * uncached region. This will no doubt cause big problems if memory allocated
58 * here is not also freed properly. -- JW
59 */
60void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
61 gfp_t gfp, unsigned long attrs)
62{ 19{
63 unsigned long order, vaddr; 20 phys_addr_t paddr = page_to_phys(page);
64 void *ret;
65 unsigned int i, err = 0;
66 struct page *page, *end;
67
68#ifdef CONFIG_MMU
69 phys_addr_t pa;
70 struct vm_struct *area;
71 unsigned long va;
72#endif
73
74 if (in_interrupt())
75 BUG();
76
77 /* Only allocate page size areas. */
78 size = PAGE_ALIGN(size);
79 order = get_order(size);
80
81 vaddr = __get_free_pages(gfp | __GFP_ZERO, order);
82 if (!vaddr)
83 return NULL;
84 21
85 /* 22 flush_dcache_range(paddr, paddr + size);
86 * we need to ensure that there are no cachelines in use, 23}
87 * or worse dirty in this area.
88 */
89 flush_dcache_range(virt_to_phys((void *)vaddr),
90 virt_to_phys((void *)vaddr) + size);
91 24
92#ifndef CONFIG_MMU 25#ifndef CONFIG_MMU
93 ret = (void *)vaddr; 26/*
94 /* 27 * Consistent memory allocators. Used for DMA devices that want to share
95 * Here's the magic! Note if the uncached shadow is not implemented, 28 * uncached memory with the processor core. My crufty no-MMU approach is
96 * it's up to the calling code to also test that condition and make 29 * simple. In the HW platform we can optionally mirror the DDR up above the
97 * other arranegments, such as manually flushing the cache and so on. 30 * processor cacheable region. So, memory accessed in this mirror region will
98 */ 31 * not be cached. It's alloced from the same pool as normal memory, but the
99# ifdef CONFIG_XILINX_UNCACHED_SHADOW 32 * handle we return is shifted up into the uncached region. This will no doubt
100 ret = (void *)((unsigned) ret | UNCACHED_SHADOW_MASK); 33 * cause big problems if memory allocated here is not also freed properly. -- JW
101# endif 34 *
102 if ((unsigned int)ret > cpuinfo.dcache_base && 35 * I have to use dcache values because I can't relate on ram size:
103 (unsigned int)ret < cpuinfo.dcache_high) 36 */
104 pr_warn("ERROR: Your cache coherent area is CACHED!!!\n"); 37#ifdef CONFIG_XILINX_UNCACHED_SHADOW
105 38#define UNCACHED_SHADOW_MASK (cpuinfo.dcache_high - cpuinfo.dcache_base + 1)
106 /* dma_handle is same as physical (shadowed) address */
107 *dma_handle = (dma_addr_t)ret;
108#else 39#else
109 /* Allocate some common virtual space to map the new pages. */ 40#define UNCACHED_SHADOW_MASK 0
110 area = get_vm_area(size, VM_ALLOC); 41#endif /* CONFIG_XILINX_UNCACHED_SHADOW */
111 if (!area) {
112 free_pages(vaddr, order);
113 return NULL;
114 }
115 va = (unsigned long) area->addr;
116 ret = (void *)va;
117
118 /* This gives us the real physical address of the first page. */
119 *dma_handle = pa = __virt_to_phys(vaddr);
120#endif
121
122 /*
123 * free wasted pages. We skip the first page since we know
124 * that it will have count = 1 and won't require freeing.
125 * We also mark the pages in use as reserved so that
126 * remap_page_range works.
127 */
128 page = virt_to_page(vaddr);
129 end = page + (1 << order);
130
131 split_page(page, order);
132
133 for (i = 0; i < size && err == 0; i += PAGE_SIZE) {
134#ifdef CONFIG_MMU
135 /* MS: This is the whole magic - use cache inhibit pages */
136 err = map_page(va + i, pa + i, _PAGE_KERNEL | _PAGE_NO_CACHE);
137#endif
138 42
139 SetPageReserved(page); 43void *uncached_kernel_address(void *ptr)
140 page++;
141 }
142
143 /* Free the otherwise unused pages. */
144 while (page < end) {
145 __free_page(page);
146 page++;
147 }
148
149 if (err) {
150 free_pages(vaddr, order);
151 return NULL;
152 }
153
154 return ret;
155}
156
157#ifdef CONFIG_MMU
158static pte_t *consistent_virt_to_pte(void *vaddr)
159{ 44{
160 unsigned long addr = (unsigned long)vaddr; 45 unsigned long addr = (unsigned long)ptr;
161
162 return pte_offset_kernel(pmd_offset(pgd_offset_k(addr), addr), addr);
163}
164
165long arch_dma_coherent_to_pfn(struct device *dev, void *vaddr,
166 dma_addr_t dma_addr)
167{
168 pte_t *ptep = consistent_virt_to_pte(vaddr);
169
170 if (pte_none(*ptep) || !pte_present(*ptep))
171 return 0;
172 46
173 return pte_pfn(*ptep); 47 addr |= UNCACHED_SHADOW_MASK;
48 if (addr > cpuinfo.dcache_base && addr < cpuinfo.dcache_high)
49 pr_warn("ERROR: Your cache coherent area is CACHED!!!\n");
50 return (void *)addr;
174} 51}
175#endif
176 52
177/* 53void *cached_kernel_address(void *ptr)
178 * free page(s) as defined by the above mapping.
179 */
180void arch_dma_free(struct device *dev, size_t size, void *vaddr,
181 dma_addr_t dma_addr, unsigned long attrs)
182{ 54{
183 struct page *page; 55 unsigned long addr = (unsigned long)ptr;
184
185 if (in_interrupt())
186 BUG();
187
188 size = PAGE_ALIGN(size);
189
190#ifndef CONFIG_MMU
191 /* Clear SHADOW_MASK bit in address, and free as per usual */
192# ifdef CONFIG_XILINX_UNCACHED_SHADOW
193 vaddr = (void *)((unsigned)vaddr & ~UNCACHED_SHADOW_MASK);
194# endif
195 page = virt_to_page(vaddr);
196
197 do {
198 __free_reserved_page(page);
199 page++;
200 } while (size -= PAGE_SIZE);
201#else
202 do {
203 pte_t *ptep = consistent_virt_to_pte(vaddr);
204 unsigned long pfn;
205
206 if (!pte_none(*ptep) && pte_present(*ptep)) {
207 pfn = pte_pfn(*ptep);
208 pte_clear(&init_mm, (unsigned int)vaddr, ptep);
209 if (pfn_valid(pfn)) {
210 page = pfn_to_page(pfn);
211 __free_reserved_page(page);
212 }
213 }
214 vaddr += PAGE_SIZE;
215 } while (size -= PAGE_SIZE);
216 56
217 /* flush tlb */ 57 return (void *)(addr & ~UNCACHED_SHADOW_MASK);
218 flush_tlb_all();
219#endif
220} 58}
59#endif /* CONFIG_MMU */