Linux 3.13-rc4
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.15 (GNU/Linux) iQEcBAABAgAGBQJSrhGrAAoJEHm+PkMAQRiGsNoH/jIK3CsQ2lbW7yRLXmfgtbzz i2Kep6D4SDvmaLpLYOVC8xNYTiE8jtTbSXHomwP5wMZ63MQDhBfnEWsEWqeZ9+D9 3Q46p0QWuoBgYu2VGkoxTfygkT6hhSpwWIi3SeImbY4fg57OHiUil/+YGhORM4Qc K4549OCTY3sIrgmWL77gzqjRUo+pQ4C73NKqZ3+5nlOmYBZC1yugk8mFwEpQkwhK 4NRNU760Fo+XIht/bINqRiPMddzC15p0mxvJy3cDW8bZa1tFSS9SB7AQUULBbcHL +2dFlFOEb5SV1sNiNPrJ0W+h2qUh2e7kPB0F8epaBppgbwVdyQoC2u4uuLV2ZN0= =lI2r -----END PGP SIGNATURE----- Merge tag 'v3.13-rc4' into perf/core Merge Linux 3.13-rc4, to refresh this branch with the latest fixes. Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
fe361cfcf4
5
CREDITS
5
CREDITS
|
@ -655,6 +655,11 @@ S: Stanford University
|
|||
S: Stanford, California 94305
|
||||
S: USA
|
||||
|
||||
N: Carlos Chinea
|
||||
E: carlos.chinea@nokia.com
|
||||
E: cch.devel@gmail.com
|
||||
D: Author of HSI Subsystem
|
||||
|
||||
N: Randolph Chung
|
||||
E: tausq@debian.org
|
||||
D: Linux/PA-RISC hacker
|
||||
|
|
|
@ -196,13 +196,6 @@ chmod 0644 /dev/cpu/microcode
|
|||
as root before you can use this. You'll probably also want to
|
||||
get the user-space microcode_ctl utility to use with this.
|
||||
|
||||
Powertweak
|
||||
----------
|
||||
|
||||
If you are running v0.1.17 or earlier, you should upgrade to
|
||||
version v0.99.0 or higher. Running old versions may cause problems
|
||||
with programs using shared memory.
|
||||
|
||||
udev
|
||||
----
|
||||
udev is a userspace application for populating /dev dynamically with
|
||||
|
@ -366,10 +359,6 @@ Intel P6 microcode
|
|||
------------------
|
||||
o <http://www.urbanmyth.org/microcode/>
|
||||
|
||||
Powertweak
|
||||
----------
|
||||
o <http://powertweak.sourceforge.net/>
|
||||
|
||||
udev
|
||||
----
|
||||
o <http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html>
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
</sect1>
|
||||
<sect1><title>Wait queues and Wake events</title>
|
||||
!Iinclude/linux/wait.h
|
||||
!Ekernel/wait.c
|
||||
!Ekernel/sched/wait.c
|
||||
</sect1>
|
||||
<sect1><title>High-resolution timers</title>
|
||||
!Iinclude/linux/ktime.h
|
||||
|
|
|
@ -73,7 +73,8 @@ range from zero to the maximal number of valid planes for the currently active
|
|||
format. For the single-planar API, applications must set <structfield> plane
|
||||
</structfield> to zero. Additional flags may be posted in the <structfield>
|
||||
flags </structfield> field. Refer to a manual for open() for details.
|
||||
Currently only O_CLOEXEC is supported. All other fields must be set to zero.
|
||||
Currently only O_CLOEXEC, O_RDONLY, O_WRONLY, and O_RDWR are supported. All
|
||||
other fields must be set to zero.
|
||||
In the case of multi-planar API, every plane is exported separately using
|
||||
multiple <constant> VIDIOC_EXPBUF </constant> calls. </para>
|
||||
|
||||
|
@ -170,8 +171,9 @@ multi-planar API. Otherwise this value must be set to zero. </entry>
|
|||
<entry>__u32</entry>
|
||||
<entry><structfield>flags</structfield></entry>
|
||||
<entry>Flags for the newly created file, currently only <constant>
|
||||
O_CLOEXEC </constant> is supported, refer to the manual of open() for more
|
||||
details.</entry>
|
||||
O_CLOEXEC </constant>, <constant>O_RDONLY</constant>, <constant>O_WRONLY
|
||||
</constant>, and <constant>O_RDWR</constant> are supported, refer to the manual
|
||||
of open() for more details.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__s32</entry>
|
||||
|
|
|
@ -0,0 +1,574 @@
|
|||
========================================
|
||||
GENERIC ASSOCIATIVE ARRAY IMPLEMENTATION
|
||||
========================================
|
||||
|
||||
Contents:
|
||||
|
||||
- Overview.
|
||||
|
||||
- The public API.
|
||||
- Edit script.
|
||||
- Operations table.
|
||||
- Manipulation functions.
|
||||
- Access functions.
|
||||
- Index key form.
|
||||
|
||||
- Internal workings.
|
||||
- Basic internal tree layout.
|
||||
- Shortcuts.
|
||||
- Splitting and collapsing nodes.
|
||||
- Non-recursive iteration.
|
||||
- Simultaneous alteration and iteration.
|
||||
|
||||
|
||||
========
|
||||
OVERVIEW
|
||||
========
|
||||
|
||||
This associative array implementation is an object container with the following
|
||||
properties:
|
||||
|
||||
(1) Objects are opaque pointers. The implementation does not care where they
|
||||
point (if anywhere) or what they point to (if anything).
|
||||
|
||||
[!] NOTE: Pointers to objects _must_ be zero in the least significant bit.
|
||||
|
||||
(2) Objects do not need to contain linkage blocks for use by the array. This
|
||||
permits an object to be located in multiple arrays simultaneously.
|
||||
Rather, the array is made up of metadata blocks that point to objects.
|
||||
|
||||
(3) Objects require index keys to locate them within the array.
|
||||
|
||||
(4) Index keys must be unique. Inserting an object with the same key as one
|
||||
already in the array will replace the old object.
|
||||
|
||||
(5) Index keys can be of any length and can be of different lengths.
|
||||
|
||||
(6) Index keys should encode the length early on, before any variation due to
|
||||
length is seen.
|
||||
|
||||
(7) Index keys can include a hash to scatter objects throughout the array.
|
||||
|
||||
(8) The array can iterated over. The objects will not necessarily come out in
|
||||
key order.
|
||||
|
||||
(9) The array can be iterated over whilst it is being modified, provided the
|
||||
RCU readlock is being held by the iterator. Note, however, under these
|
||||
circumstances, some objects may be seen more than once. If this is a
|
||||
problem, the iterator should lock against modification. Objects will not
|
||||
be missed, however, unless deleted.
|
||||
|
||||
(10) Objects in the array can be looked up by means of their index key.
|
||||
|
||||
(11) Objects can be looked up whilst the array is being modified, provided the
|
||||
RCU readlock is being held by the thread doing the look up.
|
||||
|
||||
The implementation uses a tree of 16-pointer nodes internally that are indexed
|
||||
on each level by nibbles from the index key in the same manner as in a radix
|
||||
tree. To improve memory efficiency, shortcuts can be emplaced to skip over
|
||||
what would otherwise be a series of single-occupancy nodes. Further, nodes
|
||||
pack leaf object pointers into spare space in the node rather than making an
|
||||
extra branch until as such time an object needs to be added to a full node.
|
||||
|
||||
|
||||
==============
|
||||
THE PUBLIC API
|
||||
==============
|
||||
|
||||
The public API can be found in <linux/assoc_array.h>. The associative array is
|
||||
rooted on the following structure:
|
||||
|
||||
struct assoc_array {
|
||||
...
|
||||
};
|
||||
|
||||
The code is selected by enabling CONFIG_ASSOCIATIVE_ARRAY.
|
||||
|
||||
|
||||
EDIT SCRIPT
|
||||
-----------
|
||||
|
||||
The insertion and deletion functions produce an 'edit script' that can later be
|
||||
applied to effect the changes without risking ENOMEM. This retains the
|
||||
preallocated metadata blocks that will be installed in the internal tree and
|
||||
keeps track of the metadata blocks that will be removed from the tree when the
|
||||
script is applied.
|
||||
|
||||
This is also used to keep track of dead blocks and dead objects after the
|
||||
script has been applied so that they can be freed later. The freeing is done
|
||||
after an RCU grace period has passed - thus allowing access functions to
|
||||
proceed under the RCU read lock.
|
||||
|
||||
The script appears as outside of the API as a pointer of the type:
|
||||
|
||||
struct assoc_array_edit;
|
||||
|
||||
There are two functions for dealing with the script:
|
||||
|
||||
(1) Apply an edit script.
|
||||
|
||||
void assoc_array_apply_edit(struct assoc_array_edit *edit);
|
||||
|
||||
This will perform the edit functions, interpolating various write barriers
|
||||
to permit accesses under the RCU read lock to continue. The edit script
|
||||
will then be passed to call_rcu() to free it and any dead stuff it points
|
||||
to.
|
||||
|
||||
(2) Cancel an edit script.
|
||||
|
||||
void assoc_array_cancel_edit(struct assoc_array_edit *edit);
|
||||
|
||||
This frees the edit script and all preallocated memory immediately. If
|
||||
this was for insertion, the new object is _not_ released by this function,
|
||||
but must rather be released by the caller.
|
||||
|
||||
These functions are guaranteed not to fail.
|
||||
|
||||
|
||||
OPERATIONS TABLE
|
||||
----------------
|
||||
|
||||
Various functions take a table of operations:
|
||||
|
||||
struct assoc_array_ops {
|
||||
...
|
||||
};
|
||||
|
||||
This points to a number of methods, all of which need to be provided:
|
||||
|
||||
(1) Get a chunk of index key from caller data:
|
||||
|
||||
unsigned long (*get_key_chunk)(const void *index_key, int level);
|
||||
|
||||
This should return a chunk of caller-supplied index key starting at the
|
||||
*bit* position given by the level argument. The level argument will be a
|
||||
multiple of ASSOC_ARRAY_KEY_CHUNK_SIZE and the function should return
|
||||
ASSOC_ARRAY_KEY_CHUNK_SIZE bits. No error is possible.
|
||||
|
||||
|
||||
(2) Get a chunk of an object's index key.
|
||||
|
||||
unsigned long (*get_object_key_chunk)(const void *object, int level);
|
||||
|
||||
As the previous function, but gets its data from an object in the array
|
||||
rather than from a caller-supplied index key.
|
||||
|
||||
|
||||
(3) See if this is the object we're looking for.
|
||||
|
||||
bool (*compare_object)(const void *object, const void *index_key);
|
||||
|
||||
Compare the object against an index key and return true if it matches and
|
||||
false if it doesn't.
|
||||
|
||||
|
||||
(4) Diff the index keys of two objects.
|
||||
|
||||
int (*diff_objects)(const void *object, const void *index_key);
|
||||
|
||||
Return the bit position at which the index key of the specified object
|
||||
differs from the given index key or -1 if they are the same.
|
||||
|
||||
|
||||
(5) Free an object.
|
||||
|
||||
void (*free_object)(void *object);
|
||||
|
||||
Free the specified object. Note that this may be called an RCU grace
|
||||
period after assoc_array_apply_edit() was called, so synchronize_rcu() may
|
||||
be necessary on module unloading.
|
||||
|
||||
|
||||
MANIPULATION FUNCTIONS
|
||||
----------------------
|
||||
|
||||
There are a number of functions for manipulating an associative array:
|
||||
|
||||
(1) Initialise an associative array.
|
||||
|
||||
void assoc_array_init(struct assoc_array *array);
|
||||
|
||||
This initialises the base structure for an associative array. It can't
|
||||
fail.
|
||||
|
||||
|
||||
(2) Insert/replace an object in an associative array.
|
||||
|
||||
struct assoc_array_edit *
|
||||
assoc_array_insert(struct assoc_array *array,
|
||||
const struct assoc_array_ops *ops,
|
||||
const void *index_key,
|
||||
void *object);
|
||||
|
||||
This inserts the given object into the array. Note that the least
|
||||
significant bit of the pointer must be zero as it's used to type-mark
|
||||
pointers internally.
|
||||
|
||||
If an object already exists for that key then it will be replaced with the
|
||||
new object and the old one will be freed automatically.
|
||||
|
||||
The index_key argument should hold index key information and is
|
||||
passed to the methods in the ops table when they are called.
|
||||
|
||||
This function makes no alteration to the array itself, but rather returns
|
||||
an edit script that must be applied. -ENOMEM is returned in the case of
|
||||
an out-of-memory error.
|
||||
|
||||
The caller should lock exclusively against other modifiers of the array.
|
||||
|
||||
|
||||
(3) Delete an object from an associative array.
|
||||
|
||||
struct assoc_array_edit *
|
||||
assoc_array_delete(struct assoc_array *array,
|
||||
const struct assoc_array_ops *ops,
|
||||
const void *index_key);
|
||||
|
||||
This deletes an object that matches the specified data from the array.
|
||||
|
||||
The index_key argument should hold index key information and is
|
||||
passed to the methods in the ops table when they are called.
|
||||
|
||||
This function makes no alteration to the array itself, but rather returns
|
||||
an edit script that must be applied. -ENOMEM is returned in the case of
|
||||
an out-of-memory error. NULL will be returned if the specified object is
|
||||
not found within the array.
|
||||
|
||||
The caller should lock exclusively against other modifiers of the array.
|
||||
|
||||
|
||||
(4) Delete all objects from an associative array.
|
||||
|
||||
struct assoc_array_edit *
|
||||
assoc_array_clear(struct assoc_array *array,
|
||||
const struct assoc_array_ops *ops);
|
||||
|
||||
This deletes all the objects from an associative array and leaves it
|
||||
completely empty.
|
||||
|
||||
This function makes no alteration to the array itself, but rather returns
|
||||
an edit script that must be applied. -ENOMEM is returned in the case of
|
||||
an out-of-memory error.
|
||||
|
||||
The caller should lock exclusively against other modifiers of the array.
|
||||
|
||||
|
||||
(5) Destroy an associative array, deleting all objects.
|
||||
|
||||
void assoc_array_destroy(struct assoc_array *array,
|
||||
const struct assoc_array_ops *ops);
|
||||
|
||||
This destroys the contents of the associative array and leaves it
|
||||
completely empty. It is not permitted for another thread to be traversing
|
||||
the array under the RCU read lock at the same time as this function is
|
||||
destroying it as no RCU deferral is performed on memory release -
|
||||
something that would require memory to be allocated.
|
||||
|
||||
The caller should lock exclusively against other modifiers and accessors
|
||||
of the array.
|
||||
|
||||
|
||||
(6) Garbage collect an associative array.
|
||||
|
||||
int assoc_array_gc(struct assoc_array *array,
|
||||
const struct assoc_array_ops *ops,
|
||||
bool (*iterator)(void *object, void *iterator_data),
|
||||
void *iterator_data);
|
||||
|
||||
This iterates over the objects in an associative array and passes each one
|
||||
to iterator(). If iterator() returns true, the object is kept. If it
|
||||
returns false, the object will be freed. If the iterator() function
|
||||
returns true, it must perform any appropriate refcount incrementing on the
|
||||
object before returning.
|
||||
|
||||
The internal tree will be packed down if possible as part of the iteration
|
||||
to reduce the number of nodes in it.
|
||||
|
||||
The iterator_data is passed directly to iterator() and is otherwise
|
||||
ignored by the function.
|
||||
|
||||
The function will return 0 if successful and -ENOMEM if there wasn't
|
||||
enough memory.
|
||||
|
||||
It is possible for other threads to iterate over or search the array under
|
||||
the RCU read lock whilst this function is in progress. The caller should
|
||||
lock exclusively against other modifiers of the array.
|
||||
|
||||
|
||||
ACCESS FUNCTIONS
|
||||
----------------
|
||||
|
||||
There are two functions for accessing an associative array:
|
||||
|
||||
(1) Iterate over all the objects in an associative array.
|
||||
|
||||
int assoc_array_iterate(const struct assoc_array *array,
|
||||
int (*iterator)(const void *object,
|
||||
void *iterator_data),
|
||||
void *iterator_data);
|
||||
|
||||
This passes each object in the array to the iterator callback function.
|
||||
iterator_data is private data for that function.
|
||||
|
||||
This may be used on an array at the same time as the array is being
|
||||
modified, provided the RCU read lock is held. Under such circumstances,
|
||||
it is possible for the iteration function to see some objects twice. If
|
||||
this is a problem, then modification should be locked against. The
|
||||
iteration algorithm should not, however, miss any objects.
|
||||
|
||||
The function will return 0 if no objects were in the array or else it will
|
||||
return the result of the last iterator function called. Iteration stops
|
||||
immediately if any call to the iteration function results in a non-zero
|
||||
return.
|
||||
|
||||
|
||||
(2) Find an object in an associative array.
|
||||
|
||||
void *assoc_array_find(const struct assoc_array *array,
|
||||
const struct assoc_array_ops *ops,
|
||||
const void *index_key);
|
||||
|
||||
This walks through the array's internal tree directly to the object
|
||||
specified by the index key..
|
||||
|
||||
This may be used on an array at the same time as the array is being
|
||||
modified, provided the RCU read lock is held.
|
||||
|
||||
The function will return the object if found (and set *_type to the object
|
||||
type) or will return NULL if the object was not found.
|
||||
|
||||
|
||||
INDEX KEY FORM
|
||||
--------------
|
||||
|
||||
The index key can be of any form, but since the algorithms aren't told how long
|
||||
the key is, it is strongly recommended that the index key includes its length
|
||||
very early on before any variation due to the length would have an effect on
|
||||
comparisons.
|
||||
|
||||
This will cause leaves with different length keys to scatter away from each
|
||||
other - and those with the same length keys to cluster together.
|
||||
|
||||
It is also recommended that the index key begin with a hash of the rest of the
|
||||
key to maximise scattering throughout keyspace.
|
||||
|
||||
The better the scattering, the wider and lower the internal tree will be.
|
||||
|
||||
Poor scattering isn't too much of a problem as there are shortcuts and nodes
|
||||
can contain mixtures of leaves and metadata pointers.
|
||||
|
||||
The index key is read in chunks of machine word. Each chunk is subdivided into
|
||||
one nibble (4 bits) per level, so on a 32-bit CPU this is good for 8 levels and
|
||||
on a 64-bit CPU, 16 levels. Unless the scattering is really poor, it is
|
||||
unlikely that more than one word of any particular index key will have to be
|
||||
used.
|
||||
|
||||
|
||||
=================
|
||||
INTERNAL WORKINGS
|
||||
=================
|
||||
|
||||
The associative array data structure has an internal tree. This tree is
|
||||
constructed of two types of metadata blocks: nodes and shortcuts.
|
||||
|
||||
A node is an array of slots. Each slot can contain one of four things:
|
||||
|
||||
(*) A NULL pointer, indicating that the slot is empty.
|
||||
|
||||
(*) A pointer to an object (a leaf).
|
||||
|
||||
(*) A pointer to a node at the next level.
|
||||
|
||||
(*) A pointer to a shortcut.
|
||||
|
||||
|
||||
BASIC INTERNAL TREE LAYOUT
|
||||
--------------------------
|
||||
|
||||
Ignoring shortcuts for the moment, the nodes form a multilevel tree. The index
|
||||
key space is strictly subdivided by the nodes in the tree and nodes occur on
|
||||
fixed levels. For example:
|
||||
|
||||
Level: 0 1 2 3
|
||||
=============== =============== =============== ===============
|
||||
NODE D
|
||||
NODE B NODE C +------>+---+
|
||||
+------>+---+ +------>+---+ | | 0 |
|
||||
NODE A | | 0 | | | 0 | | +---+
|
||||
+---+ | +---+ | +---+ | : :
|
||||
| 0 | | : : | : : | +---+
|
||||
+---+ | +---+ | +---+ | | f |
|
||||
| 1 |---+ | 3 |---+ | 7 |---+ +---+
|
||||
+---+ +---+ +---+
|
||||
: : : : | 8 |---+
|
||||
+---+ +---+ +---+ | NODE E
|
||||
| e |---+ | f | : : +------>+---+
|
||||
+---+ | +---+ +---+ | 0 |
|
||||
| f | | | f | +---+
|
||||
+---+ | +---+ : :
|
||||
| NODE F +---+
|
||||
+------>+---+ | f |
|
||||
| 0 | NODE G +---+
|
||||
+---+ +------>+---+
|
||||
: : | | 0 |
|
||||
+---+ | +---+
|
||||
| 6 |---+ : :
|
||||
+---+ +---+
|
||||
: : | f |
|
||||
+---+ +---+
|
||||
| f |
|
||||
+---+
|
||||
|
||||
In the above example, there are 7 nodes (A-G), each with 16 slots (0-f).
|
||||
Assuming no other meta data nodes in the tree, the key space is divided thusly:
|
||||
|
||||
KEY PREFIX NODE
|
||||
========== ====
|
||||
137* D
|
||||
138* E
|
||||
13[0-69-f]* C
|
||||
1[0-24-f]* B
|
||||
e6* G
|
||||
e[0-57-f]* F
|
||||
[02-df]* A
|
||||
|
||||
So, for instance, keys with the following example index keys will be found in
|
||||
the appropriate nodes:
|
||||
|
||||
INDEX KEY PREFIX NODE
|
||||
=============== ======= ====
|
||||
13694892892489 13 C
|
||||
13795289025897 137 D
|
||||
13889dde88793 138 E
|
||||
138bbb89003093 138 E
|
||||
1394879524789 12 C
|
||||
1458952489 1 B
|
||||
9431809de993ba - A
|
||||
b4542910809cd - A
|
||||
e5284310def98 e F
|
||||
e68428974237 e6 G
|
||||
e7fffcbd443 e F
|
||||
f3842239082 - A
|
||||
|
||||
To save memory, if a node can hold all the leaves in its portion of keyspace,
|
||||
then the node will have all those leaves in it and will not have any metadata
|
||||
pointers - even if some of those leaves would like to be in the same slot.
|
||||
|
||||
A node can contain a heterogeneous mix of leaves and metadata pointers.
|
||||
Metadata pointers must be in the slots that match their subdivisions of key
|
||||
space. The leaves can be in any slot not occupied by a metadata pointer. It
|
||||
is guaranteed that none of the leaves in a node will match a slot occupied by a
|
||||
metadata pointer. If the metadata pointer is there, any leaf whose key matches
|
||||
the metadata key prefix must be in the subtree that the metadata pointer points
|
||||
to.
|
||||
|
||||
In the above example list of index keys, node A will contain:
|
||||
|
||||
SLOT CONTENT INDEX KEY (PREFIX)
|
||||
==== =============== ==================
|
||||
1 PTR TO NODE B 1*
|
||||
any LEAF 9431809de993ba
|
||||
any LEAF b4542910809cd
|
||||
e PTR TO NODE F e*
|
||||
any LEAF f3842239082
|
||||
|
||||
and node B:
|
||||
|
||||
3 PTR TO NODE C 13*
|
||||
any LEAF 1458952489
|
||||
|
||||
|
||||
SHORTCUTS
|
||||
---------
|
||||
|
||||
Shortcuts are metadata records that jump over a piece of keyspace. A shortcut
|
||||
is a replacement for a series of single-occupancy nodes ascending through the
|
||||
levels. Shortcuts exist to save memory and to speed up traversal.
|
||||
|
||||
It is possible for the root of the tree to be a shortcut - say, for example,
|
||||
the tree contains at least 17 nodes all with key prefix '1111'. The insertion
|
||||
algorithm will insert a shortcut to skip over the '1111' keyspace in a single
|
||||
bound and get to the fourth level where these actually become different.
|
||||
|
||||
|
||||
SPLITTING AND COLLAPSING NODES
|
||||
------------------------------
|
||||
|
||||
Each node has a maximum capacity of 16 leaves and metadata pointers. If the
|
||||
insertion algorithm finds that it is trying to insert a 17th object into a
|
||||
node, that node will be split such that at least two leaves that have a common
|
||||
key segment at that level end up in a separate node rooted on that slot for
|
||||
that common key segment.
|
||||
|
||||
If the leaves in a full node and the leaf that is being inserted are
|
||||
sufficiently similar, then a shortcut will be inserted into the tree.
|
||||
|
||||
When the number of objects in the subtree rooted at a node falls to 16 or
|
||||
fewer, then the subtree will be collapsed down to a single node - and this will
|
||||
ripple towards the root if possible.
|
||||
|
||||
|
||||
NON-RECURSIVE ITERATION
|
||||
-----------------------
|
||||
|
||||
Each node and shortcut contains a back pointer to its parent and the number of
|
||||
slot in that parent that points to it. None-recursive iteration uses these to
|
||||
proceed rootwards through the tree, going to the parent node, slot N + 1 to
|
||||
make sure progress is made without the need for a stack.
|
||||
|
||||
The backpointers, however, make simultaneous alteration and iteration tricky.
|
||||
|
||||
|
||||
SIMULTANEOUS ALTERATION AND ITERATION
|
||||
-------------------------------------
|
||||
|
||||
There are a number of cases to consider:
|
||||
|
||||
(1) Simple insert/replace. This involves simply replacing a NULL or old
|
||||
matching leaf pointer with the pointer to the new leaf after a barrier.
|
||||
The metadata blocks don't change otherwise. An old leaf won't be freed
|
||||
until after the RCU grace period.
|
||||
|
||||
(2) Simple delete. This involves just clearing an old matching leaf. The
|
||||
metadata blocks don't change otherwise. The old leaf won't be freed until
|
||||
after the RCU grace period.
|
||||
|
||||
(3) Insertion replacing part of a subtree that we haven't yet entered. This
|
||||
may involve replacement of part of that subtree - but that won't affect
|
||||
the iteration as we won't have reached the pointer to it yet and the
|
||||
ancestry blocks are not replaced (the layout of those does not change).
|
||||
|
||||
(4) Insertion replacing nodes that we're actively processing. This isn't a
|
||||
problem as we've passed the anchoring pointer and won't switch onto the
|
||||
new layout until we follow the back pointers - at which point we've
|
||||
already examined the leaves in the replaced node (we iterate over all the
|
||||
leaves in a node before following any of its metadata pointers).
|
||||
|
||||
We might, however, re-see some leaves that have been split out into a new
|
||||
branch that's in a slot further along than we were at.
|
||||
|
||||
(5) Insertion replacing nodes that we're processing a dependent branch of.
|
||||
This won't affect us until we follow the back pointers. Similar to (4).
|
||||
|
||||
(6) Deletion collapsing a branch under us. This doesn't affect us because the
|
||||
back pointers will get us back to the parent of the new node before we
|
||||
could see the new node. The entire collapsed subtree is thrown away
|
||||
unchanged - and will still be rooted on the same slot, so we shouldn't
|
||||
process it a second time as we'll go back to slot + 1.
|
||||
|
||||
Note:
|
||||
|
||||
(*) Under some circumstances, we need to simultaneously change the parent
|
||||
pointer and the parent slot pointer on a node (say, for example, we
|
||||
inserted another node before it and moved it up a level). We cannot do
|
||||
this without locking against a read - so we have to replace that node too.
|
||||
|
||||
However, when we're changing a shortcut into a node this isn't a problem
|
||||
as shortcuts only have one slot and so the parent slot number isn't used
|
||||
when traversing backwards over one. This means that it's okay to change
|
||||
the slot number first - provided suitable barriers are used to make sure
|
||||
the parent slot number is read after the back pointer.
|
||||
|
||||
Obsolete blocks and leaves are freed up after an RCU grace period has passed,
|
||||
so as long as anyone doing walking or iteration holds the RCU read lock, the
|
||||
old superstructure should not go away on them.
|
|
@ -266,10 +266,12 @@ E.g.
|
|||
Invalidation is removing an entry from the cache without writing it
|
||||
back. Cache blocks can be invalidated via the invalidate_cblocks
|
||||
message, which takes an arbitrary number of cblock ranges. Each cblock
|
||||
must be expressed as a decimal value, in the future a variant message
|
||||
that takes cblock ranges expressed in hexidecimal may be needed to
|
||||
better support efficient invalidation of larger caches. The cache must
|
||||
be in passthrough mode when invalidate_cblocks is used.
|
||||
range's end value is "one past the end", meaning 5-10 expresses a range
|
||||
of values from 5 to 9. Each cblock must be expressed as a decimal
|
||||
value, in the future a variant message that takes cblock ranges
|
||||
expressed in hexidecimal may be needed to better support efficient
|
||||
invalidation of larger caches. The cache must be in passthrough mode
|
||||
when invalidate_cblocks is used.
|
||||
|
||||
invalidate_cblocks [<cblock>|<cblock begin>-<cblock end>]*
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
* ARC Performance Monitor Unit
|
||||
|
||||
The ARC 700 can be configured with a pipeline performance monitor for counting
|
||||
CPU and cache events like cache misses and hits.
|
||||
|
||||
Note that:
|
||||
* ARC 700 refers to a family of ARC processor cores;
|
||||
- There is only one type of PMU available for the whole family;
|
||||
- The PMU may support different sets of events; supported events are probed
|
||||
at boot time, as required by the reference manual.
|
||||
|
||||
* The ARC 700 PMU does not support interrupts; although HW events may be
|
||||
counted, the HW events themselves cannot serve as a trigger for a sample.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should contain
|
||||
"snps,arc700-pmu"
|
||||
|
||||
Example:
|
||||
|
||||
pmu {
|
||||
compatible = "snps,arc700-pmu";
|
||||
};
|
|
@ -7,10 +7,18 @@ The MPU contain CPUs, GIC, L2 cache and a local PRCM.
|
|||
Required properties:
|
||||
- compatible : Should be "ti,omap3-mpu" for OMAP3
|
||||
Should be "ti,omap4-mpu" for OMAP4
|
||||
Should be "ti,omap5-mpu" for OMAP5
|
||||
- ti,hwmods: "mpu"
|
||||
|
||||
Examples:
|
||||
|
||||
- For an OMAP5 SMP system:
|
||||
|
||||
mpu {
|
||||
compatible = "ti,omap5-mpu";
|
||||
ti,hwmods = "mpu"
|
||||
};
|
||||
|
||||
- For an OMAP4 SMP system:
|
||||
|
||||
mpu {
|
||||
|
|
|
@ -7,6 +7,7 @@ representation in the device tree should be done as under:-
|
|||
Required properties:
|
||||
|
||||
- compatible : should be one of
|
||||
"arm,armv8-pmuv3"
|
||||
"arm,cortex-a15-pmu"
|
||||
"arm,cortex-a9-pmu"
|
||||
"arm,cortex-a8-pmu"
|
||||
|
|
|
@ -49,7 +49,7 @@ adc@12D10000 {
|
|||
/* NTC thermistor is a hwmon device */
|
||||
ncp15wb473@0 {
|
||||
compatible = "ntc,ncp15wb473";
|
||||
pullup-uV = <1800000>;
|
||||
pullup-uv = <1800000>;
|
||||
pullup-ohm = <47000>;
|
||||
pulldown-ohm = <0>;
|
||||
io-channels = <&adc 4>;
|
||||
|
|
|
@ -6,7 +6,7 @@ SoC's in the Exynos4 family.
|
|||
|
||||
Required Properties:
|
||||
|
||||
- comptible: should be one of the following.
|
||||
- compatible: should be one of the following.
|
||||
- "samsung,exynos4210-clock" - controller compatible with Exynos4210 SoC.
|
||||
- "samsung,exynos4412-clock" - controller compatible with Exynos4412 SoC.
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ controllers within the Exynos5250 SoC.
|
|||
|
||||
Required Properties:
|
||||
|
||||
- comptible: should be one of the following.
|
||||
- compatible: should be one of the following.
|
||||
- "samsung,exynos5250-clock" - controller compatible with Exynos5250 SoC.
|
||||
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
|
|
|
@ -5,7 +5,7 @@ controllers within the Exynos5420 SoC.
|
|||
|
||||
Required Properties:
|
||||
|
||||
- comptible: should be one of the following.
|
||||
- compatible: should be one of the following.
|
||||
- "samsung,exynos5420-clock" - controller compatible with Exynos5420 SoC.
|
||||
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
|
|
|
@ -5,7 +5,7 @@ controllers within the Exynos5440 SoC.
|
|||
|
||||
Required Properties:
|
||||
|
||||
- comptible: should be "samsung,exynos5440-clock".
|
||||
- compatible: should be "samsung,exynos5440-clock".
|
||||
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
|
|
|
@ -28,7 +28,7 @@ The three cells in order are:
|
|||
dependent:
|
||||
- bit 7-0: peripheral identifier for the hardware handshaking interface. The
|
||||
identifier can be different for tx and rx.
|
||||
- bit 11-8: FIFO configuration. 0 for half FIFO, 1 for ALAP, 1 for ASAP.
|
||||
- bit 11-8: FIFO configuration. 0 for half FIFO, 1 for ALAP, 2 for ASAP.
|
||||
|
||||
Example:
|
||||
|
||||
|
|
|
@ -5,16 +5,42 @@ This is for the non-QE/CPM/GUTs GPIO controllers as found on
|
|||
|
||||
Every GPIO controller node must have #gpio-cells property defined,
|
||||
this information will be used to translate gpio-specifiers.
|
||||
See bindings/gpio/gpio.txt for details of how to specify GPIO
|
||||
information for devices.
|
||||
|
||||
The GPIO module usually is connected to the SoC's internal interrupt
|
||||
controller, see bindings/interrupt-controller/interrupts.txt (the
|
||||
interrupt client nodes section) for details how to specify this GPIO
|
||||
module's interrupt.
|
||||
|
||||
The GPIO module may serve as another interrupt controller (cascaded to
|
||||
the SoC's internal interrupt controller). See the interrupt controller
|
||||
nodes section in bindings/interrupt-controller/interrupts.txt for
|
||||
details.
|
||||
|
||||
Required properties:
|
||||
- compatible : "fsl,<CHIP>-gpio" followed by "fsl,mpc8349-gpio" for
|
||||
83xx, "fsl,mpc8572-gpio" for 85xx and "fsl,mpc8610-gpio" for 86xx.
|
||||
- #gpio-cells : Should be two. The first cell is the pin number and the
|
||||
second cell is used to specify optional parameters (currently unused).
|
||||
- interrupts : Interrupt mapping for GPIO IRQ.
|
||||
- interrupt-parent : Phandle for the interrupt controller that
|
||||
services interrupts for this device.
|
||||
- gpio-controller : Marks the port as GPIO controller.
|
||||
- compatible: "fsl,<chip>-gpio" followed by "fsl,mpc8349-gpio"
|
||||
for 83xx, "fsl,mpc8572-gpio" for 85xx, or
|
||||
"fsl,mpc8610-gpio" for 86xx.
|
||||
- #gpio-cells: Should be two. The first cell is the pin number
|
||||
and the second cell is used to specify optional
|
||||
parameters (currently unused).
|
||||
- interrupt-parent: Phandle for the interrupt controller that
|
||||
services interrupts for this device.
|
||||
- interrupts: Interrupt mapping for GPIO IRQ.
|
||||
- gpio-controller: Marks the port as GPIO controller.
|
||||
|
||||
Optional properties:
|
||||
- interrupt-controller: Empty boolean property which marks the GPIO
|
||||
module as an IRQ controller.
|
||||
- #interrupt-cells: Should be two. Defines the number of integer
|
||||
cells required to specify an interrupt within
|
||||
this interrupt controller. The first cell
|
||||
defines the pin number, the second cell
|
||||
defines additional flags (trigger type,
|
||||
trigger polarity). Note that the available
|
||||
set of trigger conditions supported by the
|
||||
GPIO module depends on the actual SoC.
|
||||
|
||||
Example of gpio-controller nodes for a MPC8347 SoC:
|
||||
|
||||
|
@ -22,39 +48,27 @@ Example of gpio-controller nodes for a MPC8347 SoC:
|
|||
#gpio-cells = <2>;
|
||||
compatible = "fsl,mpc8347-gpio", "fsl,mpc8349-gpio";
|
||||
reg = <0xc00 0x100>;
|
||||
interrupts = <74 0x8>;
|
||||
interrupt-parent = <&ipic>;
|
||||
interrupts = <74 0x8>;
|
||||
gpio-controller;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpio2: gpio-controller@d00 {
|
||||
#gpio-cells = <2>;
|
||||
compatible = "fsl,mpc8347-gpio", "fsl,mpc8349-gpio";
|
||||
reg = <0xd00 0x100>;
|
||||
interrupts = <75 0x8>;
|
||||
interrupt-parent = <&ipic>;
|
||||
interrupts = <75 0x8>;
|
||||
gpio-controller;
|
||||
};
|
||||
|
||||
See booting-without-of.txt for details of how to specify GPIO
|
||||
information for devices.
|
||||
|
||||
To use GPIO pins as interrupt sources for peripherals, specify the
|
||||
GPIO controller as the interrupt parent and define GPIO number +
|
||||
trigger mode using the interrupts property, which is defined like
|
||||
this:
|
||||
|
||||
interrupts = <number trigger>, where:
|
||||
- number: GPIO pin (0..31)
|
||||
- trigger: trigger mode:
|
||||
2 = trigger on falling edge
|
||||
3 = trigger on both edges
|
||||
|
||||
Example of device using this is:
|
||||
Example of a peripheral using the GPIO module as an IRQ controller:
|
||||
|
||||
funkyfpga@0 {
|
||||
compatible = "funky-fpga";
|
||||
...
|
||||
interrupts = <4 3>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <4 3>;
|
||||
};
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
I2C for OMAP platforms
|
||||
|
||||
Required properties :
|
||||
- compatible : Must be "ti,omap3-i2c" or "ti,omap4-i2c"
|
||||
- compatible : Must be "ti,omap2420-i2c", "ti,omap2430-i2c", "ti,omap3-i2c"
|
||||
or "ti,omap4-i2c"
|
||||
- ti,hwmods : Must be "i2c<n>", n being the instance number (1-based)
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
|
|
|
@ -15,6 +15,7 @@ adi,adt7461 +/-1C TDM Extended Temp Range I.C
|
|||
adt7461 +/-1C TDM Extended Temp Range I.C
|
||||
at,24c08 i2c serial eeprom (24cxx)
|
||||
atmel,24c02 i2c serial eeprom (24cxx)
|
||||
atmel,at97sc3204t i2c trusted platform module (TPM)
|
||||
catalyst,24c32 i2c serial eeprom
|
||||
dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock
|
||||
dallas,ds1338 I2C RTC with 56-Byte NV RAM
|
||||
|
@ -35,6 +36,7 @@ fsl,mc13892 MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51
|
|||
fsl,mma8450 MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer
|
||||
fsl,mpr121 MPR121: Proximity Capacitive Touch Sensor Controller
|
||||
fsl,sgtl5000 SGTL5000: Ultra Low-Power Audio Codec
|
||||
gmt,g751 G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire Interface
|
||||
infineon,slb9635tt Infineon SLB9635 (Soft-) I2C TPM (old protocol, max 100khz)
|
||||
infineon,slb9645tt Infineon SLB9645 I2C TPM (new protocol, max 400khz)
|
||||
maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator
|
||||
|
@ -44,6 +46,7 @@ mc,rv3029c2 Real Time Clock Module with I2C-Bus
|
|||
national,lm75 I2C TEMP SENSOR
|
||||
national,lm80 Serial Interface ACPI-Compatible Microprocessor System Hardware Monitor
|
||||
national,lm92 ±0.33°C Accurate, 12-Bit + Sign Temperature Sensor and Thermal Window Comparator with Two-Wire Interface
|
||||
nuvoton,npct501 i2c trusted platform module (TPM)
|
||||
nxp,pca9556 Octal SMBus and I2C registered interface
|
||||
nxp,pca9557 8-bit I2C-bus and SMBus I/O port with reset
|
||||
nxp,pcf8563 Real-time clock/calendar
|
||||
|
@ -61,3 +64,4 @@ taos,tsl2550 Ambient Light Sensor with SMBUS/Two Wire Serial Interface
|
|||
ti,tsc2003 I2C Touch-Screen Controller
|
||||
ti,tmp102 Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface
|
||||
ti,tmp275 Digital Temperature Sensor
|
||||
winbond,wpct301 i2c trusted platform module (TPM)
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
* TI MMC host controller for OMAP1 and 2420
|
||||
|
||||
The MMC Host Controller on TI OMAP1 and 2420 family provides
|
||||
an interface for MMC, SD, and SDIO types of memory cards.
|
||||
|
||||
This file documents differences between the core properties described
|
||||
by mmc.txt and the properties used by the omap mmc driver.
|
||||
|
||||
Note that this driver will not work with omap2430 or later omaps,
|
||||
please see the omap hsmmc driver for the current omaps.
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "ti,omap2420-mmc", for OMAP2420 controllers
|
||||
- ti,hwmods: For 2420, must be "msdi<n>", where n is controller
|
||||
instance starting 1
|
||||
|
||||
Examples:
|
||||
|
||||
msdi1: mmc@4809c000 {
|
||||
compatible = "ti,omap2420-mmc";
|
||||
ti,hwmods = "msdi1";
|
||||
reg = <0x4809c000 0x80>;
|
||||
interrupts = <83>;
|
||||
dmas = <&sdma 61 &sdma 62>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
||||
* TI MMC host controller for OMAP1 and 2420
|
||||
|
||||
The MMC Host Controller on TI OMAP1 and 2420 family provides
|
||||
an interface for MMC, SD, and SDIO types of memory cards.
|
||||
|
||||
This file documents differences between the core properties described
|
||||
by mmc.txt and the properties used by the omap mmc driver.
|
||||
|
||||
Note that this driver will not work with omap2430 or later omaps,
|
||||
please see the omap hsmmc driver for the current omaps.
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "ti,omap2420-mmc", for OMAP2420 controllers
|
||||
- ti,hwmods: For 2420, must be "msdi<n>", where n is controller
|
||||
instance starting 1
|
||||
|
||||
Examples:
|
||||
|
||||
msdi1: mmc@4809c000 {
|
||||
compatible = "ti,omap2420-mmc";
|
||||
ti,hwmods = "msdi1";
|
||||
reg = <0x4809c000 0x80>;
|
||||
interrupts = <83>;
|
||||
dmas = <&sdma 61 &sdma 62>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
|
@ -4,7 +4,7 @@ This file provides information, what the device node
|
|||
for the davinci_emac interface contains.
|
||||
|
||||
Required properties:
|
||||
- compatible: "ti,davinci-dm6467-emac";
|
||||
- compatible: "ti,davinci-dm6467-emac" or "ti,am3517-emac"
|
||||
- reg: Offset and length of the register set for the device
|
||||
- ti,davinci-ctrl-reg-offset: offset to control register
|
||||
- ti,davinci-ctrl-mod-reg-offset: offset to control module register
|
||||
|
|
|
@ -15,6 +15,7 @@ Optional properties:
|
|||
only if property "phy-reset-gpios" is available. Missing the property
|
||||
will have the duration be 1 millisecond. Numbers greater than 1000 are
|
||||
invalid and 1 millisecond will be used instead.
|
||||
- phy-supply: regulator that powers the Ethernet PHY.
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -25,4 +26,5 @@ ethernet@83fec000 {
|
|||
phy-mode = "mii";
|
||||
phy-reset-gpios = <&gpio2 14 0>; /* GPIO2_14 */
|
||||
local-mac-address = [00 04 9F 01 1B B9];
|
||||
phy-supply = <®_fec_supply>;
|
||||
};
|
||||
|
|
|
@ -8,3 +8,7 @@ Required properties:
|
|||
Optional properties:
|
||||
- phy-device : phandle to Ethernet phy
|
||||
- local-mac-address : Ethernet mac address to use
|
||||
- reg-io-width : Mask of sizes (in bytes) of the IO accesses that
|
||||
are supported on the device. Valid value for SMSC LAN91c111 are
|
||||
1, 2 or 4. If it's omitted or invalid, the size would be 2 meaning
|
||||
16-bit access only.
|
||||
|
|
|
@ -1,33 +1,30 @@
|
|||
* Freescale 83xx DMA Controller
|
||||
* Freescale DMA Controllers
|
||||
|
||||
Freescale PowerPC 83xx have on chip general purpose DMA controllers.
|
||||
** Freescale Elo DMA Controller
|
||||
This is a little-endian 4-channel DMA controller, used in Freescale mpc83xx
|
||||
series chips such as mpc8315, mpc8349, mpc8379 etc.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : compatible list, contains 2 entries, first is
|
||||
"fsl,CHIP-dma", where CHIP is the processor
|
||||
(mpc8349, mpc8360, etc.) and the second is
|
||||
"fsl,elo-dma"
|
||||
- reg : <registers mapping for DMA general status reg>
|
||||
- ranges : Should be defined as specified in 1) to describe the
|
||||
DMA controller channels.
|
||||
- compatible : must include "fsl,elo-dma"
|
||||
- reg : DMA General Status Register, i.e. DGSR which contains
|
||||
status for all the 4 DMA channels
|
||||
- ranges : describes the mapping between the address space of the
|
||||
DMA channels and the address space of the DMA controller
|
||||
- cell-index : controller index. 0 for controller @ 0x8100
|
||||
- interrupts : <interrupt mapping for DMA IRQ>
|
||||
- interrupts : interrupt specifier for DMA IRQ
|
||||
- interrupt-parent : optional, if needed for interrupt mapping
|
||||
|
||||
|
||||
- DMA channel nodes:
|
||||
- compatible : compatible list, contains 2 entries, first is
|
||||
"fsl,CHIP-dma-channel", where CHIP is the processor
|
||||
(mpc8349, mpc8350, etc.) and the second is
|
||||
"fsl,elo-dma-channel". However, see note below.
|
||||
- reg : <registers mapping for channel>
|
||||
- cell-index : dma channel index starts at 0.
|
||||
- compatible : must include "fsl,elo-dma-channel"
|
||||
However, see note below.
|
||||
- reg : DMA channel specific registers
|
||||
- cell-index : DMA channel index starts at 0.
|
||||
|
||||
Optional properties:
|
||||
- interrupts : <interrupt mapping for DMA channel IRQ>
|
||||
(on 83xx this is expected to be identical to
|
||||
the interrupts property of the parent node)
|
||||
- interrupts : interrupt specifier for DMA channel IRQ
|
||||
(on 83xx this is expected to be identical to
|
||||
the interrupts property of the parent node)
|
||||
- interrupt-parent : optional, if needed for interrupt mapping
|
||||
|
||||
Example:
|
||||
|
@ -70,30 +67,27 @@ Example:
|
|||
};
|
||||
};
|
||||
|
||||
* Freescale 85xx/86xx DMA Controller
|
||||
|
||||
Freescale PowerPC 85xx/86xx have on chip general purpose DMA controllers.
|
||||
** Freescale EloPlus DMA Controller
|
||||
This is a 4-channel DMA controller with extended addresses and chaining,
|
||||
mainly used in Freescale mpc85xx/86xx, Pxxx and BSC series chips, such as
|
||||
mpc8540, mpc8641 p4080, bsc9131 etc.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : compatible list, contains 2 entries, first is
|
||||
"fsl,CHIP-dma", where CHIP is the processor
|
||||
(mpc8540, mpc8540, etc.) and the second is
|
||||
"fsl,eloplus-dma"
|
||||
- reg : <registers mapping for DMA general status reg>
|
||||
- compatible : must include "fsl,eloplus-dma"
|
||||
- reg : DMA General Status Register, i.e. DGSR which contains
|
||||
status for all the 4 DMA channels
|
||||
- cell-index : controller index. 0 for controller @ 0x21000,
|
||||
1 for controller @ 0xc000
|
||||
- ranges : Should be defined as specified in 1) to describe the
|
||||
DMA controller channels.
|
||||
- ranges : describes the mapping between the address space of the
|
||||
DMA channels and the address space of the DMA controller
|
||||
|
||||
- DMA channel nodes:
|
||||
- compatible : compatible list, contains 2 entries, first is
|
||||
"fsl,CHIP-dma-channel", where CHIP is the processor
|
||||
(mpc8540, mpc8560, etc.) and the second is
|
||||
"fsl,eloplus-dma-channel". However, see note below.
|
||||
- cell-index : dma channel index starts at 0.
|
||||
- reg : <registers mapping for channel>
|
||||
- interrupts : <interrupt mapping for DMA channel IRQ>
|
||||
- compatible : must include "fsl,eloplus-dma-channel"
|
||||
However, see note below.
|
||||
- cell-index : DMA channel index starts at 0.
|
||||
- reg : DMA channel specific registers
|
||||
- interrupts : interrupt specifier for DMA channel IRQ
|
||||
- interrupt-parent : optional, if needed for interrupt mapping
|
||||
|
||||
Example:
|
||||
|
@ -134,6 +128,76 @@ Example:
|
|||
};
|
||||
};
|
||||
|
||||
** Freescale Elo3 DMA Controller
|
||||
DMA controller which has same function as EloPlus except that Elo3 has 8
|
||||
channels while EloPlus has only 4, it is used in Freescale Txxx and Bxxx
|
||||
series chips, such as t1040, t4240, b4860.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : must include "fsl,elo3-dma"
|
||||
- reg : contains two entries for DMA General Status Registers,
|
||||
i.e. DGSR0 which includes status for channel 1~4, and
|
||||
DGSR1 for channel 5~8
|
||||
- ranges : describes the mapping between the address space of the
|
||||
DMA channels and the address space of the DMA controller
|
||||
|
||||
- DMA channel nodes:
|
||||
- compatible : must include "fsl,eloplus-dma-channel"
|
||||
- reg : DMA channel specific registers
|
||||
- interrupts : interrupt specifier for DMA channel IRQ
|
||||
- interrupt-parent : optional, if needed for interrupt mapping
|
||||
|
||||
Example:
|
||||
dma@100300 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,elo3-dma";
|
||||
reg = <0x100300 0x4>,
|
||||
<0x100600 0x4>;
|
||||
ranges = <0x0 0x100100 0x500>;
|
||||
dma-channel@0 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x0 0x80>;
|
||||
interrupts = <28 2 0 0>;
|
||||
};
|
||||
dma-channel@80 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x80 0x80>;
|
||||
interrupts = <29 2 0 0>;
|
||||
};
|
||||
dma-channel@100 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x100 0x80>;
|
||||
interrupts = <30 2 0 0>;
|
||||
};
|
||||
dma-channel@180 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x180 0x80>;
|
||||
interrupts = <31 2 0 0>;
|
||||
};
|
||||
dma-channel@300 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x300 0x80>;
|
||||
interrupts = <76 2 0 0>;
|
||||
};
|
||||
dma-channel@380 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x380 0x80>;
|
||||
interrupts = <77 2 0 0>;
|
||||
};
|
||||
dma-channel@400 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x400 0x80>;
|
||||
interrupts = <78 2 0 0>;
|
||||
};
|
||||
dma-channel@480 {
|
||||
compatible = "fsl,eloplus-dma-channel";
|
||||
reg = <0x480 0x80>;
|
||||
interrupts = <79 2 0 0>;
|
||||
};
|
||||
};
|
||||
|
||||
Note on DMA channel compatible properties: The compatible property must say
|
||||
"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel" to be used by the Elo DMA
|
||||
driver (fsldma). Any DMA channel used by fsldma cannot be used by another
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
Qualcomm MSM pseudo random number generator.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be "qcom,prng"
|
||||
- reg : specifies base physical address and size of the registers map
|
||||
- clocks : phandle to clock-controller plus clock-specifier pair
|
||||
- clock-names : "core" clocks all registers, FIFO and circuits in PRNG IP block
|
||||
|
||||
Example:
|
||||
|
||||
rng@f9bff000 {
|
||||
compatible = "qcom,prng";
|
||||
reg = <0xf9bff000 0x200>;
|
||||
clocks = <&clock GCC_PRNG_AHB_CLK>;
|
||||
clock-names = "core";
|
||||
};
|
|
@ -1,5 +0,0 @@
|
|||
NVIDIA Tegra 2 SPI device
|
||||
|
||||
Required properties:
|
||||
- compatible : should be "nvidia,tegra20-spi".
|
||||
- gpios : should specify GPIOs used for chipselect.
|
|
@ -32,12 +32,14 @@ est ESTeem Wireless Modems
|
|||
fsl Freescale Semiconductor
|
||||
GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc.
|
||||
gef GE Fanuc Intelligent Platforms Embedded Systems, Inc.
|
||||
gmt Global Mixed-mode Technology, Inc.
|
||||
hisilicon Hisilicon Limited.
|
||||
hp Hewlett Packard
|
||||
ibm International Business Machines (IBM)
|
||||
idt Integrated Device Technologies, Inc.
|
||||
img Imagination Technologies Ltd.
|
||||
intercontrol Inter Control Group
|
||||
lg LG Corporation
|
||||
linux Linux-specific binding
|
||||
lsi LSI Corp. (LSI Logic)
|
||||
marvell Marvell Technology Group Ltd.
|
||||
|
|
|
@ -15,39 +15,48 @@ be built as module or inside kernel. Let's consider those cases.
|
|||
|
||||
Part 2 - When dmatest is built as a module...
|
||||
|
||||
After mounting debugfs and loading the module, the /sys/kernel/debug/dmatest
|
||||
folder with nodes will be created. There are two important files located. First
|
||||
is the 'run' node that controls run and stop phases of the test, and the second
|
||||
one, 'results', is used to get the test case results.
|
||||
|
||||
Note that in this case test will not run on load automatically.
|
||||
|
||||
Example of usage:
|
||||
% modprobe dmatest channel=dma0chan0 timeout=2000 iterations=1 run=1
|
||||
|
||||
...or:
|
||||
% modprobe dmatest
|
||||
% echo dma0chan0 > /sys/module/dmatest/parameters/channel
|
||||
% echo 2000 > /sys/module/dmatest/parameters/timeout
|
||||
% echo 1 > /sys/module/dmatest/parameters/iterations
|
||||
% echo 1 > /sys/kernel/debug/dmatest/run
|
||||
% echo 1 > /sys/module/dmatest/parameters/run
|
||||
|
||||
...or on the kernel command line:
|
||||
|
||||
dmatest.channel=dma0chan0 dmatest.timeout=2000 dmatest.iterations=1 dmatest.run=1
|
||||
|
||||
Hint: available channel list could be extracted by running the following
|
||||
command:
|
||||
% ls -1 /sys/class/dma/
|
||||
|
||||
After a while you will start to get messages about current status or error like
|
||||
in the original code.
|
||||
Once started a message like "dmatest: Started 1 threads using dma0chan0" is
|
||||
emitted. After that only test failure messages are reported until the test
|
||||
stops.
|
||||
|
||||
Note that running a new test will not stop any in progress test.
|
||||
|
||||
The following command should return actual state of the test.
|
||||
% cat /sys/kernel/debug/dmatest/run
|
||||
The following command returns the state of the test.
|
||||
% cat /sys/module/dmatest/parameters/run
|
||||
|
||||
To wait for test done the user may perform a busy loop that checks the state.
|
||||
To wait for test completion userpace can poll 'run' until it is false, or use
|
||||
the wait parameter. Specifying 'wait=1' when loading the module causes module
|
||||
initialization to pause until a test run has completed, while reading
|
||||
/sys/module/dmatest/parameters/wait waits for any running test to complete
|
||||
before returning. For example, the following scripts wait for 42 tests
|
||||
to complete before exiting. Note that if 'iterations' is set to 'infinite' then
|
||||
waiting is disabled.
|
||||
|
||||
% while [ $(cat /sys/kernel/debug/dmatest/run) = "Y" ]
|
||||
> do
|
||||
> echo -n "."
|
||||
> sleep 1
|
||||
> done
|
||||
> echo
|
||||
Example:
|
||||
% modprobe dmatest run=1 iterations=42 wait=1
|
||||
% modprobe -r dmatest
|
||||
...or:
|
||||
% modprobe dmatest run=1 iterations=42
|
||||
% cat /sys/module/dmatest/parameters/wait
|
||||
% modprobe -r dmatest
|
||||
|
||||
Part 3 - When built-in in the kernel...
|
||||
|
||||
|
@ -62,21 +71,22 @@ case. You always could check them at run-time by running
|
|||
|
||||
Part 4 - Gathering the test results
|
||||
|
||||
The module provides a storage for the test results in the memory. The gathered
|
||||
data could be used after test is done.
|
||||
Test results are printed to the kernel log buffer with the format:
|
||||
|
||||
The special file 'results' in the debugfs represents gathered data of the in
|
||||
progress test. The messages collected are printed to the kernel log as well.
|
||||
"dmatest: result <channel>: <test id>: '<error msg>' with src_off=<val> dst_off=<val> len=<val> (<err code>)"
|
||||
|
||||
Example of output:
|
||||
% cat /sys/kernel/debug/dmatest/results
|
||||
dma0chan0-copy0: #1: No errors with src_off=0x7bf dst_off=0x8ad len=0x3fea (0)
|
||||
% dmesg | tail -n 1
|
||||
dmatest: result dma0chan0-copy0: #1: No errors with src_off=0x7bf dst_off=0x8ad len=0x3fea (0)
|
||||
|
||||
The message format is unified across the different types of errors. A number in
|
||||
the parens represents additional information, e.g. error code, error counter,
|
||||
or status.
|
||||
or status. A test thread also emits a summary line at completion listing the
|
||||
number of tests executed, number that failed, and a result code.
|
||||
|
||||
Comparison between buffers is stored to the dedicated structure.
|
||||
Example:
|
||||
% dmesg | tail -n 1
|
||||
dmatest: dma0chan0-copy0: summary 1 test, 0 failures 1000 iops 100000 KB/s (0)
|
||||
|
||||
Note that the verify result is now accessible only via file 'results' in the
|
||||
debugfs.
|
||||
The details of a data miscompare error are also emitted, but do not follow the
|
||||
above format.
|
||||
|
|
|
@ -70,6 +70,12 @@ Unless otherwise specified, all options default to off.
|
|||
|
||||
See comments at the top of fs/btrfs/check-integrity.c for more info.
|
||||
|
||||
commit=<seconds>
|
||||
Set the interval of periodic commit, 30 seconds by default. Higher
|
||||
values defer data being synced to permanent storage with obvious
|
||||
consequences when the system crashes. The upper bound is not forced,
|
||||
but a warning is printed if it's more than 300 seconds (5 minutes).
|
||||
|
||||
compress
|
||||
compress=<type>
|
||||
compress-force
|
||||
|
@ -154,7 +160,11 @@ Unless otherwise specified, all options default to off.
|
|||
Currently this scans a list of several previous tree roots and tries to
|
||||
use the first readable.
|
||||
|
||||
skip_balance
|
||||
rescan_uuid_tree
|
||||
Force check and rebuild procedure of the UUID tree. This should not
|
||||
normally be needed.
|
||||
|
||||
skip_balance
|
||||
Skip automatic resume of interrupted balance operation after mount.
|
||||
May be resumed with "btrfs balance resume."
|
||||
|
||||
|
@ -234,24 +244,14 @@ available from the git repository at the following location:
|
|||
|
||||
These include the following tools:
|
||||
|
||||
mkfs.btrfs: create a filesystem
|
||||
* mkfs.btrfs: create a filesystem
|
||||
|
||||
btrfsctl: control program to create snapshots and subvolumes:
|
||||
* btrfs: a single tool to manage the filesystems, refer to the manpage for more details
|
||||
|
||||
mount /dev/sda2 /mnt
|
||||
btrfsctl -s new_subvol_name /mnt
|
||||
btrfsctl -s snapshot_of_default /mnt/default
|
||||
btrfsctl -s snapshot_of_new_subvol /mnt/new_subvol_name
|
||||
btrfsctl -s snapshot_of_a_snapshot /mnt/snapshot_of_new_subvol
|
||||
ls /mnt
|
||||
default snapshot_of_a_snapshot snapshot_of_new_subvol
|
||||
new_subvol_name snapshot_of_default
|
||||
* 'btrfsck' or 'btrfs check': do a consistency check of the filesystem
|
||||
|
||||
Snapshots and subvolumes cannot be deleted right now, but you can
|
||||
rm -rf all the files and directories inside them.
|
||||
Other tools for specific tasks:
|
||||
|
||||
btrfsck: do a limited check of the FS extent trees.
|
||||
* btrfs-convert: in-place conversion from ext2/3/4 filesystems
|
||||
|
||||
btrfs-debug-tree: print all of the FS metadata in text form. Example:
|
||||
|
||||
btrfs-debug-tree /dev/sda2 >& big_output_file
|
||||
* btrfs-image: dump filesystem metadata for debugging
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
00-INDEX
|
||||
- This file
|
||||
gpio.txt
|
||||
- Introduction to GPIOs and their kernel interfaces
|
||||
consumer.txt
|
||||
- How to obtain and use GPIOs in a driver
|
||||
driver.txt
|
||||
- How to write a GPIO driver
|
||||
board.txt
|
||||
- How to assign GPIOs to a consumer device and a function
|
||||
sysfs.txt
|
||||
- Information about the GPIO sysfs interface
|
||||
gpio-legacy.txt
|
||||
- Historical documentation of the deprecated GPIO integer interface
|
|
@ -0,0 +1,115 @@
|
|||
GPIO Mappings
|
||||
=============
|
||||
|
||||
This document explains how GPIOs can be assigned to given devices and functions.
|
||||
Note that it only applies to the new descriptor-based interface. For a
|
||||
description of the deprecated integer-based GPIO interface please refer to
|
||||
gpio-legacy.txt (actually, there is no real mapping possible with the old
|
||||
interface; you just fetch an integer from somewhere and request the
|
||||
corresponding GPIO.
|
||||
|
||||
Platforms that make use of GPIOs must select ARCH_REQUIRE_GPIOLIB (if GPIO usage
|
||||
is mandatory) or ARCH_WANT_OPTIONAL_GPIOLIB (if GPIO support can be omitted) in
|
||||
their Kconfig. Then, how GPIOs are mapped depends on what the platform uses to
|
||||
describe its hardware layout. Currently, mappings can be defined through device
|
||||
tree, ACPI, and platform data.
|
||||
|
||||
Device Tree
|
||||
-----------
|
||||
GPIOs can easily be mapped to devices and functions in the device tree. The
|
||||
exact way to do it depends on the GPIO controller providing the GPIOs, see the
|
||||
device tree bindings for your controller.
|
||||
|
||||
GPIOs mappings are defined in the consumer device's node, in a property named
|
||||
<function>-gpios, where <function> is the function the driver will request
|
||||
through gpiod_get(). For example:
|
||||
|
||||
foo_device {
|
||||
compatible = "acme,foo";
|
||||
...
|
||||
led-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>, /* red */
|
||||
<&gpio 16 GPIO_ACTIVE_HIGH>, /* green */
|
||||
<&gpio 17 GPIO_ACTIVE_HIGH>; /* blue */
|
||||
|
||||
power-gpio = <&gpio 1 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
This property will make GPIOs 15, 16 and 17 available to the driver under the
|
||||
"led" function, and GPIO 1 as the "power" GPIO:
|
||||
|
||||
struct gpio_desc *red, *green, *blue, *power;
|
||||
|
||||
red = gpiod_get_index(dev, "led", 0);
|
||||
green = gpiod_get_index(dev, "led", 1);
|
||||
blue = gpiod_get_index(dev, "led", 2);
|
||||
|
||||
power = gpiod_get(dev, "power");
|
||||
|
||||
The led GPIOs will be active-high, while the power GPIO will be active-low (i.e.
|
||||
gpiod_is_active_low(power) will be true).
|
||||
|
||||
ACPI
|
||||
----
|
||||
ACPI does not support function names for GPIOs. Therefore, only the "idx"
|
||||
argument of gpiod_get_index() is useful to discriminate between GPIOs assigned
|
||||
to a device. The "con_id" argument can still be set for debugging purposes (it
|
||||
will appear under error messages as well as debug and sysfs nodes).
|
||||
|
||||
Platform Data
|
||||
-------------
|
||||
Finally, GPIOs can be bound to devices and functions using platform data. Board
|
||||
files that desire to do so need to include the following header:
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
|
||||
GPIOs are mapped by the means of tables of lookups, containing instances of the
|
||||
gpiod_lookup structure. Two macros are defined to help declaring such mappings:
|
||||
|
||||
GPIO_LOOKUP(chip_label, chip_hwnum, dev_id, con_id, flags)
|
||||
GPIO_LOOKUP_IDX(chip_label, chip_hwnum, dev_id, con_id, idx, flags)
|
||||
|
||||
where
|
||||
|
||||
- chip_label is the label of the gpiod_chip instance providing the GPIO
|
||||
- chip_hwnum is the hardware number of the GPIO within the chip
|
||||
- dev_id is the identifier of the device that will make use of this GPIO. If
|
||||
NULL, the GPIO will be available to all devices.
|
||||
- con_id is the name of the GPIO function from the device point of view. It
|
||||
can be NULL.
|
||||
- idx is the index of the GPIO within the function.
|
||||
- flags is defined to specify the following properties:
|
||||
* GPIOF_ACTIVE_LOW - to configure the GPIO as active-low
|
||||
* GPIOF_OPEN_DRAIN - GPIO pin is open drain type.
|
||||
* GPIOF_OPEN_SOURCE - GPIO pin is open source type.
|
||||
|
||||
In the future, these flags might be extended to support more properties.
|
||||
|
||||
Note that GPIO_LOOKUP() is just a shortcut to GPIO_LOOKUP_IDX() where idx = 0.
|
||||
|
||||
A lookup table can then be defined as follows:
|
||||
|
||||
struct gpiod_lookup gpios_table[] = {
|
||||
GPIO_LOOKUP_IDX("gpio.0", 15, "foo.0", "led", 0, GPIO_ACTIVE_HIGH),
|
||||
GPIO_LOOKUP_IDX("gpio.0", 16, "foo.0", "led", 1, GPIO_ACTIVE_HIGH),
|
||||
GPIO_LOOKUP_IDX("gpio.0", 17, "foo.0", "led", 2, GPIO_ACTIVE_HIGH),
|
||||
GPIO_LOOKUP("gpio.0", 1, "foo.0", "power", GPIO_ACTIVE_LOW),
|
||||
};
|
||||
|
||||
And the table can be added by the board code as follows:
|
||||
|
||||
gpiod_add_table(gpios_table, ARRAY_SIZE(gpios_table));
|
||||
|
||||
The driver controlling "foo.0" will then be able to obtain its GPIOs as follows:
|
||||
|
||||
struct gpio_desc *red, *green, *blue, *power;
|
||||
|
||||
red = gpiod_get_index(dev, "led", 0);
|
||||
green = gpiod_get_index(dev, "led", 1);
|
||||
blue = gpiod_get_index(dev, "led", 2);
|
||||
|
||||
power = gpiod_get(dev, "power");
|
||||
gpiod_direction_output(power, 1);
|
||||
|
||||
Since the "power" GPIO is mapped as active-low, its actual signal will be 0
|
||||
after this code. Contrary to the legacy integer GPIO interface, the active-low
|
||||
property is handled during mapping and is thus transparent to GPIO consumers.
|
|
@ -0,0 +1,197 @@
|
|||
GPIO Descriptor Consumer Interface
|
||||
==================================
|
||||
|
||||
This document describes the consumer interface of the GPIO framework. Note that
|
||||
it describes the new descriptor-based interface. For a description of the
|
||||
deprecated integer-based GPIO interface please refer to gpio-legacy.txt.
|
||||
|
||||
|
||||
Guidelines for GPIOs consumers
|
||||
==============================
|
||||
|
||||
Drivers that can't work without standard GPIO calls should have Kconfig entries
|
||||
that depend on GPIOLIB. The functions that allow a driver to obtain and use
|
||||
GPIOs are available by including the following file:
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
||||
All the functions that work with the descriptor-based GPIO interface are
|
||||
prefixed with gpiod_. The gpio_ prefix is used for the legacy interface. No
|
||||
other function in the kernel should use these prefixes.
|
||||
|
||||
|
||||
Obtaining and Disposing GPIOs
|
||||
=============================
|
||||
|
||||
With the descriptor-based interface, GPIOs are identified with an opaque,
|
||||
non-forgeable handler that must be obtained through a call to one of the
|
||||
gpiod_get() functions. Like many other kernel subsystems, gpiod_get() takes the
|
||||
device that will use the GPIO and the function the requested GPIO is supposed to
|
||||
fulfill:
|
||||
|
||||
struct gpio_desc *gpiod_get(struct device *dev, const char *con_id)
|
||||
|
||||
If a function is implemented by using several GPIOs together (e.g. a simple LED
|
||||
device that displays digits), an additional index argument can be specified:
|
||||
|
||||
struct gpio_desc *gpiod_get_index(struct device *dev,
|
||||
const char *con_id, unsigned int idx)
|
||||
|
||||
Both functions return either a valid GPIO descriptor, or an error code checkable
|
||||
with IS_ERR(). They will never return a NULL pointer.
|
||||
|
||||
Device-managed variants of these functions are also defined:
|
||||
|
||||
struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id)
|
||||
|
||||
struct gpio_desc *devm_gpiod_get_index(struct device *dev,
|
||||
const char *con_id,
|
||||
unsigned int idx)
|
||||
|
||||
A GPIO descriptor can be disposed of using the gpiod_put() function:
|
||||
|
||||
void gpiod_put(struct gpio_desc *desc)
|
||||
|
||||
It is strictly forbidden to use a descriptor after calling this function. The
|
||||
device-managed variant is, unsurprisingly:
|
||||
|
||||
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
|
||||
|
||||
|
||||
Using GPIOs
|
||||
===========
|
||||
|
||||
Setting Direction
|
||||
-----------------
|
||||
The first thing a driver must do with a GPIO is setting its direction. This is
|
||||
done by invoking one of the gpiod_direction_*() functions:
|
||||
|
||||
int gpiod_direction_input(struct gpio_desc *desc)
|
||||
int gpiod_direction_output(struct gpio_desc *desc, int value)
|
||||
|
||||
The return value is zero for success, else a negative errno. It should be
|
||||
checked, since the get/set calls don't return errors and since misconfiguration
|
||||
is possible. You should normally issue these calls from a task context. However,
|
||||
for spinlock-safe GPIOs it is OK to use them before tasking is enabled, as part
|
||||
of early board setup.
|
||||
|
||||
For output GPIOs, the value provided becomes the initial output value. This
|
||||
helps avoid signal glitching during system startup.
|
||||
|
||||
A driver can also query the current direction of a GPIO:
|
||||
|
||||
int gpiod_get_direction(const struct gpio_desc *desc)
|
||||
|
||||
This function will return either GPIOF_DIR_IN or GPIOF_DIR_OUT.
|
||||
|
||||
Be aware that there is no default direction for GPIOs. Therefore, **using a GPIO
|
||||
without setting its direction first is illegal and will result in undefined
|
||||
behavior!**
|
||||
|
||||
|
||||
Spinlock-Safe GPIO Access
|
||||
-------------------------
|
||||
Most GPIO controllers can be accessed with memory read/write instructions. Those
|
||||
don't need to sleep, and can safely be done from inside hard (non-threaded) IRQ
|
||||
handlers and similar contexts.
|
||||
|
||||
Use the following calls to access GPIOs from an atomic context:
|
||||
|
||||
int gpiod_get_value(const struct gpio_desc *desc);
|
||||
void gpiod_set_value(struct gpio_desc *desc, int value);
|
||||
|
||||
The values are boolean, zero for low, nonzero for high. When reading the value
|
||||
of an output pin, the value returned should be what's seen on the pin. That
|
||||
won't always match the specified output value, because of issues including
|
||||
open-drain signaling and output latencies.
|
||||
|
||||
The get/set calls do not return errors because "invalid GPIO" should have been
|
||||
reported earlier from gpiod_direction_*(). However, note that not all platforms
|
||||
can read the value of output pins; those that can't should always return zero.
|
||||
Also, using these calls for GPIOs that can't safely be accessed without sleeping
|
||||
(see below) is an error.
|
||||
|
||||
|
||||
GPIO Access That May Sleep
|
||||
--------------------------
|
||||
Some GPIO controllers must be accessed using message based buses like I2C or
|
||||
SPI. Commands to read or write those GPIO values require waiting to get to the
|
||||
head of a queue to transmit a command and get its response. This requires
|
||||
sleeping, which can't be done from inside IRQ handlers.
|
||||
|
||||
Platforms that support this type of GPIO distinguish them from other GPIOs by
|
||||
returning nonzero from this call:
|
||||
|
||||
int gpiod_cansleep(const struct gpio_desc *desc)
|
||||
|
||||
To access such GPIOs, a different set of accessors is defined:
|
||||
|
||||
int gpiod_get_value_cansleep(const struct gpio_desc *desc)
|
||||
void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
|
||||
|
||||
Accessing such GPIOs requires a context which may sleep, for example a threaded
|
||||
IRQ handler, and those accessors must be used instead of spinlock-safe
|
||||
accessors without the cansleep() name suffix.
|
||||
|
||||
Other than the fact that these accessors might sleep, and will work on GPIOs
|
||||
that can't be accessed from hardIRQ handlers, these calls act the same as the
|
||||
spinlock-safe calls.
|
||||
|
||||
|
||||
Active-low State and Raw GPIO Values
|
||||
------------------------------------
|
||||
Device drivers like to manage the logical state of a GPIO, i.e. the value their
|
||||
device will actually receive, no matter what lies between it and the GPIO line.
|
||||
In some cases, it might make sense to control the actual GPIO line value. The
|
||||
following set of calls ignore the active-low property of a GPIO and work on the
|
||||
raw line value:
|
||||
|
||||
int gpiod_get_raw_value(const struct gpio_desc *desc)
|
||||
void gpiod_set_raw_value(struct gpio_desc *desc, int value)
|
||||
int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
|
||||
void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value)
|
||||
|
||||
The active-low state of a GPIO can also be queried using the following call:
|
||||
|
||||
int gpiod_is_active_low(const struct gpio_desc *desc)
|
||||
|
||||
Note that these functions should only be used with great moderation ; a driver
|
||||
should not have to care about the physical line level.
|
||||
|
||||
GPIOs mapped to IRQs
|
||||
--------------------
|
||||
GPIO lines can quite often be used as IRQs. You can get the IRQ number
|
||||
corresponding to a given GPIO using the following call:
|
||||
|
||||
int gpiod_to_irq(const struct gpio_desc *desc)
|
||||
|
||||
It will return an IRQ number, or an negative errno code if the mapping can't be
|
||||
done (most likely because that particular GPIO cannot be used as IRQ). It is an
|
||||
unchecked error to use a GPIO that wasn't set up as an input using
|
||||
gpiod_direction_input(), or to use an IRQ number that didn't originally come
|
||||
from gpiod_to_irq(). gpiod_to_irq() is not allowed to sleep.
|
||||
|
||||
Non-error values returned from gpiod_to_irq() can be passed to request_irq() or
|
||||
free_irq(). They will often be stored into IRQ resources for platform devices,
|
||||
by the board-specific initialization code. Note that IRQ trigger options are
|
||||
part of the IRQ interface, e.g. IRQF_TRIGGER_FALLING, as are system wakeup
|
||||
capabilities.
|
||||
|
||||
|
||||
Interacting With the Legacy GPIO Subsystem
|
||||
==========================================
|
||||
Many kernel subsystems still handle GPIOs using the legacy integer-based
|
||||
interface. Although it is strongly encouraged to upgrade them to the safer
|
||||
descriptor-based API, the following two functions allow you to convert a GPIO
|
||||
descriptor into the GPIO integer namespace and vice-versa:
|
||||
|
||||
int desc_to_gpio(const struct gpio_desc *desc)
|
||||
struct gpio_desc *gpio_to_desc(unsigned gpio)
|
||||
|
||||
The GPIO number returned by desc_to_gpio() can be safely used as long as the
|
||||
GPIO descriptor has not been freed. All the same, a GPIO number passed to
|
||||
gpio_to_desc() must have been properly acquired, and usage of the returned GPIO
|
||||
descriptor is only possible after the GPIO number has been released.
|
||||
|
||||
Freeing a GPIO obtained by one API with the other API is forbidden and an
|
||||
unchecked error.
|
|
@ -0,0 +1,75 @@
|
|||
GPIO Descriptor Driver Interface
|
||||
================================
|
||||
|
||||
This document serves as a guide for GPIO chip drivers writers. Note that it
|
||||
describes the new descriptor-based interface. For a description of the
|
||||
deprecated integer-based GPIO interface please refer to gpio-legacy.txt.
|
||||
|
||||
Each GPIO controller driver needs to include the following header, which defines
|
||||
the structures used to define a GPIO driver:
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
|
||||
|
||||
Internal Representation of GPIOs
|
||||
================================
|
||||
|
||||
Inside a GPIO driver, individual GPIOs are identified by their hardware number,
|
||||
which is a unique number between 0 and n, n being the number of GPIOs managed by
|
||||
the chip. This number is purely internal: the hardware number of a particular
|
||||
GPIO descriptor is never made visible outside of the driver.
|
||||
|
||||
On top of this internal number, each GPIO also need to have a global number in
|
||||
the integer GPIO namespace so that it can be used with the legacy GPIO
|
||||
interface. Each chip must thus have a "base" number (which can be automatically
|
||||
assigned), and for each GPIO the global number will be (base + hardware number).
|
||||
Although the integer representation is considered deprecated, it still has many
|
||||
users and thus needs to be maintained.
|
||||
|
||||
So for example one platform could use numbers 32-159 for GPIOs, with a
|
||||
controller defining 128 GPIOs at a "base" of 32 ; while another platform uses
|
||||
numbers 0..63 with one set of GPIO controllers, 64-79 with another type of GPIO
|
||||
controller, and on one particular board 80-95 with an FPGA. The numbers need not
|
||||
be contiguous; either of those platforms could also use numbers 2000-2063 to
|
||||
identify GPIOs in a bank of I2C GPIO expanders.
|
||||
|
||||
|
||||
Controller Drivers: gpio_chip
|
||||
=============================
|
||||
|
||||
In the gpiolib framework each GPIO controller is packaged as a "struct
|
||||
gpio_chip" (see linux/gpio/driver.h for its complete definition) with members
|
||||
common to each controller of that type:
|
||||
|
||||
- methods to establish GPIO direction
|
||||
- methods used to access GPIO values
|
||||
- method to return the IRQ number associated to a given GPIO
|
||||
- flag saying whether calls to its methods may sleep
|
||||
- optional debugfs dump method (showing extra state like pullup config)
|
||||
- optional base number (will be automatically assigned if omitted)
|
||||
- label for diagnostics and GPIOs mapping using platform data
|
||||
|
||||
The code implementing a gpio_chip should support multiple instances of the
|
||||
controller, possibly using the driver model. That code will configure each
|
||||
gpio_chip and issue gpiochip_add(). Removing a GPIO controller should be rare;
|
||||
use gpiochip_remove() when it is unavoidable.
|
||||
|
||||
Most often a gpio_chip is part of an instance-specific structure with state not
|
||||
exposed by the GPIO interfaces, such as addressing, power management, and more.
|
||||
Chips such as codecs will have complex non-GPIO state.
|
||||
|
||||
Any debugfs dump method should normally ignore signals which haven't been
|
||||
requested as GPIOs. They can use gpiochip_is_requested(), which returns either
|
||||
NULL or the label associated with that GPIO when it was requested.
|
||||
|
||||
Locking IRQ usage
|
||||
-----------------
|
||||
Input GPIOs can be used as IRQ signals. When this happens, a driver is requested
|
||||
to mark the GPIO as being used as an IRQ:
|
||||
|
||||
int gpiod_lock_as_irq(struct gpio_desc *desc)
|
||||
|
||||
This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lock
|
||||
is released:
|
||||
|
||||
void gpiod_unlock_as_irq(struct gpio_desc *desc)
|
|
@ -0,0 +1,119 @@
|
|||
GPIO Interfaces
|
||||
===============
|
||||
|
||||
The documents in this directory give detailed instructions on how to access
|
||||
GPIOs in drivers, and how to write a driver for a device that provides GPIOs
|
||||
itself.
|
||||
|
||||
Due to the history of GPIO interfaces in the kernel, there are two different
|
||||
ways to obtain and use GPIOs:
|
||||
|
||||
- The descriptor-based interface is the preferred way to manipulate GPIOs,
|
||||
and is described by all the files in this directory excepted gpio-legacy.txt.
|
||||
- The legacy integer-based interface which is considered deprecated (but still
|
||||
usable for compatibility reasons) is documented in gpio-legacy.txt.
|
||||
|
||||
The remainder of this document applies to the new descriptor-based interface.
|
||||
gpio-legacy.txt contains the same information applied to the legacy
|
||||
integer-based interface.
|
||||
|
||||
|
||||
What is a GPIO?
|
||||
===============
|
||||
|
||||
A "General Purpose Input/Output" (GPIO) is a flexible software-controlled
|
||||
digital signal. They are provided from many kinds of chip, and are familiar
|
||||
to Linux developers working with embedded and custom hardware. Each GPIO
|
||||
represents a bit connected to a particular pin, or "ball" on Ball Grid Array
|
||||
(BGA) packages. Board schematics show which external hardware connects to
|
||||
which GPIOs. Drivers can be written generically, so that board setup code
|
||||
passes such pin configuration data to drivers.
|
||||
|
||||
System-on-Chip (SOC) processors heavily rely on GPIOs. In some cases, every
|
||||
non-dedicated pin can be configured as a GPIO; and most chips have at least
|
||||
several dozen of them. Programmable logic devices (like FPGAs) can easily
|
||||
provide GPIOs; multifunction chips like power managers, and audio codecs
|
||||
often have a few such pins to help with pin scarcity on SOCs; and there are
|
||||
also "GPIO Expander" chips that connect using the I2C or SPI serial buses.
|
||||
Most PC southbridges have a few dozen GPIO-capable pins (with only the BIOS
|
||||
firmware knowing how they're used).
|
||||
|
||||
The exact capabilities of GPIOs vary between systems. Common options:
|
||||
|
||||
- Output values are writable (high=1, low=0). Some chips also have
|
||||
options about how that value is driven, so that for example only one
|
||||
value might be driven, supporting "wire-OR" and similar schemes for the
|
||||
other value (notably, "open drain" signaling).
|
||||
|
||||
- Input values are likewise readable (1, 0). Some chips support readback
|
||||
of pins configured as "output", which is very useful in such "wire-OR"
|
||||
cases (to support bidirectional signaling). GPIO controllers may have
|
||||
input de-glitch/debounce logic, sometimes with software controls.
|
||||
|
||||
- Inputs can often be used as IRQ signals, often edge triggered but
|
||||
sometimes level triggered. Such IRQs may be configurable as system
|
||||
wakeup events, to wake the system from a low power state.
|
||||
|
||||
- Usually a GPIO will be configurable as either input or output, as needed
|
||||
by different product boards; single direction ones exist too.
|
||||
|
||||
- Most GPIOs can be accessed while holding spinlocks, but those accessed
|
||||
through a serial bus normally can't. Some systems support both types.
|
||||
|
||||
On a given board each GPIO is used for one specific purpose like monitoring
|
||||
MMC/SD card insertion/removal, detecting card write-protect status, driving
|
||||
a LED, configuring a transceiver, bit-banging a serial bus, poking a hardware
|
||||
watchdog, sensing a switch, and so on.
|
||||
|
||||
|
||||
Common GPIO Properties
|
||||
======================
|
||||
|
||||
These properties are met through all the other documents of the GPIO interface
|
||||
and it is useful to understand them, especially if you need to define GPIO
|
||||
mappings.
|
||||
|
||||
Active-High and Active-Low
|
||||
--------------------------
|
||||
It is natural to assume that a GPIO is "active" when its output signal is 1
|
||||
("high"), and inactive when it is 0 ("low"). However in practice the signal of a
|
||||
GPIO may be inverted before is reaches its destination, or a device could decide
|
||||
to have different conventions about what "active" means. Such decisions should
|
||||
be transparent to device drivers, therefore it is possible to define a GPIO as
|
||||
being either active-high ("1" means "active", the default) or active-low ("0"
|
||||
means "active") so that drivers only need to worry about the logical signal and
|
||||
not about what happens at the line level.
|
||||
|
||||
Open Drain and Open Source
|
||||
--------------------------
|
||||
Sometimes shared signals need to use "open drain" (where only the low signal
|
||||
level is actually driven), or "open source" (where only the high signal level is
|
||||
driven) signaling. That term applies to CMOS transistors; "open collector" is
|
||||
used for TTL. A pullup or pulldown resistor causes the high or low signal level.
|
||||
This is sometimes called a "wire-AND"; or more practically, from the negative
|
||||
logic (low=true) perspective this is a "wire-OR".
|
||||
|
||||
One common example of an open drain signal is a shared active-low IRQ line.
|
||||
Also, bidirectional data bus signals sometimes use open drain signals.
|
||||
|
||||
Some GPIO controllers directly support open drain and open source outputs; many
|
||||
don't. When you need open drain signaling but your hardware doesn't directly
|
||||
support it, there's a common idiom you can use to emulate it with any GPIO pin
|
||||
that can be used as either an input or an output:
|
||||
|
||||
LOW: gpiod_direction_output(gpio, 0) ... this drives the signal and overrides
|
||||
the pullup.
|
||||
|
||||
HIGH: gpiod_direction_input(gpio) ... this turns off the output, so the pullup
|
||||
(or some other device) controls the signal.
|
||||
|
||||
The same logic can be applied to emulate open source signaling, by driving the
|
||||
high signal and configuring the GPIO as input for low. This open drain/open
|
||||
source emulation can be handled transparently by the GPIO framework.
|
||||
|
||||
If you are "driving" the signal high but gpiod_get_value(gpio) reports a low
|
||||
value (after the appropriate rise time passes), you know some other component is
|
||||
driving the shared signal low. That's not necessarily an error. As one common
|
||||
example, that's how I2C clocks are stretched: a slave that needs a slower clock
|
||||
delays the rising edge of SCK, and the I2C master adjusts its signaling rate
|
||||
accordingly.
|
|
@ -0,0 +1,155 @@
|
|||
GPIO Sysfs Interface for Userspace
|
||||
==================================
|
||||
|
||||
Platforms which use the "gpiolib" implementors framework may choose to
|
||||
configure a sysfs user interface to GPIOs. This is different from the
|
||||
debugfs interface, since it provides control over GPIO direction and
|
||||
value instead of just showing a gpio state summary. Plus, it could be
|
||||
present on production systems without debugging support.
|
||||
|
||||
Given appropriate hardware documentation for the system, userspace could
|
||||
know for example that GPIO #23 controls the write protect line used to
|
||||
protect boot loader segments in flash memory. System upgrade procedures
|
||||
may need to temporarily remove that protection, first importing a GPIO,
|
||||
then changing its output state, then updating the code before re-enabling
|
||||
the write protection. In normal use, GPIO #23 would never be touched,
|
||||
and the kernel would have no need to know about it.
|
||||
|
||||
Again depending on appropriate hardware documentation, on some systems
|
||||
userspace GPIO can be used to determine system configuration data that
|
||||
standard kernels won't know about. And for some tasks, simple userspace
|
||||
GPIO drivers could be all that the system really needs.
|
||||
|
||||
Note that standard kernel drivers exist for common "LEDs and Buttons"
|
||||
GPIO tasks: "leds-gpio" and "gpio_keys", respectively. Use those
|
||||
instead of talking directly to the GPIOs; they integrate with kernel
|
||||
frameworks better than your userspace code could.
|
||||
|
||||
|
||||
Paths in Sysfs
|
||||
--------------
|
||||
There are three kinds of entry in /sys/class/gpio:
|
||||
|
||||
- Control interfaces used to get userspace control over GPIOs;
|
||||
|
||||
- GPIOs themselves; and
|
||||
|
||||
- GPIO controllers ("gpio_chip" instances).
|
||||
|
||||
That's in addition to standard files including the "device" symlink.
|
||||
|
||||
The control interfaces are write-only:
|
||||
|
||||
/sys/class/gpio/
|
||||
|
||||
"export" ... Userspace may ask the kernel to export control of
|
||||
a GPIO to userspace by writing its number to this file.
|
||||
|
||||
Example: "echo 19 > export" will create a "gpio19" node
|
||||
for GPIO #19, if that's not requested by kernel code.
|
||||
|
||||
"unexport" ... Reverses the effect of exporting to userspace.
|
||||
|
||||
Example: "echo 19 > unexport" will remove a "gpio19"
|
||||
node exported using the "export" file.
|
||||
|
||||
GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
|
||||
and have the following read/write attributes:
|
||||
|
||||
/sys/class/gpio/gpioN/
|
||||
|
||||
"direction" ... reads as either "in" or "out". This value may
|
||||
normally be written. Writing as "out" defaults to
|
||||
initializing the value as low. To ensure glitch free
|
||||
operation, values "low" and "high" may be written to
|
||||
configure the GPIO as an output with that initial value.
|
||||
|
||||
Note that this attribute *will not exist* if the kernel
|
||||
doesn't support changing the direction of a GPIO, or
|
||||
it was exported by kernel code that didn't explicitly
|
||||
allow userspace to reconfigure this GPIO's direction.
|
||||
|
||||
"value" ... reads as either 0 (low) or 1 (high). If the GPIO
|
||||
is configured as an output, this value may be written;
|
||||
any nonzero value is treated as high.
|
||||
|
||||
If the pin can be configured as interrupt-generating interrupt
|
||||
and if it has been configured to generate interrupts (see the
|
||||
description of "edge"), you can poll(2) on that file and
|
||||
poll(2) will return whenever the interrupt was triggered. If
|
||||
you use poll(2), set the events POLLPRI and POLLERR. If you
|
||||
use select(2), set the file descriptor in exceptfds. After
|
||||
poll(2) returns, either lseek(2) to the beginning of the sysfs
|
||||
file and read the new value or close the file and re-open it
|
||||
to read the value.
|
||||
|
||||
"edge" ... reads as either "none", "rising", "falling", or
|
||||
"both". Write these strings to select the signal edge(s)
|
||||
that will make poll(2) on the "value" file return.
|
||||
|
||||
This file exists only if the pin can be configured as an
|
||||
interrupt generating input pin.
|
||||
|
||||
"active_low" ... reads as either 0 (false) or 1 (true). Write
|
||||
any nonzero value to invert the value attribute both
|
||||
for reading and writing. Existing and subsequent
|
||||
poll(2) support configuration via the edge attribute
|
||||
for "rising" and "falling" edges will follow this
|
||||
setting.
|
||||
|
||||
GPIO controllers have paths like /sys/class/gpio/gpiochip42/ (for the
|
||||
controller implementing GPIOs starting at #42) and have the following
|
||||
read-only attributes:
|
||||
|
||||
/sys/class/gpio/gpiochipN/
|
||||
|
||||
"base" ... same as N, the first GPIO managed by this chip
|
||||
|
||||
"label" ... provided for diagnostics (not always unique)
|
||||
|
||||
"ngpio" ... how many GPIOs this manges (N to N + ngpio - 1)
|
||||
|
||||
Board documentation should in most cases cover what GPIOs are used for
|
||||
what purposes. However, those numbers are not always stable; GPIOs on
|
||||
a daughtercard might be different depending on the base board being used,
|
||||
or other cards in the stack. In such cases, you may need to use the
|
||||
gpiochip nodes (possibly in conjunction with schematics) to determine
|
||||
the correct GPIO number to use for a given signal.
|
||||
|
||||
|
||||
Exporting from Kernel code
|
||||
--------------------------
|
||||
Kernel code can explicitly manage exports of GPIOs which have already been
|
||||
requested using gpio_request():
|
||||
|
||||
/* export the GPIO to userspace */
|
||||
int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
|
||||
|
||||
/* reverse gpio_export() */
|
||||
void gpiod_unexport(struct gpio_desc *desc);
|
||||
|
||||
/* create a sysfs link to an exported GPIO node */
|
||||
int gpiod_export_link(struct device *dev, const char *name,
|
||||
struct gpio_desc *desc);
|
||||
|
||||
/* change the polarity of a GPIO node in sysfs */
|
||||
int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value);
|
||||
|
||||
After a kernel driver requests a GPIO, it may only be made available in
|
||||
the sysfs interface by gpiod_export(). The driver can control whether the
|
||||
signal direction may change. This helps drivers prevent userspace code
|
||||
from accidentally clobbering important system state.
|
||||
|
||||
This explicit exporting can help with debugging (by making some kinds
|
||||
of experiments easier), or can provide an always-there interface that's
|
||||
suitable for documenting as part of a board support package.
|
||||
|
||||
After the GPIO has been exported, gpiod_export_link() allows creating
|
||||
symlinks from elsewhere in sysfs to the GPIO sysfs node. Drivers can
|
||||
use this to provide the interface under their own device in sysfs with
|
||||
a descriptive name.
|
||||
|
||||
Drivers can use gpiod_sysfs_set_active_low() to hide GPIO line polarity
|
||||
differences between boards from user space. Polarity change can be done both
|
||||
before and after gpiod_export(), and previously enabled poll(2) support for
|
||||
either rising or falling edge will be reconfigured to follow this setting.
|
|
@ -1190,15 +1190,24 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
owned by uid=0.
|
||||
|
||||
ima_hash= [IMA]
|
||||
Format: { "sha1" | "md5" }
|
||||
Format: { md5 | sha1 | rmd160 | sha256 | sha384
|
||||
| sha512 | ... }
|
||||
default: "sha1"
|
||||
|
||||
The list of supported hash algorithms is defined
|
||||
in crypto/hash_info.h.
|
||||
|
||||
ima_tcb [IMA]
|
||||
Load a policy which meets the needs of the Trusted
|
||||
Computing Base. This means IMA will measure all
|
||||
programs exec'd, files mmap'd for exec, and all files
|
||||
opened for read by uid=0.
|
||||
|
||||
ima_template= [IMA]
|
||||
Select one of defined IMA measurements template formats.
|
||||
Formats: { "ima" | "ima-ng" }
|
||||
Default: "ima-ng"
|
||||
|
||||
init= [KNL]
|
||||
Format: <full_path>
|
||||
Run specified binary instead of /sbin/init as init
|
||||
|
|
|
@ -313,7 +313,7 @@ static struct mic_device_desc *get_device_desc(struct mic_info *mic, int type)
|
|||
int i;
|
||||
void *dp = get_dp(mic, type);
|
||||
|
||||
for (i = mic_aligned_size(struct mic_bootparam); i < PAGE_SIZE;
|
||||
for (i = sizeof(struct mic_bootparam); i < PAGE_SIZE;
|
||||
i += mic_total_desc_size(d)) {
|
||||
d = dp + i;
|
||||
|
||||
|
@ -445,8 +445,8 @@ init_vr(struct mic_info *mic, int fd, int type,
|
|||
__func__, mic->name, vr0->va, vr0->info, vr_size,
|
||||
vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
|
||||
mpsslog("magic 0x%x expected 0x%x\n",
|
||||
vr0->info->magic, MIC_MAGIC + type);
|
||||
assert(vr0->info->magic == MIC_MAGIC + type);
|
||||
le32toh(vr0->info->magic), MIC_MAGIC + type);
|
||||
assert(le32toh(vr0->info->magic) == MIC_MAGIC + type);
|
||||
if (vr1) {
|
||||
vr1->va = (struct mic_vring *)
|
||||
&va[MIC_DEVICE_PAGE_END + vr_size];
|
||||
|
@ -458,8 +458,8 @@ init_vr(struct mic_info *mic, int fd, int type,
|
|||
__func__, mic->name, vr1->va, vr1->info, vr_size,
|
||||
vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
|
||||
mpsslog("magic 0x%x expected 0x%x\n",
|
||||
vr1->info->magic, MIC_MAGIC + type + 1);
|
||||
assert(vr1->info->magic == MIC_MAGIC + type + 1);
|
||||
le32toh(vr1->info->magic), MIC_MAGIC + type + 1);
|
||||
assert(le32toh(vr1->info->magic) == MIC_MAGIC + type + 1);
|
||||
}
|
||||
done:
|
||||
return va;
|
||||
|
@ -520,7 +520,7 @@ static void *
|
|||
virtio_net(void *arg)
|
||||
{
|
||||
static __u8 vnet_hdr[2][sizeof(struct virtio_net_hdr)];
|
||||
static __u8 vnet_buf[2][MAX_NET_PKT_SIZE] __aligned(64);
|
||||
static __u8 vnet_buf[2][MAX_NET_PKT_SIZE] __attribute__ ((aligned(64)));
|
||||
struct iovec vnet_iov[2][2] = {
|
||||
{ { .iov_base = vnet_hdr[0], .iov_len = sizeof(vnet_hdr[0]) },
|
||||
{ .iov_base = vnet_buf[0], .iov_len = sizeof(vnet_buf[0]) } },
|
||||
|
@ -1412,6 +1412,12 @@ mic_config(void *arg)
|
|||
}
|
||||
|
||||
do {
|
||||
ret = lseek(fd, 0, SEEK_SET);
|
||||
if (ret < 0) {
|
||||
mpsslog("%s: Failed to seek to file start '%s': %s\n",
|
||||
mic->name, pathname, strerror(errno));
|
||||
goto close_error1;
|
||||
}
|
||||
ret = read(fd, value, sizeof(value));
|
||||
if (ret < 0) {
|
||||
mpsslog("%s: Failed to read sysfs entry '%s': %s\n",
|
||||
|
|
|
@ -577,9 +577,6 @@ tcp_limit_output_bytes - INTEGER
|
|||
typical pfifo_fast qdiscs.
|
||||
tcp_limit_output_bytes limits the number of bytes on qdisc
|
||||
or device to reduce artificial RTT/cwnd and reduce bufferbloat.
|
||||
Note: For GSO/TSO enabled flows, we try to have at least two
|
||||
packets in flight. Reducing tcp_limit_output_bytes might also
|
||||
reduce the size of individual GSO packet (64KB being the max)
|
||||
Default: 131072
|
||||
|
||||
tcp_challenge_ack_limit - INTEGER
|
||||
|
|
|
@ -123,6 +123,16 @@ Transmission process is similar to capture as shown below.
|
|||
[shutdown] close() --------> destruction of the transmission socket and
|
||||
deallocation of all associated resources.
|
||||
|
||||
Socket creation and destruction is also straight forward, and is done
|
||||
the same way as in capturing described in the previous paragraph:
|
||||
|
||||
int fd = socket(PF_PACKET, mode, 0);
|
||||
|
||||
The protocol can optionally be 0 in case we only want to transmit
|
||||
via this socket, which avoids an expensive call to packet_rcv().
|
||||
In this case, you also need to bind(2) the TX_RING with sll_protocol = 0
|
||||
set. Otherwise, htons(ETH_P_ALL) or any other protocol, for example.
|
||||
|
||||
Binding the socket to your network interface is mandatory (with zero copy) to
|
||||
know the header size of frames used in the circular buffer.
|
||||
|
||||
|
|
|
@ -547,13 +547,11 @@ helper functions described in Section 4. In that case, pm_runtime_resume()
|
|||
should be used. Of course, for this purpose the device's runtime PM has to be
|
||||
enabled earlier by calling pm_runtime_enable().
|
||||
|
||||
If the device bus type's or driver's ->probe() callback runs
|
||||
pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts,
|
||||
they will fail returning -EAGAIN, because the device's usage counter is
|
||||
incremented by the driver core before executing ->probe(). Still, it may be
|
||||
desirable to suspend the device as soon as ->probe() has finished, so the driver
|
||||
core uses pm_runtime_put_sync() to invoke the subsystem-level idle callback for
|
||||
the device at that time.
|
||||
It may be desirable to suspend the device once ->probe() has finished.
|
||||
Therefore the driver core uses the asyncronous pm_request_idle() to submit a
|
||||
request to execute the subsystem-level idle callback for the device at that
|
||||
time. A driver that makes use of the runtime autosuspend feature, may want to
|
||||
update the last busy mark before returning from ->probe().
|
||||
|
||||
Moreover, the driver core prevents runtime PM callbacks from racing with the bus
|
||||
notifier callback in __device_release_driver(), which is necessary, because the
|
||||
|
@ -656,7 +654,7 @@ out the following operations:
|
|||
__pm_runtime_disable() with 'false' as the second argument for every device
|
||||
right before executing the subsystem-level .suspend_late() callback for it.
|
||||
|
||||
* During system resume it calls pm_runtime_enable() and pm_runtime_put_sync()
|
||||
* During system resume it calls pm_runtime_enable() and pm_runtime_put()
|
||||
for every device right after executing the subsystem-level .resume_early()
|
||||
callback and right after executing the subsystem-level .resume() callback
|
||||
for it, respectively.
|
||||
|
|
|
@ -22,3 +22,5 @@ keys.txt
|
|||
- description of the kernel key retention service.
|
||||
tomoyo.txt
|
||||
- documentation on the TOMOYO Linux Security Module.
|
||||
IMA-templates.txt
|
||||
- documentation on the template management mechanism for IMA.
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
IMA Template Management Mechanism
|
||||
|
||||
|
||||
==== INTRODUCTION ====
|
||||
|
||||
The original 'ima' template is fixed length, containing the filedata hash
|
||||
and pathname. The filedata hash is limited to 20 bytes (md5/sha1).
|
||||
The pathname is a null terminated string, limited to 255 characters.
|
||||
To overcome these limitations and to add additional file metadata, it is
|
||||
necessary to extend the current version of IMA by defining additional
|
||||
templates. For example, information that could be possibly reported are
|
||||
the inode UID/GID or the LSM labels either of the inode and of the process
|
||||
that is accessing it.
|
||||
|
||||
However, the main problem to introduce this feature is that, each time
|
||||
a new template is defined, the functions that generate and display
|
||||
the measurements list would include the code for handling a new format
|
||||
and, thus, would significantly grow over the time.
|
||||
|
||||
The proposed solution solves this problem by separating the template
|
||||
management from the remaining IMA code. The core of this solution is the
|
||||
definition of two new data structures: a template descriptor, to determine
|
||||
which information should be included in the measurement list; a template
|
||||
field, to generate and display data of a given type.
|
||||
|
||||
Managing templates with these structures is very simple. To support
|
||||
a new data type, developers define the field identifier and implement
|
||||
two functions, init() and show(), respectively to generate and display
|
||||
measurement entries. Defining a new template descriptor requires
|
||||
specifying the template format, a string of field identifiers separated
|
||||
by the '|' character. While in the current implementation it is possible
|
||||
to define new template descriptors only by adding their definition in the
|
||||
template specific code (ima_template.c), in a future version it will be
|
||||
possible to register a new template on a running kernel by supplying to IMA
|
||||
the desired format string. In this version, IMA initializes at boot time
|
||||
all defined template descriptors by translating the format into an array
|
||||
of template fields structures taken from the set of the supported ones.
|
||||
|
||||
After the initialization step, IMA will call ima_alloc_init_template()
|
||||
(new function defined within the patches for the new template management
|
||||
mechanism) to generate a new measurement entry by using the template
|
||||
descriptor chosen through the kernel configuration or through the newly
|
||||
introduced 'ima_template=' kernel command line parameter. It is during this
|
||||
phase that the advantages of the new architecture are clearly shown:
|
||||
the latter function will not contain specific code to handle a given template
|
||||
but, instead, it simply calls the init() method of the template fields
|
||||
associated to the chosen template descriptor and store the result (pointer
|
||||
to allocated data and data length) in the measurement entry structure.
|
||||
|
||||
The same mechanism is employed to display measurements entries.
|
||||
The functions ima[_ascii]_measurements_show() retrieve, for each entry,
|
||||
the template descriptor used to produce that entry and call the show()
|
||||
method for each item of the array of template fields structures.
|
||||
|
||||
|
||||
|
||||
==== SUPPORTED TEMPLATE FIELDS AND DESCRIPTORS ====
|
||||
|
||||
In the following, there is the list of supported template fields
|
||||
('<identifier>': description), that can be used to define new template
|
||||
descriptors by adding their identifier to the format string
|
||||
(support for more data types will be added later):
|
||||
|
||||
- 'd': the digest of the event (i.e. the digest of a measured file),
|
||||
calculated with the SHA1 or MD5 hash algorithm;
|
||||
- 'n': the name of the event (i.e. the file name), with size up to 255 bytes;
|
||||
- 'd-ng': the digest of the event, calculated with an arbitrary hash
|
||||
algorithm (field format: [<hash algo>:]digest, where the digest
|
||||
prefix is shown only if the hash algorithm is not SHA1 or MD5);
|
||||
- 'n-ng': the name of the event, without size limitations.
|
||||
|
||||
|
||||
Below, there is the list of defined template descriptors:
|
||||
- "ima": its format is 'd|n';
|
||||
- "ima-ng" (default): its format is 'd-ng|n-ng'.
|
||||
|
||||
|
||||
|
||||
==== USE ====
|
||||
|
||||
To specify the template descriptor to be used to generate measurement entries,
|
||||
currently the following methods are supported:
|
||||
|
||||
- select a template descriptor among those supported in the kernel
|
||||
configuration ('ima-ng' is the default choice);
|
||||
- specify a template descriptor name from the kernel command line through
|
||||
the 'ima_template=' parameter.
|
|
@ -865,15 +865,14 @@ encountered:
|
|||
calling processes has a searchable link to the key from one of its
|
||||
keyrings. There are three functions for dealing with these:
|
||||
|
||||
key_ref_t make_key_ref(const struct key *key,
|
||||
unsigned long possession);
|
||||
key_ref_t make_key_ref(const struct key *key, bool possession);
|
||||
|
||||
struct key *key_ref_to_ptr(const key_ref_t key_ref);
|
||||
|
||||
unsigned long is_key_possessed(const key_ref_t key_ref);
|
||||
bool is_key_possessed(const key_ref_t key_ref);
|
||||
|
||||
The first function constructs a key reference from a key pointer and
|
||||
possession information (which must be 0 or 1 and not any other value).
|
||||
possession information (which must be true or false).
|
||||
|
||||
The second function retrieves the key pointer from a reference and the
|
||||
third retrieves the possession flag.
|
||||
|
@ -961,14 +960,17 @@ payload contents" for more information.
|
|||
the argument will not be parsed.
|
||||
|
||||
|
||||
(*) Extra references can be made to a key by calling the following function:
|
||||
(*) Extra references can be made to a key by calling one of the following
|
||||
functions:
|
||||
|
||||
struct key *__key_get(struct key *key);
|
||||
struct key *key_get(struct key *key);
|
||||
|
||||
These need to be disposed of by calling key_put() when they've been
|
||||
finished with. The key pointer passed in will be returned. If the pointer
|
||||
is NULL or CONFIG_KEYS is not set then the key will not be dereferenced and
|
||||
no increment will take place.
|
||||
Keys so references will need to be disposed of by calling key_put() when
|
||||
they've been finished with. The key pointer passed in will be returned.
|
||||
|
||||
In the case of key_get(), if the pointer is NULL or CONFIG_KEYS is not set
|
||||
then the key will not be dereferenced and no increment will take place.
|
||||
|
||||
|
||||
(*) A key's serial number can be obtained by calling:
|
||||
|
|
|
@ -440,15 +440,15 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
|
|||
buf += " /*\n"
|
||||
buf += " * Setup default attribute lists for various fabric->tf_cit_tmpl\n"
|
||||
buf += " */\n"
|
||||
buf += " TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = " + fabric_mod_name + "_wwn_attrs;\n"
|
||||
buf += " TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = NULL;\n"
|
||||
buf += " TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = NULL;\n"
|
||||
buf += " TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = NULL;\n"
|
||||
buf += " TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL;\n"
|
||||
buf += " TF_CIT_TMPL(fabric)->tfc_tpg_nacl_base_cit.ct_attrs = NULL;\n"
|
||||
buf += " TF_CIT_TMPL(fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;\n"
|
||||
buf += " TF_CIT_TMPL(fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = NULL;\n"
|
||||
buf += " TF_CIT_TMPL(fabric)->tfc_tpg_nacl_param_cit.ct_attrs = NULL;\n"
|
||||
buf += " fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = " + fabric_mod_name + "_wwn_attrs;\n"
|
||||
buf += " fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = NULL;\n"
|
||||
buf += " fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;\n"
|
||||
buf += " fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;\n"
|
||||
buf += " fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;\n"
|
||||
buf += " fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;\n"
|
||||
buf += " fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;\n"
|
||||
buf += " fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;\n"
|
||||
buf += " fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;\n"
|
||||
buf += " /*\n"
|
||||
buf += " * Register the fabric for use within TCM\n"
|
||||
buf += " */\n"
|
||||
|
|
|
@ -63,9 +63,9 @@ levels.
|
|||
PMD split lock enabling requires pgtable_pmd_page_ctor() call on PMD table
|
||||
allocation and pgtable_pmd_page_dtor() on freeing.
|
||||
|
||||
Allocation usually happens in pmd_alloc_one(), freeing in pmd_free(), but
|
||||
make sure you cover all PMD table allocation / freeing paths: i.e X86_PAE
|
||||
preallocate few PMDs on pgd_alloc().
|
||||
Allocation usually happens in pmd_alloc_one(), freeing in pmd_free() and
|
||||
pmd_free_tlb(), but make sure you cover all PMD table allocation / freeing
|
||||
paths: i.e X86_PAE preallocate few PMDs on pgd_alloc().
|
||||
|
||||
With everything in place you can set CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK.
|
||||
|
||||
|
|
99
MAINTAINERS
99
MAINTAINERS
|
@ -893,19 +893,14 @@ F: arch/arm/include/asm/hardware/dec21285.h
|
|||
F: arch/arm/mach-footbridge/
|
||||
|
||||
ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
|
||||
M: Shawn Guo <shawn.guo@linaro.org>
|
||||
M: Sascha Hauer <kernel@pengutronix.de>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
T: git git://git.pengutronix.de/git/imx/linux-2.6.git
|
||||
F: arch/arm/mach-imx/
|
||||
F: arch/arm/configs/imx*_defconfig
|
||||
|
||||
ARM/FREESCALE IMX6
|
||||
M: Shawn Guo <shawn.guo@linaro.org>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
T: git git://git.linaro.org/people/shawnguo/linux-2.6.git
|
||||
F: arch/arm/mach-imx/*imx6*
|
||||
F: arch/arm/mach-imx/
|
||||
F: arch/arm/boot/dts/imx*
|
||||
F: arch/arm/configs/imx*_defconfig
|
||||
|
||||
ARM/FREESCALE MXS ARM ARCHITECTURE
|
||||
M: Shawn Guo <shawn.guo@linaro.org>
|
||||
|
@ -1934,7 +1929,8 @@ S: Maintained
|
|||
F: drivers/gpio/gpio-bt8xx.c
|
||||
|
||||
BTRFS FILE SYSTEM
|
||||
M: Chris Mason <chris.mason@fusionio.com>
|
||||
M: Chris Mason <clm@fb.com>
|
||||
M: Josef Bacik <jbacik@fb.com>
|
||||
L: linux-btrfs@vger.kernel.org
|
||||
W: http://btrfs.wiki.kernel.org/
|
||||
Q: http://patchwork.kernel.org/project/linux-btrfs/list/
|
||||
|
@ -2137,11 +2133,17 @@ S: Maintained
|
|||
F: Documentation/zh_CN/
|
||||
|
||||
CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
|
||||
M: Alexander Shishkin <alexander.shishkin@linux.intel.com>
|
||||
M: Peter Chen <Peter.Chen@freescale.com>
|
||||
T: git://github.com/hzpeterchen/linux-usb.git
|
||||
L: linux-usb@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/usb/chipidea/
|
||||
|
||||
CHROME HARDWARE PLATFORM SUPPORT
|
||||
M: Olof Johansson <olof@lixom.net>
|
||||
S: Maintained
|
||||
F: drivers/platform/chrome/
|
||||
|
||||
CISCO VIC ETHERNET NIC DRIVER
|
||||
M: Christian Benvenuti <benve@cisco.com>
|
||||
M: Sujith Sankar <ssujith@cisco.com>
|
||||
|
@ -2468,7 +2470,7 @@ S: Maintained
|
|||
F: drivers/media/dvb-frontends/cxd2820r*
|
||||
|
||||
CXGB3 ETHERNET DRIVER (CXGB3)
|
||||
M: Divy Le Ray <divy@chelsio.com>
|
||||
M: Santosh Raspatur <santosh@chelsio.com>
|
||||
L: netdev@vger.kernel.org
|
||||
W: http://www.chelsio.com
|
||||
S: Supported
|
||||
|
@ -4038,12 +4040,26 @@ W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
|
|||
S: Maintained
|
||||
F: fs/hpfs/
|
||||
|
||||
HSI SUBSYSTEM
|
||||
M: Sebastian Reichel <sre@debian.org>
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-bus-hsi
|
||||
F: drivers/hsi/
|
||||
F: include/linux/hsi/
|
||||
F: include/uapi/linux/hsi/
|
||||
|
||||
HSO 3G MODEM DRIVER
|
||||
M: Jan Dumon <j.dumon@option.com>
|
||||
W: http://www.pharscape.org
|
||||
S: Maintained
|
||||
F: drivers/net/usb/hso.c
|
||||
|
||||
HSR NETWORK PROTOCOL
|
||||
M: Arvid Brodin <arvid.brodin@alten.se>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: net/hsr/
|
||||
|
||||
HTCPEN TOUCHSCREEN DRIVER
|
||||
M: Pau Oliva Fora <pof@eslack.org>
|
||||
L: linux-input@vger.kernel.org
|
||||
|
@ -4065,6 +4081,7 @@ F: arch/x86/include/uapi/asm/hyperv.h
|
|||
F: arch/x86/kernel/cpu/mshyperv.c
|
||||
F: drivers/hid/hid-hyperv.c
|
||||
F: drivers/hv/
|
||||
F: drivers/input/serio/hyperv-keyboard.c
|
||||
F: drivers/net/hyperv/
|
||||
F: drivers/scsi/storvsc_drv.c
|
||||
F: drivers/video/hyperv_fb.c
|
||||
|
@ -4449,10 +4466,8 @@ M: Bruce Allan <bruce.w.allan@intel.com>
|
|||
M: Carolyn Wyborny <carolyn.wyborny@intel.com>
|
||||
M: Don Skidmore <donald.c.skidmore@intel.com>
|
||||
M: Greg Rose <gregory.v.rose@intel.com>
|
||||
M: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
|
||||
M: Alex Duyck <alexander.h.duyck@intel.com>
|
||||
M: John Ronciak <john.ronciak@intel.com>
|
||||
M: Tushar Dave <tushar.n.dave@intel.com>
|
||||
L: e1000-devel@lists.sourceforge.net
|
||||
W: http://www.intel.com/support/feedback.htm
|
||||
W: http://e1000.sourceforge.net/
|
||||
|
@ -5255,7 +5270,7 @@ S: Maintained
|
|||
F: Documentation/lockdep*.txt
|
||||
F: Documentation/lockstat.txt
|
||||
F: include/linux/lockdep.h
|
||||
F: kernel/lockdep*
|
||||
F: kernel/locking/
|
||||
|
||||
LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP/Vista Dynamic Disks)
|
||||
M: "Richard Russon (FlatCap)" <ldm@flatcap.org>
|
||||
|
@ -5967,10 +5982,10 @@ F: drivers/nfc/
|
|||
F: include/linux/platform_data/pn544.h
|
||||
|
||||
NFS, SUNRPC, AND LOCKD CLIENTS
|
||||
M: Trond Myklebust <Trond.Myklebust@netapp.com>
|
||||
M: Trond Myklebust <trond.myklebust@primarydata.com>
|
||||
L: linux-nfs@vger.kernel.org
|
||||
W: http://client.linux-nfs.org
|
||||
T: git git://git.linux-nfs.org/pub/linux/nfs-2.6.git
|
||||
T: git git://git.linux-nfs.org/projects/trondmy/linux-nfs.git
|
||||
S: Maintained
|
||||
F: fs/lockd/
|
||||
F: fs/nfs/
|
||||
|
@ -6237,8 +6252,8 @@ OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
|
|||
M: Rob Herring <rob.herring@calxeda.com>
|
||||
M: Pawel Moll <pawel.moll@arm.com>
|
||||
M: Mark Rutland <mark.rutland@arm.com>
|
||||
M: Stephen Warren <swarren@wwwdotorg.org>
|
||||
M: Ian Campbell <ijc+devicetree@hellion.org.uk>
|
||||
M: Kumar Gala <galak@codeaurora.org>
|
||||
L: devicetree@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/
|
||||
|
@ -6448,19 +6463,52 @@ F: drivers/pci/
|
|||
F: include/linux/pci*
|
||||
F: arch/x86/pci/
|
||||
|
||||
PCI DRIVER FOR IMX6
|
||||
M: Richard Zhu <r65037@freescale.com>
|
||||
M: Shawn Guo <shawn.guo@linaro.org>
|
||||
L: linux-pci@vger.kernel.org
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: drivers/pci/host/*imx6*
|
||||
|
||||
PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support)
|
||||
M: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
M: Jason Cooper <jason@lakedaemon.net>
|
||||
L: linux-pci@vger.kernel.org
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: drivers/pci/host/*mvebu*
|
||||
|
||||
PCI DRIVER FOR NVIDIA TEGRA
|
||||
M: Thierry Reding <thierry.reding@gmail.com>
|
||||
L: linux-tegra@vger.kernel.org
|
||||
L: linux-pci@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
|
||||
F: drivers/pci/host/pci-tegra.c
|
||||
|
||||
PCI DRIVER FOR RENESAS R-CAR
|
||||
M: Simon Horman <horms@verge.net.au>
|
||||
L: linux-pci@vger.kernel.org
|
||||
L: linux-sh@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/pci/host/*rcar*
|
||||
|
||||
PCI DRIVER FOR SAMSUNG EXYNOS
|
||||
M: Jingoo Han <jg1.han@samsung.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: drivers/pci/host/pci-exynos.c
|
||||
|
||||
PCI DRIVER FOR SYNOPSIS DESIGNWARE
|
||||
M: Mohit Kumar <mohit.kumar@st.com>
|
||||
M: Jingoo Han <jg1.han@samsung.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/pci/host/*designware*
|
||||
|
||||
PCMCIA SUBSYSTEM
|
||||
P: Linux PCMCIA Team
|
||||
L: linux-pcmcia@lists.infradead.org
|
||||
|
@ -7379,7 +7427,6 @@ S: Maintained
|
|||
F: kernel/sched/
|
||||
F: include/linux/sched.h
|
||||
F: include/uapi/linux/sched.h
|
||||
F: kernel/wait.c
|
||||
F: include/linux/wait.h
|
||||
|
||||
SCORE ARCHITECTURE
|
||||
|
@ -7515,9 +7562,10 @@ SELINUX SECURITY MODULE
|
|||
M: Stephen Smalley <sds@tycho.nsa.gov>
|
||||
M: James Morris <james.l.morris@oracle.com>
|
||||
M: Eric Paris <eparis@parisplace.org>
|
||||
M: Paul Moore <paul@paul-moore.com>
|
||||
L: selinux@tycho.nsa.gov (subscribers-only, general discussion)
|
||||
W: http://selinuxproject.org
|
||||
T: git git://git.infradead.org/users/eparis/selinux.git
|
||||
T: git git://git.infradead.org/users/pcmoore/selinux
|
||||
S: Supported
|
||||
F: include/linux/selinux*
|
||||
F: security/selinux/
|
||||
|
@ -8664,6 +8712,7 @@ F: drivers/media/usb/tm6000/
|
|||
TPM DEVICE DRIVER
|
||||
M: Leonidas Da Silva Barbosa <leosilva@linux.vnet.ibm.com>
|
||||
M: Ashley Lai <ashley@ashleylai.com>
|
||||
M: Peter Huewe <peterhuewe@gmx.de>
|
||||
M: Rajiv Andrade <mail@srajiv.net>
|
||||
W: http://tpmdd.sourceforge.net
|
||||
M: Marcel Selhorst <tpmdd@selhorst.net>
|
||||
|
@ -8960,8 +9009,8 @@ USB PEGASUS DRIVER
|
|||
M: Petko Manolov <petkan@nucleusys.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
L: netdev@vger.kernel.org
|
||||
T: git git://git.code.sf.net/p/pegasus2/git
|
||||
W: http://pegasus2.sourceforge.net/
|
||||
T: git git://github.com/petkan/pegasus.git
|
||||
W: https://github.com/petkan/pegasus
|
||||
S: Maintained
|
||||
F: drivers/net/usb/pegasus.*
|
||||
|
||||
|
@ -8982,8 +9031,8 @@ USB RTL8150 DRIVER
|
|||
M: Petko Manolov <petkan@nucleusys.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
L: netdev@vger.kernel.org
|
||||
T: git git://git.code.sf.net/p/pegasus2/git
|
||||
W: http://pegasus2.sourceforge.net/
|
||||
T: git git://github.com/petkan/rtl8150.git
|
||||
W: https://github.com/petkan/rtl8150
|
||||
S: Maintained
|
||||
F: drivers/net/usb/rtl8150.c
|
||||
|
||||
|
@ -9522,8 +9571,8 @@ F: drivers/xen/*swiotlb*
|
|||
|
||||
XFS FILESYSTEM
|
||||
P: Silicon Graphics Inc
|
||||
M: Dave Chinner <dchinner@fromorbit.com>
|
||||
M: Ben Myers <bpm@sgi.com>
|
||||
M: Alex Elder <elder@kernel.org>
|
||||
M: xfs@oss.sgi.com
|
||||
L: xfs@oss.sgi.com
|
||||
W: http://oss.sgi.com/projects/xfs
|
||||
|
|
4
Makefile
4
Makefile
|
@ -1,7 +1,7 @@
|
|||
VERSION = 3
|
||||
PATCHLEVEL = 12
|
||||
PATCHLEVEL = 13
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION =
|
||||
EXTRAVERSION = -rc4
|
||||
NAME = One Giant Leap for Frogkind
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
@ -16,8 +16,8 @@ config ALPHA
|
|||
select ARCH_WANT_IPC_PARSE_VERSION
|
||||
select ARCH_HAVE_NMI_SAFE_CMPXCHG
|
||||
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_CMOS_UPDATE
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_STRNLEN_USER
|
||||
select HAVE_MOD_ARCH_SPECIFIC
|
||||
|
@ -488,6 +488,20 @@ config VGA_HOSE
|
|||
which always have multiple hoses, and whose consoles support it.
|
||||
|
||||
|
||||
config ALPHA_QEMU
|
||||
bool "Run under QEMU emulation"
|
||||
depends on !ALPHA_GENERIC
|
||||
---help---
|
||||
Assume the presence of special features supported by QEMU PALcode
|
||||
that reduce the overhead of system emulation.
|
||||
|
||||
Generic kernels will auto-detect QEMU. But when building a
|
||||
system-specific kernel, the assumption is that we want to
|
||||
elimiate as many runtime tests as possible.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
|
||||
config ALPHA_SRM
|
||||
bool "Use SRM as bootloader" if ALPHA_CABRIOLET || ALPHA_AVANTI_CH || ALPHA_EB64P || ALPHA_PC164 || ALPHA_TAKARA || ALPHA_EB164 || ALPHA_ALCOR || ALPHA_MIATA || ALPHA_LX164 || ALPHA_SX164 || ALPHA_NAUTILUS || ALPHA_NONAME
|
||||
depends on TTY
|
||||
|
@ -572,6 +586,30 @@ config NUMA
|
|||
Access). This option is for configuring high-end multiprocessor
|
||||
server machines. If in doubt, say N.
|
||||
|
||||
config ALPHA_WTINT
|
||||
bool "Use WTINT" if ALPHA_SRM || ALPHA_GENERIC
|
||||
default y if ALPHA_QEMU
|
||||
default n if ALPHA_EV5 || ALPHA_EV56 || (ALPHA_EV4 && !ALPHA_LCA)
|
||||
default n if !ALPHA_SRM && !ALPHA_GENERIC
|
||||
default y if SMP
|
||||
---help---
|
||||
The Wait for Interrupt (WTINT) PALcall attempts to place the CPU
|
||||
to sleep until the next interrupt. This may reduce the power
|
||||
consumed, and the heat produced by the computer. However, it has
|
||||
the side effect of making the cycle counter unreliable as a timing
|
||||
device across the sleep.
|
||||
|
||||
For emulation under QEMU, definitely say Y here, as we have other
|
||||
mechanisms for measuring time than the cycle counter.
|
||||
|
||||
For EV4 (but not LCA), EV5 and EV56 systems, or for systems running
|
||||
MILO, sleep mode is not supported so you might as well say N here.
|
||||
|
||||
For SMP systems we cannot use the cycle counter for timing anyway,
|
||||
so you might as well say Y here.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config NODES_SHIFT
|
||||
int
|
||||
default "7"
|
||||
|
@ -613,9 +651,41 @@ config VERBOSE_MCHECK_ON
|
|||
|
||||
Take the default (1) unless you want more control or more info.
|
||||
|
||||
choice
|
||||
prompt "Timer interrupt frequency (HZ)?"
|
||||
default HZ_128 if ALPHA_QEMU
|
||||
default HZ_1200 if ALPHA_RAWHIDE
|
||||
default HZ_1024
|
||||
---help---
|
||||
The frequency at which timer interrupts occur. A high frequency
|
||||
minimizes latency, whereas a low frequency minimizes overhead of
|
||||
process accounting. The later effect is especially significant
|
||||
when being run under QEMU.
|
||||
|
||||
Note that some Alpha hardware cannot change the interrupt frequency
|
||||
of the timer. If unsure, say 1024 (or 1200 for Rawhide).
|
||||
|
||||
config HZ_32
|
||||
bool "32 Hz"
|
||||
config HZ_64
|
||||
bool "64 Hz"
|
||||
config HZ_128
|
||||
bool "128 Hz"
|
||||
config HZ_256
|
||||
bool "256 Hz"
|
||||
config HZ_1024
|
||||
bool "1024 Hz"
|
||||
config HZ_1200
|
||||
bool "1200 Hz"
|
||||
endchoice
|
||||
|
||||
config HZ
|
||||
int
|
||||
default 1200 if ALPHA_RAWHIDE
|
||||
int
|
||||
default 32 if HZ_32
|
||||
default 64 if HZ_64
|
||||
default 128 if HZ_128
|
||||
default 256 if HZ_256
|
||||
default 1200 if HZ_1200
|
||||
default 1024
|
||||
|
||||
source "drivers/pci/Kconfig"
|
||||
|
|
|
@ -33,6 +33,7 @@ struct alpha_machine_vector
|
|||
|
||||
int nr_irqs;
|
||||
int rtc_port;
|
||||
int rtc_boot_cpu_only;
|
||||
unsigned int max_asn;
|
||||
unsigned long max_isa_dma_address;
|
||||
unsigned long irq_probe_mask;
|
||||
|
@ -95,9 +96,6 @@ struct alpha_machine_vector
|
|||
|
||||
struct _alpha_agp_info *(*agp_info)(void);
|
||||
|
||||
unsigned int (*rtc_get_time)(struct rtc_time *);
|
||||
int (*rtc_set_time)(struct rtc_time *);
|
||||
|
||||
const char *vector_name;
|
||||
|
||||
/* NUMA information */
|
||||
|
@ -126,13 +124,19 @@ extern struct alpha_machine_vector alpha_mv;
|
|||
|
||||
#ifdef CONFIG_ALPHA_GENERIC
|
||||
extern int alpha_using_srm;
|
||||
extern int alpha_using_qemu;
|
||||
#else
|
||||
#ifdef CONFIG_ALPHA_SRM
|
||||
#define alpha_using_srm 1
|
||||
#else
|
||||
#define alpha_using_srm 0
|
||||
#endif
|
||||
# ifdef CONFIG_ALPHA_SRM
|
||||
# define alpha_using_srm 1
|
||||
# else
|
||||
# define alpha_using_srm 0
|
||||
# endif
|
||||
# ifdef CONFIG_ALPHA_QEMU
|
||||
# define alpha_using_qemu 1
|
||||
# else
|
||||
# define alpha_using_qemu 0
|
||||
# endif
|
||||
#endif /* GENERIC */
|
||||
|
||||
#endif
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* __ALPHA_MACHVEC_H */
|
||||
|
|
|
@ -89,6 +89,7 @@ __CALL_PAL_W1(wrmces, unsigned long);
|
|||
__CALL_PAL_RW2(wrperfmon, unsigned long, unsigned long, unsigned long);
|
||||
__CALL_PAL_W1(wrusp, unsigned long);
|
||||
__CALL_PAL_W1(wrvptptr, unsigned long);
|
||||
__CALL_PAL_RW1(wtint, unsigned long, unsigned long);
|
||||
|
||||
/*
|
||||
* TB routines..
|
||||
|
@ -111,5 +112,75 @@ __CALL_PAL_W1(wrvptptr, unsigned long);
|
|||
#define tbiap() __tbi(-1, /* no second argument */)
|
||||
#define tbia() __tbi(-2, /* no second argument */)
|
||||
|
||||
/*
|
||||
* QEMU Cserv routines..
|
||||
*/
|
||||
|
||||
static inline unsigned long
|
||||
qemu_get_walltime(void)
|
||||
{
|
||||
register unsigned long v0 __asm__("$0");
|
||||
register unsigned long a0 __asm__("$16") = 3;
|
||||
|
||||
asm("call_pal %2 # cserve get_time"
|
||||
: "=r"(v0), "+r"(a0)
|
||||
: "i"(PAL_cserve)
|
||||
: "$17", "$18", "$19", "$20", "$21");
|
||||
|
||||
return v0;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
qemu_get_alarm(void)
|
||||
{
|
||||
register unsigned long v0 __asm__("$0");
|
||||
register unsigned long a0 __asm__("$16") = 4;
|
||||
|
||||
asm("call_pal %2 # cserve get_alarm"
|
||||
: "=r"(v0), "+r"(a0)
|
||||
: "i"(PAL_cserve)
|
||||
: "$17", "$18", "$19", "$20", "$21");
|
||||
|
||||
return v0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
qemu_set_alarm_rel(unsigned long expire)
|
||||
{
|
||||
register unsigned long a0 __asm__("$16") = 5;
|
||||
register unsigned long a1 __asm__("$17") = expire;
|
||||
|
||||
asm volatile("call_pal %2 # cserve set_alarm_rel"
|
||||
: "+r"(a0), "+r"(a1)
|
||||
: "i"(PAL_cserve)
|
||||
: "$0", "$18", "$19", "$20", "$21");
|
||||
}
|
||||
|
||||
static inline void
|
||||
qemu_set_alarm_abs(unsigned long expire)
|
||||
{
|
||||
register unsigned long a0 __asm__("$16") = 6;
|
||||
register unsigned long a1 __asm__("$17") = expire;
|
||||
|
||||
asm volatile("call_pal %2 # cserve set_alarm_abs"
|
||||
: "+r"(a0), "+r"(a1)
|
||||
: "i"(PAL_cserve)
|
||||
: "$0", "$18", "$19", "$20", "$21");
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
qemu_get_vmtime(void)
|
||||
{
|
||||
register unsigned long v0 __asm__("$0");
|
||||
register unsigned long a0 __asm__("$16") = 7;
|
||||
|
||||
asm("call_pal %2 # cserve get_time"
|
||||
: "=r"(v0), "+r"(a0)
|
||||
: "i"(PAL_cserve)
|
||||
: "$17", "$18", "$19", "$20", "$21");
|
||||
|
||||
return v0;
|
||||
}
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
#endif /* __ALPHA_PAL_H */
|
||||
|
|
|
@ -1,12 +1 @@
|
|||
#ifndef _ALPHA_RTC_H
|
||||
#define _ALPHA_RTC_H
|
||||
|
||||
#if defined(CONFIG_ALPHA_MARVEL) && defined(CONFIG_SMP) \
|
||||
|| defined(CONFIG_ALPHA_GENERIC)
|
||||
# define get_rtc_time alpha_mv.rtc_get_time
|
||||
# define set_rtc_time alpha_mv.rtc_set_time
|
||||
#endif
|
||||
|
||||
#include <asm-generic/rtc.h>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,15 +22,27 @@ extern void * __memcpy(void *, const void *, size_t);
|
|||
|
||||
#define __HAVE_ARCH_MEMSET
|
||||
extern void * __constant_c_memset(void *, unsigned long, size_t);
|
||||
extern void * ___memset(void *, int, size_t);
|
||||
extern void * __memset(void *, int, size_t);
|
||||
extern void * memset(void *, int, size_t);
|
||||
|
||||
#define memset(s, c, n) \
|
||||
(__builtin_constant_p(c) \
|
||||
? (__builtin_constant_p(n) && (c) == 0 \
|
||||
? __builtin_memset((s),0,(n)) \
|
||||
: __constant_c_memset((s),0x0101010101010101UL*(unsigned char)(c),(n))) \
|
||||
: __memset((s),(c),(n)))
|
||||
/* For gcc 3.x, we cannot have the inline function named "memset" because
|
||||
the __builtin_memset will attempt to resolve to the inline as well,
|
||||
leading to a "sorry" about unimplemented recursive inlining. */
|
||||
extern inline void *__memset(void *s, int c, size_t n)
|
||||
{
|
||||
if (__builtin_constant_p(c)) {
|
||||
if (__builtin_constant_p(n)) {
|
||||
return __builtin_memset(s, c, n);
|
||||
} else {
|
||||
unsigned long c8 = (c & 0xff) * 0x0101010101010101UL;
|
||||
return __constant_c_memset(s, c8, n);
|
||||
}
|
||||
}
|
||||
return ___memset(s, c, n);
|
||||
}
|
||||
|
||||
#define memset __memset
|
||||
|
||||
#define __HAVE_ARCH_STRCPY
|
||||
extern char * strcpy(char *,const char *);
|
||||
|
|
|
@ -58,8 +58,6 @@ register struct thread_info *__current_thread_info __asm__("$8");
|
|||
#define THREAD_SIZE_ORDER 1
|
||||
#define THREAD_SIZE (2*PAGE_SIZE)
|
||||
|
||||
#define PREEMPT_ACTIVE 0x40000000
|
||||
|
||||
/*
|
||||
* Thread information flags:
|
||||
* - these are process state flags and used from assembly
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#define PAL_rdusp 58
|
||||
#define PAL_whami 60
|
||||
#define PAL_retsys 61
|
||||
#define PAL_wtint 62
|
||||
#define PAL_rti 63
|
||||
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ obj-$(CONFIG_PCI) += pci.o pci_iommu.o pci-sysfs.o
|
|||
obj-$(CONFIG_SRM_ENV) += srm_env.o
|
||||
obj-$(CONFIG_MODULES) += module.o
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_event.o
|
||||
obj-$(CONFIG_RTC_DRV_ALPHA) += rtc.o
|
||||
|
||||
ifdef CONFIG_ALPHA_GENERIC
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ EXPORT_SYMBOL(strrchr);
|
|||
EXPORT_SYMBOL(memmove);
|
||||
EXPORT_SYMBOL(__memcpy);
|
||||
EXPORT_SYMBOL(__memset);
|
||||
EXPORT_SYMBOL(___memset);
|
||||
EXPORT_SYMBOL(__memsetw);
|
||||
EXPORT_SYMBOL(__constant_c_memset);
|
||||
EXPORT_SYMBOL(copy_page);
|
||||
|
|
|
@ -66,21 +66,7 @@ do_entInt(unsigned long type, unsigned long vector,
|
|||
break;
|
||||
case 1:
|
||||
old_regs = set_irq_regs(regs);
|
||||
#ifdef CONFIG_SMP
|
||||
{
|
||||
long cpu;
|
||||
|
||||
smp_percpu_timer_interrupt(regs);
|
||||
cpu = smp_processor_id();
|
||||
if (cpu != boot_cpuid) {
|
||||
kstat_incr_irqs_this_cpu(RTC_IRQ, irq_to_desc(RTC_IRQ));
|
||||
} else {
|
||||
handle_irq(RTC_IRQ);
|
||||
}
|
||||
}
|
||||
#else
|
||||
handle_irq(RTC_IRQ);
|
||||
#endif
|
||||
set_irq_regs(old_regs);
|
||||
return;
|
||||
case 2:
|
||||
|
@ -228,7 +214,7 @@ process_mcheck_info(unsigned long vector, unsigned long la_ptr,
|
|||
*/
|
||||
|
||||
struct irqaction timer_irqaction = {
|
||||
.handler = timer_interrupt,
|
||||
.handler = rtc_timer_interrupt,
|
||||
.name = "timer",
|
||||
};
|
||||
|
||||
|
|
|
@ -43,10 +43,7 @@
|
|||
#define CAT1(x,y) x##y
|
||||
#define CAT(x,y) CAT1(x,y)
|
||||
|
||||
#define DO_DEFAULT_RTC \
|
||||
.rtc_port = 0x70, \
|
||||
.rtc_get_time = common_get_rtc_time, \
|
||||
.rtc_set_time = common_set_rtc_time
|
||||
#define DO_DEFAULT_RTC .rtc_port = 0x70
|
||||
|
||||
#define DO_EV4_MMU \
|
||||
.max_asn = EV4_MAX_ASN, \
|
||||
|
|
|
@ -83,6 +83,8 @@ struct alpha_pmu_t {
|
|||
long pmc_left[3];
|
||||
/* Subroutine for allocation of PMCs. Enforces constraints. */
|
||||
int (*check_constraints)(struct perf_event **, unsigned long *, int);
|
||||
/* Subroutine for checking validity of a raw event for this PMU. */
|
||||
int (*raw_event_valid)(u64 config);
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -203,6 +205,12 @@ success:
|
|||
}
|
||||
|
||||
|
||||
static int ev67_raw_event_valid(u64 config)
|
||||
{
|
||||
return config >= EV67_CYCLES && config < EV67_LAST_ET;
|
||||
};
|
||||
|
||||
|
||||
static const struct alpha_pmu_t ev67_pmu = {
|
||||
.event_map = ev67_perfmon_event_map,
|
||||
.max_events = ARRAY_SIZE(ev67_perfmon_event_map),
|
||||
|
@ -211,7 +219,8 @@ static const struct alpha_pmu_t ev67_pmu = {
|
|||
.pmc_count_mask = {EV67_PCTR_0_COUNT_MASK, EV67_PCTR_1_COUNT_MASK, 0},
|
||||
.pmc_max_period = {(1UL<<20) - 1, (1UL<<20) - 1, 0},
|
||||
.pmc_left = {16, 4, 0},
|
||||
.check_constraints = ev67_check_constraints
|
||||
.check_constraints = ev67_check_constraints,
|
||||
.raw_event_valid = ev67_raw_event_valid,
|
||||
};
|
||||
|
||||
|
||||
|
@ -609,7 +618,9 @@ static int __hw_perf_event_init(struct perf_event *event)
|
|||
} else if (attr->type == PERF_TYPE_HW_CACHE) {
|
||||
return -EOPNOTSUPP;
|
||||
} else if (attr->type == PERF_TYPE_RAW) {
|
||||
ev = attr->config & 0xff;
|
||||
if (!alpha_pmu->raw_event_valid(attr->config))
|
||||
return -EINVAL;
|
||||
ev = attr->config;
|
||||
} else {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,23 @@
|
|||
void (*pm_power_off)(void) = machine_power_off;
|
||||
EXPORT_SYMBOL(pm_power_off);
|
||||
|
||||
#ifdef CONFIG_ALPHA_WTINT
|
||||
/*
|
||||
* Sleep the CPU.
|
||||
* EV6, LCA45 and QEMU know how to power down, skipping N timer interrupts.
|
||||
*/
|
||||
void arch_cpu_idle(void)
|
||||
{
|
||||
wtint(0);
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
void arch_cpu_idle_dead(void)
|
||||
{
|
||||
wtint(INT_MAX);
|
||||
}
|
||||
#endif /* ALPHA_WTINT */
|
||||
|
||||
struct halt_info {
|
||||
int mode;
|
||||
char *restart_cmd;
|
||||
|
|
|
@ -135,17 +135,15 @@ extern void unregister_srm_console(void);
|
|||
/* smp.c */
|
||||
extern void setup_smp(void);
|
||||
extern void handle_ipi(struct pt_regs *);
|
||||
extern void smp_percpu_timer_interrupt(struct pt_regs *);
|
||||
|
||||
/* bios32.c */
|
||||
/* extern void reset_for_srm(void); */
|
||||
|
||||
/* time.c */
|
||||
extern irqreturn_t timer_interrupt(int irq, void *dev);
|
||||
extern irqreturn_t rtc_timer_interrupt(int irq, void *dev);
|
||||
extern void init_clockevent(void);
|
||||
extern void common_init_rtc(void);
|
||||
extern unsigned long est_cycle_freq;
|
||||
extern unsigned int common_get_rtc_time(struct rtc_time *time);
|
||||
extern int common_set_rtc_time(struct rtc_time *time);
|
||||
|
||||
/* smc37c93x.c */
|
||||
extern void SMC93x_Init(void);
|
||||
|
|
|
@ -0,0 +1,323 @@
|
|||
/*
|
||||
* linux/arch/alpha/kernel/rtc.c
|
||||
*
|
||||
* Copyright (C) 1991, 1992, 1995, 1999, 2000 Linus Torvalds
|
||||
*
|
||||
* This file contains date handling.
|
||||
*/
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/param.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mc146818rtc.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/rtc.h>
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
|
||||
/*
|
||||
* Support for the RTC device.
|
||||
*
|
||||
* We don't want to use the rtc-cmos driver, because we don't want to support
|
||||
* alarms, as that would be indistinguishable from timer interrupts.
|
||||
*
|
||||
* Further, generic code is really, really tied to a 1900 epoch. This is
|
||||
* true in __get_rtc_time as well as the users of struct rtc_time e.g.
|
||||
* rtc_tm_to_time. Thankfully all of the other epochs in use are later
|
||||
* than 1900, and so it's easy to adjust.
|
||||
*/
|
||||
|
||||
static unsigned long rtc_epoch;
|
||||
|
||||
static int __init
|
||||
specifiy_epoch(char *str)
|
||||
{
|
||||
unsigned long epoch = simple_strtoul(str, NULL, 0);
|
||||
if (epoch < 1900)
|
||||
printk("Ignoring invalid user specified epoch %lu\n", epoch);
|
||||
else
|
||||
rtc_epoch = epoch;
|
||||
return 1;
|
||||
}
|
||||
__setup("epoch=", specifiy_epoch);
|
||||
|
||||
static void __init
|
||||
init_rtc_epoch(void)
|
||||
{
|
||||
int epoch, year, ctrl;
|
||||
|
||||
if (rtc_epoch != 0) {
|
||||
/* The epoch was specified on the command-line. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Detect the epoch in use on this computer. */
|
||||
ctrl = CMOS_READ(RTC_CONTROL);
|
||||
year = CMOS_READ(RTC_YEAR);
|
||||
if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
|
||||
year = bcd2bin(year);
|
||||
|
||||
/* PC-like is standard; used for year >= 70 */
|
||||
epoch = 1900;
|
||||
if (year < 20) {
|
||||
epoch = 2000;
|
||||
} else if (year >= 20 && year < 48) {
|
||||
/* NT epoch */
|
||||
epoch = 1980;
|
||||
} else if (year >= 48 && year < 70) {
|
||||
/* Digital UNIX epoch */
|
||||
epoch = 1952;
|
||||
}
|
||||
rtc_epoch = epoch;
|
||||
|
||||
printk(KERN_INFO "Using epoch %d for rtc year %d\n", epoch, year);
|
||||
}
|
||||
|
||||
static int
|
||||
alpha_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
__get_rtc_time(tm);
|
||||
|
||||
/* Adjust for non-default epochs. It's easier to depend on the
|
||||
generic __get_rtc_time and adjust the epoch here than create
|
||||
a copy of __get_rtc_time with the edits we need. */
|
||||
if (rtc_epoch != 1900) {
|
||||
int year = tm->tm_year;
|
||||
/* Undo the century adjustment made in __get_rtc_time. */
|
||||
if (year >= 100)
|
||||
year -= 100;
|
||||
year += rtc_epoch - 1900;
|
||||
/* Redo the century adjustment with the epoch in place. */
|
||||
if (year <= 69)
|
||||
year += 100;
|
||||
tm->tm_year = year;
|
||||
}
|
||||
|
||||
return rtc_valid_tm(tm);
|
||||
}
|
||||
|
||||
static int
|
||||
alpha_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct rtc_time xtm;
|
||||
|
||||
if (rtc_epoch != 1900) {
|
||||
xtm = *tm;
|
||||
xtm.tm_year -= rtc_epoch - 1900;
|
||||
tm = &xtm;
|
||||
}
|
||||
|
||||
return __set_rtc_time(tm);
|
||||
}
|
||||
|
||||
static int
|
||||
alpha_rtc_set_mmss(struct device *dev, unsigned long nowtime)
|
||||
{
|
||||
int retval = 0;
|
||||
int real_seconds, real_minutes, cmos_minutes;
|
||||
unsigned char save_control, save_freq_select;
|
||||
|
||||
/* Note: This code only updates minutes and seconds. Comments
|
||||
indicate this was to avoid messing with unknown time zones,
|
||||
and with the epoch nonsense described above. In order for
|
||||
this to work, the existing clock cannot be off by more than
|
||||
15 minutes.
|
||||
|
||||
??? This choice is may be out of date. The x86 port does
|
||||
not have problems with timezones, and the epoch processing has
|
||||
now been fixed in alpha_set_rtc_time.
|
||||
|
||||
In either case, one can always force a full rtc update with
|
||||
the userland hwclock program, so surely 15 minute accuracy
|
||||
is no real burden. */
|
||||
|
||||
/* In order to set the CMOS clock precisely, we have to be called
|
||||
500 ms after the second nowtime has started, because when
|
||||
nowtime is written into the registers of the CMOS clock, it will
|
||||
jump to the next second precisely 500 ms later. Check the Motorola
|
||||
MC146818A or Dallas DS12887 data sheet for details. */
|
||||
|
||||
/* irq are locally disabled here */
|
||||
spin_lock(&rtc_lock);
|
||||
/* Tell the clock it's being set */
|
||||
save_control = CMOS_READ(RTC_CONTROL);
|
||||
CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
|
||||
|
||||
/* Stop and reset prescaler */
|
||||
save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
|
||||
CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
|
||||
|
||||
cmos_minutes = CMOS_READ(RTC_MINUTES);
|
||||
if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
|
||||
cmos_minutes = bcd2bin(cmos_minutes);
|
||||
|
||||
real_seconds = nowtime % 60;
|
||||
real_minutes = nowtime / 60;
|
||||
if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1) {
|
||||
/* correct for half hour time zone */
|
||||
real_minutes += 30;
|
||||
}
|
||||
real_minutes %= 60;
|
||||
|
||||
if (abs(real_minutes - cmos_minutes) < 30) {
|
||||
if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
|
||||
real_seconds = bin2bcd(real_seconds);
|
||||
real_minutes = bin2bcd(real_minutes);
|
||||
}
|
||||
CMOS_WRITE(real_seconds,RTC_SECONDS);
|
||||
CMOS_WRITE(real_minutes,RTC_MINUTES);
|
||||
} else {
|
||||
printk_once(KERN_NOTICE
|
||||
"set_rtc_mmss: can't update from %d to %d\n",
|
||||
cmos_minutes, real_minutes);
|
||||
retval = -1;
|
||||
}
|
||||
|
||||
/* The following flags have to be released exactly in this order,
|
||||
* otherwise the DS12887 (popular MC146818A clone with integrated
|
||||
* battery and quartz) will not reset the oscillator and will not
|
||||
* update precisely 500 ms later. You won't find this mentioned in
|
||||
* the Dallas Semiconductor data sheets, but who believes data
|
||||
* sheets anyway ... -- Markus Kuhn
|
||||
*/
|
||||
CMOS_WRITE(save_control, RTC_CONTROL);
|
||||
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
|
||||
spin_unlock(&rtc_lock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int
|
||||
alpha_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
switch (cmd) {
|
||||
case RTC_EPOCH_READ:
|
||||
return put_user(rtc_epoch, (unsigned long __user *)arg);
|
||||
case RTC_EPOCH_SET:
|
||||
if (arg < 1900)
|
||||
return -EINVAL;
|
||||
rtc_epoch = arg;
|
||||
return 0;
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops alpha_rtc_ops = {
|
||||
.read_time = alpha_rtc_read_time,
|
||||
.set_time = alpha_rtc_set_time,
|
||||
.set_mmss = alpha_rtc_set_mmss,
|
||||
.ioctl = alpha_rtc_ioctl,
|
||||
};
|
||||
|
||||
/*
|
||||
* Similarly, except do the actual CMOS access on the boot cpu only.
|
||||
* This requires marshalling the data across an interprocessor call.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_SMP) && \
|
||||
(defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_MARVEL))
|
||||
# define HAVE_REMOTE_RTC 1
|
||||
|
||||
union remote_data {
|
||||
struct rtc_time *tm;
|
||||
unsigned long now;
|
||||
long retval;
|
||||
};
|
||||
|
||||
static void
|
||||
do_remote_read(void *data)
|
||||
{
|
||||
union remote_data *x = data;
|
||||
x->retval = alpha_rtc_read_time(NULL, x->tm);
|
||||
}
|
||||
|
||||
static int
|
||||
remote_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
union remote_data x;
|
||||
if (smp_processor_id() != boot_cpuid) {
|
||||
x.tm = tm;
|
||||
smp_call_function_single(boot_cpuid, do_remote_read, &x, 1);
|
||||
return x.retval;
|
||||
}
|
||||
return alpha_rtc_read_time(NULL, tm);
|
||||
}
|
||||
|
||||
static void
|
||||
do_remote_set(void *data)
|
||||
{
|
||||
union remote_data *x = data;
|
||||
x->retval = alpha_rtc_set_time(NULL, x->tm);
|
||||
}
|
||||
|
||||
static int
|
||||
remote_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
union remote_data x;
|
||||
if (smp_processor_id() != boot_cpuid) {
|
||||
x.tm = tm;
|
||||
smp_call_function_single(boot_cpuid, do_remote_set, &x, 1);
|
||||
return x.retval;
|
||||
}
|
||||
return alpha_rtc_set_time(NULL, tm);
|
||||
}
|
||||
|
||||
static void
|
||||
do_remote_mmss(void *data)
|
||||
{
|
||||
union remote_data *x = data;
|
||||
x->retval = alpha_rtc_set_mmss(NULL, x->now);
|
||||
}
|
||||
|
||||
static int
|
||||
remote_set_mmss(struct device *dev, unsigned long now)
|
||||
{
|
||||
union remote_data x;
|
||||
if (smp_processor_id() != boot_cpuid) {
|
||||
x.now = now;
|
||||
smp_call_function_single(boot_cpuid, do_remote_mmss, &x, 1);
|
||||
return x.retval;
|
||||
}
|
||||
return alpha_rtc_set_mmss(NULL, now);
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops remote_rtc_ops = {
|
||||
.read_time = remote_read_time,
|
||||
.set_time = remote_set_time,
|
||||
.set_mmss = remote_set_mmss,
|
||||
.ioctl = alpha_rtc_ioctl,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __init
|
||||
alpha_rtc_init(void)
|
||||
{
|
||||
const struct rtc_class_ops *ops;
|
||||
struct platform_device *pdev;
|
||||
struct rtc_device *rtc;
|
||||
const char *name;
|
||||
|
||||
init_rtc_epoch();
|
||||
name = "rtc-alpha";
|
||||
ops = &alpha_rtc_ops;
|
||||
|
||||
#ifdef HAVE_REMOTE_RTC
|
||||
if (alpha_mv.rtc_boot_cpu_only)
|
||||
ops = &remote_rtc_ops;
|
||||
#endif
|
||||
|
||||
pdev = platform_device_register_simple(name, -1, NULL, 0);
|
||||
rtc = devm_rtc_device_register(&pdev->dev, name, ops, THIS_MODULE);
|
||||
if (IS_ERR(rtc))
|
||||
return PTR_ERR(rtc);
|
||||
|
||||
platform_set_drvdata(pdev, rtc);
|
||||
return 0;
|
||||
}
|
||||
device_initcall(alpha_rtc_init);
|
|
@ -115,10 +115,17 @@ unsigned long alpha_agpgart_size = DEFAULT_AGP_APER_SIZE;
|
|||
|
||||
#ifdef CONFIG_ALPHA_GENERIC
|
||||
struct alpha_machine_vector alpha_mv;
|
||||
#endif
|
||||
|
||||
#ifndef alpha_using_srm
|
||||
int alpha_using_srm;
|
||||
EXPORT_SYMBOL(alpha_using_srm);
|
||||
#endif
|
||||
|
||||
#ifndef alpha_using_qemu
|
||||
int alpha_using_qemu;
|
||||
#endif
|
||||
|
||||
static struct alpha_machine_vector *get_sysvec(unsigned long, unsigned long,
|
||||
unsigned long);
|
||||
static struct alpha_machine_vector *get_sysvec_byname(const char *);
|
||||
|
@ -529,11 +536,15 @@ setup_arch(char **cmdline_p)
|
|||
atomic_notifier_chain_register(&panic_notifier_list,
|
||||
&alpha_panic_block);
|
||||
|
||||
#ifdef CONFIG_ALPHA_GENERIC
|
||||
#ifndef alpha_using_srm
|
||||
/* Assume that we've booted from SRM if we haven't booted from MILO.
|
||||
Detect the later by looking for "MILO" in the system serial nr. */
|
||||
alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
|
||||
#endif
|
||||
#ifndef alpha_using_qemu
|
||||
/* Similarly, look for QEMU. */
|
||||
alpha_using_qemu = strstr((const char *)hwrpb->ssn, "QEMU") != 0;
|
||||
#endif
|
||||
|
||||
/* If we are using SRM, we want to allow callbacks
|
||||
as early as possible, so do this NOW, and then
|
||||
|
@ -1207,6 +1218,7 @@ show_cpuinfo(struct seq_file *f, void *slot)
|
|||
char *systype_name;
|
||||
char *sysvariation_name;
|
||||
int nr_processors;
|
||||
unsigned long timer_freq;
|
||||
|
||||
cpu_index = (unsigned) (cpu->type - 1);
|
||||
cpu_name = "Unknown";
|
||||
|
@ -1218,6 +1230,12 @@ show_cpuinfo(struct seq_file *f, void *slot)
|
|||
|
||||
nr_processors = get_nr_processors(cpu, hwrpb->nr_processors);
|
||||
|
||||
#if CONFIG_HZ == 1024 || CONFIG_HZ == 1200
|
||||
timer_freq = (100UL * hwrpb->intr_freq) / 4096;
|
||||
#else
|
||||
timer_freq = 100UL * CONFIG_HZ;
|
||||
#endif
|
||||
|
||||
seq_printf(f, "cpu\t\t\t: Alpha\n"
|
||||
"cpu model\t\t: %s\n"
|
||||
"cpu variation\t\t: %ld\n"
|
||||
|
@ -1243,8 +1261,7 @@ show_cpuinfo(struct seq_file *f, void *slot)
|
|||
(char*)hwrpb->ssn,
|
||||
est_cycle_freq ? : hwrpb->cycle_freq,
|
||||
est_cycle_freq ? "est." : "",
|
||||
hwrpb->intr_freq / 4096,
|
||||
(100 * hwrpb->intr_freq / 4096) % 100,
|
||||
timer_freq / 100, timer_freq % 100,
|
||||
hwrpb->pagesize,
|
||||
hwrpb->pa_bits,
|
||||
hwrpb->max_asn,
|
||||
|
|
|
@ -138,9 +138,11 @@ smp_callin(void)
|
|||
|
||||
/* Get our local ticker going. */
|
||||
smp_setup_percpu_timer(cpuid);
|
||||
init_clockevent();
|
||||
|
||||
/* Call platform-specific callin, if specified */
|
||||
if (alpha_mv.smp_callin) alpha_mv.smp_callin();
|
||||
if (alpha_mv.smp_callin)
|
||||
alpha_mv.smp_callin();
|
||||
|
||||
/* All kernel threads share the same mm context. */
|
||||
atomic_inc(&init_mm.mm_count);
|
||||
|
@ -498,35 +500,6 @@ smp_cpus_done(unsigned int max_cpus)
|
|||
((bogosum + 2500) / (5000/HZ)) % 100);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
smp_percpu_timer_interrupt(struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs;
|
||||
int cpu = smp_processor_id();
|
||||
unsigned long user = user_mode(regs);
|
||||
struct cpuinfo_alpha *data = &cpu_data[cpu];
|
||||
|
||||
old_regs = set_irq_regs(regs);
|
||||
|
||||
/* Record kernel PC. */
|
||||
profile_tick(CPU_PROFILING);
|
||||
|
||||
if (!--data->prof_counter) {
|
||||
/* We need to make like a normal interrupt -- otherwise
|
||||
timer interrupts ignore the global interrupt lock,
|
||||
which would be a Bad Thing. */
|
||||
irq_enter();
|
||||
|
||||
update_process_times(user);
|
||||
|
||||
data->prof_counter = data->prof_multiplier;
|
||||
|
||||
irq_exit();
|
||||
}
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
int
|
||||
setup_profiling_timer(unsigned int multiplier)
|
||||
{
|
||||
|
|
|
@ -224,8 +224,6 @@ struct alpha_machine_vector jensen_mv __initmv = {
|
|||
.machine_check = jensen_machine_check,
|
||||
.max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
|
||||
.rtc_port = 0x170,
|
||||
.rtc_get_time = common_get_rtc_time,
|
||||
.rtc_set_time = common_set_rtc_time,
|
||||
|
||||
.nr_irqs = 16,
|
||||
.device_interrupt = jensen_device_interrupt,
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <asm/hwrpb.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/vga.h>
|
||||
#include <asm/rtc.h>
|
||||
|
||||
#include "proto.h"
|
||||
#include "err_impl.h"
|
||||
|
@ -400,57 +399,6 @@ marvel_init_rtc(void)
|
|||
init_rtc_irq();
|
||||
}
|
||||
|
||||
struct marvel_rtc_time {
|
||||
struct rtc_time *time;
|
||||
int retval;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static void
|
||||
smp_get_rtc_time(void *data)
|
||||
{
|
||||
struct marvel_rtc_time *mrt = data;
|
||||
mrt->retval = __get_rtc_time(mrt->time);
|
||||
}
|
||||
|
||||
static void
|
||||
smp_set_rtc_time(void *data)
|
||||
{
|
||||
struct marvel_rtc_time *mrt = data;
|
||||
mrt->retval = __set_rtc_time(mrt->time);
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned int
|
||||
marvel_get_rtc_time(struct rtc_time *time)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
struct marvel_rtc_time mrt;
|
||||
|
||||
if (smp_processor_id() != boot_cpuid) {
|
||||
mrt.time = time;
|
||||
smp_call_function_single(boot_cpuid, smp_get_rtc_time, &mrt, 1);
|
||||
return mrt.retval;
|
||||
}
|
||||
#endif
|
||||
return __get_rtc_time(time);
|
||||
}
|
||||
|
||||
static int
|
||||
marvel_set_rtc_time(struct rtc_time *time)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
struct marvel_rtc_time mrt;
|
||||
|
||||
if (smp_processor_id() != boot_cpuid) {
|
||||
mrt.time = time;
|
||||
smp_call_function_single(boot_cpuid, smp_set_rtc_time, &mrt, 1);
|
||||
return mrt.retval;
|
||||
}
|
||||
#endif
|
||||
return __set_rtc_time(time);
|
||||
}
|
||||
|
||||
static void
|
||||
marvel_smp_callin(void)
|
||||
{
|
||||
|
@ -492,8 +440,7 @@ struct alpha_machine_vector marvel_ev7_mv __initmv = {
|
|||
.vector_name = "MARVEL/EV7",
|
||||
DO_EV7_MMU,
|
||||
.rtc_port = 0x70,
|
||||
.rtc_get_time = marvel_get_rtc_time,
|
||||
.rtc_set_time = marvel_set_rtc_time,
|
||||
.rtc_boot_cpu_only = 1,
|
||||
DO_MARVEL_IO,
|
||||
.machine_check = marvel_machine_check,
|
||||
.max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
|
||||
|
|
|
@ -3,13 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 1991, 1992, 1995, 1999, 2000 Linus Torvalds
|
||||
*
|
||||
* This file contains the PC-specific time handling details:
|
||||
* reading the RTC at bootup, etc..
|
||||
* 1994-07-02 Alan Modra
|
||||
* fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
|
||||
* 1995-03-26 Markus Kuhn
|
||||
* fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
|
||||
* precision CMOS clock update
|
||||
* This file contains the clocksource time handling.
|
||||
* 1997-09-10 Updated NTP code according to technical memorandum Jan '96
|
||||
* "A Kernel Model for Precision Timekeeping" by Dave Mills
|
||||
* 1997-01-09 Adrian Sun
|
||||
|
@ -21,9 +15,6 @@
|
|||
* 1999-04-16 Thorsten Kranzkowski (dl8bcu@gmx.net)
|
||||
* fixed algorithm in do_gettimeofday() for calculating the precise time
|
||||
* from processor cycle counter (now taking lost_ticks into account)
|
||||
* 2000-08-13 Jan-Benedict Glaw <jbglaw@lug-owl.de>
|
||||
* Fixed time_init to be aware of epoches != 1900. This prevents
|
||||
* booting up in 2048 for me;) Code is stolen from rtc.c.
|
||||
* 2003-06-03 R. Scott Bailey <scott.bailey@eds.com>
|
||||
* Tighten sanity in time_init from 1% (10,000 PPM) to 250 PPM
|
||||
*/
|
||||
|
@ -46,40 +37,19 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/hwrpb.h>
|
||||
#include <asm/rtc.h>
|
||||
|
||||
#include <linux/mc146818rtc.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
#include "proto.h"
|
||||
#include "irq_impl.h"
|
||||
|
||||
static int set_rtc_mmss(unsigned long);
|
||||
|
||||
DEFINE_SPINLOCK(rtc_lock);
|
||||
EXPORT_SYMBOL(rtc_lock);
|
||||
|
||||
#define TICK_SIZE (tick_nsec / 1000)
|
||||
|
||||
/*
|
||||
* Shift amount by which scaled_ticks_per_cycle is scaled. Shifting
|
||||
* by 48 gives us 16 bits for HZ while keeping the accuracy good even
|
||||
* for large CPU clock rates.
|
||||
*/
|
||||
#define FIX_SHIFT 48
|
||||
|
||||
/* lump static variables together for more efficient access: */
|
||||
static struct {
|
||||
/* cycle counter last time it got invoked */
|
||||
__u32 last_time;
|
||||
/* ticks/cycle * 2^48 */
|
||||
unsigned long scaled_ticks_per_cycle;
|
||||
/* partial unused tick */
|
||||
unsigned long partial_tick;
|
||||
} state;
|
||||
|
||||
unsigned long est_cycle_freq;
|
||||
|
||||
#ifdef CONFIG_IRQ_WORK
|
||||
|
@ -108,109 +78,156 @@ static inline __u32 rpcc(void)
|
|||
return __builtin_alpha_rpcc();
|
||||
}
|
||||
|
||||
int update_persistent_clock(struct timespec now)
|
||||
{
|
||||
return set_rtc_mmss(now.tv_sec);
|
||||
}
|
||||
|
||||
void read_persistent_clock(struct timespec *ts)
|
||||
{
|
||||
unsigned int year, mon, day, hour, min, sec, epoch;
|
||||
|
||||
sec = CMOS_READ(RTC_SECONDS);
|
||||
min = CMOS_READ(RTC_MINUTES);
|
||||
hour = CMOS_READ(RTC_HOURS);
|
||||
day = CMOS_READ(RTC_DAY_OF_MONTH);
|
||||
mon = CMOS_READ(RTC_MONTH);
|
||||
year = CMOS_READ(RTC_YEAR);
|
||||
|
||||
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
|
||||
sec = bcd2bin(sec);
|
||||
min = bcd2bin(min);
|
||||
hour = bcd2bin(hour);
|
||||
day = bcd2bin(day);
|
||||
mon = bcd2bin(mon);
|
||||
year = bcd2bin(year);
|
||||
}
|
||||
|
||||
/* PC-like is standard; used for year >= 70 */
|
||||
epoch = 1900;
|
||||
if (year < 20)
|
||||
epoch = 2000;
|
||||
else if (year >= 20 && year < 48)
|
||||
/* NT epoch */
|
||||
epoch = 1980;
|
||||
else if (year >= 48 && year < 70)
|
||||
/* Digital UNIX epoch */
|
||||
epoch = 1952;
|
||||
|
||||
printk(KERN_INFO "Using epoch = %d\n", epoch);
|
||||
|
||||
if ((year += epoch) < 1970)
|
||||
year += 100;
|
||||
|
||||
ts->tv_sec = mktime(year, mon, day, hour, min, sec);
|
||||
ts->tv_nsec = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* timer_interrupt() needs to keep up the real-time clock,
|
||||
* as well as call the "xtime_update()" routine every clocktick
|
||||
* The RTC as a clock_event_device primitive.
|
||||
*/
|
||||
irqreturn_t timer_interrupt(int irq, void *dev)
|
||||
|
||||
static DEFINE_PER_CPU(struct clock_event_device, cpu_ce);
|
||||
|
||||
irqreturn_t
|
||||
rtc_timer_interrupt(int irq, void *dev)
|
||||
{
|
||||
unsigned long delta;
|
||||
__u32 now;
|
||||
long nticks;
|
||||
int cpu = smp_processor_id();
|
||||
struct clock_event_device *ce = &per_cpu(cpu_ce, cpu);
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
/* Not SMP, do kernel PC profiling here. */
|
||||
profile_tick(CPU_PROFILING);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Calculate how many ticks have passed since the last update,
|
||||
* including any previous partial leftover. Save any resulting
|
||||
* fraction for the next pass.
|
||||
*/
|
||||
now = rpcc();
|
||||
delta = now - state.last_time;
|
||||
state.last_time = now;
|
||||
delta = delta * state.scaled_ticks_per_cycle + state.partial_tick;
|
||||
state.partial_tick = delta & ((1UL << FIX_SHIFT) - 1);
|
||||
nticks = delta >> FIX_SHIFT;
|
||||
|
||||
if (nticks)
|
||||
xtime_update(nticks);
|
||||
/* Don't run the hook for UNUSED or SHUTDOWN. */
|
||||
if (likely(ce->mode == CLOCK_EVT_MODE_PERIODIC))
|
||||
ce->event_handler(ce);
|
||||
|
||||
if (test_irq_work_pending()) {
|
||||
clear_irq_work_pending();
|
||||
irq_work_run();
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
while (nticks--)
|
||||
update_process_times(user_mode(get_irq_regs()));
|
||||
#endif
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void
|
||||
rtc_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *ce)
|
||||
{
|
||||
/* The mode member of CE is updated in generic code.
|
||||
Since we only support periodic events, nothing to do. */
|
||||
}
|
||||
|
||||
static int
|
||||
rtc_ce_set_next_event(unsigned long evt, struct clock_event_device *ce)
|
||||
{
|
||||
/* This hook is for oneshot mode, which we don't support. */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void __init
|
||||
init_rtc_clockevent(void)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
struct clock_event_device *ce = &per_cpu(cpu_ce, cpu);
|
||||
|
||||
*ce = (struct clock_event_device){
|
||||
.name = "rtc",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC,
|
||||
.rating = 100,
|
||||
.cpumask = cpumask_of(cpu),
|
||||
.set_mode = rtc_ce_set_mode,
|
||||
.set_next_event = rtc_ce_set_next_event,
|
||||
};
|
||||
|
||||
clockevents_config_and_register(ce, CONFIG_HZ, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The QEMU clock as a clocksource primitive.
|
||||
*/
|
||||
|
||||
static cycle_t
|
||||
qemu_cs_read(struct clocksource *cs)
|
||||
{
|
||||
return qemu_get_vmtime();
|
||||
}
|
||||
|
||||
static struct clocksource qemu_cs = {
|
||||
.name = "qemu",
|
||||
.rating = 400,
|
||||
.read = qemu_cs_read,
|
||||
.mask = CLOCKSOURCE_MASK(64),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
.max_idle_ns = LONG_MAX
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The QEMU alarm as a clock_event_device primitive.
|
||||
*/
|
||||
|
||||
static void
|
||||
qemu_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *ce)
|
||||
{
|
||||
/* The mode member of CE is updated for us in generic code.
|
||||
Just make sure that the event is disabled. */
|
||||
qemu_set_alarm_abs(0);
|
||||
}
|
||||
|
||||
static int
|
||||
qemu_ce_set_next_event(unsigned long evt, struct clock_event_device *ce)
|
||||
{
|
||||
qemu_set_alarm_rel(evt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
qemu_timer_interrupt(int irq, void *dev)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
struct clock_event_device *ce = &per_cpu(cpu_ce, cpu);
|
||||
|
||||
ce->event_handler(ce);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void __init
|
||||
init_qemu_clockevent(void)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
struct clock_event_device *ce = &per_cpu(cpu_ce, cpu);
|
||||
|
||||
*ce = (struct clock_event_device){
|
||||
.name = "qemu",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 400,
|
||||
.cpumask = cpumask_of(cpu),
|
||||
.set_mode = qemu_ce_set_mode,
|
||||
.set_next_event = qemu_ce_set_next_event,
|
||||
};
|
||||
|
||||
clockevents_config_and_register(ce, NSEC_PER_SEC, 1000, LONG_MAX);
|
||||
}
|
||||
|
||||
|
||||
void __init
|
||||
common_init_rtc(void)
|
||||
{
|
||||
unsigned char x;
|
||||
unsigned char x, sel = 0;
|
||||
|
||||
/* Reset periodic interrupt frequency. */
|
||||
x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f;
|
||||
/* Test includes known working values on various platforms
|
||||
where 0x26 is wrong; we refuse to change those. */
|
||||
if (x != 0x26 && x != 0x25 && x != 0x19 && x != 0x06) {
|
||||
printk("Setting RTC_FREQ to 1024 Hz (%x)\n", x);
|
||||
CMOS_WRITE(0x26, RTC_FREQ_SELECT);
|
||||
#if CONFIG_HZ == 1024 || CONFIG_HZ == 1200
|
||||
x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f;
|
||||
/* Test includes known working values on various platforms
|
||||
where 0x26 is wrong; we refuse to change those. */
|
||||
if (x != 0x26 && x != 0x25 && x != 0x19 && x != 0x06) {
|
||||
sel = RTC_REF_CLCK_32KHZ + 6;
|
||||
}
|
||||
#elif CONFIG_HZ == 256 || CONFIG_HZ == 128 || CONFIG_HZ == 64 || CONFIG_HZ == 32
|
||||
sel = RTC_REF_CLCK_32KHZ + __builtin_ffs(32768 / CONFIG_HZ);
|
||||
#else
|
||||
# error "Unknown HZ from arch/alpha/Kconfig"
|
||||
#endif
|
||||
if (sel) {
|
||||
printk(KERN_INFO "Setting RTC_FREQ to %d Hz (%x)\n",
|
||||
CONFIG_HZ, sel);
|
||||
CMOS_WRITE(sel, RTC_FREQ_SELECT);
|
||||
}
|
||||
|
||||
/* Turn on periodic interrupts. */
|
||||
x = CMOS_READ(RTC_CONTROL);
|
||||
|
@ -233,16 +250,37 @@ common_init_rtc(void)
|
|||
init_rtc_irq();
|
||||
}
|
||||
|
||||
unsigned int common_get_rtc_time(struct rtc_time *time)
|
||||
|
||||
#ifndef CONFIG_ALPHA_WTINT
|
||||
/*
|
||||
* The RPCC as a clocksource primitive.
|
||||
*
|
||||
* While we have free-running timecounters running on all CPUs, and we make
|
||||
* a half-hearted attempt in init_rtc_rpcc_info to sync the timecounter
|
||||
* with the wall clock, that initialization isn't kept up-to-date across
|
||||
* different time counters in SMP mode. Therefore we can only use this
|
||||
* method when there's only one CPU enabled.
|
||||
*
|
||||
* When using the WTINT PALcall, the RPCC may shift to a lower frequency,
|
||||
* or stop altogether, while waiting for the interrupt. Therefore we cannot
|
||||
* use this method when WTINT is in use.
|
||||
*/
|
||||
|
||||
static cycle_t read_rpcc(struct clocksource *cs)
|
||||
{
|
||||
return __get_rtc_time(time);
|
||||
return rpcc();
|
||||
}
|
||||
|
||||
int common_set_rtc_time(struct rtc_time *time)
|
||||
{
|
||||
return __set_rtc_time(time);
|
||||
}
|
||||
static struct clocksource clocksource_rpcc = {
|
||||
.name = "rpcc",
|
||||
.rating = 300,
|
||||
.read = read_rpcc,
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS
|
||||
};
|
||||
#endif /* ALPHA_WTINT */
|
||||
|
||||
|
||||
/* Validate a computed cycle counter result against the known bounds for
|
||||
the given processor core. There's too much brokenness in the way of
|
||||
timing hardware for any one method to work everywhere. :-(
|
||||
|
@ -353,33 +391,6 @@ rpcc_after_update_in_progress(void)
|
|||
return rpcc();
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
/* Until and unless we figure out how to get cpu cycle counters
|
||||
in sync and keep them there, we can't use the rpcc. */
|
||||
static cycle_t read_rpcc(struct clocksource *cs)
|
||||
{
|
||||
cycle_t ret = (cycle_t)rpcc();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct clocksource clocksource_rpcc = {
|
||||
.name = "rpcc",
|
||||
.rating = 300,
|
||||
.read = read_rpcc,
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS
|
||||
};
|
||||
|
||||
static inline void register_rpcc_clocksource(long cycle_freq)
|
||||
{
|
||||
clocksource_register_hz(&clocksource_rpcc, cycle_freq);
|
||||
}
|
||||
#else /* !CONFIG_SMP */
|
||||
static inline void register_rpcc_clocksource(long cycle_freq)
|
||||
{
|
||||
}
|
||||
#endif /* !CONFIG_SMP */
|
||||
|
||||
void __init
|
||||
time_init(void)
|
||||
{
|
||||
|
@ -387,6 +398,15 @@ time_init(void)
|
|||
unsigned long cycle_freq, tolerance;
|
||||
long diff;
|
||||
|
||||
if (alpha_using_qemu) {
|
||||
clocksource_register_hz(&qemu_cs, NSEC_PER_SEC);
|
||||
init_qemu_clockevent();
|
||||
|
||||
timer_irqaction.handler = qemu_timer_interrupt;
|
||||
init_rtc_irq();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Calibrate CPU clock -- attempt #1. */
|
||||
if (!est_cycle_freq)
|
||||
est_cycle_freq = validate_cc_value(calibrate_cc_with_pit());
|
||||
|
@ -421,100 +441,25 @@ time_init(void)
|
|||
"and unable to estimate a proper value!\n");
|
||||
}
|
||||
|
||||
/* From John Bowman <bowman@math.ualberta.ca>: allow the values
|
||||
to settle, as the Update-In-Progress bit going low isn't good
|
||||
enough on some hardware. 2ms is our guess; we haven't found
|
||||
bogomips yet, but this is close on a 500Mhz box. */
|
||||
__delay(1000000);
|
||||
|
||||
|
||||
if (HZ > (1<<16)) {
|
||||
extern void __you_loose (void);
|
||||
__you_loose();
|
||||
}
|
||||
|
||||
register_rpcc_clocksource(cycle_freq);
|
||||
|
||||
state.last_time = cc1;
|
||||
state.scaled_ticks_per_cycle
|
||||
= ((unsigned long) HZ << FIX_SHIFT) / cycle_freq;
|
||||
state.partial_tick = 0L;
|
||||
/* See above for restrictions on using clocksource_rpcc. */
|
||||
#ifndef CONFIG_ALPHA_WTINT
|
||||
if (hwrpb->nr_processors == 1)
|
||||
clocksource_register_hz(&clocksource_rpcc, cycle_freq);
|
||||
#endif
|
||||
|
||||
/* Startup the timer source. */
|
||||
alpha_mv.init_rtc();
|
||||
init_rtc_clockevent();
|
||||
}
|
||||
|
||||
/*
|
||||
* In order to set the CMOS clock precisely, set_rtc_mmss has to be
|
||||
* called 500 ms after the second nowtime has started, because when
|
||||
* nowtime is written into the registers of the CMOS clock, it will
|
||||
* jump to the next second precisely 500 ms later. Check the Motorola
|
||||
* MC146818A or Dallas DS12887 data sheet for details.
|
||||
*
|
||||
* BUG: This routine does not handle hour overflow properly; it just
|
||||
* sets the minutes. Usually you won't notice until after reboot!
|
||||
*/
|
||||
|
||||
|
||||
static int
|
||||
set_rtc_mmss(unsigned long nowtime)
|
||||
/* Initialize the clock_event_device for secondary cpus. */
|
||||
#ifdef CONFIG_SMP
|
||||
void __init
|
||||
init_clockevent(void)
|
||||
{
|
||||
int retval = 0;
|
||||
int real_seconds, real_minutes, cmos_minutes;
|
||||
unsigned char save_control, save_freq_select;
|
||||
|
||||
/* irq are locally disabled here */
|
||||
spin_lock(&rtc_lock);
|
||||
/* Tell the clock it's being set */
|
||||
save_control = CMOS_READ(RTC_CONTROL);
|
||||
CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
|
||||
|
||||
/* Stop and reset prescaler */
|
||||
save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
|
||||
CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
|
||||
|
||||
cmos_minutes = CMOS_READ(RTC_MINUTES);
|
||||
if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
|
||||
cmos_minutes = bcd2bin(cmos_minutes);
|
||||
|
||||
/*
|
||||
* since we're only adjusting minutes and seconds,
|
||||
* don't interfere with hour overflow. This avoids
|
||||
* messing with unknown time zones but requires your
|
||||
* RTC not to be off by more than 15 minutes
|
||||
*/
|
||||
real_seconds = nowtime % 60;
|
||||
real_minutes = nowtime / 60;
|
||||
if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) {
|
||||
/* correct for half hour time zone */
|
||||
real_minutes += 30;
|
||||
}
|
||||
real_minutes %= 60;
|
||||
|
||||
if (abs(real_minutes - cmos_minutes) < 30) {
|
||||
if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
|
||||
real_seconds = bin2bcd(real_seconds);
|
||||
real_minutes = bin2bcd(real_minutes);
|
||||
}
|
||||
CMOS_WRITE(real_seconds,RTC_SECONDS);
|
||||
CMOS_WRITE(real_minutes,RTC_MINUTES);
|
||||
} else {
|
||||
printk_once(KERN_NOTICE
|
||||
"set_rtc_mmss: can't update from %d to %d\n",
|
||||
cmos_minutes, real_minutes);
|
||||
retval = -1;
|
||||
}
|
||||
|
||||
/* The following flags have to be released exactly in this order,
|
||||
* otherwise the DS12887 (popular MC146818A clone with integrated
|
||||
* battery and quartz) will not reset the oscillator and will not
|
||||
* update precisely 500 ms later. You won't find this mentioned in
|
||||
* the Dallas Semiconductor data sheets, but who believes data
|
||||
* sheets anyway ... -- Markus Kuhn
|
||||
*/
|
||||
CMOS_WRITE(save_control, RTC_CONTROL);
|
||||
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
|
||||
spin_unlock(&rtc_lock);
|
||||
|
||||
return retval;
|
||||
if (alpha_using_qemu)
|
||||
init_qemu_clockevent();
|
||||
else
|
||||
init_rtc_clockevent();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -241,6 +241,21 @@ do_entIF(unsigned long type, struct pt_regs *regs)
|
|||
(const char *)(data[1] | (long)data[2] << 32),
|
||||
data[0]);
|
||||
}
|
||||
#ifdef CONFIG_ALPHA_WTINT
|
||||
if (type == 4) {
|
||||
/* If CALL_PAL WTINT is totally unsupported by the
|
||||
PALcode, e.g. MILO, "emulate" it by overwriting
|
||||
the insn. */
|
||||
unsigned int *pinsn
|
||||
= (unsigned int *) regs->pc - 1;
|
||||
if (*pinsn == PAL_wtint) {
|
||||
*pinsn = 0x47e01400; /* mov 0,$0 */
|
||||
imb();
|
||||
regs->r0 = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* ALPHA_WTINT */
|
||||
die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"),
|
||||
regs, type, NULL);
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ csum_partial_cfu_aligned(const unsigned long __user *src, unsigned long *dst,
|
|||
*dst = word | tmp;
|
||||
checksum += carry;
|
||||
}
|
||||
if (err) *errp = err;
|
||||
if (err && errp) *errp = err;
|
||||
return checksum;
|
||||
}
|
||||
|
||||
|
@ -185,7 +185,7 @@ csum_partial_cfu_dest_aligned(const unsigned long __user *src,
|
|||
*dst = word | tmp;
|
||||
checksum += carry;
|
||||
}
|
||||
if (err) *errp = err;
|
||||
if (err && errp) *errp = err;
|
||||
return checksum;
|
||||
}
|
||||
|
||||
|
@ -242,7 +242,7 @@ csum_partial_cfu_src_aligned(const unsigned long __user *src,
|
|||
stq_u(partial_dest | second_dest, dst);
|
||||
out:
|
||||
checksum += carry;
|
||||
if (err) *errp = err;
|
||||
if (err && errp) *errp = err;
|
||||
return checksum;
|
||||
}
|
||||
|
||||
|
@ -325,7 +325,7 @@ csum_partial_cfu_unaligned(const unsigned long __user * src,
|
|||
stq_u(partial_dest | word | second_dest, dst);
|
||||
checksum += carry;
|
||||
}
|
||||
if (err) *errp = err;
|
||||
if (err && errp) *errp = err;
|
||||
return checksum;
|
||||
}
|
||||
|
||||
|
@ -339,7 +339,7 @@ csum_partial_copy_from_user(const void __user *src, void *dst, int len,
|
|||
|
||||
if (len) {
|
||||
if (!access_ok(VERIFY_READ, src, len)) {
|
||||
*errp = -EFAULT;
|
||||
if (errp) *errp = -EFAULT;
|
||||
memset(dst, 0, len);
|
||||
return sum;
|
||||
}
|
||||
|
|
|
@ -30,14 +30,15 @@
|
|||
.set noat
|
||||
.set noreorder
|
||||
.text
|
||||
.globl memset
|
||||
.globl __memset
|
||||
.globl ___memset
|
||||
.globl __memsetw
|
||||
.globl __constant_c_memset
|
||||
.globl memset
|
||||
|
||||
.ent __memset
|
||||
.ent ___memset
|
||||
.align 5
|
||||
__memset:
|
||||
___memset:
|
||||
.frame $30,0,$26,0
|
||||
.prologue 0
|
||||
|
||||
|
@ -227,7 +228,7 @@ end_b:
|
|||
nop
|
||||
nop
|
||||
ret $31,($26),1 # L0 :
|
||||
.end __memset
|
||||
.end ___memset
|
||||
|
||||
/*
|
||||
* This is the original body of code, prior to replication and
|
||||
|
@ -594,4 +595,5 @@ end_w:
|
|||
|
||||
.end __memsetw
|
||||
|
||||
memset = __memset
|
||||
memset = ___memset
|
||||
__memset = ___memset
|
||||
|
|
|
@ -19,11 +19,13 @@
|
|||
.text
|
||||
.globl memset
|
||||
.globl __memset
|
||||
.globl ___memset
|
||||
.globl __memsetw
|
||||
.globl __constant_c_memset
|
||||
.ent __memset
|
||||
|
||||
.ent ___memset
|
||||
.align 5
|
||||
__memset:
|
||||
___memset:
|
||||
.frame $30,0,$26,0
|
||||
.prologue 0
|
||||
|
||||
|
@ -103,7 +105,7 @@ within_one_quad:
|
|||
|
||||
end:
|
||||
ret $31,($26),1 /* E1 */
|
||||
.end __memset
|
||||
.end ___memset
|
||||
|
||||
.align 5
|
||||
.ent __memsetw
|
||||
|
@ -121,4 +123,5 @@ __memsetw:
|
|||
|
||||
.end __memsetw
|
||||
|
||||
memset = __memset
|
||||
memset = ___memset
|
||||
__memset = ___memset
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
config ARC
|
||||
def_bool y
|
||||
select BUILDTIME_EXTABLE_SORT
|
||||
select CLONE_BACKWARDS
|
||||
# ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev
|
||||
select DEVTMPFS if !INITRAMFS_SOURCE=""
|
||||
|
|
|
@ -43,124 +43,124 @@
|
|||
iomux: iomux@FF10601c {
|
||||
/* Port 1 */
|
||||
pctl_tsin_s0: pctl-tsin-s0 { /* Serial TS-in 0 */
|
||||
pingrp = "mis0_pins";
|
||||
abilis,function = "mis0";
|
||||
};
|
||||
pctl_tsin_s1: pctl-tsin-s1 { /* Serial TS-in 1 */
|
||||
pingrp = "mis1_pins";
|
||||
abilis,function = "mis1";
|
||||
};
|
||||
pctl_gpio_a: pctl-gpio-a { /* GPIO bank A */
|
||||
pingrp = "gpioa_pins";
|
||||
abilis,function = "gpioa";
|
||||
};
|
||||
pctl_tsin_p1: pctl-tsin-p1 { /* Parallel TS-in 1 */
|
||||
pingrp = "mip1_pins";
|
||||
abilis,function = "mip1";
|
||||
};
|
||||
/* Port 2 */
|
||||
pctl_tsin_s2: pctl-tsin-s2 { /* Serial TS-in 2 */
|
||||
pingrp = "mis2_pins";
|
||||
abilis,function = "mis2";
|
||||
};
|
||||
pctl_tsin_s3: pctl-tsin-s3 { /* Serial TS-in 3 */
|
||||
pingrp = "mis3_pins";
|
||||
abilis,function = "mis3";
|
||||
};
|
||||
pctl_gpio_c: pctl-gpio-c { /* GPIO bank C */
|
||||
pingrp = "gpioc_pins";
|
||||
abilis,function = "gpioc";
|
||||
};
|
||||
pctl_tsin_p3: pctl-tsin-p3 { /* Parallel TS-in 3 */
|
||||
pingrp = "mip3_pins";
|
||||
abilis,function = "mip3";
|
||||
};
|
||||
/* Port 3 */
|
||||
pctl_tsin_s4: pctl-tsin-s4 { /* Serial TS-in 4 */
|
||||
pingrp = "mis4_pins";
|
||||
abilis,function = "mis4";
|
||||
};
|
||||
pctl_tsin_s5: pctl-tsin-s5 { /* Serial TS-in 5 */
|
||||
pingrp = "mis5_pins";
|
||||
abilis,function = "mis5";
|
||||
};
|
||||
pctl_gpio_e: pctl-gpio-e { /* GPIO bank E */
|
||||
pingrp = "gpioe_pins";
|
||||
abilis,function = "gpioe";
|
||||
};
|
||||
pctl_tsin_p5: pctl-tsin-p5 { /* Parallel TS-in 5 */
|
||||
pingrp = "mip5_pins";
|
||||
abilis,function = "mip5";
|
||||
};
|
||||
/* Port 4 */
|
||||
pctl_tsin_s6: pctl-tsin-s6 { /* Serial TS-in 6 */
|
||||
pingrp = "mis6_pins";
|
||||
abilis,function = "mis6";
|
||||
};
|
||||
pctl_tsin_s7: pctl-tsin-s7 { /* Serial TS-in 7 */
|
||||
pingrp = "mis7_pins";
|
||||
abilis,function = "mis7";
|
||||
};
|
||||
pctl_gpio_g: pctl-gpio-g { /* GPIO bank G */
|
||||
pingrp = "gpiog_pins";
|
||||
abilis,function = "gpiog";
|
||||
};
|
||||
pctl_tsin_p7: pctl-tsin-p7 { /* Parallel TS-in 7 */
|
||||
pingrp = "mip7_pins";
|
||||
abilis,function = "mip7";
|
||||
};
|
||||
/* Port 5 */
|
||||
pctl_gpio_j: pctl-gpio-j { /* GPIO bank J */
|
||||
pingrp = "gpioj_pins";
|
||||
abilis,function = "gpioj";
|
||||
};
|
||||
pctl_gpio_k: pctl-gpio-k { /* GPIO bank K */
|
||||
pingrp = "gpiok_pins";
|
||||
abilis,function = "gpiok";
|
||||
};
|
||||
pctl_ciplus: pctl-ciplus { /* CI+ interface */
|
||||
pingrp = "ciplus_pins";
|
||||
abilis,function = "ciplus";
|
||||
};
|
||||
pctl_mcard: pctl-mcard { /* M-Card interface */
|
||||
pingrp = "mcard_pins";
|
||||
abilis,function = "mcard";
|
||||
};
|
||||
/* Port 6 */
|
||||
pctl_tsout_p: pctl-tsout-p { /* Parallel TS-out */
|
||||
pingrp = "mop_pins";
|
||||
abilis,function = "mop";
|
||||
};
|
||||
pctl_tsout_s0: pctl-tsout-s0 { /* Serial TS-out 0 */
|
||||
pingrp = "mos0_pins";
|
||||
abilis,function = "mos0";
|
||||
};
|
||||
pctl_tsout_s1: pctl-tsout-s1 { /* Serial TS-out 1 */
|
||||
pingrp = "mos1_pins";
|
||||
abilis,function = "mos1";
|
||||
};
|
||||
pctl_tsout_s2: pctl-tsout-s2 { /* Serial TS-out 2 */
|
||||
pingrp = "mos2_pins";
|
||||
abilis,function = "mos2";
|
||||
};
|
||||
pctl_tsout_s3: pctl-tsout-s3 { /* Serial TS-out 3 */
|
||||
pingrp = "mos3_pins";
|
||||
abilis,function = "mos3";
|
||||
};
|
||||
/* Port 7 */
|
||||
pctl_uart0: pctl-uart0 { /* UART 0 */
|
||||
pingrp = "uart0_pins";
|
||||
abilis,function = "uart0";
|
||||
};
|
||||
pctl_uart1: pctl-uart1 { /* UART 1 */
|
||||
pingrp = "uart1_pins";
|
||||
abilis,function = "uart1";
|
||||
};
|
||||
pctl_gpio_l: pctl-gpio-l { /* GPIO bank L */
|
||||
pingrp = "gpiol_pins";
|
||||
abilis,function = "gpiol";
|
||||
};
|
||||
pctl_gpio_m: pctl-gpio-m { /* GPIO bank M */
|
||||
pingrp = "gpiom_pins";
|
||||
abilis,function = "gpiom";
|
||||
};
|
||||
/* Port 8 */
|
||||
pctl_spi3: pctl-spi3 {
|
||||
pingrp = "spi3_pins";
|
||||
abilis,function = "spi3";
|
||||
};
|
||||
/* Port 9 */
|
||||
pctl_spi1: pctl-spi1 {
|
||||
pingrp = "spi1_pins";
|
||||
abilis,function = "spi1";
|
||||
};
|
||||
pctl_gpio_n: pctl-gpio-n {
|
||||
pingrp = "gpion_pins";
|
||||
abilis,function = "gpion";
|
||||
};
|
||||
/* Unmuxed GPIOs */
|
||||
pctl_gpio_b: pctl-gpio-b {
|
||||
pingrp = "gpiob_pins";
|
||||
abilis,function = "gpiob";
|
||||
};
|
||||
pctl_gpio_d: pctl-gpio-d {
|
||||
pingrp = "gpiod_pins";
|
||||
abilis,function = "gpiod";
|
||||
};
|
||||
pctl_gpio_f: pctl-gpio-f {
|
||||
pingrp = "gpiof_pins";
|
||||
abilis,function = "gpiof";
|
||||
};
|
||||
pctl_gpio_h: pctl-gpio-h {
|
||||
pingrp = "gpioh_pins";
|
||||
abilis,function = "gpioh";
|
||||
};
|
||||
pctl_gpio_i: pctl-gpio-i {
|
||||
pingrp = "gpioi_pins";
|
||||
abilis,function = "gpioi";
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -172,9 +172,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF140000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <0>;
|
||||
gpio-pins = <&pctl_gpio_a>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <3>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpioa";
|
||||
};
|
||||
gpiob: gpio@FF141000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -184,9 +185,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF141000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <3>;
|
||||
gpio-pins = <&pctl_gpio_b>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <2>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpiob";
|
||||
};
|
||||
gpioc: gpio@FF142000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -196,9 +198,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF142000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <5>;
|
||||
gpio-pins = <&pctl_gpio_c>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <3>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpioc";
|
||||
};
|
||||
gpiod: gpio@FF143000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -208,9 +211,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF143000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <8>;
|
||||
gpio-pins = <&pctl_gpio_d>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <2>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpiod";
|
||||
};
|
||||
gpioe: gpio@FF144000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -220,9 +224,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF144000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <10>;
|
||||
gpio-pins = <&pctl_gpio_e>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <3>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpioe";
|
||||
};
|
||||
gpiof: gpio@FF145000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -232,9 +237,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF145000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <13>;
|
||||
gpio-pins = <&pctl_gpio_f>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <2>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpiof";
|
||||
};
|
||||
gpiog: gpio@FF146000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -244,9 +250,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF146000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <15>;
|
||||
gpio-pins = <&pctl_gpio_g>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <3>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpiog";
|
||||
};
|
||||
gpioh: gpio@FF147000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -256,9 +263,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF147000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <18>;
|
||||
gpio-pins = <&pctl_gpio_h>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <2>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpioh";
|
||||
};
|
||||
gpioi: gpio@FF148000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -268,9 +276,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF148000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <20>;
|
||||
gpio-pins = <&pctl_gpio_i>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <12>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpioi";
|
||||
};
|
||||
gpioj: gpio@FF149000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -280,9 +289,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF149000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <32>;
|
||||
gpio-pins = <&pctl_gpio_j>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <32>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpioj";
|
||||
};
|
||||
gpiok: gpio@FF14a000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -292,9 +302,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF14A000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <64>;
|
||||
gpio-pins = <&pctl_gpio_k>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <22>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpiok";
|
||||
};
|
||||
gpiol: gpio@FF14b000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -304,9 +315,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF14B000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <86>;
|
||||
gpio-pins = <&pctl_gpio_l>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <4>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpiol";
|
||||
};
|
||||
gpiom: gpio@FF14c000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -316,9 +328,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF14C000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <90>;
|
||||
gpio-pins = <&pctl_gpio_m>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <4>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpiom";
|
||||
};
|
||||
gpion: gpio@FF14d000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -328,9 +341,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF14D000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <94>;
|
||||
gpio-pins = <&pctl_gpio_n>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <5>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpion";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -64,62 +64,62 @@
|
|||
compatible = "gpio-leds";
|
||||
power {
|
||||
label = "Power";
|
||||
gpios = <&gpioi 0>;
|
||||
gpios = <&gpioi 0 0>;
|
||||
linux,default-trigger = "default-on";
|
||||
};
|
||||
heartbeat {
|
||||
label = "Heartbeat";
|
||||
gpios = <&gpioi 1>;
|
||||
gpios = <&gpioi 1 0>;
|
||||
linux,default-trigger = "heartbeat";
|
||||
};
|
||||
led2 {
|
||||
label = "LED2";
|
||||
gpios = <&gpioi 2>;
|
||||
gpios = <&gpioi 2 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led3 {
|
||||
label = "LED3";
|
||||
gpios = <&gpioi 3>;
|
||||
gpios = <&gpioi 3 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led4 {
|
||||
label = "LED4";
|
||||
gpios = <&gpioi 4>;
|
||||
gpios = <&gpioi 4 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led5 {
|
||||
label = "LED5";
|
||||
gpios = <&gpioi 5>;
|
||||
gpios = <&gpioi 5 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led6 {
|
||||
label = "LED6";
|
||||
gpios = <&gpioi 6>;
|
||||
gpios = <&gpioi 6 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led7 {
|
||||
label = "LED7";
|
||||
gpios = <&gpioi 7>;
|
||||
gpios = <&gpioi 7 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led8 {
|
||||
label = "LED8";
|
||||
gpios = <&gpioi 8>;
|
||||
gpios = <&gpioi 8 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led9 {
|
||||
label = "LED9";
|
||||
gpios = <&gpioi 9>;
|
||||
gpios = <&gpioi 9 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led10 {
|
||||
label = "LED10";
|
||||
gpios = <&gpioi 10>;
|
||||
gpios = <&gpioi 10 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led11 {
|
||||
label = "LED11";
|
||||
gpios = <&gpioi 11>;
|
||||
gpios = <&gpioi 11 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -43,133 +43,133 @@
|
|||
iomux: iomux@FF10601c {
|
||||
/* Port 1 */
|
||||
pctl_tsin_s0: pctl-tsin-s0 { /* Serial TS-in 0 */
|
||||
pingrp = "mis0_pins";
|
||||
abilis,function = "mis0";
|
||||
};
|
||||
pctl_tsin_s1: pctl-tsin-s1 { /* Serial TS-in 1 */
|
||||
pingrp = "mis1_pins";
|
||||
abilis,function = "mis1";
|
||||
};
|
||||
pctl_gpio_a: pctl-gpio-a { /* GPIO bank A */
|
||||
pingrp = "gpioa_pins";
|
||||
abilis,function = "gpioa";
|
||||
};
|
||||
pctl_tsin_p1: pctl-tsin-p1 { /* Parallel TS-in 1 */
|
||||
pingrp = "mip1_pins";
|
||||
abilis,function = "mip1";
|
||||
};
|
||||
/* Port 2 */
|
||||
pctl_tsin_s2: pctl-tsin-s2 { /* Serial TS-in 2 */
|
||||
pingrp = "mis2_pins";
|
||||
abilis,function = "mis2";
|
||||
};
|
||||
pctl_tsin_s3: pctl-tsin-s3 { /* Serial TS-in 3 */
|
||||
pingrp = "mis3_pins";
|
||||
abilis,function = "mis3";
|
||||
};
|
||||
pctl_gpio_c: pctl-gpio-c { /* GPIO bank C */
|
||||
pingrp = "gpioc_pins";
|
||||
abilis,function = "gpioc";
|
||||
};
|
||||
pctl_tsin_p3: pctl-tsin-p3 { /* Parallel TS-in 3 */
|
||||
pingrp = "mip3_pins";
|
||||
abilis,function = "mip3";
|
||||
};
|
||||
/* Port 3 */
|
||||
pctl_tsin_s4: pctl-tsin-s4 { /* Serial TS-in 4 */
|
||||
pingrp = "mis4_pins";
|
||||
abilis,function = "mis4";
|
||||
};
|
||||
pctl_tsin_s5: pctl-tsin-s5 { /* Serial TS-in 5 */
|
||||
pingrp = "mis5_pins";
|
||||
abilis,function = "mis5";
|
||||
};
|
||||
pctl_gpio_e: pctl-gpio-e { /* GPIO bank E */
|
||||
pingrp = "gpioe_pins";
|
||||
abilis,function = "gpioe";
|
||||
};
|
||||
pctl_tsin_p5: pctl-tsin-p5 { /* Parallel TS-in 5 */
|
||||
pingrp = "mip5_pins";
|
||||
abilis,function = "mip5";
|
||||
};
|
||||
/* Port 4 */
|
||||
pctl_tsin_s6: pctl-tsin-s6 { /* Serial TS-in 6 */
|
||||
pingrp = "mis6_pins";
|
||||
abilis,function = "mis6";
|
||||
};
|
||||
pctl_tsin_s7: pctl-tsin-s7 { /* Serial TS-in 7 */
|
||||
pingrp = "mis7_pins";
|
||||
abilis,function = "mis7";
|
||||
};
|
||||
pctl_gpio_g: pctl-gpio-g { /* GPIO bank G */
|
||||
pingrp = "gpiog_pins";
|
||||
abilis,function = "gpiog";
|
||||
};
|
||||
pctl_tsin_p7: pctl-tsin-p7 { /* Parallel TS-in 7 */
|
||||
pingrp = "mip7_pins";
|
||||
abilis,function = "mip7";
|
||||
};
|
||||
/* Port 5 */
|
||||
pctl_gpio_j: pctl-gpio-j { /* GPIO bank J */
|
||||
pingrp = "gpioj_pins";
|
||||
abilis,function = "gpioj";
|
||||
};
|
||||
pctl_gpio_k: pctl-gpio-k { /* GPIO bank K */
|
||||
pingrp = "gpiok_pins";
|
||||
abilis,function = "gpiok";
|
||||
};
|
||||
pctl_ciplus: pctl-ciplus { /* CI+ interface */
|
||||
pingrp = "ciplus_pins";
|
||||
abilis,function = "ciplus";
|
||||
};
|
||||
pctl_mcard: pctl-mcard { /* M-Card interface */
|
||||
pingrp = "mcard_pins";
|
||||
abilis,function = "mcard";
|
||||
};
|
||||
pctl_stc0: pctl-stc0 { /* Smart card I/F 0 */
|
||||
pingrp = "stc0_pins";
|
||||
abilis,function = "stc0";
|
||||
};
|
||||
pctl_stc1: pctl-stc1 { /* Smart card I/F 1 */
|
||||
pingrp = "stc1_pins";
|
||||
abilis,function = "stc1";
|
||||
};
|
||||
/* Port 6 */
|
||||
pctl_tsout_p: pctl-tsout-p { /* Parallel TS-out */
|
||||
pingrp = "mop_pins";
|
||||
abilis,function = "mop";
|
||||
};
|
||||
pctl_tsout_s0: pctl-tsout-s0 { /* Serial TS-out 0 */
|
||||
pingrp = "mos0_pins";
|
||||
abilis,function = "mos0";
|
||||
};
|
||||
pctl_tsout_s1: pctl-tsout-s1 { /* Serial TS-out 1 */
|
||||
pingrp = "mos1_pins";
|
||||
abilis,function = "mos1";
|
||||
};
|
||||
pctl_tsout_s2: pctl-tsout-s2 { /* Serial TS-out 2 */
|
||||
pingrp = "mos2_pins";
|
||||
abilis,function = "mos2";
|
||||
};
|
||||
pctl_tsout_s3: pctl-tsout-s3 { /* Serial TS-out 3 */
|
||||
pingrp = "mos3_pins";
|
||||
abilis,function = "mos3";
|
||||
};
|
||||
/* Port 7 */
|
||||
pctl_uart0: pctl-uart0 { /* UART 0 */
|
||||
pingrp = "uart0_pins";
|
||||
abilis,function = "uart0";
|
||||
};
|
||||
pctl_uart1: pctl-uart1 { /* UART 1 */
|
||||
pingrp = "uart1_pins";
|
||||
abilis,function = "uart1";
|
||||
};
|
||||
pctl_gpio_l: pctl-gpio-l { /* GPIO bank L */
|
||||
pingrp = "gpiol_pins";
|
||||
abilis,function = "gpiol";
|
||||
};
|
||||
pctl_gpio_m: pctl-gpio-m { /* GPIO bank M */
|
||||
pingrp = "gpiom_pins";
|
||||
abilis,function = "gpiom";
|
||||
};
|
||||
/* Port 8 */
|
||||
pctl_spi3: pctl-spi3 {
|
||||
pingrp = "spi3_pins";
|
||||
abilis,function = "spi3";
|
||||
};
|
||||
pctl_jtag: pctl-jtag {
|
||||
pingrp = "jtag_pins";
|
||||
abilis,function = "jtag";
|
||||
};
|
||||
/* Port 9 */
|
||||
pctl_spi1: pctl-spi1 {
|
||||
pingrp = "spi1_pins";
|
||||
abilis,function = "spi1";
|
||||
};
|
||||
pctl_gpio_n: pctl-gpio-n {
|
||||
pingrp = "gpion_pins";
|
||||
abilis,function = "gpion";
|
||||
};
|
||||
/* Unmuxed GPIOs */
|
||||
pctl_gpio_b: pctl-gpio-b {
|
||||
pingrp = "gpiob_pins";
|
||||
abilis,function = "gpiob";
|
||||
};
|
||||
pctl_gpio_d: pctl-gpio-d {
|
||||
pingrp = "gpiod_pins";
|
||||
abilis,function = "gpiod";
|
||||
};
|
||||
pctl_gpio_f: pctl-gpio-f {
|
||||
pingrp = "gpiof_pins";
|
||||
abilis,function = "gpiof";
|
||||
};
|
||||
pctl_gpio_h: pctl-gpio-h {
|
||||
pingrp = "gpioh_pins";
|
||||
abilis,function = "gpioh";
|
||||
};
|
||||
pctl_gpio_i: pctl-gpio-i {
|
||||
pingrp = "gpioi_pins";
|
||||
abilis,function = "gpioi";
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -181,9 +181,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF140000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <0>;
|
||||
gpio-pins = <&pctl_gpio_a>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <3>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpioa";
|
||||
};
|
||||
gpiob: gpio@FF141000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -193,9 +194,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF141000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <3>;
|
||||
gpio-pins = <&pctl_gpio_b>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <2>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpiob";
|
||||
};
|
||||
gpioc: gpio@FF142000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -205,9 +207,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF142000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <5>;
|
||||
gpio-pins = <&pctl_gpio_c>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <3>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpioc";
|
||||
};
|
||||
gpiod: gpio@FF143000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -217,9 +220,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF143000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <8>;
|
||||
gpio-pins = <&pctl_gpio_d>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <2>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpiod";
|
||||
};
|
||||
gpioe: gpio@FF144000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -229,9 +233,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF144000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <10>;
|
||||
gpio-pins = <&pctl_gpio_e>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <3>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpioe";
|
||||
};
|
||||
gpiof: gpio@FF145000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -241,9 +246,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF145000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <13>;
|
||||
gpio-pins = <&pctl_gpio_f>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <2>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpiof";
|
||||
};
|
||||
gpiog: gpio@FF146000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -253,9 +259,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF146000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <15>;
|
||||
gpio-pins = <&pctl_gpio_g>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <3>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpiog";
|
||||
};
|
||||
gpioh: gpio@FF147000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -265,9 +272,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF147000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <18>;
|
||||
gpio-pins = <&pctl_gpio_h>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <2>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpioh";
|
||||
};
|
||||
gpioi: gpio@FF148000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -277,9 +285,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF148000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <20>;
|
||||
gpio-pins = <&pctl_gpio_i>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <12>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpioi";
|
||||
};
|
||||
gpioj: gpio@FF149000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -289,9 +298,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF149000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <32>;
|
||||
gpio-pins = <&pctl_gpio_j>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <32>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpioj";
|
||||
};
|
||||
gpiok: gpio@FF14a000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -301,9 +311,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF14A000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <64>;
|
||||
gpio-pins = <&pctl_gpio_k>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <22>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpiok";
|
||||
};
|
||||
gpiol: gpio@FF14b000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -313,9 +324,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF14B000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <86>;
|
||||
gpio-pins = <&pctl_gpio_l>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <4>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpiol";
|
||||
};
|
||||
gpiom: gpio@FF14c000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -325,9 +337,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF14C000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <90>;
|
||||
gpio-pins = <&pctl_gpio_m>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <4>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpiom";
|
||||
};
|
||||
gpion: gpio@FF14d000 {
|
||||
compatible = "abilis,tb10x-gpio";
|
||||
|
@ -337,9 +350,10 @@
|
|||
interrupts = <27 2>;
|
||||
reg = <0xFF14D000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
gpio-base = <94>;
|
||||
gpio-pins = <&pctl_gpio_n>;
|
||||
#gpio-cells = <2>;
|
||||
abilis,ngpio = <5>;
|
||||
gpio-ranges = <&iomux 0 0 0>;
|
||||
gpio-ranges-group-names = "gpion";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -64,62 +64,62 @@
|
|||
compatible = "gpio-leds";
|
||||
power {
|
||||
label = "Power";
|
||||
gpios = <&gpioi 0>;
|
||||
gpios = <&gpioi 0 0>;
|
||||
linux,default-trigger = "default-on";
|
||||
};
|
||||
heartbeat {
|
||||
label = "Heartbeat";
|
||||
gpios = <&gpioi 1>;
|
||||
gpios = <&gpioi 1 0>;
|
||||
linux,default-trigger = "heartbeat";
|
||||
};
|
||||
led2 {
|
||||
label = "LED2";
|
||||
gpios = <&gpioi 2>;
|
||||
gpios = <&gpioi 2 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led3 {
|
||||
label = "LED3";
|
||||
gpios = <&gpioi 3>;
|
||||
gpios = <&gpioi 3 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led4 {
|
||||
label = "LED4";
|
||||
gpios = <&gpioi 4>;
|
||||
gpios = <&gpioi 4 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led5 {
|
||||
label = "LED5";
|
||||
gpios = <&gpioi 5>;
|
||||
gpios = <&gpioi 5 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led6 {
|
||||
label = "LED6";
|
||||
gpios = <&gpioi 6>;
|
||||
gpios = <&gpioi 6 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led7 {
|
||||
label = "LED7";
|
||||
gpios = <&gpioi 7>;
|
||||
gpios = <&gpioi 7 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led8 {
|
||||
label = "LED8";
|
||||
gpios = <&gpioi 8>;
|
||||
gpios = <&gpioi 8 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led9 {
|
||||
label = "LED9";
|
||||
gpios = <&gpioi 9>;
|
||||
gpios = <&gpioi 9 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led10 {
|
||||
label = "LED10";
|
||||
gpios = <&gpioi 10>;
|
||||
gpios = <&gpioi 10 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
led11 {
|
||||
label = "LED11";
|
||||
gpios = <&gpioi 11>;
|
||||
gpios = <&gpioi 11 0>;
|
||||
default-state = "off";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -62,9 +62,8 @@
|
|||
};
|
||||
|
||||
iomux: iomux@FF10601c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "abilis,tb10x-iomux";
|
||||
#gpio-range-cells = <3>;
|
||||
reg = <0xFF10601c 0x4>;
|
||||
};
|
||||
|
||||
|
|
|
@ -67,5 +67,9 @@
|
|||
reg = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
arcpmu0: pmu {
|
||||
compatible = "snps,arc700-pmu";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
|
||||
# CONFIG_LOCALVERSION_AUTO is not set
|
||||
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_IKCONFIG=y
|
||||
CONFIG_IKCONFIG_PROC=y
|
||||
CONFIG_NAMESPACES=y
|
||||
# CONFIG_UTS_NS is not set
|
||||
# CONFIG_PID_NS is not set
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
CONFIG_EMBEDDED=y
|
||||
# CONFIG_SLUB_DEBUG is not set
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_KPROBES=y
|
||||
CONFIG_MODULES=y
|
||||
# CONFIG_LBDAF is not set
|
||||
# CONFIG_BLK_DEV_BSG is not set
|
||||
# CONFIG_IOSCHED_DEADLINE is not set
|
||||
# CONFIG_IOSCHED_CFQ is not set
|
||||
CONFIG_ARC_PLAT_FPGA_LEGACY=y
|
||||
CONFIG_ARC_BOARD_ML509=y
|
||||
# CONFIG_ARC_HAS_RTSC is not set
|
||||
CONFIG_ARC_BUILTIN_DTB_NAME="angel4"
|
||||
CONFIG_PREEMPT=y
|
||||
# CONFIG_COMPACTION is not set
|
||||
# CONFIG_CROSS_MEMORY_ATTACH is not set
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_UNIX=y
|
||||
CONFIG_UNIX_DIAG=y
|
||||
CONFIG_NET_KEY=y
|
||||
CONFIG_INET=y
|
||||
# CONFIG_IPV6 is not set
|
||||
# CONFIG_STANDALONE is not set
|
||||
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
|
||||
# CONFIG_FIRMWARE_IN_KERNEL is not set
|
||||
# CONFIG_BLK_DEV is not set
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_ARC_EMAC=y
|
||||
CONFIG_LXT_PHY=y
|
||||
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
|
||||
# CONFIG_INPUT_KEYBOARD is not set
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_ARC=y
|
||||
CONFIG_SERIAL_ARC_CONSOLE=y
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
# CONFIG_HWMON is not set
|
||||
# CONFIG_VGA_CONSOLE is not set
|
||||
# CONFIG_HID is not set
|
||||
# CONFIG_USB_SUPPORT is not set
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT2_FS_XATTR=y
|
||||
CONFIG_TMPFS=y
|
||||
# CONFIG_MISC_FILESYSTEMS is not set
|
||||
CONFIG_NFS_FS=y
|
||||
# CONFIG_ENABLE_WARN_DEPRECATED is not set
|
||||
# CONFIG_ENABLE_MUST_CHECK is not set
|
||||
CONFIG_XZ_DEC=y
|
|
@ -1,5 +1,7 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2012 Synopsys, Inc. (www.synopsys.com)
|
||||
* Linux performance counter support for ARC
|
||||
*
|
||||
* Copyright (C) 2011-2013 Synopsys, Inc. (www.synopsys.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -10,4 +12,204 @@
|
|||
#ifndef __ASM_PERF_EVENT_H
|
||||
#define __ASM_PERF_EVENT_H
|
||||
|
||||
/* real maximum varies per CPU, this is the maximum supported by the driver */
|
||||
#define ARC_PMU_MAX_HWEVENTS 64
|
||||
|
||||
#define ARC_REG_CC_BUILD 0xF6
|
||||
#define ARC_REG_CC_INDEX 0x240
|
||||
#define ARC_REG_CC_NAME0 0x241
|
||||
#define ARC_REG_CC_NAME1 0x242
|
||||
|
||||
#define ARC_REG_PCT_BUILD 0xF5
|
||||
#define ARC_REG_PCT_COUNTL 0x250
|
||||
#define ARC_REG_PCT_COUNTH 0x251
|
||||
#define ARC_REG_PCT_SNAPL 0x252
|
||||
#define ARC_REG_PCT_SNAPH 0x253
|
||||
#define ARC_REG_PCT_CONFIG 0x254
|
||||
#define ARC_REG_PCT_CONTROL 0x255
|
||||
#define ARC_REG_PCT_INDEX 0x256
|
||||
|
||||
#define ARC_REG_PCT_CONTROL_CC (1 << 16) /* clear counts */
|
||||
#define ARC_REG_PCT_CONTROL_SN (1 << 17) /* snapshot */
|
||||
|
||||
struct arc_reg_pct_build {
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
unsigned int m:8, c:8, r:6, s:2, v:8;
|
||||
#else
|
||||
unsigned int v:8, s:2, r:6, c:8, m:8;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct arc_reg_cc_build {
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
unsigned int c:16, r:8, v:8;
|
||||
#else
|
||||
unsigned int v:8, r:8, c:16;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define PERF_COUNT_ARC_DCLM (PERF_COUNT_HW_MAX + 0)
|
||||
#define PERF_COUNT_ARC_DCSM (PERF_COUNT_HW_MAX + 1)
|
||||
#define PERF_COUNT_ARC_ICM (PERF_COUNT_HW_MAX + 2)
|
||||
#define PERF_COUNT_ARC_BPOK (PERF_COUNT_HW_MAX + 3)
|
||||
#define PERF_COUNT_ARC_EDTLB (PERF_COUNT_HW_MAX + 4)
|
||||
#define PERF_COUNT_ARC_EITLB (PERF_COUNT_HW_MAX + 5)
|
||||
#define PERF_COUNT_ARC_HW_MAX (PERF_COUNT_HW_MAX + 6)
|
||||
|
||||
/*
|
||||
* The "generalized" performance events seem to really be a copy
|
||||
* of the available events on x86 processors; the mapping to ARC
|
||||
* events is not always possible 1-to-1. Fortunately, there doesn't
|
||||
* seem to be an exact definition for these events, so we can cheat
|
||||
* a bit where necessary.
|
||||
*
|
||||
* In particular, the following PERF events may behave a bit differently
|
||||
* compared to other architectures:
|
||||
*
|
||||
* PERF_COUNT_HW_CPU_CYCLES
|
||||
* Cycles not in halted state
|
||||
*
|
||||
* PERF_COUNT_HW_REF_CPU_CYCLES
|
||||
* Reference cycles not in halted state, same as PERF_COUNT_HW_CPU_CYCLES
|
||||
* for now as we don't do Dynamic Voltage/Frequency Scaling (yet)
|
||||
*
|
||||
* PERF_COUNT_HW_BUS_CYCLES
|
||||
* Unclear what this means, Intel uses 0x013c, which according to
|
||||
* their datasheet means "unhalted reference cycles". It sounds similar
|
||||
* to PERF_COUNT_HW_REF_CPU_CYCLES, and we use the same counter for it.
|
||||
*
|
||||
* PERF_COUNT_HW_STALLED_CYCLES_BACKEND
|
||||
* PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
|
||||
* The ARC 700 can either measure stalls per pipeline stage, or all stalls
|
||||
* combined; for now we assign all stalls to STALLED_CYCLES_BACKEND
|
||||
* and all pipeline flushes (e.g. caused by mispredicts, etc.) to
|
||||
* STALLED_CYCLES_FRONTEND.
|
||||
*
|
||||
* We could start multiple performance counters and combine everything
|
||||
* afterwards, but that makes it complicated.
|
||||
*
|
||||
* Note that I$ cache misses aren't counted by either of the two!
|
||||
*/
|
||||
|
||||
static const char * const arc_pmu_ev_hw_map[] = {
|
||||
[PERF_COUNT_HW_CPU_CYCLES] = "crun",
|
||||
[PERF_COUNT_HW_REF_CPU_CYCLES] = "crun",
|
||||
[PERF_COUNT_HW_BUS_CYCLES] = "crun",
|
||||
[PERF_COUNT_HW_INSTRUCTIONS] = "iall",
|
||||
[PERF_COUNT_HW_BRANCH_MISSES] = "bpfail",
|
||||
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmp",
|
||||
[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = "bflush",
|
||||
[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = "bstall",
|
||||
[PERF_COUNT_ARC_DCLM] = "dclm",
|
||||
[PERF_COUNT_ARC_DCSM] = "dcsm",
|
||||
[PERF_COUNT_ARC_ICM] = "icm",
|
||||
[PERF_COUNT_ARC_BPOK] = "bpok",
|
||||
[PERF_COUNT_ARC_EDTLB] = "edtlb",
|
||||
[PERF_COUNT_ARC_EITLB] = "eitlb",
|
||||
};
|
||||
|
||||
#define C(_x) PERF_COUNT_HW_CACHE_##_x
|
||||
#define CACHE_OP_UNSUPPORTED 0xffff
|
||||
|
||||
static const unsigned arc_pmu_cache_map[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
|
||||
[C(L1D)] = {
|
||||
[C(OP_READ)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = PERF_COUNT_ARC_DCLM,
|
||||
},
|
||||
[C(OP_WRITE)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = PERF_COUNT_ARC_DCSM,
|
||||
},
|
||||
[C(OP_PREFETCH)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
|
||||
},
|
||||
},
|
||||
[C(L1I)] = {
|
||||
[C(OP_READ)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = PERF_COUNT_ARC_ICM,
|
||||
},
|
||||
[C(OP_WRITE)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
|
||||
},
|
||||
[C(OP_PREFETCH)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
|
||||
},
|
||||
},
|
||||
[C(LL)] = {
|
||||
[C(OP_READ)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
|
||||
},
|
||||
[C(OP_WRITE)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
|
||||
},
|
||||
[C(OP_PREFETCH)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
|
||||
},
|
||||
},
|
||||
[C(DTLB)] = {
|
||||
[C(OP_READ)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = PERF_COUNT_ARC_EDTLB,
|
||||
},
|
||||
[C(OP_WRITE)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
|
||||
},
|
||||
[C(OP_PREFETCH)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
|
||||
},
|
||||
},
|
||||
[C(ITLB)] = {
|
||||
[C(OP_READ)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = PERF_COUNT_ARC_EITLB,
|
||||
},
|
||||
[C(OP_WRITE)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
|
||||
},
|
||||
[C(OP_PREFETCH)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
|
||||
},
|
||||
},
|
||||
[C(BPU)] = {
|
||||
[C(OP_READ)] = {
|
||||
[C(RESULT_ACCESS)] = PERF_COUNT_HW_BRANCH_INSTRUCTIONS,
|
||||
[C(RESULT_MISS)] = PERF_COUNT_HW_BRANCH_MISSES,
|
||||
},
|
||||
[C(OP_WRITE)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
|
||||
},
|
||||
[C(OP_PREFETCH)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
|
||||
},
|
||||
},
|
||||
[C(NODE)] = {
|
||||
[C(OP_READ)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
|
||||
},
|
||||
[C(OP_WRITE)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
|
||||
},
|
||||
[C(OP_PREFETCH)] = {
|
||||
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
|
||||
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
#endif /* __ASM_PERF_EVENT_H */
|
||||
|
|
|
@ -80,8 +80,6 @@ static inline __attribute_const__ struct thread_info *current_thread_info(void)
|
|||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#define PREEMPT_ACTIVE 0x10000000
|
||||
|
||||
/*
|
||||
* thread information flags
|
||||
* - these are process state flags that various assembly files may need to
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
/******** no-legacy-syscalls-ABI *******/
|
||||
|
||||
#ifndef _UAPI_ASM_ARC_UNISTD_H
|
||||
#define _UAPI_ASM_ARC_UNISTD_H
|
||||
|
||||
#define __ARCH_WANT_SYS_EXECVE
|
||||
#define __ARCH_WANT_SYS_CLONE
|
||||
#define __ARCH_WANT_SYS_VFORK
|
||||
|
@ -32,3 +35,5 @@ __SYSCALL(__NR_arc_gettls, sys_arc_gettls)
|
|||
/* Generic syscall (fs/filesystems.c - lost in asm-generic/unistd.h */
|
||||
#define __NR_sysfs (__NR_arch_specific_syscall + 3)
|
||||
__SYSCALL(__NR_sysfs, sys_sysfs)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,6 +19,7 @@ obj-$(CONFIG_KPROBES) += kprobes.o
|
|||
obj-$(CONFIG_ARC_MISALIGN_ACCESS) += unaligned.o
|
||||
obj-$(CONFIG_KGDB) += kgdb.o
|
||||
obj-$(CONFIG_ARC_METAWARE_HLINK) += arc_hostlink.o
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_event.o
|
||||
|
||||
obj-$(CONFIG_ARC_FPU_SAVE_RESTORE) += fpu.o
|
||||
CFLAGS_fpu.o += -mdpfp
|
||||
|
|
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
* Linux performance counter support for ARC700 series
|
||||
*
|
||||
* Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
|
||||
*
|
||||
* This code is inspired by the perf support of various other architectures.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <asm/arcregs.h>
|
||||
|
||||
struct arc_pmu {
|
||||
struct pmu pmu;
|
||||
int counter_size; /* in bits */
|
||||
int n_counters;
|
||||
unsigned long used_mask[BITS_TO_LONGS(ARC_PMU_MAX_HWEVENTS)];
|
||||
int ev_hw_idx[PERF_COUNT_ARC_HW_MAX];
|
||||
};
|
||||
|
||||
/* read counter #idx; note that counter# != event# on ARC! */
|
||||
static uint64_t arc_pmu_read_counter(int idx)
|
||||
{
|
||||
uint32_t tmp;
|
||||
uint64_t result;
|
||||
|
||||
/*
|
||||
* ARC supports making 'snapshots' of the counters, so we don't
|
||||
* need to care about counters wrapping to 0 underneath our feet
|
||||
*/
|
||||
write_aux_reg(ARC_REG_PCT_INDEX, idx);
|
||||
tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
|
||||
write_aux_reg(ARC_REG_PCT_CONTROL, tmp | ARC_REG_PCT_CONTROL_SN);
|
||||
result = (uint64_t) (read_aux_reg(ARC_REG_PCT_SNAPH)) << 32;
|
||||
result |= read_aux_reg(ARC_REG_PCT_SNAPL);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void arc_perf_event_update(struct perf_event *event,
|
||||
struct hw_perf_event *hwc, int idx)
|
||||
{
|
||||
struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu);
|
||||
uint64_t prev_raw_count, new_raw_count;
|
||||
int64_t delta;
|
||||
|
||||
do {
|
||||
prev_raw_count = local64_read(&hwc->prev_count);
|
||||
new_raw_count = arc_pmu_read_counter(idx);
|
||||
} while (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
|
||||
new_raw_count) != prev_raw_count);
|
||||
|
||||
delta = (new_raw_count - prev_raw_count) &
|
||||
((1ULL << arc_pmu->counter_size) - 1ULL);
|
||||
|
||||
local64_add(delta, &event->count);
|
||||
local64_sub(delta, &hwc->period_left);
|
||||
}
|
||||
|
||||
static void arc_pmu_read(struct perf_event *event)
|
||||
{
|
||||
arc_perf_event_update(event, &event->hw, event->hw.idx);
|
||||
}
|
||||
|
||||
static int arc_pmu_cache_event(u64 config)
|
||||
{
|
||||
unsigned int cache_type, cache_op, cache_result;
|
||||
int ret;
|
||||
|
||||
cache_type = (config >> 0) & 0xff;
|
||||
cache_op = (config >> 8) & 0xff;
|
||||
cache_result = (config >> 16) & 0xff;
|
||||
if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
|
||||
return -EINVAL;
|
||||
if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
|
||||
return -EINVAL;
|
||||
if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
ret = arc_pmu_cache_map[cache_type][cache_op][cache_result];
|
||||
|
||||
if (ret == CACHE_OP_UNSUPPORTED)
|
||||
return -ENOENT;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* initializes hw_perf_event structure if event is supported */
|
||||
static int arc_pmu_event_init(struct perf_event *event)
|
||||
{
|
||||
struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu);
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
int ret;
|
||||
|
||||
/* ARC 700 PMU does not support sampling events */
|
||||
if (is_sampling_event(event))
|
||||
return -ENOENT;
|
||||
|
||||
switch (event->attr.type) {
|
||||
case PERF_TYPE_HARDWARE:
|
||||
if (event->attr.config >= PERF_COUNT_HW_MAX)
|
||||
return -ENOENT;
|
||||
if (arc_pmu->ev_hw_idx[event->attr.config] < 0)
|
||||
return -ENOENT;
|
||||
hwc->config = arc_pmu->ev_hw_idx[event->attr.config];
|
||||
pr_debug("initializing event %d with cfg %d\n",
|
||||
(int) event->attr.config, (int) hwc->config);
|
||||
return 0;
|
||||
case PERF_TYPE_HW_CACHE:
|
||||
ret = arc_pmu_cache_event(event->attr.config);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
hwc->config = arc_pmu->ev_hw_idx[ret];
|
||||
return 0;
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
/* starts all counters */
|
||||
static void arc_pmu_enable(struct pmu *pmu)
|
||||
{
|
||||
uint32_t tmp;
|
||||
tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
|
||||
write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x1);
|
||||
}
|
||||
|
||||
/* stops all counters */
|
||||
static void arc_pmu_disable(struct pmu *pmu)
|
||||
{
|
||||
uint32_t tmp;
|
||||
tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
|
||||
write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Assigns hardware counter to hardware condition.
|
||||
* Note that there is no separate start/stop mechanism;
|
||||
* stopping is achieved by assigning the 'never' condition
|
||||
*/
|
||||
static void arc_pmu_start(struct perf_event *event, int flags)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
int idx = hwc->idx;
|
||||
|
||||
if (WARN_ON_ONCE(idx == -1))
|
||||
return;
|
||||
|
||||
if (flags & PERF_EF_RELOAD)
|
||||
WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
|
||||
|
||||
event->hw.state = 0;
|
||||
|
||||
/* enable ARC pmu here */
|
||||
write_aux_reg(ARC_REG_PCT_INDEX, idx);
|
||||
write_aux_reg(ARC_REG_PCT_CONFIG, hwc->config);
|
||||
}
|
||||
|
||||
static void arc_pmu_stop(struct perf_event *event, int flags)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
int idx = hwc->idx;
|
||||
|
||||
if (!(event->hw.state & PERF_HES_STOPPED)) {
|
||||
/* stop ARC pmu here */
|
||||
write_aux_reg(ARC_REG_PCT_INDEX, idx);
|
||||
|
||||
/* condition code #0 is always "never" */
|
||||
write_aux_reg(ARC_REG_PCT_CONFIG, 0);
|
||||
|
||||
event->hw.state |= PERF_HES_STOPPED;
|
||||
}
|
||||
|
||||
if ((flags & PERF_EF_UPDATE) &&
|
||||
!(event->hw.state & PERF_HES_UPTODATE)) {
|
||||
arc_perf_event_update(event, &event->hw, idx);
|
||||
event->hw.state |= PERF_HES_UPTODATE;
|
||||
}
|
||||
}
|
||||
|
||||
static void arc_pmu_del(struct perf_event *event, int flags)
|
||||
{
|
||||
struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu);
|
||||
|
||||
arc_pmu_stop(event, PERF_EF_UPDATE);
|
||||
__clear_bit(event->hw.idx, arc_pmu->used_mask);
|
||||
|
||||
perf_event_update_userpage(event);
|
||||
}
|
||||
|
||||
/* allocate hardware counter and optionally start counting */
|
||||
static int arc_pmu_add(struct perf_event *event, int flags)
|
||||
{
|
||||
struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu);
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
int idx = hwc->idx;
|
||||
|
||||
if (__test_and_set_bit(idx, arc_pmu->used_mask)) {
|
||||
idx = find_first_zero_bit(arc_pmu->used_mask,
|
||||
arc_pmu->n_counters);
|
||||
if (idx == arc_pmu->n_counters)
|
||||
return -EAGAIN;
|
||||
|
||||
__set_bit(idx, arc_pmu->used_mask);
|
||||
hwc->idx = idx;
|
||||
}
|
||||
|
||||
write_aux_reg(ARC_REG_PCT_INDEX, idx);
|
||||
write_aux_reg(ARC_REG_PCT_CONFIG, 0);
|
||||
write_aux_reg(ARC_REG_PCT_COUNTL, 0);
|
||||
write_aux_reg(ARC_REG_PCT_COUNTH, 0);
|
||||
local64_set(&hwc->prev_count, 0);
|
||||
|
||||
hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
|
||||
if (flags & PERF_EF_START)
|
||||
arc_pmu_start(event, PERF_EF_RELOAD);
|
||||
|
||||
perf_event_update_userpage(event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arc_pmu_device_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct arc_pmu *arc_pmu;
|
||||
struct arc_reg_pct_build pct_bcr;
|
||||
struct arc_reg_cc_build cc_bcr;
|
||||
int i, j, ret;
|
||||
|
||||
union cc_name {
|
||||
struct {
|
||||
uint32_t word0, word1;
|
||||
char sentinel;
|
||||
} indiv;
|
||||
char str[9];
|
||||
} cc_name;
|
||||
|
||||
|
||||
READ_BCR(ARC_REG_PCT_BUILD, pct_bcr);
|
||||
if (!pct_bcr.v) {
|
||||
pr_err("This core does not have performance counters!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu),
|
||||
GFP_KERNEL);
|
||||
if (!arc_pmu)
|
||||
return -ENOMEM;
|
||||
|
||||
arc_pmu->n_counters = pct_bcr.c;
|
||||
BUG_ON(arc_pmu->n_counters > ARC_PMU_MAX_HWEVENTS);
|
||||
|
||||
arc_pmu->counter_size = 32 + (pct_bcr.s << 4);
|
||||
pr_info("ARC PMU found with %d counters of size %d bits\n",
|
||||
arc_pmu->n_counters, arc_pmu->counter_size);
|
||||
|
||||
READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
|
||||
|
||||
if (!cc_bcr.v)
|
||||
pr_err("Strange! Performance counters exist, but no countable conditions?\n");
|
||||
|
||||
pr_info("ARC PMU has %d countable conditions\n", cc_bcr.c);
|
||||
|
||||
cc_name.str[8] = 0;
|
||||
for (i = 0; i < PERF_COUNT_HW_MAX; i++)
|
||||
arc_pmu->ev_hw_idx[i] = -1;
|
||||
|
||||
for (j = 0; j < cc_bcr.c; j++) {
|
||||
write_aux_reg(ARC_REG_CC_INDEX, j);
|
||||
cc_name.indiv.word0 = read_aux_reg(ARC_REG_CC_NAME0);
|
||||
cc_name.indiv.word1 = read_aux_reg(ARC_REG_CC_NAME1);
|
||||
for (i = 0; i < ARRAY_SIZE(arc_pmu_ev_hw_map); i++) {
|
||||
if (arc_pmu_ev_hw_map[i] &&
|
||||
!strcmp(arc_pmu_ev_hw_map[i], cc_name.str) &&
|
||||
strlen(arc_pmu_ev_hw_map[i])) {
|
||||
pr_debug("mapping %d to idx %d with name %s\n",
|
||||
i, j, cc_name.str);
|
||||
arc_pmu->ev_hw_idx[i] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
arc_pmu->pmu = (struct pmu) {
|
||||
.pmu_enable = arc_pmu_enable,
|
||||
.pmu_disable = arc_pmu_disable,
|
||||
.event_init = arc_pmu_event_init,
|
||||
.add = arc_pmu_add,
|
||||
.del = arc_pmu_del,
|
||||
.start = arc_pmu_start,
|
||||
.stop = arc_pmu_stop,
|
||||
.read = arc_pmu_read,
|
||||
};
|
||||
|
||||
ret = perf_pmu_register(&arc_pmu->pmu, pdev->name, PERF_TYPE_RAW);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id arc_pmu_match[] = {
|
||||
{ .compatible = "snps,arc700-pmu" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, arc_pmu_match);
|
||||
#endif
|
||||
|
||||
static struct platform_driver arc_pmu_driver = {
|
||||
.driver = {
|
||||
.name = "arc700-pmu",
|
||||
.of_match_table = of_match_ptr(arc_pmu_match),
|
||||
},
|
||||
.probe = arc_pmu_device_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(arc_pmu_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mischa Jonker <mjonker@synopsys.com>");
|
||||
MODULE_DESCRIPTION("ARC PMU driver");
|
|
@ -20,8 +20,10 @@ menuconfig ARC_PLAT_TB10X
|
|||
bool "Abilis TB10x"
|
||||
select COMMON_CLK
|
||||
select PINCTRL
|
||||
select PINCTRL_TB10X
|
||||
select PINMUX
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select GPIO_TB10X
|
||||
select TB10X_IRQC
|
||||
help
|
||||
Support for platforms based on the TB10x home media gateway SOC by
|
||||
|
|
|
@ -25,7 +25,7 @@ config ARM
|
|||
select HARDIRQS_SW_RESEND
|
||||
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
|
||||
select HAVE_ARCH_KGDB
|
||||
select HAVE_ARCH_SECCOMP_FILTER
|
||||
select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT)
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_BPF_JIT
|
||||
select HAVE_CONTEXT_TRACKING
|
||||
|
@ -1496,6 +1496,7 @@ config HAVE_ARM_ARCH_TIMER
|
|||
bool "Architected timer support"
|
||||
depends on CPU_V7
|
||||
select ARM_ARCH_TIMER
|
||||
select GENERIC_CLOCKEVENTS
|
||||
help
|
||||
This option enables support for the ARM architected timer
|
||||
|
||||
|
@ -1719,7 +1720,6 @@ config AEABI
|
|||
config OABI_COMPAT
|
||||
bool "Allow old ABI binaries to run with this kernel (EXPERIMENTAL)"
|
||||
depends on AEABI && !THUMB2_KERNEL
|
||||
default y
|
||||
help
|
||||
This option preserves the old syscall interface along with the
|
||||
new (ARM EABI) one. It also provides a compatibility layer to
|
||||
|
@ -1727,11 +1727,16 @@ config OABI_COMPAT
|
|||
in memory differs between the legacy ABI and the new ARM EABI
|
||||
(only for non "thumb" binaries). This option adds a tiny
|
||||
overhead to all syscalls and produces a slightly larger kernel.
|
||||
|
||||
The seccomp filter system will not be available when this is
|
||||
selected, since there is no way yet to sensibly distinguish
|
||||
between calling conventions during filtering.
|
||||
|
||||
If you know you'll be using only pure EABI user space then you
|
||||
can say N here. If this option is not selected and you attempt
|
||||
to execute a legacy ABI binary then the result will be
|
||||
UNPREDICTABLE (in fact it can be predicted that it won't work
|
||||
at all). If in doubt say Y.
|
||||
at all). If in doubt say N.
|
||||
|
||||
config ARCH_HAS_HOLES_MEMORYMODEL
|
||||
bool
|
||||
|
|
|
@ -13,4 +13,83 @@
|
|||
/ {
|
||||
model = "IGEP COM AM335x on AQUILA Expansion";
|
||||
compatible = "isee,am335x-base0033", "isee,am335x-igep0033", "ti,am33xx";
|
||||
|
||||
hdmi {
|
||||
compatible = "ti,tilcdc,slave";
|
||||
i2c = <&i2c0>;
|
||||
pinctrl-names = "default", "off";
|
||||
pinctrl-0 = <&nxp_hdmi_pins>;
|
||||
pinctrl-1 = <&nxp_hdmi_off_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
leds_base {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&leds_base_pins>;
|
||||
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led@0 {
|
||||
label = "base:red:user";
|
||||
gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; /* gpio1_21 */
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
led@1 {
|
||||
label = "base:green:user";
|
||||
gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>; /* gpio2_0 */
|
||||
default-state = "off";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&am33xx_pinmux {
|
||||
nxp_hdmi_pins: pinmux_nxp_hdmi_pins {
|
||||
pinctrl-single,pins = <
|
||||
0x1b0 (PIN_OUTPUT | MUX_MODE3) /* xdma_event_intr0.clkout1 */
|
||||
0xa0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data0 */
|
||||
0xa4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data1 */
|
||||
0xa8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data2 */
|
||||
0xac (PIN_OUTPUT | MUX_MODE0) /* lcd_data3 */
|
||||
0xb0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data4 */
|
||||
0xb4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data5 */
|
||||
0xb8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data6 */
|
||||
0xbc (PIN_OUTPUT | MUX_MODE0) /* lcd_data7 */
|
||||
0xc0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data8 */
|
||||
0xc4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data9 */
|
||||
0xc8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data10 */
|
||||
0xcc (PIN_OUTPUT | MUX_MODE0) /* lcd_data11 */
|
||||
0xd0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data12 */
|
||||
0xd4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data13 */
|
||||
0xd8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data14 */
|
||||
0xdc (PIN_OUTPUT | MUX_MODE0) /* lcd_data15 */
|
||||
0xe0 (PIN_OUTPUT | MUX_MODE0) /* lcd_vsync */
|
||||
0xe4 (PIN_OUTPUT | MUX_MODE0) /* lcd_hsync */
|
||||
0xe8 (PIN_OUTPUT | MUX_MODE0) /* lcd_pclk */
|
||||
0xec (PIN_OUTPUT | MUX_MODE0) /* lcd_ac_bias_en */
|
||||
>;
|
||||
};
|
||||
nxp_hdmi_off_pins: pinmux_nxp_hdmi_off_pins {
|
||||
pinctrl-single,pins = <
|
||||
0x1b0 (PIN_OUTPUT | MUX_MODE3) /* xdma_event_intr0.clkout1 */
|
||||
>;
|
||||
};
|
||||
|
||||
leds_base_pins: pinmux_leds_base_pins {
|
||||
pinctrl-single,pins = <
|
||||
0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */
|
||||
0x88 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_csn3.gpio2_0 */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
&lcdc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
eeprom: eeprom@50 {
|
||||
compatible = "at,24c256";
|
||||
reg = <0x50>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -199,6 +199,35 @@
|
|||
pinctrl-0 = <&uart0_pins>;
|
||||
};
|
||||
|
||||
&usb {
|
||||
status = "okay";
|
||||
|
||||
control@44e10000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb-phy@47401300 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb-phy@47401b00 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb@47401000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb@47401800 {
|
||||
status = "okay";
|
||||
dr_mode = "host";
|
||||
};
|
||||
|
||||
dma-controller@07402000 {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
#include "tps65910.dtsi"
|
||||
|
||||
&tps {
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
*/
|
||||
/dts-v1/;
|
||||
|
||||
#include "omap34xx.dtsi"
|
||||
#include "am3517.dtsi"
|
||||
|
||||
/ {
|
||||
model = "TI AM3517 EVM (AM3517/05)";
|
||||
compatible = "ti,am3517-evm", "ti,omap3";
|
||||
model = "TI AM3517 EVM (AM3517/05 TMDSEVM3517)";
|
||||
compatible = "ti,am3517-evm", "ti,am3517", "ti,omap3";
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Device Tree Source for am3517 SoC
|
||||
*
|
||||
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
* kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include "omap3.dtsi"
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
serial3 = &uart4;
|
||||
};
|
||||
|
||||
ocp {
|
||||
am35x_otg_hs: am35x_otg_hs@5c040000 {
|
||||
compatible = "ti,omap3-musb";
|
||||
ti,hwmods = "am35x_otg_hs";
|
||||
status = "disabled";
|
||||
reg = <0x5c040000 0x1000>;
|
||||
interrupts = <71>;
|
||||
interrupt-names = "mc";
|
||||
};
|
||||
|
||||
davinci_emac: ethernet@0x5c000000 {
|
||||
compatible = "ti,am3517-emac";
|
||||
ti,hwmods = "davinci_emac";
|
||||
status = "disabled";
|
||||
reg = <0x5c000000 0x30000>;
|
||||
interrupts = <67 68 69 70>;
|
||||
ti,davinci-ctrl-reg-offset = <0x10000>;
|
||||
ti,davinci-ctrl-mod-reg-offset = <0>;
|
||||
ti,davinci-ctrl-ram-offset = <0x20000>;
|
||||
ti,davinci-ctrl-ram-size = <0x2000>;
|
||||
ti,davinci-rmii-en = /bits/ 8 <1>;
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
};
|
||||
|
||||
davinci_mdio: ethernet@0x5c030000 {
|
||||
compatible = "ti,davinci_mdio";
|
||||
ti,hwmods = "davinci_mdio";
|
||||
status = "disabled";
|
||||
reg = <0x5c030000 0x1000>;
|
||||
bus_freq = <1000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
uart4: serial@4809e000 {
|
||||
compatible = "ti,omap3-uart";
|
||||
ti,hwmods = "uart4";
|
||||
status = "disabled";
|
||||
reg = <0x4809e000 0x400>;
|
||||
interrupts = <84>;
|
||||
dmas = <&sdma 55 &sdma 54>;
|
||||
dma-names = "tx", "rx";
|
||||
clock-frequency = <48000000>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -99,22 +99,22 @@
|
|||
spi-max-frequency = <50000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pcie-controller {
|
||||
pcie-controller {
|
||||
status = "okay";
|
||||
/*
|
||||
* The two PCIe units are accessible through
|
||||
* both standard PCIe slots and mini-PCIe
|
||||
* slots on the board.
|
||||
*/
|
||||
pcie@1,0 {
|
||||
/* Port 0, Lane 0 */
|
||||
status = "okay";
|
||||
};
|
||||
pcie@2,0 {
|
||||
/* Port 1, Lane 0 */
|
||||
status = "okay";
|
||||
/*
|
||||
* The two PCIe units are accessible through
|
||||
* both standard PCIe slots and mini-PCIe
|
||||
* slots on the board.
|
||||
*/
|
||||
pcie@1,0 {
|
||||
/* Port 0, Lane 0 */
|
||||
status = "okay";
|
||||
};
|
||||
pcie@2,0 {
|
||||
/* Port 1, Lane 0 */
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -118,7 +118,7 @@
|
|||
|
||||
coherency-fabric@20200 {
|
||||
compatible = "marvell,coherency-fabric";
|
||||
reg = <0x20200 0xb0>, <0x21810 0x1c>;
|
||||
reg = <0x20200 0xb0>, <0x21010 0x1c>;
|
||||
};
|
||||
|
||||
serial@12000 {
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
/*
|
||||
* MV78230 has 2 PCIe units Gen2.0: One unit can be
|
||||
* configured as x4 or quad x1 lanes. One unit is
|
||||
* x4/x1.
|
||||
* x1 only.
|
||||
*/
|
||||
pcie-controller {
|
||||
compatible = "marvell,armada-xp-pcie";
|
||||
|
@ -62,10 +62,10 @@
|
|||
|
||||
ranges =
|
||||
<0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000 /* Port 0.0 registers */
|
||||
0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000 /* Port 2.0 registers */
|
||||
0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000 /* Port 0.1 registers */
|
||||
0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000 /* Port 0.2 registers */
|
||||
0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000 /* Port 0.3 registers */
|
||||
0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000 /* Port 1.0 registers */
|
||||
0x82000000 0x1 0 MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
|
||||
0x81000000 0x1 0 MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO */
|
||||
0x82000000 0x2 0 MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
|
||||
|
@ -74,8 +74,8 @@
|
|||
0x81000000 0x3 0 MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO */
|
||||
0x82000000 0x4 0 MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
|
||||
0x81000000 0x4 0 MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO */
|
||||
0x82000000 0x9 0 MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
|
||||
0x81000000 0x9 0 MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO */>;
|
||||
0x82000000 0x5 0 MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
|
||||
0x81000000 0x5 0 MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO */>;
|
||||
|
||||
pcie@1,0 {
|
||||
device_type = "pci";
|
||||
|
@ -145,20 +145,20 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
pcie@9,0 {
|
||||
pcie@5,0 {
|
||||
device_type = "pci";
|
||||
assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
|
||||
reg = <0x4800 0 0 0 0>;
|
||||
assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
|
||||
reg = <0x2800 0 0 0 0>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
|
||||
0x81000000 0 0 0x81000000 0x9 0 1 0>;
|
||||
ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
|
||||
0x81000000 0 0 0x81000000 0x5 0 1 0>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &mpic 99>;
|
||||
marvell,pcie-port = <2>;
|
||||
interrupt-map = <0 0 0 0 &mpic 62>;
|
||||
marvell,pcie-port = <1>;
|
||||
marvell,pcie-lane = <0>;
|
||||
clocks = <&gateclk 26>;
|
||||
clocks = <&gateclk 9>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
/*
|
||||
* MV78260 has 3 PCIe units Gen2.0: Two units can be
|
||||
* configured as x4 or quad x1 lanes. One unit is
|
||||
* x4/x1.
|
||||
* x4 only.
|
||||
*/
|
||||
pcie-controller {
|
||||
compatible = "marvell,armada-xp-pcie";
|
||||
|
@ -68,7 +68,9 @@
|
|||
0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000 /* Port 0.2 registers */
|
||||
0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000 /* Port 0.3 registers */
|
||||
0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000 /* Port 1.0 registers */
|
||||
0x82000000 0 0x82000 MBUS_ID(0xf0, 0x01) 0x82000 0 0x00002000 /* Port 3.0 registers */
|
||||
0x82000000 0 0x84000 MBUS_ID(0xf0, 0x01) 0x84000 0 0x00002000 /* Port 1.1 registers */
|
||||
0x82000000 0 0x88000 MBUS_ID(0xf0, 0x01) 0x88000 0 0x00002000 /* Port 1.2 registers */
|
||||
0x82000000 0 0x8c000 MBUS_ID(0xf0, 0x01) 0x8c000 0 0x00002000 /* Port 1.3 registers */
|
||||
0x82000000 0x1 0 MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
|
||||
0x81000000 0x1 0 MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO */
|
||||
0x82000000 0x2 0 MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
|
||||
|
@ -77,10 +79,18 @@
|
|||
0x81000000 0x3 0 MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO */
|
||||
0x82000000 0x4 0 MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
|
||||
0x81000000 0x4 0 MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO */
|
||||
0x82000000 0x9 0 MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
|
||||
0x81000000 0x9 0 MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO */
|
||||
0x82000000 0xa 0 MBUS_ID(0x08, 0xf8) 0 1 0 /* Port 3.0 MEM */
|
||||
0x81000000 0xa 0 MBUS_ID(0x08, 0xf0) 0 1 0 /* Port 3.0 IO */>;
|
||||
|
||||
0x82000000 0x5 0 MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
|
||||
0x81000000 0x5 0 MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO */
|
||||
0x82000000 0x6 0 MBUS_ID(0x08, 0xd8) 0 1 0 /* Port 1.1 MEM */
|
||||
0x81000000 0x6 0 MBUS_ID(0x08, 0xd0) 0 1 0 /* Port 1.1 IO */
|
||||
0x82000000 0x7 0 MBUS_ID(0x08, 0xb8) 0 1 0 /* Port 1.2 MEM */
|
||||
0x81000000 0x7 0 MBUS_ID(0x08, 0xb0) 0 1 0 /* Port 1.2 IO */
|
||||
0x82000000 0x8 0 MBUS_ID(0x08, 0x78) 0 1 0 /* Port 1.3 MEM */
|
||||
0x81000000 0x8 0 MBUS_ID(0x08, 0x70) 0 1 0 /* Port 1.3 IO */
|
||||
|
||||
0x82000000 0x9 0 MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
|
||||
0x81000000 0x9 0 MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO */>;
|
||||
|
||||
pcie@1,0 {
|
||||
device_type = "pci";
|
||||
|
@ -106,8 +116,8 @@
|
|||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
|
||||
0x81000000 0 0 0x81000000 0x2 0 1 0>;
|
||||
ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
|
||||
0x81000000 0 0 0x81000000 0x2 0 1 0>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &mpic 59>;
|
||||
marvell,pcie-port = <0>;
|
||||
|
@ -150,6 +160,74 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
pcie@5,0 {
|
||||
device_type = "pci";
|
||||
assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
|
||||
reg = <0x2800 0 0 0 0>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
|
||||
0x81000000 0 0 0x81000000 0x5 0 1 0>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &mpic 62>;
|
||||
marvell,pcie-port = <1>;
|
||||
marvell,pcie-lane = <0>;
|
||||
clocks = <&gateclk 9>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcie@6,0 {
|
||||
device_type = "pci";
|
||||
assigned-addresses = <0x82000800 0 0x84000 0 0x2000>;
|
||||
reg = <0x3000 0 0 0 0>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
ranges = <0x82000000 0 0 0x82000000 0x6 0 1 0
|
||||
0x81000000 0 0 0x81000000 0x6 0 1 0>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &mpic 63>;
|
||||
marvell,pcie-port = <1>;
|
||||
marvell,pcie-lane = <1>;
|
||||
clocks = <&gateclk 10>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcie@7,0 {
|
||||
device_type = "pci";
|
||||
assigned-addresses = <0x82000800 0 0x88000 0 0x2000>;
|
||||
reg = <0x3800 0 0 0 0>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
ranges = <0x82000000 0 0 0x82000000 0x7 0 1 0
|
||||
0x81000000 0 0 0x81000000 0x7 0 1 0>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &mpic 64>;
|
||||
marvell,pcie-port = <1>;
|
||||
marvell,pcie-lane = <2>;
|
||||
clocks = <&gateclk 11>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcie@8,0 {
|
||||
device_type = "pci";
|
||||
assigned-addresses = <0x82000800 0 0x8c000 0 0x2000>;
|
||||
reg = <0x4000 0 0 0 0>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
ranges = <0x82000000 0 0 0x82000000 0x8 0 1 0
|
||||
0x81000000 0 0 0x81000000 0x8 0 1 0>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &mpic 65>;
|
||||
marvell,pcie-port = <1>;
|
||||
marvell,pcie-lane = <3>;
|
||||
clocks = <&gateclk 12>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcie@9,0 {
|
||||
device_type = "pci";
|
||||
assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
|
||||
|
@ -166,23 +244,6 @@
|
|||
clocks = <&gateclk 26>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcie@10,0 {
|
||||
device_type = "pci";
|
||||
assigned-addresses = <0x82000800 0 0x82000 0 0x2000>;
|
||||
reg = <0x5000 0 0 0 0>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
ranges = <0x82000000 0 0 0x82000000 0xa 0 1 0
|
||||
0x81000000 0 0 0x81000000 0xa 0 1 0>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &mpic 103>;
|
||||
marvell,pcie-port = <3>;
|
||||
marvell,pcie-lane = <0>;
|
||||
clocks = <&gateclk 27>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
internal-regs {
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
serial4 = &usart3;
|
||||
};
|
||||
|
||||
ahb {
|
||||
apb {
|
||||
pinctrl@fffff400 {
|
||||
|
|
|
@ -85,6 +85,8 @@
|
|||
reg = <0x7e205000 0x1000>;
|
||||
interrupts = <2 21>;
|
||||
clocks = <&clk_i2c>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -93,6 +95,8 @@
|
|||
reg = <0x7e804000 0x1000>;
|
||||
interrupts = <2 21>;
|
||||
clocks = <&clk_i2c>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
|
|
@ -27,6 +27,13 @@
|
|||
i2c2_bus: i2c2-bus {
|
||||
samsung,pin-pud = <0>;
|
||||
};
|
||||
|
||||
max77686_irq: max77686-irq {
|
||||
samsung,pins = "gpx3-2";
|
||||
samsung,pin-function = <0>;
|
||||
samsung,pin-pud = <0>;
|
||||
samsung,pin-drv = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c@12C60000 {
|
||||
|
@ -35,6 +42,11 @@
|
|||
|
||||
max77686@09 {
|
||||
compatible = "maxim,max77686";
|
||||
interrupt-parent = <&gpx3>;
|
||||
interrupts = <2 0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&max77686_irq>;
|
||||
wakeup-source;
|
||||
reg = <0x09>;
|
||||
|
||||
voltage-regulators {
|
||||
|
|
|
@ -161,7 +161,7 @@
|
|||
clocks = <&clks 197>, <&clks 3>,
|
||||
<&clks 197>, <&clks 107>,
|
||||
<&clks 0>, <&clks 118>,
|
||||
<&clks 62>, <&clks 139>,
|
||||
<&clks 0>, <&clks 139>,
|
||||
<&clks 0>;
|
||||
clock-names = "core", "rxtx0",
|
||||
"rxtx1", "rxtx2",
|
||||
|
|
|
@ -44,8 +44,8 @@
|
|||
gpmc,wr-access-ns = <186>;
|
||||
gpmc,cycle2cycle-samecsen;
|
||||
gpmc,cycle2cycle-diffcsen;
|
||||
vmmc-supply = <&vddvario>;
|
||||
vmmc_aux-supply = <&vdd33a>;
|
||||
vddvario-supply = <&vddvario>;
|
||||
vdd33a-supply = <&vdd33a>;
|
||||
reg-io-width = <4>;
|
||||
smsc,save-mac-address;
|
||||
};
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* they probably share the same GPIO IRQ
|
||||
* REVISIT: Add timing support from slls644g.pdf
|
||||
*/
|
||||
8250@3,0 {
|
||||
uart@3,0 {
|
||||
compatible = "ns16550a";
|
||||
reg = <3 0 0x100>;
|
||||
bank-width = <2>;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue