Blame view

kernel/linux-imx6_3.14.28/arch/blackfin/lib/ins.S 2.57 KB
6b13f685e   김민수   BSP 최초 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  /*
   * arch/blackfin/lib/ins.S - ins{bwl} using hardware loops
   *
   * Copyright 2004-2008 Analog Devices Inc.
   * Copyright (C) 2005 Bas Vermeulen, BuyWays BV <bas@buyways.nl>
   * Licensed under the GPL-2 or later.
   */
  
  #include <linux/linkage.h>
  #include <asm/blackfin.h>
  
  .align 2
  
  #ifdef CONFIG_IPIPE
  # define DO_CLI \
  	[--sp] = rets; \
  	[--sp] = (P5:0); \
  	sp += -12; \
  	call ___ipipe_disable_root_irqs_hw; \
  	sp += 12; \
  	(P5:0) = [sp++];
  # define CLI_INNER_NOP
  #else
  # define DO_CLI cli R3;
  # define CLI_INNER_NOP nop; nop; nop;
  #endif
  
  #ifdef CONFIG_IPIPE
  # define DO_STI \
  	sp += -12; \
  	call ___ipipe_enable_root_irqs_hw; \
  	sp += 12; \
  2:	rets = [sp++];
  #else
  # define DO_STI 2: sti R3;
  #endif
  
  #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
  # define CLI_OUTER DO_CLI;
  # define STI_OUTER DO_STI;
  # define CLI_INNER 1:
  # if ANOMALY_05000416
  #  define STI_INNER nop; 2: nop;
  # else
  #  define STI_INNER 2:
  # endif
  #else
  # define CLI_OUTER
  # define STI_OUTER
  # define CLI_INNER 1: DO_CLI; CLI_INNER_NOP;
  # define STI_INNER DO_STI;
  #endif
  
  /*
   * Reads on the Blackfin are speculative. In Blackfin terms, this means they
   * can be interrupted at any time (even after they have been issued on to the
   * external bus), and re-issued after the interrupt occurs.
   *
   * If a FIFO is sitting on the end of the read, it will see two reads,
   * when the core only sees one. The FIFO receives the read which is cancelled,
   * and not delivered to the core.
   *
   * To solve this, interrupts are turned off before reads occur to I/O space.
   * There are 3 versions of all these functions
   *  - turns interrupts off every read (higher overhead, but lower latency)
   *  - turns interrupts off every loop (low overhead, but longer latency)
   *  - DMA version, which do not suffer from this issue. DMA versions have
   *      different name (prefixed by dma_ ), and are located in
   *      ../kernel/bfin_dma.c
   * Using the dma related functions are recommended for transferring large
   * buffers in/out of FIFOs.
   */
  
  #define COMMON_INS(func, ops) \
  ENTRY(_ins##func) \
  	P0 = R0;	/* P0 = port */ \
  	CLI_OUTER;	/* 3 instructions before first read access */ \
  	P1 = R1;	/* P1 = address */ \
  	P2 = R2;	/* P2 = count */ \
  	SSYNC; \
   \
  	LSETUP(1f, 2f) LC0 = P2; \
  	CLI_INNER; \
  	ops; \
  	STI_INNER; \
   \
  	STI_OUTER; \
  	RTS; \
  ENDPROC(_ins##func)
  
  COMMON_INS(l, \
  	R0 = [P0]; \
  	[P1++] = R0; \
  )
  
  COMMON_INS(w, \
  	R0 = W[P0]; \
  	W[P1++] = R0; \
  )
  
  COMMON_INS(w_8, \
  	R0 = W[P0]; \
  	B[P1++] = R0; \
  	R0 = R0 >> 8; \
  	B[P1++] = R0; \
  )
  
  COMMON_INS(b, \
  	R0 = B[P0]; \
  	B[P1++] = R0; \
  )
  
  COMMON_INS(l_16, \
  	R0 = [P0]; \
  	W[P1++] = R0; \
  	R0 = R0 >> 16; \
  	W[P1++] = R0; \
  )