forked from beagleboard/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge tag 'xtensa-20161219' of git://github.com/jcmvbkbc/linux-xtensa
Pull Xtensa updates from Max Filippov: - enable HAVE_DMA_CONTIGUOUS, configure shared DMA pool reservation in kc705 DTS - update xtensa DMA-related Documentation/features entries - clean up arch/xtensa/kernel/setup.c: move S32C1I self-test out of it, remove unused declarations, fix screen_info definition * tag 'xtensa-20161219' of git://github.com/jcmvbkbc/linux-xtensa: xtensa: update DMA-related Documentation/features entries xtensa: configure shared DMA pool reservation in kc705 DTS xtensa: enable HAVE_DMA_CONTIGUOUS xtensa: move S32C1I self-test to a separate file xtensa: fix screen_info, clean up unused declarations in setup.c
- Loading branch information
Showing
10 changed files
with
176 additions
and
135 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,5 +36,5 @@ | |
| um: | TODO | | ||
| unicore32: | TODO | | ||
| x86: | ok | | ||
| xtensa: | TODO | | ||
| xtensa: | ok | | ||
----------------------- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,5 +36,5 @@ | |
| um: | TODO | | ||
| unicore32: | TODO | | ||
| x86: | ok | | ||
| xtensa: | TODO | | ||
| xtensa: | ok | | ||
----------------------- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
* Joe Taylor <[email protected], [email protected]> | ||
*/ | ||
|
||
#include <linux/dma-contiguous.h> | ||
#include <linux/gfp.h> | ||
#include <linux/highmem.h> | ||
#include <linux/mm.h> | ||
|
@@ -146,18 +147,27 @@ static void *xtensa_dma_alloc(struct device *dev, size_t size, | |
{ | ||
unsigned long ret; | ||
unsigned long uncached = 0; | ||
unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; | ||
struct page *page = NULL; | ||
|
||
/* ignore region speicifiers */ | ||
|
||
flag &= ~(__GFP_DMA | __GFP_HIGHMEM); | ||
|
||
if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) | ||
flag |= GFP_DMA; | ||
ret = (unsigned long)__get_free_pages(flag, get_order(size)); | ||
|
||
if (ret == 0) | ||
if (gfpflags_allow_blocking(flag)) | ||
page = dma_alloc_from_contiguous(dev, count, get_order(size)); | ||
|
||
if (!page) | ||
page = alloc_pages(flag, get_order(size)); | ||
|
||
if (!page) | ||
return NULL; | ||
|
||
ret = (unsigned long)page_address(page); | ||
|
||
/* We currently don't support coherent memory outside KSEG */ | ||
|
||
BUG_ON(ret < XCHAL_KSEG_CACHED_VADDR || | ||
|
@@ -170,16 +180,19 @@ static void *xtensa_dma_alloc(struct device *dev, size_t size, | |
return (void *)uncached; | ||
} | ||
|
||
static void xtensa_dma_free(struct device *hwdev, size_t size, void *vaddr, | ||
static void xtensa_dma_free(struct device *dev, size_t size, void *vaddr, | ||
dma_addr_t dma_handle, unsigned long attrs) | ||
{ | ||
unsigned long addr = (unsigned long)vaddr + | ||
XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR; | ||
struct page *page = virt_to_page(addr); | ||
unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; | ||
|
||
BUG_ON(addr < XCHAL_KSEG_CACHED_VADDR || | ||
addr > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1); | ||
|
||
free_pages(addr, get_order(size)); | ||
if (!dma_release_from_contiguous(dev, page, count)) | ||
__free_pages(page, get_order(size)); | ||
} | ||
|
||
static dma_addr_t xtensa_map_page(struct device *dev, struct page *page, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
/* | ||
* S32C1I selftest. | ||
* | ||
* This file is subject to the terms and conditions of the GNU General Public | ||
* License. See the file "COPYING" in the main directory of this archive | ||
* for more details. | ||
* | ||
* Copyright (C) 2016 Cadence Design Systems Inc. | ||
*/ | ||
|
||
#include <linux/init.h> | ||
#include <linux/kernel.h> | ||
|
||
#include <asm/traps.h> | ||
|
||
#if XCHAL_HAVE_S32C1I | ||
|
||
static int __initdata rcw_word, rcw_probe_pc, rcw_exc; | ||
|
||
/* | ||
* Basic atomic compare-and-swap, that records PC of S32C1I for probing. | ||
* | ||
* If *v == cmp, set *v = set. Return previous *v. | ||
*/ | ||
static inline int probed_compare_swap(int *v, int cmp, int set) | ||
{ | ||
int tmp; | ||
|
||
__asm__ __volatile__( | ||
" movi %1, 1f\n" | ||
" s32i %1, %4, 0\n" | ||
" wsr %2, scompare1\n" | ||
"1: s32c1i %0, %3, 0\n" | ||
: "=a" (set), "=&a" (tmp) | ||
: "a" (cmp), "a" (v), "a" (&rcw_probe_pc), "0" (set) | ||
: "memory" | ||
); | ||
return set; | ||
} | ||
|
||
/* Handle probed exception */ | ||
|
||
static void __init do_probed_exception(struct pt_regs *regs, | ||
unsigned long exccause) | ||
{ | ||
if (regs->pc == rcw_probe_pc) { /* exception on s32c1i ? */ | ||
regs->pc += 3; /* skip the s32c1i instruction */ | ||
rcw_exc = exccause; | ||
} else { | ||
do_unhandled(regs, exccause); | ||
} | ||
} | ||
|
||
/* Simple test of S32C1I (soc bringup assist) */ | ||
|
||
static int __init check_s32c1i(void) | ||
{ | ||
int n, cause1, cause2; | ||
void *handbus, *handdata, *handaddr; /* temporarily saved handlers */ | ||
|
||
rcw_probe_pc = 0; | ||
handbus = trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, | ||
do_probed_exception); | ||
handdata = trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, | ||
do_probed_exception); | ||
handaddr = trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, | ||
do_probed_exception); | ||
|
||
/* First try an S32C1I that does not store: */ | ||
rcw_exc = 0; | ||
rcw_word = 1; | ||
n = probed_compare_swap(&rcw_word, 0, 2); | ||
cause1 = rcw_exc; | ||
|
||
/* took exception? */ | ||
if (cause1 != 0) { | ||
/* unclean exception? */ | ||
if (n != 2 || rcw_word != 1) | ||
panic("S32C1I exception error"); | ||
} else if (rcw_word != 1 || n != 1) { | ||
panic("S32C1I compare error"); | ||
} | ||
|
||
/* Then an S32C1I that stores: */ | ||
rcw_exc = 0; | ||
rcw_word = 0x1234567; | ||
n = probed_compare_swap(&rcw_word, 0x1234567, 0xabcde); | ||
cause2 = rcw_exc; | ||
|
||
if (cause2 != 0) { | ||
/* unclean exception? */ | ||
if (n != 0xabcde || rcw_word != 0x1234567) | ||
panic("S32C1I exception error (b)"); | ||
} else if (rcw_word != 0xabcde || n != 0x1234567) { | ||
panic("S32C1I store error"); | ||
} | ||
|
||
/* Verify consistency of exceptions: */ | ||
if (cause1 || cause2) { | ||
pr_warn("S32C1I took exception %d, %d\n", cause1, cause2); | ||
/* If emulation of S32C1I upon bus error gets implemented, | ||
* we can get rid of this panic for single core (not SMP) | ||
*/ | ||
panic("S32C1I exceptions not currently supported"); | ||
} | ||
if (cause1 != cause2) | ||
panic("inconsistent S32C1I exceptions"); | ||
|
||
trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, handbus); | ||
trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, handdata); | ||
trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, handaddr); | ||
return 0; | ||
} | ||
|
||
#else /* XCHAL_HAVE_S32C1I */ | ||
|
||
/* This condition should not occur with a commercially deployed processor. | ||
* Display reminder for early engr test or demo chips / FPGA bitstreams | ||
*/ | ||
static int __init check_s32c1i(void) | ||
{ | ||
pr_warn("Processor configuration lacks atomic compare-and-swap support!\n"); | ||
return 0; | ||
} | ||
|
||
#endif /* XCHAL_HAVE_S32C1I */ | ||
|
||
early_initcall(check_s32c1i); |
Oops, something went wrong.