+++ /dev/null
-From 6a6b05153678be7f443dc66be6fac842135aac00 Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Wed, 20 Jun 2012 12:07:49 +0200
-Subject: [PATCH 01/15] net: bus: add the AF_BUS socket address family
-
-AF_BUS is a new socket address family that allows both unicast and
-multicast I on a local machine with total ordering for messages
-(every process on the same bus sees each message in the same order).
-
-A process can create buses to which other processes can connect and
-communicate with each other by sending messages. Processes' addresses are
-automatically assigned by the bus on connect and are unique. Messages can
-be sent either to process' unique address or to a bus multicast address.
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
----
- include/linux/socket.h | 5 ++++-
- net/core/sock.c | 6 +++---
- 2 files changed, 7 insertions(+), 4 deletions(-)
-
-diff --git a/include/linux/socket.h b/include/linux/socket.h
-index b84bbd4..59596d2 100644
---- a/include/linux/socket.h
-+++ b/include/linux/socket.h
-@@ -195,7 +195,8 @@ struct ucred {
- #define AF_CAIF 37 /* CAIF sockets */
- #define AF_ALG 38 /* Algorithm sockets */
- #define AF_NFC 39 /* NFC sockets */
--#define AF_MAX 40 /* For now.. */
-+#define AF_BUS 40 /* BUS sockets */
-+#define AF_MAX 41 /* For now.. */
-
- /* Protocol families, same as address families. */
- #define PF_UNSPEC AF_UNSPEC
-@@ -238,6 +239,7 @@ struct ucred {
- #define PF_CAIF AF_CAIF
- #define PF_ALG AF_ALG
- #define PF_NFC AF_NFC
-+#define PF_BUS AF_BUS
- #define PF_MAX AF_MAX
-
- /* Maximum queue length specifiable by listen. */
-@@ -312,6 +314,7 @@ struct ucred {
- #define SOL_IUCV 277
- #define SOL_CAIF 278
- #define SOL_ALG 279
-+#define SOL_BUS 280
-
- /* IPX options */
- #define IPX_TYPE 1
-diff --git a/net/core/sock.c b/net/core/sock.c
-index 4b469e3..7d6d3f6 100644
---- a/net/core/sock.c
-+++ b/net/core/sock.c
-@@ -205,7 +205,7 @@ static const char *const af_family_key_strings[AF_MAX+1] = {
- "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" ,
- "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" ,
- "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG" ,
-- "sk_lock-AF_NFC" , "sk_lock-AF_MAX"
-+ "sk_lock-AF_NFC" , "sk_lock-AF_BUS" , "sk_lock-AF_MAX"
- };
- static const char *const af_family_slock_key_strings[AF_MAX+1] = {
- "slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" ,
-@@ -221,7 +221,7 @@ static const char *const af_family_slock_key_strings[AF_MAX+1] = {
- "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" ,
- "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" ,
- "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG" ,
-- "slock-AF_NFC" , "slock-AF_MAX"
-+ "slock-AF_NFC" , "slock-AF_BUS" , "slock-AF_MAX"
- };
- static const char *const af_family_clock_key_strings[AF_MAX+1] = {
- "clock-AF_UNSPEC", "clock-AF_UNIX" , "clock-AF_INET" ,
-@@ -237,7 +237,7 @@ static const char *const af_family_clock_key_strings[AF_MAX+1] = {
- "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" ,
- "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" ,
- "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG" ,
-- "clock-AF_NFC" , "clock-AF_MAX"
-+ "clock-AF_NFC" , "clock-AF_BUS" , "clock-AF_MAX"
- };
-
- /*
---
-1.7.7.6
-
+++ /dev/null
-From 9943977a50f55ee53cde6f9c4fa4f1bb25761d71 Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Tue, 26 Jun 2012 14:32:43 +0200
-Subject: [PATCH 02/15] net: bus: Add AF_BUS documentation
-
-AF_BUS is different to other POSIX BSD sockets address families so a
-is good to have a documentation about its design, ABI and semantics.
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
----
- Documentation/networking/af_bus.txt | 558 +++++++++++++++++++++++++++++++++++
- 1 files changed, 558 insertions(+), 0 deletions(-)
- create mode 100644 Documentation/networking/af_bus.txt
-
-diff --git a/Documentation/networking/af_bus.txt b/Documentation/networking/af_bus.txt
-new file mode 100644
-index 0000000..cfef22f
---- /dev/null
-+++ b/Documentation/networking/af_bus.txt
-@@ -0,0 +1,558 @@
-+ The AF_BUS socket address family
-+ ================================
-+
-+Introduction
-+------------
-+
-+AF_BUS is a message oriented inter process communication system.
-+
-+The principle features are:
-+
-+ - Reliable datagram based communication (all sockets are of type
-+ SOCK_SEQPACKET)
-+
-+ - Multicast message delivery (one to many, unicast as a subset)
-+
-+ - Strict ordering (messages are delivered to every client in the same order)
-+
-+ - Ability to pass file descriptors
-+
-+ - Ability to pass credentials
-+
-+The basic concept is to provide a virtual bus on which multiple
-+processes can communicate and policy is imposed by a "bus master".
-+
-+A process can create buses to which other processes can connect and
-+communicate with each other by sending messages. Processes' addresses
-+are automatically assigned by the bus on connect and are
-+unique. Messages can be sent either to a process' unique address or to
-+a bus multicast addresses.
-+
-+Netfilter rules or Berkeley Packet Filter can be used to restrict the
-+messages that each peer is allowed to receive. This is especially
-+important when sending to multicast addresses.
-+
-+Besides messages, process can send and receive ancillary data (i.e.,
-+SCM_RIGHTS for passing file descriptors or SCM_CREDENTIALS for passing
-+Unix credentials). In the case of a multicast message all recipients
-+of a message may obtain a copy a file descriptor or credentials.
-+
-+A bus is created by processes connecting on an AF_BUS socket. The
-+"bus master" binds itself instead of connecting to the NULL address.
-+
-+The socket address is made up of a path component and a numeric
-+component. The path component is either a pathname or an abstract
-+socket similar to a unix socket. The numeric component is used to
-+uniquely identify each connection to the bus. Thus the path identifies
-+a specific bus and the numeric component the attachment to that bus.
-+
-+The process that calls bind(2) on the socket is the owner of the bus
-+and is called the bus master. The master is a special client of the
-+bus and has some responsibility for the bus' operation. The master is
-+assigned a fixed address with all the bits zero (0x0000000000000000).
-+
-+Each process connected to an AF_BUS socket has one or more addresses
-+within that bus. These addresses are 64-bit unsigned integers,
-+interpreted by splitting the address into two parts: the most
-+significant 16 bits are a prefix identifying the type of address, and
-+the remaining 48 bits are the actual client address within that
-+prefix, as shown in this figure:
-+
-+Bit: 0 15 16 63
-+ +----------------+------------------------------------------------+
-+ | Type prefix | Client address |
-+ +----------------+------------------------------------------------+
-+
-+The prefix with all bits zero is reserved for use by the kernel, which
-+automatically assigns one address from this prefix to each client on
-+connection. The address in this prefix with all bits zero is always
-+assigned to the bus master. Addresses on the prefix 0x0000 are unique
-+and will never repeat for the lifetime of the bus master.
-+
-+A client may have multiple addresses. When data is sent to other
-+clients, those clients will always see the sender address that is in
-+the prefix 0x0000 address space when calling recvmsg(2) or
-+recvfrom(2). Similarly, the prefix 0x0000 address is returned by calls
-+to getsockname(2) and getpeername(2).
-+
-+For each prefix, the address where the least significant 48 bits are
-+all 1 (i.e., 0xffffffffffff) is also reserved, and can be used to send
-+multicast messages to all the peers on a prefix.
-+
-+The non-reserved addresses in each of the remaining prefixes are
-+managed by the bus master, which may assign additional addresses to
-+any other connected socket.
-+
-+Having different name-spaces has two advantages:
-+
-+ - Clients can have addresses on different mutually-exclusive
-+ scopes. This permits sending multicast packets to only clients
-+ that have addresses on a given prefix.
-+
-+ - The addressing scheme can be more flexible. The kernel will only
-+ assign unique addresses on the all-bits-zero prefix (0x0000) and
-+ allows the bus master process to assign additional addresses to
-+ clients on other prefixes. By having different prefixes, the
-+ kernel and bus master assignments will not collide.
-+
-+AF_BUS transport can support two network topologies. When a process
-+first connects to the bus master, it can only communicate with the bus
-+master. The process can't send and receive packets from other peers on
-+the bus. So, from the client process point of view the network
-+topology is point-to-point.
-+
-+The bus master can allow the connected peer to be part of the bus and
-+start to communicate with other peers by setting a socket option with
-+the setsockopt(2) system call using the accepted socket descriptor. At
-+this point, the topology becomes a bus to the client process.
-+
-+Packets whose destination address is not assigned to any client are
-+routed by default to the bus master (the client accepted socket
-+descriptor).
-+
-+
-+Semantics
-+---------
-+
-+Bus features:
-+
-+ - Unicast and multicast addressing scheme.
-+ - Ability to assign addresses from user-space with different prefixes.
-+ - Automatic address assignment.
-+ - Ordered packets delivery (FIFO, total ordering).
-+ - File descriptor and credentials passing.
-+ - Support for both point-to-point and bus network topologies.
-+ - Bus control access managed from user-space.
-+ - Netfilter hooks for packet sending, routing and receiving.
-+
-+A process (the "bus master") can create an AF_BUS bus with socket(2)
-+and use bind(2) to assign an address to the bus. Then it can listen(2)
-+on the created socket to start accepting incoming connections with
-+accept(2).
-+
-+Processes can connect to the bus by creating a socket with socket(2)
-+and using connect(2). The kernel will assign a unique address to each
-+connection and messages can be sent and received by using BSD socket
-+primitives.
-+
-+This uses the connect(2) semantic in a non-traditional way, with
-+AF_BUS sockets, it's not possible to connect "my" socket to a specific
-+peer socket whereas the traditional BSD sockets API usage, connect(2)
-+either connects to stream sockets, or assigns a peer address to a
-+datagram socket (so that send(2) can be used instead of sendto()).
-+
-+An AF_BUS socket address is represented as a combination of a bus
-+address and a bus path name. Address are unique within a path. The
-+unique bus address is further subdivided into a prefix and a client
-+address. Thus the path identifies a specific bus and the numeric
-+component the attachment to that bus.
-+
-+#define BUS_PATH_MAX 108
-+
-+/* Bus address */
-+struct bus_addr {
-+ uint64_t s_addr; /* 16-bit prefix + 48-bit client address */
-+};
-+
-+/* Structure describing an AF_BUS socket address. */
-+struct sockaddr_bus {
-+ sa_family_t sbus_family; /* AF_BUS */
-+ struct bus_addr sbus_addr; /* bus address */
-+ char sbus_path[BUS_PATH_MAX]; /* pathname */
-+};
-+
-+A process becomes a bus master for a given struct sockaddr_bus by
-+calling bind(2) on an AF_BUS addresses. The argument must be { AF_BUS,
-+0, path }.
-+
-+AF_BUS supports both abstract and non-abstract path names. Abstract
-+names are distinguished by the fact that sbus_path[0] == '\0' and they
-+don't represent file system paths while non-abstract paths are bound
-+to a file system path name. (See the unix(7) man page for a discussion
-+of abstract socket addresses in the AF_UNIX address family.)
-+
-+Then the process calls listen(2) to accept incoming connections. If
-+that process calls getsockname(2), the returned address will be {
-+AF_BUS, 0, path }.
-+
-+The conventional string form of the full address is path + ":" +
-+prefix + "/" + client address. Prefix and client address are
-+represented in hex.
-+
-+For example the address:
-+
-+struct sockaddr_bus addr;
-+addr.sbus_family = AF_BUS;
-+strcpy(addr.sbus_path, "/tmp/test");
-+addr.sbus_addr.s_addr = 0x0002f00ddeadbeef;
-+
-+would be represented using the string /tmp/test:0002/f00ddeadbeef.
-+
-+If the bus_addr is 0, then both the prefix and client address may be
-+omitted from the string form. To connect to a bus as a client it is
-+sufficient to specify the path, since the listening address always has
-+bus_addr == 0. it is not meanigful to specify 'bus_addr' as other than
-+0 on connect()
-+
-+The AF_BUS implementation will automatically assign a unique address
-+to each client but the bus master can assign additional addresses on a
-+different prefix by means of the setsockopt(2) system call. For
-+example:
-+
-+struct bus_addr addr;
-+addr.s_addr = 0x0001deadfee1dead;
-+ret = setsockopt(afd, SOL_BUS, BUS_ADD_ADDR, &addr, sizeof(addr));
-+
-+where afd is the accepted socket descriptor in the daemon. To show graphically:
-+
-+ L The AF_BUS listening socket }
-+ / | \ }-- listener process
-+ A1 A2 A3 The AF_BUS accepted sockets }
-+ | | |
-+ C1 C2 C3 The AF_BUS connected sockets }-- client processes
-+
-+So if setsockopt(A1, SOL_BUS, BUS_ADD_ADDR, &addr, sizeof(addr)) is
-+called, C1 will get the new address.
-+
-+The inverse operation is BUS_DEL_ADDR, which the bus master can use to
-+remove a client socket AF_BUS address:
-+
-+ret = setsockopt(afd, SOL_BUS, BUS_DEL_ADDR, &addr, sizeof(addr));
-+
-+Besides assigning additional addresses, the bus master has to allow a
-+client process to communicate with other peers on the bus using a
-+setsockopt(2):
-+
-+ret = setsockopt(afd, SOL_BUS, BUS_JOIN_BUS, NULL, 0);
-+
-+Clients are not meant to send messages to each other until the master
-+tells them (in a protocol-specific way) that the BUS_JOIN_BUS
-+setsockopt(2) call was made.
-+
-+If a client sends a message to a destination other than the bus
-+master's all-zero address before joining the bus, a EHOSTUNREACH (No
-+route to host) error is returned since the only host that exists in
-+the point-to-point network before the client joins the bus are the
-+client and the bus master.
-+
-+A EHOSTUNREACH is returned if a client that joined a bus tries to send
-+a packet to a client from another bus. Cross-bus communication is not
-+permited.
-+
-+When a process wants to send a unicast message to a peer, it fills a
-+sockaddr structure and performs a socket operation (i.e., sendto(2))
-+
-+struct sockaddr_bus addr;
-+char *msg = "Hello world";
-+
-+addr.sbus_family = AF_BUS;
-+strcpy(addr.sbus_path, "/tmp/test");
-+addr.sbus_addr.s_addr = 0x0001f00ddeadbeef;
-+
-+ret = sendto(sockfd, "Hello world", strlen("Hello world"), 0,
-+ (struct sockaddr*)&addr, sizeof(addr));
-+
-+The current implementation requires that the addr.sbus_path component
-+match the one used to conenct() to the bus but in future this
-+requirement will be removed.
-+
-+The kernel will first check that the socket is connected and that the
-+bus path of the socket correspond with the destination, then it will
-+extract the prefix and client address from the bus address using a
-+fixed 16 -bit bitmask.
-+
-+prefix = bus address >> 48 & 0xffff
-+client address = bus address & 0xffff
-+
-+If the client address is not all bits one, then the message is unicast
-+and is delivered to the socket with that assigned address
-+(0x0001f00ddeadbeef). Otherwise the message is multicast and is
-+delivered to all the peers with this address prefix (0x0001 in this
-+case).
-+
-+So, when a process wants to send a multicast message, it just has to
-+fill the address structure with the address prefix + 0xffffffffffff:
-+
-+struct sockaddr_bus addr;
-+char *msg = "Hello world";
-+
-+addr.bus_family = AF_BUS;
-+strcpy(addr.sbus_path, "/tmp/test");
-+addr.bus_addr = 0x0001ffffffffffff;
-+
-+ret = sendto(sockfd, "Hello world", strlen("Hello world"), 0,
-+ (struct sockaddr*)&addr, sizeof(addr));
-+
-+The kernel, will apply the binary and operation, learn that the
-+address is 0xffffffffffff and send the message to all the peers on
-+this prefix (0x0001).
-+
-+Socket transmit queued bytes are limited by a maximum send buffer size
-+(sysctl_wmem_max) defined in the kernel and can be modified at runtime
-+using the sysctl interface on /proc/sys/net/core/wmem_default. This
-+parameter is global for all the sockets families in a Linux system.
-+
-+AF_BUS permits the definition of a per-bus maximum send buffer size
-+using the BUS_SET_SENDBUF socket option. The bus master can call the
-+setsockopt(2) system call using as a parameter the listening socket.
-+The command sets a maximum write buffer that will be imposed on each
-+new socket that connects to the bus:
-+
-+ret = setsockopt(serverfd, SOL_BUS, BUS_SET_SENDBUF, &sndbuf,
-+sizeof(int));
-+
-+In the transmission path both Berkeley Packet Filters and Netfilter
-+hooks are available, so they can be used to filter sending packets.
-+
-+
-+Using this addressing scheme with D-Bus
-+---------------------------------------
-+
-+As an example of a use case for AF_BUS, let's analyze how the D-Bus
-+IPC system can be implemented on top of it.
-+
-+We define a new D-Bus address type "afbus".
-+
-+A D-Bus client may connect to an address of the form "afbus:path=X"
-+where X is a string. This means that it connect()s to { AF_BUS, 0, X }.
-+
-+For example: afbus:path=/tmp/test connects to { AF_BUS, 0, /tmp/test }.
-+
-+A D-Bus daemon may listen on the address "afbus:", which means that it
-+binds to { AF_BUS, 0, /tmp/test }. It will advertise an address of the
-+form "afbus:path=/tmp/test" to clients, for instance via the
-+--print-address option, or via dbus-launch setting the
-+DBUS_SESSION_BUS_ADDRESS environment variable. For instance, "afbus:"
-+is an appropriate default listening address for the session bus,
-+resulting in dbus-launch setting the DBUS_SESSION_BUS_ADDRESS
-+environment variable to something like
-+"afbus:path=/tmp/test,guid=...".
-+
-+A D-Bus daemon may listen on the address "afbus:file=/some/file",
-+which means that it will do as above, then write its path into the
-+given well-known file. For instance,
-+"afbus:file=/run/dbus/system_bus.afbus" is an appropriate listening
-+address for the system bus. Only processes with suitable privileges to
-+write to that file can impersonate the system bus.
-+
-+D-Bus clients wishing to connect to the well-known system bus should
-+attempt to connect to afbus:file=/run/dbus/system_bus.afbus, falling
-+back to unix:path=/var/run/dbus/system_bus_socket if that fails. On
-+Linux systems, the well-known system bus daemon should attempt to
-+listen on both of those addresses.
-+
-+The D-Bus daemon will serve as bus master as well since it will be the
-+process that creates and listens on the AF_BUS socket.
-+
-+D-Bus clients will use the fixed bus master address (all zero bits) to
-+send messages to the D-Bus daemon and the client's unique address to
-+send messages to other D-Bus clients using the bus.
-+
-+When initially connected, D-Bus clients will only be able to
-+communicate with the D-Bus daemon and will send authentication
-+information (AUTH message and SCM_CREDENTIALS ancillary
-+messages). Since the D-Bus daemon is also the bus master, it can allow
-+D-Bus clients to join the bus and be able to send and receive D-Bus
-+messages from other peers.
-+
-+On connection, the kernel will assign to each client an address in the
-+prefix 0x0000. If a client attempts to send messages to clients other
-+than the bus master, this is considered to be an error, and is
-+prevented by the kernel.
-+
-+When the D-Bus daemon has authenticated a client and determined that
-+it is authorized to be on this bus, it uses a setsockopt(2) call to
-+tell the kernel that this client has permission to send messages. The
-+D-Bus daemon then tells the client by sending the Hello() reply that
-+it has made the setsockopt(2) call and that now is able to send
-+messages to other peers on the bus.
-+
-+Well-known names are represented by addresses in the 0x0001, ... prefixes.
-+
-+Addresses in prefix 0x0000 must be mapped to D-Bus unique names in a
-+way that can't collide with unique names allocated by the dbus-daemon
-+for legacy clients.
-+
-+In order to be consistent with current D-Bus unique naming, the AF_BUS
-+addresses can be mapped directly to D-Bus unique names, for example
-+(0000/0000deadbeef to ":0.deadbeef"). Leading zeroes can be suppressed
-+since the common case should be relatively small numbers (the kernel
-+allocates client addresses sequentially, and machines could be
-+rebooted occasionally).
-+
-+By having both AF_BUS and legacy D-Bus clients use the same address
-+space, the D-Bus daemon can act as a proxy between clients and can be
-+sure that D-Bus unique names will be unique for both AF_BUS and legacy
-+clients.
-+
-+To act as a proxy between AF_BUS and legacy clients, each time the
-+D-Bus daemon accepts a legacy connection (i.e., AF_UNIX), it will
-+create an AF_BUS socket and establish a connection with itself. It
-+will then associate this newly created connection with the legacy one.
-+
-+To explain it graphically:
-+
-+ L The AF_BUS listening socket }
-+ / | \ }-- listener process
-+ A1 A2 A3 The AF_BUS accepted sockets }
-+ | | |
-+ C1 C2 C3 The AF_BUS connected sockets, where:
-+ | * C1 belongs to the listener process
-+ | * C2 and C3 belongs to the client processes
-+ |
-+ L2--A4 The AF_UNIX listening and accepted sockets \
-+ | in the listener process
-+ C4 The AF_UNIX connected socket in the legacy client process
-+
-+
-+where C2 and C3 are normal AF_BUS clients and C4 is a legacy
-+client. The D-Bus daemon after accepting the connection using the
-+legacy transport (A4), will create an AF_BUS socket pair (C1, A1)
-+associated with the legacy client.
-+
-+Legacy clients will send messages to the D-Bus daemon using their
-+legacy socket and the D-Bus daemon will extract the destination
-+address, resolve to the corresponding AF_BUS address and use this to
-+send the message to the right peer.
-+
-+Conversely, when an AF_BUS client sends a D-Bus message to a legacy
-+client, it will use the AF_BUS address of the connection associated
-+with that client. The D-Bus daemon will receive the message, modify
-+the message's content to set SENDER headers based on the AF_BUS source
-+address and use the legacy transport to send the D-Bus message to the
-+legacy client.
-+
-+As a special case, the bus daemon's all-zeroes address maps to
-+"org.freedesktop.DBus" and vice versa.
-+
-+When a D-Bus client receives an AF_BUS message from the bus master
-+(0/0), it must use the SENDER header field in the D-Bus message, as
-+for any other D-Bus transport, to determine whether the message is
-+actually from the D-Bus daemon (the SENDER is "org.freedesktop.DBus"
-+or missing), or from another client (the SENDER starts with ":"). It
-+is valid for messages from another AF_BUS client to be received via
-+the D-Bus daemon; if they are, the SENDER header field will always be
-+set.
-+
-+Besides its unique name, D-Bus services can have well-known names such
-+as org.gnome.Keyring or org.freedesktop.Telepathy. These well-known
-+names can also be used as a D-Bus message destination
-+address. Well-known names are not numeric and AF_BUS is not able to
-+parse D-Bus messages.
-+
-+To solve this, the D-Bus daemon will assign an additional AF_BUS
-+address to each D-Bus client that owns a well-known name. The mapping
-+between well-known names and AF_BUS address is maintained by the D-Bus
-+daemon on a persistent data structure.
-+
-+D-Bus client libraries will maintain a cache of these mappings so they
-+can send messages to services with well-known names using their mapped
-+AF_BUS address.
-+
-+If a client intending to send a D-Bus message to a given well-known
-+name does not have that well-known name in its cache, it must send the
-+AF_BUS message to the listener (0000/000000000000) instead.
-+
-+The listener must forward the D-Bus message to the owner of that
-+well-known name, setting the SENDER header field if necessary. It may
-+also send this AF_BUS-specific D-Bus signal to the sender, so that the
-+sender can update its cache:
-+
-+ org.freedesktop.DBus.AF_BUS.Forwarded (STRING well_known_name,
-+ UINT64 af_bus_client)
-+
-+ Emitted by the D-Bus daemon with sender "org.freedesktop.DBus"
-+ and object path "/org/freedesktop/DBus" to indicate that
-+ the well-known name well_known_name is represented by the
-+ AF_BUS address { AF_BUS, af_bus_client, path } where
-+ path is the path name used by this bus.
-+
-+ For instance, if the well-known name "org.gnome.Keyring"
-+ is represented by AF_BUS address 0001/0000deadbeef,
-+ the signal would have arguments ("org.gnome.Keyring",
-+ 0x00010000deadbeef), corresponding to the AF_BUS
-+ address { AF_BUS, 0x00010000deadbeef, /tmp/test }.
-+
-+If the D-Bus service for that well-known name is not active, then the
-+D-Bus daemon will first do the service activation, assign an
-+additional address to the recently activated service, store the
-+well-known service to numeric address mapping on its persistent cache,
-+and then send the AF_BUS.Forwarded signal back to the client.
-+
-+Once the mapping has been made, the AF_BUS address associated with a
-+well-known name cannot be reused for the lifetime of the D-Bus daemon
-+(which is the same as the lifetime of the socket).
-+
-+Nevertheless the AF_BUS address associated with a well-known name can
-+change, for example if a service goes away and a new instance gets
-+activated. This new instance can have a different AF_BUS address. The
-+D-Bus daemon will maintain a list of the mappings that are currently
-+valid so it can send the AF_BUS.
-+
-+Forwarded signal with the mapping information to the clients. Client
-+libraries will maintain a fixed-size Last Recently Used (LRU) cache
-+with previous mappings sent by the D-Bus daemon.
-+
-+If the clients overwrite a mapping due to the LRU replace policy and
-+later want to send a D-Bus message to the overwritten well-known name,
-+they will send the D-Bus message back to the D-Bus daemon and this
-+will send the signal with the mapping information.
-+
-+If a service goes away or if the service AF_BUS address changed and
-+the client still has the old AF_BUS address in its cache, it will send
-+the D-Bus message to the old destination.
-+
-+Since packets whose destination AF_BUS addresses are not assigned to
-+any process are routed by default to the bus master, the D-Bus daemon
-+will receive these D-bus messages and send an AF_BUS.
-+
-+Forwarded signal back to the client with the new AF_BUS address so it
-+can update its cache with the new mapping.
-+
-+For well-known names, the D-Bus daemon will use a different address
-+prefix (0x0001) so it doesn't conflict with the D-Bus unique names
-+address prefix (0x0000).
-+
-+Besides D-Bus method call messages which are unicast, D-Bus allows
-+clients to send multicast messages (D-Bus signals). Clients can send
-+signals messages using the bus unique name prefix multicast address
-+(0x0001ffffffffffff).
-+
-+A netfilter hook is used to filter these multicast messages and only
-+deliver to the correct peers based on match rules.
-+
-+
-+D-Bus aware netfilter module
-+----------------------------
-+
-+AF_BUS is designed to be a generic bus transport supporting both
-+unicast and multicast communications.
-+
-+In order for D-Bus to operate efficiently, the transport method has to
-+know the D-Bus message wire-protocol and D-Bus message structure. But
-+adding this D-Bus specific knowledge to AF_BUS will break one of the
-+fundamental design principles of any network protocol stack, namely
-+layer-independence: layer n must not make any assumptions about the
-+payload in layer n + 1.
-+
-+So, in order to have a clean protocol design but be able to allow the
-+transport to analyze the D-Bus messages, netfilter hooks are used to
-+do the filtering based on match rules.
-+
-+The kernel module has to maintain the match rules and the D-Bus daemon
-+is responsible for managing this information. Every time an add match
-+rule message is processed by the D-Bus daemon, this will update the
-+netfilter module match rules set so the netfilter hook function can
-+use that information to do the match rules based filtering.
-+
-+The D-Bus daemon and the netfilter module will use the generic netlink
-+subsystem to do the kernel-to-user-space communication. Netlink is
-+already used by most of the networking subsystem in Linux
-+(iptables/netfilter, ip/routing, etc).
-+
-+We enforce a security scheme so only the bus master's user ID can
-+update the netfilter module match rules set.
-+
-+The advantage of using the netfilter subsystem is that we decouple the
-+mechanism from the policy. AF_BUS will only add a set of hook points
-+and external modules will be used to enforce a given policy.
---
-1.7.7.6
-
+++ /dev/null
-From 7fcfceea3fefae54e168726703c5030725106e6b Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Wed, 20 Jun 2012 12:18:56 +0200
-Subject: [PATCH 03/15] net: bus: add af_bus address and af_bus socket address
- definitions
-
-An AF_BUS socket can have many addresses associated. This allows to send
-multicast packets on different domains. An af_bus address is an unsigned
-64-bit value that contains two fields: a 16-bit prefix and a 48-bit client
-address.
-
-Each bus has an associated path name that uniquely identifies the bus.
-So, a socket address is composed of the bus path and the peer address.
-
-Clients can send unicast packets to each other and multicast to different
-prefixes but they can only connect(2) to a special socket that owns the
-bus an is known as the bus master.
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
----
- include/linux/bus.h | 34 ++++++
- include/net/af_bus.h | 273 ++++++++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 307 insertions(+), 0 deletions(-)
- create mode 100644 include/linux/bus.h
- create mode 100644 include/net/af_bus.h
-
-diff --git a/include/linux/bus.h b/include/linux/bus.h
-new file mode 100644
-index 0000000..19cac36
---- /dev/null
-+++ b/include/linux/bus.h
-@@ -0,0 +1,34 @@
-+#ifndef _LINUX_BUS_H
-+#define _LINUX_BUS_H
-+
-+#include <linux/socket.h>
-+
-+/* 'protocol' to use in socket(AF_BUS, SOCK_SEQPACKET, protocol) */
-+#define BUS_PROTO_NONE 0
-+#define BUS_PROTO_DBUS 1
-+#define BUS_PROTO_MAX 1
-+
-+#define BUS_PATH_MAX 108
-+
-+/**
-+ * struct bus_addr - af_bus address
-+ * @s_addr: an af_bus address (16-bit prefix + 48-bit client address)
-+ */
-+struct bus_addr {
-+ u64 s_addr;
-+};
-+
-+
-+/**
-+ * struct sockaddr_bus - af_bus socket address
-+ * @sbus_family: the socket address family
-+ * @sbus_addr: an af_bus address
-+ * @sbus_path: a path name
-+ */
-+struct sockaddr_bus {
-+ __kernel_sa_family_t sbus_family;
-+ struct bus_addr sbus_addr;
-+ char sbus_path[BUS_PATH_MAX];
-+};
-+
-+#endif /* _LINUX_BUS_H */
-diff --git a/include/net/af_bus.h b/include/net/af_bus.h
-new file mode 100644
-index 0000000..e63eb49
---- /dev/null
-+++ b/include/net/af_bus.h
-@@ -0,0 +1,273 @@
-+/*
-+ * Copyright (c) 2012, GENIVI Alliance
-+ *
-+ * Authors: Javier Martinez Canillas, <javier.martinez@collabora.co.uk>
-+ * Alban Crequy, <alban.crequy@collabora.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * Based on BSD Unix domain sockets (net/unix).
-+ */
-+
-+#ifndef __LINUX_NET_AFBUS_H
-+#define __LINUX_NET_AFBUS_H
-+
-+#include <linux/socket.h>
-+#include <linux/bus.h>
-+#include <linux/mutex.h>
-+#include <net/sock.h>
-+#include <net/tcp_states.h>
-+
-+extern void bus_inflight(struct file *fp);
-+extern void bus_notinflight(struct file *fp);
-+extern void bus_gc(void);
-+extern void wait_for_bus_gc(void);
-+extern struct sock *bus_get_socket(struct file *filp);
-+extern struct sock *bus_peer_get(struct sock *);
-+
-+#define BUS_HASH_SIZE 256
-+
-+extern spinlock_t bus_address_lock;
-+extern struct hlist_head bus_address_table[BUS_HASH_SIZE];
-+
-+#define BUS_MAX_QLEN 10
-+#define BUS_MASTER_ADDR 0x0
-+#define BUS_PREFIX_BITS 16
-+#define BUS_CLIENT_BITS 48
-+#define BUS_PREFIX_MASK 0xffff000000000000
-+#define BUS_CLIENT_MASK 0x0000ffffffffffff
-+
-+/* AF_BUS socket options */
-+#define BUS_ADD_ADDR 1
-+#define BUS_JOIN_BUS 2
-+#define BUS_DEL_ADDR 3
-+#define BUS_SET_EAVESDROP 4
-+#define BUS_UNSET_EAVESDROP 5
-+#define BUS_SET_SENDBUF 6
-+#define BUS_SET_MAXQLEN 7
-+#define BUS_GET_QLENFULL 8
-+
-+/* Connection and socket states */
-+enum {
-+ BUS_ESTABLISHED = TCP_ESTABLISHED,
-+ BUS_CLOSE = TCP_CLOSE,
-+ BUS_LISTEN = TCP_LISTEN,
-+ BUS_MAX_STATES
-+};
-+
-+#define NF_BUS_SENDING 1
-+
-+extern unsigned int bus_tot_inflight;
-+extern spinlock_t bus_table_lock;
-+extern struct hlist_head bus_socket_table[BUS_HASH_SIZE + 1];
-+
-+/**
-+ * struct bus_address - an af_bus address associated with an af_bus sock
-+ * @refcnt: address reference counter
-+ * @len: address length
-+ * @hash: address hash value
-+ * @addr_node: member of struct bus_sock.addr_list
-+ * @table_node: member of struct hlist_head bus_address_table[hash]
-+ * @sock: the af_bus sock that owns this address
-+ * @name: the socket address for this address
-+ */
-+struct bus_address {
-+ atomic_t refcnt;
-+ int len;
-+ unsigned hash;
-+ struct hlist_node addr_node;
-+ struct hlist_node table_node;
-+ struct sock *sock;
-+ struct sockaddr_bus name[0];
-+};
-+
-+/**
-+ * struct bus_send_context - sending context for an socket buffer
-+ * @sender_socket: the sender socket associated with this sk_buff
-+ * @siocb: used to send ancillary data
-+ * @timeo: sending timeout
-+ * @max_level: file descriptor passing maximum recursion level
-+ * @namelen: length of socket address name
-+ * @hash: socket name hash value
-+ * @other: destination sock
-+ * @sender: sender socket address name
-+ * @recipient: recipient socket address name
-+ * @authenticated: flag whether the sock already joined the bus
-+ * @bus_master_side: flag whether the sock is an accepted socket
-+ * @to_master: flag whether the destination is the bus master
-+ * @multicast: flag whether the destination is a multicast address
-+ * @deliver: flag whether the skb has to be delivered
-+ * @eavesdropper: flag whether the sock is allowed to eavesdrop
-+ * @main_recipient: flag whether the sock is the main recipient
-+ */
-+struct bus_send_context {
-+ struct socket *sender_socket;
-+ struct sock_iocb *siocb;
-+ long timeo;
-+ int max_level;
-+ int namelen;
-+ unsigned hash;
-+ struct sock *other;
-+ struct sockaddr_bus *sender;
-+ struct sockaddr_bus *recipient;
-+ unsigned int authenticated:1;
-+ unsigned int bus_master_side:1;
-+ unsigned int to_master:1;
-+ unsigned int multicast:1;
-+ unsigned int deliver:1;
-+ unsigned int eavesdropper:1;
-+ unsigned int main_recipient:1;
-+};
-+
-+/**
-+ * struct bus_skb_parms - socket buffer parameters
-+ * @pid: process id
-+ * @cred: skb credentials
-+ * @fp: passed file descriptors
-+ * @secid: security id
-+ * @sendctx: skb sending context
-+ */
-+struct bus_skb_parms {
-+ struct pid *pid;
-+ const struct cred *cred;
-+ struct scm_fp_list *fp;
-+#ifdef CONFIG_SECURITY_NETWORK
-+ u32 secid;
-+#endif
-+ struct bus_send_context *sendctx;
-+};
-+
-+#define BUSCB(skb) (*(struct bus_skb_parms *)&((skb)->cb))
-+#define BUSSID(skb) (&BUSCB((skb)).secid)
-+
-+#define bus_state_lock(s) spin_lock(&bus_sk(s)->lock)
-+#define bus_state_unlock(s) spin_unlock(&bus_sk(s)->lock)
-+#define bus_state_lock_nested(s) \
-+ spin_lock_nested(&bus_sk(s)->lock, \
-+ SINGLE_DEPTH_NESTING)
-+
-+/**
-+ * struct bus - a communication bus
-+ * @master: the bus master sock
-+ * @peers: list of struct bus_sock.bus_node allowed to join the bus
-+ * @lock: protect peers concurrent access
-+ * @send_lock: enforce atomic multicast delivery
-+ * @kref: bus reference counter
-+ * @addr_cnt: address number counter to assign prefix 0x0000 addresses
-+ * @eavesdropper_cnt: eavesdroppers counter
-+ */
-+struct bus {
-+ struct sock *master;
-+ struct hlist_head peers;
-+ spinlock_t lock;
-+ spinlock_t send_lock;
-+ struct kref kref;
-+ atomic64_t addr_cnt;
-+ atomic64_t eavesdropper_cnt;
-+};
-+
-+/**
-+ * struct bus_sock - an af_bus socket
-+ * @sk: associated sock
-+ * @addr: sock principal address
-+ * @addr_list: list of struct bus_address.addr_node
-+ * @path: sock path name
-+ * @readlock: protect from concurrent reading
-+ * @peer: peer sock
-+ * @other: the listening sock
-+ * @link: list of candidates for garbage collection
-+ * @inflight: number of times the file descriptor is in flight
-+ * @lock: protect the sock from concurrent access
-+ * @gc_candidate: flag whether the is a candidate for gc
-+ * @gc_maybe_cycle: flag whether could be a cyclic reference
-+ * @recursion_level: file passing current recursion level
-+ * @peer_wq: peer sock wait queue
-+ * @bus: bus that this sock belongs to
-+ * @bus_master: flag whether the sock is the bus master
-+ * @bus_master_side: flag whether is an accepted socket
-+ * @authenticated: flag whether the sock joined the bus
-+ * @eavesdropper: flag whether the sock is allowed to eavesdrop
-+ * @bus_node: member of struct bus.peers list of joined socks
-+ */
-+struct bus_sock {
-+ /* WARNING: sk has to be the first member */
-+ struct sock sk;
-+ struct bus_address *addr;
-+ struct hlist_head addr_list;
-+ struct path path;
-+ struct mutex readlock;
-+ struct sock *peer;
-+ struct sock *other;
-+ struct list_head link;
-+ atomic_long_t inflight;
-+ spinlock_t lock;
-+ unsigned int gc_candidate:1;
-+ unsigned int gc_maybe_cycle:1;
-+ unsigned char recursion_level;
-+ struct socket_wq peer_wq;
-+ struct bus *bus;
-+ bool bus_master;
-+ bool bus_master_side;
-+ bool authenticated;
-+ bool eavesdropper;
-+ struct hlist_node bus_node;
-+};
-+#define bus_sk(__sk) ((struct bus_sock *)__sk)
-+
-+#define peer_wait peer_wq.wait
-+
-+/**
-+ * bus_same_bus - Test if two socket address belongs to the same bus
-+ * @sbusaddr1: socket address name
-+ * @sbusaddr2: socket address name
-+ */
-+static inline bool bus_same_bus(struct sockaddr_bus *sbusaddr1,
-+ struct sockaddr_bus *sbusaddr2)
-+{
-+ int offset;
-+
-+ if (sbusaddr1->sbus_path[0] != sbusaddr2->sbus_path[0])
-+ return false;
-+
-+ /*
-+ * abstract path names start with a null byte character,
-+ * so they have to be compared starting at the second char.
-+ */
-+ offset = (sbusaddr1->sbus_path[0] == '\0');
-+
-+ return !strncmp(sbusaddr1->sbus_path + offset,
-+ sbusaddr2->sbus_path + offset,
-+ BUS_PATH_MAX);
-+}
-+
-+static inline unsigned int bus_hash_fold(__wsum n)
-+{
-+ unsigned int hash = (__force unsigned int)n;
-+ hash ^= hash>>16;
-+ hash ^= hash>>8;
-+ return hash&(BUS_HASH_SIZE-1);
-+}
-+
-+static inline unsigned int bus_compute_hash(struct bus_addr addr)
-+{
-+ return bus_hash_fold(csum_partial((void *)&addr, sizeof(addr), 0));
-+}
-+
-+long bus_inq_len(struct sock *sk);
-+long bus_outq_len(struct sock *sk);
-+
-+#ifdef CONFIG_SYSCTL
-+extern int bus_sysctl_register(struct net *net);
-+extern void bus_sysctl_unregister(struct net *net);
-+#else
-+static inline int bus_sysctl_register(struct net *net) { return 0; }
-+static inline void bus_sysctl_unregister(struct net *net) {}
-+#endif
-+
-+bool bus_can_write(struct net *net, struct sockaddr_bus *addr, int len,
-+ int protocol);
-+
-+#endif /* __LINUX_NET_AFBUS_H */
---
-1.7.7.6
-
+++ /dev/null
-From 67699fea892540b8bdce95ae22ae43c94b684d29 Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Wed, 20 Jun 2012 14:29:14 +0200
-Subject: [PATCH 04/15] security: Add Linux Security Modules hook for AF_BUS
- sockets
-
-AF_BUS implements a security hook bus_connect() to be used by LSM
-to enforce connectivity security policies.
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
----
- include/linux/security.h | 11 +++++++++++
- security/capability.c | 7 +++++++
- security/security.c | 7 +++++++
- 3 files changed, 25 insertions(+), 0 deletions(-)
-
-diff --git a/include/linux/security.h b/include/linux/security.h
-index 673afbb..fa26c6d 100644
---- a/include/linux/security.h
-+++ b/include/linux/security.h
-@@ -1578,6 +1578,8 @@ struct security_operations {
-
- #ifdef CONFIG_SECURITY_NETWORK
- int (*unix_stream_connect) (struct sock *sock, struct sock *other, struct sock *newsk);
-+ int (*bus_connect) (struct sock *sock, struct sock *other,
-+ struct sock *newsk);
- int (*unix_may_send) (struct socket *sock, struct socket *other);
-
- int (*socket_create) (int family, int type, int protocol, int kern);
-@@ -2517,6 +2519,8 @@ static inline int security_inode_getsecctx(struct inode *inode, void **ctx, u32
- #ifdef CONFIG_SECURITY_NETWORK
-
- int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk);
-+int security_bus_connect(struct sock *sock, struct sock *other,
-+ struct sock *newsk);
- int security_unix_may_send(struct socket *sock, struct socket *other);
- int security_socket_create(int family, int type, int protocol, int kern);
- int security_socket_post_create(struct socket *sock, int family,
-@@ -2564,6 +2568,13 @@ static inline int security_unix_stream_connect(struct sock *sock,
- return 0;
- }
-
-+static inline int security_bus_connect(struct socket *sock,
-+ struct sock *other,
-+ struct sock *newsk)
-+{
-+ return 0;
-+}
-+
- static inline int security_unix_may_send(struct socket *sock,
- struct socket *other)
- {
-diff --git a/security/capability.c b/security/capability.c
-index 5bb21b1..5b966a6 100644
---- a/security/capability.c
-+++ b/security/capability.c
-@@ -563,6 +563,12 @@ static int cap_unix_may_send(struct socket *sock, struct socket *other)
- return 0;
- }
-
-+static int cap_bus_connect(struct sock *sock, struct sock *other,
-+ struct sock *newsk)
-+{
-+ return 0;
-+}
-+
- static int cap_socket_create(int family, int type, int protocol, int kern)
- {
- return 0;
-@@ -1015,6 +1021,7 @@ void __init security_fixup_ops(struct security_operations *ops)
- #ifdef CONFIG_SECURITY_NETWORK
- set_to_cap_if_null(ops, unix_stream_connect);
- set_to_cap_if_null(ops, unix_may_send);
-+ set_to_cap_if_null(ops, bus_connect);
- set_to_cap_if_null(ops, socket_create);
- set_to_cap_if_null(ops, socket_post_create);
- set_to_cap_if_null(ops, socket_bind);
-diff --git a/security/security.c b/security/security.c
-index bf619ff..54582ea 100644
---- a/security/security.c
-+++ b/security/security.c
-@@ -1018,6 +1018,13 @@ int security_unix_may_send(struct socket *sock, struct socket *other)
- }
- EXPORT_SYMBOL(security_unix_may_send);
-
-+int security_bus_connect(struct sock *sock, struct sock *other,
-+ struct sock *newsk)
-+{
-+ return security_ops->bus_connect(sock, other, newsk);
-+}
-+EXPORT_SYMBOL(security_bus_connect);
-+
- int security_socket_create(int family, int type, int protocol, int kern)
- {
- return security_ops->socket_create(family, type, protocol, kern);
---
-1.7.7.6
-
+++ /dev/null
-From 714516658e81f2342fe5fd2b8f5493d19f3731b4 Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Wed, 20 Jun 2012 14:32:26 +0200
-Subject: [PATCH 05/15] security: selinux: Add AF_BUS socket SELinux hooks
-
-Add Security-Enhanced Linux (SELinux) hook for AF_BUS socket address family.
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
----
- security/selinux/hooks.c | 35 +++++++++++++++++++++++++++++++++++
- 1 files changed, 35 insertions(+), 0 deletions(-)
-
-diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
-index 5626222..91edbdd 100644
---- a/security/selinux/hooks.c
-+++ b/security/selinux/hooks.c
-@@ -67,6 +67,7 @@
- #include <linux/quota.h>
- #include <linux/un.h> /* for Unix socket types */
- #include <net/af_unix.h> /* for Unix socket types */
-+#include <net/af_bus.h> /* for Bus socket types */
- #include <linux/parser.h>
- #include <linux/nfs_mount.h>
- #include <net/ipv6.h>
-@@ -4102,6 +4103,39 @@ static int selinux_socket_unix_may_send(struct socket *sock,
- &ad);
- }
-
-+static int selinux_socket_bus_connect(struct sock *sock, struct sock *other,
-+ struct sock *newsk)
-+{
-+ struct sk_security_struct *sksec_sock = sock->sk_security;
-+ struct sk_security_struct *sksec_other = other->sk_security;
-+ struct sk_security_struct *sksec_new = newsk->sk_security;
-+ struct common_audit_data ad;
-+ struct lsm_network_audit net = {0,};
-+ int err;
-+
-+ ad.type = LSM_AUDIT_DATA_NET;
-+ ad.u.net = &net;
-+ ad.u.net->sk = other;
-+
-+ err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
-+ sksec_other->sclass,
-+ UNIX_STREAM_SOCKET__CONNECTTO, &ad);
-+ if (err)
-+ return err;
-+
-+ /* server child socket */
-+ sksec_new->peer_sid = sksec_sock->sid;
-+ err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
-+ &sksec_new->sid);
-+ if (err)
-+ return err;
-+
-+ /* connecting socket */
-+ sksec_sock->peer_sid = sksec_new->sid;
-+
-+ return 0;
-+}
-+
- static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
- u32 peer_sid,
- struct common_audit_data *ad)
-@@ -5656,6 +5690,7 @@ static struct security_operations selinux_ops = {
-
- .unix_stream_connect = selinux_socket_unix_stream_connect,
- .unix_may_send = selinux_socket_unix_may_send,
-+ .bus_connect = selinux_socket_bus_connect,
-
- .socket_create = selinux_socket_create,
- .socket_post_create = selinux_socket_post_create,
---
-1.7.7.6
-
+++ /dev/null
-From b7943d96bba05258c0eeabed0aa6e006a3ec06ec Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Wed, 20 Jun 2012 14:59:16 +0200
-Subject: [PATCH 06/15] netfilter: add NFPROTO_BUS hook constant for AF_BUS
- socket family
-
-AF_BUS sockets add a netfilter NF_HOOK() on the packet sending path.
-This allows packet to be mangled by registered netfilter hooks.
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
----
- include/linux/netfilter.h | 1 +
- 1 files changed, 1 insertions(+), 0 deletions(-)
-
-diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
-index 29734be..7cff0bd 100644
---- a/include/linux/netfilter.h
-+++ b/include/linux/netfilter.h
-@@ -67,6 +67,7 @@ enum {
- NFPROTO_BRIDGE = 7,
- NFPROTO_IPV6 = 10,
- NFPROTO_DECNET = 12,
-+ NFPROTO_BUS,
- NFPROTO_NUMPROTO,
- };
-
---
-1.7.7.6
-
+++ /dev/null
-From efe7f1ea3bc352b350671bb8c2b5e573672faf6a Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Wed, 20 Jun 2012 15:22:08 +0200
-Subject: [PATCH 07/15] scm: allow AF_BUS sockets to send ancillary data
-
-UNIX domain sockets support passing file descriptors or process
-credentials in the form of ancillary data.
-
-Since AF_BUS sockets are used to communicate processes on a local
-machine, they should also support passing control messages.
-The core socket level control messages processing only allows sockets
-whose family is PF_UNIX to send SCM_RIGHTS type messages. So, let's
-also allow to PF_BUS sockets.
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
----
- net/core/scm.c | 3 ++-
- 1 files changed, 2 insertions(+), 1 deletions(-)
-
-diff --git a/net/core/scm.c b/net/core/scm.c
-index 611c5ef..87e3152 100644
---- a/net/core/scm.c
-+++ b/net/core/scm.c
-@@ -158,7 +158,8 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
- switch (cmsg->cmsg_type)
- {
- case SCM_RIGHTS:
-- if (!sock->ops || sock->ops->family != PF_UNIX)
-+ if (!sock->ops || (sock->ops->family != PF_UNIX &&
-+ sock->ops->family != PF_BUS))
- goto error;
- err=scm_fp_copy(cmsg, &p->fp);
- if (err<0)
---
-1.7.7.6
-
+++ /dev/null
-From d1bbdbce93bba76325b0d22da84cb8833da49df0 Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Wed, 20 Jun 2012 15:29:34 +0200
-Subject: [PATCH 08/15] net: bus: Add implementation of Bus domain sockets
-
-Each process connected to an AF_BUS socket, has one or more addresses
-within that bus. These addresses are 64-bit unsigned integers,
-interpreted by splitting the address into two parts: the most significant
-16 bits are a prefix identifying the type of address, and the remaining
-48 bits are the actual client address within that prefix.
-
-The process that calls bind(2) on the socket is the owner of the bus and
-is called the bus master. The master is a special client of the bus and has
-some responsibility for the bus' operation. The master is assigned a fixed
-address with all the bits zero.
-
-The prefix with all bits zero is reserved for use by the kernel, which
-automatically assigns one address from this prefix to each client on
-connection. The address in this prefix with all bits zero is always
-assigned to the bus master. Addresses on the prefix 0000 are unique
-and will never repeat for the lifetime of the bus master.
-
-AF_BUS transport can support two network topologies. When a process
-first connect to the bus master, it can only communicate with the
-bus master. The process can't send and receive packets from other
-peers on the bus. So, from the client process point of view the
-network topology is point-to-point.
-
-The bus master can allow the connected peer to be part of the bus
-and start to communicate with other peers by setting an socket option
-with the setsockopt(2) system call using the accepted socket descriptor.
-At this point, the topology becomes a bus to the client process.
-
-Packets whose destination address is not assigned to any client are routed
-by default to the bus master (the client accepted socket descriptor).
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
----
- net/bus/af_bus.c | 2688 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 files changed, 2688 insertions(+), 0 deletions(-)
- create mode 100644 net/bus/af_bus.c
-
-diff --git a/net/bus/af_bus.c b/net/bus/af_bus.c
-new file mode 100644
-index 0000000..d25af65
---- /dev/null
-+++ b/net/bus/af_bus.c
-@@ -0,0 +1,2688 @@
-+/*
-+ * Implementation of Bus domain sockets.
-+ *
-+ * Copyright (c) 2012, GENIVI Alliance
-+ *
-+ * Authors: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-+ * Alban Crequy <alban.crequy@collabora.co.uk>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * Based on BSD Unix domain sockets (net/unix).
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/string.h>
-+#include <linux/stat.h>
-+#include <linux/dcache.h>
-+#include <linux/namei.h>
-+#include <linux/socket.h>
-+#include <linux/bus.h>
-+#include <linux/fcntl.h>
-+#include <linux/termios.h>
-+#include <linux/sockios.h>
-+#include <linux/net.h>
-+#include <linux/in.h>
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <net/net_namespace.h>
-+#include <net/sock.h>
-+#include <net/af_bus.h>
-+#include <linux/proc_fs.h>
-+#include <linux/seq_file.h>
-+#include <net/scm.h>
-+#include <linux/init.h>
-+#include <linux/poll.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/mount.h>
-+#include <net/checksum.h>
-+#include <linux/security.h>
-+
-+struct hlist_head bus_socket_table[BUS_HASH_SIZE + 1];
-+EXPORT_SYMBOL_GPL(bus_socket_table);
-+struct hlist_head bus_address_table[BUS_HASH_SIZE];
-+EXPORT_SYMBOL_GPL(bus_address_table);
-+DEFINE_SPINLOCK(bus_table_lock);
-+DEFINE_SPINLOCK(bus_address_lock);
-+EXPORT_SYMBOL_GPL(bus_address_lock);
-+static atomic_long_t bus_nr_socks;
-+
-+#define bus_sockets_unbound (&bus_socket_table[BUS_HASH_SIZE])
-+
-+#define BUS_ABSTRACT(sk) (bus_sk(sk)->addr->hash != BUS_HASH_SIZE)
-+
-+#ifdef CONFIG_SECURITY_NETWORK
-+static void bus_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
-+{
-+ memcpy(BUSSID(skb), &scm->secid, sizeof(u32));
-+}
-+
-+static inline void bus_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
-+{
-+ scm->secid = *BUSSID(skb);
-+}
-+#else
-+static inline void bus_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
-+{ }
-+
-+static inline void bus_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
-+{ }
-+#endif /* CONFIG_SECURITY_NETWORK */
-+
-+/*
-+ * SMP locking strategy:
-+ * bus_socket_table hash table is protected with spinlock bus_table_lock
-+ * bus_address_table hash table is protected with spinlock bus_address_lock
-+ * each bus is protected by a separate spin lock.
-+ * multicast atomic sending is protected by a separate spin lock.
-+ * each socket state is protected by a separate spin lock.
-+ * each socket address is protected by a separate spin lock.
-+ *
-+ * When holding more than one lock, use the following hierarchy:
-+ * - bus_table_lock.
-+ * - bus_address_lock.
-+ * - socket lock.
-+ * - bus lock.
-+ * - bus send_lock.
-+ * - sock address lock.
-+ */
-+
-+#define bus_peer(sk) (bus_sk(sk)->peer)
-+
-+static inline int bus_our_peer(struct sock *sk, struct sock *osk)
-+{
-+ return bus_peer(osk) == sk;
-+}
-+
-+static inline int bus_recvq_full(struct sock const *sk)
-+{
-+ return skb_queue_len(&sk->sk_receive_queue) > sk->sk_max_ack_backlog;
-+}
-+
-+static inline u16 bus_addr_prefix(struct sockaddr_bus *busaddr)
-+{
-+ return (busaddr->sbus_addr.s_addr & BUS_PREFIX_MASK) >> BUS_CLIENT_BITS;
-+}
-+
-+static inline u64 bus_addr_client(struct sockaddr_bus *sbusaddr)
-+{
-+ return sbusaddr->sbus_addr.s_addr & BUS_CLIENT_MASK;
-+}
-+
-+static inline bool bus_mc_addr(struct sockaddr_bus *sbusaddr)
-+{
-+ return bus_addr_client(sbusaddr) == BUS_CLIENT_MASK;
-+}
-+
-+struct sock *bus_peer_get(struct sock *s)
-+{
-+ struct sock *peer;
-+
-+ bus_state_lock(s);
-+ peer = bus_peer(s);
-+ if (peer)
-+ sock_hold(peer);
-+ bus_state_unlock(s);
-+ return peer;
-+}
-+EXPORT_SYMBOL_GPL(bus_peer_get);
-+
-+static inline void bus_release_addr(struct bus_address *addr)
-+{
-+ if (atomic_dec_and_test(&addr->refcnt))
-+ kfree(addr);
-+}
-+
-+/*
-+ * Check bus socket name:
-+ * - should be not zero length.
-+ * - if started by not zero, should be NULL terminated (FS object)
-+ * - if started by zero, it is abstract name.
-+ */
-+
-+static int bus_mkname(struct sockaddr_bus *sbusaddr, int len,
-+ unsigned int *hashp)
-+{
-+ int offset = (sbusaddr->sbus_path[0] == '\0');
-+
-+ if (len <= sizeof(short) || len > sizeof(*sbusaddr))
-+ return -EINVAL;
-+ if (!sbusaddr || sbusaddr->sbus_family != AF_BUS)
-+ return -EINVAL;
-+
-+ len = strnlen(sbusaddr->sbus_path + offset, BUS_PATH_MAX) + 1 +
-+ sizeof(__kernel_sa_family_t) +
-+ sizeof(struct bus_addr);
-+
-+ *hashp = bus_compute_hash(sbusaddr->sbus_addr);
-+ return len;
-+}
-+
-+static void __bus_remove_address(struct bus_address *addr)
-+{
-+ hlist_del(&addr->table_node);
-+}
-+
-+static void __bus_insert_address(struct hlist_head *list,
-+ struct bus_address *addr)
-+{
-+ hlist_add_head(&addr->table_node, list);
-+}
-+
-+static inline void bus_remove_address(struct bus_address *addr)
-+{
-+ spin_lock(&bus_address_lock);
-+ __bus_remove_address(addr);
-+ spin_unlock(&bus_address_lock);
-+}
-+
-+static inline void bus_insert_address(struct hlist_head *list,
-+ struct bus_address *addr)
-+{
-+ spin_lock(&bus_address_lock);
-+ __bus_insert_address(list, addr);
-+ spin_unlock(&bus_address_lock);
-+}
-+
-+static void __bus_remove_socket(struct sock *sk)
-+{
-+ sk_del_node_init(sk);
-+}
-+
-+static void __bus_insert_socket(struct hlist_head *list, struct sock *sk)
-+{
-+ WARN_ON(!sk_unhashed(sk));
-+ sk_add_node(sk, list);
-+}
-+
-+static inline void bus_remove_socket(struct sock *sk)
-+{
-+ spin_lock(&bus_table_lock);
-+ __bus_remove_socket(sk);
-+ spin_unlock(&bus_table_lock);
-+}
-+
-+static inline void bus_insert_socket(struct hlist_head *list, struct sock *sk)
-+{
-+ spin_lock(&bus_table_lock);
-+ __bus_insert_socket(list, sk);
-+ spin_unlock(&bus_table_lock);
-+}
-+
-+static inline bool __bus_has_prefix(struct sock *sk, u16 prefix)
-+{
-+ struct bus_sock *u = bus_sk(sk);
-+ struct bus_address *addr;
-+ struct hlist_node *node;
-+ bool ret = false;
-+
-+ hlist_for_each_entry(addr, node, &u->addr_list, addr_node) {
-+ if (bus_addr_prefix(addr->name) == prefix)
-+ ret = true;
-+ }
-+
-+ return ret;
-+}
-+
-+static inline bool bus_has_prefix(struct sock *sk, u16 prefix)
-+{
-+ bool ret;
-+
-+ bus_state_lock(sk);
-+ ret = __bus_has_prefix(sk, prefix);
-+ bus_state_unlock(sk);
-+
-+ return ret;
-+}
-+
-+static inline bool __bus_eavesdropper(struct sock *sk, u16 condition)
-+{
-+ struct bus_sock *u = bus_sk(sk);
-+
-+ return u->eavesdropper;
-+}
-+
-+static inline bool bus_eavesdropper(struct sock *sk, u16 condition)
-+{
-+ bool ret;
-+
-+ bus_state_lock(sk);
-+ ret = __bus_eavesdropper(sk, condition);
-+ bus_state_unlock(sk);
-+
-+ return ret;
-+}
-+
-+static inline bool bus_has_prefix_eavesdropper(struct sock *sk, u16 prefix)
-+{
-+ bool ret;
-+
-+ bus_state_lock(sk);
-+ ret = __bus_has_prefix(sk, prefix) || __bus_eavesdropper(sk, 0);
-+ bus_state_unlock(sk);
-+
-+ return ret;
-+}
-+
-+static inline struct bus_address *__bus_get_address(struct sock *sk,
-+ struct bus_addr *sbus_addr)
-+{
-+ struct bus_sock *u = bus_sk(sk);
-+ struct bus_address *addr = NULL;
-+ struct hlist_node *node;
-+
-+ hlist_for_each_entry(addr, node, &u->addr_list, addr_node) {
-+ if (addr->name->sbus_addr.s_addr == sbus_addr->s_addr)
-+ return addr;
-+ }
-+
-+ return NULL;
-+}
-+
-+static inline struct bus_address *bus_get_address(struct sock *sk,
-+ struct bus_addr *sbus_addr)
-+{
-+ struct bus_address *addr;
-+
-+ bus_state_lock(sk);
-+ addr = __bus_get_address(sk, sbus_addr);
-+ bus_state_unlock(sk);
-+
-+ return addr;
-+}
-+
-+static struct sock *__bus_find_socket_byname(struct net *net,
-+ struct sockaddr_bus *sbusname,
-+ int len, unsigned int hash)
-+{
-+ struct sock *s;
-+ struct hlist_node *node;
-+
-+ sk_for_each(s, node, &bus_socket_table[hash]) {
-+ struct bus_sock *u = bus_sk(s);
-+
-+ if (!net_eq(sock_net(s), net))
-+ continue;
-+
-+ if (u->addr->len == len &&
-+ !memcmp(u->addr->name, sbusname, len))
-+ return s;
-+ }
-+
-+ return NULL;
-+}
-+
-+static inline struct sock *bus_find_socket_byname(struct net *net,
-+ struct sockaddr_bus *sbusname,
-+ int len, unsigned int hash)
-+{
-+ struct sock *s;
-+
-+ spin_lock(&bus_table_lock);
-+ s = __bus_find_socket_byname(net, sbusname, len, hash);
-+ if (s)
-+ sock_hold(s);
-+ spin_unlock(&bus_table_lock);
-+ return s;
-+}
-+
-+static struct sock *__bus_find_socket_byaddress(struct net *net,
-+ struct sockaddr_bus *sbusname,
-+ int len, int protocol,
-+ unsigned int hash)
-+{
-+ struct sock *s;
-+ struct bus_address *addr;
-+ struct hlist_node *node;
-+ struct bus_sock *u;
-+ int offset = (sbusname->sbus_path[0] == '\0');
-+ int path_len = strnlen(sbusname->sbus_path + offset, BUS_PATH_MAX);
-+
-+ len = path_len + 1 + sizeof(__kernel_sa_family_t) +
-+ sizeof(struct bus_addr);
-+
-+ hlist_for_each_entry(addr, node, &bus_address_table[hash],
-+ table_node) {
-+ s = addr->sock;
-+ u = bus_sk(s);
-+
-+ if (s->sk_protocol != protocol)
-+ continue;
-+
-+ if (!net_eq(sock_net(s), net))
-+ continue;
-+
-+ if (addr->len == len &&
-+ addr->name->sbus_family == sbusname->sbus_family &&
-+ addr->name->sbus_addr.s_addr == sbusname->sbus_addr.s_addr
-+ && bus_same_bus(addr->name, sbusname))
-+ goto found;
-+ }
-+ s = NULL;
-+found:
-+ return s;
-+}
-+
-+static inline struct sock *bus_find_socket_byaddress(struct net *net,
-+ struct sockaddr_bus *name,
-+ int len, int protocol,
-+ unsigned int hash)
-+{
-+ struct sock *s;
-+
-+ spin_lock(&bus_address_lock);
-+ s = __bus_find_socket_byaddress(net, name, len, protocol, hash);
-+ if (s)
-+ sock_hold(s);
-+ spin_unlock(&bus_address_lock);
-+ return s;
-+}
-+
-+static inline int bus_writable(struct sock *sk)
-+{
-+ return (atomic_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
-+}
-+
-+static void bus_write_space(struct sock *sk)
-+{
-+ struct bus_sock *u = bus_sk(sk);
-+ struct bus_sock *p;
-+ struct hlist_node *node;
-+ struct socket_wq *wq;
-+
-+ if (bus_writable(sk)) {
-+ rcu_read_lock();
-+ wq = rcu_dereference(sk->sk_wq);
-+ if (wq_has_sleeper(wq))
-+ wake_up_interruptible_sync_poll(&wq->wait,
-+ POLLOUT | POLLWRNORM | POLLWRBAND);
-+ sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
-+ rcu_read_unlock();
-+
-+ if (u && u->bus) {
-+ spin_lock(&u->bus->lock);
-+ hlist_for_each_entry(p, node, &u->bus->peers,
-+ bus_node) {
-+ wake_up_interruptible_sync_poll(sk_sleep(&p->sk),
-+ POLLOUT |
-+ POLLWRNORM |
-+ POLLWRBAND);
-+ sk_wake_async(&p->sk, SOCK_WAKE_SPACE,
-+ POLL_OUT);
-+ }
-+ spin_unlock(&u->bus->lock);
-+ }
-+ }
-+}
-+
-+static void bus_bus_release(struct kref *kref)
-+{
-+ struct bus *bus;
-+
-+ bus = container_of(kref, struct bus, kref);
-+
-+ kfree(bus);
-+}
-+
-+static void bus_sock_destructor(struct sock *sk)
-+{
-+ struct bus_sock *u = bus_sk(sk);
-+
-+ skb_queue_purge(&sk->sk_receive_queue);
-+
-+ WARN_ON(atomic_read(&sk->sk_wmem_alloc));
-+ WARN_ON(!sk_unhashed(sk));
-+ WARN_ON(sk->sk_socket);
-+ if (!sock_flag(sk, SOCK_DEAD)) {
-+ pr_info("Attempt to release alive bus socket: %p\n", sk);
-+ return;
-+ }
-+
-+ if (u->bus) {
-+ kref_put(&u->bus->kref, bus_bus_release);
-+ u->bus = NULL;
-+ }
-+
-+ atomic_long_dec(&bus_nr_socks);
-+ local_bh_disable();
-+ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
-+ local_bh_enable();
-+#ifdef BUS_REFCNT_DEBUG
-+ pr_debug("BUS %p is destroyed, %ld are still alive.\n", sk,
-+ atomic_long_read(&bus_nr_socks));
-+#endif
-+}
-+
-+static int bus_release_sock(struct sock *sk, int embrion)
-+{
-+ struct bus_sock *u = bus_sk(sk);
-+ struct path path;
-+ struct sock *skpair;
-+ struct sk_buff *skb;
-+ int state;
-+ struct bus_address *addr;
-+ struct hlist_node *node, *tmp;
-+
-+ bus_remove_socket(sk);
-+
-+ if (u->bus && u->authenticated &&
-+ !u->bus_master && !u->bus_master_side) {
-+ spin_lock(&u->bus->lock);
-+ hlist_del(&u->bus_node);
-+ if (u->eavesdropper)
-+ atomic64_dec(&u->bus->eavesdropper_cnt);
-+ spin_unlock(&u->bus->lock);
-+ }
-+
-+ /* Clear state */
-+ bus_state_lock(sk);
-+ sock_orphan(sk);
-+ sk->sk_shutdown = SHUTDOWN_MASK;
-+ path = u->path;
-+ u->path.dentry = NULL;
-+ u->path.mnt = NULL;
-+ state = sk->sk_state;
-+ sk->sk_state = BUS_CLOSE;
-+
-+ if (u->bus_master)
-+ u->bus->master = NULL;
-+
-+ if (u->bus_master_side) {
-+ bus_release_addr(u->addr);
-+ u->addr = NULL;
-+ } else {
-+ u->addr = NULL;
-+
-+ spin_lock(&bus_address_lock);
-+ hlist_for_each_entry_safe(addr, node, tmp, &u->addr_list,
-+ addr_node) {
-+ hlist_del(&addr->addr_node);
-+ __bus_remove_address(addr);
-+ bus_release_addr(addr);
-+ }
-+ spin_unlock(&bus_address_lock);
-+ }
-+
-+ bus_state_unlock(sk);
-+
-+ wake_up_interruptible_all(&u->peer_wait);
-+
-+ skpair = bus_peer(sk);
-+
-+ if (skpair != NULL) {
-+ bus_state_lock(skpair);
-+ /* No more writes */
-+ skpair->sk_shutdown = SHUTDOWN_MASK;
-+ if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
-+ skpair->sk_err = ECONNRESET;
-+ bus_state_unlock(skpair);
-+ skpair->sk_state_change(skpair);
-+ sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
-+ sock_put(skpair); /* It may now die */
-+ bus_peer(sk) = NULL;
-+ }
-+
-+ /* Try to flush out this socket. Throw out buffers at least */
-+
-+ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
-+ if (state == BUS_LISTEN)
-+ bus_release_sock(skb->sk, 1);
-+ /* passed fds are erased in the kfree_skb hook */
-+ kfree_skb(skb);
-+ }
-+
-+ if (path.dentry)
-+ path_put(&path);
-+
-+ sock_put(sk);
-+
-+ /* ---- Socket is dead now and most probably destroyed ---- */
-+
-+ if (bus_tot_inflight)
-+ bus_gc(); /* Garbage collect fds */
-+
-+ return 0;
-+}
-+
-+static void init_peercred(struct sock *sk)
-+{
-+ put_pid(sk->sk_peer_pid);
-+ if (sk->sk_peer_cred)
-+ put_cred(sk->sk_peer_cred);
-+ sk->sk_peer_pid = get_pid(task_tgid(current));
-+ sk->sk_peer_cred = get_current_cred();
-+}
-+
-+static void copy_peercred(struct sock *sk, struct sock *peersk)
-+{
-+ put_pid(sk->sk_peer_pid);
-+ if (sk->sk_peer_cred)
-+ put_cred(sk->sk_peer_cred);
-+ sk->sk_peer_pid = get_pid(peersk->sk_peer_pid);
-+ sk->sk_peer_cred = get_cred(peersk->sk_peer_cred);
-+}
-+
-+static int bus_listen(struct socket *sock, int backlog)
-+{
-+ int err;
-+ struct sock *sk = sock->sk;
-+ struct bus_sock *u = bus_sk(sk);
-+ struct pid *old_pid = NULL;
-+ const struct cred *old_cred = NULL;
-+
-+ err = -EINVAL;
-+ if (!u->addr || !u->bus_master)
-+ goto out; /* Only listens on an bound an master socket */
-+ bus_state_lock(sk);
-+ if (sk->sk_state != BUS_CLOSE && sk->sk_state != BUS_LISTEN)
-+ goto out_unlock;
-+ if (backlog > sk->sk_max_ack_backlog)
-+ wake_up_interruptible_all(&u->peer_wait);
-+ sk->sk_max_ack_backlog = backlog;
-+ sk->sk_state = BUS_LISTEN;
-+ /* set credentials so connect can copy them */
-+ init_peercred(sk);
-+ err = 0;
-+
-+out_unlock:
-+ bus_state_unlock(sk);
-+ put_pid(old_pid);
-+ if (old_cred)
-+ put_cred(old_cred);
-+out:
-+ return err;
-+}
-+
-+static int bus_release(struct socket *);
-+static int bus_bind(struct socket *, struct sockaddr *, int);
-+static int bus_connect(struct socket *, struct sockaddr *,
-+ int addr_len, int flags);
-+static int bus_accept(struct socket *, struct socket *, int);
-+static int bus_getname(struct socket *, struct sockaddr *, int *, int);
-+static unsigned int bus_poll(struct file *, struct socket *,
-+ poll_table *);
-+static int bus_ioctl(struct socket *, unsigned int, unsigned long);
-+static int bus_shutdown(struct socket *, int);
-+static int bus_setsockopt(struct socket *, int, int, char __user *,
-+ unsigned int);
-+static int bus_sendmsg(struct kiocb *, struct socket *,
-+ struct msghdr *, size_t);
-+static int bus_recvmsg(struct kiocb *, struct socket *,
-+ struct msghdr *, size_t, int);
-+
-+static void bus_set_peek_off(struct sock *sk, int val)
-+{
-+ struct bus_sock *u = bus_sk(sk);
-+
-+ mutex_lock(&u->readlock);
-+ sk->sk_peek_off = val;
-+ mutex_unlock(&u->readlock);
-+}
-+
-+static const struct proto_ops bus_seqpacket_ops = {
-+ .family = PF_BUS,
-+ .owner = THIS_MODULE,
-+ .release = bus_release,
-+ .bind = bus_bind,
-+ .connect = bus_connect,
-+ .socketpair = sock_no_socketpair,
-+ .accept = bus_accept,
-+ .getname = bus_getname,
-+ .poll = bus_poll,
-+ .ioctl = bus_ioctl,
-+ .listen = bus_listen,
-+ .shutdown = bus_shutdown,
-+ .setsockopt = bus_setsockopt,
-+ .getsockopt = sock_no_getsockopt,
-+ .sendmsg = bus_sendmsg,
-+ .recvmsg = bus_recvmsg,
-+ .mmap = sock_no_mmap,
-+ .sendpage = sock_no_sendpage,
-+ .set_peek_off = bus_set_peek_off,
-+};
-+
-+static struct proto bus_proto = {
-+ .name = "BUS",
-+ .owner = THIS_MODULE,
-+ .obj_size = sizeof(struct bus_sock),
-+};
-+
-+/*
-+ * AF_BUS sockets do not interact with hardware, hence they
-+ * dont trigger interrupts - so it's safe for them to have
-+ * bh-unsafe locking for their sk_receive_queue.lock. Split off
-+ * this special lock-class by reinitializing the spinlock key:
-+ */
-+static struct lock_class_key af_bus_sk_receive_queue_lock_key;
-+
-+static struct sock *bus_create1(struct net *net, struct socket *sock)
-+{
-+ struct sock *sk = NULL;
-+ struct bus_sock *u;
-+
-+ atomic_long_inc(&bus_nr_socks);
-+ if (atomic_long_read(&bus_nr_socks) > 2 * get_max_files())
-+ goto out;
-+
-+ sk = sk_alloc(net, PF_BUS, GFP_KERNEL, &bus_proto);
-+ if (!sk)
-+ goto out;
-+
-+ sock_init_data(sock, sk);
-+ lockdep_set_class(&sk->sk_receive_queue.lock,
-+ &af_bus_sk_receive_queue_lock_key);
-+
-+ sk->sk_write_space = bus_write_space;
-+ sk->sk_max_ack_backlog = BUS_MAX_QLEN;
-+ sk->sk_destruct = bus_sock_destructor;
-+ u = bus_sk(sk);
-+ u->path.dentry = NULL;
-+ u->path.mnt = NULL;
-+ u->bus = NULL;
-+ u->bus_master = false;
-+ u->authenticated = false;
-+ u->eavesdropper = false;
-+ spin_lock_init(&u->lock);
-+ atomic_long_set(&u->inflight, 0);
-+ INIT_LIST_HEAD(&u->link);
-+ INIT_HLIST_HEAD(&u->addr_list);
-+ INIT_HLIST_NODE(&u->bus_node);
-+ mutex_init(&u->readlock); /* single task reading lock */
-+ init_waitqueue_head(&u->peer_wait);
-+ bus_insert_socket(bus_sockets_unbound, sk);
-+out:
-+ if (sk == NULL)
-+ atomic_long_dec(&bus_nr_socks);
-+ else {
-+ local_bh_disable();
-+ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
-+ local_bh_enable();
-+ }
-+ return sk;
-+}
-+
-+static int bus_create(struct net *net, struct socket *sock, int protocol,
-+ int kern)
-+{
-+ struct sock *sk;
-+
-+ if (protocol < BUS_PROTO_NONE || protocol > BUS_PROTO_DBUS)
-+ return -EPROTONOSUPPORT;
-+
-+ if (protocol != BUS_PROTO_NONE)
-+ request_module("net-pf-%d-proto-%d", PF_BUS, protocol);
-+
-+ sock->state = SS_UNCONNECTED;
-+
-+ if (sock->type == SOCK_SEQPACKET)
-+ sock->ops = &bus_seqpacket_ops;
-+ else
-+ return -ESOCKTNOSUPPORT;
-+
-+ sk = bus_create1(net, sock);
-+ if (!sk)
-+ return -ENOMEM;
-+
-+ sk->sk_protocol = protocol;
-+
-+ return 0;
-+}
-+
-+static int bus_release(struct socket *sock)
-+{
-+ struct sock *sk = sock->sk;
-+
-+ if (!sk)
-+ return 0;
-+
-+ sock->sk = NULL;
-+
-+ return bus_release_sock(sk, 0);
-+}
-+
-+static struct sock *bus_find_other(struct net *net,
-+ struct sockaddr_bus *sbusname, int len,
-+ int protocol, unsigned int hash, int *error)
-+{
-+ struct sock *u;
-+ struct path path;
-+ int err = 0;
-+
-+ if (sbusname->sbus_path[0]) {
-+ struct inode *inode;
-+ err = kern_path(sbusname->sbus_path, LOOKUP_FOLLOW, &path);
-+ if (err)
-+ goto fail;
-+ inode = path.dentry->d_inode;
-+ err = inode_permission(inode, MAY_WRITE);
-+ if (err)
-+ goto put_fail;
-+
-+ err = -ECONNREFUSED;
-+ if (!S_ISSOCK(inode->i_mode))
-+ goto put_fail;
-+ u = bus_find_socket_byaddress(net, sbusname, len, protocol,
-+ hash);
-+ if (!u)
-+ goto put_fail;
-+
-+ touch_atime(&path);
-+ path_put(&path);
-+
-+ } else {
-+ err = -ECONNREFUSED;
-+ u = bus_find_socket_byaddress(net, sbusname, len, protocol, hash);
-+ if (u) {
-+ struct dentry *dentry;
-+ dentry = bus_sk(u)->path.dentry;
-+ if (dentry)
-+ touch_atime(&bus_sk(u)->path);
-+ } else
-+ goto fail;
-+ }
-+
-+ return u;
-+
-+put_fail:
-+ path_put(&path);
-+fail:
-+ *error = err;
-+ return NULL;
-+}
-+
-+
-+static int bus_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
-+{
-+ struct sock *sk = sock->sk;
-+ struct net *net = sock_net(sk);
-+ struct bus_sock *u = bus_sk(sk);
-+ struct sockaddr_bus *sbusaddr = (struct sockaddr_bus *)uaddr;
-+ char *sbus_path = sbusaddr->sbus_path;
-+ struct dentry *dentry = NULL;
-+ struct path path;
-+ int err;
-+ unsigned int hash;
-+ struct bus_address *addr;
-+ struct hlist_head *list;
-+ struct bus *bus;
-+
-+ err = -EINVAL;
-+ if (sbusaddr->sbus_family != AF_BUS)
-+ goto out;
-+
-+ /* If the address is available, the socket is the bus master */
-+ sbusaddr->sbus_addr.s_addr = BUS_MASTER_ADDR;
-+
-+ err = bus_mkname(sbusaddr, addr_len, &hash);
-+ if (err < 0)
-+ goto out;
-+ addr_len = err;
-+
-+ mutex_lock(&u->readlock);
-+
-+ err = -EINVAL;
-+ if (u->addr)
-+ goto out_up;
-+
-+ err = -ENOMEM;
-+ addr = kzalloc(sizeof(*addr) + sizeof(struct sockaddr_bus), GFP_KERNEL);
-+ if (!addr)
-+ goto out_up;
-+
-+ memcpy(addr->name, sbusaddr, sizeof(struct sockaddr_bus));
-+ addr->len = addr_len;
-+ addr->hash = hash;
-+ atomic_set(&addr->refcnt, 1);
-+ addr->sock = sk;
-+ INIT_HLIST_NODE(&addr->addr_node);
-+ INIT_HLIST_NODE(&addr->table_node);
-+
-+ if (sbus_path[0]) {
-+ umode_t mode;
-+ err = 0;
-+ /*
-+ * Get the parent directory, calculate the hash for last
-+ * component.
-+ */
-+ dentry = kern_path_create(AT_FDCWD, sbus_path, &path, 0);
-+ err = PTR_ERR(dentry);
-+ if (IS_ERR(dentry))
-+ goto out_mknod_parent;
-+
-+ /*
-+ * All right, let's create it.
-+ */
-+ mode = S_IFSOCK |
-+ (SOCK_INODE(sock)->i_mode & ~current_umask());
-+ err = mnt_want_write(path.mnt);
-+ if (err)
-+ goto out_mknod_dput;
-+ err = security_path_mknod(&path, dentry, mode, 0);
-+ if (err)
-+ goto out_mknod_drop_write;
-+ err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0);
-+out_mknod_drop_write:
-+ mnt_drop_write(path.mnt);
-+ if (err)
-+ goto out_mknod_dput;
-+ mutex_unlock(&path.dentry->d_inode->i_mutex);
-+ dput(path.dentry);
-+ path.dentry = dentry;
-+ }
-+
-+ err = -ENOMEM;
-+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
-+ if (!bus)
-+ goto out_unlock;
-+
-+ spin_lock(&bus_table_lock);
-+
-+ if (!sbus_path[0]) {
-+ err = -EADDRINUSE;
-+ if (__bus_find_socket_byname(net, sbusaddr, addr_len, hash)) {
-+ bus_release_addr(addr);
-+ kfree(bus);
-+ goto out_unlock;
-+ }
-+
-+ list = &bus_socket_table[addr->hash];
-+ } else {
-+ list = &bus_socket_table[dentry->d_inode->i_ino &
-+ (BUS_HASH_SIZE-1)];
-+ u->path = path;
-+ }
-+
-+ kref_init(&bus->kref);
-+ bus->master = sk;
-+ INIT_HLIST_HEAD(&bus->peers);
-+ spin_lock_init(&bus->lock);
-+ spin_lock_init(&bus->send_lock);
-+ atomic64_set(&bus->addr_cnt, 0);
-+ atomic64_set(&bus->eavesdropper_cnt, 0);
-+
-+ hlist_add_head(&addr->addr_node, &u->addr_list);
-+
-+ err = 0;
-+ __bus_remove_socket(sk);
-+ u->addr = addr;
-+ u->bus_master = true;
-+ u->bus = bus;
-+ __bus_insert_socket(list, sk);
-+ bus_insert_address(&bus_address_table[addr->hash], addr);
-+
-+out_unlock:
-+ spin_unlock(&bus_table_lock);
-+out_up:
-+ mutex_unlock(&u->readlock);
-+out:
-+ return err;
-+
-+out_mknod_dput:
-+ dput(dentry);
-+ mutex_unlock(&path.dentry->d_inode->i_mutex);
-+ path_put(&path);
-+out_mknod_parent:
-+ if (err == -EEXIST)
-+ err = -EADDRINUSE;
-+ bus_release_addr(addr);
-+ goto out_up;
-+}
-+
-+static long bus_wait_for_peer(struct sock *other, long timeo)
-+{
-+ struct bus_sock *u = bus_sk(other);
-+ int sched;
-+ DEFINE_WAIT(wait);
-+
-+ prepare_to_wait_exclusive(&u->peer_wait, &wait, TASK_INTERRUPTIBLE);
-+
-+ sched = !sock_flag(other, SOCK_DEAD) &&
-+ !(other->sk_shutdown & RCV_SHUTDOWN) &&
-+ bus_recvq_full(other);
-+
-+ bus_state_unlock(other);
-+
-+ if (sched)
-+ timeo = schedule_timeout(timeo);
-+
-+ finish_wait(&u->peer_wait, &wait);
-+ return timeo;
-+}
-+
-+static int bus_connect(struct socket *sock, struct sockaddr *uaddr,
-+ int addr_len, int flags)
-+{
-+ struct sockaddr_bus *sbusaddr = (struct sockaddr_bus *)uaddr;
-+ struct sock *sk = sock->sk;
-+ struct net *net = sock_net(sk);
-+ struct bus_sock *u = bus_sk(sk), *newu, *otheru;
-+ struct sock *newsk = NULL;
-+ struct sock *other = NULL;
-+ struct sk_buff *skb = NULL;
-+ struct bus_address *addr = NULL;
-+ unsigned int hash;
-+ int st;
-+ int err;
-+ long timeo;
-+
-+ /* Only connections to the bus master is allowed */
-+ sbusaddr->sbus_addr.s_addr = BUS_MASTER_ADDR;
-+
-+ err = bus_mkname(sbusaddr, addr_len, &hash);
-+ if (err < 0)
-+ goto out;
-+ addr_len = err;
-+
-+ err = -ENOMEM;
-+ addr = kzalloc(sizeof(*addr) + sizeof(struct sockaddr_bus), GFP_KERNEL);
-+ if (!addr)
-+ goto out;
-+
-+ atomic_set(&addr->refcnt, 1);
-+ INIT_HLIST_NODE(&addr->addr_node);
-+ INIT_HLIST_NODE(&addr->table_node);
-+
-+ timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
-+
-+ /* First of all allocate resources.
-+ If we will make it after state is locked,
-+ we will have to recheck all again in any case.
-+ */
-+
-+ err = -ENOMEM;
-+
-+ /* create new sock for complete connection */
-+ newsk = bus_create1(sock_net(sk), NULL);
-+ if (newsk == NULL)
-+ goto out;
-+
-+ /* Allocate skb for sending to listening sock */
-+ skb = sock_wmalloc(newsk, 1, 0, GFP_KERNEL);
-+ if (skb == NULL)
-+ goto out;
-+
-+restart:
-+ /* Find listening sock. */
-+ other = bus_find_other(net, sbusaddr, addr_len, sk->sk_protocol, hash,
-+ &err);
-+ if (!other)
-+ goto out;
-+
-+ /* Latch state of peer */
-+ bus_state_lock(other);
-+
-+ /* Apparently VFS overslept socket death. Retry. */
-+ if (sock_flag(other, SOCK_DEAD)) {
-+ bus_state_unlock(other);
-+ sock_put(other);
-+ goto restart;
-+ }
-+
-+ err = -ECONNREFUSED;
-+ if (other->sk_state != BUS_LISTEN)
-+ goto out_unlock;
-+ if (other->sk_shutdown & RCV_SHUTDOWN)
-+ goto out_unlock;
-+
-+ if (bus_recvq_full(other)) {
-+ err = -EAGAIN;
-+ if (!timeo)
-+ goto out_unlock;
-+
-+ timeo = bus_wait_for_peer(other, timeo);
-+
-+ err = sock_intr_errno(timeo);
-+ if (signal_pending(current))
-+ goto out;
-+ sock_put(other);
-+ goto restart;
-+ }
-+
-+ /* Latch our state.
-+
-+ It is tricky place. We need to grab our state lock and cannot
-+ drop lock on peer. It is dangerous because deadlock is
-+ possible. Connect to self case and simultaneous
-+ attempt to connect are eliminated by checking socket
-+ state. other is BUS_LISTEN, if sk is BUS_LISTEN we
-+ check this before attempt to grab lock.
-+
-+ Well, and we have to recheck the state after socket locked.
-+ */
-+ st = sk->sk_state;
-+
-+ switch (st) {
-+ case BUS_CLOSE:
-+ /* This is ok... continue with connect */
-+ break;
-+ case BUS_ESTABLISHED:
-+ /* Socket is already connected */
-+ err = -EISCONN;
-+ goto out_unlock;
-+ default:
-+ err = -EINVAL;
-+ goto out_unlock;
-+ }
-+
-+ bus_state_lock_nested(sk);
-+
-+ if (sk->sk_state != st) {
-+ bus_state_unlock(sk);
-+ bus_state_unlock(other);
-+ sock_put(other);
-+ goto restart;
-+ }
-+
-+ err = security_bus_connect(sk, other, newsk);
-+ if (err) {
-+ bus_state_unlock(sk);
-+ goto out_unlock;
-+ }
-+
-+ /* The way is open! Fastly set all the necessary fields... */
-+
-+ sock_hold(sk);
-+ bus_peer(newsk) = sk;
-+ newsk->sk_state = BUS_ESTABLISHED;
-+ newsk->sk_type = sk->sk_type;
-+ newsk->sk_protocol = sk->sk_protocol;
-+ init_peercred(newsk);
-+ newu = bus_sk(newsk);
-+ RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq);
-+ otheru = bus_sk(other);
-+
-+ /* copy address information from listening to new sock*/
-+ if (otheru->addr && otheru->bus_master) {
-+ atomic_inc(&otheru->addr->refcnt);
-+ newu->addr = otheru->addr;
-+ memcpy(addr->name, otheru->addr->name,
-+ sizeof(struct sockaddr_bus));
-+ addr->len = otheru->addr->len;
-+ addr->name->sbus_addr.s_addr =
-+ (atomic64_inc_return(&otheru->bus->addr_cnt) &
-+ BUS_CLIENT_MASK);
-+ addr->hash = bus_compute_hash(addr->name->sbus_addr);
-+ addr->sock = sk;
-+ u->addr = addr;
-+ kref_get(&otheru->bus->kref);
-+ u->bus = otheru->bus;
-+ u->bus_master_side = false;
-+ kref_get(&otheru->bus->kref);
-+ newu->bus = otheru->bus;
-+ newu->bus_master_side = true;
-+ hlist_add_head(&addr->addr_node, &u->addr_list);
-+
-+ bus_insert_address(&bus_address_table[addr->hash], addr);
-+ }
-+ if (otheru->path.dentry) {
-+ path_get(&otheru->path);
-+ newu->path = otheru->path;
-+ }
-+
-+ /* Set credentials */
-+ copy_peercred(sk, other);
-+ sk->sk_sndbuf = other->sk_sndbuf;
-+ sk->sk_max_ack_backlog = other->sk_max_ack_backlog;
-+ newsk->sk_sndbuf = other->sk_sndbuf;
-+
-+ sock->state = SS_CONNECTED;
-+ sk->sk_state = BUS_ESTABLISHED;
-+ sock_hold(newsk);
-+
-+ smp_mb__after_atomic_inc(); /* sock_hold() does an atomic_inc() */
-+ bus_peer(sk) = newsk;
-+
-+ bus_state_unlock(sk);
-+
-+ /* take ten and and send info to listening sock */
-+ spin_lock(&other->sk_receive_queue.lock);
-+ __skb_queue_tail(&other->sk_receive_queue, skb);
-+ spin_unlock(&other->sk_receive_queue.lock);
-+ bus_state_unlock(other);
-+ other->sk_data_ready(other, 0);
-+ sock_put(other);
-+ return 0;
-+
-+out_unlock:
-+ if (other)
-+ bus_state_unlock(other);
-+
-+out:
-+ kfree_skb(skb);
-+ if (addr)
-+ bus_release_addr(addr);
-+ if (newsk)
-+ bus_release_sock(newsk, 0);
-+ if (other)
-+ sock_put(other);
-+ return err;
-+}
-+
-+static int bus_accept(struct socket *sock, struct socket *newsock, int flags)
-+{
-+ struct sock *sk = sock->sk;
-+ struct sock *tsk;
-+ struct sk_buff *skb;
-+ int err;
-+
-+ err = -EINVAL;
-+ if (sk->sk_state != BUS_LISTEN)
-+ goto out;
-+
-+ /* If socket state is BUS_LISTEN it cannot change (for now...),
-+ * so that no locks are necessary.
-+ */
-+
-+ skb = skb_recv_datagram(sk, 0, flags&O_NONBLOCK, &err);
-+ if (!skb) {
-+ /* This means receive shutdown. */
-+ if (err == 0)
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ tsk = skb->sk;
-+ skb_free_datagram(sk, skb);
-+ wake_up_interruptible(&bus_sk(sk)->peer_wait);
-+
-+ /* attach accepted sock to socket */
-+ bus_state_lock(tsk);
-+ newsock->state = SS_CONNECTED;
-+ sock_graft(tsk, newsock);
-+ bus_state_unlock(tsk);
-+ return 0;
-+
-+out:
-+ return err;
-+}
-+
-+
-+static int bus_getname(struct socket *sock, struct sockaddr *uaddr,
-+ int *uaddr_len, int peer)
-+{
-+ struct sock *sk = sock->sk;
-+ struct bus_sock *u;
-+ DECLARE_SOCKADDR(struct sockaddr_bus *, sbusaddr, uaddr);
-+ int err = 0;
-+
-+ if (peer) {
-+ sk = bus_peer_get(sk);
-+
-+ err = -ENOTCONN;
-+ if (!sk)
-+ goto out;
-+ err = 0;
-+ } else {
-+ sock_hold(sk);
-+ }
-+
-+ u = bus_sk(sk);
-+
-+ bus_state_lock(sk);
-+ if (!u->addr) {
-+ sbusaddr->sbus_family = AF_BUS;
-+ sbusaddr->sbus_path[0] = 0;
-+ *uaddr_len = sizeof(short);
-+ } else {
-+ struct bus_address *addr = u->addr;
-+
-+ *uaddr_len = sizeof(struct sockaddr_bus);
-+ memcpy(sbusaddr, addr->name, *uaddr_len);
-+ }
-+ bus_state_unlock(sk);
-+ sock_put(sk);
-+out:
-+ return err;
-+}
-+
-+static void bus_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
-+{
-+ int i;
-+
-+ scm->fp = BUSCB(skb).fp;
-+ BUSCB(skb).fp = NULL;
-+
-+ for (i = scm->fp->count-1; i >= 0; i--)
-+ bus_notinflight(scm->fp->fp[i]);
-+}
-+
-+static void bus_destruct_scm(struct sk_buff *skb)
-+{
-+ struct scm_cookie scm;
-+ memset(&scm, 0, sizeof(scm));
-+ scm.pid = BUSCB(skb).pid;
-+ scm.cred = BUSCB(skb).cred;
-+ if (BUSCB(skb).fp)
-+ bus_detach_fds(&scm, skb);
-+
-+ scm_destroy(&scm);
-+ if (skb->sk)
-+ sock_wfree(skb);
-+}
-+
-+#define MAX_RECURSION_LEVEL 4
-+
-+static int bus_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
-+{
-+ int i;
-+ unsigned char max_level = 0;
-+ int bus_sock_count = 0;
-+
-+ for (i = scm->fp->count - 1; i >= 0; i--) {
-+ struct sock *sk = bus_get_socket(scm->fp->fp[i]);
-+
-+ if (sk) {
-+ bus_sock_count++;
-+ max_level = max(max_level,
-+ bus_sk(sk)->recursion_level);
-+ }
-+ }
-+ if (unlikely(max_level > MAX_RECURSION_LEVEL))
-+ return -ETOOMANYREFS;
-+
-+ /*
-+ * Need to duplicate file references for the sake of garbage
-+ * collection. Otherwise a socket in the fps might become a
-+ * candidate for GC while the skb is not yet queued.
-+ */
-+ BUSCB(skb).fp = scm_fp_dup(scm->fp);
-+ if (!BUSCB(skb).fp)
-+ return -ENOMEM;
-+
-+ if (bus_sock_count) {
-+ for (i = scm->fp->count - 1; i >= 0; i--)
-+ bus_inflight(scm->fp->fp[i]);
-+ }
-+ return max_level;
-+}
-+
-+static int bus_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb,
-+ bool send_fds)
-+{
-+ int err = 0;
-+
-+ BUSCB(skb).pid = get_pid(scm->pid);
-+ if (scm->cred)
-+ BUSCB(skb).cred = get_cred(scm->cred);
-+ BUSCB(skb).fp = NULL;
-+ if (scm->fp && send_fds)
-+ err = bus_attach_fds(scm, skb);
-+
-+ skb->destructor = bus_destruct_scm;
-+ return err;
-+}
-+
-+/*
-+ * Some apps rely on write() giving SCM_CREDENTIALS
-+ * We include credentials if source or destination socket
-+ * asserted SOCK_PASSCRED.
-+ */
-+static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
-+ const struct sock *other)
-+{
-+ if (BUSCB(skb).cred)
-+ return;
-+ if (test_bit(SOCK_PASSCRED, &sock->flags) ||
-+ !other->sk_socket ||
-+ test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) {
-+ BUSCB(skb).pid = get_pid(task_tgid(current));
-+ BUSCB(skb).cred = get_current_cred();
-+ }
-+}
-+
-+/*
-+ * Send AF_BUS data.
-+ */
-+
-+static void bus_deliver_skb(struct sk_buff *skb)
-+{
-+ struct bus_send_context *sendctx = BUSCB(skb).sendctx;
-+ struct socket *sock = sendctx->sender_socket;
-+
-+ if (sock_flag(sendctx->other, SOCK_RCVTSTAMP))
-+ __net_timestamp(skb);
-+ maybe_add_creds(skb, sock, sendctx->other);
-+ skb_queue_tail(&sendctx->other->sk_receive_queue, skb);
-+ if (sendctx->max_level > bus_sk(sendctx->other)->recursion_level)
-+ bus_sk(sendctx->other)->recursion_level = sendctx->max_level;
-+}
-+
-+/**
-+ * bus_sendmsg_finish - delivery an skb to a destination
-+ * @skb: sk_buff to deliver
-+ *
-+ * Delivers a packet to a destination. The skb control buffer has
-+ * all the information about the destination contained on sending
-+ * context. If the sending is unicast, then the skb is delivered
-+ * and the receiver notified but if the sending is multicast, the
-+ * skb is just marked as delivered and the actual delivery is made
-+ * outside the function with the bus->send_lock held to ensure that
-+ * the multicast sending is atomic.
-+ */
-+static int bus_sendmsg_finish(struct sk_buff *skb)
-+{
-+ int err;
-+ struct bus_send_context *sendctx;
-+ struct socket *sock;
-+ struct sock *sk;
-+ struct net *net;
-+ size_t len = skb->len;
-+
-+ sendctx = BUSCB(skb).sendctx;
-+ sock = sendctx->sender_socket;
-+ sk = sock->sk;
-+ net = sock_net(sk);
-+
-+restart:
-+ if (!sendctx->other) {
-+ err = -ECONNRESET;
-+ if (sendctx->recipient == NULL)
-+ goto out_free;
-+
-+ sendctx->other = bus_find_other(net, sendctx->recipient,
-+ sendctx->namelen,
-+ sk->sk_protocol,
-+ sendctx->hash, &err);
-+
-+ if (sendctx->other == NULL ||
-+ !bus_sk(sendctx->other)->authenticated) {
-+
-+ if (sendctx->other)
-+ sock_put(sendctx->other);
-+
-+ if (!bus_sk(sk)->bus_master_side) {
-+ err = -ENOTCONN;
-+ sendctx->other = bus_peer_get(sk);
-+ if (!sendctx->other)
-+ goto out_free;
-+ } else {
-+ sendctx->other = sk;
-+ sock_hold(sendctx->other);
-+ }
-+ }
-+ }
-+
-+ if (sk_filter(sendctx->other, skb) < 0) {
-+ /* Toss the packet but do not return any error to the sender */
-+ err = len;
-+ goto out_free;
-+ }
-+
-+ bus_state_lock(sendctx->other);
-+
-+ if (sock_flag(sendctx->other, SOCK_DEAD)) {
-+ /*
-+ * Check with 1003.1g - what should
-+ * datagram error
-+ */
-+ bus_state_unlock(sendctx->other);
-+ sock_put(sendctx->other);
-+
-+ err = 0;
-+ bus_state_lock(sk);
-+ if (bus_peer(sk) == sendctx->other) {
-+ bus_peer(sk) = NULL;
-+ bus_state_unlock(sk);
-+ sock_put(sendctx->other);
-+ err = -ECONNREFUSED;
-+ } else {
-+ bus_state_unlock(sk);
-+ }
-+
-+ sendctx->other = NULL;
-+ if (err)
-+ goto out_free;
-+ goto restart;
-+ }
-+
-+ err = -EPIPE;
-+ if (sendctx->other->sk_shutdown & RCV_SHUTDOWN)
-+ goto out_unlock;
-+
-+ if (bus_recvq_full(sendctx->other)) {
-+ if (!sendctx->timeo) {
-+ err = -EAGAIN;
-+ goto out_unlock;
-+ }
-+
-+ sendctx->timeo = bus_wait_for_peer(sendctx->other,
-+ sendctx->timeo);
-+
-+ err = sock_intr_errno(sendctx->timeo);
-+ if (signal_pending(current))
-+ goto out_free;
-+
-+ goto restart;
-+ }
-+
-+ if (!sendctx->multicast && !sendctx->eavesdropper) {
-+ bus_deliver_skb(skb);
-+ bus_state_unlock(sendctx->other);
-+ sendctx->other->sk_data_ready(sendctx->other, 0);
-+ sock_put(sendctx->other);
-+ } else {
-+ sendctx->deliver = 1;
-+ bus_state_unlock(sendctx->other);
-+ }
-+
-+ return len;
-+
-+out_unlock:
-+ bus_state_unlock(sendctx->other);
-+out_free:
-+ kfree_skb(skb);
-+ if (sendctx->other)
-+ sock_put(sendctx->other);
-+
-+ return err;
-+}
-+
-+/**
-+ * bus_sendmsg_mcast - do a multicast sending
-+ * @skb: sk_buff to deliver
-+ *
-+ * Send a packet to a multicast destination.
-+ * The function is also called for unicast sending when eavesdropping
-+ * is enabled. Since the unicast destination and the eavesdroppers
-+ * have to receive the packet atomically.
-+ */
-+static int bus_sendmsg_mcast(struct sk_buff *skb)
-+{
-+ struct bus_send_context *sendctx;
-+ struct bus_send_context *tmpctx;
-+ struct socket *sock;
-+ struct sock *sk;
-+ struct net *net;
-+ struct bus_sock *u, *s;
-+ struct hlist_node *node;
-+ u16 prefix = 0;
-+ struct sk_buff **skb_set = NULL;
-+ struct bus_send_context **sendctx_set = NULL;
-+ int rcp_cnt, send_cnt;
-+ int i;
-+ int err;
-+ int len = skb->len;
-+ bool (*is_receiver) (struct sock *, u16);
-+ bool main_rcp_found = false;
-+
-+ sendctx = BUSCB(skb).sendctx;
-+ sendctx->deliver = 0;
-+ sock = sendctx->sender_socket;
-+ sk = sock->sk;
-+ u = bus_sk(sk);
-+ net = sock_net(sk);
-+
-+ if (sendctx->multicast) {
-+ prefix = bus_addr_prefix(sendctx->recipient);
-+ if (sendctx->eavesdropper)
-+ is_receiver = &bus_has_prefix_eavesdropper;
-+ else
-+ is_receiver = &bus_has_prefix;
-+ } else {
-+ is_receiver = &bus_eavesdropper;
-+
-+ /*
-+ * If the destination is not the peer accepted socket
-+ * we have to get the correct destination.
-+ */
-+ if (!sendctx->to_master && sendctx->recipient) {
-+ sendctx->other = bus_find_other(net, sendctx->recipient,
-+ sendctx->namelen,
-+ sk->sk_protocol,
-+ sendctx->hash, &err);
-+
-+
-+ if (sendctx->other == NULL ||
-+ !bus_sk(sendctx->other)->authenticated) {
-+
-+ if (sendctx->other)
-+ sock_put(sendctx->other);
-+
-+ if (sendctx->other == NULL) {
-+ if (!bus_sk(sk)->bus_master_side) {
-+ err = -ENOTCONN;
-+ sendctx->other = bus_peer_get(sk);
-+ if (!sendctx->other)
-+ goto out;
-+ } else {
-+ sendctx->other = sk;
-+ sock_hold(sendctx->other);
-+ }
-+ }
-+ sendctx->to_master = 1;
-+ }
-+ }
-+ }
-+
-+
-+try_again:
-+ rcp_cnt = 0;
-+ main_rcp_found = false;
-+
-+ spin_lock(&u->bus->lock);
-+
-+ hlist_for_each_entry(s, node, &u->bus->peers, bus_node) {
-+
-+ if (!net_eq(sock_net(&s->sk), net))
-+ continue;
-+
-+ if (is_receiver(&s->sk, prefix) ||
-+ (!sendctx->multicast &&
-+ !sendctx->to_master &&
-+ &s->sk == sendctx->other))
-+ rcp_cnt++;
-+ }
-+
-+ spin_unlock(&u->bus->lock);
-+
-+ /*
-+ * Memory can't be allocated while holding a spinlock so
-+ * we have to release the lock, do the allocation for the
-+ * array to store each destination peer sk_buff and grab
-+ * the bus peer lock again. Peers could have joined the
-+ * bus while we relesed the lock so we allocate 5 more
-+ * recipients hoping that this will be enough to not having
-+ * to try again in case only a few peers joined the bus.
-+ */
-+ rcp_cnt += 5;
-+ skb_set = kzalloc(sizeof(struct sk_buff *) * rcp_cnt, GFP_KERNEL);
-+
-+ if (!skb_set) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+
-+ sendctx_set = kzalloc(sizeof(struct bus_send_context *) * rcp_cnt,
-+ GFP_KERNEL);
-+ if (!sendctx_set) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+
-+ for (i = 0; i < rcp_cnt; i++) {
-+ skb_set[i] = skb_clone(skb, GFP_KERNEL);
-+ if (!skb_set[i]) {
-+ err = -ENOMEM;
-+ goto out_free;
-+ }
-+ sendctx_set[i] = BUSCB(skb_set[i]).sendctx
-+ = kmalloc(sizeof(*sendctx) * rcp_cnt, GFP_KERNEL);
-+ if (!sendctx_set[i]) {
-+ err = -ENOMEM;
-+ goto out_free;
-+ }
-+ memcpy(sendctx_set[i], sendctx, sizeof(*sendctx));
-+ err = bus_scm_to_skb(sendctx_set[i]->siocb->scm,
-+ skb_set[i], true);
-+ if (err < 0)
-+ goto out_free;
-+ bus_get_secdata(sendctx_set[i]->siocb->scm,
-+ skb_set[i]);
-+
-+ sendctx_set[i]->other = NULL;
-+ }
-+
-+ send_cnt = 0;
-+
-+ spin_lock(&u->bus->lock);
-+
-+ hlist_for_each_entry(s, node, &u->bus->peers, bus_node) {
-+
-+ if (!net_eq(sock_net(&s->sk), net))
-+ continue;
-+
-+ if (send_cnt >= rcp_cnt) {
-+ spin_unlock(&u->bus->lock);
-+
-+ for (i = 0; i < rcp_cnt; i++) {
-+ sock_put(sendctx_set[i]->other);
-+ kfree_skb(skb_set[i]);
-+ kfree(sendctx_set[i]);
-+ }
-+ kfree(skb_set);
-+ kfree(sendctx_set);
-+ sendctx_set = NULL;
-+ skb_set = NULL;
-+ goto try_again;
-+ }
-+
-+ if (is_receiver(&s->sk, prefix) ||
-+ (!sendctx->multicast &&
-+ !sendctx->to_master &&
-+ &s->sk == sendctx->other)) {
-+ skb_set_owner_w(skb_set[send_cnt], &s->sk);
-+ tmpctx = BUSCB(skb_set[send_cnt]).sendctx;
-+ sock_hold(&s->sk);
-+ if (&s->sk == sendctx->other) {
-+ tmpctx->main_recipient = 1;
-+ main_rcp_found = true;
-+ }
-+ tmpctx->other = &s->sk;
-+ tmpctx->recipient = s->addr->name;
-+ tmpctx->eavesdropper = bus_eavesdropper(&s->sk, 0);
-+
-+ send_cnt++;
-+ }
-+ }
-+
-+ spin_unlock(&u->bus->lock);
-+
-+ /*
-+ * Peers have left the bus so we have to free
-+ * their pre-allocated bus_send_context and
-+ * socket buffers.
-+ */
-+ if (send_cnt < rcp_cnt) {
-+ for (i = send_cnt; i < rcp_cnt; i++) {
-+ kfree_skb(skb_set[i]);
-+ kfree(sendctx_set[i]);
-+ }
-+ rcp_cnt = send_cnt;
-+ }
-+
-+ for (i = 0; i < send_cnt; i++) {
-+ tmpctx = BUSCB(skb_set[i]).sendctx;
-+ tmpctx->deliver = 0;
-+ err = NF_HOOK(NFPROTO_BUS, NF_BUS_SENDING, skb_set[i],
-+ NULL, NULL, bus_sendmsg_finish);
-+ if (err == -EPERM)
-+ sock_put(tmpctx->other);
-+ }
-+
-+ /*
-+ * If the send context is not multicast, the destination
-+ * coud be either the peer accepted socket descriptor or
-+ * a peer that is not an eavesdropper. If the peer is not
-+ * the accepted socket descriptor and has been authenticated,
-+ * it is a member of the bus peer list so it has already been
-+ * marked for delivery.
-+ * But if the destination is the accepted socket descriptor
-+ * or is a non-authenticated peer it is not a member of the
-+ * bus peer list so the packet has to be explicitly deliver
-+ * to it.
-+ */
-+
-+ if (!sendctx->multicast &&
-+ (sendctx->to_master ||
-+ (sendctx->bus_master_side && !main_rcp_found))) {
-+ sendctx->main_recipient = 1;
-+ err = NF_HOOK(NFPROTO_BUS, NF_BUS_SENDING, skb, NULL, NULL,
-+ bus_sendmsg_finish);
-+ if (err == -EPERM)
-+ sock_put(sendctx->other);
-+ }
-+
-+ spin_lock(&u->bus->send_lock);
-+
-+ for (i = 0; i < send_cnt; i++) {
-+ tmpctx = sendctx_set[i];
-+ if (tmpctx->deliver != 1)
-+ continue;
-+
-+ bus_state_lock(tmpctx->other);
-+ bus_deliver_skb(skb_set[i]);
-+ bus_state_unlock(tmpctx->other);
-+ }
-+
-+ if (!sendctx->multicast &&
-+ sendctx->deliver == 1 &&
-+ !bus_sk(sendctx->other)->eavesdropper) {
-+ bus_state_lock(sendctx->other);
-+ bus_deliver_skb(skb);
-+ bus_state_unlock(sendctx->other);
-+ }
-+
-+ spin_unlock(&u->bus->send_lock);
-+
-+ for (i = 0; i < send_cnt; i++) {
-+ tmpctx = sendctx_set[i];
-+ if (tmpctx->deliver != 1)
-+ continue;
-+
-+ tmpctx->other->sk_data_ready(tmpctx->other, 0);
-+ sock_put(tmpctx->other);
-+ }
-+
-+ if (!sendctx->multicast &&
-+ sendctx->deliver == 1 &&
-+ !bus_sk(sendctx->other)->eavesdropper) {
-+ sendctx->other->sk_data_ready(sendctx->other, 0);
-+ sock_put(sendctx->other);
-+ }
-+
-+ err = len;
-+ goto out;
-+
-+out_free:
-+ for (i = 0; i < rcp_cnt; i++) {
-+ if (skb_set[i])
-+ kfree_skb(skb_set[i]);
-+ }
-+
-+out:
-+ kfree(skb_set);
-+ if (sendctx_set) {
-+ for (i = 0; i < rcp_cnt; i++)
-+ kfree(sendctx_set[i]);
-+ kfree(sendctx_set);
-+ }
-+
-+ if (sendctx->deliver == 0) {
-+ if (!sendctx->to_master &&
-+ !(sendctx->bus_master_side && !main_rcp_found))
-+ kfree_skb(skb);
-+ if (!sendctx->to_master &&
-+ !(sendctx->bus_master_side && !main_rcp_found))
-+ if (sendctx->other)
-+ sock_put(sendctx->other);
-+ }
-+ scm_destroy(sendctx->siocb->scm);
-+
-+ return err;
-+}
-+
-+static inline void bus_copy_path(struct sockaddr_bus *dest,
-+ struct sockaddr_bus *src)
-+{
-+ int offset;
-+
-+ /*
-+ * abstract path names start with a null byte character,
-+ * so they have to be compared starting at the second char.
-+ */
-+ offset = (src->sbus_path[0] == '\0');
-+
-+ strncpy(dest->sbus_path + offset,
-+ src->sbus_path + offset,
-+ BUS_PATH_MAX);
-+}
-+
-+/**
-+ * bus_sendmsg - send an skb to a destination
-+ * @kiocb: I/O control block info
-+ * @sock: sender socket
-+ * @msg: message header
-+ * @len: message length
-+ *
-+ * Send an socket buffer to a destination. The destination could be
-+ * either an unicast or a multicast address. In any case, a copy of
-+ * the packet has to be send to all the sockets that are allowed to
-+ * eavesdrop the communication bus.
-+ *
-+ * If the destination address is not associated with any socket, the
-+ * packet is default routed to the bus master (the sender accepted
-+ * socket).
-+ *
-+ * The af_bus sending path is hooked to the netfilter subsystem so
-+ * netfilter hooks can filter or modify the packet before delivery.
-+ */
-+static int bus_sendmsg(struct kiocb *kiocb, struct socket *sock,
-+ struct msghdr *msg, size_t len)
-+{
-+ struct sock *sk = sock->sk;
-+ struct bus_sock *u = bus_sk(sk);
-+ struct sockaddr_bus *sbusaddr = msg->msg_name;
-+ int err;
-+ struct sk_buff *skb;
-+ struct scm_cookie tmp_scm;
-+ bool to_master = false;
-+ bool multicast = false;
-+ struct bus_send_context sendctx;
-+
-+ err = sock_error(sk);
-+ if (err)
-+ return err;
-+
-+ if (sk->sk_state != BUS_ESTABLISHED)
-+ return -ENOTCONN;
-+
-+ if (!msg->msg_namelen)
-+ sbusaddr = NULL;
-+
-+ if (sbusaddr)
-+ bus_copy_path(sbusaddr, u->addr->name);
-+
-+ if ((!sbusaddr && !u->bus_master_side) ||
-+ (sbusaddr && sbusaddr->sbus_addr.s_addr == BUS_MASTER_ADDR))
-+ to_master = true;
-+ else if (sbusaddr && !u->bus_master_side && !u->authenticated)
-+ return -EHOSTUNREACH;
-+
-+ sendctx.namelen = 0; /* fake GCC */
-+ sendctx.siocb = kiocb_to_siocb(kiocb);
-+ sendctx.other = NULL;
-+
-+ if (NULL == sendctx.siocb->scm)
-+ sendctx.siocb->scm = &tmp_scm;
-+ wait_for_bus_gc();
-+ err = scm_send(sock, msg, sendctx.siocb->scm, false);
-+ if (err < 0)
-+ return err;
-+
-+ err = -EOPNOTSUPP;
-+ if (msg->msg_flags&MSG_OOB)
-+ goto out;
-+
-+ if (sbusaddr && !to_master) {
-+ err = bus_mkname(sbusaddr, msg->msg_namelen, &sendctx.hash);
-+ if (err < 0)
-+ goto out;
-+ sendctx.namelen = err;
-+ multicast = bus_mc_addr(sbusaddr);
-+ } else {
-+ err = -ENOTCONN;
-+ sendctx.other = bus_peer_get(sk);
-+ if (!sendctx.other)
-+ goto out;
-+ }
-+
-+ err = -EMSGSIZE;
-+ if (len > sk->sk_sndbuf - 32)
-+ goto out;
-+
-+ sendctx.timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
-+
-+restart:
-+ bus_state_lock(sk);
-+ if (bus_recvq_full(sk)) {
-+ err = -EAGAIN;
-+ if (!sendctx.timeo) {
-+ bus_state_unlock(sk);
-+ goto out;
-+ }
-+
-+ sendctx.timeo = bus_wait_for_peer(sk, sendctx.timeo);
-+
-+ err = sock_intr_errno(sendctx.timeo);
-+ if (signal_pending(current))
-+ goto out;
-+
-+ goto restart;
-+ } else {
-+ bus_state_unlock(sk);
-+ }
-+
-+ skb = sock_alloc_send_skb(sk, len, msg->msg_flags&MSG_DONTWAIT, &err);
-+ if (skb == NULL)
-+ goto out;
-+
-+ err = bus_scm_to_skb(sendctx.siocb->scm, skb, true);
-+ if (err < 0)
-+ goto out_free;
-+ sendctx.max_level = err + 1;
-+ bus_get_secdata(sendctx.siocb->scm, skb);
-+
-+ skb_reset_transport_header(skb);
-+ err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
-+ if (err)
-+ goto out_free;
-+
-+ sendctx.sender_socket = sock;
-+ if (u->bus_master_side && sendctx.other) {
-+ /* if the bus master sent an unicast message to a peer, we
-+ * need the address of that peer
-+ */
-+ sendctx.sender = bus_sk(sendctx.other)->addr->name;
-+ } else {
-+ sendctx.sender = u->addr->name;
-+ }
-+ sendctx.recipient = sbusaddr;
-+ sendctx.authenticated = u->authenticated;
-+ sendctx.bus_master_side = u->bus_master_side;
-+ sendctx.to_master = to_master;
-+ sendctx.multicast = multicast;
-+ sendctx.eavesdropper = atomic64_read(&u->bus->eavesdropper_cnt) ? 1 : 0;
-+ BUSCB(skb).sendctx = &sendctx;
-+
-+ if (sendctx.multicast || sendctx.eavesdropper) {
-+ sendctx.main_recipient = 0;
-+ err = bus_sendmsg_mcast(skb);
-+ return sendctx.multicast ? len : err;
-+ } else {
-+ sendctx.main_recipient = 1;
-+ len = NF_HOOK(NFPROTO_BUS, NF_BUS_SENDING, skb, NULL, NULL,
-+ bus_sendmsg_finish);
-+
-+ if (len == -EPERM) {
-+ err = len;
-+ goto out;
-+ } else {
-+ scm_destroy(sendctx.siocb->scm);
-+ return len;
-+ }
-+ }
-+
-+out_free:
-+ kfree_skb(skb);
-+out:
-+ if (sendctx.other)
-+ sock_put(sendctx.other);
-+ scm_destroy(sendctx.siocb->scm);
-+ return err;
-+}
-+
-+static void bus_copy_addr(struct msghdr *msg, struct sock *sk)
-+{
-+ struct bus_sock *u = bus_sk(sk);
-+
-+ msg->msg_namelen = 0;
-+ if (u->addr) {
-+ msg->msg_namelen = u->addr->len;
-+ memcpy(msg->msg_name, u->addr->name,
-+ sizeof(struct sockaddr_bus));
-+ }
-+}
-+
-+static int bus_recvmsg(struct kiocb *iocb, struct socket *sock,
-+ struct msghdr *msg, size_t size, int flags)
-+{
-+ struct sock_iocb *siocb = kiocb_to_siocb(iocb);
-+ struct scm_cookie tmp_scm;
-+ struct sock *sk = sock->sk;
-+ struct bus_sock *u = bus_sk(sk);
-+ int noblock = flags & MSG_DONTWAIT;
-+ struct sk_buff *skb;
-+ int err;
-+ int peeked, skip;
-+
-+ if (sk->sk_state != BUS_ESTABLISHED)
-+ return -ENOTCONN;
-+
-+ err = -EOPNOTSUPP;
-+ if (flags&MSG_OOB)
-+ goto out;
-+
-+ msg->msg_namelen = 0;
-+
-+ err = mutex_lock_interruptible(&u->readlock);
-+ if (err) {
-+ err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
-+ goto out;
-+ }
-+
-+ skip = sk_peek_offset(sk, flags);
-+
-+ skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err);
-+ if (!skb) {
-+ bus_state_lock(sk);
-+ /* Signal EOF on disconnected non-blocking SEQPACKET socket. */
-+ if (err == -EAGAIN && (sk->sk_shutdown & RCV_SHUTDOWN))
-+ err = 0;
-+ bus_state_unlock(sk);
-+ goto out_unlock;
-+ }
-+
-+ wake_up_interruptible_sync_poll(&u->peer_wait,
-+ POLLOUT | POLLWRNORM | POLLWRBAND);
-+
-+ if (msg->msg_name)
-+ bus_copy_addr(msg, skb->sk);
-+
-+ if (size > skb->len - skip)
-+ size = skb->len - skip;
-+ else if (size < skb->len - skip)
-+ msg->msg_flags |= MSG_TRUNC;
-+
-+ err = skb_copy_datagram_iovec(skb, skip, msg->msg_iov, size);
-+ if (err)
-+ goto out_free;
-+
-+ if (sock_flag(sk, SOCK_RCVTSTAMP))
-+ __sock_recv_timestamp(msg, sk, skb);
-+
-+ if (!siocb->scm) {
-+ siocb->scm = &tmp_scm;
-+ memset(&tmp_scm, 0, sizeof(tmp_scm));
-+ }
-+ scm_set_cred(siocb->scm, BUSCB(skb).pid, BUSCB(skb).cred);
-+ bus_set_secdata(siocb->scm, skb);
-+
-+ if (!(flags & MSG_PEEK)) {
-+ if (BUSCB(skb).fp)
-+ bus_detach_fds(siocb->scm, skb);
-+
-+ sk_peek_offset_bwd(sk, skb->len);
-+ } else {
-+ /* It is questionable: on PEEK we could:
-+ - do not return fds - good, but too simple 8)
-+ - return fds, and do not return them on read (old strategy,
-+ apparently wrong)
-+ - clone fds (I chose it for now, it is the most universal
-+ solution)
-+
-+ POSIX 1003.1g does not actually define this clearly
-+ at all. POSIX 1003.1g doesn't define a lot of things
-+ clearly however!
-+
-+ */
-+
-+ sk_peek_offset_fwd(sk, size);
-+
-+ if (BUSCB(skb).fp)
-+ siocb->scm->fp = scm_fp_dup(BUSCB(skb).fp);
-+ }
-+ err = (flags & MSG_TRUNC) ? skb->len - skip : size;
-+
-+ scm_recv(sock, msg, siocb->scm, flags);
-+
-+out_free:
-+ skb_free_datagram(sk, skb);
-+out_unlock:
-+ mutex_unlock(&u->readlock);
-+out:
-+ return err;
-+}
-+
-+static int bus_shutdown(struct socket *sock, int mode)
-+{
-+ struct sock *sk = sock->sk;
-+ struct sock *other;
-+
-+ mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN);
-+
-+ if (!mode)
-+ return 0;
-+
-+ bus_state_lock(sk);
-+ sk->sk_shutdown |= mode;
-+ other = bus_peer(sk);
-+ if (other)
-+ sock_hold(other);
-+ bus_state_unlock(sk);
-+ sk->sk_state_change(sk);
-+
-+ if (other) {
-+
-+ int peer_mode = 0;
-+
-+ if (mode&RCV_SHUTDOWN)
-+ peer_mode |= SEND_SHUTDOWN;
-+ if (mode&SEND_SHUTDOWN)
-+ peer_mode |= RCV_SHUTDOWN;
-+ bus_state_lock(other);
-+ other->sk_shutdown |= peer_mode;
-+ bus_state_unlock(other);
-+ other->sk_state_change(other);
-+ if (peer_mode == SHUTDOWN_MASK)
-+ sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP);
-+ else if (peer_mode & RCV_SHUTDOWN)
-+ sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN);
-+ sock_put(other);
-+ }
-+
-+ return 0;
-+}
-+
-+static int bus_add_addr(struct sock *sk, struct bus_addr *sbus_addr)
-+{
-+ struct bus_address *addr;
-+ struct sock *other;
-+ struct bus_sock *u = bus_sk(sk);
-+ struct net *net = sock_net(sk);
-+ int ret = 0;
-+
-+ addr = kzalloc(sizeof(*addr) + sizeof(struct sockaddr_bus), GFP_KERNEL);
-+ if (!addr) {
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+
-+ memcpy(addr->name, u->addr->name, sizeof(struct sockaddr_bus));
-+ addr->len = u->addr->len;
-+
-+ addr->name->sbus_addr.s_addr = sbus_addr->s_addr;
-+ addr->hash = bus_compute_hash(addr->name->sbus_addr);
-+ other = bus_find_socket_byaddress(net, addr->name, addr->len,
-+ sk->sk_protocol, addr->hash);
-+
-+ if (other) {
-+ sock_put(other);
-+ kfree(addr);
-+ ret = -EADDRINUSE;
-+ goto out;
-+ }
-+
-+ atomic_set(&addr->refcnt, 1);
-+ INIT_HLIST_NODE(&addr->addr_node);
-+ INIT_HLIST_NODE(&addr->table_node);
-+
-+ addr->sock = sk;
-+
-+ hlist_add_head(&addr->addr_node, &u->addr_list);
-+ bus_insert_address(&bus_address_table[addr->hash], addr);
-+
-+out:
-+ sock_put(sk);
-+
-+ return ret;
-+}
-+
-+static int bus_del_addr(struct sock *sk, struct bus_addr *sbus_addr)
-+{
-+ struct bus_address *addr;
-+ int ret = 0;
-+
-+ bus_state_lock(sk);
-+ addr = __bus_get_address(sk, sbus_addr);
-+ if (!addr) {
-+ ret = -EINVAL;
-+ bus_state_unlock(sk);
-+ goto out;
-+ }
-+ hlist_del(&addr->addr_node);
-+ bus_state_unlock(sk);
-+
-+ bus_remove_address(addr);
-+ bus_release_addr(addr);
-+out:
-+ sock_put(sk);
-+
-+ return ret;
-+}
-+
-+static int bus_join_bus(struct sock *sk)
-+{
-+ struct sock *peer;
-+ struct bus_sock *u = bus_sk(sk), *peeru;
-+ int err = 0;
-+
-+ peer = bus_peer_get(sk);
-+ if (!peer)
-+ return -ENOTCONN;
-+ peeru = bus_sk(peer);
-+
-+ if (!u->bus_master_side || peeru->authenticated) {
-+ err = -EINVAL;
-+ goto sock_put_out;
-+ }
-+
-+ if (sk->sk_state != BUS_ESTABLISHED) {
-+ err = -ENOTCONN;
-+ goto sock_put_out;
-+ }
-+
-+ if (peer->sk_shutdown != 0) {
-+ err = -ENOTCONN;
-+ goto sock_put_out;
-+ }
-+
-+ bus_state_lock(peer);
-+ peeru->authenticated = true;
-+ bus_state_unlock(peer);
-+
-+ spin_lock(&u->bus->lock);
-+ hlist_add_head(&peeru->bus_node, &u->bus->peers);
-+ spin_unlock(&u->bus->lock);
-+
-+sock_put_out:
-+ sock_put(peer);
-+ return err;
-+}
-+
-+static int __bus_set_eavesdrop(struct sock *sk, bool eavesdrop)
-+{
-+ struct sock *peer = bus_peer_get(sk);
-+ struct bus_sock *u = bus_sk(sk), *peeru;
-+ int err = 0;
-+
-+ if (!peer)
-+ return -ENOTCONN;
-+
-+ if (sk->sk_state != BUS_ESTABLISHED) {
-+ err = -ENOTCONN;
-+ goto sock_put_out;
-+ }
-+
-+ peeru = bus_sk(peer);
-+
-+ if (!u->bus_master_side || !peeru->authenticated) {
-+ err = -EINVAL;
-+ goto sock_put_out;
-+ }
-+
-+ if (peer->sk_shutdown != 0) {
-+ err = -ENOTCONN;
-+ goto sock_put_out;
-+ }
-+
-+ bus_state_lock(peeru);
-+ if (peeru->eavesdropper != eavesdrop) {
-+ peeru->eavesdropper = eavesdrop;
-+ if (eavesdrop)
-+ atomic64_inc(&u->bus->eavesdropper_cnt);
-+ else
-+ atomic64_dec(&u->bus->eavesdropper_cnt);
-+ }
-+ bus_state_unlock(peeru);
-+
-+sock_put_out:
-+ sock_put(peer);
-+ return err;
-+}
-+
-+static int bus_set_eavesdrop(struct sock *sk)
-+{
-+ return __bus_set_eavesdrop(sk, true);
-+}
-+
-+static int bus_unset_eavesdrop(struct sock *sk)
-+{
-+ return __bus_set_eavesdrop(sk, false);
-+}
-+
-+static inline void sk_sendbuf_set(struct sock *sk, int sndbuf)
-+{
-+ bus_state_lock(sk);
-+ sk->sk_sndbuf = sndbuf;
-+ bus_state_unlock(sk);
-+}
-+
-+static inline void sk_maxqlen_set(struct sock *sk, int qlen)
-+{
-+ bus_state_lock(sk);
-+ sk->sk_max_ack_backlog = qlen;
-+ bus_state_unlock(sk);
-+}
-+
-+static int bus_get_qlenfull(struct sock *sk)
-+{
-+ struct sock *peer;
-+ struct bus_sock *u = bus_sk(sk), *peeru;
-+ int ret = 0;
-+
-+ peer = bus_peer_get(sk);
-+ if (!peer)
-+ return -ENOTCONN;
-+
-+ peeru = bus_sk(peer);
-+
-+ if (!u->bus_master_side || peeru->authenticated) {
-+ ret = -EINVAL;
-+ goto sock_put_out;
-+ }
-+
-+ if (sk->sk_state != BUS_ESTABLISHED) {
-+ ret = -ENOTCONN;
-+ goto sock_put_out;
-+ }
-+
-+ if (peer->sk_shutdown != 0) {
-+ ret = -ENOTCONN;
-+ goto sock_put_out;
-+ }
-+
-+ ret = bus_recvq_full(peer);
-+
-+sock_put_out:
-+ sock_put(peer);
-+ return ret;
-+}
-+
-+static int bus_setsockopt(struct socket *sock, int level, int optname,
-+ char __user *optval, unsigned int optlen)
-+{
-+ struct bus_addr addr;
-+ int res;
-+ int val;
-+
-+ if (level != SOL_BUS)
-+ return -ENOPROTOOPT;
-+
-+ switch (optname) {
-+ case BUS_ADD_ADDR:
-+ case BUS_DEL_ADDR:
-+ if (optlen < sizeof(struct bus_addr))
-+ return -EINVAL;
-+
-+ if (!bus_sk(sock->sk)->bus_master_side)
-+ return -EINVAL;
-+
-+ if (copy_from_user(&addr, optval, sizeof(struct bus_addr)))
-+ return -EFAULT;
-+
-+ if (optname == BUS_ADD_ADDR)
-+ res = bus_add_addr(bus_peer_get(sock->sk), &addr);
-+ else
-+ res = bus_del_addr(bus_peer_get(sock->sk), &addr);
-+ break;
-+ case BUS_JOIN_BUS:
-+ res = bus_join_bus(sock->sk);
-+ break;
-+ case BUS_SET_EAVESDROP:
-+ res = bus_set_eavesdrop(sock->sk);
-+ break;
-+ case BUS_UNSET_EAVESDROP:
-+ res = bus_unset_eavesdrop(sock->sk);
-+ break;
-+ case BUS_SET_SENDBUF:
-+ case BUS_SET_MAXQLEN:
-+ if (sock->sk->sk_state != BUS_LISTEN) {
-+ res = -EINVAL;
-+ } else {
-+ res = -EFAULT;
-+
-+ if (copy_from_user(&val, optval, optlen))
-+ break;
-+
-+ res = 0;
-+
-+ if (optname == BUS_SET_SENDBUF)
-+ sk_sendbuf_set(sock->sk, val);
-+ else
-+ sk_maxqlen_set(sock->sk, val);
-+ }
-+ break;
-+ case BUS_GET_QLENFULL:
-+ res = bus_get_qlenfull(sock->sk);
-+
-+ if (copy_to_user(&res, optval, optlen)) {
-+ res = -EFAULT;
-+ break;
-+ }
-+ res = 0;
-+ break;
-+ default:
-+ res = -EINVAL;
-+ break;
-+ }
-+
-+ return res;
-+}
-+
-+long bus_inq_len(struct sock *sk)
-+{
-+ struct sk_buff *skb;
-+ long amount = 0;
-+
-+ if (sk->sk_state == BUS_LISTEN)
-+ return -EINVAL;
-+
-+ spin_lock(&sk->sk_receive_queue.lock);
-+ skb_queue_walk(&sk->sk_receive_queue, skb)
-+ amount += skb->len;
-+ spin_unlock(&sk->sk_receive_queue.lock);
-+
-+ return amount;
-+}
-+EXPORT_SYMBOL_GPL(bus_inq_len);
-+
-+long bus_outq_len(struct sock *sk)
-+{
-+ return sk_wmem_alloc_get(sk);
-+}
-+EXPORT_SYMBOL_GPL(bus_outq_len);
-+
-+static int bus_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-+{
-+ struct sock *sk = sock->sk;
-+ long amount = 0;
-+ int err;
-+
-+ switch (cmd) {
-+ case SIOCOUTQ:
-+ amount = bus_outq_len(sk);
-+ err = put_user(amount, (int __user *)arg);
-+ break;
-+ case SIOCINQ:
-+ amount = bus_inq_len(sk);
-+ if (amount < 0)
-+ err = amount;
-+ else
-+ err = put_user(amount, (int __user *)arg);
-+ break;
-+ default:
-+ err = -ENOIOCTLCMD;
-+ break;
-+ }
-+ return err;
-+}
-+
-+static unsigned int bus_poll(struct file *file, struct socket *sock,
-+ poll_table *wait)
-+{
-+ struct sock *sk = sock->sk, *other;
-+ unsigned int mask, writable;
-+ struct bus_sock *u = bus_sk(sk), *p;
-+ struct hlist_node *node;
-+
-+ sock_poll_wait(file, sk_sleep(sk), wait);
-+ mask = 0;
-+
-+ /* exceptional events? */
-+ if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
-+ mask |= POLLERR;
-+ if (sk->sk_shutdown & RCV_SHUTDOWN)
-+ mask |= POLLRDHUP | POLLIN | POLLRDNORM;
-+ if (sk->sk_shutdown == SHUTDOWN_MASK)
-+ mask |= POLLHUP;
-+
-+ /* readable? */
-+ if (!skb_queue_empty(&sk->sk_receive_queue))
-+ mask |= POLLIN | POLLRDNORM;
-+
-+ /* Connection-based need to check for termination and startup */
-+ if (sk->sk_state == BUS_CLOSE)
-+ mask |= POLLHUP;
-+
-+ /* No write status requested, avoid expensive OUT tests. */
-+ if (!(poll_requested_events(wait) & (POLLWRBAND|POLLWRNORM|POLLOUT)))
-+ return mask;
-+
-+ writable = bus_writable(sk);
-+ other = bus_peer_get(sk);
-+ if (other) {
-+ if (bus_recvq_full(other))
-+ writable = 0;
-+ sock_put(other);
-+ }
-+
-+ /*
-+ * If the socket has already joined the bus we have to check
-+ * that each peer receiver queue on the bus is not full.
-+ */
-+ if (!u->bus_master_side && u->authenticated) {
-+ spin_lock(&u->bus->lock);
-+ hlist_for_each_entry(p, node, &u->bus->peers, bus_node) {
-+ if (bus_recvq_full(&p->sk)) {
-+ writable = 0;
-+ break;
-+ }
-+ }
-+ spin_unlock(&u->bus->lock);
-+ }
-+
-+ if (writable)
-+ mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
-+ else
-+ set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
-+
-+ return mask;
-+}
-+
-+#ifdef CONFIG_PROC_FS
-+static struct sock *first_bus_socket(int *i)
-+{
-+ for (*i = 0; *i <= BUS_HASH_SIZE; (*i)++) {
-+ if (!hlist_empty(&bus_socket_table[*i]))
-+ return __sk_head(&bus_socket_table[*i]);
-+ }
-+ return NULL;
-+}
-+
-+static struct sock *next_bus_socket(int *i, struct sock *s)
-+{
-+ struct sock *next = sk_next(s);
-+ /* More in this chain? */
-+ if (next)
-+ return next;
-+ /* Look for next non-empty chain. */
-+ for ((*i)++; *i <= BUS_HASH_SIZE; (*i)++) {
-+ if (!hlist_empty(&bus_socket_table[*i]))
-+ return __sk_head(&bus_socket_table[*i]);
-+ }
-+ return NULL;
-+}
-+
-+struct bus_iter_state {
-+ struct seq_net_private p;
-+ int i;
-+};
-+
-+static struct sock *bus_seq_idx(struct seq_file *seq, loff_t pos)
-+{
-+ struct bus_iter_state *iter = seq->private;
-+ loff_t off = 0;
-+ struct sock *s;
-+
-+ for (s = first_bus_socket(&iter->i); s;
-+ s = next_bus_socket(&iter->i, s)) {
-+ if (sock_net(s) != seq_file_net(seq))
-+ continue;
-+ if (off == pos)
-+ return s;
-+ ++off;
-+ }
-+ return NULL;
-+}
-+
-+static void *bus_seq_start(struct seq_file *seq, loff_t *pos)
-+ __acquires(bus_table_lock)
-+{
-+ spin_lock(&bus_table_lock);
-+ return *pos ? bus_seq_idx(seq, *pos - 1) : SEQ_START_TOKEN;
-+}
-+
-+static void *bus_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-+{
-+ struct bus_iter_state *iter = seq->private;
-+ struct sock *sk = v;
-+ ++*pos;
-+
-+ if (v == SEQ_START_TOKEN)
-+ sk = first_bus_socket(&iter->i);
-+ else
-+ sk = next_bus_socket(&iter->i, sk);
-+ while (sk && (sock_net(sk) != seq_file_net(seq)))
-+ sk = next_bus_socket(&iter->i, sk);
-+ return sk;
-+}
-+
-+static void bus_seq_stop(struct seq_file *seq, void *v)
-+ __releases(bus_table_lock)
-+{
-+ spin_unlock(&bus_table_lock);
-+}
-+
-+static int bus_seq_show(struct seq_file *seq, void *v)
-+{
-+
-+ if (v == SEQ_START_TOKEN)
-+ seq_puts(seq, "Num RefCount Protocol Flags Type St " \
-+ "Inode Path\n");
-+ else {
-+ struct sock *s = v;
-+ struct bus_sock *u = bus_sk(s);
-+ bus_state_lock(s);
-+
-+ seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5lu",
-+ s,
-+ atomic_read(&s->sk_refcnt),
-+ 0,
-+ s->sk_state == BUS_LISTEN ? __SO_ACCEPTCON : 0,
-+ s->sk_type,
-+ s->sk_socket ?
-+ (s->sk_state == BUS_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED) :
-+ (s->sk_state == BUS_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING),
-+ sock_i_ino(s));
-+
-+ if (u->addr) {
-+ int i, len;
-+ seq_putc(seq, ' ');
-+
-+ i = 0;
-+ len = u->addr->len - sizeof(short);
-+ if (!BUS_ABSTRACT(s))
-+ len--;
-+ else {
-+ seq_putc(seq, '@');
-+ i++;
-+ }
-+ for ( ; i < len; i++)
-+ seq_putc(seq, u->addr->name->sbus_path[i]);
-+ }
-+ bus_state_unlock(s);
-+ seq_putc(seq, '\n');
-+ }
-+
-+ return 0;
-+}
-+
-+static const struct seq_operations bus_seq_ops = {
-+ .start = bus_seq_start,
-+ .next = bus_seq_next,
-+ .stop = bus_seq_stop,
-+ .show = bus_seq_show,
-+};
-+
-+static int bus_seq_open(struct inode *inode, struct file *file)
-+{
-+ return seq_open_net(inode, file, &bus_seq_ops,
-+ sizeof(struct bus_iter_state));
-+}
-+
-+static const struct file_operations bus_seq_fops = {
-+ .owner = THIS_MODULE,
-+ .open = bus_seq_open,
-+ .read = seq_read,
-+ .llseek = seq_lseek,
-+ .release = seq_release_net,
-+};
-+
-+#endif
-+
-+static const struct net_proto_family bus_family_ops = {
-+ .family = PF_BUS,
-+ .create = bus_create,
-+ .owner = THIS_MODULE,
-+};
-+
-+static int __init af_bus_init(void)
-+{
-+ int rc = -1;
-+ struct sk_buff *dummy_skb;
-+
-+ BUILD_BUG_ON(sizeof(struct bus_skb_parms) > sizeof(dummy_skb->cb));
-+
-+ rc = proto_register(&bus_proto, 1);
-+ if (rc != 0) {
-+ pr_crit("%s: Cannot create bus_sock SLAB cache!\n", __func__);
-+ return rc;
-+ }
-+
-+ sock_register(&bus_family_ops);
-+ return rc;
-+}
-+
-+static void __exit af_bus_exit(void)
-+{
-+ sock_unregister(PF_BUS);
-+ proto_unregister(&bus_proto);
-+}
-+
-+module_init(af_bus_init);
-+module_exit(af_bus_exit);
-+
-+MODULE_AUTHOR("Alban Crequy, Javier Martinez Canillas");
-+MODULE_DESCRIPTION("Linux Bus domain sockets");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS_NETPROTO(PF_BUS);
---
-1.7.7.6
-
+++ /dev/null
-From 2a2abe6e793a5b7f027d8af33f1ebb3e106016eb Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Wed, 20 Jun 2012 15:56:38 +0200
-Subject: [PATCH 09/15] net: bus: Add garbage collector for AF_BUS sockets.
-
-This patch adds a garbage collector for AF_BUS sockets.
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
----
- net/bus/garbage.c | 322 +++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 files changed, 322 insertions(+), 0 deletions(-)
- create mode 100644 net/bus/garbage.c
-
-diff --git a/net/bus/garbage.c b/net/bus/garbage.c
-new file mode 100644
-index 0000000..2435f38
---- /dev/null
-+++ b/net/bus/garbage.c
-@@ -0,0 +1,322 @@
-+/*
-+ * Garbage Collector For AF_BUS sockets
-+ *
-+ * Based on Garbage Collector For AF_UNIX sockets (net/unix/garbage.c).
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/string.h>
-+#include <linux/socket.h>
-+#include <linux/un.h>
-+#include <linux/net.h>
-+#include <linux/fs.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/file.h>
-+#include <linux/proc_fs.h>
-+#include <linux/mutex.h>
-+#include <linux/wait.h>
-+
-+#include <net/sock.h>
-+#include <net/af_bus.h>
-+#include <net/scm.h>
-+#include <net/tcp_states.h>
-+
-+/* Internal data structures and random procedures: */
-+
-+static LIST_HEAD(gc_inflight_list);
-+static LIST_HEAD(gc_candidates);
-+static DEFINE_SPINLOCK(bus_gc_lock);
-+static DECLARE_WAIT_QUEUE_HEAD(bus_gc_wait);
-+
-+unsigned int bus_tot_inflight;
-+
-+
-+struct sock *bus_get_socket(struct file *filp)
-+{
-+ struct sock *u_sock = NULL;
-+ struct inode *inode = filp->f_path.dentry->d_inode;
-+
-+ /*
-+ * Socket ?
-+ */
-+ if (S_ISSOCK(inode->i_mode) && !(filp->f_mode & FMODE_PATH)) {
-+ struct socket *sock = SOCKET_I(inode);
-+ struct sock *s = sock->sk;
-+
-+ /*
-+ * PF_BUS ?
-+ */
-+ if (s && sock->ops && sock->ops->family == PF_BUS)
-+ u_sock = s;
-+ }
-+ return u_sock;
-+}
-+
-+/*
-+ * Keep the number of times in flight count for the file
-+ * descriptor if it is for an AF_BUS socket.
-+ */
-+
-+void bus_inflight(struct file *fp)
-+{
-+ struct sock *s = bus_get_socket(fp);
-+ if (s) {
-+ struct bus_sock *u = bus_sk(s);
-+ spin_lock(&bus_gc_lock);
-+ if (atomic_long_inc_return(&u->inflight) == 1) {
-+ BUG_ON(!list_empty(&u->link));
-+ list_add_tail(&u->link, &gc_inflight_list);
-+ } else {
-+ BUG_ON(list_empty(&u->link));
-+ }
-+ bus_tot_inflight++;
-+ spin_unlock(&bus_gc_lock);
-+ }
-+}
-+
-+void bus_notinflight(struct file *fp)
-+{
-+ struct sock *s = bus_get_socket(fp);
-+ if (s) {
-+ struct bus_sock *u = bus_sk(s);
-+ spin_lock(&bus_gc_lock);
-+ BUG_ON(list_empty(&u->link));
-+ if (atomic_long_dec_and_test(&u->inflight))
-+ list_del_init(&u->link);
-+ bus_tot_inflight--;
-+ spin_unlock(&bus_gc_lock);
-+ }
-+}
-+
-+static void scan_inflight(struct sock *x, void (*func)(struct bus_sock *),
-+ struct sk_buff_head *hitlist)
-+{
-+ struct sk_buff *skb;
-+ struct sk_buff *next;
-+
-+ spin_lock(&x->sk_receive_queue.lock);
-+ skb_queue_walk_safe(&x->sk_receive_queue, skb, next) {
-+ /*
-+ * Do we have file descriptors ?
-+ */
-+ if (BUSCB(skb).fp) {
-+ bool hit = false;
-+ /*
-+ * Process the descriptors of this socket
-+ */
-+ int nfd = BUSCB(skb).fp->count;
-+ struct file **fp = BUSCB(skb).fp->fp;
-+ while (nfd--) {
-+ /*
-+ * Get the socket the fd matches
-+ * if it indeed does so
-+ */
-+ struct sock *sk = bus_get_socket(*fp++);
-+ if (sk) {
-+ struct bus_sock *u = bus_sk(sk);
-+
-+ /*
-+ * Ignore non-candidates, they could
-+ * have been added to the queues after
-+ * starting the garbage collection
-+ */
-+ if (u->gc_candidate) {
-+ hit = true;
-+ func(u);
-+ }
-+ }
-+ }
-+ if (hit && hitlist != NULL) {
-+ __skb_unlink(skb, &x->sk_receive_queue);
-+ __skb_queue_tail(hitlist, skb);
-+ }
-+ }
-+ }
-+ spin_unlock(&x->sk_receive_queue.lock);
-+}
-+
-+static void scan_children(struct sock *x, void (*func)(struct bus_sock *),
-+ struct sk_buff_head *hitlist)
-+{
-+ if (x->sk_state != TCP_LISTEN)
-+ scan_inflight(x, func, hitlist);
-+ else {
-+ struct sk_buff *skb;
-+ struct sk_buff *next;
-+ struct bus_sock *u;
-+ LIST_HEAD(embryos);
-+
-+ /*
-+ * For a listening socket collect the queued embryos
-+ * and perform a scan on them as well.
-+ */
-+ spin_lock(&x->sk_receive_queue.lock);
-+ skb_queue_walk_safe(&x->sk_receive_queue, skb, next) {
-+ u = bus_sk(skb->sk);
-+
-+ /*
-+ * An embryo cannot be in-flight, so it's safe
-+ * to use the list link.
-+ */
-+ BUG_ON(!list_empty(&u->link));
-+ list_add_tail(&u->link, &embryos);
-+ }
-+ spin_unlock(&x->sk_receive_queue.lock);
-+
-+ while (!list_empty(&embryos)) {
-+ u = list_entry(embryos.next, struct bus_sock, link);
-+ scan_inflight(&u->sk, func, hitlist);
-+ list_del_init(&u->link);
-+ }
-+ }
-+}
-+
-+static void dec_inflight(struct bus_sock *usk)
-+{
-+ atomic_long_dec(&usk->inflight);
-+}
-+
-+static void inc_inflight(struct bus_sock *usk)
-+{
-+ atomic_long_inc(&usk->inflight);
-+}
-+
-+static void inc_inflight_move_tail(struct bus_sock *u)
-+{
-+ atomic_long_inc(&u->inflight);
-+ /*
-+ * If this still might be part of a cycle, move it to the end
-+ * of the list, so that it's checked even if it was already
-+ * passed over
-+ */
-+ if (u->gc_maybe_cycle)
-+ list_move_tail(&u->link, &gc_candidates);
-+}
-+
-+static bool gc_in_progress = false;
-+#define BUS_INFLIGHT_TRIGGER_GC 16000
-+
-+void wait_for_bus_gc(void)
-+{
-+ /*
-+ * If number of inflight sockets is insane,
-+ * force a garbage collect right now.
-+ */
-+ if (bus_tot_inflight > BUS_INFLIGHT_TRIGGER_GC && !gc_in_progress)
-+ bus_gc();
-+ wait_event(bus_gc_wait, gc_in_progress == false);
-+}
-+
-+/* The external entry point: bus_gc() */
-+void bus_gc(void)
-+{
-+ struct bus_sock *u;
-+ struct bus_sock *next;
-+ struct sk_buff_head hitlist;
-+ struct list_head cursor;
-+ LIST_HEAD(not_cycle_list);
-+
-+ spin_lock(&bus_gc_lock);
-+
-+ /* Avoid a recursive GC. */
-+ if (gc_in_progress)
-+ goto out;
-+
-+ gc_in_progress = true;
-+ /*
-+ * First, select candidates for garbage collection. Only
-+ * in-flight sockets are considered, and from those only ones
-+ * which don't have any external reference.
-+ *
-+ * Holding bus_gc_lock will protect these candidates from
-+ * being detached, and hence from gaining an external
-+ * reference. Since there are no possible receivers, all
-+ * buffers currently on the candidates' queues stay there
-+ * during the garbage collection.
-+ *
-+ * We also know that no new candidate can be added onto the
-+ * receive queues. Other, non candidate sockets _can_ be
-+ * added to queue, so we must make sure only to touch
-+ * candidates.
-+ */
-+ list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
-+ long total_refs;
-+ long inflight_refs;
-+
-+ total_refs = file_count(u->sk.sk_socket->file);
-+ inflight_refs = atomic_long_read(&u->inflight);
-+
-+ BUG_ON(inflight_refs < 1);
-+ BUG_ON(total_refs < inflight_refs);
-+ if (total_refs == inflight_refs) {
-+ list_move_tail(&u->link, &gc_candidates);
-+ u->gc_candidate = 1;
-+ u->gc_maybe_cycle = 1;
-+ }
-+ }
-+
-+ /*
-+ * Now remove all internal in-flight reference to children of
-+ * the candidates.
-+ */
-+ list_for_each_entry(u, &gc_candidates, link)
-+ scan_children(&u->sk, dec_inflight, NULL);
-+
-+ /*
-+ * Restore the references for children of all candidates,
-+ * which have remaining references. Do this recursively, so
-+ * only those remain, which form cyclic references.
-+ *
-+ * Use a "cursor" link, to make the list traversal safe, even
-+ * though elements might be moved about.
-+ */
-+ list_add(&cursor, &gc_candidates);
-+ while (cursor.next != &gc_candidates) {
-+ u = list_entry(cursor.next, struct bus_sock, link);
-+
-+ /* Move cursor to after the current position. */
-+ list_move(&cursor, &u->link);
-+
-+ if (atomic_long_read(&u->inflight) > 0) {
-+ list_move_tail(&u->link, ¬_cycle_list);
-+ u->gc_maybe_cycle = 0;
-+ scan_children(&u->sk, inc_inflight_move_tail, NULL);
-+ }
-+ }
-+ list_del(&cursor);
-+
-+ /*
-+ * not_cycle_list contains those sockets which do not make up a
-+ * cycle. Restore these to the inflight list.
-+ */
-+ while (!list_empty(¬_cycle_list)) {
-+ u = list_entry(not_cycle_list.next, struct bus_sock, link);
-+ u->gc_candidate = 0;
-+ list_move_tail(&u->link, &gc_inflight_list);
-+ }
-+
-+ /*
-+ * Now gc_candidates contains only garbage. Restore original
-+ * inflight counters for these as well, and remove the skbuffs
-+ * which are creating the cycle(s).
-+ */
-+ skb_queue_head_init(&hitlist);
-+ list_for_each_entry(u, &gc_candidates, link)
-+ scan_children(&u->sk, inc_inflight, &hitlist);
-+
-+ spin_unlock(&bus_gc_lock);
-+
-+ /* Here we are. Hitlist is filled. Die. */
-+ __skb_queue_purge(&hitlist);
-+
-+ spin_lock(&bus_gc_lock);
-+
-+ /* All candidates should have been detached by now. */
-+ BUG_ON(!list_empty(&gc_candidates));
-+ gc_in_progress = false;
-+ wake_up(&bus_gc_wait);
-+
-+ out:
-+ spin_unlock(&bus_gc_lock);
-+}
---
-1.7.7.6
-
+++ /dev/null
-From 89d9d1c0afd8d782a9726dfb79646022086a21bb Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Wed, 20 Jun 2012 16:16:40 +0200
-Subject: [PATCH 10/15] net: bus: Add the AF_BUS socket address family to
- KBuild
-
-This patch adds the AF_BUS code to the Linux Kernel build system.
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
----
- net/Kconfig | 1 +
- net/Makefile | 1 +
- net/bus/Kconfig | 15 +++++++++++++++
- net/bus/Makefile | 7 +++++++
- 4 files changed, 24 insertions(+), 0 deletions(-)
- create mode 100644 net/bus/Kconfig
- create mode 100644 net/bus/Makefile
-
-diff --git a/net/Kconfig b/net/Kconfig
-index e07272d..c9774a1 100644
---- a/net/Kconfig
-+++ b/net/Kconfig
-@@ -47,6 +47,7 @@ menu "Networking options"
-
- source "net/packet/Kconfig"
- source "net/unix/Kconfig"
-+source "net/bus/Kconfig"
- source "net/xfrm/Kconfig"
- source "net/iucv/Kconfig"
-
-diff --git a/net/Makefile b/net/Makefile
-index ad432fa..3033018 100644
---- a/net/Makefile
-+++ b/net/Makefile
-@@ -19,6 +19,7 @@ obj-$(CONFIG_NETFILTER) += netfilter/
- obj-$(CONFIG_INET) += ipv4/
- obj-$(CONFIG_XFRM) += xfrm/
- obj-$(CONFIG_UNIX) += unix/
-+obj-$(CONFIG_AF_BUS) += bus/
- obj-$(CONFIG_NET) += ipv6/
- obj-$(CONFIG_PACKET) += packet/
- obj-$(CONFIG_NET_KEY) += key/
-diff --git a/net/bus/Kconfig b/net/bus/Kconfig
-new file mode 100644
-index 0000000..5f01410
---- /dev/null
-+++ b/net/bus/Kconfig
-@@ -0,0 +1,15 @@
-+#
-+# Bus Domain Sockets
-+#
-+
-+config AF_BUS
-+ tristate "Bus domain sockets (EXPERIMENTAL)"
-+ depends on EXPERIMENTAL
-+ ---help---
-+ If you say Y here, you will include support for Bus domain sockets.
-+ These sockets are used to create communication buses for IPC.
-+
-+ To compile this driver as a module, choose M here: the module will be
-+ called bus.
-+
-+ Say N unless you know what you are doing.
-diff --git a/net/bus/Makefile b/net/bus/Makefile
-new file mode 100644
-index 0000000..8c1fea2
---- /dev/null
-+++ b/net/bus/Makefile
-@@ -0,0 +1,7 @@
-+#
-+# Makefile for the Linux bus domain socket layer.
-+#
-+
-+obj-$(CONFIG_AF_BUS) += af-bus.o
-+
-+af-bus-y := af_bus.o garbage.o
---
-1.7.7.6
-
+++ /dev/null
-From b0049444e09caf7cb41f63a8648cc1a98a5940cf Mon Sep 17 00:00:00 2001
-From: Alban Crequy <alban.crequy@collabora.co.uk>
-Date: Wed, 20 Jun 2012 18:04:37 +0200
-Subject: [PATCH 11/15] netlink: connector: implement cn_netlink_reply
-
-In a connector callback, it was not possible to reply to a message only to a
-sender. This patch implements cn_netlink_reply(). It uses the connector socket
-to send an unicast netlink message back to the sender.
-
-The following pseudo-code can be used from a connector callback:
-
- struct cn_msg *cn_reply;
- cn_reply = kzalloc(sizeof(struct cn_msg)
- + sizeof(struct ..._nl_cfg_reply), GFP_KERNEL);
-
- cn_reply->id = msg->id;
- cn_reply->seq = msg->seq;
- cn_reply->ack = msg->ack + 1;
- cn_reply->len = sizeof(struct ..._nl_cfg_reply);
- cn_reply->flags = 0;
-
- rr = cn_netlink_reply(cn_reply, nsp->pid, GFP_KERNEL);
-
-Signed-off-by: Alban Crequy <alban.crequy@collabora.co.uk>
----
- drivers/connector/connector.c | 32 ++++++++++++++++++++++++++++++++
- include/linux/connector.h | 1 +
- 2 files changed, 33 insertions(+), 0 deletions(-)
-
-diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
-index dde6a0f..a1f9364 100644
---- a/drivers/connector/connector.c
-+++ b/drivers/connector/connector.c
-@@ -118,6 +118,38 @@ nlmsg_failure:
- EXPORT_SYMBOL_GPL(cn_netlink_send);
-
- /*
-+ * Send an unicast reply from a connector callback
-+ *
-+ */
-+int cn_netlink_reply(struct cn_msg *msg, u32 pid, gfp_t gfp_mask)
-+{
-+ unsigned int size;
-+ struct sk_buff *skb;
-+ struct nlmsghdr *nlh;
-+ struct cn_msg *data;
-+ struct cn_dev *dev = &cdev;
-+
-+ size = NLMSG_SPACE(sizeof(*msg) + msg->len);
-+
-+ skb = alloc_skb(size, gfp_mask);
-+ if (!skb)
-+ return -ENOMEM;
-+
-+ nlh = nlmsg_put(skb, 0, msg->seq, NLMSG_DONE, size - sizeof(*nlh), 0);
-+ if (nlh == NULL) {
-+ kfree_skb(skb);
-+ return -EMSGSIZE;
-+ }
-+
-+ data = nlmsg_data(nlh);
-+
-+ memcpy(data, msg, sizeof(*data) + msg->len);
-+
-+ return netlink_unicast(dev->nls, skb, pid, 1);
-+}
-+EXPORT_SYMBOL_GPL(cn_netlink_reply);
-+
-+/*
- * Callback helper - queues work and setup destructor for given data.
- */
- static int cn_call_callback(struct sk_buff *skb)
-diff --git a/include/linux/connector.h b/include/linux/connector.h
-index 7638407..c27be60 100644
---- a/include/linux/connector.h
-+++ b/include/linux/connector.h
-@@ -125,6 +125,7 @@ int cn_add_callback(struct cb_id *id, const char *name,
- void (*callback)(struct cn_msg *, struct netlink_skb_parms *));
- void cn_del_callback(struct cb_id *);
- int cn_netlink_send(struct cn_msg *, u32, gfp_t);
-+int cn_netlink_reply(struct cn_msg *, u32, gfp_t);
-
- int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name,
- struct cb_id *id,
---
-1.7.7.6
-
+++ /dev/null
-From b34502ec47d9b6cdc526c762837fd242cb674c44 Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Wed, 20 Jun 2012 18:15:09 +0200
-Subject: [PATCH 12/15] netlink: connector: Add idx and val identifiers for
- netfilter D-Bus
-
-The D-bus IPC system implements a transport that uses AF_BUS sockets to
-send D-Bus messages to the peers. This allows decouple the routing logic
-from the daemon and move it to the kernel which has the advantage of
-reducing the number of context switches and the messages copied to
-user-space.
-
-A D-Bus protocol aware netfilter module decide which peer can recive a
-given message based on a set of D-Bus match rules. These match rules
-are set from user-space using the netlink connector API.
-
-Based on a previous patch by Alban Crequy.
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
----
- include/linux/connector.h | 4 +++-
- 1 files changed, 3 insertions(+), 1 deletions(-)
-
-diff --git a/include/linux/connector.h b/include/linux/connector.h
-index c27be60..519d010 100644
---- a/include/linux/connector.h
-+++ b/include/linux/connector.h
-@@ -44,8 +44,10 @@
- #define CN_VAL_DRBD 0x1
- #define CN_KVP_IDX 0x9 /* HyperV KVP */
- #define CN_KVP_VAL 0x1 /* queries from the kernel */
-+#define CN_IDX_NFDBUS 0xA /* netfilter D-Bus */
-+#define CN_VAL_NFDBUS 0x1
-
--#define CN_NETLINK_USERS 10 /* Highest index + 1 */
-+#define CN_NETLINK_USERS 11 /* Highest index + 1 */
-
- /*
- * Maximum connector's message size.
---
-1.7.7.6
-
+++ /dev/null
-From ef39ec62107dfb7fa0ecd43026804e214569cad5 Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Wed, 20 Jun 2012 19:01:52 +0200
-Subject: [PATCH 13/15] netfilter: nfdbus: Add D-bus message parsing
-
-The netfilter D-Bus module needs to parse D-bus messages sent by
-applications to decide whether a peer can receive or not a D-Bus
-message. Add D-bus message parsing logic to be able to analyze.
-
-Based on a previous patch by Alban Crequy.
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
----
- net/bus/nfdbus/message.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++
- net/bus/nfdbus/message.h | 71 +++++++++++++++++
- 2 files changed, 265 insertions(+), 0 deletions(-)
- create mode 100644 net/bus/nfdbus/message.c
- create mode 100644 net/bus/nfdbus/message.h
-
-diff --git a/net/bus/nfdbus/message.c b/net/bus/nfdbus/message.c
-new file mode 100644
-index 0000000..93c409c
---- /dev/null
-+++ b/net/bus/nfdbus/message.c
-@@ -0,0 +1,194 @@
-+/*
-+ * message.c Basic D-Bus message parsing
-+ *
-+ * Copyright (C) 2010-2012 Collabora Ltd
-+ * Authors: Alban Crequy <alban.crequy@collabora.co.uk>
-+ * Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc.
-+ * Copyright (C) 2002, 2003 CodeFactory AB
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ */
-+
-+#include <linux/slab.h>
-+
-+#include "message.h"
-+
-+int dbus_message_type_from_string(const char *type_str)
-+{
-+ if (strcmp(type_str, "method_call") == 0)
-+ return DBUS_MESSAGE_TYPE_METHOD_CALL;
-+ if (strcmp(type_str, "method_return") == 0)
-+ return DBUS_MESSAGE_TYPE_METHOD_RETURN;
-+ else if (strcmp(type_str, "signal") == 0)
-+ return DBUS_MESSAGE_TYPE_SIGNAL;
-+ else if (strcmp(type_str, "error") == 0)
-+ return DBUS_MESSAGE_TYPE_ERROR;
-+ else
-+ return DBUS_MESSAGE_TYPE_INVALID;
-+}
-+
-+int dbus_message_parse(unsigned char *message, size_t len,
-+ struct dbus_message *dbus_message)
-+{
-+ unsigned char *cur;
-+ int array_header_len;
-+
-+ dbus_message->message = message;
-+
-+ if (len < 4 + 4 + 4 + 4 || message[1] == 0 || message[1] > 4)
-+ return -EINVAL;
-+
-+ dbus_message->type = message[1];
-+ dbus_message->body_length = *((u32 *)(message + 4));
-+ cur = message + 12;
-+ array_header_len = *(u32 *)cur;
-+ dbus_message->len_offset = 12;
-+ cur += 4;
-+ while (cur < message + len
-+ && cur < message + 12 + 4 + array_header_len) {
-+ int header_code;
-+ int signature_len;
-+ unsigned char *signature;
-+ int str_len;
-+ unsigned char *str;
-+
-+ /* D-Bus alignment craziness */
-+ if ((cur - message) % 8 != 0)
-+ cur += 8 - (cur - message) % 8;
-+
-+ header_code = *(char *)cur;
-+ cur++;
-+ signature_len = *(char *)cur;
-+ /* All header fields of the current D-Bus spec have a simple
-+ * type, either o, s, g, or u */
-+ if (signature_len != 1)
-+ return -EINVAL;
-+ cur++;
-+ signature = cur;
-+ cur += signature_len + 1;
-+ if (signature[0] != 'o' &&
-+ signature[0] != 's' &&
-+ signature[0] != 'g' &&
-+ signature[0] != 'u')
-+ return -EINVAL;
-+
-+ if (signature[0] == 'u') {
-+ cur += 4;
-+ continue;
-+ }
-+
-+ if (signature[0] != 'g') {
-+ str_len = *(u32 *)cur;
-+ cur += 4;
-+ } else {
-+ str_len = *(char *)cur;
-+ cur += 1;
-+ }
-+
-+ str = cur;
-+ switch (header_code) {
-+ case 1:
-+ dbus_message->path = str;
-+ break;
-+ case 2:
-+ dbus_message->interface = str;
-+ break;
-+ case 3:
-+ dbus_message->member = str;
-+ break;
-+ case 6:
-+ dbus_message->destination = str;
-+ break;
-+ case 7:
-+ dbus_message->sender = str;
-+ break;
-+ case 8:
-+ dbus_message->body_signature = str;
-+ break;
-+ }
-+ cur += str_len + 1;
-+ }
-+
-+ dbus_message->padding_end = (8 - (cur - message) % 8) % 8;
-+
-+ /* Jump to body D-Bus alignment craziness */
-+ if ((cur - message) % 8 != 0)
-+ cur += 8 - (cur - message) % 8;
-+ dbus_message->new_header_offset = cur - message;
-+
-+ if (dbus_message->new_header_offset
-+ + dbus_message->body_length != len) {
-+ pr_warn("Message truncated? " \
-+ "Header %d + Body %d != Length %zd\n",
-+ dbus_message->new_header_offset,
-+ dbus_message->body_length, len);
-+ return -EINVAL;
-+ }
-+
-+ if (dbus_message->body_signature &&
-+ dbus_message->body_signature[0] == 's') {
-+ int str_len;
-+ str_len = *(u32 *)cur;
-+ cur += 4;
-+ dbus_message->arg0 = cur;
-+ cur += str_len + 1;
-+ }
-+
-+ if ((cur - message) % 4 != 0)
-+ cur += 4 - (cur - message) % 4;
-+
-+ if (dbus_message->body_signature &&
-+ dbus_message->body_signature[0] == 's' &&
-+ dbus_message->body_signature[1] == 's') {
-+ int str_len;
-+ str_len = *(u32 *)cur;
-+ cur += 4;
-+ dbus_message->arg1 = cur;
-+ cur += str_len + 1;
-+ }
-+
-+ if ((cur - message) % 4 != 0)
-+ cur += 4 - (cur - message) % 4;
-+
-+ if (dbus_message->body_signature &&
-+ dbus_message->body_signature[0] == 's' &&
-+ dbus_message->body_signature[1] == 's' &&
-+ dbus_message->body_signature[2] == 's') {
-+ int str_len;
-+ str_len = *(u32 *)cur;
-+ cur += 4;
-+ dbus_message->arg2 = cur;
-+ cur += str_len + 1;
-+ }
-+
-+ if ((cur - message) % 4 != 0)
-+ cur += 4 - (cur - message) % 4;
-+
-+ if (dbus_message->type == DBUS_MESSAGE_TYPE_SIGNAL &&
-+ dbus_message->sender && dbus_message->path &&
-+ dbus_message->interface && dbus_message->member &&
-+ dbus_message->arg0 &&
-+ strcmp(dbus_message->sender, "org.freedesktop.DBus") == 0 &&
-+ strcmp(dbus_message->interface, "org.freedesktop.DBus") == 0 &&
-+ strcmp(dbus_message->path, "/org/freedesktop/DBus") == 0) {
-+ if (strcmp(dbus_message->member, "NameAcquired") == 0)
-+ dbus_message->name_acquired = dbus_message->arg0;
-+ else if (strcmp(dbus_message->member, "NameLost") == 0)
-+ dbus_message->name_lost = dbus_message->arg0;
-+ }
-+
-+ return 0;
-+}
-diff --git a/net/bus/nfdbus/message.h b/net/bus/nfdbus/message.h
-new file mode 100644
-index 0000000..e3ea4d3
---- /dev/null
-+++ b/net/bus/nfdbus/message.h
-@@ -0,0 +1,71 @@
-+/*
-+ * message.h Basic D-Bus message parsing
-+ *
-+ * Copyright (C) 2010 Collabora Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ */
-+
-+#ifndef DBUS_MESSAGE_H
-+#define DBUS_MESSAGE_H
-+
-+#include <linux/list.h>
-+
-+#define DBUS_MAXIMUM_MATCH_RULE_LENGTH 1024
-+
-+/* Types of message */
-+
-+#define DBUS_MESSAGE_TYPE_INVALID 0
-+#define DBUS_MESSAGE_TYPE_METHOD_CALL 1
-+#define DBUS_MESSAGE_TYPE_METHOD_RETURN 2
-+#define DBUS_MESSAGE_TYPE_ERROR 3
-+#define DBUS_MESSAGE_TYPE_SIGNAL 4
-+#define DBUS_NUM_MESSAGE_TYPES 5
-+
-+/* No need to implement a feature-complete parser. It only implement what is
-+ * needed by the bus. */
-+struct dbus_message {
-+ char *message;
-+ size_t len;
-+ size_t new_len;
-+
-+ /* direct pointers to the fields */
-+ int type;
-+ char *path;
-+ char *interface;
-+ char *member;
-+ char *destination;
-+ char *sender;
-+ char *body_signature;
-+ int body_length;
-+ char *arg0;
-+ char *arg1;
-+ char *arg2;
-+ char *name_acquired;
-+ char *name_lost;
-+
-+ /* How to add the 'sender' field in the headers */
-+ int new_header_offset;
-+ int len_offset;
-+ int padding_end;
-+};
-+
-+int dbus_message_type_from_string(const char *type_str);
-+
-+int dbus_message_parse(unsigned char *message, size_t len,
-+ struct dbus_message *dbus_message);
-+
-+#endif /* DBUS_MESSAGE_H */
---
-1.7.7.6
-
+++ /dev/null
-From 7532e3f92cd858c9cbe441895f3e33d007c59f57 Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Wed, 20 Jun 2012 19:05:54 +0200
-Subject: [PATCH 14/15] netfilter: nfdbus: Add D-bus match rule implementation
-
-The D-Bus netfilter module needs to decode D-Bus match rules to decide
-if a given peer can receive or not a D-Bus message. Add a match rule
-implementation to be used by the netfilter D-Bus module.
-
-Based on a previous patch by Alban Crequy.
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
----
- net/bus/nfdbus/matchrule.c | 1131 ++++++++++++++++++++++++++++++++++++++++++++
- net/bus/nfdbus/matchrule.h | 82 ++++
- 2 files changed, 1213 insertions(+), 0 deletions(-)
- create mode 100644 net/bus/nfdbus/matchrule.c
- create mode 100644 net/bus/nfdbus/matchrule.h
-
-diff --git a/net/bus/nfdbus/matchrule.c b/net/bus/nfdbus/matchrule.c
-new file mode 100644
-index 0000000..1946345
---- /dev/null
-+++ b/net/bus/nfdbus/matchrule.c
-@@ -0,0 +1,1131 @@
-+/*
-+ * matchrule.c D-Bus match rule implementation
-+ *
-+ * Based on signals.c from dbus
-+ *
-+ * Copyright (C) 2010 Collabora, Ltd.
-+ * Copyright (C) 2003, 2005 Red Hat, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ */
-+
-+#include "matchrule.h"
-+
-+#include <linux/rbtree.h>
-+#include <linux/list.h>
-+#include <linux/slab.h>
-+
-+#include "message.h"
-+
-+enum bus_match_flags {
-+ BUS_MATCH_MESSAGE_TYPE = 1 << 0,
-+ BUS_MATCH_INTERFACE = 1 << 1,
-+ BUS_MATCH_MEMBER = 1 << 2,
-+ BUS_MATCH_SENDER = 1 << 3,
-+ BUS_MATCH_DESTINATION = 1 << 4,
-+ BUS_MATCH_PATH = 1 << 5,
-+ BUS_MATCH_ARGS = 1 << 6,
-+ BUS_MATCH_PATH_NAMESPACE = 1 << 7,
-+ BUS_MATCH_CLIENT_IS_EAVESDROPPING = 1 << 8
-+};
-+
-+struct bus_match_rule {
-+ /* For debugging only*/
-+ char *rule_text;
-+
-+ unsigned int flags; /**< BusMatchFlags */
-+
-+ int message_type;
-+ char *interface;
-+ char *member;
-+ char *sender;
-+ char *destination;
-+ char *path;
-+
-+ unsigned int *arg_lens;
-+ char **args;
-+ int args_len;
-+
-+ /* bus_match_rule is attached to rule_pool, either in a simple
-+ * double-linked list if the rule does not have any interface, or in a
-+ * red-black tree sorted by interface. If several rules can have the
-+ * same interface, the first one is attached with struct rb_node and the
-+ * next ones are in the list
-+ */
-+
-+ struct rb_node node;
-+ /* Doubly-linked non-circular list. If the rule has an interface, it is
-+ * in the rb tree and the single head is right here. Otherwise, the
-+ * single head is in rule_pool->rules_without_iface. With this data
-+ * structure, we don't need any allocation to insert or remove the rule.
-+ */
-+ struct hlist_head first;
-+ struct hlist_node list;
-+
-+ /* used to delete all names from the tree */
-+ struct list_head del_list;
-+};
-+
-+struct dbus_name {
-+ struct rb_node node;
-+ char *name;
-+
-+ /* used to delete all names from the tree */
-+ struct list_head del_list;
-+};
-+
-+#define BUS_MATCH_ARG_IS_PATH 0x8000000u
-+
-+#define DBUS_STRING_MAX_LENGTH 1024
-+
-+/** Max length of a match rule string; to keep people from hosing the
-+ * daemon with some huge rule
-+ */
-+#define DBUS_MAXIMUM_MATCH_RULE_LENGTH 1024
-+
-+struct bus_match_rule *bus_match_rule_new(gfp_t gfp_flags)
-+{
-+ struct bus_match_rule *rule;
-+
-+ rule = kzalloc(sizeof(struct bus_match_rule), gfp_flags);
-+ if (rule == NULL)
-+ return NULL;
-+
-+ return rule;
-+}
-+
-+void bus_match_rule_free(struct bus_match_rule *rule)
-+{
-+ kfree(rule->rule_text);
-+ kfree(rule->interface);
-+ kfree(rule->member);
-+ kfree(rule->sender);
-+ kfree(rule->destination);
-+ kfree(rule->path);
-+ kfree(rule->arg_lens);
-+
-+ /* can't use dbus_free_string_array() since there
-+ * are embedded NULL
-+ */
-+ if (rule->args) {
-+ int i;
-+
-+ i = 0;
-+ while (i < rule->args_len) {
-+ kfree(rule->args[i]);
-+ ++i;
-+ }
-+
-+ kfree(rule->args);
-+ }
-+
-+ kfree(rule);
-+}
-+
-+static int
-+bus_match_rule_set_message_type(struct bus_match_rule *rule,
-+ int type,
-+ gfp_t gfp_flags)
-+{
-+ rule->flags |= BUS_MATCH_MESSAGE_TYPE;
-+
-+ rule->message_type = type;
-+
-+ return 1;
-+}
-+
-+static int
-+bus_match_rule_set_interface(struct bus_match_rule *rule,
-+ const char *interface,
-+ gfp_t gfp_flags)
-+{
-+ char *new;
-+
-+ WARN_ON(!interface);
-+
-+ new = kstrdup(interface, gfp_flags);
-+ if (new == NULL)
-+ return 0;
-+
-+ rule->flags |= BUS_MATCH_INTERFACE;
-+ kfree(rule->interface);
-+ rule->interface = new;
-+
-+ return 1;
-+}
-+
-+static int
-+bus_match_rule_set_member(struct bus_match_rule *rule,
-+ const char *member,
-+ gfp_t gfp_flags)
-+{
-+ char *new;
-+
-+ WARN_ON(!member);
-+
-+ new = kstrdup(member, gfp_flags);
-+ if (new == NULL)
-+ return 0;
-+
-+ rule->flags |= BUS_MATCH_MEMBER;
-+ kfree(rule->member);
-+ rule->member = new;
-+
-+ return 1;
-+}
-+
-+static int
-+bus_match_rule_set_sender(struct bus_match_rule *rule,
-+ const char *sender,
-+ gfp_t gfp_flags)
-+{
-+ char *new;
-+
-+ WARN_ON(!sender);
-+
-+ new = kstrdup(sender, gfp_flags);
-+ if (new == NULL)
-+ return 0;
-+
-+ rule->flags |= BUS_MATCH_SENDER;
-+ kfree(rule->sender);
-+ rule->sender = new;
-+
-+ return 1;
-+}
-+
-+static int
-+bus_match_rule_set_destination(struct bus_match_rule *rule,
-+ const char *destination,
-+ gfp_t gfp_flags)
-+{
-+ char *new;
-+
-+ WARN_ON(!destination);
-+
-+ new = kstrdup(destination, gfp_flags);
-+ if (new == NULL)
-+ return 0;
-+
-+ rule->flags |= BUS_MATCH_DESTINATION;
-+ kfree(rule->destination);
-+ rule->destination = new;
-+
-+ return 1;
-+}
-+
-+#define ISWHITE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || \
-+ ((c) == '\r'))
-+
-+static int find_key(const char *str, int start, char *key, int *value_pos)
-+{
-+ const char *p;
-+ const char *s;
-+ const char *key_start;
-+ const char *key_end;
-+
-+ s = str;
-+
-+ p = s + start;
-+
-+ while (*p && ISWHITE(*p))
-+ ++p;
-+
-+ key_start = p;
-+
-+ while (*p && *p != '=' && !ISWHITE(*p))
-+ ++p;
-+
-+ key_end = p;
-+
-+ while (*p && ISWHITE(*p))
-+ ++p;
-+
-+ if (key_start == key_end) {
-+ /* Empty match rules or trailing whitespace are OK */
-+ *value_pos = p - s;
-+ return 1;
-+ }
-+
-+ if (*p != '=') {
-+ pr_warn("Match rule has a key with no subsequent '=' character");
-+ return 0;
-+ }
-+ ++p;
-+
-+ strncat(key, key_start, key_end - key_start);
-+
-+ *value_pos = p - s;
-+
-+ return 1;
-+}
-+
-+static int find_value(const char *str, int start, const char *key, char *value,
-+ int *value_end)
-+{
-+ const char *p;
-+ const char *s;
-+ char quote_char;
-+ int orig_len;
-+
-+ orig_len = strlen(value);
-+
-+ s = str;
-+
-+ p = s + start;
-+
-+ quote_char = '\0';
-+
-+ while (*p) {
-+ if (quote_char == '\0') {
-+ switch (*p) {
-+ case '\0':
-+ goto done;
-+
-+ case '\'':
-+ quote_char = '\'';
-+ goto next;
-+
-+ case ',':
-+ ++p;
-+ goto done;
-+
-+ case '\\':
-+ quote_char = '\\';
-+ goto next;
-+
-+ default:
-+ strncat(value, p, 1);
-+ }
-+ } else if (quote_char == '\\') {
-+ /*\ only counts as an escape if escaping a quote mark */
-+ if (*p != '\'')
-+ strncat(value, "\\", 1);
-+
-+ strncat(value, p, 1);
-+
-+ quote_char = '\0';
-+ } else {
-+ if (*p == '\'')
-+ quote_char = '\0';
-+ else
-+ strncat(value, p, 1);
-+ }
-+
-+next:
-+ ++p;
-+ }
-+
-+done:
-+
-+ if (quote_char == '\\')
-+ strncat(value, "\\", 1);
-+ else if (quote_char == '\'') {
-+ pr_warn("Unbalanced quotation marks in match rule");
-+ return 0;
-+ }
-+
-+ /* Zero-length values are allowed */
-+
-+ *value_end = p - s;
-+
-+ return 1;
-+}
-+
-+/* duplicates aren't allowed so the real legitimate max is only 6 or
-+ * so. Leaving extra so we don't have to bother to update it.
-+ * FIXME this is sort of busted now with arg matching, but we let
-+ * you match on up to 10 args for now
-+ */
-+#define MAX_RULE_TOKENS 16
-+
-+/* this is slightly too high level to be termed a "token"
-+ * but let's not be pedantic.
-+ */
-+struct rule_token {
-+ char *key;
-+ char *value;
-+};
-+
-+static int tokenize_rule(const char *rule_text,
-+ struct rule_token tokens[MAX_RULE_TOKENS],
-+ gfp_t gfp_flags)
-+{
-+ int i;
-+ int pos;
-+ int retval;
-+
-+ retval = 0;
-+
-+ i = 0;
-+ pos = 0;
-+ while (i < MAX_RULE_TOKENS &&
-+ pos < strlen(rule_text)) {
-+ char *key;
-+ char *value;
-+
-+ key = kzalloc(DBUS_STRING_MAX_LENGTH, gfp_flags);
-+ if (!key) {
-+ pr_err("Out of memory");
-+ return 0;
-+ }
-+
-+ value = kzalloc(DBUS_STRING_MAX_LENGTH, gfp_flags);
-+ if (!value) {
-+ kfree(key);
-+ pr_err("Out of memory");
-+ return 0;
-+ }
-+
-+ if (!find_key(rule_text, pos, key, &pos))
-+ goto out;
-+
-+ if (strlen(key) == 0)
-+ goto next;
-+
-+ tokens[i].key = key;
-+
-+ if (!find_value(rule_text, pos, tokens[i].key, value, &pos))
-+ goto out;
-+
-+ tokens[i].value = value;
-+
-+next:
-+ ++i;
-+ }
-+
-+ retval = 1;
-+
-+out:
-+ if (!retval) {
-+ i = 0;
-+ while (tokens[i].key || tokens[i].value) {
-+ kfree(tokens[i].key);
-+ kfree(tokens[i].value);
-+ tokens[i].key = NULL;
-+ tokens[i].value = NULL;
-+ ++i;
-+ }
-+ }
-+
-+ return retval;
-+}
-+
-+/*
-+ * The format is comma-separated with strings quoted with single quotes
-+ * as for the shell (to escape a literal single quote, use '\'').
-+ *
-+ * type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',
-+ * member='Foo', path='/bar/foo',destination=':452345.34'
-+ *
-+ */
-+struct bus_match_rule *bus_match_rule_parse(const char *rule_text,
-+ gfp_t gfp_flags)
-+{
-+ struct bus_match_rule *rule;
-+ struct rule_token tokens[MAX_RULE_TOKENS+1]; /* NULL termination + 1 */
-+ int i;
-+
-+ if (strlen(rule_text) > DBUS_MAXIMUM_MATCH_RULE_LENGTH) {
-+ pr_warn("Match rule text is %ld bytes, maximum is %d",
-+ strlen(rule_text),
-+ DBUS_MAXIMUM_MATCH_RULE_LENGTH);
-+ return NULL;
-+ }
-+
-+ memset(tokens, '\0', sizeof(tokens));
-+
-+ rule = bus_match_rule_new(gfp_flags);
-+ if (rule == NULL) {
-+ pr_err("Out of memory");
-+ goto failed;
-+ }
-+
-+ rule->rule_text = kstrdup(rule_text, gfp_flags);
-+ if (rule->rule_text == NULL) {
-+ pr_err("Out of memory");
-+ goto failed;
-+ }
-+
-+ if (!tokenize_rule(rule_text, tokens, gfp_flags))
-+ goto failed;
-+
-+ i = 0;
-+ while (tokens[i].key != NULL) {
-+ const char *key = tokens[i].key;
-+ const char *value = tokens[i].value;
-+
-+ if (strcmp(key, "type") == 0) {
-+ int t;
-+
-+ if (rule->flags & BUS_MATCH_MESSAGE_TYPE) {
-+ pr_warn("Key %s specified twice in match rule\n",
-+ key);
-+ goto failed;
-+ }
-+
-+ t = dbus_message_type_from_string(value);
-+
-+ if (t == DBUS_MESSAGE_TYPE_INVALID) {
-+ pr_warn("Invalid message type (%s) in match rule\n",
-+ value);
-+ goto failed;
-+ }
-+
-+ if (!bus_match_rule_set_message_type(rule, t,
-+ gfp_flags)) {
-+ pr_err("Out of memeory");
-+ goto failed;
-+ }
-+ } else if (strcmp(key, "sender") == 0) {
-+ if (rule->flags & BUS_MATCH_SENDER) {
-+ pr_warn("Key %s specified twice in match rule\n",
-+ key);
-+ goto failed;
-+ }
-+
-+ if (!bus_match_rule_set_sender(rule, value,
-+ gfp_flags)) {
-+ pr_err("Out of memeory");
-+ goto failed;
-+ }
-+ } else if (strcmp(key, "interface") == 0) {
-+ if (rule->flags & BUS_MATCH_INTERFACE) {
-+ pr_warn("Key %s specified twice in match rule\n",
-+ key);
-+ goto failed;
-+ }
-+
-+ if (!bus_match_rule_set_interface(rule, value,
-+ gfp_flags)) {
-+ pr_err("Out of memeory");
-+ goto failed;
-+ }
-+ } else if (strcmp(key, "member") == 0) {
-+ if (rule->flags & BUS_MATCH_MEMBER) {
-+ pr_warn("Key %s specified twice in match rule\n",
-+ key);
-+ goto failed;
-+ }
-+
-+ if (!bus_match_rule_set_member(rule, value,
-+ gfp_flags)) {
-+ pr_err("Out of memeory");
-+ goto failed;
-+ }
-+ } else if (strcmp(key, "destination") == 0) {
-+ if (rule->flags & BUS_MATCH_DESTINATION) {
-+ pr_warn("Key %s specified twice in match rule\n",
-+ key);
-+ goto failed;
-+ }
-+
-+ if (!bus_match_rule_set_destination(rule, value,
-+ gfp_flags)) {
-+ pr_err("Out of memeory");
-+ goto failed;
-+ }
-+ } else if (strcmp(key, "eavesdrop") == 0) {
-+ if (strcmp(value, "true") == 0) {
-+ rule->flags |= BUS_MATCH_CLIENT_IS_EAVESDROPPING;
-+ } else if (strcmp(value, "false") == 0) {
-+ rule->flags &= ~(BUS_MATCH_CLIENT_IS_EAVESDROPPING);
-+ } else {
-+ pr_warn("eavesdrop='%s' is invalid, " \
-+ "it should be 'true' or 'false'\n",
-+ value);
-+ goto failed;
-+ }
-+ } else if (strncmp(key, "arg", 3) != 0) {
-+ pr_warn("Unknown key \"%s\" in match rule\n",
-+ key);
-+ goto failed;
-+ }
-+
-+ ++i;
-+ }
-+
-+ goto out;
-+
-+failed:
-+ if (rule) {
-+ bus_match_rule_free(rule);
-+ rule = NULL;
-+ }
-+
-+out:
-+
-+ i = 0;
-+ while (tokens[i].key || tokens[i].value) {
-+ WARN_ON(i >= MAX_RULE_TOKENS);
-+ kfree(tokens[i].key);
-+ kfree(tokens[i].value);
-+ ++i;
-+ }
-+
-+ return rule;
-+}
-+
-+/* return the match rule containing the hlist_head. It may not be the first
-+ * match rule in the list. */
-+struct bus_match_rule *match_rule_search(struct rb_root *root,
-+ const char *interface)
-+{
-+ struct rb_node *node = root->rb_node;
-+
-+ while (node) {
-+ struct bus_match_rule *data =
-+ container_of(node, struct bus_match_rule, node);
-+ int result;
-+
-+ result = strcmp(interface, data->interface);
-+
-+ if (result < 0)
-+ node = node->rb_left;
-+ else if (result > 0)
-+ node = node->rb_right;
-+ else
-+ return data;
-+ }
-+ return NULL;
-+}
-+
-+void match_rule_insert(struct rb_root *root, struct bus_match_rule *data)
-+{
-+ struct rb_node **new = &(root->rb_node), *parent = NULL;
-+
-+ /* Figure out where to put new node */
-+ while (*new) {
-+ struct bus_match_rule *this =
-+ container_of(*new, struct bus_match_rule, node);
-+ int result = strcmp(data->interface, this->interface);
-+
-+ parent = *new;
-+ if (result < 0)
-+ new = &((*new)->rb_left);
-+ else if (result > 0)
-+ new = &((*new)->rb_right);
-+ else {
-+ /* the head is not used */
-+ INIT_HLIST_HEAD(&data->first);
-+ /* Add it at the beginning of the list */
-+ hlist_add_head(&data->list, &this->first);
-+ return;
-+ }
-+ }
-+
-+ /* this rule is single in its list */
-+ INIT_HLIST_HEAD(&data->first);
-+ hlist_add_head(&data->list, &data->first);
-+
-+ /* Add new node and rebalance tree. */
-+ rb_link_node(&data->node, parent, new);
-+ rb_insert_color(&data->node, root);
-+}
-+
-+struct bus_match_maker *bus_matchmaker_new(gfp_t gfp_flags)
-+{
-+ struct bus_match_maker *matchmaker;
-+ int i;
-+
-+ matchmaker = kzalloc(sizeof(struct bus_match_maker), gfp_flags);
-+ if (matchmaker == NULL)
-+ return NULL;
-+
-+ for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++) {
-+ struct rule_pool *p = matchmaker->rules_by_type + i;
-+
-+ p->rules_by_iface = RB_ROOT;
-+ }
-+
-+ kref_init(&matchmaker->kref);
-+
-+ return matchmaker;
-+}
-+
-+void bus_matchmaker_free(struct kref *kref)
-+{
-+ struct bus_match_maker *matchmaker;
-+ struct list_head del_list;
-+ struct rb_node *n;
-+ int i;
-+
-+ matchmaker = container_of(kref, struct bus_match_maker, kref);
-+
-+ /* free names */
-+ INIT_LIST_HEAD(&del_list);
-+ n = matchmaker->names.rb_node;
-+ if (n) {
-+ struct dbus_name *dbus_name, *cur, *tmp;
-+
-+ dbus_name = rb_entry(n, struct dbus_name, node);
-+ list_add_tail(&dbus_name->del_list, &del_list);
-+
-+ list_for_each_entry(cur, &del_list, del_list) {
-+ struct dbus_name *right, *left;
-+ if (cur->node.rb_right) {
-+ right = rb_entry(cur->node.rb_right,
-+ struct dbus_name, node);
-+ list_add_tail(&right->del_list, &del_list);
-+ }
-+ if (cur->node.rb_left) {
-+ left = rb_entry(cur->node.rb_left,
-+ struct dbus_name, node);
-+ list_add_tail(&left->del_list, &del_list);
-+ }
-+ }
-+ list_for_each_entry_safe(dbus_name, tmp, &del_list, del_list) {
-+ kfree(dbus_name->name);
-+ list_del(&dbus_name->del_list);
-+ kfree(dbus_name);
-+ }
-+ }
-+ WARN_ON(!list_empty_careful(&del_list));
-+
-+ /* free match rules */
-+ for (i = 0 ; i < DBUS_NUM_MESSAGE_TYPES ; i++) {
-+ struct rule_pool *pool = matchmaker->rules_by_type + i;
-+ struct bus_match_rule *match_rule, *cur, *tmp;
-+ struct hlist_node *list_tmp, *list_tmp2;
-+
-+ /* free match rules from the list */
-+ hlist_for_each_entry_safe(cur, list_tmp, list_tmp2,
-+ &pool->rules_without_iface, list) {
-+ bus_match_rule_free(cur);
-+ }
-+
-+ /* free match rules from the tree */
-+ if (!pool->rules_by_iface.rb_node)
-+ continue;
-+ match_rule = rb_entry(pool->rules_by_iface.rb_node,
-+ struct bus_match_rule, node);
-+ list_add_tail(&match_rule->del_list, &del_list);
-+
-+ list_for_each_entry(cur, &del_list, del_list) {
-+ struct bus_match_rule *right, *left;
-+ if (cur->node.rb_right) {
-+ right = rb_entry(cur->node.rb_right,
-+ struct bus_match_rule, node);
-+ list_add_tail(&right->del_list, &del_list);
-+ }
-+ if (cur->node.rb_left) {
-+ left = rb_entry(cur->node.rb_left,
-+ struct bus_match_rule, node);
-+ list_add_tail(&left->del_list, &del_list);
-+ }
-+ }
-+ list_for_each_entry_safe(match_rule, tmp, &del_list, del_list) {
-+ /* keep a ref during the loop to ensure the first
-+ * iteration of the loop does not delete it */
-+ hlist_for_each_entry_safe(cur, list_tmp, list_tmp2,
-+ &match_rule->first, list) {
-+ if (cur != match_rule)
-+ bus_match_rule_free(cur);
-+ }
-+ list_del(&match_rule->del_list);
-+ bus_match_rule_free(match_rule);
-+ }
-+ WARN_ON(!list_empty_careful(&del_list));
-+ }
-+
-+ kfree(matchmaker);
-+}
-+
-+/* The rule can't be modified after it's added. */
-+int bus_matchmaker_add_rule(struct bus_match_maker *matchmaker,
-+ struct bus_match_rule *rule)
-+{
-+ struct rule_pool *pool;
-+
-+ WARN_ON(rule->message_type < 0);
-+ WARN_ON(rule->message_type >= DBUS_NUM_MESSAGE_TYPES);
-+
-+ pool = matchmaker->rules_by_type + rule->message_type;
-+
-+ if (rule->interface)
-+ match_rule_insert(&pool->rules_by_iface, rule);
-+ else
-+ hlist_add_head(&rule->list, &pool->rules_without_iface);
-+
-+ return 1;
-+}
-+
-+static int match_rule_equal(struct bus_match_rule *a,
-+ struct bus_match_rule *b)
-+{
-+ if (a->flags != b->flags)
-+ return 0;
-+
-+ if ((a->flags & BUS_MATCH_MESSAGE_TYPE) &&
-+ a->message_type != b->message_type)
-+ return 0;
-+
-+ if ((a->flags & BUS_MATCH_MEMBER) &&
-+ strcmp(a->member, b->member) != 0)
-+ return 0;
-+
-+ if ((a->flags & BUS_MATCH_PATH) &&
-+ strcmp(a->path, b->path) != 0)
-+ return 0;
-+
-+ if ((a->flags & BUS_MATCH_INTERFACE) &&
-+ strcmp(a->interface, b->interface) != 0)
-+ return 0;
-+
-+ if ((a->flags & BUS_MATCH_SENDER) &&
-+ strcmp(a->sender, b->sender) != 0)
-+ return 0;
-+
-+ if ((a->flags & BUS_MATCH_DESTINATION) &&
-+ strcmp(a->destination, b->destination) != 0)
-+ return 0;
-+
-+ if (a->flags & BUS_MATCH_ARGS) {
-+ int i;
-+
-+ if (a->args_len != b->args_len)
-+ return 0;
-+
-+ i = 0;
-+ while (i < a->args_len) {
-+ int length;
-+
-+ if ((a->args[i] != NULL) != (b->args[i] != NULL))
-+ return 0;
-+
-+ if (a->arg_lens[i] != b->arg_lens[i])
-+ return 0;
-+
-+ length = a->arg_lens[i] & ~BUS_MATCH_ARG_IS_PATH;
-+
-+ if (a->args[i] != NULL) {
-+ WARN_ON(!b->args[i]);
-+ if (memcmp(a->args[i], b->args[i], length) != 0)
-+ return 0;
-+ }
-+
-+ ++i;
-+ }
-+ }
-+
-+ return 1;
-+}
-+
-+/* Remove a single rule which is equal to the given rule by value */
-+void bus_matchmaker_remove_rule_by_value(struct bus_match_maker *matchmaker,
-+ struct bus_match_rule *rule)
-+{
-+ struct rule_pool *pool;
-+
-+ WARN_ON(rule->message_type < 0);
-+ WARN_ON(rule->message_type >= DBUS_NUM_MESSAGE_TYPES);
-+
-+ pool = matchmaker->rules_by_type + rule->message_type;
-+
-+ if (rule->interface) {
-+ struct bus_match_rule *head =
-+ match_rule_search(&pool->rules_by_iface,
-+ rule->interface);
-+
-+ struct hlist_node *cur;
-+ struct bus_match_rule *cur_rule;
-+ hlist_for_each_entry(cur_rule, cur, &head->first, list) {
-+ if (match_rule_equal(cur_rule, rule)) {
-+ hlist_del(cur);
-+ if (hlist_empty(&head->first))
-+ rb_erase(&head->node,
-+ &pool->rules_by_iface);
-+ bus_match_rule_free(cur_rule);
-+ break;
-+ }
-+ }
-+ } else {
-+ struct hlist_head *head = &pool->rules_without_iface;
-+
-+ struct hlist_node *cur;
-+ struct bus_match_rule *cur_rule;
-+ hlist_for_each_entry(cur_rule, cur, head, list) {
-+ if (match_rule_equal(cur_rule, rule)) {
-+ hlist_del(cur);
-+ bus_match_rule_free(cur_rule);
-+ break;
-+ }
-+ }
-+ }
-+
-+}
-+
-+static int connection_is_primary_owner(struct bus_match_maker *connection,
-+ const char *service_name)
-+{
-+ struct rb_node *node = connection->names.rb_node;
-+
-+ if (!service_name)
-+ return 0;
-+
-+ while (node) {
-+ struct dbus_name *data = container_of(node, struct dbus_name,
-+ node);
-+ int result;
-+
-+ result = strcmp(service_name, data->name);
-+
-+ if (result < 0)
-+ node = node->rb_left;
-+ else if (result > 0)
-+ node = node->rb_right;
-+ else
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static int match_rule_matches(struct bus_match_maker *matchmaker,
-+ struct bus_match_maker *sender,
-+ int eavesdrop,
-+ struct bus_match_rule *rule,
-+ const struct dbus_message *message)
-+{
-+ /* Don't consider the rule if this is a eavesdropping match rule
-+ * and eavesdropping is not allowed on that peer */
-+ if ((rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING) && !eavesdrop)
-+ return 0;
-+
-+ /* Since D-Bus 1.5.6, match rules do not match messages which have a
-+ * DESTINATION field unless the match rule specifically requests this
-+ * by specifying eavesdrop='true' in the match rule. */
-+ if (message->destination &&
-+ !(rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING))
-+ return 0;
-+
-+ if (rule->flags & BUS_MATCH_MEMBER) {
-+ const char *member;
-+
-+ WARN_ON(!rule->member);
-+
-+ member = message->member;
-+ if (member == NULL)
-+ return 0;
-+
-+ if (strcmp(member, rule->member) != 0)
-+ return 0;
-+ }
-+
-+ if (rule->flags & BUS_MATCH_SENDER) {
-+ WARN_ON(!rule->sender);
-+
-+ if (sender == NULL) {
-+ if (strcmp(rule->sender,
-+ "org.freedesktop.DBus") != 0)
-+ return 0;
-+ } else
-+ if (!connection_is_primary_owner(sender, rule->sender))
-+ return 0;
-+ }
-+
-+ if (rule->flags & BUS_MATCH_DESTINATION) {
-+ const char *destination;
-+
-+ WARN_ON(!rule->destination);
-+
-+ destination = message->destination;
-+ if (destination == NULL)
-+ return 0;
-+
-+ /* This will not just work out of the box because it this is
-+ * an eavesdropping match rule. */
-+ if (matchmaker == NULL) {
-+ if (strcmp(rule->destination,
-+ "org.freedesktop.DBus") != 0)
-+ return 0;
-+ } else
-+ if (!connection_is_primary_owner(matchmaker,
-+ rule->destination))
-+ return 0;
-+ }
-+
-+ if (rule->flags & BUS_MATCH_PATH) {
-+ const char *path;
-+
-+ WARN_ON(!rule->path);
-+
-+ path = message->path;
-+ if (path == NULL)
-+ return 0;
-+
-+ if (strcmp(path, rule->path) != 0)
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+static bool get_recipients_from_list(struct bus_match_maker *matchmaker,
-+ struct bus_match_maker *sender,
-+ int eavesdrop,
-+ struct hlist_head *rules,
-+ const struct dbus_message *message)
-+{
-+ struct hlist_node *cur;
-+ struct bus_match_rule *rule;
-+
-+ if (rules == NULL) {
-+ pr_debug("no rules of this type\n");
-+ return 0;
-+ }
-+
-+ hlist_for_each_entry(rule, cur, rules, list) {
-+ if (match_rule_matches(matchmaker, sender, eavesdrop, rule,
-+ message)) {
-+ pr_debug("[YES] deliver with match rule \"%s\"\n",
-+ rule->rule_text);
-+ return 1;
-+ } else {
-+ pr_debug("[NO] deliver with match rule \"%s\"\n",
-+ rule->rule_text);
-+ }
-+ }
-+ pr_debug("[NO] no match rules\n");
-+ return 0;
-+}
-+
-+static struct hlist_head
-+*bus_matchmaker_get_rules(struct bus_match_maker *matchmaker,
-+ int message_type, const char *interface)
-+{
-+ static struct hlist_head empty = {0,};
-+ struct rule_pool *p;
-+
-+ WARN_ON(message_type < 0);
-+ WARN_ON(message_type >= DBUS_NUM_MESSAGE_TYPES);
-+
-+ p = matchmaker->rules_by_type + message_type;
-+
-+ if (interface == NULL)
-+ return &p->rules_without_iface;
-+ else {
-+ struct bus_match_rule *rule =
-+ match_rule_search(&p->rules_by_iface, interface);
-+ if (rule)
-+ return &rule->first;
-+ else
-+ return ∅
-+ }
-+}
-+
-+bool bus_matchmaker_filter(struct bus_match_maker *matchmaker,
-+ struct bus_match_maker *sender,
-+ int eavesdrop,
-+ const struct dbus_message *message)
-+{
-+ int type;
-+ const char *interface;
-+ struct hlist_head *neither, *just_type, *just_iface, *both;
-+
-+ type = message->type;
-+ interface = message->interface;
-+
-+ neither = bus_matchmaker_get_rules(matchmaker,
-+ DBUS_MESSAGE_TYPE_INVALID, NULL);
-+ just_type = just_iface = both = NULL;
-+
-+ if (interface != NULL)
-+ just_iface = bus_matchmaker_get_rules(matchmaker,
-+ DBUS_MESSAGE_TYPE_INVALID,
-+ interface);
-+
-+ if (type > DBUS_MESSAGE_TYPE_INVALID && type < DBUS_NUM_MESSAGE_TYPES) {
-+ just_type = bus_matchmaker_get_rules(matchmaker, type, NULL);
-+
-+ if (interface != NULL)
-+ both = bus_matchmaker_get_rules(matchmaker, type,
-+ interface);
-+ }
-+
-+ if (get_recipients_from_list(matchmaker, sender, eavesdrop, neither,
-+ message))
-+ return 1;
-+ if (get_recipients_from_list(matchmaker, sender, eavesdrop, just_iface,
-+ message))
-+ return 1;
-+ if (get_recipients_from_list(matchmaker, sender, eavesdrop, just_type,
-+ message))
-+ return 1;
-+ if (get_recipients_from_list(matchmaker, sender, eavesdrop, both,
-+ message))
-+ return 1;
-+
-+ return connection_is_primary_owner(matchmaker, message->destination);
-+}
-+
-+void bus_matchmaker_add_name(struct bus_match_maker *matchmaker,
-+ const char *name,
-+ gfp_t gfp_flags)
-+{
-+ struct dbus_name *dbus_name;
-+ struct rb_node **new = &(matchmaker->names.rb_node), *parent = NULL;
-+
-+ dbus_name = kmalloc(sizeof(struct dbus_name), gfp_flags);
-+ if (!dbus_name)
-+ return;
-+ dbus_name->name = kstrdup(name, gfp_flags);
-+ if (!dbus_name->name)
-+ return;
-+
-+ /* Figure out where to put new node */
-+ while (*new) {
-+ struct dbus_name *this = container_of(*new, struct dbus_name,
-+ node);
-+ int result = strcmp(dbus_name->name, this->name);
-+
-+ parent = *new;
-+ if (result < 0)
-+ new = &((*new)->rb_left);
-+ else if (result > 0)
-+ new = &((*new)->rb_right);
-+ else
-+ return;
-+ }
-+
-+ /* Add new node and rebalance tree. */
-+ rb_link_node(&dbus_name->node, parent, new);
-+ rb_insert_color(&dbus_name->node, &matchmaker->names);
-+}
-+
-+void bus_matchmaker_remove_name(struct bus_match_maker *matchmaker,
-+ const char *name)
-+{
-+ struct rb_node *node = matchmaker->names.rb_node;
-+
-+ while (node) {
-+ struct dbus_name *data = container_of(node, struct dbus_name,
-+ node);
-+ int result;
-+
-+ result = strcmp(name, data->name);
-+
-+ if (result < 0)
-+ node = node->rb_left;
-+ else if (result > 0)
-+ node = node->rb_right;
-+ else {
-+ rb_erase(&data->node, &matchmaker->names);
-+ kfree(data->name);
-+ kfree(data);
-+ }
-+ }
-+
-+}
-diff --git a/net/bus/nfdbus/matchrule.h b/net/bus/nfdbus/matchrule.h
-new file mode 100644
-index 0000000..e16580c
---- /dev/null
-+++ b/net/bus/nfdbus/matchrule.h
-@@ -0,0 +1,82 @@
-+/*
-+ * signals.h Bus signal connection implementation
-+ *
-+ * Copyright (C) 2003 Red Hat, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ */
-+
-+#ifndef BUS_SIGNALS_H
-+#define BUS_SIGNALS_H
-+
-+#include <linux/gfp.h>
-+#include <linux/list.h>
-+#include <linux/rbtree.h>
-+#include <linux/slab.h>
-+#include <net/af_bus.h>
-+
-+#include "message.h"
-+
-+struct bus_match_rule *bus_match_rule_new(gfp_t gfp_flags);
-+void bus_match_rule_free(struct bus_match_rule *rule);
-+
-+struct bus_match_rule *bus_match_rule_parse(const char *rule_text,
-+ gfp_t gfp_flags);
-+
-+struct rule_pool {
-+ /* Maps non-NULL interface names to a list of bus_match_rule */
-+ struct rb_root rules_by_iface;
-+
-+ /* List of bus_match_rule which don't specify an interface */
-+ struct hlist_head rules_without_iface;
-+};
-+
-+struct bus_match_maker {
-+ struct sockaddr_bus addr;
-+
-+ struct hlist_node table_node;
-+
-+ /* Pools of rules, grouped by the type of message they match. 0
-+ * (DBUS_MESSAGE_TYPE_INVALID) represents rules that do not specify a
-+ * message type.
-+ */
-+ struct rule_pool rules_by_type[DBUS_NUM_MESSAGE_TYPES];
-+
-+ struct rb_root names;
-+
-+ struct kref kref;
-+};
-+
-+
-+struct bus_match_maker *bus_matchmaker_new(gfp_t gfp_flags);
-+void bus_matchmaker_free(struct kref *kref);
-+
-+int bus_matchmaker_add_rule(struct bus_match_maker *matchmaker,
-+ struct bus_match_rule *rule);
-+void bus_matchmaker_remove_rule_by_value(struct bus_match_maker *matchmaker,
-+ struct bus_match_rule *value);
-+
-+bool bus_matchmaker_filter(struct bus_match_maker *matchmaker,
-+ struct bus_match_maker *sender,
-+ int eavesdrop,
-+ const struct dbus_message *message);
-+
-+void bus_matchmaker_add_name(struct bus_match_maker *matchmaker,
-+ const char *name, gfp_t gfp_flags);
-+void bus_matchmaker_remove_name(struct bus_match_maker *matchmaker,
-+ const char *name);
-+
-+#endif /* BUS_SIGNALS_H */
---
-1.7.7.6
-
+++ /dev/null
-From e4839f64c6608a2199d46819e77ed03233563301 Mon Sep 17 00:00:00 2001
-From: Alban Crequy <alban.crequy@collabora.co.uk>
-Date: Fri, 22 Jun 2012 14:20:50 +0200
-Subject: [PATCH 15/15] netfilter: add netfilter D-Bus module
-
-AF_BUS has netfilter hooks on the packet sending path. This allows the
-netfilter subsystem to register netfilter hook handlers.
-
-The netfilter_dbus module allows to inspect D-Bus messages and take
-actions based on the information contained on these messages.
-
-Signed-off-by: Alban Crequy <alban.crequy@collabora.co.uk>
----
- net/bus/Kconfig | 2 +
- net/bus/Makefile | 3 +
- net/bus/nfdbus/Kconfig | 12 ++
- net/bus/nfdbus/Makefile | 6 +
- net/bus/nfdbus/nfdbus.c | 458 +++++++++++++++++++++++++++++++++++++++++++++++
- net/bus/nfdbus/nfdbus.h | 44 +++++
- 6 files changed, 525 insertions(+), 0 deletions(-)
- create mode 100644 net/bus/nfdbus/Kconfig
- create mode 100644 net/bus/nfdbus/Makefile
- create mode 100644 net/bus/nfdbus/nfdbus.c
- create mode 100644 net/bus/nfdbus/nfdbus.h
-
-diff --git a/net/bus/Kconfig b/net/bus/Kconfig
-index 5f01410..4ec0beec 100644
---- a/net/bus/Kconfig
-+++ b/net/bus/Kconfig
-@@ -13,3 +13,5 @@ config AF_BUS
- called bus.
-
- Say N unless you know what you are doing.
-+
-+source "net/bus/nfdbus/Kconfig"
-diff --git a/net/bus/Makefile b/net/bus/Makefile
-index 8c1fea2..a6ba263 100644
---- a/net/bus/Makefile
-+++ b/net/bus/Makefile
-@@ -5,3 +5,6 @@
- obj-$(CONFIG_AF_BUS) += af-bus.o
-
- af-bus-y := af_bus.o garbage.o
-+
-+# Dbus
-+obj-$(CONFIG_NETFILTER_DBUS) += nfdbus/
-diff --git a/net/bus/nfdbus/Kconfig b/net/bus/nfdbus/Kconfig
-new file mode 100644
-index 0000000..25699a1
---- /dev/null
-+++ b/net/bus/nfdbus/Kconfig
-@@ -0,0 +1,12 @@
-+#
-+# Netfilter D-Bus module configuration
-+#
-+config NETFILTER_DBUS
-+ tristate "Netfilter D-bus (EXPERIMENTAL)"
-+ depends on AF_BUS && CONNECTOR && EXPERIMENTAL
-+ ---help---
-+ If you say Y here, you will include support for a netfilter hook to
-+ parse D-Bus messages sent using the AF_BUS socket address family.
-+
-+ To compile this as a module, choose M here: the module will be
-+ called netfilter_dbus.
-diff --git a/net/bus/nfdbus/Makefile b/net/bus/nfdbus/Makefile
-new file mode 100644
-index 0000000..1a825f8
---- /dev/null
-+++ b/net/bus/nfdbus/Makefile
-@@ -0,0 +1,6 @@
-+#
-+# Makefile for the netfilter D-Bus module
-+#
-+obj-$(CONFIG_NETFILTER_DBUS) += netfilter_dbus.o
-+
-+netfilter_dbus-y := nfdbus.o message.o matchrule.o
-diff --git a/net/bus/nfdbus/nfdbus.c b/net/bus/nfdbus/nfdbus.c
-new file mode 100644
-index 0000000..be8387a
---- /dev/null
-+++ b/net/bus/nfdbus/nfdbus.c
-@@ -0,0 +1,458 @@
-+/*
-+ * nfdbus.c - Netfilter module for AF_BUS/BUS_PROTO_DBUS.
-+ */
-+
-+#define DRIVER_AUTHOR "Alban Crequy"
-+#define DRIVER_DESC "Netfilter module for AF_BUS/BUS_PROTO_DBUS."
-+
-+#include "nfdbus.h"
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/skbuff.h>
-+#include <linux/netfilter.h>
-+#include <linux/connector.h>
-+#include <net/af_bus.h>
-+
-+#include "message.h"
-+#include "matchrule.h"
-+
-+static struct nf_hook_ops nfho_dbus;
-+
-+static struct cb_id cn_cmd_id = { CN_IDX_NFDBUS, CN_VAL_NFDBUS };
-+
-+static unsigned int hash;
-+
-+/* Scoped by AF_BUS address */
-+struct hlist_head matchrules_table[BUS_HASH_SIZE];
-+DEFINE_SPINLOCK(matchrules_lock);
-+
-+static struct bus_match_maker *find_match_maker(struct sockaddr_bus *addr,
-+ bool create, bool delete)
-+{
-+ u64 hash;
-+ struct hlist_node *node;
-+ struct bus_match_maker *matchmaker;
-+ int path_len = strlen(addr->sbus_path);
-+
-+ hash = csum_partial(addr->sbus_path,
-+ strlen(addr->sbus_path), 0);
-+ hash ^= addr->sbus_addr.s_addr;
-+ hash ^= hash >> 32;
-+ hash ^= hash >> 16;
-+ hash ^= hash >> 8;
-+ hash &= 0xff;
-+
-+ spin_lock(&matchrules_lock);
-+ hlist_for_each_entry(matchmaker, node, &matchrules_table[hash],
-+ table_node) {
-+ if (addr->sbus_family == matchmaker->addr.sbus_family &&
-+ addr->sbus_addr.s_addr == matchmaker->addr.sbus_addr.s_addr &&
-+ !memcmp(addr->sbus_path, matchmaker->addr.sbus_path,
-+ path_len)) {
-+ kref_get(&matchmaker->kref);
-+ if (delete)
-+ hlist_del(&matchmaker->table_node);
-+ spin_unlock(&matchrules_lock);
-+ pr_debug("Found matchmaker for hash %llu", hash);
-+ return matchmaker;
-+ }
-+ }
-+ spin_unlock(&matchrules_lock);
-+
-+ if (!create) {
-+ pr_debug("Matchmaker for hash %llu not found", hash);
-+ return NULL;
-+ }
-+
-+ matchmaker = bus_matchmaker_new(GFP_ATOMIC);
-+ matchmaker->addr.sbus_family = addr->sbus_family;
-+ matchmaker->addr.sbus_addr.s_addr = addr->sbus_addr.s_addr;
-+ memcpy(matchmaker->addr.sbus_path, addr->sbus_path, BUS_PATH_MAX);
-+
-+ pr_debug("Create new matchmaker for hash %llu\n", hash);
-+ spin_lock(&matchrules_lock);
-+ hlist_add_head(&matchmaker->table_node, &matchrules_table[hash]);
-+ kref_get(&matchmaker->kref);
-+ spin_unlock(&matchrules_lock);
-+ return matchmaker;
-+}
-+
-+static unsigned int dbus_filter(unsigned int hooknum,
-+ struct sk_buff *skb,
-+ const struct net_device *in,
-+ const struct net_device *out,
-+ int (*okfn)(struct sk_buff *))
-+{
-+ struct bus_send_context *sendctx;
-+ struct bus_match_maker *matchmaker = NULL;
-+ struct bus_match_maker *sender = NULL;
-+ struct dbus_message msg = {0,};
-+ unsigned char *data;
-+ size_t len;
-+ int err;
-+ int ret;
-+
-+ if (!skb->sk || skb->sk->sk_family != PF_BUS) {
-+ WARN(1, "netfilter_dbus received an invalid skb");
-+ return NF_DROP;
-+ }
-+
-+ data = skb->data;
-+ sendctx = BUSCB(skb).sendctx;
-+ if (!sendctx || !sendctx->sender || !sendctx->sender_socket) {
-+ WARN(1, "netfilter_dbus received an AF_BUS packet" \
-+ " without context. This is a bug. Dropping the"
-+ " packet.");
-+ return NF_DROP;
-+ }
-+
-+ if (sendctx->sender_socket->sk->sk_protocol != BUS_PROTO_DBUS) {
-+ /* This kernel module is for D-Bus. It must not
-+ * interfere with other users of AF_BUS. */
-+ return NF_ACCEPT;
-+ }
-+ if (sendctx->recipient)
-+ matchmaker = find_match_maker(sendctx->recipient, false, false);
-+
-+ len = skb_tail_pointer(skb) - data;
-+
-+ if (sendctx->to_master && sendctx->main_recipient) {
-+ pr_debug("AF_BUS packet to the bus master. ACCEPT.\n");
-+ ret = NF_ACCEPT;
-+ goto out;
-+ }
-+
-+ if (sendctx->main_recipient && !sendctx->bus_master_side) {
-+ pr_debug("AF_BUS packet from a peer to a peer (unicast). ACCEPT.\n");
-+ ret = NF_ACCEPT;
-+ goto out;
-+ }
-+
-+ err = dbus_message_parse(data, len, &msg);
-+ if (err) {
-+ if (!sendctx->main_recipient) {
-+ pr_debug("AF_BUS packet for an eavesdropper or " \
-+ "multicast is not parsable. DROP.\n");
-+ ret = NF_DROP;
-+ goto out;
-+ } else if (sendctx->bus_master_side) {
-+ pr_debug("AF_BUS packet from bus master is not parsable. ACCEPT.\n");
-+ ret = NF_ACCEPT;
-+ goto out;
-+ } else {
-+ pr_debug("AF_BUS packet from peer is not parsable. DROP.\n");
-+ ret = NF_DROP;
-+ goto out;
-+ }
-+ }
-+
-+ if (sendctx->bus_master_side && !sendctx->main_recipient) {
-+ pr_debug("AF_BUS packet '%s' from the bus master is for an " \
-+ "eavesdropper. DROP.\n",
-+ msg.member ? msg.member : "");
-+ ret = NF_DROP;
-+ goto out;
-+ }
-+ if (sendctx->bus_master_side) {
-+ if (msg.name_acquired) {
-+ pr_debug("New name: %s [%p %p].\n",
-+ msg.name_acquired, sendctx->sender,
-+ sendctx->recipient);
-+
-+ sender = find_match_maker(sendctx->sender, true, false);
-+ bus_matchmaker_add_name(sender, msg.name_acquired,
-+ GFP_ATOMIC);
-+ }
-+ if (msg.name_lost) {
-+ pr_debug("Lost name: %s [%p %p].\n",
-+ msg.name_lost, sendctx->sender,
-+ sendctx->recipient);
-+
-+ sender = find_match_maker(sendctx->sender, true, false);
-+ bus_matchmaker_remove_name(sender, msg.name_acquired);
-+ }
-+
-+ pr_debug("AF_BUS packet '%s' from the bus master. ACCEPT.\n",
-+ msg.member ? msg.member : "");
-+ ret = NF_ACCEPT;
-+ goto out;
-+ }
-+
-+ pr_debug("Multicast AF_BUS packet, %ld bytes, " \
-+ "considering recipient %lld...\n", len,
-+ sendctx->recipient ? sendctx->recipient->sbus_addr.s_addr : 0);
-+
-+ pr_debug("Message type %d %s->%s [iface: %s][member: %s][matchmaker=%p]...\n",
-+ msg.type,
-+ msg.sender ? msg.sender : "",
-+ msg.destination ? msg.destination : "",
-+ msg.interface ? msg.interface : "",
-+ msg.member ? msg.member : "",
-+ matchmaker);
-+
-+ if (!matchmaker) {
-+ pr_debug("No match rules for this recipient. DROP.\n");
-+ ret = NF_DROP;
-+ goto out;
-+ }
-+
-+ sender = find_match_maker(sendctx->sender, true, false);
-+ err = bus_matchmaker_filter(matchmaker, sender, sendctx->eavesdropper,
-+ &msg);
-+ if (err) {
-+ pr_debug("Matchmaker: ACCEPT.\n");
-+ ret = NF_ACCEPT;
-+ goto out;
-+ } else {
-+ pr_debug("Matchmaker: DROP.\n");
-+ ret = NF_DROP;
-+ goto out;
-+ }
-+
-+out:
-+ if (matchmaker)
-+ kref_put(&matchmaker->kref, bus_matchmaker_free);
-+ if (sender)
-+ kref_put(&sender->kref, bus_matchmaker_free);
-+ return ret;
-+}
-+
-+/* Taken from drbd_nl_send_reply() */
-+static void nfdbus_nl_send_reply(struct cn_msg *msg, int ret_code)
-+{
-+ char buffer[sizeof(struct cn_msg)+sizeof(struct nfdbus_nl_cfg_reply)];
-+ struct cn_msg *cn_reply = (struct cn_msg *) buffer;
-+ struct nfdbus_nl_cfg_reply *reply =
-+ (struct nfdbus_nl_cfg_reply *)cn_reply->data;
-+ int rr;
-+
-+ memset(buffer, 0, sizeof(buffer));
-+ cn_reply->id = msg->id;
-+
-+ cn_reply->seq = msg->seq;
-+ cn_reply->ack = msg->ack + 1;
-+ cn_reply->len = sizeof(struct nfdbus_nl_cfg_reply);
-+ cn_reply->flags = 0;
-+
-+ reply->ret_code = ret_code;
-+
-+ rr = cn_netlink_send(cn_reply, 0, GFP_NOIO);
-+ if (rr && rr != -ESRCH)
-+ pr_debug("nfdbus: cn_netlink_send()=%d\n", rr);
-+}
-+
-+/**
-+ * nfdbus_check_perm - check if a pid is allowed to update match rules
-+ * @sockaddr_bus: the socket address of the bus
-+ * @pid: the process id that wants to update the match rules set
-+ *
-+ * Test if a given process id is allowed to update the match rules set
-+ * for this bus. Only the process that owns the bus master listen socket
-+ * is allowed to update the match rules set for the bus.
-+ */
-+static bool nfdbus_check_perm(struct sockaddr_bus *sbusname, pid_t pid)
-+{
-+ struct net *net = get_net_ns_by_pid(pid);
-+ struct sock *s;
-+ struct bus_address *addr;
-+ struct hlist_node *node;
-+ int offset = (sbusname->sbus_path[0] == '\0');
-+ int path_len = strnlen(sbusname->sbus_path + offset, BUS_PATH_MAX);
-+ int len;
-+ if (!net)
-+ return false;
-+
-+ len = path_len + 1 + sizeof(__kernel_sa_family_t) +
-+ sizeof(struct bus_addr);
-+
-+ spin_lock(&bus_address_lock);
-+
-+ hlist_for_each_entry(addr, node, &bus_address_table[hash],
-+ table_node) {
-+ s = addr->sock;
-+
-+ if (s->sk_protocol != BUS_PROTO_DBUS)
-+ continue;
-+
-+ if (!net_eq(sock_net(s), net))
-+ continue;
-+
-+ if (addr->len == len &&
-+ addr->name->sbus_family == sbusname->sbus_family &&
-+ addr->name->sbus_addr.s_addr == BUS_MASTER_ADDR &&
-+ bus_same_bus(addr->name, sbusname) &&
-+ pid_nr(s->sk_peer_pid) == pid) {
-+ spin_unlock(&bus_address_lock);
-+ return true;
-+ }
-+ }
-+
-+ spin_unlock(&bus_address_lock);
-+
-+ return false;
-+}
-+
-+static void cn_cmd_cb(struct cn_msg *msg, struct netlink_skb_parms *nsp)
-+{
-+ struct nfdbus_nl_cfg_req *nlp = (struct nfdbus_nl_cfg_req *)msg->data;
-+ struct cn_msg *cn_reply;
-+ struct nfdbus_nl_cfg_reply *reply;
-+ int retcode, rr;
-+ pid_t pid = task_tgid_vnr(current);
-+ int reply_size = sizeof(struct cn_msg)
-+ + sizeof(struct nfdbus_nl_cfg_reply);
-+
-+ pr_debug("nfdbus: %s nsp->pid=%d pid=%d\n", __func__, nsp->pid, pid);
-+
-+ if (!nfdbus_check_perm(&nlp->addr, pid)) {
-+ pr_debug(KERN_ERR "nfdbus: pid=%d is not allowed!\n", pid);
-+ retcode = EPERM;
-+ goto fail;
-+ }
-+
-+ cn_reply = kzalloc(reply_size, GFP_KERNEL);
-+ if (!cn_reply) {
-+ retcode = ENOMEM;
-+ goto fail;
-+ }
-+ reply = (struct nfdbus_nl_cfg_reply *) cn_reply->data;
-+
-+ if (msg->len < sizeof(struct nfdbus_nl_cfg_req)) {
-+ reply->ret_code = EINVAL;
-+ } else if (nlp->cmd == NFDBUS_CMD_ADDMATCH) {
-+ struct bus_match_rule *rule;
-+ struct bus_match_maker *matchmaker;
-+ reply->ret_code = 0;
-+
-+ if (msg->len == 0)
-+ reply->ret_code = EINVAL;
-+
-+ rule = bus_match_rule_parse(nlp->data, GFP_ATOMIC);
-+ if (rule) {
-+ matchmaker = find_match_maker(&nlp->addr, true, false);
-+ pr_debug("Add match rule for matchmaker %p\n",
-+ matchmaker);
-+ bus_matchmaker_add_rule(matchmaker, rule);
-+ kref_put(&matchmaker->kref, bus_matchmaker_free);
-+ } else {
-+ reply->ret_code = EINVAL;
-+ }
-+ } else if (nlp->cmd == NFDBUS_CMD_REMOVEMATCH) {
-+ struct bus_match_rule *rule;
-+ struct bus_match_maker *matchmaker;
-+
-+ rule = bus_match_rule_parse(nlp->data, GFP_ATOMIC);
-+ if (rule) {
-+ matchmaker = find_match_maker(&nlp->addr, false, false);
-+ if (!matchmaker) {
-+ reply->ret_code = EINVAL;
-+ } else {
-+ pr_debug("Remove match rule for matchmaker %p\n",
-+ matchmaker);
-+ bus_matchmaker_remove_rule_by_value(matchmaker, rule);
-+ kref_put(&matchmaker->kref, bus_matchmaker_free);
-+ reply->ret_code = 0;
-+ }
-+ bus_match_rule_free(rule);
-+ }
-+
-+ } else if (nlp->cmd == NFDBUS_CMD_REMOVEALLMATCH) {
-+ struct bus_match_maker *matchmaker;
-+
-+ matchmaker = find_match_maker(&nlp->addr, false, true);
-+ if (!matchmaker) {
-+ reply->ret_code = EINVAL;
-+ } else {
-+ pr_debug("Remove matchmaker %p\n", matchmaker);
-+ kref_put(&matchmaker->kref, bus_matchmaker_free);
-+ kref_put(&matchmaker->kref, bus_matchmaker_free);
-+ reply->ret_code = 0;
-+ }
-+
-+ } else {
-+ reply->ret_code = EINVAL;
-+ }
-+
-+ cn_reply->id = msg->id;
-+ cn_reply->seq = msg->seq;
-+ cn_reply->ack = msg->ack + 1;
-+ cn_reply->len = sizeof(struct nfdbus_nl_cfg_reply);
-+ cn_reply->flags = 0;
-+
-+ rr = cn_netlink_reply(cn_reply, nsp->pid, GFP_KERNEL);
-+ if (rr && rr != -ESRCH)
-+ pr_debug("nfdbus: cn_netlink_send()=%d\n", rr);
-+ pr_debug("nfdbus: cn_netlink_reply(pid=%d)=%d\n", nsp->pid, rr);
-+
-+ kfree(cn_reply);
-+ return;
-+fail:
-+ nfdbus_nl_send_reply(msg, retcode);
-+}
-+
-+static int __init nfdbus_init(void)
-+{
-+ int err;
-+ struct bus_addr master_addr;
-+
-+ master_addr.s_addr = BUS_MASTER_ADDR;
-+ hash = bus_compute_hash(master_addr);
-+
-+ pr_debug("Loading netfilter_dbus\n");
-+
-+ /* Install D-Bus netfilter hook */
-+ nfho_dbus.hook = dbus_filter;
-+ nfho_dbus.hooknum = NF_BUS_SENDING;
-+ nfho_dbus.pf = NFPROTO_BUS; /* Do not use PF_BUS, you fool! */
-+ nfho_dbus.priority = 0;
-+ nfho_dbus.owner = THIS_MODULE;
-+ err = nf_register_hook(&nfho_dbus);
-+ if (err)
-+ return err;
-+ pr_debug("Netfilter hook for D-Bus: installed.\n");
-+
-+ /* Install connector hook */
-+ err = cn_add_callback(&cn_cmd_id, "nfdbus", cn_cmd_cb);
-+ if (err)
-+ goto err_cn_cmd_out;
-+ pr_debug("Connector hook: installed.\n");
-+
-+ return 0;
-+
-+err_cn_cmd_out:
-+ nf_unregister_hook(&nfho_dbus);
-+
-+ return err;
-+}
-+
-+static void __exit nfdbus_cleanup(void)
-+{
-+ int i;
-+ struct hlist_node *node, *tmp;
-+ struct bus_match_maker *matchmaker;
-+ nf_unregister_hook(&nfho_dbus);
-+
-+ cn_del_callback(&cn_cmd_id);
-+
-+ spin_lock(&matchrules_lock);
-+ for (i = 0; i < BUS_HASH_SIZE; i++) {
-+ hlist_for_each_entry_safe(matchmaker, node, tmp,
-+ &matchrules_table[i], table_node) {
-+ hlist_del(&matchmaker->table_node);
-+ kref_put(&matchmaker->kref, bus_matchmaker_free);
-+ }
-+ }
-+ spin_unlock(&matchrules_lock);
-+
-+ pr_debug("Unloading netfilter_dbus\n");
-+}
-+
-+module_init(nfdbus_init);
-+module_exit(nfdbus_cleanup);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR(DRIVER_AUTHOR);
-+MODULE_DESCRIPTION(DRIVER_DESC);
-+MODULE_ALIAS_NET_PF_PROTO(PF_BUS, BUS_PROTO_DBUS);
-diff --git a/net/bus/nfdbus/nfdbus.h b/net/bus/nfdbus/nfdbus.h
-new file mode 100644
-index 0000000..477bde3
---- /dev/null
-+++ b/net/bus/nfdbus/nfdbus.h
-@@ -0,0 +1,44 @@
-+/*
-+ * nfdbus.h Netfilter module for AF_BUS/BUS_PROTO_DBUS.
-+ *
-+ * Copyright (C) 2012 Collabora Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ */
-+
-+#ifndef NETFILTER_DBUS_H
-+#define NETFILTER_DBUS_H
-+
-+#include <linux/types.h>
-+#include <linux/bus.h>
-+
-+#define NFDBUS_CMD_ADDMATCH 0x01
-+#define NFDBUS_CMD_REMOVEMATCH 0x02
-+#define NFDBUS_CMD_REMOVEALLMATCH 0x03
-+
-+struct nfdbus_nl_cfg_req {
-+ __u32 cmd;
-+ __u32 len;
-+ struct sockaddr_bus addr;
-+ __u64 pad;
-+ unsigned char data[0];
-+};
-+
-+struct nfdbus_nl_cfg_reply {
-+ __u32 ret_code;
-+};
-+
-+#endif /* NETFILTER_DBUS_H */
---
-1.7.7.6
-
+++ /dev/null
-From javier.martinez@collabora.co.uk Thu Jan 24 00:08:10 2013
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Thu, 24 Jan 2013 09:07:53 +0100
-Subject: af_bus: make NETFILTER_DBUS depend on NETFILTER
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: ltsi-dev@lists.linuxfoundation.org, Stephen Lawrence <stephen.lawrence@renesas.com>, Jeremiah Foster <jeremiah.foster@pelagicore.com>, Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Message-ID: <1359014873-29358-1-git-send-email-javier.martinez@collabora.co.uk>
-
-
-some users report to had a build error when NETFILTER config
-option is not set:
-
-net/bus/af_bus.c: In function 'bus_sendmsg':
-net/bus/af_bus.c:1511:7: warning: 'rcp_cnt' may be used uninitialized in
-this function
- CC net/bus/garbage.o
- LD net/bus/af-bus.o
- CC net/bus/nfdbus/nfdbus.o
-net/bus/nfdbus/nfdbus.c: In function 'nfdbus_init':
-net/bus/nfdbus/nfdbus.c:406:2: error: invalid use of undefined type
-'struct nf_hook_ops'
-net/bus/nfdbus/nfdbus.c:407:2: error: invalid use of undefined type
-'struct nf_hook_ops'
-net/bus/nfdbus/nfdbus.c:408:2: error: invalid use of undefined type
-'struct nf_hook_ops'
-net/bus/nfdbus/nfdbus.c:409:2: error: invalid use of undefined type
-'struct nf_hook_ops'
-net/bus/nfdbus/nfdbus.c:410:2: error: invalid use of undefined type
-'struct nf_hook_ops'
-net/bus/nfdbus/nfdbus.c:411:2: error: implicit declaration of function
-'nf_register_hook'
-net/bus/nfdbus/nfdbus.c:425:2: error: implicit declaration of function
-'nf_unregister_hook'
-make[3]: *** [net/bus/nfdbus/nfdbus.o] Error 1
-make[2]: *** [net/bus/nfdbus] Error 2
-make[1]: *** [net/bus] Error 2
-make: *** [net] Error 2
-
-this is because NETFILTER_DBUS uses symbols only defined when NETFITER=y
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
----
-
-Hello Greg,
-
-I've seen that people send you incremental patches and you store them
-on "patches.fixes" directory. That's why I'm sending a delta patch.
-
-Please let me know if you prefer to have the original corresponding
-patch with this fix squashed.
-
-Thanks a lot.
-
- net/bus/nfdbus/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/net/bus/nfdbus/Kconfig
-+++ b/net/bus/nfdbus/Kconfig
-@@ -3,7 +3,7 @@
- #
- config NETFILTER_DBUS
- tristate "Netfilter D-bus (EXPERIMENTAL)"
-- depends on AF_BUS && CONNECTOR && EXPERIMENTAL
-+ depends on AF_BUS && NETFILTER && CONNECTOR && EXPERIMENTAL
- ---help---
- If you say Y here, you will include support for a netfilter hook to
- parse D-Bus messages sent using the AF_BUS socket address family.
+++ /dev/null
-From 4d3626f914a2b4023a3edf428640e578527ac0c8 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 25 Jun 2012 03:43:00 -0700
-Subject: ARM: shmobile: add common DMAEngine definitions
-
-Current shmobile have DMAEngine specific settings on each CPU code,
-but SH-ARM DMAC use same value.
-
-This patch adds new dma-register.h header to share definitions
-and reduce a waste of code on SH-ARM architecture.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 5ca1d44f6a99b29ab164a06f4ec71950d6939fb5)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/include/mach/dma-register.h | 84 ++++++++++++++++++++++
- 1 file changed, 84 insertions(+)
- create mode 100644 arch/arm/mach-shmobile/include/mach/dma-register.h
-
-diff --git a/arch/arm/mach-shmobile/include/mach/dma-register.h b/arch/arm/mach-shmobile/include/mach/dma-register.h
-new file mode 100644
-index 0000000..97c40bd
---- /dev/null
-+++ b/arch/arm/mach-shmobile/include/mach/dma-register.h
-@@ -0,0 +1,84 @@
-+/*
-+ * SH-ARM CPU-specific DMA definitions, used by both DMA drivers
-+ *
-+ * Copyright (C) 2012 Renesas Solutions Corp
-+ *
-+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-+ *
-+ * Based on arch/sh/include/cpu-sh4/cpu/dma-register.h
-+ * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-+ *
-+ * 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.
-+ */
-+
-+#ifndef DMA_REGISTER_H
-+#define DMA_REGISTER_H
-+
-+/*
-+ * Direct Memory Access Controller
-+ */
-+
-+/* Transmit sizes and respective CHCR register values */
-+enum {
-+ XMIT_SZ_8BIT = 0,
-+ XMIT_SZ_16BIT = 1,
-+ XMIT_SZ_32BIT = 2,
-+ XMIT_SZ_64BIT = 7,
-+ XMIT_SZ_128BIT = 3,
-+ XMIT_SZ_256BIT = 4,
-+ XMIT_SZ_512BIT = 5,
-+};
-+
-+/* log2(size / 8) - used to calculate number of transfers */
-+static const unsigned int dma_ts_shift[] = {
-+ [XMIT_SZ_8BIT] = 0,
-+ [XMIT_SZ_16BIT] = 1,
-+ [XMIT_SZ_32BIT] = 2,
-+ [XMIT_SZ_64BIT] = 3,
-+ [XMIT_SZ_128BIT] = 4,
-+ [XMIT_SZ_256BIT] = 5,
-+ [XMIT_SZ_512BIT] = 6,
-+};
-+
-+#define TS_LOW_BIT 0x3 /* --xx */
-+#define TS_HI_BIT 0xc /* xx-- */
-+
-+#define TS_LOW_SHIFT (3)
-+#define TS_HI_SHIFT (20 - 2) /* 2 bits for shifted low TS */
-+
-+#define TS_INDEX2VAL(i) \
-+ ((((i) & TS_LOW_BIT) << TS_LOW_SHIFT) |\
-+ (((i) & TS_HI_BIT) << TS_HI_SHIFT))
-+
-+#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz)))
-+#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz)))
-+
-+
-+/*
-+ * USB High-Speed DMAC
-+ */
-+/* Transmit sizes and respective CHCR register values */
-+enum {
-+ USBTS_XMIT_SZ_8BYTE = 0,
-+ USBTS_XMIT_SZ_16BYTE = 1,
-+ USBTS_XMIT_SZ_32BYTE = 2,
-+};
-+
-+/* log2(size / 8) - used to calculate number of transfers */
-+static const unsigned int dma_usbts_shift[] = {
-+ [USBTS_XMIT_SZ_8BYTE] = 3,
-+ [USBTS_XMIT_SZ_16BYTE] = 4,
-+ [USBTS_XMIT_SZ_32BYTE] = 5,
-+};
-+
-+#define USBTS_LOW_BIT 0x3 /* --xx */
-+#define USBTS_HI_BIT 0x0 /* ---- */
-+
-+#define USBTS_LOW_SHIFT 6
-+#define USBTS_HI_SHIFT 0
-+
-+#define USBTS_INDEX2VAL(i) (((i) & 3) << 6)
-+
-+#endif /* DMA_REGISTER_H */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From c13b4e8e39cad46f37b794ba12b8a97569767e25 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Thu, 5 Jul 2012 01:24:46 -0700
-Subject: ARM: shmobile: soc-core: add R-mobile PM domain common APIs
-
-This patch adds Renesas R-mobile series common PM domain APIs.
-R-mobile CPU can use/switch this API
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 8f45b112fc66ef6869ccca4c3966976982f496a9)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/Makefile | 1 +
- arch/arm/mach-shmobile/include/mach/pm-rmobile.h | 44 ++++++
- arch/arm/mach-shmobile/pm-rmobile.c | 167 +++++++++++++++++++++++
- 3 files changed, 212 insertions(+)
- create mode 100644 arch/arm/mach-shmobile/include/mach/pm-rmobile.h
- create mode 100644 arch/arm/mach-shmobile/pm-rmobile.c
-
-diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
-index e7c2590..53846a1e 100644
---- a/arch/arm/mach-shmobile/Makefile
-+++ b/arch/arm/mach-shmobile/Makefile
-@@ -37,6 +37,7 @@ obj-$(CONFIG_ARCH_R8A7740) += entry-intc.o
- # PM objects
- obj-$(CONFIG_SUSPEND) += suspend.o
- obj-$(CONFIG_CPU_IDLE) += cpuidle.o
-+obj-$(CONFIG_ARCH_SHMOBILE) += pm-rmobile.o
- obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o sleep-sh7372.o
- obj-$(CONFIG_ARCH_R8A7779) += pm-r8a7779.o
-
-diff --git a/arch/arm/mach-shmobile/include/mach/pm-rmobile.h b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h
-new file mode 100644
-index 0000000..5a40284
---- /dev/null
-+++ b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h
-@@ -0,0 +1,44 @@
-+/*
-+ * Copyright (C) 2012 Renesas Solutions Corp.
-+ *
-+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
-+ *
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ */
-+#ifndef PM_RMOBILE_H
-+#define PM_RMOBILE_H
-+
-+#include <linux/pm_domain.h>
-+
-+struct platform_device;
-+
-+struct rmobile_pm_domain {
-+ struct generic_pm_domain genpd;
-+ struct dev_power_governor *gov;
-+ int (*suspend)(void);
-+ void (*resume)(void);
-+ unsigned int bit_shift;
-+ bool no_debug;
-+};
-+
-+static inline
-+struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d)
-+{
-+ return container_of(d, struct rmobile_pm_domain, genpd);
-+}
-+
-+#ifdef CONFIG_PM
-+extern void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd);
-+extern void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd,
-+ struct platform_device *pdev);
-+extern void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd,
-+ struct rmobile_pm_domain *rmobile_sd);
-+#else
-+#define rmobile_init_pm_domain(pd) do { } while (0)
-+#define rmobile_add_device_to_domain(pd, pdev) do { } while (0)
-+#define rmobile_pm_add_subdomain(pd, sd) do { } while (0)
-+#endif /* CONFIG_PM */
-+
-+#endif /* PM_RMOBILE_H */
-diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c
-new file mode 100644
-index 0000000..a856254
---- /dev/null
-+++ b/arch/arm/mach-shmobile/pm-rmobile.c
-@@ -0,0 +1,167 @@
-+/*
-+ * rmobile power management support
-+ *
-+ * Copyright (C) 2012 Renesas Solutions Corp.
-+ * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-+ *
-+ * based on pm-sh7372.c
-+ * Copyright (C) 2011 Magnus Damm
-+ *
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ */
-+#include <linux/console.h>
-+#include <linux/delay.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm.h>
-+#include <linux/pm_clock.h>
-+#include <asm/io.h>
-+#include <mach/pm-rmobile.h>
-+
-+/* SYSC */
-+#define SPDCR 0xe6180008
-+#define SWUCR 0xe6180014
-+#define PSTR 0xe6180080
-+
-+#define PSTR_RETRIES 100
-+#define PSTR_DELAY_US 10
-+
-+#ifdef CONFIG_PM
-+static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
-+{
-+ struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
-+ unsigned int mask = 1 << rmobile_pd->bit_shift;
-+
-+ if (rmobile_pd->suspend) {
-+ int ret = rmobile_pd->suspend();
-+
-+ if (ret)
-+ return ret;
-+ }
-+
-+ if (__raw_readl(PSTR) & mask) {
-+ unsigned int retry_count;
-+ __raw_writel(mask, SPDCR);
-+
-+ for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
-+ if (!(__raw_readl(SPDCR) & mask))
-+ break;
-+ cpu_relax();
-+ }
-+ }
-+
-+ if (!rmobile_pd->no_debug)
-+ pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n",
-+ genpd->name, mask, __raw_readl(PSTR));
-+
-+ return 0;
-+}
-+
-+static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd,
-+ bool do_resume)
-+{
-+ unsigned int mask = 1 << rmobile_pd->bit_shift;
-+ unsigned int retry_count;
-+ int ret = 0;
-+
-+ if (__raw_readl(PSTR) & mask)
-+ goto out;
-+
-+ __raw_writel(mask, SWUCR);
-+
-+ for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
-+ if (!(__raw_readl(SWUCR) & mask))
-+ break;
-+ if (retry_count > PSTR_RETRIES)
-+ udelay(PSTR_DELAY_US);
-+ else
-+ cpu_relax();
-+ }
-+ if (!retry_count)
-+ ret = -EIO;
-+
-+ if (!rmobile_pd->no_debug)
-+ pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
-+ rmobile_pd->genpd.name, mask, __raw_readl(PSTR));
-+
-+out:
-+ if (ret == 0 && rmobile_pd->resume && do_resume)
-+ rmobile_pd->resume();
-+
-+ return ret;
-+}
-+
-+static int rmobile_pd_power_up(struct generic_pm_domain *genpd)
-+{
-+ return __rmobile_pd_power_up(to_rmobile_pd(genpd), true);
-+}
-+
-+static bool rmobile_pd_active_wakeup(struct device *dev)
-+{
-+ bool (*active_wakeup)(struct device *dev);
-+
-+ active_wakeup = dev_gpd_data(dev)->ops.active_wakeup;
-+ return active_wakeup ? active_wakeup(dev) : true;
-+}
-+
-+static int rmobile_pd_stop_dev(struct device *dev)
-+{
-+ int (*stop)(struct device *dev);
-+
-+ stop = dev_gpd_data(dev)->ops.stop;
-+ if (stop) {
-+ int ret = stop(dev);
-+ if (ret)
-+ return ret;
-+ }
-+ return pm_clk_suspend(dev);
-+}
-+
-+static int rmobile_pd_start_dev(struct device *dev)
-+{
-+ int (*start)(struct device *dev);
-+ int ret;
-+
-+ ret = pm_clk_resume(dev);
-+ if (ret)
-+ return ret;
-+
-+ start = dev_gpd_data(dev)->ops.start;
-+ if (start)
-+ ret = start(dev);
-+
-+ return ret;
-+}
-+
-+void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
-+{
-+ struct generic_pm_domain *genpd = &rmobile_pd->genpd;
-+ struct dev_power_governor *gov = rmobile_pd->gov;
-+
-+ pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
-+ genpd->dev_ops.stop = rmobile_pd_stop_dev;
-+ genpd->dev_ops.start = rmobile_pd_start_dev;
-+ genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup;
-+ genpd->dev_irq_safe = true;
-+ genpd->power_off = rmobile_pd_power_down;
-+ genpd->power_on = rmobile_pd_power_up;
-+ __rmobile_pd_power_up(rmobile_pd, false);
-+}
-+
-+void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd,
-+ struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+
-+ pm_genpd_add_device(&rmobile_pd->genpd, dev);
-+ if (pm_clk_no_clocks(dev))
-+ pm_clk_add(dev, NULL);
-+}
-+
-+void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd,
-+ struct rmobile_pm_domain *rmobile_sd)
-+{
-+ pm_genpd_add_subdomain(&rmobile_pd->genpd, &rmobile_sd->genpd);
-+}
-+#endif /* CONFIG_PM */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 657ed37c21c4b58b2ce736343d1c653a842f7299 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 8 May 2012 00:00:07 -0300
-Subject: [media] V4L2: sh_mobile_ceu: manage lower 8bit bus
-
-CAMCR::DTIF feild controls camera bus as upper8bit/16bit/lower8bit.
-This patch manages unmanaged lower 8bit bus
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-(cherry picked from commit 2564f67bc8d56e5c7fc2970f80f41f2d38db3e21)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/media/video/sh_mobile_ceu_camera.c | 8 +++++---
- include/media/sh_mobile_ceu.h | 1 +
- 2 files changed, 6 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
-index 424dfac..4e0b654 100644
---- a/drivers/media/video/sh_mobile_ceu_camera.c
-+++ b/drivers/media/video/sh_mobile_ceu_camera.c
-@@ -881,11 +881,13 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd)
-
- value |= common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW ? 1 << 1 : 0;
- value |= common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW ? 1 << 0 : 0;
-- value |= pcdev->is_16bit ? 1 << 12 : 0;
-
-- /* CSI2 mode */
-- if (pcdev->pdata->csi2)
-+ if (pcdev->pdata->csi2) /* CSI2 mode */
- value |= 3 << 12;
-+ else if (pcdev->is_16bit)
-+ value |= 1 << 12;
-+ else if (pcdev->pdata->flags & SH_CEU_FLAG_LOWER_8BIT)
-+ value |= 2 << 12;
-
- ceu_write(pcdev, CAMCR, value);
-
-diff --git a/include/media/sh_mobile_ceu.h b/include/media/sh_mobile_ceu.h
-index a90a765..6fdb6ad 100644
---- a/include/media/sh_mobile_ceu.h
-+++ b/include/media/sh_mobile_ceu.h
-@@ -5,6 +5,7 @@
- #define SH_CEU_FLAG_USE_16BIT_BUS (1 << 1) /* use 16bit bus width */
- #define SH_CEU_FLAG_HSYNC_LOW (1 << 2) /* default High if possible */
- #define SH_CEU_FLAG_VSYNC_LOW (1 << 3) /* default High if possible */
-+#define SH_CEU_FLAG_LOWER_8BIT (1 << 4) /* default upper 8bit */
-
- struct device;
- struct resource;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 5d792a5a2daa8e2d397c0b5f45ac76c9e0d175ff Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Tue, 19 Jun 2012 17:43:56 +0200
-Subject: regulator: support multiple dummy fixed regulators
-
-Currently regulator_register_fixed() uses a constant name to register a
-fixed dummy regulator. This is sufficient in principle, since there is no
-reason to register multiple such regulators. The user can simply supply all
-consumers in one array and use it to initialise such a regulator. However,
-in some cases it can be convenient to register multiple such regulators.
-This is also a prerequisite for the upcoming patch, that will add a voltage
-parameter to this function. The original function is provided as a wrapper
-macro.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit dfad84aeab5f71b33a12e6803a809f698bdef5a2)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/regulator/fixed-helper.c | 14 +++++++++++---
- include/linux/regulator/fixed.h | 7 +++++--
- 2 files changed, 16 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c
-index cacd33c..3aa268d 100644
---- a/drivers/regulator/fixed-helper.c
-+++ b/drivers/regulator/fixed-helper.c
-@@ -1,4 +1,5 @@
- #include <linux/slab.h>
-+#include <linux/string.h>
- #include <linux/platform_device.h>
- #include <linux/regulator/machine.h>
- #include <linux/regulator/fixed.h>
-@@ -13,16 +14,18 @@ static void regulator_fixed_release(struct device *dev)
- {
- struct fixed_regulator_data *data = container_of(dev,
- struct fixed_regulator_data, pdev.dev);
-+ kfree(data->cfg.supply_name);
- kfree(data);
- }
-
- /**
-- * regulator_register_fixed - register a no-op fixed regulator
-+ * regulator_register_fixed_name - register a no-op fixed regulator
- * @id: platform device id
-+ * @name: name to be used for the regulator
- * @supplies: consumers for this regulator
- * @num_supplies: number of consumers
- */
--struct platform_device *regulator_register_fixed(int id,
-+struct platform_device *regulator_register_always_on(int id, const char *name,
- struct regulator_consumer_supply *supplies, int num_supplies)
- {
- struct fixed_regulator_data *data;
-@@ -31,7 +34,12 @@ struct platform_device *regulator_register_fixed(int id,
- if (!data)
- return NULL;
-
-- data->cfg.supply_name = "fixed-dummy";
-+ data->cfg.supply_name = kstrdup(name, GFP_KERNEL);
-+ if (!data->cfg.supply_name) {
-+ kfree(data);
-+ return NULL;
-+ }
-+
- data->cfg.microvolts = 0;
- data->cfg.gpio = -EINVAL;
- data->cfg.enabled_at_boot = 1;
-diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h
-index 936a7d8..7bb456c 100644
---- a/include/linux/regulator/fixed.h
-+++ b/include/linux/regulator/fixed.h
-@@ -51,14 +51,17 @@ struct fixed_voltage_config {
- struct regulator_consumer_supply;
-
- #if IS_ENABLED(CONFIG_REGULATOR)
--struct platform_device *regulator_register_fixed(int id,
-+struct platform_device *regulator_register_always_on(int id, const char *name,
- struct regulator_consumer_supply *supplies, int num_supplies);
- #else
--static inline struct platform_device *regulator_register_fixed(int id,
-+static inline struct platform_device *regulator_register_always_on(int id, const char *name,
- struct regulator_consumer_supply *supplies, int num_supplies)
- {
- return NULL;
- }
- #endif
-
-+#define regulator_register_fixed(id, s, ns) regulator_register_always_on(id, \
-+ "fixed-dummy", s, ns)
-+
- #endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From c5249f06fd57ea88ef47b750dc11a6f683bd5e5d Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Tue, 19 Jun 2012 17:44:39 +0200
-Subject: regulator: extend the fixed dummy voltage regulator to accept voltage
-
-Trivially extend the regulator_register_always_on() helper function to be
-even more useful by adding a voltage parameter to it.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit 15719ccc274981b19ad8fe9ac20c94249de8a257)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/regulator/fixed-helper.c | 5 +++--
- include/linux/regulator/fixed.h | 6 +++---
- 2 files changed, 6 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c
-index 3aa268d..f9d0279 100644
---- a/drivers/regulator/fixed-helper.c
-+++ b/drivers/regulator/fixed-helper.c
-@@ -24,9 +24,10 @@ static void regulator_fixed_release(struct device *dev)
- * @name: name to be used for the regulator
- * @supplies: consumers for this regulator
- * @num_supplies: number of consumers
-+ * @uv: voltage in microvolts
- */
- struct platform_device *regulator_register_always_on(int id, const char *name,
-- struct regulator_consumer_supply *supplies, int num_supplies)
-+ struct regulator_consumer_supply *supplies, int num_supplies, int uv)
- {
- struct fixed_regulator_data *data;
-
-@@ -40,7 +41,7 @@ struct platform_device *regulator_register_always_on(int id, const char *name,
- return NULL;
- }
-
-- data->cfg.microvolts = 0;
-+ data->cfg.microvolts = uv;
- data->cfg.gpio = -EINVAL;
- data->cfg.enabled_at_boot = 1;
- data->cfg.init_data = &data->init_data;
-diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h
-index 7bb456c..f6372ee 100644
---- a/include/linux/regulator/fixed.h
-+++ b/include/linux/regulator/fixed.h
-@@ -52,16 +52,16 @@ struct regulator_consumer_supply;
-
- #if IS_ENABLED(CONFIG_REGULATOR)
- struct platform_device *regulator_register_always_on(int id, const char *name,
-- struct regulator_consumer_supply *supplies, int num_supplies);
-+ struct regulator_consumer_supply *supplies, int num_supplies, int uv);
- #else
- static inline struct platform_device *regulator_register_always_on(int id, const char *name,
-- struct regulator_consumer_supply *supplies, int num_supplies)
-+ struct regulator_consumer_supply *supplies, int num_supplies, int uv)
- {
- return NULL;
- }
- #endif
-
- #define regulator_register_fixed(id, s, ns) regulator_register_always_on(id, \
-- "fixed-dummy", s, ns)
-+ "fixed-dummy", s, ns, 0)
-
- #endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 5f0a6815e3a7c5e73486b7b0a7ffffcf78b81cee Mon Sep 17 00:00:00 2001
-From: Tobias Klauser <tklauser@distanz.ch>
-Date: Mon, 11 Jun 2012 23:55:32 -0700
-Subject: Input: gpio_keys - remove useless reinitialization of pdata->nbuttons
-
-pdata is zeroed using memset just a few lines before, so there is no
-need to set the nbuttons member to 0 again.
-
-Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
-Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-(cherry picked from commit 4eceb14f669cb9e9d189019e8fcbf73577fe77a7)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/input/keyboard/gpio_keys.c | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
-index 62bfce4..cbb1add 100644
---- a/drivers/input/keyboard/gpio_keys.c
-+++ b/drivers/input/keyboard/gpio_keys.c
-@@ -559,7 +559,6 @@ static int gpio_keys_get_devtree_pdata(struct device *dev,
- pdata->rep = !!of_get_property(node, "autorepeat", NULL);
-
- /* First count the subnodes */
-- pdata->nbuttons = 0;
- pp = NULL;
- while ((pp = of_get_next_child(node, pp)))
- pdata->nbuttons++;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ccbea8cbb6f976a4ed42dfba5648bfb543f520d1 Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Tue, 3 Apr 2012 11:30:28 -0700
-Subject: Input: st1232 - add device tree support
-
-This patch enables DT support for the st1232 driver
-which is primarily used on the sh7372 Mackerel board.
-
-[dtor@mail.ru: chnaged to use CONFIG_OF and of_match_ptr]
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-(cherry picked from commit e6293d2f8a6cd427a1ef4ddecb16b1d5ae1929cd)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/input/touchscreen/st1232.c | 9 +++++++++
- 1 file changed, 9 insertions(+)
-
-diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
-index cbbf71b..216fabb 100644
---- a/drivers/input/touchscreen/st1232.c
-+++ b/drivers/input/touchscreen/st1232.c
-@@ -255,6 +255,14 @@ static const struct i2c_device_id st1232_ts_id[] = {
- };
- MODULE_DEVICE_TABLE(i2c, st1232_ts_id);
-
-+#ifdef CONFIG_OF
-+static const struct of_device_id st1232_ts_dt_ids[] __devinitconst = {
-+ { .compatible = "sitronix,st1232", },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids);
-+#endif
-+
- static struct i2c_driver st1232_ts_driver = {
- .probe = st1232_ts_probe,
- .remove = __devexit_p(st1232_ts_remove),
-@@ -262,6 +270,7 @@ static struct i2c_driver st1232_ts_driver = {
- .driver = {
- .name = ST1232_TS_NAME,
- .owner = THIS_MODULE,
-+ .of_match_table = of_match_ptr(st1232_ts_dt_ids),
- #ifdef CONFIG_PM
- .pm = &st1232_ts_pm_ops,
- #endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 456b9180124a8edec6c90cbd4d2b3f7c8a09a6f7 Mon Sep 17 00:00:00 2001
-From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-Date: Tue, 3 Apr 2012 11:30:28 -0700
-Subject: Input: st1232 - switch to using SIMPLE_DEV_PM_OPS
-
-Acked-by: Rafael J. Wysocki <rjw@sisk.pl>
-Reviewed-by: Simon Horman <horms@verge.net.au>
-Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-(cherry picked from commit b3571400395e318306165eabbfbe05a4c3e4366c)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/input/touchscreen/st1232.c | 11 ++++-------
- 1 file changed, 4 insertions(+), 7 deletions(-)
-
-diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
-index 216fabb..6cb68a1 100644
---- a/drivers/input/touchscreen/st1232.c
-+++ b/drivers/input/touchscreen/st1232.c
-@@ -218,7 +218,7 @@ static int __devexit st1232_ts_remove(struct i2c_client *client)
- return 0;
- }
-
--#ifdef CONFIG_PM
-+#ifdef CONFIG_PM_SLEEP
- static int st1232_ts_suspend(struct device *dev)
- {
- struct i2c_client *client = to_i2c_client(dev);
-@@ -243,12 +243,11 @@ static int st1232_ts_resume(struct device *dev)
- return 0;
- }
-
--static const struct dev_pm_ops st1232_ts_pm_ops = {
-- .suspend = st1232_ts_suspend,
-- .resume = st1232_ts_resume,
--};
- #endif
-
-+static SIMPLE_DEV_PM_OPS(st1232_ts_pm_ops,
-+ st1232_ts_suspend, st1232_ts_resume);
-+
- static const struct i2c_device_id st1232_ts_id[] = {
- { ST1232_TS_NAME, 0 },
- { }
-@@ -271,9 +270,7 @@ static struct i2c_driver st1232_ts_driver = {
- .name = ST1232_TS_NAME,
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(st1232_ts_dt_ids),
--#ifdef CONFIG_PM
- .pm = &st1232_ts_pm_ops,
--#endif
- },
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 38480ba305384441ebefad2684028756f7eab8b2 Mon Sep 17 00:00:00 2001
-From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Date: Wed, 4 Apr 2012 18:37:10 +0000
-Subject: net: sh_eth: add support R8A7740
-
-The R8A7740 has a Gigabit Ethernet MAC. This patch supports it.
-
-Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-(cherry picked from commit 73a0d907301ece200d32b4e8ba2da2ca296b507f)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/net/ethernet/renesas/Kconfig | 7 ++-
- drivers/net/ethernet/renesas/sh_eth.c | 114 +++++++++++++++++++++++++++++++++-
- drivers/net/ethernet/renesas/sh_eth.h | 5 +-
- 3 files changed, 120 insertions(+), 6 deletions(-)
-
-diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig
-index 3fb2355..46df3a0 100644
---- a/drivers/net/ethernet/renesas/Kconfig
-+++ b/drivers/net/ethernet/renesas/Kconfig
-@@ -4,11 +4,11 @@
-
- config SH_ETH
- tristate "Renesas SuperH Ethernet support"
-- depends on SUPERH && \
-+ depends on (SUPERH || ARCH_SHMOBILE) && \
- (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \
- CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \
- CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \
-- CPU_SUBTYPE_SH7757)
-+ CPU_SUBTYPE_SH7757 || ARCH_R8A7740)
- select CRC32
- select NET_CORE
- select MII
-@@ -17,4 +17,5 @@ config SH_ETH
- ---help---
- Renesas SuperH Ethernet device driver.
- This driver supporting CPUs are:
-- - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763 and SH7757.
-+ - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763, SH7757,
-+ and R8A7740.
-diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
-index d63e09b..be3c221 100644
---- a/drivers/net/ethernet/renesas/sh_eth.c
-+++ b/drivers/net/ethernet/renesas/sh_eth.c
-@@ -386,6 +386,114 @@ static void sh_eth_reset_hw_crc(struct net_device *ndev)
- sh_eth_write(ndev, 0x0, CSMR);
- }
-
-+#elif defined(CONFIG_ARCH_R8A7740)
-+#define SH_ETH_HAS_TSU 1
-+static void sh_eth_chip_reset(struct net_device *ndev)
-+{
-+ struct sh_eth_private *mdp = netdev_priv(ndev);
-+ unsigned long mii;
-+
-+ /* reset device */
-+ sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
-+ mdelay(1);
-+
-+ switch (mdp->phy_interface) {
-+ case PHY_INTERFACE_MODE_GMII:
-+ mii = 2;
-+ break;
-+ case PHY_INTERFACE_MODE_MII:
-+ mii = 1;
-+ break;
-+ case PHY_INTERFACE_MODE_RMII:
-+ default:
-+ mii = 0;
-+ break;
-+ }
-+ sh_eth_write(ndev, mii, RMII_MII);
-+}
-+
-+static void sh_eth_reset(struct net_device *ndev)
-+{
-+ int cnt = 100;
-+
-+ sh_eth_write(ndev, EDSR_ENALL, EDSR);
-+ sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
-+ while (cnt > 0) {
-+ if (!(sh_eth_read(ndev, EDMR) & 0x3))
-+ break;
-+ mdelay(1);
-+ cnt--;
-+ }
-+ if (cnt == 0)
-+ printk(KERN_ERR "Device reset fail\n");
-+
-+ /* Table Init */
-+ sh_eth_write(ndev, 0x0, TDLAR);
-+ sh_eth_write(ndev, 0x0, TDFAR);
-+ sh_eth_write(ndev, 0x0, TDFXR);
-+ sh_eth_write(ndev, 0x0, TDFFR);
-+ sh_eth_write(ndev, 0x0, RDLAR);
-+ sh_eth_write(ndev, 0x0, RDFAR);
-+ sh_eth_write(ndev, 0x0, RDFXR);
-+ sh_eth_write(ndev, 0x0, RDFFR);
-+}
-+
-+static void sh_eth_set_duplex(struct net_device *ndev)
-+{
-+ struct sh_eth_private *mdp = netdev_priv(ndev);
-+
-+ if (mdp->duplex) /* Full */
-+ sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
-+ else /* Half */
-+ sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
-+}
-+
-+static void sh_eth_set_rate(struct net_device *ndev)
-+{
-+ struct sh_eth_private *mdp = netdev_priv(ndev);
-+
-+ switch (mdp->speed) {
-+ case 10: /* 10BASE */
-+ sh_eth_write(ndev, GECMR_10, GECMR);
-+ break;
-+ case 100:/* 100BASE */
-+ sh_eth_write(ndev, GECMR_100, GECMR);
-+ break;
-+ case 1000: /* 1000BASE */
-+ sh_eth_write(ndev, GECMR_1000, GECMR);
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+/* R8A7740 */
-+static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
-+ .chip_reset = sh_eth_chip_reset,
-+ .set_duplex = sh_eth_set_duplex,
-+ .set_rate = sh_eth_set_rate,
-+
-+ .ecsr_value = ECSR_ICD | ECSR_MPD,
-+ .ecsipr_value = ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
-+ .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
-+
-+ .tx_check = EESR_TC1 | EESR_FTC,
-+ .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
-+ EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
-+ EESR_ECI,
-+ .tx_error_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
-+ EESR_TFE,
-+
-+ .apr = 1,
-+ .mpr = 1,
-+ .tpauser = 1,
-+ .bculr = 1,
-+ .hw_swap = 1,
-+ .no_trimd = 1,
-+ .no_ade = 1,
-+ .tsu = 1,
-+};
-+
- #elif defined(CONFIG_CPU_SUBTYPE_SH7619)
- #define SH_ETH_RESET_DEFAULT 1
- static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
-@@ -443,7 +551,7 @@ static void sh_eth_reset(struct net_device *ndev)
- }
- #endif
-
--#if defined(CONFIG_CPU_SH4)
-+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
- static void sh_eth_set_receive_align(struct sk_buff *skb)
- {
- int reserve;
-@@ -919,6 +1027,10 @@ static int sh_eth_rx(struct net_device *ndev)
- desc_status = edmac_to_cpu(mdp, rxdesc->status);
- pkt_len = rxdesc->frame_length;
-
-+#if defined(CONFIG_ARCH_R8A7740)
-+ desc_status >>= 16;
-+#endif
-+
- if (--boguscnt < 0)
- break;
-
-diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
-index 0fa14afc..57b8e1f 100644
---- a/drivers/net/ethernet/renesas/sh_eth.h
-+++ b/drivers/net/ethernet/renesas/sh_eth.h
-@@ -372,7 +372,7 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
- };
-
- /* Driver's parameters */
--#if defined(CONFIG_CPU_SH4)
-+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
- #define SH4_SKB_RX_ALIGN 32
- #else
- #define SH2_SH3_SKB_RX_ALIGN 2
-@@ -381,7 +381,8 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
- /*
- * Register's bits
- */
--#if defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
-+#if defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763) ||\
-+ defined(CONFIG_ARCH_R8A7740)
- /* EDSR */
- enum EDSR_BIT {
- EDSR_ENT = 0x01, EDSR_ENR = 0x02,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 02098572c84a88121b0baeb2b96cea47f17f2e3e Mon Sep 17 00:00:00 2001
-From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Date: Mon, 28 May 2012 23:07:55 +0000
-Subject: net: sh_eth: fix the rxdesc pointer when rx descriptor empty happens
-
-When Receive Descriptor Empty happens, rxdesc pointer of the driver
-and actual next descriptor of the controller may be mismatch.
-This patch fixes it.
-
-Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-(cherry picked from commit 79fba9f51755c704c0a7d7b7f0df10874dc0a744)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/net/ethernet/renesas/sh_eth.c | 8 +++++---
- 1 file changed, 5 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
-index be3c221..667169b 100644
---- a/drivers/net/ethernet/renesas/sh_eth.c
-+++ b/drivers/net/ethernet/renesas/sh_eth.c
-@@ -1101,8 +1101,12 @@ static int sh_eth_rx(struct net_device *ndev)
-
- /* Restart Rx engine if stopped. */
- /* If we don't need to check status, don't. -KDU */
-- if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R))
-+ if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R)) {
-+ /* fix the values for the next receiving */
-+ mdp->cur_rx = mdp->dirty_rx = (sh_eth_read(ndev, RDFAR) -
-+ sh_eth_read(ndev, RDLAR)) >> 4;
- sh_eth_write(ndev, EDRRR_R, EDRRR);
-+ }
-
- return 0;
- }
-@@ -1199,8 +1203,6 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
- /* Receive Descriptor Empty int */
- ndev->stats.rx_over_errors++;
-
-- if (sh_eth_read(ndev, EDRRR) ^ EDRRR_R)
-- sh_eth_write(ndev, EDRRR_R, EDRRR);
- if (netif_msg_rx_err(mdp))
- dev_err(&ndev->dev, "Receive Descriptor Empty\n");
- }
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 1c70638e065f5a6bba99f0e27a3b4a4931c77681 Mon Sep 17 00:00:00 2001
-From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Date: Wed, 20 Jun 2012 15:26:34 +0000
-Subject: net: sh_eth: fix the condition to fix the cur_tx/dirty_rx
-
-The following commit couldn't work if the RMCR is not set to 1.
-
-"net: sh_eth: fix the rxdesc pointer when rx descriptor empty happens"
-commit id 79fba9f51755c704c0a7d7b7f0df10874dc0a744
-
-If RMCR is not set, the controller will clear the EDRRR after it received
-a frame. In this case, the driver doesn't need to fix the value of
-cur_rx/dirty_rx. The driver only needs it when the controll detects
-receive descriptors are empty.
-
-Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-(cherry picked from commit a18e08bdcf845efb7344cea146e683df746bbfb4)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/net/ethernet/renesas/sh_eth.c | 12 +++++++-----
- 1 file changed, 7 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
-index 667169b..79bf09b 100644
---- a/drivers/net/ethernet/renesas/sh_eth.c
-+++ b/drivers/net/ethernet/renesas/sh_eth.c
-@@ -1011,7 +1011,7 @@ static int sh_eth_txfree(struct net_device *ndev)
- }
-
- /* Packet receive function */
--static int sh_eth_rx(struct net_device *ndev)
-+static int sh_eth_rx(struct net_device *ndev, u32 intr_status)
- {
- struct sh_eth_private *mdp = netdev_priv(ndev);
- struct sh_eth_rxdesc *rxdesc;
-@@ -1102,9 +1102,11 @@ static int sh_eth_rx(struct net_device *ndev)
- /* Restart Rx engine if stopped. */
- /* If we don't need to check status, don't. -KDU */
- if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R)) {
-- /* fix the values for the next receiving */
-- mdp->cur_rx = mdp->dirty_rx = (sh_eth_read(ndev, RDFAR) -
-- sh_eth_read(ndev, RDLAR)) >> 4;
-+ /* fix the values for the next receiving if RDE is set */
-+ if (intr_status & EESR_RDE)
-+ mdp->cur_rx = mdp->dirty_rx =
-+ (sh_eth_read(ndev, RDFAR) -
-+ sh_eth_read(ndev, RDLAR)) >> 4;
- sh_eth_write(ndev, EDRRR_R, EDRRR);
- }
-
-@@ -1273,7 +1275,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
- EESR_RTSF | /* short frame recv */
- EESR_PRE | /* PHY-LSI recv error */
- EESR_CERF)){ /* recv frame CRC error */
-- sh_eth_rx(ndev);
-+ sh_eth_rx(ndev, intr_status);
- }
-
- /* Tx Check */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a9d45f3559e2b48428446114ae6817f8a4883de8 Mon Sep 17 00:00:00 2001
-From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
-Date: Mon, 25 Jun 2012 17:34:14 +0000
-Subject: net/sh-eth: Add support selecting MII function for SH7734 and R8A7740
-
-Ethernet IP of SH7734 and R8A7740 has selecting MII register.
-The user needs to change a value according to MII to be used.
-This adds the function to change the value of this register.
-
-Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-(cherry picked from commit 5e7a76be0e48217aff6b6f34bdcce4725db999e2)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/net/ethernet/renesas/sh_eth.c | 108 ++++++++++++++++++++--------------
- drivers/net/ethernet/renesas/sh_eth.h | 1 +
- 2 files changed, 66 insertions(+), 43 deletions(-)
-
-diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
-index 79bf09b..8d696e0 100644
---- a/drivers/net/ethernet/renesas/sh_eth.c
-+++ b/drivers/net/ethernet/renesas/sh_eth.c
-@@ -49,6 +49,34 @@
- NETIF_MSG_RX_ERR| \
- NETIF_MSG_TX_ERR)
-
-+#if defined(CONFIG_CPU_SUBTYPE_SH7734) || \
-+ defined(CONFIG_CPU_SUBTYPE_SH7763) || \
-+ defined(CONFIG_ARCH_R8A7740)
-+static void sh_eth_select_mii(struct net_device *ndev)
-+{
-+ u32 value = 0x0;
-+ struct sh_eth_private *mdp = netdev_priv(ndev);
-+
-+ switch (mdp->phy_interface) {
-+ case PHY_INTERFACE_MODE_GMII:
-+ value = 0x2;
-+ break;
-+ case PHY_INTERFACE_MODE_MII:
-+ value = 0x1;
-+ break;
-+ case PHY_INTERFACE_MODE_RMII:
-+ value = 0x0;
-+ break;
-+ default:
-+ pr_warn("PHY interface mode was not setup. Set to MII.\n");
-+ value = 0x1;
-+ break;
-+ }
-+
-+ sh_eth_write(ndev, value, RMII_MII);
-+}
-+#endif
-+
- /* There is CPU dependent code */
- #if defined(CONFIG_CPU_SUBTYPE_SH7724)
- #define SH_ETH_RESET_DEFAULT 1
-@@ -283,6 +311,7 @@ static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
- #elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
- #define SH_ETH_HAS_TSU 1
- static void sh_eth_reset_hw_crc(struct net_device *ndev);
-+
- static void sh_eth_chip_reset(struct net_device *ndev)
- {
- struct sh_eth_private *mdp = netdev_priv(ndev);
-@@ -292,35 +321,6 @@ static void sh_eth_chip_reset(struct net_device *ndev)
- mdelay(1);
- }
-
--static void sh_eth_reset(struct net_device *ndev)
--{
-- int cnt = 100;
--
-- sh_eth_write(ndev, EDSR_ENALL, EDSR);
-- sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
-- while (cnt > 0) {
-- if (!(sh_eth_read(ndev, EDMR) & 0x3))
-- break;
-- mdelay(1);
-- cnt--;
-- }
-- if (cnt == 0)
-- printk(KERN_ERR "Device reset fail\n");
--
-- /* Table Init */
-- sh_eth_write(ndev, 0x0, TDLAR);
-- sh_eth_write(ndev, 0x0, TDFAR);
-- sh_eth_write(ndev, 0x0, TDFXR);
-- sh_eth_write(ndev, 0x0, TDFFR);
-- sh_eth_write(ndev, 0x0, RDLAR);
-- sh_eth_write(ndev, 0x0, RDFAR);
-- sh_eth_write(ndev, 0x0, RDFXR);
-- sh_eth_write(ndev, 0x0, RDFFR);
--
-- /* Reset HW CRC register */
-- sh_eth_reset_hw_crc(ndev);
--}
--
- static void sh_eth_set_duplex(struct net_device *ndev)
- {
- struct sh_eth_private *mdp = netdev_priv(ndev);
-@@ -377,9 +377,43 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
- .tsu = 1,
- #if defined(CONFIG_CPU_SUBTYPE_SH7734)
- .hw_crc = 1,
-+ .select_mii = 1,
- #endif
- };
-
-+static void sh_eth_reset(struct net_device *ndev)
-+{
-+ int cnt = 100;
-+
-+ sh_eth_write(ndev, EDSR_ENALL, EDSR);
-+ sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
-+ while (cnt > 0) {
-+ if (!(sh_eth_read(ndev, EDMR) & 0x3))
-+ break;
-+ mdelay(1);
-+ cnt--;
-+ }
-+ if (cnt == 0)
-+ printk(KERN_ERR "Device reset fail\n");
-+
-+ /* Table Init */
-+ sh_eth_write(ndev, 0x0, TDLAR);
-+ sh_eth_write(ndev, 0x0, TDFAR);
-+ sh_eth_write(ndev, 0x0, TDFXR);
-+ sh_eth_write(ndev, 0x0, TDFFR);
-+ sh_eth_write(ndev, 0x0, RDLAR);
-+ sh_eth_write(ndev, 0x0, RDFAR);
-+ sh_eth_write(ndev, 0x0, RDFXR);
-+ sh_eth_write(ndev, 0x0, RDFFR);
-+
-+ /* Reset HW CRC register */
-+ sh_eth_reset_hw_crc(ndev);
-+
-+ /* Select MII mode */
-+ if (sh_eth_my_cpu_data.select_mii)
-+ sh_eth_select_mii(ndev);
-+}
-+
- static void sh_eth_reset_hw_crc(struct net_device *ndev)
- {
- if (sh_eth_my_cpu_data.hw_crc)
-@@ -391,25 +425,12 @@ static void sh_eth_reset_hw_crc(struct net_device *ndev)
- static void sh_eth_chip_reset(struct net_device *ndev)
- {
- struct sh_eth_private *mdp = netdev_priv(ndev);
-- unsigned long mii;
-
- /* reset device */
- sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
- mdelay(1);
-
-- switch (mdp->phy_interface) {
-- case PHY_INTERFACE_MODE_GMII:
-- mii = 2;
-- break;
-- case PHY_INTERFACE_MODE_MII:
-- mii = 1;
-- break;
-- case PHY_INTERFACE_MODE_RMII:
-- default:
-- mii = 0;
-- break;
-- }
-- sh_eth_write(ndev, mii, RMII_MII);
-+ sh_eth_select_mii(ndev);
- }
-
- static void sh_eth_reset(struct net_device *ndev)
-@@ -492,6 +513,7 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
- .no_trimd = 1,
- .no_ade = 1,
- .tsu = 1,
-+ .select_mii = 1,
- };
-
- #elif defined(CONFIG_CPU_SUBTYPE_SH7619)
-diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
-index 57b8e1f..d6763b1392 100644
---- a/drivers/net/ethernet/renesas/sh_eth.h
-+++ b/drivers/net/ethernet/renesas/sh_eth.h
-@@ -757,6 +757,7 @@ struct sh_eth_cpu_data {
- unsigned no_trimd:1; /* E-DMAC DO NOT have TRIMD */
- unsigned no_ade:1; /* E-DMAC DO NOT have ADE bit in EESR */
- unsigned hw_crc:1; /* E-DMAC have CSMR */
-+ unsigned select_mii:1; /* EtherC have RMII_MII (MII select register) */
- };
-
- struct sh_eth_private {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From d9b780ce68b329aa745868803ec0419a3fd6975f Mon Sep 17 00:00:00 2001
-From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
-Date: Mon, 25 Jun 2012 17:35:12 +0000
-Subject: net/sh-eth: Check return value of sh_eth_reset when chip reset fail
-
-The sh_eth_reset function resets chip, but this performs nothing when failed.
-This changes sh_eth_reset return an error, when this failed in reset.
-
-Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-(cherry picked from commit 5cee1d37c9f565f1aa515408863dbb13db67dab9)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/net/ethernet/renesas/sh_eth.c | 88 ++++++++++++++++++++++-------------
- 1 file changed, 56 insertions(+), 32 deletions(-)
-
-diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
-index 8d696e0..326cb91 100644
---- a/drivers/net/ethernet/renesas/sh_eth.c
-+++ b/drivers/net/ethernet/renesas/sh_eth.c
-@@ -130,6 +130,8 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
- #elif defined(CONFIG_CPU_SUBTYPE_SH7757)
- #define SH_ETH_HAS_BOTH_MODULES 1
- #define SH_ETH_HAS_TSU 1
-+static int sh_eth_check_reset(struct net_device *ndev);
-+
- static void sh_eth_set_duplex(struct net_device *ndev)
- {
- struct sh_eth_private *mdp = netdev_priv(ndev);
-@@ -204,23 +206,19 @@ static void sh_eth_chip_reset_giga(struct net_device *ndev)
- }
-
- static int sh_eth_is_gether(struct sh_eth_private *mdp);
--static void sh_eth_reset(struct net_device *ndev)
-+static int sh_eth_reset(struct net_device *ndev)
- {
- struct sh_eth_private *mdp = netdev_priv(ndev);
-- int cnt = 100;
-+ int ret = 0;
-
- if (sh_eth_is_gether(mdp)) {
- sh_eth_write(ndev, 0x03, EDSR);
- sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER,
- EDMR);
-- while (cnt > 0) {
-- if (!(sh_eth_read(ndev, EDMR) & 0x3))
-- break;
-- mdelay(1);
-- cnt--;
-- }
-- if (cnt < 0)
-- printk(KERN_ERR "Device reset fail\n");
-+
-+ ret = sh_eth_check_reset(ndev);
-+ if (ret)
-+ goto out;
-
- /* Table Init */
- sh_eth_write(ndev, 0x0, TDLAR);
-@@ -238,6 +236,9 @@ static void sh_eth_reset(struct net_device *ndev)
- sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER,
- EDMR);
- }
-+
-+out:
-+ return ret;
- }
-
- static void sh_eth_set_duplex_giga(struct net_device *ndev)
-@@ -310,6 +311,7 @@ static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
-
- #elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
- #define SH_ETH_HAS_TSU 1
-+static int sh_eth_check_reset(struct net_device *ndev);
- static void sh_eth_reset_hw_crc(struct net_device *ndev);
-
- static void sh_eth_chip_reset(struct net_device *ndev)
-@@ -381,20 +383,16 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
- #endif
- };
-
--static void sh_eth_reset(struct net_device *ndev)
-+static int sh_eth_reset(struct net_device *ndev)
- {
-- int cnt = 100;
-+ int ret = 0;
-
- sh_eth_write(ndev, EDSR_ENALL, EDSR);
- sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
-- while (cnt > 0) {
-- if (!(sh_eth_read(ndev, EDMR) & 0x3))
-- break;
-- mdelay(1);
-- cnt--;
-- }
-- if (cnt == 0)
-- printk(KERN_ERR "Device reset fail\n");
-+
-+ ret = sh_eth_check_reset(ndev);
-+ if (ret)
-+ goto out;
-
- /* Table Init */
- sh_eth_write(ndev, 0x0, TDLAR);
-@@ -412,6 +410,8 @@ static void sh_eth_reset(struct net_device *ndev)
- /* Select MII mode */
- if (sh_eth_my_cpu_data.select_mii)
- sh_eth_select_mii(ndev);
-+out:
-+ return ret;
- }
-
- static void sh_eth_reset_hw_crc(struct net_device *ndev)
-@@ -422,6 +422,8 @@ static void sh_eth_reset_hw_crc(struct net_device *ndev)
-
- #elif defined(CONFIG_ARCH_R8A7740)
- #define SH_ETH_HAS_TSU 1
-+static int sh_eth_check_reset(struct net_device *ndev);
-+
- static void sh_eth_chip_reset(struct net_device *ndev)
- {
- struct sh_eth_private *mdp = netdev_priv(ndev);
-@@ -433,20 +435,16 @@ static void sh_eth_chip_reset(struct net_device *ndev)
- sh_eth_select_mii(ndev);
- }
-
--static void sh_eth_reset(struct net_device *ndev)
-+static int sh_eth_reset(struct net_device *ndev)
- {
-- int cnt = 100;
-+ int ret = 0;
-
- sh_eth_write(ndev, EDSR_ENALL, EDSR);
- sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
-- while (cnt > 0) {
-- if (!(sh_eth_read(ndev, EDMR) & 0x3))
-- break;
-- mdelay(1);
-- cnt--;
-- }
-- if (cnt == 0)
-- printk(KERN_ERR "Device reset fail\n");
-+
-+ ret = sh_eth_check_reset(ndev);
-+ if (ret)
-+ goto out;
-
- /* Table Init */
- sh_eth_write(ndev, 0x0, TDLAR);
-@@ -457,6 +455,9 @@ static void sh_eth_reset(struct net_device *ndev)
- sh_eth_write(ndev, 0x0, RDFAR);
- sh_eth_write(ndev, 0x0, RDFXR);
- sh_eth_write(ndev, 0x0, RDFFR);
-+
-+out:
-+ return ret;
- }
-
- static void sh_eth_set_duplex(struct net_device *ndev)
-@@ -565,11 +566,31 @@ static void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd)
-
- #if defined(SH_ETH_RESET_DEFAULT)
- /* Chip Reset */
--static void sh_eth_reset(struct net_device *ndev)
-+static int sh_eth_reset(struct net_device *ndev)
- {
- sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER, EDMR);
- mdelay(3);
- sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, EDMR);
-+
-+ return 0;
-+}
-+#else
-+static int sh_eth_check_reset(struct net_device *ndev)
-+{
-+ int ret = 0;
-+ int cnt = 100;
-+
-+ while (cnt > 0) {
-+ if (!(sh_eth_read(ndev, EDMR) & 0x3))
-+ break;
-+ mdelay(1);
-+ cnt--;
-+ }
-+ if (cnt < 0) {
-+ printk(KERN_ERR "Device reset fail\n");
-+ ret = -ETIMEDOUT;
-+ }
-+ return ret;
- }
- #endif
-
-@@ -924,7 +945,9 @@ static int sh_eth_dev_init(struct net_device *ndev)
- u32 val;
-
- /* Soft Reset */
-- sh_eth_reset(ndev);
-+ ret = sh_eth_reset(ndev);
-+ if (ret)
-+ goto out;
-
- /* Descriptor format */
- sh_eth_ring_format(ndev);
-@@ -998,6 +1021,7 @@ static int sh_eth_dev_init(struct net_device *ndev)
-
- netif_start_queue(ndev);
-
-+out:
- return ret;
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From da239ac021220b753bc1f21495ed187275f935aa Mon Sep 17 00:00:00 2001
-From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Date: Tue, 26 Jun 2012 19:59:51 +0000
-Subject: net: sh_eth: remove unnecessary function
-
-The sh_eth_timer() called mod_timer() for itself. So, this patch
-removes the function.
-
-Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-(cherry picked from commit c26502680e59af556211fc3fd3ae0f2aa5d98440)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/net/ethernet/renesas/sh_eth.c | 22 ----------------------
- drivers/net/ethernet/renesas/sh_eth.h | 1 -
- 2 files changed, 23 deletions(-)
-
-diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
-index 326cb91..cf0bc31 100644
---- a/drivers/net/ethernet/renesas/sh_eth.c
-+++ b/drivers/net/ethernet/renesas/sh_eth.c
-@@ -1339,14 +1339,6 @@ other_irq:
- return ret;
- }
-
--static void sh_eth_timer(unsigned long data)
--{
-- struct net_device *ndev = (struct net_device *)data;
-- struct sh_eth_private *mdp = netdev_priv(ndev);
--
-- mod_timer(&mdp->timer, jiffies + (10 * HZ));
--}
--
- /* PHY state control function */
- static void sh_eth_adjust_link(struct net_device *ndev)
- {
-@@ -1594,11 +1586,6 @@ static int sh_eth_open(struct net_device *ndev)
- if (ret)
- goto out_free_irq;
-
-- /* Set the timer to check for link beat. */
-- init_timer(&mdp->timer);
-- mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */
-- setup_timer(&mdp->timer, sh_eth_timer, (unsigned long)ndev);
--
- return ret;
-
- out_free_irq:
-@@ -1623,9 +1610,6 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
- /* tx_errors count up */
- ndev->stats.tx_errors++;
-
-- /* timer off */
-- del_timer_sync(&mdp->timer);
--
- /* Free all the skbuffs in the Rx queue. */
- for (i = 0; i < RX_RING_SIZE; i++) {
- rxdesc = &mdp->rx_ring[i];
-@@ -1643,10 +1627,6 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
-
- /* device init */
- sh_eth_dev_init(ndev);
--
-- /* timer on */
-- mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */
-- add_timer(&mdp->timer);
- }
-
- /* Packet transmit function */
-@@ -1719,8 +1699,6 @@ static int sh_eth_close(struct net_device *ndev)
-
- free_irq(ndev->irq, ndev);
-
-- del_timer_sync(&mdp->timer);
--
- /* Free all the skbuffs in the Rx queue. */
- sh_eth_ring_free(ndev);
-
-diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
-index d6763b1392..5af3f2a 100644
---- a/drivers/net/ethernet/renesas/sh_eth.h
-+++ b/drivers/net/ethernet/renesas/sh_eth.h
-@@ -772,7 +772,6 @@ struct sh_eth_private {
- struct sh_eth_txdesc *tx_ring;
- struct sk_buff **rx_skbuff;
- struct sk_buff **tx_skbuff;
-- struct timer_list timer;
- spinlock_t lock;
- u32 cur_rx, dirty_rx; /* Producer/consumer ring indices */
- u32 cur_tx, dirty_tx;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From c0de8fd97587b151f04aeb92c1946d30e04b3f8a Mon Sep 17 00:00:00 2001
-From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Date: Tue, 26 Jun 2012 19:59:58 +0000
-Subject: net: sh_eth: remove unnecessary members/definitions
-
-This patch removes unnecessary members in sh_th_private.
-This patch also removes unnecessary definitions in sh_eth.h
-
-Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-(cherry picked from commit 2ecbb783c3bf5a63f555c39deef308dcc1902b7f)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/net/ethernet/renesas/sh_eth.c | 7 +---
- drivers/net/ethernet/renesas/sh_eth.h | 69 -----------------------------------
- 2 files changed, 1 insertion(+), 75 deletions(-)
-
-diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
-index cf0bc31..43e76d2 100644
---- a/drivers/net/ethernet/renesas/sh_eth.c
-+++ b/drivers/net/ethernet/renesas/sh_eth.c
-@@ -941,7 +941,6 @@ static int sh_eth_dev_init(struct net_device *ndev)
- {
- int ret = 0;
- struct sh_eth_private *mdp = netdev_priv(ndev);
-- u_int32_t rx_int_var, tx_int_var;
- u32 val;
-
- /* Soft Reset */
-@@ -971,9 +970,7 @@ static int sh_eth_dev_init(struct net_device *ndev)
- /* Frame recv control */
- sh_eth_write(ndev, mdp->cd->rmcr_value, RMCR);
-
-- rx_int_var = mdp->rx_int_var = DESC_I_RINT8 | DESC_I_RINT5;
-- tx_int_var = mdp->tx_int_var = DESC_I_TINT2;
-- sh_eth_write(ndev, rx_int_var | tx_int_var, TRSCER);
-+ sh_eth_write(ndev, DESC_I_RINT8 | DESC_I_RINT5 | DESC_I_TINT2, TRSCER);
-
- if (mdp->cd->bculr)
- sh_eth_write(ndev, 0x800, BCULR); /* Burst sycle set */
-@@ -2336,8 +2333,6 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
-
- /* debug message level */
- mdp->msg_enable = SH_ETH_DEF_MSG_ENABLE;
-- mdp->post_rx = POST_RX >> (devno << 1);
-- mdp->post_fw = POST_FW >> (devno << 1);
-
- /* read and set MAC address */
- read_mac_address(ndev, pd->mac_addr);
-diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
-index 5af3f2a..37a0702 100644
---- a/drivers/net/ethernet/renesas/sh_eth.h
-+++ b/drivers/net/ethernet/renesas/sh_eth.h
-@@ -585,71 +585,6 @@ enum RPADIR_BIT {
- /* FDR */
- #define DEFAULT_FDR_INIT 0x00000707
-
--enum phy_offsets {
-- PHY_CTRL = 0, PHY_STAT = 1, PHY_IDT1 = 2, PHY_IDT2 = 3,
-- PHY_ANA = 4, PHY_ANL = 5, PHY_ANE = 6,
-- PHY_16 = 16,
--};
--
--/* PHY_CTRL */
--enum PHY_CTRL_BIT {
-- PHY_C_RESET = 0x8000, PHY_C_LOOPBK = 0x4000, PHY_C_SPEEDSL = 0x2000,
-- PHY_C_ANEGEN = 0x1000, PHY_C_PWRDN = 0x0800, PHY_C_ISO = 0x0400,
-- PHY_C_RANEG = 0x0200, PHY_C_DUPLEX = 0x0100, PHY_C_COLT = 0x0080,
--};
--#define DM9161_PHY_C_ANEGEN 0 /* auto nego special */
--
--/* PHY_STAT */
--enum PHY_STAT_BIT {
-- PHY_S_100T4 = 0x8000, PHY_S_100X_F = 0x4000, PHY_S_100X_H = 0x2000,
-- PHY_S_10T_F = 0x1000, PHY_S_10T_H = 0x0800, PHY_S_ANEGC = 0x0020,
-- PHY_S_RFAULT = 0x0010, PHY_S_ANEGA = 0x0008, PHY_S_LINK = 0x0004,
-- PHY_S_JAB = 0x0002, PHY_S_EXTD = 0x0001,
--};
--
--/* PHY_ANA */
--enum PHY_ANA_BIT {
-- PHY_A_NP = 0x8000, PHY_A_ACK = 0x4000, PHY_A_RF = 0x2000,
-- PHY_A_FCS = 0x0400, PHY_A_T4 = 0x0200, PHY_A_FDX = 0x0100,
-- PHY_A_HDX = 0x0080, PHY_A_10FDX = 0x0040, PHY_A_10HDX = 0x0020,
-- PHY_A_SEL = 0x001e,
--};
--/* PHY_ANL */
--enum PHY_ANL_BIT {
-- PHY_L_NP = 0x8000, PHY_L_ACK = 0x4000, PHY_L_RF = 0x2000,
-- PHY_L_FCS = 0x0400, PHY_L_T4 = 0x0200, PHY_L_FDX = 0x0100,
-- PHY_L_HDX = 0x0080, PHY_L_10FDX = 0x0040, PHY_L_10HDX = 0x0020,
-- PHY_L_SEL = 0x001f,
--};
--
--/* PHY_ANE */
--enum PHY_ANE_BIT {
-- PHY_E_PDF = 0x0010, PHY_E_LPNPA = 0x0008, PHY_E_NPA = 0x0004,
-- PHY_E_PRX = 0x0002, PHY_E_LPANEGA = 0x0001,
--};
--
--/* DM9161 */
--enum PHY_16_BIT {
-- PHY_16_BP4B45 = 0x8000, PHY_16_BPSCR = 0x4000, PHY_16_BPALIGN = 0x2000,
-- PHY_16_BP_ADPOK = 0x1000, PHY_16_Repeatmode = 0x0800,
-- PHY_16_TXselect = 0x0400,
-- PHY_16_Rsvd = 0x0200, PHY_16_RMIIEnable = 0x0100,
-- PHY_16_Force100LNK = 0x0080,
-- PHY_16_APDLED_CTL = 0x0040, PHY_16_COLLED_CTL = 0x0020,
-- PHY_16_RPDCTR_EN = 0x0010,
-- PHY_16_ResetStMch = 0x0008, PHY_16_PreamSupr = 0x0004,
-- PHY_16_Sleepmode = 0x0002,
-- PHY_16_RemoteLoopOut = 0x0001,
--};
--
--#define POST_RX 0x08
--#define POST_FW 0x04
--#define POST0_RX (POST_RX)
--#define POST0_FW (POST_FW)
--#define POST1_RX (POST_RX >> 2)
--#define POST1_FW (POST_FW >> 2)
--#define POST_ALL (POST0_RX | POST0_FW | POST1_RX | POST1_FW)
--
- /* ARSTR */
- enum ARSTR_BIT { ARSTR_ARSTR = 0x00000001, };
-
-@@ -786,10 +721,6 @@ struct sh_eth_private {
- int msg_enable;
- int speed;
- int duplex;
-- u32 rx_int_var, tx_int_var; /* interrupt control variables */
-- char post_rx; /* POST receive */
-- char post_fw; /* POST forward */
-- struct net_device_stats tsu_stats; /* TSU forward status */
- int port; /* for TSU */
- int vlan_num_ids; /* for VLAN tag filter */
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ec575069aff289fc8d05d09b897bb05e55e90adf Mon Sep 17 00:00:00 2001
-From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Date: Tue, 26 Jun 2012 20:00:01 +0000
-Subject: net: sh_eth: fix up the buffer pointers
-
-After freeing the buffer, the driver should change the value of
-the pointer to NULL.
-
-Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-(cherry picked from commit 91c77550000a7d888aaf9f9ac13e3e3485d18560)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/net/ethernet/renesas/sh_eth.c | 31 ++++++++++++++++++++++++-------
- 1 file changed, 24 insertions(+), 7 deletions(-)
-
-diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
-index 43e76d2..2dd2ff5 100644
---- a/drivers/net/ethernet/renesas/sh_eth.c
-+++ b/drivers/net/ethernet/renesas/sh_eth.c
-@@ -788,6 +788,7 @@ static void sh_eth_ring_free(struct net_device *ndev)
- }
- }
- kfree(mdp->rx_skbuff);
-+ mdp->rx_skbuff = NULL;
-
- /* Free Tx skb ringbuffer */
- if (mdp->tx_skbuff) {
-@@ -797,6 +798,7 @@ static void sh_eth_ring_free(struct net_device *ndev)
- }
- }
- kfree(mdp->tx_skbuff);
-+ mdp->tx_skbuff = NULL;
- }
-
- /* format skb and descriptor buffer */
-@@ -933,10 +935,31 @@ desc_ring_free:
- skb_ring_free:
- /* Free Rx and Tx skb ring buffer */
- sh_eth_ring_free(ndev);
-+ mdp->tx_ring = NULL;
-+ mdp->rx_ring = NULL;
-
- return ret;
- }
-
-+static void sh_eth_free_dma_buffer(struct sh_eth_private *mdp)
-+{
-+ int ringsize;
-+
-+ if (mdp->rx_ring) {
-+ ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
-+ dma_free_coherent(NULL, ringsize, mdp->rx_ring,
-+ mdp->rx_desc_dma);
-+ mdp->rx_ring = NULL;
-+ }
-+
-+ if (mdp->tx_ring) {
-+ ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
-+ dma_free_coherent(NULL, ringsize, mdp->tx_ring,
-+ mdp->tx_desc_dma);
-+ mdp->tx_ring = NULL;
-+ }
-+}
-+
- static int sh_eth_dev_init(struct net_device *ndev)
- {
- int ret = 0;
-@@ -1677,7 +1700,6 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
- static int sh_eth_close(struct net_device *ndev)
- {
- struct sh_eth_private *mdp = netdev_priv(ndev);
-- int ringsize;
-
- netif_stop_queue(ndev);
-
-@@ -1700,12 +1722,7 @@ static int sh_eth_close(struct net_device *ndev)
- sh_eth_ring_free(ndev);
-
- /* free DMA buffer */
-- ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
-- dma_free_coherent(NULL, ringsize, mdp->rx_ring, mdp->rx_desc_dma);
--
-- /* free DMA buffer */
-- ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
-- dma_free_coherent(NULL, ringsize, mdp->tx_ring, mdp->tx_desc_dma);
-+ sh_eth_free_dma_buffer(mdp);
-
- pm_runtime_put_sync(&mdp->pdev->dev);
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 53432c5cc072269a7e3ac40d2731da16434a24b2 Mon Sep 17 00:00:00 2001
-From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Date: Tue, 26 Jun 2012 20:00:03 +0000
-Subject: net: sh_eth: add support for set_ringparam/get_ringparam
-
-This patch supports the ethtool's set_ringparam() and get_ringparam().
-
-Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-(cherry picked from commit 525b8075edda9c2ab4b81e210505bd7487ea6e56)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/net/ethernet/renesas/sh_eth.c | 139 ++++++++++++++++++++++++++--------
- drivers/net/ethernet/renesas/sh_eth.h | 6 ++
- 2 files changed, 112 insertions(+), 33 deletions(-)
-
-diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
-index 2dd2ff5..af0b867 100644
---- a/drivers/net/ethernet/renesas/sh_eth.c
-+++ b/drivers/net/ethernet/renesas/sh_eth.c
-@@ -782,7 +782,7 @@ static void sh_eth_ring_free(struct net_device *ndev)
-
- /* Free Rx skb ringbuffer */
- if (mdp->rx_skbuff) {
-- for (i = 0; i < RX_RING_SIZE; i++) {
-+ for (i = 0; i < mdp->num_rx_ring; i++) {
- if (mdp->rx_skbuff[i])
- dev_kfree_skb(mdp->rx_skbuff[i]);
- }
-@@ -792,7 +792,7 @@ static void sh_eth_ring_free(struct net_device *ndev)
-
- /* Free Tx skb ringbuffer */
- if (mdp->tx_skbuff) {
-- for (i = 0; i < TX_RING_SIZE; i++) {
-+ for (i = 0; i < mdp->num_tx_ring; i++) {
- if (mdp->tx_skbuff[i])
- dev_kfree_skb(mdp->tx_skbuff[i]);
- }
-@@ -809,8 +809,8 @@ static void sh_eth_ring_format(struct net_device *ndev)
- struct sk_buff *skb;
- struct sh_eth_rxdesc *rxdesc = NULL;
- struct sh_eth_txdesc *txdesc = NULL;
-- int rx_ringsize = sizeof(*rxdesc) * RX_RING_SIZE;
-- int tx_ringsize = sizeof(*txdesc) * TX_RING_SIZE;
-+ int rx_ringsize = sizeof(*rxdesc) * mdp->num_rx_ring;
-+ int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring;
-
- mdp->cur_rx = mdp->cur_tx = 0;
- mdp->dirty_rx = mdp->dirty_tx = 0;
-@@ -818,7 +818,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
- memset(mdp->rx_ring, 0, rx_ringsize);
-
- /* build Rx ring buffer */
-- for (i = 0; i < RX_RING_SIZE; i++) {
-+ for (i = 0; i < mdp->num_rx_ring; i++) {
- /* skb */
- mdp->rx_skbuff[i] = NULL;
- skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
-@@ -844,7 +844,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
- }
- }
-
-- mdp->dirty_rx = (u32) (i - RX_RING_SIZE);
-+ mdp->dirty_rx = (u32) (i - mdp->num_rx_ring);
-
- /* Mark the last entry as wrapping the ring. */
- rxdesc->status |= cpu_to_edmac(mdp, RD_RDEL);
-@@ -852,7 +852,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
- memset(mdp->tx_ring, 0, tx_ringsize);
-
- /* build Tx ring buffer */
-- for (i = 0; i < TX_RING_SIZE; i++) {
-+ for (i = 0; i < mdp->num_tx_ring; i++) {
- mdp->tx_skbuff[i] = NULL;
- txdesc = &mdp->tx_ring[i];
- txdesc->status = cpu_to_edmac(mdp, TD_TFP);
-@@ -886,7 +886,7 @@ static int sh_eth_ring_init(struct net_device *ndev)
- mdp->rx_buf_sz += NET_IP_ALIGN;
-
- /* Allocate RX and TX skb rings */
-- mdp->rx_skbuff = kmalloc(sizeof(*mdp->rx_skbuff) * RX_RING_SIZE,
-+ mdp->rx_skbuff = kmalloc(sizeof(*mdp->rx_skbuff) * mdp->num_rx_ring,
- GFP_KERNEL);
- if (!mdp->rx_skbuff) {
- dev_err(&ndev->dev, "Cannot allocate Rx skb\n");
-@@ -894,7 +894,7 @@ static int sh_eth_ring_init(struct net_device *ndev)
- return ret;
- }
-
-- mdp->tx_skbuff = kmalloc(sizeof(*mdp->tx_skbuff) * TX_RING_SIZE,
-+ mdp->tx_skbuff = kmalloc(sizeof(*mdp->tx_skbuff) * mdp->num_tx_ring,
- GFP_KERNEL);
- if (!mdp->tx_skbuff) {
- dev_err(&ndev->dev, "Cannot allocate Tx skb\n");
-@@ -903,7 +903,7 @@ static int sh_eth_ring_init(struct net_device *ndev)
- }
-
- /* Allocate all Rx descriptors. */
-- rx_ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
-+ rx_ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring;
- mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma,
- GFP_KERNEL);
-
-@@ -917,7 +917,7 @@ static int sh_eth_ring_init(struct net_device *ndev)
- mdp->dirty_rx = 0;
-
- /* Allocate all Tx descriptors. */
-- tx_ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
-+ tx_ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring;
- mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma,
- GFP_KERNEL);
- if (!mdp->tx_ring) {
-@@ -946,21 +946,21 @@ static void sh_eth_free_dma_buffer(struct sh_eth_private *mdp)
- int ringsize;
-
- if (mdp->rx_ring) {
-- ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
-+ ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring;
- dma_free_coherent(NULL, ringsize, mdp->rx_ring,
- mdp->rx_desc_dma);
- mdp->rx_ring = NULL;
- }
-
- if (mdp->tx_ring) {
-- ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
-+ ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring;
- dma_free_coherent(NULL, ringsize, mdp->tx_ring,
- mdp->tx_desc_dma);
- mdp->tx_ring = NULL;
- }
- }
-
--static int sh_eth_dev_init(struct net_device *ndev)
-+static int sh_eth_dev_init(struct net_device *ndev, bool start)
- {
- int ret = 0;
- struct sh_eth_private *mdp = netdev_priv(ndev);
-@@ -1008,7 +1008,8 @@ static int sh_eth_dev_init(struct net_device *ndev)
- RFLR);
-
- sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR);
-- sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
-+ if (start)
-+ sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
-
- /* PAUSE Prohibition */
- val = (sh_eth_read(ndev, ECMR) & ECMR_DM) |
-@@ -1023,7 +1024,8 @@ static int sh_eth_dev_init(struct net_device *ndev)
- sh_eth_write(ndev, mdp->cd->ecsr_value, ECSR);
-
- /* E-MAC Interrupt Enable register */
-- sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR);
-+ if (start)
-+ sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR);
-
- /* Set MAC address */
- update_mac_address(ndev);
-@@ -1036,10 +1038,12 @@ static int sh_eth_dev_init(struct net_device *ndev)
- if (mdp->cd->tpauser)
- sh_eth_write(ndev, TPAUSER_UNLIMITED, TPAUSER);
-
-- /* Setting the Rx mode will start the Rx process. */
-- sh_eth_write(ndev, EDRRR_R, EDRRR);
-+ if (start) {
-+ /* Setting the Rx mode will start the Rx process. */
-+ sh_eth_write(ndev, EDRRR_R, EDRRR);
-
-- netif_start_queue(ndev);
-+ netif_start_queue(ndev);
-+ }
-
- out:
- return ret;
-@@ -1054,7 +1058,7 @@ static int sh_eth_txfree(struct net_device *ndev)
- int entry = 0;
-
- for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
-- entry = mdp->dirty_tx % TX_RING_SIZE;
-+ entry = mdp->dirty_tx % mdp->num_tx_ring;
- txdesc = &mdp->tx_ring[entry];
- if (txdesc->status & cpu_to_edmac(mdp, TD_TACT))
- break;
-@@ -1067,7 +1071,7 @@ static int sh_eth_txfree(struct net_device *ndev)
- freeNum++;
- }
- txdesc->status = cpu_to_edmac(mdp, TD_TFP);
-- if (entry >= TX_RING_SIZE - 1)
-+ if (entry >= mdp->num_tx_ring - 1)
- txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
-
- ndev->stats.tx_packets++;
-@@ -1082,8 +1086,8 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status)
- struct sh_eth_private *mdp = netdev_priv(ndev);
- struct sh_eth_rxdesc *rxdesc;
-
-- int entry = mdp->cur_rx % RX_RING_SIZE;
-- int boguscnt = (mdp->dirty_rx + RX_RING_SIZE) - mdp->cur_rx;
-+ int entry = mdp->cur_rx % mdp->num_rx_ring;
-+ int boguscnt = (mdp->dirty_rx + mdp->num_rx_ring) - mdp->cur_rx;
- struct sk_buff *skb;
- u16 pkt_len = 0;
- u32 desc_status;
-@@ -1134,13 +1138,13 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status)
- ndev->stats.rx_bytes += pkt_len;
- }
- rxdesc->status |= cpu_to_edmac(mdp, RD_RACT);
-- entry = (++mdp->cur_rx) % RX_RING_SIZE;
-+ entry = (++mdp->cur_rx) % mdp->num_rx_ring;
- rxdesc = &mdp->rx_ring[entry];
- }
-
- /* Refill the Rx ring buffers. */
- for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) {
-- entry = mdp->dirty_rx % RX_RING_SIZE;
-+ entry = mdp->dirty_rx % mdp->num_rx_ring;
- rxdesc = &mdp->rx_ring[entry];
- /* The size of the buffer is 16 byte boundary. */
- rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
-@@ -1157,7 +1161,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status)
- skb_checksum_none_assert(skb);
- rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
- }
-- if (entry >= RX_RING_SIZE - 1)
-+ if (entry >= mdp->num_rx_ring - 1)
- rxdesc->status |=
- cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDEL);
- else
-@@ -1557,6 +1561,71 @@ static void sh_eth_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
- }
- }
-
-+static void sh_eth_get_ringparam(struct net_device *ndev,
-+ struct ethtool_ringparam *ring)
-+{
-+ struct sh_eth_private *mdp = netdev_priv(ndev);
-+
-+ ring->rx_max_pending = RX_RING_MAX;
-+ ring->tx_max_pending = TX_RING_MAX;
-+ ring->rx_pending = mdp->num_rx_ring;
-+ ring->tx_pending = mdp->num_tx_ring;
-+}
-+
-+static int sh_eth_set_ringparam(struct net_device *ndev,
-+ struct ethtool_ringparam *ring)
-+{
-+ struct sh_eth_private *mdp = netdev_priv(ndev);
-+ int ret;
-+
-+ if (ring->tx_pending > TX_RING_MAX ||
-+ ring->rx_pending > RX_RING_MAX ||
-+ ring->tx_pending < TX_RING_MIN ||
-+ ring->rx_pending < RX_RING_MIN)
-+ return -EINVAL;
-+ if (ring->rx_mini_pending || ring->rx_jumbo_pending)
-+ return -EINVAL;
-+
-+ if (netif_running(ndev)) {
-+ netif_tx_disable(ndev);
-+ /* Disable interrupts by clearing the interrupt mask. */
-+ sh_eth_write(ndev, 0x0000, EESIPR);
-+ /* Stop the chip's Tx and Rx processes. */
-+ sh_eth_write(ndev, 0, EDTRR);
-+ sh_eth_write(ndev, 0, EDRRR);
-+ synchronize_irq(ndev->irq);
-+ }
-+
-+ /* Free all the skbuffs in the Rx queue. */
-+ sh_eth_ring_free(ndev);
-+ /* Free DMA buffer */
-+ sh_eth_free_dma_buffer(mdp);
-+
-+ /* Set new parameters */
-+ mdp->num_rx_ring = ring->rx_pending;
-+ mdp->num_tx_ring = ring->tx_pending;
-+
-+ ret = sh_eth_ring_init(ndev);
-+ if (ret < 0) {
-+ dev_err(&ndev->dev, "%s: sh_eth_ring_init failed.\n", __func__);
-+ return ret;
-+ }
-+ ret = sh_eth_dev_init(ndev, false);
-+ if (ret < 0) {
-+ dev_err(&ndev->dev, "%s: sh_eth_dev_init failed.\n", __func__);
-+ return ret;
-+ }
-+
-+ if (netif_running(ndev)) {
-+ sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
-+ /* Setting the Rx mode will start the Rx process. */
-+ sh_eth_write(ndev, EDRRR_R, EDRRR);
-+ netif_wake_queue(ndev);
-+ }
-+
-+ return 0;
-+}
-+
- static const struct ethtool_ops sh_eth_ethtool_ops = {
- .get_settings = sh_eth_get_settings,
- .set_settings = sh_eth_set_settings,
-@@ -1567,6 +1636,8 @@ static const struct ethtool_ops sh_eth_ethtool_ops = {
- .get_strings = sh_eth_get_strings,
- .get_ethtool_stats = sh_eth_get_ethtool_stats,
- .get_sset_count = sh_eth_get_sset_count,
-+ .get_ringparam = sh_eth_get_ringparam,
-+ .set_ringparam = sh_eth_set_ringparam,
- };
-
- /* network device open function */
-@@ -1597,7 +1668,7 @@ static int sh_eth_open(struct net_device *ndev)
- goto out_free_irq;
-
- /* device init */
-- ret = sh_eth_dev_init(ndev);
-+ ret = sh_eth_dev_init(ndev, true);
- if (ret)
- goto out_free_irq;
-
-@@ -1631,7 +1702,7 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
- ndev->stats.tx_errors++;
-
- /* Free all the skbuffs in the Rx queue. */
-- for (i = 0; i < RX_RING_SIZE; i++) {
-+ for (i = 0; i < mdp->num_rx_ring; i++) {
- rxdesc = &mdp->rx_ring[i];
- rxdesc->status = 0;
- rxdesc->addr = 0xBADF00D0;
-@@ -1639,14 +1710,14 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
- dev_kfree_skb(mdp->rx_skbuff[i]);
- mdp->rx_skbuff[i] = NULL;
- }
-- for (i = 0; i < TX_RING_SIZE; i++) {
-+ for (i = 0; i < mdp->num_tx_ring; i++) {
- if (mdp->tx_skbuff[i])
- dev_kfree_skb(mdp->tx_skbuff[i]);
- mdp->tx_skbuff[i] = NULL;
- }
-
- /* device init */
-- sh_eth_dev_init(ndev);
-+ sh_eth_dev_init(ndev, true);
- }
-
- /* Packet transmit function */
-@@ -1658,7 +1729,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
- unsigned long flags;
-
- spin_lock_irqsave(&mdp->lock, flags);
-- if ((mdp->cur_tx - mdp->dirty_tx) >= (TX_RING_SIZE - 4)) {
-+ if ((mdp->cur_tx - mdp->dirty_tx) >= (mdp->num_tx_ring - 4)) {
- if (!sh_eth_txfree(ndev)) {
- if (netif_msg_tx_queued(mdp))
- dev_warn(&ndev->dev, "TxFD exhausted.\n");
-@@ -1669,7 +1740,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
- }
- spin_unlock_irqrestore(&mdp->lock, flags);
-
-- entry = mdp->cur_tx % TX_RING_SIZE;
-+ entry = mdp->cur_tx % mdp->num_tx_ring;
- mdp->tx_skbuff[entry] = skb;
- txdesc = &mdp->tx_ring[entry];
- /* soft swap. */
-@@ -1683,7 +1754,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
- else
- txdesc->buffer_length = skb->len;
-
-- if (entry >= TX_RING_SIZE - 1)
-+ if (entry >= mdp->num_tx_ring - 1)
- txdesc->status |= cpu_to_edmac(mdp, TD_TACT | TD_TDLE);
- else
- txdesc->status |= cpu_to_edmac(mdp, TD_TACT);
-@@ -2313,6 +2384,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
- ether_setup(ndev);
-
- mdp = netdev_priv(ndev);
-+ mdp->num_tx_ring = TX_RING_SIZE;
-+ mdp->num_rx_ring = RX_RING_SIZE;
- mdp->addr = ioremap(res->start, resource_size(res));
- if (mdp->addr == NULL) {
- ret = -ENOMEM;
-diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
-index 37a0702..bae84fd 100644
---- a/drivers/net/ethernet/renesas/sh_eth.h
-+++ b/drivers/net/ethernet/renesas/sh_eth.h
-@@ -27,6 +27,10 @@
- #define TX_TIMEOUT (5*HZ)
- #define TX_RING_SIZE 64 /* Tx ring size */
- #define RX_RING_SIZE 64 /* Rx ring size */
-+#define TX_RING_MIN 64
-+#define RX_RING_MIN 64
-+#define TX_RING_MAX 1024
-+#define RX_RING_MAX 1024
- #define ETHERSMALL 60
- #define PKT_BUF_SZ 1538
- #define SH_ETH_TSU_TIMEOUT_MS 500
-@@ -701,6 +705,8 @@ struct sh_eth_private {
- const u16 *reg_offset;
- void __iomem *addr;
- void __iomem *tsu_addr;
-+ u32 num_rx_ring;
-+ u32 num_tx_ring;
- dma_addr_t rx_desc_dma;
- dma_addr_t tx_desc_dma;
- struct sh_eth_rxdesc *rx_ring;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 404932d6f9282b0b5acf10d854fd65611f884521 Mon Sep 17 00:00:00 2001
-From: Phil Edworthy <PHIL.EDWORTHY@renesas.com>
-Date: Tue, 14 Aug 2012 20:33:29 +0000
-Subject: net: sh_eth: Add eth support for R8A7779 device
-
-Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-(cherry picked from commit d0418bb7123f44b23d69ac349eec7daf9103472f)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/net/ethernet/renesas/Kconfig | 4 ++--
- drivers/net/ethernet/renesas/sh_eth.c | 11 ++++++++---
- 2 files changed, 10 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig
-index 46df3a0..24c2305 100644
---- a/drivers/net/ethernet/renesas/Kconfig
-+++ b/drivers/net/ethernet/renesas/Kconfig
-@@ -8,7 +8,7 @@ config SH_ETH
- (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \
- CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \
- CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \
-- CPU_SUBTYPE_SH7757 || ARCH_R8A7740)
-+ CPU_SUBTYPE_SH7757 || ARCH_R8A7740 || ARCH_R8A7779)
- select CRC32
- select NET_CORE
- select MII
-@@ -18,4 +18,4 @@ config SH_ETH
- Renesas SuperH Ethernet device driver.
- This driver supporting CPUs are:
- - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763, SH7757,
-- and R8A7740.
-+ R8A7740 and R8A7779.
-diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
-index af0b867..bad8f2e 100644
---- a/drivers/net/ethernet/renesas/sh_eth.c
-+++ b/drivers/net/ethernet/renesas/sh_eth.c
-@@ -78,7 +78,7 @@ static void sh_eth_select_mii(struct net_device *ndev)
- #endif
-
- /* There is CPU dependent code */
--#if defined(CONFIG_CPU_SUBTYPE_SH7724)
-+#if defined(CONFIG_CPU_SUBTYPE_SH7724) || defined(CONFIG_ARCH_R8A7779)
- #define SH_ETH_RESET_DEFAULT 1
- static void sh_eth_set_duplex(struct net_device *ndev)
- {
-@@ -93,13 +93,18 @@ static void sh_eth_set_duplex(struct net_device *ndev)
- static void sh_eth_set_rate(struct net_device *ndev)
- {
- struct sh_eth_private *mdp = netdev_priv(ndev);
-+ unsigned int bits = ECMR_RTM;
-+
-+#if defined(CONFIG_ARCH_R8A7779)
-+ bits |= ECMR_ELB;
-+#endif
-
- switch (mdp->speed) {
- case 10: /* 10BASE */
-- sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR);
-+ sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~bits, ECMR);
- break;
- case 100:/* 100BASE */
-- sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR);
-+ sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | bits, ECMR);
- break;
- default:
- break;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e824e077a91eecb30f3a4124516811ffc382b5a8 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Sun, 8 Apr 2012 21:17:50 -0700
-Subject: ASoC: add generic simple-card support
-
-Current ASoC requires card.c file to each platforms in order to
-specifies its CPU and Codecs pair.
-But the differences between these were only value/strings of setting.
-In order to reduce duplicate driver, this patch adds generic/simple-card.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit f2390880ec0264a0ed26b32c23bc23435b4297da)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- include/sound/simple_card.h | 38 +++++++++++++
- sound/soc/Kconfig | 3 +
- sound/soc/Makefile | 1
- sound/soc/generic/Kconfig | 4 +
- sound/soc/generic/Makefile | 3 +
- sound/soc/generic/simple-card.c | 114 ++++++++++++++++++++++++++++++++++++++++
- 6 files changed, 163 insertions(+)
- create mode 100644 include/sound/simple_card.h
- create mode 100644 sound/soc/generic/Kconfig
- create mode 100644 sound/soc/generic/Makefile
- create mode 100644 sound/soc/generic/simple-card.c
-
---- /dev/null
-+++ b/include/sound/simple_card.h
-@@ -0,0 +1,38 @@
-+/*
-+ * ASoC simple sound card support
-+ *
-+ * Copyright (C) 2012 Renesas Solutions Corp.
-+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.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
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef __SIMPLE_CARD_H
-+#define __SIMPLE_CARD_H
-+
-+#include <sound/soc.h>
-+
-+struct asoc_simple_dai_init_info {
-+ unsigned int fmt;
-+ unsigned int cpu_daifmt;
-+ unsigned int codec_daifmt;
-+ unsigned int sysclk;
-+};
-+
-+struct asoc_simple_card_info {
-+ const char *name;
-+ const char *card;
-+ const char *cpu_dai;
-+ const char *codec;
-+ const char *platform;
-+ const char *codec_dai;
-+ struct asoc_simple_dai_init_info *init; /* for snd_link.init */
-+
-+ /* used in simple-card.c */
-+ struct snd_soc_dai_link snd_link;
-+ struct snd_soc_card snd_card;
-+};
-+
-+#endif /* __SIMPLE_CARD_H */
---- a/sound/soc/Kconfig
-+++ b/sound/soc/Kconfig
-@@ -52,5 +52,8 @@ source "sound/soc/txx9/Kconfig"
- # Supported codecs
- source "sound/soc/codecs/Kconfig"
-
-+# generic frame-work
-+source "sound/soc/generic/Kconfig"
-+
- endif # SND_SOC
-
---- a/sound/soc/Makefile
-+++ b/sound/soc/Makefile
-@@ -7,6 +7,7 @@ endif
-
- obj-$(CONFIG_SND_SOC) += snd-soc-core.o
- obj-$(CONFIG_SND_SOC) += codecs/
-+obj-$(CONFIG_SND_SOC) += generic/
- obj-$(CONFIG_SND_SOC) += atmel/
- obj-$(CONFIG_SND_SOC) += au1x/
- obj-$(CONFIG_SND_SOC) += blackfin/
---- /dev/null
-+++ b/sound/soc/generic/Kconfig
-@@ -0,0 +1,4 @@
-+config SND_SIMPLE_CARD
-+ tristate "ASoC Simple sound card support"
-+ help
-+ This option enables generic simple sound card support
---- /dev/null
-+++ b/sound/soc/generic/Makefile
-@@ -0,0 +1,3 @@
-+snd-soc-simple-card-objs := simple-card.o
-+
-+obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o
---- /dev/null
-+++ b/sound/soc/generic/simple-card.c
-@@ -0,0 +1,114 @@
-+/*
-+ * ASoC simple sound card support
-+ *
-+ * Copyright (C) 2012 Renesas Solutions Corp.
-+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.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
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/platform_device.h>
-+#include <linux/module.h>
-+#include <sound/simple_card.h>
-+
-+#define asoc_simple_get_card_info(p) \
-+ container_of(p->dai_link, struct asoc_simple_card_info, snd_link)
-+
-+static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
-+{
-+ struct asoc_simple_card_info *cinfo = asoc_simple_get_card_info(rtd);
-+ struct asoc_simple_dai_init_info *iinfo = cinfo->init;
-+ struct snd_soc_dai *codec = rtd->codec_dai;
-+ struct snd_soc_dai *cpu = rtd->cpu_dai;
-+ unsigned int cpu_daifmt = iinfo->fmt | iinfo->cpu_daifmt;
-+ unsigned int codec_daifmt = iinfo->fmt | iinfo->codec_daifmt;
-+ int ret;
-+
-+ if (codec_daifmt) {
-+ ret = snd_soc_dai_set_fmt(codec, codec_daifmt);
-+ if (ret < 0)
-+ return ret;
-+ }
-+
-+ if (iinfo->sysclk) {
-+ ret = snd_soc_dai_set_sysclk(codec, 0, iinfo->sysclk, 0);
-+ if (ret < 0)
-+ return ret;
-+ }
-+
-+ if (cpu_daifmt) {
-+ ret = snd_soc_dai_set_fmt(cpu, cpu_daifmt);
-+ if (ret < 0)
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static int asoc_simple_card_probe(struct platform_device *pdev)
-+{
-+ struct asoc_simple_card_info *cinfo = pdev->dev.platform_data;
-+
-+ if (!cinfo) {
-+ dev_err(&pdev->dev, "no info for asoc-simple-card\n");
-+ return -EINVAL;
-+ }
-+
-+ if (!cinfo->name ||
-+ !cinfo->card ||
-+ !cinfo->cpu_dai ||
-+ !cinfo->codec ||
-+ !cinfo->platform ||
-+ !cinfo->codec_dai) {
-+ dev_err(&pdev->dev, "insufficient asoc_simple_card_info settings\n");
-+ return -EINVAL;
-+ }
-+
-+ /*
-+ * init snd_soc_dai_link
-+ */
-+ cinfo->snd_link.name = cinfo->name;
-+ cinfo->snd_link.stream_name = cinfo->name;
-+ cinfo->snd_link.cpu_dai_name = cinfo->cpu_dai;
-+ cinfo->snd_link.platform_name = cinfo->platform;
-+ cinfo->snd_link.codec_name = cinfo->codec;
-+ cinfo->snd_link.codec_dai_name = cinfo->codec_dai;
-+
-+ /* enable snd_link.init if cinfo has settings */
-+ if (cinfo->init)
-+ cinfo->snd_link.init = asoc_simple_card_dai_init;
-+
-+ /*
-+ * init snd_soc_card
-+ */
-+ cinfo->snd_card.name = cinfo->card;
-+ cinfo->snd_card.owner = THIS_MODULE;
-+ cinfo->snd_card.dai_link = &cinfo->snd_link;
-+ cinfo->snd_card.num_links = 1;
-+ cinfo->snd_card.dev = &pdev->dev;
-+
-+ return snd_soc_register_card(&cinfo->snd_card);
-+}
-+
-+static int asoc_simple_card_remove(struct platform_device *pdev)
-+{
-+ struct asoc_simple_card_info *cinfo = pdev->dev.platform_data;
-+
-+ return snd_soc_unregister_card(&cinfo->snd_card);
-+}
-+
-+static struct platform_driver asoc_simple_card = {
-+ .driver = {
-+ .name = "asoc-simple-card",
-+ },
-+ .probe = asoc_simple_card_probe,
-+ .remove = asoc_simple_card_remove,
-+};
-+
-+module_platform_driver(asoc_simple_card);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("ASoC Simple Sound Card");
-+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
+++ /dev/null
-From 69dbe4e265126dd9dcd679d7f707c73fa86b88ef Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Sun, 8 Apr 2012 21:18:28 -0700
-Subject: ASoC: sh: fsi: use simple-card instead of fsi-ak4642
-
-This patch uses simple-card driver instead of fsi-ak4642 on each board.
-To select AK4642 driver, each boards select it on Kconfig.
-
-This patch removes fsi-ak4642 driver which is no longer needed
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit af8a2fe12fae1b59178dc96e396e5665bcbea7da)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/Kconfig | 2 +
- arch/arm/mach-shmobile/board-ap4evb.c | 15 ++++-
- arch/arm/mach-shmobile/board-mackerel.c | 15 ++++-
- arch/sh/boards/Kconfig | 1 +
- arch/sh/boards/mach-se/7724/setup.c | 15 ++++-
- include/sound/sh_fsi.h | 12 ----
- sound/soc/sh/Kconfig | 8 ---
- sound/soc/sh/Makefile | 2 -
- sound/soc/sh/fsi-ak4642.c | 108 --------------------------------
- 9 files changed, 39 insertions(+), 139 deletions(-)
- delete mode 100644 sound/soc/sh/fsi-ak4642.c
-
-diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
-index 34560ca..2cda0c2 100644
---- a/arch/arm/mach-shmobile/Kconfig
-+++ b/arch/arm/mach-shmobile/Kconfig
-@@ -58,6 +58,7 @@ config MACH_AP4EVB
- depends on ARCH_SH7372
- select ARCH_REQUIRE_GPIOLIB
- select SH_LCD_MIPI_DSI
-+ select SND_SOC_AK4642 if SND_SIMPLE_CARD
-
- choice
- prompt "AP4EVB LCD panel selection"
-@@ -82,6 +83,7 @@ config MACH_MACKEREL
- bool "mackerel board"
- depends on ARCH_SH7372
- select ARCH_REQUIRE_GPIOLIB
-+ select SND_SOC_AK4642 if SND_SIMPLE_CARD
-
- config MACH_KOTA2
- bool "KOTA2 board"
-diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
-index b56dde2..b397512 100644
---- a/arch/arm/mach-shmobile/board-ap4evb.c
-+++ b/arch/arm/mach-shmobile/board-ap4evb.c
-@@ -50,6 +50,7 @@
- #include <media/soc_camera.h>
-
- #include <sound/sh_fsi.h>
-+#include <sound/simple_card.h>
-
- #include <video/sh_mobile_hdmi.h>
- #include <video/sh_mobile_lcdc.h>
-@@ -785,17 +786,25 @@ static struct platform_device fsi_device = {
- },
- };
-
--static struct fsi_ak4642_info fsi2_ak4643_info = {
-+static struct asoc_simple_dai_init_info fsi2_ak4643_init_info = {
-+ .fmt = SND_SOC_DAIFMT_LEFT_J,
-+ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM,
-+ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS,
-+ .sysclk = 11289600,
-+};
-+
-+static struct asoc_simple_card_info fsi2_ak4643_info = {
- .name = "AK4643",
- .card = "FSI2A-AK4643",
- .cpu_dai = "fsia-dai",
- .codec = "ak4642-codec.0-0013",
- .platform = "sh_fsi2",
-- .id = FSI_PORT_A,
-+ .codec_dai = "ak4642-hifi",
-+ .init = &fsi2_ak4643_init_info,
- };
-
- static struct platform_device fsi_ak4643_device = {
-- .name = "fsi-ak4642-audio",
-+ .name = "asoc-simple-card",
- .dev = {
- .platform_data = &fsi2_ak4643_info,
- },
-diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
-index 8c6202b..b63de55 100644
---- a/arch/arm/mach-shmobile/board-mackerel.c
-+++ b/arch/arm/mach-shmobile/board-mackerel.c
-@@ -53,6 +53,7 @@
- #include <media/soc_camera.h>
- #include <media/soc_camera_platform.h>
- #include <sound/sh_fsi.h>
-+#include <sound/simple_card.h>
-
- #include <mach/common.h>
- #include <mach/irqs.h>
-@@ -941,17 +942,25 @@ static struct platform_device fsi_device = {
- },
- };
-
--static struct fsi_ak4642_info fsi2_ak4643_info = {
-+static struct asoc_simple_dai_init_info fsi2_ak4643_init_info = {
-+ .fmt = SND_SOC_DAIFMT_LEFT_J,
-+ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM,
-+ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS,
-+ .sysclk = 11289600,
-+};
-+
-+static struct asoc_simple_card_info fsi2_ak4643_info = {
- .name = "AK4643",
- .card = "FSI2A-AK4643",
- .cpu_dai = "fsia-dai",
- .codec = "ak4642-codec.0-0013",
- .platform = "sh_fsi2",
-- .id = FSI_PORT_A,
-+ .codec_dai = "ak4642-hifi",
-+ .init = &fsi2_ak4643_init_info,
- };
-
- static struct platform_device fsi_ak4643_device = {
-- .name = "fsi-ak4642-audio",
-+ .name = "asoc-simple-card",
- .dev = {
- .platform_data = &fsi2_ak4643_info,
- },
-diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
-index d893411..0da49f3 100644
---- a/arch/sh/boards/Kconfig
-+++ b/arch/sh/boards/Kconfig
-@@ -54,6 +54,7 @@ config SH_7724_SOLUTION_ENGINE
- select SOLUTION_ENGINE
- depends on CPU_SUBTYPE_SH7724
- select ARCH_REQUIRE_GPIOLIB
-+ select SND_SOC_AK4642 if SND_SIMPLE_CARD
- help
- Select 7724 SolutionEngine if configuring for a Hitachi SH7724
- evaluation board.
-diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
-index c540b16..5cc5ed4 100644
---- a/arch/sh/boards/mach-se/7724/setup.c
-+++ b/arch/sh/boards/mach-se/7724/setup.c
-@@ -28,6 +28,7 @@
- #include <video/sh_mobile_lcdc.h>
- #include <media/sh_mobile_ceu.h>
- #include <sound/sh_fsi.h>
-+#include <sound/simple_card.h>
- #include <asm/io.h>
- #include <asm/heartbeat.h>
- #include <asm/clock.h>
-@@ -304,17 +305,25 @@ static struct platform_device fsi_device = {
- },
- };
-
--static struct fsi_ak4642_info fsi_ak4642_info = {
-+static struct asoc_simple_dai_init_info fsi2_ak4642_init_info = {
-+ .fmt = SND_SOC_DAIFMT_LEFT_J,
-+ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM,
-+ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS,
-+ .sysclk = 11289600,
-+};
-+
-+static struct asoc_simple_card_info fsi_ak4642_info = {
- .name = "AK4642",
- .card = "FSIA-AK4642",
- .cpu_dai = "fsia-dai",
- .codec = "ak4642-codec.0-0012",
- .platform = "sh_fsi.0",
-- .id = FSI_PORT_A,
-+ .codec_dai = "ak4642-hifi",
-+ .init = &fsi2_ak4642_init_info,
- };
-
- static struct platform_device fsi_ak4642_device = {
-- .name = "fsi-ak4642-audio",
-+ .name = "asoc-simple-card",
- .dev = {
- .platform_data = &fsi_ak4642_info,
- },
-diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h
-index b457e87..956e30e 100644
---- a/include/sound/sh_fsi.h
-+++ b/include/sound/sh_fsi.h
-@@ -84,16 +84,4 @@ struct sh_fsi_platform_info {
- struct sh_fsi_port_info port_b;
- };
-
--/*
-- * for fsi-ak4642
-- */
--struct fsi_ak4642_info {
-- const char *name;
-- const char *card;
-- const char *cpu_dai;
-- const char *codec;
-- const char *platform;
-- int id;
--};
--
- #endif /* __SOUND_FSI_H */
-diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
-index d8e06a6..c68b90b 100644
---- a/sound/soc/sh/Kconfig
-+++ b/sound/soc/sh/Kconfig
-@@ -46,14 +46,6 @@ config SND_SH7760_AC97
- This option enables generic sound support for the first
- AC97 unit of the SH7760.
-
--config SND_FSI_AK4642
-- tristate "FSI-AK4642 sound support"
-- depends on SND_SOC_SH4_FSI && I2C
-- select SND_SOC_AK4642
-- help
-- This option enables generic sound support for the
-- FSI - AK4642 unit
--
- config SND_FSI_DA7210
- tristate "FSI-DA7210 sound support"
- depends on SND_SOC_SH4_FSI && I2C
-diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
-index 94476d4..01808cd 100644
---- a/sound/soc/sh/Makefile
-+++ b/sound/soc/sh/Makefile
-@@ -14,13 +14,11 @@ obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o
-
- ## boards
- snd-soc-sh7760-ac97-objs := sh7760-ac97.o
--snd-soc-fsi-ak4642-objs := fsi-ak4642.o
- snd-soc-fsi-da7210-objs := fsi-da7210.o
- snd-soc-fsi-hdmi-objs := fsi-hdmi.o
- snd-soc-migor-objs := migor.o
-
- obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o
--obj-$(CONFIG_SND_FSI_AK4642) += snd-soc-fsi-ak4642.o
- obj-$(CONFIG_SND_FSI_DA7210) += snd-soc-fsi-da7210.o
- obj-$(CONFIG_SND_FSI_HDMI) += snd-soc-fsi-hdmi.o
- obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o
-diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
-deleted file mode 100644
-index 97f540a..0000000
---- a/sound/soc/sh/fsi-ak4642.c
-+++ /dev/null
-@@ -1,108 +0,0 @@
--/*
-- * FSI-AK464x sound support for ms7724se
-- *
-- * Copyright (C) 2009 Renesas Solutions Corp.
-- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
-- *
-- * This file is subject to the terms and conditions of the GNU General Public
-- * License. See the file "COPYING" in the main directory of this archive
-- * for more details.
-- */
--
--#include <linux/platform_device.h>
--#include <linux/module.h>
--#include <sound/sh_fsi.h>
--
--struct fsi_ak4642_data {
-- const char *name;
-- const char *card;
-- const char *cpu_dai;
-- const char *codec;
-- const char *platform;
-- int id;
--};
--
--static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd)
--{
-- struct snd_soc_dai *codec = rtd->codec_dai;
-- struct snd_soc_dai *cpu = rtd->cpu_dai;
-- int ret;
--
-- ret = snd_soc_dai_set_fmt(codec, SND_SOC_DAIFMT_LEFT_J |
-- SND_SOC_DAIFMT_CBM_CFM);
-- if (ret < 0)
-- return ret;
--
-- ret = snd_soc_dai_set_sysclk(codec, 0, 11289600, 0);
-- if (ret < 0)
-- return ret;
--
-- ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_LEFT_J |
-- SND_SOC_DAIFMT_CBS_CFS);
--
-- return ret;
--}
--
--static struct snd_soc_dai_link fsi_dai_link = {
-- .codec_dai_name = "ak4642-hifi",
-- .init = fsi_ak4642_dai_init,
--};
--
--static struct snd_soc_card fsi_soc_card = {
-- .owner = THIS_MODULE,
-- .dai_link = &fsi_dai_link,
-- .num_links = 1,
--};
--
--static struct platform_device *fsi_snd_device;
--
--static int fsi_ak4642_probe(struct platform_device *pdev)
--{
-- int ret = -ENOMEM;
-- struct fsi_ak4642_info *pinfo = pdev->dev.platform_data;
--
-- if (!pinfo) {
-- dev_err(&pdev->dev, "no info for fsi ak4642\n");
-- goto out;
-- }
--
-- fsi_snd_device = platform_device_alloc("soc-audio", pinfo->id);
-- if (!fsi_snd_device)
-- goto out;
--
-- fsi_dai_link.name = pinfo->name;
-- fsi_dai_link.stream_name = pinfo->name;
-- fsi_dai_link.cpu_dai_name = pinfo->cpu_dai;
-- fsi_dai_link.platform_name = pinfo->platform;
-- fsi_dai_link.codec_name = pinfo->codec;
-- fsi_soc_card.name = pinfo->card;
--
-- platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
-- ret = platform_device_add(fsi_snd_device);
--
-- if (ret)
-- platform_device_put(fsi_snd_device);
--
--out:
-- return ret;
--}
--
--static int fsi_ak4642_remove(struct platform_device *pdev)
--{
-- platform_device_unregister(fsi_snd_device);
-- return 0;
--}
--
--static struct platform_driver fsi_ak4642 = {
-- .driver = {
-- .name = "fsi-ak4642-audio",
-- },
-- .probe = fsi_ak4642_probe,
-- .remove = fsi_ak4642_remove,
--};
--
--module_platform_driver(fsi_ak4642);
--
--MODULE_LICENSE("GPL");
--MODULE_DESCRIPTION("Generic SH4 FSI-AK4642 sound card");
--MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From bd1e0d9b157b61d6a283ab31f175f6bab4277cfe Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Sun, 8 Apr 2012 21:18:58 -0700
-Subject: ASoC: sh: fsi: use simple-card instead of fsi-hdmi
-
-This patch uses simple-card driver instead of fsi-hdmi on each board.
-This patch removes fsi-hdmi driver which is no longer needed
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit fa063b48046c1f30cb06898559bb34935ade74e1)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-ap4evb.c | 20 +++++-
- arch/arm/mach-shmobile/board-mackerel.c | 20 +++++-
- sound/soc/sh/Kconfig | 7 --
- sound/soc/sh/Makefile | 2 -
- sound/soc/sh/fsi-hdmi.c | 118 --------------------------------
- 5 files changed, 38 insertions(+), 129 deletions(-)
- delete mode 100644 sound/soc/sh/fsi-hdmi.c
-
-diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
-index b397512..8302265 100644
---- a/arch/arm/mach-shmobile/board-ap4evb.c
-+++ b/arch/arm/mach-shmobile/board-ap4evb.c
-@@ -909,8 +909,26 @@ static struct platform_device lcdc1_device = {
- },
- };
-
-+static struct asoc_simple_dai_init_info fsi2_hdmi_init_info = {
-+ .cpu_daifmt = SND_SOC_DAIFMT_CBM_CFM,
-+};
-+
-+static struct asoc_simple_card_info fsi2_hdmi_info = {
-+ .name = "HDMI",
-+ .card = "FSI2B-HDMI",
-+ .cpu_dai = "fsib-dai",
-+ .codec = "sh-mobile-hdmi",
-+ .platform = "sh_fsi2",
-+ .codec_dai = "sh_mobile_hdmi-hifi",
-+ .init = &fsi2_hdmi_init_info,
-+};
-+
- static struct platform_device fsi_hdmi_device = {
-- .name = "sh_fsi2_b_hdmi",
-+ .name = "asoc-simple-card",
-+ .id = 1,
-+ .dev = {
-+ .platform_data = &fsi2_hdmi_info,
-+ },
- };
-
- static struct gpio_led ap4evb_leds[] = {
-diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
-index b63de55..fb27bac 100644
---- a/arch/arm/mach-shmobile/board-mackerel.c
-+++ b/arch/arm/mach-shmobile/board-mackerel.c
-@@ -503,8 +503,26 @@ static struct platform_device hdmi_lcdc_device = {
- },
- };
-
-+static struct asoc_simple_dai_init_info fsi2_hdmi_init_info = {
-+ .cpu_daifmt = SND_SOC_DAIFMT_CBM_CFM,
-+};
-+
-+static struct asoc_simple_card_info fsi2_hdmi_info = {
-+ .name = "HDMI",
-+ .card = "FSI2B-HDMI",
-+ .cpu_dai = "fsib-dai",
-+ .codec = "sh-mobile-hdmi",
-+ .platform = "sh_fsi2",
-+ .codec_dai = "sh_mobile_hdmi-hifi",
-+ .init = &fsi2_hdmi_init_info,
-+};
-+
- static struct platform_device fsi_hdmi_device = {
-- .name = "sh_fsi2_b_hdmi",
-+ .name = "asoc-simple-card",
-+ .id = 1,
-+ .dev = {
-+ .platform_data = &fsi2_hdmi_info,
-+ },
- };
-
- static void __init hdmi_init_pm_clock(void)
-diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
-index c68b90b..9ef49c8 100644
---- a/sound/soc/sh/Kconfig
-+++ b/sound/soc/sh/Kconfig
-@@ -54,13 +54,6 @@ config SND_FSI_DA7210
- This option enables generic sound support for the
- FSI - DA7210 unit
-
--config SND_FSI_HDMI
-- tristate "FSI-HDMI sound support"
-- depends on SND_SOC_SH4_FSI && FB_SH_MOBILE_HDMI
-- help
-- This option enables generic sound support for the
-- FSI - HDMI unit
--
- config SND_SIU_MIGOR
- tristate "SIU sound support on Migo-R"
- depends on SH_MIGOR
-diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
-index 01808cd..f37fc3a 100644
---- a/sound/soc/sh/Makefile
-+++ b/sound/soc/sh/Makefile
-@@ -15,10 +15,8 @@ obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o
- ## boards
- snd-soc-sh7760-ac97-objs := sh7760-ac97.o
- snd-soc-fsi-da7210-objs := fsi-da7210.o
--snd-soc-fsi-hdmi-objs := fsi-hdmi.o
- snd-soc-migor-objs := migor.o
-
- obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o
- obj-$(CONFIG_SND_FSI_DA7210) += snd-soc-fsi-da7210.o
--obj-$(CONFIG_SND_FSI_HDMI) += snd-soc-fsi-hdmi.o
- obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o
-diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c
-deleted file mode 100644
-index 6e41908..0000000
---- a/sound/soc/sh/fsi-hdmi.c
-+++ /dev/null
-@@ -1,118 +0,0 @@
--/*
-- * FSI - HDMI sound support
-- *
-- * Copyright (C) 2010 Renesas Solutions Corp.
-- * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-- *
-- * This file is subject to the terms and conditions of the GNU General Public
-- * License. See the file "COPYING" in the main directory of this archive
-- * for more details.
-- */
--
--#include <linux/platform_device.h>
--#include <linux/module.h>
--#include <sound/sh_fsi.h>
--
--struct fsi_hdmi_data {
-- const char *cpu_dai;
-- const char *card;
-- int id;
--};
--
--static int fsi_hdmi_dai_init(struct snd_soc_pcm_runtime *rtd)
--{
-- struct snd_soc_dai *cpu = rtd->cpu_dai;
-- int ret;
--
-- ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBM_CFM);
--
-- return ret;
--}
--
--static struct snd_soc_dai_link fsi_dai_link = {
-- .name = "HDMI",
-- .stream_name = "HDMI",
-- .codec_dai_name = "sh_mobile_hdmi-hifi",
-- .platform_name = "sh_fsi2",
-- .codec_name = "sh-mobile-hdmi",
-- .init = fsi_hdmi_dai_init,
--};
--
--static struct snd_soc_card fsi_soc_card = {
-- .owner = THIS_MODULE,
-- .dai_link = &fsi_dai_link,
-- .num_links = 1,
--};
--
--static struct platform_device *fsi_snd_device;
--
--static int fsi_hdmi_probe(struct platform_device *pdev)
--{
-- int ret = -ENOMEM;
-- const struct platform_device_id *id_entry;
-- struct fsi_hdmi_data *pdata;
--
-- id_entry = pdev->id_entry;
-- if (!id_entry) {
-- dev_err(&pdev->dev, "unknown fsi hdmi\n");
-- return -ENODEV;
-- }
--
-- pdata = (struct fsi_hdmi_data *)id_entry->driver_data;
--
-- fsi_snd_device = platform_device_alloc("soc-audio", pdata->id);
-- if (!fsi_snd_device)
-- goto out;
--
-- fsi_dai_link.cpu_dai_name = pdata->cpu_dai;
-- fsi_soc_card.name = pdata->card;
--
-- platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
-- ret = platform_device_add(fsi_snd_device);
--
-- if (ret)
-- platform_device_put(fsi_snd_device);
--
--out:
-- return ret;
--}
--
--static int fsi_hdmi_remove(struct platform_device *pdev)
--{
-- platform_device_unregister(fsi_snd_device);
-- return 0;
--}
--
--static struct fsi_hdmi_data fsi2_a_hdmi = {
-- .cpu_dai = "fsia-dai",
-- .card = "FSI2A-HDMI",
-- .id = FSI_PORT_A,
--};
--
--static struct fsi_hdmi_data fsi2_b_hdmi = {
-- .cpu_dai = "fsib-dai",
-- .card = "FSI2B-HDMI",
-- .id = FSI_PORT_B,
--};
--
--static struct platform_device_id fsi_id_table[] = {
-- /* FSI 2 */
-- { "sh_fsi2_a_hdmi", (kernel_ulong_t)&fsi2_a_hdmi },
-- { "sh_fsi2_b_hdmi", (kernel_ulong_t)&fsi2_b_hdmi },
-- {},
--};
--
--static struct platform_driver fsi_hdmi = {
-- .driver = {
-- .name = "fsi-hdmi-audio",
-- },
-- .probe = fsi_hdmi_probe,
-- .remove = fsi_hdmi_remove,
-- .id_table = fsi_id_table,
--};
--
--module_platform_driver(fsi_hdmi);
--
--MODULE_LICENSE("GPL");
--MODULE_DESCRIPTION("Generic SH4 FSI-HDMI sound card");
--MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 0baa4d444616c8bd593aaf36ca25639d66da129a Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Sun, 8 Apr 2012 21:19:25 -0700
-Subject: ASoC: sh: fsi: use simple-card instead of fsi-da7210
-
-This patch uses simple-card driver instead of fsi-da7210 on each board.
-To select DA7210 driver, each boards select it on Kconfig.
-
-This patch removes fsi-da7210 driver which is no longer needed
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit 064bfada66779d95686cacdcbb17551e2c0bf66b)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/sh/boards/Kconfig | 1 +
- arch/sh/boards/mach-ecovec24/setup.c | 26 ++++++++++++
- sound/soc/sh/Kconfig | 8 ----
- sound/soc/sh/Makefile | 2 -
- sound/soc/sh/fsi-da7210.c | 81 ------------------------------------
- 5 files changed, 27 insertions(+), 91 deletions(-)
- delete mode 100644 sound/soc/sh/fsi-da7210.c
-
-diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
-index 0da49f3..c0241bd 100644
---- a/arch/sh/boards/Kconfig
-+++ b/arch/sh/boards/Kconfig
-@@ -224,6 +224,7 @@ config SH_ECOVEC
- bool "EcoVec"
- depends on CPU_SUBTYPE_SH7724
- select ARCH_REQUIRE_GPIOLIB
-+ select SND_SOC_DA7210 if SND_SIMPLE_CARD
- help
- Renesas "R0P7724LC0011/21RL (EcoVec)" support.
-
-diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
-index d12fe9d..299a40a 100644
---- a/arch/sh/boards/mach-ecovec24/setup.c
-+++ b/arch/sh/boards/mach-ecovec24/setup.c
-@@ -32,6 +32,7 @@
- #include <linux/videodev2.h>
- #include <video/sh_mobile_lcdc.h>
- #include <sound/sh_fsi.h>
-+#include <sound/simple_card.h>
- #include <media/sh_mobile_ceu.h>
- #include <media/soc_camera.h>
- #include <media/tw9910.h>
-@@ -809,6 +810,30 @@ static struct platform_device fsi_device = {
- },
- };
-
-+static struct asoc_simple_dai_init_info fsi_da7210_init_info = {
-+ .fmt = SND_SOC_DAIFMT_I2S,
-+ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM,
-+ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS,
-+};
-+
-+static struct asoc_simple_card_info fsi_da7210_info = {
-+ .name = "DA7210",
-+ .card = "FSIB-DA7210",
-+ .cpu_dai = "fsib-dai",
-+ .codec = "da7210.0-001a",
-+ .platform = "sh_fsi.0",
-+ .codec_dai = "da7210-hifi",
-+ .init = &fsi_da7210_init_info,
-+};
-+
-+static struct platform_device fsi_da7210_device = {
-+ .name = "asoc-simple-card",
-+ .dev = {
-+ .platform_data = &fsi_da7210_info,
-+ },
-+};
-+
-+
- /* IrDA */
- static struct resource irda_resources[] = {
- [0] = {
-@@ -945,6 +970,7 @@ static struct platform_device *ecovec_devices[] __initdata = {
- &camera_devices[1],
- &camera_devices[2],
- &fsi_device,
-+ &fsi_da7210_device,
- &irda_device,
- &vou_device,
- #if defined(CONFIG_MMC_SH_MMCIF) || defined(CONFIG_MMC_SH_MMCIF_MODULE)
-diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
-index 9ef49c8..c9fdf63 100644
---- a/sound/soc/sh/Kconfig
-+++ b/sound/soc/sh/Kconfig
-@@ -46,14 +46,6 @@ config SND_SH7760_AC97
- This option enables generic sound support for the first
- AC97 unit of the SH7760.
-
--config SND_FSI_DA7210
-- tristate "FSI-DA7210 sound support"
-- depends on SND_SOC_SH4_FSI && I2C
-- select SND_SOC_DA7210
-- help
-- This option enables generic sound support for the
-- FSI - DA7210 unit
--
- config SND_SIU_MIGOR
- tristate "SIU sound support on Migo-R"
- depends on SH_MIGOR
-diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
-index f37fc3a..849b387 100644
---- a/sound/soc/sh/Makefile
-+++ b/sound/soc/sh/Makefile
-@@ -14,9 +14,7 @@ obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o
-
- ## boards
- snd-soc-sh7760-ac97-objs := sh7760-ac97.o
--snd-soc-fsi-da7210-objs := fsi-da7210.o
- snd-soc-migor-objs := migor.o
-
- obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o
--obj-$(CONFIG_SND_FSI_DA7210) += snd-soc-fsi-da7210.o
- obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o
-diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c
-deleted file mode 100644
-index 1dd3354..0000000
---- a/sound/soc/sh/fsi-da7210.c
-+++ /dev/null
-@@ -1,81 +0,0 @@
--/*
-- * fsi-da7210.c
-- *
-- * Copyright (C) 2009 Renesas Solutions Corp.
-- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
-- *
-- * This program is free software; you can redistribute it and/or modify it
-- * under the terms of the GNU General Public License as published by the
-- * Free Software Foundation; either version 2 of the License, or (at your
-- * option) any later version.
-- */
--
--#include <linux/platform_device.h>
--#include <linux/module.h>
--#include <sound/sh_fsi.h>
--
--static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd)
--{
-- struct snd_soc_dai *codec = rtd->codec_dai;
-- struct snd_soc_dai *cpu = rtd->cpu_dai;
-- int ret;
--
-- ret = snd_soc_dai_set_fmt(codec,
-- SND_SOC_DAIFMT_I2S |
-- SND_SOC_DAIFMT_CBM_CFM);
-- if (ret < 0)
-- return ret;
--
-- ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_I2S |
-- SND_SOC_DAIFMT_CBS_CFS);
--
-- return ret;
--}
--
--static struct snd_soc_dai_link fsi_da7210_dai = {
-- .name = "DA7210",
-- .stream_name = "DA7210",
-- .cpu_dai_name = "fsib-dai", /* FSI B */
-- .codec_dai_name = "da7210-hifi",
-- .platform_name = "sh_fsi.0",
-- .codec_name = "da7210-codec.0-001a",
-- .init = fsi_da7210_init,
--};
--
--static struct snd_soc_card fsi_soc_card = {
-- .name = "FSI-DA7210",
-- .owner = THIS_MODULE,
-- .dai_link = &fsi_da7210_dai,
-- .num_links = 1,
--};
--
--static struct platform_device *fsi_da7210_snd_device;
--
--static int __init fsi_da7210_sound_init(void)
--{
-- int ret;
--
-- fsi_da7210_snd_device = platform_device_alloc("soc-audio", FSI_PORT_B);
-- if (!fsi_da7210_snd_device)
-- return -ENOMEM;
--
-- platform_set_drvdata(fsi_da7210_snd_device, &fsi_soc_card);
-- ret = platform_device_add(fsi_da7210_snd_device);
-- if (ret)
-- platform_device_put(fsi_da7210_snd_device);
--
-- return ret;
--}
--
--static void __exit fsi_da7210_sound_exit(void)
--{
-- platform_device_unregister(fsi_da7210_snd_device);
--}
--
--module_init(fsi_da7210_sound_init);
--module_exit(fsi_da7210_sound_exit);
--
--/* Module information */
--MODULE_DESCRIPTION("ALSA SoC FSI DA2710");
--MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
--MODULE_LICENSE("GPL");
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 09e74410c4effeb137a0aa05425057b740deb997 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Thu, 17 May 2012 17:33:49 -0700
-Subject: ASoC: sh: fsi: use register field macro name on IN/OUT_DMAC
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit 4d62ec125be98f5a446444e4ce53f4f4e2e1baff)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- sound/soc/sh/fsi.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/sound/soc/sh/fsi.c
-+++ b/sound/soc/sh/fsi.c
-@@ -1218,8 +1218,8 @@ static int fsi_hw_startup(struct fsi_pri
- * FSI2 chip can select it.
- */
- if (fsi_ver >= 2) {
-- fsi_reg_write(fsi, OUT_DMAC, (1 << 4));
-- fsi_reg_write(fsi, IN_DMAC, (1 << 4));
-+ fsi_reg_write(fsi, OUT_DMAC, VDMD_BACK);
-+ fsi_reg_write(fsi, IN_DMAC, VDMD_BACK);
- }
-
- /* irq clear */
+++ /dev/null
-From 9bc6d811db2dfc4f27805bc62d39e1bc319653e0 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Thu, 17 May 2012 17:34:16 -0700
-Subject: ASoC: sh: fsi: add fsi_version() and removed meaningless version
- check
-
-This patch adds fsi_version() function for accessing version.
-
-And there were some meaningless version check which never hit.
-This patch removed it.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit 284c6f6547dd08d8f26e12f4014ec298faa7da03)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- sound/soc/sh/fsi.c | 26 ++++++++------------------
- 1 file changed, 8 insertions(+), 18 deletions(-)
-
---- a/sound/soc/sh/fsi.c
-+++ b/sound/soc/sh/fsi.c
-@@ -322,6 +322,10 @@ static void _fsi_master_mask_set(struct
- /*
- * basic function
- */
-+static int fsi_version(struct fsi_master *master)
-+{
-+ return master->core->ver;
-+}
-
- static struct fsi_master *fsi_get_master(struct fsi_priv *fsi)
- {
-@@ -630,11 +634,6 @@ static void fsi_spdif_clk_ctrl(struct fs
- struct fsi_master *master = fsi_get_master(fsi);
- u32 mask, val;
-
-- if (master->core->ver < 2) {
-- pr_err("fsi: register access err (%s)\n", __func__);
-- return;
-- }
--
- mask = BP | SE;
- val = enable ? mask : 0;
-
-@@ -649,9 +648,7 @@ static void fsi_spdif_clk_ctrl(struct fs
- static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
- long rate, int enable)
- {
-- struct fsi_master *master = fsi_get_master(fsi);
- set_rate_func set_rate = fsi_get_info_set_rate(fsi);
-- int fsi_ver = master->core->ver;
- int ret;
-
- if (!set_rate)
-@@ -683,10 +680,7 @@ static int fsi_set_master_clk(struct dev
- data |= (0x3 << 12);
- break;
- case SH_FSI_ACKMD_32:
-- if (fsi_ver < 2)
-- dev_err(dev, "unsupported ACKMD\n");
-- else
-- data |= (0x4 << 12);
-+ data |= (0x4 << 12);
- break;
- }
-
-@@ -709,10 +703,7 @@ static int fsi_set_master_clk(struct dev
- data |= (0x4 << 8);
- break;
- case SH_FSI_BPFMD_16:
-- if (fsi_ver < 2)
-- dev_err(dev, "unsupported ACKMD\n");
-- else
-- data |= (0x7 << 8);
-+ data |= (0x7 << 8);
- break;
- }
-
-@@ -1178,7 +1169,6 @@ static int fsi_hw_startup(struct fsi_pri
- struct device *dev)
- {
- struct fsi_master *master = fsi_get_master(fsi);
-- int fsi_ver = master->core->ver;
- u32 flags = fsi_get_info_flags(fsi);
- u32 data = 0;
-
-@@ -1217,7 +1207,7 @@ static int fsi_hw_startup(struct fsi_pri
- * FSI driver assumed that data package is in-back.
- * FSI2 chip can select it.
- */
-- if (fsi_ver >= 2) {
-+ if (fsi_version(master) >= 2) {
- fsi_reg_write(fsi, OUT_DMAC, VDMD_BACK);
- fsi_reg_write(fsi, IN_DMAC, VDMD_BACK);
- }
-@@ -1307,7 +1297,7 @@ static int fsi_set_fmt_spdif(struct fsi_
- struct fsi_master *master = fsi_get_master(fsi);
- u32 data = 0;
-
-- if (master->core->ver < 2)
-+ if (fsi_version(master) < 2)
- return -EINVAL;
-
- data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
+++ /dev/null
-From e41d8c0d85612475f270a3f0318570d4974f148f Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Thu, 17 May 2012 17:34:53 -0700
-Subject: ASoC: sh: fsi: use same format for IN/OUT
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit 9c59dd342e4dd3c0bab5a9cad1aca7ed9501cbf8)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- sound/soc/sh/fsi.c | 22 ++++++----------------
- 1 file changed, 6 insertions(+), 16 deletions(-)
-
---- a/sound/soc/sh/fsi.c
-+++ b/sound/soc/sh/fsi.c
-@@ -212,8 +212,7 @@ struct fsi_priv {
- struct fsi_stream playback;
- struct fsi_stream capture;
-
-- u32 do_fmt;
-- u32 di_fmt;
-+ u32 fmt;
-
- int chan_num:16;
- int clk_master:1;
-@@ -1192,8 +1191,8 @@ static int fsi_hw_startup(struct fsi_pri
- fsi_reg_write(fsi, CKG2, data);
-
- /* set format */
-- fsi_reg_write(fsi, DO_FMT, fsi->do_fmt);
-- fsi_reg_write(fsi, DI_FMT, fsi->di_fmt);
-+ fsi_reg_write(fsi, DO_FMT, fsi->fmt);
-+ fsi_reg_write(fsi, DI_FMT, fsi->fmt);
-
- /* spdif ? */
- if (fsi_is_spdif(fsi)) {
-@@ -1271,42 +1270,33 @@ static int fsi_dai_trigger(struct snd_pc
-
- static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt)
- {
-- u32 data = 0;
--
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
-- data = CR_I2S;
-+ fsi->fmt = CR_I2S;
- fsi->chan_num = 2;
- break;
- case SND_SOC_DAIFMT_LEFT_J:
-- data = CR_PCM;
-+ fsi->fmt = CR_PCM;
- fsi->chan_num = 2;
- break;
- default:
- return -EINVAL;
- }
-
-- fsi->do_fmt = data;
-- fsi->di_fmt = data;
--
- return 0;
- }
-
- static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
- {
- struct fsi_master *master = fsi_get_master(fsi);
-- u32 data = 0;
-
- if (fsi_version(master) < 2)
- return -EINVAL;
-
-- data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
-+ fsi->fmt = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
- fsi->chan_num = 2;
- fsi->spdif = 1;
-
-- fsi->do_fmt = data;
-- fsi->di_fmt = data;
--
- return 0;
- }
-
+++ /dev/null
-From 30a251b30f73fdfa25d8e260c389bd688951b010 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Thu, 17 May 2012 17:35:34 -0700
-Subject: ASoC: sh: fsi: call fsi_hw_startup/shutdown from fsi_dai_trigger()
-
-fsi_hw_startup/shutdown() needs the setup of bus width,
-but it is impossible to get parameter of snd_pcm_runtime at this timing.
-So, these functions are changed so that be called from fsi_dai_trigger().
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit f33238e96f619d9888713c07dcd92e4518879282)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- sound/soc/sh/fsi.c | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
-
---- a/sound/soc/sh/fsi.c
-+++ b/sound/soc/sh/fsi.c
-@@ -1233,7 +1233,9 @@ static int fsi_dai_startup(struct snd_pc
- {
- struct fsi_priv *fsi = fsi_get_priv(substream);
-
-- return fsi_hw_startup(fsi, fsi_stream_get(fsi, substream), dai->dev);
-+ fsi->rate = 0;
-+
-+ return 0;
- }
-
- static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
-@@ -1241,7 +1243,6 @@ static void fsi_dai_shutdown(struct snd_
- {
- struct fsi_priv *fsi = fsi_get_priv(substream);
-
-- fsi_hw_shutdown(fsi, dai->dev);
- fsi->rate = 0;
- }
-
-@@ -1255,11 +1256,13 @@ static int fsi_dai_trigger(struct snd_pc
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- fsi_stream_init(fsi, io, substream);
-+ fsi_hw_startup(fsi, io, dai->dev);
- ret = fsi_stream_transfer(io);
- if (0 == ret)
- fsi_stream_start(fsi, io);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
-+ fsi_hw_shutdown(fsi, dai->dev);
- fsi_stream_stop(fsi, io);
- fsi_stream_quit(fsi, io);
- break;
+++ /dev/null
-From 603569524ecf479df58238d5c3556bb0882361b1 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Thu, 17 May 2012 17:36:47 -0700
-Subject: ASoC: sh: fsi: enable chip specific data transfer mode
-
-SupherH FSI2 can use special data transfer,
-but it depends on CPU-FSI2 connection style.
-
-We can use 16bit data stream mode if it was valid connection,
-and it is required for 16bit data DMA transfer / SPDIF sound output.
-We can use 24bit data transfer if it was invalid connection.
-
-We can select connection type if CPU is SH7372,
-and it is always valid connection if latest SuperH.
-
-This patch adds new bus_option and fsi_bus_setup()
-for supporting these feature.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit 766812e6d5e2e23be1e212cf84902d5e834dd865)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- include/sound/sh_fsi.h | 6 +
- sound/soc/sh/fsi.c | 177 +++++++++++++++++++++++++++++++++++++++----------
- 2 files changed, 148 insertions(+), 35 deletions(-)
-
---- a/include/sound/sh_fsi.h
-+++ b/include/sound/sh_fsi.h
-@@ -21,10 +21,11 @@
- /*
- * flags format
- *
-- * 0x000000BA
-+ * 0x00000CBA
- *
- * A: inversion
- * B: format mode
-+ * C: chip specific
- */
-
- /* A: clock inversion */
-@@ -39,6 +40,9 @@
- #define SH_FSI_FMT_DAI (0 << 4)
- #define SH_FSI_FMT_SPDIF (1 << 4)
-
-+/* C: chip specific */
-+#define SH_FSI_OPTION_MASK 0x00000F00
-+#define SH_FSI_ENABLE_STREAM_MODE (1 << 8) /* for 16bit data */
-
- /*
- * set_rate return value
---- a/sound/soc/sh/fsi.c
-+++ b/sound/soc/sh/fsi.c
-@@ -133,6 +133,25 @@
- typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
-
- /*
-+ * bus options
-+ *
-+ * 0x000000BA
-+ *
-+ * A : sample widtht 16bit setting
-+ * B : sample widtht 24bit setting
-+ */
-+
-+#define SHIFT_16DATA 0
-+#define SHIFT_24DATA 4
-+
-+#define PACKAGE_24BITBUS_BACK 0
-+#define PACKAGE_24BITBUS_FRONT 1
-+#define PACKAGE_16BITBUS_STREAM 2
-+
-+#define BUSOP_SET(s, a) ((a) << SHIFT_ ## s ## DATA)
-+#define BUSOP_GET(s, a) (((a) >> SHIFT_ ## s ## DATA) & 0xF)
-+
-+/*
- * FSI driver use below type name for variable
- *
- * xxx_num : number of data
-@@ -190,6 +209,11 @@ struct fsi_stream {
- int oerr_num;
-
- /*
-+ * bus options
-+ */
-+ u32 bus_option;
-+
-+ /*
- * thse are initialized by fsi_handler_init()
- */
- struct fsi_stream_handler *handler;
-@@ -499,6 +523,7 @@ static void fsi_stream_init(struct fsi_p
- io->period_samples = fsi_frame2sample(fsi, runtime->period_size);
- io->period_pos = 0;
- io->sample_width = samples_to_bytes(runtime, 1);
-+ io->bus_option = 0;
- io->oerr_num = -1; /* ignore 1st err */
- io->uerr_num = -1; /* ignore 1st err */
- fsi_stream_handler_call(io, init, fsi, io);
-@@ -526,6 +551,7 @@ static void fsi_stream_quit(struct fsi_p
- io->period_samples = 0;
- io->period_pos = 0;
- io->sample_width = 0;
-+ io->bus_option = 0;
- io->oerr_num = 0;
- io->uerr_num = 0;
- spin_unlock_irqrestore(&master->lock, flags);
-@@ -585,6 +611,53 @@ static int fsi_stream_remove(struct fsi_
- }
-
- /*
-+ * format/bus/dma setting
-+ */
-+static void fsi_format_bus_setup(struct fsi_priv *fsi, struct fsi_stream *io,
-+ u32 bus, struct device *dev)
-+{
-+ struct fsi_master *master = fsi_get_master(fsi);
-+ int is_play = fsi_stream_is_play(fsi, io);
-+ u32 fmt = fsi->fmt;
-+
-+ if (fsi_version(master) >= 2) {
-+ u32 dma = 0;
-+
-+ /*
-+ * FSI2 needs DMA/Bus setting
-+ */
-+ switch (bus) {
-+ case PACKAGE_24BITBUS_FRONT:
-+ fmt |= CR_BWS_24;
-+ dma |= VDMD_FRONT;
-+ dev_dbg(dev, "24bit bus / package in front\n");
-+ break;
-+ case PACKAGE_16BITBUS_STREAM:
-+ fmt |= CR_BWS_16;
-+ dma |= VDMD_STREAM;
-+ dev_dbg(dev, "16bit bus / stream mode\n");
-+ break;
-+ case PACKAGE_24BITBUS_BACK:
-+ default:
-+ fmt |= CR_BWS_24;
-+ dma |= VDMD_BACK;
-+ dev_dbg(dev, "24bit bus / package in back\n");
-+ break;
-+ }
-+
-+ if (is_play)
-+ fsi_reg_write(fsi, OUT_DMAC, dma);
-+ else
-+ fsi_reg_write(fsi, IN_DMAC, dma);
-+ }
-+
-+ if (is_play)
-+ fsi_reg_write(fsi, DO_FMT, fmt);
-+ else
-+ fsi_reg_write(fsi, DI_FMT, fmt);
-+}
-+
-+/*
- * irq function
- */
-
-@@ -719,11 +792,26 @@ static int fsi_set_master_clk(struct dev
- */
- static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples)
- {
-- u16 *buf = (u16 *)_buf;
-+ u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
- int i;
-
-- for (i = 0; i < samples; i++)
-- fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8));
-+ if (enable_stream) {
-+ /*
-+ * stream mode
-+ * see
-+ * fsi_pio_push_init()
-+ */
-+ u32 *buf = (u32 *)_buf;
-+
-+ for (i = 0; i < samples / 2; i++)
-+ fsi_reg_write(fsi, DODT, buf[i]);
-+ } else {
-+ /* normal mode */
-+ u16 *buf = (u16 *)_buf;
-+
-+ for (i = 0; i < samples; i++)
-+ fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8));
-+ }
- }
-
- static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples)
-@@ -863,12 +951,44 @@ static void fsi_pio_start_stop(struct fs
- fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
- }
-
-+static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io)
-+{
-+ u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
-+
-+ /*
-+ * we can use 16bit stream mode
-+ * when "playback" and "16bit data"
-+ * and platform allows "stream mode"
-+ * see
-+ * fsi_pio_push16()
-+ */
-+ if (enable_stream)
-+ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
-+ BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
-+ else
-+ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
-+ BUSOP_SET(16, PACKAGE_24BITBUS_BACK);
-+ return 0;
-+}
-+
-+static int fsi_pio_pop_init(struct fsi_priv *fsi, struct fsi_stream *io)
-+{
-+ /*
-+ * always 24bit bus, package back when "capture"
-+ */
-+ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
-+ BUSOP_SET(16, PACKAGE_24BITBUS_BACK);
-+ return 0;
-+}
-+
- static struct fsi_stream_handler fsi_pio_push_handler = {
-+ .init = fsi_pio_push_init,
- .transfer = fsi_pio_push,
- .start_stop = fsi_pio_start_stop,
- };
-
- static struct fsi_stream_handler fsi_pio_pop_handler = {
-+ .init = fsi_pio_pop_init,
- .transfer = fsi_pio_pop,
- .start_stop = fsi_pio_start_stop,
- };
-@@ -910,6 +1030,13 @@ static int fsi_dma_init(struct fsi_priv
- enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE;
-
-+ /*
-+ * 24bit data : 24bit bus / package in back
-+ * 16bit data : 16bit bus / stream mode
-+ */
-+ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
-+ BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
-+
- io->dma = dma_map_single(dai->dev, runtime->dma_area,
- snd_pcm_lib_buffer_bytes(io->substream), dir);
- return 0;
-@@ -1046,25 +1173,9 @@ static int fsi_dma_transfer(struct fsi_p
- static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
- int start)
- {
-- u32 bws;
-- u32 dma;
-+ u32 enable = start ? DMA_ON : 0;
-
-- switch (io->sample_width * start) {
-- case 2:
-- bws = CR_BWS_16;
-- dma = VDMD_STREAM | DMA_ON;
-- break;
-- case 4:
-- bws = CR_BWS_24;
-- dma = VDMD_BACK | DMA_ON;
-- break;
-- default:
-- bws = 0;
-- dma = 0;
-- }
--
-- fsi_reg_mask_set(fsi, DO_FMT, CR_BWS_MASK, bws);
-- fsi_reg_write(fsi, OUT_DMAC, dma);
-+ fsi_reg_mask_set(fsi, OUT_DMAC, DMA_ON, enable);
- }
-
- static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
-@@ -1167,7 +1278,6 @@ static int fsi_hw_startup(struct fsi_pri
- struct fsi_stream *io,
- struct device *dev)
- {
-- struct fsi_master *master = fsi_get_master(fsi);
- u32 flags = fsi_get_info_flags(fsi);
- u32 data = 0;
-
-@@ -1190,10 +1300,6 @@ static int fsi_hw_startup(struct fsi_pri
-
- fsi_reg_write(fsi, CKG2, data);
-
-- /* set format */
-- fsi_reg_write(fsi, DO_FMT, fsi->fmt);
-- fsi_reg_write(fsi, DI_FMT, fsi->fmt);
--
- /* spdif ? */
- if (fsi_is_spdif(fsi)) {
- fsi_spdif_clk_ctrl(fsi, 1);
-@@ -1201,15 +1307,18 @@ static int fsi_hw_startup(struct fsi_pri
- }
-
- /*
-- * FIXME
-- *
-- * FSI driver assumed that data package is in-back.
-- * FSI2 chip can select it.
-+ * get bus settings
- */
-- if (fsi_version(master) >= 2) {
-- fsi_reg_write(fsi, OUT_DMAC, VDMD_BACK);
-- fsi_reg_write(fsi, IN_DMAC, VDMD_BACK);
-+ data = 0;
-+ switch (io->sample_width) {
-+ case 2:
-+ data = BUSOP_GET(16, io->bus_option);
-+ break;
-+ case 4:
-+ data = BUSOP_GET(24, io->bus_option);
-+ break;
- }
-+ fsi_format_bus_setup(fsi, io, data, dev);
-
- /* irq clear */
- fsi_irq_disable(fsi, io);
-@@ -1296,7 +1405,7 @@ static int fsi_set_fmt_spdif(struct fsi_
- if (fsi_version(master) < 2)
- return -EINVAL;
-
-- fsi->fmt = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
-+ fsi->fmt = CR_DTMD_SPDIF_PCM | CR_PCM;
- fsi->chan_num = 2;
- fsi->spdif = 1;
-
+++ /dev/null
-From 8dedb2aa24856018132764d9c3411c7600087b3e Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Thu, 24 May 2012 23:55:11 -0700
-Subject: ASoC: fsi: bugfix: enable master clock control on DMA stream
-
-DMA stream handler didn't care about master clock.
-This patch fixes it up.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit e42bb9bfbb43366cd1899c9564d043c41ebd8852)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- sound/soc/sh/fsi.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/sound/soc/sh/fsi.c
-+++ b/sound/soc/sh/fsi.c
-@@ -1173,9 +1173,14 @@ static int fsi_dma_transfer(struct fsi_p
- static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
- int start)
- {
-+ struct fsi_master *master = fsi_get_master(fsi);
-+ u32 clk = fsi_is_port_a(fsi) ? CRA : CRB;
- u32 enable = start ? DMA_ON : 0;
-
- fsi_reg_mask_set(fsi, OUT_DMAC, DMA_ON, enable);
-+
-+ if (fsi_is_clk_master(fsi))
-+ fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
- }
-
- static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
+++ /dev/null
-From ce1ff80d007ef6f5c64c65fd0d44b587657ae0c6 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 28 May 2012 23:27:49 -0700
-Subject: ASoC: fsi: bugfix: correct dma area
-
-FSI driver is using dma_sync_single_xxx(),
-but the dma area was not correct.
-This patch fix it up.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit 4a1b09b79b07cf70c72a091e8fe0660f68541f30)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- sound/soc/sh/fsi.c | 18 +++++++++---------
- 1 file changed, 9 insertions(+), 9 deletions(-)
-
---- a/sound/soc/sh/fsi.c
-+++ b/sound/soc/sh/fsi.c
-@@ -1053,6 +1053,13 @@ static int fsi_dma_quit(struct fsi_priv
- return 0;
- }
-
-+static dma_addr_t fsi_dma_get_area(struct fsi_stream *io)
-+{
-+ struct snd_pcm_runtime *runtime = io->substream->runtime;
-+
-+ return io->dma + samples_to_bytes(runtime, io->buff_sample_pos);
-+}
-+
- static void fsi_dma_complete(void *data)
- {
- struct fsi_stream *io = (struct fsi_stream *)data;
-@@ -1062,7 +1069,7 @@ static void fsi_dma_complete(void *data)
- enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE;
-
-- dma_sync_single_for_cpu(dai->dev, io->dma,
-+ dma_sync_single_for_cpu(dai->dev, fsi_dma_get_area(io),
- samples_to_bytes(runtime, io->period_samples), dir);
-
- io->buff_sample_pos += io->period_samples;
-@@ -1079,13 +1086,6 @@ static void fsi_dma_complete(void *data)
- snd_pcm_period_elapsed(io->substream);
- }
-
--static dma_addr_t fsi_dma_get_area(struct fsi_stream *io)
--{
-- struct snd_pcm_runtime *runtime = io->substream->runtime;
--
-- return io->dma + samples_to_bytes(runtime, io->buff_sample_pos);
--}
--
- static void fsi_dma_do_work(struct work_struct *work)
- {
- struct fsi_stream *io = container_of(work, struct fsi_stream, work);
-@@ -1111,7 +1111,7 @@ static void fsi_dma_do_work(struct work_
- len = samples_to_bytes(runtime, io->period_samples);
- buf = fsi_dma_get_area(io);
-
-- dma_sync_single_for_device(dai->dev, io->dma, len, dir);
-+ dma_sync_single_for_device(dai->dev, buf, len, dir);
-
- sg_init_table(&sg, 1);
- sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)),
+++ /dev/null
-From d94ab970e6055b3e6f7cab54a405431e47445ae4 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 28 May 2012 23:28:22 -0700
-Subject: ASoC: fsi: bugfix: ensure dma is terminated
-
-FSI DMAEngine has to be stopped certainly at the start/stop time.
-Without this patch, it will include noise on playback.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit fbe42f66c66c279b4ed9b8f515058a09bc731c49)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- sound/soc/sh/fsi.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/sound/soc/sh/fsi.c
-+++ b/sound/soc/sh/fsi.c
-@@ -1179,6 +1179,8 @@ static void fsi_dma_push_start_stop(stru
-
- fsi_reg_mask_set(fsi, OUT_DMAC, DMA_ON, enable);
-
-+ dmaengine_terminate_all(io->chan);
-+
- if (fsi_is_clk_master(fsi))
- fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
- }
+++ /dev/null
-From 341b5a7a28c7b1404b9875366b2b2c1dabd06ee8 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 28 May 2012 23:29:36 -0700
-Subject: ASoC: fsi: use dmaengine helper functions
-
-This patch used dmaengine helper functions instead of using hand setting.
-And reduced local variables
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit 5514efdfe0384576ef38c66b1672b6826696fbf3)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- sound/soc/sh/fsi.c | 19 ++++---------------
- 1 file changed, 4 insertions(+), 15 deletions(-)
-
---- a/sound/soc/sh/fsi.c
-+++ b/sound/soc/sh/fsi.c
-@@ -1090,13 +1090,10 @@ static void fsi_dma_do_work(struct work_
- {
- struct fsi_stream *io = container_of(work, struct fsi_stream, work);
- struct fsi_priv *fsi = fsi_stream_to_priv(io);
-- struct dma_chan *chan;
- struct snd_soc_dai *dai;
- struct dma_async_tx_descriptor *desc;
-- struct scatterlist sg;
- struct snd_pcm_runtime *runtime;
- enum dma_data_direction dir;
-- dma_cookie_t cookie;
- int is_play = fsi_stream_is_play(fsi, io);
- int len;
- dma_addr_t buf;
-@@ -1105,7 +1102,6 @@ static void fsi_dma_do_work(struct work_
- return;
-
- dai = fsi_get_dai(io->substream);
-- chan = io->chan;
- runtime = io->substream->runtime;
- dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
- len = samples_to_bytes(runtime, io->period_samples);
-@@ -1113,14 +1109,8 @@ static void fsi_dma_do_work(struct work_
-
- dma_sync_single_for_device(dai->dev, buf, len, dir);
-
-- sg_init_table(&sg, 1);
-- sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)),
-- len , offset_in_page(buf));
-- sg_dma_address(&sg) = buf;
-- sg_dma_len(&sg) = len;
--
-- desc = dmaengine_prep_slave_sg(chan, &sg, 1, dir,
-- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-+ desc = dmaengine_prep_slave_single(io->chan, buf, len, dir,
-+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc) {
- dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n");
- return;
-@@ -1129,13 +1119,12 @@ static void fsi_dma_do_work(struct work_
- desc->callback = fsi_dma_complete;
- desc->callback_param = io;
-
-- cookie = desc->tx_submit(desc);
-- if (cookie < 0) {
-+ if (dmaengine_submit(desc) < 0) {
- dev_err(dai->dev, "tx_submit() fail\n");
- return;
- }
-
-- dma_async_issue_pending(chan);
-+ dma_async_issue_pending(io->chan);
-
- /*
- * FIXME
+++ /dev/null
-From 2c50008416a53374914d047b290c1f28842ce4b3 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Thu, 24 May 2012 23:56:19 -0700
-Subject: ASoC: fsi: use PIO handler if DMA handler was invalid
-
-PIO handler is not good performance, but works on all platform.
-So, switch to PIO handler if DMA handler was invalid case.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit b1226dc59d55ecde7fc9a338d8cb2a313821fac0)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- sound/soc/sh/fsi.c | 29 ++++++++++++++++++++---------
- 1 file changed, 20 insertions(+), 9 deletions(-)
-
---- a/sound/soc/sh/fsi.c
-+++ b/sound/soc/sh/fsi.c
-@@ -248,7 +248,7 @@ struct fsi_priv {
- struct fsi_stream_handler {
- int (*init)(struct fsi_priv *fsi, struct fsi_stream *io);
- int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io);
-- int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io);
-+ int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev);
- int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io);
- int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io);
- void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io,
-@@ -572,16 +572,16 @@ static int fsi_stream_transfer(struct fs
- #define fsi_stream_stop(fsi, io)\
- fsi_stream_handler_call(io, start_stop, fsi, io, 0)
-
--static int fsi_stream_probe(struct fsi_priv *fsi)
-+static int fsi_stream_probe(struct fsi_priv *fsi, struct device *dev)
- {
- struct fsi_stream *io;
- int ret1, ret2;
-
- io = &fsi->playback;
-- ret1 = fsi_stream_handler_call(io, probe, fsi, io);
-+ ret1 = fsi_stream_handler_call(io, probe, fsi, io, dev);
-
- io = &fsi->capture;
-- ret2 = fsi_stream_handler_call(io, probe, fsi, io);
-+ ret2 = fsi_stream_handler_call(io, probe, fsi, io, dev);
-
- if (ret1 < 0)
- return ret1;
-@@ -1174,7 +1174,7 @@ static void fsi_dma_push_start_stop(stru
- fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
- }
-
--static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
-+static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev)
- {
- dma_cap_mask_t mask;
-
-@@ -1182,8 +1182,19 @@ static int fsi_dma_probe(struct fsi_priv
- dma_cap_set(DMA_SLAVE, mask);
-
- io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave);
-- if (!io->chan)
-- return -EIO;
-+ if (!io->chan) {
-+
-+ /* switch to PIO handler */
-+ if (fsi_stream_is_play(fsi, io))
-+ fsi->playback.handler = &fsi_pio_push_handler;
-+ else
-+ fsi->capture.handler = &fsi_pio_pop_handler;
-+
-+ dev_info(dev, "switch handler (dma => pio)\n");
-+
-+ /* probe again */
-+ return fsi_stream_probe(fsi, dev);
-+ }
-
- INIT_WORK(&io->work, fsi_dma_do_work);
-
-@@ -1673,7 +1684,7 @@ static int fsi_probe(struct platform_dev
- master->fsia.master = master;
- master->fsia.info = &info->port_a;
- fsi_handler_init(&master->fsia);
-- ret = fsi_stream_probe(&master->fsia);
-+ ret = fsi_stream_probe(&master->fsia, &pdev->dev);
- if (ret < 0) {
- dev_err(&pdev->dev, "FSIA stream probe failed\n");
- goto exit_iounmap;
-@@ -1684,7 +1695,7 @@ static int fsi_probe(struct platform_dev
- master->fsib.master = master;
- master->fsib.info = &info->port_b;
- fsi_handler_init(&master->fsib);
-- ret = fsi_stream_probe(&master->fsib);
-+ ret = fsi_stream_probe(&master->fsib, &pdev->dev);
- if (ret < 0) {
- dev_err(&pdev->dev, "FSIB stream probe failed\n");
- goto exit_fsia;
+++ /dev/null
-From 223018081111b56755835850e5dbc7a122f5f1b5 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 9 May 2012 17:09:20 +0200
-Subject: ASoC: fsi: prepare for conversion to the shdma base library
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Cc: Liam Girdwood <lrg@ti.com>
-Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
-Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit b8373147ed3ca01a968d81f22688f2836a9aeb6b)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- sound/soc/sh/fsi.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
-index 53486ff..0540408 100644
---- a/sound/soc/sh/fsi.c
-+++ b/sound/soc/sh/fsi.c
-@@ -1631,8 +1631,8 @@ static void fsi_handler_init(struct fsi_priv *fsi)
- fsi->capture.priv = fsi;
-
- if (fsi->info->tx_id) {
-- fsi->playback.slave.slave_id = fsi->info->tx_id;
-- fsi->playback.handler = &fsi_dma_push_handler;
-+ fsi->playback.slave.shdma_slave.slave_id = fsi->info->tx_id;
-+ fsi->playback.handler = &fsi_dma_push_handler;
- }
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 575ef93e0d64ff352f0bafc5038468b13796104b Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 7 May 2012 21:06:54 -0700
-Subject: fbdev: sh_mobile_hdmi: add hdmi_bit_set() function
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
-(cherry picked from commit 3f521abd6cf1320d65a49cf9fc327b82168b5ba0)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_hdmi.c | 22 ++++++++++++++++------
- 1 file changed, 16 insertions(+), 6 deletions(-)
-
-diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
-index eafb19d..e201d6f 100644
---- a/drivers/video/sh_mobile_hdmi.c
-+++ b/drivers/video/sh_mobile_hdmi.c
-@@ -236,6 +236,16 @@ static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
- return ioread8(hdmi->base + reg);
- }
-
-+static void hdmi_bit_set(struct sh_hdmi *hdmi, u8 mask, u8 data, u8 reg)
-+{
-+ u8 val = hdmi_read(hdmi, reg);
-+
-+ val &= ~mask;
-+ val |= (data & mask);
-+
-+ hdmi_write(hdmi, val, reg);
-+}
-+
- /*
- * HDMI sound
- */
-@@ -693,11 +703,11 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
- msleep(10);
-
- /* PS mode b->d, reset PLLA and PLLB */
-- hdmi_write(hdmi, 0x4C, HDMI_SYSTEM_CTRL);
-+ hdmi_bit_set(hdmi, 0xFC, 0x4C, HDMI_SYSTEM_CTRL);
-
- udelay(10);
-
-- hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL);
-+ hdmi_bit_set(hdmi, 0xFC, 0x40, HDMI_SYSTEM_CTRL);
- }
-
- static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
-@@ -917,13 +927,13 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
- u8 status1, status2, mask1, mask2;
-
- /* mode_b and PLLA and PLLB reset */
-- hdmi_write(hdmi, 0x2C, HDMI_SYSTEM_CTRL);
-+ hdmi_bit_set(hdmi, 0xFC, 0x2C, HDMI_SYSTEM_CTRL);
-
- /* How long shall reset be held? */
- udelay(10);
-
- /* mode_b and PLLA and PLLB reset release */
-- hdmi_write(hdmi, 0x20, HDMI_SYSTEM_CTRL);
-+ hdmi_bit_set(hdmi, 0xFC, 0x20, HDMI_SYSTEM_CTRL);
-
- status1 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_1);
- status2 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_2);
-@@ -1001,7 +1011,7 @@ static int sh_hdmi_display_on(struct sh_mobile_lcdc_entity *entity)
- */
- if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
- /* PS mode d->e. All functions are active */
-- hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL);
-+ hdmi_bit_set(hdmi, 0xFC, 0x80, HDMI_SYSTEM_CTRL);
- dev_dbg(hdmi->dev, "HDMI running\n");
- }
-
-@@ -1016,7 +1026,7 @@ static void sh_hdmi_display_off(struct sh_mobile_lcdc_entity *entity)
-
- dev_dbg(hdmi->dev, "%s(%p)\n", __func__, hdmi);
- /* PS mode e->a */
-- hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL);
-+ hdmi_bit_set(hdmi, 0xFC, 0x10, HDMI_SYSTEM_CTRL);
- }
-
- static const struct sh_mobile_lcdc_entity_ops sh_hdmi_ops = {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 1f09b960ec16950e3791ba297de136bedc56be51 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 7 May 2012 21:07:20 -0700
-Subject: fbdev: sh_mobile_hdmi: add interrupt output option
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
-(cherry picked from commit e0defc86423d1b5652826c9317c36dfb6af1cd48)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_hdmi.c | 7 +++++++
- include/video/sh_mobile_hdmi.h | 8 +++++++-
- 2 files changed, 14 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
-index e201d6f..0bc39bc 100644
---- a/drivers/video/sh_mobile_hdmi.c
-+++ b/drivers/video/sh_mobile_hdmi.c
-@@ -1186,6 +1186,13 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
- pm_runtime_enable(&pdev->dev);
- pm_runtime_get_sync(&pdev->dev);
-
-+ /* init interrupt polarity */
-+ if (pdata->flags & HDMI_OUTPUT_PUSH_PULL)
-+ hdmi_bit_set(hdmi, 0x02, 0x02, HDMI_SYSTEM_CTRL);
-+
-+ if (pdata->flags & HDMI_OUTPUT_POLARITY_HI)
-+ hdmi_bit_set(hdmi, 0x01, 0x01, HDMI_SYSTEM_CTRL);
-+
- /* Product and revision IDs are 0 in sh-mobile version */
- dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
- hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
-diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h
-index 728f9de..2699635 100644
---- a/include/video/sh_mobile_hdmi.h
-+++ b/include/video/sh_mobile_hdmi.h
-@@ -18,9 +18,10 @@ struct clk;
- /*
- * flags format
- *
-- * 0x0000000A
-+ * 0x000000BA
- *
- * A: Audio source select
-+ * B: Int output option
- */
-
- /* Audio source select */
-@@ -30,6 +31,11 @@ struct clk;
- #define HDMI_SND_SRC_DSD (2 << 0)
- #define HDMI_SND_SRC_HBR (3 << 0)
-
-+/* Int output option */
-+#define HDMI_OUTPUT_PUSH_PULL (1 << 4) /* System control : output mode */
-+#define HDMI_OUTPUT_POLARITY_HI (1 << 5) /* System control : output polarity */
-+
-+
- struct sh_mobile_hdmi_info {
- unsigned int flags;
- long (*clk_optimize_parent)(unsigned long target, unsigned long *best_freq,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 6fb22732c461a0efc337cc6cd03fda18e0b2d1cf Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 7 May 2012 21:07:49 -0700
-Subject: fbdev: sh_mobile_hdmi: 32bit register access support
-
-Latest SuperH HDMI allows 32bit access only.
-But the data is 8bit. So, we can keep compatibility by switching 8/32 bit access.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
-(cherry picked from commit db6668d83a265a15ffd79dbc8432598808b34bb4)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_hdmi.c | 38 ++++++++++++++++++++++++++++++++++++--
- include/video/sh_mobile_hdmi.h | 5 ++++-
- 2 files changed, 40 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
-index 0bc39bc..4d48a80 100644
---- a/drivers/video/sh_mobile_hdmi.c
-+++ b/drivers/video/sh_mobile_hdmi.c
-@@ -222,20 +222,45 @@ struct sh_hdmi {
- struct delayed_work edid_work;
- struct fb_videomode mode;
- struct fb_monspecs monspec;
-+
-+ /* register access functions */
-+ void (*write)(struct sh_hdmi *hdmi, u8 data, u8 reg);
-+ u8 (*read)(struct sh_hdmi *hdmi, u8 reg);
- };
-
- #define entity_to_sh_hdmi(e) container_of(e, struct sh_hdmi, entity)
-
--static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
-+static void __hdmi_write8(struct sh_hdmi *hdmi, u8 data, u8 reg)
- {
- iowrite8(data, hdmi->base + reg);
- }
-
--static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
-+static u8 __hdmi_read8(struct sh_hdmi *hdmi, u8 reg)
- {
- return ioread8(hdmi->base + reg);
- }
-
-+static void __hdmi_write32(struct sh_hdmi *hdmi, u8 data, u8 reg)
-+{
-+ iowrite32((u32)data, hdmi->base + (reg * 4));
-+ udelay(100);
-+}
-+
-+static u8 __hdmi_read32(struct sh_hdmi *hdmi, u8 reg)
-+{
-+ return (u8)ioread32(hdmi->base + (reg * 4));
-+}
-+
-+static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
-+{
-+ hdmi->write(hdmi, data, reg);
-+}
-+
-+static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
-+{
-+ return hdmi->read(hdmi, reg);
-+}
-+
- static void hdmi_bit_set(struct sh_hdmi *hdmi, u8 mask, u8 data, u8 reg)
- {
- u8 val = hdmi_read(hdmi, reg);
-@@ -1148,6 +1173,15 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
- goto egetclk;
- }
-
-+ /* select register access functions */
-+ if (pdata->flags & HDMI_32BIT_REG) {
-+ hdmi->write = __hdmi_write32;
-+ hdmi->read = __hdmi_read32;
-+ } else {
-+ hdmi->write = __hdmi_write8;
-+ hdmi->read = __hdmi_read8;
-+ }
-+
- /* An arbitrary relaxed pixclock just to get things started: from standard 480p */
- rate = clk_round_rate(hdmi->hdmi_clk, PICOS2KHZ(37037));
- if (rate > 0)
-diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h
-index 2699635..ce8a540 100644
---- a/include/video/sh_mobile_hdmi.h
-+++ b/include/video/sh_mobile_hdmi.h
-@@ -18,10 +18,11 @@ struct clk;
- /*
- * flags format
- *
-- * 0x000000BA
-+ * 0x00000CBA
- *
- * A: Audio source select
- * B: Int output option
-+ * C: Chip specific option
- */
-
- /* Audio source select */
-@@ -35,6 +36,8 @@ struct clk;
- #define HDMI_OUTPUT_PUSH_PULL (1 << 4) /* System control : output mode */
- #define HDMI_OUTPUT_POLARITY_HI (1 << 5) /* System control : output polarity */
-
-+/* Chip specific option */
-+#define HDMI_32BIT_REG (1 << 8)
-
- struct sh_mobile_hdmi_info {
- unsigned int flags;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ccd4120f4b46b4f6c043108aa6f5bbb8f63f959e Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 7 May 2012 21:08:17 -0700
-Subject: fbdev: sh_mobile_hdmi: add HDMI Control Register support
-
-Latest SuperH HDMI uses not only HDMI Core Register (HTOP0)
-but also HDMI Control Register (HTOP1).
-This patch adds HDMI Control Register support.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
-(cherry picked from commit c932b2731116f99a660817e8fa718c9da0798a9c)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_hdmi.c | 152 ++++++++++++++++++++++++++++++++++++++++-
- include/video/sh_mobile_hdmi.h | 1 +
- 2 files changed, 152 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
-index 4d48a80..930e550 100644
---- a/drivers/video/sh_mobile_hdmi.c
-+++ b/drivers/video/sh_mobile_hdmi.c
-@@ -31,6 +31,7 @@
-
- #include "sh_mobile_lcdcfb.h"
-
-+/* HDMI Core Control Register (HTOP0) */
- #define HDMI_SYSTEM_CTRL 0x00 /* System control */
- #define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control,
- bits 19..16 of 20-bit N for Audio Clock Regeneration packet */
-@@ -201,6 +202,68 @@
- #define HDMI_REVISION_ID 0xF1 /* Revision ID */
- #define HDMI_TEST_MODE 0xFE /* Test mode */
-
-+/* HDMI Control Register (HTOP1) */
-+#define HDMI_HTOP1_TEST_MODE 0x0000 /* Test mode */
-+#define HDMI_HTOP1_VIDEO_INPUT 0x0008 /* VideoInput */
-+#define HDMI_HTOP1_CORE_RSTN 0x000C /* CoreResetn */
-+#define HDMI_HTOP1_PLLBW 0x0018 /* PLLBW */
-+#define HDMI_HTOP1_CLK_TO_PHY 0x001C /* Clk to Phy */
-+#define HDMI_HTOP1_VIDEO_INPUT2 0x0020 /* VideoInput2 */
-+#define HDMI_HTOP1_TISEMP0_1 0x0024 /* tisemp0-1 */
-+#define HDMI_HTOP1_TISEMP2_C 0x0028 /* tisemp2-c */
-+#define HDMI_HTOP1_TISIDRV 0x002C /* tisidrv */
-+#define HDMI_HTOP1_TISEN 0x0034 /* tisen */
-+#define HDMI_HTOP1_TISDREN 0x0038 /* tisdren */
-+#define HDMI_HTOP1_CISRANGE 0x003C /* cisrange */
-+#define HDMI_HTOP1_ENABLE_SELECTOR 0x0040 /* Enable Selector */
-+#define HDMI_HTOP1_MACRO_RESET 0x0044 /* Macro reset */
-+#define HDMI_HTOP1_PLL_CALIBRATION 0x0048 /* PLL calibration */
-+#define HDMI_HTOP1_RE_CALIBRATION 0x004C /* Re-calibration */
-+#define HDMI_HTOP1_CURRENT 0x0050 /* Current */
-+#define HDMI_HTOP1_PLL_LOCK_DETECT 0x0054 /* PLL lock detect */
-+#define HDMI_HTOP1_PHY_TEST_MODE 0x0058 /* PHY Test Mode */
-+#define HDMI_HTOP1_CLK_SET 0x0080 /* Clock Set */
-+#define HDMI_HTOP1_DDC_FAIL_SAFE 0x0084 /* DDC fail safe */
-+#define HDMI_HTOP1_PRBS 0x0088 /* PRBS */
-+#define HDMI_HTOP1_EDID_AINC_CONTROL 0x008C /* EDID ainc Control */
-+#define HDMI_HTOP1_HTOP_DCL_MODE 0x00FC /* Deep Coloer Mode */
-+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF0 0x0100 /* Deep Color:FRC COEF0 */
-+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF1 0x0104 /* Deep Color:FRC COEF1 */
-+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF2 0x0108 /* Deep Color:FRC COEF2 */
-+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF3 0x010C /* Deep Color:FRC COEF3 */
-+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF0_C 0x0110 /* Deep Color:FRC COEF0C */
-+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF1_C 0x0114 /* Deep Color:FRC COEF1C */
-+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF2_C 0x0118 /* Deep Color:FRC COEF2C */
-+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF3_C 0x011C /* Deep Color:FRC COEF3C */
-+#define HDMI_HTOP1_HTOP_DCL_FRC_MODE 0x0120 /* Deep Color:FRC Mode */
-+#define HDMI_HTOP1_HTOP_DCL_RECT_START1 0x0124 /* Deep Color:Rect Start1 */
-+#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE1 0x0128 /* Deep Color:Rect Size1 */
-+#define HDMI_HTOP1_HTOP_DCL_RECT_START2 0x012C /* Deep Color:Rect Start2 */
-+#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE2 0x0130 /* Deep Color:Rect Size2 */
-+#define HDMI_HTOP1_HTOP_DCL_RECT_START3 0x0134 /* Deep Color:Rect Start3 */
-+#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE3 0x0138 /* Deep Color:Rect Size3 */
-+#define HDMI_HTOP1_HTOP_DCL_RECT_START4 0x013C /* Deep Color:Rect Start4 */
-+#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE4 0x0140 /* Deep Color:Rect Size4 */
-+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1 0x0144 /* Deep Color:Fil Para Y1_1 */
-+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2 0x0148 /* Deep Color:Fil Para Y1_2 */
-+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1 0x014C /* Deep Color:Fil Para CB1_1 */
-+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2 0x0150 /* Deep Color:Fil Para CB1_2 */
-+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1 0x0154 /* Deep Color:Fil Para CR1_1 */
-+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2 0x0158 /* Deep Color:Fil Para CR1_2 */
-+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1 0x015C /* Deep Color:Fil Para Y2_1 */
-+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2 0x0160 /* Deep Color:Fil Para Y2_2 */
-+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1 0x0164 /* Deep Color:Fil Para CB2_1 */
-+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2 0x0168 /* Deep Color:Fil Para CB2_2 */
-+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1 0x016C /* Deep Color:Fil Para CR2_1 */
-+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2 0x0170 /* Deep Color:Fil Para CR2_2 */
-+#define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1 0x0174 /* Deep Color:Cor Para Y1 */
-+#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1 0x0178 /* Deep Color:Cor Para CB1 */
-+#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1 0x017C /* Deep Color:Cor Para CR1 */
-+#define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2 0x0180 /* Deep Color:Cor Para Y2 */
-+#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2 0x0184 /* Deep Color:Cor Para CB2 */
-+#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2 0x0188 /* Deep Color:Cor Para CR2 */
-+#define HDMI_HTOP1_EDID_DATA_READ 0x0200 /* EDID Data Read 128Byte:0x03FC */
-+
- enum hotplug_state {
- HDMI_HOTPLUG_DISCONNECTED,
- HDMI_HOTPLUG_CONNECTED,
-@@ -211,6 +274,7 @@ struct sh_hdmi {
- struct sh_mobile_lcdc_entity entity;
-
- void __iomem *base;
-+ void __iomem *htop1;
- enum hotplug_state hp_state; /* hot-plug status */
- u8 preprogrammed_vic; /* use a pre-programmed VIC or
- the external mode */
-@@ -271,6 +335,17 @@ static void hdmi_bit_set(struct sh_hdmi *hdmi, u8 mask, u8 data, u8 reg)
- hdmi_write(hdmi, val, reg);
- }
-
-+static void hdmi_htop1_write(struct sh_hdmi *hdmi, u32 data, u32 reg)
-+{
-+ iowrite32(data, hdmi->htop1 + reg);
-+ udelay(100);
-+}
-+
-+static u32 hdmi_htop1_read(struct sh_hdmi *hdmi, u32 reg)
-+{
-+ return ioread32(hdmi->htop1 + reg);
-+}
-+
- /*
- * HDMI sound
- */
-@@ -781,7 +856,9 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
- /* Read EDID */
- dev_dbg(hdmi->dev, "Read back EDID code:");
- for (i = 0; i < 128; i++) {
-- edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
-+ edid[i] = (hdmi->htop1) ?
-+ (u8)hdmi_htop1_read(hdmi, HDMI_HTOP1_EDID_DATA_READ + (i * 4)) :
-+ hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
- #ifdef DEBUG
- if ((i % 16) == 0) {
- printk(KERN_CONT "\n");
-@@ -1145,10 +1222,58 @@ out:
- dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, hdmi);
- }
-
-+static void sh_hdmi_htop1_init(struct sh_hdmi *hdmi)
-+{
-+ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_MODE);
-+ hdmi_htop1_write(hdmi, 0x0000000b, 0x0010);
-+ hdmi_htop1_write(hdmi, 0x00006710, HDMI_HTOP1_HTOP_DCL_FRC_MODE);
-+ hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1);
-+ hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2);
-+ hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1);
-+ hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2);
-+ hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1);
-+ hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2);
-+ hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1);
-+ hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2);
-+ hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1);
-+ hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2);
-+ hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1);
-+ hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2);
-+ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1);
-+ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1);
-+ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1);
-+ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2);
-+ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2);
-+ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2);
-+ hdmi_htop1_write(hdmi, 0x00000008, HDMI_HTOP1_CURRENT);
-+ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP0_1);
-+ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP2_C);
-+ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PHY_TEST_MODE);
-+ hdmi_htop1_write(hdmi, 0x00000081, HDMI_HTOP1_TISIDRV);
-+ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PLLBW);
-+ hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN);
-+ hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN);
-+ hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR);
-+ hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET);
-+ hdmi_htop1_write(hdmi, 0x00000016, HDMI_HTOP1_CISRANGE);
-+ msleep(100);
-+ hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_ENABLE_SELECTOR);
-+ msleep(100);
-+ hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR);
-+ hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET);
-+ hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN);
-+ hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN);
-+ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT);
-+ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_CLK_TO_PHY);
-+ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT2);
-+ hdmi_htop1_write(hdmi, 0x0000000a, HDMI_HTOP1_CLK_SET);
-+}
-+
- static int __init sh_hdmi_probe(struct platform_device *pdev)
- {
- struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
- struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ struct resource *htop1_res;
- int irq = platform_get_irq(pdev, 0), ret;
- struct sh_hdmi *hdmi;
- long rate;
-@@ -1156,6 +1281,15 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
- if (!res || !pdata || irq < 0)
- return -ENODEV;
-
-+ htop1_res = NULL;
-+ if (pdata->flags & HDMI_HAS_HTOP1) {
-+ htop1_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+ if (!htop1_res) {
-+ dev_err(&pdev->dev, "htop1 needs register base\n");
-+ return -EINVAL;
-+ }
-+ }
-+
- hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
- if (!hdmi) {
- dev_err(&pdev->dev, "Cannot allocate device data\n");
-@@ -1227,6 +1361,17 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
- if (pdata->flags & HDMI_OUTPUT_POLARITY_HI)
- hdmi_bit_set(hdmi, 0x01, 0x01, HDMI_SYSTEM_CTRL);
-
-+ /* enable htop1 register if needed */
-+ if (htop1_res) {
-+ hdmi->htop1 = ioremap(htop1_res->start, resource_size(htop1_res));
-+ if (!hdmi->htop1) {
-+ dev_err(&pdev->dev, "control register region already claimed\n");
-+ ret = -ENOMEM;
-+ goto emap_htop1;
-+ }
-+ sh_hdmi_htop1_init(hdmi);
-+ }
-+
- /* Product and revision IDs are 0 in sh-mobile version */
- dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
- hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
-@@ -1250,6 +1395,9 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
- ecodec:
- free_irq(irq, hdmi);
- ereqirq:
-+ if (hdmi->htop1)
-+ iounmap(hdmi->htop1);
-+emap_htop1:
- pm_runtime_put(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
- iounmap(hdmi->base);
-@@ -1281,6 +1429,8 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
- pm_runtime_disable(&pdev->dev);
- clk_disable(hdmi->hdmi_clk);
- clk_put(hdmi->hdmi_clk);
-+ if (hdmi->htop1)
-+ iounmap(hdmi->htop1);
- iounmap(hdmi->base);
- release_mem_region(res->start, resource_size(res));
- kfree(hdmi);
-diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h
-index ce8a540..63d20ef 100644
---- a/include/video/sh_mobile_hdmi.h
-+++ b/include/video/sh_mobile_hdmi.h
-@@ -38,6 +38,7 @@ struct clk;
-
- /* Chip specific option */
- #define HDMI_32BIT_REG (1 << 8)
-+#define HDMI_HAS_HTOP1 (1 << 9)
-
- struct sh_mobile_hdmi_info {
- unsigned int flags;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 46a0acbafe13b92d4ea16ca47414ac22579f9827 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Thu, 14 Jun 2012 09:53:33 +0200
-Subject: fbdev: sh_mipi_dsi: fix a section mismatch
-
-sh_mipi_setup() is called from a .text function, therefore it cannot be
-__init. Additionally, sh_mipi_remove() can be moved to the .devexit.text
-section.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-(cherry picked from commit e6765ffa6897f7fb84469bab2e1be885c57ea519)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mipi_dsi.c | 7 +++----
- 1 file changed, 3 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
-index 4c6b844..3951fda 100644
---- a/drivers/video/sh_mipi_dsi.c
-+++ b/drivers/video/sh_mipi_dsi.c
-@@ -127,8 +127,7 @@ static void sh_mipi_shutdown(struct platform_device *pdev)
- sh_mipi_dsi_enable(mipi, false);
- }
-
--static int __init sh_mipi_setup(struct sh_mipi *mipi,
-- struct sh_mipi_dsi_info *pdata)
-+static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
- {
- void __iomem *base = mipi->base;
- struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
-@@ -551,7 +550,7 @@ efindslot:
- return ret;
- }
-
--static int __exit sh_mipi_remove(struct platform_device *pdev)
-+static int __devexit sh_mipi_remove(struct platform_device *pdev)
- {
- struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-@@ -592,7 +591,7 @@ static int __exit sh_mipi_remove(struct platform_device *pdev)
- }
-
- static struct platform_driver sh_mipi_driver = {
-- .remove = __exit_p(sh_mipi_remove),
-+ .remove = __devexit_p(sh_mipi_remove),
- .shutdown = sh_mipi_shutdown,
- .driver = {
- .name = "sh-mipi-dsi",
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 285591af450384157206e46d4b676f8a5d095c4a Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Tue, 22 Nov 2011 00:56:58 +0100
-Subject: fbdev: sh_mobile_lcdc: Constify sh_mobile_lcdc_fix structure
-
-The structure is only read, make it const.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-(cherry picked from commit 3281e54c80195b90ed12a5b6cddef4ab42e656e1)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_lcdcfb.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
-index e672698..5461abe 100644
---- a/drivers/video/sh_mobile_lcdcfb.c
-+++ b/drivers/video/sh_mobile_lcdcfb.c
-@@ -1003,7 +1003,7 @@ static int sh_mobile_lcdc_setcolreg(u_int regno,
- return 0;
- }
-
--static struct fb_fix_screeninfo sh_mobile_lcdc_fix = {
-+static const struct fb_fix_screeninfo sh_mobile_lcdc_fix = {
- .id = "SH Mobile LCDC",
- .type = FB_TYPE_PACKED_PIXELS,
- .visual = FB_VISUAL_TRUECOLOR,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2a41d02255f596307db8e41902cfec9877bfe493 Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Tue, 22 Nov 2011 00:56:58 +0100
-Subject: fbdev: sh_mobile_lcdc: Rename fb operation handlers with a common
- prefix
-
-Make all fb operation handlers start with sh_mobile_lcdc_ in preparation
-for the multi-plane support.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-(cherry picked from commit d7ad33421863308fe7ddf865737d4d83b64e5b81)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_lcdcfb.c | 48 +++++++++++++++++++++-------------------
- 1 file changed, 25 insertions(+), 23 deletions(-)
-
-diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
-index 5461abe..799f871 100644
---- a/drivers/video/sh_mobile_lcdcfb.c
-+++ b/drivers/video/sh_mobile_lcdcfb.c
-@@ -384,8 +384,8 @@ sh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch,
- return true;
- }
-
--static int sh_mobile_check_var(struct fb_var_screeninfo *var,
-- struct fb_info *info);
-+static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
-+ struct fb_info *info);
-
- static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
- enum sh_mobile_lcdc_entity_event event,
-@@ -439,7 +439,7 @@ static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
- fb_videomode_to_var(&var, mode);
- var.bits_per_pixel = info->var.bits_per_pixel;
- var.grayscale = info->var.grayscale;
-- ret = sh_mobile_check_var(&var, info);
-+ ret = sh_mobile_lcdc_check_var(&var, info);
- break;
- }
-
-@@ -585,7 +585,7 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
- return IRQ_HANDLED;
- }
-
--static int sh_mobile_wait_for_vsync(struct sh_mobile_lcdc_chan *ch)
-+static int sh_mobile_lcdc_wait_for_vsync(struct sh_mobile_lcdc_chan *ch)
- {
- unsigned long ldintr;
- int ret;
-@@ -686,7 +686,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
- }
-
- /*
-- * __sh_mobile_lcdc_start - Configure and tart the LCDC
-+ * __sh_mobile_lcdc_start - Configure and start the LCDC
- * @priv: LCDC device
- *
- * Configure all enabled channels and start the LCDC device. All external
-@@ -1035,8 +1035,8 @@ static void sh_mobile_lcdc_imageblit(struct fb_info *info,
- sh_mobile_lcdc_deferred_io_touch(info);
- }
-
--static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
-- struct fb_info *info)
-+static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
-+ struct fb_info *info)
- {
- struct sh_mobile_lcdc_chan *ch = info->par;
- struct sh_mobile_lcdc_priv *priv = ch->lcdc;
-@@ -1099,14 +1099,15 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
- return 0;
- }
-
--static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
-- unsigned long arg)
-+static int sh_mobile_lcdc_ioctl(struct fb_info *info, unsigned int cmd,
-+ unsigned long arg)
- {
-+ struct sh_mobile_lcdc_chan *ch = info->par;
- int retval;
-
- switch (cmd) {
- case FBIO_WAITFORVSYNC:
-- retval = sh_mobile_wait_for_vsync(info->par);
-+ retval = sh_mobile_lcdc_wait_for_vsync(ch);
- break;
-
- default:
-@@ -1158,7 +1159,7 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
- * Locking: both .fb_release() and .fb_open() are called with info->lock held if
- * user == 1, or with console sem held, if user == 0.
- */
--static int sh_mobile_release(struct fb_info *info, int user)
-+static int sh_mobile_lcdc_release(struct fb_info *info, int user)
- {
- struct sh_mobile_lcdc_chan *ch = info->par;
-
-@@ -1179,7 +1180,7 @@ static int sh_mobile_release(struct fb_info *info, int user)
- return 0;
- }
-
--static int sh_mobile_open(struct fb_info *info, int user)
-+static int sh_mobile_lcdc_open(struct fb_info *info, int user)
- {
- struct sh_mobile_lcdc_chan *ch = info->par;
-
-@@ -1192,7 +1193,8 @@ static int sh_mobile_open(struct fb_info *info, int user)
- return 0;
- }
-
--static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-+static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
-+ struct fb_info *info)
- {
- struct sh_mobile_lcdc_chan *ch = info->par;
- struct sh_mobile_lcdc_priv *p = ch->lcdc;
-@@ -1313,7 +1315,7 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
- return 0;
- }
-
--static int sh_mobile_set_par(struct fb_info *info)
-+static int sh_mobile_lcdc_set_par(struct fb_info *info)
- {
- struct sh_mobile_lcdc_chan *ch = info->par;
- int ret;
-@@ -1383,8 +1385,8 @@ static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
- * mode will reenable the clocks and update the screen in time,
- * so it does not need this. */
- if (!info->fbdefio) {
-- sh_mobile_wait_for_vsync(ch);
-- sh_mobile_wait_for_vsync(ch);
-+ sh_mobile_lcdc_wait_for_vsync(ch);
-+ sh_mobile_lcdc_wait_for_vsync(ch);
- }
- sh_mobile_lcdc_clk_off(p);
- }
-@@ -1402,12 +1404,12 @@ static struct fb_ops sh_mobile_lcdc_ops = {
- .fb_copyarea = sh_mobile_lcdc_copyarea,
- .fb_imageblit = sh_mobile_lcdc_imageblit,
- .fb_blank = sh_mobile_lcdc_blank,
-- .fb_pan_display = sh_mobile_fb_pan_display,
-- .fb_ioctl = sh_mobile_ioctl,
-- .fb_open = sh_mobile_open,
-- .fb_release = sh_mobile_release,
-- .fb_check_var = sh_mobile_check_var,
-- .fb_set_par = sh_mobile_set_par,
-+ .fb_pan_display = sh_mobile_lcdc_pan,
-+ .fb_ioctl = sh_mobile_lcdc_ioctl,
-+ .fb_open = sh_mobile_lcdc_open,
-+ .fb_release = sh_mobile_lcdc_release,
-+ .fb_check_var = sh_mobile_lcdc_check_var,
-+ .fb_set_par = sh_mobile_lcdc_set_par,
- };
-
- static void
-@@ -1537,7 +1539,7 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
- else
- var->grayscale = ch->format->fourcc;
-
-- ret = sh_mobile_check_var(var, info);
-+ ret = sh_mobile_lcdc_check_var(var, info);
- if (ret)
- return ret;
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ae0b639299213d1d1361aa368c57ee8a3d94214b Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Mon, 12 Dec 2011 18:43:16 +0100
-Subject: fbdev: sh_mobile_lcdc: Implement overlays support
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-(cherry picked from commit c5deac3c9b2284a64326e8799dfe7416bc619c02)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- .../sysfs-devices-platform-sh_mobile_lcdc_fb | 44 +
- drivers/video/sh_mobile_lcdcfb.c | 932 +++++++++++++++++++--
- include/video/sh_mobile_lcdc.h | 7 +
- 3 files changed, 911 insertions(+), 72 deletions(-)
- create mode 100644 Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb
-
-diff --git a/Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb b/Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb
-new file mode 100644
-index 0000000..2107082
---- /dev/null
-+++ b/Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb
-@@ -0,0 +1,44 @@
-+What: /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_alpha
-+Date: May 2012
-+Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+Description:
-+ This file is only available on fb[0-9] devices corresponding
-+ to overlay planes.
-+
-+ Stores the alpha blending value for the overlay. Values range
-+ from 0 (transparent) to 255 (opaque). The value is ignored if
-+ the mode is not set to Alpha Blending.
-+
-+What: /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_mode
-+Date: May 2012
-+Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+Description:
-+ This file is only available on fb[0-9] devices corresponding
-+ to overlay planes.
-+
-+ Selects the composition mode for the overlay. Possible values
-+ are
-+
-+ 0 - Alpha Blending
-+ 1 - ROP3
-+
-+What: /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_position
-+Date: May 2012
-+Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+Description:
-+ This file is only available on fb[0-9] devices corresponding
-+ to overlay planes.
-+
-+ Stores the x,y overlay position on the display in pixels. The
-+ position format is `[0-9]+,[0-9]+'.
-+
-+What: /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_rop3
-+Date: May 2012
-+Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-+Description:
-+ This file is only available on fb[0-9] devices corresponding
-+ to overlay planes.
-+
-+ Stores the raster operation (ROP3) for the overlay. Values
-+ range from 0 to 255. The value is ignored if the mode is not
-+ set to ROP3.
-diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
-index 799f871..98e81b3 100644
---- a/drivers/video/sh_mobile_lcdcfb.c
-+++ b/drivers/video/sh_mobile_lcdcfb.c
-@@ -12,6 +12,7 @@
- #include <linux/backlight.h>
- #include <linux/clk.h>
- #include <linux/console.h>
-+#include <linux/ctype.h>
- #include <linux/dma-mapping.h>
- #include <linux/delay.h>
- #include <linux/gpio.h>
-@@ -32,12 +33,176 @@
-
- #include "sh_mobile_lcdcfb.h"
-
-+/* ----------------------------------------------------------------------------
-+ * Overlay register definitions
-+ */
-+
-+#define LDBCR 0xb00
-+#define LDBCR_UPC(n) (1 << ((n) + 16))
-+#define LDBCR_UPF(n) (1 << ((n) + 8))
-+#define LDBCR_UPD(n) (1 << ((n) + 0))
-+#define LDBnBSIFR(n) (0xb20 + (n) * 0x20 + 0x00)
-+#define LDBBSIFR_EN (1 << 31)
-+#define LDBBSIFR_VS (1 << 29)
-+#define LDBBSIFR_BRSEL (1 << 28)
-+#define LDBBSIFR_MX (1 << 27)
-+#define LDBBSIFR_MY (1 << 26)
-+#define LDBBSIFR_CV3 (3 << 24)
-+#define LDBBSIFR_CV2 (2 << 24)
-+#define LDBBSIFR_CV1 (1 << 24)
-+#define LDBBSIFR_CV0 (0 << 24)
-+#define LDBBSIFR_CV_MASK (3 << 24)
-+#define LDBBSIFR_LAY_MASK (0xff << 16)
-+#define LDBBSIFR_LAY_SHIFT 16
-+#define LDBBSIFR_ROP3_MASK (0xff << 16)
-+#define LDBBSIFR_ROP3_SHIFT 16
-+#define LDBBSIFR_AL_PL8 (3 << 14)
-+#define LDBBSIFR_AL_PL1 (2 << 14)
-+#define LDBBSIFR_AL_PK (1 << 14)
-+#define LDBBSIFR_AL_1 (0 << 14)
-+#define LDBBSIFR_AL_MASK (3 << 14)
-+#define LDBBSIFR_SWPL (1 << 10)
-+#define LDBBSIFR_SWPW (1 << 9)
-+#define LDBBSIFR_SWPB (1 << 8)
-+#define LDBBSIFR_RY (1 << 7)
-+#define LDBBSIFR_CHRR_420 (2 << 0)
-+#define LDBBSIFR_CHRR_422 (1 << 0)
-+#define LDBBSIFR_CHRR_444 (0 << 0)
-+#define LDBBSIFR_RPKF_ARGB32 (0x00 << 0)
-+#define LDBBSIFR_RPKF_RGB16 (0x03 << 0)
-+#define LDBBSIFR_RPKF_RGB24 (0x0b << 0)
-+#define LDBBSIFR_RPKF_MASK (0x1f << 0)
-+#define LDBnBSSZR(n) (0xb20 + (n) * 0x20 + 0x04)
-+#define LDBBSSZR_BVSS_MASK (0xfff << 16)
-+#define LDBBSSZR_BVSS_SHIFT 16
-+#define LDBBSSZR_BHSS_MASK (0xfff << 0)
-+#define LDBBSSZR_BHSS_SHIFT 0
-+#define LDBnBLOCR(n) (0xb20 + (n) * 0x20 + 0x08)
-+#define LDBBLOCR_CVLC_MASK (0xfff << 16)
-+#define LDBBLOCR_CVLC_SHIFT 16
-+#define LDBBLOCR_CHLC_MASK (0xfff << 0)
-+#define LDBBLOCR_CHLC_SHIFT 0
-+#define LDBnBSMWR(n) (0xb20 + (n) * 0x20 + 0x0c)
-+#define LDBBSMWR_BSMWA_MASK (0xffff << 16)
-+#define LDBBSMWR_BSMWA_SHIFT 16
-+#define LDBBSMWR_BSMW_MASK (0xffff << 0)
-+#define LDBBSMWR_BSMW_SHIFT 0
-+#define LDBnBSAYR(n) (0xb20 + (n) * 0x20 + 0x10)
-+#define LDBBSAYR_FG1A_MASK (0xff << 24)
-+#define LDBBSAYR_FG1A_SHIFT 24
-+#define LDBBSAYR_FG1R_MASK (0xff << 16)
-+#define LDBBSAYR_FG1R_SHIFT 16
-+#define LDBBSAYR_FG1G_MASK (0xff << 8)
-+#define LDBBSAYR_FG1G_SHIFT 8
-+#define LDBBSAYR_FG1B_MASK (0xff << 0)
-+#define LDBBSAYR_FG1B_SHIFT 0
-+#define LDBnBSACR(n) (0xb20 + (n) * 0x20 + 0x14)
-+#define LDBBSACR_FG2A_MASK (0xff << 24)
-+#define LDBBSACR_FG2A_SHIFT 24
-+#define LDBBSACR_FG2R_MASK (0xff << 16)
-+#define LDBBSACR_FG2R_SHIFT 16
-+#define LDBBSACR_FG2G_MASK (0xff << 8)
-+#define LDBBSACR_FG2G_SHIFT 8
-+#define LDBBSACR_FG2B_MASK (0xff << 0)
-+#define LDBBSACR_FG2B_SHIFT 0
-+#define LDBnBSAAR(n) (0xb20 + (n) * 0x20 + 0x18)
-+#define LDBBSAAR_AP_MASK (0xff << 24)
-+#define LDBBSAAR_AP_SHIFT 24
-+#define LDBBSAAR_R_MASK (0xff << 16)
-+#define LDBBSAAR_R_SHIFT 16
-+#define LDBBSAAR_GY_MASK (0xff << 8)
-+#define LDBBSAAR_GY_SHIFT 8
-+#define LDBBSAAR_B_MASK (0xff << 0)
-+#define LDBBSAAR_B_SHIFT 0
-+#define LDBnBPPCR(n) (0xb20 + (n) * 0x20 + 0x1c)
-+#define LDBBPPCR_AP_MASK (0xff << 24)
-+#define LDBBPPCR_AP_SHIFT 24
-+#define LDBBPPCR_R_MASK (0xff << 16)
-+#define LDBBPPCR_R_SHIFT 16
-+#define LDBBPPCR_GY_MASK (0xff << 8)
-+#define LDBBPPCR_GY_SHIFT 8
-+#define LDBBPPCR_B_MASK (0xff << 0)
-+#define LDBBPPCR_B_SHIFT 0
-+#define LDBnBBGCL(n) (0xb10 + (n) * 0x04)
-+#define LDBBBGCL_BGA_MASK (0xff << 24)
-+#define LDBBBGCL_BGA_SHIFT 24
-+#define LDBBBGCL_BGR_MASK (0xff << 16)
-+#define LDBBBGCL_BGR_SHIFT 16
-+#define LDBBBGCL_BGG_MASK (0xff << 8)
-+#define LDBBBGCL_BGG_SHIFT 8
-+#define LDBBBGCL_BGB_MASK (0xff << 0)
-+#define LDBBBGCL_BGB_SHIFT 0
-+
- #define SIDE_B_OFFSET 0x1000
- #define MIRROR_OFFSET 0x2000
-
- #define MAX_XRES 1920
- #define MAX_YRES 1080
-
-+enum sh_mobile_lcdc_overlay_mode {
-+ LCDC_OVERLAY_BLEND,
-+ LCDC_OVERLAY_ROP3,
-+};
-+
-+/*
-+ * struct sh_mobile_lcdc_overlay - LCDC display overlay
-+ *
-+ * @channel: LCDC channel this overlay belongs to
-+ * @cfg: Overlay configuration
-+ * @info: Frame buffer device
-+ * @index: Overlay index (0-3)
-+ * @base: Overlay registers base address
-+ * @enabled: True if the overlay is enabled
-+ * @mode: Overlay blending mode (alpha blend or ROP3)
-+ * @alpha: Global alpha blending value (0-255, for alpha blending mode)
-+ * @rop3: Raster operation (for ROP3 mode)
-+ * @fb_mem: Frame buffer virtual memory address
-+ * @fb_size: Frame buffer size in bytes
-+ * @dma_handle: Frame buffer DMA address
-+ * @base_addr_y: Overlay base address (RGB or luma component)
-+ * @base_addr_c: Overlay base address (chroma component)
-+ * @pan_offset: Current pan offset in bytes
-+ * @format: Current pixelf format
-+ * @xres: Horizontal visible resolution
-+ * @xres_virtual: Horizontal total resolution
-+ * @yres: Vertical visible resolution
-+ * @yres_virtual: Vertical total resolution
-+ * @pitch: Overlay line pitch
-+ * @pos_x: Horizontal overlay position
-+ * @pos_y: Vertical overlay position
-+ */
-+struct sh_mobile_lcdc_overlay {
-+ struct sh_mobile_lcdc_chan *channel;
-+
-+ const struct sh_mobile_lcdc_overlay_cfg *cfg;
-+ struct fb_info *info;
-+
-+ unsigned int index;
-+ unsigned long base;
-+
-+ bool enabled;
-+ enum sh_mobile_lcdc_overlay_mode mode;
-+ unsigned int alpha;
-+ unsigned int rop3;
-+
-+ void *fb_mem;
-+ unsigned long fb_size;
-+
-+ dma_addr_t dma_handle;
-+ unsigned long base_addr_y;
-+ unsigned long base_addr_c;
-+ unsigned long pan_offset;
-+
-+ const struct sh_mobile_lcdc_format_info *format;
-+ unsigned int xres;
-+ unsigned int xres_virtual;
-+ unsigned int yres;
-+ unsigned int yres_virtual;
-+ unsigned int pitch;
-+ int pos_x;
-+ int pos_y;
-+};
-+
- struct sh_mobile_lcdc_priv {
- void __iomem *base;
- int irq;
-@@ -45,7 +210,10 @@ struct sh_mobile_lcdc_priv {
- struct device *dev;
- struct clk *dot_clk;
- unsigned long lddckr;
-+
- struct sh_mobile_lcdc_chan ch[2];
-+ struct sh_mobile_lcdc_overlay overlays[4];
-+
- struct notifier_block notifier;
- int started;
- int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
-@@ -141,6 +309,13 @@ static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan,
- return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]);
- }
-
-+static void lcdc_write_overlay(struct sh_mobile_lcdc_overlay *ovl,
-+ int reg, unsigned long data)
-+{
-+ iowrite32(data, ovl->channel->lcdc->base + reg);
-+ iowrite32(data, ovl->channel->lcdc->base + reg + SIDE_B_OFFSET);
-+}
-+
- static void lcdc_write(struct sh_mobile_lcdc_priv *priv,
- unsigned long reg_offs, unsigned long data)
- {
-@@ -685,6 +860,96 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
- lcdc_write_chan(ch, LDHAJR, tmp);
- }
-
-+static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl)
-+{
-+ u32 format = 0;
-+
-+ if (!ovl->enabled) {
-+ lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
-+ lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), 0);
-+ lcdc_write(ovl->channel->lcdc, LDBCR,
-+ LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
-+ return;
-+ }
-+
-+ ovl->base_addr_y = ovl->dma_handle;
-+ ovl->base_addr_c = ovl->base_addr_y + ovl->xres
-+ * ovl->yres_virtual;
-+
-+ switch (ovl->mode) {
-+ case LCDC_OVERLAY_BLEND:
-+ format = LDBBSIFR_EN | (ovl->alpha << LDBBSIFR_LAY_SHIFT);
-+ break;
-+
-+ case LCDC_OVERLAY_ROP3:
-+ format = LDBBSIFR_EN | LDBBSIFR_BRSEL
-+ | (ovl->rop3 << LDBBSIFR_ROP3_SHIFT);
-+ break;
-+ }
-+
-+ switch (ovl->format->fourcc) {
-+ case V4L2_PIX_FMT_RGB565:
-+ case V4L2_PIX_FMT_NV21:
-+ case V4L2_PIX_FMT_NV61:
-+ case V4L2_PIX_FMT_NV42:
-+ format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW;
-+ break;
-+ case V4L2_PIX_FMT_BGR24:
-+ case V4L2_PIX_FMT_NV12:
-+ case V4L2_PIX_FMT_NV16:
-+ case V4L2_PIX_FMT_NV24:
-+ format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB;
-+ break;
-+ case V4L2_PIX_FMT_BGR32:
-+ default:
-+ format |= LDBBSIFR_SWPL;
-+ break;
-+ }
-+
-+ switch (ovl->format->fourcc) {
-+ case V4L2_PIX_FMT_RGB565:
-+ format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16;
-+ break;
-+ case V4L2_PIX_FMT_BGR24:
-+ format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24;
-+ break;
-+ case V4L2_PIX_FMT_BGR32:
-+ format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32;
-+ break;
-+ case V4L2_PIX_FMT_NV12:
-+ case V4L2_PIX_FMT_NV21:
-+ format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420;
-+ break;
-+ case V4L2_PIX_FMT_NV16:
-+ case V4L2_PIX_FMT_NV61:
-+ format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_422;
-+ break;
-+ case V4L2_PIX_FMT_NV24:
-+ case V4L2_PIX_FMT_NV42:
-+ format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_444;
-+ break;
-+ }
-+
-+ lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
-+
-+ lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), format);
-+
-+ lcdc_write_overlay(ovl, LDBnBSSZR(ovl->index),
-+ (ovl->yres << LDBBSSZR_BVSS_SHIFT) |
-+ (ovl->xres << LDBBSSZR_BHSS_SHIFT));
-+ lcdc_write_overlay(ovl, LDBnBLOCR(ovl->index),
-+ (ovl->pos_y << LDBBLOCR_CVLC_SHIFT) |
-+ (ovl->pos_x << LDBBLOCR_CHLC_SHIFT));
-+ lcdc_write_overlay(ovl, LDBnBSMWR(ovl->index),
-+ ovl->pitch << LDBBSMWR_BSMW_SHIFT);
-+
-+ lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y);
-+ lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c);
-+
-+ lcdc_write(ovl->channel->lcdc, LDBCR,
-+ LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
-+}
-+
- /*
- * __sh_mobile_lcdc_start - Configure and start the LCDC
- * @priv: LCDC device
-@@ -892,6 +1157,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
- }
- }
-
-+ for (k = 0; k < ARRAY_SIZE(priv->overlays); ++k) {
-+ struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[k];
-+ sh_mobile_lcdc_overlay_setup(ovl);
-+ }
-+
- /* Start the LCDC. */
- __sh_mobile_lcdc_start(priv);
-
-@@ -975,8 +1245,506 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
- sh_mobile_lcdc_clk_off(priv);
- }
-
-+static int __sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
-+ struct fb_info *info)
-+{
-+ if (var->xres > MAX_XRES || var->yres > MAX_YRES)
-+ return -EINVAL;
-+
-+ /* Make sure the virtual resolution is at least as big as the visible
-+ * resolution.
-+ */
-+ if (var->xres_virtual < var->xres)
-+ var->xres_virtual = var->xres;
-+ if (var->yres_virtual < var->yres)
-+ var->yres_virtual = var->yres;
-+
-+ if (sh_mobile_format_is_fourcc(var)) {
-+ const struct sh_mobile_lcdc_format_info *format;
-+
-+ format = sh_mobile_format_info(var->grayscale);
-+ if (format == NULL)
-+ return -EINVAL;
-+ var->bits_per_pixel = format->bpp;
-+
-+ /* Default to RGB and JPEG color-spaces for RGB and YUV formats
-+ * respectively.
-+ */
-+ if (!format->yuv)
-+ var->colorspace = V4L2_COLORSPACE_SRGB;
-+ else if (var->colorspace != V4L2_COLORSPACE_REC709)
-+ var->colorspace = V4L2_COLORSPACE_JPEG;
-+ } else {
-+ if (var->bits_per_pixel <= 16) { /* RGB 565 */
-+ var->bits_per_pixel = 16;
-+ var->red.offset = 11;
-+ var->red.length = 5;
-+ var->green.offset = 5;
-+ var->green.length = 6;
-+ var->blue.offset = 0;
-+ var->blue.length = 5;
-+ var->transp.offset = 0;
-+ var->transp.length = 0;
-+ } else if (var->bits_per_pixel <= 24) { /* RGB 888 */
-+ var->bits_per_pixel = 24;
-+ var->red.offset = 16;
-+ var->red.length = 8;
-+ var->green.offset = 8;
-+ var->green.length = 8;
-+ var->blue.offset = 0;
-+ var->blue.length = 8;
-+ var->transp.offset = 0;
-+ var->transp.length = 0;
-+ } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */
-+ var->bits_per_pixel = 32;
-+ var->red.offset = 16;
-+ var->red.length = 8;
-+ var->green.offset = 8;
-+ var->green.length = 8;
-+ var->blue.offset = 0;
-+ var->blue.length = 8;
-+ var->transp.offset = 24;
-+ var->transp.length = 8;
-+ } else
-+ return -EINVAL;
-+
-+ var->red.msb_right = 0;
-+ var->green.msb_right = 0;
-+ var->blue.msb_right = 0;
-+ var->transp.msb_right = 0;
-+ }
-+
-+ /* Make sure we don't exceed our allocated memory. */
-+ if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
-+ info->fix.smem_len)
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+/* -----------------------------------------------------------------------------
-+ * Frame buffer operations - Overlays
-+ */
-+
-+static ssize_t
-+overlay_alpha_show(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+ struct fb_info *info = dev_get_drvdata(dev);
-+ struct sh_mobile_lcdc_overlay *ovl = info->par;
-+
-+ return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->alpha);
-+}
-+
-+static ssize_t
-+overlay_alpha_store(struct device *dev, struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ struct fb_info *info = dev_get_drvdata(dev);
-+ struct sh_mobile_lcdc_overlay *ovl = info->par;
-+ unsigned int alpha;
-+ char *endp;
-+
-+ alpha = simple_strtoul(buf, &endp, 10);
-+ if (isspace(*endp))
-+ endp++;
-+
-+ if (endp - buf != count)
-+ return -EINVAL;
-+
-+ if (alpha > 255)
-+ return -EINVAL;
-+
-+ if (ovl->alpha != alpha) {
-+ ovl->alpha = alpha;
-+
-+ if (ovl->mode == LCDC_OVERLAY_BLEND && ovl->enabled)
-+ sh_mobile_lcdc_overlay_setup(ovl);
-+ }
-+
-+ return count;
-+}
-+
-+static ssize_t
-+overlay_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+ struct fb_info *info = dev_get_drvdata(dev);
-+ struct sh_mobile_lcdc_overlay *ovl = info->par;
-+
-+ return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->mode);
-+}
-+
-+static ssize_t
-+overlay_mode_store(struct device *dev, struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ struct fb_info *info = dev_get_drvdata(dev);
-+ struct sh_mobile_lcdc_overlay *ovl = info->par;
-+ unsigned int mode;
-+ char *endp;
-+
-+ mode = simple_strtoul(buf, &endp, 10);
-+ if (isspace(*endp))
-+ endp++;
-+
-+ if (endp - buf != count)
-+ return -EINVAL;
-+
-+ if (mode != LCDC_OVERLAY_BLEND && mode != LCDC_OVERLAY_ROP3)
-+ return -EINVAL;
-+
-+ if (ovl->mode != mode) {
-+ ovl->mode = mode;
-+
-+ if (ovl->enabled)
-+ sh_mobile_lcdc_overlay_setup(ovl);
-+ }
-+
-+ return count;
-+}
-+
-+static ssize_t
-+overlay_position_show(struct device *dev, struct device_attribute *attr,
-+ char *buf)
-+{
-+ struct fb_info *info = dev_get_drvdata(dev);
-+ struct sh_mobile_lcdc_overlay *ovl = info->par;
-+
-+ return scnprintf(buf, PAGE_SIZE, "%d,%d\n", ovl->pos_x, ovl->pos_y);
-+}
-+
-+static ssize_t
-+overlay_position_store(struct device *dev, struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ struct fb_info *info = dev_get_drvdata(dev);
-+ struct sh_mobile_lcdc_overlay *ovl = info->par;
-+ char *endp;
-+ int pos_x;
-+ int pos_y;
-+
-+ pos_x = simple_strtol(buf, &endp, 10);
-+ if (*endp != ',')
-+ return -EINVAL;
-+
-+ pos_y = simple_strtol(endp + 1, &endp, 10);
-+ if (isspace(*endp))
-+ endp++;
-+
-+ if (endp - buf != count)
-+ return -EINVAL;
-+
-+ if (ovl->pos_x != pos_x || ovl->pos_y != pos_y) {
-+ ovl->pos_x = pos_x;
-+ ovl->pos_y = pos_y;
-+
-+ if (ovl->enabled)
-+ sh_mobile_lcdc_overlay_setup(ovl);
-+ }
-+
-+ return count;
-+}
-+
-+static ssize_t
-+overlay_rop3_show(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+ struct fb_info *info = dev_get_drvdata(dev);
-+ struct sh_mobile_lcdc_overlay *ovl = info->par;
-+
-+ return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->rop3);
-+}
-+
-+static ssize_t
-+overlay_rop3_store(struct device *dev, struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ struct fb_info *info = dev_get_drvdata(dev);
-+ struct sh_mobile_lcdc_overlay *ovl = info->par;
-+ unsigned int rop3;
-+ char *endp;
-+
-+ rop3 = !!simple_strtoul(buf, &endp, 10);
-+ if (isspace(*endp))
-+ endp++;
-+
-+ if (endp - buf != count)
-+ return -EINVAL;
-+
-+ if (rop3 > 255)
-+ return -EINVAL;
-+
-+ if (ovl->rop3 != rop3) {
-+ ovl->rop3 = rop3;
-+
-+ if (ovl->mode == LCDC_OVERLAY_ROP3 && ovl->enabled)
-+ sh_mobile_lcdc_overlay_setup(ovl);
-+ }
-+
-+ return count;
-+}
-+
-+static const struct device_attribute overlay_sysfs_attrs[] = {
-+ __ATTR(ovl_alpha, S_IRUGO|S_IWUSR,
-+ overlay_alpha_show, overlay_alpha_store),
-+ __ATTR(ovl_mode, S_IRUGO|S_IWUSR,
-+ overlay_mode_show, overlay_mode_store),
-+ __ATTR(ovl_position, S_IRUGO|S_IWUSR,
-+ overlay_position_show, overlay_position_store),
-+ __ATTR(ovl_rop3, S_IRUGO|S_IWUSR,
-+ overlay_rop3_show, overlay_rop3_store),
-+};
-+
-+static const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix = {
-+ .id = "SH Mobile LCDC",
-+ .type = FB_TYPE_PACKED_PIXELS,
-+ .visual = FB_VISUAL_TRUECOLOR,
-+ .accel = FB_ACCEL_NONE,
-+ .xpanstep = 0,
-+ .ypanstep = 1,
-+ .ywrapstep = 0,
-+ .capabilities = FB_CAP_FOURCC,
-+};
-+
-+static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var,
-+ struct fb_info *info)
-+{
-+ struct sh_mobile_lcdc_overlay *ovl = info->par;
-+ unsigned long base_addr_y;
-+ unsigned long base_addr_c;
-+ unsigned long pan_offset;
-+ unsigned long c_offset;
-+
-+ if (!ovl->format->yuv)
-+ pan_offset = var->yoffset * ovl->pitch
-+ + var->xoffset * (ovl->format->bpp / 8);
-+ else
-+ pan_offset = var->yoffset * ovl->pitch + var->xoffset;
-+
-+ if (pan_offset == ovl->pan_offset)
-+ return 0; /* No change, do nothing */
-+
-+ /* Set the source address for the next refresh */
-+ base_addr_y = ovl->dma_handle + pan_offset;
-+
-+ ovl->base_addr_y = base_addr_y;
-+ ovl->base_addr_c = base_addr_y;
-+
-+ if (ovl->format->yuv) {
-+ /* Set Y offset */
-+ c_offset = var->yoffset * ovl->pitch
-+ * (ovl->format->bpp - 8) / 8;
-+ base_addr_c = ovl->dma_handle
-+ + ovl->xres * ovl->yres_virtual
-+ + c_offset;
-+ /* Set X offset */
-+ if (ovl->format->fourcc == V4L2_PIX_FMT_NV24)
-+ base_addr_c += 2 * var->xoffset;
-+ else
-+ base_addr_c += var->xoffset;
-+
-+ ovl->base_addr_c = base_addr_c;
-+ }
-+
-+ lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y);
-+ lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c);
-+
-+ ovl->pan_offset = pan_offset;
-+
-+ return 0;
-+}
-+
-+static int sh_mobile_lcdc_overlay_ioctl(struct fb_info *info, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ struct sh_mobile_lcdc_overlay *ovl = info->par;
-+
-+ switch (cmd) {
-+ case FBIO_WAITFORVSYNC:
-+ return sh_mobile_lcdc_wait_for_vsync(ovl->channel);
-+
-+ default:
-+ return -ENOIOCTLCMD;
-+ }
-+}
-+
-+static int sh_mobile_lcdc_overlay_check_var(struct fb_var_screeninfo *var,
-+ struct fb_info *info)
-+{
-+ return __sh_mobile_lcdc_check_var(var, info);
-+}
-+
-+static int sh_mobile_lcdc_overlay_set_par(struct fb_info *info)
-+{
-+ struct sh_mobile_lcdc_overlay *ovl = info->par;
-+
-+ ovl->format =
-+ sh_mobile_format_info(sh_mobile_format_fourcc(&info->var));
-+
-+ ovl->xres = info->var.xres;
-+ ovl->xres_virtual = info->var.xres_virtual;
-+ ovl->yres = info->var.yres;
-+ ovl->yres_virtual = info->var.yres_virtual;
-+
-+ if (ovl->format->yuv)
-+ ovl->pitch = info->var.xres;
-+ else
-+ ovl->pitch = info->var.xres * ovl->format->bpp / 8;
-+
-+ sh_mobile_lcdc_overlay_setup(ovl);
-+
-+ info->fix.line_length = ovl->pitch;
-+
-+ if (sh_mobile_format_is_fourcc(&info->var)) {
-+ info->fix.type = FB_TYPE_FOURCC;
-+ info->fix.visual = FB_VISUAL_FOURCC;
-+ } else {
-+ info->fix.type = FB_TYPE_PACKED_PIXELS;
-+ info->fix.visual = FB_VISUAL_TRUECOLOR;
-+ }
-+
-+ return 0;
-+}
-+
-+/* Overlay blanking. Disable the overlay when blanked. */
-+static int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info)
-+{
-+ struct sh_mobile_lcdc_overlay *ovl = info->par;
-+
-+ ovl->enabled = !blank;
-+ sh_mobile_lcdc_overlay_setup(ovl);
-+
-+ /* Prevent the backlight from receiving a blanking event by returning
-+ * a non-zero value.
-+ */
-+ return 1;
-+}
-+
-+static struct fb_ops sh_mobile_lcdc_overlay_ops = {
-+ .owner = THIS_MODULE,
-+ .fb_read = fb_sys_read,
-+ .fb_write = fb_sys_write,
-+ .fb_fillrect = sys_fillrect,
-+ .fb_copyarea = sys_copyarea,
-+ .fb_imageblit = sys_imageblit,
-+ .fb_blank = sh_mobile_lcdc_overlay_blank,
-+ .fb_pan_display = sh_mobile_lcdc_overlay_pan,
-+ .fb_ioctl = sh_mobile_lcdc_overlay_ioctl,
-+ .fb_check_var = sh_mobile_lcdc_overlay_check_var,
-+ .fb_set_par = sh_mobile_lcdc_overlay_set_par,
-+};
-+
-+static void
-+sh_mobile_lcdc_overlay_fb_unregister(struct sh_mobile_lcdc_overlay *ovl)
-+{
-+ struct fb_info *info = ovl->info;
-+
-+ if (info == NULL || info->dev == NULL)
-+ return;
-+
-+ unregister_framebuffer(ovl->info);
-+}
-+
-+static int __devinit
-+sh_mobile_lcdc_overlay_fb_register(struct sh_mobile_lcdc_overlay *ovl)
-+{
-+ struct sh_mobile_lcdc_priv *lcdc = ovl->channel->lcdc;
-+ struct fb_info *info = ovl->info;
-+ unsigned int i;
-+ int ret;
-+
-+ if (info == NULL)
-+ return 0;
-+
-+ ret = register_framebuffer(info);
-+ if (ret < 0)
-+ return ret;
-+
-+ dev_info(lcdc->dev, "registered %s/overlay %u as %dx%d %dbpp.\n",
-+ dev_name(lcdc->dev), ovl->index, info->var.xres,
-+ info->var.yres, info->var.bits_per_pixel);
-+
-+ for (i = 0; i < ARRAY_SIZE(overlay_sysfs_attrs); ++i) {
-+ ret = device_create_file(info->dev, &overlay_sysfs_attrs[i]);
-+ if (ret < 0)
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static void
-+sh_mobile_lcdc_overlay_fb_cleanup(struct sh_mobile_lcdc_overlay *ovl)
-+{
-+ struct fb_info *info = ovl->info;
-+
-+ if (info == NULL || info->device == NULL)
-+ return;
-+
-+ framebuffer_release(info);
-+}
-+
-+static int __devinit
-+sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl)
-+{
-+ struct sh_mobile_lcdc_priv *priv = ovl->channel->lcdc;
-+ struct fb_var_screeninfo *var;
-+ struct fb_info *info;
-+
-+ /* Allocate and initialize the frame buffer device. */
-+ info = framebuffer_alloc(0, priv->dev);
-+ if (info == NULL) {
-+ dev_err(priv->dev, "unable to allocate fb_info\n");
-+ return -ENOMEM;
-+ }
-+
-+ ovl->info = info;
-+
-+ info->flags = FBINFO_FLAG_DEFAULT;
-+ info->fbops = &sh_mobile_lcdc_overlay_ops;
-+ info->device = priv->dev;
-+ info->screen_base = ovl->fb_mem;
-+ info->par = ovl;
-+
-+ /* Initialize fixed screen information. Restrict pan to 2 lines steps
-+ * for NV12 and NV21.
-+ */
-+ info->fix = sh_mobile_lcdc_overlay_fix;
-+ snprintf(info->fix.id, sizeof(info->fix.id),
-+ "SH Mobile LCDC Overlay %u", ovl->index);
-+ info->fix.smem_start = ovl->dma_handle;
-+ info->fix.smem_len = ovl->fb_size;
-+ info->fix.line_length = ovl->pitch;
-+
-+ if (ovl->format->yuv)
-+ info->fix.visual = FB_VISUAL_FOURCC;
-+ else
-+ info->fix.visual = FB_VISUAL_TRUECOLOR;
-+
-+ if (ovl->format->fourcc == V4L2_PIX_FMT_NV12 ||
-+ ovl->format->fourcc == V4L2_PIX_FMT_NV21)
-+ info->fix.ypanstep = 2;
-+
-+ /* Initialize variable screen information. */
-+ var = &info->var;
-+ memset(var, 0, sizeof(*var));
-+ var->xres = ovl->xres;
-+ var->yres = ovl->yres;
-+ var->xres_virtual = ovl->xres_virtual;
-+ var->yres_virtual = ovl->yres_virtual;
-+ var->activate = FB_ACTIVATE_NOW;
-+
-+ /* Use the legacy API by default for RGB formats, and the FOURCC API
-+ * for YUV formats.
-+ */
-+ if (!ovl->format->yuv)
-+ var->bits_per_pixel = ovl->format->bpp;
-+ else
-+ var->grayscale = ovl->format->fourcc;
-+
-+ return sh_mobile_lcdc_overlay_check_var(var, info);
-+}
-+
- /* -----------------------------------------------------------------------------
-- * Frame buffer operations
-+ * Frame buffer operations - main frame buffer
- */
-
- static int sh_mobile_lcdc_setcolreg(u_int regno,
-@@ -1202,9 +1970,7 @@ static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
- unsigned int best_xres = 0;
- unsigned int best_yres = 0;
- unsigned int i;
--
-- if (var->xres > MAX_XRES || var->yres > MAX_YRES)
-- return -EINVAL;
-+ int ret;
-
- /* If board code provides us with a list of available modes, make sure
- * we use one of them. Find the mode closest to the requested one. The
-@@ -1239,73 +2005,9 @@ static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
- var->yres = best_yres;
- }
-
-- /* Make sure the virtual resolution is at least as big as the visible
-- * resolution.
-- */
-- if (var->xres_virtual < var->xres)
-- var->xres_virtual = var->xres;
-- if (var->yres_virtual < var->yres)
-- var->yres_virtual = var->yres;
--
-- if (sh_mobile_format_is_fourcc(var)) {
-- const struct sh_mobile_lcdc_format_info *format;
--
-- format = sh_mobile_format_info(var->grayscale);
-- if (format == NULL)
-- return -EINVAL;
-- var->bits_per_pixel = format->bpp;
--
-- /* Default to RGB and JPEG color-spaces for RGB and YUV formats
-- * respectively.
-- */
-- if (!format->yuv)
-- var->colorspace = V4L2_COLORSPACE_SRGB;
-- else if (var->colorspace != V4L2_COLORSPACE_REC709)
-- var->colorspace = V4L2_COLORSPACE_JPEG;
-- } else {
-- if (var->bits_per_pixel <= 16) { /* RGB 565 */
-- var->bits_per_pixel = 16;
-- var->red.offset = 11;
-- var->red.length = 5;
-- var->green.offset = 5;
-- var->green.length = 6;
-- var->blue.offset = 0;
-- var->blue.length = 5;
-- var->transp.offset = 0;
-- var->transp.length = 0;
-- } else if (var->bits_per_pixel <= 24) { /* RGB 888 */
-- var->bits_per_pixel = 24;
-- var->red.offset = 16;
-- var->red.length = 8;
-- var->green.offset = 8;
-- var->green.length = 8;
-- var->blue.offset = 0;
-- var->blue.length = 8;
-- var->transp.offset = 0;
-- var->transp.length = 0;
-- } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */
-- var->bits_per_pixel = 32;
-- var->red.offset = 16;
-- var->red.length = 8;
-- var->green.offset = 8;
-- var->green.length = 8;
-- var->blue.offset = 0;
-- var->blue.length = 8;
-- var->transp.offset = 24;
-- var->transp.length = 8;
-- } else
-- return -EINVAL;
--
-- var->red.msb_right = 0;
-- var->green.msb_right = 0;
-- var->blue.msb_right = 0;
-- var->transp.msb_right = 0;
-- }
--
-- /* Make sure we don't exceed our allocated memory. */
-- if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
-- info->fix.smem_len)
-- return -EINVAL;
-+ ret = __sh_mobile_lcdc_check_var(var, info);
-+ if (ret < 0)
-+ return ret;
-
- /* only accept the forced_fourcc for dual channel configurations */
- if (p->forced_fourcc &&
-@@ -1714,15 +2416,27 @@ static const struct fb_videomode default_720p __devinitconst = {
- static int sh_mobile_lcdc_remove(struct platform_device *pdev)
- {
- struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
-- int i;
-+ unsigned int i;
-
- fb_unregister_client(&priv->notifier);
-
-+ for (i = 0; i < ARRAY_SIZE(priv->overlays); i++)
-+ sh_mobile_lcdc_overlay_fb_unregister(&priv->overlays[i]);
- for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
- sh_mobile_lcdc_channel_fb_unregister(&priv->ch[i]);
-
- sh_mobile_lcdc_stop(priv);
-
-+ for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) {
-+ struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
-+
-+ sh_mobile_lcdc_overlay_fb_cleanup(ovl);
-+
-+ if (ovl->fb_mem)
-+ dma_free_coherent(&pdev->dev, ovl->fb_size,
-+ ovl->fb_mem, ovl->dma_handle);
-+ }
-+
- for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
- struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
-
-@@ -1798,6 +2512,61 @@ static int __devinit sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *
- }
-
- static int __devinit
-+sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
-+ struct sh_mobile_lcdc_overlay *ovl)
-+{
-+ const struct sh_mobile_lcdc_format_info *format;
-+ int ret;
-+
-+ if (ovl->cfg->fourcc == 0)
-+ return 0;
-+
-+ /* Validate the format. */
-+ format = sh_mobile_format_info(ovl->cfg->fourcc);
-+ if (format == NULL) {
-+ dev_err(priv->dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc);
-+ return -EINVAL;
-+ }
-+
-+ ovl->enabled = false;
-+ ovl->mode = LCDC_OVERLAY_BLEND;
-+ ovl->alpha = 255;
-+ ovl->rop3 = 0;
-+ ovl->pos_x = 0;
-+ ovl->pos_y = 0;
-+
-+ /* The default Y virtual resolution is twice the panel size to allow for
-+ * double-buffering.
-+ */
-+ ovl->format = format;
-+ ovl->xres = ovl->cfg->max_xres;
-+ ovl->xres_virtual = ovl->xres;
-+ ovl->yres = ovl->cfg->max_yres;
-+ ovl->yres_virtual = ovl->yres * 2;
-+
-+ if (!format->yuv)
-+ ovl->pitch = ovl->xres * format->bpp / 8;
-+ else
-+ ovl->pitch = ovl->xres;
-+
-+ /* Allocate frame buffer memory. */
-+ ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres
-+ * format->bpp / 8 * 2;
-+ ovl->fb_mem = dma_alloc_coherent(priv->dev, ovl->fb_size,
-+ &ovl->dma_handle, GFP_KERNEL);
-+ if (!ovl->fb_mem) {
-+ dev_err(priv->dev, "unable to allocate buffer\n");
-+ return -ENOMEM;
-+ }
-+
-+ ret = sh_mobile_lcdc_overlay_fb_init(ovl);
-+ if (ret < 0)
-+ return ret;
-+
-+ return 0;
-+}
-+
-+static int __devinit
- sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
- struct sh_mobile_lcdc_chan *ch)
- {
-@@ -2005,6 +2774,17 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
- goto err1;
- }
-
-+ for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) {
-+ struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
-+
-+ ovl->cfg = &pdata->overlays[i];
-+ ovl->channel = &priv->ch[0];
-+
-+ error = sh_mobile_lcdc_overlay_init(priv, ovl);
-+ if (error)
-+ goto err1;
-+ }
-+
- error = sh_mobile_lcdc_start(priv);
- if (error) {
- dev_err(&pdev->dev, "unable to start hardware\n");
-@@ -2019,6 +2799,14 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
- goto err1;
- }
-
-+ for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) {
-+ struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
-+
-+ error = sh_mobile_lcdc_overlay_fb_register(ovl);
-+ if (error)
-+ goto err1;
-+ }
-+
- /* Failure ignored */
- priv->notifier.notifier_call = sh_mobile_lcdc_notify;
- fb_register_client(&priv->notifier);
-diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
-index 7571b27..ff43ffc 100644
---- a/include/video/sh_mobile_lcdc.h
-+++ b/include/video/sh_mobile_lcdc.h
-@@ -166,6 +166,12 @@ struct sh_mobile_lcdc_bl_info {
- int (*get_brightness)(void);
- };
-
-+struct sh_mobile_lcdc_overlay_cfg {
-+ int fourcc;
-+ unsigned int max_xres;
-+ unsigned int max_yres;
-+};
-+
- struct sh_mobile_lcdc_chan_cfg {
- int chan;
- int fourcc;
-@@ -186,6 +192,7 @@ struct sh_mobile_lcdc_chan_cfg {
- struct sh_mobile_lcdc_info {
- int clock_source;
- struct sh_mobile_lcdc_chan_cfg ch[2];
-+ struct sh_mobile_lcdc_overlay_cfg overlays[4];
- struct sh_mobile_meram_info *meram_dev;
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 5175271a2ba2d97d73adadcaca3ba6b6616b6f23 Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Thu, 15 Mar 2012 12:40:47 +0100
-Subject: sh_mobile_meram: Rename operations to cache_[alloc|free|update]
-
-The MERAM operations meram_register, meram_unregister and meram_update
-handle LCDC cache. In preparation for "raw" MERAM allocation, rename
-them to more appropriate names.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-(cherry picked from commit 4a2371772146b30113c9c837eb32b64f18376c0d)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_lcdcfb.c | 32 ++++---
- drivers/video/sh_mobile_lcdcfb.h | 2 +-
- drivers/video/sh_mobile_meram.c | 176 +++++++++++++++++++--------------------
- include/video/sh_mobile_meram.h | 21 ++---
- 4 files changed, 110 insertions(+), 121 deletions(-)
-
-diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
-index 98e81b3..e593e81 100644
---- a/drivers/video/sh_mobile_lcdcfb.c
-+++ b/drivers/video/sh_mobile_lcdcfb.c
-@@ -1104,7 +1104,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
- /* Compute frame buffer base address and pitch for each channel. */
- for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
- int pixelformat;
-- void *meram;
-+ void *cache;
-
- ch = &priv->ch[k];
- if (!ch->enabled)
-@@ -1119,12 +1119,10 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
- ch->cfg->meram_cfg == NULL)
- continue;
-
-- /* we need to de-init configured ICBs before we can
-- * re-initialize them.
-- */
-- if (ch->meram) {
-- mdev->ops->meram_unregister(mdev, ch->meram);
-- ch->meram = NULL;
-+ /* Free the allocated MERAM cache. */
-+ if (ch->cache) {
-+ mdev->ops->cache_free(mdev, ch->cache);
-+ ch->cache = NULL;
- }
-
- switch (ch->format->fourcc) {
-@@ -1146,14 +1144,14 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
- break;
- }
-
-- meram = mdev->ops->meram_register(mdev, ch->cfg->meram_cfg,
-+ cache = mdev->ops->cache_alloc(mdev, ch->cfg->meram_cfg,
- ch->pitch, ch->yres, pixelformat,
- &ch->line_size);
-- if (!IS_ERR(meram)) {
-- mdev->ops->meram_update(mdev, meram,
-+ if (!IS_ERR(cache)) {
-+ mdev->ops->cache_update(mdev, cache,
- ch->base_addr_y, ch->base_addr_c,
- &ch->base_addr_y, &ch->base_addr_c);
-- ch->meram = meram;
-+ ch->cache = cache;
- }
- }
-
-@@ -1223,12 +1221,12 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
-
- sh_mobile_lcdc_display_off(ch);
-
-- /* disable the meram */
-- if (ch->meram) {
-+ /* Free the MERAM cache. */
-+ if (ch->cache) {
- struct sh_mobile_meram_info *mdev;
- mdev = priv->meram_dev;
-- mdev->ops->meram_unregister(mdev, ch->meram);
-- ch->meram = 0;
-+ mdev->ops->cache_free(mdev, ch->cache);
-+ ch->cache = 0;
- }
-
- }
-@@ -1839,11 +1837,11 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
- base_addr_c += var->xoffset;
- }
-
-- if (ch->meram) {
-+ if (ch->cache) {
- struct sh_mobile_meram_info *mdev;
-
- mdev = priv->meram_dev;
-- mdev->ops->meram_update(mdev, ch->meram,
-+ mdev->ops->cache_update(mdev, ch->cache,
- base_addr_y, base_addr_c,
- &base_addr_y, &base_addr_c);
- }
-diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
-index 5c3bddd..e53cd11 100644
---- a/drivers/video/sh_mobile_lcdcfb.h
-+++ b/drivers/video/sh_mobile_lcdcfb.h
-@@ -59,7 +59,7 @@ struct sh_mobile_lcdc_chan {
- unsigned long *reg_offs;
- unsigned long ldmt1r_value;
- unsigned long enabled; /* ME and SE in LDCNT2R */
-- void *meram;
-+ void *cache;
-
- struct mutex open_lock; /* protects the use counter */
- int use_count;
-diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
-index 82ba830..4aa3fcb 100644
---- a/drivers/video/sh_mobile_meram.c
-+++ b/drivers/video/sh_mobile_meram.c
-@@ -194,13 +194,13 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
- }
-
- /* -----------------------------------------------------------------------------
-- * Allocation
-+ * LCDC cache planes allocation, init, cleanup and free
- */
-
- /* Allocate ICBs and MERAM for a plane. */
--static int __meram_alloc(struct sh_mobile_meram_priv *priv,
-- struct sh_mobile_meram_fb_plane *plane,
-- size_t size)
-+static int meram_plane_alloc(struct sh_mobile_meram_priv *priv,
-+ struct sh_mobile_meram_fb_plane *plane,
-+ size_t size)
- {
- unsigned long mem;
- unsigned long idx;
-@@ -229,8 +229,8 @@ static int __meram_alloc(struct sh_mobile_meram_priv *priv,
- }
-
- /* Free ICBs and MERAM for a plane. */
--static void __meram_free(struct sh_mobile_meram_priv *priv,
-- struct sh_mobile_meram_fb_plane *plane)
-+static void meram_plane_free(struct sh_mobile_meram_priv *priv,
-+ struct sh_mobile_meram_fb_plane *plane)
- {
- gen_pool_free(priv->pool, priv->meram + plane->marker->offset,
- plane->marker->size * 1024);
-@@ -248,62 +248,6 @@ static int is_nvcolor(int cspace)
- return 0;
- }
-
--/* Allocate memory for the ICBs and mark them as used. */
--static struct sh_mobile_meram_fb_cache *
--meram_alloc(struct sh_mobile_meram_priv *priv,
-- const struct sh_mobile_meram_cfg *cfg,
-- int pixelformat)
--{
-- struct sh_mobile_meram_fb_cache *cache;
-- unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
-- int ret;
--
-- if (cfg->icb[0].meram_size == 0)
-- return ERR_PTR(-EINVAL);
--
-- if (nplanes == 2 && cfg->icb[1].meram_size == 0)
-- return ERR_PTR(-EINVAL);
--
-- cache = kzalloc(sizeof(*cache), GFP_KERNEL);
-- if (cache == NULL)
-- return ERR_PTR(-ENOMEM);
--
-- cache->nplanes = nplanes;
--
-- ret = __meram_alloc(priv, &cache->planes[0], cfg->icb[0].meram_size);
-- if (ret < 0)
-- goto error;
--
-- cache->planes[0].marker->current_reg = 1;
-- cache->planes[0].marker->pixelformat = pixelformat;
--
-- if (cache->nplanes == 1)
-- return cache;
--
-- ret = __meram_alloc(priv, &cache->planes[1], cfg->icb[1].meram_size);
-- if (ret < 0) {
-- __meram_free(priv, &cache->planes[0]);
-- goto error;
-- }
--
-- return cache;
--
--error:
-- kfree(cache);
-- return ERR_PTR(-ENOMEM);
--}
--
--/* Unmark the specified ICB as used. */
--static void meram_free(struct sh_mobile_meram_priv *priv,
-- struct sh_mobile_meram_fb_cache *cache)
--{
-- __meram_free(priv, &cache->planes[0]);
-- if (cache->nplanes == 2)
-- __meram_free(priv, &cache->planes[1]);
--
-- kfree(cache);
--}
--
- /* Set the next address to fetch. */
- static void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
- struct sh_mobile_meram_fb_cache *cache,
-@@ -355,10 +299,10 @@ meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
- (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1))
-
- /* Initialize MERAM. */
--static int meram_init(struct sh_mobile_meram_priv *priv,
-- struct sh_mobile_meram_fb_plane *plane,
-- unsigned int xres, unsigned int yres,
-- unsigned int *out_pitch)
-+static int meram_plane_init(struct sh_mobile_meram_priv *priv,
-+ struct sh_mobile_meram_fb_plane *plane,
-+ unsigned int xres, unsigned int yres,
-+ unsigned int *out_pitch)
- {
- struct sh_mobile_meram_icb *marker = plane->marker;
- unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres);
-@@ -427,8 +371,8 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
- return 0;
- }
-
--static void meram_deinit(struct sh_mobile_meram_priv *priv,
-- struct sh_mobile_meram_fb_plane *plane)
-+static void meram_plane_cleanup(struct sh_mobile_meram_priv *priv,
-+ struct sh_mobile_meram_fb_plane *plane)
- {
- /* disable ICB */
- meram_write_icb(priv->base, plane->cache->index, MExxCTL,
-@@ -441,18 +385,60 @@ static void meram_deinit(struct sh_mobile_meram_priv *priv,
- }
-
- /* -----------------------------------------------------------------------------
-- * Registration/unregistration
-+ * LCDC cache operations
- */
-
--static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
-- const struct sh_mobile_meram_cfg *cfg,
-- unsigned int xres, unsigned int yres,
-- unsigned int pixelformat,
-- unsigned int *pitch)
-+/* Allocate memory for the ICBs and mark them as used. */
-+static struct sh_mobile_meram_fb_cache *
-+meram_cache_alloc(struct sh_mobile_meram_priv *priv,
-+ const struct sh_mobile_meram_cfg *cfg,
-+ int pixelformat)
-+{
-+ unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
-+ struct sh_mobile_meram_fb_cache *cache;
-+ int ret;
-+
-+ cache = kzalloc(sizeof(*cache), GFP_KERNEL);
-+ if (cache == NULL)
-+ return ERR_PTR(-ENOMEM);
-+
-+ cache->nplanes = nplanes;
-+
-+ ret = meram_plane_alloc(priv, &cache->planes[0],
-+ cfg->icb[0].meram_size);
-+ if (ret < 0)
-+ goto error;
-+
-+ cache->planes[0].marker->current_reg = 1;
-+ cache->planes[0].marker->pixelformat = pixelformat;
-+
-+ if (cache->nplanes == 1)
-+ return cache;
-+
-+ ret = meram_plane_alloc(priv, &cache->planes[1],
-+ cfg->icb[1].meram_size);
-+ if (ret < 0) {
-+ meram_plane_free(priv, &cache->planes[0]);
-+ goto error;
-+ }
-+
-+ return cache;
-+
-+error:
-+ kfree(cache);
-+ return ERR_PTR(-ENOMEM);
-+}
-+
-+static void *sh_mobile_cache_alloc(struct sh_mobile_meram_info *pdata,
-+ const struct sh_mobile_meram_cfg *cfg,
-+ unsigned int xres, unsigned int yres,
-+ unsigned int pixelformat,
-+ unsigned int *pitch)
- {
- struct sh_mobile_meram_fb_cache *cache;
- struct sh_mobile_meram_priv *priv = pdata->priv;
- struct platform_device *pdev = pdata->pdev;
-+ unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
- unsigned int out_pitch;
-
- if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
-@@ -469,10 +455,16 @@ static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
- return ERR_PTR(-EINVAL);
- }
-
-+ if (cfg->icb[0].meram_size == 0)
-+ return ERR_PTR(-EINVAL);
-+
-+ if (nplanes == 2 && cfg->icb[1].meram_size == 0)
-+ return ERR_PTR(-EINVAL);
-+
- mutex_lock(&priv->lock);
-
- /* We now register the ICBs and allocate the MERAM regions. */
-- cache = meram_alloc(priv, cfg, pixelformat);
-+ cache = meram_cache_alloc(priv, cfg, pixelformat);
- if (IS_ERR(cache)) {
- dev_err(&pdev->dev, "MERAM allocation failed (%ld).",
- PTR_ERR(cache));
-@@ -480,14 +472,14 @@ static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
- }
-
- /* initialize MERAM */
-- meram_init(priv, &cache->planes[0], xres, yres, &out_pitch);
-+ meram_plane_init(priv, &cache->planes[0], xres, yres, &out_pitch);
- *pitch = out_pitch;
- if (pixelformat == SH_MOBILE_MERAM_PF_NV)
-- meram_init(priv, &cache->planes[1], xres, (yres + 1) / 2,
-- &out_pitch);
-+ meram_plane_init(priv, &cache->planes[1],
-+ xres, (yres + 1) / 2, &out_pitch);
- else if (pixelformat == SH_MOBILE_MERAM_PF_NV24)
-- meram_init(priv, &cache->planes[1], 2 * xres, (yres + 1) / 2,
-- &out_pitch);
-+ meram_plane_init(priv, &cache->planes[1],
-+ 2 * xres, (yres + 1) / 2, &out_pitch);
-
- err:
- mutex_unlock(&priv->lock);
-@@ -495,25 +487,29 @@ err:
- }
-
- static void
--sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata, void *data)
-+sh_mobile_cache_free(struct sh_mobile_meram_info *pdata, void *data)
- {
- struct sh_mobile_meram_fb_cache *cache = data;
- struct sh_mobile_meram_priv *priv = pdata->priv;
-
- mutex_lock(&priv->lock);
-
-- /* deinit & free */
-- meram_deinit(priv, &cache->planes[0]);
-- if (cache->nplanes == 2)
-- meram_deinit(priv, &cache->planes[1]);
-+ /* Cleanup and free. */
-+ meram_plane_cleanup(priv, &cache->planes[0]);
-+ meram_plane_free(priv, &cache->planes[0]);
-
-- meram_free(priv, cache);
-+ if (cache->nplanes == 2) {
-+ meram_plane_cleanup(priv, &cache->planes[1]);
-+ meram_plane_free(priv, &cache->planes[1]);
-+ }
-+
-+ kfree(cache);
-
- mutex_unlock(&priv->lock);
- }
-
- static void
--sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data,
-+sh_mobile_cache_update(struct sh_mobile_meram_info *pdata, void *data,
- unsigned long base_addr_y, unsigned long base_addr_c,
- unsigned long *icb_addr_y, unsigned long *icb_addr_c)
- {
-@@ -530,9 +526,9 @@ sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data,
-
- static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
- .module = THIS_MODULE,
-- .meram_register = sh_mobile_meram_register,
-- .meram_unregister = sh_mobile_meram_unregister,
-- .meram_update = sh_mobile_meram_update,
-+ .cache_alloc = sh_mobile_cache_alloc,
-+ .cache_free = sh_mobile_cache_free,
-+ .cache_update = sh_mobile_cache_update,
- };
-
- /* -----------------------------------------------------------------------------
-diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
-index 29b2fd3..8a5afaf 100644
---- a/include/video/sh_mobile_meram.h
-+++ b/include/video/sh_mobile_meram.h
-@@ -41,19 +41,14 @@ struct sh_mobile_meram_cfg {
- struct module;
- struct sh_mobile_meram_ops {
- struct module *module;
-- /* register usage of meram */
-- void *(*meram_register)(struct sh_mobile_meram_info *meram_dev,
-- const struct sh_mobile_meram_cfg *cfg,
-- unsigned int xres, unsigned int yres,
-- unsigned int pixelformat,
-- unsigned int *pitch);
--
-- /* unregister usage of meram */
-- void (*meram_unregister)(struct sh_mobile_meram_info *meram_dev,
-- void *data);
--
-- /* update meram settings */
-- void (*meram_update)(struct sh_mobile_meram_info *meram_dev, void *data,
-+
-+ /* LCDC cache management */
-+ void *(*cache_alloc)(struct sh_mobile_meram_info *meram_dev,
-+ const struct sh_mobile_meram_cfg *cfg,
-+ unsigned int xres, unsigned int yres,
-+ unsigned int pixelformat, unsigned int *pitch);
-+ void (*cache_free)(struct sh_mobile_meram_info *meram_dev, void *data);
-+ void (*cache_update)(struct sh_mobile_meram_info *meram_dev, void *data,
- unsigned long base_addr_y,
- unsigned long base_addr_c,
- unsigned long *icb_addr_y,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b8fe39bce6f2c38cfa04299077173aff50600687 Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Thu, 15 Mar 2012 12:40:47 +0100
-Subject: sh_mobile_meram: Use direct function calls for the public API
-
-There's no reason to use abstract operation pointers to implement the
-MERAM API. Replace them by direct function calls.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-(cherry picked from commit 6e729b416b44296f5ed503b40ac58c2bffb43caf)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_lcdcfb.c | 27 ++++++++--------------
- drivers/video/sh_mobile_meram.c | 40 ++++++++++++++++----------------
- include/video/sh_mobile_meram.h | 50 ++++++++++++++++++++++++++++------------
- 3 files changed, 65 insertions(+), 52 deletions(-)
-
-diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
-index e593e81..9da4b1b6 100644
---- a/drivers/video/sh_mobile_lcdcfb.c
-+++ b/drivers/video/sh_mobile_lcdcfb.c
-@@ -1115,13 +1115,12 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
- ch->line_size = ch->pitch;
-
- /* Enable MERAM if possible. */
-- if (mdev == NULL || mdev->ops == NULL ||
-- ch->cfg->meram_cfg == NULL)
-+ if (mdev == NULL || ch->cfg->meram_cfg == NULL)
- continue;
-
- /* Free the allocated MERAM cache. */
- if (ch->cache) {
-- mdev->ops->cache_free(mdev, ch->cache);
-+ sh_mobile_meram_cache_free(mdev, ch->cache);
- ch->cache = NULL;
- }
-
-@@ -1144,11 +1143,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
- break;
- }
-
-- cache = mdev->ops->cache_alloc(mdev, ch->cfg->meram_cfg,
-+ cache = sh_mobile_meram_cache_alloc(mdev, ch->cfg->meram_cfg,
- ch->pitch, ch->yres, pixelformat,
- &ch->line_size);
- if (!IS_ERR(cache)) {
-- mdev->ops->cache_update(mdev, cache,
-+ sh_mobile_meram_cache_update(mdev, cache,
- ch->base_addr_y, ch->base_addr_c,
- &ch->base_addr_y, &ch->base_addr_c);
- ch->cache = cache;
-@@ -1223,9 +1222,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
-
- /* Free the MERAM cache. */
- if (ch->cache) {
-- struct sh_mobile_meram_info *mdev;
-- mdev = priv->meram_dev;
-- mdev->ops->cache_free(mdev, ch->cache);
-+ sh_mobile_meram_cache_free(priv->meram_dev, ch->cache);
- ch->cache = 0;
- }
-
-@@ -1808,7 +1805,7 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
- struct sh_mobile_lcdc_priv *priv = ch->lcdc;
- unsigned long ldrcntr;
- unsigned long new_pan_offset;
-- unsigned long base_addr_y, base_addr_c;
-+ unsigned long base_addr_y, base_addr_c = 0;
- unsigned long c_offset;
-
- if (!ch->format->yuv)
-@@ -1837,14 +1834,10 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
- base_addr_c += var->xoffset;
- }
-
-- if (ch->cache) {
-- struct sh_mobile_meram_info *mdev;
--
-- mdev = priv->meram_dev;
-- mdev->ops->cache_update(mdev, ch->cache,
-- base_addr_y, base_addr_c,
-- &base_addr_y, &base_addr_c);
-- }
-+ if (ch->cache)
-+ sh_mobile_meram_cache_update(priv->meram_dev, ch->cache,
-+ base_addr_y, base_addr_c,
-+ &base_addr_y, &base_addr_c);
-
- ch->base_addr_y = base_addr_y;
- ch->base_addr_c = base_addr_c;
-diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
-index 4aa3fcb..fdb6fc1 100644
---- a/drivers/video/sh_mobile_meram.c
-+++ b/drivers/video/sh_mobile_meram.c
-@@ -11,6 +11,7 @@
-
- #include <linux/device.h>
- #include <linux/err.h>
-+#include <linux/export.h>
- #include <linux/genalloc.h>
- #include <linux/io.h>
- #include <linux/kernel.h>
-@@ -429,11 +430,10 @@ error:
- return ERR_PTR(-ENOMEM);
- }
-
--static void *sh_mobile_cache_alloc(struct sh_mobile_meram_info *pdata,
-- const struct sh_mobile_meram_cfg *cfg,
-- unsigned int xres, unsigned int yres,
-- unsigned int pixelformat,
-- unsigned int *pitch)
-+void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *pdata,
-+ const struct sh_mobile_meram_cfg *cfg,
-+ unsigned int xres, unsigned int yres,
-+ unsigned int pixelformat, unsigned int *pitch)
- {
- struct sh_mobile_meram_fb_cache *cache;
- struct sh_mobile_meram_priv *priv = pdata->priv;
-@@ -441,6 +441,9 @@ static void *sh_mobile_cache_alloc(struct sh_mobile_meram_info *pdata,
- unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
- unsigned int out_pitch;
-
-+ if (priv == NULL)
-+ return ERR_PTR(-ENODEV);
-+
- if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
- pixelformat != SH_MOBILE_MERAM_PF_NV24 &&
- pixelformat != SH_MOBILE_MERAM_PF_RGB)
-@@ -485,9 +488,10 @@ err:
- mutex_unlock(&priv->lock);
- return cache;
- }
-+EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_alloc);
-
--static void
--sh_mobile_cache_free(struct sh_mobile_meram_info *pdata, void *data)
-+void
-+sh_mobile_meram_cache_free(struct sh_mobile_meram_info *pdata, void *data)
- {
- struct sh_mobile_meram_fb_cache *cache = data;
- struct sh_mobile_meram_priv *priv = pdata->priv;
-@@ -507,11 +511,14 @@ sh_mobile_cache_free(struct sh_mobile_meram_info *pdata, void *data)
-
- mutex_unlock(&priv->lock);
- }
--
--static void
--sh_mobile_cache_update(struct sh_mobile_meram_info *pdata, void *data,
-- unsigned long base_addr_y, unsigned long base_addr_c,
-- unsigned long *icb_addr_y, unsigned long *icb_addr_c)
-+EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_free);
-+
-+void
-+sh_mobile_meram_cache_update(struct sh_mobile_meram_info *pdata, void *data,
-+ unsigned long base_addr_y,
-+ unsigned long base_addr_c,
-+ unsigned long *icb_addr_y,
-+ unsigned long *icb_addr_c)
- {
- struct sh_mobile_meram_fb_cache *cache = data;
- struct sh_mobile_meram_priv *priv = pdata->priv;
-@@ -523,13 +530,7 @@ sh_mobile_cache_update(struct sh_mobile_meram_info *pdata, void *data,
-
- mutex_unlock(&priv->lock);
- }
--
--static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
-- .module = THIS_MODULE,
-- .cache_alloc = sh_mobile_cache_alloc,
-- .cache_free = sh_mobile_cache_free,
-- .cache_update = sh_mobile_cache_update,
--};
-+EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_update);
-
- /* -----------------------------------------------------------------------------
- * Power management
-@@ -620,7 +621,6 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
- for (i = 0; i < MERAM_ICB_NUM; ++i)
- priv->icbs[i].index = i;
-
-- pdata->ops = &sh_mobile_meram_ops;
- pdata->priv = priv;
- pdata->pdev = pdev;
-
-diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
-index 8a5afaf..1134837 100644
---- a/include/video/sh_mobile_meram.h
-+++ b/include/video/sh_mobile_meram.h
-@@ -15,7 +15,6 @@ enum {
-
-
- struct sh_mobile_meram_priv;
--struct sh_mobile_meram_ops;
-
- /*
- * struct sh_mobile_meram_info - MERAM platform data
-@@ -24,7 +23,6 @@ struct sh_mobile_meram_ops;
- struct sh_mobile_meram_info {
- int addr_mode;
- u32 reserved_icbs;
-- struct sh_mobile_meram_ops *ops;
- struct sh_mobile_meram_priv *priv;
- struct platform_device *pdev;
- };
-@@ -38,21 +36,43 @@ struct sh_mobile_meram_cfg {
- struct sh_mobile_meram_icb_cfg icb[2];
- };
-
--struct module;
--struct sh_mobile_meram_ops {
-- struct module *module;
--
-- /* LCDC cache management */
-- void *(*cache_alloc)(struct sh_mobile_meram_info *meram_dev,
-- const struct sh_mobile_meram_cfg *cfg,
-- unsigned int xres, unsigned int yres,
-- unsigned int pixelformat, unsigned int *pitch);
-- void (*cache_free)(struct sh_mobile_meram_info *meram_dev, void *data);
-- void (*cache_update)(struct sh_mobile_meram_info *meram_dev, void *data,
-+#if defined(CONFIG_FB_SH_MOBILE_MERAM) || \
-+ defined(CONFIG_FB_SH_MOBILE_MERAM_MODULE)
-+void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev,
-+ const struct sh_mobile_meram_cfg *cfg,
-+ unsigned int xres, unsigned int yres,
-+ unsigned int pixelformat,
-+ unsigned int *pitch);
-+void sh_mobile_meram_cache_free(struct sh_mobile_meram_info *dev, void *data);
-+void sh_mobile_meram_cache_update(struct sh_mobile_meram_info *dev, void *data,
-+ unsigned long base_addr_y,
-+ unsigned long base_addr_c,
-+ unsigned long *icb_addr_y,
-+ unsigned long *icb_addr_c);
-+#else
-+static inline void *
-+sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev,
-+ const struct sh_mobile_meram_cfg *cfg,
-+ unsigned int xres, unsigned int yres,
-+ unsigned int pixelformat,
-+ unsigned int *pitch)
-+{
-+ return ERR_PTR(-ENODEV);
-+}
-+
-+static inline void
-+sh_mobile_meram_cache_free(struct sh_mobile_meram_info *dev, void *data)
-+{
-+}
-+
-+static inline void
-+sh_mobile_meram_cache_update(struct sh_mobile_meram_info *dev, void *data,
- unsigned long base_addr_y,
- unsigned long base_addr_c,
- unsigned long *icb_addr_y,
-- unsigned long *icb_addr_c);
--};
-+ unsigned long *icb_addr_c)
-+{
-+}
-+#endif
-
- #endif /* __VIDEO_SH_MOBILE_MERAM_H__ */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 81c446ad9189a068ef555c436c96d651dc86c4da Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Thu, 15 Mar 2012 13:18:17 +0100
-Subject: sh_mobile_meram: Add direct MERAM allocation API
-
-The API can be used to allocate and free MERAM blocks directly, without
-going through ICBs.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-(cherry picked from commit 239921ec1d969e904676f444a92e6d68a928d98c)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_meram.c | 41 +++++++++++++++++++++++++++++++++++++----
- include/video/sh_mobile_meram.h | 16 ++++++++++++++++
- 2 files changed, 53 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
-index fdb6fc1..7a0ba8b 100644
---- a/drivers/video/sh_mobile_meram.c
-+++ b/drivers/video/sh_mobile_meram.c
-@@ -195,6 +195,21 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
- }
-
- /* -----------------------------------------------------------------------------
-+ * MERAM allocation and free
-+ */
-+
-+static unsigned long meram_alloc(struct sh_mobile_meram_priv *priv, size_t size)
-+{
-+ return gen_pool_alloc(priv->pool, size);
-+}
-+
-+static void meram_free(struct sh_mobile_meram_priv *priv, unsigned long mem,
-+ size_t size)
-+{
-+ gen_pool_free(priv->pool, mem, size);
-+}
-+
-+/* -----------------------------------------------------------------------------
- * LCDC cache planes allocation, init, cleanup and free
- */
-
-@@ -216,7 +231,7 @@ static int meram_plane_alloc(struct sh_mobile_meram_priv *priv,
- return -ENOMEM;
- plane->marker = &priv->icbs[idx];
-
-- mem = gen_pool_alloc(priv->pool, size * 1024);
-+ mem = meram_alloc(priv, size * 1024);
- if (mem == 0)
- return -ENOMEM;
-
-@@ -233,8 +248,8 @@ static int meram_plane_alloc(struct sh_mobile_meram_priv *priv,
- static void meram_plane_free(struct sh_mobile_meram_priv *priv,
- struct sh_mobile_meram_fb_plane *plane)
- {
-- gen_pool_free(priv->pool, priv->meram + plane->marker->offset,
-- plane->marker->size * 1024);
-+ meram_free(priv, priv->meram + plane->marker->offset,
-+ plane->marker->size * 1024);
-
- __clear_bit(plane->marker->index, &priv->used_icb);
- __clear_bit(plane->cache->index, &priv->used_icb);
-@@ -386,9 +401,27 @@ static void meram_plane_cleanup(struct sh_mobile_meram_priv *priv,
- }
-
- /* -----------------------------------------------------------------------------
-- * LCDC cache operations
-+ * MERAM operations
- */
-
-+unsigned long sh_mobile_meram_alloc(struct sh_mobile_meram_info *pdata,
-+ size_t size)
-+{
-+ struct sh_mobile_meram_priv *priv = pdata->priv;
-+
-+ return meram_alloc(priv, size);
-+}
-+EXPORT_SYMBOL_GPL(sh_mobile_meram_alloc);
-+
-+void sh_mobile_meram_free(struct sh_mobile_meram_info *pdata, unsigned long mem,
-+ size_t size)
-+{
-+ struct sh_mobile_meram_priv *priv = pdata->priv;
-+
-+ meram_free(priv, mem, size);
-+}
-+EXPORT_SYMBOL_GPL(sh_mobile_meram_free);
-+
- /* Allocate memory for the ICBs and mark them as used. */
- static struct sh_mobile_meram_fb_cache *
- meram_cache_alloc(struct sh_mobile_meram_priv *priv,
-diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
-index 1134837..062e6e7 100644
---- a/include/video/sh_mobile_meram.h
-+++ b/include/video/sh_mobile_meram.h
-@@ -38,6 +38,10 @@ struct sh_mobile_meram_cfg {
-
- #if defined(CONFIG_FB_SH_MOBILE_MERAM) || \
- defined(CONFIG_FB_SH_MOBILE_MERAM_MODULE)
-+unsigned long sh_mobile_meram_alloc(struct sh_mobile_meram_info *meram_dev,
-+ size_t size);
-+void sh_mobile_meram_free(struct sh_mobile_meram_info *meram_dev,
-+ unsigned long mem, size_t size);
- void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev,
- const struct sh_mobile_meram_cfg *cfg,
- unsigned int xres, unsigned int yres,
-@@ -50,6 +54,18 @@ void sh_mobile_meram_cache_update(struct sh_mobile_meram_info *dev, void *data,
- unsigned long *icb_addr_y,
- unsigned long *icb_addr_c);
- #else
-+static inline unsigned long
-+sh_mobile_meram_alloc(struct sh_mobile_meram_info *meram_dev, size_t size)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+sh_mobile_meram_free(struct sh_mobile_meram_info *meram_dev,
-+ unsigned long mem, size_t size)
-+{
-+}
-+
- static inline void *
- sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev,
- const struct sh_mobile_meram_cfg *cfg,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From fbcfe8a409c3a0177d599e2b6a73a70fd4dffc8a Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Thu, 15 Mar 2012 18:34:05 +0100
-Subject: fbdev: sh_mobile_lcdc: Destroy mutex at remove time
-
-Add a missing mutex_destroy() call when the driver is unbound from the
-device.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-(cherry picked from commit 0c75c4e073a8ec35bfd6c8adcceb2b896f2063e2)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_lcdcfb.c | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
-index 9da4b1b6..644c230 100644
---- a/drivers/video/sh_mobile_lcdcfb.c
-+++ b/drivers/video/sh_mobile_lcdcfb.c
-@@ -2444,8 +2444,11 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
- }
-
- for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
-- if (priv->ch[i].bl)
-- sh_mobile_lcdc_bl_remove(priv->ch[i].bl);
-+ struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
-+
-+ if (ch->bl)
-+ sh_mobile_lcdc_bl_remove(ch->bl);
-+ mutex_destroy(&ch->open_lock);
- }
-
- if (priv->dot_clk) {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 8a18c739cb6639c5b8e43cc19929f98c532afae7 Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Wed, 18 Jul 2012 16:29:20 +0200
-Subject: fbdev: sh_mobile_lcdc: Fix line pitch computation
-
-Line pitch depends on the virtual horizontal resolution, compute it
-accordingly.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-(cherry picked from commit 16ca21c9a9f64577221c47d8d2f00d13b880aefa)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_lcdcfb.c | 16 ++++++++--------
- 1 file changed, 8 insertions(+), 8 deletions(-)
-
-diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
-index 644c230..67877cc 100644
---- a/drivers/video/sh_mobile_lcdcfb.c
-+++ b/drivers/video/sh_mobile_lcdcfb.c
-@@ -1580,9 +1580,9 @@ static int sh_mobile_lcdc_overlay_set_par(struct fb_info *info)
- ovl->yres_virtual = info->var.yres_virtual;
-
- if (ovl->format->yuv)
-- ovl->pitch = info->var.xres;
-+ ovl->pitch = info->var.xres_virtual;
- else
-- ovl->pitch = info->var.xres * ovl->format->bpp / 8;
-+ ovl->pitch = info->var.xres_virtual * ovl->format->bpp / 8;
-
- sh_mobile_lcdc_overlay_setup(ovl);
-
-@@ -2024,9 +2024,9 @@ static int sh_mobile_lcdc_set_par(struct fb_info *info)
- ch->yres_virtual = info->var.yres_virtual;
-
- if (ch->format->yuv)
-- ch->pitch = info->var.xres;
-+ ch->pitch = info->var.xres_virtual;
- else
-- ch->pitch = info->var.xres * ch->format->bpp / 8;
-+ ch->pitch = info->var.xres_virtual * ch->format->bpp / 8;
-
- ret = sh_mobile_lcdc_start(ch->lcdc);
- if (ret < 0)
-@@ -2539,9 +2539,9 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
- ovl->yres_virtual = ovl->yres * 2;
-
- if (!format->yuv)
-- ovl->pitch = ovl->xres * format->bpp / 8;
-+ ovl->pitch = ovl->xres_virtual * format->bpp / 8;
- else
-- ovl->pitch = ovl->xres;
-+ ovl->pitch = ovl->xres_virtual;
-
- /* Allocate frame buffer memory. */
- ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres
-@@ -2628,10 +2628,10 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
-
- if (!format->yuv) {
- ch->colorspace = V4L2_COLORSPACE_SRGB;
-- ch->pitch = ch->xres * format->bpp / 8;
-+ ch->pitch = ch->xres_virtual * format->bpp / 8;
- } else {
- ch->colorspace = V4L2_COLORSPACE_REC709;
-- ch->pitch = ch->xres;
-+ ch->pitch = ch->xres_virtual;
- }
-
- ch->display.width = cfg->panel_cfg.width;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 1cd17c833c8811e06b3dddbe9a9c71e6735a58f9 Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Wed, 18 Jul 2012 16:59:16 +0200
-Subject: fbdev: sh_mobile_lcdc: Use channel configuration to initialize fb
- device
-
-Copy the x and y virtual resolutions from the channel information
-instead of recomputing them.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-(cherry picked from commit bd5f2c6911c210af52fa4dc4cf504043ff8a4971)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_lcdcfb.c | 10 ++++++----
- 1 file changed, 6 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
-index 67877cc..68011b5 100644
---- a/drivers/video/sh_mobile_lcdcfb.c
-+++ b/drivers/video/sh_mobile_lcdcfb.c
-@@ -2214,14 +2214,14 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
- info->fix.ypanstep = 2;
-
- /* Initialize variable screen information using the first mode as
-- * default. The default Y virtual resolution is twice the panel size to
-- * allow for double-buffering.
-+ * default.
- */
- var = &info->var;
- fb_videomode_to_var(var, mode);
- var->width = ch->cfg->panel_cfg.width;
- var->height = ch->cfg->panel_cfg.height;
-- var->yres_virtual = var->yres * 2;
-+ var->xres_virtual = ch->xres_virtual;
-+ var->yres_virtual = ch->yres_virtual;
- var->activate = FB_ACTIVATE_NOW;
-
- /* Use the legacy API by default for RGB formats, and the FOURCC API
-@@ -2619,7 +2619,9 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
- num_modes = cfg->num_modes;
- }
-
-- /* Use the first mode as default. */
-+ /* Use the first mode as default. The default Y virtual resolution is
-+ * twice the panel size to allow for double-buffering.
-+ */
- ch->format = format;
- ch->xres = mode->xres;
- ch->xres_virtual = mode->xres;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 194360fff0a2a4255630477db84bf7af704109ca Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Wed, 18 Jul 2012 17:09:04 +0200
-Subject: fbdev: sh_mobile_lcdc: Support horizontal panning
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-(cherry picked from commit 15dede882e564601947f2ce4b647742c0351be6d)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_lcdcfb.c | 22 ++++++++++++++++------
- 1 file changed, 16 insertions(+), 6 deletions(-)
-
-diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
-index 68011b5..d82c1de 100644
---- a/drivers/video/sh_mobile_lcdcfb.c
-+++ b/drivers/video/sh_mobile_lcdcfb.c
-@@ -1493,7 +1493,7 @@ static const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix = {
- .type = FB_TYPE_PACKED_PIXELS,
- .visual = FB_VISUAL_TRUECOLOR,
- .accel = FB_ACCEL_NONE,
-- .xpanstep = 0,
-+ .xpanstep = 1,
- .ypanstep = 1,
- .ywrapstep = 0,
- .capabilities = FB_CAP_FOURCC,
-@@ -1714,9 +1714,14 @@ sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl)
- else
- info->fix.visual = FB_VISUAL_TRUECOLOR;
-
-- if (ovl->format->fourcc == V4L2_PIX_FMT_NV12 ||
-- ovl->format->fourcc == V4L2_PIX_FMT_NV21)
-+ switch (ovl->format->fourcc) {
-+ case V4L2_PIX_FMT_NV16:
-+ case V4L2_PIX_FMT_NV61:
- info->fix.ypanstep = 2;
-+ case V4L2_PIX_FMT_NV12:
-+ case V4L2_PIX_FMT_NV21:
-+ info->fix.xpanstep = 2;
-+ }
-
- /* Initialize variable screen information. */
- var = &info->var;
-@@ -1771,7 +1776,7 @@ static const struct fb_fix_screeninfo sh_mobile_lcdc_fix = {
- .type = FB_TYPE_PACKED_PIXELS,
- .visual = FB_VISUAL_TRUECOLOR,
- .accel = FB_ACCEL_NONE,
-- .xpanstep = 0,
-+ .xpanstep = 1,
- .ypanstep = 1,
- .ywrapstep = 0,
- .capabilities = FB_CAP_FOURCC,
-@@ -2209,9 +2214,14 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
- else
- info->fix.visual = FB_VISUAL_TRUECOLOR;
-
-- if (ch->format->fourcc == V4L2_PIX_FMT_NV12 ||
-- ch->format->fourcc == V4L2_PIX_FMT_NV21)
-+ switch (ch->format->fourcc) {
-+ case V4L2_PIX_FMT_NV16:
-+ case V4L2_PIX_FMT_NV61:
- info->fix.ypanstep = 2;
-+ case V4L2_PIX_FMT_NV12:
-+ case V4L2_PIX_FMT_NV21:
-+ info->fix.xpanstep = 2;
-+ }
-
- /* Initialize variable screen information using the first mode as
- * default.
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 07f80feb4f79273ade0b493d4f173d4721709d74 Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Thu, 19 Jul 2012 02:29:52 +0200
-Subject: fbdev: sh_mobile_lcdc: Fix overlay registers update during pan
- operation
-
-Updating overlay registers require switching to overlay update mode.
-This was correctly done when configuring the overlay format and size,
-but not when updating the base address registers during pan operation.
-Fix it.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-(cherry picked from commit 8be7c66995bf06769dc4c5f7a62f3cd62a627e7e)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_lcdcfb.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
-index d82c1de..a502709 100644
---- a/drivers/video/sh_mobile_lcdcfb.c
-+++ b/drivers/video/sh_mobile_lcdcfb.c
-@@ -1539,9 +1539,14 @@ static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var,
- ovl->base_addr_c = base_addr_c;
- }
-
-+ lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
-+
- lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y);
- lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c);
-
-+ lcdc_write(ovl->channel->lcdc, LDBCR,
-+ LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
-+
- ovl->pan_offset = pan_offset;
-
- return 0;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 896e926e26d250d1b5397c5a39d12fb25c6928b5 Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Thu, 15 Mar 2012 18:15:37 +0100
-Subject: fbdev: sh_mobile_lcdc: Fix pan offset computation in YUV mode
-
-The chroma plane offset in memory is equal to the luma plane maximum
-size. Fix offset computations.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-(cherry picked from commit a4aa25f6e7885a42c90fe5f0a965403df6cbc943)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_lcdcfb.c | 110 ++++++++++++++++++---------------------
- drivers/video/sh_mobile_lcdcfb.h | 3 +-
- 2 files changed, 54 insertions(+), 59 deletions(-)
-
-diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
-index a502709..8cb653b 100644
---- a/drivers/video/sh_mobile_lcdcfb.c
-+++ b/drivers/video/sh_mobile_lcdcfb.c
-@@ -161,7 +161,7 @@ enum sh_mobile_lcdc_overlay_mode {
- * @dma_handle: Frame buffer DMA address
- * @base_addr_y: Overlay base address (RGB or luma component)
- * @base_addr_c: Overlay base address (chroma component)
-- * @pan_offset: Current pan offset in bytes
-+ * @pan_y_offset: Panning linear offset in bytes (luma component)
- * @format: Current pixelf format
- * @xres: Horizontal visible resolution
- * @xres_virtual: Horizontal total resolution
-@@ -191,7 +191,7 @@ struct sh_mobile_lcdc_overlay {
- dma_addr_t dma_handle;
- unsigned long base_addr_y;
- unsigned long base_addr_c;
-- unsigned long pan_offset;
-+ unsigned long pan_y_offset;
-
- const struct sh_mobile_lcdc_format_info *format;
- unsigned int xres;
-@@ -873,8 +873,8 @@ static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl)
- }
-
- ovl->base_addr_y = ovl->dma_handle;
-- ovl->base_addr_c = ovl->base_addr_y + ovl->xres
-- * ovl->yres_virtual;
-+ ovl->base_addr_c = ovl->dma_handle
-+ + ovl->xres_virtual * ovl->yres_virtual;
-
- switch (ovl->mode) {
- case LCDC_OVERLAY_BLEND:
-@@ -1111,7 +1111,8 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
- continue;
-
- ch->base_addr_y = ch->dma_handle;
-- ch->base_addr_c = ch->base_addr_y + ch->xres * ch->yres_virtual;
-+ ch->base_addr_c = ch->dma_handle
-+ + ch->xres_virtual * ch->yres_virtual;
- ch->line_size = ch->pitch;
-
- /* Enable MERAM if possible. */
-@@ -1505,39 +1506,36 @@ static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var,
- struct sh_mobile_lcdc_overlay *ovl = info->par;
- unsigned long base_addr_y;
- unsigned long base_addr_c;
-- unsigned long pan_offset;
-+ unsigned long y_offset;
- unsigned long c_offset;
-
-- if (!ovl->format->yuv)
-- pan_offset = var->yoffset * ovl->pitch
-- + var->xoffset * (ovl->format->bpp / 8);
-- else
-- pan_offset = var->yoffset * ovl->pitch + var->xoffset;
-+ if (!ovl->format->yuv) {
-+ y_offset = (var->yoffset * ovl->xres_virtual + var->xoffset)
-+ * ovl->format->bpp / 8;
-+ c_offset = 0;
-+ } else {
-+ unsigned int xsub = ovl->format->bpp < 24 ? 2 : 1;
-+ unsigned int ysub = ovl->format->bpp < 16 ? 2 : 1;
-+
-+ y_offset = var->yoffset * ovl->xres_virtual + var->xoffset;
-+ c_offset = var->yoffset / ysub * ovl->xres_virtual * 2 / xsub
-+ + var->xoffset * 2 / xsub;
-+ }
-
-- if (pan_offset == ovl->pan_offset)
-- return 0; /* No change, do nothing */
-+ /* If the Y offset hasn't changed, the C offset hasn't either. There's
-+ * nothing to do in that case.
-+ */
-+ if (y_offset == ovl->pan_y_offset)
-+ return 0;
-
- /* Set the source address for the next refresh */
-- base_addr_y = ovl->dma_handle + pan_offset;
-+ base_addr_y = ovl->dma_handle + y_offset;
-+ base_addr_c = ovl->dma_handle + ovl->xres_virtual * ovl->yres_virtual
-+ + c_offset;
-
- ovl->base_addr_y = base_addr_y;
-- ovl->base_addr_c = base_addr_y;
--
-- if (ovl->format->yuv) {
-- /* Set Y offset */
-- c_offset = var->yoffset * ovl->pitch
-- * (ovl->format->bpp - 8) / 8;
-- base_addr_c = ovl->dma_handle
-- + ovl->xres * ovl->yres_virtual
-- + c_offset;
-- /* Set X offset */
-- if (ovl->format->fourcc == V4L2_PIX_FMT_NV24)
-- base_addr_c += 2 * var->xoffset;
-- else
-- base_addr_c += var->xoffset;
--
-- ovl->base_addr_c = base_addr_c;
-- }
-+ ovl->base_addr_c = base_addr_c;
-+ ovl->pan_y_offset = y_offset;
-
- lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
-
-@@ -1547,8 +1545,6 @@ static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var,
- lcdc_write(ovl->channel->lcdc, LDBCR,
- LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
-
-- ovl->pan_offset = pan_offset;
--
- return 0;
- }
-
-@@ -1814,35 +1810,33 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
- struct sh_mobile_lcdc_chan *ch = info->par;
- struct sh_mobile_lcdc_priv *priv = ch->lcdc;
- unsigned long ldrcntr;
-- unsigned long new_pan_offset;
-- unsigned long base_addr_y, base_addr_c = 0;
-+ unsigned long base_addr_y, base_addr_c;
-+ unsigned long y_offset;
- unsigned long c_offset;
-
-- if (!ch->format->yuv)
-- new_pan_offset = var->yoffset * ch->pitch
-- + var->xoffset * (ch->format->bpp / 8);
-- else
-- new_pan_offset = var->yoffset * ch->pitch + var->xoffset;
-+ if (!ch->format->yuv) {
-+ y_offset = (var->yoffset * ch->xres_virtual + var->xoffset)
-+ * ch->format->bpp / 8;
-+ c_offset = 0;
-+ } else {
-+ unsigned int xsub = ch->format->bpp < 24 ? 2 : 1;
-+ unsigned int ysub = ch->format->bpp < 16 ? 2 : 1;
-
-- if (new_pan_offset == ch->pan_offset)
-- return 0; /* No change, do nothing */
-+ y_offset = var->yoffset * ch->xres_virtual + var->xoffset;
-+ c_offset = var->yoffset / ysub * ch->xres_virtual * 2 / xsub
-+ + var->xoffset * 2 / xsub;
-+ }
-
-- ldrcntr = lcdc_read(priv, _LDRCNTR);
-+ /* If the Y offset hasn't changed, the C offset hasn't either. There's
-+ * nothing to do in that case.
-+ */
-+ if (y_offset == ch->pan_y_offset)
-+ return 0;
-
- /* Set the source address for the next refresh */
-- base_addr_y = ch->dma_handle + new_pan_offset;
-- if (ch->format->yuv) {
-- /* Set y offset */
-- c_offset = var->yoffset * ch->pitch
-- * (ch->format->bpp - 8) / 8;
-- base_addr_c = ch->dma_handle + ch->xres * ch->yres_virtual
-- + c_offset;
-- /* Set x offset */
-- if (ch->format->fourcc == V4L2_PIX_FMT_NV24)
-- base_addr_c += 2 * var->xoffset;
-- else
-- base_addr_c += var->xoffset;
-- }
-+ base_addr_y = ch->dma_handle + y_offset;
-+ base_addr_c = ch->dma_handle + ch->xres_virtual * ch->yres_virtual
-+ + c_offset;
-
- if (ch->cache)
- sh_mobile_meram_cache_update(priv->meram_dev, ch->cache,
-@@ -1851,17 +1845,18 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
-
- ch->base_addr_y = base_addr_y;
- ch->base_addr_c = base_addr_c;
-+ ch->pan_y_offset = y_offset;
-
- lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
- if (ch->format->yuv)
- lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
-
-+ ldrcntr = lcdc_read(priv, _LDRCNTR);
- if (lcdc_chan_is_sublcd(ch))
- lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
- else
- lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS);
-
-- ch->pan_offset = new_pan_offset;
-
- sh_mobile_lcdc_deferred_io_touch(info);
-
-@@ -2734,7 +2729,6 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
- }
- init_waitqueue_head(&ch->frame_end_wait);
- init_completion(&ch->vsync_completion);
-- ch->pan_offset = 0;
-
- /* probe the backlight is there is one defined */
- if (ch->cfg->bl_info.max_brightness)
-diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
-index e53cd11..0f92f65 100644
---- a/drivers/video/sh_mobile_lcdcfb.h
-+++ b/drivers/video/sh_mobile_lcdcfb.h
-@@ -47,6 +47,7 @@ struct sh_mobile_lcdc_entity {
- /*
- * struct sh_mobile_lcdc_chan - LCDC display channel
- *
-+ * @pan_y_offset: Panning linear offset in bytes (luma component)
- * @base_addr_y: Frame buffer viewport base address (luma component)
- * @base_addr_c: Frame buffer viewport base address (chroma component)
- * @pitch: Frame buffer line pitch
-@@ -68,7 +69,7 @@ struct sh_mobile_lcdc_chan {
- unsigned long fb_size;
-
- dma_addr_t dma_handle;
-- unsigned long pan_offset;
-+ unsigned long pan_y_offset;
-
- unsigned long frame_end;
- wait_queue_head_t frame_end_wait;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 633f3cd2b85466e5744a86cbe888d78f30302083 Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Thu, 26 Jul 2012 14:36:55 +0200
-Subject: fbdev: sh_mobile_lcdc: Fix vertical panning step
-
-Commit 15dede882e564601947f2ce4b647742c0351be6d added support for
-horizontal panning but accidentally computes the Y pan step value
-incorrectly for NV12/21 and NV16/61 formats. Fix this.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
-(cherry picked from commit ac33a207b13a70bbca6e58094e28bd92b9fc1ff3)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/video/sh_mobile_lcdcfb.c | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
-
-diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
-index 8cb653b..699487c 100644
---- a/drivers/video/sh_mobile_lcdcfb.c
-+++ b/drivers/video/sh_mobile_lcdcfb.c
-@@ -1716,11 +1716,11 @@ sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl)
- info->fix.visual = FB_VISUAL_TRUECOLOR;
-
- switch (ovl->format->fourcc) {
-- case V4L2_PIX_FMT_NV16:
-- case V4L2_PIX_FMT_NV61:
-- info->fix.ypanstep = 2;
- case V4L2_PIX_FMT_NV12:
- case V4L2_PIX_FMT_NV21:
-+ info->fix.ypanstep = 2;
-+ case V4L2_PIX_FMT_NV16:
-+ case V4L2_PIX_FMT_NV61:
- info->fix.xpanstep = 2;
- }
-
-@@ -2215,11 +2215,11 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
- info->fix.visual = FB_VISUAL_TRUECOLOR;
-
- switch (ch->format->fourcc) {
-- case V4L2_PIX_FMT_NV16:
-- case V4L2_PIX_FMT_NV61:
-- info->fix.ypanstep = 2;
- case V4L2_PIX_FMT_NV12:
- case V4L2_PIX_FMT_NV21:
-+ info->fix.ypanstep = 2;
-+ case V4L2_PIX_FMT_NV16:
-+ case V4L2_PIX_FMT_NV61:
- info->fix.xpanstep = 2;
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 18ed06783eaf892967a3260bd9056a4aba81bfa0 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Fri, 6 Apr 2012 01:28:14 -0700
-Subject: ARM: mach-shmobile: r8a7740: add gpio_irq support
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 9f6b78223b7b49bc06d2e84b15d48f02206ec3c3)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/pfc-r8a7740.c | 39 ++++++++++++++++++++++++++++++++++++
- 1 file changed, 39 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c
-index a4fff69..670fe18 100644
---- a/arch/arm/mach-shmobile/pfc-r8a7740.c
-+++ b/arch/arm/mach-shmobile/pfc-r8a7740.c
-@@ -22,6 +22,7 @@
- #include <linux/kernel.h>
- #include <linux/gpio.h>
- #include <mach/r8a7740.h>
-+#include <mach/irqs.h>
-
- #define CPU_ALL_PORT(fn, pfx, sfx) \
- PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx), \
-@@ -2527,6 +2528,41 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
- { },
- };
-
-+static struct pinmux_irq pinmux_irqs[] = {
-+ PINMUX_IRQ(evt2irq(0x0200), PORT2_FN0, PORT13_FN0), /* IRQ0A */
-+ PINMUX_IRQ(evt2irq(0x0220), PORT20_FN0), /* IRQ1A */
-+ PINMUX_IRQ(evt2irq(0x0240), PORT11_FN0, PORT12_FN0), /* IRQ2A */
-+ PINMUX_IRQ(evt2irq(0x0260), PORT10_FN0, PORT14_FN0), /* IRQ3A */
-+ PINMUX_IRQ(evt2irq(0x0280), PORT15_FN0, PORT172_FN0), /* IRQ4A */
-+ PINMUX_IRQ(evt2irq(0x02A0), PORT0_FN0, PORT1_FN0), /* IRQ5A */
-+ PINMUX_IRQ(evt2irq(0x02C0), PORT121_FN0, PORT173_FN0), /* IRQ6A */
-+ PINMUX_IRQ(evt2irq(0x02E0), PORT120_FN0, PORT209_FN0), /* IRQ7A */
-+ PINMUX_IRQ(evt2irq(0x0300), PORT119_FN0), /* IRQ8A */
-+ PINMUX_IRQ(evt2irq(0x0320), PORT118_FN0, PORT210_FN0), /* IRQ9A */
-+ PINMUX_IRQ(evt2irq(0x0340), PORT19_FN0), /* IRQ10A */
-+ PINMUX_IRQ(evt2irq(0x0360), PORT104_FN0), /* IRQ11A */
-+ PINMUX_IRQ(evt2irq(0x0380), PORT42_FN0, PORT97_FN0), /* IRQ12A */
-+ PINMUX_IRQ(evt2irq(0x03A0), PORT64_FN0, PORT98_FN0), /* IRQ13A */
-+ PINMUX_IRQ(evt2irq(0x03C0), PORT63_FN0, PORT99_FN0), /* IRQ14A */
-+ PINMUX_IRQ(evt2irq(0x03E0), PORT62_FN0, PORT100_FN0), /* IRQ15A */
-+ PINMUX_IRQ(evt2irq(0x3200), PORT68_FN0, PORT211_FN0), /* IRQ16A */
-+ PINMUX_IRQ(evt2irq(0x3220), PORT69_FN0), /* IRQ17A */
-+ PINMUX_IRQ(evt2irq(0x3240), PORT70_FN0), /* IRQ18A */
-+ PINMUX_IRQ(evt2irq(0x3260), PORT71_FN0), /* IRQ19A */
-+ PINMUX_IRQ(evt2irq(0x3280), PORT67_FN0), /* IRQ20A */
-+ PINMUX_IRQ(evt2irq(0x32A0), PORT202_FN0), /* IRQ21A */
-+ PINMUX_IRQ(evt2irq(0x32C0), PORT95_FN0), /* IRQ22A */
-+ PINMUX_IRQ(evt2irq(0x32E0), PORT96_FN0), /* IRQ23A */
-+ PINMUX_IRQ(evt2irq(0x3300), PORT180_FN0), /* IRQ24A */
-+ PINMUX_IRQ(evt2irq(0x3320), PORT38_FN0), /* IRQ25A */
-+ PINMUX_IRQ(evt2irq(0x3340), PORT58_FN0, PORT81_FN0), /* IRQ26A */
-+ PINMUX_IRQ(evt2irq(0x3360), PORT57_FN0, PORT168_FN0), /* IRQ27A */
-+ PINMUX_IRQ(evt2irq(0x3380), PORT56_FN0, PORT169_FN0), /* IRQ28A */
-+ PINMUX_IRQ(evt2irq(0x33A0), PORT50_FN0, PORT170_FN0), /* IRQ29A */
-+ PINMUX_IRQ(evt2irq(0x33C0), PORT49_FN0, PORT171_FN0), /* IRQ30A */
-+ PINMUX_IRQ(evt2irq(0x33E0), PORT41_FN0, PORT167_FN0), /* IRQ31A */
-+};
-+
- static struct pinmux_info r8a7740_pinmux_info = {
- .name = "r8a7740_pfc",
- .reserved_id = PINMUX_RESERVED,
-@@ -2554,6 +2590,9 @@ static struct pinmux_info r8a7740_pinmux_info = {
-
- .gpio_data = pinmux_data,
- .gpio_data_size = ARRAY_SIZE(pinmux_data),
-+
-+ .gpio_irq = pinmux_irqs,
-+ .gpio_irq_size = ARRAY_SIZE(pinmux_irqs),
- };
-
- void r8a7740_pinmux_init(void)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 46dccabaa06e08bb7b9b2ac4b46f784b8afba7f0 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Fri, 13 Apr 2012 02:41:06 -0700
-Subject: ARM: mach-shmobile: r8a7740: cleanup I2C workaround method
-
-Current workaround of I2C on r8a7740 used mdelay(),
-but it was an overkill.
-This patch cleans up the workaround delay.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 4228716c87f7915410721952bad3e568fb5f2431)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/setup-r8a7740.c | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
-
---- a/arch/arm/mach-shmobile/setup-r8a7740.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
-@@ -368,19 +368,19 @@ static void r8a7740_i2c_workaround(struc
- i2c_write(reg, ICSTART, i2c_read(reg, ICSTART) | 0x10);
- i2c_read(reg, ICSTART); /* dummy read */
-
-- mdelay(100);
-+ udelay(10);
-
- i2c_write(reg, ICCR, 0x01);
-- i2c_read(reg, ICCR);
- i2c_write(reg, ICSTART, 0x00);
-- i2c_read(reg, ICSTART);
-+
-+ udelay(10);
-
- i2c_write(reg, ICCR, 0x10);
-- mdelay(100);
-+ udelay(10);
- i2c_write(reg, ICCR, 0x00);
-- mdelay(100);
-+ udelay(10);
- i2c_write(reg, ICCR, 0x10);
-- mdelay(100);
-+ udelay(10);
-
- iounmap(reg);
- }
+++ /dev/null
-From 9b696a8092bedbd771c4b8e6a8c12edbd6881444 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Sun, 1 Apr 2012 18:46:09 -0700
-Subject: ARM: mach-shmobile: clock-r8a7740: add FSI clock
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 7ee8948d158946e52ea21562f2ceef268439f36e)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/clock-r8a7740.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
-index 99c4d74..b6fa1b7 100644
---- a/arch/arm/mach-shmobile/clock-r8a7740.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
-@@ -257,7 +257,7 @@ enum {
- MSTP222,
- MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
-
-- MSTP329, MSTP323,
-+ MSTP329, MSTP328, MSTP323,
-
- MSTP_NR
- };
-@@ -280,6 +280,7 @@ static struct clk mstp_clks[MSTP_NR] = {
- [MSTP200] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
-
- [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
-+ [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */
- [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
- };
-
-@@ -334,6 +335,7 @@ static struct clk_lookup lookups[] = {
- CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]),
-
- CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]),
-+ CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]),
- CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]),
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a747b7aa896100a6b9dd0dc0828c27ef344f381c Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 24 Apr 2012 02:07:47 -0700
-Subject: ARM: mach-shmobile: clock-r8a7740: add USB clock
-
-R8A7740 USB needs many clocks for workaround,
-and it has confusing name "usb24s" and "usb24".
-This "usb24s" will be used by other clocks.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit fcca3f0f007d97f095a3ebe8f209021b517309d2)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/clock-r8a7740.c | 118 ++++++++++++++++++++++++++++++++-
- 1 file changed, 116 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
-index b6fa1b7..b9b1d73 100644
---- a/arch/arm/mach-shmobile/clock-r8a7740.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
-@@ -47,6 +47,7 @@
- #define PLLC01CR 0xe6150028
-
- #define SUBCKCR 0xe6150080
-+#define USBCKCR 0xe615008c
-
- #define MSTPSR0 0xe6150030
- #define MSTPSR1 0xe6150038
-@@ -181,6 +182,100 @@ static struct clk pllc1_div2_clk = {
- .parent = &pllc1_clk,
- };
-
-+/* USB clock */
-+static struct clk *usb24s_parents[] = {
-+ [0] = &system_clk,
-+ [1] = &extal2_clk
-+};
-+
-+static unsigned long usb24s_recalc(struct clk *clk)
-+{
-+ return clk->parent->rate;
-+};
-+
-+static int usb24s_enable(struct clk *clk)
-+{
-+ __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR);
-+
-+ return 0;
-+}
-+
-+static void usb24s_disable(struct clk *clk)
-+{
-+ __raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR);
-+}
-+
-+static int usb24s_set_parent(struct clk *clk, struct clk *parent)
-+{
-+ int i, ret;
-+ u32 val;
-+
-+ if (!clk->parent_table || !clk->parent_num)
-+ return -EINVAL;
-+
-+ /* Search the parent */
-+ for (i = 0; i < clk->parent_num; i++)
-+ if (clk->parent_table[i] == parent)
-+ break;
-+
-+ if (i == clk->parent_num)
-+ return -ENODEV;
-+
-+ ret = clk_reparent(clk, parent);
-+ if (ret < 0)
-+ return ret;
-+
-+ val = __raw_readl(USBCKCR);
-+ val &= ~(1 << 7);
-+ val |= i << 7;
-+ __raw_writel(val, USBCKCR);
-+
-+ return 0;
-+}
-+
-+static struct sh_clk_ops usb24s_clk_ops = {
-+ .recalc = usb24s_recalc,
-+ .enable = usb24s_enable,
-+ .disable = usb24s_disable,
-+ .set_parent = usb24s_set_parent,
-+};
-+
-+static struct clk usb24s_clk = {
-+ .ops = &usb24s_clk_ops,
-+ .parent_table = usb24s_parents,
-+ .parent_num = ARRAY_SIZE(usb24s_parents),
-+ .parent = &system_clk,
-+};
-+
-+static unsigned long usb24_recalc(struct clk *clk)
-+{
-+ return clk->parent->rate /
-+ ((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2);
-+};
-+
-+static int usb24_set_rate(struct clk *clk, unsigned long rate)
-+{
-+ u32 val;
-+
-+ /* closer to which ? parent->rate or parent->rate/2 */
-+ val = __raw_readl(USBCKCR);
-+ val &= ~(1 << 6);
-+ val |= (rate > (clk->parent->rate / 4) * 3) << 6;
-+ __raw_writel(val, USBCKCR);
-+
-+ return 0;
-+}
-+
-+static struct sh_clk_ops usb24_clk_ops = {
-+ .recalc = usb24_recalc,
-+ .set_rate = usb24_set_rate,
-+};
-+
-+static struct clk usb24_clk = {
-+ .ops = &usb24_clk_ops,
-+ .parent = &usb24s_clk,
-+};
-+
- struct clk *main_clks[] = {
- &extalr_clk,
- &extal1_clk,
-@@ -196,6 +291,8 @@ struct clk *main_clks[] = {
- &pllc0_clk,
- &pllc1_clk,
- &pllc1_div2_clk,
-+ &usb24s_clk,
-+ &usb24_clk,
- };
-
- static void div4_kick(struct clk *clk)
-@@ -223,7 +320,7 @@ static struct clk_div4_table div4_table = {
-
- enum {
- DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP,
-- DIV4_HPP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
-+ DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
- DIV4_NR
- };
-
-@@ -234,6 +331,7 @@ struct clk div4_clks[DIV4_NR] = {
- [DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT),
- [DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0),
- [DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0),
-+ [DIV4_USBP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0),
- [DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0),
- [DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0),
- [DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0),
-@@ -257,7 +355,9 @@ enum {
- MSTP222,
- MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
-
-- MSTP329, MSTP328, MSTP323,
-+ MSTP329, MSTP328, MSTP323, MSTP320,
-+
-+ MSTP416, MSTP407, MSTP406,
-
- MSTP_NR
- };
-@@ -282,6 +382,11 @@ static struct clk mstp_clks[MSTP_NR] = {
- [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
- [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */
- [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
-+ [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */
-+
-+ [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */
-+ [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-Func */
-+ [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 6, 0), /* USB Phy */
- };
-
- static struct clk_lookup lookups[] = {
-@@ -300,6 +405,7 @@ static struct clk_lookup lookups[] = {
- CLKDEV_CON_ID("pllc0_clk", &pllc0_clk),
- CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
- CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
-+ CLKDEV_CON_ID("usb24s", &usb24s_clk),
-
- /* DIV4 clocks */
- CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
-@@ -337,6 +443,14 @@ static struct clk_lookup lookups[] = {
- CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]),
- CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]),
- CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]),
-+ CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]),
-+
-+ /* ICK */
-+ CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]),
-+ CLKDEV_ICK_ID("func", "renesas_usbhs", &mstp_clks[MSTP407]),
-+ CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]),
-+ CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]),
-+ CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk),
- };
-
- void __init r8a7740_clock_init(u8 md_ck)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From df046bb39c81fb474109a85f21b35345df0b9441 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 24 Apr 2012 02:08:11 -0700
-Subject: ARM: mach-shmobile: clock-r8a7740: add SDHI clock
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 19ad322de262c810463aeb8769c66474d8b68210)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/clock-r8a7740.c | 10 +++++++++-
- 1 file changed, 9 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
-index b9b1d73..86f7147 100644
---- a/arch/arm/mach-shmobile/clock-r8a7740.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
-@@ -356,8 +356,9 @@ enum {
- MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
-
- MSTP329, MSTP328, MSTP323, MSTP320,
-+ MSTP314, MSTP313,
-
-- MSTP416, MSTP407, MSTP406,
-+ MSTP416, MSTP415, MSTP407, MSTP406,
-
- MSTP_NR
- };
-@@ -383,8 +384,11 @@ static struct clk mstp_clks[MSTP_NR] = {
- [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */
- [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
- [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */
-+ [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
-+ [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */
-
- [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */
-+ [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */
- [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-Func */
- [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 6, 0), /* USB Phy */
- };
-@@ -444,6 +448,10 @@ static struct clk_lookup lookups[] = {
- CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]),
- CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]),
- CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]),
-+ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]),
-+ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]),
-+
-+ CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]),
-
- /* ICK */
- CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]),
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 3b4d84a8de5adaa8ec1b4db8b3409fc75340bd7f Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 24 Apr 2012 02:08:29 -0700
-Subject: ARM: mach-shmobile: clock-r8a7740: add MMCIF clock
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit f2c2d7e9210c4a82336b208adc88630cd0e77f57)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/clock-r8a7740.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
-index 86f7147..89a2f9d 100644
---- a/arch/arm/mach-shmobile/clock-r8a7740.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
-@@ -356,7 +356,7 @@ enum {
- MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
-
- MSTP329, MSTP328, MSTP323, MSTP320,
-- MSTP314, MSTP313,
-+ MSTP314, MSTP313, MSTP312,
-
- MSTP416, MSTP415, MSTP407, MSTP406,
-
-@@ -386,6 +386,7 @@ static struct clk mstp_clks[MSTP_NR] = {
- [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */
- [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
- [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */
-+ [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */
-
- [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */
- [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */
-@@ -450,6 +451,7 @@ static struct clk_lookup lookups[] = {
- CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]),
- CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]),
- CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]),
-+ CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]),
-
- CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]),
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 02b6fac5cb1a97bb8851976abdd8a229a852907f Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Sun, 6 May 2012 18:12:41 -0700
-Subject: ARM: mach-shmobile: clock-r8a7740: use followparent_recalc on usb24s
-
-If the clocks is always same value as the parent clock,
-we can use followparent_recalc() for .recalc
-
-Reported-by: Paul Mundt <lethal@linux-sh.org>
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Reviewed-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit c8241085e8606a14ef48e6d99556133c48aaddaf)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/clock-r8a7740.c | 7 +------
- 1 file changed, 1 insertion(+), 6 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
-index 89a2f9d..81b54a6 100644
---- a/arch/arm/mach-shmobile/clock-r8a7740.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
-@@ -188,11 +188,6 @@ static struct clk *usb24s_parents[] = {
- [1] = &extal2_clk
- };
-
--static unsigned long usb24s_recalc(struct clk *clk)
--{
-- return clk->parent->rate;
--};
--
- static int usb24s_enable(struct clk *clk)
- {
- __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR);
-@@ -234,7 +229,7 @@ static int usb24s_set_parent(struct clk *clk, struct clk *parent)
- }
-
- static struct sh_clk_ops usb24s_clk_ops = {
-- .recalc = usb24s_recalc,
-+ .recalc = followparent_recalc,
- .enable = usb24s_enable,
- .disable = usb24s_disable,
- .set_parent = usb24s_set_parent,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 6dbc9d7efd3ddd2dbc0a1b95b3a237173df5e1d8 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Fri, 6 Apr 2012 01:28:59 -0700
-Subject: ARM: mach-shmobile: add armadillo800eva board support.
-
-This adds very basic armadillo800eva board (R-Mobile A1) support
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 4d22e564ca7bb5c7340c782aedd93bed99f3fb41)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/Kconfig | 11 +-
- arch/arm/mach-shmobile/Makefile | 1 +
- arch/arm/mach-shmobile/board-armadillo800eva.c | 154 +++++++++++++++++++++++++
- 3 files changed, 164 insertions(+), 2 deletions(-)
- create mode 100644 arch/arm/mach-shmobile/board-armadillo800eva.c
-
-diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
-index 2cda0c2..799e996 100644
---- a/arch/arm/mach-shmobile/Kconfig
-+++ b/arch/arm/mach-shmobile/Kconfig
-@@ -95,6 +95,11 @@ config MACH_BONITO
- select ARCH_REQUIRE_GPIOLIB
- depends on ARCH_R8A7740
-
-+config MACH_ARMADILLO800EVA
-+ bool "Armadillo-800 EVA board"
-+ depends on ARCH_R8A7740
-+ select ARCH_REQUIRE_GPIOLIB
-+
- config MACH_MARZEN
- bool "MARZEN board"
- depends on ARCH_R8A7779
-@@ -112,7 +117,8 @@ config MEMORY_START
- hex "Physical memory start address"
- default "0x50000000" if MACH_G3EVM
- default "0x40000000" if MACH_G4EVM || MACH_AP4EVB || MACH_AG5EVM || \
-- MACH_MACKEREL || MACH_BONITO
-+ MACH_MACKEREL || MACH_BONITO || \
-+ MACH_ARMADILLO800EVA
- default "0x41000000" if MACH_KOTA2
- default "0x00000000"
- ---help---
-@@ -124,7 +130,8 @@ config MEMORY_SIZE
- hex "Physical memory size"
- default "0x08000000" if MACH_G3EVM
- default "0x08000000" if MACH_G4EVM
-- default "0x20000000" if MACH_AG5EVM || MACH_BONITO
-+ default "0x20000000" if MACH_AG5EVM || MACH_BONITO || \
-+ MACH_ARMADILLO800EVA
- default "0x1e000000" if MACH_KOTA2
- default "0x10000000" if MACH_AP4EVB || MACH_MACKEREL
- default "0x04000000"
-diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
-index 53846a1e..b39033b 100644
---- a/arch/arm/mach-shmobile/Makefile
-+++ b/arch/arm/mach-shmobile/Makefile
-@@ -50,6 +50,7 @@ obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o
- obj-$(CONFIG_MACH_KOTA2) += board-kota2.o
- obj-$(CONFIG_MACH_BONITO) += board-bonito.o
- obj-$(CONFIG_MACH_MARZEN) += board-marzen.o
-+obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o
-
- # Framework support
- obj-$(CONFIG_SMP) += $(smp-y)
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-new file mode 100644
-index 0000000..28bc259
---- /dev/null
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -0,0 +1,154 @@
-+/*
-+ * armadillo 800 eva board support
-+ *
-+ * Copyright (C) 2012 Renesas Solutions Corp.
-+ * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; version 2 of the License.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/err.h>
-+#include <linux/kernel.h>
-+#include <linux/platform_device.h>
-+#include <linux/gpio.h>
-+#include <mach/common.h>
-+#include <mach/irqs.h>
-+#include <asm/page.h>
-+#include <asm/mach-types.h>
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/mach/time.h>
-+#include <asm/hardware/cache-l2x0.h>
-+#include <mach/r8a7740.h>
-+
-+/*
-+ * CON1 Camera Module
-+ * CON2 Extension Bus
-+ * CON3 HDMI Output
-+ * CON4 Composite Video Output
-+ * CON5 H-UDI JTAG
-+ * CON6 ARM JTAG
-+ * CON7 SD1
-+ * CON8 SD2
-+ * CON9 RTC BackUp
-+ * CON10 Monaural Mic Input
-+ * CON11 Stereo Headphone Output
-+ * CON12 Audio Line Output(L)
-+ * CON13 Audio Line Output(R)
-+ * CON14 AWL13 Module
-+ * CON15 Extension
-+ * CON16 LCD1
-+ * CON17 LCD2
-+ * CON19 Power Input
-+ * CON20 USB1
-+ * CON21 USB2
-+ * CON22 Serial
-+ * CON23 LAN
-+ * CON24 USB3
-+ * LED1 Camera LED(Yellow)
-+ * LED2 Power LED (Green)
-+ * ED3-LED6 User LED(Yellow)
-+ * LED7 LAN link LED(Green)
-+ * LED8 LAN activity LED(Yellow)
-+ */
-+
-+/*
-+ * DipSwitch
-+ *
-+ * SW1
-+ *
-+ * -12345678-+---------------+----------------------------
-+ * 1 | boot | hermit
-+ * 0 | boot | OS auto boot
-+ * -12345678-+---------------+----------------------------
-+ * 00 | boot device | eMMC
-+ * 10 | boot device | SDHI0 (CON7)
-+ * 01 | boot device | -
-+ * 11 | boot device | Extension Buss (CS0)
-+ * -12345678-+---------------+----------------------------
-+ * 0 | Extension Bus | D8-D15 disable, eMMC enable
-+ * 1 | Extension Bus | D8-D15 enable, eMMC disable
-+ * -12345678-+---------------+----------------------------
-+ * 0 | SDHI1 | COM8 enable, COM14 disable
-+ * 1 | SDHI1 | COM8 enable, COM14 disable
-+ * -12345678-+---------------+----------------------------
-+ * 00 | JTAG | SH-X2
-+ * 10 | JTAG | ARM
-+ * 01 | JTAG | -
-+ * 11 | JTAG | Boundary Scan
-+ *-----------+---------------+----------------------------
-+ */
-+
-+/*
-+ * board devices
-+ */
-+static struct platform_device *eva_devices[] __initdata = {
-+};
-+
-+/*
-+ * board init
-+ */
-+static void __init eva_init(void)
-+{
-+ r8a7740_pinmux_init();
-+
-+ /* SCIFA1 */
-+ gpio_request(GPIO_FN_SCIFA1_RXD, NULL);
-+ gpio_request(GPIO_FN_SCIFA1_TXD, NULL);
-+
-+#ifdef CONFIG_CACHE_L2X0
-+ /* Early BRESP enable, Shared attribute override enable, 32K*8way */
-+ l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff);
-+#endif
-+
-+ r8a7740_add_standard_devices();
-+
-+ platform_add_devices(eva_devices,
-+ ARRAY_SIZE(eva_devices));
-+}
-+
-+static void __init eva_earlytimer_init(void)
-+{
-+ struct clk *xtal1;
-+
-+ r8a7740_clock_init(MD_CK0 | MD_CK2);
-+
-+ xtal1 = clk_get(NULL, "extal1");
-+ if (!IS_ERR(xtal1)) {
-+ /* armadillo 800 eva extal1 is 24MHz */
-+ clk_set_rate(xtal1, 24000000);
-+ clk_put(xtal1);
-+ }
-+
-+ shmobile_earlytimer_init();
-+}
-+
-+static void __init eva_add_early_devices(void)
-+{
-+ r8a7740_add_early_devices();
-+
-+ /* override timer setup with board-specific code */
-+ shmobile_timer.init = eva_earlytimer_init;
-+}
-+
-+MACHINE_START(ARMADILLO800EVA, "armadillo800eva")
-+ .map_io = r8a7740_map_io,
-+ .init_early = eva_add_early_devices,
-+ .init_irq = r8a7740_init_irq,
-+ .handle_irq = shmobile_handle_irq_intc,
-+ .init_machine = eva_init,
-+ .timer = &shmobile_timer,
-+MACHINE_END
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 90660861a7540365f6c7c4412f30a74e4a7d9dd3 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Fri, 6 Apr 2012 01:29:36 -0700
-Subject: ARM: mach-shmobile: armadillo800eva: add defconfig
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit edc4910171f332466fa8f164de3d2395d80163db)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/configs/armadillo800eva_defconfig | 143 +++++++++++++++++++++++++++++
- 1 file changed, 143 insertions(+)
- create mode 100644 arch/arm/configs/armadillo800eva_defconfig
-
-diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
-new file mode 100644
-index 0000000..0d20749
---- /dev/null
-+++ b/arch/arm/configs/armadillo800eva_defconfig
-@@ -0,0 +1,143 @@
-+CONFIG_EXPERIMENTAL=y
-+CONFIG_SYSVIPC=y
-+CONFIG_IKCONFIG=y
-+CONFIG_IKCONFIG_PROC=y
-+CONFIG_LOG_BUF_SHIFT=16
-+# CONFIG_UTS_NS is not set
-+# CONFIG_IPC_NS is not set
-+# CONFIG_USER_NS is not set
-+# CONFIG_PID_NS is not set
-+CONFIG_SYSFS_DEPRECATED=y
-+CONFIG_SYSFS_DEPRECATED_V2=y
-+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-+CONFIG_KALLSYMS_ALL=y
-+CONFIG_SLAB=y
-+CONFIG_MODULES=y
-+CONFIG_MODULE_UNLOAD=y
-+CONFIG_MODULE_FORCE_UNLOAD=y
-+# CONFIG_BLK_DEV_BSG is not set
-+# CONFIG_IOSCHED_DEADLINE is not set
-+# CONFIG_IOSCHED_CFQ is not set
-+CONFIG_ARCH_SHMOBILE=y
-+CONFIG_ARCH_R8A7740=y
-+CONFIG_MACH_ARMADILLO800EVA=y
-+# CONFIG_SH_TIMER_TMU is not set
-+# CONFIG_ARM_THUMB is not set
-+CONFIG_CPU_BPREDICT_DISABLE=y
-+# CONFIG_CACHE_L2X0 is not set
-+CONFIG_ARM_ERRATA_430973=y
-+CONFIG_ARM_ERRATA_458693=y
-+CONFIG_ARM_ERRATA_460075=y
-+CONFIG_ARM_ERRATA_720789=y
-+CONFIG_ARM_ERRATA_743622=y
-+CONFIG_ARM_ERRATA_751472=y
-+CONFIG_ARM_ERRATA_754322=y
-+CONFIG_AEABI=y
-+# CONFIG_OABI_COMPAT is not set
-+CONFIG_FORCE_MAX_ZONEORDER=13
-+CONFIG_ZBOOT_ROM_TEXT=0x0
-+CONFIG_ZBOOT_ROM_BSS=0x0
-+CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096"
-+CONFIG_CMDLINE_FORCE=y
-+CONFIG_KEXEC=y
-+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-+# CONFIG_SUSPEND is not set
-+CONFIG_NET=y
-+CONFIG_PACKET=y
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-+# CONFIG_INET_XFRM_MODE_BEET is not set
-+# CONFIG_INET_LRO is not set
-+# CONFIG_INET_DIAG is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_WIRELESS is not set
-+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-+CONFIG_SCSI=y
-+CONFIG_BLK_DEV_SD=y
-+CONFIG_MD=y
-+CONFIG_BLK_DEV_DM=y
-+CONFIG_NETDEVICES=y
-+# CONFIG_NET_VENDOR_BROADCOM is not set
-+# CONFIG_NET_VENDOR_CHELSIO is not set
-+# CONFIG_NET_VENDOR_FARADAY is not set
-+# CONFIG_NET_VENDOR_INTEL is not set
-+# CONFIG_NET_VENDOR_MARVELL is not set
-+# CONFIG_NET_VENDOR_MICREL is not set
-+# CONFIG_NET_VENDOR_NATSEMI is not set
-+CONFIG_SH_ETH=y
-+# CONFIG_NET_VENDOR_SEEQ is not set
-+# CONFIG_NET_VENDOR_STMICRO is not set
-+# CONFIG_WLAN is not set
-+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-+CONFIG_INPUT_EVDEV=y
-+# CONFIG_KEYBOARD_ATKBD is not set
-+CONFIG_KEYBOARD_GPIO=y
-+# CONFIG_INPUT_MOUSE is not set
-+CONFIG_INPUT_TOUCHSCREEN=y
-+CONFIG_TOUCHSCREEN_ST1232=y
-+# CONFIG_SERIO is not set
-+# CONFIG_LEGACY_PTYS is not set
-+CONFIG_SERIAL_SH_SCI=y
-+CONFIG_SERIAL_SH_SCI_NR_UARTS=8
-+CONFIG_SERIAL_SH_SCI_CONSOLE=y
-+# CONFIG_HW_RANDOM is not set
-+CONFIG_I2C=y
-+CONFIG_I2C_SH_MOBILE=y
-+# CONFIG_HWMON is not set
-+CONFIG_FB=y
-+CONFIG_FB_MODE_HELPERS=y
-+CONFIG_FB_SH_MOBILE_LCDC=y
-+CONFIG_LCD_CLASS_DEVICE=y
-+CONFIG_FRAMEBUFFER_CONSOLE=y
-+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
-+CONFIG_LOGO=y
-+# CONFIG_LOGO_LINUX_MONO is not set
-+# CONFIG_LOGO_LINUX_VGA16 is not set
-+CONFIG_SOUND=y
-+CONFIG_SND=y
-+# CONFIG_SND_SUPPORT_OLD_API is not set
-+# CONFIG_SND_VERBOSE_PROCFS is not set
-+# CONFIG_SND_DRIVERS is not set
-+# CONFIG_SND_ARM is not set
-+CONFIG_SND_SOC=y
-+CONFIG_SND_SOC_SH4_FSI=y
-+# CONFIG_HID_SUPPORT is not set
-+# CONFIG_USB_SUPPORT is not set
-+CONFIG_UIO=y
-+CONFIG_UIO_PDRV_GENIRQ=y
-+# CONFIG_DNOTIFY is not set
-+CONFIG_MSDOS_FS=y
-+CONFIG_VFAT_FS=y
-+CONFIG_TMPFS=y
-+# CONFIG_MISC_FILESYSTEMS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+CONFIG_NFS_V3_ACL=y
-+CONFIG_NFS_V4=y
-+CONFIG_NFS_V4_1=y
-+CONFIG_ROOT_NFS=y
-+CONFIG_NLS_CODEPAGE_437=y
-+CONFIG_NLS_ISO8859_1=y
-+# CONFIG_ENABLE_WARN_DEPRECATED is not set
-+# CONFIG_ENABLE_MUST_CHECK is not set
-+CONFIG_MAGIC_SYSRQ=y
-+CONFIG_DEBUG_SECTION_MISMATCH=y
-+CONFIG_DEBUG_KERNEL=y
-+CONFIG_LOCKUP_DETECTOR=y
-+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
-+# CONFIG_DETECT_HUNG_TASK is not set
-+# CONFIG_SCHED_DEBUG is not set
-+CONFIG_DEBUG_KMEMLEAK=y
-+CONFIG_DEBUG_SPINLOCK=y
-+CONFIG_DEBUG_INFO=y
-+# CONFIG_FTRACE is not set
-+CONFIG_CRYPTO=y
-+CONFIG_CRYPTO_CBC=y
-+CONFIG_CRYPTO_MD5=y
-+CONFIG_CRYPTO_DES=y
-+CONFIG_CRYPTO_ANSI_CPRNG=y
-+CONFIG_XZ_DEC=y
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 4dac8081711cdd9f55ee3191344bff84f7b573ff Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Fri, 6 Apr 2012 01:30:09 -0700
-Subject: ARM: mach-shmobile: armadillo800eva: add support LCDC0
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit dad29d1c29b7a8699403e45822065d979309f756)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 105 +++++++++++++++++++++++++
- 1 file changed, 105 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index 28bc259..5cc17a8 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -24,6 +24,7 @@
- #include <linux/kernel.h>
- #include <linux/platform_device.h>
- #include <linux/gpio.h>
-+#include <linux/videodev2.h>
- #include <mach/common.h>
- #include <mach/irqs.h>
- #include <asm/page.h>
-@@ -33,6 +34,7 @@
- #include <asm/mach/time.h>
- #include <asm/hardware/cache-l2x0.h>
- #include <mach/r8a7740.h>
-+#include <video/sh_mobile_lcdc.h>
-
- /*
- * CON1 Camera Module
-@@ -92,10 +94,66 @@
- *-----------+---------------+----------------------------
- */
-
-+/* LCDC */
-+static struct fb_videomode lcdc0_mode = {
-+ .name = "AMPIER/AM-800480",
-+ .xres = 800,
-+ .yres = 480,
-+ .left_margin = 88,
-+ .right_margin = 40,
-+ .hsync_len = 128,
-+ .upper_margin = 20,
-+ .lower_margin = 5,
-+ .vsync_len = 5,
-+ .sync = 0,
-+};
-+
-+static struct sh_mobile_lcdc_info lcdc0_info = {
-+ .clock_source = LCDC_CLK_BUS,
-+ .ch[0] = {
-+ .chan = LCDC_CHAN_MAINLCD,
-+ .fourcc = V4L2_PIX_FMT_RGB565,
-+ .interface_type = RGB24,
-+ .clock_divider = 5,
-+ .flags = 0,
-+ .lcd_modes = &lcdc0_mode,
-+ .num_modes = 1,
-+ .panel_cfg = {
-+ .width = 111,
-+ .height = 68,
-+ },
-+ },
-+};
-+
-+static struct resource lcdc0_resources[] = {
-+ [0] = {
-+ .name = "LCD0",
-+ .start = 0xfe940000,
-+ .end = 0xfe943fff,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = intcs_evt2irq(0x580),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device lcdc0_device = {
-+ .name = "sh_mobile_lcdc_fb",
-+ .num_resources = ARRAY_SIZE(lcdc0_resources),
-+ .resource = lcdc0_resources,
-+ .id = 0,
-+ .dev = {
-+ .platform_data = &lcdc0_info,
-+ .coherent_dma_mask = ~0,
-+ },
-+};
-+
- /*
- * board devices
- */
- static struct platform_device *eva_devices[] __initdata = {
-+ &lcdc0_device,
- };
-
- /*
-@@ -109,6 +167,53 @@ static void __init eva_init(void)
- gpio_request(GPIO_FN_SCIFA1_RXD, NULL);
- gpio_request(GPIO_FN_SCIFA1_TXD, NULL);
-
-+ /* LCDC0 */
-+ gpio_request(GPIO_FN_LCDC0_SELECT, NULL);
-+ gpio_request(GPIO_FN_LCD0_D0, NULL);
-+ gpio_request(GPIO_FN_LCD0_D1, NULL);
-+ gpio_request(GPIO_FN_LCD0_D2, NULL);
-+ gpio_request(GPIO_FN_LCD0_D3, NULL);
-+ gpio_request(GPIO_FN_LCD0_D4, NULL);
-+ gpio_request(GPIO_FN_LCD0_D5, NULL);
-+ gpio_request(GPIO_FN_LCD0_D6, NULL);
-+ gpio_request(GPIO_FN_LCD0_D7, NULL);
-+ gpio_request(GPIO_FN_LCD0_D8, NULL);
-+ gpio_request(GPIO_FN_LCD0_D9, NULL);
-+ gpio_request(GPIO_FN_LCD0_D10, NULL);
-+ gpio_request(GPIO_FN_LCD0_D11, NULL);
-+ gpio_request(GPIO_FN_LCD0_D12, NULL);
-+ gpio_request(GPIO_FN_LCD0_D13, NULL);
-+ gpio_request(GPIO_FN_LCD0_D14, NULL);
-+ gpio_request(GPIO_FN_LCD0_D15, NULL);
-+ gpio_request(GPIO_FN_LCD0_D16, NULL);
-+ gpio_request(GPIO_FN_LCD0_D17, NULL);
-+ gpio_request(GPIO_FN_LCD0_D18_PORT40, NULL);
-+ gpio_request(GPIO_FN_LCD0_D19_PORT4, NULL);
-+ gpio_request(GPIO_FN_LCD0_D20_PORT3, NULL);
-+ gpio_request(GPIO_FN_LCD0_D21_PORT2, NULL);
-+ gpio_request(GPIO_FN_LCD0_D22_PORT0, NULL);
-+ gpio_request(GPIO_FN_LCD0_D23_PORT1, NULL);
-+ gpio_request(GPIO_FN_LCD0_DCK, NULL);
-+ gpio_request(GPIO_FN_LCD0_VSYN, NULL);
-+ gpio_request(GPIO_FN_LCD0_HSYN, NULL);
-+ gpio_request(GPIO_FN_LCD0_DISP, NULL);
-+ gpio_request(GPIO_FN_LCD0_LCLK_PORT165, NULL);
-+
-+ gpio_request(GPIO_PORT61, NULL); /* LCDDON */
-+ gpio_direction_output(GPIO_PORT61, 1);
-+
-+ gpio_request(GPIO_PORT202, NULL); /* LCD0_LED_CONT */
-+ gpio_direction_output(GPIO_PORT202, 0);
-+
-+ /*
-+ * CAUTION
-+ *
-+ * DBGMD/LCDC0/FSIA MUX
-+ * DBGMD_SELECT_B should be set after setting PFC Function.
-+ */
-+ gpio_request(GPIO_PORT176, NULL);
-+ gpio_direction_output(GPIO_PORT176, 1);
-+
- #ifdef CONFIG_CACHE_L2X0
- /* Early BRESP enable, Shared attribute override enable, 32K*8way */
- l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 683089b4115c60b9b9f35ec3f5d91122a8a416e1 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Fri, 6 Apr 2012 01:31:33 -0700
-Subject: ARM: mach-shmobile: armadillo800eva: add support gpio_key
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit f7e7d31a1299e11be780f8e2d235570792849e31)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 26 ++++++++++++++++++++++++++
- 1 file changed, 26 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index 5cc17a8..0bce9b8 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -22,8 +22,10 @@
- #include <linux/clk.h>
- #include <linux/err.h>
- #include <linux/kernel.h>
-+#include <linux/input.h>
- #include <linux/platform_device.h>
- #include <linux/gpio.h>
-+#include <linux/gpio_keys.h>
- #include <linux/videodev2.h>
- #include <mach/common.h>
- #include <mach/irqs.h>
-@@ -149,11 +151,35 @@ static struct platform_device lcdc0_device = {
- },
- };
-
-+/* GPIO KEY */
-+#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
-+
-+static struct gpio_keys_button gpio_buttons[] = {
-+ GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW1"),
-+ GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW2"),
-+ GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW3"),
-+ GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW4"),
-+};
-+
-+static struct gpio_keys_platform_data gpio_key_info = {
-+ .buttons = gpio_buttons,
-+ .nbuttons = ARRAY_SIZE(gpio_buttons),
-+};
-+
-+static struct platform_device gpio_keys_device = {
-+ .name = "gpio-keys",
-+ .id = -1,
-+ .dev = {
-+ .platform_data = &gpio_key_info,
-+ },
-+};
-+
- /*
- * board devices
- */
- static struct platform_device *eva_devices[] __initdata = {
- &lcdc0_device,
-+ &gpio_keys_device,
- };
-
- /*
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ab1150c0be9d95c57f6f03a56917c77b2af01bce Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Fri, 6 Apr 2012 01:32:02 -0700
-Subject: ARM: mach-shmobile: armadillo800eva: add support sh_eth
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit d8fed1e254ba1ed38fd2977fdac4c2e35ed5dbc1)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 58 ++++++++++++++++++++++++++
- 1 file changed, 58 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index 0bce9b8..d439e7f 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -26,6 +26,7 @@
- #include <linux/platform_device.h>
- #include <linux/gpio.h>
- #include <linux/gpio_keys.h>
-+#include <linux/sh_eth.h>
- #include <linux/videodev2.h>
- #include <mach/common.h>
- #include <mach/irqs.h>
-@@ -96,6 +97,38 @@
- *-----------+---------------+----------------------------
- */
-
-+/* Ether */
-+static struct sh_eth_plat_data sh_eth_platdata = {
-+ .phy = 0x00, /* LAN8710A */
-+ .edmac_endian = EDMAC_LITTLE_ENDIAN,
-+ .register_type = SH_ETH_REG_GIGABIT,
-+ .phy_interface = PHY_INTERFACE_MODE_MII,
-+};
-+
-+static struct resource sh_eth_resources[] = {
-+ {
-+ .start = 0xe9a00000,
-+ .end = 0xe9a00800 - 1,
-+ .flags = IORESOURCE_MEM,
-+ }, {
-+ .start = 0xe9a01800,
-+ .end = 0xe9a02000 - 1,
-+ .flags = IORESOURCE_MEM,
-+ }, {
-+ .start = evt2irq(0x0500),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device sh_eth_device = {
-+ .name = "sh-eth",
-+ .dev = {
-+ .platform_data = &sh_eth_platdata,
-+ },
-+ .resource = sh_eth_resources,
-+ .num_resources = ARRAY_SIZE(sh_eth_resources),
-+};
-+
- /* LCDC */
- static struct fb_videomode lcdc0_mode = {
- .name = "AMPIER/AM-800480",
-@@ -180,6 +213,7 @@ static struct platform_device gpio_keys_device = {
- static struct platform_device *eva_devices[] __initdata = {
- &lcdc0_device,
- &gpio_keys_device,
-+ &sh_eth_device,
- };
-
- /*
-@@ -231,6 +265,30 @@ static void __init eva_init(void)
- gpio_request(GPIO_PORT202, NULL); /* LCD0_LED_CONT */
- gpio_direction_output(GPIO_PORT202, 0);
-
-+ /* GETHER */
-+ gpio_request(GPIO_FN_ET_CRS, NULL);
-+ gpio_request(GPIO_FN_ET_MDC, NULL);
-+ gpio_request(GPIO_FN_ET_MDIO, NULL);
-+ gpio_request(GPIO_FN_ET_TX_ER, NULL);
-+ gpio_request(GPIO_FN_ET_RX_ER, NULL);
-+ gpio_request(GPIO_FN_ET_ERXD0, NULL);
-+ gpio_request(GPIO_FN_ET_ERXD1, NULL);
-+ gpio_request(GPIO_FN_ET_ERXD2, NULL);
-+ gpio_request(GPIO_FN_ET_ERXD3, NULL);
-+ gpio_request(GPIO_FN_ET_TX_CLK, NULL);
-+ gpio_request(GPIO_FN_ET_TX_EN, NULL);
-+ gpio_request(GPIO_FN_ET_ETXD0, NULL);
-+ gpio_request(GPIO_FN_ET_ETXD1, NULL);
-+ gpio_request(GPIO_FN_ET_ETXD2, NULL);
-+ gpio_request(GPIO_FN_ET_ETXD3, NULL);
-+ gpio_request(GPIO_FN_ET_PHY_INT, NULL);
-+ gpio_request(GPIO_FN_ET_COL, NULL);
-+ gpio_request(GPIO_FN_ET_RX_DV, NULL);
-+ gpio_request(GPIO_FN_ET_RX_CLK, NULL);
-+
-+ gpio_request(GPIO_PORT18, NULL); /* PHY_RST */
-+ gpio_direction_output(GPIO_PORT18, 1);
-+
- /*
- * CAUTION
- *
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 6c075ffc555411ed9a75c338058837c617323f16 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Fri, 6 Apr 2012 01:30:42 -0700
-Subject: ARM: mach-shmobile: armadillo800eva: add support ST1232
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Reviewed-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 46cf668748070e54879d528fa58107abc835dff3)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 15 +++++++++++++++
- 1 file changed, 15 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index d439e7f..4d066f9 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -207,6 +207,14 @@ static struct platform_device gpio_keys_device = {
- },
- };
-
-+/* I2C */
-+static struct i2c_board_info i2c0_devices[] = {
-+ {
-+ I2C_BOARD_INFO("st1232-ts", 0x55),
-+ .irq = evt2irq(0x0340),
-+ },
-+};
-+
- /*
- * board devices
- */
-@@ -265,6 +273,11 @@ static void __init eva_init(void)
- gpio_request(GPIO_PORT202, NULL); /* LCD0_LED_CONT */
- gpio_direction_output(GPIO_PORT202, 0);
-
-+ /* Touchscreen */
-+ gpio_request(GPIO_FN_IRQ10, NULL); /* TP_INT */
-+ gpio_request(GPIO_PORT166, NULL); /* TP_RST_B */
-+ gpio_direction_output(GPIO_PORT166, 1);
-+
- /* GETHER */
- gpio_request(GPIO_FN_ET_CRS, NULL);
- gpio_request(GPIO_FN_ET_MDC, NULL);
-@@ -303,6 +316,8 @@ static void __init eva_init(void)
- l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff);
- #endif
-
-+ i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices));
-+
- r8a7740_add_standard_devices();
-
- platform_add_devices(eva_devices,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 1dae1324b5c1a1b5c27de07729b9b52a61037b3e Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 24 Apr 2012 02:09:08 -0700
-Subject: ARM: mach-shmobile: armadillo800eva: add USB function support
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 1c96293e9f8b8ec9620201bcf7f776f0e0f89edb)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 247 ++++++++++++++++++++++++-
- 1 file changed, 237 insertions(+), 10 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index 4d066f9..1d25d5f 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -20,14 +20,17 @@
- */
-
- #include <linux/clk.h>
-+#include <linux/delay.h>
- #include <linux/err.h>
- #include <linux/kernel.h>
- #include <linux/input.h>
-+#include <linux/irq.h>
- #include <linux/platform_device.h>
- #include <linux/gpio.h>
- #include <linux/gpio_keys.h>
- #include <linux/sh_eth.h>
- #include <linux/videodev2.h>
-+#include <linux/usb/renesas_usbhs.h>
- #include <mach/common.h>
- #include <mach/irqs.h>
- #include <asm/page.h>
-@@ -90,6 +93,9 @@
- * 0 | SDHI1 | COM8 enable, COM14 disable
- * 1 | SDHI1 | COM8 enable, COM14 disable
- * -12345678-+---------------+----------------------------
-+ * 0 | USB0 | COM20 enable, COM24 disable
-+ * 1 | USB0 | COM20 disable, COM24 enable
-+ * -12345678-+---------------+----------------------------
- * 00 | JTAG | SH-X2
- * 10 | JTAG | ARM
- * 01 | JTAG | -
-@@ -97,6 +103,195 @@
- *-----------+---------------+----------------------------
- */
-
-+/*
-+ * USB function
-+ *
-+ * When you use USB Function,
-+ * set SW1.6 ON, and connect cable to CN24.
-+ *
-+ * USBF needs workaround on R8A7740 chip.
-+ * These are a little bit complex.
-+ * see
-+ * usbhsf_power_ctrl()
-+ *
-+ * CAUTION
-+ *
-+ * It uses autonomy mode for USB hotplug at this point
-+ * (= usbhs_private.platform_callback.get_vbus is NULL),
-+ * since we don't know what's happen on PM control
-+ * on this workaround.
-+ */
-+#define USBCR1 0xe605810a
-+#define USBH 0xC6700000
-+#define USBH_USBCTR 0x10834
-+
-+struct usbhsf_private {
-+ struct clk *phy;
-+ struct clk *usb24;
-+ struct clk *pci;
-+ struct clk *func;
-+ struct clk *host;
-+ void __iomem *usbh_base;
-+ struct renesas_usbhs_platform_info info;
-+};
-+
-+#define usbhsf_get_priv(pdev) \
-+ container_of(renesas_usbhs_get_info(pdev), \
-+ struct usbhsf_private, info)
-+
-+static int usbhsf_get_id(struct platform_device *pdev)
-+{
-+ return USBHS_GADGET;
-+}
-+
-+static void usbhsf_power_ctrl(struct platform_device *pdev,
-+ void __iomem *base, int enable)
-+{
-+ struct usbhsf_private *priv = usbhsf_get_priv(pdev);
-+
-+ /*
-+ * Work around for USB Function.
-+ * It needs USB host clock, and settings
-+ */
-+ if (enable) {
-+ /*
-+ * enable all the related usb clocks
-+ * for usb workaround
-+ */
-+ clk_enable(priv->usb24);
-+ clk_enable(priv->pci);
-+ clk_enable(priv->host);
-+ clk_enable(priv->func);
-+ clk_enable(priv->phy);
-+
-+ /*
-+ * set USBCR1
-+ *
-+ * Port1 is driven by USB function,
-+ * Port2 is driven by USB HOST
-+ * One HOST (Port1 or Port2 is HOST)
-+ * USB PLL input clock = 24MHz
-+ */
-+ __raw_writew(0xd750, USBCR1);
-+ mdelay(1);
-+
-+ /*
-+ * start USB Host
-+ */
-+ __raw_writel(0x0000000c, priv->usbh_base + USBH_USBCTR);
-+ __raw_writel(0x00000008, priv->usbh_base + USBH_USBCTR);
-+ mdelay(10);
-+
-+ /*
-+ * USB PHY Power ON
-+ */
-+ __raw_writew(0xd770, USBCR1);
-+ __raw_writew(0x4000, base + 0x102); /* USBF :: SUSPMODE */
-+
-+ } else {
-+ __raw_writel(0x0000010f, priv->usbh_base + USBH_USBCTR);
-+ __raw_writew(0xd7c0, USBCR1); /* GPIO */
-+
-+ clk_disable(priv->phy);
-+ clk_disable(priv->func); /* usb work around */
-+ clk_disable(priv->host); /* usb work around */
-+ clk_disable(priv->pci); /* usb work around */
-+ clk_disable(priv->usb24); /* usb work around */
-+ }
-+}
-+
-+static void usbhsf_hardware_exit(struct platform_device *pdev)
-+{
-+ struct usbhsf_private *priv = usbhsf_get_priv(pdev);
-+
-+ if (!IS_ERR(priv->phy))
-+ clk_put(priv->phy);
-+ if (!IS_ERR(priv->usb24))
-+ clk_put(priv->usb24);
-+ if (!IS_ERR(priv->pci))
-+ clk_put(priv->pci);
-+ if (!IS_ERR(priv->host))
-+ clk_put(priv->host);
-+ if (!IS_ERR(priv->func))
-+ clk_put(priv->func);
-+ if (priv->usbh_base)
-+ iounmap(priv->usbh_base);
-+
-+ priv->phy = NULL;
-+ priv->usb24 = NULL;
-+ priv->pci = NULL;
-+ priv->host = NULL;
-+ priv->func = NULL;
-+ priv->usbh_base = NULL;
-+}
-+
-+static int usbhsf_hardware_init(struct platform_device *pdev)
-+{
-+ struct usbhsf_private *priv = usbhsf_get_priv(pdev);
-+
-+ priv->phy = clk_get(&pdev->dev, "phy");
-+ priv->usb24 = clk_get(&pdev->dev, "usb24");
-+ priv->pci = clk_get(&pdev->dev, "pci");
-+ priv->func = clk_get(&pdev->dev, "func");
-+ priv->host = clk_get(&pdev->dev, "host");
-+ priv->usbh_base = ioremap_nocache(USBH, 0x20000);
-+
-+ if (IS_ERR(priv->phy) ||
-+ IS_ERR(priv->usb24) ||
-+ IS_ERR(priv->pci) ||
-+ IS_ERR(priv->host) ||
-+ IS_ERR(priv->func) ||
-+ !priv->usbh_base) {
-+ dev_err(&pdev->dev, "USB clock setting failed\n");
-+ usbhsf_hardware_exit(pdev);
-+ return -EIO;
-+ }
-+
-+ /* usb24 use 1/1 of parent clock (= usb24s = 24MHz) */
-+ clk_set_rate(priv->usb24,
-+ clk_get_rate(clk_get_parent(priv->usb24)));
-+
-+ return 0;
-+}
-+
-+static struct usbhsf_private usbhsf_private = {
-+ .info = {
-+ .platform_callback = {
-+ .get_id = usbhsf_get_id,
-+ .hardware_init = usbhsf_hardware_init,
-+ .hardware_exit = usbhsf_hardware_exit,
-+ .power_ctrl = usbhsf_power_ctrl,
-+ },
-+ .driver_param = {
-+ .buswait_bwait = 5,
-+ .detection_delay = 5,
-+ },
-+ }
-+};
-+
-+static struct resource usbhsf_resources[] = {
-+ {
-+ .name = "USBHS",
-+ .start = 0xe6890000,
-+ .end = 0xe6890104 - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ .start = evt2irq(0x0A20),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device usbhsf_device = {
-+ .name = "renesas_usbhs",
-+ .dev = {
-+ .platform_data = &usbhsf_private.info,
-+ },
-+ .id = -1,
-+ .num_resources = ARRAY_SIZE(usbhsf_resources),
-+ .resource = usbhsf_resources,
-+};
-+
- /* Ether */
- static struct sh_eth_plat_data sh_eth_platdata = {
- .phy = 0x00, /* LAN8710A */
-@@ -224,11 +419,41 @@ static struct platform_device *eva_devices[] __initdata = {
- &sh_eth_device,
- };
-
-+static void __init eva_clock_init(void)
-+{
-+ struct clk *system = clk_get(NULL, "system_clk");
-+ struct clk *xtal1 = clk_get(NULL, "extal1");
-+ struct clk *usb24s = clk_get(NULL, "usb24s");
-+
-+ if (IS_ERR(system) ||
-+ IS_ERR(xtal1) ||
-+ IS_ERR(usb24s)) {
-+ pr_err("armadillo800eva board clock init failed\n");
-+ goto clock_error;
-+ }
-+
-+ /* armadillo 800 eva extal1 is 24MHz */
-+ clk_set_rate(xtal1, 24000000);
-+
-+ /* usb24s use extal1 (= system) clock (= 24MHz) */
-+ clk_set_parent(usb24s, system);
-+
-+clock_error:
-+ if (!IS_ERR(system))
-+ clk_put(system);
-+ if (!IS_ERR(xtal1))
-+ clk_put(xtal1);
-+ if (!IS_ERR(usb24s))
-+ clk_put(usb24s);
-+}
-+
- /*
- * board init
- */
- static void __init eva_init(void)
- {
-+ eva_clock_init();
-+
- r8a7740_pinmux_init();
-
- /* SCIFA1 */
-@@ -302,6 +527,18 @@ static void __init eva_init(void)
- gpio_request(GPIO_PORT18, NULL); /* PHY_RST */
- gpio_direction_output(GPIO_PORT18, 1);
-
-+ /* USB */
-+ gpio_request(GPIO_PORT159, NULL); /* USB_DEVICE_MODE */
-+ gpio_direction_input(GPIO_PORT159);
-+
-+ if (gpio_get_value(GPIO_PORT159)) {
-+ /* USB Host */
-+ } else {
-+ /* USB Func */
-+ gpio_request(GPIO_FN_VBUS, NULL);
-+ platform_device_register(&usbhsf_device);
-+ }
-+
- /*
- * CAUTION
- *
-@@ -326,17 +563,7 @@ static void __init eva_init(void)
-
- static void __init eva_earlytimer_init(void)
- {
-- struct clk *xtal1;
--
- r8a7740_clock_init(MD_CK0 | MD_CK2);
--
-- xtal1 = clk_get(NULL, "extal1");
-- if (!IS_ERR(xtal1)) {
-- /* armadillo 800 eva extal1 is 24MHz */
-- clk_set_rate(xtal1, 24000000);
-- clk_put(xtal1);
-- }
--
- shmobile_earlytimer_init();
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 4cc08f83ce664539a9c3dab8a1b486002346ee83 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 24 Apr 2012 02:09:19 -0700
-Subject: ARM: mach-shmobile: armadillo800eva: add SDHI0 support
-
-On armadillo800eva board,
-CD (= Card Detect) pin is not connected to SDHI0_CD.
-Then, we can use IRQ31 as card detect irq,
-but it needs chattering removal operation.
-We should use IRQ card detect in the future,
-but this patch use polling mode at this point.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 49c01112d6afdb679276c172ffcd4f1205c1ff97)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 71 ++++++++++++++++++++++++++
- 1 file changed, 71 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index 1d25d5f..ed85686 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -31,6 +31,9 @@
- #include <linux/sh_eth.h>
- #include <linux/videodev2.h>
- #include <linux/usb/renesas_usbhs.h>
-+#include <linux/mfd/tmio.h>
-+#include <linux/mmc/host.h>
-+#include <linux/mmc/sh_mobile_sdhi.h>
- #include <mach/common.h>
- #include <mach/irqs.h>
- #include <asm/page.h>
-@@ -402,6 +405,55 @@ static struct platform_device gpio_keys_device = {
- },
- };
-
-+/* SDHI0 */
-+/*
-+ * FIXME
-+ *
-+ * It use polling mode here, since
-+ * CD (= Card Detect) pin is not connected to SDHI0_CD.
-+ * We can use IRQ31 as card detect irq,
-+ * but it needs chattering removal operation
-+ */
-+#define IRQ31 evt2irq(0x33E0)
-+static struct sh_mobile_sdhi_info sdhi0_info = {
-+ .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |\
-+ MMC_CAP_NEEDS_POLL,
-+ .tmio_ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
-+ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
-+};
-+
-+static struct resource sdhi0_resources[] = {
-+ {
-+ .name = "SDHI0",
-+ .start = 0xe6850000,
-+ .end = 0xe6850100 - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ /*
-+ * no SH_MOBILE_SDHI_IRQ_CARD_DETECT here
-+ */
-+ {
-+ .name = SH_MOBILE_SDHI_IRQ_SDCARD,
-+ .start = evt2irq(0x0E20),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ {
-+ .name = SH_MOBILE_SDHI_IRQ_SDIO,
-+ .start = evt2irq(0x0E40),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device sdhi0_device = {
-+ .name = "sh_mobile_sdhi",
-+ .id = 0,
-+ .dev = {
-+ .platform_data = &sdhi0_info,
-+ },
-+ .num_resources = ARRAY_SIZE(sdhi0_resources),
-+ .resource = sdhi0_resources,
-+};
-+
- /* I2C */
- static struct i2c_board_info i2c0_devices[] = {
- {
-@@ -417,6 +469,7 @@ static struct platform_device *eva_devices[] __initdata = {
- &lcdc0_device,
- &gpio_keys_device,
- &sh_eth_device,
-+ &sdhi0_device,
- };
-
- static void __init eva_clock_init(void)
-@@ -539,6 +592,24 @@ static void __init eva_init(void)
- platform_device_register(&usbhsf_device);
- }
-
-+ /* SDHI0 */
-+ gpio_request(GPIO_FN_SDHI0_CMD, NULL);
-+ gpio_request(GPIO_FN_SDHI0_CLK, NULL);
-+ gpio_request(GPIO_FN_SDHI0_D0, NULL);
-+ gpio_request(GPIO_FN_SDHI0_D1, NULL);
-+ gpio_request(GPIO_FN_SDHI0_D2, NULL);
-+ gpio_request(GPIO_FN_SDHI0_D3, NULL);
-+ gpio_request(GPIO_FN_SDHI0_WP, NULL);
-+
-+ gpio_request(GPIO_PORT17, NULL); /* SDHI0_18/33_B */
-+ gpio_request(GPIO_PORT74, NULL); /* SDHI0_PON */
-+ gpio_request(GPIO_PORT75, NULL); /* SDSLOT1_PON */
-+ gpio_direction_output(GPIO_PORT17, 0);
-+ gpio_direction_output(GPIO_PORT74, 1);
-+ gpio_direction_output(GPIO_PORT75, 1);
-+
-+ /* we can use GPIO_FN_IRQ31_PORT167 here for SDHI0 CD irq */
-+
- /*
- * CAUTION
- *
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 78c21b71d7b4c9b2a5b2a785aca79aee0b9ffba2 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 24 Apr 2012 02:09:31 -0700
-Subject: ARM: mach-shmobile: armadillo800eva: add SDHI1 support
-
-We can switch CON8/CON14 by SW1.5
-SDHI1 is CON8 (SW1.5 = ON)
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 2e3a5ef28f8182c439a5a276ff4c0883c02787f4)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 66 +++++++++++++++++++++++++-
- 1 file changed, 65 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index ed85686..5f62428 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -93,7 +93,7 @@
- * 0 | Extension Bus | D8-D15 disable, eMMC enable
- * 1 | Extension Bus | D8-D15 enable, eMMC disable
- * -12345678-+---------------+----------------------------
-- * 0 | SDHI1 | COM8 enable, COM14 disable
-+ * 0 | SDHI1 | COM8 disable, COM14 enable
- * 1 | SDHI1 | COM8 enable, COM14 disable
- * -12345678-+---------------+----------------------------
- * 0 | USB0 | COM20 enable, COM24 disable
-@@ -454,6 +454,44 @@ static struct platform_device sdhi0_device = {
- .resource = sdhi0_resources,
- };
-
-+/* SDHI1 */
-+static struct sh_mobile_sdhi_info sdhi1_info = {
-+ .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
-+ .tmio_ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
-+ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
-+};
-+
-+static struct resource sdhi1_resources[] = {
-+ [0] = {
-+ .name = "SDHI1",
-+ .start = 0xe6860000,
-+ .end = 0xe6860100 - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = evt2irq(0x0E80),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [2] = {
-+ .start = evt2irq(0x0EA0),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [3] = {
-+ .start = evt2irq(0x0EC0),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device sdhi1_device = {
-+ .name = "sh_mobile_sdhi",
-+ .id = 1,
-+ .dev = {
-+ .platform_data = &sdhi1_info,
-+ },
-+ .num_resources = ARRAY_SIZE(sdhi1_resources),
-+ .resource = sdhi1_resources,
-+};
-+
- /* I2C */
- static struct i2c_board_info i2c0_devices[] = {
- {
-@@ -619,6 +657,32 @@ static void __init eva_init(void)
- gpio_request(GPIO_PORT176, NULL);
- gpio_direction_output(GPIO_PORT176, 1);
-
-+ /*
-+ * We can switch CON8/CON14 by SW1.5,
-+ * but it needs after DBGMD_SELECT_B
-+ */
-+ gpio_request(GPIO_PORT6, NULL);
-+ gpio_direction_input(GPIO_PORT6);
-+ if (gpio_get_value(GPIO_PORT6)) {
-+ /* CON14 enable */
-+ } else {
-+ /* CON8 (SDHI1) enable */
-+ gpio_request(GPIO_FN_SDHI1_CLK, NULL);
-+ gpio_request(GPIO_FN_SDHI1_CMD, NULL);
-+ gpio_request(GPIO_FN_SDHI1_D0, NULL);
-+ gpio_request(GPIO_FN_SDHI1_D1, NULL);
-+ gpio_request(GPIO_FN_SDHI1_D2, NULL);
-+ gpio_request(GPIO_FN_SDHI1_D3, NULL);
-+ gpio_request(GPIO_FN_SDHI1_CD, NULL);
-+ gpio_request(GPIO_FN_SDHI1_WP, NULL);
-+
-+ gpio_request(GPIO_PORT16, NULL); /* SDSLOT2_PON */
-+ gpio_direction_output(GPIO_PORT16, 1);
-+
-+ platform_device_register(&sdhi1_device);
-+ }
-+
-+
- #ifdef CONFIG_CACHE_L2X0
- /* Early BRESP enable, Shared attribute override enable, 32K*8way */
- l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 0d4e5e39563404cb97b24a37388535b6c54ac90d Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 24 Apr 2012 02:09:42 -0700
-Subject: ARM: mach-shmobile: armadillo800eva: add MMCIF support
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 0a4266bb22774bb0b6390d2633a151d996a14e77)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 57 ++++++++++++++++++++++++++
- 1 file changed, 57 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index 5f62428..0cfaec5 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -33,6 +33,7 @@
- #include <linux/usb/renesas_usbhs.h>
- #include <linux/mfd/tmio.h>
- #include <linux/mmc/host.h>
-+#include <linux/mmc/sh_mmcif.h>
- #include <linux/mmc/sh_mobile_sdhi.h>
- #include <mach/common.h>
- #include <mach/irqs.h>
-@@ -492,6 +493,44 @@ static struct platform_device sdhi1_device = {
- .resource = sdhi1_resources,
- };
-
-+/* MMCIF */
-+static struct sh_mmcif_plat_data sh_mmcif_plat = {
-+ .sup_pclk = 0,
-+ .ocr = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
-+ .caps = MMC_CAP_4_BIT_DATA |
-+ MMC_CAP_8_BIT_DATA |
-+ MMC_CAP_NONREMOVABLE,
-+};
-+
-+static struct resource sh_mmcif_resources[] = {
-+ [0] = {
-+ .name = "MMCIF",
-+ .start = 0xe6bd0000,
-+ .end = 0xe6bd0100 - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ /* MMC ERR */
-+ .start = evt2irq(0x1AC0),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [2] = {
-+ /* MMC NOR */
-+ .start = evt2irq(0x1AE0),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device sh_mmcif_device = {
-+ .name = "sh_mmcif",
-+ .id = -1,
-+ .dev = {
-+ .platform_data = &sh_mmcif_plat,
-+ },
-+ .num_resources = ARRAY_SIZE(sh_mmcif_resources),
-+ .resource = sh_mmcif_resources,
-+};
-+
- /* I2C */
- static struct i2c_board_info i2c0_devices[] = {
- {
-@@ -508,6 +547,7 @@ static struct platform_device *eva_devices[] __initdata = {
- &gpio_keys_device,
- &sh_eth_device,
- &sdhi0_device,
-+ &sh_mmcif_device,
- };
-
- static void __init eva_clock_init(void)
-@@ -649,6 +689,23 @@ static void __init eva_init(void)
- /* we can use GPIO_FN_IRQ31_PORT167 here for SDHI0 CD irq */
-
- /*
-+ * MMCIF
-+ *
-+ * Here doesn't care SW1.4 status,
-+ * since CON2 is not mounted.
-+ */
-+ gpio_request(GPIO_FN_MMC1_CLK_PORT103, NULL);
-+ gpio_request(GPIO_FN_MMC1_CMD_PORT104, NULL);
-+ gpio_request(GPIO_FN_MMC1_D0_PORT149, NULL);
-+ gpio_request(GPIO_FN_MMC1_D1_PORT148, NULL);
-+ gpio_request(GPIO_FN_MMC1_D2_PORT147, NULL);
-+ gpio_request(GPIO_FN_MMC1_D3_PORT146, NULL);
-+ gpio_request(GPIO_FN_MMC1_D4_PORT145, NULL);
-+ gpio_request(GPIO_FN_MMC1_D5_PORT144, NULL);
-+ gpio_request(GPIO_FN_MMC1_D6_PORT143, NULL);
-+ gpio_request(GPIO_FN_MMC1_D7_PORT142, NULL);
-+
-+ /*
- * CAUTION
- *
- * DBGMD/LCDC0/FSIA MUX
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 3d1f581e9dbb224b5f0543883cc3e86876c8e5fe Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 24 Apr 2012 02:10:05 -0700
-Subject: ARM: mach-shmobile: r8a7740: reserve DMA memory for the frame buffer
-
-The default 2MB size of DMA coherent memory isn't enough for allocate
-frame buffer memory.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 3841e6f561af717478b253ce1dcba7bff9e9f890)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/setup-r8a7740.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
-index 34a1548..ec4eb49 100644
---- a/arch/arm/mach-shmobile/setup-r8a7740.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
-@@ -18,6 +18,7 @@
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #include <linux/delay.h>
-+#include <linux/dma-mapping.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/io.h>
-@@ -60,6 +61,12 @@ static struct map_desc r8a7740_io_desc[] __initdata = {
- void __init r8a7740_map_io(void)
- {
- iotable_init(r8a7740_io_desc, ARRAY_SIZE(r8a7740_io_desc));
-+
-+ /*
-+ * DMA memory at 0xff200000 - 0xffdfffff. The default 2MB size isn't
-+ * enough to allocate the frame buffer memory.
-+ */
-+ init_consistent_dma_size(12 << 20);
- }
-
- /* SCIFA0 */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From c1d7a1d9c12959dea7cc4f0552e6b7985afeb186 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Sun, 6 May 2012 22:58:41 -0700
-Subject: ARM: mach-shmobile: clock-r8a7740: add sh-eth clock
-
-armadillo800eva board is using sh-eth, but clock-r8a7740 didn't care it.
-This clock was enabled by boot-loader.
-This patch fix it up.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Reviewed-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 9c18f238c1ec36b9912b5b36ae24e0c221179044)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 1 +
- arch/arm/mach-shmobile/clock-r8a7740.c | 3 +++
- 2 files changed, 4 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index 0cfaec5..e750ea6 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -321,6 +321,7 @@ static struct resource sh_eth_resources[] = {
-
- static struct platform_device sh_eth_device = {
- .name = "sh-eth",
-+ .id = -1,
- .dev = {
- .platform_data = &sh_eth_platdata,
- },
-diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
-index 81b54a6..26eea5f 100644
---- a/arch/arm/mach-shmobile/clock-r8a7740.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
-@@ -352,6 +352,7 @@ enum {
-
- MSTP329, MSTP328, MSTP323, MSTP320,
- MSTP314, MSTP313, MSTP312,
-+ MSTP309,
-
- MSTP416, MSTP415, MSTP407, MSTP406,
-
-@@ -382,6 +383,7 @@ static struct clk mstp_clks[MSTP_NR] = {
- [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
- [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */
- [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */
-+ [MSTP309] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 9, 0), /* GEther */
-
- [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */
- [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */
-@@ -447,6 +449,7 @@ static struct clk_lookup lookups[] = {
- CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]),
- CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]),
- CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]),
-+ CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP309]),
-
- CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]),
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b578e0342552c51f1d81de4d730bf5325f52b48a Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Wed, 25 Apr 2012 20:57:13 -0700
-Subject: ARM: mach-shmobile: armadillo800eva: defconfig update
-
-This patch enable USBFunc/SHDI/MMCIF,
-remove debug settings,
-and cleanuped by c2330e286f68f1c408b4aa6515ba49d57f05beae script
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 9183857d503f915ee05abb6e03cea7253dcbace6)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/configs/armadillo800eva_defconfig | 25 ++++++++++++-------------
- 1 file changed, 12 insertions(+), 13 deletions(-)
-
-diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
-index 0d20749..ddc9fe6 100644
---- a/arch/arm/configs/armadillo800eva_defconfig
-+++ b/arch/arm/configs/armadillo800eva_defconfig
-@@ -10,7 +10,6 @@ CONFIG_LOG_BUF_SHIFT=16
- CONFIG_SYSFS_DEPRECATED=y
- CONFIG_SYSFS_DEPRECATED_V2=y
- CONFIG_CC_OPTIMIZE_FOR_SIZE=y
--CONFIG_KALLSYMS_ALL=y
- CONFIG_SLAB=y
- CONFIG_MODULES=y
- CONFIG_MODULE_UNLOAD=y
-@@ -63,6 +62,7 @@ CONFIG_BLK_DEV_DM=y
- CONFIG_NETDEVICES=y
- # CONFIG_NET_VENDOR_BROADCOM is not set
- # CONFIG_NET_VENDOR_CHELSIO is not set
-+# CONFIG_NET_VENDOR_CIRRUS is not set
- # CONFIG_NET_VENDOR_FARADAY is not set
- # CONFIG_NET_VENDOR_INTEL is not set
- # CONFIG_NET_VENDOR_MARVELL is not set
-@@ -70,6 +70,7 @@ CONFIG_NETDEVICES=y
- # CONFIG_NET_VENDOR_NATSEMI is not set
- CONFIG_SH_ETH=y
- # CONFIG_NET_VENDOR_SEEQ is not set
-+# CONFIG_NET_VENDOR_SMSC is not set
- # CONFIG_NET_VENDOR_STMICRO is not set
- # CONFIG_WLAN is not set
- # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-@@ -106,7 +107,15 @@ CONFIG_SND=y
- CONFIG_SND_SOC=y
- CONFIG_SND_SOC_SH4_FSI=y
- # CONFIG_HID_SUPPORT is not set
--# CONFIG_USB_SUPPORT is not set
-+CONFIG_USB=y
-+# CONFIG_USB_DEVICE_CLASS is not set
-+CONFIG_USB_RENESAS_USBHS=y
-+CONFIG_USB_GADGET=y
-+CONFIG_USB_RENESAS_USBHS_UDC=y
-+CONFIG_USB_ETH=m
-+CONFIG_MMC=y
-+CONFIG_MMC_SDHI=y
-+CONFIG_MMC_SH_MMCIF=y
- CONFIG_UIO=y
- CONFIG_UIO_PDRV_GENIRQ=y
- # CONFIG_DNOTIFY is not set
-@@ -124,17 +133,7 @@ CONFIG_NLS_CODEPAGE_437=y
- CONFIG_NLS_ISO8859_1=y
- # CONFIG_ENABLE_WARN_DEPRECATED is not set
- # CONFIG_ENABLE_MUST_CHECK is not set
--CONFIG_MAGIC_SYSRQ=y
--CONFIG_DEBUG_SECTION_MISMATCH=y
--CONFIG_DEBUG_KERNEL=y
--CONFIG_LOCKUP_DETECTOR=y
--CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
--# CONFIG_DETECT_HUNG_TASK is not set
--# CONFIG_SCHED_DEBUG is not set
--CONFIG_DEBUG_KMEMLEAK=y
--CONFIG_DEBUG_SPINLOCK=y
--CONFIG_DEBUG_INFO=y
--# CONFIG_FTRACE is not set
-+# CONFIG_ARM_UNWIND is not set
- CONFIG_CRYPTO=y
- CONFIG_CRYPTO_CBC=y
- CONFIG_CRYPTO_MD5=y
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e8f0e8b7d350aad665d17ffe656edaa2c2dda533 Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Mon, 14 May 2012 19:54:41 +0900
-Subject: ARM: mach-shmobile: Use DT_MACHINE for armadillo 800 eva
-
-Use DT_MACHINE_START() on the r8a7740 based armadillo 800 eva board.
-
-Also include a tiny DTS file to describe the board and update the
-Kconfig dependencies to select CONFIG_USE_OF.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit e6bf705911a0b64c589b6c408a316e7d465acbbd)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/boot/dts/r8a7740-armadillo800eva.dts | 22 ++++++++++++++++++++++
- arch/arm/mach-shmobile/Kconfig | 1 +
- arch/arm/mach-shmobile/board-armadillo800eva.c | 8 +++++++-
- 3 files changed, 30 insertions(+), 1 deletion(-)
- create mode 100644 arch/arm/boot/dts/r8a7740-armadillo800eva.dts
-
-diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
-new file mode 100644
-index 0000000..a7505a9
---- /dev/null
-+++ b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
-@@ -0,0 +1,22 @@
-+/*
-+ * Device Tree Source for the armadillo 800 eva board
-+ *
-+ * Copyright (C) 2012 Renesas Solutions Corp.
-+ *
-+ * 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.
-+ */
-+
-+/dts-v1/;
-+/include/ "skeleton.dtsi"
-+
-+/ {
-+ model = "armadillo 800 eva";
-+ compatible = "renesas,armadillo800eva";
-+
-+ memory {
-+ device_type = "memory";
-+ reg = <0x40000000 0x20000000>;
-+ };
-+};
-diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
-index 799e996..da57dde 100644
---- a/arch/arm/mach-shmobile/Kconfig
-+++ b/arch/arm/mach-shmobile/Kconfig
-@@ -99,6 +99,7 @@ config MACH_ARMADILLO800EVA
- bool "Armadillo-800 EVA board"
- depends on ARCH_R8A7740
- select ARCH_REQUIRE_GPIOLIB
-+ select USE_OF
-
- config MACH_MARZEN
- bool "MARZEN board"
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index e750ea6..9e37026 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -768,11 +768,17 @@ static void __init eva_add_early_devices(void)
- shmobile_timer.init = eva_earlytimer_init;
- }
-
--MACHINE_START(ARMADILLO800EVA, "armadillo800eva")
-+static const char *eva_boards_compat_dt[] __initdata = {
-+ "renesas,armadillo800eva",
-+ NULL,
-+};
-+
-+DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva")
- .map_io = r8a7740_map_io,
- .init_early = eva_add_early_devices,
- .init_irq = r8a7740_init_irq,
- .handle_irq = shmobile_handle_irq_intc,
- .init_machine = eva_init,
- .timer = &shmobile_timer,
-+ .dt_compat = eva_boards_compat_dt,
- MACHINE_END
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 86c25d5111c1edb9ca3cc28eaa0abd387250959a Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 12 Jun 2012 02:35:15 -0700
-Subject: ARM: shmobile: r8a7740: add HDMI interrupt support
-
-It is required from sh_mobile_hdmi driver.
-This patch is based on v1.0 manual
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 7d7136cabcad632a81cd568a9c1135db276fe0f2)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/intc-r8a7740.c | 13 +++++++++----
- 1 file changed, 9 insertions(+), 4 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/intc-r8a7740.c b/arch/arm/mach-shmobile/intc-r8a7740.c
-index 09c42af..9a69a31 100644
---- a/arch/arm/mach-shmobile/intc-r8a7740.c
-+++ b/arch/arm/mach-shmobile/intc-r8a7740.c
-@@ -71,10 +71,12 @@ enum {
- DMAC3_1_DEI0, DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3,
- DMAC3_2_DEI4, DMAC3_2_DEI5, DMAC3_2_DADERR,
- SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM,
-+ HDMI,
- USBH_INT, USBH_OHCI, USBH_EHCI, USBH_PME, USBH_BIND,
- RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF,
- SPU2_0, SPU2_1,
- FSI, FMSI,
-+ HDMI_SSS, HDMI_KEY,
- IPMMU,
- AP_ARM_CTIIRQ, AP_ARM_PMURQ,
- MFIS2,
-@@ -182,6 +184,7 @@ static struct intc_vect intca_vectors[] __initdata = {
- INTC_VECT(USBH_EHCI, 0x1580),
- INTC_VECT(USBH_PME, 0x15A0),
- INTC_VECT(USBH_BIND, 0x15C0),
-+ INTC_VECT(HDMI, 0x1700),
- INTC_VECT(RSPI_OVRF, 0x1780),
- INTC_VECT(RSPI_SPTEF, 0x17A0),
- INTC_VECT(RSPI_SPRF, 0x17C0),
-@@ -189,6 +192,8 @@ static struct intc_vect intca_vectors[] __initdata = {
- INTC_VECT(SPU2_1, 0x1820),
- INTC_VECT(FSI, 0x1840),
- INTC_VECT(FMSI, 0x1860),
-+ INTC_VECT(HDMI_SSS, 0x18A0),
-+ INTC_VECT(HDMI_KEY, 0x18C0),
- INTC_VECT(IPMMU, 0x1920),
- INTC_VECT(AP_ARM_CTIIRQ, 0x1980),
- INTC_VECT(AP_ARM_PMURQ, 0x19A0),
-@@ -304,11 +309,11 @@ static struct intc_mask_reg intca_mask_registers[] __initdata = {
- USBH_EHCI, USBH_PME, USBH_BIND, 0 } },
- /* IMR3A3 / IMCR3A3 */
- { /* IMR4A3 / IMCR4A3 */ 0xe6950090, 0xe69500d0, 8,
-- { 0, 0, 0, 0,
-+ { HDMI, 0, 0, 0,
- RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF, 0 } },
- { /* IMR5A3 / IMCR5A3 */ 0xe6950094, 0xe69500d4, 8,
- { SPU2_0, SPU2_1, FSI, FMSI,
-- 0, 0, 0, 0 } },
-+ 0, HDMI_SSS, HDMI_KEY, 0 } },
- { /* IMR6A3 / IMCR6A3 */ 0xe6950098, 0xe69500d8, 8,
- { 0, IPMMU, 0, 0,
- AP_ARM_CTIIRQ, AP_ARM_PMURQ, 0, 0 } },
-@@ -353,10 +358,10 @@ static struct intc_prio_reg intca_prio_registers[] __initdata = {
- { 0xe6950014, 0, 16, 4, /* IPRFA3 */ { USBH2, 0, 0, 0 } },
- /* IPRGA3 */
- /* IPRHA3 */
-- /* IPRIA3 */
-+ { 0xe6950020, 0, 16, 4, /* IPRIA3 */ { HDMI, 0, 0, 0 } },
- { 0xe6950024, 0, 16, 4, /* IPRJA3 */ { RSPI, 0, 0, 0 } },
- { 0xe6950028, 0, 16, 4, /* IPRKA3 */ { SPU2, 0, FSI, FMSI } },
-- /* IPRLA3 */
-+ { 0xe695002c, 0, 16, 4, /* IPRLA3 */ { 0, HDMI_SSS, HDMI_KEY, 0 } },
- { 0xe6950030, 0, 16, 4, /* IPRMA3 */ { IPMMU, 0, 0, 0 } },
- { 0xe6950034, 0, 16, 4, /* IPRNA3 */ { AP_ARM2, 0, 0, 0 } },
- { 0xe6950038, 0, 16, 4, /* IPROA3 */ { MFIS2, CPORTR2S,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 86a946d62d5993f9f8bff6db6445a0a12893665d Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 12 Jun 2012 02:35:36 -0700
-Subject: ARM: shmobile: r8a7740: add HDMI clock support
-
-It is required from sh_mobile_hdmi driver.
-This patch is based on v1.0 manual
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit c6750acb3b54c77c011045467770d5143be749ee)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/clock-r8a7740.c | 84 ++++++++++++++++++++++++++++++++++
- 1 file changed, 84 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
-index 26eea5f..b095343 100644
---- a/arch/arm/mach-shmobile/clock-r8a7740.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
-@@ -54,6 +54,7 @@
- #define MSTPSR2 0xe6150040
- #define MSTPSR3 0xe6150048
- #define MSTPSR4 0xe615004c
-+#define HDMICKCR 0xe6150094
- #define SMSTPCR0 0xe6150130
- #define SMSTPCR1 0xe6150134
- #define SMSTPCR2 0xe6150138
-@@ -313,6 +314,79 @@ static struct clk_div4_table div4_table = {
- .kick = div4_kick,
- };
-
-+/* DIV6 reparent */
-+enum {
-+ DIV6_HDMI,
-+ DIV6_REPARENT_NR,
-+};
-+
-+static struct clk *hdmi_parent[] = {
-+ [0] = &pllc1_div2_clk,
-+ [1] = &system_clk,
-+ [2] = &dv_clk
-+};
-+
-+static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
-+ [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0,
-+ hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2),
-+};
-+
-+/* HDMI1/2 clock */
-+static unsigned long hdmi12_recalc(struct clk *clk)
-+{
-+ u32 val = __raw_readl(HDMICKCR);
-+ int shift = (int)clk->priv;
-+
-+ val >>= shift;
-+ val &= 0x3;
-+
-+ return clk->parent->rate / (1 << val);
-+};
-+
-+static int hdmi12_set_rate(struct clk *clk, unsigned long rate)
-+{
-+ u32 val, mask;
-+ int i, shift;
-+
-+ for (i = 0; i < 3; i++)
-+ if (rate == clk->parent->rate / (1 << i))
-+ goto find;
-+ return -ENODEV;
-+
-+find:
-+ shift = (int)clk->priv;
-+
-+ val = __raw_readl(HDMICKCR);
-+ mask = ~(0x3 << shift);
-+ val = (val & mask) | i << shift;
-+ __raw_writel(val, HDMICKCR);
-+
-+ return 0;
-+};
-+
-+static struct sh_clk_ops hdmi12_clk_ops = {
-+ .recalc = hdmi12_recalc,
-+ .set_rate = hdmi12_set_rate,
-+};
-+
-+static struct clk hdmi1_clk = {
-+ .ops = &hdmi12_clk_ops,
-+ .priv = (void *)9,
-+ .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */
-+};
-+
-+static struct clk hdmi2_clk = {
-+ .ops = &hdmi12_clk_ops,
-+ .priv = (void *)11,
-+ .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */
-+};
-+
-+static struct clk *late_main_clks[] = {
-+ &hdmi1_clk,
-+ &hdmi2_clk,
-+};
-+
-+/* MSTP */
- enum {
- DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP,
- DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
-@@ -408,6 +482,8 @@ static struct clk_lookup lookups[] = {
- CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
- CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
- CLKDEV_CON_ID("usb24s", &usb24s_clk),
-+ CLKDEV_CON_ID("hdmi1", &hdmi1_clk),
-+ CLKDEV_CON_ID("hdmi2", &hdmi2_clk),
-
- /* DIV4 clocks */
- CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
-@@ -459,6 +535,7 @@ static struct clk_lookup lookups[] = {
- CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]),
- CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]),
- CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk),
-+ CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]),
- };
-
- void __init r8a7740_clock_init(u8 md_ck)
-@@ -495,8 +572,15 @@ void __init r8a7740_clock_init(u8 md_ck)
- ret = sh_clk_div6_register(div6_clks, DIV6_NR);
-
- if (!ret)
-+ ret = sh_clk_div6_reparent_register(div6_reparent_clks,
-+ DIV6_REPARENT_NR);
-+
-+ if (!ret)
- ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
-
-+ for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
-+ ret = clk_register(late_main_clks[k]);
-+
- clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
- if (!ret)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 77cd6be2b59e2839e6c2b8cab77a480e092aedec Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 12 Jun 2012 02:35:58 -0700
-Subject: ARM: shmobile: r8a7740: add HDMI GPIO support
-
-In order to enable HDMI GPIO selection from platform board,
-this patch adds its interface to GPIO framework.
-
-This patch is based on v1.0 manual
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit e2dcd461a7ba0c3deb44336136ea784c8b972292)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/include/mach/r8a7740.h | 4 ++++
- arch/arm/mach-shmobile/pfc-r8a7740.c | 9 +++++++++
- 2 files changed, 13 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-index 9d447ab..2764846 100644
---- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
-+++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-@@ -565,6 +565,10 @@ enum {
- GPIO_FN_RESETP_PULLUP,
- GPIO_FN_RESETP_PLAIN,
-
-+ /* HDMI */
-+ GPIO_FN_HDMI_HPD,
-+ GPIO_FN_HDMI_CEC,
-+
- /* SDENC */
- GPIO_FN_SDENC_CPG,
- GPIO_FN_SDENC_DV_CLKI,
-diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c
-index 670fe18..0dda816 100644
---- a/arch/arm/mach-shmobile/pfc-r8a7740.c
-+++ b/arch/arm/mach-shmobile/pfc-r8a7740.c
-@@ -560,6 +560,9 @@ enum {
- /* SDENC */
- SDENC_CPG_MARK, SDENC_DV_CLKI_MARK,
-
-+ /* HDMI */
-+ HDMI_HPD_MARK, HDMI_CEC_MARK,
-+
- /* DEBUG */
- EDEBGREQ_PULLUP_MARK, /* for JTAG */
- EDEBGREQ_PULLDOWN_MARK,
-@@ -1620,9 +1623,11 @@ static pinmux_enum_t pinmux_data[] = {
-
- /* Port210 */
- PINMUX_DATA(IRQ9_PORT210_MARK, PORT210_FN0, MSEL1CR_9_1),
-+ PINMUX_DATA(HDMI_HPD_MARK, PORT210_FN1),
-
- /* Port211 */
- PINMUX_DATA(IRQ16_PORT211_MARK, PORT211_FN0, MSEL1CR_16_1),
-+ PINMUX_DATA(HDMI_CEC_MARK, PORT211_FN1),
-
- /* LCDC select */
- PINMUX_DATA(LCDC0_SELECT_MARK, MSEL3CR_6_0),
-@@ -2097,6 +2102,10 @@ static struct pinmux_gpio pinmux_gpios[] = {
- GPIO_FN(SDENC_CPG),
- GPIO_FN(SDENC_DV_CLKI),
-
-+ /* HDMI */
-+ GPIO_FN(HDMI_HPD),
-+ GPIO_FN(HDMI_CEC),
-+
- /* SYSC */
- GPIO_FN(RESETP_PULLUP),
- GPIO_FN(RESETP_PLAIN),
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From acd1ae033a03a0c6356e68d9d17427afb0f53eb0 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 12 Jun 2012 02:36:21 -0700
-Subject: ARM: shmobile: r8a7740: add MERAM work-around
-
-r8a7740 chip has lasting errata on MERAM buffer, and this patch adds
-its work-around on setup-r8a7740.c
-It solved CEU/VIO6C/2D-DMAC/VCP1/VPU5F/JPU/DISP memroy access error.
-
-But MERAM driver can't control this issue,
-since this work-around requires access to non-MERAM register address.
-So, This it will be called as board specific code at this point.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit d49679e5928709bce8937dce396458b139c4b34d)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -587,6 +587,7 @@ static void __init eva_init(void)
- eva_clock_init();
-
- r8a7740_pinmux_init();
-+ r8a7740_meram_workaround();
-
- /* SCIFA1 */
- gpio_request(GPIO_FN_SCIFA1_RXD, NULL);
+++ /dev/null
-From 5484e5aba2cd92f69af04090ab0f4e018175df69 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 12 Jun 2012 02:36:39 -0700
-Subject: ARM: shmobile: r8a7740: add CEU clock support
-
-It is required from sh_mobile_ceu_camera driver.
-This patch is based on v1.0 manual
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit ad9f1721c15b84f1a2e45a8a03f1ff7c86c2829b)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/clock-r8a7740.c | 23 ++++++++++++++++++++++-
- 1 file changed, 22 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
-index b095343..ce0930a 100644
---- a/arch/arm/mach-shmobile/clock-r8a7740.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
-@@ -43,6 +43,8 @@
- /* CPG registers */
- #define FRQCRA 0xe6150000
- #define FRQCRB 0xe6150004
-+#define VCLKCR1 0xE6150008
-+#define VCLKCR2 0xE615000c
- #define FRQCRC 0xe61500e0
- #define PLLC01CR 0xe6150028
-
-@@ -317,6 +319,7 @@ static struct clk_div4_table div4_table = {
- /* DIV6 reparent */
- enum {
- DIV6_HDMI,
-+ DIV6_VCLK1, DIV6_VCLK2,
- DIV6_REPARENT_NR,
- };
-
-@@ -326,9 +329,21 @@ static struct clk *hdmi_parent[] = {
- [2] = &dv_clk
- };
-
-+static struct clk *vclk_parents[8] = {
-+ [0] = &pllc1_div2_clk,
-+ [2] = &dv_clk,
-+ [3] = &usb24s_clk,
-+ [4] = &extal1_div2_clk,
-+ [5] = &extalr_clk,
-+};
-+
- static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
- [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0,
- hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2),
-+ [DIV6_VCLK1] = SH_CLK_DIV6_EXT(VCLKCR1, 0,
-+ vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3),
-+ [DIV6_VCLK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0,
-+ vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3),
- };
-
- /* HDMI1/2 clock */
-@@ -417,7 +432,7 @@ static struct clk div6_clks[DIV6_NR] = {
- };
-
- enum {
-- MSTP125,
-+ MSTP128, MSTP127, MSTP125,
- MSTP116, MSTP111, MSTP100, MSTP117,
-
- MSTP230,
-@@ -434,6 +449,8 @@ enum {
- };
-
- static struct clk mstp_clks[MSTP_NR] = {
-+ [MSTP128] = SH_CLK_MSTP32(&div4_clks[DIV4_S], SMSTPCR1, 28, 0), /* CEU21 */
-+ [MSTP127] = SH_CLK_MSTP32(&div4_clks[DIV4_S], SMSTPCR1, 27, 0), /* CEU20 */
- [MSTP125] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */
- [MSTP117] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */
- [MSTP116] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */
-@@ -484,6 +501,8 @@ static struct clk_lookup lookups[] = {
- CLKDEV_CON_ID("usb24s", &usb24s_clk),
- CLKDEV_CON_ID("hdmi1", &hdmi1_clk),
- CLKDEV_CON_ID("hdmi2", &hdmi2_clk),
-+ CLKDEV_CON_ID("video1", &div6_reparent_clks[DIV6_VCLK1]),
-+ CLKDEV_CON_ID("video2", &div6_reparent_clks[DIV6_VCLK2]),
-
- /* DIV4 clocks */
- CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
-@@ -506,6 +525,8 @@ static struct clk_lookup lookups[] = {
- CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]),
- CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]),
- CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]),
-+ CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]),
-+ CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP128]),
-
- CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]),
- CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]),
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 3380d7910c8f2625a74337bd1a3f1d81bc146c73 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 12 Jun 2012 02:36:58 -0700
-Subject: ARM: shmobile: r8a7740: add FSI parent clock support
-
-r8a7740 FSI can select its parent clock,
-and its selection is dependent on platform board.
-
-In order to enable FSI parent selection from platform board,
-this patch adds its interface to clock framework.
-
-This patch is based on v1.0 manual
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 69efac9a8bc6d479bc4c339ae4ac4d353460def6)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/clock-r8a7740.c | 31 +++++++++++++++++++++++++++++++
- 1 file changed, 31 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
-index ce0930a..7b9e4ab 100644
---- a/arch/arm/mach-shmobile/clock-r8a7740.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
-@@ -46,6 +46,7 @@
- #define VCLKCR1 0xE6150008
- #define VCLKCR2 0xE615000c
- #define FRQCRC 0xe61500e0
-+#define FSIACKCR 0xe6150018
- #define PLLC01CR 0xe6150028
-
- #define SUBCKCR 0xe6150080
-@@ -56,6 +57,7 @@
- #define MSTPSR2 0xe6150040
- #define MSTPSR3 0xe6150048
- #define MSTPSR4 0xe615004c
-+#define FSIBCKCR 0xe6150090
- #define HDMICKCR 0xe6150094
- #define SMSTPCR0 0xe6150130
- #define SMSTPCR1 0xe6150134
-@@ -274,6 +276,13 @@ static struct clk usb24_clk = {
- .parent = &usb24s_clk,
- };
-
-+/* External FSIACK/FSIBCK clock */
-+static struct clk fsiack_clk = {
-+};
-+
-+static struct clk fsibck_clk = {
-+};
-+
- struct clk *main_clks[] = {
- &extalr_clk,
- &extal1_clk,
-@@ -291,6 +300,8 @@ struct clk *main_clks[] = {
- &pllc1_div2_clk,
- &usb24s_clk,
- &usb24_clk,
-+ &fsiack_clk,
-+ &fsibck_clk,
- };
-
- static void div4_kick(struct clk *clk)
-@@ -320,6 +331,7 @@ static struct clk_div4_table div4_table = {
- enum {
- DIV6_HDMI,
- DIV6_VCLK1, DIV6_VCLK2,
-+ DIV6_FSIA, DIV6_FSIB,
- DIV6_REPARENT_NR,
- };
-
-@@ -337,6 +349,16 @@ static struct clk *vclk_parents[8] = {
- [5] = &extalr_clk,
- };
-
-+static struct clk *fsia_parents[] = {
-+ [0] = &pllc1_div2_clk,
-+ [1] = &fsiack_clk, /* external clock */
-+};
-+
-+static struct clk *fsib_parents[] = {
-+ [0] = &pllc1_div2_clk,
-+ [1] = &fsibck_clk, /* external clock */
-+};
-+
- static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
- [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0,
- hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2),
-@@ -344,6 +366,10 @@ static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
- vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3),
- [DIV6_VCLK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0,
- vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3),
-+ [DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0,
-+ fsia_parents, ARRAY_SIZE(fsia_parents), 6, 2),
-+ [DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0,
-+ fsib_parents, ARRAY_SIZE(fsib_parents), 6, 2),
- };
-
- /* HDMI1/2 clock */
-@@ -503,6 +529,8 @@ static struct clk_lookup lookups[] = {
- CLKDEV_CON_ID("hdmi2", &hdmi2_clk),
- CLKDEV_CON_ID("video1", &div6_reparent_clks[DIV6_VCLK1]),
- CLKDEV_CON_ID("video2", &div6_reparent_clks[DIV6_VCLK2]),
-+ CLKDEV_CON_ID("fsiack", &fsiack_clk),
-+ CLKDEV_CON_ID("fsibck", &fsibck_clk),
-
- /* DIV4 clocks */
- CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
-@@ -557,6 +585,9 @@ static struct clk_lookup lookups[] = {
- CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]),
- CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk),
- CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]),
-+
-+ CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]),
-+ CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]),
- };
-
- void __init r8a7740_clock_init(u8 md_ck)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ead2de820556aa2682e1505f691a5207365d4e69 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 12 Jun 2012 02:37:16 -0700
-Subject: ARM: shmobile: r8a7740: add FSI-B (for HDMI) GPIO support
-
-In order to enable FSI-B selection from platform board,
-this patch adds its interface to GPIO framework.
-
-This patch is based on v1.0 manual
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 147d1ffdc21d067f0084f0911dbf1eee57e3d76b)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/include/mach/r8a7740.h | 5 ++++-
- arch/arm/mach-shmobile/pfc-r8a7740.c | 11 +++++++++--
- 2 files changed, 13 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-index 2764846..6468fcc 100644
---- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
-+++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-@@ -139,7 +139,7 @@ enum {
- GPIO_FN_DBGMD10, GPIO_FN_DBGMD11, GPIO_FN_DBGMD20,
- GPIO_FN_DBGMD21,
-
-- /* FSI */
-+ /* FSI-A */
- GPIO_FN_FSIAISLD_PORT0, /* FSIAISLD Port 0/5 */
- GPIO_FN_FSIAISLD_PORT5,
- GPIO_FN_FSIASPDIF_PORT9, /* FSIASPDIF Port 9/18 */
-@@ -150,6 +150,9 @@ enum {
- GPIO_FN_FSIACK, GPIO_FN_FSIAILR,
- GPIO_FN_FSIAIBT,
-
-+ /* FSI-B */
-+ GPIO_FN_FSIBCK,
-+
- /* FMSI */
- GPIO_FN_FMSISLD_PORT1, /* FMSISLD Port 1/6 */
- GPIO_FN_FMSISLD_PORT6,
-diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c
-index 0dda816..03def0f 100644
---- a/arch/arm/mach-shmobile/pfc-r8a7740.c
-+++ b/arch/arm/mach-shmobile/pfc-r8a7740.c
-@@ -169,7 +169,7 @@ enum {
- DBGMD10_MARK, DBGMD11_MARK, DBGMD20_MARK,
- DBGMD21_MARK,
-
-- /* FSI */
-+ /* FSI-A */
- FSIAISLD_PORT0_MARK, /* FSIAISLD Port 0/5 */
- FSIAISLD_PORT5_MARK,
- FSIASPDIF_PORT9_MARK, /* FSIASPDIF Port 9/18 */
-@@ -178,6 +178,9 @@ enum {
- FSIAOBT_MARK, FSIAOSLD_MARK, FSIAOMC_MARK,
- FSIACK_MARK, FSIAILR_MARK, FSIAIBT_MARK,
-
-+ /* FSI-B */
-+ FSIBCK_MARK,
-+
- /* FMSI */
- FMSISLD_PORT1_MARK, /* FMSISLD Port 1/6 */
- FMSISLD_PORT6_MARK,
-@@ -774,6 +777,7 @@ static pinmux_enum_t pinmux_data[] = {
-
- /* Port11 */
- PINMUX_DATA(FSIACK_MARK, PORT11_FN1),
-+ PINMUX_DATA(FSIBCK_MARK, PORT11_FN2),
- PINMUX_DATA(IRQ2_PORT11_MARK, PORT11_FN0, MSEL1CR_2_0),
-
- /* Port12 */
-@@ -1696,7 +1700,7 @@ static struct pinmux_gpio pinmux_gpios[] = {
- GPIO_FN(DBGMD10), GPIO_FN(DBGMD11), GPIO_FN(DBGMD20),
- GPIO_FN(DBGMD21),
-
-- /* FSI */
-+ /* FSI-A */
- GPIO_FN(FSIAISLD_PORT0), /* FSIAISLD Port 0/5 */
- GPIO_FN(FSIAISLD_PORT5),
- GPIO_FN(FSIASPDIF_PORT9), /* FSIASPDIF Port 9/18 */
-@@ -1705,6 +1709,9 @@ static struct pinmux_gpio pinmux_gpios[] = {
- GPIO_FN(FSIAOBT), GPIO_FN(FSIAOSLD), GPIO_FN(FSIAOMC),
- GPIO_FN(FSIACK), GPIO_FN(FSIAILR), GPIO_FN(FSIAIBT),
-
-+ /* FSI-B */
-+ GPIO_FN(FSIBCK),
-+
- /* FMSI */
- GPIO_FN(FMSISLD_PORT1), /* FMSISLD Port 1/6 */
- GPIO_FN(FMSISLD_PORT6),
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e92cdf42dfe94be35bc251b5eaa9a0db2c8679e9 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 12 Jun 2012 02:39:11 -0700
-Subject: ARM: shmobile: armadillo800eva: enable HDMI
-
-This patch enable HDMI support on CON3.
-And removed unnecessary CONFIG_SYSFS_DEPRECATED_xxx config.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 910c14d0b8f121df420a878cbd973ffa7d549393)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/configs/armadillo800eva_defconfig | 10 +--
- arch/arm/mach-shmobile/board-armadillo800eva.c | 100 +++++++++++++++++++++++++
- 2 files changed, 101 insertions(+), 9 deletions(-)
-
-diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
-index ddc9fe6..f6ebdde 100644
---- a/arch/arm/configs/armadillo800eva_defconfig
-+++ b/arch/arm/configs/armadillo800eva_defconfig
-@@ -5,10 +5,7 @@ CONFIG_IKCONFIG_PROC=y
- CONFIG_LOG_BUF_SHIFT=16
- # CONFIG_UTS_NS is not set
- # CONFIG_IPC_NS is not set
--# CONFIG_USER_NS is not set
- # CONFIG_PID_NS is not set
--CONFIG_SYSFS_DEPRECATED=y
--CONFIG_SYSFS_DEPRECATED_V2=y
- CONFIG_CC_OPTIMIZE_FOR_SIZE=y
- CONFIG_SLAB=y
- CONFIG_MODULES=y
-@@ -90,25 +87,21 @@ CONFIG_I2C=y
- CONFIG_I2C_SH_MOBILE=y
- # CONFIG_HWMON is not set
- CONFIG_FB=y
--CONFIG_FB_MODE_HELPERS=y
- CONFIG_FB_SH_MOBILE_LCDC=y
-+CONFIG_FB_SH_MOBILE_HDMI=y
- CONFIG_LCD_CLASS_DEVICE=y
- CONFIG_FRAMEBUFFER_CONSOLE=y
- CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
- CONFIG_LOGO=y
- # CONFIG_LOGO_LINUX_MONO is not set
- # CONFIG_LOGO_LINUX_VGA16 is not set
--CONFIG_SOUND=y
--CONFIG_SND=y
- # CONFIG_SND_SUPPORT_OLD_API is not set
- # CONFIG_SND_VERBOSE_PROCFS is not set
- # CONFIG_SND_DRIVERS is not set
- # CONFIG_SND_ARM is not set
--CONFIG_SND_SOC=y
- CONFIG_SND_SOC_SH4_FSI=y
- # CONFIG_HID_SUPPORT is not set
- CONFIG_USB=y
--# CONFIG_USB_DEVICE_CLASS is not set
- CONFIG_USB_RENESAS_USBHS=y
- CONFIG_USB_GADGET=y
- CONFIG_USB_RENESAS_USBHS_UDC=y
-@@ -124,7 +117,6 @@ CONFIG_VFAT_FS=y
- CONFIG_TMPFS=y
- # CONFIG_MISC_FILESYSTEMS is not set
- CONFIG_NFS_FS=y
--CONFIG_NFS_V3=y
- CONFIG_NFS_V3_ACL=y
- CONFIG_NFS_V4=y
- CONFIG_NFS_V4_1=y
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index 6e6839d..4e6893f 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -45,6 +45,7 @@
- #include <asm/hardware/cache-l2x0.h>
- #include <mach/r8a7740.h>
- #include <video/sh_mobile_lcdc.h>
-+#include <video/sh_mobile_hdmi.h>
-
- /*
- * CON1 Camera Module
-@@ -384,6 +385,103 @@ static struct platform_device lcdc0_device = {
- },
- };
-
-+/*
-+ * LCDC1/HDMI
-+ */
-+static struct sh_mobile_hdmi_info hdmi_info = {
-+ .flags = HDMI_OUTPUT_PUSH_PULL |
-+ HDMI_OUTPUT_POLARITY_HI |
-+ HDMI_32BIT_REG |
-+ HDMI_HAS_HTOP1 |
-+ HDMI_SND_SRC_SPDIF,
-+};
-+
-+static struct resource hdmi_resources[] = {
-+ [0] = {
-+ .name = "HDMI",
-+ .start = 0xe6be0000,
-+ .end = 0xe6be03ff,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = evt2irq(0x1700),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [2] = {
-+ .name = "HDMI emma3pf",
-+ .start = 0xe6be4000,
-+ .end = 0xe6be43ff,
-+ .flags = IORESOURCE_MEM,
-+ },
-+};
-+
-+static struct platform_device hdmi_device = {
-+ .name = "sh-mobile-hdmi",
-+ .num_resources = ARRAY_SIZE(hdmi_resources),
-+ .resource = hdmi_resources,
-+ .id = -1,
-+ .dev = {
-+ .platform_data = &hdmi_info,
-+ },
-+};
-+
-+static const struct fb_videomode lcdc1_mode = {
-+ .name = "HDMI 720p",
-+ .xres = 1280,
-+ .yres = 720,
-+ .pixclock = 13468,
-+ .left_margin = 220,
-+ .right_margin = 110,
-+ .hsync_len = 40,
-+ .upper_margin = 20,
-+ .lower_margin = 5,
-+ .vsync_len = 5,
-+ .refresh = 60,
-+ .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
-+};
-+
-+static struct sh_mobile_lcdc_info hdmi_lcdc_info = {
-+ .clock_source = LCDC_CLK_PERIPHERAL, /* HDMI clock */
-+ .ch[0] = {
-+ .chan = LCDC_CHAN_MAINLCD,
-+ .fourcc = V4L2_PIX_FMT_RGB565,
-+ .interface_type = RGB24,
-+ .clock_divider = 1,
-+ .flags = LCDC_FLAGS_DWPOL,
-+ .lcd_modes = &lcdc1_mode,
-+ .num_modes = 1,
-+ .tx_dev = &hdmi_device,
-+ .panel_cfg = {
-+ .width = 1280,
-+ .height = 720,
-+ },
-+ },
-+};
-+
-+static struct resource hdmi_lcdc_resources[] = {
-+ [0] = {
-+ .name = "LCDC1",
-+ .start = 0xfe944000,
-+ .end = 0xfe948000 - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = intcs_evt2irq(0x1780),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device hdmi_lcdc_device = {
-+ .name = "sh_mobile_lcdc_fb",
-+ .num_resources = ARRAY_SIZE(hdmi_lcdc_resources),
-+ .resource = hdmi_lcdc_resources,
-+ .id = 1,
-+ .dev = {
-+ .platform_data = &hdmi_lcdc_info,
-+ .coherent_dma_mask = ~0,
-+ },
-+};
-+
- /* GPIO KEY */
- #define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
-
-@@ -549,6 +647,8 @@ static struct platform_device *eva_devices[] __initdata = {
- &sh_eth_device,
- &sdhi0_device,
- &sh_mmcif_device,
-+ &hdmi_device,
-+ &hdmi_lcdc_device,
- };
-
- static void __init eva_clock_init(void)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e942f8cdf5f982742f6bc8cb49fd546bb828ffce Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Wed, 20 Jun 2012 12:53:25 +0200
-Subject: ARM: mach-shmobile: armadillo800eva: Use late init machine hook
-
-Since commit 21cc1b7ede3cf456cf1d51f8a906093261f7c111 ("ARM: shmobile:
-use machine specific hook for late init") suspend and CPU idle are not
-initialized automatically anymore. Set shmobile_init_late() as the
-machine late init hook to initialize them.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 37f971b68009b8fadd322130787d693137302925)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index 4e6893f..bbf5ccff 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -880,6 +880,7 @@ DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva")
- .init_irq = r8a7740_init_irq,
- .handle_irq = shmobile_handle_irq_intc,
- .init_machine = eva_init,
-+ .init_late = shmobile_init_late,
- .timer = &shmobile_timer,
- .dt_compat = eva_boards_compat_dt,
- MACHINE_END
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From c7934751659fc8d58c97d51edc6fdb5af8307330 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 12 Jun 2012 02:40:07 -0700
-Subject: ARM: shmobile: armadillo800eva: enable camera
-
-This patch enable camera support on CON1
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 3760e79450f48e31fde2b2dd49c5ab6a685c3ea8)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/configs/armadillo800eva_defconfig | 10 +++
- arch/arm/mach-shmobile/board-armadillo800eva.c | 111 ++++++++++++++++++++++++-
- 2 files changed, 120 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
-index f6ebdde..df1ce54 100644
---- a/arch/arm/configs/armadillo800eva_defconfig
-+++ b/arch/arm/configs/armadillo800eva_defconfig
-@@ -86,6 +86,16 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
- CONFIG_I2C=y
- CONFIG_I2C_SH_MOBILE=y
- # CONFIG_HWMON is not set
-+CONFIG_MEDIA_SUPPORT=y
-+CONFIG_VIDEO_DEV=y
-+# CONFIG_RC_CORE is not set
-+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
-+# CONFIG_V4L_USB_DRIVERS is not set
-+CONFIG_V4L_PLATFORM_DRIVERS=y
-+CONFIG_SOC_CAMERA=y
-+CONFIG_SOC_CAMERA_MT9T112=y
-+CONFIG_VIDEO_SH_MOBILE_CEU=y
-+# CONFIG_RADIO_ADAPTERS is not set
- CONFIG_FB=y
- CONFIG_FB_SH_MOBILE_LCDC=y
- CONFIG_FB_SH_MOBILE_HDMI=y
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index bbf5ccff..a513ebe 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -37,13 +37,16 @@
- #include <linux/mmc/sh_mobile_sdhi.h>
- #include <mach/common.h>
- #include <mach/irqs.h>
-+#include <mach/r8a7740.h>
-+#include <media/mt9t112.h>
-+#include <media/sh_mobile_ceu.h>
-+#include <media/soc_camera.h>
- #include <asm/page.h>
- #include <asm/mach-types.h>
- #include <asm/mach/arch.h>
- #include <asm/mach/map.h>
- #include <asm/mach/time.h>
- #include <asm/hardware/cache-l2x0.h>
--#include <mach/r8a7740.h>
- #include <video/sh_mobile_lcdc.h>
- #include <video/sh_mobile_hdmi.h>
-
-@@ -630,6 +633,87 @@ static struct platform_device sh_mmcif_device = {
- .resource = sh_mmcif_resources,
- };
-
-+/* Camera */
-+static int mt9t111_power(struct device *dev, int mode)
-+{
-+ struct clk *mclk = clk_get(NULL, "video1");
-+
-+ if (IS_ERR(mclk)) {
-+ dev_err(dev, "can't get video1 clock\n");
-+ return -EINVAL;
-+ }
-+
-+ if (mode) {
-+ /* video1 (= CON1 camera) expect 24MHz */
-+ clk_set_rate(mclk, clk_round_rate(mclk, 24000000));
-+ clk_enable(mclk);
-+ gpio_direction_output(GPIO_PORT158, 1);
-+ } else {
-+ gpio_direction_output(GPIO_PORT158, 0);
-+ clk_disable(mclk);
-+ }
-+
-+ clk_put(mclk);
-+
-+ return 0;
-+}
-+
-+static struct i2c_board_info i2c_camera_mt9t111 = {
-+ I2C_BOARD_INFO("mt9t112", 0x3d),
-+};
-+
-+static struct mt9t112_camera_info mt9t111_info = {
-+ .divider = { 16, 0, 0, 7, 0, 10, 14, 7, 7 },
-+};
-+
-+static struct soc_camera_link mt9t111_link = {
-+ .i2c_adapter_id = 0,
-+ .bus_id = 0,
-+ .board_info = &i2c_camera_mt9t111,
-+ .power = mt9t111_power,
-+ .priv = &mt9t111_info,
-+};
-+
-+static struct platform_device camera_device = {
-+ .name = "soc-camera-pdrv",
-+ .id = 0,
-+ .dev = {
-+ .platform_data = &mt9t111_link,
-+ },
-+};
-+
-+/* CEU0 */
-+static struct sh_mobile_ceu_info sh_mobile_ceu0_info = {
-+ .flags = SH_CEU_FLAG_LOWER_8BIT,
-+};
-+
-+static struct resource ceu0_resources[] = {
-+ [0] = {
-+ .name = "CEU",
-+ .start = 0xfe910000,
-+ .end = 0xfe91009f,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = intcs_evt2irq(0x0500),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [2] = {
-+ /* place holder for contiguous memory */
-+ },
-+};
-+
-+static struct platform_device ceu0_device = {
-+ .name = "sh_mobile_ceu",
-+ .id = 0,
-+ .num_resources = ARRAY_SIZE(ceu0_resources),
-+ .resource = ceu0_resources,
-+ .dev = {
-+ .platform_data = &sh_mobile_ceu0_info,
-+ .coherent_dma_mask = 0xffffffff,
-+ },
-+};
-+
- /* I2C */
- static struct i2c_board_info i2c0_devices[] = {
- {
-@@ -649,6 +733,8 @@ static struct platform_device *eva_devices[] __initdata = {
- &sh_mmcif_device,
- &hdmi_device,
- &hdmi_lcdc_device,
-+ &camera_device,
-+ &ceu0_device,
- };
-
- static void __init eva_clock_init(void)
-@@ -807,6 +893,29 @@ static void __init eva_init(void)
- gpio_request(GPIO_FN_MMC1_D6_PORT143, NULL);
- gpio_request(GPIO_FN_MMC1_D7_PORT142, NULL);
-
-+ /* CEU0 */
-+ gpio_request(GPIO_FN_VIO0_D7, NULL);
-+ gpio_request(GPIO_FN_VIO0_D6, NULL);
-+ gpio_request(GPIO_FN_VIO0_D5, NULL);
-+ gpio_request(GPIO_FN_VIO0_D4, NULL);
-+ gpio_request(GPIO_FN_VIO0_D3, NULL);
-+ gpio_request(GPIO_FN_VIO0_D2, NULL);
-+ gpio_request(GPIO_FN_VIO0_D1, NULL);
-+ gpio_request(GPIO_FN_VIO0_D0, NULL);
-+ gpio_request(GPIO_FN_VIO0_CLK, NULL);
-+ gpio_request(GPIO_FN_VIO0_HD, NULL);
-+ gpio_request(GPIO_FN_VIO0_VD, NULL);
-+ gpio_request(GPIO_FN_VIO0_FIELD, NULL);
-+ gpio_request(GPIO_FN_VIO_CKO, NULL);
-+
-+ /* CON1/CON15 Camera */
-+ gpio_request(GPIO_PORT173, NULL); /* STANDBY */
-+ gpio_request(GPIO_PORT172, NULL); /* RST */
-+ gpio_request(GPIO_PORT158, NULL); /* CAM_PON */
-+ gpio_direction_output(GPIO_PORT173, 0);
-+ gpio_direction_output(GPIO_PORT172, 1);
-+ gpio_direction_output(GPIO_PORT158, 0); /* see mt9t111_power() */
-+
- /*
- * CAUTION
- *
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 0e0018e5c4b1d2d6c6fe9d67a8c5916752884589 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 25 Jun 2012 03:36:49 -0700
-Subject: ARM: shmobile: r8a7740: add DMAEngine support for FSI
-
-Current shdmac can support FSI DMAC on r8a7740.
-This support reduce CPU duty when sound was playback.
-
-This patch is based on v1.0 manual
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 643c3307bbbe7e80c6693376137971fbdcbe1c82)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/clock-r8a7740.c | 8 +-
- arch/arm/mach-shmobile/include/mach/r8a7740.h | 8 ++
- arch/arm/mach-shmobile/setup-r8a7740.c | 198 ++++++++++++++++++++++++++
- 3 files changed, 213 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
-index 7b9e4ab..39b1311 100644
---- a/arch/arm/mach-shmobile/clock-r8a7740.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
-@@ -463,6 +463,7 @@ enum {
-
- MSTP230,
- MSTP222,
-+ MSTP218, MSTP217, MSTP216,
- MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
-
- MSTP329, MSTP328, MSTP323, MSTP320,
-@@ -485,6 +486,9 @@ static struct clk mstp_clks[MSTP_NR] = {
-
- [MSTP230] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 30, 0), /* SCIFA6 */
- [MSTP222] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 22, 0), /* SCIFA7 */
-+ [MSTP218] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* DMAC1 */
-+ [MSTP217] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* DMAC2 */
-+ [MSTP216] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 16, 0), /* DMAC3 */
- [MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */
- [MSTP206] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */
- [MSTP204] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */
-@@ -563,7 +567,9 @@ static struct clk_lookup lookups[] = {
- CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
- CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]),
- CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]),
--
-+ CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]),
-+ CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]),
-+ CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]),
- CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP222]),
- CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]),
-
-diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-index 6468fcc..f71507b 100644
---- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
-+++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-@@ -588,4 +588,12 @@ enum {
- GPIO_FN_TRACEAUD_FROM_MEMC,
- };
-
-+/* DMA slave IDs */
-+enum {
-+ SHDMA_SLAVE_INVALID,
-+ SHDMA_SLAVE_FSIA_RX,
-+ SHDMA_SLAVE_FSIA_TX,
-+ SHDMA_SLAVE_FSIB_TX,
-+};
-+
- #endif /* __ASM_R8A7740_H__ */
-diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
-index 366311b..516a7ec 100644
---- a/arch/arm/mach-shmobile/setup-r8a7740.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
-@@ -24,7 +24,9 @@
- #include <linux/io.h>
- #include <linux/platform_device.h>
- #include <linux/serial_sci.h>
-+#include <linux/sh_dma.h>
- #include <linux/sh_timer.h>
-+#include <linux/dma-mapping.h>
- #include <mach/r8a7740.h>
- #include <mach/common.h>
- #include <mach/irqs.h>
-@@ -276,6 +278,199 @@ static struct platform_device *r8a7740_early_devices[] __initdata = {
- &cmt10_device,
- };
-
-+/* DMA */
-+enum {
-+ XMIT_SZ_8BIT = 0,
-+ XMIT_SZ_16BIT = 1,
-+ XMIT_SZ_32BIT = 2,
-+ XMIT_SZ_64BIT = 7,
-+ XMIT_SZ_128BIT = 3,
-+ XMIT_SZ_256BIT = 4,
-+ XMIT_SZ_512BIT = 5,
-+};
-+
-+/* log2(size / 8) - used to calculate number of transfers */
-+#define TS_SHIFT { \
-+ [XMIT_SZ_8BIT] = 0, \
-+ [XMIT_SZ_16BIT] = 1, \
-+ [XMIT_SZ_32BIT] = 2, \
-+ [XMIT_SZ_64BIT] = 3, \
-+ [XMIT_SZ_128BIT] = 4, \
-+ [XMIT_SZ_256BIT] = 5, \
-+ [XMIT_SZ_512BIT] = 6, \
-+}
-+
-+#define TS_INDEX2VAL(i) ((((i) & 0x3) << 3) | (((i) & 0xc) << (20 - 2)))
-+#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz)))
-+#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz)))
-+
-+static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = {
-+ {
-+ .slave_id = SHDMA_SLAVE_FSIA_TX,
-+ .addr = 0xfe1f0024,
-+ .chcr = CHCR_TX(XMIT_SZ_32BIT),
-+ .mid_rid = 0xb1,
-+ }, {
-+ .slave_id = SHDMA_SLAVE_FSIA_RX,
-+ .addr = 0xfe1f0020,
-+ .chcr = CHCR_RX(XMIT_SZ_32BIT),
-+ .mid_rid = 0xb2,
-+ }, {
-+ .slave_id = SHDMA_SLAVE_FSIB_TX,
-+ .addr = 0xfe1f0064,
-+ .chcr = CHCR_TX(XMIT_SZ_32BIT),
-+ .mid_rid = 0xb5,
-+ },
-+};
-+
-+#define DMA_CHANNEL(a, b, c) \
-+{ \
-+ .offset = a, \
-+ .dmars = b, \
-+ .dmars_bit = c, \
-+ .chclr_offset = (0x220 - 0x20) + a \
-+}
-+
-+static const struct sh_dmae_channel r8a7740_dmae_channels[] = {
-+ DMA_CHANNEL(0x00, 0, 0),
-+ DMA_CHANNEL(0x10, 0, 8),
-+ DMA_CHANNEL(0x20, 4, 0),
-+ DMA_CHANNEL(0x30, 4, 8),
-+ DMA_CHANNEL(0x50, 8, 0),
-+ DMA_CHANNEL(0x60, 8, 8),
-+};
-+
-+static const unsigned int ts_shift[] = TS_SHIFT;
-+
-+static struct sh_dmae_pdata dma_platform_data = {
-+ .slave = r8a7740_dmae_slaves,
-+ .slave_num = ARRAY_SIZE(r8a7740_dmae_slaves),
-+ .channel = r8a7740_dmae_channels,
-+ .channel_num = ARRAY_SIZE(r8a7740_dmae_channels),
-+ .ts_low_shift = 3,
-+ .ts_low_mask = 0x18,
-+ .ts_high_shift = (20 - 2),
-+ .ts_high_mask = 0x00300000,
-+ .ts_shift = ts_shift,
-+ .ts_shift_num = ARRAY_SIZE(ts_shift),
-+ .dmaor_init = DMAOR_DME,
-+ .chclr_present = 1,
-+};
-+
-+/* Resource order important! */
-+static struct resource r8a7740_dmae0_resources[] = {
-+ {
-+ /* Channel registers and DMAOR */
-+ .start = 0xfe008020,
-+ .end = 0xfe00828f,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ /* DMARSx */
-+ .start = 0xfe009000,
-+ .end = 0xfe00900b,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ .name = "error_irq",
-+ .start = evt2irq(0x20c0),
-+ .end = evt2irq(0x20c0),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ {
-+ /* IRQ for channels 0-5 */
-+ .start = evt2irq(0x2000),
-+ .end = evt2irq(0x20a0),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+/* Resource order important! */
-+static struct resource r8a7740_dmae1_resources[] = {
-+ {
-+ /* Channel registers and DMAOR */
-+ .start = 0xfe018020,
-+ .end = 0xfe01828f,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ /* DMARSx */
-+ .start = 0xfe019000,
-+ .end = 0xfe01900b,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ .name = "error_irq",
-+ .start = evt2irq(0x21c0),
-+ .end = evt2irq(0x21c0),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ {
-+ /* IRQ for channels 0-5 */
-+ .start = evt2irq(0x2100),
-+ .end = evt2irq(0x21a0),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+/* Resource order important! */
-+static struct resource r8a7740_dmae2_resources[] = {
-+ {
-+ /* Channel registers and DMAOR */
-+ .start = 0xfe028020,
-+ .end = 0xfe02828f,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ /* DMARSx */
-+ .start = 0xfe029000,
-+ .end = 0xfe02900b,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ .name = "error_irq",
-+ .start = evt2irq(0x22c0),
-+ .end = evt2irq(0x22c0),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ {
-+ /* IRQ for channels 0-5 */
-+ .start = evt2irq(0x2200),
-+ .end = evt2irq(0x22a0),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device dma0_device = {
-+ .name = "sh-dma-engine",
-+ .id = 0,
-+ .resource = r8a7740_dmae0_resources,
-+ .num_resources = ARRAY_SIZE(r8a7740_dmae0_resources),
-+ .dev = {
-+ .platform_data = &dma_platform_data,
-+ },
-+};
-+
-+static struct platform_device dma1_device = {
-+ .name = "sh-dma-engine",
-+ .id = 1,
-+ .resource = r8a7740_dmae1_resources,
-+ .num_resources = ARRAY_SIZE(r8a7740_dmae1_resources),
-+ .dev = {
-+ .platform_data = &dma_platform_data,
-+ },
-+};
-+
-+static struct platform_device dma2_device = {
-+ .name = "sh-dma-engine",
-+ .id = 2,
-+ .resource = r8a7740_dmae2_resources,
-+ .num_resources = ARRAY_SIZE(r8a7740_dmae2_resources),
-+ .dev = {
-+ .platform_data = &dma_platform_data,
-+ },
-+};
-+
- /* I2C */
- static struct resource i2c0_resources[] = {
- [0] = {
-@@ -322,6 +517,9 @@ static struct platform_device i2c1_device = {
- static struct platform_device *r8a7740_late_devices[] __initdata = {
- &i2c0_device,
- &i2c1_device,
-+ &dma0_device,
-+ &dma1_device,
-+ &dma2_device,
- };
-
- /*
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b96167a50df2468ba7f7eb96fab0bec5e0ee7106 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 25 Jun 2012 03:37:00 -0700
-Subject: ARM: shmobile: r8a7740: add DMAEngine support for SDHI
-
-Current shdmac can support SDHI DMAC on r8a7740.
-This support reduce CPU duty when SDHI access.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit cb76eb812ee03187da3b46e190895b55019d2133)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/include/mach/r8a7740.h | 6 ++++++
- arch/arm/mach-shmobile/setup-r8a7740.c | 30 +++++++++++++++++++++++++++
- 2 files changed, 36 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-index f71507b..0f14ce8 100644
---- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
-+++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-@@ -591,6 +591,12 @@ enum {
- /* DMA slave IDs */
- enum {
- SHDMA_SLAVE_INVALID,
-+ SHDMA_SLAVE_SDHI0_RX,
-+ SHDMA_SLAVE_SDHI0_TX,
-+ SHDMA_SLAVE_SDHI1_RX,
-+ SHDMA_SLAVE_SDHI1_TX,
-+ SHDMA_SLAVE_SDHI2_RX,
-+ SHDMA_SLAVE_SDHI2_TX,
- SHDMA_SLAVE_FSIA_RX,
- SHDMA_SLAVE_FSIA_TX,
- SHDMA_SLAVE_FSIB_TX,
-diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
-index 516a7ec..320c43a 100644
---- a/arch/arm/mach-shmobile/setup-r8a7740.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
-@@ -306,6 +306,36 @@ enum {
-
- static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = {
- {
-+ .slave_id = SHDMA_SLAVE_SDHI0_TX,
-+ .addr = 0xe6850030,
-+ .chcr = CHCR_TX(XMIT_SZ_16BIT),
-+ .mid_rid = 0xc1,
-+ }, {
-+ .slave_id = SHDMA_SLAVE_SDHI0_RX,
-+ .addr = 0xe6850030,
-+ .chcr = CHCR_RX(XMIT_SZ_16BIT),
-+ .mid_rid = 0xc2,
-+ }, {
-+ .slave_id = SHDMA_SLAVE_SDHI1_TX,
-+ .addr = 0xe6860030,
-+ .chcr = CHCR_TX(XMIT_SZ_16BIT),
-+ .mid_rid = 0xc9,
-+ }, {
-+ .slave_id = SHDMA_SLAVE_SDHI1_RX,
-+ .addr = 0xe6860030,
-+ .chcr = CHCR_RX(XMIT_SZ_16BIT),
-+ .mid_rid = 0xca,
-+ }, {
-+ .slave_id = SHDMA_SLAVE_SDHI2_TX,
-+ .addr = 0xe6870030,
-+ .chcr = CHCR_TX(XMIT_SZ_16BIT),
-+ .mid_rid = 0xcd,
-+ }, {
-+ .slave_id = SHDMA_SLAVE_SDHI2_RX,
-+ .addr = 0xe6870030,
-+ .chcr = CHCR_RX(XMIT_SZ_16BIT),
-+ .mid_rid = 0xce,
-+ }, {
- .slave_id = SHDMA_SLAVE_FSIA_TX,
- .addr = 0xfe1f0024,
- .chcr = CHCR_TX(XMIT_SZ_32BIT),
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 59ea669a42f7a0fa16df6d769a6843d3060b64f2 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 25 Jun 2012 03:37:10 -0700
-Subject: ARM: shmobile: r8a7740: add DMAEngine support for USB
-
-Current shdmac can support USB DMAC on r8a7740.
-This support reduce CPU duty when USB access.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit dbf382e556931aa75b2d7970d64661544d6c327c)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/clock-r8a7740.c | 4 +-
- arch/arm/mach-shmobile/include/mach/r8a7740.h | 2 +
- arch/arm/mach-shmobile/setup-r8a7740.c | 87 +++++++++++++++++++++++++++
- 3 files changed, 92 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
-index 39b1311..daf3eac 100644
---- a/arch/arm/mach-shmobile/clock-r8a7740.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
-@@ -463,7 +463,7 @@ enum {
-
- MSTP230,
- MSTP222,
-- MSTP218, MSTP217, MSTP216,
-+ MSTP218, MSTP217, MSTP216, MSTP214,
- MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
-
- MSTP329, MSTP328, MSTP323, MSTP320,
-@@ -489,6 +489,7 @@ static struct clk mstp_clks[MSTP_NR] = {
- [MSTP218] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* DMAC1 */
- [MSTP217] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* DMAC2 */
- [MSTP216] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 16, 0), /* DMAC3 */
-+ [MSTP214] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 14, 0), /* USBDMAC */
- [MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */
- [MSTP206] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */
- [MSTP204] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */
-@@ -567,6 +568,7 @@ static struct clk_lookup lookups[] = {
- CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
- CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]),
- CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]),
-+ CLKDEV_DEV_ID("sh-dma-engine.3", &mstp_clks[MSTP214]),
- CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]),
- CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]),
- CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]),
-diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-index 0f14ce8..8bd7b9c 100644
---- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
-+++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-@@ -600,6 +600,8 @@ enum {
- SHDMA_SLAVE_FSIA_RX,
- SHDMA_SLAVE_FSIA_TX,
- SHDMA_SLAVE_FSIB_TX,
-+ SHDMA_SLAVE_USBHS_TX,
-+ SHDMA_SLAVE_USBHS_RX,
- };
-
- #endif /* __ASM_R8A7740_H__ */
-diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
-index 320c43a..5e84609 100644
---- a/arch/arm/mach-shmobile/setup-r8a7740.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
-@@ -501,6 +501,92 @@ static struct platform_device dma2_device = {
- },
- };
-
-+/* USB-DMAC */
-+/* Transmit sizes and respective CHCR register values */
-+enum {
-+ USBTS_XMIT_SZ_8BYTE = 0,
-+ USBTS_XMIT_SZ_16BYTE = 1,
-+ USBTS_XMIT_SZ_32BYTE = 2,
-+};
-+
-+/* log2(size / 8) - used to calculate number of transfers */
-+static const unsigned int dma_usbts_shift[] = {
-+ [USBTS_XMIT_SZ_8BYTE] = 3,
-+ [USBTS_XMIT_SZ_16BYTE] = 4,
-+ [USBTS_XMIT_SZ_32BYTE] = 5,
-+};
-+
-+static const struct sh_dmae_channel r8a7740_usb_dma_channels[] = {
-+ {
-+ .offset = 0,
-+ }, {
-+ .offset = 0x20,
-+ },
-+};
-+
-+#define USBTS_INDEX2VAL(i) (((i) & 3) << 6)
-+
-+static const struct sh_dmae_slave_config r8a7740_usb_dma_slaves[] = {
-+ {
-+ .slave_id = SHDMA_SLAVE_USBHS_TX,
-+ .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE),
-+ }, {
-+ .slave_id = SHDMA_SLAVE_USBHS_RX,
-+ .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE),
-+ },
-+};
-+
-+static struct sh_dmae_pdata usb_dma_platform_data = {
-+ .slave = r8a7740_usb_dma_slaves,
-+ .slave_num = ARRAY_SIZE(r8a7740_usb_dma_slaves),
-+ .channel = r8a7740_usb_dma_channels,
-+ .channel_num = ARRAY_SIZE(r8a7740_usb_dma_channels),
-+ .ts_low_shift = 6,
-+ .ts_low_mask = 0xc0,
-+ .ts_high_shift = 0,
-+ .ts_high_mask = 0,
-+ .ts_shift = dma_usbts_shift,
-+ .ts_shift_num = ARRAY_SIZE(dma_usbts_shift),
-+ .dmaor_init = DMAOR_DME,
-+ .chcr_offset = 0x14,
-+ .chcr_ie_bit = 1 << 5,
-+ .dmaor_is_32bit = 1,
-+ .needs_tend_set = 1,
-+ .no_dmars = 1,
-+ .slave_only = 1,
-+};
-+
-+static struct resource r8a7740_usb_dma_resources[] = {
-+ {
-+ /* Channel registers and DMAOR */
-+ .start = 0xe68a0020,
-+ .end = 0xe68a0064 - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ /* VCR/SWR/DMICR */
-+ .start = 0xe68a0000,
-+ .end = 0xe68a0014 - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ /* IRQ for channels */
-+ .start = evt2irq(0x0a00),
-+ .end = evt2irq(0x0a00),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device usb_dma_device = {
-+ .name = "sh-dma-engine",
-+ .id = 3,
-+ .resource = r8a7740_usb_dma_resources,
-+ .num_resources = ARRAY_SIZE(r8a7740_usb_dma_resources),
-+ .dev = {
-+ .platform_data = &usb_dma_platform_data,
-+ },
-+};
-+
- /* I2C */
- static struct resource i2c0_resources[] = {
- [0] = {
-@@ -550,6 +636,7 @@ static struct platform_device *r8a7740_late_devices[] __initdata = {
- &dma0_device,
- &dma1_device,
- &dma2_device,
-+ &usb_dma_device,
- };
-
- /*
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 5fa62ea250079de3ea68853067d0935524c3e766 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 25 Jun 2012 03:43:10 -0700
-Subject: ARM: shmobile: use common DMAEngine definitions on r8a7740
-
-This patch switch over to use common DMAEngine definitions,
-and reduced a waste of code.
-
-It is easy to understand if sh_dmae_pdata / sh_dmae_slave_config
-settings are used defined value instead of direct value.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit d7de938f3da618b1592427f625e150c0a68b9ecb)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/setup-r8a7740.c | 64 ++++++----------------------------
- 1 file changed, 11 insertions(+), 53 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
-index 5e84609..48d7bbf 100644
---- a/arch/arm/mach-shmobile/setup-r8a7740.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
-@@ -27,6 +27,7 @@
- #include <linux/sh_dma.h>
- #include <linux/sh_timer.h>
- #include <linux/dma-mapping.h>
-+#include <mach/dma-register.h>
- #include <mach/r8a7740.h>
- #include <mach/common.h>
- #include <mach/irqs.h>
-@@ -279,31 +280,6 @@ static struct platform_device *r8a7740_early_devices[] __initdata = {
- };
-
- /* DMA */
--enum {
-- XMIT_SZ_8BIT = 0,
-- XMIT_SZ_16BIT = 1,
-- XMIT_SZ_32BIT = 2,
-- XMIT_SZ_64BIT = 7,
-- XMIT_SZ_128BIT = 3,
-- XMIT_SZ_256BIT = 4,
-- XMIT_SZ_512BIT = 5,
--};
--
--/* log2(size / 8) - used to calculate number of transfers */
--#define TS_SHIFT { \
-- [XMIT_SZ_8BIT] = 0, \
-- [XMIT_SZ_16BIT] = 1, \
-- [XMIT_SZ_32BIT] = 2, \
-- [XMIT_SZ_64BIT] = 3, \
-- [XMIT_SZ_128BIT] = 4, \
-- [XMIT_SZ_256BIT] = 5, \
-- [XMIT_SZ_512BIT] = 6, \
--}
--
--#define TS_INDEX2VAL(i) ((((i) & 0x3) << 3) | (((i) & 0xc) << (20 - 2)))
--#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz)))
--#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz)))
--
- static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = {
- {
- .slave_id = SHDMA_SLAVE_SDHI0_TX,
-@@ -370,19 +346,17 @@ static const struct sh_dmae_channel r8a7740_dmae_channels[] = {
- DMA_CHANNEL(0x60, 8, 8),
- };
-
--static const unsigned int ts_shift[] = TS_SHIFT;
--
- static struct sh_dmae_pdata dma_platform_data = {
- .slave = r8a7740_dmae_slaves,
- .slave_num = ARRAY_SIZE(r8a7740_dmae_slaves),
- .channel = r8a7740_dmae_channels,
- .channel_num = ARRAY_SIZE(r8a7740_dmae_channels),
-- .ts_low_shift = 3,
-- .ts_low_mask = 0x18,
-- .ts_high_shift = (20 - 2),
-- .ts_high_mask = 0x00300000,
-- .ts_shift = ts_shift,
-- .ts_shift_num = ARRAY_SIZE(ts_shift),
-+ .ts_low_shift = TS_LOW_SHIFT,
-+ .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT,
-+ .ts_high_shift = TS_HI_SHIFT,
-+ .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT,
-+ .ts_shift = dma_ts_shift,
-+ .ts_shift_num = ARRAY_SIZE(dma_ts_shift),
- .dmaor_init = DMAOR_DME,
- .chclr_present = 1,
- };
-@@ -502,20 +476,6 @@ static struct platform_device dma2_device = {
- };
-
- /* USB-DMAC */
--/* Transmit sizes and respective CHCR register values */
--enum {
-- USBTS_XMIT_SZ_8BYTE = 0,
-- USBTS_XMIT_SZ_16BYTE = 1,
-- USBTS_XMIT_SZ_32BYTE = 2,
--};
--
--/* log2(size / 8) - used to calculate number of transfers */
--static const unsigned int dma_usbts_shift[] = {
-- [USBTS_XMIT_SZ_8BYTE] = 3,
-- [USBTS_XMIT_SZ_16BYTE] = 4,
-- [USBTS_XMIT_SZ_32BYTE] = 5,
--};
--
- static const struct sh_dmae_channel r8a7740_usb_dma_channels[] = {
- {
- .offset = 0,
-@@ -524,8 +484,6 @@ static const struct sh_dmae_channel r8a7740_usb_dma_channels[] = {
- },
- };
-
--#define USBTS_INDEX2VAL(i) (((i) & 3) << 6)
--
- static const struct sh_dmae_slave_config r8a7740_usb_dma_slaves[] = {
- {
- .slave_id = SHDMA_SLAVE_USBHS_TX,
-@@ -541,10 +499,10 @@ static struct sh_dmae_pdata usb_dma_platform_data = {
- .slave_num = ARRAY_SIZE(r8a7740_usb_dma_slaves),
- .channel = r8a7740_usb_dma_channels,
- .channel_num = ARRAY_SIZE(r8a7740_usb_dma_channels),
-- .ts_low_shift = 6,
-- .ts_low_mask = 0xc0,
-- .ts_high_shift = 0,
-- .ts_high_mask = 0,
-+ .ts_low_shift = USBTS_LOW_SHIFT,
-+ .ts_low_mask = USBTS_LOW_BIT << USBTS_LOW_SHIFT,
-+ .ts_high_shift = USBTS_HI_SHIFT,
-+ .ts_high_mask = USBTS_HI_BIT << USBTS_HI_SHIFT,
- .ts_shift = dma_usbts_shift,
- .ts_shift_num = ARRAY_SIZE(dma_usbts_shift),
- .dmaor_init = DMAOR_DME,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2b0c07b75a3b421285bae10961bf20e0011839b6 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 25 Jun 2012 03:32:50 -0700
-Subject: ARM: shmobile: armadillo800eva: enable FSI-WM8978 sound
-
-This patch enable sound support on CON11
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 5389bf719f87101339f292256392bff5ae926917)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/Kconfig | 1 +
- arch/arm/mach-shmobile/board-armadillo800eva.c | 99 ++++++++++++++++++++++++++
- 2 files changed, 100 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
-index da57dde..c74b74a 100644
---- a/arch/arm/mach-shmobile/Kconfig
-+++ b/arch/arm/mach-shmobile/Kconfig
-@@ -100,6 +100,7 @@ config MACH_ARMADILLO800EVA
- depends on ARCH_R8A7740
- select ARCH_REQUIRE_GPIOLIB
- select USE_OF
-+ select SND_SOC_WM8978 if SND_SIMPLE_CARD
-
- config MACH_MARZEN
- bool "MARZEN board"
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index a513ebe..afe7860 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -49,6 +49,8 @@
- #include <asm/hardware/cache-l2x0.h>
- #include <video/sh_mobile_lcdc.h>
- #include <video/sh_mobile_hdmi.h>
-+#include <sound/sh_fsi.h>
-+#include <sound/simple_card.h>
-
- /*
- * CON1 Camera Module
-@@ -112,6 +114,28 @@
- */
-
- /*
-+ * FSI-WM8978
-+ *
-+ * this command is required when playback.
-+ *
-+ * # amixer set "Headphone" 50
-+ */
-+
-+/*
-+ * FIXME !!
-+ *
-+ * gpio_no_direction
-+ *
-+ * current gpio frame work doesn't have
-+ * the method to control only pull up/down/free.
-+ * this function should be replaced by correct gpio function
-+ */
-+static void __init gpio_no_direction(u32 addr)
-+{
-+ __raw_writeb(0x00, addr);
-+}
-+
-+/*
- * USB function
- *
- * When you use USB Function,
-@@ -714,12 +738,71 @@ static struct platform_device ceu0_device = {
- },
- };
-
-+/* FSI */
-+static struct sh_fsi_platform_info fsi_info = {
-+ /* FSI-WM8978 */
-+ .port_a = {
-+ },
-+};
-+
-+static struct resource fsi_resources[] = {
-+ [0] = {
-+ .name = "FSI",
-+ .start = 0xfe1f0000,
-+ .end = 0xfe1f8400 - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = evt2irq(0x1840),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device fsi_device = {
-+ .name = "sh_fsi2",
-+ .id = -1,
-+ .num_resources = ARRAY_SIZE(fsi_resources),
-+ .resource = fsi_resources,
-+ .dev = {
-+ .platform_data = &fsi_info,
-+ },
-+};
-+
-+/* FSI-WM8978 */
-+static struct asoc_simple_dai_init_info fsi_wm8978_init_info = {
-+ .fmt = SND_SOC_DAIFMT_I2S,
-+ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF,
-+ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS,
-+ .sysclk = 12288000,
-+};
-+
-+static struct asoc_simple_card_info fsi_wm8978_info = {
-+ .name = "wm8978",
-+ .card = "FSI2A-WM8978",
-+ .cpu_dai = "fsia-dai",
-+ .codec = "wm8978.0-001a",
-+ .platform = "sh_fsi2",
-+ .codec_dai = "wm8978-hifi",
-+ .init = &fsi_wm8978_init_info,
-+};
-+
-+static struct platform_device fsi_wm8978_device = {
-+ .name = "asoc-simple-card",
-+ .id = 0,
-+ .dev = {
-+ .platform_data = &fsi_wm8978_info,
-+ },
-+};
-+
- /* I2C */
- static struct i2c_board_info i2c0_devices[] = {
- {
- I2C_BOARD_INFO("st1232-ts", 0x55),
- .irq = evt2irq(0x0340),
- },
-+ {
-+ I2C_BOARD_INFO("wm8978", 0x1a),
-+ },
- };
-
- /*
-@@ -735,6 +818,8 @@ static struct platform_device *eva_devices[] __initdata = {
- &hdmi_lcdc_device,
- &camera_device,
- &ceu0_device,
-+ &fsi_device,
-+ &fsi_wm8978_device,
- };
-
- static void __init eva_clock_init(void)
-@@ -768,6 +853,8 @@ clock_error:
- /*
- * board init
- */
-+#define GPIO_PORT7CR 0xe6050007
-+#define GPIO_PORT8CR 0xe6050008
- static void __init eva_init(void)
- {
- eva_clock_init();
-@@ -916,6 +1003,18 @@ static void __init eva_init(void)
- gpio_direction_output(GPIO_PORT172, 1);
- gpio_direction_output(GPIO_PORT158, 0); /* see mt9t111_power() */
-
-+ /* FSI-WM8978 */
-+ gpio_request(GPIO_FN_FSIAIBT, NULL);
-+ gpio_request(GPIO_FN_FSIAILR, NULL);
-+ gpio_request(GPIO_FN_FSIAOMC, NULL);
-+ gpio_request(GPIO_FN_FSIAOSLD, NULL);
-+ gpio_request(GPIO_FN_FSIAISLD_PORT5, NULL);
-+
-+ gpio_request(GPIO_PORT7, NULL);
-+ gpio_request(GPIO_PORT8, NULL);
-+ gpio_no_direction(GPIO_PORT7CR); /* FSIAOBT needs no direction */
-+ gpio_no_direction(GPIO_PORT8CR); /* FSIAOLR needs no direction */
-+
- /*
- * CAUTION
- *
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 850c6f996ee51eddf540325ec5c892073dbc2567 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 25 Jun 2012 03:33:04 -0700
-Subject: ARM: shmobile: armadillo800eva: enable FSI-HDMI sound
-
-This patch enable HDMI sound support on CON3
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 0676c05e57c6e37fc9f985a8f6ea2883e5b2cbda)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 82 +++++++++++++++++++++++++-
- 1 file changed, 79 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index afe7860..df5fd2c 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -739,10 +739,42 @@ static struct platform_device ceu0_device = {
- };
-
- /* FSI */
-+static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable)
-+{
-+ struct clk *fsib;
-+ int ret;
-+
-+ /* it support 48KHz only */
-+ if (48000 != rate)
-+ return -EINVAL;
-+
-+ fsib = clk_get(dev, "ickb");
-+ if (IS_ERR(fsib))
-+ return -EINVAL;
-+
-+ if (enable) {
-+ ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
-+ clk_enable(fsib);
-+ } else {
-+ ret = 0;
-+ clk_disable(fsib);
-+ }
-+
-+ clk_put(fsib);
-+
-+ return ret;
-+}
-+
- static struct sh_fsi_platform_info fsi_info = {
- /* FSI-WM8978 */
- .port_a = {
- },
-+ /* FSI-HDMI */
-+ .port_b = {
-+ .flags = SH_FSI_FMT_SPDIF |
-+ SH_FSI_ENABLE_STREAM_MODE,
-+ .set_rate = fsi_hdmi_set_rate,
-+ }
- };
-
- static struct resource fsi_resources[] = {
-@@ -794,6 +826,29 @@ static struct platform_device fsi_wm8978_device = {
- },
- };
-
-+/* FSI-HDMI */
-+static struct asoc_simple_dai_init_info fsi2_hdmi_init_info = {
-+ .cpu_daifmt = SND_SOC_DAIFMT_CBM_CFM,
-+};
-+
-+static struct asoc_simple_card_info fsi2_hdmi_info = {
-+ .name = "HDMI",
-+ .card = "FSI2B-HDMI",
-+ .cpu_dai = "fsib-dai",
-+ .codec = "sh-mobile-hdmi",
-+ .platform = "sh_fsi2",
-+ .codec_dai = "sh_mobile_hdmi-hifi",
-+ .init = &fsi2_hdmi_init_info,
-+};
-+
-+static struct platform_device fsi_hdmi_device = {
-+ .name = "asoc-simple-card",
-+ .id = 1,
-+ .dev = {
-+ .platform_data = &fsi2_hdmi_info,
-+ },
-+};
-+
- /* I2C */
- static struct i2c_board_info i2c0_devices[] = {
- {
-@@ -819,6 +874,7 @@ static struct platform_device *eva_devices[] __initdata = {
- &camera_device,
- &ceu0_device,
- &fsi_device,
-+ &fsi_hdmi_device,
- &fsi_wm8978_device,
- };
-
-@@ -827,10 +883,14 @@ static void __init eva_clock_init(void)
- struct clk *system = clk_get(NULL, "system_clk");
- struct clk *xtal1 = clk_get(NULL, "extal1");
- struct clk *usb24s = clk_get(NULL, "usb24s");
-+ struct clk *fsibck = clk_get(NULL, "fsibck");
-+ struct clk *fsib = clk_get(&fsi_device.dev, "ickb");
-
- if (IS_ERR(system) ||
- IS_ERR(xtal1) ||
-- IS_ERR(usb24s)) {
-+ IS_ERR(usb24s) ||
-+ IS_ERR(fsibck) ||
-+ IS_ERR(fsib)) {
- pr_err("armadillo800eva board clock init failed\n");
- goto clock_error;
- }
-@@ -841,6 +901,11 @@ static void __init eva_clock_init(void)
- /* usb24s use extal1 (= system) clock (= 24MHz) */
- clk_set_parent(usb24s, system);
-
-+ /* FSIBCK is 12.288MHz, and it is parent of FSI-B */
-+ clk_set_parent(fsib, fsibck);
-+ clk_set_rate(fsibck, 12288000);
-+ clk_set_rate(fsib, 12288000);
-+
- clock_error:
- if (!IS_ERR(system))
- clk_put(system);
-@@ -848,6 +913,10 @@ clock_error:
- clk_put(xtal1);
- if (!IS_ERR(usb24s))
- clk_put(usb24s);
-+ if (!IS_ERR(fsibck))
-+ clk_put(fsibck);
-+ if (!IS_ERR(fsib))
-+ clk_put(fsib);
- }
-
- /*
-@@ -857,8 +926,6 @@ clock_error:
- #define GPIO_PORT8CR 0xe6050008
- static void __init eva_init(void)
- {
-- eva_clock_init();
--
- r8a7740_pinmux_init();
- r8a7740_meram_workaround();
-
-@@ -1015,6 +1082,13 @@ static void __init eva_init(void)
- gpio_no_direction(GPIO_PORT7CR); /* FSIAOBT needs no direction */
- gpio_no_direction(GPIO_PORT8CR); /* FSIAOLR needs no direction */
-
-+ /* FSI-HDMI */
-+ gpio_request(GPIO_FN_FSIBCK, NULL);
-+
-+ /* HDMI */
-+ gpio_request(GPIO_FN_HDMI_HPD, NULL);
-+ gpio_request(GPIO_FN_HDMI_CEC, NULL);
-+
- /*
- * CAUTION
- *
-@@ -1061,6 +1135,8 @@ static void __init eva_init(void)
-
- platform_add_devices(eva_devices,
- ARRAY_SIZE(eva_devices));
-+
-+ eva_clock_init();
- }
-
- static void __init eva_earlytimer_init(void)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 95f8bc86715253ac6371cf581049a13a0a1d94eb Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 25 Jun 2012 03:37:20 -0700
-Subject: ARM: shmobile: armadillo800eva: enable DMAEngine on FSI
-
-It is possible to reduce CPU load if FSI playback used DMAEngine.
-This patch enabled it.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit dc7dd5841f714c3bc3f358cb126ba4432947e854)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/configs/armadillo800eva_defconfig | 2 ++
- arch/arm/mach-shmobile/board-armadillo800eva.c | 2 ++
- 2 files changed, 4 insertions(+)
-
-diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
-index df1ce54..16bbb3f 100644
---- a/arch/arm/configs/armadillo800eva_defconfig
-+++ b/arch/arm/configs/armadillo800eva_defconfig
-@@ -119,6 +119,8 @@ CONFIG_USB_ETH=m
- CONFIG_MMC=y
- CONFIG_MMC_SDHI=y
- CONFIG_MMC_SH_MMCIF=y
-+CONFIG_DMADEVICES=y
-+CONFIG_SH_DMAE=y
- CONFIG_UIO=y
- CONFIG_UIO_PDRV_GENIRQ=y
- # CONFIG_DNOTIFY is not set
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index df5fd2c..032e04d 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -768,12 +768,14 @@ static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable)
- static struct sh_fsi_platform_info fsi_info = {
- /* FSI-WM8978 */
- .port_a = {
-+ .tx_id = SHDMA_SLAVE_FSIA_TX,
- },
- /* FSI-HDMI */
- .port_b = {
- .flags = SH_FSI_FMT_SPDIF |
- SH_FSI_ENABLE_STREAM_MODE,
- .set_rate = fsi_hdmi_set_rate,
-+ .tx_id = SHDMA_SLAVE_FSIB_TX,
- }
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 67c3e7eb10a9da8600072c0b2292287dafe97219 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 25 Jun 2012 03:37:38 -0700
-Subject: ARM: shmobile: armadillo800eva: enable DMAEngine on SDHI
-
-It is possible to reduce CPU load if SDHI used DMAEngine.
-This patch enabled it.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 95798e350dde44920a021a7e7e720a3be15e8220)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index 032e04d..54bf618 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -543,6 +543,8 @@ static struct platform_device gpio_keys_device = {
- */
- #define IRQ31 evt2irq(0x33E0)
- static struct sh_mobile_sdhi_info sdhi0_info = {
-+ .dma_slave_tx = SHDMA_SLAVE_SDHI0_TX,
-+ .dma_slave_rx = SHDMA_SLAVE_SDHI0_RX,
- .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |\
- MMC_CAP_NEEDS_POLL,
- .tmio_ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
-@@ -583,6 +585,8 @@ static struct platform_device sdhi0_device = {
-
- /* SDHI1 */
- static struct sh_mobile_sdhi_info sdhi1_info = {
-+ .dma_slave_tx = SHDMA_SLAVE_SDHI1_TX,
-+ .dma_slave_rx = SHDMA_SLAVE_SDHI1_RX,
- .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
- .tmio_ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
- .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ad78daa637449523d9cdfd7b28f5ea0150ac349a Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 25 Jun 2012 03:37:47 -0700
-Subject: ARM: shmobile: armadillo800eva: enable DMAEngine on USB
-
-It is possible to reduce CPU load if USB used DMAEngine.
-This patch enabled it.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit f7e566fa26b7d34514d5ba7b8b4464934be8ff2c)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index 54bf618..539f1cf 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -297,6 +297,8 @@ static struct usbhsf_private usbhsf_private = {
- .driver_param = {
- .buswait_bwait = 5,
- .detection_delay = 5,
-+ .d0_rx_id = SHDMA_SLAVE_USBHS_RX,
-+ .d1_tx_id = SHDMA_SLAVE_USBHS_TX,
- },
- }
- };
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2d6b318376b8c20432ed164d31b047a74c6d5215 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 25 Jun 2012 03:41:45 -0700
-Subject: ARM: shmobile: use common extra gpio functions on armadillo800eva
-
-This patch switch over to use common extra gpio method,
-and reduced a waste of code on SH-ARM.
-
-But these functions should be replaced by correct
-gpio function in the future.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit a01366b4b5cc669633d1cf6ee327c85a5406ef5f)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 18 ++----------------
- 1 file changed, 2 insertions(+), 16 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index 539f1cf..a4fd71a 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -122,20 +122,6 @@
- */
-
- /*
-- * FIXME !!
-- *
-- * gpio_no_direction
-- *
-- * current gpio frame work doesn't have
-- * the method to control only pull up/down/free.
-- * this function should be replaced by correct gpio function
-- */
--static void __init gpio_no_direction(u32 addr)
--{
-- __raw_writeb(0x00, addr);
--}
--
--/*
- * USB function
- *
- * When you use USB Function,
-@@ -1087,8 +1073,8 @@ static void __init eva_init(void)
-
- gpio_request(GPIO_PORT7, NULL);
- gpio_request(GPIO_PORT8, NULL);
-- gpio_no_direction(GPIO_PORT7CR); /* FSIAOBT needs no direction */
-- gpio_no_direction(GPIO_PORT8CR); /* FSIAOLR needs no direction */
-+ gpio_direction_none(GPIO_PORT7CR); /* FSIAOBT needs no direction */
-+ gpio_direction_none(GPIO_PORT8CR); /* FSIAOLR needs no direction */
-
- /* FSI-HDMI */
- gpio_request(GPIO_FN_FSIBCK, NULL);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 6a9259faadbdfcb18a8f2ee78d414ae7194a2b10 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Fri, 29 Jun 2012 08:33:11 +0200
-Subject: ARM: mach-shmobile: add fixed voltage regulators to armadillo800eva
-
-On armadillo800eva provide a 3.3V supply for its SD/MMC-card interfaces.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit f65ad7e36cbae24f05ea2314ad63e9dd23294c60)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 16 ++++++++++++++++
- 1 file changed, 16 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index a4fd71a..7c77f07 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -28,6 +28,8 @@
- #include <linux/platform_device.h>
- #include <linux/gpio.h>
- #include <linux/gpio_keys.h>
-+#include <linux/regulator/fixed.h>
-+#include <linux/regulator/machine.h>
- #include <linux/sh_eth.h>
- #include <linux/videodev2.h>
- #include <linux/usb/renesas_usbhs.h>
-@@ -520,6 +522,17 @@ static struct platform_device gpio_keys_device = {
- },
- };
-
-+/* Fixed 3.3V regulator to be used by SDHI0, SDHI1, MMCIF */
-+static struct regulator_consumer_supply fixed3v3_power_consumers[] =
-+{
-+ REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
-+ REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"),
-+ REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"),
-+ REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.1"),
-+ REGULATOR_SUPPLY("vmmc", "sh_mmcif"),
-+ REGULATOR_SUPPLY("vqmmc", "sh_mmcif"),
-+};
-+
- /* SDHI0 */
- /*
- * FIXME
-@@ -920,6 +933,9 @@ clock_error:
- #define GPIO_PORT8CR 0xe6050008
- static void __init eva_init(void)
- {
-+ regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
-+ ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
-+
- r8a7740_pinmux_init();
- r8a7740_meram_workaround();
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 34b7faf5447e1eefc86e43779a132ad8e8cf5c32 Mon Sep 17 00:00:00 2001
-From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
-Date: Wed, 27 Jun 2012 09:59:00 +0900
-Subject: ARM: mach-shmobile: Convert sh_clk_mstp32_register to
- sh_clk_mstp_register
-
-sh_clk_mstp32_register is deprecated. This convert to sh_clk_mstp_register.
-
-Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 64e9de2f854fb5d08d255b24568c60b090f2603a)
-
-Conflicts:
- arch/arm/mach-shmobile/clock-r8a7740.c
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/clock-r8a7740.c | 2 +-
- arch/arm/mach-shmobile/clock-r8a7779.c | 2 +-
- arch/arm/mach-shmobile/clock-sh7367.c | 2 +-
- arch/arm/mach-shmobile/clock-sh7372.c | 2 +-
- arch/arm/mach-shmobile/clock-sh7377.c | 2 +-
- arch/arm/mach-shmobile/clock-sh73a0.c | 2 +-
- 6 files changed, 6 insertions(+), 6 deletions(-)
-
---- a/arch/arm/mach-shmobile/clock-r8a7740.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
-@@ -636,7 +636,7 @@ void __init r8a7740_clock_init(u8 md_ck)
- DIV6_REPARENT_NR);
-
- if (!ret)
-- ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
-+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
-
- for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
- ret = clk_register(late_main_clks[k]);
---- a/arch/arm/mach-shmobile/clock-r8a7779.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
-@@ -167,7 +167,7 @@ void __init r8a7779_clock_init(void)
- ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
-
- if (!ret)
-- ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
-+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
-
- for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
- ret = clk_register(late_main_clks[k]);
---- a/arch/arm/mach-shmobile/clock-sh7367.c
-+++ b/arch/arm/mach-shmobile/clock-sh7367.c
-@@ -344,7 +344,7 @@ void __init sh7367_clock_init(void)
- ret = sh_clk_div6_register(div6_clks, DIV6_NR);
-
- if (!ret)
-- ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
-+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
-
- clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
---- a/arch/arm/mach-shmobile/clock-sh7372.c
-+++ b/arch/arm/mach-shmobile/clock-sh7372.c
-@@ -704,7 +704,7 @@ void __init sh7372_clock_init(void)
- ret = sh_clk_div6_reparent_register(div6_reparent_clks, DIV6_REPARENT_NR);
-
- if (!ret)
-- ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
-+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
-
- for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
- ret = clk_register(late_main_clks[k]);
---- a/arch/arm/mach-shmobile/clock-sh7377.c
-+++ b/arch/arm/mach-shmobile/clock-sh7377.c
-@@ -355,7 +355,7 @@ void __init sh7377_clock_init(void)
- ret = sh_clk_div6_register(div6_clks, DIV6_NR);
-
- if (!ret)
-- ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
-+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
-
- clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
---- a/arch/arm/mach-shmobile/clock-sh73a0.c
-+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
-@@ -612,7 +612,7 @@ void __init sh73a0_clock_init(void)
- ret = sh_clk_div6_reparent_register(div6_clks, DIV6_NR);
-
- if (!ret)
-- ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
-+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
-
- for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
- ret = clk_register(late_main_clks[k]);
+++ /dev/null
-From e52c21c95e6ce158bd78d4b0d3b55fb4350beb4a Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Thu, 5 Jul 2012 01:25:24 -0700
-Subject: ARM: shmobile: r8a7740: fixup: MSEL1CR 7bit control
-
-MSEL1CR 7bit selects IRQ7 source pin which was
-VBUS pin or A21/MSIOF0_RSYNC/MSIOF1_TSYNC pin.
-But current pfc-r8a7740 MSEL1CR 7bit setting was wrong.
-This patch fix it up
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 444c5ed8d746140cd8f5591f708e5f1f84a9876e)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/pfc-r8a7740.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c
-index 03def0f..ce9e7fa 100644
---- a/arch/arm/mach-shmobile/pfc-r8a7740.c
-+++ b/arch/arm/mach-shmobile/pfc-r8a7740.c
-@@ -1261,7 +1261,7 @@ static pinmux_enum_t pinmux_data[] = {
- PINMUX_DATA(A21_MARK, PORT120_FN1),
- PINMUX_DATA(MSIOF0_RSYNC_MARK, PORT120_FN2),
- PINMUX_DATA(MSIOF1_TSYNC_PORT120_MARK, PORT120_FN3, MSEL4CR_10_0),
-- PINMUX_DATA(IRQ7_PORT120_MARK, PORT120_FN0, MSEL1CR_7_0),
-+ PINMUX_DATA(IRQ7_PORT120_MARK, PORT120_FN0, MSEL1CR_7_1),
-
- /* Port121 */
- PINMUX_DATA(A20_MARK, PORT121_FN1),
-@@ -1623,7 +1623,7 @@ static pinmux_enum_t pinmux_data[] = {
-
- /* Port209 */
- PINMUX_DATA(VBUS_MARK, PORT209_FN1),
-- PINMUX_DATA(IRQ7_PORT209_MARK, PORT209_FN0, MSEL1CR_7_1),
-+ PINMUX_DATA(IRQ7_PORT209_MARK, PORT209_FN0, MSEL1CR_7_0),
-
- /* Port210 */
- PINMUX_DATA(IRQ9_PORT210_MARK, PORT210_FN0, MSEL1CR_9_1),
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From cfbc3351777b8b9160e410b3f1dfdb2558214b1a Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Thu, 5 Jul 2012 01:25:58 -0700
-Subject: ARM: shmobile: r8a7740: add A4S pm domain support
-
-This patch adds basic A4S pm domain support.
-Now, below devices can be controled by PM
-
-Common-SHwy, Common-HPB, BSC, MFI, MMFROM, HS-SHwy,
-SYS-HPB, INTCA, DBSC, DDRPHY (Logic),
-ATAPI, GbEther, AXI-bus
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 8459293c27bcd13aabacb7ee8097f6818f2ceedb)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/Makefile | 1 +
- arch/arm/mach-shmobile/include/mach/r8a7740.h | 6 ++++++
- arch/arm/mach-shmobile/pm-r8a7740.c | 30 +++++++++++++++++++++++++++
- arch/arm/mach-shmobile/setup-r8a7740.c | 5 +++++
- 4 files changed, 42 insertions(+)
- create mode 100644 arch/arm/mach-shmobile/pm-r8a7740.c
-
-diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
-index b39033b..7804bd1 100644
---- a/arch/arm/mach-shmobile/Makefile
-+++ b/arch/arm/mach-shmobile/Makefile
-@@ -39,6 +39,7 @@ obj-$(CONFIG_SUSPEND) += suspend.o
- obj-$(CONFIG_CPU_IDLE) += cpuidle.o
- obj-$(CONFIG_ARCH_SHMOBILE) += pm-rmobile.o
- obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o sleep-sh7372.o
-+obj-$(CONFIG_ARCH_R8A7740) += pm-r8a7740.o
- obj-$(CONFIG_ARCH_R8A7779) += pm-r8a7779.o
-
- # Board objects
-diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-index 8bd7b9c..e8c87e9 100644
---- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
-+++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-@@ -19,6 +19,8 @@
- #ifndef __ASM_R8A7740_H__
- #define __ASM_R8A7740_H__
-
-+#include <mach/pm-rmobile.h>
-+
- /*
- * MD_CKx pin
- */
-@@ -604,4 +606,8 @@ enum {
- SHDMA_SLAVE_USBHS_RX,
- };
-
-+#ifdef CONFIG_PM
-+extern struct rmobile_pm_domain r8a7740_pd_a4s;
-+#endif /* CONFIG_PM */
-+
- #endif /* __ASM_R8A7740_H__ */
-diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c
-new file mode 100644
-index 0000000..d2fe815
---- /dev/null
-+++ b/arch/arm/mach-shmobile/pm-r8a7740.c
-@@ -0,0 +1,30 @@
-+/*
-+ * r8a7740 power management support
-+ *
-+ * Copyright (C) 2012 Renesas Solutions Corp.
-+ * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-+ *
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ */
-+#include <mach/pm-rmobile.h>
-+
-+#ifdef CONFIG_PM
-+static int r8a7740_pd_a4s_suspend(void)
-+{
-+ /*
-+ * The A4S domain contains the CPU core and therefore it should
-+ * only be turned off if the CPU is in use.
-+ */
-+ return -EBUSY;
-+}
-+
-+struct rmobile_pm_domain r8a7740_pd_a4s = {
-+ .genpd.name = "A4S",
-+ .bit_shift = 10,
-+ .gov = &pm_domain_always_on_gov,
-+ .no_debug = true,
-+ .suspend = r8a7740_pd_a4s_suspend,
-+};
-+#endif /* CONFIG_PM */
-diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
-index 48d7bbf..c37ad75 100644
---- a/arch/arm/mach-shmobile/setup-r8a7740.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
-@@ -29,6 +29,7 @@
- #include <linux/dma-mapping.h>
- #include <mach/dma-register.h>
- #include <mach/r8a7740.h>
-+#include <mach/pm-rmobile.h>
- #include <mach/common.h>
- #include <mach/irqs.h>
- #include <asm/mach-types.h>
-@@ -671,6 +672,10 @@ void __init r8a7740_add_standard_devices(void)
- r8a7740_i2c_workaround(&i2c0_device);
- r8a7740_i2c_workaround(&i2c1_device);
-
-+ /* PM domain */
-+ rmobile_init_pm_domain(&r8a7740_pd_a4s);
-+
-+ /* add devices */
- platform_add_devices(r8a7740_early_devices,
- ARRAY_SIZE(r8a7740_early_devices));
- platform_add_devices(r8a7740_late_devices,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 12c6836de664df0456e3d827b605ef1bf4bb323a Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Thu, 5 Jul 2012 01:26:31 -0700
-Subject: ARM: shmobile: r8a7740: add A3SP pm domain support
-
-This patch adds basic A3SP pm domain support.
-Now, below devices can be controled by PM
-
-DMAC1/2/3, IPMMU, DDM, FLCTL, SYS-HPB, BBIF1, MSIOF1/2,
-SCIFA,SCIFB, IIC1, IrDA, USBH, USBDMAC, SDHI0/1/2, TPU,
-DREQPAK (Sys), MMCIF, RSPI, SIM, USBF
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 802a5639aa7041b27cb865d3be289cd8afe3387b)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/include/mach/r8a7740.h | 1 +
- arch/arm/mach-shmobile/pm-r8a7740.c | 19 +++++++++++++++++++
- arch/arm/mach-shmobile/setup-r8a7740.c | 16 ++++++++++++++++
- 3 files changed, 36 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-index e8c87e9..a5691cf 100644
---- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
-+++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-@@ -608,6 +608,7 @@ enum {
-
- #ifdef CONFIG_PM
- extern struct rmobile_pm_domain r8a7740_pd_a4s;
-+extern struct rmobile_pm_domain r8a7740_pd_a3sp;
- #endif /* CONFIG_PM */
-
- #endif /* __ASM_R8A7740_H__ */
-diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c
-index d2fe815..de7c621 100644
---- a/arch/arm/mach-shmobile/pm-r8a7740.c
-+++ b/arch/arm/mach-shmobile/pm-r8a7740.c
-@@ -8,6 +8,7 @@
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-+#include <linux/console.h>
- #include <mach/pm-rmobile.h>
-
- #ifdef CONFIG_PM
-@@ -27,4 +28,22 @@ struct rmobile_pm_domain r8a7740_pd_a4s = {
- .no_debug = true,
- .suspend = r8a7740_pd_a4s_suspend,
- };
-+
-+static int r8a7740_pd_a3sp_suspend(void)
-+{
-+ /*
-+ * Serial consoles make use of SCIF hardware located in A3SP,
-+ * keep such power domain on if "no_console_suspend" is set.
-+ */
-+ return console_suspend_enabled ? 0 : -EBUSY;
-+}
-+
-+struct rmobile_pm_domain r8a7740_pd_a3sp = {
-+ .genpd.name = "A3SP",
-+ .bit_shift = 11,
-+ .gov = &pm_domain_always_on_gov,
-+ .no_debug = true,
-+ .suspend = r8a7740_pd_a3sp_suspend,
-+};
-+
- #endif /* CONFIG_PM */
-diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
-index c37ad75..59c79412 100644
---- a/arch/arm/mach-shmobile/setup-r8a7740.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
-@@ -674,12 +674,28 @@ void __init r8a7740_add_standard_devices(void)
-
- /* PM domain */
- rmobile_init_pm_domain(&r8a7740_pd_a4s);
-+ rmobile_init_pm_domain(&r8a7740_pd_a3sp);
-+
-+ rmobile_pm_add_subdomain(&r8a7740_pd_a4s, &r8a7740_pd_a3sp);
-
- /* add devices */
- platform_add_devices(r8a7740_early_devices,
- ARRAY_SIZE(r8a7740_early_devices));
- platform_add_devices(r8a7740_late_devices,
- ARRAY_SIZE(r8a7740_late_devices));
-+
-+ /* add devices to PM domain */
-+
-+ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif0_device);
-+ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif1_device);
-+ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif2_device);
-+ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif3_device);
-+ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif4_device);
-+ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif5_device);
-+ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif6_device);
-+ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif7_device);
-+ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scifb_device);
-+ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &i2c1_device);
- }
-
- static void __init r8a7740_earlytimer_init(void)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ffd8b73a5eead1c3d0361edd426cd5560a853b6c Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Thu, 5 Jul 2012 01:26:53 -0700
-Subject: ARM: shmobile: r8a7740: add A4LC pm domain support
-
-This patch adds basic A4LC pm domain support.
-Now, below devices can be controled by PM
-
-MERAM, LCDC, VOU, ICBS, SDENC-Link
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit a330ce3cdaba5202051edf8ae69482e15fdc9db5)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/include/mach/r8a7740.h | 1 +
- arch/arm/mach-shmobile/pm-r8a7740.c | 5 +++++
- arch/arm/mach-shmobile/setup-r8a7740.c | 1 +
- 3 files changed, 7 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-index a5691cf..7143147 100644
---- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
-+++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
-@@ -609,6 +609,7 @@ enum {
- #ifdef CONFIG_PM
- extern struct rmobile_pm_domain r8a7740_pd_a4s;
- extern struct rmobile_pm_domain r8a7740_pd_a3sp;
-+extern struct rmobile_pm_domain r8a7740_pd_a4lc;
- #endif /* CONFIG_PM */
-
- #endif /* __ASM_R8A7740_H__ */
-diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c
-index de7c621..893504d 100644
---- a/arch/arm/mach-shmobile/pm-r8a7740.c
-+++ b/arch/arm/mach-shmobile/pm-r8a7740.c
-@@ -46,4 +46,9 @@ struct rmobile_pm_domain r8a7740_pd_a3sp = {
- .suspend = r8a7740_pd_a3sp_suspend,
- };
-
-+struct rmobile_pm_domain r8a7740_pd_a4lc = {
-+ .genpd.name = "A4LC",
-+ .bit_shift = 1,
-+};
-+
- #endif /* CONFIG_PM */
-diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
-index 59c79412..c006d8d 100644
---- a/arch/arm/mach-shmobile/setup-r8a7740.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
-@@ -675,6 +675,7 @@ void __init r8a7740_add_standard_devices(void)
- /* PM domain */
- rmobile_init_pm_domain(&r8a7740_pd_a4s);
- rmobile_init_pm_domain(&r8a7740_pd_a3sp);
-+ rmobile_init_pm_domain(&r8a7740_pd_a4lc);
-
- rmobile_pm_add_subdomain(&r8a7740_pd_a4s, &r8a7740_pd_a3sp);
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a15b184d2c262c2133a1573ae9516633fdaf6f60 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Thu, 5 Jul 2012 01:27:14 -0700
-Subject: ARM: shmobile: armadillo800eva: USB Func enables external IRQ mode
-
-We can control renesas_usbhs driver as 2 way which are
-autonomy mode and external IRQ trigger mode.
-
-Autonomy mode is very easy settings for platform,
-but it required USB power domain always ON,
-since its connection/disconnection IRQ come from it.
-
-If platform uses external IRQ trigger mode,
-USB power domain can be OFF, since its
-connection/disconnection IRQ come from external IRQ.
-
-This patch enable external IRQ mode.
-Now it is possible to add USB support on A4SP domain.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit d483b983a5efaa101714186a8485a5fd4de42fba)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 46 +++++++++++++++++++++-----
- 1 file changed, 38 insertions(+), 8 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index 7c77f07..5002f64 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -133,14 +133,8 @@
- * These are a little bit complex.
- * see
- * usbhsf_power_ctrl()
-- *
-- * CAUTION
-- *
-- * It uses autonomy mode for USB hotplug at this point
-- * (= usbhs_private.platform_callback.get_vbus is NULL),
-- * since we don't know what's happen on PM control
-- * on this workaround.
- */
-+#define IRQ7 evt2irq(0x02e0)
- #define USBCR1 0xe605810a
- #define USBH 0xC6700000
- #define USBH_USBCTR 0x10834
-@@ -220,6 +214,20 @@ static void usbhsf_power_ctrl(struct platform_device *pdev,
- }
- }
-
-+static int usbhsf_get_vbus(struct platform_device *pdev)
-+{
-+ return gpio_get_value(GPIO_PORT209);
-+}
-+
-+static irqreturn_t usbhsf_interrupt(int irq, void *data)
-+{
-+ struct platform_device *pdev = data;
-+
-+ renesas_usbhs_call_notify_hotplug(pdev);
-+
-+ return IRQ_HANDLED;
-+}
-+
- static void usbhsf_hardware_exit(struct platform_device *pdev)
- {
- struct usbhsf_private *priv = usbhsf_get_priv(pdev);
-@@ -243,11 +251,14 @@ static void usbhsf_hardware_exit(struct platform_device *pdev)
- priv->host = NULL;
- priv->func = NULL;
- priv->usbh_base = NULL;
-+
-+ free_irq(IRQ7, pdev);
- }
-
- static int usbhsf_hardware_init(struct platform_device *pdev)
- {
- struct usbhsf_private *priv = usbhsf_get_priv(pdev);
-+ int ret;
-
- priv->phy = clk_get(&pdev->dev, "phy");
- priv->usb24 = clk_get(&pdev->dev, "usb24");
-@@ -267,6 +278,14 @@ static int usbhsf_hardware_init(struct platform_device *pdev)
- return -EIO;
- }
-
-+ ret = request_irq(IRQ7, usbhsf_interrupt, IRQF_TRIGGER_NONE,
-+ dev_name(&pdev->dev), pdev);
-+ if (ret) {
-+ dev_err(&pdev->dev, "request_irq err\n");
-+ return ret;
-+ }
-+ irq_set_irq_type(IRQ7, IRQ_TYPE_EDGE_BOTH);
-+
- /* usb24 use 1/1 of parent clock (= usb24s = 24MHz) */
- clk_set_rate(priv->usb24,
- clk_get_rate(clk_get_parent(priv->usb24)));
-@@ -278,6 +297,7 @@ static struct usbhsf_private usbhsf_private = {
- .info = {
- .platform_callback = {
- .get_id = usbhsf_get_id,
-+ .get_vbus = usbhsf_get_vbus,
- .hardware_init = usbhsf_hardware_init,
- .hardware_exit = usbhsf_hardware_exit,
- .power_ctrl = usbhsf_power_ctrl,
-@@ -1018,7 +1038,17 @@ static void __init eva_init(void)
- /* USB Host */
- } else {
- /* USB Func */
-- gpio_request(GPIO_FN_VBUS, NULL);
-+ /*
-+ * A1 chip has 2 IRQ7 pin and it was controled by MSEL register.
-+ * OTOH, usbhs interrupt needs its value (HI/LOW) to decide
-+ * USB connection/disconnection (usbhsf_get_vbus()).
-+ * This means we needs to select GPIO_FN_IRQ7_PORT209 first,
-+ * and select GPIO_PORT209 here
-+ */
-+ gpio_request(GPIO_FN_IRQ7_PORT209, NULL);
-+ gpio_request(GPIO_PORT209, NULL);
-+ gpio_direction_input(GPIO_PORT209);
-+
- platform_device_register(&usbhsf_device);
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ac8b41bd50ebd214726fffdac141ee4d37d3fb40 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Thu, 5 Jul 2012 01:27:37 -0700
-Subject: ARM: shmobile: armadillo800eva: A4LC domain includes LCDC
-
-It is possible to control LCDC under A4LC domain to reduce power.
-This patch enable it.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 1000076a88d58acf77d8fa8bf5d2567425b8ea1b)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index 5002f64..101242a 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -1177,6 +1177,9 @@ static void __init eva_init(void)
- ARRAY_SIZE(eva_devices));
-
- eva_clock_init();
-+
-+ rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &lcdc0_device);
-+ rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &hdmi_lcdc_device);
- }
-
- static void __init eva_earlytimer_init(void)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 481b82720f5d1da8062da229cecc6ccfd875fb68 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Thu, 5 Jul 2012 01:28:00 -0700
-Subject: ARM: shmobile: armadillo800eva: A3SP domain includes USB
-
-Because USB Func is controlled by external IRQ mode,
-it is possible to control USB under A3SP domain to reduce power.
-This patch enables it.
-
-Armadillo800eva board switchs USB Host/Func by SW1.6,
-So, the device to adds into domain is selected on this patch.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 0f54788d8b4f7aa8d74b0a5a0ad706bcc216b3c7)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index 101242a..cf10f92 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -953,6 +953,8 @@ clock_error:
- #define GPIO_PORT8CR 0xe6050008
- static void __init eva_init(void)
- {
-+ struct platform_device *usb = NULL;
-+
- regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
- ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
-
-@@ -1050,6 +1052,7 @@ static void __init eva_init(void)
- gpio_direction_input(GPIO_PORT209);
-
- platform_device_register(&usbhsf_device);
-+ usb = &usbhsf_device;
- }
-
- /* SDHI0 */
-@@ -1180,6 +1183,8 @@ static void __init eva_init(void)
-
- rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &lcdc0_device);
- rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &hdmi_lcdc_device);
-+ if (usb)
-+ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, usb);
- }
-
- static void __init eva_earlytimer_init(void)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From db4818fde4a8b81acde03834936d131a21c4ae4f Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Fri, 6 Jul 2012 17:08:07 +0900
-Subject: ARM: mach-shmobile: r8a7740 generic board support via DT
-
-Add generic DT board support for the r8a7740 SoC.
-
-SCIF serial ports and timers are kept as regular
-platform devices. Other on-chip and on-board devices
-should be configured via the device tree.
-
-At this point there is no interrupt controller support
-in place but such code will be added over time when
-proper IRQ domain support has been added to INTC.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 755d57b2229bd8cfa1d553c0b6878f2096f55ec3)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/boot/dts/r8a7740.dtsi | 21 +++++++++++++++
- arch/arm/mach-shmobile/setup-r8a7740.c | 47 ++++++++++++++++++++++++++++++++++
- 2 files changed, 68 insertions(+)
- create mode 100644 arch/arm/boot/dts/r8a7740.dtsi
-
-diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi
-new file mode 100644
-index 0000000..798fa35
---- /dev/null
-+++ b/arch/arm/boot/dts/r8a7740.dtsi
-@@ -0,0 +1,21 @@
-+/*
-+ * Device Tree Source for the r8a7740 SoC
-+ *
-+ * Copyright (C) 2012 Renesas Solutions Corp.
-+ *
-+ * 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/ "skeleton.dtsi"
-+
-+/ {
-+ compatible = "renesas,r8a7740";
-+
-+ cpus {
-+ cpu@0 {
-+ compatible = "arm,cortex-a9";
-+ };
-+ };
-+};
-diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
-index c006d8d..78948a9 100644
---- a/arch/arm/mach-shmobile/setup-r8a7740.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
-@@ -23,6 +23,7 @@
- #include <linux/init.h>
- #include <linux/io.h>
- #include <linux/platform_device.h>
-+#include <linux/of_platform.h>
- #include <linux/serial_sci.h>
- #include <linux/sh_dma.h>
- #include <linux/sh_timer.h>
-@@ -716,3 +717,49 @@ void __init r8a7740_add_early_devices(void)
- /* override timer setup with soc-specific code */
- shmobile_timer.init = r8a7740_earlytimer_init;
- }
-+
-+#ifdef CONFIG_USE_OF
-+
-+void __init r8a7740_add_early_devices_dt(void)
-+{
-+ shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */
-+
-+ early_platform_add_devices(r8a7740_early_devices,
-+ ARRAY_SIZE(r8a7740_early_devices));
-+
-+ /* setup early console here as well */
-+ shmobile_setup_console();
-+}
-+
-+static const struct of_dev_auxdata r8a7740_auxdata_lookup[] __initconst = {
-+ { }
-+};
-+
-+void __init r8a7740_add_standard_devices_dt(void)
-+{
-+ /* clocks are setup late during boot in the case of DT */
-+ r8a7740_clock_init(0);
-+
-+ platform_add_devices(r8a7740_early_devices,
-+ ARRAY_SIZE(r8a7740_early_devices));
-+
-+ of_platform_populate(NULL, of_default_bus_match_table,
-+ r8a7740_auxdata_lookup, NULL);
-+}
-+
-+static const char *r8a7740_boards_compat_dt[] __initdata = {
-+ "renesas,r8a7740",
-+ NULL,
-+};
-+
-+DT_MACHINE_START(SH7372_DT, "Generic R8A7740 (Flattened Device Tree)")
-+ .map_io = r8a7740_map_io,
-+ .init_early = r8a7740_add_early_devices_dt,
-+ .init_irq = r8a7740_init_irq,
-+ .handle_irq = shmobile_handle_irq_intc,
-+ .init_machine = r8a7740_add_standard_devices_dt,
-+ .timer = &shmobile_timer,
-+ .dt_compat = r8a7740_boards_compat_dt,
-+MACHINE_END
-+
-+#endif /* CONFIG_USE_OF */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 8a8dced180f83f64ff5d6098281f27053df630ad Mon Sep 17 00:00:00 2001
-From: Simon Horman <horms@verge.net.au>
-Date: Fri, 6 Jul 2012 20:08:15 +0900
-Subject: ARM: mach-shmobile: armadillo800eva: defconfig Allow use of armhf
- userspace
-
-This allows use a Debian armhf usespace
-as well as the existing ability to use a Debian armel userspace.
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 70523b4e57cb6eeb1da7c8ebf19df855221825ad)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/configs/armadillo800eva_defconfig | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
-index 16bbb3f..7d87184 100644
---- a/arch/arm/configs/armadillo800eva_defconfig
-+++ b/arch/arm/configs/armadillo800eva_defconfig
-@@ -18,7 +18,7 @@ CONFIG_ARCH_SHMOBILE=y
- CONFIG_ARCH_R8A7740=y
- CONFIG_MACH_ARMADILLO800EVA=y
- # CONFIG_SH_TIMER_TMU is not set
--# CONFIG_ARM_THUMB is not set
-+CONFIG_ARM_THUMB=y
- CONFIG_CPU_BPREDICT_DISABLE=y
- # CONFIG_CACHE_L2X0 is not set
- CONFIG_ARM_ERRATA_430973=y
-@@ -36,6 +36,7 @@ CONFIG_ZBOOT_ROM_BSS=0x0
- CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096"
- CONFIG_CMDLINE_FORCE=y
- CONFIG_KEXEC=y
-+CONFIG_VFP=y
- # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
- # CONFIG_SUSPEND is not set
- CONFIG_NET=y
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From fdfc19ff5c71ac77f6cc8781402dd92452e4e053 Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Tue, 24 Jul 2012 15:26:08 +0200
-Subject: ARM: mach-shmobile: armadillo800eva: Fix GPIO buttons descriptions
-
-The GPIO buttons are named SW3, SW4, SW5 and SW6 on the board
-silkscreen. Update the buttons descriptions accordingly.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Simon Horman <horms@verge.net.au>
-(cherry picked from commit 2d85b9494d10501f20ebf043f8d599e45736d78f)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index cf10f92..a002504 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -523,10 +523,10 @@ static struct platform_device hdmi_lcdc_device = {
- #define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
-
- static struct gpio_keys_button gpio_buttons[] = {
-- GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW1"),
-- GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW2"),
-- GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW3"),
-- GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW4"),
-+ GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW3"),
-+ GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW4"),
-+ GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW5"),
-+ GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW6"),
- };
-
- static struct gpio_keys_platform_data gpio_key_info = {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 10ee1d677c8fa257269f2c5e062525035b866a61 Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Tue, 24 Jul 2012 15:26:09 +0200
-Subject: ARM: mach-shmobile: armadillo800eva: Enable power button as wakeup
- source
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Simon Horman <horms@verge.net.au>
-(cherry picked from commit 5c1d2d16772e2d7d4e2e8da99a92d6f50b9102f0)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
-index a002504..65cb793 100644
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -520,10 +520,11 @@ static struct platform_device hdmi_lcdc_device = {
- };
-
- /* GPIO KEY */
--#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
-+#define GPIO_KEY(c, g, d, ...) \
-+ { .code = c, .gpio = g, .desc = d, .active_low = 1, __VA_ARGS__ }
-
- static struct gpio_keys_button gpio_buttons[] = {
-- GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW3"),
-+ GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW3", .wakeup = 1),
- GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW4"),
- GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW5"),
- GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW6"),
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 1b5f7629ee098b784f2b8e2ee49d03d90e01f811 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Sun, 2 Sep 2012 23:06:52 -0700
-Subject: ARM: shmobile: armadillo800eva: enable rw rootfs mount
-
-armadillo800eva default boot loader is "hermit",
-and it's tag->u.core.flags has flag when kernel boots.
-Because of this, ${LINUX}/arch/arm/kernel/setup.c :: parse_tag_core()
-didn't remove MS_RDONLY flag from root_mountflags.
-Thus, the rootfs is mounted as "readonly".
-This patch adds "rw" kernel parameter,
-and enable read/write mounts for rootfs
-
-Cc: Masahiro Nakai <nakai@atmark-techno.com>
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Simon Horman <horms@verge.net.au>
-(cherry picked from commit 28e515878f8896b33c325ff9767cb0237210fb4c)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/configs/armadillo800eva_defconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
-index 7d87184..90610c7 100644
---- a/arch/arm/configs/armadillo800eva_defconfig
-+++ b/arch/arm/configs/armadillo800eva_defconfig
-@@ -33,7 +33,7 @@ CONFIG_AEABI=y
- CONFIG_FORCE_MAX_ZONEORDER=13
- CONFIG_ZBOOT_ROM_TEXT=0x0
- CONFIG_ZBOOT_ROM_BSS=0x0
--CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096"
-+CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096 rw"
- CONFIG_CMDLINE_FORCE=y
- CONFIG_KEXEC=y
- CONFIG_VFP=y
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Jan 14 21:42:16 2013
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Tue, 15 Jan 2013 14:41:36 +0900
-Subject: armadillo800eva: defconfig: Enable drivers used with multimedia
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Message-ID: <1358228496-29613-3-git-send-email-dhobsong@igel.co.jp>
-
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/configs/armadillo800eva_defconfig | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/arch/arm/configs/armadillo800eva_defconfig
-+++ b/arch/arm/configs/armadillo800eva_defconfig
-@@ -37,6 +37,7 @@ CONFIG_CMDLINE="console=tty0 console=tty
- CONFIG_CMDLINE_FORCE=y
- CONFIG_KEXEC=y
- CONFIG_VFP=y
-+CONFIG_CMA=y
- # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
- # CONFIG_SUSPEND is not set
- CONFIG_NET=y
-@@ -45,6 +46,7 @@ CONFIG_UNIX=y
- CONFIG_INET=y
- CONFIG_IP_PNP=y
- CONFIG_IP_PNP_DHCP=y
-+CONFIG_SHMOBILE_PMB=y
- # CONFIG_INET_XFRM_MODE_TRANSPORT is not set
- # CONFIG_INET_XFRM_MODE_TUNNEL is not set
- # CONFIG_INET_XFRM_MODE_BEET is not set
-@@ -99,6 +101,7 @@ CONFIG_VIDEO_SH_MOBILE_CEU=y
- # CONFIG_RADIO_ADAPTERS is not set
- CONFIG_FB=y
- CONFIG_FB_SH_MOBILE_LCDC=y
-+CONFIG_FB_SH_MOBILE_MERAM=y
- CONFIG_FB_SH_MOBILE_HDMI=y
- CONFIG_LCD_CLASS_DEVICE=y
- CONFIG_FRAMEBUFFER_CONSOLE=y
-@@ -124,6 +127,7 @@ CONFIG_DMADEVICES=y
- CONFIG_SH_DMAE=y
- CONFIG_UIO=y
- CONFIG_UIO_PDRV_GENIRQ=y
-+CONFIG_UIO_DMEM_GENIRQ=y
- # CONFIG_DNOTIFY is not set
- CONFIG_MSDOS_FS=y
- CONFIG_VFAT_FS=y
+++ /dev/null
-From horms@vergenet.net Mon Dec 3 20:53:02 2012
-From: Simon Horman <horms+renesas@verge.net.au>
-Date: Tue, 4 Dec 2012 13:52:51 +0900
-Subject: [PATCH 2/2] ASoC: sh: fsi: select simple-card on Kconfig
-To: ltsi-dev@lists.linuxfoundation.org
-Cc: Greg KH <gregkh@linuxfoundation.org>
-Message-ID: <1354596771-7290-3-git-send-email-horms+renesas@verge.net.au>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-Current SuperH FSI require simple-card driver as sound card.
-This patch select it on Kconfig when FSI was selected.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit cd04461e2f491c81d30fb3b234cf43db3f098103)
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- sound/soc/sh/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
-index c9fdf63..6bcb116 100644
---- a/sound/soc/sh/Kconfig
-+++ b/sound/soc/sh/Kconfig
-@@ -22,6 +22,7 @@ config SND_SOC_SH4_SSI
-
- config SND_SOC_SH4_FSI
- tristate "SH4 FSI support"
-+ select SND_SIMPLE_CARD
- help
- This option enables FSI sound support
-
---
-1.7.10.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Wed Nov 21 23:30:36 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Thu, 22 Nov 2012 16:28:26 +0900
-Subject: [PATCH 3/7] iommu/shmobile: Add iommu driver for Renesas IPMMU modules
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Hideki EIRAKU <hdk@igel.co.jp>
-Message-ID: <1353569310-16564-4-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Hideki EIRAKU <hdk@igel.co.jp>
-
-This is the Renesas IPMMU driver and IOMMU API implementation.
-
-The IPMMU module supports the MMU function and the PMB function. The
-MMU function provides address translation by pagetable compatible with
-ARMv6. The PMB function provides address translation including
-tile-linear translation. This patch implements the MMU function.
-
-The iommu driver does not register a platform driver directly because:
-- the register space of the MMU function and the PMB function
- have a common register (used for settings flush), so they should ideally
- have a way to appropriately share this register.
-- the MMU function uses the IOMMU API while the PMB function does not.
-- the two functions may be used independently.
-
-Signed-off-by: Hideki EIRAKU <hdk@igel.co.jp>
----
- arch/arm/mach-shmobile/Kconfig | 6
- arch/arm/mach-shmobile/Makefile | 3
- arch/arm/mach-shmobile/include/mach/ipmmu.h | 16 +
- arch/arm/mach-shmobile/ipmmu.c | 150 +++++++++++
- drivers/iommu/Kconfig | 56 ++++
- drivers/iommu/Makefile | 1
- drivers/iommu/shmobile-iommu.c | 352 ++++++++++++++++++++++++++++
- 7 files changed, 584 insertions(+)
- create mode 100644 arch/arm/mach-shmobile/include/mach/ipmmu.h
- create mode 100644 arch/arm/mach-shmobile/ipmmu.c
- create mode 100644 drivers/iommu/shmobile-iommu.c
-
---- a/arch/arm/mach-shmobile/Kconfig
-+++ b/arch/arm/mach-shmobile/Kconfig
-@@ -175,6 +175,12 @@ endmenu
- config SH_CLK_CPG
- bool
-
-+config SHMOBILE_IPMMU
-+ bool
-+
-+config SHMOBILE_IPMMU_TLB
-+ bool
-+
- source "drivers/sh/Kconfig"
-
- endif
---- a/arch/arm/mach-shmobile/Makefile
-+++ b/arch/arm/mach-shmobile/Makefile
-@@ -56,3 +56,6 @@ obj-$(CONFIG_MACH_ARMADILLO800EVA) += bo
- # Framework support
- obj-$(CONFIG_SMP) += $(smp-y)
- obj-$(CONFIG_GENERIC_GPIO) += $(pfc-y)
-+
-+# IPMMU/IPMMUI
-+obj-$(CONFIG_SHMOBILE_IPMMU) += ipmmu.o
---- /dev/null
-+++ b/arch/arm/mach-shmobile/include/mach/ipmmu.h
-@@ -0,0 +1,16 @@
-+#ifdef CONFIG_SHMOBILE_IPMMU_TLB
-+void ipmmu_tlb_flush(struct device *ipmmu_dev);
-+void ipmmu_tlb_set(struct device *ipmmu_dev, unsigned long phys, int size,
-+ int asid);
-+void ipmmu_add_device(struct device *dev);
-+int ipmmu_iommu_init(struct device *dev);
-+#else
-+static inline void ipmmu_add_device(struct device *dev)
-+{
-+}
-+
-+static int ipmmu_iommu_init(struct device *dev)
-+{
-+ return -EINVAL;
-+}
-+#endif
---- /dev/null
-+++ b/arch/arm/mach-shmobile/ipmmu.c
-@@ -0,0 +1,150 @@
-+/*
-+ * IPMMU/IPMMUI
-+ * Copyright (C) 2012 Hideki EIRAKU
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; version 2 of the License.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ */
-+
-+#include <linux/platform_device.h>
-+#include <linux/io.h>
-+#include <linux/err.h>
-+#include <linux/export.h>
-+#include <linux/slab.h>
-+#include <mach/ipmmu.h>
-+
-+#define IMCTR1 0x000
-+#define IMCTR2 0x004
-+#define IMASID 0x010
-+#define IMTTBR 0x014
-+#define IMTTBCR 0x018
-+
-+#define IMCTR1_TLBEN (1 << 0)
-+#define IMCTR1_FLUSH (1 << 1)
-+
-+struct ipmmu_priv {
-+ void __iomem *ipmmu_base;
-+ int tlb_enabled;
-+ struct mutex flush_lock;
-+};
-+
-+static void ipmmu_reg_write(struct ipmmu_priv *priv, unsigned long reg_off,
-+ unsigned long data)
-+{
-+ iowrite32(data, priv->ipmmu_base + reg_off);
-+}
-+
-+void ipmmu_tlb_flush(struct device *dev)
-+{
-+ struct ipmmu_priv *priv;
-+
-+ if (!dev)
-+ return;
-+ priv = dev_get_drvdata(dev);
-+ mutex_lock(&priv->flush_lock);
-+ if (priv->tlb_enabled)
-+ ipmmu_reg_write(priv, IMCTR1, IMCTR1_FLUSH | IMCTR1_TLBEN);
-+ else
-+ ipmmu_reg_write(priv, IMCTR1, IMCTR1_FLUSH);
-+ mutex_unlock(&priv->flush_lock);
-+}
-+
-+void ipmmu_tlb_set(struct device *dev, unsigned long phys, int size, int asid)
-+{
-+ struct ipmmu_priv *priv;
-+
-+ if (!dev)
-+ return;
-+ priv = dev_get_drvdata(dev);
-+ mutex_lock(&priv->flush_lock);
-+ switch (size) {
-+ default:
-+ priv->tlb_enabled = 0;
-+ break;
-+ case 0x2000:
-+ ipmmu_reg_write(priv, IMTTBCR, 1);
-+ priv->tlb_enabled = 1;
-+ break;
-+ case 0x1000:
-+ ipmmu_reg_write(priv, IMTTBCR, 2);
-+ priv->tlb_enabled = 1;
-+ break;
-+ case 0x800:
-+ ipmmu_reg_write(priv, IMTTBCR, 3);
-+ priv->tlb_enabled = 1;
-+ break;
-+ case 0x400:
-+ ipmmu_reg_write(priv, IMTTBCR, 4);
-+ priv->tlb_enabled = 1;
-+ break;
-+ case 0x200:
-+ ipmmu_reg_write(priv, IMTTBCR, 5);
-+ priv->tlb_enabled = 1;
-+ break;
-+ case 0x100:
-+ ipmmu_reg_write(priv, IMTTBCR, 6);
-+ priv->tlb_enabled = 1;
-+ break;
-+ case 0x80:
-+ ipmmu_reg_write(priv, IMTTBCR, 7);
-+ priv->tlb_enabled = 1;
-+ break;
-+ }
-+ ipmmu_reg_write(priv, IMTTBR, phys);
-+ ipmmu_reg_write(priv, IMASID, asid);
-+ mutex_unlock(&priv->flush_lock);
-+}
-+
-+static int __devinit ipmmu_probe(struct platform_device *pdev)
-+{
-+ struct resource *res;
-+ struct ipmmu_priv *priv;
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!res) {
-+ dev_err(&pdev->dev, "cannot get platform resources\n");
-+ return -ENOENT;
-+ }
-+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-+ if (!priv) {
-+ dev_err(&pdev->dev, "cannot allocate device data\n");
-+ return -ENOMEM;
-+ }
-+ mutex_init(&priv->flush_lock);
-+ priv->ipmmu_base = ioremap_nocache(res->start, resource_size(res));
-+ if (!priv->ipmmu_base) {
-+ dev_err(&pdev->dev, "ioremap_nocache failed\n");
-+ kfree(priv);
-+ return -ENOMEM;
-+ }
-+ platform_set_drvdata(pdev, priv);
-+ ipmmu_reg_write(priv, IMCTR1, 0x0); /* disable TLB */
-+ ipmmu_reg_write(priv, IMCTR2, 0x0); /* disable PMB */
-+ ipmmu_iommu_init(&pdev->dev);
-+ return 0;
-+}
-+
-+static struct platform_driver ipmmu_driver = {
-+ .probe = ipmmu_probe,
-+ .driver = {
-+ .owner = THIS_MODULE,
-+ .name = "ipmmu",
-+ },
-+};
-+
-+static int __init ipmmu_init(void)
-+{
-+ return platform_driver_register(&ipmmu_driver);
-+}
-+subsys_initcall(ipmmu_init);
---- a/drivers/iommu/Kconfig
-+++ b/drivers/iommu/Kconfig
-@@ -162,4 +162,60 @@ config TEGRA_IOMMU_SMMU
- space through the SMMU (System Memory Management Unit)
- hardware included on Tegra SoCs.
-
-+config SHMOBILE_IOMMU
-+ bool "IOMMU for Renesas IPMMU/IPMMUI"
-+ default n
-+ select IOMMU_API
-+ select ARM_DMA_USE_IOMMU
-+ select SHMOBILE_IPMMU
-+ select SHMOBILE_IPMMU_TLB
-+
-+choice
-+ prompt "IPMMU/IPMMUI address space size"
-+ default SHMOBILE_IOMMU_ADDRSIZE_2048MB
-+ depends on SHMOBILE_IOMMU
-+ help
-+ This option sets IPMMU/IPMMUI address space size by
-+ adjusting the 1st level page table size. The page table size
-+ is calculated as follows:
-+
-+ page table size = number of page table entries * 4 bytes
-+ number of page table entries = address space size / 1 MiB
-+
-+ For example, when the address space size is 2048 MiB, the
-+ 1st level page table size is 8192 bytes.
-+
-+ config SHMOBILE_IOMMU_ADDRSIZE_2048MB
-+ bool "2 GiB"
-+
-+ config SHMOBILE_IOMMU_ADDRSIZE_1024MB
-+ bool "1 GiB"
-+
-+ config SHMOBILE_IOMMU_ADDRSIZE_512MB
-+ bool "512 MiB"
-+
-+ config SHMOBILE_IOMMU_ADDRSIZE_256MB
-+ bool "256 MiB"
-+
-+ config SHMOBILE_IOMMU_ADDRSIZE_128MB
-+ bool "128 MiB"
-+
-+ config SHMOBILE_IOMMU_ADDRSIZE_64MB
-+ bool "64 MiB"
-+
-+ config SHMOBILE_IOMMU_ADDRSIZE_32MB
-+ bool "32 MiB"
-+
-+endchoice
-+
-+config SHMOBILE_IOMMU_L1SIZE
-+ int
-+ default 8192 if SHMOBILE_IOMMU_ADDRSIZE_2048MB
-+ default 4096 if SHMOBILE_IOMMU_ADDRSIZE_1024MB
-+ default 2048 if SHMOBILE_IOMMU_ADDRSIZE_512MB
-+ default 1024 if SHMOBILE_IOMMU_ADDRSIZE_256MB
-+ default 512 if SHMOBILE_IOMMU_ADDRSIZE_128MB
-+ default 256 if SHMOBILE_IOMMU_ADDRSIZE_64MB
-+ default 128 if SHMOBILE_IOMMU_ADDRSIZE_32MB
-+
- endif # IOMMU_SUPPORT
---- a/drivers/iommu/Makefile
-+++ b/drivers/iommu/Makefile
-@@ -10,3 +10,4 @@ obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o
- obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
- obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o
- obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o
-+obj-$(CONFIG_SHMOBILE_IOMMU) += shmobile-iommu.o
---- /dev/null
-+++ b/drivers/iommu/shmobile-iommu.c
-@@ -0,0 +1,352 @@
-+/*
-+ * IOMMU for IPMMU/IPMMUI
-+ * Copyright (C) 2012 Hideki EIRAKU
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; version 2 of the License.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ */
-+
-+#include <linux/io.h>
-+#include <linux/dmapool.h>
-+#include <linux/slab.h>
-+#include <linux/platform_device.h>
-+#include <linux/iommu.h>
-+#include <linux/dma-mapping.h>
-+#include <mach/ipmmu.h>
-+#include <asm/dma-iommu.h>
-+
-+#define L1_SIZE CONFIG_SHMOBILE_IOMMU_L1SIZE
-+#define L1_LEN (L1_SIZE / 4)
-+#define L1_ALIGN L1_SIZE
-+#define L2_SIZE 0x400
-+#define L2_LEN (L2_SIZE / 4)
-+#define L2_ALIGN L2_SIZE
-+
-+struct shmobile_iommu_priv_pgtable {
-+ uint32_t *pgtable;
-+ dma_addr_t handle;
-+};
-+
-+struct shmobile_iommu_priv {
-+ struct shmobile_iommu_priv_pgtable l1, l2[L1_LEN];
-+ spinlock_t map_lock;
-+ atomic_t active;
-+};
-+
-+static struct dma_iommu_mapping *iommu_mapping;
-+static struct device *ipmmu_devices;
-+static struct dma_pool *l1pool, *l2pool;
-+static spinlock_t lock;
-+static DEFINE_SPINLOCK(lock_add);
-+static struct shmobile_iommu_priv *attached;
-+static int num_attached_devices;
-+static struct device *ipmmu_access_device;
-+
-+static int shmobile_iommu_domain_init(struct iommu_domain *domain)
-+{
-+ struct shmobile_iommu_priv *priv;
-+ int i;
-+
-+ priv = kmalloc(sizeof(*priv), GFP_KERNEL);
-+ if (!priv)
-+ return -ENOMEM;
-+ priv->l1.pgtable = dma_pool_alloc(l1pool, GFP_KERNEL,
-+ &priv->l1.handle);
-+ if (!priv->l1.pgtable) {
-+ kfree(priv);
-+ return -ENOMEM;
-+ }
-+ for (i = 0; i < L1_LEN; i++)
-+ priv->l2[i].pgtable = NULL;
-+ memset(priv->l1.pgtable, 0, L1_SIZE);
-+ spin_lock_init(&priv->map_lock);
-+ atomic_set(&priv->active, 0);
-+ domain->priv = priv;
-+ return 0;
-+}
-+
-+static void shmobile_iommu_domain_destroy(struct iommu_domain *domain)
-+{
-+ struct shmobile_iommu_priv *priv = domain->priv;
-+ int i;
-+
-+ for (i = 0; i < L1_LEN; i++) {
-+ if (priv->l2[i].pgtable)
-+ dma_pool_free(l2pool, priv->l2[i].pgtable,
-+ priv->l2[i].handle);
-+ }
-+ dma_pool_free(l1pool, priv->l1.pgtable, priv->l1.handle);
-+ kfree(priv);
-+ domain->priv = NULL;
-+}
-+
-+static int shmobile_iommu_attach_device(struct iommu_domain *domain,
-+ struct device *dev)
-+{
-+ struct shmobile_iommu_priv *priv = domain->priv;
-+ int ret = -EBUSY;
-+
-+ spin_lock(&lock);
-+ if (attached != priv) {
-+ if (attached)
-+ goto err;
-+ atomic_set(&priv->active, 1);
-+ ipmmu_tlb_set(ipmmu_access_device, priv->l1.handle, L1_SIZE,
-+ 0);
-+ wmb();
-+ ipmmu_tlb_flush(ipmmu_access_device);
-+ attached = priv;
-+ num_attached_devices = 0;
-+ }
-+ num_attached_devices++;
-+ ret = 0;
-+err:
-+ spin_unlock(&lock);
-+ return ret;
-+}
-+
-+static void shmobile_iommu_detach_device(struct iommu_domain *domain,
-+ struct device *dev)
-+{
-+ struct shmobile_iommu_priv *priv = domain->priv;
-+
-+ spin_lock(&lock);
-+ atomic_set(&priv->active, 0);
-+ num_attached_devices--;
-+ if (!num_attached_devices) {
-+ ipmmu_tlb_set(ipmmu_access_device, 0, 0, 0);
-+ ipmmu_tlb_flush(ipmmu_access_device);
-+ attached = NULL;
-+ }
-+ spin_unlock(&lock);
-+}
-+
-+static int
-+l2alloc(struct shmobile_iommu_priv *priv, unsigned int l1index)
-+{
-+ if (!priv->l2[l1index].pgtable) {
-+ priv->l2[l1index].pgtable = dma_pool_alloc(l2pool, GFP_KERNEL,
-+ &priv->l2[l1index].handle);
-+ if (!priv->l2[l1index].pgtable)
-+ return -ENOMEM;
-+ memset(priv->l2[l1index].pgtable, 0, L2_SIZE);
-+ }
-+ priv->l1.pgtable[l1index] = priv->l2[l1index].handle | 0x1;
-+ return 0;
-+}
-+
-+static void
-+l2realfree(struct shmobile_iommu_priv_pgtable *l2)
-+{
-+ if (l2->pgtable)
-+ dma_pool_free(l2pool, l2->pgtable, l2->handle);
-+}
-+
-+static int
-+l2free(struct shmobile_iommu_priv *priv, unsigned int l1index,
-+ struct shmobile_iommu_priv_pgtable *l2)
-+{
-+ priv->l1.pgtable[l1index] = 0;
-+ if (priv->l2[l1index].pgtable) {
-+ *l2 = priv->l2[l1index];
-+ priv->l2[l1index].pgtable = NULL;
-+ }
-+ return 0;
-+}
-+
-+static int shmobile_iommu_map(struct iommu_domain *domain, unsigned long iova,
-+ phys_addr_t paddr, size_t size, int prot)
-+{
-+ struct shmobile_iommu_priv_pgtable l2 = { .pgtable = NULL };
-+ struct shmobile_iommu_priv *priv = domain->priv;
-+ unsigned int l1index, l2index, i;
-+ int ret;
-+
-+ l1index = iova >> 20;
-+ switch (size) {
-+ case 0x1000:
-+ l2index = (iova >> 12) & 0xff;
-+ spin_lock(&priv->map_lock);
-+ ret = l2alloc(priv, l1index);
-+ if (!ret)
-+ priv->l2[l1index].pgtable[l2index] = paddr | 0xff2;
-+ spin_unlock(&priv->map_lock);
-+ break;
-+ case 0x10000:
-+ l2index = (iova >> 12) & 0xf0;
-+ spin_lock(&priv->map_lock);
-+ ret = l2alloc(priv, l1index);
-+ if (!ret) {
-+ for (i = 0; i < 0x10; i++)
-+ priv->l2[l1index].pgtable[l2index + i] =
-+ paddr | 0xff1;
-+ }
-+ spin_unlock(&priv->map_lock);
-+ break;
-+ case 0x100000:
-+ spin_lock(&priv->map_lock);
-+ l2free(priv, l1index, &l2);
-+ priv->l1.pgtable[l1index] = paddr | 0xc02;
-+ spin_unlock(&priv->map_lock);
-+ ret = 0;
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ }
-+ if (!ret && atomic_read(&priv->active)) {
-+ wmb();
-+ ipmmu_tlb_flush(ipmmu_access_device);
-+ l2realfree(&l2);
-+ }
-+ return ret;
-+}
-+
-+static size_t shmobile_iommu_unmap(struct iommu_domain *domain,
-+ unsigned long iova, size_t size)
-+{
-+ struct shmobile_iommu_priv_pgtable l2 = { .pgtable = NULL };
-+ struct shmobile_iommu_priv *priv = domain->priv;
-+ unsigned int l1index, l2index, i;
-+ uint32_t l2entry = 0;
-+ size_t ret = 0;
-+
-+ l1index = iova >> 20;
-+ if (!(iova & 0xFFFFF) && size >= 0x100000) {
-+ spin_lock(&priv->map_lock);
-+ l2free(priv, l1index, &l2);
-+ spin_unlock(&priv->map_lock);
-+ ret = 0x100000;
-+ goto done;
-+ }
-+ l2index = (iova >> 12) & 0xff;
-+ spin_lock(&priv->map_lock);
-+ if (priv->l2[l1index].pgtable)
-+ l2entry = priv->l2[l1index].pgtable[l2index];
-+ switch (l2entry & 3) {
-+ case 1:
-+ if (l2index & 0xf)
-+ break;
-+ for (i = 0; i < 0x10; i++)
-+ priv->l2[l1index].pgtable[l2index + i] = 0;
-+ ret = 0x10000;
-+ break;
-+ case 2:
-+ priv->l2[l1index].pgtable[l2index] = 0;
-+ ret = 0x1000;
-+ break;
-+ }
-+ spin_unlock(&priv->map_lock);
-+done:
-+ if (ret && atomic_read(&priv->active)) {
-+ wmb();
-+ ipmmu_tlb_flush(ipmmu_access_device);
-+ l2realfree(&l2);
-+ }
-+ return ret;
-+}
-+
-+static phys_addr_t shmobile_iommu_iova_to_phys(struct iommu_domain *domain,
-+ unsigned long iova)
-+{
-+ struct shmobile_iommu_priv *priv = domain->priv;
-+ uint32_t l1entry = 0, l2entry = 0;
-+ unsigned int l1index, l2index;
-+
-+ l1index = iova >> 20;
-+ l2index = (iova >> 12) & 0xff;
-+ spin_lock(&priv->map_lock);
-+ if (priv->l2[l1index].pgtable)
-+ l2entry = priv->l2[l1index].pgtable[l2index];
-+ else
-+ l1entry = priv->l1.pgtable[l1index];
-+ spin_unlock(&priv->map_lock);
-+ switch (l2entry & 3) {
-+ case 1:
-+ return (l2entry & ~0xffff) | (iova & 0xffff);
-+ case 2:
-+ return (l2entry & ~0xfff) | (iova & 0xfff);
-+ default:
-+ if ((l1entry & 3) == 2)
-+ return (l1entry & ~0xfffff) | (iova & 0xfffff);
-+ return 0;
-+ }
-+}
-+
-+static struct iommu_ops shmobile_iommu_ops = {
-+ .domain_init = shmobile_iommu_domain_init,
-+ .domain_destroy = shmobile_iommu_domain_destroy,
-+ .attach_dev = shmobile_iommu_attach_device,
-+ .detach_dev = shmobile_iommu_detach_device,
-+ .map = shmobile_iommu_map,
-+ .unmap = shmobile_iommu_unmap,
-+ .iova_to_phys = shmobile_iommu_iova_to_phys,
-+ .pgsize_bitmap = 0x111000,
-+};
-+
-+static int shmobile_iommu_attach_all_devices(void)
-+{
-+ struct device *dev;
-+ int ret = 0;
-+
-+ spin_lock(&lock_add);
-+ iommu_mapping = arm_iommu_create_mapping(&platform_bus_type, 0x0,
-+ L1_LEN << 20, 0);
-+ if (IS_ERR_OR_NULL(iommu_mapping)) {
-+ ret = PTR_ERR(iommu_mapping);
-+ goto err;
-+ }
-+ for (dev = ipmmu_devices; dev; dev = dev->archdata.iommu) {
-+ if (arm_iommu_attach_device(dev, iommu_mapping))
-+ pr_err("arm_iommu_attach_device failed\n");
-+ }
-+err:
-+ spin_unlock(&lock_add);
-+ return 0;
-+}
-+
-+void ipmmu_add_device(struct device *dev)
-+{
-+ spin_lock(&lock_add);
-+ dev->archdata.iommu = ipmmu_devices;
-+ ipmmu_devices = dev;
-+ if (!IS_ERR_OR_NULL(iommu_mapping)) {
-+ if (arm_iommu_attach_device(dev, iommu_mapping))
-+ pr_err("arm_iommu_attach_device failed\n");
-+ }
-+ spin_unlock(&lock_add);
-+}
-+
-+int ipmmu_iommu_init(struct device *dev)
-+{
-+ dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
-+ l1pool = dma_pool_create("shmobile-iommu-pgtable1", dev,
-+ L1_SIZE, L1_ALIGN, 0);
-+ if (!l1pool)
-+ goto nomem_pool1;
-+ l2pool = dma_pool_create("shmobile-iommu-pgtable2", dev,
-+ L2_SIZE, L2_ALIGN, 0);
-+ if (!l2pool)
-+ goto nomem_pool2;
-+ spin_lock_init(&lock);
-+ attached = NULL;
-+ ipmmu_access_device = dev;
-+ bus_set_iommu(&platform_bus_type, &shmobile_iommu_ops);
-+ if (shmobile_iommu_attach_all_devices())
-+ pr_err("shmobile_iommu_attach_all_devices failed\n");
-+ return 0;
-+nomem_pool2:
-+ dma_pool_destroy(l1pool);
-+nomem_pool1:
-+ return -ENOMEM;
-+}
+++ /dev/null
-From dhobsong@igel.co.jp Wed Nov 21 23:30:38 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Thu, 22 Nov 2012 16:28:27 +0900
-Subject: [PATCH 4/7] shmobile: armadillo800eva enable IOMMU support
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Message-ID: <1353569310-16564-5-git-send-email-dhobsong@igel.co.jp>
-
-
-Add the IPMMU device and register the LCDC, VPU, and VIO devices to allocate
-DMA memory via the IPMMU.
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 3 +++
- arch/arm/mach-shmobile/setup-r8a7740.c | 23 +++++++++++++++++++++++
- 2 files changed, 26 insertions(+)
-
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -40,6 +40,7 @@
- #include <mach/common.h>
- #include <mach/irqs.h>
- #include <mach/r8a7740.h>
-+#include <mach/ipmmu.h>
- #include <media/mt9t112.h>
- #include <media/sh_mobile_ceu.h>
- #include <media/soc_camera.h>
-@@ -1177,6 +1178,8 @@ static void __init eva_init(void)
-
- r8a7740_add_standard_devices();
-
-+ ipmmu_add_device(&lcdc0_device.dev);
-+
- platform_add_devices(eva_devices,
- ARRAY_SIZE(eva_devices));
-
---- a/arch/arm/mach-shmobile/setup-r8a7740.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
-@@ -35,6 +35,7 @@
- #include <mach/r8a7740.h>
- #include <mach/pm-rmobile.h>
- #include <mach/common.h>
-+#include <mach/ipmmu.h>
- #include <mach/irqs.h>
- #include <asm/mach-types.h>
- #include <asm/mach/map.h>
-@@ -359,6 +360,23 @@ static struct platform_device cmt10_devi
- .num_resources = ARRAY_SIZE(cmt10_resources),
- };
-
-+/* IPMMUI (an IPMMU module for ICB/LMB) */
-+static struct resource ipmmu_resources[] = {
-+ [0] = {
-+ .name = "IPMMUI",
-+ .start = 0xfe951000,
-+ .end = 0xfe9510ff,
-+ .flags = IORESOURCE_MEM,
-+ },
-+};
-+
-+static struct platform_device ipmmu_device = {
-+ .name = "ipmmu",
-+ .id = -1,
-+ .resource = ipmmu_resources,
-+ .num_resources = ARRAY_SIZE(ipmmu_resources),
-+};
-+
- static struct platform_device *r8a7740_early_devices[] __initdata = {
- &scif0_device,
- &scif1_device,
-@@ -373,6 +391,7 @@ static struct platform_device *r8a7740_e
- &vpu_device,
- &vpc_device,
- &vio_device,
-+ &ipmmu_device,
-
- };
-
-@@ -778,6 +797,10 @@ void __init r8a7740_add_standard_devices
- /* add devices */
- platform_add_devices(r8a7740_early_devices,
- ARRAY_SIZE(r8a7740_early_devices));
-+
-+ ipmmu_add_device(&vpu_device.dev);
-+ ipmmu_add_device(&vio_device.dev);
-+
- platform_add_devices(r8a7740_late_devices,
- ARRAY_SIZE(r8a7740_late_devices));
-
+++ /dev/null
-From dhobsong@igel.co.jp Wed Nov 21 23:30:33 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Thu, 22 Nov 2012 16:28:25 +0900
-Subject: [PATCH 2/7] shmobile: armadillo800eva: Set LCD color depth to 32 bpp
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Message-ID: <1353569310-16564-3-git-send-email-dhobsong@igel.co.jp>
-
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -385,7 +385,7 @@ static struct sh_mobile_lcdc_info lcdc0_
- .clock_source = LCDC_CLK_BUS,
- .ch[0] = {
- .chan = LCDC_CHAN_MAINLCD,
-- .fourcc = V4L2_PIX_FMT_RGB565,
-+ .fourcc = V4L2_PIX_FMT_BGR32,
- .interface_type = RGB24,
- .clock_divider = 5,
- .flags = 0,
+++ /dev/null
-From dhobsong@igel.co.jp Mon Jan 14 21:42:10 2013
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Tue, 15 Jan 2013 14:41:35 +0900
-Subject: shmobile/iommu: Only enable driver on ARM based shmobile configuration
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Message-ID: <1358228496-29613-2-git-send-email-dhobsong@igel.co.jp>
-Status: RO
-Content-Length: 622
-Lines: 23
-
-
-Make sure that the shmobile IOMMU driver cannot be inadvertently enabled
-on other platforms.
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- drivers/iommu/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/iommu/Kconfig
-+++ b/drivers/iommu/Kconfig
-@@ -165,6 +165,7 @@ config TEGRA_IOMMU_SMMU
- config SHMOBILE_IOMMU
- bool "IOMMU for Renesas IPMMU/IPMMUI"
- default n
-+ depends on (ARM && ARCH_SHMOBILE)
- select IOMMU_API
- select ARM_DMA_USE_IOMMU
- select SHMOBILE_IPMMU
+++ /dev/null
-From dhobsong@igel.co.jp Wed Nov 21 23:30:40 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Thu, 22 Nov 2012 16:28:28 +0900
-Subject: [PATCH 5/7] shmobile: ipmmu: Add basic PMB support
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Message-ID: <1353569310-16564-6-git-send-email-dhobsong@igel.co.jp>
-
-
-Currently only the userspace API via character device is supported.
-All register access and hardware dependent functionality is
-provided by the IPMMU driver, which is shared with the IOMMU/TLB API.
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mach-shmobile/Kconfig | 7
- arch/arm/mach-shmobile/Makefile | 1
- arch/arm/mach-shmobile/include/mach/ipmmu.h | 34 +++
- arch/arm/mach-shmobile/ipmmu-pmb.c | 269 ++++++++++++++++++++++++++++
- arch/arm/mach-shmobile/ipmmu.c | 236 +++++++++++++++++++++++-
- include/linux/ipmmu.h | 29 +++
- 6 files changed, 565 insertions(+), 11 deletions(-)
- create mode 100644 arch/arm/mach-shmobile/ipmmu-pmb.c
- create mode 100644 include/linux/ipmmu.h
-
---- a/arch/arm/mach-shmobile/Kconfig
-+++ b/arch/arm/mach-shmobile/Kconfig
-@@ -181,6 +181,13 @@ config SHMOBILE_IPMMU
- config SHMOBILE_IPMMU_TLB
- bool
-
-+config SHMOBILE_PMB
-+ bool "IPMMU PMB driver"
-+ default n
-+ select SHMOBILE_IPMMU
-+ help
-+ This enables build of the IPMMU PMB driver.
-+
- source "drivers/sh/Kconfig"
-
- endif
---- a/arch/arm/mach-shmobile/Makefile
-+++ b/arch/arm/mach-shmobile/Makefile
-@@ -59,3 +59,4 @@ obj-$(CONFIG_GENERIC_GPIO) += $(pfc-y)
-
- # IPMMU/IPMMUI
- obj-$(CONFIG_SHMOBILE_IPMMU) += ipmmu.o
-+obj-$(CONFIG_SHMOBILE_PMB) += ipmmu-pmb.o
---- a/arch/arm/mach-shmobile/include/mach/ipmmu.h
-+++ b/arch/arm/mach-shmobile/include/mach/ipmmu.h
-@@ -1,5 +1,12 @@
--#ifdef CONFIG_SHMOBILE_IPMMU_TLB
-+#include <linux/ipmmu.h>
-+#ifndef __SHMOBILE_IPMMU_H__
-+#define __SHMOBILE_IPMMU_H__
-+
-+#ifdef CONFIG_SHMOBILE_IPMMU
- void ipmmu_tlb_flush(struct device *ipmmu_dev);
-+#endif
-+
-+#ifdef CONFIG_SHMOBILE_IPMMU_TLB
- void ipmmu_tlb_set(struct device *ipmmu_dev, unsigned long phys, int size,
- int asid);
- void ipmmu_add_device(struct device *dev);
-@@ -9,8 +16,31 @@ static inline void ipmmu_add_device(stru
- {
- }
-
--static int ipmmu_iommu_init(struct device *dev)
-+static inline int ipmmu_iommu_init(struct device *dev)
- {
- return -EINVAL;
- }
- #endif
-+#ifdef CONFIG_SHMOBILE_PMB
-+/* Access functions used by PMB device */
-+void handle_free(struct device *dev, unsigned long handle, int size_mb);
-+unsigned long handle_alloc(struct device *dev, int size_mb);
-+int ipmmu_pmb_set_addr(struct device *dev, int index, unsigned long addr,
-+ int enabled);
-+int ipmmu_pmb_set_data(struct device *dev, int index,
-+ struct ipmmu_pmb_info *info,
-+ struct pmb_tile_info *tile);
-+int ipmmu_pmb_enable(struct device *dev, int index);
-+/* PMB initialization */
-+void *ipmmu_pmb_init(struct device *dev);
-+void ipmmu_pmb_deinit(void *pmb_priv);
-+#else
-+static inline void *ipmmu_pmb_init(struct device *dev)
-+{
-+ return NULL;
-+}
-+static inline void ipmmu_pmb_deinit(void *pmb_priv)
-+{
-+}
-+#endif
-+#endif /* __SHMOBILE_IPMMU_H__ */
---- /dev/null
-+++ b/arch/arm/mach-shmobile/ipmmu-pmb.c
-@@ -0,0 +1,269 @@
-+/*
-+ * IPMMU-PMB driver
-+ * Copyright (C) 2012 Damian Hobson-Garcia
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; version 2 of the License.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ */
-+
-+#include <linux/platform_device.h>
-+#include <linux/io.h>
-+#include <linux/err.h>
-+#include <linux/export.h>
-+#include <linux/cdev.h>
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/ipmmu.h>
-+#include <mach/ipmmu.h>
-+#include <asm/uaccess.h>
-+
-+#define PMB_DEVICE_NAME "pmb"
-+
-+#define PMB_NR 16
-+struct ipmmu_pmb_data {
-+ struct ipmmu_pmb_priv *priv;
-+ struct ipmmu_pmb_info info;
-+ struct pmb_tile_info tile;
-+ unsigned long handle;
-+ int index;
-+};
-+
-+struct ipmmu_pmb_priv {
-+ struct cdev cdev;
-+ struct class *pmb_class;
-+ dev_t pmb_dev;
-+ unsigned long busy_pmbs;
-+ struct mutex pmb_lock;
-+ struct ipmmu_pmb_data pmbs[PMB_NR];
-+ struct device *ipmmu_dev;
-+ int pmb_enabled;
-+};
-+
-+struct ipmmu_pmb_priv *static_priv;
-+
-+static int set_pmb(struct ipmmu_pmb_data *data,
-+ struct ipmmu_pmb_info *info)
-+{
-+ struct ipmmu_pmb_priv *priv = data->priv;
-+ unsigned long data_mask;
-+ int err;
-+
-+ if (!info->enabled) {
-+ if (data->handle) {
-+ handle_free(priv->ipmmu_dev, data->handle,
-+ data->info.size_mb);
-+ data->handle = 0;
-+ }
-+ data->info = *info;
-+ ipmmu_pmb_set_data(priv->ipmmu_dev, data->index, NULL, NULL);
-+ ipmmu_pmb_set_addr(priv->ipmmu_dev, data->index, 0, 0);
-+ ipmmu_tlb_flush(priv->ipmmu_dev);
-+ return 0;
-+ }
-+
-+ if (data->info.enabled) {
-+ err = -EBUSY;
-+ goto err_out;
-+ }
-+
-+ data_mask = ~((info->size_mb) - 1);
-+
-+ if (info->paddr & ~(data_mask)) {
-+ err = -EINVAL;
-+ goto err_out;
-+ }
-+
-+ data->handle = handle_alloc(priv->ipmmu_dev, info->size_mb);
-+
-+ if (!data->handle) {
-+ err = -ENOMEM;
-+ goto err_out;
-+ }
-+
-+ data->info = *info;
-+
-+ ipmmu_pmb_set_addr(priv->ipmmu_dev, data->index, data->handle, 1);
-+ ipmmu_pmb_set_data(priv->ipmmu_dev, data->index, &data->info,
-+ &data->tile);
-+
-+ if (!data->priv->pmb_enabled) {
-+ ipmmu_pmb_enable(priv->ipmmu_dev, 1);
-+ data->priv->pmb_enabled = 1;
-+ }
-+
-+ ipmmu_tlb_flush(priv->ipmmu_dev);
-+
-+ return 0;
-+
-+err_out:
-+ info->enabled = 0;
-+ return err;
-+}
-+
-+static int set_tile(struct ipmmu_pmb_data *data,
-+ struct pmb_tile_info *tile)
-+{
-+ struct ipmmu_pmb_priv *priv = data->priv;
-+ data->tile = *tile;
-+ return ipmmu_pmb_set_data(priv->ipmmu_dev, data->index, &data->info,
-+ &data->tile);
-+}
-+
-+static int ipmmu_pmb_open(struct inode *inode, struct file *filp)
-+{
-+ struct ipmmu_pmb_priv *priv;
-+ int idx;
-+ priv = container_of(inode->i_cdev, struct ipmmu_pmb_priv,
-+ cdev);
-+
-+ mutex_lock(&priv->pmb_lock);
-+ idx = find_first_zero_bit(&priv->busy_pmbs, PMB_NR);
-+ if (idx == PMB_NR)
-+ return -EBUSY;
-+
-+ __set_bit(idx, &priv->busy_pmbs);
-+ mutex_unlock(&priv->pmb_lock);
-+ priv->pmbs[idx].index = idx;
-+ priv->pmbs[idx].priv = priv;
-+ filp->private_data = &priv->pmbs[idx];
-+ return 0;
-+}
-+
-+static int ipmmu_pmb_release(struct inode *inode, struct file *filp)
-+{
-+ struct ipmmu_pmb_data *pmb;
-+ pmb = filp->private_data;
-+ if (pmb->info.enabled) {
-+ pmb->info.enabled = 0;
-+ set_pmb(pmb, &pmb->info);
-+ }
-+
-+ mutex_lock(&pmb->priv->pmb_lock);
-+ __clear_bit(pmb->index, &pmb->priv->busy_pmbs);
-+ mutex_unlock(&pmb->priv->pmb_lock);
-+ return 0;
-+}
-+
-+static long ipmmu_pmb_ioctl(struct file *filp, unsigned int cmd_in,
-+ unsigned long arg)
-+{
-+ struct ipmmu_pmb_data *pmb;
-+ struct ipmmu_pmb_info user_set;
-+ struct pmb_tile_info user_tile;
-+ long ret = -EINVAL;
-+ pmb = filp->private_data;
-+ switch (cmd_in) {
-+ case IPMMU_GET_PMB:
-+ ret = copy_to_user((char *)arg, &pmb->info, sizeof(pmb->info));
-+ break;
-+ case IPMMU_SET_PMB:
-+ ret = copy_from_user(&user_set, (char *)arg, sizeof(user_set));
-+ if (ret)
-+ break;
-+ ret = set_pmb(pmb, &user_set);
-+ if (!ret)
-+ pmb->info = user_set;
-+ break;
-+ case IPMMU_GET_PMB_HANDLE:
-+ ret = copy_to_user((char *)arg, &pmb->handle,
-+ sizeof(pmb->handle));
-+ break;
-+ case IPMMU_GET_PMB_TL:
-+ ret = copy_to_user((char *)arg, &pmb->tile, sizeof(pmb->tile));
-+ break;
-+ case IPMMU_SET_PMB_TL:
-+ ret = copy_from_user(&user_tile, (char *)arg,
-+ sizeof(user_tile));
-+ if (ret)
-+ break;
-+ ret = set_tile(pmb, &user_tile);
-+ if (!ret)
-+ pmb->tile = user_tile;
-+ break;
-+ }
-+ return ret;
-+}
-+
-+static const struct file_operations ipmmu_pmb_fops = {
-+ .owner = THIS_MODULE,
-+ .open = ipmmu_pmb_open,
-+ .release = ipmmu_pmb_release,
-+ .unlocked_ioctl = ipmmu_pmb_ioctl,
-+};
-+
-+void ipmmu_pmb_deinit(void *arg)
-+{
-+ struct ipmmu_pmb_priv *priv = arg;
-+
-+ if (!priv || IS_ERR(priv))
-+ return;
-+
-+ cdev_del(&priv->cdev);
-+ device_destroy(priv->pmb_class, priv->pmb_dev);
-+ unregister_chrdev_region(priv->pmb_dev, 1);
-+ class_destroy(priv->pmb_class);
-+ kfree(priv);
-+}
-+
-+void *ipmmu_pmb_init(struct device *ipmmu_dev)
-+{
-+ int err = -ENOENT;
-+ struct ipmmu_pmb_priv *priv;
-+
-+ priv = kzalloc(sizeof(struct ipmmu_pmb_priv), GFP_KERNEL);
-+ if (!priv) {
-+ dev_err(ipmmu_dev, "cannot allocate device data\n");
-+ return ERR_PTR(-ENOMEM);
-+ }
-+
-+ priv->ipmmu_dev = ipmmu_dev;
-+ static_priv = priv;
-+
-+ mutex_init(&priv->pmb_lock);
-+
-+ priv->pmb_class = class_create(THIS_MODULE, "ipmmu-pmb");
-+ if (!priv->pmb_class)
-+ goto free_priv;
-+
-+ err = alloc_chrdev_region(&priv->pmb_dev, 0, 1, PMB_DEVICE_NAME);
-+ if (err) {
-+ dev_err(ipmmu_dev, "cannot allocate device num\n");
-+ goto destroy_class;
-+ }
-+
-+ if (!device_create(priv->pmb_class, ipmmu_dev, priv->pmb_dev, priv,
-+ "pmb"))
-+ goto unregister_region;
-+
-+ cdev_init(&priv->cdev, &ipmmu_pmb_fops);
-+ priv->cdev.owner = THIS_MODULE;
-+ priv->cdev.ops = &ipmmu_pmb_fops;
-+ err = cdev_add(&priv->cdev, priv->pmb_dev, 1);
-+ if (err) {
-+ dev_err(ipmmu_dev, "cannot add ipmmu_pmb device\n");
-+ goto destroy_device;
-+ }
-+
-+ return priv;
-+
-+destroy_device:
-+ device_destroy(priv->pmb_class, priv->pmb_dev);
-+unregister_region:
-+ unregister_chrdev_region(priv->pmb_dev, 1);
-+destroy_class:
-+ class_destroy(priv->pmb_class);
-+free_priv:
-+ kfree(priv);
-+ return ERR_PTR(err);
-+}
---- a/arch/arm/mach-shmobile/ipmmu.c
-+++ b/arch/arm/mach-shmobile/ipmmu.c
-@@ -23,28 +23,242 @@
- #include <linux/export.h>
- #include <linux/slab.h>
- #include <mach/ipmmu.h>
-+#include <linux/ipmmu.h>
-
--#define IMCTR1 0x000
--#define IMCTR2 0x004
--#define IMASID 0x010
--#define IMTTBR 0x014
--#define IMTTBCR 0x018
--
-+#define IMCTR1 0x00
- #define IMCTR1_TLBEN (1 << 0)
- #define IMCTR1_FLUSH (1 << 1)
-+#define IMCTR2 0x04
-+#define IMCTR2_PMBEN 0x01
-+#define IMASID 0x010
-+#define IMTTBR 0x014
-+#define IMTTBCR 0x018
-+#define IMPMBA_BASE 0x80
-+#define IMPBMA_V (1 << 8)
-+#define IMPMBD_BASE 0xC0
-+#define IMPBMD_V (1 << 8)
-+#define IMPBMD_SZ_16M 0x00
-+#define IMPBMD_SZ_64M 0x10
-+#define IMPBMD_SZ_128M 0x80
-+#define IMPBMD_SZ_512M 0x90
-+#define IMPBMD_BV (1 << 9)
-+#define IMPBMD_TBM_MASK (7 << 12)
-+#define IMPBMD_TBM_POS 12
-+#define IMPBMD_HBM_MASK (7 << 16)
-+#define IMPBMD_HBM_POS 16
-+#define IMPBMD_VBM_MASK (7 << 20)
-+#define IMPBMD_VBM_POS 20
-+
-+#define IMPBMA(x) (IMPMBA_BASE + 0x4*x)
-+#define IMPBMD(x) (IMPMBD_BASE + 0x4*x)
-+
-+/* the smallest size that can be reserverd in the pmb */
-+#define PMB_GRANULARITY (16 << 20)
-+#define PMB_START_ADDR 0x80000000
-+#define PMB_SIZE 0x40000000
-+#define NUM_BITS(x) ((x) / PMB_GRANULARITY)
-+#define NR_BITMAPS ((NUM_BITS(PMB_SIZE) + BITS_PER_LONG - 1) \
-+ >> ilog2(BITS_PER_LONG))
-
- struct ipmmu_priv {
-- void __iomem *ipmmu_base;
-- int tlb_enabled;
-- struct mutex flush_lock;
-+ struct device *dev;
-+ void __iomem *ipmmu_base;
-+ int tlb_enabled;
-+ struct mutex flush_lock;
-+ struct mutex alloc_lock;
-+ unsigned long alloc_bitmaps[NR_BITMAPS];
-+ void *pmb_priv;
- };
-
-+static int valid_size(int size_mb)
-+{
-+ switch (size_mb) {
-+ case 16:
-+ case 64:
-+ case 128:
-+ case 512:
-+ return 1;
-+ }
-+ return 0;
-+
-+}
-+unsigned long handle_alloc(struct device *dev,
-+ int size_mb)
-+{
-+ int i;
-+ int idx;
-+ unsigned long tmp_bitmap;
-+ unsigned long alloc_mask;
-+ unsigned long align_mask;
-+ int alloc_bits;
-+ struct ipmmu_priv *priv;
-+
-+ if (!valid_size(size_mb))
-+ return -1;
-+
-+ priv = dev_get_drvdata(dev);
-+
-+ alloc_bits = NUM_BITS(size_mb << 20);
-+ alloc_mask = alloc_bits < BITS_PER_LONG ?
-+ (1 << alloc_bits) - 1 : -1;
-+
-+
-+ align_mask = alloc_mask - 1;
-+ for (i = BITS_PER_LONG >> 1; i >= alloc_bits; i = i >> 1)
-+ align_mask = align_mask | (align_mask << i);
-+
-+ mutex_lock(&priv->alloc_lock);
-+ for (i = 0; i < NR_BITMAPS; i++) {
-+ tmp_bitmap = priv->alloc_bitmaps[i];
-+ tmp_bitmap |= align_mask;
-+ idx = 0;
-+ while (idx < BITS_PER_LONG) {
-+ idx = find_next_zero_bit(&tmp_bitmap, BITS_PER_LONG,
-+ idx);
-+ if (!((alloc_mask << idx) & priv->alloc_bitmaps[i]) ||
-+ (idx == BITS_PER_LONG))
-+ break;
-+ idx++;
-+ }
-+ if (idx < BITS_PER_LONG)
-+ break;
-+ }
-+ if (i == NR_BITMAPS) {
-+ mutex_unlock(&priv->alloc_lock);
-+ return 0;
-+ }
-+
-+ priv->alloc_bitmaps[i] |= (alloc_mask << idx);
-+ mutex_unlock(&priv->alloc_lock);
-+
-+ return PMB_START_ADDR + (i * BITS_PER_LONG + idx) * PMB_GRANULARITY;
-+}
-+
-+void handle_free(struct device *dev,
-+ unsigned long handle,
-+ int size_mb)
-+{
-+ int idx;
-+ unsigned long offset;
-+ unsigned long alloc_bits;
-+ unsigned long alloc_mask;
-+ struct ipmmu_priv *priv;
-+
-+ priv = dev_get_drvdata(dev);
-+
-+ alloc_bits = NUM_BITS(size_mb << 20);
-+ alloc_mask = alloc_bits < BITS_PER_LONG ?
-+ (1 << alloc_bits) - 1 : -1;
-+ offset = handle - PMB_START_ADDR;
-+ offset /= PMB_GRANULARITY;
-+ idx = offset & (BITS_PER_LONG - 1);
-+ offset = offset / BITS_PER_LONG;
-+ mutex_lock(&priv->alloc_lock);
-+ priv->alloc_bitmaps[offset] &= ~(alloc_mask << idx);
-+ mutex_unlock(&priv->alloc_lock);
-+}
-+
- static void ipmmu_reg_write(struct ipmmu_priv *priv, unsigned long reg_off,
- unsigned long data)
- {
- iowrite32(data, priv->ipmmu_base + reg_off);
- }
-
-+int ipmmu_pmb_enable(struct device *dev,
-+ int enable)
-+{
-+
-+ struct ipmmu_priv *priv;
-+
-+ priv = dev_get_drvdata(dev);
-+ ipmmu_reg_write(priv, IMCTR2, enable ? IMCTR2_PMBEN : 0);
-+ return 0;
-+
-+}
-+int ipmmu_pmb_set_addr(struct device *dev,
-+ int index,
-+ unsigned long addr,
-+ int enabled)
-+{
-+
-+ struct ipmmu_priv *priv;
-+
-+ priv = dev_get_drvdata(dev);
-+ if (!enabled) {
-+ ipmmu_reg_write(priv, IMPBMA(index), 0);
-+ return 0;
-+ }
-+
-+ ipmmu_reg_write(priv, IMPBMA(index), addr |
-+ IMPBMD_V);
-+ return 0;
-+
-+}
-+
-+int ipmmu_pmb_set_data(struct device *dev,
-+ int index,
-+ struct ipmmu_pmb_info *info,
-+ struct pmb_tile_info *tile)
-+{
-+ int vbm, hbm, tbm;
-+ int w, h;
-+ unsigned long temp;
-+ struct ipmmu_priv *priv;
-+
-+ priv = dev_get_drvdata(dev);
-+
-+ if (!info || !info->enabled) {
-+ ipmmu_reg_write(priv, IMPBMD(index), 0);
-+ return 0;
-+ }
-+
-+ temp = info->paddr;
-+
-+ switch (info->size_mb) {
-+ case 16:
-+ temp |= IMPBMD_SZ_16M;
-+ break;
-+ case 64:
-+ temp |= IMPBMD_SZ_64M;
-+ break;
-+ case 128:
-+ temp |= IMPBMD_SZ_128M;
-+ break;
-+ case 512:
-+ temp |= IMPBMD_SZ_512M;
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ temp |= IMPBMD_V;
-+
-+ if (!tile || !tile->enabled) {
-+ ipmmu_reg_write(priv, IMPBMD(index), temp);
-+ return 0;
-+ }
-+
-+ w = tile->tile_width;
-+ h = tile->tile_height;
-+
-+ if (w & (w - 1) || h & (h - 1))
-+ return -EINVAL;
-+
-+ tbm = ilog2(tile->tile_width);
-+ vbm = ilog2(tile->tile_height) - 1;
-+ hbm = ilog2(tile->buffer_pitch) - tbm - 1;
-+ tbm -= 4;
-+
-+ temp |= (tbm << IMPBMD_TBM_POS) & IMPBMD_TBM_MASK;
-+ temp |= (vbm << IMPBMD_VBM_POS) & IMPBMD_VBM_MASK;
-+ temp |= (hbm << IMPBMD_HBM_POS) & IMPBMD_HBM_MASK;
-+ temp |= IMPBMD_BV;
-+ ipmmu_reg_write(priv, IMPBMD(index),
-+ temp);
-+ ipmmu_tlb_flush(priv->dev);
-+ return 0;
-+}
-+
- void ipmmu_tlb_flush(struct device *dev)
- {
- struct ipmmu_priv *priv;
-@@ -122,6 +336,8 @@ static int __devinit ipmmu_probe(struct
- return -ENOMEM;
- }
- mutex_init(&priv->flush_lock);
-+ mutex_init(&priv->alloc_lock);
-+
- priv->ipmmu_base = ioremap_nocache(res->start, resource_size(res));
- if (!priv->ipmmu_base) {
- dev_err(&pdev->dev, "ioremap_nocache failed\n");
-@@ -129,9 +345,11 @@ static int __devinit ipmmu_probe(struct
- return -ENOMEM;
- }
- platform_set_drvdata(pdev, priv);
-+ priv->dev = &pdev->dev;
- ipmmu_reg_write(priv, IMCTR1, 0x0); /* disable TLB */
- ipmmu_reg_write(priv, IMCTR2, 0x0); /* disable PMB */
- ipmmu_iommu_init(&pdev->dev);
-+ priv->pmb_priv = ipmmu_pmb_init(&pdev->dev);
- return 0;
- }
-
---- /dev/null
-+++ b/include/linux/ipmmu.h
-@@ -0,0 +1,29 @@
-+#ifndef __LINUX_IPMMU_PMB_H__
-+#define __LINUX_IPMMU_PMB_H__
-+
-+struct ipmmu_pmb_info {
-+ int enabled;
-+ unsigned long paddr;
-+ int size_mb;
-+};
-+
-+struct pmb_tile_info {
-+ int tile_width;
-+ int tile_height;
-+ int buffer_pitch;
-+ int enabled;
-+};
-+
-+/* IOCTL commands. */
-+
-+#define IPMMU_SET_PMB _IOW('S', 37, struct ipmmu_pmb_phys *)
-+#define IPMMU_GET_PMB _IOR('S', 38, struct ipmmu_pmb_phys *)
-+#define IPMMU_GET_PMB_HANDLE _IOR('S', 39, unsigned long *)
-+#define IPMMU_SET_PMB_TL _IOW('S', 41, struct ipmmu_pmb_tile_info *)
-+#define IPMMU_GET_PMB_TL _IOR('S', 42, struct ipmmu_pmb_tile_info *)
-+
-+#ifdef __kernel
-+
-+#endif /* __kernel */
-+
-+#endif /* __LINUX_IPMMU_PMB_H__ */
+++ /dev/null
-From dhobsong@igel.co.jp Wed Nov 21 23:30:45 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Thu, 22 Nov 2012 16:28:30 +0900
-Subject: [PATCH 7/7] shmobile: r8a7740: Add MERAM UIO device
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Message-ID: <1353569310-16564-8-git-send-email-dhobsong@igel.co.jp>
-
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mach-shmobile/setup-r8a7740.c | 34 +++++++++++++++++++++++++++++++++
- 1 file changed, 34 insertions(+)
-
---- a/arch/arm/mach-shmobile/setup-r8a7740.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
-@@ -105,6 +105,39 @@ static struct platform_device vpc_device
- .num_resources = ARRAY_SIZE(vpc_resources),
- };
-
-+/* MERAM */
-+static struct uio_info meram_uio_platform_data = {
-+ .name = "MERAM",
-+ .version = "0",
-+ .irq = -1,
-+};
-+
-+static struct resource meram_uio_resources[] = {
-+ [0] = {
-+ .name = "MERAM",
-+ .start = 0xe8000000,
-+ .end = 0xe807ffff,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .name = "MERAM_MEM",
-+ .start = 0xe8080000,
-+ .end = 0xe81fffff,
-+ .flags = IORESOURCE_MEM,
-+ },
-+};
-+
-+static struct platform_device meram_uio_device = {
-+ .name = "uio_pdrv_genirq",
-+ .id = 0,
-+ .dev = {
-+ .platform_data = &meram_uio_platform_data,
-+ .coherent_dma_mask = ~0,
-+ },
-+ .resource = meram_uio_resources,
-+ .num_resources = ARRAY_SIZE(meram_uio_resources),
-+};
-+
- /* VCP1 */
- static unsigned int regions[] = {
- (80 << 20),
-@@ -424,6 +457,7 @@ static struct platform_device *r8a7740_e
- &vio_device,
- &ipmmu_device,
- &meram_device,
-+ &meram_uio_device,
-
- };
-
+++ /dev/null
-From dhobsong@igel.co.jp Wed Nov 21 23:30:31 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Thu, 22 Nov 2012 16:28:24 +0900
-Subject: [PATCH 1/7] shmobile: r8a7740: Add support for VCP-1 (VPU), VPC, VIO multimedia IP
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Message-ID: <1353569310-16564-2-git-send-email-dhobsong@igel.co.jp>
-
-
-Att the UIO device and clock settings for these multimedia IP cores
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 1
- arch/arm/mach-shmobile/clock-r8a7740.c | 9 ++
- arch/arm/mach-shmobile/include/mach/common.h | 1
- arch/arm/mach-shmobile/setup-r8a7740.c | 100 +++++++++++++++++++++++++
- 4 files changed, 110 insertions(+), 1 deletion(-)
-
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -1212,6 +1212,7 @@ DT_MACHINE_START(ARMADILLO800EVA_DT, "ar
- .init_early = eva_add_early_devices,
- .init_irq = r8a7740_init_irq,
- .handle_irq = shmobile_handle_irq_intc,
-+ .reserve = r8a7740_reserve_memory,
- .init_machine = eva_init,
- .init_late = shmobile_init_late,
- .timer = &shmobile_timer,
---- a/arch/arm/mach-shmobile/clock-r8a7740.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
-@@ -459,7 +459,7 @@ static struct clk div6_clks[DIV6_NR] = {
-
- enum {
- MSTP128, MSTP127, MSTP125,
-- MSTP116, MSTP111, MSTP100, MSTP117,
-+ MSTP116, MSTP111, MSTP100, MSTP117, MSTP101, MSTP107, MSTP103,
-
- MSTP230,
- MSTP222,
-@@ -483,6 +483,9 @@ static struct clk mstp_clks[MSTP_NR] = {
- [MSTP116] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */
- [MSTP111] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 11, 0), /* TMU1 */
- [MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */
-+ [MSTP101] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 1, 0), /* VPU5HA2 */
-+ [MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 3, 0), /* VIO6C */
-+ [MSTP107] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 7, 0), /* VPC */
-
- [MSTP230] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 30, 0), /* SCIFA6 */
- [MSTP222] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 22, 0), /* SCIFA7 */
-@@ -554,6 +557,10 @@ static struct clk_lookup lookups[] = {
-
- /* MSTP32 clocks */
- CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]),
-+ CLKDEV_DEV_ID("uio_dmem_genirq.0", &mstp_clks[MSTP101]),
-+ CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[MSTP103]),
-+ CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[MSTP107]),
-+ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]),
- CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP111]),
- CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]),
- CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]),
---- a/arch/arm/mach-shmobile/include/mach/common.h
-+++ b/arch/arm/mach-shmobile/include/mach/common.h
-@@ -68,6 +68,7 @@ extern void r8a7740_map_io(void);
- extern void r8a7740_add_early_devices(void);
- extern void r8a7740_add_standard_devices(void);
- extern void r8a7740_clock_init(u8 md_ck);
-+extern void r8a7740_reserve_memory(void);
- extern void r8a7740_pinmux_init(void);
-
- extern void r8a7779_init_irq(void);
---- a/arch/arm/mach-shmobile/setup-r8a7740.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
-@@ -23,10 +23,13 @@
- #include <linux/init.h>
- #include <linux/io.h>
- #include <linux/platform_device.h>
-+#include <linux/platform_data/uio_dmem_genirq.h>
- #include <linux/of_platform.h>
- #include <linux/serial_sci.h>
- #include <linux/sh_dma.h>
- #include <linux/sh_timer.h>
-+#include <linux/uio_driver.h>
-+#include <linux/dma-contiguous.h>
- #include <linux/dma-mapping.h>
- #include <mach/dma-register.h>
- #include <mach/r8a7740.h>
-@@ -74,6 +77,94 @@ void __init r8a7740_map_io(void)
- init_consistent_dma_size(12 << 20);
- }
-
-+/* VPC */
-+static struct uio_info vpc_platform_data = {
-+ .name = "VPC",
-+ .version = "0",
-+ .irq = -1,
-+};
-+
-+static struct resource vpc_resources[] = {
-+ [0] = {
-+ .name = "VPC",
-+ .start = 0xfe9d0000,
-+ .end = 0xfe9d0020,
-+ .flags = IORESOURCE_MEM,
-+ },
-+};
-+
-+static struct platform_device vpc_device = {
-+ .name = "uio_pdrv_genirq",
-+ .id = 2,
-+ .dev = {
-+ .platform_data = &vpc_platform_data,
-+ },
-+ .resource = vpc_resources,
-+ .num_resources = ARRAY_SIZE(vpc_resources),
-+};
-+
-+/* VCP1 */
-+static unsigned int regions[] = {
-+ (80 << 20),
-+};
-+
-+static struct uio_dmem_genirq_pdata vpu_platform_data = {
-+ .uioinfo = {
-+ .name = "VPU5",
-+ .version = "0",
-+ .irq = intcs_evt2irq(0x880),
-+ },
-+ .dynamic_region_sizes = regions,
-+ .num_dynamic_regions = ARRAY_SIZE(regions),
-+};
-+
-+static struct resource vpu_resources[] = {
-+ [0] = {
-+ .name = "VPU",
-+ .start = 0xfe900000,
-+ .end = 0xfe900157,
-+ .flags = IORESOURCE_MEM,
-+ },
-+};
-+
-+static struct platform_device vpu_device = {
-+ .name = "uio_dmem_genirq",
-+ .id = 0,
-+ .dev = {
-+ .platform_data = &vpu_platform_data,
-+ .coherent_dma_mask = ~0,
-+ },
-+ .resource = vpu_resources,
-+ .num_resources = ARRAY_SIZE(vpu_resources),
-+};
-+
-+/* VI00 */
-+static struct uio_info vio_platform_data = {
-+ .name = "VIO6C",
-+ .version = "0",
-+ .irq = intcs_evt2irq(0x4E0),
-+};
-+
-+static struct resource vio_resources[] = {
-+ [0] = {
-+ .name = "VIO6",
-+ .start = 0xfe920000,
-+ .end = 0xfe928000,
-+ .flags = IORESOURCE_MEM,
-+ },
-+};
-+
-+static struct platform_device vio_device = {
-+ .name = "uio_pdrv_genirq",
-+ .id = 1,
-+ .dev = {
-+ .platform_data = &vio_platform_data,
-+ .coherent_dma_mask = ~0,
-+ },
-+ .resource = vio_resources,
-+ .num_resources = ARRAY_SIZE(vio_resources),
-+};
-+
- /* SCIFA0 */
- static struct plat_sci_port scif0_platform_data = {
- .mapbase = 0xe6c40000,
-@@ -279,6 +370,10 @@ static struct platform_device *r8a7740_e
- &scif7_device,
- &scifb_device,
- &cmt10_device,
-+ &vpu_device,
-+ &vpc_device,
-+ &vio_device,
-+
- };
-
- /* DMA */
-@@ -718,6 +813,11 @@ void __init r8a7740_add_early_devices(vo
- shmobile_timer.init = r8a7740_earlytimer_init;
- }
-
-+void __init r8a7740_reserve_memory(void)
-+{
-+ dma_declare_contiguous(&vpu_device.dev, 80 << 20, 0, 0);
-+}
-+
- #ifdef CONFIG_USE_OF
-
- void __init r8a7740_add_early_devices_dt(void)
+++ /dev/null
-From dhobsong@igel.co.jp Wed Nov 21 23:30:42 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Thu, 22 Nov 2012 16:28:29 +0900
-Subject: [PATCH 6/7] shmobile: r8a7740: Set up MERAM address range
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Message-ID: <1353569310-16564-7-git-send-email-dhobsong@igel.co.jp>
-
-
-The default address range settings have both the MERAM and the IPMMU-PMB
-set to use the same range, starting from 0x80000000. The MERAM has
-priority over this address range, which means that regardless of the PMB
-setting, any H/W accesses to the 0x80000000 memory region will be intercepted
-by the MERAM. This patch uses the MERAM driver to change the MERAM memory
-range to start at 0xC0000000.
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mach-shmobile/setup-r8a7740.c | 32 ++++++++++++++++++++++++++++++++
- 1 file changed, 32 insertions(+)
-
---- a/arch/arm/mach-shmobile/setup-r8a7740.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
-@@ -30,6 +30,7 @@
- #include <linux/sh_timer.h>
- #include <linux/uio_driver.h>
- #include <linux/dma-contiguous.h>
-+#include <video/sh_mobile_meram.h>
- #include <linux/dma-mapping.h>
- #include <mach/dma-register.h>
- #include <mach/r8a7740.h>
-@@ -377,6 +378,36 @@ static struct platform_device ipmmu_devi
- .num_resources = ARRAY_SIZE(ipmmu_resources),
- };
-
-+/* MERAM */
-+static struct sh_mobile_meram_info meram_info = {
-+ .addr_mode = SH_MOBILE_MERAM_MODE1,
-+};
-+
-+static struct resource meram_resources[] = {
-+ [0] = {
-+ .name = "MERAM",
-+ .start = 0xe8000000,
-+ .end = 0xe807ffff,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .name = "MERAM",
-+ .start = 0xe8080000,
-+ .end = 0xe81fffff,
-+ .flags = IORESOURCE_MEM,
-+ }
-+};
-+
-+static struct platform_device meram_device = {
-+ .name = "sh_mobile_meram",
-+ .id = 0,
-+ .num_resources = ARRAY_SIZE(meram_resources),
-+ .resource = meram_resources,
-+ .dev = {
-+ .platform_data = &meram_info,
-+ },
-+};
-+
- static struct platform_device *r8a7740_early_devices[] __initdata = {
- &scif0_device,
- &scif1_device,
-@@ -392,6 +423,7 @@ static struct platform_device *r8a7740_e
- &vpc_device,
- &vio_device,
- &ipmmu_device,
-+ &meram_device,
-
- };
-
+++ /dev/null
-From 1fe826bf63cef59dde06a3e53f44445469c3ec75 Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Fri, 23 Mar 2012 17:56:29 +0800
-Subject: MAINTAINERS: add entry for Atmel isi driver
-
-commit 1551554518371d919bbf6f3f1b1599ea2e7d2ac0 upstream.
-
-Signed-off-by: Josh Wu <josh.wu@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- MAINTAINERS | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/MAINTAINERS b/MAINTAINERS
-index a60009d..c7c725e 100644
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -1331,6 +1331,13 @@ M: Nicolas Ferre <nicolas.ferre@atmel.com>
- S: Supported
- F: drivers/tty/serial/atmel_serial.c
-
-+ATMEL ISI DRIVER
-+M: Josh Wu <josh.wu@atmel.com>
-+L: linux-media@vger.kernel.org
-+S: Supported
-+F: drivers/media/video/atmel-isi.c
-+F: include/media/atmel-isi.h
-+
- ATMEL LCDFB DRIVER
- M: Nicolas Ferre <nicolas.ferre@atmel.com>
- L: linux-fbdev@vger.kernel.org
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 5dfa35bf3ff4ceaa13e05e8ed563435b499a665e Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Fri, 23 Mar 2012 17:56:55 +0800
-Subject: MAINTAINERS: add entry for Atmel touch screen ADC controller driver
-
-commit ff2675d6994157c308d7ce504b9f19a1c22d01a8 upstream.
-
-Signed-off-by: Josh Wu <josh.wu@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- MAINTAINERS | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/MAINTAINERS b/MAINTAINERS
-index c7c725e..347df81 100644
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -1355,6 +1355,12 @@ M: Nicolas Ferre <nicolas.ferre@atmel.com>
- S: Supported
- F: drivers/spi/spi-atmel.*
-
-+ATMEL TSADCC DRIVER
-+M: Josh Wu <josh.wu@atmel.com>
-+L: linux-input@vger.kernel.org
-+S: Supported
-+F: drivers/input/touchscreen/atmel_tsadcc.c
-+
- ATMEL USBA UDC DRIVER
- M: Nicolas Ferre <nicolas.ferre@atmel.com>
- L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From aebdb4a2d3da9740c830b56ebdaaf9ade2e52b93 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 26 Mar 2012 15:50:36 +0200
-Subject: MAINTAINERS: add entry for Atmel DMA driver
-
-commit b414dc16f6ee64a23c525f80b924e44b0f0bee18 upstream.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- MAINTAINERS | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/MAINTAINERS b/MAINTAINERS
-index 347df81..5d607d2 100644
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -1331,6 +1331,14 @@ M: Nicolas Ferre <nicolas.ferre@atmel.com>
- S: Supported
- F: drivers/tty/serial/atmel_serial.c
-
-+ATMEL DMA DRIVER
-+M: Nicolas Ferre <nicolas.ferre@atmel.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+F: drivers/dma/at_hdmac.c
-+F: drivers/dma/at_hdmac_regs.h
-+F: arch/arm/mach-at91/include/mach/at_hdmac.h
-+
- ATMEL ISI DRIVER
- M: Josh Wu <josh.wu@atmel.com>
- L: linux-media@vger.kernel.org
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 5ef2e8ea2b7b19632f2d8d931ddaa130669d50a1 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 26 Mar 2012 15:59:32 +0200
-Subject: MAINTAINERS: add entry for Atmel timer counter (TC)
-
-commit e9cb1c5a5ba906d01bf49a27460bd357aa6089ab upstream.
-
-Add an entry for the Timer Counter (TC) library and the clocksource
-driver that is using this library.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- MAINTAINERS | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/MAINTAINERS b/MAINTAINERS
-index 5d607d2..54d18b0 100644
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -1363,6 +1363,13 @@ M: Nicolas Ferre <nicolas.ferre@atmel.com>
- S: Supported
- F: drivers/spi/spi-atmel.*
-
-+ATMEL Timer Counter (TC) AND CLOCKSOURCE DRIVERS
-+M: Nicolas Ferre <nicolas.ferre@atmel.com>
-+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-+S: Supported
-+F: drivers/misc/atmel_tclib.c
-+F: drivers/clocksource/tcb_clksrc.c
-+
- ATMEL TSADCC DRIVER
- M: Josh Wu <josh.wu@atmel.com>
- L: linux-input@vger.kernel.org
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From c28695c921cee53829198558dc3ed95d9b65c83c Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 26 Mar 2012 16:11:19 +0200
-Subject: MAINTAINERS: remove non-responding web link for atmel_usba driver
-
-commit 1066c51ee28189aabff073bcd197b84a4f87ea81 upstream.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Cc: Haavard Skinnemoen <hskinnemoen@gmail.com>
-Cc: Hans-Christian Egtvedt <egtvedt@samfundet.no>
----
- MAINTAINERS | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/MAINTAINERS b/MAINTAINERS
-index 54d18b0..9c7e7ce 100644
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -1379,7 +1379,6 @@ F: drivers/input/touchscreen/atmel_tsadcc.c
- ATMEL USBA UDC DRIVER
- M: Nicolas Ferre <nicolas.ferre@atmel.com>
- L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
--W: http://avr32linux.org/twiki/bin/view/Main/AtmelUsbDeviceDriver
- S: Supported
- F: drivers/usb/gadget/atmel_usba_udc.*
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 0bec15efe762b830db265b747b134a15e6600045 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 15 Mar 2012 12:21:12 +0100
-Subject: ARM: at91: change AT91 Kconfig entry comment
-
-commit 929e994f7e249a58f50ccdd066da9899a6e39c7a upstream.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/Kconfig | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -350,8 +350,8 @@ config ARCH_AT91
- select IRQ_DOMAIN
- select NEED_MACH_IO_H if PCCARD
- help
-- This enables support for systems based on the Atmel AT91RM9200,
-- AT91SAM9 processors.
-+ This enables support for systems based on Atmel
-+ AT91RM9200 and AT91SAM9* processors.
-
- config ARCH_BCMRING
- bool "Broadcom BCMRING"
+++ /dev/null
-From 9826d66f3e249659ca04a31885496ecb04f956ee Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 15 Mar 2012 12:26:43 +0100
-Subject: ARM: at91/Kconfig: change at91sam9g45 entry
-
-commit ca1dcbf7fc6a9d849f487a50f8ee34f923d8e16b upstream.
-
-The AT91SAM9G45 entry covers the whole family so we also add the AT91SAM9M10
-name and the "families" qualifier. Then, add a comment to explain which SoCs
-are supported by this entry: AT91SAM9G45, AT91SAM9G46 but also
-AT91SAM9M10 and AT91SAM9M11.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/Kconfig | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
-index 45db05d..dfbc2c5 100644
---- a/arch/arm/mach-at91/Kconfig
-+++ b/arch/arm/mach-at91/Kconfig
-@@ -89,13 +89,16 @@ config ARCH_AT91SAM9G20
- select HAVE_NET_MACB
-
- config ARCH_AT91SAM9G45
-- bool "AT91SAM9G45"
-+ bool "AT91SAM9G45 or AT91SAM9M10 families"
- select CPU_ARM926T
- select GENERIC_CLOCKEVENTS
- select HAVE_AT91_USART3
- select HAVE_FB_ATMEL
- select HAVE_NET_MACB
- select HAVE_AT91_DBGU1
-+ help
-+ Select this if you are using one of Atmel's AT91SAM9G45 family SoC.
-+ This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11.
-
- config ARCH_AT91SAM9X5
- bool "AT91SAM9x5 family"
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 146a8f586032093247b7fbe75bde12d4d9bb4129 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 15 Mar 2012 12:48:41 +0100
-Subject: ARM: at91/Kconfig: add comment to at91sam9x5 family entry
-
-commit a26e1af50e716711c340146529403b37c5d455e8 upstream.
-
-Add comment to make it clear that several SoC are supported by
-this generic entry.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/Kconfig | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
-index dfbc2c5..cad7a15 100644
---- a/arch/arm/mach-at91/Kconfig
-+++ b/arch/arm/mach-at91/Kconfig
-@@ -107,6 +107,12 @@ config ARCH_AT91SAM9X5
- select HAVE_FB_ATMEL
- select HAVE_NET_MACB
- select HAVE_AT91_DBGU0
-+ help
-+ Select this if you are using one of Atmel's AT91SAM9x5 family SoC.
-+ This means that your SAM9 name finishes with a '5' (except if it is
-+ AT91SAM9G45!).
-+ This support covers AT91SAM9G15, AT91SAM9G25, AT91SAM9X25, AT91SAM9G35
-+ and AT91SAM9X35.
-
- config ARCH_AT91X40
- bool "AT91x40"
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 18a3e8c78f1e37ef27874b915a8719589c801557 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 15 Mar 2012 12:57:03 +0100
-Subject: ARM: at91/Kconfig: add clarifications to AT91SAM9M10G45-EK entry
-
-commit fefbc4075a191e9e8c1064906c400ed19a0bc48a upstream.
-
-Add clarifications about the SoCs that can be found on an AT91SAM9M10G45-EK
-board. Add also the web link to this board on Atmel's website.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/Kconfig | 7 ++++---
- 1 file changed, 4 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
-index cad7a15..d2922a1 100644
---- a/arch/arm/mach-at91/Kconfig
-+++ b/arch/arm/mach-at91/Kconfig
-@@ -442,9 +442,10 @@ comment "AT91SAM9G45 Board Type"
- config MACH_AT91SAM9M10G45EK
- bool "Atmel AT91SAM9M10G45-EK Evaluation Kits"
- help
-- Select this if you are using Atmel's AT91SAM9G45-EKES Evaluation Kit.
-- "ES" at the end of the name means that this board is an
-- Engineering Sample.
-+ Select this if you are using Atmel's AT91SAM9M10G45-EK Evaluation Kit.
-+ Those boards can be populated with any SoC of AT91SAM9G45 or AT91SAM9M10
-+ families: AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11.
-+ <http://www.atmel.com/tools/SAM9M10-G45-EK.aspx>
-
- endif
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 7be4beaa63a35e15e2c80938cc45aee62670cf49 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 15 Mar 2012 13:49:21 +0100
-Subject: ARM: at91/Kconfig: add AT91SAM9x5 family to AT91_EARLY_DBGU0 entry
-
-commit 514982adc7a5439140e09facf492e58fc8a7fcc3 upstream.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
-index d2922a1..e0b8b10 100644
---- a/arch/arm/mach-at91/Kconfig
-+++ b/arch/arm/mach-at91/Kconfig
-@@ -529,7 +529,7 @@ choice
- prompt "Select a UART for early kernel messages"
-
- config AT91_EARLY_DBGU0
-- bool "DBGU on rm9200, 9260/9g20, 9261/9g10 and 9rl"
-+ bool "DBGU on rm9200, 9260/9g20, 9261/9g10, 9rl and 9x5"
- depends on HAVE_AT91_DBGU0
-
- config AT91_EARLY_DBGU1
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b1331a2b88162177d8a1f011736a51401724c20e Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 15 Mar 2012 13:56:44 +0100
-Subject: ARM: at91/Kconfig: website link for AT91SAM9G20-EK
-
-commit ff65e398f3e3d1ee38a6b23d5a9f8e2fd950be49 upstream.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
-index e0b8b10..8acc164 100644
---- a/arch/arm/mach-at91/Kconfig
-+++ b/arch/arm/mach-at91/Kconfig
-@@ -373,6 +373,7 @@ config MACH_AT91SAM9G20EK_2MMC
- Select this if you are using an Atmel AT91SAM9G20-EK Evaluation Kit
- with 2 SD/MMC Slots. This is the case for AT91SAM9G20-EK rev. C and
- onwards.
-+ <http://www.atmel.com/tools/SAM9G20-EK.aspx>
-
- config MACH_CPU9G20
- bool "Eukrea CPU9G20 board"
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 4af884378298168d5bdd0e8d16a3d0ce86b0925a Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 15 Mar 2012 14:38:09 +0100
-Subject: rtc: Kconfig: remove dependency for AT91 rtc driver
-
-commit 938f970eb23d40dba49d7b14b774ed7ae7ec974a upstream.
-
-This will allow to select this driver for newer SoCs.
-Keep dependency on AT91 because of the use of an header
-file located in include/mach directory.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/rtc/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
-index 8c8377d..4161bfe 100644
---- a/drivers/rtc/Kconfig
-+++ b/drivers/rtc/Kconfig
-@@ -838,7 +838,7 @@ config RTC_DRV_AT32AP700X
-
- config RTC_DRV_AT91RM9200
- tristate "AT91RM9200 or some AT91SAM9 RTC"
-- depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
-+ depends on ARCH_AT91
- help
- Driver for the internal RTC (Realtime Clock) module found on
- Atmel AT91RM9200's and some AT91SAM9 chips. On AT91SAM9 chips
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 491ea72aa5bb04a0ab7078c74e0f8159044ececc Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 15 Mar 2012 16:02:02 +0100
-Subject: Input: Kconfig: remove dependency for atmel_tsadcc driver
-
-commit 1fc4ec3791729db4e2602e9afb1045aef1bc3a58 upstream.
-
-This will allow to select this driver for newer SoCs.
-Keep dependency on AT91 because of the use of an header
-file located in include/mach directory.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Dmitry Torokhov <dtor@mail.ru>
----
- drivers/input/touchscreen/Kconfig | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
-index 2a21419..75838d7 100644
---- a/drivers/input/touchscreen/Kconfig
-+++ b/drivers/input/touchscreen/Kconfig
-@@ -489,10 +489,10 @@ config TOUCHSCREEN_TI_TSCADC
-
- config TOUCHSCREEN_ATMEL_TSADCC
- tristate "Atmel Touchscreen Interface"
-- depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
-+ depends on ARCH_AT91
- help
- Say Y here if you have a 4-wire touchscreen connected to the
-- ADC Controller on your Atmel SoC (such as the AT91SAM9RL).
-+ ADC Controller on your Atmel SoC.
-
- If unsure, say N.
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2a6149a2914f5495085f2535a26b19a6e74de0bc Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 15 Mar 2012 16:10:59 +0100
-Subject: hwrng: Kconfig: remove dependency for atmel-rng driver
-
-commit 1234f4bada54cfcd4dfeeebccf0295d49174da40 upstream.
-
-This will allow to select this driver for newer SoCs. Make sure to
-keep dependency on HAVE_CLK to avoid breaking other machines.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
----
- drivers/char/hw_random/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
-index 0689bf6..b2402eb 100644
---- a/drivers/char/hw_random/Kconfig
-+++ b/drivers/char/hw_random/Kconfig
-@@ -62,7 +62,7 @@ config HW_RANDOM_AMD
-
- config HW_RANDOM_ATMEL
- tristate "Atmel Random Number Generator support"
-- depends on HW_RANDOM && ARCH_AT91SAM9G45
-+ depends on HW_RANDOM && HAVE_CLK
- default HW_RANDOM
- ---help---
- This driver provides kernel-side support for the Random Number
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 07c647f806c4b990c3ece3a6389de178d131b0d3 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Wed, 15 Feb 2012 18:35:40 +0800
-Subject: ARM: at91: uncompress Store UART address in a variable
-
-commit c40a763be603867c226505dbe0845ea16a4ee538 upstream.
-
-This will allow a future change to auto-detect which UART to use.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/include/mach/uncompress.h | 20 +++++++++++---------
- 1 file changed, 11 insertions(+), 9 deletions(-)
-
-diff --git a/arch/arm/mach-at91/include/mach/uncompress.h b/arch/arm/mach-at91/include/mach/uncompress.h
-index 4218647..d985af7 100644
---- a/arch/arm/mach-at91/include/mach/uncompress.h
-+++ b/arch/arm/mach-at91/include/mach/uncompress.h
-@@ -43,6 +43,14 @@
- #define UART_OFFSET AT91_USART5
- #endif
-
-+void __iomem *at91_uart;
-+
-+static inline void arch_decomp_setup(void)
-+{
-+#ifdef UART_OFFSET
-+ at91_uart = (void __iomem *) UART_OFFSET; /* physical address */
-+#endif
-+}
- /*
- * The following code assumes the serial port has already been
- * initialized by the bootloader. If you didn't setup a port in
-@@ -53,27 +61,21 @@
- static void putc(int c)
- {
- #ifdef UART_OFFSET
-- void __iomem *sys = (void __iomem *) UART_OFFSET; /* physical address */
--
-- while (!(__raw_readl(sys + ATMEL_US_CSR) & ATMEL_US_TXRDY))
-+ while (!(__raw_readl(at91_uart + ATMEL_US_CSR) & ATMEL_US_TXRDY))
- barrier();
-- __raw_writel(c, sys + ATMEL_US_THR);
-+ __raw_writel(c, at91_uart + ATMEL_US_THR);
- #endif
- }
-
- static inline void flush(void)
- {
- #ifdef UART_OFFSET
-- void __iomem *sys = (void __iomem *) UART_OFFSET; /* physical address */
--
- /* wait for transmission to complete */
-- while (!(__raw_readl(sys + ATMEL_US_CSR) & ATMEL_US_TXEMPTY))
-+ while (!(__raw_readl(at91_uart + ATMEL_US_CSR) & ATMEL_US_TXEMPTY))
- barrier();
- #endif
- }
-
--#define arch_decomp_setup()
--
- #define arch_decomp_wdog()
-
- #endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b975f66bd77491d4f1b426fb4c02f337f0178f5f Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Wed, 15 Feb 2012 18:44:40 +0800
-Subject: ARM: at91: uncompress: autodetect the uart to use
-
-commit 5f29d0a0ee2c3c2ed06384c923db336183ee6708 upstream.
-
-This will now autodetect the first uart enabled by the bootloader
-and will use it for uncompress. This will still assume that the bootloader
-configured it (pins and clock).
-
-This also allows to include all soc headers together.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/Kconfig | 53 --------
- arch/arm/mach-at91/include/mach/at91rm9200.h | 5 -
- arch/arm/mach-at91/include/mach/at91sam9260.h | 7 --
- arch/arm/mach-at91/include/mach/at91sam9261.h | 4 -
- arch/arm/mach-at91/include/mach/at91sam9263.h | 4 -
- arch/arm/mach-at91/include/mach/at91sam9g45.h | 5 -
- arch/arm/mach-at91/include/mach/at91sam9rl.h | 5 -
- arch/arm/mach-at91/include/mach/at91sam9x5.h | 8 --
- arch/arm/mach-at91/include/mach/hardware.h | 16 +--
- arch/arm/mach-at91/include/mach/uncompress.h | 170 ++++++++++++++++++++++----
- 10 files changed, 148 insertions(+), 129 deletions(-)
-
-diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
-index 8acc164..885fdb9 100644
---- a/arch/arm/mach-at91/Kconfig
-+++ b/arch/arm/mach-at91/Kconfig
-@@ -9,15 +9,6 @@ config HAVE_AT91_DBGU0
- config HAVE_AT91_DBGU1
- bool
-
--config HAVE_AT91_USART3
-- bool
--
--config HAVE_AT91_USART4
-- bool
--
--config HAVE_AT91_USART5
-- bool
--
- config AT91_SAM9_ALT_RESET
- bool
- default !ARCH_AT91X40
-@@ -36,16 +27,12 @@ config ARCH_AT91RM9200
- select CPU_ARM920T
- select GENERIC_CLOCKEVENTS
- select HAVE_AT91_DBGU0
-- select HAVE_AT91_USART3
-
- config ARCH_AT91SAM9260
- bool "AT91SAM9260 or AT91SAM9XE"
- select CPU_ARM926T
- select GENERIC_CLOCKEVENTS
- select HAVE_AT91_DBGU0
-- select HAVE_AT91_USART3
-- select HAVE_AT91_USART4
-- select HAVE_AT91_USART5
- select HAVE_NET_MACB
-
- config ARCH_AT91SAM9261
-@@ -74,7 +61,6 @@ config ARCH_AT91SAM9RL
- bool "AT91SAM9RL"
- select CPU_ARM926T
- select GENERIC_CLOCKEVENTS
-- select HAVE_AT91_USART3
- select HAVE_FB_ATMEL
- select HAVE_AT91_DBGU0
-
-@@ -83,16 +69,12 @@ config ARCH_AT91SAM9G20
- select CPU_ARM926T
- select GENERIC_CLOCKEVENTS
- select HAVE_AT91_DBGU0
-- select HAVE_AT91_USART3
-- select HAVE_AT91_USART4
-- select HAVE_AT91_USART5
- select HAVE_NET_MACB
-
- config ARCH_AT91SAM9G45
- bool "AT91SAM9G45 or AT91SAM9M10 families"
- select CPU_ARM926T
- select GENERIC_CLOCKEVENTS
-- select HAVE_AT91_USART3
- select HAVE_FB_ATMEL
- select HAVE_NET_MACB
- select HAVE_AT91_DBGU1
-@@ -526,41 +508,6 @@ config AT91_TIMER_HZ
- system clock (of at least several MHz), rounding is less of a
- problem so it can be safer to use a decimal values like 100.
-
--choice
-- prompt "Select a UART for early kernel messages"
--
--config AT91_EARLY_DBGU0
-- bool "DBGU on rm9200, 9260/9g20, 9261/9g10, 9rl and 9x5"
-- depends on HAVE_AT91_DBGU0
--
--config AT91_EARLY_DBGU1
-- bool "DBGU on 9263 and 9g45"
-- depends on HAVE_AT91_DBGU1
--
--config AT91_EARLY_USART0
-- bool "USART0"
--
--config AT91_EARLY_USART1
-- bool "USART1"
--
--config AT91_EARLY_USART2
-- bool "USART2"
-- depends on ! ARCH_AT91X40
--
--config AT91_EARLY_USART3
-- bool "USART3"
-- depends on HAVE_AT91_USART3
--
--config AT91_EARLY_USART4
-- bool "USART4"
-- depends on HAVE_AT91_USART4
--
--config AT91_EARLY_USART5
-- bool "USART5"
-- depends on HAVE_AT91_USART5
--
--endchoice
--
- endmenu
-
- endif
-diff --git a/arch/arm/mach-at91/include/mach/at91rm9200.h b/arch/arm/mach-at91/include/mach/at91rm9200.h
-index 603e6aa..e67317c 100644
---- a/arch/arm/mach-at91/include/mach/at91rm9200.h
-+++ b/arch/arm/mach-at91/include/mach/at91rm9200.h
-@@ -88,11 +88,6 @@
- #define AT91RM9200_BASE_RTC 0xfffffe00 /* Real-Time Clock */
- #define AT91RM9200_BASE_MC 0xffffff00 /* Memory Controllers */
-
--#define AT91_USART0 AT91RM9200_BASE_US0
--#define AT91_USART1 AT91RM9200_BASE_US1
--#define AT91_USART2 AT91RM9200_BASE_US2
--#define AT91_USART3 AT91RM9200_BASE_US3
--
- /*
- * Internal Memory.
- */
-diff --git a/arch/arm/mach-at91/include/mach/at91sam9260.h b/arch/arm/mach-at91/include/mach/at91sam9260.h
-index 08ae9af..416c7b6 100644
---- a/arch/arm/mach-at91/include/mach/at91sam9260.h
-+++ b/arch/arm/mach-at91/include/mach/at91sam9260.h
-@@ -95,13 +95,6 @@
- #define AT91SAM9260_BASE_WDT 0xfffffd40
- #define AT91SAM9260_BASE_GPBR 0xfffffd50
-
--#define AT91_USART0 AT91SAM9260_BASE_US0
--#define AT91_USART1 AT91SAM9260_BASE_US1
--#define AT91_USART2 AT91SAM9260_BASE_US2
--#define AT91_USART3 AT91SAM9260_BASE_US3
--#define AT91_USART4 AT91SAM9260_BASE_US4
--#define AT91_USART5 AT91SAM9260_BASE_US5
--
-
- /*
- * Internal Memory.
-diff --git a/arch/arm/mach-at91/include/mach/at91sam9261.h b/arch/arm/mach-at91/include/mach/at91sam9261.h
-index 44fbdc1..a041406 100644
---- a/arch/arm/mach-at91/include/mach/at91sam9261.h
-+++ b/arch/arm/mach-at91/include/mach/at91sam9261.h
-@@ -79,10 +79,6 @@
- #define AT91SAM9261_BASE_WDT 0xfffffd40
- #define AT91SAM9261_BASE_GPBR 0xfffffd50
-
--#define AT91_USART0 AT91SAM9261_BASE_US0
--#define AT91_USART1 AT91SAM9261_BASE_US1
--#define AT91_USART2 AT91SAM9261_BASE_US2
--
-
- /*
- * Internal Memory.
-diff --git a/arch/arm/mach-at91/include/mach/at91sam9263.h b/arch/arm/mach-at91/include/mach/at91sam9263.h
-index d96cbb2..d201029 100644
---- a/arch/arm/mach-at91/include/mach/at91sam9263.h
-+++ b/arch/arm/mach-at91/include/mach/at91sam9263.h
-@@ -95,10 +95,6 @@
- #define AT91SAM9263_BASE_RTT1 0xfffffd50
- #define AT91SAM9263_BASE_GPBR 0xfffffd60
-
--#define AT91_USART0 AT91SAM9263_BASE_US0
--#define AT91_USART1 AT91SAM9263_BASE_US1
--#define AT91_USART2 AT91SAM9263_BASE_US2
--
- #define AT91_SMC AT91_SMC0
-
- /*
-diff --git a/arch/arm/mach-at91/include/mach/at91sam9g45.h b/arch/arm/mach-at91/include/mach/at91sam9g45.h
-index d052abc..3a4da24 100644
---- a/arch/arm/mach-at91/include/mach/at91sam9g45.h
-+++ b/arch/arm/mach-at91/include/mach/at91sam9g45.h
-@@ -106,11 +106,6 @@
- #define AT91SAM9G45_BASE_RTC 0xfffffdb0
- #define AT91SAM9G45_BASE_GPBR 0xfffffd60
-
--#define AT91_USART0 AT91SAM9G45_BASE_US0
--#define AT91_USART1 AT91SAM9G45_BASE_US1
--#define AT91_USART2 AT91SAM9G45_BASE_US2
--#define AT91_USART3 AT91SAM9G45_BASE_US3
--
- /*
- * Internal Memory.
- */
-diff --git a/arch/arm/mach-at91/include/mach/at91sam9rl.h b/arch/arm/mach-at91/include/mach/at91sam9rl.h
-index e0073eb..a15db56 100644
---- a/arch/arm/mach-at91/include/mach/at91sam9rl.h
-+++ b/arch/arm/mach-at91/include/mach/at91sam9rl.h
-@@ -89,11 +89,6 @@
- #define AT91SAM9RL_BASE_GPBR 0xfffffd60
- #define AT91SAM9RL_BASE_RTC 0xfffffe00
-
--#define AT91_USART0 AT91SAM9RL_BASE_US0
--#define AT91_USART1 AT91SAM9RL_BASE_US1
--#define AT91_USART2 AT91SAM9RL_BASE_US2
--#define AT91_USART3 AT91SAM9RL_BASE_US3
--
-
- /*
- * Internal Memory.
-diff --git a/arch/arm/mach-at91/include/mach/at91sam9x5.h b/arch/arm/mach-at91/include/mach/at91sam9x5.h
-index 88e43d5..c75ee19 100644
---- a/arch/arm/mach-at91/include/mach/at91sam9x5.h
-+++ b/arch/arm/mach-at91/include/mach/at91sam9x5.h
-@@ -55,14 +55,6 @@
- #define AT91SAM9X5_BASE_USART2 0xf8024000
-
- /*
-- * Base addresses for early serial code (uncompress.h)
-- */
--#define AT91_DBGU AT91_BASE_DBGU0
--#define AT91_USART0 AT91SAM9X5_BASE_USART0
--#define AT91_USART1 AT91SAM9X5_BASE_USART1
--#define AT91_USART2 AT91SAM9X5_BASE_USART2
--
--/*
- * Internal Memory.
- */
- #define AT91SAM9X5_SRAM_BASE 0x00300000 /* Internal SRAM base address */
-diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h
-index e9e29a6..3a01f8f 100644
---- a/arch/arm/mach-at91/include/mach/hardware.h
-+++ b/arch/arm/mach-at91/include/mach/hardware.h
-@@ -22,27 +22,17 @@
- /* 9263, 9g45 */
- #define AT91_BASE_DBGU1 0xffffee00
-
--#if defined(CONFIG_ARCH_AT91RM9200)
-+#if defined(CONFIG_ARCH_AT91X40)
-+#include <mach/at91x40.h>
-+#else
- #include <mach/at91rm9200.h>
--#elif defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
- #include <mach/at91sam9260.h>
--#elif defined(CONFIG_ARCH_AT91SAM9261) || defined(CONFIG_ARCH_AT91SAM9G10)
- #include <mach/at91sam9261.h>
--#elif defined(CONFIG_ARCH_AT91SAM9263)
- #include <mach/at91sam9263.h>
--#elif defined(CONFIG_ARCH_AT91SAM9RL)
- #include <mach/at91sam9rl.h>
--#elif defined(CONFIG_ARCH_AT91SAM9G45)
- #include <mach/at91sam9g45.h>
--#elif defined(CONFIG_ARCH_AT91SAM9X5)
- #include <mach/at91sam9x5.h>
--#elif defined(CONFIG_ARCH_AT91X40)
--#include <mach/at91x40.h>
--#else
--#error "Unsupported AT91 processor"
--#endif
-
--#if !defined(CONFIG_ARCH_AT91X40)
- /*
- * On all at91 except rm9200 and x40 have the System Controller starts
- * at address 0xffffc000 and has a size of 16KiB.
-diff --git a/arch/arm/mach-at91/include/mach/uncompress.h b/arch/arm/mach-at91/include/mach/uncompress.h
-index d985af7..6f6118d 100644
---- a/arch/arm/mach-at91/include/mach/uncompress.h
-+++ b/arch/arm/mach-at91/include/mach/uncompress.h
-@@ -1,7 +1,8 @@
- /*
- * arch/arm/mach-at91/include/mach/uncompress.h
- *
-- * Copyright (C) 2003 SAN People
-+ * Copyright (C) 2003 SAN People
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -25,32 +26,149 @@
- #include <linux/atmel_serial.h>
- #include <mach/hardware.h>
-
--#if defined(CONFIG_AT91_EARLY_DBGU0)
--#define UART_OFFSET AT91_BASE_DBGU0
--#elif defined(CONFIG_AT91_EARLY_DBGU1)
--#define UART_OFFSET AT91_BASE_DBGU1
--#elif defined(CONFIG_AT91_EARLY_USART0)
--#define UART_OFFSET AT91_USART0
--#elif defined(CONFIG_AT91_EARLY_USART1)
--#define UART_OFFSET AT91_USART1
--#elif defined(CONFIG_AT91_EARLY_USART2)
--#define UART_OFFSET AT91_USART2
--#elif defined(CONFIG_AT91_EARLY_USART3)
--#define UART_OFFSET AT91_USART3
--#elif defined(CONFIG_AT91_EARLY_USART4)
--#define UART_OFFSET AT91_USART4
--#elif defined(CONFIG_AT91_EARLY_USART5)
--#define UART_OFFSET AT91_USART5
--#endif
-+#include <mach/at91_dbgu.h>
-+#include <mach/cpu.h>
-
- void __iomem *at91_uart;
-
-+#if !defined(CONFIG_ARCH_AT91X40)
-+static const u32 uarts_rm9200[] = {
-+ AT91_BASE_DBGU0,
-+ AT91RM9200_BASE_US0,
-+ AT91RM9200_BASE_US1,
-+ AT91RM9200_BASE_US2,
-+ AT91RM9200_BASE_US3,
-+ 0,
-+};
-+
-+static const u32 uarts_sam9260[] = {
-+ AT91_BASE_DBGU0,
-+ AT91SAM9260_BASE_US0,
-+ AT91SAM9260_BASE_US1,
-+ AT91SAM9260_BASE_US2,
-+ AT91SAM9260_BASE_US3,
-+ AT91SAM9260_BASE_US4,
-+ AT91SAM9260_BASE_US5,
-+ 0,
-+};
-+
-+static const u32 uarts_sam9261[] = {
-+ AT91_BASE_DBGU0,
-+ AT91SAM9261_BASE_US0,
-+ AT91SAM9261_BASE_US1,
-+ AT91SAM9261_BASE_US2,
-+ 0,
-+};
-+
-+static const u32 uarts_sam9263[] = {
-+ AT91_BASE_DBGU1,
-+ AT91SAM9263_BASE_US0,
-+ AT91SAM9263_BASE_US1,
-+ AT91SAM9263_BASE_US2,
-+ 0,
-+};
-+
-+static const u32 uarts_sam9g45[] = {
-+ AT91_BASE_DBGU1,
-+ AT91SAM9G45_BASE_US0,
-+ AT91SAM9G45_BASE_US1,
-+ AT91SAM9G45_BASE_US2,
-+ AT91SAM9G45_BASE_US3,
-+ 0,
-+};
-+
-+static const u32 uarts_sam9rl[] = {
-+ AT91_BASE_DBGU0,
-+ AT91SAM9RL_BASE_US0,
-+ AT91SAM9RL_BASE_US1,
-+ AT91SAM9RL_BASE_US2,
-+ AT91SAM9RL_BASE_US3,
-+ 0,
-+};
-+
-+static const u32 uarts_sam9x5[] = {
-+ AT91_BASE_DBGU0,
-+ AT91SAM9X5_BASE_USART0,
-+ AT91SAM9X5_BASE_USART1,
-+ AT91SAM9X5_BASE_USART2,
-+ 0,
-+};
-+
-+static inline const u32* decomp_soc_detect(u32 dbgu_base)
-+{
-+ u32 cidr, socid;
-+
-+ cidr = __raw_readl(dbgu_base + AT91_DBGU_CIDR);
-+ socid = cidr & ~AT91_CIDR_VERSION;
-+
-+ switch (socid) {
-+ case ARCH_ID_AT91RM9200:
-+ return uarts_rm9200;
-+
-+ case ARCH_ID_AT91SAM9G20:
-+ case ARCH_ID_AT91SAM9260:
-+ return uarts_sam9260;
-+
-+ case ARCH_ID_AT91SAM9261:
-+ return uarts_sam9261;
-+
-+ case ARCH_ID_AT91SAM9263:
-+ return uarts_sam9263;
-+
-+ case ARCH_ID_AT91SAM9G45:
-+ return uarts_sam9g45;
-+
-+ case ARCH_ID_AT91SAM9RL64:
-+ return uarts_sam9rl;
-+
-+ case ARCH_ID_AT91SAM9X5:
-+ return uarts_sam9x5;
-+ }
-+
-+ /* at91sam9g10 */
-+ if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
-+ return uarts_sam9261;
-+ }
-+ /* at91sam9xe */
-+ else if ((cidr & AT91_CIDR_ARCH) == ARCH_FAMILY_AT91SAM9XE) {
-+ return uarts_sam9260;
-+ }
-+
-+ return NULL;
-+}
-+
- static inline void arch_decomp_setup(void)
- {
--#ifdef UART_OFFSET
-- at91_uart = (void __iomem *) UART_OFFSET; /* physical address */
--#endif
-+ int i = 0;
-+ const u32* usarts;
-+
-+ usarts = decomp_soc_detect(AT91_BASE_DBGU0);
-+
-+ if (!usarts)
-+ usarts = decomp_soc_detect(AT91_BASE_DBGU1);
-+ if (!usarts) {
-+ at91_uart = NULL;
-+ return;
-+ }
-+
-+ do {
-+ /* physical address */
-+ at91_uart = (void __iomem *)usarts[i];
-+
-+ if (__raw_readl(at91_uart + ATMEL_US_BRGR))
-+ return;
-+ i++;
-+ } while (usarts[i]);
-+
-+ at91_uart = NULL;
- }
-+#else
-+static inline void arch_decomp_setup(void)
-+{
-+ at91_uart = NULL;
-+}
-+#endif
-+
- /*
- * The following code assumes the serial port has already been
- * initialized by the bootloader. If you didn't setup a port in
-@@ -60,20 +178,22 @@ static inline void arch_decomp_setup(void)
- */
- static void putc(int c)
- {
--#ifdef UART_OFFSET
-+ if (!at91_uart)
-+ return;
-+
- while (!(__raw_readl(at91_uart + ATMEL_US_CSR) & ATMEL_US_TXRDY))
- barrier();
- __raw_writel(c, at91_uart + ATMEL_US_THR);
--#endif
- }
-
- static inline void flush(void)
- {
--#ifdef UART_OFFSET
-+ if (!at91_uart)
-+ return;
-+
- /* wait for transmission to complete */
- while (!(__raw_readl(at91_uart + ATMEL_US_CSR) & ATMEL_US_TXEMPTY))
- barrier();
--#endif
- }
-
- #define arch_decomp_wdog()
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From bfb9a880b47717d96c83725f5134f1b24fc43550 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Thu, 5 Apr 2012 13:43:40 +0800
-Subject: ARM: at91: drop at91_set_serial_console
-
-commit a27fa58117ae1161adefedde449e5a71b3c593a4 upstream.
-
-at91_set_serial_console is used to define the default console of linux.
-This is already manage by the cmdline. And if the boot loader can not be
-modified you can still set it by enabling the CONFIG_CMDLINE_EXTEND option.
-And then the command-line arguments provided by the boot loader will be
-appended to the default kernel command string.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/at91rm9200.c | 12 ------------
- arch/arm/mach-at91/at91rm9200_devices.c | 12 ------------
- arch/arm/mach-at91/at91sam9260.c | 12 ------------
- arch/arm/mach-at91/at91sam9260_devices.c | 12 ------------
- arch/arm/mach-at91/at91sam9261.c | 12 ------------
- arch/arm/mach-at91/at91sam9261_devices.c | 12 ------------
- arch/arm/mach-at91/at91sam9263.c | 12 ------------
- arch/arm/mach-at91/at91sam9263_devices.c | 12 ------------
- arch/arm/mach-at91/at91sam9g45.c | 12 ------------
- arch/arm/mach-at91/at91sam9g45_devices.c | 12 ------------
- arch/arm/mach-at91/at91sam9rl.c | 12 ------------
- arch/arm/mach-at91/at91sam9rl_devices.c | 12 ------------
- arch/arm/mach-at91/board-1arm.c | 3 ---
- arch/arm/mach-at91/board-afeb-9260v1.c | 3 ---
- arch/arm/mach-at91/board-cam60.c | 3 ---
- arch/arm/mach-at91/board-carmeva.c | 3 ---
- arch/arm/mach-at91/board-cpu9krea.c | 3 ---
- arch/arm/mach-at91/board-cpuat91.c | 3 ---
- arch/arm/mach-at91/board-csb337.c | 3 ---
- arch/arm/mach-at91/board-csb637.c | 3 ---
- arch/arm/mach-at91/board-eb9200.c | 3 ---
- arch/arm/mach-at91/board-ecbat91.c | 3 ---
- arch/arm/mach-at91/board-eco920.c | 3 ---
- arch/arm/mach-at91/board-flexibity.c | 3 ---
- arch/arm/mach-at91/board-foxg20.c | 3 ---
- arch/arm/mach-at91/board-kafa.c | 3 ---
- arch/arm/mach-at91/board-kb9202.c | 3 ---
- arch/arm/mach-at91/board-neocore926.c | 3 ---
- arch/arm/mach-at91/board-picotux200.c | 3 ---
- arch/arm/mach-at91/board-qil-a9260.c | 4 ----
- arch/arm/mach-at91/board-rm9200dk.c | 3 ---
- arch/arm/mach-at91/board-rm9200ek.c | 3 ---
- arch/arm/mach-at91/board-rsi-ews.c | 3 ---
- arch/arm/mach-at91/board-sam9-l9260.c | 3 ---
- arch/arm/mach-at91/board-sam9260ek.c | 3 ---
- arch/arm/mach-at91/board-sam9261ek.c | 3 ---
- arch/arm/mach-at91/board-sam9263ek.c | 3 ---
- arch/arm/mach-at91/board-sam9g20ek.c | 3 ---
- arch/arm/mach-at91/board-sam9m10g45ek.c | 3 ---
- arch/arm/mach-at91/board-sam9rlek.c | 3 ---
- arch/arm/mach-at91/board-snapper9260.c | 1 -
- arch/arm/mach-at91/board-stamp9g20.c | 3 ---
- arch/arm/mach-at91/board-usb-a926x.c | 3 ---
- arch/arm/mach-at91/board-yl-9200.c | 3 ---
- arch/arm/mach-at91/generic.h | 11 -----------
- arch/arm/mach-at91/include/mach/board.h | 1 -
- 46 files changed, 251 deletions(-)
-
-diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
-index 364c193..d50da1a 100644
---- a/arch/arm/mach-at91/at91rm9200.c
-+++ b/arch/arm/mach-at91/at91rm9200.c
-@@ -258,18 +258,6 @@ static void __init at91rm9200_register_clocks(void)
- clk_register(&pck3);
- }
-
--static struct clk_lookup console_clock_lookup;
--
--void __init at91rm9200_set_console_clock(int id)
--{
-- if (id >= ARRAY_SIZE(usart_clocks_lookups))
-- return;
--
-- console_clock_lookup.con_id = "usart";
-- console_clock_lookup.clk = usart_clocks_lookups[id].clk;
-- clkdev_add(&console_clock_lookup);
--}
--
- /* --------------------------------------------------------------------
- * GPIO
- * -------------------------------------------------------------------- */
-diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
-index 05774e5..99affb5 100644
---- a/arch/arm/mach-at91/at91rm9200_devices.c
-+++ b/arch/arm/mach-at91/at91rm9200_devices.c
-@@ -1152,14 +1152,6 @@ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
- at91_uarts[portnr] = pdev;
- }
-
--void __init at91_set_serial_console(unsigned portnr)
--{
-- if (portnr < ATMEL_MAX_UART) {
-- atmel_default_console_device = at91_uarts[portnr];
-- at91rm9200_set_console_clock(at91_uarts[portnr]->id);
-- }
--}
--
- void __init at91_add_device_serial(void)
- {
- int i;
-@@ -1168,13 +1160,9 @@ void __init at91_add_device_serial(void)
- if (at91_uarts[i])
- platform_device_register(at91_uarts[i]);
- }
--
-- if (!atmel_default_console_device)
-- printk(KERN_INFO "AT91: No default serial console defined.\n");
- }
- #else
- void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
--void __init at91_set_serial_console(unsigned portnr) {}
- void __init at91_add_device_serial(void) {}
- #endif
-
-diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
-index 46f7742..a27bbec 100644
---- a/arch/arm/mach-at91/at91sam9260.c
-+++ b/arch/arm/mach-at91/at91sam9260.c
-@@ -268,18 +268,6 @@ static void __init at91sam9260_register_clocks(void)
- clk_register(&pck1);
- }
-
--static struct clk_lookup console_clock_lookup;
--
--void __init at91sam9260_set_console_clock(int id)
--{
-- if (id >= ARRAY_SIZE(usart_clocks_lookups))
-- return;
--
-- console_clock_lookup.con_id = "usart";
-- console_clock_lookup.clk = usart_clocks_lookups[id].clk;
-- clkdev_add(&console_clock_lookup);
--}
--
- /* --------------------------------------------------------------------
- * GPIO
- * -------------------------------------------------------------------- */
-diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
-index 5652dde..ad00fe9 100644
---- a/arch/arm/mach-at91/at91sam9260_devices.c
-+++ b/arch/arm/mach-at91/at91sam9260_devices.c
-@@ -1229,14 +1229,6 @@ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
- at91_uarts[portnr] = pdev;
- }
-
--void __init at91_set_serial_console(unsigned portnr)
--{
-- if (portnr < ATMEL_MAX_UART) {
-- atmel_default_console_device = at91_uarts[portnr];
-- at91sam9260_set_console_clock(at91_uarts[portnr]->id);
-- }
--}
--
- void __init at91_add_device_serial(void)
- {
- int i;
-@@ -1245,13 +1237,9 @@ void __init at91_add_device_serial(void)
- if (at91_uarts[i])
- platform_device_register(at91_uarts[i]);
- }
--
-- if (!atmel_default_console_device)
-- printk(KERN_INFO "AT91: No default serial console defined.\n");
- }
- #else
- void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
--void __init at91_set_serial_console(unsigned portnr) {}
- void __init at91_add_device_serial(void) {}
- #endif
-
-diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
-index 7de81e6..c77d503 100644
---- a/arch/arm/mach-at91/at91sam9261.c
-+++ b/arch/arm/mach-at91/at91sam9261.c
-@@ -239,18 +239,6 @@ static void __init at91sam9261_register_clocks(void)
- clk_register(&hck1);
- }
-
--static struct clk_lookup console_clock_lookup;
--
--void __init at91sam9261_set_console_clock(int id)
--{
-- if (id >= ARRAY_SIZE(usart_clocks_lookups))
-- return;
--
-- console_clock_lookup.con_id = "usart";
-- console_clock_lookup.clk = usart_clocks_lookups[id].clk;
-- clkdev_add(&console_clock_lookup);
--}
--
- /* --------------------------------------------------------------------
- * GPIO
- * -------------------------------------------------------------------- */
-diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
-index 4db961a..9295e90 100644
---- a/arch/arm/mach-at91/at91sam9261_devices.c
-+++ b/arch/arm/mach-at91/at91sam9261_devices.c
-@@ -1051,14 +1051,6 @@ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
- at91_uarts[portnr] = pdev;
- }
-
--void __init at91_set_serial_console(unsigned portnr)
--{
-- if (portnr < ATMEL_MAX_UART) {
-- atmel_default_console_device = at91_uarts[portnr];
-- at91sam9261_set_console_clock(at91_uarts[portnr]->id);
-- }
--}
--
- void __init at91_add_device_serial(void)
- {
- int i;
-@@ -1067,13 +1059,9 @@ void __init at91_add_device_serial(void)
- if (at91_uarts[i])
- platform_device_register(at91_uarts[i]);
- }
--
-- if (!atmel_default_console_device)
-- printk(KERN_INFO "AT91: No default serial console defined.\n");
- }
- #else
- void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
--void __init at91_set_serial_console(unsigned portnr) {}
- void __init at91_add_device_serial(void) {}
- #endif
-
-diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
-index ef301be..7fae365 100644
---- a/arch/arm/mach-at91/at91sam9263.c
-+++ b/arch/arm/mach-at91/at91sam9263.c
-@@ -255,18 +255,6 @@ static void __init at91sam9263_register_clocks(void)
- clk_register(&pck3);
- }
-
--static struct clk_lookup console_clock_lookup;
--
--void __init at91sam9263_set_console_clock(int id)
--{
-- if (id >= ARRAY_SIZE(usart_clocks_lookups))
-- return;
--
-- console_clock_lookup.con_id = "usart";
-- console_clock_lookup.clk = usart_clocks_lookups[id].clk;
-- clkdev_add(&console_clock_lookup);
--}
--
- /* --------------------------------------------------------------------
- * GPIO
- * -------------------------------------------------------------------- */
-diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
-index fe99206..dfe5bc0 100644
---- a/arch/arm/mach-at91/at91sam9263_devices.c
-+++ b/arch/arm/mach-at91/at91sam9263_devices.c
-@@ -1461,14 +1461,6 @@ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
- at91_uarts[portnr] = pdev;
- }
-
--void __init at91_set_serial_console(unsigned portnr)
--{
-- if (portnr < ATMEL_MAX_UART) {
-- atmel_default_console_device = at91_uarts[portnr];
-- at91sam9263_set_console_clock(at91_uarts[portnr]->id);
-- }
--}
--
- void __init at91_add_device_serial(void)
- {
- int i;
-@@ -1477,13 +1469,9 @@ void __init at91_add_device_serial(void)
- if (at91_uarts[i])
- platform_device_register(at91_uarts[i]);
- }
--
-- if (!atmel_default_console_device)
-- printk(KERN_INFO "AT91: No default serial console defined.\n");
- }
- #else
- void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
--void __init at91_set_serial_console(unsigned portnr) {}
- void __init at91_add_device_serial(void) {}
- #endif
-
-diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
-index d222f83..f205449 100644
---- a/arch/arm/mach-at91/at91sam9g45.c
-+++ b/arch/arm/mach-at91/at91sam9g45.c
-@@ -288,18 +288,6 @@ static void __init at91sam9g45_register_clocks(void)
- clk_register(&pck1);
- }
-
--static struct clk_lookup console_clock_lookup;
--
--void __init at91sam9g45_set_console_clock(int id)
--{
-- if (id >= ARRAY_SIZE(usart_clocks_lookups))
-- return;
--
-- console_clock_lookup.con_id = "usart";
-- console_clock_lookup.clk = usart_clocks_lookups[id].clk;
-- clkdev_add(&console_clock_lookup);
--}
--
- /* --------------------------------------------------------------------
- * GPIO
- * -------------------------------------------------------------------- */
-diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
-index 6b008ae..db2f88c2 100644
---- a/arch/arm/mach-at91/at91sam9g45_devices.c
-+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
-@@ -1741,14 +1741,6 @@ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
- at91_uarts[portnr] = pdev;
- }
-
--void __init at91_set_serial_console(unsigned portnr)
--{
-- if (portnr < ATMEL_MAX_UART) {
-- atmel_default_console_device = at91_uarts[portnr];
-- at91sam9g45_set_console_clock(at91_uarts[portnr]->id);
-- }
--}
--
- void __init at91_add_device_serial(void)
- {
- int i;
-@@ -1757,13 +1749,9 @@ void __init at91_add_device_serial(void)
- if (at91_uarts[i])
- platform_device_register(at91_uarts[i]);
- }
--
-- if (!atmel_default_console_device)
-- printk(KERN_INFO "AT91: No default serial console defined.\n");
- }
- #else
- void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
--void __init at91_set_serial_console(unsigned portnr) {}
- void __init at91_add_device_serial(void) {}
- #endif
-
-diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
-index d9f2774..e420085 100644
---- a/arch/arm/mach-at91/at91sam9rl.c
-+++ b/arch/arm/mach-at91/at91sam9rl.c
-@@ -232,18 +232,6 @@ static void __init at91sam9rl_register_clocks(void)
- clk_register(&pck1);
- }
-
--static struct clk_lookup console_clock_lookup;
--
--void __init at91sam9rl_set_console_clock(int id)
--{
-- if (id >= ARRAY_SIZE(usart_clocks_lookups))
-- return;
--
-- console_clock_lookup.con_id = "usart";
-- console_clock_lookup.clk = usart_clocks_lookups[id].clk;
-- clkdev_add(&console_clock_lookup);
--}
--
- /* --------------------------------------------------------------------
- * GPIO
- * -------------------------------------------------------------------- */
-diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
-index fe4ae22..9c0b148 100644
---- a/arch/arm/mach-at91/at91sam9rl_devices.c
-+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
-@@ -1192,14 +1192,6 @@ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
- at91_uarts[portnr] = pdev;
- }
-
--void __init at91_set_serial_console(unsigned portnr)
--{
-- if (portnr < ATMEL_MAX_UART) {
-- atmel_default_console_device = at91_uarts[portnr];
-- at91sam9rl_set_console_clock(at91_uarts[portnr]->id);
-- }
--}
--
- void __init at91_add_device_serial(void)
- {
- int i;
-@@ -1208,13 +1200,9 @@ void __init at91_add_device_serial(void)
- if (at91_uarts[i])
- platform_device_register(at91_uarts[i]);
- }
--
-- if (!atmel_default_console_device)
-- printk(KERN_INFO "AT91: No default serial console defined.\n");
- }
- #else
- void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
--void __init at91_set_serial_console(unsigned portnr) {}
- void __init at91_add_device_serial(void) {}
- #endif
-
-diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
-index 2628384..f43ad91 100644
---- a/arch/arm/mach-at91/board-1arm.c
-+++ b/arch/arm/mach-at91/board-1arm.c
-@@ -58,9 +58,6 @@ static void __init onearm_init_early(void)
- at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- static struct macb_platform_data __initdata onearm_eth_data = {
-diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
-index 161efba..7c7c682 100644
---- a/arch/arm/mach-at91/board-afeb-9260v1.c
-+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
-@@ -65,9 +65,6 @@ static void __init afeb9260_init_early(void)
- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9260_ID_US1, 2,
- ATMEL_UART_CTS | ATMEL_UART_RTS);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- /*
-diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
-index c6d44ee..871717d 100644
---- a/arch/arm/mach-at91/board-cam60.c
-+++ b/arch/arm/mach-at91/board-cam60.c
-@@ -52,9 +52,6 @@ static void __init cam60_init_early(void)
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- /*
-diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
-index 59d9cf9..168b3fa 100644
---- a/arch/arm/mach-at91/board-carmeva.c
-+++ b/arch/arm/mach-at91/board-carmeva.c
-@@ -52,9 +52,6 @@ static void __init carmeva_init_early(void)
- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- static struct macb_platform_data __initdata carmeva_eth_data = {
-diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
-index 5f3680e..4073e30 100644
---- a/arch/arm/mach-at91/board-cpu9krea.c
-+++ b/arch/arm/mach-at91/board-cpu9krea.c
-@@ -77,9 +77,6 @@ static void __init cpu9krea_init_early(void)
-
- /* USART5 on ttyS6. (Rx, Tx) */
- at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- /*
-diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
-index e094cc8..76c62ed 100644
---- a/arch/arm/mach-at91/board-cpuat91.c
-+++ b/arch/arm/mach-at91/board-cpuat91.c
-@@ -78,9 +78,6 @@ static void __init cpuat91_init_early(void)
- /* USART3 on ttyS4 (Rx, Tx, CTS, RTS) */
- at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_CTS |
- ATMEL_UART_RTS);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- static struct macb_platform_data __initdata cpuat91_eth_data = {
-diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
-index 1a1547b..d984435 100644
---- a/arch/arm/mach-at91/board-csb337.c
-+++ b/arch/arm/mach-at91/board-csb337.c
-@@ -53,9 +53,6 @@ static void __init csb337_init_early(void)
-
- /* DBGU on ttyS0 */
- at91_register_uart(0, 0, 0);
--
-- /* make console=ttyS0 the default */
-- at91_set_serial_console(0);
- }
-
- static struct macb_platform_data __initdata csb337_eth_data = {
-diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
-index f650bf3..0c9935d 100644
---- a/arch/arm/mach-at91/board-csb637.c
-+++ b/arch/arm/mach-at91/board-csb637.c
-@@ -47,9 +47,6 @@ static void __init csb637_init_early(void)
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
--
-- /* make console=ttyS0 (ie, DBGU) the default */
-- at91_set_serial_console(0);
- }
-
- static struct macb_platform_data __initdata csb637_eth_data = {
-diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
-index d302ca3..a189b9f 100644
---- a/arch/arm/mach-at91/board-eb9200.c
-+++ b/arch/arm/mach-at91/board-eb9200.c
-@@ -55,9 +55,6 @@ static void __init eb9200_init_early(void)
-
- /* USART2 on ttyS2. (Rx, Tx) - IRDA */
- at91_register_uart(AT91RM9200_ID_US2, 2, 0);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- static struct macb_platform_data __initdata eb9200_eth_data = {
-diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
-index 69966ce..307c530 100644
---- a/arch/arm/mach-at91/board-ecbat91.c
-+++ b/arch/arm/mach-at91/board-ecbat91.c
-@@ -59,9 +59,6 @@ static void __init ecb_at91init_early(void)
-
- /* USART0 on ttyS1. (Rx & Tx only) */
- at91_register_uart(AT91RM9200_ID_US0, 1, 0);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- static struct macb_platform_data __initdata ecb_at91eth_data = {
-diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c
-index f23aabe..7df6a9b 100644
---- a/arch/arm/mach-at91/board-eco920.c
-+++ b/arch/arm/mach-at91/board-eco920.c
-@@ -43,9 +43,6 @@ static void __init eco920_init_early(void)
-
- /* DBGU on ttyS0. (Rx & Tx only */
- at91_register_uart(0, 0, 0);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- static struct macb_platform_data __initdata eco920_eth_data = {
-diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
-index 1815152..6dcc962 100644
---- a/arch/arm/mach-at91/board-flexibity.c
-+++ b/arch/arm/mach-at91/board-flexibity.c
-@@ -44,9 +44,6 @@ static void __init flexibity_init_early(void)
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- /* USB Host port */
-diff --git a/arch/arm/mach-at91/board-foxg20.c b/arch/arm/mach-at91/board-foxg20.c
-index caf017f..bb07807 100644
---- a/arch/arm/mach-at91/board-foxg20.c
-+++ b/arch/arm/mach-at91/board-foxg20.c
-@@ -93,9 +93,6 @@ static void __init foxg20_init_early(void)
- /* USART5 on ttyS6. (Rx & Tx only) */
- at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
-
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
--
- /* Set the internal pull-up resistor on DRXD */
- at91_set_A_periph(AT91_PIN_PB14, 1);
-
-diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
-index efde1b2..3e858ed 100644
---- a/arch/arm/mach-at91/board-kafa.c
-+++ b/arch/arm/mach-at91/board-kafa.c
-@@ -56,9 +56,6 @@ static void __init kafa_init_early(void)
-
- /* USART0 on ttyS1 (Rx, Tx, CTS, RTS) */
- at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- static struct macb_platform_data __initdata kafa_eth_data = {
-diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
-index 59b92aa..ccbc8be 100644
---- a/arch/arm/mach-at91/board-kb9202.c
-+++ b/arch/arm/mach-at91/board-kb9202.c
-@@ -65,9 +65,6 @@ static void __init kb9202_init_early(void)
-
- /* USART3 on ttyS3 (Rx, Tx, CTS, RTS) - RS485 (optional) */
- at91_register_uart(AT91RM9200_ID_US3, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- static struct macb_platform_data __initdata kb9202_eth_data = {
-diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
-index 57d5f6a..c456fdc 100644
---- a/arch/arm/mach-at91/board-neocore926.c
-+++ b/arch/arm/mach-at91/board-neocore926.c
-@@ -61,9 +61,6 @@ static void __init neocore926_init_early(void)
-
- /* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- /*
-diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
-index 59e35dd..4ca56cd 100644
---- a/arch/arm/mach-at91/board-picotux200.c
-+++ b/arch/arm/mach-at91/board-picotux200.c
-@@ -56,9 +56,6 @@ static void __init picotux200_init_early(void)
- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- static struct macb_platform_data __initdata picotux200_eth_data = {
-diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
-index b6ed5ed..189d3fe 100644
---- a/arch/arm/mach-at91/board-qil-a9260.c
-+++ b/arch/arm/mach-at91/board-qil-a9260.c
-@@ -66,10 +66,6 @@ static void __init ek_init_early(void)
-
- /* USART2 on ttyS3. (Rx, Tx, CTS, RTS) */
- at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
--
-- /* set serial console to ttyS1 (ie, USART0) */
-- at91_set_serial_console(1);
--
- }
-
- /*
-diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c
-index 01332aa..d5ce630 100644
---- a/arch/arm/mach-at91/board-rm9200dk.c
-+++ b/arch/arm/mach-at91/board-rm9200dk.c
-@@ -61,9 +61,6 @@ static void __init dk_init_early(void)
- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- static struct macb_platform_data __initdata dk_eth_data = {
-diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
-index b2e4fe2..e96d5f5 100644
---- a/arch/arm/mach-at91/board-rm9200ek.c
-+++ b/arch/arm/mach-at91/board-rm9200ek.c
-@@ -61,9 +61,6 @@ static void __init ek_init_early(void)
- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- static struct macb_platform_data __initdata ek_eth_data = {
-diff --git a/arch/arm/mach-at91/board-rsi-ews.c b/arch/arm/mach-at91/board-rsi-ews.c
-index af0750f..2c84463 100644
---- a/arch/arm/mach-at91/board-rsi-ews.c
-+++ b/arch/arm/mach-at91/board-rsi-ews.c
-@@ -52,9 +52,6 @@ static void __init rsi_ews_init_early(void)
- /* USART3 on ttyS4. (Rx, Tx, RTS) */
- /* RS485 communication */
- at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_RTS);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- /*
-diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
-index e8b116b..dee44cb 100644
---- a/arch/arm/mach-at91/board-sam9-l9260.c
-+++ b/arch/arm/mach-at91/board-sam9-l9260.c
-@@ -62,9 +62,6 @@ static void __init ek_init_early(void)
-
- /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- /*
-diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
-index d5aec55..6da17b5 100644
---- a/arch/arm/mach-at91/board-sam9260ek.c
-+++ b/arch/arm/mach-at91/board-sam9260ek.c
-@@ -65,9 +65,6 @@ static void __init ek_init_early(void)
-
- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- /*
-diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
-index 065fed3..950c20b 100644
---- a/arch/arm/mach-at91/board-sam9261ek.c
-+++ b/arch/arm/mach-at91/board-sam9261ek.c
-@@ -64,9 +64,6 @@ static void __init ek_init_early(void)
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- /*
-diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
-index 2ffe50f..4424873 100644
---- a/arch/arm/mach-at91/board-sam9263ek.c
-+++ b/arch/arm/mach-at91/board-sam9263ek.c
-@@ -63,9 +63,6 @@ static void __init ek_init_early(void)
-
- /* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- /*
-diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
-index 8923ec9..05f8467 100644
---- a/arch/arm/mach-at91/board-sam9g20ek.c
-+++ b/arch/arm/mach-at91/board-sam9g20ek.c
-@@ -76,9 +76,6 @@ static void __init ek_init_early(void)
-
- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- /*
-diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
-index c88e908..be2ca19 100644
---- a/arch/arm/mach-at91/board-sam9m10g45ek.c
-+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
-@@ -60,9 +60,6 @@ static void __init ek_init_early(void)
- /* USART0 not connected on the -EK board */
- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9G45_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- /*
-diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
-index b109ce2..23f383a 100644
---- a/arch/arm/mach-at91/board-sam9rlek.c
-+++ b/arch/arm/mach-at91/board-sam9rlek.c
-@@ -48,9 +48,6 @@ static void __init ek_init_early(void)
-
- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */
- at91_register_uart(AT91SAM9RL_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- /*
-diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
-index ebc9d01..1a6774a 100644
---- a/arch/arm/mach-at91/board-snapper9260.c
-+++ b/arch/arm/mach-at91/board-snapper9260.c
-@@ -46,7 +46,6 @@ static void __init snapper9260_init_early(void)
-
- /* Debug on ttyS0 */
- at91_register_uart(0, 0, 0);
-- at91_set_serial_console(0);
-
- at91_register_uart(AT91SAM9260_ID_US0, 1,
- ATMEL_UART_CTS | ATMEL_UART_RTS);
-diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
-index 7640049..38a7ca5 100644
---- a/arch/arm/mach-at91/board-stamp9g20.c
-+++ b/arch/arm/mach-at91/board-stamp9g20.c
-@@ -39,9 +39,6 @@ void __init stamp9g20_init_early(void)
-
- /* DGBU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- static void __init stamp9g20evb_init_early(void)
-diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c
-index b7483a3..ee482eb 100644
---- a/arch/arm/mach-at91/board-usb-a926x.c
-+++ b/arch/arm/mach-at91/board-usb-a926x.c
-@@ -56,9 +56,6 @@ static void __init ek_init_early(void)
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- /*
-diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
-index 38dd279..e94a04e 100644
---- a/arch/arm/mach-at91/board-yl-9200.c
-+++ b/arch/arm/mach-at91/board-yl-9200.c
-@@ -75,9 +75,6 @@ static void __init yl9200_init_early(void)
-
- /* USART3 on ttyS3. (Rx, Tx, RTS - RS485 interface) */
- at91_register_uart(AT91RM9200_ID_US3, 3, ATMEL_UART_RTS);
--
-- /* set serial console to ttyS0 (ie, DBGU) */
-- at91_set_serial_console(0);
- }
-
- /*
-diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
-index dd9b346..0a60bf8 100644
---- a/arch/arm/mach-at91/generic.h
-+++ b/arch/arm/mach-at91/generic.h
-@@ -40,17 +40,6 @@ extern struct sys_timer at91sam926x_timer;
- extern struct sys_timer at91x40_timer;
-
- /* Clocks */
--/*
-- * function to specify the clock of the default console. As we do not
-- * use the device/driver bus, the dev_name is not intialize. So we need
-- * to link the clock to a specific con_id only "usart"
-- */
--extern void __init at91rm9200_set_console_clock(int id);
--extern void __init at91sam9260_set_console_clock(int id);
--extern void __init at91sam9261_set_console_clock(int id);
--extern void __init at91sam9263_set_console_clock(int id);
--extern void __init at91sam9rl_set_console_clock(int id);
--extern void __init at91sam9g45_set_console_clock(int id);
- #ifdef CONFIG_AT91_PMC_UNIT
- extern int __init at91_clock_init(unsigned long main_clock);
- extern int __init at91_dt_clock_init(void);
-diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
-index 49a8211..369afc2 100644
---- a/arch/arm/mach-at91/include/mach/board.h
-+++ b/arch/arm/mach-at91/include/mach/board.h
-@@ -121,7 +121,6 @@ extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_de
- #define ATMEL_UART_RI 0x20
-
- extern void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins);
--extern void __init at91_set_serial_console(unsigned portnr);
-
- extern struct platform_device *atmel_default_console_device;
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2f0374f8e78dc83a1589f405fac8c86e7fe2f2cd Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Thu, 5 Apr 2012 14:14:28 +0800
-Subject: ARM: at91: do not pin mux the UARTs in init_early
-
-commit 71b149b3f740501c2d59c80de5b10f5e45051099 upstream.
-
-There is no need to pinmux the UART so early in the kernel.
-Move it to the board init.
-
-This will also allow to finally move the gpio driver to platform device/driver.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/board-1arm.c | 21 +++++-----
- arch/arm/mach-at91/board-afeb-9260v1.c | 25 ++++++------
- arch/arm/mach-at91/board-cam60.c | 5 +--
- arch/arm/mach-at91/board-carmeva.c | 15 ++++----
- arch/arm/mach-at91/board-cpu9krea.c | 49 ++++++++++++------------
- arch/arm/mach-at91/board-cpuat91.c | 37 +++++++++---------
- arch/arm/mach-at91/board-csb337.c | 5 +--
- arch/arm/mach-at91/board-csb637.c | 5 +--
- arch/arm/mach-at91/board-eb9200.c | 21 +++++-----
- arch/arm/mach-at91/board-ecbat91.c | 11 +++---
- arch/arm/mach-at91/board-eco920.c | 5 +--
- arch/arm/mach-at91/board-flexibity.c | 5 +--
- arch/arm/mach-at91/board-foxg20.c | 68 ++++++++++++++++-----------------
- arch/arm/mach-at91/board-gsia18s.c | 63 +++++++++++++++---------------
- arch/arm/mach-at91/board-kafa.c | 11 +++---
- arch/arm/mach-at91/board-kb9202.c | 23 ++++++-----
- arch/arm/mach-at91/board-neocore926.c | 11 +++---
- arch/arm/mach-at91/board-pcontrol-g20.c | 21 +++++-----
- arch/arm/mach-at91/board-picotux200.c | 15 ++++----
- arch/arm/mach-at91/board-qil-a9260.c | 27 +++++++------
- arch/arm/mach-at91/board-rm9200dk.c | 15 ++++----
- arch/arm/mach-at91/board-rm9200ek.c | 15 ++++----
- arch/arm/mach-at91/board-rsi-ews.c | 27 +++++++------
- arch/arm/mach-at91/board-sam9-l9260.c | 21 +++++-----
- arch/arm/mach-at91/board-sam9260ek.c | 21 +++++-----
- arch/arm/mach-at91/board-sam9261ek.c | 5 +--
- arch/arm/mach-at91/board-sam9263ek.c | 11 +++---
- arch/arm/mach-at91/board-sam9g20ek.c | 21 +++++-----
- arch/arm/mach-at91/board-sam9m10g45ek.c | 13 +++----
- arch/arm/mach-at91/board-sam9rlek.c | 11 +++---
- arch/arm/mach-at91/board-snapper9260.c | 17 ++++-----
- arch/arm/mach-at91/board-stamp9g20.c | 61 ++++++++++++-----------------
- arch/arm/mach-at91/board-usb-a926x.c | 5 +--
- arch/arm/mach-at91/board-yl-9200.c | 27 +++++++------
- 34 files changed, 333 insertions(+), 380 deletions(-)
-
-diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
-index f43ad91..271f994 100644
---- a/arch/arm/mach-at91/board-1arm.c
-+++ b/arch/arm/mach-at91/board-1arm.c
-@@ -47,17 +47,6 @@ static void __init onearm_init_early(void)
-
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 on ttyS1 (Rx, Tx, CTS, RTS) */
-- at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
--
-- /* USART1 on ttyS2 (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
-- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-- | ATMEL_UART_RI);
- }
-
- static struct macb_platform_data __initdata onearm_eth_data = {
-@@ -79,6 +68,16 @@ static struct at91_udc_data __initdata onearm_udc_data = {
- static void __init onearm_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 on ttyS1 (Rx, Tx, CTS, RTS) */
-+ at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
-+
-+ /* USART1 on ttyS2 (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-+ | ATMEL_UART_RI);
- at91_add_device_serial();
- /* Ethernet */
- at91_add_device_eth(&onearm_eth_data);
-diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
-index 7c7c682..b7d8aa7 100644
---- a/arch/arm/mach-at91/board-afeb-9260v1.c
-+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
-@@ -52,19 +52,6 @@ static void __init afeb9260_init_early(void)
- {
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91SAM9260_ID_US0, 1,
-- ATMEL_UART_CTS | ATMEL_UART_RTS
-- | ATMEL_UART_DTR | ATMEL_UART_DSR
-- | ATMEL_UART_DCD | ATMEL_UART_RI);
--
-- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-- at91_register_uart(AT91SAM9260_ID_US1, 2,
-- ATMEL_UART_CTS | ATMEL_UART_RTS);
- }
-
- /*
-@@ -180,6 +167,18 @@ static struct at91_cf_data afeb9260_cf_data = {
- static void __init afeb9260_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91SAM9260_ID_US0, 1,
-+ ATMEL_UART_CTS | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR | ATMEL_UART_DSR
-+ | ATMEL_UART_DCD | ATMEL_UART_RI);
-+
-+ /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-+ at91_register_uart(AT91SAM9260_ID_US1, 2,
-+ ATMEL_UART_CTS | ATMEL_UART_RTS);
- at91_add_device_serial();
- /* USB Host */
- at91_add_device_usbh(&afeb9260_usbh_data);
-diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
-index 871717d..29d3ef0 100644
---- a/arch/arm/mach-at91/board-cam60.c
-+++ b/arch/arm/mach-at91/board-cam60.c
-@@ -49,9 +49,6 @@ static void __init cam60_init_early(void)
- {
- /* Initialize processor: 10 MHz crystal */
- at91_initialize(10000000);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
- }
-
- /*
-@@ -172,6 +169,8 @@ static void __init cam60_add_device_nand(void)
- static void __init cam60_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
- at91_add_device_serial();
- /* SPI */
- at91_add_device_spi(cam60_spi_devices, ARRAY_SIZE(cam60_spi_devices));
-diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
-index 168b3fa..44328a6 100644
---- a/arch/arm/mach-at91/board-carmeva.c
-+++ b/arch/arm/mach-at91/board-carmeva.c
-@@ -44,14 +44,6 @@ static void __init carmeva_init_early(void)
- {
- /* Initialize processor: 20.000 MHz crystal */
- at91_initialize(20000000);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-- | ATMEL_UART_RI);
- }
-
- static struct macb_platform_data __initdata carmeva_eth_data = {
-@@ -136,6 +128,13 @@ static struct gpio_led carmeva_leds[] = {
- static void __init carmeva_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-+ | ATMEL_UART_RI);
- at91_add_device_serial();
- /* Ethernet */
- at91_add_device_eth(&carmeva_eth_data);
-diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
-index 4073e30..69951ec 100644
---- a/arch/arm/mach-at91/board-cpu9krea.c
-+++ b/arch/arm/mach-at91/board-cpu9krea.c
-@@ -52,31 +52,6 @@ static void __init cpu9krea_init_early(void)
- {
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* DGBU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS |
-- ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR |
-- ATMEL_UART_DCD | ATMEL_UART_RI);
--
-- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS |
-- ATMEL_UART_RTS);
--
-- /* USART2 on ttyS3. (Rx, Tx, RTS, CTS) */
-- at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS |
-- ATMEL_UART_RTS);
--
-- /* USART3 on ttyS4. (Rx, Tx) */
-- at91_register_uart(AT91SAM9260_ID_US3, 4, 0);
--
-- /* USART4 on ttyS5. (Rx, Tx) */
-- at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
--
-- /* USART5 on ttyS6. (Rx, Tx) */
-- at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
- }
-
- /*
-@@ -349,6 +324,30 @@ static void __init cpu9krea_board_init(void)
- /* NOR */
- cpu9krea_add_device_nor();
- /* Serial */
-+ /* DGBU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS |
-+ ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR |
-+ ATMEL_UART_DCD | ATMEL_UART_RI);
-+
-+ /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-+ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS |
-+ ATMEL_UART_RTS);
-+
-+ /* USART2 on ttyS3. (Rx, Tx, RTS, CTS) */
-+ at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS |
-+ ATMEL_UART_RTS);
-+
-+ /* USART3 on ttyS4. (Rx, Tx) */
-+ at91_register_uart(AT91SAM9260_ID_US3, 4, 0);
-+
-+ /* USART4 on ttyS5. (Rx, Tx) */
-+ at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
-+
-+ /* USART5 on ttyS6. (Rx, Tx) */
-+ at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
- at91_add_device_serial();
- /* USB Host */
- at91_add_device_usbh(&cpu9krea_usbh_data);
-diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
-index 76c62ed..895cf2d 100644
---- a/arch/arm/mach-at91/board-cpuat91.c
-+++ b/arch/arm/mach-at91/board-cpuat91.c
-@@ -59,25 +59,6 @@ static void __init cpuat91_init_early(void)
-
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */
-- at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS |
-- ATMEL_UART_RTS);
--
-- /* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS |
-- ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR |
-- ATMEL_UART_DCD | ATMEL_UART_RI);
--
-- /* USART2 on ttyS3 (Rx, Tx) */
-- at91_register_uart(AT91RM9200_ID_US2, 3, 0);
--
-- /* USART3 on ttyS4 (Rx, Tx, CTS, RTS) */
-- at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_CTS |
-- ATMEL_UART_RTS);
- }
-
- static struct macb_platform_data __initdata cpuat91_eth_data = {
-@@ -158,6 +139,24 @@ static struct platform_device *platform_devices[] __initdata = {
- static void __init cpuat91_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */
-+ at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS |
-+ ATMEL_UART_RTS);
-+
-+ /* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS |
-+ ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR |
-+ ATMEL_UART_DCD | ATMEL_UART_RI);
-+
-+ /* USART2 on ttyS3 (Rx, Tx) */
-+ at91_register_uart(AT91RM9200_ID_US2, 3, 0);
-+
-+ /* USART3 on ttyS4 (Rx, Tx, CTS, RTS) */
-+ at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_CTS |
-+ ATMEL_UART_RTS);
- at91_add_device_serial();
- /* LEDs. */
- at91_gpio_leds(cpuat91_leds, ARRAY_SIZE(cpuat91_leds));
-diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
-index d984435..ad7f9f0 100644
---- a/arch/arm/mach-at91/board-csb337.c
-+++ b/arch/arm/mach-at91/board-csb337.c
-@@ -50,9 +50,6 @@ static void __init csb337_init_early(void)
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
--
-- /* DBGU on ttyS0 */
-- at91_register_uart(0, 0, 0);
- }
-
- static struct macb_platform_data __initdata csb337_eth_data = {
-@@ -226,6 +223,8 @@ static struct gpio_led csb_leds[] = {
- static void __init csb337_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0 */
-+ at91_register_uart(0, 0, 0);
- at91_add_device_serial();
- /* Ethernet */
- at91_add_device_eth(&csb337_eth_data);
-diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
-index 0c9935d..7c8b05a 100644
---- a/arch/arm/mach-at91/board-csb637.c
-+++ b/arch/arm/mach-at91/board-csb637.c
-@@ -44,9 +44,6 @@ static void __init csb637_init_early(void)
- {
- /* Initialize processor: 3.6864 MHz crystal */
- at91_initialize(3686400);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
- }
-
- static struct macb_platform_data __initdata csb637_eth_data = {
-@@ -115,6 +112,8 @@ static void __init csb637_board_init(void)
- /* LED(s) */
- at91_gpio_leds(csb_leds, ARRAY_SIZE(csb_leds));
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
- at91_add_device_serial();
- /* Ethernet */
- at91_add_device_eth(&csb637_eth_data);
-diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
-index a189b9f..bd10172 100644
---- a/arch/arm/mach-at91/board-eb9200.c
-+++ b/arch/arm/mach-at91/board-eb9200.c
-@@ -44,17 +44,6 @@ static void __init eb9200_init_early(void)
- {
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-- | ATMEL_UART_RI);
--
-- /* USART2 on ttyS2. (Rx, Tx) - IRDA */
-- at91_register_uart(AT91RM9200_ID_US2, 2, 0);
- }
-
- static struct macb_platform_data __initdata eb9200_eth_data = {
-@@ -98,6 +87,16 @@ static struct i2c_board_info __initdata eb9200_i2c_devices[] = {
- static void __init eb9200_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-+ | ATMEL_UART_RI);
-+
-+ /* USART2 on ttyS2. (Rx, Tx) - IRDA */
-+ at91_register_uart(AT91RM9200_ID_US2, 2, 0);
- at91_add_device_serial();
- /* Ethernet */
- at91_add_device_eth(&eb9200_eth_data);
-diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
-index 307c530..2510825 100644
---- a/arch/arm/mach-at91/board-ecbat91.c
-+++ b/arch/arm/mach-at91/board-ecbat91.c
-@@ -53,12 +53,6 @@ static void __init ecb_at91init_early(void)
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PC7, AT91_PIN_PC7);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 on ttyS1. (Rx & Tx only) */
-- at91_register_uart(AT91RM9200_ID_US0, 1, 0);
- }
-
- static struct macb_platform_data __initdata ecb_at91eth_data = {
-@@ -149,6 +143,11 @@ static struct spi_board_info __initdata ecb_at91spi_devices[] = {
- static void __init ecb_at91board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 on ttyS1. (Rx & Tx only) */
-+ at91_register_uart(AT91RM9200_ID_US0, 1, 0);
- at91_add_device_serial();
-
- /* Ethernet */
-diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c
-index 7df6a9b..bebeae8 100644
---- a/arch/arm/mach-at91/board-eco920.c
-+++ b/arch/arm/mach-at91/board-eco920.c
-@@ -40,9 +40,6 @@ static void __init eco920_init_early(void)
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
--
-- /* DBGU on ttyS0. (Rx & Tx only */
-- at91_register_uart(0, 0, 0);
- }
-
- static struct macb_platform_data __initdata eco920_eth_data = {
-@@ -100,6 +97,8 @@ static struct spi_board_info eco920_spi_devices[] = {
-
- static void __init eco920_board_init(void)
- {
-+ /* DBGU on ttyS0. (Rx & Tx only */
-+ at91_register_uart(0, 0, 0);
- at91_add_device_serial();
- at91_add_device_eth(&eco920_eth_data);
- at91_add_device_usbh(&eco920_usbh_data);
-diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
-index 6dcc962..47658f7 100644
---- a/arch/arm/mach-at91/board-flexibity.c
-+++ b/arch/arm/mach-at91/board-flexibity.c
-@@ -41,9 +41,6 @@ static void __init flexibity_init_early(void)
- {
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
- }
-
- /* USB Host port */
-@@ -140,6 +137,8 @@ static struct gpio_led flexibity_leds[] = {
- static void __init flexibity_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
- at91_add_device_serial();
- /* USB Host */
- at91_add_device_usbh(&flexibity_usbh_data);
-diff --git a/arch/arm/mach-at91/board-foxg20.c b/arch/arm/mach-at91/board-foxg20.c
-index bb07807..33411e6 100644
---- a/arch/arm/mach-at91/board-foxg20.c
-+++ b/arch/arm/mach-at91/board-foxg20.c
-@@ -61,41 +61,6 @@ static void __init foxg20_init_early(void)
- {
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91SAM9260_ID_US0, 1,
-- ATMEL_UART_CTS
-- | ATMEL_UART_RTS
-- | ATMEL_UART_DTR
-- | ATMEL_UART_DSR
-- | ATMEL_UART_DCD
-- | ATMEL_UART_RI);
--
-- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-- at91_register_uart(AT91SAM9260_ID_US1, 2,
-- ATMEL_UART_CTS
-- | ATMEL_UART_RTS);
--
-- /* USART2 on ttyS3. (Rx & Tx only) */
-- at91_register_uart(AT91SAM9260_ID_US2, 3, 0);
--
-- /* USART3 on ttyS4. (Rx, Tx, RTS, CTS) */
-- at91_register_uart(AT91SAM9260_ID_US3, 4,
-- ATMEL_UART_CTS
-- | ATMEL_UART_RTS);
--
-- /* USART4 on ttyS5. (Rx & Tx only) */
-- at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
--
-- /* USART5 on ttyS6. (Rx & Tx only) */
-- at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
--
-- /* Set the internal pull-up resistor on DRXD */
-- at91_set_A_periph(AT91_PIN_PB14, 1);
--
- }
-
- /*
-@@ -238,6 +203,39 @@ static struct i2c_board_info __initdata foxg20_i2c_devices[] = {
- static void __init foxg20_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91SAM9260_ID_US0, 1,
-+ ATMEL_UART_CTS
-+ | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR
-+ | ATMEL_UART_DSR
-+ | ATMEL_UART_DCD
-+ | ATMEL_UART_RI);
-+
-+ /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-+ at91_register_uart(AT91SAM9260_ID_US1, 2,
-+ ATMEL_UART_CTS
-+ | ATMEL_UART_RTS);
-+
-+ /* USART2 on ttyS3. (Rx & Tx only) */
-+ at91_register_uart(AT91SAM9260_ID_US2, 3, 0);
-+
-+ /* USART3 on ttyS4. (Rx, Tx, RTS, CTS) */
-+ at91_register_uart(AT91SAM9260_ID_US3, 4,
-+ ATMEL_UART_CTS
-+ | ATMEL_UART_RTS);
-+
-+ /* USART4 on ttyS5. (Rx & Tx only) */
-+ at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
-+
-+ /* USART5 on ttyS6. (Rx & Tx only) */
-+ at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
-+
-+ /* Set the internal pull-up resistor on DRXD */
-+ at91_set_A_periph(AT91_PIN_PB14, 1);
- at91_add_device_serial();
- /* USB Host */
- at91_add_device_usbh(&foxg20_usbh_data);
-diff --git a/arch/arm/mach-at91/board-gsia18s.c b/arch/arm/mach-at91/board-gsia18s.c
-index 230e719..3e0dfa6 100644
---- a/arch/arm/mach-at91/board-gsia18s.c
-+++ b/arch/arm/mach-at91/board-gsia18s.c
-@@ -41,38 +41,6 @@
- static void __init gsia18s_init_early(void)
- {
- stamp9g20_init_early();
--
-- /*
-- * USART0 on ttyS1 (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI).
-- * Used for Internal Analog Modem.
-- */
-- at91_register_uart(AT91SAM9260_ID_US0, 1,
-- ATMEL_UART_CTS | ATMEL_UART_RTS |
-- ATMEL_UART_DTR | ATMEL_UART_DSR |
-- ATMEL_UART_DCD | ATMEL_UART_RI);
-- /*
-- * USART1 on ttyS2 (Rx, Tx, CTS, RTS).
-- * Used for GPS or WiFi or Data stream.
-- */
-- at91_register_uart(AT91SAM9260_ID_US1, 2,
-- ATMEL_UART_CTS | ATMEL_UART_RTS);
-- /*
-- * USART2 on ttyS3 (Rx, Tx, CTS, RTS).
-- * Used for External Modem.
-- */
-- at91_register_uart(AT91SAM9260_ID_US2, 3,
-- ATMEL_UART_CTS | ATMEL_UART_RTS);
-- /*
-- * USART3 on ttyS4 (Rx, Tx, RTS).
-- * Used for RS-485.
-- */
-- at91_register_uart(AT91SAM9260_ID_US3, 4, ATMEL_UART_RTS);
--
-- /*
-- * USART4 on ttyS5 (Rx, Tx).
-- * Used for TRX433 Radio Module.
-- */
-- at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
- }
-
- /*
-@@ -558,6 +526,37 @@ static int __init gsia18s_power_off_init(void)
-
- static void __init gsia18s_board_init(void)
- {
-+ /*
-+ * USART0 on ttyS1 (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI).
-+ * Used for Internal Analog Modem.
-+ */
-+ at91_register_uart(AT91SAM9260_ID_US0, 1,
-+ ATMEL_UART_CTS | ATMEL_UART_RTS |
-+ ATMEL_UART_DTR | ATMEL_UART_DSR |
-+ ATMEL_UART_DCD | ATMEL_UART_RI);
-+ /*
-+ * USART1 on ttyS2 (Rx, Tx, CTS, RTS).
-+ * Used for GPS or WiFi or Data stream.
-+ */
-+ at91_register_uart(AT91SAM9260_ID_US1, 2,
-+ ATMEL_UART_CTS | ATMEL_UART_RTS);
-+ /*
-+ * USART2 on ttyS3 (Rx, Tx, CTS, RTS).
-+ * Used for External Modem.
-+ */
-+ at91_register_uart(AT91SAM9260_ID_US2, 3,
-+ ATMEL_UART_CTS | ATMEL_UART_RTS);
-+ /*
-+ * USART3 on ttyS4 (Rx, Tx, RTS).
-+ * Used for RS-485.
-+ */
-+ at91_register_uart(AT91SAM9260_ID_US3, 4, ATMEL_UART_RTS);
-+
-+ /*
-+ * USART4 on ttyS5 (Rx, Tx).
-+ * Used for TRX433 Radio Module.
-+ */
-+ at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
- stamp9g20_board_init();
- at91_add_device_usbh(&usbh_data);
- at91_add_device_udc(&udc_data);
-diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
-index 3e858ed..f46b3eb 100644
---- a/arch/arm/mach-at91/board-kafa.c
-+++ b/arch/arm/mach-at91/board-kafa.c
-@@ -50,12 +50,6 @@ static void __init kafa_init_early(void)
-
- /* Set up the LEDs */
- at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 on ttyS1 (Rx, Tx, CTS, RTS) */
-- at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
- }
-
- static struct macb_platform_data __initdata kafa_eth_data = {
-@@ -77,6 +71,11 @@ static struct at91_udc_data __initdata kafa_udc_data = {
- static void __init kafa_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 on ttyS1 (Rx, Tx, CTS, RTS) */
-+ at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
- at91_add_device_serial();
- /* Ethernet */
- at91_add_device_eth(&kafa_eth_data);
-diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
-index ccbc8be..e71b9e1 100644
---- a/arch/arm/mach-at91/board-kb9202.c
-+++ b/arch/arm/mach-at91/board-kb9202.c
-@@ -53,18 +53,6 @@ static void __init kb9202_init_early(void)
-
- /* Set up the LEDs */
- at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 on ttyS1 (Rx & Tx only) */
-- at91_register_uart(AT91RM9200_ID_US0, 1, 0);
--
-- /* USART1 on ttyS2 (Rx & Tx only) - IRDA (optional) */
-- at91_register_uart(AT91RM9200_ID_US1, 2, 0);
--
-- /* USART3 on ttyS3 (Rx, Tx, CTS, RTS) - RS485 (optional) */
-- at91_register_uart(AT91RM9200_ID_US3, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
- }
-
- static struct macb_platform_data __initdata kb9202_eth_data = {
-@@ -113,6 +101,17 @@ static struct atmel_nand_data __initdata kb9202_nand_data = {
- static void __init kb9202_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 on ttyS1 (Rx & Tx only) */
-+ at91_register_uart(AT91RM9200_ID_US0, 1, 0);
-+
-+ /* USART1 on ttyS2 (Rx & Tx only) - IRDA (optional) */
-+ at91_register_uart(AT91RM9200_ID_US1, 2, 0);
-+
-+ /* USART3 on ttyS3 (Rx, Tx, CTS, RTS) - RS485 (optional) */
-+ at91_register_uart(AT91RM9200_ID_US3, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
- at91_add_device_serial();
- /* Ethernet */
- at91_add_device_eth(&kb9202_eth_data);
-diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
-index c456fdc..d2f4cc1 100644
---- a/arch/arm/mach-at91/board-neocore926.c
-+++ b/arch/arm/mach-at91/board-neocore926.c
-@@ -55,12 +55,6 @@ static void __init neocore926_init_early(void)
- {
- /* Initialize processor: 20 MHz crystal */
- at91_initialize(20000000);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
-- at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
- }
-
- /*
-@@ -338,6 +332,11 @@ static struct ac97c_platform_data neocore926_ac97_data = {
- static void __init neocore926_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
-+ at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
- at91_add_device_serial();
-
- /* USB Host */
-diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c
-index b4a12fc..7fe6383 100644
---- a/arch/arm/mach-at91/board-pcontrol-g20.c
-+++ b/arch/arm/mach-at91/board-pcontrol-g20.c
-@@ -40,17 +40,6 @@
- static void __init pcontrol_g20_init_early(void)
- {
- stamp9g20_init_early();
--
-- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback A2 */
-- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS
-- | ATMEL_UART_RTS);
--
-- /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) isolated RS485 X5 */
-- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS
-- | ATMEL_UART_RTS);
--
-- /* USART2 on ttyS3. (Rx, Tx) 9bit-Bus Multidrop-mode X4 */
-- at91_register_uart(AT91SAM9260_ID_US4, 3, 0);
- }
-
- static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {
-@@ -199,6 +188,16 @@ static struct spi_board_info pcontrol_g20_spi_devices[] = {
-
- static void __init pcontrol_g20_board_init(void)
- {
-+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback A2 */
-+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS
-+ | ATMEL_UART_RTS);
-+
-+ /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) isolated RS485 X5 */
-+ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS
-+ | ATMEL_UART_RTS);
-+
-+ /* USART2 on ttyS3. (Rx, Tx) 9bit-Bus Multidrop-mode X4 */
-+ at91_register_uart(AT91SAM9260_ID_US4, 3, 0);
- stamp9g20_board_init();
- at91_add_device_usbh(&usbh_data);
- at91_add_device_eth(&macb_data);
-diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
-index 4ca56cd..b45c0a5 100644
---- a/arch/arm/mach-at91/board-picotux200.c
-+++ b/arch/arm/mach-at91/board-picotux200.c
-@@ -48,14 +48,6 @@ static void __init picotux200_init_early(void)
- {
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-- | ATMEL_UART_RI);
- }
-
- static struct macb_platform_data __initdata picotux200_eth_data = {
-@@ -103,6 +95,13 @@ static struct platform_device picotux200_flash = {
- static void __init picotux200_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-+ | ATMEL_UART_RI);
- at91_add_device_serial();
- /* Ethernet */
- at91_add_device_eth(&picotux200_eth_data);
-diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
-index 189d3fe..0c61bf0 100644
---- a/arch/arm/mach-at91/board-qil-a9260.c
-+++ b/arch/arm/mach-at91/board-qil-a9260.c
-@@ -52,20 +52,6 @@ static void __init ek_init_early(void)
- {
- /* Initialize processor: 12.000 MHz crystal */
- at91_initialize(12000000);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-- | ATMEL_UART_RI);
--
-- /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
-- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
--
-- /* USART2 on ttyS3. (Rx, Tx, CTS, RTS) */
-- at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
- }
-
- /*
-@@ -231,6 +217,19 @@ static struct gpio_led ek_leds[] = {
- static void __init ek_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-+ | ATMEL_UART_RI);
-+
-+ /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
-+ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-+
-+ /* USART2 on ttyS3. (Rx, Tx, CTS, RTS) */
-+ at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
- at91_add_device_serial();
- /* USB Host */
- at91_add_device_usbh(&ek_usbh_data);
-diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c
-index d5ce630..4a0b097 100644
---- a/arch/arm/mach-at91/board-rm9200dk.c
-+++ b/arch/arm/mach-at91/board-rm9200dk.c
-@@ -53,14 +53,6 @@ static void __init dk_init_early(void)
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-- | ATMEL_UART_RI);
- }
-
- static struct macb_platform_data __initdata dk_eth_data = {
-@@ -188,6 +180,13 @@ static struct gpio_led dk_leds[] = {
- static void __init dk_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-+ | ATMEL_UART_RI);
- at91_add_device_serial();
- /* Ethernet */
- at91_add_device_eth(&dk_eth_data);
-diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
-index e96d5f5..6fa54ac 100644
---- a/arch/arm/mach-at91/board-rm9200ek.c
-+++ b/arch/arm/mach-at91/board-rm9200ek.c
-@@ -53,14 +53,6 @@ static void __init ek_init_early(void)
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-- | ATMEL_UART_RI);
- }
-
- static struct macb_platform_data __initdata ek_eth_data = {
-@@ -159,6 +151,13 @@ static struct gpio_led ek_leds[] = {
- static void __init ek_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-+ | ATMEL_UART_RI);
- at91_add_device_serial();
- /* Ethernet */
- at91_add_device_eth(&ek_eth_data);
-diff --git a/arch/arm/mach-at91/board-rsi-ews.c b/arch/arm/mach-at91/board-rsi-ews.c
-index 2c84463..10d8730 100644
---- a/arch/arm/mach-at91/board-rsi-ews.c
-+++ b/arch/arm/mach-at91/board-rsi-ews.c
-@@ -38,20 +38,6 @@ static void __init rsi_ews_init_early(void)
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PB6, AT91_PIN_PB9);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- /* This one is for debugging */
-- at91_register_uart(0, 0, 0);
--
-- /* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- /* Dialin/-out modem interface */
-- at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
-- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-- | ATMEL_UART_RI);
--
-- /* USART3 on ttyS4. (Rx, Tx, RTS) */
-- /* RS485 communication */
-- at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_RTS);
- }
-
- /*
-@@ -202,6 +188,19 @@ static struct platform_device rsiews_nor_flash = {
- static void __init rsi_ews_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ /* This one is for debugging */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ /* Dialin/-out modem interface */
-+ at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-+ | ATMEL_UART_RI);
-+
-+ /* USART3 on ttyS4. (Rx, Tx, RTS) */
-+ /* RS485 communication */
-+ at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_RTS);
- at91_add_device_serial();
- at91_set_gpio_output(AT91_PIN_PA21, 0);
- /* Ethernet */
-diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
-index dee44cb..5343dab 100644
---- a/arch/arm/mach-at91/board-sam9-l9260.c
-+++ b/arch/arm/mach-at91/board-sam9-l9260.c
-@@ -51,17 +51,6 @@ static void __init ek_init_early(void)
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PA9, AT91_PIN_PA6);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-- | ATMEL_UART_RI);
--
-- /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
-- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
- }
-
- /*
-@@ -182,6 +171,16 @@ static struct at91_mmc_data __initdata ek_mmc_data = {
- static void __init ek_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-+ | ATMEL_UART_RI);
-+
-+ /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
-+ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
- at91_add_device_serial();
- /* USB Host */
- at91_add_device_usbh(&ek_usbh_data);
-diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
-index 6da17b5..7b3c391 100644
---- a/arch/arm/mach-at91/board-sam9260ek.c
-+++ b/arch/arm/mach-at91/board-sam9260ek.c
-@@ -54,17 +54,6 @@ static void __init ek_init_early(void)
- {
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-- | ATMEL_UART_RI);
--
-- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
- }
-
- /*
-@@ -317,6 +306,16 @@ static void __init ek_add_device_buttons(void) {}
- static void __init ek_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-+ | ATMEL_UART_RI);
-+
-+ /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-+ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
- at91_add_device_serial();
- /* USB Host */
- at91_add_device_usbh(&ek_usbh_data);
-diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
-index 950c20b..de1ed46 100644
---- a/arch/arm/mach-at91/board-sam9261ek.c
-+++ b/arch/arm/mach-at91/board-sam9261ek.c
-@@ -61,9 +61,6 @@ static void __init ek_init_early(void)
-
- /* Setup the LEDs */
- at91_init_leds(AT91_PIN_PA13, AT91_PIN_PA14);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
- }
-
- /*
-@@ -575,6 +572,8 @@ static struct gpio_led ek_leds[] = {
- static void __init ek_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
- at91_add_device_serial();
- /* USB Host */
- at91_add_device_usbh(&ek_usbh_data);
-diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
-index 4424873..983cb98 100644
---- a/arch/arm/mach-at91/board-sam9263ek.c
-+++ b/arch/arm/mach-at91/board-sam9263ek.c
-@@ -57,12 +57,6 @@ static void __init ek_init_early(void)
- {
- /* Initialize processor: 16.367 MHz crystal */
- at91_initialize(16367660);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
-- at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
- }
-
- /*
-@@ -409,6 +403,11 @@ static struct at91_can_data ek_can_data = {
- static void __init ek_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
-+ at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
- at91_add_device_serial();
- /* USB Host */
- at91_add_device_usbh(&ek_usbh_data);
-diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
-index 05f8467..3d61553 100644
---- a/arch/arm/mach-at91/board-sam9g20ek.c
-+++ b/arch/arm/mach-at91/board-sam9g20ek.c
-@@ -65,17 +65,6 @@ static void __init ek_init_early(void)
- {
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-- | ATMEL_UART_RI);
--
-- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
- }
-
- /*
-@@ -369,6 +358,16 @@ static struct i2c_board_info __initdata ek_i2c_devices[] = {
- static void __init ek_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-+ | ATMEL_UART_RI);
-+
-+ /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-+ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
- at91_add_device_serial();
- /* USB Host */
- at91_add_device_usbh(&ek_usbh_data);
-diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
-index be2ca19..9a87f0b 100644
---- a/arch/arm/mach-at91/board-sam9m10g45ek.c
-+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
-@@ -53,13 +53,6 @@ static void __init ek_init_early(void)
- {
- /* Initialize processor: 12.000 MHz crystal */
- at91_initialize(12000000);
--
-- /* DGBU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 not connected on the -EK board */
-- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-- at91_register_uart(AT91SAM9G45_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
- }
-
- /*
-@@ -454,6 +447,12 @@ static struct platform_device *devices[] __initdata = {
- static void __init ek_board_init(void)
- {
- /* Serial */
-+ /* DGBU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 not connected on the -EK board */
-+ /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-+ at91_register_uart(AT91SAM9G45_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
- at91_add_device_serial();
- /* USB HS Host */
- at91_add_device_usbh_ohci(&ek_usbh_hs_data);
-diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
-index 23f383a..be3239f 100644
---- a/arch/arm/mach-at91/board-sam9rlek.c
-+++ b/arch/arm/mach-at91/board-sam9rlek.c
-@@ -42,12 +42,6 @@ static void __init ek_init_early(void)
- {
- /* Initialize processor: 12.000 MHz crystal */
- at91_initialize(12000000);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */
-- at91_register_uart(AT91SAM9RL_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
- }
-
- /*
-@@ -293,6 +287,11 @@ static void __init ek_add_device_buttons(void) {}
- static void __init ek_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */
-+ at91_register_uart(AT91SAM9RL_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
- at91_add_device_serial();
- /* USB HS */
- at91_add_device_usba(&ek_usba_udc_data);
-diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
-index 1a6774a..9d446f1 100644
---- a/arch/arm/mach-at91/board-snapper9260.c
-+++ b/arch/arm/mach-at91/board-snapper9260.c
-@@ -43,15 +43,6 @@
- static void __init snapper9260_init_early(void)
- {
- at91_initialize(18432000);
--
-- /* Debug on ttyS0 */
-- at91_register_uart(0, 0, 0);
--
-- at91_register_uart(AT91SAM9260_ID_US0, 1,
-- ATMEL_UART_CTS | ATMEL_UART_RTS);
-- at91_register_uart(AT91SAM9260_ID_US1, 2,
-- ATMEL_UART_CTS | ATMEL_UART_RTS);
-- at91_register_uart(AT91SAM9260_ID_US2, 3, 0);
- }
-
- static struct at91_usbh_data __initdata snapper9260_usbh_data = {
-@@ -167,6 +158,14 @@ static void __init snapper9260_board_init(void)
- snapper9260_i2c_isl1208.irq = gpio_to_irq(AT91_PIN_PA31);
- i2c_register_board_info(0, &snapper9260_i2c_isl1208, 1);
-
-+ /* Debug on ttyS0 */
-+ at91_register_uart(0, 0, 0);
-+
-+ at91_register_uart(AT91SAM9260_ID_US0, 1,
-+ ATMEL_UART_CTS | ATMEL_UART_RTS);
-+ at91_register_uart(AT91SAM9260_ID_US1, 2,
-+ ATMEL_UART_CTS | ATMEL_UART_RTS);
-+ at91_register_uart(AT91SAM9260_ID_US2, 3, 0);
- at91_add_device_serial();
- at91_add_device_usbh(&snapper9260_usbh_data);
- at91_add_device_udc(&snapper9260_udc_data);
-diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
-index 38a7ca5..ee86f9d 100644
---- a/arch/arm/mach-at91/board-stamp9g20.c
-+++ b/arch/arm/mach-at91/board-stamp9g20.c
-@@ -36,41 +36,6 @@ void __init stamp9g20_init_early(void)
- {
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* DGBU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--}
--
--static void __init stamp9g20evb_init_early(void)
--{
-- stamp9g20_init_early();
--
-- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-- | ATMEL_UART_DTR | ATMEL_UART_DSR
-- | ATMEL_UART_DCD | ATMEL_UART_RI);
--}
--
--static void __init portuxg20_init_early(void)
--{
-- stamp9g20_init_early();
--
-- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-- | ATMEL_UART_DTR | ATMEL_UART_DSR
-- | ATMEL_UART_DCD | ATMEL_UART_RI);
--
-- /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
-- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
--
-- /* USART2 on ttyS3. (Rx, Tx, CTS, RTS) */
-- at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
--
-- /* USART4 on ttyS5. (Rx, Tx only) */
-- at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
--
-- /* USART5 on ttyS6. (Rx, Tx only) */
-- at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
- }
-
- /*
-@@ -251,6 +216,8 @@ void add_w1(void)
- void __init stamp9g20_board_init(void)
- {
- /* Serial */
-+ /* DGBU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
- at91_add_device_serial();
- /* NAND */
- add_device_nand();
-@@ -266,6 +233,22 @@ void __init stamp9g20_board_init(void)
-
- static void __init portuxg20_board_init(void)
- {
-+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR | ATMEL_UART_DSR
-+ | ATMEL_UART_DCD | ATMEL_UART_RI);
-+
-+ /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
-+ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-+
-+ /* USART2 on ttyS3. (Rx, Tx, CTS, RTS) */
-+ at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
-+
-+ /* USART4 on ttyS5. (Rx, Tx only) */
-+ at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
-+
-+ /* USART5 on ttyS6. (Rx, Tx only) */
-+ at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
- stamp9g20_board_init();
- /* USB Host */
- at91_add_device_usbh(&usbh_data);
-@@ -283,6 +266,10 @@ static void __init portuxg20_board_init(void)
-
- static void __init stamp9g20evb_board_init(void)
- {
-+ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR | ATMEL_UART_DSR
-+ | ATMEL_UART_DCD | ATMEL_UART_RI);
- stamp9g20_board_init();
- /* USB Host */
- at91_add_device_usbh(&usbh_data);
-@@ -300,7 +287,7 @@ MACHINE_START(PORTUXG20, "taskit PortuxG20")
- /* Maintainer: taskit GmbH */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-- .init_early = portuxg20_init_early,
-+ .init_early = stamp9g20_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = portuxg20_board_init,
- MACHINE_END
-@@ -309,7 +296,7 @@ MACHINE_START(STAMP9G20, "taskit Stamp9G20")
- /* Maintainer: taskit GmbH */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-- .init_early = stamp9g20evb_init_early,
-+ .init_early = stamp9g20_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = stamp9g20evb_board_init,
- MACHINE_END
-diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c
-index ee482eb..332ecd4 100644
---- a/arch/arm/mach-at91/board-usb-a926x.c
-+++ b/arch/arm/mach-at91/board-usb-a926x.c
-@@ -53,9 +53,6 @@ static void __init ek_init_early(void)
- {
- /* Initialize processor: 12.00 MHz crystal */
- at91_initialize(12000000);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
- }
-
- /*
-@@ -322,6 +319,8 @@ static void __init ek_add_device_leds(void)
- static void __init ek_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
- at91_add_device_serial();
- /* USB Host */
- at91_add_device_usbh(&ek_usbh_data);
-diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
-index e94a04e..db8d25c 100644
---- a/arch/arm/mach-at91/board-yl-9200.c
-+++ b/arch/arm/mach-at91/board-yl-9200.c
-@@ -61,20 +61,6 @@ static void __init yl9200_init_early(void)
-
- /* Setup the LEDs D2=PB17 (timer), D3=PB16 (cpu) */
- at91_init_leds(AT91_PIN_PB16, AT91_PIN_PB17);
--
-- /* DBGU on ttyS0. (Rx & Tx only) */
-- at91_register_uart(0, 0, 0);
--
-- /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-- at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-- | ATMEL_UART_RI);
--
-- /* USART0 on ttyS2. (Rx & Tx only to JP3) */
-- at91_register_uart(AT91RM9200_ID_US0, 2, 0);
--
-- /* USART3 on ttyS3. (Rx, Tx, RTS - RS485 interface) */
-- at91_register_uart(AT91RM9200_ID_US3, 3, ATMEL_UART_RTS);
- }
-
- /*
-@@ -558,6 +544,19 @@ void __init yl9200_add_device_video(void) {}
- static void __init yl9200_board_init(void)
- {
- /* Serial */
-+ /* DBGU on ttyS0. (Rx & Tx only) */
-+ at91_register_uart(0, 0, 0);
-+
-+ /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-+ at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-+ | ATMEL_UART_RI);
-+
-+ /* USART0 on ttyS2. (Rx & Tx only to JP3) */
-+ at91_register_uart(AT91RM9200_ID_US0, 2, 0);
-+
-+ /* USART3 on ttyS3. (Rx, Tx, RTS - RS485 interface) */
-+ at91_register_uart(AT91RM9200_ID_US3, 3, ATMEL_UART_RTS);
- at91_add_device_serial();
- /* Ethernet */
- at91_add_device_eth(&yl9200_eth_data);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 940c679c9142bff7bc2c16192d6e118b9b07d9a2 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Thu, 5 Apr 2012 14:27:57 +0800
-Subject: ARM: at91: move at91_init_leds to board init
-
-commit 7eb1dbb3beb982a7d72514abff96ebc08a22e5cd upstream.
-
-This will also allow to finally move the gpio driver to platform device/driver.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/board-csb337.c | 5 ++---
- arch/arm/mach-at91/board-ecbat91.c | 6 +++---
- arch/arm/mach-at91/board-eco920.c | 5 ++---
- arch/arm/mach-at91/board-kafa.c | 6 +++---
- arch/arm/mach-at91/board-kb9202.c | 6 +++---
- arch/arm/mach-at91/board-rm9200dk.c | 6 +++---
- arch/arm/mach-at91/board-rm9200ek.c | 6 +++---
- arch/arm/mach-at91/board-rsi-ews.c | 6 +++---
- arch/arm/mach-at91/board-sam9-l9260.c | 6 +++---
- arch/arm/mach-at91/board-sam9261ek.c | 6 +++---
- arch/arm/mach-at91/board-yl-9200.c | 6 +++---
- 11 files changed, 31 insertions(+), 33 deletions(-)
-
-diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
-index ad7f9f0..cd81336 100644
---- a/arch/arm/mach-at91/board-csb337.c
-+++ b/arch/arm/mach-at91/board-csb337.c
-@@ -47,9 +47,6 @@ static void __init csb337_init_early(void)
- {
- /* Initialize processor: 3.6864 MHz crystal */
- at91_initialize(3686400);
--
-- /* Setup the LEDs */
-- at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
- }
-
- static struct macb_platform_data __initdata csb337_eth_data = {
-@@ -222,6 +219,8 @@ static struct gpio_led csb_leds[] = {
-
- static void __init csb337_board_init(void)
- {
-+ /* Setup the LEDs */
-+ at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
- /* Serial */
- /* DBGU on ttyS0 */
- at91_register_uart(0, 0, 0);
-diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
-index 2510825..89cc372 100644
---- a/arch/arm/mach-at91/board-ecbat91.c
-+++ b/arch/arm/mach-at91/board-ecbat91.c
-@@ -50,9 +50,6 @@ static void __init ecb_at91init_early(void)
-
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* Setup the LEDs */
-- at91_init_leds(AT91_PIN_PC7, AT91_PIN_PC7);
- }
-
- static struct macb_platform_data __initdata ecb_at91eth_data = {
-@@ -142,6 +139,9 @@ static struct spi_board_info __initdata ecb_at91spi_devices[] = {
-
- static void __init ecb_at91board_init(void)
- {
-+ /* Setup the LEDs */
-+ at91_init_leds(AT91_PIN_PC7, AT91_PIN_PC7);
-+
- /* Serial */
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c
-index bebeae8..558546c 100644
---- a/arch/arm/mach-at91/board-eco920.c
-+++ b/arch/arm/mach-at91/board-eco920.c
-@@ -37,9 +37,6 @@ static void __init eco920_init_early(void)
- at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
-
- at91_initialize(18432000);
--
-- /* Setup the LEDs */
-- at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
- }
-
- static struct macb_platform_data __initdata eco920_eth_data = {
-@@ -97,6 +94,8 @@ static struct spi_board_info eco920_spi_devices[] = {
-
- static void __init eco920_board_init(void)
- {
-+ /* Setup the LEDs */
-+ at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
- /* DBGU on ttyS0. (Rx & Tx only */
- at91_register_uart(0, 0, 0);
- at91_add_device_serial();
-diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
-index f46b3eb..f260657 100644
---- a/arch/arm/mach-at91/board-kafa.c
-+++ b/arch/arm/mach-at91/board-kafa.c
-@@ -47,9 +47,6 @@ static void __init kafa_init_early(void)
-
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* Set up the LEDs */
-- at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
- }
-
- static struct macb_platform_data __initdata kafa_eth_data = {
-@@ -70,6 +67,9 @@ static struct at91_udc_data __initdata kafa_udc_data = {
-
- static void __init kafa_board_init(void)
- {
-+ /* Set up the LEDs */
-+ at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
-+
- /* Serial */
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
-index e71b9e1..ba39db5 100644
---- a/arch/arm/mach-at91/board-kb9202.c
-+++ b/arch/arm/mach-at91/board-kb9202.c
-@@ -50,9 +50,6 @@ static void __init kb9202_init_early(void)
-
- /* Initialize processor: 10 MHz crystal */
- at91_initialize(10000000);
--
-- /* Set up the LEDs */
-- at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
- }
-
- static struct macb_platform_data __initdata kb9202_eth_data = {
-@@ -100,6 +97,9 @@ static struct atmel_nand_data __initdata kb9202_nand_data = {
-
- static void __init kb9202_board_init(void)
- {
-+ /* Set up the LEDs */
-+ at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
-+
- /* Serial */
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c
-index 4a0b097..afd7a47 100644
---- a/arch/arm/mach-at91/board-rm9200dk.c
-+++ b/arch/arm/mach-at91/board-rm9200dk.c
-@@ -50,9 +50,6 @@ static void __init dk_init_early(void)
- {
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* Setup the LEDs */
-- at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
- }
-
- static struct macb_platform_data __initdata dk_eth_data = {
-@@ -179,6 +176,9 @@ static struct gpio_led dk_leds[] = {
-
- static void __init dk_board_init(void)
- {
-+ /* Setup the LEDs */
-+ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
-+
- /* Serial */
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
-index 6fa54ac..2b15b8a 100644
---- a/arch/arm/mach-at91/board-rm9200ek.c
-+++ b/arch/arm/mach-at91/board-rm9200ek.c
-@@ -50,9 +50,6 @@ static void __init ek_init_early(void)
- {
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* Setup the LEDs */
-- at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
- }
-
- static struct macb_platform_data __initdata ek_eth_data = {
-@@ -150,6 +147,9 @@ static struct gpio_led ek_leds[] = {
-
- static void __init ek_board_init(void)
- {
-+ /* Setup the LEDs */
-+ at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
-+
- /* Serial */
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-diff --git a/arch/arm/mach-at91/board-rsi-ews.c b/arch/arm/mach-at91/board-rsi-ews.c
-index 10d8730..24ab9be 100644
---- a/arch/arm/mach-at91/board-rsi-ews.c
-+++ b/arch/arm/mach-at91/board-rsi-ews.c
-@@ -35,9 +35,6 @@ static void __init rsi_ews_init_early(void)
- {
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* Setup the LEDs */
-- at91_init_leds(AT91_PIN_PB6, AT91_PIN_PB9);
- }
-
- /*
-@@ -187,6 +184,9 @@ static struct platform_device rsiews_nor_flash = {
- */
- static void __init rsi_ews_board_init(void)
- {
-+ /* Setup the LEDs */
-+ at91_init_leds(AT91_PIN_PB6, AT91_PIN_PB9);
-+
- /* Serial */
- /* DBGU on ttyS0. (Rx & Tx only) */
- /* This one is for debugging */
-diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
-index 5343dab..cdd21f2 100644
---- a/arch/arm/mach-at91/board-sam9-l9260.c
-+++ b/arch/arm/mach-at91/board-sam9-l9260.c
-@@ -48,9 +48,6 @@ static void __init ek_init_early(void)
- {
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* Setup the LEDs */
-- at91_init_leds(AT91_PIN_PA9, AT91_PIN_PA6);
- }
-
- /*
-@@ -170,6 +167,9 @@ static struct at91_mmc_data __initdata ek_mmc_data = {
-
- static void __init ek_board_init(void)
- {
-+ /* Setup the LEDs */
-+ at91_init_leds(AT91_PIN_PA9, AT91_PIN_PA6);
-+
- /* Serial */
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
-index de1ed46..2736453 100644
---- a/arch/arm/mach-at91/board-sam9261ek.c
-+++ b/arch/arm/mach-at91/board-sam9261ek.c
-@@ -58,9 +58,6 @@ static void __init ek_init_early(void)
- {
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* Setup the LEDs */
-- at91_init_leds(AT91_PIN_PA13, AT91_PIN_PA14);
- }
-
- /*
-@@ -571,6 +568,9 @@ static struct gpio_led ek_leds[] = {
-
- static void __init ek_board_init(void)
- {
-+ /* Setup the LEDs */
-+ at91_init_leds(AT91_PIN_PA13, AT91_PIN_PA14);
-+
- /* Serial */
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
-index db8d25c..d56665e 100644
---- a/arch/arm/mach-at91/board-yl-9200.c
-+++ b/arch/arm/mach-at91/board-yl-9200.c
-@@ -58,9 +58,6 @@ static void __init yl9200_init_early(void)
-
- /* Initialize processor: 18.432 MHz crystal */
- at91_initialize(18432000);
--
-- /* Setup the LEDs D2=PB17 (timer), D3=PB16 (cpu) */
-- at91_init_leds(AT91_PIN_PB16, AT91_PIN_PB17);
- }
-
- /*
-@@ -543,6 +540,9 @@ void __init yl9200_add_device_video(void) {}
-
- static void __init yl9200_board_init(void)
- {
-+ /* Setup the LEDs D2=PB17 (timer), D3=PB16 (cpu) */
-+ at91_init_leds(AT91_PIN_PB16, AT91_PIN_PB17);
-+
- /* Serial */
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ec2eded8dc34a9404174de06999cdeab641651c4 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Mon, 13 Feb 2012 14:58:30 +0800
-Subject: ARM: at91: pm select memory controler at runtime
-
-commit efd09165aa554f84a42565d5ae6a1af58b06a97a upstream.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-[nicolas.ferre@atmel.com: add cpuidle modification]
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/cpuidle.c | 8 +++++++-
- arch/arm/mach-at91/pm.c | 12 ++++++++----
- arch/arm/mach-at91/pm.h | 13 -------------
- 3 files changed, 15 insertions(+), 18 deletions(-)
-
-diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c
-index ece1f9a..0c63815 100644
---- a/arch/arm/mach-at91/cpuidle.c
-+++ b/arch/arm/mach-at91/cpuidle.c
-@@ -21,6 +21,7 @@
- #include <linux/export.h>
- #include <asm/proc-fns.h>
- #include <asm/cpuidle.h>
-+#include <mach/cpu.h>
-
- #include "pm.h"
-
-@@ -33,7 +34,12 @@ static int at91_enter_idle(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
- {
-- at91_standby();
-+ if (cpu_is_at91rm9200())
-+ at91rm9200_standby();
-+ else if (cpu_is_at91sam9g45())
-+ at91sam9g45_standby();
-+ else
-+ at91sam9_standby();
-
- return index;
- }
-diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
-index f630250..1bfaad6 100644
---- a/arch/arm/mach-at91/pm.c
-+++ b/arch/arm/mach-at91/pm.c
-@@ -261,7 +261,12 @@ static int at91_pm_enter(suspend_state_t state)
- * For ARM 926 based chips, this requirement is weaker
- * as at91sam9 can access a RAM in self-refresh mode.
- */
-- at91_standby();
-+ if (cpu_is_at91rm9200())
-+ at91rm9200_standby();
-+ else if (cpu_is_at91sam9g45())
-+ at91sam9g45_standby();
-+ else
-+ at91sam9_standby();
- break;
-
- case PM_SUSPEND_ON:
-@@ -307,10 +312,9 @@ static int __init at91_pm_init(void)
-
- pr_info("AT91: Power Management%s\n", (slow_clock ? " (with slow clock mode)" : ""));
-
--#ifdef CONFIG_ARCH_AT91RM9200
- /* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh. */
-- at91_ramc_write(0, AT91RM9200_SDRAMC_LPR, 0);
--#endif
-+ if (cpu_is_at91rm9200())
-+ at91_ramc_write(0, AT91RM9200_SDRAMC_LPR, 0);
-
- suspend_set_ops(&at91_pm_ops);
-
-diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
-index 89f56f3..1b4865e 100644
---- a/arch/arm/mach-at91/pm.h
-+++ b/arch/arm/mach-at91/pm.h
-@@ -12,7 +12,6 @@
- #define __ARCH_ARM_MACH_AT91_PM
-
- #include <mach/at91_ramc.h>
--#ifdef CONFIG_ARCH_AT91RM9200
- #include <mach/at91rm9200_sdramc.h>
-
- /*
-@@ -43,10 +42,6 @@ static inline void at91rm9200_standby(void)
- "r" (lpr));
- }
-
--#define at91_standby at91rm9200_standby
--
--#elif defined(CONFIG_ARCH_AT91SAM9G45)
--
- /* We manage both DDRAM/SDRAM controllers, we need more than one value to
- * remember.
- */
-@@ -75,10 +70,6 @@ static inline void at91sam9g45_standby(void)
- at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
- }
-
--#define at91_standby at91sam9g45_standby
--
--#else
--
- #ifdef CONFIG_ARCH_AT91SAM9263
- /*
- * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
-@@ -102,8 +93,4 @@ static inline void at91sam9_standby(void)
- at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr);
- }
-
--#define at91_standby at91sam9_standby
--
--#endif
--
- #endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From c57f12b42c6bb7481d27ffb9073b32102ab3015c Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 6 Apr 2012 13:04:04 +0800
-Subject: ARM: at91: add SOC_AT91SAM9 kconfig option to factorise select
-
-commit 1441bd325bbbcd38d190b2444481b23cdf70069a upstream.
-
-This will allow to simplify the switch to multi soc in the same kernel.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/Kconfig | 29 +++++++++++++----------------
- arch/arm/mach-at91/Makefile | 17 +++++++++--------
- 2 files changed, 22 insertions(+), 24 deletions(-)
-
-diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
-index 885fdb9..40e31c7 100644
---- a/arch/arm/mach-at91/Kconfig
-+++ b/arch/arm/mach-at91/Kconfig
-@@ -17,6 +17,11 @@ config AT91_SAM9G45_RESET
- bool
- default !ARCH_AT91X40
-
-+config SOC_AT91SAM9
-+ bool
-+ select GENERIC_CLOCKEVENTS
-+ select CPU_ARM926T
-+
- menu "Atmel AT91 System-on-Chip"
-
- choice
-@@ -30,51 +35,44 @@ config ARCH_AT91RM9200
-
- config ARCH_AT91SAM9260
- bool "AT91SAM9260 or AT91SAM9XE"
-- select CPU_ARM926T
-- select GENERIC_CLOCKEVENTS
-+ select SOC_AT91SAM9
- select HAVE_AT91_DBGU0
- select HAVE_NET_MACB
-
- config ARCH_AT91SAM9261
- bool "AT91SAM9261"
-- select CPU_ARM926T
-- select GENERIC_CLOCKEVENTS
-+ select SOC_AT91SAM9
- select HAVE_FB_ATMEL
- select HAVE_AT91_DBGU0
-
- config ARCH_AT91SAM9G10
- bool "AT91SAM9G10"
-- select CPU_ARM926T
-- select GENERIC_CLOCKEVENTS
-+ select SOC_AT91SAM9
- select HAVE_AT91_DBGU0
- select HAVE_FB_ATMEL
-
- config ARCH_AT91SAM9263
- bool "AT91SAM9263"
-- select CPU_ARM926T
-- select GENERIC_CLOCKEVENTS
-+ select SOC_AT91SAM9
- select HAVE_FB_ATMEL
- select HAVE_NET_MACB
- select HAVE_AT91_DBGU1
-
- config ARCH_AT91SAM9RL
- bool "AT91SAM9RL"
-- select CPU_ARM926T
-- select GENERIC_CLOCKEVENTS
-+ select SOC_AT91SAM9
- select HAVE_FB_ATMEL
- select HAVE_AT91_DBGU0
-
- config ARCH_AT91SAM9G20
- bool "AT91SAM9G20"
-- select CPU_ARM926T
-- select GENERIC_CLOCKEVENTS
-+ select SOC_AT91SAM9
- select HAVE_AT91_DBGU0
- select HAVE_NET_MACB
-
- config ARCH_AT91SAM9G45
- bool "AT91SAM9G45 or AT91SAM9M10 families"
-- select CPU_ARM926T
-- select GENERIC_CLOCKEVENTS
-+ select SOC_AT91SAM9
- select HAVE_FB_ATMEL
- select HAVE_NET_MACB
- select HAVE_AT91_DBGU1
-@@ -84,8 +82,7 @@ config ARCH_AT91SAM9G45
-
- config ARCH_AT91SAM9X5
- bool "AT91SAM9x5 family"
-- select CPU_ARM926T
-- select GENERIC_CLOCKEVENTS
-+ select SOC_AT91SAM9
- select HAVE_FB_ATMEL
- select HAVE_NET_MACB
- select HAVE_AT91_DBGU0
-diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
-index 8512e53..d97d0f4 100644
---- a/arch/arm/mach-at91/Makefile
-+++ b/arch/arm/mach-at91/Makefile
-@@ -10,17 +10,18 @@ obj- :=
- obj-$(CONFIG_AT91_PMC_UNIT) += clock.o
- obj-$(CONFIG_AT91_SAM9_ALT_RESET) += at91sam9_alt_reset.o
- obj-$(CONFIG_AT91_SAM9G45_RESET) += at91sam9g45_reset.o
-+obj-$(CONFIG_SOC_AT91SAM9) += at91sam926x_time.o sam9_smc.o
-
- # CPU-specific support
- obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o
--obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
--obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o
--obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o
--obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o
--obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o
--obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
--obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o
--obj-$(CONFIG_ARCH_AT91SAM9X5) += at91sam9x5.o at91sam926x_time.o sam9_smc.o
-+obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam9260_devices.o
-+obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam9261_devices.o
-+obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam9261_devices.o
-+obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam9263_devices.o
-+obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam9rl_devices.o
-+obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam9260_devices.o
-+obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam9g45_devices.o
-+obj-$(CONFIG_ARCH_AT91SAM9X5) += at91sam9x5.o
- obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o
-
- # AT91RM9200 board-specific support
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From f9375e3c4c45dafefe52350547b1f927f966ddd3 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 6 Apr 2012 11:51:50 +0800
-Subject: ARN: at91: introduce SOC_AT91xxx define to allow to compile SoC core
- support
-
-commit 1e3ce2b8545390a2aee8dbfcd49ca4161b636000 upstream.
-
-We can now compile all SoC core support together and DT boards.
-We still can not compile together the non DT board.
-So We keep the ARCH_AT91xxx for the non DT board and for backward defconfig
-compatibility. This will enable the plaform_device ressources.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/configs/at91rm9200_defconfig | 1 +
- arch/arm/mach-at91/Kconfig | 91 ++++++++++++++++++++++++-----------
- arch/arm/mach-at91/Makefile | 25 ++++++----
- arch/arm/mach-at91/include/mach/cpu.h | 28 +++++------
- arch/arm/mach-at91/pm.h | 2 +-
- arch/arm/mach-at91/pm_slowclock.S | 2 +-
- arch/arm/mach-at91/soc.h | 14 +++---
- 7 files changed, 101 insertions(+), 62 deletions(-)
-
-diff --git a/arch/arm/configs/at91rm9200_defconfig b/arch/arm/configs/at91rm9200_defconfig
-index bbe4e1a..d54e2ac 100644
---- a/arch/arm/configs/at91rm9200_defconfig
-+++ b/arch/arm/configs/at91rm9200_defconfig
-@@ -14,6 +14,7 @@ CONFIG_MODULE_SRCVERSION_ALL=y
- # CONFIG_BLK_DEV_BSG is not set
- # CONFIG_IOSCHED_CFQ is not set
- CONFIG_ARCH_AT91=y
-+CONFIG_ARCH_AT91RM9200=y
- CONFIG_MACH_ONEARM=y
- CONFIG_ARCH_AT91RM9200DK=y
- CONFIG_MACH_AT91RM9200EK=y
-diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
-index 40e31c7..98a42f3 100644
---- a/arch/arm/mach-at91/Kconfig
-+++ b/arch/arm/mach-at91/Kconfig
-@@ -24,68 +24,66 @@ config SOC_AT91SAM9
-
- menu "Atmel AT91 System-on-Chip"
-
--choice
-- prompt "Atmel AT91 Processor"
-+comment "Atmel AT91 Processor"
-
--config ARCH_AT91RM9200
-+config SOC_AT91SAM9
-+ bool
-+ select CPU_ARM926T
-+ select AT91_SAM9_TIME
-+ select AT91_SAM9_SMC
-+
-+config SOC_AT91RM9200
- bool "AT91RM9200"
- select CPU_ARM920T
- select GENERIC_CLOCKEVENTS
- select HAVE_AT91_DBGU0
-
--config ARCH_AT91SAM9260
-- bool "AT91SAM9260 or AT91SAM9XE"
-+config SOC_AT91SAM9260
-+ bool "AT91SAM9260, AT91SAM9XE or AT91SAM9G20"
- select SOC_AT91SAM9
- select HAVE_AT91_DBGU0
- select HAVE_NET_MACB
-+ help
-+ Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE
-+ or AT91SAM9G20 SoC.
-
--config ARCH_AT91SAM9261
-- bool "AT91SAM9261"
-- select SOC_AT91SAM9
-- select HAVE_FB_ATMEL
-- select HAVE_AT91_DBGU0
--
--config ARCH_AT91SAM9G10
-- bool "AT91SAM9G10"
-+config SOC_AT91SAM9261
-+ bool "AT91SAM9261 or AT91SAM9G10"
- select SOC_AT91SAM9
- select HAVE_AT91_DBGU0
- select HAVE_FB_ATMEL
-+ help
-+ Select this if you are using one of Atmel's AT91SAM9261 or AT91SAM9G10 SoC.
-
--config ARCH_AT91SAM9263
-+config SOC_AT91SAM9263
- bool "AT91SAM9263"
- select SOC_AT91SAM9
-+ select HAVE_AT91_DBGU1
- select HAVE_FB_ATMEL
- select HAVE_NET_MACB
-- select HAVE_AT91_DBGU1
-
--config ARCH_AT91SAM9RL
-+config SOC_AT91SAM9RL
- bool "AT91SAM9RL"
- select SOC_AT91SAM9
-- select HAVE_FB_ATMEL
- select HAVE_AT91_DBGU0
-+ select HAVE_FB_ATMEL
-
--config ARCH_AT91SAM9G20
-- bool "AT91SAM9G20"
-- select SOC_AT91SAM9
-- select HAVE_AT91_DBGU0
-- select HAVE_NET_MACB
--
--config ARCH_AT91SAM9G45
-+config SOC_AT91SAM9G45
- bool "AT91SAM9G45 or AT91SAM9M10 families"
- select SOC_AT91SAM9
-+ select HAVE_AT91_DBGU1
- select HAVE_FB_ATMEL
- select HAVE_NET_MACB
-- select HAVE_AT91_DBGU1
- help
- Select this if you are using one of Atmel's AT91SAM9G45 family SoC.
- This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11.
-
--config ARCH_AT91SAM9X5
-+config SOC_AT91SAM9X5
- bool "AT91SAM9x5 family"
- select SOC_AT91SAM9
-+ select HAVE_AT91_DBGU0
- select HAVE_FB_ATMEL
- select HAVE_NET_MACB
-- select HAVE_AT91_DBGU0
- help
- Select this if you are using one of Atmel's AT91SAM9x5 family SoC.
- This means that your SAM9 name finishes with a '5' (except if it is
-@@ -93,8 +91,47 @@ config ARCH_AT91SAM9X5
- This support covers AT91SAM9G15, AT91SAM9G25, AT91SAM9X25, AT91SAM9G35
- and AT91SAM9X35.
-
-+choice
-+ prompt "Atmel AT91 Processor Devices for non DT boards"
-+
-+config ARCH_AT91_NONE
-+ bool "None"
-+
-+config ARCH_AT91RM9200
-+ bool "AT91RM9200"
-+ select SOC_AT91RM9200
-+
-+config ARCH_AT91SAM9260
-+ bool "AT91SAM9260 or AT91SAM9XE"
-+ select SOC_AT91SAM9260
-+
-+config ARCH_AT91SAM9261
-+ bool "AT91SAM9261"
-+ select SOC_AT91SAM9261
-+
-+config ARCH_AT91SAM9G10
-+ bool "AT91SAM9G10"
-+ select SOC_AT91SAM9261
-+
-+config ARCH_AT91SAM9263
-+ bool "AT91SAM9263"
-+ select SOC_AT91SAM9263
-+
-+config ARCH_AT91SAM9RL
-+ bool "AT91SAM9RL"
-+ select SOC_AT91SAM9RL
-+
-+config ARCH_AT91SAM9G20
-+ bool "AT91SAM9G20"
-+ select SOC_AT91SAM9260
-+
-+config ARCH_AT91SAM9G45
-+ bool "AT91SAM9G45"
-+ select SOC_AT91SAM9G45
-+
- config ARCH_AT91X40
- bool "AT91x40"
-+ depends on !MMU
- select ARCH_USES_GETTIMEOFFSET
-
- endchoice
-diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
-index d97d0f4..79d0f60 100644
---- a/arch/arm/mach-at91/Makefile
-+++ b/arch/arm/mach-at91/Makefile
-@@ -13,15 +13,22 @@ obj-$(CONFIG_AT91_SAM9G45_RESET) += at91sam9g45_reset.o
- obj-$(CONFIG_SOC_AT91SAM9) += at91sam926x_time.o sam9_smc.o
-
- # CPU-specific support
--obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o
--obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam9260_devices.o
--obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam9261_devices.o
--obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam9261_devices.o
--obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam9263_devices.o
--obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam9rl_devices.o
--obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam9260_devices.o
--obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam9g45_devices.o
--obj-$(CONFIG_ARCH_AT91SAM9X5) += at91sam9x5.o
-+obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o at91rm9200_time.o
-+obj-$(CONFIG_SOC_AT91SAM9260) += at91sam9260.o
-+obj-$(CONFIG_SOC_AT91SAM9261) += at91sam9261.o
-+obj-$(CONFIG_SOC_AT91SAM9263) += at91sam9263.o
-+obj-$(CONFIG_SOC_AT91SAM9G45) += at91sam9g45.o
-+obj-$(CONFIG_SOC_AT91SAM9X5) += at91sam9x5.o
-+obj-$(CONFIG_SOC_AT91SAM9RL) += at91sam9rl.o
-+
-+obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200_devices.o
-+obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260_devices.o
-+obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261_devices.o
-+obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261_devices.o
-+obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263_devices.o
-+obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl_devices.o
-+obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260_devices.o
-+obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45_devices.o
- obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o
-
- # AT91RM9200 board-specific support
-diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h
-index 0118c33..73d2fd2 100644
---- a/arch/arm/mach-at91/include/mach/cpu.h
-+++ b/arch/arm/mach-at91/include/mach/cpu.h
-@@ -54,6 +54,7 @@
- #define ARCH_REVISON_9200_BGA (0 << 0)
- #define ARCH_REVISON_9200_PQFP (1 << 0)
-
-+#ifndef __ASSEMBLY__
- enum at91_soc_type {
- /* 920T */
- AT91_SOC_RM9200,
-@@ -106,7 +107,7 @@ static inline int at91_soc_is_detected(void)
- return at91_soc_initdata.type != AT91_SOC_NONE;
- }
-
--#ifdef CONFIG_ARCH_AT91RM9200
-+#ifdef CONFIG_SOC_AT91RM9200
- #define cpu_is_at91rm9200() (at91_soc_initdata.type == AT91_SOC_RM9200)
- #define cpu_is_at91rm9200_bga() (at91_soc_initdata.subtype == AT91_SOC_RM9200_BGA)
- #define cpu_is_at91rm9200_pqfp() (at91_soc_initdata.subtype == AT91_SOC_RM9200_PQFP)
-@@ -116,45 +117,37 @@ static inline int at91_soc_is_detected(void)
- #define cpu_is_at91rm9200_pqfp() (0)
- #endif
-
--#ifdef CONFIG_ARCH_AT91SAM9260
-+#ifdef CONFIG_SOC_AT91SAM9260
- #define cpu_is_at91sam9xe() (at91_soc_initdata.subtype == AT91_SOC_SAM9XE)
- #define cpu_is_at91sam9260() (at91_soc_initdata.type == AT91_SOC_SAM9260)
-+#define cpu_is_at91sam9g20() (at91_soc_initdata.type == AT91_SOC_SAM9G20)
- #else
- #define cpu_is_at91sam9xe() (0)
- #define cpu_is_at91sam9260() (0)
--#endif
--
--#ifdef CONFIG_ARCH_AT91SAM9G20
--#define cpu_is_at91sam9g20() (at91_soc_initdata.type == AT91_SOC_SAM9G20)
--#else
- #define cpu_is_at91sam9g20() (0)
- #endif
-
--#ifdef CONFIG_ARCH_AT91SAM9261
-+#ifdef CONFIG_SOC_AT91SAM9261
- #define cpu_is_at91sam9261() (at91_soc_initdata.type == AT91_SOC_SAM9261)
--#else
--#define cpu_is_at91sam9261() (0)
--#endif
--
--#ifdef CONFIG_ARCH_AT91SAM9G10
- #define cpu_is_at91sam9g10() (at91_soc_initdata.type == AT91_SOC_SAM9G10)
- #else
-+#define cpu_is_at91sam9261() (0)
- #define cpu_is_at91sam9g10() (0)
- #endif
-
--#ifdef CONFIG_ARCH_AT91SAM9263
-+#ifdef CONFIG_SOC_AT91SAM9263
- #define cpu_is_at91sam9263() (at91_soc_initdata.type == AT91_SOC_SAM9263)
- #else
- #define cpu_is_at91sam9263() (0)
- #endif
-
--#ifdef CONFIG_ARCH_AT91SAM9RL
-+#ifdef CONFIG_SOC_AT91SAM9RL
- #define cpu_is_at91sam9rl() (at91_soc_initdata.type == AT91_SOC_SAM9RL)
- #else
- #define cpu_is_at91sam9rl() (0)
- #endif
-
--#ifdef CONFIG_ARCH_AT91SAM9G45
-+#ifdef CONFIG_SOC_AT91SAM9G45
- #define cpu_is_at91sam9g45() (at91_soc_initdata.type == AT91_SOC_SAM9G45)
- #define cpu_is_at91sam9g45es() (at91_soc_initdata.subtype == AT91_SOC_SAM9G45ES)
- #define cpu_is_at91sam9m10() (at91_soc_initdata.subtype == AT91_SOC_SAM9M10)
-@@ -168,7 +161,7 @@ static inline int at91_soc_is_detected(void)
- #define cpu_is_at91sam9m11() (0)
- #endif
-
--#ifdef CONFIG_ARCH_AT91SAM9X5
-+#ifdef CONFIG_SOC_AT91SAM9X5
- #define cpu_is_at91sam9x5() (at91_soc_initdata.type == AT91_SOC_SAM9X5)
- #define cpu_is_at91sam9g15() (at91_soc_initdata.subtype == AT91_SOC_SAM9G15)
- #define cpu_is_at91sam9g35() (at91_soc_initdata.subtype == AT91_SOC_SAM9G35)
-@@ -189,5 +182,6 @@ static inline int at91_soc_is_detected(void)
- * definitions may reduce clutter in common drivers.
- */
- #define cpu_is_at32ap7000() (0)
-+#endif /* __ASSEMBLY__ */
-
- #endif /* __MACH_CPU_H__ */
-diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
-index 1b4865e..38f467c 100644
---- a/arch/arm/mach-at91/pm.h
-+++ b/arch/arm/mach-at91/pm.h
-@@ -70,7 +70,7 @@ static inline void at91sam9g45_standby(void)
- at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
- }
-
--#ifdef CONFIG_ARCH_AT91SAM9263
-+#ifdef CONFIG_SOC_AT91SAM9263
- /*
- * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
- * handle those cases both here and in the Suspend-To-RAM support.
-diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_slowclock.S
-index db54521..098c28d 100644
---- a/arch/arm/mach-at91/pm_slowclock.S
-+++ b/arch/arm/mach-at91/pm_slowclock.S
-@@ -18,7 +18,7 @@
- #include <mach/at91_ramc.h>
-
-
--#ifdef CONFIG_ARCH_AT91SAM9263
-+#ifdef CONFIG_SOC_AT91SAM9263
- /*
- * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
- * handle those cases both here and in the Suspend-To-RAM support.
-diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
-index 5db4aa4..683dddf 100644
---- a/arch/arm/mach-at91/soc.h
-+++ b/arch/arm/mach-at91/soc.h
-@@ -26,30 +26,30 @@ static inline int at91_soc_is_enabled(void)
- return at91_boot_soc.init != NULL;
- }
-
--#if !defined(CONFIG_ARCH_AT91RM9200)
-+#if !defined(CONFIG_SOC_AT91RM9200)
- #define at91rm9200_soc at91_boot_soc
- #endif
-
--#if !(defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20))
-+#if !defined(CONFIG_SOC_AT91SAM9260)
- #define at91sam9260_soc at91_boot_soc
- #endif
-
--#if !(defined(CONFIG_ARCH_AT91SAM9261) || defined(CONFIG_ARCH_AT91SAM9G10))
-+#if !defined(CONFIG_SOC_AT91SAM9261)
- #define at91sam9261_soc at91_boot_soc
- #endif
-
--#if !defined(CONFIG_ARCH_AT91SAM9263)
-+#if !defined(CONFIG_SOC_AT91SAM9263)
- #define at91sam9263_soc at91_boot_soc
- #endif
-
--#if !defined(CONFIG_ARCH_AT91SAM9G45)
-+#if !defined(CONFIG_SOC_AT91SAM9G45)
- #define at91sam9g45_soc at91_boot_soc
- #endif
-
--#if !defined(CONFIG_ARCH_AT91SAM9RL)
-+#if !defined(CONFIG_SOC_AT91SAM9RL)
- #define at91sam9rl_soc at91_boot_soc
- #endif
-
--#if !defined(CONFIG_ARCH_AT91SAM9X5)
-+#if !defined(CONFIG_SOC_AT91SAM9X5)
- #define at91sam9x5_soc at91_boot_soc
- #endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 48fbfca1c5db644eb14c62307d2608def41a78cf Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Thu, 1 Mar 2012 14:47:44 +0800
-Subject: ARM: at91/dt: do not specify the board any more
-
-commit 7c8a98c8c0475f0659beb9798f6ddebc2c840079 upstream.
-
-This will allow to add any board to a compiled kernel by just passing the DTB.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/board-dt.c | 8 +-------
- 1 file changed, 1 insertion(+), 7 deletions(-)
-
-diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
-index c18d4d3..a1fce05 100644
---- a/arch/arm/mach-at91/board-dt.c
-+++ b/arch/arm/mach-at91/board-dt.c
-@@ -1,10 +1,6 @@
- /*
- * Setup code for AT91SAM Evaluation Kits with Device Tree support
- *
-- * Covers: * AT91SAM9G45-EKES board
-- * * AT91SAM9M10-EKES board
-- * * AT91SAM9M10G45-EK board
-- *
- * Copyright (C) 2011 Atmel,
- * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>
- *
-@@ -49,9 +45,7 @@ static void __init at91_dt_device_init(void)
- }
-
- static const char *at91_dt_board_compat[] __initdata = {
-- "atmel,at91sam9m10g45ek",
-- "atmel,at91sam9x5ek",
-- "calao,usb-a9g20",
-+ "atmel,at91sam9",
- NULL
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 5227ce7aea2f044e2e189626ea6f8d0cb7ac682c Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Sun, 8 Apr 2012 17:40:06 +0200
-Subject: ARM: at91: add defconfig for device tree
-
-commit 39ecc143b4c1f3d42e8300e7f5274681b99f95c2 upstream.
-
-This will enable all current SoC support on DT (9260, 9g20, 9g45 family
-and 9x5 family).
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/configs/at91_dt_defconfig | 196 +++++++++++++++++++++++++++++++++++++
- 1 file changed, 196 insertions(+)
- create mode 100644 arch/arm/configs/at91_dt_defconfig
-
-diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig
-new file mode 100644
-index 0000000..67bc571
---- /dev/null
-+++ b/arch/arm/configs/at91_dt_defconfig
-@@ -0,0 +1,196 @@
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_LOCALVERSION_AUTO is not set
-+# CONFIG_SWAP is not set
-+CONFIG_SYSVIPC=y
-+CONFIG_LOG_BUF_SHIFT=14
-+CONFIG_BLK_DEV_INITRD=y
-+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-+CONFIG_KALLSYMS_ALL=y
-+CONFIG_EMBEDDED=y
-+CONFIG_SLAB=y
-+CONFIG_MODULES=y
-+CONFIG_MODULE_UNLOAD=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_ARCH_AT91=y
-+CONFIG_SOC_AT91SAM9260=y
-+CONFIG_SOC_AT91SAM9263=y
-+CONFIG_SOC_AT91SAM9G45=y
-+CONFIG_SOC_AT91SAM9X5=y
-+CONFIG_MACH_AT91SAM_DT=y
-+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-+CONFIG_AT91_TIMER_HZ=128
-+CONFIG_AEABI=y
-+# CONFIG_OABI_COMPAT is not set
-+CONFIG_LEDS=y
-+CONFIG_LEDS_CPU=y
-+CONFIG_UACCESS_WITH_MEMCPY=y
-+CONFIG_ZBOOT_ROM_TEXT=0x0
-+CONFIG_ZBOOT_ROM_BSS=0x0
-+CONFIG_ARM_APPENDED_DTB=y
-+CONFIG_ARM_ATAG_DTB_COMPAT=y
-+CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw"
-+CONFIG_KEXEC=y
-+CONFIG_AUTO_ZRELADDR=y
-+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-+CONFIG_NET=y
-+CONFIG_PACKET=y
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+CONFIG_IP_MULTICAST=y
-+CONFIG_IP_PNP=y
-+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-+# CONFIG_INET_XFRM_MODE_BEET is not set
-+# CONFIG_INET_DIAG is not set
-+CONFIG_IPV6=y
-+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-+# CONFIG_INET6_XFRM_MODE_BEET is not set
-+CONFIG_IPV6_SIT_6RD=y
-+# CONFIG_WIRELESS is not set
-+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-+CONFIG_DEVTMPFS=y
-+CONFIG_DEVTMPFS_MOUNT=y
-+# CONFIG_STANDALONE is not set
-+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-+CONFIG_MTD=y
-+CONFIG_MTD_CMDLINE_PARTS=y
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+CONFIG_MTD_NAND=y
-+CONFIG_MTD_NAND_ATMEL=y
-+CONFIG_MTD_UBI=y
-+CONFIG_MTD_UBI_GLUEBI=y
-+CONFIG_PROC_DEVICETREE=y
-+CONFIG_BLK_DEV_LOOP=y
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_BLK_DEV_RAM_COUNT=4
-+CONFIG_BLK_DEV_RAM_SIZE=8192
-+CONFIG_ATMEL_PWM=y
-+CONFIG_ATMEL_TCLIB=y
-+CONFIG_EEPROM_93CX6=m
-+CONFIG_SCSI=y
-+CONFIG_BLK_DEV_SD=y
-+CONFIG_SCSI_MULTI_LUN=y
-+# CONFIG_SCSI_LOWLEVEL is not set
-+CONFIG_NETDEVICES=y
-+CONFIG_MII=y
-+CONFIG_MACB=y
-+# CONFIG_NET_VENDOR_BROADCOM is not set
-+# CONFIG_NET_VENDOR_CHELSIO is not set
-+# CONFIG_NET_VENDOR_FARADAY is not set
-+# CONFIG_NET_VENDOR_INTEL is not set
-+# CONFIG_NET_VENDOR_MARVELL is not set
-+# CONFIG_NET_VENDOR_MICREL is not set
-+# CONFIG_NET_VENDOR_NATSEMI is not set
-+# CONFIG_NET_VENDOR_SEEQ is not set
-+# CONFIG_NET_VENDOR_SMSC is not set
-+# CONFIG_NET_VENDOR_STMICRO is not set
-+CONFIG_DAVICOM_PHY=y
-+CONFIG_MICREL_PHY=y
-+# CONFIG_WLAN is not set
-+CONFIG_INPUT_POLLDEV=y
-+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-+CONFIG_INPUT_MOUSEDEV_SCREEN_X=480
-+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=272
-+CONFIG_INPUT_JOYDEV=y
-+CONFIG_INPUT_EVDEV=y
-+# CONFIG_KEYBOARD_ATKBD is not set
-+CONFIG_KEYBOARD_GPIO=y
-+# CONFIG_INPUT_MOUSE is not set
-+CONFIG_INPUT_TOUCHSCREEN=y
-+# CONFIG_SERIO is not set
-+CONFIG_LEGACY_PTY_COUNT=4
-+CONFIG_SERIAL_ATMEL=y
-+CONFIG_SERIAL_ATMEL_CONSOLE=y
-+CONFIG_HW_RANDOM=y
-+CONFIG_I2C=y
-+CONFIG_I2C_GPIO=y
-+CONFIG_SPI=y
-+CONFIG_SPI_ATMEL=y
-+# CONFIG_HWMON is not set
-+CONFIG_WATCHDOG=y
-+CONFIG_AT91SAM9X_WATCHDOG=y
-+CONFIG_SSB=m
-+CONFIG_FB=y
-+CONFIG_FB_MODE_HELPERS=y
-+CONFIG_FB_ATMEL=y
-+CONFIG_BACKLIGHT_LCD_SUPPORT=y
-+# CONFIG_LCD_CLASS_DEVICE is not set
-+CONFIG_BACKLIGHT_CLASS_DEVICE=y
-+CONFIG_BACKLIGHT_ATMEL_LCDC=y
-+# CONFIG_BACKLIGHT_GENERIC is not set
-+CONFIG_FRAMEBUFFER_CONSOLE=y
-+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
-+CONFIG_FONTS=y
-+CONFIG_FONT_8x8=y
-+CONFIG_FONT_ACORN_8x8=y
-+CONFIG_FONT_MINI_4x6=y
-+CONFIG_LOGO=y
-+# CONFIG_HID_SUPPORT is not set
-+CONFIG_USB=y
-+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-+CONFIG_USB_DEVICEFS=y
-+# CONFIG_USB_DEVICE_CLASS is not set
-+CONFIG_USB_EHCI_HCD=y
-+CONFIG_USB_OHCI_HCD=y
-+CONFIG_USB_ACM=y
-+CONFIG_USB_STORAGE=y
-+CONFIG_USB_SERIAL=y
-+CONFIG_USB_SERIAL_GENERIC=y
-+CONFIG_USB_SERIAL_FTDI_SIO=y
-+CONFIG_USB_SERIAL_PL2303=y
-+CONFIG_USB_GADGET=y
-+CONFIG_USB_AT91=m
-+CONFIG_USB_ATMEL_USBA=m
-+CONFIG_USB_ETH=m
-+CONFIG_USB_GADGETFS=m
-+CONFIG_USB_CDC_COMPOSITE=m
-+CONFIG_USB_G_ACM_MS=m
-+CONFIG_USB_G_MULTI=m
-+CONFIG_USB_G_MULTI_CDC=y
-+CONFIG_MMC=y
-+CONFIG_MMC_ATMELMCI=y
-+CONFIG_NEW_LEDS=y
-+CONFIG_LEDS_CLASS=y
-+CONFIG_LEDS_GPIO=y
-+CONFIG_LEDS_TRIGGERS=y
-+CONFIG_LEDS_TRIGGER_TIMER=y
-+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-+CONFIG_LEDS_TRIGGER_GPIO=y
-+CONFIG_RTC_CLASS=y
-+CONFIG_RTC_DRV_AT91RM9200=y
-+CONFIG_RTC_DRV_AT91SAM9=y
-+CONFIG_DMADEVICES=y
-+# CONFIG_IOMMU_SUPPORT is not set
-+CONFIG_EXT2_FS=y
-+CONFIG_FANOTIFY=y
-+CONFIG_VFAT_FS=y
-+CONFIG_TMPFS=y
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+CONFIG_ROOT_NFS=y
-+CONFIG_NLS_CODEPAGE_437=y
-+CONFIG_NLS_CODEPAGE_850=y
-+CONFIG_NLS_ISO8859_1=y
-+CONFIG_STRIP_ASM_SYMS=y
-+CONFIG_DEBUG_FS=y
-+# CONFIG_SCHED_DEBUG is not set
-+# CONFIG_DEBUG_BUGVERBOSE is not set
-+# CONFIG_FTRACE is not set
-+CONFIG_DEBUG_USER=y
-+CONFIG_CRYPTO=y
-+CONFIG_CRYPTO_ECB=y
-+CONFIG_CRYPTO_AES=y
-+CONFIG_CRYPTO_ARC4=y
-+# CONFIG_CRYPTO_ANSI_CPRNG is not set
-+CONFIG_CRYPTO_USER_API_HASH=m
-+CONFIG_CRYPTO_USER_API_SKCIPHER=m
-+# CONFIG_CRYPTO_HW is not set
-+CONFIG_CRC_CCITT=m
-+CONFIG_CRC_ITU_T=m
-+CONFIG_CRC7=m
-+CONFIG_AVERAGE=y
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 91c5d96f8c4ace401677cb00a843a1ab9f8646c6 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Mon, 9 Apr 2012 19:26:33 +0800
-Subject: ARM: at91: add at91sam9260 DT support
-
-commit 5b6089cb6f283b29e7b1e181f95afd3dcf2d8948 upstream.
-
-The at91sam9260 and at91sam9g20 share most of the same IP.
-So udpate the node property in the at91sam9g20 only.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/at91sam9260.dtsi | 238 +++++++++++++++++++++++++++++++++++++
- arch/arm/boot/dts/at91sam9g20.dtsi | 226 +----------------------------------
- arch/arm/mach-at91/Makefile.boot | 1 +
- 3 files changed, 242 insertions(+), 223 deletions(-)
- create mode 100644 arch/arm/boot/dts/at91sam9260.dtsi
-
-diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
-new file mode 100644
-index 0000000..f4605ff
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9260.dtsi
-@@ -0,0 +1,238 @@
-+/*
-+ * at91sam9260.dtsi - Device Tree Include file for AT91SAM9260 family SoC
-+ *
-+ * Copyright (C) 2011 Atmel,
-+ * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>,
-+ * 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2 or later.
-+ */
-+
-+/include/ "skeleton.dtsi"
-+
-+/ {
-+ model = "Atmel AT91SAM9260 family SoC";
-+ compatible = "atmel,at91sam9260";
-+ interrupt-parent = <&aic>;
-+
-+ aliases {
-+ serial0 = &dbgu;
-+ serial1 = &usart0;
-+ serial2 = &usart1;
-+ serial3 = &usart2;
-+ serial4 = &usart3;
-+ serial5 = &usart4;
-+ serial6 = &usart5;
-+ gpio0 = &pioA;
-+ gpio1 = &pioB;
-+ gpio2 = &pioC;
-+ tcb0 = &tcb0;
-+ tcb1 = &tcb1;
-+ };
-+ cpus {
-+ cpu@0 {
-+ compatible = "arm,arm926ejs";
-+ };
-+ };
-+
-+ memory {
-+ reg = <0x20000000 0x04000000>;
-+ };
-+
-+ ahb {
-+ compatible = "simple-bus";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ apb {
-+ compatible = "simple-bus";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ aic: interrupt-controller@fffff000 {
-+ #interrupt-cells = <2>;
-+ compatible = "atmel,at91rm9200-aic";
-+ interrupt-controller;
-+ reg = <0xfffff000 0x200>;
-+ };
-+
-+ ramc0: ramc@ffffea00 {
-+ compatible = "atmel,at91sam9260-sdramc";
-+ reg = <0xffffea00 0x200>;
-+ };
-+
-+ pmc: pmc@fffffc00 {
-+ compatible = "atmel,at91rm9200-pmc";
-+ reg = <0xfffffc00 0x100>;
-+ };
-+
-+ rstc@fffffd00 {
-+ compatible = "atmel,at91sam9260-rstc";
-+ reg = <0xfffffd00 0x10>;
-+ };
-+
-+ shdwc@fffffd10 {
-+ compatible = "atmel,at91sam9260-shdwc";
-+ reg = <0xfffffd10 0x10>;
-+ };
-+
-+ pit: timer@fffffd30 {
-+ compatible = "atmel,at91sam9260-pit";
-+ reg = <0xfffffd30 0xf>;
-+ interrupts = <1 4>;
-+ };
-+
-+ tcb0: timer@fffa0000 {
-+ compatible = "atmel,at91rm9200-tcb";
-+ reg = <0xfffa0000 0x100>;
-+ interrupts = <17 4 18 4 19 4>;
-+ };
-+
-+ tcb1: timer@fffdc000 {
-+ compatible = "atmel,at91rm9200-tcb";
-+ reg = <0xfffdc000 0x100>;
-+ interrupts = <26 4 27 4 28 4>;
-+ };
-+
-+ pioA: gpio@fffff400 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff400 0x100>;
-+ interrupts = <2 4>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ };
-+
-+ pioB: gpio@fffff600 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff600 0x100>;
-+ interrupts = <3 4>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ };
-+
-+ pioC: gpio@fffff800 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff800 0x100>;
-+ interrupts = <4 4>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ };
-+
-+ dbgu: serial@fffff200 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xfffff200 0x200>;
-+ interrupts = <1 4>;
-+ status = "disabled";
-+ };
-+
-+ usart0: serial@fffb0000 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xfffb0000 0x200>;
-+ interrupts = <6 4>;
-+ atmel,use-dma-rx;
-+ atmel,use-dma-tx;
-+ status = "disabled";
-+ };
-+
-+ usart1: serial@fffb4000 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xfffb4000 0x200>;
-+ interrupts = <7 4>;
-+ atmel,use-dma-rx;
-+ atmel,use-dma-tx;
-+ status = "disabled";
-+ };
-+
-+ usart2: serial@fffb8000 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xfffb8000 0x200>;
-+ interrupts = <8 4>;
-+ atmel,use-dma-rx;
-+ atmel,use-dma-tx;
-+ status = "disabled";
-+ };
-+
-+ usart3: serial@fffd0000 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xfffd0000 0x200>;
-+ interrupts = <23 4>;
-+ atmel,use-dma-rx;
-+ atmel,use-dma-tx;
-+ status = "disabled";
-+ };
-+
-+ usart4: serial@fffd4000 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xfffd4000 0x200>;
-+ interrupts = <24 4>;
-+ atmel,use-dma-rx;
-+ atmel,use-dma-tx;
-+ status = "disabled";
-+ };
-+
-+ usart5: serial@fffd8000 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xfffd8000 0x200>;
-+ interrupts = <25 4>;
-+ atmel,use-dma-rx;
-+ atmel,use-dma-tx;
-+ status = "disabled";
-+ };
-+
-+ macb0: ethernet@fffc4000 {
-+ compatible = "cdns,at32ap7000-macb", "cdns,macb";
-+ reg = <0xfffc4000 0x100>;
-+ interrupts = <21 4>;
-+ status = "disabled";
-+ };
-+
-+ usb1: gadget@fffa4000 {
-+ compatible = "atmel,at91rm9200-udc";
-+ reg = <0xfffa4000 0x4000>;
-+ interrupts = <10 4>;
-+ status = "disabled";
-+ };
-+ };
-+
-+ nand0: nand@40000000 {
-+ compatible = "atmel,at91rm9200-nand";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ reg = <0x40000000 0x10000000
-+ 0xffffe800 0x200
-+ >;
-+ atmel,nand-addr-offset = <21>;
-+ atmel,nand-cmd-offset = <22>;
-+ gpios = <&pioC 13 0
-+ &pioC 14 0
-+ 0
-+ >;
-+ status = "disabled";
-+ };
-+
-+ usb0: ohci@00500000 {
-+ compatible = "atmel,at91rm9200-ohci", "usb-ohci";
-+ reg = <0x00500000 0x100000>;
-+ interrupts = <20 4>;
-+ status = "disabled";
-+ };
-+ };
-+
-+ i2c@0 {
-+ compatible = "i2c-gpio";
-+ gpios = <&pioA 23 0 /* sda */
-+ &pioA 24 0 /* scl */
-+ >;
-+ i2c-gpio,sda-open-drain;
-+ i2c-gpio,scl-open-drain;
-+ i2c-gpio,delay-us = <2>; /* ~100 kHz */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+};
-diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi
-index 773ef48..0eb1a75 100644
---- a/arch/arm/boot/dts/at91sam9g20.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g20.dtsi
-@@ -1,238 +1,18 @@
- /*
- * at91sam9g20.dtsi - Device Tree Include file for AT91SAM9G20 family SoC
- *
-- * Copyright (C) 2011 Atmel,
-- * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>,
-- * 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
- *
-- * Licensed under GPLv2 or later.
-+ * Licensed under GPLv2.
- */
-
--/include/ "skeleton.dtsi"
-+/include/ "at91sam9260.dtsi"
-
- / {
- model = "Atmel AT91SAM9G20 family SoC";
- compatible = "atmel,at91sam9g20";
-- interrupt-parent = <&aic>;
--
-- aliases {
-- serial0 = &dbgu;
-- serial1 = &usart0;
-- serial2 = &usart1;
-- serial3 = &usart2;
-- serial4 = &usart3;
-- serial5 = &usart4;
-- serial6 = &usart5;
-- gpio0 = &pioA;
-- gpio1 = &pioB;
-- gpio2 = &pioC;
-- tcb0 = &tcb0;
-- tcb1 = &tcb1;
-- };
-- cpus {
-- cpu@0 {
-- compatible = "arm,arm926ejs";
-- };
-- };
-
- memory {
- reg = <0x20000000 0x08000000>;
- };
--
-- ahb {
-- compatible = "simple-bus";
-- #address-cells = <1>;
-- #size-cells = <1>;
-- ranges;
--
-- apb {
-- compatible = "simple-bus";
-- #address-cells = <1>;
-- #size-cells = <1>;
-- ranges;
--
-- aic: interrupt-controller@fffff000 {
-- #interrupt-cells = <2>;
-- compatible = "atmel,at91rm9200-aic";
-- interrupt-controller;
-- reg = <0xfffff000 0x200>;
-- };
--
-- ramc0: ramc@ffffea00 {
-- compatible = "atmel,at91sam9260-sdramc";
-- reg = <0xffffea00 0x200>;
-- };
--
-- pmc: pmc@fffffc00 {
-- compatible = "atmel,at91rm9200-pmc";
-- reg = <0xfffffc00 0x100>;
-- };
--
-- rstc@fffffd00 {
-- compatible = "atmel,at91sam9260-rstc";
-- reg = <0xfffffd00 0x10>;
-- };
--
-- shdwc@fffffd10 {
-- compatible = "atmel,at91sam9260-shdwc";
-- reg = <0xfffffd10 0x10>;
-- };
--
-- pit: timer@fffffd30 {
-- compatible = "atmel,at91sam9260-pit";
-- reg = <0xfffffd30 0xf>;
-- interrupts = <1 4>;
-- };
--
-- tcb0: timer@fffa0000 {
-- compatible = "atmel,at91rm9200-tcb";
-- reg = <0xfffa0000 0x100>;
-- interrupts = <17 4 18 4 19 4>;
-- };
--
-- tcb1: timer@fffdc000 {
-- compatible = "atmel,at91rm9200-tcb";
-- reg = <0xfffdc000 0x100>;
-- interrupts = <26 4 27 4 28 4>;
-- };
--
-- pioA: gpio@fffff400 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffff400 0x100>;
-- interrupts = <2 4>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- };
--
-- pioB: gpio@fffff600 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffff600 0x100>;
-- interrupts = <3 4>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- };
--
-- pioC: gpio@fffff800 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffff800 0x100>;
-- interrupts = <4 4>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- };
--
-- dbgu: serial@fffff200 {
-- compatible = "atmel,at91sam9260-usart";
-- reg = <0xfffff200 0x200>;
-- interrupts = <1 4>;
-- status = "disabled";
-- };
--
-- usart0: serial@fffb0000 {
-- compatible = "atmel,at91sam9260-usart";
-- reg = <0xfffb0000 0x200>;
-- interrupts = <6 4>;
-- atmel,use-dma-rx;
-- atmel,use-dma-tx;
-- status = "disabled";
-- };
--
-- usart1: serial@fffb4000 {
-- compatible = "atmel,at91sam9260-usart";
-- reg = <0xfffb4000 0x200>;
-- interrupts = <7 4>;
-- atmel,use-dma-rx;
-- atmel,use-dma-tx;
-- status = "disabled";
-- };
--
-- usart2: serial@fffb8000 {
-- compatible = "atmel,at91sam9260-usart";
-- reg = <0xfffb8000 0x200>;
-- interrupts = <8 4>;
-- atmel,use-dma-rx;
-- atmel,use-dma-tx;
-- status = "disabled";
-- };
--
-- usart3: serial@fffd0000 {
-- compatible = "atmel,at91sam9260-usart";
-- reg = <0xfffd0000 0x200>;
-- interrupts = <23 4>;
-- atmel,use-dma-rx;
-- atmel,use-dma-tx;
-- status = "disabled";
-- };
--
-- usart4: serial@fffd4000 {
-- compatible = "atmel,at91sam9260-usart";
-- reg = <0xfffd4000 0x200>;
-- interrupts = <24 4>;
-- atmel,use-dma-rx;
-- atmel,use-dma-tx;
-- status = "disabled";
-- };
--
-- usart5: serial@fffd8000 {
-- compatible = "atmel,at91sam9260-usart";
-- reg = <0xfffd8000 0x200>;
-- interrupts = <25 4>;
-- atmel,use-dma-rx;
-- atmel,use-dma-tx;
-- status = "disabled";
-- };
--
-- macb0: ethernet@fffc4000 {
-- compatible = "cdns,at32ap7000-macb", "cdns,macb";
-- reg = <0xfffc4000 0x100>;
-- interrupts = <21 4>;
-- status = "disabled";
-- };
--
-- usb1: gadget@fffa4000 {
-- compatible = "atmel,at91rm9200-udc";
-- reg = <0xfffa4000 0x4000>;
-- interrupts = <10 4>;
-- status = "disabled";
-- };
-- };
--
-- nand0: nand@40000000 {
-- compatible = "atmel,at91rm9200-nand";
-- #address-cells = <1>;
-- #size-cells = <1>;
-- reg = <0x40000000 0x10000000
-- 0xffffe800 0x200
-- >;
-- atmel,nand-addr-offset = <21>;
-- atmel,nand-cmd-offset = <22>;
-- gpios = <&pioC 13 0
-- &pioC 14 0
-- 0
-- >;
-- status = "disabled";
-- };
--
-- usb0: ohci@00500000 {
-- compatible = "atmel,at91rm9200-ohci", "usb-ohci";
-- reg = <0x00500000 0x100000>;
-- interrupts = <20 4>;
-- status = "disabled";
-- };
-- };
--
-- i2c@0 {
-- compatible = "i2c-gpio";
-- gpios = <&pioA 23 0 /* sda */
-- &pioA 24 0 /* scl */
-- >;
-- i2c-gpio,sda-open-drain;
-- i2c-gpio,scl-open-drain;
-- i2c-gpio,delay-us = <2>; /* ~100 kHz */
-- #address-cells = <1>;
-- #size-cells = <0>;
-- status = "disabled";
-- };
- };
-diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
-index 0da66ca..0c2336c 100644
---- a/arch/arm/mach-at91/Makefile.boot
-+++ b/arch/arm/mach-at91/Makefile.boot
-@@ -14,6 +14,7 @@ initrd_phys-y := 0x20410000
- endif
-
- # Keep dtb files sorted alphabetically for each SoC
-+# sam9260
- # sam9g20
- dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9g20.dtb
- # sam9g45
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e3ade6b868e15d2280fee9d17e5bdd0301411e76 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Mon, 30 Jan 2012 23:45:52 +0800
-Subject: arm: at91: add Calao TNY-A9260 and TNY-A9G20 board support
-
-commit 995376a54460ea2e6279ad96353323048f7db3ab upstream.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/tny_a9260.dts | 15 ++++++
- arch/arm/boot/dts/tny_a9260_common.dtsi | 83 +++++++++++++++++++++++++++++++++
- arch/arm/boot/dts/tny_a9g20.dts | 15 ++++++
- arch/arm/mach-at91/Makefile.boot | 2 +
- 4 files changed, 115 insertions(+)
- create mode 100644 arch/arm/boot/dts/tny_a9260.dts
- create mode 100644 arch/arm/boot/dts/tny_a9260_common.dtsi
- create mode 100644 arch/arm/boot/dts/tny_a9g20.dts
-
-diff --git a/arch/arm/boot/dts/tny_a9260.dts b/arch/arm/boot/dts/tny_a9260.dts
-new file mode 100644
-index 0000000..367a16d
---- /dev/null
-+++ b/arch/arm/boot/dts/tny_a9260.dts
-@@ -0,0 +1,15 @@
-+/*
-+ * tny_a9260.dts - Device Tree file for Caloa TNY A9260 board
-+ *
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2.
-+ */
-+/dts-v1/;
-+/include/ "at91sam9260.dtsi"
-+/include/ "tny_a9260_common.dtsi"
-+
-+/ {
-+ model = "Calao TNY A9260";
-+ compatible = "calao,tny-a9260", "atmel,at91sam9260", "atmel,at91sam9";
-+};
-diff --git a/arch/arm/boot/dts/tny_a9260_common.dtsi b/arch/arm/boot/dts/tny_a9260_common.dtsi
-new file mode 100644
-index 0000000..0e6d3de
---- /dev/null
-+++ b/arch/arm/boot/dts/tny_a9260_common.dtsi
-@@ -0,0 +1,83 @@
-+/*
-+ * tny_a9260_common.dtsi - Device Tree file for Caloa TNY A926x board
-+ *
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2.
-+ */
-+
-+/ {
-+ chosen {
-+ bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock6 rw rootfstype=ubifs";
-+ };
-+
-+ memory {
-+ reg = <0x20000000 0x4000000>;
-+ };
-+
-+ clocks {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ main_clock: clock@0 {
-+ compatible = "atmel,osc", "fixed-clock";
-+ clock-frequency = <12000000>;
-+ };
-+ };
-+
-+ ahb {
-+ apb {
-+ dbgu: serial@fffff200 {
-+ status = "okay";
-+ };
-+ };
-+
-+ nand0: nand@40000000 {
-+ nand-bus-width = <8>;
-+ nand-ecc-mode = "soft";
-+ nand-on-flash-bbt;
-+ status = "okay";
-+
-+ at91bootstrap@0 {
-+ label = "at91bootstrap";
-+ reg = <0x0 0x20000>;
-+ };
-+
-+ barebox@20000 {
-+ label = "barebox";
-+ reg = <0x20000 0x40000>;
-+ };
-+
-+ bareboxenv@60000 {
-+ label = "bareboxenv";
-+ reg = <0x60000 0x20000>;
-+ };
-+
-+ bareboxenv2@80000 {
-+ label = "bareboxenv2";
-+ reg = <0x80000 0x20000>;
-+ };
-+
-+ oftree@80000 {
-+ label = "oftree";
-+ reg = <0xa0000 0x20000>;
-+ };
-+
-+ kernel@a0000 {
-+ label = "kernel";
-+ reg = <0xc0000 0x400000>;
-+ };
-+
-+ rootfs@4a0000 {
-+ label = "rootfs";
-+ reg = <0x4c0000 0x7800000>;
-+ };
-+
-+ data@7ca0000 {
-+ label = "data";
-+ reg = <0x7cc0000 0x8340000>;
-+ };
-+ };
-+ };
-+};
-diff --git a/arch/arm/boot/dts/tny_a9g20.dts b/arch/arm/boot/dts/tny_a9g20.dts
-new file mode 100644
-index 0000000..e1ab64c
---- /dev/null
-+++ b/arch/arm/boot/dts/tny_a9g20.dts
-@@ -0,0 +1,15 @@
-+/*
-+ * tny_a9g20.dts - Device Tree file for Caloa TNY A9G20 board
-+ *
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2.
-+ */
-+/dts-v1/;
-+/include/ "at91sam9g20.dtsi"
-+/include/ "tny_a9260_common.dtsi"
-+
-+/ {
-+ model = "Calao TNY A9G20";
-+ compatible = "calao,tny-a9g20", "atmel,at91sam9g20", "atmel,at91sam9";
-+};
-diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
-index 0c2336c..bdf9841 100644
---- a/arch/arm/mach-at91/Makefile.boot
-+++ b/arch/arm/mach-at91/Makefile.boot
-@@ -15,7 +15,9 @@ endif
-
- # Keep dtb files sorted alphabetically for each SoC
- # sam9260
-+dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9260.dtb
- # sam9g20
-+dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9g20.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9g20.dtb
- # sam9g45
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9m10g45ek.dtb
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 8eb252d75d14c55d013aafe27d6fd74f587d7e53 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Mon, 13 Feb 2012 00:54:47 +0800
-Subject: ARM: at91: add at91sam9g20ek boards dt support
-
-commit 5cb4e73575e3c66b73ccda811b2ba70339703ea5 upstream.
-
-Add both board revision support 1mmc and 2mmc and use a dtsi for common part.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/at91sam9g20ek.dts | 29 ++++++
- arch/arm/boot/dts/at91sam9g20ek_2mmc.dts | 29 ++++++
- arch/arm/boot/dts/at91sam9g20ek_common.dtsi | 142 ++++++++++++++++++++++++++++
- arch/arm/mach-at91/Makefile.boot | 2 +
- 4 files changed, 202 insertions(+)
- create mode 100644 arch/arm/boot/dts/at91sam9g20ek.dts
- create mode 100644 arch/arm/boot/dts/at91sam9g20ek_2mmc.dts
- create mode 100644 arch/arm/boot/dts/at91sam9g20ek_common.dtsi
-
-diff --git a/arch/arm/boot/dts/at91sam9g20ek.dts b/arch/arm/boot/dts/at91sam9g20ek.dts
-new file mode 100644
-index 0000000..e5324bf
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9g20ek.dts
-@@ -0,0 +1,29 @@
-+/*
-+ * at91sam9g20ek.dts - Device Tree file for Atmel at91sam9g20ek board
-+ *
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2.
-+ */
-+/dts-v1/;
-+/include/ "at91sam9g20ek_common.dtsi"
-+
-+/ {
-+ model = "Atmel at91sam9g20ek";
-+ compatible = "atmel,at91sam9g20ek", "atmel,at91sam9g20", "atmel,at91sam9";
-+
-+ leds {
-+ compatible = "gpio-leds";
-+
-+ ds1 {
-+ label = "ds1";
-+ gpios = <&pioA 9 0>;
-+ linux,default-trigger = "heartbeat";
-+ };
-+
-+ ds5 {
-+ label = "ds5";
-+ gpios = <&pioA 6 1>;
-+ };
-+ };
-+};
-diff --git a/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts b/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts
-new file mode 100644
-index 0000000..f1b2e14
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts
-@@ -0,0 +1,29 @@
-+/*
-+ * at91sam9g20ek_2mmc.dts - Device Tree file for Atmel at91sam9g20ek 2 MMC board
-+ *
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2.
-+ */
-+/dts-v1/;
-+/include/ "at91sam9g20ek_common.dtsi"
-+
-+/ {
-+ model = "Atmel at91sam9g20ek 2 mmc";
-+ compatible = "atmel,at91sam9g20ek_2mmc", "atmel,at91sam9g20", "atmel,at91sam9";
-+
-+ leds {
-+ compatible = "gpio-leds";
-+
-+ ds1 {
-+ label = "ds1";
-+ gpios = <&pioB 9 0>;
-+ linux,default-trigger = "heartbeat";
-+ };
-+
-+ ds5 {
-+ label = "ds5";
-+ gpios = <&pioB 8 1>;
-+ };
-+ };
-+};
-diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
-new file mode 100644
-index 0000000..b06c0db
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
-@@ -0,0 +1,142 @@
-+/*
-+ * at91sam9g20ek_common.dtsi - Device Tree file for Atmel at91sam9g20ek board
-+ *
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2.
-+ */
-+/include/ "at91sam9g20.dtsi"
-+
-+/ {
-+
-+ chosen {
-+ bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
-+ };
-+
-+ memory {
-+ reg = <0x20000000 0x4000000>;
-+ };
-+
-+ clocks {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ main_clock: clock@0 {
-+ compatible = "atmel,osc", "fixed-clock";
-+ clock-frequency = <18432000>;
-+ };
-+ };
-+
-+ ahb {
-+ apb {
-+ dbgu: serial@fffff200 {
-+ status = "okay";
-+ };
-+
-+ usart0: serial@fffb0000 {
-+ status = "okay";
-+ };
-+
-+ usart1: serial@fffb4000 {
-+ status = "okay";
-+ };
-+
-+ macb0: ethernet@fffc4000 {
-+ phy-mode = "rmii";
-+ status = "okay";
-+ };
-+
-+ usb1: gadget@fffa4000 {
-+ atmel,vbus-gpio = <&pioC 5 0>;
-+ status = "okay";
-+ };
-+ };
-+
-+ nand0: nand@40000000 {
-+ nand-bus-width = <8>;
-+ nand-ecc-mode = "soft";
-+ nand-on-flash-bbt;
-+ status = "okay";
-+
-+ at91bootstrap@0 {
-+ label = "at91bootstrap";
-+ reg = <0x0 0x20000>;
-+ };
-+
-+ barebox@20000 {
-+ label = "barebox";
-+ reg = <0x20000 0x40000>;
-+ };
-+
-+ bareboxenv@60000 {
-+ label = "bareboxenv";
-+ reg = <0x60000 0x20000>;
-+ };
-+
-+ bareboxenv2@80000 {
-+ label = "bareboxenv2";
-+ reg = <0x80000 0x20000>;
-+ };
-+
-+ oftree@80000 {
-+ label = "oftree";
-+ reg = <0xa0000 0x20000>;
-+ };
-+
-+ kernel@a0000 {
-+ label = "kernel";
-+ reg = <0xc0000 0x400000>;
-+ };
-+
-+ rootfs@4a0000 {
-+ label = "rootfs";
-+ reg = <0x4c0000 0x7800000>;
-+ };
-+
-+ data@7ca0000 {
-+ label = "data";
-+ reg = <0x7cc0000 0x8340000>;
-+ };
-+ };
-+
-+ usb0: ohci@00500000 {
-+ num-ports = <2>;
-+ status = "okay";
-+ };
-+ };
-+
-+ i2c@0 {
-+ status = "okay";
-+
-+ 24c512@50 {
-+ compatible = "24c512";
-+ reg = <0x50>;
-+ };
-+
-+ wm8731@1b {
-+ compatible = "wm8731";
-+ reg = <0x1b>;
-+ };
-+ };
-+
-+ gpio_keys {
-+ compatible = "gpio-keys";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ btn3 {
-+ label = "Buttin 3";
-+ gpios = <&pioA 30 1>;
-+ linux,code = <0x103>;
-+ gpio-key,wakeup;
-+ };
-+
-+ btn4 {
-+ label = "Buttin 4";
-+ gpios = <&pioA 31 1>;
-+ linux,code = <0x104>;
-+ gpio-key,wakeup;
-+ };
-+ };
-+};
-diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
-index bdf9841..30d6c10 100644
---- a/arch/arm/mach-at91/Makefile.boot
-+++ b/arch/arm/mach-at91/Makefile.boot
-@@ -17,6 +17,8 @@ endif
- # sam9260
- dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9260.dtb
- # sam9g20
-+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g20ek.dtb
-+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g20ek_2mmc.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9g20.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9g20.dtb
- # sam9g45
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 820b7c95d6958edce4db6d204c9e3ccb8fb742a5 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Wed, 11 Apr 2012 23:40:31 +0800
-Subject: ARM: at91: USB A926x update nand partition
-
-commit d78504774435d5fc961f58a92ba7ec441d8b74c9 upstream.
-
-We now store the dtb in a nand partition.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/usb_a9g20.dts | 11 ++++++++---
- arch/arm/mach-at91/board-usb-a926x.c | 4 ++++
- 2 files changed, 12 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts
-index 7c2399c..0f88ec8 100644
---- a/arch/arm/boot/dts/usb_a9g20.dts
-+++ b/arch/arm/boot/dts/usb_a9g20.dts
-@@ -74,19 +74,24 @@
- reg = <0x80000 0x20000>;
- };
-
-+ oftree@80000 {
-+ label = "oftree";
-+ reg = <0xa0000 0x20000>;
-+ };
-+
- kernel@a0000 {
- label = "kernel";
-- reg = <0xa0000 0x400000>;
-+ reg = <0xc0000 0x400000>;
- };
-
- rootfs@4a0000 {
- label = "rootfs";
-- reg = <0x4a0000 0x7800000>;
-+ reg = <0x4c0000 0x7800000>;
- };
-
- data@7ca0000 {
- label = "data";
-- reg = <0x7ca0000 0x8360000>;
-+ reg = <0x7cc0000 0x8340000>;
- };
- };
-
-diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c
-index 332ecd4..95393fc 100644
---- a/arch/arm/mach-at91/board-usb-a926x.c
-+++ b/arch/arm/mach-at91/board-usb-a926x.c
-@@ -172,6 +172,10 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
- .offset = MTDPART_OFS_NXTBLK,
- .size = SZ_128K,
- }, {
-+ .name = "oftree",
-+ .offset = MTDPART_OFS_NXTBLK,
-+ .size = SZ_128K,
-+ }, {
- .name = "kernel",
- .offset = MTDPART_OFS_NXTBLK,
- .size = 4 * SZ_1M,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 7c87b9d5d1ab4d9487de665e92ab94de3bdf050f Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Wed, 11 Apr 2012 23:42:44 +0800
-Subject: ARM: at91: Calao USB A926x factorize common binding in
- usb_a9260_common
-
-commit cff4175ecdc2447847526b6352ca6f7d1139d5b5 upstream.
-
-This will simplify the adding of the A9260.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/usb_a9260_common.dtsi | 117 ++++++++++++++++++++++++++++++++
- arch/arm/boot/dts/usb_a9g20.dts | 107 +----------------------------
- 2 files changed, 118 insertions(+), 106 deletions(-)
- create mode 100644 arch/arm/boot/dts/usb_a9260_common.dtsi
-
-diff --git a/arch/arm/boot/dts/usb_a9260_common.dtsi b/arch/arm/boot/dts/usb_a9260_common.dtsi
-new file mode 100644
-index 0000000..e70d229
---- /dev/null
-+++ b/arch/arm/boot/dts/usb_a9260_common.dtsi
-@@ -0,0 +1,117 @@
-+/*
-+ * usb_a926x.dts - Device Tree file for Caloa USB A926x board
-+ *
-+ * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2 or later.
-+ */
-+
-+/ {
-+ clocks {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ main_clock: clock@0 {
-+ compatible = "atmel,osc", "fixed-clock";
-+ clock-frequency = <12000000>;
-+ };
-+ };
-+
-+ ahb {
-+ apb {
-+ dbgu: serial@fffff200 {
-+ status = "okay";
-+ };
-+
-+ macb0: ethernet@fffc4000 {
-+ phy-mode = "rmii";
-+ status = "okay";
-+ };
-+
-+ usb1: gadget@fffa4000 {
-+ atmel,vbus-gpio = <&pioC 5 0>;
-+ status = "okay";
-+ };
-+ };
-+
-+ nand0: nand@40000000 {
-+ nand-bus-width = <8>;
-+ nand-ecc-mode = "soft";
-+ nand-on-flash-bbt;
-+ status = "okay";
-+
-+ at91bootstrap@0 {
-+ label = "at91bootstrap";
-+ reg = <0x0 0x20000>;
-+ };
-+
-+ barebox@20000 {
-+ label = "barebox";
-+ reg = <0x20000 0x40000>;
-+ };
-+
-+ bareboxenv@60000 {
-+ label = "bareboxenv";
-+ reg = <0x60000 0x20000>;
-+ };
-+
-+ bareboxenv2@80000 {
-+ label = "bareboxenv2";
-+ reg = <0x80000 0x20000>;
-+ };
-+
-+ oftree@80000 {
-+ label = "oftree";
-+ reg = <0xa0000 0x20000>;
-+ };
-+
-+ kernel@a0000 {
-+ label = "kernel";
-+ reg = <0xc0000 0x400000>;
-+ };
-+
-+ rootfs@4a0000 {
-+ label = "rootfs";
-+ reg = <0x4c0000 0x7800000>;
-+ };
-+
-+ data@7ca0000 {
-+ label = "data";
-+ reg = <0x7cc0000 0x8340000>;
-+ };
-+ };
-+
-+ usb0: ohci@00500000 {
-+ num-ports = <2>;
-+ status = "okay";
-+ };
-+ };
-+
-+ leds {
-+ compatible = "gpio-leds";
-+
-+ user_led {
-+ label = "user_led";
-+ gpios = <&pioB 21 1>;
-+ linux,default-trigger = "heartbeat";
-+ };
-+ };
-+
-+ gpio_keys {
-+ compatible = "gpio-keys";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ user_pb {
-+ label = "user_pb";
-+ gpios = <&pioB 10 1>;
-+ linux,code = <28>;
-+ gpio-key,wakeup;
-+ };
-+ };
-+
-+ i2c@0 {
-+ status = "okay";
-+ };
-+};
-diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts
-index 0f88ec8..2dacb16c 100644
---- a/arch/arm/boot/dts/usb_a9g20.dts
-+++ b/arch/arm/boot/dts/usb_a9g20.dts
-@@ -7,6 +7,7 @@
- */
- /dts-v1/;
- /include/ "at91sam9g20.dtsi"
-+/include/ "usb_a9260_common.dtsi"
-
- / {
- model = "Calao USB A9G20";
-@@ -20,113 +21,7 @@
- reg = <0x20000000 0x4000000>;
- };
-
-- clocks {
-- #address-cells = <1>;
-- #size-cells = <1>;
-- ranges;
--
-- main_clock: clock@0 {
-- compatible = "atmel,osc", "fixed-clock";
-- clock-frequency = <12000000>;
-- };
-- };
--
-- ahb {
-- apb {
-- dbgu: serial@fffff200 {
-- status = "okay";
-- };
--
-- macb0: ethernet@fffc4000 {
-- phy-mode = "rmii";
-- status = "okay";
-- };
--
-- usb1: gadget@fffa4000 {
-- atmel,vbus-gpio = <&pioC 5 0>;
-- status = "okay";
-- };
-- };
--
-- nand0: nand@40000000 {
-- nand-bus-width = <8>;
-- nand-ecc-mode = "soft";
-- nand-on-flash-bbt;
-- status = "okay";
--
-- at91bootstrap@0 {
-- label = "at91bootstrap";
-- reg = <0x0 0x20000>;
-- };
--
-- barebox@20000 {
-- label = "barebox";
-- reg = <0x20000 0x40000>;
-- };
--
-- bareboxenv@60000 {
-- label = "bareboxenv";
-- reg = <0x60000 0x20000>;
-- };
--
-- bareboxenv2@80000 {
-- label = "bareboxenv2";
-- reg = <0x80000 0x20000>;
-- };
--
-- oftree@80000 {
-- label = "oftree";
-- reg = <0xa0000 0x20000>;
-- };
--
-- kernel@a0000 {
-- label = "kernel";
-- reg = <0xc0000 0x400000>;
-- };
--
-- rootfs@4a0000 {
-- label = "rootfs";
-- reg = <0x4c0000 0x7800000>;
-- };
--
-- data@7ca0000 {
-- label = "data";
-- reg = <0x7cc0000 0x8340000>;
-- };
-- };
--
-- usb0: ohci@00500000 {
-- num-ports = <2>;
-- status = "okay";
-- };
-- };
--
-- leds {
-- compatible = "gpio-leds";
--
-- user_led {
-- label = "user_led";
-- gpios = <&pioB 21 1>;
-- linux,default-trigger = "heartbeat";
-- };
-- };
--
-- gpio_keys {
-- compatible = "gpio-keys";
-- #address-cells = <1>;
-- #size-cells = <0>;
--
-- user_pb {
-- label = "user_pb";
-- gpios = <&pioB 10 1>;
-- linux,code = <28>;
-- gpio-key,wakeup;
-- };
-- };
--
- i2c@0 {
-- status = "okay";
--
- rv3029c2@56 {
- compatible = "rv3029c2";
- reg = <0x56>;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 4c5e3f92533de94648bd618ec5825c9952f1ab57 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Mon, 9 Apr 2012 14:43:34 +0800
-Subject: ARM: at91: DT: add Calao USB A9260 DT support
-
-commit 4e114c9576b53461b14ac30f5e6159e73aa6abd3 upstream.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/usb_a9260.dts | 23 +++++++++++++++++++++++
- arch/arm/mach-at91/Makefile.boot | 1 +
- 2 files changed, 24 insertions(+)
- create mode 100644 arch/arm/boot/dts/usb_a9260.dts
-
-diff --git a/arch/arm/boot/dts/usb_a9260.dts b/arch/arm/boot/dts/usb_a9260.dts
-new file mode 100644
-index 0000000..2962160
---- /dev/null
-+++ b/arch/arm/boot/dts/usb_a9260.dts
-@@ -0,0 +1,23 @@
-+/*
-+ * usb_a9260.dts - Device Tree file for Caloa USB A9260 board
-+ *
-+ * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2 or later.
-+ */
-+/dts-v1/;
-+/include/ "at91sam9260.dtsi"
-+/include/ "usb_a9260_common.dtsi"
-+
-+/ {
-+ model = "Calao USB A9260";
-+ compatible = "calao,usb-a9260", "atmel,at91sam9260", "atmel,at91sam9";
-+
-+ chosen {
-+ bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
-+ };
-+
-+ memory {
-+ reg = <0x20000000 0x4000000>;
-+ };
-+};
-diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
-index 30d6c10..b2ac536 100644
---- a/arch/arm/mach-at91/Makefile.boot
-+++ b/arch/arm/mach-at91/Makefile.boot
-@@ -16,6 +16,7 @@ endif
- # Keep dtb files sorted alphabetically for each SoC
- # sam9260
- dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9260.dtb
-+dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9260.dtb
- # sam9g20
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g20ek.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g20ek_2mmc.dtb
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e693aa3e62f8ab17d523978b44543d489c4525e6 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Tue, 28 Feb 2012 15:23:43 +0800
-Subject: ARM: at91: standard device init only if DT is not populated.
-
-commit 8cf93b9ceaf4534cdeda5727782001f8fecb1688 upstream.
-
-This will avoid the CONFIG_OF on the *_devices.c as this file is deprecated
-for DT support.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/at91sam9260_devices.c | 20 +++-----------------
- arch/arm/mach-at91/at91sam9g45_devices.c | 30 ++++--------------------------
- 2 files changed, 7 insertions(+), 43 deletions(-)
-
-diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
-index ad00fe9..d556de1 100644
---- a/arch/arm/mach-at91/at91sam9260_devices.c
-+++ b/arch/arm/mach-at91/at91sam9260_devices.c
-@@ -702,25 +702,8 @@ static struct platform_device at91sam9260_tcb1_device = {
- .num_resources = ARRAY_SIZE(tcb1_resources),
- };
-
--#if defined(CONFIG_OF)
--static struct of_device_id tcb_ids[] = {
-- { .compatible = "atmel,at91rm9200-tcb" },
-- { /*sentinel*/ }
--};
--#endif
--
- static void __init at91_add_device_tc(void)
- {
--#if defined(CONFIG_OF)
-- struct device_node *np;
--
-- np = of_find_matching_node(NULL, tcb_ids);
-- if (np) {
-- of_node_put(np);
-- return;
-- }
--#endif
--
- platform_device_register(&at91sam9260_tcb0_device);
- platform_device_register(&at91sam9260_tcb1_device);
- }
-@@ -1364,6 +1347,9 @@ void __init at91_add_device_cf(struct at91_cf_data * data) {}
- */
- static int __init at91_add_standard_devices(void)
- {
-+ if (of_have_populated_dt())
-+ return 0;
-+
- at91_add_device_rtt();
- at91_add_device_watchdog();
- at91_add_device_tc();
-diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
-index db2f88c2..35bd42d 100644
---- a/arch/arm/mach-at91/at91sam9g45_devices.c
-+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
-@@ -69,15 +69,7 @@ static struct platform_device at_hdmac_device = {
-
- void __init at91_add_device_hdmac(void)
- {
--#if defined(CONFIG_OF)
-- struct device_node *of_node =
-- of_find_node_by_name(NULL, "dma-controller");
--
-- if (of_node)
-- of_node_put(of_node);
-- else
--#endif
-- platform_device_register(&at_hdmac_device);
-+ platform_device_register(&at_hdmac_device);
- }
- #else
- void __init at91_add_device_hdmac(void) {}
-@@ -1094,25 +1086,8 @@ static struct platform_device at91sam9g45_tcb1_device = {
- .num_resources = ARRAY_SIZE(tcb1_resources),
- };
-
--#if defined(CONFIG_OF)
--static struct of_device_id tcb_ids[] = {
-- { .compatible = "atmel,at91rm9200-tcb" },
-- { /*sentinel*/ }
--};
--#endif
--
- static void __init at91_add_device_tc(void)
- {
--#if defined(CONFIG_OF)
-- struct device_node *np;
--
-- np = of_find_matching_node(NULL, tcb_ids);
-- if (np) {
-- of_node_put(np);
-- return;
-- }
--#endif
--
- platform_device_register(&at91sam9g45_tcb0_device);
- platform_device_register(&at91sam9g45_tcb1_device);
- }
-@@ -1763,6 +1738,9 @@ void __init at91_add_device_serial(void) {}
- */
- static int __init at91_add_standard_devices(void)
- {
-+ if (of_have_populated_dt())
-+ return 0;
-+
- at91_add_device_hdmac();
- at91_add_device_rtc();
- at91_add_device_rtt();
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 04f070b90ea4e6121ecf05da4f2d86e28a7e3d72 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Sun, 26 Feb 2012 19:12:43 +0800
-Subject: ARM: at91: add at91sam9263 DT support
-
-commit 4abb367722c2dc06972658c8fad5b4763114477c upstream.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/at91sam9263.dtsi | 220 +++++++++++++++++++++++++++++++
- arch/arm/mach-at91/at91sam9263.c | 10 ++
- arch/arm/mach-at91/at91sam9263_devices.c | 20 +++
- 3 files changed, 250 insertions(+)
- create mode 100644 arch/arm/boot/dts/at91sam9263.dtsi
-
-diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
-new file mode 100644
-index 0000000..0209913
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9263.dtsi
-@@ -0,0 +1,220 @@
-+/*
-+ * at91sam9263.dtsi - Device Tree Include file for AT91SAM9263 family SoC
-+ *
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2 only.
-+ */
-+
-+/include/ "skeleton.dtsi"
-+
-+/ {
-+ model = "Atmel AT91SAM9263 family SoC";
-+ compatible = "atmel,at91sam9263";
-+ interrupt-parent = <&aic>;
-+
-+ aliases {
-+ serial0 = &dbgu;
-+ serial1 = &usart0;
-+ serial2 = &usart1;
-+ serial3 = &usart2;
-+ gpio0 = &pioA;
-+ gpio1 = &pioB;
-+ gpio2 = &pioC;
-+ gpio3 = &pioD;
-+ gpio4 = &pioE;
-+ tcb0 = &tcb0;
-+ };
-+ cpus {
-+ cpu@0 {
-+ compatible = "arm,arm926ejs";
-+ };
-+ };
-+
-+ memory {
-+ reg = <0x20000000 0x08000000>;
-+ };
-+
-+ ahb {
-+ compatible = "simple-bus";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ apb {
-+ compatible = "simple-bus";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ aic: interrupt-controller@fffff000 {
-+ #interrupt-cells = <2>;
-+ compatible = "atmel,at91rm9200-aic";
-+ interrupt-controller;
-+ reg = <0xfffff000 0x200>;
-+ };
-+
-+ pmc: pmc@fffffc00 {
-+ compatible = "atmel,at91rm9200-pmc";
-+ reg = <0xfffffc00 0x100>;
-+ };
-+
-+ ramc: ramc@ffffe200 {
-+ compatible = "atmel,at91sam9260-sdramc";
-+ reg = <0xffffe200 0x200
-+ 0xffffe800 0x200>;
-+ };
-+
-+ pit: timer@fffffd30 {
-+ compatible = "atmel,at91sam9260-pit";
-+ reg = <0xfffffd30 0xf>;
-+ interrupts = <1 4>;
-+ };
-+
-+ tcb0: timer@fff7c000 {
-+ compatible = "atmel,at91rm9200-tcb";
-+ reg = <0xfff7c000 0x100>;
-+ interrupts = <19 4>;
-+ };
-+
-+ rstc@fffffd00 {
-+ compatible = "atmel,at91sam9260-rstc";
-+ reg = <0xfffffd00 0x10>;
-+ };
-+
-+ shdwc@fffffd10 {
-+ compatible = "atmel,at91sam9260-shdwc";
-+ reg = <0xfffffd10 0x10>;
-+ };
-+
-+ pioA: gpio@fffff200 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff200 0x100>;
-+ interrupts = <2 4>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ };
-+
-+ pioB: gpio@fffff400 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff400 0x100>;
-+ interrupts = <3 4>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ };
-+
-+ pioC: gpio@fffff600 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff600 0x100>;
-+ interrupts = <4 4>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ };
-+
-+ pioD: gpio@fffff800 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff800 0x100>;
-+ interrupts = <4 4>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ };
-+
-+ pioE: gpio@fffffa00 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffffa00 0x100>;
-+ interrupts = <4 4>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ };
-+
-+ dbgu: serial@ffffee00 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xffffee00 0x200>;
-+ interrupts = <1 4>;
-+ status = "disabled";
-+ };
-+
-+ usart0: serial@fff8c000 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xfff8c000 0x200>;
-+ interrupts = <7 4>;
-+ atmel,use-dma-rx;
-+ atmel,use-dma-tx;
-+ status = "disabled";
-+ };
-+
-+ usart1: serial@fff90000 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xfff90000 0x200>;
-+ interrupts = <8 4>;
-+ atmel,use-dma-rx;
-+ atmel,use-dma-tx;
-+ status = "disabled";
-+ };
-+
-+ usart2: serial@fff94000 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xfff94000 0x200>;
-+ interrupts = <9 4>;
-+ atmel,use-dma-rx;
-+ atmel,use-dma-tx;
-+ status = "disabled";
-+ };
-+
-+ macb0: ethernet@fffbc000 {
-+ compatible = "cdns,at32ap7000-macb", "cdns,macb";
-+ reg = <0xfffbc000 0x100>;
-+ interrupts = <21 4>;
-+ status = "disabled";
-+ };
-+
-+ usb1: gadget@fff78000 {
-+ compatible = "atmel,at91rm9200-udc";
-+ reg = <0xfff78000 0x4000>;
-+ interrupts = <24 4>;
-+ status = "disabled";
-+ };
-+ };
-+
-+ nand0: nand@40000000 {
-+ compatible = "atmel,at91rm9200-nand";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ reg = <0x40000000 0x10000000
-+ 0xffffe000 0x200
-+ >;
-+ atmel,nand-addr-offset = <21>;
-+ atmel,nand-cmd-offset = <22>;
-+ gpios = <&pioA 22 0
-+ &pioD 15 0
-+ 0
-+ >;
-+ status = "disabled";
-+ };
-+
-+ usb0: ohci@00a00000 {
-+ compatible = "atmel,at91rm9200-ohci", "usb-ohci";
-+ reg = <0x00a00000 0x100000>;
-+ interrupts = <29 4>;
-+ status = "disabled";
-+ };
-+ };
-+
-+ i2c@0 {
-+ compatible = "i2c-gpio";
-+ gpios = <&pioB 4 0 /* sda */
-+ &pioB 5 0 /* scl */
-+ >;
-+ i2c-gpio,sda-open-drain;
-+ i2c-gpio,scl-open-drain;
-+ i2c-gpio,delay-us = <2>; /* ~100 kHz */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+};
-diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
-index 7fae365..ed91c7e 100644
---- a/arch/arm/mach-at91/at91sam9263.c
-+++ b/arch/arm/mach-at91/at91sam9263.c
-@@ -199,6 +199,16 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_ID("pioC", &pioCDE_clk),
- CLKDEV_CON_ID("pioD", &pioCDE_clk),
- CLKDEV_CON_ID("pioE", &pioCDE_clk),
-+ /* more usart lookup table for DT entries */
-+ CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck),
-+ CLKDEV_CON_DEV_ID("usart", "fff8c000.serial", &usart0_clk),
-+ CLKDEV_CON_DEV_ID("usart", "fff90000.serial", &usart1_clk),
-+ CLKDEV_CON_DEV_ID("usart", "fff94000.serial", &usart2_clk),
-+ /* more tc lookup table for DT entries */
-+ CLKDEV_CON_DEV_ID("t0_clk", "fff7c000.timer", &tcb_clk),
-+ CLKDEV_CON_DEV_ID("hclk", "a00000.ohci", &ohci_clk),
-+ CLKDEV_CON_DEV_ID("spi_clk", "fffa4000.spi", &spi0_clk),
-+ CLKDEV_CON_DEV_ID("spi_clk", "fffa8000.spi", &spi1_clk),
- };
-
- static struct clk_lookup usart_clocks_lookups[] = {
-diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
-index dfe5bc0..175e000 100644
---- a/arch/arm/mach-at91/at91sam9263_devices.c
-+++ b/arch/arm/mach-at91/at91sam9263_devices.c
-@@ -953,8 +953,25 @@ static struct platform_device at91sam9263_tcb_device = {
- .num_resources = ARRAY_SIZE(tcb_resources),
- };
-
-+#if defined(CONFIG_OF)
-+static struct of_device_id tcb_ids[] = {
-+ { .compatible = "atmel,at91rm9200-tcb" },
-+ { /*sentinel*/ }
-+};
-+#endif
-+
- static void __init at91_add_device_tc(void)
- {
-+#if defined(CONFIG_OF)
-+ struct device_node *np;
-+
-+ np = of_find_matching_node(NULL, tcb_ids);
-+ if (np) {
-+ of_node_put(np);
-+ return;
-+ }
-+#endif
-+
- platform_device_register(&at91sam9263_tcb_device);
- }
- #else
-@@ -1483,6 +1500,9 @@ void __init at91_add_device_serial(void) {}
- */
- static int __init at91_add_standard_devices(void)
- {
-+ if (of_have_populated_dt())
-+ return 0;
-+
- at91_add_device_rtt();
- at91_add_device_watchdog();
- at91_add_device_tc();
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 8dc26edb6641e03867239b76f0a6ab0042308db4 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Sun, 26 Feb 2012 19:12:43 +0800
-Subject: ARM: at91: add at91sam9263ek DT support
-
-commit 39f31cd40ae0c2301c00e6f1cf17bf20863c498c upstream.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/at91sam9263ek.dts | 156 ++++++++++++++++++++++++++++++++++++
- arch/arm/mach-at91/Makefile.boot | 2 +
- 2 files changed, 158 insertions(+)
- create mode 100644 arch/arm/boot/dts/at91sam9263ek.dts
-
-diff --git a/arch/arm/boot/dts/at91sam9263ek.dts b/arch/arm/boot/dts/at91sam9263ek.dts
-new file mode 100644
-index 0000000..f86ac4b
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9263ek.dts
-@@ -0,0 +1,156 @@
-+/*
-+ * at91sam9263ek.dts - Device Tree file for Atmel at91sam9263 reference board
-+ *
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2 only
-+ */
-+/dts-v1/;
-+/include/ "at91sam9263.dtsi"
-+
-+/ {
-+ model = "Atmel at91sam9263ek";
-+ compatible = "atmel,at91sam9263ek", "atmel,at91sam9263", "atmel,at91sam9";
-+
-+ chosen {
-+ bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
-+ };
-+
-+ memory {
-+ reg = <0x20000000 0x4000000>;
-+ };
-+
-+ clocks {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ main_clock: clock@0 {
-+ compatible = "atmel,osc", "fixed-clock";
-+ clock-frequency = <16367660>;
-+ };
-+ };
-+
-+ ahb {
-+ apb {
-+ dbgu: serial@ffffee00 {
-+ status = "okay";
-+ };
-+
-+ usart0: serial@fff8c000 {
-+ status = "okay";
-+ };
-+
-+ macb0: ethernet@fffbc000 {
-+ phy-mode = "rmii";
-+ status = "okay";
-+ };
-+
-+ usb1: gadget@fff78000 {
-+ atmel,vbus-gpio = <&pioA 25 0>;
-+ status = "okay";
-+ };
-+ };
-+
-+ nand0: nand@40000000 {
-+ nand-bus-width = <8>;
-+ nand-ecc-mode = "soft";
-+ nand-on-flash-bbt = <1>;
-+ status = "okay";
-+
-+ at91bootstrap@0 {
-+ label = "at91bootstrap";
-+ reg = <0x0 0x20000>;
-+ };
-+
-+ barebox@20000 {
-+ label = "barebox";
-+ reg = <0x20000 0x40000>;
-+ };
-+
-+ bareboxenv@60000 {
-+ label = "bareboxenv";
-+ reg = <0x60000 0x20000>;
-+ };
-+
-+ bareboxenv2@80000 {
-+ label = "bareboxenv2";
-+ reg = <0x80000 0x20000>;
-+ };
-+
-+ oftree@80000 {
-+ label = "oftree";
-+ reg = <0xa0000 0x20000>;
-+ };
-+
-+ kernel@a0000 {
-+ label = "kernel";
-+ reg = <0xc0000 0x400000>;
-+ };
-+
-+ rootfs@4a0000 {
-+ label = "rootfs";
-+ reg = <0x4c0000 0x7800000>;
-+ };
-+
-+ data@7ca0000 {
-+ label = "data";
-+ reg = <0x7cc0000 0x8340000>;
-+ };
-+ };
-+
-+ usb0: ohci@00a00000 {
-+ num-ports = <2>;
-+ status = "okay";
-+ atmel,vbus-gpio = <&pioA 24 0
-+ &pioA 21 0
-+ >;
-+ };
-+ };
-+
-+ leds {
-+ compatible = "gpio-leds";
-+
-+ d3 {
-+ label = "d3";
-+ gpios = <&pioB 7 0>;
-+ linux,default-trigger = "heartbeat";
-+ };
-+
-+ d2 {
-+ label = "d2";
-+ gpios = <&pioC 29 1>;
-+ linux,default-trigger = "nand-disk";
-+ };
-+ };
-+
-+ gpio_keys {
-+ compatible = "gpio-keys";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ left_click {
-+ label = "left_click";
-+ gpios = <&pioC 5 1>;
-+ linux,code = <272>;
-+ gpio-key,wakeup;
-+ };
-+
-+ right_click {
-+ label = "right_click";
-+ gpios = <&pioC 4 1>;
-+ linux,code = <273>;
-+ gpio-key,wakeup;
-+ };
-+ };
-+
-+ i2c@0 {
-+ status = "okay";
-+
-+ 24c512@50 {
-+ compatible = "24c512";
-+ reg = <0x50>;
-+ pagesize = <128>;
-+ };
-+ };
-+};
-diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
-index b2ac536..0c6e0e9 100644
---- a/arch/arm/mach-at91/Makefile.boot
-+++ b/arch/arm/mach-at91/Makefile.boot
-@@ -17,6 +17,8 @@ endif
- # sam9260
- dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9260.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9260.dtb
-+# sam9263
-+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9263ek.dtb
- # sam9g20
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g20ek.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g20ek_2mmc.dtb
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ae8f5dd8fc1213e42edc565e31cd14f4aee1ff8d Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Thu, 12 Apr 2012 18:01:33 +0800
-Subject: ARM: at91: DT: add Calao USB A9263 board support
-
-commit 1fb4f71977c5ffe5875412949b0b7ab2bed3a283 upstream.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/usb_a9263.dts | 131 +++++++++++++++++++++++++++++++++++++++
- arch/arm/mach-at91/Makefile.boot | 1 +
- 2 files changed, 132 insertions(+)
- create mode 100644 arch/arm/boot/dts/usb_a9263.dts
-
-diff --git a/arch/arm/boot/dts/usb_a9263.dts b/arch/arm/boot/dts/usb_a9263.dts
-new file mode 100644
-index 0000000..6fe05cc
---- /dev/null
-+++ b/arch/arm/boot/dts/usb_a9263.dts
-@@ -0,0 +1,131 @@
-+/*
-+ * usb_a9263.dts - Device Tree file for Caloa USB A9293 board
-+ *
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2 only
-+ */
-+/dts-v1/;
-+/include/ "at91sam9263.dtsi"
-+
-+/ {
-+ model = "Calao USB A9263";
-+ compatible = "atmel,usb-a9263", "atmel,at91sam9263", "atmel,at91sam9";
-+
-+ chosen {
-+ bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
-+ };
-+
-+ memory {
-+ reg = <0x20000000 0x4000000>;
-+ };
-+
-+ clocks {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ main_clock: clock@0 {
-+ compatible = "atmel,osc", "fixed-clock";
-+ clock-frequency = <12000000>;
-+ };
-+ };
-+
-+ ahb {
-+ apb {
-+ dbgu: serial@ffffee00 {
-+ status = "okay";
-+ };
-+
-+ macb0: ethernet@fffbc000 {
-+ phy-mode = "rmii";
-+ status = "okay";
-+ };
-+
-+ usb1: gadget@fff78000 {
-+ atmel,vbus-gpio = <&pioB 11 0>;
-+ status = "okay";
-+ };
-+
-+ };
-+
-+ nand0: nand@40000000 {
-+ nand-bus-width = <8>;
-+ nand-ecc-mode = "soft";
-+ nand-on-flash-bbt;
-+ status = "okay";
-+
-+ at91bootstrap@0 {
-+ label = "at91bootstrap";
-+ reg = <0x0 0x20000>;
-+ };
-+
-+ barebox@20000 {
-+ label = "barebox";
-+ reg = <0x20000 0x40000>;
-+ };
-+
-+ bareboxenv@60000 {
-+ label = "bareboxenv";
-+ reg = <0x60000 0x20000>;
-+ };
-+
-+ bareboxenv2@80000 {
-+ label = "bareboxenv2";
-+ reg = <0x80000 0x20000>;
-+ };
-+
-+ oftree@80000 {
-+ label = "oftree";
-+ reg = <0xa0000 0x20000>;
-+ };
-+
-+ kernel@a0000 {
-+ label = "kernel";
-+ reg = <0xc0000 0x400000>;
-+ };
-+
-+ rootfs@4a0000 {
-+ label = "rootfs";
-+ reg = <0x4c0000 0x7800000>;
-+ };
-+
-+ data@7ca0000 {
-+ label = "data";
-+ reg = <0x7cc0000 0x8340000>;
-+ };
-+ };
-+
-+ usb0: ohci@00a00000 {
-+ num-ports = <2>;
-+ status = "okay";
-+ };
-+ };
-+
-+ leds {
-+ compatible = "gpio-leds";
-+
-+ user_led {
-+ label = "user_led";
-+ gpios = <&pioB 21 0>;
-+ linux,default-trigger = "heartbeat";
-+ };
-+ };
-+
-+ gpio_keys {
-+ compatible = "gpio-keys";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ user_pb {
-+ label = "user_pb";
-+ gpios = <&pioB 10 1>;
-+ linux,code = <28>;
-+ gpio-key,wakeup;
-+ };
-+ };
-+
-+ i2c@0 {
-+ status = "okay";
-+ };
-+};
-diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
-index 0c6e0e9..7f0a5cb 100644
---- a/arch/arm/mach-at91/Makefile.boot
-+++ b/arch/arm/mach-at91/Makefile.boot
-@@ -19,6 +19,7 @@ dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9260.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9260.dtb
- # sam9263
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9263ek.dtb
-+dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9263.dtb
- # sam9g20
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g20ek.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g20ek_2mmc.dtb
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 7c00f8580d1555427d9619881d0ad59f57665fbc Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Thu, 12 Apr 2012 18:47:32 +0800
-Subject: ARM: at91: DT: add Calao TNY A9263 board support
-
-commit 15787753d08107f2066b8ed8c9f8046ef3b766bb upstream.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/tny_a9263.dts | 97 ++++++++++++++++++++++++++++++++++++++++
- arch/arm/mach-at91/Makefile.boot | 1 +
- 2 files changed, 98 insertions(+)
- create mode 100644 arch/arm/boot/dts/tny_a9263.dts
-
-diff --git a/arch/arm/boot/dts/tny_a9263.dts b/arch/arm/boot/dts/tny_a9263.dts
-new file mode 100644
-index 0000000..dee9c57
---- /dev/null
-+++ b/arch/arm/boot/dts/tny_a9263.dts
-@@ -0,0 +1,97 @@
-+/*
-+ * usb_a9263.dts - Device Tree file for Caloa USB A9293 board
-+ *
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2 only
-+ */
-+/dts-v1/;
-+/include/ "at91sam9263.dtsi"
-+
-+/ {
-+ model = "Calao TNY A9263";
-+ compatible = "atmel,tny-a9263", "atmel,at91sam9263", "atmel,at91sam9";
-+
-+ chosen {
-+ bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
-+ };
-+
-+ memory {
-+ reg = <0x20000000 0x4000000>;
-+ };
-+
-+ clocks {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ main_clock: clock@0 {
-+ compatible = "atmel,osc", "fixed-clock";
-+ clock-frequency = <12000000>;
-+ };
-+ };
-+
-+ ahb {
-+ apb {
-+ dbgu: serial@ffffee00 {
-+ status = "okay";
-+ };
-+
-+ usb1: gadget@fff78000 {
-+ atmel,vbus-gpio = <&pioB 11 0>;
-+ status = "okay";
-+ };
-+ };
-+
-+ nand0: nand@40000000 {
-+ nand-bus-width = <8>;
-+ nand-ecc-mode = "soft";
-+ nand-on-flash-bbt;
-+ status = "okay";
-+
-+ at91bootstrap@0 {
-+ label = "at91bootstrap";
-+ reg = <0x0 0x20000>;
-+ };
-+
-+ barebox@20000 {
-+ label = "barebox";
-+ reg = <0x20000 0x40000>;
-+ };
-+
-+ bareboxenv@60000 {
-+ label = "bareboxenv";
-+ reg = <0x60000 0x20000>;
-+ };
-+
-+ bareboxenv2@80000 {
-+ label = "bareboxenv2";
-+ reg = <0x80000 0x20000>;
-+ };
-+
-+ oftree@80000 {
-+ label = "oftree";
-+ reg = <0xa0000 0x20000>;
-+ };
-+
-+ kernel@a0000 {
-+ label = "kernel";
-+ reg = <0xc0000 0x400000>;
-+ };
-+
-+ rootfs@4a0000 {
-+ label = "rootfs";
-+ reg = <0x4c0000 0x7800000>;
-+ };
-+
-+ data@7ca0000 {
-+ label = "data";
-+ reg = <0x7cc0000 0x8340000>;
-+ };
-+ };
-+ };
-+
-+ i2c@0 {
-+ status = "okay";
-+ };
-+};
-diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
-index 7f0a5cb..618fc5b 100644
---- a/arch/arm/mach-at91/Makefile.boot
-+++ b/arch/arm/mach-at91/Makefile.boot
-@@ -19,6 +19,7 @@ dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9260.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9260.dtb
- # sam9263
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9263ek.dtb
-+dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9263.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9263.dtb
- # sam9g20
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g20ek.dtb
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 32a078f6d401977db0ed9eca60974a7f52db183f Mon Sep 17 00:00:00 2001
-From: Boris BREZILLON <linux-arm@overkiz.com>
-Date: Fri, 20 Apr 2012 14:37:50 +0200
-Subject: ARM: at91: add kizbox board dt support.
-
-commit df8267487c7f8d707faca430f4d759dbc2dad6f5 upstream.
-
-This patch adds support for the kizbox board (based on at91sam9g20 SoC)
-
-Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/boot/dts/kizbox.dts | 138 +++++++++++++++++++++++++++++++++++++++
- arch/arm/mach-at91/Makefile.boot | 1 +
- 2 files changed, 139 insertions(+)
- create mode 100644 arch/arm/boot/dts/kizbox.dts
-
-diff --git a/arch/arm/boot/dts/kizbox.dts b/arch/arm/boot/dts/kizbox.dts
-new file mode 100644
-index 0000000..e8814fe
---- /dev/null
-+++ b/arch/arm/boot/dts/kizbox.dts
-@@ -0,0 +1,138 @@
-+/*
-+ * kizbox.dts - Device Tree file for Overkiz Kizbox board
-+ *
-+ * Copyright (C) 2012 Boris BREZILLON <linux-arm@overkiz.com>
-+ *
-+ * Licensed under GPLv2.
-+ */
-+/dts-v1/;
-+/include/ "at91sam9g20.dtsi"
-+
-+/ {
-+
-+ model = "Overkiz kizbox";
-+ compatible = "overkiz,kizbox", "atmel,at91sam9g20", "atmel,at91sam9";
-+
-+ chosen {
-+ bootargs = "panic=5 ubi.mtd=1 rootfstype=ubifs root=ubi0:root";
-+ };
-+
-+ memory {
-+ reg = <0x20000000 0x2000000>;
-+ };
-+
-+ clocks {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ main_clock: clock@0 {
-+ compatible = "atmel,osc", "fixed-clock";
-+ clock-frequency = <18432000>;
-+ };
-+ };
-+
-+ ahb {
-+ apb {
-+ dbgu: serial@fffff200 {
-+ status = "okay";
-+ };
-+
-+ usart0: serial@fffb0000 {
-+ status = "okay";
-+ };
-+
-+ usart1: serial@fffb4000 {
-+ status = "okay";
-+ };
-+
-+ macb0: ethernet@fffc4000 {
-+ phy-mode = "mii";
-+ status = "okay";
-+ };
-+
-+ };
-+
-+ nand0: nand@40000000 {
-+ nand-bus-width = <8>;
-+ nand-ecc-mode = "soft";
-+ status = "okay";
-+
-+ bootloaderkernel@0 {
-+ label = "bootloader-kernel";
-+ reg = <0x0 0xc0000>;
-+ };
-+
-+ ubi@c0000 {
-+ label = "ubi";
-+ reg = <0xc0000 0x7f40000>;
-+ };
-+
-+ };
-+
-+ usb0: ohci@00500000 {
-+ num-ports = <1>;
-+ status = "okay";
-+ };
-+ };
-+
-+ i2c@0 {
-+ status = "okay";
-+
-+ pcf8563@51 {
-+ /* nxp pcf8563 rtc */
-+ compatible = "nxp,pcf8563";
-+ reg = <0x51>;
-+ };
-+
-+ };
-+
-+ leds {
-+ compatible = "gpio-leds";
-+
-+ led1g {
-+ label = "led1:green";
-+ gpios = <&pioB 0 1>;
-+ linux,default-trigger = "none";
-+ };
-+
-+ led1r {
-+ label = "led1:red";
-+ gpios = <&pioB 1 1>;
-+ linux,default-trigger = "none";
-+ };
-+
-+ led2g {
-+ label = "led2:green";
-+ gpios = <&pioB 2 1>;
-+ linux,default-trigger = "none";
-+ default-state = "on";
-+ };
-+
-+ led2r {
-+ label = "led2:red";
-+ gpios = <&pioB 3 1>;
-+ linux,default-trigger = "none";
-+ };
-+ };
-+
-+ gpio_keys {
-+ compatible = "gpio-keys";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ reset {
-+ label = "reset";
-+ gpios = <&pioB 30 1>;
-+ linux,code = <0x100>;
-+ gpio-key,wakeup;
-+ };
-+
-+ mode {
-+ label = "mode";
-+ gpios = <&pioB 31 1>;
-+ linux,code = <0x101>;
-+ gpio-key,wakeup;
-+ };
-+ };
-+};
-\ No newline at end of file
-diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
-index 618fc5b..99e8097 100644
---- a/arch/arm/mach-at91/Makefile.boot
-+++ b/arch/arm/mach-at91/Makefile.boot
-@@ -24,6 +24,7 @@ dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9263.dtb
- # sam9g20
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g20ek.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g20ek_2mmc.dtb
-+dtb-$(CONFIG_MACH_AT91SAM_DT) += kizbox.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9g20.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9g20.dtb
- # sam9g45
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b05042223346bdeceecd5f4039da27b86010f682 Mon Sep 17 00:00:00 2001
-From: Tim Schendekehl <tim.schendekehl@egnite.de>
-Date: Tue, 24 Apr 2012 18:47:59 +0200
-Subject: Ethernut 5 board support
-
-commit 26690863e2c1fa4fee5f6137b219f4b8a1a02287 upstream.
-
-Add support for the Ethernut 5 open hardware design, based
-on Atmel's AT91SAM9XE512 SoC.
-
-Signed-off-by: Tim Schendekehl <tim.schendekehl@egnite.de>
----
- arch/arm/boot/dts/ethernut5.dts | 84 ++++++++++++++++++++++++++++++++++++++++
- arch/arm/mach-at91/Makefile.boot | 1 +
- 2 files changed, 85 insertions(+)
- create mode 100644 arch/arm/boot/dts/ethernut5.dts
-
-diff --git a/arch/arm/boot/dts/ethernut5.dts b/arch/arm/boot/dts/ethernut5.dts
-new file mode 100644
-index 0000000..1ea9d34
---- /dev/null
-+++ b/arch/arm/boot/dts/ethernut5.dts
-@@ -0,0 +1,84 @@
-+/*
-+ * ethernut5.dts - Device Tree file for Ethernut 5 board
-+ *
-+ * Copyright (C) 2012 egnite GmbH <info@egnite.de>
-+ *
-+ * Licensed under GPLv2.
-+ */
-+/dts-v1/;
-+/include/ "at91sam9260.dtsi"
-+
-+/ {
-+ model = "Ethernut 5";
-+ compatible = "egnite,ethernut5", "atmel,at91sam9260", "atmel,at91sam9";
-+
-+ chosen {
-+ bootargs = "console=ttyS0,115200 root=/dev/mtdblock0 rw rootfstype=jffs2";
-+ };
-+
-+ memory {
-+ reg = <0x20000000 0x08000000>;
-+ };
-+
-+ ahb {
-+ apb {
-+ dbgu: serial@fffff200 {
-+ status = "okay";
-+ };
-+
-+ usart0: serial@fffb0000 {
-+ status = "okay";
-+ };
-+
-+ usart1: serial@fffb4000 {
-+ status = "okay";
-+ };
-+
-+ macb0: ethernet@fffc4000 {
-+ phy-mode = "rmii";
-+ status = "okay";
-+ };
-+
-+ usb1: gadget@fffa4000 {
-+ atmel,vbus-gpio = <&pioC 5 0>;
-+ status = "okay";
-+ };
-+ };
-+
-+ nand0: nand@40000000 {
-+ nand-bus-width = <8>;
-+ nand-ecc-mode = "soft";
-+ nand-on-flash-bbt;
-+ status = "okay";
-+
-+ gpios = <0
-+ &pioC 14 0
-+ 0
-+ >;
-+
-+ root@0 {
-+ label = "root";
-+ reg = <0x0 0x08000000>;
-+ };
-+
-+ data@20000 {
-+ label = "data";
-+ reg = <0x08000000 0x38000000>;
-+ };
-+ };
-+
-+ usb0: ohci@00500000 {
-+ num-ports = <2>;
-+ status = "okay";
-+ };
-+ };
-+
-+ i2c@0 {
-+ status = "okay";
-+
-+ pcf8563@50 {
-+ compatible = "nxp,pcf8563";
-+ reg = <0x51>;
-+ };
-+ };
-+};
-diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
-index 99e8097..c03417d 100644
---- a/arch/arm/mach-at91/Makefile.boot
-+++ b/arch/arm/mach-at91/Makefile.boot
-@@ -15,6 +15,7 @@ endif
-
- # Keep dtb files sorted alphabetically for each SoC
- # sam9260
-+dtb-$(CONFIG_MACH_AT91SAM_DT) += ethernut5.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9260.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9260.dtb
- # sam9263
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 917cda0ea634a3812fbe22a20f634254beafa1a0 Mon Sep 17 00:00:00 2001
-From: Hong Xu <hong.xu@atmel.com>
-Date: Tue, 17 Apr 2012 14:26:30 +0800
-Subject: ARM: at91: Add machine header file for AT91SAM9N12 SoC
-
-commit 02059684271079f96e2a7a4bdc7912f029997866 upstream.
-
-Signed-off-by: Hong Xu <hong.xu@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/mach-at91/include/mach/at91sam9n12.h | 60 ++++++++++++++++++++++
- .../mach-at91/include/mach/at91sam9n12_matrix.h | 53 +++++++++++++++++++
- arch/arm/mach-at91/include/mach/cpu.h | 10 ++++
- arch/arm/mach-at91/include/mach/hardware.h | 1 +
- arch/arm/mach-at91/soc.h | 5 ++
- 5 files changed, 129 insertions(+)
- create mode 100644 arch/arm/mach-at91/include/mach/at91sam9n12.h
- create mode 100644 arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h
-
-diff --git a/arch/arm/mach-at91/include/mach/at91sam9n12.h b/arch/arm/mach-at91/include/mach/at91sam9n12.h
-new file mode 100644
-index 0000000..d374b87
---- /dev/null
-+++ b/arch/arm/mach-at91/include/mach/at91sam9n12.h
-@@ -0,0 +1,60 @@
-+/*
-+ * SoC specific header file for the AT91SAM9N12
-+ *
-+ * Copyright (C) 2012 Atmel Corporation
-+ *
-+ * Common definitions, based on AT91SAM9N12 SoC datasheet
-+ *
-+ * Licensed under GPLv2 or later
-+ */
-+
-+#ifndef _AT91SAM9N12_H_
-+#define _AT91SAM9N12_H_
-+
-+/*
-+ * Peripheral identifiers/interrupts.
-+ */
-+#define AT91SAM9N12_ID_PIOAB 2 /* Parallel I/O Controller A and B */
-+#define AT91SAM9N12_ID_PIOCD 3 /* Parallel I/O Controller C and D */
-+#define AT91SAM9N12_ID_FUSE 4 /* FUSE Controller */
-+#define AT91SAM9N12_ID_USART0 5 /* USART 0 */
-+#define AT91SAM9N12_ID_USART1 6 /* USART 1 */
-+#define AT91SAM9N12_ID_USART2 7 /* USART 2 */
-+#define AT91SAM9N12_ID_USART3 8 /* USART 3 */
-+#define AT91SAM9N12_ID_TWI0 9 /* Two-Wire Interface 0 */
-+#define AT91SAM9N12_ID_TWI1 10 /* Two-Wire Interface 1 */
-+#define AT91SAM9N12_ID_MCI 12 /* High Speed Multimedia Card Interface */
-+#define AT91SAM9N12_ID_SPI0 13 /* Serial Peripheral Interface 0 */
-+#define AT91SAM9N12_ID_SPI1 14 /* Serial Peripheral Interface 1 */
-+#define AT91SAM9N12_ID_UART0 15 /* UART 0 */
-+#define AT91SAM9N12_ID_UART1 16 /* UART 1 */
-+#define AT91SAM9N12_ID_TCB 17 /* Timer Counter 0, 1, 2, 3, 4 and 5 */
-+#define AT91SAM9N12_ID_PWM 18 /* Pulse Width Modulation Controller */
-+#define AT91SAM9N12_ID_ADC 19 /* ADC Controller */
-+#define AT91SAM9N12_ID_DMA 20 /* DMA Controller */
-+#define AT91SAM9N12_ID_UHP 22 /* USB Host High Speed */
-+#define AT91SAM9N12_ID_UDP 23 /* USB Device High Speed */
-+#define AT91SAM9N12_ID_LCDC 25 /* LCD Controller */
-+#define AT91SAM9N12_ID_ISI 25 /* Image Sensor Interface */
-+#define AT91SAM9N12_ID_SSC 28 /* Synchronous Serial Controller */
-+#define AT91SAM9N12_ID_TRNG 30 /* TRNG */
-+#define AT91SAM9N12_ID_IRQ0 31 /* Advanced Interrupt Controller */
-+
-+/*
-+ * User Peripheral physical base addresses.
-+ */
-+#define AT91SAM9N12_BASE_USART0 0xf801c000
-+#define AT91SAM9N12_BASE_USART1 0xf8020000
-+#define AT91SAM9N12_BASE_USART2 0xf8024000
-+#define AT91SAM9N12_BASE_USART3 0xf8028000
-+
-+/*
-+ * Internal Memory.
-+ */
-+#define AT91SAM9N12_SRAM_BASE 0x00300000 /* Internal SRAM base address */
-+#define AT91SAM9N12_SRAM_SIZE SZ_32K /* Internal SRAM size (32Kb) */
-+
-+#define AT91SAM9N12_ROM_BASE 0x00100000 /* Internal ROM base address */
-+#define AT91SAM9N12_ROM_SIZE SZ_128K /* Internal ROM size (128Kb) */
-+
-+#endif
-diff --git a/arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h
-new file mode 100644
-index 0000000..40060cd
---- /dev/null
-+++ b/arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h
-@@ -0,0 +1,53 @@
-+/*
-+ * Matrix-centric header file for the AT91SAM9N12
-+ *
-+ * Copyright (C) 2012 Atmel Corporation.
-+ *
-+ * Only EBI related registers.
-+ * Write Protect register definitions may be useful.
-+ *
-+ * Licensed under GPLv2 or later.
-+ */
-+
-+#ifndef _AT91SAM9N12_MATRIX_H_
-+#define _AT91SAM9N12_MATRIX_H_
-+
-+#define AT91_MATRIX_EBICSA (AT91_MATRIX + 0x118) /* EBI Chip Select Assignment Register */
-+#define AT91_MATRIX_EBI_CS1A (1 << 1) /* Chip Select 1 Assignment */
-+#define AT91_MATRIX_EBI_CS1A_SMC (0 << 1)
-+#define AT91_MATRIX_EBI_CS1A_SDRAMC (1 << 1)
-+#define AT91_MATRIX_EBI_CS3A (1 << 3) /* Chip Select 3 Assignment */
-+#define AT91_MATRIX_EBI_CS3A_SMC (0 << 3)
-+#define AT91_MATRIX_EBI_CS3A_SMC_NANDFLASH (1 << 3)
-+#define AT91_MATRIX_EBI_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */
-+#define AT91_MATRIX_EBI_DBPU_ON (0 << 8)
-+#define AT91_MATRIX_EBI_DBPU_OFF (1 << 8)
-+#define AT91_MATRIX_EBI_VDDIOMSEL (1 << 16) /* Memory voltage selection */
-+#define AT91_MATRIX_EBI_VDDIOMSEL_1_8V (0 << 16)
-+#define AT91_MATRIX_EBI_VDDIOMSEL_3_3V (1 << 16)
-+#define AT91_MATRIX_EBI_EBI_IOSR (1 << 17) /* EBI I/O slew rate selection */
-+#define AT91_MATRIX_EBI_EBI_IOSR_REDUCED (0 << 17)
-+#define AT91_MATRIX_EBI_EBI_IOSR_NORMAL (1 << 17)
-+#define AT91_MATRIX_EBI_DDR_IOSR (1 << 18) /* DDR2 dedicated port I/O slew rate selection */
-+#define AT91_MATRIX_EBI_DDR_IOSR_REDUCED (0 << 18)
-+#define AT91_MATRIX_EBI_DDR_IOSR_NORMAL (1 << 18)
-+#define AT91_MATRIX_NFD0_SELECT (1 << 24) /* NAND Flash Data Bus Selection */
-+#define AT91_MATRIX_NFD0_ON_D0 (0 << 24)
-+#define AT91_MATRIX_NFD0_ON_D16 (1 << 24)
-+#define AT91_MATRIX_DDR_MP_EN (1 << 25) /* DDR Multi-port Enable */
-+#define AT91_MATRIX_MP_OFF (0 << 25)
-+#define AT91_MATRIX_MP_ON (1 << 25)
-+
-+#define AT91_MATRIX_WPMR (AT91_MATRIX + 0x1E4) /* Write Protect Mode Register */
-+#define AT91_MATRIX_WPMR_WPEN (1 << 0) /* Write Protect ENable */
-+#define AT91_MATRIX_WPMR_WP_WPDIS (0 << 0)
-+#define AT91_MATRIX_WPMR_WP_WPEN (1 << 0)
-+#define AT91_MATRIX_WPMR_WPKEY (0xFFFFFF << 8) /* Write Protect KEY */
-+
-+#define AT91_MATRIX_WPSR (AT91_MATRIX + 0x1E8) /* Write Protect Status Register */
-+#define AT91_MATRIX_WPSR_WPVS (1 << 0) /* Write Protect Violation Status */
-+#define AT91_MATRIX_WPSR_NO_WPV (0 << 0)
-+#define AT91_MATRIX_WPSR_WPV (1 << 0)
-+#define AT91_MATRIX_WPSR_WPVSRC (0xFFFF << 8) /* Write Protect Violation Source */
-+
-+#endif
-diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h
-index 73d2fd2..b6504c1 100644
---- a/arch/arm/mach-at91/include/mach/cpu.h
-+++ b/arch/arm/mach-at91/include/mach/cpu.h
-@@ -25,6 +25,7 @@
- #define ARCH_ID_AT91SAM9G45MRL 0x819b05a2 /* aka 9G45-ES2 & non ES lots */
- #define ARCH_ID_AT91SAM9G45ES 0x819b05a1 /* 9G45-ES (Engineering Sample) */
- #define ARCH_ID_AT91SAM9X5 0x819a05a0
-+#define ARCH_ID_AT91SAM9N12 0x819a07a0
-
- #define ARCH_ID_AT91SAM9XE128 0x329973a0
- #define ARCH_ID_AT91SAM9XE256 0x329a93a0
-@@ -71,6 +72,9 @@ enum at91_soc_type {
- /* SAM9X5 */
- AT91_SOC_SAM9X5,
-
-+ /* SAM9N12 */
-+ AT91_SOC_SAM9N12,
-+
- /* Unknown type */
- AT91_SOC_NONE
- };
-@@ -177,6 +181,12 @@ static inline int at91_soc_is_detected(void)
- #define cpu_is_at91sam9x25() (0)
- #endif
-
-+#ifdef CONFIG_SOC_AT91SAM9N12
-+#define cpu_is_at91sam9n12() (at91_soc_initdata.type == AT91_SOC_SAM9N12)
-+#else
-+#define cpu_is_at91sam9n12() (0)
-+#endif
-+
- /*
- * Since this is ARM, we will never run on any AVR32 CPU. But these
- * definitions may reduce clutter in common drivers.
-diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h
-index 3a01f8f..24b46bd 100644
---- a/arch/arm/mach-at91/include/mach/hardware.h
-+++ b/arch/arm/mach-at91/include/mach/hardware.h
-@@ -32,6 +32,7 @@
- #include <mach/at91sam9rl.h>
- #include <mach/at91sam9g45.h>
- #include <mach/at91sam9x5.h>
-+#include <mach/at91sam9n12.h>
-
- /*
- * On all at91 except rm9200 and x40 have the System Controller starts
-diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
-index 683dddf..a9cfeb1 100644
---- a/arch/arm/mach-at91/soc.h
-+++ b/arch/arm/mach-at91/soc.h
-@@ -20,6 +20,7 @@ extern struct at91_init_soc at91sam9263_soc;
- extern struct at91_init_soc at91sam9g45_soc;
- extern struct at91_init_soc at91sam9rl_soc;
- extern struct at91_init_soc at91sam9x5_soc;
-+extern struct at91_init_soc at91sam9n12_soc;
-
- static inline int at91_soc_is_enabled(void)
- {
-@@ -53,3 +54,7 @@ static inline int at91_soc_is_enabled(void)
- #if !defined(CONFIG_SOC_AT91SAM9X5)
- #define at91sam9x5_soc at91_boot_soc
- #endif
-+
-+#if !defined(CONFIG_SOC_AT91SAM9N12)
-+#define at91sam9n12_soc at91_boot_soc
-+#endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From db8c0e1e68b38c879f7ff677bdacd20c3ec5b388 Mon Sep 17 00:00:00 2001
-From: Hong Xu <hong.xu@atmel.com>
-Date: Tue, 17 Apr 2012 14:26:31 +0800
-Subject: ARM: at91: Add machine files for AT91SAM9N12 SoC
-
-commit 74db4fb93e4ed4d6241bf0f28e4b5d68a7a05577 upstream.
-
-Signed-off-by: Hong Xu <hong.xu@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/mach-at91/Kconfig | 8 +
- arch/arm/mach-at91/Makefile | 1
- arch/arm/mach-at91/Makefile.boot | 2
- arch/arm/mach-at91/at91sam9n12.c | 233 +++++++++++++++++++++++++++++++++++++++
- arch/arm/mach-at91/clock.c | 15 +-
- arch/arm/mach-at91/setup.c | 6 +
- 6 files changed, 260 insertions(+), 5 deletions(-)
- create mode 100644 arch/arm/mach-at91/at91sam9n12.c
-
---- a/arch/arm/mach-at91/Kconfig
-+++ b/arch/arm/mach-at91/Kconfig
-@@ -91,6 +91,14 @@ config SOC_AT91SAM9X5
- This support covers AT91SAM9G15, AT91SAM9G25, AT91SAM9X25, AT91SAM9G35
- and AT91SAM9X35.
-
-+config SOC_AT91SAM9N12
-+ bool "AT91SAM9N12 family"
-+ select SOC_AT91SAM9
-+ select HAVE_AT91_DBGU0
-+ select HAVE_FB_ATMEL
-+ help
-+ Select this if you are using Atmel's AT91SAM9N12 SoC.
-+
- choice
- prompt "Atmel AT91 Processor Devices for non DT boards"
-
---- a/arch/arm/mach-at91/Makefile
-+++ b/arch/arm/mach-at91/Makefile
-@@ -18,6 +18,7 @@ obj-$(CONFIG_SOC_AT91SAM9260) += at91sam
- obj-$(CONFIG_SOC_AT91SAM9261) += at91sam9261.o
- obj-$(CONFIG_SOC_AT91SAM9263) += at91sam9263.o
- obj-$(CONFIG_SOC_AT91SAM9G45) += at91sam9g45.o
-+obj-$(CONFIG_SOC_AT91SAM9N12) += at91sam9n12.o
- obj-$(CONFIG_SOC_AT91SAM9X5) += at91sam9x5.o
- obj-$(CONFIG_SOC_AT91SAM9RL) += at91sam9rl.o
-
---- a/arch/arm/mach-at91/Makefile.boot
-+++ b/arch/arm/mach-at91/Makefile.boot
-@@ -30,5 +30,7 @@ dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9g
- dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9g20.dtb
- # sam9g45
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9m10g45ek.dtb
-+# sam9n12
-+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9n12ek.dtb
- # sam9x5
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g25ek.dtb
---- /dev/null
-+++ b/arch/arm/mach-at91/at91sam9n12.c
-@@ -0,0 +1,233 @@
-+/*
-+ * SoC specific setup code for the AT91SAM9N12
-+ *
-+ * Copyright (C) 2012 Atmel Corporation.
-+ *
-+ * Licensed under GPLv2 or later.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/dma-mapping.h>
-+
-+#include <asm/irq.h>
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <mach/at91sam9n12.h>
-+#include <mach/at91_pmc.h>
-+#include <mach/cpu.h>
-+#include <mach/board.h>
-+
-+#include "soc.h"
-+#include "generic.h"
-+#include "clock.h"
-+#include "sam9_smc.h"
-+
-+/* --------------------------------------------------------------------
-+ * Clocks
-+ * -------------------------------------------------------------------- */
-+
-+/*
-+ * The peripheral clocks.
-+ */
-+static struct clk pioAB_clk = {
-+ .name = "pioAB_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_PIOAB,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk pioCD_clk = {
-+ .name = "pioCD_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_PIOCD,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk usart0_clk = {
-+ .name = "usart0_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_USART0,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk usart1_clk = {
-+ .name = "usart1_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_USART1,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk usart2_clk = {
-+ .name = "usart2_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_USART2,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk usart3_clk = {
-+ .name = "usart3_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_USART3,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk twi0_clk = {
-+ .name = "twi0_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_TWI0,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk twi1_clk = {
-+ .name = "twi1_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_TWI1,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk mmc_clk = {
-+ .name = "mci_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_MCI,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk spi0_clk = {
-+ .name = "spi0_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_SPI0,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk spi1_clk = {
-+ .name = "spi1_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_SPI1,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk uart0_clk = {
-+ .name = "uart0_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_UART0,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk uart1_clk = {
-+ .name = "uart1_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_UART1,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk tcb_clk = {
-+ .name = "tcb_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_TCB,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk pwm_clk = {
-+ .name = "pwm_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_PWM,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk adc_clk = {
-+ .name = "adc_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_ADC,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk dma_clk = {
-+ .name = "dma_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_DMA,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk uhp_clk = {
-+ .name = "uhp",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_UHP,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk udp_clk = {
-+ .name = "udp_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_UDP,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk lcdc_clk = {
-+ .name = "lcdc_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_LCDC,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk ssc_clk = {
-+ .name = "ssc_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_SSC,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+
-+static struct clk *periph_clocks[] __initdata = {
-+ &pioAB_clk,
-+ &pioCD_clk,
-+ &usart0_clk,
-+ &usart1_clk,
-+ &usart2_clk,
-+ &usart3_clk,
-+ &twi0_clk,
-+ &twi1_clk,
-+ &mmc_clk,
-+ &spi0_clk,
-+ &spi1_clk,
-+ &lcdc_clk,
-+ &uart0_clk,
-+ &uart1_clk,
-+ &tcb_clk,
-+ &pwm_clk,
-+ &adc_clk,
-+ &dma_clk,
-+ &uhp_clk,
-+ &udp_clk,
-+ &ssc_clk,
-+};
-+
-+static struct clk_lookup periph_clocks_lookups[] = {
-+ /* lookup table for DT entries */
-+ CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
-+ CLKDEV_CON_DEV_ID("usart", "f801c000.serial", &usart0_clk),
-+ CLKDEV_CON_DEV_ID("usart", "f8020000.serial", &usart1_clk),
-+ CLKDEV_CON_DEV_ID("usart", "f8024000.serial", &usart2_clk),
-+ CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
-+ CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb_clk),
-+ CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb_clk),
-+ CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma_clk),
-+ CLKDEV_CON_ID("pioA", &pioAB_clk),
-+ CLKDEV_CON_ID("pioB", &pioAB_clk),
-+ CLKDEV_CON_ID("pioC", &pioCD_clk),
-+ CLKDEV_CON_ID("pioD", &pioCD_clk),
-+ /* additional fake clock for macb_hclk */
-+ CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &uhp_clk),
-+ CLKDEV_CON_DEV_ID("ohci_clk", "500000.ohci", &uhp_clk),
-+};
-+
-+/*
-+ * The two programmable clocks.
-+ * You must configure pin multiplexing to bring these signals out.
-+ */
-+static struct clk pck0 = {
-+ .name = "pck0",
-+ .pmc_mask = AT91_PMC_PCK0,
-+ .type = CLK_TYPE_PROGRAMMABLE,
-+ .id = 0,
-+};
-+static struct clk pck1 = {
-+ .name = "pck1",
-+ .pmc_mask = AT91_PMC_PCK1,
-+ .type = CLK_TYPE_PROGRAMMABLE,
-+ .id = 1,
-+};
-+
-+static void __init at91sam9n12_register_clocks(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
-+ clk_register(periph_clocks[i]);
-+ clk_register(&pck0);
-+ clk_register(&pck1);
-+
-+ clkdev_add_table(periph_clocks_lookups,
-+ ARRAY_SIZE(periph_clocks_lookups));
-+
-+}
-+
-+/* --------------------------------------------------------------------
-+ * AT91SAM9N12 processor initialization
-+ * -------------------------------------------------------------------- */
-+
-+static void __init at91sam9n12_map_io(void)
-+{
-+ at91_init_sram(0, AT91SAM9N12_SRAM_BASE, AT91SAM9N12_SRAM_SIZE);
-+}
-+
-+void __init at91sam9n12_initialize(void)
-+{
-+ at91_extern_irq = (1 << AT91SAM9N12_ID_IRQ0);
-+
-+ /* Register GPIO subsystem (using DT) */
-+ at91_gpio_init(NULL, 0);
-+}
-+
-+struct at91_init_soc __initdata at91sam9n12_soc = {
-+ .map_io = at91sam9n12_map_io,
-+ .register_clocks = at91sam9n12_register_clocks,
-+ .init = at91sam9n12_initialize,
-+};
---- a/arch/arm/mach-at91/clock.c
-+++ b/arch/arm/mach-at91/clock.c
-@@ -58,13 +58,15 @@ EXPORT_SYMBOL_GPL(at91_pmc_base);
-
- #define cpu_has_800M_plla() ( cpu_is_at91sam9g20() \
- || cpu_is_at91sam9g45() \
-- || cpu_is_at91sam9x5())
-+ || cpu_is_at91sam9x5() \
-+ || cpu_is_at91sam9n12())
-
- #define cpu_has_300M_plla() (cpu_is_at91sam9g10())
-
- #define cpu_has_pllb() (!(cpu_is_at91sam9rl() \
- || cpu_is_at91sam9g45() \
-- || cpu_is_at91sam9x5()))
-+ || cpu_is_at91sam9x5() \
-+ || cpu_is_at91sam9n12()))
-
- #define cpu_has_upll() (cpu_is_at91sam9g45() \
- || cpu_is_at91sam9x5())
-@@ -78,12 +80,15 @@ EXPORT_SYMBOL_GPL(at91_pmc_base);
- || cpu_is_at91sam9x5()))
-
- #define cpu_has_plladiv2() (cpu_is_at91sam9g45() \
-- || cpu_is_at91sam9x5())
-+ || cpu_is_at91sam9x5() \
-+ || cpu_is_at91sam9n12())
-
- #define cpu_has_mdiv3() (cpu_is_at91sam9g45() \
-- || cpu_is_at91sam9x5())
-+ || cpu_is_at91sam9x5() \
-+ || cpu_is_at91sam9n12())
-
--#define cpu_has_alt_prescaler() (cpu_is_at91sam9x5())
-+#define cpu_has_alt_prescaler() (cpu_is_at91sam9x5() \
-+ || cpu_is_at91sam9n12())
-
- static LIST_HEAD(clocks);
- static DEFINE_SPINLOCK(clk_lock);
---- a/arch/arm/mach-at91/setup.c
-+++ b/arch/arm/mach-at91/setup.c
-@@ -145,6 +145,11 @@ static void __init soc_detect(u32 dbgu_b
- at91_soc_initdata.type = AT91_SOC_SAM9X5;
- at91_boot_soc = at91sam9x5_soc;
- break;
-+
-+ case ARCH_ID_AT91SAM9N12:
-+ at91_soc_initdata.type = AT91_SOC_SAM9N12;
-+ at91_boot_soc = at91sam9n12_soc;
-+ break;
- }
-
- /* at91sam9g10 */
-@@ -212,6 +217,7 @@ static const char *soc_name[] = {
- [AT91_SOC_SAM9G45] = "at91sam9g45",
- [AT91_SOC_SAM9RL] = "at91sam9rl",
- [AT91_SOC_SAM9X5] = "at91sam9x5",
-+ [AT91_SOC_SAM9N12] = "at91sam9n12",
- [AT91_SOC_NONE] = "Unknown"
- };
-
+++ /dev/null
-From a38377b607a1019457b443714b66b7d9cdd47380 Mon Sep 17 00:00:00 2001
-From: Hong Xu <hong.xu@atmel.com>
-Date: Tue, 17 Apr 2012 14:26:29 +0800
-Subject: ARM: at91: Add DT description files for AT91SAM9N12-EK
-
-commit cce783c608fee0716cff65926d1835a5fd097b69 upstream.
-
-Added AT91SAM9N12 SoC DT file, as well as the board definition
-.dts file for AT91SAM9N12-EK.
-
-Signed-off-by: Hong Xu <hong.xu@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/boot/dts/at91sam9n12.dtsi | 221 ++++++++++++++++++++++++++++++++++++
- arch/arm/boot/dts/at91sam9n12ek.dts | 84 ++++++++++++++
- 2 files changed, 305 insertions(+)
- create mode 100644 arch/arm/boot/dts/at91sam9n12.dtsi
- create mode 100644 arch/arm/boot/dts/at91sam9n12ek.dts
-
-diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
-new file mode 100644
-index 0000000..cb84de7
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
-@@ -0,0 +1,221 @@
-+/*
-+ * at91sam9n12.dtsi - Device Tree include file for AT91SAM9N12 SoC
-+ *
-+ * Copyright (C) 2012 Atmel,
-+ * 2012 Hong Xu <hong.xu@atmel.com>
-+ *
-+ * Licensed under GPLv2 or later.
-+ */
-+
-+/include/ "skeleton.dtsi"
-+
-+/ {
-+ model = "Atmel AT91SAM9N12 SoC";
-+ compatible = "atmel,at91sam9n12";
-+ interrupt-parent = <&aic>;
-+
-+ aliases {
-+ serial0 = &dbgu;
-+ serial1 = &usart0;
-+ serial2 = &usart1;
-+ serial3 = &usart2;
-+ serial4 = &usart3;
-+ gpio0 = &pioA;
-+ gpio1 = &pioB;
-+ gpio2 = &pioC;
-+ gpio3 = &pioD;
-+ tcb0 = &tcb0;
-+ tcb1 = &tcb1;
-+ };
-+ cpus {
-+ cpu@0 {
-+ compatible = "arm,arm926ejs";
-+ };
-+ };
-+
-+ memory {
-+ reg = <0x20000000 0x10000000>;
-+ };
-+
-+ ahb {
-+ compatible = "simple-bus";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ apb {
-+ compatible = "simple-bus";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ aic: interrupt-controller@fffff000 {
-+ #interrupt-cells = <2>;
-+ compatible = "atmel,at91rm9200-aic";
-+ interrupt-controller;
-+ reg = <0xfffff000 0x200>;
-+ };
-+
-+ ramc0: ramc@ffffe800 {
-+ compatible = "atmel,at91sam9g45-ddramc";
-+ reg = <0xffffe800 0x200>;
-+ };
-+
-+ pmc: pmc@fffffc00 {
-+ compatible = "atmel,at91rm9200-pmc";
-+ reg = <0xfffffc00 0x100>;
-+ };
-+
-+ rstc@fffffe00 {
-+ compatible = "atmel,at91sam9g45-rstc";
-+ reg = <0xfffffe00 0x10>;
-+ };
-+
-+ pit: timer@fffffe30 {
-+ compatible = "atmel,at91sam9260-pit";
-+ reg = <0xfffffe30 0xf>;
-+ interrupts = <1 4>;
-+ };
-+
-+ shdwc@fffffe10 {
-+ compatible = "atmel,at91sam9x5-shdwc";
-+ reg = <0xfffffe10 0x10>;
-+ };
-+
-+ tcb0: timer@f8008000 {
-+ compatible = "atmel,at91sam9x5-tcb";
-+ reg = <0xf8008000 0x100>;
-+ interrupts = <17 4>;
-+ };
-+
-+ tcb1: timer@f800c000 {
-+ compatible = "atmel,at91sam9x5-tcb";
-+ reg = <0xf800c000 0x100>;
-+ interrupts = <17 4>;
-+ };
-+
-+ dma: dma-controller@ffffec00 {
-+ compatible = "atmel,at91sam9g45-dma";
-+ reg = <0xffffec00 0x200>;
-+ interrupts = <20 4>;
-+ };
-+
-+ pioA: gpio@fffff400 {
-+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-+ reg = <0xfffff400 0x100>;
-+ interrupts = <2 4>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ };
-+
-+ pioB: gpio@fffff600 {
-+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-+ reg = <0xfffff600 0x100>;
-+ interrupts = <2 4>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ };
-+
-+ pioC: gpio@fffff800 {
-+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-+ reg = <0xfffff800 0x100>;
-+ interrupts = <3 4>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ };
-+
-+ pioD: gpio@fffffa00 {
-+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-+ reg = <0xfffffa00 0x100>;
-+ interrupts = <3 4>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ };
-+
-+ dbgu: serial@fffff200 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xfffff200 0x200>;
-+ interrupts = <1 4>;
-+ status = "disabled";
-+ };
-+
-+ usart0: serial@f801c000 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xf801c000 0x4000>;
-+ interrupts = <5 4>;
-+ atmel,use-dma-rx;
-+ atmel,use-dma-tx;
-+ status = "disabled";
-+ };
-+
-+ usart1: serial@f8020000 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xf8020000 0x4000>;
-+ interrupts = <6 4>;
-+ atmel,use-dma-rx;
-+ atmel,use-dma-tx;
-+ status = "disabled";
-+ };
-+
-+ usart2: serial@f8024000 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xf8024000 0x4000>;
-+ interrupts = <7 4>;
-+ atmel,use-dma-rx;
-+ atmel,use-dma-tx;
-+ status = "disabled";
-+ };
-+
-+ usart3: serial@f8028000 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xf8028000 0x4000>;
-+ interrupts = <8 4>;
-+ atmel,use-dma-rx;
-+ atmel,use-dma-tx;
-+ status = "disabled";
-+ };
-+ };
-+
-+ nand0: nand@40000000 {
-+ compatible = "atmel,at91rm9200-nand";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ reg = < 0x40000000 0x10000000
-+ 0xffffe000 0x00000600
-+ 0xffffe600 0x00000200
-+ 0x00100000 0x00100000
-+ >;
-+ atmel,nand-addr-offset = <21>;
-+ atmel,nand-cmd-offset = <22>;
-+ gpios = <&pioD 5 0
-+ &pioD 4 0
-+ 0
-+ >;
-+ status = "disabled";
-+ };
-+
-+ usb0: ohci@00500000 {
-+ compatible = "atmel,at91rm9200-ohci", "usb-ohci";
-+ reg = <0x00500000 0x00100000>;
-+ interrupts = <22 4>;
-+ status = "disabled";
-+ };
-+ };
-+
-+ i2c@0 {
-+ compatible = "i2c-gpio";
-+ gpios = <&pioA 30 0 /* sda */
-+ &pioA 31 0 /* scl */
-+ >;
-+ i2c-gpio,sda-open-drain;
-+ i2c-gpio,scl-open-drain;
-+ i2c-gpio,delay-us = <2>; /* ~100 kHz */
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+};
-diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts
-new file mode 100644
-index 0000000..f4e43e3
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9n12ek.dts
-@@ -0,0 +1,84 @@
-+/*
-+ * at91sam9n12ek.dts - Device Tree file for AT91SAM9N12-EK board
-+ *
-+ * Copyright (C) 2012 Atmel,
-+ * 2012 Hong Xu <hong.xu@atmel.com>
-+ *
-+ * Licensed under GPLv2 or later.
-+ */
-+/dts-v1/;
-+/include/ "at91sam9n12.dtsi"
-+
-+/ {
-+ model = "Atmel AT91SAM9N12-EK";
-+ compatible = "atmel,at91sam9n12ek", "atmel,at91sam9n12", "atmel,at91sam9";
-+
-+ chosen {
-+ bootargs = "mem=128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
-+ };
-+
-+ memory {
-+ reg = <0x20000000 0x10000000>;
-+ };
-+
-+ clocks {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ main_clock: clock@0 {
-+ compatible = "atmel,osc", "fixed-clock";
-+ clock-frequency = <16000000>;
-+ };
-+ };
-+
-+ ahb {
-+ apb {
-+ dbgu: serial@fffff200 {
-+ status = "okay";
-+ };
-+ };
-+
-+ nand0: nand@40000000 {
-+ nand-bus-width = <8>;
-+ nand-ecc-mode = "soft";
-+ nand-on-flash-bbt;
-+ status = "okay";
-+ };
-+ };
-+
-+ leds {
-+ compatible = "gpio-leds";
-+
-+ d8 {
-+ label = "d8";
-+ gpios = <&pioB 4 1>;
-+ linux,default-trigger = "mmc0";
-+ };
-+
-+ d9 {
-+ label = "d6";
-+ gpios = <&pioB 5 1>;
-+ linux,default-trigger = "nand-disk";
-+ };
-+
-+ d10 {
-+ label = "d7";
-+ gpios = <&pioB 6 0>;
-+ linux,default-trigger = "heartbeat";
-+ };
-+ };
-+
-+ gpio_keys {
-+ compatible = "gpio-keys";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ enter {
-+ label = "Enter";
-+ gpios = <&pioB 4 1>;
-+ linux,code = <28>;
-+ gpio-key,wakeup;
-+ };
-+ };
-+};
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From cf269a7d1c0c08e2f7d609f026c28e32d41a1b0d Mon Sep 17 00:00:00 2001
-From: Paul Bolle <pebolle@tiscali.nl>
-Date: Thu, 7 Jun 2012 12:18:46 +0200
-Subject: ARM: at91: remove two unused headers
-
-commit 2d1c9ccd68cdee502eb4829dfe1def7debc0298e upstream.
-
-Commit 82c583e3ae31ffa76d1280197274cc1e1cde3179 ("AT91RM9200 hardware
-headers") introduced arch/arm/mach-at91/include/mach/at91_spi.h and
-arch/arm/mach-at91/include/mach/at91_ssc.h. (These files were called
-at91rm9200_spi.h and at91rm9200_ssc.h then.) That commit was added in
-the v2.6.18 development cycle.
-
-Nothing includes them now and nothing uses the named constants they
-provide. (There's no way these named constants could be used unless
-these files were included somehow.) It actually seems these two headers
-have never been used since they were added to the tree. They can safely
-be removed.
-
-Signed-off-by: Paul Bolle <pebolle@tiscali.nl>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/include/mach/at91_spi.h | 81 ----------------------
- arch/arm/mach-at91/include/mach/at91_ssc.h | 106 -----------------------------
- 2 files changed, 187 deletions(-)
- delete mode 100644 arch/arm/mach-at91/include/mach/at91_spi.h
- delete mode 100644 arch/arm/mach-at91/include/mach/at91_ssc.h
-
-diff --git a/arch/arm/mach-at91/include/mach/at91_spi.h b/arch/arm/mach-at91/include/mach/at91_spi.h
-deleted file mode 100644
-index 2f6ba0c..0000000
---- a/arch/arm/mach-at91/include/mach/at91_spi.h
-+++ /dev/null
-@@ -1,81 +0,0 @@
--/*
-- * arch/arm/mach-at91/include/mach/at91_spi.h
-- *
-- * Copyright (C) 2005 Ivan Kokshaysky
-- * Copyright (C) SAN People
-- *
-- * Serial Peripheral Interface (SPI) registers.
-- * Based on AT91RM9200 datasheet revision E.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- */
--
--#ifndef AT91_SPI_H
--#define AT91_SPI_H
--
--#define AT91_SPI_CR 0x00 /* Control Register */
--#define AT91_SPI_SPIEN (1 << 0) /* SPI Enable */
--#define AT91_SPI_SPIDIS (1 << 1) /* SPI Disable */
--#define AT91_SPI_SWRST (1 << 7) /* SPI Software Reset */
--#define AT91_SPI_LASTXFER (1 << 24) /* Last Transfer [SAM9261 only] */
--
--#define AT91_SPI_MR 0x04 /* Mode Register */
--#define AT91_SPI_MSTR (1 << 0) /* Master/Slave Mode */
--#define AT91_SPI_PS (1 << 1) /* Peripheral Select */
--#define AT91_SPI_PS_FIXED (0 << 1)
--#define AT91_SPI_PS_VARIABLE (1 << 1)
--#define AT91_SPI_PCSDEC (1 << 2) /* Chip Select Decode */
--#define AT91_SPI_DIV32 (1 << 3) /* Clock Selection [AT91RM9200 only] */
--#define AT91_SPI_MODFDIS (1 << 4) /* Mode Fault Detection */
--#define AT91_SPI_LLB (1 << 7) /* Local Loopback Enable */
--#define AT91_SPI_PCS (0xf << 16) /* Peripheral Chip Select */
--#define AT91_SPI_DLYBCS (0xff << 24) /* Delay Between Chip Selects */
--
--#define AT91_SPI_RDR 0x08 /* Receive Data Register */
--#define AT91_SPI_RD (0xffff << 0) /* Receive Data */
--#define AT91_SPI_PCS (0xf << 16) /* Peripheral Chip Select */
--
--#define AT91_SPI_TDR 0x0c /* Transmit Data Register */
--#define AT91_SPI_TD (0xffff << 0) /* Transmit Data */
--#define AT91_SPI_PCS (0xf << 16) /* Peripheral Chip Select */
--#define AT91_SPI_LASTXFER (1 << 24) /* Last Transfer [SAM9261 only] */
--
--#define AT91_SPI_SR 0x10 /* Status Register */
--#define AT91_SPI_RDRF (1 << 0) /* Receive Data Register Full */
--#define AT91_SPI_TDRE (1 << 1) /* Transmit Data Register Full */
--#define AT91_SPI_MODF (1 << 2) /* Mode Fault Error */
--#define AT91_SPI_OVRES (1 << 3) /* Overrun Error Status */
--#define AT91_SPI_ENDRX (1 << 4) /* End of RX buffer */
--#define AT91_SPI_ENDTX (1 << 5) /* End of TX buffer */
--#define AT91_SPI_RXBUFF (1 << 6) /* RX Buffer Full */
--#define AT91_SPI_TXBUFE (1 << 7) /* TX Buffer Empty */
--#define AT91_SPI_NSSR (1 << 8) /* NSS Rising [SAM9261 only] */
--#define AT91_SPI_TXEMPTY (1 << 9) /* Transmission Register Empty [SAM9261 only] */
--#define AT91_SPI_SPIENS (1 << 16) /* SPI Enable Status */
--
--#define AT91_SPI_IER 0x14 /* Interrupt Enable Register */
--#define AT91_SPI_IDR 0x18 /* Interrupt Disable Register */
--#define AT91_SPI_IMR 0x1c /* Interrupt Mask Register */
--
--#define AT91_SPI_CSR(n) (0x30 + ((n) * 4)) /* Chip Select Registers 0-3 */
--#define AT91_SPI_CPOL (1 << 0) /* Clock Polarity */
--#define AT91_SPI_NCPHA (1 << 1) /* Clock Phase */
--#define AT91_SPI_CSAAT (1 << 3) /* Chip Select Active After Transfer [SAM9261 only] */
--#define AT91_SPI_BITS (0xf << 4) /* Bits Per Transfer */
--#define AT91_SPI_BITS_8 (0 << 4)
--#define AT91_SPI_BITS_9 (1 << 4)
--#define AT91_SPI_BITS_10 (2 << 4)
--#define AT91_SPI_BITS_11 (3 << 4)
--#define AT91_SPI_BITS_12 (4 << 4)
--#define AT91_SPI_BITS_13 (5 << 4)
--#define AT91_SPI_BITS_14 (6 << 4)
--#define AT91_SPI_BITS_15 (7 << 4)
--#define AT91_SPI_BITS_16 (8 << 4)
--#define AT91_SPI_SCBR (0xff << 8) /* Serial Clock Baud Rate */
--#define AT91_SPI_DLYBS (0xff << 16) /* Delay before SPCK */
--#define AT91_SPI_DLYBCT (0xff << 24) /* Delay between Consecutive Transfers */
--
--#endif
-diff --git a/arch/arm/mach-at91/include/mach/at91_ssc.h b/arch/arm/mach-at91/include/mach/at91_ssc.h
-deleted file mode 100644
-index a81114c..0000000
---- a/arch/arm/mach-at91/include/mach/at91_ssc.h
-+++ /dev/null
-@@ -1,106 +0,0 @@
--/*
-- * arch/arm/mach-at91/include/mach/at91_ssc.h
-- *
-- * Copyright (C) SAN People
-- *
-- * Serial Synchronous Controller (SSC) registers.
-- * Based on AT91RM9200 datasheet revision E.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- */
--
--#ifndef AT91_SSC_H
--#define AT91_SSC_H
--
--#define AT91_SSC_CR 0x00 /* Control Register */
--#define AT91_SSC_RXEN (1 << 0) /* Receive Enable */
--#define AT91_SSC_RXDIS (1 << 1) /* Receive Disable */
--#define AT91_SSC_TXEN (1 << 8) /* Transmit Enable */
--#define AT91_SSC_TXDIS (1 << 9) /* Transmit Disable */
--#define AT91_SSC_SWRST (1 << 15) /* Software Reset */
--
--#define AT91_SSC_CMR 0x04 /* Clock Mode Register */
--#define AT91_SSC_CMR_DIV (0xfff << 0) /* Clock Divider */
--
--#define AT91_SSC_RCMR 0x10 /* Receive Clock Mode Register */
--#define AT91_SSC_CKS (3 << 0) /* Clock Selection */
--#define AT91_SSC_CKS_DIV (0 << 0)
--#define AT91_SSC_CKS_CLOCK (1 << 0)
--#define AT91_SSC_CKS_PIN (2 << 0)
--#define AT91_SSC_CKO (7 << 2) /* Clock Output Mode Selection */
--#define AT91_SSC_CKO_NONE (0 << 2)
--#define AT91_SSC_CKO_CONTINUOUS (1 << 2)
--#define AT91_SSC_CKI (1 << 5) /* Clock Inversion */
--#define AT91_SSC_CKI_FALLING (0 << 5)
--#define AT91_SSC_CK_RISING (1 << 5)
--#define AT91_SSC_CKG (1 << 6) /* Receive Clock Gating Selection [AT91SAM9261 only] */
--#define AT91_SSC_CKG_NONE (0 << 6)
--#define AT91_SSC_CKG_RFLOW (1 << 6)
--#define AT91_SSC_CKG_RFHIGH (2 << 6)
--#define AT91_SSC_START (0xf << 8) /* Start Selection */
--#define AT91_SSC_START_CONTINUOUS (0 << 8)
--#define AT91_SSC_START_TX_RX (1 << 8)
--#define AT91_SSC_START_LOW_RF (2 << 8)
--#define AT91_SSC_START_HIGH_RF (3 << 8)
--#define AT91_SSC_START_FALLING_RF (4 << 8)
--#define AT91_SSC_START_RISING_RF (5 << 8)
--#define AT91_SSC_START_LEVEL_RF (6 << 8)
--#define AT91_SSC_START_EDGE_RF (7 << 8)
--#define AT91_SSC_STOP (1 << 12) /* Receive Stop Selection [AT91SAM9261 only] */
--#define AT91_SSC_STTDLY (0xff << 16) /* Start Delay */
--#define AT91_SSC_PERIOD (0xff << 24) /* Period Divider Selection */
--
--#define AT91_SSC_RFMR 0x14 /* Receive Frame Mode Register */
--#define AT91_SSC_DATALEN (0x1f << 0) /* Data Length */
--#define AT91_SSC_LOOP (1 << 5) /* Loop Mode */
--#define AT91_SSC_MSBF (1 << 7) /* Most Significant Bit First */
--#define AT91_SSC_DATNB (0xf << 8) /* Data Number per Frame */
--#define AT91_SSC_FSLEN (0xf << 16) /* Frame Sync Length */
--#define AT91_SSC_FSOS (7 << 20) /* Frame Sync Output Selection */
--#define AT91_SSC_FSOS_NONE (0 << 20)
--#define AT91_SSC_FSOS_NEGATIVE (1 << 20)
--#define AT91_SSC_FSOS_POSITIVE (2 << 20)
--#define AT91_SSC_FSOS_LOW (3 << 20)
--#define AT91_SSC_FSOS_HIGH (4 << 20)
--#define AT91_SSC_FSOS_TOGGLE (5 << 20)
--#define AT91_SSC_FSEDGE (1 << 24) /* Frame Sync Edge Detection */
--#define AT91_SSC_FSEDGE_POSITIVE (0 << 24)
--#define AT91_SSC_FSEDGE_NEGATIVE (1 << 24)
--
--#define AT91_SSC_TCMR 0x18 /* Transmit Clock Mode Register */
--#define AT91_SSC_TFMR 0x1c /* Transmit Fram Mode Register */
--#define AT91_SSC_DATDEF (1 << 5) /* Data Default Value */
--#define AT91_SSC_FSDEN (1 << 23) /* Frame Sync Data Enable */
--
--#define AT91_SSC_RHR 0x20 /* Receive Holding Register */
--#define AT91_SSC_THR 0x24 /* Transmit Holding Register */
--#define AT91_SSC_RSHR 0x30 /* Receive Sync Holding Register */
--#define AT91_SSC_TSHR 0x34 /* Transmit Sync Holding Register */
--
--#define AT91_SSC_RC0R 0x38 /* Receive Compare 0 Register [AT91SAM9261 only] */
--#define AT91_SSC_RC1R 0x3c /* Receive Compare 1 Register [AT91SAM9261 only] */
--
--#define AT91_SSC_SR 0x40 /* Status Register */
--#define AT91_SSC_TXRDY (1 << 0) /* Transmit Ready */
--#define AT91_SSC_TXEMPTY (1 << 1) /* Transmit Empty */
--#define AT91_SSC_ENDTX (1 << 2) /* End of Transmission */
--#define AT91_SSC_TXBUFE (1 << 3) /* Transmit Buffer Empty */
--#define AT91_SSC_RXRDY (1 << 4) /* Receive Ready */
--#define AT91_SSC_OVRUN (1 << 5) /* Receive Overrun */
--#define AT91_SSC_ENDRX (1 << 6) /* End of Reception */
--#define AT91_SSC_RXBUFF (1 << 7) /* Receive Buffer Full */
--#define AT91_SSC_CP0 (1 << 8) /* Compare 0 [AT91SAM9261 only] */
--#define AT91_SSC_CP1 (1 << 9) /* Compare 1 [AT91SAM9261 only] */
--#define AT91_SSC_TXSYN (1 << 10) /* Transmit Sync */
--#define AT91_SSC_RXSYN (1 << 11) /* Receive Sync */
--#define AT91_SSC_TXENA (1 << 16) /* Transmit Enable */
--#define AT91_SSC_RXENA (1 << 17) /* Receive Enable */
--
--#define AT91_SSC_IER 0x44 /* Interrupt Enable Register */
--#define AT91_SSC_IDR 0x48 /* Interrupt Disable Register */
--#define AT91_SSC_IMR 0x4c /* Interrupt Mask Register */
--
--#endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 27948a35ec0d89d516dad5eca85e2bd27109483e Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Thu, 31 May 2012 17:26:05 +0200
-Subject: ARM: at91: fix at91_aic_write macro
-
-commit f25b00be60ab3865308a89437af66b277b04f53e upstream.
-
-Fix at91_aic_write macro to avoid potential issues.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/include/mach/at91_aic.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-at91/include/mach/at91_aic.h b/arch/arm/mach-at91/include/mach/at91_aic.h
-index 3045781..c1413ed 100644
---- a/arch/arm/mach-at91/include/mach/at91_aic.h
-+++ b/arch/arm/mach-at91/include/mach/at91_aic.h
-@@ -23,7 +23,7 @@ extern void __iomem *at91_aic_base;
- __raw_readl(at91_aic_base + field)
-
- #define at91_aic_write(field, value) \
-- __raw_writel(value, at91_aic_base + field);
-+ __raw_writel(value, at91_aic_base + field)
- #else
- .extern at91_aic_base
- #endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b6a6d64d8d141bd4f88453c6586dfe67813db266 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Wed, 9 May 2012 10:49:41 +0200
-Subject: USB: ohci-at91: use resource_size() for memory/io resource length
-
-commit 7a82f612fa3aadb5676184ae202903f5a42e4f4a upstream.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/usb/host/ohci-at91.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
-index 55d3d64..84901c3 100644
---- a/drivers/usb/host/ohci-at91.c
-+++ b/drivers/usb/host/ohci-at91.c
-@@ -129,7 +129,7 @@ static int __devinit usb_hcd_at91_probe(const struct hc_driver *driver,
- if (!hcd)
- return -ENOMEM;
- hcd->rsrc_start = pdev->resource[0].start;
-- hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
-+ hcd->rsrc_len = resource_size(&pdev->resource[0]);
-
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
- pr_debug("request_mem_region failed\n");
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 4bd0bf333245414643729d864fdea1023984b8e9 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 9 Jul 2012 21:06:25 +0200
-Subject: ARM: at91/clock: fix PLLA overclock warning
-
-commit 2ed1f58900280f79485bbc15f781687bd9584675 upstream.
-
-Fix PLLA overclock warning in relation with datasheet numbers.
-Add new > 240 MHz and > 210 MHz SoC categories.
-
-Reported-by: Jiri Prchal <jiri.prchal@aksignal.cz>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/clock.c | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
-diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
-index de2ec6b..188c829 100644
---- a/arch/arm/mach-at91/clock.c
-+++ b/arch/arm/mach-at91/clock.c
-@@ -63,6 +63,12 @@ EXPORT_SYMBOL_GPL(at91_pmc_base);
-
- #define cpu_has_300M_plla() (cpu_is_at91sam9g10())
-
-+#define cpu_has_240M_plla() (cpu_is_at91sam9261() \
-+ || cpu_is_at91sam9263() \
-+ || cpu_is_at91sam9rl())
-+
-+#define cpu_has_210M_plla() (cpu_is_at91sam9260())
-+
- #define cpu_has_pllb() (!(cpu_is_at91sam9rl() \
- || cpu_is_at91sam9g45() \
- || cpu_is_at91sam9x5() \
-@@ -706,6 +712,12 @@ static int __init at91_pmc_init(unsigned long main_clock)
- } else if (cpu_has_800M_plla()) {
- if (plla.rate_hz > 800000000)
- pll_overclock = true;
-+ } else if (cpu_has_240M_plla()) {
-+ if (plla.rate_hz > 240000000)
-+ pll_overclock = true;
-+ } else if (cpu_has_210M_plla()) {
-+ if (plla.rate_hz > 210000000)
-+ pll_overclock = true;
- } else {
- if (plla.rate_hz > 209000000)
- pll_overclock = true;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From d8b0eeec1568a9dd566c733e25d349704aa0ba61 Mon Sep 17 00:00:00 2001
-From: Bo Shen <voice.shen@atmel.com>
-Date: Fri, 17 Aug 2012 16:23:56 +0800
-Subject: ARM: at91/dts: remove partial parameter in at91sam9g25ek.dts
-
-commit 9e0255dd035348953e23161b7158b2ce0ddc182e upstream.
-
-Remove the malformed "mem=" bootargs parameter in at91sam9g25ek.dts
-
-Signed-off-by: Bo Shen <voice.shen@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/at91sam9g25ek.dts | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts
-index 7829a4d..96514c1 100644
---- a/arch/arm/boot/dts/at91sam9g25ek.dts
-+++ b/arch/arm/boot/dts/at91sam9g25ek.dts
-@@ -15,7 +15,7 @@
- compatible = "atmel,at91sam9g25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
-
- chosen {
-- bootargs = "128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
-+ bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
- };
-
- ahb {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 119447ac8e1e07bc8a44760ffa4a72ec55fce825 Mon Sep 17 00:00:00 2001
-From: Paul Bolle <pebolle@tiscali.nl>
-Date: Thu, 24 May 2012 16:30:29 +0200
-Subject: ARM: at91: set i2c_board_info.type to "ds1339" directly
-
-commit c1cb59fde7d1570e23d97d9b2a988760f732e28b upstream.
-
-The single element of the cpu9krea_i2c_devices array (of type struct
-i2c_board_info) has its "type" member set twice. First to "rtc-ds1307"
-(through the I2C_BOARD_INFO macro) and then directly to "ds1339". Just
-set it (once and) directly to "ds1339" instead.
-
-Signed-off-by: Paul Bolle <pebolle@tiscali.nl>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/board-cpu9krea.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
-diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
-index 69951ec..ece0d76 100644
---- a/arch/arm/mach-at91/board-cpu9krea.c
-+++ b/arch/arm/mach-at91/board-cpu9krea.c
-@@ -253,8 +253,7 @@ static struct gpio_led cpu9krea_leds[] = {
-
- static struct i2c_board_info __initdata cpu9krea_i2c_devices[] = {
- {
-- I2C_BOARD_INFO("rtc-ds1307", 0x68),
-- .type = "ds1339",
-+ I2C_BOARD_INFO("ds1339", 0x68),
- },
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 10bcd9d24bf2abbe98c2e12f83926e1aa1dc4799 Mon Sep 17 00:00:00 2001
-From: Richard Genoud <richard.genoud@gmail.com>
-Date: Fri, 22 Jun 2012 15:29:28 +0200
-Subject: ARM: at91/defconfig: Remove unaffected config option
-
-commit b4084bcf5ae833e049b0c428868de7e4efae2e4f upstream.
-
-The commit bf4289cba02b8cf770ecd7959ca70839f0dd9d3c removed the use of
-CONFIG_MTD_NAND_ATMEL_ECC_NONE and CONFIG_MTD_NAND_ATMEL_ECC_HW but the
-Kconfig file was forgotten.
-
-This patch remove those inoperative options.
-
-Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/configs/afeb9260_defconfig | 1 -
- arch/arm/configs/at91sam9263_defconfig | 1 -
- arch/arm/configs/qil-a9260_defconfig | 1 -
- arch/arm/configs/usb-a9260_defconfig | 1 -
- drivers/mtd/nand/Kconfig | 40 ----------------------------------
- 5 files changed, 44 deletions(-)
-
-diff --git a/arch/arm/configs/afeb9260_defconfig b/arch/arm/configs/afeb9260_defconfig
-index 2afdf67..c285a9d 100644
---- a/arch/arm/configs/afeb9260_defconfig
-+++ b/arch/arm/configs/afeb9260_defconfig
-@@ -39,7 +39,6 @@ CONFIG_MTD_BLOCK=y
- CONFIG_MTD_DATAFLASH=y
- CONFIG_MTD_NAND=y
- CONFIG_MTD_NAND_ATMEL=y
--CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y
- CONFIG_BLK_DEV_RAM=y
- CONFIG_BLK_DEV_RAM_SIZE=8192
- CONFIG_ATMEL_SSC=y
-diff --git a/arch/arm/configs/at91sam9263_defconfig b/arch/arm/configs/at91sam9263_defconfig
-index 1cf9626..585e7e0 100644
---- a/arch/arm/configs/at91sam9263_defconfig
-+++ b/arch/arm/configs/at91sam9263_defconfig
-@@ -61,7 +61,6 @@ CONFIG_MTD_DATAFLASH=y
- CONFIG_MTD_BLOCK2MTD=y
- CONFIG_MTD_NAND=y
- CONFIG_MTD_NAND_ATMEL=y
--CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y
- CONFIG_MTD_UBI=y
- CONFIG_MTD_UBI_GLUEBI=y
- CONFIG_BLK_DEV_LOOP=y
-diff --git a/arch/arm/configs/qil-a9260_defconfig b/arch/arm/configs/qil-a9260_defconfig
-index 9160f3b..2bb100b 100644
---- a/arch/arm/configs/qil-a9260_defconfig
-+++ b/arch/arm/configs/qil-a9260_defconfig
-@@ -50,7 +50,6 @@ CONFIG_MTD_BLOCK=y
- CONFIG_MTD_DATAFLASH=y
- CONFIG_MTD_NAND=y
- CONFIG_MTD_NAND_ATMEL=y
--CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y
- CONFIG_BLK_DEV_LOOP=y
- # CONFIG_MISC_DEVICES is not set
- CONFIG_SCSI=y
-diff --git a/arch/arm/configs/usb-a9260_defconfig b/arch/arm/configs/usb-a9260_defconfig
-index 2e39f38..a1501e1 100644
---- a/arch/arm/configs/usb-a9260_defconfig
-+++ b/arch/arm/configs/usb-a9260_defconfig
-@@ -49,7 +49,6 @@ CONFIG_MTD_BLOCK=y
- CONFIG_MTD_DATAFLASH=y
- CONFIG_MTD_NAND=y
- CONFIG_MTD_NAND_ATMEL=y
--CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y
- CONFIG_BLK_DEV_LOOP=y
- # CONFIG_MISC_DEVICES is not set
- CONFIG_SCSI=y
-diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
-index 7d17cec..0e43a3f 100644
---- a/drivers/mtd/nand/Kconfig
-+++ b/drivers/mtd/nand/Kconfig
-@@ -366,46 +366,6 @@ config MTD_NAND_ATMEL
- help
- Enables support for NAND Flash / Smart Media Card interface
- on Atmel AT91 and AVR32 processors.
--choice
-- prompt "ECC management for NAND Flash / SmartMedia on AT91 / AVR32"
-- depends on MTD_NAND_ATMEL
--
--config MTD_NAND_ATMEL_ECC_HW
-- bool "Hardware ECC"
-- depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260 || AVR32
-- help
-- Use hardware ECC instead of software ECC when the chip
-- supports it.
--
-- The hardware ECC controller is capable of single bit error
-- correction and 2-bit random detection per page.
--
-- NB : hardware and software ECC schemes are incompatible.
-- If you switch from one to another, you'll have to erase your
-- mtd partition.
--
-- If unsure, say Y
--
--config MTD_NAND_ATMEL_ECC_SOFT
-- bool "Software ECC"
-- help
-- Use software ECC.
--
-- NB : hardware and software ECC schemes are incompatible.
-- If you switch from one to another, you'll have to erase your
-- mtd partition.
--
--config MTD_NAND_ATMEL_ECC_NONE
-- bool "No ECC (testing only, DANGEROUS)"
-- depends on DEBUG_KERNEL
-- help
-- No ECC will be used.
-- It's not a good idea and it should be reserved for testing
-- purpose only.
--
-- If unsure, say N
--
--endchoice
-
- config MTD_NAND_PXA3xx
- tristate "Support for NAND flash devices on PXA3xx"
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From d735b914ddb8a98a5a79c817c04625c70158941d Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Thu, 13 Sep 2012 12:40:26 +0200
-Subject: ARM: at91: fix missing #interrupt-cells on gpio-controller
-
-commit 51ac51a6a5ab5f0aff46c4757ba4c32f3f8f7a2e upstream.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Tested-by: Bo Shen <voice.shen@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/at91sam9260.dtsi | 3 +++
- arch/arm/boot/dts/at91sam9263.dtsi | 5 +++++
- arch/arm/boot/dts/at91sam9g45.dtsi | 5 +++++
- arch/arm/boot/dts/at91sam9n12.dtsi | 4 ++++
- arch/arm/boot/dts/at91sam9x5.dtsi | 4 ++++
- 5 files changed, 21 insertions(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
-index f4605ff..eddc467 100644
---- a/arch/arm/boot/dts/at91sam9260.dtsi
-+++ b/arch/arm/boot/dts/at91sam9260.dtsi
-@@ -103,6 +103,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioB: gpio@fffff600 {
-@@ -112,6 +113,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioC: gpio@fffff800 {
-@@ -121,6 +123,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- dbgu: serial@fffff200 {
-diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
-index 0209913..d330de9 100644
---- a/arch/arm/boot/dts/at91sam9263.dtsi
-+++ b/arch/arm/boot/dts/at91sam9263.dtsi
-@@ -94,6 +94,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioB: gpio@fffff400 {
-@@ -103,6 +104,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioC: gpio@fffff600 {
-@@ -112,6 +114,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioD: gpio@fffff800 {
-@@ -121,6 +124,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioE: gpio@fffffa00 {
-@@ -130,6 +134,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- dbgu: serial@ffffee00 {
-diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
-index c804214..d1c497d 100644
---- a/arch/arm/boot/dts/at91sam9g45.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
-@@ -112,6 +112,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioB: gpio@fffff400 {
-@@ -121,6 +122,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioC: gpio@fffff600 {
-@@ -130,6 +132,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioD: gpio@fffff800 {
-@@ -139,6 +142,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioE: gpio@fffffa00 {
-@@ -148,6 +152,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- dbgu: serial@ffffee00 {
-diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
-index cb84de7..a69e89a 100644
---- a/arch/arm/boot/dts/at91sam9n12.dtsi
-+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
-@@ -107,6 +107,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioB: gpio@fffff600 {
-@@ -116,6 +117,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioC: gpio@fffff800 {
-@@ -125,6 +127,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioD: gpio@fffffa00 {
-@@ -134,6 +137,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- dbgu: serial@fffff200 {
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index dd4ed74..80a50864 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -114,6 +114,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioB: gpio@fffff600 {
-@@ -123,6 +124,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioC: gpio@fffff800 {
-@@ -132,6 +134,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- pioD: gpio@fffffa00 {
-@@ -141,6 +144,7 @@
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- dbgu: serial@fffff200 {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 232aa09c9e9aa7e03a83382ef27612bcbed93570 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Wed, 19 Sep 2012 10:02:32 +0200
-Subject: ARM: at91: missing header file for rtc-at91rm9200.c
-
-Included in commit 14070ade02cc378bc30dae383532768a94805988 upstream.
-
-Missing asm/io.h inclusion causing issue with __raw_readl and
-__raw_writel.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- drivers/rtc/rtc-at91rm9200.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
-index dc474bc..f02acb0 100644
---- a/drivers/rtc/rtc-at91rm9200.c
-+++ b/drivers/rtc/rtc-at91rm9200.c
-@@ -28,6 +28,7 @@
- #include <linux/ioctl.h>
- #include <linux/completion.h>
-
-+#include <asm/io.h>
- #include <asm/uaccess.h>
-
- #include <mach/at91_rtc.h>
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 79625ccc49e70d4cc8bb3361c98fd5ff3ad40157 Mon Sep 17 00:00:00 2001
-From: Joachim Eastwood <manabian@gmail.com>
-Date: Thu, 23 Aug 2012 18:14:54 +0200
-Subject: ASoC: atmel-ssc: include linux/io.h for raw io
-
-commit b969afc8b719bbe3f0842a694e6bf5e87f08868f upstream.
-
-Include linux/io.h for raw io operations in atmel-scc header.
-
-This fixes the following build error:
- CC [M] sound/soc/atmel/atmel_ssc_dai.o
-sound/soc/atmel/atmel_ssc_dai.c: In function 'atmel_ssc_interrupt':
-sound/soc/atmel/atmel_ssc_dai.c:171: error: implicit declaration of function '__raw_readl'
-sound/soc/atmel/atmel_ssc_dai.c: In function 'atmel_ssc_shutdown':
-sound/soc/atmel/atmel_ssc_dai.c:249: error: implicit declaration of function '__raw_writel'
-
-Signed-off-by: Joachim Eastwood <joachim.eastwood@jotron.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
----
- include/linux/atmel-ssc.h | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
-index 0602339..4eb3175 100644
---- a/include/linux/atmel-ssc.h
-+++ b/include/linux/atmel-ssc.h
-@@ -3,6 +3,7 @@
-
- #include <linux/platform_device.h>
- #include <linux/list.h>
-+#include <linux/io.h>
-
- struct ssc_device {
- struct list_head list;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 6c4b12f6fc72208ab963463412acba210d137e71 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Fri, 25 May 2012 14:11:51 +0200
-Subject: ARM: at91: aic can use fast eoi handler type
-
-commit 42a859daaf6af4d234fcf964a421666d5cca3f6a upstream.
-
-The Advanced Interrupt Controller allows us to use the fast EOI handler type.
-It lets us remove the Atmel specific workaround into arch/arm/kernel/irq.c
-used to indicate to the AIC the end of the interrupt treatment.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Signed-off-by: Will Deacon <will.deacon@arm.com>
----
- arch/arm/kernel/irq.c | 10 ----------
- arch/arm/mach-at91/gpio.c | 9 +++++----
- arch/arm/mach-at91/include/mach/irqs.h | 7 -------
- arch/arm/mach-at91/irq.c | 15 ++++++++++++---
- 4 files changed, 17 insertions(+), 24 deletions(-)
-
-diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
-index 8349d4e..16cedb4 100644
---- a/arch/arm/kernel/irq.c
-+++ b/arch/arm/kernel/irq.c
-@@ -40,13 +40,6 @@
- #include <asm/mach/irq.h>
- #include <asm/mach/time.h>
-
--/*
-- * No architecture-specific irq_finish function defined in arm/arch/irqs.h.
-- */
--#ifndef irq_finish
--#define irq_finish(irq) do { } while (0)
--#endif
--
- unsigned long irq_err_count;
-
- int arch_show_interrupts(struct seq_file *p, int prec)
-@@ -85,9 +78,6 @@ void handle_IRQ(unsigned int irq, struct pt_regs *regs)
- generic_handle_irq(irq);
- }
-
-- /* AT91 specific workaround */
-- irq_finish(irq);
--
- irq_exit();
- set_irq_regs(old_regs);
- }
-diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
-index 325837a..be42cf0 100644
---- a/arch/arm/mach-at91/gpio.c
-+++ b/arch/arm/mach-at91/gpio.c
-@@ -26,6 +26,8 @@
- #include <linux/of_irq.h>
- #include <linux/of_gpio.h>
-
-+#include <asm/mach/irq.h>
-+
- #include <mach/hardware.h>
- #include <mach/at91_pio.h>
-
-@@ -585,15 +587,14 @@ static struct irq_chip gpio_irqchip = {
-
- static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
- {
-+ struct irq_chip *chip = irq_desc_get_chip(desc);
- struct irq_data *idata = irq_desc_get_irq_data(desc);
-- struct irq_chip *chip = irq_data_get_irq_chip(idata);
- struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
- void __iomem *pio = at91_gpio->regbase;
- unsigned long isr;
- int n;
-
-- /* temporarily mask (level sensitive) parent IRQ */
-- chip->irq_ack(idata);
-+ chained_irq_enter(chip, desc);
- for (;;) {
- /* Reading ISR acks pending (edge triggered) GPIO interrupts.
- * When there none are pending, we're finished unless we need
-@@ -614,7 +615,7 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
- n = find_next_bit(&isr, BITS_PER_LONG, n + 1);
- }
- }
-- chip->irq_unmask(idata);
-+ chained_irq_exit(chip, desc);
- /* now it may re-trigger */
- }
-
-diff --git a/arch/arm/mach-at91/include/mach/irqs.h b/arch/arm/mach-at91/include/mach/irqs.h
-index ac8b7df..2d510ee 100644
---- a/arch/arm/mach-at91/include/mach/irqs.h
-+++ b/arch/arm/mach-at91/include/mach/irqs.h
-@@ -28,13 +28,6 @@
-
-
- /*
-- * Acknowledge interrupt with AIC after interrupt has been handled.
-- * (by kernel/irq.c)
-- */
--#define irq_finish(irq) do { at91_aic_write(AT91_AIC_EOICR, 0); } while (0)
--
--
--/*
- * IRQ interrupt symbols are the AT91xxx_ID_* symbols
- * for IRQs handled directly through the AIC, or else the AT91_PIN_*
- * symbols in gpio.h for ones handled indirectly as GPIOs.
-diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
-index cfcfcbe..2d5d4c8 100644
---- a/arch/arm/mach-at91/irq.c
-+++ b/arch/arm/mach-at91/irq.c
-@@ -55,6 +55,15 @@ static void at91_aic_unmask_irq(struct irq_data *d)
- at91_aic_write(AT91_AIC_IECR, 1 << d->hwirq);
- }
-
-+static void at91_aic_eoi(struct irq_data *d)
-+{
-+ /*
-+ * Mark end-of-interrupt on AIC, the controller doesn't care about
-+ * the value written. Moreover it's a write-only register.
-+ */
-+ at91_aic_write(AT91_AIC_EOICR, 0);
-+}
-+
- unsigned int at91_extern_irq;
-
- #define is_extern_irq(hwirq) ((1 << (hwirq)) & at91_extern_irq)
-@@ -128,11 +137,11 @@ void at91_irq_resume(void)
-
- static struct irq_chip at91_aic_chip = {
- .name = "AIC",
-- .irq_ack = at91_aic_mask_irq,
- .irq_mask = at91_aic_mask_irq,
- .irq_unmask = at91_aic_unmask_irq,
- .irq_set_type = at91_aic_set_type,
- .irq_set_wake = at91_aic_set_wake,
-+ .irq_eoi = at91_aic_eoi,
- };
-
- static void __init at91_aic_hw_init(unsigned int spu_vector)
-@@ -171,7 +180,7 @@ static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq,
- /* Active Low interrupt, without priority */
- at91_aic_write(AT91_AIC_SMR(hw), AT91_AIC_SRCTYPE_LOW);
-
-- irq_set_chip_and_handler(virq, &at91_aic_chip, handle_level_irq);
-+ irq_set_chip_and_handler(virq, &at91_aic_chip, handle_fasteoi_irq);
- set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
-
- return 0;
-@@ -238,7 +247,7 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
- /* Active Low interrupt, with the specified priority */
- at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
-
-- irq_set_chip_and_handler(i, &at91_aic_chip, handle_level_irq);
-+ irq_set_chip_and_handler(i, &at91_aic_chip, handle_fasteoi_irq);
- set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 6d79a82baf09ee3a77f305542cf0ed0c00fa325f Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Mon, 9 Apr 2012 19:36:36 +0800
-Subject: ARM: at91: aic add dt support for external irqs
-
-commit c65739437045c351a2a0ddb834719b9d616d4d47 upstream.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- Documentation/devicetree/bindings/arm/atmel-aic.txt | 1 +
- arch/arm/boot/dts/at91sam9260.dtsi | 1 +
- arch/arm/boot/dts/at91sam9263.dtsi | 1 +
- arch/arm/boot/dts/at91sam9g45.dtsi | 1 +
- arch/arm/boot/dts/at91sam9x5.dtsi | 1 +
- arch/arm/mach-at91/at91sam9x5.c | 2 --
- arch/arm/mach-at91/irq.c | 12 ++++++++++++
- 7 files changed, 17 insertions(+), 2 deletions(-)
-
-diff --git a/Documentation/devicetree/bindings/arm/atmel-aic.txt b/Documentation/devicetree/bindings/arm/atmel-aic.txt
-index aabca4f..1953b0c 100644
---- a/Documentation/devicetree/bindings/arm/atmel-aic.txt
-+++ b/Documentation/devicetree/bindings/arm/atmel-aic.txt
-@@ -15,6 +15,7 @@ Required properties:
- Valid combinations are 1, 2, 3, 4, 8.
- Default flag for internal sources should be set to 4 (active high).
- - reg: Should contain AIC registers location and length
-+- atmel,external-irqs: u32 array of external irqs.
-
- Examples:
- /*
-diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
-index eddc467..fb86de0 100644
---- a/arch/arm/boot/dts/at91sam9260.dtsi
-+++ b/arch/arm/boot/dts/at91sam9260.dtsi
-@@ -56,6 +56,7 @@
- compatible = "atmel,at91rm9200-aic";
- interrupt-controller;
- reg = <0xfffff000 0x200>;
-+ atmel,external-irqs = <29 30 31>;
- };
-
- ramc0: ramc@ffffea00 {
-diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
-index d330de9..78b2808 100644
---- a/arch/arm/boot/dts/at91sam9263.dtsi
-+++ b/arch/arm/boot/dts/at91sam9263.dtsi
-@@ -52,6 +52,7 @@
- compatible = "atmel,at91rm9200-aic";
- interrupt-controller;
- reg = <0xfffff000 0x200>;
-+ atmel,external-irqs = <30 31>;
- };
-
- pmc: pmc@fffffc00 {
-diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
-index d1c497d..779ffca 100644
---- a/arch/arm/boot/dts/at91sam9g45.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
-@@ -57,6 +57,7 @@
- compatible = "atmel,at91rm9200-aic";
- interrupt-controller;
- reg = <0xfffff000 0x200>;
-+ atmel,external-irqs = <31>;
- };
-
- ramc0: ramc@ffffe400 {
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index 80a50864..170b6f8 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -55,6 +55,7 @@
- compatible = "atmel,at91rm9200-aic";
- interrupt-controller;
- reg = <0xfffff000 0x200>;
-+ atmel,external-irqs = <31>;
- };
-
- ramc0: ramc@ffffe800 {
-diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
-index 13c8cae..dce3ff3 100644
---- a/arch/arm/mach-at91/at91sam9x5.c
-+++ b/arch/arm/mach-at91/at91sam9x5.c
-@@ -306,8 +306,6 @@ static void __init at91sam9x5_map_io(void)
-
- void __init at91sam9x5_initialize(void)
- {
-- at91_extern_irq = (1 << AT91SAM9X5_ID_IRQ0);
--
- /* Register GPIO subsystem (using DT) */
- at91_gpio_init(NULL, 0);
- }
-diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
-index 2d5d4c8..df8605f 100644
---- a/arch/arm/mach-at91/irq.c
-+++ b/arch/arm/mach-at91/irq.c
-@@ -194,6 +194,10 @@ static struct irq_domain_ops at91_aic_irq_ops = {
- int __init at91_aic_of_init(struct device_node *node,
- struct device_node *parent)
- {
-+ struct property *prop;
-+ const __be32 *p;
-+ u32 val;
-+
- at91_aic_base = of_iomap(node, 0);
- at91_aic_np = node;
-
-@@ -202,6 +206,14 @@ int __init at91_aic_of_init(struct device_node *node,
- if (!at91_aic_domain)
- panic("Unable to add AIC irq domain (DT)\n");
-
-+ at91_extern_irq = 0;
-+ of_property_for_each_u32(node, "atmel,external-irqs", prop, p, val) {
-+ if (val > 31)
-+ pr_warn("AIC: external irq %d > 31 skip it\n", val);
-+ else
-+ at91_extern_irq |= (1 << val);
-+ }
-+
- irq_set_default_host(at91_aic_domain);
-
- at91_aic_hw_init(NR_AIC_IRQS);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 70df58d418b354d8e1ad6597463da2b3d32148c3 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Wed, 20 Jun 2012 16:13:30 +0200
-Subject: ARM: at91: add of irq priorities support
-
-commit f8a073ee378b9893aee0749c3868a6ecfb0c1636 upstream.
-
-Add a third cell to define irq priority.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Reviewed-by: Rob Herring <rob.herring@calxeda.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-
-Conflicts:
- arch/arm/boot/dts/at91sam9260.dtsi
- arch/arm/boot/dts/at91sam9g45.dtsi
- arch/arm/boot/dts/at91sam9x5.dtsi
----
- .../devicetree/bindings/arm/atmel-aic.txt | 8 +++--
- arch/arm/boot/dts/at91sam9260.dtsi | 34 ++++++++++----------
- arch/arm/boot/dts/at91sam9263.dtsi | 30 +++++++++---------
- arch/arm/boot/dts/at91sam9g45.dtsi | 36 +++++++++++-----------
- arch/arm/boot/dts/at91sam9n12.dtsi | 30 +++++++++---------
- arch/arm/boot/dts/at91sam9x5.dtsi | 36 +++++++++++-----------
- arch/arm/mach-at91/include/mach/at91_aic.h | 3 ++
- arch/arm/mach-at91/irq.c | 34 ++++++++++++++++++--
- 8 files changed, 122 insertions(+), 89 deletions(-)
-
-diff --git a/Documentation/devicetree/bindings/arm/atmel-aic.txt b/Documentation/devicetree/bindings/arm/atmel-aic.txt
-index 1953b0c..19078bf 100644
---- a/Documentation/devicetree/bindings/arm/atmel-aic.txt
-+++ b/Documentation/devicetree/bindings/arm/atmel-aic.txt
-@@ -4,7 +4,7 @@ Required properties:
- - compatible: Should be "atmel,<chip>-aic"
- - interrupt-controller: Identifies the node as an interrupt controller.
- - interrupt-parent: For single AIC system, it is an empty property.
--- #interrupt-cells: The number of cells to define the interrupts. It sould be 2.
-+- #interrupt-cells: The number of cells to define the interrupts. It sould be 3.
- The first cell is the IRQ number (aka "Peripheral IDentifier" on datasheet).
- The second cell is used to specify flags:
- bits[3:0] trigger type and level flags:
-@@ -14,6 +14,8 @@ Required properties:
- 8 = active low level-sensitive.
- Valid combinations are 1, 2, 3, 4, 8.
- Default flag for internal sources should be set to 4 (active high).
-+ The third cell is used to specify the irq priority from 0 (lowest) to 7
-+ (highest).
- - reg: Should contain AIC registers location and length
- - atmel,external-irqs: u32 array of external irqs.
-
-@@ -25,7 +27,7 @@ Examples:
- compatible = "atmel,at91rm9200-aic";
- interrupt-controller;
- interrupt-parent;
-- #interrupt-cells = <2>;
-+ #interrupt-cells = <3>;
- reg = <0xfffff000 0x200>;
- };
-
-@@ -35,5 +37,5 @@ Examples:
- dma: dma-controller@ffffec00 {
- compatible = "atmel,at91sam9g45-dma";
- reg = <0xffffec00 0x200>;
-- interrupts = <21 4>;
-+ interrupts = <21 4 5>;
- };
-diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
-index fb86de0..12df8ca 100644
---- a/arch/arm/boot/dts/at91sam9260.dtsi
-+++ b/arch/arm/boot/dts/at91sam9260.dtsi
-@@ -52,7 +52,7 @@
- ranges;
-
- aic: interrupt-controller@fffff000 {
-- #interrupt-cells = <2>;
-+ #interrupt-cells = <3>;
- compatible = "atmel,at91rm9200-aic";
- interrupt-controller;
- reg = <0xfffff000 0x200>;
-@@ -82,25 +82,25 @@
- pit: timer@fffffd30 {
- compatible = "atmel,at91sam9260-pit";
- reg = <0xfffffd30 0xf>;
-- interrupts = <1 4>;
-+ interrupts = <1 4 7>;
- };
-
- tcb0: timer@fffa0000 {
- compatible = "atmel,at91rm9200-tcb";
- reg = <0xfffa0000 0x100>;
-- interrupts = <17 4 18 4 19 4>;
-+ interrupts = <17 4 0 18 4 0 19 4 0>;
- };
-
- tcb1: timer@fffdc000 {
- compatible = "atmel,at91rm9200-tcb";
- reg = <0xfffdc000 0x100>;
-- interrupts = <26 4 27 4 28 4>;
-+ interrupts = <26 4 0 27 4 0 28 4 0>;
- };
-
- pioA: gpio@fffff400 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x100>;
-- interrupts = <2 4>;
-+ interrupts = <2 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -110,7 +110,7 @@
- pioB: gpio@fffff600 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff600 0x100>;
-- interrupts = <3 4>;
-+ interrupts = <3 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -120,7 +120,7 @@
- pioC: gpio@fffff800 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff800 0x100>;
-- interrupts = <4 4>;
-+ interrupts = <4 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -130,14 +130,14 @@
- dbgu: serial@fffff200 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffff200 0x200>;
-- interrupts = <1 4>;
-+ interrupts = <1 4 7>;
- status = "disabled";
- };
-
- usart0: serial@fffb0000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffb0000 0x200>;
-- interrupts = <6 4>;
-+ interrupts = <6 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -146,7 +146,7 @@
- usart1: serial@fffb4000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffb4000 0x200>;
-- interrupts = <7 4>;
-+ interrupts = <7 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -155,7 +155,7 @@
- usart2: serial@fffb8000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffb8000 0x200>;
-- interrupts = <8 4>;
-+ interrupts = <8 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -164,7 +164,7 @@
- usart3: serial@fffd0000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffd0000 0x200>;
-- interrupts = <23 4>;
-+ interrupts = <23 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -173,7 +173,7 @@
- usart4: serial@fffd4000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffd4000 0x200>;
-- interrupts = <24 4>;
-+ interrupts = <24 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -182,7 +182,7 @@
- usart5: serial@fffd8000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffd8000 0x200>;
-- interrupts = <25 4>;
-+ interrupts = <25 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -191,14 +191,14 @@
- macb0: ethernet@fffc4000 {
- compatible = "cdns,at32ap7000-macb", "cdns,macb";
- reg = <0xfffc4000 0x100>;
-- interrupts = <21 4>;
-+ interrupts = <21 4 3>;
- status = "disabled";
- };
-
- usb1: gadget@fffa4000 {
- compatible = "atmel,at91rm9200-udc";
- reg = <0xfffa4000 0x4000>;
-- interrupts = <10 4>;
-+ interrupts = <10 4 2>;
- status = "disabled";
- };
- };
-@@ -222,7 +222,7 @@
- usb0: ohci@00500000 {
- compatible = "atmel,at91rm9200-ohci", "usb-ohci";
- reg = <0x00500000 0x100000>;
-- interrupts = <20 4>;
-+ interrupts = <20 4 2>;
- status = "disabled";
- };
- };
-diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
-index 78b2808..195019b 100644
---- a/arch/arm/boot/dts/at91sam9263.dtsi
-+++ b/arch/arm/boot/dts/at91sam9263.dtsi
-@@ -48,7 +48,7 @@
- ranges;
-
- aic: interrupt-controller@fffff000 {
-- #interrupt-cells = <2>;
-+ #interrupt-cells = <3>;
- compatible = "atmel,at91rm9200-aic";
- interrupt-controller;
- reg = <0xfffff000 0x200>;
-@@ -69,13 +69,13 @@
- pit: timer@fffffd30 {
- compatible = "atmel,at91sam9260-pit";
- reg = <0xfffffd30 0xf>;
-- interrupts = <1 4>;
-+ interrupts = <1 4 7>;
- };
-
- tcb0: timer@fff7c000 {
- compatible = "atmel,at91rm9200-tcb";
- reg = <0xfff7c000 0x100>;
-- interrupts = <19 4>;
-+ interrupts = <19 4 0>;
- };
-
- rstc@fffffd00 {
-@@ -91,7 +91,7 @@
- pioA: gpio@fffff200 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff200 0x100>;
-- interrupts = <2 4>;
-+ interrupts = <2 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -101,7 +101,7 @@
- pioB: gpio@fffff400 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x100>;
-- interrupts = <3 4>;
-+ interrupts = <3 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -111,7 +111,7 @@
- pioC: gpio@fffff600 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff600 0x100>;
-- interrupts = <4 4>;
-+ interrupts = <4 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -121,7 +121,7 @@
- pioD: gpio@fffff800 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff800 0x100>;
-- interrupts = <4 4>;
-+ interrupts = <4 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -131,7 +131,7 @@
- pioE: gpio@fffffa00 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffffa00 0x100>;
-- interrupts = <4 4>;
-+ interrupts = <4 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -141,14 +141,14 @@
- dbgu: serial@ffffee00 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xffffee00 0x200>;
-- interrupts = <1 4>;
-+ interrupts = <1 4 7>;
- status = "disabled";
- };
-
- usart0: serial@fff8c000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfff8c000 0x200>;
-- interrupts = <7 4>;
-+ interrupts = <7 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -157,7 +157,7 @@
- usart1: serial@fff90000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfff90000 0x200>;
-- interrupts = <8 4>;
-+ interrupts = <8 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -166,7 +166,7 @@
- usart2: serial@fff94000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfff94000 0x200>;
-- interrupts = <9 4>;
-+ interrupts = <9 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -175,14 +175,14 @@
- macb0: ethernet@fffbc000 {
- compatible = "cdns,at32ap7000-macb", "cdns,macb";
- reg = <0xfffbc000 0x100>;
-- interrupts = <21 4>;
-+ interrupts = <21 4 3>;
- status = "disabled";
- };
-
- usb1: gadget@fff78000 {
- compatible = "atmel,at91rm9200-udc";
- reg = <0xfff78000 0x4000>;
-- interrupts = <24 4>;
-+ interrupts = <24 4 2>;
- status = "disabled";
- };
- };
-@@ -206,7 +206,7 @@
- usb0: ohci@00a00000 {
- compatible = "atmel,at91rm9200-ohci", "usb-ohci";
- reg = <0x00a00000 0x100000>;
-- interrupts = <29 4>;
-+ interrupts = <29 4 2>;
- status = "disabled";
- };
- };
-diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
-index 779ffca..6a3ed54 100644
---- a/arch/arm/boot/dts/at91sam9g45.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
-@@ -53,7 +53,7 @@
- ranges;
-
- aic: interrupt-controller@fffff000 {
-- #interrupt-cells = <2>;
-+ #interrupt-cells = <3>;
- compatible = "atmel,at91rm9200-aic";
- interrupt-controller;
- reg = <0xfffff000 0x200>;
-@@ -79,7 +79,7 @@
- pit: timer@fffffd30 {
- compatible = "atmel,at91sam9260-pit";
- reg = <0xfffffd30 0xf>;
-- interrupts = <1 4>;
-+ interrupts = <1 4 7>;
- };
-
-
-@@ -91,25 +91,25 @@
- tcb0: timer@fff7c000 {
- compatible = "atmel,at91rm9200-tcb";
- reg = <0xfff7c000 0x100>;
-- interrupts = <18 4>;
-+ interrupts = <18 4 0>;
- };
-
- tcb1: timer@fffd4000 {
- compatible = "atmel,at91rm9200-tcb";
- reg = <0xfffd4000 0x100>;
-- interrupts = <18 4>;
-+ interrupts = <18 4 0>;
- };
-
- dma: dma-controller@ffffec00 {
- compatible = "atmel,at91sam9g45-dma";
- reg = <0xffffec00 0x200>;
-- interrupts = <21 4>;
-+ interrupts = <21 4 0>;
- };
-
- pioA: gpio@fffff200 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff200 0x100>;
-- interrupts = <2 4>;
-+ interrupts = <2 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -119,7 +119,7 @@
- pioB: gpio@fffff400 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x100>;
-- interrupts = <3 4>;
-+ interrupts = <3 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -129,7 +129,7 @@
- pioC: gpio@fffff600 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff600 0x100>;
-- interrupts = <4 4>;
-+ interrupts = <4 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -139,7 +139,7 @@
- pioD: gpio@fffff800 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff800 0x100>;
-- interrupts = <5 4>;
-+ interrupts = <5 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -149,7 +149,7 @@
- pioE: gpio@fffffa00 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffffa00 0x100>;
-- interrupts = <5 4>;
-+ interrupts = <5 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -159,14 +159,14 @@
- dbgu: serial@ffffee00 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xffffee00 0x200>;
-- interrupts = <1 4>;
-+ interrupts = <1 4 7>;
- status = "disabled";
- };
-
- usart0: serial@fff8c000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfff8c000 0x200>;
-- interrupts = <7 4>;
-+ interrupts = <7 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -175,7 +175,7 @@
- usart1: serial@fff90000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfff90000 0x200>;
-- interrupts = <8 4>;
-+ interrupts = <8 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -184,7 +184,7 @@
- usart2: serial@fff94000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfff94000 0x200>;
-- interrupts = <9 4>;
-+ interrupts = <9 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -193,7 +193,7 @@
- usart3: serial@fff98000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfff98000 0x200>;
-- interrupts = <10 4>;
-+ interrupts = <10 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -202,7 +202,7 @@
- macb0: ethernet@fffbc000 {
- compatible = "cdns,at32ap7000-macb", "cdns,macb";
- reg = <0xfffbc000 0x100>;
-- interrupts = <25 4>;
-+ interrupts = <25 4 3>;
- status = "disabled";
- };
- };
-@@ -226,14 +226,14 @@
- usb0: ohci@00700000 {
- compatible = "atmel,at91rm9200-ohci", "usb-ohci";
- reg = <0x00700000 0x100000>;
-- interrupts = <22 4>;
-+ interrupts = <22 4 2>;
- status = "disabled";
- };
-
- usb1: ehci@00800000 {
- compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
- reg = <0x00800000 0x100000>;
-- interrupts = <22 4>;
-+ interrupts = <22 4 2>;
- status = "disabled";
- };
- };
-diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
-index a69e89a..ef9336a 100644
---- a/arch/arm/boot/dts/at91sam9n12.dtsi
-+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
-@@ -50,7 +50,7 @@
- ranges;
-
- aic: interrupt-controller@fffff000 {
-- #interrupt-cells = <2>;
-+ #interrupt-cells = <3>;
- compatible = "atmel,at91rm9200-aic";
- interrupt-controller;
- reg = <0xfffff000 0x200>;
-@@ -74,7 +74,7 @@
- pit: timer@fffffe30 {
- compatible = "atmel,at91sam9260-pit";
- reg = <0xfffffe30 0xf>;
-- interrupts = <1 4>;
-+ interrupts = <1 4 7>;
- };
-
- shdwc@fffffe10 {
-@@ -85,25 +85,25 @@
- tcb0: timer@f8008000 {
- compatible = "atmel,at91sam9x5-tcb";
- reg = <0xf8008000 0x100>;
-- interrupts = <17 4>;
-+ interrupts = <17 4 0>;
- };
-
- tcb1: timer@f800c000 {
- compatible = "atmel,at91sam9x5-tcb";
- reg = <0xf800c000 0x100>;
-- interrupts = <17 4>;
-+ interrupts = <17 4 0>;
- };
-
- dma: dma-controller@ffffec00 {
- compatible = "atmel,at91sam9g45-dma";
- reg = <0xffffec00 0x200>;
-- interrupts = <20 4>;
-+ interrupts = <20 4 0>;
- };
-
- pioA: gpio@fffff400 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x100>;
-- interrupts = <2 4>;
-+ interrupts = <2 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -113,7 +113,7 @@
- pioB: gpio@fffff600 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff600 0x100>;
-- interrupts = <2 4>;
-+ interrupts = <2 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -123,7 +123,7 @@
- pioC: gpio@fffff800 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff800 0x100>;
-- interrupts = <3 4>;
-+ interrupts = <3 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -133,7 +133,7 @@
- pioD: gpio@fffffa00 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffffa00 0x100>;
-- interrupts = <3 4>;
-+ interrupts = <3 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -143,14 +143,14 @@
- dbgu: serial@fffff200 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffff200 0x200>;
-- interrupts = <1 4>;
-+ interrupts = <1 4 7>;
- status = "disabled";
- };
-
- usart0: serial@f801c000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xf801c000 0x4000>;
-- interrupts = <5 4>;
-+ interrupts = <5 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -159,7 +159,7 @@
- usart1: serial@f8020000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xf8020000 0x4000>;
-- interrupts = <6 4>;
-+ interrupts = <6 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -168,7 +168,7 @@
- usart2: serial@f8024000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xf8024000 0x4000>;
-- interrupts = <7 4>;
-+ interrupts = <7 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -177,7 +177,7 @@
- usart3: serial@f8028000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xf8028000 0x4000>;
-- interrupts = <8 4>;
-+ interrupts = <8 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -205,7 +205,7 @@
- usb0: ohci@00500000 {
- compatible = "atmel,at91rm9200-ohci", "usb-ohci";
- reg = <0x00500000 0x00100000>;
-- interrupts = <22 4>;
-+ interrupts = <22 4 2>;
- status = "disabled";
- };
- };
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index 170b6f8..fc38d21 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -51,7 +51,7 @@
- ranges;
-
- aic: interrupt-controller@fffff000 {
-- #interrupt-cells = <2>;
-+ #interrupt-cells = <3>;
- compatible = "atmel,at91rm9200-aic";
- interrupt-controller;
- reg = <0xfffff000 0x200>;
-@@ -81,37 +81,37 @@
- pit: timer@fffffe30 {
- compatible = "atmel,at91sam9260-pit";
- reg = <0xfffffe30 0xf>;
-- interrupts = <1 4>;
-+ interrupts = <1 4 7>;
- };
-
- tcb0: timer@f8008000 {
- compatible = "atmel,at91sam9x5-tcb";
- reg = <0xf8008000 0x100>;
-- interrupts = <17 4>;
-+ interrupts = <17 4 0>;
- };
-
- tcb1: timer@f800c000 {
- compatible = "atmel,at91sam9x5-tcb";
- reg = <0xf800c000 0x100>;
-- interrupts = <17 4>;
-+ interrupts = <17 4 0>;
- };
-
- dma0: dma-controller@ffffec00 {
- compatible = "atmel,at91sam9g45-dma";
- reg = <0xffffec00 0x200>;
-- interrupts = <20 4>;
-+ interrupts = <20 4 0>;
- };
-
- dma1: dma-controller@ffffee00 {
- compatible = "atmel,at91sam9g45-dma";
- reg = <0xffffee00 0x200>;
-- interrupts = <21 4>;
-+ interrupts = <21 4 0>;
- };
-
- pioA: gpio@fffff400 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x100>;
-- interrupts = <2 4>;
-+ interrupts = <2 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -121,7 +121,7 @@
- pioB: gpio@fffff600 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff600 0x100>;
-- interrupts = <2 4>;
-+ interrupts = <2 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -131,7 +131,7 @@
- pioC: gpio@fffff800 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff800 0x100>;
-- interrupts = <3 4>;
-+ interrupts = <3 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -141,7 +141,7 @@
- pioD: gpio@fffffa00 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffffa00 0x100>;
-- interrupts = <3 4>;
-+ interrupts = <3 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
-@@ -151,14 +151,14 @@
- dbgu: serial@fffff200 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffff200 0x200>;
-- interrupts = <1 4>;
-+ interrupts = <1 4 7>;
- status = "disabled";
- };
-
- usart0: serial@f801c000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xf801c000 0x200>;
-- interrupts = <5 4>;
-+ interrupts = <5 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -167,7 +167,7 @@
- usart1: serial@f8020000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xf8020000 0x200>;
-- interrupts = <6 4>;
-+ interrupts = <6 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -176,7 +176,7 @@
- usart2: serial@f8024000 {
- compatible = "atmel,at91sam9260-usart";
- reg = <0xf8024000 0x200>;
-- interrupts = <7 4>;
-+ interrupts = <7 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
- status = "disabled";
-@@ -185,14 +185,14 @@
- macb0: ethernet@f802c000 {
- compatible = "cdns,at32ap7000-macb", "cdns,macb";
- reg = <0xf802c000 0x100>;
-- interrupts = <24 4>;
-+ interrupts = <24 4 3>;
- status = "disabled";
- };
-
- macb1: ethernet@f8030000 {
- compatible = "cdns,at32ap7000-macb", "cdns,macb";
- reg = <0xf8030000 0x100>;
-- interrupts = <27 4>;
-+ interrupts = <27 4 3>;
- status = "disabled";
- };
- };
-@@ -215,14 +215,14 @@
- usb0: ohci@00600000 {
- compatible = "atmel,at91rm9200-ohci", "usb-ohci";
- reg = <0x00600000 0x100000>;
-- interrupts = <22 4>;
-+ interrupts = <22 4 2>;
- status = "disabled";
- };
-
- usb1: ehci@00700000 {
- compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
- reg = <0x00700000 0x100000>;
-- interrupts = <22 4>;
-+ interrupts = <22 4 2>;
- status = "disabled";
- };
- };
-diff --git a/arch/arm/mach-at91/include/mach/at91_aic.h b/arch/arm/mach-at91/include/mach/at91_aic.h
-index c1413ed..3af7272 100644
---- a/arch/arm/mach-at91/include/mach/at91_aic.h
-+++ b/arch/arm/mach-at91/include/mach/at91_aic.h
-@@ -28,6 +28,9 @@ extern void __iomem *at91_aic_base;
- .extern at91_aic_base
- #endif
-
-+#define AT91_AIC_IRQ_MIN_PRIORITY 0
-+#define AT91_AIC_IRQ_MAX_PRIORITY 7
-+
- #define AT91_AIC_SMR(n) ((n) * 4) /* Source Mode Registers 0-31 */
- #define AT91_AIC_PRIOR (7 << 0) /* Priority Level */
- #define AT91_AIC_SRCTYPE (3 << 5) /* Interrupt Source Type */
-diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
-index df8605f..db8e141 100644
---- a/arch/arm/mach-at91/irq.c
-+++ b/arch/arm/mach-at91/irq.c
-@@ -30,6 +30,7 @@
- #include <linux/of_irq.h>
- #include <linux/irqdomain.h>
- #include <linux/err.h>
-+#include <linux/slab.h>
-
- #include <mach/hardware.h>
- #include <asm/irq.h>
-@@ -42,6 +43,7 @@
- void __iomem *at91_aic_base;
- static struct irq_domain *at91_aic_domain;
- static struct device_node *at91_aic_np;
-+static unsigned int *at91_aic_irq_priorities;
-
- static void at91_aic_mask_irq(struct irq_data *d)
- {
-@@ -177,8 +179,9 @@ static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq,
- /* Put virq number in Source Vector Register */
- at91_aic_write(AT91_AIC_SVR(hw), virq);
-
-- /* Active Low interrupt, without priority */
-- at91_aic_write(AT91_AIC_SMR(hw), AT91_AIC_SRCTYPE_LOW);
-+ /* Active Low interrupt, with priority */
-+ at91_aic_write(AT91_AIC_SMR(hw),
-+ AT91_AIC_SRCTYPE_LOW | at91_aic_irq_priorities[hw]);
-
- irq_set_chip_and_handler(virq, &at91_aic_chip, handle_fasteoi_irq);
- set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
-@@ -186,9 +189,28 @@ static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq,
- return 0;
- }
-
-+static int at91_aic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
-+ const u32 *intspec, unsigned int intsize,
-+ irq_hw_number_t *out_hwirq, unsigned int *out_type)
-+{
-+ if (WARN_ON(intsize < 3))
-+ return -EINVAL;
-+ if (WARN_ON(intspec[0] >= NR_AIC_IRQS))
-+ return -EINVAL;
-+ if (WARN_ON((intspec[2] < AT91_AIC_IRQ_MIN_PRIORITY)
-+ || (intspec[2] > AT91_AIC_IRQ_MAX_PRIORITY)))
-+ return -EINVAL;
-+
-+ *out_hwirq = intspec[0];
-+ *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
-+ at91_aic_irq_priorities[*out_hwirq] = intspec[2];
-+
-+ return 0;
-+}
-+
- static struct irq_domain_ops at91_aic_irq_ops = {
- .map = at91_aic_irq_map,
-- .xlate = irq_domain_xlate_twocell,
-+ .xlate = at91_aic_irq_domain_xlate,
- };
-
- int __init at91_aic_of_init(struct device_node *node,
-@@ -198,6 +220,12 @@ int __init at91_aic_of_init(struct device_node *node,
- const __be32 *p;
- u32 val;
-
-+ at91_aic_irq_priorities = kzalloc(NR_AIC_IRQS
-+ * sizeof(*at91_aic_irq_priorities),
-+ GFP_KERNEL);
-+ if (!at91_aic_irq_priorities)
-+ return -ENOMEM;
-+
- at91_aic_base = of_iomap(node, 0);
- at91_aic_np = node;
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 3513672c75cce07bc51cc8e433b18c238490e05f Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Fri, 22 Jun 2012 11:41:34 +0200
-Subject: ARM: at91: remove static irq priorities for sam9x5
-
-commit 3a6b37134c71be1b085be7fe5234f364dc68e2de upstream.
-
-Since irq priorites are managed in DT, static ones are no more required for
-sam9x5 which only has DT support.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/at91sam9x5.c | 38 --------------------------------------
- 1 file changed, 38 deletions(-)
-
-diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
-index dce3ff3..c949dc7 100644
---- a/arch/arm/mach-at91/at91sam9x5.c
-+++ b/arch/arm/mach-at91/at91sam9x5.c
-@@ -313,47 +313,9 @@ void __init at91sam9x5_initialize(void)
- /* --------------------------------------------------------------------
- * Interrupt initialization
- * -------------------------------------------------------------------- */
--/*
-- * The default interrupt priority levels (0 = lowest, 7 = highest).
-- */
--static unsigned int at91sam9x5_default_irq_priority[NR_AIC_IRQS] __initdata = {
-- 7, /* Advanced Interrupt Controller (FIQ) */
-- 7, /* System Peripherals */
-- 1, /* Parallel IO Controller A and B */
-- 1, /* Parallel IO Controller C and D */
-- 4, /* Soft Modem */
-- 5, /* USART 0 */
-- 5, /* USART 1 */
-- 5, /* USART 2 */
-- 5, /* USART 3 */
-- 6, /* Two-Wire Interface 0 */
-- 6, /* Two-Wire Interface 1 */
-- 6, /* Two-Wire Interface 2 */
-- 0, /* Multimedia Card Interface 0 */
-- 5, /* Serial Peripheral Interface 0 */
-- 5, /* Serial Peripheral Interface 1 */
-- 5, /* UART 0 */
-- 5, /* UART 1 */
-- 0, /* Timer Counter 0, 1, 2, 3, 4 and 5 */
-- 0, /* Pulse Width Modulation Controller */
-- 0, /* ADC Controller */
-- 0, /* DMA Controller 0 */
-- 0, /* DMA Controller 1 */
-- 2, /* USB Host High Speed port */
-- 2, /* USB Device High speed port */
-- 3, /* Ethernet MAC 0 */
-- 3, /* LDC Controller or Image Sensor Interface */
-- 0, /* Multimedia Card Interface 1 */
-- 3, /* Ethernet MAC 1 */
-- 4, /* Synchronous Serial Interface */
-- 4, /* CAN Controller 0 */
-- 4, /* CAN Controller 1 */
-- 0, /* Advanced Interrupt Controller (IRQ0) */
--};
-
- struct at91_init_soc __initdata at91sam9x5_soc = {
- .map_io = at91sam9x5_map_io,
-- .default_irq_priority = at91sam9x5_default_irq_priority,
- .register_clocks = at91sam9x5_register_clocks,
- .init = at91sam9x5_initialize,
- };
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 567e7d20c108ffb8974c7294ec0263da01ce419d Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Mon, 11 Jun 2012 15:38:03 +0200
-Subject: ARM: at91: at91 based machines specify their own irq handler at run
- time
-
-commit 3e135466745a62b1814edef74c7b4a25e6bda707 upstream.
-
-SOC_AT91SAM9 selects MULTI_IRQ_HANDLER in order to let machines specify their
-own IRQ handler at run time.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/Kconfig | 1 +
- arch/arm/mach-at91/board-1arm.c | 2 ++
- arch/arm/mach-at91/board-afeb-9260v1.c | 2 ++
- arch/arm/mach-at91/board-cam60.c | 2 ++
- arch/arm/mach-at91/board-carmeva.c | 2 ++
- arch/arm/mach-at91/board-cpu9krea.c | 2 ++
- arch/arm/mach-at91/board-cpuat91.c | 2 ++
- arch/arm/mach-at91/board-csb337.c | 2 ++
- arch/arm/mach-at91/board-csb637.c | 2 ++
- arch/arm/mach-at91/board-dt.c | 2 ++
- arch/arm/mach-at91/board-eb01.c | 2 ++
- arch/arm/mach-at91/board-eb9200.c | 2 ++
- arch/arm/mach-at91/board-ecbat91.c | 2 ++
- arch/arm/mach-at91/board-eco920.c | 2 ++
- arch/arm/mach-at91/board-flexibity.c | 2 ++
- arch/arm/mach-at91/board-foxg20.c | 2 ++
- arch/arm/mach-at91/board-gsia18s.c | 2 ++
- arch/arm/mach-at91/board-kafa.c | 2 ++
- arch/arm/mach-at91/board-kb9202.c | 2 ++
- arch/arm/mach-at91/board-neocore926.c | 2 ++
- arch/arm/mach-at91/board-pcontrol-g20.c | 2 ++
- arch/arm/mach-at91/board-picotux200.c | 2 ++
- arch/arm/mach-at91/board-qil-a9260.c | 2 ++
- arch/arm/mach-at91/board-rm9200dk.c | 2 ++
- arch/arm/mach-at91/board-rm9200ek.c | 2 ++
- arch/arm/mach-at91/board-rsi-ews.c | 2 ++
- arch/arm/mach-at91/board-sam9-l9260.c | 2 ++
- arch/arm/mach-at91/board-sam9260ek.c | 2 ++
- arch/arm/mach-at91/board-sam9261ek.c | 2 ++
- arch/arm/mach-at91/board-sam9263ek.c | 2 ++
- arch/arm/mach-at91/board-sam9g20ek.c | 3 +++
- arch/arm/mach-at91/board-sam9m10g45ek.c | 2 ++
- arch/arm/mach-at91/board-sam9rlek.c | 2 ++
- arch/arm/mach-at91/board-snapper9260.c | 2 ++
- arch/arm/mach-at91/board-stamp9g20.c | 3 +++
- arch/arm/mach-at91/board-usb-a926x.c | 4 ++++
- arch/arm/mach-at91/board-yl-9200.c | 2 ++
- arch/arm/mach-at91/include/mach/at91_aic.h | 2 ++
- arch/arm/mach-at91/include/mach/entry-macro.S | 27 ---------------------------
- arch/arm/mach-at91/irq.c | 19 +++++++++++++++++++
- 40 files changed, 98 insertions(+), 27 deletions(-)
- delete mode 100644 arch/arm/mach-at91/include/mach/entry-macro.S
-
-diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
-index 19505c0..e401dea 100644
---- a/arch/arm/mach-at91/Kconfig
-+++ b/arch/arm/mach-at91/Kconfig
-@@ -29,6 +29,7 @@ comment "Atmel AT91 Processor"
- config SOC_AT91SAM9
- bool
- select CPU_ARM926T
-+ select MULTI_IRQ_HANDLER
- select AT91_SAM9_TIME
- select AT91_SAM9_SMC
-
-diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
-index 271f994..22d8856 100644
---- a/arch/arm/mach-at91/board-1arm.c
-+++ b/arch/arm/mach-at91/board-1arm.c
-@@ -36,6 +36,7 @@
-
- #include <mach/board.h>
- #include <mach/cpu.h>
-+#include <mach/at91_aic.h>
-
- #include "generic.h"
-
-@@ -91,6 +92,7 @@ MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
- /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .timer = &at91rm9200_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = onearm_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = onearm_board_init,
-diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
-index b7d8aa7..de7be19 100644
---- a/arch/arm/mach-at91/board-afeb-9260v1.c
-+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
-@@ -44,6 +44,7 @@
- #include <asm/mach/irq.h>
-
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
-
- #include "generic.h"
-
-@@ -212,6 +213,7 @@ MACHINE_START(AFEB9260, "Custom afeb9260 board")
- /* Maintainer: Sergey Lapin <slapin@ossfans.org> */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = afeb9260_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = afeb9260_board_init,
-diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
-index 29d3ef0..477e708 100644
---- a/arch/arm/mach-at91/board-cam60.c
-+++ b/arch/arm/mach-at91/board-cam60.c
-@@ -39,6 +39,7 @@
- #include <asm/mach/irq.h>
-
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
-
- #include "sam9_smc.h"
-@@ -188,6 +189,7 @@ MACHINE_START(CAM60, "KwikByte CAM60")
- /* Maintainer: KwikByte */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = cam60_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = cam60_board_init,
-diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
-index 44328a6..a5b002f 100644
---- a/arch/arm/mach-at91/board-carmeva.c
-+++ b/arch/arm/mach-at91/board-carmeva.c
-@@ -36,6 +36,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
-
- #include "generic.h"
-
-@@ -158,6 +159,7 @@ MACHINE_START(CARMEVA, "Carmeva")
- /* Maintainer: Conitec Datasystems */
- .timer = &at91rm9200_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = carmeva_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = carmeva_board_init,
-diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
-index ece0d76..7ddc219 100644
---- a/arch/arm/mach-at91/board-cpu9krea.c
-+++ b/arch/arm/mach-at91/board-cpu9krea.c
-@@ -41,6 +41,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
- #include <mach/at91sam9260_matrix.h>
- #include <mach/at91_matrix.h>
-@@ -375,6 +376,7 @@ MACHINE_START(CPUAT9G20, "Eukrea CPU9G20")
- /* Maintainer: Eric Benard - EUKREA Electromatique */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = cpu9krea_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = cpu9krea_board_init,
-diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
-index 895cf2d..2e6d043 100644
---- a/arch/arm/mach-at91/board-cpuat91.c
-+++ b/arch/arm/mach-at91/board-cpuat91.c
-@@ -37,6 +37,7 @@
- #include <asm/mach/irq.h>
-
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91rm9200_mc.h>
- #include <mach/at91_ramc.h>
- #include <mach/cpu.h>
-@@ -178,6 +179,7 @@ MACHINE_START(CPUAT91, "Eukrea")
- /* Maintainer: Eric Benard - EUKREA Electromatique */
- .timer = &at91rm9200_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = cpuat91_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = cpuat91_board_init,
-diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
-index cd81336..462bc31 100644
---- a/arch/arm/mach-at91/board-csb337.c
-+++ b/arch/arm/mach-at91/board-csb337.c
-@@ -39,6 +39,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
-
- #include "generic.h"
-
-@@ -252,6 +253,7 @@ MACHINE_START(CSB337, "Cogent CSB337")
- /* Maintainer: Bill Gatliff */
- .timer = &at91rm9200_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = csb337_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = csb337_board_init,
-diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
-index 7c8b05a..872871a 100644
---- a/arch/arm/mach-at91/board-csb637.c
-+++ b/arch/arm/mach-at91/board-csb637.c
-@@ -36,6 +36,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
-
- #include "generic.h"
-
-@@ -133,6 +134,7 @@ MACHINE_START(CSB637, "Cogent CSB637")
- /* Maintainer: Bill Gatliff */
- .timer = &at91rm9200_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = csb637_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = csb637_board_init,
-diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
-index a1fce05..e8f45c4 100644
---- a/arch/arm/mach-at91/board-dt.c
-+++ b/arch/arm/mach-at91/board-dt.c
-@@ -16,6 +16,7 @@
- #include <linux/of_platform.h>
-
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
-
- #include <asm/setup.h>
- #include <asm/irq.h>
-@@ -53,6 +54,7 @@ DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
- /* Maintainer: Atmel */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = at91_dt_initialize,
- .init_irq = at91_dt_init_irq,
- .init_machine = at91_dt_device_init,
-diff --git a/arch/arm/mach-at91/board-eb01.c b/arch/arm/mach-at91/board-eb01.c
-index d2023f2..01f66e9 100644
---- a/arch/arm/mach-at91/board-eb01.c
-+++ b/arch/arm/mach-at91/board-eb01.c
-@@ -28,6 +28,7 @@
- #include <asm/mach/arch.h>
- #include <asm/mach/map.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include "generic.h"
-
- static void __init at91eb01_init_irq(void)
-@@ -43,6 +44,7 @@ static void __init at91eb01_init_early(void)
- MACHINE_START(AT91EB01, "Atmel AT91 EB01")
- /* Maintainer: Greg Ungerer <gerg@snapgear.com> */
- .timer = &at91x40_timer,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = at91eb01_init_early,
- .init_irq = at91eb01_init_irq,
- MACHINE_END
-diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
-index bd10172..d1e1f3f 100644
---- a/arch/arm/mach-at91/board-eb9200.c
-+++ b/arch/arm/mach-at91/board-eb9200.c
-@@ -36,6 +36,7 @@
- #include <asm/mach/irq.h>
-
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
-
- #include "generic.h"
-
-@@ -118,6 +119,7 @@ static void __init eb9200_board_init(void)
- MACHINE_START(ATEB9200, "Embest ATEB9200")
- .timer = &at91rm9200_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = eb9200_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = eb9200_board_init,
-diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
-index 89cc372..9c24cb2 100644
---- a/arch/arm/mach-at91/board-ecbat91.c
-+++ b/arch/arm/mach-at91/board-ecbat91.c
-@@ -39,6 +39,7 @@
-
- #include <mach/board.h>
- #include <mach/cpu.h>
-+#include <mach/at91_aic.h>
-
- #include "generic.h"
-
-@@ -170,6 +171,7 @@ MACHINE_START(ECBAT91, "emQbit's ECB_AT91")
- /* Maintainer: emQbit.com */
- .timer = &at91rm9200_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = ecb_at91init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = ecb_at91board_init,
-diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c
-index 558546c..82bdfde 100644
---- a/arch/arm/mach-at91/board-eco920.c
-+++ b/arch/arm/mach-at91/board-eco920.c
-@@ -25,6 +25,7 @@
- #include <asm/mach/map.h>
-
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91rm9200_mc.h>
- #include <mach/at91_ramc.h>
- #include <mach/cpu.h>
-@@ -132,6 +133,7 @@ MACHINE_START(ECO920, "eco920")
- /* Maintainer: Sascha Hauer */
- .timer = &at91rm9200_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = eco920_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = eco920_board_init,
-diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
-index 47658f7..6cc83a8 100644
---- a/arch/arm/mach-at91/board-flexibity.c
-+++ b/arch/arm/mach-at91/board-flexibity.c
-@@ -34,6 +34,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
-
- #include "generic.h"
-
-@@ -160,6 +161,7 @@ MACHINE_START(FLEXIBITY, "Flexibity Connect")
- /* Maintainer: Maxim Osipov */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = flexibity_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = flexibity_board_init,
-diff --git a/arch/arm/mach-at91/board-foxg20.c b/arch/arm/mach-at91/board-foxg20.c
-index 33411e6..69ab124 100644
---- a/arch/arm/mach-at91/board-foxg20.c
-+++ b/arch/arm/mach-at91/board-foxg20.c
-@@ -42,6 +42,7 @@
- #include <asm/mach/irq.h>
-
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
-
- #include "sam9_smc.h"
-@@ -262,6 +263,7 @@ MACHINE_START(ACMENETUSFOXG20, "Acme Systems srl FOX Board G20")
- /* Maintainer: Sergio Tanzilli */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = foxg20_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = foxg20_board_init,
-diff --git a/arch/arm/mach-at91/board-gsia18s.c b/arch/arm/mach-at91/board-gsia18s.c
-index 3e0dfa6..a9d5e78 100644
---- a/arch/arm/mach-at91/board-gsia18s.c
-+++ b/arch/arm/mach-at91/board-gsia18s.c
-@@ -31,6 +31,7 @@
- #include <asm/mach/arch.h>
-
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
- #include <mach/gsia18s.h>
- #include <mach/stamp9g20.h>
-@@ -575,6 +576,7 @@ static void __init gsia18s_board_init(void)
- MACHINE_START(GSIA18S, "GS_IA18_S")
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = gsia18s_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = gsia18s_board_init,
-diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
-index f260657..64c1dbf 100644
---- a/arch/arm/mach-at91/board-kafa.c
-+++ b/arch/arm/mach-at91/board-kafa.c
-@@ -35,6 +35,7 @@
- #include <asm/mach/irq.h>
-
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/cpu.h>
-
- #include "generic.h"
-@@ -93,6 +94,7 @@ MACHINE_START(KAFA, "Sperry-Sun KAFA")
- /* Maintainer: Sergei Sharonov */
- .timer = &at91rm9200_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = kafa_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = kafa_board_init,
-diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
-index ba39db5..5d96cb8 100644
---- a/arch/arm/mach-at91/board-kb9202.c
-+++ b/arch/arm/mach-at91/board-kb9202.c
-@@ -37,6 +37,7 @@
-
- #include <mach/board.h>
- #include <mach/cpu.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91rm9200_mc.h>
- #include <mach/at91_ramc.h>
-
-@@ -133,6 +134,7 @@ MACHINE_START(KB9200, "KB920x")
- /* Maintainer: KwikByte, Inc. */
- .timer = &at91rm9200_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = kb9202_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = kb9202_board_init,
-diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
-index d2f4cc1..18103c5d 100644
---- a/arch/arm/mach-at91/board-neocore926.c
-+++ b/arch/arm/mach-at91/board-neocore926.c
-@@ -45,6 +45,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
-
- #include "sam9_smc.h"
-@@ -378,6 +379,7 @@ MACHINE_START(NEOCORE926, "ADENEO NEOCORE 926")
- /* Maintainer: ADENEO */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = neocore926_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = neocore926_board_init,
-diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c
-index 7fe6383..9ca3e32 100644
---- a/arch/arm/mach-at91/board-pcontrol-g20.c
-+++ b/arch/arm/mach-at91/board-pcontrol-g20.c
-@@ -30,6 +30,7 @@
- #include <asm/mach/arch.h>
-
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
- #include <mach/stamp9g20.h>
-
-@@ -218,6 +219,7 @@ MACHINE_START(PCONTROL_G20, "PControl G20")
- /* Maintainer: pgsellmann@portner-elektronik.at */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = pcontrol_g20_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = pcontrol_g20_board_init,
-diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
-index b45c0a5..1270655 100644
---- a/arch/arm/mach-at91/board-picotux200.c
-+++ b/arch/arm/mach-at91/board-picotux200.c
-@@ -38,6 +38,7 @@
- #include <asm/mach/irq.h>
-
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91rm9200_mc.h>
- #include <mach/at91_ramc.h>
-
-@@ -120,6 +121,7 @@ MACHINE_START(PICOTUX2XX, "picotux 200")
- /* Maintainer: Kleinhenz Elektronik GmbH */
- .timer = &at91rm9200_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = picotux200_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = picotux200_board_init,
-diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
-index 0c61bf0..bf351e2 100644
---- a/arch/arm/mach-at91/board-qil-a9260.c
-+++ b/arch/arm/mach-at91/board-qil-a9260.c
-@@ -41,6 +41,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
- #include <mach/at91_shdwc.h>
-
-@@ -258,6 +259,7 @@ MACHINE_START(QIL_A9260, "CALAO QIL_A9260")
- /* Maintainer: calao-systems */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = ek_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = ek_board_init,
-diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c
-index afd7a47..cc2bf97 100644
---- a/arch/arm/mach-at91/board-rm9200dk.c
-+++ b/arch/arm/mach-at91/board-rm9200dk.c
-@@ -40,6 +40,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91rm9200_mc.h>
- #include <mach/at91_ramc.h>
-
-@@ -223,6 +224,7 @@ MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
- /* Maintainer: SAN People/Atmel */
- .timer = &at91rm9200_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = dk_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = dk_board_init,
-diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
-index 2b15b8a..62e19e6 100644
---- a/arch/arm/mach-at91/board-rm9200ek.c
-+++ b/arch/arm/mach-at91/board-rm9200ek.c
-@@ -40,6 +40,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91rm9200_mc.h>
- #include <mach/at91_ramc.h>
-
-@@ -190,6 +191,7 @@ MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
- /* Maintainer: SAN People/Atmel */
- .timer = &at91rm9200_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = ek_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = ek_board_init,
-diff --git a/arch/arm/mach-at91/board-rsi-ews.c b/arch/arm/mach-at91/board-rsi-ews.c
-index 24ab9be..c3b43ae 100644
---- a/arch/arm/mach-at91/board-rsi-ews.c
-+++ b/arch/arm/mach-at91/board-rsi-ews.c
-@@ -26,6 +26,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
-
- #include <linux/gpio.h>
-
-@@ -225,6 +226,7 @@ MACHINE_START(RSI_EWS, "RSI EWS")
- /* Maintainer: Josef Holzmayr <holzmayr@rsi-elektrotechnik.de> */
- .timer = &at91rm9200_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = rsi_ews_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = rsi_ews_board_init,
-diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
-index cdd21f2..7bf6da7 100644
---- a/arch/arm/mach-at91/board-sam9-l9260.c
-+++ b/arch/arm/mach-at91/board-sam9-l9260.c
-@@ -38,6 +38,7 @@
- #include <asm/mach/irq.h>
-
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
-
- #include "sam9_smc.h"
-@@ -202,6 +203,7 @@ MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
- /* Maintainer: Olimex */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = ek_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = ek_board_init,
-diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
-index 7b3c391..889c1bf 100644
---- a/arch/arm/mach-at91/board-sam9260ek.c
-+++ b/arch/arm/mach-at91/board-sam9260ek.c
-@@ -42,6 +42,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
- #include <mach/at91_shdwc.h>
- #include <mach/system_rev.h>
-@@ -344,6 +345,7 @@ MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
- /* Maintainer: Atmel */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = ek_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = ek_board_init,
-diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
-index 2736453..2269be5 100644
---- a/arch/arm/mach-at91/board-sam9261ek.c
-+++ b/arch/arm/mach-at91/board-sam9261ek.c
-@@ -46,6 +46,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
- #include <mach/at91_shdwc.h>
- #include <mach/system_rev.h>
-@@ -615,6 +616,7 @@ MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK")
- /* Maintainer: Atmel */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = ek_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = ek_board_init,
-diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
-index 983cb98..82adf58 100644
---- a/arch/arm/mach-at91/board-sam9263ek.c
-+++ b/arch/arm/mach-at91/board-sam9263ek.c
-@@ -45,6 +45,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
- #include <mach/at91_shdwc.h>
- #include <mach/system_rev.h>
-@@ -443,6 +444,7 @@ MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
- /* Maintainer: Atmel */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = ek_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = ek_board_init,
-diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
-index 3d61553..da6d019 100644
---- a/arch/arm/mach-at91/board-sam9g20ek.c
-+++ b/arch/arm/mach-at91/board-sam9g20ek.c
-@@ -42,6 +42,7 @@
- #include <asm/mach/irq.h>
-
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
- #include <mach/system_rev.h>
-
-@@ -399,6 +400,7 @@ MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
- /* Maintainer: Atmel */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = ek_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = ek_board_init,
-@@ -408,6 +410,7 @@ MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
- /* Maintainer: Atmel */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = ek_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = ek_board_init,
-diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
-index 9a87f0b..d1882d5 100644
---- a/arch/arm/mach-at91/board-sam9m10g45ek.c
-+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
-@@ -41,6 +41,7 @@
- #include <asm/mach/irq.h>
-
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
- #include <mach/at91_shdwc.h>
- #include <mach/system_rev.h>
-@@ -491,6 +492,7 @@ MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
- /* Maintainer: Atmel */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = ek_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = ek_board_init,
-diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
-index be3239f..e7dc3ea 100644
---- a/arch/arm/mach-at91/board-sam9rlek.c
-+++ b/arch/arm/mach-at91/board-sam9rlek.c
-@@ -31,6 +31,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
- #include <mach/at91_shdwc.h>
-
-@@ -319,6 +320,7 @@ MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK")
- /* Maintainer: Atmel */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = ek_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = ek_board_init,
-diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
-index 9d446f1..a4e031a 100644
---- a/arch/arm/mach-at91/board-snapper9260.c
-+++ b/arch/arm/mach-at91/board-snapper9260.c
-@@ -33,6 +33,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
-
- #include "sam9_smc.h"
-@@ -178,6 +179,7 @@ static void __init snapper9260_board_init(void)
- MACHINE_START(SNAPPER_9260, "Bluewater Systems Snapper 9260/9G20 module")
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = snapper9260_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = snapper9260_board_init,
-diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
-index ee86f9d..29eae16 100644
---- a/arch/arm/mach-at91/board-stamp9g20.c
-+++ b/arch/arm/mach-at91/board-stamp9g20.c
-@@ -26,6 +26,7 @@
- #include <asm/mach/arch.h>
-
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
-
- #include "sam9_smc.h"
-@@ -287,6 +288,7 @@ MACHINE_START(PORTUXG20, "taskit PortuxG20")
- /* Maintainer: taskit GmbH */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = stamp9g20_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = portuxg20_board_init,
-@@ -296,6 +298,7 @@ MACHINE_START(STAMP9G20, "taskit Stamp9G20")
- /* Maintainer: taskit GmbH */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = stamp9g20_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = stamp9g20evb_board_init,
-diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c
-index 95393fc..c1476b9 100644
---- a/arch/arm/mach-at91/board-usb-a926x.c
-+++ b/arch/arm/mach-at91/board-usb-a926x.c
-@@ -42,6 +42,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91sam9_smc.h>
- #include <mach/at91_shdwc.h>
-
-@@ -358,6 +359,7 @@ MACHINE_START(USB_A9263, "CALAO USB_A9263")
- /* Maintainer: calao-systems */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = ek_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = ek_board_init,
-@@ -367,6 +369,7 @@ MACHINE_START(USB_A9260, "CALAO USB_A9260")
- /* Maintainer: calao-systems */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = ek_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = ek_board_init,
-@@ -376,6 +379,7 @@ MACHINE_START(USB_A9G20, "CALAO USB_A92G0")
- /* Maintainer: Jean-Christophe PLAGNIOL-VILLARD */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = ek_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = ek_board_init,
-diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
-index d56665e..516d340 100644
---- a/arch/arm/mach-at91/board-yl-9200.c
-+++ b/arch/arm/mach-at91/board-yl-9200.c
-@@ -44,6 +44,7 @@
-
- #include <mach/hardware.h>
- #include <mach/board.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91rm9200_mc.h>
- #include <mach/at91_ramc.h>
- #include <mach/cpu.h>
-@@ -590,6 +591,7 @@ MACHINE_START(YL9200, "uCdragon YL-9200")
- /* Maintainer: S.Birtles */
- .timer = &at91rm9200_timer,
- .map_io = at91_map_io,
-+ .handle_irq = at91_aic_handle_irq,
- .init_early = yl9200_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = yl9200_board_init,
-diff --git a/arch/arm/mach-at91/include/mach/at91_aic.h b/arch/arm/mach-at91/include/mach/at91_aic.h
-index 3af7272..7867378 100644
---- a/arch/arm/mach-at91/include/mach/at91_aic.h
-+++ b/arch/arm/mach-at91/include/mach/at91_aic.h
-@@ -65,4 +65,6 @@ extern void __iomem *at91_aic_base;
- #define AT91_AIC_FFDR 0x144 /* Fast Forcing Disable Register [SAM9 only] */
- #define AT91_AIC_FFSR 0x148 /* Fast Forcing Status Register [SAM9 only] */
-
-+void at91_aic_handle_irq(struct pt_regs *regs);
-+
- #endif
-diff --git a/arch/arm/mach-at91/include/mach/entry-macro.S b/arch/arm/mach-at91/include/mach/entry-macro.S
-deleted file mode 100644
-index 903bf20..0000000
---- a/arch/arm/mach-at91/include/mach/entry-macro.S
-+++ /dev/null
-@@ -1,27 +0,0 @@
--/*
-- * arch/arm/mach-at91/include/mach/entry-macro.S
-- *
-- * Copyright (C) 2003-2005 SAN People
-- *
-- * Low-level IRQ helper macros for AT91RM9200 platforms
-- *
-- * 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 <mach/hardware.h>
--#include <mach/at91_aic.h>
--
-- .macro get_irqnr_preamble, base, tmp
-- ldr \base, =at91_aic_base @ base virtual address of AIC peripheral
-- ldr \base, [\base]
-- .endm
--
-- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-- ldr \irqnr, [\base, #AT91_AIC_IVR] @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt)
-- ldr \irqstat, [\base, #AT91_AIC_ISR] @ read interrupt source number
-- teq \irqstat, #0 @ ISR is 0 when no current interrupt, or spurious interrupt
-- streq \tmp, [\base, #AT91_AIC_EOICR] @ not going to be handled further, then ACK it now.
-- .endm
--
-diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
-index db8e141..390d4df 100644
---- a/arch/arm/mach-at91/irq.c
-+++ b/arch/arm/mach-at91/irq.c
-@@ -36,6 +36,7 @@
- #include <asm/irq.h>
- #include <asm/setup.h>
-
-+#include <asm/exception.h>
- #include <asm/mach/arch.h>
- #include <asm/mach/irq.h>
- #include <asm/mach/map.h>
-@@ -45,6 +46,24 @@ static struct irq_domain *at91_aic_domain;
- static struct device_node *at91_aic_np;
- static unsigned int *at91_aic_irq_priorities;
-
-+asmlinkage void __exception_irq_entry at91_aic_handle_irq(struct pt_regs *regs)
-+{
-+ u32 irqnr;
-+ u32 irqstat;
-+
-+ irqnr = at91_aic_read(AT91_AIC_IVR);
-+ irqstat = at91_aic_read(AT91_AIC_ISR);
-+
-+ /*
-+ * ISR value is 0 when there is no current interrupt or when there is
-+ * a spurious interrupt
-+ */
-+ if (!irqstat)
-+ at91_aic_write(AT91_AIC_EOICR, 0);
-+ else
-+ handle_IRQ(irqnr, regs);
-+}
-+
- static void at91_aic_mask_irq(struct irq_data *d)
- {
- /* Disable interrupt on AIC */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From f53355af7dda7196da453539fae26457c459dfb2 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Thu, 21 Jun 2012 14:47:27 +0200
-Subject: ARM: at91: sparse irq support
-
-commit 8fe82a5550a8e97b3f59c74f994b88ed6b3544a3 upstream.
-
-Enable sparse irq support for multisoc image. It involves to add the
-NR_IRQS_LEGACY offset to static SoC irq number definitions since NR_IRQS_LEGACY
-irq descs are allocated before AIC requests irq descs allocation.
-Move NR_AIC_IRQS macro to a more appropiate place with the purpose to
-remove mach/irqs.h later.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-
-Conflicts:
- arch/arm/mach-at91/at91sam9260_devices.c
- arch/arm/mach-at91/at91sam9g45_devices.c
----
- arch/arm/mach-at91/Kconfig | 1 +
- arch/arm/mach-at91/at91rm9200.c | 1 +
- arch/arm/mach-at91/at91rm9200_devices.c | 84 +++++++++++------------
- arch/arm/mach-at91/at91sam9260.c | 1 +
- arch/arm/mach-at91/at91sam9260_devices.c | 88 ++++++++++++------------
- arch/arm/mach-at91/at91sam9261.c | 1 +
- arch/arm/mach-at91/at91sam9261_devices.c | 68 +++++++++----------
- arch/arm/mach-at91/at91sam9263.c | 1 +
- arch/arm/mach-at91/at91sam9263_devices.c | 80 +++++++++++-----------
- arch/arm/mach-at91/at91sam926x_time.c | 2 +-
- arch/arm/mach-at91/at91sam9g45.c | 1 +
- arch/arm/mach-at91/at91sam9g45_devices.c | 104 ++++++++++++++---------------
- arch/arm/mach-at91/at91sam9rl.c | 1 +
- arch/arm/mach-at91/at91sam9rl_devices.c | 76 ++++++++++-----------
- arch/arm/mach-at91/at91x40.c | 1 +
- arch/arm/mach-at91/include/mach/at91_aic.h | 3 +
- arch/arm/mach-at91/include/mach/irqs.h | 12 ----
- arch/arm/mach-at91/irq.c | 6 +-
- arch/arm/mach-at91/pm.c | 1 +
- 19 files changed, 267 insertions(+), 265 deletions(-)
-
-diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
-index e401dea..7d0c40a 100644
---- a/arch/arm/mach-at91/Kconfig
-+++ b/arch/arm/mach-at91/Kconfig
-@@ -30,6 +30,7 @@ config SOC_AT91SAM9
- bool
- select CPU_ARM926T
- select MULTI_IRQ_HANDLER
-+ select SPARSE_IRQ
- select AT91_SAM9_TIME
- select AT91_SAM9_SMC
-
-diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
-index d50da1a..801c30b 100644
---- a/arch/arm/mach-at91/at91rm9200.c
-+++ b/arch/arm/mach-at91/at91rm9200.c
-@@ -17,6 +17,7 @@
- #include <asm/mach/map.h>
- #include <asm/system_misc.h>
- #include <mach/at91rm9200.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91_pmc.h>
- #include <mach/at91_st.h>
- #include <mach/cpu.h>
-diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
-index 99affb5..04d69d3 100644
---- a/arch/arm/mach-at91/at91rm9200_devices.c
-+++ b/arch/arm/mach-at91/at91rm9200_devices.c
-@@ -41,8 +41,8 @@ static struct resource usbh_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91RM9200_ID_UHP,
-- .end = AT91RM9200_ID_UHP,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_UHP,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_UHP,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -94,8 +94,8 @@ static struct resource udc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91RM9200_ID_UDP,
-- .end = AT91RM9200_ID_UDP,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_UDP,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_UDP,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -145,8 +145,8 @@ static struct resource eth_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91RM9200_ID_EMAC,
-- .end = AT91RM9200_ID_EMAC,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_EMAC,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_EMAC,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -305,8 +305,8 @@ static struct resource mmc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91RM9200_ID_MCI,
-- .end = AT91RM9200_ID_MCI,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_MCI,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_MCI,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -488,8 +488,8 @@ static struct resource twi_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91RM9200_ID_TWI,
-- .end = AT91RM9200_ID_TWI,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_TWI,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_TWI,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -532,8 +532,8 @@ static struct resource spi_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91RM9200_ID_SPI,
-- .end = AT91RM9200_ID_SPI,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_SPI,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_SPI,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -598,18 +598,18 @@ static struct resource tcb0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91RM9200_ID_TC0,
-- .end = AT91RM9200_ID_TC0,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_TC0,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_TC0,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
-- .start = AT91RM9200_ID_TC1,
-- .end = AT91RM9200_ID_TC1,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_TC1,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_TC1,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
-- .start = AT91RM9200_ID_TC2,
-- .end = AT91RM9200_ID_TC2,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_TC2,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_TC2,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -628,18 +628,18 @@ static struct resource tcb1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91RM9200_ID_TC3,
-- .end = AT91RM9200_ID_TC3,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_TC3,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_TC3,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
-- .start = AT91RM9200_ID_TC4,
-- .end = AT91RM9200_ID_TC4,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_TC4,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_TC4,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
-- .start = AT91RM9200_ID_TC5,
-- .end = AT91RM9200_ID_TC5,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_TC5,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_TC5,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -673,8 +673,8 @@ static struct resource rtc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91_ID_SYS,
-- .end = AT91_ID_SYS,
-+ .start = NR_IRQS_LEGACY + AT91_ID_SYS,
-+ .end = NR_IRQS_LEGACY + AT91_ID_SYS,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -729,8 +729,8 @@ static struct resource ssc0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91RM9200_ID_SSC0,
-- .end = AT91RM9200_ID_SSC0,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_SSC0,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_SSC0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -771,8 +771,8 @@ static struct resource ssc1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91RM9200_ID_SSC1,
-- .end = AT91RM9200_ID_SSC1,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_SSC1,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_SSC1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -813,8 +813,8 @@ static struct resource ssc2_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91RM9200_ID_SSC2,
-- .end = AT91RM9200_ID_SSC2,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_SSC2,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_SSC2,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -897,8 +897,8 @@ static struct resource dbgu_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91_ID_SYS,
-- .end = AT91_ID_SYS,
-+ .start = NR_IRQS_LEGACY + AT91_ID_SYS,
-+ .end = NR_IRQS_LEGACY + AT91_ID_SYS,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -935,8 +935,8 @@ static struct resource uart0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91RM9200_ID_US0,
-- .end = AT91RM9200_ID_US0,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_US0,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_US0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -984,8 +984,8 @@ static struct resource uart1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91RM9200_ID_US1,
-- .end = AT91RM9200_ID_US1,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_US1,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_US1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1035,8 +1035,8 @@ static struct resource uart2_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91RM9200_ID_US2,
-- .end = AT91RM9200_ID_US2,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_US2,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_US2,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1078,8 +1078,8 @@ static struct resource uart3_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91RM9200_ID_US3,
-- .end = AT91RM9200_ID_US3,
-+ .start = NR_IRQS_LEGACY + AT91RM9200_ID_US3,
-+ .end = NR_IRQS_LEGACY + AT91RM9200_ID_US3,
- .flags = IORESOURCE_IRQ,
- },
- };
-diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
-index a27bbec..c644131 100644
---- a/arch/arm/mach-at91/at91sam9260.c
-+++ b/arch/arm/mach-at91/at91sam9260.c
-@@ -20,6 +20,7 @@
- #include <mach/cpu.h>
- #include <mach/at91_dbgu.h>
- #include <mach/at91sam9260.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91_pmc.h>
- #include <mach/at91_rstc.h>
-
-diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
-index d556de1..43e60fb 100644
---- a/arch/arm/mach-at91/at91sam9260_devices.c
-+++ b/arch/arm/mach-at91/at91sam9260_devices.c
-@@ -42,8 +42,8 @@ static struct resource usbh_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_UHP,
-- .end = AT91SAM9260_ID_UHP,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_UHP,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_UHP,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -95,8 +95,8 @@ static struct resource udc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_UDP,
-- .end = AT91SAM9260_ID_UDP,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_UDP,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_UDP,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -146,8 +146,8 @@ static struct resource eth_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_EMAC,
-- .end = AT91SAM9260_ID_EMAC,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_EMAC,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_EMAC,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -220,8 +220,8 @@ static struct resource mmc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_MCI,
-- .end = AT91SAM9260_ID_MCI,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -302,8 +302,8 @@ static struct resource mmc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_MCI,
-- .end = AT91SAM9260_ID_MCI,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -493,8 +493,8 @@ static struct resource twi_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_TWI,
-- .end = AT91SAM9260_ID_TWI,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_TWI,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_TWI,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -537,8 +537,8 @@ static struct resource spi0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_SPI0,
-- .end = AT91SAM9260_ID_SPI0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -563,8 +563,8 @@ static struct resource spi1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_SPI1,
-- .end = AT91SAM9260_ID_SPI1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -649,18 +649,18 @@ static struct resource tcb0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_TC0,
-- .end = AT91SAM9260_ID_TC0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_TC0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_TC0,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
-- .start = AT91SAM9260_ID_TC1,
-- .end = AT91SAM9260_ID_TC1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_TC1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_TC1,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
-- .start = AT91SAM9260_ID_TC2,
-- .end = AT91SAM9260_ID_TC2,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_TC2,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_TC2,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -679,18 +679,18 @@ static struct resource tcb1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_TC3,
-- .end = AT91SAM9260_ID_TC3,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_TC3,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_TC3,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
-- .start = AT91SAM9260_ID_TC4,
-- .end = AT91SAM9260_ID_TC4,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_TC4,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_TC4,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
-- .start = AT91SAM9260_ID_TC5,
-- .end = AT91SAM9260_ID_TC5,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_TC5,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_TC5,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -804,8 +804,8 @@ static struct resource ssc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_SSC,
-- .end = AT91SAM9260_ID_SSC,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_SSC,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_SSC,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -879,8 +879,8 @@ static struct resource dbgu_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91_ID_SYS,
-- .end = AT91_ID_SYS,
-+ .start = NR_IRQS_LEGACY + AT91_ID_SYS,
-+ .end = NR_IRQS_LEGACY + AT91_ID_SYS,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -917,8 +917,8 @@ static struct resource uart0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_US0,
-- .end = AT91SAM9260_ID_US0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_US0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_US0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -968,8 +968,8 @@ static struct resource uart1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_US1,
-- .end = AT91SAM9260_ID_US1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_US1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_US1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1011,8 +1011,8 @@ static struct resource uart2_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_US2,
-- .end = AT91SAM9260_ID_US2,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_US2,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_US2,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1054,8 +1054,8 @@ static struct resource uart3_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_US3,
-- .end = AT91SAM9260_ID_US3,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_US3,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_US3,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1097,8 +1097,8 @@ static struct resource uart4_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_US4,
-- .end = AT91SAM9260_ID_US4,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_US4,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_US4,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1135,8 +1135,8 @@ static struct resource uart5_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9260_ID_US5,
-- .end = AT91SAM9260_ID_US5,
-+ .start = NR_IRQS_LEGACY + AT91SAM9260_ID_US5,
-+ .end = NR_IRQS_LEGACY + AT91SAM9260_ID_US5,
- .flags = IORESOURCE_IRQ,
- },
- };
-diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
-index c77d503..f40762c 100644
---- a/arch/arm/mach-at91/at91sam9261.c
-+++ b/arch/arm/mach-at91/at91sam9261.c
-@@ -19,6 +19,7 @@
- #include <asm/system_misc.h>
- #include <mach/cpu.h>
- #include <mach/at91sam9261.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91_pmc.h>
- #include <mach/at91_rstc.h>
-
-diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
-index 9295e90..8df5c1b 100644
---- a/arch/arm/mach-at91/at91sam9261_devices.c
-+++ b/arch/arm/mach-at91/at91sam9261_devices.c
-@@ -45,8 +45,8 @@ static struct resource usbh_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9261_ID_UHP,
-- .end = AT91SAM9261_ID_UHP,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_UHP,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_UHP,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -98,8 +98,8 @@ static struct resource udc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9261_ID_UDP,
-- .end = AT91SAM9261_ID_UDP,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_UDP,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_UDP,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -148,8 +148,8 @@ static struct resource mmc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9261_ID_MCI,
-- .end = AT91SAM9261_ID_MCI,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_MCI,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_MCI,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -310,8 +310,8 @@ static struct resource twi_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9261_ID_TWI,
-- .end = AT91SAM9261_ID_TWI,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_TWI,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_TWI,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -354,8 +354,8 @@ static struct resource spi0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9261_ID_SPI0,
-- .end = AT91SAM9261_ID_SPI0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -380,8 +380,8 @@ static struct resource spi1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9261_ID_SPI1,
-- .end = AT91SAM9261_ID_SPI1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -468,8 +468,8 @@ static struct resource lcdc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9261_ID_LCDC,
-- .end = AT91SAM9261_ID_LCDC,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_LCDC,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_LCDC,
- .flags = IORESOURCE_IRQ,
- },
- #if defined(CONFIG_FB_INTSRAM)
-@@ -566,18 +566,18 @@ static struct resource tcb_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9261_ID_TC0,
-- .end = AT91SAM9261_ID_TC0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_TC0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_TC0,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
-- .start = AT91SAM9261_ID_TC1,
-- .end = AT91SAM9261_ID_TC1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_TC1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_TC1,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
-- .start = AT91SAM9261_ID_TC2,
-- .end = AT91SAM9261_ID_TC2,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_TC2,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_TC2,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -689,8 +689,8 @@ static struct resource ssc0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9261_ID_SSC0,
-- .end = AT91SAM9261_ID_SSC0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -731,8 +731,8 @@ static struct resource ssc1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9261_ID_SSC1,
-- .end = AT91SAM9261_ID_SSC1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -773,8 +773,8 @@ static struct resource ssc2_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9261_ID_SSC2,
-- .end = AT91SAM9261_ID_SSC2,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC2,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC2,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -857,8 +857,8 @@ static struct resource dbgu_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91_ID_SYS,
-- .end = AT91_ID_SYS,
-+ .start = NR_IRQS_LEGACY + AT91_ID_SYS,
-+ .end = NR_IRQS_LEGACY + AT91_ID_SYS,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -895,8 +895,8 @@ static struct resource uart0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9261_ID_US0,
-- .end = AT91SAM9261_ID_US0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_US0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_US0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -938,8 +938,8 @@ static struct resource uart1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9261_ID_US1,
-- .end = AT91SAM9261_ID_US1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_US1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_US1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -981,8 +981,8 @@ static struct resource uart2_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9261_ID_US2,
-- .end = AT91SAM9261_ID_US2,
-+ .start = NR_IRQS_LEGACY + AT91SAM9261_ID_US2,
-+ .end = NR_IRQS_LEGACY + AT91SAM9261_ID_US2,
- .flags = IORESOURCE_IRQ,
- },
- };
-diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
-index ed91c7e..84b3810 100644
---- a/arch/arm/mach-at91/at91sam9263.c
-+++ b/arch/arm/mach-at91/at91sam9263.c
-@@ -18,6 +18,7 @@
- #include <asm/mach/map.h>
- #include <asm/system_misc.h>
- #include <mach/at91sam9263.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91_pmc.h>
- #include <mach/at91_rstc.h>
-
-diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
-index 175e000..eb6bbf8 100644
---- a/arch/arm/mach-at91/at91sam9263_devices.c
-+++ b/arch/arm/mach-at91/at91sam9263_devices.c
-@@ -44,8 +44,8 @@ static struct resource usbh_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_UHP,
-- .end = AT91SAM9263_ID_UHP,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_UHP,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_UHP,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -104,8 +104,8 @@ static struct resource udc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_UDP,
-- .end = AT91SAM9263_ID_UDP,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_UDP,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_UDP,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -155,8 +155,8 @@ static struct resource eth_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_EMAC,
-- .end = AT91SAM9263_ID_EMAC,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_EMAC,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_EMAC,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -229,8 +229,8 @@ static struct resource mmc0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_MCI0,
-- .end = AT91SAM9263_ID_MCI0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -254,8 +254,8 @@ static struct resource mmc1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_MCI1,
-- .end = AT91SAM9263_ID_MCI1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -567,8 +567,8 @@ static struct resource twi_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_TWI,
-- .end = AT91SAM9263_ID_TWI,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_TWI,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_TWI,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -611,8 +611,8 @@ static struct resource spi0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_SPI0,
-- .end = AT91SAM9263_ID_SPI0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -637,8 +637,8 @@ static struct resource spi1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_SPI1,
-- .end = AT91SAM9263_ID_SPI1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -725,8 +725,8 @@ static struct resource ac97_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_AC97C,
-- .end = AT91SAM9263_ID_AC97C,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_AC97C,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_AC97C,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -776,8 +776,8 @@ static struct resource can_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_CAN,
-- .end = AT91SAM9263_ID_CAN,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_CAN,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_CAN,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -816,8 +816,8 @@ static struct resource lcdc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_LCDC,
-- .end = AT91SAM9263_ID_LCDC,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_LCDC,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_LCDC,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -883,8 +883,8 @@ struct resource isi_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_ISI,
-- .end = AT91SAM9263_ID_ISI,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_ISI,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_ISI,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -940,8 +940,8 @@ static struct resource tcb_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_TCB,
-- .end = AT91SAM9263_ID_TCB,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_TCB,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_TCB,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1108,8 +1108,8 @@ static struct resource pwm_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_PWMC,
-- .end = AT91SAM9263_ID_PWMC,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_PWMC,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_PWMC,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1161,8 +1161,8 @@ static struct resource ssc0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_SSC0,
-- .end = AT91SAM9263_ID_SSC0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1203,8 +1203,8 @@ static struct resource ssc1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_SSC1,
-- .end = AT91SAM9263_ID_SSC1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1284,8 +1284,8 @@ static struct resource dbgu_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91_ID_SYS,
-- .end = AT91_ID_SYS,
-+ .start = NR_IRQS_LEGACY + AT91_ID_SYS,
-+ .end = NR_IRQS_LEGACY + AT91_ID_SYS,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1322,8 +1322,8 @@ static struct resource uart0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_US0,
-- .end = AT91SAM9263_ID_US0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_US0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_US0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1365,8 +1365,8 @@ static struct resource uart1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_US1,
-- .end = AT91SAM9263_ID_US1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_US1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_US1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1408,8 +1408,8 @@ static struct resource uart2_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9263_ID_US2,
-- .end = AT91SAM9263_ID_US2,
-+ .start = NR_IRQS_LEGACY + AT91SAM9263_ID_US2,
-+ .end = NR_IRQS_LEGACY + AT91SAM9263_ID_US2,
- .flags = IORESOURCE_IRQ,
- },
- };
-diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
-index a94758b..ffc0957 100644
---- a/arch/arm/mach-at91/at91sam926x_time.c
-+++ b/arch/arm/mach-at91/at91sam926x_time.c
-@@ -137,7 +137,7 @@ static struct irqaction at91sam926x_pit_irq = {
- .name = "at91_tick",
- .flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
- .handler = at91sam926x_pit_interrupt,
-- .irq = AT91_ID_SYS,
-+ .irq = NR_IRQS_LEGACY + AT91_ID_SYS,
- };
-
- static void at91sam926x_pit_reset(void)
-diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
-index f205449..55d2959 100644
---- a/arch/arm/mach-at91/at91sam9g45.c
-+++ b/arch/arm/mach-at91/at91sam9g45.c
-@@ -18,6 +18,7 @@
- #include <asm/mach/map.h>
- #include <asm/system_misc.h>
- #include <mach/at91sam9g45.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91_pmc.h>
- #include <mach/cpu.h>
-
-diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
-index 35bd42d..7a3f0b3 100644
---- a/arch/arm/mach-at91/at91sam9g45_devices.c
-+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
-@@ -50,8 +50,8 @@ static struct resource hdmac_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_DMA,
-- .end = AT91SAM9G45_ID_DMA,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_DMA,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_DMA,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -91,8 +91,8 @@ static struct resource usbh_ohci_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_UHPHS,
-- .end = AT91SAM9G45_ID_UHPHS,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -153,8 +153,8 @@ static struct resource usbh_ehci_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_UHPHS,
-- .end = AT91SAM9G45_ID_UHPHS,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -210,8 +210,8 @@ static struct resource usba_udc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [2] = {
-- .start = AT91SAM9G45_ID_UDPHS,
-- .end = AT91SAM9G45_ID_UDPHS,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_UDPHS,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_UDPHS,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -293,8 +293,8 @@ static struct resource eth_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_EMAC,
-- .end = AT91SAM9G45_ID_EMAC,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_EMAC,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_EMAC,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -367,8 +367,8 @@ static struct resource mmc0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_MCI0,
-- .end = AT91SAM9G45_ID_MCI0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -392,8 +392,8 @@ static struct resource mmc1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_MCI1,
-- .end = AT91SAM9G45_ID_MCI1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -643,8 +643,8 @@ static struct resource twi0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_TWI0,
-- .end = AT91SAM9G45_ID_TWI0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -663,8 +663,8 @@ static struct resource twi1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_TWI1,
-- .end = AT91SAM9G45_ID_TWI1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -718,8 +718,8 @@ static struct resource spi0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_SPI0,
-- .end = AT91SAM9G45_ID_SPI0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -744,8 +744,8 @@ static struct resource spi1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_SPI1,
-- .end = AT91SAM9G45_ID_SPI1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -832,8 +832,8 @@ static struct resource ac97_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_AC97C,
-- .end = AT91SAM9G45_ID_AC97C,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_AC97C,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_AC97C,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -885,8 +885,8 @@ struct resource isi_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_ISI,
-- .end = AT91SAM9G45_ID_ISI,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_ISI,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_ISI,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -977,8 +977,8 @@ static struct resource lcdc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_LCDC,
-- .end = AT91SAM9G45_ID_LCDC,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_LCDC,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_LCDC,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1052,8 +1052,8 @@ static struct resource tcb0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_TCB,
-- .end = AT91SAM9G45_ID_TCB,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1073,8 +1073,8 @@ static struct resource tcb1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_TCB,
-- .end = AT91SAM9G45_ID_TCB,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1108,8 +1108,8 @@ static struct resource rtc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91_ID_SYS,
-- .end = AT91_ID_SYS,
-+ .start = NR_IRQS_LEGACY + AT91_ID_SYS,
-+ .end = NR_IRQS_LEGACY + AT91_ID_SYS,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1145,8 +1145,8 @@ static struct resource tsadcc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_TSC,
-- .end = AT91SAM9G45_ID_TSC,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_TSC,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_TSC,
- .flags = IORESOURCE_IRQ,
- }
- };
-@@ -1300,8 +1300,8 @@ static struct resource pwm_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_PWMC,
-- .end = AT91SAM9G45_ID_PWMC,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_PWMC,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_PWMC,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1353,8 +1353,8 @@ static struct resource ssc0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_SSC0,
-- .end = AT91SAM9G45_ID_SSC0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1395,8 +1395,8 @@ static struct resource ssc1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_SSC1,
-- .end = AT91SAM9G45_ID_SSC1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1475,8 +1475,8 @@ static struct resource dbgu_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91_ID_SYS,
-- .end = AT91_ID_SYS,
-+ .start = NR_IRQS_LEGACY + AT91_ID_SYS,
-+ .end = NR_IRQS_LEGACY + AT91_ID_SYS,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1513,8 +1513,8 @@ static struct resource uart0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_US0,
-- .end = AT91SAM9G45_ID_US0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_US0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_US0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1556,8 +1556,8 @@ static struct resource uart1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_US1,
-- .end = AT91SAM9G45_ID_US1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_US1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_US1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1599,8 +1599,8 @@ static struct resource uart2_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_US2,
-- .end = AT91SAM9G45_ID_US2,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_US2,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_US2,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1642,8 +1642,8 @@ static struct resource uart3_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9G45_ID_US3,
-- .end = AT91SAM9G45_ID_US3,
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_US3,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_US3,
- .flags = IORESOURCE_IRQ,
- },
- };
-diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
-index e420085..72ce50a 100644
---- a/arch/arm/mach-at91/at91sam9rl.c
-+++ b/arch/arm/mach-at91/at91sam9rl.c
-@@ -19,6 +19,7 @@
- #include <mach/cpu.h>
- #include <mach/at91_dbgu.h>
- #include <mach/at91sam9rl.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91_pmc.h>
- #include <mach/at91_rstc.h>
-
-diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
-index 9c0b148..f09fff9 100644
---- a/arch/arm/mach-at91/at91sam9rl_devices.c
-+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
-@@ -41,8 +41,8 @@ static struct resource hdmac_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [2] = {
-- .start = AT91SAM9RL_ID_DMA,
-- .end = AT91SAM9RL_ID_DMA,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_DMA,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_DMA,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -84,8 +84,8 @@ static struct resource usba_udc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [2] = {
-- .start = AT91SAM9RL_ID_UDPHS,
-- .end = AT91SAM9RL_ID_UDPHS,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_UDPHS,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_UDPHS,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -172,8 +172,8 @@ static struct resource mmc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9RL_ID_MCI,
-- .end = AT91SAM9RL_ID_MCI,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_MCI,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_MCI,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -339,8 +339,8 @@ static struct resource twi_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9RL_ID_TWI0,
-- .end = AT91SAM9RL_ID_TWI0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_TWI0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_TWI0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -383,8 +383,8 @@ static struct resource spi_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9RL_ID_SPI,
-- .end = AT91SAM9RL_ID_SPI,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_SPI,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_SPI,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -452,8 +452,8 @@ static struct resource ac97_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9RL_ID_AC97C,
-- .end = AT91SAM9RL_ID_AC97C,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_AC97C,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_AC97C,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -507,8 +507,8 @@ static struct resource lcdc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9RL_ID_LCDC,
-- .end = AT91SAM9RL_ID_LCDC,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_LCDC,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_LCDC,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -574,18 +574,18 @@ static struct resource tcb_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9RL_ID_TC0,
-- .end = AT91SAM9RL_ID_TC0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC0,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
-- .start = AT91SAM9RL_ID_TC1,
-- .end = AT91SAM9RL_ID_TC1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC1,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
-- .start = AT91SAM9RL_ID_TC2,
-- .end = AT91SAM9RL_ID_TC2,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC2,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC2,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -621,8 +621,8 @@ static struct resource tsadcc_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9RL_ID_TSC,
-- .end = AT91SAM9RL_ID_TSC,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_TSC,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_TSC,
- .flags = IORESOURCE_IRQ,
- }
- };
-@@ -768,8 +768,8 @@ static struct resource pwm_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9RL_ID_PWMC,
-- .end = AT91SAM9RL_ID_PWMC,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_PWMC,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_PWMC,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -821,8 +821,8 @@ static struct resource ssc0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9RL_ID_SSC0,
-- .end = AT91SAM9RL_ID_SSC0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -863,8 +863,8 @@ static struct resource ssc1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9RL_ID_SSC1,
-- .end = AT91SAM9RL_ID_SSC1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -943,8 +943,8 @@ static struct resource dbgu_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91_ID_SYS,
-- .end = AT91_ID_SYS,
-+ .start = NR_IRQS_LEGACY + AT91_ID_SYS,
-+ .end = NR_IRQS_LEGACY + AT91_ID_SYS,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -981,8 +981,8 @@ static struct resource uart0_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9RL_ID_US0,
-- .end = AT91SAM9RL_ID_US0,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_US0,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_US0,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1032,8 +1032,8 @@ static struct resource uart1_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9RL_ID_US1,
-- .end = AT91SAM9RL_ID_US1,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_US1,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_US1,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1075,8 +1075,8 @@ static struct resource uart2_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9RL_ID_US2,
-- .end = AT91SAM9RL_ID_US2,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_US2,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_US2,
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -1118,8 +1118,8 @@ static struct resource uart3_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = AT91SAM9RL_ID_US3,
-- .end = AT91SAM9RL_ID_US3,
-+ .start = NR_IRQS_LEGACY + AT91SAM9RL_ID_US3,
-+ .end = NR_IRQS_LEGACY + AT91SAM9RL_ID_US3,
- .flags = IORESOURCE_IRQ,
- },
- };
-diff --git a/arch/arm/mach-at91/at91x40.c b/arch/arm/mach-at91/at91x40.c
-index d62fe09..4c0f5fd 100644
---- a/arch/arm/mach-at91/at91x40.c
-+++ b/arch/arm/mach-at91/at91x40.c
-@@ -17,6 +17,7 @@
- #include <asm/system_misc.h>
- #include <asm/mach/arch.h>
- #include <mach/at91x40.h>
-+#include <mach/at91_aic.h>
- #include <mach/at91_st.h>
- #include <mach/timex.h>
- #include "generic.h"
-diff --git a/arch/arm/mach-at91/include/mach/at91_aic.h b/arch/arm/mach-at91/include/mach/at91_aic.h
-index 7867378..fd42a85 100644
---- a/arch/arm/mach-at91/include/mach/at91_aic.h
-+++ b/arch/arm/mach-at91/include/mach/at91_aic.h
-@@ -28,6 +28,9 @@ extern void __iomem *at91_aic_base;
- .extern at91_aic_base
- #endif
-
-+/* Number of irq lines managed by AIC */
-+#define NR_AIC_IRQS 32
-+
- #define AT91_AIC_IRQ_MIN_PRIORITY 0
- #define AT91_AIC_IRQ_MAX_PRIORITY 7
-
-diff --git a/arch/arm/mach-at91/include/mach/irqs.h b/arch/arm/mach-at91/include/mach/irqs.h
-index 2d510ee..cab60d5 100644
---- a/arch/arm/mach-at91/include/mach/irqs.h
-+++ b/arch/arm/mach-at91/include/mach/irqs.h
-@@ -22,18 +22,6 @@
- #define __ASM_ARCH_IRQS_H
-
- #include <linux/io.h>
--#include <mach/at91_aic.h>
--
--#define NR_AIC_IRQS 32
--
--
--/*
-- * IRQ interrupt symbols are the AT91xxx_ID_* symbols
-- * for IRQs handled directly through the AIC, or else the AT91_PIN_*
-- * symbols in gpio.h for ones handled indirectly as GPIOs.
-- * We make provision for 5 banks of GPIO.
-- */
--#define NR_IRQS (NR_AIC_IRQS + (5 * 32))
-
- /* FIQ is AIC source 0. */
- #define FIQ_START AT91_ID_FIQ
-diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
-index 390d4df..75ca2f4 100644
---- a/arch/arm/mach-at91/irq.c
-+++ b/arch/arm/mach-at91/irq.c
-@@ -41,6 +41,8 @@
- #include <asm/mach/irq.h>
- #include <asm/mach/map.h>
-
-+#include <mach/at91_aic.h>
-+
- void __iomem *at91_aic_base;
- static struct irq_domain *at91_aic_domain;
- static struct device_node *at91_aic_np;
-@@ -302,11 +304,11 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
- */
- for (i = 0; i < NR_AIC_IRQS; i++) {
- /* Put hardware irq number in Source Vector Register: */
-- at91_aic_write(AT91_AIC_SVR(i), i);
-+ at91_aic_write(AT91_AIC_SVR(i), NR_IRQS_LEGACY + i);
- /* Active Low interrupt, with the specified priority */
- at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
-
-- irq_set_chip_and_handler(i, &at91_aic_chip, handle_fasteoi_irq);
-+ irq_set_chip_and_handler(NR_IRQS_LEGACY + i, &at91_aic_chip, handle_fasteoi_irq);
- set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
- }
-
-diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
-index 1bfaad6..2c2d865 100644
---- a/arch/arm/mach-at91/pm.c
-+++ b/arch/arm/mach-at91/pm.c
-@@ -25,6 +25,7 @@
- #include <asm/mach/time.h>
- #include <asm/mach/irq.h>
-
-+#include <mach/at91_aic.h>
- #include <mach/at91_pmc.h>
- #include <mach/cpu.h>
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From eb023f54611256fb88f23973139adb9c7c0b4c7f Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Thu, 14 Jun 2012 15:41:04 +0200
-Subject: ARM: at91: remove mach/irqs.h
-
-commit 4c6971a6debb340d487cf6189f15a1332702330f upstream.
-
-mach/irqs only defines FIQ_START which doesn't appear to be used anywhere
-so remove it.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/include/mach/irqs.h | 29 -----------------------------
- 1 file changed, 29 deletions(-)
- delete mode 100644 arch/arm/mach-at91/include/mach/irqs.h
-
-diff --git a/arch/arm/mach-at91/include/mach/irqs.h b/arch/arm/mach-at91/include/mach/irqs.h
-deleted file mode 100644
-index cab60d5..0000000
---- a/arch/arm/mach-at91/include/mach/irqs.h
-+++ /dev/null
-@@ -1,29 +0,0 @@
--/*
-- * arch/arm/mach-at91/include/mach/irqs.h
-- *
-- * Copyright (C) 2004 SAN People
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-- */
--
--#ifndef __ASM_ARCH_IRQS_H
--#define __ASM_ARCH_IRQS_H
--
--#include <linux/io.h>
--
--/* FIQ is AIC source 0. */
--#define FIQ_START AT91_ID_FIQ
--
--#endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 908da403154b9fc68fdefdca20cc4049cd13c7b9 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Wed, 30 May 2012 10:01:09 +0200
-Subject: ARM: at91: add AIC5 support
-
-commit c4b68520dc0ec96153bc0d87bca5ffba508edfcf upstream.
-
-The number of lines of AIC5 has increased from 32 to 128. Due to this
-increase, a source select register has been introduced for the interrupt
-line selection. Moreover, register mapping has been changed. For that reasons,
-we need some dedicated callbacks for AIC5.
-Power management is also concerned by these changes. On suspend, we can't get
-the whole interrupt mask register as before, we have to read this register 128
-times. To reduce this overhead, a snapshot of the whole IMR is maintained.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/generic.h | 2 +
- arch/arm/mach-at91/include/mach/at91_aic.h | 26 +++
- arch/arm/mach-at91/irq.c | 343 ++++++++++++++++++++++++-----
- 3 files changed, 314 insertions(+), 57 deletions(-)
-
-diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
-index 0a60bf8..f496506 100644
---- a/arch/arm/mach-at91/generic.h
-+++ b/arch/arm/mach-at91/generic.h
-@@ -29,6 +29,8 @@ extern void __init at91x40_init_interrupts(unsigned int priority[]);
- extern void __init at91_aic_init(unsigned int priority[]);
- extern int __init at91_aic_of_init(struct device_node *node,
- struct device_node *parent);
-+extern int __init at91_aic5_of_init(struct device_node *node,
-+ struct device_node *parent);
-
-
- /* Timer */
-diff --git a/arch/arm/mach-at91/include/mach/at91_aic.h b/arch/arm/mach-at91/include/mach/at91_aic.h
-index fd42a85..eaea661 100644
---- a/arch/arm/mach-at91/include/mach/at91_aic.h
-+++ b/arch/arm/mach-at91/include/mach/at91_aic.h
-@@ -30,11 +30,16 @@ extern void __iomem *at91_aic_base;
-
- /* Number of irq lines managed by AIC */
- #define NR_AIC_IRQS 32
-+#define NR_AIC5_IRQS 128
-+
-+#define AT91_AIC5_SSR 0x0 /* Source Select Register [AIC5] */
-+#define AT91_AIC5_INTSEL_MSK (0x7f << 0) /* Interrupt Line Selection Mask */
-
- #define AT91_AIC_IRQ_MIN_PRIORITY 0
- #define AT91_AIC_IRQ_MAX_PRIORITY 7
-
- #define AT91_AIC_SMR(n) ((n) * 4) /* Source Mode Registers 0-31 */
-+#define AT91_AIC5_SMR 0x4 /* Source Mode Register [AIC5] */
- #define AT91_AIC_PRIOR (7 << 0) /* Priority Level */
- #define AT91_AIC_SRCTYPE (3 << 5) /* Interrupt Source Type */
- #define AT91_AIC_SRCTYPE_LOW (0 << 5)
-@@ -43,31 +48,52 @@ extern void __iomem *at91_aic_base;
- #define AT91_AIC_SRCTYPE_RISING (3 << 5)
-
- #define AT91_AIC_SVR(n) (0x80 + ((n) * 4)) /* Source Vector Registers 0-31 */
-+#define AT91_AIC5_SVR 0x8 /* Source Vector Register [AIC5] */
- #define AT91_AIC_IVR 0x100 /* Interrupt Vector Register */
-+#define AT91_AIC5_IVR 0x10 /* Interrupt Vector Register [AIC5] */
- #define AT91_AIC_FVR 0x104 /* Fast Interrupt Vector Register */
-+#define AT91_AIC5_FVR 0x14 /* Fast Interrupt Vector Register [AIC5] */
- #define AT91_AIC_ISR 0x108 /* Interrupt Status Register */
-+#define AT91_AIC5_ISR 0x18 /* Interrupt Status Register [AIC5] */
- #define AT91_AIC_IRQID (0x1f << 0) /* Current Interrupt Identifier */
-
- #define AT91_AIC_IPR 0x10c /* Interrupt Pending Register */
-+#define AT91_AIC5_IPR0 0x20 /* Interrupt Pending Register 0 [AIC5] */
-+#define AT91_AIC5_IPR1 0x24 /* Interrupt Pending Register 1 [AIC5] */
-+#define AT91_AIC5_IPR2 0x28 /* Interrupt Pending Register 2 [AIC5] */
-+#define AT91_AIC5_IPR3 0x2c /* Interrupt Pending Register 3 [AIC5] */
- #define AT91_AIC_IMR 0x110 /* Interrupt Mask Register */
-+#define AT91_AIC5_IMR 0x30 /* Interrupt Mask Register [AIC5] */
- #define AT91_AIC_CISR 0x114 /* Core Interrupt Status Register */
-+#define AT91_AIC5_CISR 0x34 /* Core Interrupt Status Register [AIC5] */
- #define AT91_AIC_NFIQ (1 << 0) /* nFIQ Status */
- #define AT91_AIC_NIRQ (1 << 1) /* nIRQ Status */
-
- #define AT91_AIC_IECR 0x120 /* Interrupt Enable Command Register */
-+#define AT91_AIC5_IECR 0x40 /* Interrupt Enable Command Register [AIC5] */
- #define AT91_AIC_IDCR 0x124 /* Interrupt Disable Command Register */
-+#define AT91_AIC5_IDCR 0x44 /* Interrupt Disable Command Register [AIC5] */
- #define AT91_AIC_ICCR 0x128 /* Interrupt Clear Command Register */
-+#define AT91_AIC5_ICCR 0x48 /* Interrupt Clear Command Register [AIC5] */
- #define AT91_AIC_ISCR 0x12c /* Interrupt Set Command Register */
-+#define AT91_AIC5_ISCR 0x4c /* Interrupt Set Command Register [AIC5] */
- #define AT91_AIC_EOICR 0x130 /* End of Interrupt Command Register */
-+#define AT91_AIC5_EOICR 0x38 /* End of Interrupt Command Register [AIC5] */
- #define AT91_AIC_SPU 0x134 /* Spurious Interrupt Vector Register */
-+#define AT91_AIC5_SPU 0x3c /* Spurious Interrupt Vector Register [AIC5] */
- #define AT91_AIC_DCR 0x138 /* Debug Control Register */
-+#define AT91_AIC5_DCR 0x6c /* Debug Control Register [AIC5] */
- #define AT91_AIC_DCR_PROT (1 << 0) /* Protection Mode */
- #define AT91_AIC_DCR_GMSK (1 << 1) /* General Mask */
-
- #define AT91_AIC_FFER 0x140 /* Fast Forcing Enable Register [SAM9 only] */
-+#define AT91_AIC5_FFER 0x50 /* Fast Forcing Enable Register [AIC5] */
- #define AT91_AIC_FFDR 0x144 /* Fast Forcing Disable Register [SAM9 only] */
-+#define AT91_AIC5_FFDR 0x54 /* Fast Forcing Disable Register [AIC5] */
- #define AT91_AIC_FFSR 0x148 /* Fast Forcing Status Register [SAM9 only] */
-+#define AT91_AIC5_FFSR 0x58 /* Fast Forcing Status Register [AIC5] */
-
- void at91_aic_handle_irq(struct pt_regs *regs);
-+void at91_aic5_handle_irq(struct pt_regs *regs);
-
- #endif
-diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
-index 75ca2f4..c5eaaa0 100644
---- a/arch/arm/mach-at91/irq.c
-+++ b/arch/arm/mach-at91/irq.c
-@@ -23,6 +23,7 @@
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/mm.h>
-+#include <linux/bitmap.h>
- #include <linux/types.h>
- #include <linux/irq.h>
- #include <linux/of.h>
-@@ -46,9 +47,116 @@
- void __iomem *at91_aic_base;
- static struct irq_domain *at91_aic_domain;
- static struct device_node *at91_aic_np;
-+static unsigned int n_irqs = NR_AIC_IRQS;
-+static unsigned long at91_aic_caps = 0;
- static unsigned int *at91_aic_irq_priorities;
-
--asmlinkage void __exception_irq_entry at91_aic_handle_irq(struct pt_regs *regs)
-+/* AIC5 introduces a Source Select Register */
-+#define AT91_AIC_CAP_AIC5 (1 << 0)
-+#define has_aic5() (at91_aic_caps & AT91_AIC_CAP_AIC5)
-+
-+#ifdef CONFIG_PM
-+
-+static unsigned long *wakeups;
-+static unsigned long *backups;
-+
-+#define set_backup(bit) set_bit(bit, backups)
-+#define clear_backup(bit) clear_bit(bit, backups)
-+
-+static int at91_aic_pm_init(void)
-+{
-+ backups = kzalloc(BITS_TO_LONGS(n_irqs) * sizeof(*backups), GFP_KERNEL);
-+ if (!backups)
-+ return -ENOMEM;
-+
-+ wakeups = kzalloc(BITS_TO_LONGS(n_irqs) * sizeof(*backups), GFP_KERNEL);
-+ if (!wakeups) {
-+ kfree(backups);
-+ return -ENOMEM;
-+ }
-+
-+ return 0;
-+}
-+
-+static int at91_aic_set_wake(struct irq_data *d, unsigned value)
-+{
-+ if (unlikely(d->hwirq >= n_irqs))
-+ return -EINVAL;
-+
-+ if (value)
-+ set_bit(d->hwirq, wakeups);
-+ else
-+ clear_bit(d->hwirq, wakeups);
-+
-+ return 0;
-+}
-+
-+void at91_irq_suspend(void)
-+{
-+ int i = 0, bit;
-+
-+ if (has_aic5()) {
-+ /* disable enabled irqs */
-+ while ((bit = find_next_bit(backups, n_irqs, i)) < n_irqs) {
-+ at91_aic_write(AT91_AIC5_SSR,
-+ bit & AT91_AIC5_INTSEL_MSK);
-+ at91_aic_write(AT91_AIC5_IDCR, 1);
-+ i = bit;
-+ }
-+ /* enable wakeup irqs */
-+ i = 0;
-+ while ((bit = find_next_bit(wakeups, n_irqs, i)) < n_irqs) {
-+ at91_aic_write(AT91_AIC5_SSR,
-+ bit & AT91_AIC5_INTSEL_MSK);
-+ at91_aic_write(AT91_AIC5_IECR, 1);
-+ i = bit;
-+ }
-+ } else {
-+ at91_aic_write(AT91_AIC_IDCR, *backups);
-+ at91_aic_write(AT91_AIC_IECR, *wakeups);
-+ }
-+}
-+
-+void at91_irq_resume(void)
-+{
-+ int i = 0, bit;
-+
-+ if (has_aic5()) {
-+ /* disable wakeup irqs */
-+ while ((bit = find_next_bit(wakeups, n_irqs, i)) < n_irqs) {
-+ at91_aic_write(AT91_AIC5_SSR,
-+ bit & AT91_AIC5_INTSEL_MSK);
-+ at91_aic_write(AT91_AIC5_IDCR, 1);
-+ i = bit;
-+ }
-+ /* enable irqs disabled for suspend */
-+ i = 0;
-+ while ((bit = find_next_bit(backups, n_irqs, i)) < n_irqs) {
-+ at91_aic_write(AT91_AIC5_SSR,
-+ bit & AT91_AIC5_INTSEL_MSK);
-+ at91_aic_write(AT91_AIC5_IECR, 1);
-+ i = bit;
-+ }
-+ } else {
-+ at91_aic_write(AT91_AIC_IDCR, *wakeups);
-+ at91_aic_write(AT91_AIC_IECR, *backups);
-+ }
-+}
-+
-+#else
-+static inline int at91_aic_pm_init(void)
-+{
-+ return 0;
-+}
-+
-+#define set_backup(bit)
-+#define clear_backup(bit)
-+#define at91_aic_set_wake NULL
-+
-+#endif /* CONFIG_PM */
-+
-+asmlinkage void __exception_irq_entry
-+at91_aic_handle_irq(struct pt_regs *regs)
- {
- u32 irqnr;
- u32 irqstat;
-@@ -66,16 +174,53 @@ asmlinkage void __exception_irq_entry at91_aic_handle_irq(struct pt_regs *regs)
- handle_IRQ(irqnr, regs);
- }
-
-+asmlinkage void __exception_irq_entry
-+at91_aic5_handle_irq(struct pt_regs *regs)
-+{
-+ u32 irqnr;
-+ u32 irqstat;
-+
-+ irqnr = at91_aic_read(AT91_AIC5_IVR);
-+ irqstat = at91_aic_read(AT91_AIC5_ISR);
-+
-+ if (!irqstat)
-+ at91_aic_write(AT91_AIC5_EOICR, 0);
-+ else
-+ handle_IRQ(irqnr, regs);
-+}
-+
- static void at91_aic_mask_irq(struct irq_data *d)
- {
- /* Disable interrupt on AIC */
- at91_aic_write(AT91_AIC_IDCR, 1 << d->hwirq);
-+ /* Update ISR cache */
-+ clear_backup(d->hwirq);
-+}
-+
-+static void __maybe_unused at91_aic5_mask_irq(struct irq_data *d)
-+{
-+ /* Disable interrupt on AIC5 */
-+ at91_aic_write(AT91_AIC5_SSR, d->hwirq & AT91_AIC5_INTSEL_MSK);
-+ at91_aic_write(AT91_AIC5_IDCR, 1);
-+ /* Update ISR cache */
-+ clear_backup(d->hwirq);
- }
-
- static void at91_aic_unmask_irq(struct irq_data *d)
- {
- /* Enable interrupt on AIC */
- at91_aic_write(AT91_AIC_IECR, 1 << d->hwirq);
-+ /* Update ISR cache */
-+ set_backup(d->hwirq);
-+}
-+
-+static void __maybe_unused at91_aic5_unmask_irq(struct irq_data *d)
-+{
-+ /* Enable interrupt on AIC5 */
-+ at91_aic_write(AT91_AIC5_SSR, d->hwirq & AT91_AIC5_INTSEL_MSK);
-+ at91_aic_write(AT91_AIC5_IECR, 1);
-+ /* Update ISR cache */
-+ set_backup(d->hwirq);
- }
-
- static void at91_aic_eoi(struct irq_data *d)
-@@ -87,13 +232,18 @@ static void at91_aic_eoi(struct irq_data *d)
- at91_aic_write(AT91_AIC_EOICR, 0);
- }
-
--unsigned int at91_extern_irq;
-+static void __maybe_unused at91_aic5_eoi(struct irq_data *d)
-+{
-+ at91_aic_write(AT91_AIC5_EOICR, 0);
-+}
-
--#define is_extern_irq(hwirq) ((1 << (hwirq)) & at91_extern_irq)
-+unsigned long *at91_extern_irq;
-
--static int at91_aic_set_type(struct irq_data *d, unsigned type)
-+#define is_extern_irq(hwirq) test_bit(hwirq, at91_extern_irq)
-+
-+static int at91_aic_compute_srctype(struct irq_data *d, unsigned type)
- {
-- unsigned int smr, srctype;
-+ int srctype;
-
- switch (type) {
- case IRQ_TYPE_LEVEL_HIGH:
-@@ -106,58 +256,44 @@ static int at91_aic_set_type(struct irq_data *d, unsigned type)
- if ((d->hwirq == AT91_ID_FIQ) || is_extern_irq(d->hwirq)) /* only supported on external interrupts */
- srctype = AT91_AIC_SRCTYPE_LOW;
- else
-- return -EINVAL;
-+ srctype = -EINVAL;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- if ((d->hwirq == AT91_ID_FIQ) || is_extern_irq(d->hwirq)) /* only supported on external interrupts */
- srctype = AT91_AIC_SRCTYPE_FALLING;
- else
-- return -EINVAL;
-+ srctype = -EINVAL;
- break;
- default:
-- return -EINVAL;
-+ srctype = -EINVAL;
- }
-
-- smr = at91_aic_read(AT91_AIC_SMR(d->hwirq)) & ~AT91_AIC_SRCTYPE;
-- at91_aic_write(AT91_AIC_SMR(d->hwirq), smr | srctype);
-- return 0;
-+ return srctype;
- }
-
--#ifdef CONFIG_PM
--
--static u32 wakeups;
--static u32 backups;
--
--static int at91_aic_set_wake(struct irq_data *d, unsigned value)
-+static int at91_aic_set_type(struct irq_data *d, unsigned type)
- {
-- if (unlikely(d->hwirq >= NR_AIC_IRQS))
-- return -EINVAL;
--
-- if (value)
-- wakeups |= (1 << d->hwirq);
-- else
-- wakeups &= ~(1 << d->hwirq);
-+ unsigned int smr;
-+ int srctype;
-+
-+ srctype = at91_aic_compute_srctype(d, type);
-+ if (srctype < 0)
-+ return srctype;
-+
-+ if (has_aic5()) {
-+ at91_aic_write(AT91_AIC5_SSR,
-+ d->hwirq & AT91_AIC5_INTSEL_MSK);
-+ smr = at91_aic_read(AT91_AIC5_SMR) & ~AT91_AIC_SRCTYPE;
-+ at91_aic_write(AT91_AIC5_SMR, smr | srctype);
-+ } else {
-+ smr = at91_aic_read(AT91_AIC_SMR(d->hwirq))
-+ & ~AT91_AIC_SRCTYPE;
-+ at91_aic_write(AT91_AIC_SMR(d->hwirq), smr | srctype);
-+ }
-
- return 0;
- }
-
--void at91_irq_suspend(void)
--{
-- backups = at91_aic_read(AT91_AIC_IMR);
-- at91_aic_write(AT91_AIC_IDCR, backups);
-- at91_aic_write(AT91_AIC_IECR, wakeups);
--}
--
--void at91_irq_resume(void)
--{
-- at91_aic_write(AT91_AIC_IDCR, wakeups);
-- at91_aic_write(AT91_AIC_IECR, backups);
--}
--
--#else
--#define at91_aic_set_wake NULL
--#endif
--
- static struct irq_chip at91_aic_chip = {
- .name = "AIC",
- .irq_mask = at91_aic_mask_irq,
-@@ -193,6 +329,35 @@ static void __init at91_aic_hw_init(unsigned int spu_vector)
- at91_aic_write(AT91_AIC_ICCR, 0xFFFFFFFF);
- }
-
-+static void __init __maybe_unused at91_aic5_hw_init(unsigned int spu_vector)
-+{
-+ int i;
-+
-+ /*
-+ * Perform 8 End Of Interrupt Command to make sure AIC
-+ * will not Lock out nIRQ
-+ */
-+ for (i = 0; i < 8; i++)
-+ at91_aic_write(AT91_AIC5_EOICR, 0);
-+
-+ /*
-+ * Spurious Interrupt ID in Spurious Vector Register.
-+ * When there is no current interrupt, the IRQ Vector Register
-+ * reads the value stored in AIC_SPU
-+ */
-+ at91_aic_write(AT91_AIC5_SPU, spu_vector);
-+
-+ /* No debugging in AIC: Debug (Protect) Control Register */
-+ at91_aic_write(AT91_AIC5_DCR, 0);
-+
-+ /* Disable and clear all interrupts initially */
-+ for (i = 0; i < n_irqs; i++) {
-+ at91_aic_write(AT91_AIC5_SSR, i & AT91_AIC5_INTSEL_MSK);
-+ at91_aic_write(AT91_AIC5_IDCR, 1);
-+ at91_aic_write(AT91_AIC5_ICCR, 1);
-+ }
-+}
-+
- #if defined(CONFIG_OF)
- static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t hw)
-@@ -210,13 +375,31 @@ static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq,
- return 0;
- }
-
-+static int at91_aic5_irq_map(struct irq_domain *h, unsigned int virq,
-+ irq_hw_number_t hw)
-+{
-+ at91_aic_write(AT91_AIC5_SSR, hw & AT91_AIC5_INTSEL_MSK);
-+
-+ /* Put virq number in Source Vector Register */
-+ at91_aic_write(AT91_AIC5_SVR, virq);
-+
-+ /* Active Low interrupt, with priority */
-+ at91_aic_write(AT91_AIC5_SMR,
-+ AT91_AIC_SRCTYPE_LOW | at91_aic_irq_priorities[hw]);
-+
-+ irq_set_chip_and_handler(virq, &at91_aic_chip, handle_fasteoi_irq);
-+ set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
-+
-+ return 0;
-+}
-+
- static int at91_aic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
- const u32 *intspec, unsigned int intsize,
- irq_hw_number_t *out_hwirq, unsigned int *out_type)
- {
- if (WARN_ON(intsize < 3))
- return -EINVAL;
-- if (WARN_ON(intspec[0] >= NR_AIC_IRQS))
-+ if (WARN_ON(intspec[0] >= n_irqs))
- return -EINVAL;
- if (WARN_ON((intspec[2] < AT91_AIC_IRQ_MIN_PRIORITY)
- || (intspec[2] > AT91_AIC_IRQ_MAX_PRIORITY)))
-@@ -234,14 +417,24 @@ static struct irq_domain_ops at91_aic_irq_ops = {
- .xlate = at91_aic_irq_domain_xlate,
- };
-
--int __init at91_aic_of_init(struct device_node *node,
-- struct device_node *parent)
-+int __init at91_aic_of_common_init(struct device_node *node,
-+ struct device_node *parent)
- {
- struct property *prop;
- const __be32 *p;
- u32 val;
-
-- at91_aic_irq_priorities = kzalloc(NR_AIC_IRQS
-+ at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs)
-+ * sizeof(*at91_extern_irq), GFP_KERNEL);
-+ if (!at91_extern_irq)
-+ return -ENOMEM;
-+
-+ if (at91_aic_pm_init()) {
-+ kfree(at91_extern_irq);
-+ return -ENOMEM;
-+ }
-+
-+ at91_aic_irq_priorities = kzalloc(n_irqs
- * sizeof(*at91_aic_irq_priorities),
- GFP_KERNEL);
- if (!at91_aic_irq_priorities)
-@@ -250,22 +443,56 @@ int __init at91_aic_of_init(struct device_node *node,
- at91_aic_base = of_iomap(node, 0);
- at91_aic_np = node;
-
-- at91_aic_domain = irq_domain_add_linear(at91_aic_np, NR_AIC_IRQS,
-+ at91_aic_domain = irq_domain_add_linear(at91_aic_np, n_irqs,
- &at91_aic_irq_ops, NULL);
- if (!at91_aic_domain)
- panic("Unable to add AIC irq domain (DT)\n");
-
-- at91_extern_irq = 0;
- of_property_for_each_u32(node, "atmel,external-irqs", prop, p, val) {
-- if (val > 31)
-- pr_warn("AIC: external irq %d > 31 skip it\n", val);
-+ if (val >= n_irqs)
-+ pr_warn("AIC: external irq %d >= %d skip it\n",
-+ val, n_irqs);
- else
-- at91_extern_irq |= (1 << val);
-+ set_bit(val, at91_extern_irq);
- }
-
- irq_set_default_host(at91_aic_domain);
-
-- at91_aic_hw_init(NR_AIC_IRQS);
-+ return 0;
-+}
-+
-+int __init at91_aic_of_init(struct device_node *node,
-+ struct device_node *parent)
-+{
-+ int err;
-+
-+ err = at91_aic_of_common_init(node, parent);
-+ if (err)
-+ return err;
-+
-+ at91_aic_hw_init(n_irqs);
-+
-+ return 0;
-+}
-+
-+int __init at91_aic5_of_init(struct device_node *node,
-+ struct device_node *parent)
-+{
-+ int err;
-+
-+ at91_aic_caps |= AT91_AIC_CAP_AIC5;
-+ n_irqs = NR_AIC5_IRQS;
-+ at91_aic_chip.irq_ack = at91_aic5_mask_irq;
-+ at91_aic_chip.irq_mask = at91_aic5_mask_irq;
-+ at91_aic_chip.irq_unmask = at91_aic5_unmask_irq;
-+ at91_aic_chip.irq_eoi = at91_aic5_eoi;
-+ at91_aic_irq_ops.map = at91_aic5_irq_map;
-+
-+ err = at91_aic_of_common_init(node, parent);
-+ if (err)
-+ return err;
-+
-+ at91_aic5_hw_init(n_irqs);
-
- return 0;
- }
-@@ -274,22 +501,25 @@ int __init at91_aic_of_init(struct device_node *node,
- /*
- * Initialize the AIC interrupt controller.
- */
--void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
-+void __init at91_aic_init(unsigned int *priority)
- {
- unsigned int i;
- int irq_base;
-
-+ if (at91_aic_pm_init())
-+ panic("Unable to allocate bit maps\n");
-+
- at91_aic_base = ioremap(AT91_AIC, 512);
- if (!at91_aic_base)
- panic("Unable to ioremap AIC registers\n");
-
- /* Add irq domain for AIC */
-- irq_base = irq_alloc_descs(-1, 0, NR_AIC_IRQS, 0);
-+ irq_base = irq_alloc_descs(-1, 0, n_irqs, 0);
- if (irq_base < 0) {
- WARN(1, "Cannot allocate irq_descs, assuming pre-allocated\n");
- irq_base = 0;
- }
-- at91_aic_domain = irq_domain_add_legacy(at91_aic_np, NR_AIC_IRQS,
-+ at91_aic_domain = irq_domain_add_legacy(at91_aic_np, n_irqs,
- irq_base, 0,
- &irq_domain_simple_ops, NULL);
-
-@@ -302,15 +532,14 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
- * The IVR is used by macro get_irqnr_and_base to read and verify.
- * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred.
- */
-- for (i = 0; i < NR_AIC_IRQS; i++) {
-+ for (i = 0; i < n_irqs; i++) {
- /* Put hardware irq number in Source Vector Register: */
- at91_aic_write(AT91_AIC_SVR(i), NR_IRQS_LEGACY + i);
- /* Active Low interrupt, with the specified priority */
- at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
--
- irq_set_chip_and_handler(NR_IRQS_LEGACY + i, &at91_aic_chip, handle_fasteoi_irq);
- set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
- }
-
-- at91_aic_hw_init(NR_AIC_IRQS);
-+ at91_aic_hw_init(n_irqs);
- }
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 269418c20b0c2e0aaa9da1e46b110a4c9f4b90f9 Mon Sep 17 00:00:00 2001
-From: Stephen Warren <swarren@nvidia.com>
-Date: Wed, 4 Apr 2012 09:27:46 -0600
-Subject: dt: add property iteration helpers
-
-commit c541adc637066407d4cda9db14dcb0e618966a4c upstream.
-
-This patch adds macros of_property_for_each_u32() and
-of_property_for_each_string(), which iterate over an array of values
-within a device-tree property. Usage is for example:
-
-struct property *prop;
-const __be32 *p;
-u32 u;
-of_property_for_each_u32(np, "propname", prop, p, u)
- printk("U32 value: %x\n", u);
-
-struct property *prop;
-const char *s;
-of_property_for_each_string(np, "propname", prop, s)
- printk("String value: %s\n", s);
-
-Based on work by Rob Herring <robherring2@gmail.com>
-
-Cc: Grant Likely <grant.likely@secretlab.ca>
-Signed-off-by: Stephen Warren <swarren@nvidia.com>
-Acked-by: Rob Herring <rob.herring@calxeda.com>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- drivers/of/base.c | 41 +++++++++++++++++++++++++++++++++++++++++
- include/linux/of.h | 35 +++++++++++++++++++++++++++++++++++
- 2 files changed, 76 insertions(+)
-
---- a/drivers/of/base.c
-+++ b/drivers/of/base.c
-@@ -1260,3 +1260,44 @@ int of_alias_get_id(struct device_node *
- return id;
- }
- EXPORT_SYMBOL_GPL(of_alias_get_id);
-+
-+const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
-+ u32 *pu)
-+{
-+ const void *curv = cur;
-+
-+ if (!prop)
-+ return NULL;
-+
-+ if (!cur) {
-+ curv = prop->value;
-+ goto out_val;
-+ }
-+
-+ curv += sizeof(*cur);
-+ if (curv >= prop->value + prop->length)
-+ return NULL;
-+
-+out_val:
-+ *pu = be32_to_cpup(curv);
-+ return curv;
-+}
-+EXPORT_SYMBOL_GPL(of_prop_next_u32);
-+
-+const char *of_prop_next_string(struct property *prop, const char *cur)
-+{
-+ const void *curv = cur;
-+
-+ if (!prop)
-+ return NULL;
-+
-+ if (!cur)
-+ return prop->value;
-+
-+ curv += strlen(cur) + 1;
-+ if (curv >= prop->value + prop->length)
-+ return NULL;
-+
-+ return curv;
-+}
-+EXPORT_SYMBOL_GPL(of_prop_next_string);
---- a/include/linux/of.h
-+++ b/include/linux/of.h
-@@ -260,6 +260,37 @@ extern void of_detach_node(struct device
- #endif
-
- #define of_match_ptr(_ptr) (_ptr)
-+
-+/*
-+ * struct property *prop;
-+ * const __be32 *p;
-+ * u32 u;
-+ *
-+ * of_property_for_each_u32(np, "propname", prop, p, u)
-+ * printk("U32 value: %x\n", u);
-+ */
-+const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
-+ u32 *pu);
-+#define of_property_for_each_u32(np, propname, prop, p, u) \
-+ for (prop = of_find_property(np, propname, NULL), \
-+ p = of_prop_next_u32(prop, NULL, &u); \
-+ p; \
-+ p = of_prop_next_u32(prop, p, &u))
-+
-+/*
-+ * struct property *prop;
-+ * const char *s;
-+ *
-+ * of_property_for_each_string(np, "propname", prop, s)
-+ * printk("String value: %s\n", s);
-+ */
-+const char *of_prop_next_string(struct property *prop, const char *cur);
-+#define of_property_for_each_string(np, propname, prop, s) \
-+ for (prop = of_find_property(np, propname, NULL), \
-+ s = of_prop_next_string(prop, NULL); \
-+ s; \
-+ s = of_prop_next_string(prop, s))
-+
- #else /* CONFIG_OF */
-
- static inline const char* of_node_full_name(struct device_node *np)
-@@ -355,6 +386,10 @@ static inline int of_machine_is_compatib
-
- #define of_match_ptr(_ptr) NULL
- #define of_match_node(_matches, _node) NULL
-+#define of_property_for_each_u32(np, propname, prop, p, u) \
-+ while (0)
-+#define of_property_for_each_string(np, propname, prop, s) \
-+ while (0)
- #endif /* CONFIG_OF */
-
- #ifndef of_node_to_nid
+++ /dev/null
-From b6a60e81276efc7c6aa5f37f50f52ac0d8391187 Mon Sep 17 00:00:00 2001
-From: Arnd Bergmann <arnd@arndb.de>
-Date: Wed, 4 Jul 2012 07:45:16 +0000
-Subject: ARM: at91: fix new build errors
-
-commit 14070ade02cc378bc30dae383532768a94805988 upstream.
-
-MULTI_IRQ_HANDLER and SPARSE_IRQ are now required everywhere because
-mach/irqs.h and mach/entry-macros.S are gone but the symbols are
-only selected for AT91SAM9, not for the NOMMU parts.
-
-A few files now need to include linux/io.h directly, which used to
-be included through other headers that have changed.
-
-The new at91_aic_irq_priorities variable is only used with CONFIG_OF
-enabled and should not be visible otherwise.
-
-Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-Acked-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/Kconfig | 4 ++++
- arch/arm/mach-at91/at91x40.c | 1 +
- arch/arm/mach-at91/irq.c | 3 ++-
- drivers/rtc/rtc-at91rm9200.c | 1 +
- 4 files changed, 8 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
-index 7d0c40a..c8050b1 100644
---- a/arch/arm/mach-at91/Kconfig
-+++ b/arch/arm/mach-at91/Kconfig
-@@ -37,6 +37,8 @@ config SOC_AT91SAM9
- config SOC_AT91RM9200
- bool "AT91RM9200"
- select CPU_ARM920T
-+ select MULTI_IRQ_HANDLER
-+ select SPARSE_IRQ
- select GENERIC_CLOCKEVENTS
- select HAVE_AT91_DBGU0
-
-@@ -142,6 +144,8 @@ config ARCH_AT91SAM9G45
- config ARCH_AT91X40
- bool "AT91x40"
- depends on !MMU
-+ select MULTI_IRQ_HANDLER
-+ select SPARSE_IRQ
- select ARCH_USES_GETTIMEOFFSET
-
- endchoice
-diff --git a/arch/arm/mach-at91/at91x40.c b/arch/arm/mach-at91/at91x40.c
-index 4c0f5fd..46090e6 100644
---- a/arch/arm/mach-at91/at91x40.c
-+++ b/arch/arm/mach-at91/at91x40.c
-@@ -13,6 +13,7 @@
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/irq.h>
-+#include <linux/io.h>
- #include <asm/proc-fns.h>
- #include <asm/system_misc.h>
- #include <asm/mach/arch.h>
-diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
-index c5eaaa0..1e02c0e 100644
---- a/arch/arm/mach-at91/irq.c
-+++ b/arch/arm/mach-at91/irq.c
-@@ -49,7 +49,6 @@ static struct irq_domain *at91_aic_domain;
- static struct device_node *at91_aic_np;
- static unsigned int n_irqs = NR_AIC_IRQS;
- static unsigned long at91_aic_caps = 0;
--static unsigned int *at91_aic_irq_priorities;
-
- /* AIC5 introduces a Source Select Register */
- #define AT91_AIC_CAP_AIC5 (1 << 0)
-@@ -359,6 +358,8 @@ static void __init __maybe_unused at91_aic5_hw_init(unsigned int spu_vector)
- }
-
- #if defined(CONFIG_OF)
-+static unsigned int *at91_aic_irq_priorities;
-+
- static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t hw)
- {
-diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
-index f02acb0..a4c78c0 100644
---- a/drivers/rtc/rtc-at91rm9200.c
-+++ b/drivers/rtc/rtc-at91rm9200.c
-@@ -27,6 +27,7 @@
- #include <linux/interrupt.h>
- #include <linux/ioctl.h>
- #include <linux/completion.h>
-+#include <linux/io.h>
-
- #include <asm/io.h>
- #include <asm/uaccess.h>
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 8784aa5855d4f4ebc018df2ee43a143c7560ba37 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 10 May 2012 12:17:39 +0200
-Subject: dmaengine: at_hdmac: remove some at_dma_slave comments
-
-commit b89a9cb4027a498de7dad12a68b06ae1b254042c upstream.
-
-These comments were covering removed struct at_dma_slave fields.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
----
- arch/arm/mach-at91/include/mach/at_hdmac.h | 5 -----
- 1 file changed, 5 deletions(-)
-
-diff --git a/arch/arm/mach-at91/include/mach/at_hdmac.h b/arch/arm/mach-at91/include/mach/at_hdmac.h
-index fff48d1..810a13e 100644
---- a/arch/arm/mach-at91/include/mach/at_hdmac.h
-+++ b/arch/arm/mach-at91/include/mach/at_hdmac.h
-@@ -26,11 +26,6 @@ struct at_dma_platform_data {
- /**
- * struct at_dma_slave - Controller-specific information about a slave
- * @dma_dev: required DMA master device
-- * @tx_reg: physical address of data register used for
-- * memory-to-peripheral transfers
-- * @rx_reg: physical address of data register used for
-- * peripheral-to-memory transfers
-- * @reg_width: peripheral register width
- * @cfg: Platform-specific initializer for the CFG register
- * @ctrla: Platform-specific initializer for the CTRLA register
- */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 7d5ebe64bdd79c895951ec7d72425f7806b14fbd Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 10 May 2012 12:17:40 +0200
-Subject: dmaengine: at_hdmac: remove ATC_DEFAULT_CTRLA constant
-
-commit b409ebfb14a71b64e11b156dc82ede698480397e upstream.
-
-Not needed constant that was set to 0.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
----
- drivers/dma/at_hdmac.c | 12 +++++-------
- 1 file changed, 5 insertions(+), 7 deletions(-)
-
---- a/drivers/dma/at_hdmac.c
-+++ b/drivers/dma/at_hdmac.c
-@@ -39,7 +39,6 @@
- */
-
- #define ATC_DEFAULT_CFG (ATC_FIFOCFG_HALFFIFO)
--#define ATC_DEFAULT_CTRLA (0)
- #define ATC_DEFAULT_CTRLB (ATC_SIF(AT_DMA_MEM_IF) \
- |ATC_DIF(AT_DMA_MEM_IF))
-
-@@ -574,7 +573,6 @@ atc_prep_dma_memcpy(struct dma_chan *cha
- return NULL;
- }
-
-- ctrla = ATC_DEFAULT_CTRLA;
- ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN
- | ATC_SRC_ADDR_MODE_INCR
- | ATC_DST_ADDR_MODE_INCR
-@@ -585,13 +583,13 @@ atc_prep_dma_memcpy(struct dma_chan *cha
- * of the most common optimization.
- */
- if (!((src | dest | len) & 3)) {
-- ctrla |= ATC_SRC_WIDTH_WORD | ATC_DST_WIDTH_WORD;
-+ ctrla = ATC_SRC_WIDTH_WORD | ATC_DST_WIDTH_WORD;
- src_width = dst_width = 2;
- } else if (!((src | dest | len) & 1)) {
-- ctrla |= ATC_SRC_WIDTH_HALFWORD | ATC_DST_WIDTH_HALFWORD;
-+ ctrla = ATC_SRC_WIDTH_HALFWORD | ATC_DST_WIDTH_HALFWORD;
- src_width = dst_width = 1;
- } else {
-- ctrla |= ATC_SRC_WIDTH_BYTE | ATC_DST_WIDTH_BYTE;
-+ ctrla = ATC_SRC_WIDTH_BYTE | ATC_DST_WIDTH_BYTE;
- src_width = dst_width = 0;
- }
-
-@@ -668,7 +666,7 @@ atc_prep_slave_sg(struct dma_chan *chan,
- return NULL;
- }
-
-- ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla;
-+ ctrla = atslave->ctrla;
- ctrlb = ATC_IEN;
-
- switch (direction) {
-@@ -812,7 +810,7 @@ atc_dma_cyclic_fill_desc(struct dma_chan
- u32 ctrla;
-
- /* prepare common CRTLA value */
-- ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla
-+ ctrla = atslave->ctrla
- | ATC_DST_WIDTH(reg_width)
- | ATC_SRC_WIDTH(reg_width)
- | period_len >> reg_width;
+++ /dev/null
-From dc894a3e43407b912568b2c3a1fc83585994be14 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 10 May 2012 12:17:41 +0200
-Subject: dmaengine: at_hdmac: take maxburst from slave configuration
-
-commit 1dd1ea8eb46a71201943148cc0ed3182cd04e288 upstream.
-
-The maxburst/chunk size was taken from the private slave DMA data structure.
-Use the common API provided by DMA_SLAVE_CONFIG to setup src/dst maxburst
-values.
-The ctrla field is not needed anymore in the slave private structure nor the
-header constants that were located in an architecture specific directory.
-The at91sam9g45_devices.c file that was using this platform data is also
-modified to remove this now useless data.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
----
- arch/arm/mach-at91/at91sam9g45_devices.c | 1 -
- arch/arm/mach-at91/include/mach/at_hdmac.h | 21 ---------------------
- drivers/dma/at_hdmac.c | 7 ++++---
- drivers/dma/at_hdmac_regs.h | 21 ++++++++++++++++++++-
- 4 files changed, 24 insertions(+), 26 deletions(-)
-
---- a/arch/arm/mach-at91/at91sam9g45_devices.c
-+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
-@@ -433,7 +433,6 @@ void __init at91_add_device_mci(short mm
- atslave->dma_dev = &at_hdmac_device.dev;
- atslave->cfg = ATC_FIFOCFG_HALFFIFO
- | ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW;
-- atslave->ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16;
- if (mmc_id == 0) /* MCI0 */
- atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI0)
- | ATC_DST_PER(AT_DMA_ID_MCI0);
---- a/arch/arm/mach-at91/include/mach/at_hdmac.h
-+++ b/arch/arm/mach-at91/include/mach/at_hdmac.h
-@@ -27,12 +27,10 @@ struct at_dma_platform_data {
- * struct at_dma_slave - Controller-specific information about a slave
- * @dma_dev: required DMA master device
- * @cfg: Platform-specific initializer for the CFG register
-- * @ctrla: Platform-specific initializer for the CTRLA register
- */
- struct at_dma_slave {
- struct device *dma_dev;
- u32 cfg;
-- u32 ctrla;
- };
-
-
-@@ -59,24 +57,5 @@ struct at_dma_slave {
- #define ATC_FIFOCFG_HALFFIFO (0x1 << 28)
- #define ATC_FIFOCFG_ENOUGHSPACE (0x2 << 28)
-
--/* Platform-configurable bits in CTRLA */
--#define ATC_SCSIZE_MASK (0x7 << 16) /* Source Chunk Transfer Size */
--#define ATC_SCSIZE_1 (0x0 << 16)
--#define ATC_SCSIZE_4 (0x1 << 16)
--#define ATC_SCSIZE_8 (0x2 << 16)
--#define ATC_SCSIZE_16 (0x3 << 16)
--#define ATC_SCSIZE_32 (0x4 << 16)
--#define ATC_SCSIZE_64 (0x5 << 16)
--#define ATC_SCSIZE_128 (0x6 << 16)
--#define ATC_SCSIZE_256 (0x7 << 16)
--#define ATC_DCSIZE_MASK (0x7 << 20) /* Destination Chunk Transfer Size */
--#define ATC_DCSIZE_1 (0x0 << 20)
--#define ATC_DCSIZE_4 (0x1 << 20)
--#define ATC_DCSIZE_8 (0x2 << 20)
--#define ATC_DCSIZE_16 (0x3 << 20)
--#define ATC_DCSIZE_32 (0x4 << 20)
--#define ATC_DCSIZE_64 (0x5 << 20)
--#define ATC_DCSIZE_128 (0x6 << 20)
--#define ATC_DCSIZE_256 (0x7 << 20)
-
- #endif /* AT_HDMAC_H */
---- a/drivers/dma/at_hdmac.c
-+++ b/drivers/dma/at_hdmac.c
-@@ -666,7 +666,8 @@ atc_prep_slave_sg(struct dma_chan *chan,
- return NULL;
- }
-
-- ctrla = atslave->ctrla;
-+ ctrla = ATC_SCSIZE(sconfig->src_maxburst)
-+ | ATC_DCSIZE(sconfig->dst_maxburst);
- ctrlb = ATC_IEN;
-
- switch (direction) {
-@@ -805,12 +806,12 @@ atc_dma_cyclic_fill_desc(struct dma_chan
- enum dma_transfer_direction direction)
- {
- struct at_dma_chan *atchan = to_at_dma_chan(chan);
-- struct at_dma_slave *atslave = chan->private;
- struct dma_slave_config *sconfig = &atchan->dma_sconfig;
- u32 ctrla;
-
- /* prepare common CRTLA value */
-- ctrla = atslave->ctrla
-+ ctrla = ATC_SCSIZE(sconfig->src_maxburst)
-+ | ATC_DCSIZE(sconfig->dst_maxburst)
- | ATC_DST_WIDTH(reg_width)
- | ATC_SRC_WIDTH(reg_width)
- | period_len >> reg_width;
---- a/drivers/dma/at_hdmac_regs.h
-+++ b/drivers/dma/at_hdmac_regs.h
-@@ -87,7 +87,26 @@
- /* Bitfields in CTRLA */
- #define ATC_BTSIZE_MAX 0xFFFFUL /* Maximum Buffer Transfer Size */
- #define ATC_BTSIZE(x) (ATC_BTSIZE_MAX & (x)) /* Buffer Transfer Size */
--/* Chunck Tranfer size definitions are in at_hdmac.h */
-+#define ATC_SCSIZE_MASK (0x7 << 16) /* Source Chunk Transfer Size */
-+#define ATC_SCSIZE(x) (ATC_SCSIZE_MASK & ((x) << 16))
-+#define ATC_SCSIZE_1 (0x0 << 16)
-+#define ATC_SCSIZE_4 (0x1 << 16)
-+#define ATC_SCSIZE_8 (0x2 << 16)
-+#define ATC_SCSIZE_16 (0x3 << 16)
-+#define ATC_SCSIZE_32 (0x4 << 16)
-+#define ATC_SCSIZE_64 (0x5 << 16)
-+#define ATC_SCSIZE_128 (0x6 << 16)
-+#define ATC_SCSIZE_256 (0x7 << 16)
-+#define ATC_DCSIZE_MASK (0x7 << 20) /* Destination Chunk Transfer Size */
-+#define ATC_DCSIZE(x) (ATC_DCSIZE_MASK & ((x) << 20))
-+#define ATC_DCSIZE_1 (0x0 << 20)
-+#define ATC_DCSIZE_4 (0x1 << 20)
-+#define ATC_DCSIZE_8 (0x2 << 20)
-+#define ATC_DCSIZE_16 (0x3 << 20)
-+#define ATC_DCSIZE_32 (0x4 << 20)
-+#define ATC_DCSIZE_64 (0x5 << 20)
-+#define ATC_DCSIZE_128 (0x6 << 20)
-+#define ATC_DCSIZE_256 (0x7 << 20)
- #define ATC_SRC_WIDTH_MASK (0x3 << 24) /* Source Single Transfer Size */
- #define ATC_SRC_WIDTH(x) ((x) << 24)
- #define ATC_SRC_WIDTH_BYTE (0x0 << 24)
+++ /dev/null
-From cbf60a8fc3f77c39c2612d91a86797c4153ce4fe Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 12 Jun 2012 10:34:52 +0200
-Subject: dmaengine: at_hdmac: trivial: fix comment in header
-
-commit 9102d8715e5c10db37d81ab75285a2f6746360b2 upstream.
-
-Not all Atmel SoCs were pointed out in header comment which was bringing
-confusion. Remove the truncated list of supported devices, replace by the
-only one that is not supported.
-
-Reported-by: Elen Song <elen.song@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/dma/at_hdmac.c | 7 +++----
- 1 file changed, 3 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
-index 7292aa8..bb16013 100644
---- a/drivers/dma/at_hdmac.c
-+++ b/drivers/dma/at_hdmac.c
-@@ -9,10 +9,9 @@
- * (at your option) any later version.
- *
- *
-- * This supports the Atmel AHB DMA Controller,
-- *
-- * The driver has currently been tested with the Atmel AT91SAM9RL
-- * and AT91SAM9G45 series.
-+ * This supports the Atmel AHB DMA Controller found in several Atmel SoCs.
-+ * The only Atmel DMA Controller that is not covered by this driver is the one
-+ * found on AT91SAM9263.
- */
-
- #include <linux/clk.h>
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 667d21c53f93478f575a888a3258187d401b4305 Mon Sep 17 00:00:00 2001
-From: Andrew Victor <avictor.za@gmail.com>
-Date: Thu, 26 Apr 2012 00:30:42 +0000
-Subject: AT91: Remove fixed mapping for AT91RM9200 ethernet
-
-commit c5f0f83c3be4c965c40c78d52000db30c0ceab5d upstream.
-
-The AT91RM9200 Ethernet controller still has a fixed IO mapping.
-So:
-* Remove the fixed IO mapping and AT91_VA_BASE_EMAC definition.
-* Pass the physical base-address via platform-resources to the driver.
-* Convert at91_ether.c driver to perform an ioremap().
-* Ethernet PHY detection needs to be performed during the driver
-initialization process, it can no longer be done first.
-
-Signed-off-by: Andrew Victor <linux@maxim.org.za>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- arch/arm/mach-at91/at91rm9200.c | 10 -
- arch/arm/mach-at91/at91rm9200_devices.c | 4 +-
- arch/arm/mach-at91/include/mach/hardware.h | 1 -
- drivers/net/ethernet/cadence/at91_ether.c | 527 ++++++++++++++++-------------
- drivers/net/ethernet/cadence/at91_ether.h | 1 +
- 5 files changed, 287 insertions(+), 256 deletions(-)
-
-diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
-index 801c30b..6f50c67 100644
---- a/arch/arm/mach-at91/at91rm9200.c
-+++ b/arch/arm/mach-at91/at91rm9200.c
-@@ -27,15 +27,6 @@
- #include "clock.h"
- #include "sam9_smc.h"
-
--static struct map_desc at91rm9200_io_desc[] __initdata = {
-- {
-- .virtual = AT91_VA_BASE_EMAC,
-- .pfn = __phys_to_pfn(AT91RM9200_BASE_EMAC),
-- .length = SZ_16K,
-- .type = MT_DEVICE,
-- },
--};
--
- /* --------------------------------------------------------------------
- * Clocks
- * -------------------------------------------------------------------- */
-@@ -304,7 +295,6 @@ static void __init at91rm9200_map_io(void)
- {
- /* Map peripherals */
- at91_init_sram(0, AT91RM9200_SRAM_BASE, AT91RM9200_SRAM_SIZE);
-- iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
- }
-
- static void __init at91rm9200_ioremap_registers(void)
-diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
-index 04d69d3..01fb732 100644
---- a/arch/arm/mach-at91/at91rm9200_devices.c
-+++ b/arch/arm/mach-at91/at91rm9200_devices.c
-@@ -140,8 +140,8 @@ static struct macb_platform_data eth_data;
-
- static struct resource eth_resources[] = {
- [0] = {
-- .start = AT91_VA_BASE_EMAC,
-- .end = AT91_VA_BASE_EMAC + SZ_16K - 1,
-+ .start = AT91RM9200_BASE_EMAC,
-+ .end = AT91RM9200_BASE_EMAC + SZ_16K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h
-index 24b46bd..09242b6 100644
---- a/arch/arm/mach-at91/include/mach/hardware.h
-+++ b/arch/arm/mach-at91/include/mach/hardware.h
-@@ -85,7 +85,6 @@
- * Virtual to Physical Address mapping for IO devices.
- */
- #define AT91_VA_BASE_SYS AT91_IO_P2V(AT91_BASE_SYS)
--#define AT91_VA_BASE_EMAC AT91_IO_P2V(AT91RM9200_BASE_EMAC)
-
- /* Internal SRAM is mapped below the IO devices */
- #define AT91_SRAM_MAX SZ_1M
-diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
-index 9061170..62761e1 100644
---- a/drivers/net/ethernet/cadence/at91_ether.c
-+++ b/drivers/net/ethernet/cadence/at91_ether.c
-@@ -30,6 +30,7 @@
- #include <linux/platform_device.h>
- #include <linux/clk.h>
- #include <linux/gfp.h>
-+#include <linux/phy.h>
-
- #include <asm/io.h>
- #include <asm/uaccess.h>
-@@ -51,21 +52,17 @@
- /*
- * Read from a EMAC register.
- */
--static inline unsigned long at91_emac_read(unsigned int reg)
-+static inline unsigned long at91_emac_read(struct at91_private *lp, unsigned int reg)
- {
-- void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC;
--
-- return __raw_readl(emac_base + reg);
-+ return __raw_readl(lp->emac_base + reg);
- }
-
- /*
- * Write to a EMAC register.
- */
--static inline void at91_emac_write(unsigned int reg, unsigned long value)
-+static inline void at91_emac_write(struct at91_private *lp, unsigned int reg, unsigned long value)
- {
-- void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC;
--
-- __raw_writel(value, emac_base + reg);
-+ __raw_writel(value, lp->emac_base + reg);
- }
-
- /* ........................... PHY INTERFACE ........................... */
-@@ -75,32 +72,33 @@ static inline void at91_emac_write(unsigned int reg, unsigned long value)
- * When not called from an interrupt-handler, access to the PHY must be
- * protected by a spinlock.
- */
--static void enable_mdi(void)
-+static void enable_mdi(struct at91_private *lp)
- {
- unsigned long ctl;
-
-- ctl = at91_emac_read(AT91_EMAC_CTL);
-- at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_MPE); /* enable management port */
-+ ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-+ at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_MPE); /* enable management port */
- }
-
- /*
- * Disable the MDIO bit in the MAC control register
- */
--static void disable_mdi(void)
-+static void disable_mdi(struct at91_private *lp)
- {
- unsigned long ctl;
-
-- ctl = at91_emac_read(AT91_EMAC_CTL);
-- at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE); /* disable management port */
-+ ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-+ at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE); /* disable management port */
- }
-
- /*
- * Wait until the PHY operation is complete.
- */
--static inline void at91_phy_wait(void) {
-+static inline void at91_phy_wait(struct at91_private *lp)
-+{
- unsigned long timeout = jiffies + 2;
-
-- while (!(at91_emac_read(AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) {
-+ while (!(at91_emac_read(lp, AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) {
- if (time_after(jiffies, timeout)) {
- printk("at91_ether: MIO timeout\n");
- break;
-@@ -113,28 +111,28 @@ static inline void at91_phy_wait(void) {
- * Write value to the a PHY register
- * Note: MDI interface is assumed to already have been enabled.
- */
--static void write_phy(unsigned char phy_addr, unsigned char address, unsigned int value)
-+static void write_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int value)
- {
-- at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W
-+ at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W
- | ((phy_addr & 0x1f) << 23) | (address << 18) | (value & AT91_EMAC_DATA));
-
- /* Wait until IDLE bit in Network Status register is cleared */
-- at91_phy_wait();
-+ at91_phy_wait(lp);
- }
-
- /*
- * Read value stored in a PHY register.
- * Note: MDI interface is assumed to already have been enabled.
- */
--static void read_phy(unsigned char phy_addr, unsigned char address, unsigned int *value)
-+static void read_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int *value)
- {
-- at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R
-+ at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R
- | ((phy_addr & 0x1f) << 23) | (address << 18));
-
- /* Wait until IDLE bit in Network Status register is cleared */
-- at91_phy_wait();
-+ at91_phy_wait(lp);
-
-- *value = at91_emac_read(AT91_EMAC_MAN) & AT91_EMAC_DATA;
-+ *value = at91_emac_read(lp, AT91_EMAC_MAN) & AT91_EMAC_DATA;
- }
-
- /* ........................... PHY MANAGEMENT .......................... */
-@@ -158,13 +156,13 @@ static void update_linkspeed(struct net_device *dev, int silent)
- }
-
- /* Link up, or auto-negotiation still in progress */
-- read_phy(lp->phy_address, MII_BMSR, &bmsr);
-- read_phy(lp->phy_address, MII_BMCR, &bmcr);
-+ read_phy(lp, lp->phy_address, MII_BMSR, &bmsr);
-+ read_phy(lp, lp->phy_address, MII_BMCR, &bmcr);
- if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */
- if (!(bmsr & BMSR_ANEGCOMPLETE))
- return; /* Do nothing - another interrupt generated when negotiation complete */
-
-- read_phy(lp->phy_address, MII_LPA, &lpa);
-+ read_phy(lp, lp->phy_address, MII_LPA, &lpa);
- if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100;
- else speed = SPEED_10;
- if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL;
-@@ -175,7 +173,7 @@ static void update_linkspeed(struct net_device *dev, int silent)
- }
-
- /* Update the MAC */
-- mac_cfg = at91_emac_read(AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD);
-+ mac_cfg = at91_emac_read(lp, AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD);
- if (speed == SPEED_100) {
- if (duplex == DUPLEX_FULL) /* 100 Full Duplex */
- mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD;
-@@ -186,7 +184,7 @@ static void update_linkspeed(struct net_device *dev, int silent)
- mac_cfg |= AT91_EMAC_FD;
- else {} /* 10 Half Duplex */
- }
-- at91_emac_write(AT91_EMAC_CFG, mac_cfg);
-+ at91_emac_write(lp, AT91_EMAC_CFG, mac_cfg);
-
- if (!silent)
- printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
-@@ -207,34 +205,34 @@ static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
- * level-triggering. We therefore have to check if the PHY actually has
- * an IRQ pending.
- */
-- enable_mdi();
-+ enable_mdi(lp);
- if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
-- read_phy(lp->phy_address, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */
-+ read_phy(lp, lp->phy_address, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */
- if (!(phy & (1 << 0)))
- goto done;
- }
- else if (lp->phy_type == MII_LXT971A_ID) {
-- read_phy(lp->phy_address, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */
-+ read_phy(lp, lp->phy_address, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */
- if (!(phy & (1 << 2)))
- goto done;
- }
- else if (lp->phy_type == MII_BCM5221_ID) {
-- read_phy(lp->phy_address, MII_BCMINTR_REG, &phy); /* ack interrupt in Broadcom PHY */
-+ read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &phy); /* ack interrupt in Broadcom PHY */
- if (!(phy & (1 << 0)))
- goto done;
- }
- else if (lp->phy_type == MII_KS8721_ID) {
-- read_phy(lp->phy_address, MII_TPISTATUS, &phy); /* ack interrupt in Micrel PHY */
-+ read_phy(lp, lp->phy_address, MII_TPISTATUS, &phy); /* ack interrupt in Micrel PHY */
- if (!(phy & ((1 << 2) | 1)))
- goto done;
- }
-- else if (lp->phy_type == MII_T78Q21x3_ID) { /* ack interrupt in Teridian PHY */
-- read_phy(lp->phy_address, MII_T78Q21INT_REG, &phy);
-+ else if (lp->phy_type == MII_T78Q21x3_ID) { /* ack interrupt in Teridian PHY */
-+ read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &phy);
- if (!(phy & ((1 << 2) | 1)))
- goto done;
- }
- else if (lp->phy_type == MII_DP83848_ID) {
-- read_phy(lp->phy_address, MII_DPPHYSTS_REG, &phy); /* ack interrupt in DP83848 PHY */
-+ read_phy(lp, lp->phy_address, MII_DPPHYSTS_REG, &phy); /* ack interrupt in DP83848 PHY */
- if (!(phy & (1 << 7)))
- goto done;
- }
-@@ -242,7 +240,7 @@ static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
- update_linkspeed(dev, 0);
-
- done:
-- disable_mdi();
-+ disable_mdi(lp);
-
- return IRQ_HANDLED;
- }
-@@ -273,41 +271,41 @@ static void enable_phyirq(struct net_device *dev)
- }
-
- spin_lock_irq(&lp->lock);
-- enable_mdi();
-+ enable_mdi(lp);
-
- if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */
-- read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr);
-+ read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr);
- dsintr = dsintr & ~0xf00; /* clear bits 8..11 */
-- write_phy(lp->phy_address, MII_DSINTR_REG, dsintr);
-+ write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr);
- }
- else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
-- read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr);
-+ read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr);
- dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */
-- write_phy(lp->phy_address, MII_ISINTE_REG, dsintr);
-+ write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr);
- }
- else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */
- dsintr = (1 << 15) | ( 1 << 14);
-- write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr);
-+ write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr);
- }
- else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */
- dsintr = (1 << 10) | ( 1 << 8);
-- write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
-+ write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr);
- }
- else if (lp->phy_type == MII_T78Q21x3_ID) { /* for Teridian PHY */
-- read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr);
-+ read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr);
- dsintr = dsintr | 0x500; /* set bits 8, 10 */
-- write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr);
-+ write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr);
- }
- else if (lp->phy_type == MII_DP83848_ID) { /* National Semiconductor DP83848 PHY */
-- read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr);
-+ read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr);
- dsintr = dsintr | 0x3c; /* set bits 2..5 */
-- write_phy(lp->phy_address, MII_DPMISR_REG, dsintr);
-- read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr);
-+ write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr);
-+ read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr);
- dsintr = dsintr | 0x3; /* set bits 0,1 */
-- write_phy(lp->phy_address, MII_DPMICR_REG, dsintr);
-+ write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr);
- }
-
-- disable_mdi();
-+ disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
- }
-
-@@ -326,43 +324,43 @@ static void disable_phyirq(struct net_device *dev)
- }
-
- spin_lock_irq(&lp->lock);
-- enable_mdi();
-+ enable_mdi(lp);
-
- if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */
-- read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr);
-+ read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr);
- dsintr = dsintr | 0xf00; /* set bits 8..11 */
-- write_phy(lp->phy_address, MII_DSINTR_REG, dsintr);
-+ write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr);
- }
- else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
-- read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr);
-+ read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr);
- dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */
-- write_phy(lp->phy_address, MII_ISINTE_REG, dsintr);
-+ write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr);
- }
- else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */
-- read_phy(lp->phy_address, MII_BCMINTR_REG, &dsintr);
-+ read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &dsintr);
- dsintr = ~(1 << 14);
-- write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr);
-+ write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr);
- }
- else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */
-- read_phy(lp->phy_address, MII_TPISTATUS, &dsintr);
-+ read_phy(lp, lp->phy_address, MII_TPISTATUS, &dsintr);
- dsintr = ~((1 << 10) | (1 << 8));
-- write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
-+ write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr);
- }
- else if (lp->phy_type == MII_T78Q21x3_ID) { /* for Teridian PHY */
-- read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr);
-+ read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr);
- dsintr = dsintr & ~0x500; /* clear bits 8, 10 */
-- write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr);
-+ write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr);
- }
- else if (lp->phy_type == MII_DP83848_ID) { /* National Semiconductor DP83848 PHY */
-- read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr);
-+ read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr);
- dsintr = dsintr & ~0x3; /* clear bits 0, 1 */
-- write_phy(lp->phy_address, MII_DPMICR_REG, dsintr);
-- read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr);
-+ write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr);
-+ read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr);
- dsintr = dsintr & ~0x3c; /* clear bits 2..5 */
-- write_phy(lp->phy_address, MII_DPMISR_REG, dsintr);
-+ write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr);
- }
-
-- disable_mdi();
-+ disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-
- irq_number = lp->board_data.phy_irq_pin;
-@@ -379,17 +377,17 @@ static void reset_phy(struct net_device *dev)
- unsigned int bmcr;
-
- spin_lock_irq(&lp->lock);
-- enable_mdi();
-+ enable_mdi(lp);
-
- /* Perform PHY reset */
-- write_phy(lp->phy_address, MII_BMCR, BMCR_RESET);
-+ write_phy(lp, lp->phy_address, MII_BMCR, BMCR_RESET);
-
- /* Wait until PHY reset is complete */
- do {
-- read_phy(lp->phy_address, MII_BMCR, &bmcr);
-+ read_phy(lp, lp->phy_address, MII_BMCR, &bmcr);
- } while (!(bmcr & BMCR_RESET));
-
-- disable_mdi();
-+ disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
- }
- #endif
-@@ -399,13 +397,37 @@ static void at91ether_check_link(unsigned long dev_id)
- struct net_device *dev = (struct net_device *) dev_id;
- struct at91_private *lp = netdev_priv(dev);
-
-- enable_mdi();
-+ enable_mdi(lp);
- update_linkspeed(dev, 1);
-- disable_mdi();
-+ disable_mdi(lp);
-
- mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
- }
-
-+/*
-+ * Perform any PHY-specific initialization.
-+ */
-+static void __init initialize_phy(struct at91_private *lp)
-+{
-+ unsigned int val;
-+
-+ spin_lock_irq(&lp->lock);
-+ enable_mdi(lp);
-+
-+ if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
-+ read_phy(lp, lp->phy_address, MII_DSCR_REG, &val);
-+ if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */
-+ lp->phy_media = PORT_FIBRE;
-+ } else if (machine_is_csb337()) {
-+ /* mix link activity status into LED2 link state */
-+ write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x0d22);
-+ } else if (machine_is_ecbat91())
-+ write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x156A);
-+
-+ disable_mdi(lp);
-+ spin_unlock_irq(&lp->lock);
-+}
-+
- /* ......................... ADDRESS MANAGEMENT ........................ */
-
- /*
-@@ -454,17 +476,19 @@ static short __init unpack_mac_address(struct net_device *dev, unsigned int hi,
- */
- static void __init get_mac_address(struct net_device *dev)
- {
-+ struct at91_private *lp = netdev_priv(dev);
-+
- /* Check Specific-Address 1 */
-- if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA1H), at91_emac_read(AT91_EMAC_SA1L)))
-+ if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA1H), at91_emac_read(lp, AT91_EMAC_SA1L)))
- return;
- /* Check Specific-Address 2 */
-- if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA2H), at91_emac_read(AT91_EMAC_SA2L)))
-+ if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA2H), at91_emac_read(lp, AT91_EMAC_SA2L)))
- return;
- /* Check Specific-Address 3 */
-- if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA3H), at91_emac_read(AT91_EMAC_SA3L)))
-+ if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA3H), at91_emac_read(lp, AT91_EMAC_SA3L)))
- return;
- /* Check Specific-Address 4 */
-- if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA4H), at91_emac_read(AT91_EMAC_SA4L)))
-+ if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA4H), at91_emac_read(lp, AT91_EMAC_SA4L)))
- return;
-
- printk(KERN_ERR "at91_ether: Your bootloader did not configure a MAC address.\n");
-@@ -475,11 +499,13 @@ static void __init get_mac_address(struct net_device *dev)
- */
- static void update_mac_address(struct net_device *dev)
- {
-- at91_emac_write(AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]));
-- at91_emac_write(AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4]));
-+ struct at91_private *lp = netdev_priv(dev);
-
-- at91_emac_write(AT91_EMAC_SA2L, 0);
-- at91_emac_write(AT91_EMAC_SA2H, 0);
-+ at91_emac_write(lp, AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]));
-+ at91_emac_write(lp, AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4]));
-+
-+ at91_emac_write(lp, AT91_EMAC_SA2L, 0);
-+ at91_emac_write(lp, AT91_EMAC_SA2H, 0);
- }
-
- /*
-@@ -559,6 +585,7 @@ static int hash_get_index(__u8 *addr)
- */
- static void at91ether_sethashtable(struct net_device *dev)
- {
-+ struct at91_private *lp = netdev_priv(dev);
- struct netdev_hw_addr *ha;
- unsigned long mc_filter[2];
- unsigned int bitnr;
-@@ -570,8 +597,8 @@ static void at91ether_sethashtable(struct net_device *dev)
- mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
- }
-
-- at91_emac_write(AT91_EMAC_HSL, mc_filter[0]);
-- at91_emac_write(AT91_EMAC_HSH, mc_filter[1]);
-+ at91_emac_write(lp, AT91_EMAC_HSL, mc_filter[0]);
-+ at91_emac_write(lp, AT91_EMAC_HSH, mc_filter[1]);
- }
-
- /*
-@@ -579,9 +606,10 @@ static void at91ether_sethashtable(struct net_device *dev)
- */
- static void at91ether_set_multicast_list(struct net_device *dev)
- {
-+ struct at91_private *lp = netdev_priv(dev);
- unsigned long cfg;
-
-- cfg = at91_emac_read(AT91_EMAC_CFG);
-+ cfg = at91_emac_read(lp, AT91_EMAC_CFG);
-
- if (dev->flags & IFF_PROMISC) /* Enable promiscuous mode */
- cfg |= AT91_EMAC_CAF;
-@@ -589,34 +617,37 @@ static void at91ether_set_multicast_list(struct net_device *dev)
- cfg &= ~AT91_EMAC_CAF;
-
- if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */
-- at91_emac_write(AT91_EMAC_HSH, -1);
-- at91_emac_write(AT91_EMAC_HSL, -1);
-+ at91_emac_write(lp, AT91_EMAC_HSH, -1);
-+ at91_emac_write(lp, AT91_EMAC_HSL, -1);
- cfg |= AT91_EMAC_MTI;
- } else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */
- at91ether_sethashtable(dev);
- cfg |= AT91_EMAC_MTI;
- } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */
-- at91_emac_write(AT91_EMAC_HSH, 0);
-- at91_emac_write(AT91_EMAC_HSL, 0);
-+ at91_emac_write(lp, AT91_EMAC_HSH, 0);
-+ at91_emac_write(lp, AT91_EMAC_HSL, 0);
- cfg &= ~AT91_EMAC_MTI;
- }
-
-- at91_emac_write(AT91_EMAC_CFG, cfg);
-+ at91_emac_write(lp, AT91_EMAC_CFG, cfg);
- }
-
- /* ......................... ETHTOOL SUPPORT ........................... */
-
- static int mdio_read(struct net_device *dev, int phy_id, int location)
- {
-+ struct at91_private *lp = netdev_priv(dev);
- unsigned int value;
-
-- read_phy(phy_id, location, &value);
-+ read_phy(lp, phy_id, location, &value);
- return value;
- }
-
- static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
- {
-- write_phy(phy_id, location, value);
-+ struct at91_private *lp = netdev_priv(dev);
-+
-+ write_phy(lp, phy_id, location, value);
- }
-
- static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-@@ -625,11 +656,11 @@ static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cm
- int ret;
-
- spin_lock_irq(&lp->lock);
-- enable_mdi();
-+ enable_mdi(lp);
-
- ret = mii_ethtool_gset(&lp->mii, cmd);
-
-- disable_mdi();
-+ disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-
- if (lp->phy_media == PORT_FIBRE) { /* override media type since mii.c doesn't know */
-@@ -646,11 +677,11 @@ static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cm
- int ret;
-
- spin_lock_irq(&lp->lock);
-- enable_mdi();
-+ enable_mdi(lp);
-
- ret = mii_ethtool_sset(&lp->mii, cmd);
-
-- disable_mdi();
-+ disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-
- return ret;
-@@ -662,11 +693,11 @@ static int at91ether_nwayreset(struct net_device *dev)
- int ret;
-
- spin_lock_irq(&lp->lock);
-- enable_mdi();
-+ enable_mdi(lp);
-
- ret = mii_nway_restart(&lp->mii);
-
-- disable_mdi();
-+ disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-
- return ret;
-@@ -696,9 +727,9 @@ static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
- return -EINVAL;
-
- spin_lock_irq(&lp->lock);
-- enable_mdi();
-+ enable_mdi(lp);
- res = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL);
-- disable_mdi();
-+ disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-
- return res;
-@@ -731,11 +762,11 @@ static void at91ether_start(struct net_device *dev)
- lp->rxBuffIndex = 0;
-
- /* Program address of descriptor list in Rx Buffer Queue register */
-- at91_emac_write(AT91_EMAC_RBQP, (unsigned long) dlist_phys);
-+ at91_emac_write(lp, AT91_EMAC_RBQP, (unsigned long) dlist_phys);
-
- /* Enable Receive and Transmit */
-- ctl = at91_emac_read(AT91_EMAC_CTL);
-- at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE);
-+ ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-+ at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE);
- }
-
- /*
-@@ -752,8 +783,8 @@ static int at91ether_open(struct net_device *dev)
- clk_enable(lp->ether_clk); /* Re-enable Peripheral clock */
-
- /* Clear internal statistics */
-- ctl = at91_emac_read(AT91_EMAC_CTL);
-- at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_CSR);
-+ ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-+ at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_CSR);
-
- /* Update the MAC address (incase user has changed it) */
- update_mac_address(dev);
-@@ -762,15 +793,15 @@ static int at91ether_open(struct net_device *dev)
- enable_phyirq(dev);
-
- /* Enable MAC interrupts */
-- at91_emac_write(AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA
-+ at91_emac_write(lp, AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA
- | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
- | AT91_EMAC_ROVR | AT91_EMAC_ABT);
-
- /* Determine current link speed */
- spin_lock_irq(&lp->lock);
-- enable_mdi();
-+ enable_mdi(lp);
- update_linkspeed(dev, 0);
-- disable_mdi();
-+ disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-
- at91ether_start(dev);
-@@ -787,14 +818,14 @@ static int at91ether_close(struct net_device *dev)
- unsigned long ctl;
-
- /* Disable Receiver and Transmitter */
-- ctl = at91_emac_read(AT91_EMAC_CTL);
-- at91_emac_write(AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE));
-+ ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-+ at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE));
-
- /* Disable PHY interrupt */
- disable_phyirq(dev);
-
- /* Disable MAC interrupts */
-- at91_emac_write(AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA
-+ at91_emac_write(lp, AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA
- | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
- | AT91_EMAC_ROVR | AT91_EMAC_ABT);
-
-@@ -812,7 +843,7 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
- {
- struct at91_private *lp = netdev_priv(dev);
-
-- if (at91_emac_read(AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) {
-+ if (at91_emac_read(lp, AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) {
- netif_stop_queue(dev);
-
- /* Store packet information (to free when Tx completed) */
-@@ -822,9 +853,9 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
- dev->stats.tx_bytes += skb->len;
-
- /* Set address of the data in the Transmit Address register */
-- at91_emac_write(AT91_EMAC_TAR, lp->skb_physaddr);
-+ at91_emac_write(lp, AT91_EMAC_TAR, lp->skb_physaddr);
- /* Set length of the packet in the Transmit Control register */
-- at91_emac_write(AT91_EMAC_TCR, skb->len);
-+ at91_emac_write(lp, AT91_EMAC_TCR, skb->len);
-
- } else {
- printk(KERN_ERR "at91_ether.c: at91ether_start_xmit() called, but device is busy!\n");
-@@ -841,31 +872,32 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
- */
- static struct net_device_stats *at91ether_stats(struct net_device *dev)
- {
-+ struct at91_private *lp = netdev_priv(dev);
- int ale, lenerr, seqe, lcol, ecol;
-
- if (netif_running(dev)) {
-- dev->stats.rx_packets += at91_emac_read(AT91_EMAC_OK); /* Good frames received */
-- ale = at91_emac_read(AT91_EMAC_ALE);
-+ dev->stats.rx_packets += at91_emac_read(lp, AT91_EMAC_OK); /* Good frames received */
-+ ale = at91_emac_read(lp, AT91_EMAC_ALE);
- dev->stats.rx_frame_errors += ale; /* Alignment errors */
-- lenerr = at91_emac_read(AT91_EMAC_ELR) + at91_emac_read(AT91_EMAC_USF);
-+ lenerr = at91_emac_read(lp, AT91_EMAC_ELR) + at91_emac_read(lp, AT91_EMAC_USF);
- dev->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */
-- seqe = at91_emac_read(AT91_EMAC_SEQE);
-+ seqe = at91_emac_read(lp, AT91_EMAC_SEQE);
- dev->stats.rx_crc_errors += seqe; /* CRC error */
-- dev->stats.rx_fifo_errors += at91_emac_read(AT91_EMAC_DRFC); /* Receive buffer not available */
-+ dev->stats.rx_fifo_errors += at91_emac_read(lp, AT91_EMAC_DRFC);/* Receive buffer not available */
- dev->stats.rx_errors += (ale + lenerr + seqe
-- + at91_emac_read(AT91_EMAC_CDE) + at91_emac_read(AT91_EMAC_RJB));
-+ + at91_emac_read(lp, AT91_EMAC_CDE) + at91_emac_read(lp, AT91_EMAC_RJB));
-
-- dev->stats.tx_packets += at91_emac_read(AT91_EMAC_FRA); /* Frames successfully transmitted */
-- dev->stats.tx_fifo_errors += at91_emac_read(AT91_EMAC_TUE); /* Transmit FIFO underruns */
-- dev->stats.tx_carrier_errors += at91_emac_read(AT91_EMAC_CSE); /* Carrier Sense errors */
-- dev->stats.tx_heartbeat_errors += at91_emac_read(AT91_EMAC_SQEE);/* Heartbeat error */
-+ dev->stats.tx_packets += at91_emac_read(lp, AT91_EMAC_FRA); /* Frames successfully transmitted */
-+ dev->stats.tx_fifo_errors += at91_emac_read(lp, AT91_EMAC_TUE); /* Transmit FIFO underruns */
-+ dev->stats.tx_carrier_errors += at91_emac_read(lp, AT91_EMAC_CSE); /* Carrier Sense errors */
-+ dev->stats.tx_heartbeat_errors += at91_emac_read(lp, AT91_EMAC_SQEE);/* Heartbeat error */
-
-- lcol = at91_emac_read(AT91_EMAC_LCOL);
-- ecol = at91_emac_read(AT91_EMAC_ECOL);
-+ lcol = at91_emac_read(lp, AT91_EMAC_LCOL);
-+ ecol = at91_emac_read(lp, AT91_EMAC_ECOL);
- dev->stats.tx_window_errors += lcol; /* Late collisions */
- dev->stats.tx_aborted_errors += ecol; /* 16 collisions */
-
-- dev->stats.collisions += (at91_emac_read(AT91_EMAC_SCOL) + at91_emac_read(AT91_EMAC_MCOL) + lcol + ecol);
-+ dev->stats.collisions += (at91_emac_read(lp, AT91_EMAC_SCOL) + at91_emac_read(lp, AT91_EMAC_MCOL) + lcol + ecol);
- }
- return &dev->stats;
- }
-@@ -922,7 +954,7 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
-
- /* MAC Interrupt Status register indicates what interrupts are pending.
- It is automatically cleared once read. */
-- intstatus = at91_emac_read(AT91_EMAC_ISR);
-+ intstatus = at91_emac_read(lp, AT91_EMAC_ISR);
-
- if (intstatus & AT91_EMAC_RCOM) /* Receive complete */
- at91ether_rx(dev);
-@@ -942,9 +974,9 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
-
- /* Work-around for Errata #11 */
- if (intstatus & AT91_EMAC_RBNA) {
-- ctl = at91_emac_read(AT91_EMAC_CTL);
-- at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE);
-- at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE);
-+ ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-+ at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE);
-+ at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE);
- }
-
- if (intstatus & AT91_EMAC_ROVR)
-@@ -980,189 +1012,199 @@ static const struct net_device_ops at91ether_netdev_ops = {
- };
-
- /*
-- * Initialize the ethernet interface
-+ * Detect the PHY type, and its address.
- */
--static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address,
-- struct platform_device *pdev, struct clk *ether_clk)
-+static int __init at91ether_phy_detect(struct at91_private *lp)
-+{
-+ unsigned int phyid1, phyid2;
-+ unsigned long phy_id;
-+ unsigned short phy_address = 0;
-+
-+ while (phy_address < PHY_MAX_ADDR) {
-+ /* Read the PHY ID registers */
-+ enable_mdi(lp);
-+ read_phy(lp, phy_address, MII_PHYSID1, &phyid1);
-+ read_phy(lp, phy_address, MII_PHYSID2, &phyid2);
-+ disable_mdi(lp);
-+
-+ phy_id = (phyid1 << 16) | (phyid2 & 0xfff0);
-+ switch (phy_id) {
-+ case MII_DM9161_ID: /* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */
-+ case MII_DM9161A_ID: /* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */
-+ case MII_LXT971A_ID: /* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */
-+ case MII_RTL8201_ID: /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */
-+ case MII_BCM5221_ID: /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */
-+ case MII_DP83847_ID: /* National Semiconductor DP83847: */
-+ case MII_DP83848_ID: /* National Semiconductor DP83848: */
-+ case MII_AC101L_ID: /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
-+ case MII_KS8721_ID: /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
-+ case MII_T78Q21x3_ID: /* Teridian 78Q21x3: PHY_ID1 = 0x0E, PHY_ID2 = 7237 */
-+ case MII_LAN83C185_ID: /* SMSC LAN83C185: PHY_ID1 = 0x0007, PHY_ID2 = 0xC0A1 */
-+ /* store detected values */
-+ lp->phy_type = phy_id; /* Type of PHY connected */
-+ lp->phy_address = phy_address; /* MDI address of PHY */
-+ return 1;
-+ }
-+
-+ phy_address++;
-+ }
-+
-+ return 0; /* not detected */
-+}
-+
-+
-+/*
-+ * Detect MAC & PHY and perform ethernet interface initialization
-+ */
-+static int __init at91ether_probe(struct platform_device *pdev)
- {
- struct macb_platform_data *board_data = pdev->dev.platform_data;
-+ struct resource *regs;
- struct net_device *dev;
- struct at91_private *lp;
-- unsigned int val;
- int res;
-
-+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!regs)
-+ return -ENOENT;
-+
- dev = alloc_etherdev(sizeof(struct at91_private));
- if (!dev)
- return -ENOMEM;
-
-- dev->base_addr = AT91_VA_BASE_EMAC;
-- dev->irq = AT91RM9200_ID_EMAC;
-+ lp = netdev_priv(dev);
-+ lp->board_data = *board_data;
-+ spin_lock_init(&lp->lock);
-+
-+ dev->base_addr = regs->start; /* physical base address */
-+ lp->emac_base = ioremap(regs->start, regs->end - regs->start + 1);
-+ if (!lp->emac_base) {
-+ res = -ENOMEM;
-+ goto err_free_dev;
-+ }
-+
-+ /* Clock */
-+ lp->ether_clk = clk_get(&pdev->dev, "ether_clk");
-+ if (IS_ERR(lp->ether_clk)) {
-+ res = -ENODEV;
-+ goto err_ioumap;
-+ }
-+ clk_enable(lp->ether_clk);
-
- /* Install the interrupt handler */
-+ dev->irq = platform_get_irq(pdev, 0);
- if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev)) {
-- free_netdev(dev);
-- return -EBUSY;
-+ res = -EBUSY;
-+ goto err_disable_clock;
- }
-
- /* Allocate memory for DMA Receive descriptors */
-- lp = netdev_priv(dev);
- lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL);
- if (lp->dlist == NULL) {
-- free_irq(dev->irq, dev);
-- free_netdev(dev);
-- return -ENOMEM;
-+ res = -ENOMEM;
-+ goto err_free_irq;
- }
-- lp->board_data = *board_data;
-- lp->ether_clk = ether_clk;
-- platform_set_drvdata(pdev, dev);
--
-- spin_lock_init(&lp->lock);
-
- ether_setup(dev);
- dev->netdev_ops = &at91ether_netdev_ops;
- dev->ethtool_ops = &at91ether_ethtool_ops;
--
-+ platform_set_drvdata(pdev, dev);
- SET_NETDEV_DEV(dev, &pdev->dev);
-
- get_mac_address(dev); /* Get ethernet address and store it in dev->dev_addr */
- update_mac_address(dev); /* Program ethernet address into MAC */
-
-- at91_emac_write(AT91_EMAC_CTL, 0);
-+ at91_emac_write(lp, AT91_EMAC_CTL, 0);
-
-- if (lp->board_data.is_rmii)
-- at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII);
-+ if (board_data->is_rmii)
-+ at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII);
- else
-- at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG);
-+ at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG);
-
-- /* Perform PHY-specific initialization */
-- spin_lock_irq(&lp->lock);
-- enable_mdi();
-- if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
-- read_phy(phy_address, MII_DSCR_REG, &val);
-- if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */
-- lp->phy_media = PORT_FIBRE;
-- } else if (machine_is_csb337()) {
-- /* mix link activity status into LED2 link state */
-- write_phy(phy_address, MII_LEDCTRL_REG, 0x0d22);
-- } else if (machine_is_ecbat91())
-- write_phy(phy_address, MII_LEDCTRL_REG, 0x156A);
-+ /* Detect PHY */
-+ if (!at91ether_phy_detect(lp)) {
-+ printk(KERN_ERR "at91_ether: Could not detect ethernet PHY\n");
-+ res = -ENODEV;
-+ goto err_free_dmamem;
-+ }
-
-- disable_mdi();
-- spin_unlock_irq(&lp->lock);
-+ initialize_phy(lp);
-
- lp->mii.dev = dev; /* Support for ethtool */
- lp->mii.mdio_read = mdio_read;
- lp->mii.mdio_write = mdio_write;
-- lp->mii.phy_id = phy_address;
-+ lp->mii.phy_id = lp->phy_address;
- lp->mii.phy_id_mask = 0x1f;
- lp->mii.reg_num_mask = 0x1f;
-
-- lp->phy_type = phy_type; /* Type of PHY connected */
-- lp->phy_address = phy_address; /* MDI address of PHY */
--
- /* Register the network interface */
- res = register_netdev(dev);
-- if (res) {
-- free_irq(dev->irq, dev);
-- free_netdev(dev);
-- dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
-- return res;
-- }
-+ if (res)
-+ goto err_free_dmamem;
-
- /* Determine current link speed */
- spin_lock_irq(&lp->lock);
-- enable_mdi();
-+ enable_mdi(lp);
- update_linkspeed(dev, 0);
-- disable_mdi();
-+ disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
- netif_carrier_off(dev); /* will be enabled in open() */
-
- /* If board has no PHY IRQ, use a timer to poll the PHY */
-- if (!gpio_is_valid(lp->board_data.phy_irq_pin)) {
-+ if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
-+ gpio_request(board_data->phy_irq_pin, "ethernet_phy");
-+ } else {
-+ /* If board has no PHY IRQ, use a timer to poll the PHY */
- init_timer(&lp->check_timer);
- lp->check_timer.data = (unsigned long)dev;
- lp->check_timer.function = at91ether_check_link;
-- } else if (lp->board_data.phy_irq_pin >= 32)
-- gpio_request(lp->board_data.phy_irq_pin, "ethernet_phy");
-+ }
-
- /* Display ethernet banner */
- printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%pM)\n",
- dev->name, (uint) dev->base_addr, dev->irq,
-- at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-",
-- at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex",
-+ at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-",
-+ at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex",
- dev->dev_addr);
-- if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
-+ if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
- printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
-- else if (phy_type == MII_LXT971A_ID)
-+ else if (lp->phy_type == MII_LXT971A_ID)
- printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
-- else if (phy_type == MII_RTL8201_ID)
-+ else if (lp->phy_type == MII_RTL8201_ID)
- printk(KERN_INFO "%s: Realtek RTL8201(B)L PHY\n", dev->name);
-- else if (phy_type == MII_BCM5221_ID)
-+ else if (lp->phy_type == MII_BCM5221_ID)
- printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name);
-- else if (phy_type == MII_DP83847_ID)
-+ else if (lp->phy_type == MII_DP83847_ID)
- printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", dev->name);
-- else if (phy_type == MII_DP83848_ID)
-+ else if (lp->phy_type == MII_DP83848_ID)
- printk(KERN_INFO "%s: National Semiconductor DP83848 PHY\n", dev->name);
-- else if (phy_type == MII_AC101L_ID)
-+ else if (lp->phy_type == MII_AC101L_ID)
- printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name);
-- else if (phy_type == MII_KS8721_ID)
-+ else if (lp->phy_type == MII_KS8721_ID)
- printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name);
-- else if (phy_type == MII_T78Q21x3_ID)
-+ else if (lp->phy_type == MII_T78Q21x3_ID)
- printk(KERN_INFO "%s: Teridian 78Q21x3 PHY\n", dev->name);
-- else if (phy_type == MII_LAN83C185_ID)
-+ else if (lp->phy_type == MII_LAN83C185_ID)
- printk(KERN_INFO "%s: SMSC LAN83C185 PHY\n", dev->name);
-
-- return 0;
--}
--
--/*
-- * Detect MAC and PHY and perform initialization
-- */
--static int __init at91ether_probe(struct platform_device *pdev)
--{
-- unsigned int phyid1, phyid2;
-- int detected = -1;
-- unsigned long phy_id;
-- unsigned short phy_address = 0;
-- struct clk *ether_clk;
--
-- ether_clk = clk_get(&pdev->dev, "ether_clk");
-- if (IS_ERR(ether_clk)) {
-- printk(KERN_ERR "at91_ether: no clock defined\n");
-- return -ENODEV;
-- }
-- clk_enable(ether_clk); /* Enable Peripheral clock */
--
-- while ((detected != 0) && (phy_address < 32)) {
-- /* Read the PHY ID registers */
-- enable_mdi();
-- read_phy(phy_address, MII_PHYSID1, &phyid1);
-- read_phy(phy_address, MII_PHYSID2, &phyid2);
-- disable_mdi();
--
-- phy_id = (phyid1 << 16) | (phyid2 & 0xfff0);
-- switch (phy_id) {
-- case MII_DM9161_ID: /* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */
-- case MII_DM9161A_ID: /* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */
-- case MII_LXT971A_ID: /* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */
-- case MII_RTL8201_ID: /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */
-- case MII_BCM5221_ID: /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */
-- case MII_DP83847_ID: /* National Semiconductor DP83847: */
-- case MII_DP83848_ID: /* National Semiconductor DP83848: */
-- case MII_AC101L_ID: /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
-- case MII_KS8721_ID: /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
-- case MII_T78Q21x3_ID: /* Teridian 78Q21x3: PHY_ID1 = 0x0E, PHY_ID2 = 7237 */
-- case MII_LAN83C185_ID: /* SMSC LAN83C185: PHY_ID1 = 0x0007, PHY_ID2 = 0xC0A1 */
-- detected = at91ether_setup(phy_id, phy_address, pdev, ether_clk);
-- break;
-- }
-+ clk_disable(lp->ether_clk); /* Disable Peripheral clock */
-
-- phy_address++;
-- }
-+ return 0;
-
-- clk_disable(ether_clk); /* Disable Peripheral clock */
-
-- return detected;
-+err_free_dmamem:
-+ platform_set_drvdata(pdev, NULL);
-+ dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
-+err_free_irq:
-+ free_irq(dev->irq, dev);
-+err_disable_clock:
-+ clk_disable(lp->ether_clk);
-+ clk_put(lp->ether_clk);
-+err_ioumap:
-+ iounmap(lp->emac_base);
-+err_free_dev:
-+ free_netdev(dev);
-+ return res;
- }
-
- static int __devexit at91ether_remove(struct platform_device *pdev)
-@@ -1170,8 +1212,7 @@ static int __devexit at91ether_remove(struct platform_device *pdev)
- struct net_device *dev = platform_get_drvdata(pdev);
- struct at91_private *lp = netdev_priv(dev);
-
-- if (gpio_is_valid(lp->board_data.phy_irq_pin) &&
-- lp->board_data.phy_irq_pin >= 32)
-+ if (gpio_is_valid(lp->board_data.phy_irq_pin))
- gpio_free(lp->board_data.phy_irq_pin);
-
- unregister_netdev(dev);
-diff --git a/drivers/net/ethernet/cadence/at91_ether.h b/drivers/net/ethernet/cadence/at91_ether.h
-index 3725fbb0..0ef6328 100644
---- a/drivers/net/ethernet/cadence/at91_ether.h
-+++ b/drivers/net/ethernet/cadence/at91_ether.h
-@@ -88,6 +88,7 @@ struct at91_private
- struct macb_platform_data board_data; /* board-specific
- * configuration (shared with
- * macb for common data */
-+ void __iomem *emac_base; /* base register address */
- struct clk *ether_clk; /* clock */
-
- /* PHY */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 8d5bf013fc624b1abb36240dd06dc5b43201e2a9 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 26 Apr 2012 00:30:43 +0000
-Subject: net/at91_ether: use gpio_to_irq for phy IRQ line
-
-commit 86cc070eb19640d42941d3074e42c761d4c1c59c upstream.
-
-Use the gpio_to_irq() function to retrieve the phy IRQ line
-from the GPIO pin specification.
-This fix is needed now that we have moved to irqdomains on AT91.
-
-Reported-by: Jamie Iles <jamie@jamieiles.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Cc: Andrew Victor <avictor.za@gmail.com>
-Cc: David S. Miller <davem@davemloft.net>
-Cc: netdev@vger.kernel.org
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- drivers/net/ethernet/cadence/at91_ether.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
-index 62761e1..7788419 100644
---- a/drivers/net/ethernet/cadence/at91_ether.c
-+++ b/drivers/net/ethernet/cadence/at91_ether.c
-@@ -263,7 +263,7 @@ static void enable_phyirq(struct net_device *dev)
- return;
- }
-
-- irq_number = lp->board_data.phy_irq_pin;
-+ irq_number = gpio_to_irq(lp->board_data.phy_irq_pin);
- status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev);
- if (status) {
- printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status);
-@@ -363,7 +363,7 @@ static void disable_phyirq(struct net_device *dev)
- disable_mdi(lp);
- spin_unlock_irq(&lp->lock);
-
-- irq_number = lp->board_data.phy_irq_pin;
-+ irq_number = gpio_to_irq(lp->board_data.phy_irq_pin);
- free_irq(irq_number, dev); /* Free interrupt handler */
- }
-
-@@ -1234,7 +1234,7 @@ static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
-
- if (netif_running(net_dev)) {
- if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
-- int phy_irq = lp->board_data.phy_irq_pin;
-+ int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin);
- disable_irq(phy_irq);
- }
-
-@@ -1258,7 +1258,7 @@ static int at91ether_resume(struct platform_device *pdev)
- netif_start_queue(net_dev);
-
- if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
-- int phy_irq = lp->board_data.phy_irq_pin;
-+ int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin);
- enable_irq(phy_irq);
- }
- }
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From df5dbd6c7571a36641c5ec724afb595ba2d9fa82 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 3 Jul 2012 23:14:13 +0000
-Subject: net/macb: manage carrier state with call to netif_carrier_{on|off}()
-
-commit 03fc4721cd96753696a988a2ba563f9f08ad4e9f upstream.
-
-OFF carrier state is setup in probe() open() and suspend() functions.
-The carrier ON state is managed in macb_handle_link_change().
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- drivers/net/ethernet/cadence/macb.c | 13 +++++++++++--
- 1 file changed, 11 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
-index c4834c2..6100b85 100644
---- a/drivers/net/ethernet/cadence/macb.c
-+++ b/drivers/net/ethernet/cadence/macb.c
-@@ -179,13 +179,16 @@ static void macb_handle_link_change(struct net_device *dev)
- spin_unlock_irqrestore(&bp->lock, flags);
-
- if (status_change) {
-- if (phydev->link)
-+ if (phydev->link) {
-+ netif_carrier_on(dev);
- netdev_info(dev, "link up (%d/%s)\n",
- phydev->speed,
- phydev->duplex == DUPLEX_FULL ?
- "Full" : "Half");
-- else
-+ } else {
-+ netif_carrier_off(dev);
- netdev_info(dev, "link down\n");
-+ }
- }
- }
-
-@@ -1033,6 +1036,9 @@ static int macb_open(struct net_device *dev)
-
- netdev_dbg(bp->dev, "open\n");
-
-+ /* carrier starts down */
-+ netif_carrier_off(dev);
-+
- /* if the phy is not yet register, retry later*/
- if (!bp->phy_dev)
- return -EAGAIN;
-@@ -1405,6 +1411,8 @@ static int __init macb_probe(struct platform_device *pdev)
-
- platform_set_drvdata(pdev, dev);
-
-+ netif_carrier_off(dev);
-+
- netdev_info(dev, "Cadence %s at 0x%08lx irq %d (%pM)\n",
- macb_is_gem(bp) ? "GEM" : "MACB", dev->base_addr,
- dev->irq, dev->dev_addr);
-@@ -1468,6 +1476,7 @@ static int macb_suspend(struct platform_device *pdev, pm_message_t state)
- struct net_device *netdev = platform_get_drvdata(pdev);
- struct macb *bp = netdev_priv(netdev);
-
-+ netif_carrier_off(netdev);
- netif_device_detach(netdev);
-
- clk_disable(bp->hclk);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ff53d26da93227bae1309bfd9c404d17fd5baf8b Mon Sep 17 00:00:00 2001
-From: Bo Shen <voice.shen@atmel.com>
-Date: Fri, 11 May 2012 17:39:28 +0800
-Subject: ALSA: atmel/ac97c: correct the unexpected behavior when using
- uninitial value for reset pin
-
-commit b2522f9262539fc328b4b9344f8a2f7ef2cb18d5 upstream.
-
-When pdata->reset_pin is passed with a negative value (means gpio
-is invalid), then chip->reset_pin will not be assigned to a vaule,
-it will use default value 0. This will cause unexpected behavior.
-
-So, add this patch to correct.
-
-Signed-off-by: Bo Shen <voice.shen@atmel.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
----
- sound/atmel/ac97c.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
-index 115313e..f5ded64 100644
---- a/sound/atmel/ac97c.c
-+++ b/sound/atmel/ac97c.c
-@@ -991,6 +991,8 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
- gpio_direction_output(pdata->reset_pin, 1);
- chip->reset_pin = pdata->reset_pin;
- }
-+ } else {
-+ chip->reset_pin = -EINVAL;
- }
-
- snd_card_set_dev(card, &pdev->dev);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a1ac896220cc6517c99b449fee4b98618cf4d4d2 Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Thu, 31 May 2012 18:09:20 +0800
-Subject: MTD: at91: extract hw ecc initialization to one function
-
-commit 3dfe41a4c705223c66373968327407e11c2fb1a1 upstream.
-
-This patch moves hw ecc initialization code to one function.
-
-Signed-off-by: Hong Xu <hong.xu@atmel.com>
-Signed-off-by: Josh Wu <josh.wu@atmel.com>
----
- drivers/mtd/nand/atmel_nand.c | 127 ++++++++++++++++++++++--------------------
- 1 file changed, 66 insertions(+), 61 deletions(-)
-
-diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
-index 2165576..4ea0a04 100644
---- a/drivers/mtd/nand/atmel_nand.c
-+++ b/drivers/mtd/nand/atmel_nand.c
-@@ -523,6 +523,66 @@ static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
- }
- #endif
-
-+static int __init atmel_hw_nand_init_params(struct platform_device *pdev,
-+ struct atmel_nand_host *host)
-+{
-+ struct mtd_info *mtd = &host->mtd;
-+ struct nand_chip *nand_chip = &host->nand_chip;
-+ struct resource *regs;
-+
-+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+ if (!regs) {
-+ dev_err(host->dev,
-+ "Can't get I/O resource regs, use software ECC\n");
-+ nand_chip->ecc.mode = NAND_ECC_SOFT;
-+ return 0;
-+ }
-+
-+ host->ecc = ioremap(regs->start, resource_size(regs));
-+ if (host->ecc == NULL) {
-+ dev_err(host->dev, "ioremap failed\n");
-+ return -EIO;
-+ }
-+
-+ /* ECC is calculated for the whole page (1 step) */
-+ nand_chip->ecc.size = mtd->writesize;
-+
-+ /* set ECC page size and oob layout */
-+ switch (mtd->writesize) {
-+ case 512:
-+ nand_chip->ecc.layout = &atmel_oobinfo_small;
-+ ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
-+ break;
-+ case 1024:
-+ nand_chip->ecc.layout = &atmel_oobinfo_large;
-+ ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056);
-+ break;
-+ case 2048:
-+ nand_chip->ecc.layout = &atmel_oobinfo_large;
-+ ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112);
-+ break;
-+ case 4096:
-+ nand_chip->ecc.layout = &atmel_oobinfo_large;
-+ ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224);
-+ break;
-+ default:
-+ /* page size not handled by HW ECC */
-+ /* switching back to soft ECC */
-+ nand_chip->ecc.mode = NAND_ECC_SOFT;
-+ return 0;
-+ }
-+
-+ /* set up for HW ECC */
-+ nand_chip->ecc.calculate = atmel_nand_calculate;
-+ nand_chip->ecc.correct = atmel_nand_correct;
-+ nand_chip->ecc.hwctl = atmel_nand_hwctl;
-+ nand_chip->ecc.read_page = atmel_nand_read_page;
-+ nand_chip->ecc.bytes = 4;
-+ nand_chip->ecc.strength = 1;
-+
-+ return 0;
-+}
-+
- /*
- * Probe for the NAND device.
- */
-@@ -531,7 +591,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
- struct atmel_nand_host *host;
- struct mtd_info *mtd;
- struct nand_chip *nand_chip;
-- struct resource *regs;
- struct resource *mem;
- struct mtd_part_parser_data ppdata = {};
- int res;
-@@ -583,29 +642,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
- nand_chip->dev_ready = atmel_nand_device_ready;
-
- nand_chip->ecc.mode = host->board.ecc_mode;
--
-- regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-- if (!regs && nand_chip->ecc.mode == NAND_ECC_HW) {
-- printk(KERN_ERR "atmel_nand: can't get I/O resource "
-- "regs\nFalling back on software ECC\n");
-- nand_chip->ecc.mode = NAND_ECC_SOFT;
-- }
--
-- if (nand_chip->ecc.mode == NAND_ECC_HW) {
-- host->ecc = ioremap(regs->start, resource_size(regs));
-- if (host->ecc == NULL) {
-- printk(KERN_ERR "atmel_nand: ioremap failed\n");
-- res = -EIO;
-- goto err_ecc_ioremap;
-- }
-- nand_chip->ecc.calculate = atmel_nand_calculate;
-- nand_chip->ecc.correct = atmel_nand_correct;
-- nand_chip->ecc.hwctl = atmel_nand_hwctl;
-- nand_chip->ecc.read_page = atmel_nand_read_page;
-- nand_chip->ecc.bytes = 4;
-- nand_chip->ecc.strength = 1;
-- }
--
- nand_chip->chip_delay = 20; /* 20us command delay time */
-
- if (host->board.bus_width_16) /* 16-bit bus width */
-@@ -657,40 +693,9 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
- }
-
- if (nand_chip->ecc.mode == NAND_ECC_HW) {
-- /* ECC is calculated for the whole page (1 step) */
-- nand_chip->ecc.size = mtd->writesize;
--
-- /* set ECC page size and oob layout */
-- switch (mtd->writesize) {
-- case 512:
-- nand_chip->ecc.layout = &atmel_oobinfo_small;
-- ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
-- break;
-- case 1024:
-- nand_chip->ecc.layout = &atmel_oobinfo_large;
-- ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056);
-- break;
-- case 2048:
-- nand_chip->ecc.layout = &atmel_oobinfo_large;
-- ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112);
-- break;
-- case 4096:
-- nand_chip->ecc.layout = &atmel_oobinfo_large;
-- ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224);
-- break;
-- default:
-- /* page size not handled by HW ECC */
-- /* switching back to soft ECC */
-- nand_chip->ecc.mode = NAND_ECC_SOFT;
-- nand_chip->ecc.calculate = NULL;
-- nand_chip->ecc.correct = NULL;
-- nand_chip->ecc.hwctl = NULL;
-- nand_chip->ecc.read_page = NULL;
-- nand_chip->ecc.postpad = 0;
-- nand_chip->ecc.prepad = 0;
-- nand_chip->ecc.bytes = 0;
-- break;
-- }
-+ res = atmel_hw_nand_init_params(pdev, host);
-+ if (res != 0)
-+ goto err_hw_ecc;
- }
-
- /* second phase scan */
-@@ -707,15 +712,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
- return res;
-
- err_scan_tail:
-+ if (host->ecc)
-+ iounmap(host->ecc);
-+err_hw_ecc:
- err_scan_ident:
- err_no_card:
- atmel_nand_disable(host);
- platform_set_drvdata(pdev, NULL);
- if (host->dma_chan)
- dma_release_channel(host->dma_chan);
-- if (host->ecc)
-- iounmap(host->ecc);
--err_ecc_ioremap:
- iounmap(host->io_base);
- err_nand_ioremap:
- kfree(host);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 0ac83ef70e787b4309088615a0375d7318bdcd8f Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Tue, 26 Jun 2012 17:42:22 +0800
-Subject: MTD: at91: add dt parameters for Atmel PMECC
-
-commit a41b51a1f7c15a1b00f30a3ad2d0373ad51b883d upstream.
-
-Add DT support for PMECC parameters.
-
-Signed-off-by: Hong Xu <hong.xu@atmel.com>
-Signed-off-by: Josh Wu <josh.wu@atmel.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- .../devicetree/bindings/mtd/atmel-nand.txt | 40 ++++++++++++++++-
- drivers/mtd/nand/atmel_nand.c | 52 +++++++++++++++++++++-
- 2 files changed, 90 insertions(+), 2 deletions(-)
-
-diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
-index a200695..d555421 100644
---- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
-+++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
-@@ -3,7 +3,9 @@ Atmel NAND flash
- Required properties:
- - compatible : "atmel,at91rm9200-nand".
- - reg : should specify localbus address and size used for the chip,
-- and if availlable the ECC.
-+ and hardware ECC controller if available.
-+ If the hardware ECC is PMECC, it should contain address and size for
-+ PMECC, PMECC Error Location controller and ROM which has lookup tables.
- - atmel,nand-addr-offset : offset for the address latch.
- - atmel,nand-cmd-offset : offset for the command latch.
- - #address-cells, #size-cells : Must be present if the device has sub-nodes
-@@ -16,6 +18,15 @@ Optional properties:
- - nand-ecc-mode : String, operation mode of the NAND ecc mode, soft by default.
- Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first",
- "soft_bch".
-+- atmel,has-pmecc : boolean to enable Programmable Multibit ECC hardware.
-+ Only supported by at91sam9x5 or later sam9 product.
-+- atmel,pmecc-cap : error correct capability for Programmable Multibit ECC
-+ Controller. Supported values are: 2, 4, 8, 12, 24.
-+- atmel,pmecc-sector-size : sector size for ECC computation. Supported values
-+ are: 512, 1024.
-+- atmel,pmecc-lookup-table-offset : includes two offsets of lookup table in ROM
-+ for different sector size. First one is for sector size 512, the next is for
-+ sector size 1024.
- - nand-bus-width : 8 or 16 bus width if not present 8
- - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false
-
-@@ -39,3 +50,30 @@ nand0: nand@40000000,0 {
- ...
- };
- };
-+
-+/* for PMECC supported chips */
-+nand0: nand@40000000 {
-+ compatible = "atmel,at91rm9200-nand";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ reg = < 0x40000000 0x10000000 /* bus addr & size */
-+ 0xffffe000 0x00000600 /* PMECC addr & size */
-+ 0xffffe600 0x00000200 /* PMECC ERRLOC addr & size */
-+ 0x00100000 0x00100000 /* ROM addr & size */
-+ >;
-+ atmel,nand-addr-offset = <21>; /* ale */
-+ atmel,nand-cmd-offset = <22>; /* cle */
-+ nand-on-flash-bbt;
-+ nand-ecc-mode = "hw";
-+ atmel,has-pmecc; /* enable PMECC */
-+ atmel,pmecc-cap = <2>;
-+ atmel,pmecc-sector-size = <512>;
-+ atmel,pmecc-lookup-table-offset = <0x8000 0x10000>;
-+ gpios = <&pioD 5 0 /* rdy */
-+ &pioD 4 0 /* nce */
-+ 0 /* cd */
-+ >;
-+ partition@0 {
-+ ...
-+ };
-+};
-diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
-index 4ea0a04..712a705 100644
---- a/drivers/mtd/nand/atmel_nand.c
-+++ b/drivers/mtd/nand/atmel_nand.c
-@@ -93,6 +93,11 @@ struct atmel_nand_host {
-
- struct completion comp;
- struct dma_chan *dma_chan;
-+
-+ bool has_pmecc;
-+ u8 pmecc_corr_cap;
-+ u16 pmecc_sector_size;
-+ u32 pmecc_lookup_table_offset;
- };
-
- static int cpu_has_dma(void)
-@@ -477,7 +482,8 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
- static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
- struct device_node *np)
- {
-- u32 val;
-+ u32 val, table_offset;
-+ u32 offset[2];
- int ecc_mode;
- struct atmel_nand_data *board = &host->board;
- enum of_gpio_flags flags;
-@@ -513,6 +519,50 @@ static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
- board->enable_pin = of_get_gpio(np, 1);
- board->det_pin = of_get_gpio(np, 2);
-
-+ host->has_pmecc = of_property_read_bool(np, "atmel,has-pmecc");
-+
-+ if (!(board->ecc_mode == NAND_ECC_HW) || !host->has_pmecc)
-+ return 0; /* Not using PMECC */
-+
-+ /* use PMECC, get correction capability, sector size and lookup
-+ * table offset.
-+ */
-+ if (of_property_read_u32(np, "atmel,pmecc-cap", &val) != 0) {
-+ dev_err(host->dev, "Cannot decide PMECC Capability\n");
-+ return -EINVAL;
-+ } else if ((val != 2) && (val != 4) && (val != 8) && (val != 12) &&
-+ (val != 24)) {
-+ dev_err(host->dev,
-+ "Unsupported PMECC correction capability: %d; should be 2, 4, 8, 12 or 24\n",
-+ val);
-+ return -EINVAL;
-+ }
-+ host->pmecc_corr_cap = (u8)val;
-+
-+ if (of_property_read_u32(np, "atmel,pmecc-sector-size", &val) != 0) {
-+ dev_err(host->dev, "Cannot decide PMECC Sector Size\n");
-+ return -EINVAL;
-+ } else if ((val != 512) && (val != 1024)) {
-+ dev_err(host->dev,
-+ "Unsupported PMECC sector size: %d; should be 512 or 1024 bytes\n",
-+ val);
-+ return -EINVAL;
-+ }
-+ host->pmecc_sector_size = (u16)val;
-+
-+ if (of_property_read_u32_array(np, "atmel,pmecc-lookup-table-offset",
-+ offset, 2) != 0) {
-+ dev_err(host->dev, "Cannot get PMECC lookup table offset\n");
-+ return -EINVAL;
-+ }
-+ table_offset = host->pmecc_sector_size == 512 ? offset[0] : offset[1];
-+
-+ if (!table_offset) {
-+ dev_err(host->dev, "Invalid PMECC lookup table offset\n");
-+ return -EINVAL;
-+ }
-+ host->pmecc_lookup_table_offset = table_offset;
-+
- return 0;
- }
- #else
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 095fbbb23efb47cf006720652a877ffefe50c609 Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Fri, 29 Jun 2012 15:29:21 +0800
-Subject: MTD: at91: atmel_nand: Update driver to support Programmable Multibit
- ECC controller
-
-Is seen as commit 6dc4ff786c62fa34390607264d4d3ec54e22d5b7 upstream.
-
-The Programmable Multibit ECC (PMECC) controller is a programmable binary
-BCH(Bose, Chaudhuri and Hocquenghem) encoder and decoder. This controller
-can be used to support both SLC and MLC NAND Flash devices. It supports to
-generate ECC to correct 2, 4, 8, 12 or 24 bits of error per sector of data.
-
-To use PMECC in this driver, the user needs to set the address and size of
-PMECC, PMECC error location controllers and ROM. And also needs to pass the
-correction capability, the sector size and ROM lookup table offsets via dt.
-
-This driver has been tested on AT91SAM9X5-EK and AT91SAM9N12-EK with JFFS2,
-YAFFS2, UBIFS and mtd-utils.
-
-Signed-off-by: Hong Xu <hong.xu@atmel.com>
-Signed-off-by: Josh Wu <josh.wu@atmel.com>
-Tested-by: Richard Genoud <richard.genoud@gmail.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/mtd/nand/atmel_nand.c | 747 +++++++++++++++++++++++++++++++++++++-
- drivers/mtd/nand/atmel_nand_ecc.h | 114 +++++-
- 2 files changed, 859 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
-index 712a705..42b64fb 100644
---- a/drivers/mtd/nand/atmel_nand.c
-+++ b/drivers/mtd/nand/atmel_nand.c
-@@ -15,6 +15,8 @@
- * (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c)
- * (C) Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
- *
-+ * Add Programmable Multibit ECC support for various AT91 SoC
-+ * (C) Copyright 2012 ATMEL, Hong Xu
- *
- * 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
-@@ -98,8 +100,31 @@ struct atmel_nand_host {
- u8 pmecc_corr_cap;
- u16 pmecc_sector_size;
- u32 pmecc_lookup_table_offset;
-+
-+ int pmecc_bytes_per_sector;
-+ int pmecc_sector_number;
-+ int pmecc_degree; /* Degree of remainders */
-+ int pmecc_cw_len; /* Length of codeword */
-+
-+ void __iomem *pmerrloc_base;
-+ void __iomem *pmecc_rom_base;
-+
-+ /* lookup table for alpha_to and index_of */
-+ void __iomem *pmecc_alpha_to;
-+ void __iomem *pmecc_index_of;
-+
-+ /* data for pmecc computation */
-+ int16_t *pmecc_partial_syn;
-+ int16_t *pmecc_si;
-+ int16_t *pmecc_smu; /* Sigma table */
-+ int16_t *pmecc_lmu; /* polynomal order */
-+ int *pmecc_mu;
-+ int *pmecc_dmu;
-+ int *pmecc_delta;
- };
-
-+static struct nand_ecclayout atmel_pmecc_oobinfo;
-+
- static int cpu_has_dma(void)
- {
- return cpu_is_at91sam9rl() || cpu_is_at91sam9g45();
-@@ -293,6 +318,703 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
- }
-
- /*
-+ * Return number of ecc bytes per sector according to sector size and
-+ * correction capability
-+ *
-+ * Following table shows what at91 PMECC supported:
-+ * Correction Capability Sector_512_bytes Sector_1024_bytes
-+ * ===================== ================ =================
-+ * 2-bits 4-bytes 4-bytes
-+ * 4-bits 7-bytes 7-bytes
-+ * 8-bits 13-bytes 14-bytes
-+ * 12-bits 20-bytes 21-bytes
-+ * 24-bits 39-bytes 42-bytes
-+ */
-+static int __devinit pmecc_get_ecc_bytes(int cap, int sector_size)
-+{
-+ int m = 12 + sector_size / 512;
-+ return (m * cap + 7) / 8;
-+}
-+
-+static void __devinit pmecc_config_ecc_layout(struct nand_ecclayout *layout,
-+ int oobsize, int ecc_len)
-+{
-+ int i;
-+
-+ layout->eccbytes = ecc_len;
-+
-+ /* ECC will occupy the last ecc_len bytes continuously */
-+ for (i = 0; i < ecc_len; i++)
-+ layout->eccpos[i] = oobsize - ecc_len + i;
-+
-+ layout->oobfree[0].offset = 2;
-+ layout->oobfree[0].length =
-+ oobsize - ecc_len - layout->oobfree[0].offset;
-+}
-+
-+static void __devinit __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host)
-+{
-+ int table_size;
-+
-+ table_size = host->pmecc_sector_size == 512 ?
-+ PMECC_LOOKUP_TABLE_SIZE_512 : PMECC_LOOKUP_TABLE_SIZE_1024;
-+
-+ return host->pmecc_rom_base + host->pmecc_lookup_table_offset +
-+ table_size * sizeof(int16_t);
-+}
-+
-+static void pmecc_data_free(struct atmel_nand_host *host)
-+{
-+ kfree(host->pmecc_partial_syn);
-+ kfree(host->pmecc_si);
-+ kfree(host->pmecc_lmu);
-+ kfree(host->pmecc_smu);
-+ kfree(host->pmecc_mu);
-+ kfree(host->pmecc_dmu);
-+ kfree(host->pmecc_delta);
-+}
-+
-+static int __devinit pmecc_data_alloc(struct atmel_nand_host *host)
-+{
-+ const int cap = host->pmecc_corr_cap;
-+
-+ host->pmecc_partial_syn = kzalloc((2 * cap + 1) * sizeof(int16_t),
-+ GFP_KERNEL);
-+ host->pmecc_si = kzalloc((2 * cap + 1) * sizeof(int16_t), GFP_KERNEL);
-+ host->pmecc_lmu = kzalloc((cap + 1) * sizeof(int16_t), GFP_KERNEL);
-+ host->pmecc_smu = kzalloc((cap + 2) * (2 * cap + 1) * sizeof(int16_t),
-+ GFP_KERNEL);
-+ host->pmecc_mu = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL);
-+ host->pmecc_dmu = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL);
-+ host->pmecc_delta = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL);
-+
-+ if (host->pmecc_partial_syn &&
-+ host->pmecc_si &&
-+ host->pmecc_lmu &&
-+ host->pmecc_smu &&
-+ host->pmecc_mu &&
-+ host->pmecc_dmu &&
-+ host->pmecc_delta)
-+ return 0;
-+
-+ /* error happened */
-+ pmecc_data_free(host);
-+ return -ENOMEM;
-+}
-+
-+static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector)
-+{
-+ struct nand_chip *nand_chip = mtd->priv;
-+ struct atmel_nand_host *host = nand_chip->priv;
-+ int i;
-+ uint32_t value;
-+
-+ /* Fill odd syndromes */
-+ for (i = 0; i < host->pmecc_corr_cap; i++) {
-+ value = pmecc_readl_rem_relaxed(host->ecc, sector, i / 2);
-+ if (i & 1)
-+ value >>= 16;
-+ value &= 0xffff;
-+ host->pmecc_partial_syn[(2 * i) + 1] = (int16_t)value;
-+ }
-+}
-+
-+static void pmecc_substitute(struct mtd_info *mtd)
-+{
-+ struct nand_chip *nand_chip = mtd->priv;
-+ struct atmel_nand_host *host = nand_chip->priv;
-+ int16_t __iomem *alpha_to = host->pmecc_alpha_to;
-+ int16_t __iomem *index_of = host->pmecc_index_of;
-+ int16_t *partial_syn = host->pmecc_partial_syn;
-+ const int cap = host->pmecc_corr_cap;
-+ int16_t *si;
-+ int i, j;
-+
-+ /* si[] is a table that holds the current syndrome value,
-+ * an element of that table belongs to the field
-+ */
-+ si = host->pmecc_si;
-+
-+ memset(&si[1], 0, sizeof(int16_t) * (2 * cap - 1));
-+
-+ /* Computation 2t syndromes based on S(x) */
-+ /* Odd syndromes */
-+ for (i = 1; i < 2 * cap; i += 2) {
-+ for (j = 0; j < host->pmecc_degree; j++) {
-+ if (partial_syn[i] & ((unsigned short)0x1 << j))
-+ si[i] = readw_relaxed(alpha_to + i * j) ^ si[i];
-+ }
-+ }
-+ /* Even syndrome = (Odd syndrome) ** 2 */
-+ for (i = 2, j = 1; j <= cap; i = ++j << 1) {
-+ if (si[j] == 0) {
-+ si[i] = 0;
-+ } else {
-+ int16_t tmp;
-+
-+ tmp = readw_relaxed(index_of + si[j]);
-+ tmp = (tmp * 2) % host->pmecc_cw_len;
-+ si[i] = readw_relaxed(alpha_to + tmp);
-+ }
-+ }
-+
-+ return;
-+}
-+
-+static void pmecc_get_sigma(struct mtd_info *mtd)
-+{
-+ struct nand_chip *nand_chip = mtd->priv;
-+ struct atmel_nand_host *host = nand_chip->priv;
-+
-+ int16_t *lmu = host->pmecc_lmu;
-+ int16_t *si = host->pmecc_si;
-+ int *mu = host->pmecc_mu;
-+ int *dmu = host->pmecc_dmu; /* Discrepancy */
-+ int *delta = host->pmecc_delta; /* Delta order */
-+ int cw_len = host->pmecc_cw_len;
-+ const int16_t cap = host->pmecc_corr_cap;
-+ const int num = 2 * cap + 1;
-+ int16_t __iomem *index_of = host->pmecc_index_of;
-+ int16_t __iomem *alpha_to = host->pmecc_alpha_to;
-+ int i, j, k;
-+ uint32_t dmu_0_count, tmp;
-+ int16_t *smu = host->pmecc_smu;
-+
-+ /* index of largest delta */
-+ int ro;
-+ int largest;
-+ int diff;
-+
-+ dmu_0_count = 0;
-+
-+ /* First Row */
-+
-+ /* Mu */
-+ mu[0] = -1;
-+
-+ memset(smu, 0, sizeof(int16_t) * num);
-+ smu[0] = 1;
-+
-+ /* discrepancy set to 1 */
-+ dmu[0] = 1;
-+ /* polynom order set to 0 */
-+ lmu[0] = 0;
-+ delta[0] = (mu[0] * 2 - lmu[0]) >> 1;
-+
-+ /* Second Row */
-+
-+ /* Mu */
-+ mu[1] = 0;
-+ /* Sigma(x) set to 1 */
-+ memset(&smu[num], 0, sizeof(int16_t) * num);
-+ smu[num] = 1;
-+
-+ /* discrepancy set to S1 */
-+ dmu[1] = si[1];
-+
-+ /* polynom order set to 0 */
-+ lmu[1] = 0;
-+
-+ delta[1] = (mu[1] * 2 - lmu[1]) >> 1;
-+
-+ /* Init the Sigma(x) last row */
-+ memset(&smu[(cap + 1) * num], 0, sizeof(int16_t) * num);
-+
-+ for (i = 1; i <= cap; i++) {
-+ mu[i + 1] = i << 1;
-+ /* Begin Computing Sigma (Mu+1) and L(mu) */
-+ /* check if discrepancy is set to 0 */
-+ if (dmu[i] == 0) {
-+ dmu_0_count++;
-+
-+ tmp = ((cap - (lmu[i] >> 1) - 1) / 2);
-+ if ((cap - (lmu[i] >> 1) - 1) & 0x1)
-+ tmp += 2;
-+ else
-+ tmp += 1;
-+
-+ if (dmu_0_count == tmp) {
-+ for (j = 0; j <= (lmu[i] >> 1) + 1; j++)
-+ smu[(cap + 1) * num + j] =
-+ smu[i * num + j];
-+
-+ lmu[cap + 1] = lmu[i];
-+ return;
-+ }
-+
-+ /* copy polynom */
-+ for (j = 0; j <= lmu[i] >> 1; j++)
-+ smu[(i + 1) * num + j] = smu[i * num + j];
-+
-+ /* copy previous polynom order to the next */
-+ lmu[i + 1] = lmu[i];
-+ } else {
-+ ro = 0;
-+ largest = -1;
-+ /* find largest delta with dmu != 0 */
-+ for (j = 0; j < i; j++) {
-+ if ((dmu[j]) && (delta[j] > largest)) {
-+ largest = delta[j];
-+ ro = j;
-+ }
-+ }
-+
-+ /* compute difference */
-+ diff = (mu[i] - mu[ro]);
-+
-+ /* Compute degree of the new smu polynomial */
-+ if ((lmu[i] >> 1) > ((lmu[ro] >> 1) + diff))
-+ lmu[i + 1] = lmu[i];
-+ else
-+ lmu[i + 1] = ((lmu[ro] >> 1) + diff) * 2;
-+
-+ /* Init smu[i+1] with 0 */
-+ for (k = 0; k < num; k++)
-+ smu[(i + 1) * num + k] = 0;
-+
-+ /* Compute smu[i+1] */
-+ for (k = 0; k <= lmu[ro] >> 1; k++) {
-+ int16_t a, b, c;
-+
-+ if (!(smu[ro * num + k] && dmu[i]))
-+ continue;
-+ a = readw_relaxed(index_of + dmu[i]);
-+ b = readw_relaxed(index_of + dmu[ro]);
-+ c = readw_relaxed(index_of + smu[ro * num + k]);
-+ tmp = a + (cw_len - b) + c;
-+ a = readw_relaxed(alpha_to + tmp % cw_len);
-+ smu[(i + 1) * num + (k + diff)] = a;
-+ }
-+
-+ for (k = 0; k <= lmu[i] >> 1; k++)
-+ smu[(i + 1) * num + k] ^= smu[i * num + k];
-+ }
-+
-+ /* End Computing Sigma (Mu+1) and L(mu) */
-+ /* In either case compute delta */
-+ delta[i + 1] = (mu[i + 1] * 2 - lmu[i + 1]) >> 1;
-+
-+ /* Do not compute discrepancy for the last iteration */
-+ if (i >= cap)
-+ continue;
-+
-+ for (k = 0; k <= (lmu[i + 1] >> 1); k++) {
-+ tmp = 2 * (i - 1);
-+ if (k == 0) {
-+ dmu[i + 1] = si[tmp + 3];
-+ } else if (smu[(i + 1) * num + k] && si[tmp + 3 - k]) {
-+ int16_t a, b, c;
-+ a = readw_relaxed(index_of +
-+ smu[(i + 1) * num + k]);
-+ b = si[2 * (i - 1) + 3 - k];
-+ c = readw_relaxed(index_of + b);
-+ tmp = a + c;
-+ tmp %= cw_len;
-+ dmu[i + 1] = readw_relaxed(alpha_to + tmp) ^
-+ dmu[i + 1];
-+ }
-+ }
-+ }
-+
-+ return;
-+}
-+
-+static int pmecc_err_location(struct mtd_info *mtd)
-+{
-+ struct nand_chip *nand_chip = mtd->priv;
-+ struct atmel_nand_host *host = nand_chip->priv;
-+ unsigned long end_time;
-+ const int cap = host->pmecc_corr_cap;
-+ const int num = 2 * cap + 1;
-+ int sector_size = host->pmecc_sector_size;
-+ int err_nbr = 0; /* number of error */
-+ int roots_nbr; /* number of roots */
-+ int i;
-+ uint32_t val;
-+ int16_t *smu = host->pmecc_smu;
-+
-+ pmerrloc_writel(host->pmerrloc_base, ELDIS, PMERRLOC_DISABLE);
-+
-+ for (i = 0; i <= host->pmecc_lmu[cap + 1] >> 1; i++) {
-+ pmerrloc_writel_sigma_relaxed(host->pmerrloc_base, i,
-+ smu[(cap + 1) * num + i]);
-+ err_nbr++;
-+ }
-+
-+ val = (err_nbr - 1) << 16;
-+ if (sector_size == 1024)
-+ val |= 1;
-+
-+ pmerrloc_writel(host->pmerrloc_base, ELCFG, val);
-+ pmerrloc_writel(host->pmerrloc_base, ELEN,
-+ sector_size * 8 + host->pmecc_degree * cap);
-+
-+ end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS);
-+ while (!(pmerrloc_readl_relaxed(host->pmerrloc_base, ELISR)
-+ & PMERRLOC_CALC_DONE)) {
-+ if (unlikely(time_after(jiffies, end_time))) {
-+ dev_err(host->dev, "PMECC: Timeout to calculate error location.\n");
-+ return -1;
-+ }
-+ cpu_relax();
-+ }
-+
-+ roots_nbr = (pmerrloc_readl_relaxed(host->pmerrloc_base, ELISR)
-+ & PMERRLOC_ERR_NUM_MASK) >> 8;
-+ /* Number of roots == degree of smu hence <= cap */
-+ if (roots_nbr == host->pmecc_lmu[cap + 1] >> 1)
-+ return err_nbr - 1;
-+
-+ /* Number of roots does not match the degree of smu
-+ * unable to correct error */
-+ return -1;
-+}
-+
-+static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
-+ int sector_num, int extra_bytes, int err_nbr)
-+{
-+ struct nand_chip *nand_chip = mtd->priv;
-+ struct atmel_nand_host *host = nand_chip->priv;
-+ int i = 0;
-+ int byte_pos, bit_pos, sector_size, pos;
-+ uint32_t tmp;
-+ uint8_t err_byte;
-+
-+ sector_size = host->pmecc_sector_size;
-+
-+ while (err_nbr) {
-+ tmp = pmerrloc_readl_el_relaxed(host->pmerrloc_base, i) - 1;
-+ byte_pos = tmp / 8;
-+ bit_pos = tmp % 8;
-+
-+ if (byte_pos >= (sector_size + extra_bytes))
-+ BUG(); /* should never happen */
-+
-+ if (byte_pos < sector_size) {
-+ err_byte = *(buf + byte_pos);
-+ *(buf + byte_pos) ^= (1 << bit_pos);
-+
-+ pos = sector_num * host->pmecc_sector_size + byte_pos;
-+ dev_info(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
-+ pos, bit_pos, err_byte, *(buf + byte_pos));
-+ } else {
-+ /* Bit flip in OOB area */
-+ tmp = sector_num * host->pmecc_bytes_per_sector
-+ + (byte_pos - sector_size);
-+ err_byte = ecc[tmp];
-+ ecc[tmp] ^= (1 << bit_pos);
-+
-+ pos = tmp + nand_chip->ecc.layout->eccpos[0];
-+ dev_info(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
-+ pos, bit_pos, err_byte, ecc[tmp]);
-+ }
-+
-+ i++;
-+ err_nbr--;
-+ }
-+
-+ return;
-+}
-+
-+static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf,
-+ u8 *ecc)
-+{
-+ struct nand_chip *nand_chip = mtd->priv;
-+ struct atmel_nand_host *host = nand_chip->priv;
-+ int i, err_nbr, eccbytes;
-+ uint8_t *buf_pos;
-+
-+ eccbytes = nand_chip->ecc.bytes;
-+ for (i = 0; i < eccbytes; i++)
-+ if (ecc[i] != 0xff)
-+ goto normal_check;
-+ /* Erased page, return OK */
-+ return 0;
-+
-+normal_check:
-+ for (i = 0; i < host->pmecc_sector_number; i++) {
-+ err_nbr = 0;
-+ if (pmecc_stat & 0x1) {
-+ buf_pos = buf + i * host->pmecc_sector_size;
-+
-+ pmecc_gen_syndrome(mtd, i);
-+ pmecc_substitute(mtd);
-+ pmecc_get_sigma(mtd);
-+
-+ err_nbr = pmecc_err_location(mtd);
-+ if (err_nbr == -1) {
-+ dev_err(host->dev, "PMECC: Too many errors\n");
-+ mtd->ecc_stats.failed++;
-+ return -EIO;
-+ } else {
-+ pmecc_correct_data(mtd, buf_pos, ecc, i,
-+ host->pmecc_bytes_per_sector, err_nbr);
-+ mtd->ecc_stats.corrected += err_nbr;
-+ }
-+ }
-+ pmecc_stat >>= 1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
-+ struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
-+{
-+ struct atmel_nand_host *host = chip->priv;
-+ int eccsize = chip->ecc.size;
-+ uint8_t *oob = chip->oob_poi;
-+ uint32_t *eccpos = chip->ecc.layout->eccpos;
-+ uint32_t stat;
-+ unsigned long end_time;
-+
-+ pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
-+ pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
-+ pmecc_writel(host->ecc, CFG, (pmecc_readl_relaxed(host->ecc, CFG)
-+ & ~PMECC_CFG_WRITE_OP) | PMECC_CFG_AUTO_ENABLE);
-+
-+ pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE);
-+ pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA);
-+
-+ chip->read_buf(mtd, buf, eccsize);
-+ chip->read_buf(mtd, oob, mtd->oobsize);
-+
-+ end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS);
-+ while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) {
-+ if (unlikely(time_after(jiffies, end_time))) {
-+ dev_err(host->dev, "PMECC: Timeout to get error status.\n");
-+ return -EIO;
-+ }
-+ cpu_relax();
-+ }
-+
-+ stat = pmecc_readl_relaxed(host->ecc, ISR);
-+ if (stat != 0)
-+ if (pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]) != 0)
-+ return -EIO;
-+
-+ return 0;
-+}
-+
-+static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
-+ struct nand_chip *chip, const uint8_t *buf, int oob_required)
-+{
-+ struct atmel_nand_host *host = chip->priv;
-+ uint32_t *eccpos = chip->ecc.layout->eccpos;
-+ int i, j;
-+ unsigned long end_time;
-+
-+ pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
-+ pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
-+
-+ pmecc_writel(host->ecc, CFG, (pmecc_readl_relaxed(host->ecc, CFG) |
-+ PMECC_CFG_WRITE_OP) & ~PMECC_CFG_AUTO_ENABLE);
-+
-+ pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE);
-+ pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA);
-+
-+ chip->write_buf(mtd, (u8 *)buf, mtd->writesize);
-+
-+ end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS);
-+ while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) {
-+ if (unlikely(time_after(jiffies, end_time))) {
-+ dev_err(host->dev, "PMECC: Timeout to get ECC value.\n");
-+ return -EIO;
-+ }
-+ cpu_relax();
-+ }
-+
-+ for (i = 0; i < host->pmecc_sector_number; i++) {
-+ for (j = 0; j < host->pmecc_bytes_per_sector; j++) {
-+ int pos;
-+
-+ pos = i * host->pmecc_bytes_per_sector + j;
-+ chip->oob_poi[eccpos[pos]] =
-+ pmecc_readb_ecc_relaxed(host->ecc, i, j);
-+ }
-+ }
-+ chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
-+
-+ return 0;
-+}
-+
-+static void atmel_pmecc_core_init(struct mtd_info *mtd)
-+{
-+ struct nand_chip *nand_chip = mtd->priv;
-+ struct atmel_nand_host *host = nand_chip->priv;
-+ uint32_t val = 0;
-+ struct nand_ecclayout *ecc_layout;
-+
-+ pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
-+ pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
-+
-+ switch (host->pmecc_corr_cap) {
-+ case 2:
-+ val = PMECC_CFG_BCH_ERR2;
-+ break;
-+ case 4:
-+ val = PMECC_CFG_BCH_ERR4;
-+ break;
-+ case 8:
-+ val = PMECC_CFG_BCH_ERR8;
-+ break;
-+ case 12:
-+ val = PMECC_CFG_BCH_ERR12;
-+ break;
-+ case 24:
-+ val = PMECC_CFG_BCH_ERR24;
-+ break;
-+ }
-+
-+ if (host->pmecc_sector_size == 512)
-+ val |= PMECC_CFG_SECTOR512;
-+ else if (host->pmecc_sector_size == 1024)
-+ val |= PMECC_CFG_SECTOR1024;
-+
-+ switch (host->pmecc_sector_number) {
-+ case 1:
-+ val |= PMECC_CFG_PAGE_1SECTOR;
-+ break;
-+ case 2:
-+ val |= PMECC_CFG_PAGE_2SECTORS;
-+ break;
-+ case 4:
-+ val |= PMECC_CFG_PAGE_4SECTORS;
-+ break;
-+ case 8:
-+ val |= PMECC_CFG_PAGE_8SECTORS;
-+ break;
-+ }
-+
-+ val |= (PMECC_CFG_READ_OP | PMECC_CFG_SPARE_DISABLE
-+ | PMECC_CFG_AUTO_DISABLE);
-+ pmecc_writel(host->ecc, CFG, val);
-+
-+ ecc_layout = nand_chip->ecc.layout;
-+ pmecc_writel(host->ecc, SAREA, mtd->oobsize - 1);
-+ pmecc_writel(host->ecc, SADDR, ecc_layout->eccpos[0]);
-+ pmecc_writel(host->ecc, EADDR,
-+ ecc_layout->eccpos[ecc_layout->eccbytes - 1]);
-+ /* See datasheet about PMECC Clock Control Register */
-+ pmecc_writel(host->ecc, CLK, 2);
-+ pmecc_writel(host->ecc, IDR, 0xff);
-+ pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE);
-+}
-+
-+static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev,
-+ struct atmel_nand_host *host)
-+{
-+ struct mtd_info *mtd = &host->mtd;
-+ struct nand_chip *nand_chip = &host->nand_chip;
-+ struct resource *regs, *regs_pmerr, *regs_rom;
-+ int cap, sector_size, err_no;
-+
-+ cap = host->pmecc_corr_cap;
-+ sector_size = host->pmecc_sector_size;
-+ dev_info(host->dev, "Initialize PMECC params, cap: %d, sector: %d\n",
-+ cap, sector_size);
-+
-+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+ if (!regs) {
-+ dev_warn(host->dev,
-+ "Can't get I/O resource regs for PMECC controller, rolling back on software ECC\n");
-+ nand_chip->ecc.mode = NAND_ECC_SOFT;
-+ return 0;
-+ }
-+
-+ host->ecc = ioremap(regs->start, resource_size(regs));
-+ if (host->ecc == NULL) {
-+ dev_err(host->dev, "ioremap failed\n");
-+ err_no = -EIO;
-+ goto err_pmecc_ioremap;
-+ }
-+
-+ regs_pmerr = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-+ regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3);
-+ if (regs_pmerr && regs_rom) {
-+ host->pmerrloc_base = ioremap(regs_pmerr->start,
-+ resource_size(regs_pmerr));
-+ host->pmecc_rom_base = ioremap(regs_rom->start,
-+ resource_size(regs_rom));
-+ }
-+
-+ if (!host->pmerrloc_base || !host->pmecc_rom_base) {
-+ dev_err(host->dev,
-+ "Can not get I/O resource for PMECC ERRLOC controller or ROM!\n");
-+ err_no = -EIO;
-+ goto err_pmloc_ioremap;
-+ }
-+
-+ /* ECC is calculated for the whole page (1 step) */
-+ nand_chip->ecc.size = mtd->writesize;
-+
-+ /* set ECC page size and oob layout */
-+ switch (mtd->writesize) {
-+ case 2048:
-+ host->pmecc_degree = PMECC_GF_DIMENSION_13;
-+ host->pmecc_cw_len = (1 << host->pmecc_degree) - 1;
-+ host->pmecc_sector_number = mtd->writesize / sector_size;
-+ host->pmecc_bytes_per_sector = pmecc_get_ecc_bytes(
-+ cap, sector_size);
-+ host->pmecc_alpha_to = pmecc_get_alpha_to(host);
-+ host->pmecc_index_of = host->pmecc_rom_base +
-+ host->pmecc_lookup_table_offset;
-+
-+ nand_chip->ecc.steps = 1;
-+ nand_chip->ecc.strength = cap;
-+ nand_chip->ecc.bytes = host->pmecc_bytes_per_sector *
-+ host->pmecc_sector_number;
-+ if (nand_chip->ecc.bytes > mtd->oobsize - 2) {
-+ dev_err(host->dev, "No room for ECC bytes\n");
-+ err_no = -EINVAL;
-+ goto err_no_ecc_room;
-+ }
-+ pmecc_config_ecc_layout(&atmel_pmecc_oobinfo,
-+ mtd->oobsize,
-+ nand_chip->ecc.bytes);
-+ nand_chip->ecc.layout = &atmel_pmecc_oobinfo;
-+ break;
-+ case 512:
-+ case 1024:
-+ case 4096:
-+ /* TODO */
-+ dev_warn(host->dev,
-+ "Unsupported page size for PMECC, use Software ECC\n");
-+ default:
-+ /* page size not handled by HW ECC */
-+ /* switching back to soft ECC */
-+ nand_chip->ecc.mode = NAND_ECC_SOFT;
-+ return 0;
-+ }
-+
-+ /* Allocate data for PMECC computation */
-+ err_no = pmecc_data_alloc(host);
-+ if (err_no) {
-+ dev_err(host->dev,
-+ "Cannot allocate memory for PMECC computation!\n");
-+ goto err_pmecc_data_alloc;
-+ }
-+
-+ nand_chip->ecc.read_page = atmel_nand_pmecc_read_page;
-+ nand_chip->ecc.write_page = atmel_nand_pmecc_write_page;
-+
-+ atmel_pmecc_core_init(mtd);
-+
-+ return 0;
-+
-+err_pmecc_data_alloc:
-+err_no_ecc_room:
-+err_pmloc_ioremap:
-+ iounmap(host->ecc);
-+ if (host->pmerrloc_base)
-+ iounmap(host->pmerrloc_base);
-+ if (host->pmecc_rom_base)
-+ iounmap(host->pmecc_rom_base);
-+err_pmecc_ioremap:
-+ return err_no;
-+}
-+
-+/*
- * Calculate HW ECC
- *
- * function called after a write
-@@ -743,7 +1465,11 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
- }
-
- if (nand_chip->ecc.mode == NAND_ECC_HW) {
-- res = atmel_hw_nand_init_params(pdev, host);
-+ if (host->has_pmecc)
-+ res = atmel_pmecc_nand_init_params(pdev, host);
-+ else
-+ res = atmel_hw_nand_init_params(pdev, host);
-+
- if (res != 0)
- goto err_hw_ecc;
- }
-@@ -762,8 +1488,16 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
- return res;
-
- err_scan_tail:
-+ if (host->has_pmecc && host->nand_chip.ecc.mode == NAND_ECC_HW) {
-+ pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
-+ pmecc_data_free(host);
-+ }
- if (host->ecc)
- iounmap(host->ecc);
-+ if (host->pmerrloc_base)
-+ iounmap(host->pmerrloc_base);
-+ if (host->pmecc_rom_base)
-+ iounmap(host->pmecc_rom_base);
- err_hw_ecc:
- err_scan_ident:
- err_no_card:
-@@ -789,8 +1523,19 @@ static int __exit atmel_nand_remove(struct platform_device *pdev)
-
- atmel_nand_disable(host);
-
-+ if (host->has_pmecc && host->nand_chip.ecc.mode == NAND_ECC_HW) {
-+ pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
-+ pmerrloc_writel(host->pmerrloc_base, ELDIS,
-+ PMERRLOC_DISABLE);
-+ pmecc_data_free(host);
-+ }
-+
- if (host->ecc)
- iounmap(host->ecc);
-+ if (host->pmecc_rom_base)
-+ iounmap(host->pmecc_rom_base);
-+ if (host->pmerrloc_base)
-+ iounmap(host->pmerrloc_base);
-
- if (host->dma_chan)
- dma_release_channel(host->dma_chan);
-diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h
-index 578c776..8a1e9a6 100644
---- a/drivers/mtd/nand/atmel_nand_ecc.h
-+++ b/drivers/mtd/nand/atmel_nand_ecc.h
-@@ -3,7 +3,7 @@
- * Based on AT91SAM9260 datasheet revision B.
- *
- * Copyright (C) 2007 Andrew Victor
-- * Copyright (C) 2007 Atmel Corporation.
-+ * Copyright (C) 2007 - 2012 Atmel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
-@@ -36,4 +36,116 @@
- #define ATMEL_ECC_NPR 0x10 /* NParity register */
- #define ATMEL_ECC_NPARITY (0xffff << 0) /* NParity */
-
-+/* PMECC Register Definitions */
-+#define ATMEL_PMECC_CFG 0x000 /* Configuration Register */
-+#define PMECC_CFG_BCH_ERR2 (0 << 0)
-+#define PMECC_CFG_BCH_ERR4 (1 << 0)
-+#define PMECC_CFG_BCH_ERR8 (2 << 0)
-+#define PMECC_CFG_BCH_ERR12 (3 << 0)
-+#define PMECC_CFG_BCH_ERR24 (4 << 0)
-+
-+#define PMECC_CFG_SECTOR512 (0 << 4)
-+#define PMECC_CFG_SECTOR1024 (1 << 4)
-+
-+#define PMECC_CFG_PAGE_1SECTOR (0 << 8)
-+#define PMECC_CFG_PAGE_2SECTORS (1 << 8)
-+#define PMECC_CFG_PAGE_4SECTORS (2 << 8)
-+#define PMECC_CFG_PAGE_8SECTORS (3 << 8)
-+
-+#define PMECC_CFG_READ_OP (0 << 12)
-+#define PMECC_CFG_WRITE_OP (1 << 12)
-+
-+#define PMECC_CFG_SPARE_ENABLE (1 << 16)
-+#define PMECC_CFG_SPARE_DISABLE (0 << 16)
-+
-+#define PMECC_CFG_AUTO_ENABLE (1 << 20)
-+#define PMECC_CFG_AUTO_DISABLE (0 << 20)
-+
-+#define ATMEL_PMECC_SAREA 0x004 /* Spare area size */
-+#define ATMEL_PMECC_SADDR 0x008 /* PMECC starting address */
-+#define ATMEL_PMECC_EADDR 0x00c /* PMECC ending address */
-+#define ATMEL_PMECC_CLK 0x010 /* PMECC clock control */
-+#define PMECC_CLK_133MHZ (2 << 0)
-+
-+#define ATMEL_PMECC_CTRL 0x014 /* PMECC control register */
-+#define PMECC_CTRL_RST (1 << 0)
-+#define PMECC_CTRL_DATA (1 << 1)
-+#define PMECC_CTRL_USER (1 << 2)
-+#define PMECC_CTRL_ENABLE (1 << 4)
-+#define PMECC_CTRL_DISABLE (1 << 5)
-+
-+#define ATMEL_PMECC_SR 0x018 /* PMECC status register */
-+#define PMECC_SR_BUSY (1 << 0)
-+#define PMECC_SR_ENABLE (1 << 4)
-+
-+#define ATMEL_PMECC_IER 0x01c /* PMECC interrupt enable */
-+#define PMECC_IER_ENABLE (1 << 0)
-+#define ATMEL_PMECC_IDR 0x020 /* PMECC interrupt disable */
-+#define PMECC_IER_DISABLE (1 << 0)
-+#define ATMEL_PMECC_IMR 0x024 /* PMECC interrupt mask */
-+#define PMECC_IER_MASK (1 << 0)
-+#define ATMEL_PMECC_ISR 0x028 /* PMECC interrupt status */
-+#define ATMEL_PMECC_ECCx 0x040 /* PMECC ECC x */
-+#define ATMEL_PMECC_REMx 0x240 /* PMECC REM x */
-+
-+/* PMERRLOC Register Definitions */
-+#define ATMEL_PMERRLOC_ELCFG 0x000 /* Error location config */
-+#define PMERRLOC_ELCFG_SECTOR_512 (0 << 0)
-+#define PMERRLOC_ELCFG_SECTOR_1024 (1 << 0)
-+#define PMERRLOC_ELCFG_NUM_ERRORS(n) ((n) << 16)
-+
-+#define ATMEL_PMERRLOC_ELPRIM 0x004 /* Error location primitive */
-+#define ATMEL_PMERRLOC_ELEN 0x008 /* Error location enable */
-+#define ATMEL_PMERRLOC_ELDIS 0x00c /* Error location disable */
-+#define PMERRLOC_DISABLE (1 << 0)
-+
-+#define ATMEL_PMERRLOC_ELSR 0x010 /* Error location status */
-+#define PMERRLOC_ELSR_BUSY (1 << 0)
-+#define ATMEL_PMERRLOC_ELIER 0x014 /* Error location int enable */
-+#define ATMEL_PMERRLOC_ELIDR 0x018 /* Error location int disable */
-+#define ATMEL_PMERRLOC_ELIMR 0x01c /* Error location int mask */
-+#define ATMEL_PMERRLOC_ELISR 0x020 /* Error location int status */
-+#define PMERRLOC_ERR_NUM_MASK (0x1f << 8)
-+#define PMERRLOC_CALC_DONE (1 << 0)
-+#define ATMEL_PMERRLOC_SIGMAx 0x028 /* Error location SIGMA x */
-+#define ATMEL_PMERRLOC_ELx 0x08c /* Error location x */
-+
-+/* Register access macros for PMECC */
-+#define pmecc_readl_relaxed(addr, reg) \
-+ readl_relaxed((addr) + ATMEL_PMECC_##reg)
-+
-+#define pmecc_writel(addr, reg, value) \
-+ writel((value), (addr) + ATMEL_PMECC_##reg)
-+
-+#define pmecc_readb_ecc_relaxed(addr, sector, n) \
-+ readb_relaxed((addr) + ATMEL_PMECC_ECCx + ((sector) * 0x40) + (n))
-+
-+#define pmecc_readl_rem_relaxed(addr, sector, n) \
-+ readl_relaxed((addr) + ATMEL_PMECC_REMx + ((sector) * 0x40) + ((n) * 4))
-+
-+#define pmerrloc_readl_relaxed(addr, reg) \
-+ readl_relaxed((addr) + ATMEL_PMERRLOC_##reg)
-+
-+#define pmerrloc_writel(addr, reg, value) \
-+ writel((value), (addr) + ATMEL_PMERRLOC_##reg)
-+
-+#define pmerrloc_writel_sigma_relaxed(addr, n, value) \
-+ writel_relaxed((value), (addr) + ATMEL_PMERRLOC_SIGMAx + ((n) * 4))
-+
-+#define pmerrloc_readl_sigma_relaxed(addr, n) \
-+ readl_relaxed((addr) + ATMEL_PMERRLOC_SIGMAx + ((n) * 4))
-+
-+#define pmerrloc_readl_el_relaxed(addr, n) \
-+ readl_relaxed((addr) + ATMEL_PMERRLOC_ELx + ((n) * 4))
-+
-+/* Galois field dimension */
-+#define PMECC_GF_DIMENSION_13 13
-+#define PMECC_GF_DIMENSION_14 14
-+
-+#define PMECC_LOOKUP_TABLE_SIZE_512 0x2000
-+#define PMECC_LOOKUP_TABLE_SIZE_1024 0x4000
-+
-+/* Time out value for reading PMECC status register */
-+#define PMECC_MAX_TIMEOUT_MS 100
-+
- #endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 8a6cf5507a3070841f8b4636af42d847d885f50d Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Mon, 25 Jun 2012 15:15:54 +0800
-Subject: MTD: nand: add return value for write_page()/write_page_raw()
- functions in structure of nand_ecc_ctrl.
-
-Is the equivalent of commit fdbad98dff8007f2b8bee6698b5d25ebba0471c9 upstream.
-
-There is an implemention of hardware ECC write page function which may return an
-error indication.
-For instance, using Atmel HW PMECC to write one page into a nand flash, the hardware
-engine will compute the BCH ecc code for this page. so we need read a the
-status register to theck whether the ecc code is generated.
-But we cannot assume the status register always can be ready, for example,
-incorrect hardware configuration or hardware issue, in such case we need
-write_page() to return a error code.
-
-Since the definition of 'write_page' function in struct nand_ecc_ctrl is 'void'.
-So this patch will:
- 1. add return 'int' value for 'write_page' function.
- 2. to be consitent, add return 'int' value for 'write_page_raw' fuctions too.
- 3. add code to test the return value, and if negative, indicate an
- error happend when write page with ECC.
- 4. fix the compile warning in all impacted nand flash driver.
-
-Note: I couldn't compile-test all of these easily, as some had ARCH dependencies.
-
-Signed-off-by: Josh Wu <josh.wu@atmel.com>
----
- drivers/mtd/nand/nand_base.c | 27 +++++++++++++++++++--------
- include/linux/mtd/nand.h | 4 ++--
- 2 files changed, 21 insertions(+), 10 deletions(-)
-
---- a/drivers/mtd/nand/nand_base.c
-+++ b/drivers/mtd/nand/nand_base.c
-@@ -1922,11 +1922,13 @@ out:
- *
- * Not for syndrome calculating ECC controllers, which use a special oob layout.
- */
--static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
-+static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf)
- {
- chip->write_buf(mtd, buf, mtd->writesize);
- chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
-+
-+ return 0;
- }
-
- /**
-@@ -1937,7 +1939,7 @@ static void nand_write_page_raw(struct m
- *
- * We need a special oob layout and handling even when ECC isn't checked.
- */
--static void nand_write_page_raw_syndrome(struct mtd_info *mtd,
-+static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
- struct nand_chip *chip,
- const uint8_t *buf)
- {
-@@ -1967,6 +1969,8 @@ static void nand_write_page_raw_syndrome
- size = mtd->oobsize - (oob - chip->oob_poi);
- if (size)
- chip->write_buf(mtd, oob, size);
-+
-+ return 0;
- }
- /**
- * nand_write_page_swecc - [REPLACEABLE] software ECC based page write function
-@@ -1974,7 +1978,7 @@ static void nand_write_page_raw_syndrome
- * @chip: nand chip info structure
- * @buf: data buffer
- */
--static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
-+static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf)
- {
- int i, eccsize = chip->ecc.size;
-@@ -1991,7 +1995,7 @@ static void nand_write_page_swecc(struct
- for (i = 0; i < chip->ecc.total; i++)
- chip->oob_poi[eccpos[i]] = ecc_calc[i];
-
-- chip->ecc.write_page_raw(mtd, chip, buf);
-+ return chip->ecc.write_page_raw(mtd, chip, buf);
- }
-
- /**
-@@ -2000,7 +2004,7 @@ static void nand_write_page_swecc(struct
- * @chip: nand chip info structure
- * @buf: data buffer
- */
--static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
-+static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf)
- {
- int i, eccsize = chip->ecc.size;
-@@ -2020,6 +2024,8 @@ static void nand_write_page_hwecc(struct
- chip->oob_poi[eccpos[i]] = ecc_calc[i];
-
- chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
-+
-+ return 0;
- }
-
- /**
-@@ -2031,7 +2037,7 @@ static void nand_write_page_hwecc(struct
- * The hw generator calculates the error syndrome automatically. Therefore we
- * need a special oob layout and handling.
- */
--static void nand_write_page_syndrome(struct mtd_info *mtd,
-+static int nand_write_page_syndrome(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf)
- {
- int i, eccsize = chip->ecc.size;
-@@ -2064,6 +2070,8 @@ static void nand_write_page_syndrome(str
- i = mtd->oobsize - (oob - chip->oob_poi);
- if (i)
- chip->write_buf(mtd, oob, i);
-+
-+ return 0;
- }
-
- /**
-@@ -2083,9 +2091,12 @@ static int nand_write_page(struct mtd_in
- chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
-
- if (unlikely(raw))
-- chip->ecc.write_page_raw(mtd, chip, buf);
-+ status = chip->ecc.write_page_raw(mtd, chip, buf);
- else
-- chip->ecc.write_page(mtd, chip, buf);
-+ status = chip->ecc.write_page(mtd, chip, buf);
-+
-+ if (status < 0)
-+ return status;
-
- /*
- * Cached progamming disabled for now. Not sure if it's worth the
---- a/include/linux/mtd/nand.h
-+++ b/include/linux/mtd/nand.h
-@@ -361,13 +361,13 @@ struct nand_ecc_ctrl {
- uint8_t *calc_ecc);
- int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int page);
-- void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
-+ int (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf);
- int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int page);
- int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
- uint32_t offs, uint32_t len, uint8_t *buf);
-- void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
-+ int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf);
- int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip,
- int page);
+++ /dev/null
-From b9401beeb6444e9e2bc4de97b1efc2ac9491a34f Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Thu, 12 Jul 2012 13:20:22 +0800
-Subject: MTD: atmel nand: fix gpio missing request
-
-commit 28446acb1f8268cda4b2076f72519534f84d6a36 upstream.
-
-without this the gpio will not be muxed as a gpio by the current custom pinmux
-or later by the pinctrl
-
-Acked-by: Linus Walleij <linus.walleij@linaro.org>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- drivers/mtd/nand/atmel_nand.c | 50 ++++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 49 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
-index 42b64fb..c512bba 100644
---- a/drivers/mtd/nand/atmel_nand.c
-+++ b/drivers/mtd/nand/atmel_nand.c
-@@ -1410,8 +1410,41 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
- nand_chip->IO_ADDR_W = host->io_base;
- nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
-
-- if (gpio_is_valid(host->board.rdy_pin))
-+ if (gpio_is_valid(host->board.rdy_pin)) {
-+ res = devm_gpio_request(&pdev->dev,
-+ host->board.rdy_pin, "nand_rdy");
-+ if (res < 0) {
-+ dev_err(&pdev->dev,
-+ "can't request rdy gpio %d\n", host->board.rdy_pin);
-+ goto err_ecc_ioremap;
-+ }
-+
-+ res = gpio_direction_input(host->board.rdy_pin);
-+ if (res < 0) {
-+ dev_err(&pdev->dev,
-+ "can't request input direction rdy gpio %d\n", host->board.rdy_pin);
-+ goto err_ecc_ioremap;
-+ }
-+
- nand_chip->dev_ready = atmel_nand_device_ready;
-+ }
-+
-+ if (gpio_is_valid(host->board.enable_pin)) {
-+ res = devm_gpio_request(&pdev->dev,
-+ host->board.enable_pin, "nand_enable");
-+ if (res < 0) {
-+ dev_err(&pdev->dev,
-+ "can't request enable gpio %d\n", host->board.enable_pin);
-+ goto err_ecc_ioremap;
-+ }
-+
-+ res = gpio_direction_output(host->board.enable_pin, 1);
-+ if (res < 0) {
-+ dev_err(&pdev->dev,
-+ "can't request output direction enable gpio %d\n", host->board.enable_pin);
-+ goto err_ecc_ioremap;
-+ }
-+ }
-
- nand_chip->ecc.mode = host->board.ecc_mode;
- nand_chip->chip_delay = 20; /* 20us command delay time */
-@@ -1426,6 +1459,21 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
- atmel_nand_enable(host);
-
- if (gpio_is_valid(host->board.det_pin)) {
-+ res = devm_gpio_request(&pdev->dev,
-+ host->board.det_pin, "nand_det");
-+ if (res < 0) {
-+ dev_err(&pdev->dev,
-+ "can't request det gpio %d\n", host->board.det_pin);
-+ goto err_no_card;
-+ }
-+
-+ res = gpio_direction_input(host->board.det_pin);
-+ if (res < 0) {
-+ dev_err(&pdev->dev,
-+ "can't request input direction det gpio %d\n", host->board.det_pin);
-+ goto err_no_card;
-+ }
-+
- if (gpio_get_value(host->board.det_pin)) {
- printk(KERN_INFO "No SmartMedia card inserted.\n");
- res = -ENXIO;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 0e4179bc4720ad2cc938df8eda49685e84be6e91 Mon Sep 17 00:00:00 2001
-From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
-Date: Fri, 7 Sep 2012 14:54:25 +0800
-Subject: usb: gadget: at91_udc: move the dereference below the NULL test
-
-commit 162ca3ca613e02e115ec9c5273f94bd22dad0af2 upstream.
-
-The dereference should be moved below the NULL test.
-
-spatch with a semantic match is used to found this.
-(http://coccinelle.lip6.fr/)
-
-Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
-Signed-off-by: Felipe Balbi <balbi@ti.com>
----
- drivers/usb/gadget/at91_udc.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
-index 9d7bcd9..d6249f0 100644
---- a/drivers/usb/gadget/at91_udc.c
-+++ b/drivers/usb/gadget/at91_udc.c
-@@ -469,7 +469,7 @@ static int at91_ep_enable(struct usb_ep *_ep,
- const struct usb_endpoint_descriptor *desc)
- {
- struct at91_ep *ep = container_of(_ep, struct at91_ep, ep);
-- struct at91_udc *udc = ep->udc;
-+ struct at91_udc *udc;
- u16 maxpacket;
- u32 tmp;
- unsigned long flags;
-@@ -484,6 +484,7 @@ static int at91_ep_enable(struct usb_ep *_ep,
- return -EINVAL;
- }
-
-+ udc = ep->udc;
- if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
- DBG("bogus device state\n");
- return -ESHUTDOWN;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2b2b3800d382a683216a2e0fc6a27ba480716f2a Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Wed, 29 Aug 2012 11:49:18 +0200
-Subject: USB: ohci-at91: fix PIO handling in relation with number of ports
-
-commit 6fffb77c8393151b0cf8cef1b9c2ba90587dd2e8 upstream.
-
-If the number of ports present on the SoC/board is not the maximum
-and that the platform data is not filled with all data, there is
-an easy way to mess the PIO setup for this interface.
-This quick fix addresses mis-configuration in USB host platform data
-that is common in at91 boards since commit 0ee6d1e (USB: ohci-at91:
-change maximum number of ports) that did not modified the associatd
-board files.
-
-Reported-by: Klaus Falkner <klaus.falkner@solectrix.de>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Cc: Stable <stable@vger.kernel.org> [3.4+]
-Acked-by: Alan Stern <stern@rowland.harvard.edu>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/usb/host/ohci-at91.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/drivers/usb/host/ohci-at91.c
-+++ b/drivers/usb/host/ohci-at91.c
-@@ -647,6 +647,16 @@ static int __devexit ohci_hcd_at91_drv_r
-
- if (pdata) {
- at91_for_each_port(i) {
-+ /*
-+ * do not configure PIO if not in relation with
-+ * real USB port on board
-+ */
-+ if (i >= pdata->ports) {
-+ pdata->vbus_pin[i] = -EINVAL;
-+ pdata->overcurrent_pin[i] = -EINVAL;
-+ break;
-+ }
-+
- if (!gpio_is_valid(pdata->vbus_pin[i]))
- continue;
- ohci_at91_usb_set_power(pdata, i, 0);
+++ /dev/null
-From 620f6b0ce1071fd027a1882a21e41143d8bb5d95 Mon Sep 17 00:00:00 2001
-From: Alexandre Pereira da Silva <aletes.xgr@gmail.com>
-Date: Tue, 26 Jun 2012 11:27:12 -0300
-Subject: usb: gadget: at91_udc: Propagate devicetree to gadget drivers
-
-commit 65c84ea18b1b4b8c03fb67c3bea023ed1446bd2e upstream.
-
-Fill dev.of_node of gadget drivers, so they can use devicetree
-
-Signed-off-by: Alexandre Pereira da Silva <aletes.xgr@gmail.com>
-Signed-off-by: Felipe Balbi <balbi@ti.com>
----
- drivers/usb/gadget/at91_udc.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
-index ffb46bc..ddeaadb 100644
---- a/drivers/usb/gadget/at91_udc.c
-+++ b/drivers/usb/gadget/at91_udc.c
-@@ -1650,6 +1650,7 @@ static int at91_start(struct usb_gadget_driver *driver,
-
- udc->driver = driver;
- udc->gadget.dev.driver = &driver->driver;
-+ udc->gadget.dev.of_node = udc->pdev->dev.of_node;
- dev_set_drvdata(&udc->gadget.dev, &driver->driver);
- udc->enabled = 1;
- udc->selfpowered = 1;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 5f66b12556f296e2aa31268877ad5c2961a073f4 Mon Sep 17 00:00:00 2001
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Date: Fri, 27 Apr 2012 11:24:39 -0700
-Subject: USB: ohci-at91.c: remove err() usage
-
-commit 2418d5f979fa424c401654f0f1e1d6abffecc379 upstream.
-
-err() was a very old USB-specific macro that I thought had
-gone away. This patch removes it from being used in the
-driver and uses dev_err() instead.
-
-CC: Alan Stern <stern@rowland.harvard.edu>
-CC: Grant Likely <grant.likely@secretlab.ca>
-CC: Rob Herring <rob.herring@calxeda.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/usb/host/ohci-at91.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
-index 5dfea46..aaa8d2b 100644
---- a/drivers/usb/host/ohci-at91.c
-+++ b/drivers/usb/host/ohci-at91.c
-@@ -243,7 +243,8 @@ ohci_at91_start (struct usb_hcd *hcd)
- int ret;
-
- if ((ret = ohci_run(ohci)) < 0) {
-- err("can't start %s", hcd->self.bus_name);
-+ dev_err(hcd->self.controller, "can't start %s\n",
-+ hcd->self.bus_name);
- ohci_stop(hcd);
- return ret;
- }
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 736d87b6261c8fee4399f3d2605609fd97b43f5e Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Fri, 21 Sep 2012 15:49:29 +0200
-Subject: MTD: atmel_nand: revet the oob_required parameter in
- ecc.read/write_page
-
-Only for v3.4 compatibility. Do not propagate upstream
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/mtd/nand/atmel_nand.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
-index c512bba..b5e5a76 100644
---- a/drivers/mtd/nand/atmel_nand.c
-+++ b/drivers/mtd/nand/atmel_nand.c
-@@ -759,7 +759,7 @@ normal_check:
- }
-
- static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
-- struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
-+ struct nand_chip *chip, uint8_t *buf, int page)
- {
- struct atmel_nand_host *host = chip->priv;
- int eccsize = chip->ecc.size;
-@@ -797,7 +797,7 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
- }
-
- static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
-- struct nand_chip *chip, const uint8_t *buf, int oob_required)
-+ struct nand_chip *chip, const uint8_t *buf)
- {
- struct atmel_nand_host *host = chip->priv;
- uint32_t *eccpos = chip->ecc.layout->eccpos;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b0b4d9808e0c71070375befa5b06707eb91c3a2a Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 19 Jun 2012 13:14:10 +0200
-Subject: USB: Kconfig: add Atmel usba driver entry
-
-Allow the USBA entry to be selected for every AT91 SoC.
-Will allow to select driver for newer SoCs.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/usb/gadget/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
-index 2633f75..10fea8b 100644
---- a/drivers/usb/gadget/Kconfig
-+++ b/drivers/usb/gadget/Kconfig
-@@ -150,7 +150,7 @@ config USB_AT91
- config USB_ATMEL_USBA
- tristate "Atmel USBA"
- select USB_GADGET_DUALSPEED
-- depends on AVR32 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
-+ depends on AVR32 || ARCH_AT91
- help
- USBA is the integrated high-speed USB Device controller on
- the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 76cbb89fa9ac0f8a422bdd44f6deb0dd3566c960 Mon Sep 17 00:00:00 2001
-From: Stephen Warren <swarren@wwwdotorg.org>
-Date: Fri, 23 Mar 2012 10:29:46 -0600
-Subject: pinctrl: core device tree mapping table parsing support
-
-commit 57291ce295c0aca738dd284c4a9c591c09ebee71 upstream.
-
-During pinctrl_get(), if the client device has a device tree node, look
-for the common pinctrl properties there. If found, parse the referenced
-device tree nodes, with the help of the pinctrl drivers, and generate
-mapping table entries from them.
-
-During pinctrl_put(), free any results of device tree parsing.
-
-Acked-by: Dong Aisheng <dong.aisheng@linaro.org>
-Signed-off-by: Stephen Warren <swarren@wwwdotorg.org>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- drivers/pinctrl/Makefile | 1 +
- drivers/pinctrl/core.c | 72 +++++++++---
- drivers/pinctrl/core.h | 11 +-
- drivers/pinctrl/devicetree.c | 249 ++++++++++++++++++++++++++++++++++++++++
- drivers/pinctrl/devicetree.h | 35 ++++++
- include/linux/pinctrl/pinctrl.h | 7 ++
- 6 files changed, 357 insertions(+), 18 deletions(-)
- create mode 100644 drivers/pinctrl/devicetree.c
- create mode 100644 drivers/pinctrl/devicetree.h
-
-diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
-index 6d4150b..049c9fb 100644
---- a/drivers/pinctrl/Makefile
-+++ b/drivers/pinctrl/Makefile
-@@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG
- obj-$(CONFIG_PINCTRL) += core.o
- obj-$(CONFIG_PINMUX) += pinmux.o
- obj-$(CONFIG_PINCONF) += pinconf.o
-+obj-$(CONFIG_OF) += devicetree.o
- obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
- obj-$(CONFIG_PINCTRL_PXA3xx) += pinctrl-pxa3xx.o
- obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o
-diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
-index df6296c..832f71d 100644
---- a/drivers/pinctrl/core.c
-+++ b/drivers/pinctrl/core.c
-@@ -26,6 +26,7 @@
- #include <linux/pinctrl/pinctrl.h>
- #include <linux/pinctrl/machine.h>
- #include "core.h"
-+#include "devicetree.h"
- #include "pinmux.h"
- #include "pinconf.h"
-
-@@ -45,7 +46,7 @@ struct pinctrl_maps {
- DEFINE_MUTEX(pinctrl_mutex);
-
- /* Global list of pin control devices (struct pinctrl_dev) */
--static LIST_HEAD(pinctrldev_list);
-+LIST_HEAD(pinctrldev_list);
-
- /* List of pin controller handles (struct pinctrl) */
- static LIST_HEAD(pinctrl_list);
-@@ -579,6 +580,13 @@ static struct pinctrl *create_pinctrl(struct device *dev)
- }
- p->dev = dev;
- INIT_LIST_HEAD(&p->states);
-+ INIT_LIST_HEAD(&p->dt_maps);
-+
-+ ret = pinctrl_dt_to_map(p);
-+ if (ret < 0) {
-+ kfree(p);
-+ return ERR_PTR(ret);
-+ }
-
- devname = dev_name(dev);
-
-@@ -662,6 +670,8 @@ static void pinctrl_put_locked(struct pinctrl *p, bool inlist)
- kfree(state);
- }
-
-+ pinctrl_dt_free_maps(p);
-+
- if (inlist)
- list_del(&p->node);
- kfree(p);
-@@ -787,15 +797,8 @@ int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
- }
- EXPORT_SYMBOL_GPL(pinctrl_select_state);
-
--/**
-- * pinctrl_register_mappings() - register a set of pin controller mappings
-- * @maps: the pincontrol mappings table to register. This should probably be
-- * marked with __initdata so it can be discarded after boot. This
-- * function will perform a shallow copy for the mapping entries.
-- * @num_maps: the number of maps in the mapping table
-- */
--int pinctrl_register_mappings(struct pinctrl_map const *maps,
-- unsigned num_maps)
-+int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
-+ bool dup, bool locked)
- {
- int i, ret;
- struct pinctrl_maps *maps_node;
-@@ -851,20 +854,52 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps,
- }
-
- maps_node->num_maps = num_maps;
-- maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps, GFP_KERNEL);
-- if (!maps_node->maps) {
-- pr_err("failed to duplicate mapping table\n");
-- kfree(maps_node);
-- return -ENOMEM;
-+ if (dup) {
-+ maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps,
-+ GFP_KERNEL);
-+ if (!maps_node->maps) {
-+ pr_err("failed to duplicate mapping table\n");
-+ kfree(maps_node);
-+ return -ENOMEM;
-+ }
-+ } else {
-+ maps_node->maps = maps;
- }
-
-- mutex_lock(&pinctrl_mutex);
-+ if (!locked)
-+ mutex_lock(&pinctrl_mutex);
- list_add_tail(&maps_node->node, &pinctrl_maps);
-- mutex_unlock(&pinctrl_mutex);
-+ if (!locked)
-+ mutex_unlock(&pinctrl_mutex);
-
- return 0;
- }
-
-+/**
-+ * pinctrl_register_mappings() - register a set of pin controller mappings
-+ * @maps: the pincontrol mappings table to register. This should probably be
-+ * marked with __initdata so it can be discarded after boot. This
-+ * function will perform a shallow copy for the mapping entries.
-+ * @num_maps: the number of maps in the mapping table
-+ */
-+int pinctrl_register_mappings(struct pinctrl_map const *maps,
-+ unsigned num_maps)
-+{
-+ return pinctrl_register_map(maps, num_maps, true, false);
-+}
-+
-+void pinctrl_unregister_map(struct pinctrl_map const *map)
-+{
-+ struct pinctrl_maps *maps_node;
-+
-+ list_for_each_entry(maps_node, &pinctrl_maps, node) {
-+ if (maps_node->maps == map) {
-+ list_del(&maps_node->node);
-+ return;
-+ }
-+ }
-+}
-+
- #ifdef CONFIG_DEBUG_FS
-
- static int pinctrl_pins_show(struct seq_file *s, void *what)
-@@ -1231,6 +1266,9 @@ static int pinctrl_check_ops(struct pinctrl_dev *pctldev)
- !ops->get_group_pins)
- return -EINVAL;
-
-+ if (ops->dt_node_to_map && !ops->dt_free_map)
-+ return -EINVAL;
-+
- return 0;
- }
-
-diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
-index 17ecf65..98ae808 100644
---- a/drivers/pinctrl/core.h
-+++ b/drivers/pinctrl/core.h
-@@ -52,12 +52,15 @@ struct pinctrl_dev {
- * @dev: the device using this pin control handle
- * @states: a list of states for this device
- * @state: the current state
-+ * @dt_maps: the mapping table chunks dynamically parsed from device tree for
-+ * this device, if any
- */
- struct pinctrl {
- struct list_head node;
- struct device *dev;
- struct list_head states;
- struct pinctrl_state *state;
-+ struct list_head dt_maps;
- };
-
- /**
-@@ -100,7 +103,8 @@ struct pinctrl_setting_configs {
- * struct pinctrl_setting - an individual mux or config setting
- * @node: list node for struct pinctrl_settings's @settings field
- * @type: the type of setting
-- * @pctldev: pin control device handling to be programmed
-+ * @pctldev: pin control device handling to be programmed. Not used for
-+ * PIN_MAP_TYPE_DUMMY_STATE.
- * @data: Data specific to the setting type
- */
- struct pinctrl_setting {
-@@ -153,4 +157,9 @@ static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev,
- return radix_tree_lookup(&pctldev->pin_desc_tree, pin);
- }
-
-+int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
-+ bool dup, bool locked);
-+void pinctrl_unregister_map(struct pinctrl_map const *map);
-+
- extern struct mutex pinctrl_mutex;
-+extern struct list_head pinctrldev_list;
-diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
-new file mode 100644
-index 0000000..5ef2feb
---- /dev/null
-+++ b/drivers/pinctrl/devicetree.c
-@@ -0,0 +1,249 @@
-+/*
-+ * Device tree integration for the pin control subsystem
-+ *
-+ * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#include <linux/device.h>
-+#include <linux/of.h>
-+#include <linux/pinctrl/pinctrl.h>
-+#include <linux/slab.h>
-+
-+#include "core.h"
-+#include "devicetree.h"
-+
-+/**
-+ * struct pinctrl_dt_map - mapping table chunk parsed from device tree
-+ * @node: list node for struct pinctrl's @dt_maps field
-+ * @pctldev: the pin controller that allocated this struct, and will free it
-+ * @maps: the mapping table entries
-+ */
-+struct pinctrl_dt_map {
-+ struct list_head node;
-+ struct pinctrl_dev *pctldev;
-+ struct pinctrl_map *map;
-+ unsigned num_maps;
-+};
-+
-+static void dt_free_map(struct pinctrl_dev *pctldev,
-+ struct pinctrl_map *map, unsigned num_maps)
-+{
-+ if (pctldev) {
-+ struct pinctrl_ops *ops = pctldev->desc->pctlops;
-+ ops->dt_free_map(pctldev, map, num_maps);
-+ } else {
-+ /* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
-+ kfree(map);
-+ }
-+}
-+
-+void pinctrl_dt_free_maps(struct pinctrl *p)
-+{
-+ struct pinctrl_dt_map *dt_map, *n1;
-+
-+ list_for_each_entry_safe(dt_map, n1, &p->dt_maps, node) {
-+ pinctrl_unregister_map(dt_map->map);
-+ list_del(&dt_map->node);
-+ dt_free_map(dt_map->pctldev, dt_map->map,
-+ dt_map->num_maps);
-+ kfree(dt_map);
-+ }
-+
-+ of_node_put(p->dev->of_node);
-+}
-+
-+static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,
-+ struct pinctrl_dev *pctldev,
-+ struct pinctrl_map *map, unsigned num_maps)
-+{
-+ int i;
-+ struct pinctrl_dt_map *dt_map;
-+
-+ /* Initialize common mapping table entry fields */
-+ for (i = 0; i < num_maps; i++) {
-+ map[i].dev_name = dev_name(p->dev);
-+ map[i].name = statename;
-+ if (pctldev)
-+ map[i].ctrl_dev_name = dev_name(pctldev->dev);
-+ }
-+
-+ /* Remember the converted mapping table entries */
-+ dt_map = kzalloc(sizeof(*dt_map), GFP_KERNEL);
-+ if (!dt_map) {
-+ dev_err(p->dev, "failed to alloc struct pinctrl_dt_map\n");
-+ dt_free_map(pctldev, map, num_maps);
-+ return -ENOMEM;
-+ }
-+
-+ dt_map->pctldev = pctldev;
-+ dt_map->map = map;
-+ dt_map->num_maps = num_maps;
-+ list_add_tail(&dt_map->node, &p->dt_maps);
-+
-+ return pinctrl_register_map(map, num_maps, false, true);
-+}
-+
-+static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
-+{
-+ struct pinctrl_dev *pctldev;
-+
-+ list_for_each_entry(pctldev, &pinctrldev_list, node)
-+ if (pctldev->dev->of_node == np)
-+ return pctldev;
-+
-+ return NULL;
-+}
-+
-+static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
-+ struct device_node *np_config)
-+{
-+ struct device_node *np_pctldev;
-+ struct pinctrl_dev *pctldev;
-+ struct pinctrl_ops *ops;
-+ int ret;
-+ struct pinctrl_map *map;
-+ unsigned num_maps;
-+
-+ /* Find the pin controller containing np_config */
-+ np_pctldev = of_node_get(np_config);
-+ for (;;) {
-+ np_pctldev = of_get_next_parent(np_pctldev);
-+ if (!np_pctldev || of_node_is_root(np_pctldev)) {
-+ dev_err(p->dev, "could not find pctldev for node %s\n",
-+ np_config->full_name);
-+ of_node_put(np_pctldev);
-+ /* FIXME: This should trigger deferrered probe */
-+ return -ENODEV;
-+ }
-+ pctldev = find_pinctrl_by_of_node(np_pctldev);
-+ if (pctldev)
-+ break;
-+ }
-+ of_node_put(np_pctldev);
-+
-+ /*
-+ * Call pinctrl driver to parse device tree node, and
-+ * generate mapping table entries
-+ */
-+ ops = pctldev->desc->pctlops;
-+ if (!ops->dt_node_to_map) {
-+ dev_err(p->dev, "pctldev %s doesn't support DT\n",
-+ dev_name(pctldev->dev));
-+ return -ENODEV;
-+ }
-+ ret = ops->dt_node_to_map(pctldev, np_config, &map, &num_maps);
-+ if (ret < 0)
-+ return ret;
-+
-+ /* Stash the mapping table chunk away for later use */
-+ return dt_remember_or_free_map(p, statename, pctldev, map, num_maps);
-+}
-+
-+static int dt_remember_dummy_state(struct pinctrl *p, const char *statename)
-+{
-+ struct pinctrl_map *map;
-+
-+ map = kzalloc(sizeof(*map), GFP_KERNEL);
-+ if (!map) {
-+ dev_err(p->dev, "failed to alloc struct pinctrl_map\n");
-+ return -ENOMEM;
-+ }
-+
-+ /* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
-+ map->type = PIN_MAP_TYPE_DUMMY_STATE;
-+
-+ return dt_remember_or_free_map(p, statename, NULL, map, 1);
-+}
-+
-+int pinctrl_dt_to_map(struct pinctrl *p)
-+{
-+ struct device_node *np = p->dev->of_node;
-+ int state, ret;
-+ char *propname;
-+ struct property *prop;
-+ const char *statename;
-+ const __be32 *list;
-+ int size, config;
-+ phandle phandle;
-+ struct device_node *np_config;
-+
-+ /* CONFIG_OF enabled, p->dev not instantiated from DT */
-+ if (!np) {
-+ dev_dbg(p->dev, "no of_node; not parsing pinctrl DT\n");
-+ return 0;
-+ }
-+
-+ /* We may store pointers to property names within the node */
-+ of_node_get(np);
-+
-+ /* For each defined state ID */
-+ for (state = 0; ; state++) {
-+ /* Retrieve the pinctrl-* property */
-+ propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state);
-+ prop = of_find_property(np, propname, &size);
-+ kfree(propname);
-+ if (!prop)
-+ break;
-+ list = prop->value;
-+ size /= sizeof(*list);
-+
-+ /* Determine whether pinctrl-names property names the state */
-+ ret = of_property_read_string_index(np, "pinctrl-names",
-+ state, &statename);
-+ /*
-+ * If not, statename is just the integer state ID. But rather
-+ * than dynamically allocate it and have to free it later,
-+ * just point part way into the property name for the string.
-+ */
-+ if (ret < 0) {
-+ /* strlen("pinctrl-") == 8 */
-+ statename = prop->name + 8;
-+ }
-+
-+ /* For every referenced pin configuration node in it */
-+ for (config = 0; config < size; config++) {
-+ phandle = be32_to_cpup(list++);
-+
-+ /* Look up the pin configuration node */
-+ np_config = of_find_node_by_phandle(phandle);
-+ if (!np_config) {
-+ dev_err(p->dev,
-+ "prop %s index %i invalid phandle\n",
-+ prop->name, config);
-+ ret = -EINVAL;
-+ goto err;
-+ }
-+
-+ /* Parse the node */
-+ ret = dt_to_map_one_config(p, statename, np_config);
-+ of_node_put(np_config);
-+ if (ret < 0)
-+ goto err;
-+ }
-+
-+ /* No entries in DT? Generate a dummy state table entry */
-+ if (!size) {
-+ ret = dt_remember_dummy_state(p, statename);
-+ if (ret < 0)
-+ goto err;
-+ }
-+ }
-+
-+ return 0;
-+
-+err:
-+ pinctrl_dt_free_maps(p);
-+ return ret;
-+}
-diff --git a/drivers/pinctrl/devicetree.h b/drivers/pinctrl/devicetree.h
-new file mode 100644
-index 0000000..760bc49
---- /dev/null
-+++ b/drivers/pinctrl/devicetree.h
-@@ -0,0 +1,35 @@
-+/*
-+ * Internal interface to pinctrl device tree integration
-+ *
-+ * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#ifdef CONFIG_OF
-+
-+void pinctrl_dt_free_maps(struct pinctrl *p);
-+int pinctrl_dt_to_map(struct pinctrl *p);
-+
-+#else
-+
-+static inline int pinctrl_dt_to_map(struct pinctrl *p)
-+{
-+ return 0;
-+}
-+
-+static inline void pinctrl_dt_free_maps(struct pinctrl *p)
-+{
-+}
-+
-+#endif
-diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
-index 4e9f078..aa92cde 100644
---- a/include/linux/pinctrl/pinctrl.h
-+++ b/include/linux/pinctrl/pinctrl.h
-@@ -21,9 +21,11 @@
-
- struct device;
- struct pinctrl_dev;
-+struct pinctrl_map;
- struct pinmux_ops;
- struct pinconf_ops;
- struct gpio_chip;
-+struct device_node;
-
- /**
- * struct pinctrl_pin_desc - boards/machines provide information on their
-@@ -83,6 +85,11 @@ struct pinctrl_ops {
- unsigned *num_pins);
- void (*pin_dbg_show) (struct pinctrl_dev *pctldev, struct seq_file *s,
- unsigned offset);
-+ int (*dt_node_to_map) (struct pinctrl_dev *pctldev,
-+ struct device_node *np_config,
-+ struct pinctrl_map **map, unsigned *num_maps);
-+ void (*dt_free_map) (struct pinctrl_dev *pctldev,
-+ struct pinctrl_map *map, unsigned num_maps);
- };
-
- /**
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e159086ce1559954a5f30e4b42feab3934459208 Mon Sep 17 00:00:00 2001
-From: Stephen Warren <swarren@nvidia.com>
-Date: Tue, 3 Apr 2012 21:53:56 -0600
-Subject: pinctrl: fix build when CONFIG_OF && !CONFIG_PINCTRL
-
-commit eafeb7a44aa8f79c992b9d557ede740c739f4b25 upstream.
-
-pinctrl/devicetree.c won't compile when !CONFIG_PINCTRL, since the
-pinctrl headers don't declare some types when !PINCTRL. Make sure
-pinctrl/Makefile only attempts to compile devicetree.c when OF &&
-PINCTRL.
-
-Acked-by: Dong Aisheng <dong.aisheng@linaro.org>
-Signed-off-by: Stephen Warren <swarren@nvidia.com>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- drivers/pinctrl/Makefile | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
-index 049c9fb..8e3c95a 100644
---- a/drivers/pinctrl/Makefile
-+++ b/drivers/pinctrl/Makefile
-@@ -5,7 +5,9 @@ ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG
- obj-$(CONFIG_PINCTRL) += core.o
- obj-$(CONFIG_PINMUX) += pinmux.o
- obj-$(CONFIG_PINCONF) += pinconf.o
--obj-$(CONFIG_OF) += devicetree.o
-+ifeq ($(CONFIG_OF),y)
-+obj-$(CONFIG_PINCTRL) += devicetree.o
-+endif
- obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
- obj-$(CONFIG_PINCTRL_PXA3xx) += pinctrl-pxa3xx.o
- obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 1a5a72c0a928388e178aca6290fd866b67b045d8 Mon Sep 17 00:00:00 2001
-From: Linus Walleij <linus.walleij@linaro.org>
-Date: Tue, 24 Apr 2012 15:20:02 +0200
-Subject: pinctrl: fix dangling comment
-
-commit dd5127010afa560b1cfde7e2cffeadabdd20885d upstream.
-
-This comment was referring to an older PINMUX define, it should
-be PINCTRL now.
-
-Reported-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Dong Aisheng <dong.aisheng@linaro.org>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- include/linux/pinctrl/machine.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h
-index e4d1de7..9c4a198 100644
---- a/include/linux/pinctrl/machine.h
-+++ b/include/linux/pinctrl/machine.h
-@@ -163,5 +163,5 @@ static inline int pinctrl_register_mappings(struct pinctrl_map const *map,
- return 0;
- }
-
--#endif /* !CONFIG_PINMUX */
-+#endif /* !CONFIG_PINCTRL */
- #endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 6697baae87bbd04741c77c498d560a16edceb42a Mon Sep 17 00:00:00 2001
-From: Stephen Warren <swarren@nvidia.com>
-Date: Mon, 16 Apr 2012 10:51:00 -0600
-Subject: pinctrl: implement devm_pinctrl_get()/put()
-
-commit 6d4ca1fb467932773da7b808c52f3d7ef4461ba0 upstream.
-
-These functions allow the driver core to automatically clean up any
-allocations made by drivers, thus leading to simplified drivers.
-
-Signed-off-by: Stephen Warren <swarren@nvidia.com>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- Documentation/driver-model/devres.txt | 4 +++
- Documentation/pinctrl.txt | 48 ++++++++++++++++++------------
- drivers/pinctrl/core.c | 56 +++++++++++++++++++++++++++++++++++
- include/linux/pinctrl/consumer.h | 44 +++++++++++++++++++++++++++
- 4 files changed, 133 insertions(+), 19 deletions(-)
-
-diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
-index 2a596a4..ef4fa7b 100644
---- a/Documentation/driver-model/devres.txt
-+++ b/Documentation/driver-model/devres.txt
-@@ -276,3 +276,7 @@ REGULATOR
- devm_regulator_get()
- devm_regulator_put()
- devm_regulator_bulk_get()
-+
-+PINCTRL
-+ devm_pinctrl_get()
-+ devm_pinctrl_put()
-diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
-index d97bccf..fa829f1 100644
---- a/Documentation/pinctrl.txt
-+++ b/Documentation/pinctrl.txt
-@@ -952,13 +952,13 @@ case), we define a mapping like this:
- The result of grabbing this mapping from the device with something like
- this (see next paragraph):
-
-- p = pinctrl_get(dev);
-+ p = devm_pinctrl_get(dev);
- s = pinctrl_lookup_state(p, "8bit");
- ret = pinctrl_select_state(p, s);
-
- or more simply:
-
-- p = pinctrl_get_select(dev, "8bit");
-+ p = devm_pinctrl_get_select(dev, "8bit");
-
- Will be that you activate all the three bottom records in the mapping at
- once. Since they share the same name, pin controller device, function and
-@@ -992,7 +992,7 @@ foo_probe()
- /* Allocate a state holder named "foo" etc */
- struct foo_state *foo = ...;
-
-- foo->p = pinctrl_get(&device);
-+ foo->p = devm_pinctrl_get(&device);
- if (IS_ERR(foo->p)) {
- /* FIXME: clean up "foo" here */
- return PTR_ERR(foo->p);
-@@ -1000,24 +1000,17 @@ foo_probe()
-
- foo->s = pinctrl_lookup_state(foo->p, PINCTRL_STATE_DEFAULT);
- if (IS_ERR(foo->s)) {
-- pinctrl_put(foo->p);
- /* FIXME: clean up "foo" here */
- return PTR_ERR(s);
- }
-
- ret = pinctrl_select_state(foo->s);
- if (ret < 0) {
-- pinctrl_put(foo->p);
- /* FIXME: clean up "foo" here */
- return ret;
- }
- }
-
--foo_remove()
--{
-- pinctrl_put(state->p);
--}
--
- This get/lookup/select/put sequence can just as well be handled by bus drivers
- if you don't want each and every driver to handle it and you know the
- arrangement on your bus.
-@@ -1029,6 +1022,11 @@ The semantics of the pinctrl APIs are:
- kernel memory to hold the pinmux state. All mapping table parsing or similar
- slow operations take place within this API.
-
-+- devm_pinctrl_get() is a variant of pinctrl_get() that causes pinctrl_put()
-+ to be called automatically on the retrieved pointer when the associated
-+ device is removed. It is recommended to use this function over plain
-+ pinctrl_get().
-+
- - pinctrl_lookup_state() is called in process context to obtain a handle to a
- specific state for a the client device. This operation may be slow too.
-
-@@ -1041,14 +1039,25 @@ The semantics of the pinctrl APIs are:
-
- - pinctrl_put() frees all information associated with a pinctrl handle.
-
-+- devm_pinctrl_put() is a variant of pinctrl_put() that may be used to
-+ explicitly destroy a pinctrl object returned by devm_pinctrl_get().
-+ However, use of this function will be rare, due to the automatic cleanup
-+ that will occur even without calling it.
-+
-+ pinctrl_get() must be paired with a plain pinctrl_put().
-+ pinctrl_get() may not be paired with devm_pinctrl_put().
-+ devm_pinctrl_get() can optionally be paired with devm_pinctrl_put().
-+ devm_pinctrl_get() may not be paired with plain pinctrl_put().
-+
- Usually the pin control core handled the get/put pair and call out to the
- device drivers bookkeeping operations, like checking available functions and
- the associated pins, whereas the enable/disable pass on to the pin controller
- driver which takes care of activating and/or deactivating the mux setting by
- quickly poking some registers.
-
--The pins are allocated for your device when you issue the pinctrl_get() call,
--after this you should be able to see this in the debugfs listing of all pins.
-+The pins are allocated for your device when you issue the devm_pinctrl_get()
-+call, after this you should be able to see this in the debugfs listing of all
-+pins.
-
-
- System pin control hogging
-@@ -1094,13 +1103,13 @@ it, disables and releases it, and muxes it in on the pins defined by group B:
-
- #include <linux/pinctrl/consumer.h>
-
--foo_switch()
--{
-- struct pinctrl *p;
-- struct pinctrl_state *s1, *s2;
-+struct pinctrl *p;
-+struct pinctrl_state *s1, *s2;
-
-+foo_probe()
-+{
- /* Setup */
-- p = pinctrl_get(&device);
-+ p = devm_pinctrl_get(&device);
- if (IS_ERR(p))
- ...
-
-@@ -1111,7 +1120,10 @@ foo_switch()
- s2 = pinctrl_lookup_state(foo->p, "pos-B");
- if (IS_ERR(s2))
- ...
-+}
-
-+foo_switch()
-+{
- /* Enable on position A */
- ret = pinctrl_select_state(s1);
- if (ret < 0)
-@@ -1125,8 +1137,6 @@ foo_switch()
- ...
-
- ...
--
-- pinctrl_put(p);
- }
-
- The above has to be done from process context.
-diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
-index 832f71d..f4544f4 100644
---- a/drivers/pinctrl/core.c
-+++ b/drivers/pinctrl/core.c
-@@ -23,6 +23,7 @@
- #include <linux/sysfs.h>
- #include <linux/debugfs.h>
- #include <linux/seq_file.h>
-+#include <linux/pinctrl/consumer.h>
- #include <linux/pinctrl/pinctrl.h>
- #include <linux/pinctrl/machine.h>
- #include "core.h"
-@@ -797,6 +798,61 @@ int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
- }
- EXPORT_SYMBOL_GPL(pinctrl_select_state);
-
-+static void devm_pinctrl_release(struct device *dev, void *res)
-+{
-+ pinctrl_put(*(struct pinctrl **)res);
-+}
-+
-+/**
-+ * struct devm_pinctrl_get() - Resource managed pinctrl_get()
-+ * @dev: the device to obtain the handle for
-+ *
-+ * If there is a need to explicitly destroy the returned struct pinctrl,
-+ * devm_pinctrl_put() should be used, rather than plain pinctrl_put().
-+ */
-+struct pinctrl *devm_pinctrl_get(struct device *dev)
-+{
-+ struct pinctrl **ptr, *p;
-+
-+ ptr = devres_alloc(devm_pinctrl_release, sizeof(*ptr), GFP_KERNEL);
-+ if (!ptr)
-+ return ERR_PTR(-ENOMEM);
-+
-+ p = pinctrl_get(dev);
-+ if (!IS_ERR(p)) {
-+ *ptr = p;
-+ devres_add(dev, ptr);
-+ } else {
-+ devres_free(ptr);
-+ }
-+
-+ return p;
-+}
-+EXPORT_SYMBOL_GPL(devm_pinctrl_get);
-+
-+static int devm_pinctrl_match(struct device *dev, void *res, void *data)
-+{
-+ struct pinctrl **p = res;
-+
-+ return *p == data;
-+}
-+
-+/**
-+ * devm_pinctrl_put() - Resource managed pinctrl_put()
-+ * @p: the pinctrl handle to release
-+ *
-+ * Deallocate a struct pinctrl obtained via devm_pinctrl_get(). Normally
-+ * this function will not need to be called and the resource management
-+ * code will ensure that the resource is freed.
-+ */
-+void devm_pinctrl_put(struct pinctrl *p)
-+{
-+ WARN_ON(devres_destroy(p->dev, devm_pinctrl_release,
-+ devm_pinctrl_match, p));
-+ pinctrl_put(p);
-+}
-+EXPORT_SYMBOL_GPL(devm_pinctrl_put);
-+
- int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
- bool dup, bool locked)
- {
-diff --git a/include/linux/pinctrl/consumer.h b/include/linux/pinctrl/consumer.h
-index 191e726..6dd96fb 100644
---- a/include/linux/pinctrl/consumer.h
-+++ b/include/linux/pinctrl/consumer.h
-@@ -36,6 +36,9 @@ extern struct pinctrl_state * __must_check pinctrl_lookup_state(
- const char *name);
- extern int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *s);
-
-+extern struct pinctrl * __must_check devm_pinctrl_get(struct device *dev);
-+extern void devm_pinctrl_put(struct pinctrl *p);
-+
- #else /* !CONFIG_PINCTRL */
-
- static inline int pinctrl_request_gpio(unsigned gpio)
-@@ -79,6 +82,15 @@ static inline int pinctrl_select_state(struct pinctrl *p,
- return 0;
- }
-
-+static inline struct pinctrl * __must_check devm_pinctrl_get(struct device *dev)
-+{
-+ return NULL;
-+}
-+
-+static inline void devm_pinctrl_put(struct pinctrl *p)
-+{
-+}
-+
- #endif /* CONFIG_PINCTRL */
-
- static inline struct pinctrl * __must_check pinctrl_get_select(
-@@ -113,6 +125,38 @@ static inline struct pinctrl * __must_check pinctrl_get_select_default(
- return pinctrl_get_select(dev, PINCTRL_STATE_DEFAULT);
- }
-
-+static inline struct pinctrl * __must_check devm_pinctrl_get_select(
-+ struct device *dev, const char *name)
-+{
-+ struct pinctrl *p;
-+ struct pinctrl_state *s;
-+ int ret;
-+
-+ p = devm_pinctrl_get(dev);
-+ if (IS_ERR(p))
-+ return p;
-+
-+ s = pinctrl_lookup_state(p, name);
-+ if (IS_ERR(s)) {
-+ devm_pinctrl_put(p);
-+ return ERR_PTR(PTR_ERR(s));
-+ }
-+
-+ ret = pinctrl_select_state(p, s);
-+ if (ret < 0) {
-+ devm_pinctrl_put(p);
-+ return ERR_PTR(ret);
-+ }
-+
-+ return p;
-+}
-+
-+static inline struct pinctrl * __must_check devm_pinctrl_get_select_default(
-+ struct device *dev)
-+{
-+ return devm_pinctrl_get_select(dev, PINCTRL_STATE_DEFAULT);
-+}
-+
- #ifdef CONFIG_PINCONF
-
- extern int pin_config_get(const char *dev_name, const char *name,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 1329721ec7c0898aea3607ac6c02fb8d68b42fea Mon Sep 17 00:00:00 2001
-From: Dong Aisheng <dong.aisheng@linaro.org>
-Date: Thu, 26 Apr 2012 16:15:50 +0800
-Subject: pinctrl: add pinctrl_provide_dummies interface for platforms to use
-
-commit 5b3aa5f7c6287b1a0698950a91e94546888e553b upstream.
-
-Add a interface pinctrl_provide_dummies for platform to indicate
-whether it needs use pinctrl dummy state.
-
-ChangeLog v3->v4:
-* remove dummy gpio support in pinctrl subsystem.
- Let gpio driver decide whether it wants to use pinctrl gpio mux
- function.
-ChangeLog v2->v3:
-* Also changed the missed pinctrl gpio APIs in v1.
-ChangeLog v1->v2:
-* Based on sascha's suggestion, drop using kconfig since it will hide
- pinctrl errors on all other boards.
- See: https://lkml.org/lkml/2012/4/18/282
- It seemed both Linus and Stephen agreed with this way, so i'm ok
- with it too.
-* Add dummy gpio support.
- pinctrl gpio in the same situation as state.
-* Patch name changed.
- Original is pinctrl: handle dummy state in core.
-* Split removing old dt dummy interface into a separate patch
-
-Cc: Linus Walleij <linus.walleij@linaro.org>
-Cc: Sascha Hauer <s.hauer@pengutronix.de>
-Acked-by: Stephen Warren <swarren@wwwdotorg.org>
-Signed-off-by: Dong Aisheng <dong.aisheng@linaro.org>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- drivers/pinctrl/core.c | 29 +++++++++++++++++++++++++++--
- include/linux/pinctrl/machine.h | 5 ++++-
- 2 files changed, 31 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
-index f4544f4..2b6363c5 100644
---- a/drivers/pinctrl/core.c
-+++ b/drivers/pinctrl/core.c
-@@ -43,6 +43,8 @@ struct pinctrl_maps {
- unsigned num_maps;
- };
-
-+static bool pinctrl_dummy_state;
-+
- /* Mutex taken by all entry points */
- DEFINE_MUTEX(pinctrl_mutex);
-
-@@ -61,6 +63,19 @@ static LIST_HEAD(pinctrl_maps);
- _i_ < _maps_node_->num_maps; \
- i++, _map_ = &_maps_node_->maps[_i_])
-
-+/**
-+ * pinctrl_provide_dummies() - indicate if pinctrl provides dummy state support
-+ *
-+ * Usually this function is called by platforms without pinctrl driver support
-+ * but run with some shared drivers using pinctrl APIs.
-+ * After calling this function, the pinctrl core will return successfully
-+ * with creating a dummy state for the driver to keep going smoothly.
-+ */
-+void pinctrl_provide_dummies(void)
-+{
-+ pinctrl_dummy_state = true;
-+}
-+
- const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev)
- {
- /* We're not allowed to register devices without name */
-@@ -696,8 +711,18 @@ static struct pinctrl_state *pinctrl_lookup_state_locked(struct pinctrl *p,
- struct pinctrl_state *state;
-
- state = find_state(p, name);
-- if (!state)
-- return ERR_PTR(-ENODEV);
-+ if (!state) {
-+ if (pinctrl_dummy_state) {
-+ /* create dummy state */
-+ dev_dbg(p->dev, "using pinctrl dummy state (%s)\n",
-+ name);
-+ state = create_state(p, name);
-+ if (IS_ERR(state))
-+ return state;
-+ } else {
-+ return ERR_PTR(-ENODEV);
-+ }
-+ }
-
- return state;
- }
-diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h
-index 9c4a198..7d22ab0 100644
---- a/include/linux/pinctrl/machine.h
-+++ b/include/linux/pinctrl/machine.h
-@@ -154,7 +154,7 @@ struct pinctrl_map {
-
- extern int pinctrl_register_mappings(struct pinctrl_map const *map,
- unsigned num_maps);
--
-+extern void pinctrl_provide_dummies(void);
- #else
-
- static inline int pinctrl_register_mappings(struct pinctrl_map const *map,
-@@ -163,5 +163,8 @@ static inline int pinctrl_register_mappings(struct pinctrl_map const *map,
- return 0;
- }
-
-+static inline void pinctrl_provide_dummies(void)
-+{
-+}
- #endif /* !CONFIG_PINCTRL */
- #endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 87d3596781005abbbadb4b5acc43c0820f80a112 Mon Sep 17 00:00:00 2001
-From: Dong Aisheng <dong.aisheng@linaro.org>
-Date: Wed, 23 May 2012 21:22:40 +0800
-Subject: pinctrl: remove pinctrl_remove_gpio_range
-
-commit 5d589b092ab212bbcc27828167e1c036e7fc77d2 upstream.
-
-The gpio ranges will be automatically removed when the pinctrl
-driver is unregistered.
-
-Acked-by: Stephen Warren <swarren@wwwdotorg.org>
-Signed-off-by: Dong Aisheng <dong.aisheng@linaro.org>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- drivers/pinctrl/core.c | 19 +++++--------------
- drivers/pinctrl/pinctrl-tegra.c | 1 -
- drivers/pinctrl/pinctrl-u300.c | 2 --
- include/linux/pinctrl/pinctrl.h | 2 --
- 4 files changed, 5 insertions(+), 19 deletions(-)
-
-diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
-index 2b6363c5..7b3fc93 100644
---- a/drivers/pinctrl/core.c
-+++ b/drivers/pinctrl/core.c
-@@ -313,20 +313,6 @@ void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
- EXPORT_SYMBOL_GPL(pinctrl_add_gpio_range);
-
- /**
-- * pinctrl_remove_gpio_range() - remove a range of GPIOs fro a pin controller
-- * @pctldev: pin controller device to remove the range from
-- * @range: the GPIO range to remove
-- */
--void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
-- struct pinctrl_gpio_range *range)
--{
-- mutex_lock(&pinctrl_mutex);
-- list_del(&range->node);
-- mutex_unlock(&pinctrl_mutex);
--}
--EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range);
--
--/**
- * pinctrl_get_group_selector() - returns the group selector for a group
- * @pctldev: the pin controller handling the group
- * @pin_group: the pin group to look up
-@@ -1456,6 +1442,7 @@ EXPORT_SYMBOL_GPL(pinctrl_register);
- */
- void pinctrl_unregister(struct pinctrl_dev *pctldev)
- {
-+ struct pinctrl_gpio_range *range, *n;
- if (pctldev == NULL)
- return;
-
-@@ -1471,6 +1458,10 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
- /* Destroy descriptor tree */
- pinctrl_free_pindescs(pctldev, pctldev->desc->pins,
- pctldev->desc->npins);
-+ /* remove gpio ranges map */
-+ list_for_each_entry_safe(range, n, &pctldev->gpio_ranges, node)
-+ list_del(&range->node);
-+
- kfree(pctldev);
-
- mutex_unlock(&pinctrl_mutex);
-diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c
-index 9b32968..0b3c02f 100644
---- a/drivers/pinctrl/pinctrl-tegra.c
-+++ b/drivers/pinctrl/pinctrl-tegra.c
-@@ -525,7 +525,6 @@ static int __devexit tegra_pinctrl_remove(struct platform_device *pdev)
- {
- struct tegra_pmx *pmx = platform_get_drvdata(pdev);
-
-- pinctrl_remove_gpio_range(pmx->pctl, &tegra_pinctrl_gpio_range);
- pinctrl_unregister(pmx->pctl);
-
- return 0;
-diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c
-index 26eb8cc..9ff6207 100644
---- a/drivers/pinctrl/pinctrl-u300.c
-+++ b/drivers/pinctrl/pinctrl-u300.c
-@@ -1185,8 +1185,6 @@ static int __devexit u300_pmx_remove(struct platform_device *pdev)
- struct u300_pmx *upmx = platform_get_drvdata(pdev);
- int i;
-
-- for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++)
-- pinctrl_remove_gpio_range(upmx->pctl, &u300_gpio_ranges[i]);
- pinctrl_unregister(upmx->pctl);
- iounmap(upmx->virtbase);
- release_mem_region(upmx->phybase, upmx->physize);
-diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
-index aa92cde..6e30132 100644
---- a/include/linux/pinctrl/pinctrl.h
-+++ b/include/linux/pinctrl/pinctrl.h
-@@ -124,8 +124,6 @@ extern void pinctrl_unregister(struct pinctrl_dev *pctldev);
- extern bool pin_is_valid(struct pinctrl_dev *pctldev, int pin);
- extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
- struct pinctrl_gpio_range *range);
--extern void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
-- struct pinctrl_gpio_range *range);
- extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
- extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
- #else
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a41052a3f24aebed6c1adb152bba379c729693e0 Mon Sep 17 00:00:00 2001
-From: Dong Aisheng <dong.aisheng@linaro.org>
-Date: Wed, 23 May 2012 21:22:41 +0800
-Subject: pinctrl: add pinctrl_add_gpio_ranges function
-
-commit 3e5e00b654997aa2c3998d30f7213b9611eb23d7 upstream.
-
-Often GPIO ranges are added in batch, so create a special
-function for that.
-
-Acked-by: Stephen Warren <swarren@wwwdotorg.org>
-Signed-off-by: Dong Aisheng <dong.aisheng@linaro.org>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- drivers/pinctrl/core.c | 11 +++++++++++
- include/linux/pinctrl/pinctrl.h | 3 +++
- 2 files changed, 14 insertions(+)
-
-diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
-index 7b3fc93..fa8a440 100644
---- a/drivers/pinctrl/core.c
-+++ b/drivers/pinctrl/core.c
-@@ -312,6 +312,17 @@ void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
- }
- EXPORT_SYMBOL_GPL(pinctrl_add_gpio_range);
-
-+void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
-+ struct pinctrl_gpio_range *ranges,
-+ unsigned nranges)
-+{
-+ int i;
-+
-+ for (i = 0; i < nranges; i++)
-+ pinctrl_add_gpio_range(pctldev, &ranges[i]);
-+}
-+EXPORT_SYMBOL_GPL(pinctrl_add_gpio_ranges);
-+
- /**
- * pinctrl_get_group_selector() - returns the group selector for a group
- * @pctldev: the pin controller handling the group
-diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
-index 6e30132..e162710 100644
---- a/include/linux/pinctrl/pinctrl.h
-+++ b/include/linux/pinctrl/pinctrl.h
-@@ -124,6 +124,9 @@ extern void pinctrl_unregister(struct pinctrl_dev *pctldev);
- extern bool pin_is_valid(struct pinctrl_dev *pctldev, int pin);
- extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
- struct pinctrl_gpio_range *range);
-+extern void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
-+ struct pinctrl_gpio_range *ranges,
-+ unsigned nranges);
- extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
- extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
- #else
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 0de7501c1c0b0fa626a51fecb9af7487e128c1fe Mon Sep 17 00:00:00 2001
-From: Dong Aisheng <dong.aisheng@linaro.org>
-Date: Wed, 25 Apr 2012 19:38:13 +0800
-Subject: pinctrl: support gpio request deferred probing
-
-commit 4650b7cbea4db73f459181f67f939b510e3a17b2 upstream.
-
-As pinctrl handles, it may be possible the pinctrl gpio ranges
-are still not got registered when user call pinctrl_gpio_request.
-Thus, add defer support for it too.
-
-Signed-off-by: Dong Aisheng <dong.aisheng@linaro.org>
-Acked-by: Stephen Warren <swarren@wwwdotorg.org>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- drivers/pinctrl/core.c | 7 ++++---
- 1 file changed, 4 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
-index fa8a440..c9c74dc 100644
---- a/drivers/pinctrl/core.c
-+++ b/drivers/pinctrl/core.c
-@@ -272,7 +272,8 @@ pinctrl_match_gpio_range(struct pinctrl_dev *pctldev, unsigned gpio)
- *
- * Find the pin controller handling a certain GPIO pin from the pinspace of
- * the GPIO subsystem, return the device and the matching GPIO range. Returns
-- * negative if the GPIO range could not be found in any device.
-+ * -EPROBE_DEFER if the GPIO range could not be found in any device since it
-+ * may still have not been registered.
- */
- static int pinctrl_get_device_gpio_range(unsigned gpio,
- struct pinctrl_dev **outdev,
-@@ -292,7 +293,7 @@ static int pinctrl_get_device_gpio_range(unsigned gpio,
- }
- }
-
-- return -EINVAL;
-+ return -EPROBE_DEFER;
- }
-
- /**
-@@ -374,7 +375,7 @@ int pinctrl_request_gpio(unsigned gpio)
- ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
- if (ret) {
- mutex_unlock(&pinctrl_mutex);
-- return -EINVAL;
-+ return ret;
- }
-
- /* Convert to the pin controllers number space */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e9c7b63720ebd0869e642f4aae9f4ff1a53c349c Mon Sep 17 00:00:00 2001
-From: Stephen Warren <swarren@nvidia.com>
-Date: Wed, 25 Apr 2012 10:32:16 -0600
-Subject: pinctrl: propagate map validation errors
-
-commit fde04f419a230fb7f7dc018a9deca6f5d431831e upstream.
-
-pinctrl_register_map() was returning early if pinmux_validate_map() or
-pinconf_validate_map() failed, but was not actually returning the error
-code.
-
-Signed-off-by: Stephen Warren <swarren@nvidia.com>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- drivers/pinctrl/core.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
-index c9c74dc..6ae3a33 100644
---- a/drivers/pinctrl/core.c
-+++ b/drivers/pinctrl/core.c
-@@ -911,13 +911,13 @@ int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
- case PIN_MAP_TYPE_MUX_GROUP:
- ret = pinmux_validate_map(&maps[i], i);
- if (ret < 0)
-- return 0;
-+ return ret;
- break;
- case PIN_MAP_TYPE_CONFIGS_PIN:
- case PIN_MAP_TYPE_CONFIGS_GROUP:
- ret = pinconf_validate_map(&maps[i], i);
- if (ret < 0)
-- return 0;
-+ return ret;
- break;
- default:
- pr_err("failed to register map %s (%d): invalid type given\n",
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 7b9faf9925d33fe49a04ccad79dbb7ca08a8cc67 Mon Sep 17 00:00:00 2001
-From: Linus Walleij <linus.walleij@linaro.org>
-Date: Thu, 12 Apr 2012 19:48:42 +0200
-Subject: pinctrl: mark non-EXPERIMENTAL
-
-commit 630e2d0494f001cc3c435cac374f92e4bde0f518 upstream.
-
-With the finalization of the external driver API and the device
-tree support, this subsystem is now mature and can be promoted to
-non-experimental status.
-
-Acked-by: Stephen Warren <swarren@wwwdotorg.org>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- drivers/pinctrl/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
-index abfb964..f73a5ea 100644
---- a/drivers/pinctrl/Kconfig
-+++ b/drivers/pinctrl/Kconfig
-@@ -4,7 +4,6 @@
-
- config PINCTRL
- bool
-- depends on EXPERIMENTAL
-
- if PINCTRL
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ca7138a65812dda79268a64d765335279d4f917c Mon Sep 17 00:00:00 2001
-From: Linus Walleij <linus.walleij@linaro.org>
-Date: Tue, 10 Apr 2012 10:00:38 +0200
-Subject: pinctrl: implement pinctrl deferred probing
-
-commit c05127c4e2c6e7d9949347a76fd05c337bcd5e84 upstream.
-
-If drivers try to obtain pinctrl handles for a pin controller that
-has not yet registered to the subsystem, we need to be able to
-back out and retry with deferred probing. So let's return
--EPROBE_DEFER whenever this location fails. Also downgrade the
-errors to info, maybe we will even set them to debug once the
-deferred probing is commonplace.
-
-Cc: Arnd Bergmann <arnd@arndb.de>
-Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-Acked-by: Stephen Warren <swarren@wwwdotorg.org>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- Documentation/pinctrl.txt | 5 +++++
- drivers/pinctrl/core.c | 9 ++++++---
- drivers/pinctrl/devicetree.c | 6 +++---
- 3 files changed, 14 insertions(+), 6 deletions(-)
-
-diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
-index fa829f1..b85f0bd 100644
---- a/Documentation/pinctrl.txt
-+++ b/Documentation/pinctrl.txt
-@@ -1059,6 +1059,11 @@ The pins are allocated for your device when you issue the devm_pinctrl_get()
- call, after this you should be able to see this in the debugfs listing of all
- pins.
-
-+NOTE: the pinctrl system will return -EPROBE_DEFER if it cannot find the
-+requested pinctrl handles, for example if the pinctrl driver has not yet
-+registered. Thus make sure that the error path in your driver gracefully
-+cleans up and is ready to retry the probing later in the startup process.
-+
-
- System pin control hogging
- ==========================
-diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
-index 6ae3a33..ff78028 100644
---- a/drivers/pinctrl/core.c
-+++ b/drivers/pinctrl/core.c
-@@ -531,11 +531,14 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
-
- setting->pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
- if (setting->pctldev == NULL) {
-- dev_err(p->dev, "unknown pinctrl device %s in map entry",
-+ dev_info(p->dev, "unknown pinctrl device %s in map entry, deferring probe",
- map->ctrl_dev_name);
- kfree(setting);
-- /* Eventually, this should trigger deferred probe */
-- return -ENODEV;
-+ /*
-+ * OK let us guess that the driver is not there yet, and
-+ * let's defer obtaining this pinctrl handle to later...
-+ */
-+ return -EPROBE_DEFER;
- }
-
- switch (map->type) {
-diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
-index 5ef2feb..fcb1de4 100644
---- a/drivers/pinctrl/devicetree.c
-+++ b/drivers/pinctrl/devicetree.c
-@@ -121,11 +121,11 @@ static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
- for (;;) {
- np_pctldev = of_get_next_parent(np_pctldev);
- if (!np_pctldev || of_node_is_root(np_pctldev)) {
-- dev_err(p->dev, "could not find pctldev for node %s\n",
-+ dev_info(p->dev, "could not find pctldev for node %s, deferring probe\n",
- np_config->full_name);
- of_node_put(np_pctldev);
-- /* FIXME: This should trigger deferrered probe */
-- return -ENODEV;
-+ /* OK let's just assume this will appear later then */
-+ return -EPROBE_DEFER;
- }
- pctldev = find_pinctrl_by_of_node(np_pctldev);
- if (pctldev)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 9ef4d54b79f8a5da7112864968dcf12cb1bcedb4 Mon Sep 17 00:00:00 2001
-From: Viresh Kumar <viresh.kumar@st.com>
-Date: Fri, 30 Mar 2012 11:25:40 +0530
-Subject: pinctrl: replace list_*() with get_*_count()
-
-commit d1e90e9e7467dbfe521b25ba79f520bf676ebc36 upstream.
-
-Most of the SoC drivers implement list_groups() and list_functions()
-routines for pinctrl and pinmux. These routines continue returning
-zero until the selector argument is greater than total count of
-available groups or functions.
-
-This patch replaces these list_*() routines with get_*_count()
-routines, which returns the number of available selection for SoC
-driver. pinctrl layer will use this value to check the range it can
-choose.
-
-This patch fixes all user drivers for this change. There are other
-routines in user drivers, which have checks to check validity of
-selector passed to them. It is also no more required and hence
-removed.
-
-Documentation updated as well.
-
-Acked-by: Stephen Warren <swarren@wwwdotorg.org>
-Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
-[Folded in fix and fixed a minor merge artifact manually]
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- Documentation/pinctrl.txt | 37 +++++++++++++++----------------------
- drivers/pinctrl/core.c | 10 ++++++----
- drivers/pinctrl/pinconf.c | 3 ++-
- drivers/pinctrl/pinctrl-pxa3xx.c | 24 ++++++++++--------------
- drivers/pinctrl/pinctrl-sirf.c | 20 ++++++--------------
- drivers/pinctrl/pinctrl-tegra.c | 40 ++++++----------------------------------
- drivers/pinctrl/pinctrl-u300.c | 20 ++++++--------------
- drivers/pinctrl/pinmux.c | 11 +++++++----
- include/linux/pinctrl/pinctrl.h | 6 ++----
- include/linux/pinctrl/pinmux.h | 7 +++----
- 10 files changed, 63 insertions(+), 115 deletions(-)
-
-diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
-index b85f0bd..f5add79 100644
---- a/Documentation/pinctrl.txt
-+++ b/Documentation/pinctrl.txt
-@@ -152,11 +152,9 @@ static const struct foo_group foo_groups[] = {
- };
-
-
--static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
-+static int foo_get_groups_count(struct pinctrl_dev *pctldev)
- {
-- if (selector >= ARRAY_SIZE(foo_groups))
-- return -EINVAL;
-- return 0;
-+ return ARRAY_SIZE(foo_groups);
- }
-
- static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
-@@ -175,7 +173,7 @@ static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
- }
-
- static struct pinctrl_ops foo_pctrl_ops = {
-- .list_groups = foo_list_groups,
-+ .get_groups_count = foo_get_groups_count,
- .get_group_name = foo_get_group_name,
- .get_group_pins = foo_get_group_pins,
- };
-@@ -186,13 +184,12 @@ static struct pinctrl_desc foo_desc = {
- .pctlops = &foo_pctrl_ops,
- };
-
--The pin control subsystem will call the .list_groups() function repeatedly
--beginning on 0 until it returns non-zero to determine legal selectors, then
--it will call the other functions to retrieve the name and pins of the group.
--Maintaining the data structure of the groups is up to the driver, this is
--just a simple example - in practice you may need more entries in your group
--structure, for example specific register ranges associated with each group
--and so on.
-+The pin control subsystem will call the .get_groups_count() function to
-+determine total number of legal selectors, then it will call the other functions
-+to retrieve the name and pins of the group. Maintaining the data structure of
-+the groups is up to the driver, this is just a simple example - in practice you
-+may need more entries in your group structure, for example specific register
-+ranges associated with each group and so on.
-
-
- Pin configuration
-@@ -606,11 +603,9 @@ static const struct foo_group foo_groups[] = {
- };
-
-
--static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
-+static int foo_get_groups_count(struct pinctrl_dev *pctldev)
- {
-- if (selector >= ARRAY_SIZE(foo_groups))
-- return -EINVAL;
-- return 0;
-+ return ARRAY_SIZE(foo_groups);
- }
-
- static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
-@@ -629,7 +624,7 @@ static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
- }
-
- static struct pinctrl_ops foo_pctrl_ops = {
-- .list_groups = foo_list_groups,
-+ .get_groups_count = foo_get_groups_count,
- .get_group_name = foo_get_group_name,
- .get_group_pins = foo_get_group_pins,
- };
-@@ -663,11 +658,9 @@ static const struct foo_pmx_func foo_functions[] = {
- },
- };
-
--int foo_list_funcs(struct pinctrl_dev *pctldev, unsigned selector)
-+int foo_get_functions_count(struct pinctrl_dev *pctldev)
- {
-- if (selector >= ARRAY_SIZE(foo_functions))
-- return -EINVAL;
-- return 0;
-+ return ARRAY_SIZE(foo_functions);
- }
-
- const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned selector)
-@@ -703,7 +696,7 @@ void foo_disable(struct pinctrl_dev *pctldev, unsigned selector,
- }
-
- struct pinmux_ops foo_pmxops = {
-- .list_functions = foo_list_funcs,
-+ .get_functions_count = foo_get_functions_count,
- .get_function_name = foo_get_fname,
- .get_function_groups = foo_get_groups,
- .enable = foo_enable,
-diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
-index ff78028..c70ae2d 100644
---- a/drivers/pinctrl/core.c
-+++ b/drivers/pinctrl/core.c
-@@ -333,9 +333,10 @@ int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
- const char *pin_group)
- {
- const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
-+ unsigned ngroups = pctlops->get_groups_count(pctldev);
- unsigned group_selector = 0;
-
-- while (pctlops->list_groups(pctldev, group_selector) >= 0) {
-+ while (group_selector < ngroups) {
- const char *gname = pctlops->get_group_name(pctldev,
- group_selector);
- if (!strcmp(gname, pin_group)) {
-@@ -1023,12 +1024,13 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
- {
- struct pinctrl_dev *pctldev = s->private;
- const struct pinctrl_ops *ops = pctldev->desc->pctlops;
-- unsigned selector = 0;
-+ unsigned ngroups, selector = 0;
-
-+ ngroups = ops->get_groups_count(pctldev);
- mutex_lock(&pinctrl_mutex);
-
- seq_puts(s, "registered pin groups:\n");
-- while (ops->list_groups(pctldev, selector) >= 0) {
-+ while (selector < ngroups) {
- const unsigned *pins;
- unsigned num_pins;
- const char *gname = ops->get_group_name(pctldev, selector);
-@@ -1343,7 +1345,7 @@ static int pinctrl_check_ops(struct pinctrl_dev *pctldev)
- const struct pinctrl_ops *ops = pctldev->desc->pctlops;
-
- if (!ops ||
-- !ops->list_groups ||
-+ !ops->get_groups_count ||
- !ops->get_group_name ||
- !ops->get_group_pins)
- return -EINVAL;
-diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
-index 7321e86..eb3a14f4 100644
---- a/drivers/pinctrl/pinconf.c
-+++ b/drivers/pinctrl/pinconf.c
-@@ -495,6 +495,7 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
- struct pinctrl_dev *pctldev = s->private;
- const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
- const struct pinconf_ops *ops = pctldev->desc->confops;
-+ unsigned ngroups = pctlops->get_groups_count(pctldev);
- unsigned selector = 0;
-
- if (!ops || !ops->pin_config_group_get)
-@@ -505,7 +506,7 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
-
- mutex_lock(&pinctrl_mutex);
-
-- while (pctlops->list_groups(pctldev, selector) >= 0) {
-+ while (selector < ngroups) {
- const char *gname = pctlops->get_group_name(pctldev, selector);
-
- seq_printf(s, "%u (%s):", selector, gname);
-diff --git a/drivers/pinctrl/pinctrl-pxa3xx.c b/drivers/pinctrl/pinctrl-pxa3xx.c
-index 079dce0..7644e42 100644
---- a/drivers/pinctrl/pinctrl-pxa3xx.c
-+++ b/drivers/pinctrl/pinctrl-pxa3xx.c
-@@ -25,20 +25,18 @@ static struct pinctrl_gpio_range pxa3xx_pinctrl_gpio_range = {
- .pin_base = 0,
- };
-
--static int pxa3xx_list_groups(struct pinctrl_dev *pctrldev, unsigned selector)
-+static int pxa3xx_get_groups_count(struct pinctrl_dev *pctrldev)
- {
- struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-- if (selector >= info->num_grps)
-- return -EINVAL;
-- return 0;
-+
-+ return info->num_grps;
- }
-
- static const char *pxa3xx_get_group_name(struct pinctrl_dev *pctrldev,
- unsigned selector)
- {
- struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-- if (selector >= info->num_grps)
-- return NULL;
-+
- return info->grps[selector].name;
- }
-
-@@ -48,25 +46,23 @@ static int pxa3xx_get_group_pins(struct pinctrl_dev *pctrldev,
- unsigned *num_pins)
- {
- struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-- if (selector >= info->num_grps)
-- return -EINVAL;
-+
- *pins = info->grps[selector].pins;
- *num_pins = info->grps[selector].npins;
- return 0;
- }
-
- static struct pinctrl_ops pxa3xx_pctrl_ops = {
-- .list_groups = pxa3xx_list_groups,
-+ .get_groups_count = pxa3xx_get_groups_count,
- .get_group_name = pxa3xx_get_group_name,
- .get_group_pins = pxa3xx_get_group_pins,
- };
-
--static int pxa3xx_pmx_list_func(struct pinctrl_dev *pctrldev, unsigned func)
-+static int pxa3xx_pmx_get_funcs_count(struct pinctrl_dev *pctrldev)
- {
- struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-- if (func >= info->num_funcs)
-- return -EINVAL;
-- return 0;
-+
-+ return info->num_funcs;
- }
-
- static const char *pxa3xx_pmx_get_func_name(struct pinctrl_dev *pctrldev,
-@@ -170,7 +166,7 @@ static int pxa3xx_pmx_request_gpio(struct pinctrl_dev *pctrldev,
- }
-
- static struct pinmux_ops pxa3xx_pmx_ops = {
-- .list_functions = pxa3xx_pmx_list_func,
-+ .get_functions_count = pxa3xx_pmx_get_funcs_count,
- .get_function_name = pxa3xx_pmx_get_func_name,
- .get_function_groups = pxa3xx_pmx_get_groups,
- .enable = pxa3xx_pmx_enable,
-diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c
-index 6b3534c..ba15b1a 100644
---- a/drivers/pinctrl/pinctrl-sirf.c
-+++ b/drivers/pinctrl/pinctrl-sirf.c
-@@ -853,18 +853,14 @@ static const struct sirfsoc_pin_group sirfsoc_pin_groups[] = {
- SIRFSOC_PIN_GROUP("gpsgrp", gps_pins),
- };
-
--static int sirfsoc_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
-+static int sirfsoc_get_groups_count(struct pinctrl_dev *pctldev)
- {
-- if (selector >= ARRAY_SIZE(sirfsoc_pin_groups))
-- return -EINVAL;
-- return 0;
-+ return ARRAY_SIZE(sirfsoc_pin_groups);
- }
-
- static const char *sirfsoc_get_group_name(struct pinctrl_dev *pctldev,
- unsigned selector)
- {
-- if (selector >= ARRAY_SIZE(sirfsoc_pin_groups))
-- return NULL;
- return sirfsoc_pin_groups[selector].name;
- }
-
-@@ -872,8 +868,6 @@ static int sirfsoc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector
- const unsigned **pins,
- unsigned *num_pins)
- {
-- if (selector >= ARRAY_SIZE(sirfsoc_pin_groups))
-- return -EINVAL;
- *pins = sirfsoc_pin_groups[selector].pins;
- *num_pins = sirfsoc_pin_groups[selector].num_pins;
- return 0;
-@@ -886,7 +880,7 @@ static void sirfsoc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s
- }
-
- static struct pinctrl_ops sirfsoc_pctrl_ops = {
-- .list_groups = sirfsoc_list_groups,
-+ .get_groups_count = sirfsoc_get_groups_count,
- .get_group_name = sirfsoc_get_group_name,
- .get_group_pins = sirfsoc_get_group_pins,
- .pin_dbg_show = sirfsoc_pin_dbg_show,
-@@ -1033,11 +1027,9 @@ static void sirfsoc_pinmux_disable(struct pinctrl_dev *pmxdev, unsigned selector
- sirfsoc_pinmux_endisable(spmx, selector, false);
- }
-
--static int sirfsoc_pinmux_list_funcs(struct pinctrl_dev *pmxdev, unsigned selector)
-+static int sirfsoc_pinmux_get_funcs_count(struct pinctrl_dev *pmxdev)
- {
-- if (selector >= ARRAY_SIZE(sirfsoc_pmx_functions))
-- return -EINVAL;
-- return 0;
-+ return ARRAY_SIZE(sirfsoc_pmx_functions);
- }
-
- static const char *sirfsoc_pinmux_get_func_name(struct pinctrl_dev *pctldev,
-@@ -1074,9 +1066,9 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
- }
-
- static struct pinmux_ops sirfsoc_pinmux_ops = {
-- .list_functions = sirfsoc_pinmux_list_funcs,
- .enable = sirfsoc_pinmux_enable,
- .disable = sirfsoc_pinmux_disable,
-+ .get_functions_count = sirfsoc_pinmux_get_funcs_count,
- .get_function_name = sirfsoc_pinmux_get_func_name,
- .get_function_groups = sirfsoc_pinmux_get_groups,
- .gpio_request_enable = sirfsoc_pinmux_request_gpio,
-diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c
-index 0b3c02f..c4c47c5 100644
---- a/drivers/pinctrl/pinctrl-tegra.c
-+++ b/drivers/pinctrl/pinctrl-tegra.c
-@@ -53,15 +53,11 @@ static inline void pmx_writel(struct tegra_pmx *pmx, u32 val, u32 bank, u32 reg)
- writel(val, pmx->regs[bank] + reg);
- }
-
--static int tegra_pinctrl_list_groups(struct pinctrl_dev *pctldev,
-- unsigned group)
-+static int tegra_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
- {
- struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-
-- if (group >= pmx->soc->ngroups)
-- return -EINVAL;
--
-- return 0;
-+ return pmx->soc->ngroups;
- }
-
- static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
-@@ -69,9 +65,6 @@ static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
- {
- struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-
-- if (group >= pmx->soc->ngroups)
-- return NULL;
--
- return pmx->soc->groups[group].name;
- }
-
-@@ -82,9 +75,6 @@ static int tegra_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
- {
- struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-
-- if (group >= pmx->soc->ngroups)
-- return -EINVAL;
--
- *pins = pmx->soc->groups[group].pins;
- *num_pins = pmx->soc->groups[group].npins;
-
-@@ -99,21 +89,17 @@ static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
- }
-
- static struct pinctrl_ops tegra_pinctrl_ops = {
-- .list_groups = tegra_pinctrl_list_groups,
-+ .get_groups_count = tegra_pinctrl_get_groups_count,
- .get_group_name = tegra_pinctrl_get_group_name,
- .get_group_pins = tegra_pinctrl_get_group_pins,
- .pin_dbg_show = tegra_pinctrl_pin_dbg_show,
- };
-
--static int tegra_pinctrl_list_funcs(struct pinctrl_dev *pctldev,
-- unsigned function)
-+static int tegra_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
- {
- struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-
-- if (function >= pmx->soc->nfunctions)
-- return -EINVAL;
--
-- return 0;
-+ return pmx->soc->nfunctions;
- }
-
- static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
-@@ -121,9 +107,6 @@ static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
- {
- struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-
-- if (function >= pmx->soc->nfunctions)
-- return NULL;
--
- return pmx->soc->functions[function].name;
- }
-
-@@ -134,9 +117,6 @@ static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
- {
- struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-
-- if (function >= pmx->soc->nfunctions)
-- return -EINVAL;
--
- *groups = pmx->soc->functions[function].groups;
- *num_groups = pmx->soc->functions[function].ngroups;
-
-@@ -151,8 +131,6 @@ static int tegra_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function,
- int i;
- u32 val;
-
-- if (group >= pmx->soc->ngroups)
-- return -EINVAL;
- g = &pmx->soc->groups[group];
-
- if (g->mux_reg < 0)
-@@ -180,8 +158,6 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
- const struct tegra_pingroup *g;
- u32 val;
-
-- if (group >= pmx->soc->ngroups)
-- return;
- g = &pmx->soc->groups[group];
-
- if (g->mux_reg < 0)
-@@ -194,7 +170,7 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
- }
-
- static struct pinmux_ops tegra_pinmux_ops = {
-- .list_functions = tegra_pinctrl_list_funcs,
-+ .get_functions_count = tegra_pinctrl_get_funcs_count,
- .get_function_name = tegra_pinctrl_get_func_name,
- .get_function_groups = tegra_pinctrl_get_func_groups,
- .enable = tegra_pinctrl_enable,
-@@ -324,8 +300,6 @@ static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev,
- s16 reg;
- u32 val, mask;
-
-- if (group >= pmx->soc->ngroups)
-- return -EINVAL;
- g = &pmx->soc->groups[group];
-
- ret = tegra_pinconf_reg(pmx, g, param, &bank, ®, &bit, &width);
-@@ -353,8 +327,6 @@ static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
- s16 reg;
- u32 val, mask;
-
-- if (group >= pmx->soc->ngroups)
-- return -EINVAL;
- g = &pmx->soc->groups[group];
-
- ret = tegra_pinconf_reg(pmx, g, param, &bank, ®, &bit, &width);
-diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c
-index 9ff6207..10de43c 100644
---- a/drivers/pinctrl/pinctrl-u300.c
-+++ b/drivers/pinctrl/pinctrl-u300.c
-@@ -836,18 +836,14 @@ static const struct u300_pin_group u300_pin_groups[] = {
- },
- };
-
--static int u300_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
-+static int u300_get_groups_count(struct pinctrl_dev *pctldev)
- {
-- if (selector >= ARRAY_SIZE(u300_pin_groups))
-- return -EINVAL;
-- return 0;
-+ return ARRAY_SIZE(u300_pin_groups);
- }
-
- static const char *u300_get_group_name(struct pinctrl_dev *pctldev,
- unsigned selector)
- {
-- if (selector >= ARRAY_SIZE(u300_pin_groups))
-- return NULL;
- return u300_pin_groups[selector].name;
- }
-
-@@ -855,8 +851,6 @@ static int u300_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
- const unsigned **pins,
- unsigned *num_pins)
- {
-- if (selector >= ARRAY_SIZE(u300_pin_groups))
-- return -EINVAL;
- *pins = u300_pin_groups[selector].pins;
- *num_pins = u300_pin_groups[selector].num_pins;
- return 0;
-@@ -869,7 +863,7 @@ static void u300_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
- }
-
- static struct pinctrl_ops u300_pctrl_ops = {
-- .list_groups = u300_list_groups,
-+ .get_groups_count = u300_get_groups_count,
- .get_group_name = u300_get_group_name,
- .get_group_pins = u300_get_group_pins,
- .pin_dbg_show = u300_pin_dbg_show,
-@@ -991,11 +985,9 @@ static void u300_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
- u300_pmx_endisable(upmx, selector, false);
- }
-
--static int u300_pmx_list_funcs(struct pinctrl_dev *pctldev, unsigned selector)
-+static int u300_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
- {
-- if (selector >= ARRAY_SIZE(u300_pmx_functions))
-- return -EINVAL;
-- return 0;
-+ return ARRAY_SIZE(u300_pmx_functions);
- }
-
- static const char *u300_pmx_get_func_name(struct pinctrl_dev *pctldev,
-@@ -1014,7 +1006,7 @@ static int u300_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
- }
-
- static struct pinmux_ops u300_pmx_ops = {
-- .list_functions = u300_pmx_list_funcs,
-+ .get_functions_count = u300_pmx_get_funcs_count,
- .get_function_name = u300_pmx_get_func_name,
- .get_function_groups = u300_pmx_get_groups,
- .enable = u300_pmx_enable,
-diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
-index 4e62783..375b214 100644
---- a/drivers/pinctrl/pinmux.c
-+++ b/drivers/pinctrl/pinmux.c
-@@ -33,10 +33,11 @@
- int pinmux_check_ops(struct pinctrl_dev *pctldev)
- {
- const struct pinmux_ops *ops = pctldev->desc->pmxops;
-+ unsigned nfuncs = ops->get_functions_count(pctldev);
- unsigned selector = 0;
-
- /* Check that we implement required operations */
-- if (!ops->list_functions ||
-+ if (!ops->get_functions_count ||
- !ops->get_function_name ||
- !ops->get_function_groups ||
- !ops->enable ||
-@@ -44,7 +45,7 @@ int pinmux_check_ops(struct pinctrl_dev *pctldev)
- return -EINVAL;
-
- /* Check that all functions registered have names */
-- while (ops->list_functions(pctldev, selector) >= 0) {
-+ while (selector < nfuncs) {
- const char *fname = ops->get_function_name(pctldev,
- selector);
- if (!fname) {
-@@ -287,10 +288,11 @@ static int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev,
- const char *function)
- {
- const struct pinmux_ops *ops = pctldev->desc->pmxops;
-+ unsigned nfuncs = ops->get_functions_count(pctldev);
- unsigned selector = 0;
-
- /* See if this pctldev has this function */
-- while (ops->list_functions(pctldev, selector) >= 0) {
-+ while (selector < nfuncs) {
- const char *fname = ops->get_function_name(pctldev,
- selector);
-
-@@ -477,11 +479,12 @@ static int pinmux_functions_show(struct seq_file *s, void *what)
- {
- struct pinctrl_dev *pctldev = s->private;
- const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
-+ unsigned nfuncs = pmxops->get_functions_count(pctldev);
- unsigned func_selector = 0;
-
- mutex_lock(&pinctrl_mutex);
-
-- while (pmxops->list_functions(pctldev, func_selector) >= 0) {
-+ while (func_selector < nfuncs) {
- const char *func = pmxops->get_function_name(pctldev,
- func_selector);
- const char * const *groups;
-diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
-index e162710..ba08516 100644
---- a/include/linux/pinctrl/pinctrl.h
-+++ b/include/linux/pinctrl/pinctrl.h
-@@ -66,9 +66,7 @@ struct pinctrl_gpio_range {
- /**
- * struct pinctrl_ops - global pin control operations, to be implemented by
- * pin controller drivers.
-- * @list_groups: list the number of selectable named groups available
-- * in this pinmux driver, the core will begin on 0 and call this
-- * repeatedly as long as it returns >= 0 to enumerate the groups
-+ * @get_groups_count: Returns the count of total number of groups registered.
- * @get_group_name: return the group name of the pin group
- * @get_group_pins: return an array of pins corresponding to a certain
- * group selector @pins, and the size of the array in @num_pins
-@@ -76,7 +74,7 @@ struct pinctrl_gpio_range {
- * info for a certain pin in debugfs
- */
- struct pinctrl_ops {
-- int (*list_groups) (struct pinctrl_dev *pctldev, unsigned selector);
-+ int (*get_groups_count) (struct pinctrl_dev *pctldev);
- const char *(*get_group_name) (struct pinctrl_dev *pctldev,
- unsigned selector);
- int (*get_group_pins) (struct pinctrl_dev *pctldev,
-diff --git a/include/linux/pinctrl/pinmux.h b/include/linux/pinctrl/pinmux.h
-index 47e9237..dd7bef6 100644
---- a/include/linux/pinctrl/pinmux.h
-+++ b/include/linux/pinctrl/pinmux.h
-@@ -29,9 +29,8 @@ struct pinctrl_dev;
- * is allowed to answer "no" by returning a negative error code
- * @free: the reverse function of the request() callback, frees a pin after
- * being requested
-- * @list_functions: list the number of selectable named functions available
-- * in this pinmux driver, the core will begin on 0 and call this
-- * repeatedly as long as it returns >= 0 to enumerate mux settings
-+ * @get_functions_count: returns number of selectable named functions available
-+ * in this pinmux driver
- * @get_function_name: return the function name of the muxing selector,
- * called by the core to figure out which mux setting it shall map a
- * certain device to
-@@ -62,7 +61,7 @@ struct pinctrl_dev;
- struct pinmux_ops {
- int (*request) (struct pinctrl_dev *pctldev, unsigned offset);
- int (*free) (struct pinctrl_dev *pctldev, unsigned offset);
-- int (*list_functions) (struct pinctrl_dev *pctldev, unsigned selector);
-+ int (*get_functions_count) (struct pinctrl_dev *pctldev);
- const char *(*get_function_name) (struct pinctrl_dev *pctldev,
- unsigned selector);
- int (*get_function_groups) (struct pinctrl_dev *pctldev,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 063384f9528680eae1564f69f66bbb240c6398ea Mon Sep 17 00:00:00 2001
-From: Dong Aisheng <dong.aisheng@linaro.org>
-Date: Tue, 17 Apr 2012 15:00:45 +0800
-Subject: pinctrl: show pin name when request pins
-
-commit d0bd8df56ebffe4a5ca42e27aca2a1243c70ed53 upstream.
-
-Pin name is more useful to users.
-
-Acked-by: Stephen Warren <swarren@wwwdotorg.org>
-Signed-off-by: Dong Aisheng <dong.aisheng@linaro.org>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- drivers/pinctrl/pinmux.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
-index 375b214..d6f6823 100644
---- a/drivers/pinctrl/pinmux.c
-+++ b/drivers/pinctrl/pinmux.c
-@@ -86,8 +86,6 @@ static int pin_request(struct pinctrl_dev *pctldev,
- const struct pinmux_ops *ops = pctldev->desc->pmxops;
- int status = -EINVAL;
-
-- dev_dbg(pctldev->dev, "request pin %d for %s\n", pin, owner);
--
- desc = pin_desc_get(pctldev, pin);
- if (desc == NULL) {
- dev_err(pctldev->dev,
-@@ -95,6 +93,9 @@ static int pin_request(struct pinctrl_dev *pctldev,
- goto out;
- }
-
-+ dev_dbg(pctldev->dev, "request pin %d (%s) for %s\n",
-+ pin, desc->name, owner);
-+
- if (gpio_range) {
- /* There's no need to support multiple GPIO requests */
- if (desc->gpio_owner) {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 98e0834df26052480b71e183d23b6cc38d51d7a0 Mon Sep 17 00:00:00 2001
-From: Dong Aisheng <dong.aisheng@linaro.org>
-Date: Tue, 17 Apr 2012 15:00:46 +0800
-Subject: pinctrl: show pin name for pingroups in sysfs
-
-commit dcb5dbc305b975cccf40942feba40964069541d3 upstream.
-
-Pin name is more useful to users.
-
-After change, when cat pingroups in sysfs, it becomes:
-root@freescale /sys/kernel/debug/pinctrl/20e0000.iomuxc$ cat pingroups
-registered pin groups:
-group: uart4grp-1
-pin 219 (MX6Q_PAD_KEY_ROW0)
-pin 218 (MX6Q_PAD_KEY_COL0)
-
-group: usdhc4grp-1
-pin 305 (MX6Q_PAD_SD4_CMD)
-pin 306 (MX6Q_PAD_SD4_CLK)
-pin 315 (MX6Q_PAD_SD4_DAT0)
-pin 316 (MX6Q_PAD_SD4_DAT1)
-pin 317 (MX6Q_PAD_SD4_DAT2)
-pin 318 (MX6Q_PAD_SD4_DAT3)
-pin 319 (MX6Q_PAD_SD4_DAT4)
-pin 320 (MX6Q_PAD_SD4_DAT5)
-pin 321 (MX6Q_PAD_SD4_DAT6)
-pin 322 (MX6Q_PAD_SD4_DAT7)
-
-Acked-by: Stephen Warren <swarren@wwwdotorg.org>
-Signed-off-by: Dong Aisheng <dong.aisheng@linaro.org>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- drivers/pinctrl/core.c | 32 ++++++++++++++++++++++++++++----
- drivers/pinctrl/core.h | 1 +
- 2 files changed, 29 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
-index c70ae2d..5f8a7d2 100644
---- a/drivers/pinctrl/core.c
-+++ b/drivers/pinctrl/core.c
-@@ -141,6 +141,25 @@ int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name)
- }
-
- /**
-+ * pin_get_name_from_id() - look up a pin name from a pin id
-+ * @pctldev: the pin control device to lookup the pin on
-+ * @name: the name of the pin to look up
-+ */
-+const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin)
-+{
-+ const struct pin_desc *desc;
-+
-+ desc = pin_desc_get(pctldev, pin);
-+ if (desc == NULL) {
-+ dev_err(pctldev->dev, "failed to get pin(%d) name\n",
-+ pin);
-+ return NULL;
-+ }
-+
-+ return desc->name;
-+}
-+
-+/**
- * pin_is_valid() - check if pin exists on controller
- * @pctldev: the pin control device to check the pin on
- * @pin: pin to check, use the local pin controller index number
-@@ -1034,6 +1053,7 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
- const unsigned *pins;
- unsigned num_pins;
- const char *gname = ops->get_group_name(pctldev, selector);
-+ const char *pname;
- int ret;
- int i;
-
-@@ -1043,10 +1063,14 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
- seq_printf(s, "%s [ERROR GETTING PINS]\n",
- gname);
- else {
-- seq_printf(s, "group: %s, pins = [ ", gname);
-- for (i = 0; i < num_pins; i++)
-- seq_printf(s, "%d ", pins[i]);
-- seq_puts(s, "]\n");
-+ seq_printf(s, "group: %s\n", gname);
-+ for (i = 0; i < num_pins; i++) {
-+ pname = pin_get_name(pctldev, pins[i]);
-+ if (WARN_ON(!pname))
-+ return -EINVAL;
-+ seq_printf(s, "pin %d (%s)\n", pins[i], pname);
-+ }
-+ seq_puts(s, "\n");
- }
- selector++;
- }
-diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
-index 98ae808..1f40ff6 100644
---- a/drivers/pinctrl/core.h
-+++ b/drivers/pinctrl/core.h
-@@ -148,6 +148,7 @@ struct pin_desc {
-
- struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name);
- int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name);
-+const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin);
- int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
- const char *pin_group);
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From c71effdb46261af0b8304ed628c0f2d97e9b56d6 Mon Sep 17 00:00:00 2001
-From: Dong Aisheng <dong.aisheng@linaro.org>
-Date: Fri, 27 Apr 2012 11:36:20 +0800
-Subject: dt: add of_get_child_count helper function
-
-commit 183f1d0c6450ee032d97a2d01ed5eb00e0dbaa49 upstream.
-
-Currently most code to get child count in kernel are almost same,
-add a helper to implement this function for dt to use.
-
-Cc: Grant Likely <grant.likely@secretlab.ca>
-Acked-by: Rob Herring <rob.herring@calxeda.com>
-Acked-by: Stephen Warren <swarren@wwwdotorg.org>
-Signed-off-by: Dong Aisheng <dong.aisheng@linaro.org>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- include/linux/of.h | 16 ++++++++++++++++
- 1 file changed, 16 insertions(+)
-
---- a/include/linux/of.h
-+++ b/include/linux/of.h
-@@ -194,6 +194,17 @@ extern struct device_node *of_get_next_c
- for (child = of_get_next_child(parent, NULL); child != NULL; \
- child = of_get_next_child(parent, child))
-
-+static inline int of_get_child_count(const struct device_node *np)
-+{
-+ struct device_node *child;
-+ int num = 0;
-+
-+ for_each_child_of_node(np, child)
-+ num++;
-+
-+ return num;
-+}
-+
- extern struct device_node *of_find_node_with_property(
- struct device_node *from, const char *prop_name);
- #define for_each_node_with_property(dn, prop_name) \
-@@ -306,6 +317,11 @@ static inline bool of_have_populated_dt(
- #define for_each_child_of_node(parent, child) \
- while (0)
-
-+static inline int of_get_child_count(const struct device_node *np)
-+{
-+ return 0;
-+}
-+
- static inline int of_device_is_compatible(const struct device_node *device,
- const char *name)
- {
+++ /dev/null
-From 8eaef7cd81925116f062014a50057edf8b24ebc3 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 24 Sep 2012 14:57:08 +0200
-Subject: MTD: atmel_nand: add 9x5 to list of SoC with DMA
-
-Temporary: may have to be replaced by a device-tree property.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/mtd/nand/atmel_nand.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
-index b5e5a76..a1b5468 100644
---- a/drivers/mtd/nand/atmel_nand.c
-+++ b/drivers/mtd/nand/atmel_nand.c
-@@ -127,7 +127,7 @@ static struct nand_ecclayout atmel_pmecc_oobinfo;
-
- static int cpu_has_dma(void)
- {
-- return cpu_is_at91sam9rl() || cpu_is_at91sam9g45();
-+ return cpu_is_at91sam9rl() || cpu_is_at91sam9g45() || cpu_is_at91sam9x5();
- }
-
- /*
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 7e46312721b0ed2c4a893b2b38cca0fcd39c1cc5 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 24 Sep 2012 15:07:06 +0200
-Subject: MTD: atmel_nand: POI fall back is not an issue: change log
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/mtd/nand/atmel_nand.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
-index a1b5468..cacccba 100644
---- a/drivers/mtd/nand/atmel_nand.c
-+++ b/drivers/mtd/nand/atmel_nand.c
-@@ -281,7 +281,7 @@ err_dma:
- dma_unmap_single(dma_dev->dev, phys_addr, len, dir);
- err_buf:
- if (err != 0)
-- dev_warn(host->dev, "Fall back to CPU I/O\n");
-+ dev_dbg(host->dev, "Fall back to CPU I/O\n");
- return err;
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From bfa303b459025a62eae939042183bb3b78fe5107 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 8 Oct 2012 16:55:29 +0200
-Subject: MTD: atmel_nand: add 9n12 to list of SoC with DMA
-
-Temporary: may have to be replaced by a device-tree property.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/mtd/nand/atmel_nand.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
-index cacccba..a92f603 100644
---- a/drivers/mtd/nand/atmel_nand.c
-+++ b/drivers/mtd/nand/atmel_nand.c
-@@ -127,7 +127,8 @@ static struct nand_ecclayout atmel_pmecc_oobinfo;
-
- static int cpu_has_dma(void)
- {
-- return cpu_is_at91sam9rl() || cpu_is_at91sam9g45() || cpu_is_at91sam9x5();
-+ return cpu_is_at91sam9rl() || cpu_is_at91sam9g45()
-+ || cpu_is_at91sam9x5() || cpu_is_at91sam9n12();
- }
-
- /*
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 1fe1424112c1385a4f3b89fb8944150692279ba9 Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Wed, 17 Nov 2010 12:28:13 +0100
-Subject: input: atmel_tsadcc: add support for ARCH_AT91SAM9X5
-
-XXX: split header creation in a new patch (or don't do it)
-
-Signed-off-by: Josh Wu <josh.wu@atmel.com>
----
- drivers/input/touchscreen/atmel_tsadcc.c | 150 ++++++++++++----------------
- drivers/input/touchscreen/atmel_tsadcc.h | 162 +++++++++++++++++++++++++++++++
- 2 files changed, 222 insertions(+), 90 deletions(-)
- create mode 100644 drivers/input/touchscreen/atmel_tsadcc.h
-
-diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
-index 201b2d2..a0e8d52 100644
---- a/drivers/input/touchscreen/atmel_tsadcc.c
-+++ b/drivers/input/touchscreen/atmel_tsadcc.c
-@@ -25,74 +25,9 @@
- #include <mach/board.h>
- #include <mach/cpu.h>
-
--/* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */
--
--#define ATMEL_TSADCC_CR 0x00 /* Control register */
--#define ATMEL_TSADCC_SWRST (1 << 0) /* Software Reset*/
--#define ATMEL_TSADCC_START (1 << 1) /* Start conversion */
--
--#define ATMEL_TSADCC_MR 0x04 /* Mode register */
--#define ATMEL_TSADCC_TSAMOD (3 << 0) /* ADC mode */
--#define ATMEL_TSADCC_TSAMOD_ADC_ONLY_MODE (0x0) /* ADC Mode */
--#define ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE (0x1) /* Touch Screen Only Mode */
--#define ATMEL_TSADCC_LOWRES (1 << 4) /* Resolution selection */
--#define ATMEL_TSADCC_SLEEP (1 << 5) /* Sleep mode */
--#define ATMEL_TSADCC_PENDET (1 << 6) /* Pen Detect selection */
--#define ATMEL_TSADCC_PRES (1 << 7) /* Pressure Measurement Selection */
--#define ATMEL_TSADCC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */
--#define ATMEL_TSADCC_EPRESCAL (0xff << 8) /* Prescalar Rate Selection (Extended) */
--#define ATMEL_TSADCC_STARTUP (0x7f << 16) /* Start Up time */
--#define ATMEL_TSADCC_SHTIM (0xf << 24) /* Sample & Hold time */
--#define ATMEL_TSADCC_PENDBC (0xf << 28) /* Pen Detect debouncing time */
--
--#define ATMEL_TSADCC_TRGR 0x08 /* Trigger register */
--#define ATMEL_TSADCC_TRGMOD (7 << 0) /* Trigger mode */
--#define ATMEL_TSADCC_TRGMOD_NONE (0 << 0)
--#define ATMEL_TSADCC_TRGMOD_EXT_RISING (1 << 0)
--#define ATMEL_TSADCC_TRGMOD_EXT_FALLING (2 << 0)
--#define ATMEL_TSADCC_TRGMOD_EXT_ANY (3 << 0)
--#define ATMEL_TSADCC_TRGMOD_PENDET (4 << 0)
--#define ATMEL_TSADCC_TRGMOD_PERIOD (5 << 0)
--#define ATMEL_TSADCC_TRGMOD_CONTINUOUS (6 << 0)
--#define ATMEL_TSADCC_TRGPER (0xffff << 16) /* Trigger period */
--
--#define ATMEL_TSADCC_TSR 0x0C /* Touch Screen register */
--#define ATMEL_TSADCC_TSFREQ (0xf << 0) /* TS Frequency in Interleaved mode */
--#define ATMEL_TSADCC_TSSHTIM (0xf << 24) /* Sample & Hold time */
--
--#define ATMEL_TSADCC_CHER 0x10 /* Channel Enable register */
--#define ATMEL_TSADCC_CHDR 0x14 /* Channel Disable register */
--#define ATMEL_TSADCC_CHSR 0x18 /* Channel Status register */
--#define ATMEL_TSADCC_CH(n) (1 << (n)) /* Channel number */
--
--#define ATMEL_TSADCC_SR 0x1C /* Status register */
--#define ATMEL_TSADCC_EOC(n) (1 << ((n)+0)) /* End of conversion for channel N */
--#define ATMEL_TSADCC_OVRE(n) (1 << ((n)+8)) /* Overrun error for channel N */
--#define ATMEL_TSADCC_DRDY (1 << 16) /* Data Ready */
--#define ATMEL_TSADCC_GOVRE (1 << 17) /* General Overrun Error */
--#define ATMEL_TSADCC_ENDRX (1 << 18) /* End of RX Buffer */
--#define ATMEL_TSADCC_RXBUFF (1 << 19) /* TX Buffer full */
--#define ATMEL_TSADCC_PENCNT (1 << 20) /* Pen contact */
--#define ATMEL_TSADCC_NOCNT (1 << 21) /* No contact */
--
--#define ATMEL_TSADCC_LCDR 0x20 /* Last Converted Data register */
--#define ATMEL_TSADCC_DATA (0x3ff << 0) /* Channel data */
--
--#define ATMEL_TSADCC_IER 0x24 /* Interrupt Enable register */
--#define ATMEL_TSADCC_IDR 0x28 /* Interrupt Disable register */
--#define ATMEL_TSADCC_IMR 0x2C /* Interrupt Mask register */
--#define ATMEL_TSADCC_CDR0 0x30 /* Channel Data 0 */
--#define ATMEL_TSADCC_CDR1 0x34 /* Channel Data 1 */
--#define ATMEL_TSADCC_CDR2 0x38 /* Channel Data 2 */
--#define ATMEL_TSADCC_CDR3 0x3C /* Channel Data 3 */
--#define ATMEL_TSADCC_CDR4 0x40 /* Channel Data 4 */
--#define ATMEL_TSADCC_CDR5 0x44 /* Channel Data 5 */
--
--#define ATMEL_TSADCC_XPOS 0x50
--#define ATMEL_TSADCC_Z1DAT 0x54
--#define ATMEL_TSADCC_Z2DAT 0x58
--
--#define PRESCALER_VAL(x) ((x) >> 8)
-+#include "atmel_tsadcc.h"
-+
-+#define cpu_has_9x5_adc() (cpu_is_at91sam9x5())
-
- #define ADC_DEFAULT_CLOCK 100000
-
-@@ -124,12 +59,17 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
-
- if (status & ATMEL_TSADCC_NOCNT) {
- /* Contact lost */
-- reg = atmel_tsadcc_read(ATMEL_TSADCC_MR) | ATMEL_TSADCC_PENDBC;
--
-- atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
-+ if (cpu_has_9x5_adc()) {
-+ /* 9X5 using TSMR to set PENDBC time */
-+ reg = atmel_tsadcc_read(ATMEL_TSADCC_TSMR) | ATMEL_TSADCC_PENDBC;
-+ atmel_tsadcc_write(ATMEL_TSADCC_TSMR, reg);
-+ } else {
-+ reg = atmel_tsadcc_read(ATMEL_TSADCC_MR) | ATMEL_TSADCC_PENDBC;
-+ atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
-+ }
- atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE);
- atmel_tsadcc_write(ATMEL_TSADCC_IDR,
-- ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT);
-+ ATMEL_TSADCC_CONVERSION_END | ATMEL_TSADCC_NOCNT);
- atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);
-
- input_report_key(input_dev, BTN_TOUCH, 0);
-@@ -138,23 +78,31 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
-
- } else if (status & ATMEL_TSADCC_PENCNT) {
- /* Pen detected */
-- reg = atmel_tsadcc_read(ATMEL_TSADCC_MR);
-- reg &= ~ATMEL_TSADCC_PENDBC;
-+ if (cpu_has_9x5_adc()) {
-+ reg = atmel_tsadcc_read(ATMEL_TSADCC_TSMR);
-+ reg &= ~ATMEL_TSADCC_PENDBC;
-+ atmel_tsadcc_write(ATMEL_TSADCC_TSMR, reg);
-+ } else {
-+ reg = atmel_tsadcc_read(ATMEL_TSADCC_MR);
-+ reg &= ~ATMEL_TSADCC_PENDBC;
-+ atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
-+ }
-
- atmel_tsadcc_write(ATMEL_TSADCC_IDR, ATMEL_TSADCC_PENCNT);
-- atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
- atmel_tsadcc_write(ATMEL_TSADCC_IER,
-- ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT);
-+ ATMEL_TSADCC_CONVERSION_END | ATMEL_TSADCC_NOCNT);
- atmel_tsadcc_write(ATMEL_TSADCC_TRGR,
- ATMEL_TSADCC_TRGMOD_PERIOD | (0x0FFF << 16));
-
-- } else if (status & ATMEL_TSADCC_EOC(3)) {
-+ } else if ((status & ATMEL_TSADCC_CONVERSION_END) == ATMEL_TSADCC_CONVERSION_END) {
- /* Conversion finished */
-
- if (ts_dev->bufferedmeasure) {
- /* Last measurement is always discarded, since it can
- * be erroneous.
- * Always report previous measurement */
-+ dev_dbg(&input_dev->dev, "x = %d, y = %d\n",
-+ ts_dev->prev_absx, ts_dev->prev_absy);
- input_report_abs(input_dev, ABS_X, ts_dev->prev_absx);
- input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy);
- input_report_key(input_dev, BTN_TOUCH, 1);
-@@ -163,11 +111,16 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
- ts_dev->bufferedmeasure = 1;
-
- /* Now make new measurement */
-- ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10;
-- ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2);
--
-- ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10;
-- ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0);
-+ if (cpu_has_9x5_adc()) {
-+ ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_XPOSR) & 0xffff;
-+ ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_YPOSR) & 0xffff;
-+ } else {
-+ ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10;
-+ ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2);
-+
-+ ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10;
-+ ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0);
-+ }
- }
-
- return IRQ_HANDLED;
-@@ -284,18 +237,35 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
-
- dev_info(&pdev->dev, "Prescaler is set at: %d\n", prsc);
-
-- reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE |
-- ((0x00 << 5) & ATMEL_TSADCC_SLEEP) | /* Normal Mode */
-- ((0x01 << 6) & ATMEL_TSADCC_PENDET) | /* Enable Pen Detect */
-- (prsc << 8) |
-- ((0x26 << 16) & ATMEL_TSADCC_STARTUP) |
-- ((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC);
-+ if (cpu_has_9x5_adc()) {
-+ reg = ((0x01 << 5) & ATMEL_TSADCC_SLEEP) | /* Sleep Mode */
-+ (prsc << 8) |
-+ ((0x8 << 16) & ATMEL_TSADCC_STARTUP) |
-+ ((pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TRACKTIM);
-+ } else {
-+ reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE |
-+ ((0x00 << 5) & ATMEL_TSADCC_SLEEP) | /* Normal Mode */
-+ ((0x01 << 6) & ATMEL_TSADCC_PENDET) | /* Enable Pen Detect */
-+ (prsc << 8) |
-+ ((0x26 << 16) & ATMEL_TSADCC_STARTUP) |
-+ ((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC);
-+ }
-
- atmel_tsadcc_write(ATMEL_TSADCC_CR, ATMEL_TSADCC_SWRST);
- atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
- atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE);
-- atmel_tsadcc_write(ATMEL_TSADCC_TSR,
-- (pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TSSHTIM);
-+
-+ if (cpu_has_9x5_adc()) {
-+ atmel_tsadcc_write(ATMEL_TSADCC_TSMR,
-+ ATMEL_TSADCC_TSMODE_4WIRE_NO_PRESS |
-+ ATMEL_TSADCC_NOTSDMA |
-+ ATMEL_TSADCC_PENDET_ENA |
-+ (pdata->pendet_debounce << 28) |
-+ (0x0 << 8));
-+ } else {
-+ atmel_tsadcc_write(ATMEL_TSADCC_TSR,
-+ (pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TSSHTIM);
-+ }
-
- atmel_tsadcc_read(ATMEL_TSADCC_SR);
- atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);
-diff --git a/drivers/input/touchscreen/atmel_tsadcc.h b/drivers/input/touchscreen/atmel_tsadcc.h
-new file mode 100644
-index 0000000..5918c20
---- /dev/null
-+++ b/drivers/input/touchscreen/atmel_tsadcc.h
-@@ -0,0 +1,162 @@
-+/*
-+ * Header file for AT91/AT32 ADC + touchscreen Controller
-+ *
-+ * Data structure and register user interface
-+ *
-+ * Copyright (C) 2010 Atmel Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+#ifndef __ATMEL_TSADCC_H__
-+#define __ATMEL_TSADCC_H__
-+
-+/* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */
-+#define ATMEL_TSADCC_CR 0x00 /* Control register */
-+#define ATMEL_TSADCC_SWRST (1 << 0) /* Software Reset*/
-+#define ATMEL_TSADCC_START (1 << 1) /* Start conversion */
-+
-+#define ATMEL_TSADCC_MR 0x04 /* Mode register */
-+#define ATMEL_TSADCC_TSAMOD (3 << 0) /* ADC mode */
-+#define ATMEL_TSADCC_TSAMOD_ADC_ONLY_MODE (0x0) /* ADC Mode */
-+#define ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE (0x1) /* Touch Screen Only Mode */
-+#define ATMEL_TSADCC_LOWRES (1 << 4) /* Resolution selection */
-+#define ATMEL_TSADCC_SLEEP (1 << 5) /* Sleep mode */
-+#define ATMEL_TSADCC_PENDET (1 << 6) /* Pen Detect selection */
-+#define ATMEL_TSADCC_PRES (1 << 7) /* Pressure Measurement Selection */
-+#define ATMEL_TSADCC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */
-+#define ATMEL_TSADCC_EPRESCAL (0xff << 8) /* Prescalar Rate Selection (Extended) */
-+#define ATMEL_TSADCC_STARTUP (0x7f << 16) /* Start Up time */
-+#define ATMEL_TSADCC_SHTIM (0xf << 24) /* Sample & Hold time */
-+#define ATMEL_TSADCC_PENDBC (0xf << 28) /* Pen Detect debouncing time */
-+
-+#define ATMEL_TSADCC_TRGR 0x08 /* Trigger register */
-+#define ATMEL_TSADCC_TRGMOD (7 << 0) /* Trigger mode */
-+#define ATMEL_TSADCC_TRGMOD_NONE (0 << 0)
-+#define ATMEL_TSADCC_TRGMOD_EXT_RISING (1 << 0)
-+#define ATMEL_TSADCC_TRGMOD_EXT_FALLING (2 << 0)
-+#define ATMEL_TSADCC_TRGMOD_EXT_ANY (3 << 0)
-+#define ATMEL_TSADCC_TRGMOD_PENDET (4 << 0)
-+#define ATMEL_TSADCC_TRGMOD_PERIOD (5 << 0)
-+#define ATMEL_TSADCC_TRGMOD_CONTINUOUS (6 << 0)
-+#define ATMEL_TSADCC_TRGPER (0xffff << 16) /* Trigger period */
-+
-+#define ATMEL_TSADCC_TSR 0x0C /* Touch Screen register */
-+#define ATMEL_TSADCC_TSFREQ (0xf << 0) /* TS Frequency in Interleaved mode */
-+#define ATMEL_TSADCC_TSSHTIM (0xf << 24) /* Sample & Hold time */
-+
-+#define ATMEL_TSADCC_CHER 0x10 /* Channel Enable register */
-+#define ATMEL_TSADCC_CHDR 0x14 /* Channel Disable register */
-+#define ATMEL_TSADCC_CHSR 0x18 /* Channel Status register */
-+#define ATMEL_TSADCC_CH(n) (1 << (n)) /* Channel number */
-+
-+#define ATMEL_TSADCC_SR 0x1C /* Status register */
-+#define ATMEL_TSADCC_EOC(n) (1 << ((n)+0)) /* End of conversion for channel N */
-+#define ATMEL_TSADCC_OVRE(n) (1 << ((n)+8)) /* Overrun error for channel N */
-+#define ATMEL_TSADCC_DRDY (1 << 16) /* Data Ready */
-+#define ATMEL_TSADCC_GOVRE (1 << 17) /* General Overrun Error */
-+#define ATMEL_TSADCC_ENDRX (1 << 18) /* End of RX Buffer */
-+#define ATMEL_TSADCC_RXBUFF (1 << 19) /* TX Buffer full */
-+#define ATMEL_TSADCC_PENCNT (1 << 20) /* Pen contact */
-+#define ATMEL_TSADCC_NOCNT (1 << 21) /* No contact */
-+
-+#define ATMEL_TSADCC_LCDR 0x20 /* Last Converted Data register */
-+#define ATMEL_TSADCC_DATA (0x3ff << 0) /* Channel data */
-+
-+#define ATMEL_TSADCC_IER 0x24 /* Interrupt Enable register */
-+#define ATMEL_TSADCC_IDR 0x28 /* Interrupt Disable register */
-+#define ATMEL_TSADCC_IMR 0x2C /* Interrupt Mask register */
-+#define ATMEL_TSADCC_CDR0 0x30 /* Channel Data 0 */
-+#define ATMEL_TSADCC_CDR1 0x34 /* Channel Data 1 */
-+#define ATMEL_TSADCC_CDR2 0x38 /* Channel Data 2 */
-+#define ATMEL_TSADCC_CDR3 0x3C /* Channel Data 3 */
-+#define ATMEL_TSADCC_CDR4 0x40 /* Channel Data 4 */
-+#define ATMEL_TSADCC_CDR5 0x44 /* Channel Data 5 */
-+
-+#define ATMEL_TSADCC_XPOS 0x50
-+#define ATMEL_TSADCC_Z1DAT 0x54
-+#define ATMEL_TSADCC_Z2DAT 0x58
-+
-+#define ATMEL_TSADCC_CONVERSION_END (ATMEL_TSADCC_EOC(3))
-+
-+/* Register definitions based on AT91SAM9X5 preliminary draft datasheet */
-+#define ATMEL_TSADCC_TRACKTIM (0x0f << 24) /* Tracking Time */
-+
-+#define ATMEL_TSADCC_ISR 0x30 /* Interrupt Status register */
-+#define ATMEL_TSADCC_XRDY (1 << 20) /* Measure XPOS Ready */
-+#define ATMEL_TSADCC_YRDY (1 << 21) /* Measure YPOS Ready */
-+#define ATMEL_TSADCC_PRDY (1 << 22) /* Measure Pressure Ready */
-+#define ATMEL_TSADCC_COMPE (1 << 26) /* Comparison Event */
-+#define ATMEL_TSADCC_PEN (1 << 29) /* Pen Contact */
-+#define ATMEL_TSADCC_NOPEN (1 << 30) /* No Pen Contact */
-+#define ATMEL_TSADCC_PENDET_STATUS (1 << 31) /* Pen Detect Status (not interrupt source) */
-+
-+#define ATMEL_TSADCC_TSMR 0xb0
-+#define ATMEL_TSADCC_TSMODE (3 << 0) /* Touch Screen Mode */
-+#define ATMEL_TSADCC_TSMODE_NO (0 << 0) /* No Touch Screen */
-+#define ATMEL_TSADCC_TSMODE_4WIRE_NO_PRESS (1 << 0) /* 4-wire Touch Screen without pressure measurement */
-+#define ATMEL_TSADCC_TSMODE_4WIRE_PRESS (2 << 0) /* 4-wire Touch Screen with pressure measurement */
-+#define ATMEL_TSADCC_TSMODE_5WIRE (3 << 0) /* 5-wire Touch Screen */
-+#define ATMEL_TSADCC_TSAV (3 << 4) /* Touch Screen Average */
-+#define ATMEL_TSADCC_TSAV_1 (0 << 4) /* No filtering. Only one conversion ADC per measure */
-+#define ATMEL_TSADCC_TSAV_2 (1 << 4) /* Averages 2 ADC conversions */
-+#define ATMEL_TSADCC_TSAV_4 (2 << 4) /* Averages 4 ADC conversions */
-+#define ATMEL_TSADCC_TSAV_8 (3 << 4) /* Averages 8 ADC conversions */
-+#define ATMEL_TSADCC_TSSCTIM (0x0f << 16) /* Touch Screen switches closure time */
-+
-+#define ATMEL_TSADCC_NOTSDMA (1 << 22) /* No Touchscreen DMA */
-+#define ATMEL_TSADCC_PENDET_DIS (0 << 24) /* Pen contact detection disable */
-+#define ATMEL_TSADCC_PENDET_ENA (1 << 24) /* Pen contact detection enable */
-+
-+#define ATMEL_TSADCC_XPOSR 0xb4
-+#define ATMEL_TSADCC_XSCALE (0x3ff << 16) /* Scale of X Position */
-+
-+#define ATMEL_TSADCC_YPOSR 0xb8
-+#define ATMEL_TSADCC_YPOS (0x3ff << 0) /* Y Position */
-+#define ATMEL_TSADCC_YSCALE (0x3ff << 16) /* Scale of Y Position */
-+
-+/* 9x5 ADC registers which conflict with previous definition */
-+#ifdef CONFIG_ARCH_AT91SAM9X5
-+#undef ATMEL_TSADCC_TRGR
-+#undef ATMEL_TSADCC_SR
-+#define ATMEL_TSADCC_SR ATMEL_TSADCC_ISR
-+#define ATMEL_TSADCC_TRGR 0xc0
-+
-+/* For code compatiable, redefine with 9x5 value */
-+#undef ATMEL_TSADCC_STARTUP
-+#define ATMEL_TSADCC_STARTUP (0x0f << 16) /* Startup Time */
-+#undef ATMEL_TSADCC_DRDY
-+#define ATMEL_TSADCC_DRDY (1 << 24) /* Data Ready */
-+#undef ATMEL_TSADCC_GOVRE
-+#define ATMEL_TSADCC_GOVRE (1 << 25) /* General Overrun */
-+#undef ATMEL_TSADCC_TSFREQ
-+#define ATMEL_TSADCC_TSFREQ (0x0f << 8) /* Touch Screen Frequency */
-+#undef ATMEL_TSADCC_PENDET
-+#define ATMEL_TSADCC_PENDET (1 << 24) /* Pen Contact Detection Enable */
-+#undef ATMEL_TSADCC_XPOS
-+#define ATMEL_TSADCC_XPOS (0x3ff << 0) /* X Position */
-+
-+#undef ATMEL_TSADCC_NOCNT
-+#define ATMEL_TSADCC_NOCNT ATMEL_TSADCC_NOPEN
-+#undef ATMEL_TSADCC_PENCNT
-+#define ATMEL_TSADCC_PENCNT ATMEL_TSADCC_PEN
-+#undef ATMEL_TSADCC_CONVERSION_END
-+#define ATMEL_TSADCC_CONVERSION_END (ATMEL_TSADCC_XRDY | ATMEL_TSADCC_YRDY | ATMEL_TSADCC_PRDY)
-+
-+#endif
-+
-+/* Retrieve prescaler value */
-+#define PRESCALER_VAL(x) ((x) >> 8)
-+
-+#endif /* __ATMEL_TSADCC_H__ */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2cdc659b4c98955fbd33065c56c468b494129321 Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Wed, 17 Nov 2010 13:12:11 +0100
-Subject: input: atmel_tsadcc: add touch screen pressure measurement
-
-Signed-off-by: Josh Wu <josh.wu@atmel.com>
----
- drivers/input/touchscreen/atmel_tsadcc.c | 26 +++++++++++++++++++++++---
- drivers/input/touchscreen/atmel_tsadcc.h | 4 ++++
- 2 files changed, 27 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
-index a0e8d52..b6a1630 100644
---- a/drivers/input/touchscreen/atmel_tsadcc.c
-+++ b/drivers/input/touchscreen/atmel_tsadcc.c
-@@ -38,6 +38,7 @@ struct atmel_tsadcc {
- int irq;
- unsigned int prev_absx;
- unsigned int prev_absy;
-+ unsigned int prev_absz;
- unsigned char bufferedmeasure;
- };
-
-@@ -53,6 +54,9 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
-
- unsigned int status;
- unsigned int reg;
-+ unsigned int z1, z2;
-+ unsigned int Rxp = 1;
-+ unsigned int factor = 1000;
-
- status = atmel_tsadcc_read(ATMEL_TSADCC_SR);
- status &= atmel_tsadcc_read(ATMEL_TSADCC_IMR);
-@@ -101,11 +105,15 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
- /* Last measurement is always discarded, since it can
- * be erroneous.
- * Always report previous measurement */
-- dev_dbg(&input_dev->dev, "x = %d, y = %d\n",
-- ts_dev->prev_absx, ts_dev->prev_absy);
-+ dev_dbg(&input_dev->dev,
-+ "x = %d, y = %d, pressure = %d\n",
-+ ts_dev->prev_absx, ts_dev->prev_absy,
-+ ts_dev->prev_absz);
- input_report_abs(input_dev, ABS_X, ts_dev->prev_absx);
- input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy);
- input_report_key(input_dev, BTN_TOUCH, 1);
-+ if (cpu_has_9x5_adc())
-+ input_report_abs(input_dev, ABS_PRESSURE, ts_dev->prev_absz);
- input_sync(input_dev);
- } else
- ts_dev->bufferedmeasure = 1;
-@@ -114,6 +122,17 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
- if (cpu_has_9x5_adc()) {
- ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_XPOSR) & 0xffff;
- ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_YPOSR) & 0xffff;
-+
-+ /* calculate the pressure */
-+ reg = atmel_tsadcc_read(ATMEL_TSADCC_PRESSR);
-+ z1 = reg & ATMEL_TSADCC_PRESSR_Z1;
-+ z2 = (reg & ATMEL_TSADCC_PRESSR_Z2) >> 16;
-+
-+ if (z1 != 0)
-+ ts_dev->prev_absz = Rxp * (ts_dev->prev_absx * factor / 1024) * (z2 * factor / z1 - factor) / factor;
-+ else
-+ ts_dev->prev_absz = 0;
-+
- } else {
- ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10;
- ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2);
-@@ -209,6 +228,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
- __set_bit(EV_ABS, input_dev->evbit);
- input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0);
- input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0);
-+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xffffff, 0, 0);
-
- input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
-
-@@ -257,7 +277,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
-
- if (cpu_has_9x5_adc()) {
- atmel_tsadcc_write(ATMEL_TSADCC_TSMR,
-- ATMEL_TSADCC_TSMODE_4WIRE_NO_PRESS |
-+ ATMEL_TSADCC_TSMODE_4WIRE_PRESS |
- ATMEL_TSADCC_NOTSDMA |
- ATMEL_TSADCC_PENDET_ENA |
- (pdata->pendet_debounce << 28) |
-diff --git a/drivers/input/touchscreen/atmel_tsadcc.h b/drivers/input/touchscreen/atmel_tsadcc.h
-index 5918c20..231497e 100644
---- a/drivers/input/touchscreen/atmel_tsadcc.h
-+++ b/drivers/input/touchscreen/atmel_tsadcc.h
-@@ -126,6 +126,10 @@
- #define ATMEL_TSADCC_YPOS (0x3ff << 0) /* Y Position */
- #define ATMEL_TSADCC_YSCALE (0x3ff << 16) /* Scale of Y Position */
-
-+#define ATMEL_TSADCC_PRESSR 0xbc /* Touchscreen Pressure Register */
-+#define ATMEL_TSADCC_PRESSR_Z1 (0x3ff << 0) /* Data of Z1 Measurement */
-+#define ATMEL_TSADCC_PRESSR_Z2 (0x3ff << 16) /* Data of Z2 Measurement */
-+
- /* 9x5 ADC registers which conflict with previous definition */
- #ifdef CONFIG_ARCH_AT91SAM9X5
- #undef ATMEL_TSADCC_TRGR
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 647050060bff19f002e3c0aef95410ab0915dfe1 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Tue, 5 Apr 2011 17:30:03 +0200
-Subject: input: atmel_tsadcc: enable touchscreen averaging and add fast wake
- up
-
-Enable the touchscreen average to improve the resulting events. For this
-to work the trigger period needs to be reduced.
-
-This puts a field into at91_tsadcc_data to allow platforms to specify
-the number of conversions to average over.
-
-XXX: should the trigger period passed by the platform, too, as this
-depends on the number of conversions?
-XXX: seperate fast wake up into a seperate patch? What does it?
-XXX: don't use bare constants
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- drivers/input/touchscreen/atmel_tsadcc.c | 14 ++++++++------
- drivers/input/touchscreen/atmel_tsadcc.h | 1 +
- 2 files changed, 9 insertions(+), 6 deletions(-)
-
-diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
-index b6a1630..48faecb 100644
---- a/drivers/input/touchscreen/atmel_tsadcc.c
-+++ b/drivers/input/touchscreen/atmel_tsadcc.c
-@@ -96,7 +96,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
- atmel_tsadcc_write(ATMEL_TSADCC_IER,
- ATMEL_TSADCC_CONVERSION_END | ATMEL_TSADCC_NOCNT);
- atmel_tsadcc_write(ATMEL_TSADCC_TRGR,
-- ATMEL_TSADCC_TRGMOD_PERIOD | (0x0FFF << 16));
-+ ATMEL_TSADCC_TRGMOD_PERIOD | (0x00D0 << 16));
-
- } else if ((status & ATMEL_TSADCC_CONVERSION_END) == ATMEL_TSADCC_CONVERSION_END) {
- /* Conversion finished */
-@@ -259,6 +259,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
-
- if (cpu_has_9x5_adc()) {
- reg = ((0x01 << 5) & ATMEL_TSADCC_SLEEP) | /* Sleep Mode */
-+ ((0x01 << 6) & ATMEL_TSADCC_FWUP) | /* Fast Wake Up */
- (prsc << 8) |
- ((0x8 << 16) & ATMEL_TSADCC_STARTUP) |
- ((pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TRACKTIM);
-@@ -277,11 +278,12 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
-
- if (cpu_has_9x5_adc()) {
- atmel_tsadcc_write(ATMEL_TSADCC_TSMR,
-- ATMEL_TSADCC_TSMODE_4WIRE_PRESS |
-- ATMEL_TSADCC_NOTSDMA |
-- ATMEL_TSADCC_PENDET_ENA |
-- (pdata->pendet_debounce << 28) |
-- (0x0 << 8));
-+ ATMEL_TSADCC_TSMODE_4WIRE_PRESS |
-+ (pdata->filtering_average << 4) | /* Touchscreen average */
-+ ATMEL_TSADCC_NOTSDMA |
-+ ATMEL_TSADCC_PENDET_ENA |
-+ (pdata->pendet_debounce << 28) |
-+ (0x3 << 8)); /* Touchscreen freq */
- } else {
- atmel_tsadcc_write(ATMEL_TSADCC_TSR,
- (pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TSSHTIM);
-diff --git a/drivers/input/touchscreen/atmel_tsadcc.h b/drivers/input/touchscreen/atmel_tsadcc.h
-index 231497e..572770a 100644
---- a/drivers/input/touchscreen/atmel_tsadcc.h
-+++ b/drivers/input/touchscreen/atmel_tsadcc.h
-@@ -34,6 +34,7 @@
- #define ATMEL_TSADCC_LOWRES (1 << 4) /* Resolution selection */
- #define ATMEL_TSADCC_SLEEP (1 << 5) /* Sleep mode */
- #define ATMEL_TSADCC_PENDET (1 << 6) /* Pen Detect selection */
-+#define ATMEL_TSADCC_FWUP (1 << 6) /* Fast Wake Up selection (5series) */
- #define ATMEL_TSADCC_PRES (1 << 7) /* Pressure Measurement Selection */
- #define ATMEL_TSADCC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */
- #define ATMEL_TSADCC_EPRESCAL (0xff << 8) /* Prescalar Rate Selection (Extended) */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 93e19b757f18fdf8b8a00999046b3abd4ea9b4a6 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Fri, 6 May 2011 17:54:45 +0200
-Subject: input: atmel_tsadcc: add ACR register and change trigger period value
-
-Add ACR register which allows to configure internal ADC resistor, that should
-prevent from adding resistor on display module. Furthermore increase
-trigger period which seems to be related with resistor value. A Too small
-value causes continuous irq.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- drivers/input/touchscreen/atmel_tsadcc.c | 30 +++++++++++++++++++++++++++++-
- drivers/input/touchscreen/atmel_tsadcc.h | 3 +++
- 2 files changed, 32 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
-index 48faecb..20154ba 100644
---- a/drivers/input/touchscreen/atmel_tsadcc.c
-+++ b/drivers/input/touchscreen/atmel_tsadcc.c
-@@ -47,6 +47,17 @@ static void __iomem *tsc_base;
- #define atmel_tsadcc_read(reg) __raw_readl(tsc_base + (reg))
- #define atmel_tsadcc_write(reg, val) __raw_writel((val), tsc_base + (reg))
-
-+static void atmel_tsadcc_dump_conf(struct platform_device *pdev)
-+{
-+ dev_info(&pdev->dev, "--- configuration ---\n");
-+ dev_info(&pdev->dev, "Mode Register: %#x\n", atmel_tsadcc_read(ATMEL_TSADCC_MR));
-+ dev_info(&pdev->dev, "Trigger Register: %#x\n", atmel_tsadcc_read(ATMEL_TSADCC_TRGR));
-+ dev_info(&pdev->dev, "Touchscreen Mode Register: %#x\n", atmel_tsadcc_read(ATMEL_TSADCC_TSMR));
-+ dev_info(&pdev->dev, "Analog Control Register: %#x\n", atmel_tsadcc_read(ATMEL_TSADCC_ACR));
-+ dev_info(&pdev->dev, "ADC Channel Status Register: %#x\n", atmel_tsadcc_read(ATMEL_TSADCC_CHSR));
-+ dev_info(&pdev->dev, "---------------------\n");
-+}
-+
- static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
- {
- struct atmel_tsadcc *ts_dev = (struct atmel_tsadcc *)dev;
-@@ -95,8 +106,14 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
- atmel_tsadcc_write(ATMEL_TSADCC_IDR, ATMEL_TSADCC_PENCNT);
- atmel_tsadcc_write(ATMEL_TSADCC_IER,
- ATMEL_TSADCC_CONVERSION_END | ATMEL_TSADCC_NOCNT);
-+ /* this value is related to the resistor bits value of
-+ * ACR register and R64. If internal resistor value is
-+ * increased then this value has to be increased. This
-+ * behavior seems to happen only with averaging on 8
-+ * values
-+ */
- atmel_tsadcc_write(ATMEL_TSADCC_TRGR,
-- ATMEL_TSADCC_TRGMOD_PERIOD | (0x00D0 << 16));
-+ ATMEL_TSADCC_TRGMOD_PERIOD | (0x0FF << 16));
-
- } else if ((status & ATMEL_TSADCC_CONVERSION_END) == ATMEL_TSADCC_CONVERSION_END) {
- /* Conversion finished */
-@@ -289,9 +306,20 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
- (pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TSSHTIM);
- }
-
-+ /* Change adc internal resistor value for better pen detection,
-+ * default value is 100 kOhm.
-+ * 0 = 200 kOhm, 1 = 150 kOhm, 2 = 100 kOhm, 3 = 50 kOhm
-+ * option only available on ES2 and higher
-+ */
-+ if (cpu_has_9x5_adc()) {
-+ atmel_tsadcc_write(ATMEL_TSADCC_ACR, pdata->pendet_sensitivity);
-+ }
-+
- atmel_tsadcc_read(ATMEL_TSADCC_SR);
- atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);
-
-+ /* atmel_tsadcc_dump_conf(pdev); */
-+
- /* All went ok, so register to the input system */
- err = input_register_device(input_dev);
- if (err)
-diff --git a/drivers/input/touchscreen/atmel_tsadcc.h b/drivers/input/touchscreen/atmel_tsadcc.h
-index 572770a..fe74506 100644
---- a/drivers/input/touchscreen/atmel_tsadcc.h
-+++ b/drivers/input/touchscreen/atmel_tsadcc.h
-@@ -103,6 +103,9 @@
- #define ATMEL_TSADCC_NOPEN (1 << 30) /* No Pen Contact */
- #define ATMEL_TSADCC_PENDET_STATUS (1 << 31) /* Pen Detect Status (not interrupt source) */
-
-+#define ATMEL_TSADCC_ACR 0x94 /* Analog Control Register */
-+#define ATMEL_TSADCC_PENDET_SENSITIVITY (0x3 << 0) /* ADC internal resistor */
-+
- #define ATMEL_TSADCC_TSMR 0xb0
- #define ATMEL_TSADCC_TSMODE (3 << 0) /* Touch Screen Mode */
- #define ATMEL_TSADCC_TSMODE_NO (0 << 0) /* No Touch Screen */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 385b5e2f9342fcf20ad97d4bf788e5e60635d542 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 16 Jun 2011 19:24:04 +0200
-Subject: AT91/input: atmel_tsadcc: rework irq infrastructure and parameters
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/input/touchscreen/atmel_tsadcc.c | 70 ++++++++++++++++++--------------
- 1 file changed, 40 insertions(+), 30 deletions(-)
-
-diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
-index 20154ba..397d17a 100644
---- a/drivers/input/touchscreen/atmel_tsadcc.c
-+++ b/drivers/input/touchscreen/atmel_tsadcc.c
-@@ -30,6 +30,7 @@
- #define cpu_has_9x5_adc() (cpu_is_at91sam9x5())
-
- #define ADC_DEFAULT_CLOCK 100000
-+#define ZTHRESHOLD 3200
-
- struct atmel_tsadcc {
- struct input_dev *input;
-@@ -39,7 +40,6 @@ struct atmel_tsadcc {
- unsigned int prev_absx;
- unsigned int prev_absy;
- unsigned int prev_absz;
-- unsigned char bufferedmeasure;
- };
-
- static void __iomem *tsc_base;
-@@ -62,6 +62,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
- {
- struct atmel_tsadcc *ts_dev = (struct atmel_tsadcc *)dev;
- struct input_dev *input_dev = ts_dev->input;
-+ struct at91_tsadcc_data *pdata = input_dev->dev.parent->platform_data;
-
- unsigned int status;
- unsigned int reg;
-@@ -76,7 +77,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
- /* Contact lost */
- if (cpu_has_9x5_adc()) {
- /* 9X5 using TSMR to set PENDBC time */
-- reg = atmel_tsadcc_read(ATMEL_TSADCC_TSMR) | ATMEL_TSADCC_PENDBC;
-+ reg = atmel_tsadcc_read(ATMEL_TSADCC_TSMR) | ((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC);
- atmel_tsadcc_write(ATMEL_TSADCC_TSMR, reg);
- } else {
- reg = atmel_tsadcc_read(ATMEL_TSADCC_MR) | ATMEL_TSADCC_PENDBC;
-@@ -88,7 +89,6 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
- atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);
-
- input_report_key(input_dev, BTN_TOUCH, 0);
-- ts_dev->bufferedmeasure = 0;
- input_sync(input_dev);
-
- } else if (status & ATMEL_TSADCC_PENCNT) {
-@@ -118,27 +118,20 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
- } else if ((status & ATMEL_TSADCC_CONVERSION_END) == ATMEL_TSADCC_CONVERSION_END) {
- /* Conversion finished */
-
-- if (ts_dev->bufferedmeasure) {
-- /* Last measurement is always discarded, since it can
-- * be erroneous.
-- * Always report previous measurement */
-- dev_dbg(&input_dev->dev,
-- "x = %d, y = %d, pressure = %d\n",
-- ts_dev->prev_absx, ts_dev->prev_absy,
-- ts_dev->prev_absz);
-- input_report_abs(input_dev, ABS_X, ts_dev->prev_absx);
-- input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy);
-- input_report_key(input_dev, BTN_TOUCH, 1);
-- if (cpu_has_9x5_adc())
-- input_report_abs(input_dev, ABS_PRESSURE, ts_dev->prev_absz);
-- input_sync(input_dev);
-- } else
-- ts_dev->bufferedmeasure = 1;
--
-- /* Now make new measurement */
-+ /* make new measurement */
- if (cpu_has_9x5_adc()) {
-- ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_XPOSR) & 0xffff;
-- ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_YPOSR) & 0xffff;
-+ unsigned int xscale, yscale;
-+
-+ /* calculate position */
-+ reg = atmel_tsadcc_read(ATMEL_TSADCC_XPOSR);
-+ ts_dev->prev_absx = (reg & ATMEL_TSADCC_XPOS) << 10;
-+ xscale = (reg & ATMEL_TSADCC_XSCALE) >> 16;
-+ ts_dev->prev_absx /= xscale ? xscale: 1;
-+
-+ reg = atmel_tsadcc_read(ATMEL_TSADCC_YPOSR);
-+ ts_dev->prev_absy = (reg & ATMEL_TSADCC_YPOS) << 10;
-+ yscale = (reg & ATMEL_TSADCC_YSCALE) >> 16;
-+ ts_dev->prev_absy /= yscale ? yscale: 1 << 10;
-
- /* calculate the pressure */
- reg = atmel_tsadcc_read(ATMEL_TSADCC_PRESSR);
-@@ -157,6 +150,23 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
- ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10;
- ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0);
- }
-+
-+ /* report measurement to input layer */
-+ if (ts_dev->prev_absz < ZTHRESHOLD) {
-+ dev_dbg(&input_dev->dev,
-+ "x = %d, y = %d, pressure = %d\n",
-+ ts_dev->prev_absx, ts_dev->prev_absy,
-+ ts_dev->prev_absz);
-+ input_report_abs(input_dev, ABS_X, ts_dev->prev_absx);
-+ input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy);
-+ if (cpu_has_9x5_adc())
-+ input_report_abs(input_dev, ABS_PRESSURE, ts_dev->prev_absz);
-+ input_report_key(input_dev, BTN_TOUCH, 1);
-+ input_sync(input_dev);
-+ } else {
-+ dev_dbg(&input_dev->dev,
-+ "pressure too low: not reporting\n");
-+ }
- }
-
- return IRQ_HANDLED;
-@@ -233,7 +243,6 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
- }
-
- ts_dev->input = input_dev;
-- ts_dev->bufferedmeasure = 0;
-
- snprintf(ts_dev->phys, sizeof(ts_dev->phys),
- "%s/input0", dev_name(&pdev->dev));
-@@ -275,10 +284,10 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
- dev_info(&pdev->dev, "Prescaler is set at: %d\n", prsc);
-
- if (cpu_has_9x5_adc()) {
-- reg = ((0x01 << 5) & ATMEL_TSADCC_SLEEP) | /* Sleep Mode */
-- ((0x01 << 6) & ATMEL_TSADCC_FWUP) | /* Fast Wake Up */
-+ reg = ((0x00 << 5) & ATMEL_TSADCC_SLEEP) | /* no Sleep Mode */
-+ ((0x00 << 6) & ATMEL_TSADCC_FWUP) | /* no Fast Wake Up needed */
- (prsc << 8) |
-- ((0x8 << 16) & ATMEL_TSADCC_STARTUP) |
-+ ((0x4 << 16) & ATMEL_TSADCC_STARTUP) |
- ((pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TRACKTIM);
- } else {
- reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE |
-@@ -296,10 +305,10 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
- if (cpu_has_9x5_adc()) {
- atmel_tsadcc_write(ATMEL_TSADCC_TSMR,
- ATMEL_TSADCC_TSMODE_4WIRE_PRESS |
-- (pdata->filtering_average << 4) | /* Touchscreen average */
-+ ((pdata->filtering_average << 4) & ATMEL_TSADCC_TSAV) | /* Touchscreen average */
- ATMEL_TSADCC_NOTSDMA |
- ATMEL_TSADCC_PENDET_ENA |
-- (pdata->pendet_debounce << 28) |
-+ ((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC) |
- (0x3 << 8)); /* Touchscreen freq */
- } else {
- atmel_tsadcc_write(ATMEL_TSADCC_TSR,
-@@ -312,7 +321,8 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
- * option only available on ES2 and higher
- */
- if (cpu_has_9x5_adc()) {
-- atmel_tsadcc_write(ATMEL_TSADCC_ACR, pdata->pendet_sensitivity);
-+ if (pdata->pendet_sensitivity <= ATMEL_TSADCC_PENDET_SENSITIVITY)
-+ atmel_tsadcc_write(ATMEL_TSADCC_ACR, pdata->pendet_sensitivity);
- }
-
- atmel_tsadcc_read(ATMEL_TSADCC_SR);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 08f2a486546d5837c09535727250b2c03832c063 Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Thu, 7 Jun 2012 14:19:11 +0800
-Subject: input: at91: add tsadcc_data for 9x5
-
-Signed-off-by: Josh Wu <josh.wu@atmel.com>
----
- arch/arm/mach-at91/include/mach/board.h | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
-index 369afc2..726e5f3 100644
---- a/arch/arm/mach-at91/include/mach/board.h
-+++ b/arch/arm/mach-at91/include/mach/board.h
-@@ -175,7 +175,9 @@ extern void __init at91_add_device_isi(struct isi_platform_data *data,
- /* Touchscreen Controller */
- struct at91_tsadcc_data {
- unsigned int adc_clock;
-+ u8 filtering_average;
- u8 pendet_debounce;
-+ u8 pendet_sensitivity;
- u8 ts_sample_hold_time;
- };
- extern void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 6d6f92eb0c26eabf7a8716e282252abdddebb108 Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Wed, 13 Jun 2012 17:28:40 +0800
-Subject: input: at91: add dt support for atmel touch screen adc controller.
-
-Signed-off-by: Josh Wu <josh.wu@atmel.com>
----
- drivers/input/touchscreen/atmel_tsadcc.c | 86 ++++++++++++++++++++++++++++++--
- 1 file changed, 82 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
-index 397d17a..021f87e 100644
---- a/drivers/input/touchscreen/atmel_tsadcc.c
-+++ b/drivers/input/touchscreen/atmel_tsadcc.c
-@@ -40,6 +40,8 @@ struct atmel_tsadcc {
- unsigned int prev_absx;
- unsigned int prev_absy;
- unsigned int prev_absz;
-+
-+ struct at91_tsadcc_data board;
- };
-
- static void __iomem *tsc_base;
-@@ -62,7 +64,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
- {
- struct atmel_tsadcc *ts_dev = (struct atmel_tsadcc *)dev;
- struct input_dev *input_dev = ts_dev->input;
-- struct at91_tsadcc_data *pdata = input_dev->dev.parent->platform_data;
-+ struct at91_tsadcc_data *pdata = &ts_dev->board;
-
- unsigned int status;
- unsigned int reg;
-@@ -172,6 +174,63 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
- return IRQ_HANDLED;
- }
-
-+#if defined(CONFIG_OF)
-+static int __devinit atmel_of_init_tsadcc(struct device_node *np,
-+ struct at91_tsadcc_data *pdata,
-+ struct platform_device *pdev)
-+{
-+ u32 val;
-+
-+ if (of_property_read_u32(np, "atmel,tsadcc_clock", &val) == 0)
-+ pdata->adc_clock = val;
-+
-+ if (of_property_read_u32(np, "atmel,filtering_average", &val) == 0) {
-+ if (val > 0x03) {
-+ dev_err(&pdev->dev, "invalid touch average setting, 0x%02x\n",
-+ val);
-+ return -EINVAL;
-+ }
-+ pdata->filtering_average = (u8)val;
-+ }
-+
-+ if (of_property_read_u32(np, "atmel,pendet_debounce", &val) == 0) {
-+ if (val > 0x0f) {
-+ dev_err(&pdev->dev, "invalid pen detect debounce, 0x%02x\n",
-+ val);
-+ return -EINVAL;
-+ }
-+ pdata->pendet_debounce = (u8)val;
-+ }
-+
-+ if (of_property_read_u32(np, "atmel,pendet_sensitivity", &val) == 0) {
-+ if (val > 0x03) {
-+ dev_err(&pdev->dev, "invalid pen detective sensitivity setting, 0x%02x\n",
-+ val);
-+ return -EINVAL;
-+ }
-+ pdata->pendet_sensitivity = (u8)val;
-+ }
-+
-+ if (of_property_read_u32(np, "atmel,ts_sample_hold_time", &val) == 0) {
-+ if (val > 0x0f) {
-+ dev_err(&pdev->dev, "invalid ts sample hold time, 0x%02x\n",
-+ val);
-+ return -EINVAL;
-+ }
-+ pdata->ts_sample_hold_time = (u8)val;
-+ }
-+
-+ return 0;
-+}
-+#else
-+static int __devinit atmel_of_init_tsadcc(struct device_node *np,
-+ struct at91_tsadcc_data *pdata,
-+ struct platform_device *pdev)
-+{
-+ return -EINVAL;
-+}
-+#endif
-+
- /*
- * The functions for inserting/removing us as a module.
- */
-@@ -181,7 +240,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
- struct atmel_tsadcc *ts_dev;
- struct input_dev *input_dev;
- struct resource *res;
-- struct at91_tsadcc_data *pdata = pdev->dev.platform_data;
-+ struct at91_tsadcc_data *pdata;
- int err = 0;
- unsigned int prsc;
- unsigned int reg;
-@@ -199,6 +258,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
- return -ENOMEM;
- }
- platform_set_drvdata(pdev, ts_dev);
-+ pdata = &ts_dev->board;
-
- input_dev = input_allocate_device();
- if (!input_dev) {
-@@ -264,8 +324,16 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
- prsc = clk_get_rate(ts_dev->clk);
- dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc);
-
-- if (!pdata)
-- goto err_fail;
-+ if (pdev->dev.of_node) {
-+ err = atmel_of_init_tsadcc(pdev->dev.of_node, pdata, pdev);
-+ if (err)
-+ goto err_fail;
-+ } else {
-+ if (!pdev->dev.platform_data)
-+ goto err_fail;
-+ else
-+ memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
-+ }
-
- if (!pdata->adc_clock)
- pdata->adc_clock = ADC_DEFAULT_CLOCK;
-@@ -374,11 +442,21 @@ static int __devexit atmel_tsadcc_remove(struct platform_device *pdev)
- return 0;
- }
-
-+#if defined(CONFIG_OF)
-+static const struct of_device_id atmel_tsaddcc_dt_ids[] = {
-+ { .compatible = "atmel,at91sam9x5-tsadcc"},
-+ { /* sentinel */ }
-+}
-+
-+MODULE_DEVICE_TABLE(of, atmel_tsaddcc_dt_ids);
-+#endif
-+
- static struct platform_driver atmel_tsadcc_driver = {
- .probe = atmel_tsadcc_probe,
- .remove = __devexit_p(atmel_tsadcc_remove),
- .driver = {
- .name = "atmel_tsadcc",
-+ .of_match_table = of_match_ptr(atmel_tsaddcc_dt_ids),
- },
- };
- module_platform_driver(atmel_tsadcc_driver);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From bef13f58287044dc0ab7f04707daa3344d54592d Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 6 Sep 2012 14:55:37 +0200
-Subject: net/macb: Add support for Gigabit Ethernet mode
-
-Add Gigabit Ethernet mode to GEM cadence IP and enable RGMII connection.
-
-Signed-off-by: Patrice Vilchez <patrice.vilchez@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/net/ethernet/cadence/macb.c | 15 ++++++++++++---
- drivers/net/ethernet/cadence/macb.h | 4 ++++
- 2 files changed, 16 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
-index 6100b85..e9b909a 100644
---- a/drivers/net/ethernet/cadence/macb.c
-+++ b/drivers/net/ethernet/cadence/macb.c
-@@ -152,13 +152,17 @@ static void macb_handle_link_change(struct net_device *dev)
-
- reg = macb_readl(bp, NCFGR);
- reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
-+ if (macb_is_gem(bp))
-+ reg &= ~GEM_BIT(GBE);
-
- if (phydev->duplex)
- reg |= MACB_BIT(FD);
- if (phydev->speed == SPEED_100)
- reg |= MACB_BIT(SPD);
-+ if (phydev->speed == SPEED_1000)
-+ reg |= GEM_BIT(GBE);
-
-- macb_writel(bp, NCFGR, reg);
-+ macb_or_gem_writel(bp, NCFGR, reg);
-
- bp->speed = phydev->speed;
- bp->duplex = phydev->duplex;
-@@ -216,7 +220,10 @@ static int macb_mii_probe(struct net_device *dev)
- }
-
- /* mask with MAC supported features */
-- phydev->supported &= PHY_BASIC_FEATURES;
-+ if (macb_is_gem(bp))
-+ phydev->supported &= PHY_GBIT_FEATURES;
-+ else
-+ phydev->supported &= PHY_BASIC_FEATURES;
-
- phydev->advertising = phydev->supported;
-
-@@ -1383,7 +1390,9 @@ static int __init macb_probe(struct platform_device *pdev)
- bp->phy_interface = err;
- }
-
-- if (bp->phy_interface == PHY_INTERFACE_MODE_RMII)
-+ if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII)
-+ macb_or_gem_writel(bp, USRIO, GEM_BIT(RGMII));
-+ else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII)
- #if defined(CONFIG_ARCH_AT91)
- macb_or_gem_writel(bp, USRIO, (MACB_BIT(RMII) |
- MACB_BIT(CLKEN)));
-diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
-index 335e288..f69ceef 100644
---- a/drivers/net/ethernet/cadence/macb.h
-+++ b/drivers/net/ethernet/cadence/macb.h
-@@ -145,6 +145,8 @@
- #define MACB_IRXFCS_SIZE 1
-
- /* GEM specific NCFGR bitfields. */
-+#define GEM_GBE_OFFSET 10
-+#define GEM_GBE_SIZE 1
- #define GEM_CLK_OFFSET 18
- #define GEM_CLK_SIZE 3
- #define GEM_DBW_OFFSET 21
-@@ -246,6 +248,8 @@
- /* Bitfields in USRIO (AT91) */
- #define MACB_RMII_OFFSET 0
- #define MACB_RMII_SIZE 1
-+#define GEM_RGMII_OFFSET 0 /* GEM gigabit mode */
-+#define GEM_RGMII_SIZE 1
- #define MACB_CLKEN_OFFSET 1
- #define MACB_CLKEN_SIZE 1
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ae87461f10e59a207038af4df8944fabc8c9ac55 Mon Sep 17 00:00:00 2001
-From: Havard Skinnemoen <havard@skinnemoen.net>
-Date: Fri, 28 May 2010 17:13:33 +0200
-Subject: net/macb: memory barriers cleanup
-
-Remove a couple of unneeded barriers and document the remaining ones.
-
-Signed-off-by: Havard Skinnemoen <havard@skinnemoen.net>
-[nicolas.ferre@atmel.com: split patch in topics]
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/net/ethernet/cadence/macb.c | 18 ++++++++++++++----
- 1 file changed, 14 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
-index e9b909a..a4dcd11 100644
---- a/drivers/net/ethernet/cadence/macb.c
-+++ b/drivers/net/ethernet/cadence/macb.c
-@@ -372,7 +372,9 @@ static void macb_tx(struct macb *bp)
-
- BUG_ON(skb == NULL);
-
-+ /* Make hw descriptor updates visible to CPU */
- rmb();
-+
- bufstat = bp->tx_ring[tail].ctrl;
-
- if (!(bufstat & MACB_BIT(TX_USED)))
-@@ -415,7 +417,10 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
- if (frag == last_frag)
- break;
- }
-+
-+ /* Make descriptor updates visible to hardware */
- wmb();
-+
- return 1;
- }
-
-@@ -436,12 +441,14 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
- frag_len);
- offset += RX_BUFFER_SIZE;
- bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
-- wmb();
-
- if (frag == last_frag)
- break;
- }
-
-+ /* Make descriptor updates visible to hardware */
-+ wmb();
-+
- skb->protocol = eth_type_trans(skb, bp->dev);
-
- bp->stats.rx_packets++;
-@@ -461,6 +468,8 @@ static void discard_partial_frame(struct macb *bp, unsigned int begin,
-
- for (frag = begin; frag != end; frag = NEXT_RX(frag))
- bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
-+
-+ /* Make descriptor updates visible to hardware */
- wmb();
-
- /*
-@@ -479,7 +488,9 @@ static int macb_rx(struct macb *bp, int budget)
- for (; budget > 0; tail = NEXT_RX(tail)) {
- u32 addr, ctrl;
-
-+ /* Make hw descriptor updates visible to CPU */
- rmb();
-+
- addr = bp->rx_ring[tail].addr;
- ctrl = bp->rx_ring[tail].ctrl;
-
-@@ -674,6 +685,8 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
-
- bp->tx_ring[entry].addr = mapping;
- bp->tx_ring[entry].ctrl = ctrl;
-+
-+ /* Make newly initialized descriptor visible to hardware */
- wmb();
-
- entry = NEXT_TX(entry);
-@@ -782,9 +795,6 @@ static void macb_init_rings(struct macb *bp)
-
- static void macb_reset_hw(struct macb *bp)
- {
-- /* Make sure we have the write buffer for ourselves */
-- wmb();
--
- /*
- * Disable RX and TX (XXX: Should we halt the transmission
- * more gracefully?)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 60a3639d4642fc21195f51f4875c07d7418c5097 Mon Sep 17 00:00:00 2001
-From: Havard Skinnemoen <havard@skinnemoen.net>
-Date: Fri, 28 May 2010 17:45:43 +0200
-Subject: net/macb: change debugging messages
-
-Convert some noisy netdev_dbg() statements to netdev_vdbg(). Defining
-DEBUG will no longer fill up the logs; VERBOSE_DEBUG still does.
-Add one more verbose debug for ISR status.
-
-Signed-off-by: Havard Skinnemoen <havard@skinnemoen.net>
-[nicolas.ferre@atmel.com: split patch in topics, add ISR status]
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/net/ethernet/cadence/macb.c | 22 ++++++++++++----------
- 1 file changed, 12 insertions(+), 10 deletions(-)
-
-diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
-index a4dcd11..ce1f558 100644
---- a/drivers/net/ethernet/cadence/macb.c
-+++ b/drivers/net/ethernet/cadence/macb.c
-@@ -313,7 +313,7 @@ static void macb_tx(struct macb *bp)
- status = macb_readl(bp, TSR);
- macb_writel(bp, TSR, status);
-
-- netdev_dbg(bp->dev, "macb_tx status = %02lx\n", (unsigned long)status);
-+ netdev_vdbg(bp->dev, "macb_tx status = %02lx\n", (unsigned long)status);
-
- if (status & (MACB_BIT(UND) | MACB_BIT(TSR_RLE))) {
- int i;
-@@ -380,7 +380,7 @@ static void macb_tx(struct macb *bp)
- if (!(bufstat & MACB_BIT(TX_USED)))
- break;
-
-- netdev_dbg(bp->dev, "skb %u (data %p) TX complete\n",
-+ netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
- tail, skb->data);
- dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len,
- DMA_TO_DEVICE);
-@@ -406,7 +406,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
-
- len = MACB_BFEXT(RX_FRMLEN, bp->rx_ring[last_frag].ctrl);
-
-- netdev_dbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
-+ netdev_vdbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
- first_frag, last_frag, len);
-
- skb = netdev_alloc_skb(bp->dev, len + RX_OFFSET);
-@@ -453,7 +453,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
-
- bp->stats.rx_packets++;
- bp->stats.rx_bytes += len;
-- netdev_dbg(bp->dev, "received skb of length %u, csum: %08x\n",
-+ netdev_vdbg(bp->dev, "received skb of length %u, csum: %08x\n",
- skb->len, skb->csum);
- netif_receive_skb(skb);
-
-@@ -535,7 +535,7 @@ static int macb_poll(struct napi_struct *napi, int budget)
-
- work_done = 0;
-
-- netdev_dbg(bp->dev, "poll: status = %08lx, budget = %d\n",
-+ netdev_vdbg(bp->dev, "poll: status = %08lx, budget = %d\n",
- (unsigned long)status, budget);
-
- work_done = macb_rx(bp, budget);
-@@ -574,6 +574,8 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
- break;
- }
-
-+ netdev_vdbg(bp->dev, "isr = 0x%08lx\n", (unsigned long)status);
-+
- if (status & MACB_RX_INT_FLAGS) {
- /*
- * There's no point taking any more interrupts
-@@ -585,7 +587,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
- macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
-
- if (napi_schedule_prep(&bp->napi)) {
-- netdev_dbg(bp->dev, "scheduling RX softirq\n");
-+ netdev_vdbg(bp->dev, "scheduling RX softirq\n");
- __napi_schedule(&bp->napi);
- }
- }
-@@ -647,8 +649,8 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
- u32 ctrl;
- unsigned long flags;
-
--#ifdef DEBUG
-- netdev_dbg(bp->dev,
-+#if defined(DEBUG) && defined(VERBOSE_DEBUG)
-+ netdev_vdbg(bp->dev,
- "start_xmit: len %u head %p data %p tail %p end %p\n",
- skb->len, skb->head, skb->data,
- skb_tail_pointer(skb), skb_end_pointer(skb));
-@@ -670,12 +672,12 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
- }
-
- entry = bp->tx_head;
-- netdev_dbg(bp->dev, "Allocated ring entry %u\n", entry);
-+ netdev_vdbg(bp->dev, "Allocated ring entry %u\n", entry);
- mapping = dma_map_single(&bp->pdev->dev, skb->data,
- len, DMA_TO_DEVICE);
- bp->tx_skb[entry].skb = skb;
- bp->tx_skb[entry].mapping = mapping;
-- netdev_dbg(bp->dev, "Mapped skb data %p to DMA addr %08lx\n",
-+ netdev_vdbg(bp->dev, "Mapped skb data %p to DMA addr %08lx\n",
- skb->data, (unsigned long)mapping);
-
- ctrl = MACB_BF(TX_FRMLEN, len);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From d34b7418567147f5a2ea6a890328c41f3743b862 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 6 Sep 2012 15:23:47 +0200
-Subject: net/macb: remove macb_get_drvinfo()
-
-This function has little meaning so remove it altogether and
-let ethtool core fill in the fields automatically.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/net/ethernet/cadence/macb.c | 11 -----------
- 1 file changed, 11 deletions(-)
-
-diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
-index ce1f558..dc34ff1 100644
---- a/drivers/net/ethernet/cadence/macb.c
-+++ b/drivers/net/ethernet/cadence/macb.c
-@@ -1223,20 +1223,9 @@ static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
- return phy_ethtool_sset(phydev, cmd);
- }
-
--static void macb_get_drvinfo(struct net_device *dev,
-- struct ethtool_drvinfo *info)
--{
-- struct macb *bp = netdev_priv(dev);
--
-- strcpy(info->driver, bp->pdev->dev.driver->name);
-- strcpy(info->version, "$Revision: 1.14 $");
-- strcpy(info->bus_info, dev_name(&bp->pdev->dev));
--}
--
- static const struct ethtool_ops macb_ethtool_ops = {
- .get_settings = macb_get_settings,
- .set_settings = macb_set_settings,
-- .get_drvinfo = macb_get_drvinfo,
- .get_link = ethtool_op_get_link,
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From dab3e98e23315687f3aa67714b003f5ff96e3df2 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 3 Sep 2012 17:52:09 +0200
-Subject: net/macb: tx status is more than 8 bits now
-
-On some revision of GEM, TSR status register has more information.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/net/ethernet/cadence/macb.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
-index dc34ff1..4e05a29 100644
---- a/drivers/net/ethernet/cadence/macb.c
-+++ b/drivers/net/ethernet/cadence/macb.c
-@@ -313,7 +313,7 @@ static void macb_tx(struct macb *bp)
- status = macb_readl(bp, TSR);
- macb_writel(bp, TSR, status);
-
-- netdev_vdbg(bp->dev, "macb_tx status = %02lx\n", (unsigned long)status);
-+ netdev_vdbg(bp->dev, "macb_tx status = 0x%03lx\n", (unsigned long)status);
-
- if (status & (MACB_BIT(UND) | MACB_BIT(TSR_RLE))) {
- int i;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From f7d00d86af150d53a98b12fb609ac0b98d6044f6 Mon Sep 17 00:00:00 2001
-From: Havard Skinnemoen <havard@skinnemoen.net>
-Date: Mon, 21 Jun 2010 18:56:29 +0200
-Subject: net/macb: clean up ring buffer logic
-
-Instead of masking head and tail every time we increment them, just let them
-wrap through UINT_MAX and mask them when subscripting. Add simple accessor
-functions to do the subscripting properly to minimize the chances of messing
-this up.
-
-This makes the code slightly smaller, and hopefully faster as well. Also,
-doing the ring buffer management this way will simplify things a lot when
-making the ring sizes configurable in the future.
-
-Signed-off-by: Havard Skinnemoen <havard@skinnemoen.net>
-[nicolas.ferre@atmel.com: split patch in topics, adapt to newer kernel]
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/net/ethernet/cadence/macb.c | 168 +++++++++++++++++++++++-------------
- drivers/net/ethernet/cadence/macb.h | 22 +++--
- 2 files changed, 122 insertions(+), 68 deletions(-)
-
-diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
-index 4e05a29..2554354 100644
---- a/drivers/net/ethernet/cadence/macb.c
-+++ b/drivers/net/ethernet/cadence/macb.c
-@@ -31,24 +31,13 @@
-
- #define RX_BUFFER_SIZE 128
- #define RX_RING_SIZE 512
--#define RX_RING_BYTES (sizeof(struct dma_desc) * RX_RING_SIZE)
-+#define RX_RING_BYTES (sizeof(struct macb_dma_desc) * RX_RING_SIZE)
-
- /* Make the IP header word-aligned (the ethernet header is 14 bytes) */
- #define RX_OFFSET 2
-
- #define TX_RING_SIZE 128
--#define DEF_TX_RING_PENDING (TX_RING_SIZE - 1)
--#define TX_RING_BYTES (sizeof(struct dma_desc) * TX_RING_SIZE)
--
--#define TX_RING_GAP(bp) \
-- (TX_RING_SIZE - (bp)->tx_pending)
--#define TX_BUFFS_AVAIL(bp) \
-- (((bp)->tx_tail <= (bp)->tx_head) ? \
-- (bp)->tx_tail + (bp)->tx_pending - (bp)->tx_head : \
-- (bp)->tx_tail - (bp)->tx_head - TX_RING_GAP(bp))
--#define NEXT_TX(n) (((n) + 1) & (TX_RING_SIZE - 1))
--
--#define NEXT_RX(n) (((n) + 1) & (RX_RING_SIZE - 1))
-+#define TX_RING_BYTES (sizeof(struct macb_dma_desc) * TX_RING_SIZE)
-
- /* minimum number of free TX descriptors before waking up TX process */
- #define MACB_TX_WAKEUP_THRESH (TX_RING_SIZE / 4)
-@@ -56,6 +45,51 @@
- #define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \
- | MACB_BIT(ISR_ROVR))
-
-+/* Ring buffer accessors */
-+static unsigned int macb_tx_ring_wrap(unsigned int index)
-+{
-+ return index & (TX_RING_SIZE - 1);
-+}
-+
-+static unsigned int macb_tx_ring_avail(struct macb *bp)
-+{
-+ return TX_RING_SIZE - (bp->tx_head - bp->tx_tail);
-+}
-+
-+static struct macb_dma_desc *macb_tx_desc(struct macb *bp, unsigned int index)
-+{
-+ return &bp->tx_ring[macb_tx_ring_wrap(index)];
-+}
-+
-+static struct macb_tx_skb *macb_tx_skb(struct macb *bp, unsigned int index)
-+{
-+ return &bp->tx_skb[macb_tx_ring_wrap(index)];
-+}
-+
-+static dma_addr_t macb_tx_dma(struct macb *bp, unsigned int index)
-+{
-+ dma_addr_t offset;
-+
-+ offset = macb_tx_ring_wrap(index) * sizeof(struct macb_dma_desc);
-+
-+ return bp->tx_ring_dma + offset;
-+}
-+
-+static unsigned int macb_rx_ring_wrap(unsigned int index)
-+{
-+ return index & (RX_RING_SIZE - 1);
-+}
-+
-+static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
-+{
-+ return &bp->rx_ring[macb_rx_ring_wrap(index)];
-+}
-+
-+static void *macb_rx_buffer(struct macb *bp, unsigned int index)
-+{
-+ return bp->rx_buffers + RX_BUFFER_SIZE * macb_rx_ring_wrap(index);
-+}
-+
- static void __macb_set_hwaddr(struct macb *bp)
- {
- u32 bottom;
-@@ -335,17 +369,18 @@ static void macb_tx(struct macb *bp)
- bp->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
-
- /* free transmit buffer in upper layer*/
-- for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) {
-- struct ring_info *rp = &bp->tx_skb[tail];
-- struct sk_buff *skb = rp->skb;
--
-- BUG_ON(skb == NULL);
-+ for (tail = bp->tx_tail; tail != head; tail++) {
-+ struct macb_tx_skb *tx_skb;
-+ struct sk_buff *skb;
-
- rmb();
-
-- dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len,
-- DMA_TO_DEVICE);
-- rp->skb = NULL;
-+ tx_skb = macb_tx_skb(bp, tail);
-+ skb = tx_skb->skb;
-+
-+ dma_unmap_single(&bp->pdev->dev, tx_skb->mapping,
-+ skb->len, DMA_TO_DEVICE);
-+ tx_skb->skb = NULL;
- dev_kfree_skb_irq(skb);
- }
-
-@@ -365,34 +400,38 @@ static void macb_tx(struct macb *bp)
- return;
-
- head = bp->tx_head;
-- for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) {
-- struct ring_info *rp = &bp->tx_skb[tail];
-- struct sk_buff *skb = rp->skb;
-- u32 bufstat;
-+ for (tail = bp->tx_tail; tail != head; tail++) {
-+ struct macb_tx_skb *tx_skb;
-+ struct sk_buff *skb;
-+ struct macb_dma_desc *desc;
-+ u32 ctrl;
-
-- BUG_ON(skb == NULL);
-+ desc = macb_tx_desc(bp, tail);
-
- /* Make hw descriptor updates visible to CPU */
- rmb();
-
-- bufstat = bp->tx_ring[tail].ctrl;
-+ ctrl = desc->ctrl;
-
-- if (!(bufstat & MACB_BIT(TX_USED)))
-+ if (!(ctrl & MACB_BIT(TX_USED)))
- break;
-
-+ tx_skb = macb_tx_skb(bp, tail);
-+ skb = tx_skb->skb;
-+
- netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
-- tail, skb->data);
-- dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len,
-+ macb_tx_ring_wrap(tail), skb->data);
-+ dma_unmap_single(&bp->pdev->dev, tx_skb->mapping, skb->len,
- DMA_TO_DEVICE);
- bp->stats.tx_packets++;
- bp->stats.tx_bytes += skb->len;
-- rp->skb = NULL;
-+ tx_skb->skb = NULL;
- dev_kfree_skb_irq(skb);
- }
-
- bp->tx_tail = tail;
-- if (netif_queue_stopped(bp->dev) &&
-- TX_BUFFS_AVAIL(bp) > MACB_TX_WAKEUP_THRESH)
-+ if (netif_queue_stopped(bp->dev)
-+ && macb_tx_ring_avail(bp) > MACB_TX_WAKEUP_THRESH)
- netif_wake_queue(bp->dev);
- }
-
-@@ -403,17 +442,21 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
- unsigned int frag;
- unsigned int offset = 0;
- struct sk_buff *skb;
-+ struct macb_dma_desc *desc;
-
-- len = MACB_BFEXT(RX_FRMLEN, bp->rx_ring[last_frag].ctrl);
-+ desc = macb_rx_desc(bp, last_frag);
-+ len = MACB_BFEXT(RX_FRMLEN, desc->ctrl);
-
- netdev_vdbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
-- first_frag, last_frag, len);
-+ macb_rx_ring_wrap(first_frag),
-+ macb_rx_ring_wrap(last_frag), len);
-
- skb = netdev_alloc_skb(bp->dev, len + RX_OFFSET);
- if (!skb) {
- bp->stats.rx_dropped++;
-- for (frag = first_frag; ; frag = NEXT_RX(frag)) {
-- bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
-+ for (frag = first_frag; ; frag++) {
-+ desc = macb_rx_desc(bp, frag);
-+ desc->addr &= ~MACB_BIT(RX_USED);
- if (frag == last_frag)
- break;
- }
-@@ -428,7 +471,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
- skb_checksum_none_assert(skb);
- skb_put(skb, len);
-
-- for (frag = first_frag; ; frag = NEXT_RX(frag)) {
-+ for (frag = first_frag; ; frag++) {
- unsigned int frag_len = RX_BUFFER_SIZE;
-
- if (offset + frag_len > len) {
-@@ -436,11 +479,10 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
- frag_len = len - offset;
- }
- skb_copy_to_linear_data_offset(skb, offset,
-- (bp->rx_buffers +
-- (RX_BUFFER_SIZE * frag)),
-- frag_len);
-+ macb_rx_buffer(bp, frag), frag_len);
- offset += RX_BUFFER_SIZE;
-- bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
-+ desc = macb_rx_desc(bp, frag);
-+ desc->addr &= ~MACB_BIT(RX_USED);
-
- if (frag == last_frag)
- break;
-@@ -466,8 +508,10 @@ static void discard_partial_frame(struct macb *bp, unsigned int begin,
- {
- unsigned int frag;
-
-- for (frag = begin; frag != end; frag = NEXT_RX(frag))
-- bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
-+ for (frag = begin; frag != end; frag++) {
-+ struct macb_dma_desc *desc = macb_rx_desc(bp, frag);
-+ desc->addr &= ~MACB_BIT(RX_USED);
-+ }
-
- /* Make descriptor updates visible to hardware */
- wmb();
-@@ -482,17 +526,18 @@ static void discard_partial_frame(struct macb *bp, unsigned int begin,
- static int macb_rx(struct macb *bp, int budget)
- {
- int received = 0;
-- unsigned int tail = bp->rx_tail;
-+ unsigned int tail;
- int first_frag = -1;
-
-- for (; budget > 0; tail = NEXT_RX(tail)) {
-+ for (tail = bp->rx_tail; budget > 0; tail++) {
-+ struct macb_dma_desc *desc = macb_rx_desc(bp, tail);
- u32 addr, ctrl;
-
- /* Make hw descriptor updates visible to CPU */
- rmb();
-
-- addr = bp->rx_ring[tail].addr;
-- ctrl = bp->rx_ring[tail].ctrl;
-+ addr = desc->addr;
-+ ctrl = desc->ctrl;
-
- if (!(addr & MACB_BIT(RX_USED)))
- break;
-@@ -646,6 +691,8 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
- struct macb *bp = netdev_priv(dev);
- dma_addr_t mapping;
- unsigned int len, entry;
-+ struct macb_dma_desc *desc;
-+ struct macb_tx_skb *tx_skb;
- u32 ctrl;
- unsigned long flags;
-
-@@ -662,7 +709,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
- spin_lock_irqsave(&bp->lock, flags);
-
- /* This is a hard error, log it. */
-- if (TX_BUFFS_AVAIL(bp) < 1) {
-+ if (macb_tx_ring_avail(bp) < 1) {
- netif_stop_queue(dev);
- spin_unlock_irqrestore(&bp->lock, flags);
- netdev_err(bp->dev, "BUG! Tx Ring full when queue awake!\n");
-@@ -671,12 +718,15 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
- return NETDEV_TX_BUSY;
- }
-
-- entry = bp->tx_head;
-+ entry = macb_tx_ring_wrap(bp->tx_head);
-+ bp->tx_head++;
- netdev_vdbg(bp->dev, "Allocated ring entry %u\n", entry);
- mapping = dma_map_single(&bp->pdev->dev, skb->data,
- len, DMA_TO_DEVICE);
-- bp->tx_skb[entry].skb = skb;
-- bp->tx_skb[entry].mapping = mapping;
-+
-+ tx_skb = &bp->tx_skb[entry];
-+ tx_skb->skb = skb;
-+ tx_skb->mapping = mapping;
- netdev_vdbg(bp->dev, "Mapped skb data %p to DMA addr %08lx\n",
- skb->data, (unsigned long)mapping);
-
-@@ -685,20 +735,18 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
- if (entry == (TX_RING_SIZE - 1))
- ctrl |= MACB_BIT(TX_WRAP);
-
-- bp->tx_ring[entry].addr = mapping;
-- bp->tx_ring[entry].ctrl = ctrl;
-+ desc = &bp->tx_ring[entry];
-+ desc->addr = mapping;
-+ desc->ctrl = ctrl;
-
- /* Make newly initialized descriptor visible to hardware */
- wmb();
-
-- entry = NEXT_TX(entry);
-- bp->tx_head = entry;
--
- skb_tx_timestamp(skb);
-
- macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
-
-- if (TX_BUFFS_AVAIL(bp) < 1)
-+ if (macb_tx_ring_avail(bp) < 1)
- netif_stop_queue(dev);
-
- spin_unlock_irqrestore(&bp->lock, flags);
-@@ -734,7 +782,7 @@ static int macb_alloc_consistent(struct macb *bp)
- {
- int size;
-
-- size = TX_RING_SIZE * sizeof(struct ring_info);
-+ size = TX_RING_SIZE * sizeof(struct macb_tx_skb);
- bp->tx_skb = kmalloc(size, GFP_KERNEL);
- if (!bp->tx_skb)
- goto out_err;
-@@ -1407,8 +1455,6 @@ static int __init macb_probe(struct platform_device *pdev)
- macb_or_gem_writel(bp, USRIO, MACB_BIT(MII));
- #endif
-
-- bp->tx_pending = DEF_TX_RING_PENDING;
--
- err = register_netdev(dev);
- if (err) {
- dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
-diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
-index f69ceef..8a4ee2f 100644
---- a/drivers/net/ethernet/cadence/macb.h
-+++ b/drivers/net/ethernet/cadence/macb.h
-@@ -356,7 +356,12 @@
- __v; \
- })
-
--struct dma_desc {
-+/**
-+ * struct macb_dma_desc - Hardware DMA descriptor
-+ * @addr: DMA address of data buffer
-+ * @ctrl: Control and status bits
-+ */
-+struct macb_dma_desc {
- u32 addr;
- u32 ctrl;
- };
-@@ -421,7 +426,12 @@ struct dma_desc {
- #define MACB_TX_USED_OFFSET 31
- #define MACB_TX_USED_SIZE 1
-
--struct ring_info {
-+/**
-+ * struct macb_tx_skb - data about an skb which is being transmitted
-+ * @skb: skb currently being transmitted
-+ * @mapping: DMA address of the skb's data buffer
-+ */
-+struct macb_tx_skb {
- struct sk_buff *skb;
- dma_addr_t mapping;
- };
-@@ -506,12 +516,12 @@ struct macb {
- void __iomem *regs;
-
- unsigned int rx_tail;
-- struct dma_desc *rx_ring;
-+ struct macb_dma_desc *rx_ring;
- void *rx_buffers;
-
- unsigned int tx_head, tx_tail;
-- struct dma_desc *tx_ring;
-- struct ring_info *tx_skb;
-+ struct macb_dma_desc *tx_ring;
-+ struct macb_tx_skb *tx_skb;
-
- spinlock_t lock;
- struct platform_device *pdev;
-@@ -529,8 +539,6 @@ struct macb {
- dma_addr_t tx_ring_dma;
- dma_addr_t rx_buffers_dma;
-
-- unsigned int rx_pending, tx_pending;
--
- struct mii_bus *mii_bus;
- struct phy_device *phy_dev;
- unsigned int link;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 69edea954864a5d0aeed3be5171ac62889442043 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 3 Sep 2012 17:56:18 +0200
-Subject: net/macb: ethtool interface: add register dump feature
-
-Add macb_get_regs() ethtool function and its helper function:
-macb_get_regs_len().
-The version field is deduced from the IP revision which gives the
-"MACB or GEM" information. An additional version field is reserved.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Reviewed-by: Ben Hutchings <bhutchings@solarflare.com>
----
- drivers/net/ethernet/cadence/macb.c | 40 +++++++++++++++++++++++++++++++++++++
- drivers/net/ethernet/cadence/macb.h | 3 +++
- 2 files changed, 43 insertions(+)
-
-diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
-index 2554354..6486a56 100644
---- a/drivers/net/ethernet/cadence/macb.c
-+++ b/drivers/net/ethernet/cadence/macb.c
-@@ -1271,9 +1271,49 @@ static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
- return phy_ethtool_sset(phydev, cmd);
- }
-
-+static int macb_get_regs_len(struct net_device *netdev)
-+{
-+ return MACB_GREGS_NBR * sizeof(u32);
-+}
-+
-+static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs,
-+ void *p)
-+{
-+ struct macb *bp = netdev_priv(dev);
-+ unsigned int tail, head;
-+ u32 *regs_buff = p;
-+
-+ regs->version = (macb_readl(bp, MID) & ((1 << MACB_REV_SIZE) - 1))
-+ | MACB_GREGS_VERSION;
-+
-+ tail = macb_tx_ring_wrap(bp->tx_tail);
-+ head = macb_tx_ring_wrap(bp->tx_head);
-+
-+ regs_buff[0] = macb_readl(bp, NCR);
-+ regs_buff[1] = macb_or_gem_readl(bp, NCFGR);
-+ regs_buff[2] = macb_readl(bp, NSR);
-+ regs_buff[3] = macb_readl(bp, TSR);
-+ regs_buff[4] = macb_readl(bp, RBQP);
-+ regs_buff[5] = macb_readl(bp, TBQP);
-+ regs_buff[6] = macb_readl(bp, RSR);
-+ regs_buff[7] = macb_readl(bp, IMR);
-+
-+ regs_buff[8] = tail;
-+ regs_buff[9] = head;
-+ regs_buff[10] = macb_tx_dma(bp, tail);
-+ regs_buff[11] = macb_tx_dma(bp, head);
-+
-+ if (macb_is_gem(bp)) {
-+ regs_buff[12] = gem_readl(bp, USRIO);
-+ regs_buff[13] = gem_readl(bp, DMACFG);
-+ }
-+}
-+
- static const struct ethtool_ops macb_ethtool_ops = {
- .get_settings = macb_get_settings,
- .set_settings = macb_set_settings,
-+ .get_regs_len = macb_get_regs_len,
-+ .get_regs = macb_get_regs,
- .get_link = ethtool_op_get_link,
- };
-
-diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
-index 8a4ee2f..5be5900 100644
---- a/drivers/net/ethernet/cadence/macb.h
-+++ b/drivers/net/ethernet/cadence/macb.h
-@@ -10,6 +10,9 @@
- #ifndef _MACB_H
- #define _MACB_H
-
-+#define MACB_GREGS_NBR 16
-+#define MACB_GREGS_VERSION 1
-+
- /* MACB register offsets */
- #define MACB_NCR 0x0000
- #define MACB_NCFGR 0x0004
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2d0de9104b7a27b8423f7a44c4fa45dc3508f25a Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 22 Jun 2010 18:38:26 +0200
-Subject: net/macb: better manage tx errors
-
-Handle all TX errors, not only underruns. TX error management is
-deferred to a dedicated workqueue.
-Reinitialize the TX ring after treating all remaining frames, and
-restart the controller when everything has been cleaned up properly.
-Napi is not stopped during this task as the driver only handles
-napi for RX for now.
-With this sequence, we do not need a special check during the xmit
-method as the packets will be caught by TX disable during workqueue
-execution.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/net/ethernet/cadence/macb.c | 166 ++++++++++++++++++++++++------------
- drivers/net/ethernet/cadence/macb.h | 1 +
- 2 files changed, 113 insertions(+), 54 deletions(-)
-
-diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
-index 6486a56..cd24ce6 100644
---- a/drivers/net/ethernet/cadence/macb.c
-+++ b/drivers/net/ethernet/cadence/macb.c
-@@ -44,6 +44,16 @@
-
- #define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \
- | MACB_BIT(ISR_ROVR))
-+#define MACB_TX_ERR_FLAGS (MACB_BIT(ISR_TUND) \
-+ | MACB_BIT(ISR_RLE) \
-+ | MACB_BIT(TXERR))
-+#define MACB_TX_INT_FLAGS (MACB_TX_ERR_FLAGS | MACB_BIT(TCOMP))
-+
-+/*
-+ * Graceful stop timeouts in us. We should allow up to
-+ * 1 frame time (10 Mbits/s, full-duplex, ignoring collisions)
-+ */
-+#define MACB_HALT_TIMEOUT 1230
-
- /* Ring buffer accessors */
- static unsigned int macb_tx_ring_wrap(unsigned int index)
-@@ -338,66 +348,113 @@ static void macb_update_stats(struct macb *bp)
- *p += __raw_readl(reg);
- }
-
--static void macb_tx(struct macb *bp)
-+static int macb_halt_tx(struct macb *bp)
- {
-- unsigned int tail;
-- unsigned int head;
-- u32 status;
-+ unsigned long halt_time, timeout;
-+ u32 status;
-
-- status = macb_readl(bp, TSR);
-- macb_writel(bp, TSR, status);
-+ macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(THALT));
-
-- netdev_vdbg(bp->dev, "macb_tx status = 0x%03lx\n", (unsigned long)status);
-+ timeout = jiffies + usecs_to_jiffies(MACB_HALT_TIMEOUT);
-+ do {
-+ halt_time = jiffies;
-+ status = macb_readl(bp, TSR);
-+ if (!(status & MACB_BIT(TGO)))
-+ return 0;
-
-- if (status & (MACB_BIT(UND) | MACB_BIT(TSR_RLE))) {
-- int i;
-- netdev_err(bp->dev, "TX %s, resetting buffers\n",
-- status & MACB_BIT(UND) ?
-- "underrun" : "retry limit exceeded");
-+ usleep_range(10, 250);
-+ } while (time_before(halt_time, timeout));
-
-- /* Transfer ongoing, disable transmitter, to avoid confusion */
-- if (status & MACB_BIT(TGO))
-- macb_writel(bp, NCR, macb_readl(bp, NCR) & ~MACB_BIT(TE));
-+ return -ETIMEDOUT;
-+}
-
-- head = bp->tx_head;
-+static void macb_tx_error_task(struct work_struct *work)
-+{
-+ struct macb *bp = container_of(work, struct macb, tx_error_task);
-+ struct macb_tx_skb *tx_skb;
-+ struct sk_buff *skb;
-+ unsigned int tail;
-
-- /*Mark all the buffer as used to avoid sending a lost buffer*/
-- for (i = 0; i < TX_RING_SIZE; i++)
-- bp->tx_ring[i].ctrl = MACB_BIT(TX_USED);
-+ netdev_vdbg(bp->dev, "macb_tx_error_task: t = %u, h = %u\n",
-+ bp->tx_tail, bp->tx_head);
-
-- /* Add wrap bit */
-- bp->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
-+ /* Make sure nobody is trying to queue up new packets */
-+ netif_stop_queue(bp->dev);
-
-- /* free transmit buffer in upper layer*/
-- for (tail = bp->tx_tail; tail != head; tail++) {
-- struct macb_tx_skb *tx_skb;
-- struct sk_buff *skb;
-+ /*
-+ * Stop transmission now
-+ * (in case we have just queued new packets)
-+ */
-+ if (macb_halt_tx(bp))
-+ /* Just complain for now, reinitializing TX path can be good */
-+ netdev_err(bp->dev, "BUG: halt tx timed out\n");
-
-- rmb();
-+ /* No need for the lock here as nobody will interrupt us anymore */
-
-- tx_skb = macb_tx_skb(bp, tail);
-- skb = tx_skb->skb;
-+ /*
-+ * Treat frames in TX queue including the ones that caused the error.
-+ * Free transmit buffers in upper layer.
-+ */
-+ for (tail = bp->tx_tail; tail != bp->tx_head; tail++) {
-+ struct macb_dma_desc *desc;
-+ u32 ctrl;
-
-- dma_unmap_single(&bp->pdev->dev, tx_skb->mapping,
-- skb->len, DMA_TO_DEVICE);
-- tx_skb->skb = NULL;
-- dev_kfree_skb_irq(skb);
-- }
-+ desc = macb_tx_desc(bp, tail);
-+ ctrl = desc->ctrl;
-+ tx_skb = macb_tx_skb(bp, tail);
-+ skb = tx_skb->skb;
-
-- bp->tx_head = bp->tx_tail = 0;
-+ if (ctrl & MACB_BIT(TX_USED)) {
-+ netdev_vdbg(bp->dev, "txerr skb %u (data %p) TX complete\n",
-+ macb_tx_ring_wrap(tail), skb->data);
-+ bp->stats.tx_packets++;
-+ bp->stats.tx_bytes += skb->len;
-+ } else {
-+ /*
-+ * "Buffers exhausted mid-frame" errors may only happen
-+ * if the driver is buggy, so complain loudly about those.
-+ * Statistics are updated by hardware.
-+ */
-+ if (ctrl & MACB_BIT(TX_BUF_EXHAUSTED))
-+ netdev_err(bp->dev,
-+ "BUG: TX buffers exhausted mid-frame\n");
-
-- /* Enable the transmitter again */
-- if (status & MACB_BIT(TGO))
-- macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TE));
-+ desc->ctrl = ctrl | MACB_BIT(TX_USED);
-+ }
-+
-+ dma_unmap_single(&bp->pdev->dev, tx_skb->mapping, skb->len,
-+ DMA_TO_DEVICE);
-+ tx_skb->skb = NULL;
-+ dev_kfree_skb(skb);
- }
-
-- if (!(status & MACB_BIT(COMP)))
-- /*
-- * This may happen when a buffer becomes complete
-- * between reading the ISR and scanning the
-- * descriptors. Nothing to worry about.
-- */
-- return;
-+ /* Make descriptor updates visible to hardware */
-+ wmb();
-+
-+ /* Reinitialize the TX desc queue */
-+ macb_writel(bp, TBQP, bp->tx_ring_dma);
-+ /* Make TX ring reflect state of hardware */
-+ bp->tx_head = bp->tx_tail = 0;
-+
-+ /* Now we are ready to start transmission again */
-+ netif_wake_queue(bp->dev);
-+
-+ /* Housework before enabling TX IRQ */
-+ macb_writel(bp, TSR, macb_readl(bp, TSR));
-+ macb_writel(bp, IER, MACB_TX_INT_FLAGS);
-+}
-+
-+static void macb_tx_interrupt(struct macb *bp)
-+{
-+ unsigned int tail;
-+ unsigned int head;
-+ u32 status;
-+
-+ status = macb_readl(bp, TSR);
-+ macb_writel(bp, TSR, status);
-+
-+ netdev_vdbg(bp->dev, "macb_tx_interrupt status = 0x%03lx\n",
-+ (unsigned long)status);
-
- head = bp->tx_head;
- for (tail = bp->tx_tail; tail != head; tail++) {
-@@ -637,9 +694,14 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
- }
- }
-
-- if (status & (MACB_BIT(TCOMP) | MACB_BIT(ISR_TUND) |
-- MACB_BIT(ISR_RLE)))
-- macb_tx(bp);
-+ if (unlikely(status & (MACB_TX_ERR_FLAGS))) {
-+ macb_writel(bp, IDR, MACB_TX_INT_FLAGS);
-+ schedule_work(&bp->tx_error_task);
-+ break;
-+ }
-+
-+ if (status & MACB_BIT(TCOMP))
-+ macb_tx_interrupt(bp);
-
- /*
- * Link change detection isn't possible with RMII, so we'll
-@@ -969,13 +1031,8 @@ static void macb_init_hw(struct macb *bp)
- macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE));
-
- /* Enable interrupts */
-- macb_writel(bp, IER, (MACB_BIT(RCOMP)
-- | MACB_BIT(RXUBR)
-- | MACB_BIT(ISR_TUND)
-- | MACB_BIT(ISR_RLE)
-- | MACB_BIT(TXERR)
-- | MACB_BIT(TCOMP)
-- | MACB_BIT(ISR_ROVR)
-+ macb_writel(bp, IER, (MACB_RX_INT_FLAGS
-+ | MACB_TX_INT_FLAGS
- | MACB_BIT(HRESP)));
-
- }
-@@ -1423,6 +1480,7 @@ static int __init macb_probe(struct platform_device *pdev)
- bp->dev = dev;
-
- spin_lock_init(&bp->lock);
-+ INIT_WORK(&bp->tx_error_task, macb_tx_error_task);
-
- bp->pclk = clk_get(&pdev->dev, "pclk");
- if (IS_ERR(bp->pclk)) {
-diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
-index 5be5900..bfab8ef 100644
---- a/drivers/net/ethernet/cadence/macb.h
-+++ b/drivers/net/ethernet/cadence/macb.h
-@@ -532,6 +532,7 @@ struct macb {
- struct clk *hclk;
- struct net_device *dev;
- struct napi_struct napi;
-+ struct work_struct tx_error_task;
- struct net_device_stats stats;
- union {
- struct macb_stats macb;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 392c13a787ed77602e6dd398e5389aa82d157a0e Mon Sep 17 00:00:00 2001
-From: Havard Skinnemoen <havard@skinnemoen.net>
-Date: Tue, 24 Mar 2009 10:45:18 +0100
-Subject: net/macb: Offset first RX buffer by two bytes
-
-Make the ethernet frame payload word-aligned, possibly making the
-memcpy into the skb a bit faster. This will be even more important
-after we eliminate the copy altogether.
-
-Also eliminate the redundant RX_OFFSET constant -- it has the same
-definition and purpose as NET_IP_ALIGN.
-
-Signed-off-by: Havard Skinnemoen <havard@skinnemoen.net>
-[nicolas.ferre@atmel.com: adapt to newer kernel]
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/net/ethernet/cadence/macb.c | 23 ++++++++++++++++-------
- 1 file changed, 16 insertions(+), 7 deletions(-)
-
-diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
-index cd24ce6..88a1d20 100644
---- a/drivers/net/ethernet/cadence/macb.c
-+++ b/drivers/net/ethernet/cadence/macb.c
-@@ -33,9 +33,6 @@
- #define RX_RING_SIZE 512
- #define RX_RING_BYTES (sizeof(struct macb_dma_desc) * RX_RING_SIZE)
-
--/* Make the IP header word-aligned (the ethernet header is 14 bytes) */
--#define RX_OFFSET 2
--
- #define TX_RING_SIZE 128
- #define TX_RING_BYTES (sizeof(struct macb_dma_desc) * TX_RING_SIZE)
-
-@@ -497,7 +494,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
- {
- unsigned int len;
- unsigned int frag;
-- unsigned int offset = 0;
-+ unsigned int offset;
- struct sk_buff *skb;
- struct macb_dma_desc *desc;
-
-@@ -508,7 +505,16 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
- macb_rx_ring_wrap(first_frag),
- macb_rx_ring_wrap(last_frag), len);
-
-- skb = netdev_alloc_skb(bp->dev, len + RX_OFFSET);
-+ /*
-+ * The ethernet header starts NET_IP_ALIGN bytes into the
-+ * first buffer. Since the header is 14 bytes, this makes the
-+ * payload word-aligned.
-+ *
-+ * Instead of calling skb_reserve(NET_IP_ALIGN), we just copy
-+ * the two padding bytes into the skb so that we avoid hitting
-+ * the slowpath in memcpy(), and pull them off afterwards.
-+ */
-+ skb = netdev_alloc_skb(bp->dev, len + NET_IP_ALIGN);
- if (!skb) {
- bp->stats.rx_dropped++;
- for (frag = first_frag; ; frag++) {
-@@ -524,7 +530,8 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
- return 1;
- }
-
-- skb_reserve(skb, RX_OFFSET);
-+ offset = 0;
-+ len += NET_IP_ALIGN;
- skb_checksum_none_assert(skb);
- skb_put(skb, len);
-
-@@ -548,10 +555,11 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
- /* Make descriptor updates visible to hardware */
- wmb();
-
-+ __skb_pull(skb, NET_IP_ALIGN);
- skb->protocol = eth_type_trans(skb, bp->dev);
-
- bp->stats.rx_packets++;
-- bp->stats.rx_bytes += len;
-+ bp->stats.rx_bytes += skb->len;
- netdev_vdbg(bp->dev, "received skb of length %u, csum: %08x\n",
- skb->len, skb->csum);
- netif_receive_skb(skb);
-@@ -1011,6 +1019,7 @@ static void macb_init_hw(struct macb *bp)
- __macb_set_hwaddr(bp);
-
- config = macb_mdc_clk_div(bp);
-+ config |= MACB_BF(RBOF, NET_IP_ALIGN); /* Make eth data aligned */
- config |= MACB_BIT(PAE); /* PAuse Enable */
- config |= MACB_BIT(DRFCS); /* Discard Rx FCS */
- config |= MACB_BIT(BIG); /* Receive oversized frames */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 97a5734b38bdb9226e9806e766a3a2c2b80d1dd4 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Wed, 19 Sep 2012 15:14:34 +0200
-Subject: net/macb: GEM DMA configuration register update
-
-Add information to the DMA Configuration Register to
-maximize system performance:
-- rx/tx packet buffer full memory size
-- allow possibility to use INCR16 if supported
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/net/ethernet/cadence/macb.c | 10 ++++++++--
- drivers/net/ethernet/cadence/macb.h | 11 +++++++++++
- 2 files changed, 19 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
-index 88a1d20..56bab3c 100644
---- a/drivers/net/ethernet/cadence/macb.c
-+++ b/drivers/net/ethernet/cadence/macb.c
-@@ -997,8 +997,12 @@ static u32 macb_dbw(struct macb *bp)
- }
-
- /*
-- * Configure the receive DMA engine to use the correct receive buffer size.
-- * This is a configurable parameter for GEM.
-+ * Configure the receive DMA engine
-+ * - use the correct receive buffer size
-+ * - set the possibility to use INCR16 bursts
-+ * (if not supported by FIFO, it will fallback to default)
-+ * - set both rx/tx packet buffers to full memory size
-+ * These are configurable parameters for GEM.
- */
- static void macb_configure_dma(struct macb *bp)
- {
-@@ -1007,6 +1011,8 @@ static void macb_configure_dma(struct macb *bp)
- if (macb_is_gem(bp)) {
- dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
- dmacfg |= GEM_BF(RXBS, RX_BUFFER_SIZE / 64);
-+ dmacfg |= GEM_BF(FBLDO, 16);
-+ dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
- gem_writel(bp, DMACFG, dmacfg);
- }
- }
-diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
-index bfab8ef..256559d 100644
---- a/drivers/net/ethernet/cadence/macb.h
-+++ b/drivers/net/ethernet/cadence/macb.h
-@@ -161,8 +161,19 @@
- #define GEM_DBW128 2
-
- /* Bitfields in DMACFG. */
-+#define GEM_FBLDO_OFFSET 0
-+#define GEM_FBLDO_SIZE 5
-+#define GEM_RXBMS_OFFSET 8
-+#define GEM_RXBMS_SIZE 2
-+#define GEM_TXPBMS_OFFSET 10
-+#define GEM_TXPBMS_SIZE 1
-+#define GEM_TXCOEN_OFFSET 11
-+#define GEM_TXCOEN_SIZE 1
- #define GEM_RXBS_OFFSET 16
- #define GEM_RXBS_SIZE 8
-+#define GEM_DDRP_OFFSET 24
-+#define GEM_DDRP_SIZE 1
-+
-
- /* Bitfields in NSR */
- #define MACB_NSR_LINK_OFFSET 0
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2013c10691d645778545505b7ea07fa539b8ae11 Mon Sep 17 00:00:00 2001
-From: Havard Skinnemoen <havard@skinnemoen.net>
-Date: Tue, 24 Mar 2009 10:45:19 +0100
-Subject: net/macb: Use non-coherent memory for rx buffers
-
-Allocate regular pages to use as backing for the RX ring and use the
-DMA API to sync the caches. This should give a bit better performance
-since it allows the CPU to do burst transfers from memory. It is also
-a necessary step on the way to reduce the amount of copying done by
-the driver.
-
-Signed-off-by: Havard Skinnemoen <havard@skinnemoen.net>
-[nicolas.ferre@atmel.com: adapt to newer kernel]
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/net/ethernet/cadence/macb.c | 206 +++++++++++++++++++++++-------------
- drivers/net/ethernet/cadence/macb.h | 20 +++-
- 2 files changed, 148 insertions(+), 78 deletions(-)
-
-diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
-index 56bab3c..e3168bf 100644
---- a/drivers/net/ethernet/cadence/macb.c
-+++ b/drivers/net/ethernet/cadence/macb.c
-@@ -10,6 +10,7 @@
-
- #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
- #include <linux/clk.h>
-+#include <linux/highmem.h>
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/kernel.h>
-@@ -32,6 +33,8 @@
- #define RX_BUFFER_SIZE 128
- #define RX_RING_SIZE 512
- #define RX_RING_BYTES (sizeof(struct macb_dma_desc) * RX_RING_SIZE)
-+#define RX_BUFFERS_PER_PAGE (PAGE_SIZE / RX_BUFFER_SIZE)
-+#define RX_RING_PAGES (RX_RING_SIZE / RX_BUFFERS_PER_PAGE)
-
- #define TX_RING_SIZE 128
- #define TX_RING_BYTES (sizeof(struct macb_dma_desc) * TX_RING_SIZE)
-@@ -92,9 +95,16 @@ static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
- return &bp->rx_ring[macb_rx_ring_wrap(index)];
- }
-
--static void *macb_rx_buffer(struct macb *bp, unsigned int index)
-+static struct macb_rx_page *macb_rx_page(struct macb *bp, unsigned int index)
- {
-- return bp->rx_buffers + RX_BUFFER_SIZE * macb_rx_ring_wrap(index);
-+ unsigned int entry = macb_rx_ring_wrap(index);
-+
-+ return &bp->rx_page[entry / RX_BUFFERS_PER_PAGE];
-+}
-+
-+static unsigned int macb_rx_page_offset(struct macb *bp, unsigned int index)
-+{
-+ return (index % RX_BUFFERS_PER_PAGE) * RX_BUFFER_SIZE;
- }
-
- static void __macb_set_hwaddr(struct macb *bp)
-@@ -492,11 +502,15 @@ static void macb_tx_interrupt(struct macb *bp)
- static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
- unsigned int last_frag)
- {
-- unsigned int len;
-- unsigned int frag;
-- unsigned int offset;
-- struct sk_buff *skb;
-- struct macb_dma_desc *desc;
-+ unsigned int len;
-+ unsigned int frag;
-+ unsigned int skb_offset;
-+ unsigned int pg_offset;
-+ struct macb_rx_page *rx_page;
-+ dma_addr_t phys;
-+ void *buf;
-+ struct sk_buff *skb;
-+ struct macb_dma_desc *desc;
-
- desc = macb_rx_desc(bp, last_frag);
- len = MACB_BFEXT(RX_FRMLEN, desc->ctrl);
-@@ -530,7 +544,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
- return 1;
- }
-
-- offset = 0;
-+ skb_offset = 0;
- len += NET_IP_ALIGN;
- skb_checksum_none_assert(skb);
- skb_put(skb, len);
-@@ -538,13 +552,28 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
- for (frag = first_frag; ; frag++) {
- unsigned int frag_len = RX_BUFFER_SIZE;
-
-- if (offset + frag_len > len) {
-+ if (skb_offset + frag_len > len) {
- BUG_ON(frag != last_frag);
-- frag_len = len - offset;
-+ frag_len = len - skb_offset;
- }
-- skb_copy_to_linear_data_offset(skb, offset,
-- macb_rx_buffer(bp, frag), frag_len);
-- offset += RX_BUFFER_SIZE;
-+
-+ rx_page = macb_rx_page(bp, frag);
-+ pg_offset = macb_rx_page_offset(bp, frag);
-+ phys = rx_page->phys;
-+
-+ dma_sync_single_range_for_cpu(&bp->pdev->dev, phys,
-+ pg_offset, frag_len, DMA_FROM_DEVICE);
-+
-+ buf = kmap_atomic(rx_page->page);
-+ skb_copy_to_linear_data_offset(skb, skb_offset,
-+ buf + pg_offset, frag_len);
-+ kunmap_atomic(buf);
-+
-+ skb_offset += frag_len;
-+
-+ dma_sync_single_range_for_device(&bp->pdev->dev, phys,
-+ pg_offset, frag_len, DMA_FROM_DEVICE);
-+
- desc = macb_rx_desc(bp, frag);
- desc->addr &= ~MACB_BIT(RX_USED);
-
-@@ -824,86 +853,90 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
- return NETDEV_TX_OK;
- }
-
--static void macb_free_consistent(struct macb *bp)
-+static void macb_free_rings(struct macb *bp)
- {
-- if (bp->tx_skb) {
-- kfree(bp->tx_skb);
-- bp->tx_skb = NULL;
-- }
-- if (bp->rx_ring) {
-- dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES,
-- bp->rx_ring, bp->rx_ring_dma);
-- bp->rx_ring = NULL;
-- }
-- if (bp->tx_ring) {
-- dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES,
-- bp->tx_ring, bp->tx_ring_dma);
-- bp->tx_ring = NULL;
-- }
-- if (bp->rx_buffers) {
-- dma_free_coherent(&bp->pdev->dev,
-- RX_RING_SIZE * RX_BUFFER_SIZE,
-- bp->rx_buffers, bp->rx_buffers_dma);
-- bp->rx_buffers = NULL;
-+ int i;
-+
-+ for (i = 0; i < RX_RING_PAGES; i++) {
-+ struct macb_rx_page *rx_page = &bp->rx_page[i];
-+
-+ if (!rx_page->page)
-+ continue;
-+
-+ dma_unmap_page(&bp->pdev->dev, rx_page->phys,
-+ PAGE_SIZE, DMA_FROM_DEVICE);
-+ put_page(rx_page->page);
-+ rx_page->page = NULL;
- }
-+
-+ kfree(bp->tx_skb);
-+ kfree(bp->rx_page);
-+ dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES, bp->tx_ring,
-+ bp->tx_ring_dma);
-+ dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES, bp->rx_ring,
-+ bp->rx_ring_dma);
- }
-
--static int macb_alloc_consistent(struct macb *bp)
-+static int macb_init_rings(struct macb *bp)
- {
-- int size;
-+ struct page *page;
-+ dma_addr_t phys;
-+ unsigned int page_idx;
-+ unsigned int ring_idx;
-+ unsigned int i;
-
-- size = TX_RING_SIZE * sizeof(struct macb_tx_skb);
-- bp->tx_skb = kmalloc(size, GFP_KERNEL);
-- if (!bp->tx_skb)
-- goto out_err;
--
-- size = RX_RING_BYTES;
-- bp->rx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
-+ bp->rx_ring = dma_alloc_coherent(&bp->pdev->dev, RX_RING_BYTES,
- &bp->rx_ring_dma, GFP_KERNEL);
- if (!bp->rx_ring)
-- goto out_err;
-+ goto err_alloc_rx_ring;
-+
- netdev_dbg(bp->dev,
- "Allocated RX ring of %d bytes at %08lx (mapped %p)\n",
-- size, (unsigned long)bp->rx_ring_dma, bp->rx_ring);
-+ RX_RING_BYTES, (unsigned long)bp->rx_ring_dma, bp->rx_ring);
-
-- size = TX_RING_BYTES;
-- bp->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
-+ bp->tx_ring = dma_alloc_coherent(&bp->pdev->dev, TX_RING_BYTES,
- &bp->tx_ring_dma, GFP_KERNEL);
- if (!bp->tx_ring)
-- goto out_err;
-- netdev_dbg(bp->dev,
-- "Allocated TX ring of %d bytes at %08lx (mapped %p)\n",
-- size, (unsigned long)bp->tx_ring_dma, bp->tx_ring);
--
-- size = RX_RING_SIZE * RX_BUFFER_SIZE;
-- bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size,
-- &bp->rx_buffers_dma, GFP_KERNEL);
-- if (!bp->rx_buffers)
-- goto out_err;
-+ goto err_alloc_tx_ring;
-+
- netdev_dbg(bp->dev,
-- "Allocated RX buffers of %d bytes at %08lx (mapped %p)\n",
-- size, (unsigned long)bp->rx_buffers_dma, bp->rx_buffers);
-+ "Allocated TX ring of %d bytes at 0x%08lx (mapped %p)\n",
-+ TX_RING_BYTES, (unsigned long)bp->tx_ring_dma, bp->tx_ring);
-
-- return 0;
-+ bp->rx_page = kcalloc(RX_RING_PAGES, sizeof(struct macb_rx_page),
-+ GFP_KERNEL);
-+ if (!bp->rx_page)
-+ goto err_alloc_rx_page;
-
--out_err:
-- macb_free_consistent(bp);
-- return -ENOMEM;
--}
-+ bp->tx_skb = kcalloc(TX_RING_SIZE, sizeof(struct macb_tx_skb),
-+ GFP_KERNEL);
-+ if (!bp->tx_skb)
-+ goto err_alloc_tx_skb;
-
--static void macb_init_rings(struct macb *bp)
--{
-- int i;
-- dma_addr_t addr;
-+ for (page_idx = 0, ring_idx = 0; page_idx < RX_RING_PAGES; page_idx++) {
-+ page = alloc_page(GFP_KERNEL);
-+ if (!page)
-+ goto err_alloc_page;
-+
-+ phys = dma_map_page(&bp->pdev->dev, page, 0, PAGE_SIZE,
-+ DMA_FROM_DEVICE);
-+ if (dma_mapping_error(&bp->pdev->dev, phys))
-+ goto err_map_page;
-+
-+ bp->rx_page[page_idx].page = page;
-+ bp->rx_page[page_idx].phys = phys;
-
-- addr = bp->rx_buffers_dma;
-- for (i = 0; i < RX_RING_SIZE; i++) {
-- bp->rx_ring[i].addr = addr;
-- bp->rx_ring[i].ctrl = 0;
-- addr += RX_BUFFER_SIZE;
-+ for (i = 0; i < RX_BUFFERS_PER_PAGE; i++, ring_idx++) {
-+ bp->rx_ring[ring_idx].addr = phys;
-+ bp->rx_ring[ring_idx].ctrl = 0;
-+ phys += RX_BUFFER_SIZE;
-+ }
- }
- bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP);
-
-+ netdev_dbg(bp->dev, "Allocated %u RX buffers (%lu pages)\n",
-+ RX_RING_SIZE, RX_RING_PAGES);
-+
- for (i = 0; i < TX_RING_SIZE; i++) {
- bp->tx_ring[i].addr = 0;
- bp->tx_ring[i].ctrl = MACB_BIT(TX_USED);
-@@ -911,6 +944,28 @@ static void macb_init_rings(struct macb *bp)
- bp->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
-
- bp->rx_tail = bp->tx_head = bp->tx_tail = 0;
-+
-+ return 0;
-+
-+err_map_page:
-+ __free_page(page);
-+err_alloc_page:
-+ while (page_idx--) {
-+ dma_unmap_page(&bp->pdev->dev, bp->rx_page[page_idx].phys,
-+ PAGE_SIZE, DMA_FROM_DEVICE);
-+ __free_page(bp->rx_page[page_idx].page);
-+ }
-+ kfree(bp->tx_skb);
-+err_alloc_tx_skb:
-+ kfree(bp->rx_page);
-+err_alloc_rx_page:
-+ dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES, bp->tx_ring,
-+ bp->tx_ring_dma);
-+err_alloc_tx_ring:
-+ dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES, bp->rx_ring,
-+ bp->rx_ring_dma);
-+err_alloc_rx_ring:
-+ return -ENOMEM;
- }
-
- static void macb_reset_hw(struct macb *bp)
-@@ -1185,16 +1240,15 @@ static int macb_open(struct net_device *dev)
- if (!is_valid_ether_addr(dev->dev_addr))
- return -EADDRNOTAVAIL;
-
-- err = macb_alloc_consistent(bp);
-+ err = macb_init_rings(bp);
- if (err) {
-- netdev_err(dev, "Unable to allocate DMA memory (error %d)\n",
-+ netdev_err(dev, "Unable to allocate DMA rings (error %d)\n",
- err);
- return err;
- }
-
- napi_enable(&bp->napi);
-
-- macb_init_rings(bp);
- macb_init_hw(bp);
-
- /* schedule a link state check */
-@@ -1221,7 +1275,7 @@ static int macb_close(struct net_device *dev)
- netif_carrier_off(dev);
- spin_unlock_irqrestore(&bp->lock, flags);
-
-- macb_free_consistent(bp);
-+ macb_free_rings(bp);
-
- return 0;
- }
-diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
-index 256559d..01aecea 100644
---- a/drivers/net/ethernet/cadence/macb.h
-+++ b/drivers/net/ethernet/cadence/macb.h
-@@ -441,6 +441,23 @@ struct macb_dma_desc {
- #define MACB_TX_USED_SIZE 1
-
- /**
-+ * struct macb_rx_page - data associated with a page used as RX buffers
-+ * @page: Physical page used as storage for the buffers
-+ * @phys: DMA address of the page
-+ *
-+ * Each page is used to provide %MACB_RX_BUFFERS_PER_PAGE RX buffers.
-+ * The page gets an initial reference when it is inserted into the
-+ * ring, and an additional reference each time it is passed up the
-+ * stack as a fragment. When all the buffers have been used, we drop
-+ * the initial reference and allocate a new page. Any additional
-+ * references are dropped when the higher layers free the skb.
-+ */
-+struct macb_rx_page {
-+ struct page *page;
-+ dma_addr_t phys;
-+};
-+
-+/**
- * struct macb_tx_skb - data about an skb which is being transmitted
- * @skb: skb currently being transmitted
- * @mapping: DMA address of the skb's data buffer
-@@ -531,7 +548,7 @@ struct macb {
-
- unsigned int rx_tail;
- struct macb_dma_desc *rx_ring;
-- void *rx_buffers;
-+ struct macb_rx_page *rx_page;
-
- unsigned int tx_head, tx_tail;
- struct macb_dma_desc *tx_ring;
-@@ -552,7 +569,6 @@ struct macb {
-
- dma_addr_t rx_ring_dma;
- dma_addr_t tx_ring_dma;
-- dma_addr_t rx_buffers_dma;
-
- struct mii_bus *mii_bus;
- struct phy_device *phy_dev;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e2086addb7f23c3aa497a3b9e36559efd6059e62 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 26 Jun 2012 11:07:32 +0200
-Subject: phy/micrel: Use proper phy in gmac
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/net/phy/micrel.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
-index 590f902..cc7f75b 100644
---- a/drivers/net/phy/micrel.c
-+++ b/drivers/net/phy/micrel.c
-@@ -191,6 +191,7 @@ static int __init ksphy_init(void)
- {
- int ret;
-
-+#if 0
- ret = phy_driver_register(&ks8001_driver);
- if (ret)
- goto err1;
-@@ -208,9 +209,15 @@ static int __init ksphy_init(void)
- ret = phy_driver_register(&ks8051_driver);
- if (ret)
- goto err5;
-+#endif
-+
-+ ret = phy_driver_register(&ksz9021_driver);
-+ if (ret)
-+ goto err1;
-
- return 0;
-
-+#if 0
- err5:
- phy_driver_unregister(&ks8041_driver);
- err4:
-@@ -219,6 +226,7 @@ err3:
- phy_driver_unregister(&ksz9021_driver);
- err2:
- phy_driver_unregister(&ks8001_driver);
-+#endif
- err1:
- return ret;
- }
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From af15c74766bcffe30022f7c27e477d2fce4b8471 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Tue, 10 Jul 2012 12:03:54 +0200
-Subject: phy/micrel: we need to register ks8051 phy for emac
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- drivers/net/phy/micrel.c | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
-index cc7f75b..2d80e01 100644
---- a/drivers/net/phy/micrel.c
-+++ b/drivers/net/phy/micrel.c
-@@ -206,10 +206,10 @@ static int __init ksphy_init(void)
- ret = phy_driver_register(&ks8041_driver);
- if (ret)
- goto err4;
-+#endif
- ret = phy_driver_register(&ks8051_driver);
- if (ret)
-- goto err5;
--#endif
-+ goto err2;
-
- ret = phy_driver_register(&ksz9021_driver);
- if (ret)
-@@ -227,6 +227,8 @@ err3:
- err2:
- phy_driver_unregister(&ks8001_driver);
- #endif
-+err2:
-+ phy_driver_unregister(&ks8051_driver);
- err1:
- return ret;
- }
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e3cfccfee57c12157e38081fc11e0a2f2f5863f3 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Fri, 10 Jun 2011 17:21:28 +0200
-Subject: media/video: atmel-isi: add dumb set_parm()
-
-Add dumb set_parm() & get_parm() function to struct soc_camera_host_ops.
-Needed for ffmpeg to be able to capture frames from ISI driver.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/media/video/atmel-isi.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c
-index ec3f6a0..7a44df4 100644
---- a/drivers/media/video/atmel-isi.c
-+++ b/drivers/media/video/atmel-isi.c
-@@ -893,6 +893,12 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd)
- return 0;
- }
-
-+
-+static int isi_camera_set_parm(struct soc_camera_device *icd, struct v4l2_streamparm *parm)
-+{
-+ return 0;
-+}
-+
- static struct soc_camera_host_ops isi_soc_camera_host_ops = {
- .owner = THIS_MODULE,
- .add = isi_camera_add_device,
-@@ -904,6 +910,8 @@ static struct soc_camera_host_ops isi_soc_camera_host_ops = {
- .poll = isi_camera_poll,
- .querycap = isi_camera_querycap,
- .set_bus_param = isi_camera_set_bus_param,
-+ .set_parm = isi_camera_set_parm,
-+ .get_parm = isi_camera_set_parm,
- };
-
- /* -----------------------------------------------------------------------*/
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 53e09e8e36a22c3d0b7b0001f6c57ee9e750ee29 Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Mon, 1 Nov 2010 16:38:41 +0800
-Subject: video/atmel_lcdfb: add support for AT91SAM9x5
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Josh Wu <josh.wu@atmel.com>
-Signed-off-by: Dan Liang <dan.liang@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-[ukleinek: forward-port to 2.6.39-rcish]
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
-
-Conflicts:
-
- drivers/video/atmel_lcdfb.c
----
- arch/arm/mach-at91/include/mach/atmel_hlcdfb.h | 865 +++++++++++++++++++++++++
- drivers/video/atmel_lcdfb.c | 670 ++++++++++++++-----
- include/video/atmel_lcdc.h | 15
- 3 files changed, 1390 insertions(+), 160 deletions(-)
- create mode 100644 arch/arm/mach-at91/include/mach/atmel_hlcdfb.h
-
---- /dev/null
-+++ b/arch/arm/mach-at91/include/mach/atmel_hlcdfb.h
-@@ -0,0 +1,865 @@
-+/*
-+ * Header file for AT91 High end LCD Controller
-+ *
-+ * Data structure and register user interface
-+ *
-+ * Copyright (C) 2010 Atmel Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PUROFFSETE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+#ifndef __ATMEL_HLCD_H__
-+#define __ATMEL_HLCD_H__
-+
-+/* Lcdc hardware registers */
-+#define ATMEL_LCDC_LCDCFG0 0x0000
-+#define LCDC_LCDCFG0_CLKPOL (0x1 << 0)
-+#define LCDC_LCDCFG0_CLKSEL (0x1 << 2)
-+#define LCDC_LCDCFG0_CLKPWMSEL (0x1 << 3)
-+#define LCDC_LCDCFG0_CGDISBASE (0x1 << 8)
-+#define LCDC_LCDCFG0_CGDISOVR1 (0x1 << 9)
-+#define LCDC_LCDCFG0_CGDISHEO (0x1 << 11)
-+#define LCDC_LCDCFG0_CGDISHCR (0x1 << 12)
-+#define LCDC_LCDCFG0_CLKDIV_OFFSET 16
-+#define LCDC_LCDCFG0_CLKDIV (0xff << LCDC_LCDCFG0_CLKDIV_OFFSET)
-+
-+#define ATMEL_LCDC_LCDCFG1 0x0004
-+#define LCDC_LCDCFG1_HSPW_OFFSET 0
-+#define LCDC_LCDCFG1_HSPW (0x3f << LCDC_LCDCFG1_HSPW_OFFSET)
-+#define LCDC_LCDCFG1_VSPW_OFFSET 16
-+#define LCDC_LCDCFG1_VSPW (0x3f << LCDC_LCDCFG1_VSPW_OFFSET)
-+
-+#define ATMEL_LCDC_LCDCFG2 0x0008
-+#define LCDC_LCDCFG2_VFPW_OFFSET 0
-+#define LCDC_LCDCFG2_VFPW (0x3f << LCDC_LCDCFG2_VFPW_OFFSET)
-+#define LCDC_LCDCFG2_VBPW_OFFSET 16
-+#define LCDC_LCDCFG2_VBPW (0x3f << LCDC_LCDCFG2_VBPW_OFFSET)
-+
-+#define ATMEL_LCDC_LCDCFG3 0x000C
-+#define LCDC_LCDCFG3_HFPW_OFFSET 0
-+#define LCDC_LCDCFG3_HFPW (0xff << LCDC_LCDCFG3_HFPW_OFFSET)
-+#define LCDC_LCDCFG3_HBPW_OFFSET 16
-+#define LCDC_LCDCFG3_HBPW (0xff << LCDC_LCDCFG3_HBPW_OFFSET)
-+
-+#define ATMEL_LCDC_LCDCFG4 0x0010
-+#define LCDC_LCDCFG4_PPL_OFFSET 0
-+#define LCDC_LCDCFG4_PPL (0x7ff << LCDC_LCDCFG4_PPL_OFFSET)
-+#define LCDC_LCDCFG4_RPF_OFFSET 16
-+#define LCDC_LCDCFG4_RPF (0x7ff << LCDC_LCDCFG4_RPF_OFFSET)
-+
-+#define ATMEL_LCDC_LCDCFG5 0x0014
-+#define LCDC_LCDCFG5_HSPOL (0x1 << 0)
-+#define LCDC_LCDCFG5_VSPOL (0x1 << 1)
-+#define LCDC_LCDCFG5_VSPDLYS (0x1 << 2)
-+#define LCDC_LCDCFG5_VSPDLYE (0x1 << 3)
-+#define LCDC_LCDCFG5_DISPPOL (0x1 << 4)
-+#define LCDC_LCDCFG5_SERIAL (0x1 << 5)
-+#define LCDC_LCDCFG5_DITHER (0x1 << 6)
-+#define LCDC_LCDCFG5_DISPDLY (0x1 << 7)
-+#define LCDC_LCDCFG5_MODE_OFFSET 8
-+#define LCDC_LCDCFG5_MODE (0x3 << LCDC_LCDCFG5_MODE_OFFSET)
-+#define LCDC_LCDCFG5_MODE_OUTPUT_12BPP (0x0 << 8)
-+#define LCDC_LCDCFG5_MODE_OUTPUT_16BPP (0x1 << 8)
-+#define LCDC_LCDCFG5_MODE_OUTPUT_18BPP (0x2 << 8)
-+#define LCDC_LCDCFG5_MODE_OUTPUT_24BPP (0x3 << 8)
-+#define LCDC_LCDCFG5_VSPSU (0x1 << 12)
-+#define LCDC_LCDCFG5_VSPHO (0x1 << 13)
-+#define LCDC_LCDCFG5_GUARDTIME_OFFSET 16
-+#define LCDC_LCDCFG5_GUARDTIME (0x1f << LCDC_LCDCFG5_GUARDTIME_OFFSET)
-+
-+#define ATMEL_LCDC_LCDCFG6 0x0018
-+#define LCDC_LCDCFG6_PWMPS_OFFSET 0
-+#define LCDC_LCDCFG6_PWMPS (0x7 << LCDC_LCDCFG6_PWMPS_OFFSET)
-+#define LCDC_LCDCFG6_PWMPOL (0x1 << 4)
-+#define LCDC_LCDCFG6_PWMCVAL_OFFSET 8
-+#define LCDC_LCDCFG6_PWMCVAL (0xff << LCDC_LCDCFG6_PWMCVAL_OFFSET)
-+
-+#define ATMEL_LCDC_LCDEN 0x0020
-+#define LCDC_LCDEN_CLKEN (0x1 << 0)
-+#define LCDC_LCDEN_SYNCEN (0x1 << 1)
-+#define LCDC_LCDEN_DISPEN (0x1 << 2)
-+#define LCDC_LCDEN_PWMEN (0x1 << 3)
-+
-+#define ATMEL_LCDC_LCDDIS 0x0024
-+#define LCDC_LCDDIS_CLKDIS (0x1 << 0)
-+#define LCDC_LCDDIS_SYNCDIS (0x1 << 1)
-+#define LCDC_LCDDIS_DISPDIS (0x1 << 2)
-+#define LCDC_LCDDIS_PWMDIS (0x1 << 3)
-+#define LCDC_LCDDIS_CLKRST (0x1 << 8)
-+#define LCDC_LCDDIS_SYNCRST (0x1 << 9)
-+#define LCDC_LCDDIS_DISPRST (0x1 << 10)
-+#define LCDC_LCDDIS_PWMRST (0x1 << 11)
-+
-+#define ATMEL_LCDC_LCDSR 0x0028
-+#define LCDC_LCDSR_CLKSTS (0x1 << 0)
-+#define LCDC_LCDSR_LCDSTS (0x1 << 1)
-+#define LCDC_LCDSR_DISPSTS (0x1 << 2)
-+#define LCDC_LCDSR_PWMSTS (0x1 << 3)
-+#define LCDC_LCDSR_SIPSTS (0x1 << 4)
-+
-+#define ATMEL_LCDC_LCDIER 0x002C
-+#define LCDC_LCDIER_SOFIE (0x1 << 0)
-+#define LCDC_LCDIER_DISIE (0x1 << 1)
-+#define LCDC_LCDIER_DISPIE (0x1 << 2)
-+#define LCDC_LCDIER_FIFOERRIE (0x1 << 4)
-+#define LCDC_LCDIER_BASEIE (0x1 << 8)
-+#define LCDC_LCDIER_OVR1IE (0x1 << 9)
-+#define LCDC_LCDIER_HEOIE (0x1 << 11)
-+#define LCDC_LCDIER_HCRIE (0x1 << 12)
-+
-+#define ATMEL_LCDC_LCDIDR 0x0030
-+#define LCDC_LCDIDR_SOFID (0x1 << 0)
-+#define LCDC_LCDIDR_DISID (0x1 << 1)
-+#define LCDC_LCDIDR_DISPID (0x1 << 2)
-+#define LCDC_LCDIDR_FIFOERRID (0x1 << 4)
-+#define LCDC_LCDIDR_BASEID (0x1 << 8)
-+#define LCDC_LCDIDR_OVR1ID (0x1 << 9)
-+#define LCDC_LCDIDR_HEOID (0x1 << 11)
-+#define LCDC_LCDIDR_HCRID (0x1 << 12)
-+
-+#define ATMEL_LCDC_LCDIMR 0x0034
-+#define LCDC_LCDIMR_SOFIM (0x1 << 0)
-+#define LCDC_LCDIMR_DISIM (0x1 << 1)
-+#define LCDC_LCDIMR_DISPIM (0x1 << 2)
-+#define LCDC_LCDIMR_FIFOERRIM (0x1 << 4)
-+#define LCDC_LCDIMR_BASEIM (0x1 << 8)
-+#define LCDC_LCDIMR_OVR1IM (0x1 << 9)
-+#define LCDC_LCDIMR_HEOIM (0x1 << 11)
-+#define LCDC_LCDIMR_HCRIM (0x1 << 12)
-+
-+#define ATMEL_LCDC_LCDISR 0x0038
-+#define LCDC_LCDISR_SOF (0x1 << 0)
-+#define LCDC_LCDISR_DIS (0x1 << 1)
-+#define LCDC_LCDISR_DISP (0x1 << 2)
-+#define LCDC_LCDISR_FIFOERR (0x1 << 4)
-+#define LCDC_LCDISR_BASE (0x1 << 8)
-+#define LCDC_LCDISR_OVR1 (0x1 << 9)
-+#define LCDC_LCDISR_HEO (0x1 << 11)
-+#define LCDC_LCDISR_HCR (0x1 << 12)
-+
-+#define ATMEL_LCDC_BASECHER 0x0040
-+#define LCDC_BASECHER_CHEN (0x1 << 0)
-+#define LCDC_BASECHER_UPDATEEN (0x1 << 1)
-+#define LCDC_BASECHER_A2QEN (0x1 << 2)
-+
-+#define ATMEL_LCDC_BASECHDR 0x0044
-+#define LCDC_BASECHDR_CHDIS (0x1 << 0)
-+#define LCDC_BASECHDR_CHRST (0x1 << 8)
-+
-+#define ATMEL_LCDC_BASECHSR 0x0048
-+#define LCDC_BASECHSR_CHSR (0x1 << 0)
-+#define LCDC_BASECHSR_UPDATESR (0x1 << 1)
-+#define LCDC_BASECHSR_A2QSR (0x1 << 2)
-+
-+#define ATMEL_LCDC_BASEIER 0x004C
-+#define LCDC_BASEIER_DMA (0x1 << 2)
-+#define LCDC_BASEIER_DSCR (0x1 << 3)
-+#define LCDC_BASEIER_ADD (0x1 << 4)
-+#define LCDC_BASEIER_DONE (0x1 << 5)
-+#define LCDC_BASEIER_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_BASEIDR 0x0050
-+#define LCDC_BASEIDR_DMA (0x1 << 2)
-+#define LCDC_BASEIDR_DSCR (0x1 << 3)
-+#define LCDC_BASEIDR_ADD (0x1 << 4)
-+#define LCDC_BASEIDR_DONE (0x1 << 5)
-+#define LCDC_BASEIDR_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_BASEIMR 0x0054
-+#define LCDC_BASEIMR_DMA (0x1 << 2)
-+#define LCDC_BASEIMR_DSCR (0x1 << 3)
-+#define LCDC_BASEIMR_ADD (0x1 << 4)
-+#define LCDC_BASEIMR_DONE (0x1 << 5)
-+#define LCDC_BASEIMR_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_BASEISR 0x0058
-+#define LCDC_BASEISR_DMA (0x1 << 2)
-+#define LCDC_BASEISR_DSCR (0x1 << 3)
-+#define LCDC_BASEISR_ADD (0x1 << 4)
-+#define LCDC_BASEISR_DONE (0x1 << 5)
-+#define LCDC_BASEISR_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_BASEHEAD 0x005C
-+
-+#define ATMEL_LCDC_BASEADDR 0x0060
-+
-+#define ATMEL_LCDC_BASECTRL 0x0064
-+#define LCDC_BASECTRL_DFETCH (0x1 << 0)
-+#define LCDC_BASECTRL_LFETCH (0x1 << 1)
-+#define LCDC_BASECTRL_DMAIEN (0x1 << 2)
-+#define LCDC_BASECTRL_DSCRIEN (0x1 << 3)
-+#define LCDC_BASECTRL_ADDIEN (0x1 << 4)
-+#define LCDC_BASECTRL_DONEIEN (0x1 << 5)
-+
-+#define ATMEL_LCDC_BASENEXT 0x0068
-+
-+#define ATMEL_LCDC_BASECFG0 0x006C
-+#define LCDC_BASECFG0_BLEN_OFFSET 4
-+#define LCDC_BASECFG0_BLEN (0x3 << LCDC_BASECFG0_BLEN_OFFSET)
-+#define LCDC_BASECFG0_BLEN_AHB_SINGLE (0x0 << 4)
-+#define LCDC_BASECFG0_BLEN_AHB_INCR4 (0x1 << 4)
-+#define LCDC_BASECFG0_BLEN_AHB_INCR8 (0x2 << 4)
-+#define LCDC_BASECFG0_BLEN_AHB_INCR16 (0x3 << 4)
-+#define LCDC_BASECFG0_DLBO (0x1 << 8)
-+
-+#define ATMEL_LCDC_BASECFG1 0x0070
-+#define LCDC_BASECFG1_CLUTEN (0x1 << 0)
-+#define LCDC_BASECFG1_RGBMODE_OFFSET 4
-+#define LCDC_BASECFG1_RGBMODE (0xf << LCDC_BASECFG1_RGBMODE_OFFSET)
-+#define LCDC_BASECFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4)
-+#define LCDC_BASECFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4)
-+#define LCDC_BASECFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4)
-+#define LCDC_BASECFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4)
-+#define LCDC_BASECFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4)
-+#define LCDC_BASECFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4)
-+#define LCDC_BASECFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4)
-+#define LCDC_BASECFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4)
-+#define LCDC_BASECFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4)
-+#define LCDC_BASECFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4)
-+#define LCDC_BASECFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4)
-+#define LCDC_BASECFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4)
-+#define LCDC_BASECFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4)
-+#define LCDC_BASECFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4)
-+#define LCDC_BASECFG1_CLUTMODE_OFFSET 8
-+#define LCDC_BASECFG1_CLUTMODE (0x3 << LCDC_BASECFG1_CLUTMODE_OFFSET)
-+#define LCDC_BASECFG1_CLUTMODE_1BPP (0x0 << 8)
-+#define LCDC_BASECFG1_CLUTMODE_2BPP (0x1 << 8)
-+#define LCDC_BASECFG1_CLUTMODE_4BPP (0x2 << 8)
-+#define LCDC_BASECFG1_CLUTMODE_8BPP (0x3 << 8)
-+
-+#define ATMEL_LCDC_BASECFG2 0x0074
-+
-+#define ATMEL_LCDC_BASECFG3 0x0078
-+#define LCDC_BASECFG3_BDEF_OFFSET 0
-+#define LCDC_BASECFG3_BDEF (0xff << LCDC_BASECFG3_BDEF_OFFSET)
-+#define LCDC_BASECFG3_GDEF_OFFSET 8
-+#define LCDC_BASECFG3_GDEF (0xff << LCDC_BASECFG3_GDEF_OFFSET)
-+#define LCDC_BASECFG3_RDEF_OFFSET 16
-+#define LCDC_BASECFG3_RDEF (0xff << LCDC_BASECFG3_RDEF_OFFSET)
-+
-+#define ATMEL_LCDC_BASECFG4 0x007C
-+#define LCDC_BASECFG4_DMA (0x1 << 8)
-+#define LCDC_BASECFG4_REP (0x1 << 9)
-+
-+#define ATMEL_LCDC_OVRCHER1 0x0100
-+#define LCDC_OVRCHER1_CHEN (0x1 << 0)
-+#define LCDC_OVRCHER1_UPDATEEN (0x1 << 1)
-+#define LCDC_OVRCHER1_A2QEN (0x1 << 2)
-+
-+#define ATMEL_LCDC_OVRCHDR1 0x0104
-+#define LCDC_OVRCHDR1_CHDIS (0x1 << 0)
-+#define LCDC_OVRCHDR1_CHRST (0x1 << 8)
-+
-+#define ATMEL_LCDC_OVRCHSR1 0x0108
-+#define LCDC_OVRCHSR1_CHSR (0x1 << 0)
-+#define LCDC_OVRCHSR1_UPDATESR (0x1 << 1)
-+#define LCDC_OVRCHSR1_A2QSR (0x1 << 2)
-+
-+#define ATMEL_LCDC_OVRIER1 0x010C
-+#define LCDC_OVRIER1_DMA (0x1 << 2)
-+#define LCDC_OVRIER1_DSCR (0x1 << 3)
-+#define LCDC_OVRIER1_ADD (0x1 << 4)
-+#define LCDC_OVRIER1_DONE (0x1 << 5)
-+#define LCDC_OVRIER1_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_OVRIDR1 0x0110
-+#define LCDC_OVRIDR1_DMA (0x1 << 2)
-+#define LCDC_OVRIDR1_DSCR (0x1 << 3)
-+#define LCDC_OVRIDR1_ADD (0x1 << 4)
-+#define LCDC_OVRIDR1_DONE (0x1 << 5)
-+#define LCDC_OVRIDR1_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_OVRIMR1 0x0114
-+#define LCDC_OVRIMR1_DMA (0x1 << 2)
-+#define LCDC_OVRIMR1_DSCR (0x1 << 3)
-+#define LCDC_OVRIMR1_ADD (0x1 << 4)
-+#define LCDC_OVRIMR1_DONE (0x1 << 5)
-+#define LCDC_OVRIMR1_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_OVRISR1 0x0118
-+#define LCDC_OVRISR1_DMA (0x1 << 2)
-+#define LCDC_OVRISR1_DSCR (0x1 << 3)
-+#define LCDC_OVRISR1_ADD (0x1 << 4)
-+#define LCDC_OVRISR1_DONE (0x1 << 5)
-+#define LCDC_OVRISR1_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_OVRHEAD1 0x011C
-+
-+#define ATMEL_LCDC_OVRADDR1 0x0120
-+
-+#define ATMEL_LCDC_OVRCTRL1 0x0124
-+#define LCDC_OVRCTRL1_DFETCH (0x1 << 0)
-+#define LCDC_OVRCTRL1_LFETCH (0x1 << 1)
-+#define LCDC_OVRCTRL1_DMAIEN (0x1 << 2)
-+#define LCDC_OVRCTRL1_DSCRIEN (0x1 << 3)
-+#define LCDC_OVRCTRL1_ADDIEN (0x1 << 4)
-+#define LCDC_OVRCTRL1_DONEIEN (0x1 << 5)
-+
-+#define ATMEL_LCDC_OVRNEXT1 0x0128
-+
-+#define ATMEL_LCDC_OVR1CFG0 0x012C
-+#define LCDC_OVR1CFG0_BLEN_OFFSET 4
-+#define LCDC_OVR1CFG0_BLEN (0x3 << LCDC_OVR1CFG0_BLEN_OFFSET)
-+#define LCDC_OVR1CFG0_BLEN_AHB_SINGLE (0x0 << 4)
-+#define LCDC_OVR1CFG0_BLEN_AHB_INCR4 (0x1 << 4)
-+#define LCDC_OVR1CFG0_BLEN_AHB_INCR8 (0x2 << 4)
-+#define LCDC_OVR1CFG0_BLEN_AHB_INCR16 (0x3 << 4)
-+#define LCDC_OVR1CFG0_DLBO (0x1 << 8)
-+#define LCDC_OVR1CFG0_ROTDIS (0x1 << 12)
-+#define LCDC_OVR1CFG0_LOCKDIS (0x1 << 13)
-+
-+#define ATMEL_LCDC_OVR1CFG1 0x0130
-+#define LCDC_OVR1CFG1_CLUTEN (0x1 << 0)
-+#define LCDC_OVR1CFG1_RGBMODE_OFFSET 4
-+#define LCDC_OVR1CFG1_RGBMODE (0xf << LCDC_OVR1CFG1_RGBMODE_OFFSET)
-+#define LCDC_OVR1CFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4)
-+#define LCDC_OVR1CFG1_CLUTMODE_OFFSET 8
-+#define LCDC_OVR1CFG1_CLUTMODE (0x3 << LCDC_OVR1CFG1_CLUTMODE_OFFSET)
-+#define LCDC_OVR1CFG1_CLUTMODE_1BPP (0x0 << 8)
-+#define LCDC_OVR1CFG1_CLUTMODE_2BPP (0x1 << 8)
-+#define LCDC_OVR1CFG1_CLUTMODE_4BPP (0x2 << 8)
-+#define LCDC_OVR1CFG1_CLUTMODE_8BPP (0x3 << 8)
-+
-+#define ATMEL_LCDC_OVR1CFG2 0x0134
-+#define LCDC_OVR1CFG2_XOFFSET_OFFSET 0
-+#define LCDC_OVR1CFG2_XOFFSET (0x7ff << LCDC_OVR1CFG2_XOFFSET_OFFSET)
-+#define LCDC_OVR1CFG2_YOFFSET_OFFSET 16
-+#define LCDC_OVR1CFG2_YOFFSET (0x7ff << LCDC_OVR1CFG2_YOFFSET_OFFSET)
-+
-+#define ATMEL_LCDC_OVR1CFG3 0x0138
-+#define LCDC_OVR1CFG3_XSIZE_OFFSET 0
-+#define LCDC_OVR1CFG3_XSIZE (0x7ff << LCDC_OVR1CFG3_XSIZE_OFFSET)
-+#define LCDC_OVR1CFG3_YSIZE_OFFSET 16
-+#define LCDC_OVR1CFG3_YSIZE (0x7ff << LCDC_OVR1CFG3_YSIZE_OFFSET)
-+
-+#define ATMEL_LCDC_OVR1CFG4 0x013C
-+
-+#define ATMEL_LCDC_OVR1CFG5 0x0140
-+
-+#define ATMEL_LCDC_OVR1CFG6 0x0144
-+#define LCDC_OVR1CFG6_BDEF_OFFSET 0
-+#define LCDC_OVR1CFG6_BDEF (0xff << LCDC_OVR1CFG6_BDEF_OFFSET)
-+#define LCDC_OVR1CFG6_GDEF_OFFSET 8
-+#define LCDC_OVR1CFG6_GDEF (0xff << LCDC_OVR1CFG6_GDEF_OFFSET)
-+#define LCDC_OVR1CFG6_RDEF_OFFSET 16
-+#define LCDC_OVR1CFG6_RDEF (0xff << LCDC_OVR1CFG6_RDEF_OFFSET)
-+
-+#define ATMEL_LCDC_OVR1CFG7 0x0148
-+#define LCDC_OVR1CFG7_BKEY_OFFSET 0
-+#define LCDC_OVR1CFG7_BKEY (0xff << LCDC_OVR1CFG7_BKEY_OFFSET)
-+#define LCDC_OVR1CFG7_GKEY_OFFSET 8
-+#define LCDC_OVR1CFG7_GKEY (0xff << LCDC_OVR1CFG7_GKEY_OFFST)
-+#define LCDC_OVR1CFG7_RKEY_OFFSET 16
-+#define LCDC_OVR1CFG7_RKEY (0xff << LCDC_OVR1CFG7_RKEY_OFFSET)
-+
-+#define ATMEL_LCDC_OVR1CFG8 0x014C
-+#define LCDC_OVR1CFG8_BMASK_OFFSET 0
-+#define LCDC_OVR1CFG8_BMASK (0xff << LCDC_OVR1CFG8_BMASK_OFFSET)
-+#define LCDC_OVR1CFG8_GMASK_OFFSET 8
-+#define LCDC_OVR1CFG8_GMASK (0xff << LCDC_OVR1CFG8_GMASK_OFFSET)
-+#define LCDC_OVR1CFG8_RMASK_OFFSET 16
-+#define LCDC_OVR1CFG8_RMASK (0xff << LCDC_OVR1CFG8_RMASK_OFFSET)
-+
-+#define ATMEL_LCDC_OVR1CFG9 0x0150
-+#define LCDC_OVR1CFG9_CRKEY (0x1 << 0)
-+#define LCDC_OVR1CFG9_INV (0x1 << 1)
-+#define LCDC_OVR1CFG9_ITER2BL (0x1 << 2)
-+#define LCDC_OVR1CFG9_ITER (0x1 << 3)
-+#define LCDC_OVR1CFG9_REVALPHA (0x1 << 4)
-+#define LCDC_OVR1CFG9_GAEN (0x1 << 5)
-+#define LCDC_OVR1CFG9_LAEN (0x1 << 6)
-+#define LCDC_OVR1CFG9_OVR (0x1 << 7)
-+#define LCDC_OVR1CFG9_DMA (0x1 << 8)
-+#define LCDC_OVR1CFG9_REP (0x1 << 9)
-+#define LCDC_OVR1CFG9_DSTKEY (0x1 << 10)
-+#define LCDC_OVR1CFG9_GA_OFFSET 16
-+#define LCDC_OVR1CFG9_GA (0xff << LCDC_OVR1CFG9_GA_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCHER 0x0280
-+#define LCDC_HEOCHER_CHEN (0x1 << 0)
-+#define LCDC_HEOCHER_UPDATEEN (0x1 << 1)
-+#define LCDC_HEOCHER_A2QEN (0x1 << 2)
-+
-+#define ATMEL_LCDC_HEOCHDR 0x0284
-+#define LCDC_HEOCHDR_CHDIS (0x1 << 0)
-+#define LCDC_HEOCHDR_CHRST (0x1 << 8)
-+
-+#define ATMEL_LCDC_HEOCHSR 0x0288
-+#define LCDC_HEOCHSR_CHSR (0x1 << 0)
-+#define LCDC_HEOCHSR_UPDATESR (0x1 << 1)
-+#define LCDC_HEOCHSR_A2QSR (0x1 << 2)
-+
-+#define ATMEL_LCDC_HEOIER 0x028C
-+#define LCDC_HEOIER_DMA (0x1 << 2)
-+#define LCDC_HEOIER_DSCR (0x1 << 3)
-+#define LCDC_HEOIER_ADD (0x1 << 4)
-+#define LCDC_HEOIER_DONE (0x1 << 5)
-+#define LCDC_HEOIER_OVR (0x1 << 6)
-+#define LCDC_HEOIER_UDMA (0x1 << 10)
-+#define LCDC_HEOIER_UDSCR (0x1 << 11)
-+#define LCDC_HEOIER_UADD (0x1 << 12)
-+#define LCDC_HEOIER_UDONE (0x1 << 13)
-+#define LCDC_HEOIER_UOVR (0x1 << 14)
-+#define LCDC_HEOIER_VDMA (0x1 << 18)
-+#define LCDC_HEOIER_VDSCR (0x1 << 19)
-+#define LCDC_HEOIER_VADD (0x1 << 20)
-+#define LCDC_HEOIER_VDONE (0x1 << 21)
-+#define LCDC_HEOIER_VOVR (0x1 << 22)
-+
-+#define ATMEL_LCDC_HEOIDR 0x0290
-+#define LCDC_HEOIDR_DMA (0x1 << 2)
-+#define LCDC_HEOIDR_DSCR (0x1 << 3)
-+#define LCDC_HEOIDR_ADD (0x1 << 4)
-+#define LCDC_HEOIDR_DONE (0x1 << 5)
-+#define LCDC_HEOIDR_OVR (0x1 << 6)
-+#define LCDC_HEOIDR_UDMA (0x1 << 10)
-+#define LCDC_HEOIDR_UDSCR (0x1 << 11)
-+#define LCDC_HEOIDR_UADD (0x1 << 12)
-+#define LCDC_HEOIDR_UDONE (0x1 << 13)
-+#define LCDC_HEOIDR_UOVR (0x1 << 14)
-+#define LCDC_HEOIDR_VDMA (0x1 << 18)
-+#define LCDC_HEOIDR_VDSCR (0x1 << 19)
-+#define LCDC_HEOIDR_VADD (0x1 << 20)
-+#define LCDC_HEOIDR_VDONE (0x1 << 21)
-+#define LCDC_HEOIDR_VOVR (0x1 << 22)
-+
-+#define ATMEL_LCDC_HEOIMR 0x0294
-+#define LCDC_HEOIMR_DMA (0x1 << 2)
-+#define LCDC_HEOIMR_DSCR (0x1 << 3)
-+#define LCDC_HEOIMR_ADD (0x1 << 4)
-+#define LCDC_HEOIMR_DONE (0x1 << 5)
-+#define LCDC_HEOIMR_OVR (0x1 << 6)
-+#define LCDC_HEOIMR_UDMA (0x1 << 10)
-+#define LCDC_HEOIMR_UDSCR (0x1 << 11)
-+#define LCDC_HEOIMR_UADD (0x1 << 12)
-+#define LCDC_HEOIMR_UDONE (0x1 << 13)
-+#define LCDC_HEOIMR_UOVR (0x1 << 14)
-+#define LCDC_HEOIMR_VDMA (0x1 << 18)
-+#define LCDC_HEOIMR_VDSCR (0x1 << 19)
-+#define LCDC_HEOIMR_VADD (0x1 << 20)
-+#define LCDC_HEOIMR_VDONE (0x1 << 21)
-+#define LCDC_HEOIMR_VOVR (0x1 << 22)
-+
-+#define ATMEL_LCDC_HEOISR 0x0298
-+#define LCDC_HEOISR_DMA (0x1 << 2)
-+#define LCDC_HEOISR_DSCR (0x1 << 3)
-+#define LCDC_HEOISR_ADD (0x1 << 4)
-+#define LCDC_HEOISR_DONE (0x1 << 5)
-+#define LCDC_HEOISR_OVR (0x1 << 6)
-+#define LCDC_HEOISR_UDMA (0x1 << 10)
-+#define LCDC_HEOISR_UDSCR (0x1 << 11)
-+#define LCDC_HEOISR_UADD (0x1 << 12)
-+#define LCDC_HEOISR_UDONE (0x1 << 13)
-+#define LCDC_HEOISR_UOVR (0x1 << 14)
-+#define LCDC_HEOISR_VDMA (0x1 << 18)
-+#define LCDC_HEOISR_VDSCR (0x1 << 19)
-+#define LCDC_HEOISR_VADD (0x1 << 20)
-+#define LCDC_HEOISR_VDONE (0x1 << 21)
-+#define LCDC_HEOISR_VOVR (0x1 << 22)
-+
-+#define ATMEL_LCDC_HEOHEAD 0x029C
-+
-+#define ATMEL_LCDC_HEOADDR 0x02A0
-+
-+#define ATMEL_LCDC_HEOCTRL 0x02A4
-+#define LCDC_HEOCTRL_DFETCH (0x1 << 0)
-+#define LCDC_HEOCTRL_LFETCH (0x1 << 1)
-+#define LCDC_HEOCTRL_DMAIEN (0x1 << 2)
-+#define LCDC_HEOCTRL_DSCRIEN (0x1 << 3)
-+#define LCDC_HEOCTRL_ADDIEN (0x1 << 4)
-+#define LCDC_HEOCTRL_DONEIEN (0x1 << 5)
-+
-+#define ATMEL_LCDC_HEONEXT 0x02A8
-+
-+#define ATMEL_LCDC_HEOUHEAD 0x02AC
-+
-+#define ATMEL_LCDC_HEOUADDR 0x02B0
-+
-+#define ATMEL_LCDC_HEOUCTRL 0x02B4
-+#define LCDC_HEOUCTRL_UDFETCH (0x1 << 0)
-+#define LCDC_HEOUCTRL_UDMAIEN (0x1 << 2)
-+#define LCDC_HEOUCTRL_UDSCRIEN (0x1 << 3)
-+#define LCDC_HEOUCTRL_UADDIEN (0x1 << 4)
-+#define LCDC_HEOUCTRL_UDONEIEN (0x1 << 5)
-+
-+#define ATMEL_LCDC_HEOUNEXT 0x02B8
-+
-+#define ATMEL_LCDC_HEOVHEAD 0x02BC
-+
-+#define ATMEL_LCDC_HEOVADDR 0x02C0
-+
-+#define ATMEL_LCDC_HEOVCTRL 0x02C4
-+#define LCDC_HEOVCTRL_VDFETCH (0x1 << 0)
-+#define LCDC_HEOVCTRL_VDMAIEN (0x1 << 2)
-+#define LCDC_HEOVCTRL_VDSCRIEN (0x1 << 3)
-+#define LCDC_HEOVCTRL_VADDIEN (0x1 << 4)
-+#define LCDC_HEOVCTRL_VDONEIEN (0x1 << 5)
-+
-+#define ATMEL_LCDC_HEOVNEXT 0x02C8
-+
-+#define ATMEL_LCDC_HEOCFG0 0x02CC
-+#define LCDC_HEOCFG0_BLEN_OFFSET 4
-+#define LCDC_HEOCFG0_BLEN (0x3 << LCDC_HEOCFG0_BLEN_OFFSET)
-+#define LCDC_HEOCFG0_BLEN_AHB_SINGLE (0x0 << 4)
-+#define LCDC_HEOCFG0_BLEN_AHB_INCR4 (0x1 << 4)
-+#define LCDC_HEOCFG0_BLEN_AHB_INCR8 (0x2 << 4)
-+#define LCDC_HEOCFG0_BLEN_AHB_INCR16 (0x3 << 4)
-+#define LCDC_HEOCFG0_BLENUV_OFFSET 6
-+#define LCDC_HEOCFG0_BLENUV (0x3 << LCDC_HEOCFG0_BLENUV_OFFSET)
-+#define LCDC_HEOCFG0_BLENUV_AHB_SINGLE (0x0 << 6)
-+#define LCDC_HEOCFG0_BLENUV_AHB_INCR4 (0x1 << 6)
-+#define LCDC_HEOCFG0_BLENUV_AHB_INCR8 (0x2 << 6)
-+#define LCDC_HEOCFG0_BLENUV_AHB_INCR16 (0x3 << 6)
-+#define LCDC_HEOCFG0_DLBO (0x1 << 8)
-+#define LCDC_HEOCFG0_ROTDIS (0x1 << 12)
-+#define LCDC_HEOCFG0_LOCKDIS (0x1 << 13)
-+
-+#define ATMEL_LCDC_HEOCFG1 0x02D0
-+#define LCDC_HEOCFG1_CLUTEN (0x1 << 0)
-+#define LCDC_HEOCFG1_YUVEN (0x1 << 1)
-+#define LCDC_HEOCFG1_RGBMODE_OFFSET 4
-+#define LCDC_HEOCFG1_RGBMODE (0xf << LCDC_HEOCFG1_RGBMODE_OFFSET)
-+#define LCDC_HEOCFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4)
-+#define LCDC_HEOCFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4)
-+#define LCDC_HEOCFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4)
-+#define LCDC_HEOCFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4)
-+#define LCDC_HEOCFG1_CLUTMODE_OFFSET 8
-+#define LCDC_HEOCFG1_CLUTMODE (0x3 << LCDC_HEOCFG1_CLUTMODE_OFFSET)
-+#define LCDC_HEOCFG1_CLUTMODE_1BPP (0x0 << 8)
-+#define LCDC_HEOCFG1_CLUTMODE_2BPP (0x1 << 8)
-+#define LCDC_HEOCFG1_CLUTMODE_4BPP (0x2 << 8)
-+#define LCDC_HEOCFG1_CLUTMODE_8BPP (0x3 << 8)
-+#define LCDC_HEOCFG1_YUVMODE_OFFSET 12
-+#define LCDC_HEOCFG1_YUVMODE (0xf << LCDC_HEOCFG1_YUVMODE_OFFSET)
-+#define LCDC_HEOCFG1_YUVMODE_32BPP_AYCBCR (0x0 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE0 (0x1 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE1 (0x2 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE2 (0x3 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE3 (0x4 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_SEMIPLANAR (0x5 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_PLANAR (0x6 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_12BPP_YCBCR_SEMIPLANAR (0x7 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_12BPP_YCBCR_PLANAR (0x8 << 12)
-+#define LCDC_HEOCFG1_YUV422ROT (0x1 << 16)
-+#define LCDC_HEOCFG1_YUV422SWP (0x1 << 17)
-+
-+#define ATMEL_LCDC_HEOCFG2 0x02D4
-+#define LCDC_HEOCFG2_XOFFSET_OFFSET 0
-+#define LCDC_HEOCFG2_XOFFSET (0x7ff << LCDC_HEOCFG2_XOFFSET_OFFSET)
-+#define LCDC_HEOCFG2_YOFFSET_OFFSET 16
-+#define LCDC_HEOCFG2_YOFFSET (0x7ff << LCDC_HEOCFG2_YOFFSET_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCFG3 0x02D8
-+#define LCDC_HEOCFG3_XSIZE_OFFSET 0
-+#define LCDC_HEOCFG3_XSIZE (0x7ff << LCDC_HEOCFG3_XSIZE_OFFSET)
-+#define LCDC_HEOCFG3_YSIZE_OFFSET 16
-+#define LCDC_HEOCFG3_YSIZE (0x7ff << LCDC_HEOCFG3_YSIZE_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCFG4 0x02DC
-+#define LCDC_HEOCFG4_XMEM_SIZE_OFFSET 0
-+#define LCDC_HEOCFG4_XMEM_SIZE (0x7ff << LCDC_HEOCFG4_XMEM_SIZE_OFFSET)
-+#define LCDC_HEOCFG4_YMEM_SIZE_OFFSET 16
-+#define LCDC_HEOCFG4_YMEM_SIZE (0x7ff << LCDC_HEOCFG4_YMEM_SIZE_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCFG5 0x02E0
-+
-+#define ATMEL_LCDC_HEOCFG6 0x02E4
-+
-+#define ATMEL_LCDC_HEOCFG7 0x02E8
-+
-+#define ATMEL_LCDC_HEOCFG8 0x02EC
-+
-+#define ATMEL_LCDC_HEOCFG9 0x02F0
-+#define LCDC_HEOCFG9_BDEF_OFFSET 0
-+#define LCDC_HEOCFG9_BDEF (0xff << LCDC_HEOCFG9_BDEF_OFFSET)
-+#define LCDC_HEOCFG9_GDEF_OFFSET 8
-+#define LCDC_HEOCFG9_GDEF (0xff << LCDC_HEOCFG9_GDEF_OFFSET)
-+#define LCDC_HEOCFG9_RDEF_OFFSET 16
-+#define LCDC_HEOCFG9_RDEF (0xff << LCDC_HEOCFG9_RDEF_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCFG10 0x02F4
-+#define LCDC_HEOCFG10_BKEY_OFFSET 0
-+#define LCDC_HEOCFG10_BKEY (0xff << LCDC_HEOCFG10_BKEY_OFFSET)
-+#define LCDC_HEOCFG10_GKEY_OFFSET 8
-+#define LCDC_HEOCFG10_GKEY (0xff << LCDC_HEOCFG10_GKEY_OFFSET)
-+#define LCDC_HEOCFG10_RKEY_OFFSET 16
-+#define LCDC_HEOCFG10_RKEY (0xff << LCDC_HEOCFG10_RKEY_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCFG11 0x02F8
-+#define LCDC_HEOCFG11_BMASK_OFFSET 0
-+#define LCDC_HEOCFG11_BMASK (0xff << LCDC_HEOCFG11_BMASK_OFFSET)
-+#define LCDC_HEOCFG11_GMASK_OFFSET 8
-+#define LCDC_HEOCFG11_GMASK (0xff << LCDC_HEOCFG11_GMASK_OFFSET)
-+#define LCDC_HEOCFG11_RMASK_OFFSET 16
-+#define LCDC_HEOCFG11_RMASK (0xff << LCDC_HEOCFG11_RMASK_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCFG12 0x02FC
-+#define LCDC_HEOCFG12_CRKEY (0x1 << 0)
-+#define LCDC_HEOCFG12_INV (0x1 << 1)
-+#define LCDC_HEOCFG12_ITER2BL (0x1 << 2)
-+#define LCDC_HEOCFG12_ITER (0x1 << 3)
-+#define LCDC_HEOCFG12_REVALPHA (0x1 << 4)
-+#define LCDC_HEOCFG12_GAEN (0x1 << 5)
-+#define LCDC_HEOCFG12_LAEN (0x1 << 6)
-+#define LCDC_HEOCFG12_OVR (0x1 << 7)
-+#define LCDC_HEOCFG12_DMA (0x1 << 8)
-+#define LCDC_HEOCFG12_REP (0x1 << 9)
-+#define LCDC_HEOCFG12_DSTKEY (0x1 << 10)
-+#define LCDC_HEOCFG12_VIDPRI (0x1 << 12)
-+#define LCDC_HEOCFG12_GA_OFFSET 16
-+#define LCDC_HEOCFG12_GA (0xff << LCDC_HEOCFG12_GA_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCFG13 0x0300
-+#define LCDC_HEOCFG13_XFACTOR_OFFSET 0
-+#define LCDC_HEOCFG13_XFACTOR (0x1fff << LCDC_HEOCFG13_XFACTOR_OFFSET)
-+#define LCDC_HEOCFG13_YFACTOR_OFFSET 16
-+#define LCDC_HEOCFG13_YFACTOR (0x1fff << LCDC_HEOCFG13_YFACTOR_OFFSET)
-+#define LCDC_HEOCFG13_SCALEN (0x1 << 31)
-+
-+#define ATMEL_LCDC_HEOCFG14 0x0304
-+#define LCDC_HEOCFG14_CSCRY_OFFSET 0
-+#define LCDC_HEOCFG14_CSCRY (0x3ff << LCDC_HEOCFG14_CSCRY_OFFSET)
-+#define LCDC_HEOCFG14_CSCRU_OFFSET 10
-+#define LCDC_HEOCFG14_CSCRU (0x3ff << LCDC_HEOCFG14_CSCRU_OFFSET)
-+#define LCDC_HEOCFG14_CSCRV_OFFSET 20
-+#define LCDC_HEOCFG14_CSCRV (0x3ff << LCDC_HEOCFG14_CSCRV_OFFSET)
-+#define LCDC_HEOCFG14_CSCYOFF (0x1 << 30)
-+
-+#define ATMEL_LCDC_HEOCFG15 0x0308
-+#define LCDC_HEOCFG15_CSCGY_OFFSET 0
-+#define LCDC_HEOCFG15_CSCGY (0x3ff << LCDC_HEOCFG15_CSCGY_OFFSET)
-+#define LCDC_HEOCFG15_CSCGU_OFFSET 10
-+#define LCDC_HEOCFG15_CSCGU (0x3ff << LCDC_HEOCFG15_CSCGU_OFFSET)
-+#define LCDC_HEOCFG15_CSCGV_OFFSET 20
-+#define LCDC_HEOCFG15_CSCGV (0x3ff << LCDC_HEOCFG15_CSCGV_OFFSET)
-+#define LCDC_HEOCFG15_CSCUOFF (0x1 << 30)
-+
-+#define ATMEL_LCDC_HEOCFG16 0x030C
-+#define LCDC_HEOCFG16_CSCBY_OFFSET 0
-+#define LCDC_HEOCFG16_CSCBY (0x3ff << LCDC_HEOCFG16_CSCBY_OFFSET)
-+#define LCDC_HEOCFG16_CSCBU_OFFSET 10
-+#define LCDC_HEOCFG16_CSCBU (0x3ff << LCDC_HEOCFG16_CSCBU_OFFSET)
-+#define LCDC_HEOCFG16_CSCBV_OFFSET 20
-+#define LCDC_HEOCFG16_CSCBV (0x3ff << LCDC_HEOCFG16_CSCBV_OFFSET)
-+#define LCDC_HEOCFG16_CSCVOFF (0x1 << 30)
-+
-+#define ATMEL_LCDC_HCRCHER 0x0340
-+#define LCDC_HCRCHER_CHEN (0x1 << 0)
-+#define LCDC_HCRCHER_UPDATEEN (0x1 << 1)
-+#define LCDC_HCRCHER_A2QEN (0x1 << 2)
-+
-+#define ATMEL_LCDC_HCRCHDR 0x0344
-+#define LCDC_HCRCHDR_CHDIS (0x1 << 0)
-+#define LCDC_HCRCHDR_CHRST (0x1 << 8)
-+
-+#define ATMEL_LCDC_HCRCHSR 0x0348
-+#define LCDC_HCRCHSR_CHSR (0x1 << 0)
-+#define LCDC_HCRCHSR_UPDATESR (0x1 << 1)
-+#define LCDC_HCRCHSR_A2QSR (0x1 << 2)
-+
-+#define ATMEL_LCDC_HCRIER 0x034C
-+#define LCDC_HCRIER_DMA (0x1 << 2)
-+#define LCDC_HCRIER_DSCR (0x1 << 3)
-+#define LCDC_HCRIER_ADD (0x1 << 4)
-+#define LCDC_HCRIER_DONE (0x1 << 5)
-+#define LCDC_HCRIER_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_HCRIDR 0x0350
-+#define LCDC_HCRIDR_DMA (0x1 << 2)
-+#define LCDC_HCRIDR_DSCR (0x1 << 3)
-+#define LCDC_HCRIDR_ADD (0x1 << 4)
-+#define LCDC_HCRIDR_DONE (0x1 << 5)
-+#define LCDC_HCRIDR_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_HCRIMR 0x0354
-+#define LCDC_HCRIMR_DMA (0x1 << 2)
-+#define LCDC_HCRIMR_DSCR (0x1 << 3)
-+#define LCDC_HCRIMR_ADD (0x1 << 4)
-+#define LCDC_HCRIMR_DONE (0x1 << 5)
-+#define LCDC_HCRIMR_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_HCRISR 0x0358
-+#define LCDC_HCRISR_DMA (0x1 << 2)
-+#define LCDC_HCRISR_DSCR (0x1 << 3)
-+#define LCDC_HCRISR_ADD (0x1 << 4)
-+#define LCDC_HCRISR_DONE (0x1 << 5)
-+#define LCDC_HCRISR_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_HCRHEAD 0x035C
-+
-+#define ATMEL_LCDC_HCRADDR 0x0360
-+
-+#define ATMEL_LCDC_HCRCTRL 0x0364
-+#define LCDC_HCRCTRL_DFETCH (0x1 << 0)
-+#define LCDC_HCRCTRL_LFETCH (0x1 << 1)
-+#define LCDC_HCRCTRL_DMAIEN (0x1 << 2)
-+#define LCDC_HCRCTRL_DSCRIEN (0x1 << 3)
-+#define LCDC_HCRCTRL_ADDIEN (0x1 << 4)
-+#define LCDC_HCRCTRL_DONEIEN (0x1 << 5)
-+
-+#define ATMEL_LCDC_HCRNEXT 0x0368
-+
-+#define ATMEL_LCDC_HCRCFG0 0x036C
-+#define LCDC_HCRCFG0_BLEN_OFFSET 4
-+#define LCDC_HCRCFG0_BLEN (0x3 << LCDC_HCRCFG0_BLEN_OFFSET)
-+#define LCDC_HCRCFG0_BLEN_AHB_SINGLE (0x0 << 4)
-+#define LCDC_HCRCFG0_BLEN_AHB_INCR4 (0x1 << 4)
-+#define LCDC_HCRCFG0_BLEN_AHB_INCR8 (0x2 << 4)
-+#define LCDC_HCRCFG0_BLEN_AHB_INCR16 (0x3 << 4)
-+#define LCDC_HCRCFG0_DLBO (0x1 << 8)
-+
-+#define ATMEL_LCDC_HCRCFG1 0x0370
-+#define LCDC_HCRCFG1_CLUTEN (0x1 << 0)
-+#define LCDC_HCRCFG1_RGBMODE_OFFSET 4
-+#define LCDC_HCRCFG1_RGBMODE (0xf << LCDC_HCRCFG1_RGBMODE_OFFSET)
-+#define LCDC_HCRCFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4)
-+#define LCDC_HCRCFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4)
-+#define LCDC_HCRCFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4)
-+#define LCDC_HCRCFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4)
-+#define LCDC_HCRCFG1_CLUTMODE_OFFSET 8
-+#define LCDC_HCRCFG1_CLUTMODE (0x3 << LCDC_HCRCFG1_CLUTMODE_OFFSET)
-+#define LCDC_HCRCFG1_CLUTMODE_1BPP (0x0 << 8)
-+#define LCDC_HCRCFG1_CLUTMODE_2BPP (0x1 << 8)
-+#define LCDC_HCRCFG1_CLUTMODE_4BPP (0x2 << 8)
-+#define LCDC_HCRCFG1_CLUTMODE_8BPP (0x3 << 8)
-+
-+#define ATMEL_LCDC_HCRCFG2 0x0374
-+#define LCDC_HCRCFG2_XOFFSET_OFFSET 0
-+#define LCDC_HCRCFG2_XOFFSET (0x7ff << LCDC_HCRCFG2_XOFFSET_OFFSET)
-+#define LCDC_HCRCFG2_YOFFSET_OFFSET 16
-+#define LCDC_HCRCFG2_YOFFSET (0x7ff << LCDC_HCRCFG2_YOFFSET_OFFSET)
-+
-+#define ATMEL_LCDC_HCRCFG3 0x0378
-+#define LCDC_HCRCFG3_XSIZE_OFFSET 0
-+#define LCDC_HCRCFG3_XSIZE (0x7f << LCDC_HCRCFG3_XSIZE_OFFSET)
-+#define LCDC_HCRCFG3_YSIZE_OFFSET 16
-+#define LCDC_HCRCFG3_YSIZE (0x7f << LCDC_HCRCFG3_YSIZE_OFFSET)
-+
-+#define ATMEL_LCDC_HCRCFG4 0x037C
-+
-+#define ATMEL_LCDC_HCRCFG6 0x0384
-+#define LCDC_HCRCFG6_BDEF_OFFSET 0
-+#define LCDC_HCRCFG6_BDEF (0xff << LCDC_HCRCFG6_BDEF_OFFSET)
-+#define LCDC_HCRCFG6_GDEF_OFFSET 8
-+#define LCDC_HCRCFG6_GDEF (0xff << LCDC_HCRCFG6_GDEF_OFFSET)
-+#define LCDC_HCRCFG6_RDEF_OFFSET 16
-+#define LCDC_HCRCFG6_RDEF (0xff << LCDC_HCRCFG6_RDEF_OFFSET)
-+
-+#define ATMEL_LCDC_HCRCFG7 0x0388
-+#define LCDC_HCRCFG7_BKEY_OFFSET 0
-+#define LCDC_HCRCFG7_BKEY (0xff << LCDC_HCRCFG7_BKEY_OFFSET)
-+#define LCDC_HCRCFG7_GKEY_OFFSET 8
-+#define LCDC_HCRCFG7_GKEY (0xff << LCDC_HCRCFG7_GKEY_OFFSET)
-+#define LCDC_HCRCFG7_RKEY_OFFSET 16
-+#define LCDC_HCRCFG7_RKEY (0xff << LCDC_HCRCFG7_RKEY_OFFSET)
-+
-+#define ATMEL_LCDC_HCRCFG8 0x038C
-+#define LCDC_HCRCFG8_BMASK_OFFSET 0
-+#define LCDC_HCRCFG8_BMASK (0xff << LCDC_HCRCFG8_BMASK_OFFSET)
-+#define LCDC_HCRCFG8_GMASK_OFFSET 8
-+#define LCDC_HCRCFG8_GMASK (0xff << LCDC_HCRCFG8_GMASK_OFFSET)
-+#define LCDC_HCRCFG8_RMASK_OFFSET 16
-+#define LCDC_HCRCFG8_RMASK (0xff << LCDC_HCRCFG8_RMASK_OFFSET)
-+
-+#define ATMEL_LCDC_HCRCFG9 0x0390
-+#define LCDC_HCRCFG9_CRKEY (0x1 << 0)
-+#define LCDC_HCRCFG9_INV (0x1 << 1)
-+#define LCDC_HCRCFG9_ITER2BL (0x1 << 2)
-+#define LCDC_HCRCFG9_ITER (0x1 << 3)
-+#define LCDC_HCRCFG9_REVALPHA (0x1 << 4)
-+#define LCDC_HCRCFG9_GAEN (0x1 << 5)
-+#define LCDC_HCRCFG9_LAEN (0x1 << 6)
-+#define LCDC_HCRCFG9_OVR (0x1 << 7)
-+#define LCDC_HCRCFG9_DMA (0x1 << 8)
-+#define LCDC_HCRCFG9_REP (0x1 << 9)
-+#define LCDC_HCRCFG9_DSTKEY (0x1 << 10)
-+#define LCDC_HCRCFG9_GA_OFFSET 16
-+#define LCDC_HCRCFG9_GA_Msk (0xff << LCDC_HCRCFG9_GA_OFFSET)
-+
-+#define ATMEL_LCDC_BASECLUT 0x400
-+#define LCDC_BASECLUT_BCLUT_OFFSET 0
-+#define LCDC_BASECLUT_BCLUT (0xff << LCDC_BASECLUT_BCLUT_OFFSET)
-+#define LCDC_BASECLUT_GCLUT_OFFSET 8
-+#define LCDC_BASECLUT_GCLUT (0xff << LCDC_BASECLUT_GCLUT_OFFSET)
-+#define LCDC_BASECLUT_RCLUT_OFFSET 16
-+#define LCDC_BASECLUT_RCLUT (0xff << LCDC_BASECLUT_RCLUT_OFFSET)
-+
-+#define ATMEL_LCDC_OVR1CLUT 0x800
-+#define LCDC_OVR1CLUT_BCLUT_OFFSET 0
-+#define LCDC_OVR1CLUT_BCLUT (0xff << LCDC_OVR1CLUT_BCLUT_OFFSET)
-+#define LCDC_OVR1CLUT_GCLUT_OFFSET 8
-+#define LCDC_OVR1CLUT_GCLUT (0xff << LCDC_OVR1CLUT_GCLUT_OFFSET)
-+#define LCDC_OVR1CLUT_RCLUT_OFFSET 16
-+#define LCDC_OVR1CLUT_RCLUT (0xff << LCDC_OVR1CLUT_RCLUT_OFFSET)
-+#define LCDC_OVR1CLUT_ACLUT_OFFSET 24
-+#define LCDC_OVR1CLUT_ACLUT (0xff << LCDC_OVR1CLUT_ACLUT_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCLUT 0x1000
-+#define LCDC_HEOCLUT_BCLUT_OFFSET 0
-+#define LCDC_HEOCLUT_BCLUT (0xff << LCDC_HEOCLUT_BCLUT_OFFSET)
-+#define LCDC_HEOCLUT_GCLUT_OFFSET 8
-+#define LCDC_HEOCLUT_GCLUT (0xff << LCDC_HEOCLUT_GCLUT_OFFSET)
-+#define LCDC_HEOCLUT_RCLUT_OFFSET 16
-+#define LCDC_HEOCLUT_RCLUT (0xff << LCDC_HEOCLUT_RCLUT_OFFSET)
-+#define LCDC_HEOCLUT_ACLUT_OFFSET 24
-+#define LCDC_HEOCLUT_ACLUT (0xff << LCDC_HEOCLUT_ACLUT_OFFSET)
-+
-+#define ATMEL_LCDC_HCRCLUT 0x1400
-+#define LCDC_HCRCLUT_BCLUT_OFFSET 0
-+#define LCDC_HCRCLUT_BCLUT (0xff << LCDC_HCRCLUT_BCLUT_OFFSET)
-+#define LCDC_HCRCLUT_GCLUT_OFFSET 8
-+#define LCDC_HCRCLUT_GCLUT (0xff << LCDC_HCRCLUT_GCLUT_OFFSET)
-+#define LCDC_HCRCLUT_RCLUT_OFFSET 16
-+#define LCDC_HCRCLUT_RCLUT (0xff << LCDC_HCRCLUT_RCLUT_OFFSET)
-+#define LCDC_HCRCLUT_ACLUT_OFFSET 24
-+#define LCDC_HCRCLUT_ACLUT (0xff << LCDC_HCRCLUT_ACLUT_OFFSET)
-+
-+/* Base layer CLUT */
-+#define ATMEL_LCDC_LUT(n) (0x0400 + ((n)*4))
-+
-+
-+#endif /* __ATMEL_HLCDC4_H__ */
---- a/drivers/video/atmel_lcdfb.c
-+++ b/drivers/video/atmel_lcdfb.c
-@@ -1,7 +1,7 @@
- /*
- * Driver for AT91/AT32 LCD Controller
- *
-- * Copyright (C) 2007 Atmel Corporation
-+ * Copyright (C) 2007-2010 Atmel Corporation
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
-@@ -25,6 +25,7 @@
- #include <asm/gpio.h>
-
- #include <video/atmel_lcdc.h>
-+#include <mach/atmel_hlcdfb.h>
-
- #define lcdc_readl(sinfo, reg) __raw_readl((sinfo)->mmio+(reg))
- #define lcdc_writel(sinfo, reg, val) __raw_writel((val), (sinfo)->mmio+(reg))
-@@ -76,6 +77,9 @@ static u32 contrast_ctr = ATMEL_LCDC_PS_
- | ATMEL_LCDC_POL_POSITIVE
- | ATMEL_LCDC_ENA_PWMENABLE;
-
-+static const u32 contrast_pwm_ctr = LCDC_LCDCFG6_PWMPOL
-+ | (ATMEL_LCDC_CVAL_DEFAULT << LCDC_LCDCFG6_PWMCVAL_OFFSET);
-+
- #ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
-
- /* some bl->props field just changed */
-@@ -84,6 +88,7 @@ static int atmel_bl_update_status(struct
- struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
- int power = sinfo->bl_power;
- int brightness = bl->props.brightness;
-+ u32 reg;
-
- /* REVISIT there may be a meaningful difference between
- * fb_blank and power ... there seem to be some cases
-@@ -94,17 +99,28 @@ static int atmel_bl_update_status(struct
- else if (bl->props.power != sinfo->bl_power)
- power = bl->props.power;
-
-- if (brightness < 0 && power == FB_BLANK_UNBLANK)
-- brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
-- else if (power != FB_BLANK_UNBLANK)
-+ if (brightness < 0 && power == FB_BLANK_UNBLANK) {
-+ if (cpu_is_at91sam9x5())
-+ brightness = lcdc_readl(sinfo, ATMEL_LCDC_LCDCFG6)
-+ >> LCDC_LCDCFG6_PWMCVAL_OFFSET;
-+ else
-+ brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
-+ } else if (power != FB_BLANK_UNBLANK) {
- brightness = 0;
-+ }
-
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
-- if (contrast_ctr & ATMEL_LCDC_POL_POSITIVE)
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
-- brightness ? contrast_ctr : 0);
-- else
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
-+ if (cpu_is_at91sam9x5()) {
-+ reg = lcdc_readl(sinfo, ATMEL_LCDC_LCDCFG6) & ~LCDC_LCDCFG6_PWMCVAL;
-+ reg |= brightness << LCDC_LCDCFG6_PWMCVAL_OFFSET;
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG6, reg);
-+ } else {
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
-+ if (contrast_ctr & ATMEL_LCDC_POL_POSITIVE)
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
-+ brightness ? contrast_ctr : 0);
-+ else
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
-+ }
-
- bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;
-
-@@ -115,7 +131,10 @@ static int atmel_bl_get_brightness(struc
- {
- struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
-
-- return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
-+ if (cpu_is_at91sam9x5())
-+ return lcdc_readl(sinfo, ATMEL_LCDC_LCDCFG6) >> LCDC_LCDCFG6_PWMCVAL_OFFSET;
-+ else
-+ return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
- }
-
- static const struct backlight_ops atmel_lcdc_bl_ops = {
-@@ -171,14 +190,17 @@ static void exit_backlight(struct atmel_
-
- static void init_contrast(struct atmel_lcdfb_info *sinfo)
- {
-- /* contrast pwm can be 'inverted' */
-- if (sinfo->lcdcon_pol_negative)
-- contrast_ctr &= ~(ATMEL_LCDC_POL_POSITIVE);
--
-- /* have some default contrast/backlight settings */
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
--
-+ if (cpu_is_at91sam9x5()) {
-+ /* have some default contrast/backlight settings */
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG6, contrast_pwm_ctr);
-+ } else {
-+ /* contrast pwm can be 'inverted' */
-+ if (sinfo->lcdcon_pol_negative)
-+ contrast_ctr &= ~(ATMEL_LCDC_POL_POSITIVE);
-+ /* have some default contrast/backlight settings */
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
-+ }
- if (sinfo->lcdcon_is_backlight)
- init_backlight(sinfo);
- }
-@@ -220,32 +242,78 @@ static unsigned long compute_hozval(unsi
-
- static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo)
- {
-- /* Turn off the LCD controller and the DMA controller */
-- lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-- sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
--
-- /* Wait for the LCDC core to become idle */
-- while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
-- msleep(10);
-+ if (cpu_is_at91sam9x5()) {
-+ /* Disable DISP signal */
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_DISPDIS);
-+ while ((lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_DISPSTS))
-+ msleep(1);
-+ /* Disable synchronization */
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_SYNCDIS);
-+ while ((lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_LCDSTS))
-+ msleep(1);
-+ /* Disable pixel clock */
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_CLKDIS);
-+ while ((lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_CLKSTS))
-+ msleep(1);
-+ /* Disable PWM */
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_PWMDIS);
-+ while ((lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_PWMSTS))
-+ msleep(1);
-+ } else {
-+ /* Turn off the LCD controller and the DMA controller */
-+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-+ sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
-+
-+ /* Wait for the LCDC core to become idle */
-+ while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
-+ msleep(10);
-
-- lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
-+ }
- }
-
- static void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo)
- {
- atmel_lcdfb_stop_nowait(sinfo);
-
-- /* Wait for DMA engine to become idle... */
-- while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
-- msleep(10);
-+ if (cpu_is_at91sam9x5()) {
-+ /* Wait for the end of DMA transfer */
-+ while (!(lcdc_readl(sinfo, ATMEL_LCDC_BASEISR) & LCDC_BASEISR_DMA))
-+ msleep(10);
-+ } else {
-+ /* Wait for DMA engine to become idle... */
-+ while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
-+ msleep(10);
-+ }
- }
-
- static void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo)
- {
-- lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
-- lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-- (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET)
-- | ATMEL_LCDC_PWR);
-+ u32 value;
-+
-+ if (cpu_is_at91sam9x5()) {
-+ value = lcdc_readl(sinfo, ATMEL_LCDC_LCDEN);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDEN, value | LCDC_LCDEN_CLKEN);
-+ while (!(lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_CLKSTS))
-+ msleep(1);
-+ value = lcdc_readl(sinfo, ATMEL_LCDC_LCDEN);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDEN, value | LCDC_LCDEN_SYNCEN);
-+ while (!(lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_LCDSTS))
-+ msleep(1);
-+ value = lcdc_readl(sinfo, ATMEL_LCDC_LCDEN);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDEN, value | LCDC_LCDEN_DISPEN);
-+ while (!(lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_DISPSTS))
-+ msleep(1);
-+ value = lcdc_readl(sinfo, ATMEL_LCDC_LCDEN);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDEN, value | LCDC_LCDEN_PWMEN);
-+ while (!(lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_PWMSTS))
-+ msleep(1);
-+ } else {
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
-+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-+ (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET)
-+ | ATMEL_LCDC_PWR);
-+ }
- }
-
- static void atmel_lcdfb_update_dma(struct fb_info *info,
-@@ -254,14 +322,31 @@ static void atmel_lcdfb_update_dma(struc
- struct atmel_lcdfb_info *sinfo = info->par;
- struct fb_fix_screeninfo *fix = &info->fix;
- unsigned long dma_addr;
-+ struct lcd_dma_desc *desc;
-
- dma_addr = (fix->smem_start + var->yoffset * fix->line_length
- + var->xoffset * info->var.bits_per_pixel / 8);
-
- dma_addr &= ~3UL;
-
-- /* Set framebuffer DMA base address and pixel offset */
-- lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
-+ if (cpu_is_at91sam9x5()) {
-+ /* Setup the DMA descriptor, this descriptor will loop to itself */
-+ desc = (struct lcd_dma_desc *)sinfo->p_dma_desc;
-+
-+ desc->address = dma_addr;
-+ /* Disable DMA transfer interrupt & descriptor loaded interrupt. */
-+ desc->control = LCDC_BASECTRL_ADDIEN | LCDC_BASECTRL_DSCRIEN
-+ | LCDC_BASECTRL_DMAIEN | LCDC_BASECTRL_DFETCH;
-+ desc->next = sinfo->dma_desc_phys;
-+
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASEADDR, dma_addr);
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASECTRL, desc->control);
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASENEXT, sinfo->dma_desc_phys);
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASECHER, LCDC_BASECHER_CHEN | LCDC_BASECHER_UPDATEEN);
-+ } else {
-+ /* Set framebuffer DMA base address and pixel offset */
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
-+ }
-
- atmel_lcdfb_update_dma2d(sinfo, var, info);
- }
-@@ -272,12 +357,18 @@ static inline void atmel_lcdfb_free_vide
-
- dma_free_writecombine(info->device, info->fix.smem_len,
- info->screen_base, info->fix.smem_start);
-+
-+ if (cpu_is_at91sam9x5()) {
-+ if (sinfo->p_dma_desc)
-+ dma_free_writecombine(info->device, sizeof(struct lcd_dma_desc),
-+ sinfo->p_dma_desc, sinfo->dma_desc_phys);
-+ }
- }
-
- /**
- * atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory
- * @sinfo: the frame buffer to allocate memory for
-- *
-+ *
- * This function is called only from the atmel_lcdfb_probe()
- * so no locking by fb_info->mm_lock around smem_len setting is needed.
- */
-@@ -300,6 +391,19 @@ static int atmel_lcdfb_alloc_video_memor
-
- memset(info->screen_base, 0, info->fix.smem_len);
-
-+ if (cpu_is_at91sam9x5()) {
-+ sinfo->p_dma_desc = dma_alloc_writecombine(info->device,
-+ sizeof(struct lcd_dma_desc),
-+ (dma_addr_t *)&(sinfo->dma_desc_phys),
-+ GFP_KERNEL);
-+
-+ if (!sinfo->p_dma_desc) {
-+ dma_free_writecombine(info->device, info->fix.smem_len,
-+ info->screen_base, info->fix.smem_start);
-+ return -ENOMEM;
-+ }
-+ }
-+
- return 0;
- }
-
-@@ -393,18 +497,33 @@ static int atmel_lcdfb_check_var(struct
- }
-
- /* Saturate vertical and horizontal timings at maximum values */
-- var->vsync_len = min_t(u32, var->vsync_len,
-- (ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1);
-- var->upper_margin = min_t(u32, var->upper_margin,
-- ATMEL_LCDC_VBP >> ATMEL_LCDC_VBP_OFFSET);
-- var->lower_margin = min_t(u32, var->lower_margin,
-- ATMEL_LCDC_VFP);
-- var->right_margin = min_t(u32, var->right_margin,
-- (ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 1);
-- var->hsync_len = min_t(u32, var->hsync_len,
-- (ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1);
-- var->left_margin = min_t(u32, var->left_margin,
-- ATMEL_LCDC_HBP + 1);
-+ if (cpu_is_at91sam9x5()) {
-+ var->vsync_len = min_t(u32, var->vsync_len,
-+ (LCDC_LCDCFG1_VSPW >> LCDC_LCDCFG1_VSPW_OFFSET) + 1);
-+ var->upper_margin = min_t(u32, var->upper_margin,
-+ (LCDC_LCDCFG2_VFPW >> LCDC_LCDCFG2_VFPW_OFFSET) + 1);
-+ var->lower_margin = min_t(u32, var->lower_margin,
-+ LCDC_LCDCFG2_VBPW >> LCDC_LCDCFG2_VBPW_OFFSET);
-+ var->right_margin = min_t(u32, var->right_margin,
-+ (LCDC_LCDCFG3_HBPW >> LCDC_LCDCFG3_HBPW_OFFSET) + 1);
-+ var->hsync_len = min_t(u32, var->hsync_len,
-+ (LCDC_LCDCFG1_HSPW >> LCDC_LCDCFG1_HSPW_OFFSET) + 1);
-+ var->left_margin = min_t(u32, var->left_margin,
-+ (LCDC_LCDCFG3_HFPW >> LCDC_LCDCFG3_HFPW_OFFSET) + 1);
-+ } else {
-+ var->vsync_len = min_t(u32, var->vsync_len,
-+ (ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1);
-+ var->upper_margin = min_t(u32, var->upper_margin,
-+ ATMEL_LCDC_VBP >> ATMEL_LCDC_VBP_OFFSET);
-+ var->lower_margin = min_t(u32, var->lower_margin,
-+ ATMEL_LCDC_VFP);
-+ var->right_margin = min_t(u32, var->right_margin,
-+ (ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 1);
-+ var->hsync_len = min_t(u32, var->hsync_len,
-+ (ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1);
-+ var->left_margin = min_t(u32, var->left_margin,
-+ ATMEL_LCDC_HBP + 1);
-+ }
-
- /* Some parameters can't be zero */
- var->vsync_len = max_t(u32, var->vsync_len, 1);
-@@ -419,9 +538,53 @@ static int atmel_lcdfb_check_var(struct
- case 8:
- var->red.offset = var->green.offset = var->blue.offset = 0;
- var->red.length = var->green.length = var->blue.length
-- = var->bits_per_pixel;
-+ = var->bits_per_pixel;
-+ break;
-+ case 12:
-+ if (cpu_is_at91sam9x5()) {
-+ /* RGB:444 mode */
-+ var->red.offset = 8;
-+ var->blue.offset = 0;
-+ var->green.offset = 4;
-+ var->red.length = var->green.length = var->blue.length = 4;
-+ } else {
-+ /*TODO: rework*/
-+ BUG();
-+ }
-+ break;
-+ case 15:
-+ if (cpu_is_at91sam9x5()) {
-+ /* RGB:555 mode */
-+ var->red.offset = 10;
-+ var->blue.offset = 0;
-+ var->green.length = 5;
-+ var->red.length = var->green.length = var->blue.length = 5;
-+ } else {
-+ /*TODO: rework*/
-+ BUG();
-+ }
- break;
- case 16:
-+ if (cpu_is_at91sam9x5()) {
-+ if (sinfo->alpha_enabled) {
-+ /* ARGB:4444 mode */
-+ var->red.offset = 8;
-+ var->blue.offset = 0;
-+ var->green.offset = 4;
-+ var->transp.offset = 12;
-+ var->red.length = var->green.length
-+ = var->blue.length
-+ = var->transp.length = 4;
-+ } else {
-+ /* RGB:565 mode */
-+ var->red.offset = 11;
-+ var->blue.offset = 0;
-+ var->green.offset = 5;
-+ var->green.length = 6;
-+ var->red.length = var->blue.length = 5;
-+ }
-+ break;
-+ }
- /* Older SOCs use IBGR:555 rather than BGR:565. */
- if (sinfo->have_intensity_bit)
- var->green.length = 5;
-@@ -441,6 +604,7 @@ static int atmel_lcdfb_check_var(struct
- var->red.length = var->blue.length = 5;
- break;
- case 32:
-+ /* TODO 32 & 24 modes */
- var->transp.offset = 24;
- var->transp.length = 8;
- /* fall through */
-@@ -477,6 +641,252 @@ static void atmel_lcdfb_reset(struct atm
- atmel_lcdfb_start(sinfo);
- }
-
-+static int atmel_lcdfb_setup_9x5_core(struct fb_info *info)
-+{
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ unsigned long value;
-+ unsigned long clk_value_khz;
-+
-+ dev_dbg(info->device, "%s:\n", __func__);
-+ /* Set pixel clock */
-+ clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
-+
-+ value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock));
-+
-+ if (value < 1) {
-+ dev_notice(info->device, "using system clock as pixel clock\n");
-+ value = LCDC_LCDCFG0_CLKPOL | LCDC_LCDCFG0_CLKPWMSEL | LCDC_LCDCFG0_CGDISBASE;
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG0, value);
-+ } else {
-+ info->var.pixclock = KHZ2PICOS(clk_value_khz / value);
-+ dev_dbg(info->device, " updated pixclk: %lu KHz\n",
-+ PICOS2KHZ(info->var.pixclock));
-+ value = value - 2;
-+ dev_dbg(info->device, " * programming CLKDIV = 0x%08lx\n",
-+ value);
-+ value = (value << LCDC_LCDCFG0_CLKDIV_OFFSET)
-+ | LCDC_LCDCFG0_CLKPOL
-+ | LCDC_LCDCFG0_CGDISBASE;
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG0, value);
-+ }
-+
-+ /* Initialize control register 5 */
-+ value = (sinfo->guard_time << LCDC_LCDCFG5_GUARDTIME_OFFSET)
-+ | LCDC_LCDCFG5_DISPDLY
-+ | LCDC_LCDCFG5_VSPDLYS;
-+
-+ if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
-+ value |= LCDC_LCDCFG5_HSPOL;
-+ if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
-+ value |= LCDC_LCDCFG5_VSPOL;
-+
-+ switch (info->var.bits_per_pixel) {
-+ case 12:
-+ value |= LCDC_LCDCFG5_MODE_OUTPUT_12BPP;
-+ break;
-+ case 16:
-+ if (info->var.transp.offset != 0)
-+ value |= LCDC_LCDCFG5_MODE_OUTPUT_12BPP;
-+ else
-+ value |= LCDC_LCDCFG5_MODE_OUTPUT_16BPP;
-+ break;
-+ case 18:
-+ value |= LCDC_LCDCFG5_MODE_OUTPUT_18BPP;
-+ break;
-+ case 24:
-+ case 32:
-+ value |= LCDC_LCDCFG5_MODE_OUTPUT_24BPP;
-+ break;
-+ default:
-+ BUG();
-+ break;
-+ }
-+ dev_dbg(info->device, " * LCDC_LCDCFG5 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG5, value);
-+
-+ /* Vertical & Horizontal Timing */
-+ value = (info->var.vsync_len - 1) << LCDC_LCDCFG1_VSPW_OFFSET;
-+ value |= (info->var.hsync_len - 1) << LCDC_LCDCFG1_HSPW_OFFSET;
-+ dev_dbg(info->device, " * LCDC_LCDCFG1 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG1, value);
-+
-+ value = (info->var.lower_margin) << LCDC_LCDCFG2_VBPW_OFFSET;
-+ value |= (info->var.upper_margin - 1) << LCDC_LCDCFG2_VFPW_OFFSET;
-+ dev_dbg(info->device, " * LCDC_LCDCFG2 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG2, value);
-+
-+ value = (info->var.right_margin - 1) << LCDC_LCDCFG3_HBPW_OFFSET;
-+ value |= (info->var.left_margin - 1) << LCDC_LCDCFG3_HFPW_OFFSET;
-+ dev_dbg(info->device, " * LCDC_LCDCFG3 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG3, value);
-+
-+ /* Display size */
-+ value = (info->var.yres - 1) << LCDC_LCDCFG4_RPF_OFFSET;
-+ value |= (info->var.xres - 1) << LCDC_LCDCFG4_PPL_OFFSET;
-+ dev_dbg(info->device, " * LCDC_LCDCFG4 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG4, value);
-+
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASECFG0, LCDC_BASECFG0_BLEN_AHB_INCR4 | LCDC_BASECFG0_DLBO);
-+ switch (info->var.bits_per_pixel) {
-+ case 12:
-+ value = LCDC_BASECFG1_RGBMODE_12BPP_RGB_444;
-+ break;
-+ case 16:
-+ if (info->var.transp.offset != 0)
-+ value = LCDC_BASECFG1_RGBMODE_16BPP_ARGB_4444;
-+ else
-+ value = LCDC_BASECFG1_RGBMODE_16BPP_RGB_565;
-+ break;
-+ case 18:
-+ value = LCDC_BASECFG1_RGBMODE_18BPP_RGB_666_PACKED;
-+ break;
-+ case 24:
-+ value = LCDC_BASECFG1_RGBMODE_24BPP_RGB_888_PACKED;
-+ break;
-+ case 32:
-+ value = LCDC_BASECFG1_RGBMODE_32BPP_ARGB_8888;
-+ break;
-+ default:
-+ BUG();
-+ break;
-+ }
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASECFG1, value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASECFG2, 0);
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASECFG3, 0); /* Default color */
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASECFG4, LCDC_BASECFG4_DMA);
-+
-+ /* Disable all interrupts */
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDIDR, ~0UL);
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASEIDR, ~0UL);
-+ /* Enable BASE LAYER overflow interrupts, if want to enable DMA interrupt, also need set it at LCDC_BASECTRL reg */
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASEIER, LCDC_BASEIER_OVR);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDIER, LCDC_LCDIER_FIFOERRIE | LCDC_LCDIER_BASEIE);
-+
-+ return 0;
-+}
-+
-+static int atmel_lcdfb_setup_core(struct fb_info *info)
-+{
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ unsigned long hozval_linesz;
-+ unsigned long value;
-+ unsigned long clk_value_khz;
-+ unsigned long pix_factor = 2;
-+
-+ if (cpu_is_at91sam9x5()) {
-+ return atmel_lcdfb_setup_9x5_core(info);
-+ } else {
-+ /* ...set frame size and burst length = 8 words (?) */
-+ value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32;
-+ value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET);
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value);
-+
-+ /* Set pixel clock */
-+ if (cpu_is_at91sam9g45() && !cpu_is_at91sam9g45es())
-+ pix_factor = 1;
-+
-+ clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
-+
-+ value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock));
-+
-+ if (value < pix_factor) {
-+ dev_notice(info->device, "Bypassing pixel clock divider\n");
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
-+ } else {
-+ value = (value / pix_factor) - 1;
-+ dev_dbg(info->device, " * programming CLKVAL = 0x%08lx\n",
-+ value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1,
-+ value << ATMEL_LCDC_CLKVAL_OFFSET);
-+ info->var.pixclock =
-+ KHZ2PICOS(clk_value_khz / (pix_factor * (value + 1)));
-+ dev_dbg(info->device, " updated pixclk: %lu KHz\n",
-+ PICOS2KHZ(info->var.pixclock));
-+ }
-+
-+
-+ /* Initialize control register 2 */
-+ value = sinfo->default_lcdcon2;
-+
-+ if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
-+ value |= ATMEL_LCDC_INVLINE_INVERTED;
-+ if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
-+ value |= ATMEL_LCDC_INVFRAME_INVERTED;
-+
-+ switch (info->var.bits_per_pixel) {
-+ case 1:
-+ value |= ATMEL_LCDC_PIXELSIZE_1;
-+ break;
-+ case 2:
-+ value |= ATMEL_LCDC_PIXELSIZE_2;
-+ break;
-+ case 4:
-+ value |= ATMEL_LCDC_PIXELSIZE_4;
-+ break;
-+ case 8:
-+ value |= ATMEL_LCDC_PIXELSIZE_8;
-+ break;
-+ case 15: /* fall through */
-+ case 16:
-+ value |= ATMEL_LCDC_PIXELSIZE_16;
-+ break;
-+ case 24:
-+ value |= ATMEL_LCDC_PIXELSIZE_24;
-+ break;
-+ case 32:
-+ value |= ATMEL_LCDC_PIXELSIZE_32;
-+ break;
-+ default:
-+ BUG();
-+ break;
-+ }
-+ dev_dbg(info->device, " * LCDCON2 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value);
-+
-+ /* Vertical timing */
-+ value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET;
-+ value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET;
-+ value |= info->var.lower_margin;
-+ dev_dbg(info->device, " * LCDTIM1 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value);
-+
-+ /* Horizontal timing */
-+ value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET;
-+ value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET;
-+ value |= (info->var.left_margin - 1);
-+ dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
-+
-+ /* Horizontal value (aka line size) */
-+ hozval_linesz = compute_hozval(info->var.xres,
-+ lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2));
-+
-+ /* Display size */
-+ value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
-+ value |= info->var.yres - 1;
-+ dev_dbg(info->device, " * LCDFRMCFG = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value);
-+
-+ /* FIFO Threshold: Use formula from data sheet */
-+ value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3);
-+ lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value);
-+
-+ /* Toggle LCD_MODE every frame */
-+ lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0);
-+
-+ /* Disable all interrupts */
-+ lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
-+ /* Enable FIFO & DMA errors */
-+ lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
-+
-+ /* ...wait for DMA engine to become idle... */
-+ while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
-+ msleep(10);
-+
-+ return 0;
-+ }
-+}
-+
- /**
- * atmel_lcdfb_set_par - Alters the hardware state.
- * @info: frame buffer structure that represents a single frame buffer
-@@ -494,11 +904,7 @@ static void atmel_lcdfb_reset(struct atm
- static int atmel_lcdfb_set_par(struct fb_info *info)
- {
- struct atmel_lcdfb_info *sinfo = info->par;
-- unsigned long hozval_linesz;
-- unsigned long value;
-- unsigned long clk_value_khz;
- unsigned long bits_per_line;
-- unsigned long pix_factor = 2;
-
- might_sleep();
-
-@@ -523,98 +929,8 @@ static int atmel_lcdfb_set_par(struct fb
- dev_dbg(info->device, " * update DMA engine\n");
- atmel_lcdfb_update_dma(info, &info->var);
-
-- /* ...set frame size and burst length = 8 words (?) */
-- value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32;
-- value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET);
-- lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value);
--
- /* Now, the LCDC core... */
--
-- /* Set pixel clock */
-- if (cpu_is_at91sam9g45() && !cpu_is_at91sam9g45es())
-- pix_factor = 1;
--
-- clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
--
-- value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock));
--
-- if (value < pix_factor) {
-- dev_notice(info->device, "Bypassing pixel clock divider\n");
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
-- } else {
-- value = (value / pix_factor) - 1;
-- dev_dbg(info->device, " * programming CLKVAL = 0x%08lx\n",
-- value);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1,
-- value << ATMEL_LCDC_CLKVAL_OFFSET);
-- info->var.pixclock =
-- KHZ2PICOS(clk_value_khz / (pix_factor * (value + 1)));
-- dev_dbg(info->device, " updated pixclk: %lu KHz\n",
-- PICOS2KHZ(info->var.pixclock));
-- }
--
--
-- /* Initialize control register 2 */
-- value = sinfo->default_lcdcon2;
--
-- if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
-- value |= ATMEL_LCDC_INVLINE_INVERTED;
-- if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
-- value |= ATMEL_LCDC_INVFRAME_INVERTED;
--
-- switch (info->var.bits_per_pixel) {
-- case 1: value |= ATMEL_LCDC_PIXELSIZE_1; break;
-- case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break;
-- case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break;
-- case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break;
-- case 15: /* fall through */
-- case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break;
-- case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break;
-- case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break;
-- default: BUG(); break;
-- }
-- dev_dbg(info->device, " * LCDCON2 = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value);
--
-- /* Vertical timing */
-- value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET;
-- value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET;
-- value |= info->var.lower_margin;
-- dev_dbg(info->device, " * LCDTIM1 = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value);
--
-- /* Horizontal timing */
-- value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET;
-- value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET;
-- value |= (info->var.left_margin - 1);
-- dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
--
-- /* Horizontal value (aka line size) */
-- hozval_linesz = compute_hozval(info->var.xres,
-- lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2));
--
-- /* Display size */
-- value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
-- value |= info->var.yres - 1;
-- dev_dbg(info->device, " * LCDFRMCFG = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value);
--
-- /* FIFO Threshold: Use formula from data sheet */
-- value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3);
-- lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value);
--
-- /* Toggle LCD_MODE every frame */
-- lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0);
--
-- /* Disable all interrupts */
-- lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
-- /* Enable FIFO & DMA errors */
-- lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
--
-- /* ...wait for DMA engine to become idle... */
-- while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
-- msleep(10);
-+ atmel_lcdfb_setup_core(info);
-
- atmel_lcdfb_start(sinfo);
-
-@@ -776,14 +1092,32 @@ static irqreturn_t atmel_lcdfb_interrupt
- struct fb_info *info = dev_id;
- struct atmel_lcdfb_info *sinfo = info->par;
- u32 status;
-+ u32 baselayer_status;
-+
-+ if (cpu_is_at91sam9x5()) {
-+ /* Check for error status via interrupt.*/
-+ status = lcdc_readl(sinfo, ATMEL_LCDC_LCDISR);
-+ if (status & LCDC_LCDISR_FIFOERR) {
-+ dev_warn(info->device, "FIFO underflow %#x\n", status);
-+ } else if (status & LCDC_LCDISR_BASE) {
-+ /* Check base layer's overflow error. */
-+ baselayer_status = lcdc_readl(sinfo, ATMEL_LCDC_BASEISR);
-+
-+ if (baselayer_status & LCDC_BASEISR_OVR)
-+ dev_warn(info->device, "base layer overflow %#x\n",
-+ baselayer_status);
-
-- status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
-- if (status & ATMEL_LCDC_UFLWI) {
-- dev_warn(info->device, "FIFO underflow %#x\n", status);
-- /* reset DMA and FIFO to avoid screen shifting */
-- schedule_work(&sinfo->task);
-+ }
-+ } else {
-+ status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
-+ if (status & ATMEL_LCDC_UFLWI) {
-+ dev_warn(info->device, "FIFO underflow %#x\n", status);
-+ /* reset DMA and FIFO to avoid screen shifting */
-+ schedule_work(&sinfo->task);
-+ }
-+ lcdc_writel(sinfo, ATMEL_LCDC_ICR, status);
- }
-- lcdc_writel(sinfo, ATMEL_LCDC_ICR, status);
-+
- return IRQ_HANDLED;
- }
-
-@@ -928,6 +1262,8 @@ static int __init atmel_lcdfb_probe(stru
-
- /* Initialize video memory */
- map = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+ sinfo->p_dma_desc = NULL;
-+ sinfo->dma_desc_phys = 0;
- if (map) {
- /* use a pre-allocated memory buffer */
- info->fix.smem_start = map->start;
-@@ -1038,7 +1374,7 @@ unmap_mmio:
- exit_backlight(sinfo);
- iounmap(sinfo->mmio);
- release_mem:
-- release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
-+ release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
- free_fb:
- if (map)
- iounmap(info->screen_base);
-@@ -1083,7 +1419,7 @@ static int __exit atmel_lcdfb_remove(str
- fb_dealloc_cmap(&info->cmap);
- free_irq(sinfo->irq_base, info);
- iounmap(sinfo->mmio);
-- release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
-+ release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
- if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) {
- iounmap(info->screen_base);
- release_mem_region(info->fix.smem_start, info->fix.smem_len);
-@@ -1108,10 +1444,17 @@ static int atmel_lcdfb_suspend(struct pl
- * We don't want to handle interrupts while the clock is
- * stopped. It may take forever.
- */
-- lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
-+ if (cpu_is_at91sam9x5()) {
-+ /* Disable all interrupts */
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDIDR, ~0UL);
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASEIDR, ~0UL);
-+ } else {
-+ lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
-+
-+ sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
-+ }
-
-- sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR);
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
- if (sinfo->atmel_lcdfb_power_control)
- sinfo->atmel_lcdfb_power_control(0);
-
-@@ -1130,11 +1473,18 @@ static int atmel_lcdfb_resume(struct pla
- atmel_lcdfb_start(sinfo);
- if (sinfo->atmel_lcdfb_power_control)
- sinfo->atmel_lcdfb_power_control(1);
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon);
-
-- /* Enable FIFO & DMA errors */
-- lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI
-- | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
-+ if (cpu_is_at91sam9x5()) {
-+ /* Enable fifo error & BASE LAYER overflow interrupts */
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASEIER, LCDC_BASEIER_OVR);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDIER, LCDC_LCDIER_FIFOERRIE | LCDC_LCDIER_BASEIE);
-+ } else {
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon);
-+
-+ /* Enable FIFO & DMA errors */
-+ lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI
-+ | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
-+ }
-
- return 0;
- }
---- a/include/video/atmel_lcdc.h
-+++ b/include/video/atmel_lcdc.h
-@@ -47,12 +47,16 @@ struct atmel_lcdfb_info {
- struct clk *bus_clk;
- struct clk *lcdc_clk;
-
-+ struct lcd_dma_desc *p_dma_desc;
-+ dma_addr_t dma_desc_phys;
-+
- #ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
- struct backlight_device *backlight;
- u8 bl_power;
- #endif
- bool lcdcon_is_backlight;
- bool lcdcon_pol_negative;
-+ bool alpha_enabled;
- u8 saved_lcdcon;
-
- u8 default_bpp;
-@@ -65,6 +69,12 @@ struct atmel_lcdfb_info {
- bool have_intensity_bit;
- };
-
-+struct lcd_dma_desc {
-+ u32 address;
-+ u32 control;
-+ u32 next;
-+};
-+
- #define ATMEL_LCDC_DMABADDR1 0x00
- #define ATMEL_LCDC_DMABADDR2 0x04
- #define ATMEL_LCDC_DMAFRMPT1 0x08
-@@ -215,6 +225,11 @@ struct atmel_lcdfb_info {
- #define ATMEL_LCDC_OWRI (1 << 5)
- #define ATMEL_LCDC_MERI (1 << 6)
-
-+#if !defined(CONFIG_ARCH_AT91SAM9X5)
- #define ATMEL_LCDC_LUT(n) (0x0c00 + ((n)*4))
-+#else
-+/* Base layer CLUT */
-+#define ATMEL_LCDC_LUT(n) (0x0400 + ((n)*4))
-+#endif
-
- #endif /* __ATMEL_LCDC_H__ */
+++ /dev/null
-From 4b390fa4276515efa7c11faf731368289873c486 Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Wed, 9 Mar 2011 11:21:51 +0800
-Subject: video/atmel_lcdfb: The output bpp should not change according to
- memory bpp
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The 9x5-ek using 24 bits output for its connection to LCD screen.
-The output bpp can now be configurated in board file.
-
-XXX: these are two different changes?
-
-Signed-off-by: Josh Wu <josh.wu@atmel.com>
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
----
- drivers/video/atmel_lcdfb.c | 25 +++----------------------
- 1 file changed, 3 insertions(+), 22 deletions(-)
-
---- a/drivers/video/atmel_lcdfb.c
-+++ b/drivers/video/atmel_lcdfb.c
-@@ -671,7 +671,9 @@ static int atmel_lcdfb_setup_9x5_core(st
- }
-
- /* Initialize control register 5 */
-- value = (sinfo->guard_time << LCDC_LCDCFG5_GUARDTIME_OFFSET)
-+ /* In 9x5, the default_lcdcon2 will use for LCDCFG5 */
-+ value = sinfo->default_lcdcon2;
-+ value |= (sinfo->guard_time << LCDC_LCDCFG5_GUARDTIME_OFFSET)
- | LCDC_LCDCFG5_DISPDLY
- | LCDC_LCDCFG5_VSPDLYS;
-
-@@ -680,27 +682,6 @@ static int atmel_lcdfb_setup_9x5_core(st
- if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
- value |= LCDC_LCDCFG5_VSPOL;
-
-- switch (info->var.bits_per_pixel) {
-- case 12:
-- value |= LCDC_LCDCFG5_MODE_OUTPUT_12BPP;
-- break;
-- case 16:
-- if (info->var.transp.offset != 0)
-- value |= LCDC_LCDCFG5_MODE_OUTPUT_12BPP;
-- else
-- value |= LCDC_LCDCFG5_MODE_OUTPUT_16BPP;
-- break;
-- case 18:
-- value |= LCDC_LCDCFG5_MODE_OUTPUT_18BPP;
-- break;
-- case 24:
-- case 32:
-- value |= LCDC_LCDCFG5_MODE_OUTPUT_24BPP;
-- break;
-- default:
-- BUG();
-- break;
-- }
- dev_dbg(info->device, " * LCDC_LCDCFG5 = %08lx\n", value);
- lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG5, value);
-
+++ /dev/null
-From b87963ed623148fd11efc742fbabfcde68aba645 Mon Sep 17 00:00:00 2001
-From: Wolfram Sang <w.sang@pengutronix.de>
-Date: Thu, 19 May 2011 09:42:55 +0200
-Subject: video: atmelfb: initially split atmelfb into a driver and library
- part
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
-
-Conflicts:
-
- drivers/video/atmel_lcdfb.c
----
- drivers/video/Makefile | 2
- drivers/video/atmel_lcdfb.c | 1439 ---------------------------------------
- drivers/video/atmel_lcdfb_core.c | 1077 +++++++++++++++++++++++++++++
- include/video/atmel_lcdc.h | 17
- 4 files changed, 1106 insertions(+), 1429 deletions(-)
- create mode 100644 drivers/video/atmel_lcdfb_core.c
-
---- a/drivers/video/Makefile
-+++ b/drivers/video/Makefile
-@@ -95,7 +95,7 @@ obj-$(CONFIG_FB_EP93XX) += ep93xx-fb.
- obj-$(CONFIG_FB_SA1100) += sa1100fb.o
- obj-$(CONFIG_FB_HIT) += hitfb.o
- obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o
--obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o
-+obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o atmel_lcdfb_core.o
- obj-$(CONFIG_FB_PVR2) += pvr2fb.o
- obj-$(CONFIG_FB_VOODOO1) += sstfb.o
- obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o
---- a/drivers/video/atmel_lcdfb.c
-+++ b/drivers/video/atmel_lcdfb.c
-@@ -10,1409 +10,12 @@
-
- #include <linux/kernel.h>
- #include <linux/platform_device.h>
--#include <linux/dma-mapping.h>
- #include <linux/interrupt.h>
--#include <linux/clk.h>
- #include <linux/fb.h>
- #include <linux/init.h>
- #include <linux/delay.h>
--#include <linux/backlight.h>
--#include <linux/gfp.h>
--#include <linux/module.h>
--
--#include <mach/board.h>
--#include <mach/cpu.h>
--#include <asm/gpio.h>
-
- #include <video/atmel_lcdc.h>
--#include <mach/atmel_hlcdfb.h>
--
--#define lcdc_readl(sinfo, reg) __raw_readl((sinfo)->mmio+(reg))
--#define lcdc_writel(sinfo, reg, val) __raw_writel((val), (sinfo)->mmio+(reg))
--
--/* configurable parameters */
--#define ATMEL_LCDC_CVAL_DEFAULT 0xc8
--#define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */
--#define ATMEL_LCDC_FIFO_SIZE 512 /* words */
--
--#if defined(CONFIG_ARCH_AT91)
--#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
-- | FBINFO_PARTIAL_PAN_OK \
-- | FBINFO_HWACCEL_YPAN)
--
--static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
-- struct fb_var_screeninfo *var,
-- struct fb_info *info)
--{
--
--}
--#elif defined(CONFIG_AVR32)
--#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
-- | FBINFO_PARTIAL_PAN_OK \
-- | FBINFO_HWACCEL_XPAN \
-- | FBINFO_HWACCEL_YPAN)
--
--static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
-- struct fb_var_screeninfo *var,
-- struct fb_info *info)
--{
-- u32 dma2dcfg;
-- u32 pixeloff;
--
-- pixeloff = (var->xoffset * info->var.bits_per_pixel) & 0x1f;
--
-- dma2dcfg = (info->var.xres_virtual - info->var.xres)
-- * info->var.bits_per_pixel / 8;
-- dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
-- lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
--
-- /* Update configuration */
-- lcdc_writel(sinfo, ATMEL_LCDC_DMACON,
-- lcdc_readl(sinfo, ATMEL_LCDC_DMACON)
-- | ATMEL_LCDC_DMAUPDT);
--}
--#endif
--
--static u32 contrast_ctr = ATMEL_LCDC_PS_DIV8
-- | ATMEL_LCDC_POL_POSITIVE
-- | ATMEL_LCDC_ENA_PWMENABLE;
--
--static const u32 contrast_pwm_ctr = LCDC_LCDCFG6_PWMPOL
-- | (ATMEL_LCDC_CVAL_DEFAULT << LCDC_LCDCFG6_PWMCVAL_OFFSET);
--
--#ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
--
--/* some bl->props field just changed */
--static int atmel_bl_update_status(struct backlight_device *bl)
--{
-- struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
-- int power = sinfo->bl_power;
-- int brightness = bl->props.brightness;
-- u32 reg;
--
-- /* REVISIT there may be a meaningful difference between
-- * fb_blank and power ... there seem to be some cases
-- * this doesn't handle correctly.
-- */
-- if (bl->props.fb_blank != sinfo->bl_power)
-- power = bl->props.fb_blank;
-- else if (bl->props.power != sinfo->bl_power)
-- power = bl->props.power;
--
-- if (brightness < 0 && power == FB_BLANK_UNBLANK) {
-- if (cpu_is_at91sam9x5())
-- brightness = lcdc_readl(sinfo, ATMEL_LCDC_LCDCFG6)
-- >> LCDC_LCDCFG6_PWMCVAL_OFFSET;
-- else
-- brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
-- } else if (power != FB_BLANK_UNBLANK) {
-- brightness = 0;
-- }
--
-- if (cpu_is_at91sam9x5()) {
-- reg = lcdc_readl(sinfo, ATMEL_LCDC_LCDCFG6) & ~LCDC_LCDCFG6_PWMCVAL;
-- reg |= brightness << LCDC_LCDCFG6_PWMCVAL_OFFSET;
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG6, reg);
-- } else {
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
-- if (contrast_ctr & ATMEL_LCDC_POL_POSITIVE)
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
-- brightness ? contrast_ctr : 0);
-- else
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
-- }
--
-- bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;
--
-- return 0;
--}
--
--static int atmel_bl_get_brightness(struct backlight_device *bl)
--{
-- struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
--
-- if (cpu_is_at91sam9x5())
-- return lcdc_readl(sinfo, ATMEL_LCDC_LCDCFG6) >> LCDC_LCDCFG6_PWMCVAL_OFFSET;
-- else
-- return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
--}
--
--static const struct backlight_ops atmel_lcdc_bl_ops = {
-- .update_status = atmel_bl_update_status,
-- .get_brightness = atmel_bl_get_brightness,
--};
--
--static void init_backlight(struct atmel_lcdfb_info *sinfo)
--{
-- struct backlight_properties props;
-- struct backlight_device *bl;
--
-- sinfo->bl_power = FB_BLANK_UNBLANK;
--
-- if (sinfo->backlight)
-- return;
--
-- memset(&props, 0, sizeof(struct backlight_properties));
-- props.type = BACKLIGHT_RAW;
-- props.max_brightness = 0xff;
-- bl = backlight_device_register("backlight", &sinfo->pdev->dev, sinfo,
-- &atmel_lcdc_bl_ops, &props);
-- if (IS_ERR(bl)) {
-- dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n",
-- PTR_ERR(bl));
-- return;
-- }
-- sinfo->backlight = bl;
--
-- bl->props.power = FB_BLANK_UNBLANK;
-- bl->props.fb_blank = FB_BLANK_UNBLANK;
-- bl->props.brightness = atmel_bl_get_brightness(bl);
--}
--
--static void exit_backlight(struct atmel_lcdfb_info *sinfo)
--{
-- if (sinfo->backlight)
-- backlight_device_unregister(sinfo->backlight);
--}
--
--#else
--
--static void init_backlight(struct atmel_lcdfb_info *sinfo)
--{
-- dev_warn(&sinfo->pdev->dev, "backlight control is not available\n");
--}
--
--static void exit_backlight(struct atmel_lcdfb_info *sinfo)
--{
--}
--
--#endif
--
--static void init_contrast(struct atmel_lcdfb_info *sinfo)
--{
-- if (cpu_is_at91sam9x5()) {
-- /* have some default contrast/backlight settings */
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG6, contrast_pwm_ctr);
-- } else {
-- /* contrast pwm can be 'inverted' */
-- if (sinfo->lcdcon_pol_negative)
-- contrast_ctr &= ~(ATMEL_LCDC_POL_POSITIVE);
-- /* have some default contrast/backlight settings */
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
-- }
-- if (sinfo->lcdcon_is_backlight)
-- init_backlight(sinfo);
--}
--
--
--static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
-- .type = FB_TYPE_PACKED_PIXELS,
-- .visual = FB_VISUAL_TRUECOLOR,
-- .xpanstep = 0,
-- .ypanstep = 1,
-- .ywrapstep = 0,
-- .accel = FB_ACCEL_NONE,
--};
--
--static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2)
--{
-- unsigned long value;
--
-- if (!(cpu_is_at91sam9261() || cpu_is_at91sam9g10()
-- || cpu_is_at32ap7000()))
-- return xres;
--
-- value = xres;
-- if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) {
-- /* STN display */
-- if ((lcdcon2 & ATMEL_LCDC_DISTYPE) == ATMEL_LCDC_DISTYPE_STNCOLOR) {
-- value *= 3;
-- }
-- if ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_4
-- || ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_8
-- && (lcdcon2 & ATMEL_LCDC_SCANMOD) == ATMEL_LCDC_SCANMOD_DUAL ))
-- value = DIV_ROUND_UP(value, 4);
-- else
-- value = DIV_ROUND_UP(value, 8);
-- }
--
-- return value;
--}
--
--static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo)
--{
-- if (cpu_is_at91sam9x5()) {
-- /* Disable DISP signal */
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_DISPDIS);
-- while ((lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_DISPSTS))
-- msleep(1);
-- /* Disable synchronization */
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_SYNCDIS);
-- while ((lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_LCDSTS))
-- msleep(1);
-- /* Disable pixel clock */
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_CLKDIS);
-- while ((lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_CLKSTS))
-- msleep(1);
-- /* Disable PWM */
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_PWMDIS);
-- while ((lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_PWMSTS))
-- msleep(1);
-- } else {
-- /* Turn off the LCD controller and the DMA controller */
-- lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-- sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
--
-- /* Wait for the LCDC core to become idle */
-- while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
-- msleep(10);
--
-- lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
-- }
--}
--
--static void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo)
--{
-- atmel_lcdfb_stop_nowait(sinfo);
--
-- if (cpu_is_at91sam9x5()) {
-- /* Wait for the end of DMA transfer */
-- while (!(lcdc_readl(sinfo, ATMEL_LCDC_BASEISR) & LCDC_BASEISR_DMA))
-- msleep(10);
-- } else {
-- /* Wait for DMA engine to become idle... */
-- while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
-- msleep(10);
-- }
--}
--
--static void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo)
--{
-- u32 value;
--
-- if (cpu_is_at91sam9x5()) {
-- value = lcdc_readl(sinfo, ATMEL_LCDC_LCDEN);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDEN, value | LCDC_LCDEN_CLKEN);
-- while (!(lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_CLKSTS))
-- msleep(1);
-- value = lcdc_readl(sinfo, ATMEL_LCDC_LCDEN);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDEN, value | LCDC_LCDEN_SYNCEN);
-- while (!(lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_LCDSTS))
-- msleep(1);
-- value = lcdc_readl(sinfo, ATMEL_LCDC_LCDEN);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDEN, value | LCDC_LCDEN_DISPEN);
-- while (!(lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_DISPSTS))
-- msleep(1);
-- value = lcdc_readl(sinfo, ATMEL_LCDC_LCDEN);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDEN, value | LCDC_LCDEN_PWMEN);
-- while (!(lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_PWMSTS))
-- msleep(1);
-- } else {
-- lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
-- lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-- (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET)
-- | ATMEL_LCDC_PWR);
-- }
--}
--
--static void atmel_lcdfb_update_dma(struct fb_info *info,
-- struct fb_var_screeninfo *var)
--{
-- struct atmel_lcdfb_info *sinfo = info->par;
-- struct fb_fix_screeninfo *fix = &info->fix;
-- unsigned long dma_addr;
-- struct lcd_dma_desc *desc;
--
-- dma_addr = (fix->smem_start + var->yoffset * fix->line_length
-- + var->xoffset * info->var.bits_per_pixel / 8);
--
-- dma_addr &= ~3UL;
--
-- if (cpu_is_at91sam9x5()) {
-- /* Setup the DMA descriptor, this descriptor will loop to itself */
-- desc = (struct lcd_dma_desc *)sinfo->p_dma_desc;
--
-- desc->address = dma_addr;
-- /* Disable DMA transfer interrupt & descriptor loaded interrupt. */
-- desc->control = LCDC_BASECTRL_ADDIEN | LCDC_BASECTRL_DSCRIEN
-- | LCDC_BASECTRL_DMAIEN | LCDC_BASECTRL_DFETCH;
-- desc->next = sinfo->dma_desc_phys;
--
-- lcdc_writel(sinfo, ATMEL_LCDC_BASEADDR, dma_addr);
-- lcdc_writel(sinfo, ATMEL_LCDC_BASECTRL, desc->control);
-- lcdc_writel(sinfo, ATMEL_LCDC_BASENEXT, sinfo->dma_desc_phys);
-- lcdc_writel(sinfo, ATMEL_LCDC_BASECHER, LCDC_BASECHER_CHEN | LCDC_BASECHER_UPDATEEN);
-- } else {
-- /* Set framebuffer DMA base address and pixel offset */
-- lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
-- }
--
-- atmel_lcdfb_update_dma2d(sinfo, var, info);
--}
--
--static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
--{
-- struct fb_info *info = sinfo->info;
--
-- dma_free_writecombine(info->device, info->fix.smem_len,
-- info->screen_base, info->fix.smem_start);
--
-- if (cpu_is_at91sam9x5()) {
-- if (sinfo->p_dma_desc)
-- dma_free_writecombine(info->device, sizeof(struct lcd_dma_desc),
-- sinfo->p_dma_desc, sinfo->dma_desc_phys);
-- }
--}
--
--/**
-- * atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory
-- * @sinfo: the frame buffer to allocate memory for
-- *
-- * This function is called only from the atmel_lcdfb_probe()
-- * so no locking by fb_info->mm_lock around smem_len setting is needed.
-- */
--static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
--{
-- struct fb_info *info = sinfo->info;
-- struct fb_var_screeninfo *var = &info->var;
-- unsigned int smem_len;
--
-- smem_len = (var->xres_virtual * var->yres_virtual
-- * ((var->bits_per_pixel + 7) / 8));
-- info->fix.smem_len = max(smem_len, sinfo->smem_len);
--
-- info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len,
-- (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL);
--
-- if (!info->screen_base) {
-- return -ENOMEM;
-- }
--
-- memset(info->screen_base, 0, info->fix.smem_len);
--
-- if (cpu_is_at91sam9x5()) {
-- sinfo->p_dma_desc = dma_alloc_writecombine(info->device,
-- sizeof(struct lcd_dma_desc),
-- (dma_addr_t *)&(sinfo->dma_desc_phys),
-- GFP_KERNEL);
--
-- if (!sinfo->p_dma_desc) {
-- dma_free_writecombine(info->device, info->fix.smem_len,
-- info->screen_base, info->fix.smem_start);
-- return -ENOMEM;
-- }
-- }
--
-- return 0;
--}
--
--static const struct fb_videomode *atmel_lcdfb_choose_mode(struct fb_var_screeninfo *var,
-- struct fb_info *info)
--{
-- struct fb_videomode varfbmode;
-- const struct fb_videomode *fbmode = NULL;
--
-- fb_var_to_videomode(&varfbmode, var);
-- fbmode = fb_find_nearest_mode(&varfbmode, &info->modelist);
-- if (fbmode)
-- fb_videomode_to_var(var, fbmode);
-- return fbmode;
--}
--
--
--/**
-- * atmel_lcdfb_check_var - Validates a var passed in.
-- * @var: frame buffer variable screen structure
-- * @info: frame buffer structure that represents a single frame buffer
-- *
-- * Checks to see if the hardware supports the state requested by
-- * var passed in. This function does not alter the hardware
-- * state!!! This means the data stored in struct fb_info and
-- * struct atmel_lcdfb_info do not change. This includes the var
-- * inside of struct fb_info. Do NOT change these. This function
-- * can be called on its own if we intent to only test a mode and
-- * not actually set it. The stuff in modedb.c is a example of
-- * this. If the var passed in is slightly off by what the
-- * hardware can support then we alter the var PASSED in to what
-- * we can do. If the hardware doesn't support mode change a
-- * -EINVAL will be returned by the upper layers. You don't need
-- * to implement this function then. If you hardware doesn't
-- * support changing the resolution then this function is not
-- * needed. In this case the driver would just provide a var that
-- * represents the static state the screen is in.
-- *
-- * Returns negative errno on error, or zero on success.
-- */
--static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
-- struct fb_info *info)
--{
-- struct device *dev = info->device;
-- struct atmel_lcdfb_info *sinfo = info->par;
-- unsigned long clk_value_khz;
--
-- clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
--
-- dev_dbg(dev, "%s:\n", __func__);
--
-- if (!(var->pixclock && var->bits_per_pixel)) {
-- /* choose a suitable mode if possible */
-- if (!atmel_lcdfb_choose_mode(var, info)) {
-- dev_err(dev, "needed value not specified\n");
-- return -EINVAL;
-- }
-- }
--
-- dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres);
-- dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock));
-- dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel);
-- dev_dbg(dev, " clk: %lu KHz\n", clk_value_khz);
--
-- if (PICOS2KHZ(var->pixclock) > clk_value_khz) {
-- dev_err(dev, "%lu KHz pixel clock is too fast\n", PICOS2KHZ(var->pixclock));
-- return -EINVAL;
-- }
--
-- /* Do not allow to have real resoulution larger than virtual */
-- if (var->xres > var->xres_virtual)
-- var->xres_virtual = var->xres;
--
-- if (var->yres > var->yres_virtual)
-- var->yres_virtual = var->yres;
--
-- /* Force same alignment for each line */
-- var->xres = (var->xres + 3) & ~3UL;
-- var->xres_virtual = (var->xres_virtual + 3) & ~3UL;
--
-- var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
-- var->transp.msb_right = 0;
-- var->transp.offset = var->transp.length = 0;
-- var->xoffset = var->yoffset = 0;
--
-- if (info->fix.smem_len) {
-- unsigned int smem_len = (var->xres_virtual * var->yres_virtual
-- * ((var->bits_per_pixel + 7) / 8));
-- if (smem_len > info->fix.smem_len)
-- return -EINVAL;
-- }
--
-- /* Saturate vertical and horizontal timings at maximum values */
-- if (cpu_is_at91sam9x5()) {
-- var->vsync_len = min_t(u32, var->vsync_len,
-- (LCDC_LCDCFG1_VSPW >> LCDC_LCDCFG1_VSPW_OFFSET) + 1);
-- var->upper_margin = min_t(u32, var->upper_margin,
-- (LCDC_LCDCFG2_VFPW >> LCDC_LCDCFG2_VFPW_OFFSET) + 1);
-- var->lower_margin = min_t(u32, var->lower_margin,
-- LCDC_LCDCFG2_VBPW >> LCDC_LCDCFG2_VBPW_OFFSET);
-- var->right_margin = min_t(u32, var->right_margin,
-- (LCDC_LCDCFG3_HBPW >> LCDC_LCDCFG3_HBPW_OFFSET) + 1);
-- var->hsync_len = min_t(u32, var->hsync_len,
-- (LCDC_LCDCFG1_HSPW >> LCDC_LCDCFG1_HSPW_OFFSET) + 1);
-- var->left_margin = min_t(u32, var->left_margin,
-- (LCDC_LCDCFG3_HFPW >> LCDC_LCDCFG3_HFPW_OFFSET) + 1);
-- } else {
-- var->vsync_len = min_t(u32, var->vsync_len,
-- (ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1);
-- var->upper_margin = min_t(u32, var->upper_margin,
-- ATMEL_LCDC_VBP >> ATMEL_LCDC_VBP_OFFSET);
-- var->lower_margin = min_t(u32, var->lower_margin,
-- ATMEL_LCDC_VFP);
-- var->right_margin = min_t(u32, var->right_margin,
-- (ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 1);
-- var->hsync_len = min_t(u32, var->hsync_len,
-- (ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1);
-- var->left_margin = min_t(u32, var->left_margin,
-- ATMEL_LCDC_HBP + 1);
-- }
--
-- /* Some parameters can't be zero */
-- var->vsync_len = max_t(u32, var->vsync_len, 1);
-- var->right_margin = max_t(u32, var->right_margin, 1);
-- var->hsync_len = max_t(u32, var->hsync_len, 1);
-- var->left_margin = max_t(u32, var->left_margin, 1);
--
-- switch (var->bits_per_pixel) {
-- case 1:
-- case 2:
-- case 4:
-- case 8:
-- var->red.offset = var->green.offset = var->blue.offset = 0;
-- var->red.length = var->green.length = var->blue.length
-- = var->bits_per_pixel;
-- break;
-- case 12:
-- if (cpu_is_at91sam9x5()) {
-- /* RGB:444 mode */
-- var->red.offset = 8;
-- var->blue.offset = 0;
-- var->green.offset = 4;
-- var->red.length = var->green.length = var->blue.length = 4;
-- } else {
-- /*TODO: rework*/
-- BUG();
-- }
-- break;
-- case 15:
-- if (cpu_is_at91sam9x5()) {
-- /* RGB:555 mode */
-- var->red.offset = 10;
-- var->blue.offset = 0;
-- var->green.length = 5;
-- var->red.length = var->green.length = var->blue.length = 5;
-- } else {
-- /*TODO: rework*/
-- BUG();
-- }
-- break;
-- case 16:
-- if (cpu_is_at91sam9x5()) {
-- if (sinfo->alpha_enabled) {
-- /* ARGB:4444 mode */
-- var->red.offset = 8;
-- var->blue.offset = 0;
-- var->green.offset = 4;
-- var->transp.offset = 12;
-- var->red.length = var->green.length
-- = var->blue.length
-- = var->transp.length = 4;
-- } else {
-- /* RGB:565 mode */
-- var->red.offset = 11;
-- var->blue.offset = 0;
-- var->green.offset = 5;
-- var->green.length = 6;
-- var->red.length = var->blue.length = 5;
-- }
-- break;
-- }
-- /* Older SOCs use IBGR:555 rather than BGR:565. */
-- if (sinfo->have_intensity_bit)
-- var->green.length = 5;
-- else
-- var->green.length = 6;
--
-- if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
-- /* RGB:5X5 mode */
-- var->red.offset = var->green.length + 5;
-- var->blue.offset = 0;
-- } else {
-- /* BGR:5X5 mode */
-- var->red.offset = 0;
-- var->blue.offset = var->green.length + 5;
-- }
-- var->green.offset = 5;
-- var->red.length = var->blue.length = 5;
-- break;
-- case 32:
-- /* TODO 32 & 24 modes */
-- var->transp.offset = 24;
-- var->transp.length = 8;
-- /* fall through */
-- case 24:
-- if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
-- /* RGB:888 mode */
-- var->red.offset = 16;
-- var->blue.offset = 0;
-- } else {
-- /* BGR:888 mode */
-- var->red.offset = 0;
-- var->blue.offset = 16;
-- }
-- var->green.offset = 8;
-- var->red.length = var->green.length = var->blue.length = 8;
-- break;
-- default:
-- dev_err(dev, "color depth %d not supported\n",
-- var->bits_per_pixel);
-- return -EINVAL;
-- }
--
-- return 0;
--}
--
--/*
-- * LCD reset sequence
-- */
--static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo)
--{
-- might_sleep();
--
-- atmel_lcdfb_stop(sinfo);
-- atmel_lcdfb_start(sinfo);
--}
--
--static int atmel_lcdfb_setup_9x5_core(struct fb_info *info)
--{
-- struct atmel_lcdfb_info *sinfo = info->par;
-- unsigned long value;
-- unsigned long clk_value_khz;
--
-- dev_dbg(info->device, "%s:\n", __func__);
-- /* Set pixel clock */
-- clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
--
-- value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock));
--
-- if (value < 1) {
-- dev_notice(info->device, "using system clock as pixel clock\n");
-- value = LCDC_LCDCFG0_CLKPOL | LCDC_LCDCFG0_CLKPWMSEL | LCDC_LCDCFG0_CGDISBASE;
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG0, value);
-- } else {
-- info->var.pixclock = KHZ2PICOS(clk_value_khz / value);
-- dev_dbg(info->device, " updated pixclk: %lu KHz\n",
-- PICOS2KHZ(info->var.pixclock));
-- value = value - 2;
-- dev_dbg(info->device, " * programming CLKDIV = 0x%08lx\n",
-- value);
-- value = (value << LCDC_LCDCFG0_CLKDIV_OFFSET)
-- | LCDC_LCDCFG0_CLKPOL
-- | LCDC_LCDCFG0_CGDISBASE;
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG0, value);
-- }
--
-- /* Initialize control register 5 */
-- /* In 9x5, the default_lcdcon2 will use for LCDCFG5 */
-- value = sinfo->default_lcdcon2;
-- value |= (sinfo->guard_time << LCDC_LCDCFG5_GUARDTIME_OFFSET)
-- | LCDC_LCDCFG5_DISPDLY
-- | LCDC_LCDCFG5_VSPDLYS;
--
-- if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
-- value |= LCDC_LCDCFG5_HSPOL;
-- if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
-- value |= LCDC_LCDCFG5_VSPOL;
--
-- dev_dbg(info->device, " * LCDC_LCDCFG5 = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG5, value);
--
-- /* Vertical & Horizontal Timing */
-- value = (info->var.vsync_len - 1) << LCDC_LCDCFG1_VSPW_OFFSET;
-- value |= (info->var.hsync_len - 1) << LCDC_LCDCFG1_HSPW_OFFSET;
-- dev_dbg(info->device, " * LCDC_LCDCFG1 = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG1, value);
--
-- value = (info->var.lower_margin) << LCDC_LCDCFG2_VBPW_OFFSET;
-- value |= (info->var.upper_margin - 1) << LCDC_LCDCFG2_VFPW_OFFSET;
-- dev_dbg(info->device, " * LCDC_LCDCFG2 = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG2, value);
--
-- value = (info->var.right_margin - 1) << LCDC_LCDCFG3_HBPW_OFFSET;
-- value |= (info->var.left_margin - 1) << LCDC_LCDCFG3_HFPW_OFFSET;
-- dev_dbg(info->device, " * LCDC_LCDCFG3 = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG3, value);
--
-- /* Display size */
-- value = (info->var.yres - 1) << LCDC_LCDCFG4_RPF_OFFSET;
-- value |= (info->var.xres - 1) << LCDC_LCDCFG4_PPL_OFFSET;
-- dev_dbg(info->device, " * LCDC_LCDCFG4 = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG4, value);
--
-- lcdc_writel(sinfo, ATMEL_LCDC_BASECFG0, LCDC_BASECFG0_BLEN_AHB_INCR4 | LCDC_BASECFG0_DLBO);
-- switch (info->var.bits_per_pixel) {
-- case 12:
-- value = LCDC_BASECFG1_RGBMODE_12BPP_RGB_444;
-- break;
-- case 16:
-- if (info->var.transp.offset != 0)
-- value = LCDC_BASECFG1_RGBMODE_16BPP_ARGB_4444;
-- else
-- value = LCDC_BASECFG1_RGBMODE_16BPP_RGB_565;
-- break;
-- case 18:
-- value = LCDC_BASECFG1_RGBMODE_18BPP_RGB_666_PACKED;
-- break;
-- case 24:
-- value = LCDC_BASECFG1_RGBMODE_24BPP_RGB_888_PACKED;
-- break;
-- case 32:
-- value = LCDC_BASECFG1_RGBMODE_32BPP_ARGB_8888;
-- break;
-- default:
-- BUG();
-- break;
-- }
-- lcdc_writel(sinfo, ATMEL_LCDC_BASECFG1, value);
-- lcdc_writel(sinfo, ATMEL_LCDC_BASECFG2, 0);
-- lcdc_writel(sinfo, ATMEL_LCDC_BASECFG3, 0); /* Default color */
-- lcdc_writel(sinfo, ATMEL_LCDC_BASECFG4, LCDC_BASECFG4_DMA);
--
-- /* Disable all interrupts */
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDIDR, ~0UL);
-- lcdc_writel(sinfo, ATMEL_LCDC_BASEIDR, ~0UL);
-- /* Enable BASE LAYER overflow interrupts, if want to enable DMA interrupt, also need set it at LCDC_BASECTRL reg */
-- lcdc_writel(sinfo, ATMEL_LCDC_BASEIER, LCDC_BASEIER_OVR);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDIER, LCDC_LCDIER_FIFOERRIE | LCDC_LCDIER_BASEIE);
--
-- return 0;
--}
--
--static int atmel_lcdfb_setup_core(struct fb_info *info)
--{
-- struct atmel_lcdfb_info *sinfo = info->par;
-- unsigned long hozval_linesz;
-- unsigned long value;
-- unsigned long clk_value_khz;
-- unsigned long pix_factor = 2;
--
-- if (cpu_is_at91sam9x5()) {
-- return atmel_lcdfb_setup_9x5_core(info);
-- } else {
-- /* ...set frame size and burst length = 8 words (?) */
-- value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32;
-- value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET);
-- lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value);
--
-- /* Set pixel clock */
-- if (cpu_is_at91sam9g45() && !cpu_is_at91sam9g45es())
-- pix_factor = 1;
--
-- clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
--
-- value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock));
--
-- if (value < pix_factor) {
-- dev_notice(info->device, "Bypassing pixel clock divider\n");
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
-- } else {
-- value = (value / pix_factor) - 1;
-- dev_dbg(info->device, " * programming CLKVAL = 0x%08lx\n",
-- value);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1,
-- value << ATMEL_LCDC_CLKVAL_OFFSET);
-- info->var.pixclock =
-- KHZ2PICOS(clk_value_khz / (pix_factor * (value + 1)));
-- dev_dbg(info->device, " updated pixclk: %lu KHz\n",
-- PICOS2KHZ(info->var.pixclock));
-- }
--
--
-- /* Initialize control register 2 */
-- value = sinfo->default_lcdcon2;
--
-- if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
-- value |= ATMEL_LCDC_INVLINE_INVERTED;
-- if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
-- value |= ATMEL_LCDC_INVFRAME_INVERTED;
--
-- switch (info->var.bits_per_pixel) {
-- case 1:
-- value |= ATMEL_LCDC_PIXELSIZE_1;
-- break;
-- case 2:
-- value |= ATMEL_LCDC_PIXELSIZE_2;
-- break;
-- case 4:
-- value |= ATMEL_LCDC_PIXELSIZE_4;
-- break;
-- case 8:
-- value |= ATMEL_LCDC_PIXELSIZE_8;
-- break;
-- case 15: /* fall through */
-- case 16:
-- value |= ATMEL_LCDC_PIXELSIZE_16;
-- break;
-- case 24:
-- value |= ATMEL_LCDC_PIXELSIZE_24;
-- break;
-- case 32:
-- value |= ATMEL_LCDC_PIXELSIZE_32;
-- break;
-- default:
-- BUG();
-- break;
-- }
-- dev_dbg(info->device, " * LCDCON2 = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value);
--
-- /* Vertical timing */
-- value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET;
-- value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET;
-- value |= info->var.lower_margin;
-- dev_dbg(info->device, " * LCDTIM1 = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value);
--
-- /* Horizontal timing */
-- value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET;
-- value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET;
-- value |= (info->var.left_margin - 1);
-- dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
--
-- /* Horizontal value (aka line size) */
-- hozval_linesz = compute_hozval(info->var.xres,
-- lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2));
--
-- /* Display size */
-- value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
-- value |= info->var.yres - 1;
-- dev_dbg(info->device, " * LCDFRMCFG = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value);
--
-- /* FIFO Threshold: Use formula from data sheet */
-- value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3);
-- lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value);
--
-- /* Toggle LCD_MODE every frame */
-- lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0);
--
-- /* Disable all interrupts */
-- lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
-- /* Enable FIFO & DMA errors */
-- lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
--
-- /* ...wait for DMA engine to become idle... */
-- while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
-- msleep(10);
--
-- return 0;
-- }
--}
--
--/**
-- * atmel_lcdfb_set_par - Alters the hardware state.
-- * @info: frame buffer structure that represents a single frame buffer
-- *
-- * Using the fb_var_screeninfo in fb_info we set the resolution
-- * of the this particular framebuffer. This function alters the
-- * par AND the fb_fix_screeninfo stored in fb_info. It doesn't
-- * not alter var in fb_info since we are using that data. This
-- * means we depend on the data in var inside fb_info to be
-- * supported by the hardware. atmel_lcdfb_check_var is always called
-- * before atmel_lcdfb_set_par to ensure this. Again if you can't
-- * change the resolution you don't need this function.
-- *
-- */
--static int atmel_lcdfb_set_par(struct fb_info *info)
--{
-- struct atmel_lcdfb_info *sinfo = info->par;
-- unsigned long bits_per_line;
--
-- might_sleep();
--
-- dev_dbg(info->device, "%s:\n", __func__);
-- dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n",
-- info->var.xres, info->var.yres,
-- info->var.xres_virtual, info->var.yres_virtual);
--
-- atmel_lcdfb_stop_nowait(sinfo);
--
-- if (info->var.bits_per_pixel == 1)
-- info->fix.visual = FB_VISUAL_MONO01;
-- else if (info->var.bits_per_pixel <= 8)
-- info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-- else
-- info->fix.visual = FB_VISUAL_TRUECOLOR;
--
-- bits_per_line = info->var.xres_virtual * info->var.bits_per_pixel;
-- info->fix.line_length = DIV_ROUND_UP(bits_per_line, 8);
--
-- /* Re-initialize the DMA engine... */
-- dev_dbg(info->device, " * update DMA engine\n");
-- atmel_lcdfb_update_dma(info, &info->var);
--
-- /* Now, the LCDC core... */
-- atmel_lcdfb_setup_core(info);
--
-- atmel_lcdfb_start(sinfo);
--
-- dev_dbg(info->device, " * DONE\n");
--
-- return 0;
--}
--
--static inline unsigned int chan_to_field(unsigned int chan, const struct fb_bitfield *bf)
--{
-- chan &= 0xffff;
-- chan >>= 16 - bf->length;
-- return chan << bf->offset;
--}
--
--/**
-- * atmel_lcdfb_setcolreg - Optional function. Sets a color register.
-- * @regno: Which register in the CLUT we are programming
-- * @red: The red value which can be up to 16 bits wide
-- * @green: The green value which can be up to 16 bits wide
-- * @blue: The blue value which can be up to 16 bits wide.
-- * @transp: If supported the alpha value which can be up to 16 bits wide.
-- * @info: frame buffer info structure
-- *
-- * Set a single color register. The values supplied have a 16 bit
-- * magnitude which needs to be scaled in this function for the hardware.
-- * Things to take into consideration are how many color registers, if
-- * any, are supported with the current color visual. With truecolor mode
-- * no color palettes are supported. Here a pseudo palette is created
-- * which we store the value in pseudo_palette in struct fb_info. For
-- * pseudocolor mode we have a limited color palette. To deal with this
-- * we can program what color is displayed for a particular pixel value.
-- * DirectColor is similar in that we can program each color field. If
-- * we have a static colormap we don't need to implement this function.
-- *
-- * Returns negative errno on error, or zero on success. In an
-- * ideal world, this would have been the case, but as it turns
-- * out, the other drivers return 1 on failure, so that's what
-- * we're going to do.
-- */
--static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
-- unsigned int green, unsigned int blue,
-- unsigned int transp, struct fb_info *info)
--{
-- struct atmel_lcdfb_info *sinfo = info->par;
-- unsigned int val;
-- u32 *pal;
-- int ret = 1;
--
-- if (info->var.grayscale)
-- red = green = blue = (19595 * red + 38470 * green
-- + 7471 * blue) >> 16;
--
-- switch (info->fix.visual) {
-- case FB_VISUAL_TRUECOLOR:
-- if (regno < 16) {
-- pal = info->pseudo_palette;
--
-- val = chan_to_field(red, &info->var.red);
-- val |= chan_to_field(green, &info->var.green);
-- val |= chan_to_field(blue, &info->var.blue);
--
-- pal[regno] = val;
-- ret = 0;
-- }
-- break;
--
-- case FB_VISUAL_PSEUDOCOLOR:
-- if (regno < 256) {
-- if (sinfo->have_intensity_bit) {
-- /* old style I+BGR:555 */
-- val = ((red >> 11) & 0x001f);
-- val |= ((green >> 6) & 0x03e0);
-- val |= ((blue >> 1) & 0x7c00);
--
-- /*
-- * TODO: intensity bit. Maybe something like
-- * ~(red[10] ^ green[10] ^ blue[10]) & 1
-- */
-- } else {
-- /* new style BGR:565 / RGB:565 */
-- if (sinfo->lcd_wiring_mode ==
-- ATMEL_LCDC_WIRING_RGB) {
-- val = ((blue >> 11) & 0x001f);
-- val |= ((red >> 0) & 0xf800);
-- } else {
-- val = ((red >> 11) & 0x001f);
-- val |= ((blue >> 0) & 0xf800);
-- }
--
-- val |= ((green >> 5) & 0x07e0);
-- }
--
-- lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
-- ret = 0;
-- }
-- break;
--
-- case FB_VISUAL_MONO01:
-- if (regno < 2) {
-- val = (regno == 0) ? 0x00 : 0x1F;
-- lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
-- ret = 0;
-- }
-- break;
--
-- }
--
-- return ret;
--}
--
--static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var,
-- struct fb_info *info)
--{
-- dev_dbg(info->device, "%s\n", __func__);
--
-- atmel_lcdfb_update_dma(info, var);
--
-- return 0;
--}
--
--static int atmel_lcdfb_blank(int blank_mode, struct fb_info *info)
--{
-- struct atmel_lcdfb_info *sinfo = info->par;
--
-- switch (blank_mode) {
-- case FB_BLANK_UNBLANK:
-- case FB_BLANK_NORMAL:
-- atmel_lcdfb_start(sinfo);
-- break;
-- case FB_BLANK_VSYNC_SUSPEND:
-- case FB_BLANK_HSYNC_SUSPEND:
-- break;
-- case FB_BLANK_POWERDOWN:
-- atmel_lcdfb_stop(sinfo);
-- break;
-- default:
-- return -EINVAL;
-- }
--
-- /* let fbcon do a soft blank for us */
-- return ((blank_mode == FB_BLANK_NORMAL) ? 1 : 0);
--}
--
--static struct fb_ops atmel_lcdfb_ops = {
-- .owner = THIS_MODULE,
-- .fb_check_var = atmel_lcdfb_check_var,
-- .fb_set_par = atmel_lcdfb_set_par,
-- .fb_setcolreg = atmel_lcdfb_setcolreg,
-- .fb_blank = atmel_lcdfb_blank,
-- .fb_pan_display = atmel_lcdfb_pan_display,
-- .fb_fillrect = cfb_fillrect,
-- .fb_copyarea = cfb_copyarea,
-- .fb_imageblit = cfb_imageblit,
--};
--
--static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
--{
-- struct fb_info *info = dev_id;
-- struct atmel_lcdfb_info *sinfo = info->par;
-- u32 status;
-- u32 baselayer_status;
--
-- if (cpu_is_at91sam9x5()) {
-- /* Check for error status via interrupt.*/
-- status = lcdc_readl(sinfo, ATMEL_LCDC_LCDISR);
-- if (status & LCDC_LCDISR_FIFOERR) {
-- dev_warn(info->device, "FIFO underflow %#x\n", status);
-- } else if (status & LCDC_LCDISR_BASE) {
-- /* Check base layer's overflow error. */
-- baselayer_status = lcdc_readl(sinfo, ATMEL_LCDC_BASEISR);
--
-- if (baselayer_status & LCDC_BASEISR_OVR)
-- dev_warn(info->device, "base layer overflow %#x\n",
-- baselayer_status);
--
-- }
-- } else {
-- status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
-- if (status & ATMEL_LCDC_UFLWI) {
-- dev_warn(info->device, "FIFO underflow %#x\n", status);
-- /* reset DMA and FIFO to avoid screen shifting */
-- schedule_work(&sinfo->task);
-- }
-- lcdc_writel(sinfo, ATMEL_LCDC_ICR, status);
-- }
--
-- return IRQ_HANDLED;
--}
--
--/*
-- * LCD controller task (to reset the LCD)
-- */
--static void atmel_lcdfb_task(struct work_struct *work)
--{
-- struct atmel_lcdfb_info *sinfo =
-- container_of(work, struct atmel_lcdfb_info, task);
--
-- atmel_lcdfb_reset(sinfo);
--}
--
--static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
--{
-- struct fb_info *info = sinfo->info;
-- int ret = 0;
--
-- info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;
--
-- dev_info(info->device,
-- "%luKiB frame buffer at %08lx (mapped at %p)\n",
-- (unsigned long)info->fix.smem_len / 1024,
-- (unsigned long)info->fix.smem_start,
-- info->screen_base);
--
-- /* Allocate colormap */
-- ret = fb_alloc_cmap(&info->cmap, 256, 0);
-- if (ret < 0)
-- dev_err(info->device, "Alloc color map failed\n");
--
-- return ret;
--}
--
--static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo)
--{
-- if (sinfo->bus_clk)
-- clk_enable(sinfo->bus_clk);
-- clk_enable(sinfo->lcdc_clk);
--}
--
--static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
--{
-- if (sinfo->bus_clk)
-- clk_disable(sinfo->bus_clk);
-- clk_disable(sinfo->lcdc_clk);
--}
--
--
--static int __init atmel_lcdfb_probe(struct platform_device *pdev)
--{
-- struct device *dev = &pdev->dev;
-- struct fb_info *info;
-- struct atmel_lcdfb_info *sinfo;
-- struct atmel_lcdfb_info *pdata_sinfo;
-- struct fb_videomode fbmode;
-- struct resource *regs = NULL;
-- struct resource *map = NULL;
-- int ret;
--
-- dev_dbg(dev, "%s BEGIN\n", __func__);
--
-- ret = -ENOMEM;
-- info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev);
-- if (!info) {
-- dev_err(dev, "cannot allocate memory\n");
-- goto out;
-- }
--
-- sinfo = info->par;
--
-- if (dev->platform_data) {
-- pdata_sinfo = (struct atmel_lcdfb_info *)dev->platform_data;
-- sinfo->default_bpp = pdata_sinfo->default_bpp;
-- sinfo->default_dmacon = pdata_sinfo->default_dmacon;
-- sinfo->default_lcdcon2 = pdata_sinfo->default_lcdcon2;
-- sinfo->default_monspecs = pdata_sinfo->default_monspecs;
-- sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control;
-- sinfo->guard_time = pdata_sinfo->guard_time;
-- sinfo->smem_len = pdata_sinfo->smem_len;
-- sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight;
-- sinfo->lcdcon_pol_negative = pdata_sinfo->lcdcon_pol_negative;
-- sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode;
-- } else {
-- dev_err(dev, "cannot get default configuration\n");
-- goto free_info;
-- }
-- sinfo->info = info;
-- sinfo->pdev = pdev;
-- if (cpu_is_at91sam9261() || cpu_is_at91sam9263() ||
-- cpu_is_at91sam9rl()) {
-- sinfo->have_intensity_bit = true;
-- }
--
-- strcpy(info->fix.id, sinfo->pdev->name);
-- info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
-- info->pseudo_palette = sinfo->pseudo_palette;
-- info->fbops = &atmel_lcdfb_ops;
--
-- memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs));
-- info->fix = atmel_lcdfb_fix;
--
-- /* Enable LCDC Clocks */
-- if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()
-- || cpu_is_at32ap7000()) {
-- sinfo->bus_clk = clk_get(dev, "hck1");
-- if (IS_ERR(sinfo->bus_clk)) {
-- ret = PTR_ERR(sinfo->bus_clk);
-- goto free_info;
-- }
-- }
-- sinfo->lcdc_clk = clk_get(dev, "lcdc_clk");
-- if (IS_ERR(sinfo->lcdc_clk)) {
-- ret = PTR_ERR(sinfo->lcdc_clk);
-- goto put_bus_clk;
-- }
-- atmel_lcdfb_start_clock(sinfo);
--
-- ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb,
-- info->monspecs.modedb_len, info->monspecs.modedb,
-- sinfo->default_bpp);
-- if (!ret) {
-- dev_err(dev, "no suitable video mode found\n");
-- goto stop_clk;
-- }
--
--
-- regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- if (!regs) {
-- dev_err(dev, "resources unusable\n");
-- ret = -ENXIO;
-- goto stop_clk;
-- }
--
-- sinfo->irq_base = platform_get_irq(pdev, 0);
-- if (sinfo->irq_base < 0) {
-- dev_err(dev, "unable to get irq\n");
-- ret = sinfo->irq_base;
-- goto stop_clk;
-- }
--
-- /* Initialize video memory */
-- map = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-- sinfo->p_dma_desc = NULL;
-- sinfo->dma_desc_phys = 0;
-- if (map) {
-- /* use a pre-allocated memory buffer */
-- info->fix.smem_start = map->start;
-- info->fix.smem_len = resource_size(map);
-- if (!request_mem_region(info->fix.smem_start,
-- info->fix.smem_len, pdev->name)) {
-- ret = -EBUSY;
-- goto stop_clk;
-- }
--
-- info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
-- if (!info->screen_base)
-- goto release_intmem;
--
-- /*
-- * Don't clear the framebuffer -- someone may have set
-- * up a splash image.
-- */
-- } else {
-- /* alocate memory buffer */
-- ret = atmel_lcdfb_alloc_video_memory(sinfo);
-- if (ret < 0) {
-- dev_err(dev, "cannot allocate framebuffer: %d\n", ret);
-- goto stop_clk;
-- }
-- }
--
-- /* LCDC registers */
-- info->fix.mmio_start = regs->start;
-- info->fix.mmio_len = resource_size(regs);
--
-- if (!request_mem_region(info->fix.mmio_start,
-- info->fix.mmio_len, pdev->name)) {
-- ret = -EBUSY;
-- goto free_fb;
-- }
--
-- sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len);
-- if (!sinfo->mmio) {
-- dev_err(dev, "cannot map LCDC registers\n");
-- goto release_mem;
-- }
--
-- /* Initialize PWM for contrast or backlight ("off") */
-- init_contrast(sinfo);
--
-- /* interrupt */
-- ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info);
-- if (ret) {
-- dev_err(dev, "request_irq failed: %d\n", ret);
-- goto unmap_mmio;
-- }
--
-- /* Some operations on the LCDC might sleep and
-- * require a preemptible task context */
-- INIT_WORK(&sinfo->task, atmel_lcdfb_task);
--
-- ret = atmel_lcdfb_init_fbinfo(sinfo);
-- if (ret < 0) {
-- dev_err(dev, "init fbinfo failed: %d\n", ret);
-- goto unregister_irqs;
-- }
--
-- /*
-- * This makes sure that our colour bitfield
-- * descriptors are correctly initialised.
-- */
-- atmel_lcdfb_check_var(&info->var, info);
--
-- ret = fb_set_var(info, &info->var);
-- if (ret) {
-- dev_warn(dev, "unable to set display parameters\n");
-- goto free_cmap;
-- }
--
-- dev_set_drvdata(dev, info);
--
-- /*
-- * Tell the world that we're ready to go
-- */
-- ret = register_framebuffer(info);
-- if (ret < 0) {
-- dev_err(dev, "failed to register framebuffer device: %d\n", ret);
-- goto reset_drvdata;
-- }
--
-- /* add selected videomode to modelist */
-- fb_var_to_videomode(&fbmode, &info->var);
-- fb_add_videomode(&fbmode, &info->modelist);
--
-- /* Power up the LCDC screen */
-- if (sinfo->atmel_lcdfb_power_control)
-- sinfo->atmel_lcdfb_power_control(1);
--
-- dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %d\n",
-- info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base);
--
-- return 0;
--
--reset_drvdata:
-- dev_set_drvdata(dev, NULL);
--free_cmap:
-- fb_dealloc_cmap(&info->cmap);
--unregister_irqs:
-- cancel_work_sync(&sinfo->task);
-- free_irq(sinfo->irq_base, info);
--unmap_mmio:
-- exit_backlight(sinfo);
-- iounmap(sinfo->mmio);
--release_mem:
-- release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
--free_fb:
-- if (map)
-- iounmap(info->screen_base);
-- else
-- atmel_lcdfb_free_video_memory(sinfo);
--
--release_intmem:
-- if (map)
-- release_mem_region(info->fix.smem_start, info->fix.smem_len);
--stop_clk:
-- atmel_lcdfb_stop_clock(sinfo);
-- clk_put(sinfo->lcdc_clk);
--put_bus_clk:
-- if (sinfo->bus_clk)
-- clk_put(sinfo->bus_clk);
--free_info:
-- framebuffer_release(info);
--out:
-- dev_dbg(dev, "%s FAILED\n", __func__);
-- return ret;
--}
--
--static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
--{
-- struct device *dev = &pdev->dev;
-- struct fb_info *info = dev_get_drvdata(dev);
-- struct atmel_lcdfb_info *sinfo;
--
-- if (!info || !info->par)
-- return 0;
-- sinfo = info->par;
--
-- cancel_work_sync(&sinfo->task);
-- exit_backlight(sinfo);
-- if (sinfo->atmel_lcdfb_power_control)
-- sinfo->atmel_lcdfb_power_control(0);
-- unregister_framebuffer(info);
-- atmel_lcdfb_stop_clock(sinfo);
-- clk_put(sinfo->lcdc_clk);
-- if (sinfo->bus_clk)
-- clk_put(sinfo->bus_clk);
-- fb_dealloc_cmap(&info->cmap);
-- free_irq(sinfo->irq_base, info);
-- iounmap(sinfo->mmio);
-- release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
-- if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) {
-- iounmap(info->screen_base);
-- release_mem_region(info->fix.smem_start, info->fix.smem_len);
-- } else {
-- atmel_lcdfb_free_video_memory(sinfo);
-- }
--
-- dev_set_drvdata(dev, NULL);
-- framebuffer_release(info);
--
-- return 0;
--}
-
- #ifdef CONFIG_PM
-
-@@ -1425,16 +28,10 @@ static int atmel_lcdfb_suspend(struct pl
- * We don't want to handle interrupts while the clock is
- * stopped. It may take forever.
- */
-- if (cpu_is_at91sam9x5()) {
-- /* Disable all interrupts */
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDIDR, ~0UL);
-- lcdc_writel(sinfo, ATMEL_LCDC_BASEIDR, ~0UL);
-- } else {
-- lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
--
-- sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
-- }
-+ lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
-+
-+ sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
-
- if (sinfo->atmel_lcdfb_power_control)
- sinfo->atmel_lcdfb_power_control(0);
-@@ -1455,17 +52,11 @@ static int atmel_lcdfb_resume(struct pla
- if (sinfo->atmel_lcdfb_power_control)
- sinfo->atmel_lcdfb_power_control(1);
-
-- if (cpu_is_at91sam9x5()) {
-- /* Enable fifo error & BASE LAYER overflow interrupts */
-- lcdc_writel(sinfo, ATMEL_LCDC_BASEIER, LCDC_BASEIER_OVR);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDIER, LCDC_LCDIER_FIFOERRIE | LCDC_LCDIER_BASEIE);
-- } else {
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon);
--
-- /* Enable FIFO & DMA errors */
-- lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI
-- | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
-- }
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon);
-+
-+ /* Enable FIFO & DMA errors */
-+ lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI
-+ | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
-
- return 0;
- }
-@@ -1475,6 +66,15 @@ static int atmel_lcdfb_resume(struct pla
- #define atmel_lcdfb_resume NULL
- #endif
-
-+static int __init atmel_lcdfb_probe(struct platform_device *pdev)
-+{
-+ return __atmel_lcdfb_probe(pdev);
-+}
-+static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
-+{
-+ return __atmel_lcdfb_remove(pdev);
-+}
-+
- static struct platform_driver atmel_lcdfb_driver = {
- .remove = __exit_p(atmel_lcdfb_remove),
- .suspend = atmel_lcdfb_suspend,
-@@ -1490,13 +90,12 @@ static int __init atmel_lcdfb_init(void)
- {
- return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe);
- }
-+module_init(atmel_lcdfb_init);
-
- static void __exit atmel_lcdfb_exit(void)
- {
- platform_driver_unregister(&atmel_lcdfb_driver);
- }
--
--module_init(atmel_lcdfb_init);
- module_exit(atmel_lcdfb_exit);
-
- MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver");
---- /dev/null
-+++ b/drivers/video/atmel_lcdfb_core.c
-@@ -0,0 +1,1077 @@
-+/*
-+ * Driver for AT91/AT32 LCD Controller
-+ *
-+ * Copyright (C) 2007 Atmel Corporation
-+ *
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file COPYING in the main directory of this archive for
-+ * more details.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/platform_device.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/interrupt.h>
-+#include <linux/clk.h>
-+#include <linux/fb.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/backlight.h>
-+#include <linux/gfp.h>
-+
-+#include <mach/board.h>
-+#include <mach/cpu.h>
-+#include <mach/gpio.h>
-+
-+#include <video/atmel_lcdc.h>
-+
-+/* configurable parameters */
-+#define ATMEL_LCDC_CVAL_DEFAULT 0xc8
-+#define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */
-+#define ATMEL_LCDC_FIFO_SIZE 512 /* words */
-+
-+#if defined(CONFIG_ARCH_AT91)
-+#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
-+ | FBINFO_PARTIAL_PAN_OK \
-+ | FBINFO_HWACCEL_YPAN)
-+
-+static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
-+ struct fb_var_screeninfo *var)
-+{
-+
-+}
-+#elif defined(CONFIG_AVR32)
-+#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
-+ | FBINFO_PARTIAL_PAN_OK \
-+ | FBINFO_HWACCEL_XPAN \
-+ | FBINFO_HWACCEL_YPAN)
-+
-+static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
-+ struct fb_var_screeninfo *var)
-+{
-+ u32 dma2dcfg;
-+ u32 pixeloff;
-+
-+ pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f;
-+
-+ dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8;
-+ dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
-+
-+ /* Update configuration */
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON,
-+ lcdc_readl(sinfo, ATMEL_LCDC_DMACON)
-+ | ATMEL_LCDC_DMAUPDT);
-+}
-+#endif
-+
-+static u32 contrast_ctr = ATMEL_LCDC_PS_DIV8
-+ | ATMEL_LCDC_POL_POSITIVE
-+ | ATMEL_LCDC_ENA_PWMENABLE;
-+
-+#ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
-+
-+/* some bl->props field just changed */
-+static int atmel_bl_update_status(struct backlight_device *bl)
-+{
-+ struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
-+ int power = sinfo->bl_power;
-+ int brightness = bl->props.brightness;
-+
-+ /* REVISIT there may be a meaningful difference between
-+ * fb_blank and power ... there seem to be some cases
-+ * this doesn't handle correctly.
-+ */
-+ if (bl->props.fb_blank != sinfo->bl_power)
-+ power = bl->props.fb_blank;
-+ else if (bl->props.power != sinfo->bl_power)
-+ power = bl->props.power;
-+
-+ if (brightness < 0 && power == FB_BLANK_UNBLANK)
-+ brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
-+ else if (power != FB_BLANK_UNBLANK)
-+ brightness = 0;
-+
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
-+ brightness ? contrast_ctr : 0);
-+
-+ bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;
-+
-+ return 0;
-+}
-+
-+static int atmel_bl_get_brightness(struct backlight_device *bl)
-+{
-+ struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
-+
-+ return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
-+}
-+
-+static const struct backlight_ops atmel_lcdc_bl_ops = {
-+ .update_status = atmel_bl_update_status,
-+ .get_brightness = atmel_bl_get_brightness,
-+};
-+
-+static void init_backlight(struct atmel_lcdfb_info *sinfo)
-+{
-+ struct backlight_properties props;
-+ struct backlight_device *bl;
-+
-+ sinfo->bl_power = FB_BLANK_UNBLANK;
-+
-+ if (sinfo->backlight)
-+ return;
-+
-+ memset(&props, 0, sizeof(struct backlight_properties));
-+ props.type = BACKLIGHT_RAW;
-+ props.max_brightness = 0xff;
-+ bl = backlight_device_register("backlight", &sinfo->pdev->dev, sinfo,
-+ &atmel_lcdc_bl_ops, &props);
-+ if (IS_ERR(bl)) {
-+ dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n",
-+ PTR_ERR(bl));
-+ return;
-+ }
-+ sinfo->backlight = bl;
-+
-+ bl->props.power = FB_BLANK_UNBLANK;
-+ bl->props.fb_blank = FB_BLANK_UNBLANK;
-+ bl->props.brightness = atmel_bl_get_brightness(bl);
-+}
-+
-+static void exit_backlight(struct atmel_lcdfb_info *sinfo)
-+{
-+ if (sinfo->backlight)
-+ backlight_device_unregister(sinfo->backlight);
-+}
-+
-+#else
-+
-+static void init_backlight(struct atmel_lcdfb_info *sinfo)
-+{
-+ dev_warn(&sinfo->pdev->dev, "backlight control is not available\n");
-+}
-+
-+static void exit_backlight(struct atmel_lcdfb_info *sinfo)
-+{
-+}
-+
-+#endif
-+
-+static void init_contrast(struct atmel_lcdfb_info *sinfo)
-+{
-+ /* contrast pwm can be 'inverted' */
-+ if (sinfo->lcdcon_pol_negative)
-+ contrast_ctr &= ~(ATMEL_LCDC_POL_POSITIVE);
-+
-+ /* have some default contrast/backlight settings */
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
-+
-+ if (sinfo->lcdcon_is_backlight)
-+ init_backlight(sinfo);
-+}
-+
-+
-+static struct fb_fix_screeninfo atmel_lcdfb_fix = {
-+ .type = FB_TYPE_PACKED_PIXELS,
-+ .visual = FB_VISUAL_TRUECOLOR,
-+ .xpanstep = 0,
-+ .ypanstep = 1,
-+ .ywrapstep = 0,
-+ .accel = FB_ACCEL_NONE,
-+};
-+
-+static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2)
-+{
-+ unsigned long value;
-+
-+ if (!(cpu_is_at91sam9261() || cpu_is_at91sam9g10()
-+ || cpu_is_at32ap7000()))
-+ return xres;
-+
-+ value = xres;
-+ if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) {
-+ /* STN display */
-+ if ((lcdcon2 & ATMEL_LCDC_DISTYPE) == ATMEL_LCDC_DISTYPE_STNCOLOR) {
-+ value *= 3;
-+ }
-+ if ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_4
-+ || ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_8
-+ && (lcdcon2 & ATMEL_LCDC_SCANMOD) == ATMEL_LCDC_SCANMOD_DUAL ))
-+ value = DIV_ROUND_UP(value, 4);
-+ else
-+ value = DIV_ROUND_UP(value, 8);
-+ }
-+
-+ return value;
-+}
-+
-+static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo)
-+{
-+ /* Turn off the LCD controller and the DMA controller */
-+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-+ sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
-+
-+ /* Wait for the LCDC core to become idle */
-+ while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
-+ msleep(10);
-+
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
-+}
-+
-+void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo)
-+{
-+ atmel_lcdfb_stop_nowait(sinfo);
-+
-+ /* Wait for DMA engine to become idle... */
-+ while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
-+ msleep(10);
-+}
-+EXPORT_SYMBOL_GPL(atmel_lcdfb_stop);
-+
-+void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo)
-+{
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
-+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-+ (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET)
-+ | ATMEL_LCDC_PWR);
-+}
-+EXPORT_SYMBOL_GPL(atmel_lcdfb_start);
-+
-+static void atmel_lcdfb_update_dma(struct fb_info *info,
-+ struct fb_var_screeninfo *var)
-+{
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ struct fb_fix_screeninfo *fix = &info->fix;
-+ unsigned long dma_addr;
-+
-+ dma_addr = (fix->smem_start + var->yoffset * fix->line_length
-+ + var->xoffset * var->bits_per_pixel / 8);
-+
-+ dma_addr &= ~3UL;
-+
-+ /* Set framebuffer DMA base address and pixel offset */
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
-+
-+ atmel_lcdfb_update_dma2d(sinfo, var);
-+}
-+
-+static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
-+{
-+ struct fb_info *info = sinfo->info;
-+
-+ dma_free_writecombine(info->device, info->fix.smem_len,
-+ info->screen_base, info->fix.smem_start);
-+}
-+
-+/**
-+ * atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory
-+ * @sinfo: the frame buffer to allocate memory for
-+ *
-+ * This function is called only from the atmel_lcdfb_probe()
-+ * so no locking by fb_info->mm_lock around smem_len setting is needed.
-+ */
-+static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
-+{
-+ struct fb_info *info = sinfo->info;
-+ struct fb_var_screeninfo *var = &info->var;
-+ unsigned int smem_len;
-+
-+ smem_len = (var->xres_virtual * var->yres_virtual
-+ * ((var->bits_per_pixel + 7) / 8));
-+ info->fix.smem_len = max(smem_len, sinfo->smem_len);
-+
-+ info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len,
-+ (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL);
-+
-+ if (!info->screen_base) {
-+ return -ENOMEM;
-+ }
-+
-+ memset(info->screen_base, 0, info->fix.smem_len);
-+
-+ return 0;
-+}
-+
-+static const struct fb_videomode *atmel_lcdfb_choose_mode(struct fb_var_screeninfo *var,
-+ struct fb_info *info)
-+{
-+ struct fb_videomode varfbmode;
-+ const struct fb_videomode *fbmode = NULL;
-+
-+ fb_var_to_videomode(&varfbmode, var);
-+ fbmode = fb_find_nearest_mode(&varfbmode, &info->modelist);
-+ if (fbmode)
-+ fb_videomode_to_var(var, fbmode);
-+ return fbmode;
-+}
-+
-+
-+/**
-+ * atmel_lcdfb_check_var - Validates a var passed in.
-+ * @var: frame buffer variable screen structure
-+ * @info: frame buffer structure that represents a single frame buffer
-+ *
-+ * Checks to see if the hardware supports the state requested by
-+ * var passed in. This function does not alter the hardware
-+ * state!!! This means the data stored in struct fb_info and
-+ * struct atmel_lcdfb_info do not change. This includes the var
-+ * inside of struct fb_info. Do NOT change these. This function
-+ * can be called on its own if we intent to only test a mode and
-+ * not actually set it. The stuff in modedb.c is a example of
-+ * this. If the var passed in is slightly off by what the
-+ * hardware can support then we alter the var PASSED in to what
-+ * we can do. If the hardware doesn't support mode change a
-+ * -EINVAL will be returned by the upper layers. You don't need
-+ * to implement this function then. If you hardware doesn't
-+ * support changing the resolution then this function is not
-+ * needed. In this case the driver would just provide a var that
-+ * represents the static state the screen is in.
-+ *
-+ * Returns negative errno on error, or zero on success.
-+ */
-+static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
-+ struct fb_info *info)
-+{
-+ struct device *dev = info->device;
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ unsigned long clk_value_khz;
-+
-+ clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
-+
-+ dev_dbg(dev, "%s:\n", __func__);
-+
-+ if (!(var->pixclock && var->bits_per_pixel)) {
-+ /* choose a suitable mode if possible */
-+ if (!atmel_lcdfb_choose_mode(var, info)) {
-+ dev_err(dev, "needed value not specified\n");
-+ return -EINVAL;
-+ }
-+ }
-+
-+ dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres);
-+ dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock));
-+ dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel);
-+ dev_dbg(dev, " clk: %lu KHz\n", clk_value_khz);
-+
-+ if (PICOS2KHZ(var->pixclock) > clk_value_khz) {
-+ dev_err(dev, "%lu KHz pixel clock is too fast\n", PICOS2KHZ(var->pixclock));
-+ return -EINVAL;
-+ }
-+
-+ /* Do not allow to have real resoulution larger than virtual */
-+ if (var->xres > var->xres_virtual)
-+ var->xres_virtual = var->xres;
-+
-+ if (var->yres > var->yres_virtual)
-+ var->yres_virtual = var->yres;
-+
-+ /* Force same alignment for each line */
-+ var->xres = (var->xres + 3) & ~3UL;
-+ var->xres_virtual = (var->xres_virtual + 3) & ~3UL;
-+
-+ var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
-+ var->transp.msb_right = 0;
-+ var->transp.offset = var->transp.length = 0;
-+ var->xoffset = var->yoffset = 0;
-+
-+ if (info->fix.smem_len) {
-+ unsigned int smem_len = (var->xres_virtual * var->yres_virtual
-+ * ((var->bits_per_pixel + 7) / 8));
-+ if (smem_len > info->fix.smem_len)
-+ return -EINVAL;
-+ }
-+
-+ /* Saturate vertical and horizontal timings at maximum values */
-+ var->vsync_len = min_t(u32, var->vsync_len,
-+ (ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1);
-+ var->upper_margin = min_t(u32, var->upper_margin,
-+ ATMEL_LCDC_VBP >> ATMEL_LCDC_VBP_OFFSET);
-+ var->lower_margin = min_t(u32, var->lower_margin,
-+ ATMEL_LCDC_VFP);
-+ var->right_margin = min_t(u32, var->right_margin,
-+ (ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 1);
-+ var->hsync_len = min_t(u32, var->hsync_len,
-+ (ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1);
-+ var->left_margin = min_t(u32, var->left_margin,
-+ ATMEL_LCDC_HBP + 1);
-+
-+ /* Some parameters can't be zero */
-+ var->vsync_len = max_t(u32, var->vsync_len, 1);
-+ var->right_margin = max_t(u32, var->right_margin, 1);
-+ var->hsync_len = max_t(u32, var->hsync_len, 1);
-+ var->left_margin = max_t(u32, var->left_margin, 1);
-+
-+ switch (var->bits_per_pixel) {
-+ case 1:
-+ case 2:
-+ case 4:
-+ case 8:
-+ var->red.offset = var->green.offset = var->blue.offset = 0;
-+ var->red.length = var->green.length = var->blue.length
-+ = var->bits_per_pixel;
-+ break;
-+ case 15:
-+ case 16:
-+ if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
-+ /* RGB:565 mode */
-+ var->red.offset = 11;
-+ var->blue.offset = 0;
-+ var->green.length = 6;
-+ } else if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB555) {
-+ var->red.offset = 10;
-+ var->blue.offset = 0;
-+ var->green.length = 5;
-+ } else {
-+ /* BGR:555 mode */
-+ var->red.offset = 0;
-+ var->blue.offset = 10;
-+ var->green.length = 5;
-+ }
-+ var->green.offset = 5;
-+ var->red.length = var->blue.length = 5;
-+ break;
-+ case 32:
-+ var->transp.offset = 24;
-+ var->transp.length = 8;
-+ /* fall through */
-+ case 24:
-+ if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
-+ /* RGB:888 mode */
-+ var->red.offset = 16;
-+ var->blue.offset = 0;
-+ } else {
-+ /* BGR:888 mode */
-+ var->red.offset = 0;
-+ var->blue.offset = 16;
-+ }
-+ var->green.offset = 8;
-+ var->red.length = var->green.length = var->blue.length = 8;
-+ break;
-+ default:
-+ dev_err(dev, "color depth %d not supported\n",
-+ var->bits_per_pixel);
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * LCD reset sequence
-+ */
-+static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo)
-+{
-+ might_sleep();
-+
-+ atmel_lcdfb_stop(sinfo);
-+ atmel_lcdfb_start(sinfo);
-+}
-+
-+/**
-+ * atmel_lcdfb_set_par - Alters the hardware state.
-+ * @info: frame buffer structure that represents a single frame buffer
-+ *
-+ * Using the fb_var_screeninfo in fb_info we set the resolution
-+ * of the this particular framebuffer. This function alters the
-+ * par AND the fb_fix_screeninfo stored in fb_info. It doesn't
-+ * not alter var in fb_info since we are using that data. This
-+ * means we depend on the data in var inside fb_info to be
-+ * supported by the hardware. atmel_lcdfb_check_var is always called
-+ * before atmel_lcdfb_set_par to ensure this. Again if you can't
-+ * change the resolution you don't need this function.
-+ *
-+ */
-+static int atmel_lcdfb_set_par(struct fb_info *info)
-+{
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ unsigned long hozval_linesz;
-+ unsigned long value;
-+ unsigned long clk_value_khz;
-+ unsigned long bits_per_line;
-+ unsigned long pix_factor = 2;
-+
-+ might_sleep();
-+
-+ dev_dbg(info->device, "%s:\n", __func__);
-+ dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n",
-+ info->var.xres, info->var.yres,
-+ info->var.xres_virtual, info->var.yres_virtual);
-+
-+ atmel_lcdfb_stop_nowait(sinfo);
-+
-+ if (info->var.bits_per_pixel == 1)
-+ info->fix.visual = FB_VISUAL_MONO01;
-+ else if (info->var.bits_per_pixel <= 8)
-+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ else
-+ info->fix.visual = FB_VISUAL_TRUECOLOR;
-+
-+ bits_per_line = info->var.xres_virtual * info->var.bits_per_pixel;
-+ info->fix.line_length = DIV_ROUND_UP(bits_per_line, 8);
-+
-+ /* Re-initialize the DMA engine... */
-+ dev_dbg(info->device, " * update DMA engine\n");
-+ atmel_lcdfb_update_dma(info, &info->var);
-+
-+ /* ...set frame size and burst length = 8 words (?) */
-+ value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32;
-+ value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET);
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value);
-+
-+ /* Now, the LCDC core... */
-+
-+ /* Set pixel clock */
-+ if (cpu_is_at91sam9g45() && !cpu_is_at91sam9g45es())
-+ pix_factor = 1;
-+
-+ clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
-+
-+ value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock));
-+
-+ if (value < pix_factor) {
-+ dev_notice(info->device, "Bypassing pixel clock divider\n");
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
-+ } else {
-+ value = (value / pix_factor) - 1;
-+ dev_dbg(info->device, " * programming CLKVAL = 0x%08lx\n",
-+ value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1,
-+ value << ATMEL_LCDC_CLKVAL_OFFSET);
-+ info->var.pixclock =
-+ KHZ2PICOS(clk_value_khz / (pix_factor * (value + 1)));
-+ dev_dbg(info->device, " updated pixclk: %lu KHz\n",
-+ PICOS2KHZ(info->var.pixclock));
-+ }
-+
-+
-+ /* Initialize control register 2 */
-+ value = sinfo->default_lcdcon2;
-+
-+ if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
-+ value |= ATMEL_LCDC_INVLINE_INVERTED;
-+ if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
-+ value |= ATMEL_LCDC_INVFRAME_INVERTED;
-+
-+ switch (info->var.bits_per_pixel) {
-+ case 1: value |= ATMEL_LCDC_PIXELSIZE_1; break;
-+ case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break;
-+ case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break;
-+ case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break;
-+ case 15: /* fall through */
-+ case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break;
-+ case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break;
-+ case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break;
-+ default: BUG(); break;
-+ }
-+ dev_dbg(info->device, " * LCDCON2 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value);
-+
-+ /* Vertical timing */
-+ value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET;
-+ value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET;
-+ value |= info->var.lower_margin;
-+ dev_dbg(info->device, " * LCDTIM1 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value);
-+
-+ /* Horizontal timing */
-+ value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET;
-+ value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET;
-+ value |= (info->var.left_margin - 1);
-+ dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
-+
-+ /* Horizontal value (aka line size) */
-+ hozval_linesz = compute_hozval(info->var.xres,
-+ lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2));
-+
-+ /* Display size */
-+ value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
-+ value |= info->var.yres - 1;
-+ dev_dbg(info->device, " * LCDFRMCFG = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value);
-+
-+ /* FIFO Threshold: Use formula from data sheet */
-+ value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3);
-+ lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value);
-+
-+ /* Toggle LCD_MODE every frame */
-+ lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0);
-+
-+ /* Disable all interrupts */
-+ lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
-+ /* Enable FIFO & DMA errors */
-+ lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
-+
-+ /* ...wait for DMA engine to become idle... */
-+ while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
-+ msleep(10);
-+
-+ atmel_lcdfb_start(sinfo);
-+
-+ dev_dbg(info->device, " * DONE\n");
-+
-+ return 0;
-+}
-+
-+static inline unsigned int chan_to_field(unsigned int chan, const struct fb_bitfield *bf)
-+{
-+ chan &= 0xffff;
-+ chan >>= 16 - bf->length;
-+ return chan << bf->offset;
-+}
-+
-+/**
-+ * atmel_lcdfb_setcolreg - Optional function. Sets a color register.
-+ * @regno: Which register in the CLUT we are programming
-+ * @red: The red value which can be up to 16 bits wide
-+ * @green: The green value which can be up to 16 bits wide
-+ * @blue: The blue value which can be up to 16 bits wide.
-+ * @transp: If supported the alpha value which can be up to 16 bits wide.
-+ * @info: frame buffer info structure
-+ *
-+ * Set a single color register. The values supplied have a 16 bit
-+ * magnitude which needs to be scaled in this function for the hardware.
-+ * Things to take into consideration are how many color registers, if
-+ * any, are supported with the current color visual. With truecolor mode
-+ * no color palettes are supported. Here a pseudo palette is created
-+ * which we store the value in pseudo_palette in struct fb_info. For
-+ * pseudocolor mode we have a limited color palette. To deal with this
-+ * we can program what color is displayed for a particular pixel value.
-+ * DirectColor is similar in that we can program each color field. If
-+ * we have a static colormap we don't need to implement this function.
-+ *
-+ * Returns negative errno on error, or zero on success. In an
-+ * ideal world, this would have been the case, but as it turns
-+ * out, the other drivers return 1 on failure, so that's what
-+ * we're going to do.
-+ */
-+static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
-+ unsigned int green, unsigned int blue,
-+ unsigned int transp, struct fb_info *info)
-+{
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ unsigned int val;
-+ u32 *pal;
-+ int ret = 1;
-+
-+ if (info->var.grayscale)
-+ red = green = blue = (19595 * red + 38470 * green
-+ + 7471 * blue) >> 16;
-+
-+ switch (info->fix.visual) {
-+ case FB_VISUAL_TRUECOLOR:
-+ if (regno < 16) {
-+ pal = info->pseudo_palette;
-+
-+ val = chan_to_field(red, &info->var.red);
-+ val |= chan_to_field(green, &info->var.green);
-+ val |= chan_to_field(blue, &info->var.blue);
-+
-+ pal[regno] = val;
-+ ret = 0;
-+ }
-+ break;
-+
-+ case FB_VISUAL_PSEUDOCOLOR:
-+ if (regno < 256) {
-+ val = ((red >> 11) & 0x001f);
-+ val |= ((green >> 6) & 0x03e0);
-+ val |= ((blue >> 1) & 0x7c00);
-+
-+ /*
-+ * TODO: intensity bit. Maybe something like
-+ * ~(red[10] ^ green[10] ^ blue[10]) & 1
-+ */
-+
-+ lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
-+ ret = 0;
-+ }
-+ break;
-+
-+ case FB_VISUAL_MONO01:
-+ if (regno < 2) {
-+ val = (regno == 0) ? 0x00 : 0x1F;
-+ lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
-+ ret = 0;
-+ }
-+ break;
-+
-+ }
-+
-+ return ret;
-+}
-+
-+static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var,
-+ struct fb_info *info)
-+{
-+ dev_dbg(info->device, "%s\n", __func__);
-+
-+ atmel_lcdfb_update_dma(info, var);
-+
-+ return 0;
-+}
-+
-+static int atmel_lcdfb_blank(int blank_mode, struct fb_info *info)
-+{
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+
-+ switch (blank_mode) {
-+ case FB_BLANK_UNBLANK:
-+ case FB_BLANK_NORMAL:
-+ atmel_lcdfb_start(sinfo);
-+ break;
-+ case FB_BLANK_VSYNC_SUSPEND:
-+ case FB_BLANK_HSYNC_SUSPEND:
-+ break;
-+ case FB_BLANK_POWERDOWN:
-+ atmel_lcdfb_stop(sinfo);
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ /* let fbcon do a soft blank for us */
-+ return ((blank_mode == FB_BLANK_NORMAL) ? 1 : 0);
-+}
-+
-+static struct fb_ops atmel_lcdfb_ops = {
-+ .owner = THIS_MODULE,
-+ .fb_check_var = atmel_lcdfb_check_var,
-+ .fb_set_par = atmel_lcdfb_set_par,
-+ .fb_setcolreg = atmel_lcdfb_setcolreg,
-+ .fb_blank = atmel_lcdfb_blank,
-+ .fb_pan_display = atmel_lcdfb_pan_display,
-+ .fb_fillrect = cfb_fillrect,
-+ .fb_copyarea = cfb_copyarea,
-+ .fb_imageblit = cfb_imageblit,
-+};
-+
-+static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
-+{
-+ struct fb_info *info = dev_id;
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ u32 status;
-+
-+ status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
-+ if (status & ATMEL_LCDC_UFLWI) {
-+ dev_warn(info->device, "FIFO underflow %#x\n", status);
-+ /* reset DMA and FIFO to avoid screen shifting */
-+ schedule_work(&sinfo->task);
-+ }
-+ lcdc_writel(sinfo, ATMEL_LCDC_ICR, status);
-+ return IRQ_HANDLED;
-+}
-+
-+/*
-+ * LCD controller task (to reset the LCD)
-+ */
-+static void atmel_lcdfb_task(struct work_struct *work)
-+{
-+ struct atmel_lcdfb_info *sinfo =
-+ container_of(work, struct atmel_lcdfb_info, task);
-+
-+ atmel_lcdfb_reset(sinfo);
-+}
-+
-+static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
-+{
-+ struct fb_info *info = sinfo->info;
-+ int ret = 0;
-+
-+ info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;
-+
-+ dev_info(info->device,
-+ "%luKiB frame buffer at %08lx (mapped at %p)\n",
-+ (unsigned long)info->fix.smem_len / 1024,
-+ (unsigned long)info->fix.smem_start,
-+ info->screen_base);
-+
-+ /* Allocate colormap */
-+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
-+ if (ret < 0)
-+ dev_err(info->device, "Alloc color map failed\n");
-+
-+ return ret;
-+}
-+
-+void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo)
-+{
-+ if (sinfo->bus_clk)
-+ clk_enable(sinfo->bus_clk);
-+ clk_enable(sinfo->lcdc_clk);
-+}
-+EXPORT_SYMBOL_GPL(atmel_lcdfb_start_clock);
-+
-+void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
-+{
-+ if (sinfo->bus_clk)
-+ clk_disable(sinfo->bus_clk);
-+ clk_disable(sinfo->lcdc_clk);
-+}
-+EXPORT_SYMBOL_GPL(atmel_lcdfb_stop_clock);
-+
-+
-+int __atmel_lcdfb_probe(struct platform_device *pdev,
-+ struct atmel_lcdfb_devdata *dev_data)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct fb_info *info;
-+ struct atmel_lcdfb_info *sinfo;
-+ struct atmel_lcdfb_info *pdata_sinfo;
-+ struct fb_videomode fbmode;
-+ struct resource *regs = NULL;
-+ struct resource *map = NULL;
-+ int ret;
-+
-+ dev_dbg(dev, "%s BEGIN\n", __func__);
-+
-+ ret = -ENOMEM;
-+ info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev);
-+ if (!info) {
-+ dev_err(dev, "cannot allocate memory\n");
-+ goto out;
-+ }
-+
-+ sinfo = info->par;
-+
-+ if (dev->platform_data) {
-+ pdata_sinfo = (struct atmel_lcdfb_info *)dev->platform_data;
-+ sinfo->default_bpp = pdata_sinfo->default_bpp;
-+ sinfo->default_dmacon = pdata_sinfo->default_dmacon;
-+ sinfo->default_lcdcon2 = pdata_sinfo->default_lcdcon2;
-+ sinfo->default_monspecs = pdata_sinfo->default_monspecs;
-+ sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control;
-+ sinfo->guard_time = pdata_sinfo->guard_time;
-+ sinfo->smem_len = pdata_sinfo->smem_len;
-+ sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight;
-+ sinfo->lcdcon_pol_negative = pdata_sinfo->lcdcon_pol_negative;
-+ sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode;
-+ } else {
-+ dev_err(dev, "cannot get default configuration\n");
-+ goto free_info;
-+ }
-+ sinfo->info = info;
-+ sinfo->pdev = pdev;
-+
-+ strcpy(info->fix.id, sinfo->pdev->name);
-+ info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
-+ info->pseudo_palette = sinfo->pseudo_palette;
-+ info->fbops = &atmel_lcdfb_ops;
-+
-+ memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs));
-+ info->fix = atmel_lcdfb_fix;
-+
-+ /* Enable LCDC Clocks */
-+ if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()
-+ || cpu_is_at32ap7000()) {
-+ sinfo->bus_clk = clk_get(dev, "hck1");
-+ if (IS_ERR(sinfo->bus_clk)) {
-+ ret = PTR_ERR(sinfo->bus_clk);
-+ goto free_info;
-+ }
-+ }
-+ sinfo->lcdc_clk = clk_get(dev, "lcdc_clk");
-+ if (IS_ERR(sinfo->lcdc_clk)) {
-+ ret = PTR_ERR(sinfo->lcdc_clk);
-+ goto put_bus_clk;
-+ }
-+ atmel_lcdfb_start_clock(sinfo);
-+
-+ ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb,
-+ info->monspecs.modedb_len, info->monspecs.modedb,
-+ sinfo->default_bpp);
-+ if (!ret) {
-+ dev_err(dev, "no suitable video mode found\n");
-+ goto stop_clk;
-+ }
-+
-+
-+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!regs) {
-+ dev_err(dev, "resources unusable\n");
-+ ret = -ENXIO;
-+ goto stop_clk;
-+ }
-+
-+ sinfo->irq_base = platform_get_irq(pdev, 0);
-+ if (sinfo->irq_base < 0) {
-+ dev_err(dev, "unable to get irq\n");
-+ ret = sinfo->irq_base;
-+ goto stop_clk;
-+ }
-+
-+ /* Initialize video memory */
-+ map = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+ if (map) {
-+ /* use a pre-allocated memory buffer */
-+ info->fix.smem_start = map->start;
-+ info->fix.smem_len = map->end - map->start + 1;
-+ if (!request_mem_region(info->fix.smem_start,
-+ info->fix.smem_len, pdev->name)) {
-+ ret = -EBUSY;
-+ goto stop_clk;
-+ }
-+
-+ info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
-+ if (!info->screen_base)
-+ goto release_intmem;
-+
-+ /*
-+ * Don't clear the framebuffer -- someone may have set
-+ * up a splash image.
-+ */
-+ } else {
-+ /* alocate memory buffer */
-+ ret = atmel_lcdfb_alloc_video_memory(sinfo);
-+ if (ret < 0) {
-+ dev_err(dev, "cannot allocate framebuffer: %d\n", ret);
-+ goto stop_clk;
-+ }
-+ }
-+
-+ /* LCDC registers */
-+ info->fix.mmio_start = regs->start;
-+ info->fix.mmio_len = regs->end - regs->start + 1;
-+
-+ if (!request_mem_region(info->fix.mmio_start,
-+ info->fix.mmio_len, pdev->name)) {
-+ ret = -EBUSY;
-+ goto free_fb;
-+ }
-+
-+ sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len);
-+ if (!sinfo->mmio) {
-+ dev_err(dev, "cannot map LCDC registers\n");
-+ goto release_mem;
-+ }
-+
-+ /* Initialize PWM for contrast or backlight ("off") */
-+ init_contrast(sinfo);
-+
-+ /* interrupt */
-+ ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info);
-+ if (ret) {
-+ dev_err(dev, "request_irq failed: %d\n", ret);
-+ goto unmap_mmio;
-+ }
-+
-+ /* Some operations on the LCDC might sleep and
-+ * require a preemptible task context */
-+ INIT_WORK(&sinfo->task, atmel_lcdfb_task);
-+
-+ ret = atmel_lcdfb_init_fbinfo(sinfo);
-+ if (ret < 0) {
-+ dev_err(dev, "init fbinfo failed: %d\n", ret);
-+ goto unregister_irqs;
-+ }
-+
-+ /*
-+ * This makes sure that our colour bitfield
-+ * descriptors are correctly initialised.
-+ */
-+ atmel_lcdfb_check_var(&info->var, info);
-+
-+ ret = fb_set_var(info, &info->var);
-+ if (ret) {
-+ dev_warn(dev, "unable to set display parameters\n");
-+ goto free_cmap;
-+ }
-+
-+ dev_set_drvdata(dev, info);
-+
-+ /*
-+ * Tell the world that we're ready to go
-+ */
-+ ret = register_framebuffer(info);
-+ if (ret < 0) {
-+ dev_err(dev, "failed to register framebuffer device: %d\n", ret);
-+ goto reset_drvdata;
-+ }
-+
-+ /* add selected videomode to modelist */
-+ fb_var_to_videomode(&fbmode, &info->var);
-+ fb_add_videomode(&fbmode, &info->modelist);
-+
-+ /* Power up the LCDC screen */
-+ if (sinfo->atmel_lcdfb_power_control)
-+ sinfo->atmel_lcdfb_power_control(1);
-+
-+ dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %d\n",
-+ info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base);
-+
-+ return 0;
-+
-+reset_drvdata:
-+ dev_set_drvdata(dev, NULL);
-+free_cmap:
-+ fb_dealloc_cmap(&info->cmap);
-+unregister_irqs:
-+ cancel_work_sync(&sinfo->task);
-+ free_irq(sinfo->irq_base, info);
-+unmap_mmio:
-+ exit_backlight(sinfo);
-+ iounmap(sinfo->mmio);
-+release_mem:
-+ release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
-+free_fb:
-+ if (map)
-+ iounmap(info->screen_base);
-+ else
-+ atmel_lcdfb_free_video_memory(sinfo);
-+
-+release_intmem:
-+ if (map)
-+ release_mem_region(info->fix.smem_start, info->fix.smem_len);
-+stop_clk:
-+ atmel_lcdfb_stop_clock(sinfo);
-+ clk_put(sinfo->lcdc_clk);
-+put_bus_clk:
-+ if (sinfo->bus_clk)
-+ clk_put(sinfo->bus_clk);
-+free_info:
-+ framebuffer_release(info);
-+out:
-+ dev_dbg(dev, "%s FAILED\n", __func__);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(__atmel_lcdfb_probe);
-+
-+int __atmel_lcdfb_remove(struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct fb_info *info = dev_get_drvdata(dev);
-+ struct atmel_lcdfb_info *sinfo;
-+
-+ if (!info || !info->par)
-+ return 0;
-+ sinfo = info->par;
-+
-+ cancel_work_sync(&sinfo->task);
-+ exit_backlight(sinfo);
-+ if (sinfo->atmel_lcdfb_power_control)
-+ sinfo->atmel_lcdfb_power_control(0);
-+ unregister_framebuffer(info);
-+ atmel_lcdfb_stop_clock(sinfo);
-+ clk_put(sinfo->lcdc_clk);
-+ if (sinfo->bus_clk)
-+ clk_put(sinfo->bus_clk);
-+ fb_dealloc_cmap(&info->cmap);
-+ free_irq(sinfo->irq_base, info);
-+ iounmap(sinfo->mmio);
-+ release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
-+ if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) {
-+ iounmap(info->screen_base);
-+ release_mem_region(info->fix.smem_start, info->fix.smem_len);
-+ } else {
-+ atmel_lcdfb_free_video_memory(sinfo);
-+ }
-+
-+ dev_set_drvdata(dev, NULL);
-+ framebuffer_release(info);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(__atmel_lcdfb_remove);
---- a/include/video/atmel_lcdc.h
-+++ b/include/video/atmel_lcdc.h
-@@ -32,6 +32,13 @@
- #define ATMEL_LCDC_WIRING_RGB 1
- #define ATMEL_LCDC_WIRING_RGB555 2
-
-+extern void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo);
-+extern void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo);
-+extern void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo);
-+extern void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo);
-+
-+extern int __atmel_lcdfb_probe(struct platform_device *pdev);
-+extern int __atmel_lcdfb_remove(struct platform_device *pdev);
-
- /* LCD Controller info data structure, stored in device platform_data */
- struct atmel_lcdfb_info {
-@@ -47,9 +54,6 @@ struct atmel_lcdfb_info {
- struct clk *bus_clk;
- struct clk *lcdc_clk;
-
-- struct lcd_dma_desc *p_dma_desc;
-- dma_addr_t dma_desc_phys;
--
- #ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
- struct backlight_device *backlight;
- u8 bl_power;
-@@ -69,11 +73,8 @@ struct atmel_lcdfb_info {
- bool have_intensity_bit;
- };
-
--struct lcd_dma_desc {
-- u32 address;
-- u32 control;
-- u32 next;
--};
-+#define lcdc_readl(sinfo, reg) __raw_readl((sinfo)->mmio+(reg))
-+#define lcdc_writel(sinfo, reg, val) __raw_writel((val), (sinfo)->mmio+(reg))
-
- #define ATMEL_LCDC_DMABADDR1 0x00
- #define ATMEL_LCDC_DMABADDR2 0x04
+++ /dev/null
-From 69e93611104cfbc122ce9058de6c418018f550ba Mon Sep 17 00:00:00 2001
-From: Wolfram Sang <w.sang@pengutronix.de>
-Date: Thu, 19 May 2011 14:29:36 +0200
-Subject: video: atmelfb: refactor core setup
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
----
- drivers/video/atmel_lcdfb.c | 158 ++++++++++++++++++++++++++++++++++++++-
- drivers/video/atmel_lcdfb_core.c | 126 +------------------------------
- include/video/atmel_lcdc.h | 8 +-
- 3 files changed, 166 insertions(+), 126 deletions(-)
-
-diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
-index 4e1454c..85063d6 100644
---- a/drivers/video/atmel_lcdfb.c
-+++ b/drivers/video/atmel_lcdfb.c
-@@ -12,12 +12,162 @@
- #include <linux/platform_device.h>
- #include <linux/interrupt.h>
- #include <linux/fb.h>
-+#include <linux/clk.h>
- #include <linux/init.h>
- #include <linux/delay.h>
-
-+#include <mach/board.h>
-+#include <mach/cpu.h>
-+
- #include <video/atmel_lcdc.h>
-
--#ifdef CONFIG_PM
-+/* configurable parameters */
-+#define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */
-+#define ATMEL_LCDC_FIFO_SIZE 512 /* words */
-+
-+static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2)
-+{
-+ unsigned long value;
-+
-+ if (!(cpu_is_at91sam9261() || cpu_is_at91sam9g10()
-+ || cpu_is_at32ap7000()))
-+ return xres;
-+
-+ value = xres;
-+ if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) {
-+ /* STN display */
-+ if ((lcdcon2 & ATMEL_LCDC_DISTYPE) == ATMEL_LCDC_DISTYPE_STNCOLOR) {
-+ value *= 3;
-+ }
-+ if ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_4
-+ || ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_8
-+ && (lcdcon2 & ATMEL_LCDC_SCANMOD) == ATMEL_LCDC_SCANMOD_DUAL ))
-+ value = DIV_ROUND_UP(value, 4);
-+ else
-+ value = DIV_ROUND_UP(value, 8);
-+ }
-+
-+ return value;
-+}
-+
-+static int atmel_lcdfb_setup_core(struct fb_info *info)
-+{
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ unsigned long hozval_linesz;
-+ unsigned long value;
-+ unsigned long clk_value_khz;
-+ unsigned long pix_factor = 2;
-+
-+ /* ...set frame size and burst length = 8 words (?) */
-+ value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32;
-+ value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET);
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value);
-+
-+ /* Set pixel clock */
-+ if (cpu_is_at91sam9g45() && !cpu_is_at91sam9g45es())
-+ pix_factor = 1;
-+
-+ clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
-+
-+ value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock));
-+
-+ if (value < pix_factor) {
-+ dev_notice(info->device, "Bypassing pixel clock divider\n");
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
-+ } else {
-+ value = (value / pix_factor) - 1;
-+ dev_dbg(info->device, " * programming CLKVAL = 0x%08lx\n",
-+ value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1,
-+ value << ATMEL_LCDC_CLKVAL_OFFSET);
-+ info->var.pixclock =
-+ KHZ2PICOS(clk_value_khz / (pix_factor * (value + 1)));
-+ dev_dbg(info->device, " updated pixclk: %lu KHz\n",
-+ PICOS2KHZ(info->var.pixclock));
-+ }
-+
-+
-+ /* Initialize control register 2 */
-+ value = sinfo->default_lcdcon2;
-+
-+ if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
-+ value |= ATMEL_LCDC_INVLINE_INVERTED;
-+ if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
-+ value |= ATMEL_LCDC_INVFRAME_INVERTED;
-+
-+ switch (info->var.bits_per_pixel) {
-+ case 1:
-+ value |= ATMEL_LCDC_PIXELSIZE_1;
-+ break;
-+ case 2:
-+ value |= ATMEL_LCDC_PIXELSIZE_2;
-+ break;
-+ case 4:
-+ value |= ATMEL_LCDC_PIXELSIZE_4;
-+ break;
-+ case 8:
-+ value |= ATMEL_LCDC_PIXELSIZE_8;
-+ break;
-+ case 15: /* fall through */
-+ case 16:
-+ value |= ATMEL_LCDC_PIXELSIZE_16;
-+ break;
-+ case 24:
-+ value |= ATMEL_LCDC_PIXELSIZE_24;
-+ break;
-+ case 32:
-+ value |= ATMEL_LCDC_PIXELSIZE_32;
-+ break;
-+ default:
-+ BUG();
-+ break;
-+ }
-+ dev_dbg(info->device, " * LCDCON2 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value);
-+
-+ /* Vertical timing */
-+ value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET;
-+ value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET;
-+ value |= info->var.lower_margin;
-+ dev_dbg(info->device, " * LCDTIM1 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value);
-+
-+ /* Horizontal timing */
-+ value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET;
-+ value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET;
-+ value |= (info->var.left_margin - 1);
-+ dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
-+
-+ /* Horizontal value (aka line size) */
-+ hozval_linesz = compute_hozval(info->var.xres,
-+ lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2));
-+
-+ /* Display size */
-+ value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
-+ value |= info->var.yres - 1;
-+ dev_dbg(info->device, " * LCDFRMCFG = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value);
-+
-+ /* FIFO Threshold: Use formula from data sheet */
-+ value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3);
-+ lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value);
-+
-+ /* Toggle LCD_MODE every frame */
-+ lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0);
-+
-+ /* Disable all interrupts */
-+ lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
-+ /* Enable FIFO & DMA errors */
-+ lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
-+
-+ /* ...wait for DMA engine to become idle... */
-+ while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
-+ msleep(10);
-+
-+ return 0;
-+}
-+
-
- static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
- {
-@@ -66,9 +216,13 @@ static int atmel_lcdfb_resume(struct platform_device *pdev)
- #define atmel_lcdfb_resume NULL
- #endif
-
-+static struct atmel_lcdfb_devdata dev_data = {
-+ .setup_core = atmel_lcdfb_setup_core,
-+};
-+
- static int __init atmel_lcdfb_probe(struct platform_device *pdev)
- {
-- return __atmel_lcdfb_probe(pdev);
-+ return __atmel_lcdfb_probe(pdev, &dev_data);
- }
- static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
- {
-diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c
-index 54bdbcb..9a7c5eb 100644
---- a/drivers/video/atmel_lcdfb_core.c
-+++ b/drivers/video/atmel_lcdfb_core.c
-@@ -27,8 +27,6 @@
-
- /* configurable parameters */
- #define ATMEL_LCDC_CVAL_DEFAULT 0xc8
--#define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */
--#define ATMEL_LCDC_FIFO_SIZE 512 /* words */
-
- #if defined(CONFIG_ARCH_AT91)
- #define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
-@@ -183,31 +181,6 @@ static struct fb_fix_screeninfo atmel_lcdfb_fix = {
- .accel = FB_ACCEL_NONE,
- };
-
--static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2)
--{
-- unsigned long value;
--
-- if (!(cpu_is_at91sam9261() || cpu_is_at91sam9g10()
-- || cpu_is_at32ap7000()))
-- return xres;
--
-- value = xres;
-- if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) {
-- /* STN display */
-- if ((lcdcon2 & ATMEL_LCDC_DISTYPE) == ATMEL_LCDC_DISTYPE_STNCOLOR) {
-- value *= 3;
-- }
-- if ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_4
-- || ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_8
-- && (lcdcon2 & ATMEL_LCDC_SCANMOD) == ATMEL_LCDC_SCANMOD_DUAL ))
-- value = DIV_ROUND_UP(value, 4);
-- else
-- value = DIV_ROUND_UP(value, 8);
-- }
--
-- return value;
--}
--
- static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo)
- {
- /* Turn off the LCD controller and the DMA controller */
-@@ -487,11 +460,7 @@ static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo)
- static int atmel_lcdfb_set_par(struct fb_info *info)
- {
- struct atmel_lcdfb_info *sinfo = info->par;
-- unsigned long hozval_linesz;
-- unsigned long value;
-- unsigned long clk_value_khz;
- unsigned long bits_per_line;
-- unsigned long pix_factor = 2;
-
- might_sleep();
-
-@@ -516,98 +485,8 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
- dev_dbg(info->device, " * update DMA engine\n");
- atmel_lcdfb_update_dma(info, &info->var);
-
-- /* ...set frame size and burst length = 8 words (?) */
-- value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32;
-- value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET);
-- lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value);
--
- /* Now, the LCDC core... */
--
-- /* Set pixel clock */
-- if (cpu_is_at91sam9g45() && !cpu_is_at91sam9g45es())
-- pix_factor = 1;
--
-- clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
--
-- value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock));
--
-- if (value < pix_factor) {
-- dev_notice(info->device, "Bypassing pixel clock divider\n");
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
-- } else {
-- value = (value / pix_factor) - 1;
-- dev_dbg(info->device, " * programming CLKVAL = 0x%08lx\n",
-- value);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1,
-- value << ATMEL_LCDC_CLKVAL_OFFSET);
-- info->var.pixclock =
-- KHZ2PICOS(clk_value_khz / (pix_factor * (value + 1)));
-- dev_dbg(info->device, " updated pixclk: %lu KHz\n",
-- PICOS2KHZ(info->var.pixclock));
-- }
--
--
-- /* Initialize control register 2 */
-- value = sinfo->default_lcdcon2;
--
-- if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
-- value |= ATMEL_LCDC_INVLINE_INVERTED;
-- if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
-- value |= ATMEL_LCDC_INVFRAME_INVERTED;
--
-- switch (info->var.bits_per_pixel) {
-- case 1: value |= ATMEL_LCDC_PIXELSIZE_1; break;
-- case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break;
-- case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break;
-- case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break;
-- case 15: /* fall through */
-- case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break;
-- case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break;
-- case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break;
-- default: BUG(); break;
-- }
-- dev_dbg(info->device, " * LCDCON2 = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value);
--
-- /* Vertical timing */
-- value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET;
-- value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET;
-- value |= info->var.lower_margin;
-- dev_dbg(info->device, " * LCDTIM1 = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value);
--
-- /* Horizontal timing */
-- value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET;
-- value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET;
-- value |= (info->var.left_margin - 1);
-- dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
--
-- /* Horizontal value (aka line size) */
-- hozval_linesz = compute_hozval(info->var.xres,
-- lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2));
--
-- /* Display size */
-- value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
-- value |= info->var.yres - 1;
-- dev_dbg(info->device, " * LCDFRMCFG = %08lx\n", value);
-- lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value);
--
-- /* FIFO Threshold: Use formula from data sheet */
-- value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3);
-- lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value);
--
-- /* Toggle LCD_MODE every frame */
-- lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0);
--
-- /* Disable all interrupts */
-- lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
-- /* Enable FIFO & DMA errors */
-- lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
--
-- /* ...wait for DMA engine to become idle... */
-- while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
-- msleep(10);
-+ sinfo->dev_data->setup_core(info);
-
- atmel_lcdfb_start(sinfo);
-
-@@ -837,7 +716,7 @@ int __atmel_lcdfb_probe(struct platform_device *pdev,
-
- sinfo = info->par;
-
-- if (dev->platform_data) {
-+ if (dev->platform_data && dev_data) {
- pdata_sinfo = (struct atmel_lcdfb_info *)dev->platform_data;
- sinfo->default_bpp = pdata_sinfo->default_bpp;
- sinfo->default_dmacon = pdata_sinfo->default_dmacon;
-@@ -849,6 +728,7 @@ int __atmel_lcdfb_probe(struct platform_device *pdev,
- sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight;
- sinfo->lcdcon_pol_negative = pdata_sinfo->lcdcon_pol_negative;
- sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode;
-+ sinfo->dev_data = dev_data;
- } else {
- dev_err(dev, "cannot get default configuration\n");
- goto free_info;
-diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h
-index 4fa084b..b1a5fad1 100644
---- a/include/video/atmel_lcdc.h
-+++ b/include/video/atmel_lcdc.h
-@@ -37,15 +37,21 @@ extern void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo);
- extern void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo);
- extern void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo);
-
--extern int __atmel_lcdfb_probe(struct platform_device *pdev);
-+extern int __atmel_lcdfb_probe(struct platform_device *pdev,
-+ struct atmel_lcdfb_devdata *devdata);
- extern int __atmel_lcdfb_remove(struct platform_device *pdev);
-
-+struct atmel_lcdfb_devdata {
-+ int (*setup_core)(struct fb_info *info);
-+};
-+
- /* LCD Controller info data structure, stored in device platform_data */
- struct atmel_lcdfb_info {
- spinlock_t lock;
- struct fb_info *info;
- void __iomem *mmio;
- int irq_base;
-+ struct atmel_lcdfb_devdata *dev_data;
- struct work_struct task;
-
- unsigned int guard_time;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 77d8d936f1c593a6e273e93585514f7d8428c68a Mon Sep 17 00:00:00 2001
-From: Wolfram Sang <w.sang@pengutronix.de>
-Date: Thu, 19 May 2011 15:12:30 +0200
-Subject: video: atmelfb: refactor start/stop
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
----
- drivers/video/atmel_lcdfb.c | 30 +++++++++++++++++++++++-
- drivers/video/atmel_lcdfb_core.c | 50 ++++++++++------------------------------
- include/video/atmel_lcdc.h | 9 +++++---
- 3 files changed, 47 insertions(+), 42 deletions(-)
-
-diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
-index 85063d6..422be1a 100644
---- a/drivers/video/atmel_lcdfb.c
-+++ b/drivers/video/atmel_lcdfb.c
-@@ -25,6 +25,32 @@
- #define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */
- #define ATMEL_LCDC_FIFO_SIZE 512 /* words */
-
-+void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo)
-+{
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
-+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-+ (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET)
-+ | ATMEL_LCDC_PWR);
-+}
-+
-+static void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo, u32 flags)
-+{
-+ /* Turn off the LCD controller and the DMA controller */
-+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-+ sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
-+
-+ /* Wait for the LCDC core to become idle */
-+ while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
-+ msleep(10);
-+
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
-+
-+ if (!(flags & ATMEL_LCDC_STOP_NOWAIT))
-+ /* Wait for DMA engine to become idle... */
-+ while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
-+ msleep(10);
-+}
-+
- static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2)
- {
- unsigned long value;
-@@ -186,7 +212,7 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
- if (sinfo->atmel_lcdfb_power_control)
- sinfo->atmel_lcdfb_power_control(0);
-
-- atmel_lcdfb_stop(sinfo);
-+ atmel_lcdfb_stop(sinfo, 0);
- atmel_lcdfb_stop_clock(sinfo);
-
- return 0;
-@@ -218,6 +244,8 @@ static int atmel_lcdfb_resume(struct platform_device *pdev)
-
- static struct atmel_lcdfb_devdata dev_data = {
- .setup_core = atmel_lcdfb_setup_core,
-+ .start = atmel_lcdfb_start,
-+ .stop = atmel_lcdfb_stop,
- };
-
- static int __init atmel_lcdfb_probe(struct platform_device *pdev)
-diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c
-index 9a7c5eb..8413b76 100644
---- a/drivers/video/atmel_lcdfb_core.c
-+++ b/drivers/video/atmel_lcdfb_core.c
-@@ -181,38 +181,6 @@ static struct fb_fix_screeninfo atmel_lcdfb_fix = {
- .accel = FB_ACCEL_NONE,
- };
-
--static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo)
--{
-- /* Turn off the LCD controller and the DMA controller */
-- lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-- sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
--
-- /* Wait for the LCDC core to become idle */
-- while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
-- msleep(10);
--
-- lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
--}
--
--void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo)
--{
-- atmel_lcdfb_stop_nowait(sinfo);
--
-- /* Wait for DMA engine to become idle... */
-- while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
-- msleep(10);
--}
--EXPORT_SYMBOL_GPL(atmel_lcdfb_stop);
--
--void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo)
--{
-- lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
-- lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-- (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET)
-- | ATMEL_LCDC_PWR);
--}
--EXPORT_SYMBOL_GPL(atmel_lcdfb_start);
--
- static void atmel_lcdfb_update_dma(struct fb_info *info,
- struct fb_var_screeninfo *var)
- {
-@@ -439,8 +407,10 @@ static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo)
- {
- might_sleep();
-
-- atmel_lcdfb_stop(sinfo);
-- atmel_lcdfb_start(sinfo);
-+ if (sinfo->dev_data->stop)
-+ sinfo->dev_data->stop(sinfo, 0);
-+ if (sinfo->dev_data->start)
-+ sinfo->dev_data->start(sinfo);
- }
-
- /**
-@@ -469,7 +439,8 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
- info->var.xres, info->var.yres,
- info->var.xres_virtual, info->var.yres_virtual);
-
-- atmel_lcdfb_stop_nowait(sinfo);
-+ if (sinfo->dev_data->stop)
-+ sinfo->dev_data->stop(sinfo, ATMEL_LCDC_STOP_NOWAIT);
-
- if (info->var.bits_per_pixel == 1)
- info->fix.visual = FB_VISUAL_MONO01;
-@@ -488,7 +459,8 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
- /* Now, the LCDC core... */
- sinfo->dev_data->setup_core(info);
-
-- atmel_lcdfb_start(sinfo);
-+ if (sinfo->dev_data->start)
-+ sinfo->dev_data->start(sinfo);
-
- dev_dbg(info->device, " * DONE\n");
-
-@@ -600,13 +572,15 @@ static int atmel_lcdfb_blank(int blank_mode, struct fb_info *info)
- switch (blank_mode) {
- case FB_BLANK_UNBLANK:
- case FB_BLANK_NORMAL:
-- atmel_lcdfb_start(sinfo);
-+ if (sinfo->dev_data->start)
-+ sinfo->dev_data->start(sinfo);
- break;
- case FB_BLANK_VSYNC_SUSPEND:
- case FB_BLANK_HSYNC_SUSPEND:
- break;
- case FB_BLANK_POWERDOWN:
-- atmel_lcdfb_stop(sinfo);
-+ if (sinfo->dev_data->stop)
-+ sinfo->dev_data->stop(sinfo, 0);
- break;
- default:
- return -EINVAL;
-diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h
-index b1a5fad1..ea7ce31 100644
---- a/include/video/atmel_lcdc.h
-+++ b/include/video/atmel_lcdc.h
-@@ -32,17 +32,20 @@
- #define ATMEL_LCDC_WIRING_RGB 1
- #define ATMEL_LCDC_WIRING_RGB555 2
-
--extern void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo);
--extern void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo);
-+#define ATMEL_LCDC_STOP_NOWAIT (1 << 0)
-+
- extern void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo);
- extern void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo);
--
- extern int __atmel_lcdfb_probe(struct platform_device *pdev,
- struct atmel_lcdfb_devdata *devdata);
- extern int __atmel_lcdfb_remove(struct platform_device *pdev);
-
-+struct atmel_lcdfb_info;
-+
- struct atmel_lcdfb_devdata {
- int (*setup_core)(struct fb_info *info);
-+ void (*start)(struct atmel_lcdfb_info *sinfo);
-+ void (*stop)(struct atmel_lcdfb_info *sinfo, u32 flags);
- };
-
- /* LCD Controller info data structure, stored in device platform_data */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 815c18d931e79076ce64c0af0aa249ec993aa366 Mon Sep 17 00:00:00 2001
-From: Wolfram Sang <w.sang@pengutronix.de>
-Date: Thu, 19 May 2011 15:37:12 +0200
-Subject: video: atmelfb: refactor isr
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
----
- drivers/video/atmel_lcdfb.c | 18 ++++++++++++++++++
- drivers/video/atmel_lcdfb_core.c | 39 ++++++++++++---------------------------
- include/video/atmel_lcdc.h | 2 ++
- 3 files changed, 32 insertions(+), 27 deletions(-)
-
-diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
-index 422be1a..3653e2a 100644
---- a/drivers/video/atmel_lcdfb.c
-+++ b/drivers/video/atmel_lcdfb.c
-@@ -194,6 +194,23 @@ static int atmel_lcdfb_setup_core(struct fb_info *info)
- return 0;
- }
-
-+static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
-+{
-+ struct fb_info *info = dev_id;
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ u32 status;
-+
-+ status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
-+ if (status & ATMEL_LCDC_UFLWI) {
-+ dev_warn(info->device, "FIFO underflow %#x\n", status);
-+ /* reset DMA and FIFO to avoid screen shifting */
-+ schedule_work(&sinfo->task);
-+ }
-+ lcdc_writel(sinfo, ATMEL_LCDC_ICR, status);
-+ return IRQ_HANDLED;
-+}
-+
-+#ifdef CONFIG_PM
-
- static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
- {
-@@ -246,6 +263,7 @@ static struct atmel_lcdfb_devdata dev_data = {
- .setup_core = atmel_lcdfb_setup_core,
- .start = atmel_lcdfb_start,
- .stop = atmel_lcdfb_stop,
-+ .isr = atmel_lcdfb_interrupt,
- };
-
- static int __init atmel_lcdfb_probe(struct platform_device *pdev)
-diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c
-index 8413b76..eab4d88 100644
---- a/drivers/video/atmel_lcdfb_core.c
-+++ b/drivers/video/atmel_lcdfb_core.c
-@@ -602,22 +602,6 @@ static struct fb_ops atmel_lcdfb_ops = {
- .fb_imageblit = cfb_imageblit,
- };
-
--static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
--{
-- struct fb_info *info = dev_id;
-- struct atmel_lcdfb_info *sinfo = info->par;
-- u32 status;
--
-- status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
-- if (status & ATMEL_LCDC_UFLWI) {
-- dev_warn(info->device, "FIFO underflow %#x\n", status);
-- /* reset DMA and FIFO to avoid screen shifting */
-- schedule_work(&sinfo->task);
-- }
-- lcdc_writel(sinfo, ATMEL_LCDC_ICR, status);
-- return IRQ_HANDLED;
--}
--
- /*
- * LCD controller task (to reset the LCD)
- */
-@@ -750,12 +734,8 @@ int __atmel_lcdfb_probe(struct platform_device *pdev,
- goto stop_clk;
- }
-
-+ /* No error checking, some devices can do without IRQ */
- sinfo->irq_base = platform_get_irq(pdev, 0);
-- if (sinfo->irq_base < 0) {
-- dev_err(dev, "unable to get irq\n");
-- ret = sinfo->irq_base;
-- goto stop_clk;
-- }
-
- /* Initialize video memory */
- map = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-@@ -806,10 +786,13 @@ int __atmel_lcdfb_probe(struct platform_device *pdev,
- init_contrast(sinfo);
-
- /* interrupt */
-- ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info);
-- if (ret) {
-- dev_err(dev, "request_irq failed: %d\n", ret);
-- goto unmap_mmio;
-+ if (sinfo->irq_base >= 0) {
-+ ret = request_irq(sinfo->irq_base, sinfo->dev_data->isr,
-+ IRQF_SHARED, pdev->name, info);
-+ if (ret) {
-+ dev_err(dev, "request_irq failed: %d\n", ret);
-+ goto unmap_mmio;
-+ }
- }
-
- /* Some operations on the LCDC might sleep and
-@@ -864,7 +847,8 @@ free_cmap:
- fb_dealloc_cmap(&info->cmap);
- unregister_irqs:
- cancel_work_sync(&sinfo->task);
-- free_irq(sinfo->irq_base, info);
-+ if (sinfo->irq_base >= 0)
-+ free_irq(sinfo->irq_base, info);
- unmap_mmio:
- exit_backlight(sinfo);
- iounmap(sinfo->mmio);
-@@ -913,7 +897,8 @@ int __atmel_lcdfb_remove(struct platform_device *pdev)
- if (sinfo->bus_clk)
- clk_put(sinfo->bus_clk);
- fb_dealloc_cmap(&info->cmap);
-- free_irq(sinfo->irq_base, info);
-+ if (sinfo->irq_base >= 0)
-+ free_irq(sinfo->irq_base, info);
- iounmap(sinfo->mmio);
- release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
- if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) {
-diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h
-index ea7ce31..14b5664 100644
---- a/include/video/atmel_lcdc.h
-+++ b/include/video/atmel_lcdc.h
-@@ -23,6 +23,7 @@
- #define __ATMEL_LCDC_H__
-
- #include <linux/workqueue.h>
-+#include <linux/interrupt.h>
-
- /* Way LCD wires are connected to the chip:
- * Some Atmel chips use BGR color mode (instead of standard RGB)
-@@ -46,6 +47,7 @@ struct atmel_lcdfb_devdata {
- int (*setup_core)(struct fb_info *info);
- void (*start)(struct atmel_lcdfb_info *sinfo);
- void (*stop)(struct atmel_lcdfb_info *sinfo, u32 flags);
-+ irqreturn_t (*isr)(int irq, void *dev_id);
- };
-
- /* LCD Controller info data structure, stored in device platform_data */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 8da5e6762ea376a5ff47963430d72fe84bab91c9 Mon Sep 17 00:00:00 2001
-From: Wolfram Sang <w.sang@pengutronix.de>
-Date: Thu, 19 May 2011 16:40:13 +0200
-Subject: video: atmelfb: refactor backlight routines
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
----
- drivers/video/atmel_lcdfb.c | 61 +++++++++++++++++++++++++++++++++
- drivers/video/atmel_lcdfb_core.c | 73 ++++------------------------------------
- include/video/atmel_lcdc.h | 3 ++
- 3 files changed, 71 insertions(+), 66 deletions(-)
-
-diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
-index 3653e2a..046e6c5 100644
---- a/drivers/video/atmel_lcdfb.c
-+++ b/drivers/video/atmel_lcdfb.c
-@@ -11,6 +11,7 @@
- #include <linux/kernel.h>
- #include <linux/platform_device.h>
- #include <linux/interrupt.h>
-+#include <linux/backlight.h>
- #include <linux/fb.h>
- #include <linux/clk.h>
- #include <linux/init.h>
-@@ -22,9 +23,67 @@
- #include <video/atmel_lcdc.h>
-
- /* configurable parameters */
-+#define ATMEL_LCDC_CVAL_DEFAULT 0xc8
- #define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */
- #define ATMEL_LCDC_FIFO_SIZE 512 /* words */
-
-+static u32 contrast_ctr = ATMEL_LCDC_PS_DIV8
-+ | ATMEL_LCDC_POL_POSITIVE
-+ | ATMEL_LCDC_ENA_PWMENABLE;
-+
-+/* some bl->props field just changed */
-+static int atmel_bl_update_status(struct backlight_device *bl)
-+{
-+ struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
-+ int power = sinfo->bl_power;
-+ int brightness = bl->props.brightness;
-+
-+ /* REVISIT there may be a meaningful difference between
-+ * fb_blank and power ... there seem to be some cases
-+ * this doesn't handle correctly.
-+ */
-+ if (bl->props.fb_blank != sinfo->bl_power)
-+ power = bl->props.fb_blank;
-+ else if (bl->props.power != sinfo->bl_power)
-+ power = bl->props.power;
-+
-+ if (brightness < 0 && power == FB_BLANK_UNBLANK)
-+ brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
-+ else if (power != FB_BLANK_UNBLANK)
-+ brightness = 0;
-+
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
-+ brightness ? contrast_ctr : 0);
-+
-+ bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;
-+
-+ return 0;
-+}
-+
-+static int atmel_bl_get_brightness(struct backlight_device *bl)
-+{
-+ struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
-+
-+ return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
-+}
-+
-+static const struct backlight_ops atmel_lcdc_bl_ops = {
-+ .update_status = atmel_bl_update_status,
-+ .get_brightness = atmel_bl_get_brightness,
-+};
-+
-+static void atmel_lcdfb_init_contrast(struct atmel_lcdfb_info *sinfo)
-+{
-+ /* contrast pwm can be 'inverted' */
-+ if (sinfo->lcdcon_pol_negative)
-+ contrast_ctr &= ~(ATMEL_LCDC_POL_POSITIVE);
-+
-+ /* have some default contrast/backlight settings */
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
-+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
-+}
-+
- void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo)
- {
- lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
-@@ -264,6 +323,8 @@ static struct atmel_lcdfb_devdata dev_data = {
- .start = atmel_lcdfb_start,
- .stop = atmel_lcdfb_stop,
- .isr = atmel_lcdfb_interrupt,
-+ .bl_ops = &atmel_lcdc_bl_ops,
-+ .init_contrast = atmel_lcdfb_init_contrast,
- };
-
- static int __init atmel_lcdfb_probe(struct platform_device *pdev)
-diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c
-index eab4d88..ef63996 100644
---- a/drivers/video/atmel_lcdfb_core.c
-+++ b/drivers/video/atmel_lcdfb_core.c
-@@ -16,7 +16,6 @@
- #include <linux/fb.h>
- #include <linux/init.h>
- #include <linux/delay.h>
--#include <linux/backlight.h>
- #include <linux/gfp.h>
-
- #include <mach/board.h>
-@@ -63,54 +62,8 @@ static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
- }
- #endif
-
--static u32 contrast_ctr = ATMEL_LCDC_PS_DIV8
-- | ATMEL_LCDC_POL_POSITIVE
-- | ATMEL_LCDC_ENA_PWMENABLE;
--
- #ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
-
--/* some bl->props field just changed */
--static int atmel_bl_update_status(struct backlight_device *bl)
--{
-- struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
-- int power = sinfo->bl_power;
-- int brightness = bl->props.brightness;
--
-- /* REVISIT there may be a meaningful difference between
-- * fb_blank and power ... there seem to be some cases
-- * this doesn't handle correctly.
-- */
-- if (bl->props.fb_blank != sinfo->bl_power)
-- power = bl->props.fb_blank;
-- else if (bl->props.power != sinfo->bl_power)
-- power = bl->props.power;
--
-- if (brightness < 0 && power == FB_BLANK_UNBLANK)
-- brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
-- else if (power != FB_BLANK_UNBLANK)
-- brightness = 0;
--
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
-- brightness ? contrast_ctr : 0);
--
-- bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;
--
-- return 0;
--}
--
--static int atmel_bl_get_brightness(struct backlight_device *bl)
--{
-- struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
--
-- return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
--}
--
--static const struct backlight_ops atmel_lcdc_bl_ops = {
-- .update_status = atmel_bl_update_status,
-- .get_brightness = atmel_bl_get_brightness,
--};
--
- static void init_backlight(struct atmel_lcdfb_info *sinfo)
- {
- struct backlight_properties props;
-@@ -118,14 +71,14 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo)
-
- sinfo->bl_power = FB_BLANK_UNBLANK;
-
-- if (sinfo->backlight)
-+ if (sinfo->backlight || !sinfo->dev_data->bl_ops)
- return;
-
- memset(&props, 0, sizeof(struct backlight_properties));
- props.type = BACKLIGHT_RAW;
- props.max_brightness = 0xff;
- bl = backlight_device_register("backlight", &sinfo->pdev->dev, sinfo,
-- &atmel_lcdc_bl_ops, &props);
-+ sinfo->dev_data->bl_ops, &props);
- if (IS_ERR(bl)) {
- dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n",
- PTR_ERR(bl));
-@@ -135,7 +88,7 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo)
-
- bl->props.power = FB_BLANK_UNBLANK;
- bl->props.fb_blank = FB_BLANK_UNBLANK;
-- bl->props.brightness = atmel_bl_get_brightness(bl);
-+ bl->props.brightness = sinfo->dev_data->bl_ops->get_brightness(bl);
- }
-
- static void exit_backlight(struct atmel_lcdfb_info *sinfo)
-@@ -157,21 +110,6 @@ static void exit_backlight(struct atmel_lcdfb_info *sinfo)
-
- #endif
-
--static void init_contrast(struct atmel_lcdfb_info *sinfo)
--{
-- /* contrast pwm can be 'inverted' */
-- if (sinfo->lcdcon_pol_negative)
-- contrast_ctr &= ~(ATMEL_LCDC_POL_POSITIVE);
--
-- /* have some default contrast/backlight settings */
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
-- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
--
-- if (sinfo->lcdcon_is_backlight)
-- init_backlight(sinfo);
--}
--
--
- static struct fb_fix_screeninfo atmel_lcdfb_fix = {
- .type = FB_TYPE_PACKED_PIXELS,
- .visual = FB_VISUAL_TRUECOLOR,
-@@ -783,7 +721,10 @@ int __atmel_lcdfb_probe(struct platform_device *pdev,
- }
-
- /* Initialize PWM for contrast or backlight ("off") */
-- init_contrast(sinfo);
-+ if (sinfo->dev_data->init_contrast)
-+ sinfo->dev_data->init_contrast(sinfo);
-+ if (sinfo->lcdcon_is_backlight)
-+ init_backlight(sinfo);
-
- /* interrupt */
- if (sinfo->irq_base >= 0) {
-diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h
-index 14b5664..e7c0a3f 100644
---- a/include/video/atmel_lcdc.h
-+++ b/include/video/atmel_lcdc.h
-@@ -24,6 +24,7 @@
-
- #include <linux/workqueue.h>
- #include <linux/interrupt.h>
-+#include <linux/backlight.h>
-
- /* Way LCD wires are connected to the chip:
- * Some Atmel chips use BGR color mode (instead of standard RGB)
-@@ -48,6 +49,8 @@ struct atmel_lcdfb_devdata {
- void (*start)(struct atmel_lcdfb_info *sinfo);
- void (*stop)(struct atmel_lcdfb_info *sinfo, u32 flags);
- irqreturn_t (*isr)(int irq, void *dev_id);
-+ void (*init_contrast)(struct atmel_lcdfb_info *sinfo);
-+ const struct backlight_ops *bl_ops;
- };
-
- /* LCD Controller info data structure, stored in device platform_data */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 546b4b1084b216e3ee2a1cde0868ee256e5e43d5 Mon Sep 17 00:00:00 2001
-From: Wolfram Sang <w.sang@pengutronix.de>
-Date: Fri, 20 May 2011 14:31:29 +0200
-Subject: video: atmelfb: refactor dma_update
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
----
- drivers/video/atmel_lcdfb.c | 55 ++++++++++++++++++++++++++++++++++++
- drivers/video/atmel_lcdfb_core.c | 61 ++++------------------------------------
- include/video/atmel_lcdc.h | 2 ++
- 3 files changed, 62 insertions(+), 56 deletions(-)
-
-diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
-index 046e6c5..cd6d22e 100644
---- a/drivers/video/atmel_lcdfb.c
-+++ b/drivers/video/atmel_lcdfb.c
-@@ -31,6 +31,59 @@ static u32 contrast_ctr = ATMEL_LCDC_PS_DIV8
- | ATMEL_LCDC_POL_POSITIVE
- | ATMEL_LCDC_ENA_PWMENABLE;
-
-+#if defined(CONFIG_ARCH_AT91)
-+#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
-+ | FBINFO_PARTIAL_PAN_OK \
-+ | FBINFO_HWACCEL_YPAN)
-+
-+static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
-+ struct fb_var_screeninfo *var)
-+{
-+
-+}
-+#elif defined(CONFIG_AVR32)
-+#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
-+ | FBINFO_PARTIAL_PAN_OK \
-+ | FBINFO_HWACCEL_XPAN \
-+ | FBINFO_HWACCEL_YPAN)
-+
-+static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
-+ struct fb_var_screeninfo *var)
-+{
-+ u32 dma2dcfg;
-+ u32 pixeloff;
-+
-+ pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f;
-+
-+ dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8;
-+ dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
-+
-+ /* Update configuration */
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON,
-+ lcdc_readl(sinfo, ATMEL_LCDC_DMACON)
-+ | ATMEL_LCDC_DMAUPDT);
-+}
-+#endif
-+
-+static void atmel_lcdfb_update_dma(struct fb_info *info,
-+ struct fb_var_screeninfo *var)
-+{
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ struct fb_fix_screeninfo *fix = &info->fix;
-+ unsigned long dma_addr;
-+
-+ dma_addr = (fix->smem_start + var->yoffset * fix->line_length
-+ + var->xoffset * var->bits_per_pixel / 8);
-+
-+ dma_addr &= ~3UL;
-+
-+ /* Set framebuffer DMA base address and pixel offset */
-+ lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
-+
-+ atmel_lcdfb_update_dma2d(sinfo, var);
-+}
-+
- /* some bl->props field just changed */
- static int atmel_bl_update_status(struct backlight_device *bl)
- {
-@@ -323,8 +376,10 @@ static struct atmel_lcdfb_devdata dev_data = {
- .start = atmel_lcdfb_start,
- .stop = atmel_lcdfb_stop,
- .isr = atmel_lcdfb_interrupt,
-+ .update_dma = atmel_lcdfb_update_dma,
- .bl_ops = &atmel_lcdc_bl_ops,
- .init_contrast = atmel_lcdfb_init_contrast,
-+ .fbinfo_flags = ATMEL_LCDFB_FBINFO_DEFAULT,
- };
-
- static int __init atmel_lcdfb_probe(struct platform_device *pdev)
-diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c
-index ef63996..4146e9b 100644
---- a/drivers/video/atmel_lcdfb_core.c
-+++ b/drivers/video/atmel_lcdfb_core.c
-@@ -27,41 +27,6 @@
- /* configurable parameters */
- #define ATMEL_LCDC_CVAL_DEFAULT 0xc8
-
--#if defined(CONFIG_ARCH_AT91)
--#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
-- | FBINFO_PARTIAL_PAN_OK \
-- | FBINFO_HWACCEL_YPAN)
--
--static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
-- struct fb_var_screeninfo *var)
--{
--
--}
--#elif defined(CONFIG_AVR32)
--#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
-- | FBINFO_PARTIAL_PAN_OK \
-- | FBINFO_HWACCEL_XPAN \
-- | FBINFO_HWACCEL_YPAN)
--
--static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
-- struct fb_var_screeninfo *var)
--{
-- u32 dma2dcfg;
-- u32 pixeloff;
--
-- pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f;
--
-- dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8;
-- dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
-- lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
--
-- /* Update configuration */
-- lcdc_writel(sinfo, ATMEL_LCDC_DMACON,
-- lcdc_readl(sinfo, ATMEL_LCDC_DMACON)
-- | ATMEL_LCDC_DMAUPDT);
--}
--#endif
--
- #ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
-
- static void init_backlight(struct atmel_lcdfb_info *sinfo)
-@@ -119,24 +84,6 @@ static struct fb_fix_screeninfo atmel_lcdfb_fix = {
- .accel = FB_ACCEL_NONE,
- };
-
--static void atmel_lcdfb_update_dma(struct fb_info *info,
-- struct fb_var_screeninfo *var)
--{
-- struct atmel_lcdfb_info *sinfo = info->par;
-- struct fb_fix_screeninfo *fix = &info->fix;
-- unsigned long dma_addr;
--
-- dma_addr = (fix->smem_start + var->yoffset * fix->line_length
-- + var->xoffset * var->bits_per_pixel / 8);
--
-- dma_addr &= ~3UL;
--
-- /* Set framebuffer DMA base address and pixel offset */
-- lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
--
-- atmel_lcdfb_update_dma2d(sinfo, var);
--}
--
- static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
- {
- struct fb_info *info = sinfo->info;
-@@ -392,7 +339,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
-
- /* Re-initialize the DMA engine... */
- dev_dbg(info->device, " * update DMA engine\n");
-- atmel_lcdfb_update_dma(info, &info->var);
-+ sinfo->dev_data->update_dma(info, &info->var);
-
- /* Now, the LCDC core... */
- sinfo->dev_data->setup_core(info);
-@@ -496,9 +443,11 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
- static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var,
- struct fb_info *info)
- {
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+
- dev_dbg(info->device, "%s\n", __func__);
-
-- atmel_lcdfb_update_dma(info, var);
-+ sinfo->dev_data->update_dma(info, var);
-
- return 0;
- }
-@@ -633,7 +582,7 @@ int __atmel_lcdfb_probe(struct platform_device *pdev,
- sinfo->pdev = pdev;
-
- strcpy(info->fix.id, sinfo->pdev->name);
-- info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
-+ info->flags = dev_data->fbinfo_flags;
- info->pseudo_palette = sinfo->pseudo_palette;
- info->fbops = &atmel_lcdfb_ops;
-
-diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h
-index e7c0a3f..866ab47 100644
---- a/include/video/atmel_lcdc.h
-+++ b/include/video/atmel_lcdc.h
-@@ -49,8 +49,10 @@ struct atmel_lcdfb_devdata {
- void (*start)(struct atmel_lcdfb_info *sinfo);
- void (*stop)(struct atmel_lcdfb_info *sinfo, u32 flags);
- irqreturn_t (*isr)(int irq, void *dev_id);
-+ void (*update_dma)(struct fb_info *info, struct fb_var_screeninfo *var);
- void (*init_contrast)(struct atmel_lcdfb_info *sinfo);
- const struct backlight_ops *bl_ops;
-+ int fbinfo_flags;
- };
-
- /* LCD Controller info data structure, stored in device platform_data */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 67667d141480aa33acf52e27648fccb696282d03 Mon Sep 17 00:00:00 2001
-From: Wolfram Sang <w.sang@pengutronix.de>
-Date: Fri, 20 May 2011 14:51:45 +0200
-Subject: video: atmelfb: refactor LUT
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
----
- drivers/video/atmel_lcdfb.c | 1 +
- drivers/video/atmel_lcdfb_core.c | 6 ++++--
- include/video/atmel_lcdc.h | 8 ++------
- 3 files changed, 7 insertions(+), 8 deletions(-)
-
---- a/drivers/video/atmel_lcdfb.c
-+++ b/drivers/video/atmel_lcdfb.c
-@@ -380,6 +380,7 @@ static struct atmel_lcdfb_devdata dev_da
- .bl_ops = &atmel_lcdc_bl_ops,
- .init_contrast = atmel_lcdfb_init_contrast,
- .fbinfo_flags = ATMEL_LCDFB_FBINFO_DEFAULT,
-+ .lut_base = ATMEL_LCDC_LUT,
- };
-
- static int __init atmel_lcdfb_probe(struct platform_device *pdev)
---- a/drivers/video/atmel_lcdfb_core.c
-+++ b/drivers/video/atmel_lcdfb_core.c
-@@ -422,7 +422,8 @@ static int atmel_lcdfb_setcolreg(unsigne
- * ~(red[10] ^ green[10] ^ blue[10]) & 1
- */
-
-- lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
-+ lcdc_writel(sinfo, sinfo->dev_data->lut_base + regno * 4,
-+ val);
- ret = 0;
- }
- break;
-@@ -430,7 +431,8 @@ static int atmel_lcdfb_setcolreg(unsigne
- case FB_VISUAL_MONO01:
- if (regno < 2) {
- val = (regno == 0) ? 0x00 : 0x1F;
-- lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
-+ lcdc_writel(sinfo, sinfo->dev_data->lut_base + regno * 4,
-+ val);
- ret = 0;
- }
- break;
---- a/include/video/atmel_lcdc.h
-+++ b/include/video/atmel_lcdc.h
-@@ -53,6 +53,7 @@ struct atmel_lcdfb_devdata {
- void (*init_contrast)(struct atmel_lcdfb_info *sinfo);
- const struct backlight_ops *bl_ops;
- int fbinfo_flags;
-+ u32 lut_base;
- };
-
- /* LCD Controller info data structure, stored in device platform_data */
-@@ -242,11 +243,6 @@ struct atmel_lcdfb_info {
- #define ATMEL_LCDC_OWRI (1 << 5)
- #define ATMEL_LCDC_MERI (1 << 6)
-
--#if !defined(CONFIG_ARCH_AT91SAM9X5)
--#define ATMEL_LCDC_LUT(n) (0x0c00 + ((n)*4))
--#else
--/* Base layer CLUT */
--#define ATMEL_LCDC_LUT(n) (0x0400 + ((n)*4))
--#endif
-+#define ATMEL_LCDC_LUT 0x0c00
-
- #endif /* __ATMEL_LCDC_H__ */
+++ /dev/null
-From 005b72392f702b19971e90e6be15c87a37df492c Mon Sep 17 00:00:00 2001
-From: Wolfram Sang <w.sang@pengutronix.de>
-Date: Fri, 20 May 2011 15:04:10 +0200
-Subject: video: atmelfb: refactor limit_screeninfo
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
----
- drivers/video/atmel_lcdfb.c | 18 ++++++++++++++++++
- drivers/video/atmel_lcdfb_core.c | 14 ++------------
- include/video/atmel_lcdc.h | 1 +
- 3 files changed, 21 insertions(+), 12 deletions(-)
-
-diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
-index f8993cd..7a48e9c 100644
---- a/drivers/video/atmel_lcdfb.c
-+++ b/drivers/video/atmel_lcdfb.c
-@@ -306,6 +306,23 @@ static int atmel_lcdfb_setup_core(struct fb_info *info)
- return 0;
- }
-
-+static void atmelfb_limit_screeninfo(struct fb_var_screeninfo *var)
-+{
-+ /* Saturate vertical and horizontal timings at maximum values */
-+ var->vsync_len = min_t(u32, var->vsync_len,
-+ (ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1);
-+ var->upper_margin = min_t(u32, var->upper_margin,
-+ ATMEL_LCDC_VBP >> ATMEL_LCDC_VBP_OFFSET);
-+ var->lower_margin = min_t(u32, var->lower_margin,
-+ ATMEL_LCDC_VFP);
-+ var->right_margin = min_t(u32, var->right_margin,
-+ (ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 1);
-+ var->hsync_len = min_t(u32, var->hsync_len,
-+ (ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1);
-+ var->left_margin = min_t(u32, var->left_margin,
-+ ATMEL_LCDC_HBP + 1);
-+}
-+
- static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
- {
- struct fb_info *info = dev_id;
-@@ -379,6 +396,7 @@ static struct atmel_lcdfb_devdata dev_data = {
- .update_dma = atmel_lcdfb_update_dma,
- .bl_ops = &atmel_lcdc_bl_ops,
- .init_contrast = atmel_lcdfb_init_contrast,
-+ .limit_screeninfo = atmelfb_limit_screeninfo,
- .fbinfo_flags = ATMEL_LCDFB_FBINFO_DEFAULT,
- .lut_base = ATMEL_LCDC_LUT,
- };
-diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c
-index 0edafb6..20a4e4f 100644
---- a/drivers/video/atmel_lcdfb_core.c
-+++ b/drivers/video/atmel_lcdfb_core.c
-@@ -211,18 +211,8 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
- }
-
- /* Saturate vertical and horizontal timings at maximum values */
-- var->vsync_len = min_t(u32, var->vsync_len,
-- (ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1);
-- var->upper_margin = min_t(u32, var->upper_margin,
-- ATMEL_LCDC_VBP >> ATMEL_LCDC_VBP_OFFSET);
-- var->lower_margin = min_t(u32, var->lower_margin,
-- ATMEL_LCDC_VFP);
-- var->right_margin = min_t(u32, var->right_margin,
-- (ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 1);
-- var->hsync_len = min_t(u32, var->hsync_len,
-- (ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1);
-- var->left_margin = min_t(u32, var->left_margin,
-- ATMEL_LCDC_HBP + 1);
-+ if (sinfo->dev_data->limit_screeninfo)
-+ sinfo->dev_data->limit_screeninfo(var);
-
- /* Some parameters can't be zero */
- var->vsync_len = max_t(u32, var->vsync_len, 1);
-diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h
-index 6c470c4..6031b5a 100644
---- a/include/video/atmel_lcdc.h
-+++ b/include/video/atmel_lcdc.h
-@@ -51,6 +51,7 @@ struct atmel_lcdfb_devdata {
- irqreturn_t (*isr)(int irq, void *dev_id);
- void (*update_dma)(struct fb_info *info, struct fb_var_screeninfo *var);
- void (*init_contrast)(struct atmel_lcdfb_info *sinfo);
-+ void (*limit_screeninfo)(struct fb_var_screeninfo *var);
- const struct backlight_ops *bl_ops;
- int fbinfo_flags;
- u32 lut_base;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a9336b89063ddcea9906959bcc72ff47c7cbeed8 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 22 Oct 2012 15:45:30 +0200
-Subject: arm: at91: refactor lcdc-includes
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Among others the HEO-ISR bit is fixed.
-
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
-
-Conflicts:
- arch/arm/mach-at91/board-neocore926.c
- arch/arm/mach-at91/board-sam9261ek.c
- arch/arm/mach-at91/board-sam9263ek.c
- arch/arm/mach-at91/board-sam9m10g45ek.c
- arch/arm/mach-at91/board-sam9rlek.c
----
- arch/arm/mach-at91/at91sam9261_devices.c | 4
- arch/arm/mach-at91/at91sam9263_devices.c | 4
- arch/arm/mach-at91/at91sam9g45_devices.c | 4
- arch/arm/mach-at91/at91sam9rl_devices.c | 4
- arch/arm/mach-at91/board-neocore926.c | 4
- arch/arm/mach-at91/board-sam9261ek.c | 4
- arch/arm/mach-at91/board-sam9263ek.c | 4
- arch/arm/mach-at91/board-sam9m10g45ek.c | 4
- arch/arm/mach-at91/board-sam9rlek.c | 4
- arch/arm/mach-at91/include/mach/atmel_hlcdc.h | 718 ++++++++++++++++++
- arch/arm/mach-at91/include/mach/atmel_hlcdc_ovl.h | 156 +++
- arch/arm/mach-at91/include/mach/atmel_hlcdfb.h | 865 ----------------------
- arch/arm/mach-at91/include/mach/atmel_lcdc.h | 177 ++++
- drivers/video/atmel_lcdfb.c | 3
- drivers/video/atmel_lcdfb_core.c | 2
- include/video/atmel_lcdc.h | 249 ------
- include/video/atmel_lcdfb.h | 100 ++
- 17 files changed, 1181 insertions(+), 1125 deletions(-)
- rename arch/arm/mach-at91/include/mach/{atmel_hlcdfb.h => atmel_hlcdc.h} (82%)
- create mode 100644 arch/arm/mach-at91/include/mach/atmel_hlcdc_ovl.h
- rename {include/video => arch/arm/mach-at91/include/mach}/atmel_lcdc.h (73%)
- create mode 100644 include/video/atmel_lcdfb.h
-
---- a/arch/arm/mach-at91/at91sam9261_devices.c
-+++ b/arch/arm/mach-at91/at91sam9261_devices.c
-@@ -19,9 +19,11 @@
- #include <linux/i2c-gpio.h>
-
- #include <linux/fb.h>
--#include <video/atmel_lcdc.h>
-+#include <video/atmel_lcdfb.h>
-
- #include <mach/board.h>
-+#include <mach/gpio.h>
-+#include <mach/atmel_lcdc.h>
- #include <mach/at91sam9261.h>
- #include <mach/at91sam9261_matrix.h>
- #include <mach/at91_matrix.h>
---- a/arch/arm/mach-at91/at91sam9263_devices.c
-+++ b/arch/arm/mach-at91/at91sam9263_devices.c
-@@ -18,9 +18,11 @@
- #include <linux/i2c-gpio.h>
-
- #include <linux/fb.h>
--#include <video/atmel_lcdc.h>
-+#include <video/atmel_lcdfb.h>
-
- #include <mach/board.h>
-+#include <mach/gpio.h>
-+#include <mach/atmel_lcdc.h>
- #include <mach/at91sam9263.h>
- #include <mach/at91sam9263_matrix.h>
- #include <mach/at91_matrix.h>
---- a/arch/arm/mach-at91/at91sam9g45_devices.c
-+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
-@@ -20,9 +20,11 @@
- #include <linux/atmel-mci.h>
-
- #include <linux/fb.h>
--#include <video/atmel_lcdc.h>
-+#include <video/atmel_lcdfb.h>
-
- #include <mach/board.h>
-+#include <mach/gpio.h>
-+#include <mach/atmel_lcdc.h>
- #include <mach/at91sam9g45.h>
- #include <mach/at91sam9g45_matrix.h>
- #include <mach/at91_matrix.h>
---- a/arch/arm/mach-at91/at91sam9rl_devices.c
-+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
-@@ -15,9 +15,11 @@
- #include <linux/i2c-gpio.h>
-
- #include <linux/fb.h>
--#include <video/atmel_lcdc.h>
-+#include <video/atmel_lcdfb.h>
-
- #include <mach/board.h>
-+#include <mach/gpio.h>
-+#include <mach/atmel_lcdc.h>
- #include <mach/at91sam9rl.h>
- #include <mach/at91sam9rl_matrix.h>
- #include <mach/at91_matrix.h>
---- a/arch/arm/mach-at91/board-neocore926.c
-+++ b/arch/arm/mach-at91/board-neocore926.c
-@@ -32,7 +32,7 @@
- #include <linux/gpio_keys.h>
- #include <linux/input.h>
-
--#include <video/atmel_lcdc.h>
-+#include <video/atmel_lcdfb.h>
-
- #include <asm/setup.h>
- #include <asm/mach-types.h>
-@@ -46,6 +46,8 @@
- #include <mach/hardware.h>
- #include <mach/board.h>
- #include <mach/at91_aic.h>
-+#include <mach/gpio.h>
-+#include <mach/atmel_lcdc.h>
- #include <mach/at91sam9_smc.h>
-
- #include "sam9_smc.h"
---- a/arch/arm/mach-at91/board-sam9261ek.c
-+++ b/arch/arm/mach-at91/board-sam9261ek.c
-@@ -34,7 +34,7 @@
- #include <linux/gpio_keys.h>
- #include <linux/input.h>
-
--#include <video/atmel_lcdc.h>
-+#include <video/atmel_lcdfb.h>
-
- #include <asm/setup.h>
- #include <asm/mach-types.h>
-@@ -47,6 +47,8 @@
- #include <mach/hardware.h>
- #include <mach/board.h>
- #include <mach/at91_aic.h>
-+#include <mach/gpio.h>
-+#include <mach/atmel_lcdc.h>
- #include <mach/at91sam9_smc.h>
- #include <mach/at91_shdwc.h>
- #include <mach/system_rev.h>
---- a/arch/arm/mach-at91/board-sam9263ek.c
-+++ b/arch/arm/mach-at91/board-sam9263ek.c
-@@ -33,7 +33,7 @@
- #include <linux/input.h>
- #include <linux/leds.h>
-
--#include <video/atmel_lcdc.h>
-+#include <video/atmel_lcdfb.h>
-
- #include <asm/setup.h>
- #include <asm/mach-types.h>
-@@ -46,6 +46,8 @@
- #include <mach/hardware.h>
- #include <mach/board.h>
- #include <mach/at91_aic.h>
-+#include <mach/gpio.h>
-+#include <mach/atmel_lcdc.h>
- #include <mach/at91sam9_smc.h>
- #include <mach/at91_shdwc.h>
- #include <mach/system_rev.h>
---- a/arch/arm/mach-at91/board-sam9m10g45ek.c
-+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
-@@ -28,7 +28,7 @@
- #include <linux/delay.h>
-
- #include <mach/hardware.h>
--#include <video/atmel_lcdc.h>
-+#include <video/atmel_lcdfb.h>
- #include <media/soc_camera.h>
- #include <media/atmel-isi.h>
-
-@@ -42,6 +42,8 @@
-
- #include <mach/board.h>
- #include <mach/at91_aic.h>
-+#include <mach/gpio.h>
-+#include <mach/atmel_lcdc.h>
- #include <mach/at91sam9_smc.h>
- #include <mach/at91_shdwc.h>
- #include <mach/system_rev.h>
---- a/arch/arm/mach-at91/board-sam9rlek.c
-+++ b/arch/arm/mach-at91/board-sam9rlek.c
-@@ -19,7 +19,7 @@
- #include <linux/input.h>
- #include <linux/gpio_keys.h>
-
--#include <video/atmel_lcdc.h>
-+#include <video/atmel_lcdfb.h>
-
- #include <asm/setup.h>
- #include <asm/mach-types.h>
-@@ -32,6 +32,8 @@
- #include <mach/hardware.h>
- #include <mach/board.h>
- #include <mach/at91_aic.h>
-+#include <mach/gpio.h>
-+#include <mach/atmel_lcdc.h>
- #include <mach/at91sam9_smc.h>
- #include <mach/at91_shdwc.h>
-
---- /dev/null
-+++ b/arch/arm/mach-at91/include/mach/atmel_hlcdc.h
-@@ -0,0 +1,718 @@
-+/*
-+ * Header file for AT91 High end LCD Controller
-+ *
-+ * Data structure and register user interface
-+ *
-+ * Copyright (C) 2010 Atmel Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PUROFFSETE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+#ifndef __MACH_ATMEL_HLCD_H__
-+#define __MACH_ATMEL_HLCD_H__
-+
-+/* Lcdc hardware registers */
-+#define ATMEL_LCDC_LCDCFG0 0x0000
-+#define LCDC_LCDCFG0_CLKPOL (0x1 << 0)
-+#define LCDC_LCDCFG0_CLKSEL (0x1 << 2)
-+#define LCDC_LCDCFG0_CLKPWMSEL (0x1 << 3)
-+#define LCDC_LCDCFG0_CGDISBASE (0x1 << 8)
-+#define LCDC_LCDCFG0_CGDISOVR1 (0x1 << 9)
-+#define LCDC_LCDCFG0_CGDISHEO (0x1 << 11)
-+#define LCDC_LCDCFG0_CGDISHCR (0x1 << 12)
-+#define LCDC_LCDCFG0_CLKDIV_OFFSET 16
-+#define LCDC_LCDCFG0_CLKDIV (0xff << LCDC_LCDCFG0_CLKDIV_OFFSET)
-+
-+#define ATMEL_LCDC_LCDCFG1 0x0004
-+#define LCDC_LCDCFG1_HSPW_OFFSET 0
-+#define LCDC_LCDCFG1_HSPW (0x3f << LCDC_LCDCFG1_HSPW_OFFSET)
-+#define LCDC_LCDCFG1_VSPW_OFFSET 16
-+#define LCDC_LCDCFG1_VSPW (0x3f << LCDC_LCDCFG1_VSPW_OFFSET)
-+
-+#define ATMEL_LCDC_LCDCFG2 0x0008
-+#define LCDC_LCDCFG2_VFPW_OFFSET 0
-+#define LCDC_LCDCFG2_VFPW (0x3f << LCDC_LCDCFG2_VFPW_OFFSET)
-+#define LCDC_LCDCFG2_VBPW_OFFSET 16
-+#define LCDC_LCDCFG2_VBPW (0x3f << LCDC_LCDCFG2_VBPW_OFFSET)
-+
-+#define ATMEL_LCDC_LCDCFG3 0x000C
-+#define LCDC_LCDCFG3_HFPW_OFFSET 0
-+#define LCDC_LCDCFG3_HFPW (0xff << LCDC_LCDCFG3_HFPW_OFFSET)
-+#define LCDC_LCDCFG3_HBPW_OFFSET 16
-+#define LCDC_LCDCFG3_HBPW (0xff << LCDC_LCDCFG3_HBPW_OFFSET)
-+
-+#define ATMEL_LCDC_LCDCFG4 0x0010
-+#define LCDC_LCDCFG4_PPL_OFFSET 0
-+#define LCDC_LCDCFG4_PPL (0x7ff << LCDC_LCDCFG4_PPL_OFFSET)
-+#define LCDC_LCDCFG4_RPF_OFFSET 16
-+#define LCDC_LCDCFG4_RPF (0x7ff << LCDC_LCDCFG4_RPF_OFFSET)
-+
-+#define ATMEL_LCDC_LCDCFG5 0x0014
-+#define LCDC_LCDCFG5_HSPOL (0x1 << 0)
-+#define LCDC_LCDCFG5_VSPOL (0x1 << 1)
-+#define LCDC_LCDCFG5_VSPDLYS (0x1 << 2)
-+#define LCDC_LCDCFG5_VSPDLYE (0x1 << 3)
-+#define LCDC_LCDCFG5_DISPPOL (0x1 << 4)
-+#define LCDC_LCDCFG5_SERIAL (0x1 << 5)
-+#define LCDC_LCDCFG5_DITHER (0x1 << 6)
-+#define LCDC_LCDCFG5_DISPDLY (0x1 << 7)
-+#define LCDC_LCDCFG5_MODE_OFFSET 8
-+#define LCDC_LCDCFG5_MODE (0x3 << LCDC_LCDCFG5_MODE_OFFSET)
-+#define LCDC_LCDCFG5_MODE_OUTPUT_12BPP (0x0 << 8)
-+#define LCDC_LCDCFG5_MODE_OUTPUT_16BPP (0x1 << 8)
-+#define LCDC_LCDCFG5_MODE_OUTPUT_18BPP (0x2 << 8)
-+#define LCDC_LCDCFG5_MODE_OUTPUT_24BPP (0x3 << 8)
-+#define LCDC_LCDCFG5_VSPSU (0x1 << 12)
-+#define LCDC_LCDCFG5_VSPHO (0x1 << 13)
-+#define LCDC_LCDCFG5_GUARDTIME_OFFSET 16
-+#define LCDC_LCDCFG5_GUARDTIME (0x1f << LCDC_LCDCFG5_GUARDTIME_OFFSET)
-+
-+#define ATMEL_LCDC_LCDCFG6 0x0018
-+#define LCDC_LCDCFG6_PWMPS_OFFSET 0
-+#define LCDC_LCDCFG6_PWMPS (0x7 << LCDC_LCDCFG6_PWMPS_OFFSET)
-+#define LCDC_LCDCFG6_PWMPOL (0x1 << 4)
-+#define LCDC_LCDCFG6_PWMCVAL_OFFSET 8
-+#define LCDC_LCDCFG6_PWMCVAL (0xff << LCDC_LCDCFG6_PWMCVAL_OFFSET)
-+
-+#define ATMEL_LCDC_LCDEN 0x0020
-+#define LCDC_LCDEN_CLKEN (0x1 << 0)
-+#define LCDC_LCDEN_SYNCEN (0x1 << 1)
-+#define LCDC_LCDEN_DISPEN (0x1 << 2)
-+#define LCDC_LCDEN_PWMEN (0x1 << 3)
-+
-+#define ATMEL_LCDC_LCDDIS 0x0024
-+#define LCDC_LCDDIS_CLKDIS (0x1 << 0)
-+#define LCDC_LCDDIS_SYNCDIS (0x1 << 1)
-+#define LCDC_LCDDIS_DISPDIS (0x1 << 2)
-+#define LCDC_LCDDIS_PWMDIS (0x1 << 3)
-+#define LCDC_LCDDIS_CLKRST (0x1 << 8)
-+#define LCDC_LCDDIS_SYNCRST (0x1 << 9)
-+#define LCDC_LCDDIS_DISPRST (0x1 << 10)
-+#define LCDC_LCDDIS_PWMRST (0x1 << 11)
-+
-+#define ATMEL_LCDC_LCDSR 0x0028
-+#define LCDC_LCDSR_CLKSTS (0x1 << 0)
-+#define LCDC_LCDSR_LCDSTS (0x1 << 1)
-+#define LCDC_LCDSR_DISPSTS (0x1 << 2)
-+#define LCDC_LCDSR_PWMSTS (0x1 << 3)
-+#define LCDC_LCDSR_SIPSTS (0x1 << 4)
-+
-+#define ATMEL_LCDC_LCDIER 0x002C
-+#define LCDC_LCDIER_SOFIE (0x1 << 0)
-+#define LCDC_LCDIER_DISIE (0x1 << 1)
-+#define LCDC_LCDIER_DISPIE (0x1 << 2)
-+#define LCDC_LCDIER_FIFOERRIE (0x1 << 4)
-+#define LCDC_LCDIER_BASEIE (0x1 << 8)
-+#define LCDC_LCDIER_OVR1IE (0x1 << 9)
-+#define LCDC_LCDIER_HEOIE (0x1 << 11)
-+#define LCDC_LCDIER_HCRIE (0x1 << 12)
-+
-+#define ATMEL_LCDC_LCDIDR 0x0030
-+#define LCDC_LCDIDR_SOFID (0x1 << 0)
-+#define LCDC_LCDIDR_DISID (0x1 << 1)
-+#define LCDC_LCDIDR_DISPID (0x1 << 2)
-+#define LCDC_LCDIDR_FIFOERRID (0x1 << 4)
-+#define LCDC_LCDIDR_BASEID (0x1 << 8)
-+#define LCDC_LCDIDR_OVR1ID (0x1 << 9)
-+#define LCDC_LCDIDR_HEOID (0x1 << 11)
-+#define LCDC_LCDIDR_HCRID (0x1 << 12)
-+
-+#define ATMEL_LCDC_LCDIMR 0x0034
-+#define LCDC_LCDIMR_SOFIM (0x1 << 0)
-+#define LCDC_LCDIMR_DISIM (0x1 << 1)
-+#define LCDC_LCDIMR_DISPIM (0x1 << 2)
-+#define LCDC_LCDIMR_FIFOERRIM (0x1 << 4)
-+#define LCDC_LCDIMR_BASEIM (0x1 << 8)
-+#define LCDC_LCDIMR_OVR1IM (0x1 << 9)
-+#define LCDC_LCDIMR_HEOIM (0x1 << 11)
-+#define LCDC_LCDIMR_HCRIM (0x1 << 12)
-+
-+#define ATMEL_LCDC_LCDISR 0x0038
-+#define LCDC_LCDISR_SOF (0x1 << 0)
-+#define LCDC_LCDISR_DIS (0x1 << 1)
-+#define LCDC_LCDISR_DISP (0x1 << 2)
-+#define LCDC_LCDISR_FIFOERR (0x1 << 4)
-+#define LCDC_LCDISR_BASE (0x1 << 8)
-+#define LCDC_LCDISR_OVR1 (0x1 << 9)
-+#define LCDC_LCDISR_HEO (0x1 << 10)
-+#define LCDC_LCDISR_HCR (0x1 << 12)
-+
-+#define ATMEL_LCDC_BASECHER 0x0040
-+#define LCDC_BASECHER_CHEN (0x1 << 0)
-+#define LCDC_BASECHER_UPDATEEN (0x1 << 1)
-+#define LCDC_BASECHER_A2QEN (0x1 << 2)
-+
-+#define ATMEL_LCDC_BASECHDR 0x0044
-+#define LCDC_BASECHDR_CHDIS (0x1 << 0)
-+#define LCDC_BASECHDR_CHRST (0x1 << 8)
-+
-+#define ATMEL_LCDC_BASECHSR 0x0048
-+#define LCDC_BASECHSR_CHSR (0x1 << 0)
-+#define LCDC_BASECHSR_UPDATESR (0x1 << 1)
-+#define LCDC_BASECHSR_A2QSR (0x1 << 2)
-+
-+#define ATMEL_LCDC_BASEIER 0x004C
-+#define LCDC_BASEIER_DMA (0x1 << 2)
-+#define LCDC_BASEIER_DSCR (0x1 << 3)
-+#define LCDC_BASEIER_ADD (0x1 << 4)
-+#define LCDC_BASEIER_DONE (0x1 << 5)
-+#define LCDC_BASEIER_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_BASEIDR 0x0050
-+#define LCDC_BASEIDR_DMA (0x1 << 2)
-+#define LCDC_BASEIDR_DSCR (0x1 << 3)
-+#define LCDC_BASEIDR_ADD (0x1 << 4)
-+#define LCDC_BASEIDR_DONE (0x1 << 5)
-+#define LCDC_BASEIDR_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_BASEIMR 0x0054
-+#define LCDC_BASEIMR_DMA (0x1 << 2)
-+#define LCDC_BASEIMR_DSCR (0x1 << 3)
-+#define LCDC_BASEIMR_ADD (0x1 << 4)
-+#define LCDC_BASEIMR_DONE (0x1 << 5)
-+#define LCDC_BASEIMR_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_BASEISR 0x0058
-+#define LCDC_BASEISR_DMA (0x1 << 2)
-+#define LCDC_BASEISR_DSCR (0x1 << 3)
-+#define LCDC_BASEISR_ADD (0x1 << 4)
-+#define LCDC_BASEISR_DONE (0x1 << 5)
-+#define LCDC_BASEISR_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_BASEHEAD 0x005C
-+
-+#define ATMEL_LCDC_BASEADDR 0x0060
-+
-+#define ATMEL_LCDC_BASECTRL 0x0064
-+#define LCDC_BASECTRL_DFETCH (0x1 << 0)
-+#define LCDC_BASECTRL_LFETCH (0x1 << 1)
-+#define LCDC_BASECTRL_DMAIEN (0x1 << 2)
-+#define LCDC_BASECTRL_DSCRIEN (0x1 << 3)
-+#define LCDC_BASECTRL_ADDIEN (0x1 << 4)
-+#define LCDC_BASECTRL_DONEIEN (0x1 << 5)
-+
-+#define ATMEL_LCDC_BASENEXT 0x0068
-+
-+#define ATMEL_LCDC_BASECFG0 0x006C
-+#define LCDC_BASECFG0_BLEN_OFFSET 4
-+#define LCDC_BASECFG0_BLEN (0x3 << LCDC_BASECFG0_BLEN_OFFSET)
-+#define LCDC_BASECFG0_BLEN_AHB_SINGLE (0x0 << 4)
-+#define LCDC_BASECFG0_BLEN_AHB_INCR4 (0x1 << 4)
-+#define LCDC_BASECFG0_BLEN_AHB_INCR8 (0x2 << 4)
-+#define LCDC_BASECFG0_BLEN_AHB_INCR16 (0x3 << 4)
-+#define LCDC_BASECFG0_DLBO (0x1 << 8)
-+
-+#define ATMEL_LCDC_BASECFG1 0x0070
-+#define LCDC_BASECFG1_CLUTEN (0x1 << 0)
-+#define LCDC_BASECFG1_RGBMODE_OFFSET 4
-+#define LCDC_BASECFG1_RGBMODE (0xf << LCDC_BASECFG1_RGBMODE_OFFSET)
-+#define LCDC_BASECFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4)
-+#define LCDC_BASECFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4)
-+#define LCDC_BASECFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4)
-+#define LCDC_BASECFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4)
-+#define LCDC_BASECFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4)
-+#define LCDC_BASECFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4)
-+#define LCDC_BASECFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4)
-+#define LCDC_BASECFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4)
-+#define LCDC_BASECFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4)
-+#define LCDC_BASECFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4)
-+#define LCDC_BASECFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4)
-+#define LCDC_BASECFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4)
-+#define LCDC_BASECFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4)
-+#define LCDC_BASECFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4)
-+#define LCDC_BASECFG1_CLUTMODE_OFFSET 8
-+#define LCDC_BASECFG1_CLUTMODE (0x3 << LCDC_BASECFG1_CLUTMODE_OFFSET)
-+#define LCDC_BASECFG1_CLUTMODE_1BPP (0x0 << 8)
-+#define LCDC_BASECFG1_CLUTMODE_2BPP (0x1 << 8)
-+#define LCDC_BASECFG1_CLUTMODE_4BPP (0x2 << 8)
-+#define LCDC_BASECFG1_CLUTMODE_8BPP (0x3 << 8)
-+
-+#define ATMEL_LCDC_BASECFG2 0x0074
-+
-+#define ATMEL_LCDC_BASECFG3 0x0078
-+#define LCDC_BASECFG3_BDEF_OFFSET 0
-+#define LCDC_BASECFG3_BDEF (0xff << LCDC_BASECFG3_BDEF_OFFSET)
-+#define LCDC_BASECFG3_GDEF_OFFSET 8
-+#define LCDC_BASECFG3_GDEF (0xff << LCDC_BASECFG3_GDEF_OFFSET)
-+#define LCDC_BASECFG3_RDEF_OFFSET 16
-+#define LCDC_BASECFG3_RDEF (0xff << LCDC_BASECFG3_RDEF_OFFSET)
-+
-+#define ATMEL_LCDC_BASECFG4 0x007C
-+#define LCDC_BASECFG4_DMA (0x1 << 8)
-+#define LCDC_BASECFG4_REP (0x1 << 9)
-+
-+#define ATMEL_LCDC_HEOCHER 0x0280
-+#define LCDC_HEOCHER_CHEN (0x1 << 0)
-+#define LCDC_HEOCHER_UPDATEEN (0x1 << 1)
-+#define LCDC_HEOCHER_A2QEN (0x1 << 2)
-+
-+#define ATMEL_LCDC_HEOCHDR 0x0284
-+#define LCDC_HEOCHDR_CHDIS (0x1 << 0)
-+#define LCDC_HEOCHDR_CHRST (0x1 << 8)
-+
-+#define ATMEL_LCDC_HEOCHSR 0x0288
-+#define LCDC_HEOCHSR_CHSR (0x1 << 0)
-+#define LCDC_HEOCHSR_UPDATESR (0x1 << 1)
-+#define LCDC_HEOCHSR_A2QSR (0x1 << 2)
-+
-+#define ATMEL_LCDC_HEOIER 0x028C
-+#define LCDC_HEOIER_DMA (0x1 << 2)
-+#define LCDC_HEOIER_DSCR (0x1 << 3)
-+#define LCDC_HEOIER_ADD (0x1 << 4)
-+#define LCDC_HEOIER_DONE (0x1 << 5)
-+#define LCDC_HEOIER_OVR (0x1 << 6)
-+#define LCDC_HEOIER_UDMA (0x1 << 10)
-+#define LCDC_HEOIER_UDSCR (0x1 << 11)
-+#define LCDC_HEOIER_UADD (0x1 << 12)
-+#define LCDC_HEOIER_UDONE (0x1 << 13)
-+#define LCDC_HEOIER_UOVR (0x1 << 14)
-+#define LCDC_HEOIER_VDMA (0x1 << 18)
-+#define LCDC_HEOIER_VDSCR (0x1 << 19)
-+#define LCDC_HEOIER_VADD (0x1 << 20)
-+#define LCDC_HEOIER_VDONE (0x1 << 21)
-+#define LCDC_HEOIER_VOVR (0x1 << 22)
-+
-+#define ATMEL_LCDC_HEOIDR 0x0290
-+#define LCDC_HEOIDR_DMA (0x1 << 2)
-+#define LCDC_HEOIDR_DSCR (0x1 << 3)
-+#define LCDC_HEOIDR_ADD (0x1 << 4)
-+#define LCDC_HEOIDR_DONE (0x1 << 5)
-+#define LCDC_HEOIDR_OVR (0x1 << 6)
-+#define LCDC_HEOIDR_UDMA (0x1 << 10)
-+#define LCDC_HEOIDR_UDSCR (0x1 << 11)
-+#define LCDC_HEOIDR_UADD (0x1 << 12)
-+#define LCDC_HEOIDR_UDONE (0x1 << 13)
-+#define LCDC_HEOIDR_UOVR (0x1 << 14)
-+#define LCDC_HEOIDR_VDMA (0x1 << 18)
-+#define LCDC_HEOIDR_VDSCR (0x1 << 19)
-+#define LCDC_HEOIDR_VADD (0x1 << 20)
-+#define LCDC_HEOIDR_VDONE (0x1 << 21)
-+#define LCDC_HEOIDR_VOVR (0x1 << 22)
-+
-+#define ATMEL_LCDC_HEOIMR 0x0294
-+#define LCDC_HEOIMR_DMA (0x1 << 2)
-+#define LCDC_HEOIMR_DSCR (0x1 << 3)
-+#define LCDC_HEOIMR_ADD (0x1 << 4)
-+#define LCDC_HEOIMR_DONE (0x1 << 5)
-+#define LCDC_HEOIMR_OVR (0x1 << 6)
-+#define LCDC_HEOIMR_UDMA (0x1 << 10)
-+#define LCDC_HEOIMR_UDSCR (0x1 << 11)
-+#define LCDC_HEOIMR_UADD (0x1 << 12)
-+#define LCDC_HEOIMR_UDONE (0x1 << 13)
-+#define LCDC_HEOIMR_UOVR (0x1 << 14)
-+#define LCDC_HEOIMR_VDMA (0x1 << 18)
-+#define LCDC_HEOIMR_VDSCR (0x1 << 19)
-+#define LCDC_HEOIMR_VADD (0x1 << 20)
-+#define LCDC_HEOIMR_VDONE (0x1 << 21)
-+#define LCDC_HEOIMR_VOVR (0x1 << 22)
-+
-+#define ATMEL_LCDC_HEOISR 0x0298
-+#define LCDC_HEOISR_DMA (0x1 << 2)
-+#define LCDC_HEOISR_DSCR (0x1 << 3)
-+#define LCDC_HEOISR_ADD (0x1 << 4)
-+#define LCDC_HEOISR_DONE (0x1 << 5)
-+#define LCDC_HEOISR_OVR (0x1 << 6)
-+#define LCDC_HEOISR_UDMA (0x1 << 10)
-+#define LCDC_HEOISR_UDSCR (0x1 << 11)
-+#define LCDC_HEOISR_UADD (0x1 << 12)
-+#define LCDC_HEOISR_UDONE (0x1 << 13)
-+#define LCDC_HEOISR_UOVR (0x1 << 14)
-+#define LCDC_HEOISR_VDMA (0x1 << 18)
-+#define LCDC_HEOISR_VDSCR (0x1 << 19)
-+#define LCDC_HEOISR_VADD (0x1 << 20)
-+#define LCDC_HEOISR_VDONE (0x1 << 21)
-+#define LCDC_HEOISR_VOVR (0x1 << 22)
-+
-+#define ATMEL_LCDC_HEOHEAD 0x029C
-+
-+#define ATMEL_LCDC_HEOADDR 0x02A0
-+
-+#define ATMEL_LCDC_HEOCTRL 0x02A4
-+#define LCDC_HEOCTRL_DFETCH (0x1 << 0)
-+#define LCDC_HEOCTRL_LFETCH (0x1 << 1)
-+#define LCDC_HEOCTRL_DMAIEN (0x1 << 2)
-+#define LCDC_HEOCTRL_DSCRIEN (0x1 << 3)
-+#define LCDC_HEOCTRL_ADDIEN (0x1 << 4)
-+#define LCDC_HEOCTRL_DONEIEN (0x1 << 5)
-+
-+#define ATMEL_LCDC_HEONEXT 0x02A8
-+
-+#define ATMEL_LCDC_HEOUHEAD 0x02AC
-+
-+#define ATMEL_LCDC_HEOUADDR 0x02B0
-+
-+#define ATMEL_LCDC_HEOUCTRL 0x02B4
-+#define LCDC_HEOUCTRL_UDFETCH (0x1 << 0)
-+#define LCDC_HEOUCTRL_UDMAIEN (0x1 << 2)
-+#define LCDC_HEOUCTRL_UDSCRIEN (0x1 << 3)
-+#define LCDC_HEOUCTRL_UADDIEN (0x1 << 4)
-+#define LCDC_HEOUCTRL_UDONEIEN (0x1 << 5)
-+
-+#define ATMEL_LCDC_HEOUNEXT 0x02B8
-+
-+#define ATMEL_LCDC_HEOVHEAD 0x02BC
-+
-+#define ATMEL_LCDC_HEOVADDR 0x02C0
-+
-+#define ATMEL_LCDC_HEOVCTRL 0x02C4
-+#define LCDC_HEOVCTRL_VDFETCH (0x1 << 0)
-+#define LCDC_HEOVCTRL_VDMAIEN (0x1 << 2)
-+#define LCDC_HEOVCTRL_VDSCRIEN (0x1 << 3)
-+#define LCDC_HEOVCTRL_VADDIEN (0x1 << 4)
-+#define LCDC_HEOVCTRL_VDONEIEN (0x1 << 5)
-+
-+#define ATMEL_LCDC_HEOVNEXT 0x02C8
-+
-+#define ATMEL_LCDC_HEOCFG0 0x02CC
-+#define LCDC_HEOCFG0_BLEN_OFFSET 4
-+#define LCDC_HEOCFG0_BLEN (0x3 << LCDC_HEOCFG0_BLEN_OFFSET)
-+#define LCDC_HEOCFG0_BLEN_AHB_SINGLE (0x0 << 4)
-+#define LCDC_HEOCFG0_BLEN_AHB_INCR4 (0x1 << 4)
-+#define LCDC_HEOCFG0_BLEN_AHB_INCR8 (0x2 << 4)
-+#define LCDC_HEOCFG0_BLEN_AHB_INCR16 (0x3 << 4)
-+#define LCDC_HEOCFG0_BLENUV_OFFSET 6
-+#define LCDC_HEOCFG0_BLENUV (0x3 << LCDC_HEOCFG0_BLENUV_OFFSET)
-+#define LCDC_HEOCFG0_BLENUV_AHB_SINGLE (0x0 << 6)
-+#define LCDC_HEOCFG0_BLENUV_AHB_INCR4 (0x1 << 6)
-+#define LCDC_HEOCFG0_BLENUV_AHB_INCR8 (0x2 << 6)
-+#define LCDC_HEOCFG0_BLENUV_AHB_INCR16 (0x3 << 6)
-+#define LCDC_HEOCFG0_DLBO (0x1 << 8)
-+#define LCDC_HEOCFG0_ROTDIS (0x1 << 12)
-+#define LCDC_HEOCFG0_LOCKDIS (0x1 << 13)
-+
-+#define ATMEL_LCDC_HEOCFG1 0x02D0
-+#define LCDC_HEOCFG1_CLUTEN (0x1 << 0)
-+#define LCDC_HEOCFG1_YUVEN (0x1 << 1)
-+#define LCDC_HEOCFG1_RGBMODE_OFFSET 4
-+#define LCDC_HEOCFG1_RGBMODE (0xf << LCDC_HEOCFG1_RGBMODE_OFFSET)
-+#define LCDC_HEOCFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4)
-+#define LCDC_HEOCFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4)
-+#define LCDC_HEOCFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4)
-+#define LCDC_HEOCFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4)
-+#define LCDC_HEOCFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4)
-+#define LCDC_HEOCFG1_CLUTMODE_OFFSET 8
-+#define LCDC_HEOCFG1_CLUTMODE (0x3 << LCDC_HEOCFG1_CLUTMODE_OFFSET)
-+#define LCDC_HEOCFG1_CLUTMODE_1BPP (0x0 << 8)
-+#define LCDC_HEOCFG1_CLUTMODE_2BPP (0x1 << 8)
-+#define LCDC_HEOCFG1_CLUTMODE_4BPP (0x2 << 8)
-+#define LCDC_HEOCFG1_CLUTMODE_8BPP (0x3 << 8)
-+#define LCDC_HEOCFG1_YUVMODE_OFFSET 12
-+#define LCDC_HEOCFG1_YUVMODE (0xf << LCDC_HEOCFG1_YUVMODE_OFFSET)
-+#define LCDC_HEOCFG1_YUVMODE_32BPP_AYCBCR (0x0 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE0 (0x1 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE1 (0x2 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE2 (0x3 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE3 (0x4 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_SEMIPLANAR (0x5 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_PLANAR (0x6 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_12BPP_YCBCR_SEMIPLANAR (0x7 << 12)
-+#define LCDC_HEOCFG1_YUVMODE_12BPP_YCBCR_PLANAR (0x8 << 12)
-+#define LCDC_HEOCFG1_YUV422ROT (0x1 << 16)
-+#define LCDC_HEOCFG1_YUV422SWP (0x1 << 17)
-+
-+#define ATMEL_LCDC_HEOCFG2 0x02D4
-+#define LCDC_HEOCFG2_XOFFSET_OFFSET 0
-+#define LCDC_HEOCFG2_XOFFSET (0x7ff << LCDC_HEOCFG2_XOFFSET_OFFSET)
-+#define LCDC_HEOCFG2_YOFFSET_OFFSET 16
-+#define LCDC_HEOCFG2_YOFFSET (0x7ff << LCDC_HEOCFG2_YOFFSET_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCFG3 0x02D8
-+#define LCDC_HEOCFG3_XSIZE_OFFSET 0
-+#define LCDC_HEOCFG3_XSIZE (0x7ff << LCDC_HEOCFG3_XSIZE_OFFSET)
-+#define LCDC_HEOCFG3_YSIZE_OFFSET 16
-+#define LCDC_HEOCFG3_YSIZE (0x7ff << LCDC_HEOCFG3_YSIZE_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCFG4 0x02DC
-+#define LCDC_HEOCFG4_XMEM_SIZE_OFFSET 0
-+#define LCDC_HEOCFG4_XMEM_SIZE (0x7ff << LCDC_HEOCFG4_XMEM_SIZE_OFFSET)
-+#define LCDC_HEOCFG4_YMEM_SIZE_OFFSET 16
-+#define LCDC_HEOCFG4_YMEM_SIZE (0x7ff << LCDC_HEOCFG4_YMEM_SIZE_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCFG5 0x02E0
-+
-+#define ATMEL_LCDC_HEOCFG6 0x02E4
-+
-+#define ATMEL_LCDC_HEOCFG7 0x02E8
-+
-+#define ATMEL_LCDC_HEOCFG8 0x02EC
-+
-+#define ATMEL_LCDC_HEOCFG9 0x02F0
-+#define LCDC_HEOCFG9_BDEF_OFFSET 0
-+#define LCDC_HEOCFG9_BDEF (0xff << LCDC_HEOCFG9_BDEF_OFFSET)
-+#define LCDC_HEOCFG9_GDEF_OFFSET 8
-+#define LCDC_HEOCFG9_GDEF (0xff << LCDC_HEOCFG9_GDEF_OFFSET)
-+#define LCDC_HEOCFG9_RDEF_OFFSET 16
-+#define LCDC_HEOCFG9_RDEF (0xff << LCDC_HEOCFG9_RDEF_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCFG10 0x02F4
-+#define LCDC_HEOCFG10_BKEY_OFFSET 0
-+#define LCDC_HEOCFG10_BKEY (0xff << LCDC_HEOCFG10_BKEY_OFFSET)
-+#define LCDC_HEOCFG10_GKEY_OFFSET 8
-+#define LCDC_HEOCFG10_GKEY (0xff << LCDC_HEOCFG10_GKEY_OFFSET)
-+#define LCDC_HEOCFG10_RKEY_OFFSET 16
-+#define LCDC_HEOCFG10_RKEY (0xff << LCDC_HEOCFG10_RKEY_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCFG11 0x02F8
-+#define LCDC_HEOCFG11_BMASK_OFFSET 0
-+#define LCDC_HEOCFG11_BMASK (0xff << LCDC_HEOCFG11_BMASK_OFFSET)
-+#define LCDC_HEOCFG11_GMASK_OFFSET 8
-+#define LCDC_HEOCFG11_GMASK (0xff << LCDC_HEOCFG11_GMASK_OFFSET)
-+#define LCDC_HEOCFG11_RMASK_OFFSET 16
-+#define LCDC_HEOCFG11_RMASK (0xff << LCDC_HEOCFG11_RMASK_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCFG12 0x02FC
-+#define LCDC_HEOCFG12_CRKEY (0x1 << 0)
-+#define LCDC_HEOCFG12_INV (0x1 << 1)
-+#define LCDC_HEOCFG12_ITER2BL (0x1 << 2)
-+#define LCDC_HEOCFG12_ITER (0x1 << 3)
-+#define LCDC_HEOCFG12_REVALPHA (0x1 << 4)
-+#define LCDC_HEOCFG12_GAEN (0x1 << 5)
-+#define LCDC_HEOCFG12_LAEN (0x1 << 6)
-+#define LCDC_HEOCFG12_OVR (0x1 << 7)
-+#define LCDC_HEOCFG12_DMA (0x1 << 8)
-+#define LCDC_HEOCFG12_REP (0x1 << 9)
-+#define LCDC_HEOCFG12_DSTKEY (0x1 << 10)
-+#define LCDC_HEOCFG12_VIDPRI (0x1 << 12)
-+#define LCDC_HEOCFG12_GA_OFFSET 16
-+#define LCDC_HEOCFG12_GA (0xff << LCDC_HEOCFG12_GA_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCFG13 0x0300
-+#define LCDC_HEOCFG13_XFACTOR_OFFSET 0
-+#define LCDC_HEOCFG13_XFACTOR (0x1fff << LCDC_HEOCFG13_XFACTOR_OFFSET)
-+#define LCDC_HEOCFG13_YFACTOR_OFFSET 16
-+#define LCDC_HEOCFG13_YFACTOR (0x1fff << LCDC_HEOCFG13_YFACTOR_OFFSET)
-+#define LCDC_HEOCFG13_SCALEN (0x1 << 31)
-+
-+#define ATMEL_LCDC_HEOCFG14 0x0304
-+#define LCDC_HEOCFG14_CSCRY_OFFSET 0
-+#define LCDC_HEOCFG14_CSCRY (0x3ff << LCDC_HEOCFG14_CSCRY_OFFSET)
-+#define LCDC_HEOCFG14_CSCRU_OFFSET 10
-+#define LCDC_HEOCFG14_CSCRU (0x3ff << LCDC_HEOCFG14_CSCRU_OFFSET)
-+#define LCDC_HEOCFG14_CSCRV_OFFSET 20
-+#define LCDC_HEOCFG14_CSCRV (0x3ff << LCDC_HEOCFG14_CSCRV_OFFSET)
-+#define LCDC_HEOCFG14_CSCYOFF (0x1 << 30)
-+
-+#define ATMEL_LCDC_HEOCFG15 0x0308
-+#define LCDC_HEOCFG15_CSCGY_OFFSET 0
-+#define LCDC_HEOCFG15_CSCGY (0x3ff << LCDC_HEOCFG15_CSCGY_OFFSET)
-+#define LCDC_HEOCFG15_CSCGU_OFFSET 10
-+#define LCDC_HEOCFG15_CSCGU (0x3ff << LCDC_HEOCFG15_CSCGU_OFFSET)
-+#define LCDC_HEOCFG15_CSCGV_OFFSET 20
-+#define LCDC_HEOCFG15_CSCGV (0x3ff << LCDC_HEOCFG15_CSCGV_OFFSET)
-+#define LCDC_HEOCFG15_CSCUOFF (0x1 << 30)
-+
-+#define ATMEL_LCDC_HEOCFG16 0x030C
-+#define LCDC_HEOCFG16_CSCBY_OFFSET 0
-+#define LCDC_HEOCFG16_CSCBY (0x3ff << LCDC_HEOCFG16_CSCBY_OFFSET)
-+#define LCDC_HEOCFG16_CSCBU_OFFSET 10
-+#define LCDC_HEOCFG16_CSCBU (0x3ff << LCDC_HEOCFG16_CSCBU_OFFSET)
-+#define LCDC_HEOCFG16_CSCBV_OFFSET 20
-+#define LCDC_HEOCFG16_CSCBV (0x3ff << LCDC_HEOCFG16_CSCBV_OFFSET)
-+#define LCDC_HEOCFG16_CSCVOFF (0x1 << 30)
-+
-+#define ATMEL_LCDC_HCRCHER 0x0340
-+#define LCDC_HCRCHER_CHEN (0x1 << 0)
-+#define LCDC_HCRCHER_UPDATEEN (0x1 << 1)
-+#define LCDC_HCRCHER_A2QEN (0x1 << 2)
-+
-+#define ATMEL_LCDC_HCRCHDR 0x0344
-+#define LCDC_HCRCHDR_CHDIS (0x1 << 0)
-+#define LCDC_HCRCHDR_CHRST (0x1 << 8)
-+
-+#define ATMEL_LCDC_HCRCHSR 0x0348
-+#define LCDC_HCRCHSR_CHSR (0x1 << 0)
-+#define LCDC_HCRCHSR_UPDATESR (0x1 << 1)
-+#define LCDC_HCRCHSR_A2QSR (0x1 << 2)
-+
-+#define ATMEL_LCDC_HCRIER 0x034C
-+#define LCDC_HCRIER_DMA (0x1 << 2)
-+#define LCDC_HCRIER_DSCR (0x1 << 3)
-+#define LCDC_HCRIER_ADD (0x1 << 4)
-+#define LCDC_HCRIER_DONE (0x1 << 5)
-+#define LCDC_HCRIER_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_HCRIDR 0x0350
-+#define LCDC_HCRIDR_DMA (0x1 << 2)
-+#define LCDC_HCRIDR_DSCR (0x1 << 3)
-+#define LCDC_HCRIDR_ADD (0x1 << 4)
-+#define LCDC_HCRIDR_DONE (0x1 << 5)
-+#define LCDC_HCRIDR_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_HCRIMR 0x0354
-+#define LCDC_HCRIMR_DMA (0x1 << 2)
-+#define LCDC_HCRIMR_DSCR (0x1 << 3)
-+#define LCDC_HCRIMR_ADD (0x1 << 4)
-+#define LCDC_HCRIMR_DONE (0x1 << 5)
-+#define LCDC_HCRIMR_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_HCRISR 0x0358
-+#define LCDC_HCRISR_DMA (0x1 << 2)
-+#define LCDC_HCRISR_DSCR (0x1 << 3)
-+#define LCDC_HCRISR_ADD (0x1 << 4)
-+#define LCDC_HCRISR_DONE (0x1 << 5)
-+#define LCDC_HCRISR_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_HCRHEAD 0x035C
-+
-+#define ATMEL_LCDC_HCRADDR 0x0360
-+
-+#define ATMEL_LCDC_HCRCTRL 0x0364
-+#define LCDC_HCRCTRL_DFETCH (0x1 << 0)
-+#define LCDC_HCRCTRL_LFETCH (0x1 << 1)
-+#define LCDC_HCRCTRL_DMAIEN (0x1 << 2)
-+#define LCDC_HCRCTRL_DSCRIEN (0x1 << 3)
-+#define LCDC_HCRCTRL_ADDIEN (0x1 << 4)
-+#define LCDC_HCRCTRL_DONEIEN (0x1 << 5)
-+
-+#define ATMEL_LCDC_HCRNEXT 0x0368
-+
-+#define ATMEL_LCDC_HCRCFG0 0x036C
-+#define LCDC_HCRCFG0_BLEN_OFFSET 4
-+#define LCDC_HCRCFG0_BLEN (0x3 << LCDC_HCRCFG0_BLEN_OFFSET)
-+#define LCDC_HCRCFG0_BLEN_AHB_SINGLE (0x0 << 4)
-+#define LCDC_HCRCFG0_BLEN_AHB_INCR4 (0x1 << 4)
-+#define LCDC_HCRCFG0_BLEN_AHB_INCR8 (0x2 << 4)
-+#define LCDC_HCRCFG0_BLEN_AHB_INCR16 (0x3 << 4)
-+#define LCDC_HCRCFG0_DLBO (0x1 << 8)
-+
-+#define ATMEL_LCDC_HCRCFG1 0x0370
-+#define LCDC_HCRCFG1_CLUTEN (0x1 << 0)
-+#define LCDC_HCRCFG1_RGBMODE_OFFSET 4
-+#define LCDC_HCRCFG1_RGBMODE (0xf << LCDC_HCRCFG1_RGBMODE_OFFSET)
-+#define LCDC_HCRCFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4)
-+#define LCDC_HCRCFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4)
-+#define LCDC_HCRCFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4)
-+#define LCDC_HCRCFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4)
-+#define LCDC_HCRCFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4)
-+#define LCDC_HCRCFG1_CLUTMODE_OFFSET 8
-+#define LCDC_HCRCFG1_CLUTMODE (0x3 << LCDC_HCRCFG1_CLUTMODE_OFFSET)
-+#define LCDC_HCRCFG1_CLUTMODE_1BPP (0x0 << 8)
-+#define LCDC_HCRCFG1_CLUTMODE_2BPP (0x1 << 8)
-+#define LCDC_HCRCFG1_CLUTMODE_4BPP (0x2 << 8)
-+#define LCDC_HCRCFG1_CLUTMODE_8BPP (0x3 << 8)
-+
-+#define ATMEL_LCDC_HCRCFG2 0x0374
-+#define LCDC_HCRCFG2_XOFFSET_OFFSET 0
-+#define LCDC_HCRCFG2_XOFFSET (0x7ff << LCDC_HCRCFG2_XOFFSET_OFFSET)
-+#define LCDC_HCRCFG2_YOFFSET_OFFSET 16
-+#define LCDC_HCRCFG2_YOFFSET (0x7ff << LCDC_HCRCFG2_YOFFSET_OFFSET)
-+
-+#define ATMEL_LCDC_HCRCFG3 0x0378
-+#define LCDC_HCRCFG3_XSIZE_OFFSET 0
-+#define LCDC_HCRCFG3_XSIZE (0x7f << LCDC_HCRCFG3_XSIZE_OFFSET)
-+#define LCDC_HCRCFG3_YSIZE_OFFSET 16
-+#define LCDC_HCRCFG3_YSIZE (0x7f << LCDC_HCRCFG3_YSIZE_OFFSET)
-+
-+#define ATMEL_LCDC_HCRCFG4 0x037C
-+
-+#define ATMEL_LCDC_HCRCFG6 0x0384
-+#define LCDC_HCRCFG6_BDEF_OFFSET 0
-+#define LCDC_HCRCFG6_BDEF (0xff << LCDC_HCRCFG6_BDEF_OFFSET)
-+#define LCDC_HCRCFG6_GDEF_OFFSET 8
-+#define LCDC_HCRCFG6_GDEF (0xff << LCDC_HCRCFG6_GDEF_OFFSET)
-+#define LCDC_HCRCFG6_RDEF_OFFSET 16
-+#define LCDC_HCRCFG6_RDEF (0xff << LCDC_HCRCFG6_RDEF_OFFSET)
-+
-+#define ATMEL_LCDC_HCRCFG7 0x0388
-+#define LCDC_HCRCFG7_BKEY_OFFSET 0
-+#define LCDC_HCRCFG7_BKEY (0xff << LCDC_HCRCFG7_BKEY_OFFSET)
-+#define LCDC_HCRCFG7_GKEY_OFFSET 8
-+#define LCDC_HCRCFG7_GKEY (0xff << LCDC_HCRCFG7_GKEY_OFFSET)
-+#define LCDC_HCRCFG7_RKEY_OFFSET 16
-+#define LCDC_HCRCFG7_RKEY (0xff << LCDC_HCRCFG7_RKEY_OFFSET)
-+
-+#define ATMEL_LCDC_HCRCFG8 0x038C
-+#define LCDC_HCRCFG8_BMASK_OFFSET 0
-+#define LCDC_HCRCFG8_BMASK (0xff << LCDC_HCRCFG8_BMASK_OFFSET)
-+#define LCDC_HCRCFG8_GMASK_OFFSET 8
-+#define LCDC_HCRCFG8_GMASK (0xff << LCDC_HCRCFG8_GMASK_OFFSET)
-+#define LCDC_HCRCFG8_RMASK_OFFSET 16
-+#define LCDC_HCRCFG8_RMASK (0xff << LCDC_HCRCFG8_RMASK_OFFSET)
-+
-+#define ATMEL_LCDC_HCRCFG9 0x0390
-+#define LCDC_HCRCFG9_CRKEY (0x1 << 0)
-+#define LCDC_HCRCFG9_INV (0x1 << 1)
-+#define LCDC_HCRCFG9_ITER2BL (0x1 << 2)
-+#define LCDC_HCRCFG9_ITER (0x1 << 3)
-+#define LCDC_HCRCFG9_REVALPHA (0x1 << 4)
-+#define LCDC_HCRCFG9_GAEN (0x1 << 5)
-+#define LCDC_HCRCFG9_LAEN (0x1 << 6)
-+#define LCDC_HCRCFG9_OVR (0x1 << 7)
-+#define LCDC_HCRCFG9_DMA (0x1 << 8)
-+#define LCDC_HCRCFG9_REP (0x1 << 9)
-+#define LCDC_HCRCFG9_DSTKEY (0x1 << 10)
-+#define LCDC_HCRCFG9_GA_OFFSET 16
-+#define LCDC_HCRCFG9_GA_Msk (0xff << LCDC_HCRCFG9_GA_OFFSET)
-+
-+#define ATMEL_LCDC_BASECLUT 0x400
-+#define LCDC_BASECLUT_BCLUT_OFFSET 0
-+#define LCDC_BASECLUT_BCLUT (0xff << LCDC_BASECLUT_BCLUT_OFFSET)
-+#define LCDC_BASECLUT_GCLUT_OFFSET 8
-+#define LCDC_BASECLUT_GCLUT (0xff << LCDC_BASECLUT_GCLUT_OFFSET)
-+#define LCDC_BASECLUT_RCLUT_OFFSET 16
-+#define LCDC_BASECLUT_RCLUT (0xff << LCDC_BASECLUT_RCLUT_OFFSET)
-+
-+#define ATMEL_LCDC_OVR1CLUT 0x800
-+#define LCDC_OVR1CLUT_BCLUT_OFFSET 0
-+#define LCDC_OVR1CLUT_BCLUT (0xff << LCDC_OVR1CLUT_BCLUT_OFFSET)
-+#define LCDC_OVR1CLUT_GCLUT_OFFSET 8
-+#define LCDC_OVR1CLUT_GCLUT (0xff << LCDC_OVR1CLUT_GCLUT_OFFSET)
-+#define LCDC_OVR1CLUT_RCLUT_OFFSET 16
-+#define LCDC_OVR1CLUT_RCLUT (0xff << LCDC_OVR1CLUT_RCLUT_OFFSET)
-+#define LCDC_OVR1CLUT_ACLUT_OFFSET 24
-+#define LCDC_OVR1CLUT_ACLUT (0xff << LCDC_OVR1CLUT_ACLUT_OFFSET)
-+
-+#define ATMEL_LCDC_HEOCLUT 0x1000
-+#define LCDC_HEOCLUT_BCLUT_OFFSET 0
-+#define LCDC_HEOCLUT_BCLUT (0xff << LCDC_HEOCLUT_BCLUT_OFFSET)
-+#define LCDC_HEOCLUT_GCLUT_OFFSET 8
-+#define LCDC_HEOCLUT_GCLUT (0xff << LCDC_HEOCLUT_GCLUT_OFFSET)
-+#define LCDC_HEOCLUT_RCLUT_OFFSET 16
-+#define LCDC_HEOCLUT_RCLUT (0xff << LCDC_HEOCLUT_RCLUT_OFFSET)
-+#define LCDC_HEOCLUT_ACLUT_OFFSET 24
-+#define LCDC_HEOCLUT_ACLUT (0xff << LCDC_HEOCLUT_ACLUT_OFFSET)
-+
-+#define ATMEL_LCDC_HCRCLUT 0x1400
-+#define LCDC_HCRCLUT_BCLUT_OFFSET 0
-+#define LCDC_HCRCLUT_BCLUT (0xff << LCDC_HCRCLUT_BCLUT_OFFSET)
-+#define LCDC_HCRCLUT_GCLUT_OFFSET 8
-+#define LCDC_HCRCLUT_GCLUT (0xff << LCDC_HCRCLUT_GCLUT_OFFSET)
-+#define LCDC_HCRCLUT_RCLUT_OFFSET 16
-+#define LCDC_HCRCLUT_RCLUT (0xff << LCDC_HCRCLUT_RCLUT_OFFSET)
-+#define LCDC_HCRCLUT_ACLUT_OFFSET 24
-+#define LCDC_HCRCLUT_ACLUT (0xff << LCDC_HCRCLUT_ACLUT_OFFSET)
-+
-+/* Base layer CLUT */
-+#define ATMEL_HLCDC_LUT 0x0400
-+
-+
-+#endif /* __MACH_ATMEL_HLCDC4_H__ */
---- /dev/null
-+++ b/arch/arm/mach-at91/include/mach/atmel_hlcdc_ovl.h
-@@ -0,0 +1,156 @@
-+#ifndef __MACH_ATMEL_HLCD_OVL_H__
-+#define __MACH_ATMEL_HLCD_OVL_H__
-+
-+/*
-+ * OVL has a seperate resource which already starts at offset 0x100.
-+ * So, these defines start at 0x0. The manual will list them at 0x100.
-+ */
-+
-+#define ATMEL_LCDC_OVRCHER1 0x0000
-+#define LCDC_OVRCHER1_CHEN (0x1 << 0)
-+#define LCDC_OVRCHER1_UPDATEEN (0x1 << 1)
-+#define LCDC_OVRCHER1_A2QEN (0x1 << 2)
-+
-+#define ATMEL_LCDC_OVRCHDR1 0x0004
-+#define LCDC_OVRCHDR1_CHDIS (0x1 << 0)
-+#define LCDC_OVRCHDR1_CHRST (0x1 << 8)
-+
-+#define ATMEL_LCDC_OVRCHSR1 0x0008
-+#define LCDC_OVRCHSR1_CHSR (0x1 << 0)
-+#define LCDC_OVRCHSR1_UPDATESR (0x1 << 1)
-+#define LCDC_OVRCHSR1_A2QSR (0x1 << 2)
-+
-+#define ATMEL_LCDC_OVRIER1 0x000C
-+#define LCDC_OVRIER1_DMA (0x1 << 2)
-+#define LCDC_OVRIER1_DSCR (0x1 << 3)
-+#define LCDC_OVRIER1_ADD (0x1 << 4)
-+#define LCDC_OVRIER1_DONE (0x1 << 5)
-+#define LCDC_OVRIER1_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_OVRIDR1 0x0010
-+#define LCDC_OVRIDR1_DMA (0x1 << 2)
-+#define LCDC_OVRIDR1_DSCR (0x1 << 3)
-+#define LCDC_OVRIDR1_ADD (0x1 << 4)
-+#define LCDC_OVRIDR1_DONE (0x1 << 5)
-+#define LCDC_OVRIDR1_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_OVRIMR1 0x0014
-+#define LCDC_OVRIMR1_DMA (0x1 << 2)
-+#define LCDC_OVRIMR1_DSCR (0x1 << 3)
-+#define LCDC_OVRIMR1_ADD (0x1 << 4)
-+#define LCDC_OVRIMR1_DONE (0x1 << 5)
-+#define LCDC_OVRIMR1_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_OVRISR1 0x0018
-+#define LCDC_OVRISR1_DMA (0x1 << 2)
-+#define LCDC_OVRISR1_DSCR (0x1 << 3)
-+#define LCDC_OVRISR1_ADD (0x1 << 4)
-+#define LCDC_OVRISR1_DONE (0x1 << 5)
-+#define LCDC_OVRISR1_OVR (0x1 << 6)
-+
-+#define ATMEL_LCDC_OVRHEAD1 0x001C
-+
-+#define ATMEL_LCDC_OVRADDR1 0x0020
-+
-+#define ATMEL_LCDC_OVRCTRL1 0x0024
-+#define LCDC_OVRCTRL1_DFETCH (0x1 << 0)
-+#define LCDC_OVRCTRL1_LFETCH (0x1 << 1)
-+#define LCDC_OVRCTRL1_DMAIEN (0x1 << 2)
-+#define LCDC_OVRCTRL1_DSCRIEN (0x1 << 3)
-+#define LCDC_OVRCTRL1_ADDIEN (0x1 << 4)
-+#define LCDC_OVRCTRL1_DONEIEN (0x1 << 5)
-+
-+#define ATMEL_LCDC_OVRNEXT1 0x0028
-+
-+#define ATMEL_LCDC_OVR1CFG0 0x002C
-+#define LCDC_OVR1CFG0_BLEN_OFFSET 4
-+#define LCDC_OVR1CFG0_BLEN (0x3 << LCDC_OVR1CFG0_BLEN_OFFSET)
-+#define LCDC_OVR1CFG0_BLEN_AHB_SINGLE (0x0 << 4)
-+#define LCDC_OVR1CFG0_BLEN_AHB_INCR4 (0x1 << 4)
-+#define LCDC_OVR1CFG0_BLEN_AHB_INCR8 (0x2 << 4)
-+#define LCDC_OVR1CFG0_BLEN_AHB_INCR16 (0x3 << 4)
-+#define LCDC_OVR1CFG0_DLBO (0x1 << 8)
-+#define LCDC_OVR1CFG0_ROTDIS (0x1 << 12)
-+#define LCDC_OVR1CFG0_LOCKDIS (0x1 << 13)
-+
-+#define ATMEL_LCDC_OVR1CFG1 0x0030
-+#define LCDC_OVR1CFG1_CLUTEN (0x1 << 0)
-+#define LCDC_OVR1CFG1_RGBMODE_OFFSET 4
-+#define LCDC_OVR1CFG1_RGBMODE (0xf << LCDC_OVR1CFG1_RGBMODE_OFFSET)
-+#define LCDC_OVR1CFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4)
-+#define LCDC_OVR1CFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4)
-+#define LCDC_OVR1CFG1_CLUTMODE_OFFSET 8
-+#define LCDC_OVR1CFG1_CLUTMODE (0x3 << LCDC_OVR1CFG1_CLUTMODE_OFFSET)
-+#define LCDC_OVR1CFG1_CLUTMODE_1BPP (0x0 << 8)
-+#define LCDC_OVR1CFG1_CLUTMODE_2BPP (0x1 << 8)
-+#define LCDC_OVR1CFG1_CLUTMODE_4BPP (0x2 << 8)
-+#define LCDC_OVR1CFG1_CLUTMODE_8BPP (0x3 << 8)
-+
-+#define ATMEL_LCDC_OVR1CFG2 0x0034
-+#define LCDC_OVR1CFG2_XOFFSET_OFFSET 0
-+#define LCDC_OVR1CFG2_XOFFSET (0x7ff << LCDC_OVR1CFG2_XOFFSET_OFFSET)
-+#define LCDC_OVR1CFG2_YOFFSET_OFFSET 16
-+#define LCDC_OVR1CFG2_YOFFSET (0x7ff << LCDC_OVR1CFG2_YOFFSET_OFFSET)
-+
-+#define ATMEL_LCDC_OVR1CFG3 0x0038
-+#define LCDC_OVR1CFG3_XSIZE_OFFSET 0
-+#define LCDC_OVR1CFG3_XSIZE (0x7ff << LCDC_OVR1CFG3_XSIZE_OFFSET)
-+#define LCDC_OVR1CFG3_YSIZE_OFFSET 16
-+#define LCDC_OVR1CFG3_YSIZE (0x7ff << LCDC_OVR1CFG3_YSIZE_OFFSET)
-+
-+#define ATMEL_LCDC_OVR1CFG4 0x003C
-+
-+#define ATMEL_LCDC_OVR1CFG5 0x0040
-+
-+#define ATMEL_LCDC_OVR1CFG6 0x0044
-+#define LCDC_OVR1CFG6_BDEF_OFFSET 0
-+#define LCDC_OVR1CFG6_BDEF (0xff << LCDC_OVR1CFG6_BDEF_OFFSET)
-+#define LCDC_OVR1CFG6_GDEF_OFFSET 8
-+#define LCDC_OVR1CFG6_GDEF (0xff << LCDC_OVR1CFG6_GDEF_OFFSET)
-+#define LCDC_OVR1CFG6_RDEF_OFFSET 16
-+#define LCDC_OVR1CFG6_RDEF (0xff << LCDC_OVR1CFG6_RDEF_OFFSET)
-+
-+#define ATMEL_LCDC_OVR1CFG7 0x0048
-+#define LCDC_OVR1CFG7_BKEY_OFFSET 0
-+#define LCDC_OVR1CFG7_BKEY (0xff << LCDC_OVR1CFG7_BKEY_OFFSET)
-+#define LCDC_OVR1CFG7_GKEY_OFFSET 8
-+#define LCDC_OVR1CFG7_GKEY (0xff << LCDC_OVR1CFG7_GKEY_OFFST)
-+#define LCDC_OVR1CFG7_RKEY_OFFSET 16
-+#define LCDC_OVR1CFG7_RKEY (0xff << LCDC_OVR1CFG7_RKEY_OFFSET)
-+
-+#define ATMEL_LCDC_OVR1CFG8 0x004C
-+#define LCDC_OVR1CFG8_BMASK_OFFSET 0
-+#define LCDC_OVR1CFG8_BMASK (0xff << LCDC_OVR1CFG8_BMASK_OFFSET)
-+#define LCDC_OVR1CFG8_GMASK_OFFSET 8
-+#define LCDC_OVR1CFG8_GMASK (0xff << LCDC_OVR1CFG8_GMASK_OFFSET)
-+#define LCDC_OVR1CFG8_RMASK_OFFSET 16
-+#define LCDC_OVR1CFG8_RMASK (0xff << LCDC_OVR1CFG8_RMASK_OFFSET)
-+
-+#define ATMEL_LCDC_OVR1CFG9 0x0050
-+#define LCDC_OVR1CFG9_CRKEY (0x1 << 0)
-+#define LCDC_OVR1CFG9_INV (0x1 << 1)
-+#define LCDC_OVR1CFG9_ITER2BL (0x1 << 2)
-+#define LCDC_OVR1CFG9_ITER (0x1 << 3)
-+#define LCDC_OVR1CFG9_REVALPHA (0x1 << 4)
-+#define LCDC_OVR1CFG9_GAEN (0x1 << 5)
-+#define LCDC_OVR1CFG9_LAEN (0x1 << 6)
-+#define LCDC_OVR1CFG9_OVR (0x1 << 7)
-+#define LCDC_OVR1CFG9_DMA (0x1 << 8)
-+#define LCDC_OVR1CFG9_REP (0x1 << 9)
-+#define LCDC_OVR1CFG9_DSTKEY (0x1 << 10)
-+#define LCDC_OVR1CFG9_GA_OFFSET 16
-+#define LCDC_OVR1CFG9_GA (0xff << LCDC_OVR1CFG9_GA_OFFSET)
-+
-+#endif /* __MACH_ATMEL_HLCD_OVL_H__ */
---- a/arch/arm/mach-at91/include/mach/atmel_hlcdfb.h
-+++ /dev/null
-@@ -1,865 +0,0 @@
--/*
-- * Header file for AT91 High end LCD Controller
-- *
-- * Data structure and register user interface
-- *
-- * Copyright (C) 2010 Atmel Corporation
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PUROFFSETE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-- */
--#ifndef __ATMEL_HLCD_H__
--#define __ATMEL_HLCD_H__
--
--/* Lcdc hardware registers */
--#define ATMEL_LCDC_LCDCFG0 0x0000
--#define LCDC_LCDCFG0_CLKPOL (0x1 << 0)
--#define LCDC_LCDCFG0_CLKSEL (0x1 << 2)
--#define LCDC_LCDCFG0_CLKPWMSEL (0x1 << 3)
--#define LCDC_LCDCFG0_CGDISBASE (0x1 << 8)
--#define LCDC_LCDCFG0_CGDISOVR1 (0x1 << 9)
--#define LCDC_LCDCFG0_CGDISHEO (0x1 << 11)
--#define LCDC_LCDCFG0_CGDISHCR (0x1 << 12)
--#define LCDC_LCDCFG0_CLKDIV_OFFSET 16
--#define LCDC_LCDCFG0_CLKDIV (0xff << LCDC_LCDCFG0_CLKDIV_OFFSET)
--
--#define ATMEL_LCDC_LCDCFG1 0x0004
--#define LCDC_LCDCFG1_HSPW_OFFSET 0
--#define LCDC_LCDCFG1_HSPW (0x3f << LCDC_LCDCFG1_HSPW_OFFSET)
--#define LCDC_LCDCFG1_VSPW_OFFSET 16
--#define LCDC_LCDCFG1_VSPW (0x3f << LCDC_LCDCFG1_VSPW_OFFSET)
--
--#define ATMEL_LCDC_LCDCFG2 0x0008
--#define LCDC_LCDCFG2_VFPW_OFFSET 0
--#define LCDC_LCDCFG2_VFPW (0x3f << LCDC_LCDCFG2_VFPW_OFFSET)
--#define LCDC_LCDCFG2_VBPW_OFFSET 16
--#define LCDC_LCDCFG2_VBPW (0x3f << LCDC_LCDCFG2_VBPW_OFFSET)
--
--#define ATMEL_LCDC_LCDCFG3 0x000C
--#define LCDC_LCDCFG3_HFPW_OFFSET 0
--#define LCDC_LCDCFG3_HFPW (0xff << LCDC_LCDCFG3_HFPW_OFFSET)
--#define LCDC_LCDCFG3_HBPW_OFFSET 16
--#define LCDC_LCDCFG3_HBPW (0xff << LCDC_LCDCFG3_HBPW_OFFSET)
--
--#define ATMEL_LCDC_LCDCFG4 0x0010
--#define LCDC_LCDCFG4_PPL_OFFSET 0
--#define LCDC_LCDCFG4_PPL (0x7ff << LCDC_LCDCFG4_PPL_OFFSET)
--#define LCDC_LCDCFG4_RPF_OFFSET 16
--#define LCDC_LCDCFG4_RPF (0x7ff << LCDC_LCDCFG4_RPF_OFFSET)
--
--#define ATMEL_LCDC_LCDCFG5 0x0014
--#define LCDC_LCDCFG5_HSPOL (0x1 << 0)
--#define LCDC_LCDCFG5_VSPOL (0x1 << 1)
--#define LCDC_LCDCFG5_VSPDLYS (0x1 << 2)
--#define LCDC_LCDCFG5_VSPDLYE (0x1 << 3)
--#define LCDC_LCDCFG5_DISPPOL (0x1 << 4)
--#define LCDC_LCDCFG5_SERIAL (0x1 << 5)
--#define LCDC_LCDCFG5_DITHER (0x1 << 6)
--#define LCDC_LCDCFG5_DISPDLY (0x1 << 7)
--#define LCDC_LCDCFG5_MODE_OFFSET 8
--#define LCDC_LCDCFG5_MODE (0x3 << LCDC_LCDCFG5_MODE_OFFSET)
--#define LCDC_LCDCFG5_MODE_OUTPUT_12BPP (0x0 << 8)
--#define LCDC_LCDCFG5_MODE_OUTPUT_16BPP (0x1 << 8)
--#define LCDC_LCDCFG5_MODE_OUTPUT_18BPP (0x2 << 8)
--#define LCDC_LCDCFG5_MODE_OUTPUT_24BPP (0x3 << 8)
--#define LCDC_LCDCFG5_VSPSU (0x1 << 12)
--#define LCDC_LCDCFG5_VSPHO (0x1 << 13)
--#define LCDC_LCDCFG5_GUARDTIME_OFFSET 16
--#define LCDC_LCDCFG5_GUARDTIME (0x1f << LCDC_LCDCFG5_GUARDTIME_OFFSET)
--
--#define ATMEL_LCDC_LCDCFG6 0x0018
--#define LCDC_LCDCFG6_PWMPS_OFFSET 0
--#define LCDC_LCDCFG6_PWMPS (0x7 << LCDC_LCDCFG6_PWMPS_OFFSET)
--#define LCDC_LCDCFG6_PWMPOL (0x1 << 4)
--#define LCDC_LCDCFG6_PWMCVAL_OFFSET 8
--#define LCDC_LCDCFG6_PWMCVAL (0xff << LCDC_LCDCFG6_PWMCVAL_OFFSET)
--
--#define ATMEL_LCDC_LCDEN 0x0020
--#define LCDC_LCDEN_CLKEN (0x1 << 0)
--#define LCDC_LCDEN_SYNCEN (0x1 << 1)
--#define LCDC_LCDEN_DISPEN (0x1 << 2)
--#define LCDC_LCDEN_PWMEN (0x1 << 3)
--
--#define ATMEL_LCDC_LCDDIS 0x0024
--#define LCDC_LCDDIS_CLKDIS (0x1 << 0)
--#define LCDC_LCDDIS_SYNCDIS (0x1 << 1)
--#define LCDC_LCDDIS_DISPDIS (0x1 << 2)
--#define LCDC_LCDDIS_PWMDIS (0x1 << 3)
--#define LCDC_LCDDIS_CLKRST (0x1 << 8)
--#define LCDC_LCDDIS_SYNCRST (0x1 << 9)
--#define LCDC_LCDDIS_DISPRST (0x1 << 10)
--#define LCDC_LCDDIS_PWMRST (0x1 << 11)
--
--#define ATMEL_LCDC_LCDSR 0x0028
--#define LCDC_LCDSR_CLKSTS (0x1 << 0)
--#define LCDC_LCDSR_LCDSTS (0x1 << 1)
--#define LCDC_LCDSR_DISPSTS (0x1 << 2)
--#define LCDC_LCDSR_PWMSTS (0x1 << 3)
--#define LCDC_LCDSR_SIPSTS (0x1 << 4)
--
--#define ATMEL_LCDC_LCDIER 0x002C
--#define LCDC_LCDIER_SOFIE (0x1 << 0)
--#define LCDC_LCDIER_DISIE (0x1 << 1)
--#define LCDC_LCDIER_DISPIE (0x1 << 2)
--#define LCDC_LCDIER_FIFOERRIE (0x1 << 4)
--#define LCDC_LCDIER_BASEIE (0x1 << 8)
--#define LCDC_LCDIER_OVR1IE (0x1 << 9)
--#define LCDC_LCDIER_HEOIE (0x1 << 11)
--#define LCDC_LCDIER_HCRIE (0x1 << 12)
--
--#define ATMEL_LCDC_LCDIDR 0x0030
--#define LCDC_LCDIDR_SOFID (0x1 << 0)
--#define LCDC_LCDIDR_DISID (0x1 << 1)
--#define LCDC_LCDIDR_DISPID (0x1 << 2)
--#define LCDC_LCDIDR_FIFOERRID (0x1 << 4)
--#define LCDC_LCDIDR_BASEID (0x1 << 8)
--#define LCDC_LCDIDR_OVR1ID (0x1 << 9)
--#define LCDC_LCDIDR_HEOID (0x1 << 11)
--#define LCDC_LCDIDR_HCRID (0x1 << 12)
--
--#define ATMEL_LCDC_LCDIMR 0x0034
--#define LCDC_LCDIMR_SOFIM (0x1 << 0)
--#define LCDC_LCDIMR_DISIM (0x1 << 1)
--#define LCDC_LCDIMR_DISPIM (0x1 << 2)
--#define LCDC_LCDIMR_FIFOERRIM (0x1 << 4)
--#define LCDC_LCDIMR_BASEIM (0x1 << 8)
--#define LCDC_LCDIMR_OVR1IM (0x1 << 9)
--#define LCDC_LCDIMR_HEOIM (0x1 << 11)
--#define LCDC_LCDIMR_HCRIM (0x1 << 12)
--
--#define ATMEL_LCDC_LCDISR 0x0038
--#define LCDC_LCDISR_SOF (0x1 << 0)
--#define LCDC_LCDISR_DIS (0x1 << 1)
--#define LCDC_LCDISR_DISP (0x1 << 2)
--#define LCDC_LCDISR_FIFOERR (0x1 << 4)
--#define LCDC_LCDISR_BASE (0x1 << 8)
--#define LCDC_LCDISR_OVR1 (0x1 << 9)
--#define LCDC_LCDISR_HEO (0x1 << 11)
--#define LCDC_LCDISR_HCR (0x1 << 12)
--
--#define ATMEL_LCDC_BASECHER 0x0040
--#define LCDC_BASECHER_CHEN (0x1 << 0)
--#define LCDC_BASECHER_UPDATEEN (0x1 << 1)
--#define LCDC_BASECHER_A2QEN (0x1 << 2)
--
--#define ATMEL_LCDC_BASECHDR 0x0044
--#define LCDC_BASECHDR_CHDIS (0x1 << 0)
--#define LCDC_BASECHDR_CHRST (0x1 << 8)
--
--#define ATMEL_LCDC_BASECHSR 0x0048
--#define LCDC_BASECHSR_CHSR (0x1 << 0)
--#define LCDC_BASECHSR_UPDATESR (0x1 << 1)
--#define LCDC_BASECHSR_A2QSR (0x1 << 2)
--
--#define ATMEL_LCDC_BASEIER 0x004C
--#define LCDC_BASEIER_DMA (0x1 << 2)
--#define LCDC_BASEIER_DSCR (0x1 << 3)
--#define LCDC_BASEIER_ADD (0x1 << 4)
--#define LCDC_BASEIER_DONE (0x1 << 5)
--#define LCDC_BASEIER_OVR (0x1 << 6)
--
--#define ATMEL_LCDC_BASEIDR 0x0050
--#define LCDC_BASEIDR_DMA (0x1 << 2)
--#define LCDC_BASEIDR_DSCR (0x1 << 3)
--#define LCDC_BASEIDR_ADD (0x1 << 4)
--#define LCDC_BASEIDR_DONE (0x1 << 5)
--#define LCDC_BASEIDR_OVR (0x1 << 6)
--
--#define ATMEL_LCDC_BASEIMR 0x0054
--#define LCDC_BASEIMR_DMA (0x1 << 2)
--#define LCDC_BASEIMR_DSCR (0x1 << 3)
--#define LCDC_BASEIMR_ADD (0x1 << 4)
--#define LCDC_BASEIMR_DONE (0x1 << 5)
--#define LCDC_BASEIMR_OVR (0x1 << 6)
--
--#define ATMEL_LCDC_BASEISR 0x0058
--#define LCDC_BASEISR_DMA (0x1 << 2)
--#define LCDC_BASEISR_DSCR (0x1 << 3)
--#define LCDC_BASEISR_ADD (0x1 << 4)
--#define LCDC_BASEISR_DONE (0x1 << 5)
--#define LCDC_BASEISR_OVR (0x1 << 6)
--
--#define ATMEL_LCDC_BASEHEAD 0x005C
--
--#define ATMEL_LCDC_BASEADDR 0x0060
--
--#define ATMEL_LCDC_BASECTRL 0x0064
--#define LCDC_BASECTRL_DFETCH (0x1 << 0)
--#define LCDC_BASECTRL_LFETCH (0x1 << 1)
--#define LCDC_BASECTRL_DMAIEN (0x1 << 2)
--#define LCDC_BASECTRL_DSCRIEN (0x1 << 3)
--#define LCDC_BASECTRL_ADDIEN (0x1 << 4)
--#define LCDC_BASECTRL_DONEIEN (0x1 << 5)
--
--#define ATMEL_LCDC_BASENEXT 0x0068
--
--#define ATMEL_LCDC_BASECFG0 0x006C
--#define LCDC_BASECFG0_BLEN_OFFSET 4
--#define LCDC_BASECFG0_BLEN (0x3 << LCDC_BASECFG0_BLEN_OFFSET)
--#define LCDC_BASECFG0_BLEN_AHB_SINGLE (0x0 << 4)
--#define LCDC_BASECFG0_BLEN_AHB_INCR4 (0x1 << 4)
--#define LCDC_BASECFG0_BLEN_AHB_INCR8 (0x2 << 4)
--#define LCDC_BASECFG0_BLEN_AHB_INCR16 (0x3 << 4)
--#define LCDC_BASECFG0_DLBO (0x1 << 8)
--
--#define ATMEL_LCDC_BASECFG1 0x0070
--#define LCDC_BASECFG1_CLUTEN (0x1 << 0)
--#define LCDC_BASECFG1_RGBMODE_OFFSET 4
--#define LCDC_BASECFG1_RGBMODE (0xf << LCDC_BASECFG1_RGBMODE_OFFSET)
--#define LCDC_BASECFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4)
--#define LCDC_BASECFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4)
--#define LCDC_BASECFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4)
--#define LCDC_BASECFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4)
--#define LCDC_BASECFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4)
--#define LCDC_BASECFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4)
--#define LCDC_BASECFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4)
--#define LCDC_BASECFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4)
--#define LCDC_BASECFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4)
--#define LCDC_BASECFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4)
--#define LCDC_BASECFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4)
--#define LCDC_BASECFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4)
--#define LCDC_BASECFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4)
--#define LCDC_BASECFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4)
--#define LCDC_BASECFG1_CLUTMODE_OFFSET 8
--#define LCDC_BASECFG1_CLUTMODE (0x3 << LCDC_BASECFG1_CLUTMODE_OFFSET)
--#define LCDC_BASECFG1_CLUTMODE_1BPP (0x0 << 8)
--#define LCDC_BASECFG1_CLUTMODE_2BPP (0x1 << 8)
--#define LCDC_BASECFG1_CLUTMODE_4BPP (0x2 << 8)
--#define LCDC_BASECFG1_CLUTMODE_8BPP (0x3 << 8)
--
--#define ATMEL_LCDC_BASECFG2 0x0074
--
--#define ATMEL_LCDC_BASECFG3 0x0078
--#define LCDC_BASECFG3_BDEF_OFFSET 0
--#define LCDC_BASECFG3_BDEF (0xff << LCDC_BASECFG3_BDEF_OFFSET)
--#define LCDC_BASECFG3_GDEF_OFFSET 8
--#define LCDC_BASECFG3_GDEF (0xff << LCDC_BASECFG3_GDEF_OFFSET)
--#define LCDC_BASECFG3_RDEF_OFFSET 16
--#define LCDC_BASECFG3_RDEF (0xff << LCDC_BASECFG3_RDEF_OFFSET)
--
--#define ATMEL_LCDC_BASECFG4 0x007C
--#define LCDC_BASECFG4_DMA (0x1 << 8)
--#define LCDC_BASECFG4_REP (0x1 << 9)
--
--#define ATMEL_LCDC_OVRCHER1 0x0100
--#define LCDC_OVRCHER1_CHEN (0x1 << 0)
--#define LCDC_OVRCHER1_UPDATEEN (0x1 << 1)
--#define LCDC_OVRCHER1_A2QEN (0x1 << 2)
--
--#define ATMEL_LCDC_OVRCHDR1 0x0104
--#define LCDC_OVRCHDR1_CHDIS (0x1 << 0)
--#define LCDC_OVRCHDR1_CHRST (0x1 << 8)
--
--#define ATMEL_LCDC_OVRCHSR1 0x0108
--#define LCDC_OVRCHSR1_CHSR (0x1 << 0)
--#define LCDC_OVRCHSR1_UPDATESR (0x1 << 1)
--#define LCDC_OVRCHSR1_A2QSR (0x1 << 2)
--
--#define ATMEL_LCDC_OVRIER1 0x010C
--#define LCDC_OVRIER1_DMA (0x1 << 2)
--#define LCDC_OVRIER1_DSCR (0x1 << 3)
--#define LCDC_OVRIER1_ADD (0x1 << 4)
--#define LCDC_OVRIER1_DONE (0x1 << 5)
--#define LCDC_OVRIER1_OVR (0x1 << 6)
--
--#define ATMEL_LCDC_OVRIDR1 0x0110
--#define LCDC_OVRIDR1_DMA (0x1 << 2)
--#define LCDC_OVRIDR1_DSCR (0x1 << 3)
--#define LCDC_OVRIDR1_ADD (0x1 << 4)
--#define LCDC_OVRIDR1_DONE (0x1 << 5)
--#define LCDC_OVRIDR1_OVR (0x1 << 6)
--
--#define ATMEL_LCDC_OVRIMR1 0x0114
--#define LCDC_OVRIMR1_DMA (0x1 << 2)
--#define LCDC_OVRIMR1_DSCR (0x1 << 3)
--#define LCDC_OVRIMR1_ADD (0x1 << 4)
--#define LCDC_OVRIMR1_DONE (0x1 << 5)
--#define LCDC_OVRIMR1_OVR (0x1 << 6)
--
--#define ATMEL_LCDC_OVRISR1 0x0118
--#define LCDC_OVRISR1_DMA (0x1 << 2)
--#define LCDC_OVRISR1_DSCR (0x1 << 3)
--#define LCDC_OVRISR1_ADD (0x1 << 4)
--#define LCDC_OVRISR1_DONE (0x1 << 5)
--#define LCDC_OVRISR1_OVR (0x1 << 6)
--
--#define ATMEL_LCDC_OVRHEAD1 0x011C
--
--#define ATMEL_LCDC_OVRADDR1 0x0120
--
--#define ATMEL_LCDC_OVRCTRL1 0x0124
--#define LCDC_OVRCTRL1_DFETCH (0x1 << 0)
--#define LCDC_OVRCTRL1_LFETCH (0x1 << 1)
--#define LCDC_OVRCTRL1_DMAIEN (0x1 << 2)
--#define LCDC_OVRCTRL1_DSCRIEN (0x1 << 3)
--#define LCDC_OVRCTRL1_ADDIEN (0x1 << 4)
--#define LCDC_OVRCTRL1_DONEIEN (0x1 << 5)
--
--#define ATMEL_LCDC_OVRNEXT1 0x0128
--
--#define ATMEL_LCDC_OVR1CFG0 0x012C
--#define LCDC_OVR1CFG0_BLEN_OFFSET 4
--#define LCDC_OVR1CFG0_BLEN (0x3 << LCDC_OVR1CFG0_BLEN_OFFSET)
--#define LCDC_OVR1CFG0_BLEN_AHB_SINGLE (0x0 << 4)
--#define LCDC_OVR1CFG0_BLEN_AHB_INCR4 (0x1 << 4)
--#define LCDC_OVR1CFG0_BLEN_AHB_INCR8 (0x2 << 4)
--#define LCDC_OVR1CFG0_BLEN_AHB_INCR16 (0x3 << 4)
--#define LCDC_OVR1CFG0_DLBO (0x1 << 8)
--#define LCDC_OVR1CFG0_ROTDIS (0x1 << 12)
--#define LCDC_OVR1CFG0_LOCKDIS (0x1 << 13)
--
--#define ATMEL_LCDC_OVR1CFG1 0x0130
--#define LCDC_OVR1CFG1_CLUTEN (0x1 << 0)
--#define LCDC_OVR1CFG1_RGBMODE_OFFSET 4
--#define LCDC_OVR1CFG1_RGBMODE (0xf << LCDC_OVR1CFG1_RGBMODE_OFFSET)
--#define LCDC_OVR1CFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4)
--#define LCDC_OVR1CFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4)
--#define LCDC_OVR1CFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4)
--#define LCDC_OVR1CFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4)
--#define LCDC_OVR1CFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4)
--#define LCDC_OVR1CFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4)
--#define LCDC_OVR1CFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4)
--#define LCDC_OVR1CFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4)
--#define LCDC_OVR1CFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4)
--#define LCDC_OVR1CFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4)
--#define LCDC_OVR1CFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4)
--#define LCDC_OVR1CFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4)
--#define LCDC_OVR1CFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4)
--#define LCDC_OVR1CFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4)
--#define LCDC_OVR1CFG1_CLUTMODE_OFFSET 8
--#define LCDC_OVR1CFG1_CLUTMODE (0x3 << LCDC_OVR1CFG1_CLUTMODE_OFFSET)
--#define LCDC_OVR1CFG1_CLUTMODE_1BPP (0x0 << 8)
--#define LCDC_OVR1CFG1_CLUTMODE_2BPP (0x1 << 8)
--#define LCDC_OVR1CFG1_CLUTMODE_4BPP (0x2 << 8)
--#define LCDC_OVR1CFG1_CLUTMODE_8BPP (0x3 << 8)
--
--#define ATMEL_LCDC_OVR1CFG2 0x0134
--#define LCDC_OVR1CFG2_XOFFSET_OFFSET 0
--#define LCDC_OVR1CFG2_XOFFSET (0x7ff << LCDC_OVR1CFG2_XOFFSET_OFFSET)
--#define LCDC_OVR1CFG2_YOFFSET_OFFSET 16
--#define LCDC_OVR1CFG2_YOFFSET (0x7ff << LCDC_OVR1CFG2_YOFFSET_OFFSET)
--
--#define ATMEL_LCDC_OVR1CFG3 0x0138
--#define LCDC_OVR1CFG3_XSIZE_OFFSET 0
--#define LCDC_OVR1CFG3_XSIZE (0x7ff << LCDC_OVR1CFG3_XSIZE_OFFSET)
--#define LCDC_OVR1CFG3_YSIZE_OFFSET 16
--#define LCDC_OVR1CFG3_YSIZE (0x7ff << LCDC_OVR1CFG3_YSIZE_OFFSET)
--
--#define ATMEL_LCDC_OVR1CFG4 0x013C
--
--#define ATMEL_LCDC_OVR1CFG5 0x0140
--
--#define ATMEL_LCDC_OVR1CFG6 0x0144
--#define LCDC_OVR1CFG6_BDEF_OFFSET 0
--#define LCDC_OVR1CFG6_BDEF (0xff << LCDC_OVR1CFG6_BDEF_OFFSET)
--#define LCDC_OVR1CFG6_GDEF_OFFSET 8
--#define LCDC_OVR1CFG6_GDEF (0xff << LCDC_OVR1CFG6_GDEF_OFFSET)
--#define LCDC_OVR1CFG6_RDEF_OFFSET 16
--#define LCDC_OVR1CFG6_RDEF (0xff << LCDC_OVR1CFG6_RDEF_OFFSET)
--
--#define ATMEL_LCDC_OVR1CFG7 0x0148
--#define LCDC_OVR1CFG7_BKEY_OFFSET 0
--#define LCDC_OVR1CFG7_BKEY (0xff << LCDC_OVR1CFG7_BKEY_OFFSET)
--#define LCDC_OVR1CFG7_GKEY_OFFSET 8
--#define LCDC_OVR1CFG7_GKEY (0xff << LCDC_OVR1CFG7_GKEY_OFFST)
--#define LCDC_OVR1CFG7_RKEY_OFFSET 16
--#define LCDC_OVR1CFG7_RKEY (0xff << LCDC_OVR1CFG7_RKEY_OFFSET)
--
--#define ATMEL_LCDC_OVR1CFG8 0x014C
--#define LCDC_OVR1CFG8_BMASK_OFFSET 0
--#define LCDC_OVR1CFG8_BMASK (0xff << LCDC_OVR1CFG8_BMASK_OFFSET)
--#define LCDC_OVR1CFG8_GMASK_OFFSET 8
--#define LCDC_OVR1CFG8_GMASK (0xff << LCDC_OVR1CFG8_GMASK_OFFSET)
--#define LCDC_OVR1CFG8_RMASK_OFFSET 16
--#define LCDC_OVR1CFG8_RMASK (0xff << LCDC_OVR1CFG8_RMASK_OFFSET)
--
--#define ATMEL_LCDC_OVR1CFG9 0x0150
--#define LCDC_OVR1CFG9_CRKEY (0x1 << 0)
--#define LCDC_OVR1CFG9_INV (0x1 << 1)
--#define LCDC_OVR1CFG9_ITER2BL (0x1 << 2)
--#define LCDC_OVR1CFG9_ITER (0x1 << 3)
--#define LCDC_OVR1CFG9_REVALPHA (0x1 << 4)
--#define LCDC_OVR1CFG9_GAEN (0x1 << 5)
--#define LCDC_OVR1CFG9_LAEN (0x1 << 6)
--#define LCDC_OVR1CFG9_OVR (0x1 << 7)
--#define LCDC_OVR1CFG9_DMA (0x1 << 8)
--#define LCDC_OVR1CFG9_REP (0x1 << 9)
--#define LCDC_OVR1CFG9_DSTKEY (0x1 << 10)
--#define LCDC_OVR1CFG9_GA_OFFSET 16
--#define LCDC_OVR1CFG9_GA (0xff << LCDC_OVR1CFG9_GA_OFFSET)
--
--#define ATMEL_LCDC_HEOCHER 0x0280
--#define LCDC_HEOCHER_CHEN (0x1 << 0)
--#define LCDC_HEOCHER_UPDATEEN (0x1 << 1)
--#define LCDC_HEOCHER_A2QEN (0x1 << 2)
--
--#define ATMEL_LCDC_HEOCHDR 0x0284
--#define LCDC_HEOCHDR_CHDIS (0x1 << 0)
--#define LCDC_HEOCHDR_CHRST (0x1 << 8)
--
--#define ATMEL_LCDC_HEOCHSR 0x0288
--#define LCDC_HEOCHSR_CHSR (0x1 << 0)
--#define LCDC_HEOCHSR_UPDATESR (0x1 << 1)
--#define LCDC_HEOCHSR_A2QSR (0x1 << 2)
--
--#define ATMEL_LCDC_HEOIER 0x028C
--#define LCDC_HEOIER_DMA (0x1 << 2)
--#define LCDC_HEOIER_DSCR (0x1 << 3)
--#define LCDC_HEOIER_ADD (0x1 << 4)
--#define LCDC_HEOIER_DONE (0x1 << 5)
--#define LCDC_HEOIER_OVR (0x1 << 6)
--#define LCDC_HEOIER_UDMA (0x1 << 10)
--#define LCDC_HEOIER_UDSCR (0x1 << 11)
--#define LCDC_HEOIER_UADD (0x1 << 12)
--#define LCDC_HEOIER_UDONE (0x1 << 13)
--#define LCDC_HEOIER_UOVR (0x1 << 14)
--#define LCDC_HEOIER_VDMA (0x1 << 18)
--#define LCDC_HEOIER_VDSCR (0x1 << 19)
--#define LCDC_HEOIER_VADD (0x1 << 20)
--#define LCDC_HEOIER_VDONE (0x1 << 21)
--#define LCDC_HEOIER_VOVR (0x1 << 22)
--
--#define ATMEL_LCDC_HEOIDR 0x0290
--#define LCDC_HEOIDR_DMA (0x1 << 2)
--#define LCDC_HEOIDR_DSCR (0x1 << 3)
--#define LCDC_HEOIDR_ADD (0x1 << 4)
--#define LCDC_HEOIDR_DONE (0x1 << 5)
--#define LCDC_HEOIDR_OVR (0x1 << 6)
--#define LCDC_HEOIDR_UDMA (0x1 << 10)
--#define LCDC_HEOIDR_UDSCR (0x1 << 11)
--#define LCDC_HEOIDR_UADD (0x1 << 12)
--#define LCDC_HEOIDR_UDONE (0x1 << 13)
--#define LCDC_HEOIDR_UOVR (0x1 << 14)
--#define LCDC_HEOIDR_VDMA (0x1 << 18)
--#define LCDC_HEOIDR_VDSCR (0x1 << 19)
--#define LCDC_HEOIDR_VADD (0x1 << 20)
--#define LCDC_HEOIDR_VDONE (0x1 << 21)
--#define LCDC_HEOIDR_VOVR (0x1 << 22)
--
--#define ATMEL_LCDC_HEOIMR 0x0294
--#define LCDC_HEOIMR_DMA (0x1 << 2)
--#define LCDC_HEOIMR_DSCR (0x1 << 3)
--#define LCDC_HEOIMR_ADD (0x1 << 4)
--#define LCDC_HEOIMR_DONE (0x1 << 5)
--#define LCDC_HEOIMR_OVR (0x1 << 6)
--#define LCDC_HEOIMR_UDMA (0x1 << 10)
--#define LCDC_HEOIMR_UDSCR (0x1 << 11)
--#define LCDC_HEOIMR_UADD (0x1 << 12)
--#define LCDC_HEOIMR_UDONE (0x1 << 13)
--#define LCDC_HEOIMR_UOVR (0x1 << 14)
--#define LCDC_HEOIMR_VDMA (0x1 << 18)
--#define LCDC_HEOIMR_VDSCR (0x1 << 19)
--#define LCDC_HEOIMR_VADD (0x1 << 20)
--#define LCDC_HEOIMR_VDONE (0x1 << 21)
--#define LCDC_HEOIMR_VOVR (0x1 << 22)
--
--#define ATMEL_LCDC_HEOISR 0x0298
--#define LCDC_HEOISR_DMA (0x1 << 2)
--#define LCDC_HEOISR_DSCR (0x1 << 3)
--#define LCDC_HEOISR_ADD (0x1 << 4)
--#define LCDC_HEOISR_DONE (0x1 << 5)
--#define LCDC_HEOISR_OVR (0x1 << 6)
--#define LCDC_HEOISR_UDMA (0x1 << 10)
--#define LCDC_HEOISR_UDSCR (0x1 << 11)
--#define LCDC_HEOISR_UADD (0x1 << 12)
--#define LCDC_HEOISR_UDONE (0x1 << 13)
--#define LCDC_HEOISR_UOVR (0x1 << 14)
--#define LCDC_HEOISR_VDMA (0x1 << 18)
--#define LCDC_HEOISR_VDSCR (0x1 << 19)
--#define LCDC_HEOISR_VADD (0x1 << 20)
--#define LCDC_HEOISR_VDONE (0x1 << 21)
--#define LCDC_HEOISR_VOVR (0x1 << 22)
--
--#define ATMEL_LCDC_HEOHEAD 0x029C
--
--#define ATMEL_LCDC_HEOADDR 0x02A0
--
--#define ATMEL_LCDC_HEOCTRL 0x02A4
--#define LCDC_HEOCTRL_DFETCH (0x1 << 0)
--#define LCDC_HEOCTRL_LFETCH (0x1 << 1)
--#define LCDC_HEOCTRL_DMAIEN (0x1 << 2)
--#define LCDC_HEOCTRL_DSCRIEN (0x1 << 3)
--#define LCDC_HEOCTRL_ADDIEN (0x1 << 4)
--#define LCDC_HEOCTRL_DONEIEN (0x1 << 5)
--
--#define ATMEL_LCDC_HEONEXT 0x02A8
--
--#define ATMEL_LCDC_HEOUHEAD 0x02AC
--
--#define ATMEL_LCDC_HEOUADDR 0x02B0
--
--#define ATMEL_LCDC_HEOUCTRL 0x02B4
--#define LCDC_HEOUCTRL_UDFETCH (0x1 << 0)
--#define LCDC_HEOUCTRL_UDMAIEN (0x1 << 2)
--#define LCDC_HEOUCTRL_UDSCRIEN (0x1 << 3)
--#define LCDC_HEOUCTRL_UADDIEN (0x1 << 4)
--#define LCDC_HEOUCTRL_UDONEIEN (0x1 << 5)
--
--#define ATMEL_LCDC_HEOUNEXT 0x02B8
--
--#define ATMEL_LCDC_HEOVHEAD 0x02BC
--
--#define ATMEL_LCDC_HEOVADDR 0x02C0
--
--#define ATMEL_LCDC_HEOVCTRL 0x02C4
--#define LCDC_HEOVCTRL_VDFETCH (0x1 << 0)
--#define LCDC_HEOVCTRL_VDMAIEN (0x1 << 2)
--#define LCDC_HEOVCTRL_VDSCRIEN (0x1 << 3)
--#define LCDC_HEOVCTRL_VADDIEN (0x1 << 4)
--#define LCDC_HEOVCTRL_VDONEIEN (0x1 << 5)
--
--#define ATMEL_LCDC_HEOVNEXT 0x02C8
--
--#define ATMEL_LCDC_HEOCFG0 0x02CC
--#define LCDC_HEOCFG0_BLEN_OFFSET 4
--#define LCDC_HEOCFG0_BLEN (0x3 << LCDC_HEOCFG0_BLEN_OFFSET)
--#define LCDC_HEOCFG0_BLEN_AHB_SINGLE (0x0 << 4)
--#define LCDC_HEOCFG0_BLEN_AHB_INCR4 (0x1 << 4)
--#define LCDC_HEOCFG0_BLEN_AHB_INCR8 (0x2 << 4)
--#define LCDC_HEOCFG0_BLEN_AHB_INCR16 (0x3 << 4)
--#define LCDC_HEOCFG0_BLENUV_OFFSET 6
--#define LCDC_HEOCFG0_BLENUV (0x3 << LCDC_HEOCFG0_BLENUV_OFFSET)
--#define LCDC_HEOCFG0_BLENUV_AHB_SINGLE (0x0 << 6)
--#define LCDC_HEOCFG0_BLENUV_AHB_INCR4 (0x1 << 6)
--#define LCDC_HEOCFG0_BLENUV_AHB_INCR8 (0x2 << 6)
--#define LCDC_HEOCFG0_BLENUV_AHB_INCR16 (0x3 << 6)
--#define LCDC_HEOCFG0_DLBO (0x1 << 8)
--#define LCDC_HEOCFG0_ROTDIS (0x1 << 12)
--#define LCDC_HEOCFG0_LOCKDIS (0x1 << 13)
--
--#define ATMEL_LCDC_HEOCFG1 0x02D0
--#define LCDC_HEOCFG1_CLUTEN (0x1 << 0)
--#define LCDC_HEOCFG1_YUVEN (0x1 << 1)
--#define LCDC_HEOCFG1_RGBMODE_OFFSET 4
--#define LCDC_HEOCFG1_RGBMODE (0xf << LCDC_HEOCFG1_RGBMODE_OFFSET)
--#define LCDC_HEOCFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4)
--#define LCDC_HEOCFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4)
--#define LCDC_HEOCFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4)
--#define LCDC_HEOCFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4)
--#define LCDC_HEOCFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4)
--#define LCDC_HEOCFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4)
--#define LCDC_HEOCFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4)
--#define LCDC_HEOCFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4)
--#define LCDC_HEOCFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4)
--#define LCDC_HEOCFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4)
--#define LCDC_HEOCFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4)
--#define LCDC_HEOCFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4)
--#define LCDC_HEOCFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4)
--#define LCDC_HEOCFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4)
--#define LCDC_HEOCFG1_CLUTMODE_OFFSET 8
--#define LCDC_HEOCFG1_CLUTMODE (0x3 << LCDC_HEOCFG1_CLUTMODE_OFFSET)
--#define LCDC_HEOCFG1_CLUTMODE_1BPP (0x0 << 8)
--#define LCDC_HEOCFG1_CLUTMODE_2BPP (0x1 << 8)
--#define LCDC_HEOCFG1_CLUTMODE_4BPP (0x2 << 8)
--#define LCDC_HEOCFG1_CLUTMODE_8BPP (0x3 << 8)
--#define LCDC_HEOCFG1_YUVMODE_OFFSET 12
--#define LCDC_HEOCFG1_YUVMODE (0xf << LCDC_HEOCFG1_YUVMODE_OFFSET)
--#define LCDC_HEOCFG1_YUVMODE_32BPP_AYCBCR (0x0 << 12)
--#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE0 (0x1 << 12)
--#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE1 (0x2 << 12)
--#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE2 (0x3 << 12)
--#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_MODE3 (0x4 << 12)
--#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_SEMIPLANAR (0x5 << 12)
--#define LCDC_HEOCFG1_YUVMODE_16BPP_YCBCR_PLANAR (0x6 << 12)
--#define LCDC_HEOCFG1_YUVMODE_12BPP_YCBCR_SEMIPLANAR (0x7 << 12)
--#define LCDC_HEOCFG1_YUVMODE_12BPP_YCBCR_PLANAR (0x8 << 12)
--#define LCDC_HEOCFG1_YUV422ROT (0x1 << 16)
--#define LCDC_HEOCFG1_YUV422SWP (0x1 << 17)
--
--#define ATMEL_LCDC_HEOCFG2 0x02D4
--#define LCDC_HEOCFG2_XOFFSET_OFFSET 0
--#define LCDC_HEOCFG2_XOFFSET (0x7ff << LCDC_HEOCFG2_XOFFSET_OFFSET)
--#define LCDC_HEOCFG2_YOFFSET_OFFSET 16
--#define LCDC_HEOCFG2_YOFFSET (0x7ff << LCDC_HEOCFG2_YOFFSET_OFFSET)
--
--#define ATMEL_LCDC_HEOCFG3 0x02D8
--#define LCDC_HEOCFG3_XSIZE_OFFSET 0
--#define LCDC_HEOCFG3_XSIZE (0x7ff << LCDC_HEOCFG3_XSIZE_OFFSET)
--#define LCDC_HEOCFG3_YSIZE_OFFSET 16
--#define LCDC_HEOCFG3_YSIZE (0x7ff << LCDC_HEOCFG3_YSIZE_OFFSET)
--
--#define ATMEL_LCDC_HEOCFG4 0x02DC
--#define LCDC_HEOCFG4_XMEM_SIZE_OFFSET 0
--#define LCDC_HEOCFG4_XMEM_SIZE (0x7ff << LCDC_HEOCFG4_XMEM_SIZE_OFFSET)
--#define LCDC_HEOCFG4_YMEM_SIZE_OFFSET 16
--#define LCDC_HEOCFG4_YMEM_SIZE (0x7ff << LCDC_HEOCFG4_YMEM_SIZE_OFFSET)
--
--#define ATMEL_LCDC_HEOCFG5 0x02E0
--
--#define ATMEL_LCDC_HEOCFG6 0x02E4
--
--#define ATMEL_LCDC_HEOCFG7 0x02E8
--
--#define ATMEL_LCDC_HEOCFG8 0x02EC
--
--#define ATMEL_LCDC_HEOCFG9 0x02F0
--#define LCDC_HEOCFG9_BDEF_OFFSET 0
--#define LCDC_HEOCFG9_BDEF (0xff << LCDC_HEOCFG9_BDEF_OFFSET)
--#define LCDC_HEOCFG9_GDEF_OFFSET 8
--#define LCDC_HEOCFG9_GDEF (0xff << LCDC_HEOCFG9_GDEF_OFFSET)
--#define LCDC_HEOCFG9_RDEF_OFFSET 16
--#define LCDC_HEOCFG9_RDEF (0xff << LCDC_HEOCFG9_RDEF_OFFSET)
--
--#define ATMEL_LCDC_HEOCFG10 0x02F4
--#define LCDC_HEOCFG10_BKEY_OFFSET 0
--#define LCDC_HEOCFG10_BKEY (0xff << LCDC_HEOCFG10_BKEY_OFFSET)
--#define LCDC_HEOCFG10_GKEY_OFFSET 8
--#define LCDC_HEOCFG10_GKEY (0xff << LCDC_HEOCFG10_GKEY_OFFSET)
--#define LCDC_HEOCFG10_RKEY_OFFSET 16
--#define LCDC_HEOCFG10_RKEY (0xff << LCDC_HEOCFG10_RKEY_OFFSET)
--
--#define ATMEL_LCDC_HEOCFG11 0x02F8
--#define LCDC_HEOCFG11_BMASK_OFFSET 0
--#define LCDC_HEOCFG11_BMASK (0xff << LCDC_HEOCFG11_BMASK_OFFSET)
--#define LCDC_HEOCFG11_GMASK_OFFSET 8
--#define LCDC_HEOCFG11_GMASK (0xff << LCDC_HEOCFG11_GMASK_OFFSET)
--#define LCDC_HEOCFG11_RMASK_OFFSET 16
--#define LCDC_HEOCFG11_RMASK (0xff << LCDC_HEOCFG11_RMASK_OFFSET)
--
--#define ATMEL_LCDC_HEOCFG12 0x02FC
--#define LCDC_HEOCFG12_CRKEY (0x1 << 0)
--#define LCDC_HEOCFG12_INV (0x1 << 1)
--#define LCDC_HEOCFG12_ITER2BL (0x1 << 2)
--#define LCDC_HEOCFG12_ITER (0x1 << 3)
--#define LCDC_HEOCFG12_REVALPHA (0x1 << 4)
--#define LCDC_HEOCFG12_GAEN (0x1 << 5)
--#define LCDC_HEOCFG12_LAEN (0x1 << 6)
--#define LCDC_HEOCFG12_OVR (0x1 << 7)
--#define LCDC_HEOCFG12_DMA (0x1 << 8)
--#define LCDC_HEOCFG12_REP (0x1 << 9)
--#define LCDC_HEOCFG12_DSTKEY (0x1 << 10)
--#define LCDC_HEOCFG12_VIDPRI (0x1 << 12)
--#define LCDC_HEOCFG12_GA_OFFSET 16
--#define LCDC_HEOCFG12_GA (0xff << LCDC_HEOCFG12_GA_OFFSET)
--
--#define ATMEL_LCDC_HEOCFG13 0x0300
--#define LCDC_HEOCFG13_XFACTOR_OFFSET 0
--#define LCDC_HEOCFG13_XFACTOR (0x1fff << LCDC_HEOCFG13_XFACTOR_OFFSET)
--#define LCDC_HEOCFG13_YFACTOR_OFFSET 16
--#define LCDC_HEOCFG13_YFACTOR (0x1fff << LCDC_HEOCFG13_YFACTOR_OFFSET)
--#define LCDC_HEOCFG13_SCALEN (0x1 << 31)
--
--#define ATMEL_LCDC_HEOCFG14 0x0304
--#define LCDC_HEOCFG14_CSCRY_OFFSET 0
--#define LCDC_HEOCFG14_CSCRY (0x3ff << LCDC_HEOCFG14_CSCRY_OFFSET)
--#define LCDC_HEOCFG14_CSCRU_OFFSET 10
--#define LCDC_HEOCFG14_CSCRU (0x3ff << LCDC_HEOCFG14_CSCRU_OFFSET)
--#define LCDC_HEOCFG14_CSCRV_OFFSET 20
--#define LCDC_HEOCFG14_CSCRV (0x3ff << LCDC_HEOCFG14_CSCRV_OFFSET)
--#define LCDC_HEOCFG14_CSCYOFF (0x1 << 30)
--
--#define ATMEL_LCDC_HEOCFG15 0x0308
--#define LCDC_HEOCFG15_CSCGY_OFFSET 0
--#define LCDC_HEOCFG15_CSCGY (0x3ff << LCDC_HEOCFG15_CSCGY_OFFSET)
--#define LCDC_HEOCFG15_CSCGU_OFFSET 10
--#define LCDC_HEOCFG15_CSCGU (0x3ff << LCDC_HEOCFG15_CSCGU_OFFSET)
--#define LCDC_HEOCFG15_CSCGV_OFFSET 20
--#define LCDC_HEOCFG15_CSCGV (0x3ff << LCDC_HEOCFG15_CSCGV_OFFSET)
--#define LCDC_HEOCFG15_CSCUOFF (0x1 << 30)
--
--#define ATMEL_LCDC_HEOCFG16 0x030C
--#define LCDC_HEOCFG16_CSCBY_OFFSET 0
--#define LCDC_HEOCFG16_CSCBY (0x3ff << LCDC_HEOCFG16_CSCBY_OFFSET)
--#define LCDC_HEOCFG16_CSCBU_OFFSET 10
--#define LCDC_HEOCFG16_CSCBU (0x3ff << LCDC_HEOCFG16_CSCBU_OFFSET)
--#define LCDC_HEOCFG16_CSCBV_OFFSET 20
--#define LCDC_HEOCFG16_CSCBV (0x3ff << LCDC_HEOCFG16_CSCBV_OFFSET)
--#define LCDC_HEOCFG16_CSCVOFF (0x1 << 30)
--
--#define ATMEL_LCDC_HCRCHER 0x0340
--#define LCDC_HCRCHER_CHEN (0x1 << 0)
--#define LCDC_HCRCHER_UPDATEEN (0x1 << 1)
--#define LCDC_HCRCHER_A2QEN (0x1 << 2)
--
--#define ATMEL_LCDC_HCRCHDR 0x0344
--#define LCDC_HCRCHDR_CHDIS (0x1 << 0)
--#define LCDC_HCRCHDR_CHRST (0x1 << 8)
--
--#define ATMEL_LCDC_HCRCHSR 0x0348
--#define LCDC_HCRCHSR_CHSR (0x1 << 0)
--#define LCDC_HCRCHSR_UPDATESR (0x1 << 1)
--#define LCDC_HCRCHSR_A2QSR (0x1 << 2)
--
--#define ATMEL_LCDC_HCRIER 0x034C
--#define LCDC_HCRIER_DMA (0x1 << 2)
--#define LCDC_HCRIER_DSCR (0x1 << 3)
--#define LCDC_HCRIER_ADD (0x1 << 4)
--#define LCDC_HCRIER_DONE (0x1 << 5)
--#define LCDC_HCRIER_OVR (0x1 << 6)
--
--#define ATMEL_LCDC_HCRIDR 0x0350
--#define LCDC_HCRIDR_DMA (0x1 << 2)
--#define LCDC_HCRIDR_DSCR (0x1 << 3)
--#define LCDC_HCRIDR_ADD (0x1 << 4)
--#define LCDC_HCRIDR_DONE (0x1 << 5)
--#define LCDC_HCRIDR_OVR (0x1 << 6)
--
--#define ATMEL_LCDC_HCRIMR 0x0354
--#define LCDC_HCRIMR_DMA (0x1 << 2)
--#define LCDC_HCRIMR_DSCR (0x1 << 3)
--#define LCDC_HCRIMR_ADD (0x1 << 4)
--#define LCDC_HCRIMR_DONE (0x1 << 5)
--#define LCDC_HCRIMR_OVR (0x1 << 6)
--
--#define ATMEL_LCDC_HCRISR 0x0358
--#define LCDC_HCRISR_DMA (0x1 << 2)
--#define LCDC_HCRISR_DSCR (0x1 << 3)
--#define LCDC_HCRISR_ADD (0x1 << 4)
--#define LCDC_HCRISR_DONE (0x1 << 5)
--#define LCDC_HCRISR_OVR (0x1 << 6)
--
--#define ATMEL_LCDC_HCRHEAD 0x035C
--
--#define ATMEL_LCDC_HCRADDR 0x0360
--
--#define ATMEL_LCDC_HCRCTRL 0x0364
--#define LCDC_HCRCTRL_DFETCH (0x1 << 0)
--#define LCDC_HCRCTRL_LFETCH (0x1 << 1)
--#define LCDC_HCRCTRL_DMAIEN (0x1 << 2)
--#define LCDC_HCRCTRL_DSCRIEN (0x1 << 3)
--#define LCDC_HCRCTRL_ADDIEN (0x1 << 4)
--#define LCDC_HCRCTRL_DONEIEN (0x1 << 5)
--
--#define ATMEL_LCDC_HCRNEXT 0x0368
--
--#define ATMEL_LCDC_HCRCFG0 0x036C
--#define LCDC_HCRCFG0_BLEN_OFFSET 4
--#define LCDC_HCRCFG0_BLEN (0x3 << LCDC_HCRCFG0_BLEN_OFFSET)
--#define LCDC_HCRCFG0_BLEN_AHB_SINGLE (0x0 << 4)
--#define LCDC_HCRCFG0_BLEN_AHB_INCR4 (0x1 << 4)
--#define LCDC_HCRCFG0_BLEN_AHB_INCR8 (0x2 << 4)
--#define LCDC_HCRCFG0_BLEN_AHB_INCR16 (0x3 << 4)
--#define LCDC_HCRCFG0_DLBO (0x1 << 8)
--
--#define ATMEL_LCDC_HCRCFG1 0x0370
--#define LCDC_HCRCFG1_CLUTEN (0x1 << 0)
--#define LCDC_HCRCFG1_RGBMODE_OFFSET 4
--#define LCDC_HCRCFG1_RGBMODE (0xf << LCDC_HCRCFG1_RGBMODE_OFFSET)
--#define LCDC_HCRCFG1_RGBMODE_12BPP_RGB_444 (0x0 << 4)
--#define LCDC_HCRCFG1_RGBMODE_16BPP_ARGB_4444 (0x1 << 4)
--#define LCDC_HCRCFG1_RGBMODE_16BPP_RGBA_4444 (0x2 << 4)
--#define LCDC_HCRCFG1_RGBMODE_16BPP_RGB_565 (0x3 << 4)
--#define LCDC_HCRCFG1_RGBMODE_16BPP_TRGB_1555 (0x4 << 4)
--#define LCDC_HCRCFG1_RGBMODE_18BPP_RGB_666 (0x5 << 4)
--#define LCDC_HCRCFG1_RGBMODE_18BPP_RGB_666_PACKED (0x6 << 4)
--#define LCDC_HCRCFG1_RGBMODE_19BPP_TRGB_1666 (0x7 << 4)
--#define LCDC_HCRCFG1_RGBMODE_19BPP_TRGB_PACKED (0x8 << 4)
--#define LCDC_HCRCFG1_RGBMODE_24BPP_RGB_888 (0x9 << 4)
--#define LCDC_HCRCFG1_RGBMODE_24BPP_RGB_888_PACKED (0xA << 4)
--#define LCDC_HCRCFG1_RGBMODE_25BPP_TRGB_1888 (0xB << 4)
--#define LCDC_HCRCFG1_RGBMODE_32BPP_ARGB_8888 (0xC << 4)
--#define LCDC_HCRCFG1_RGBMODE_32BPP_RGBA_8888 (0xD << 4)
--#define LCDC_HCRCFG1_CLUTMODE_OFFSET 8
--#define LCDC_HCRCFG1_CLUTMODE (0x3 << LCDC_HCRCFG1_CLUTMODE_OFFSET)
--#define LCDC_HCRCFG1_CLUTMODE_1BPP (0x0 << 8)
--#define LCDC_HCRCFG1_CLUTMODE_2BPP (0x1 << 8)
--#define LCDC_HCRCFG1_CLUTMODE_4BPP (0x2 << 8)
--#define LCDC_HCRCFG1_CLUTMODE_8BPP (0x3 << 8)
--
--#define ATMEL_LCDC_HCRCFG2 0x0374
--#define LCDC_HCRCFG2_XOFFSET_OFFSET 0
--#define LCDC_HCRCFG2_XOFFSET (0x7ff << LCDC_HCRCFG2_XOFFSET_OFFSET)
--#define LCDC_HCRCFG2_YOFFSET_OFFSET 16
--#define LCDC_HCRCFG2_YOFFSET (0x7ff << LCDC_HCRCFG2_YOFFSET_OFFSET)
--
--#define ATMEL_LCDC_HCRCFG3 0x0378
--#define LCDC_HCRCFG3_XSIZE_OFFSET 0
--#define LCDC_HCRCFG3_XSIZE (0x7f << LCDC_HCRCFG3_XSIZE_OFFSET)
--#define LCDC_HCRCFG3_YSIZE_OFFSET 16
--#define LCDC_HCRCFG3_YSIZE (0x7f << LCDC_HCRCFG3_YSIZE_OFFSET)
--
--#define ATMEL_LCDC_HCRCFG4 0x037C
--
--#define ATMEL_LCDC_HCRCFG6 0x0384
--#define LCDC_HCRCFG6_BDEF_OFFSET 0
--#define LCDC_HCRCFG6_BDEF (0xff << LCDC_HCRCFG6_BDEF_OFFSET)
--#define LCDC_HCRCFG6_GDEF_OFFSET 8
--#define LCDC_HCRCFG6_GDEF (0xff << LCDC_HCRCFG6_GDEF_OFFSET)
--#define LCDC_HCRCFG6_RDEF_OFFSET 16
--#define LCDC_HCRCFG6_RDEF (0xff << LCDC_HCRCFG6_RDEF_OFFSET)
--
--#define ATMEL_LCDC_HCRCFG7 0x0388
--#define LCDC_HCRCFG7_BKEY_OFFSET 0
--#define LCDC_HCRCFG7_BKEY (0xff << LCDC_HCRCFG7_BKEY_OFFSET)
--#define LCDC_HCRCFG7_GKEY_OFFSET 8
--#define LCDC_HCRCFG7_GKEY (0xff << LCDC_HCRCFG7_GKEY_OFFSET)
--#define LCDC_HCRCFG7_RKEY_OFFSET 16
--#define LCDC_HCRCFG7_RKEY (0xff << LCDC_HCRCFG7_RKEY_OFFSET)
--
--#define ATMEL_LCDC_HCRCFG8 0x038C
--#define LCDC_HCRCFG8_BMASK_OFFSET 0
--#define LCDC_HCRCFG8_BMASK (0xff << LCDC_HCRCFG8_BMASK_OFFSET)
--#define LCDC_HCRCFG8_GMASK_OFFSET 8
--#define LCDC_HCRCFG8_GMASK (0xff << LCDC_HCRCFG8_GMASK_OFFSET)
--#define LCDC_HCRCFG8_RMASK_OFFSET 16
--#define LCDC_HCRCFG8_RMASK (0xff << LCDC_HCRCFG8_RMASK_OFFSET)
--
--#define ATMEL_LCDC_HCRCFG9 0x0390
--#define LCDC_HCRCFG9_CRKEY (0x1 << 0)
--#define LCDC_HCRCFG9_INV (0x1 << 1)
--#define LCDC_HCRCFG9_ITER2BL (0x1 << 2)
--#define LCDC_HCRCFG9_ITER (0x1 << 3)
--#define LCDC_HCRCFG9_REVALPHA (0x1 << 4)
--#define LCDC_HCRCFG9_GAEN (0x1 << 5)
--#define LCDC_HCRCFG9_LAEN (0x1 << 6)
--#define LCDC_HCRCFG9_OVR (0x1 << 7)
--#define LCDC_HCRCFG9_DMA (0x1 << 8)
--#define LCDC_HCRCFG9_REP (0x1 << 9)
--#define LCDC_HCRCFG9_DSTKEY (0x1 << 10)
--#define LCDC_HCRCFG9_GA_OFFSET 16
--#define LCDC_HCRCFG9_GA_Msk (0xff << LCDC_HCRCFG9_GA_OFFSET)
--
--#define ATMEL_LCDC_BASECLUT 0x400
--#define LCDC_BASECLUT_BCLUT_OFFSET 0
--#define LCDC_BASECLUT_BCLUT (0xff << LCDC_BASECLUT_BCLUT_OFFSET)
--#define LCDC_BASECLUT_GCLUT_OFFSET 8
--#define LCDC_BASECLUT_GCLUT (0xff << LCDC_BASECLUT_GCLUT_OFFSET)
--#define LCDC_BASECLUT_RCLUT_OFFSET 16
--#define LCDC_BASECLUT_RCLUT (0xff << LCDC_BASECLUT_RCLUT_OFFSET)
--
--#define ATMEL_LCDC_OVR1CLUT 0x800
--#define LCDC_OVR1CLUT_BCLUT_OFFSET 0
--#define LCDC_OVR1CLUT_BCLUT (0xff << LCDC_OVR1CLUT_BCLUT_OFFSET)
--#define LCDC_OVR1CLUT_GCLUT_OFFSET 8
--#define LCDC_OVR1CLUT_GCLUT (0xff << LCDC_OVR1CLUT_GCLUT_OFFSET)
--#define LCDC_OVR1CLUT_RCLUT_OFFSET 16
--#define LCDC_OVR1CLUT_RCLUT (0xff << LCDC_OVR1CLUT_RCLUT_OFFSET)
--#define LCDC_OVR1CLUT_ACLUT_OFFSET 24
--#define LCDC_OVR1CLUT_ACLUT (0xff << LCDC_OVR1CLUT_ACLUT_OFFSET)
--
--#define ATMEL_LCDC_HEOCLUT 0x1000
--#define LCDC_HEOCLUT_BCLUT_OFFSET 0
--#define LCDC_HEOCLUT_BCLUT (0xff << LCDC_HEOCLUT_BCLUT_OFFSET)
--#define LCDC_HEOCLUT_GCLUT_OFFSET 8
--#define LCDC_HEOCLUT_GCLUT (0xff << LCDC_HEOCLUT_GCLUT_OFFSET)
--#define LCDC_HEOCLUT_RCLUT_OFFSET 16
--#define LCDC_HEOCLUT_RCLUT (0xff << LCDC_HEOCLUT_RCLUT_OFFSET)
--#define LCDC_HEOCLUT_ACLUT_OFFSET 24
--#define LCDC_HEOCLUT_ACLUT (0xff << LCDC_HEOCLUT_ACLUT_OFFSET)
--
--#define ATMEL_LCDC_HCRCLUT 0x1400
--#define LCDC_HCRCLUT_BCLUT_OFFSET 0
--#define LCDC_HCRCLUT_BCLUT (0xff << LCDC_HCRCLUT_BCLUT_OFFSET)
--#define LCDC_HCRCLUT_GCLUT_OFFSET 8
--#define LCDC_HCRCLUT_GCLUT (0xff << LCDC_HCRCLUT_GCLUT_OFFSET)
--#define LCDC_HCRCLUT_RCLUT_OFFSET 16
--#define LCDC_HCRCLUT_RCLUT (0xff << LCDC_HCRCLUT_RCLUT_OFFSET)
--#define LCDC_HCRCLUT_ACLUT_OFFSET 24
--#define LCDC_HCRCLUT_ACLUT (0xff << LCDC_HCRCLUT_ACLUT_OFFSET)
--
--/* Base layer CLUT */
--#define ATMEL_LCDC_LUT(n) (0x0400 + ((n)*4))
--
--
--#endif /* __ATMEL_HLCDC4_H__ */
---- /dev/null
-+++ b/arch/arm/mach-at91/include/mach/atmel_lcdc.h
-@@ -0,0 +1,177 @@
-+/*
-+ * Header file for AT91/AT32 LCD Controller
-+ *
-+ * Data structure and register user interface
-+ *
-+ * Copyright (C) 2007 Atmel Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+#ifndef __MACH_ATMEL_LCDC_H__
-+#define __MACH_ATMEL_LCDC_H__
-+
-+#define ATMEL_LCDC_DMABADDR1 0x00
-+#define ATMEL_LCDC_DMABADDR2 0x04
-+#define ATMEL_LCDC_DMAFRMPT1 0x08
-+#define ATMEL_LCDC_DMAFRMPT2 0x0c
-+#define ATMEL_LCDC_DMAFRMADD1 0x10
-+#define ATMEL_LCDC_DMAFRMADD2 0x14
-+
-+#define ATMEL_LCDC_DMAFRMCFG 0x18
-+#define ATMEL_LCDC_FRSIZE (0x7fffff << 0)
-+#define ATMEL_LCDC_BLENGTH_OFFSET 24
-+#define ATMEL_LCDC_BLENGTH (0x7f << ATMEL_LCDC_BLENGTH_OFFSET)
-+
-+#define ATMEL_LCDC_DMACON 0x1c
-+#define ATMEL_LCDC_DMAEN (0x1 << 0)
-+#define ATMEL_LCDC_DMARST (0x1 << 1)
-+#define ATMEL_LCDC_DMABUSY (0x1 << 2)
-+#define ATMEL_LCDC_DMAUPDT (0x1 << 3)
-+#define ATMEL_LCDC_DMA2DEN (0x1 << 4)
-+
-+#define ATMEL_LCDC_DMA2DCFG 0x20
-+#define ATMEL_LCDC_ADDRINC_OFFSET 0
-+#define ATMEL_LCDC_ADDRINC (0xffff)
-+#define ATMEL_LCDC_PIXELOFF_OFFSET 24
-+#define ATMEL_LCDC_PIXELOFF (0x1f << 24)
-+
-+#define ATMEL_LCDC_LCDCON1 0x0800
-+#define ATMEL_LCDC_BYPASS (1 << 0)
-+#define ATMEL_LCDC_CLKVAL_OFFSET 12
-+#define ATMEL_LCDC_CLKVAL (0x1ff << ATMEL_LCDC_CLKVAL_OFFSET)
-+#define ATMEL_LCDC_LINCNT (0x7ff << 21)
-+
-+#define ATMEL_LCDC_LCDCON2 0x0804
-+#define ATMEL_LCDC_DISTYPE (3 << 0)
-+#define ATMEL_LCDC_DISTYPE_STNMONO (0 << 0)
-+#define ATMEL_LCDC_DISTYPE_STNCOLOR (1 << 0)
-+#define ATMEL_LCDC_DISTYPE_TFT (2 << 0)
-+#define ATMEL_LCDC_SCANMOD (1 << 2)
-+#define ATMEL_LCDC_SCANMOD_SINGLE (0 << 2)
-+#define ATMEL_LCDC_SCANMOD_DUAL (1 << 2)
-+#define ATMEL_LCDC_IFWIDTH (3 << 3)
-+#define ATMEL_LCDC_IFWIDTH_4 (0 << 3)
-+#define ATMEL_LCDC_IFWIDTH_8 (1 << 3)
-+#define ATMEL_LCDC_IFWIDTH_16 (2 << 3)
-+#define ATMEL_LCDC_PIXELSIZE (7 << 5)
-+#define ATMEL_LCDC_PIXELSIZE_1 (0 << 5)
-+#define ATMEL_LCDC_PIXELSIZE_2 (1 << 5)
-+#define ATMEL_LCDC_PIXELSIZE_4 (2 << 5)
-+#define ATMEL_LCDC_PIXELSIZE_8 (3 << 5)
-+#define ATMEL_LCDC_PIXELSIZE_16 (4 << 5)
-+#define ATMEL_LCDC_PIXELSIZE_24 (5 << 5)
-+#define ATMEL_LCDC_PIXELSIZE_32 (6 << 5)
-+#define ATMEL_LCDC_INVVD (1 << 8)
-+#define ATMEL_LCDC_INVVD_NORMAL (0 << 8)
-+#define ATMEL_LCDC_INVVD_INVERTED (1 << 8)
-+#define ATMEL_LCDC_INVFRAME (1 << 9 )
-+#define ATMEL_LCDC_INVFRAME_NORMAL (0 << 9)
-+#define ATMEL_LCDC_INVFRAME_INVERTED (1 << 9)
-+#define ATMEL_LCDC_INVLINE (1 << 10)
-+#define ATMEL_LCDC_INVLINE_NORMAL (0 << 10)
-+#define ATMEL_LCDC_INVLINE_INVERTED (1 << 10)
-+#define ATMEL_LCDC_INVCLK (1 << 11)
-+#define ATMEL_LCDC_INVCLK_NORMAL (0 << 11)
-+#define ATMEL_LCDC_INVCLK_INVERTED (1 << 11)
-+#define ATMEL_LCDC_INVDVAL (1 << 12)
-+#define ATMEL_LCDC_INVDVAL_NORMAL (0 << 12)
-+#define ATMEL_LCDC_INVDVAL_INVERTED (1 << 12)
-+#define ATMEL_LCDC_CLKMOD (1 << 15)
-+#define ATMEL_LCDC_CLKMOD_ACTIVEDISPLAY (0 << 15)
-+#define ATMEL_LCDC_CLKMOD_ALWAYSACTIVE (1 << 15)
-+#define ATMEL_LCDC_MEMOR (1 << 31)
-+#define ATMEL_LCDC_MEMOR_BIG (0 << 31)
-+#define ATMEL_LCDC_MEMOR_LITTLE (1 << 31)
-+
-+#define ATMEL_LCDC_TIM1 0x0808
-+#define ATMEL_LCDC_VFP (0xffU << 0)
-+#define ATMEL_LCDC_VBP_OFFSET 8
-+#define ATMEL_LCDC_VBP (0xffU << ATMEL_LCDC_VBP_OFFSET)
-+#define ATMEL_LCDC_VPW_OFFSET 16
-+#define ATMEL_LCDC_VPW (0x3fU << ATMEL_LCDC_VPW_OFFSET)
-+#define ATMEL_LCDC_VHDLY_OFFSET 24
-+#define ATMEL_LCDC_VHDLY (0xfU << ATMEL_LCDC_VHDLY_OFFSET)
-+
-+#define ATMEL_LCDC_TIM2 0x080c
-+#define ATMEL_LCDC_HBP (0xffU << 0)
-+#define ATMEL_LCDC_HPW_OFFSET 8
-+#define ATMEL_LCDC_HPW (0x3fU << ATMEL_LCDC_HPW_OFFSET)
-+#define ATMEL_LCDC_HFP_OFFSET 21
-+#define ATMEL_LCDC_HFP (0x7ffU << ATMEL_LCDC_HFP_OFFSET)
-+
-+#define ATMEL_LCDC_LCDFRMCFG 0x0810
-+#define ATMEL_LCDC_LINEVAL (0x7ff << 0)
-+#define ATMEL_LCDC_HOZVAL_OFFSET 21
-+#define ATMEL_LCDC_HOZVAL (0x7ff << ATMEL_LCDC_HOZVAL_OFFSET)
-+
-+#define ATMEL_LCDC_FIFO 0x0814
-+#define ATMEL_LCDC_FIFOTH (0xffff)
-+
-+#define ATMEL_LCDC_MVAL 0x0818
-+
-+#define ATMEL_LCDC_DP1_2 0x081c
-+#define ATMEL_LCDC_DP4_7 0x0820
-+#define ATMEL_LCDC_DP3_5 0x0824
-+#define ATMEL_LCDC_DP2_3 0x0828
-+#define ATMEL_LCDC_DP5_7 0x082c
-+#define ATMEL_LCDC_DP3_4 0x0830
-+#define ATMEL_LCDC_DP4_5 0x0834
-+#define ATMEL_LCDC_DP6_7 0x0838
-+#define ATMEL_LCDC_DP1_2_VAL (0xff)
-+#define ATMEL_LCDC_DP4_7_VAL (0xfffffff)
-+#define ATMEL_LCDC_DP3_5_VAL (0xfffff)
-+#define ATMEL_LCDC_DP2_3_VAL (0xfff)
-+#define ATMEL_LCDC_DP5_7_VAL (0xfffffff)
-+#define ATMEL_LCDC_DP3_4_VAL (0xffff)
-+#define ATMEL_LCDC_DP4_5_VAL (0xfffff)
-+#define ATMEL_LCDC_DP6_7_VAL (0xfffffff)
-+
-+#define ATMEL_LCDC_PWRCON 0x083c
-+#define ATMEL_LCDC_PWR (1 << 0)
-+#define ATMEL_LCDC_GUARDT_OFFSET 1
-+#define ATMEL_LCDC_GUARDT (0x7f << ATMEL_LCDC_GUARDT_OFFSET)
-+#define ATMEL_LCDC_BUSY (1 << 31)
-+
-+#define ATMEL_LCDC_CONTRAST_CTR 0x0840
-+#define ATMEL_LCDC_PS (3 << 0)
-+#define ATMEL_LCDC_PS_DIV1 (0 << 0)
-+#define ATMEL_LCDC_PS_DIV2 (1 << 0)
-+#define ATMEL_LCDC_PS_DIV4 (2 << 0)
-+#define ATMEL_LCDC_PS_DIV8 (3 << 0)
-+#define ATMEL_LCDC_POL (1 << 2)
-+#define ATMEL_LCDC_POL_NEGATIVE (0 << 2)
-+#define ATMEL_LCDC_POL_POSITIVE (1 << 2)
-+#define ATMEL_LCDC_ENA (1 << 3)
-+#define ATMEL_LCDC_ENA_PWMDISABLE (0 << 3)
-+#define ATMEL_LCDC_ENA_PWMENABLE (1 << 3)
-+
-+#define ATMEL_LCDC_CONTRAST_VAL 0x0844
-+#define ATMEL_LCDC_CVAL (0xff)
-+
-+#define ATMEL_LCDC_IER 0x0848
-+#define ATMEL_LCDC_IDR 0x084c
-+#define ATMEL_LCDC_IMR 0x0850
-+#define ATMEL_LCDC_ISR 0x0854
-+#define ATMEL_LCDC_ICR 0x0858
-+#define ATMEL_LCDC_LNI (1 << 0)
-+#define ATMEL_LCDC_LSTLNI (1 << 1)
-+#define ATMEL_LCDC_EOFI (1 << 2)
-+#define ATMEL_LCDC_UFLWI (1 << 4)
-+#define ATMEL_LCDC_OWRI (1 << 5)
-+#define ATMEL_LCDC_MERI (1 << 6)
-+
-+#define ATMEL_LCDC_LUT 0x0c00
-+
-+#endif /* __MACH_ATMEL_LCDC_H__ */
---- a/drivers/video/atmel_lcdfb.c
-+++ b/drivers/video/atmel_lcdfb.c
-@@ -19,8 +19,9 @@
-
- #include <mach/board.h>
- #include <mach/cpu.h>
-+#include <mach/atmel_lcdc.h>
-
--#include <video/atmel_lcdc.h>
-+#include <video/atmel_lcdfb.h>
-
- /* configurable parameters */
- #define ATMEL_LCDC_CVAL_DEFAULT 0xc8
---- a/drivers/video/atmel_lcdfb_core.c
-+++ b/drivers/video/atmel_lcdfb_core.c
-@@ -22,7 +22,7 @@
- #include <mach/cpu.h>
- #include <mach/gpio.h>
-
--#include <video/atmel_lcdc.h>
-+#include <video/atmel_lcdfb.h>
-
- /* configurable parameters */
- #define ATMEL_LCDC_CVAL_DEFAULT 0xc8
---- a/include/video/atmel_lcdc.h
-+++ /dev/null
-@@ -1,249 +0,0 @@
--/*
-- * Header file for AT91/AT32 LCD Controller
-- *
-- * Data structure and register user interface
-- *
-- * Copyright (C) 2007 Atmel Corporation
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-- */
--#ifndef __ATMEL_LCDC_H__
--#define __ATMEL_LCDC_H__
--
--#include <linux/workqueue.h>
--#include <linux/interrupt.h>
--#include <linux/backlight.h>
--
--/* Way LCD wires are connected to the chip:
-- * Some Atmel chips use BGR color mode (instead of standard RGB)
-- * A swapped wiring onboard can bring to RGB mode.
-- */
--#define ATMEL_LCDC_WIRING_BGR 0
--#define ATMEL_LCDC_WIRING_RGB 1
--#define ATMEL_LCDC_WIRING_RGB555 2
--
--#define ATMEL_LCDC_STOP_NOWAIT (1 << 0)
--
--extern void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo);
--extern void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo);
--extern int __atmel_lcdfb_probe(struct platform_device *pdev,
-- struct atmel_lcdfb_devdata *devdata);
--extern int __atmel_lcdfb_remove(struct platform_device *pdev);
--
--struct atmel_lcdfb_info;
--
--struct atmel_lcdfb_devdata {
-- int (*setup_core)(struct fb_info *info);
-- void (*start)(struct atmel_lcdfb_info *sinfo);
-- void (*stop)(struct atmel_lcdfb_info *sinfo, u32 flags);
-- irqreturn_t (*isr)(int irq, void *dev_id);
-- void (*update_dma)(struct fb_info *info, struct fb_var_screeninfo *var);
-- void (*init_contrast)(struct atmel_lcdfb_info *sinfo);
-- void (*limit_screeninfo)(struct fb_var_screeninfo *var);
-- const struct backlight_ops *bl_ops;
-- int fbinfo_flags;
-- u32 lut_base;
--};
--
-- /* LCD Controller info data structure, stored in device platform_data */
--struct atmel_lcdfb_info {
-- spinlock_t lock;
-- struct fb_info *info;
-- void __iomem *mmio;
-- int irq_base;
-- struct atmel_lcdfb_devdata *dev_data;
-- struct work_struct task;
--
-- unsigned int guard_time;
-- unsigned int smem_len;
-- struct platform_device *pdev;
-- struct clk *bus_clk;
-- struct clk *lcdc_clk;
--
--#ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
-- struct backlight_device *backlight;
-- u8 bl_power;
--#endif
-- bool lcdcon_is_backlight;
-- bool lcdcon_pol_negative;
-- bool alpha_enabled;
-- u8 saved_lcdcon;
--
-- u8 default_bpp;
-- u8 lcd_wiring_mode;
-- unsigned int default_lcdcon2;
-- unsigned int default_dmacon;
-- void (*atmel_lcdfb_power_control)(int on);
-- struct fb_monspecs *default_monspecs;
-- u32 pseudo_palette[16];
-- bool have_intensity_bit;
--};
--
--#define lcdc_readl(sinfo, reg) __raw_readl((sinfo)->mmio+(reg))
--#define lcdc_writel(sinfo, reg, val) __raw_writel((val), (sinfo)->mmio+(reg))
--
--#define ATMEL_LCDC_DMABADDR1 0x00
--#define ATMEL_LCDC_DMABADDR2 0x04
--#define ATMEL_LCDC_DMAFRMPT1 0x08
--#define ATMEL_LCDC_DMAFRMPT2 0x0c
--#define ATMEL_LCDC_DMAFRMADD1 0x10
--#define ATMEL_LCDC_DMAFRMADD2 0x14
--
--#define ATMEL_LCDC_DMAFRMCFG 0x18
--#define ATMEL_LCDC_FRSIZE (0x7fffff << 0)
--#define ATMEL_LCDC_BLENGTH_OFFSET 24
--#define ATMEL_LCDC_BLENGTH (0x7f << ATMEL_LCDC_BLENGTH_OFFSET)
--
--#define ATMEL_LCDC_DMACON 0x1c
--#define ATMEL_LCDC_DMAEN (0x1 << 0)
--#define ATMEL_LCDC_DMARST (0x1 << 1)
--#define ATMEL_LCDC_DMABUSY (0x1 << 2)
--#define ATMEL_LCDC_DMAUPDT (0x1 << 3)
--#define ATMEL_LCDC_DMA2DEN (0x1 << 4)
--
--#define ATMEL_LCDC_DMA2DCFG 0x20
--#define ATMEL_LCDC_ADDRINC_OFFSET 0
--#define ATMEL_LCDC_ADDRINC (0xffff)
--#define ATMEL_LCDC_PIXELOFF_OFFSET 24
--#define ATMEL_LCDC_PIXELOFF (0x1f << 24)
--
--#define ATMEL_LCDC_LCDCON1 0x0800
--#define ATMEL_LCDC_BYPASS (1 << 0)
--#define ATMEL_LCDC_CLKVAL_OFFSET 12
--#define ATMEL_LCDC_CLKVAL (0x1ff << ATMEL_LCDC_CLKVAL_OFFSET)
--#define ATMEL_LCDC_LINCNT (0x7ff << 21)
--
--#define ATMEL_LCDC_LCDCON2 0x0804
--#define ATMEL_LCDC_DISTYPE (3 << 0)
--#define ATMEL_LCDC_DISTYPE_STNMONO (0 << 0)
--#define ATMEL_LCDC_DISTYPE_STNCOLOR (1 << 0)
--#define ATMEL_LCDC_DISTYPE_TFT (2 << 0)
--#define ATMEL_LCDC_SCANMOD (1 << 2)
--#define ATMEL_LCDC_SCANMOD_SINGLE (0 << 2)
--#define ATMEL_LCDC_SCANMOD_DUAL (1 << 2)
--#define ATMEL_LCDC_IFWIDTH (3 << 3)
--#define ATMEL_LCDC_IFWIDTH_4 (0 << 3)
--#define ATMEL_LCDC_IFWIDTH_8 (1 << 3)
--#define ATMEL_LCDC_IFWIDTH_16 (2 << 3)
--#define ATMEL_LCDC_PIXELSIZE (7 << 5)
--#define ATMEL_LCDC_PIXELSIZE_1 (0 << 5)
--#define ATMEL_LCDC_PIXELSIZE_2 (1 << 5)
--#define ATMEL_LCDC_PIXELSIZE_4 (2 << 5)
--#define ATMEL_LCDC_PIXELSIZE_8 (3 << 5)
--#define ATMEL_LCDC_PIXELSIZE_16 (4 << 5)
--#define ATMEL_LCDC_PIXELSIZE_24 (5 << 5)
--#define ATMEL_LCDC_PIXELSIZE_32 (6 << 5)
--#define ATMEL_LCDC_INVVD (1 << 8)
--#define ATMEL_LCDC_INVVD_NORMAL (0 << 8)
--#define ATMEL_LCDC_INVVD_INVERTED (1 << 8)
--#define ATMEL_LCDC_INVFRAME (1 << 9 )
--#define ATMEL_LCDC_INVFRAME_NORMAL (0 << 9)
--#define ATMEL_LCDC_INVFRAME_INVERTED (1 << 9)
--#define ATMEL_LCDC_INVLINE (1 << 10)
--#define ATMEL_LCDC_INVLINE_NORMAL (0 << 10)
--#define ATMEL_LCDC_INVLINE_INVERTED (1 << 10)
--#define ATMEL_LCDC_INVCLK (1 << 11)
--#define ATMEL_LCDC_INVCLK_NORMAL (0 << 11)
--#define ATMEL_LCDC_INVCLK_INVERTED (1 << 11)
--#define ATMEL_LCDC_INVDVAL (1 << 12)
--#define ATMEL_LCDC_INVDVAL_NORMAL (0 << 12)
--#define ATMEL_LCDC_INVDVAL_INVERTED (1 << 12)
--#define ATMEL_LCDC_CLKMOD (1 << 15)
--#define ATMEL_LCDC_CLKMOD_ACTIVEDISPLAY (0 << 15)
--#define ATMEL_LCDC_CLKMOD_ALWAYSACTIVE (1 << 15)
--#define ATMEL_LCDC_MEMOR (1 << 31)
--#define ATMEL_LCDC_MEMOR_BIG (0 << 31)
--#define ATMEL_LCDC_MEMOR_LITTLE (1 << 31)
--
--#define ATMEL_LCDC_TIM1 0x0808
--#define ATMEL_LCDC_VFP (0xffU << 0)
--#define ATMEL_LCDC_VBP_OFFSET 8
--#define ATMEL_LCDC_VBP (0xffU << ATMEL_LCDC_VBP_OFFSET)
--#define ATMEL_LCDC_VPW_OFFSET 16
--#define ATMEL_LCDC_VPW (0x3fU << ATMEL_LCDC_VPW_OFFSET)
--#define ATMEL_LCDC_VHDLY_OFFSET 24
--#define ATMEL_LCDC_VHDLY (0xfU << ATMEL_LCDC_VHDLY_OFFSET)
--
--#define ATMEL_LCDC_TIM2 0x080c
--#define ATMEL_LCDC_HBP (0xffU << 0)
--#define ATMEL_LCDC_HPW_OFFSET 8
--#define ATMEL_LCDC_HPW (0x3fU << ATMEL_LCDC_HPW_OFFSET)
--#define ATMEL_LCDC_HFP_OFFSET 21
--#define ATMEL_LCDC_HFP (0x7ffU << ATMEL_LCDC_HFP_OFFSET)
--
--#define ATMEL_LCDC_LCDFRMCFG 0x0810
--#define ATMEL_LCDC_LINEVAL (0x7ff << 0)
--#define ATMEL_LCDC_HOZVAL_OFFSET 21
--#define ATMEL_LCDC_HOZVAL (0x7ff << ATMEL_LCDC_HOZVAL_OFFSET)
--
--#define ATMEL_LCDC_FIFO 0x0814
--#define ATMEL_LCDC_FIFOTH (0xffff)
--
--#define ATMEL_LCDC_MVAL 0x0818
--
--#define ATMEL_LCDC_DP1_2 0x081c
--#define ATMEL_LCDC_DP4_7 0x0820
--#define ATMEL_LCDC_DP3_5 0x0824
--#define ATMEL_LCDC_DP2_3 0x0828
--#define ATMEL_LCDC_DP5_7 0x082c
--#define ATMEL_LCDC_DP3_4 0x0830
--#define ATMEL_LCDC_DP4_5 0x0834
--#define ATMEL_LCDC_DP6_7 0x0838
--#define ATMEL_LCDC_DP1_2_VAL (0xff)
--#define ATMEL_LCDC_DP4_7_VAL (0xfffffff)
--#define ATMEL_LCDC_DP3_5_VAL (0xfffff)
--#define ATMEL_LCDC_DP2_3_VAL (0xfff)
--#define ATMEL_LCDC_DP5_7_VAL (0xfffffff)
--#define ATMEL_LCDC_DP3_4_VAL (0xffff)
--#define ATMEL_LCDC_DP4_5_VAL (0xfffff)
--#define ATMEL_LCDC_DP6_7_VAL (0xfffffff)
--
--#define ATMEL_LCDC_PWRCON 0x083c
--#define ATMEL_LCDC_PWR (1 << 0)
--#define ATMEL_LCDC_GUARDT_OFFSET 1
--#define ATMEL_LCDC_GUARDT (0x7f << ATMEL_LCDC_GUARDT_OFFSET)
--#define ATMEL_LCDC_BUSY (1 << 31)
--
--#define ATMEL_LCDC_CONTRAST_CTR 0x0840
--#define ATMEL_LCDC_PS (3 << 0)
--#define ATMEL_LCDC_PS_DIV1 (0 << 0)
--#define ATMEL_LCDC_PS_DIV2 (1 << 0)
--#define ATMEL_LCDC_PS_DIV4 (2 << 0)
--#define ATMEL_LCDC_PS_DIV8 (3 << 0)
--#define ATMEL_LCDC_POL (1 << 2)
--#define ATMEL_LCDC_POL_NEGATIVE (0 << 2)
--#define ATMEL_LCDC_POL_POSITIVE (1 << 2)
--#define ATMEL_LCDC_ENA (1 << 3)
--#define ATMEL_LCDC_ENA_PWMDISABLE (0 << 3)
--#define ATMEL_LCDC_ENA_PWMENABLE (1 << 3)
--
--#define ATMEL_LCDC_CONTRAST_VAL 0x0844
--#define ATMEL_LCDC_CVAL (0xff)
--
--#define ATMEL_LCDC_IER 0x0848
--#define ATMEL_LCDC_IDR 0x084c
--#define ATMEL_LCDC_IMR 0x0850
--#define ATMEL_LCDC_ISR 0x0854
--#define ATMEL_LCDC_ICR 0x0858
--#define ATMEL_LCDC_LNI (1 << 0)
--#define ATMEL_LCDC_LSTLNI (1 << 1)
--#define ATMEL_LCDC_EOFI (1 << 2)
--#define ATMEL_LCDC_UFLWI (1 << 4)
--#define ATMEL_LCDC_OWRI (1 << 5)
--#define ATMEL_LCDC_MERI (1 << 6)
--
--#define ATMEL_LCDC_LUT 0x0c00
--
--#endif /* __ATMEL_LCDC_H__ */
---- /dev/null
-+++ b/include/video/atmel_lcdfb.h
-@@ -0,0 +1,100 @@
-+/*
-+ * Header file for AT91/AT32 LCD Controller
-+ *
-+ * Data structure and register user interface
-+ *
-+ * Copyright (C) 2007 Atmel Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+#ifndef __ATMEL_LCDC_H__
-+#define __ATMEL_LCDC_H__
-+
-+#include <linux/workqueue.h>
-+#include <linux/interrupt.h>
-+#include <linux/backlight.h>
-+
-+/* Way LCD wires are connected to the chip:
-+ * Some Atmel chips use BGR color mode (instead of standard RGB)
-+ * A swapped wiring onboard can bring to RGB mode.
-+ */
-+#define ATMEL_LCDC_WIRING_BGR 0
-+#define ATMEL_LCDC_WIRING_RGB 1
-+#define ATMEL_LCDC_WIRING_RGB555 2
-+
-+#define ATMEL_LCDC_STOP_NOWAIT (1 << 0)
-+
-+struct atmel_lcdfb_info;
-+
-+struct atmel_lcdfb_devdata {
-+ int (*setup_core)(struct fb_info *info);
-+ void (*start)(struct atmel_lcdfb_info *sinfo);
-+ void (*stop)(struct atmel_lcdfb_info *sinfo, u32 flags);
-+ irqreturn_t (*isr)(int irq, void *dev_id);
-+ void (*update_dma)(struct fb_info *info, struct fb_var_screeninfo *var);
-+ void (*init_contrast)(struct atmel_lcdfb_info *sinfo);
-+ void (*limit_screeninfo)(struct fb_var_screeninfo *var);
-+ const struct backlight_ops *bl_ops;
-+ int fbinfo_flags;
-+ u32 lut_base;
-+ int dma_desc_size;
-+};
-+
-+extern void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo);
-+extern void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo);
-+extern int __atmel_lcdfb_probe(struct platform_device *pdev,
-+ struct atmel_lcdfb_devdata *devdata);
-+extern int __atmel_lcdfb_remove(struct platform_device *pdev);
-+
-+ /* LCD Controller info data structure, stored in device platform_data */
-+struct atmel_lcdfb_info {
-+ spinlock_t lock;
-+ struct fb_info *info;
-+ void __iomem *mmio;
-+ int irq_base;
-+ struct atmel_lcdfb_devdata *dev_data;
-+ struct work_struct task;
-+
-+ void *dma_desc;
-+ dma_addr_t dma_desc_phys;
-+
-+ unsigned int guard_time;
-+ unsigned int smem_len;
-+ struct platform_device *pdev;
-+ struct clk *bus_clk;
-+ struct clk *lcdc_clk;
-+
-+#ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
-+ struct backlight_device *backlight;
-+ u8 bl_power;
-+#endif
-+ bool lcdcon_is_backlight;
-+ bool lcdcon_pol_negative;
-+ bool alpha_enabled;
-+ u8 saved_lcdcon;
-+
-+ u8 default_bpp;
-+ u8 lcd_wiring_mode;
-+ unsigned int default_lcdcon2;
-+ unsigned int default_dmacon;
-+ void (*atmel_lcdfb_power_control)(int on);
-+ struct fb_monspecs *default_monspecs;
-+ u32 pseudo_palette[16];
-+};
-+
-+#define lcdc_readl(sinfo, reg) __raw_readl((sinfo)->mmio+(reg))
-+#define lcdc_writel(sinfo, reg, val) __raw_writel((val), (sinfo)->mmio+(reg))
-+
-+#endif /* __ATMEL_LCDC_H__ */
+++ /dev/null
-From 3ceb9c35a7c43f0762c0a857a49a3633fef821fd Mon Sep 17 00:00:00 2001
-From: Wolfram Sang <w.sang@pengutronix.de>
-Date: Mon, 23 May 2011 15:36:52 +0200
-Subject: video: atmel_hlcdfb: add new driver
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
----
- drivers/video/Kconfig | 9 +
- drivers/video/Makefile | 1 +
- drivers/video/atmel_hlcdfb.c | 514 +++++++++++++++++++++++++++++++++++++++
- drivers/video/atmel_lcdfb_core.c | 15 ++
- 4 files changed, 539 insertions(+)
- create mode 100644 drivers/video/atmel_hlcdfb.c
-
-diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
-index a290be5..ceccaa3 100644
---- a/drivers/video/Kconfig
-+++ b/drivers/video/Kconfig
-@@ -1028,6 +1028,15 @@ config FB_ATMEL_STN
-
- If unsure, say N.
-
-+config FB_ATMEL_HLCD
-+ tristate "AT91 HLCD Controller support"
-+ depends on FB && HAVE_FB_ATMEL
-+ select FB_CFB_FILLRECT
-+ select FB_CFB_COPYAREA
-+ select FB_CFB_IMAGEBLIT
-+ help
-+ This enables support for the AT91 HLCD Controller.
-+
- config FB_NVIDIA
- tristate "nVidia Framebuffer Support"
- depends on FB && PCI
-diff --git a/drivers/video/Makefile b/drivers/video/Makefile
-index 37c5625..36320ea 100644
---- a/drivers/video/Makefile
-+++ b/drivers/video/Makefile
-@@ -96,6 +96,7 @@ obj-$(CONFIG_FB_SA1100) += sa1100fb.o
- obj-$(CONFIG_FB_HIT) += hitfb.o
- obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o
- obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o atmel_lcdfb_core.o
-+obj-$(CONFIG_FB_ATMEL_HLCD) += atmel_hlcdfb.o atmel_lcdfb_core.o
- obj-$(CONFIG_FB_PVR2) += pvr2fb.o
- obj-$(CONFIG_FB_VOODOO1) += sstfb.o
- obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o
-diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c
-new file mode 100644
-index 0000000..b772841
---- /dev/null
-+++ b/drivers/video/atmel_hlcdfb.c
-@@ -0,0 +1,514 @@
-+/*
-+ * Driver for AT91/AT32 LCD Controller
-+ *
-+ * Copyright (C) 2007 Atmel Corporation
-+ *
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file COPYING in the main directory of this archive for
-+ * more details.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/platform_device.h>
-+#include <linux/interrupt.h>
-+#include <linux/backlight.h>
-+#include <linux/fb.h>
-+#include <linux/clk.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+
-+#include <mach/board.h>
-+#include <mach/cpu.h>
-+#include <mach/atmel_hlcdc.h>
-+#include <mach/atmel_hlcdc_ovl.h>
-+
-+#include <video/atmel_lcdfb.h>
-+
-+#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
-+ | FBINFO_PARTIAL_PAN_OK \
-+ | FBINFO_HWACCEL_YPAN)
-+
-+#define ATMEL_LCDC_CVAL_DEFAULT 0xc8
-+
-+struct atmel_hlcd_dma_desc {
-+ u32 address;
-+ u32 control;
-+ u32 next;
-+};
-+
-+static void atmel_hlcdfb_update_dma_base(struct fb_info *info,
-+
-+ struct fb_var_screeninfo *var)
-+{
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ struct fb_fix_screeninfo *fix = &info->fix;
-+ unsigned long dma_addr;
-+ struct atmel_hlcd_dma_desc *desc;
-+
-+ dma_addr = (fix->smem_start + var->yoffset * fix->line_length
-+ + var->xoffset * var->bits_per_pixel / 8);
-+
-+ dma_addr &= ~3UL;
-+
-+ /* Setup the DMA descriptor, this descriptor will loop to itself */
-+ desc = sinfo->dma_desc;
-+
-+ desc->address = dma_addr;
-+ /* Disable DMA transfer interrupt & descriptor loaded interrupt. */
-+ desc->control = LCDC_BASECTRL_ADDIEN | LCDC_BASECTRL_DSCRIEN
-+ | LCDC_BASECTRL_DMAIEN | LCDC_BASECTRL_DFETCH;
-+ desc->next = sinfo->dma_desc_phys;
-+
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASEADDR, dma_addr);
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASECTRL, desc->control);
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASENEXT, sinfo->dma_desc_phys);
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASECHER, LCDC_BASECHER_CHEN | LCDC_BASECHER_UPDATEEN);
-+}
-+
-+static void atmel_hlcdfb_update_dma_ovl(struct fb_info *info,
-+ struct fb_var_screeninfo *var)
-+{
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ struct fb_fix_screeninfo *fix = &info->fix;
-+ unsigned long dma_addr;
-+ struct atmel_hlcd_dma_desc *desc;
-+
-+ dma_addr = (fix->smem_start + var->yoffset * fix->line_length
-+ + var->xoffset * var->bits_per_pixel / 8);
-+
-+ dma_addr &= ~3UL;
-+
-+ /* Setup the DMA descriptor, this descriptor will loop to itself */
-+ desc = sinfo->dma_desc;
-+
-+ desc->address = dma_addr;
-+ /* Disable DMA transfer interrupt & descriptor loaded interrupt. */
-+ desc->control = LCDC_OVRCTRL1_ADDIEN | LCDC_OVRCTRL1_DSCRIEN
-+ | LCDC_OVRCTRL1_DMAIEN | LCDC_OVRCTRL1_DFETCH;
-+ desc->next = sinfo->dma_desc_phys;
-+
-+ lcdc_writel(sinfo, ATMEL_LCDC_OVRADDR1, dma_addr);
-+ lcdc_writel(sinfo, ATMEL_LCDC_OVRCTRL1, desc->control);
-+ lcdc_writel(sinfo, ATMEL_LCDC_OVRNEXT1, sinfo->dma_desc_phys);
-+ lcdc_writel(sinfo, ATMEL_LCDC_OVRCHER1, LCDC_OVRCHER1_CHEN | LCDC_OVRCHER1_UPDATEEN);
-+}
-+
-+/* some bl->props field just changed */
-+static int atmel_bl_update_status(struct backlight_device *bl)
-+{
-+ struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
-+ int power = sinfo->bl_power;
-+ int brightness = bl->props.brightness;
-+ u32 reg;
-+
-+ /* REVISIT there may be a meaningful difference between
-+ * fb_blank and power ... there seem to be some cases
-+ * this doesn't handle correctly.
-+ */
-+ if (bl->props.fb_blank != sinfo->bl_power)
-+ power = bl->props.fb_blank;
-+ else if (bl->props.power != sinfo->bl_power)
-+ power = bl->props.power;
-+
-+ if (brightness < 0 && power == FB_BLANK_UNBLANK)
-+ brightness = lcdc_readl(sinfo, ATMEL_LCDC_LCDCFG6)
-+ >> LCDC_LCDCFG6_PWMCVAL_OFFSET;
-+ else if (power != FB_BLANK_UNBLANK)
-+ brightness = 0;
-+
-+ reg = lcdc_readl(sinfo, ATMEL_LCDC_LCDCFG6) & ~LCDC_LCDCFG6_PWMCVAL;
-+ reg |= brightness << LCDC_LCDCFG6_PWMCVAL_OFFSET;
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG6, reg);
-+
-+ bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;
-+
-+ return 0;
-+}
-+
-+static int atmel_bl_get_brightness(struct backlight_device *bl)
-+{
-+ struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
-+
-+ return lcdc_readl(sinfo, ATMEL_LCDC_LCDCFG6) >> LCDC_LCDCFG6_PWMCVAL_OFFSET;
-+}
-+
-+static const struct backlight_ops atmel_hlcdc_bl_ops = {
-+ .update_status = atmel_bl_update_status,
-+ .get_brightness = atmel_bl_get_brightness,
-+};
-+
-+static void atmel_hlcdfb_init_contrast(struct atmel_lcdfb_info *sinfo)
-+{
-+ /* have some default contrast/backlight settings */
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG6, LCDC_LCDCFG6_PWMPOL |
-+ (ATMEL_LCDC_CVAL_DEFAULT << LCDC_LCDCFG6_PWMCVAL_OFFSET));
-+}
-+
-+void atmel_hlcdfb_start(struct atmel_lcdfb_info *sinfo)
-+{
-+ u32 value;
-+
-+ value = lcdc_readl(sinfo, ATMEL_LCDC_LCDEN);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDEN, value | LCDC_LCDEN_CLKEN);
-+ while (!(lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_CLKSTS))
-+ msleep(1);
-+ value = lcdc_readl(sinfo, ATMEL_LCDC_LCDEN);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDEN, value | LCDC_LCDEN_SYNCEN);
-+ while (!(lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_LCDSTS))
-+ msleep(1);
-+ value = lcdc_readl(sinfo, ATMEL_LCDC_LCDEN);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDEN, value | LCDC_LCDEN_DISPEN);
-+ while (!(lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_DISPSTS))
-+ msleep(1);
-+ value = lcdc_readl(sinfo, ATMEL_LCDC_LCDEN);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDEN, value | LCDC_LCDEN_PWMEN);
-+ while (!(lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_PWMSTS))
-+ msleep(1);
-+}
-+
-+static void atmel_hlcdfb_stop(struct atmel_lcdfb_info *sinfo, u32 flags)
-+{
-+ /* Disable DISP signal */
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_DISPDIS);
-+ while ((lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_DISPSTS))
-+ msleep(1);
-+ /* Disable synchronization */
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_SYNCDIS);
-+ while ((lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_LCDSTS))
-+ msleep(1);
-+ /* Disable pixel clock */
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_CLKDIS);
-+ while ((lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_CLKSTS))
-+ msleep(1);
-+ /* Disable PWM */
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDDIS, LCDC_LCDDIS_PWMDIS);
-+ while ((lcdc_readl(sinfo, ATMEL_LCDC_LCDSR) & LCDC_LCDSR_PWMSTS))
-+ msleep(1);
-+
-+ if (!(flags & ATMEL_LCDC_STOP_NOWAIT))
-+ /* Wait for the end of DMA transfer */
-+ while (!(lcdc_readl(sinfo, ATMEL_LCDC_BASEISR) & LCDC_BASEISR_DMA))
-+ msleep(10);
-+ //FIXME: OVL DMA?
-+}
-+
-+static u32 atmel_hlcdfb_get_rgbmode(struct fb_info *info)
-+{
-+ u32 value = 0;
-+
-+ switch (info->var.bits_per_pixel) {
-+ case 1:
-+ value = LCDC_BASECFG1_CLUTMODE_1BPP | LCDC_BASECFG1_CLUTEN;
-+ break;
-+ case 2:
-+ value = LCDC_BASECFG1_CLUTMODE_2BPP | LCDC_BASECFG1_CLUTEN;
-+ break;
-+ case 4:
-+ value = LCDC_BASECFG1_CLUTMODE_4BPP | LCDC_BASECFG1_CLUTEN;
-+ break;
-+ case 8:
-+ value = LCDC_BASECFG1_CLUTMODE_8BPP | LCDC_BASECFG1_CLUTEN;
-+ break;
-+ case 12:
-+ value = LCDC_BASECFG1_RGBMODE_12BPP_RGB_444;
-+ break;
-+ case 16:
-+ if (info->var.transp.offset)
-+ value = LCDC_BASECFG1_RGBMODE_16BPP_ARGB_4444;
-+ else
-+ value = LCDC_BASECFG1_RGBMODE_16BPP_RGB_565;
-+ break;
-+ case 18:
-+ value = LCDC_BASECFG1_RGBMODE_18BPP_RGB_666_PACKED;
-+ break;
-+ case 24:
-+ value = LCDC_BASECFG1_RGBMODE_24BPP_RGB_888_PACKED;
-+ break;
-+ case 32:
-+ value = LCDC_BASECFG1_RGBMODE_32BPP_ARGB_8888;
-+ break;
-+ default:
-+ dev_err(info->device, "Cannot set video mode for %dbpp\n",
-+ info->var.bits_per_pixel);
-+ break;
-+ }
-+
-+ return value;
-+}
-+
-+static int atmel_hlcdfb_setup_core_base(struct fb_info *info)
-+{
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ unsigned long value;
-+ unsigned long clk_value_khz;
-+
-+ dev_dbg(info->device, "%s:\n", __func__);
-+ /* Set pixel clock */
-+ clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
-+
-+ value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock));
-+
-+ if (value < 1) {
-+ dev_notice(info->device, "using system clock as pixel clock\n");
-+ value = LCDC_LCDCFG0_CLKPOL | LCDC_LCDCFG0_CLKPWMSEL | LCDC_LCDCFG0_CGDISBASE;
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG0, value);
-+ } else {
-+ info->var.pixclock = KHZ2PICOS(clk_value_khz / value);
-+ dev_dbg(info->device, " updated pixclk: %lu KHz\n",
-+ PICOS2KHZ(info->var.pixclock));
-+ value = value - 2;
-+ dev_dbg(info->device, " * programming CLKDIV = 0x%08lx\n",
-+ value);
-+ value = (value << LCDC_LCDCFG0_CLKDIV_OFFSET)
-+ | LCDC_LCDCFG0_CLKPOL
-+ | LCDC_LCDCFG0_CGDISBASE;
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG0, value);
-+ }
-+
-+ /* Initialize control register 5 */
-+ /* In 9x5, the default_lcdcon2 will use for LCDCFG5 */
-+ value = sinfo->default_lcdcon2;
-+ value |= (sinfo->guard_time << LCDC_LCDCFG5_GUARDTIME_OFFSET)
-+ | LCDC_LCDCFG5_DISPDLY
-+ | LCDC_LCDCFG5_VSPDLYS;
-+
-+ if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
-+ value |= LCDC_LCDCFG5_HSPOL;
-+ if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
-+ value |= LCDC_LCDCFG5_VSPOL;
-+
-+ dev_dbg(info->device, " * LCDC_LCDCFG5 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG5, value);
-+
-+ /* Vertical & Horizontal Timing */
-+ value = (info->var.vsync_len - 1) << LCDC_LCDCFG1_VSPW_OFFSET;
-+ value |= (info->var.hsync_len - 1) << LCDC_LCDCFG1_HSPW_OFFSET;
-+ dev_dbg(info->device, " * LCDC_LCDCFG1 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG1, value);
-+
-+ value = (info->var.lower_margin) << LCDC_LCDCFG2_VBPW_OFFSET;
-+ value |= (info->var.upper_margin - 1) << LCDC_LCDCFG2_VFPW_OFFSET;
-+ dev_dbg(info->device, " * LCDC_LCDCFG2 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG2, value);
-+
-+ value = (info->var.right_margin - 1) << LCDC_LCDCFG3_HBPW_OFFSET;
-+ value |= (info->var.left_margin - 1) << LCDC_LCDCFG3_HFPW_OFFSET;
-+ dev_dbg(info->device, " * LCDC_LCDCFG3 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG3, value);
-+
-+ /* Display size */
-+ value = (info->var.yres - 1) << LCDC_LCDCFG4_RPF_OFFSET;
-+ value |= (info->var.xres - 1) << LCDC_LCDCFG4_PPL_OFFSET;
-+ dev_dbg(info->device, " * LCDC_LCDCFG4 = %08lx\n", value);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG4, value);
-+
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASECFG0, LCDC_BASECFG0_BLEN_AHB_INCR4 | LCDC_BASECFG0_DLBO);
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASECFG1, atmel_hlcdfb_get_rgbmode(info));
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASECFG2, 0);
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASECFG3, 0); /* Default color */
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASECFG4, LCDC_BASECFG4_DMA);
-+
-+ /* Disable all interrupts */
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDIDR, ~0UL);
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASEIDR, ~0UL);
-+ /* Enable BASE LAYER overflow interrupts, if want to enable DMA interrupt, also need set it at LCDC_BASECTRL reg */
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASEIER, LCDC_BASEIER_OVR);
-+ //FIXME: Let video-driver register a callback
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDIER, LCDC_LCDIER_FIFOERRIE |
-+ LCDC_LCDIER_BASEIE | LCDC_LCDIER_HEOIE);
-+
-+ return 0;
-+}
-+
-+static int atmel_hlcdfb_setup_core_ovl(struct fb_info *info)
-+{
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ u32 xpos, ypos, xres, yres, cfg9;
-+
-+ if (info->var.nonstd >> 31) {
-+ xpos = (info->var.nonstd >> 10) & 0x3ff;
-+ ypos = info->var.nonstd & 0x3ff;
-+ xres = info->var.xres ? info->var.xres - 1 : 0;
-+ yres = info->var.yres ? info->var.yres - 1 : 0;
-+ cfg9 = LCDC_OVR1CFG9_DMA | LCDC_OVR1CFG9_OVR |
-+ LCDC_OVR1CFG9_ITER | LCDC_OVR1CFG9_ITER2BL |
-+ LCDC_OVR1CFG9_REP;
-+ if (info->var.transp.offset)
-+ cfg9 |= LCDC_OVR1CFG9_LAEN;
-+ else
-+ cfg9 |= LCDC_OVR1CFG9_GAEN | LCDC_OVR1CFG9_GA;
-+ } else {
-+ xpos = ypos = yres = xres = cfg9 = 0;
-+ }
-+
-+ lcdc_writel(sinfo, ATMEL_LCDC_OVR1CFG0,
-+ LCDC_OVR1CFG0_BLEN_AHB_INCR4 | LCDC_OVR1CFG0_DLBO);
-+ lcdc_writel(sinfo, ATMEL_LCDC_OVR1CFG1,
-+ atmel_hlcdfb_get_rgbmode(info));
-+ lcdc_writel(sinfo, ATMEL_LCDC_OVR1CFG2, xpos |
-+ (ypos << LCDC_OVR1CFG2_YOFFSET_OFFSET));
-+ lcdc_writel(sinfo, ATMEL_LCDC_OVR1CFG3, xres |
-+ (yres << LCDC_OVR1CFG3_YSIZE_OFFSET));
-+ lcdc_writel(sinfo, ATMEL_LCDC_OVR1CFG9, cfg9);
-+
-+ return 0;
-+}
-+static void atmelfb_limit_screeninfo(struct fb_var_screeninfo *var)
-+{
-+ /* Saturate vertical and horizontal timings at maximum values */
-+ var->vsync_len = min_t(u32, var->vsync_len,
-+ (LCDC_LCDCFG1_VSPW >> LCDC_LCDCFG1_VSPW_OFFSET) + 1);
-+ var->upper_margin = min_t(u32, var->upper_margin,
-+ (LCDC_LCDCFG2_VFPW >> LCDC_LCDCFG2_VFPW_OFFSET) + 1);
-+ var->lower_margin = min_t(u32, var->lower_margin,
-+ LCDC_LCDCFG2_VBPW >> LCDC_LCDCFG2_VBPW_OFFSET);
-+ var->right_margin = min_t(u32, var->right_margin,
-+ (LCDC_LCDCFG3_HBPW >> LCDC_LCDCFG3_HBPW_OFFSET) + 1);
-+ var->hsync_len = min_t(u32, var->hsync_len,
-+ (LCDC_LCDCFG1_HSPW >> LCDC_LCDCFG1_HSPW_OFFSET) + 1);
-+ var->left_margin = min_t(u32, var->left_margin,
-+ (LCDC_LCDCFG3_HFPW >> LCDC_LCDCFG3_HFPW_OFFSET) + 1);
-+
-+}
-+
-+static irqreturn_t atmel_hlcdfb_interrupt(int irq, void *dev_id)
-+{
-+ struct fb_info *info = dev_id;
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+ u32 status, baselayer_status;
-+
-+ /* Check for error status via interrupt.*/
-+ status = lcdc_readl(sinfo, ATMEL_LCDC_LCDISR);
-+ if (status & LCDC_LCDISR_HEO)
-+ return IRQ_NONE;
-+
-+ if (status & LCDC_LCDISR_FIFOERR)
-+ dev_warn(info->device, "FIFO underflow %#x\n", status);
-+
-+ if (status & LCDC_LCDISR_BASE) {
-+ /* Check base layer's overflow error. */
-+ baselayer_status = lcdc_readl(sinfo, ATMEL_LCDC_BASEISR);
-+
-+ if (baselayer_status & LCDC_BASEISR_OVR)
-+ dev_warn(info->device, "base layer overflow %#x\n",
-+ baselayer_status);
-+ }
-+
-+ return IRQ_HANDLED;
-+}
-+
-+
-+#ifdef CONFIG_PM
-+
-+static int atmel_hlcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
-+{
-+ struct fb_info *info = platform_get_drvdata(pdev);
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+
-+ /*
-+ * We don't want to handle interrupts while the clock is
-+ * stopped. It may take forever.
-+ */
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDIDR, ~0UL);
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASEIDR, ~0UL);
-+
-+ if (sinfo->atmel_lcdfb_power_control)
-+ sinfo->atmel_lcdfb_power_control(0);
-+
-+ atmel_hlcdfb_stop(sinfo, 0);
-+ atmel_lcdfb_stop_clock(sinfo);
-+
-+ return 0;
-+}
-+
-+static int atmel_hlcdfb_resume(struct platform_device *pdev)
-+{
-+ struct fb_info *info = platform_get_drvdata(pdev);
-+ struct atmel_lcdfb_info *sinfo = info->par;
-+
-+ atmel_lcdfb_start_clock(sinfo);
-+ atmel_hlcdfb_start(sinfo);
-+ if (sinfo->atmel_lcdfb_power_control)
-+ sinfo->atmel_lcdfb_power_control(1);
-+
-+ /* Enable fifo error & BASE LAYER overflow interrupts */
-+ lcdc_writel(sinfo, ATMEL_LCDC_BASEIER, LCDC_BASEIER_OVR);
-+ lcdc_writel(sinfo, ATMEL_LCDC_LCDIER, LCDC_LCDIER_FIFOERRIE |
-+ LCDC_LCDIER_BASEIE | LCDC_LCDIER_HEOIE);
-+
-+ return 0;
-+}
-+
-+#else
-+#define atmel_hlcdfb_suspend NULL
-+#define atmel_hlcdfb_resume NULL
-+#endif
-+
-+static struct atmel_lcdfb_devdata dev_data_base = {
-+ .setup_core = atmel_hlcdfb_setup_core_base,
-+ .start = atmel_hlcdfb_start,
-+ .stop = atmel_hlcdfb_stop,
-+ .isr = atmel_hlcdfb_interrupt,
-+ .update_dma = atmel_hlcdfb_update_dma_base,
-+ .bl_ops = &atmel_hlcdc_bl_ops,
-+ .init_contrast = atmel_hlcdfb_init_contrast,
-+ .limit_screeninfo = atmelfb_limit_screeninfo,
-+ .fbinfo_flags = ATMEL_LCDFB_FBINFO_DEFAULT,
-+ .lut_base = ATMEL_HLCDC_LUT,
-+ .dma_desc_size = sizeof(struct atmel_hlcd_dma_desc),
-+};
-+
-+static struct atmel_lcdfb_devdata dev_data_ovl = {
-+ .setup_core = atmel_hlcdfb_setup_core_ovl,
-+ .update_dma = atmel_hlcdfb_update_dma_ovl,
-+ .limit_screeninfo = atmelfb_limit_screeninfo,
-+ .fbinfo_flags = ATMEL_LCDFB_FBINFO_DEFAULT,
-+ .lut_base = 0x800, //FIXME: add define
-+ .dma_desc_size = sizeof(struct atmel_hlcd_dma_desc),
-+};
-+
-+static const struct platform_device_id atmelfb_dev_table[] = {
-+ { "atmel_hlcdfb_base", (kernel_ulong_t)&dev_data_base },
-+ { "atmel_hlcdfb_ovl", (kernel_ulong_t)&dev_data_ovl },
-+}
-+MODULE_DEVICE_TABLE(platform, atmelfb_dev_table);
-+
-+static int __init atmel_hlcdfb_probe(struct platform_device *pdev)
-+{
-+ const struct platform_device_id *id = platform_get_device_id(pdev);
-+
-+ return __atmel_lcdfb_probe(pdev, (struct atmel_lcdfb_devdata *)id->driver_data);
-+}
-+static int __exit atmel_hlcdfb_remove(struct platform_device *pdev)
-+{
-+ return __atmel_lcdfb_remove(pdev);
-+}
-+
-+static struct platform_driver atmel_hlcdfb_driver = {
-+ .remove = __exit_p(atmel_hlcdfb_remove),
-+ .suspend = atmel_hlcdfb_suspend,
-+ .resume = atmel_hlcdfb_resume,
-+
-+ .driver = {
-+ .name = "atmel_hlcdfb",
-+ .owner = THIS_MODULE,
-+ },
-+ .id_table = atmelfb_dev_table,
-+};
-+
-+static int __init atmel_hlcdfb_init(void)
-+{
-+ return platform_driver_probe(&atmel_hlcdfb_driver, atmel_hlcdfb_probe);
-+}
-+module_init(atmel_hlcdfb_init);
-+
-+static void __exit atmel_hlcdfb_exit(void)
-+{
-+ platform_driver_unregister(&atmel_hlcdfb_driver);
-+}
-+module_exit(atmel_hlcdfb_exit);
-+
-+MODULE_DESCRIPTION("AT91 HLCD Controller framebuffer driver");
-+MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com> "
-+ "and Wolfram Sang <w.sang@pengutronix.de");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c
-index 060d41f..cd57361 100644
---- a/drivers/video/atmel_lcdfb_core.c
-+++ b/drivers/video/atmel_lcdfb_core.c
-@@ -90,6 +90,10 @@ static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
-
- dma_free_writecombine(info->device, info->fix.smem_len,
- info->screen_base, info->fix.smem_start);
-+
-+ if (sinfo->dev_data->dma_desc_size && sinfo->dma_desc)
-+ dma_free_writecombine(info->device, sinfo->dev_data->dma_desc_size,
-+ sinfo->dma_desc, sinfo->dma_desc_phys);
- }
-
- /**
-@@ -118,6 +122,17 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
-
- memset(info->screen_base, 0, info->fix.smem_len);
-
-+ if (sinfo->dev_data->dma_desc_size) {
-+ sinfo->dma_desc = dma_alloc_writecombine(info->device,
-+ sinfo->dev_data->dma_desc_size,
-+ &(sinfo->dma_desc_phys), GFP_KERNEL);
-+
-+ if (!sinfo->dma_desc) {
-+ dma_free_writecombine(info->device, info->fix.smem_len,
-+ info->screen_base, info->fix.smem_start);
-+ return -ENOMEM;
-+ }
-+ }
- return 0;
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b1afedb79996e6e81b696c380a170564bf0aec72 Mon Sep 17 00:00:00 2001
-From: Wolfram Sang <w.sang@pengutronix.de>
-Date: Mon, 30 May 2011 17:04:35 +0200
-Subject: WIP: add clut resource
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Warning: will currently break old AT91-boards!
-
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
----
- drivers/video/atmel_hlcdfb.c | 2 --
- drivers/video/atmel_lcdfb.c | 1 -
- drivers/video/atmel_lcdfb_core.c | 35 ++++++++++++++++++++++++++---------
- include/video/atmel_lcdfb.h | 2 +-
- 4 files changed, 27 insertions(+), 13 deletions(-)
-
-diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c
-index b772841..346bb80 100644
---- a/drivers/video/atmel_hlcdfb.c
-+++ b/drivers/video/atmel_hlcdfb.c
-@@ -454,7 +454,6 @@ static struct atmel_lcdfb_devdata dev_data_base = {
- .init_contrast = atmel_hlcdfb_init_contrast,
- .limit_screeninfo = atmelfb_limit_screeninfo,
- .fbinfo_flags = ATMEL_LCDFB_FBINFO_DEFAULT,
-- .lut_base = ATMEL_HLCDC_LUT,
- .dma_desc_size = sizeof(struct atmel_hlcd_dma_desc),
- };
-
-@@ -463,7 +462,6 @@ static struct atmel_lcdfb_devdata dev_data_ovl = {
- .update_dma = atmel_hlcdfb_update_dma_ovl,
- .limit_screeninfo = atmelfb_limit_screeninfo,
- .fbinfo_flags = ATMEL_LCDFB_FBINFO_DEFAULT,
-- .lut_base = 0x800, //FIXME: add define
- .dma_desc_size = sizeof(struct atmel_hlcd_dma_desc),
- };
-
-diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
-index 8d7992c..402cb24 100644
---- a/drivers/video/atmel_lcdfb.c
-+++ b/drivers/video/atmel_lcdfb.c
-@@ -399,7 +399,6 @@ static struct atmel_lcdfb_devdata dev_data = {
- .init_contrast = atmel_lcdfb_init_contrast,
- .limit_screeninfo = atmelfb_limit_screeninfo,
- .fbinfo_flags = ATMEL_LCDFB_FBINFO_DEFAULT,
-- .lut_base = ATMEL_LCDC_LUT,
- };
-
- static int __init atmel_lcdfb_probe(struct platform_device *pdev)
-diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c
-index cd57361..89d974a 100644
---- a/drivers/video/atmel_lcdfb_core.c
-+++ b/drivers/video/atmel_lcdfb_core.c
-@@ -426,9 +426,7 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
- * TODO: intensity bit. Maybe something like
- * ~(red[10] ^ green[10] ^ blue[10]) & 1
- */
--
-- lcdc_writel(sinfo, sinfo->dev_data->lut_base + regno * 4,
-- val);
-+ writel(val, sinfo->clut + regno * 4);
- ret = 0;
- }
- break;
-@@ -436,8 +434,7 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
- case FB_VISUAL_MONO01:
- if (regno < 2) {
- val = (regno == 0) ? 0x00 : 0x1F;
-- lcdc_writel(sinfo, sinfo->dev_data->lut_base + regno * 4,
-- val);
-+ writel(val, sinfo->clut + regno * 4);
- ret = 0;
- }
- break;
-@@ -553,7 +550,7 @@ int __atmel_lcdfb_probe(struct platform_device *pdev,
- struct atmel_lcdfb_info *sinfo;
- struct atmel_lcdfb_info *pdata_sinfo;
- struct fb_videomode fbmode;
-- struct resource *regs = NULL;
-+ struct resource *regs = NULL, *clut = NULL;
- struct resource *map = NULL;
- int ret;
-
-@@ -628,11 +625,19 @@ int __atmel_lcdfb_probe(struct platform_device *pdev,
- goto stop_clk;
- }
-
-+ clut = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+ if (!clut) {
-+ dev_err(dev, "clut resources unusable\n");
-+ ret = -ENXIO;
-+ goto stop_clk;
-+ }
-+
- /* No error checking, some devices can do without IRQ */
- sinfo->irq_base = platform_get_irq(pdev, 0);
-
- /* Initialize video memory */
-- map = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+ //FIXME: Fix LUTs for old platforms
-+ map = platform_get_resource(pdev, IORESOURCE_MEM, 2);
- if (map) {
- /* use a pre-allocated memory buffer */
- info->fix.smem_start = map->start;
-@@ -676,6 +681,17 @@ int __atmel_lcdfb_probe(struct platform_device *pdev,
- goto release_mem;
- }
-
-+ //FIXME: proper request_region and cleanup
-+ if (!request_mem_region(clut->start, resource_size(clut), pdev->name)) {
-+ ret = -EBUSY;
-+ goto unmap_mmio;
-+ }
-+ sinfo->clut = ioremap(clut->start, resource_size(clut));
-+ if (!sinfo->clut) {
-+ dev_err(dev, "cannot map CLUT\n");
-+ goto unmap_mmio;
-+ }
-+
- /* Initialize PWM for contrast or backlight ("off") */
- if (sinfo->dev_data->init_contrast)
- sinfo->dev_data->init_contrast(sinfo);
-@@ -688,7 +704,7 @@ int __atmel_lcdfb_probe(struct platform_device *pdev,
- IRQF_SHARED, pdev->name, info);
- if (ret) {
- dev_err(dev, "request_irq failed: %d\n", ret);
-- goto unmap_mmio;
-+ goto clear_backlight;
- }
- }
-
-@@ -746,8 +762,9 @@ unregister_irqs:
- cancel_work_sync(&sinfo->task);
- if (sinfo->irq_base >= 0)
- free_irq(sinfo->irq_base, info);
--unmap_mmio:
-+clear_backlight:
- exit_backlight(sinfo);
-+unmap_mmio:
- iounmap(sinfo->mmio);
- release_mem:
- release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
-diff --git a/include/video/atmel_lcdfb.h b/include/video/atmel_lcdfb.h
-index 3a0dfc7..a9563b8 100644
---- a/include/video/atmel_lcdfb.h
-+++ b/include/video/atmel_lcdfb.h
-@@ -48,7 +48,6 @@ struct atmel_lcdfb_devdata {
- void (*limit_screeninfo)(struct fb_var_screeninfo *var);
- const struct backlight_ops *bl_ops;
- int fbinfo_flags;
-- u32 lut_base;
- int dma_desc_size;
- };
-
-@@ -63,6 +62,7 @@ struct atmel_lcdfb_info {
- spinlock_t lock;
- struct fb_info *info;
- void __iomem *mmio;
-+ void __iomem *clut;
- int irq_base;
- struct atmel_lcdfb_devdata *dev_data;
- struct work_struct task;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From fc3816309304b6ccbb3f1db1b433d2cb9a7df6ca Mon Sep 17 00:00:00 2001
-From: Wolfram Sang <w.sang@pengutronix.de>
-Date: Tue, 7 Jun 2011 12:58:36 +0200
-Subject: video: atmel_lcdfb: add error-msg when out of memory
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
----
- drivers/video/atmel_lcdfb_core.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c
-index 89d974a..ff84234 100644
---- a/drivers/video/atmel_lcdfb_core.c
-+++ b/drivers/video/atmel_lcdfb_core.c
-@@ -221,8 +221,10 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
- if (info->fix.smem_len) {
- unsigned int smem_len = (var->xres_virtual * var->yres_virtual
- * ((var->bits_per_pixel + 7) / 8));
-- if (smem_len > info->fix.smem_len)
-+ if (smem_len > info->fix.smem_len) {
-+ dev_err(dev, "not enough memory for this mode\n");
- return -EINVAL;
-+ }
- }
-
- /* Saturate vertical and horizontal timings at maximum values */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 368c0a49db43c164a47f60bb1d956ebea0a661ef Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Fri, 17 Feb 2012 13:12:21 +0100
-Subject: video: atmel_lcdfb: HLCD modifications
-
-HAS TO BE REWORKED: break compatibility with previous LCD IP due to register
-map changes
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- arch/arm/mach-at91/include/mach/atmel_hlcdc.h | 43 +++++++++++++++++++++++++++
- drivers/video/atmel_hlcdfb.c | 5 ++--
- drivers/video/atmel_lcdfb.c | 1 +
- drivers/video/atmel_lcdfb_core.c | 1 +
- drivers/video/backlight/Kconfig | 4 +--
- 5 files changed, 50 insertions(+), 4 deletions(-)
-
-diff --git a/arch/arm/mach-at91/include/mach/atmel_hlcdc.h b/arch/arm/mach-at91/include/mach/atmel_hlcdc.h
-index 9ed7e6e..738a853 100644
---- a/arch/arm/mach-at91/include/mach/atmel_hlcdc.h
-+++ b/arch/arm/mach-at91/include/mach/atmel_hlcdc.h
-@@ -29,8 +29,10 @@
- #define LCDC_LCDCFG0_CLKPWMSEL (0x1 << 3)
- #define LCDC_LCDCFG0_CGDISBASE (0x1 << 8)
- #define LCDC_LCDCFG0_CGDISOVR1 (0x1 << 9)
-+#define LCDC_LCDCFG0_CGDISOVR2 (0x1 << 10)
- #define LCDC_LCDCFG0_CGDISHEO (0x1 << 11)
- #define LCDC_LCDCFG0_CGDISHCR (0x1 << 12)
-+#define LCDC_LCDCFG0_CGDISPP (0x1 << 13)
- #define LCDC_LCDCFG0_CLKDIV_OFFSET 16
- #define LCDC_LCDCFG0_CLKDIV (0xff << LCDC_LCDCFG0_CLKDIV_OFFSET)
-
-@@ -49,8 +51,10 @@
- #define ATMEL_LCDC_LCDCFG3 0x000C
- #define LCDC_LCDCFG3_HFPW_OFFSET 0
- #define LCDC_LCDCFG3_HFPW (0xff << LCDC_LCDCFG3_HFPW_OFFSET)
-+#define LCDC2_LCDCFG3_HFPW (0x1ff << LCDC_LCDCFG3_HFPW_OFFSET)
- #define LCDC_LCDCFG3_HBPW_OFFSET 16
- #define LCDC_LCDCFG3_HBPW (0xff << LCDC_LCDCFG3_HBPW_OFFSET)
-+#define LCDC2_LCDCFG3_HBPW (0x1ff << LCDC_LCDCFG3_HBPW_OFFSET)
-
- #define ATMEL_LCDC_LCDCFG4 0x0010
- #define LCDC_LCDCFG4_PPL_OFFSET 0
-@@ -73,6 +77,7 @@
- #define LCDC_LCDCFG5_MODE_OUTPUT_16BPP (0x1 << 8)
- #define LCDC_LCDCFG5_MODE_OUTPUT_18BPP (0x2 << 8)
- #define LCDC_LCDCFG5_MODE_OUTPUT_24BPP (0x3 << 8)
-+#define LCDC_LCDCFG5_PP (0x1 << 10)
- #define LCDC_LCDCFG5_VSPSU (0x1 << 12)
- #define LCDC_LCDCFG5_VSPHO (0x1 << 13)
- #define LCDC_LCDCFG5_GUARDTIME_OFFSET 16
-@@ -115,8 +120,10 @@
- #define LCDC_LCDIER_FIFOERRIE (0x1 << 4)
- #define LCDC_LCDIER_BASEIE (0x1 << 8)
- #define LCDC_LCDIER_OVR1IE (0x1 << 9)
-+#define LCDC_LCDIER_OVR2IE (0x1 << 10)
- #define LCDC_LCDIER_HEOIE (0x1 << 11)
- #define LCDC_LCDIER_HCRIE (0x1 << 12)
-+#define LCDC_LCDIER_PPIE (0x1 << 13)
-
- #define ATMEL_LCDC_LCDIDR 0x0030
- #define LCDC_LCDIDR_SOFID (0x1 << 0)
-@@ -125,8 +132,10 @@
- #define LCDC_LCDIDR_FIFOERRID (0x1 << 4)
- #define LCDC_LCDIDR_BASEID (0x1 << 8)
- #define LCDC_LCDIDR_OVR1ID (0x1 << 9)
-+#define LCDC_LCDIDR_OVR2ID (0x1 << 10)
- #define LCDC_LCDIDR_HEOID (0x1 << 11)
- #define LCDC_LCDIDR_HCRID (0x1 << 12)
-+#define LCDC_LCDIDR_PPID (0x1 << 13)
-
- #define ATMEL_LCDC_LCDIMR 0x0034
- #define LCDC_LCDIMR_SOFIM (0x1 << 0)
-@@ -135,8 +144,10 @@
- #define LCDC_LCDIMR_FIFOERRIM (0x1 << 4)
- #define LCDC_LCDIMR_BASEIM (0x1 << 8)
- #define LCDC_LCDIMR_OVR1IM (0x1 << 9)
-+#define LCDC_LCDIMR_OVR2IM (0x1 << 10)
- #define LCDC_LCDIMR_HEOIM (0x1 << 11)
- #define LCDC_LCDIMR_HCRIM (0x1 << 12)
-+#define LCDC_LCDIMR_PPIM (0x1 << 13)
-
- #define ATMEL_LCDC_LCDISR 0x0038
- #define LCDC_LCDISR_SOF (0x1 << 0)
-@@ -145,8 +156,11 @@
- #define LCDC_LCDISR_FIFOERR (0x1 << 4)
- #define LCDC_LCDISR_BASE (0x1 << 8)
- #define LCDC_LCDISR_OVR1 (0x1 << 9)
-+#define LCDC_LCDISR_OVR2 (0x1 << 10)
- #define LCDC_LCDISR_HEO (0x1 << 10)
-+#define LCDC2_LCDISR_HEO (0x1 << 11)
- #define LCDC_LCDISR_HCR (0x1 << 12)
-+#define LCDC_LCDISR_PP (0x1 << 13)
-
- #define ATMEL_LCDC_BASECHER 0x0040
- #define LCDC_BASECHER_CHEN (0x1 << 0)
-@@ -205,6 +219,7 @@
- #define ATMEL_LCDC_BASENEXT 0x0068
-
- #define ATMEL_LCDC_BASECFG0 0x006C
-+#define LCDC_BASECFG0_SIF (0x1 << 0)
- #define LCDC_BASECFG0_BLEN_OFFSET 4
- #define LCDC_BASECFG0_BLEN (0x3 << LCDC_BASECFG0_BLEN_OFFSET)
- #define LCDC_BASECFG0_BLEN_AHB_SINGLE (0x0 << 4)
-@@ -251,8 +266,22 @@
- #define ATMEL_LCDC_BASECFG4 0x007C
- #define LCDC_BASECFG4_DMA (0x1 << 8)
- #define LCDC_BASECFG4_REP (0x1 << 9)
-+#define LCDC_BASECFG4_DISCEN (0x1 << 11)
-+
-+#define ATMEL_LCDC_BASECFG5 0x0080
-+#define LCDC_BASECFG5_DISCXPOS_OFFSET 0
-+#define LCDC_BASECFG5_DISCXPOS (0x7ff << LCDC_BASECFG5_DISCXPOS_OFFSET)
-+#define LCDC_BASECFG5_DISCYPOS_OFFSET 16
-+#define LCDC_BASECFG5_DISCYPOS (0x7ff << LCDC_BASECFG5_DISCYPOS_OFFSET)
-+
-+#define ATMEL_LCDC_BASECFG6 0x0084
-+#define LCDC_BASECFG6_DISCXSIZE_OFFSET 0
-+#define LCDC_BASECFG6_DISCXSIZE (0x7ff << LCDC_BASECFG6_DISCXSIZE_OFFSET)
-+#define LCDC_BASECFG6_DISCYSIZE_OFFSET 16
-+#define LCDC_BASECFG6_DISCYSIZE (0x7ff << LCDC_BASECFG6_DISCYSIZE_OFFSET)
-
- #define ATMEL_LCDC_HEOCHER 0x0280
-+#define ATMEL_LCDC2_HEOCHER 0x0340
- #define LCDC_HEOCHER_CHEN (0x1 << 0)
- #define LCDC_HEOCHER_UPDATEEN (0x1 << 1)
- #define LCDC_HEOCHER_A2QEN (0x1 << 2)
-@@ -674,6 +703,7 @@
- #define LCDC_HCRCFG9_GA_Msk (0xff << LCDC_HCRCFG9_GA_OFFSET)
-
- #define ATMEL_LCDC_BASECLUT 0x400
-+#define ATMEL_LCDC2_BASECLUT 0x600
- #define LCDC_BASECLUT_BCLUT_OFFSET 0
- #define LCDC_BASECLUT_BCLUT (0xff << LCDC_BASECLUT_BCLUT_OFFSET)
- #define LCDC_BASECLUT_GCLUT_OFFSET 8
-@@ -682,6 +712,7 @@
- #define LCDC_BASECLUT_RCLUT (0xff << LCDC_BASECLUT_RCLUT_OFFSET)
-
- #define ATMEL_LCDC_OVR1CLUT 0x800
-+#define ATMEL_LCDC2_OVR1CLUT 0xa00
- #define LCDC_OVR1CLUT_BCLUT_OFFSET 0
- #define LCDC_OVR1CLUT_BCLUT (0xff << LCDC_OVR1CLUT_BCLUT_OFFSET)
- #define LCDC_OVR1CLUT_GCLUT_OFFSET 8
-@@ -691,7 +722,18 @@
- #define LCDC_OVR1CLUT_ACLUT_OFFSET 24
- #define LCDC_OVR1CLUT_ACLUT (0xff << LCDC_OVR1CLUT_ACLUT_OFFSET)
-
-+#define ATMEL_LCDC_OVR2CLUT 0xe00
-+#define LCDC_OVR2CLUT_BCLUT_OFFSET 0
-+#define LCDC_OVR2CLUT_BCLUT (0xff << LCDC_OVR2CLUT_BCLUT_OFFSET)
-+#define LCDC_OVR2CLUT_GCLUT_OFFSET 8
-+#define LCDC_OVR2CLUT_GCLUT (0xff << LCDC_OVR2CLUT_GCLUT_OFFSET)
-+#define LCDC_OVR2CLUT_RCLUT_OFFSET 16
-+#define LCDC_OVR2CLUT_RCLUT (0xff << LCDC_OVR2CLUT_RCLUT_OFFSET)
-+#define LCDC_OVR2CLUT_ACLUT_OFFSET 24
-+#define LCDC_OVR2CLUT_ACLUT (0xff << LCDC_OVR2CLUT_ACLUT_OFFSET)
-+
- #define ATMEL_LCDC_HEOCLUT 0x1000
-+#define ATMEL_LCDC2_HEOCLUT 0x1200
- #define LCDC_HEOCLUT_BCLUT_OFFSET 0
- #define LCDC_HEOCLUT_BCLUT (0xff << LCDC_HEOCLUT_BCLUT_OFFSET)
- #define LCDC_HEOCLUT_GCLUT_OFFSET 8
-@@ -702,6 +744,7 @@
- #define LCDC_HEOCLUT_ACLUT (0xff << LCDC_HEOCLUT_ACLUT_OFFSET)
-
- #define ATMEL_LCDC_HCRCLUT 0x1400
-+#define ATMEL_LCDC2_HCRCLUT 0x1600
- #define LCDC_HCRCLUT_BCLUT_OFFSET 0
- #define LCDC_HCRCLUT_BCLUT (0xff << LCDC_HCRCLUT_BCLUT_OFFSET)
- #define LCDC_HCRCLUT_GCLUT_OFFSET 8
-diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c
-index 346bb80..c4c4559 100644
---- a/drivers/video/atmel_hlcdfb.c
-+++ b/drivers/video/atmel_hlcdfb.c
-@@ -9,6 +9,7 @@
- */
-
- #include <linux/kernel.h>
-+#include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/interrupt.h>
- #include <linux/backlight.h>
-@@ -363,11 +364,11 @@ static void atmelfb_limit_screeninfo(struct fb_var_screeninfo *var)
- var->lower_margin = min_t(u32, var->lower_margin,
- LCDC_LCDCFG2_VBPW >> LCDC_LCDCFG2_VBPW_OFFSET);
- var->right_margin = min_t(u32, var->right_margin,
-- (LCDC_LCDCFG3_HBPW >> LCDC_LCDCFG3_HBPW_OFFSET) + 1);
-+ (LCDC2_LCDCFG3_HBPW >> LCDC_LCDCFG3_HBPW_OFFSET) + 1);
- var->hsync_len = min_t(u32, var->hsync_len,
- (LCDC_LCDCFG1_HSPW >> LCDC_LCDCFG1_HSPW_OFFSET) + 1);
- var->left_margin = min_t(u32, var->left_margin,
-- (LCDC_LCDCFG3_HFPW >> LCDC_LCDCFG3_HFPW_OFFSET) + 1);
-+ (LCDC2_LCDCFG3_HFPW >> LCDC_LCDCFG3_HFPW_OFFSET) + 1);
-
- }
-
-diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
-index 402cb24..86e3e32 100644
---- a/drivers/video/atmel_lcdfb.c
-+++ b/drivers/video/atmel_lcdfb.c
-@@ -9,6 +9,7 @@
- */
-
- #include <linux/kernel.h>
-+#include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/interrupt.h>
- #include <linux/backlight.h>
-diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c
-index ff84234..133d4ad 100644
---- a/drivers/video/atmel_lcdfb_core.c
-+++ b/drivers/video/atmel_lcdfb_core.c
-@@ -9,6 +9,7 @@
- */
-
- #include <linux/kernel.h>
-+#include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/dma-mapping.h>
- #include <linux/interrupt.h>
-diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
-index af16884..18d066b 100644
---- a/drivers/video/backlight/Kconfig
-+++ b/drivers/video/backlight/Kconfig
-@@ -144,8 +144,8 @@ if BACKLIGHT_CLASS_DEVICE
-
- config BACKLIGHT_ATMEL_LCDC
- bool "Atmel LCDC Contrast-as-Backlight control"
-- depends on FB_ATMEL
-- default y if MACH_SAM9261EK || MACH_SAM9G10EK || MACH_SAM9263EK
-+ depends on FB_ATMEL || FB_ATMEL_HLCD
-+ default y
- help
- This provides a backlight control internal to the Atmel LCDC
- driver. If the LCD "contrast control" on your board is wired
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 44715fbb365b351a7f1efe27639a56684991eccc Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Fri, 24 Jun 2011 13:03:29 +0200
-Subject: atmel_lcdfb: change pixel clock ratio calculation
-
-DIV_ROUND_UP() was used to calculate the pixel clock divider
-in atmel_hlcdfb_setup_core_base().
-But this rounding was producing a bigger divider each time it was called.
-We replace by DIV_ROUND_CLOSEST() to calculate it.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/video/atmel_hlcdfb.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c
-index c4c4559..a629dda 100644
---- a/drivers/video/atmel_hlcdfb.c
-+++ b/drivers/video/atmel_hlcdfb.c
-@@ -247,7 +247,7 @@ static int atmel_hlcdfb_setup_core_base(struct fb_info *info)
- /* Set pixel clock */
- clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
-
-- value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock));
-+ value = DIV_ROUND_CLOSEST(clk_value_khz, PICOS2KHZ(info->var.pixclock));
-
- if (value < 1) {
- dev_notice(info->device, "using system clock as pixel clock\n");
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a16a507fb90bf1629f81cae4fc197def0382bc91 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
-Date: Tue, 24 May 2011 23:45:21 +0200
-Subject: media/at91sam9x5-video: new driver for the high end overlay on
- at91sam9x5
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
----
- drivers/media/video/Kconfig | 8 +
- drivers/media/video/Makefile | 1 +
- drivers/media/video/at91sam9x5-video.c | 1441 ++++++++++++++++++++++++++++++++
- 3 files changed, 1450 insertions(+)
- create mode 100644 drivers/media/video/at91sam9x5-video.c
-
-diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
-index ce1e7ba..70a6a55 100644
---- a/drivers/media/video/Kconfig
-+++ b/drivers/media/video/Kconfig
-@@ -1163,6 +1163,14 @@ source "drivers/media/video/s5p-tv/Kconfig"
- endif # V4L_PLATFORM_DRIVERS
- endif # VIDEO_CAPTURE_DRIVERS
-
-+config VIDEO_AT91SAM9X5
-+ tristate "Support for AT91SAM9X5 Video"
-+ depends on ARCH_AT91
-+ depends on VIDEO_V4L2
-+ select VIDEOBUF2_DMA_CONTIG
-+ help
-+ support for the "High End Overlay" found in Atmel's AT91SAM9X5 SoCs.
-+
- menuconfig V4L_MEM2MEM_DRIVERS
- bool "Memory-to-memory multimedia devices"
- depends on VIDEO_V4L2
-diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
-index a6282a3..2b41c18 100644
---- a/drivers/media/video/Makefile
-+++ b/drivers/media/video/Makefile
-@@ -121,6 +121,7 @@ obj-$(CONFIG_VIDEO_MXB) += mxb.o
- obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
- obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
- obj-$(CONFIG_VIDEO_TIMBERDALE) += timblogiw.o
-+obj-$(CONFIG_VIDEO_AT91SAM9X5) += at91sam9x5-video.o
-
- obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
- obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
-diff --git a/drivers/media/video/at91sam9x5-video.c b/drivers/media/video/at91sam9x5-video.c
-new file mode 100644
-index 0000000..26ce376
---- /dev/null
-+++ b/drivers/media/video/at91sam9x5-video.c
-@@ -0,0 +1,1441 @@
-+/*
-+ * Copyright (C) 2011 Pengutronix
-+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
-+ *
-+ * 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.
-+ */
-+
-+/*
-+ * XXX:
-+ * - handle setting of global alpha
-+ * - handle more formats
-+ * - complete this list :-)
-+ */
-+
-+#include <linux/err.h>
-+#include <linux/fb.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/slab.h>
-+
-+#include <media/v4l2-common.h>
-+#include <media/v4l2-dev.h>
-+#include <media/v4l2-ioctl.h>
-+#include <media/videobuf2-dma-contig.h>
-+
-+#define debug(fmt, ...)
-+
-+#define DRIVER_NAME "at91sam9x5-video"
-+
-+#define REG_HEOCHER 0x00
-+#define REG_HEOCHER_CHEN 0x00000001
-+#define REG_HEOCHER_UPDATEEN 0x00000002
-+#define REG_HEOCHER_A2QEN 0x00000004
-+
-+#define REG_HEOCHDR 0x04
-+#define REG_HEOCHDR_CHDIS 0x00000001
-+#define REG_HEOCHDR_CHRST 0x00000100
-+
-+#define REG_HEOCHSR 0x08
-+#define REG_HEOCHSR_CHSR 0x00000001
-+#define REG_HEOCHSR_UPDATESR 0x00000002
-+#define REG_HEOCHSR_A2QSR 0x00000004
-+
-+#define REG_HEOIER 0x0c
-+#define REG_HEOIDR 0x10
-+#define REG_HEOIMR 0x14
-+#define REG_HEOISR 0x18
-+#define REG_HEOIxR_DMA 0x00000004
-+#define REG_HEOIxR_DSCR 0x00000008
-+#define REG_HEOIxR_ADD 0x00000010
-+#define REG_HEOIxR_DONE 0x00000020
-+#define REG_HEOIxR_OVR 0x00000040
-+#define REG_HEOIxR_UDMA 0x00000400
-+#define REG_HEOIxR_UDSCR 0x00000800
-+#define REG_HEOIxR_UADD 0x00001000
-+#define REG_HEOIxR_UDONE 0x00002000
-+#define REG_HEOIxR_UOVR 0x00004000
-+#define REG_HEOIxR_VDMA 0x00040000
-+#define REG_HEOIxR_VDSCR 0x00080000
-+#define REG_HEOIxR_VADD 0x00100000
-+#define REG_HEOIxR_VDONE 0x00200000
-+#define REG_HEOIxR_VOVR 0x00400000
-+
-+#define REG_HEOHEAD 0x1c
-+#define REG_HEOUHEAD 0x2c
-+#define REG_HEOVHEAD 0x3c
-+
-+#define REG_HEOADDR 0x20
-+#define REG_HEOUADDR 0x30
-+#define REG_HEOVADDR 0x40
-+
-+#define REG_HEOCTRL 0x24
-+#define REG_HEOUCTRL 0x34
-+#define REG_HEOVCTRL 0x44
-+#define REG_HEOxCTRL_DFETCH 0x00000001
-+#define REG_HEOCTRL_LFETCH 0x00000002
-+#define REG_HEOxCTRL_DMAIEN 0x00000004
-+#define REG_HEOxCTRL_DSCRIEN 0x00000008
-+#define REG_HEOxCTRL_ADDIEN 0x00000010
-+#define REG_HEOxCTRL_DONEIEN 0x00000020
-+
-+#define REG_HEONEXT 0x28
-+#define REG_HEOUNEXT 0x38
-+#define REG_HEOVNEXT 0x48
-+
-+#define REG_HEOCFG0 0x4c
-+#define REG_HEOCFG0_DLBO 0x00000100
-+#define REG_HEOCFG0_BLEN 0x00000030
-+#define REG_HEOCFG0_BLEN_INCR1 0x00000000
-+#define REG_HEOCFG0_BLEN_INCR4 0x00000010
-+#define REG_HEOCFG0_BLEN_INCR8 0x00000020
-+#define REG_HEOCFG0_BLEN_INCR16 0x00000030
-+#define REG_HEOCFG0_BLENUV 0x000000c0
-+#define REG_HEOCFG0_BLENUV_INCR1 0x00000000
-+#define REG_HEOCFG0_BLENUV_INCR4 0x00000040
-+#define REG_HEOCFG0_BLENUV_INCR8 0x00000080
-+#define REG_HEOCFG0_BLENUV_INCR16 0x000000c0
-+
-+#define REG_HEOCFG1 0x50
-+#define REG_HEOCFG1_CLUTEN 0x00000001
-+#define REG_HEOCFG1_YUVEN 0x00000002
-+#define REG_HEOCFG1_YUVMODE_12YCBCRP 0x00008000
-+
-+#define REG_HEOCFG2 0x54
-+#define REG_HEOCFG2_XPOS 0x000007ff
-+#define REG_HEOCFG2_YPOS 0x07ff0000
-+
-+#define REG_HEOCFG3 0x58
-+#define REG_HEOCFG3_XSIZE 0x000007ff
-+#define REG_HEOCFG3_YSIZE 0x07ff0000
-+
-+#define REG_HEOCFG4 0x5c
-+#define REG_HEOCFG4_XMEMSIZE 0x000007ff
-+#define REG_HEOCFG4_YMEMSIZE 0x07ff0000
-+
-+#define REG_HEOCFG5 0x60
-+#define REG_HEOCFG5_XSTRIDE 0xffffffff
-+
-+#define REG_HEOCFG6 0x64
-+#define REG_HEOCFG6_PSTRIDE 0xffffffff
-+
-+#define REG_HEOCFG7 0x68
-+#define REG_HEOCFG7_UVXSTRIDE 0xffffffff
-+
-+#define REG_HEOCFG8 0x6c
-+#define REG_HEOCFG8_UVPSTRIDE 0xffffffff
-+
-+#define REG_HEOCFG9 0x70
-+#define REG_HEOCFG10 0x74
-+#define REG_HEOCFG11 0x78
-+
-+#define REG_HEOCFG12 0x7c
-+#define REG_HEOCFG12_CRKEY 0x00000001
-+#define REG_HEOCFG12_INV 0x00000002
-+#define REG_HEOCFG12_ITER2BL 0x00000004
-+#define REG_HEOCFG12_ITER 0x00000008
-+#define REG_HEOCFG12_REVALPHA 0x00000010
-+#define REG_HEOCFG12_GAEN 0x00000020
-+#define REG_HEOCFG12_LAEN 0x00000040
-+#define REG_HEOCFG12_OVR 0x00000080
-+#define REG_HEOCFG12_DMA 0x00000100
-+#define REG_HEOCFG12_REP 0x00000200
-+#define REG_HEOCFG12_DSTKEY 0x00000400
-+#define REG_HEOCFG12_VIDPRI 0x00001000
-+#define REG_HEOCFG12_GA 0x00ff0000
-+
-+#define REG_HEOCFG13 0x80
-+#define REG_HEOCFG13_XFACTOR 0x00001fff
-+#define REG_HEOCFG13_YFACTOR 0x1fff0000
-+#define REG_HEOCFG13_SCALEN 0x80000000
-+
-+#define REG_HEOCFG14 0x84
-+#define REG_HEOCFG15 0x88
-+#define REG_HEOCFG16 0x8c
-+
-+#define valtomask(val, mask) (((val) << __ffs((mask))) & (mask))
-+#define valfrommask(val, mask) (((val) & (mask)) >> __ffs((mask)))
-+
-+struct at91sam9x5_video_pdata {
-+ u16 base_width;
-+ u16 base_height;
-+};
-+
-+struct at91sam9x5_video_bufinfo {
-+ struct vb2_buffer *vb;
-+ unsigned u_planeno, v_planeno;
-+ unsigned long plane_size[3];
-+};
-+
-+struct at91sam9x5_video_priv {
-+ struct platform_device *pdev;
-+
-+ /* framebuffer stuff */
-+ struct notifier_block fb_notifier;
-+ struct fb_info *fbinfo;
-+
-+ struct video_device *video_dev;
-+
-+ void __iomem *regbase;
-+ unsigned int irq;
-+
-+ struct vb2_queue queue;
-+ void *alloc_ctx;
-+
-+ struct at91sam9x5_video_bufinfo cur, next;
-+
-+ /* protects the members after lock and hardware access */
-+ spinlock_t lock;
-+
-+ enum {
-+ /* DMA not running */
-+ at91sam9x5_video_HW_IDLE,
-+ /* DMA running, unless cfgstate is BAD */
-+ at91sam9x5_video_HW_RUNNING,
-+ } hwstate;
-+
-+ enum {
-+ at91sam9x5_video_CFG_GOOD,
-+ /* the shadow registers need an update */
-+ at91sam9x5_video_CFG_GOOD_LATCH,
-+ at91sam9x5_video_CFG_BAD,
-+ } cfgstate;
-+
-+ /* if true the vid_out config in hardware doesn't match sw config */
-+ int cfgupdate;
-+
-+ int valid_config;
-+
-+ struct v4l2_pix_format fmt_vid_out_cur, fmt_vid_out_next;
-+
-+ int rotation;
-+
-+ struct v4l2_window fmt_vid_overlay;
-+
-+ /*
-+ * For YUV formats Y data is always in plane 0. U, V are either both in
-+ * 0, both in 1, or U in 1 or V in 2. -1 for formats that don't use U
-+ * and V.
-+ */
-+ int u_planeno, v_planeno;
-+
-+ unsigned long plane_size[3];
-+
-+ /*
-+ * These are the offsets into the buffers to start the hardware for.
-+ * Depending on rotation and overlay position this is more or less ugly
-+ * to calculate. (y_offset is used for rgb data, too.)
-+ */
-+ u32 y_offset, u_offset, v_offset;
-+
-+ u32 irqstat;
-+};
-+
-+static u32 at91sam9x5_video_read32(struct at91sam9x5_video_priv *priv,
-+ size_t offset)
-+{
-+ /* XXX: really use the __raw variants? */
-+ return __raw_readl(priv->regbase + offset);
-+}
-+
-+static void at91sam9x5_video_write32(struct at91sam9x5_video_priv *priv,
-+ size_t offset, u32 val)
-+{
-+ debug("$%x := %08x, $08 == %08x\n", offset, val,
-+ at91sam9x5_video_read32(priv, REG_HEOCHSR));
-+ __raw_writel(val, priv->regbase + offset);
-+ debug("$08 == %08x\n", at91sam9x5_video_read32(priv, REG_HEOCHSR));
-+}
-+
-+static int __at91sam9x5_video_buf_in_use(struct at91sam9x5_video_priv *priv,
-+ struct at91sam9x5_video_bufinfo *bi,
-+ size_t heoaddr_offset, unsigned planeno)
-+{
-+ if (planeno >= 0) {
-+ u32 heoaddr = at91sam9x5_video_read32(priv, heoaddr_offset);
-+ dma_addr_t plane_paddr =
-+ vb2_dma_contig_plane_dma_addr(bi->vb, planeno);
-+
-+ if (heoaddr - plane_paddr <= bi->plane_size[planeno])
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int at91sam9x5_video_buf_in_use(struct at91sam9x5_video_priv *priv,
-+ struct at91sam9x5_video_bufinfo *bi)
-+{
-+ if (__at91sam9x5_video_buf_in_use(priv, bi, REG_HEOADDR, 0))
-+ return 1;
-+ if (__at91sam9x5_video_buf_in_use(priv, bi,
-+ REG_HEOUADDR, bi->u_planeno))
-+ return 1;
-+ if (__at91sam9x5_video_buf_in_use(priv, bi,
-+ REG_HEOVADDR, bi->v_planeno))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+static u32 at91sam9x5_video_handle_irqstat(struct at91sam9x5_video_priv *priv)
-+{
-+ u32 heoisr = at91sam9x5_video_read32(priv, REG_HEOISR);
-+
-+ debug("cur=%p, next=%p, heoisr=%08x\n", priv->cur.vb,
-+ priv->next.vb, heoisr);
-+ debug("cfgupdate=%d hwstate=%d cfgstate=%d\n",
-+ priv->cfgupdate, priv->hwstate, priv->cfgstate);
-+
-+ if (!priv->cur.vb) {
-+ priv->cur = priv->next;
-+ priv->next.vb = NULL;
-+ }
-+
-+ if (priv->hwstate == at91sam9x5_video_HW_IDLE &&
-+ !(at91sam9x5_video_read32(priv, REG_HEOCHSR) &
-+ REG_HEOCHSR_CHSR)) {
-+ if (priv->cur.vb) {
-+ vb2_buffer_done(priv->cur.vb, VB2_BUF_STATE_DONE);
-+ priv->cur.vb = NULL;
-+ }
-+
-+ if (priv->next.vb) {
-+ vb2_buffer_done(priv->next.vb, VB2_BUF_STATE_DONE);
-+ priv->next.vb = NULL;
-+ }
-+
-+ at91sam9x5_video_write32(priv, REG_HEOIDR,
-+ REG_HEOIxR_ADD | REG_HEOIxR_DMA |
-+ REG_HEOIxR_UADD | REG_HEOIxR_UDMA |
-+ REG_HEOIxR_VADD | REG_HEOIxR_VDMA);
-+
-+ } else if (priv->cur.vb && priv->next.vb) {
-+ int hwrunning = 1;
-+ if (priv->cfgstate == at91sam9x5_video_CFG_BAD &&
-+ !(at91sam9x5_video_read32(priv, REG_HEOCHSR) &
-+ REG_HEOCHSR_CHSR))
-+ hwrunning = 0;
-+
-+ if (!hwrunning || !at91sam9x5_video_buf_in_use(priv,
-+ &priv->cur)) {
-+ vb2_buffer_done(priv->cur.vb, VB2_BUF_STATE_DONE);
-+ priv->cur = priv->next;
-+ priv->next.vb = NULL;
-+ }
-+ } else if (priv->next.vb) {
-+ priv->cur = priv->next;
-+ priv->next.vb = NULL;
-+ }
-+
-+ return heoisr;
-+}
-+
-+static irqreturn_t at91sam9x5_video_irq(int irq, void *data)
-+{
-+ struct at91sam9x5_video_priv *priv = data;
-+ unsigned long flags;
-+ u32 handled, heoimr;
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+
-+ heoimr = at91sam9x5_video_read32(priv, REG_HEOIMR);
-+ handled = at91sam9x5_video_handle_irqstat(priv);
-+
-+ debug("%x, HEOCHSR = %08x\n", handled,
-+ at91sam9x5_video_read32(priv, REG_HEOCHSR));
-+
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ if (handled & heoimr)
-+ return IRQ_HANDLED;
-+ else
-+ return IRQ_NONE;
-+}
-+
-+static inline int sign(int x)
-+{
-+ if (x > 0)
-+ return 1;
-+ else if (x < 0)
-+ return -1;
-+ else
-+ return 0;
-+}
-+
-+static void at91sam9x5_video_show_buf(struct at91sam9x5_video_priv *priv,
-+ struct vb2_buffer *vb)
-+{
-+ dma_addr_t buffer = vb2_dma_contig_plane_dma_addr(vb, 0);
-+ void *vaddr = vb2_plane_vaddr(vb, 0);
-+ struct v4l2_pix_format *pix = &priv->fmt_vid_out_cur;
-+ /* XXX: format dependant */
-+ size_t offset_dmadesc = ALIGN(pix->width * pix->height +
-+ ALIGN(pix->width, 2) * ALIGN(pix->height, 2) / 2, 32);
-+ u32 *dmadesc = vaddr + offset_dmadesc;
-+ u32 heocher;
-+
-+ if (priv->cfgstate == at91sam9x5_video_CFG_GOOD_LATCH) {
-+ heocher = REG_HEOCHER_UPDATEEN;
-+ priv->cfgstate = at91sam9x5_video_CFG_GOOD;
-+ } else {
-+ BUG_ON(priv->cfgstate != at91sam9x5_video_CFG_GOOD);
-+ heocher = 0;
-+ }
-+
-+ debug("vout=%ux%u, heocher=%08x\n", pix->width, pix->height, heocher);
-+
-+ dmadesc[0] = buffer + priv->y_offset;
-+ dmadesc[1] = REG_HEOxCTRL_DFETCH;
-+ dmadesc[2] = buffer + offset_dmadesc;
-+
-+ if (priv->u_planeno >= 0) {
-+ dmadesc[3] = vb2_dma_contig_plane_dma_addr(vb, priv->u_planeno) +
-+ priv->u_offset;
-+ dmadesc[4] = REG_HEOxCTRL_DFETCH;
-+ dmadesc[5] = buffer + offset_dmadesc + 3 * 4;
-+ }
-+
-+ if (priv->v_planeno >= 0) {
-+ dmadesc[6] = vb2_dma_contig_plane_dma_addr(vb, priv->v_planeno) +
-+ priv->v_offset;
-+ dmadesc[7] = REG_HEOxCTRL_DFETCH;
-+ dmadesc[8] = buffer + offset_dmadesc + 6 * 4;
-+ }
-+
-+
-+ debug("HEOCHSR = %08x\n", at91sam9x5_video_read32(priv, REG_HEOCHSR));
-+ if (likely(priv->hwstate == at91sam9x5_video_HW_RUNNING)) {
-+
-+ at91sam9x5_video_write32(priv, REG_HEOHEAD, dmadesc[2]);
-+
-+ if (priv->u_planeno >= 0)
-+ at91sam9x5_video_write32(priv,
-+ REG_HEOUHEAD, dmadesc[5]);
-+
-+ if (priv->v_planeno >= 0)
-+ at91sam9x5_video_write32(priv,
-+ REG_HEOVHEAD, dmadesc[8]);
-+
-+ at91sam9x5_video_write32(priv,
-+ REG_HEOCHER, heocher | REG_HEOCHER_A2QEN);
-+
-+ } else {
-+
-+ at91sam9x5_video_write32(priv, REG_HEOADDR, dmadesc[0]);
-+ at91sam9x5_video_write32(priv, REG_HEOCTRL, dmadesc[1]);
-+ at91sam9x5_video_write32(priv, REG_HEONEXT, dmadesc[2]);
-+
-+ if (priv->u_planeno >= 0) {
-+ at91sam9x5_video_write32(priv,
-+ REG_HEOUADDR, dmadesc[3]);
-+ at91sam9x5_video_write32(priv,
-+ REG_HEOUCTRL, dmadesc[4]);
-+ at91sam9x5_video_write32(priv,
-+ REG_HEOUNEXT, dmadesc[5]);
-+ }
-+
-+ if (priv->v_planeno >= 0) {
-+ at91sam9x5_video_write32(priv,
-+ REG_HEOVADDR, dmadesc[6]);
-+ at91sam9x5_video_write32(priv,
-+ REG_HEOVCTRL, dmadesc[7]);
-+ at91sam9x5_video_write32(priv,
-+ REG_HEOVNEXT, dmadesc[8]);
-+ }
-+
-+ at91sam9x5_video_write32(priv, REG_HEOCHER,
-+ heocher | REG_HEOCHER_CHEN);
-+
-+ priv->hwstate = at91sam9x5_video_HW_RUNNING;
-+ }
-+
-+ if (priv->cur.vb && at91sam9x5_video_buf_in_use(priv, &priv->cur)) {
-+ if (priv->next.vb) {
-+ /* drop next; XXX: is this an error? */
-+ debug("drop %p\n", priv->next.vb);
-+ vb2_buffer_done(priv->next.vb, VB2_BUF_STATE_ERROR);
-+ }
-+ } else {
-+ if (priv->cur.vb)
-+ vb2_buffer_done(priv->cur.vb, VB2_BUF_STATE_DONE);
-+
-+ priv->cur = priv->next;
-+ }
-+ priv->next.vb = vb;
-+ priv->next.u_planeno = priv->u_planeno;
-+ priv->next.v_planeno = priv->v_planeno;
-+ priv->next.plane_size[0] = priv->plane_size[0];
-+ priv->next.plane_size[1] = priv->plane_size[1];
-+ priv->next.plane_size[2] = priv->plane_size[2];
-+}
-+
-+static int experimental;
-+module_param(experimental, bool, 0644);
-+MODULE_PARM_DESC(experimental, "enable experimental features");
-+
-+static void at91sam9x5_video_params(unsigned width, unsigned height,
-+ int rotation, u32 *xstride, u32 *pstride, u32 *tloffset)
-+{
-+/* offset of pixel at (x, y) in the buffer */
-+#define po(x, y) ((x) + width * (y))
-+
-+ /* offsets of the edges in counter-clockwise order */
-+ const unsigned e[] = {
-+ po(0, 0),
-+ po(0, height - 1),
-+ po(width - 1, height - 1),
-+ po(width - 1, 0),
-+ };
-+
-+ /*
-+ * offsets of the pixels next to the corresponding edges
-+ * If edge[i] goes to the top left corner, edge_neighbour[i] is
-+ * located just below of edge[i].
-+ */
-+ const unsigned en[] = {
-+ po(0, 1),
-+ po(1, height - 1),
-+ po(width - 1, height - 2),
-+ po(width - 2, 0),
-+ };
-+
-+#define ro(r) ((rotation + (r)) % 4)
-+
-+ *xstride = en[ro(0)] - e[ro(3)];
-+ *pstride = e[ro(3)] - en[ro(3)];
-+ *tloffset = e[ro(0)];
-+}
-+
-+static void at91sam9x5_video_update_config_real(
-+ struct at91sam9x5_video_priv *priv)
-+{
-+ struct v4l2_pix_format *pix = &priv->fmt_vid_out_cur;
-+ struct v4l2_window *win = &priv->fmt_vid_overlay;
-+ struct v4l2_rect *rect = &win->w;
-+ /* XXX: check for overflow? */
-+ s32 right = rect->left + rect->width, bottom = rect->top + rect->height;
-+
-+ unsigned hwxpos, hwypos, hwxsize, hwysize;
-+ unsigned hwxmem_size, hwymem_size;
-+ s32 hwxstride, hwpstride;
-+ s32 hwuvxstride, hwuvpstride;
-+ s32 rotated_pixwidth, rotated_pixheight;
-+
-+ debug("vout=%ux%u, ovl=(%d,%d)+(%d,%d)\n", pix->width, pix->height,
-+ rect->left, rect->top, rect->width, rect->height);
-+
-+ if (!experimental && priv->rotation) {
-+ dev_info(&priv->video_dev->dev, "disable rotation\n");
-+ priv->rotation = 0;
-+ }
-+
-+ if (rect->left < 0)
-+ hwxpos = 0;
-+ else
-+ hwxpos = rect->left;
-+
-+ if (rect->top < 0)
-+ hwypos = 0;
-+ else
-+ hwypos = rect->top;
-+
-+ if (right > priv->fbinfo->var.xres)
-+ hwxsize = priv->fbinfo->var.xres - hwxpos;
-+ else
-+ hwxsize = right - hwxpos;
-+
-+ if (bottom > priv->fbinfo->var.yres)
-+ hwysize = priv->fbinfo->var.yres - hwypos;
-+ else
-+ hwysize = bottom - hwypos;
-+
-+ at91sam9x5_video_write32(priv, REG_HEOCFG2,
-+ valtomask(hwxpos, REG_HEOCFG2_XPOS) |
-+ valtomask(hwypos, REG_HEOCFG2_YPOS));
-+
-+ at91sam9x5_video_write32(priv, REG_HEOCFG3,
-+ valtomask(hwxsize - 1, REG_HEOCFG3_XSIZE) |
-+ valtomask(hwysize - 1, REG_HEOCFG3_YSIZE));
-+
-+ /* XXX:
-+ * - clipping
-+ */
-+ at91sam9x5_video_write32(priv, REG_HEOCFG1,
-+ REG_HEOCFG1_YUVMODE_12YCBCRP |
-+ REG_HEOCFG1_YUVEN);
-+ at91sam9x5_video_write32(priv, REG_HEOCFG12,
-+ REG_HEOCFG12_GAEN |
-+ REG_HEOCFG12_OVR |
-+ REG_HEOCFG12_DMA |
-+ REG_HEOCFG12_REP |
-+ REG_HEOCFG12_GA);
-+
-+#define vx(pos) xedge[(priv->rotation + pos) % 4]
-+#define vy(pos) yedge[(priv->rotation + pos) % 4]
-+
-+ if (priv->rotation & 1) {
-+ rotated_pixwidth = pix->height;
-+ rotated_pixheight = pix->width;
-+ } else {
-+ rotated_pixwidth = pix->width;
-+ rotated_pixheight = pix->height;
-+ }
-+
-+ hwxmem_size = rotated_pixwidth * hwxsize / rect->width;
-+ hwymem_size = rotated_pixheight * hwysize / rect->height;
-+
-+ at91sam9x5_video_write32(priv, REG_HEOCFG4,
-+ valtomask(hwxmem_size - 1, REG_HEOCFG4_XMEMSIZE) |
-+ valtomask(hwymem_size - 1, REG_HEOCFG4_YMEMSIZE));
-+
-+ at91sam9x5_video_write32(priv, REG_HEOCFG13,
-+ REG_HEOCFG13_SCALEN |
-+ valtomask(1024 * hwxmem_size / hwxsize,
-+ REG_HEOCFG13_XFACTOR) |
-+ valtomask(1024 * hwymem_size / hwysize,
-+ REG_HEOCFG13_YFACTOR));
-+
-+ at91sam9x5_video_params(pix->width, pix->height, priv->rotation,
-+ &hwxstride, &hwpstride, &priv->y_offset);
-+
-+ /* XXX: format-dependant */
-+ at91sam9x5_video_params(DIV_ROUND_UP(pix->width, 2),
-+ DIV_ROUND_UP(pix->height, 2), priv->rotation,
-+ &hwuvxstride, &hwuvpstride, &priv->u_offset);
-+
-+ at91sam9x5_video_write32(priv, REG_HEOCFG5,
-+ valtomask(hwxstride - 1, REG_HEOCFG5_XSTRIDE));
-+ at91sam9x5_video_write32(priv, REG_HEOCFG6,
-+ valtomask(hwpstride - 1, REG_HEOCFG6_PSTRIDE));
-+
-+ at91sam9x5_video_write32(priv, REG_HEOCFG7,
-+ valtomask(hwuvxstride - 1, REG_HEOCFG7_UVXSTRIDE));
-+ at91sam9x5_video_write32(priv, REG_HEOCFG8,
-+ valtomask(hwuvpstride - 1, REG_HEOCFG8_UVPSTRIDE));
-+
-+ /* XXX: format dependant */
-+ priv->u_planeno = 0;
-+ priv->v_planeno = 0;
-+ priv->u_offset += pix->width * pix->height;
-+ priv->v_offset = priv->u_offset +
-+ DIV_ROUND_UP(pix->width, 2) * DIV_ROUND_UP(pix->height, 2);
-+
-+ /* XXX: evaluate pix->colorspace */
-+ at91sam9x5_video_write32(priv, REG_HEOCFG14, 0x4c900091);
-+ at91sam9x5_video_write32(priv, REG_HEOCFG15, 0x7a5f5090);
-+ at91sam9x5_video_write32(priv, REG_HEOCFG16, 0x40040890);
-+}
-+
-+static void at91sam9x5_video_update_config(struct at91sam9x5_video_priv *priv,
-+ int overlay_only)
-+{
-+ debug("cfgupdate=%d overlay_only=%d\n", priv->cfgupdate, overlay_only);
-+
-+ at91sam9x5_video_handle_irqstat(priv);
-+
-+ if (priv->cfgupdate || overlay_only) {
-+ struct v4l2_pix_format *pix = &priv->fmt_vid_out_cur;
-+ struct v4l2_window *win = &priv->fmt_vid_overlay;
-+ struct v4l2_rect *rect = &win->w;
-+
-+ if (!overlay_only) {
-+ *pix = priv->fmt_vid_out_next;
-+ priv->cfgupdate = 0;
-+ }
-+
-+ /* XXX: handle clipping */
-+ if (rect->width <= 0 || rect->height <= 0 ||
-+ /* vid_out is set */
-+ pix->width <= 0 ||
-+ pix->height <= 0 ||
-+ /* window is partly invisible or too small */
-+ rect->left < 0 ||
-+ rect->top < 0 ||
-+ rect->left >= (int)priv->fbinfo->var.xres - 5 ||
-+ rect->top >= (int)priv->fbinfo->var.yres - 5 ||
-+ rect->left + rect->width >
-+ (int)priv->fbinfo->var.xres ||
-+ rect->top + rect->height >
-+ (int)priv->fbinfo->var.yres) {
-+
-+ if (priv->cfgstate == at91sam9x5_video_CFG_GOOD ||
-+ priv->cfgstate ==
-+ at91sam9x5_video_CFG_GOOD_LATCH)
-+ at91sam9x5_video_write32(priv,
-+ REG_HEOCHDR, REG_HEOCHDR_CHDIS);
-+
-+ priv->cfgstate = at91sam9x5_video_CFG_BAD;
-+ } else {
-+ at91sam9x5_video_update_config_real(priv);
-+
-+ debug("hwstate=%d cfgstate=%d\n",
-+ priv->hwstate, priv->cfgstate);
-+ if (overlay_only && priv->hwstate ==
-+ at91sam9x5_video_HW_RUNNING) {
-+ if (priv->cfgstate ==
-+ at91sam9x5_video_CFG_BAD) {
-+ priv->cfgstate =
-+ at91sam9x5_video_CFG_GOOD_LATCH;
-+ priv->hwstate =
-+ at91sam9x5_video_HW_IDLE;
-+
-+ at91sam9x5_video_show_buf(priv,
-+ priv->cur.vb);
-+ } else
-+ at91sam9x5_video_write32(priv,
-+ REG_HEOCHER,
-+ REG_HEOCHER_UPDATEEN);
-+ } else
-+ priv->cfgstate =
-+ at91sam9x5_video_CFG_GOOD_LATCH;
-+ }
-+
-+ }
-+}
-+
-+static int at91sam9x5_video_vb_queue_setup(struct vb2_queue *q,
-+ const struct v4l2_format *fmt,
-+ unsigned int *num_buffers, unsigned int *num_planes,
-+ unsigned int sizes[], void *alloc_ctxs[])
-+{
-+ struct at91sam9x5_video_priv *priv =
-+ container_of(q, struct at91sam9x5_video_priv, queue);
-+ struct v4l2_pix_format *pix = &priv->fmt_vid_out_next;
-+
-+ debug("vout=%ux%u\n", pix->width, pix->height);
-+
-+ /* XXX */
-+ *num_planes = 1;
-+
-+ /*
-+ * The last 9 (aligned) words are used for the 3 dma descriptors (3
-+ * 32-bit words each). The additional 32 bits are for alignment.
-+ * XXX: is that allowed and done right?
-+ * XXX: format-dependant
-+ */
-+ sizes[0] = pix->width * pix->height +
-+ ALIGN(pix->width, 2) * ALIGN(pix->height, 2) / 2 +
-+ 10 * 32;
-+ priv->plane_size[0] = sizes[0];
-+
-+ alloc_ctxs[0] = priv->alloc_ctx;
-+
-+ return 0;
-+}
-+
-+static void at91sam9x5_video_vb_wait_prepare(struct vb2_queue *q)
-+{
-+ struct at91sam9x5_video_priv *priv =
-+ container_of(q, struct at91sam9x5_video_priv, queue);
-+ unsigned long flags;
-+
-+ debug("cfgupdate=%d hwstate=%d cfgstate=%d\n",
-+ priv->cfgupdate, priv->hwstate, priv->cfgstate);
-+ debug("bufs=%p,%p\n", priv->cur.vb, priv->next.vb);
-+ spin_lock_irqsave(&priv->lock, flags);
-+
-+ at91sam9x5_video_handle_irqstat(priv);
-+
-+ at91sam9x5_video_write32(priv, REG_HEOIER,
-+ REG_HEOIxR_ADD | REG_HEOIxR_DMA |
-+ REG_HEOIxR_UADD | REG_HEOIxR_UDMA |
-+ REG_HEOIxR_VADD | REG_HEOIxR_VDMA);
-+
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+}
-+
-+static void at91sam9x5_video_vb_wait_finish(struct vb2_queue *q)
-+{
-+ struct at91sam9x5_video_priv *priv =
-+ container_of(q, struct at91sam9x5_video_priv, queue);
-+ unsigned long flags;
-+
-+ debug("cfgupdate=%d hwstate=%d cfgstate=%d\n",
-+ priv->cfgupdate, priv->hwstate, priv->cfgstate);
-+ debug("bufs=%p,%p\n", priv->cur.vb, priv->next.vb);
-+ spin_lock_irqsave(&priv->lock, flags);
-+
-+ at91sam9x5_video_write32(priv, REG_HEOIDR,
-+ REG_HEOIxR_ADD | REG_HEOIxR_DMA |
-+ REG_HEOIxR_UADD | REG_HEOIxR_UDMA |
-+ REG_HEOIxR_VADD | REG_HEOIxR_VDMA);
-+
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+}
-+
-+static int at91sam9x5_video_vb_buf_prepare(struct vb2_buffer *vb)
-+{
-+ struct vb2_queue *q = vb->vb2_queue;
-+ struct at91sam9x5_video_priv *priv =
-+ container_of(q, struct at91sam9x5_video_priv, queue);
-+ struct v4l2_pix_format *pix = &priv->fmt_vid_out_cur;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+ if (priv->cfgupdate)
-+ pix = &priv->fmt_vid_out_next;
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ debug("vout=%ux%u\n", pix->width, pix->height);
-+ debug("buflen=%u\n", vb->v4l2_planes[0].length);
-+
-+ /* XXX: format-dependant */
-+ if (vb->v4l2_planes[0].length < pix->width * pix->height +
-+ ALIGN(pix->width, 2) * ALIGN(pix->height, 2) / 2 +
-+ 10 * 32)
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+static void at91sam9x5_video_vb_buf_queue(struct vb2_buffer *vb)
-+{
-+ struct vb2_queue *q = vb->vb2_queue;
-+ struct at91sam9x5_video_priv *priv =
-+ container_of(q, struct at91sam9x5_video_priv, queue);
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+
-+ at91sam9x5_video_update_config(priv, 0);
-+
-+ switch (priv->cfgstate) {
-+ case at91sam9x5_video_CFG_GOOD:
-+ case at91sam9x5_video_CFG_GOOD_LATCH:
-+ /* show_buf takes care of the eventual hwstate update */
-+ at91sam9x5_video_show_buf(priv, vb);
-+ break;
-+
-+ case at91sam9x5_video_CFG_BAD:
-+ vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
-+ priv->hwstate = at91sam9x5_video_HW_RUNNING;
-+ break;
-+ }
-+
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+}
-+
-+const struct vb2_ops at91sam9x5_video_vb_ops = {
-+ .queue_setup = at91sam9x5_video_vb_queue_setup,
-+
-+ .wait_prepare = at91sam9x5_video_vb_wait_prepare,
-+ .wait_finish = at91sam9x5_video_vb_wait_finish,
-+
-+ .buf_prepare = at91sam9x5_video_vb_buf_prepare,
-+ .buf_queue = at91sam9x5_video_vb_buf_queue,
-+};
-+
-+static int at91sam9x5_video_vidioc_querycap(struct file *filp,
-+ void *fh, struct v4l2_capability *cap)
-+{
-+ strcpy(cap->driver, DRIVER_NAME);
-+ cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING |
-+ V4L2_CAP_VIDEO_OVERLAY;
-+
-+ /* XXX */
-+ cap->version = 0;
-+ cap->card[0] = '\0';
-+ cap->bus_info[0] = '\0';
-+
-+ return 0;
-+}
-+
-+static int at91sam9x5_video_vidioc_g_fmt_vid_out(struct file *filp,
-+ void *fh, struct v4l2_format *f)
-+{
-+ struct video_device *vdev = filp->private_data;
-+ struct at91sam9x5_video_priv *priv = video_get_drvdata(vdev);
-+ unsigned long flags;
-+
-+ if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-+ return -EINVAL;
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+
-+ f->fmt.pix = priv->fmt_vid_out_next;
-+
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+ return 0;
-+}
-+
-+static int at91sam9x5_video_vidioc_s_fmt_vid_out(struct file *filp,
-+ void *fh, struct v4l2_format *f)
-+{
-+ struct video_device *vdev = filp->private_data;
-+ struct at91sam9x5_video_priv *priv = video_get_drvdata(vdev);
-+ struct v4l2_pix_format *pix = &f->fmt.pix;
-+ unsigned long flags;
-+
-+ if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-+ return -EINVAL;
-+
-+ if (pix->pixelformat != V4L2_PIX_FMT_YUV420)
-+ return -EINVAL;
-+
-+ debug("vout=%ux%u\n", pix->width, pix->height);
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+
-+ priv->fmt_vid_out_next = *pix;
-+
-+ priv->cfgupdate = 1;
-+
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ return 0;
-+}
-+
-+static int at91sam9x5_video_vidioc_g_fmt_vid_overlay(struct file *filp,
-+ void *fh, struct v4l2_format *f)
-+{
-+ struct video_device *vdev = filp->private_data;
-+ struct at91sam9x5_video_priv *priv = video_get_drvdata(vdev);
-+ unsigned long flags;
-+
-+ if (f->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
-+ return -EINVAL;
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+
-+ f->fmt.win = priv->fmt_vid_overlay;
-+
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ return 0;
-+}
-+
-+static int at91sam9x5_video_vidioc_s_fmt_vid_overlay(struct file *filp,
-+ void *fh, struct v4l2_format *f)
-+{
-+ struct video_device *vdev = filp->private_data;
-+ struct at91sam9x5_video_priv *priv = video_get_drvdata(vdev);
-+ struct v4l2_window *win = &f->fmt.win;
-+ unsigned long flags;
-+
-+ if (f->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
-+ return -EINVAL;
-+
-+ debug("rect=(%d,%d)+(%d,%d)\n",
-+ win->w.left, win->w.top, win->w.width, win->w.height);
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+
-+ priv->fmt_vid_overlay = *win;
-+
-+ at91sam9x5_video_update_config(priv, 1);
-+
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ return 0;
-+}
-+
-+static int at91sam9x5_video_vidioc_enum_fmt_vid_out(struct file *filp,
-+ void *fh, struct v4l2_fmtdesc *f)
-+{
-+ /* XXX: support more formats */
-+ if (f->index > 0)
-+ return -EINVAL;
-+
-+ f->pixelformat = V4L2_PIX_FMT_YUV420;
-+ return 0;
-+}
-+
-+static int at91sam9x5_video_vidioc_reqbufs(struct file *filp,
-+ void *fh, struct v4l2_requestbuffers *b)
-+{
-+ struct video_device *vdev = filp->private_data;
-+ struct at91sam9x5_video_priv *priv = video_get_drvdata(vdev);
-+ struct vb2_queue *q = &priv->queue;
-+
-+ if (b->type != q->type) {
-+ dev_err(&priv->pdev->dev, "invalid buffer type (%d != %d)\n",
-+ b->type, q->type);
-+ return -EINVAL;
-+ }
-+
-+ return vb2_reqbufs(q, b);
-+}
-+
-+static int at91sam9x5_video_vidioc_querybuf(struct file *filp,
-+ void *fh, struct v4l2_buffer *b)
-+{
-+ struct video_device *vdev = filp->private_data;
-+ struct at91sam9x5_video_priv *priv = video_get_drvdata(vdev);
-+
-+ return vb2_querybuf(&priv->queue, b);
-+}
-+
-+static int at91sam9x5_video_vidioc_qbuf(struct file *filp,
-+ void *fh, struct v4l2_buffer *b)
-+{
-+ struct video_device *vdev = filp->private_data;
-+ struct at91sam9x5_video_priv *priv = video_get_drvdata(vdev);
-+
-+ return vb2_qbuf(&priv->queue, b);
-+}
-+
-+static int at91sam9x5_video_vidioc_dqbuf(struct file *filp,
-+ void *fh, struct v4l2_buffer *b)
-+{
-+ struct video_device *vdev = filp->private_data;
-+ struct at91sam9x5_video_priv *priv = video_get_drvdata(vdev);
-+
-+ return vb2_dqbuf(&priv->queue, b, filp->f_flags & O_NONBLOCK);
-+}
-+
-+static int at91sam9x5_video_vidioc_streamon(struct file *filp,
-+ void *fh, enum v4l2_buf_type type)
-+{
-+ struct video_device *vdev = video_devdata(filp);
-+ struct at91sam9x5_video_priv *priv = video_get_drvdata(vdev);
-+
-+ return vb2_streamon(&priv->queue, type);
-+}
-+
-+static int at91sam9x5_video_vidioc_streamoff(struct file *filp,
-+ void *fh, enum v4l2_buf_type type)
-+{
-+ struct video_device *vdev = video_devdata(filp);
-+ struct at91sam9x5_video_priv *priv = video_get_drvdata(vdev);
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+
-+ /* disable channel */
-+ at91sam9x5_video_write32(priv, REG_HEOCHDR, REG_HEOCHDR_CHDIS);
-+
-+ at91sam9x5_video_handle_irqstat(priv);
-+
-+ if (priv->cur.vb)
-+ at91sam9x5_video_write32(priv, REG_HEOIER,
-+ REG_HEOIxR_ADD | REG_HEOIxR_DMA |
-+ REG_HEOIxR_UADD | REG_HEOIxR_UDMA |
-+ REG_HEOIxR_VADD | REG_HEOIxR_VDMA);
-+
-+ priv->hwstate = at91sam9x5_video_HW_IDLE;
-+
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ return vb2_streamoff(&priv->queue, type);
-+}
-+
-+static int at91sam9x5_video_vidioc_queryctrl(struct file *filp, void *fh,
-+ struct v4l2_queryctrl *a)
-+{
-+ int ret;
-+
-+ switch (a->id) {
-+ case V4L2_CID_ROTATE:
-+ ret = v4l2_ctrl_query_fill(a, 0, 270, 90, 0);
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+static int at91sam9x5_video_vidioc_g_ctrl(struct file *filp, void *fh,
-+ struct v4l2_control *a)
-+{
-+ struct video_device *vdev = video_devdata(filp);
-+ struct at91sam9x5_video_priv *priv = video_get_drvdata(vdev);
-+ int ret = 0;
-+
-+ switch (a->id) {
-+ case V4L2_CID_ROTATE:
-+ a->value = 90 * priv->rotation;
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+static int at91sam9x5_video_vidioc_s_ctrl(struct file *filp, void *fh,
-+ struct v4l2_control *a)
-+{
-+ struct video_device *vdev = video_devdata(filp);
-+ struct at91sam9x5_video_priv *priv = video_get_drvdata(vdev);
-+ int ret;
-+ unsigned long flags;
-+
-+ switch (a->id) {
-+ case V4L2_CID_ROTATE:
-+ if (a->value / 90 * 90 != a->value ||
-+ (a->value / 90) % 4 != a->value / 90) {
-+ ret = -EINVAL;
-+ } else {
-+ debug("rotation: %d\n", a->value);
-+ spin_lock_irqsave(&priv->lock, flags);
-+ priv->rotation = a->value / 90;
-+ at91sam9x5_video_update_config(priv, 1);
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+ }
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+static const struct v4l2_ioctl_ops at91sam9x5_video_ioctl_ops = {
-+ .vidioc_querycap = at91sam9x5_video_vidioc_querycap,
-+ .vidioc_g_fmt_vid_out = at91sam9x5_video_vidioc_g_fmt_vid_out,
-+ .vidioc_s_fmt_vid_out = at91sam9x5_video_vidioc_s_fmt_vid_out,
-+ .vidioc_g_fmt_vid_overlay = at91sam9x5_video_vidioc_g_fmt_vid_overlay,
-+ .vidioc_s_fmt_vid_overlay = at91sam9x5_video_vidioc_s_fmt_vid_overlay,
-+ .vidioc_enum_fmt_vid_out = at91sam9x5_video_vidioc_enum_fmt_vid_out,
-+ .vidioc_reqbufs = at91sam9x5_video_vidioc_reqbufs,
-+ .vidioc_querybuf = at91sam9x5_video_vidioc_querybuf,
-+ .vidioc_qbuf = at91sam9x5_video_vidioc_qbuf,
-+ .vidioc_dqbuf = at91sam9x5_video_vidioc_dqbuf,
-+ .vidioc_streamon = at91sam9x5_video_vidioc_streamon,
-+ .vidioc_streamoff = at91sam9x5_video_vidioc_streamoff,
-+ .vidioc_queryctrl = at91sam9x5_video_vidioc_queryctrl,
-+ .vidioc_g_ctrl = at91sam9x5_video_vidioc_g_ctrl,
-+ .vidioc_s_ctrl = at91sam9x5_video_vidioc_s_ctrl,
-+};
-+
-+static int at91sam9x5_video_open(struct file *filp)
-+{
-+ struct video_device *vdev = video_devdata(filp);
-+
-+ /*
-+ * XXX: allow only one open? Or is that already enforced by the
-+ * framework?
-+ */
-+ filp->private_data = vdev;
-+
-+ return 0;
-+}
-+
-+static int at91sam9x5_video_release(struct file *filp)
-+{
-+ struct video_device *vdev = video_devdata(filp);
-+
-+ dev_dbg(&vdev->dev, "%s\n", __func__);
-+
-+ return 0;
-+}
-+
-+static int at91sam9x5_video_mmap(struct file *filp, struct vm_area_struct *vma)
-+{
-+ struct video_device *vdev = video_devdata(filp);
-+ struct at91sam9x5_video_priv *priv = video_get_drvdata(vdev);
-+
-+ dev_dbg(&vdev->dev, "%s\n", __func__);
-+
-+ /* returning -EIO here makes gst-launch segfault */
-+ return vb2_mmap(&priv->queue, vma);
-+}
-+
-+static struct v4l2_file_operations at91sam9x5_video_fops = {
-+ .owner = THIS_MODULE,
-+ .open = at91sam9x5_video_open,
-+ .release = at91sam9x5_video_release,
-+ .ioctl = video_ioctl2,
-+ .mmap = at91sam9x5_video_mmap,
-+};
-+
-+static int at91sam9x5_video_register(struct at91sam9x5_video_priv *priv,
-+ struct fb_info *fbinfo)
-+{
-+ int ret = -ENOMEM;
-+ struct platform_device *pdev = priv->pdev;
-+ struct resource *res;
-+ const struct at91sam9x5_video_pdata *pdata =
-+ dev_get_platdata(&pdev->dev);
-+ struct vb2_queue *q = &priv->queue;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+ if (priv->fbinfo) {
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+ return -EBUSY;
-+ }
-+ priv->fbinfo = fbinfo;
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ /* XXX: this doesn't belong here, does it? */
-+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-+
-+ if (!pdata) {
-+ dev_err(&pdev->dev, "failed to get platform data\n");
-+ goto err_get_pdata;
-+ }
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!res) {
-+ dev_err(&pdev->dev, "failed to get register base\n");
-+ goto err_get_regbase;
-+ }
-+
-+ priv->regbase = ioremap(res->start, resource_size(res));
-+ if (!priv->regbase) {
-+ dev_err(&pdev->dev, "failed to remap register base\n");
-+ goto err_ioremap;
-+ }
-+
-+ /*
-+ * XXX: video_device_alloc is just a kzalloc, so embedding struct
-+ * video_device into struct at91sam9x5_video_priv would work, too.
-+ * Is that allowed?
-+ */
-+ priv->video_dev = video_device_alloc();
-+ if (!priv->video_dev) {
-+ dev_err(&pdev->dev, "failed to alloc video device for %p\n",
-+ fbinfo);
-+ goto err_video_device_alloc;
-+ }
-+
-+ priv->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
-+ if (IS_ERR(priv->alloc_ctx)) {
-+ ret = PTR_ERR(priv->alloc_ctx);
-+ dev_err(&pdev->dev, "failed to init alloc_ctx (%d)\n", ret);
-+ goto err_init_ctx;
-+ }
-+
-+ q->ops = &at91sam9x5_video_vb_ops;
-+ q->mem_ops = &vb2_dma_contig_memops;
-+ q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-+ q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_WRITE;
-+
-+ ret = vb2_queue_init(q);
-+ if (ret) {
-+ dev_err(&pdev->dev, "failed to init queue (%d)\n", ret);
-+ goto err_queue_init;
-+ }
-+
-+ priv->video_dev->fops = &at91sam9x5_video_fops;
-+ priv->video_dev->ioctl_ops = &at91sam9x5_video_ioctl_ops;
-+ priv->video_dev->release = video_device_release;
-+
-+ video_set_drvdata(priv->video_dev, priv);
-+
-+ /* reset channel and clear status */
-+ at91sam9x5_video_write32(priv, REG_HEOCHDR, REG_HEOCHDR_CHRST);
-+ (void)at91sam9x5_video_read32(priv, REG_HEOISR);
-+
-+ /* set maximal bursting */
-+ at91sam9x5_video_write32(priv, REG_HEOCFG0,
-+ REG_HEOCFG0_BLEN_INCR16 |
-+ REG_HEOCFG0_BLENUV_INCR16);
-+
-+ ret = platform_get_irq(pdev, 0);
-+ if (ret <= 0) {
-+ dev_err(&pdev->dev, "failed to get irq from resources (%d)\n",
-+ ret);
-+ if (!ret)
-+ ret = -ENXIO;
-+ goto err_get_irq;
-+ }
-+ priv->irq = ret;
-+
-+ ret = request_irq(priv->irq, at91sam9x5_video_irq, IRQF_SHARED,
-+ DRIVER_NAME, priv);
-+ if (ret) {
-+ dev_err(&pdev->dev, "failed to request irq (%d)\n", ret);
-+ goto err_request_irq;
-+ }
-+
-+ ret = video_register_device(priv->video_dev,
-+ /* XXX: really grabber? */ VFL_TYPE_GRABBER, -1);
-+ if (ret) {
-+ dev_err(&pdev->dev, "failed to register video device (%d)\n",
-+ ret);
-+
-+ free_irq(priv->irq, priv);
-+ err_request_irq:
-+ err_get_irq:
-+
-+ vb2_queue_release(q);
-+err_queue_init:
-+
-+ vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
-+ err_init_ctx:
-+
-+ video_device_release(priv->video_dev);
-+ err_video_device_alloc:
-+
-+ iounmap(priv->regbase);
-+
-+ priv->fbinfo = NULL;
-+ }
-+ err_ioremap:
-+ err_get_regbase:
-+ err_get_pdata:
-+
-+ return ret;
-+}
-+
-+static void at91sam9x5_video_unregister(struct at91sam9x5_video_priv *priv)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+
-+ if (!priv->fbinfo) {
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+ return;
-+ }
-+ /* XXX: handle fbinfo being NULL in various callbacks */
-+ priv->fbinfo = NULL;
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ /* silence DMA */
-+ at91sam9x5_video_write32(priv, REG_HEOIDR,
-+ REG_HEOIxR_ADD | REG_HEOIxR_DMA | REG_HEOIxR_UADD |
-+ REG_HEOIxR_UDMA | REG_HEOIxR_VADD | REG_HEOIxR_VDMA);
-+
-+ video_unregister_device(priv->video_dev);
-+ free_irq(priv->irq, priv);
-+ vb2_queue_release(&priv->queue);
-+ vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
-+ video_device_release(priv->video_dev);
-+ iounmap(priv->regbase);
-+}
-+
-+static int at91sam9x5_video_fb_event_notify(struct notifier_block *self,
-+ unsigned long action, void *data)
-+{
-+ struct at91sam9x5_video_priv *priv =
-+ container_of(self, struct at91sam9x5_video_priv, fb_notifier);
-+ struct fb_event *event = data;
-+ struct fb_info *fbinfo = event->info;
-+
-+ /* XXX: only do this for atmel_lcdfb devices! */
-+ switch (action) {
-+ case FB_EVENT_FB_REGISTERED:
-+ at91sam9x5_video_register(priv, fbinfo);
-+ break;
-+
-+ case FB_EVENT_FB_UNREGISTERED:
-+ at91sam9x5_video_unregister(priv);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static int __devinit at91sam9x5_video_probe(struct platform_device *pdev)
-+{
-+ int ret = -ENOMEM;
-+ size_t i;
-+ struct at91sam9x5_video_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-+
-+ if (!priv) {
-+ dev_err(&pdev->dev, "failed to allocate driver private data\n");
-+ goto err_alloc_priv;
-+ }
-+
-+ priv->pdev = pdev;
-+ priv->fb_notifier.notifier_call = at91sam9x5_video_fb_event_notify;
-+
-+ platform_set_drvdata(pdev, priv);
-+
-+ spin_lock_init(&priv->lock);
-+
-+ ret = fb_register_client(&priv->fb_notifier);
-+ if (ret) {
-+ dev_err(&pdev->dev, "failed to register fb client (%d)\n", ret);
-+
-+ kfree(priv);
-+err_alloc_priv:
-+
-+ return ret;
-+ }
-+
-+ /* XXX: This is racy. If a new fb is registered then
-+ * at91sam9x5_video_register is called twice. This should be solved
-+ * somewhere in drivers/fb. priv->fbinfo is used to prevent multiple
-+ * registration.
-+ */
-+
-+ for (i = 0; i < ARRAY_SIZE(registered_fb); ++i)
-+ if (registered_fb[i])
-+ at91sam9x5_video_register(priv, registered_fb[i]);
-+
-+ return 0;
-+}
-+
-+int __devexit at91sam9x5_video_remove(struct platform_device *pdev)
-+{
-+ struct at91sam9x5_video_priv *priv = platform_get_drvdata(pdev);
-+
-+ fb_unregister_client(&priv->fb_notifier);
-+ at91sam9x5_video_unregister(priv);
-+ kfree(priv);
-+
-+ return 0;
-+}
-+
-+static struct platform_driver at91sam9x5_video_driver = {
-+ .driver = {
-+ .name = DRIVER_NAME,
-+ .owner = THIS_MODULE,
-+ },
-+ .probe = at91sam9x5_video_probe,
-+ .remove = at91sam9x5_video_remove,
-+};
-+
-+static struct platform_device *at91sam9x5_video_device;
-+static int __init at91sam9x5_video_init(void)
-+{
-+ /* XXX: register the device in arch/arm/mach-at91 */
-+ int ret;
-+ const struct resource res[] = {
-+ {
-+ .start = 0xf8038280,
-+ .end = 0xf803833f,
-+ .flags = IORESOURCE_MEM,
-+ }, {
-+ .start = 25,
-+ .end = 25,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ };
-+ const struct at91sam9x5_video_pdata pdata = {
-+ .base_width = 800,
-+ .base_height = 480,
-+ };
-+
-+ ret = platform_driver_register(&at91sam9x5_video_driver);
-+ if (ret) {
-+ pr_err("failed to register driver (%d)", ret);
-+ goto err_driver_register;
-+ }
-+
-+ at91sam9x5_video_device = platform_device_register_resndata(NULL,
-+ DRIVER_NAME, -1,
-+ res, ARRAY_SIZE(res), &pdata, sizeof(pdata));
-+ if (IS_ERR(at91sam9x5_video_device)) {
-+ ret = PTR_ERR(at91sam9x5_video_device);
-+ pr_err("failed to register device (%d)", ret);
-+ platform_driver_unregister(&at91sam9x5_video_driver);
-+ }
-+
-+ err_driver_register:
-+ return ret;
-+}
-+module_init(at91sam9x5_video_init);
-+
-+static void __exit at91sam9x5_video_exit(void)
-+{
-+ platform_device_unregister(at91sam9x5_video_device);
-+ platform_driver_unregister(&at91sam9x5_video_driver);
-+}
-+module_exit(at91sam9x5_video_exit);
-+
-+MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>");
-+MODULE_LICENSE("GPL v2");
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 4518de39893c780fa549a88ee1d671c152c3b1a6 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 9 Oct 2012 18:23:51 +0200
-Subject: video: atmel_lcdfb*: protect bl_power with
- CONFIG_BACKLIGHT_ATMEL_LCDC
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/video/atmel_hlcdfb.c | 24 +++++++++++++++++++-----
- drivers/video/atmel_lcdfb.c | 24 +++++++++++++++++++-----
- 2 files changed, 38 insertions(+), 10 deletions(-)
-
-diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c
-index a629dda..db6ec3e 100644
---- a/drivers/video/atmel_hlcdfb.c
-+++ b/drivers/video/atmel_hlcdfb.c
-@@ -94,6 +94,7 @@ static void atmel_hlcdfb_update_dma_ovl(struct fb_info *info,
- lcdc_writel(sinfo, ATMEL_LCDC_OVRCHER1, LCDC_OVRCHER1_CHEN | LCDC_OVRCHER1_UPDATEEN);
- }
-
-+#if defined(CONFIG_BACKLIGHT_ATMEL_LCDC)
- /* some bl->props field just changed */
- static int atmel_bl_update_status(struct backlight_device *bl)
- {
-@@ -133,17 +134,30 @@ static int atmel_bl_get_brightness(struct backlight_device *bl)
- return lcdc_readl(sinfo, ATMEL_LCDC_LCDCFG6) >> LCDC_LCDCFG6_PWMCVAL_OFFSET;
- }
-
--static const struct backlight_ops atmel_hlcdc_bl_ops = {
-- .update_status = atmel_bl_update_status,
-- .get_brightness = atmel_bl_get_brightness,
--};
--
- static void atmel_hlcdfb_init_contrast(struct atmel_lcdfb_info *sinfo)
- {
- /* have some default contrast/backlight settings */
- lcdc_writel(sinfo, ATMEL_LCDC_LCDCFG6, LCDC_LCDCFG6_PWMPOL |
- (ATMEL_LCDC_CVAL_DEFAULT << LCDC_LCDCFG6_PWMCVAL_OFFSET));
- }
-+#else
-+static int atmel_bl_update_status(struct backlight_device *bl)
-+{
-+ return 0;
-+}
-+
-+static int atmel_bl_get_brightness(struct backlight_device *bl)
-+{
-+ return ATMEL_LCDC_CVAL_DEFAULT;
-+}
-+
-+static void atmel_hlcdfb_init_contrast(struct atmel_lcdfb_info *sinfo) {}
-+#endif
-+
-+static const struct backlight_ops atmel_hlcdc_bl_ops = {
-+ .update_status = atmel_bl_update_status,
-+ .get_brightness = atmel_bl_get_brightness,
-+};
-
- void atmel_hlcdfb_start(struct atmel_lcdfb_info *sinfo)
- {
-diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
-index 86e3e32..651c88f 100644
---- a/drivers/video/atmel_lcdfb.c
-+++ b/drivers/video/atmel_lcdfb.c
-@@ -86,6 +86,7 @@ static void atmel_lcdfb_update_dma(struct fb_info *info,
- atmel_lcdfb_update_dma2d(sinfo, var);
- }
-
-+#if defined(CONFIG_BACKLIGHT_ATMEL_LCDC)
- /* some bl->props field just changed */
- static int atmel_bl_update_status(struct backlight_device *bl)
- {
-@@ -123,11 +124,6 @@ static int atmel_bl_get_brightness(struct backlight_device *bl)
- return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
- }
-
--static const struct backlight_ops atmel_lcdc_bl_ops = {
-- .update_status = atmel_bl_update_status,
-- .get_brightness = atmel_bl_get_brightness,
--};
--
- static void atmel_lcdfb_init_contrast(struct atmel_lcdfb_info *sinfo)
- {
- /* contrast pwm can be 'inverted' */
-@@ -138,6 +134,24 @@ static void atmel_lcdfb_init_contrast(struct atmel_lcdfb_info *sinfo)
- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
- }
-+#else
-+static int atmel_bl_update_status(struct backlight_device *bl)
-+{
-+ return 0;
-+}
-+
-+static int atmel_bl_get_brightness(struct backlight_device *bl)
-+{
-+ return ATMEL_LCDC_CVAL_DEFAULT;
-+}
-+
-+static void atmel_lcdfb_init_contrast(struct atmel_lcdfb_info *sinfo) {}
-+#endif
-+
-+static const struct backlight_ops atmel_lcdc_bl_ops = {
-+ .update_status = atmel_bl_update_status,
-+ .get_brightness = atmel_bl_get_brightness,
-+};
-
- void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo)
- {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From baff53548e8947d970076daf0f1322c9afdadd9f Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 16 Oct 2012 18:21:15 +0200
-Subject: ARM: at91/9x5: modify consistent DMA size
-
-update to 8M
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/at91sam9x5.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
-index c949dc7..7eb00c53 100644
---- a/arch/arm/mach-at91/at91sam9x5.c
-+++ b/arch/arm/mach-at91/at91sam9x5.c
-@@ -302,6 +302,7 @@ static void __init at91sam9x5_register_clocks(void)
- static void __init at91sam9x5_map_io(void)
- {
- at91_init_sram(0, AT91SAM9X5_SRAM_BASE, AT91SAM9X5_SRAM_SIZE);
-+ init_consistent_dma_size(SZ_8M);
- }
-
- void __init at91sam9x5_initialize(void)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 4cb1b0adbd898531ca518f009a6086777d69cf0f Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 16 Oct 2012 18:23:00 +0200
-Subject: video: atmel_lcdfb: adapt to all IP configurations
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/include/mach/atmel_hlcdc.h | 3 +--
- drivers/video/atmel_hlcdfb.c | 14 ++++++++++++--
- 2 files changed, 13 insertions(+), 4 deletions(-)
-
-diff --git a/arch/arm/mach-at91/include/mach/atmel_hlcdc.h b/arch/arm/mach-at91/include/mach/atmel_hlcdc.h
-index 738a853..71ccb96 100644
---- a/arch/arm/mach-at91/include/mach/atmel_hlcdc.h
-+++ b/arch/arm/mach-at91/include/mach/atmel_hlcdc.h
-@@ -157,8 +157,7 @@
- #define LCDC_LCDISR_BASE (0x1 << 8)
- #define LCDC_LCDISR_OVR1 (0x1 << 9)
- #define LCDC_LCDISR_OVR2 (0x1 << 10)
--#define LCDC_LCDISR_HEO (0x1 << 10)
--#define LCDC2_LCDISR_HEO (0x1 << 11)
-+#define LCDC_LCDISR_HEO (0x1 << 11)
- #define LCDC_LCDISR_HCR (0x1 << 12)
- #define LCDC_LCDISR_PP (0x1 << 13)
-
-diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c
-index db6ec3e..262c15b 100644
---- a/drivers/video/atmel_hlcdfb.c
-+++ b/drivers/video/atmel_hlcdfb.c
-@@ -370,6 +370,16 @@ static int atmel_hlcdfb_setup_core_ovl(struct fb_info *info)
- }
- static void atmelfb_limit_screeninfo(struct fb_var_screeninfo *var)
- {
-+ u32 hbpw, hfpw;
-+
-+ if (cpu_is_at91sam9x5()) {
-+ hbpw = LCDC_LCDCFG3_HBPW;
-+ hfpw = LCDC_LCDCFG3_HFPW;
-+ } else {
-+ hbpw = LCDC2_LCDCFG3_HBPW;
-+ hfpw = LCDC2_LCDCFG3_HFPW;
-+ }
-+
- /* Saturate vertical and horizontal timings at maximum values */
- var->vsync_len = min_t(u32, var->vsync_len,
- (LCDC_LCDCFG1_VSPW >> LCDC_LCDCFG1_VSPW_OFFSET) + 1);
-@@ -378,11 +388,11 @@ static void atmelfb_limit_screeninfo(struct fb_var_screeninfo *var)
- var->lower_margin = min_t(u32, var->lower_margin,
- LCDC_LCDCFG2_VBPW >> LCDC_LCDCFG2_VBPW_OFFSET);
- var->right_margin = min_t(u32, var->right_margin,
-- (LCDC2_LCDCFG3_HBPW >> LCDC_LCDCFG3_HBPW_OFFSET) + 1);
-+ (hbpw >> LCDC_LCDCFG3_HBPW_OFFSET) + 1);
- var->hsync_len = min_t(u32, var->hsync_len,
- (LCDC_LCDCFG1_HSPW >> LCDC_LCDCFG1_HSPW_OFFSET) + 1);
- var->left_margin = min_t(u32, var->left_margin,
-- (LCDC2_LCDCFG3_HFPW >> LCDC_LCDCFG3_HFPW_OFFSET) + 1);
-+ (hfpw >> LCDC_LCDCFG3_HFPW_OFFSET) + 1);
-
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b2453fc81b197e3fbcfebdc3be5509dcaea82f59 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 16 Oct 2012 18:26:10 +0200
-Subject: media/at91sam9x5-video: cleanup modifications
-
-pdata not used: remove them for now: ease transition to DT
-one type, one static, and one debug message modifications
-
-Can we squashed in another patch...
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/media/video/at91sam9x5-video.c | 22 ++++++++++++++--------
- 1 file changed, 14 insertions(+), 8 deletions(-)
-
-diff --git a/drivers/media/video/at91sam9x5-video.c b/drivers/media/video/at91sam9x5-video.c
-index 26ce376..c83dad1 100644
---- a/drivers/media/video/at91sam9x5-video.c
-+++ b/drivers/media/video/at91sam9x5-video.c
-@@ -347,8 +347,7 @@ static irqreturn_t at91sam9x5_video_irq(int irq, void *data)
- heoimr = at91sam9x5_video_read32(priv, REG_HEOIMR);
- handled = at91sam9x5_video_handle_irqstat(priv);
-
-- debug("%x, HEOCHSR = %08x\n", handled,
-- at91sam9x5_video_read32(priv, REG_HEOCHSR));
-+ debug("HEOIMR = 0x%08x, HEOCHSR = 0x%08x\n", heoimr, handled);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
-@@ -475,7 +474,7 @@ static void at91sam9x5_video_show_buf(struct at91sam9x5_video_priv *priv,
- priv->next.plane_size[2] = priv->plane_size[2];
- }
-
--static int experimental;
-+static bool experimental;
- module_param(experimental, bool, 0644);
- MODULE_PARM_DESC(experimental, "enable experimental features");
-
-@@ -1155,8 +1154,8 @@ static int at91sam9x5_video_register(struct at91sam9x5_video_priv *priv,
- int ret = -ENOMEM;
- struct platform_device *pdev = priv->pdev;
- struct resource *res;
-- const struct at91sam9x5_video_pdata *pdata =
-- dev_get_platdata(&pdev->dev);
-+ /*const struct at91sam9x5_video_pdata *pdata =
-+ dev_get_platdata(&pdev->dev);*/
- struct vb2_queue *q = &priv->queue;
- unsigned long flags;
-
-@@ -1171,10 +1170,13 @@ static int at91sam9x5_video_register(struct at91sam9x5_video_priv *priv,
- /* XXX: this doesn't belong here, does it? */
- pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-
-+ /* Not used for now */
-+#if 0
- if (!pdata) {
- dev_err(&pdev->dev, "failed to get platform data\n");
- goto err_get_pdata;
- }
-+#endif
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
-@@ -1272,10 +1274,14 @@ err_queue_init:
- iounmap(priv->regbase);
-
- priv->fbinfo = NULL;
-+ } else {
-+ dev_info(&pdev->dev,
-+ "video device registered @ 0x%08x, irq = %d\n",
-+ (unsigned int)priv->regbase, priv->irq);
- }
- err_ioremap:
- err_get_regbase:
-- err_get_pdata:
-+/* err_get_pdata:*/
-
- return ret;
- }
-@@ -1369,7 +1375,7 @@ err_alloc_priv:
- return 0;
- }
-
--int __devexit at91sam9x5_video_remove(struct platform_device *pdev)
-+static int __devexit at91sam9x5_video_remove(struct platform_device *pdev)
- {
- struct at91sam9x5_video_priv *priv = platform_get_drvdata(pdev);
-
-@@ -1386,7 +1392,7 @@ static struct platform_driver at91sam9x5_video_driver = {
- .owner = THIS_MODULE,
- },
- .probe = at91sam9x5_video_probe,
-- .remove = at91sam9x5_video_remove,
-+ .remove = __devexit_p(at91sam9x5_video_remove),
- };
-
- static struct platform_device *at91sam9x5_video_device;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From d97e93bccbd81a88c5c60553b1dca5d59f23aa08 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 16 Oct 2012 18:29:45 +0200
-Subject: media/at91sam9x5-video: align DMA descriptors on 64 bits
-
-Needed for future revisions of the LCD ip
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/media/video/at91sam9x5-video.c | 46 ++++++++++++++++++++--------------
- 1 file changed, 27 insertions(+), 19 deletions(-)
-
-diff --git a/drivers/media/video/at91sam9x5-video.c b/drivers/media/video/at91sam9x5-video.c
-index c83dad1..9d7e6c5 100644
---- a/drivers/media/video/at91sam9x5-video.c
-+++ b/drivers/media/video/at91sam9x5-video.c
-@@ -375,7 +375,7 @@ static void at91sam9x5_video_show_buf(struct at91sam9x5_video_priv *priv,
- struct v4l2_pix_format *pix = &priv->fmt_vid_out_cur;
- /* XXX: format dependant */
- size_t offset_dmadesc = ALIGN(pix->width * pix->height +
-- ALIGN(pix->width, 2) * ALIGN(pix->height, 2) / 2, 32);
-+ ALIGN(pix->width, 2) * ALIGN(pix->height, 2) / 2, 64);
- u32 *dmadesc = vaddr + offset_dmadesc;
- u32 heocher;
-
-@@ -388,23 +388,30 @@ static void at91sam9x5_video_show_buf(struct at91sam9x5_video_priv *priv,
- }
-
- debug("vout=%ux%u, heocher=%08x\n", pix->width, pix->height, heocher);
-+ debug("dmadesc @ 0x%08x\n", dmadesc);
-+ debug("dmadesc u @ 0x%08x\n", &dmadesc[4]);
-+ debug("dmadesc v @ 0x%08x\n", &dmadesc[8]);
-
- dmadesc[0] = buffer + priv->y_offset;
- dmadesc[1] = REG_HEOxCTRL_DFETCH;
- dmadesc[2] = buffer + offset_dmadesc;
-+ /* dmadesc[3] not used to align U plane descriptor */
-
- if (priv->u_planeno >= 0) {
-- dmadesc[3] = vb2_dma_contig_plane_dma_addr(vb, priv->u_planeno) +
-+ dmadesc[4] = vb2_dma_contig_plane_dma_addr(vb, priv->u_planeno) +
- priv->u_offset;
-- dmadesc[4] = REG_HEOxCTRL_DFETCH;
-- dmadesc[5] = buffer + offset_dmadesc + 3 * 4;
-+ dmadesc[5] = REG_HEOxCTRL_DFETCH;
-+ /* link to physical address of this U descriptor */
-+ dmadesc[6] = buffer + offset_dmadesc + 4 * 4;
- }
-+ /* dmadesc[7] not used to align V plane descriptor */
-
- if (priv->v_planeno >= 0) {
-- dmadesc[6] = vb2_dma_contig_plane_dma_addr(vb, priv->v_planeno) +
-+ dmadesc[8] = vb2_dma_contig_plane_dma_addr(vb, priv->v_planeno) +
- priv->v_offset;
-- dmadesc[7] = REG_HEOxCTRL_DFETCH;
-- dmadesc[8] = buffer + offset_dmadesc + 6 * 4;
-+ dmadesc[9] = REG_HEOxCTRL_DFETCH;
-+ /* link to physical address of this V descriptor */
-+ dmadesc[10] = buffer + offset_dmadesc + 8 * 4;
- }
-
-
-@@ -415,11 +422,11 @@ static void at91sam9x5_video_show_buf(struct at91sam9x5_video_priv *priv,
-
- if (priv->u_planeno >= 0)
- at91sam9x5_video_write32(priv,
-- REG_HEOUHEAD, dmadesc[5]);
-+ REG_HEOUHEAD, dmadesc[6]);
-
- if (priv->v_planeno >= 0)
- at91sam9x5_video_write32(priv,
-- REG_HEOVHEAD, dmadesc[8]);
-+ REG_HEOVHEAD, dmadesc[10]);
-
- at91sam9x5_video_write32(priv,
- REG_HEOCHER, heocher | REG_HEOCHER_A2QEN);
-@@ -432,20 +439,20 @@ static void at91sam9x5_video_show_buf(struct at91sam9x5_video_priv *priv,
-
- if (priv->u_planeno >= 0) {
- at91sam9x5_video_write32(priv,
-- REG_HEOUADDR, dmadesc[3]);
-+ REG_HEOUADDR, dmadesc[4]);
- at91sam9x5_video_write32(priv,
-- REG_HEOUCTRL, dmadesc[4]);
-+ REG_HEOUCTRL, dmadesc[5]);
- at91sam9x5_video_write32(priv,
-- REG_HEOUNEXT, dmadesc[5]);
-+ REG_HEOUNEXT, dmadesc[6]);
- }
-
- if (priv->v_planeno >= 0) {
- at91sam9x5_video_write32(priv,
-- REG_HEOVADDR, dmadesc[6]);
-+ REG_HEOVADDR, dmadesc[8]);
- at91sam9x5_video_write32(priv,
-- REG_HEOVCTRL, dmadesc[7]);
-+ REG_HEOVCTRL, dmadesc[9]);
- at91sam9x5_video_write32(priv,
-- REG_HEOVNEXT, dmadesc[8]);
-+ REG_HEOVNEXT, dmadesc[10]);
- }
-
- at91sam9x5_video_write32(priv, REG_HEOCHER,
-@@ -713,14 +720,15 @@ static int at91sam9x5_video_vb_queue_setup(struct vb2_queue *q,
- *num_planes = 1;
-
- /*
-- * The last 9 (aligned) words are used for the 3 dma descriptors (3
-- * 32-bit words each). The additional 32 bits are for alignment.
-+ * The last 9 (64 bits aligned) words are used for the 3 dma
-+ * descriptors (3 * 32-bit words each).
-+ * The additional 64 + 2 * 32 bits are for alignment.
- * XXX: is that allowed and done right?
- * XXX: format-dependant
- */
- sizes[0] = pix->width * pix->height +
- ALIGN(pix->width, 2) * ALIGN(pix->height, 2) / 2 +
-- 10 * 32;
-+ 9 * 32 + 128;
- priv->plane_size[0] = sizes[0];
-
- alloc_ctxs[0] = priv->alloc_ctx;
-@@ -787,7 +795,7 @@ static int at91sam9x5_video_vb_buf_prepare(struct vb2_buffer *vb)
- /* XXX: format-dependant */
- if (vb->v4l2_planes[0].length < pix->width * pix->height +
- ALIGN(pix->width, 2) * ALIGN(pix->height, 2) / 2 +
-- 10 * 32)
-+ 9 * 32 + 128)
- return -EINVAL;
-
- return 0;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 5ce36caa7629ccccf5ae2b7c35c578cc2bfedc3f Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 16 Oct 2012 18:30:47 +0200
-Subject: media/at91sam9x5-video: change scaling factor calculation
-
-Useful for future revision of the HEO IP
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/media/video/at91sam9x5-video.c | 36 ++++++++++++++++++++++++++++------
- 1 file changed, 30 insertions(+), 6 deletions(-)
-
-diff --git a/drivers/media/video/at91sam9x5-video.c b/drivers/media/video/at91sam9x5-video.c
-index 9d7e6c5..1e5a0a7 100644
---- a/drivers/media/video/at91sam9x5-video.c
-+++ b/drivers/media/video/at91sam9x5-video.c
-@@ -518,6 +518,19 @@ static void at91sam9x5_video_params(unsigned width, unsigned height,
- *tloffset = e[ro(0)];
- }
-
-+static void at91sam9x5_video_setup_scaling_coef(
-+ struct at91sam9x5_video_priv *priv,
-+ unsigned hwxmem_size, unsigned hwxsize,
-+ unsigned hwymem_size, unsigned hwysize,
-+ unsigned *xphidef, unsigned *yphidef) {}
-+
-+static void at91sam9x5_video_setup_scaling_factor(
-+ unsigned hwmem_size, unsigned hwsize,
-+ unsigned phidef, unsigned *factor)
-+{
-+ *factor = 1024 * hwmem_size / hwsize;
-+}
-+
- static void at91sam9x5_video_update_config_real(
- struct at91sam9x5_video_priv *priv)
- {
-@@ -529,6 +542,9 @@ static void at91sam9x5_video_update_config_real(
-
- unsigned hwxpos, hwypos, hwxsize, hwysize;
- unsigned hwxmem_size, hwymem_size;
-+ unsigned xphidef = 0;
-+ unsigned yphidef = 0;
-+ unsigned xfactor, yfactor;
- s32 hwxstride, hwpstride;
- s32 hwuvxstride, hwuvpstride;
- s32 rotated_pixwidth, rotated_pixheight;
-@@ -600,12 +616,20 @@ static void at91sam9x5_video_update_config_real(
- valtomask(hwxmem_size - 1, REG_HEOCFG4_XMEMSIZE) |
- valtomask(hwymem_size - 1, REG_HEOCFG4_YMEMSIZE));
-
-- at91sam9x5_video_write32(priv, REG_HEOCFG13,
-- REG_HEOCFG13_SCALEN |
-- valtomask(1024 * hwxmem_size / hwxsize,
-- REG_HEOCFG13_XFACTOR) |
-- valtomask(1024 * hwymem_size / hwysize,
-- REG_HEOCFG13_YFACTOR));
-+ at91sam9x5_video_setup_scaling_coef(priv,
-+ hwxmem_size, hwxsize,
-+ hwymem_size, hwysize,
-+ &xphidef, &yphidef);
-+
-+ at91sam9x5_video_setup_scaling_factor(hwxmem_size - 1, hwxsize - 1,
-+ xphidef, &xfactor);
-+
-+ at91sam9x5_video_setup_scaling_factor(hwymem_size - 1, hwysize - 1,
-+ yphidef, &yfactor);
-+
-+ at91sam9x5_video_write32(priv, REG_HEOCFG13, REG_HEOCFG13_SCALEN
-+ | valtomask(xfactor, REG_HEOCFG13_XFACTOR)
-+ | valtomask(yfactor, REG_HEOCFG13_YFACTOR));
-
- at91sam9x5_video_params(pix->width, pix->height, priv->rotation,
- &hwxstride, &hwpstride, &priv->y_offset);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e189f537c714246294a5b552d4d8110fbabb4636 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 16 Oct 2012 18:46:07 +0200
-Subject: media/at91sam9x5-video: add device tree support
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/media/video/at91sam9x5-video.c | 55 +++++++++++-----------------------
- 1 file changed, 18 insertions(+), 37 deletions(-)
-
-diff --git a/drivers/media/video/at91sam9x5-video.c b/drivers/media/video/at91sam9x5-video.c
-index 1e5a0a7..548aebc 100644
---- a/drivers/media/video/at91sam9x5-video.c
-+++ b/drivers/media/video/at91sam9x5-video.c
-@@ -21,6 +21,8 @@
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/slab.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-
- #include <media/v4l2-common.h>
- #include <media/v4l2-dev.h>
-@@ -1418,59 +1420,38 @@ static int __devexit at91sam9x5_video_remove(struct platform_device *pdev)
- return 0;
- }
-
-+#if defined(CONFIG_OF)
-+static const struct of_device_id atmel_heo_dt_ids[] = {
-+ {
-+ .compatible = "atmel,at91sam9x5-heo",
-+ .data = (void *)0,
-+ }, {
-+ /* sentinel */
-+ }
-+};
-+
-+MODULE_DEVICE_TABLE(of, atmel_heo_dt_ids);
-+#endif
-+
- static struct platform_driver at91sam9x5_video_driver = {
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
-+ .of_match_table = of_match_ptr(atmel_heo_dt_ids),
- },
- .probe = at91sam9x5_video_probe,
- .remove = __devexit_p(at91sam9x5_video_remove),
- };
-
--static struct platform_device *at91sam9x5_video_device;
- static int __init at91sam9x5_video_init(void)
- {
-- /* XXX: register the device in arch/arm/mach-at91 */
-- int ret;
-- const struct resource res[] = {
-- {
-- .start = 0xf8038280,
-- .end = 0xf803833f,
-- .flags = IORESOURCE_MEM,
-- }, {
-- .start = 25,
-- .end = 25,
-- .flags = IORESOURCE_IRQ,
-- },
-- };
-- const struct at91sam9x5_video_pdata pdata = {
-- .base_width = 800,
-- .base_height = 480,
-- };
--
-- ret = platform_driver_register(&at91sam9x5_video_driver);
-- if (ret) {
-- pr_err("failed to register driver (%d)", ret);
-- goto err_driver_register;
-- }
--
-- at91sam9x5_video_device = platform_device_register_resndata(NULL,
-- DRIVER_NAME, -1,
-- res, ARRAY_SIZE(res), &pdata, sizeof(pdata));
-- if (IS_ERR(at91sam9x5_video_device)) {
-- ret = PTR_ERR(at91sam9x5_video_device);
-- pr_err("failed to register device (%d)", ret);
-- platform_driver_unregister(&at91sam9x5_video_driver);
-- }
--
-- err_driver_register:
-- return ret;
-+ return platform_driver_probe(&at91sam9x5_video_driver,
-+ &at91sam9x5_video_probe);
- }
- module_init(at91sam9x5_video_init);
-
- static void __exit at91sam9x5_video_exit(void)
- {
-- platform_device_unregister(at91sam9x5_video_device);
- platform_driver_unregister(&at91sam9x5_video_driver);
- }
- module_exit(at91sam9x5_video_exit);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 0b97e71038029ad93c9acb1ee992de536c236226 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 18 Jun 2012 14:14:57 +0200
-Subject: ARM: at91/video: Atmel HLCD is only selected by newer products
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/Kconfig | 4 ++--
- drivers/video/Kconfig | 5 ++++-
- 2 files changed, 6 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
-index c8050b1..79d08ed 100644
---- a/arch/arm/mach-at91/Kconfig
-+++ b/arch/arm/mach-at91/Kconfig
-@@ -86,7 +86,7 @@ config SOC_AT91SAM9X5
- bool "AT91SAM9x5 family"
- select SOC_AT91SAM9
- select HAVE_AT91_DBGU0
-- select HAVE_FB_ATMEL
-+ select HAVE_FB_ATMEL_HLCD
- select HAVE_NET_MACB
- help
- Select this if you are using one of Atmel's AT91SAM9x5 family SoC.
-@@ -99,7 +99,7 @@ config SOC_AT91SAM9N12
- bool "AT91SAM9N12 family"
- select SOC_AT91SAM9
- select HAVE_AT91_DBGU0
-- select HAVE_FB_ATMEL
-+ select HAVE_FB_ATMEL_HLCD
- help
- Select this if you are using Atmel's AT91SAM9N12 SoC.
-
-diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
-index ceccaa3..0928c36 100644
---- a/drivers/video/Kconfig
-+++ b/drivers/video/Kconfig
-@@ -8,6 +8,9 @@ menu "Graphics support"
- config HAVE_FB_ATMEL
- bool
-
-+config HAVE_FB_ATMEL_HLCD
-+ bool
-+
- config SH_MIPI_DSI
- tristate
- depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
-@@ -1030,7 +1033,7 @@ config FB_ATMEL_STN
-
- config FB_ATMEL_HLCD
- tristate "AT91 HLCD Controller support"
-- depends on FB && HAVE_FB_ATMEL
-+ depends on FB && HAVE_FB_ATMEL_HLCD
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2a9a4fc2e8860de7266d5b5c6624865b7647c17c Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Wed, 16 May 2012 15:25:58 +0200
-Subject: mmc: atmel-mci: the r/w proof capability lack was not well managed
-
-commit 7a90dcc2d7ceb64bb37044a8d2ee462b936ddf73 upstream.
-
-First mci IPs (mainly on rm9200 and 9261) don't have the r/w proof
-capability. The driver didn't work correctly without this capability
-in PDC mode because of the double buffer switch which is too slow
-even if we stop the transfer to perform this switch.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Signed-off-by: Chris Ball <cjb@laptop.org>
----
- drivers/mmc/host/atmel-mci.c | 92 ++++++++++++++++++++++++++++++++++++-------
- 1 file changed, 78 insertions(+), 14 deletions(-)
-
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -91,6 +91,11 @@ struct atmel_mci_dma {
- * @regs: Pointer to MMIO registers.
- * @sg: Scatterlist entry currently being processed by PIO or PDC code.
- * @pio_offset: Offset into the current scatterlist entry.
-+ * @buffer: Buffer used if we don't have the r/w proof capability. We
-+ * don't have the time to switch pdc buffers so we have to use only
-+ * one buffer for the full transaction.
-+ * @buf_size: size of the buffer.
-+ * @phys_buf_addr: buffer address needed for pdc.
- * @cur_slot: The slot which is currently using the controller.
- * @mrq: The request currently being processed on @cur_slot,
- * or NULL if the controller is idle.
-@@ -167,6 +172,9 @@ struct atmel_mci {
- struct scatterlist *sg;
- unsigned int sg_len;
- unsigned int pio_offset;
-+ unsigned int *buffer;
-+ unsigned int buf_size;
-+ dma_addr_t buf_phys_addr;
-
- struct atmel_mci_slot *cur_slot;
- struct mmc_request *mrq;
-@@ -481,6 +489,11 @@ err:
- dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n");
- }
-
-+static inline unsigned int atmci_get_version(struct atmel_mci *host)
-+{
-+ return atmci_readl(host, ATMCI_VERSION) & 0x00000fff;
-+}
-+
- static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host,
- unsigned int ns)
- {
-@@ -604,6 +617,7 @@ static void atmci_pdc_set_single_buf(str
- enum atmci_xfer_dir dir, enum atmci_pdc_buf buf_nb)
- {
- u32 pointer_reg, counter_reg;
-+ unsigned int buf_size;
-
- if (dir == XFER_RECEIVE) {
- pointer_reg = ATMEL_PDC_RPR;
-@@ -618,8 +632,15 @@ static void atmci_pdc_set_single_buf(str
- counter_reg += ATMEL_PDC_SCND_BUF_OFF;
- }
-
-- atmci_writel(host, pointer_reg, sg_dma_address(host->sg));
-- if (host->data_size <= sg_dma_len(host->sg)) {
-+ if (!host->caps.has_rwproof) {
-+ buf_size = host->buf_size;
-+ atmci_writel(host, pointer_reg, host->buf_phys_addr);
-+ } else {
-+ buf_size = sg_dma_len(host->sg);
-+ atmci_writel(host, pointer_reg, sg_dma_address(host->sg));
-+ }
-+
-+ if (host->data_size <= buf_size) {
- if (host->data_size & 0x3) {
- /* If size is different from modulo 4, transfer bytes */
- atmci_writel(host, counter_reg, host->data_size);
-@@ -671,7 +692,15 @@ static void atmci_pdc_cleanup(struct atm
- */
- static void atmci_pdc_complete(struct atmel_mci *host)
- {
-+ int transfer_size = host->data->blocks * host->data->blksz;
-+
- atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
-+
-+ if ((!host->caps.has_rwproof)
-+ && (host->data->flags & MMC_DATA_READ))
-+ sg_copy_from_buffer(host->data->sg, host->data->sg_len,
-+ host->buffer, transfer_size);
-+
- atmci_pdc_cleanup(host);
-
- /*
-@@ -820,6 +849,12 @@ atmci_prepare_data_pdc(struct atmel_mci
- /* Configure PDC */
- host->data_size = data->blocks * data->blksz;
- sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, dir);
-+
-+ if ((!host->caps.has_rwproof)
-+ && (host->data->flags & MMC_DATA_WRITE))
-+ sg_copy_to_buffer(host->data->sg, host->data->sg_len,
-+ host->buffer, host->data_size);
-+
- if (host->data_size)
- atmci_pdc_set_both_buf(host,
- ((dir == DMA_FROM_DEVICE) ? XFER_RECEIVE : XFER_TRANSMIT));
-@@ -1883,13 +1918,26 @@ static int __init atmci_init_slot(struct
- mmc->caps |= MMC_CAP_SDIO_IRQ;
- if (host->caps.has_highspeed)
- mmc->caps |= MMC_CAP_SD_HIGHSPEED;
-- if (slot_data->bus_width >= 4)
-+ /*
-+ * Without the read/write proof capability, it is strongly suggested to
-+ * use only one bit for data to prevent fifo underruns and overruns
-+ * which will corrupt data.
-+ */
-+ if ((slot_data->bus_width >= 4) && host->caps.has_rwproof)
- mmc->caps |= MMC_CAP_4_BIT_DATA;
-
-- mmc->max_segs = 64;
-- mmc->max_req_size = 32768 * 512;
-- mmc->max_blk_size = 32768;
-- mmc->max_blk_count = 512;
-+ if (atmci_get_version(host) < 0x200) {
-+ mmc->max_segs = 256;
-+ mmc->max_blk_size = 4095;
-+ mmc->max_blk_count = 256;
-+ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
-+ mmc->max_seg_size = mmc->max_blk_size * mmc->max_segs;
-+ } else {
-+ mmc->max_segs = 64;
-+ mmc->max_req_size = 32768 * 512;
-+ mmc->max_blk_size = 32768;
-+ mmc->max_blk_count = 512;
-+ }
-
- /* Assume card is present initially */
- set_bit(ATMCI_CARD_PRESENT, &slot->flags);
-@@ -2013,11 +2061,6 @@ static bool atmci_configure_dma(struct a
- }
- }
-
--static inline unsigned int atmci_get_version(struct atmel_mci *host)
--{
-- return atmci_readl(host, ATMCI_VERSION) & 0x00000fff;
--}
--
- /*
- * HSMCI (High Speed MCI) module is not fully compatible with MCI module.
- * HSMCI provides DMA support and a new config register but no more supports
-@@ -2144,14 +2187,20 @@ static int __init atmci_probe(struct pla
- if (pdata->slot[0].bus_width) {
- ret = atmci_init_slot(host, &pdata->slot[0],
- 0, ATMCI_SDCSEL_SLOT_A, ATMCI_SDIOIRQA);
-- if (!ret)
-+ if (!ret) {
- nr_slots++;
-+ host->buf_size = host->slot[0]->mmc->max_req_size;
-+ }
- }
- if (pdata->slot[1].bus_width) {
- ret = atmci_init_slot(host, &pdata->slot[1],
- 1, ATMCI_SDCSEL_SLOT_B, ATMCI_SDIOIRQB);
-- if (!ret)
-+ if (!ret) {
- nr_slots++;
-+ if (host->slot[1]->mmc->max_req_size > host->buf_size)
-+ host->buf_size =
-+ host->slot[1]->mmc->max_req_size;
-+ }
- }
-
- if (!nr_slots) {
-@@ -2159,6 +2208,17 @@ static int __init atmci_probe(struct pla
- goto err_init_slot;
- }
-
-+ if (!host->caps.has_rwproof) {
-+ host->buffer = dma_alloc_coherent(&pdev->dev, host->buf_size,
-+ &host->buf_phys_addr,
-+ GFP_KERNEL);
-+ if (!host->buffer) {
-+ ret = -ENOMEM;
-+ dev_err(&pdev->dev, "buffer allocation failed\n");
-+ goto err_init_slot;
-+ }
-+ }
-+
- dev_info(&pdev->dev,
- "Atmel MCI controller at 0x%08lx irq %d, %u slots\n",
- host->mapbase, irq, nr_slots);
-@@ -2185,6 +2245,10 @@ static int __exit atmci_remove(struct pl
-
- platform_set_drvdata(pdev, NULL);
-
-+ if (host->buffer)
-+ dma_free_coherent(&pdev->dev, host->buf_size,
-+ host->buffer, host->buf_phys_addr);
-+
- for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
- if (host->slot[i])
- atmci_cleanup_slot(host->slot[i], i);
+++ /dev/null
-From 6ab65f30491092a6dc2fadf895ff4b1dbe95566b Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Wed, 16 May 2012 15:25:59 +0200
-Subject: mmc: atmel-mci: change the state machine for compatibility with old
- IP
-
-commit f51775471ac6155d3bb8494dcb5c0a13a84f611e upstream.
-
-The state machine use in atmel-mci can't work with old IP versions
-(< 0x200). This patch allows to have a common state machine for all
-versions in order to remove at91-mci driver only used for old versions.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Signed-off-by: Chris Ball <cjb@laptop.org>
----
- drivers/mmc/host/atmel-mci.c | 278 +++++++++++++++++++++++++------------------
- 1 file changed, 162 insertions(+), 116 deletions(-)
-
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -45,19 +45,19 @@
- #define ATMCI_DMA_THRESHOLD 16
-
- enum {
-- EVENT_CMD_COMPLETE = 0,
-+ EVENT_CMD_RDY = 0,
- EVENT_XFER_COMPLETE,
-- EVENT_DATA_COMPLETE,
-+ EVENT_NOTBUSY,
- EVENT_DATA_ERROR,
- };
-
- enum atmel_mci_state {
- STATE_IDLE = 0,
- STATE_SENDING_CMD,
-- STATE_SENDING_DATA,
-- STATE_DATA_BUSY,
-+ STATE_DATA_XFER,
-+ STATE_WAITING_NOTBUSY,
- STATE_SENDING_STOP,
-- STATE_DATA_ERROR,
-+ STATE_END_REQUEST,
- };
-
- enum atmci_xfer_dir {
-@@ -710,7 +710,6 @@ static void atmci_pdc_complete(struct at
- if (host->data) {
- atmci_set_pending(host, EVENT_XFER_COMPLETE);
- tasklet_schedule(&host->tasklet);
-- atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
- }
- }
-
-@@ -837,7 +836,7 @@ atmci_prepare_data_pdc(struct atmel_mci
- iflags |= ATMCI_ENDRX | ATMCI_RXBUFF;
- } else {
- dir = DMA_TO_DEVICE;
-- iflags |= ATMCI_ENDTX | ATMCI_TXBUFE;
-+ iflags |= ATMCI_ENDTX | ATMCI_TXBUFE | ATMCI_BLKE;
- }
-
- /* Set BLKLEN */
-@@ -977,8 +976,7 @@ static void atmci_stop_transfer(struct a
- */
- static void atmci_stop_transfer_pdc(struct atmel_mci *host)
- {
-- atmci_set_pending(host, EVENT_XFER_COMPLETE);
-- atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
-+ atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
- }
-
- static void atmci_stop_transfer_dma(struct atmel_mci *host)
-@@ -1014,6 +1012,7 @@ static void atmci_start_request(struct a
-
- host->pending_events = 0;
- host->completed_events = 0;
-+ host->cmd_status = 0;
- host->data_status = 0;
-
- if (host->need_reset) {
-@@ -1031,7 +1030,7 @@ static void atmci_start_request(struct a
-
- iflags = atmci_readl(host, ATMCI_IMR);
- if (iflags & ~(ATMCI_SDIOIRQA | ATMCI_SDIOIRQB))
-- dev_warn(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n",
-+ dev_dbg(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n",
- iflags);
-
- if (unlikely(test_and_clear_bit(ATMCI_CARD_NEED_INIT, &slot->flags))) {
-@@ -1369,19 +1368,6 @@ static void atmci_command_complete(struc
- cmd->error = -EIO;
- else
- cmd->error = 0;
--
-- if (cmd->error) {
-- dev_dbg(&host->pdev->dev,
-- "command error: status=0x%08x\n", status);
--
-- if (cmd->data) {
-- host->stop_transfer(host);
-- host->data = NULL;
-- atmci_writel(host, ATMCI_IDR, ATMCI_NOTBUSY
-- | ATMCI_TXRDY | ATMCI_RXRDY
-- | ATMCI_DATA_ERROR_FLAGS);
-- }
-- }
- }
-
- static void atmci_detect_change(unsigned long data)
-@@ -1444,23 +1430,21 @@ static void atmci_detect_change(unsigned
- break;
- case STATE_SENDING_CMD:
- mrq->cmd->error = -ENOMEDIUM;
-- if (!mrq->data)
-- break;
-- /* fall through */
-- case STATE_SENDING_DATA:
-+ if (mrq->data)
-+ host->stop_transfer(host);
-+ break;
-+ case STATE_DATA_XFER:
- mrq->data->error = -ENOMEDIUM;
- host->stop_transfer(host);
- break;
-- case STATE_DATA_BUSY:
-- case STATE_DATA_ERROR:
-- if (mrq->data->error == -EINPROGRESS)
-- mrq->data->error = -ENOMEDIUM;
-- if (!mrq->stop)
-- break;
-- /* fall through */
-+ case STATE_WAITING_NOTBUSY:
-+ mrq->data->error = -ENOMEDIUM;
-+ break;
- case STATE_SENDING_STOP:
- mrq->stop->error = -ENOMEDIUM;
- break;
-+ case STATE_END_REQUEST:
-+ break;
- }
-
- atmci_request_end(host, mrq);
-@@ -1488,7 +1472,6 @@ static void atmci_tasklet_func(unsigned
- struct atmel_mci *host = (struct atmel_mci *)priv;
- struct mmc_request *mrq = host->mrq;
- struct mmc_data *data = host->data;
-- struct mmc_command *cmd = host->cmd;
- enum atmel_mci_state state = host->state;
- enum atmel_mci_state prev_state;
- u32 status;
-@@ -1510,101 +1493,164 @@ static void atmci_tasklet_func(unsigned
- break;
-
- case STATE_SENDING_CMD:
-+ /*
-+ * Command has been sent, we are waiting for command
-+ * ready. Then we have three next states possible:
-+ * END_REQUEST by default, WAITING_NOTBUSY if it's a
-+ * command needing it or DATA_XFER if there is data.
-+ */
- if (!atmci_test_and_clear_pending(host,
-- EVENT_CMD_COMPLETE))
-+ EVENT_CMD_RDY))
- break;
-
- host->cmd = NULL;
-- atmci_set_completed(host, EVENT_CMD_COMPLETE);
-+ atmci_set_completed(host, EVENT_CMD_RDY);
- atmci_command_complete(host, mrq->cmd);
-- if (!mrq->data || cmd->error) {
-- atmci_request_end(host, host->mrq);
-- goto unlock;
-- }
-+ if (mrq->data) {
-+ /*
-+ * If there is a command error don't start
-+ * data transfer.
-+ */
-+ if (mrq->cmd->error) {
-+ host->stop_transfer(host);
-+ host->data = NULL;
-+ atmci_writel(host, ATMCI_IDR,
-+ ATMCI_TXRDY | ATMCI_RXRDY
-+ | ATMCI_DATA_ERROR_FLAGS);
-+ state = STATE_END_REQUEST;
-+ } else
-+ state = STATE_DATA_XFER;
-+ } else if ((!mrq->data) && (mrq->cmd->flags & MMC_RSP_BUSY)) {
-+ atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
-+ state = STATE_WAITING_NOTBUSY;
-+ } else
-+ state = STATE_END_REQUEST;
-
-- prev_state = state = STATE_SENDING_DATA;
-- /* fall through */
-+ break;
-
-- case STATE_SENDING_DATA:
-+ case STATE_DATA_XFER:
- if (atmci_test_and_clear_pending(host,
- EVENT_DATA_ERROR)) {
-- host->stop_transfer(host);
-- if (data->stop)
-- atmci_send_stop_cmd(host, data);
-- state = STATE_DATA_ERROR;
-+ atmci_set_completed(host, EVENT_DATA_ERROR);
-+ state = STATE_END_REQUEST;
- break;
- }
-
-+ /*
-+ * A data transfer is in progress. The event expected
-+ * to move to the next state depends of data transfer
-+ * type (PDC or DMA). Once transfer done we can move
-+ * to the next step which is WAITING_NOTBUSY in write
-+ * case and directly SENDING_STOP in read case.
-+ */
- if (!atmci_test_and_clear_pending(host,
- EVENT_XFER_COMPLETE))
- break;
-
- atmci_set_completed(host, EVENT_XFER_COMPLETE);
-- prev_state = state = STATE_DATA_BUSY;
-- /* fall through */
-
-- case STATE_DATA_BUSY:
-- if (!atmci_test_and_clear_pending(host,
-- EVENT_DATA_COMPLETE))
-- break;
--
-- host->data = NULL;
-- atmci_set_completed(host, EVENT_DATA_COMPLETE);
-- status = host->data_status;
-- if (unlikely(status & ATMCI_DATA_ERROR_FLAGS)) {
-- if (status & ATMCI_DTOE) {
-- dev_dbg(&host->pdev->dev,
-- "data timeout error\n");
-- data->error = -ETIMEDOUT;
-- } else if (status & ATMCI_DCRCE) {
-- dev_dbg(&host->pdev->dev,
-- "data CRC error\n");
-- data->error = -EILSEQ;
-- } else {
-- dev_dbg(&host->pdev->dev,
-- "data FIFO error (status=%08x)\n",
-- status);
-- data->error = -EIO;
-- }
-+ if (host->data->flags & MMC_DATA_WRITE) {
-+ atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
-+ state = STATE_WAITING_NOTBUSY;
-+ } else if (host->mrq->stop) {
-+ atmci_writel(host, ATMCI_IER, ATMCI_CMDRDY);
-+ atmci_send_stop_cmd(host, data);
-+ state = STATE_SENDING_STOP;
- } else {
-+ host->data = NULL;
- data->bytes_xfered = data->blocks * data->blksz;
- data->error = 0;
-- atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS);
-+ state = STATE_END_REQUEST;
- }
-+ break;
-
-- if (!data->stop) {
-- atmci_request_end(host, host->mrq);
-- goto unlock;
-- }
-+ case STATE_WAITING_NOTBUSY:
-+ /*
-+ * We can be in the state for two reasons: a command
-+ * requiring waiting not busy signal (stop command
-+ * included) or a write operation. In the latest case,
-+ * we need to send a stop command.
-+ */
-+ if (!atmci_test_and_clear_pending(host,
-+ EVENT_NOTBUSY))
-+ break;
-
-- prev_state = state = STATE_SENDING_STOP;
-- if (!data->error)
-- atmci_send_stop_cmd(host, data);
-- /* fall through */
-+ atmci_set_completed(host, EVENT_NOTBUSY);
-+
-+ if (host->data) {
-+ /*
-+ * For some commands such as CMD53, even if
-+ * there is data transfer, there is no stop
-+ * command to send.
-+ */
-+ if (host->mrq->stop) {
-+ atmci_writel(host, ATMCI_IER,
-+ ATMCI_CMDRDY);
-+ atmci_send_stop_cmd(host, data);
-+ state = STATE_SENDING_STOP;
-+ } else {
-+ host->data = NULL;
-+ data->bytes_xfered = data->blocks
-+ * data->blksz;
-+ data->error = 0;
-+ state = STATE_END_REQUEST;
-+ }
-+ } else
-+ state = STATE_END_REQUEST;
-+ break;
-
- case STATE_SENDING_STOP:
-+ /*
-+ * In this state, it is important to set host->data to
-+ * NULL (which is tested in the waiting notbusy state)
-+ * in order to go to the end request state instead of
-+ * sending stop again.
-+ */
- if (!atmci_test_and_clear_pending(host,
-- EVENT_CMD_COMPLETE))
-+ EVENT_CMD_RDY))
- break;
-
- host->cmd = NULL;
-+ host->data = NULL;
-+ data->bytes_xfered = data->blocks * data->blksz;
-+ data->error = 0;
- atmci_command_complete(host, mrq->stop);
-- atmci_request_end(host, host->mrq);
-- goto unlock;
-+ if (mrq->stop->error) {
-+ host->stop_transfer(host);
-+ atmci_writel(host, ATMCI_IDR,
-+ ATMCI_TXRDY | ATMCI_RXRDY
-+ | ATMCI_DATA_ERROR_FLAGS);
-+ state = STATE_END_REQUEST;
-+ } else {
-+ atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
-+ state = STATE_WAITING_NOTBUSY;
-+ }
-+ break;
-
-- case STATE_DATA_ERROR:
-- if (!atmci_test_and_clear_pending(host,
-- EVENT_XFER_COMPLETE))
-- break;
-+ case STATE_END_REQUEST:
-+ atmci_writel(host, ATMCI_IDR, ATMCI_TXRDY | ATMCI_RXRDY
-+ | ATMCI_DATA_ERROR_FLAGS);
-+ status = host->data_status;
-+ if (unlikely(status)) {
-+ host->stop_transfer(host);
-+ host->data = NULL;
-+ if (status & ATMCI_DTOE) {
-+ data->error = -ETIMEDOUT;
-+ } else if (status & ATMCI_DCRCE) {
-+ data->error = -EILSEQ;
-+ } else {
-+ data->error = -EIO;
-+ }
-+ }
-
-- state = STATE_DATA_BUSY;
-+ atmci_request_end(host, host->mrq);
-+ state = STATE_IDLE;
- break;
- }
- } while (state != prev_state);
-
- host->state = state;
-
--unlock:
- spin_unlock(&host->lock);
- }
-
-@@ -1659,9 +1705,6 @@ static void atmci_read_data_pio(struct a
- | ATMCI_DATA_ERROR_FLAGS));
- host->data_status = status;
- data->bytes_xfered += nbytes;
-- smp_wmb();
-- atmci_set_pending(host, EVENT_DATA_ERROR);
-- tasklet_schedule(&host->tasklet);
- return;
- }
- } while (status & ATMCI_RXRDY);
-@@ -1732,9 +1775,6 @@ static void atmci_write_data_pio(struct
- | ATMCI_DATA_ERROR_FLAGS));
- host->data_status = status;
- data->bytes_xfered += nbytes;
-- smp_wmb();
-- atmci_set_pending(host, EVENT_DATA_ERROR);
-- tasklet_schedule(&host->tasklet);
- return;
- }
- } while (status & ATMCI_TXRDY);
-@@ -1752,16 +1792,6 @@ done:
- atmci_set_pending(host, EVENT_XFER_COMPLETE);
- }
-
--static void atmci_cmd_interrupt(struct atmel_mci *host, u32 status)
--{
-- atmci_writel(host, ATMCI_IDR, ATMCI_CMDRDY);
--
-- host->cmd_status = status;
-- smp_wmb();
-- atmci_set_pending(host, EVENT_CMD_COMPLETE);
-- tasklet_schedule(&host->tasklet);
--}
--
- static void atmci_sdio_interrupt(struct atmel_mci *host, u32 status)
- {
- int i;
-@@ -1790,8 +1820,9 @@ static irqreturn_t atmci_interrupt(int i
-
- if (pending & ATMCI_DATA_ERROR_FLAGS) {
- atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS
-- | ATMCI_RXRDY | ATMCI_TXRDY);
-- pending &= atmci_readl(host, ATMCI_IMR);
-+ | ATMCI_RXRDY | ATMCI_TXRDY
-+ | ATMCI_ENDRX | ATMCI_ENDTX
-+ | ATMCI_RXBUFF | ATMCI_TXBUFE);
-
- host->data_status = status;
- smp_wmb();
-@@ -1849,23 +1880,38 @@ static irqreturn_t atmci_interrupt(int i
- }
- }
-
-+ /*
-+ * First mci IPs, so mainly the ones having pdc, have some
-+ * issues with the notbusy signal. You can't get it after
-+ * data transmission if you have not sent a stop command.
-+ * The appropriate workaround is to use the BLKE signal.
-+ */
-+ if (pending & ATMCI_BLKE) {
-+ atmci_writel(host, ATMCI_IDR, ATMCI_BLKE);
-+ smp_wmb();
-+ atmci_set_pending(host, EVENT_NOTBUSY);
-+ tasklet_schedule(&host->tasklet);
-+ }
-
- if (pending & ATMCI_NOTBUSY) {
-- atmci_writel(host, ATMCI_IDR,
-- ATMCI_DATA_ERROR_FLAGS | ATMCI_NOTBUSY);
-- if (!host->data_status)
-- host->data_status = status;
-+ atmci_writel(host, ATMCI_IDR, ATMCI_NOTBUSY);
- smp_wmb();
-- atmci_set_pending(host, EVENT_DATA_COMPLETE);
-+ atmci_set_pending(host, EVENT_NOTBUSY);
- tasklet_schedule(&host->tasklet);
- }
-+
- if (pending & ATMCI_RXRDY)
- atmci_read_data_pio(host);
- if (pending & ATMCI_TXRDY)
- atmci_write_data_pio(host);
-
-- if (pending & ATMCI_CMDRDY)
-- atmci_cmd_interrupt(host, status);
-+ if (pending & ATMCI_CMDRDY) {
-+ atmci_writel(host, ATMCI_IDR, ATMCI_CMDRDY);
-+ host->cmd_status = status;
-+ smp_wmb();
-+ atmci_set_pending(host, EVENT_CMD_RDY);
-+ tasklet_schedule(&host->tasklet);
-+ }
-
- if (pending & (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB))
- atmci_sdio_interrupt(host, status);
+++ /dev/null
-From 410edf632453503d8d888a2932679ced461e16b6 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Wed, 16 May 2012 15:26:00 +0200
-Subject: mmc: atmel-mci: add support for version lower than v2xx
-
-commit 24011f346471f7636f0ba6ffe2064fdd1a091daa upstream.
-
-Fix mci IP bugs and endianness issue.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Signed-off-by: Chris Ball <cjb@laptop.org>
----
- drivers/mmc/host/atmel-mci.c | 62 ++++++++++++++++++++++++++++++++++++++++---
- 1 file changed, 58 insertions(+), 4 deletions(-)
-
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -78,6 +78,9 @@ struct atmel_mci_caps {
- bool has_highspeed;
- bool has_rwproof;
- bool has_odd_clk_div;
-+ bool has_bad_data_ordering;
-+ bool need_reset_after_xfer;
-+ bool need_blksz_mul_4;
- };
-
- struct atmel_mci_dma {
-@@ -121,6 +124,7 @@ struct atmel_mci_dma {
- * @queue: List of slots waiting for access to the controller.
- * @need_clock_update: Update the clock rate before the next request.
- * @need_reset: Reset controller before next request.
-+ * @timer: Timer to balance the data timeout error flag which cannot rise.
- * @mode_reg: Value of the MR register.
- * @cfg_reg: Value of the CFG register.
- * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus
-@@ -198,6 +202,7 @@ struct atmel_mci {
-
- bool need_clock_update;
- bool need_reset;
-+ struct timer_list timer;
- u32 mode_reg;
- u32 cfg_reg;
- unsigned long bus_hz;
-@@ -494,6 +499,27 @@ static inline unsigned int atmci_get_ver
- return atmci_readl(host, ATMCI_VERSION) & 0x00000fff;
- }
-
-+static void atmci_timeout_timer(unsigned long data)
-+{
-+ struct atmel_mci *host;
-+
-+ host = (struct atmel_mci *)data;
-+
-+ dev_dbg(&host->pdev->dev, "software timeout\n");
-+
-+ if (host->mrq->cmd->data) {
-+ host->mrq->cmd->data->error = -ETIMEDOUT;
-+ host->data = NULL;
-+ } else {
-+ host->mrq->cmd->error = -ETIMEDOUT;
-+ host->cmd = NULL;
-+ }
-+ host->need_reset = 1;
-+ host->state = STATE_END_REQUEST;
-+ smp_wmb();
-+ tasklet_schedule(&host->tasklet);
-+}
-+
- static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host,
- unsigned int ns)
- {
-@@ -693,13 +719,18 @@ static void atmci_pdc_cleanup(struct atm
- static void atmci_pdc_complete(struct atmel_mci *host)
- {
- int transfer_size = host->data->blocks * host->data->blksz;
-+ int i;
-
- atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
-
- if ((!host->caps.has_rwproof)
-- && (host->data->flags & MMC_DATA_READ))
-+ && (host->data->flags & MMC_DATA_READ)) {
-+ if (host->caps.has_bad_data_ordering)
-+ for (i = 0; i < transfer_size; i++)
-+ host->buffer[i] = swab32(host->buffer[i]);
- sg_copy_from_buffer(host->data->sg, host->data->sg_len,
- host->buffer, transfer_size);
-+ }
-
- atmci_pdc_cleanup(host);
-
-@@ -821,6 +852,7 @@ atmci_prepare_data_pdc(struct atmel_mci
- u32 iflags, tmp;
- unsigned int sg_len;
- enum dma_data_direction dir;
-+ int i;
-
- data->error = -EINPROGRESS;
-
-@@ -850,9 +882,13 @@ atmci_prepare_data_pdc(struct atmel_mci
- sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, dir);
-
- if ((!host->caps.has_rwproof)
-- && (host->data->flags & MMC_DATA_WRITE))
-+ && (host->data->flags & MMC_DATA_WRITE)) {
- sg_copy_to_buffer(host->data->sg, host->data->sg_len,
- host->buffer, host->data_size);
-+ if (host->caps.has_bad_data_ordering)
-+ for (i = 0; i < host->data_size; i++)
-+ host->buffer[i] = swab32(host->buffer[i]);
-+ }
-
- if (host->data_size)
- atmci_pdc_set_both_buf(host,
-@@ -1015,7 +1051,7 @@ static void atmci_start_request(struct a
- host->cmd_status = 0;
- host->data_status = 0;
-
-- if (host->need_reset) {
-+ if (host->need_reset || host->caps.need_reset_after_xfer) {
- iflags = atmci_readl(host, ATMCI_IMR);
- iflags &= (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB);
- atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
-@@ -1079,6 +1115,8 @@ static void atmci_start_request(struct a
- * prepared yet.)
- */
- atmci_writel(host, ATMCI_IER, iflags);
-+
-+ mod_timer(&host->timer, jiffies + msecs_to_jiffies(2000));
- }
-
- static void atmci_queue_request(struct atmel_mci *host,
-@@ -1344,6 +1382,8 @@ static void atmci_request_end(struct atm
- host->state = STATE_IDLE;
- }
-
-+ del_timer(&host->timer);
-+
- spin_unlock(&host->lock);
- mmc_request_done(prev_mmc, mrq);
- spin_lock(&host->lock);
-@@ -1366,7 +1406,12 @@ static void atmci_command_complete(struc
- cmd->error = -EILSEQ;
- else if (status & (ATMCI_RINDE | ATMCI_RDIRE | ATMCI_RENDE))
- cmd->error = -EIO;
-- else
-+ else if (host->mrq->data && (host->mrq->data->blksz & 3)) {
-+ if (host->caps.need_blksz_mul_4) {
-+ cmd->error = -EINVAL;
-+ host->need_reset = 1;
-+ }
-+ } else
- cmd->error = 0;
- }
-
-@@ -2127,6 +2172,9 @@ static void __init atmci_get_cap(struct
- host->caps.has_highspeed = 0;
- host->caps.has_rwproof = 0;
- host->caps.has_odd_clk_div = 0;
-+ host->caps.has_bad_data_ordering = 1;
-+ host->caps.need_reset_after_xfer = 1;
-+ host->caps.need_blksz_mul_4 = 1;
-
- /* keep only major version number */
- switch (version & 0xf00) {
-@@ -2146,7 +2194,11 @@ static void __init atmci_get_cap(struct
- host->caps.has_highspeed = 1;
- case 0x200:
- host->caps.has_rwproof = 1;
-+ host->caps.need_blksz_mul_4 = 0;
- case 0x100:
-+ host->caps.has_bad_data_ordering = 0;
-+ host->caps.need_reset_after_xfer = 0;
-+ case 0x0:
- break;
- default:
- host->caps.has_pdc = 0;
-@@ -2265,6 +2317,8 @@ static int __init atmci_probe(struct pla
- }
- }
-
-+ setup_timer(&host->timer, atmci_timeout_timer, (unsigned long)host);
-+
- dev_info(&pdev->dev,
- "Atmel MCI controller at 0x%08lx irq %d, %u slots\n",
- host->mapbase, irq, nr_slots);
+++ /dev/null
-From f83911708a2a24e8d44657d737f6aac9e840d2d2 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Wed, 16 May 2012 15:26:01 +0200
-Subject: mmc: atmel-mci: add debug logs
-
-commit 6801c41a77123712accfde898820972a1f6fc117 upstream.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Signed-off-by: Chris Ball <cjb@laptop.org>
----
- drivers/mmc/host/atmel-mci.c | 41 +++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 41 insertions(+)
-
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -631,6 +631,7 @@ static void atmci_send_command(struct at
-
- static void atmci_send_stop_cmd(struct atmel_mci *host, struct mmc_data *data)
- {
-+ dev_dbg(&host->pdev->dev, "send stop command\n");
- atmci_send_command(host, data->stop, host->stop_cmdr);
- atmci_writel(host, ATMCI_IER, ATMCI_CMDRDY);
- }
-@@ -739,6 +740,8 @@ static void atmci_pdc_complete(struct at
- * to send the stop command or waiting for NBUSY in this case.
- */
- if (host->data) {
-+ dev_dbg(&host->pdev->dev,
-+ "(%s) set pending xfer complete\n", __func__);
- atmci_set_pending(host, EVENT_XFER_COMPLETE);
- tasklet_schedule(&host->tasklet);
- }
-@@ -776,6 +779,8 @@ static void atmci_dma_complete(void *arg
- * to send the stop command or waiting for NBUSY in this case.
- */
- if (data) {
-+ dev_dbg(&host->pdev->dev,
-+ "(%s) set pending xfer complete\n", __func__);
- atmci_set_pending(host, EVENT_XFER_COMPLETE);
- tasklet_schedule(&host->tasklet);
-
-@@ -1003,6 +1008,8 @@ atmci_submit_data_dma(struct atmel_mci *
-
- static void atmci_stop_transfer(struct atmel_mci *host)
- {
-+ dev_dbg(&host->pdev->dev,
-+ "(%s) set pending xfer complete\n", __func__);
- atmci_set_pending(host, EVENT_XFER_COMPLETE);
- atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
- }
-@@ -1024,6 +1031,8 @@ static void atmci_stop_transfer_dma(stru
- atmci_dma_cleanup(host);
- } else {
- /* Data transfer was stopped by the interrupt handler */
-+ dev_dbg(&host->pdev->dev,
-+ "(%s) set pending xfer complete\n", __func__);
- atmci_set_pending(host, EVENT_XFER_COMPLETE);
- atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
- }
-@@ -1051,6 +1060,8 @@ static void atmci_start_request(struct a
- host->cmd_status = 0;
- host->data_status = 0;
-
-+ dev_dbg(&host->pdev->dev, "start request: cmd %u\n", mrq->cmd->opcode);
-+
- if (host->need_reset || host->caps.need_reset_after_xfer) {
- iflags = atmci_readl(host, ATMCI_IMR);
- iflags &= (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB);
-@@ -1131,6 +1142,7 @@ static void atmci_queue_request(struct a
- host->state = STATE_SENDING_CMD;
- atmci_start_request(host, slot);
- } else {
-+ dev_dbg(&host->pdev->dev, "queue request\n");
- list_add_tail(&slot->queue_node, &host->queue);
- }
- spin_unlock_bh(&host->lock);
-@@ -1143,6 +1155,7 @@ static void atmci_request(struct mmc_hos
- struct mmc_data *data;
-
- WARN_ON(slot->mrq);
-+ dev_dbg(&host->pdev->dev, "MRQ: cmd %u\n", mrq->cmd->opcode);
-
- /*
- * We may "know" the card is gone even though there's still an
-@@ -1532,6 +1545,7 @@ static void atmci_tasklet_func(unsigned
-
- do {
- prev_state = state;
-+ dev_dbg(&host->pdev->dev, "FSM: state=%d\n", state);
-
- switch (state) {
- case STATE_IDLE:
-@@ -1544,14 +1558,18 @@ static void atmci_tasklet_func(unsigned
- * END_REQUEST by default, WAITING_NOTBUSY if it's a
- * command needing it or DATA_XFER if there is data.
- */
-+ dev_dbg(&host->pdev->dev, "FSM: cmd ready?\n");
- if (!atmci_test_and_clear_pending(host,
- EVENT_CMD_RDY))
- break;
-
-+ dev_dbg(&host->pdev->dev, "set completed cmd ready\n");
- host->cmd = NULL;
- atmci_set_completed(host, EVENT_CMD_RDY);
- atmci_command_complete(host, mrq->cmd);
- if (mrq->data) {
-+ dev_dbg(&host->pdev->dev,
-+ "command with data transfer");
- /*
- * If there is a command error don't start
- * data transfer.
-@@ -1566,6 +1584,8 @@ static void atmci_tasklet_func(unsigned
- } else
- state = STATE_DATA_XFER;
- } else if ((!mrq->data) && (mrq->cmd->flags & MMC_RSP_BUSY)) {
-+ dev_dbg(&host->pdev->dev,
-+ "command response need waiting notbusy");
- atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
- state = STATE_WAITING_NOTBUSY;
- } else
-@@ -1576,6 +1596,7 @@ static void atmci_tasklet_func(unsigned
- case STATE_DATA_XFER:
- if (atmci_test_and_clear_pending(host,
- EVENT_DATA_ERROR)) {
-+ dev_dbg(&host->pdev->dev, "set completed data error\n");
- atmci_set_completed(host, EVENT_DATA_ERROR);
- state = STATE_END_REQUEST;
- break;
-@@ -1588,10 +1609,14 @@ static void atmci_tasklet_func(unsigned
- * to the next step which is WAITING_NOTBUSY in write
- * case and directly SENDING_STOP in read case.
- */
-+ dev_dbg(&host->pdev->dev, "FSM: xfer complete?\n");
- if (!atmci_test_and_clear_pending(host,
- EVENT_XFER_COMPLETE))
- break;
-
-+ dev_dbg(&host->pdev->dev,
-+ "(%s) set completed xfer complete\n",
-+ __func__);
- atmci_set_completed(host, EVENT_XFER_COMPLETE);
-
- if (host->data->flags & MMC_DATA_WRITE) {
-@@ -1616,10 +1641,12 @@ static void atmci_tasklet_func(unsigned
- * included) or a write operation. In the latest case,
- * we need to send a stop command.
- */
-+ dev_dbg(&host->pdev->dev, "FSM: not busy?\n");
- if (!atmci_test_and_clear_pending(host,
- EVENT_NOTBUSY))
- break;
-
-+ dev_dbg(&host->pdev->dev, "set completed not busy\n");
- atmci_set_completed(host, EVENT_NOTBUSY);
-
- if (host->data) {
-@@ -1651,10 +1678,12 @@ static void atmci_tasklet_func(unsigned
- * in order to go to the end request state instead of
- * sending stop again.
- */
-+ dev_dbg(&host->pdev->dev, "FSM: cmd ready?\n");
- if (!atmci_test_and_clear_pending(host,
- EVENT_CMD_RDY))
- break;
-
-+ dev_dbg(&host->pdev->dev, "FSM: cmd ready\n");
- host->cmd = NULL;
- host->data = NULL;
- data->bytes_xfered = data->blocks * data->blksz;
-@@ -1864,18 +1893,21 @@ static irqreturn_t atmci_interrupt(int i
- break;
-
- if (pending & ATMCI_DATA_ERROR_FLAGS) {
-+ dev_dbg(&host->pdev->dev, "IRQ: data error\n");
- atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS
- | ATMCI_RXRDY | ATMCI_TXRDY
- | ATMCI_ENDRX | ATMCI_ENDTX
- | ATMCI_RXBUFF | ATMCI_TXBUFE);
-
- host->data_status = status;
-+ dev_dbg(&host->pdev->dev, "set pending data error\n");
- smp_wmb();
- atmci_set_pending(host, EVENT_DATA_ERROR);
- tasklet_schedule(&host->tasklet);
- }
-
- if (pending & ATMCI_TXBUFE) {
-+ dev_dbg(&host->pdev->dev, "IRQ: tx buffer empty\n");
- atmci_writel(host, ATMCI_IDR, ATMCI_TXBUFE);
- atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX);
- /*
-@@ -1891,6 +1923,7 @@ static irqreturn_t atmci_interrupt(int i
- atmci_pdc_complete(host);
- }
- } else if (pending & ATMCI_ENDTX) {
-+ dev_dbg(&host->pdev->dev, "IRQ: end of tx buffer\n");
- atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX);
-
- if (host->data_size) {
-@@ -1901,6 +1934,7 @@ static irqreturn_t atmci_interrupt(int i
- }
-
- if (pending & ATMCI_RXBUFF) {
-+ dev_dbg(&host->pdev->dev, "IRQ: rx buffer full\n");
- atmci_writel(host, ATMCI_IDR, ATMCI_RXBUFF);
- atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX);
- /*
-@@ -1916,6 +1950,7 @@ static irqreturn_t atmci_interrupt(int i
- atmci_pdc_complete(host);
- }
- } else if (pending & ATMCI_ENDRX) {
-+ dev_dbg(&host->pdev->dev, "IRQ: end of rx buffer\n");
- atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX);
-
- if (host->data_size) {
-@@ -1932,15 +1967,19 @@ static irqreturn_t atmci_interrupt(int i
- * The appropriate workaround is to use the BLKE signal.
- */
- if (pending & ATMCI_BLKE) {
-+ dev_dbg(&host->pdev->dev, "IRQ: blke\n");
- atmci_writel(host, ATMCI_IDR, ATMCI_BLKE);
- smp_wmb();
-+ dev_dbg(&host->pdev->dev, "set pending notbusy\n");
- atmci_set_pending(host, EVENT_NOTBUSY);
- tasklet_schedule(&host->tasklet);
- }
-
- if (pending & ATMCI_NOTBUSY) {
-+ dev_dbg(&host->pdev->dev, "IRQ: not_busy\n");
- atmci_writel(host, ATMCI_IDR, ATMCI_NOTBUSY);
- smp_wmb();
-+ dev_dbg(&host->pdev->dev, "set pending notbusy\n");
- atmci_set_pending(host, EVENT_NOTBUSY);
- tasklet_schedule(&host->tasklet);
- }
-@@ -1951,9 +1990,11 @@ static irqreturn_t atmci_interrupt(int i
- atmci_write_data_pio(host);
-
- if (pending & ATMCI_CMDRDY) {
-+ dev_dbg(&host->pdev->dev, "IRQ: cmd ready\n");
- atmci_writel(host, ATMCI_IDR, ATMCI_CMDRDY);
- host->cmd_status = status;
- smp_wmb();
-+ dev_dbg(&host->pdev->dev, "set pending cmd rdy\n");
- atmci_set_pending(host, EVENT_CMD_RDY);
- tasklet_schedule(&host->tasklet);
- }
+++ /dev/null
-From df09e320ce8def6b95f5ae3fb7d3b547e0d275a8 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Wed, 23 May 2012 15:46:00 +0200
-Subject: mmc: atmel-mci: fix data timeout issue
-
-commit b87cc1b5d3a96ef9f1b3a4f8ce7aaff18e96c994 upstream.
-
-The data timeout timer was configured after mmc_add_host call. So, with bad
-timings, it was possible to have a mmc request causing mod_timer call on a
-non setup timer.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- drivers/mmc/host/atmel-mci.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -2320,6 +2320,8 @@ static int __init atmci_probe(struct pla
-
- platform_set_drvdata(pdev, host);
-
-+ setup_timer(&host->timer, atmci_timeout_timer, (unsigned long)host);
-+
- /* We need at least one slot to succeed */
- nr_slots = 0;
- ret = -ENODEV;
-@@ -2358,8 +2360,6 @@ static int __init atmci_probe(struct pla
- }
- }
-
-- setup_timer(&host->timer, atmci_timeout_timer, (unsigned long)host);
--
- dev_info(&pdev->dev,
- "Atmel MCI controller at 0x%08lx irq %d, %u slots\n",
- host->mapbase, irq, nr_slots);
+++ /dev/null
-From 975d22ac8acbc75c1f283bad017101d603a263f1 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Mon, 21 May 2012 12:23:27 +0200
-Subject: ARM: at91: add atmel-mci support for chips and boards which can use
- it
-
-commit 4cf3326ab5f34a333a46c59d0d3783db9cef13bf upstream.
-
-Since atmel-mci driver supports all atmel mci versions,
-use it instead of the deprecated at91_mci driver.
-Platform data and all related configuration are removed.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-[nicolas.ferre@atmel.com: remove at91_mci platform data]
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/at91rm9200_devices.c | 92 ++++++++++--------
- arch/arm/mach-at91/at91sam9260_devices.c | 84 +---------------
- arch/arm/mach-at91/at91sam9261_devices.c | 60 ++++++------
- arch/arm/mach-at91/at91sam9263.c | 4 +-
- arch/arm/mach-at91/at91sam9263_devices.c | 161 ++++++++++++++++++-------------
- arch/arm/mach-at91/at91sam9rl_devices.c | 60 ++++++------
- arch/arm/mach-at91/board-afeb-9260v1.c | 14 +--
- arch/arm/mach-at91/board-carmeva.c | 14 +--
- arch/arm/mach-at91/board-cpu9krea.c | 14 +--
- arch/arm/mach-at91/board-cpuat91.c | 13 +--
- arch/arm/mach-at91/board-csb337.c | 14 +--
- arch/arm/mach-at91/board-eb9200.c | 14 +--
- arch/arm/mach-at91/board-ecbat91.c | 14 +--
- arch/arm/mach-at91/board-eco920.c | 14 +--
- arch/arm/mach-at91/board-flexibity.c | 14 +--
- arch/arm/mach-at91/board-foxg20.c | 16 +--
- arch/arm/mach-at91/board-kb9202.c | 14 +--
- arch/arm/mach-at91/board-neocore926.c | 13 +--
- arch/arm/mach-at91/board-picotux200.c | 14 +--
- arch/arm/mach-at91/board-qil-a9260.c | 14 +--
- arch/arm/mach-at91/board-rm9200dk.c | 14 +--
- arch/arm/mach-at91/board-rm9200ek.c | 14 +--
- arch/arm/mach-at91/board-rsi-ews.c | 13 +--
- arch/arm/mach-at91/board-sam9-l9260.c | 16 +--
- arch/arm/mach-at91/board-sam9260ek.c | 16 +--
- arch/arm/mach-at91/board-sam9261ek.c | 13 +--
- arch/arm/mach-at91/board-sam9263ek.c | 13 +--
- arch/arm/mach-at91/board-sam9g20ek.c | 16 +--
- arch/arm/mach-at91/board-sam9rlek.c | 13 +--
- arch/arm/mach-at91/board-stamp9g20.c | 14 ---
- arch/arm/mach-at91/board-usb-a926x.c | 2 -
- arch/arm/mach-at91/board-yl-9200.c | 13 +--
- 32 files changed, 375 insertions(+), 439 deletions(-)
-
-diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
-index 01fb732..9ac427a 100644
---- a/arch/arm/mach-at91/at91rm9200_devices.c
-+++ b/arch/arm/mach-at91/at91rm9200_devices.c
-@@ -294,9 +294,9 @@ void __init at91_add_device_cf(struct at91_cf_data *data) {}
- * MMC / SD
- * -------------------------------------------------------------------- */
-
--#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-+#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
- static u64 mmc_dmamask = DMA_BIT_MASK(32);
--static struct at91_mmc_data mmc_data;
-+static struct mci_platform_data mmc_data;
-
- static struct resource mmc_resources[] = {
- [0] = {
-@@ -312,7 +312,7 @@ static struct resource mmc_resources[] = {
- };
-
- static struct platform_device at91rm9200_mmc_device = {
-- .name = "at91_mci",
-+ .name = "atmel_mci",
- .id = -1,
- .dev = {
- .dma_mask = &mmc_dmamask,
-@@ -323,53 +323,69 @@ static struct platform_device at91rm9200_mmc_device = {
- .num_resources = ARRAY_SIZE(mmc_resources),
- };
-
--void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
- {
-+ unsigned int i;
-+ unsigned int slot_count = 0;
-+
- if (!data)
- return;
-
-- /* input/irq */
-- if (gpio_is_valid(data->det_pin)) {
-- at91_set_gpio_input(data->det_pin, 1);
-- at91_set_deglitch(data->det_pin, 1);
-- }
-- if (gpio_is_valid(data->wp_pin))
-- at91_set_gpio_input(data->wp_pin, 1);
-- if (gpio_is_valid(data->vcc_pin))
-- at91_set_gpio_output(data->vcc_pin, 0);
--
-- /* CLK */
-- at91_set_A_periph(AT91_PIN_PA27, 0);
-+ for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
-
-- if (data->slot_b) {
-- /* CMD */
-- at91_set_B_periph(AT91_PIN_PA8, 1);
-+ if (!data->slot[i].bus_width)
-+ continue;
-
-- /* DAT0, maybe DAT1..DAT3 */
-- at91_set_B_periph(AT91_PIN_PA9, 1);
-- if (data->wire4) {
-- at91_set_B_periph(AT91_PIN_PA10, 1);
-- at91_set_B_periph(AT91_PIN_PA11, 1);
-- at91_set_B_periph(AT91_PIN_PA12, 1);
-+ /* input/irq */
-+ if (gpio_is_valid(data->slot[i].detect_pin)) {
-+ at91_set_gpio_input(data->slot[i].detect_pin, 1);
-+ at91_set_deglitch(data->slot[i].detect_pin, 1);
- }
-- } else {
-- /* CMD */
-- at91_set_A_periph(AT91_PIN_PA28, 1);
--
-- /* DAT0, maybe DAT1..DAT3 */
-- at91_set_A_periph(AT91_PIN_PA29, 1);
-- if (data->wire4) {
-- at91_set_B_periph(AT91_PIN_PB3, 1);
-- at91_set_B_periph(AT91_PIN_PB4, 1);
-- at91_set_B_periph(AT91_PIN_PB5, 1);
-+ if (gpio_is_valid(data->slot[i].wp_pin))
-+ at91_set_gpio_input(data->slot[i].wp_pin, 1);
-+
-+ switch (i) {
-+ case 0: /* slot A */
-+ /* CMD */
-+ at91_set_A_periph(AT91_PIN_PA28, 1);
-+ /* DAT0, maybe DAT1..DAT3 */
-+ at91_set_A_periph(AT91_PIN_PA29, 1);
-+ if (data->slot[i].bus_width == 4) {
-+ at91_set_B_periph(AT91_PIN_PB3, 1);
-+ at91_set_B_periph(AT91_PIN_PB4, 1);
-+ at91_set_B_periph(AT91_PIN_PB5, 1);
-+ }
-+ slot_count++;
-+ break;
-+ case 1: /* slot B */
-+ /* CMD */
-+ at91_set_B_periph(AT91_PIN_PA8, 1);
-+ /* DAT0, maybe DAT1..DAT3 */
-+ at91_set_B_periph(AT91_PIN_PA9, 1);
-+ if (data->slot[i].bus_width == 4) {
-+ at91_set_B_periph(AT91_PIN_PA10, 1);
-+ at91_set_B_periph(AT91_PIN_PA11, 1);
-+ at91_set_B_periph(AT91_PIN_PA12, 1);
-+ }
-+ slot_count++;
-+ break;
-+ default:
-+ printk(KERN_ERR
-+ "AT91: SD/MMC slot %d not available\n", i);
-+ break;
-+ }
-+ if (slot_count) {
-+ /* CLK */
-+ at91_set_A_periph(AT91_PIN_PA27, 0);
-+
-+ mmc_data = *data;
-+ platform_device_register(&at91rm9200_mmc_device);
- }
- }
-
-- mmc_data = *data;
-- platform_device_register(&at91rm9200_mmc_device);
- }
- #else
--void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
- #endif
-
-
-diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
-index 43e60fb..2c54662 100644
---- a/arch/arm/mach-at91/at91sam9260_devices.c
-+++ b/arch/arm/mach-at91/at91sam9260_devices.c
-@@ -206,92 +206,10 @@ void __init at91_add_device_eth(struct macb_platform_data *data) {}
-
-
- /* --------------------------------------------------------------------
-- * MMC / SD
-- * -------------------------------------------------------------------- */
--
--#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
--static u64 mmc_dmamask = DMA_BIT_MASK(32);
--static struct at91_mmc_data mmc_data;
--
--static struct resource mmc_resources[] = {
-- [0] = {
-- .start = AT91SAM9260_BASE_MCI,
-- .end = AT91SAM9260_BASE_MCI + SZ_16K - 1,
-- .flags = IORESOURCE_MEM,
-- },
-- [1] = {
-- .start = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
-- .end = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
-- .flags = IORESOURCE_IRQ,
-- },
--};
--
--static struct platform_device at91sam9260_mmc_device = {
-- .name = "at91_mci",
-- .id = -1,
-- .dev = {
-- .dma_mask = &mmc_dmamask,
-- .coherent_dma_mask = DMA_BIT_MASK(32),
-- .platform_data = &mmc_data,
-- },
-- .resource = mmc_resources,
-- .num_resources = ARRAY_SIZE(mmc_resources),
--};
--
--void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
--{
-- if (!data)
-- return;
--
-- /* input/irq */
-- if (gpio_is_valid(data->det_pin)) {
-- at91_set_gpio_input(data->det_pin, 1);
-- at91_set_deglitch(data->det_pin, 1);
-- }
-- if (gpio_is_valid(data->wp_pin))
-- at91_set_gpio_input(data->wp_pin, 1);
-- if (gpio_is_valid(data->vcc_pin))
-- at91_set_gpio_output(data->vcc_pin, 0);
--
-- /* CLK */
-- at91_set_A_periph(AT91_PIN_PA8, 0);
--
-- if (data->slot_b) {
-- /* CMD */
-- at91_set_B_periph(AT91_PIN_PA1, 1);
--
-- /* DAT0, maybe DAT1..DAT3 */
-- at91_set_B_periph(AT91_PIN_PA0, 1);
-- if (data->wire4) {
-- at91_set_B_periph(AT91_PIN_PA5, 1);
-- at91_set_B_periph(AT91_PIN_PA4, 1);
-- at91_set_B_periph(AT91_PIN_PA3, 1);
-- }
-- } else {
-- /* CMD */
-- at91_set_A_periph(AT91_PIN_PA7, 1);
--
-- /* DAT0, maybe DAT1..DAT3 */
-- at91_set_A_periph(AT91_PIN_PA6, 1);
-- if (data->wire4) {
-- at91_set_A_periph(AT91_PIN_PA9, 1);
-- at91_set_A_periph(AT91_PIN_PA10, 1);
-- at91_set_A_periph(AT91_PIN_PA11, 1);
-- }
-- }
--
-- mmc_data = *data;
-- platform_device_register(&at91sam9260_mmc_device);
--}
--#else
--void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
--#endif
--
--/* --------------------------------------------------------------------
- * MMC / SD Slot for Atmel MCI Driver
- * -------------------------------------------------------------------- */
-
--#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-+#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
- static u64 mmc_dmamask = DMA_BIT_MASK(32);
- static struct mci_platform_data mmc_data;
-
-diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
-index 1eecff8..08b3b02 100644
---- a/arch/arm/mach-at91/at91sam9261_devices.c
-+++ b/arch/arm/mach-at91/at91sam9261_devices.c
-@@ -139,9 +139,9 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
- * MMC / SD
- * -------------------------------------------------------------------- */
-
--#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-+#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
- static u64 mmc_dmamask = DMA_BIT_MASK(32);
--static struct at91_mmc_data mmc_data;
-+static struct mci_platform_data mmc_data;
-
- static struct resource mmc_resources[] = {
- [0] = {
-@@ -157,7 +157,7 @@ static struct resource mmc_resources[] = {
- };
-
- static struct platform_device at91sam9261_mmc_device = {
-- .name = "at91_mci",
-+ .name = "atmel_mci",
- .id = -1,
- .dev = {
- .dma_mask = &mmc_dmamask,
-@@ -168,40 +168,40 @@ static struct platform_device at91sam9261_mmc_device = {
- .num_resources = ARRAY_SIZE(mmc_resources),
- };
-
--void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
- {
- if (!data)
- return;
-
-- /* input/irq */
-- if (gpio_is_valid(data->det_pin)) {
-- at91_set_gpio_input(data->det_pin, 1);
-- at91_set_deglitch(data->det_pin, 1);
-- }
-- if (gpio_is_valid(data->wp_pin))
-- at91_set_gpio_input(data->wp_pin, 1);
-- if (gpio_is_valid(data->vcc_pin))
-- at91_set_gpio_output(data->vcc_pin, 0);
--
-- /* CLK */
-- at91_set_B_periph(AT91_PIN_PA2, 0);
--
-- /* CMD */
-- at91_set_B_periph(AT91_PIN_PA1, 1);
--
-- /* DAT0, maybe DAT1..DAT3 */
-- at91_set_B_periph(AT91_PIN_PA0, 1);
-- if (data->wire4) {
-- at91_set_B_periph(AT91_PIN_PA4, 1);
-- at91_set_B_periph(AT91_PIN_PA5, 1);
-- at91_set_B_periph(AT91_PIN_PA6, 1);
-- }
-+ if (data->slot[0].bus_width) {
-+ /* input/irq */
-+ if (gpio_is_valid(data->slot[0].detect_pin)) {
-+ at91_set_gpio_input(data->slot[0].detect_pin, 1);
-+ at91_set_deglitch(data->slot[0].detect_pin, 1);
-+ }
-+ if (gpio_is_valid(data->slot[0].wp_pin))
-+ at91_set_gpio_input(data->slot[0].wp_pin, 1);
-+
-+ /* CLK */
-+ at91_set_B_periph(AT91_PIN_PA2, 0);
-
-- mmc_data = *data;
-- platform_device_register(&at91sam9261_mmc_device);
-+ /* CMD */
-+ at91_set_B_periph(AT91_PIN_PA1, 1);
-+
-+ /* DAT0, maybe DAT1..DAT3 */
-+ at91_set_B_periph(AT91_PIN_PA0, 1);
-+ if (data->slot[0].bus_width == 4) {
-+ at91_set_B_periph(AT91_PIN_PA4, 1);
-+ at91_set_B_periph(AT91_PIN_PA5, 1);
-+ at91_set_B_periph(AT91_PIN_PA6, 1);
-+ }
-+
-+ mmc_data = *data;
-+ platform_device_register(&at91sam9261_mmc_device);
-+ }
- }
- #else
--void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
- #endif
-
-
-diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
-index 84b3810..144ef5d 100644
---- a/arch/arm/mach-at91/at91sam9263.c
-+++ b/arch/arm/mach-at91/at91sam9263.c
-@@ -188,8 +188,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_ID("hclk", &macb_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
-- CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.0", &mmc0_clk),
-- CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.1", &mmc1_clk),
-+ CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk),
-+ CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk),
- CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
- CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
- CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
-diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
-index f0318e9..a111315 100644
---- a/arch/arm/mach-at91/at91sam9263_devices.c
-+++ b/arch/arm/mach-at91/at91sam9263_devices.c
-@@ -220,9 +220,9 @@ void __init at91_add_device_eth(struct macb_platform_data *data) {}
- * MMC / SD
- * -------------------------------------------------------------------- */
-
--#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-+#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
- static u64 mmc_dmamask = DMA_BIT_MASK(32);
--static struct at91_mmc_data mmc0_data, mmc1_data;
-+static struct mci_platform_data mmc0_data, mmc1_data;
-
- static struct resource mmc0_resources[] = {
- [0] = {
-@@ -238,7 +238,7 @@ static struct resource mmc0_resources[] = {
- };
-
- static struct platform_device at91sam9263_mmc0_device = {
-- .name = "at91_mci",
-+ .name = "atmel_mci",
- .id = 0,
- .dev = {
- .dma_mask = &mmc_dmamask,
-@@ -263,7 +263,7 @@ static struct resource mmc1_resources[] = {
- };
-
- static struct platform_device at91sam9263_mmc1_device = {
-- .name = "at91_mci",
-+ .name = "atmel_mci",
- .id = 1,
- .dev = {
- .dma_mask = &mmc_dmamask,
-@@ -274,85 +274,110 @@ static struct platform_device at91sam9263_mmc1_device = {
- .num_resources = ARRAY_SIZE(mmc1_resources),
- };
-
--void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
- {
-+ unsigned int i;
-+ unsigned int slot_count = 0;
-+
- if (!data)
- return;
-
-- /* input/irq */
-- if (gpio_is_valid(data->det_pin)) {
-- at91_set_gpio_input(data->det_pin, 1);
-- at91_set_deglitch(data->det_pin, 1);
-- }
-- if (gpio_is_valid(data->wp_pin))
-- at91_set_gpio_input(data->wp_pin, 1);
-- if (gpio_is_valid(data->vcc_pin))
-- at91_set_gpio_output(data->vcc_pin, 0);
-+ for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
-
-- if (mmc_id == 0) { /* MCI0 */
-- /* CLK */
-- at91_set_A_periph(AT91_PIN_PA12, 0);
-+ if (!data->slot[i].bus_width)
-+ continue;
-
-- if (data->slot_b) {
-- /* CMD */
-- at91_set_A_periph(AT91_PIN_PA16, 1);
-+ /* input/irq */
-+ if (gpio_is_valid(data->slot[i].detect_pin)) {
-+ at91_set_gpio_input(data->slot[i].detect_pin,
-+ 1);
-+ at91_set_deglitch(data->slot[i].detect_pin,
-+ 1);
-+ }
-+ if (gpio_is_valid(data->slot[i].wp_pin))
-+ at91_set_gpio_input(data->slot[i].wp_pin, 1);
-+
-+ if (mmc_id == 0) { /* MCI0 */
-+ switch (i) {
-+ case 0: /* slot A */
-+ /* CMD */
-+ at91_set_A_periph(AT91_PIN_PA1, 1);
-+ /* DAT0, maybe DAT1..DAT3 */
-+ at91_set_A_periph(AT91_PIN_PA0, 1);
-+ if (data->slot[i].bus_width == 4) {
-+ at91_set_A_periph(AT91_PIN_PA3, 1);
-+ at91_set_A_periph(AT91_PIN_PA4, 1);
-+ at91_set_A_periph(AT91_PIN_PA5, 1);
-+ }
-+ slot_count++;
-+ break;
-+ case 1: /* slot B */
-+ /* CMD */
-+ at91_set_A_periph(AT91_PIN_PA16, 1);
-+ /* DAT0, maybe DAT1..DAT3 */
-+ at91_set_A_periph(AT91_PIN_PA17, 1);
-+ if (data->slot[i].bus_width == 4) {
-+ at91_set_A_periph(AT91_PIN_PA18, 1);
-+ at91_set_A_periph(AT91_PIN_PA19, 1);
-+ at91_set_A_periph(AT91_PIN_PA20, 1);
-+ }
-+ slot_count++;
-+ break;
-+ default:
-+ printk(KERN_ERR
-+ "AT91: SD/MMC slot %d not available\n", i);
-+ break;
-+ }
-+ if (slot_count) {
-+ /* CLK */
-+ at91_set_A_periph(AT91_PIN_PA12, 0);
-
-- /* DAT0, maybe DAT1..DAT3 */
-- at91_set_A_periph(AT91_PIN_PA17, 1);
-- if (data->wire4) {
-- at91_set_A_periph(AT91_PIN_PA18, 1);
-- at91_set_A_periph(AT91_PIN_PA19, 1);
-- at91_set_A_periph(AT91_PIN_PA20, 1);
-+ mmc0_data = *data;
-+ platform_device_register(&at91sam9263_mmc0_device);
- }
-- } else {
-- /* CMD */
-- at91_set_A_periph(AT91_PIN_PA1, 1);
--
-- /* DAT0, maybe DAT1..DAT3 */
-- at91_set_A_periph(AT91_PIN_PA0, 1);
-- if (data->wire4) {
-- at91_set_A_periph(AT91_PIN_PA3, 1);
-- at91_set_A_periph(AT91_PIN_PA4, 1);
-- at91_set_A_periph(AT91_PIN_PA5, 1);
-+ } else if (mmc_id == 1) { /* MCI1 */
-+ switch (i) {
-+ case 0: /* slot A */
-+ /* CMD */
-+ at91_set_A_periph(AT91_PIN_PA7, 1);
-+ /* DAT0, maybe DAT1..DAT3 */
-+ at91_set_A_periph(AT91_PIN_PA8, 1);
-+ if (data->slot[i].bus_width == 4) {
-+ at91_set_A_periph(AT91_PIN_PA9, 1);
-+ at91_set_A_periph(AT91_PIN_PA10, 1);
-+ at91_set_A_periph(AT91_PIN_PA11, 1);
-+ }
-+ slot_count++;
-+ break;
-+ case 1: /* slot B */
-+ /* CMD */
-+ at91_set_A_periph(AT91_PIN_PA21, 1);
-+ /* DAT0, maybe DAT1..DAT3 */
-+ at91_set_A_periph(AT91_PIN_PA22, 1);
-+ if (data->slot[i].bus_width == 4) {
-+ at91_set_A_periph(AT91_PIN_PA23, 1);
-+ at91_set_A_periph(AT91_PIN_PA24, 1);
-+ at91_set_A_periph(AT91_PIN_PA25, 1);
-+ }
-+ slot_count++;
-+ break;
-+ default:
-+ printk(KERN_ERR
-+ "AT91: SD/MMC slot %d not available\n", i);
-+ break;
- }
-- }
-+ if (slot_count) {
-+ /* CLK */
-+ at91_set_A_periph(AT91_PIN_PA6, 0);
-
-- mmc0_data = *data;
-- platform_device_register(&at91sam9263_mmc0_device);
-- } else { /* MCI1 */
-- /* CLK */
-- at91_set_A_periph(AT91_PIN_PA6, 0);
--
-- if (data->slot_b) {
-- /* CMD */
-- at91_set_A_periph(AT91_PIN_PA21, 1);
--
-- /* DAT0, maybe DAT1..DAT3 */
-- at91_set_A_periph(AT91_PIN_PA22, 1);
-- if (data->wire4) {
-- at91_set_A_periph(AT91_PIN_PA23, 1);
-- at91_set_A_periph(AT91_PIN_PA24, 1);
-- at91_set_A_periph(AT91_PIN_PA25, 1);
-- }
-- } else {
-- /* CMD */
-- at91_set_A_periph(AT91_PIN_PA7, 1);
--
-- /* DAT0, maybe DAT1..DAT3 */
-- at91_set_A_periph(AT91_PIN_PA8, 1);
-- if (data->wire4) {
-- at91_set_A_periph(AT91_PIN_PA9, 1);
-- at91_set_A_periph(AT91_PIN_PA10, 1);
-- at91_set_A_periph(AT91_PIN_PA11, 1);
-+ mmc1_data = *data;
-+ platform_device_register(&at91sam9263_mmc1_device);
- }
- }
--
-- mmc1_data = *data;
-- platform_device_register(&at91sam9263_mmc1_device);
- }
- }
- #else
--void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
- #endif
-
- /* --------------------------------------------------------------------
-diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
-index 0d1b76f..88687b9 100644
---- a/arch/arm/mach-at91/at91sam9rl_devices.c
-+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
-@@ -163,9 +163,9 @@ void __init at91_add_device_usba(struct usba_platform_data *data) {}
- * MMC / SD
- * -------------------------------------------------------------------- */
-
--#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-+#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
- static u64 mmc_dmamask = DMA_BIT_MASK(32);
--static struct at91_mmc_data mmc_data;
-+static struct mci_platform_data mmc_data;
-
- static struct resource mmc_resources[] = {
- [0] = {
-@@ -181,7 +181,7 @@ static struct resource mmc_resources[] = {
- };
-
- static struct platform_device at91sam9rl_mmc_device = {
-- .name = "at91_mci",
-+ .name = "atmel_mci",
- .id = -1,
- .dev = {
- .dma_mask = &mmc_dmamask,
-@@ -192,40 +192,40 @@ static struct platform_device at91sam9rl_mmc_device = {
- .num_resources = ARRAY_SIZE(mmc_resources),
- };
-
--void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
- {
- if (!data)
- return;
-
-- /* input/irq */
-- if (gpio_is_valid(data->det_pin)) {
-- at91_set_gpio_input(data->det_pin, 1);
-- at91_set_deglitch(data->det_pin, 1);
-- }
-- if (gpio_is_valid(data->wp_pin))
-- at91_set_gpio_input(data->wp_pin, 1);
-- if (gpio_is_valid(data->vcc_pin))
-- at91_set_gpio_output(data->vcc_pin, 0);
--
-- /* CLK */
-- at91_set_A_periph(AT91_PIN_PA2, 0);
--
-- /* CMD */
-- at91_set_A_periph(AT91_PIN_PA1, 1);
--
-- /* DAT0, maybe DAT1..DAT3 */
-- at91_set_A_periph(AT91_PIN_PA0, 1);
-- if (data->wire4) {
-- at91_set_A_periph(AT91_PIN_PA3, 1);
-- at91_set_A_periph(AT91_PIN_PA4, 1);
-- at91_set_A_periph(AT91_PIN_PA5, 1);
-+ if (data->slot[0].bus_width) {
-+ /* input/irq */
-+ if (gpio_is_valid(data->slot[0].detect_pin)) {
-+ at91_set_gpio_input(data->slot[0].detect_pin, 1);
-+ at91_set_deglitch(data->slot[0].detect_pin, 1);
-+ }
-+ if (gpio_is_valid(data->slot[0].wp_pin))
-+ at91_set_gpio_input(data->slot[0].wp_pin, 1);
-+
-+ /* CLK */
-+ at91_set_A_periph(AT91_PIN_PA2, 0);
-+
-+ /* CMD */
-+ at91_set_A_periph(AT91_PIN_PA1, 1);
-+
-+ /* DAT0, maybe DAT1..DAT3 */
-+ at91_set_A_periph(AT91_PIN_PA0, 1);
-+ if (data->slot[0].bus_width == 4) {
-+ at91_set_A_periph(AT91_PIN_PA3, 1);
-+ at91_set_A_periph(AT91_PIN_PA4, 1);
-+ at91_set_A_periph(AT91_PIN_PA5, 1);
-+ }
-+
-+ mmc_data = *data;
-+ platform_device_register(&at91sam9rl_mmc_device);
- }
--
-- mmc_data = *data;
-- platform_device_register(&at91sam9rl_mmc_device);
- }
- #else
--void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
- #endif
-
-
-diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
-index de7be19..93a832f 100644
---- a/arch/arm/mach-at91/board-afeb-9260v1.c
-+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
-@@ -133,12 +133,12 @@ static struct atmel_nand_data __initdata afeb9260_nand_data = {
- /*
- * MCI (SD/MMC)
- */
--static struct at91_mmc_data __initdata afeb9260_mmc_data = {
-- .det_pin = AT91_PIN_PC9,
-- .wp_pin = AT91_PIN_PC4,
-- .slot_b = 1,
-- .wire4 = 1,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata afeb9260_mci0_data = {
-+ .slot[1] = {
-+ .bus_width = 4,
-+ .detect_pin = AT91_PIN_PC9,
-+ .wp_pin = AT91_PIN_PC4,
-+ },
- };
-
-
-@@ -199,7 +199,7 @@ static void __init afeb9260_board_init(void)
- at91_set_B_periph(AT91_PIN_PA10, 0); /* ETX2 */
- at91_set_B_periph(AT91_PIN_PA11, 0); /* ETX3 */
- /* MMC */
-- at91_add_device_mmc(0, &afeb9260_mmc_data);
-+ at91_add_device_mci(0, &afeb9260_mci0_data);
- /* I2C */
- at91_add_device_i2c(afeb9260_i2c_devices,
- ARRAY_SIZE(afeb9260_i2c_devices));
-diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
-index a5b002f..71d8f36 100644
---- a/arch/arm/mach-at91/board-carmeva.c
-+++ b/arch/arm/mach-at91/board-carmeva.c
-@@ -71,12 +71,12 @@ static struct at91_udc_data __initdata carmeva_udc_data = {
- // .vcc_pin = -EINVAL,
- // };
-
--static struct at91_mmc_data __initdata carmeva_mmc_data = {
-- .slot_b = 0,
-- .wire4 = 1,
-- .det_pin = AT91_PIN_PB10,
-- .wp_pin = AT91_PIN_PC14,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata carmeva_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = AT91_PIN_PB10,
-+ .wp_pin = AT91_PIN_PC14,
-+ },
- };
-
- static struct spi_board_info carmeva_spi_devices[] = {
-@@ -150,7 +150,7 @@ static void __init carmeva_board_init(void)
- /* Compact Flash */
- // at91_add_device_cf(&carmeva_cf_data);
- /* MMC */
-- at91_add_device_mmc(0, &carmeva_mmc_data);
-+ at91_add_device_mci(0, &carmeva_mci0_data);
- /* LEDs */
- at91_gpio_leds(carmeva_leds, ARRAY_SIZE(carmeva_leds));
- }
-diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
-index 7ddc219..e71c473 100644
---- a/arch/arm/mach-at91/board-cpu9krea.c
-+++ b/arch/arm/mach-at91/board-cpu9krea.c
-@@ -311,12 +311,12 @@ static void __init cpu9krea_add_device_buttons(void)
- /*
- * MCI (SD/MMC)
- */
--static struct at91_mmc_data __initdata cpu9krea_mmc_data = {
-- .slot_b = 0,
-- .wire4 = 1,
-- .det_pin = AT91_PIN_PA29,
-- .wp_pin = -EINVAL,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata cpu9krea_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = AT91_PIN_PA29,
-+ .wp_pin = -EINVAL,
-+ },
- };
-
- static void __init cpu9krea_board_init(void)
-@@ -358,7 +358,7 @@ static void __init cpu9krea_board_init(void)
- /* Ethernet */
- at91_add_device_eth(&cpu9krea_macb_data);
- /* MMC */
-- at91_add_device_mmc(0, &cpu9krea_mmc_data);
-+ at91_add_device_mci(0, &cpu9krea_mci0_data);
- /* I2C */
- at91_add_device_i2c(cpu9krea_i2c_devices,
- ARRAY_SIZE(cpu9krea_i2c_devices));
-diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
-index 2e6d043..2cbd1a2 100644
---- a/arch/arm/mach-at91/board-cpuat91.c
-+++ b/arch/arm/mach-at91/board-cpuat91.c
-@@ -78,11 +78,12 @@ static struct at91_udc_data __initdata cpuat91_udc_data = {
- .pullup_pin = AT91_PIN_PC14,
- };
-
--static struct at91_mmc_data __initdata cpuat91_mmc_data = {
-- .det_pin = AT91_PIN_PC2,
-- .wire4 = 1,
-- .wp_pin = -EINVAL,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata cpuat91_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = AT91_PIN_PC2,
-+ .wp_pin = -EINVAL,
-+ },
- };
-
- static struct physmap_flash_data cpuat91_flash_data = {
-@@ -168,7 +169,7 @@ static void __init cpuat91_board_init(void)
- /* USB Device */
- at91_add_device_udc(&cpuat91_udc_data);
- /* MMC */
-- at91_add_device_mmc(0, &cpuat91_mmc_data);
-+ at91_add_device_mci(0, &cpuat91_mci0_data);
- /* I2C */
- at91_add_device_i2c(NULL, 0);
- /* Platform devices */
-diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
-index 462bc31..81a8bc4 100644
---- a/arch/arm/mach-at91/board-csb337.c
-+++ b/arch/arm/mach-at91/board-csb337.c
-@@ -87,12 +87,12 @@ static struct at91_cf_data __initdata csb337_cf_data = {
- .rst_pin = AT91_PIN_PD2,
- };
-
--static struct at91_mmc_data __initdata csb337_mmc_data = {
-- .det_pin = AT91_PIN_PD5,
-- .slot_b = 0,
-- .wire4 = 1,
-- .wp_pin = AT91_PIN_PD6,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata csb337_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = AT91_PIN_PD5,
-+ .wp_pin = AT91_PIN_PD6,
-+ },
- };
-
- static struct spi_board_info csb337_spi_devices[] = {
-@@ -240,7 +240,7 @@ static void __init csb337_board_init(void)
- /* SPI */
- at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices));
- /* MMC */
-- at91_add_device_mmc(0, &csb337_mmc_data);
-+ at91_add_device_mci(0, &csb337_mci0_data);
- /* NOR flash */
- platform_device_register(&csb_flash);
- /* LEDs */
-diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
-index d1e1f3f..0cfac16 100644
---- a/arch/arm/mach-at91/board-eb9200.c
-+++ b/arch/arm/mach-at91/board-eb9200.c
-@@ -70,12 +70,12 @@ static struct at91_cf_data __initdata eb9200_cf_data = {
- .rst_pin = AT91_PIN_PC5,
- };
-
--static struct at91_mmc_data __initdata eb9200_mmc_data = {
-- .slot_b = 0,
-- .wire4 = 1,
-- .det_pin = -EINVAL,
-- .wp_pin = -EINVAL,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata eb9200_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = -EINVAL,
-+ .wp_pin = -EINVAL,
-+ },
- };
-
- static struct i2c_board_info __initdata eb9200_i2c_devices[] = {
-@@ -113,7 +113,7 @@ static void __init eb9200_board_init(void)
- at91_add_device_spi(NULL, 0);
- /* MMC */
- /* only supports 1 or 4 bit interface, not wired through to SPI */
-- at91_add_device_mmc(0, &eb9200_mmc_data);
-+ at91_add_device_mci(0, &eb9200_mci0_data);
- }
-
- MACHINE_START(ATEB9200, "Embest ATEB9200")
-diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
-index 9c24cb2..a9d50fc 100644
---- a/arch/arm/mach-at91/board-ecbat91.c
-+++ b/arch/arm/mach-at91/board-ecbat91.c
-@@ -64,12 +64,12 @@ static struct at91_usbh_data __initdata ecb_at91usbh_data = {
- .overcurrent_pin= {-EINVAL, -EINVAL},
- };
-
--static struct at91_mmc_data __initdata ecb_at91mmc_data = {
-- .slot_b = 0,
-- .wire4 = 1,
-- .det_pin = -EINVAL,
-- .wp_pin = -EINVAL,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata ecbat91_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = -EINVAL,
-+ .wp_pin = -EINVAL,
-+ },
- };
-
-
-@@ -161,7 +161,7 @@ static void __init ecb_at91board_init(void)
- at91_add_device_i2c(NULL, 0);
-
- /* MMC */
-- at91_add_device_mmc(0, &ecb_at91mmc_data);
-+ at91_add_device_mci(0, &ecbat91_mci0_data);
-
- /* SPI */
- at91_add_device_spi(ecb_at91spi_devices, ARRAY_SIZE(ecb_at91spi_devices));
-diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c
-index 82bdfde..aaf7015 100644
---- a/arch/arm/mach-at91/board-eco920.c
-+++ b/arch/arm/mach-at91/board-eco920.c
-@@ -56,12 +56,12 @@ static struct at91_udc_data __initdata eco920_udc_data = {
- .pullup_pin = AT91_PIN_PB13,
- };
-
--static struct at91_mmc_data __initdata eco920_mmc_data = {
-- .slot_b = 0,
-- .wire4 = 0,
-- .det_pin = -EINVAL,
-- .wp_pin = -EINVAL,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata eco920_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 1,
-+ .detect_pin = -EINVAL,
-+ .wp_pin = -EINVAL,
-+ },
- };
-
- static struct physmap_flash_data eco920_flash_data = {
-@@ -104,7 +104,7 @@ static void __init eco920_board_init(void)
- at91_add_device_usbh(&eco920_usbh_data);
- at91_add_device_udc(&eco920_udc_data);
-
-- at91_add_device_mmc(0, &eco920_mmc_data);
-+ at91_add_device_mci(0, &eco920_mci0_data);
- platform_device_register(&eco920_flash);
-
- at91_ramc_write(0, AT91_SMC_CSR(7), AT91_SMC_RWHOLD_(1)
-diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
-index 6cc83a8..fa98aba 100644
---- a/arch/arm/mach-at91/board-flexibity.c
-+++ b/arch/arm/mach-at91/board-flexibity.c
-@@ -75,12 +75,12 @@ static struct spi_board_info flexibity_spi_devices[] = {
- };
-
- /* MCI (SD/MMC) */
--static struct at91_mmc_data __initdata flexibity_mmc_data = {
-- .slot_b = 0,
-- .wire4 = 1,
-- .det_pin = AT91_PIN_PC9,
-- .wp_pin = AT91_PIN_PC4,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata flexibity_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = AT91_PIN_PC9,
-+ .wp_pin = AT91_PIN_PC4,
-+ },
- };
-
- /* LEDs */
-@@ -152,7 +152,7 @@ static void __init flexibity_board_init(void)
- at91_add_device_spi(flexibity_spi_devices,
- ARRAY_SIZE(flexibity_spi_devices));
- /* MMC */
-- at91_add_device_mmc(0, &flexibity_mmc_data);
-+ at91_add_device_mci(0, &flexibity_mci0_data);
- /* LEDs */
- at91_gpio_leds(flexibity_leds, ARRAY_SIZE(flexibity_leds));
- }
-diff --git a/arch/arm/mach-at91/board-foxg20.c b/arch/arm/mach-at91/board-foxg20.c
-index 69ab124..6e47071 100644
---- a/arch/arm/mach-at91/board-foxg20.c
-+++ b/arch/arm/mach-at91/board-foxg20.c
-@@ -86,7 +86,7 @@ static struct at91_udc_data __initdata foxg20_udc_data = {
- * SPI devices.
- */
- static struct spi_board_info foxg20_spi_devices[] = {
--#if !defined(CONFIG_MMC_AT91)
-+#if !IS_ENABLED(CONFIG_MMC_ATMELMCI)
- {
- .modalias = "mtd_dataflash",
- .chip_select = 1,
-@@ -109,12 +109,12 @@ static struct macb_platform_data __initdata foxg20_macb_data = {
- * MCI (SD/MMC)
- * det_pin, wp_pin and vcc_pin are not connected
- */
--static struct at91_mmc_data __initdata foxg20_mmc_data = {
-- .slot_b = 1,
-- .wire4 = 1,
-- .det_pin = -EINVAL,
-- .wp_pin = -EINVAL,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata foxg20_mci0_data = {
-+ .slot[1] = {
-+ .bus_width = 4,
-+ .detect_pin = -EINVAL,
-+ .wp_pin = -EINVAL,
-+ },
- };
-
-
-@@ -247,7 +247,7 @@ static void __init foxg20_board_init(void)
- /* Ethernet */
- at91_add_device_eth(&foxg20_macb_data);
- /* MMC */
-- at91_add_device_mmc(0, &foxg20_mmc_data);
-+ at91_add_device_mci(0, &foxg20_mci0_data);
- /* I2C */
- at91_add_device_i2c(foxg20_i2c_devices, ARRAY_SIZE(foxg20_i2c_devices));
- /* LEDs */
-diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
-index 5d96cb8..330d603 100644
---- a/arch/arm/mach-at91/board-kb9202.c
-+++ b/arch/arm/mach-at91/board-kb9202.c
-@@ -69,12 +69,12 @@ static struct at91_udc_data __initdata kb9202_udc_data = {
- .pullup_pin = AT91_PIN_PB22,
- };
-
--static struct at91_mmc_data __initdata kb9202_mmc_data = {
-- .det_pin = AT91_PIN_PB2,
-- .slot_b = 0,
-- .wire4 = 1,
-- .wp_pin = -EINVAL,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata kb9202_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = AT91_PIN_PB2,
-+ .wp_pin = -EINVAL,
-+ },
- };
-
- static struct mtd_partition __initdata kb9202_nand_partition[] = {
-@@ -121,7 +121,7 @@ static void __init kb9202_board_init(void)
- /* USB Device */
- at91_add_device_udc(&kb9202_udc_data);
- /* MMC */
-- at91_add_device_mmc(0, &kb9202_mmc_data);
-+ at91_add_device_mci(0, &kb9202_mci0_data);
- /* I2C */
- at91_add_device_i2c(NULL, 0);
- /* SPI */
-diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
-index 5d3b4d6..7fb2a8f 100644
---- a/arch/arm/mach-at91/board-neocore926.c
-+++ b/arch/arm/mach-at91/board-neocore926.c
-@@ -140,11 +140,12 @@ static struct spi_board_info neocore926_spi_devices[] = {
- /*
- * MCI (SD/MMC)
- */
--static struct at91_mmc_data __initdata neocore926_mmc_data = {
-- .wire4 = 1,
-- .det_pin = AT91_PIN_PE18,
-- .wp_pin = AT91_PIN_PE19,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata neocore926_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = AT91_PIN_PE18,
-+ .wp_pin = AT91_PIN_PE19,
-+ },
- };
-
-
-@@ -356,7 +357,7 @@ static void __init neocore926_board_init(void)
- neocore926_add_device_ts();
-
- /* MMC */
-- at91_add_device_mmc(1, &neocore926_mmc_data);
-+ at91_add_device_mci(0, &neocore926_mci0_data);
-
- /* Ethernet */
- at91_add_device_eth(&neocore926_macb_data);
-diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
-index 1270655..f83e1de 100644
---- a/arch/arm/mach-at91/board-picotux200.c
-+++ b/arch/arm/mach-at91/board-picotux200.c
-@@ -62,12 +62,12 @@ static struct at91_usbh_data __initdata picotux200_usbh_data = {
- .overcurrent_pin= {-EINVAL, -EINVAL},
- };
-
--static struct at91_mmc_data __initdata picotux200_mmc_data = {
-- .det_pin = AT91_PIN_PB27,
-- .slot_b = 0,
-- .wire4 = 1,
-- .wp_pin = AT91_PIN_PA17,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata picotux200_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = AT91_PIN_PB27,
-+ .wp_pin = AT91_PIN_PA17,
-+ },
- };
-
- #define PICOTUX200_FLASH_BASE AT91_CHIPSELECT_0
-@@ -112,7 +112,7 @@ static void __init picotux200_board_init(void)
- at91_add_device_i2c(NULL, 0);
- /* MMC */
- at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
-- at91_add_device_mmc(0, &picotux200_mmc_data);
-+ at91_add_device_mci(0, &picotux200_mci0_data);
- /* NOR Flash */
- platform_device_register(&picotux200_flash);
- }
-diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
-index bf351e2..799f214 100644
---- a/arch/arm/mach-at91/board-qil-a9260.c
-+++ b/arch/arm/mach-at91/board-qil-a9260.c
-@@ -156,12 +156,12 @@ static void __init ek_add_device_nand(void)
- /*
- * MCI (SD/MMC)
- */
--static struct at91_mmc_data __initdata ek_mmc_data = {
-- .slot_b = 0,
-- .wire4 = 1,
-- .det_pin = -EINVAL,
-- .wp_pin = -EINVAL,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata ek_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = -EINVAL,
-+ .wp_pin = -EINVAL,
-+ },
- };
-
- /*
-@@ -245,7 +245,7 @@ static void __init ek_board_init(void)
- /* Ethernet */
- at91_add_device_eth(&ek_macb_data);
- /* MMC */
-- at91_add_device_mmc(0, &ek_mmc_data);
-+ at91_add_device_mci(0, &ek_mci0_data);
- /* Push Buttons */
- ek_add_device_buttons();
- /* LEDs */
-diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c
-index cc2bf97..54733ec 100644
---- a/arch/arm/mach-at91/board-rm9200dk.c
-+++ b/arch/arm/mach-at91/board-rm9200dk.c
-@@ -77,12 +77,12 @@ static struct at91_cf_data __initdata dk_cf_data = {
- };
-
- #ifndef CONFIG_MTD_AT91_DATAFLASH_CARD
--static struct at91_mmc_data __initdata dk_mmc_data = {
-- .slot_b = 0,
-- .wire4 = 1,
-- .det_pin = -EINVAL,
-- .wp_pin = -EINVAL,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata dk_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = -EINVAL,
-+ .wp_pin = -EINVAL,
-+ },
- };
- #endif
-
-@@ -208,7 +208,7 @@ static void __init dk_board_init(void)
- #else
- /* MMC */
- at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
-- at91_add_device_mmc(0, &dk_mmc_data);
-+ at91_add_device_mci(0, &dk_mci0_data);
- #endif
- /* NAND */
- at91_add_device_nand(&dk_nand_data);
-diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
-index 62e19e6..69ef141 100644
---- a/arch/arm/mach-at91/board-rm9200ek.c
-+++ b/arch/arm/mach-at91/board-rm9200ek.c
-@@ -70,12 +70,12 @@ static struct at91_udc_data __initdata ek_udc_data = {
- };
-
- #ifndef CONFIG_MTD_AT91_DATAFLASH_CARD
--static struct at91_mmc_data __initdata ek_mmc_data = {
-- .det_pin = AT91_PIN_PB27,
-- .slot_b = 0,
-- .wire4 = 1,
-- .wp_pin = AT91_PIN_PA17,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata ek_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = AT91_PIN_PB27,
-+ .wp_pin = AT91_PIN_PA17,
-+ }
- };
- #endif
-
-@@ -177,7 +177,7 @@ static void __init ek_board_init(void)
- #else
- /* MMC */
- at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
-- at91_add_device_mmc(0, &ek_mmc_data);
-+ at91_add_device_mci(0, &ek_mci0_data);
- #endif
- /* NOR Flash */
- platform_device_register(&ek_flash);
-diff --git a/arch/arm/mach-at91/board-rsi-ews.c b/arch/arm/mach-at91/board-rsi-ews.c
-index c3b43ae..806d0c3 100644
---- a/arch/arm/mach-at91/board-rsi-ews.c
-+++ b/arch/arm/mach-at91/board-rsi-ews.c
-@@ -58,11 +58,12 @@ static struct at91_usbh_data rsi_ews_usbh_data __initdata = {
- /*
- * SD/MC
- */
--static struct at91_mmc_data rsi_ews_mmc_data __initdata = {
-- .slot_b = 0,
-- .wire4 = 1,
-- .det_pin = AT91_PIN_PB27,
-- .wp_pin = AT91_PIN_PB29,
-+static struct mci_platform_data __initdata rsi_ews_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = AT91_PIN_PB27,
-+ .wp_pin = AT91_PIN_PB29,
-+ },
- };
-
- /*
-@@ -215,7 +216,7 @@ static void __init rsi_ews_board_init(void)
- at91_add_device_spi(rsi_ews_spi_devices,
- ARRAY_SIZE(rsi_ews_spi_devices));
- /* MMC */
-- at91_add_device_mmc(0, &rsi_ews_mmc_data);
-+ at91_add_device_mci(0, &rsi_ews_mci0_data);
- /* NOR Flash */
- platform_device_register(&rsiews_nor_flash);
- /* LEDs */
-diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
-index 7bf6da7..3573f10 100644
---- a/arch/arm/mach-at91/board-sam9-l9260.c
-+++ b/arch/arm/mach-at91/board-sam9-l9260.c
-@@ -73,7 +73,7 @@ static struct at91_udc_data __initdata ek_udc_data = {
- * SPI devices.
- */
- static struct spi_board_info ek_spi_devices[] = {
--#if !defined(CONFIG_MMC_AT91)
-+#if !IS_ENABLED(CONFIG_MMC_ATMELMCI)
- { /* DataFlash chip */
- .modalias = "mtd_dataflash",
- .chip_select = 1,
-@@ -158,12 +158,12 @@ static void __init ek_add_device_nand(void)
- /*
- * MCI (SD/MMC)
- */
--static struct at91_mmc_data __initdata ek_mmc_data = {
-- .slot_b = 1,
-- .wire4 = 1,
-- .det_pin = AT91_PIN_PC8,
-- .wp_pin = AT91_PIN_PC4,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata ek_mci0_data = {
-+ .slot[1] = {
-+ .bus_width = 4,
-+ .detect_pin = AT91_PIN_PC8,
-+ .wp_pin = AT91_PIN_PC4,
-+ },
- };
-
- static void __init ek_board_init(void)
-@@ -194,7 +194,7 @@ static void __init ek_board_init(void)
- /* Ethernet */
- at91_add_device_eth(&ek_macb_data);
- /* MMC */
-- at91_add_device_mmc(0, &ek_mmc_data);
-+ at91_add_device_mci(0, &ek_mci0_data);
- /* I2C */
- at91_add_device_i2c(NULL, 0);
- }
-diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
-index 889c1bf..8cd6e67 100644
---- a/arch/arm/mach-at91/board-sam9260ek.c
-+++ b/arch/arm/mach-at91/board-sam9260ek.c
-@@ -108,7 +108,7 @@ static void __init at73c213_set_clk(struct at73c213_board_info *info) {}
- * SPI devices.
- */
- static struct spi_board_info ek_spi_devices[] = {
--#if !defined(CONFIG_MMC_AT91)
-+#if !IS_ENABLED(CONFIG_MMC_ATMELMCI)
- { /* DataFlash chip */
- .modalias = "mtd_dataflash",
- .chip_select = 1,
-@@ -211,12 +211,12 @@ static void __init ek_add_device_nand(void)
- /*
- * MCI (SD/MMC)
- */
--static struct at91_mmc_data __initdata ek_mmc_data = {
-- .slot_b = 1,
-- .wire4 = 1,
-- .det_pin = -EINVAL,
-- .wp_pin = -EINVAL,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata ek_mci0_data = {
-+ .slot[1] = {
-+ .bus_width = 4,
-+ .detect_pin = -EINVAL,
-+ .wp_pin = -EINVAL,
-+ },
- };
-
-
-@@ -329,7 +329,7 @@ static void __init ek_board_init(void)
- /* Ethernet */
- at91_add_device_eth(&ek_macb_data);
- /* MMC */
-- at91_add_device_mmc(0, &ek_mmc_data);
-+ at91_add_device_mci(0, &ek_mci0_data);
- /* I2C */
- at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
- /* SSC (to AT73C213) */
-diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
-index 2e1c9c5..b8900d5 100644
---- a/arch/arm/mach-at91/board-sam9261ek.c
-+++ b/arch/arm/mach-at91/board-sam9261ek.c
-@@ -342,11 +342,12 @@ static struct spi_board_info ek_spi_devices[] = {
- * MCI (SD/MMC)
- * det_pin, wp_pin and vcc_pin are not connected
- */
--static struct at91_mmc_data __initdata ek_mmc_data = {
-- .wire4 = 1,
-- .det_pin = -EINVAL,
-- .wp_pin = -EINVAL,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = -EINVAL,
-+ .wp_pin = -EINVAL,
-+ },
- };
-
- #endif /* CONFIG_SPI_ATMEL_* */
-@@ -600,7 +601,7 @@ static void __init ek_board_init(void)
- at91_add_device_ssc(AT91SAM9261_ID_SSC1, ATMEL_SSC_TX);
- #else
- /* MMC */
-- at91_add_device_mmc(0, &ek_mmc_data);
-+ at91_add_device_mci(0, &mci0_data);
- #endif
- /* LCD Controller */
- at91_add_device_lcdc(&ek_lcdc_data);
-diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
-index 7c34908..d4dd017 100644
---- a/arch/arm/mach-at91/board-sam9263ek.c
-+++ b/arch/arm/mach-at91/board-sam9263ek.c
-@@ -143,11 +143,12 @@ static struct spi_board_info ek_spi_devices[] = {
- /*
- * MCI (SD/MMC)
- */
--static struct at91_mmc_data __initdata ek_mmc_data = {
-- .wire4 = 1,
-- .det_pin = AT91_PIN_PE18,
-- .wp_pin = AT91_PIN_PE19,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata mci1_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = AT91_PIN_PE18,
-+ .wp_pin = AT91_PIN_PE19,
-+ },
- };
-
-
-@@ -422,7 +423,7 @@ static void __init ek_board_init(void)
- /* Touchscreen */
- ek_add_device_ts();
- /* MMC */
-- at91_add_device_mmc(1, &ek_mmc_data);
-+ at91_add_device_mci(1, &mci1_data);
- /* Ethernet */
- at91_add_device_eth(&ek_macb_data);
- /* NAND */
-diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
-index da6d019..50dc86d 100644
---- a/arch/arm/mach-at91/board-sam9g20ek.c
-+++ b/arch/arm/mach-at91/board-sam9g20ek.c
-@@ -90,7 +90,7 @@ static struct at91_udc_data __initdata ek_udc_data = {
- * SPI devices.
- */
- static struct spi_board_info ek_spi_devices[] = {
--#if !(defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_AT91))
-+#if !IS_ENABLED(CONFIG_MMC_ATMELMCI)
- { /* DataFlash chip */
- .modalias = "mtd_dataflash",
- .chip_select = 1,
-@@ -197,7 +197,6 @@ static void __init ek_add_device_nand(void)
- * MCI (SD/MMC)
- * wp_pin and vcc_pin are not connected
- */
--#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
- static struct mci_platform_data __initdata ek_mmc_data = {
- .slot[1] = {
- .bus_width = 4,
-@@ -206,28 +205,15 @@ static struct mci_platform_data __initdata ek_mmc_data = {
- },
-
- };
--#else
--static struct at91_mmc_data __initdata ek_mmc_data = {
-- .slot_b = 1, /* Only one slot so use slot B */
-- .wire4 = 1,
-- .det_pin = AT91_PIN_PC9,
-- .wp_pin = -EINVAL,
-- .vcc_pin = -EINVAL,
--};
--#endif
-
- static void __init ek_add_device_mmc(void)
- {
--#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
- if (ek_have_2mmc()) {
- ek_mmc_data.slot[0].bus_width = 4;
- ek_mmc_data.slot[0].detect_pin = AT91_PIN_PC2;
- ek_mmc_data.slot[0].wp_pin = -1;
- }
- at91_add_device_mci(0, &ek_mmc_data);
--#else
-- at91_add_device_mmc(0, &ek_mmc_data);
--#endif
- }
-
- /*
-diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
-index 81d82be..628fec9 100644
---- a/arch/arm/mach-at91/board-sam9rlek.c
-+++ b/arch/arm/mach-at91/board-sam9rlek.c
-@@ -58,11 +58,12 @@ static struct usba_platform_data __initdata ek_usba_udc_data = {
- /*
- * MCI (SD/MMC)
- */
--static struct at91_mmc_data __initdata ek_mmc_data = {
-- .wire4 = 1,
-- .det_pin = AT91_PIN_PA15,
-- .wp_pin = -EINVAL,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = AT91_PIN_PA15,
-+ .wp_pin = -EINVAL,
-+ },
- };
-
-
-@@ -305,7 +306,7 @@ static void __init ek_board_init(void)
- /* SPI */
- at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
- /* MMC */
-- at91_add_device_mmc(0, &ek_mmc_data);
-+ at91_add_device_mci(0, &mci0_data);
- /* LCD Controller */
- at91_add_device_lcdc(&ek_lcdc_data);
- /* AC97 */
-diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
-index 29eae16..c3fb31d 100644
---- a/arch/arm/mach-at91/board-stamp9g20.c
-+++ b/arch/arm/mach-at91/board-stamp9g20.c
-@@ -83,7 +83,6 @@ static void __init add_device_nand(void)
- * MCI (SD/MMC)
- * det_pin, wp_pin and vcc_pin are not connected
- */
--#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
- static struct mci_platform_data __initdata mmc_data = {
- .slot[0] = {
- .bus_width = 4,
-@@ -91,15 +90,6 @@ static struct mci_platform_data __initdata mmc_data = {
- .wp_pin = -1,
- },
- };
--#else
--static struct at91_mmc_data __initdata mmc_data = {
-- .slot_b = 0,
-- .wire4 = 1,
-- .det_pin = -EINVAL,
-- .wp_pin = -EINVAL,
-- .vcc_pin = -EINVAL,
--};
--#endif
-
-
- /*
-@@ -223,11 +213,7 @@ void __init stamp9g20_board_init(void)
- /* NAND */
- add_device_nand();
- /* MMC */
--#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
- at91_add_device_mci(0, &mmc_data);
--#else
-- at91_add_device_mmc(0, &mmc_data);
--#endif
- /* W1 */
- add_w1();
- }
-diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c
-index c1476b9..6ea069b 100644
---- a/arch/arm/mach-at91/board-usb-a926x.c
-+++ b/arch/arm/mach-at91/board-usb-a926x.c
-@@ -109,14 +109,12 @@ static struct mmc_spi_platform_data at91_mmc_spi_pdata = {
- * SPI devices.
- */
- static struct spi_board_info usb_a9263_spi_devices[] = {
--#if !defined(CONFIG_MMC_AT91)
- { /* DataFlash chip */
- .modalias = "mtd_dataflash",
- .chip_select = 0,
- .max_speed_hz = 15 * 1000 * 1000,
- .bus_num = 0,
- }
--#endif
- };
-
- static struct spi_board_info usb_a9g20_spi_devices[] = {
-diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
-index 516d340..2355de2 100644
---- a/arch/arm/mach-at91/board-yl-9200.c
-+++ b/arch/arm/mach-at91/board-yl-9200.c
-@@ -119,11 +119,12 @@ static struct at91_udc_data __initdata yl9200_udc_data = {
- /*
- * MMC
- */
--static struct at91_mmc_data __initdata yl9200_mmc_data = {
-- .det_pin = AT91_PIN_PB9,
-- .wire4 = 1,
-- .wp_pin = -EINVAL,
-- .vcc_pin = -EINVAL,
-+static struct mci_platform_data __initdata yl9200_mci0_data = {
-+ .slot[0] = {
-+ .bus_width = 4,
-+ .detect_pin = AT91_PIN_PB9,
-+ .wp_pin = -EINVAL,
-+ },
- };
-
- /*
-@@ -568,7 +569,7 @@ static void __init yl9200_board_init(void)
- /* I2C */
- at91_add_device_i2c(yl9200_i2c_devices, ARRAY_SIZE(yl9200_i2c_devices));
- /* MMC */
-- at91_add_device_mmc(0, &yl9200_mmc_data);
-+ at91_add_device_mci(0, &yl9200_mci0_data);
- /* NAND */
- at91_add_device_nand(&yl9200_nand_data);
- /* NOR Flash */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 92fd4e4886274f462ffdb6eb350fa2b851e2f263 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 2 Jul 2012 17:15:58 +0200
-Subject: ARM: at91/defconfig: change the MCI driver to use in defconfigs
-
-commit 24f5c4b6e6f2933eb22979283db6174f378d9b36 upstream.
-
-Since atmel-mci driver supports all atmel mci versions,
-use it instead of the deprecated at91_mci driver.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/configs/at91rm9200_defconfig | 2 +-
- arch/arm/configs/at91sam9261_defconfig | 2 +-
- arch/arm/configs/at91sam9263_defconfig | 2 +-
- arch/arm/configs/at91sam9g20_defconfig | 2 +-
- arch/arm/configs/at91sam9rl_defconfig | 2 +-
- arch/arm/configs/cpu9260_defconfig | 2 +-
- arch/arm/configs/cpu9g20_defconfig | 2 +-
- arch/arm/configs/qil-a9260_defconfig | 2 +-
- arch/arm/configs/stamp9g20_defconfig | 1 -
- 9 files changed, 8 insertions(+), 9 deletions(-)
-
-diff --git a/arch/arm/configs/at91rm9200_defconfig b/arch/arm/configs/at91rm9200_defconfig
-index d54e2ac..4ae57a3 100644
---- a/arch/arm/configs/at91rm9200_defconfig
-+++ b/arch/arm/configs/at91rm9200_defconfig
-@@ -232,7 +232,7 @@ CONFIG_USB_GADGET=y
- CONFIG_USB_ETH=m
- CONFIG_USB_MASS_STORAGE=m
- CONFIG_MMC=y
--CONFIG_MMC_AT91=y
-+CONFIG_MMC_ATMELMCI=y
- CONFIG_NEW_LEDS=y
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_GPIO=y
-diff --git a/arch/arm/configs/at91sam9261_defconfig b/arch/arm/configs/at91sam9261_defconfig
-index ade6b2f..1e8712e 100644
---- a/arch/arm/configs/at91sam9261_defconfig
-+++ b/arch/arm/configs/at91sam9261_defconfig
-@@ -128,7 +128,7 @@ CONFIG_USB_GADGETFS=m
- CONFIG_USB_FILE_STORAGE=m
- CONFIG_USB_G_SERIAL=m
- CONFIG_MMC=y
--CONFIG_MMC_AT91=m
-+CONFIG_MMC_ATMELMCI=m
- CONFIG_NEW_LEDS=y
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_GPIO=y
-diff --git a/arch/arm/configs/at91sam9263_defconfig b/arch/arm/configs/at91sam9263_defconfig
-index 585e7e0..d2050ca 100644
---- a/arch/arm/configs/at91sam9263_defconfig
-+++ b/arch/arm/configs/at91sam9263_defconfig
-@@ -137,7 +137,7 @@ CONFIG_USB_FILE_STORAGE=m
- CONFIG_USB_G_SERIAL=m
- CONFIG_MMC=y
- CONFIG_SDIO_UART=m
--CONFIG_MMC_AT91=m
-+CONFIG_MMC_ATMELMCI=m
- CONFIG_NEW_LEDS=y
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_ATMEL_PWM=y
-diff --git a/arch/arm/configs/at91sam9g20_defconfig b/arch/arm/configs/at91sam9g20_defconfig
-index 994d331..e1b0e80 100644
---- a/arch/arm/configs/at91sam9g20_defconfig
-+++ b/arch/arm/configs/at91sam9g20_defconfig
-@@ -99,7 +99,7 @@ CONFIG_USB_GADGETFS=m
- CONFIG_USB_FILE_STORAGE=m
- CONFIG_USB_G_SERIAL=m
- CONFIG_MMC=y
--CONFIG_MMC_AT91=m
-+CONFIG_MMC_ATMELMCI=m
- CONFIG_NEW_LEDS=y
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_GPIO=y
-diff --git a/arch/arm/configs/at91sam9rl_defconfig b/arch/arm/configs/at91sam9rl_defconfig
-index ad562ee..7cf8785 100644
---- a/arch/arm/configs/at91sam9rl_defconfig
-+++ b/arch/arm/configs/at91sam9rl_defconfig
-@@ -60,7 +60,7 @@ CONFIG_AT91SAM9X_WATCHDOG=y
- CONFIG_FB=y
- CONFIG_FB_ATMEL=y
- CONFIG_MMC=y
--CONFIG_MMC_AT91=m
-+CONFIG_MMC_ATMELMCI=m
- CONFIG_RTC_CLASS=y
- CONFIG_RTC_DRV_AT91SAM9=y
- CONFIG_EXT2_FS=y
-diff --git a/arch/arm/configs/cpu9260_defconfig b/arch/arm/configs/cpu9260_defconfig
-index bbf729e..921480c 100644
---- a/arch/arm/configs/cpu9260_defconfig
-+++ b/arch/arm/configs/cpu9260_defconfig
-@@ -82,7 +82,7 @@ CONFIG_USB_STORAGE=y
- CONFIG_USB_GADGET=y
- CONFIG_USB_ETH=m
- CONFIG_MMC=y
--CONFIG_MMC_AT91=m
-+CONFIG_MMC_ATMELMCI=m
- CONFIG_NEW_LEDS=y
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_GPIO=y
-diff --git a/arch/arm/configs/cpu9g20_defconfig b/arch/arm/configs/cpu9g20_defconfig
-index e7d7942..ea116cb 100644
---- a/arch/arm/configs/cpu9g20_defconfig
-+++ b/arch/arm/configs/cpu9g20_defconfig
-@@ -82,7 +82,7 @@ CONFIG_USB_STORAGE=y
- CONFIG_USB_GADGET=y
- CONFIG_USB_ETH=m
- CONFIG_MMC=y
--CONFIG_MMC_AT91=m
-+CONFIG_MMC_ATMELMCI=m
- CONFIG_NEW_LEDS=y
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_GPIO=y
-diff --git a/arch/arm/configs/qil-a9260_defconfig b/arch/arm/configs/qil-a9260_defconfig
-index 2bb100b..42d5db1 100644
---- a/arch/arm/configs/qil-a9260_defconfig
-+++ b/arch/arm/configs/qil-a9260_defconfig
-@@ -86,7 +86,7 @@ CONFIG_USB_STORAGE=y
- CONFIG_USB_GADGET=y
- CONFIG_USB_ETH=m
- CONFIG_MMC=y
--CONFIG_MMC_AT91=m
-+CONFIG_MMC_ATMELMCI=m
- CONFIG_NEW_LEDS=y
- CONFIG_LEDS_CLASS=y
- CONFIG_LEDS_GPIO=y
-diff --git a/arch/arm/configs/stamp9g20_defconfig b/arch/arm/configs/stamp9g20_defconfig
-index d5e260b..52f1488 100644
---- a/arch/arm/configs/stamp9g20_defconfig
-+++ b/arch/arm/configs/stamp9g20_defconfig
-@@ -100,7 +100,6 @@ CONFIG_USB_ETH=m
- CONFIG_USB_FILE_STORAGE=m
- CONFIG_USB_G_SERIAL=m
- CONFIG_MMC=y
--# CONFIG_MMC_AT91 is not set
- CONFIG_MMC_ATMELMCI=y
- CONFIG_NEW_LEDS=y
- CONFIG_LEDS_CLASS=y
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 66bca56097bd85e2969d9ef7df5e53b0dc51a258 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 24 Apr 2012 16:46:26 +0200
-Subject: mmc: atmel-mci: fix burst/chunk size modification
-
-commit 693e5e2025278d90e1427f037e5ec8ea1ec7d5c4 upstream.
-
-The use of DMA slave config operation requires that the burst size
-(aka chunk size) is specified through this interface.
-Modify atmel-mci slave driver to use this specification on its side.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/mmc/host/atmel-mci-regs.h | 14 ++++++++++++++
- drivers/mmc/host/atmel-mci.c | 8 +++++---
- 2 files changed, 19 insertions(+), 3 deletions(-)
-
---- a/drivers/mmc/host/atmel-mci-regs.h
-+++ b/drivers/mmc/host/atmel-mci-regs.h
-@@ -140,4 +140,18 @@
- #define atmci_writel(port,reg,value) \
- __raw_writel((value), (port)->regs + reg)
-
-+/*
-+ * Fix sconfig's burst size according to atmel MCI. We need to convert them as:
-+ * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3.
-+ *
-+ * This can be done by finding most significant bit set.
-+ */
-+static inline unsigned int atmci_convert_chksize(unsigned int maxburst)
-+{
-+ if (maxburst > 1)
-+ return fls(maxburst) - 2;
-+ else
-+ return 0;
-+}
-+
- #endif /* __DRIVERS_MMC_ATMEL_MCI_H__ */
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -912,6 +912,7 @@ atmci_prepare_data_dma(struct atmel_mci
- enum dma_data_direction direction;
- enum dma_transfer_direction slave_dirn;
- unsigned int sglen;
-+ u32 maxburst;
- u32 iflags;
-
- data->error = -EINPROGRESS;
-@@ -945,17 +946,18 @@ atmci_prepare_data_dma(struct atmel_mci
- if (!chan)
- return -ENODEV;
-
-- if (host->caps.has_dma)
-- atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(3) | ATMCI_DMAEN);
--
- if (data->flags & MMC_DATA_READ) {
- direction = DMA_FROM_DEVICE;
- host->dma_conf.direction = slave_dirn = DMA_DEV_TO_MEM;
-+ maxburst = atmci_convert_chksize(host->dma_conf.src_maxburst);
- } else {
- direction = DMA_TO_DEVICE;
- host->dma_conf.direction = slave_dirn = DMA_MEM_TO_DEV;
-+ maxburst = atmci_convert_chksize(host->dma_conf.dst_maxburst);
- }
-
-+ atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(maxburst) | ATMCI_DMAEN);
-+
- sglen = dma_map_sg(chan->device->dev, data->sg,
- data->sg_len, direction);
-
+++ /dev/null
-From d7950b4e5a002a389587c0c85ef326a61ef1ef3d Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Tue, 20 Mar 2012 18:41:48 +0100
-Subject: mmc: atmel-mci: add device tree support
-
-commit e919fd200033e80b26f152d22c00a8fae7f8d548 upstream.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- Documentation/devicetree/bindings/mmc/atmel-hsmci.txt | 67 ++++++++++++++
- drivers/mmc/host/atmel-mci.c | 85 +++++++++++++++++-
- 2 files changed, 150 insertions(+), 2 deletions(-)
- create mode 100644 Documentation/devicetree/bindings/mmc/atmel-hsmci.txt
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt
-@@ -0,0 +1,67 @@
-+* Atmel High Speed MultiMedia Card Interface
-+
-+This controller on atmel products provides an interface for MMC, SD and SDIO
-+types of memory cards.
-+
-+1) MCI node
-+
-+Required properties:
-+- compatible: no blank "atmel,hsmci"
-+- reg: should contain HSMCI registers location and length
-+- interrupts: should contain HSMCI interrupt number
-+- #address-cells: should be one. The cell is the slot id.
-+- #size-cells: should be zero.
-+- at least one slot node
-+
-+The node contains child nodes for each slot that the platform uses
-+
-+Example MCI node:
-+
-+mmc0: mmc@f0008000 {
-+ compatible = "atmel,hsmci";
-+ reg = <0xf0008000 0x600>;
-+ interrupts = <12 4>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ [ child node definitions...]
-+};
-+
-+2) slot nodes
-+
-+Required properties:
-+- reg: should contain the slot id.
-+- bus-width: number of data lines connected to the controller
-+
-+Optional properties:
-+- cd-gpios: specify GPIOs for card detection
-+- cd-inverted: invert the value of external card detect gpio line
-+- wp-gpios: specify GPIOs for write protection
-+
-+Example slot node:
-+
-+slot@0 {
-+ reg = <0>;
-+ bus-width = <4>;
-+ cd-gpios = <&pioD 15 0>
-+ cd-inverted;
-+};
-+
-+Example full MCI node:
-+mmc0: mmc@f0008000 {
-+ compatible = "atmel,hsmci";
-+ reg = <0xf0008000 0x600>;
-+ interrupts = <12 4>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ slot@0 {
-+ reg = <0>;
-+ bus-width = <4>;
-+ cd-gpios = <&pioD 15 0>
-+ cd-inverted;
-+ };
-+ slot@1 {
-+ reg = <1>;
-+ bus-width = <4>;
-+ };
-+};
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -19,6 +19,9 @@
- #include <linux/interrupt.h>
- #include <linux/ioport.h>
- #include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/of_gpio.h>
- #include <linux/platform_device.h>
- #include <linux/scatterlist.h>
- #include <linux/seq_file.h>
-@@ -494,6 +497,70 @@ err:
- dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n");
- }
-
-+#if defined(CONFIG_OF)
-+static const struct of_device_id atmci_dt_ids[] = {
-+ { .compatible = "atmel,hsmci" },
-+ { /* sentinel */ }
-+};
-+
-+MODULE_DEVICE_TABLE(of, atmci_dt_ids);
-+
-+static struct mci_platform_data __devinit*
-+atmci_of_init(struct platform_device *pdev)
-+{
-+ struct device_node *np = pdev->dev.of_node;
-+ struct device_node *cnp;
-+ struct mci_platform_data *pdata;
-+ u32 slot_id;
-+
-+ if (!np) {
-+ dev_err(&pdev->dev, "device node not found\n");
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-+ if (!pdata) {
-+ dev_err(&pdev->dev, "could not allocate memory for pdata\n");
-+ return ERR_PTR(-ENOMEM);
-+ }
-+
-+ for_each_child_of_node(np, cnp) {
-+ if (of_property_read_u32(cnp, "reg", &slot_id)) {
-+ dev_warn(&pdev->dev, "reg property is missing for %s\n",
-+ cnp->full_name);
-+ continue;
-+ }
-+
-+ if (slot_id >= ATMCI_MAX_NR_SLOTS) {
-+ dev_warn(&pdev->dev, "can't have more than %d slots\n",
-+ ATMCI_MAX_NR_SLOTS);
-+ break;
-+ }
-+
-+ if (of_property_read_u32(cnp, "bus-width",
-+ &pdata->slot[slot_id].bus_width))
-+ pdata->slot[slot_id].bus_width = 1;
-+
-+ pdata->slot[slot_id].detect_pin =
-+ of_get_named_gpio(cnp, "cd-gpios", 0);
-+
-+ pdata->slot[slot_id].detect_is_active_high =
-+ of_property_read_bool(cnp, "cd-inverted");
-+
-+ pdata->slot[slot_id].wp_pin =
-+ of_get_named_gpio(cnp, "wp-gpios", 0);
-+ }
-+
-+ return pdata;
-+}
-+#else /* CONFIG_OF */
-+static inline struct mci_platform_data*
-+atmci_of_init(struct platform_device *dev)
-+{
-+ return ERR_PTR(-EINVAL);
-+}
-+#endif
-+
- static inline unsigned int atmci_get_version(struct atmel_mci *host)
- {
- return atmci_readl(host, ATMCI_VERSION) & 0x00000fff;
-@@ -2044,6 +2111,13 @@ static int __init atmci_init_slot(struct
- slot->sdc_reg = sdc_reg;
- slot->sdio_irq = sdio_irq;
-
-+ dev_dbg(&mmc->class_dev,
-+ "slot[%u]: bus_width=%u, detect_pin=%d, "
-+ "detect_is_active_high=%s, wp_pin=%d\n",
-+ id, slot_data->bus_width, slot_data->detect_pin,
-+ slot_data->detect_is_active_high ? "true" : "false",
-+ slot_data->wp_pin);
-+
- mmc->ops = &atmci_ops;
- mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512);
- mmc->f_max = host->bus_hz / 2;
-@@ -2264,8 +2338,14 @@ static int __init atmci_probe(struct pla
- if (!regs)
- return -ENXIO;
- pdata = pdev->dev.platform_data;
-- if (!pdata)
-- return -ENXIO;
-+ if (!pdata) {
-+ pdata = atmci_of_init(pdev);
-+ if (IS_ERR(pdata)) {
-+ dev_err(&pdev->dev, "platform data not available\n");
-+ return PTR_ERR(pdata);
-+ }
-+ }
-+
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return irq;
-@@ -2481,6 +2561,7 @@ static struct platform_driver atmci_driv
- .driver = {
- .name = "atmel_mci",
- .pm = ATMCI_PM_OPS,
-+ .of_match_table = of_match_ptr(atmci_dt_ids),
- },
- };
-
+++ /dev/null
-From 51bec071d4a9c3202e5d03821f12659a46866ad6 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Tue, 22 May 2012 11:38:26 +0200
-Subject: ARM: at91: add clocks for DT entries
-
-Add clocks to clock lookup table for DT entries.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/mach-at91/at91sam9260.c | 1 +
- arch/arm/mach-at91/at91sam9263.c | 2 ++
- arch/arm/mach-at91/at91sam9g45.c | 2 ++
- arch/arm/mach-at91/at91sam9n12.c | 1 +
- arch/arm/mach-at91/at91sam9x5.c | 2 ++
- 5 files changed, 8 insertions(+)
-
-diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
-index c644131..4696729 100644
---- a/arch/arm/mach-at91/at91sam9260.c
-+++ b/arch/arm/mach-at91/at91sam9260.c
-@@ -219,6 +219,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("t1_clk", "fffdc000.timer", &tc4_clk),
- CLKDEV_CON_DEV_ID("t2_clk", "fffdc000.timer", &tc5_clk),
- CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &ohci_clk),
-+ CLKDEV_CON_DEV_ID("mci_clk", "fffa8000.mmc", &mmc_clk),
- /* fake hclk clock */
- CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
- CLKDEV_CON_ID("pioA", &pioA_clk),
-diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
-index 144ef5d..c82d521 100644
---- a/arch/arm/mach-at91/at91sam9263.c
-+++ b/arch/arm/mach-at91/at91sam9263.c
-@@ -210,6 +210,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("hclk", "a00000.ohci", &ohci_clk),
- CLKDEV_CON_DEV_ID("spi_clk", "fffa4000.spi", &spi0_clk),
- CLKDEV_CON_DEV_ID("spi_clk", "fffa8000.spi", &spi1_clk),
-+ CLKDEV_CON_DEV_ID("mci_clk", "fff80000.mmc", &mmc0_clk),
-+ CLKDEV_CON_DEV_ID("mci_clk", "fff84000.mmc", &mmc1_clk),
- };
-
- static struct clk_lookup usart_clocks_lookups[] = {
-diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
-index 55d2959..f6d0eab 100644
---- a/arch/arm/mach-at91/at91sam9g45.c
-+++ b/arch/arm/mach-at91/at91sam9g45.c
-@@ -236,6 +236,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("t0_clk", "fffd4000.timer", &tcb0_clk),
- CLKDEV_CON_DEV_ID("hclk", "700000.ohci", &uhphs_clk),
- CLKDEV_CON_DEV_ID("ehci_clk", "800000.ehci", &uhphs_clk),
-+ CLKDEV_CON_DEV_ID("mci_clk", "fff80000.mmc", &mmc0_clk),
-+ CLKDEV_CON_DEV_ID("mci_clk", "fffd0000.mmc", &mmc1_clk),
- /* fake hclk clock */
- CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
- CLKDEV_CON_ID("pioA", &pioA_clk),
-diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c
-index 0849466..cce4e0f 100644
---- a/arch/arm/mach-at91/at91sam9n12.c
-+++ b/arch/arm/mach-at91/at91sam9n12.c
-@@ -168,6 +168,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
- CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb_clk),
- CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb_clk),
-+ CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc_clk),
- CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma_clk),
- CLKDEV_CON_ID("pioA", &pioAB_clk),
- CLKDEV_CON_ID("pioB", &pioAB_clk),
-diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
-index 7eb00c53..796b3c0 100644
---- a/arch/arm/mach-at91/at91sam9x5.c
-+++ b/arch/arm/mach-at91/at91sam9x5.c
-@@ -225,6 +225,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
- CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma0_clk),
- CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk),
-+ CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc0_clk),
-+ CLKDEV_CON_DEV_ID("mci_clk", "f000c000.mmc", &mmc1_clk),
- CLKDEV_CON_ID("pioA", &pioAB_clk),
- CLKDEV_CON_ID("pioB", &pioAB_clk),
- CLKDEV_CON_ID("pioC", &pioCD_clk),
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From f71ff4055fb6e030293b84faa33e61123cc7b3a2 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Thu, 24 May 2012 16:58:42 +0200
-Subject: ARM: dts: add nodes for atmel hsmci controllers for atmel SOCs
-
-Add mci controller nodes to atmel SOCs.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-
-Conflicts:
-
- arch/arm/boot/dts/at91sam9260.dtsi
- arch/arm/boot/dts/at91sam9g45.dtsi
- arch/arm/boot/dts/at91sam9x5.dtsi
----
- arch/arm/boot/dts/at91sam9260.dtsi | 9 +++++++++
- arch/arm/boot/dts/at91sam9263.dtsi | 18 ++++++++++++++++++
- arch/arm/boot/dts/at91sam9g45.dtsi | 18 ++++++++++++++++++
- arch/arm/boot/dts/at91sam9n12.dtsi | 9 +++++++++
- arch/arm/boot/dts/at91sam9x5.dtsi | 18 ++++++++++++++++++
- 5 files changed, 72 insertions(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
-index 12df8ca..1f2c7d0 100644
---- a/arch/arm/boot/dts/at91sam9260.dtsi
-+++ b/arch/arm/boot/dts/at91sam9260.dtsi
-@@ -201,6 +201,15 @@
- interrupts = <10 4 2>;
- status = "disabled";
- };
-+
-+ mmc0: mmc@fffa8000 {
-+ compatible = "atmel,hsmci";
-+ reg = <0xfffa800 0x600>;
-+ interrupts = <9 4>;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
- };
-
- nand0: nand@40000000 {
-diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
-index 195019b..a76f6cd 100644
---- a/arch/arm/boot/dts/at91sam9263.dtsi
-+++ b/arch/arm/boot/dts/at91sam9263.dtsi
-@@ -185,6 +185,24 @@
- interrupts = <24 4 2>;
- status = "disabled";
- };
-+
-+ mmc0: mmc@fff80000 {
-+ compatible = "atmel,hsmci";
-+ reg = <0xfff80000 0x600>;
-+ interrupts = <10 4>;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ mmc1: mmc@fff84000 {
-+ compatible = "atmel,hsmci";
-+ reg = <0xfff84000 0x600>;
-+ interrupts = <11 4>;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
- };
-
- nand0: nand@40000000 {
-diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
-index 6a3ed54..4b833d4 100644
---- a/arch/arm/boot/dts/at91sam9g45.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
-@@ -205,6 +205,24 @@
- interrupts = <25 4 3>;
- status = "disabled";
- };
-+
-+ mmc0: mmc@fff80000 {
-+ compatible = "atmel,hsmci";
-+ reg = <0xfff80000 0x600>;
-+ interrupts = <11 4>;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ mmc1: mmc@fffd0000 {
-+ compatible = "atmel,hsmci";
-+ reg = <0xfffd0000 0x600>;
-+ interrupts = <29 4>;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
- };
-
- nand0: nand@40000000 {
-diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
-index ef9336a..aead257 100644
---- a/arch/arm/boot/dts/at91sam9n12.dtsi
-+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
-@@ -82,6 +82,15 @@
- reg = <0xfffffe10 0x10>;
- };
-
-+ mmc0: mmc@f0008000 {
-+ compatible = "atmel,hsmci";
-+ reg = <0xf0008000 0x600>;
-+ interrupts = <12 4>;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
- tcb0: timer@f8008000 {
- compatible = "atmel,at91sam9x5-tcb";
- reg = <0xf8008000 0x100>;
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index fc38d21..1be3df7 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -195,6 +195,24 @@
- interrupts = <27 4 3>;
- status = "disabled";
- };
-+
-+ mmc0: mmc@f0008000 {
-+ compatible = "atmel,hsmci";
-+ reg = <0xf0008000 0x600>;
-+ interrupts = <12 4>;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ mmc1: mmc@f000c000 {
-+ compatible = "atmel,hsmci";
-+ reg = <0xf000c000 0x600>;
-+ interrupts = <26 4>;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
- };
-
- nand0: nand@40000000 {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ca13863c856e2bf24c72539444a06237ce6834fb Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Thu, 24 May 2012 17:01:19 +0200
-Subject: ARM: dts: add nodes for atmel hsmci controllers for atmel boards
-
-Add mci controller nodes to atmel boards.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- arch/arm/boot/dts/at91sam9263ek.dts | 10 ++++++++++
- arch/arm/boot/dts/at91sam9g20ek_2mmc.dts | 12 ++++++++++++
- arch/arm/boot/dts/at91sam9g20ek_common.dtsi | 9 +++++++++
- arch/arm/boot/dts/at91sam9g25ek.dts | 18 ++++++++++++++++++
- arch/arm/boot/dts/at91sam9m10g45ek.dts | 19 +++++++++++++++++++
- arch/arm/boot/dts/at91sam9n12ek.dts | 9 +++++++++
- 6 files changed, 77 insertions(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9263ek.dts b/arch/arm/boot/dts/at91sam9263ek.dts
-index f86ac4b..05028ed 100644
---- a/arch/arm/boot/dts/at91sam9263ek.dts
-+++ b/arch/arm/boot/dts/at91sam9263ek.dts
-@@ -50,6 +50,16 @@
- atmel,vbus-gpio = <&pioA 25 0>;
- status = "okay";
- };
-+
-+ mmc0: mmc@fff80000 {
-+ status = "okay";
-+ slot@0 {
-+ reg = <0>;
-+ bus-width = <4>;
-+ cd-gpios = <&pioE 18 0>;
-+ wp-gpios = <&pioE 19 0>;
-+ };
-+ };
- };
-
- nand0: nand@40000000 {
-diff --git a/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts b/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts
-index f1b2e14..684b229 100644
---- a/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts
-+++ b/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts
-@@ -12,6 +12,18 @@
- model = "Atmel at91sam9g20ek 2 mmc";
- compatible = "atmel,at91sam9g20ek_2mmc", "atmel,at91sam9g20", "atmel,at91sam9";
-
-+ ahb {
-+ apb{
-+ mmc0: mmc@fffa8000 {
-+ slot@0 {
-+ reg = <0>;
-+ bus-width = <4>;
-+ cd-gpios = <&pioC 2 0>;
-+ };
-+ };
-+ };
-+ };
-+
- leds {
- compatible = "gpio-leds";
-
-diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
-index b06c0db..7da326a 100644
---- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
-@@ -51,6 +51,15 @@
- atmel,vbus-gpio = <&pioC 5 0>;
- status = "okay";
- };
-+
-+ mmc0: mmc@fffa8000 {
-+ status = "okay";
-+ slot@1 {
-+ reg = <1>;
-+ bus-width = <4>;
-+ cd-gpios = <&pioC 9 0>;
-+ };
-+ };
- };
-
- nand0: nand@40000000 {
-diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts
-index 96514c1..4857e6c 100644
---- a/arch/arm/boot/dts/at91sam9g25ek.dts
-+++ b/arch/arm/boot/dts/at91sam9g25ek.dts
-@@ -32,6 +32,24 @@
- phy-mode = "rmii";
- status = "okay";
- };
-+
-+ mmc0: mmc@f0008000 {
-+ status = "okay";
-+ slot@0 {
-+ reg = <0>;
-+ bus-width = <4>;
-+ cd-gpios = <&pioD 15 0>;
-+ };
-+ };
-+
-+ mmc1: mmc@f000c000 {
-+ status = "okay";
-+ slot@0 {
-+ reg = <0>;
-+ bus-width = <4>;
-+ cd-gpios = <&pioD 14 0>;
-+ };
-+ };
- };
-
- usb0: ohci@00600000 {
-diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts
-index a3633bd..7a7b571 100644
---- a/arch/arm/boot/dts/at91sam9m10g45ek.dts
-+++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts
-@@ -46,6 +46,25 @@
- phy-mode = "rmii";
- status = "okay";
- };
-+
-+ mmc0: mmc@fff80000 {
-+ status = "okay";
-+ slot@0 {
-+ reg = <0>;
-+ bus-width = <4>;
-+ cd-gpios = <&pioD 10 0>;
-+ };
-+ };
-+
-+ mmc1: mmc@fffd0000 {
-+ status = "okay";
-+ slot@0 {
-+ reg = <0>;
-+ bus-width = <4>;
-+ cd-gpios = <&pioD 11 0>;
-+ wp-gpios = <&pioD 29 0>;
-+ };
-+ };
- };
-
- nand0: nand@40000000 {
-diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts
-index f4e43e3..44b42d9 100644
---- a/arch/arm/boot/dts/at91sam9n12ek.dts
-+++ b/arch/arm/boot/dts/at91sam9n12ek.dts
-@@ -37,6 +37,15 @@
- dbgu: serial@fffff200 {
- status = "okay";
- };
-+
-+ mmc0: mmc@f0008000 {
-+ status = "okay";
-+ slot@0 {
-+ reg = <0>;
-+ bus-width = <4>;
-+ cd-gpios = <&pioA 7 0>;
-+ };
-+ };
- };
-
- nand0: nand@40000000 {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 7cc485eab96c78d9e36f62040cc1c5ba927a5eed Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Thu, 7 Jun 2012 10:54:33 +0200
-Subject: mmc: atmel-mci: remove not needed DMA capability test
-
-The test about DMA capability is not needed as it is
-performed in DMA-only functions: so remove it.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/mmc/host/atmel-mci.c | 5 ++---
- 1 file changed, 2 insertions(+), 3 deletions(-)
-
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -835,9 +835,8 @@ static void atmci_dma_complete(void *arg
-
- dev_vdbg(&host->pdev->dev, "DMA complete\n");
-
-- if (host->caps.has_dma)
-- /* Disable DMA hardware handshaking on MCI */
-- atmci_writel(host, ATMCI_DMA, atmci_readl(host, ATMCI_DMA) & ~ATMCI_DMAEN);
-+ /* Disable DMA hardware handshaking on MCI */
-+ atmci_writel(host, ATMCI_DMA, atmci_readl(host, ATMCI_DMA) & ~ATMCI_DMAEN);
-
- atmci_dma_cleanup(host);
-
+++ /dev/null
-From 78f6c26cc14ac43da5dbfd46726ce7b8df9b0702 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Wed, 14 Mar 2012 12:46:18 +0100
-Subject: ARM: at91/atmel-mci: remove unused setup_dma_addr() macro
-
-This macro is not used anymove in atmel-mci driver. It has been removed
-by a patch that was dealing with dw_dmac.c e2b35f3:
-(dmaengine/dw_dmac: Fix dw_dmac user drivers to adapt to slave_config changes)
-
-We are now using the dmaengine API to specify the slave DMA parameters:
-dmaengine_slave_config().
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Cc: Chris Ball <cjb@laptop.org>
-Cc: <linux-mmc@vger.kernel.org>
----
- arch/arm/mach-at91/include/mach/atmel-mci.h | 7 -------
- 1 file changed, 7 deletions(-)
-
-diff --git a/arch/arm/mach-at91/include/mach/atmel-mci.h b/arch/arm/mach-at91/include/mach/atmel-mci.h
-index 998cb0c..5d84fe3 100644
---- a/arch/arm/mach-at91/include/mach/atmel-mci.h
-+++ b/arch/arm/mach-at91/include/mach/atmel-mci.h
-@@ -14,11 +14,4 @@ struct mci_dma_data {
- #define slave_data_ptr(s) (&(s)->sdata)
- #define find_slave_dev(s) ((s)->sdata.dma_dev)
-
--#define setup_dma_addr(s, t, r) do { \
-- if (s) { \
-- (s)->sdata.tx_reg = (t); \
-- (s)->sdata.rx_reg = (r); \
-- } \
--} while (0)
--
- #endif /* __MACH_ATMEL_MCI_H */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 6dd4494f6c46cf3aeba389b557a5315b6453b727 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Fri, 22 Jun 2012 16:41:08 +0200
-Subject: ARM: dts: fix add mmc irq priority
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- arch/arm/boot/dts/at91sam9260.dtsi | 2 +-
- arch/arm/boot/dts/at91sam9263.dtsi | 4 ++--
- arch/arm/boot/dts/at91sam9g45.dtsi | 4 ++--
- arch/arm/boot/dts/at91sam9n12.dtsi | 2 +-
- arch/arm/boot/dts/at91sam9x5.dtsi | 4 ++--
- 5 files changed, 8 insertions(+), 8 deletions(-)
-
---- a/arch/arm/boot/dts/at91sam9260.dtsi
-+++ b/arch/arm/boot/dts/at91sam9260.dtsi
-@@ -205,7 +205,7 @@
- mmc0: mmc@fffa8000 {
- compatible = "atmel,hsmci";
- reg = <0xfffa800 0x600>;
-- interrupts = <9 4>;
-+ interrupts = <9 4 0>;
- status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
---- a/arch/arm/boot/dts/at91sam9263.dtsi
-+++ b/arch/arm/boot/dts/at91sam9263.dtsi
-@@ -189,7 +189,7 @@
- mmc0: mmc@fff80000 {
- compatible = "atmel,hsmci";
- reg = <0xfff80000 0x600>;
-- interrupts = <10 4>;
-+ interrupts = <10 4 0>;
- status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
-@@ -198,7 +198,7 @@
- mmc1: mmc@fff84000 {
- compatible = "atmel,hsmci";
- reg = <0xfff84000 0x600>;
-- interrupts = <11 4>;
-+ interrupts = <11 4 0>;
- status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
---- a/arch/arm/boot/dts/at91sam9g45.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
-@@ -209,7 +209,7 @@
- mmc0: mmc@fff80000 {
- compatible = "atmel,hsmci";
- reg = <0xfff80000 0x600>;
-- interrupts = <11 4>;
-+ interrupts = <11 4 0>;
- status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
-@@ -218,7 +218,7 @@
- mmc1: mmc@fffd0000 {
- compatible = "atmel,hsmci";
- reg = <0xfffd0000 0x600>;
-- interrupts = <29 4>;
-+ interrupts = <29 4 0>;
- status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
---- a/arch/arm/boot/dts/at91sam9n12.dtsi
-+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
-@@ -85,7 +85,7 @@
- mmc0: mmc@f0008000 {
- compatible = "atmel,hsmci";
- reg = <0xf0008000 0x600>;
-- interrupts = <12 4>;
-+ interrupts = <12 4 0>;
- status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -199,7 +199,7 @@
- mmc0: mmc@f0008000 {
- compatible = "atmel,hsmci";
- reg = <0xf0008000 0x600>;
-- interrupts = <12 4>;
-+ interrupts = <12 4 0>;
- status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
-@@ -208,7 +208,7 @@
- mmc1: mmc@f000c000 {
- compatible = "atmel,hsmci";
- reg = <0xf000c000 0x600>;
-- interrupts = <26 4>;
-+ interrupts = <26 4 0>;
- status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
+++ /dev/null
-From 6eecb222c79306c6fad8e4934ba9dfbbac033067 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 6 Sep 2011 17:49:35 +0200
-Subject: mmc: atmel-mci: support 8-bit buswidth
-
-This patch adds support for 8-bit buswidth.
-Relevant SDCR value modified.
-
-Derived from a patch by Jaehoon Chung on dw_mmc.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/mmc/host/atmel-mci.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -1263,6 +1263,9 @@ static void atmci_set_ios(struct mmc_hos
- case MMC_BUS_WIDTH_4:
- slot->sdc_reg |= ATMCI_SDCBUS_4BIT;
- break;
-+ case MMC_BUS_WIDTH_8:
-+ slot->sdc_reg |= ATMCI_SDCBUS_8BIT;
-+ break;
- }
-
- if (ios->clock) {
+++ /dev/null
-From 6200f62344e4ab0492623a51fabdac4e57ba6e89 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Fri, 6 Jul 2012 11:49:05 +0200
-Subject: mmc: atmel-mci: fix incorrect setting of host->data to NULL
-
-commit 41b4e9a194f69b1c945038c559ea407a6b383e81 upstream.
-
-Setting host->data to NULL is incorrect sequence in STATE_SENDING_STOP
-state of FSM: This early setting leads to the skip of dma_unmap_sg()
-in atmci_dma_cleanup() which is a bug.
-
-Idea taken form dw_mmc by Seungwon Jeon.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Cc: Seungwon Jeon <tgih.jun@samsung.com>
----
- drivers/mmc/host/atmel-mci.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -1756,7 +1756,6 @@ static void atmci_tasklet_func(unsigned
-
- dev_dbg(&host->pdev->dev, "FSM: cmd ready\n");
- host->cmd = NULL;
-- host->data = NULL;
- data->bytes_xfered = data->blocks * data->blksz;
- data->error = 0;
- atmci_command_complete(host, mrq->stop);
-@@ -1770,6 +1769,7 @@ static void atmci_tasklet_func(unsigned
- atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
- state = STATE_WAITING_NOTBUSY;
- }
-+ host->data = NULL;
- break;
-
- case STATE_END_REQUEST:
+++ /dev/null
-From a57a7a65247a77826cd2f021fadd536d46bb7d36 Mon Sep 17 00:00:00 2001
-From: Subhash Jadavani <subhashj@codeaurora.org>
-Date: Wed, 13 Jun 2012 17:10:43 +0530
-Subject: mmc: block: fix the data timeout issue with ACMD22
-
-commit d380443cd0271903bf9516bc04cead81676be034 upstream.
-
-If multi block write operation fails for SD card, during
-error handling we send the SD_APP_SEND_NUM_WR_BLKS (ACMD22)
-to know how many blocks were already programmed by card.
-
-But mmc_sd_num_wr_blocks() function which sends the ACMD22
-calculates the data timeout value from csd.tacc_ns and
-csd.tacc_clks parameters which will be 0 for block addressed
-(>2GB cards) SD card. This would result in timeout_ns and
-timeout_clks being 0 in the mmc_request passed to host driver.
-This means host controller would program its data timeout timer
-value with 0 which could result in DATA TIMEOUT errors from
-controller.
-
-To fix this issue, mmc_sd_num_wr_blocks() should instead
-just call the mmc_set_data_timeout() to calculate the
-data timeout value. mmc_set_data_timeout() function
-ensures that non zero timeout value is set even for
-block addressed SD cards.
-
-Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
-Reviewed-by: Venkatraman S <svenkatr@ti.com>
-Signed-off-by: Chris Ball <cjb@laptop.org>
----
- drivers/mmc/card/block.c | 14 +-------------
- 1 file changed, 1 insertion(+), 13 deletions(-)
-
-diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
-index dabec55..d8f802e 100644
---- a/drivers/mmc/card/block.c
-+++ b/drivers/mmc/card/block.c
-@@ -553,7 +553,6 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
- struct mmc_request mrq = {NULL};
- struct mmc_command cmd = {0};
- struct mmc_data data = {0};
-- unsigned int timeout_us;
-
- struct scatterlist sg;
-
-@@ -573,23 +572,12 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
- cmd.arg = 0;
- cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
-
-- data.timeout_ns = card->csd.tacc_ns * 100;
-- data.timeout_clks = card->csd.tacc_clks * 100;
--
-- timeout_us = data.timeout_ns / 1000;
-- timeout_us += data.timeout_clks * 1000 /
-- (card->host->ios.clock / 1000);
--
-- if (timeout_us > 100000) {
-- data.timeout_ns = 100000000;
-- data.timeout_clks = 0;
-- }
--
- data.blksz = 4;
- data.blocks = 1;
- data.flags = MMC_DATA_READ;
- data.sg = &sg;
- data.sg_len = 1;
-+ mmc_set_data_timeout(&data, card);
-
- mrq.cmd = &cmd;
- mrq.data = &data;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 8f6fe6c730556e621c6e404c945a330ed4107ad3 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Fri, 6 Jul 2012 12:11:51 +0200
-Subject: mmc: atmel-mci: modify CLKDIV displaying in debugfs
-
-commit 8a4de07e05e7bedc894c2de3b3b04673d6d840ec upstream.
-
-Modify clock division displaying in debugfs for matching
-the new CLKDIV,CLKODD user interface arrangement.
-Is using the has_odd_clk_div property to choose the proper format.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/mmc/host/atmel-mci.c | 12 +++++++++---
- 1 file changed, 9 insertions(+), 3 deletions(-)
-
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -395,11 +395,17 @@ static int atmci_regs_show(struct seq_fi
- clk_disable(host->mck);
- spin_unlock_bh(&host->lock);
-
-- seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n",
-+ seq_printf(s, "MR:\t0x%08x%s%s ",
- buf[ATMCI_MR / 4],
- buf[ATMCI_MR / 4] & ATMCI_MR_RDPROOF ? " RDPROOF" : "",
-- buf[ATMCI_MR / 4] & ATMCI_MR_WRPROOF ? " WRPROOF" : "",
-- buf[ATMCI_MR / 4] & 0xff);
-+ buf[ATMCI_MR / 4] & ATMCI_MR_WRPROOF ? " WRPROOF" : "");
-+ if (host->caps.has_odd_clk_div)
-+ seq_printf(s, "{CLKDIV,CLKODD}=%u\n",
-+ ((buf[ATMCI_MR / 4] & 0xff) << 1)
-+ | ((buf[ATMCI_MR / 4] >> 16) & 1));
-+ else
-+ seq_printf(s, "CLKDIV=%u\n",
-+ (buf[ATMCI_MR / 4] & 0xff));
- seq_printf(s, "DTOR:\t0x%08x\n", buf[ATMCI_DTOR / 4]);
- seq_printf(s, "SDCR:\t0x%08x\n", buf[ATMCI_SDCR / 4]);
- seq_printf(s, "ARGR:\t0x%08x\n", buf[ATMCI_ARGR / 4]);
+++ /dev/null
-From 60bbd1c2625b64f10374f25698d289fa3147bef2 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Mon, 9 Jul 2012 08:51:50 +0200
-Subject: mmc: atmel-mci: increase dma threshold
-
-There are some issues with some SD cards when dma is used. DMA transfer
-during cmd6 seems to hang for an unknown reason. Since using PIO prevents from
-this issue, the dma threshold has been increased to not use dma for this
-command.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- drivers/mmc/host/atmel-mci.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
-index e03367c..05a293e 100644
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -45,7 +45,7 @@
- #include "atmel-mci-regs.h"
-
- #define ATMCI_DATA_ERROR_FLAGS (ATMCI_DCRCE | ATMCI_DTOE | ATMCI_OVRE | ATMCI_UNRE)
--#define ATMCI_DMA_THRESHOLD 16
-+#define ATMCI_DMA_THRESHOLD 65
-
- enum {
- EVENT_CMD_RDY = 0,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 7c25754fa2e567e1a0d91f79e6c4813da979c0b1 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Tue, 24 Jul 2012 09:32:29 +0200
-Subject: mmc: atmel-mci: not busy flag has also to be used for read operations
-
-commit 077d40731edc90ee9dedf63249034c8cd5f694ce upstream.
-
-Even if the datasheet says that the not busy flag has to be used only for
-write operations, it's false excepted for version lesser than v2xx.
-Not waiting the not busy flag for read operations can cause the controller to
-hang-up during some SD card initialization.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- drivers/mmc/host/atmel-mci.c | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -84,6 +84,7 @@ struct atmel_mci_caps {
- bool has_bad_data_ordering;
- bool need_reset_after_xfer;
- bool need_blksz_mul_4;
-+ bool need_notbusy_for_read_ops;
- };
-
- struct atmel_mci_dma {
-@@ -1696,7 +1697,8 @@ static void atmci_tasklet_func(unsigned
- __func__);
- atmci_set_completed(host, EVENT_XFER_COMPLETE);
-
-- if (host->data->flags & MMC_DATA_WRITE) {
-+ if (host->caps.need_notbusy_for_read_ops
-+ || (host->data->flags & MMC_DATA_WRITE)) {
- atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
- state = STATE_WAITING_NOTBUSY;
- } else if (host->mrq->stop) {
-@@ -2300,6 +2302,7 @@ static void __init atmci_get_cap(struct
- host->caps.has_bad_data_ordering = 1;
- host->caps.need_reset_after_xfer = 1;
- host->caps.need_blksz_mul_4 = 1;
-+ host->caps.need_notbusy_for_read_ops = 0;
-
- /* keep only major version number */
- switch (version & 0xf00) {
-@@ -2320,6 +2323,7 @@ static void __init atmci_get_cap(struct
- case 0x200:
- host->caps.has_rwproof = 1;
- host->caps.need_blksz_mul_4 = 0;
-+ host->caps.need_notbusy_for_read_ops = 1;
- case 0x100:
- host->caps.has_bad_data_ordering = 0;
- host->caps.need_reset_after_xfer = 0;
+++ /dev/null
-From f15c1fee74041aaa81f21f9f499b1f6926bcf716 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 22 Oct 2012 15:52:48 +0200
-Subject: Replace clk_lookup.con_id with clk_lookup.dev_id entries for twi clk
-
-commit af2a5f09fb6d317a0ec4b5026cd50f0b49a60419 upstream.
-
-The old driver used con_id clock entries. Convert to use dev_id
-for clock lookup via standard method.
-
-Signed-off-by: Nikolaus Voss <n.voss@weinmann.de>
-Tested-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Reviewed-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-
-Conflicts:
- arch/arm/mach-at91/at91sam9x5.c
----
- arch/arm/mach-at91/at91rm9200.c | 1 +
- arch/arm/mach-at91/at91sam9260.c | 1 +
- arch/arm/mach-at91/at91sam9261.c | 1 +
- arch/arm/mach-at91/at91sam9263.c | 1 +
- arch/arm/mach-at91/at91sam9g45.c | 2 ++
- arch/arm/mach-at91/at91sam9rl.c | 2 ++
- arch/arm/mach-at91/at91sam9x5.c | 3 +++
- 7 files changed, 11 insertions(+)
-
-diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
-index 6f50c67..f2112f9 100644
---- a/arch/arm/mach-at91/at91rm9200.c
-+++ b/arch/arm/mach-at91/at91rm9200.c
-@@ -187,6 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
- /* fake hclk clock */
- CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
- CLKDEV_CON_ID("pioA", &pioA_clk),
-diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
-index 4696729..d824b0e 100644
---- a/arch/arm/mach-at91/at91sam9260.c
-+++ b/arch/arm/mach-at91/at91sam9260.c
-@@ -203,6 +203,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
- CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
- /* more usart lookup table for DT entries */
- CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
- CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
-diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
-index f40762c..71ca1e0 100644
---- a/arch/arm/mach-at91/at91sam9261.c
-+++ b/arch/arm/mach-at91/at91sam9261.c
-@@ -178,6 +178,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
- CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
-+ CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
- CLKDEV_CON_ID("pioA", &pioA_clk),
- CLKDEV_CON_ID("pioB", &pioB_clk),
- CLKDEV_CON_ID("pioC", &pioC_clk),
-diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
-index c82d521..00c947e 100644
---- a/arch/arm/mach-at91/at91sam9263.c
-+++ b/arch/arm/mach-at91/at91sam9263.c
-@@ -193,6 +193,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
- CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
- CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
- /* fake hclk clock */
- CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
- CLKDEV_CON_ID("pioA", &pioA_clk),
-diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
-index f6d0eab..5de8b00 100644
---- a/arch/arm/mach-at91/at91sam9g45.c
-+++ b/arch/arm/mach-at91/at91sam9g45.c
-@@ -222,6 +222,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
- CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb0_clk),
- CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "at91_i2c.0", &twi0_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "at91_i2c.1", &twi1_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
- CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
-diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
-index 72ce50a..bf79c1f 100644
---- a/arch/arm/mach-at91/at91sam9rl.c
-+++ b/arch/arm/mach-at91/at91sam9rl.c
-@@ -186,6 +186,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "at91_i2c.0", &twi0_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "at91_i2c.1", &twi1_clk),
- CLKDEV_CON_ID("pioA", &pioA_clk),
- CLKDEV_CON_ID("pioB", &pioB_clk),
- CLKDEV_CON_ID("pioC", &pioC_clk),
-diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
-index 796b3c0..15ac57b 100644
---- a/arch/arm/mach-at91/at91sam9x5.c
-+++ b/arch/arm/mach-at91/at91sam9x5.c
-@@ -227,6 +227,9 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk),
- CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc0_clk),
- CLKDEV_CON_DEV_ID("mci_clk", "f000c000.mmc", &mmc1_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "at91_i2c.0", &twi0_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "at91_i2c.1", &twi1_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "at91_i2c.2", &twi2_clk),
- CLKDEV_CON_ID("pioA", &pioAB_clk),
- CLKDEV_CON_ID("pioB", &pioAB_clk),
- CLKDEV_CON_ID("pioC", &pioCD_clk),
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From bec34acb1d565ac4659747861bd68b1b99492c83 Mon Sep 17 00:00:00 2001
-From: Nikolaus Voss <n.voss@weinmann.de>
-Date: Tue, 8 Nov 2011 11:49:24 +0100
-Subject: i2c: at91: remove old polling driver
-
-commit a879e9c34b93ee43f5caa7f94eb17e7af4f6ef50 upstream.
-
-It will get replaced by a superior one. Safe to remove since this one
-depends on BROKEN anyhow.
-
-Signed-off-by: Nikolaus Voss <n.voss@weinmann.de>
-Tested-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Reviewed-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-
-[wsa: added commit message]
-
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
----
- arch/arm/mach-at91/include/mach/at91_twi.h | 68 -------
- drivers/i2c/busses/Makefile | 1 -
- drivers/i2c/busses/i2c-at91.c | 314 -----------------------------
- 3 files changed, 383 deletions(-)
- delete mode 100644 arch/arm/mach-at91/include/mach/at91_twi.h
- delete mode 100644 drivers/i2c/busses/i2c-at91.c
-
-diff --git a/arch/arm/mach-at91/include/mach/at91_twi.h b/arch/arm/mach-at91/include/mach/at91_twi.h
-deleted file mode 100644
-index bb2880f..0000000
---- a/arch/arm/mach-at91/include/mach/at91_twi.h
-+++ /dev/null
-@@ -1,68 +0,0 @@
--/*
-- * arch/arm/mach-at91/include/mach/at91_twi.h
-- *
-- * Copyright (C) 2005 Ivan Kokshaysky
-- * Copyright (C) SAN People
-- *
-- * Two-wire Interface (TWI) registers.
-- * Based on AT91RM9200 datasheet revision E.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- */
--
--#ifndef AT91_TWI_H
--#define AT91_TWI_H
--
--#define AT91_TWI_CR 0x00 /* Control Register */
--#define AT91_TWI_START (1 << 0) /* Send a Start Condition */
--#define AT91_TWI_STOP (1 << 1) /* Send a Stop Condition */
--#define AT91_TWI_MSEN (1 << 2) /* Master Transfer Enable */
--#define AT91_TWI_MSDIS (1 << 3) /* Master Transfer Disable */
--#define AT91_TWI_SVEN (1 << 4) /* Slave Transfer Enable [SAM9260 only] */
--#define AT91_TWI_SVDIS (1 << 5) /* Slave Transfer Disable [SAM9260 only] */
--#define AT91_TWI_SWRST (1 << 7) /* Software Reset */
--
--#define AT91_TWI_MMR 0x04 /* Master Mode Register */
--#define AT91_TWI_IADRSZ (3 << 8) /* Internal Device Address Size */
--#define AT91_TWI_IADRSZ_NO (0 << 8)
--#define AT91_TWI_IADRSZ_1 (1 << 8)
--#define AT91_TWI_IADRSZ_2 (2 << 8)
--#define AT91_TWI_IADRSZ_3 (3 << 8)
--#define AT91_TWI_MREAD (1 << 12) /* Master Read Direction */
--#define AT91_TWI_DADR (0x7f << 16) /* Device Address */
--
--#define AT91_TWI_SMR 0x08 /* Slave Mode Register [SAM9260 only] */
--#define AT91_TWI_SADR (0x7f << 16) /* Slave Address */
--
--#define AT91_TWI_IADR 0x0c /* Internal Address Register */
--
--#define AT91_TWI_CWGR 0x10 /* Clock Waveform Generator Register */
--#define AT91_TWI_CLDIV (0xff << 0) /* Clock Low Divisor */
--#define AT91_TWI_CHDIV (0xff << 8) /* Clock High Divisor */
--#define AT91_TWI_CKDIV (7 << 16) /* Clock Divider */
--
--#define AT91_TWI_SR 0x20 /* Status Register */
--#define AT91_TWI_TXCOMP (1 << 0) /* Transmission Complete */
--#define AT91_TWI_RXRDY (1 << 1) /* Receive Holding Register Ready */
--#define AT91_TWI_TXRDY (1 << 2) /* Transmit Holding Register Ready */
--#define AT91_TWI_SVREAD (1 << 3) /* Slave Read [SAM9260 only] */
--#define AT91_TWI_SVACC (1 << 4) /* Slave Access [SAM9260 only] */
--#define AT91_TWI_GACC (1 << 5) /* General Call Access [SAM9260 only] */
--#define AT91_TWI_OVRE (1 << 6) /* Overrun Error [AT91RM9200 only] */
--#define AT91_TWI_UNRE (1 << 7) /* Underrun Error [AT91RM9200 only] */
--#define AT91_TWI_NACK (1 << 8) /* Not Acknowledged */
--#define AT91_TWI_ARBLST (1 << 9) /* Arbitration Lost [SAM9260 only] */
--#define AT91_TWI_SCLWS (1 << 10) /* Clock Wait State [SAM9260 only] */
--#define AT91_TWI_EOSACC (1 << 11) /* End of Slave Address [SAM9260 only] */
--
--#define AT91_TWI_IER 0x24 /* Interrupt Enable Register */
--#define AT91_TWI_IDR 0x28 /* Interrupt Disable Register */
--#define AT91_TWI_IMR 0x2c /* Interrupt Mask Register */
--#define AT91_TWI_RHR 0x30 /* Receive Holding Register */
--#define AT91_TWI_THR 0x34 /* Transmit Holding Register */
--
--#endif
--
-diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
-index 569567b..b74c801 100644
---- a/drivers/i2c/busses/Makefile
-+++ b/drivers/i2c/busses/Makefile
-@@ -28,7 +28,6 @@ obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
- obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
-
- # Embedded system I2C/SMBus host controller drivers
--obj-$(CONFIG_I2C_AT91) += i2c-at91.o
- obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
- obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
- obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
-diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
-deleted file mode 100644
-index 1679dee..0000000
---- a/drivers/i2c/busses/i2c-at91.c
-+++ /dev/null
-@@ -1,314 +0,0 @@
--/*
-- i2c Support for Atmel's AT91 Two-Wire Interface (TWI)
--
-- Copyright (C) 2004 Rick Bronson
-- Converted to 2.6 by Andrew Victor <andrew@sanpeople.com>
--
-- Borrowed heavily from original work by:
-- Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--*/
--
--#include <linux/module.h>
--#include <linux/kernel.h>
--#include <linux/err.h>
--#include <linux/slab.h>
--#include <linux/types.h>
--#include <linux/delay.h>
--#include <linux/i2c.h>
--#include <linux/init.h>
--#include <linux/clk.h>
--#include <linux/platform_device.h>
--#include <linux/io.h>
--
--#include <mach/at91_twi.h>
--#include <mach/board.h>
--#include <mach/cpu.h>
--
--#define TWI_CLOCK 100000 /* Hz. max 400 Kbits/sec */
--
--
--static struct clk *twi_clk;
--static void __iomem *twi_base;
--
--#define at91_twi_read(reg) __raw_readl(twi_base + (reg))
--#define at91_twi_write(reg, val) __raw_writel((val), twi_base + (reg))
--
--
--/*
-- * Initialize the TWI hardware registers.
-- */
--static void __devinit at91_twi_hwinit(void)
--{
-- unsigned long cdiv, ckdiv;
--
-- at91_twi_write(AT91_TWI_IDR, 0xffffffff); /* Disable all interrupts */
-- at91_twi_write(AT91_TWI_CR, AT91_TWI_SWRST); /* Reset peripheral */
-- at91_twi_write(AT91_TWI_CR, AT91_TWI_MSEN); /* Set Master mode */
--
-- /* Calcuate clock dividers */
-- cdiv = (clk_get_rate(twi_clk) / (2 * TWI_CLOCK)) - 3;
-- cdiv = cdiv + 1; /* round up */
-- ckdiv = 0;
-- while (cdiv > 255) {
-- ckdiv++;
-- cdiv = cdiv >> 1;
-- }
--
-- if (cpu_is_at91rm9200()) { /* AT91RM9200 Errata #22 */
-- if (ckdiv > 5) {
-- printk(KERN_ERR "AT91 I2C: Invalid TWI_CLOCK value!\n");
-- ckdiv = 5;
-- }
-- }
--
-- at91_twi_write(AT91_TWI_CWGR, (ckdiv << 16) | (cdiv << 8) | cdiv);
--}
--
--/*
-- * Poll the i2c status register until the specified bit is set.
-- * Returns 0 if timed out (100 msec).
-- */
--static short at91_poll_status(unsigned long bit)
--{
-- int loop_cntr = 10000;
--
-- do {
-- udelay(10);
-- } while (!(at91_twi_read(AT91_TWI_SR) & bit) && (--loop_cntr > 0));
--
-- return (loop_cntr > 0);
--}
--
--static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
--{
-- /* Send Start */
-- at91_twi_write(AT91_TWI_CR, AT91_TWI_START);
--
-- /* Read data */
-- while (length--) {
-- if (!length) /* need to send Stop before reading last byte */
-- at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP);
-- if (!at91_poll_status(AT91_TWI_RXRDY)) {
-- dev_dbg(&adap->dev, "RXRDY timeout\n");
-- return -ETIMEDOUT;
-- }
-- *buf++ = (at91_twi_read(AT91_TWI_RHR) & 0xff);
-- }
--
-- return 0;
--}
--
--static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length)
--{
-- /* Load first byte into transmitter */
-- at91_twi_write(AT91_TWI_THR, *buf++);
--
-- /* Send Start */
-- at91_twi_write(AT91_TWI_CR, AT91_TWI_START);
--
-- do {
-- if (!at91_poll_status(AT91_TWI_TXRDY)) {
-- dev_dbg(&adap->dev, "TXRDY timeout\n");
-- return -ETIMEDOUT;
-- }
--
-- length--; /* byte was transmitted */
--
-- if (length > 0) /* more data to send? */
-- at91_twi_write(AT91_TWI_THR, *buf++);
-- } while (length);
--
-- /* Send Stop */
-- at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP);
--
-- return 0;
--}
--
--/*
-- * Generic i2c master transfer entrypoint.
-- *
-- * Note: We do not use Atmel's feature of storing the "internal device address".
-- * Instead the "internal device address" has to be written using a separate
-- * i2c message.
-- * http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2004-September/024411.html
-- */
--static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num)
--{
-- int i, ret;
--
-- dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num);
--
-- for (i = 0; i < num; i++) {
-- dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
-- pmsg->flags & I2C_M_RD ? "read" : "writ",
-- pmsg->len, pmsg->len > 1 ? "s" : "",
-- pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr);
--
-- at91_twi_write(AT91_TWI_MMR, (pmsg->addr << 16)
-- | ((pmsg->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0));
--
-- if (pmsg->len && pmsg->buf) { /* sanity check */
-- if (pmsg->flags & I2C_M_RD)
-- ret = xfer_read(adap, pmsg->buf, pmsg->len);
-- else
-- ret = xfer_write(adap, pmsg->buf, pmsg->len);
--
-- if (ret)
-- return ret;
--
-- /* Wait until transfer is finished */
-- if (!at91_poll_status(AT91_TWI_TXCOMP)) {
-- dev_dbg(&adap->dev, "TXCOMP timeout\n");
-- return -ETIMEDOUT;
-- }
-- }
-- dev_dbg(&adap->dev, "transfer complete\n");
-- pmsg++; /* next message */
-- }
-- return i;
--}
--
--/*
-- * Return list of supported functionality.
-- */
--static u32 at91_func(struct i2c_adapter *adapter)
--{
-- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
--}
--
--static struct i2c_algorithm at91_algorithm = {
-- .master_xfer = at91_xfer,
-- .functionality = at91_func,
--};
--
--/*
-- * Main initialization routine.
-- */
--static int __devinit at91_i2c_probe(struct platform_device *pdev)
--{
-- struct i2c_adapter *adapter;
-- struct resource *res;
-- int rc;
--
-- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- if (!res)
-- return -ENXIO;
--
-- if (!request_mem_region(res->start, resource_size(res), "at91_i2c"))
-- return -EBUSY;
--
-- twi_base = ioremap(res->start, resource_size(res));
-- if (!twi_base) {
-- rc = -ENOMEM;
-- goto fail0;
-- }
--
-- twi_clk = clk_get(NULL, "twi_clk");
-- if (IS_ERR(twi_clk)) {
-- dev_err(&pdev->dev, "no clock defined\n");
-- rc = -ENODEV;
-- goto fail1;
-- }
--
-- adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
-- if (adapter == NULL) {
-- dev_err(&pdev->dev, "can't allocate inteface!\n");
-- rc = -ENOMEM;
-- goto fail2;
-- }
-- snprintf(adapter->name, sizeof(adapter->name), "AT91");
-- adapter->algo = &at91_algorithm;
-- adapter->class = I2C_CLASS_HWMON;
-- adapter->dev.parent = &pdev->dev;
-- /* adapter->id == 0 ... only one TWI controller for now */
--
-- platform_set_drvdata(pdev, adapter);
--
-- clk_enable(twi_clk); /* enable peripheral clock */
-- at91_twi_hwinit(); /* initialize TWI controller */
--
-- rc = i2c_add_numbered_adapter(adapter);
-- if (rc) {
-- dev_err(&pdev->dev, "Adapter %s registration failed\n",
-- adapter->name);
-- goto fail3;
-- }
--
-- dev_info(&pdev->dev, "AT91 i2c bus driver.\n");
-- return 0;
--
--fail3:
-- platform_set_drvdata(pdev, NULL);
-- kfree(adapter);
-- clk_disable(twi_clk);
--fail2:
-- clk_put(twi_clk);
--fail1:
-- iounmap(twi_base);
--fail0:
-- release_mem_region(res->start, resource_size(res));
--
-- return rc;
--}
--
--static int __devexit at91_i2c_remove(struct platform_device *pdev)
--{
-- struct i2c_adapter *adapter = platform_get_drvdata(pdev);
-- struct resource *res;
-- int rc;
--
-- rc = i2c_del_adapter(adapter);
-- platform_set_drvdata(pdev, NULL);
--
-- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- iounmap(twi_base);
-- release_mem_region(res->start, resource_size(res));
--
-- clk_disable(twi_clk); /* disable peripheral clock */
-- clk_put(twi_clk);
--
-- return rc;
--}
--
--#ifdef CONFIG_PM
--
--/* NOTE: could save a few mA by keeping clock off outside of at91_xfer... */
--
--static int at91_i2c_suspend(struct platform_device *pdev, pm_message_t mesg)
--{
-- clk_disable(twi_clk);
-- return 0;
--}
--
--static int at91_i2c_resume(struct platform_device *pdev)
--{
-- return clk_enable(twi_clk);
--}
--
--#else
--#define at91_i2c_suspend NULL
--#define at91_i2c_resume NULL
--#endif
--
--static struct platform_driver at91_i2c_driver = {
-- .probe = at91_i2c_probe,
-- .remove = __devexit_p(at91_i2c_remove),
-- .suspend = at91_i2c_suspend,
-- .resume = at91_i2c_resume,
-- .driver = {
-- .name = "at91_i2c",
-- .owner = THIS_MODULE,
-- },
--};
--
--module_platform_driver(at91_i2c_driver);
--
--MODULE_AUTHOR("Rick Bronson");
--MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91");
--MODULE_LICENSE("GPL");
--MODULE_ALIAS("platform:at91_i2c");
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 3fbefb2c85df4c467c48f9963119f26c62d7a31b Mon Sep 17 00:00:00 2001
-From: Nikolaus Voss <n.voss@weinmann.de>
-Date: Tue, 8 Nov 2011 11:49:46 +0100
-Subject: i2c: at91: add new driver
-
-commit fac368a040484293006bb488e67972aafcf88ec7 upstream.
-
-This driver has the following properties compared to the old driver:
-1. Support for multiple interfaces.
-2. Interrupt driven I/O as opposed to polling/busy waiting.
-3. Support for _one_ repeated start (Sr) condition, which is enough
- for most real-world applications including all SMBus transfer types.
- (The hardware does not support issuing arbitrary Sr conditions on the
- bus.)
-
-testing: SoC: at91sam9g45
- - BQ20Z80 battery SMBus client.
- - on a 2.6.38 kernel with several i2c clients (temp-sensor,
- audio-codec, touchscreen-controller, w1-bridge, io-expanders)
-
-Signed-off-by: Nikolaus Voss <n.voss@weinmann.de>
-Reviewed-by: Felipe Balbi <balbi@ti.com>
-Tested-by: Hubert Feurstein <h.feurstein@gmail.com>
-Tested-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Reviewed-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-
-[wsa: squashed with the following patches from Ludovic to have some flaws
-fixed:
- i2c: at91: use managed resources
- i2c: at91: add warning about transmission issues for some devices
- i2c: at91: use an id table for SoC dependent parameters
-]
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
----
- arch/arm/mach-at91/at91rm9200.c | 2
- arch/arm/mach-at91/at91rm9200_devices.c | 2
- arch/arm/mach-at91/at91sam9260.c | 3
- arch/arm/mach-at91/at91sam9260_devices.c | 8
- arch/arm/mach-at91/at91sam9261.c | 3
- arch/arm/mach-at91/at91sam9261_devices.c | 8
- arch/arm/mach-at91/at91sam9263.c | 2
- arch/arm/mach-at91/at91sam9263_devices.c | 2
- arch/arm/mach-at91/at91sam9g45.c | 4
- arch/arm/mach-at91/at91sam9g45_devices.c | 4
- arch/arm/mach-at91/at91sam9rl.c | 4
- arch/arm/mach-at91/at91sam9rl_devices.c | 2
- drivers/i2c/busses/Kconfig | 17 -
- drivers/i2c/busses/Makefile | 1
- drivers/i2c/busses/i2c-at91.c | 505 +++++++++++++++++++++++++++++++
- 15 files changed, 545 insertions(+), 22 deletions(-)
- create mode 100644 drivers/i2c/busses/i2c-at91.c
-
---- a/arch/arm/mach-at91/at91rm9200.c
-+++ b/arch/arm/mach-at91/at91rm9200.c
-@@ -187,7 +187,7 @@ static struct clk_lookup periph_clocks_l
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
-- CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200", &twi_clk),
- /* fake hclk clock */
- CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
- CLKDEV_CON_ID("pioA", &pioA_clk),
---- a/arch/arm/mach-at91/at91rm9200_devices.c
-+++ b/arch/arm/mach-at91/at91rm9200_devices.c
-@@ -511,7 +511,7 @@ static struct resource twi_resources[] =
- };
-
- static struct platform_device at91rm9200_twi_device = {
-- .name = "at91_i2c",
-+ .name = "i2c-at91rm9200",
- .id = -1,
- .resource = twi_resources,
- .num_resources = ARRAY_SIZE(twi_resources),
---- a/arch/arm/mach-at91/at91sam9260.c
-+++ b/arch/arm/mach-at91/at91sam9260.c
-@@ -203,7 +203,8 @@ static struct clk_lookup periph_clocks_l
- CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
- CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
-- CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20", &twi_clk),
- /* more usart lookup table for DT entries */
- CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
- CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
---- a/arch/arm/mach-at91/at91sam9260_devices.c
-+++ b/arch/arm/mach-at91/at91sam9260_devices.c
-@@ -418,7 +418,6 @@ static struct resource twi_resources[] =
- };
-
- static struct platform_device at91sam9260_twi_device = {
-- .name = "at91_i2c",
- .id = -1,
- .resource = twi_resources,
- .num_resources = ARRAY_SIZE(twi_resources),
-@@ -426,6 +425,13 @@ static struct platform_device at91sam926
-
- void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
- {
-+ /* IP version is not the same on 9260 and g20 */
-+ if (cpu_is_at91sam9g20()) {
-+ at91sam9260_twi_device.name = "i2c-at91sam9g20";
-+ } else {
-+ at91sam9260_twi_device.name = "i2c-at91sam9260";
-+ }
-+
- /* pins used for TWI interface */
- at91_set_A_periph(AT91_PIN_PA23, 0); /* TWD */
- at91_set_multi_drive(AT91_PIN_PA23, 1);
---- a/arch/arm/mach-at91/at91sam9261.c
-+++ b/arch/arm/mach-at91/at91sam9261.c
-@@ -178,7 +178,8 @@ static struct clk_lookup periph_clocks_l
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
- CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
-- CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261", &twi_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10", &twi_clk),
- CLKDEV_CON_ID("pioA", &pioA_clk),
- CLKDEV_CON_ID("pioB", &pioB_clk),
- CLKDEV_CON_ID("pioC", &pioC_clk),
---- a/arch/arm/mach-at91/at91sam9261_devices.c
-+++ b/arch/arm/mach-at91/at91sam9261_devices.c
-@@ -319,7 +319,6 @@ static struct resource twi_resources[] =
- };
-
- static struct platform_device at91sam9261_twi_device = {
-- .name = "at91_i2c",
- .id = -1,
- .resource = twi_resources,
- .num_resources = ARRAY_SIZE(twi_resources),
-@@ -327,6 +326,13 @@ static struct platform_device at91sam926
-
- void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
- {
-+ /* IP version is not the same on 9261 and g10 */
-+ if (cpu_is_at91sam9g10()) {
-+ at91sam9261_twi_device.name = "i2c-at91sam9g10";
-+ } else {
-+ at91sam9261_twi_device.name = "i2c-at91sam9261";
-+ }
-+
- /* pins used for TWI interface */
- at91_set_A_periph(AT91_PIN_PA7, 0); /* TWD */
- at91_set_multi_drive(AT91_PIN_PA7, 1);
---- a/arch/arm/mach-at91/at91sam9263.c
-+++ b/arch/arm/mach-at91/at91sam9263.c
-@@ -193,7 +193,7 @@ static struct clk_lookup periph_clocks_l
- CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
- CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
- CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
-- CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
- /* fake hclk clock */
- CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
- CLKDEV_CON_ID("pioA", &pioA_clk),
---- a/arch/arm/mach-at91/at91sam9263_devices.c
-+++ b/arch/arm/mach-at91/at91sam9263_devices.c
-@@ -601,7 +601,7 @@ static struct resource twi_resources[] =
- };
-
- static struct platform_device at91sam9263_twi_device = {
-- .name = "at91_i2c",
-+ .name = "i2c-at91sam9260",
- .id = -1,
- .resource = twi_resources,
- .num_resources = ARRAY_SIZE(twi_resources),
---- a/arch/arm/mach-at91/at91sam9g45.c
-+++ b/arch/arm/mach-at91/at91sam9g45.c
-@@ -222,8 +222,8 @@ static struct clk_lookup periph_clocks_l
- CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
- CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb0_clk),
- CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
-- CLKDEV_CON_DEV_ID(NULL, "at91_i2c.0", &twi0_clk),
-- CLKDEV_CON_DEV_ID(NULL, "at91_i2c.1", &twi1_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi0_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.1", &twi1_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
- CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
---- a/arch/arm/mach-at91/at91sam9g45_devices.c
-+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
-@@ -651,7 +651,7 @@ static struct resource twi0_resources[]
- };
-
- static struct platform_device at91sam9g45_twi0_device = {
-- .name = "at91_i2c",
-+ .name = "i2c-at91sam9g10",
- .id = 0,
- .resource = twi0_resources,
- .num_resources = ARRAY_SIZE(twi0_resources),
-@@ -671,7 +671,7 @@ static struct resource twi1_resources[]
- };
-
- static struct platform_device at91sam9g45_twi1_device = {
-- .name = "at91_i2c",
-+ .name = "i2c-at91sam9g10",
- .id = 1,
- .resource = twi1_resources,
- .num_resources = ARRAY_SIZE(twi1_resources),
---- a/arch/arm/mach-at91/at91sam9rl.c
-+++ b/arch/arm/mach-at91/at91sam9rl.c
-@@ -186,8 +186,8 @@ static struct clk_lookup periph_clocks_l
- CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
-- CLKDEV_CON_DEV_ID(NULL, "at91_i2c.0", &twi0_clk),
-- CLKDEV_CON_DEV_ID(NULL, "at91_i2c.1", &twi1_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi0_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.1", &twi1_clk),
- CLKDEV_CON_ID("pioA", &pioA_clk),
- CLKDEV_CON_ID("pioB", &pioB_clk),
- CLKDEV_CON_ID("pioC", &pioC_clk),
---- a/arch/arm/mach-at91/at91sam9rl_devices.c
-+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
-@@ -348,7 +348,7 @@ static struct resource twi_resources[] =
- };
-
- static struct platform_device at91sam9rl_twi_device = {
-- .name = "at91_i2c",
-+ .name = "i2c-at91sam9g20",
- .id = -1,
- .resource = twi_resources,
- .num_resources = ARRAY_SIZE(twi_resources),
---- a/drivers/i2c/busses/Kconfig
-+++ b/drivers/i2c/busses/Kconfig
-@@ -287,18 +287,21 @@ comment "I2C system bus drivers (mostly
-
- config I2C_AT91
- tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
-- depends on ARCH_AT91 && EXPERIMENTAL && BROKEN
-+ depends on ARCH_AT91 && EXPERIMENTAL
- help
- This supports the use of the I2C interface on Atmel AT91
- processors.
-
-- This driver is BROKEN because the controller which it uses
-- will easily trigger RX overrun and TX underrun errors. Using
-- low I2C clock rates may partially work around those issues
-- on some systems. Another serious problem is that there is no
-- documented way to issue repeated START conditions, as needed
-+ A serious problem is that there is no documented way to issue
-+ repeated START conditions for more than two messages, as needed
- to support combined I2C messages. Use the i2c-gpio driver
-- unless your system can cope with those limitations.
-+ unless your system can cope with this limitation.
-+
-+ Caution! at91rm9200, at91sam9261, at91sam9260, at91sam9263 devices
-+ don't have clock stretching in transmission mode. For that reason,
-+ you can encounter underrun issues causing premature stop sendings if
-+ the latency to fill the transmission register is too long. If you
-+ are facing this situation, use the i2c-gpio driver.
-
- config I2C_AU1550
- tristate "Au1550/Au1200/Au1300 SMBus interface"
---- a/drivers/i2c/busses/Makefile
-+++ b/drivers/i2c/busses/Makefile
-@@ -28,6 +28,7 @@ obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
- obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
-
- # Embedded system I2C/SMBus host controller drivers
-+obj-$(CONFIG_I2C_AT91) += i2c-at91.o
- obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
- obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
- obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
---- /dev/null
-+++ b/drivers/i2c/busses/i2c-at91.c
-@@ -0,0 +1,505 @@
-+/*
-+ * i2c Support for Atmel's AT91 Two-Wire Interface (TWI)
-+ *
-+ * Copyright (C) 2011 Weinmann Medical GmbH
-+ * Author: Nikolaus Voss <n.voss@weinmann.de>
-+ *
-+ * Evolved from original work by:
-+ * Copyright (C) 2004 Rick Bronson
-+ * Converted to 2.6 by Andrew Victor <andrew@sanpeople.com>
-+ *
-+ * Borrowed heavily from original work by:
-+ * Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/completion.h>
-+#include <linux/err.h>
-+#include <linux/i2c.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/slab.h>
-+
-+#define TWI_CLK_HZ 100000 /* max 400 Kbits/s */
-+#define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */
-+
-+/* AT91 TWI register definitions */
-+#define AT91_TWI_CR 0x0000 /* Control Register */
-+#define AT91_TWI_START 0x0001 /* Send a Start Condition */
-+#define AT91_TWI_STOP 0x0002 /* Send a Stop Condition */
-+#define AT91_TWI_MSEN 0x0004 /* Master Transfer Enable */
-+#define AT91_TWI_SVDIS 0x0020 /* Slave Transfer Disable */
-+#define AT91_TWI_SWRST 0x0080 /* Software Reset */
-+
-+#define AT91_TWI_MMR 0x0004 /* Master Mode Register */
-+#define AT91_TWI_IADRSZ_1 0x0100 /* Internal Device Address Size */
-+#define AT91_TWI_MREAD 0x1000 /* Master Read Direction */
-+
-+#define AT91_TWI_IADR 0x000c /* Internal Address Register */
-+
-+#define AT91_TWI_CWGR 0x0010 /* Clock Waveform Generator Reg */
-+
-+#define AT91_TWI_SR 0x0020 /* Status Register */
-+#define AT91_TWI_TXCOMP 0x0001 /* Transmission Complete */
-+#define AT91_TWI_RXRDY 0x0002 /* Receive Holding Register Ready */
-+#define AT91_TWI_TXRDY 0x0004 /* Transmit Holding Register Ready */
-+
-+#define AT91_TWI_OVRE 0x0040 /* Overrun Error */
-+#define AT91_TWI_UNRE 0x0080 /* Underrun Error */
-+#define AT91_TWI_NACK 0x0100 /* Not Acknowledged */
-+
-+#define AT91_TWI_IER 0x0024 /* Interrupt Enable Register */
-+#define AT91_TWI_IDR 0x0028 /* Interrupt Disable Register */
-+#define AT91_TWI_IMR 0x002c /* Interrupt Mask Register */
-+#define AT91_TWI_RHR 0x0030 /* Receive Holding Register */
-+#define AT91_TWI_THR 0x0034 /* Transmit Holding Register */
-+
-+struct at91_twi_pdata {
-+ unsigned clk_max_div;
-+ unsigned clk_offset;
-+ bool has_unre_flag;
-+};
-+
-+struct at91_twi_dev {
-+ struct device *dev;
-+ void __iomem *base;
-+ struct completion cmd_complete;
-+ struct clk *clk;
-+ u8 *buf;
-+ size_t buf_len;
-+ struct i2c_msg *msg;
-+ int irq;
-+ unsigned transfer_status;
-+ struct i2c_adapter adapter;
-+ unsigned twi_cwgr_reg;
-+ struct at91_twi_pdata *pdata;
-+};
-+
-+static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg)
-+{
-+ return readl_relaxed(dev->base + reg);
-+}
-+
-+static void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, unsigned val)
-+{
-+ writel_relaxed(val, dev->base + reg);
-+}
-+
-+static void at91_disable_twi_interrupts(struct at91_twi_dev *dev)
-+{
-+ at91_twi_write(dev, AT91_TWI_IDR,
-+ AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY);
-+}
-+
-+static void at91_init_twi_bus(struct at91_twi_dev *dev)
-+{
-+ at91_disable_twi_interrupts(dev);
-+ at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SWRST);
-+ at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_MSEN);
-+ at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SVDIS);
-+ at91_twi_write(dev, AT91_TWI_CWGR, dev->twi_cwgr_reg);
-+}
-+
-+/*
-+ * Calculate symmetric clock as stated in datasheet:
-+ * twi_clk = F_MAIN / (2 * (cdiv * (1 << ckdiv) + offset))
-+ */
-+static void __devinit at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
-+{
-+ int ckdiv, cdiv, div;
-+ struct at91_twi_pdata *pdata = dev->pdata;
-+ int offset = pdata->clk_offset;
-+ int max_ckdiv = pdata->clk_max_div;
-+
-+ div = max(0, (int)DIV_ROUND_UP(clk_get_rate(dev->clk),
-+ 2 * twi_clk) - offset);
-+ ckdiv = fls(div >> 8);
-+ cdiv = div >> ckdiv;
-+
-+ if (ckdiv > max_ckdiv) {
-+ dev_warn(dev->dev, "%d exceeds ckdiv max value which is %d.\n",
-+ ckdiv, max_ckdiv);
-+ ckdiv = max_ckdiv;
-+ cdiv = 255;
-+ }
-+
-+ dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv;
-+ dev_dbg(dev->dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv);
-+}
-+
-+static void at91_twi_write_next_byte(struct at91_twi_dev *dev)
-+{
-+ if (dev->buf_len <= 0)
-+ return;
-+
-+ at91_twi_write(dev, AT91_TWI_THR, *dev->buf);
-+
-+ /* send stop when last byte has been written */
-+ if (--dev->buf_len == 0)
-+ at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
-+
-+ dev_dbg(dev->dev, "wrote 0x%x, to go %d\n", *dev->buf, dev->buf_len);
-+
-+ ++dev->buf;
-+}
-+
-+static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
-+{
-+ if (dev->buf_len <= 0)
-+ return;
-+
-+ *dev->buf = at91_twi_read(dev, AT91_TWI_RHR) & 0xff;
-+ --dev->buf_len;
-+
-+ /* handle I2C_SMBUS_BLOCK_DATA */
-+ if (unlikely(dev->msg->flags & I2C_M_RECV_LEN)) {
-+ dev->msg->flags &= ~I2C_M_RECV_LEN;
-+ dev->buf_len += *dev->buf;
-+ dev->msg->len = dev->buf_len + 1;
-+ dev_dbg(dev->dev, "received block length %d\n", dev->buf_len);
-+ }
-+
-+ /* send stop if second but last byte has been read */
-+ if (dev->buf_len == 1)
-+ at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
-+
-+ dev_dbg(dev->dev, "read 0x%x, to go %d\n", *dev->buf, dev->buf_len);
-+
-+ ++dev->buf;
-+}
-+
-+static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
-+{
-+ struct at91_twi_dev *dev = dev_id;
-+ const unsigned status = at91_twi_read(dev, AT91_TWI_SR);
-+ const unsigned irqstatus = status & at91_twi_read(dev, AT91_TWI_IMR);
-+
-+ if (!irqstatus)
-+ return IRQ_NONE;
-+ else if (irqstatus & AT91_TWI_RXRDY)
-+ at91_twi_read_next_byte(dev);
-+ else if (irqstatus & AT91_TWI_TXRDY)
-+ at91_twi_write_next_byte(dev);
-+
-+ /* catch error flags */
-+ dev->transfer_status |= status;
-+
-+ if (irqstatus & AT91_TWI_TXCOMP) {
-+ at91_disable_twi_interrupts(dev);
-+ complete(&dev->cmd_complete);
-+ }
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static int at91_do_twi_transfer(struct at91_twi_dev *dev)
-+{
-+ int ret;
-+ bool has_unre_flag = dev->pdata->has_unre_flag;
-+
-+ dev_dbg(dev->dev, "transfer: %s %d bytes.\n",
-+ (dev->msg->flags & I2C_M_RD) ? "read" : "write", dev->buf_len);
-+
-+ INIT_COMPLETION(dev->cmd_complete);
-+ dev->transfer_status = 0;
-+ if (dev->msg->flags & I2C_M_RD) {
-+ unsigned start_flags = AT91_TWI_START;
-+
-+ if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) {
-+ dev_err(dev->dev, "RXRDY still set!");
-+ at91_twi_read(dev, AT91_TWI_RHR);
-+ }
-+
-+ /* if only one byte is to be read, immediately stop transfer */
-+ if (dev->buf_len <= 1 && !(dev->msg->flags & I2C_M_RECV_LEN))
-+ start_flags |= AT91_TWI_STOP;
-+ at91_twi_write(dev, AT91_TWI_CR, start_flags);
-+ at91_twi_write(dev, AT91_TWI_IER,
-+ AT91_TWI_TXCOMP | AT91_TWI_RXRDY);
-+ } else {
-+ at91_twi_write_next_byte(dev);
-+ at91_twi_write(dev, AT91_TWI_IER,
-+ AT91_TWI_TXCOMP | AT91_TWI_TXRDY);
-+ }
-+
-+ ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
-+ dev->adapter.timeout);
-+ if (ret == 0) {
-+ dev_err(dev->dev, "controller timed out\n");
-+ at91_init_twi_bus(dev);
-+ return -ETIMEDOUT;
-+ }
-+ if (dev->transfer_status & AT91_TWI_NACK) {
-+ dev_dbg(dev->dev, "received nack\n");
-+ return -EREMOTEIO;
-+ }
-+ if (dev->transfer_status & AT91_TWI_OVRE) {
-+ dev_err(dev->dev, "overrun while reading\n");
-+ return -EIO;
-+ }
-+ if (has_unre_flag && dev->transfer_status & AT91_TWI_UNRE) {
-+ dev_err(dev->dev, "underrun while writing\n");
-+ return -EIO;
-+ }
-+ dev_dbg(dev->dev, "transfer complete\n");
-+
-+ return 0;
-+}
-+
-+static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
-+{
-+ struct at91_twi_dev *dev = i2c_get_adapdata(adap);
-+ int ret;
-+ unsigned int_addr_flag = 0;
-+ struct i2c_msg *m_start = msg;
-+
-+ dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num);
-+
-+ /*
-+ * The hardware can handle at most two messages concatenated by a
-+ * repeated start via it's internal address feature.
-+ */
-+ if (num > 2) {
-+ dev_err(dev->dev,
-+ "cannot handle more than two concatenated messages.\n");
-+ return 0;
-+ } else if (num == 2) {
-+ int internal_address = 0;
-+ int i;
-+
-+ if (msg->flags & I2C_M_RD) {
-+ dev_err(dev->dev, "first transfer must be write.\n");
-+ return -EINVAL;
-+ }
-+ if (msg->len > 3) {
-+ dev_err(dev->dev, "first message size must be <= 3.\n");
-+ return -EINVAL;
-+ }
-+
-+ /* 1st msg is put into the internal address, start with 2nd */
-+ m_start = &msg[1];
-+ for (i = 0; i < msg->len; ++i) {
-+ const unsigned addr = msg->buf[msg->len - 1 - i];
-+
-+ internal_address |= addr << (8 * i);
-+ int_addr_flag += AT91_TWI_IADRSZ_1;
-+ }
-+ at91_twi_write(dev, AT91_TWI_IADR, internal_address);
-+ }
-+
-+ at91_twi_write(dev, AT91_TWI_MMR, (m_start->addr << 16) | int_addr_flag
-+ | ((m_start->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0));
-+
-+ dev->buf_len = m_start->len;
-+ dev->buf = m_start->buf;
-+ dev->msg = m_start;
-+
-+ ret = at91_do_twi_transfer(dev);
-+
-+ return (ret < 0) ? ret : num;
-+}
-+
-+static u32 at91_twi_func(struct i2c_adapter *adapter)
-+{
-+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
-+ | I2C_FUNC_SMBUS_READ_BLOCK_DATA;
-+}
-+
-+static struct i2c_algorithm at91_twi_algorithm = {
-+ .master_xfer = at91_twi_xfer,
-+ .functionality = at91_twi_func,
-+};
-+
-+static struct at91_twi_pdata at91rm9200_config = {
-+ .clk_max_div = 5,
-+ .clk_offset = 3,
-+ .has_unre_flag = true,
-+};
-+
-+static struct at91_twi_pdata at91sam9261_config = {
-+ .clk_max_div = 5,
-+ .clk_offset = 4,
-+ .has_unre_flag = false,
-+};
-+
-+static struct at91_twi_pdata at91sam9260_config = {
-+ .clk_max_div = 7,
-+ .clk_offset = 4,
-+ .has_unre_flag = false,
-+};
-+
-+static struct at91_twi_pdata at91sam9g20_config = {
-+ .clk_max_div = 7,
-+ .clk_offset = 4,
-+ .has_unre_flag = false,
-+};
-+
-+static struct at91_twi_pdata at91sam9g10_config = {
-+ .clk_max_div = 7,
-+ .clk_offset = 4,
-+ .has_unre_flag = false,
-+};
-+
-+static const struct platform_device_id at91_twi_devtypes[] = {
-+ {
-+ .name = "i2c-at91rm9200",
-+ .driver_data = (unsigned long) &at91rm9200_config,
-+ }, {
-+ .name = "i2c-at91sam9261",
-+ .driver_data = (unsigned long) &at91sam9261_config,
-+ }, {
-+ .name = "i2c-at91sam9260",
-+ .driver_data = (unsigned long) &at91sam9260_config,
-+ }, {
-+ .name = "i2c-at91sam9g20",
-+ .driver_data = (unsigned long) &at91sam9g20_config,
-+ }, {
-+ .name = "i2c-at91sam9g10",
-+ .driver_data = (unsigned long) &at91sam9g10_config,
-+ }, {
-+ /* sentinel */
-+ }
-+};
-+
-+static int __devinit at91_twi_probe(struct platform_device *pdev)
-+{
-+ struct at91_twi_dev *dev;
-+ struct resource *mem;
-+ int rc;
-+
-+ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-+ if (!dev)
-+ return -ENOMEM;
-+ init_completion(&dev->cmd_complete);
-+ dev->dev = &pdev->dev;
-+
-+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!mem)
-+ return -ENODEV;
-+
-+ dev->pdata = at91_twi_get_driver_data(pdev);
-+ if (!dev->pdata)
-+ return -ENODEV;
-+
-+ dev->base = devm_request_and_ioremap(&pdev->dev, mem);
-+ if (!dev->base)
-+ return -EBUSY;
-+
-+ dev->irq = platform_get_irq(pdev, 0);
-+ if (dev->irq < 0)
-+ return dev->irq;
-+
-+ rc = devm_request_irq(&pdev->dev, dev->irq, atmel_twi_interrupt, 0,
-+ dev_name(dev->dev), dev);
-+ if (rc) {
-+ dev_err(dev->dev, "Cannot get irq %d: %d\n", dev->irq, rc);
-+ return rc;
-+ }
-+
-+ platform_set_drvdata(pdev, dev);
-+
-+ dev->clk = devm_clk_get(dev->dev, NULL);
-+ if (IS_ERR(dev->clk)) {
-+ dev_err(dev->dev, "no clock defined\n");
-+ return -ENODEV;
-+ }
-+ clk_prepare_enable(dev->clk);
-+
-+ at91_calc_twi_clock(dev, TWI_CLK_HZ);
-+ at91_init_twi_bus(dev);
-+
-+ snprintf(dev->adapter.name, sizeof(dev->adapter.name), "AT91");
-+ i2c_set_adapdata(&dev->adapter, dev);
-+ dev->adapter.owner = THIS_MODULE;
-+ dev->adapter.class = I2C_CLASS_HWMON;
-+ dev->adapter.algo = &at91_twi_algorithm;
-+ dev->adapter.dev.parent = dev->dev;
-+ dev->adapter.nr = pdev->id;
-+ dev->adapter.timeout = AT91_I2C_TIMEOUT;
-+
-+ rc = i2c_add_numbered_adapter(&dev->adapter);
-+ if (rc) {
-+ dev_err(dev->dev, "Adapter %s registration failed\n",
-+ dev->adapter.name);
-+ clk_disable_unprepare(dev->clk);
-+ return rc;
-+ }
-+
-+ dev_info(dev->dev, "AT91 i2c bus driver.\n");
-+ return 0;
-+}
-+
-+static int __devexit at91_twi_remove(struct platform_device *pdev)
-+{
-+ struct at91_twi_dev *dev = platform_get_drvdata(pdev);
-+ int rc;
-+
-+ rc = i2c_del_adapter(&dev->adapter);
-+ clk_disable_unprepare(dev->clk);
-+
-+ return rc;
-+}
-+
-+#ifdef CONFIG_PM
-+
-+static int at91_twi_runtime_suspend(struct device *dev)
-+{
-+ struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
-+
-+ clk_disable(twi_dev->clk);
-+
-+ return 0;
-+}
-+
-+static int at91_twi_runtime_resume(struct device *dev)
-+{
-+ struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
-+
-+ return clk_enable(twi_dev->clk);
-+}
-+
-+static const struct dev_pm_ops at91_twi_pm = {
-+ .runtime_suspend = at91_twi_runtime_suspend,
-+ .runtime_resume = at91_twi_runtime_resume,
-+};
-+
-+#define at91_twi_pm_ops (&at91_twi_pm)
-+#else
-+#define at91_twi_pm_ops NULL
-+#endif
-+
-+static struct platform_driver at91_twi_driver = {
-+ .probe = at91_twi_probe,
-+ .remove = __devexit_p(at91_twi_remove),
-+ .id_table = at91_twi_devtypes,
-+ .driver = {
-+ .name = "at91_i2c",
-+ .owner = THIS_MODULE,
-+ .pm = at91_twi_pm_ops,
-+ },
-+};
-+
-+static int __init at91_twi_init(void)
-+{
-+ return platform_driver_register(&at91_twi_driver);
-+}
-+
-+static void __exit at91_twi_exit(void)
-+{
-+ platform_driver_unregister(&at91_twi_driver);
-+}
-+
-+subsys_initcall(at91_twi_init);
-+module_exit(at91_twi_exit);
-+
-+MODULE_AUTHOR("Nikolaus Voss <n.voss@weinmann.de>");
-+MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:at91_i2c");
+++ /dev/null
-From 5ef32638a0ab40462ae3f103062d27b47c9f1ca0 Mon Sep 17 00:00:00 2001
-From: Nikolaus Voss <n.voss@weinmann.de>
-Date: Tue, 8 Nov 2011 12:11:03 +0100
-Subject: arm: at91: G45 TWI: remove open drain setting for twi function gpios
-
-commit 774c8018d2566207c92f47b6421dad7d88bbfd49 upstream.
-
-The G45 datasheets explicitly states that setting the open drain property
-on peripheral function gpios is not allowed. (How about other A91 chips?)
-
-Signed-off-by: Nikolaus Voss <n.voss@weinmann.de>
-Tested-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Reviewed-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
----
- arch/arm/mach-at91/at91sam9g45_devices.c | 6 ------
- 1 file changed, 6 deletions(-)
-
-diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
-index 4223d28..29f334c 100644
---- a/arch/arm/mach-at91/at91sam9g45_devices.c
-+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
-@@ -684,18 +684,12 @@ void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, in
- /* pins used for TWI interface */
- if (i2c_id == 0) {
- at91_set_A_periph(AT91_PIN_PA20, 0); /* TWD */
-- at91_set_multi_drive(AT91_PIN_PA20, 1);
--
- at91_set_A_periph(AT91_PIN_PA21, 0); /* TWCK */
-- at91_set_multi_drive(AT91_PIN_PA21, 1);
-
- platform_device_register(&at91sam9g45_twi0_device);
- } else {
- at91_set_A_periph(AT91_PIN_PB10, 0); /* TWD */
-- at91_set_multi_drive(AT91_PIN_PB10, 1);
--
- at91_set_A_periph(AT91_PIN_PB11, 0); /* TWCK */
-- at91_set_multi_drive(AT91_PIN_PB11, 1);
-
- platform_device_register(&at91sam9g45_twi1_device);
- }
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 5a1164b76ebc50a37e21818651b755787c19dc26 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Wed, 12 Sep 2012 08:42:13 +0200
-Subject: ARM: at91: do not configure at91sam9g10 twi pio as open-drain
-
-commit 94e734655fbe294c50d304547cae033e87ec229e upstream.
-
-As indicated in the datasheet, TWD and TWCK must not be programmed as
-open-drain.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Acked-by: Nikolaus Voss <n.voss@weinmann.de>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
----
- arch/arm/mach-at91/at91sam9261_devices.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
-index 3d7b2f4..d2ae522 100644
---- a/arch/arm/mach-at91/at91sam9261_devices.c
-+++ b/arch/arm/mach-at91/at91sam9261_devices.c
-@@ -329,16 +329,16 @@ void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
- /* IP version is not the same on 9261 and g10 */
- if (cpu_is_at91sam9g10()) {
- at91sam9261_twi_device.name = "i2c-at91sam9g10";
-+ /* I2C PIO must not be configured as open-drain on this chip */
- } else {
- at91sam9261_twi_device.name = "i2c-at91sam9261";
-+ at91_set_multi_drive(AT91_PIN_PA7, 1);
-+ at91_set_multi_drive(AT91_PIN_PA8, 1);
- }
-
- /* pins used for TWI interface */
- at91_set_A_periph(AT91_PIN_PA7, 0); /* TWD */
-- at91_set_multi_drive(AT91_PIN_PA7, 1);
--
- at91_set_A_periph(AT91_PIN_PA8, 0); /* TWCK */
-- at91_set_multi_drive(AT91_PIN_PA8, 1);
-
- i2c_register_board_info(0, devices, nr_devices);
- platform_device_register(&at91sam9261_twi_device);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2fdca46a8f7ee49b6f38f8d8a42c14cfaf02881b Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Wed, 12 Sep 2012 08:42:14 +0200
-Subject: i2c: at91: add dt support to i2c-at91
-
-commit 70d46a241ed3bb0d1bb2bc15720b6f7c215c37f5 upstream.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Acked-by: Nikolaus Voss <n.voss@weinmann.de>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
----
- .../devicetree/bindings/i2c/atmel-i2c.txt | 30 +++++++++++++
- drivers/i2c/busses/i2c-at91.c | 49 ++++++++++++++++++++++
- 2 files changed, 79 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/i2c/atmel-i2c.txt
-
-diff --git a/Documentation/devicetree/bindings/i2c/atmel-i2c.txt b/Documentation/devicetree/bindings/i2c/atmel-i2c.txt
-new file mode 100644
-index 0000000..b689a0d
---- /dev/null
-+++ b/Documentation/devicetree/bindings/i2c/atmel-i2c.txt
-@@ -0,0 +1,30 @@
-+I2C for Atmel platforms
-+
-+Required properties :
-+- compatible : Must be "atmel,at91rm9200-i2c", "atmel,at91sam9261-i2c",
-+ "atmel,at91sam9260-i2c", "atmel,at91sam9g20-i2c", "atmel,at91sam9g10-i2c"
-+ or "atmel,at91sam9x5-i2c"
-+- reg: physical base address of the controller and length of memory mapped
-+ region.
-+- interrupts: interrupt number to the cpu.
-+- #address-cells = <1>;
-+- #size-cells = <0>;
-+
-+Optional properties:
-+- Child nodes conforming to i2c bus binding
-+
-+Examples :
-+
-+i2c0: i2c@fff84000 {
-+ compatible = "atmel,at91sam9g20-i2c";
-+ reg = <0xfff84000 0x100>;
-+ interrupts = <12 4 6>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ 24c512@50 {
-+ compatible = "24c512";
-+ reg = <0x50>;
-+ pagesize = <128>;
-+ }
-+}
-diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
-index 78bcad0..aa59a25 100644
---- a/drivers/i2c/busses/i2c-at91.c
-+++ b/drivers/i2c/busses/i2c-at91.c
-@@ -24,6 +24,9 @@
- #include <linux/interrupt.h>
- #include <linux/io.h>
- #include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/of_i2c.h>
- #include <linux/platform_device.h>
- #include <linux/slab.h>
-
-@@ -347,6 +350,12 @@ static struct at91_twi_pdata at91sam9g10_config = {
- .has_unre_flag = false,
- };
-
-+static struct at91_twi_pdata at91sam9x5_config = {
-+ .clk_max_div = 7,
-+ .clk_offset = 4,
-+ .has_unre_flag = false,
-+};
-+
- static const struct platform_device_id at91_twi_devtypes[] = {
- {
- .name = "i2c-at91rm9200",
-@@ -368,6 +377,42 @@ static const struct platform_device_id at91_twi_devtypes[] = {
- }
- };
-
-+#if defined(CONFIG_OF)
-+static const struct of_device_id atmel_twi_dt_ids[] = {
-+ {
-+ .compatible = "atmel,at91sam9260-i2c",
-+ .data = &at91sam9260_config,
-+ } , {
-+ .compatible = "atmel,at91sam9g20-i2c",
-+ .data = &at91sam9g20_config,
-+ } , {
-+ .compatible = "atmel,at91sam9g10-i2c",
-+ .data = &at91sam9g10_config,
-+ }, {
-+ .compatible = "atmel,at91sam9x5-i2c",
-+ .data = &at91sam9x5_config,
-+ }, {
-+ /* sentinel */
-+ }
-+};
-+MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids);
-+#else
-+#define atmel_twi_dt_ids NULL
-+#endif
-+
-+static struct at91_twi_pdata * __devinit at91_twi_get_driver_data(
-+ struct platform_device *pdev)
-+{
-+ if (pdev->dev.of_node) {
-+ const struct of_device_id *match;
-+ match = of_match_node(atmel_twi_dt_ids, pdev->dev.of_node);
-+ if (!match)
-+ return NULL;
-+ return match->data;
-+ }
-+ return (struct at91_twi_pdata *) platform_get_device_id(pdev)->driver_data;
-+}
-+
- static int __devinit at91_twi_probe(struct platform_device *pdev)
- {
- struct at91_twi_dev *dev;
-@@ -423,6 +468,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
- dev->adapter.dev.parent = dev->dev;
- dev->adapter.nr = pdev->id;
- dev->adapter.timeout = AT91_I2C_TIMEOUT;
-+ dev->adapter.dev.of_node = pdev->dev.of_node;
-
- rc = i2c_add_numbered_adapter(&dev->adapter);
- if (rc) {
-@@ -432,6 +478,8 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
- return rc;
- }
-
-+ of_i2c_register_devices(&dev->adapter);
-+
- dev_info(dev->dev, "AT91 i2c bus driver.\n");
- return 0;
- }
-@@ -482,6 +530,7 @@ static struct platform_driver at91_twi_driver = {
- .driver = {
- .name = "at91_i2c",
- .owner = THIS_MODULE,
-+ .of_match_table = atmel_twi_dt_ids,
- .pm = at91_twi_pm_ops,
- },
- };
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2724054c26f7d6f755ddd75a8e0ad93f63db6e96 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 22 Oct 2012 15:53:10 +0200
-Subject: ARM: at91: add clocks for I2C DT entries
-
-commit f7d19b9065569268dd13307213c40d168fb0be82 upstream.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Acked-by: Nikolaus Voss <n.voss@weinmann.de>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-
-Conflicts:
- arch/arm/mach-at91/at91sam9263.c
- arch/arm/mach-at91/at91sam9g45.c
- arch/arm/mach-at91/at91sam9x5.c
----
- arch/arm/mach-at91/at91sam9260.c | 1 +
- arch/arm/mach-at91/at91sam9263.c | 1 +
- arch/arm/mach-at91/at91sam9g45.c | 2 ++
- arch/arm/mach-at91/at91sam9n12.c | 2 ++
- arch/arm/mach-at91/at91sam9x5.c | 3 +++
- 5 files changed, 9 insertions(+)
-
-diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
-index a936c15..040f79a 100644
---- a/arch/arm/mach-at91/at91sam9260.c
-+++ b/arch/arm/mach-at91/at91sam9260.c
-@@ -213,6 +213,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("usart", "fffd0000.serial", &usart3_clk),
- CLKDEV_CON_DEV_ID("usart", "fffd4000.serial", &usart4_clk),
- CLKDEV_CON_DEV_ID("usart", "fffd8000.serial", &usart5_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffac000.i2c", &twi_clk),
- /* more tc lookup table for DT entries */
- CLKDEV_CON_DEV_ID("t0_clk", "fffa0000.timer", &tc0_clk),
- CLKDEV_CON_DEV_ID("t1_clk", "fffa0000.timer", &tc1_clk),
-diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
-index d49cfe9..00723ec 100644
---- a/arch/arm/mach-at91/at91sam9263.c
-+++ b/arch/arm/mach-at91/at91sam9263.c
-@@ -213,6 +213,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("spi_clk", "fffa8000.spi", &spi1_clk),
- CLKDEV_CON_DEV_ID("mci_clk", "fff80000.mmc", &mmc0_clk),
- CLKDEV_CON_DEV_ID("mci_clk", "fff84000.mmc", &mmc1_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi_clk),
- };
-
- static struct clk_lookup usart_clocks_lookups[] = {
-diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
-index 7d5ac91..7ccbf9c 100644
---- a/arch/arm/mach-at91/at91sam9g45.c
-+++ b/arch/arm/mach-at91/at91sam9g45.c
-@@ -240,6 +240,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("ehci_clk", "800000.ehci", &uhphs_clk),
- CLKDEV_CON_DEV_ID("mci_clk", "fff80000.mmc", &mmc0_clk),
- CLKDEV_CON_DEV_ID("mci_clk", "fffd0000.mmc", &mmc1_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fff84000.i2c", &twi0_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi1_clk),
- /* fake hclk clock */
- CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
- CLKDEV_CON_ID("pioA", &pioA_clk),
-diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c
-index cce4e0f..ebe94bb 100644
---- a/arch/arm/mach-at91/at91sam9n12.c
-+++ b/arch/arm/mach-at91/at91sam9n12.c
-@@ -170,6 +170,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb_clk),
- CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc_clk),
- CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
- CLKDEV_CON_ID("pioA", &pioAB_clk),
- CLKDEV_CON_ID("pioB", &pioAB_clk),
- CLKDEV_CON_ID("pioC", &pioCD_clk),
-diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
-index 15ac57b..f40c1ab 100644
---- a/arch/arm/mach-at91/at91sam9x5.c
-+++ b/arch/arm/mach-at91/at91sam9x5.c
-@@ -230,6 +230,9 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID(NULL, "at91_i2c.0", &twi0_clk),
- CLKDEV_CON_DEV_ID(NULL, "at91_i2c.1", &twi1_clk),
- CLKDEV_CON_DEV_ID(NULL, "at91_i2c.2", &twi2_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "f8018000.i2c", &twi2_clk),
- CLKDEV_CON_ID("pioA", &pioAB_clk),
- CLKDEV_CON_ID("pioB", &pioAB_clk),
- CLKDEV_CON_ID("pioC", &pioCD_clk),
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 21e4af4484eeb15cdc5e79f2ec5655598c5bc8bc Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Wed, 12 Sep 2012 08:42:16 +0200
-Subject: ARM: dts: add twi nodes for atmel SoCs
-
-commit 05dcd361a2785c3fcb9c43a621da4434cf1519b4 upstream.
-
-Add TWI nodes for atmel SoCs but keep i2c-gpio ones in order to let the
-choice to the user in dts files.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
----
- arch/arm/boot/dts/at91sam9260.dtsi | 10 ++++++++++
- arch/arm/boot/dts/at91sam9263.dtsi | 10 ++++++++++
- arch/arm/boot/dts/at91sam9g20.dtsi | 8 ++++++++
- arch/arm/boot/dts/at91sam9g45.dtsi | 20 ++++++++++++++++++++
- arch/arm/boot/dts/at91sam9n12.dtsi | 20 ++++++++++++++++++++
- arch/arm/boot/dts/at91sam9x5.dtsi | 30 ++++++++++++++++++++++++++++++
- 6 files changed, 98 insertions(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
-index 8d95e83c..0352bf8 100644
---- a/arch/arm/boot/dts/at91sam9260.dtsi
-+++ b/arch/arm/boot/dts/at91sam9260.dtsi
-@@ -28,6 +28,7 @@
- gpio2 = &pioC;
- tcb0 = &tcb0;
- tcb1 = &tcb1;
-+ i2c0 = &i2c0;
- };
- cpus {
- cpu@0 {
-@@ -210,6 +211,15 @@
- #address-cells = <1>;
- #size-cells = <0>;
- };
-+
-+ i2c0: i2c@fffac000 {
-+ compatible = "atmel,at91sam9260-i2c";
-+ reg = <0xfffac000 0x100>;
-+ interrupts = <11 4 6>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
- };
-
- nand0: nand@40000000 {
-diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
-index 54e6984..26ab452 100644
---- a/arch/arm/boot/dts/at91sam9263.dtsi
-+++ b/arch/arm/boot/dts/at91sam9263.dtsi
-@@ -24,6 +24,7 @@
- gpio3 = &pioD;
- gpio4 = &pioE;
- tcb0 = &tcb0;
-+ i2c0 = &i2c0;
- };
- cpus {
- cpu@0 {
-@@ -203,6 +204,15 @@
- #address-cells = <1>;
- #size-cells = <0>;
- };
-+
-+ i2c0: i2c@fff88000 {
-+ compatible = "atmel,at91sam9263-i2c";
-+ reg = <0xfff88000 0x100>;
-+ interrupts = <13 4 6>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
- };
-
- nand0: nand@40000000 {
-diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi
-index 0eb1a75..4537a74 100644
---- a/arch/arm/boot/dts/at91sam9g20.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g20.dtsi
-@@ -15,4 +15,12 @@
- memory {
- reg = <0x20000000 0x08000000>;
- };
-+
-+ ahb {
-+ apb {
-+ i2c0: i2c@fffac000 {
-+ compatible = "atmel,at91sam9g20-i2c";
-+ };
-+ };
-+ };
- };
-diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
-index da135f9..b032a8c 100644
---- a/arch/arm/boot/dts/at91sam9g45.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
-@@ -29,6 +29,8 @@
- gpio4 = &pioE;
- tcb0 = &tcb0;
- tcb1 = &tcb1;
-+ i2c0 = &i2c0;
-+ i2c1 = &i2c1;
- };
- cpus {
- cpu@0 {
-@@ -223,6 +225,24 @@
- #address-cells = <1>;
- #size-cells = <0>;
- };
-+
-+ i2c0: i2c@fff84000 {
-+ compatible = "atmel,at91sam9g10-i2c";
-+ reg = <0xfff84000 0x100>;
-+ interrupts = <12 4 6>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
-+ i2c1: i2c@fff88000 {
-+ compatible = "atmel,at91sam9g10-i2c";
-+ reg = <0xfff88000 0x100>;
-+ interrupts = <13 4 6>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
- };
-
- nand0: nand@40000000 {
-diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
-index 42d5fc2..0d08c4e 100644
---- a/arch/arm/boot/dts/at91sam9n12.dtsi
-+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
-@@ -26,6 +26,8 @@
- gpio3 = &pioD;
- tcb0 = &tcb0;
- tcb1 = &tcb1;
-+ i2c0 = &i2c0;
-+ i2c1 = &i2c1;
- };
- cpus {
- cpu@0 {
-@@ -191,6 +193,24 @@
- atmel,use-dma-tx;
- status = "disabled";
- };
-+
-+ i2c0: i2c@f8010000 {
-+ compatible = "atmel,at91sam9x5-i2c";
-+ reg = <0xf8010000 0x100>;
-+ interrupts = <9 4 6>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
-+ i2c1: i2c@f8014000 {
-+ compatible = "atmel,at91sam9x5-i2c";
-+ reg = <0xf8014000 0x100>;
-+ interrupts = <10 4 6>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
- };
-
- nand0: nand@40000000 {
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index ad7016a..fec3316 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -27,6 +27,9 @@
- gpio3 = &pioD;
- tcb0 = &tcb0;
- tcb1 = &tcb1;
-+ i2c0 = &i2c0;
-+ i2c1 = &i2c1;
-+ i2c2 = &i2c2;
- };
- cpus {
- cpu@0 {
-@@ -213,6 +216,33 @@
- #address-cells = <1>;
- #size-cells = <0>;
- };
-+
-+ i2c0: i2c@f8010000 {
-+ compatible = "atmel,at91sam9x5-i2c";
-+ reg = <0xf8010000 0x100>;
-+ interrupts = <9 4 6>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
-+ i2c1: i2c@f8014000 {
-+ compatible = "atmel,at91sam9x5-i2c";
-+ reg = <0xf8014000 0x100>;
-+ interrupts = <10 4 6>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
-+ i2c2: i2c@f8018000 {
-+ compatible = "atmel,at91sam9x5-i2c";
-+ reg = <0xf8018000 0x100>;
-+ interrupts = <11 4 6>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
- };
-
- nand0: nand@40000000 {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From dbdd2b87e86567c31fa90d1d72ee974306a3c8c7 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 22 Oct 2012 15:53:27 +0200
-Subject: ARM: dts: add twi nodes for atmel boards
-
-commit fbc1871511ed201504d6e5b36f13ea77e4be2907 upstream.
-
-Still use i2c-gpio on boards which have a SoC with a TWI IP which
-doesn't have clock stretching in transmission mode.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-
-Conflicts:
- arch/arm/boot/dts/at91sam9g25ek.dts
- arch/arm/boot/dts/at91sam9m10g45ek.dts
- arch/arm/boot/dts/at91sam9n12ek.dts
----
- arch/arm/boot/dts/at91sam9g25ek.dts | 12 ++++++++++++
- arch/arm/boot/dts/at91sam9m10g45ek.dts | 8 ++++++++
- arch/arm/boot/dts/at91sam9n12ek.dts | 8 ++++++++
- 3 files changed, 28 insertions(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts
-index 4857e6c..5b054e4 100644
---- a/arch/arm/boot/dts/at91sam9g25ek.dts
-+++ b/arch/arm/boot/dts/at91sam9g25ek.dts
-@@ -50,6 +50,18 @@
- cd-gpios = <&pioD 14 0>;
- };
- };
-+
-+ i2c0: i2c@f8010000 {
-+ status = "okay";
-+ };
-+
-+ i2c1: i2c@f8014000 {
-+ status = "okay";
-+ };
-+
-+ i2c2: i2c@f8018000 {
-+ status = "okay";
-+ };
- };
-
- usb0: ohci@00600000 {
-diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts
-index 7a7b571..6a4aedd 100644
---- a/arch/arm/boot/dts/at91sam9m10g45ek.dts
-+++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts
-@@ -65,6 +65,14 @@
- wp-gpios = <&pioD 29 0>;
- };
- };
-+
-+ i2c0: i2c@fff84000 {
-+ status = "okay";
-+ };
-+
-+ i2c1: i2c@fff88000 {
-+ status = "okay";
-+ };
- };
-
- nand0: nand@40000000 {
-diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts
-index 44b42d9..ccc94de 100644
---- a/arch/arm/boot/dts/at91sam9n12ek.dts
-+++ b/arch/arm/boot/dts/at91sam9n12ek.dts
-@@ -46,6 +46,14 @@
- cd-gpios = <&pioA 7 0>;
- };
- };
-+
-+ i2c0: i2c@f8010000 {
-+ status = "okay";
-+ };
-+
-+ i2c1: i2c@f8014000 {
-+ status = "okay";
-+ };
- };
-
- nand0: nand@40000000 {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From f8a2c18935b2f0955623ca0c59ba8832485a47c3 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Fri, 14 Sep 2012 16:04:55 +0200
-Subject: i2c: at91: add dma support
-
-Add dma support for Atmel TWI which is available on sam9x5 and later.
-
-When using dma for reception, you have to read only n-2 bytes. The last
-two bytes are read manually. Don't doing this should cause to send the
-STOP command too late and then to get extra data in the receive
-register.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- drivers/i2c/busses/i2c-at91.c | 326 ++++++++++++++++++++++++++++++++++++++++--
- 1 file changed, 314 insertions(+), 12 deletions(-)
-
-diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
-index aa59a25..33219f8 100644
---- a/drivers/i2c/busses/i2c-at91.c
-+++ b/drivers/i2c/busses/i2c-at91.c
-@@ -19,6 +19,8 @@
-
- #include <linux/clk.h>
- #include <linux/completion.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/dmaengine.h>
- #include <linux/err.h>
- #include <linux/i2c.h>
- #include <linux/interrupt.h>
-@@ -30,6 +32,8 @@
- #include <linux/platform_device.h>
- #include <linux/slab.h>
-
-+#include <mach/at_hdmac.h>
-+
- #define TWI_CLK_HZ 100000 /* max 400 Kbits/s */
- #define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */
-
-@@ -65,9 +69,21 @@
- #define AT91_TWI_THR 0x0034 /* Transmit Holding Register */
-
- struct at91_twi_pdata {
-- unsigned clk_max_div;
-- unsigned clk_offset;
-- bool has_unre_flag;
-+ unsigned clk_max_div;
-+ unsigned clk_offset;
-+ bool has_unre_flag;
-+ bool has_dma_support;
-+ struct at_dma_slave dma_slave;
-+};
-+
-+struct at91_twi_dma {
-+ struct dma_chan *chan_rx;
-+ struct dma_chan *chan_tx;
-+ struct scatterlist sg;
-+ struct dma_async_tx_descriptor *data_desc;
-+ enum dma_data_direction direction;
-+ bool buf_mapped;
-+ bool xfer_in_progress;
- };
-
- struct at91_twi_dev {
-@@ -79,10 +95,13 @@ struct at91_twi_dev {
- size_t buf_len;
- struct i2c_msg *msg;
- int irq;
-+ unsigned imr;
- unsigned transfer_status;
- struct i2c_adapter adapter;
- unsigned twi_cwgr_reg;
- struct at91_twi_pdata *pdata;
-+ bool use_dma;
-+ struct at91_twi_dma dma;
- };
-
- static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg)
-@@ -98,7 +117,18 @@ static void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, unsigned val)
- static void at91_disable_twi_interrupts(struct at91_twi_dev *dev)
- {
- at91_twi_write(dev, AT91_TWI_IDR,
-- AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY);
-+ AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY);
-+}
-+
-+static void at91_twi_irq_save(struct at91_twi_dev *dev)
-+{
-+ dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & 0x7;
-+ at91_disable_twi_interrupts(dev);
-+}
-+
-+static void at91_twi_irq_restore(struct at91_twi_dev *dev)
-+{
-+ at91_twi_write(dev, AT91_TWI_IER, dev->imr);
- }
-
- static void at91_init_twi_bus(struct at91_twi_dev *dev)
-@@ -137,6 +167,30 @@ static void __devinit at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
- dev_dbg(dev->dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv);
- }
-
-+static void at91_twi_dma_cleanup(struct at91_twi_dev *dev)
-+{
-+ struct at91_twi_dma *dma = &dev->dma;
-+
-+ at91_twi_irq_save(dev);
-+
-+ if (dma->xfer_in_progress) {
-+ if (dma->direction == DMA_FROM_DEVICE)
-+ dma->chan_rx->device->device_control(dma->chan_rx,
-+ DMA_TERMINATE_ALL, 0);
-+ else
-+ dma->chan_tx->device->device_control(dma->chan_tx,
-+ DMA_TERMINATE_ALL, 0);
-+ dma->xfer_in_progress = false;
-+ }
-+ if (dma->buf_mapped) {
-+ dma_unmap_single(dev->dev, sg_dma_address(&dma->sg),
-+ dev->buf_len, dma->direction);
-+ dma->buf_mapped = false;
-+ }
-+
-+ at91_twi_irq_restore(dev);
-+}
-+
- static void at91_twi_write_next_byte(struct at91_twi_dev *dev)
- {
- if (dev->buf_len <= 0)
-@@ -153,6 +207,65 @@ static void at91_twi_write_next_byte(struct at91_twi_dev *dev)
- ++dev->buf;
- }
-
-+static void at91_twi_write_data_dma_callback(void *data)
-+{
-+ struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
-+
-+ dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
-+ dev->buf_len, DMA_TO_DEVICE);
-+
-+ at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
-+}
-+
-+static void at91_twi_write_data_dma(struct at91_twi_dev *dev)
-+{
-+ dma_addr_t dma_addr;
-+ dma_cookie_t cookie;
-+ struct dma_async_tx_descriptor *txdesc;
-+ struct at91_twi_dma *dma = &dev->dma;
-+ struct dma_chan *chan_tx = dma->chan_tx;
-+
-+ if (dev->buf_len <= 0)
-+ return;
-+
-+ dma->direction = DMA_TO_DEVICE;
-+
-+ at91_twi_irq_save(dev);
-+ dma_addr = dma_map_single(dev->dev, dev->buf, dev->buf_len,
-+ DMA_TO_DEVICE);
-+ if (dma_mapping_error(dev->dev, dma_addr)) {
-+ dev_err(dev->dev, "dma map failed\n");
-+ return;
-+ }
-+ dma->buf_mapped = true;
-+ at91_twi_irq_restore(dev);
-+ sg_dma_len(&dma->sg) = dev->buf_len;
-+ sg_dma_address(&dma->sg) = dma_addr;
-+
-+ txdesc = chan_tx->device->device_prep_slave_sg(chan_tx, &dma->sg,
-+ 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK, NULL);
-+ if (!txdesc) {
-+ dev_err(dev->dev, "dma prep slave sg failed\n");
-+ goto error;
-+ }
-+
-+ txdesc->callback = at91_twi_write_data_dma_callback;
-+ txdesc->callback_param = dev;
-+
-+ dma->xfer_in_progress = true;
-+ cookie = txdesc->tx_submit(txdesc);
-+ if (dma_submit_error(cookie)) {
-+ dev_err(dev->dev, "dma submit error\n");
-+ goto error;
-+ }
-+ dma->chan_tx->device->device_issue_pending(chan_tx);
-+
-+ return;
-+
-+error:
-+ at91_twi_dma_cleanup(dev);
-+}
-+
- static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
- {
- if (dev->buf_len <= 0)
-@@ -178,6 +291,66 @@ static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
- ++dev->buf;
- }
-
-+static void at91_twi_read_data_dma_callback(void *data)
-+{
-+ struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
-+
-+ dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
-+ dev->buf_len, DMA_FROM_DEVICE);
-+
-+ /* The last two bytes have to be read without using dma */
-+ dev->buf += dev->buf_len - 2;
-+ dev->buf_len = 2;
-+ at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_RXRDY);
-+}
-+
-+static void at91_twi_read_data_dma(struct at91_twi_dev *dev)
-+{
-+ dma_addr_t dma_addr;
-+ dma_cookie_t cookie;
-+ struct dma_async_tx_descriptor *rxdesc;
-+ struct at91_twi_dma *dma = &dev->dma;
-+ struct dma_chan *chan_rx = dma->chan_rx;
-+
-+ dma->direction = DMA_FROM_DEVICE;
-+
-+ /* Keep in mind that we won't use dma to read the last two bytes */
-+ at91_twi_irq_save(dev);
-+ dma_addr = dma_map_single(dev->dev, dev->buf, dev->buf_len - 2,
-+ DMA_FROM_DEVICE);
-+ if (dma_mapping_error(dev->dev, dma_addr)) {
-+ dev_err(dev->dev, "dma map failed\n");
-+ return;
-+ }
-+ dma->buf_mapped = true;
-+ at91_twi_irq_restore(dev);
-+ dma->sg.dma_address = dma_addr;
-+ sg_dma_len(&dma->sg) = dev->buf_len - 2;
-+
-+ rxdesc = chan_rx->device->device_prep_slave_sg(chan_rx, &dma->sg,
-+ 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK, NULL);
-+ if (!rxdesc) {
-+ dev_err(dev->dev, "dma prep slave sg failed\n");
-+ goto error;
-+ }
-+
-+ rxdesc->callback = at91_twi_read_data_dma_callback;
-+ rxdesc->callback_param = dev;
-+
-+ dma->xfer_in_progress = true;
-+ cookie = rxdesc->tx_submit(rxdesc);
-+ if (dma_submit_error(cookie)) {
-+ dev_err(dev->dev, "dma submit error\n");
-+ goto error;
-+ }
-+ dma->chan_rx->device->device_issue_pending(dma->chan_rx);
-+
-+ return;
-+
-+error:
-+ at91_twi_dma_cleanup(dev);
-+}
-+
- static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
- {
- struct at91_twi_dev *dev = dev_id;
-@@ -224,12 +397,36 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
- if (dev->buf_len <= 1 && !(dev->msg->flags & I2C_M_RECV_LEN))
- start_flags |= AT91_TWI_STOP;
- at91_twi_write(dev, AT91_TWI_CR, start_flags);
-- at91_twi_write(dev, AT91_TWI_IER,
-+ /*
-+ * When using dma, the last byte has to be read manually in
-+ * order to not send the stop command too late and then
-+ * to receive extra data. In practice, there are some issues
-+ * if you use the dma to read n-1 bytes because of latency.
-+ * Reading n-2 bytes with dma and the two last ones manually
-+ * seems to be the best solution.
-+ */
-+ if (dev->use_dma && (dev->buf_len > 2)) {
-+ at91_twi_read_data_dma(dev);
-+ /*
-+ * It is important to enable TXCOMP irq here because
-+ * doing it only when transferring the last two bytes
-+ * will mask NACK errors since TXCOMP is set when a
-+ * NACK occurs.
-+ */
-+ at91_twi_write(dev, AT91_TWI_IER,
-+ AT91_TWI_TXCOMP);
-+ } else
-+ at91_twi_write(dev, AT91_TWI_IER,
- AT91_TWI_TXCOMP | AT91_TWI_RXRDY);
- } else {
-- at91_twi_write_next_byte(dev);
-- at91_twi_write(dev, AT91_TWI_IER,
-- AT91_TWI_TXCOMP | AT91_TWI_TXRDY);
-+ if (dev->use_dma) {
-+ at91_twi_write_data_dma(dev);
-+ at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP);
-+ } else {
-+ at91_twi_write_next_byte(dev);
-+ at91_twi_write(dev, AT91_TWI_IER,
-+ AT91_TWI_TXCOMP | AT91_TWI_TXRDY);
-+ }
- }
-
- ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
-@@ -237,23 +434,31 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
- if (ret == 0) {
- dev_err(dev->dev, "controller timed out\n");
- at91_init_twi_bus(dev);
-- return -ETIMEDOUT;
-+ ret = -ETIMEDOUT;
-+ goto error;
- }
- if (dev->transfer_status & AT91_TWI_NACK) {
- dev_dbg(dev->dev, "received nack\n");
-- return -EREMOTEIO;
-+ ret = -EREMOTEIO;
-+ goto error;
- }
- if (dev->transfer_status & AT91_TWI_OVRE) {
- dev_err(dev->dev, "overrun while reading\n");
-- return -EIO;
-+ ret = -EIO;
-+ goto error;
- }
- if (has_unre_flag && dev->transfer_status & AT91_TWI_UNRE) {
- dev_err(dev->dev, "underrun while writing\n");
-- return -EIO;
-+ ret = -EIO;
-+ goto error;
- }
- dev_dbg(dev->dev, "transfer complete\n");
-
- return 0;
-+
-+error:
-+ at91_twi_dma_cleanup(dev);
-+ return ret;
- }
-
- static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
-@@ -324,36 +529,42 @@ static struct at91_twi_pdata at91rm9200_config = {
- .clk_max_div = 5,
- .clk_offset = 3,
- .has_unre_flag = true,
-+ .has_dma_support = false,
- };
-
- static struct at91_twi_pdata at91sam9261_config = {
- .clk_max_div = 5,
- .clk_offset = 4,
- .has_unre_flag = false,
-+ .has_dma_support = false,
- };
-
- static struct at91_twi_pdata at91sam9260_config = {
- .clk_max_div = 7,
- .clk_offset = 4,
- .has_unre_flag = false,
-+ .has_dma_support = false,
- };
-
- static struct at91_twi_pdata at91sam9g20_config = {
- .clk_max_div = 7,
- .clk_offset = 4,
- .has_unre_flag = false,
-+ .has_dma_support = false,
- };
-
- static struct at91_twi_pdata at91sam9g10_config = {
- .clk_max_div = 7,
- .clk_offset = 4,
- .has_unre_flag = false,
-+ .has_dma_support = false,
- };
-
- static struct at91_twi_pdata at91sam9x5_config = {
- .clk_max_div = 7,
- .clk_offset = 4,
- .has_unre_flag = false,
-+ .has_dma_support = true,
- };
-
- static const struct platform_device_id at91_twi_devtypes[] = {
-@@ -400,6 +611,90 @@ MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids);
- #define atmel_twi_dt_ids NULL
- #endif
-
-+static bool __devinit filter(struct dma_chan *chan, void *slave)
-+{
-+ struct at_dma_slave *sl = slave;
-+
-+ if (sl->dma_dev == chan->device->dev) {
-+ chan->private = sl;
-+ return true;
-+ } else {
-+ return false;
-+ }
-+}
-+
-+static int __devinit at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr)
-+{
-+ int ret = 0;
-+ struct at_dma_slave *sdata;
-+ struct dma_slave_config slave_config;
-+ struct at91_twi_dma *dma = &dev->dma;
-+
-+ sdata = &dev->pdata->dma_slave;
-+
-+ memset(&slave_config, 0, sizeof(slave_config));
-+ slave_config.src_addr = (dma_addr_t)phy_addr + AT91_TWI_RHR;
-+ slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-+ slave_config.src_maxburst = 1;
-+ slave_config.dst_addr = (dma_addr_t)phy_addr + AT91_TWI_THR;
-+ slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-+ slave_config.dst_maxburst = 1;
-+ slave_config.device_fc = false;
-+
-+ if (sdata && sdata->dma_dev) {
-+ dma_cap_mask_t mask;
-+
-+ dma_cap_zero(mask);
-+ dma_cap_set(DMA_SLAVE, mask);
-+ dma->chan_tx = dma_request_channel(mask, filter, sdata);
-+ if (!dma->chan_tx) {
-+ dev_err(dev->dev, "no DMA channel available for tx\n");
-+ ret = -EBUSY;
-+ goto error;
-+ }
-+ dma->chan_rx = dma_request_channel(mask, filter, sdata);
-+ if (!dma->chan_rx) {
-+ dev_err(dev->dev, "no DMA channel available for rx\n");
-+ ret = -EBUSY;
-+ goto error;
-+ }
-+ } else {
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ slave_config.direction = DMA_TO_DEVICE;
-+ if (dmaengine_slave_config(dma->chan_tx, &slave_config)) {
-+ dev_err(dev->dev, "failed to configure tx channel\n");
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ slave_config.direction = DMA_FROM_DEVICE;
-+ if (dmaengine_slave_config(dma->chan_rx, &slave_config)) {
-+ dev_err(dev->dev, "failed to configure rx channel\n");
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ sg_init_table(&dma->sg, 1);
-+ dma->buf_mapped = false;
-+ dma->xfer_in_progress = false;
-+
-+ dev_info(dev->dev, "using %s (tx) and %s (rx) for DMA transfers\n",
-+ dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx));
-+
-+ return ret;
-+
-+error:
-+ dev_info(dev->dev, "can't use DMA\n");
-+ if (dma->chan_rx)
-+ dma_release_channel(dma->chan_rx);
-+ if (dma->chan_tx)
-+ dma_release_channel(dma->chan_tx);
-+ return ret;
-+}
-+
- static struct at91_twi_pdata * __devinit at91_twi_get_driver_data(
- struct platform_device *pdev)
- {
-@@ -418,6 +713,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
- struct at91_twi_dev *dev;
- struct resource *mem;
- int rc;
-+ u32 phy_addr;
-
- dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
- if (!dev)
-@@ -428,6 +724,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem)
- return -ENODEV;
-+ phy_addr = mem->start;
-
- dev->pdata = at91_twi_get_driver_data(pdev);
- if (!dev->pdata)
-@@ -457,6 +754,11 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
- }
- clk_prepare_enable(dev->clk);
-
-+ if (dev->pdata->has_dma_support) {
-+ if (at91_twi_configure_dma(dev, phy_addr) == 0)
-+ dev->use_dma = true;
-+ }
-+
- at91_calc_twi_clock(dev, TWI_CLK_HZ);
- at91_init_twi_bus(dev);
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 864c6c3dcb6dbdd5ff29c3ddd2a43aa758b9d9ea Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Tue, 18 Sep 2012 18:32:38 +0200
-Subject: i2c: at91: backport fix for devm_clk_get
-
-i2c-at91 is backported from a 3.6, devm_clk_get is not yet implemented
-on 3.4.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- drivers/i2c/busses/i2c-at91.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
-index 33219f8..296c430 100644
---- a/drivers/i2c/busses/i2c-at91.c
-+++ b/drivers/i2c/busses/i2c-at91.c
-@@ -747,7 +747,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
-
- platform_set_drvdata(pdev, dev);
-
-- dev->clk = devm_clk_get(dev->dev, NULL);
-+ dev->clk = clk_get(dev->dev, NULL);
- if (IS_ERR(dev->clk)) {
- dev_err(dev->dev, "no clock defined\n");
- return -ENODEV;
-@@ -777,6 +777,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
- dev_err(dev->dev, "Adapter %s registration failed\n",
- dev->adapter.name);
- clk_disable_unprepare(dev->clk);
-+ clk_put(dev->clk);
- return rc;
- }
-
-@@ -793,6 +794,7 @@ static int __devexit at91_twi_remove(struct platform_device *pdev)
-
- rc = i2c_del_adapter(&dev->adapter);
- clk_disable_unprepare(dev->clk);
-+ clk_put(dev->clk);
-
- return rc;
- }
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2fcde4a50eec3c26971c7c2095f56b6d9f21b1c7 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 22 Oct 2012 16:00:47 +0200
-Subject: i2c: at91: add dt property for DMA configuration
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-
-Conflicts:
- arch/arm/boot/dts/at91sam9x5.dtsi
----
- arch/arm/boot/dts/at91sam9x5.dtsi | 5 ++++
- drivers/i2c/busses/i2c-at91.c | 56 ++++++++++++++++++++++++++++++++++++++-
- 2 files changed, 60 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index fec3316..79718e7 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -103,12 +103,14 @@
- compatible = "atmel,at91sam9g45-dma";
- reg = <0xffffec00 0x200>;
- interrupts = <20 4 0>;
-+ #dma-cells = <1>;
- };
-
- dma1: dma-controller@ffffee00 {
- compatible = "atmel,at91sam9g45-dma";
- reg = <0xffffee00 0x200>;
- interrupts = <21 4 0>;
-+ #dma-cells = <1>;
- };
-
- pioA: gpio@fffff400 {
-@@ -221,6 +223,7 @@
- compatible = "atmel,at91sam9x5-i2c";
- reg = <0xf8010000 0x100>;
- interrupts = <9 4 6>;
-+ dma = <&dma0 0x10002278>;
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
-@@ -230,6 +233,7 @@
- compatible = "atmel,at91sam9x5-i2c";
- reg = <0xf8014000 0x100>;
- interrupts = <10 4 6>;
-+ dma = <&dma1 0x10002256>;
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
-@@ -239,6 +243,7 @@
- compatible = "atmel,at91sam9x5-i2c";
- reg = <0xf8018000 0x100>;
- interrupts = <11 4 6>;
-+ dma = <&dma0 0x1000229A>;
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
-diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
-index 296c430..c004b34 100644
---- a/drivers/i2c/busses/i2c-at91.c
-+++ b/drivers/i2c/busses/i2c-at91.c
-@@ -589,6 +589,55 @@ static const struct platform_device_id at91_twi_devtypes[] = {
- };
-
- #if defined(CONFIG_OF)
-+static int at91_twi_of_init(struct device_node *np, struct at_dma_slave *atslave)
-+{
-+ struct of_phandle_args dma_spec;
-+ struct device_node *dmac_np;
-+ struct platform_device *dmac_pdev;
-+ const __be32 *nbcells;
-+ int ret;
-+
-+ ret = of_parse_phandle_with_args(np, "dma", "#dma-cells", 0, &dma_spec);
-+ if (ret || !dma_spec.np) {
-+ pr_err("%s: can't parse dma property (%d)\n", np->full_name, ret);
-+ goto err0;
-+ }
-+ dmac_np = dma_spec.np;
-+
-+ /* check property format */
-+ nbcells = of_get_property(dmac_np, "#dma-cells", NULL);
-+ if (!nbcells) {
-+ pr_err("%s: #dma-cells property is required\n", np->full_name);
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ if (dma_spec.args_count != be32_to_cpup(nbcells)
-+ || dma_spec.args_count != 1) {
-+ pr_err("%s: wrong #dma-cells for %s\n",
-+ np->full_name, dmac_np->full_name);
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ dmac_pdev = of_find_device_by_node(dmac_np);
-+ if (!dmac_pdev) {
-+ pr_err("%s: unable to find pdev from DMA controller\n",
-+ dmac_np->full_name);
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ atslave->dma_dev = &dmac_pdev->dev;
-+ atslave->cfg = dma_spec.args[0];
-+
-+err1:
-+ of_node_put(dma_spec.np);
-+err0:
-+ pr_debug("%s exited with status %d\n", __func__, ret);
-+ return ret;
-+}
-+
- static const struct of_device_id atmel_twi_dt_ids[] = {
- {
- .compatible = "atmel,at91sam9260-i2c",
-@@ -608,6 +657,10 @@ static const struct of_device_id atmel_twi_dt_ids[] = {
- };
- MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids);
- #else
-+static int at91_twi_of_init(struct device_node *np, struct at_dma_slave *atslave)
-+{
-+ return -ENODEV;
-+}
- #define atmel_twi_dt_ids NULL
- #endif
-
-@@ -755,7 +808,8 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
- clk_prepare_enable(dev->clk);
-
- if (dev->pdata->has_dma_support) {
-- if (at91_twi_configure_dma(dev, phy_addr) == 0)
-+ if ( at91_twi_of_init(pdev->dev.of_node, &dev->pdata->dma_slave) == 0
-+ && at91_twi_configure_dma(dev, phy_addr) == 0)
- dev->use_dma = true;
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a68cb9084fc130e4137f2050cee1de250f038899 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 24 Sep 2012 12:12:27 +0200
-Subject: ARM: at91: add MCI DMA for at91sam9x5.dtsi
-
-Temporary cfg hack
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/at91sam9x5.dtsi | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index 79718e7..88907db 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -208,6 +208,7 @@
- status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
-+ dma = <&dma0 0x10002200>;
- };
-
- mmc1: mmc@f000c000 {
-@@ -217,6 +218,7 @@
- status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
-+ dma = <&dma1 0x10002200>;
- };
-
- i2c0: i2c@f8010000 {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 68814f3931e1e284d2f8270218f83333765b8c00 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Wed, 19 Sep 2012 09:27:02 +0200
-Subject: ARM: at91: add i2c and qt1070 pin muxing
-
-Pin mux is temporary done in board-dt file.
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- arch/arm/mach-at91/board-dt.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
-index e8f45c4..9355d77 100644
---- a/arch/arm/mach-at91/board-dt.c
-+++ b/arch/arm/mach-at91/board-dt.c
-@@ -43,6 +43,14 @@ static void __init at91_dt_init_irq(void)
- static void __init at91_dt_device_init(void)
- {
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-+ /* Temporary pin mux stuff */
-+ if (of_machine_is_compatible("atmel,at91sam9x5")) {
-+ at91_set_A_periph(AT91_PIN_PA30, 0); /* TWD */
-+ at91_set_A_periph(AT91_PIN_PA31, 0); /* TWCK */
-+ printk("AT91: i2c pin mux done\n");
-+ at91_set_gpio_input(AT91_PIN_PA7, 1);
-+ printk("AT91: qt1070 pin mux done\n");
-+ }
- }
-
- static const char *at91_dt_board_compat[] __initdata = {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 3d6072e790e82ecbfbb3dfc84e22ba325db16f92 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 24 Sep 2012 12:27:10 +0200
-Subject: AT91: board-dt add mci pinmux for 9x5
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/board-dt.c | 24 ++++++++++++++++++++++++
- 1 file changed, 24 insertions(+)
-
-diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
-index 9355d77..15830cb 100644
---- a/arch/arm/mach-at91/board-dt.c
-+++ b/arch/arm/mach-at91/board-dt.c
-@@ -50,6 +50,30 @@ static void __init at91_dt_device_init(void)
- printk("AT91: i2c pin mux done\n");
- at91_set_gpio_input(AT91_PIN_PA7, 1);
- printk("AT91: qt1070 pin mux done\n");
-+
-+ at91_set_gpio_input(AT91_PIN_PD14, 1);
-+ at91_set_deglitch(AT91_PIN_PD14, 1);
-+ at91_set_gpio_input(AT91_PIN_PD15, 1);
-+ at91_set_deglitch(AT91_PIN_PD15, 1);
-+ /* CLK */
-+ at91_set_A_periph(AT91_PIN_PA17, 0);
-+ /* CMD */
-+ at91_set_A_periph(AT91_PIN_PA16, 1);
-+ /* DAT0, DAT1..DAT3 */
-+ at91_set_A_periph(AT91_PIN_PA15, 1);
-+ at91_set_A_periph(AT91_PIN_PA18, 1);
-+ at91_set_A_periph(AT91_PIN_PA19, 1);
-+ at91_set_A_periph(AT91_PIN_PA20, 1);
-+ /* CLK */
-+ at91_set_B_periph(AT91_PIN_PA13, 0);
-+ /* CMD */
-+ at91_set_B_periph(AT91_PIN_PA12, 1);
-+ /* DAT0, DAT1..DAT3 */
-+ at91_set_B_periph(AT91_PIN_PA11, 1);
-+ at91_set_B_periph(AT91_PIN_PA2, 1);
-+ at91_set_B_periph(AT91_PIN_PA3, 1);
-+ at91_set_B_periph(AT91_PIN_PA4, 1);
-+ printk("AT91: mci0/1 pin mux done\n");
- }
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 1a4758d4c8790c591d2be79382e878526f6dfcb6 Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Mon, 24 Sep 2012 14:50:45 +0800
-Subject: mtd: atmel_nand: add 4k page nand flash support for PMECC.
-
----
- drivers/mtd/nand/atmel_nand.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
-index a92f603..e881c15 100644
---- a/drivers/mtd/nand/atmel_nand.c
-+++ b/drivers/mtd/nand/atmel_nand.c
-@@ -952,6 +952,7 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev,
- /* set ECC page size and oob layout */
- switch (mtd->writesize) {
- case 2048:
-+ case 4096:
- host->pmecc_degree = PMECC_GF_DIMENSION_13;
- host->pmecc_cw_len = (1 << host->pmecc_degree) - 1;
- host->pmecc_sector_number = mtd->writesize / sector_size;
-@@ -977,7 +978,6 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev,
- break;
- case 512:
- case 1024:
-- case 4096:
- /* TODO */
- dev_warn(host->dev,
- "Unsupported page size for PMECC, use Software ECC\n");
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 56a1ff8d7f47a95326ee0eb59209031d3b4a98c9 Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Mon, 24 Sep 2012 14:58:38 +0800
-Subject: mtd: atmel_nand: incease the chip_delay time(tR) for support big
- flash chips such like MT29F8G08ABABA.
-
----
- drivers/mtd/nand/atmel_nand.c | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
-index e881c15..3978336 100644
---- a/drivers/mtd/nand/atmel_nand.c
-+++ b/drivers/mtd/nand/atmel_nand.c
-@@ -1448,7 +1448,11 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
- }
-
- nand_chip->ecc.mode = host->board.ecc_mode;
-- nand_chip->chip_delay = 20; /* 20us command delay time */
-+
-+ /* For support 4k-page flash, incease the delay time to 25us.
-+ * In P.108 of MT29F8G08ABABA datasheet, tR max is 25us.
-+ */
-+ nand_chip->chip_delay = 25;
-
- if (host->board.bus_width_16) /* 16-bit bus width */
- nand_chip->options |= NAND_BUSWIDTH_16;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ab8f5cfc534946bd9627feee2a4b10398a1ca789 Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Tue, 25 Sep 2012 10:40:22 +0800
-Subject: at91: 9x5: add DT parameters to enable PMECC
-
-Signed-off-by: Josh Wu <josh.wu@atmel.com>
----
- arch/arm/boot/dts/at91sam9x5.dtsi | 4 ++++
- arch/arm/boot/dts/at91sam9x5cm.dtsi | 5 ++++-
- 2 files changed, 8 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index 88907db..2cefd49 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -257,7 +257,11 @@
- #address-cells = <1>;
- #size-cells = <1>;
- reg = <0x40000000 0x10000000
-+ 0xffffe000 0x600 /* PMECC Registers */
-+ 0xffffe600 0x200 /* PMECC Error Location Registers */
-+ 0x00100000 0x100000 /* ROM code */
- >;
-+ atmel,pmecc-lookup-table-offset = <0x8000 0x10000>;
- atmel,nand-addr-offset = <21>;
- atmel,nand-cmd-offset = <22>;
- gpios = <&pioD 5 0
-diff --git a/arch/arm/boot/dts/at91sam9x5cm.dtsi b/arch/arm/boot/dts/at91sam9x5cm.dtsi
-index 31e7be2..4027ac7 100644
---- a/arch/arm/boot/dts/at91sam9x5cm.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5cm.dtsi
-@@ -26,7 +26,10 @@
- ahb {
- nand0: nand@40000000 {
- nand-bus-width = <8>;
-- nand-ecc-mode = "soft";
-+ nand-ecc-mode = "hw";
-+ atmel,has-pmecc; /* Enable PMECC */
-+ atmel,pmecc-cap = <2>;
-+ atmel,pmecc-sector-size = <512>;
- nand-on-flash-bbt;
- status = "okay";
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b91b13d77cdd19b1fdbd1ba82111370f2cc124a9 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 2 Oct 2012 11:50:15 +0200
-Subject: ARM: at91: split 9x5 dts/dtsi in a "common" set of peripherals
-
-Creating this new at91sam9x5_common.dtsi, will allow to cover the
-whole at91sam9x5 family of SoCs without having to duplicate nodes.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-
-Conflicts:
- arch/arm/boot/dts/at91sam9g25ek.dts
----
- arch/arm/boot/dts/at91sam9g25ek.dts | 19 +----------
- arch/arm/boot/dts/at91sam9x5_common.dtsi | 54 ++++++++++++++++++++++++++++++++
- 2 files changed, 55 insertions(+), 18 deletions(-)
- create mode 100644 arch/arm/boot/dts/at91sam9x5_common.dtsi
-
-diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts
-index 5b054e4..91c0f02 100644
---- a/arch/arm/boot/dts/at91sam9g25ek.dts
-+++ b/arch/arm/boot/dts/at91sam9g25ek.dts
-@@ -7,8 +7,7 @@
- * Licensed under GPLv2 or later.
- */
- /dts-v1/;
--/include/ "at91sam9x5.dtsi"
--/include/ "at91sam9x5cm.dtsi"
-+/include/ "at91sam9x5_common.dtsi"
-
- / {
- model = "Atmel AT91SAM9G25-EK";
-@@ -20,10 +19,6 @@
-
- ahb {
- apb {
-- dbgu: serial@fffff200 {
-- status = "okay";
-- };
--
- usart0: serial@f801c000 {
- status = "okay";
- };
-@@ -63,17 +58,5 @@
- status = "okay";
- };
- };
--
-- usb0: ohci@00600000 {
-- status = "okay";
-- num-ports = <2>;
-- atmel,vbus-gpio = <&pioD 19 1
-- &pioD 20 1
-- >;
-- };
--
-- usb1: ehci@00700000 {
-- status = "okay";
-- };
- };
- };
-diff --git a/arch/arm/boot/dts/at91sam9x5_common.dtsi b/arch/arm/boot/dts/at91sam9x5_common.dtsi
-new file mode 100644
-index 0000000..b805425
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9x5_common.dtsi
-@@ -0,0 +1,54 @@
-+/*
-+ * at91sam9x5_common.dtsi - Device Tree Include file for AT91SAM9x5 Evaluation Kit:
-+ * common peripherals.
-+ *
-+ * Copyright (C) 2012 Atmel,
-+ * 2012 Nicolas Ferre <nicolas.ferre@atmel.com>
-+ *
-+ * Licensed under GPLv2 or later.
-+ */
-+/include/ "at91sam9x5.dtsi"
-+/include/ "at91sam9x5cm.dtsi"
-+
-+/ {
-+ ahb {
-+ apb {
-+ dbgu: serial@fffff200 {
-+ status = "okay";
-+ };
-+
-+ mmc0: mmc@f0008000 {
-+ status = "okay";
-+ slot@0 {
-+ reg = <0>;
-+ bus-width = <4>;
-+ cd-gpios = <&pioD 15 0>;
-+ };
-+ };
-+
-+ i2c0: i2c@f8010000 {
-+ status = "okay";
-+ };
-+
-+ i2c1: i2c@f8014000 {
-+ status = "okay";
-+ };
-+
-+ i2c2: i2c@f8018000 {
-+ status = "okay";
-+ };
-+ };
-+
-+ usb0: ohci@00600000 {
-+ status = "okay";
-+ num-ports = <2>;
-+ atmel,vbus-gpio = <&pioD 19 1
-+ &pioD 20 1
-+ >;
-+ };
-+
-+ usb1: ehci@00700000 {
-+ status = "okay";
-+ };
-+ };
-+};
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From c21000658bdd029faf2054f0fffa9672152ac1e9 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 2 Oct 2012 11:55:18 +0200
-Subject: ARM: at91/9x5 family: add at91sam9x25ek.dts
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/at91sam9x25ek.dts | 46 +++++++++++++++++++++++++++++++++++++
- arch/arm/mach-at91/Makefile.boot | 1 +
- 2 files changed, 47 insertions(+)
- create mode 100644 arch/arm/boot/dts/at91sam9x25ek.dts
-
-diff --git a/arch/arm/boot/dts/at91sam9x25ek.dts b/arch/arm/boot/dts/at91sam9x25ek.dts
-new file mode 100644
-index 0000000..cf903f5
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9x25ek.dts
-@@ -0,0 +1,46 @@
-+/*
-+ * at91sam9x25ek.dts - Device Tree file for AT91SAM9X25-EK board
-+ *
-+ * Copyright (C) 2012 Atmel,
-+ * 2012 Nicolas Ferre <nicolas.ferre@atmel.com>
-+ *
-+ * Licensed under GPLv2 or later.
-+ */
-+/dts-v1/;
-+/include/ "at91sam9x5_common.dtsi"
-+
-+/ {
-+ model = "Atmel AT91SAM9X25-EK";
-+ compatible = "atmel,at91sam9x25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
-+
-+ chosen {
-+ bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
-+ };
-+
-+ ahb {
-+ apb {
-+ mmc1: mmc@f000c000 {
-+ status = "okay";
-+ slot@0 {
-+ reg = <0>;
-+ bus-width = <4>;
-+ cd-gpios = <&pioD 14 0>;
-+ };
-+ };
-+
-+ usart0: serial@f801c000 {
-+ status = "okay";
-+ };
-+
-+ macb0: ethernet@f802c000 {
-+ phy-mode = "rmii";
-+ status = "okay";
-+ };
-+
-+ macb1: ethernet@f8030000 {
-+ phy-mode = "rmii";
-+ status = "okay";
-+ };
-+ };
-+ };
-+};
-diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
-index 9e84fe4..9532f93 100644
---- a/arch/arm/mach-at91/Makefile.boot
-+++ b/arch/arm/mach-at91/Makefile.boot
-@@ -34,3 +34,4 @@ dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9m10g45ek.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9n12ek.dtb
- # sam9x5
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g25ek.dtb
-+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9x25ek.dtb
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 245b4491a6575ca148b06d29400c1f87bc9408d8 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 16 Oct 2012 19:04:39 +0200
-Subject: ARM: at91: add new at91sam9g35ek.dts
-
-With LCD DT definition
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/at91sam9g35ek.dts | 49 +++++++++++++++++++++++++++++++++++++
- arch/arm/boot/dts/at91sam9x5.dtsi | 15 ++++++++++++
- arch/arm/mach-at91/Makefile.boot | 1 +
- 3 files changed, 65 insertions(+)
- create mode 100644 arch/arm/boot/dts/at91sam9g35ek.dts
-
-diff --git a/arch/arm/boot/dts/at91sam9g35ek.dts b/arch/arm/boot/dts/at91sam9g35ek.dts
-new file mode 100644
-index 0000000..f2c3341
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9g35ek.dts
-@@ -0,0 +1,49 @@
-+/*
-+ * at91sam9g35ek.dts - Device Tree file for AT91SAM9G35-EK board
-+ *
-+ * Copyright (C) 2012 Atmel,
-+ * 2012 Nicolas Ferre <nicolas.ferre@atmel.com>
-+ *
-+ * Licensed under GPLv2 or later.
-+ */
-+/dts-v1/;
-+/include/ "at91sam9x5_common.dtsi"
-+
-+/ {
-+ model = "Atmel AT91SAM9G35-EK";
-+ compatible = "atmel,at91sam9g35ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
-+
-+ chosen {
-+ bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
-+ };
-+
-+ ahb {
-+ apb {
-+ mmc1: mmc@f000c000 {
-+ status = "okay";
-+ slot@0 {
-+ reg = <0>;
-+ bus-width = <4>;
-+ cd-gpios = <&pioD 14 0>;
-+ };
-+ };
-+
-+ usart0: serial@f801c000 {
-+ status = "okay";
-+ };
-+
-+ macb0: ethernet@f802c000 {
-+ phy-mode = "rmii";
-+ status = "okay";
-+ };
-+
-+ lcd@f8038000 {
-+ status = "okay";
-+ };
-+
-+ lcdovl1@f8038100 {
-+ status = "okay";
-+ };
-+ };
-+ };
-+};
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index 2cefd49..50388fd 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -250,6 +250,21 @@
- #size-cells = <0>;
- status = "disabled";
- };
-+
-+ lcd@f8038000 {
-+ compatible = "atmel,at91sam9x5-lcd";
-+ reg = <0xf8038000 0xff
-+ 0xf8038400 0x3ff>;
-+ interrupts = <25 4 3>;
-+ status = "disabled";
-+ };
-+
-+ lcdovl1@f8038100 {
-+ compatible = "atmel,at91sam9x5-lcd";
-+ reg = <0xf8038100 0xff
-+ 0xf8038800 0x3ff>;
-+ status = "disabled";
-+ };
- };
-
- nand0: nand@40000000 {
-diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
-index 9532f93..410485a 100644
---- a/arch/arm/mach-at91/Makefile.boot
-+++ b/arch/arm/mach-at91/Makefile.boot
-@@ -34,4 +34,5 @@ dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9m10g45ek.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9n12ek.dtb
- # sam9x5
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g25ek.dtb
-+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g35ek.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9x25ek.dtb
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From f0e81f4a05048c4b863e2b3afd5b114e489a7887 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Tue, 16 Oct 2012 19:05:25 +0200
-Subject: ARM: at91: add pinmux for 9x5 LCD
-
-Temporaty in board-dt
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/board-dt.c | 102 +++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 101 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
-index 15830cb..c0d242c 100644
---- a/arch/arm/mach-at91/board-dt.c
-+++ b/arch/arm/mach-at91/board-dt.c
-@@ -26,6 +26,103 @@
-
- #include "generic.h"
-
-+#include <linux/fb.h>
-+
-+#include <video/atmel_lcdfb.h>
-+#include <mach/atmel_hlcdc.h>
-+
-+/*
-+ * LCD Controller
-+ */
-+static struct fb_videomode at91_tft_vga_modes[] = {
-+ {
-+ .name = "LG",
-+ .refresh = 60,
-+ .xres = 800, .yres = 480,
-+ .pixclock = KHZ2PICOS(33260),
-+
-+ .left_margin = 88, .right_margin = 168,
-+ .upper_margin = 8, .lower_margin = 37,
-+ .hsync_len = 128, .vsync_len = 2,
-+
-+ .sync = 0,
-+ .vmode = FB_VMODE_NONINTERLACED,
-+ },
-+};
-+
-+static struct fb_monspecs at91fb_default_monspecs = {
-+ .manufacturer = "LG",
-+ .monitor = "LB043WQ1",
-+
-+ .modedb = at91_tft_vga_modes,
-+ .modedb_len = ARRAY_SIZE(at91_tft_vga_modes),
-+ .hfmin = 15000,
-+ .hfmax = 17640,
-+ .vfmin = 57,
-+ .vfmax = 67,
-+};
-+
-+/* Default output mode is TFT 24 bit */
-+#define BPP_OUT_DEFAULT_LCDCFG5 (LCDC_LCDCFG5_MODE_OUTPUT_24BPP)
-+
-+/* Driver datas */
-+static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
-+ .lcdcon_is_backlight = true,
-+ .alpha_enabled = false,
-+ .default_bpp = 16,
-+ /* Reserve enough memory for 32bpp */
-+ .smem_len = 800 * 480 * 4,
-+ /* default_lcdcon2 is used for LCDCFG5 */
-+ .default_lcdcon2 = BPP_OUT_DEFAULT_LCDCFG5,
-+ .default_monspecs = &at91fb_default_monspecs,
-+ .guard_time = 9,
-+ .lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB,
-+};
-+
-+void __init at91sam9x5_pinmux_lcd(void)
-+{
-+ at91_set_A_periph(AT91_PIN_PC26, 0); /* LCDPWM */
-+
-+ at91_set_A_periph(AT91_PIN_PC27, 0); /* LCDVSYNC */
-+ at91_set_A_periph(AT91_PIN_PC28, 0); /* LCDHSYNC */
-+
-+ at91_set_A_periph(AT91_PIN_PC24, 0); /* LCDDISP */
-+ at91_set_A_periph(AT91_PIN_PC29, 0); /* LCDDEN */
-+ at91_set_A_periph(AT91_PIN_PC30, 0); /* LCDPCK */
-+
-+ at91_set_A_periph(AT91_PIN_PC0, 0); /* LCDD0 */
-+ at91_set_A_periph(AT91_PIN_PC1, 0); /* LCDD1 */
-+ at91_set_A_periph(AT91_PIN_PC2, 0); /* LCDD2 */
-+ at91_set_A_periph(AT91_PIN_PC3, 0); /* LCDD3 */
-+ at91_set_A_periph(AT91_PIN_PC4, 0); /* LCDD4 */
-+ at91_set_A_periph(AT91_PIN_PC5, 0); /* LCDD5 */
-+ at91_set_A_periph(AT91_PIN_PC6, 0); /* LCDD6 */
-+ at91_set_A_periph(AT91_PIN_PC7, 0); /* LCDD7 */
-+ at91_set_A_periph(AT91_PIN_PC8, 0); /* LCDD8 */
-+ at91_set_A_periph(AT91_PIN_PC9, 0); /* LCDD9 */
-+ at91_set_A_periph(AT91_PIN_PC10, 0); /* LCDD10 */
-+ at91_set_A_periph(AT91_PIN_PC11, 0); /* LCDD11 */
-+ at91_set_A_periph(AT91_PIN_PC12, 0); /* LCDD12 */
-+ at91_set_A_periph(AT91_PIN_PC13, 0); /* LCDD13 */
-+ at91_set_A_periph(AT91_PIN_PC14, 0); /* LCDD14 */
-+ at91_set_A_periph(AT91_PIN_PC15, 0); /* LCDD15 */
-+ at91_set_A_periph(AT91_PIN_PC16, 0); /* LCDD16 */
-+ at91_set_A_periph(AT91_PIN_PC17, 0); /* LCDD17 */
-+ at91_set_A_periph(AT91_PIN_PC18, 0); /* LCDD18 */
-+ at91_set_A_periph(AT91_PIN_PC19, 0); /* LCDD19 */
-+ at91_set_A_periph(AT91_PIN_PC20, 0); /* LCDD20 */
-+ at91_set_A_periph(AT91_PIN_PC21, 0); /* LCDD21 */
-+ at91_set_A_periph(AT91_PIN_PC22, 0); /* LCDD22 */
-+ at91_set_A_periph(AT91_PIN_PC23, 0); /* LCDD23 */
-+
-+ printk("AT91: lcd pin mux done\n");
-+}
-+
-+struct of_dev_auxdata at91_auxdata_lookup[] __initdata = {
-+ OF_DEV_AUXDATA("atmel,at91sam9x5-lcd", 0xf8038000, "atmel_hlcdfb_base", &ek_lcdc_data),
-+ OF_DEV_AUXDATA("atmel,at91sam9x5-lcd", 0xf8038100, "atmel_hlcdfb_ovl", &ek_lcdc_data),
-+ { /* sentinel */ }
-+};
-
- static const struct of_device_id irq_of_match[] __initconst = {
-
-@@ -42,7 +139,6 @@ static void __init at91_dt_init_irq(void)
-
- static void __init at91_dt_device_init(void)
- {
-- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
- /* Temporary pin mux stuff */
- if (of_machine_is_compatible("atmel,at91sam9x5")) {
- at91_set_A_periph(AT91_PIN_PA30, 0); /* TWD */
-@@ -74,7 +170,11 @@ static void __init at91_dt_device_init(void)
- at91_set_B_periph(AT91_PIN_PA3, 1);
- at91_set_B_periph(AT91_PIN_PA4, 1);
- printk("AT91: mci0/1 pin mux done\n");
-+
-+ at91sam9x5_pinmux_lcd();
- }
-+
-+ of_platform_populate(NULL, of_default_bus_match_table, at91_auxdata_lookup, NULL);
- }
-
- static const char *at91_dt_board_compat[] __initdata = {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From d97e19aab9e85eb9c7acd60af983a82f8384d702 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Wed, 17 Oct 2012 10:14:48 +0200
-Subject: ARM: at91: add LCD HEO DT entry for at91sam9x5
-
-At91sam9x5.dtsi entry and activated in sam9g35ek.dts.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/boot/dts/at91sam9g35ek.dts | 4 ++++
- arch/arm/boot/dts/at91sam9x5.dtsi | 7 +++++++
- 2 files changed, 11 insertions(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9g35ek.dts b/arch/arm/boot/dts/at91sam9g35ek.dts
-index f2c3341..0cb762e 100644
---- a/arch/arm/boot/dts/at91sam9g35ek.dts
-+++ b/arch/arm/boot/dts/at91sam9g35ek.dts
-@@ -44,6 +44,10 @@
- lcdovl1@f8038100 {
- status = "okay";
- };
-+
-+ lcdheo1@f8038280 {
-+ status = "okay";
-+ };
- };
- };
- };
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index 50388fd..027b9eb 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -265,6 +265,13 @@
- 0xf8038800 0x3ff>;
- status = "disabled";
- };
-+
-+ lcdheo1@f8038280 {
-+ compatible = "atmel,at91sam9x5-heo";
-+ reg = <0xf8038280 0xbf>;
-+ interrupts = <25 4 3>;
-+ status = "disabled";
-+ };
- };
-
- nand0: nand@40000000 {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 9b5d8f610459f6a0f3a506642681ecac65664293 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 22 Oct 2012 16:04:42 +0200
-Subject: AT91SAM9G45: add crypto peripherals
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-commit 815e972110052e8da68b5b5298ca2cd69cb7c3c0 upstream.
-
-Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Eric Bénard <eric@eukrea.com>
-Tested-by: Eric Bénard <eric@eukrea.com>
-
-Conflicts:
- arch/arm/mach-at91/at91sam9g45.c
----
- arch/arm/mach-at91/at91sam9g45.c | 16 +++-
- arch/arm/mach-at91/at91sam9g45_devices.c | 131 +++++++++++++++++++++++++-
- arch/arm/mach-at91/include/mach/at91sam9g45.h | 2 +
- 3 files changed, 147 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
-index 7ccbf9c..4b791bf 100644
---- a/arch/arm/mach-at91/at91sam9g45.c
-+++ b/arch/arm/mach-at91/at91sam9g45.c
-@@ -177,6 +177,13 @@ static struct clk vdec_clk = {
- .type = CLK_TYPE_PERIPHERAL,
- };
-
-+/* AES/TDES/SHA clock - Only for sam9m11/sam9g56 */
-+static struct clk aestdessha_clk = {
-+ .name = "aestdessha_clk",
-+ .pmc_mask = 1 << AT91SAM9G45_ID_AESTDESSHA,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+
- static struct clk *periph_clocks[] __initdata = {
- &pioA_clk,
- &pioB_clk,
-@@ -205,6 +212,7 @@ static struct clk *periph_clocks[] __initdata = {
- &isi_clk,
- &udphs_clk,
- &mmc1_clk,
-+ &aestdessha_clk,
- // irq0
- };
-
-@@ -226,6 +234,9 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.1", &twi1_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
-+ CLKDEV_CON_DEV_ID("sha_clk", "atmel_sha", &aestdessha_clk),
-+ CLKDEV_CON_DEV_ID("tdes_clk", "atmel_tdes", &aestdessha_clk),
-+ CLKDEV_CON_DEV_ID("aes_clk", "atmel_aes", &aestdessha_clk),
- CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
- /* more usart lookup table for DT entries */
- CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck),
-@@ -242,6 +253,9 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("mci_clk", "fffd0000.mmc", &mmc1_clk),
- CLKDEV_CON_DEV_ID(NULL, "fff84000.i2c", &twi0_clk),
- CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi1_clk),
-+ CLKDEV_CON_DEV_ID("aes_clk", "fffc0000.aes", &aestdessha_clk),
-+ CLKDEV_CON_DEV_ID("tdes_clk", "fffc4000.tdes", &aestdessha_clk),
-+ CLKDEV_CON_DEV_ID("sha_clk", "fffc8000.sha", &aestdessha_clk),
- /* fake hclk clock */
- CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
- CLKDEV_CON_ID("pioA", &pioA_clk),
-@@ -387,7 +401,7 @@ static unsigned int at91sam9g45_default_irq_priority[NR_AIC_IRQS] __initdata = {
- 2, /* USB Device High speed port */
- 0,
- 0, /* Multimedia Card Interface 1 */
-- 0,
-+ 0, /* AESTDESSHA Crypto HW Accelerators */
- 0, /* Advanced Interrupt Controller (IRQ0) */
- };
-
-diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
-index 29f334c..3d523f0 100644
---- a/arch/arm/mach-at91/at91sam9g45_devices.c
-+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
-@@ -31,7 +31,7 @@
- #include <mach/at91sam9_smc.h>
- #include <mach/at_hdmac.h>
- #include <mach/atmel-mci.h>
--
-+#include <linux/platform_data/atmel-aes.h>
- #include <media/atmel-isi.h>
-
- #include "generic.h"
-@@ -514,6 +514,132 @@ void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
-
-
- /* --------------------------------------------------------------------
-+ * SHA1/SHA256
-+ * -------------------------------------------------------------------- */
-+
-+#if defined(CONFIG_CRYPTO_DEV_ATMEL_SHA) || defined(CONFIG_CRYPTO_DEV_ATMEL_SHA_MODULE)
-+static struct resource sha_resources[] = {
-+ {
-+ .start = AT91SAM9G45_BASE_SHA,
-+ .end = AT91SAM9G45_BASE_SHA + SZ_16K - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device at91sam9g45_sha_device = {
-+ .name = "atmel_sha",
-+ .id = -1,
-+ .resource = sha_resources,
-+ .num_resources = ARRAY_SIZE(sha_resources),
-+};
-+
-+static void __init at91_add_device_sha(void)
-+{
-+ platform_device_register(&at91sam9g45_sha_device);
-+}
-+#else
-+static void __init at91_add_device_sha(void) {}
-+#endif
-+
-+/* --------------------------------------------------------------------
-+ * DES/TDES
-+ * -------------------------------------------------------------------- */
-+
-+#if defined(CONFIG_CRYPTO_DEV_ATMEL_TDES) || defined(CONFIG_CRYPTO_DEV_ATMEL_TDES_MODULE)
-+static struct resource tdes_resources[] = {
-+ [0] = {
-+ .start = AT91SAM9G45_BASE_TDES,
-+ .end = AT91SAM9G45_BASE_TDES + SZ_16K - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device at91sam9g45_tdes_device = {
-+ .name = "atmel_tdes",
-+ .id = -1,
-+ .resource = tdes_resources,
-+ .num_resources = ARRAY_SIZE(tdes_resources),
-+};
-+
-+static void __init at91_add_device_tdes(void)
-+{
-+ platform_device_register(&at91sam9g45_tdes_device);
-+}
-+#else
-+static void __init at91_add_device_tdes(void) {}
-+#endif
-+
-+/* --------------------------------------------------------------------
-+ * AES
-+ * -------------------------------------------------------------------- */
-+
-+#if defined(CONFIG_CRYPTO_DEV_ATMEL_AES) || defined(CONFIG_CRYPTO_DEV_ATMEL_AES_MODULE)
-+static struct aes_platform_data aes_data;
-+static u64 aes_dmamask = DMA_BIT_MASK(32);
-+
-+static struct resource aes_resources[] = {
-+ [0] = {
-+ .start = AT91SAM9G45_BASE_AES,
-+ .end = AT91SAM9G45_BASE_AES + SZ_16K - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
-+ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device at91sam9g45_aes_device = {
-+ .name = "atmel_aes",
-+ .id = -1,
-+ .dev = {
-+ .dma_mask = &aes_dmamask,
-+ .coherent_dma_mask = DMA_BIT_MASK(32),
-+ .platform_data = &aes_data,
-+ },
-+ .resource = aes_resources,
-+ .num_resources = ARRAY_SIZE(aes_resources),
-+};
-+
-+static void __init at91_add_device_aes(void)
-+{
-+ struct at_dma_slave *atslave;
-+ struct aes_dma_data *alt_atslave;
-+
-+ alt_atslave = kzalloc(sizeof(struct aes_dma_data), GFP_KERNEL);
-+
-+ /* DMA TX slave channel configuration */
-+ atslave = &alt_atslave->txdata;
-+ atslave->dma_dev = &at_hdmac_device.dev;
-+ atslave->cfg = ATC_FIFOCFG_ENOUGHSPACE | ATC_SRC_H2SEL_HW |
-+ ATC_SRC_PER(AT_DMA_ID_AES_RX);
-+
-+ /* DMA RX slave channel configuration */
-+ atslave = &alt_atslave->rxdata;
-+ atslave->dma_dev = &at_hdmac_device.dev;
-+ atslave->cfg = ATC_FIFOCFG_ENOUGHSPACE | ATC_DST_H2SEL_HW |
-+ ATC_DST_PER(AT_DMA_ID_AES_TX);
-+
-+ aes_data.dma_slave = alt_atslave;
-+ platform_device_register(&at91sam9g45_aes_device);
-+}
-+#else
-+static void __init at91_add_device_aes(void) {}
-+#endif
-+
-+
-+/* --------------------------------------------------------------------
- * NAND / SmartMedia
- * -------------------------------------------------------------------- */
-
-@@ -1742,6 +1868,9 @@ static int __init at91_add_standard_devices(void)
- at91_add_device_trng();
- at91_add_device_watchdog();
- at91_add_device_tc();
-+ at91_add_device_sha();
-+ at91_add_device_tdes();
-+ at91_add_device_aes();
- return 0;
- }
-
-diff --git a/arch/arm/mach-at91/include/mach/at91sam9g45.h b/arch/arm/mach-at91/include/mach/at91sam9g45.h
-index 3a4da24..8eba102 100644
---- a/arch/arm/mach-at91/include/mach/at91sam9g45.h
-+++ b/arch/arm/mach-at91/include/mach/at91sam9g45.h
-@@ -136,6 +136,8 @@
- #define AT_DMA_ID_SSC1_RX 8
- #define AT_DMA_ID_AC97_TX 9
- #define AT_DMA_ID_AC97_RX 10
-+#define AT_DMA_ID_AES_TX 11
-+#define AT_DMA_ID_AES_RX 12
- #define AT_DMA_ID_MCI1 13
-
- #endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 6b9039aedd996147b5146b74594a69221d0873d8 Mon Sep 17 00:00:00 2001
-From: Nicolas Royer <nicolas@eukrea.com>
-Date: Mon, 17 Sep 2012 18:26:04 +0200
-Subject: crypto: add Atmel AES driver
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-commit bd3c7b5c2aba0d806285700848f588ca482094d8 upstream.
-
-Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Eric Bénard <eric@eukrea.com>
-Tested-by: Eric Bénard <eric@eukrea.com>
----
- drivers/crypto/Kconfig | 17 +
- drivers/crypto/Makefile | 1 +
- drivers/crypto/atmel-aes-regs.h | 62 ++
- drivers/crypto/atmel-aes.c | 1206 +++++++++++++++++++++++++++++++
- include/linux/platform_data/atmel-aes.h | 22 +
- 5 files changed, 1308 insertions(+)
- create mode 100644 drivers/crypto/atmel-aes-regs.h
- create mode 100644 drivers/crypto/atmel-aes.c
- create mode 100644 include/linux/platform_data/atmel-aes.h
-
-diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
-index dd414d9..98c7da5 100644
---- a/drivers/crypto/Kconfig
-+++ b/drivers/crypto/Kconfig
-@@ -296,4 +296,21 @@ config CRYPTO_DEV_TEGRA_AES
- To compile this driver as a module, choose M here: the module
- will be called tegra-aes.
-
-+config CRYPTO_DEV_ATMEL_AES
-+ tristate "Support for Atmel AES hw accelerator"
-+ depends on ARCH_AT91
-+ select CRYPTO_CBC
-+ select CRYPTO_ECB
-+ select CRYPTO_AES
-+ select CRYPTO_ALGAPI
-+ select CRYPTO_BLKCIPHER
-+ select AT_HDMAC
-+ help
-+ Some Atmel processors have AES hw accelerator.
-+ Select this if you want to use the Atmel module for
-+ AES algorithms.
-+
-+ To compile this driver as a module, choose M here: the module
-+ will be called atmel-aes.
-+
- endif # CRYPTO_HW
-diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
-index f3e64ea..73ad830 100644
---- a/drivers/crypto/Makefile
-+++ b/drivers/crypto/Makefile
-@@ -14,3 +14,4 @@ obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o
- obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o
- obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o
- obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o
-+obj-$(CONFIG_CRYPTO_DEV_ATMEL_AES) += atmel-aes.o
-diff --git a/drivers/crypto/atmel-aes-regs.h b/drivers/crypto/atmel-aes-regs.h
-new file mode 100644
-index 0000000..2786bb1
---- /dev/null
-+++ b/drivers/crypto/atmel-aes-regs.h
-@@ -0,0 +1,62 @@
-+#ifndef __ATMEL_AES_REGS_H__
-+#define __ATMEL_AES_REGS_H__
-+
-+#define AES_CR 0x00
-+#define AES_CR_START (1 << 0)
-+#define AES_CR_SWRST (1 << 8)
-+#define AES_CR_LOADSEED (1 << 16)
-+
-+#define AES_MR 0x04
-+#define AES_MR_CYPHER_DEC (0 << 0)
-+#define AES_MR_CYPHER_ENC (1 << 0)
-+#define AES_MR_DUALBUFF (1 << 3)
-+#define AES_MR_PROCDLY_MASK (0xF << 4)
-+#define AES_MR_PROCDLY_OFFSET 4
-+#define AES_MR_SMOD_MASK (0x3 << 8)
-+#define AES_MR_SMOD_MANUAL (0x0 << 8)
-+#define AES_MR_SMOD_AUTO (0x1 << 8)
-+#define AES_MR_SMOD_IDATAR0 (0x2 << 8)
-+#define AES_MR_KEYSIZE_MASK (0x3 << 10)
-+#define AES_MR_KEYSIZE_128 (0x0 << 10)
-+#define AES_MR_KEYSIZE_192 (0x1 << 10)
-+#define AES_MR_KEYSIZE_256 (0x2 << 10)
-+#define AES_MR_OPMOD_MASK (0x7 << 12)
-+#define AES_MR_OPMOD_ECB (0x0 << 12)
-+#define AES_MR_OPMOD_CBC (0x1 << 12)
-+#define AES_MR_OPMOD_OFB (0x2 << 12)
-+#define AES_MR_OPMOD_CFB (0x3 << 12)
-+#define AES_MR_OPMOD_CTR (0x4 << 12)
-+#define AES_MR_LOD (0x1 << 15)
-+#define AES_MR_CFBS_MASK (0x7 << 16)
-+#define AES_MR_CFBS_128b (0x0 << 16)
-+#define AES_MR_CFBS_64b (0x1 << 16)
-+#define AES_MR_CFBS_32b (0x2 << 16)
-+#define AES_MR_CFBS_16b (0x3 << 16)
-+#define AES_MR_CFBS_8b (0x4 << 16)
-+#define AES_MR_CKEY_MASK (0xF << 20)
-+#define AES_MR_CKEY_OFFSET 20
-+#define AES_MR_CMTYP_MASK (0x1F << 24)
-+#define AES_MR_CMTYP_OFFSET 24
-+
-+#define AES_IER 0x10
-+#define AES_IDR 0x14
-+#define AES_IMR 0x18
-+#define AES_ISR 0x1C
-+#define AES_INT_DATARDY (1 << 0)
-+#define AES_INT_URAD (1 << 8)
-+#define AES_ISR_URAT_MASK (0xF << 12)
-+#define AES_ISR_URAT_IDR_WR_PROC (0x0 << 12)
-+#define AES_ISR_URAT_ODR_RD_PROC (0x1 << 12)
-+#define AES_ISR_URAT_MR_WR_PROC (0x2 << 12)
-+#define AES_ISR_URAT_ODR_RD_SUBK (0x3 << 12)
-+#define AES_ISR_URAT_MR_WR_SUBK (0x4 << 12)
-+#define AES_ISR_URAT_WOR_RD (0x5 << 12)
-+
-+#define AES_KEYWR(x) (0x20 + ((x) * 0x04))
-+#define AES_IDATAR(x) (0x40 + ((x) * 0x04))
-+#define AES_ODATAR(x) (0x50 + ((x) * 0x04))
-+#define AES_IVR(x) (0x60 + ((x) * 0x04))
-+
-+#define AES_HW_VERSION 0xFC
-+
-+#endif /* __ATMEL_AES_REGS_H__ */
-diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
-new file mode 100644
-index 0000000..6bb20ff
---- /dev/null
-+++ b/drivers/crypto/atmel-aes.c
-@@ -0,0 +1,1206 @@
-+/*
-+ * Cryptographic API.
-+ *
-+ * Support for ATMEL AES HW acceleration.
-+ *
-+ * Copyright (c) 2012 Eukréa Electromatique - ATMEL
-+ * Author: Nicolas Royer <nicolas@eukrea.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 published
-+ * by the Free Software Foundation.
-+ *
-+ * Some ideas are from omap-aes.c driver.
-+ */
-+
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/err.h>
-+#include <linux/clk.h>
-+#include <linux/io.h>
-+#include <linux/hw_random.h>
-+#include <linux/platform_device.h>
-+
-+#include <linux/device.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/interrupt.h>
-+#include <linux/kernel.h>
-+#include <linux/clk.h>
-+#include <linux/irq.h>
-+#include <linux/io.h>
-+#include <linux/platform_device.h>
-+#include <linux/scatterlist.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/delay.h>
-+#include <linux/crypto.h>
-+#include <linux/cryptohash.h>
-+#include <crypto/scatterwalk.h>
-+#include <crypto/algapi.h>
-+#include <crypto/aes.h>
-+#include <crypto/hash.h>
-+#include <crypto/internal/hash.h>
-+#include <linux/platform_data/atmel-aes.h>
-+#include "atmel-aes-regs.h"
-+
-+#define CFB8_BLOCK_SIZE 1
-+#define CFB16_BLOCK_SIZE 2
-+#define CFB32_BLOCK_SIZE 4
-+#define CFB64_BLOCK_SIZE 8
-+
-+/* AES flags */
-+#define AES_FLAGS_MODE_MASK 0x01ff
-+#define AES_FLAGS_ENCRYPT BIT(0)
-+#define AES_FLAGS_CBC BIT(1)
-+#define AES_FLAGS_CFB BIT(2)
-+#define AES_FLAGS_CFB8 BIT(3)
-+#define AES_FLAGS_CFB16 BIT(4)
-+#define AES_FLAGS_CFB32 BIT(5)
-+#define AES_FLAGS_CFB64 BIT(6)
-+#define AES_FLAGS_OFB BIT(7)
-+#define AES_FLAGS_CTR BIT(8)
-+
-+#define AES_FLAGS_INIT BIT(16)
-+#define AES_FLAGS_DMA BIT(17)
-+#define AES_FLAGS_BUSY BIT(18)
-+
-+#define AES_FLAGS_DUALBUFF BIT(24)
-+
-+#define ATMEL_AES_QUEUE_LENGTH 1
-+#define ATMEL_AES_CACHE_SIZE 0
-+
-+#define ATMEL_AES_DMA_THRESHOLD 16
-+
-+
-+struct atmel_aes_dev;
-+
-+struct atmel_aes_ctx {
-+ struct atmel_aes_dev *dd;
-+
-+ int keylen;
-+ u32 key[AES_KEYSIZE_256 / sizeof(u32)];
-+};
-+
-+struct atmel_aes_reqctx {
-+ unsigned long mode;
-+};
-+
-+struct atmel_aes_dma {
-+ struct dma_chan *chan;
-+ struct dma_slave_config dma_conf;
-+};
-+
-+struct atmel_aes_dev {
-+ struct list_head list;
-+ unsigned long phys_base;
-+ void __iomem *io_base;
-+
-+ struct atmel_aes_ctx *ctx;
-+ struct device *dev;
-+ struct clk *iclk;
-+ int irq;
-+
-+ unsigned long flags;
-+ int err;
-+
-+ spinlock_t lock;
-+ struct crypto_queue queue;
-+
-+ struct tasklet_struct done_task;
-+ struct tasklet_struct queue_task;
-+
-+ struct ablkcipher_request *req;
-+ size_t total;
-+
-+ struct scatterlist *in_sg;
-+ unsigned int nb_in_sg;
-+
-+ struct scatterlist *out_sg;
-+ unsigned int nb_out_sg;
-+
-+ size_t bufcnt;
-+
-+ u8 buf_in[ATMEL_AES_DMA_THRESHOLD] __aligned(sizeof(u32));
-+ int dma_in;
-+ struct atmel_aes_dma dma_lch_in;
-+
-+ u8 buf_out[ATMEL_AES_DMA_THRESHOLD] __aligned(sizeof(u32));
-+ int dma_out;
-+ struct atmel_aes_dma dma_lch_out;
-+
-+ u32 hw_version;
-+};
-+
-+struct atmel_aes_drv {
-+ struct list_head dev_list;
-+ spinlock_t lock;
-+};
-+
-+static struct atmel_aes_drv atmel_aes = {
-+ .dev_list = LIST_HEAD_INIT(atmel_aes.dev_list),
-+ .lock = __SPIN_LOCK_UNLOCKED(atmel_aes.lock),
-+};
-+
-+static int atmel_aes_sg_length(struct ablkcipher_request *req,
-+ struct scatterlist *sg)
-+{
-+ unsigned int total = req->nbytes;
-+ int sg_nb;
-+ unsigned int len;
-+ struct scatterlist *sg_list;
-+
-+ sg_nb = 0;
-+ sg_list = sg;
-+ total = req->nbytes;
-+
-+ while (total) {
-+ len = min(sg_list->length, total);
-+
-+ sg_nb++;
-+ total -= len;
-+
-+ sg_list = sg_next(sg_list);
-+ if (!sg_list)
-+ total = 0;
-+ }
-+
-+ return sg_nb;
-+}
-+
-+static inline u32 atmel_aes_read(struct atmel_aes_dev *dd, u32 offset)
-+{
-+ return readl_relaxed(dd->io_base + offset);
-+}
-+
-+static inline void atmel_aes_write(struct atmel_aes_dev *dd,
-+ u32 offset, u32 value)
-+{
-+ writel_relaxed(value, dd->io_base + offset);
-+}
-+
-+static void atmel_aes_read_n(struct atmel_aes_dev *dd, u32 offset,
-+ u32 *value, int count)
-+{
-+ for (; count--; value++, offset += 4)
-+ *value = atmel_aes_read(dd, offset);
-+}
-+
-+static void atmel_aes_write_n(struct atmel_aes_dev *dd, u32 offset,
-+ u32 *value, int count)
-+{
-+ for (; count--; value++, offset += 4)
-+ atmel_aes_write(dd, offset, *value);
-+}
-+
-+static void atmel_aes_dualbuff_test(struct atmel_aes_dev *dd)
-+{
-+ atmel_aes_write(dd, AES_MR, AES_MR_DUALBUFF);
-+
-+ if (atmel_aes_read(dd, AES_MR) & AES_MR_DUALBUFF)
-+ dd->flags |= AES_FLAGS_DUALBUFF;
-+}
-+
-+static struct atmel_aes_dev *atmel_aes_find_dev(struct atmel_aes_ctx *ctx)
-+{
-+ struct atmel_aes_dev *aes_dd = NULL;
-+ struct atmel_aes_dev *tmp;
-+
-+ spin_lock_bh(&atmel_aes.lock);
-+ if (!ctx->dd) {
-+ list_for_each_entry(tmp, &atmel_aes.dev_list, list) {
-+ aes_dd = tmp;
-+ break;
-+ }
-+ ctx->dd = aes_dd;
-+ } else {
-+ aes_dd = ctx->dd;
-+ }
-+
-+ spin_unlock_bh(&atmel_aes.lock);
-+
-+ return aes_dd;
-+}
-+
-+static int atmel_aes_hw_init(struct atmel_aes_dev *dd)
-+{
-+ clk_prepare_enable(dd->iclk);
-+
-+ if (!(dd->flags & AES_FLAGS_INIT)) {
-+ atmel_aes_write(dd, AES_CR, AES_CR_SWRST);
-+ atmel_aes_dualbuff_test(dd);
-+ dd->flags |= AES_FLAGS_INIT;
-+ dd->err = 0;
-+ }
-+
-+ return 0;
-+}
-+
-+static void atmel_aes_hw_version_init(struct atmel_aes_dev *dd)
-+{
-+ atmel_aes_hw_init(dd);
-+
-+ dd->hw_version = atmel_aes_read(dd, AES_HW_VERSION);
-+
-+ clk_disable_unprepare(dd->iclk);
-+}
-+
-+static void atmel_aes_finish_req(struct atmel_aes_dev *dd, int err)
-+{
-+ struct ablkcipher_request *req = dd->req;
-+
-+ clk_disable_unprepare(dd->iclk);
-+ dd->flags &= ~AES_FLAGS_BUSY;
-+
-+ req->base.complete(&req->base, err);
-+}
-+
-+static void atmel_aes_dma_callback(void *data)
-+{
-+ struct atmel_aes_dev *dd = data;
-+
-+ /* dma_lch_out - completed */
-+ tasklet_schedule(&dd->done_task);
-+}
-+
-+static int atmel_aes_crypt_dma(struct atmel_aes_dev *dd)
-+{
-+ struct dma_async_tx_descriptor *in_desc, *out_desc;
-+ int nb_dma_sg_in, nb_dma_sg_out;
-+
-+ dd->nb_in_sg = atmel_aes_sg_length(dd->req, dd->in_sg);
-+ if (!dd->nb_in_sg)
-+ goto exit_err;
-+
-+ nb_dma_sg_in = dma_map_sg(dd->dev, dd->in_sg, dd->nb_in_sg,
-+ DMA_TO_DEVICE);
-+ if (!nb_dma_sg_in)
-+ goto exit_err;
-+
-+ in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, dd->in_sg,
-+ nb_dma_sg_in, DMA_MEM_TO_DEV,
-+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-+
-+ if (!in_desc)
-+ goto unmap_in;
-+
-+ /* callback not needed */
-+
-+ dd->nb_out_sg = atmel_aes_sg_length(dd->req, dd->out_sg);
-+ if (!dd->nb_out_sg)
-+ goto unmap_in;
-+
-+ nb_dma_sg_out = dma_map_sg(dd->dev, dd->out_sg, dd->nb_out_sg,
-+ DMA_FROM_DEVICE);
-+ if (!nb_dma_sg_out)
-+ goto unmap_out;
-+
-+ out_desc = dmaengine_prep_slave_sg(dd->dma_lch_out.chan, dd->out_sg,
-+ nb_dma_sg_out, DMA_DEV_TO_MEM,
-+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-+
-+ if (!out_desc)
-+ goto unmap_out;
-+
-+ out_desc->callback = atmel_aes_dma_callback;
-+ out_desc->callback_param = dd;
-+
-+ dd->total -= dd->req->nbytes;
-+
-+ dmaengine_submit(out_desc);
-+ dma_async_issue_pending(dd->dma_lch_out.chan);
-+
-+ dmaengine_submit(in_desc);
-+ dma_async_issue_pending(dd->dma_lch_in.chan);
-+
-+ return 0;
-+
-+unmap_out:
-+ dma_unmap_sg(dd->dev, dd->out_sg, dd->nb_out_sg,
-+ DMA_FROM_DEVICE);
-+unmap_in:
-+ dma_unmap_sg(dd->dev, dd->in_sg, dd->nb_in_sg,
-+ DMA_TO_DEVICE);
-+exit_err:
-+ return -EINVAL;
-+}
-+
-+static int atmel_aes_crypt_cpu_start(struct atmel_aes_dev *dd)
-+{
-+ dd->flags &= ~AES_FLAGS_DMA;
-+
-+ /* use cache buffers */
-+ dd->nb_in_sg = atmel_aes_sg_length(dd->req, dd->in_sg);
-+ if (!dd->nb_in_sg)
-+ return -EINVAL;
-+
-+ dd->nb_out_sg = atmel_aes_sg_length(dd->req, dd->out_sg);
-+ if (!dd->nb_in_sg)
-+ return -EINVAL;
-+
-+ dd->bufcnt = sg_copy_to_buffer(dd->in_sg, dd->nb_in_sg,
-+ dd->buf_in, dd->total);
-+
-+ if (!dd->bufcnt)
-+ return -EINVAL;
-+
-+ dd->total -= dd->bufcnt;
-+
-+ atmel_aes_write(dd, AES_IER, AES_INT_DATARDY);
-+ atmel_aes_write_n(dd, AES_IDATAR(0), (u32 *) dd->buf_in,
-+ dd->bufcnt >> 2);
-+
-+ return 0;
-+}
-+
-+static int atmel_aes_crypt_dma_start(struct atmel_aes_dev *dd)
-+{
-+ int err;
-+
-+ if (dd->flags & AES_FLAGS_CFB8) {
-+ dd->dma_lch_in.dma_conf.dst_addr_width =
-+ DMA_SLAVE_BUSWIDTH_1_BYTE;
-+ dd->dma_lch_out.dma_conf.src_addr_width =
-+ DMA_SLAVE_BUSWIDTH_1_BYTE;
-+ } else if (dd->flags & AES_FLAGS_CFB16) {
-+ dd->dma_lch_in.dma_conf.dst_addr_width =
-+ DMA_SLAVE_BUSWIDTH_2_BYTES;
-+ dd->dma_lch_out.dma_conf.src_addr_width =
-+ DMA_SLAVE_BUSWIDTH_2_BYTES;
-+ } else {
-+ dd->dma_lch_in.dma_conf.dst_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
-+ dd->dma_lch_out.dma_conf.src_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
-+ }
-+
-+ dmaengine_slave_config(dd->dma_lch_in.chan, &dd->dma_lch_in.dma_conf);
-+ dmaengine_slave_config(dd->dma_lch_out.chan, &dd->dma_lch_out.dma_conf);
-+
-+ dd->flags |= AES_FLAGS_DMA;
-+ err = atmel_aes_crypt_dma(dd);
-+
-+ return err;
-+}
-+
-+static int atmel_aes_write_ctrl(struct atmel_aes_dev *dd)
-+{
-+ int err;
-+ u32 valcr = 0, valmr = 0;
-+
-+ err = atmel_aes_hw_init(dd);
-+
-+ if (err)
-+ return err;
-+
-+ /* MR register must be set before IV registers */
-+ if (dd->ctx->keylen == AES_KEYSIZE_128)
-+ valmr |= AES_MR_KEYSIZE_128;
-+ else if (dd->ctx->keylen == AES_KEYSIZE_192)
-+ valmr |= AES_MR_KEYSIZE_192;
-+ else
-+ valmr |= AES_MR_KEYSIZE_256;
-+
-+ if (dd->flags & AES_FLAGS_CBC) {
-+ valmr |= AES_MR_OPMOD_CBC;
-+ } else if (dd->flags & AES_FLAGS_CFB) {
-+ valmr |= AES_MR_OPMOD_CFB;
-+ if (dd->flags & AES_FLAGS_CFB8)
-+ valmr |= AES_MR_CFBS_8b;
-+ else if (dd->flags & AES_FLAGS_CFB16)
-+ valmr |= AES_MR_CFBS_16b;
-+ else if (dd->flags & AES_FLAGS_CFB32)
-+ valmr |= AES_MR_CFBS_32b;
-+ else if (dd->flags & AES_FLAGS_CFB64)
-+ valmr |= AES_MR_CFBS_64b;
-+ } else if (dd->flags & AES_FLAGS_OFB) {
-+ valmr |= AES_MR_OPMOD_OFB;
-+ } else if (dd->flags & AES_FLAGS_CTR) {
-+ valmr |= AES_MR_OPMOD_CTR;
-+ } else {
-+ valmr |= AES_MR_OPMOD_ECB;
-+ }
-+
-+ if (dd->flags & AES_FLAGS_ENCRYPT)
-+ valmr |= AES_MR_CYPHER_ENC;
-+
-+ if (dd->total > ATMEL_AES_DMA_THRESHOLD) {
-+ valmr |= AES_MR_SMOD_IDATAR0;
-+ if (dd->flags & AES_FLAGS_DUALBUFF)
-+ valmr |= AES_MR_DUALBUFF;
-+ } else {
-+ valmr |= AES_MR_SMOD_AUTO;
-+ }
-+
-+ atmel_aes_write(dd, AES_CR, valcr);
-+ atmel_aes_write(dd, AES_MR, valmr);
-+
-+ atmel_aes_write_n(dd, AES_KEYWR(0), dd->ctx->key,
-+ dd->ctx->keylen >> 2);
-+
-+ if (((dd->flags & AES_FLAGS_CBC) || (dd->flags & AES_FLAGS_CFB) ||
-+ (dd->flags & AES_FLAGS_OFB) || (dd->flags & AES_FLAGS_CTR)) &&
-+ dd->req->info) {
-+ atmel_aes_write_n(dd, AES_IVR(0), dd->req->info, 4);
-+ }
-+
-+ return 0;
-+}
-+
-+static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
-+ struct ablkcipher_request *req)
-+{
-+ struct crypto_async_request *async_req, *backlog;
-+ struct atmel_aes_ctx *ctx;
-+ struct atmel_aes_reqctx *rctx;
-+ unsigned long flags;
-+ int err, ret = 0;
-+
-+ spin_lock_irqsave(&dd->lock, flags);
-+ if (req)
-+ ret = ablkcipher_enqueue_request(&dd->queue, req);
-+ if (dd->flags & AES_FLAGS_BUSY) {
-+ spin_unlock_irqrestore(&dd->lock, flags);
-+ return ret;
-+ }
-+ backlog = crypto_get_backlog(&dd->queue);
-+ async_req = crypto_dequeue_request(&dd->queue);
-+ if (async_req)
-+ dd->flags |= AES_FLAGS_BUSY;
-+ spin_unlock_irqrestore(&dd->lock, flags);
-+
-+ if (!async_req)
-+ return ret;
-+
-+ if (backlog)
-+ backlog->complete(backlog, -EINPROGRESS);
-+
-+ req = ablkcipher_request_cast(async_req);
-+
-+ /* assign new request to device */
-+ dd->req = req;
-+ dd->total = req->nbytes;
-+ dd->in_sg = req->src;
-+ dd->out_sg = req->dst;
-+
-+ rctx = ablkcipher_request_ctx(req);
-+ ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req));
-+ rctx->mode &= AES_FLAGS_MODE_MASK;
-+ dd->flags = (dd->flags & ~AES_FLAGS_MODE_MASK) | rctx->mode;
-+ dd->ctx = ctx;
-+ ctx->dd = dd;
-+
-+ err = atmel_aes_write_ctrl(dd);
-+ if (!err) {
-+ if (dd->total > ATMEL_AES_DMA_THRESHOLD)
-+ err = atmel_aes_crypt_dma_start(dd);
-+ else
-+ err = atmel_aes_crypt_cpu_start(dd);
-+ }
-+ if (err) {
-+ /* aes_task will not finish it, so do it here */
-+ atmel_aes_finish_req(dd, err);
-+ tasklet_schedule(&dd->queue_task);
-+ }
-+
-+ return ret;
-+}
-+
-+static int atmel_aes_crypt_dma_stop(struct atmel_aes_dev *dd)
-+{
-+ int err = -EINVAL;
-+
-+ if (dd->flags & AES_FLAGS_DMA) {
-+ dma_unmap_sg(dd->dev, dd->out_sg,
-+ dd->nb_out_sg, DMA_FROM_DEVICE);
-+ dma_unmap_sg(dd->dev, dd->in_sg,
-+ dd->nb_in_sg, DMA_TO_DEVICE);
-+ err = 0;
-+ }
-+
-+ return err;
-+}
-+
-+static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
-+{
-+ struct atmel_aes_ctx *ctx = crypto_ablkcipher_ctx(
-+ crypto_ablkcipher_reqtfm(req));
-+ struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req);
-+ struct atmel_aes_dev *dd;
-+
-+ if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) {
-+ pr_err("request size is not exact amount of AES blocks\n");
-+ return -EINVAL;
-+ }
-+
-+ dd = atmel_aes_find_dev(ctx);
-+ if (!dd)
-+ return -ENODEV;
-+
-+ rctx->mode = mode;
-+
-+ return atmel_aes_handle_queue(dd, req);
-+}
-+
-+static bool atmel_aes_filter(struct dma_chan *chan, void *slave)
-+{
-+ struct at_dma_slave *sl = slave;
-+
-+ if (sl && sl->dma_dev == chan->device->dev) {
-+ chan->private = sl;
-+ return true;
-+ } else {
-+ return false;
-+ }
-+}
-+
-+static int atmel_aes_dma_init(struct atmel_aes_dev *dd)
-+{
-+ int err = -ENOMEM;
-+ struct aes_platform_data *pdata;
-+ dma_cap_mask_t mask_in, mask_out;
-+
-+ pdata = dd->dev->platform_data;
-+
-+ if (pdata && pdata->dma_slave->txdata.dma_dev &&
-+ pdata->dma_slave->rxdata.dma_dev) {
-+
-+ /* Try to grab 2 DMA channels */
-+ dma_cap_zero(mask_in);
-+ dma_cap_set(DMA_SLAVE, mask_in);
-+
-+ dd->dma_lch_in.chan = dma_request_channel(mask_in,
-+ atmel_aes_filter, &pdata->dma_slave->rxdata);
-+ if (!dd->dma_lch_in.chan)
-+ goto err_dma_in;
-+
-+ dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV;
-+ dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base +
-+ AES_IDATAR(0);
-+ dd->dma_lch_in.dma_conf.src_maxburst = 1;
-+ dd->dma_lch_in.dma_conf.dst_maxburst = 1;
-+ dd->dma_lch_in.dma_conf.device_fc = false;
-+
-+ dma_cap_zero(mask_out);
-+ dma_cap_set(DMA_SLAVE, mask_out);
-+ dd->dma_lch_out.chan = dma_request_channel(mask_out,
-+ atmel_aes_filter, &pdata->dma_slave->txdata);
-+ if (!dd->dma_lch_out.chan)
-+ goto err_dma_out;
-+
-+ dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM;
-+ dd->dma_lch_out.dma_conf.src_addr = dd->phys_base +
-+ AES_ODATAR(0);
-+ dd->dma_lch_out.dma_conf.src_maxburst = 1;
-+ dd->dma_lch_out.dma_conf.dst_maxburst = 1;
-+ dd->dma_lch_out.dma_conf.device_fc = false;
-+
-+ return 0;
-+ } else {
-+ return -ENODEV;
-+ }
-+
-+err_dma_out:
-+ dma_release_channel(dd->dma_lch_in.chan);
-+err_dma_in:
-+ return err;
-+}
-+
-+static void atmel_aes_dma_cleanup(struct atmel_aes_dev *dd)
-+{
-+ dma_release_channel(dd->dma_lch_in.chan);
-+ dma_release_channel(dd->dma_lch_out.chan);
-+}
-+
-+static int atmel_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
-+ unsigned int keylen)
-+{
-+ struct atmel_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
-+
-+ if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
-+ keylen != AES_KEYSIZE_256) {
-+ crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
-+ return -EINVAL;
-+ }
-+
-+ memcpy(ctx->key, key, keylen);
-+ ctx->keylen = keylen;
-+
-+ return 0;
-+}
-+
-+static int atmel_aes_ecb_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_ENCRYPT);
-+}
-+
-+static int atmel_aes_ecb_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ 0);
-+}
-+
-+static int atmel_aes_cbc_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_ENCRYPT | AES_FLAGS_CBC);
-+}
-+
-+static int atmel_aes_cbc_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_CBC);
-+}
-+
-+static int atmel_aes_ofb_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_ENCRYPT | AES_FLAGS_OFB);
-+}
-+
-+static int atmel_aes_ofb_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_OFB);
-+}
-+
-+static int atmel_aes_cfb_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_ENCRYPT | AES_FLAGS_CFB);
-+}
-+
-+static int atmel_aes_cfb_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_CFB);
-+}
-+
-+static int atmel_aes_cfb64_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_ENCRYPT | AES_FLAGS_CFB | AES_FLAGS_CFB64);
-+}
-+
-+static int atmel_aes_cfb64_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_CFB | AES_FLAGS_CFB64);
-+}
-+
-+static int atmel_aes_cfb32_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_ENCRYPT | AES_FLAGS_CFB | AES_FLAGS_CFB32);
-+}
-+
-+static int atmel_aes_cfb32_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_CFB | AES_FLAGS_CFB32);
-+}
-+
-+static int atmel_aes_cfb16_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_ENCRYPT | AES_FLAGS_CFB | AES_FLAGS_CFB16);
-+}
-+
-+static int atmel_aes_cfb16_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_CFB | AES_FLAGS_CFB16);
-+}
-+
-+static int atmel_aes_cfb8_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_ENCRYPT | AES_FLAGS_CFB | AES_FLAGS_CFB8);
-+}
-+
-+static int atmel_aes_cfb8_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_CFB | AES_FLAGS_CFB8);
-+}
-+
-+static int atmel_aes_ctr_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_ENCRYPT | AES_FLAGS_CTR);
-+}
-+
-+static int atmel_aes_ctr_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_aes_crypt(req,
-+ AES_FLAGS_CTR);
-+}
-+
-+static int atmel_aes_cra_init(struct crypto_tfm *tfm)
-+{
-+ tfm->crt_ablkcipher.reqsize = sizeof(struct atmel_aes_reqctx);
-+
-+ return 0;
-+}
-+
-+static void atmel_aes_cra_exit(struct crypto_tfm *tfm)
-+{
-+}
-+
-+static struct crypto_alg aes_algs[] = {
-+{
-+ .cra_name = "ecb(aes)",
-+ .cra_driver_name = "atmel-ecb-aes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = AES_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-+ .cra_alignmask = 0x0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_aes_cra_init,
-+ .cra_exit = atmel_aes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = AES_MIN_KEY_SIZE,
-+ .max_keysize = AES_MAX_KEY_SIZE,
-+ .setkey = atmel_aes_setkey,
-+ .encrypt = atmel_aes_ecb_encrypt,
-+ .decrypt = atmel_aes_ecb_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "cbc(aes)",
-+ .cra_driver_name = "atmel-cbc-aes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = AES_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-+ .cra_alignmask = 0x0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_aes_cra_init,
-+ .cra_exit = atmel_aes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = AES_MIN_KEY_SIZE,
-+ .max_keysize = AES_MAX_KEY_SIZE,
-+ .ivsize = AES_BLOCK_SIZE,
-+ .setkey = atmel_aes_setkey,
-+ .encrypt = atmel_aes_cbc_encrypt,
-+ .decrypt = atmel_aes_cbc_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "ofb(aes)",
-+ .cra_driver_name = "atmel-ofb-aes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = AES_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-+ .cra_alignmask = 0x0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_aes_cra_init,
-+ .cra_exit = atmel_aes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = AES_MIN_KEY_SIZE,
-+ .max_keysize = AES_MAX_KEY_SIZE,
-+ .ivsize = AES_BLOCK_SIZE,
-+ .setkey = atmel_aes_setkey,
-+ .encrypt = atmel_aes_ofb_encrypt,
-+ .decrypt = atmel_aes_ofb_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "cfb(aes)",
-+ .cra_driver_name = "atmel-cfb-aes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = AES_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-+ .cra_alignmask = 0x0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_aes_cra_init,
-+ .cra_exit = atmel_aes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = AES_MIN_KEY_SIZE,
-+ .max_keysize = AES_MAX_KEY_SIZE,
-+ .ivsize = AES_BLOCK_SIZE,
-+ .setkey = atmel_aes_setkey,
-+ .encrypt = atmel_aes_cfb_encrypt,
-+ .decrypt = atmel_aes_cfb_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "cfb32(aes)",
-+ .cra_driver_name = "atmel-cfb32-aes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = CFB32_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-+ .cra_alignmask = 0x0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_aes_cra_init,
-+ .cra_exit = atmel_aes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = AES_MIN_KEY_SIZE,
-+ .max_keysize = AES_MAX_KEY_SIZE,
-+ .ivsize = AES_BLOCK_SIZE,
-+ .setkey = atmel_aes_setkey,
-+ .encrypt = atmel_aes_cfb32_encrypt,
-+ .decrypt = atmel_aes_cfb32_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "cfb16(aes)",
-+ .cra_driver_name = "atmel-cfb16-aes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = CFB16_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-+ .cra_alignmask = 0x0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_aes_cra_init,
-+ .cra_exit = atmel_aes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = AES_MIN_KEY_SIZE,
-+ .max_keysize = AES_MAX_KEY_SIZE,
-+ .ivsize = AES_BLOCK_SIZE,
-+ .setkey = atmel_aes_setkey,
-+ .encrypt = atmel_aes_cfb16_encrypt,
-+ .decrypt = atmel_aes_cfb16_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "cfb8(aes)",
-+ .cra_driver_name = "atmel-cfb8-aes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = CFB64_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-+ .cra_alignmask = 0x0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_aes_cra_init,
-+ .cra_exit = atmel_aes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = AES_MIN_KEY_SIZE,
-+ .max_keysize = AES_MAX_KEY_SIZE,
-+ .ivsize = AES_BLOCK_SIZE,
-+ .setkey = atmel_aes_setkey,
-+ .encrypt = atmel_aes_cfb8_encrypt,
-+ .decrypt = atmel_aes_cfb8_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "ctr(aes)",
-+ .cra_driver_name = "atmel-ctr-aes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = AES_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-+ .cra_alignmask = 0x0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_aes_cra_init,
-+ .cra_exit = atmel_aes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = AES_MIN_KEY_SIZE,
-+ .max_keysize = AES_MAX_KEY_SIZE,
-+ .ivsize = AES_BLOCK_SIZE,
-+ .setkey = atmel_aes_setkey,
-+ .encrypt = atmel_aes_ctr_encrypt,
-+ .decrypt = atmel_aes_ctr_decrypt,
-+ }
-+},
-+};
-+
-+static struct crypto_alg aes_cfb64_alg[] = {
-+{
-+ .cra_name = "cfb64(aes)",
-+ .cra_driver_name = "atmel-cfb64-aes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = CFB64_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-+ .cra_alignmask = 0x0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_aes_cra_init,
-+ .cra_exit = atmel_aes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = AES_MIN_KEY_SIZE,
-+ .max_keysize = AES_MAX_KEY_SIZE,
-+ .ivsize = AES_BLOCK_SIZE,
-+ .setkey = atmel_aes_setkey,
-+ .encrypt = atmel_aes_cfb64_encrypt,
-+ .decrypt = atmel_aes_cfb64_decrypt,
-+ }
-+},
-+};
-+
-+static void atmel_aes_queue_task(unsigned long data)
-+{
-+ struct atmel_aes_dev *dd = (struct atmel_aes_dev *)data;
-+
-+ atmel_aes_handle_queue(dd, NULL);
-+}
-+
-+static void atmel_aes_done_task(unsigned long data)
-+{
-+ struct atmel_aes_dev *dd = (struct atmel_aes_dev *) data;
-+ int err;
-+
-+ if (!(dd->flags & AES_FLAGS_DMA)) {
-+ atmel_aes_read_n(dd, AES_ODATAR(0), (u32 *) dd->buf_out,
-+ dd->bufcnt >> 2);
-+
-+ if (sg_copy_from_buffer(dd->out_sg, dd->nb_out_sg,
-+ dd->buf_out, dd->bufcnt))
-+ err = 0;
-+ else
-+ err = -EINVAL;
-+
-+ goto cpu_end;
-+ }
-+
-+ err = atmel_aes_crypt_dma_stop(dd);
-+
-+ err = dd->err ? : err;
-+
-+ if (dd->total && !err) {
-+ err = atmel_aes_crypt_dma_start(dd);
-+ if (!err)
-+ return; /* DMA started. Not fininishing. */
-+ }
-+
-+cpu_end:
-+ atmel_aes_finish_req(dd, err);
-+ atmel_aes_handle_queue(dd, NULL);
-+}
-+
-+static irqreturn_t atmel_aes_irq(int irq, void *dev_id)
-+{
-+ struct atmel_aes_dev *aes_dd = dev_id;
-+ u32 reg;
-+
-+ reg = atmel_aes_read(aes_dd, AES_ISR);
-+ if (reg & atmel_aes_read(aes_dd, AES_IMR)) {
-+ atmel_aes_write(aes_dd, AES_IDR, reg);
-+ if (AES_FLAGS_BUSY & aes_dd->flags)
-+ tasklet_schedule(&aes_dd->done_task);
-+ else
-+ dev_warn(aes_dd->dev, "AES interrupt when no active requests.\n");
-+ return IRQ_HANDLED;
-+ }
-+
-+ return IRQ_NONE;
-+}
-+
-+static void atmel_aes_unregister_algs(struct atmel_aes_dev *dd)
-+{
-+ int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(aes_algs); i++)
-+ crypto_unregister_alg(&aes_algs[i]);
-+ if (dd->hw_version >= 0x130)
-+ crypto_unregister_alg(&aes_cfb64_alg[0]);
-+}
-+
-+static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
-+{
-+ int err, i, j;
-+
-+ for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
-+ INIT_LIST_HEAD(&aes_algs[i].cra_list);
-+ err = crypto_register_alg(&aes_algs[i]);
-+ if (err)
-+ goto err_aes_algs;
-+ }
-+
-+ atmel_aes_hw_version_init(dd);
-+
-+ if (dd->hw_version >= 0x130) {
-+ INIT_LIST_HEAD(&aes_cfb64_alg[0].cra_list);
-+ err = crypto_register_alg(&aes_cfb64_alg[0]);
-+ if (err)
-+ goto err_aes_cfb64_alg;
-+ }
-+
-+ return 0;
-+
-+err_aes_cfb64_alg:
-+ i = ARRAY_SIZE(aes_algs);
-+err_aes_algs:
-+ for (j = 0; j < i; j++)
-+ crypto_unregister_alg(&aes_algs[j]);
-+
-+ return err;
-+}
-+
-+static int __devinit atmel_aes_probe(struct platform_device *pdev)
-+{
-+ struct atmel_aes_dev *aes_dd;
-+ struct aes_platform_data *pdata;
-+ struct device *dev = &pdev->dev;
-+ struct resource *aes_res;
-+ unsigned long aes_phys_size;
-+ int err;
-+
-+ pdata = pdev->dev.platform_data;
-+ if (!pdata) {
-+ err = -ENXIO;
-+ goto aes_dd_err;
-+ }
-+
-+ aes_dd = kzalloc(sizeof(struct atmel_aes_dev), GFP_KERNEL);
-+ if (aes_dd == NULL) {
-+ dev_err(dev, "unable to alloc data struct.\n");
-+ err = -ENOMEM;
-+ goto aes_dd_err;
-+ }
-+
-+ aes_dd->dev = dev;
-+
-+ platform_set_drvdata(pdev, aes_dd);
-+
-+ INIT_LIST_HEAD(&aes_dd->list);
-+
-+ tasklet_init(&aes_dd->done_task, atmel_aes_done_task,
-+ (unsigned long)aes_dd);
-+ tasklet_init(&aes_dd->queue_task, atmel_aes_queue_task,
-+ (unsigned long)aes_dd);
-+
-+ crypto_init_queue(&aes_dd->queue, ATMEL_AES_QUEUE_LENGTH);
-+
-+ aes_dd->irq = -1;
-+
-+ /* Get the base address */
-+ aes_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!aes_res) {
-+ dev_err(dev, "no MEM resource info\n");
-+ err = -ENODEV;
-+ goto res_err;
-+ }
-+ aes_dd->phys_base = aes_res->start;
-+ aes_phys_size = resource_size(aes_res);
-+
-+ /* Get the IRQ */
-+ aes_dd->irq = platform_get_irq(pdev, 0);
-+ if (aes_dd->irq < 0) {
-+ dev_err(dev, "no IRQ resource info\n");
-+ err = aes_dd->irq;
-+ goto aes_irq_err;
-+ }
-+
-+ err = request_irq(aes_dd->irq, atmel_aes_irq, IRQF_SHARED, "atmel-aes",
-+ aes_dd);
-+ if (err) {
-+ dev_err(dev, "unable to request aes irq.\n");
-+ goto aes_irq_err;
-+ }
-+
-+ /* Initializing the clock */
-+ aes_dd->iclk = clk_get(&pdev->dev, NULL);
-+ if (IS_ERR(aes_dd->iclk)) {
-+ dev_err(dev, "clock intialization failed.\n");
-+ err = PTR_ERR(aes_dd->iclk);
-+ goto clk_err;
-+ }
-+
-+ aes_dd->io_base = ioremap(aes_dd->phys_base, aes_phys_size);
-+ if (!aes_dd->io_base) {
-+ dev_err(dev, "can't ioremap\n");
-+ err = -ENOMEM;
-+ goto aes_io_err;
-+ }
-+
-+ err = atmel_aes_dma_init(aes_dd);
-+ if (err)
-+ goto err_aes_dma;
-+
-+ spin_lock(&atmel_aes.lock);
-+ list_add_tail(&aes_dd->list, &atmel_aes.dev_list);
-+ spin_unlock(&atmel_aes.lock);
-+
-+ err = atmel_aes_register_algs(aes_dd);
-+ if (err)
-+ goto err_algs;
-+
-+ dev_info(dev, "Atmel AES\n");
-+
-+ return 0;
-+
-+err_algs:
-+ spin_lock(&atmel_aes.lock);
-+ list_del(&aes_dd->list);
-+ spin_unlock(&atmel_aes.lock);
-+ atmel_aes_dma_cleanup(aes_dd);
-+err_aes_dma:
-+ iounmap(aes_dd->io_base);
-+aes_io_err:
-+ clk_put(aes_dd->iclk);
-+clk_err:
-+ free_irq(aes_dd->irq, aes_dd);
-+aes_irq_err:
-+res_err:
-+ tasklet_kill(&aes_dd->done_task);
-+ tasklet_kill(&aes_dd->queue_task);
-+ kfree(aes_dd);
-+ aes_dd = NULL;
-+aes_dd_err:
-+ dev_err(dev, "initialization failed.\n");
-+
-+ return err;
-+}
-+
-+static int __devexit atmel_aes_remove(struct platform_device *pdev)
-+{
-+ static struct atmel_aes_dev *aes_dd;
-+
-+ aes_dd = platform_get_drvdata(pdev);
-+ if (!aes_dd)
-+ return -ENODEV;
-+ spin_lock(&atmel_aes.lock);
-+ list_del(&aes_dd->list);
-+ spin_unlock(&atmel_aes.lock);
-+
-+ atmel_aes_unregister_algs(aes_dd);
-+
-+ tasklet_kill(&aes_dd->done_task);
-+ tasklet_kill(&aes_dd->queue_task);
-+
-+ atmel_aes_dma_cleanup(aes_dd);
-+
-+ iounmap(aes_dd->io_base);
-+
-+ clk_put(aes_dd->iclk);
-+
-+ if (aes_dd->irq > 0)
-+ free_irq(aes_dd->irq, aes_dd);
-+
-+ kfree(aes_dd);
-+ aes_dd = NULL;
-+
-+ return 0;
-+}
-+
-+static struct platform_driver atmel_aes_driver = {
-+ .probe = atmel_aes_probe,
-+ .remove = __devexit_p(atmel_aes_remove),
-+ .driver = {
-+ .name = "atmel_aes",
-+ .owner = THIS_MODULE,
-+ },
-+};
-+
-+module_platform_driver(atmel_aes_driver);
-+
-+MODULE_DESCRIPTION("Atmel AES hw acceleration support.");
-+MODULE_LICENSE("GPL v2");
-+MODULE_AUTHOR("Nicolas Royer - Eukréa Electromatique");
-diff --git a/include/linux/platform_data/atmel-aes.h b/include/linux/platform_data/atmel-aes.h
-new file mode 100644
-index 0000000..e7a1949
---- /dev/null
-+++ b/include/linux/platform_data/atmel-aes.h
-@@ -0,0 +1,22 @@
-+#ifndef __LINUX_ATMEL_AES_H
-+#define __LINUX_ATMEL_AES_H
-+
-+#include <mach/at_hdmac.h>
-+
-+/**
-+ * struct aes_dma_data - DMA data for AES
-+ */
-+struct aes_dma_data {
-+ struct at_dma_slave txdata;
-+ struct at_dma_slave rxdata;
-+};
-+
-+/**
-+ * struct aes_platform_data - board-specific AES configuration
-+ * @dma_slave: DMA slave interface to use in data transfers.
-+ */
-+struct aes_platform_data {
-+ struct aes_dma_data *dma_slave;
-+};
-+
-+#endif /* __LINUX_ATMEL_AES_H */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 7ba996263729126963359429782339ddf8705333 Mon Sep 17 00:00:00 2001
-From: Nicolas Royer <nicolas@eukrea.com>
-Date: Mon, 17 Sep 2012 18:26:05 +0200
-Subject: crypto: add Atmel DES/TDES driver
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-commit 13802005d8f2db244ec1f5d7f6923de8f7a463db upstream.
-
-Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Eric Bénard <eric@eukrea.com>
-Tested-by: Eric Bénard <eric@eukrea.com>
----
- drivers/crypto/Kconfig | 16 +
- drivers/crypto/Makefile | 1 +
- drivers/crypto/atmel-tdes-regs.h | 89 +++
- drivers/crypto/atmel-tdes.c | 1215 ++++++++++++++++++++++++++++++++++++++
- 4 files changed, 1321 insertions(+)
- create mode 100644 drivers/crypto/atmel-tdes-regs.h
- create mode 100644 drivers/crypto/atmel-tdes.c
-
-diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
-index 98c7da5..2124898 100644
---- a/drivers/crypto/Kconfig
-+++ b/drivers/crypto/Kconfig
-@@ -313,4 +313,20 @@ config CRYPTO_DEV_ATMEL_AES
- To compile this driver as a module, choose M here: the module
- will be called atmel-aes.
-
-+config CRYPTO_DEV_ATMEL_TDES
-+ tristate "Support for Atmel DES/TDES hw accelerator"
-+ depends on ARCH_AT91
-+ select CRYPTO_DES
-+ select CRYPTO_CBC
-+ select CRYPTO_ECB
-+ select CRYPTO_ALGAPI
-+ select CRYPTO_BLKCIPHER
-+ help
-+ Some Atmel processors have DES/TDES hw accelerator.
-+ Select this if you want to use the Atmel module for
-+ DES/TDES algorithms.
-+
-+ To compile this driver as a module, choose M here: the module
-+ will be called atmel-tdes.
-+
- endif # CRYPTO_HW
-diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
-index 73ad830..443bf4d 100644
---- a/drivers/crypto/Makefile
-+++ b/drivers/crypto/Makefile
-@@ -15,3 +15,4 @@ obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o
- obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o
- obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o
- obj-$(CONFIG_CRYPTO_DEV_ATMEL_AES) += atmel-aes.o
-+obj-$(CONFIG_CRYPTO_DEV_ATMEL_TDES) += atmel-tdes.o
-diff --git a/drivers/crypto/atmel-tdes-regs.h b/drivers/crypto/atmel-tdes-regs.h
-new file mode 100644
-index 0000000..5ac2a90
---- /dev/null
-+++ b/drivers/crypto/atmel-tdes-regs.h
-@@ -0,0 +1,89 @@
-+#ifndef __ATMEL_TDES_REGS_H__
-+#define __ATMEL_TDES_REGS_H__
-+
-+#define TDES_CR 0x00
-+#define TDES_CR_START (1 << 0)
-+#define TDES_CR_SWRST (1 << 8)
-+#define TDES_CR_LOADSEED (1 << 16)
-+
-+#define TDES_MR 0x04
-+#define TDES_MR_CYPHER_DEC (0 << 0)
-+#define TDES_MR_CYPHER_ENC (1 << 0)
-+#define TDES_MR_TDESMOD_MASK (0x3 << 1)
-+#define TDES_MR_TDESMOD_DES (0x0 << 1)
-+#define TDES_MR_TDESMOD_TDES (0x1 << 1)
-+#define TDES_MR_TDESMOD_XTEA (0x2 << 1)
-+#define TDES_MR_KEYMOD_3KEY (0 << 4)
-+#define TDES_MR_KEYMOD_2KEY (1 << 4)
-+#define TDES_MR_SMOD_MASK (0x3 << 8)
-+#define TDES_MR_SMOD_MANUAL (0x0 << 8)
-+#define TDES_MR_SMOD_AUTO (0x1 << 8)
-+#define TDES_MR_SMOD_PDC (0x2 << 8)
-+#define TDES_MR_OPMOD_MASK (0x3 << 12)
-+#define TDES_MR_OPMOD_ECB (0x0 << 12)
-+#define TDES_MR_OPMOD_CBC (0x1 << 12)
-+#define TDES_MR_OPMOD_OFB (0x2 << 12)
-+#define TDES_MR_OPMOD_CFB (0x3 << 12)
-+#define TDES_MR_LOD (0x1 << 15)
-+#define TDES_MR_CFBS_MASK (0x3 << 16)
-+#define TDES_MR_CFBS_64b (0x0 << 16)
-+#define TDES_MR_CFBS_32b (0x1 << 16)
-+#define TDES_MR_CFBS_16b (0x2 << 16)
-+#define TDES_MR_CFBS_8b (0x3 << 16)
-+#define TDES_MR_CKEY_MASK (0xF << 20)
-+#define TDES_MR_CKEY_OFFSET 20
-+#define TDES_MR_CTYPE_MASK (0x3F << 24)
-+#define TDES_MR_CTYPE_OFFSET 24
-+
-+#define TDES_IER 0x10
-+#define TDES_IDR 0x14
-+#define TDES_IMR 0x18
-+#define TDES_ISR 0x1C
-+#define TDES_INT_DATARDY (1 << 0)
-+#define TDES_INT_ENDRX (1 << 1)
-+#define TDES_INT_ENDTX (1 << 2)
-+#define TDES_INT_RXBUFF (1 << 3)
-+#define TDES_INT_TXBUFE (1 << 4)
-+#define TDES_INT_URAD (1 << 8)
-+#define TDES_ISR_URAT_MASK (0x3 << 12)
-+#define TDES_ISR_URAT_IDR (0x0 << 12)
-+#define TDES_ISR_URAT_ODR (0x1 << 12)
-+#define TDES_ISR_URAT_MR (0x2 << 12)
-+#define TDES_ISR_URAT_WO (0x3 << 12)
-+
-+
-+#define TDES_KEY1W1R 0x20
-+#define TDES_KEY1W2R 0x24
-+#define TDES_KEY2W1R 0x28
-+#define TDES_KEY2W2R 0x2C
-+#define TDES_KEY3W1R 0x30
-+#define TDES_KEY3W2R 0x34
-+#define TDES_IDATA1R 0x40
-+#define TDES_IDATA2R 0x44
-+#define TDES_ODATA1R 0x50
-+#define TDES_ODATA2R 0x54
-+#define TDES_IV1R 0x60
-+#define TDES_IV2R 0x64
-+
-+#define TDES_XTEARNDR 0x70
-+#define TDES_XTEARNDR_XTEA_RNDS_MASK (0x3F << 0)
-+#define TDES_XTEARNDR_XTEA_RNDS_OFFSET 0
-+
-+#define TDES_RPR 0x100
-+#define TDES_RCR 0x104
-+#define TDES_TPR 0x108
-+#define TDES_TCR 0x10C
-+#define TDES_RNPR 0x118
-+#define TDES_RNCR 0x11C
-+#define TDES_TNPR 0x118
-+#define TDES_TNCR 0x11C
-+#define TDES_PTCR 0x120
-+#define TDES_PTCR_RXTEN (1 << 0)
-+#define TDES_PTCR_RXTDIS (1 << 1)
-+#define TDES_PTCR_TXTEN (1 << 8)
-+#define TDES_PTCR_TXTDIS (1 << 9)
-+#define TDES_PTSR 0x124
-+#define TDES_PTSR_RXTEN (1 << 0)
-+#define TDES_PTSR_TXTEN (1 << 8)
-+
-+#endif /* __ATMEL_TDES_REGS_H__ */
-diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c
-new file mode 100644
-index 0000000..eb2b61e
---- /dev/null
-+++ b/drivers/crypto/atmel-tdes.c
-@@ -0,0 +1,1215 @@
-+/*
-+ * Cryptographic API.
-+ *
-+ * Support for ATMEL DES/TDES HW acceleration.
-+ *
-+ * Copyright (c) 2012 Eukréa Electromatique - ATMEL
-+ * Author: Nicolas Royer <nicolas@eukrea.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 published
-+ * by the Free Software Foundation.
-+ *
-+ * Some ideas are from omap-aes.c drivers.
-+ */
-+
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/err.h>
-+#include <linux/clk.h>
-+#include <linux/io.h>
-+#include <linux/hw_random.h>
-+#include <linux/platform_device.h>
-+
-+#include <linux/device.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/interrupt.h>
-+#include <linux/kernel.h>
-+#include <linux/clk.h>
-+#include <linux/irq.h>
-+#include <linux/io.h>
-+#include <linux/platform_device.h>
-+#include <linux/scatterlist.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/delay.h>
-+#include <linux/crypto.h>
-+#include <linux/cryptohash.h>
-+#include <crypto/scatterwalk.h>
-+#include <crypto/algapi.h>
-+#include <crypto/des.h>
-+#include <crypto/hash.h>
-+#include <crypto/internal/hash.h>
-+#include "atmel-tdes-regs.h"
-+
-+/* TDES flags */
-+#define TDES_FLAGS_MODE_MASK 0x007f
-+#define TDES_FLAGS_ENCRYPT BIT(0)
-+#define TDES_FLAGS_CBC BIT(1)
-+#define TDES_FLAGS_CFB BIT(2)
-+#define TDES_FLAGS_CFB8 BIT(3)
-+#define TDES_FLAGS_CFB16 BIT(4)
-+#define TDES_FLAGS_CFB32 BIT(5)
-+#define TDES_FLAGS_OFB BIT(6)
-+
-+#define TDES_FLAGS_INIT BIT(16)
-+#define TDES_FLAGS_FAST BIT(17)
-+#define TDES_FLAGS_BUSY BIT(18)
-+
-+#define ATMEL_TDES_QUEUE_LENGTH 1
-+
-+#define CFB8_BLOCK_SIZE 1
-+#define CFB16_BLOCK_SIZE 2
-+#define CFB32_BLOCK_SIZE 4
-+#define CFB64_BLOCK_SIZE 8
-+
-+
-+struct atmel_tdes_dev;
-+
-+struct atmel_tdes_ctx {
-+ struct atmel_tdes_dev *dd;
-+
-+ int keylen;
-+ u32 key[3*DES_KEY_SIZE / sizeof(u32)];
-+ unsigned long flags;
-+};
-+
-+struct atmel_tdes_reqctx {
-+ unsigned long mode;
-+};
-+
-+struct atmel_tdes_dev {
-+ struct list_head list;
-+ unsigned long phys_base;
-+ void __iomem *io_base;
-+
-+ struct atmel_tdes_ctx *ctx;
-+ struct device *dev;
-+ struct clk *iclk;
-+ int irq;
-+
-+ unsigned long flags;
-+ int err;
-+
-+ spinlock_t lock;
-+ struct crypto_queue queue;
-+
-+ struct tasklet_struct done_task;
-+ struct tasklet_struct queue_task;
-+
-+ struct ablkcipher_request *req;
-+ size_t total;
-+
-+ struct scatterlist *in_sg;
-+ size_t in_offset;
-+ struct scatterlist *out_sg;
-+ size_t out_offset;
-+
-+ size_t buflen;
-+ size_t dma_size;
-+
-+ void *buf_in;
-+ int dma_in;
-+ dma_addr_t dma_addr_in;
-+
-+ void *buf_out;
-+ int dma_out;
-+ dma_addr_t dma_addr_out;
-+};
-+
-+struct atmel_tdes_drv {
-+ struct list_head dev_list;
-+ spinlock_t lock;
-+};
-+
-+static struct atmel_tdes_drv atmel_tdes = {
-+ .dev_list = LIST_HEAD_INIT(atmel_tdes.dev_list),
-+ .lock = __SPIN_LOCK_UNLOCKED(atmel_tdes.lock),
-+};
-+
-+static int atmel_tdes_sg_copy(struct scatterlist **sg, size_t *offset,
-+ void *buf, size_t buflen, size_t total, int out)
-+{
-+ unsigned int count, off = 0;
-+
-+ while (buflen && total) {
-+ count = min((*sg)->length - *offset, total);
-+ count = min(count, buflen);
-+
-+ if (!count)
-+ return off;
-+
-+ scatterwalk_map_and_copy(buf + off, *sg, *offset, count, out);
-+
-+ off += count;
-+ buflen -= count;
-+ *offset += count;
-+ total -= count;
-+
-+ if (*offset == (*sg)->length) {
-+ *sg = sg_next(*sg);
-+ if (*sg)
-+ *offset = 0;
-+ else
-+ total = 0;
-+ }
-+ }
-+
-+ return off;
-+}
-+
-+static inline u32 atmel_tdes_read(struct atmel_tdes_dev *dd, u32 offset)
-+{
-+ return readl_relaxed(dd->io_base + offset);
-+}
-+
-+static inline void atmel_tdes_write(struct atmel_tdes_dev *dd,
-+ u32 offset, u32 value)
-+{
-+ writel_relaxed(value, dd->io_base + offset);
-+}
-+
-+static void atmel_tdes_write_n(struct atmel_tdes_dev *dd, u32 offset,
-+ u32 *value, int count)
-+{
-+ for (; count--; value++, offset += 4)
-+ atmel_tdes_write(dd, offset, *value);
-+}
-+
-+static struct atmel_tdes_dev *atmel_tdes_find_dev(struct atmel_tdes_ctx *ctx)
-+{
-+ struct atmel_tdes_dev *tdes_dd = NULL;
-+ struct atmel_tdes_dev *tmp;
-+
-+ spin_lock_bh(&atmel_tdes.lock);
-+ if (!ctx->dd) {
-+ list_for_each_entry(tmp, &atmel_tdes.dev_list, list) {
-+ tdes_dd = tmp;
-+ break;
-+ }
-+ ctx->dd = tdes_dd;
-+ } else {
-+ tdes_dd = ctx->dd;
-+ }
-+ spin_unlock_bh(&atmel_tdes.lock);
-+
-+ return tdes_dd;
-+}
-+
-+static int atmel_tdes_hw_init(struct atmel_tdes_dev *dd)
-+{
-+ clk_prepare_enable(dd->iclk);
-+
-+ if (!(dd->flags & TDES_FLAGS_INIT)) {
-+ atmel_tdes_write(dd, TDES_CR, TDES_CR_SWRST);
-+ dd->flags |= TDES_FLAGS_INIT;
-+ dd->err = 0;
-+ }
-+
-+ return 0;
-+}
-+
-+static int atmel_tdes_write_ctrl(struct atmel_tdes_dev *dd)
-+{
-+ int err;
-+ u32 valcr = 0, valmr = TDES_MR_SMOD_PDC;
-+
-+ err = atmel_tdes_hw_init(dd);
-+
-+ if (err)
-+ return err;
-+
-+ atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS);
-+
-+ /* MR register must be set before IV registers */
-+ if (dd->ctx->keylen > (DES_KEY_SIZE << 1)) {
-+ valmr |= TDES_MR_KEYMOD_3KEY;
-+ valmr |= TDES_MR_TDESMOD_TDES;
-+ } else if (dd->ctx->keylen > DES_KEY_SIZE) {
-+ valmr |= TDES_MR_KEYMOD_2KEY;
-+ valmr |= TDES_MR_TDESMOD_TDES;
-+ } else {
-+ valmr |= TDES_MR_TDESMOD_DES;
-+ }
-+
-+ if (dd->flags & TDES_FLAGS_CBC) {
-+ valmr |= TDES_MR_OPMOD_CBC;
-+ } else if (dd->flags & TDES_FLAGS_CFB) {
-+ valmr |= TDES_MR_OPMOD_CFB;
-+
-+ if (dd->flags & TDES_FLAGS_CFB8)
-+ valmr |= TDES_MR_CFBS_8b;
-+ else if (dd->flags & TDES_FLAGS_CFB16)
-+ valmr |= TDES_MR_CFBS_16b;
-+ else if (dd->flags & TDES_FLAGS_CFB32)
-+ valmr |= TDES_MR_CFBS_32b;
-+ } else if (dd->flags & TDES_FLAGS_OFB) {
-+ valmr |= TDES_MR_OPMOD_OFB;
-+ }
-+
-+ if ((dd->flags & TDES_FLAGS_ENCRYPT) || (dd->flags & TDES_FLAGS_OFB))
-+ valmr |= TDES_MR_CYPHER_ENC;
-+
-+ atmel_tdes_write(dd, TDES_CR, valcr);
-+ atmel_tdes_write(dd, TDES_MR, valmr);
-+
-+ atmel_tdes_write_n(dd, TDES_KEY1W1R, dd->ctx->key,
-+ dd->ctx->keylen >> 2);
-+
-+ if (((dd->flags & TDES_FLAGS_CBC) || (dd->flags & TDES_FLAGS_CFB) ||
-+ (dd->flags & TDES_FLAGS_OFB)) && dd->req->info) {
-+ atmel_tdes_write_n(dd, TDES_IV1R, dd->req->info, 2);
-+ }
-+
-+ return 0;
-+}
-+
-+static int atmel_tdes_crypt_dma_stop(struct atmel_tdes_dev *dd)
-+{
-+ int err = 0;
-+ size_t count;
-+
-+ atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS);
-+
-+ if (dd->flags & TDES_FLAGS_FAST) {
-+ dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
-+ dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
-+ } else {
-+ dma_sync_single_for_device(dd->dev, dd->dma_addr_out,
-+ dd->dma_size, DMA_FROM_DEVICE);
-+
-+ /* copy data */
-+ count = atmel_tdes_sg_copy(&dd->out_sg, &dd->out_offset,
-+ dd->buf_out, dd->buflen, dd->dma_size, 1);
-+ if (count != dd->dma_size) {
-+ err = -EINVAL;
-+ pr_err("not all data converted: %u\n", count);
-+ }
-+ }
-+
-+ return err;
-+}
-+
-+static int atmel_tdes_dma_init(struct atmel_tdes_dev *dd)
-+{
-+ int err = -ENOMEM;
-+
-+ dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, 0);
-+ dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, 0);
-+ dd->buflen = PAGE_SIZE;
-+ dd->buflen &= ~(DES_BLOCK_SIZE - 1);
-+
-+ if (!dd->buf_in || !dd->buf_out) {
-+ dev_err(dd->dev, "unable to alloc pages.\n");
-+ goto err_alloc;
-+ }
-+
-+ /* MAP here */
-+ dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in,
-+ dd->buflen, DMA_TO_DEVICE);
-+ if (dma_mapping_error(dd->dev, dd->dma_addr_in)) {
-+ dev_err(dd->dev, "dma %d bytes error\n", dd->buflen);
-+ err = -EINVAL;
-+ goto err_map_in;
-+ }
-+
-+ dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out,
-+ dd->buflen, DMA_FROM_DEVICE);
-+ if (dma_mapping_error(dd->dev, dd->dma_addr_out)) {
-+ dev_err(dd->dev, "dma %d bytes error\n", dd->buflen);
-+ err = -EINVAL;
-+ goto err_map_out;
-+ }
-+
-+ return 0;
-+
-+err_map_out:
-+ dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen,
-+ DMA_TO_DEVICE);
-+err_map_in:
-+ free_page((unsigned long)dd->buf_out);
-+ free_page((unsigned long)dd->buf_in);
-+err_alloc:
-+ if (err)
-+ pr_err("error: %d\n", err);
-+ return err;
-+}
-+
-+static void atmel_tdes_dma_cleanup(struct atmel_tdes_dev *dd)
-+{
-+ dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
-+ DMA_FROM_DEVICE);
-+ dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen,
-+ DMA_TO_DEVICE);
-+ free_page((unsigned long)dd->buf_out);
-+ free_page((unsigned long)dd->buf_in);
-+}
-+
-+static int atmel_tdes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
-+ dma_addr_t dma_addr_out, int length)
-+{
-+ struct atmel_tdes_ctx *ctx = crypto_tfm_ctx(tfm);
-+ struct atmel_tdes_dev *dd = ctx->dd;
-+ int len32;
-+
-+ dd->dma_size = length;
-+
-+ if (!(dd->flags & TDES_FLAGS_FAST)) {
-+ dma_sync_single_for_device(dd->dev, dma_addr_in, length,
-+ DMA_TO_DEVICE);
-+ }
-+
-+ if ((dd->flags & TDES_FLAGS_CFB) && (dd->flags & TDES_FLAGS_CFB8))
-+ len32 = DIV_ROUND_UP(length, sizeof(u8));
-+ else if ((dd->flags & TDES_FLAGS_CFB) && (dd->flags & TDES_FLAGS_CFB16))
-+ len32 = DIV_ROUND_UP(length, sizeof(u16));
-+ else
-+ len32 = DIV_ROUND_UP(length, sizeof(u32));
-+
-+ atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS);
-+ atmel_tdes_write(dd, TDES_TPR, dma_addr_in);
-+ atmel_tdes_write(dd, TDES_TCR, len32);
-+ atmel_tdes_write(dd, TDES_RPR, dma_addr_out);
-+ atmel_tdes_write(dd, TDES_RCR, len32);
-+
-+ /* Enable Interrupt */
-+ atmel_tdes_write(dd, TDES_IER, TDES_INT_ENDRX);
-+
-+ /* Start DMA transfer */
-+ atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTEN | TDES_PTCR_RXTEN);
-+
-+ return 0;
-+}
-+
-+static int atmel_tdes_crypt_dma_start(struct atmel_tdes_dev *dd)
-+{
-+ struct crypto_tfm *tfm = crypto_ablkcipher_tfm(
-+ crypto_ablkcipher_reqtfm(dd->req));
-+ int err, fast = 0, in, out;
-+ size_t count;
-+ dma_addr_t addr_in, addr_out;
-+
-+ if (sg_is_last(dd->in_sg) && sg_is_last(dd->out_sg)) {
-+ /* check for alignment */
-+ in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32));
-+ out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32));
-+
-+ fast = in && out;
-+ }
-+
-+ if (fast) {
-+ count = min(dd->total, sg_dma_len(dd->in_sg));
-+ count = min(count, sg_dma_len(dd->out_sg));
-+
-+ if (count != dd->total) {
-+ pr_err("request length != buffer length\n");
-+ return -EINVAL;
-+ }
-+
-+ err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
-+ if (!err) {
-+ dev_err(dd->dev, "dma_map_sg() error\n");
-+ return -EINVAL;
-+ }
-+
-+ err = dma_map_sg(dd->dev, dd->out_sg, 1,
-+ DMA_FROM_DEVICE);
-+ if (!err) {
-+ dev_err(dd->dev, "dma_map_sg() error\n");
-+ dma_unmap_sg(dd->dev, dd->in_sg, 1,
-+ DMA_TO_DEVICE);
-+ return -EINVAL;
-+ }
-+
-+ addr_in = sg_dma_address(dd->in_sg);
-+ addr_out = sg_dma_address(dd->out_sg);
-+
-+ dd->flags |= TDES_FLAGS_FAST;
-+
-+ } else {
-+ /* use cache buffers */
-+ count = atmel_tdes_sg_copy(&dd->in_sg, &dd->in_offset,
-+ dd->buf_in, dd->buflen, dd->total, 0);
-+
-+ addr_in = dd->dma_addr_in;
-+ addr_out = dd->dma_addr_out;
-+
-+ dd->flags &= ~TDES_FLAGS_FAST;
-+
-+ }
-+
-+ dd->total -= count;
-+
-+ err = atmel_tdes_crypt_dma(tfm, addr_in, addr_out, count);
-+ if (err) {
-+ dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
-+ dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
-+ }
-+
-+ return err;
-+}
-+
-+
-+static void atmel_tdes_finish_req(struct atmel_tdes_dev *dd, int err)
-+{
-+ struct ablkcipher_request *req = dd->req;
-+
-+ clk_disable_unprepare(dd->iclk);
-+
-+ dd->flags &= ~TDES_FLAGS_BUSY;
-+
-+ req->base.complete(&req->base, err);
-+}
-+
-+static int atmel_tdes_handle_queue(struct atmel_tdes_dev *dd,
-+ struct ablkcipher_request *req)
-+{
-+ struct crypto_async_request *async_req, *backlog;
-+ struct atmel_tdes_ctx *ctx;
-+ struct atmel_tdes_reqctx *rctx;
-+ unsigned long flags;
-+ int err, ret = 0;
-+
-+ spin_lock_irqsave(&dd->lock, flags);
-+ if (req)
-+ ret = ablkcipher_enqueue_request(&dd->queue, req);
-+ if (dd->flags & TDES_FLAGS_BUSY) {
-+ spin_unlock_irqrestore(&dd->lock, flags);
-+ return ret;
-+ }
-+ backlog = crypto_get_backlog(&dd->queue);
-+ async_req = crypto_dequeue_request(&dd->queue);
-+ if (async_req)
-+ dd->flags |= TDES_FLAGS_BUSY;
-+ spin_unlock_irqrestore(&dd->lock, flags);
-+
-+ if (!async_req)
-+ return ret;
-+
-+ if (backlog)
-+ backlog->complete(backlog, -EINPROGRESS);
-+
-+ req = ablkcipher_request_cast(async_req);
-+
-+ /* assign new request to device */
-+ dd->req = req;
-+ dd->total = req->nbytes;
-+ dd->in_offset = 0;
-+ dd->in_sg = req->src;
-+ dd->out_offset = 0;
-+ dd->out_sg = req->dst;
-+
-+ rctx = ablkcipher_request_ctx(req);
-+ ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req));
-+ rctx->mode &= TDES_FLAGS_MODE_MASK;
-+ dd->flags = (dd->flags & ~TDES_FLAGS_MODE_MASK) | rctx->mode;
-+ dd->ctx = ctx;
-+ ctx->dd = dd;
-+
-+ err = atmel_tdes_write_ctrl(dd);
-+ if (!err)
-+ err = atmel_tdes_crypt_dma_start(dd);
-+ if (err) {
-+ /* des_task will not finish it, so do it here */
-+ atmel_tdes_finish_req(dd, err);
-+ tasklet_schedule(&dd->queue_task);
-+ }
-+
-+ return ret;
-+}
-+
-+
-+static int atmel_tdes_crypt(struct ablkcipher_request *req, unsigned long mode)
-+{
-+ struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx(
-+ crypto_ablkcipher_reqtfm(req));
-+ struct atmel_tdes_reqctx *rctx = ablkcipher_request_ctx(req);
-+ struct atmel_tdes_dev *dd;
-+
-+ if (mode & TDES_FLAGS_CFB8) {
-+ if (!IS_ALIGNED(req->nbytes, CFB8_BLOCK_SIZE)) {
-+ pr_err("request size is not exact amount of CFB8 blocks\n");
-+ return -EINVAL;
-+ }
-+ } else if (mode & TDES_FLAGS_CFB16) {
-+ if (!IS_ALIGNED(req->nbytes, CFB16_BLOCK_SIZE)) {
-+ pr_err("request size is not exact amount of CFB16 blocks\n");
-+ return -EINVAL;
-+ }
-+ } else if (mode & TDES_FLAGS_CFB32) {
-+ if (!IS_ALIGNED(req->nbytes, CFB32_BLOCK_SIZE)) {
-+ pr_err("request size is not exact amount of CFB32 blocks\n");
-+ return -EINVAL;
-+ }
-+ } else if (!IS_ALIGNED(req->nbytes, DES_BLOCK_SIZE)) {
-+ pr_err("request size is not exact amount of DES blocks\n");
-+ return -EINVAL;
-+ }
-+
-+ dd = atmel_tdes_find_dev(ctx);
-+ if (!dd)
-+ return -ENODEV;
-+
-+ rctx->mode = mode;
-+
-+ return atmel_tdes_handle_queue(dd, req);
-+}
-+
-+static int atmel_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
-+ unsigned int keylen)
-+{
-+ u32 tmp[DES_EXPKEY_WORDS];
-+ int err;
-+ struct crypto_tfm *ctfm = crypto_ablkcipher_tfm(tfm);
-+
-+ struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
-+
-+ if (keylen != DES_KEY_SIZE) {
-+ crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
-+ return -EINVAL;
-+ }
-+
-+ err = des_ekey(tmp, key);
-+ if (err == 0 && (ctfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
-+ ctfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
-+ return -EINVAL;
-+ }
-+
-+ memcpy(ctx->key, key, keylen);
-+ ctx->keylen = keylen;
-+
-+ return 0;
-+}
-+
-+static int atmel_tdes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
-+ unsigned int keylen)
-+{
-+ struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
-+ const char *alg_name;
-+
-+ alg_name = crypto_tfm_alg_name(crypto_ablkcipher_tfm(tfm));
-+
-+ /*
-+ * HW bug in cfb 3-keys mode.
-+ */
-+ if (strstr(alg_name, "cfb") && (keylen != 2*DES_KEY_SIZE)) {
-+ crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
-+ return -EINVAL;
-+ } else if ((keylen != 2*DES_KEY_SIZE) && (keylen != 3*DES_KEY_SIZE)) {
-+ crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
-+ return -EINVAL;
-+ }
-+
-+ memcpy(ctx->key, key, keylen);
-+ ctx->keylen = keylen;
-+
-+ return 0;
-+}
-+
-+static int atmel_tdes_ecb_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT);
-+}
-+
-+static int atmel_tdes_ecb_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_tdes_crypt(req, 0);
-+}
-+
-+static int atmel_tdes_cbc_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CBC);
-+}
-+
-+static int atmel_tdes_cbc_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_tdes_crypt(req, TDES_FLAGS_CBC);
-+}
-+static int atmel_tdes_cfb_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB);
-+}
-+
-+static int atmel_tdes_cfb_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_tdes_crypt(req, TDES_FLAGS_CFB);
-+}
-+
-+static int atmel_tdes_cfb8_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB |
-+ TDES_FLAGS_CFB8);
-+}
-+
-+static int atmel_tdes_cfb8_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_tdes_crypt(req, TDES_FLAGS_CFB | TDES_FLAGS_CFB8);
-+}
-+
-+static int atmel_tdes_cfb16_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB |
-+ TDES_FLAGS_CFB16);
-+}
-+
-+static int atmel_tdes_cfb16_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_tdes_crypt(req, TDES_FLAGS_CFB | TDES_FLAGS_CFB16);
-+}
-+
-+static int atmel_tdes_cfb32_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB |
-+ TDES_FLAGS_CFB32);
-+}
-+
-+static int atmel_tdes_cfb32_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_tdes_crypt(req, TDES_FLAGS_CFB | TDES_FLAGS_CFB32);
-+}
-+
-+static int atmel_tdes_ofb_encrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_OFB);
-+}
-+
-+static int atmel_tdes_ofb_decrypt(struct ablkcipher_request *req)
-+{
-+ return atmel_tdes_crypt(req, TDES_FLAGS_OFB);
-+}
-+
-+static int atmel_tdes_cra_init(struct crypto_tfm *tfm)
-+{
-+ tfm->crt_ablkcipher.reqsize = sizeof(struct atmel_tdes_reqctx);
-+
-+ return 0;
-+}
-+
-+static void atmel_tdes_cra_exit(struct crypto_tfm *tfm)
-+{
-+}
-+
-+static struct crypto_alg tdes_algs[] = {
-+{
-+ .cra_name = "ecb(des)",
-+ .cra_driver_name = "atmel-ecb-des",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = DES_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-+ .cra_alignmask = 0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_tdes_cra_init,
-+ .cra_exit = atmel_tdes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = DES_KEY_SIZE,
-+ .max_keysize = DES_KEY_SIZE,
-+ .setkey = atmel_des_setkey,
-+ .encrypt = atmel_tdes_ecb_encrypt,
-+ .decrypt = atmel_tdes_ecb_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "cbc(des)",
-+ .cra_driver_name = "atmel-cbc-des",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = DES_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-+ .cra_alignmask = 0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_tdes_cra_init,
-+ .cra_exit = atmel_tdes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = DES_KEY_SIZE,
-+ .max_keysize = DES_KEY_SIZE,
-+ .ivsize = DES_BLOCK_SIZE,
-+ .setkey = atmel_des_setkey,
-+ .encrypt = atmel_tdes_cbc_encrypt,
-+ .decrypt = atmel_tdes_cbc_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "cfb(des)",
-+ .cra_driver_name = "atmel-cfb-des",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = DES_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-+ .cra_alignmask = 0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_tdes_cra_init,
-+ .cra_exit = atmel_tdes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = DES_KEY_SIZE,
-+ .max_keysize = DES_KEY_SIZE,
-+ .ivsize = DES_BLOCK_SIZE,
-+ .setkey = atmel_des_setkey,
-+ .encrypt = atmel_tdes_cfb_encrypt,
-+ .decrypt = atmel_tdes_cfb_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "cfb8(des)",
-+ .cra_driver_name = "atmel-cfb8-des",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = CFB8_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-+ .cra_alignmask = 0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_tdes_cra_init,
-+ .cra_exit = atmel_tdes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = DES_KEY_SIZE,
-+ .max_keysize = DES_KEY_SIZE,
-+ .ivsize = DES_BLOCK_SIZE,
-+ .setkey = atmel_des_setkey,
-+ .encrypt = atmel_tdes_cfb8_encrypt,
-+ .decrypt = atmel_tdes_cfb8_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "cfb16(des)",
-+ .cra_driver_name = "atmel-cfb16-des",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = CFB16_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-+ .cra_alignmask = 0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_tdes_cra_init,
-+ .cra_exit = atmel_tdes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = DES_KEY_SIZE,
-+ .max_keysize = DES_KEY_SIZE,
-+ .ivsize = DES_BLOCK_SIZE,
-+ .setkey = atmel_des_setkey,
-+ .encrypt = atmel_tdes_cfb16_encrypt,
-+ .decrypt = atmel_tdes_cfb16_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "cfb32(des)",
-+ .cra_driver_name = "atmel-cfb32-des",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = CFB32_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-+ .cra_alignmask = 0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_tdes_cra_init,
-+ .cra_exit = atmel_tdes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = DES_KEY_SIZE,
-+ .max_keysize = DES_KEY_SIZE,
-+ .ivsize = DES_BLOCK_SIZE,
-+ .setkey = atmel_des_setkey,
-+ .encrypt = atmel_tdes_cfb32_encrypt,
-+ .decrypt = atmel_tdes_cfb32_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "ofb(des)",
-+ .cra_driver_name = "atmel-ofb-des",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = DES_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-+ .cra_alignmask = 0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_tdes_cra_init,
-+ .cra_exit = atmel_tdes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = DES_KEY_SIZE,
-+ .max_keysize = DES_KEY_SIZE,
-+ .ivsize = DES_BLOCK_SIZE,
-+ .setkey = atmel_des_setkey,
-+ .encrypt = atmel_tdes_ofb_encrypt,
-+ .decrypt = atmel_tdes_ofb_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "ecb(des3_ede)",
-+ .cra_driver_name = "atmel-ecb-tdes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = DES_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-+ .cra_alignmask = 0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_tdes_cra_init,
-+ .cra_exit = atmel_tdes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = 2 * DES_KEY_SIZE,
-+ .max_keysize = 3 * DES_KEY_SIZE,
-+ .setkey = atmel_tdes_setkey,
-+ .encrypt = atmel_tdes_ecb_encrypt,
-+ .decrypt = atmel_tdes_ecb_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "cbc(des3_ede)",
-+ .cra_driver_name = "atmel-cbc-tdes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = DES_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-+ .cra_alignmask = 0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_tdes_cra_init,
-+ .cra_exit = atmel_tdes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = 2*DES_KEY_SIZE,
-+ .max_keysize = 3*DES_KEY_SIZE,
-+ .ivsize = DES_BLOCK_SIZE,
-+ .setkey = atmel_tdes_setkey,
-+ .encrypt = atmel_tdes_cbc_encrypt,
-+ .decrypt = atmel_tdes_cbc_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "cfb(des3_ede)",
-+ .cra_driver_name = "atmel-cfb-tdes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = DES_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-+ .cra_alignmask = 0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_tdes_cra_init,
-+ .cra_exit = atmel_tdes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = 2*DES_KEY_SIZE,
-+ .max_keysize = 2*DES_KEY_SIZE,
-+ .ivsize = DES_BLOCK_SIZE,
-+ .setkey = atmel_tdes_setkey,
-+ .encrypt = atmel_tdes_cfb_encrypt,
-+ .decrypt = atmel_tdes_cfb_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "cfb8(des3_ede)",
-+ .cra_driver_name = "atmel-cfb8-tdes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = CFB8_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-+ .cra_alignmask = 0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_tdes_cra_init,
-+ .cra_exit = atmel_tdes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = 2*DES_KEY_SIZE,
-+ .max_keysize = 2*DES_KEY_SIZE,
-+ .ivsize = DES_BLOCK_SIZE,
-+ .setkey = atmel_tdes_setkey,
-+ .encrypt = atmel_tdes_cfb8_encrypt,
-+ .decrypt = atmel_tdes_cfb8_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "cfb16(des3_ede)",
-+ .cra_driver_name = "atmel-cfb16-tdes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = CFB16_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-+ .cra_alignmask = 0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_tdes_cra_init,
-+ .cra_exit = atmel_tdes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = 2*DES_KEY_SIZE,
-+ .max_keysize = 2*DES_KEY_SIZE,
-+ .ivsize = DES_BLOCK_SIZE,
-+ .setkey = atmel_tdes_setkey,
-+ .encrypt = atmel_tdes_cfb16_encrypt,
-+ .decrypt = atmel_tdes_cfb16_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "cfb32(des3_ede)",
-+ .cra_driver_name = "atmel-cfb32-tdes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = CFB32_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-+ .cra_alignmask = 0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_tdes_cra_init,
-+ .cra_exit = atmel_tdes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = 2*DES_KEY_SIZE,
-+ .max_keysize = 2*DES_KEY_SIZE,
-+ .ivsize = DES_BLOCK_SIZE,
-+ .setkey = atmel_tdes_setkey,
-+ .encrypt = atmel_tdes_cfb32_encrypt,
-+ .decrypt = atmel_tdes_cfb32_decrypt,
-+ }
-+},
-+{
-+ .cra_name = "ofb(des3_ede)",
-+ .cra_driver_name = "atmel-ofb-tdes",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-+ .cra_blocksize = DES_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-+ .cra_alignmask = 0,
-+ .cra_type = &crypto_ablkcipher_type,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_tdes_cra_init,
-+ .cra_exit = atmel_tdes_cra_exit,
-+ .cra_u.ablkcipher = {
-+ .min_keysize = 2*DES_KEY_SIZE,
-+ .max_keysize = 3*DES_KEY_SIZE,
-+ .ivsize = DES_BLOCK_SIZE,
-+ .setkey = atmel_tdes_setkey,
-+ .encrypt = atmel_tdes_ofb_encrypt,
-+ .decrypt = atmel_tdes_ofb_decrypt,
-+ }
-+},
-+};
-+
-+static void atmel_tdes_queue_task(unsigned long data)
-+{
-+ struct atmel_tdes_dev *dd = (struct atmel_tdes_dev *)data;
-+
-+ atmel_tdes_handle_queue(dd, NULL);
-+}
-+
-+static void atmel_tdes_done_task(unsigned long data)
-+{
-+ struct atmel_tdes_dev *dd = (struct atmel_tdes_dev *) data;
-+ int err;
-+
-+ err = atmel_tdes_crypt_dma_stop(dd);
-+
-+ err = dd->err ? : err;
-+
-+ if (dd->total && !err) {
-+ err = atmel_tdes_crypt_dma_start(dd);
-+ if (!err)
-+ return;
-+ }
-+
-+ atmel_tdes_finish_req(dd, err);
-+ atmel_tdes_handle_queue(dd, NULL);
-+}
-+
-+static irqreturn_t atmel_tdes_irq(int irq, void *dev_id)
-+{
-+ struct atmel_tdes_dev *tdes_dd = dev_id;
-+ u32 reg;
-+
-+ reg = atmel_tdes_read(tdes_dd, TDES_ISR);
-+ if (reg & atmel_tdes_read(tdes_dd, TDES_IMR)) {
-+ atmel_tdes_write(tdes_dd, TDES_IDR, reg);
-+ if (TDES_FLAGS_BUSY & tdes_dd->flags)
-+ tasklet_schedule(&tdes_dd->done_task);
-+ else
-+ dev_warn(tdes_dd->dev, "TDES interrupt when no active requests.\n");
-+ return IRQ_HANDLED;
-+ }
-+
-+ return IRQ_NONE;
-+}
-+
-+static void atmel_tdes_unregister_algs(struct atmel_tdes_dev *dd)
-+{
-+ int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(tdes_algs); i++)
-+ crypto_unregister_alg(&tdes_algs[i]);
-+}
-+
-+static int atmel_tdes_register_algs(struct atmel_tdes_dev *dd)
-+{
-+ int err, i, j;
-+
-+ for (i = 0; i < ARRAY_SIZE(tdes_algs); i++) {
-+ INIT_LIST_HEAD(&tdes_algs[i].cra_list);
-+ err = crypto_register_alg(&tdes_algs[i]);
-+ if (err)
-+ goto err_tdes_algs;
-+ }
-+
-+ return 0;
-+
-+err_tdes_algs:
-+ for (j = 0; j < i; j++)
-+ crypto_unregister_alg(&tdes_algs[j]);
-+
-+ return err;
-+}
-+
-+static int __devinit atmel_tdes_probe(struct platform_device *pdev)
-+{
-+ struct atmel_tdes_dev *tdes_dd;
-+ struct device *dev = &pdev->dev;
-+ struct resource *tdes_res;
-+ unsigned long tdes_phys_size;
-+ int err;
-+
-+ tdes_dd = kzalloc(sizeof(struct atmel_tdes_dev), GFP_KERNEL);
-+ if (tdes_dd == NULL) {
-+ dev_err(dev, "unable to alloc data struct.\n");
-+ err = -ENOMEM;
-+ goto tdes_dd_err;
-+ }
-+
-+ tdes_dd->dev = dev;
-+
-+ platform_set_drvdata(pdev, tdes_dd);
-+
-+ INIT_LIST_HEAD(&tdes_dd->list);
-+
-+ tasklet_init(&tdes_dd->done_task, atmel_tdes_done_task,
-+ (unsigned long)tdes_dd);
-+ tasklet_init(&tdes_dd->queue_task, atmel_tdes_queue_task,
-+ (unsigned long)tdes_dd);
-+
-+ crypto_init_queue(&tdes_dd->queue, ATMEL_TDES_QUEUE_LENGTH);
-+
-+ tdes_dd->irq = -1;
-+
-+ /* Get the base address */
-+ tdes_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!tdes_res) {
-+ dev_err(dev, "no MEM resource info\n");
-+ err = -ENODEV;
-+ goto res_err;
-+ }
-+ tdes_dd->phys_base = tdes_res->start;
-+ tdes_phys_size = resource_size(tdes_res);
-+
-+ /* Get the IRQ */
-+ tdes_dd->irq = platform_get_irq(pdev, 0);
-+ if (tdes_dd->irq < 0) {
-+ dev_err(dev, "no IRQ resource info\n");
-+ err = tdes_dd->irq;
-+ goto res_err;
-+ }
-+
-+ err = request_irq(tdes_dd->irq, atmel_tdes_irq, IRQF_SHARED,
-+ "atmel-tdes", tdes_dd);
-+ if (err) {
-+ dev_err(dev, "unable to request tdes irq.\n");
-+ goto tdes_irq_err;
-+ }
-+
-+ /* Initializing the clock */
-+ tdes_dd->iclk = clk_get(&pdev->dev, NULL);
-+ if (IS_ERR(tdes_dd->iclk)) {
-+ dev_err(dev, "clock intialization failed.\n");
-+ err = PTR_ERR(tdes_dd->iclk);
-+ goto clk_err;
-+ }
-+
-+ tdes_dd->io_base = ioremap(tdes_dd->phys_base, tdes_phys_size);
-+ if (!tdes_dd->io_base) {
-+ dev_err(dev, "can't ioremap\n");
-+ err = -ENOMEM;
-+ goto tdes_io_err;
-+ }
-+
-+ err = atmel_tdes_dma_init(tdes_dd);
-+ if (err)
-+ goto err_tdes_dma;
-+
-+ spin_lock(&atmel_tdes.lock);
-+ list_add_tail(&tdes_dd->list, &atmel_tdes.dev_list);
-+ spin_unlock(&atmel_tdes.lock);
-+
-+ err = atmel_tdes_register_algs(tdes_dd);
-+ if (err)
-+ goto err_algs;
-+
-+ dev_info(dev, "Atmel DES/TDES\n");
-+
-+ return 0;
-+
-+err_algs:
-+ spin_lock(&atmel_tdes.lock);
-+ list_del(&tdes_dd->list);
-+ spin_unlock(&atmel_tdes.lock);
-+ atmel_tdes_dma_cleanup(tdes_dd);
-+err_tdes_dma:
-+ iounmap(tdes_dd->io_base);
-+tdes_io_err:
-+ clk_put(tdes_dd->iclk);
-+clk_err:
-+ free_irq(tdes_dd->irq, tdes_dd);
-+tdes_irq_err:
-+res_err:
-+ tasklet_kill(&tdes_dd->done_task);
-+ tasklet_kill(&tdes_dd->queue_task);
-+ kfree(tdes_dd);
-+ tdes_dd = NULL;
-+tdes_dd_err:
-+ dev_err(dev, "initialization failed.\n");
-+
-+ return err;
-+}
-+
-+static int __devexit atmel_tdes_remove(struct platform_device *pdev)
-+{
-+ static struct atmel_tdes_dev *tdes_dd;
-+
-+ tdes_dd = platform_get_drvdata(pdev);
-+ if (!tdes_dd)
-+ return -ENODEV;
-+ spin_lock(&atmel_tdes.lock);
-+ list_del(&tdes_dd->list);
-+ spin_unlock(&atmel_tdes.lock);
-+
-+ atmel_tdes_unregister_algs(tdes_dd);
-+
-+ tasklet_kill(&tdes_dd->done_task);
-+ tasklet_kill(&tdes_dd->queue_task);
-+
-+ atmel_tdes_dma_cleanup(tdes_dd);
-+
-+ iounmap(tdes_dd->io_base);
-+
-+ clk_put(tdes_dd->iclk);
-+
-+ if (tdes_dd->irq >= 0)
-+ free_irq(tdes_dd->irq, tdes_dd);
-+
-+ kfree(tdes_dd);
-+ tdes_dd = NULL;
-+
-+ return 0;
-+}
-+
-+static struct platform_driver atmel_tdes_driver = {
-+ .probe = atmel_tdes_probe,
-+ .remove = __devexit_p(atmel_tdes_remove),
-+ .driver = {
-+ .name = "atmel_tdes",
-+ .owner = THIS_MODULE,
-+ },
-+};
-+
-+module_platform_driver(atmel_tdes_driver);
-+
-+MODULE_DESCRIPTION("Atmel DES/TDES hw acceleration support.");
-+MODULE_LICENSE("GPL v2");
-+MODULE_AUTHOR("Nicolas Royer - Eukréa Electromatique");
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 08f29ab9122d183ff7b1d1057cd9f172748a6026 Mon Sep 17 00:00:00 2001
-From: Nicolas Royer <nicolas@eukrea.com>
-Date: Mon, 17 Sep 2012 18:26:06 +0200
-Subject: crypto: add Atmel SHA1/SHA256 driver
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-commit ebc82efa1cd64efba0f41455460411b852b5b89c upstream.
-
-Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Eric Bénard <eric@eukrea.com>
-Tested-by: Eric Bénard <eric@eukrea.com>
----
- drivers/crypto/Kconfig | 14 +
- drivers/crypto/Makefile | 1 +
- drivers/crypto/atmel-sha-regs.h | 46 ++
- drivers/crypto/atmel-sha.c | 1112 +++++++++++++++++++++++++++++++++++++++
- 4 files changed, 1173 insertions(+)
- create mode 100644 drivers/crypto/atmel-sha-regs.h
- create mode 100644 drivers/crypto/atmel-sha.c
-
-diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
-index 2124898..2339add 100644
---- a/drivers/crypto/Kconfig
-+++ b/drivers/crypto/Kconfig
-@@ -329,4 +329,18 @@ config CRYPTO_DEV_ATMEL_TDES
- To compile this driver as a module, choose M here: the module
- will be called atmel-tdes.
-
-+config CRYPTO_DEV_ATMEL_SHA
-+ tristate "Support for Atmel SHA1/SHA256 hw accelerator"
-+ depends on ARCH_AT91
-+ select CRYPTO_SHA1
-+ select CRYPTO_SHA256
-+ select CRYPTO_ALGAPI
-+ help
-+ Some Atmel processors have SHA1/SHA256 hw accelerator.
-+ Select this if you want to use the Atmel module for
-+ SHA1/SHA256 algorithms.
-+
-+ To compile this driver as a module, choose M here: the module
-+ will be called atmel-sha.
-+
- endif # CRYPTO_HW
-diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
-index 443bf4d..d355c25 100644
---- a/drivers/crypto/Makefile
-+++ b/drivers/crypto/Makefile
-@@ -16,3 +16,4 @@ obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o
- obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o
- obj-$(CONFIG_CRYPTO_DEV_ATMEL_AES) += atmel-aes.o
- obj-$(CONFIG_CRYPTO_DEV_ATMEL_TDES) += atmel-tdes.o
-+obj-$(CONFIG_CRYPTO_DEV_ATMEL_SHA) += atmel-sha.o
-diff --git a/drivers/crypto/atmel-sha-regs.h b/drivers/crypto/atmel-sha-regs.h
-new file mode 100644
-index 0000000..dc53a20
---- /dev/null
-+++ b/drivers/crypto/atmel-sha-regs.h
-@@ -0,0 +1,46 @@
-+#ifndef __ATMEL_SHA_REGS_H__
-+#define __ATMEL_SHA_REGS_H__
-+
-+#define SHA_REG_DIGEST(x) (0x80 + ((x) * 0x04))
-+#define SHA_REG_DIN(x) (0x40 + ((x) * 0x04))
-+
-+#define SHA_CR 0x00
-+#define SHA_CR_START (1 << 0)
-+#define SHA_CR_FIRST (1 << 4)
-+#define SHA_CR_SWRST (1 << 8)
-+
-+#define SHA_MR 0x04
-+#define SHA_MR_MODE_MASK (0x3 << 0)
-+#define SHA_MR_MODE_MANUAL 0x0
-+#define SHA_MR_MODE_AUTO 0x1
-+#define SHA_MR_MODE_PDC 0x2
-+#define SHA_MR_DUALBUFF (1 << 3)
-+#define SHA_MR_PROCDLY (1 << 4)
-+#define SHA_MR_ALGO_SHA1 (0 << 8)
-+#define SHA_MR_ALGO_SHA256 (1 << 8)
-+
-+#define SHA_IER 0x10
-+#define SHA_IDR 0x14
-+#define SHA_IMR 0x18
-+#define SHA_ISR 0x1C
-+#define SHA_INT_DATARDY (1 << 0)
-+#define SHA_INT_ENDTX (1 << 1)
-+#define SHA_INT_TXBUFE (1 << 2)
-+#define SHA_INT_URAD (1 << 8)
-+#define SHA_ISR_URAT_MASK (0x7 << 12)
-+#define SHA_ISR_URAT_IDR (0x0 << 12)
-+#define SHA_ISR_URAT_ODR (0x1 << 12)
-+#define SHA_ISR_URAT_MR (0x2 << 12)
-+#define SHA_ISR_URAT_WO (0x5 << 12)
-+
-+#define SHA_TPR 0x108
-+#define SHA_TCR 0x10C
-+#define SHA_TNPR 0x118
-+#define SHA_TNCR 0x11C
-+#define SHA_PTCR 0x120
-+#define SHA_PTCR_TXTEN (1 << 8)
-+#define SHA_PTCR_TXTDIS (1 << 9)
-+#define SHA_PTSR 0x124
-+#define SHA_PTSR_TXTEN (1 << 8)
-+
-+#endif /* __ATMEL_SHA_REGS_H__ */
-diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
-new file mode 100644
-index 0000000..f938b9d
---- /dev/null
-+++ b/drivers/crypto/atmel-sha.c
-@@ -0,0 +1,1112 @@
-+/*
-+ * Cryptographic API.
-+ *
-+ * Support for ATMEL SHA1/SHA256 HW acceleration.
-+ *
-+ * Copyright (c) 2012 Eukréa Electromatique - ATMEL
-+ * Author: Nicolas Royer <nicolas@eukrea.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 published
-+ * by the Free Software Foundation.
-+ *
-+ * Some ideas are from omap-sham.c drivers.
-+ */
-+
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/err.h>
-+#include <linux/clk.h>
-+#include <linux/io.h>
-+#include <linux/hw_random.h>
-+#include <linux/platform_device.h>
-+
-+#include <linux/device.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/interrupt.h>
-+#include <linux/kernel.h>
-+#include <linux/clk.h>
-+#include <linux/irq.h>
-+#include <linux/io.h>
-+#include <linux/platform_device.h>
-+#include <linux/scatterlist.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/delay.h>
-+#include <linux/crypto.h>
-+#include <linux/cryptohash.h>
-+#include <crypto/scatterwalk.h>
-+#include <crypto/algapi.h>
-+#include <crypto/sha.h>
-+#include <crypto/hash.h>
-+#include <crypto/internal/hash.h>
-+#include "atmel-sha-regs.h"
-+
-+/* SHA flags */
-+#define SHA_FLAGS_BUSY BIT(0)
-+#define SHA_FLAGS_FINAL BIT(1)
-+#define SHA_FLAGS_DMA_ACTIVE BIT(2)
-+#define SHA_FLAGS_OUTPUT_READY BIT(3)
-+#define SHA_FLAGS_INIT BIT(4)
-+#define SHA_FLAGS_CPU BIT(5)
-+#define SHA_FLAGS_DMA_READY BIT(6)
-+
-+#define SHA_FLAGS_FINUP BIT(16)
-+#define SHA_FLAGS_SG BIT(17)
-+#define SHA_FLAGS_SHA1 BIT(18)
-+#define SHA_FLAGS_SHA256 BIT(19)
-+#define SHA_FLAGS_ERROR BIT(20)
-+#define SHA_FLAGS_PAD BIT(21)
-+
-+#define SHA_FLAGS_DUALBUFF BIT(24)
-+
-+#define SHA_OP_UPDATE 1
-+#define SHA_OP_FINAL 2
-+
-+#define SHA_BUFFER_LEN PAGE_SIZE
-+
-+#define ATMEL_SHA_DMA_THRESHOLD 56
-+
-+
-+struct atmel_sha_dev;
-+
-+struct atmel_sha_reqctx {
-+ struct atmel_sha_dev *dd;
-+ unsigned long flags;
-+ unsigned long op;
-+
-+ u8 digest[SHA256_DIGEST_SIZE] __aligned(sizeof(u32));
-+ size_t digcnt;
-+ size_t bufcnt;
-+ size_t buflen;
-+ dma_addr_t dma_addr;
-+
-+ /* walk state */
-+ struct scatterlist *sg;
-+ unsigned int offset; /* offset in current sg */
-+ unsigned int total; /* total request */
-+
-+ u8 buffer[0] __aligned(sizeof(u32));
-+};
-+
-+struct atmel_sha_ctx {
-+ struct atmel_sha_dev *dd;
-+
-+ unsigned long flags;
-+
-+ /* fallback stuff */
-+ struct crypto_shash *fallback;
-+
-+};
-+
-+#define ATMEL_SHA_QUEUE_LENGTH 1
-+
-+struct atmel_sha_dev {
-+ struct list_head list;
-+ unsigned long phys_base;
-+ struct device *dev;
-+ struct clk *iclk;
-+ int irq;
-+ void __iomem *io_base;
-+
-+ spinlock_t lock;
-+ int err;
-+ struct tasklet_struct done_task;
-+
-+ unsigned long flags;
-+ struct crypto_queue queue;
-+ struct ahash_request *req;
-+};
-+
-+struct atmel_sha_drv {
-+ struct list_head dev_list;
-+ spinlock_t lock;
-+};
-+
-+static struct atmel_sha_drv atmel_sha = {
-+ .dev_list = LIST_HEAD_INIT(atmel_sha.dev_list),
-+ .lock = __SPIN_LOCK_UNLOCKED(atmel_sha.lock),
-+};
-+
-+static inline u32 atmel_sha_read(struct atmel_sha_dev *dd, u32 offset)
-+{
-+ return readl_relaxed(dd->io_base + offset);
-+}
-+
-+static inline void atmel_sha_write(struct atmel_sha_dev *dd,
-+ u32 offset, u32 value)
-+{
-+ writel_relaxed(value, dd->io_base + offset);
-+}
-+
-+static void atmel_sha_dualbuff_test(struct atmel_sha_dev *dd)
-+{
-+ atmel_sha_write(dd, SHA_MR, SHA_MR_DUALBUFF);
-+
-+ if (atmel_sha_read(dd, SHA_MR) & SHA_MR_DUALBUFF)
-+ dd->flags |= SHA_FLAGS_DUALBUFF;
-+}
-+
-+static size_t atmel_sha_append_sg(struct atmel_sha_reqctx *ctx)
-+{
-+ size_t count;
-+
-+ while ((ctx->bufcnt < ctx->buflen) && ctx->total) {
-+ count = min(ctx->sg->length - ctx->offset, ctx->total);
-+ count = min(count, ctx->buflen - ctx->bufcnt);
-+
-+ if (count <= 0)
-+ break;
-+
-+ scatterwalk_map_and_copy(ctx->buffer + ctx->bufcnt, ctx->sg,
-+ ctx->offset, count, 0);
-+
-+ ctx->bufcnt += count;
-+ ctx->offset += count;
-+ ctx->total -= count;
-+
-+ if (ctx->offset == ctx->sg->length) {
-+ ctx->sg = sg_next(ctx->sg);
-+ if (ctx->sg)
-+ ctx->offset = 0;
-+ else
-+ ctx->total = 0;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * The purpose of this padding is to ensure that the padded message
-+ * is a multiple of 512 bits. The bit "1" is appended at the end of
-+ * the message followed by "padlen-1" zero bits. Then a 64 bits block
-+ * equals to the message length in bits is appended.
-+ *
-+ * padlen is calculated as followed:
-+ * - if message length < 56 bytes then padlen = 56 - message length
-+ * - else padlen = 64 + 56 - message length
-+ */
-+static void atmel_sha_fill_padding(struct atmel_sha_reqctx *ctx, int length)
-+{
-+ unsigned int index, padlen;
-+ u64 bits;
-+ u64 size;
-+
-+ bits = (ctx->bufcnt + ctx->digcnt + length) << 3;
-+ size = cpu_to_be64(bits);
-+
-+ index = ctx->bufcnt & 0x3f;
-+ padlen = (index < 56) ? (56 - index) : ((64+56) - index);
-+ *(ctx->buffer + ctx->bufcnt) = 0x80;
-+ memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen-1);
-+ memcpy(ctx->buffer + ctx->bufcnt + padlen, &size, 8);
-+ ctx->bufcnt += padlen + 8;
-+ ctx->flags |= SHA_FLAGS_PAD;
-+}
-+
-+static int atmel_sha_init(struct ahash_request *req)
-+{
-+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-+ struct atmel_sha_ctx *tctx = crypto_ahash_ctx(tfm);
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
-+ struct atmel_sha_dev *dd = NULL;
-+ struct atmel_sha_dev *tmp;
-+
-+ spin_lock_bh(&atmel_sha.lock);
-+ if (!tctx->dd) {
-+ list_for_each_entry(tmp, &atmel_sha.dev_list, list) {
-+ dd = tmp;
-+ break;
-+ }
-+ tctx->dd = dd;
-+ } else {
-+ dd = tctx->dd;
-+ }
-+
-+ spin_unlock_bh(&atmel_sha.lock);
-+
-+ ctx->dd = dd;
-+
-+ ctx->flags = 0;
-+
-+ dev_dbg(dd->dev, "init: digest size: %d\n",
-+ crypto_ahash_digestsize(tfm));
-+
-+ if (crypto_ahash_digestsize(tfm) == SHA1_DIGEST_SIZE)
-+ ctx->flags |= SHA_FLAGS_SHA1;
-+ else if (crypto_ahash_digestsize(tfm) == SHA256_DIGEST_SIZE)
-+ ctx->flags |= SHA_FLAGS_SHA256;
-+
-+ ctx->bufcnt = 0;
-+ ctx->digcnt = 0;
-+ ctx->buflen = SHA_BUFFER_LEN;
-+
-+ return 0;
-+}
-+
-+static void atmel_sha_write_ctrl(struct atmel_sha_dev *dd, int dma)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req);
-+ u32 valcr = 0, valmr = SHA_MR_MODE_AUTO;
-+
-+ if (likely(dma)) {
-+ atmel_sha_write(dd, SHA_IER, SHA_INT_TXBUFE);
-+ valmr = SHA_MR_MODE_PDC;
-+ if (dd->flags & SHA_FLAGS_DUALBUFF)
-+ valmr = SHA_MR_DUALBUFF;
-+ } else {
-+ atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY);
-+ }
-+
-+ if (ctx->flags & SHA_FLAGS_SHA256)
-+ valmr |= SHA_MR_ALGO_SHA256;
-+
-+ /* Setting CR_FIRST only for the first iteration */
-+ if (!ctx->digcnt)
-+ valcr = SHA_CR_FIRST;
-+
-+ atmel_sha_write(dd, SHA_CR, valcr);
-+ atmel_sha_write(dd, SHA_MR, valmr);
-+}
-+
-+static int atmel_sha_xmit_cpu(struct atmel_sha_dev *dd, const u8 *buf,
-+ size_t length, int final)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req);
-+ int count, len32;
-+ const u32 *buffer = (const u32 *)buf;
-+
-+ dev_dbg(dd->dev, "xmit_cpu: digcnt: %d, length: %d, final: %d\n",
-+ ctx->digcnt, length, final);
-+
-+ atmel_sha_write_ctrl(dd, 0);
-+
-+ /* should be non-zero before next lines to disable clocks later */
-+ ctx->digcnt += length;
-+
-+ if (final)
-+ dd->flags |= SHA_FLAGS_FINAL; /* catch last interrupt */
-+
-+ len32 = DIV_ROUND_UP(length, sizeof(u32));
-+
-+ dd->flags |= SHA_FLAGS_CPU;
-+
-+ for (count = 0; count < len32; count++)
-+ atmel_sha_write(dd, SHA_REG_DIN(count), buffer[count]);
-+
-+ return -EINPROGRESS;
-+}
-+
-+static int atmel_sha_xmit_pdc(struct atmel_sha_dev *dd, dma_addr_t dma_addr1,
-+ size_t length1, dma_addr_t dma_addr2, size_t length2, int final)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req);
-+ int len32;
-+
-+ dev_dbg(dd->dev, "xmit_pdc: digcnt: %d, length: %d, final: %d\n",
-+ ctx->digcnt, length1, final);
-+
-+ len32 = DIV_ROUND_UP(length1, sizeof(u32));
-+ atmel_sha_write(dd, SHA_PTCR, SHA_PTCR_TXTDIS);
-+ atmel_sha_write(dd, SHA_TPR, dma_addr1);
-+ atmel_sha_write(dd, SHA_TCR, len32);
-+
-+ len32 = DIV_ROUND_UP(length2, sizeof(u32));
-+ atmel_sha_write(dd, SHA_TNPR, dma_addr2);
-+ atmel_sha_write(dd, SHA_TNCR, len32);
-+
-+ atmel_sha_write_ctrl(dd, 1);
-+
-+ /* should be non-zero before next lines to disable clocks later */
-+ ctx->digcnt += length1;
-+
-+ if (final)
-+ dd->flags |= SHA_FLAGS_FINAL; /* catch last interrupt */
-+
-+ dd->flags |= SHA_FLAGS_DMA_ACTIVE;
-+
-+ /* Start DMA transfer */
-+ atmel_sha_write(dd, SHA_PTCR, SHA_PTCR_TXTEN);
-+
-+ return -EINPROGRESS;
-+}
-+
-+static int atmel_sha_update_cpu(struct atmel_sha_dev *dd)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req);
-+ int bufcnt;
-+
-+ atmel_sha_append_sg(ctx);
-+ atmel_sha_fill_padding(ctx, 0);
-+
-+ bufcnt = ctx->bufcnt;
-+ ctx->bufcnt = 0;
-+
-+ return atmel_sha_xmit_cpu(dd, ctx->buffer, bufcnt, 1);
-+}
-+
-+static int atmel_sha_xmit_dma_map(struct atmel_sha_dev *dd,
-+ struct atmel_sha_reqctx *ctx,
-+ size_t length, int final)
-+{
-+ ctx->dma_addr = dma_map_single(dd->dev, ctx->buffer,
-+ ctx->buflen + SHA1_BLOCK_SIZE, DMA_TO_DEVICE);
-+ if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
-+ dev_err(dd->dev, "dma %u bytes error\n", ctx->buflen +
-+ SHA1_BLOCK_SIZE);
-+ return -EINVAL;
-+ }
-+
-+ ctx->flags &= ~SHA_FLAGS_SG;
-+
-+ /* next call does not fail... so no unmap in the case of error */
-+ return atmel_sha_xmit_pdc(dd, ctx->dma_addr, length, 0, 0, final);
-+}
-+
-+static int atmel_sha_update_dma_slow(struct atmel_sha_dev *dd)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req);
-+ unsigned int final;
-+ size_t count;
-+
-+ atmel_sha_append_sg(ctx);
-+
-+ final = (ctx->flags & SHA_FLAGS_FINUP) && !ctx->total;
-+
-+ dev_dbg(dd->dev, "slow: bufcnt: %u, digcnt: %d, final: %d\n",
-+ ctx->bufcnt, ctx->digcnt, final);
-+
-+ if (final)
-+ atmel_sha_fill_padding(ctx, 0);
-+
-+ if (final || (ctx->bufcnt == ctx->buflen && ctx->total)) {
-+ count = ctx->bufcnt;
-+ ctx->bufcnt = 0;
-+ return atmel_sha_xmit_dma_map(dd, ctx, count, final);
-+ }
-+
-+ return 0;
-+}
-+
-+static int atmel_sha_update_dma_start(struct atmel_sha_dev *dd)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req);
-+ unsigned int length, final, tail;
-+ struct scatterlist *sg;
-+ unsigned int count;
-+
-+ if (!ctx->total)
-+ return 0;
-+
-+ if (ctx->bufcnt || ctx->offset)
-+ return atmel_sha_update_dma_slow(dd);
-+
-+ dev_dbg(dd->dev, "fast: digcnt: %d, bufcnt: %u, total: %u\n",
-+ ctx->digcnt, ctx->bufcnt, ctx->total);
-+
-+ sg = ctx->sg;
-+
-+ if (!IS_ALIGNED(sg->offset, sizeof(u32)))
-+ return atmel_sha_update_dma_slow(dd);
-+
-+ if (!sg_is_last(sg) && !IS_ALIGNED(sg->length, SHA1_BLOCK_SIZE))
-+ /* size is not SHA1_BLOCK_SIZE aligned */
-+ return atmel_sha_update_dma_slow(dd);
-+
-+ length = min(ctx->total, sg->length);
-+
-+ if (sg_is_last(sg)) {
-+ if (!(ctx->flags & SHA_FLAGS_FINUP)) {
-+ /* not last sg must be SHA1_BLOCK_SIZE aligned */
-+ tail = length & (SHA1_BLOCK_SIZE - 1);
-+ length -= tail;
-+ if (length == 0) {
-+ /* offset where to start slow */
-+ ctx->offset = length;
-+ return atmel_sha_update_dma_slow(dd);
-+ }
-+ }
-+ }
-+
-+ ctx->total -= length;
-+ ctx->offset = length; /* offset where to start slow */
-+
-+ final = (ctx->flags & SHA_FLAGS_FINUP) && !ctx->total;
-+
-+ /* Add padding */
-+ if (final) {
-+ tail = length & (SHA1_BLOCK_SIZE - 1);
-+ length -= tail;
-+ ctx->total += tail;
-+ ctx->offset = length; /* offset where to start slow */
-+
-+ sg = ctx->sg;
-+ atmel_sha_append_sg(ctx);
-+
-+ atmel_sha_fill_padding(ctx, length);
-+
-+ ctx->dma_addr = dma_map_single(dd->dev, ctx->buffer,
-+ ctx->buflen + SHA1_BLOCK_SIZE, DMA_TO_DEVICE);
-+ if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
-+ dev_err(dd->dev, "dma %u bytes error\n",
-+ ctx->buflen + SHA1_BLOCK_SIZE);
-+ return -EINVAL;
-+ }
-+
-+ if (length == 0) {
-+ ctx->flags &= ~SHA_FLAGS_SG;
-+ count = ctx->bufcnt;
-+ ctx->bufcnt = 0;
-+ return atmel_sha_xmit_pdc(dd, ctx->dma_addr, count, 0,
-+ 0, final);
-+ } else {
-+ ctx->sg = sg;
-+ if (!dma_map_sg(dd->dev, ctx->sg, 1,
-+ DMA_TO_DEVICE)) {
-+ dev_err(dd->dev, "dma_map_sg error\n");
-+ return -EINVAL;
-+ }
-+
-+ ctx->flags |= SHA_FLAGS_SG;
-+
-+ count = ctx->bufcnt;
-+ ctx->bufcnt = 0;
-+ return atmel_sha_xmit_pdc(dd, sg_dma_address(ctx->sg),
-+ length, ctx->dma_addr, count, final);
-+ }
-+ }
-+
-+ if (!dma_map_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE)) {
-+ dev_err(dd->dev, "dma_map_sg error\n");
-+ return -EINVAL;
-+ }
-+
-+ ctx->flags |= SHA_FLAGS_SG;
-+
-+ /* next call does not fail... so no unmap in the case of error */
-+ return atmel_sha_xmit_pdc(dd, sg_dma_address(ctx->sg), length, 0,
-+ 0, final);
-+}
-+
-+static int atmel_sha_update_dma_stop(struct atmel_sha_dev *dd)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req);
-+
-+ if (ctx->flags & SHA_FLAGS_SG) {
-+ dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE);
-+ if (ctx->sg->length == ctx->offset) {
-+ ctx->sg = sg_next(ctx->sg);
-+ if (ctx->sg)
-+ ctx->offset = 0;
-+ }
-+ if (ctx->flags & SHA_FLAGS_PAD)
-+ dma_unmap_single(dd->dev, ctx->dma_addr,
-+ ctx->buflen + SHA1_BLOCK_SIZE, DMA_TO_DEVICE);
-+ } else {
-+ dma_unmap_single(dd->dev, ctx->dma_addr, ctx->buflen +
-+ SHA1_BLOCK_SIZE, DMA_TO_DEVICE);
-+ }
-+
-+ return 0;
-+}
-+
-+static int atmel_sha_update_req(struct atmel_sha_dev *dd)
-+{
-+ struct ahash_request *req = dd->req;
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
-+ int err;
-+
-+ dev_dbg(dd->dev, "update_req: total: %u, digcnt: %d, finup: %d\n",
-+ ctx->total, ctx->digcnt, (ctx->flags & SHA_FLAGS_FINUP) != 0);
-+
-+ if (ctx->flags & SHA_FLAGS_CPU)
-+ err = atmel_sha_update_cpu(dd);
-+ else
-+ err = atmel_sha_update_dma_start(dd);
-+
-+ /* wait for dma completion before can take more data */
-+ dev_dbg(dd->dev, "update: err: %d, digcnt: %d\n",
-+ err, ctx->digcnt);
-+
-+ return err;
-+}
-+
-+static int atmel_sha_final_req(struct atmel_sha_dev *dd)
-+{
-+ struct ahash_request *req = dd->req;
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
-+ int err = 0;
-+ int count;
-+
-+ if (ctx->bufcnt >= ATMEL_SHA_DMA_THRESHOLD) {
-+ atmel_sha_fill_padding(ctx, 0);
-+ count = ctx->bufcnt;
-+ ctx->bufcnt = 0;
-+ err = atmel_sha_xmit_dma_map(dd, ctx, count, 1);
-+ }
-+ /* faster to handle last block with cpu */
-+ else {
-+ atmel_sha_fill_padding(ctx, 0);
-+ count = ctx->bufcnt;
-+ ctx->bufcnt = 0;
-+ err = atmel_sha_xmit_cpu(dd, ctx->buffer, count, 1);
-+ }
-+
-+ dev_dbg(dd->dev, "final_req: err: %d\n", err);
-+
-+ return err;
-+}
-+
-+static void atmel_sha_copy_hash(struct ahash_request *req)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
-+ u32 *hash = (u32 *)ctx->digest;
-+ int i;
-+
-+ if (likely(ctx->flags & SHA_FLAGS_SHA1))
-+ for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++)
-+ hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i));
-+ else
-+ for (i = 0; i < SHA256_DIGEST_SIZE / sizeof(u32); i++)
-+ hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i));
-+}
-+
-+static void atmel_sha_copy_ready_hash(struct ahash_request *req)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
-+
-+ if (!req->result)
-+ return;
-+
-+ if (likely(ctx->flags & SHA_FLAGS_SHA1))
-+ memcpy(req->result, ctx->digest, SHA1_DIGEST_SIZE);
-+ else
-+ memcpy(req->result, ctx->digest, SHA256_DIGEST_SIZE);
-+}
-+
-+static int atmel_sha_finish(struct ahash_request *req)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
-+ struct atmel_sha_dev *dd = ctx->dd;
-+ int err = 0;
-+
-+ if (ctx->digcnt)
-+ atmel_sha_copy_ready_hash(req);
-+
-+ dev_dbg(dd->dev, "digcnt: %d, bufcnt: %d\n", ctx->digcnt,
-+ ctx->bufcnt);
-+
-+ return err;
-+}
-+
-+static void atmel_sha_finish_req(struct ahash_request *req, int err)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
-+ struct atmel_sha_dev *dd = ctx->dd;
-+
-+ if (!err) {
-+ atmel_sha_copy_hash(req);
-+ if (SHA_FLAGS_FINAL & dd->flags)
-+ err = atmel_sha_finish(req);
-+ } else {
-+ ctx->flags |= SHA_FLAGS_ERROR;
-+ }
-+
-+ /* atomic operation is not needed here */
-+ dd->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL | SHA_FLAGS_CPU |
-+ SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY);
-+
-+ clk_disable_unprepare(dd->iclk);
-+
-+ if (req->base.complete)
-+ req->base.complete(&req->base, err);
-+
-+ /* handle new request */
-+ tasklet_schedule(&dd->done_task);
-+}
-+
-+static int atmel_sha_hw_init(struct atmel_sha_dev *dd)
-+{
-+ clk_prepare_enable(dd->iclk);
-+
-+ if (SHA_FLAGS_INIT & dd->flags) {
-+ atmel_sha_write(dd, SHA_CR, SHA_CR_SWRST);
-+ atmel_sha_dualbuff_test(dd);
-+ dd->flags |= SHA_FLAGS_INIT;
-+ dd->err = 0;
-+ }
-+
-+ return 0;
-+}
-+
-+static int atmel_sha_handle_queue(struct atmel_sha_dev *dd,
-+ struct ahash_request *req)
-+{
-+ struct crypto_async_request *async_req, *backlog;
-+ struct atmel_sha_reqctx *ctx;
-+ unsigned long flags;
-+ int err = 0, ret = 0;
-+
-+ spin_lock_irqsave(&dd->lock, flags);
-+ if (req)
-+ ret = ahash_enqueue_request(&dd->queue, req);
-+
-+ if (SHA_FLAGS_BUSY & dd->flags) {
-+ spin_unlock_irqrestore(&dd->lock, flags);
-+ return ret;
-+ }
-+
-+ backlog = crypto_get_backlog(&dd->queue);
-+ async_req = crypto_dequeue_request(&dd->queue);
-+ if (async_req)
-+ dd->flags |= SHA_FLAGS_BUSY;
-+
-+ spin_unlock_irqrestore(&dd->lock, flags);
-+
-+ if (!async_req)
-+ return ret;
-+
-+ if (backlog)
-+ backlog->complete(backlog, -EINPROGRESS);
-+
-+ req = ahash_request_cast(async_req);
-+ dd->req = req;
-+ ctx = ahash_request_ctx(req);
-+
-+ dev_dbg(dd->dev, "handling new req, op: %lu, nbytes: %d\n",
-+ ctx->op, req->nbytes);
-+
-+ err = atmel_sha_hw_init(dd);
-+
-+ if (err)
-+ goto err1;
-+
-+ if (ctx->op == SHA_OP_UPDATE) {
-+ err = atmel_sha_update_req(dd);
-+ if (err != -EINPROGRESS && (ctx->flags & SHA_FLAGS_FINUP)) {
-+ /* no final() after finup() */
-+ err = atmel_sha_final_req(dd);
-+ }
-+ } else if (ctx->op == SHA_OP_FINAL) {
-+ err = atmel_sha_final_req(dd);
-+ }
-+
-+err1:
-+ if (err != -EINPROGRESS)
-+ /* done_task will not finish it, so do it here */
-+ atmel_sha_finish_req(req, err);
-+
-+ dev_dbg(dd->dev, "exit, err: %d\n", err);
-+
-+ return ret;
-+}
-+
-+static int atmel_sha_enqueue(struct ahash_request *req, unsigned int op)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
-+ struct atmel_sha_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
-+ struct atmel_sha_dev *dd = tctx->dd;
-+
-+ ctx->op = op;
-+
-+ return atmel_sha_handle_queue(dd, req);
-+}
-+
-+static int atmel_sha_update(struct ahash_request *req)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
-+
-+ if (!req->nbytes)
-+ return 0;
-+
-+ ctx->total = req->nbytes;
-+ ctx->sg = req->src;
-+ ctx->offset = 0;
-+
-+ if (ctx->flags & SHA_FLAGS_FINUP) {
-+ if (ctx->bufcnt + ctx->total < ATMEL_SHA_DMA_THRESHOLD)
-+ /* faster to use CPU for short transfers */
-+ ctx->flags |= SHA_FLAGS_CPU;
-+ } else if (ctx->bufcnt + ctx->total < ctx->buflen) {
-+ atmel_sha_append_sg(ctx);
-+ return 0;
-+ }
-+ return atmel_sha_enqueue(req, SHA_OP_UPDATE);
-+}
-+
-+static int atmel_sha_final(struct ahash_request *req)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
-+ struct atmel_sha_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
-+ struct atmel_sha_dev *dd = tctx->dd;
-+
-+ int err = 0;
-+
-+ ctx->flags |= SHA_FLAGS_FINUP;
-+
-+ if (ctx->flags & SHA_FLAGS_ERROR)
-+ return 0; /* uncompleted hash is not needed */
-+
-+ if (ctx->bufcnt) {
-+ return atmel_sha_enqueue(req, SHA_OP_FINAL);
-+ } else if (!(ctx->flags & SHA_FLAGS_PAD)) { /* add padding */
-+ err = atmel_sha_hw_init(dd);
-+ if (err)
-+ goto err1;
-+
-+ dd->flags |= SHA_FLAGS_BUSY;
-+ err = atmel_sha_final_req(dd);
-+ } else {
-+ /* copy ready hash (+ finalize hmac) */
-+ return atmel_sha_finish(req);
-+ }
-+
-+err1:
-+ if (err != -EINPROGRESS)
-+ /* done_task will not finish it, so do it here */
-+ atmel_sha_finish_req(req, err);
-+
-+ return err;
-+}
-+
-+static int atmel_sha_finup(struct ahash_request *req)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
-+ int err1, err2;
-+
-+ ctx->flags |= SHA_FLAGS_FINUP;
-+
-+ err1 = atmel_sha_update(req);
-+ if (err1 == -EINPROGRESS || err1 == -EBUSY)
-+ return err1;
-+
-+ /*
-+ * final() has to be always called to cleanup resources
-+ * even if udpate() failed, except EINPROGRESS
-+ */
-+ err2 = atmel_sha_final(req);
-+
-+ return err1 ?: err2;
-+}
-+
-+static int atmel_sha_digest(struct ahash_request *req)
-+{
-+ return atmel_sha_init(req) ?: atmel_sha_finup(req);
-+}
-+
-+static int atmel_sha_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base)
-+{
-+ struct atmel_sha_ctx *tctx = crypto_tfm_ctx(tfm);
-+ const char *alg_name = crypto_tfm_alg_name(tfm);
-+
-+ /* Allocate a fallback and abort if it failed. */
-+ tctx->fallback = crypto_alloc_shash(alg_name, 0,
-+ CRYPTO_ALG_NEED_FALLBACK);
-+ if (IS_ERR(tctx->fallback)) {
-+ pr_err("atmel-sha: fallback driver '%s' could not be loaded.\n",
-+ alg_name);
-+ return PTR_ERR(tctx->fallback);
-+ }
-+ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
-+ sizeof(struct atmel_sha_reqctx) +
-+ SHA_BUFFER_LEN + SHA256_BLOCK_SIZE);
-+
-+ return 0;
-+}
-+
-+static int atmel_sha_cra_init(struct crypto_tfm *tfm)
-+{
-+ return atmel_sha_cra_init_alg(tfm, NULL);
-+}
-+
-+static void atmel_sha_cra_exit(struct crypto_tfm *tfm)
-+{
-+ struct atmel_sha_ctx *tctx = crypto_tfm_ctx(tfm);
-+
-+ crypto_free_shash(tctx->fallback);
-+ tctx->fallback = NULL;
-+}
-+
-+static struct ahash_alg sha_algs[] = {
-+{
-+ .init = atmel_sha_init,
-+ .update = atmel_sha_update,
-+ .final = atmel_sha_final,
-+ .finup = atmel_sha_finup,
-+ .digest = atmel_sha_digest,
-+ .halg = {
-+ .digestsize = SHA1_DIGEST_SIZE,
-+ .base = {
-+ .cra_name = "sha1",
-+ .cra_driver_name = "atmel-sha1",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_ASYNC |
-+ CRYPTO_ALG_NEED_FALLBACK,
-+ .cra_blocksize = SHA1_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_sha_ctx),
-+ .cra_alignmask = 0,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_sha_cra_init,
-+ .cra_exit = atmel_sha_cra_exit,
-+ }
-+ }
-+},
-+{
-+ .init = atmel_sha_init,
-+ .update = atmel_sha_update,
-+ .final = atmel_sha_final,
-+ .finup = atmel_sha_finup,
-+ .digest = atmel_sha_digest,
-+ .halg = {
-+ .digestsize = SHA256_DIGEST_SIZE,
-+ .base = {
-+ .cra_name = "sha256",
-+ .cra_driver_name = "atmel-sha256",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_ASYNC |
-+ CRYPTO_ALG_NEED_FALLBACK,
-+ .cra_blocksize = SHA256_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_sha_ctx),
-+ .cra_alignmask = 0,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_sha_cra_init,
-+ .cra_exit = atmel_sha_cra_exit,
-+ }
-+ }
-+},
-+};
-+
-+static void atmel_sha_done_task(unsigned long data)
-+{
-+ struct atmel_sha_dev *dd = (struct atmel_sha_dev *)data;
-+ int err = 0;
-+
-+ if (!(SHA_FLAGS_BUSY & dd->flags)) {
-+ atmel_sha_handle_queue(dd, NULL);
-+ return;
-+ }
-+
-+ if (SHA_FLAGS_CPU & dd->flags) {
-+ if (SHA_FLAGS_OUTPUT_READY & dd->flags) {
-+ dd->flags &= ~SHA_FLAGS_OUTPUT_READY;
-+ goto finish;
-+ }
-+ } else if (SHA_FLAGS_DMA_READY & dd->flags) {
-+ if (SHA_FLAGS_DMA_ACTIVE & dd->flags) {
-+ dd->flags &= ~SHA_FLAGS_DMA_ACTIVE;
-+ atmel_sha_update_dma_stop(dd);
-+ if (dd->err) {
-+ err = dd->err;
-+ goto finish;
-+ }
-+ }
-+ if (SHA_FLAGS_OUTPUT_READY & dd->flags) {
-+ /* hash or semi-hash ready */
-+ dd->flags &= ~(SHA_FLAGS_DMA_READY |
-+ SHA_FLAGS_OUTPUT_READY);
-+ err = atmel_sha_update_dma_start(dd);
-+ if (err != -EINPROGRESS)
-+ goto finish;
-+ }
-+ }
-+ return;
-+
-+finish:
-+ /* finish curent request */
-+ atmel_sha_finish_req(dd->req, err);
-+}
-+
-+static irqreturn_t atmel_sha_irq(int irq, void *dev_id)
-+{
-+ struct atmel_sha_dev *sha_dd = dev_id;
-+ u32 reg;
-+
-+ reg = atmel_sha_read(sha_dd, SHA_ISR);
-+ if (reg & atmel_sha_read(sha_dd, SHA_IMR)) {
-+ atmel_sha_write(sha_dd, SHA_IDR, reg);
-+ if (SHA_FLAGS_BUSY & sha_dd->flags) {
-+ sha_dd->flags |= SHA_FLAGS_OUTPUT_READY;
-+ if (!(SHA_FLAGS_CPU & sha_dd->flags))
-+ sha_dd->flags |= SHA_FLAGS_DMA_READY;
-+ tasklet_schedule(&sha_dd->done_task);
-+ } else {
-+ dev_warn(sha_dd->dev, "SHA interrupt when no active requests.\n");
-+ }
-+ return IRQ_HANDLED;
-+ }
-+
-+ return IRQ_NONE;
-+}
-+
-+static void atmel_sha_unregister_algs(struct atmel_sha_dev *dd)
-+{
-+ int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(sha_algs); i++)
-+ crypto_unregister_ahash(&sha_algs[i]);
-+}
-+
-+static int atmel_sha_register_algs(struct atmel_sha_dev *dd)
-+{
-+ int err, i, j;
-+
-+ for (i = 0; i < ARRAY_SIZE(sha_algs); i++) {
-+ err = crypto_register_ahash(&sha_algs[i]);
-+ if (err)
-+ goto err_sha_algs;
-+ }
-+
-+ return 0;
-+
-+err_sha_algs:
-+ for (j = 0; j < i; j++)
-+ crypto_unregister_ahash(&sha_algs[j]);
-+
-+ return err;
-+}
-+
-+static int __devinit atmel_sha_probe(struct platform_device *pdev)
-+{
-+ struct atmel_sha_dev *sha_dd;
-+ struct device *dev = &pdev->dev;
-+ struct resource *sha_res;
-+ unsigned long sha_phys_size;
-+ int err;
-+
-+ sha_dd = kzalloc(sizeof(struct atmel_sha_dev), GFP_KERNEL);
-+ if (sha_dd == NULL) {
-+ dev_err(dev, "unable to alloc data struct.\n");
-+ err = -ENOMEM;
-+ goto sha_dd_err;
-+ }
-+
-+ sha_dd->dev = dev;
-+
-+ platform_set_drvdata(pdev, sha_dd);
-+
-+ INIT_LIST_HEAD(&sha_dd->list);
-+
-+ tasklet_init(&sha_dd->done_task, atmel_sha_done_task,
-+ (unsigned long)sha_dd);
-+
-+ crypto_init_queue(&sha_dd->queue, ATMEL_SHA_QUEUE_LENGTH);
-+
-+ sha_dd->irq = -1;
-+
-+ /* Get the base address */
-+ sha_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!sha_res) {
-+ dev_err(dev, "no MEM resource info\n");
-+ err = -ENODEV;
-+ goto res_err;
-+ }
-+ sha_dd->phys_base = sha_res->start;
-+ sha_phys_size = resource_size(sha_res);
-+
-+ /* Get the IRQ */
-+ sha_dd->irq = platform_get_irq(pdev, 0);
-+ if (sha_dd->irq < 0) {
-+ dev_err(dev, "no IRQ resource info\n");
-+ err = sha_dd->irq;
-+ goto res_err;
-+ }
-+
-+ err = request_irq(sha_dd->irq, atmel_sha_irq, IRQF_SHARED, "atmel-sha",
-+ sha_dd);
-+ if (err) {
-+ dev_err(dev, "unable to request sha irq.\n");
-+ goto res_err;
-+ }
-+
-+ /* Initializing the clock */
-+ sha_dd->iclk = clk_get(&pdev->dev, NULL);
-+ if (IS_ERR(sha_dd->iclk)) {
-+ dev_err(dev, "clock intialization failed.\n");
-+ err = PTR_ERR(sha_dd->iclk);
-+ goto clk_err;
-+ }
-+
-+ sha_dd->io_base = ioremap(sha_dd->phys_base, sha_phys_size);
-+ if (!sha_dd->io_base) {
-+ dev_err(dev, "can't ioremap\n");
-+ err = -ENOMEM;
-+ goto sha_io_err;
-+ }
-+
-+ spin_lock(&atmel_sha.lock);
-+ list_add_tail(&sha_dd->list, &atmel_sha.dev_list);
-+ spin_unlock(&atmel_sha.lock);
-+
-+ err = atmel_sha_register_algs(sha_dd);
-+ if (err)
-+ goto err_algs;
-+
-+ dev_info(dev, "Atmel SHA1/SHA256\n");
-+
-+ return 0;
-+
-+err_algs:
-+ spin_lock(&atmel_sha.lock);
-+ list_del(&sha_dd->list);
-+ spin_unlock(&atmel_sha.lock);
-+ iounmap(sha_dd->io_base);
-+sha_io_err:
-+ clk_put(sha_dd->iclk);
-+clk_err:
-+ free_irq(sha_dd->irq, sha_dd);
-+res_err:
-+ tasklet_kill(&sha_dd->done_task);
-+ kfree(sha_dd);
-+ sha_dd = NULL;
-+sha_dd_err:
-+ dev_err(dev, "initialization failed.\n");
-+
-+ return err;
-+}
-+
-+static int __devexit atmel_sha_remove(struct platform_device *pdev)
-+{
-+ static struct atmel_sha_dev *sha_dd;
-+
-+ sha_dd = platform_get_drvdata(pdev);
-+ if (!sha_dd)
-+ return -ENODEV;
-+ spin_lock(&atmel_sha.lock);
-+ list_del(&sha_dd->list);
-+ spin_unlock(&atmel_sha.lock);
-+
-+ atmel_sha_unregister_algs(sha_dd);
-+
-+ tasklet_kill(&sha_dd->done_task);
-+
-+ iounmap(sha_dd->io_base);
-+
-+ clk_put(sha_dd->iclk);
-+
-+ if (sha_dd->irq >= 0)
-+ free_irq(sha_dd->irq, sha_dd);
-+
-+ kfree(sha_dd);
-+ sha_dd = NULL;
-+
-+ return 0;
-+}
-+
-+static struct platform_driver atmel_sha_driver = {
-+ .probe = atmel_sha_probe,
-+ .remove = __devexit_p(atmel_sha_remove),
-+ .driver = {
-+ .name = "atmel_sha",
-+ .owner = THIS_MODULE,
-+ },
-+};
-+
-+module_platform_driver(atmel_sha_driver);
-+
-+MODULE_DESCRIPTION("Atmel SHA1/SHA256 hw acceleration support.");
-+MODULE_LICENSE("GPL v2");
-+MODULE_AUTHOR("Nicolas Royer - Eukréa Electromatique");
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 6cfecc127971e728597592ccfaafc2527cdf2d1a Mon Sep 17 00:00:00 2001
-From: Nicolas Royer <nicolas@eukrea.com>
-Date: Mon, 17 Sep 2012 18:26:07 +0200
-Subject: crypto: add atmel-test driver
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Eric Bénard <eric@eukrea.com>
-Tested-by: Eric Bénard <eric@eukrea.com>
----
- drivers/crypto/Kconfig | 12 ++
- drivers/crypto/Makefile | 1 +
- drivers/crypto/atmel-test.c | 444 ++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 457 insertions(+)
- create mode 100644 drivers/crypto/atmel-test.c
-
-diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
-index 2339add..7a356fe 100644
---- a/drivers/crypto/Kconfig
-+++ b/drivers/crypto/Kconfig
-@@ -343,4 +343,16 @@ config CRYPTO_DEV_ATMEL_SHA
- To compile this driver as a module, choose M here: the module
- will be called atmel-sha.
-
-+config CRYPTO_DEV_ATMEL_TEST
-+ tristate "TEST MODULE"
-+ depends on ARCH_AT91
-+ select CRYPTO_SHA1
-+ select CRYPTO_SHA256
-+ help
-+ Some Atmel processors have SHA1/SHA256/TDES/AES hw accelerator.
-+ Select this if you want to test SHA1/SHA256/TDES/AES drivers.
-+
-+ To compile this driver as a module, choose M here: the module
-+ will be called atmel-test.
-+
- endif # CRYPTO_HW
-diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
-index d355c25..bbe005b 100644
---- a/drivers/crypto/Makefile
-+++ b/drivers/crypto/Makefile
-@@ -17,3 +17,4 @@ obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o
- obj-$(CONFIG_CRYPTO_DEV_ATMEL_AES) += atmel-aes.o
- obj-$(CONFIG_CRYPTO_DEV_ATMEL_TDES) += atmel-tdes.o
- obj-$(CONFIG_CRYPTO_DEV_ATMEL_SHA) += atmel-sha.o
-+obj-$(CONFIG_CRYPTO_DEV_ATMEL_TEST) += atmel-test.o
-diff --git a/drivers/crypto/atmel-test.c b/drivers/crypto/atmel-test.c
-new file mode 100644
-index 0000000..4a23db5
---- /dev/null
-+++ b/drivers/crypto/atmel-test.c
-@@ -0,0 +1,444 @@
-+/*
-+ * Cryptographic API.
-+ *
-+ * ATMEL SHA1/SHA256/TDES/AES HW acceleration test.
-+ *
-+ * Author: Nicolas Royer - Eukréa Electromatique
-+ *
-+ * 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/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/crypto.h>
-+#include <linux/err.h>
-+#include <linux/scatterlist.h>
-+#include <linux/gfp.h>
-+#include <crypto/hash.h>
-+
-+static char *pattern64 =
-+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
-+ "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
-+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
-+ "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
-+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
-+ "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
-+ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
-+ "\xad\x2b\x41\x7b\xe6\x6c\x37\x10";
-+
-+static char *key32 =
-+ "\x60\x3d\xeb\x10\x15\xca\x71\xbe"
-+ "\x2b\x73\xae\xf0\x85\x7d\x77\x81"
-+ "\x1f\x35\x2c\x07\x3b\x61\x08\xd7"
-+ "\x2d\x98\x10\xa3\x09\x14\xdf\xf4";
-+
-+static char *iv16 =
-+ "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
-+ "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58";
-+
-+#define SHA1_MSG_LEN 20
-+#define SHA256_MSG_LEN 32
-+static char sha_out_buf[SHA256_MSG_LEN];
-+
-+#define TVMEMSIZE 4
-+static char *tvmem[TVMEMSIZE];
-+
-+
-+static void hexdump(unsigned char *buf, unsigned int len)
-+{
-+ print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
-+ 16, 1,
-+ buf, len, false);
-+}
-+
-+struct hmac_sha_result {
-+ struct completion completion;
-+ int err;
-+};
-+
-+static void hmac_sha_complete(struct crypto_async_request *req, int err)
-+{
-+ struct hmac_sha_result *r = req->data;
-+ if (err == -EINPROGRESS)
-+ return;
-+ r->err = err;
-+ complete(&r->completion);
-+}
-+
-+static inline int do_one_ahash_op(struct ahash_request *req, int ret)
-+{
-+ if (ret == -EINPROGRESS || ret == -EBUSY) {
-+ struct hmac_sha_result *tr = req->base.data;
-+
-+ ret = wait_for_completion_interruptible(&tr->completion);
-+ if (!ret)
-+ ret = tr->err;
-+ INIT_COMPLETION(tr->completion);
-+ }
-+ return ret;
-+}
-+
-+static int hmac_sha_update(const char *algo, char *data_in, size_t dlen,
-+ char *hash_out, size_t outlen)
-+{
-+ int rc = 0;
-+ struct crypto_ahash *tfm;
-+ struct scatterlist sg[TVMEMSIZE];
-+ struct ahash_request *req;
-+ struct hmac_sha_result tresult;
-+ int i, j;
-+
-+ /* Set hash output to 0 initially */
-+ memset(hash_out, 0, outlen);
-+
-+ init_completion(&tresult.completion);
-+ tfm = crypto_alloc_ahash(algo, 0, 0);
-+ if (IS_ERR(tfm)) {
-+ printk(KERN_ERR "crypto_alloc_ahash failed\n");
-+ rc = PTR_ERR(tfm);
-+ goto err_tfm;
-+ }
-+ req = ahash_request_alloc(tfm, GFP_KERNEL);
-+ if (!req) {
-+ printk(KERN_ERR "failed to allocate request\n");
-+ rc = -ENOMEM;
-+ goto err_req;
-+ }
-+ if (crypto_ahash_digestsize(tfm) > outlen) {
-+ printk(KERN_ERR "tfm size > result buffer\n");
-+ rc = -EINVAL;
-+ goto err_req;
-+ }
-+ ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-+ hmac_sha_complete, &tresult);
-+
-+ sg_init_table(sg, TVMEMSIZE);
-+
-+ i = 0;
-+ j = dlen;
-+
-+ while (j > PAGE_SIZE) {
-+ sg_set_buf(sg + i, tvmem[i], PAGE_SIZE);
-+ memcpy(tvmem[i], data_in + i * PAGE_SIZE, PAGE_SIZE);
-+ i++;
-+ j -= PAGE_SIZE;
-+ }
-+ sg_set_buf(sg + i, tvmem[i], j);
-+ memcpy(tvmem[i], data_in + i * PAGE_SIZE, j);
-+
-+ crypto_ahash_clear_flags(tfm, -0);
-+ ahash_request_set_crypt(req, sg, hash_out, dlen);
-+ rc = crypto_ahash_init(req);
-+ rc = do_one_ahash_op(req, crypto_ahash_update(req));
-+ if (rc)
-+ goto out;
-+
-+ rc = do_one_ahash_op(req, crypto_ahash_final(req));
-+
-+out:
-+ ahash_request_free(req);
-+err_req:
-+ crypto_free_ahash(tfm);
-+err_tfm:
-+ return rc;
-+}
-+
-+static int hmac_sha_digest(const char *algo, char *data_in, size_t dlen,
-+ char *hash_out, size_t outlen)
-+{
-+ int rc = 0;
-+ struct crypto_ahash *tfm;
-+ struct scatterlist sg;
-+ struct ahash_request *req;
-+ struct hmac_sha_result tresult;
-+
-+ /* Set hash output to 0 initially */
-+ memset(hash_out, 0, outlen);
-+
-+ init_completion(&tresult.completion);
-+ tfm = crypto_alloc_ahash(algo, 0, 0);
-+ if (IS_ERR(tfm)) {
-+ printk(KERN_ERR "crypto_alloc_ahash failed\n");
-+ rc = PTR_ERR(tfm);
-+ goto err_tfm;
-+ }
-+ req = ahash_request_alloc(tfm, GFP_KERNEL);
-+ if (!req) {
-+ printk(KERN_ERR "failed to allocate request\n");
-+ rc = -ENOMEM;
-+ goto err_req;
-+ }
-+ if (crypto_ahash_digestsize(tfm) > outlen) {
-+ printk(KERN_ERR "tfm size > result buffer\n");
-+ rc = -EINVAL;
-+ goto err_req;
-+ }
-+ ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-+ hmac_sha_complete, &tresult);
-+
-+ sg_init_one(&sg, data_in, dlen);
-+
-+ crypto_ahash_clear_flags(tfm, -0);
-+ ahash_request_set_crypt(req, &sg, hash_out, dlen);
-+ rc = do_one_ahash_op(req, crypto_ahash_digest(req));
-+
-+ ahash_request_free(req);
-+err_req:
-+ crypto_free_ahash(tfm);
-+err_tfm:
-+ return rc;
-+}
-+
-+struct tcrypt_result {
-+ struct completion completion;
-+ int err;
-+};
-+
-+static void tcrypt_complete(struct crypto_async_request *req, int err)
-+{
-+ struct tcrypt_result *res = req->data;
-+
-+ if (err == -EINPROGRESS)
-+ return;
-+
-+ res->err = err;
-+ complete(&res->completion);
-+}
-+
-+static inline int do_one_acipher_op(struct ablkcipher_request *req, int ret)
-+{
-+ if (ret == -EINPROGRESS || ret == -EBUSY) {
-+ struct tcrypt_result *tr = req->base.data;
-+
-+ ret = wait_for_completion_interruptible(&tr->completion);
-+ if (!ret)
-+ ret = tr->err;
-+ INIT_COMPLETION(tr->completion);
-+ }
-+ return ret;
-+}
-+
-+static int test_acipher(const char *algo, int enc, char *data_in,
-+ char *data_out, size_t data_len, char *key, int keysize)
-+ {
-+ struct crypto_ablkcipher *tfm;
-+ struct tcrypt_result tresult;
-+ struct ablkcipher_request *req;
-+ struct scatterlist sg[TVMEMSIZE];
-+ unsigned int ret, i, j, iv_len;
-+ char iv[128];
-+
-+ ret = -EAGAIN;
-+
-+ init_completion(&tresult.completion);
-+
-+ tfm = crypto_alloc_ablkcipher(algo, 0, 0);
-+ if (IS_ERR(tfm)) {
-+ printk(KERN_ERR "failed to load transform for %s: %ld\n",
-+ algo, PTR_ERR(tfm));
-+ return ret;
-+ }
-+
-+ req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
-+ if (!req) {
-+ printk(KERN_ERR "tcrypt: skcipher: Failed to allocate request for %s\n",
-+ algo);
-+ goto out;
-+ }
-+
-+ ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-+ tcrypt_complete, &tresult);
-+
-+ crypto_ablkcipher_clear_flags(tfm, ~0);
-+
-+ ret = crypto_ablkcipher_setkey(tfm, key, keysize);
-+ if (ret) {
-+ printk(KERN_ERR "setkey() failed flags=%x\n",
-+ crypto_ablkcipher_get_flags(tfm));
-+ goto out_free_req;
-+ }
-+
-+ printk(KERN_INFO "KEY:\n");
-+ hexdump(key, keysize);
-+
-+ sg_init_table(sg, TVMEMSIZE);
-+
-+ i = 0;
-+ j = data_len;
-+
-+ while (j > PAGE_SIZE) {
-+ sg_set_buf(sg + i, tvmem[i], PAGE_SIZE);
-+ memcpy(tvmem[i], data_in + i * PAGE_SIZE, PAGE_SIZE);
-+ i++;
-+ j -= PAGE_SIZE;
-+ }
-+ sg_set_buf(sg + i, tvmem[i], j);
-+ memcpy(tvmem[i], data_in + i * PAGE_SIZE, j);
-+
-+ iv_len = crypto_ablkcipher_ivsize(tfm);
-+ memcpy(iv, iv16, iv_len);
-+
-+ printk(KERN_INFO "IV:\n");
-+ hexdump(iv, iv_len);
-+
-+ ablkcipher_request_set_crypt(req, sg, sg, data_len, iv);
-+
-+ printk(KERN_INFO "IN:\n");
-+ hexdump(data_in, data_len);
-+
-+ if (enc)
-+ ret = do_one_acipher_op(req, crypto_ablkcipher_encrypt(req));
-+ else
-+ ret = do_one_acipher_op(req, crypto_ablkcipher_decrypt(req));
-+
-+ if (ret)
-+ printk(KERN_ERR "failed flags=%x\n",
-+ crypto_ablkcipher_get_flags(tfm));
-+ else {
-+ i = 0;
-+ j = data_len;
-+ while (j > PAGE_SIZE) {
-+ memcpy(data_out + i * PAGE_SIZE, tvmem[i], PAGE_SIZE);
-+ i++;
-+ j -= PAGE_SIZE;
-+ }
-+ memcpy(data_out + i * PAGE_SIZE, tvmem[i], j);
-+
-+ printk(KERN_INFO "OUT:\n");
-+ hexdump(data_out, data_len);
-+ }
-+
-+out_free_req:
-+ ablkcipher_request_free(req);
-+out:
-+ crypto_free_ablkcipher(tfm);
-+
-+ return ret;
-+}
-+
-+static int mode = 10;
-+module_param_named(mode, mode, int,
-+ S_IRUGO | S_IWUSR | S_IWGRP);
-+
-+static int keylen = 8;
-+module_param_named(keylen, keylen, int,
-+ S_IRUGO | S_IWUSR | S_IWGRP);
-+
-+static int dlen = 64;
-+module_param_named(dlen, dlen, int,
-+ S_IRUGO | S_IWUSR | S_IWGRP);
-+
-+char *ahash_algs[] = {"sha1", "sha256"};
-+
-+char *acipher_algs[] = {
-+ "ecb(des)", "cbc(des)", "cfb(des)", "cfb32(des)",
-+ "cfb16(des)", "cfb8(des)", "ofb(des)", "ecb(des3_ede)",
-+ "cbc(des3_ede)", "cfb(des3_ede)", "cfb32(des3_ede)", "cfb16(des3_ede)",
-+ "cfb8(des3_ede)", "ofb(des3_ede)", "ecb(aes)", "cbc(aes)",
-+ "ofb(aes)", "cfb(aes)", "cfb64(aes)", "cfb32(aes)",
-+ "cfb16(aes)", "cfb8(aes)", "ctr(aes)"};
-+
-+static int __init init_main(void)
-+{
-+ unsigned int i;
-+ char *buf_in;
-+ char *buf_out;
-+ char *buf_res;
-+
-+ if ((dlen <= 0) || (dlen > TVMEMSIZE*PAGE_SIZE)) {
-+ printk(KERN_ERR " 0 < dlen <= %i\n",
-+ (int) (TVMEMSIZE*PAGE_SIZE));
-+ return -EAGAIN;
-+ }
-+
-+ for (i = 0; i < TVMEMSIZE; i++) {
-+ tvmem[i] = (void *)__get_free_page(GFP_KERNEL);
-+ if (!tvmem[i])
-+ goto err_free_tv;
-+ }
-+
-+ buf_in = kzalloc(dlen, GFP_KERNEL);
-+ if (!buf_in)
-+ goto err_buf_in_alloc;
-+ buf_out = kzalloc(dlen, GFP_KERNEL);
-+ if (!buf_out)
-+ goto err_buf_out_alloc;
-+ buf_res = kzalloc(dlen, GFP_KERNEL);
-+ if (!buf_res)
-+ goto err_buf_res_alloc;
-+
-+ if (dlen > 64) {
-+ memcpy(buf_in, pattern64, 64);
-+ memset(buf_in+64, 0xFF, dlen-64);
-+ } else
-+ memcpy(buf_in, pattern64, dlen);
-+
-+ if (mode < 10) {
-+ if (mode >= ARRAY_SIZE(ahash_algs)) {
-+ printk(KERN_ERR "mode must be < %d or > 10\n",
-+ ARRAY_SIZE(ahash_algs));
-+ goto exit;
-+ }
-+ printk(KERN_INFO "\n%s digest_req\n", ahash_algs[mode]);
-+ hmac_sha_digest(ahash_algs[mode], buf_in, dlen, sha_out_buf,
-+ mode ? SHA256_MSG_LEN : SHA1_MSG_LEN);
-+ hexdump(sha_out_buf, mode ? SHA256_MSG_LEN : SHA1_MSG_LEN);
-+
-+ printk(KERN_INFO "\n%s update_req\n", ahash_algs[mode]);
-+ hmac_sha_update(ahash_algs[mode], buf_in, dlen, sha_out_buf,
-+ mode ? SHA256_MSG_LEN : SHA1_MSG_LEN);
-+ hexdump(sha_out_buf, mode ? SHA256_MSG_LEN : SHA1_MSG_LEN);
-+ } else {
-+ mode -= 10;
-+
-+ if (mode >= ARRAY_SIZE(acipher_algs)) {
-+ printk(KERN_ERR "mode must be < %d\n",
-+ ARRAY_SIZE(acipher_algs) + 10);
-+ goto exit;
-+ }
-+
-+ printk(KERN_INFO "\n%s encrypt\n", acipher_algs[mode]);
-+ if (test_acipher(acipher_algs[mode], 1, buf_in, buf_out,
-+ dlen, key32, keylen))
-+ goto exit;
-+
-+ printk(KERN_INFO "\n%s decrypt\n", acipher_algs[mode]);
-+ if (test_acipher(acipher_algs[mode], 0, buf_out, buf_res,
-+ dlen, key32, keylen))
-+ goto exit;
-+
-+ if (memcmp(buf_in, buf_res, dlen))
-+ printk(KERN_INFO "\n%s test failed\n\n",
-+ acipher_algs[mode]);
-+ else
-+ printk(KERN_INFO "\n%s test OK\n\n",
-+ acipher_algs[mode]);
-+ }
-+
-+exit:
-+ kfree(buf_res);
-+err_buf_res_alloc:
-+ kfree(buf_out);
-+err_buf_out_alloc:
-+ kfree(buf_in);
-+err_buf_in_alloc:
-+err_free_tv:
-+ for (i = 0; i < TVMEMSIZE && tvmem[i]; i++)
-+ free_page((unsigned long)tvmem[i]);
-+
-+ return -EAGAIN;
-+}
-+
-+static void __exit cleanup_main(void)
-+{
-+}
-+
-+module_init(init_main);
-+module_exit(cleanup_main);
-+
-+MODULE_LICENSE("GPL v2");
-+MODULE_AUTHOR("Nicolas Royer - Eukréa Electromatique");
-+MODULE_DESCRIPTION("Atmel HW crypto test");
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 6f6e5ce06de79a8b3bf26062a01bece308994236 Mon Sep 17 00:00:00 2001
-From: Nicolas Royer <nicolas@eukrea.com>
-Date: Mon, 17 Sep 2012 18:26:08 +0200
-Subject: crypto: add new tests to tcrypt
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-commit de197533485c09598215802b0e401a688e172573 upstream.
-
-- set sg buffers size equals to message size
-- add cfb & ofb tests for AES, DES & TDES
-
-Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Eric Bénard <eric@eukrea.com>
-Tested-by: Eric Bénard <eric@eukrea.com>
----
- crypto/tcrypt.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-----
- 1 file changed, 45 insertions(+), 5 deletions(-)
-
-diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
-index 8f147bf..a9296bd 100644
---- a/crypto/tcrypt.c
-+++ b/crypto/tcrypt.c
-@@ -809,7 +809,7 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int sec,
- struct cipher_speed_template *template,
- unsigned int tcount, u8 *keysize)
- {
-- unsigned int ret, i, j, iv_len;
-+ unsigned int ret, i, j, k, iv_len;
- struct tcrypt_result tresult;
- const char *key;
- char iv[128];
-@@ -883,11 +883,23 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int sec,
- }
-
- sg_init_table(sg, TVMEMSIZE);
-- sg_set_buf(sg, tvmem[0] + *keysize,
-+
-+ k = *keysize + *b_size;
-+ if (k > PAGE_SIZE) {
-+ sg_set_buf(sg, tvmem[0] + *keysize,
- PAGE_SIZE - *keysize);
-- for (j = 1; j < TVMEMSIZE; j++) {
-- sg_set_buf(sg + j, tvmem[j], PAGE_SIZE);
-- memset(tvmem[j], 0xff, PAGE_SIZE);
-+ k -= PAGE_SIZE;
-+ j = 1;
-+ while (k > PAGE_SIZE) {
-+ sg_set_buf(sg + j, tvmem[j], PAGE_SIZE);
-+ memset(tvmem[j], 0xff, PAGE_SIZE);
-+ j++;
-+ k -= PAGE_SIZE;
-+ }
-+ sg_set_buf(sg + j, tvmem[j], k);
-+ memset(tvmem[j], 0xff, k);
-+ } else {
-+ sg_set_buf(sg, tvmem[0] + *keysize, *b_size);
- }
-
- iv_len = crypto_ablkcipher_ivsize(tfm);
-@@ -1512,6 +1524,14 @@ static int do_test(int m)
- speed_template_16_24_32);
- test_acipher_speed("ctr(aes)", DECRYPT, sec, NULL, 0,
- speed_template_16_24_32);
-+ test_acipher_speed("cfb(aes)", ENCRYPT, sec, NULL, 0,
-+ speed_template_16_24_32);
-+ test_acipher_speed("cfb(aes)", DECRYPT, sec, NULL, 0,
-+ speed_template_16_24_32);
-+ test_acipher_speed("ofb(aes)", ENCRYPT, sec, NULL, 0,
-+ speed_template_16_24_32);
-+ test_acipher_speed("ofb(aes)", DECRYPT, sec, NULL, 0,
-+ speed_template_16_24_32);
- break;
-
- case 501:
-@@ -1527,6 +1547,18 @@ static int do_test(int m)
- test_acipher_speed("cbc(des3_ede)", DECRYPT, sec,
- des3_speed_template, DES3_SPEED_VECTORS,
- speed_template_24);
-+ test_acipher_speed("cfb(des3_ede)", ENCRYPT, sec,
-+ des3_speed_template, DES3_SPEED_VECTORS,
-+ speed_template_24);
-+ test_acipher_speed("cfb(des3_ede)", DECRYPT, sec,
-+ des3_speed_template, DES3_SPEED_VECTORS,
-+ speed_template_24);
-+ test_acipher_speed("ofb(des3_ede)", ENCRYPT, sec,
-+ des3_speed_template, DES3_SPEED_VECTORS,
-+ speed_template_24);
-+ test_acipher_speed("ofb(des3_ede)", DECRYPT, sec,
-+ des3_speed_template, DES3_SPEED_VECTORS,
-+ speed_template_24);
- break;
-
- case 502:
-@@ -1538,6 +1570,14 @@ static int do_test(int m)
- speed_template_8);
- test_acipher_speed("cbc(des)", DECRYPT, sec, NULL, 0,
- speed_template_8);
-+ test_acipher_speed("cfb(des)", ENCRYPT, sec, NULL, 0,
-+ speed_template_8);
-+ test_acipher_speed("cfb(des)", DECRYPT, sec, NULL, 0,
-+ speed_template_8);
-+ test_acipher_speed("ofb(des)", ENCRYPT, sec, NULL, 0,
-+ speed_template_8);
-+ test_acipher_speed("ofb(des)", DECRYPT, sec, NULL, 0,
-+ speed_template_8);
- break;
-
- case 503:
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 499af8e10dac88ff1e4586930d7a157b2e38a893 Mon Sep 17 00:00:00 2001
-From: Nicolas Royer <nicolas@eukrea.com>
-Date: Mon, 17 Sep 2012 18:26:09 +0200
-Subject: AT91SAM9G45: crypto: same platform data header for all crypto
- peripherals
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Eric Bénard <eric@eukrea.com>
-Tested-by: Eric Bénard <eric@eukrea.com>
----
- arch/arm/mach-at91/at91sam9g45_devices.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
-index 3d523f0..896088d 100644
---- a/arch/arm/mach-at91/at91sam9g45_devices.c
-+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
-@@ -31,7 +31,7 @@
- #include <mach/at91sam9_smc.h>
- #include <mach/at_hdmac.h>
- #include <mach/atmel-mci.h>
--#include <linux/platform_data/atmel-aes.h>
-+#include <linux/platform_data/atmel-crypto.h>
- #include <media/atmel-isi.h>
-
- #include "generic.h"
-@@ -584,7 +584,7 @@ static void __init at91_add_device_tdes(void) {}
- * -------------------------------------------------------------------- */
-
- #if defined(CONFIG_CRYPTO_DEV_ATMEL_AES) || defined(CONFIG_CRYPTO_DEV_ATMEL_AES_MODULE)
--static struct aes_platform_data aes_data;
-+static struct crypto_platform_data aes_data;
- static u64 aes_dmamask = DMA_BIT_MASK(32);
-
- static struct resource aes_resources[] = {
-@@ -615,9 +615,9 @@ static struct platform_device at91sam9g45_aes_device = {
- static void __init at91_add_device_aes(void)
- {
- struct at_dma_slave *atslave;
-- struct aes_dma_data *alt_atslave;
-+ struct crypto_dma_data *alt_atslave;
-
-- alt_atslave = kzalloc(sizeof(struct aes_dma_data), GFP_KERNEL);
-+ alt_atslave = kzalloc(sizeof(struct crypto_dma_data), GFP_KERNEL);
-
- /* DMA TX slave channel configuration */
- atslave = &alt_atslave->txdata;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 29e5c6be830144305786ffb9143c06a9e96846ce Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 22 Oct 2012 16:05:01 +0200
-Subject: AT91SAM9G45: dts: add crypto peripherals
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Eric Bénard <eric@eukrea.com>
-Tested-by: Eric Bénard <eric@eukrea.com>
-
-Conflicts:
- arch/arm/boot/dts/at91sam9g45.dtsi
----
- arch/arm/boot/dts/at91sam9g45.dtsi | 25 +++++++++++++++++++++++++
- 1 file changed, 25 insertions(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
-index b032a8c..948dc96 100644
---- a/arch/arm/boot/dts/at91sam9g45.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
-@@ -106,6 +106,7 @@
- compatible = "atmel,at91sam9g45-dma";
- reg = <0xffffec00 0x200>;
- interrupts = <21 4 0>;
-+ #dma-cells = <1>;
- };
-
- pioA: gpio@fffff200 {
-@@ -243,6 +244,30 @@
- #size-cells = <0>;
- status = "disabled";
- };
-+
-+ aes@fffc0000 {
-+ compatible = "atmel,sam9g46-aes";
-+ reg = <0xfffc0000 0x100>;
-+ interrupts = <28 4 0>;
-+ dma = <&dma 0x2000020c /* tx cfg = ATC_FIFOCFG_ENOUGHSPACE 0x20006020
-+ | ATC_DST_H2SEL_HW
-+ | ATC_DST_PER(AT_DMA_ID_AES_TX); */
-+ &dma 0x200020b0 /* rx cfg = ATC_FIFOCFG_ENOUGHSPACE 0x20000603
-+ | ATC_SRC_H2SEL_HW
-+ | ATC_SRC_PER(AT_DMA_ID_AES_RX); */
-+ >;
-+ dma-name = "tx", "rx";
-+ };
-+ tdes@0xfffc4000 {
-+ compatible = "atmel,sam9g46-tdes";
-+ reg = <0xfffc4000 0x130>;
-+ interrupts = <28 4 0>;
-+ };
-+ sha@0xfffc8000 {
-+ compatible = "atmel,sam9g46-sha";
-+ reg = <0xfffc8000 0x130>;
-+ interrupts = <28 4 0>;
-+ };
- };
-
- nand0: nand@40000000 {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 4d751232a49a7f677bd665ca70c2887e6d2537d5 Mon Sep 17 00:00:00 2001
-From: Nicolas Royer <nicolas@eukrea.com>
-Date: Mon, 17 Sep 2012 18:26:13 +0200
-Subject: AT91SAM9N12: add crypto peripherals
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Eric Bénard <eric@eukrea.com>
-Tested-by: Eric Bénard <eric@eukrea.com>
----
- arch/arm/mach-at91/at91sam9n12.c | 17 +++++++++++++++++
- arch/arm/mach-at91/include/mach/at91sam9n12.h | 2 ++
- 2 files changed, 19 insertions(+)
-
-diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c
-index ebe94bb..d09baf1 100644
---- a/arch/arm/mach-at91/at91sam9n12.c
-+++ b/arch/arm/mach-at91/at91sam9n12.c
-@@ -17,6 +17,7 @@
- #include <mach/cpu.h>
- #include <mach/board.h>
-
-+
- #include "soc.h"
- #include "generic.h"
- #include "clock.h"
-@@ -134,6 +135,17 @@ static struct clk ssc_clk = {
- .pmc_mask = 1 << AT91SAM9N12_ID_SSC,
- .type = CLK_TYPE_PERIPHERAL,
- };
-+static struct clk aes_clk = {
-+ .name = "aes_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_AES,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+static struct clk sha_clk = {
-+ .name = "sha_clk",
-+ .pmc_mask = 1 << AT91SAM9N12_ID_SHA,
-+ .type = CLK_TYPE_PERIPHERAL,
-+};
-+
-
- static struct clk *periph_clocks[] __initdata = {
- &pioAB_clk,
-@@ -157,6 +169,8 @@ static struct clk *periph_clocks[] __initdata = {
- &uhp_clk,
- &udp_clk,
- &ssc_clk,
-+ &aes_clk,
-+ &sha_clk,
- };
-
- static struct clk_lookup periph_clocks_lookups[] = {
-@@ -176,6 +190,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_ID("pioB", &pioAB_clk),
- CLKDEV_CON_ID("pioC", &pioCD_clk),
- CLKDEV_CON_ID("pioD", &pioCD_clk),
-+ CLKDEV_CON_DEV_ID("aes_clk", "f000c000.aes", &aes_clk),
-+ CLKDEV_CON_DEV_ID("sha_clk", "f0014000.sha", &sha_clk),
- /* additional fake clock for macb_hclk */
- CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &uhp_clk),
- CLKDEV_CON_DEV_ID("ohci_clk", "500000.ohci", &uhp_clk),
-@@ -219,6 +235,7 @@ static void __init at91sam9n12_register_clocks(void)
- static void __init at91sam9n12_map_io(void)
- {
- at91_init_sram(0, AT91SAM9N12_SRAM_BASE, AT91SAM9N12_SRAM_SIZE);
-+ init_consistent_dma_size(SZ_4M);
- }
-
- void __init at91sam9n12_initialize(void)
-diff --git a/arch/arm/mach-at91/include/mach/at91sam9n12.h b/arch/arm/mach-at91/include/mach/at91sam9n12.h
-index d374b87..e07b0de 100644
---- a/arch/arm/mach-at91/include/mach/at91sam9n12.h
-+++ b/arch/arm/mach-at91/include/mach/at91sam9n12.h
-@@ -36,7 +36,9 @@
- #define AT91SAM9N12_ID_UDP 23 /* USB Device High Speed */
- #define AT91SAM9N12_ID_LCDC 25 /* LCD Controller */
- #define AT91SAM9N12_ID_ISI 25 /* Image Sensor Interface */
-+#define AT91SAM9N12_ID_SHA 27 /* SHA */
- #define AT91SAM9N12_ID_SSC 28 /* Synchronous Serial Controller */
-+#define AT91SAM9N12_ID_AES 29 /* AES */
- #define AT91SAM9N12_ID_TRNG 30 /* TRNG */
- #define AT91SAM9N12_ID_IRQ0 31 /* Advanced Interrupt Controller */
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 13559e1bdab3b9d165dd3e4949b38f7102c48a1a Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 22 Oct 2012 16:05:17 +0200
-Subject: AT91SAM9N12: dts: add crypto peripherals
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Eric Bénard <eric@eukrea.com>
-Tested-by: Eric Bénard <eric@eukrea.com>
-
-Conflicts:
- arch/arm/boot/dts/at91sam9n12.dtsi
----
- arch/arm/boot/dts/at91sam9n12.dtsi | 24 ++++++++++++++++++++++++
- 1 file changed, 24 insertions(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
-index 0d08c4e..42b53bd 100644
---- a/arch/arm/boot/dts/at91sam9n12.dtsi
-+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
-@@ -109,6 +109,7 @@
- compatible = "atmel,at91sam9g45-dma";
- reg = <0xffffec00 0x200>;
- interrupts = <20 4 0>;
-+ #dma-cells = <1>;
- };
-
- pioA: gpio@fffff400 {
-@@ -211,6 +212,29 @@
- #size-cells = <0>;
- status = "disabled";
- };
-+
-+ aes@f000c000 {
-+ compatible = "atmel,sam9g46-aes";
-+ reg = <0xf000c000 0x100>;
-+ interrupts = <29 4 0>;
-+ dma = <&dma 0x2000060B /* tx cfg = ATC_FIFOCFG_ENOUGHSPACE */
-+ /* | ATC_DST_H2SEL_HW */
-+ /* | ATC_DST_PER(AT_DMA_ID_AES_TX); */
-+ &dma 0x200060A0 /* rx cfg = ATC_FIFOCFG_ENOUGHSPACE */
-+ /* | ATC_SRC_H2SEL_HW */
-+ /* | ATC_SRC_PER(AT_DMA_ID_AES_RX); */
-+ >;
-+ dma-name = "tx", "rx";
-+ };
-+
-+ sha@f0014000 {
-+ compatible = "atmel,sam9g46-sha";
-+ reg = <0xf0014000 0x100>;
-+ interrupts = <27 4 0>;
-+ dma = <&dma 0x200060C0>; /* rx cfg = ATC_FIFOCFG_ENOUGHSPACE */
-+ /* | ATC_SRC_H2SEL_HW */
-+ /* | ATC_SRC_PER(AT_DMA_ID_SHA_RX); */
-+ };
- };
-
- nand0: nand@40000000 {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 79aedf981e952379dd4538f85b1c62467eaa84ab Mon Sep 17 00:00:00 2001
-From: Nicolas Royer <nicolas@eukrea.com>
-Date: Mon, 17 Sep 2012 18:26:15 +0200
-Subject: crypto: Atmel AES; add device tree support
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Eric Bénard <eric@eukrea.com>
-Tested-by: Eric Bénard <eric@eukrea.com>
----
- drivers/crypto/atmel-aes.c | 626 +++++++++++++++++++++++------
- include/linux/platform_data/atmel-aes.h | 22 -
- include/linux/platform_data/atmel-crypto.h | 22 +
- 3 files changed, 524 insertions(+), 146 deletions(-)
- delete mode 100644 include/linux/platform_data/atmel-aes.h
- create mode 100644 include/linux/platform_data/atmel-crypto.h
-
-diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
-index 6bb20ff..035b87a 100644
---- a/drivers/crypto/atmel-aes.c
-+++ b/drivers/crypto/atmel-aes.c
-@@ -43,16 +43,19 @@
- #include <crypto/aes.h>
- #include <crypto/hash.h>
- #include <crypto/internal/hash.h>
--#include <linux/platform_data/atmel-aes.h>
-+#include <linux/platform_data/atmel-crypto.h>
- #include "atmel-aes-regs.h"
-
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+
- #define CFB8_BLOCK_SIZE 1
- #define CFB16_BLOCK_SIZE 2
- #define CFB32_BLOCK_SIZE 4
- #define CFB64_BLOCK_SIZE 8
-
- /* AES flags */
--#define AES_FLAGS_MODE_MASK 0x01ff
-+#define AES_FLAGS_MODE_MASK 0x03ff
- #define AES_FLAGS_ENCRYPT BIT(0)
- #define AES_FLAGS_CBC BIT(1)
- #define AES_FLAGS_CFB BIT(2)
-@@ -60,21 +63,26 @@
- #define AES_FLAGS_CFB16 BIT(4)
- #define AES_FLAGS_CFB32 BIT(5)
- #define AES_FLAGS_CFB64 BIT(6)
--#define AES_FLAGS_OFB BIT(7)
--#define AES_FLAGS_CTR BIT(8)
-+#define AES_FLAGS_CFB128 BIT(7)
-+#define AES_FLAGS_OFB BIT(8)
-+#define AES_FLAGS_CTR BIT(9)
-
- #define AES_FLAGS_INIT BIT(16)
- #define AES_FLAGS_DMA BIT(17)
- #define AES_FLAGS_BUSY BIT(18)
-+#define AES_FLAGS_FAST BIT(19)
-
--#define AES_FLAGS_DUALBUFF BIT(24)
--
--#define ATMEL_AES_QUEUE_LENGTH 1
--#define ATMEL_AES_CACHE_SIZE 0
-+#define ATMEL_AES_QUEUE_LENGTH 50
-
- #define ATMEL_AES_DMA_THRESHOLD 16
-
-
-+struct atmel_aes_caps {
-+ bool has_dualbuff;
-+ bool has_cfb64;
-+ u32 max_burst_size;
-+};
-+
- struct atmel_aes_dev;
-
- struct atmel_aes_ctx {
-@@ -82,6 +90,8 @@ struct atmel_aes_ctx {
-
- int keylen;
- u32 key[AES_KEYSIZE_256 / sizeof(u32)];
-+
-+ u16 block_size;
- };
-
- struct atmel_aes_reqctx {
-@@ -117,20 +127,27 @@ struct atmel_aes_dev {
-
- struct scatterlist *in_sg;
- unsigned int nb_in_sg;
--
-+ size_t in_offset;
- struct scatterlist *out_sg;
- unsigned int nb_out_sg;
-+ size_t out_offset;
-
- size_t bufcnt;
-+ size_t buflen;
-+ size_t dma_size;
-
-- u8 buf_in[ATMEL_AES_DMA_THRESHOLD] __aligned(sizeof(u32));
-- int dma_in;
-+ void *buf_in;
-+ int dma_in;
-+ dma_addr_t dma_addr_in;
- struct atmel_aes_dma dma_lch_in;
-
-- u8 buf_out[ATMEL_AES_DMA_THRESHOLD] __aligned(sizeof(u32));
-- int dma_out;
-+ void *buf_out;
-+ int dma_out;
-+ dma_addr_t dma_addr_out;
- struct atmel_aes_dma dma_lch_out;
-
-+ struct atmel_aes_caps caps;
-+
- u32 hw_version;
- };
-
-@@ -170,6 +187,37 @@ static int atmel_aes_sg_length(struct ablkcipher_request *req,
- return sg_nb;
- }
-
-+static int atmel_aes_sg_copy(struct scatterlist **sg, size_t *offset,
-+ void *buf, size_t buflen, size_t total, int out)
-+{
-+ unsigned int count, off = 0;
-+
-+ while (buflen && total) {
-+ count = min((*sg)->length - *offset, total);
-+ count = min(count, buflen);
-+
-+ if (!count)
-+ return off;
-+
-+ scatterwalk_map_and_copy(buf + off, *sg, *offset, count, out);
-+
-+ off += count;
-+ buflen -= count;
-+ *offset += count;
-+ total -= count;
-+
-+ if (*offset == (*sg)->length) {
-+ *sg = sg_next(*sg);
-+ if (*sg)
-+ *offset = 0;
-+ else
-+ total = 0;
-+ }
-+ }
-+
-+ return off;
-+}
-+
- static inline u32 atmel_aes_read(struct atmel_aes_dev *dd, u32 offset)
- {
- return readl_relaxed(dd->io_base + offset);
-@@ -195,14 +243,6 @@ static void atmel_aes_write_n(struct atmel_aes_dev *dd, u32 offset,
- atmel_aes_write(dd, offset, *value);
- }
-
--static void atmel_aes_dualbuff_test(struct atmel_aes_dev *dd)
--{
-- atmel_aes_write(dd, AES_MR, AES_MR_DUALBUFF);
--
-- if (atmel_aes_read(dd, AES_MR) & AES_MR_DUALBUFF)
-- dd->flags |= AES_FLAGS_DUALBUFF;
--}
--
- static struct atmel_aes_dev *atmel_aes_find_dev(struct atmel_aes_ctx *ctx)
- {
- struct atmel_aes_dev *aes_dd = NULL;
-@@ -230,7 +270,6 @@ static int atmel_aes_hw_init(struct atmel_aes_dev *dd)
-
- if (!(dd->flags & AES_FLAGS_INIT)) {
- atmel_aes_write(dd, AES_CR, AES_CR_SWRST);
-- atmel_aes_dualbuff_test(dd);
- dd->flags |= AES_FLAGS_INIT;
- dd->err = 0;
- }
-@@ -238,11 +277,19 @@ static int atmel_aes_hw_init(struct atmel_aes_dev *dd)
- return 0;
- }
-
-+static inline unsigned int atmel_aes_get_version(struct atmel_aes_dev *dd)
-+{
-+ return atmel_aes_read(dd, AES_HW_VERSION) & 0x00000fff;
-+}
-+
- static void atmel_aes_hw_version_init(struct atmel_aes_dev *dd)
- {
- atmel_aes_hw_init(dd);
-
-- dd->hw_version = atmel_aes_read(dd, AES_HW_VERSION);
-+ dd->hw_version = atmel_aes_get_version(dd);
-+
-+ dev_info(dd->dev,
-+ "version: 0x%x\n", dd->hw_version);
-
- clk_disable_unprepare(dd->iclk);
- }
-@@ -265,50 +312,77 @@ static void atmel_aes_dma_callback(void *data)
- tasklet_schedule(&dd->done_task);
- }
-
--static int atmel_aes_crypt_dma(struct atmel_aes_dev *dd)
-+static int atmel_aes_crypt_dma(struct atmel_aes_dev *dd,
-+ dma_addr_t dma_addr_in, dma_addr_t dma_addr_out, int length)
- {
-+ struct scatterlist sg[2];
- struct dma_async_tx_descriptor *in_desc, *out_desc;
-- int nb_dma_sg_in, nb_dma_sg_out;
-
-- dd->nb_in_sg = atmel_aes_sg_length(dd->req, dd->in_sg);
-- if (!dd->nb_in_sg)
-- goto exit_err;
-+ dd->dma_size = length;
-
-- nb_dma_sg_in = dma_map_sg(dd->dev, dd->in_sg, dd->nb_in_sg,
-- DMA_TO_DEVICE);
-- if (!nb_dma_sg_in)
-- goto exit_err;
-+ if (!(dd->flags & AES_FLAGS_FAST)) {
-+ dma_sync_single_for_device(dd->dev, dma_addr_in, length,
-+ DMA_TO_DEVICE);
-+ }
-
-- in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, dd->in_sg,
-- nb_dma_sg_in, DMA_MEM_TO_DEV,
-- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-+ if (dd->flags & AES_FLAGS_CFB8) {
-+ dd->dma_lch_in.dma_conf.dst_addr_width =
-+ DMA_SLAVE_BUSWIDTH_1_BYTE;
-+ dd->dma_lch_out.dma_conf.src_addr_width =
-+ DMA_SLAVE_BUSWIDTH_1_BYTE;
-+ } else if (dd->flags & AES_FLAGS_CFB16) {
-+ dd->dma_lch_in.dma_conf.dst_addr_width =
-+ DMA_SLAVE_BUSWIDTH_2_BYTES;
-+ dd->dma_lch_out.dma_conf.src_addr_width =
-+ DMA_SLAVE_BUSWIDTH_2_BYTES;
-+ } else {
-+ dd->dma_lch_in.dma_conf.dst_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
-+ dd->dma_lch_out.dma_conf.src_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
-+ }
-
-- if (!in_desc)
-- goto unmap_in;
-+ if (dd->flags & (AES_FLAGS_CFB8 | AES_FLAGS_CFB16 |
-+ AES_FLAGS_CFB32 | AES_FLAGS_CFB64)) {
-+ dd->dma_lch_in.dma_conf.src_maxburst = 1;
-+ dd->dma_lch_in.dma_conf.dst_maxburst = 1;
-+ dd->dma_lch_out.dma_conf.src_maxburst = 1;
-+ dd->dma_lch_out.dma_conf.dst_maxburst = 1;
-+ } else {
-+ dd->dma_lch_in.dma_conf.src_maxburst = dd->caps.max_burst_size;
-+ dd->dma_lch_in.dma_conf.dst_maxburst = dd->caps.max_burst_size;
-+ dd->dma_lch_out.dma_conf.src_maxburst = dd->caps.max_burst_size;
-+ dd->dma_lch_out.dma_conf.dst_maxburst = dd->caps.max_burst_size;
-+ }
-
-- /* callback not needed */
-+ dmaengine_slave_config(dd->dma_lch_in.chan, &dd->dma_lch_in.dma_conf);
-+ dmaengine_slave_config(dd->dma_lch_out.chan, &dd->dma_lch_out.dma_conf);
-
-- dd->nb_out_sg = atmel_aes_sg_length(dd->req, dd->out_sg);
-- if (!dd->nb_out_sg)
-- goto unmap_in;
-+ dd->flags |= AES_FLAGS_DMA;
-
-- nb_dma_sg_out = dma_map_sg(dd->dev, dd->out_sg, dd->nb_out_sg,
-- DMA_FROM_DEVICE);
-- if (!nb_dma_sg_out)
-- goto unmap_out;
-+ sg_init_table(&sg[0], 1);
-+ sg_dma_address(&sg[0]) = dma_addr_in;
-+ sg_dma_len(&sg[0]) = length;
-
-- out_desc = dmaengine_prep_slave_sg(dd->dma_lch_out.chan, dd->out_sg,
-- nb_dma_sg_out, DMA_DEV_TO_MEM,
-- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-+ sg_init_table(&sg[1], 1);
-+ sg_dma_address(&sg[1]) = dma_addr_out;
-+ sg_dma_len(&sg[1]) = length;
-
-+ in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, &sg[0],
-+ 1, DMA_MEM_TO_DEV,
-+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-+ if (!in_desc)
-+ return -EINVAL;
-+
-+ out_desc = dmaengine_prep_slave_sg(dd->dma_lch_out.chan, &sg[1],
-+ 1, DMA_DEV_TO_MEM,
-+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!out_desc)
-- goto unmap_out;
-+ return -EINVAL;
-
- out_desc->callback = atmel_aes_dma_callback;
- out_desc->callback_param = dd;
-
-- dd->total -= dd->req->nbytes;
--
- dmaengine_submit(out_desc);
- dma_async_issue_pending(dd->dma_lch_out.chan);
-
-@@ -316,15 +390,6 @@ static int atmel_aes_crypt_dma(struct atmel_aes_dev *dd)
- dma_async_issue_pending(dd->dma_lch_in.chan);
-
- return 0;
--
--unmap_out:
-- dma_unmap_sg(dd->dev, dd->out_sg, dd->nb_out_sg,
-- DMA_FROM_DEVICE);
--unmap_in:
-- dma_unmap_sg(dd->dev, dd->in_sg, dd->nb_in_sg,
-- DMA_TO_DEVICE);
--exit_err:
-- return -EINVAL;
- }
-
- static int atmel_aes_crypt_cpu_start(struct atmel_aes_dev *dd)
-@@ -357,30 +422,66 @@ static int atmel_aes_crypt_cpu_start(struct atmel_aes_dev *dd)
-
- static int atmel_aes_crypt_dma_start(struct atmel_aes_dev *dd)
- {
-- int err;
-+ int err, fast = 0, in, out;
-+ size_t count;
-+ dma_addr_t addr_in, addr_out;
-+
-+ if ((!dd->in_offset) && (!dd->out_offset)) {
-+ /* check for alignment */
-+ in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32)) &&
-+ IS_ALIGNED(dd->in_sg->length, dd->ctx->block_size);
-+ out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32)) &&
-+ IS_ALIGNED(dd->out_sg->length, dd->ctx->block_size);
-+ fast = in && out;
-+
-+ if (sg_dma_len(dd->in_sg) != sg_dma_len(dd->out_sg))
-+ fast = 0;
-+ }
-+
-+
-+ if (fast) {
-+ count = min(dd->total, sg_dma_len(dd->in_sg));
-+ count = min(count, sg_dma_len(dd->out_sg));
-+
-+ err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
-+ if (!err) {
-+ dev_err(dd->dev, "dma_map_sg() error\n");
-+ return -EINVAL;
-+ }
-+
-+ err = dma_map_sg(dd->dev, dd->out_sg, 1,
-+ DMA_FROM_DEVICE);
-+ if (!err) {
-+ dev_err(dd->dev, "dma_map_sg() error\n");
-+ dma_unmap_sg(dd->dev, dd->in_sg, 1,
-+ DMA_TO_DEVICE);
-+ return -EINVAL;
-+ }
-+
-+ addr_in = sg_dma_address(dd->in_sg);
-+ addr_out = sg_dma_address(dd->out_sg);
-+
-+ dd->flags |= AES_FLAGS_FAST;
-
-- if (dd->flags & AES_FLAGS_CFB8) {
-- dd->dma_lch_in.dma_conf.dst_addr_width =
-- DMA_SLAVE_BUSWIDTH_1_BYTE;
-- dd->dma_lch_out.dma_conf.src_addr_width =
-- DMA_SLAVE_BUSWIDTH_1_BYTE;
-- } else if (dd->flags & AES_FLAGS_CFB16) {
-- dd->dma_lch_in.dma_conf.dst_addr_width =
-- DMA_SLAVE_BUSWIDTH_2_BYTES;
-- dd->dma_lch_out.dma_conf.src_addr_width =
-- DMA_SLAVE_BUSWIDTH_2_BYTES;
- } else {
-- dd->dma_lch_in.dma_conf.dst_addr_width =
-- DMA_SLAVE_BUSWIDTH_4_BYTES;
-- dd->dma_lch_out.dma_conf.src_addr_width =
-- DMA_SLAVE_BUSWIDTH_4_BYTES;
-+ /* use cache buffers */
-+ count = atmel_aes_sg_copy(&dd->in_sg, &dd->in_offset,
-+ dd->buf_in, dd->buflen, dd->total, 0);
-+
-+ addr_in = dd->dma_addr_in;
-+ addr_out = dd->dma_addr_out;
-+
-+ dd->flags &= ~AES_FLAGS_FAST;
- }
-
-- dmaengine_slave_config(dd->dma_lch_in.chan, &dd->dma_lch_in.dma_conf);
-- dmaengine_slave_config(dd->dma_lch_out.chan, &dd->dma_lch_out.dma_conf);
-+ dd->total -= count;
-
-- dd->flags |= AES_FLAGS_DMA;
-- err = atmel_aes_crypt_dma(dd);
-+ err = atmel_aes_crypt_dma(dd, addr_in, addr_out, count);
-+
-+ if (err && (dd->flags & AES_FLAGS_FAST)) {
-+ dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
-+ dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
-+ }
-
- return err;
- }
-@@ -415,6 +516,8 @@ static int atmel_aes_write_ctrl(struct atmel_aes_dev *dd)
- valmr |= AES_MR_CFBS_32b;
- else if (dd->flags & AES_FLAGS_CFB64)
- valmr |= AES_MR_CFBS_64b;
-+ else if (dd->flags & AES_FLAGS_CFB128)
-+ valmr |= AES_MR_CFBS_128b;
- } else if (dd->flags & AES_FLAGS_OFB) {
- valmr |= AES_MR_OPMOD_OFB;
- } else if (dd->flags & AES_FLAGS_CTR) {
-@@ -428,7 +531,7 @@ static int atmel_aes_write_ctrl(struct atmel_aes_dev *dd)
-
- if (dd->total > ATMEL_AES_DMA_THRESHOLD) {
- valmr |= AES_MR_SMOD_IDATAR0;
-- if (dd->flags & AES_FLAGS_DUALBUFF)
-+ if (dd->caps.has_dualbuff)
- valmr |= AES_MR_DUALBUFF;
- } else {
- valmr |= AES_MR_SMOD_AUTO;
-@@ -482,7 +585,9 @@ static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
- /* assign new request to device */
- dd->req = req;
- dd->total = req->nbytes;
-+ dd->in_offset = 0;
- dd->in_sg = req->src;
-+ dd->out_offset = 0;
- dd->out_sg = req->dst;
-
- rctx = ablkcipher_request_ctx(req);
-@@ -511,18 +616,86 @@ static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
- static int atmel_aes_crypt_dma_stop(struct atmel_aes_dev *dd)
- {
- int err = -EINVAL;
-+ size_t count;
-
- if (dd->flags & AES_FLAGS_DMA) {
-- dma_unmap_sg(dd->dev, dd->out_sg,
-- dd->nb_out_sg, DMA_FROM_DEVICE);
-- dma_unmap_sg(dd->dev, dd->in_sg,
-- dd->nb_in_sg, DMA_TO_DEVICE);
- err = 0;
-+ if (dd->flags & AES_FLAGS_FAST) {
-+ dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
-+ dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
-+ } else {
-+ dma_sync_single_for_device(dd->dev, dd->dma_addr_out,
-+ dd->dma_size, DMA_FROM_DEVICE);
-+
-+ /* copy data */
-+ count = atmel_aes_sg_copy(&dd->out_sg, &dd->out_offset,
-+ dd->buf_out, dd->buflen, dd->dma_size, 1);
-+ if (count != dd->dma_size) {
-+ err = -EINVAL;
-+ pr_err("not all data converted: %u\n", count);
-+ }
-+ }
-+ }
-+
-+ return err;
-+}
-+
-+
-+static int atmel_aes_buff_init(struct atmel_aes_dev *dd)
-+{
-+ int err = -ENOMEM;
-+
-+ dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, 0);
-+ dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, 0);
-+ dd->buflen = PAGE_SIZE;
-+ dd->buflen &= ~(AES_BLOCK_SIZE - 1);
-+
-+ if (!dd->buf_in || !dd->buf_out) {
-+ dev_err(dd->dev, "unable to alloc pages.\n");
-+ goto err_alloc;
- }
-
-+ /* MAP here */
-+ dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in,
-+ dd->buflen, DMA_TO_DEVICE);
-+ if (dma_mapping_error(dd->dev, dd->dma_addr_in)) {
-+ dev_err(dd->dev, "dma %d bytes error\n", dd->buflen);
-+ err = -EINVAL;
-+ goto err_map_in;
-+ }
-+
-+ dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out,
-+ dd->buflen, DMA_FROM_DEVICE);
-+ if (dma_mapping_error(dd->dev, dd->dma_addr_out)) {
-+ dev_err(dd->dev, "dma %d bytes error\n", dd->buflen);
-+ err = -EINVAL;
-+ goto err_map_out;
-+ }
-+
-+ return 0;
-+
-+err_map_out:
-+ dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen,
-+ DMA_TO_DEVICE);
-+err_map_in:
-+ free_page((unsigned long)dd->buf_out);
-+ free_page((unsigned long)dd->buf_in);
-+err_alloc:
-+ if (err)
-+ pr_err("error: %d\n", err);
- return err;
- }
-
-+static void atmel_aes_buff_cleanup(struct atmel_aes_dev *dd)
-+{
-+ dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
-+ DMA_FROM_DEVICE);
-+ dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen,
-+ DMA_TO_DEVICE);
-+ free_page((unsigned long)dd->buf_out);
-+ free_page((unsigned long)dd->buf_in);
-+}
-+
- static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
- {
- struct atmel_aes_ctx *ctx = crypto_ablkcipher_ctx(
-@@ -530,9 +703,30 @@ static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
- struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req);
- struct atmel_aes_dev *dd;
-
-- if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) {
-- pr_err("request size is not exact amount of AES blocks\n");
-- return -EINVAL;
-+ if (mode & AES_FLAGS_CFB8) {
-+ if (!IS_ALIGNED(req->nbytes, CFB8_BLOCK_SIZE)) {
-+ pr_err("request size is not exact amount of CFB8 blocks\n");
-+ return -EINVAL;
-+ }
-+ ctx->block_size = CFB8_BLOCK_SIZE;
-+ } else if (mode & AES_FLAGS_CFB16) {
-+ if (!IS_ALIGNED(req->nbytes, CFB16_BLOCK_SIZE)) {
-+ pr_err("request size is not exact amount of CFB16 blocks\n");
-+ return -EINVAL;
-+ }
-+ ctx->block_size = CFB16_BLOCK_SIZE;
-+ } else if (mode & AES_FLAGS_CFB32) {
-+ if (!IS_ALIGNED(req->nbytes, CFB32_BLOCK_SIZE)) {
-+ pr_err("request size is not exact amount of CFB32 blocks\n");
-+ return -EINVAL;
-+ }
-+ ctx->block_size = CFB32_BLOCK_SIZE;
-+ } else {
-+ if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) {
-+ pr_err("request size is not exact amount of AES blocks\n");
-+ return -EINVAL;
-+ }
-+ ctx->block_size = AES_BLOCK_SIZE;
- }
-
- dd = atmel_aes_find_dev(ctx);
-@@ -556,14 +750,12 @@ static bool atmel_aes_filter(struct dma_chan *chan, void *slave)
- }
- }
-
--static int atmel_aes_dma_init(struct atmel_aes_dev *dd)
-+static int atmel_aes_dma_init(struct atmel_aes_dev *dd,
-+ struct crypto_platform_data *pdata)
- {
- int err = -ENOMEM;
-- struct aes_platform_data *pdata;
- dma_cap_mask_t mask_in, mask_out;
-
-- pdata = dd->dev->platform_data;
--
- if (pdata && pdata->dma_slave->txdata.dma_dev &&
- pdata->dma_slave->rxdata.dma_dev) {
-
-@@ -573,28 +765,38 @@ static int atmel_aes_dma_init(struct atmel_aes_dev *dd)
-
- dd->dma_lch_in.chan = dma_request_channel(mask_in,
- atmel_aes_filter, &pdata->dma_slave->rxdata);
-+
- if (!dd->dma_lch_in.chan)
- goto err_dma_in;
-
- dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV;
- dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base +
- AES_IDATAR(0);
-- dd->dma_lch_in.dma_conf.src_maxburst = 1;
-- dd->dma_lch_in.dma_conf.dst_maxburst = 1;
-+ dd->dma_lch_in.dma_conf.src_maxburst = dd->caps.max_burst_size;
-+ dd->dma_lch_in.dma_conf.src_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
-+ dd->dma_lch_in.dma_conf.dst_maxburst = dd->caps.max_burst_size;
-+ dd->dma_lch_in.dma_conf.dst_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
- dd->dma_lch_in.dma_conf.device_fc = false;
-
- dma_cap_zero(mask_out);
- dma_cap_set(DMA_SLAVE, mask_out);
- dd->dma_lch_out.chan = dma_request_channel(mask_out,
- atmel_aes_filter, &pdata->dma_slave->txdata);
-+
- if (!dd->dma_lch_out.chan)
- goto err_dma_out;
-
- dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM;
- dd->dma_lch_out.dma_conf.src_addr = dd->phys_base +
- AES_ODATAR(0);
-- dd->dma_lch_out.dma_conf.src_maxburst = 1;
-- dd->dma_lch_out.dma_conf.dst_maxburst = 1;
-+ dd->dma_lch_out.dma_conf.src_maxburst = dd->caps.max_burst_size;
-+ dd->dma_lch_out.dma_conf.src_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
-+ dd->dma_lch_out.dma_conf.dst_maxburst = dd->caps.max_burst_size;
-+ dd->dma_lch_out.dma_conf.dst_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
- dd->dma_lch_out.dma_conf.device_fc = false;
-
- return 0;
-@@ -670,13 +872,13 @@ static int atmel_aes_ofb_decrypt(struct ablkcipher_request *req)
- static int atmel_aes_cfb_encrypt(struct ablkcipher_request *req)
- {
- return atmel_aes_crypt(req,
-- AES_FLAGS_ENCRYPT | AES_FLAGS_CFB);
-+ AES_FLAGS_ENCRYPT | AES_FLAGS_CFB | AES_FLAGS_CFB128);
- }
-
- static int atmel_aes_cfb_decrypt(struct ablkcipher_request *req)
- {
- return atmel_aes_crypt(req,
-- AES_FLAGS_CFB);
-+ AES_FLAGS_CFB | AES_FLAGS_CFB128);
- }
-
- static int atmel_aes_cfb64_encrypt(struct ablkcipher_request *req)
-@@ -758,7 +960,7 @@ static struct crypto_alg aes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-- .cra_alignmask = 0x0,
-+ .cra_alignmask = 0xf,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_aes_cra_init,
-@@ -778,7 +980,7 @@ static struct crypto_alg aes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-- .cra_alignmask = 0x0,
-+ .cra_alignmask = 0xf,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_aes_cra_init,
-@@ -799,7 +1001,7 @@ static struct crypto_alg aes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-- .cra_alignmask = 0x0,
-+ .cra_alignmask = 0xf,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_aes_cra_init,
-@@ -820,7 +1022,7 @@ static struct crypto_alg aes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-- .cra_alignmask = 0x0,
-+ .cra_alignmask = 0xf,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_aes_cra_init,
-@@ -841,7 +1043,7 @@ static struct crypto_alg aes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = CFB32_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-- .cra_alignmask = 0x0,
-+ .cra_alignmask = 0x3,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_aes_cra_init,
-@@ -862,7 +1064,7 @@ static struct crypto_alg aes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = CFB16_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-- .cra_alignmask = 0x0,
-+ .cra_alignmask = 0x1,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_aes_cra_init,
-@@ -904,7 +1106,7 @@ static struct crypto_alg aes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-- .cra_alignmask = 0x0,
-+ .cra_alignmask = 0xf,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_aes_cra_init,
-@@ -920,15 +1122,14 @@ static struct crypto_alg aes_algs[] = {
- },
- };
-
--static struct crypto_alg aes_cfb64_alg[] = {
--{
-+static struct crypto_alg aes_cfb64_alg = {
- .cra_name = "cfb64(aes)",
- .cra_driver_name = "atmel-cfb64-aes",
- .cra_priority = 100,
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = CFB64_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_aes_ctx),
-- .cra_alignmask = 0x0,
-+ .cra_alignmask = 0x7,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_aes_cra_init,
-@@ -941,7 +1142,6 @@ static struct crypto_alg aes_cfb64_alg[] = {
- .encrypt = atmel_aes_cfb64_encrypt,
- .decrypt = atmel_aes_cfb64_decrypt,
- }
--},
- };
-
- static void atmel_aes_queue_task(unsigned long data)
-@@ -974,7 +1174,14 @@ static void atmel_aes_done_task(unsigned long data)
- err = dd->err ? : err;
-
- if (dd->total && !err) {
-- err = atmel_aes_crypt_dma_start(dd);
-+ if (dd->flags & AES_FLAGS_FAST) {
-+ dd->in_sg = sg_next(dd->in_sg);
-+ dd->out_sg = sg_next(dd->out_sg);
-+ if (!dd->in_sg || !dd->out_sg)
-+ err = -EINVAL;
-+ }
-+ if (!err)
-+ err = atmel_aes_crypt_dma_start(dd);
- if (!err)
- return; /* DMA started. Not fininishing. */
- }
-@@ -1008,8 +1215,8 @@ static void atmel_aes_unregister_algs(struct atmel_aes_dev *dd)
-
- for (i = 0; i < ARRAY_SIZE(aes_algs); i++)
- crypto_unregister_alg(&aes_algs[i]);
-- if (dd->hw_version >= 0x130)
-- crypto_unregister_alg(&aes_cfb64_alg[0]);
-+ if (dd->caps.has_cfb64)
-+ crypto_unregister_alg(&aes_cfb64_alg);
- }
-
- static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
-@@ -1023,11 +1230,9 @@ static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
- goto err_aes_algs;
- }
-
-- atmel_aes_hw_version_init(dd);
--
-- if (dd->hw_version >= 0x130) {
-- INIT_LIST_HEAD(&aes_cfb64_alg[0].cra_list);
-- err = crypto_register_alg(&aes_cfb64_alg[0]);
-+ if (dd->caps.has_cfb64) {
-+ INIT_LIST_HEAD(&aes_cfb64_alg.cra_list);
-+ err = crypto_register_alg(&aes_cfb64_alg);
- if (err)
- goto err_aes_cfb64_alg;
- }
-@@ -1043,10 +1248,158 @@ err_aes_algs:
- return err;
- }
-
-+
-+#ifdef CONFIG_OF
-+static const struct of_device_id atmel_aes_dt_ids[] = {
-+ { .compatible = "atmel,sam9g46-aes" },
-+ { /* sentinel */ }
-+};
-+
-+MODULE_DEVICE_TABLE(of, atmel_aes_dt_ids);
-+
-+static int atmel_aes_dma_of_init(struct device_node *np,
-+ struct at_dma_slave *atslave, const char *name)
-+{
-+ struct of_phandle_args dma_spec;
-+ struct device_node *dmac_np;
-+ struct platform_device *dmac_pdev;
-+ const __be32 *nbcells;
-+ int ret;
-+ int index;
-+
-+ index = of_property_match_string(np, "dma-name", name);
-+ if (index < 0) {
-+ pr_err("%s: dma-name property is required\n", np->full_name);
-+ ret = -EINVAL;
-+ goto err0;
-+ }
-+
-+ ret = of_parse_phandle_with_args(np, "dma", "#dma-cells",
-+ index, &dma_spec);
-+ if (ret || !dma_spec.np) {
-+ pr_err("%s: can't parse dma property (%d)\n",
-+ np->full_name, ret);
-+ goto err0;
-+ }
-+ dmac_np = dma_spec.np;
-+
-+ /* check property format */
-+ nbcells = of_get_property(dmac_np, "#dma-cells", NULL);
-+ if (!nbcells) {
-+ pr_err("%s: #dma-cells property is required\n", np->full_name);
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ if (dma_spec.args_count != be32_to_cpup(nbcells)
-+ || dma_spec.args_count != 1) {
-+ pr_err("%s: wrong #dma-cells for %s\n",
-+ np->full_name, dmac_np->full_name);
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ /* retreive DMA controller information */
-+ dmac_pdev = of_find_device_by_node(dmac_np);
-+ if (!dmac_pdev) {
-+ pr_err("%s: unable to find pdev from DMA controller\n",
-+ dmac_np->full_name);
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ /* now fill in the at_dma_slave structure */
-+ atslave->dma_dev = &dmac_pdev->dev;
-+ atslave->cfg = dma_spec.args[0];
-+
-+err1:
-+ of_node_put(dma_spec.np);
-+err0:
-+ pr_debug("%s exited with status %d\n", __func__, ret);
-+ return ret;
-+}
-+
-+static struct crypto_platform_data __devinit*
-+atmel_aes_of_init(struct platform_device *pdev)
-+{
-+ struct device_node *np = pdev->dev.of_node;
-+ struct crypto_platform_data *pdata;
-+ struct at_dma_slave *atslave;
-+
-+ if (!np) {
-+ dev_err(&pdev->dev, "device node not found\n");
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-+ if (!pdata) {
-+ dev_err(&pdev->dev, "could not allocate memory for pdata\n");
-+ return ERR_PTR(-ENOMEM);
-+ }
-+
-+ pdata->dma_slave = devm_kzalloc(&pdev->dev,
-+ sizeof(*(pdata->dma_slave)),
-+ GFP_KERNEL);
-+ if (!pdata->dma_slave) {
-+ dev_err(&pdev->dev, "could not allocate memory for dma_slave\n");
-+ devm_kfree(&pdev->dev, pdata);
-+ return ERR_PTR(-ENOMEM);
-+ }
-+
-+ atslave = &pdata->dma_slave->txdata;
-+ /* retrieve TX DMA configuration first */
-+ if (atmel_aes_dma_of_init(np, atslave, "tx")) {
-+ dev_err(&pdev->dev, "could not find TX DMA parameters\n");
-+ devm_kfree(&pdev->dev, pdata->dma_slave);
-+ devm_kfree(&pdev->dev, pdata);
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ atslave = &pdata->dma_slave->rxdata;
-+ /* retrieve RX DMA configuration first */
-+ if (atmel_aes_dma_of_init(np, atslave, "rx")) {
-+ dev_err(&pdev->dev, "could not find RX DMA parameters\n");
-+ devm_kfree(&pdev->dev, pdata->dma_slave);
-+ devm_kfree(&pdev->dev, pdata);
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ return pdata;
-+}
-+#else /* CONFIG_OF */
-+static inline struct crypto_platform_data*
-+atmel_aes_of_init(struct platform_device *dev)
-+{
-+ return ERR_PTR(-EINVAL);
-+}
-+#endif
-+
-+static void atmel_aes_get_cap(struct atmel_aes_dev *dd)
-+{
-+ dd->caps.has_dualbuff = 0;
-+ dd->caps.has_cfb64 = 0;
-+ dd->caps.max_burst_size = 1;
-+
-+ /* keep only major version number */
-+ switch (dd->hw_version & 0xff0) {
-+ case 0x130:
-+ dd->caps.has_dualbuff = 1;
-+ dd->caps.has_cfb64 = 1;
-+ dd->caps.max_burst_size = 4;
-+ break;
-+ case 0x120:
-+ break;
-+ default:
-+ dev_warn(dd->dev,
-+ "Unmanaged aes version, set minimum capabilities\n");
-+ break;
-+ }
-+}
-+
- static int __devinit atmel_aes_probe(struct platform_device *pdev)
- {
- struct atmel_aes_dev *aes_dd;
-- struct aes_platform_data *pdata;
-+ struct crypto_platform_data *pdata;
- struct device *dev = &pdev->dev;
- struct resource *aes_res;
- unsigned long aes_phys_size;
-@@ -1054,8 +1407,11 @@ static int __devinit atmel_aes_probe(struct platform_device *pdev)
-
- pdata = pdev->dev.platform_data;
- if (!pdata) {
-- err = -ENXIO;
-- goto aes_dd_err;
-+ pdata = atmel_aes_of_init(pdev);
-+ if (IS_ERR(pdata)) {
-+ dev_err(&pdev->dev, "platform data not available\n");
-+ return PTR_ERR(pdata);
-+ }
- }
-
- aes_dd = kzalloc(sizeof(struct atmel_aes_dev), GFP_KERNEL);
-@@ -1106,7 +1462,7 @@ static int __devinit atmel_aes_probe(struct platform_device *pdev)
- }
-
- /* Initializing the clock */
-- aes_dd->iclk = clk_get(&pdev->dev, NULL);
-+ aes_dd->iclk = clk_get(&pdev->dev, "aes_clk");
- if (IS_ERR(aes_dd->iclk)) {
- dev_err(dev, "clock intialization failed.\n");
- err = PTR_ERR(aes_dd->iclk);
-@@ -1120,7 +1476,15 @@ static int __devinit atmel_aes_probe(struct platform_device *pdev)
- goto aes_io_err;
- }
-
-- err = atmel_aes_dma_init(aes_dd);
-+ atmel_aes_hw_version_init(aes_dd);
-+
-+ atmel_aes_get_cap(aes_dd);
-+
-+ err = atmel_aes_buff_init(aes_dd);
-+ if (err)
-+ goto err_aes_buff;
-+
-+ err = atmel_aes_dma_init(aes_dd, pdata);
- if (err)
- goto err_aes_dma;
-
-@@ -1142,6 +1506,8 @@ err_algs:
- spin_unlock(&atmel_aes.lock);
- atmel_aes_dma_cleanup(aes_dd);
- err_aes_dma:
-+ atmel_aes_buff_cleanup(aes_dd);
-+err_aes_buff:
- iounmap(aes_dd->io_base);
- aes_io_err:
- clk_put(aes_dd->iclk);
-@@ -1191,15 +1557,27 @@ static int __devexit atmel_aes_remove(struct platform_device *pdev)
- }
-
- static struct platform_driver atmel_aes_driver = {
-- .probe = atmel_aes_probe,
- .remove = __devexit_p(atmel_aes_remove),
- .driver = {
- .name = "atmel_aes",
-- .owner = THIS_MODULE,
-+ .owner = THIS_MODULE,
-+ .of_match_table = of_match_ptr(atmel_aes_dt_ids),
- },
- };
-
--module_platform_driver(atmel_aes_driver);
-+static int __init atmel_aes_init(void)
-+{
-+ return platform_driver_probe(&atmel_aes_driver, atmel_aes_probe);
-+}
-+
-+static void __exit atmel_aes_exit(void)
-+{
-+ platform_driver_unregister(&atmel_aes_driver);
-+}
-+
-+late_initcall(atmel_aes_init); /* try to load after dma driver when built-in */
-+module_exit(atmel_aes_exit);
-+
-
- MODULE_DESCRIPTION("Atmel AES hw acceleration support.");
- MODULE_LICENSE("GPL v2");
-diff --git a/include/linux/platform_data/atmel-aes.h b/include/linux/platform_data/atmel-aes.h
-deleted file mode 100644
-index e7a1949..0000000
---- a/include/linux/platform_data/atmel-aes.h
-+++ /dev/null
-@@ -1,22 +0,0 @@
--#ifndef __LINUX_ATMEL_AES_H
--#define __LINUX_ATMEL_AES_H
--
--#include <mach/at_hdmac.h>
--
--/**
-- * struct aes_dma_data - DMA data for AES
-- */
--struct aes_dma_data {
-- struct at_dma_slave txdata;
-- struct at_dma_slave rxdata;
--};
--
--/**
-- * struct aes_platform_data - board-specific AES configuration
-- * @dma_slave: DMA slave interface to use in data transfers.
-- */
--struct aes_platform_data {
-- struct aes_dma_data *dma_slave;
--};
--
--#endif /* __LINUX_ATMEL_AES_H */
-diff --git a/include/linux/platform_data/atmel-crypto.h b/include/linux/platform_data/atmel-crypto.h
-new file mode 100644
-index 0000000..eddfca7
---- /dev/null
-+++ b/include/linux/platform_data/atmel-crypto.h
-@@ -0,0 +1,22 @@
-+#ifndef __LINUX_ATMEL_CRYPTO_H
-+#define __LINUX_ATMEL_CRYPTO_H
-+
-+#include <mach/at_hdmac.h>
-+
-+/**
-+ * struct crypto_dma_data - DMA data for AES/TDES/SHA
-+ */
-+struct crypto_dma_data {
-+ struct at_dma_slave txdata;
-+ struct at_dma_slave rxdata;
-+};
-+
-+/**
-+ * struct tdes_platform_data - board-specific AES/TDES/SHA configuration
-+ * @dma_slave: DMA slave interface to use in data transfers.
-+ */
-+struct crypto_platform_data {
-+ struct crypto_dma_data *dma_slave;
-+};
-+
-+#endif /* __LINUX_ATMEL_CRYPTO_H */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 0de4fb161bfb4a5bdf3deec1d94015435f428e88 Mon Sep 17 00:00:00 2001
-From: Nicolas Royer <nicolas@eukrea.com>
-Date: Mon, 17 Sep 2012 18:26:16 +0200
-Subject: crypto: Atmel TDES; add device tree support
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Eric Bénard <eric@eukrea.com>
-Tested-by: Eric Bénard <eric@eukrea.com>
----
- drivers/crypto/atmel-tdes-regs.h | 2 +
- drivers/crypto/atmel-tdes.c | 541 +++++++++++++++++++++++++++++++++++----
- 2 files changed, 487 insertions(+), 56 deletions(-)
-
-diff --git a/drivers/crypto/atmel-tdes-regs.h b/drivers/crypto/atmel-tdes-regs.h
-index 5ac2a90..f86734d 100644
---- a/drivers/crypto/atmel-tdes-regs.h
-+++ b/drivers/crypto/atmel-tdes-regs.h
-@@ -69,6 +69,8 @@
- #define TDES_XTEARNDR_XTEA_RNDS_MASK (0x3F << 0)
- #define TDES_XTEARNDR_XTEA_RNDS_OFFSET 0
-
-+#define TDES_HW_VERSION 0xFC
-+
- #define TDES_RPR 0x100
- #define TDES_RCR 0x104
- #define TDES_TPR 0x108
-diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c
-index eb2b61e..9de10bd 100644
---- a/drivers/crypto/atmel-tdes.c
-+++ b/drivers/crypto/atmel-tdes.c
-@@ -43,29 +43,37 @@
- #include <crypto/des.h>
- #include <crypto/hash.h>
- #include <crypto/internal/hash.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_data/atmel-crypto.h>
- #include "atmel-tdes-regs.h"
-
- /* TDES flags */
--#define TDES_FLAGS_MODE_MASK 0x007f
-+#define TDES_FLAGS_MODE_MASK 0x00ff
- #define TDES_FLAGS_ENCRYPT BIT(0)
- #define TDES_FLAGS_CBC BIT(1)
- #define TDES_FLAGS_CFB BIT(2)
- #define TDES_FLAGS_CFB8 BIT(3)
- #define TDES_FLAGS_CFB16 BIT(4)
- #define TDES_FLAGS_CFB32 BIT(5)
--#define TDES_FLAGS_OFB BIT(6)
-+#define TDES_FLAGS_CFB64 BIT(6)
-+#define TDES_FLAGS_OFB BIT(7)
-
- #define TDES_FLAGS_INIT BIT(16)
- #define TDES_FLAGS_FAST BIT(17)
- #define TDES_FLAGS_BUSY BIT(18)
-+#define TDES_FLAGS_DMA BIT(19)
-
--#define ATMEL_TDES_QUEUE_LENGTH 1
-+#define ATMEL_TDES_QUEUE_LENGTH 50
-
- #define CFB8_BLOCK_SIZE 1
- #define CFB16_BLOCK_SIZE 2
- #define CFB32_BLOCK_SIZE 4
--#define CFB64_BLOCK_SIZE 8
-
-+struct atmel_tdes_caps {
-+ bool has_dma;
-+ u32 has_cfb_3keys;
-+};
-
- struct atmel_tdes_dev;
-
-@@ -75,12 +83,19 @@ struct atmel_tdes_ctx {
- int keylen;
- u32 key[3*DES_KEY_SIZE / sizeof(u32)];
- unsigned long flags;
-+
-+ u16 block_size;
- };
-
- struct atmel_tdes_reqctx {
- unsigned long mode;
- };
-
-+struct atmel_tdes_dma {
-+ struct dma_chan *chan;
-+ struct dma_slave_config dma_conf;
-+};
-+
- struct atmel_tdes_dev {
- struct list_head list;
- unsigned long phys_base;
-@@ -104,8 +119,10 @@ struct atmel_tdes_dev {
- size_t total;
-
- struct scatterlist *in_sg;
-+ unsigned int nb_in_sg;
- size_t in_offset;
- struct scatterlist *out_sg;
-+ unsigned int nb_out_sg;
- size_t out_offset;
-
- size_t buflen;
-@@ -114,10 +131,16 @@ struct atmel_tdes_dev {
- void *buf_in;
- int dma_in;
- dma_addr_t dma_addr_in;
-+ struct atmel_tdes_dma dma_lch_in;
-
- void *buf_out;
- int dma_out;
- dma_addr_t dma_addr_out;
-+ struct atmel_tdes_dma dma_lch_out;
-+
-+ struct atmel_tdes_caps caps;
-+
-+ u32 hw_version;
- };
-
- struct atmel_tdes_drv {
-@@ -212,6 +235,31 @@ static int atmel_tdes_hw_init(struct atmel_tdes_dev *dd)
- return 0;
- }
-
-+static inline unsigned int atmel_tdes_get_version(struct atmel_tdes_dev *dd)
-+{
-+ return atmel_tdes_read(dd, TDES_HW_VERSION) & 0x00000fff;
-+}
-+
-+static void atmel_tdes_hw_version_init(struct atmel_tdes_dev *dd)
-+{
-+ atmel_tdes_hw_init(dd);
-+
-+ dd->hw_version = atmel_tdes_get_version(dd);
-+
-+ dev_info(dd->dev,
-+ "version: 0x%x\n", dd->hw_version);
-+
-+ clk_disable_unprepare(dd->iclk);
-+}
-+
-+static void atmel_tdes_dma_callback(void *data)
-+{
-+ struct atmel_tdes_dev *dd = data;
-+
-+ /* dma_lch_out - completed */
-+ tasklet_schedule(&dd->done_task);
-+}
-+
- static int atmel_tdes_write_ctrl(struct atmel_tdes_dev *dd)
- {
- int err;
-@@ -222,7 +270,9 @@ static int atmel_tdes_write_ctrl(struct atmel_tdes_dev *dd)
- if (err)
- return err;
-
-- atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS);
-+ if (!dd->caps.has_dma)
-+ atmel_tdes_write(dd, TDES_PTCR,
-+ TDES_PTCR_TXTDIS | TDES_PTCR_RXTDIS);
-
- /* MR register must be set before IV registers */
- if (dd->ctx->keylen > (DES_KEY_SIZE << 1)) {
-@@ -246,6 +296,8 @@ static int atmel_tdes_write_ctrl(struct atmel_tdes_dev *dd)
- valmr |= TDES_MR_CFBS_16b;
- else if (dd->flags & TDES_FLAGS_CFB32)
- valmr |= TDES_MR_CFBS_32b;
-+ else if (dd->flags & TDES_FLAGS_CFB64)
-+ valmr |= TDES_MR_CFBS_64b;
- } else if (dd->flags & TDES_FLAGS_OFB) {
- valmr |= TDES_MR_OPMOD_OFB;
- }
-@@ -267,7 +319,7 @@ static int atmel_tdes_write_ctrl(struct atmel_tdes_dev *dd)
- return 0;
- }
-
--static int atmel_tdes_crypt_dma_stop(struct atmel_tdes_dev *dd)
-+static int atmel_tdes_crypt_pdc_stop(struct atmel_tdes_dev *dd)
- {
- int err = 0;
- size_t count;
-@@ -293,7 +345,7 @@ static int atmel_tdes_crypt_dma_stop(struct atmel_tdes_dev *dd)
- return err;
- }
-
--static int atmel_tdes_dma_init(struct atmel_tdes_dev *dd)
-+static int atmel_tdes_buff_init(struct atmel_tdes_dev *dd)
- {
- int err = -ENOMEM;
-
-@@ -338,7 +390,7 @@ err_alloc:
- return err;
- }
-
--static void atmel_tdes_dma_cleanup(struct atmel_tdes_dev *dd)
-+static void atmel_tdes_buff_cleanup(struct atmel_tdes_dev *dd)
- {
- dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
- DMA_FROM_DEVICE);
-@@ -348,7 +400,7 @@ static void atmel_tdes_dma_cleanup(struct atmel_tdes_dev *dd)
- free_page((unsigned long)dd->buf_in);
- }
-
--static int atmel_tdes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
-+static int atmel_tdes_crypt_pdc(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
- dma_addr_t dma_addr_out, int length)
- {
- struct atmel_tdes_ctx *ctx = crypto_tfm_ctx(tfm);
-@@ -384,7 +436,76 @@ static int atmel_tdes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
- return 0;
- }
-
--static int atmel_tdes_crypt_dma_start(struct atmel_tdes_dev *dd)
-+static int atmel_tdes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
-+ dma_addr_t dma_addr_out, int length)
-+{
-+ struct atmel_tdes_ctx *ctx = crypto_tfm_ctx(tfm);
-+ struct atmel_tdes_dev *dd = ctx->dd;
-+ struct scatterlist sg[2];
-+ struct dma_async_tx_descriptor *in_desc, *out_desc;
-+
-+ dd->dma_size = length;
-+
-+ if (!(dd->flags & TDES_FLAGS_FAST)) {
-+ dma_sync_single_for_device(dd->dev, dma_addr_in, length,
-+ DMA_TO_DEVICE);
-+ }
-+
-+ if (dd->flags & TDES_FLAGS_CFB8) {
-+ dd->dma_lch_in.dma_conf.dst_addr_width =
-+ DMA_SLAVE_BUSWIDTH_1_BYTE;
-+ dd->dma_lch_out.dma_conf.src_addr_width =
-+ DMA_SLAVE_BUSWIDTH_1_BYTE;
-+ } else if (dd->flags & TDES_FLAGS_CFB16) {
-+ dd->dma_lch_in.dma_conf.dst_addr_width =
-+ DMA_SLAVE_BUSWIDTH_2_BYTES;
-+ dd->dma_lch_out.dma_conf.src_addr_width =
-+ DMA_SLAVE_BUSWIDTH_2_BYTES;
-+ } else {
-+ dd->dma_lch_in.dma_conf.dst_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
-+ dd->dma_lch_out.dma_conf.src_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
-+ }
-+
-+ dmaengine_slave_config(dd->dma_lch_in.chan, &dd->dma_lch_in.dma_conf);
-+ dmaengine_slave_config(dd->dma_lch_out.chan, &dd->dma_lch_out.dma_conf);
-+
-+ dd->flags |= TDES_FLAGS_DMA;
-+
-+ sg_init_table(&sg[0], 1);
-+ sg_dma_address(&sg[0]) = dma_addr_in;
-+ sg_dma_len(&sg[0]) = length;
-+
-+ sg_init_table(&sg[1], 1);
-+ sg_dma_address(&sg[1]) = dma_addr_out;
-+ sg_dma_len(&sg[1]) = length;
-+
-+ in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, &sg[0],
-+ 1, DMA_MEM_TO_DEV,
-+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-+ if (!in_desc)
-+ return -EINVAL;
-+
-+ out_desc = dmaengine_prep_slave_sg(dd->dma_lch_out.chan, &sg[1],
-+ 1, DMA_DEV_TO_MEM,
-+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-+ if (!out_desc)
-+ return -EINVAL;
-+
-+ out_desc->callback = atmel_tdes_dma_callback;
-+ out_desc->callback_param = dd;
-+
-+ dmaengine_submit(out_desc);
-+ dma_async_issue_pending(dd->dma_lch_out.chan);
-+
-+ dmaengine_submit(in_desc);
-+ dma_async_issue_pending(dd->dma_lch_in.chan);
-+
-+ return 0;
-+}
-+
-+static int atmel_tdes_crypt_start(struct atmel_tdes_dev *dd)
- {
- struct crypto_tfm *tfm = crypto_ablkcipher_tfm(
- crypto_ablkcipher_reqtfm(dd->req));
-@@ -392,23 +513,23 @@ static int atmel_tdes_crypt_dma_start(struct atmel_tdes_dev *dd)
- size_t count;
- dma_addr_t addr_in, addr_out;
-
-- if (sg_is_last(dd->in_sg) && sg_is_last(dd->out_sg)) {
-+ if ((!dd->in_offset) && (!dd->out_offset)) {
- /* check for alignment */
-- in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32));
-- out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32));
--
-+ in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32)) &&
-+ IS_ALIGNED(dd->in_sg->length, dd->ctx->block_size);
-+ out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32)) &&
-+ IS_ALIGNED(dd->out_sg->length, dd->ctx->block_size);
- fast = in && out;
-+
-+ if (sg_dma_len(dd->in_sg) != sg_dma_len(dd->out_sg))
-+ fast = 0;
- }
-
-+
- if (fast) {
- count = min(dd->total, sg_dma_len(dd->in_sg));
- count = min(count, sg_dma_len(dd->out_sg));
-
-- if (count != dd->total) {
-- pr_err("request length != buffer length\n");
-- return -EINVAL;
-- }
--
- err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
- if (!err) {
- dev_err(dd->dev, "dma_map_sg() error\n");
-@@ -438,13 +559,16 @@ static int atmel_tdes_crypt_dma_start(struct atmel_tdes_dev *dd)
- addr_out = dd->dma_addr_out;
-
- dd->flags &= ~TDES_FLAGS_FAST;
--
- }
-
- dd->total -= count;
-
-- err = atmel_tdes_crypt_dma(tfm, addr_in, addr_out, count);
-- if (err) {
-+ if (dd->caps.has_dma)
-+ err = atmel_tdes_crypt_dma(tfm, addr_in, addr_out, count);
-+ else
-+ err = atmel_tdes_crypt_pdc(tfm, addr_in, addr_out, count);
-+
-+ if (err && (dd->flags & TDES_FLAGS_FAST)) {
- dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
- dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
- }
-@@ -452,7 +576,6 @@ static int atmel_tdes_crypt_dma_start(struct atmel_tdes_dev *dd)
- return err;
- }
-
--
- static void atmel_tdes_finish_req(struct atmel_tdes_dev *dd, int err)
- {
- struct ablkcipher_request *req = dd->req;
-@@ -511,7 +634,7 @@ static int atmel_tdes_handle_queue(struct atmel_tdes_dev *dd,
-
- err = atmel_tdes_write_ctrl(dd);
- if (!err)
-- err = atmel_tdes_crypt_dma_start(dd);
-+ err = atmel_tdes_crypt_start(dd);
- if (err) {
- /* des_task will not finish it, so do it here */
- atmel_tdes_finish_req(dd, err);
-@@ -521,41 +644,145 @@ static int atmel_tdes_handle_queue(struct atmel_tdes_dev *dd,
- return ret;
- }
-
-+static int atmel_tdes_crypt_dma_stop(struct atmel_tdes_dev *dd)
-+{
-+ int err = -EINVAL;
-+ size_t count;
-+
-+ if (dd->flags & TDES_FLAGS_DMA) {
-+ err = 0;
-+ if (dd->flags & TDES_FLAGS_FAST) {
-+ dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
-+ dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
-+ } else {
-+ dma_sync_single_for_device(dd->dev, dd->dma_addr_out,
-+ dd->dma_size, DMA_FROM_DEVICE);
-+
-+ /* copy data */
-+ count = atmel_tdes_sg_copy(&dd->out_sg, &dd->out_offset,
-+ dd->buf_out, dd->buflen, dd->dma_size, 1);
-+ if (count != dd->dma_size) {
-+ err = -EINVAL;
-+ pr_err("not all data converted: %u\n", count);
-+ }
-+ }
-+ }
-+ return err;
-+}
-
- static int atmel_tdes_crypt(struct ablkcipher_request *req, unsigned long mode)
- {
- struct atmel_tdes_ctx *ctx = crypto_ablkcipher_ctx(
- crypto_ablkcipher_reqtfm(req));
- struct atmel_tdes_reqctx *rctx = ablkcipher_request_ctx(req);
-- struct atmel_tdes_dev *dd;
-
- if (mode & TDES_FLAGS_CFB8) {
- if (!IS_ALIGNED(req->nbytes, CFB8_BLOCK_SIZE)) {
- pr_err("request size is not exact amount of CFB8 blocks\n");
- return -EINVAL;
- }
-+ ctx->block_size = CFB8_BLOCK_SIZE;
- } else if (mode & TDES_FLAGS_CFB16) {
- if (!IS_ALIGNED(req->nbytes, CFB16_BLOCK_SIZE)) {
- pr_err("request size is not exact amount of CFB16 blocks\n");
- return -EINVAL;
- }
-+ ctx->block_size = CFB16_BLOCK_SIZE;
- } else if (mode & TDES_FLAGS_CFB32) {
- if (!IS_ALIGNED(req->nbytes, CFB32_BLOCK_SIZE)) {
- pr_err("request size is not exact amount of CFB32 blocks\n");
- return -EINVAL;
- }
-- } else if (!IS_ALIGNED(req->nbytes, DES_BLOCK_SIZE)) {
-- pr_err("request size is not exact amount of DES blocks\n");
-- return -EINVAL;
-+ ctx->block_size = CFB32_BLOCK_SIZE;
-+ } else {
-+ if (!IS_ALIGNED(req->nbytes, DES_BLOCK_SIZE)) {
-+ pr_err("request size is not exact amount of DES blocks\n");
-+ return -EINVAL;
-+ }
-+ ctx->block_size = DES_BLOCK_SIZE;
- }
-
-- dd = atmel_tdes_find_dev(ctx);
-- if (!dd)
-+ rctx->mode = mode;
-+
-+ return atmel_tdes_handle_queue(ctx->dd, req);
-+}
-+
-+static bool atmel_tdes_filter(struct dma_chan *chan, void *slave)
-+{
-+ struct at_dma_slave *sl = slave;
-+
-+ if (sl && sl->dma_dev == chan->device->dev) {
-+ chan->private = sl;
-+ return true;
-+ } else {
-+ return false;
-+ }
-+}
-+
-+static int atmel_tdes_dma_init(struct atmel_tdes_dev *dd,
-+ struct crypto_platform_data *pdata)
-+{
-+ int err = -ENOMEM;
-+ dma_cap_mask_t mask_in, mask_out;
-+
-+ if (pdata && pdata->dma_slave->txdata.dma_dev &&
-+ pdata->dma_slave->rxdata.dma_dev) {
-+
-+ /* Try to grab 2 DMA channels */
-+ dma_cap_zero(mask_in);
-+ dma_cap_set(DMA_SLAVE, mask_in);
-+
-+ dd->dma_lch_in.chan = dma_request_channel(mask_in,
-+ atmel_tdes_filter, &pdata->dma_slave->rxdata);
-+
-+ if (!dd->dma_lch_in.chan)
-+ goto err_dma_in;
-+
-+ dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV;
-+ dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base +
-+ TDES_IDATA1R;
-+ dd->dma_lch_in.dma_conf.src_maxburst = 1;
-+ dd->dma_lch_in.dma_conf.src_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
-+ dd->dma_lch_in.dma_conf.dst_maxburst = 1;
-+ dd->dma_lch_in.dma_conf.dst_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
-+ dd->dma_lch_in.dma_conf.device_fc = false;
-+
-+ dma_cap_zero(mask_out);
-+ dma_cap_set(DMA_SLAVE, mask_out);
-+ dd->dma_lch_out.chan = dma_request_channel(mask_out,
-+ atmel_tdes_filter, &pdata->dma_slave->txdata);
-+
-+ if (!dd->dma_lch_out.chan)
-+ goto err_dma_out;
-+
-+ dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM;
-+ dd->dma_lch_out.dma_conf.src_addr = dd->phys_base +
-+ TDES_ODATA1R;
-+ dd->dma_lch_out.dma_conf.src_maxburst = 1;
-+ dd->dma_lch_out.dma_conf.src_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
-+ dd->dma_lch_out.dma_conf.dst_maxburst = 1;
-+ dd->dma_lch_out.dma_conf.dst_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
-+ dd->dma_lch_out.dma_conf.device_fc = false;
-+
-+ return 0;
-+ } else {
- return -ENODEV;
-+ }
-
-- rctx->mode = mode;
-+err_dma_out:
-+ dma_release_channel(dd->dma_lch_in.chan);
-+err_dma_in:
-+ return err;
-+}
-
-- return atmel_tdes_handle_queue(dd, req);
-+static void atmel_tdes_dma_cleanup(struct atmel_tdes_dev *dd)
-+{
-+ dma_release_channel(dd->dma_lch_in.chan);
-+ dma_release_channel(dd->dma_lch_out.chan);
- }
-
- static int atmel_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
-@@ -595,7 +822,8 @@ static int atmel_tdes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
- /*
- * HW bug in cfb 3-keys mode.
- */
-- if (strstr(alg_name, "cfb") && (keylen != 2*DES_KEY_SIZE)) {
-+ if (!ctx->dd->caps.has_cfb_3keys && strstr(alg_name, "cfb")
-+ && (keylen != 2*DES_KEY_SIZE)) {
- crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
- return -EINVAL;
- } else if ((keylen != 2*DES_KEY_SIZE) && (keylen != 3*DES_KEY_SIZE)) {
-@@ -683,8 +911,15 @@ static int atmel_tdes_ofb_decrypt(struct ablkcipher_request *req)
-
- static int atmel_tdes_cra_init(struct crypto_tfm *tfm)
- {
-+ struct atmel_tdes_ctx *ctx = crypto_tfm_ctx(tfm);
-+ struct atmel_tdes_dev *dd;
-+
- tfm->crt_ablkcipher.reqsize = sizeof(struct atmel_tdes_reqctx);
-
-+ dd = atmel_tdes_find_dev(ctx);
-+ if (!dd)
-+ return -ENODEV;
-+
- return 0;
- }
-
-@@ -700,7 +935,7 @@ static struct crypto_alg tdes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = DES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-- .cra_alignmask = 0,
-+ .cra_alignmask = 0x7,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_tdes_cra_init,
-@@ -720,7 +955,7 @@ static struct crypto_alg tdes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = DES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-- .cra_alignmask = 0,
-+ .cra_alignmask = 0x7,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_tdes_cra_init,
-@@ -741,7 +976,7 @@ static struct crypto_alg tdes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = DES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-- .cra_alignmask = 0,
-+ .cra_alignmask = 0x7,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_tdes_cra_init,
-@@ -783,7 +1018,7 @@ static struct crypto_alg tdes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = CFB16_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-- .cra_alignmask = 0,
-+ .cra_alignmask = 0x1,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_tdes_cra_init,
-@@ -804,7 +1039,7 @@ static struct crypto_alg tdes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = CFB32_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-- .cra_alignmask = 0,
-+ .cra_alignmask = 0x3,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_tdes_cra_init,
-@@ -825,7 +1060,7 @@ static struct crypto_alg tdes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = DES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-- .cra_alignmask = 0,
-+ .cra_alignmask = 0x7,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_tdes_cra_init,
-@@ -846,7 +1081,7 @@ static struct crypto_alg tdes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = DES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-- .cra_alignmask = 0,
-+ .cra_alignmask = 0x7,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_tdes_cra_init,
-@@ -866,7 +1101,7 @@ static struct crypto_alg tdes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = DES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-- .cra_alignmask = 0,
-+ .cra_alignmask = 0x7,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_tdes_cra_init,
-@@ -887,7 +1122,7 @@ static struct crypto_alg tdes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = DES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-- .cra_alignmask = 0,
-+ .cra_alignmask = 0x7,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_tdes_cra_init,
-@@ -929,7 +1164,7 @@ static struct crypto_alg tdes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = CFB16_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-- .cra_alignmask = 0,
-+ .cra_alignmask = 0x1,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_tdes_cra_init,
-@@ -950,7 +1185,7 @@ static struct crypto_alg tdes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = CFB32_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-- .cra_alignmask = 0,
-+ .cra_alignmask = 0x3,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_tdes_cra_init,
-@@ -971,7 +1206,7 @@ static struct crypto_alg tdes_algs[] = {
- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
- .cra_blocksize = DES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct atmel_tdes_ctx),
-- .cra_alignmask = 0,
-+ .cra_alignmask = 0x7,
- .cra_type = &crypto_ablkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_init = atmel_tdes_cra_init,
-@@ -999,14 +1234,24 @@ static void atmel_tdes_done_task(unsigned long data)
- struct atmel_tdes_dev *dd = (struct atmel_tdes_dev *) data;
- int err;
-
-- err = atmel_tdes_crypt_dma_stop(dd);
-+ if (!(dd->flags & TDES_FLAGS_DMA))
-+ err = atmel_tdes_crypt_pdc_stop(dd);
-+ else
-+ err = atmel_tdes_crypt_dma_stop(dd);
-
- err = dd->err ? : err;
-
- if (dd->total && !err) {
-- err = atmel_tdes_crypt_dma_start(dd);
-+ if (dd->flags & TDES_FLAGS_FAST) {
-+ dd->in_sg = sg_next(dd->in_sg);
-+ dd->out_sg = sg_next(dd->out_sg);
-+ if (!dd->in_sg || !dd->out_sg)
-+ err = -EINVAL;
-+ }
-+ if (!err)
-+ err = atmel_tdes_crypt_start(dd);
- if (!err)
-- return;
-+ return; /* DMA started. Not fininishing. */
- }
-
- atmel_tdes_finish_req(dd, err);
-@@ -1059,9 +1304,157 @@ err_tdes_algs:
- return err;
- }
-
-+#ifdef CONFIG_OF
-+static const struct of_device_id atmel_tdes_dt_ids[] = {
-+ { .compatible = "atmel,sam9g46-tdes" },
-+ { /* sentinel */ }
-+};
-+
-+MODULE_DEVICE_TABLE(of, atmel_tdes_dt_ids);
-+
-+static int atmel_tdes_dma_of_init(struct device_node *np,
-+ struct at_dma_slave *atslave, const char *name)
-+{
-+ struct of_phandle_args dma_spec;
-+ struct device_node *dmac_np;
-+ struct platform_device *dmac_pdev;
-+ const __be32 *nbcells;
-+ int ret;
-+ int index;
-+
-+ index = of_property_match_string(np, "dma-name", name);
-+ if (index < 0) {
-+ pr_err("%s: dma-name property is required\n", np->full_name);
-+ ret = -EINVAL;
-+ goto err0;
-+ }
-+
-+ ret = of_parse_phandle_with_args(np, "dma", "#dma-cells",
-+ index, &dma_spec);
-+ if (ret || !dma_spec.np) {
-+ pr_err("%s: can't parse dma property (%d)\n",
-+ np->full_name, ret);
-+ goto err0;
-+ }
-+ dmac_np = dma_spec.np;
-+
-+ /* check property format */
-+ nbcells = of_get_property(dmac_np, "#dma-cells", NULL);
-+ if (!nbcells) {
-+ pr_err("%s: #dma-cells property is required\n", np->full_name);
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ if (dma_spec.args_count != be32_to_cpup(nbcells)
-+ || dma_spec.args_count != 1) {
-+ pr_err("%s: wrong #dma-cells for %s\n",
-+ np->full_name, dmac_np->full_name);
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ /* retreive DMA controller information */
-+ dmac_pdev = of_find_device_by_node(dmac_np);
-+ if (!dmac_pdev) {
-+ pr_err("%s: unable to find pdev from DMA controller\n",
-+ dmac_np->full_name);
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ /* now fill in the at_dma_slave structure */
-+ atslave->dma_dev = &dmac_pdev->dev;
-+ atslave->cfg = dma_spec.args[0];
-+
-+err1:
-+ of_node_put(dma_spec.np);
-+err0:
-+ pr_debug("%s exited with status %d\n", __func__, ret);
-+ return ret;
-+}
-+
-+
-+static struct crypto_platform_data __devinit*
-+atmel_tdes_of_init(struct platform_device *pdev)
-+{
-+ struct device_node *np = pdev->dev.of_node;
-+ struct crypto_platform_data *pdata;
-+ struct at_dma_slave *atslave;
-+
-+ if (!np) {
-+ dev_err(&pdev->dev, "device node not found\n");
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-+ if (!pdata) {
-+ dev_err(&pdev->dev, "could not allocate memory for pdata\n");
-+ return ERR_PTR(-ENOMEM);
-+ }
-+
-+ pdata->dma_slave = devm_kzalloc(&pdev->dev,
-+ sizeof(*(pdata->dma_slave)),
-+ GFP_KERNEL);
-+ if (!pdata->dma_slave) {
-+ dev_err(&pdev->dev, "could not allocate memory for dma_slave\n");
-+ devm_kfree(&pdev->dev, pdata);
-+ return ERR_PTR(-ENOMEM);
-+ }
-+
-+ atslave = &pdata->dma_slave->txdata;
-+ /* retrieve TX DMA configuration first */
-+ if (atmel_tdes_dma_of_init(np, atslave, "tx")) {
-+ dev_err(&pdev->dev, "could not find TX DMA parameters\n");
-+ devm_kfree(&pdev->dev, pdata->dma_slave);
-+ devm_kfree(&pdev->dev, pdata);
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ atslave = &pdata->dma_slave->rxdata;
-+ /* retrieve RX DMA configuration first */
-+ if (atmel_tdes_dma_of_init(np, atslave, "rx")) {
-+ dev_err(&pdev->dev, "could not find RX DMA parameters\n");
-+ devm_kfree(&pdev->dev, pdata->dma_slave);
-+ devm_kfree(&pdev->dev, pdata);
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ return pdata;
-+}
-+#else /* CONFIG_OF */
-+static inline struct crypto_platform_data*
-+atmel_tdes_of_init(struct platform_device *dev)
-+{
-+ return ERR_PTR(-EINVAL);
-+}
-+#endif
-+
-+static void atmel_tdes_get_cap(struct atmel_tdes_dev *dd)
-+{
-+
-+ dd->caps.has_dma = 0;
-+ dd->caps.has_cfb_3keys = 0;
-+
-+ /* keep only major version number */
-+ switch (dd->hw_version & 0xf00) {
-+ case 0x700:
-+ dd->caps.has_dma = 1;
-+ dd->caps.has_cfb_3keys = 1;
-+ break;
-+ case 0x600:
-+ break;
-+ default:
-+ dev_warn(dd->dev,
-+ "Unmanaged tdes version, set minimum capabilities\n");
-+ break;
-+ }
-+}
-+
- static int __devinit atmel_tdes_probe(struct platform_device *pdev)
- {
- struct atmel_tdes_dev *tdes_dd;
-+ struct crypto_platform_data *pdata;
- struct device *dev = &pdev->dev;
- struct resource *tdes_res;
- unsigned long tdes_phys_size;
-@@ -1115,7 +1508,7 @@ static int __devinit atmel_tdes_probe(struct platform_device *pdev)
- }
-
- /* Initializing the clock */
-- tdes_dd->iclk = clk_get(&pdev->dev, NULL);
-+ tdes_dd->iclk = clk_get(&pdev->dev, "tdes_clk");
- if (IS_ERR(tdes_dd->iclk)) {
- dev_err(dev, "clock intialization failed.\n");
- err = PTR_ERR(tdes_dd->iclk);
-@@ -1129,9 +1522,27 @@ static int __devinit atmel_tdes_probe(struct platform_device *pdev)
- goto tdes_io_err;
- }
-
-- err = atmel_tdes_dma_init(tdes_dd);
-+ atmel_tdes_hw_version_init(tdes_dd);
-+
-+ atmel_tdes_get_cap(tdes_dd);
-+
-+ err = atmel_tdes_buff_init(tdes_dd);
- if (err)
-- goto err_tdes_dma;
-+ goto err_tdes_buff;
-+
-+ if (tdes_dd->caps.has_dma) {
-+ pdata = pdev->dev.platform_data;
-+ if (!pdata) {
-+ pdata = atmel_tdes_of_init(pdev);
-+ if (IS_ERR(pdata)) {
-+ dev_err(&pdev->dev, "platform data not available\n");
-+ goto err_pdata;
-+ }
-+ }
-+ err = atmel_tdes_dma_init(tdes_dd, pdata);
-+ if (err)
-+ goto err_tdes_dma;
-+ }
-
- spin_lock(&atmel_tdes.lock);
- list_add_tail(&tdes_dd->list, &atmel_tdes.dev_list);
-@@ -1149,8 +1560,12 @@ err_algs:
- spin_lock(&atmel_tdes.lock);
- list_del(&tdes_dd->list);
- spin_unlock(&atmel_tdes.lock);
-- atmel_tdes_dma_cleanup(tdes_dd);
-+ if (tdes_dd->caps.has_dma)
-+ atmel_tdes_dma_cleanup(tdes_dd);
- err_tdes_dma:
-+err_pdata:
-+ atmel_tdes_buff_cleanup(tdes_dd);
-+err_tdes_buff:
- iounmap(tdes_dd->io_base);
- tdes_io_err:
- clk_put(tdes_dd->iclk);
-@@ -1184,7 +1599,10 @@ static int __devexit atmel_tdes_remove(struct platform_device *pdev)
- tasklet_kill(&tdes_dd->done_task);
- tasklet_kill(&tdes_dd->queue_task);
-
-- atmel_tdes_dma_cleanup(tdes_dd);
-+ if (tdes_dd->caps.has_dma)
-+ atmel_tdes_dma_cleanup(tdes_dd);
-+
-+ atmel_tdes_buff_cleanup(tdes_dd);
-
- iounmap(tdes_dd->io_base);
-
-@@ -1200,15 +1618,26 @@ static int __devexit atmel_tdes_remove(struct platform_device *pdev)
- }
-
- static struct platform_driver atmel_tdes_driver = {
-- .probe = atmel_tdes_probe,
- .remove = __devexit_p(atmel_tdes_remove),
- .driver = {
- .name = "atmel_tdes",
-- .owner = THIS_MODULE,
-+ .owner = THIS_MODULE,
-+ .of_match_table = of_match_ptr(atmel_tdes_dt_ids),
- },
- };
-
--module_platform_driver(atmel_tdes_driver);
-+static int __init atmel_tdes_init(void)
-+{
-+ return platform_driver_probe(&atmel_tdes_driver, atmel_tdes_probe);
-+}
-+
-+static void __exit atmel_tdes_exit(void)
-+{
-+ platform_driver_unregister(&atmel_tdes_driver);
-+}
-+
-+late_initcall(atmel_tdes_init); /* try to load after dma driver when built-in */
-+module_exit(atmel_tdes_exit);
-
- MODULE_DESCRIPTION("Atmel DES/TDES hw acceleration support.");
- MODULE_LICENSE("GPL v2");
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 35a5e22b90101fbaf150d1ac05f740da3f840779 Mon Sep 17 00:00:00 2001
-From: Nicolas Royer <nicolas@eukrea.com>
-Date: Mon, 17 Sep 2012 18:26:17 +0200
-Subject: crypto: Atmel SHA; add device tree support
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Eric Bénard <eric@eukrea.com>
-Tested-by: Eric Bénard <eric@eukrea.com>
----
- drivers/crypto/atmel-sha-regs.h | 7 +-
- drivers/crypto/atmel-sha.c | 698 ++++++++++++++++++++++++++++++++++------
- 2 files changed, 608 insertions(+), 97 deletions(-)
-
-diff --git a/drivers/crypto/atmel-sha-regs.h b/drivers/crypto/atmel-sha-regs.h
-index dc53a20..83b2d74 100644
---- a/drivers/crypto/atmel-sha-regs.h
-+++ b/drivers/crypto/atmel-sha-regs.h
-@@ -14,10 +14,13 @@
- #define SHA_MR_MODE_MANUAL 0x0
- #define SHA_MR_MODE_AUTO 0x1
- #define SHA_MR_MODE_PDC 0x2
--#define SHA_MR_DUALBUFF (1 << 3)
- #define SHA_MR_PROCDLY (1 << 4)
- #define SHA_MR_ALGO_SHA1 (0 << 8)
- #define SHA_MR_ALGO_SHA256 (1 << 8)
-+#define SHA_MR_ALGO_SHA384 (2 << 8)
-+#define SHA_MR_ALGO_SHA512 (3 << 8)
-+#define SHA_MR_ALGO_SHA224 (4 << 8)
-+#define SHA_MR_DUALBUFF (1 << 16)
-
- #define SHA_IER 0x10
- #define SHA_IDR 0x14
-@@ -33,6 +36,8 @@
- #define SHA_ISR_URAT_MR (0x2 << 12)
- #define SHA_ISR_URAT_WO (0x5 << 12)
-
-+#define SHA_HW_VERSION 0xFC
-+
- #define SHA_TPR 0x108
- #define SHA_TCR 0x10C
- #define SHA_TNPR 0x118
-diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
-index f938b9d..f66f1c8 100644
---- a/drivers/crypto/atmel-sha.c
-+++ b/drivers/crypto/atmel-sha.c
-@@ -43,6 +43,9 @@
- #include <crypto/sha.h>
- #include <crypto/hash.h>
- #include <crypto/internal/hash.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_data/atmel-crypto.h>
- #include "atmel-sha-regs.h"
-
- /* SHA flags */
-@@ -57,11 +60,12 @@
- #define SHA_FLAGS_FINUP BIT(16)
- #define SHA_FLAGS_SG BIT(17)
- #define SHA_FLAGS_SHA1 BIT(18)
--#define SHA_FLAGS_SHA256 BIT(19)
--#define SHA_FLAGS_ERROR BIT(20)
--#define SHA_FLAGS_PAD BIT(21)
--
--#define SHA_FLAGS_DUALBUFF BIT(24)
-+#define SHA_FLAGS_SHA224 BIT(19)
-+#define SHA_FLAGS_SHA256 BIT(20)
-+#define SHA_FLAGS_SHA384 BIT(21)
-+#define SHA_FLAGS_SHA512 BIT(22)
-+#define SHA_FLAGS_ERROR BIT(23)
-+#define SHA_FLAGS_PAD BIT(24)
-
- #define SHA_OP_UPDATE 1
- #define SHA_OP_FINAL 2
-@@ -70,6 +74,12 @@
-
- #define ATMEL_SHA_DMA_THRESHOLD 56
-
-+struct atmel_sha_caps {
-+ bool has_dma;
-+ bool has_dualbuff;
-+ bool has_sha224;
-+ bool has_sha_384_512;
-+};
-
- struct atmel_sha_dev;
-
-@@ -78,8 +88,8 @@ struct atmel_sha_reqctx {
- unsigned long flags;
- unsigned long op;
-
-- u8 digest[SHA256_DIGEST_SIZE] __aligned(sizeof(u32));
-- size_t digcnt;
-+ u8 digest[SHA512_DIGEST_SIZE] __aligned(sizeof(u32));
-+ u64 digcnt[2];
- size_t bufcnt;
- size_t buflen;
- dma_addr_t dma_addr;
-@@ -89,6 +99,8 @@ struct atmel_sha_reqctx {
- unsigned int offset; /* offset in current sg */
- unsigned int total; /* total request */
-
-+ size_t block_size;
-+
- u8 buffer[0] __aligned(sizeof(u32));
- };
-
-@@ -102,7 +114,12 @@ struct atmel_sha_ctx {
-
- };
-
--#define ATMEL_SHA_QUEUE_LENGTH 1
-+#define ATMEL_SHA_QUEUE_LENGTH 50
-+
-+struct atmel_sha_dma {
-+ struct dma_chan *chan;
-+ struct dma_slave_config dma_conf;
-+};
-
- struct atmel_sha_dev {
- struct list_head list;
-@@ -119,6 +136,12 @@ struct atmel_sha_dev {
- unsigned long flags;
- struct crypto_queue queue;
- struct ahash_request *req;
-+
-+ struct atmel_sha_dma dma_lch_in;
-+
-+ struct atmel_sha_caps caps;
-+
-+ u32 hw_version;
- };
-
- struct atmel_sha_drv {
-@@ -142,14 +165,6 @@ static inline void atmel_sha_write(struct atmel_sha_dev *dd,
- writel_relaxed(value, dd->io_base + offset);
- }
-
--static void atmel_sha_dualbuff_test(struct atmel_sha_dev *dd)
--{
-- atmel_sha_write(dd, SHA_MR, SHA_MR_DUALBUFF);
--
-- if (atmel_sha_read(dd, SHA_MR) & SHA_MR_DUALBUFF)
-- dd->flags |= SHA_FLAGS_DUALBUFF;
--}
--
- static size_t atmel_sha_append_sg(struct atmel_sha_reqctx *ctx)
- {
- size_t count;
-@@ -193,19 +208,40 @@ static size_t atmel_sha_append_sg(struct atmel_sha_reqctx *ctx)
- static void atmel_sha_fill_padding(struct atmel_sha_reqctx *ctx, int length)
- {
- unsigned int index, padlen;
-- u64 bits;
-- u64 size;
--
-- bits = (ctx->bufcnt + ctx->digcnt + length) << 3;
-- size = cpu_to_be64(bits);
--
-- index = ctx->bufcnt & 0x3f;
-- padlen = (index < 56) ? (56 - index) : ((64+56) - index);
-- *(ctx->buffer + ctx->bufcnt) = 0x80;
-- memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen-1);
-- memcpy(ctx->buffer + ctx->bufcnt + padlen, &size, 8);
-- ctx->bufcnt += padlen + 8;
-- ctx->flags |= SHA_FLAGS_PAD;
-+ u64 bits[2];
-+ u64 size[2];
-+
-+ size[0] = ctx->digcnt[0];
-+ size[1] = ctx->digcnt[1];
-+
-+ size[0] += ctx->bufcnt;
-+ if (size[0] < ctx->bufcnt)
-+ size[1]++;
-+
-+ size[0] += length;
-+ if (size[0] < length)
-+ size[1]++;
-+
-+ bits[1] = cpu_to_be64(size[0] << 3);
-+ bits[0] = cpu_to_be64(size[1] << 3 | size[0] >> 61);
-+
-+ if (ctx->flags & (SHA_FLAGS_SHA384 | SHA_FLAGS_SHA512)) {
-+ index = ctx->bufcnt & 0x7f;
-+ padlen = (index < 112) ? (112 - index) : ((128+112) - index);
-+ *(ctx->buffer + ctx->bufcnt) = 0x80;
-+ memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen-1);
-+ memcpy(ctx->buffer + ctx->bufcnt + padlen, bits, 16);
-+ ctx->bufcnt += padlen + 16;
-+ ctx->flags |= SHA_FLAGS_PAD;
-+ } else {
-+ index = ctx->bufcnt & 0x3f;
-+ padlen = (index < 56) ? (56 - index) : ((64+56) - index);
-+ *(ctx->buffer + ctx->bufcnt) = 0x80;
-+ memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen-1);
-+ memcpy(ctx->buffer + ctx->bufcnt + padlen, &bits[1], 8);
-+ ctx->bufcnt += padlen + 8;
-+ ctx->flags |= SHA_FLAGS_PAD;
-+ }
- }
-
- static int atmel_sha_init(struct ahash_request *req)
-@@ -236,13 +272,35 @@ static int atmel_sha_init(struct ahash_request *req)
- dev_dbg(dd->dev, "init: digest size: %d\n",
- crypto_ahash_digestsize(tfm));
-
-- if (crypto_ahash_digestsize(tfm) == SHA1_DIGEST_SIZE)
-+ switch (crypto_ahash_digestsize(tfm)) {
-+ case SHA1_DIGEST_SIZE:
- ctx->flags |= SHA_FLAGS_SHA1;
-- else if (crypto_ahash_digestsize(tfm) == SHA256_DIGEST_SIZE)
-+ ctx->block_size = SHA1_BLOCK_SIZE;
-+ break;
-+ case SHA224_DIGEST_SIZE:
-+ ctx->flags |= SHA_FLAGS_SHA224;
-+ ctx->block_size = SHA224_BLOCK_SIZE;
-+ break;
-+ case SHA256_DIGEST_SIZE:
- ctx->flags |= SHA_FLAGS_SHA256;
-+ ctx->block_size = SHA256_BLOCK_SIZE;
-+ break;
-+ case SHA384_DIGEST_SIZE:
-+ ctx->flags |= SHA_FLAGS_SHA384;
-+ ctx->block_size = SHA384_BLOCK_SIZE;
-+ break;
-+ case SHA512_DIGEST_SIZE:
-+ ctx->flags |= SHA_FLAGS_SHA512;
-+ ctx->block_size = SHA512_BLOCK_SIZE;
-+ break;
-+ default:
-+ return -EINVAL;
-+ break;
-+ }
-
- ctx->bufcnt = 0;
-- ctx->digcnt = 0;
-+ ctx->digcnt[0] = 0;
-+ ctx->digcnt[1] = 0;
- ctx->buflen = SHA_BUFFER_LEN;
-
- return 0;
-@@ -254,19 +312,28 @@ static void atmel_sha_write_ctrl(struct atmel_sha_dev *dd, int dma)
- u32 valcr = 0, valmr = SHA_MR_MODE_AUTO;
-
- if (likely(dma)) {
-- atmel_sha_write(dd, SHA_IER, SHA_INT_TXBUFE);
-+ if (!dd->caps.has_dma)
-+ atmel_sha_write(dd, SHA_IER, SHA_INT_TXBUFE);
- valmr = SHA_MR_MODE_PDC;
-- if (dd->flags & SHA_FLAGS_DUALBUFF)
-- valmr = SHA_MR_DUALBUFF;
-+ if (dd->caps.has_dualbuff)
-+ valmr |= SHA_MR_DUALBUFF;
- } else {
- atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY);
- }
-
-- if (ctx->flags & SHA_FLAGS_SHA256)
-+ if (ctx->flags & SHA_FLAGS_SHA1)
-+ valmr |= SHA_MR_ALGO_SHA1;
-+ else if (ctx->flags & SHA_FLAGS_SHA224)
-+ valmr |= SHA_MR_ALGO_SHA224;
-+ else if (ctx->flags & SHA_FLAGS_SHA256)
- valmr |= SHA_MR_ALGO_SHA256;
-+ else if (ctx->flags & SHA_FLAGS_SHA384)
-+ valmr |= SHA_MR_ALGO_SHA384;
-+ else if (ctx->flags & SHA_FLAGS_SHA512)
-+ valmr |= SHA_MR_ALGO_SHA512;
-
- /* Setting CR_FIRST only for the first iteration */
-- if (!ctx->digcnt)
-+ if (!(ctx->digcnt[0] || ctx->digcnt[1]))
- valcr = SHA_CR_FIRST;
-
- atmel_sha_write(dd, SHA_CR, valcr);
-@@ -280,13 +347,15 @@ static int atmel_sha_xmit_cpu(struct atmel_sha_dev *dd, const u8 *buf,
- int count, len32;
- const u32 *buffer = (const u32 *)buf;
-
-- dev_dbg(dd->dev, "xmit_cpu: digcnt: %d, length: %d, final: %d\n",
-- ctx->digcnt, length, final);
-+ dev_dbg(dd->dev, "xmit_cpu: digcnt: 0x%llx 0x%llx, length: %d, final: %d\n",
-+ ctx->digcnt[1], ctx->digcnt[0], length, final);
-
- atmel_sha_write_ctrl(dd, 0);
-
- /* should be non-zero before next lines to disable clocks later */
-- ctx->digcnt += length;
-+ ctx->digcnt[0] += length;
-+ if (ctx->digcnt[0] < length)
-+ ctx->digcnt[1]++;
-
- if (final)
- dd->flags |= SHA_FLAGS_FINAL; /* catch last interrupt */
-@@ -307,8 +376,8 @@ static int atmel_sha_xmit_pdc(struct atmel_sha_dev *dd, dma_addr_t dma_addr1,
- struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req);
- int len32;
-
-- dev_dbg(dd->dev, "xmit_pdc: digcnt: %d, length: %d, final: %d\n",
-- ctx->digcnt, length1, final);
-+ dev_dbg(dd->dev, "xmit_pdc: digcnt: 0x%llx 0x%llx, length: %d, final: %d\n",
-+ ctx->digcnt[1], ctx->digcnt[0], length1, final);
-
- len32 = DIV_ROUND_UP(length1, sizeof(u32));
- atmel_sha_write(dd, SHA_PTCR, SHA_PTCR_TXTDIS);
-@@ -322,7 +391,9 @@ static int atmel_sha_xmit_pdc(struct atmel_sha_dev *dd, dma_addr_t dma_addr1,
- atmel_sha_write_ctrl(dd, 1);
-
- /* should be non-zero before next lines to disable clocks later */
-- ctx->digcnt += length1;
-+ ctx->digcnt[0] += length1;
-+ if (ctx->digcnt[0] < length1)
-+ ctx->digcnt[1]++;
-
- if (final)
- dd->flags |= SHA_FLAGS_FINAL; /* catch last interrupt */
-@@ -335,6 +406,86 @@ static int atmel_sha_xmit_pdc(struct atmel_sha_dev *dd, dma_addr_t dma_addr1,
- return -EINPROGRESS;
- }
-
-+static void atmel_sha_dma_callback(void *data)
-+{
-+ struct atmel_sha_dev *dd = data;
-+
-+ /* dma_lch_in - completed - wait DATRDY */
-+ atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY);
-+}
-+
-+static int atmel_sha_xmit_dma(struct atmel_sha_dev *dd, dma_addr_t dma_addr1,
-+ size_t length1, dma_addr_t dma_addr2, size_t length2, int final)
-+{
-+ struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req);
-+ struct dma_async_tx_descriptor *in_desc;
-+ struct scatterlist sg[2];
-+
-+ dev_dbg(dd->dev, "xmit_dma: digcnt: 0x%llx 0x%llx, length: %d, final: %d\n",
-+ ctx->digcnt[1], ctx->digcnt[0], length1, final);
-+
-+ if (ctx->flags & (SHA_FLAGS_SHA1 | SHA_FLAGS_SHA224 |
-+ SHA_FLAGS_SHA256)) {
-+ dd->dma_lch_in.dma_conf.src_maxburst = 16;
-+ dd->dma_lch_in.dma_conf.dst_maxburst = 16;
-+ } else {
-+ dd->dma_lch_in.dma_conf.src_maxburst = 32;
-+ dd->dma_lch_in.dma_conf.dst_maxburst = 32;
-+ }
-+
-+ dmaengine_slave_config(dd->dma_lch_in.chan, &dd->dma_lch_in.dma_conf);
-+
-+ if (length2) {
-+ sg_init_table(sg, 2);
-+ sg_dma_address(&sg[0]) = dma_addr1;
-+ sg_dma_len(&sg[0]) = length1;
-+ sg_dma_address(&sg[1]) = dma_addr2;
-+ sg_dma_len(&sg[1]) = length2;
-+ in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, sg, 2,
-+ DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-+ } else {
-+ sg_init_table(sg, 1);
-+ sg_dma_address(&sg[0]) = dma_addr1;
-+ sg_dma_len(&sg[0]) = length1;
-+ in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, sg, 1,
-+ DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-+ }
-+ if (!in_desc)
-+ return -EINVAL;
-+
-+ in_desc->callback = atmel_sha_dma_callback;
-+ in_desc->callback_param = dd;
-+
-+ atmel_sha_write_ctrl(dd, 1);
-+
-+ /* should be non-zero before next lines to disable clocks later */
-+ ctx->digcnt[0] += length1;
-+ if (ctx->digcnt[0] < length1)
-+ ctx->digcnt[1]++;
-+
-+ if (final)
-+ dd->flags |= SHA_FLAGS_FINAL; /* catch last interrupt */
-+
-+ dd->flags |= SHA_FLAGS_DMA_ACTIVE;
-+
-+ /* Start DMA transfer */
-+ dmaengine_submit(in_desc);
-+ dma_async_issue_pending(dd->dma_lch_in.chan);
-+
-+ return -EINPROGRESS;
-+}
-+
-+static int atmel_sha_xmit_start(struct atmel_sha_dev *dd, dma_addr_t dma_addr1,
-+ size_t length1, dma_addr_t dma_addr2, size_t length2, int final)
-+{
-+ if (dd->caps.has_dma)
-+ return atmel_sha_xmit_dma(dd, dma_addr1, length1,
-+ dma_addr2, length2, final);
-+ else
-+ return atmel_sha_xmit_pdc(dd, dma_addr1, length1,
-+ dma_addr2, length2, final);
-+}
-+
- static int atmel_sha_update_cpu(struct atmel_sha_dev *dd)
- {
- struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req);
-@@ -342,7 +493,6 @@ static int atmel_sha_update_cpu(struct atmel_sha_dev *dd)
-
- atmel_sha_append_sg(ctx);
- atmel_sha_fill_padding(ctx, 0);
--
- bufcnt = ctx->bufcnt;
- ctx->bufcnt = 0;
-
-@@ -354,17 +504,17 @@ static int atmel_sha_xmit_dma_map(struct atmel_sha_dev *dd,
- size_t length, int final)
- {
- ctx->dma_addr = dma_map_single(dd->dev, ctx->buffer,
-- ctx->buflen + SHA1_BLOCK_SIZE, DMA_TO_DEVICE);
-+ ctx->buflen + ctx->block_size, DMA_TO_DEVICE);
- if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
- dev_err(dd->dev, "dma %u bytes error\n", ctx->buflen +
-- SHA1_BLOCK_SIZE);
-+ ctx->block_size);
- return -EINVAL;
- }
-
- ctx->flags &= ~SHA_FLAGS_SG;
-
- /* next call does not fail... so no unmap in the case of error */
-- return atmel_sha_xmit_pdc(dd, ctx->dma_addr, length, 0, 0, final);
-+ return atmel_sha_xmit_start(dd, ctx->dma_addr, length, 0, 0, final);
- }
-
- static int atmel_sha_update_dma_slow(struct atmel_sha_dev *dd)
-@@ -377,8 +527,8 @@ static int atmel_sha_update_dma_slow(struct atmel_sha_dev *dd)
-
- final = (ctx->flags & SHA_FLAGS_FINUP) && !ctx->total;
-
-- dev_dbg(dd->dev, "slow: bufcnt: %u, digcnt: %d, final: %d\n",
-- ctx->bufcnt, ctx->digcnt, final);
-+ dev_dbg(dd->dev, "slow: bufcnt: %u, digcnt: 0x%llx 0x%llx, final: %d\n",
-+ ctx->bufcnt, ctx->digcnt[1], ctx->digcnt[0], final);
-
- if (final)
- atmel_sha_fill_padding(ctx, 0);
-@@ -405,30 +555,25 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev *dd)
- if (ctx->bufcnt || ctx->offset)
- return atmel_sha_update_dma_slow(dd);
-
-- dev_dbg(dd->dev, "fast: digcnt: %d, bufcnt: %u, total: %u\n",
-- ctx->digcnt, ctx->bufcnt, ctx->total);
-+ dev_dbg(dd->dev, "fast: digcnt: 0x%llx 0x%llx, bufcnt: %u, total: %u\n",
-+ ctx->digcnt[1], ctx->digcnt[0], ctx->bufcnt, ctx->total);
-
- sg = ctx->sg;
-
- if (!IS_ALIGNED(sg->offset, sizeof(u32)))
- return atmel_sha_update_dma_slow(dd);
-
-- if (!sg_is_last(sg) && !IS_ALIGNED(sg->length, SHA1_BLOCK_SIZE))
-- /* size is not SHA1_BLOCK_SIZE aligned */
-+ if (!sg_is_last(sg) && !IS_ALIGNED(sg->length, ctx->block_size))
-+ /* size is not ctx->block_size aligned */
- return atmel_sha_update_dma_slow(dd);
-
- length = min(ctx->total, sg->length);
-
- if (sg_is_last(sg)) {
- if (!(ctx->flags & SHA_FLAGS_FINUP)) {
-- /* not last sg must be SHA1_BLOCK_SIZE aligned */
-- tail = length & (SHA1_BLOCK_SIZE - 1);
-+ /* not last sg must be ctx->block_size aligned */
-+ tail = length & (ctx->block_size - 1);
- length -= tail;
-- if (length == 0) {
-- /* offset where to start slow */
-- ctx->offset = length;
-- return atmel_sha_update_dma_slow(dd);
-- }
- }
- }
-
-@@ -439,7 +584,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev *dd)
-
- /* Add padding */
- if (final) {
-- tail = length & (SHA1_BLOCK_SIZE - 1);
-+ tail = length & (ctx->block_size - 1);
- length -= tail;
- ctx->total += tail;
- ctx->offset = length; /* offset where to start slow */
-@@ -450,10 +595,10 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev *dd)
- atmel_sha_fill_padding(ctx, length);
-
- ctx->dma_addr = dma_map_single(dd->dev, ctx->buffer,
-- ctx->buflen + SHA1_BLOCK_SIZE, DMA_TO_DEVICE);
-+ ctx->buflen + ctx->block_size, DMA_TO_DEVICE);
- if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
- dev_err(dd->dev, "dma %u bytes error\n",
-- ctx->buflen + SHA1_BLOCK_SIZE);
-+ ctx->buflen + ctx->block_size);
- return -EINVAL;
- }
-
-@@ -461,7 +606,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev *dd)
- ctx->flags &= ~SHA_FLAGS_SG;
- count = ctx->bufcnt;
- ctx->bufcnt = 0;
-- return atmel_sha_xmit_pdc(dd, ctx->dma_addr, count, 0,
-+ return atmel_sha_xmit_start(dd, ctx->dma_addr, count, 0,
- 0, final);
- } else {
- ctx->sg = sg;
-@@ -475,7 +620,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev *dd)
-
- count = ctx->bufcnt;
- ctx->bufcnt = 0;
-- return atmel_sha_xmit_pdc(dd, sg_dma_address(ctx->sg),
-+ return atmel_sha_xmit_start(dd, sg_dma_address(ctx->sg),
- length, ctx->dma_addr, count, final);
- }
- }
-@@ -488,7 +633,7 @@ static int atmel_sha_update_dma_start(struct atmel_sha_dev *dd)
- ctx->flags |= SHA_FLAGS_SG;
-
- /* next call does not fail... so no unmap in the case of error */
-- return atmel_sha_xmit_pdc(dd, sg_dma_address(ctx->sg), length, 0,
-+ return atmel_sha_xmit_start(dd, sg_dma_address(ctx->sg), length, 0,
- 0, final);
- }
-
-@@ -503,12 +648,13 @@ static int atmel_sha_update_dma_stop(struct atmel_sha_dev *dd)
- if (ctx->sg)
- ctx->offset = 0;
- }
-- if (ctx->flags & SHA_FLAGS_PAD)
-+ if (ctx->flags & SHA_FLAGS_PAD) {
- dma_unmap_single(dd->dev, ctx->dma_addr,
-- ctx->buflen + SHA1_BLOCK_SIZE, DMA_TO_DEVICE);
-+ ctx->buflen + ctx->block_size, DMA_TO_DEVICE);
-+ }
- } else {
- dma_unmap_single(dd->dev, ctx->dma_addr, ctx->buflen +
-- SHA1_BLOCK_SIZE, DMA_TO_DEVICE);
-+ ctx->block_size, DMA_TO_DEVICE);
- }
-
- return 0;
-@@ -520,8 +666,8 @@ static int atmel_sha_update_req(struct atmel_sha_dev *dd)
- struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
- int err;
-
-- dev_dbg(dd->dev, "update_req: total: %u, digcnt: %d, finup: %d\n",
-- ctx->total, ctx->digcnt, (ctx->flags & SHA_FLAGS_FINUP) != 0);
-+ dev_dbg(dd->dev, "update_req: total: %u, digcnt: 0x%llx 0x%llx\n",
-+ ctx->total, ctx->digcnt[1], ctx->digcnt[0]);
-
- if (ctx->flags & SHA_FLAGS_CPU)
- err = atmel_sha_update_cpu(dd);
-@@ -529,8 +675,8 @@ static int atmel_sha_update_req(struct atmel_sha_dev *dd)
- err = atmel_sha_update_dma_start(dd);
-
- /* wait for dma completion before can take more data */
-- dev_dbg(dd->dev, "update: err: %d, digcnt: %d\n",
-- err, ctx->digcnt);
-+ dev_dbg(dd->dev, "update: err: %d, digcnt: 0x%llx 0%llx\n",
-+ err, ctx->digcnt[1], ctx->digcnt[0]);
-
- return err;
- }
-@@ -567,12 +713,21 @@ static void atmel_sha_copy_hash(struct ahash_request *req)
- u32 *hash = (u32 *)ctx->digest;
- int i;
-
-- if (likely(ctx->flags & SHA_FLAGS_SHA1))
-+ if (ctx->flags & SHA_FLAGS_SHA1)
- for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++)
- hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i));
-- else
-+ else if (ctx->flags & SHA_FLAGS_SHA224)
-+ for (i = 0; i < SHA224_DIGEST_SIZE / sizeof(u32); i++)
-+ hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i));
-+ else if (ctx->flags & SHA_FLAGS_SHA256)
- for (i = 0; i < SHA256_DIGEST_SIZE / sizeof(u32); i++)
- hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i));
-+ else if (ctx->flags & SHA_FLAGS_SHA384)
-+ for (i = 0; i < SHA384_DIGEST_SIZE / sizeof(u32); i++)
-+ hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i));
-+ else
-+ for (i = 0; i < SHA512_DIGEST_SIZE / sizeof(u32); i++)
-+ hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i));
- }
-
- static void atmel_sha_copy_ready_hash(struct ahash_request *req)
-@@ -582,10 +737,16 @@ static void atmel_sha_copy_ready_hash(struct ahash_request *req)
- if (!req->result)
- return;
-
-- if (likely(ctx->flags & SHA_FLAGS_SHA1))
-+ if (ctx->flags & SHA_FLAGS_SHA1)
- memcpy(req->result, ctx->digest, SHA1_DIGEST_SIZE);
-- else
-+ else if (ctx->flags & SHA_FLAGS_SHA224)
-+ memcpy(req->result, ctx->digest, SHA224_DIGEST_SIZE);
-+ else if (ctx->flags & SHA_FLAGS_SHA256)
- memcpy(req->result, ctx->digest, SHA256_DIGEST_SIZE);
-+ else if (ctx->flags & SHA_FLAGS_SHA384)
-+ memcpy(req->result, ctx->digest, SHA384_DIGEST_SIZE);
-+ else
-+ memcpy(req->result, ctx->digest, SHA512_DIGEST_SIZE);
- }
-
- static int atmel_sha_finish(struct ahash_request *req)
-@@ -594,11 +755,11 @@ static int atmel_sha_finish(struct ahash_request *req)
- struct atmel_sha_dev *dd = ctx->dd;
- int err = 0;
-
-- if (ctx->digcnt)
-+ if (ctx->digcnt[0] || ctx->digcnt[1])
- atmel_sha_copy_ready_hash(req);
-
-- dev_dbg(dd->dev, "digcnt: %d, bufcnt: %d\n", ctx->digcnt,
-- ctx->bufcnt);
-+ dev_dbg(dd->dev, "digcnt: 0x%llx 0x%llx, bufcnt: %d\n", ctx->digcnt[1],
-+ ctx->digcnt[0], ctx->bufcnt);
-
- return err;
- }
-@@ -633,9 +794,8 @@ static int atmel_sha_hw_init(struct atmel_sha_dev *dd)
- {
- clk_prepare_enable(dd->iclk);
-
-- if (SHA_FLAGS_INIT & dd->flags) {
-+ if (!(SHA_FLAGS_INIT & dd->flags)) {
- atmel_sha_write(dd, SHA_CR, SHA_CR_SWRST);
-- atmel_sha_dualbuff_test(dd);
- dd->flags |= SHA_FLAGS_INIT;
- dd->err = 0;
- }
-@@ -643,6 +803,23 @@ static int atmel_sha_hw_init(struct atmel_sha_dev *dd)
- return 0;
- }
-
-+static inline unsigned int atmel_sha_get_version(struct atmel_sha_dev *dd)
-+{
-+ return atmel_sha_read(dd, SHA_HW_VERSION) & 0x00000fff;
-+}
-+
-+static void atmel_sha_hw_version_init(struct atmel_sha_dev *dd)
-+{
-+ atmel_sha_hw_init(dd);
-+
-+ dd->hw_version = atmel_sha_get_version(dd);
-+
-+ dev_info(dd->dev,
-+ "version: 0x%x\n", dd->hw_version);
-+
-+ clk_disable_unprepare(dd->iclk);
-+}
-+
- static int atmel_sha_handle_queue(struct atmel_sha_dev *dd,
- struct ahash_request *req)
- {
-@@ -687,10 +864,9 @@ static int atmel_sha_handle_queue(struct atmel_sha_dev *dd,
-
- if (ctx->op == SHA_OP_UPDATE) {
- err = atmel_sha_update_req(dd);
-- if (err != -EINPROGRESS && (ctx->flags & SHA_FLAGS_FINUP)) {
-+ if (err != -EINPROGRESS && (ctx->flags & SHA_FLAGS_FINUP))
- /* no final() after finup() */
- err = atmel_sha_final_req(dd);
-- }
- } else if (ctx->op == SHA_OP_FINAL) {
- err = atmel_sha_final_req(dd);
- }
-@@ -813,7 +989,7 @@ static int atmel_sha_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base)
- }
- crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
- sizeof(struct atmel_sha_reqctx) +
-- SHA_BUFFER_LEN + SHA256_BLOCK_SIZE);
-+ SHA_BUFFER_LEN + SHA512_BLOCK_SIZE);
-
- return 0;
- }
-@@ -831,7 +1007,7 @@ static void atmel_sha_cra_exit(struct crypto_tfm *tfm)
- tctx->fallback = NULL;
- }
-
--static struct ahash_alg sha_algs[] = {
-+static struct ahash_alg sha_1_256_algs[] = {
- {
- .init = atmel_sha_init,
- .update = atmel_sha_update,
-@@ -880,6 +1056,79 @@ static struct ahash_alg sha_algs[] = {
- },
- };
-
-+static struct ahash_alg sha_224_alg = {
-+ .init = atmel_sha_init,
-+ .update = atmel_sha_update,
-+ .final = atmel_sha_final,
-+ .finup = atmel_sha_finup,
-+ .digest = atmel_sha_digest,
-+ .halg = {
-+ .digestsize = SHA224_DIGEST_SIZE,
-+ .base = {
-+ .cra_name = "sha224",
-+ .cra_driver_name = "atmel-sha224",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_ASYNC |
-+ CRYPTO_ALG_NEED_FALLBACK,
-+ .cra_blocksize = SHA224_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_sha_ctx),
-+ .cra_alignmask = 0,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_sha_cra_init,
-+ .cra_exit = atmel_sha_cra_exit,
-+ }
-+ }
-+};
-+
-+static struct ahash_alg sha_384_512_algs[] = {
-+{
-+ .init = atmel_sha_init,
-+ .update = atmel_sha_update,
-+ .final = atmel_sha_final,
-+ .finup = atmel_sha_finup,
-+ .digest = atmel_sha_digest,
-+ .halg = {
-+ .digestsize = SHA384_DIGEST_SIZE,
-+ .base = {
-+ .cra_name = "sha384",
-+ .cra_driver_name = "atmel-sha384",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_ASYNC |
-+ CRYPTO_ALG_NEED_FALLBACK,
-+ .cra_blocksize = SHA384_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_sha_ctx),
-+ .cra_alignmask = 0x3,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_sha_cra_init,
-+ .cra_exit = atmel_sha_cra_exit,
-+ }
-+ }
-+},
-+{
-+ .init = atmel_sha_init,
-+ .update = atmel_sha_update,
-+ .final = atmel_sha_final,
-+ .finup = atmel_sha_finup,
-+ .digest = atmel_sha_digest,
-+ .halg = {
-+ .digestsize = SHA512_DIGEST_SIZE,
-+ .base = {
-+ .cra_name = "sha512",
-+ .cra_driver_name = "atmel-sha512",
-+ .cra_priority = 100,
-+ .cra_flags = CRYPTO_ALG_ASYNC |
-+ CRYPTO_ALG_NEED_FALLBACK,
-+ .cra_blocksize = SHA512_BLOCK_SIZE,
-+ .cra_ctxsize = sizeof(struct atmel_sha_ctx),
-+ .cra_alignmask = 0x3,
-+ .cra_module = THIS_MODULE,
-+ .cra_init = atmel_sha_cra_init,
-+ .cra_exit = atmel_sha_cra_exit,
-+ }
-+ }
-+},
-+};
-+
- static void atmel_sha_done_task(unsigned long data)
- {
- struct atmel_sha_dev *dd = (struct atmel_sha_dev *)data;
-@@ -946,32 +1195,251 @@ static void atmel_sha_unregister_algs(struct atmel_sha_dev *dd)
- {
- int i;
-
-- for (i = 0; i < ARRAY_SIZE(sha_algs); i++)
-- crypto_unregister_ahash(&sha_algs[i]);
-+ for (i = 0; i < ARRAY_SIZE(sha_1_256_algs); i++)
-+ crypto_unregister_ahash(&sha_1_256_algs[i]);
-+
-+ if (dd->caps.has_sha224)
-+ crypto_unregister_ahash(&sha_224_alg);
-+
-+ if (dd->caps.has_sha_384_512) {
-+ for (i = 0; i < ARRAY_SIZE(sha_384_512_algs); i++)
-+ crypto_unregister_ahash(&sha_384_512_algs[i]);
-+ }
- }
-
- static int atmel_sha_register_algs(struct atmel_sha_dev *dd)
- {
- int err, i, j;
-
-- for (i = 0; i < ARRAY_SIZE(sha_algs); i++) {
-- err = crypto_register_ahash(&sha_algs[i]);
-+ for (i = 0; i < ARRAY_SIZE(sha_1_256_algs); i++) {
-+ err = crypto_register_ahash(&sha_1_256_algs[i]);
- if (err)
-- goto err_sha_algs;
-+ goto err_sha_1_256_algs;
-+ }
-+
-+ if (dd->caps.has_sha224) {
-+ err = crypto_register_ahash(&sha_224_alg);
-+ if (err)
-+ goto err_sha_224_algs;
-+ }
-+
-+ if (dd->caps.has_sha_384_512) {
-+ for (i = 0; i < ARRAY_SIZE(sha_384_512_algs); i++) {
-+ err = crypto_register_ahash(&sha_384_512_algs[i]);
-+ if (err)
-+ goto err_sha_384_512_algs;
-+ }
- }
-
- return 0;
-
--err_sha_algs:
-+err_sha_384_512_algs:
-+ for (j = 0; j < i; j++)
-+ crypto_unregister_ahash(&sha_384_512_algs[j]);
-+ crypto_unregister_ahash(&sha_224_alg);
-+err_sha_224_algs:
-+ i = ARRAY_SIZE(sha_1_256_algs);
-+err_sha_1_256_algs:
- for (j = 0; j < i; j++)
-- crypto_unregister_ahash(&sha_algs[j]);
-+ crypto_unregister_ahash(&sha_1_256_algs[j]);
-
- return err;
- }
-
-+static bool atmel_sha_filter(struct dma_chan *chan, void *slave)
-+{
-+ struct at_dma_slave *sl = slave;
-+
-+ if (sl && sl->dma_dev == chan->device->dev) {
-+ chan->private = sl;
-+ return true;
-+ } else {
-+ return false;
-+ }
-+}
-+
-+static int atmel_sha_dma_init(struct atmel_sha_dev *dd,
-+ struct crypto_platform_data *pdata)
-+{
-+ int err = -ENOMEM;
-+ dma_cap_mask_t mask_in;
-+
-+ if (pdata && pdata->dma_slave->rxdata.dma_dev) {
-+ /* Try to grab DMA channel */
-+ dma_cap_zero(mask_in);
-+ dma_cap_set(DMA_SLAVE, mask_in);
-+
-+ dd->dma_lch_in.chan = dma_request_channel(mask_in,
-+ atmel_sha_filter, &pdata->dma_slave->rxdata);
-+
-+ if (!dd->dma_lch_in.chan)
-+ return err;
-+
-+ dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV;
-+ dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base +
-+ SHA_REG_DIN(0);
-+ dd->dma_lch_in.dma_conf.src_maxburst = 1;
-+ dd->dma_lch_in.dma_conf.src_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
-+ dd->dma_lch_in.dma_conf.dst_maxburst = 1;
-+ dd->dma_lch_in.dma_conf.dst_addr_width =
-+ DMA_SLAVE_BUSWIDTH_4_BYTES;
-+ dd->dma_lch_in.dma_conf.device_fc = false;
-+
-+ return 0;
-+ }
-+
-+ return -ENODEV;
-+}
-+
-+static void atmel_sha_dma_cleanup(struct atmel_sha_dev *dd)
-+{
-+ dma_release_channel(dd->dma_lch_in.chan);
-+}
-+
-+
-+#ifdef CONFIG_OF
-+static const struct of_device_id atmel_sha_dt_ids[] = {
-+ { .compatible = "atmel,sam9g46-sha" },
-+ { /* sentinel */ }
-+};
-+
-+MODULE_DEVICE_TABLE(of, atmel_sha_dt_ids);
-+
-+static int atmel_sha_dma_of_init(struct device_node *np,
-+ struct at_dma_slave *atslave)
-+{
-+ struct of_phandle_args dma_spec;
-+ struct device_node *dmac_np;
-+ struct platform_device *dmac_pdev;
-+ const __be32 *nbcells;
-+ int ret;
-+
-+ ret = of_parse_phandle_with_args(np, "dma", "#dma-cells", 0, &dma_spec);
-+ if (ret || !dma_spec.np) {
-+ pr_err("%s: can't parse dma property (%d)\n",
-+ np->full_name, ret);
-+ goto err0;
-+ }
-+ dmac_np = dma_spec.np;
-+
-+ /* check property format */
-+ nbcells = of_get_property(dmac_np, "#dma-cells", NULL);
-+ if (!nbcells) {
-+ pr_err("%s: #dma-cells property is required\n", np->full_name);
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ if (dma_spec.args_count != be32_to_cpup(nbcells)
-+ || dma_spec.args_count != 1) {
-+ pr_err("%s: wrong #dma-cells for %s\n",
-+ np->full_name, dmac_np->full_name);
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ /* retreive DMA controller information */
-+ dmac_pdev = of_find_device_by_node(dmac_np);
-+ if (!dmac_pdev) {
-+ pr_err("%s: unable to find pdev from DMA controller\n",
-+ dmac_np->full_name);
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ /* now fill in the at_dma_slave structure */
-+ atslave->dma_dev = &dmac_pdev->dev;
-+ atslave->cfg = dma_spec.args[0];
-+
-+err1:
-+ of_node_put(dma_spec.np);
-+err0:
-+ pr_debug("%s exited with status %d\n", __func__, ret);
-+ return ret;
-+}
-+
-+
-+static struct crypto_platform_data __devinit*
-+atmel_sha_of_init(struct platform_device *pdev)
-+{
-+ struct device_node *np = pdev->dev.of_node;
-+ struct crypto_platform_data *pdata;
-+ struct at_dma_slave *atslave;
-+
-+ if (!np) {
-+ dev_err(&pdev->dev, "device node not found\n");
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-+ if (!pdata) {
-+ dev_err(&pdev->dev, "could not allocate memory for pdata\n");
-+ return ERR_PTR(-ENOMEM);
-+ }
-+
-+ pdata->dma_slave = devm_kzalloc(&pdev->dev,
-+ sizeof(*(pdata->dma_slave)),
-+ GFP_KERNEL);
-+ if (!pdata->dma_slave) {
-+ dev_err(&pdev->dev, "could not allocate memory for dma_slave\n");
-+ devm_kfree(&pdev->dev, pdata);
-+ return ERR_PTR(-ENOMEM);
-+ }
-+
-+ atslave = &pdata->dma_slave->rxdata;
-+ /* retrieve RX DMA configuration first */
-+ if (atmel_sha_dma_of_init(np, atslave)) {
-+ dev_err(&pdev->dev, "could not find RX DMA parameters\n");
-+ devm_kfree(&pdev->dev, pdata->dma_slave);
-+ devm_kfree(&pdev->dev, pdata);
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ return pdata;
-+}
-+#else /* CONFIG_OF */
-+static inline struct crypto_platform_data*
-+atmel_sha_of_init(struct platform_device *dev)
-+{
-+ return ERR_PTR(-EINVAL);
-+}
-+#endif
-+
-+static void atmel_sha_get_cap(struct atmel_sha_dev *dd)
-+{
-+
-+ dd->caps.has_dma = 0;
-+ dd->caps.has_dualbuff = 0;
-+ dd->caps.has_sha224 = 0;
-+ dd->caps.has_sha_384_512 = 0;
-+
-+ /* keep only major version number */
-+ switch (dd->hw_version & 0xff0) {
-+ case 0x410:
-+ dd->caps.has_dma = 1;
-+ dd->caps.has_dualbuff = 1;
-+ dd->caps.has_sha224 = 1;
-+ dd->caps.has_sha_384_512 = 1;
-+ break;
-+ case 0x400:
-+ dd->caps.has_dma = 1;
-+ dd->caps.has_dualbuff = 1;
-+ dd->caps.has_sha224 = 1;
-+ break;
-+ case 0x320:
-+ break;
-+ default:
-+ dev_warn(dd->dev,
-+ "Unmanaged sha version, set minimum capabilities\n");
-+ break;
-+ }
-+}
-+
- static int __devinit atmel_sha_probe(struct platform_device *pdev)
- {
- struct atmel_sha_dev *sha_dd;
-+ struct crypto_platform_data *pdata;
- struct device *dev = &pdev->dev;
- struct resource *sha_res;
- unsigned long sha_phys_size;
-@@ -1023,7 +1491,7 @@ static int __devinit atmel_sha_probe(struct platform_device *pdev)
- }
-
- /* Initializing the clock */
-- sha_dd->iclk = clk_get(&pdev->dev, NULL);
-+ sha_dd->iclk = clk_get(&pdev->dev, "sha_clk");
- if (IS_ERR(sha_dd->iclk)) {
- dev_err(dev, "clock intialization failed.\n");
- err = PTR_ERR(sha_dd->iclk);
-@@ -1037,6 +1505,24 @@ static int __devinit atmel_sha_probe(struct platform_device *pdev)
- goto sha_io_err;
- }
-
-+ atmel_sha_hw_version_init(sha_dd);
-+
-+ atmel_sha_get_cap(sha_dd);
-+
-+ if (sha_dd->caps.has_dma) {
-+ pdata = pdev->dev.platform_data;
-+ if (!pdata) {
-+ pdata = atmel_sha_of_init(pdev);
-+ if (IS_ERR(pdata)) {
-+ dev_err(&pdev->dev, "platform data not available\n");
-+ goto err_pdata;
-+ }
-+ }
-+ err = atmel_sha_dma_init(sha_dd, pdata);
-+ if (err)
-+ goto err_sha_dma;
-+ }
-+
- spin_lock(&atmel_sha.lock);
- list_add_tail(&sha_dd->list, &atmel_sha.dev_list);
- spin_unlock(&atmel_sha.lock);
-@@ -1053,6 +1539,10 @@ err_algs:
- spin_lock(&atmel_sha.lock);
- list_del(&sha_dd->list);
- spin_unlock(&atmel_sha.lock);
-+ if (sha_dd->caps.has_dma)
-+ atmel_sha_dma_cleanup(sha_dd);
-+err_sha_dma:
-+err_pdata:
- iounmap(sha_dd->io_base);
- sha_io_err:
- clk_put(sha_dd->iclk);
-@@ -1083,6 +1573,9 @@ static int __devexit atmel_sha_remove(struct platform_device *pdev)
-
- tasklet_kill(&sha_dd->done_task);
-
-+ if (sha_dd->caps.has_dma)
-+ atmel_sha_dma_cleanup(sha_dd);
-+
- iounmap(sha_dd->io_base);
-
- clk_put(sha_dd->iclk);
-@@ -1097,15 +1590,28 @@ static int __devexit atmel_sha_remove(struct platform_device *pdev)
- }
-
- static struct platform_driver atmel_sha_driver = {
-- .probe = atmel_sha_probe,
- .remove = __devexit_p(atmel_sha_remove),
- .driver = {
- .name = "atmel_sha",
-+ .of_match_table = of_match_ptr(atmel_sha_dt_ids),
- .owner = THIS_MODULE,
- },
- };
-
--module_platform_driver(atmel_sha_driver);
-+static int __init atmel_sha_drv_init(void)
-+{
-+ return platform_driver_probe(&atmel_sha_driver, atmel_sha_probe);
-+}
-+
-+static void __exit atmel_sha_drv_exit(void)
-+{
-+ platform_driver_unregister(&atmel_sha_driver);
-+}
-+
-+/* try to load after dma driver when built-in */
-+late_initcall(atmel_sha_drv_init);
-+module_exit(atmel_sha_drv_exit);
-+
-
- MODULE_DESCRIPTION("Atmel SHA1/SHA256 hw acceleration support.");
- MODULE_LICENSE("GPL v2");
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a025a84b58085328fc8a963088c70cb00ada2bae Mon Sep 17 00:00:00 2001
-From: Nicolas Royer <nicolas@eukrea.com>
-Date: Mon, 17 Sep 2012 18:26:18 +0200
-Subject: crypto: Atmel Test; add SHA224, SHA384 and SHA512 support
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Eric Bénard <eric@eukrea.com>
-Tested-by: Eric Bénard <eric@eukrea.com>
----
- drivers/crypto/atmel-test.c | 25 +++++++++++++++++++------
- 1 file changed, 19 insertions(+), 6 deletions(-)
-
-diff --git a/drivers/crypto/atmel-test.c b/drivers/crypto/atmel-test.c
-index 4a23db5..d9eb80d 100644
---- a/drivers/crypto/atmel-test.c
-+++ b/drivers/crypto/atmel-test.c
-@@ -41,7 +41,11 @@ static char *iv16 =
-
- #define SHA1_MSG_LEN 20
- #define SHA256_MSG_LEN 32
--static char sha_out_buf[SHA256_MSG_LEN];
-+#define SHA224_MSG_LEN 28
-+#define SHA384_MSG_LEN 48
-+#define SHA512_MSG_LEN 64
-+
-+static char sha_out_buf[SHA512_MSG_LEN];
-
- #define TVMEMSIZE 4
- static char *tvmem[TVMEMSIZE];
-@@ -331,7 +335,7 @@ static int dlen = 64;
- module_param_named(dlen, dlen, int,
- S_IRUGO | S_IWUSR | S_IWGRP);
-
--char *ahash_algs[] = {"sha1", "sha256"};
-+char *ahash_algs[] = {"sha1", "sha256", "sha224", "sha384", "sha512"};
-
- char *acipher_algs[] = {
- "ecb(des)", "cbc(des)", "cfb(des)", "cfb32(des)",
-@@ -347,6 +351,7 @@ static int __init init_main(void)
- char *buf_in;
- char *buf_out;
- char *buf_res;
-+ size_t outlen;
-
- if ((dlen <= 0) || (dlen > TVMEMSIZE*PAGE_SIZE)) {
- printk(KERN_ERR " 0 < dlen <= %i\n",
-@@ -382,15 +387,23 @@ static int __init init_main(void)
- ARRAY_SIZE(ahash_algs));
- goto exit;
- }
-+ switch (mode) {
-+ case 0:outlen = SHA1_MSG_LEN; break;
-+ case 1:outlen = SHA256_MSG_LEN; break;
-+ case 2:outlen = SHA224_MSG_LEN; break;
-+ case 3:outlen = SHA384_MSG_LEN; break;
-+ case 4:outlen = SHA512_MSG_LEN; break;
-+ }
-+
- printk(KERN_INFO "\n%s digest_req\n", ahash_algs[mode]);
- hmac_sha_digest(ahash_algs[mode], buf_in, dlen, sha_out_buf,
-- mode ? SHA256_MSG_LEN : SHA1_MSG_LEN);
-- hexdump(sha_out_buf, mode ? SHA256_MSG_LEN : SHA1_MSG_LEN);
-+ outlen);
-+ hexdump(sha_out_buf, outlen);
-
- printk(KERN_INFO "\n%s update_req\n", ahash_algs[mode]);
- hmac_sha_update(ahash_algs[mode], buf_in, dlen, sha_out_buf,
-- mode ? SHA256_MSG_LEN : SHA1_MSG_LEN);
-- hexdump(sha_out_buf, mode ? SHA256_MSG_LEN : SHA1_MSG_LEN);
-+ outlen);
-+ hexdump(sha_out_buf, outlen);
- } else {
- mode -= 10;
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 72689543bfd43fa0c87169fdd66c4e17deb6309d Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Thu, 16 Aug 2012 17:36:55 +0800
-Subject: arm: at91: use macro to declare soc boot data
-
-Instead of check the pointer of the init function, check the new builtin bool
-to known if the soc is enabled.
-
-This is needed as with the switch to the pinctrl the init will be NULL on pure
-DT SoC.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/mach-at91/at91rm9200.c | 4 ++--
- arch/arm/mach-at91/at91sam9260.c | 4 ++--
- arch/arm/mach-at91/at91sam9261.c | 4 ++--
- arch/arm/mach-at91/at91sam9263.c | 4 ++--
- arch/arm/mach-at91/at91sam9g45.c | 4 ++--
- arch/arm/mach-at91/at91sam9n12.c | 4 ++--
- arch/arm/mach-at91/at91sam9rl.c | 4 ++--
- arch/arm/mach-at91/at91sam9x5.c | 4 ++--
- arch/arm/mach-at91/soc.h | 12 +++++++++++-
- 9 files changed, 27 insertions(+), 17 deletions(-)
-
-diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
-index b4f0565..a454734 100644
---- a/arch/arm/mach-at91/at91rm9200.c
-+++ b/arch/arm/mach-at91/at91rm9200.c
-@@ -361,10 +361,10 @@ static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
- 0 /* Advanced Interrupt Controller (IRQ6) */
- };
-
--struct at91_init_soc __initdata at91rm9200_soc = {
-+AT91_SOC_START(rm9200)
- .map_io = at91rm9200_map_io,
- .default_irq_priority = at91rm9200_default_irq_priority,
- .ioremap_registers = at91rm9200_ioremap_registers,
- .register_clocks = at91rm9200_register_clocks,
- .init = at91rm9200_initialize,
--};
-+AT91_SOC_END
-diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
-index 040f79a..bb9bc50 100644
---- a/arch/arm/mach-at91/at91sam9260.c
-+++ b/arch/arm/mach-at91/at91sam9260.c
-@@ -383,10 +383,10 @@ static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = {
- 0, /* Advanced Interrupt Controller */
- };
-
--struct at91_init_soc __initdata at91sam9260_soc = {
-+AT91_SOC_START(sam9260)
- .map_io = at91sam9260_map_io,
- .default_irq_priority = at91sam9260_default_irq_priority,
- .ioremap_registers = at91sam9260_ioremap_registers,
- .register_clocks = at91sam9260_register_clocks,
- .init = at91sam9260_initialize,
--};
-+AT91_SOC_END
-diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
-index 8d999eb..93a24e9 100644
---- a/arch/arm/mach-at91/at91sam9261.c
-+++ b/arch/arm/mach-at91/at91sam9261.c
-@@ -334,10 +334,10 @@ static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = {
- 0, /* Advanced Interrupt Controller */
- };
-
--struct at91_init_soc __initdata at91sam9261_soc = {
-+AT91_SOC_START(sam9261)
- .map_io = at91sam9261_map_io,
- .default_irq_priority = at91sam9261_default_irq_priority,
- .ioremap_registers = at91sam9261_ioremap_registers,
- .register_clocks = at91sam9261_register_clocks,
- .init = at91sam9261_initialize,
--};
-+AT91_SOC_END
-diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
-index 00723ec..76499a6 100644
---- a/arch/arm/mach-at91/at91sam9263.c
-+++ b/arch/arm/mach-at91/at91sam9263.c
-@@ -367,10 +367,10 @@ static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = {
- 0, /* Advanced Interrupt Controller (IRQ1) */
- };
-
--struct at91_init_soc __initdata at91sam9263_soc = {
-+AT91_SOC_START(sam9263)
- .map_io = at91sam9263_map_io,
- .default_irq_priority = at91sam9263_default_irq_priority,
- .ioremap_registers = at91sam9263_ioremap_registers,
- .register_clocks = at91sam9263_register_clocks,
- .init = at91sam9263_initialize,
--};
-+AT91_SOC_END
-diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
-index 4b791bf..5e7a1dd 100644
---- a/arch/arm/mach-at91/at91sam9g45.c
-+++ b/arch/arm/mach-at91/at91sam9g45.c
-@@ -405,10 +405,10 @@ static unsigned int at91sam9g45_default_irq_priority[NR_AIC_IRQS] __initdata = {
- 0, /* Advanced Interrupt Controller (IRQ0) */
- };
-
--struct at91_init_soc __initdata at91sam9g45_soc = {
-+AT91_SOC_START(sam9g45)
- .map_io = at91sam9g45_map_io,
- .default_irq_priority = at91sam9g45_default_irq_priority,
- .ioremap_registers = at91sam9g45_ioremap_registers,
- .register_clocks = at91sam9g45_register_clocks,
- .init = at91sam9g45_initialize,
--};
-+AT91_SOC_END
-diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c
-index d09baf1..6fa0df1 100644
---- a/arch/arm/mach-at91/at91sam9n12.c
-+++ b/arch/arm/mach-at91/at91sam9n12.c
-@@ -246,8 +246,8 @@ void __init at91sam9n12_initialize(void)
- at91_gpio_init(NULL, 0);
- }
-
--struct at91_init_soc __initdata at91sam9n12_soc = {
-+AT91_SOC_START(sam9n12)
- .map_io = at91sam9n12_map_io,
- .register_clocks = at91sam9n12_register_clocks,
- .init = at91sam9n12_initialize,
--};
-+AT91_SOC_END
-diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
-index 72e9084..cbe72e4 100644
---- a/arch/arm/mach-at91/at91sam9rl.c
-+++ b/arch/arm/mach-at91/at91sam9rl.c
-@@ -338,10 +338,10 @@ static unsigned int at91sam9rl_default_irq_priority[NR_AIC_IRQS] __initdata = {
- 0, /* Advanced Interrupt Controller */
- };
-
--struct at91_init_soc __initdata at91sam9rl_soc = {
-+AT91_SOC_START(sam9rl)
- .map_io = at91sam9rl_map_io,
- .default_irq_priority = at91sam9rl_default_irq_priority,
- .ioremap_registers = at91sam9rl_ioremap_registers,
- .register_clocks = at91sam9rl_register_clocks,
- .init = at91sam9rl_initialize,
--};
-+AT91_SOC_END
-diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
-index f40c1ab..af00de4 100644
---- a/arch/arm/mach-at91/at91sam9x5.c
-+++ b/arch/arm/mach-at91/at91sam9x5.c
-@@ -323,8 +323,8 @@ void __init at91sam9x5_initialize(void)
- * Interrupt initialization
- * -------------------------------------------------------------------- */
-
--struct at91_init_soc __initdata at91sam9x5_soc = {
-+AT91_SOC_START(sam9x5)
- .map_io = at91sam9x5_map_io,
- .register_clocks = at91sam9x5_register_clocks,
- .init = at91sam9x5_initialize,
--};
-+AT91_SOC_END
-diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
-index a9cfeb1..9c6d3d4 100644
---- a/arch/arm/mach-at91/soc.h
-+++ b/arch/arm/mach-at91/soc.h
-@@ -5,6 +5,7 @@
- */
-
- struct at91_init_soc {
-+ int builtin;
- unsigned int *default_irq_priority;
- void (*map_io)(void);
- void (*ioremap_registers)(void);
-@@ -22,9 +23,18 @@ extern struct at91_init_soc at91sam9rl_soc;
- extern struct at91_init_soc at91sam9x5_soc;
- extern struct at91_init_soc at91sam9n12_soc;
-
-+#define AT91_SOC_START(_name) \
-+struct at91_init_soc __initdata at91##_name##_soc \
-+ __used \
-+ = { \
-+ .builtin = 1, \
-+
-+#define AT91_SOC_END \
-+};
-+
- static inline int at91_soc_is_enabled(void)
- {
-- return at91_boot_soc.init != NULL;
-+ return at91_boot_soc.builtin;
- }
-
- #if !defined(CONFIG_SOC_AT91RM9200)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 76c442f41acf1572f18ca23d8a7755b5f292e979 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 6 Jul 2012 06:48:33 +0800
-Subject: ARM: at91: gpio: implement request
-
-Configure the pin as pio when requested.
-
-It is needed to configure the pin as PIO at "request time" when we are
-using DT. Indeed, the muxing via old AT91 API is not allowed anymore if
-we are using the plain gpiolib.
-
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Linus Walleij <linus.walleij@linaro.org>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/mach-at91/gpio.c | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
-diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
-index be42cf0..3b8f463 100644
---- a/arch/arm/mach-at91/gpio.c
-+++ b/arch/arm/mach-at91/gpio.c
-@@ -46,6 +46,7 @@ struct at91_gpio_chip {
-
- #define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
-
-+static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset);
- static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip);
- static void at91_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val);
- static int at91_gpiolib_get(struct gpio_chip *chip, unsigned offset);
-@@ -59,6 +60,7 @@ static int at91_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset);
- { \
- .chip = { \
- .label = name, \
-+ .request = at91_gpiolib_request, \
- .direction_input = at91_gpiolib_direction_input, \
- .direction_output = at91_gpiolib_direction_output, \
- .get = at91_gpiolib_get, \
-@@ -862,6 +864,16 @@ void __init at91_gpio_irq_setup(void)
- }
-
- /* gpiolib support */
-+static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset)
-+{
-+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-+ void __iomem *pio = at91_gpio->regbase;
-+ unsigned mask = 1 << offset;
-+
-+ __raw_writel(mask, pio + PIO_PER);
-+ return 0;
-+}
-+
- static int at91_gpiolib_direction_input(struct gpio_chip *chip,
- unsigned offset)
- {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 72453e8a1a0bb1784b533f53454b08081cf7ec5b Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Wed, 4 Jul 2012 17:20:46 +0800
-Subject: at91: regroup gpio and pinctrl under the same ranges
-
-Fix also the reg size as we have 512 bytes bank not 256 bytes per gpio/mux
-controller
-
-Acked-by: Linus Walleij <linus.walleij@linaro.org>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/boot/dts/at91sam9260.dtsi | 59 +++++++++++----------
- arch/arm/boot/dts/at91sam9263.dtsi | 94 +++++++++++++++++----------------
- arch/arm/boot/dts/at91sam9g45.dtsi | 103 ++++++++++++++++++++-----------------
- arch/arm/boot/dts/at91sam9n12.dtsi | 83 ++++++++++++++++--------------
- arch/arm/boot/dts/at91sam9x5.dtsi | 83 ++++++++++++++++--------------
- 5 files changed, 228 insertions(+), 194 deletions(-)
-
-diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
-index 0352bf8..e50261d 100644
---- a/arch/arm/boot/dts/at91sam9260.dtsi
-+++ b/arch/arm/boot/dts/at91sam9260.dtsi
-@@ -98,34 +98,41 @@
- interrupts = <26 4 0 27 4 0 28 4 0>;
- };
-
-- pioA: gpio@fffff400 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffff400 0x100>;
-- interrupts = <2 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
-+ pinctrl@fffff400 {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
-+ ranges = <0xfffff400 0xfffff400 0x600>;
-
-- pioB: gpio@fffff600 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffff600 0x100>;
-- interrupts = <3 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
-+ pioA: gpio@fffff400 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff400 0x200>;
-+ interrupts = <2 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-
-- pioC: gpio@fffff800 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffff800 0x100>;
-- interrupts = <4 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-+ pioB: gpio@fffff600 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff600 0x200>;
-+ interrupts = <3 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-+
-+ pioC: gpio@fffff800 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff800 0x200>;
-+ interrupts = <4 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
- };
-
- dbgu: serial@fffff200 {
-diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
-index 26ab452..45e5363 100644
---- a/arch/arm/boot/dts/at91sam9263.dtsi
-+++ b/arch/arm/boot/dts/at91sam9263.dtsi
-@@ -89,54 +89,60 @@
- reg = <0xfffffd10 0x10>;
- };
-
-- pioA: gpio@fffff200 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffff200 0x100>;
-- interrupts = <2 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
-+ pinctrl@fffff200 {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
-+ ranges = <0xfffff200 0xfffff200 0xa00>;
-
-- pioB: gpio@fffff400 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffff400 0x100>;
-- interrupts = <3 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
-+ pioA: gpio@fffff200 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff200 0x200>;
-+ interrupts = <2 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-
-- pioC: gpio@fffff600 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffff600 0x100>;
-- interrupts = <4 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
-+ pioB: gpio@fffff400 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff400 0x200>;
-+ interrupts = <3 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-
-- pioD: gpio@fffff800 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffff800 0x100>;
-- interrupts = <4 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
-+ pioC: gpio@fffff600 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff600 0x200>;
-+ interrupts = <4 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-
-- pioE: gpio@fffffa00 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffffa00 0x100>;
-- interrupts = <4 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-+ pioD: gpio@fffff800 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff800 0x200>;
-+ interrupts = <4 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-+
-+ pioE: gpio@fffffa00 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffffa00 0x200>;
-+ interrupts = <4 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
- };
-
- dbgu: serial@ffffee00 {
-diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
-index 948dc96..59a21c1 100644
---- a/arch/arm/boot/dts/at91sam9g45.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
-@@ -109,54 +109,61 @@
- #dma-cells = <1>;
- };
-
-- pioA: gpio@fffff200 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffff200 0x100>;
-- interrupts = <2 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
--
-- pioB: gpio@fffff400 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffff400 0x100>;
-- interrupts = <3 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
--
-- pioC: gpio@fffff600 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffff600 0x100>;
-- interrupts = <4 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
--
-- pioD: gpio@fffff800 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffff800 0x100>;
-- interrupts = <5 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
--
-- pioE: gpio@fffffa00 {
-- compatible = "atmel,at91rm9200-gpio";
-- reg = <0xfffffa00 0x100>;
-- interrupts = <5 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-+ pinctrl@fffff200 {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
-+ ranges = <0xfffff200 0xfffff200 0xa00>;
-+
-+ pioA: gpio@fffff200 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff200 0x200>;
-+ interrupts = <2 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-+
-+ pioB: gpio@fffff400 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff400 0x200>;
-+ interrupts = <3 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-+
-+ pioC: gpio@fffff600 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff600 0x200>;
-+ interrupts = <4 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-+
-+ pioD: gpio@fffff800 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffff800 0x200>;
-+ interrupts = <5 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-+
-+ pioE: gpio@fffffa00 {
-+ compatible = "atmel,at91rm9200-gpio";
-+ reg = <0xfffffa00 0x200>;
-+ interrupts = <5 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
- };
-
- dbgu: serial@ffffee00 {
-diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
-index 42b53bd..135ecef 100644
---- a/arch/arm/boot/dts/at91sam9n12.dtsi
-+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
-@@ -112,44 +112,51 @@
- #dma-cells = <1>;
- };
-
-- pioA: gpio@fffff400 {
-- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-- reg = <0xfffff400 0x100>;
-- interrupts = <2 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
--
-- pioB: gpio@fffff600 {
-- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-- reg = <0xfffff600 0x100>;
-- interrupts = <2 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
--
-- pioC: gpio@fffff800 {
-- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-- reg = <0xfffff800 0x100>;
-- interrupts = <3 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
--
-- pioD: gpio@fffffa00 {
-- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-- reg = <0xfffffa00 0x100>;
-- interrupts = <3 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-+ pinctrl@fffff400 {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
-+ ranges = <0xfffff400 0xfffff400 0x800>;
-+
-+ pioA: gpio@fffff400 {
-+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-+ reg = <0xfffff400 0x200>;
-+ interrupts = <2 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-+
-+ pioB: gpio@fffff600 {
-+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-+ reg = <0xfffff600 0x200>;
-+ interrupts = <2 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-+
-+ pioC: gpio@fffff800 {
-+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-+ reg = <0xfffff800 0x200>;
-+ interrupts = <3 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-+
-+ pioD: gpio@fffffa00 {
-+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-+ reg = <0xfffffa00 0x200>;
-+ interrupts = <3 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
- };
-
- dbgu: serial@fffff200 {
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index 027b9eb..df5f307 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -113,44 +113,51 @@
- #dma-cells = <1>;
- };
-
-- pioA: gpio@fffff400 {
-- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-- reg = <0xfffff400 0x100>;
-- interrupts = <2 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
--
-- pioB: gpio@fffff600 {
-- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-- reg = <0xfffff600 0x100>;
-- interrupts = <2 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
--
-- pioC: gpio@fffff800 {
-- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-- reg = <0xfffff800 0x100>;
-- interrupts = <3 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-- };
--
-- pioD: gpio@fffffa00 {
-- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-- reg = <0xfffffa00 0x100>;
-- interrupts = <3 4 1>;
-- #gpio-cells = <2>;
-- gpio-controller;
-- interrupt-controller;
-- #interrupt-cells = <2>;
-+ pinctrl@fffff200 {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
-+ ranges = <0xfffff400 0xfffff400 0x800>;
-+
-+ pioA: gpio@fffff400 {
-+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-+ reg = <0xfffff400 0x200>;
-+ interrupts = <2 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-+
-+ pioB: gpio@fffff600 {
-+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-+ reg = <0xfffff600 0x200>;
-+ interrupts = <2 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-+
-+ pioC: gpio@fffff800 {
-+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-+ reg = <0xfffff800 0x200>;
-+ interrupts = <3 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-+
-+ pioD: gpio@fffffa00 {
-+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-+ reg = <0xfffffa00 0x200>;
-+ interrupts = <3 4 1>;
-+ #gpio-cells = <2>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
- };
-
- dbgu: serial@fffff200 {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 4c602f8997780f19f61b8fdfb7e751ac04b2b850 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Sat, 14 Jul 2012 15:26:08 +0800
-Subject: arm: at91: at91sam9x5: fix gpio number per bank
-
-On the at91sam9x5 SoC series, GPIO banks B and D only have 19 and 22
-pins. So add a property to set this parameter.
-
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Linus Walleij <linus.walleij@linaro.org>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- .../devicetree/bindings/gpio/gpio_atmel.txt | 5 ++++
- arch/arm/boot/dts/at91sam9x5.dtsi | 2 ++
- arch/arm/mach-at91/gpio.c | 33 ++++++++++++++--------
- 3 files changed, 29 insertions(+), 11 deletions(-)
-
-diff --git a/Documentation/devicetree/bindings/gpio/gpio_atmel.txt b/Documentation/devicetree/bindings/gpio/gpio_atmel.txt
-index 66efc80..85f8c0d 100644
---- a/Documentation/devicetree/bindings/gpio/gpio_atmel.txt
-+++ b/Documentation/devicetree/bindings/gpio/gpio_atmel.txt
-@@ -9,6 +9,10 @@ Required properties:
- unused).
- - gpio-controller: Marks the device node as a GPIO controller.
-
-+optional properties:
-+- #gpio-lines: Number of gpio if absent 32.
-+
-+
- Example:
- pioA: gpio@fffff200 {
- compatible = "atmel,at91rm9200-gpio";
-@@ -16,5 +20,6 @@ Example:
- interrupts = <2 4>;
- #gpio-cells = <2>;
- gpio-controller;
-+ #gpio-lines = <19>;
- };
-
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index df5f307..4e61a5d 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -135,6 +135,7 @@
- interrupts = <2 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
-+ #gpio-lines = <19>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
-@@ -155,6 +156,7 @@
- interrupts = <3 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
-+ #gpio-lines = <22>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
-diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
-index 3b8f463..a34f0ed 100644
---- a/arch/arm/mach-at91/gpio.c
-+++ b/arch/arm/mach-at91/gpio.c
-@@ -33,6 +33,8 @@
-
- #include "generic.h"
-
-+#define MAX_NB_GPIO_PER_BANK 32
-+
- struct at91_gpio_chip {
- struct gpio_chip chip;
- struct at91_gpio_chip *next; /* Bank sharing same clock */
-@@ -56,7 +58,7 @@ static int at91_gpiolib_direction_input(struct gpio_chip *chip,
- unsigned offset);
- static int at91_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset);
-
--#define AT91_GPIO_CHIP(name, nr_gpio) \
-+#define AT91_GPIO_CHIP(name) \
- { \
- .chip = { \
- .label = name, \
-@@ -67,16 +69,16 @@ static int at91_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset);
- .set = at91_gpiolib_set, \
- .dbg_show = at91_gpiolib_dbg_show, \
- .to_irq = at91_gpiolib_to_irq, \
-- .ngpio = nr_gpio, \
-+ .ngpio = MAX_NB_GPIO_PER_BANK, \
- }, \
- }
-
- static struct at91_gpio_chip gpio_chip[] = {
-- AT91_GPIO_CHIP("pioA", 32),
-- AT91_GPIO_CHIP("pioB", 32),
-- AT91_GPIO_CHIP("pioC", 32),
-- AT91_GPIO_CHIP("pioD", 32),
-- AT91_GPIO_CHIP("pioE", 32),
-+ AT91_GPIO_CHIP("pioA"),
-+ AT91_GPIO_CHIP("pioB"),
-+ AT91_GPIO_CHIP("pioC"),
-+ AT91_GPIO_CHIP("pioD"),
-+ AT91_GPIO_CHIP("pioE"),
- };
-
- static int gpio_banks;
-@@ -91,7 +93,7 @@ static unsigned long at91_gpio_caps;
-
- static inline void __iomem *pin_to_controller(unsigned pin)
- {
-- pin /= 32;
-+ pin /= MAX_NB_GPIO_PER_BANK;
- if (likely(pin < gpio_banks))
- return gpio_chip[pin].regbase;
-
-@@ -100,7 +102,7 @@ static inline void __iomem *pin_to_controller(unsigned pin)
-
- static inline unsigned pin_to_mask(unsigned pin)
- {
-- return 1 << (pin % 32);
-+ return 1 << (pin % MAX_NB_GPIO_PER_BANK);
- }
-
-
-@@ -992,6 +994,7 @@ static void __init of_at91_gpio_init_one(struct device_node *np)
- {
- int alias_idx;
- struct at91_gpio_chip *at91_gpio;
-+ uint32_t ngpio;
-
- if (!np)
- return;
-@@ -1004,7 +1007,7 @@ static void __init of_at91_gpio_init_one(struct device_node *np)
- }
-
- at91_gpio = &gpio_chip[alias_idx];
-- at91_gpio->chip.base = alias_idx * at91_gpio->chip.ngpio;
-+ at91_gpio->chip.base = alias_idx * MAX_NB_GPIO_PER_BANK;
-
- at91_gpio->regbase = of_iomap(np, 0);
- if (!at91_gpio->regbase) {
-@@ -1024,6 +1027,14 @@ static void __init of_at91_gpio_init_one(struct device_node *np)
- if (of_device_is_compatible(np, "atmel,at91sam9x5-gpio"))
- at91_gpio_caps |= AT91_GPIO_CAP_PIO3;
-
-+ if (!of_property_read_u32(np, "#gpio-lines", &ngpio)) {
-+ if (ngpio >= MAX_NB_GPIO_PER_BANK)
-+ pr_err("at91_gpio.%d, gpio-nb >= %d failback to %d\n",
-+ alias_idx, MAX_NB_GPIO_PER_BANK, MAX_NB_GPIO_PER_BANK);
-+ else
-+ at91_gpio->chip.ngpio = ngpio;
-+ }
-+
- /* Setup clock */
- if (at91_gpio_setup_clk(alias_idx))
- goto ioremap_err;
-@@ -1061,7 +1072,7 @@ static void __init at91_gpio_init_one(int idx, u32 regbase, int pioc_hwirq)
- {
- struct at91_gpio_chip *at91_gpio = &gpio_chip[idx];
-
-- at91_gpio->chip.base = idx * at91_gpio->chip.ngpio;
-+ at91_gpio->chip.base = idx * MAX_NB_GPIO_PER_BANK;
- at91_gpio->pioc_hwirq = pioc_hwirq;
- at91_gpio->pioc_idx = idx;
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 51011b0c7102852db8fdc5617a971c3873ba5d7e Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Thu, 12 Jul 2012 23:35:02 +0800
-Subject: ARM: at91: add dummies pinctrl for non dt platform
-
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Linus Walleij <linus.walleij@linaro.org>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/mach-at91/setup.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/arch/arm/mach-at91/setup.c
-+++ b/arch/arm/mach-at91/setup.c
-@@ -10,6 +10,7 @@
- #include <linux/mm.h>
- #include <linux/pm.h>
- #include <linux/of_address.h>
-+#include <linux/pinctrl/machine.h>
-
- #include <asm/system_misc.h>
- #include <asm/mach/map.h>
-@@ -465,4 +466,6 @@ void __init at91_initialize(unsigned lon
- at91_boot_soc.register_clocks();
-
- at91_boot_soc.init();
-+
-+ pinctrl_provide_dummies();
- }
+++ /dev/null
-From a72342c1ce82d49f1c725078239d6e5d7dfad170 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Thu, 18 Oct 2012 17:48:34 +0200
-Subject: ARM: at91: add pinctrl support
-
-This is also include the gpio controller as the IP share both.
-Each soc will have to describe the SoC limitation and pin configuration via
-DT.
-
-This will allow to do not need to touch the C code when adding new SoC if the
-IP version is supported.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-
-Conflicts:
- arch/arm/mach-at91/board-dt.c
----
- Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt | 84
- arch/arm/Kconfig | 2
- arch/arm/mach-at91/board-dt.c | 2
- arch/arm/mach-at91/gpio.c | 165 -
- drivers/pinctrl/Kconfig | 9
- drivers/pinctrl/Makefile | 1
- drivers/pinctrl/pinctrl-at91.c | 1490 ++++++++++
- 7 files changed, 1591 insertions(+), 162 deletions(-)
- create mode 100644 Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
- create mode 100644 drivers/pinctrl/pinctrl-at91.c
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
-@@ -0,0 +1,84 @@
-+* Atmel AT91 Pinmux Controller
-+
-+The AT91 Pinmux Controler, enables the IC
-+to share one PAD to several functional blocks. The sharing is done by
-+multiplexing the PAD input/output signals. For each PAD there are up to
-+8 muxing options (called periph modes). Since different modules require
-+different PAD settings (like pull up, keeper, etc) the contoller controls
-+also the PAD settings parameters.
-+
-+Please refer to pinctrl-bindings.txt in this directory for details of the
-+common pinctrl bindings used by client devices, including the meaning of the
-+phrase "pin configuration node".
-+
-+Atmel AT91 pin configuration node is a node of a group of pins which can be
-+used for a specific device or function. This node represents both mux and config
-+of the pins in that group. The 'pins' selects the function mode(also named pin
-+mode) this pin can work on and the 'config' configures various pad settings
-+such as pull-up, multi drive, etc.
-+
-+Required properties for iomux controller:
-+- compatible: "atmel,at91rm9200-pinctrl"
-+- atmel,mux-mask: array of mask (periph per bank) to describe if a pin can be
-+ configured in this periph mode. All the periph and bank need to be describe.
-+
-+Required properties for pin configuration node:
-+- atmel,pins: 4 integers array, represents a group of pins mux and config
-+ setting. The format is atmel,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
-+ The PERIPH 0 means gpio.
-+
-+Bits used for CONFIG:
-+PULL_UP(1 << 0): indicate this pin need a pull up.
-+MULTIDRIVE(1 << 1): indicate this pin need to be configured as multidrive.
-+
-+NOTE:
-+Some requirements for using atmel,at91rm9200-pinctrl binding:
-+1. We have pin function node defined under at91 controller node to represent
-+ what pinmux functions this SoC supports.
-+2. The pin configuration node intends to work on a specific function should
-+ to be defined under that specific function node.
-+ The function node's name should represent well about what function
-+ this group of pins in this pin configuration node are working on.
-+3. The driver can use the function node's name and pin configuration node's
-+ name describe the pin function and group hierarchy.
-+ For example, Linux Iat91 pinctrl driver takes the function node's name
-+ as the function name and pin configuration node's name as group name to
-+ create the map table.
-+4. Each pin configuration node should have a phandle, devices can set pins
-+ configurations by referring to the phandle of that pin configuration node.
-+5. The gpio controller must be describe in the pinctrl simple-bus.
-+
-+Examples:
-+
-+pinctrl@fffff400 {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+ compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
-+ reg = <0xfffff400 0x600>;
-+
-+ atmel,mux-mask = <
-+ /* A B */
-+ 0xffffffff 0xffc00c3b /* pioA */
-+ 0xffffffff 0x7fff3ccf /* pioB */
-+ 0xffffffff 0x007fffff /* pioC */
-+ >;
-+
-+ /* shared pinctrl settings */
-+ dbgu {
-+ pinctrl_dbgu: dbgu-0 {
-+ atmel,pins =
-+ <1 14 0x1 0x0 /* PB14 periph A */
-+ 1 15 0x1 0x1>; /* PB15 periph with pullup */
-+ };
-+ };
-+};
-+
-+dbgu: serial@fffff200 {
-+ compatible = "atmel,at91sam9260-usart";
-+ reg = <0xfffff200 0x200>;
-+ interrupts = <1 4 7>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_dbgu>;
-+ status = "disabled";
-+};
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -349,6 +349,8 @@ config ARCH_AT91
- select CLKDEV_LOOKUP
- select IRQ_DOMAIN
- select NEED_MACH_IO_H if PCCARD
-+ select PINCTRL
-+ select PINCTRL_AT91 if USE_OF
- help
- This enables support for systems based on Atmel
- AT91RM9200 and AT91SAM9* processors.
---- a/arch/arm/mach-at91/board-dt.c
-+++ b/arch/arm/mach-at91/board-dt.c
-@@ -127,8 +127,6 @@ struct of_dev_auxdata at91_auxdata_looku
- static const struct of_device_id irq_of_match[] __initconst = {
-
- { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
-- { .compatible = "atmel,at91rm9200-gpio", .data = at91_gpio_of_irq_setup },
-- { .compatible = "atmel,at91sam9x5-gpio", .data = at91_gpio_of_irq_setup },
- { /*sentinel*/ }
- };
-
---- a/arch/arm/mach-at91/gpio.c
-+++ b/arch/arm/mach-at91/gpio.c
-@@ -23,8 +23,6 @@
- #include <linux/io.h>
- #include <linux/irqdomain.h>
- #include <linux/of_address.h>
--#include <linux/of_irq.h>
--#include <linux/of_gpio.h>
-
- #include <asm/mach/irq.h>
-
-@@ -717,80 +715,6 @@ postcore_initcall(at91_gpio_debugfs_init
- */
- static struct lock_class_key gpio_lock_class;
-
--#if defined(CONFIG_OF)
--static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq,
-- irq_hw_number_t hw)
--{
-- struct at91_gpio_chip *at91_gpio = h->host_data;
--
-- irq_set_lockdep_class(virq, &gpio_lock_class);
--
-- /*
-- * Can use the "simple" and not "edge" handler since it's
-- * shorter, and the AIC handles interrupts sanely.
-- */
-- irq_set_chip_and_handler(virq, &gpio_irqchip,
-- handle_simple_irq);
-- set_irq_flags(virq, IRQF_VALID);
-- irq_set_chip_data(virq, at91_gpio);
--
-- return 0;
--}
--
--static struct irq_domain_ops at91_gpio_ops = {
-- .map = at91_gpio_irq_map,
-- .xlate = irq_domain_xlate_twocell,
--};
--
--int __init at91_gpio_of_irq_setup(struct device_node *node,
-- struct device_node *parent)
--{
-- struct at91_gpio_chip *prev = NULL;
-- int alias_idx = of_alias_get_id(node, "gpio");
-- struct at91_gpio_chip *at91_gpio = &gpio_chip[alias_idx];
--
-- /* Setup proper .irq_set_type function */
-- if (has_pio3())
-- gpio_irqchip.irq_set_type = alt_gpio_irq_type;
-- else
-- gpio_irqchip.irq_set_type = gpio_irq_type;
--
-- /* Disable irqs of this PIO controller */
-- __raw_writel(~0, at91_gpio->regbase + PIO_IDR);
--
-- /* Setup irq domain */
-- at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio,
-- &at91_gpio_ops, at91_gpio);
-- if (!at91_gpio->domain)
-- panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n",
-- at91_gpio->pioc_idx);
--
-- /* Setup chained handler */
-- if (at91_gpio->pioc_idx)
-- prev = &gpio_chip[at91_gpio->pioc_idx - 1];
--
-- /* The toplevel handler handles one bank of GPIOs, except
-- * on some SoC it can handles up to three...
-- * We only set up the handler for the first of the list.
-- */
-- if (prev && prev->next == at91_gpio)
-- return 0;
--
-- at91_gpio->pioc_virq = irq_create_mapping(irq_find_host(parent),
-- at91_gpio->pioc_hwirq);
-- irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio);
-- irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler);
--
-- return 0;
--}
--#else
--int __init at91_gpio_of_irq_setup(struct device_node *node,
-- struct device_node *parent)
--{
-- return -EINVAL;
--}
--#endif
--
- /*
- * irqdomain initialization: pile up irqdomains on top of AIC range
- */
-@@ -989,85 +913,6 @@ err:
- return -EINVAL;
- }
-
--#ifdef CONFIG_OF_GPIO
--static void __init of_at91_gpio_init_one(struct device_node *np)
--{
-- int alias_idx;
-- struct at91_gpio_chip *at91_gpio;
-- uint32_t ngpio;
--
-- if (!np)
-- return;
--
-- alias_idx = of_alias_get_id(np, "gpio");
-- if (alias_idx >= MAX_GPIO_BANKS) {
-- pr_err("at91_gpio, failed alias idx(%d) > MAX_GPIO_BANKS(%d), ignoring.\n",
-- alias_idx, MAX_GPIO_BANKS);
-- return;
-- }
--
-- at91_gpio = &gpio_chip[alias_idx];
-- at91_gpio->chip.base = alias_idx * MAX_NB_GPIO_PER_BANK;
--
-- at91_gpio->regbase = of_iomap(np, 0);
-- if (!at91_gpio->regbase) {
-- pr_err("at91_gpio.%d, failed to map registers, ignoring.\n",
-- alias_idx);
-- return;
-- }
--
-- /* Get the interrupts property */
-- if (of_property_read_u32(np, "interrupts", &at91_gpio->pioc_hwirq)) {
-- pr_err("at91_gpio.%d, failed to get interrupts property, ignoring.\n",
-- alias_idx);
-- goto ioremap_err;
-- }
--
-- /* Get capabilities from compatibility property */
-- if (of_device_is_compatible(np, "atmel,at91sam9x5-gpio"))
-- at91_gpio_caps |= AT91_GPIO_CAP_PIO3;
--
-- if (!of_property_read_u32(np, "#gpio-lines", &ngpio)) {
-- if (ngpio >= MAX_NB_GPIO_PER_BANK)
-- pr_err("at91_gpio.%d, gpio-nb >= %d failback to %d\n",
-- alias_idx, MAX_NB_GPIO_PER_BANK, MAX_NB_GPIO_PER_BANK);
-- else
-- at91_gpio->chip.ngpio = ngpio;
-- }
--
-- /* Setup clock */
-- if (at91_gpio_setup_clk(alias_idx))
-- goto ioremap_err;
--
-- at91_gpio->chip.of_node = np;
-- gpio_banks = max(gpio_banks, alias_idx + 1);
-- at91_gpio->pioc_idx = alias_idx;
-- return;
--
--ioremap_err:
-- iounmap(at91_gpio->regbase);
--}
--
--static int __init of_at91_gpio_init(void)
--{
-- struct device_node *np = NULL;
--
-- /*
-- * This isn't ideal, but it gets things hooked up until this
-- * driver is converted into a platform_device
-- */
-- for_each_compatible_node(np, NULL, "atmel,at91rm9200-gpio")
-- of_at91_gpio_init_one(np);
--
-- return gpio_banks > 0 ? 0 : -EINVAL;
--}
--#else
--static int __init of_at91_gpio_init(void)
--{
-- return -EINVAL;
--}
--#endif
--
- static void __init at91_gpio_init_one(int idx, u32 regbase, int pioc_hwirq)
- {
- struct at91_gpio_chip *at91_gpio = &gpio_chip[idx];
-@@ -1102,11 +947,11 @@ void __init at91_gpio_init(struct at91_g
-
- BUG_ON(nr_banks > MAX_GPIO_BANKS);
-
-- if (of_at91_gpio_init() < 0) {
-- /* No GPIO controller found in device tree */
-- for (i = 0; i < nr_banks; i++)
-- at91_gpio_init_one(i, data[i].regbase, data[i].id);
-- }
-+ if (of_have_populated_dt())
-+ return;
-+
-+ for (i = 0; i < nr_banks; i++)
-+ at91_gpio_init_one(i, data[i].regbase, data[i].id);
-
- for (i = 0; i < gpio_banks; i++) {
- at91_gpio = &gpio_chip[i];
---- a/drivers/pinctrl/Kconfig
-+++ b/drivers/pinctrl/Kconfig
-@@ -26,6 +26,15 @@ config DEBUG_PINCTRL
- help
- Say Y here to add some extra checks and diagnostics to PINCTRL calls.
-
-+config PINCTRL_AT91
-+ bool "AT91 pinctrl driver"
-+ depends on OF
-+ depends on ARCH_AT91
-+ select PINMUX
-+ select PINCONF
-+ help
-+ Say Y here to enable the at91 pinctrl driver
-+
- config PINCTRL_PXA3xx
- bool
- select PINMUX
---- a/drivers/pinctrl/Makefile
-+++ b/drivers/pinctrl/Makefile
-@@ -9,6 +9,7 @@ ifeq ($(CONFIG_OF),y)
- obj-$(CONFIG_PINCTRL) += devicetree.o
- endif
- obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
-+obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
- obj-$(CONFIG_PINCTRL_PXA3xx) += pinctrl-pxa3xx.o
- obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o
- obj-$(CONFIG_PINCTRL_PXA168) += pinctrl-pxa168.o
---- /dev/null
-+++ b/drivers/pinctrl/pinctrl-at91.c
-@@ -0,0 +1,1490 @@
-+/*
-+ * at91 pinctrl driver based on at91 pinmux core
-+ *
-+ * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Under GPLv2 only
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/err.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/of_address.h>
-+#include <linux/of_irq.h>
-+#include <linux/slab.h>
-+#include <linux/interrupt.h>
-+#include <linux/irq.h>
-+#include <linux/irqdomain.h>
-+#include <linux/io.h>
-+#include <linux/gpio.h>
-+#include <linux/irqdomain.h>
-+#include <linux/pinctrl/machine.h>
-+#include <linux/pinctrl/pinconf.h>
-+#include <linux/pinctrl/pinctrl.h>
-+#include <linux/pinctrl/pinmux.h>
-+/* Since we request GPIOs from ourself */
-+#include <linux/pinctrl/consumer.h>
-+
-+#include <asm/mach/irq.h>
-+
-+#include <mach/hardware.h>
-+#include <mach/at91_pio.h>
-+
-+#include "core.h"
-+
-+#define MAX_NB_GPIO_PER_BANK 32
-+
-+struct at91_pinctrl_mux_ops;
-+
-+struct at91_gpio_chip {
-+ struct gpio_chip chip;
-+ struct pinctrl_gpio_range range;
-+ struct at91_gpio_chip *next; /* Bank sharing same clock */
-+ int pioc_hwirq; /* PIO bank interrupt identifier on AIC */
-+ int pioc_virq; /* PIO bank Linux virtual interrupt */
-+ int pioc_idx; /* PIO bank index */
-+ void __iomem *regbase; /* PIO bank virtual address */
-+ struct clk *clock; /* associated clock */
-+ struct irq_domain *domain; /* associated irq domain */
-+ struct at91_pinctrl_mux_ops *ops; /* ops */
-+};
-+
-+#define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
-+
-+static struct at91_gpio_chip *gpio_chips[MAX_GPIO_BANKS];
-+
-+static int gpio_banks;
-+
-+#define PULL_UP (0 << 1)
-+#define MULTI_DRIVE (1 << 1)
-+
-+/**
-+ * struct at91_pmx_func - describes AT91 pinmux functions
-+ * @name: the name of this specific function
-+ * @groups: corresponding pin groups
-+ * @ngroups: the number of groups
-+ */
-+struct at91_pmx_func {
-+ const char *name;
-+ const char **groups;
-+ unsigned ngroups;
-+};
-+
-+enum at91_mux {
-+ AT91_MUX_GPIO = 0,
-+ AT91_MUX_PERIPH_A = 1,
-+ AT91_MUX_PERIPH_B = 2,
-+ AT91_MUX_PERIPH_C = 3,
-+ AT91_MUX_PERIPH_D = 4,
-+};
-+
-+/**
-+ * struct at91_pmx_pin - describes an At91 pin mux
-+ * @bank: the bank of the pin
-+ * @pin: the pin number in the @bank
-+ * @mux: the mux mode : gpio or periph_x of the pin i.e. alternate function.
-+ * @conf: the configuration of the pin: PULL_UP, MULTIDRIVE etc...
-+ */
-+struct at91_pmx_pin {
-+ uint32_t bank;
-+ uint32_t pin;
-+ enum at91_mux mux;
-+ unsigned long conf;
-+};
-+
-+/**
-+ * struct at91_pin_group - describes an At91 pin group
-+ * @name: the name of this specific pin group
-+ * @pins_conf: the mux mode for each pin in this group. The size of this
-+ * array is the same as pins.
-+ * @pins: an array of discrete physical pins used in this group, taken
-+ * from the driver-local pin enumeration space
-+ * @npins: the number of pins in this group array, i.e. the number of
-+ * elements in .pins so we can iterate over that array
-+ */
-+struct at91_pin_group {
-+ const char *name;
-+ struct at91_pmx_pin *pins_conf;
-+ unsigned int *pins;
-+ unsigned npins;
-+};
-+
-+/**
-+ * struct at91_pinctrl_mux_ops - describes an At91 mux ops group
-+ * on new IP with support for periph C and D the way to mux in
-+ * periph A and B has changed
-+ * So provide the right call back
-+ * if not present means the IP does not support it
-+ * @get_periph: return the periph mode configured
-+ * @mux_A_periph: mux as periph A
-+ * @mux_B_periph: mux as periph B
-+ * @mux_C_periph: mux as periph C
-+ * @mux_D_periph: mux as periph D
-+ * @irq_type: return irq type
-+ */
-+struct at91_pinctrl_mux_ops {
-+ enum at91_mux (*get_periph)(void __iomem *pio, unsigned mask);
-+ void (*mux_A_periph)(void __iomem *pio, unsigned mask);
-+ void (*mux_B_periph)(void __iomem *pio, unsigned mask);
-+ void (*mux_C_periph)(void __iomem *pio, unsigned mask);
-+ void (*mux_D_periph)(void __iomem *pio, unsigned mask);
-+ /* irq */
-+ int (*irq_type)(struct irq_data *d, unsigned type);
-+};
-+
-+static int gpio_irq_type(struct irq_data *d, unsigned type);
-+static int alt_gpio_irq_type(struct irq_data *d, unsigned type);
-+
-+struct at91_pinctrl {
-+ struct device *dev;
-+ struct pinctrl_dev *pctl;
-+
-+ int nbanks;
-+
-+ uint32_t *mux_mask;
-+ int nmux;
-+
-+ struct at91_pmx_func *functions;
-+ int nfunctions;
-+
-+ struct at91_pin_group *groups;
-+ int ngroups;
-+
-+ struct at91_pinctrl_mux_ops *ops;
-+};
-+
-+static const inline struct at91_pin_group *at91_pinctrl_find_group_by_name(
-+ const struct at91_pinctrl *info,
-+ const char *name)
-+{
-+ const struct at91_pin_group *grp = NULL;
-+ int i;
-+
-+ for (i = 0; i < info->ngroups; i++) {
-+ if (strcmp(info->groups[i].name, name))
-+ continue;
-+
-+ grp = &info->groups[i];
-+ dev_dbg(info->dev, "%s: %d 0:%d\n", name, grp->npins, grp->pins[0]);
-+ break;
-+ }
-+
-+ return grp;
-+}
-+
-+static int at91_get_groups_count(struct pinctrl_dev *pctldev)
-+{
-+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
-+
-+ return info->ngroups;
-+}
-+
-+static const char *at91_get_group_name(struct pinctrl_dev *pctldev,
-+ unsigned selector)
-+{
-+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
-+
-+ return info->groups[selector].name;
-+}
-+
-+static int at91_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
-+ const unsigned **pins,
-+ unsigned *npins)
-+{
-+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
-+
-+ if (selector >= info->ngroups)
-+ return -EINVAL;
-+
-+ *pins = info->groups[selector].pins;
-+ *npins = info->groups[selector].npins;
-+
-+ return 0;
-+}
-+
-+static void at91_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
-+ unsigned offset)
-+{
-+ seq_printf(s, "%s", dev_name(pctldev->dev));
-+}
-+
-+static int at91_dt_node_to_map(struct pinctrl_dev *pctldev,
-+ struct device_node *np,
-+ struct pinctrl_map **map, unsigned *num_maps)
-+{
-+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
-+ const struct at91_pin_group *grp;
-+ struct pinctrl_map *new_map;
-+ struct device_node *parent;
-+ int map_num = 1;
-+ int i;
-+ struct at91_pmx_pin *pin;
-+
-+ /*
-+ * first find the group of this node and check if we need create
-+ * config maps for pins
-+ */
-+ grp = at91_pinctrl_find_group_by_name(info, np->name);
-+ if (!grp) {
-+ dev_err(info->dev, "unable to find group for node %s\n",
-+ np->name);
-+ return -EINVAL;
-+ }
-+
-+ map_num += grp->npins;
-+ new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num, GFP_KERNEL);
-+ if (!new_map)
-+ return -ENOMEM;
-+
-+ *map = new_map;
-+ *num_maps = map_num;
-+
-+ /* create mux map */
-+ parent = of_get_parent(np);
-+ if (!parent) {
-+ kfree(new_map);
-+ return -EINVAL;
-+ }
-+ new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
-+ new_map[0].data.mux.function = parent->name;
-+ new_map[0].data.mux.group = np->name;
-+ of_node_put(parent);
-+
-+ /* create config map */
-+ new_map++;
-+ for (i = 0; i < grp->npins; i++) {
-+ pin = &grp->pins_conf[i];
-+
-+ new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
-+ new_map[i].data.configs.group_or_pin =
-+ pin_get_name(pctldev, grp->pins[i]);
-+ new_map[i].data.configs.configs = &grp->pins_conf[i].conf;
-+ new_map[i].data.configs.num_configs = 1;
-+ }
-+
-+ dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
-+ (*map)->data.mux.function, (*map)->data.mux.group, map_num);
-+
-+ return 0;
-+}
-+
-+static void at91_dt_free_map(struct pinctrl_dev *pctldev,
-+ struct pinctrl_map *map, unsigned num_maps)
-+{
-+}
-+
-+static struct pinctrl_ops at91_pctrl_ops = {
-+ .get_groups_count = at91_get_groups_count,
-+ .get_group_name = at91_get_group_name,
-+ .get_group_pins = at91_get_group_pins,
-+ .pin_dbg_show = at91_pin_dbg_show,
-+ .dt_node_to_map = at91_dt_node_to_map,
-+ .dt_free_map = at91_dt_free_map,
-+};
-+
-+static void __iomem * pin_to_controller(struct at91_pinctrl *info,
-+ unsigned int bank)
-+{
-+ return gpio_chips[bank]->regbase;
-+}
-+
-+static inline int pin_to_bank(unsigned pin)
-+{
-+ return pin /= MAX_NB_GPIO_PER_BANK;
-+}
-+
-+static unsigned pin_to_mask(unsigned int pin)
-+{
-+ return 1 << pin;
-+}
-+
-+static void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask)
-+{
-+ writel_relaxed(mask, pio + PIO_IDR);
-+}
-+
-+static unsigned at91_mux_get_pullup(void __iomem *pio, unsigned pin)
-+{
-+ return (readl_relaxed(pio + PIO_PUSR) >> pin) & 0x1;
-+}
-+
-+static void at91_mux_set_pullup(void __iomem *pio, unsigned mask, bool on)
-+{
-+ writel_relaxed(mask, pio + (on ? PIO_PUER : PIO_PUDR));
-+}
-+
-+static unsigned at91_mux_get_multidrive(void __iomem *pio, unsigned pin)
-+{
-+ return (readl_relaxed(pio + PIO_MDSR) >> pin) & 0x1;
-+}
-+
-+static void at91_mux_set_multidrive(void __iomem *pio, unsigned mask, bool on)
-+{
-+ writel_relaxed(mask, pio + (on ? PIO_MDER : PIO_MDDR));
-+}
-+
-+static void at91_mux_set_A_periph(void __iomem *pio, unsigned mask)
-+{
-+ writel_relaxed(mask, pio + PIO_ASR);
-+}
-+
-+static void at91_mux_set_B_periph(void __iomem *pio, unsigned mask)
-+{
-+ writel_relaxed(mask, pio + PIO_BSR);
-+}
-+
-+static void at91_mux_pio3_set_A_periph(void __iomem *pio, unsigned mask)
-+{
-+
-+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) & ~mask,
-+ pio + PIO_ABCDSR1);
-+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) & ~mask,
-+ pio + PIO_ABCDSR2);
-+}
-+
-+static void at91_mux_pio3_set_B_periph(void __iomem *pio, unsigned mask)
-+{
-+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) | mask,
-+ pio + PIO_ABCDSR1);
-+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) & ~mask,
-+ pio + PIO_ABCDSR2);
-+}
-+
-+static void at91_mux_pio3_set_C_periph(void __iomem *pio, unsigned mask)
-+{
-+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) & ~mask, pio + PIO_ABCDSR1);
-+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
-+}
-+
-+static void at91_mux_pio3_set_D_periph(void __iomem *pio, unsigned mask)
-+{
-+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) | mask, pio + PIO_ABCDSR1);
-+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
-+}
-+
-+static enum at91_mux at91_mux_pio3_get_periph(void __iomem *pio, unsigned mask)
-+{
-+ unsigned select;
-+
-+ if (readl_relaxed(pio + PIO_PSR) & mask)
-+ return AT91_MUX_GPIO;
-+
-+ select = !!(readl_relaxed(pio + PIO_ABCDSR1) & mask);
-+ select |= (!!(readl_relaxed(pio + PIO_ABCDSR2) & mask) << 1);
-+
-+ return select + 1;
-+}
-+
-+static enum at91_mux at91_mux_get_periph(void __iomem *pio, unsigned mask)
-+{
-+ unsigned select;
-+
-+ if (readl_relaxed(pio + PIO_PSR) & mask)
-+ return AT91_MUX_GPIO;
-+
-+ select = readl_relaxed(pio + PIO_ABSR) & mask;
-+
-+ return select + 1;
-+}
-+
-+static struct at91_pinctrl_mux_ops at91rm9200_ops = {
-+ .get_periph = at91_mux_get_periph,
-+ .mux_A_periph = at91_mux_set_A_periph,
-+ .mux_B_periph = at91_mux_set_B_periph,
-+ .irq_type = gpio_irq_type,
-+};
-+
-+static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
-+ .get_periph = at91_mux_pio3_get_periph,
-+ .mux_A_periph = at91_mux_pio3_set_A_periph,
-+ .mux_B_periph = at91_mux_pio3_set_B_periph,
-+ .mux_C_periph = at91_mux_pio3_set_C_periph,
-+ .mux_D_periph = at91_mux_pio3_set_D_periph,
-+ .irq_type = alt_gpio_irq_type,
-+};
-+
-+static void at91_pin_dbg(const struct device *dev, const struct at91_pmx_pin *pin)
-+{
-+ if (pin->mux) {
-+ dev_dbg(dev, "pio%c%d configured as periph%c with conf = 0x%lu\n",
-+ pin->bank + 'A', pin->pin, pin->mux - 1 + 'A', pin->conf);
-+ } else {
-+ dev_dbg(dev, "pio%c%d configured as gpio with conf = 0x%lu\n",
-+ pin->bank + 'A', pin->pin, pin->conf);
-+ }
-+}
-+
-+static int pin_check_config(struct at91_pinctrl *info, const char* name,
-+ int index, const struct at91_pmx_pin *pin)
-+{
-+ int mux;
-+
-+ /* check if it's a valid config */
-+ if (pin->bank >= info->nbanks) {
-+ dev_err(info->dev, "%s: pin conf %d bank_id %d >= nbanks %d\n",
-+ name, index, pin->bank, info->nbanks);
-+ return -EINVAL;
-+ }
-+
-+ if (pin->pin >= MAX_NB_GPIO_PER_BANK) {
-+ dev_err(info->dev, "%s: pin conf %d pin_bank_id %d >= %d\n",
-+ name, index, pin->pin, MAX_NB_GPIO_PER_BANK);
-+ return -EINVAL;
-+ }
-+
-+ if (!pin->mux)
-+ return 0;
-+
-+ mux = pin->mux - 1;
-+
-+ if (mux >= info->nmux) {
-+ dev_err(info->dev, "%s: pin conf %d mux_id %d >= nmux %d\n",
-+ name, index, mux, info->nmux);
-+ return -EINVAL;
-+ }
-+
-+ if (!(info->mux_mask[pin->bank * info->nmux + mux] & 1 << pin->pin)) {
-+ dev_err(info->dev, "%s: pin conf %d mux_id %d not supported for pio%c%d\n",
-+ name, index, mux, pin->bank + 'A', pin->pin);
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static void at91_mux_gpio_disable(void __iomem *pio, unsigned mask)
-+{
-+ writel_relaxed(mask, pio + PIO_PDR);
-+}
-+
-+static void at91_mux_gpio_enable(void __iomem *pio, unsigned mask, bool input)
-+{
-+ writel_relaxed(mask, pio + PIO_PER);
-+ writel_relaxed(mask, pio + (input ? PIO_ODR : PIO_OER));
-+}
-+
-+static int at91_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
-+ unsigned group)
-+{
-+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
-+ const struct at91_pmx_pin *pins_conf = info->groups[group].pins_conf;
-+ const struct at91_pmx_pin *pin;
-+ uint32_t npins = info->groups[group].npins;
-+ int i, ret;
-+ unsigned mask;
-+ void __iomem *pio;
-+
-+ dev_dbg(info->dev, "enable function %s group %s\n",
-+ info->functions[selector].name, info->groups[group].name);
-+
-+ /* first check that all the pins of the group are valid with a valid
-+ * paramter */
-+ for (i = 0; i < npins; i++) {
-+ pin = &pins_conf[i];
-+ ret = pin_check_config(info, info->groups[group].name, i, pin);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ for (i = 0; i < npins; i++) {
-+ pin = &pins_conf[i];
-+ at91_pin_dbg(info->dev, pin);
-+ pio = pin_to_controller(info, pin->bank);
-+ mask = pin_to_mask(pin->pin);
-+ at91_mux_disable_interrupt(pio, mask);
-+ switch(pin->mux) {
-+ case AT91_MUX_GPIO:
-+ at91_mux_gpio_enable(pio, mask, 1);
-+ break;
-+ case AT91_MUX_PERIPH_A:
-+ info->ops->mux_A_periph(pio, mask);
-+ break;
-+ case AT91_MUX_PERIPH_B:
-+ info->ops->mux_B_periph(pio, mask);
-+ break;
-+ case AT91_MUX_PERIPH_C:
-+ if (!info->ops->mux_C_periph)
-+ return -EINVAL;
-+ info->ops->mux_C_periph(pio, mask);
-+ break;
-+ case AT91_MUX_PERIPH_D:
-+ if (!info->ops->mux_D_periph)
-+ return -EINVAL;
-+ info->ops->mux_D_periph(pio, mask);
-+ break;
-+ }
-+ if (pin->mux)
-+ at91_mux_gpio_disable(pio, mask);
-+ }
-+
-+ return 0;
-+}
-+
-+static void at91_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
-+ unsigned group)
-+{
-+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
-+ const struct at91_pmx_pin *pins_conf = info->groups[group].pins_conf;
-+ const struct at91_pmx_pin *pin;
-+ uint32_t npins = info->groups[group].npins;
-+ int i;
-+ unsigned mask;
-+ void __iomem *pio;
-+
-+ for (i = 0; i < npins; i++) {
-+ pin = &pins_conf[i];
-+ at91_pin_dbg(info->dev, pin);
-+ pio = pin_to_controller(info, pin->bank);
-+ mask = pin_to_mask(pin->pin);
-+ at91_mux_gpio_enable(pio, mask, 1);
-+ }
-+}
-+
-+static int at91_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
-+{
-+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
-+
-+ return info->nfunctions;
-+}
-+
-+static const char *at91_pmx_get_func_name(struct pinctrl_dev *pctldev,
-+ unsigned selector)
-+{
-+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
-+
-+ return info->functions[selector].name;
-+}
-+
-+static int at91_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
-+ const char * const **groups,
-+ unsigned * const num_groups)
-+{
-+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
-+
-+ *groups = info->functions[selector].groups;
-+ *num_groups = info->functions[selector].ngroups;
-+
-+ return 0;
-+}
-+
-+int at91_gpio_request_enable(struct pinctrl_dev *pctldev,
-+ struct pinctrl_gpio_range *range,
-+ unsigned offset)
-+{
-+ struct at91_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-+ struct at91_gpio_chip *at91_chip;
-+ struct gpio_chip *chip;
-+ unsigned mask;
-+
-+ if (!range) {
-+ dev_err(npct->dev, "invalid range\n");
-+ return -EINVAL;
-+ }
-+ if (!range->gc) {
-+ dev_err(npct->dev, "missing GPIO chip in range\n");
-+ return -EINVAL;
-+ }
-+ chip = range->gc;
-+ at91_chip = container_of(chip, struct at91_gpio_chip, chip);
-+
-+ dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset);
-+
-+ mask = 1 << (offset - chip->base);
-+
-+ dev_dbg(npct->dev, "enable pin %u as PIO%c%d 0x%x\n",
-+ offset, 'A' + range->id, offset - chip->base, mask);
-+
-+ writel_relaxed(mask, at91_chip->regbase + PIO_PER);
-+
-+ return 0;
-+}
-+
-+void at91_gpio_disable_free(struct pinctrl_dev *pctldev,
-+ struct pinctrl_gpio_range *range,
-+ unsigned offset)
-+{
-+ struct at91_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
-+
-+ dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset);
-+ /* Set the pin to some default state, GPIO is usually default */
-+}
-+
-+static struct pinmux_ops at91_pmx_ops = {
-+ .get_functions_count = at91_pmx_get_funcs_count,
-+ .get_function_name = at91_pmx_get_func_name,
-+ .get_function_groups = at91_pmx_get_groups,
-+ .enable = at91_pmx_enable,
-+ .disable = at91_pmx_disable,
-+ .gpio_request_enable = at91_gpio_request_enable,
-+ .gpio_disable_free = at91_gpio_disable_free,
-+};
-+
-+static int at91_pinconf_get(struct pinctrl_dev *pctldev,
-+ unsigned pin_id, unsigned long *config)
-+{
-+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
-+ void __iomem *pio;
-+ unsigned pin;
-+
-+ dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, *config);
-+ pio = pin_to_controller(info, pin_to_bank(pin_id));
-+ pin = pin_id % MAX_NB_GPIO_PER_BANK;
-+
-+ if (at91_mux_get_multidrive(pio, pin))
-+ *config |= MULTI_DRIVE;
-+
-+ if (at91_mux_get_pullup(pio, pin))
-+ *config |= PULL_UP;
-+
-+ return 0;
-+}
-+
-+static int at91_pinconf_set(struct pinctrl_dev *pctldev,
-+ unsigned pin_id, unsigned long config)
-+{
-+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
-+ unsigned mask;
-+ void __iomem *pio;
-+
-+ dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, config);
-+ pio = pin_to_controller(info, pin_to_bank(pin_id));
-+ mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK);
-+
-+ at91_mux_set_pullup(pio, mask, config & PULL_UP);
-+ at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE);
-+ return 0;
-+}
-+
-+static void at91_pinconf_dbg_show(struct pinctrl_dev *pctldev,
-+ struct seq_file *s, unsigned pin_id)
-+{
-+
-+}
-+
-+static void at91_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
-+ struct seq_file *s, unsigned group)
-+{
-+}
-+
-+struct pinconf_ops at91_pinconf_ops = {
-+ .pin_config_get = at91_pinconf_get,
-+ .pin_config_set = at91_pinconf_set,
-+ .pin_config_dbg_show = at91_pinconf_dbg_show,
-+ .pin_config_group_dbg_show = at91_pinconf_group_dbg_show,
-+};
-+
-+static struct pinctrl_desc at91_pinctrl_desc = {
-+ .pctlops = &at91_pctrl_ops,
-+ .pmxops = &at91_pmx_ops,
-+ .confops = &at91_pinconf_ops,
-+ .owner = THIS_MODULE,
-+};
-+
-+static const char *gpio_compat = "atmel,at91rm9200-gpio";
-+
-+static void __devinit at91_pinctrl_child_count(struct at91_pinctrl *info,
-+ struct device_node *np)
-+{
-+ struct device_node *child;
-+
-+ for_each_child_of_node(np, child) {
-+ if (of_device_is_compatible(child, gpio_compat)) {
-+ info->nbanks++;
-+ } else {
-+ info->nfunctions++;
-+ info->ngroups += of_get_child_count(child);
-+ }
-+ }
-+}
-+
-+static int __devinit at91_pinctrl_mux_mask(struct at91_pinctrl *info,
-+ struct device_node *np)
-+{
-+ int ret = 0;
-+ int size;
-+ const const __be32 *list;
-+
-+ list = of_get_property(np, "atmel,mux-mask", &size);
-+ if (!list) {
-+ dev_err(info->dev, "can not read the mux-mask of %d\n", size);
-+ return -EINVAL;
-+ }
-+
-+ size /= sizeof(*list);
-+ if (!size || size % info->nbanks) {
-+ dev_err(info->dev, "wrong mux mask array should be by %d\n", info->nbanks);
-+ return -EINVAL;
-+ }
-+ info->nmux = size / info->nbanks;
-+
-+ info->mux_mask = devm_kzalloc(info->dev, sizeof(u32) * size, GFP_KERNEL);
-+ if (!info->mux_mask) {
-+ dev_err(info->dev, "could not alloc mux_mask\n");
-+ return -ENOMEM;
-+ }
-+
-+ ret = of_property_read_u32_array(np, "atmel,mux-mask",
-+ info->mux_mask, size);
-+ if (ret)
-+ dev_err(info->dev, "can not read the mux-mask of %d\n", size);
-+ return ret;
-+}
-+
-+static int __devinit at91_pinctrl_parse_groups(struct device_node *np,
-+ struct at91_pin_group *grp,
-+ struct at91_pinctrl *info,
-+ u32 index)
-+{
-+ struct at91_pmx_pin *pin;
-+ int size;
-+ const const __be32 *list;
-+ int i, j;
-+
-+ dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
-+
-+ /* Initialise group */
-+ grp->name = np->name;
-+
-+ /*
-+ * the binding format is fsl,pins = <bank pin mux CONFIG ...>,
-+ * do sanity check and calculate pins number
-+ */
-+ list = of_get_property(np, "atmel,pins", &size);
-+ /* we do not check return since it's safe node passed down */
-+ size /= sizeof(*list);
-+ if (!size || size % 4) {
-+ dev_err(info->dev, "wrong pins number or pins and configs should be by 4\n");
-+ return -EINVAL;
-+ }
-+
-+ grp->npins = size / 4;
-+ pin = grp->pins_conf = devm_kzalloc(info->dev, grp->npins * sizeof(struct at91_pmx_pin),
-+ GFP_KERNEL);
-+ grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
-+ GFP_KERNEL);
-+ if (!grp->pins_conf || !grp->pins)
-+ return -ENOMEM;
-+
-+ for (i = 0, j = 0; i < size; i += 4, j++) {
-+ pin->bank = be32_to_cpu(*list++);
-+ pin->pin = be32_to_cpu(*list++);
-+ grp->pins[j] = pin->bank * MAX_NB_GPIO_PER_BANK + pin->pin;
-+ pin->mux = be32_to_cpu(*list++);
-+ pin->conf = be32_to_cpu(*list++);
-+
-+ at91_pin_dbg(info->dev, pin);
-+ pin++;
-+ }
-+
-+ return 0;
-+}
-+
-+static int __devinit at91_pinctrl_parse_functions(struct device_node *np,
-+ struct at91_pinctrl *info, u32 index)
-+{
-+ struct device_node *child;
-+ struct at91_pmx_func *func;
-+ struct at91_pin_group *grp;
-+ int ret;
-+ static u32 grp_index;
-+ u32 i = 0;
-+
-+ dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
-+
-+ func = &info->functions[index];
-+
-+ /* Initialise function */
-+ func->name = np->name;
-+ func->ngroups = of_get_child_count(np);
-+ if (func->ngroups <= 0) {
-+ dev_err(info->dev, "no groups defined\n");
-+ return -EINVAL;
-+ }
-+ func->groups = devm_kzalloc(info->dev,
-+ func->ngroups * sizeof(char *), GFP_KERNEL);
-+ if (!func->groups)
-+ return -ENOMEM;
-+
-+ for_each_child_of_node(np, child) {
-+ func->groups[i] = child->name;
-+ grp = &info->groups[grp_index++];
-+ ret = at91_pinctrl_parse_groups(child, grp, info, i++);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static struct of_device_id at91_pinctrl_of_match[] __devinitdata = {
-+ { .compatible = "atmel,at91rm9200-pinctrl", .data = &at91rm9200_ops },
-+ { .compatible = "atmel,at91sam9x5-pinctrl", .data = &at91sam9x5_ops },
-+ { /* sentinel */ }
-+};
-+
-+static int __devinit at91_pinctrl_probe_dt(struct platform_device *pdev,
-+ struct at91_pinctrl *info)
-+{
-+ int ret = 0;
-+ int i, j;
-+ uint32_t *tmp;
-+ struct device_node *np = pdev->dev.of_node;
-+ struct device_node *child;
-+
-+ if (!np)
-+ return -ENODEV;
-+
-+ info->dev = &pdev->dev;
-+ info->ops =
-+ of_match_device(at91_pinctrl_of_match, &pdev->dev)->data;
-+ at91_pinctrl_child_count(info, np);
-+
-+ if (info->nbanks < 1) {
-+ dev_err(&pdev->dev, "you need to specify atleast one gpio-controller\n");
-+ return -EINVAL;
-+ }
-+
-+ ret = at91_pinctrl_mux_mask(info, np);
-+ if (ret)
-+ return ret;
-+
-+ dev_dbg(&pdev->dev, "nmux = %d\n", info->nmux);
-+
-+ dev_dbg(&pdev->dev, "mux-mask\n");
-+ tmp = info->mux_mask;
-+ for (i = 0; i < info->nbanks; i++) {
-+ for (j = 0; j < info->nmux; j++, tmp++) {
-+ dev_dbg(&pdev->dev, "%d:%d\t0x%x\n", i, j, tmp[0]);
-+ }
-+ }
-+
-+ dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
-+ dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
-+ info->functions = devm_kzalloc(&pdev->dev, info->nfunctions * sizeof(struct at91_pmx_func),
-+ GFP_KERNEL);
-+ if (!info->functions)
-+ return -ENOMEM;
-+
-+ info->groups = devm_kzalloc(&pdev->dev, info->ngroups * sizeof(struct at91_pin_group),
-+ GFP_KERNEL);
-+ if (!info->groups)
-+ return -ENOMEM;
-+
-+ dev_dbg(&pdev->dev, "nbanks = %d\n", info->nbanks);
-+ dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
-+ dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
-+
-+ i = 0;
-+
-+ for_each_child_of_node(np, child) {
-+ if (of_device_is_compatible(child, gpio_compat))
-+ continue;
-+ ret = at91_pinctrl_parse_functions(child, info, i++);
-+ if (ret) {
-+ dev_err(&pdev->dev, "failed to parse function\n");
-+ return ret;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static int __devinit at91_pinctrl_probe(struct platform_device *pdev)
-+{
-+ struct at91_pinctrl *info;
-+ struct pinctrl_pin_desc *pdesc;
-+ int ret, i, j ,k;
-+
-+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
-+ if (!info)
-+ return -ENOMEM;
-+
-+ ret = at91_pinctrl_probe_dt(pdev, info);
-+ if (ret)
-+ return ret;
-+
-+ /*
-+ * We need all the GPIO drivers to probe FIRST, or we will not be able
-+ * to obtain references to the struct gpio_chip * for them, and we
-+ * need this to proceed.
-+ */
-+ for (i = 0; i < info->nbanks; i++) {
-+ if (!gpio_chips[i]) {
-+ dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i);
-+ devm_kfree(&pdev->dev, info);
-+ return -EPROBE_DEFER;
-+ }
-+ }
-+
-+ at91_pinctrl_desc.name = dev_name(&pdev->dev);
-+ at91_pinctrl_desc.npins = info->nbanks * MAX_NB_GPIO_PER_BANK;
-+ at91_pinctrl_desc.pins = pdesc =
-+ devm_kzalloc(&pdev->dev, sizeof(*pdesc) * at91_pinctrl_desc.npins, GFP_KERNEL);
-+
-+ if (!at91_pinctrl_desc.pins)
-+ return -ENOMEM;
-+
-+ for (i = 0 , k = 0; i < info->nbanks; i++) {
-+ for (j = 0; j < MAX_NB_GPIO_PER_BANK; j++, k++) {
-+ pdesc->number = k;
-+ pdesc->name = kasprintf(GFP_KERNEL, "pio%c%d", i + 'A', j);
-+ pdesc++;
-+ }
-+ }
-+
-+ platform_set_drvdata(pdev, info);
-+ info->pctl = pinctrl_register(&at91_pinctrl_desc, &pdev->dev, info);
-+
-+ if (!info->pctl) {
-+ dev_err(&pdev->dev, "could not register AT91 pinctrl driver\n");
-+ ret = -EINVAL;
-+ goto err;
-+ }
-+
-+ /* We will handle a range of GPIO pins */
-+ for (i = 0; i < info->nbanks; i++)
-+ pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range);
-+
-+ dev_info(&pdev->dev, "initialized AT91 pinctrl driver\n");
-+
-+ return 0;
-+
-+err:
-+ return ret;
-+}
-+
-+int __devexit at91_pinctrl_remove(struct platform_device *pdev)
-+{
-+ struct at91_pinctrl *info = platform_get_drvdata(pdev);
-+
-+ pinctrl_unregister(info->pctl);
-+
-+ return 0;
-+}
-+
-+static int at91_gpio_request(struct gpio_chip *chip, unsigned offset)
-+{
-+ /*
-+ * Map back to global GPIO space and request muxing, the direction
-+ * parameter does not matter for this controller.
-+ */
-+ int gpio = chip->base + offset;
-+ int bank = chip->base / chip->ngpio;
-+
-+ dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__,
-+ 'A' + bank, offset, gpio);
-+
-+ return pinctrl_request_gpio(gpio);
-+}
-+
-+static void at91_gpio_free(struct gpio_chip *chip, unsigned offset)
-+{
-+ int gpio = chip->base + offset;
-+
-+ pinctrl_free_gpio(gpio);
-+}
-+
-+static int at91_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-+{
-+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-+ void __iomem *pio = at91_gpio->regbase;
-+ unsigned mask = 1 << offset;
-+
-+ writel_relaxed(mask, pio + PIO_ODR);
-+ return 0;
-+}
-+
-+static int at91_gpio_get(struct gpio_chip *chip, unsigned offset)
-+{
-+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-+ void __iomem *pio = at91_gpio->regbase;
-+ unsigned mask = 1 << offset;
-+ u32 pdsr;
-+
-+ pdsr = readl_relaxed(pio + PIO_PDSR);
-+ return (pdsr & mask) != 0;
-+}
-+
-+static void at91_gpio_set(struct gpio_chip *chip, unsigned offset,
-+ int val)
-+{
-+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-+ void __iomem *pio = at91_gpio->regbase;
-+ unsigned mask = 1 << offset;
-+
-+ writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR));
-+}
-+
-+static int at91_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
-+ int val)
-+{
-+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-+ void __iomem *pio = at91_gpio->regbase;
-+ unsigned mask = 1 << offset;
-+
-+ writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR));
-+ writel_relaxed(mask, pio + PIO_OER);
-+
-+ return 0;
-+}
-+
-+static int at91_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-+{
-+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-+ int virq;
-+
-+ if (offset < chip->ngpio)
-+ virq = irq_create_mapping(at91_gpio->domain, offset);
-+ else
-+ virq = -ENXIO;
-+
-+ dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
-+ chip->label, offset + chip->base, virq);
-+ return virq;
-+}
-+
-+#ifdef CONFIG_DEBUG_FS
-+static void at91_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
-+{
-+ enum at91_mux mode;
-+ int i;
-+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-+ void __iomem *pio = at91_gpio->regbase;
-+
-+ for (i = 0; i < chip->ngpio; i++) {
-+ unsigned pin = chip->base + i;
-+ unsigned mask = pin_to_mask(pin);
-+ const char *gpio_label;
-+ u32 pdsr;
-+
-+ gpio_label = gpiochip_is_requested(chip, i);
-+ if (!gpio_label)
-+ continue;
-+ mode = at91_gpio->ops->get_periph(pio, mask);
-+ seq_printf(s, "[%s] GPIO%s%d: ",
-+ gpio_label, chip->label, i);
-+ if (mode == AT91_MUX_GPIO) {
-+ pdsr = readl_relaxed(pio + PIO_PDSR);
-+
-+ seq_printf(s, "[gpio] %s\n",
-+ pdsr & mask ?
-+ "set" : "clear");
-+ } else {
-+ seq_printf(s, "[periph %c]\n",
-+ mode + 'A' - 1);
-+ }
-+ }
-+}
-+#else
-+#define at91_gpio_dbg_show NULL
-+#endif
-+
-+/* Several AIC controller irqs are dispatched through this GPIO handler.
-+ * To use any AT91_PIN_* as an externally triggered IRQ, first call
-+ * at91_set_gpio_input() then maybe enable its glitch filter.
-+ * Then just request_irq() with the pin ID; it works like any ARM IRQ
-+ * handler.
-+ * First implementation always triggers on rising and falling edges
-+ * whereas the newer PIO3 can be additionally configured to trigger on
-+ * level, edge with any polarity.
-+ *
-+ * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after
-+ * configuring them with at91_set_a_periph() or at91_set_b_periph().
-+ * IRQ0..IRQ6 should be configurable, e.g. level vs edge triggering.
-+ */
-+
-+static void gpio_irq_mask(struct irq_data *d)
-+{
-+ struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
-+ void __iomem *pio = at91_gpio->regbase;
-+ unsigned mask = 1 << d->hwirq;
-+
-+ if (pio)
-+ writel_relaxed(mask, pio + PIO_IDR);
-+}
-+
-+static void gpio_irq_unmask(struct irq_data *d)
-+{
-+ struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
-+ void __iomem *pio = at91_gpio->regbase;
-+ unsigned mask = 1 << d->hwirq;
-+
-+ if (pio)
-+ writel_relaxed(mask, pio + PIO_IER);
-+}
-+
-+static int gpio_irq_type(struct irq_data *d, unsigned type)
-+{
-+ switch (type) {
-+ case IRQ_TYPE_NONE:
-+ case IRQ_TYPE_EDGE_BOTH:
-+ return 0;
-+ default:
-+ return -EINVAL;
-+ }
-+}
-+
-+/* Alternate irq type for PIO3 support */
-+static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
-+{
-+ struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
-+ void __iomem *pio = at91_gpio->regbase;
-+ unsigned mask = 1 << d->hwirq;
-+
-+ switch (type) {
-+ case IRQ_TYPE_EDGE_RISING:
-+ writel_relaxed(mask, pio + PIO_ESR);
-+ writel_relaxed(mask, pio + PIO_REHLSR);
-+ break;
-+ case IRQ_TYPE_EDGE_FALLING:
-+ writel_relaxed(mask, pio + PIO_ESR);
-+ writel_relaxed(mask, pio + PIO_FELLSR);
-+ break;
-+ case IRQ_TYPE_LEVEL_LOW:
-+ writel_relaxed(mask, pio + PIO_LSR);
-+ writel_relaxed(mask, pio + PIO_FELLSR);
-+ break;
-+ case IRQ_TYPE_LEVEL_HIGH:
-+ writel_relaxed(mask, pio + PIO_LSR);
-+ writel_relaxed(mask, pio + PIO_REHLSR);
-+ break;
-+ case IRQ_TYPE_EDGE_BOTH:
-+ /*
-+ * disable additional interrupt modes:
-+ * fall back to default behavior
-+ */
-+ writel_relaxed(mask, pio + PIO_AIMDR);
-+ return 0;
-+ case IRQ_TYPE_NONE:
-+ default:
-+ pr_warn("AT91: No type for irq %d\n", gpio_to_irq(d->irq));
-+ return -EINVAL;
-+ }
-+
-+ /* enable additional interrupt modes */
-+ writel_relaxed(mask, pio + PIO_AIMER);
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+static int gpio_irq_set_wake(struct irq_data *d, unsigned state)
-+{
-+ struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
-+ unsigned bank = at91_gpio->pioc_idx;
-+
-+ if (unlikely(bank >= MAX_GPIO_BANKS))
-+ return -EINVAL;
-+
-+ irq_set_irq_wake(at91_gpio->pioc_virq, state);
-+
-+ return 0;
-+}
-+#else
-+#define gpio_irq_set_wake NULL
-+#endif
-+
-+static struct irq_chip gpio_irqchip = {
-+ .name = "GPIO",
-+ .irq_disable = gpio_irq_mask,
-+ .irq_mask = gpio_irq_mask,
-+ .irq_unmask = gpio_irq_unmask,
-+ /* .irq_set_type is set dynamically */
-+ .irq_set_wake = gpio_irq_set_wake,
-+};
-+
-+static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
-+{
-+ struct irq_chip *chip = irq_desc_get_chip(desc);
-+ struct irq_data *idata = irq_desc_get_irq_data(desc);
-+ struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
-+ void __iomem *pio = at91_gpio->regbase;
-+ unsigned long isr;
-+ int n;
-+
-+ chained_irq_enter(chip, desc);
-+ for (;;) {
-+ /* Reading ISR acks pending (edge triggered) GPIO interrupts.
-+ * When there none are pending, we're finished unless we need
-+ * to process multiple banks (like ID_PIOCDE on sam9263).
-+ */
-+ isr = readl_relaxed(pio + PIO_ISR) & readl_relaxed(pio + PIO_IMR);
-+ if (!isr) {
-+ if (!at91_gpio->next)
-+ break;
-+ at91_gpio = at91_gpio->next;
-+ pio = at91_gpio->regbase;
-+ continue;
-+ }
-+
-+ n = find_first_bit(&isr, BITS_PER_LONG);
-+ while (n < BITS_PER_LONG) {
-+ generic_handle_irq(irq_find_mapping(at91_gpio->domain, n));
-+ n = find_next_bit(&isr, BITS_PER_LONG, n + 1);
-+ }
-+ }
-+ chained_irq_exit(chip, desc);
-+ /* now it may re-trigger */
-+}
-+
-+/*
-+ * This lock class tells lockdep that GPIO irqs are in a different
-+ * category than their parents, so it won't report false recursion.
-+ */
-+static struct lock_class_key gpio_lock_class;
-+
-+static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq,
-+ irq_hw_number_t hw)
-+{
-+ struct at91_gpio_chip *at91_gpio = h->host_data;
-+
-+ irq_set_lockdep_class(virq, &gpio_lock_class);
-+
-+ /*
-+ * Can use the "simple" and not "edge" handler since it's
-+ * shorter, and the AIC handles interrupts sanely.
-+ */
-+ irq_set_chip_and_handler(virq, &gpio_irqchip,
-+ handle_simple_irq);
-+ set_irq_flags(virq, IRQF_VALID);
-+ irq_set_chip_data(virq, at91_gpio);
-+
-+ return 0;
-+}
-+
-+static struct irq_domain_ops at91_gpio_ops = {
-+ .map = at91_gpio_irq_map,
-+ .xlate = irq_domain_xlate_twocell,
-+};
-+
-+static int at91_gpio_of_irq_setup(struct device_node *node,
-+ struct at91_gpio_chip *at91_gpio)
-+{
-+ struct at91_gpio_chip *prev = NULL;
-+ struct irq_data *d = irq_get_irq_data(at91_gpio->pioc_virq);
-+
-+ at91_gpio->pioc_hwirq = irqd_to_hwirq(d);
-+
-+ /* Setup proper .irq_set_type function */
-+ gpio_irqchip.irq_set_type = at91_gpio->ops->irq_type;
-+
-+ /* Disable irqs of this PIO controller */
-+ writel_relaxed(~0, at91_gpio->regbase + PIO_IDR);
-+
-+ /* Setup irq domain */
-+ at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio,
-+ &at91_gpio_ops, at91_gpio);
-+ if (!at91_gpio->domain)
-+ panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n",
-+ at91_gpio->pioc_idx);
-+
-+ /* Setup chained handler */
-+ if (at91_gpio->pioc_idx)
-+ prev = gpio_chips[at91_gpio->pioc_idx - 1];
-+
-+ /* The toplevel handler handles one bank of GPIOs, except
-+ * on some SoC it can handles up to three...
-+ * We only set up the handler for the first of the list.
-+ */
-+ if (prev && prev->next == at91_gpio)
-+ return 0;
-+
-+ irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio);
-+ irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler);
-+
-+ return 0;
-+}
-+
-+/* This structure is replicated for each GPIO block allocated at probe time */
-+static struct gpio_chip at91_gpio_template = {
-+ .request = at91_gpio_request,
-+ .free = at91_gpio_free,
-+ .direction_input = at91_gpio_direction_input,
-+ .get = at91_gpio_get,
-+ .direction_output = at91_gpio_direction_output,
-+ .set = at91_gpio_set,
-+ .to_irq = at91_gpio_to_irq,
-+ .dbg_show = at91_gpio_dbg_show,
-+ .can_sleep = 0,
-+ .ngpio = MAX_NB_GPIO_PER_BANK,
-+};
-+
-+static void __devinit at91_gpio_probe_fixup(void)
-+{
-+ unsigned i;
-+ struct at91_gpio_chip *at91_gpio, *last = NULL;
-+
-+ for (i = 0; i < gpio_banks; i++) {
-+ at91_gpio = gpio_chips[i];
-+
-+ /*
-+ * GPIO controller are grouped on some SoC:
-+ * PIOC, PIOD and PIOE can share the same IRQ line
-+ */
-+ if (last && last->pioc_virq == at91_gpio->pioc_virq)
-+ last->next = at91_gpio;
-+ last = at91_gpio;
-+ }
-+}
-+
-+static struct of_device_id at91_gpio_of_match[] __devinitdata = {
-+ { .compatible = "atmel,at91rm9200-gpio", .data = &at91rm9200_ops },
-+ { .compatible = "atmel,at91sam9x5-gpio", .data = &at91sam9x5_ops, },
-+ { /* sentinel */ }
-+};
-+
-+static int __devinit at91_gpio_probe(struct platform_device *pdev)
-+{
-+ struct device_node *np = pdev->dev.of_node;
-+ struct resource *res;
-+ struct at91_gpio_chip *at91_chip = NULL;
-+ struct gpio_chip *chip;
-+ struct pinctrl_gpio_range *range;
-+ int ret = 0;
-+ int irq;
-+ int alias_idx = of_alias_get_id(np, "gpio");
-+ uint32_t ngpio;
-+
-+ BUG_ON(alias_idx >= ARRAY_SIZE(gpio_chips));
-+ if (gpio_chips[alias_idx]) {
-+ ret = -EBUSY;
-+ goto err;
-+ }
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!res) {
-+ ret = -ENOENT;
-+ goto err;
-+ }
-+
-+ irq = platform_get_irq(pdev, 0);
-+ if (irq < 0) {
-+ ret = irq;
-+ goto err;
-+ }
-+
-+ at91_chip = devm_kzalloc(&pdev->dev, sizeof(*at91_chip), GFP_KERNEL);
-+ if (!at91_chip) {
-+ ret = -ENOMEM;
-+ goto err;
-+ }
-+
-+ at91_chip->regbase = devm_request_and_ioremap(&pdev->dev, res);
-+ if (!at91_chip->regbase) {
-+ dev_err(&pdev->dev, "failed to map registers, ignoring.\n");
-+ ret = -EBUSY;
-+ goto err;
-+ }
-+
-+ at91_chip->ops =
-+ of_match_device(at91_gpio_of_match, &pdev->dev)->data;
-+ at91_chip->pioc_virq = irq;
-+ at91_chip->pioc_idx = alias_idx;
-+
-+ at91_chip->clock = clk_get(&pdev->dev, NULL);
-+ if (IS_ERR(at91_chip->clock)) {
-+ dev_err(&pdev->dev, "failed to get clock, ignoring.\n");
-+ goto err;
-+ }
-+
-+ if (clk_prepare(at91_chip->clock))
-+ goto clk_prep_err;
-+
-+ /* enable PIO controller's clock */
-+ if (clk_enable(at91_chip->clock)) {
-+ dev_err(&pdev->dev, "failed to enable clock, ignoring.\n");
-+ goto clk_err;
-+ }
-+
-+ at91_chip->chip = at91_gpio_template;
-+
-+ chip = &at91_chip->chip;
-+ chip->of_node = np;
-+ chip->label = dev_name(&pdev->dev);
-+ chip->dev = &pdev->dev;
-+ chip->owner = THIS_MODULE;
-+ chip->base = alias_idx * MAX_NB_GPIO_PER_BANK;
-+
-+ if (!of_property_read_u32(np, "#gpio-lines", &ngpio)) {
-+ if (ngpio >= MAX_NB_GPIO_PER_BANK)
-+ pr_err("at91_gpio.%d, gpio-nb >= %d failback to %d\n",
-+ alias_idx, MAX_NB_GPIO_PER_BANK, MAX_NB_GPIO_PER_BANK);
-+ else
-+ chip->ngpio = ngpio;
-+ }
-+
-+ range = &at91_chip->range;
-+ range->name = chip->label;
-+ range->id = alias_idx;
-+ range->pin_base = range->base = range->id * MAX_NB_GPIO_PER_BANK;
-+
-+ range->npins = chip->ngpio;
-+ range->gc = chip;
-+
-+ ret = gpiochip_add(chip);
-+ if (ret)
-+ goto clk_err;
-+
-+ gpio_chips[alias_idx] = at91_chip;
-+ gpio_banks = max(gpio_banks, alias_idx + 1);
-+
-+ at91_gpio_probe_fixup();
-+
-+ at91_gpio_of_irq_setup(np, at91_chip);
-+
-+ dev_info(&pdev->dev, "at address %p\n", at91_chip->regbase);
-+
-+ return 0;
-+
-+clk_err:
-+ clk_unprepare(at91_chip->clock);
-+clk_prep_err:
-+ clk_put(at91_chip->clock);
-+err:
-+ dev_err(&pdev->dev, "Failure %i for GPIO %i\n", ret, alias_idx);
-+
-+ return ret;
-+}
-+
-+static struct platform_driver at91_gpio_driver = {
-+ .driver = {
-+ .name = "gpio-at91",
-+ .owner = THIS_MODULE,
-+ .of_match_table = of_match_ptr(at91_gpio_of_match),
-+ },
-+ .probe = at91_gpio_probe,
-+};
-+
-+static struct platform_driver at91_pinctrl_driver = {
-+ .driver = {
-+ .name = "pinctrl-at91",
-+ .owner = THIS_MODULE,
-+ .of_match_table = of_match_ptr(at91_pinctrl_of_match),
-+ },
-+ .probe = at91_pinctrl_probe,
-+ .remove = __devexit_p(at91_pinctrl_remove),
-+};
-+
-+static int __init at91_pinctrl_init(void)
-+{
-+ int ret;
-+
-+ ret = platform_driver_register(&at91_gpio_driver);
-+ if (ret)
-+ return ret;
-+ return platform_driver_register(&at91_pinctrl_driver);
-+}
-+arch_initcall(at91_pinctrl_init);
-+
-+static void __exit at91_pinctrl_exit(void)
-+{
-+ platform_driver_unregister(&at91_pinctrl_driver);
-+}
-+
-+module_exit(at91_pinctrl_exit);
-+MODULE_AUTHOR("Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>");
-+MODULE_DESCRIPTION("Atmel AT91 pinctrl driver");
-+MODULE_LICENSE("GPL v2");
+++ /dev/null
-From 765cac5205bcee3f9c6e0fb2aa819c0136fff54f Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Mon, 22 Oct 2012 16:08:50 +0200
-Subject: arm: at91: dt: at91sam9 add pinctrl support
-
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-
-Conflicts:
- arch/arm/mach-at91/at91sam9263.c
- arch/arm/mach-at91/at91sam9n12.c
- arch/arm/mach-at91/at91sam9x5.c
----
- Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt | 68 ++++++++--
- arch/arm/boot/dts/at91sam9260.dtsi | 9 +
- arch/arm/boot/dts/at91sam9263.dtsi | 12 +
- arch/arm/boot/dts/at91sam9g45.dtsi | 11 +
- arch/arm/boot/dts/at91sam9n12.dtsi | 12 +
- arch/arm/boot/dts/at91sam9x5.dtsi | 12 +
- arch/arm/configs/at91_dt_defconfig | 1
- arch/arm/mach-at91/at91sam9260.c | 3
- arch/arm/mach-at91/at91sam9263.c | 5
- arch/arm/mach-at91/at91sam9g45.c | 6
- arch/arm/mach-at91/at91sam9n12.c | 11 -
- arch/arm/mach-at91/at91sam9x5.c | 18 --
- arch/arm/mach-at91/setup.c | 3
- drivers/pinctrl/pinctrl-at91.c | 2
- 14 files changed, 140 insertions(+), 33 deletions(-)
-
---- a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
-+++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
-@@ -22,6 +22,62 @@ Required properties for iomux controller
- - atmel,mux-mask: array of mask (periph per bank) to describe if a pin can be
- configured in this periph mode. All the periph and bank need to be describe.
-
-+How to create such array:
-+
-+Each column will represent the possible peripheral of the pinctrl
-+Each line will represent a pio bank
-+
-+Take an example on the 9260
-+Peripheral: 2 ( A and B)
-+Bank: 3 (A, B and C)
-+=>
-+
-+ /* A B */
-+ 0xffffffff 0xffc00c3b /* pioA */
-+ 0xffffffff 0x7fff3ccf /* pioB */
-+ 0xffffffff 0x007fffff /* pioC */
-+
-+For each peripheral/bank we will descibe in a u32 if a pin can can be
-+configured in it by putting 1 to the pin bit (1 << pin)
-+
-+Let's take the pioA on peripheral B
-+From the datasheet Table 10-2.
-+Peripheral B
-+PA0 MCDB0
-+PA1 MCCDB
-+PA2
-+PA3 MCDB3
-+PA4 MCDB2
-+PA5 MCDB1
-+PA6
-+PA7
-+PA8
-+PA9
-+PA10 ETX2
-+PA11 ETX3
-+PA12
-+PA13
-+PA14
-+PA15
-+PA16
-+PA17
-+PA18
-+PA19
-+PA20
-+PA21
-+PA22 ETXER
-+PA23 ETX2
-+PA24 ETX3
-+PA25 ERX2
-+PA26 ERX3
-+PA27 ERXCK
-+PA28 ECRS
-+PA29 ECOL
-+PA30 RXD4
-+PA31 TXD4
-+
-+=> 0xffc00c3b
-+
- Required properties for pin configuration node:
- - atmel,pins: 4 integers array, represents a group of pins mux and config
- setting. The format is atmel,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
-@@ -35,18 +91,14 @@ NOTE:
- Some requirements for using atmel,at91rm9200-pinctrl binding:
- 1. We have pin function node defined under at91 controller node to represent
- what pinmux functions this SoC supports.
--2. The pin configuration node intends to work on a specific function should
-- to be defined under that specific function node.
-- The function node's name should represent well about what function
-- this group of pins in this pin configuration node are working on.
--3. The driver can use the function node's name and pin configuration node's
-+2. The driver can use the function node's name and pin configuration node's
- name describe the pin function and group hierarchy.
-- For example, Linux Iat91 pinctrl driver takes the function node's name
-+ For example, Linux at91 pinctrl driver takes the function node's name
- as the function name and pin configuration node's name as group name to
- create the map table.
--4. Each pin configuration node should have a phandle, devices can set pins
-+3. Each pin configuration node should have a phandle, devices can set pins
- configurations by referring to the phandle of that pin configuration node.
--5. The gpio controller must be describe in the pinctrl simple-bus.
-+4. The gpio controller must be describe in the pinctrl simple-bus.
-
- Examples:
-
---- a/arch/arm/boot/dts/at91sam9260.dtsi
-+++ b/arch/arm/boot/dts/at91sam9260.dtsi
-@@ -104,6 +104,15 @@
- compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
- ranges = <0xfffff400 0xfffff400 0x600>;
-
-+ atmel,mux-mask = <
-+ /* A B */
-+ 0xffffffff 0xffc00c3b /* pioA */
-+ 0xffffffff 0x7fff3ccf /* pioB */
-+ 0xffffffff 0x007fffff /* pioC */
-+ >;
-+
-+ /* shared pinctrl settings */
-+
- pioA: gpio@fffff400 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x200>;
---- a/arch/arm/boot/dts/at91sam9263.dtsi
-+++ b/arch/arm/boot/dts/at91sam9263.dtsi
-@@ -95,6 +95,17 @@
- compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
- ranges = <0xfffff200 0xfffff200 0xa00>;
-
-+ atmel,mux-mask = <
-+ /* A B */
-+ 0xfffffffb 0xffffe07f /* pioA */
-+ 0x0007ffff 0x39072fff /* pioB */
-+ 0xffffffff 0x3ffffff8 /* pioC */
-+ 0xfffffbff 0xffffffff /* pioD */
-+ 0xffe00fff 0xfbfcff00 /* pioE */
-+ >;
-+
-+ /* shared pinctrl settings */
-+
- pioA: gpio@fffff200 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff200 0x200>;
-@@ -143,6 +154,7 @@
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
-+ };
- };
-
- dbgu: serial@ffffee00 {
---- a/arch/arm/boot/dts/at91sam9g45.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
-@@ -115,6 +115,17 @@
- compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
- ranges = <0xfffff200 0xfffff200 0xa00>;
-
-+ atmel,mux-mask = <
-+ /* A B */
-+ 0xffffffff 0xffc003ff /* pioA */
-+ 0xffffffff 0x800f8f00 /* pioB */
-+ 0xffffffff 0x00000e00 /* pioC */
-+ 0xffffffff 0xff0c1381 /* pioD */
-+ 0xffffffff 0x81ffff81 /* pioE */
-+ >;
-+
-+ /* shared pinctrl settings */
-+
- pioA: gpio@fffff200 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff200 0x200>;
---- a/arch/arm/boot/dts/at91sam9n12.dtsi
-+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
-@@ -115,9 +115,19 @@
- pinctrl@fffff400 {
- #address-cells = <1>;
- #size-cells = <1>;
-- compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
-+ compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus";
- ranges = <0xfffff400 0xfffff400 0x800>;
-
-+ atmel,mux-mask = <
-+ /* A B C */
-+ 0xffffffff 0xffe07983 0x00000000 /* pioA */
-+ 0x00040000 0x00047e0f 0x00000000 /* pioB */
-+ 0xfdffffff 0x07c00000 0xb83fffff /* pioC */
-+ 0x003fffff 0x003f8000 0x00000000 /* pioD */
-+ >;
-+
-+ /* shared pinctrl settings */
-+
- pioA: gpio@fffff400 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x200>;
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -116,9 +116,19 @@
- pinctrl@fffff200 {
- #address-cells = <1>;
- #size-cells = <1>;
-- compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
-+ compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus";
- ranges = <0xfffff400 0xfffff400 0x800>;
-
-+ atmel,mux-mask = <
-+ /* A B C */
-+ 0xffffffff 0xffe0399f 0xc000001c /* pioA */
-+ 0xffffffff 0xffc003ff 0xffc003ff /* pioB */
-+ 0xffffffff 0xffc003ff 0xffc003ff /* pioC */
-+ 0xffffffff 0xffc003ff 0xffc003ff /* pioD */
-+ >;
-+
-+ /* shared pinctrl settings */
-+
- pioA: gpio@fffff400 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x200>;
---- a/arch/arm/configs/at91_dt_defconfig
-+++ b/arch/arm/configs/at91_dt_defconfig
-@@ -111,6 +111,7 @@ CONFIG_I2C=y
- CONFIG_I2C_GPIO=y
- CONFIG_SPI=y
- CONFIG_SPI_ATMEL=y
-+CONFIG_PINCTRL_AT91=y
- # CONFIG_HWMON is not set
- CONFIG_WATCHDOG=y
- CONFIG_AT91SAM9X_WATCHDOG=y
---- a/arch/arm/mach-at91/at91sam9260.c
-+++ b/arch/arm/mach-at91/at91sam9260.c
-@@ -228,6 +228,9 @@ static struct clk_lookup periph_clocks_l
- CLKDEV_CON_ID("pioA", &pioA_clk),
- CLKDEV_CON_ID("pioB", &pioB_clk),
- CLKDEV_CON_ID("pioC", &pioC_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioA_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioB_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioC_clk),
- };
-
- static struct clk_lookup usart_clocks_lookups[] = {
---- a/arch/arm/mach-at91/at91sam9263.c
-+++ b/arch/arm/mach-at91/at91sam9263.c
-@@ -214,6 +214,11 @@ static struct clk_lookup periph_clocks_l
- CLKDEV_CON_DEV_ID("mci_clk", "fff80000.mmc", &mmc0_clk),
- CLKDEV_CON_DEV_ID("mci_clk", "fff84000.mmc", &mmc1_clk),
- CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff200.gpio", &pioA_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioB_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioCDE_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCDE_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCDE_clk),
- };
-
- static struct clk_lookup usart_clocks_lookups[] = {
---- a/arch/arm/mach-at91/at91sam9g45.c
-+++ b/arch/arm/mach-at91/at91sam9g45.c
-@@ -258,6 +258,12 @@ static struct clk_lookup periph_clocks_l
- CLKDEV_CON_DEV_ID("sha_clk", "fffc8000.sha", &aestdessha_clk),
- /* fake hclk clock */
- CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff200.gpio", &pioA_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioB_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioC_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioDE_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioDE_clk),
-+
- CLKDEV_CON_ID("pioA", &pioA_clk),
- CLKDEV_CON_ID("pioB", &pioB_clk),
- CLKDEV_CON_ID("pioC", &pioC_clk),
---- a/arch/arm/mach-at91/at91sam9n12.c
-+++ b/arch/arm/mach-at91/at91sam9n12.c
-@@ -186,12 +186,12 @@ static struct clk_lookup periph_clocks_l
- CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma_clk),
- CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
- CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
-- CLKDEV_CON_ID("pioA", &pioAB_clk),
-- CLKDEV_CON_ID("pioB", &pioAB_clk),
-- CLKDEV_CON_ID("pioC", &pioCD_clk),
-- CLKDEV_CON_ID("pioD", &pioCD_clk),
- CLKDEV_CON_DEV_ID("aes_clk", "f000c000.aes", &aes_clk),
- CLKDEV_CON_DEV_ID("sha_clk", "f0014000.sha", &sha_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioAB_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioAB_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCD_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCD_clk),
- /* additional fake clock for macb_hclk */
- CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &uhp_clk),
- CLKDEV_CON_DEV_ID("ohci_clk", "500000.ohci", &uhp_clk),
-@@ -241,9 +241,6 @@ static void __init at91sam9n12_map_io(vo
- void __init at91sam9n12_initialize(void)
- {
- at91_extern_irq = (1 << AT91SAM9N12_ID_IRQ0);
--
-- /* Register GPIO subsystem (using DT) */
-- at91_gpio_init(NULL, 0);
- }
-
- AT91_SOC_START(sam9n12)
---- a/arch/arm/mach-at91/at91sam9x5.c
-+++ b/arch/arm/mach-at91/at91sam9x5.c
-@@ -227,16 +227,13 @@ static struct clk_lookup periph_clocks_l
- CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk),
- CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc0_clk),
- CLKDEV_CON_DEV_ID("mci_clk", "f000c000.mmc", &mmc1_clk),
-- CLKDEV_CON_DEV_ID(NULL, "at91_i2c.0", &twi0_clk),
-- CLKDEV_CON_DEV_ID(NULL, "at91_i2c.1", &twi1_clk),
-- CLKDEV_CON_DEV_ID(NULL, "at91_i2c.2", &twi2_clk),
- CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
- CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
- CLKDEV_CON_DEV_ID(NULL, "f8018000.i2c", &twi2_clk),
-- CLKDEV_CON_ID("pioA", &pioAB_clk),
-- CLKDEV_CON_ID("pioB", &pioAB_clk),
-- CLKDEV_CON_ID("pioC", &pioCD_clk),
-- CLKDEV_CON_ID("pioD", &pioCD_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioAB_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioAB_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCD_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCD_clk),
- /* additional fake clock for macb_hclk */
- CLKDEV_CON_DEV_ID("hclk", "f802c000.ethernet", &macb0_clk),
- CLKDEV_CON_DEV_ID("hclk", "f8030000.ethernet", &macb1_clk),
-@@ -313,12 +310,6 @@ static void __init at91sam9x5_map_io(voi
- init_consistent_dma_size(SZ_8M);
- }
-
--void __init at91sam9x5_initialize(void)
--{
-- /* Register GPIO subsystem (using DT) */
-- at91_gpio_init(NULL, 0);
--}
--
- /* --------------------------------------------------------------------
- * Interrupt initialization
- * -------------------------------------------------------------------- */
-@@ -326,5 +317,4 @@ void __init at91sam9x5_initialize(void)
- AT91_SOC_START(sam9x5)
- .map_io = at91sam9x5_map_io,
- .register_clocks = at91sam9x5_register_clocks,
-- .init = at91sam9x5_initialize,
- AT91_SOC_END
---- a/arch/arm/mach-at91/setup.c
-+++ b/arch/arm/mach-at91/setup.c
-@@ -451,7 +451,8 @@ void __init at91_dt_initialize(void)
- /* Register the processor-specific clocks */
- at91_boot_soc.register_clocks();
-
-- at91_boot_soc.init();
-+ if (at91_boot_soc.init)
-+ at91_boot_soc.init();
- }
- #endif
-
---- a/drivers/pinctrl/pinctrl-at91.c
-+++ b/drivers/pinctrl/pinctrl-at91.c
-@@ -749,7 +749,7 @@ static int __devinit at91_pinctrl_parse_
- grp->name = np->name;
-
- /*
-- * the binding format is fsl,pins = <bank pin mux CONFIG ...>,
-+ * the binding format is atmel,pins = <bank pin mux CONFIG ...>,
- * do sanity check and calculate pins number
- */
- list = of_get_property(np, "atmel,pins", &size);
+++ /dev/null
-From afea54d51f37890af0531b619ba64331141dc5aa Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 6 Jul 2012 00:41:57 +0800
-Subject: tty: atmel_serial: add pinctrl support
-
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Acked-by: Linus Walleij <linus.walleij@linaro.org>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- drivers/tty/serial/atmel_serial.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
---- a/drivers/tty/serial/atmel_serial.c
-+++ b/drivers/tty/serial/atmel_serial.c
-@@ -39,6 +39,7 @@
- #include <linux/atmel_pdc.h>
- #include <linux/atmel_serial.h>
- #include <linux/uaccess.h>
-+#include <linux/pinctrl/consumer.h>
-
- #include <asm/io.h>
- #include <asm/ioctls.h>
-@@ -1773,6 +1774,7 @@ static int __devinit atmel_serial_probe(
- struct atmel_uart_data *pdata = pdev->dev.platform_data;
- void *data;
- int ret = -ENODEV;
-+ struct pinctrl *pinctrl;
-
- BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
-
-@@ -1804,6 +1806,12 @@ static int __devinit atmel_serial_probe(
-
- atmel_init_port(port, pdev);
-
-+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-+ if (IS_ERR(pinctrl)) {
-+ ret = PTR_ERR(pinctrl);
-+ goto err;
-+ }
-+
- if (!atmel_use_dma_rx(&port->uart)) {
- ret = -ENOMEM;
- data = kmalloc(sizeof(struct atmel_uart_char)
+++ /dev/null
-From 47e8824eb5ab3ec2eaf244dd0c2f378b46e90077 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 6 Jul 2012 00:41:57 +0800
-Subject: arm: at91: dt: sam9m10g45ek: use rts/cts pinctrl group for uart1
-
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Linus Walleij <linus.walleij@linaro.org>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/boot/dts/at91sam9m10g45ek.dts | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts
-index 6a4aedd..94a8399 100644
---- a/arch/arm/boot/dts/at91sam9m10g45ek.dts
-+++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts
-@@ -39,6 +39,7 @@
- };
-
- usart1: serial@fff90000 {
-+ pinctrl-0 = <&pinctrl_uart0 &pinctrl_uart1_rts_cts>;
- status = "okay";
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e1f12883d126b1f7c4903cd3ae3a67abf4cf6456 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 10 Aug 2012 03:38:36 +0800
-Subject: arm: at91: dt: sam9263ek: use rts/cts pinctrl group for uart0
-
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Linus Walleij <linus.walleij@linaro.org>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/boot/dts/at91sam9263ek.dts | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9263ek.dts b/arch/arm/boot/dts/at91sam9263ek.dts
-index 05028ed..4c25adf 100644
---- a/arch/arm/boot/dts/at91sam9263ek.dts
-+++ b/arch/arm/boot/dts/at91sam9263ek.dts
-@@ -38,6 +38,7 @@
- };
-
- usart0: serial@fff8c000 {
-+ pinctrl-0 = <&pinctrl_uart0 &pinctrl_uart0_rts_cts>;
- status = "okay";
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ebb32199a57519af1f5fcbf45e14ccb6d89b5481 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 10 Aug 2012 13:07:57 +0800
-Subject: arm: at91: dt: sam9g20ek: use rts/cts/dtr/dsr/dcd/ri pinctrl group
- for uart0
-
-Acked-by: Linus Walleij <linus.walleij@linaro.org>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/boot/dts/at91sam9g20ek_common.dtsi | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
-index 7da326a..6820417 100644
---- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
-@@ -35,6 +35,12 @@
- };
-
- usart0: serial@fffb0000 {
-+ pinctrl-0 =
-+ <&pinctrl_uart0
-+ &pinctrl_uart0_rts_cts
-+ &pinctrl_uart0_dtr_dsr
-+ &pinctrl_uart0_dcd
-+ &pinctrl_uart0_ri>;
- status = "okay";
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 0ffceb12d5e93ea68125847c9ecc02c45f1d5d31 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Thu, 12 Jul 2012 23:36:52 +0800
-Subject: arm: at91: dt: at91sam9 add nand pinctrl support
-
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/boot/dts/at91sam9260.dtsi | 10 ++++++++++
- arch/arm/boot/dts/at91sam9263.dtsi | 10 ++++++++++
- arch/arm/boot/dts/at91sam9g45.dtsi | 10 ++++++++++
- arch/arm/boot/dts/at91sam9n12.dtsi | 10 ++++++++++
- arch/arm/boot/dts/at91sam9x5.dtsi | 10 ++++++++++
- 5 files changed, 50 insertions(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
-index 3654ace..2dd4e0b 100644
---- a/arch/arm/boot/dts/at91sam9260.dtsi
-+++ b/arch/arm/boot/dts/at91sam9260.dtsi
-@@ -113,6 +113,14 @@
-
- /* shared pinctrl settings */
-
-+ nand {
-+ pinctrl_nand: nand-0 {
-+ atmel,pins =
-+ <2 13 0x0 0x1 /* PC13 gpio RDY pin pull_up */
-+ 2 14 0x0 0x1>; /* PC14 gpio enable pin pull_up */
-+ };
-+ };
-+
- pioA: gpio@fffff400 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x200>;
-@@ -247,6 +255,8 @@
- >;
- atmel,nand-addr-offset = <21>;
- atmel,nand-cmd-offset = <22>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_nand>;
- gpios = <&pioC 13 0
- &pioC 14 0
- 0
-diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
-index d7f416d..5aa07e4 100644
---- a/arch/arm/boot/dts/at91sam9263.dtsi
-+++ b/arch/arm/boot/dts/at91sam9263.dtsi
-@@ -106,6 +106,14 @@
-
- /* shared pinctrl settings */
-
-+ nand {
-+ pinctrl_nand: nand-0 {
-+ atmel,pins =
-+ <0 22 0x0 0x1 /* PA22 gpio RDY pin pull_up*/
-+ 3 15 0x0 0x1>; /* PD15 gpio enable pin pull_up */
-+ };
-+ };
-+
- pioA: gpio@fffff200 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff200 0x200>;
-@@ -242,6 +250,8 @@
- >;
- atmel,nand-addr-offset = <21>;
- atmel,nand-cmd-offset = <22>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_nand>;
- gpios = <&pioA 22 0
- &pioD 15 0
- 0
-diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
-index e2fa457..f08b8c2 100644
---- a/arch/arm/boot/dts/at91sam9g45.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
-@@ -126,6 +126,14 @@
-
- /* shared pinctrl settings */
-
-+ nand {
-+ pinctrl_nand: nand-0 {
-+ atmel,pins =
-+ <2 8 0x0 0x1 /* PC8 gpio RDY pin pull_up*/
-+ 2 14 0x0 0x1>; /* PC14 gpio enable pin pull_up */
-+ };
-+ };
-+
- pioA: gpio@fffff200 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff200 0x200>;
-@@ -297,6 +305,8 @@
- >;
- atmel,nand-addr-offset = <21>;
- atmel,nand-cmd-offset = <22>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_nand>;
- gpios = <&pioC 8 0
- &pioC 14 0
- 0
-diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
-index fc451f9..ec9b573 100644
---- a/arch/arm/boot/dts/at91sam9n12.dtsi
-+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
-@@ -128,6 +128,14 @@
-
- /* shared pinctrl settings */
-
-+ nand {
-+ pinctrl_nand: nand-0 {
-+ atmel,pins =
-+ <3 5 0x0 0x1 /* PD5 gpio RDY pin pull_up*/
-+ 3 4 0x0 0x1>; /* PD4 gpio enable pin pull_up */
-+ };
-+ };
-+
- pioA: gpio@fffff400 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x200>;
-@@ -265,6 +273,8 @@
- >;
- atmel,nand-addr-offset = <21>;
- atmel,nand-cmd-offset = <22>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_nand>;
- gpios = <&pioD 5 0
- &pioD 4 0
- 0
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index 84baa90..28e053a 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -129,6 +129,14 @@
-
- /* shared pinctrl settings */
-
-+ nand {
-+ pinctrl_nand: nand-0 {
-+ atmel,pins =
-+ <3 4 0x0 0x1 /* PD5 gpio RDY pin pull_up */
-+ 3 5 0x0 0x1>; /* PD4 gpio enable pin pull_up */
-+ };
-+ };
-+
- pioA: gpio@fffff400 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x200>;
-@@ -305,6 +313,8 @@
- atmel,pmecc-lookup-table-offset = <0x8000 0x10000>;
- atmel,nand-addr-offset = <21>;
- atmel,nand-cmd-offset = <22>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_nand>;
- gpios = <&pioD 5 0
- &pioD 4 0
- 0
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 8bf3e7d44fe43bcb7b5a80dddd3fc59ac748cf0a Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Thu, 12 Jul 2012 23:31:39 +0800
-Subject: MTD: atmel_nand: add pinctrl consumer support
-
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
-Acked-by: Linus Walleij <linus.walleij@linaro.org>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- drivers/mtd/nand/atmel_nand.c | 9 +++++++++
- 1 file changed, 9 insertions(+)
-
-diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
-index 3978336..625898e 100644
---- a/drivers/mtd/nand/atmel_nand.c
-+++ b/drivers/mtd/nand/atmel_nand.c
-@@ -41,6 +41,7 @@
- #include <linux/gpio.h>
- #include <linux/io.h>
- #include <linux/platform_data/atmel.h>
-+#include <linux/pinctrl/consumer.h>
-
- #include <mach/cpu.h>
-
-@@ -1367,6 +1368,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
- struct resource *mem;
- struct mtd_part_parser_data ppdata = {};
- int res;
-+ struct pinctrl *pinctrl;
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
-@@ -1411,6 +1413,13 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
- nand_chip->IO_ADDR_W = host->io_base;
- nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
-
-+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-+ if (IS_ERR(pinctrl)) {
-+ dev_err(host->dev, "Failed to request pinctrl\n");
-+ res = PTR_ERR(pinctrl);
-+ goto err_ecc_ioremap;
-+ }
-+
- if (gpio_is_valid(host->board.rdy_pin)) {
- res = devm_gpio_request(&pdev->dev,
- host->board.rdy_pin, "nand_rdy");
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 8826cf74bca084ee93056cc92da87e655b46a76c Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Wed, 26 Sep 2012 14:57:45 +0800
-Subject: pinctrl: at91 add deglitch, debounce, pull down and schmitt trigger
- mux option support
-
-add :
- set_deglitch: enable/disable deglitch
- set_debounce: enable/disable debounce
- set_pulldown: enable/disable pulldown
- disable_schmitt_trig: disable schmitt trigger
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- drivers/pinctrl/pinctrl-at91.c | 110 +++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 110 insertions(+)
-
-diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
-index 9c0fe11..73f7245 100644
---- a/drivers/pinctrl/pinctrl-at91.c
-+++ b/drivers/pinctrl/pinctrl-at91.c
-@@ -60,6 +60,12 @@ static int gpio_banks;
-
- #define PULL_UP (0 << 1)
- #define MULTI_DRIVE (1 << 1)
-+#define DEGLITCH (1 << 2)
-+#define PULL_DOWN (1 << 3)
-+#define DIS_SCHMIT (1 << 4)
-+#define DEBOUNCE (1 << 16)
-+#define DEBOUNCE_VAL_SHIFT 17
-+#define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
-
- /**
- * struct at91_pmx_func - describes AT91 pinmux functions
-@@ -123,6 +129,14 @@ struct at91_pin_group {
- * @mux_B_periph: mux as periph B
- * @mux_C_periph: mux as periph C
- * @mux_D_periph: mux as periph D
-+ * @get_deglitch: get deglitch status
-+ * @set_deglitch: enable/disable deglitch
-+ * @get_debounce: get debounce status
-+ * @set_debounce: enable/disable debounce
-+ * @get_pulldown: get pulldown status
-+ * @set_pulldown: enable/disable pulldown
-+ * @get_schmitt_trig: get schmitt trigger status
-+ * @disable_schmitt_trig: disable schmitt trigger
- * @irq_type: return irq type
- */
- struct at91_pinctrl_mux_ops {
-@@ -131,6 +145,14 @@ struct at91_pinctrl_mux_ops {
- void (*mux_B_periph)(void __iomem *pio, unsigned mask);
- void (*mux_C_periph)(void __iomem *pio, unsigned mask);
- void (*mux_D_periph)(void __iomem *pio, unsigned mask);
-+ bool (*get_deglitch)(void __iomem *pio, unsigned pin);
-+ void (*set_deglitch)(void __iomem *pio, unsigned mask, bool in_on);
-+ bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
-+ void (*set_debounce)(void __iomem *pio, unsigned mask, bool in_on, u32 div);
-+ bool (*get_pulldown)(void __iomem *pio, unsigned pin);
-+ void (*set_pulldown)(void __iomem *pio, unsigned mask, bool in_on);
-+ bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
-+ void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask);
- /* irq */
- int (*irq_type)(struct irq_data *d, unsigned type);
- };
-@@ -390,10 +412,70 @@ static enum at91_mux at91_mux_get_periph(void __iomem *pio, unsigned mask)
- return select + 1;
- }
-
-+static bool at91_mux_get_deglitch(void __iomem *pio, unsigned pin)
-+{
-+ return (__raw_readl(pio + PIO_IFSR) >> pin) & 0x1;
-+}
-+
-+static void at91_mux_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
-+{
-+ __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR));
-+}
-+
-+static void at91_mux_pio3_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
-+{
-+ if (is_on)
-+ __raw_writel(mask, pio + PIO_IFSCDR);
-+ at91_mux_set_deglitch(pio, mask, is_on);
-+}
-+
-+static bool at91_mux_pio3_get_debounce(void __iomem *pio, unsigned pin, u32 *div)
-+{
-+ *div = __raw_readl(pio + PIO_SCDR);
-+
-+ return (__raw_readl(pio + PIO_IFSCSR) >> pin) & 0x1;
-+}
-+
-+static void at91_mux_pio3_set_debounce(void __iomem *pio, unsigned mask,
-+ bool is_on, u32 div)
-+{
-+ if (is_on) {
-+ __raw_writel(mask, pio + PIO_IFSCER);
-+ __raw_writel(div & PIO_SCDR_DIV, pio + PIO_SCDR);
-+ __raw_writel(mask, pio + PIO_IFER);
-+ } else {
-+ __raw_writel(mask, pio + PIO_IFDR);
-+ }
-+}
-+
-+static bool at91_mux_pio3_get_pulldown(void __iomem *pio, unsigned pin)
-+{
-+ return (__raw_readl(pio + PIO_PPDSR) >> pin) & 0x1;
-+}
-+
-+static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is_on)
-+{
-+ /* Disable pull-up anyway */
-+ __raw_writel(mask, pio + PIO_PUDR);
-+ __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
-+}
-+
-+static void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask)
-+{
-+ __raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
-+}
-+
-+static bool at91_mux_pio3_get_schmitt_trig(void __iomem *pio, unsigned pin)
-+{
-+ return (__raw_readl(pio + PIO_SCHMITT) >> pin) & 0x1;
-+}
-+
- static struct at91_pinctrl_mux_ops at91rm9200_ops = {
- .get_periph = at91_mux_get_periph,
- .mux_A_periph = at91_mux_set_A_periph,
- .mux_B_periph = at91_mux_set_B_periph,
-+ .get_deglitch = at91_mux_get_deglitch,
-+ .set_deglitch = at91_mux_set_deglitch,
- .irq_type = gpio_irq_type,
- };
-
-@@ -403,6 +485,14 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
- .mux_B_periph = at91_mux_pio3_set_B_periph,
- .mux_C_periph = at91_mux_pio3_set_C_periph,
- .mux_D_periph = at91_mux_pio3_set_D_periph,
-+ .get_deglitch = at91_mux_get_deglitch,
-+ .set_deglitch = at91_mux_pio3_set_deglitch,
-+ .get_debounce = at91_mux_pio3_get_debounce,
-+ .set_debounce = at91_mux_pio3_set_debounce,
-+ .get_pulldown = at91_mux_pio3_get_pulldown,
-+ .set_pulldown = at91_mux_pio3_set_pulldown,
-+ .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
-+ .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
- .irq_type = alt_gpio_irq_type,
- };
-
-@@ -628,6 +718,7 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
- struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
- void __iomem *pio;
- unsigned pin;
-+ int div;
-
- dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, *config);
- pio = pin_to_controller(info, pin_to_bank(pin_id));
-@@ -639,6 +730,15 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
- if (at91_mux_get_pullup(pio, pin))
- *config |= PULL_UP;
-
-+ if (info->ops->get_deglitch && info->ops->get_deglitch(pio, pin))
-+ *config |= DEGLITCH;
-+ if (info->ops->get_debounce && info->ops->get_debounce(pio, pin, &div))
-+ *config |= DEBOUNCE | (div << DEBOUNCE_VAL_SHIFT);
-+ if (info->ops->get_pulldown && info->ops->get_pulldown(pio, pin))
-+ *config |= PULL_DOWN;
-+ if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin))
-+ *config |= DIS_SCHMIT;
-+
- return 0;
- }
-
-@@ -655,6 +755,16 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
-
- at91_mux_set_pullup(pio, mask, config & PULL_UP);
- at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE);
-+ if (info->ops->set_deglitch)
-+ info->ops->set_deglitch(pio, mask, config & DEGLITCH);
-+ if (info->ops->set_debounce)
-+ info->ops->set_debounce(pio, mask, DEBOUNCE,
-+ (config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
-+ if (info->ops->set_pulldown)
-+ info->ops->set_pulldown(pio, mask, config & PULL_DOWN);
-+ if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT)
-+ info->ops->disable_schmitt_trig(pio, mask);
-+
- return 0;
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 13a4a967e2e9ef7f99ea38b2cd6b369d401d6182 Mon Sep 17 00:00:00 2001
-From: Josh Wu <josh.wu@atmel.com>
-Date: Mon, 24 Sep 2012 08:06:30 +0800
-Subject: mtd: atmel_nand: fix the compile error which miss label
- "err_ecc_ioremap"
-
-Add err_ecc_ioremap label to fix following errors:
----8<---
- CC drivers/mtd/nand/atmel_nand.o
-drivers/mtd/nand/atmel_nand.c: In function 'atmel_nand_probe':
-drivers/mtd/nand/atmel_nand.c:1423: error: label 'err_ecc_ioremap' used but not defined
-make[3]: *** [drivers/mtd/nand/atmel_nand.o] Error 1
-make[2]: *** [drivers/mtd/nand] Error 2
-make[1]: *** [drivers/mtd] Error 2
-make: *** [drivers] Error 2
---->8---
-
-This error was introduced in b654a9a46fc2100b318050483f8c5b5d0f187303 (mtd: atmel nand: fix gpio missing request)
-
-Signed-off-by: Josh Wu <josh.wu@atmel.com>
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- drivers/mtd/nand/atmel_nand.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
-index 625898e..fadec27 100644
---- a/drivers/mtd/nand/atmel_nand.c
-+++ b/drivers/mtd/nand/atmel_nand.c
-@@ -1398,7 +1398,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
- if (pdev->dev.of_node) {
- res = atmel_of_init_port(host, pdev->dev.of_node);
- if (res)
-- goto err_nand_ioremap;
-+ goto err_ecc_ioremap;
- } else {
- memcpy(&host->board, pdev->dev.platform_data,
- sizeof(struct atmel_nand_data));
-@@ -1554,6 +1554,8 @@ err_scan_tail:
- pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
- pmecc_data_free(host);
- }
-+
-+err_ecc_ioremap:
- if (host->ecc)
- iounmap(host->ecc);
- if (host->pmerrloc_base)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 190a3340bea144c80801b81d5caa4c6f6556bb31 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Tue, 16 Oct 2012 17:05:33 +0200
-Subject: pinctrl/at91: fix compatible order
-
-sam9x5 is newer than rm9200
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- drivers/pinctrl/pinctrl-at91.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
-index 73f7245..a26dcb3 100644
---- a/drivers/pinctrl/pinctrl-at91.c
-+++ b/drivers/pinctrl/pinctrl-at91.c
-@@ -930,8 +930,8 @@ static int __devinit at91_pinctrl_parse_functions(struct device_node *np,
- }
-
- static struct of_device_id at91_pinctrl_of_match[] __devinitdata = {
-- { .compatible = "atmel,at91rm9200-pinctrl", .data = &at91rm9200_ops },
- { .compatible = "atmel,at91sam9x5-pinctrl", .data = &at91sam9x5_ops },
-+ { .compatible = "atmel,at91rm9200-pinctrl", .data = &at91rm9200_ops },
- { /* sentinel */ }
- };
-
-@@ -1441,8 +1441,8 @@ static void __devinit at91_gpio_probe_fixup(void)
- }
-
- static struct of_device_id at91_gpio_of_match[] __devinitdata = {
-+ { .compatible = "atmel,at91sam9x5-gpio", .data = &at91sam9x5_ops },
- { .compatible = "atmel,at91rm9200-gpio", .data = &at91rm9200_ops },
-- { .compatible = "atmel,at91sam9x5-gpio", .data = &at91sam9x5_ops, },
- { /* sentinel */ }
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 84fe665121d2a8f3389d33acfc29257eb8b2d8d1 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 19 Oct 2012 08:45:55 +0800
-Subject: pinctrl: at91: fix gpio irq support
-
-we can not use readl/writel_relaxed for interrupts
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- drivers/pinctrl/pinctrl-at91.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
-index a26dcb3..605fffd 100644
---- a/drivers/pinctrl/pinctrl-at91.c
-+++ b/drivers/pinctrl/pinctrl-at91.c
-@@ -1213,7 +1213,7 @@ static void gpio_irq_mask(struct irq_data *d)
- unsigned mask = 1 << d->hwirq;
-
- if (pio)
-- writel_relaxed(mask, pio + PIO_IDR);
-+ __raw_writel(mask, pio + PIO_IDR);
- }
-
- static void gpio_irq_unmask(struct irq_data *d)
-@@ -1223,7 +1223,7 @@ static void gpio_irq_unmask(struct irq_data *d)
- unsigned mask = 1 << d->hwirq;
-
- if (pio)
-- writel_relaxed(mask, pio + PIO_IER);
-+ __raw_writel(mask, pio + PIO_IER);
- }
-
- static int gpio_irq_type(struct irq_data *d, unsigned type)
-@@ -1321,7 +1321,7 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
- * When there none are pending, we're finished unless we need
- * to process multiple banks (like ID_PIOCDE on sam9263).
- */
-- isr = readl_relaxed(pio + PIO_ISR) & readl_relaxed(pio + PIO_IMR);
-+ isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR);
- if (!isr) {
- if (!at91_gpio->next)
- break;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 79f38b7f00e4a08e1f0066ebfcbf2540a4a8b8cb Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Tue, 16 Oct 2012 17:06:37 +0200
-Subject: i2c: at91: add pinctrl
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- drivers/i2c/busses/i2c-at91.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
-index c004b34..f471747 100644
---- a/drivers/i2c/busses/i2c-at91.c
-+++ b/drivers/i2c/busses/i2c-at91.c
-@@ -30,6 +30,7 @@
- #include <linux/of_device.h>
- #include <linux/of_i2c.h>
- #include <linux/platform_device.h>
-+#include <linux/pinctrl/consumer.h>
- #include <linux/slab.h>
-
- #include <mach/at_hdmac.h>
-@@ -767,6 +768,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
- struct resource *mem;
- int rc;
- u32 phy_addr;
-+ struct pinctrl *pinctrl;
-
- dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
- if (!dev)
-@@ -779,6 +781,12 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
- return -ENODEV;
- phy_addr = mem->start;
-
-+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-+ if (IS_ERR(pinctrl)) {
-+ dev_err(&pdev->dev, "Failed to request pinctrl\n");
-+ return PTR_ERR(pinctrl);
-+ }
-+
- dev->pdata = at91_twi_get_driver_data(pdev);
- if (!dev->pdata)
- return -ENODEV;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From f89227d6aec0e90ca9b2969e806703e63ca2d324 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Tue, 16 Oct 2012 17:07:17 +0200
-Subject: media: atmel_isi: add pinctrl
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- drivers/media/video/atmel-isi.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c
-index 7a44df4..ef80695 100644
---- a/drivers/media/video/atmel-isi.c
-+++ b/drivers/media/video/atmel-isi.c
-@@ -20,6 +20,7 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
-+#include <linux/pinctrl/consumer.h>
- #include <linux/slab.h>
-
- #include <media/atmel-isi.h>
-@@ -949,6 +950,7 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev)
- struct device *dev = &pdev->dev;
- struct soc_camera_host *soc_host;
- struct isi_platform_data *pdata;
-+ struct pinctrl *pinctrl;
-
- pdata = dev->platform_data;
- if (!pdata || !pdata->data_width_flags || !pdata->mck_hz) {
-@@ -961,6 +963,12 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev)
- if (!regs)
- return -ENXIO;
-
-+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-+ if (IS_ERR(pinctrl)) {
-+ dev_err(&pdev->dev, "Failed to request pinctrl\n");
-+ return PTR_ERR(pinctrl);
-+ }
-+
- pclk = clk_get(&pdev->dev, "isi_clk");
- if (IS_ERR(pclk))
- return PTR_ERR(pclk);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 06938a0f16eb491a16c123065cd5cda8e4111ba2 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Tue, 16 Oct 2012 17:08:12 +0200
-Subject: mmc: at91: add pinctrl
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- drivers/mmc/host/atmel-mci.c | 36 ++++++++++++++++++++++++++++++------
- 1 file changed, 30 insertions(+), 6 deletions(-)
-
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -28,6 +28,7 @@
- #include <linux/slab.h>
- #include <linux/stat.h>
- #include <linux/types.h>
-+#include <linux/pinctrl/consumer.h>
-
- #include <linux/mmc/host.h>
- #include <linux/mmc/sdio.h>
-@@ -2160,12 +2161,20 @@ static int __init atmci_init_slot(struct
- /* Assume card is present initially */
- set_bit(ATMCI_CARD_PRESENT, &slot->flags);
- if (gpio_is_valid(slot->detect_pin)) {
-- if (gpio_request(slot->detect_pin, "mmc_detect")) {
-- dev_dbg(&mmc->class_dev, "no detect pin available\n");
-+ if (devm_gpio_request(&mmc->class_dev, slot->detect_pin,
-+ "mmc_detect")) {
-+ dev_dbg(&mmc->class_dev, "can't request detect pin\n");
- slot->detect_pin = -EBUSY;
-- } else if (gpio_get_value(slot->detect_pin) ^
-- slot->detect_is_active_high) {
-- clear_bit(ATMCI_CARD_PRESENT, &slot->flags);
-+ } else {
-+ if (gpio_direction_input(slot->detect_pin)) {
-+ dev_err(&mmc->class_dev,
-+ "can't set detect pin direction\n");
-+ devm_gpio_free(&mmc->class_dev, slot->detect_pin);
-+ slot->detect_pin = -EBUSY;
-+ } else if (gpio_get_value(slot->detect_pin) ^
-+ slot->detect_is_active_high) {
-+ clear_bit(ATMCI_CARD_PRESENT, &slot->flags);
-+ }
- }
- }
-
-@@ -2173,9 +2182,17 @@ static int __init atmci_init_slot(struct
- mmc->caps |= MMC_CAP_NEEDS_POLL;
-
- if (gpio_is_valid(slot->wp_pin)) {
-- if (gpio_request(slot->wp_pin, "mmc_wp")) {
-+ if (devm_gpio_request(&mmc->class_dev, slot->wp_pin,
-+ "mmc_wp")) {
- dev_dbg(&mmc->class_dev, "no WP pin available\n");
- slot->wp_pin = -EBUSY;
-+ } else {
-+ if (gpio_direction_output(slot->wp_pin, 0)) {
-+ dev_err(&mmc->class_dev,
-+ "can't set WP pin direction\n");
-+ devm_gpio_free(&mmc->class_dev, slot->wp_pin);
-+ slot->wp_pin = -EBUSY;
-+ }
- }
- }
-
-@@ -2345,6 +2362,7 @@ static int __init atmci_probe(struct pla
- unsigned int nr_slots;
- int irq;
- int ret;
-+ struct pinctrl *pinctrl;
-
- regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!regs)
-@@ -2358,6 +2376,12 @@ static int __init atmci_probe(struct pla
- }
- }
-
-+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-+ if (IS_ERR(pinctrl)) {
-+ dev_err(&pdev->dev, "Failed to request pinctrl\n");
-+ return PTR_ERR(pinctrl);
-+ }
-+
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return irq;
+++ /dev/null
-From 5c8912c7fe8e2cf9fe8e2ec695810fa72202f354 Mon Sep 17 00:00:00 2001
-From: Ludovic Desroches <ludovic.desroches@atmel.com>
-Date: Tue, 16 Oct 2012 17:08:54 +0200
-Subject: video: atmel_lcdfb: add pinctrl
-
-Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- drivers/video/atmel_lcdfb_core.c | 9 +++++++++
- 1 file changed, 9 insertions(+)
-
-diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c
-index 133d4ad..b71a80c 100644
---- a/drivers/video/atmel_lcdfb_core.c
-+++ b/drivers/video/atmel_lcdfb_core.c
-@@ -11,6 +11,7 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
-+#include <linux/pinctrl/consumer.h>
- #include <linux/dma-mapping.h>
- #include <linux/interrupt.h>
- #include <linux/clk.h>
-@@ -556,6 +557,7 @@ int __atmel_lcdfb_probe(struct platform_device *pdev,
- struct resource *regs = NULL, *clut = NULL;
- struct resource *map = NULL;
- int ret;
-+ struct pinctrl *pinctrl;
-
- dev_dbg(dev, "%s BEGIN\n", __func__);
-
-@@ -635,6 +637,13 @@ int __atmel_lcdfb_probe(struct platform_device *pdev,
- goto stop_clk;
- }
-
-+ pinctrl = devm_pinctrl_get_select_default(dev);
-+ if (IS_ERR(pinctrl)) {
-+ dev_err(dev, "Failed to request pinctrl\n");
-+ ret = PTR_ERR(pinctrl);
-+ goto stop_clk;
-+ }
-+
- /* No error checking, some devices can do without IRQ */
- sinfo->irq_base = platform_get_irq(pdev, 0);
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 7fd1be019470e05075ed05e67b824c34d2f4f024 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 19 Oct 2012 05:52:10 +0800
-Subject: arm: at91sam9g45: add missing uart pinctrl node
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/boot/dts/at91sam9g45.dtsi | 73 ++++++++++++++++++++++++++++++++++++++
- 1 file changed, 73 insertions(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
-index f08b8c2..e379b89 100644
---- a/arch/arm/boot/dts/at91sam9g45.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
-@@ -125,6 +125,69 @@
- >;
-
- /* shared pinctrl settings */
-+ dbgu {
-+ pinctrl_dbgu: dbgu-0 {
-+ atmel,pins =
-+ <1 12 0x1 0x0 /* PB12 periph A */
-+ 1 13 0x1 0x0>; /* PB13 periph A */
-+ };
-+ };
-+
-+ uart0 {
-+ pinctrl_uart0: uart0-0 {
-+ atmel,pins =
-+ <1 19 0x1 0x1 /* PB19 periph A with pullup */
-+ 1 18 0x1 0x0>; /* PB18 periph A */
-+ };
-+
-+ pinctrl_uart0_rts_cts: uart0_rts_cts-0 {
-+ atmel,pins =
-+ <1 17 0x2 0x0 /* PB17 periph B */
-+ 1 15 0x2 0x0>; /* PB15 periph B */
-+ };
-+ };
-+
-+ uart1 {
-+ pinctrl_uart1: uart1-0 {
-+ atmel,pins =
-+ <1 4 0x1 0x1 /* PB4 periph A with pullup */
-+ 1 5 0x1 0x0>; /* PB5 periph A */
-+ };
-+
-+ pinctrl_uart1_rts_cts: uart1_rts_cts-0 {
-+ atmel,pins =
-+ <3 16 0x1 0x0 /* PD16 periph A */
-+ 3 17 0x1 0x0>; /* PD17 periph A */
-+ };
-+ };
-+
-+ uart2 {
-+ pinctrl_uart2: uart2-0 {
-+ atmel,pins =
-+ <1 6 0x1 0x1 /* PB6 periph A with pullup */
-+ 1 7 0x1 0x0>; /* PB7 periph A */
-+ };
-+
-+ pinctrl_uart2_rts_cts: uart2_rts_cts-0 {
-+ atmel,pins =
-+ <2 9 0x2 0x0 /* PC9 periph B */
-+ 2 11 0x2 0x0>; /* PC11 periph B */
-+ };
-+ };
-+
-+ uart3 {
-+ pinctrl_uart3: uart3-0 {
-+ atmel,pins =
-+ <1 8 0x1 0x1 /* PB9 periph A with pullup */
-+ 1 9 0x1 0x0>; /* PB8 periph A */
-+ };
-+
-+ pinctrl_uart3_rts_cts: uart3_rts_cts-0 {
-+ atmel,pins =
-+ <0 23 0x2 0x0 /* PA23 periph B */
-+ 0 24 0x2 0x0>; /* PA24 periph B */
-+ };
-+ };
-
- nand {
- pinctrl_nand: nand-0 {
-@@ -189,6 +252,8 @@
- compatible = "atmel,at91sam9260-usart";
- reg = <0xffffee00 0x200>;
- interrupts = <1 4 7>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_dbgu>;
- status = "disabled";
- };
-
-@@ -198,6 +263,8 @@
- interrupts = <7 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart0>;
- status = "disabled";
- };
-
-@@ -207,6 +274,8 @@
- interrupts = <8 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart1>;
- status = "disabled";
- };
-
-@@ -216,6 +285,8 @@
- interrupts = <9 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart2>;
- status = "disabled";
- };
-
-@@ -225,6 +296,8 @@
- interrupts = <10 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart3>;
- status = "disabled";
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 140ae475ee6bbf6287ccdba37173a91de2a41179 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 19 Oct 2012 05:52:10 +0800
-Subject: arm: at91sam9263: add missing uart pinctrl node
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/boot/dts/at91sam9263.dtsi | 57 ++++++++++++++++++++++++++++++++++++++
- 1 file changed, 57 insertions(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
-index 5aa07e4..690e036 100644
---- a/arch/arm/boot/dts/at91sam9263.dtsi
-+++ b/arch/arm/boot/dts/at91sam9263.dtsi
-@@ -105,6 +105,55 @@
- >;
-
- /* shared pinctrl settings */
-+ dbgu {
-+ pinctrl_dbgu: dbgu-0 {
-+ atmel,pins =
-+ <2 30 0x1 0x0 /* PC30 periph A */
-+ 2 31 0x1 0x1>; /* PC31 periph with pullup */
-+ };
-+ };
-+
-+ uart0 {
-+ pinctrl_uart0: uart0-0 {
-+ atmel,pins =
-+ <0 26 0x1 0x1 /* PA26 periph A with pullup */
-+ 0 27 0x1 0x0>; /* PA27 periph A */
-+ };
-+
-+ pinctrl_uart0_rts_cts: uart0_rts_cts-0 {
-+ atmel,pins =
-+ <0 28 0x1 0x0 /* PA28 periph A */
-+ 0 29 0x1 0x0>; /* PA29 periph A */
-+ };
-+ };
-+
-+ uart1 {
-+ pinctrl_uart1: uart1-0 {
-+ atmel,pins =
-+ <3 0 0x1 0x1 /* PD0 periph A with pullup */
-+ 3 1 0x1 0x0>; /* PD1 periph A */
-+ };
-+
-+ pinctrl_uart1_rts_cts: uart1_rts_cts-0 {
-+ atmel,pins =
-+ <3 7 0x2 0x0 /* PD7 periph B */
-+ 3 8 0x2 0x0>; /* PD8 periph B */
-+ };
-+ };
-+
-+ uart2 {
-+ pinctrl_uart2: uart2-0 {
-+ atmel,pins =
-+ <3 2 0x1 0x1 /* PD2 periph A with pullup */
-+ 3 3 0x1 0x0>; /* PD3 periph A */
-+ };
-+
-+ pinctrl_uart2_rts_cts: uart2_rts_cts-0 {
-+ atmel,pins =
-+ <3 5 0x2 0x0 /* PD5 periph B */
-+ 4 6 0x2 0x0>; /* PD6 periph B */
-+ };
-+ };
-
- nand {
- pinctrl_nand: nand-0 {
-@@ -169,6 +218,8 @@
- compatible = "atmel,at91sam9260-usart";
- reg = <0xffffee00 0x200>;
- interrupts = <1 4 7>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_dbgu>;
- status = "disabled";
- };
-
-@@ -178,6 +229,8 @@
- interrupts = <7 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart0>;
- status = "disabled";
- };
-
-@@ -187,6 +240,8 @@
- interrupts = <8 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart1>;
- status = "disabled";
- };
-
-@@ -196,6 +251,8 @@
- interrupts = <9 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart2>;
- status = "disabled";
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a35197fd3f74ef70f53b89627df1471df405434a Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 19 Oct 2012 05:52:10 +0800
-Subject: arm: at91sam9260: add missing uart pinctrl node
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/boot/dts/at91sam9260.dtsi | 109 +++++++++++++++++++++++++++++++++++++
- 1 file changed, 109 insertions(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
-index 2dd4e0b..7c9d91a 100644
---- a/arch/arm/boot/dts/at91sam9260.dtsi
-+++ b/arch/arm/boot/dts/at91sam9260.dtsi
-@@ -112,6 +112,101 @@
- >;
-
- /* shared pinctrl settings */
-+ dbgu {
-+ pinctrl_dbgu: dbgu-0 {
-+ atmel,pins =
-+ <1 14 0x1 0x0 /* PB14 periph A */
-+ 1 15 0x1 0x1>; /* PB15 periph with pullup */
-+ };
-+ };
-+
-+ uart0 {
-+ pinctrl_uart0: uart0-0 {
-+ atmel,pins =
-+ <1 4 0x1 0x0 /* PB4 periph A */
-+ 1 5 0x1 0x0>; /* PB5 periph A */
-+ };
-+
-+ pinctrl_uart0_rts_cts: uart0_rts_cts-0 {
-+ atmel,pins =
-+ <1 26 0x1 0x0 /* PB26 periph A */
-+ 1 27 0x1 0x0>; /* PB27 periph A */
-+ };
-+
-+ pinctrl_uart0_dtr_dsr: uart0_dtr_dsr-0 {
-+ atmel,pins =
-+ <1 24 0x1 0x0 /* PB24 periph A */
-+ 1 22 0x1 0x0>; /* PB22 periph A */
-+ };
-+
-+ pinctrl_uart0_dcd: uart0_dcd-0 {
-+ atmel,pins =
-+ <1 23 0x1 0x0>; /* PB23 periph A */
-+ };
-+
-+ pinctrl_uart0_ri: uart0_ri-0 {
-+ atmel,pins =
-+ <1 25 0x1 0x0>; /* PB25 periph A */
-+ };
-+ };
-+
-+ uart1 {
-+ pinctrl_uart1: uart1-0 {
-+ atmel,pins =
-+ <2 6 0x1 0x1 /* PB6 periph A with pullup */
-+ 2 7 0x1 0x0>; /* PB7 periph A */
-+ };
-+
-+ pinctrl_uart1_rts_cts: uart1_rts_cts-0 {
-+ atmel,pins =
-+ <1 28 0x1 0x0 /* PB28 periph A */
-+ 1 29 0x1 0x0>; /* PB29 periph A */
-+ };
-+ };
-+
-+ uart2 {
-+ pinctrl_uart2: uart2-0 {
-+ atmel,pins =
-+ <1 8 0x1 0x1 /* PB8 periph A with pullup */
-+ 1 9 0x1 0x0>; /* PB9 periph A */
-+ };
-+
-+ pinctrl_uart2_rts_cts: uart2_rts_cts-0 {
-+ atmel,pins =
-+ <0 4 0x1 0x0 /* PA4 periph A */
-+ 0 5 0x1 0x0>; /* PA5 periph A */
-+ };
-+ };
-+
-+ uart3 {
-+ pinctrl_uart3: uart3-0 {
-+ atmel,pins =
-+ <2 10 0x1 0x1 /* PB10 periph A with pullup */
-+ 2 11 0x1 0x0>; /* PB11 periph A */
-+ };
-+
-+ pinctrl_uart3_rts_cts: uart3_rts_cts-0 {
-+ atmel,pins =
-+ <3 8 0x2 0x0 /* PB8 periph B */
-+ 3 10 0x2 0x0>; /* PB10 periph B */
-+ };
-+ };
-+
-+ uart4 {
-+ pinctrl_uart4: uart4-0 {
-+ atmel,pins =
-+ <0 31 0x2 0x1 /* PA31 periph B with pullup */
-+ 0 30 0x2 0x0>; /* PA30 periph B */
-+ };
-+ };
-+
-+ uart5 {
-+ pinctrl_uart5: uart5-0 {
-+ atmel,pins =
-+ <2 12 0x1 0x1 /* PB12 periph A with pullup */
-+ 2 13 0x1 0x0>; /* PB13 periph A */
-+ };
-+ };
-
- nand {
- pinctrl_nand: nand-0 {
-@@ -156,6 +251,8 @@
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffff200 0x200>;
- interrupts = <1 4 7>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_dbgu>;
- status = "disabled";
- };
-
-@@ -165,6 +262,8 @@
- interrupts = <6 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart0>;
- status = "disabled";
- };
-
-@@ -174,6 +273,8 @@
- interrupts = <7 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart1>;
- status = "disabled";
- };
-
-@@ -183,6 +284,8 @@
- interrupts = <8 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart2>;
- status = "disabled";
- };
-
-@@ -192,6 +295,8 @@
- interrupts = <23 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart3>;
- status = "disabled";
- };
-
-@@ -201,6 +306,8 @@
- interrupts = <24 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart4>;
- status = "disabled";
- };
-
-@@ -210,6 +317,8 @@
- interrupts = <25 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart5>;
- status = "disabled";
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 6020cbc2ed1b39e116af501b16196f41fb02560c Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 19 Oct 2012 06:08:16 +0800
-Subject: arm: at91sam9x5: sync with the mainline
-
-where we have one dtsi per soc and one dts per board
-we have also a common dtsi name at91sam9x5ek.dtsi for the based board
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/boot/dts/at91sam9g15.dtsi | 28 +++++++
- arch/arm/boot/dts/at91sam9g15ek.dts | 16 ++++
- arch/arm/boot/dts/at91sam9g25.dtsi | 28 +++++++
- arch/arm/boot/dts/at91sam9g25ek.dts | 42 +---------
- arch/arm/boot/dts/at91sam9g35.dtsi | 28 +++++++
- arch/arm/boot/dts/at91sam9g35ek.dts | 21 +----
- arch/arm/boot/dts/at91sam9x25.dtsi | 28 +++++++
- arch/arm/boot/dts/at91sam9x25ek.dts | 24 +-----
- arch/arm/boot/dts/at91sam9x35.dtsi | 28 +++++++
- arch/arm/boot/dts/at91sam9x35ek.dts | 16 ++++
- arch/arm/boot/dts/at91sam9x5.dtsi | 97 ++++++++++++++++++++--
- .../{at91sam9x5_common.dtsi => at91sam9x5ek.dtsi} | 32 ++++++-
- arch/arm/mach-at91/Makefile.boot | 2 +
- 13 files changed, 298 insertions(+), 92 deletions(-)
- create mode 100644 arch/arm/boot/dts/at91sam9g15.dtsi
- create mode 100644 arch/arm/boot/dts/at91sam9g15ek.dts
- create mode 100644 arch/arm/boot/dts/at91sam9g25.dtsi
- create mode 100644 arch/arm/boot/dts/at91sam9g35.dtsi
- create mode 100644 arch/arm/boot/dts/at91sam9x25.dtsi
- create mode 100644 arch/arm/boot/dts/at91sam9x35.dtsi
- create mode 100644 arch/arm/boot/dts/at91sam9x35ek.dts
- rename arch/arm/boot/dts/{at91sam9x5_common.dtsi => at91sam9x5ek.dtsi} (54%)
-
-diff --git a/arch/arm/boot/dts/at91sam9g15.dtsi b/arch/arm/boot/dts/at91sam9g15.dtsi
-new file mode 100644
-index 0000000..fbe7a70
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9g15.dtsi
-@@ -0,0 +1,28 @@
-+/*
-+ * at91sam9g15.dtsi - Device Tree Include file for AT91SAM9G15 SoC
-+ *
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2.
-+ */
-+
-+/include/ "at91sam9x5.dtsi"
-+
-+/ {
-+ model = "Atmel AT91SAM9G15 SoC";
-+ compatible = "atmel, at91sam9g15, atmel,at91sam9x5";
-+
-+ ahb {
-+ apb {
-+ pinctrl@fffff400 {
-+ atmel,mux-mask = <
-+ /* A B C */
-+ 0xffffffff 0xffe0399f 0x00000000 /* pioA */
-+ 0x00040000 0x00047e3f 0x00000000 /* pioB */
-+ 0xfdffffff 0x00000000 0xb83fffff /* pioC */
-+ 0x003fffff 0x003f8000 0x00000000 /* pioD */
-+ >;
-+ };
-+ };
-+ };
-+};
-diff --git a/arch/arm/boot/dts/at91sam9g15ek.dts b/arch/arm/boot/dts/at91sam9g15ek.dts
-new file mode 100644
-index 0000000..86dd3f6
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9g15ek.dts
-@@ -0,0 +1,16 @@
-+/*
-+ * at91sam9g15ek.dts - Device Tree file for AT91SAM9G15-EK board
-+ *
-+ * Copyright (C) 2012 Atmel,
-+ * 2012 Nicolas Ferre <nicolas.ferre@atmel.com>
-+ *
-+ * Licensed under GPLv2 or later.
-+ */
-+/dts-v1/;
-+/include/ "at91sam9g15.dtsi"
-+/include/ "at91sam9x5ek.dtsi"
-+
-+/ {
-+ model = "Atmel AT91SAM9G25-EK";
-+ compatible = "atmel,at91sam9g15ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
-+};
-diff --git a/arch/arm/boot/dts/at91sam9g25.dtsi b/arch/arm/boot/dts/at91sam9g25.dtsi
-new file mode 100644
-index 0000000..05a718f
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9g25.dtsi
-@@ -0,0 +1,28 @@
-+/*
-+ * at91sam9g25.dtsi - Device Tree Include file for AT91SAM9G25 SoC
-+ *
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2.
-+ */
-+
-+/include/ "at91sam9x5.dtsi"
-+
-+/ {
-+ model = "Atmel AT91SAM9G25 SoC";
-+ compatible = "atmel, at91sam9g25, atmel,at91sam9x5";
-+
-+ ahb {
-+ apb {
-+ pinctrl@fffff400 {
-+ atmel,mux-mask = <
-+ /* A B C */
-+ 0xffffffff 0xffe0399f 0xc000001c /* pioA */
-+ 0x0007ffff 0x8000fe3f 0x00000000 /* pioB */
-+ 0x80000000 0x07c0ffff 0xb83fffff /* pioC */
-+ 0x003fffff 0x003f8000 0x00000000 /* pioD */
-+ >;
-+ };
-+ };
-+ };
-+};
-diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts
-index 91c0f02..4abc978 100644
---- a/arch/arm/boot/dts/at91sam9g25ek.dts
-+++ b/arch/arm/boot/dts/at91sam9g25ek.dts
-@@ -7,55 +7,17 @@
- * Licensed under GPLv2 or later.
- */
- /dts-v1/;
--/include/ "at91sam9x5_common.dtsi"
-+/include/ "at91sam9g25.dtsi"
-+/include/ "at91sam9x5ek.dtsi"
-
- / {
- model = "Atmel AT91SAM9G25-EK";
- compatible = "atmel,at91sam9g25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
-
-- chosen {
-- bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
-- };
--
- ahb {
- apb {
-- usart0: serial@f801c000 {
-- status = "okay";
-- };
--
-- macb0: ethernet@f802c000 {
-- phy-mode = "rmii";
-- status = "okay";
-- };
--
-- mmc0: mmc@f0008000 {
-- status = "okay";
-- slot@0 {
-- reg = <0>;
-- bus-width = <4>;
-- cd-gpios = <&pioD 15 0>;
-- };
-- };
--
- mmc1: mmc@f000c000 {
- status = "okay";
-- slot@0 {
-- reg = <0>;
-- bus-width = <4>;
-- cd-gpios = <&pioD 14 0>;
-- };
-- };
--
-- i2c0: i2c@f8010000 {
-- status = "okay";
-- };
--
-- i2c1: i2c@f8014000 {
-- status = "okay";
-- };
--
-- i2c2: i2c@f8018000 {
-- status = "okay";
- };
- };
- };
-diff --git a/arch/arm/boot/dts/at91sam9g35.dtsi b/arch/arm/boot/dts/at91sam9g35.dtsi
-new file mode 100644
-index 0000000..f9d14a7
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9g35.dtsi
-@@ -0,0 +1,28 @@
-+/*
-+ * at91sam9g35.dtsi - Device Tree Include file for AT91SAM9G35 SoC
-+ *
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2.
-+ */
-+
-+/include/ "at91sam9x5.dtsi"
-+
-+/ {
-+ model = "Atmel AT91SAM9G35 SoC";
-+ compatible = "atmel, at91sam9g35, atmel,at91sam9x5";
-+
-+ ahb {
-+ apb {
-+ pinctrl@fffff400 {
-+ atmel,mux-mask = <
-+ /* A B C */
-+ 0xffffffff 0xffe0399f 0xc000000c /* pioA */
-+ 0x000406ff 0x00047e3f 0x00000000 /* pioB */
-+ 0xfdffffff 0x00000000 0xb83fffff /* pioC */
-+ 0x003fffff 0x003f8000 0x00000000 /* pioD */
-+ >;
-+ };
-+ };
-+ };
-+};
-diff --git a/arch/arm/boot/dts/at91sam9g35ek.dts b/arch/arm/boot/dts/at91sam9g35ek.dts
-index 0cb762e..2781a30 100644
---- a/arch/arm/boot/dts/at91sam9g35ek.dts
-+++ b/arch/arm/boot/dts/at91sam9g35ek.dts
-@@ -7,34 +7,17 @@
- * Licensed under GPLv2 or later.
- */
- /dts-v1/;
--/include/ "at91sam9x5_common.dtsi"
-+/include/ "at91sam9g35.dtsi"
-+/include/ "at91sam9x5ek.dtsi"
-
- / {
- model = "Atmel AT91SAM9G35-EK";
- compatible = "atmel,at91sam9g35ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
-
-- chosen {
-- bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
-- };
--
- ahb {
- apb {
- mmc1: mmc@f000c000 {
- status = "okay";
-- slot@0 {
-- reg = <0>;
-- bus-width = <4>;
-- cd-gpios = <&pioD 14 0>;
-- };
-- };
--
-- usart0: serial@f801c000 {
-- status = "okay";
-- };
--
-- macb0: ethernet@f802c000 {
-- phy-mode = "rmii";
-- status = "okay";
- };
-
- lcd@f8038000 {
-diff --git a/arch/arm/boot/dts/at91sam9x25.dtsi b/arch/arm/boot/dts/at91sam9x25.dtsi
-new file mode 100644
-index 0000000..956c65f
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9x25.dtsi
-@@ -0,0 +1,28 @@
-+/*
-+ * at91sam9x25.dtsi - Device Tree Include file for AT91SAM9X25 SoC
-+ *
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2.
-+ */
-+
-+/include/ "at91sam9x5.dtsi"
-+
-+/ {
-+ model = "Atmel AT91SAM9X25 SoC";
-+ compatible = "atmel, at91sam9x25, atmel,at91sam9x5";
-+
-+ ahb {
-+ apb {
-+ pinctrl@fffff400 {
-+ atmel,mux-mask = <
-+ /* A B C */
-+ 0xffffffff 0xffe03fff 0xc000001c /* pioA */
-+ 0x0007ffff 0x00047e3f 0x00000000 /* pioB */
-+ 0x80000000 0xfffd0000 0xb83fffff /* pioC */
-+ 0x003fffff 0x003f8000 0x00000000 /* pioD */
-+ >;
-+ };
-+ };
-+ };
-+};
-diff --git a/arch/arm/boot/dts/at91sam9x25ek.dts b/arch/arm/boot/dts/at91sam9x25ek.dts
-index cf903f5..7e38951 100644
---- a/arch/arm/boot/dts/at91sam9x25ek.dts
-+++ b/arch/arm/boot/dts/at91sam9x25ek.dts
-@@ -7,38 +7,20 @@
- * Licensed under GPLv2 or later.
- */
- /dts-v1/;
--/include/ "at91sam9x5_common.dtsi"
-+/include/ "at91sam9x25.dtsi"
-+/include/ "at91sam9x5ek.dtsi"
-
- / {
-- model = "Atmel AT91SAM9X25-EK";
-+ model = "Atmel AT91SAM9G25-EK";
- compatible = "atmel,at91sam9x25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
-
-- chosen {
-- bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
-- };
--
- ahb {
- apb {
- mmc1: mmc@f000c000 {
- status = "okay";
-- slot@0 {
-- reg = <0>;
-- bus-width = <4>;
-- cd-gpios = <&pioD 14 0>;
-- };
-- };
--
-- usart0: serial@f801c000 {
-- status = "okay";
-- };
--
-- macb0: ethernet@f802c000 {
-- phy-mode = "rmii";
-- status = "okay";
- };
-
- macb1: ethernet@f8030000 {
-- phy-mode = "rmii";
- status = "okay";
- };
- };
-diff --git a/arch/arm/boot/dts/at91sam9x35.dtsi b/arch/arm/boot/dts/at91sam9x35.dtsi
-new file mode 100644
-index 0000000..fb102d6
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9x35.dtsi
-@@ -0,0 +1,28 @@
-+/*
-+ * at91sam9x35.dtsi - Device Tree Include file for AT91SAM9X35 SoC
-+ *
-+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-+ *
-+ * Licensed under GPLv2.
-+ */
-+
-+/include/ "at91sam9x5.dtsi"
-+
-+/ {
-+ model = "Atmel AT91SAM9X35 SoC";
-+ compatible = "atmel, at91sam9x35, atmel,at91sam9x5";
-+
-+ ahb {
-+ apb {
-+ pinctrl@fffff400 {
-+ atmel,mux-mask = <
-+ /* A B C */
-+ 0xffffffff 0xffe03fff 0xc000000c /* pioA */
-+ 0x000406ff 0x00047e3f 0x00000000 /* pioB */
-+ 0xfdffffff 0x00000000 0xb83fffff /* pioC */
-+ 0x003fffff 0x003f8000 0x00000000 /* pioD */
-+ >;
-+ };
-+ };
-+ };
-+};
-diff --git a/arch/arm/boot/dts/at91sam9x35ek.dts b/arch/arm/boot/dts/at91sam9x35ek.dts
-new file mode 100644
-index 0000000..5ccb607
---- /dev/null
-+++ b/arch/arm/boot/dts/at91sam9x35ek.dts
-@@ -0,0 +1,16 @@
-+/*
-+ * at91sam9x35ek.dts - Device Tree file for AT91SAM9X35-EK board
-+ *
-+ * Copyright (C) 2012 Atmel,
-+ * 2012 Nicolas Ferre <nicolas.ferre@atmel.com>
-+ *
-+ * Licensed under GPLv2 or later.
-+ */
-+/dts-v1/;
-+/include/ "at91sam9x35.dtsi"
-+/include/ "at91sam9x5ek.dtsi"
-+
-+/ {
-+ model = "Atmel AT91SAM9X35-EK";
-+ compatible = "atmel,at91sam9x35ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
-+};
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index 28e053a..7cefc2c 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -113,21 +113,92 @@
- #dma-cells = <1>;
- };
-
-- pinctrl@fffff200 {
-+ pinctrl@fffff400 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus";
- ranges = <0xfffff400 0xfffff400 0x800>;
-
-- atmel,mux-mask = <
-- /* A B C */
-- 0xffffffff 0xffe0399f 0xc000001c /* pioA */
-- 0xffffffff 0xffc003ff 0xffc003ff /* pioB */
-- 0xffffffff 0xffc003ff 0xffc003ff /* pioC */
-- 0xffffffff 0xffc003ff 0xffc003ff /* pioD */
-- >;
--
- /* shared pinctrl settings */
-+ dbgu {
-+ pinctrl_dbgu: dbgu-0 {
-+ atmel,pins =
-+ <0 9 0x1 0x0 /* PA9 periph A */
-+ 0 10 0x1 0x1>; /* PA10 periph A with pullup */
-+ };
-+ };
-+
-+ uart0 {
-+ pinctrl_uart0: uart0-0 {
-+ atmel,pins =
-+ <0 0 0x1 0x1 /* PA0 periph A with pullup */
-+ 0 1 0x1 0x0>; /* PA1 periph A */
-+ };
-+
-+ pinctrl_uart0_rts_cts: uart0_rts_cts-0 {
-+ atmel,pins =
-+ <0 2 0x1 0x0 /* PA2 periph A */
-+ 0 3 0x1 0x0>; /* PA3 periph A */
-+ };
-+ };
-+
-+ uart1 {
-+ pinctrl_uart1: uart1-0 {
-+ atmel,pins =
-+ <0 5 0x1 0x1 /* PA5 periph A with pullup */
-+ 0 6 0x1 0x0>; /* PA6 periph A */
-+ };
-+
-+ pinctrl_uart1_rts_cts: uart1_rts_cts-0 {
-+ atmel,pins =
-+ <3 27 0x3 0x0 /* PC27 periph C */
-+ 3 28 0x3 0x0>; /* PC28 periph C */
-+ };
-+ };
-+
-+ uart2 {
-+ pinctrl_uart2: uart2-0 {
-+ atmel,pins =
-+ <0 7 0x1 0x1 /* PA7 periph A with pullup */
-+ 0 8 0x1 0x0>; /* PA8 periph A */
-+ };
-+
-+ pinctrl_uart2_rts_cts: uart2_rts_cts-0 {
-+ atmel,pins =
-+ <0 0 0x2 0x0 /* PB0 periph B */
-+ 0 1 0x2 0x0>; /* PB1 periph B */
-+ };
-+ };
-+
-+ uart3 {
-+ pinctrl_uart3: uart3-0 {
-+ atmel,pins =
-+ <3 23 0x2 0x1 /* PC22 periph B with pullup */
-+ 3 23 0x2 0x0>; /* PC23 periph B */
-+ };
-+
-+ pinctrl_uart3_rts_cts: uart3_rts_cts-0 {
-+ atmel,pins =
-+ <3 24 0x2 0x0 /* PC24 periph B */
-+ 3 25 0x2 0x0>; /* PC25 periph B */
-+ };
-+ };
-+
-+ usart0 {
-+ pinctrl_usart0: usart0-0 {
-+ atmel,pins =
-+ <3 8 0x3 0x0 /* PC8 periph C */
-+ 3 9 0x3 0x1>; /* PC9 periph C with pullup */
-+ };
-+ };
-+
-+ usart1 {
-+ pinctrl_usart1: usart1-0 {
-+ atmel,pins =
-+ <3 16 0x3 0x0 /* PC16 periph C */
-+ 3 17 0x3 0x1>; /* PC17 periph C with pullup */
-+ };
-+ };
-
- nand {
- pinctrl_nand: nand-0 {
-@@ -184,6 +255,8 @@
- compatible = "atmel,at91sam9260-usart";
- reg = <0xfffff200 0x200>;
- interrupts = <1 4 7>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_dbgu>;
- status = "disabled";
- };
-
-@@ -193,6 +266,8 @@
- interrupts = <5 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart0>;
- status = "disabled";
- };
-
-@@ -202,6 +277,8 @@
- interrupts = <6 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart1>;
- status = "disabled";
- };
-
-@@ -211,6 +288,8 @@
- interrupts = <7 4 5>;
- atmel,use-dma-rx;
- atmel,use-dma-tx;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart2>;
- status = "disabled";
- };
-
-diff --git a/arch/arm/boot/dts/at91sam9x5_common.dtsi b/arch/arm/boot/dts/at91sam9x5ek.dtsi
-similarity index 54%
-rename from arch/arm/boot/dts/at91sam9x5_common.dtsi
-rename to arch/arm/boot/dts/at91sam9x5ek.dtsi
-index b805425..8854794 100644
---- a/arch/arm/boot/dts/at91sam9x5_common.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5ek.dtsi
-@@ -1,22 +1,31 @@
- /*
-- * at91sam9x5_common.dtsi - Device Tree Include file for AT91SAM9x5 Evaluation Kit:
-- * common peripherals.
-+ * at91sam9x5ek.dtsi - Device Tree file for AT91SAM9x5CM Base board
- *
- * Copyright (C) 2012 Atmel,
- * 2012 Nicolas Ferre <nicolas.ferre@atmel.com>
- *
- * Licensed under GPLv2 or later.
- */
--/include/ "at91sam9x5.dtsi"
- /include/ "at91sam9x5cm.dtsi"
-
- / {
-+ model = "Atmel AT91SAM9X5-EK";
-+ compatible = "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
-+
-+ chosen {
-+ bootargs = "128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
-+ };
-+
- ahb {
- apb {
- dbgu: serial@fffff200 {
- status = "okay";
- };
-
-+ usart0: serial@f801c000 {
-+ status = "okay";
-+ };
-+
- mmc0: mmc@f0008000 {
- status = "okay";
- slot@0 {
-@@ -26,6 +35,23 @@
- };
- };
-
-+ mmc1: mmc@f000c000 {
-+ slot@0 {
-+ reg = <0>;
-+ bus-width = <4>;
-+ cd-gpios = <&pioD 14 0>;
-+ };
-+ };
-+
-+ macb0: ethernet@f802c000 {
-+ phy-mode = "rmii";
-+ status = "okay";
-+ };
-+
-+ macb1: ethernet@f8030000 {
-+ phy-mode = "rmii";
-+ };
-+
- i2c0: i2c@f8010000 {
- status = "okay";
- };
-diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
-index 410485a..f63b8bf 100644
---- a/arch/arm/mach-at91/Makefile.boot
-+++ b/arch/arm/mach-at91/Makefile.boot
-@@ -33,6 +33,8 @@ dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9m10g45ek.dtb
- # sam9n12
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9n12ek.dtb
- # sam9x5
-+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g15ek.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g25ek.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g35ek.dtb
- dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9x25ek.dtb
-+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9x35ek.dtb
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 11835542ca3b571da8a2cf2ef0ffe65260818ff9 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 19 Oct 2012 07:14:06 +0800
-Subject: ARM: at91/DT: add i2c mmc nand pinctrl in device tree support
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/boot/dts/at91sam9x5.dtsi | 132 +++++++++++++++++++++++++++++++-----
- arch/arm/boot/dts/at91sam9x5ek.dtsi | 24 ++++---
- arch/arm/mach-at91/board-dt.c | 27 --------
- 3 files changed, 130 insertions(+), 53 deletions(-)
-
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index 7cefc2c..726bb82 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -151,8 +151,8 @@
-
- pinctrl_uart1_rts_cts: uart1_rts_cts-0 {
- atmel,pins =
-- <3 27 0x3 0x0 /* PC27 periph C */
-- 3 28 0x3 0x0>; /* PC28 periph C */
-+ <2 27 0x3 0x0 /* PC27 periph C */
-+ 2 28 0x3 0x0>; /* PC28 periph C */
- };
- };
-
-@@ -165,46 +165,134 @@
-
- pinctrl_uart2_rts_cts: uart2_rts_cts-0 {
- atmel,pins =
-- <0 0 0x2 0x0 /* PB0 periph B */
-- 0 1 0x2 0x0>; /* PB1 periph B */
-+ <1 0 0x2 0x0 /* PB0 periph B */
-+ 1 1 0x2 0x0>; /* PB1 periph B */
- };
- };
-
- uart3 {
- pinctrl_uart3: uart3-0 {
- atmel,pins =
-- <3 23 0x2 0x1 /* PC22 periph B with pullup */
-- 3 23 0x2 0x0>; /* PC23 periph B */
-+ <2 22 0x2 0x1 /* PC22 periph B with pullup */
-+ 2 23 0x2 0x0>; /* PC23 periph B */
- };
-
- pinctrl_uart3_rts_cts: uart3_rts_cts-0 {
- atmel,pins =
-- <3 24 0x2 0x0 /* PC24 periph B */
-- 3 25 0x2 0x0>; /* PC25 periph B */
-+ <2 24 0x2 0x0 /* PC24 periph B */
-+ 2 25 0x2 0x0>; /* PC25 periph B */
- };
- };
-
- usart0 {
- pinctrl_usart0: usart0-0 {
- atmel,pins =
-- <3 8 0x3 0x0 /* PC8 periph C */
-- 3 9 0x3 0x1>; /* PC9 periph C with pullup */
-+ <2 8 0x3 0x0 /* PC8 periph C */
-+ 2 9 0x3 0x1>; /* PC9 periph C with pullup */
- };
- };
-
- usart1 {
- pinctrl_usart1: usart1-0 {
- atmel,pins =
-- <3 16 0x3 0x0 /* PC16 periph C */
-- 3 17 0x3 0x1>; /* PC17 periph C with pullup */
-+ <2 16 0x3 0x0 /* PC16 periph C */
-+ 2 17 0x3 0x1>; /* PC17 periph C with pullup */
- };
- };
-
- nand {
-- pinctrl_nand: nand-0 {
-+ pinctrl_nand_rdy_enable: nand_rdy_enable-0 {
- atmel,pins =
-- <3 4 0x0 0x1 /* PD5 gpio RDY pin pull_up */
-- 3 5 0x0 0x1>; /* PD4 gpio enable pin pull_up */
-+ <3 5 0x0 0x1 /* PD5 gpio RDY pin pull_up */
-+ 3 4 0x0 0x1>; /* PD4 gpio enable pin pull_up */
-+ };
-+
-+ pinctrl_nand_oe_we_ale_cle: nand_oe_we_ale_cle-0 {
-+ atmel,pins =
-+ <3 0 0x1 0x1 /* PD0 periph A with pullup */
-+ 3 1 0x1 0x1 /* PD1 periph A with pullup */
-+ 3 2 0x1 0x1 /* PD2 periph A with pullup */
-+ 3 3 0x1 0x1>; /* PD3 periph A with pullup */
-+ };
-+
-+ pinctrl_nand_bus_on_d16_8bit: nand_bus_on_d16_8bit-0 {
-+ atmel,pins =
-+ <3 6 0x1 0x1 /* PD6 periph A with pullup */
-+ 3 7 0x1 0x1 /* PD7 periph A with pullup */
-+ 3 8 0x1 0x1 /* PD8 periph A with pullup */
-+ 3 9 0x1 0x1 /* PD9 periph A with pullup */
-+ 3 10 0x1 0x1 /* PD10 periph A with pullup */
-+ 3 11 0x1 0x1 /* PD11 periph A with pullup */
-+ 3 12 0x1 0x1 /* PD12 periph A with pullup */
-+ 3 13 0x1 0x1>; /* PD13 periph A with pullup */
-+ };
-+
-+ pinctrl_nand_bus_on_d16_16bit: nand_bus_on_d16_16bit-0 {
-+ atmel,pins =
-+ <3 14 0x1 0x1 /* PD14 periph A with pullup */
-+ 3 15 0x1 0x1 /* PD15 periph A with pullup */
-+ 3 16 0x1 0x1 /* PD16 periph A with pullup */
-+ 3 17 0x1 0x1 /* PD17 periph A with pullup */
-+ 3 18 0x1 0x1 /* PD18 periph A with pullup */
-+ 3 19 0x1 0x1 /* PD19 periph A with pullup */
-+ 3 20 0x1 0x1 /* PD20 periph A with pullup */
-+ 3 21 0x1 0x1>; /* PD21 periph A with pullup */
-+ };
-+ };
-+
-+ i2c0 {
-+ pinctrl_i2c0: i2c0-0 {
-+ atmel,pins =
-+ <0 30 0x1 0x2 /* PA30 periph A Multidrive */
-+ 0 31 0x1 0x3>; /* PA31 periph A Multidrive with pullup */
-+ };
-+ };
-+
-+ i2c1 {
-+ pinctrl_i2c1: i2c1-0 {
-+ atmel,pins =
-+ <2 0 0x3 0x2 /* PC0 periph C Multidrive */
-+ 2 1 0x3 0x3>; /* PC1 periph C Multidrive with pullup */
-+ };
-+ };
-+
-+ i2c2 {
-+ pinctrl_i2c2: i2c2-0 {
-+ atmel,pins =
-+ <1 4 0x2 0x2 /* PB4 periph B Multidrive */
-+ 1 5 0x2 0x3>; /* PB5 periph B Multidrive with pullup */
-+ };
-+ };
-+
-+ mmc0 {
-+ pinctrl_mmc0_clk_cmd_dat0: mm0_clk_cmd_dat0 {
-+ atmel,pins =
-+ <0 17 0x1 0x0 /* PA17 periph A */
-+ 0 16 0x1 0x1 /* PA16 periph A with pullpup */
-+ 0 15 0x1 0x1>; /* PA15 periph A with pullpup */
-+ };
-+
-+ pinctrl_mmc0_dat1_3: mm0_dat1_3 {
-+ atmel,pins =
-+ <0 18 0x1 0x1 /* PA18 periph A with pullpup */
-+ 0 19 0x1 0x1 /* PA19 periph A with pullpup */
-+ 0 20 0x1 0x1>; /* PA20 periph A with pullpup */
-+ };
-+ };
-+
-+ mmc1 {
-+ pinctrl_mmc1_clk_cmd_dat0: mm1_clk_cmd_dat0 {
-+ atmel,pins =
-+ <0 13 0x2 0x0 /* PA13 periph B */
-+ 0 12 0x2 0x1 /* PA12 periph B with pullpup */
-+ 0 11 0x2 0x1>; /* PA11 periph B with pullpup */
-+ };
-+
-+ pinctrl_mmc1_dat1_3: mm1_dat1_3 {
-+ atmel,pins =
-+ <0 2 0x2 0x1 /* PA2 periph B with pullpup */
-+ 0 3 0x2 0x1 /* PA3 periph B with pullpup */
-+ 0 4 0x2 0x1>; /* PA4 periph B with pullpup */
- };
- };
-
-@@ -311,20 +399,22 @@
- compatible = "atmel,hsmci";
- reg = <0xf0008000 0x600>;
- interrupts = <12 4 0>;
-- status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
- dma = <&dma0 0x10002200>;
-+ pinctrl-names = "default";
-+ status = "disabled";
- };
-
- mmc1: mmc@f000c000 {
- compatible = "atmel,hsmci";
- reg = <0xf000c000 0x600>;
- interrupts = <26 4 0>;
-- status = "disabled";
- #address-cells = <1>;
- #size-cells = <0>;
- dma = <&dma1 0x10002200>;
-+ pinctrl-names = "default";
-+ status = "disabled";
- };
-
- i2c0: i2c@f8010000 {
-@@ -334,6 +424,8 @@
- dma = <&dma0 0x10002278>;
- #address-cells = <1>;
- #size-cells = <0>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_i2c0>;
- status = "disabled";
- };
-
-@@ -344,6 +436,8 @@
- dma = <&dma1 0x10002256>;
- #address-cells = <1>;
- #size-cells = <0>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_i2c1>;
- status = "disabled";
- };
-
-@@ -354,6 +448,8 @@
- dma = <&dma0 0x1000229A>;
- #address-cells = <1>;
- #size-cells = <0>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_i2c2>;
- status = "disabled";
- };
-
-@@ -393,7 +489,7 @@
- atmel,nand-addr-offset = <21>;
- atmel,nand-cmd-offset = <22>;
- pinctrl-names = "default";
-- pinctrl-0 = <&pinctrl_nand>;
-+ pinctrl-0 = <&pinctrl_nand_rdy_enable &pinctrl_nand_oe_we_ale_cle>;
- gpios = <&pioD 5 0
- &pioD 4 0
- 0
-diff --git a/arch/arm/boot/dts/at91sam9x5ek.dtsi b/arch/arm/boot/dts/at91sam9x5ek.dtsi
-index 8854794..0406e0d 100644
---- a/arch/arm/boot/dts/at91sam9x5ek.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5ek.dtsi
-@@ -18,6 +18,20 @@
-
- ahb {
- apb {
-+ pinctrl@fffff400 {
-+ board {
-+ pinctrl_mmc0_cd: mmc0_cd {
-+ atmel,pins =
-+ <3 15 0x0 0x5>; /* PD15 gpio with pullup deglitch */
-+ };
-+
-+ pinctrl_mmc1_cd: mmc1_cd {
-+ atmel,pins =
-+ <3 14 0x0 0x5>; /* PD14 gpio with pullup deglitch */
-+ };
-+ };
-+ };
-+
- dbgu: serial@fffff200 {
- status = "okay";
- };
-@@ -27,6 +41,7 @@
- };
-
- mmc0: mmc@f0008000 {
-+ pinctrl-0 = <&pinctrl_mmc0_clk_cmd_dat0 &pinctrl_mmc0_dat1_3 &pinctrl_mmc0_cd>;
- status = "okay";
- slot@0 {
- reg = <0>;
-@@ -36,6 +51,7 @@
- };
-
- mmc1: mmc@f000c000 {
-+ pinctrl-0 = <&pinctrl_mmc1_clk_cmd_dat0 &pinctrl_mmc1_dat1_3 &pinctrl_mmc1_cd>;
- slot@0 {
- reg = <0>;
- bus-width = <4>;
-@@ -55,14 +71,6 @@
- i2c0: i2c@f8010000 {
- status = "okay";
- };
--
-- i2c1: i2c@f8014000 {
-- status = "okay";
-- };
--
-- i2c2: i2c@f8018000 {
-- status = "okay";
-- };
- };
-
- usb0: ohci@00600000 {
-diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
-index b1a5d3c..95798f5 100644
---- a/arch/arm/mach-at91/board-dt.c
-+++ b/arch/arm/mach-at91/board-dt.c
-@@ -139,36 +139,9 @@ static void __init at91_dt_device_init(void)
- {
- /* Temporary pin mux stuff */
- if (of_machine_is_compatible("atmel,at91sam9x5")) {
-- at91_set_A_periph(AT91_PIN_PA30, 0); /* TWD */
-- at91_set_A_periph(AT91_PIN_PA31, 0); /* TWCK */
-- printk("AT91: i2c pin mux done\n");
- at91_set_gpio_input(AT91_PIN_PA7, 1);
- printk("AT91: qt1070 pin mux done\n");
-
-- at91_set_gpio_input(AT91_PIN_PD14, 1);
-- at91_set_deglitch(AT91_PIN_PD14, 1);
-- at91_set_gpio_input(AT91_PIN_PD15, 1);
-- at91_set_deglitch(AT91_PIN_PD15, 1);
-- /* CLK */
-- at91_set_A_periph(AT91_PIN_PA17, 0);
-- /* CMD */
-- at91_set_A_periph(AT91_PIN_PA16, 1);
-- /* DAT0, DAT1..DAT3 */
-- at91_set_A_periph(AT91_PIN_PA15, 1);
-- at91_set_A_periph(AT91_PIN_PA18, 1);
-- at91_set_A_periph(AT91_PIN_PA19, 1);
-- at91_set_A_periph(AT91_PIN_PA20, 1);
-- /* CLK */
-- at91_set_B_periph(AT91_PIN_PA13, 0);
-- /* CMD */
-- at91_set_B_periph(AT91_PIN_PA12, 1);
-- /* DAT0, DAT1..DAT3 */
-- at91_set_B_periph(AT91_PIN_PA11, 1);
-- at91_set_B_periph(AT91_PIN_PA2, 1);
-- at91_set_B_periph(AT91_PIN_PA3, 1);
-- at91_set_B_periph(AT91_PIN_PA4, 1);
-- printk("AT91: mci0/1 pin mux done\n");
--
- at91sam9x5_pinmux_lcd();
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 8d8a30e133d80f1d5a4f7c9a49496fadb5935018 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 19 Oct 2012 13:44:54 +0800
-Subject: at91sam9x5: add lcd pinctrl support
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/boot/dts/at91sam9x5.dtsi | 38 ++++++++++++++++++++++++++++++++++++++
- 1 file changed, 38 insertions(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index 726bb82..c1b0334 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -296,6 +296,42 @@
- };
- };
-
-+ lcd {
-+ pinctrl_lcd: lcd-0 {
-+ atmel,pins =
-+ <2 26 0x1 0x1 /* PC26 periph A */
-+ 2 27 0x1 0x1 /* PC27 periph A */
-+ 2 28 0x1 0x1 /* PC28 periph A */
-+ 2 24 0x1 0x1 /* PC24 periph A */
-+ 2 29 0x1 0x1 /* PC29 periph A */
-+ 2 30 0x1 0x1 /* PC30 periph A */
-+ 2 0 0x1 0x1 /* PC0 periph A */
-+ 2 1 0x1 0x1 /* PC1 periph A */
-+ 2 2 0x1 0x1 /* PC2 periph A */
-+ 2 3 0x1 0x1 /* PC3 periph A */
-+ 2 4 0x1 0x1 /* PC4 periph A */
-+ 2 5 0x1 0x1 /* PC5 periph A */
-+ 2 6 0x1 0x1 /* PC6 periph A */
-+ 2 7 0x1 0x1 /* PC7 periph A */
-+ 2 8 0x1 0x1 /* PC8 periph A */
-+ 2 9 0x1 0x1 /* PC9 periph A */
-+ 2 10 0x1 0x1 /* PC10 periph A */
-+ 2 11 0x1 0x1 /* PC11 periph A */
-+ 2 12 0x1 0x1 /* PC12 periph A */
-+ 2 13 0x1 0x1 /* PC13 periph A */
-+ 2 14 0x1 0x1 /* PC14 periph A */
-+ 2 15 0x1 0x1 /* PC15 periph A */
-+ 2 16 0x1 0x1 /* PC16 periph A */
-+ 2 17 0x1 0x1 /* PC17 periph A */
-+ 2 18 0x1 0x1 /* PC18 periph A */
-+ 2 19 0x1 0x1 /* PC19 periph A */
-+ 2 20 0x1 0x1 /* PC20 periph A */
-+ 2 21 0x1 0x1 /* PC21 periph A */
-+ 2 22 0x1 0x1 /* PC22 periph A */
-+ 2 23 0x1 0x1>; /* PC23 periph A */
-+ };
-+ };
-+
- pioA: gpio@fffff400 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x200>;
-@@ -458,6 +494,8 @@
- reg = <0xf8038000 0xff
- 0xf8038400 0x3ff>;
- interrupts = <25 4 3>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_lcd>;
- status = "disabled";
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 09d9306960be4117e00c086bc90bb510e581fdc9 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 19 Oct 2012 15:13:13 +0800
-Subject: arm: at91sam9x5ek: drop temporary pinmux
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/mach-at91/board-dt.c | 41 -----------------------------------------
- 1 file changed, 41 deletions(-)
-
-diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
-index 95798f5..16b6b3c 100644
---- a/arch/arm/mach-at91/board-dt.c
-+++ b/arch/arm/mach-at91/board-dt.c
-@@ -79,45 +79,6 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
- .lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB,
- };
-
--void __init at91sam9x5_pinmux_lcd(void)
--{
-- at91_set_A_periph(AT91_PIN_PC26, 0); /* LCDPWM */
--
-- at91_set_A_periph(AT91_PIN_PC27, 0); /* LCDVSYNC */
-- at91_set_A_periph(AT91_PIN_PC28, 0); /* LCDHSYNC */
--
-- at91_set_A_periph(AT91_PIN_PC24, 0); /* LCDDISP */
-- at91_set_A_periph(AT91_PIN_PC29, 0); /* LCDDEN */
-- at91_set_A_periph(AT91_PIN_PC30, 0); /* LCDPCK */
--
-- at91_set_A_periph(AT91_PIN_PC0, 0); /* LCDD0 */
-- at91_set_A_periph(AT91_PIN_PC1, 0); /* LCDD1 */
-- at91_set_A_periph(AT91_PIN_PC2, 0); /* LCDD2 */
-- at91_set_A_periph(AT91_PIN_PC3, 0); /* LCDD3 */
-- at91_set_A_periph(AT91_PIN_PC4, 0); /* LCDD4 */
-- at91_set_A_periph(AT91_PIN_PC5, 0); /* LCDD5 */
-- at91_set_A_periph(AT91_PIN_PC6, 0); /* LCDD6 */
-- at91_set_A_periph(AT91_PIN_PC7, 0); /* LCDD7 */
-- at91_set_A_periph(AT91_PIN_PC8, 0); /* LCDD8 */
-- at91_set_A_periph(AT91_PIN_PC9, 0); /* LCDD9 */
-- at91_set_A_periph(AT91_PIN_PC10, 0); /* LCDD10 */
-- at91_set_A_periph(AT91_PIN_PC11, 0); /* LCDD11 */
-- at91_set_A_periph(AT91_PIN_PC12, 0); /* LCDD12 */
-- at91_set_A_periph(AT91_PIN_PC13, 0); /* LCDD13 */
-- at91_set_A_periph(AT91_PIN_PC14, 0); /* LCDD14 */
-- at91_set_A_periph(AT91_PIN_PC15, 0); /* LCDD15 */
-- at91_set_A_periph(AT91_PIN_PC16, 0); /* LCDD16 */
-- at91_set_A_periph(AT91_PIN_PC17, 0); /* LCDD17 */
-- at91_set_A_periph(AT91_PIN_PC18, 0); /* LCDD18 */
-- at91_set_A_periph(AT91_PIN_PC19, 0); /* LCDD19 */
-- at91_set_A_periph(AT91_PIN_PC20, 0); /* LCDD20 */
-- at91_set_A_periph(AT91_PIN_PC21, 0); /* LCDD21 */
-- at91_set_A_periph(AT91_PIN_PC22, 0); /* LCDD22 */
-- at91_set_A_periph(AT91_PIN_PC23, 0); /* LCDD23 */
--
-- printk("AT91: lcd pin mux done\n");
--}
--
- struct of_dev_auxdata at91_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("atmel,at91sam9x5-lcd", 0xf8038000, "atmel_hlcdfb_base", &ek_lcdc_data),
- OF_DEV_AUXDATA("atmel,at91sam9x5-lcd", 0xf8038100, "atmel_hlcdfb_ovl", &ek_lcdc_data),
-@@ -141,8 +102,6 @@ static void __init at91_dt_device_init(void)
- if (of_machine_is_compatible("atmel,at91sam9x5")) {
- at91_set_gpio_input(AT91_PIN_PA7, 1);
- printk("AT91: qt1070 pin mux done\n");
--
-- at91sam9x5_pinmux_lcd();
- }
-
- of_platform_populate(NULL, of_default_bus_match_table, at91_auxdata_lookup, NULL);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ddf17dd12f2a3a717ad9b947682b5d7d3b350245 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Fri, 19 Oct 2012 14:11:05 +0800
-Subject: video: atmel lcd only request the pinctrl once
-
-Introduce simple bus to represent the LCDC itself so we can attached the
-pinctrl to it
-
-signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-
-Conflicts:
- arch/arm/boot/dts/at91sam9x5.dtsi
----
- arch/arm/boot/dts/at91sam9g35ek.dts | 17 ++++++++-----
- arch/arm/boot/dts/at91sam9x5.dtsi | 42 +++++++++++++++++-------------
- drivers/video/atmel_lcdfb_core.c | 51 +++++++++++++++++++++++++++++++------
- 3 files changed, 78 insertions(+), 32 deletions(-)
-
-diff --git a/arch/arm/boot/dts/at91sam9g35ek.dts b/arch/arm/boot/dts/at91sam9g35ek.dts
-index 2781a30..9f91dbc 100644
---- a/arch/arm/boot/dts/at91sam9g35ek.dts
-+++ b/arch/arm/boot/dts/at91sam9g35ek.dts
-@@ -20,16 +20,19 @@
- status = "okay";
- };
-
-- lcd@f8038000 {
-+ lcd_bus@f8038000 {
- status = "okay";
-- };
-+ lcd@f8038000 {
-+ status = "okay";
-+ };
-
-- lcdovl1@f8038100 {
-- status = "okay";
-- };
-+ lcdovl1@f8038100 {
-+ status = "okay";
-+ };
-
-- lcdheo1@f8038280 {
-- status = "okay";
-+ lcdheo1@f8038280 {
-+ status = "okay";
-+ };
- };
- };
- };
-diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
-index c1b0334..1fcbbe8 100644
---- a/arch/arm/boot/dts/at91sam9x5.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
-@@ -489,28 +489,36 @@
- status = "disabled";
- };
-
-- lcd@f8038000 {
-- compatible = "atmel,at91sam9x5-lcd";
-- reg = <0xf8038000 0xff
-- 0xf8038400 0x3ff>;
-- interrupts = <25 4 3>;
-+ lcd_bus@f8038000 {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "atmel,at91sam9x5-lcd-bus", "simple-bus";
-+ ranges = <0xf8038000 0xf8038000 0x4000>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_lcd>;
- status = "disabled";
-- };
-
-- lcdovl1@f8038100 {
-- compatible = "atmel,at91sam9x5-lcd";
-- reg = <0xf8038100 0xff
-- 0xf8038800 0x3ff>;
-- status = "disabled";
-- };
-+ lcd@f8038000 {
-+ compatible = "atmel,at91sam9x5-lcd";
-+ reg = <0xf8038000 0xff
-+ 0xf8038400 0x3ff>;
-+ interrupts = <25 4 3>;
-+ status = "disabled";
-+ };
-
-- lcdheo1@f8038280 {
-- compatible = "atmel,at91sam9x5-heo";
-- reg = <0xf8038280 0xbf>;
-- interrupts = <25 4 3>;
-- status = "disabled";
-+ lcdovl1@f8038100 {
-+ compatible = "atmel,at91sam9x5-lcd";
-+ reg = <0xf8038100 0xff
-+ 0xf8038800 0x3ff>;
-+ status = "disabled";
-+ };
-+
-+ lcdheo1@f8038280 {
-+ compatible = "atmel,at91sam9x5-heo";
-+ reg = <0xf8038280 0xbf>;
-+ interrupts = <25 4 3>;
-+ status = "disabled";
-+ };
- };
- };
-
-diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c
-index b71a80c..4d272ee 100644
---- a/drivers/video/atmel_lcdfb_core.c
-+++ b/drivers/video/atmel_lcdfb_core.c
-@@ -19,6 +19,8 @@
- #include <linux/init.h>
- #include <linux/delay.h>
- #include <linux/gfp.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-
- #include <mach/board.h>
- #include <mach/cpu.h>
-@@ -557,7 +559,6 @@ int __atmel_lcdfb_probe(struct platform_device *pdev,
- struct resource *regs = NULL, *clut = NULL;
- struct resource *map = NULL;
- int ret;
-- struct pinctrl *pinctrl;
-
- dev_dbg(dev, "%s BEGIN\n", __func__);
-
-@@ -637,13 +638,6 @@ int __atmel_lcdfb_probe(struct platform_device *pdev,
- goto stop_clk;
- }
-
-- pinctrl = devm_pinctrl_get_select_default(dev);
-- if (IS_ERR(pinctrl)) {
-- dev_err(dev, "Failed to request pinctrl\n");
-- ret = PTR_ERR(pinctrl);
-- goto stop_clk;
-- }
--
- /* No error checking, some devices can do without IRQ */
- sinfo->irq_base = platform_get_irq(pdev, 0);
-
-@@ -840,3 +834,44 @@ int __atmel_lcdfb_remove(struct platform_device *pdev)
- return 0;
- }
- EXPORT_SYMBOL_GPL(__atmel_lcdfb_remove);
-+
-+static const struct of_device_id atmel_lcdfb_bus_dt_ids[] = {
-+ { .compatible = "atmel,at91sam9x5-lcd-bus" },
-+ { /* sentinel */ }
-+};
-+
-+static int atmel_lcdfb_bus_probe(struct platform_device *pdev)
-+{
-+ struct pinctrl *pinctrl;
-+ struct device *dev = &pdev->dev;
-+
-+ pinctrl = devm_pinctrl_get_select_default(dev);
-+ if (IS_ERR(pinctrl)) {
-+ dev_err(dev, "Failed to request pinctrl\n");
-+ return PTR_ERR(pinctrl);
-+ }
-+
-+ return 0;
-+}
-+
-+static struct platform_driver atmel_lcdfb_bus = {
-+ .probe = atmel_lcdfb_bus_probe,
-+ .driver = {
-+ .name = "atmel_lcdfb_bus",
-+ .owner = THIS_MODULE,
-+ .of_match_table = of_match_ptr(atmel_lcdfb_bus_dt_ids),
-+ },
-+};
-+
-+static int __init atmel_lcdfb_bus_init(void)
-+{
-+ return platform_driver_register(&atmel_lcdfb_bus);
-+}
-+
-+static void __exit atmel_lcdfb_bus_exit(void)
-+{
-+ platform_driver_unregister(&atmel_lcdfb_bus);
-+}
-+
-+module_init(atmel_lcdfb_bus_init);
-+module_exit(atmel_lcdfb_bus_exit);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From d947868defbab5b064de68d4df8aaad09127c51f Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Wed, 26 Sep 2012 17:04:31 +0200
-Subject: ARM: at91: add at91-3.4-trunk-contents.txt file
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/at91-3.4-trunk-contents.txt | 71 ++++++++++++++++++++++++++
- 1 file changed, 71 insertions(+)
- create mode 100644 arch/arm/mach-at91/at91-3.4-trunk-contents.txt
-
-diff --git a/arch/arm/mach-at91/at91-3.4-trunk-contents.txt b/arch/arm/mach-at91/at91-3.4-trunk-contents.txt
-new file mode 100644
-index 0000000..bfc5a47
---- /dev/null
-+++ b/arch/arm/mach-at91/at91-3.4-trunk-contents.txt
-@@ -0,0 +1,71 @@
-+This file lists all branches that are pulled into the at91-3.4-trunk_merge
-+branch of git://rfolxts01.rfo.atmel.com/linux and their external dependencies.
-+
-+The at91-3.4-trunk/v3.4.x_* branches are kept in the order in which they
-+get applied.
-+
-+external dependencies:
-+NONE
-+
-+at91-3.4-trunk_merge:
-+at91-3.4-trunk/v3.4.x_base git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_base
-+
-+at91-3.4-trunk/v3.4.x_cleanup+fixes git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_cleanup+fixes
-+ depends on at91-3.4-trunk/v3.4.x_base
-+
-+at91-3.4-trunk/v3.4.x_aic5 git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_aic5
-+ depends on at91-3.4-trunk/v3.4.x_base
-+
-+at91-3.4-trunk/v3.4.x_dma git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_dma
-+at91-3.4-trunk/v3.4.x_ethernet git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_ethernet
-+at91-3.4-trunk/v3.4.x_ac97 git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_ac97
-+at91-3.4-trunk/v3.4.x_pmecc git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_pmecc
-+at91-3.4-trunk/v3.4.x_touch git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_touch
-+at91-3.4-trunk/v3.4.x_gmac git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_gmac
-+at91-3.4-trunk/v3.4.x_phy git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_phy
-+at91-3.4-trunk/v3.4.x_usb git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_usb
-+at91-3.4-trunk/v3.4.x_isi git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_isi
-+
-+at91-3.4-trunk/v3.4.x_lcd git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_lcd
-+at91-3.4-trunk/v3.4.x_soc_lcd git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_soc_lcd
-+ depends on at91-3.4-trunk/v3.4.x_base
-+ depends on at91-3.4-trunk/v3.4.x_lcd
-+
-+at91-3.4-trunk/v3.4.x_mci git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_mci
-+ depends on at91-3.4-trunk/v3.4.x_base
-+
-+at91-3.4-trunk/v3.4.x_i2c git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_i2c
-+ depends on at91-3.4-trunk/v3.4.x_base
-+at91-3.4-trunk/v3.4.x_slaveDMA_i2c git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_slaveDMA_i2c
-+ depends on at91-3.4-trunk/v3.4.x_i2c
-+
-+at91-3.4-trunk/v3.4.x_slaveDMA_mci git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_slaveDMA
-+ depends on at91-3.4-trunk/v3.4.x_mci
-+ depends on at91-3.4-trunk/v3.4.x_slaveDMA_i2c
-+
-+at91-3.4-trunk/v3.4.x_pinmux_sam9x5 git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_pinmux_sam9x5
-+ depends on at91-3.4-trunk/v3.4.x_base
-+
-+at91-3.4-trunk/v3.4.x_pmecc_4k_support git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_pmecc_4k_support
-+ depends on at91-3.4-trunk/v3.4.x_pmecc
-+
-+at91-3.4-trunk/v3.4.x_pmecc_dt_9x5 git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_pmecc_dt_9x5
-+ depends on at91-3.4-trunk/v3.4.x_pmecc
-+
-+at91-3.4-trunk/v3.4.x_sam9x5_dt git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_sam9x5_dt
-+ depends on at91-3.4-trunk/v3.4.x_pmecc_dt_9x5
-+ depends on at91-3.4-trunk/v3.4.x_lcd
-+ depends on at91-3.4-trunk/v3.4.x_pinmux_sam9x5
-+
-+at91-3.4-trunk/v3.4.x_crypto git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_crypto
-+ depends on at91-3.4-trunk/v3.4.x_aic5
-+
-+at91-3.4-trunk/v3.4.x_pinctrl git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_pinctrl
-+ depends on at91-3.4-trunk/v3.4.x_base
-+ depends on at91-3.4-trunk/v3.4.x_cleanup+fixes
-+ depends on at91-3.4-trunk/v3.4.x_aic5
-+ depends on at91-3.4-trunk/v3.4.x_pmecc
-+ depends on at91-3.4-trunk/v3.4.x_pmecc_4k_support
-+
-+at91-3.4-trunk/v3.4.x_pinctrl_drivers git://rfolxts01.rfo.atmel.com/linux at91-3.4-trunk/v3.4.x_pinctrl_drivers
-+ depends on **ALL**
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b5aefffc52ac50286873f9f5952f6bb428f822c7 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Wed, 17 Oct 2012 11:37:49 +0200
-Subject: ARM: at91: add defconfig for sam9x5 family
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/configs/at91sam9x5_defconfig | 238 ++++++++++++++++++++++++++++++++++
- 1 file changed, 238 insertions(+)
- create mode 100644 arch/arm/configs/at91sam9x5_defconfig
-
-diff --git a/arch/arm/configs/at91sam9x5_defconfig b/arch/arm/configs/at91sam9x5_defconfig
-new file mode 100644
-index 0000000..0dbbf71
---- /dev/null
-+++ b/arch/arm/configs/at91sam9x5_defconfig
-@@ -0,0 +1,238 @@
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_LOCALVERSION_AUTO is not set
-+# CONFIG_SWAP is not set
-+CONFIG_SYSVIPC=y
-+CONFIG_POSIX_MQUEUE=y
-+CONFIG_IRQ_DOMAIN_DEBUG=y
-+CONFIG_LOG_BUF_SHIFT=14
-+CONFIG_BLK_DEV_INITRD=y
-+CONFIG_KALLSYMS_ALL=y
-+CONFIG_EMBEDDED=y
-+CONFIG_SLAB=y
-+CONFIG_MODULES=y
-+CONFIG_MODULE_UNLOAD=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_ARCH_AT91=y
-+CONFIG_SOC_AT91SAM9X5=y
-+CONFIG_MACH_AT91SAM_DT=y
-+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-+CONFIG_AEABI=y
-+# CONFIG_OABI_COMPAT is not set
-+CONFIG_LEDS=y
-+CONFIG_LEDS_CPU=y
-+CONFIG_UACCESS_WITH_MEMCPY=y
-+CONFIG_ZBOOT_ROM_TEXT=0x0
-+CONFIG_ZBOOT_ROM_BSS=0x0
-+CONFIG_ARM_APPENDED_DTB=y
-+CONFIG_ARM_ATAG_DTB_COMPAT=y
-+CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw"
-+CONFIG_AUTO_ZRELADDR=y
-+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-+CONFIG_NET=y
-+CONFIG_PACKET=y
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+CONFIG_IP_MULTICAST=y
-+CONFIG_IP_PNP=y
-+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-+# CONFIG_INET_XFRM_MODE_BEET is not set
-+# CONFIG_INET_DIAG is not set
-+CONFIG_IPV6=y
-+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-+# CONFIG_INET6_XFRM_MODE_BEET is not set
-+CONFIG_IPV6_SIT_6RD=y
-+CONFIG_CFG80211=y
-+# CONFIG_CFG80211_DEFAULT_PS is not set
-+CONFIG_CFG80211_DEBUGFS=y
-+CONFIG_WIRELESS_EXT_SYSFS=y
-+CONFIG_MAC80211=y
-+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-+CONFIG_DEVTMPFS=y
-+CONFIG_DEVTMPFS_MOUNT=y
-+# CONFIG_STANDALONE is not set
-+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-+CONFIG_MTD=y
-+CONFIG_MTD_CMDLINE_PARTS=y
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+CONFIG_MTD_NAND=y
-+CONFIG_MTD_NAND_ATMEL=y
-+CONFIG_MTD_UBI=y
-+CONFIG_PROC_DEVICETREE=y
-+CONFIG_BLK_DEV_LOOP=y
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_BLK_DEV_RAM_COUNT=4
-+CONFIG_BLK_DEV_RAM_SIZE=8192
-+CONFIG_ATMEL_TCLIB=y
-+CONFIG_EEPROM_AT24=y
-+CONFIG_SCSI=y
-+CONFIG_BLK_DEV_SD=y
-+CONFIG_SCSI_MULTI_LUN=y
-+# CONFIG_SCSI_LOWLEVEL is not set
-+CONFIG_NETDEVICES=y
-+CONFIG_MII=y
-+CONFIG_MACB=y
-+# CONFIG_NET_VENDOR_BROADCOM is not set
-+# CONFIG_NET_VENDOR_CHELSIO is not set
-+# CONFIG_NET_VENDOR_CIRRUS is not set
-+# CONFIG_NET_VENDOR_FARADAY is not set
-+# CONFIG_NET_VENDOR_INTEL is not set
-+# CONFIG_NET_VENDOR_MARVELL is not set
-+# CONFIG_NET_VENDOR_MICREL is not set
-+# CONFIG_NET_VENDOR_NATSEMI is not set
-+# CONFIG_NET_VENDOR_SEEQ is not set
-+# CONFIG_NET_VENDOR_SMSC is not set
-+# CONFIG_NET_VENDOR_STMICRO is not set
-+CONFIG_DAVICOM_PHY=y
-+CONFIG_MICREL_PHY=y
-+CONFIG_LIBERTAS_THINFIRM=m
-+CONFIG_LIBERTAS_THINFIRM_USB=m
-+CONFIG_AT76C50X_USB=m
-+CONFIG_USB_ZD1201=m
-+CONFIG_RTL8187=m
-+CONFIG_ATH_COMMON=m
-+CONFIG_ATH9K=m
-+CONFIG_ATH6KL=m
-+CONFIG_ATH6KL_SDIO=m
-+CONFIG_ATH6KL_USB=m
-+CONFIG_B43=m
-+CONFIG_B43_SDIO=y
-+CONFIG_B43_DEBUG=y
-+CONFIG_B43LEGACY=m
-+CONFIG_BRCMFMAC=m
-+CONFIG_BRCMFMAC_USB=y
-+CONFIG_IWM=m
-+CONFIG_LIBERTAS=m
-+CONFIG_LIBERTAS_USB=m
-+CONFIG_LIBERTAS_SDIO=m
-+CONFIG_P54_COMMON=m
-+CONFIG_RT2X00=m
-+CONFIG_RT2500USB=m
-+CONFIG_RT73USB=m
-+CONFIG_RT2800USB=m
-+CONFIG_RT2800USB_RT53XX=y
-+CONFIG_RT2800USB_UNKNOWN=y
-+CONFIG_RTL8192CU=m
-+CONFIG_WL1251=m
-+CONFIG_WL1251_SDIO=m
-+CONFIG_WL12XX_MENU=m
-+CONFIG_WL12XX=m
-+CONFIG_WL12XX_SDIO=m
-+CONFIG_ZD1211RW=m
-+CONFIG_MWIFIEX=m
-+CONFIG_MWIFIEX_SDIO=m
-+CONFIG_INPUT_POLLDEV=m
-+# CONFIG_INPUT_MOUSEDEV is not set
-+CONFIG_INPUT_JOYDEV=y
-+CONFIG_INPUT_EVDEV=y
-+# CONFIG_KEYBOARD_ATKBD is not set
-+CONFIG_KEYBOARD_QT1070=y
-+CONFIG_KEYBOARD_GPIO=y
-+# CONFIG_INPUT_MOUSE is not set
-+CONFIG_INPUT_TOUCHSCREEN=y
-+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
-+CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
-+# CONFIG_SERIO is not set
-+CONFIG_LEGACY_PTY_COUNT=4
-+CONFIG_SERIAL_ATMEL=y
-+CONFIG_SERIAL_ATMEL_CONSOLE=y
-+# CONFIG_HW_RANDOM is not set
-+CONFIG_I2C=y
-+CONFIG_I2C_CHARDEV=y
-+CONFIG_I2C_AT91=y
-+CONFIG_GPIO_SYSFS=y
-+# CONFIG_HWMON is not set
-+CONFIG_MEDIA_SUPPORT=y
-+CONFIG_MEDIA_CONTROLLER=y
-+CONFIG_VIDEO_DEV=y
-+CONFIG_VIDEO_V4L2_SUBDEV_API=y
-+# CONFIG_RC_CORE is not set
-+# CONFIG_MEDIA_TUNER_SIMPLE is not set
-+# CONFIG_MEDIA_TUNER_TDA8290 is not set
-+# CONFIG_MEDIA_TUNER_TDA827X is not set
-+# CONFIG_MEDIA_TUNER_TDA18271 is not set
-+# CONFIG_MEDIA_TUNER_TDA9887 is not set
-+# CONFIG_MEDIA_TUNER_TEA5761 is not set
-+# CONFIG_MEDIA_TUNER_TEA5767 is not set
-+# CONFIG_MEDIA_TUNER_MT20XX is not set
-+# CONFIG_MEDIA_TUNER_MT2060 is not set
-+# CONFIG_MEDIA_TUNER_MT2063 is not set
-+# CONFIG_MEDIA_TUNER_MT2266 is not set
-+# CONFIG_MEDIA_TUNER_MT2131 is not set
-+# CONFIG_MEDIA_TUNER_QT1010 is not set
-+# CONFIG_MEDIA_TUNER_XC2028 is not set
-+# CONFIG_MEDIA_TUNER_XC5000 is not set
-+# CONFIG_MEDIA_TUNER_XC4000 is not set
-+# CONFIG_MEDIA_TUNER_MXL5005S is not set
-+# CONFIG_MEDIA_TUNER_MXL5007T is not set
-+# CONFIG_MEDIA_TUNER_MC44S803 is not set
-+# CONFIG_MEDIA_TUNER_MAX2165 is not set
-+# CONFIG_MEDIA_TUNER_TDA18218 is not set
-+# CONFIG_MEDIA_TUNER_TDA18212 is not set
-+CONFIG_VIDEO_FIXED_MINOR_RANGES=y
-+# CONFIG_V4L_USB_DRIVERS is not set
-+CONFIG_V4L_PLATFORM_DRIVERS=y
-+CONFIG_SOC_CAMERA=y
-+CONFIG_SOC_CAMERA_OV2640=y
-+CONFIG_VIDEO_ATMEL_ISI=y
-+CONFIG_VIDEO_AT91SAM9X5=y
-+# CONFIG_RADIO_ADAPTERS is not set
-+CONFIG_FB=y
-+CONFIG_FB_MODE_HELPERS=y
-+CONFIG_FB_ATMEL_HLCD=y
-+CONFIG_BACKLIGHT_LCD_SUPPORT=y
-+# CONFIG_LCD_CLASS_DEVICE is not set
-+CONFIG_BACKLIGHT_CLASS_DEVICE=y
-+# CONFIG_BACKLIGHT_GENERIC is not set
-+CONFIG_USB=y
-+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-+CONFIG_USB_EHCI_HCD=y
-+CONFIG_USB_OHCI_HCD=y
-+CONFIG_USB_STORAGE=y
-+CONFIG_USB_SERIAL=y
-+CONFIG_MMC=y
-+# CONFIG_MMC_BLOCK_BOUNCE is not set
-+CONFIG_SDIO_UART=m
-+CONFIG_MMC_ATMELMCI=y
-+CONFIG_LEDS_CLASS=y
-+CONFIG_LEDS_GPIO=y
-+CONFIG_LEDS_TRIGGER_TIMER=y
-+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-+CONFIG_LEDS_TRIGGER_GPIO=y
-+CONFIG_RTC_CLASS=y
-+CONFIG_RTC_DRV_AT91RM9200=y
-+CONFIG_DMADEVICES=y
-+CONFIG_AT_HDMAC=y
-+CONFIG_DMATEST=m
-+# CONFIG_IOMMU_SUPPORT is not set
-+CONFIG_EXT2_FS=y
-+CONFIG_FANOTIFY=y
-+CONFIG_VFAT_FS=y
-+CONFIG_TMPFS=y
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_SUMMARY=y
-+CONFIG_UBIFS_FS=y
-+CONFIG_UBIFS_FS_XATTR=y
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+CONFIG_ROOT_NFS=y
-+CONFIG_NLS_CODEPAGE_437=y
-+CONFIG_NLS_CODEPAGE_850=y
-+CONFIG_NLS_ISO8859_1=y
-+CONFIG_STRIP_ASM_SYMS=y
-+CONFIG_DEBUG_FS=y
-+# CONFIG_SCHED_DEBUG is not set
-+# CONFIG_FTRACE is not set
-+CONFIG_DEBUG_USER=y
-+CONFIG_DEBUG_LL=y
-+CONFIG_EARLY_PRINTK=y
-+CONFIG_CRYPTO_ECB=y
-+# CONFIG_CRYPTO_ANSI_CPRNG is not set
-+CONFIG_CRYPTO_USER_API_HASH=m
-+CONFIG_CRYPTO_USER_API_SKCIPHER=m
-+# CONFIG_CRYPTO_HW is not set
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e21c824bce9438f80a402e4ac4b8b1f017964138 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Wed, 20 Jun 2012 18:05:56 +0200
-Subject: MMC: atmel-mci: add device tree property for configuration
-
-Configuration option is now handled by the "dma" device tree property
-that links to the corresponding DMA controller.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/mmc/host/atmel-mci.c | 82 +++++++++++++++++++++++++++++++++++++++----
- 1 file changed, 75 insertions(+), 7 deletions(-)
-
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -513,12 +513,65 @@ static const struct of_device_id atmci_d
-
- MODULE_DEVICE_TABLE(of, atmci_dt_ids);
-
-+static int atmci_dma_of_init(struct device_node *np,
-+ struct at_dma_slave *atslave)
-+{
-+ struct of_phandle_args dma_spec;
-+ struct device_node *dmac_np;
-+ struct platform_device *dmac_pdev;
-+ const __be32 *nbcells;
-+ int ret;
-+
-+ ret = of_parse_phandle_with_args(np, "dma", "#dma-cells", 0, &dma_spec);
-+ if (ret || !dma_spec.np) {
-+ pr_err("%s: can't parse dma property (%d)\n", np->full_name, ret);
-+ goto err0;
-+ }
-+ dmac_np = dma_spec.np;
-+
-+ /* check property format */
-+ nbcells = of_get_property(dmac_np, "#dma-cells", NULL);
-+ if (!nbcells) {
-+ pr_err("%s: #dma-cells property is required\n", np->full_name);
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ if (dma_spec.args_count != be32_to_cpup(nbcells)
-+ || dma_spec.args_count != 1) {
-+ pr_err("%s: wrong #dma-cells for %s\n",
-+ np->full_name, dmac_np->full_name);
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ /* retreive DMA controller information */
-+ dmac_pdev = of_find_device_by_node(dmac_np);
-+ if (!dmac_pdev) {
-+ pr_err("%s: unable to find pdev from DMA controller\n",
-+ dmac_np->full_name);
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ /* now fill in the at_dma_slave structure */
-+ atslave->dma_dev = &dmac_pdev->dev;
-+ atslave->cfg = dma_spec.args[0];
-+
-+err1:
-+ of_node_put(dma_spec.np);
-+err0:
-+ pr_debug("%s exited with status %d\n", __func__, ret);
-+ return ret;
-+}
-+
- static struct mci_platform_data __devinit*
- atmci_of_init(struct platform_device *pdev)
- {
- struct device_node *np = pdev->dev.of_node;
- struct device_node *cnp;
- struct mci_platform_data *pdata;
-+ struct at_dma_slave *atslave;
- u32 slot_id;
-
- if (!np) {
-@@ -532,6 +585,24 @@ atmci_of_init(struct platform_device *pd
- return ERR_PTR(-ENOMEM);
- }
-
-+ pdata->dma_slave = devm_kzalloc(&pdev->dev,
-+ sizeof(*(pdata->dma_slave)),
-+ GFP_KERNEL);
-+ if (!pdata->dma_slave) {
-+ dev_err(&pdev->dev, "could not allocate memory for dma_slave\n");
-+ devm_kfree(&pdev->dev, pdata);
-+ return ERR_PTR(-ENOMEM);
-+ }
-+ atslave = &pdata->dma_slave->sdata;
-+
-+ /* retrive DMA configuration first */
-+ if (atmci_dma_of_init(np, atslave)) {
-+ dev_err(&pdev->dev, "could not find DMA parameters\n");
-+ devm_kfree(&pdev->dev, pdata->dma_slave);
-+ devm_kfree(&pdev->dev, pdata);
-+ return ERR_PTR(-EINVAL);
-+ }
-+
- for_each_child_of_node(np, cnp) {
- if (of_property_read_u32(cnp, "reg", &slot_id)) {
- dev_warn(&pdev->dev, "reg property is missing for %s\n",
-@@ -2259,16 +2330,13 @@ static bool atmci_filter(struct dma_chan
- }
- }
-
--static bool atmci_configure_dma(struct atmel_mci *host)
-+static bool atmci_configure_dma(struct atmel_mci *host,
-+ struct mci_platform_data *pdata)
- {
-- struct mci_platform_data *pdata;
--
- if (host == NULL)
- return false;
-
-- pdata = host->pdev->dev.platform_data;
--
-- if (pdata && find_slave_dev(pdata->dma_slave)) {
-+ if (pdata && pdata->dma_slave && find_slave_dev(pdata->dma_slave)) {
- dma_cap_mask_t mask;
-
- /* Try to grab a DMA channel */
-@@ -2420,7 +2488,7 @@ static int __init atmci_probe(struct pla
-
- /* Get MCI capabilities and set operations according to it */
- atmci_get_cap(host);
-- if (host->caps.has_dma && atmci_configure_dma(host)) {
-+ if (host->caps.has_dma && atmci_configure_dma(host, pdata)) {
- host->prepare_data = &atmci_prepare_data_dma;
- host->submit_data = &atmci_submit_data_dma;
- host->stop_transfer = &atmci_stop_transfer_dma;
+++ /dev/null
-From 87437fe8c93900352b99d6f883e730e7577f2a22 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Tue, 23 Oct 2012 13:47:30 +0800
-Subject: pinctrl: at19: fix typo on PULL_UP
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- drivers/pinctrl/pinctrl-at91.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
-index 605fffd..1a2404b 100644
---- a/drivers/pinctrl/pinctrl-at91.c
-+++ b/drivers/pinctrl/pinctrl-at91.c
-@@ -58,7 +58,7 @@ static struct at91_gpio_chip *gpio_chips[MAX_GPIO_BANKS];
-
- static int gpio_banks;
-
--#define PULL_UP (0 << 1)
-+#define PULL_UP (1 << 0)
- #define MULTI_DRIVE (1 << 1)
- #define DEGLITCH (1 << 2)
- #define PULL_DOWN (1 << 3)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From f5e557974fc40c9886708fba8a4ff73d88696a73 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Tue, 23 Oct 2012 14:25:36 +0800
-Subject: pinctrl: at91: fix pull down support
-
-Drop pullup disable in set_pulldown
-if the pullup is not needed the pull will be disable by set_pullup
-otherwise we will end up by always disabling the pullup
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- drivers/pinctrl/pinctrl-at91.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
-index 1a2404b..b836567 100644
---- a/drivers/pinctrl/pinctrl-at91.c
-+++ b/drivers/pinctrl/pinctrl-at91.c
-@@ -455,8 +455,6 @@ static bool at91_mux_pio3_get_pulldown(void __iomem *pio, unsigned pin)
-
- static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is_on)
- {
-- /* Disable pull-up anyway */
-- __raw_writel(mask, pio + PIO_PUDR);
- __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
- }
-
-@@ -753,6 +751,9 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
- pio = pin_to_controller(info, pin_to_bank(pin_id));
- mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK);
-
-+ if (config & PULL_UP && config & PULL_DOWN)
-+ return -EINVAL;
-+
- at91_mux_set_pullup(pio, mask, config & PULL_UP);
- at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE);
- if (info->ops->set_deglitch)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From c5e8d355aa1cc2b2fe24f55777cbc08454af9d24 Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Tue, 23 Oct 2012 15:06:54 +0800
-Subject: arm: at91sam9xcm: add specific nand pinctrl
-
-the nand is on d16 and 8bit
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/boot/dts/at91sam9x5cm.dtsi | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/arch/arm/boot/dts/at91sam9x5cm.dtsi b/arch/arm/boot/dts/at91sam9x5cm.dtsi
-index 4027ac7..ca049fb 100644
---- a/arch/arm/boot/dts/at91sam9x5cm.dtsi
-+++ b/arch/arm/boot/dts/at91sam9x5cm.dtsi
-@@ -31,6 +31,7 @@
- atmel,pmecc-cap = <2>;
- atmel,pmecc-sector-size = <512>;
- nand-on-flash-bbt;
-+ pinctrl-0 = <&pinctrl_nand_rdy_enable &pinctrl_nand_oe_we_ale_cle &pinctrl_nand_bus_on_d16_8bit>;
- status = "okay";
-
- at91bootstrap@0 {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 7bc6b19e0e851436b17dd40d9ec55566c19d4ceb Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Wed, 24 Oct 2012 01:15:51 +0800
-Subject: pinctrl: at91: fix debounce support
-
-add missing mask check
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- drivers/pinctrl/pinctrl-at91.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
-index b836567..f2e4ef5 100644
---- a/drivers/pinctrl/pinctrl-at91.c
-+++ b/drivers/pinctrl/pinctrl-at91.c
-@@ -759,7 +759,7 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
- if (info->ops->set_deglitch)
- info->ops->set_deglitch(pio, mask, config & DEGLITCH);
- if (info->ops->set_debounce)
-- info->ops->set_debounce(pio, mask, DEBOUNCE,
-+ info->ops->set_debounce(pio, mask, config & DEBOUNCE,
- (config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
- if (info->ops->set_pulldown)
- info->ops->set_pulldown(pio, mask, config & PULL_DOWN);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 270c2034f23b4fc57136c147f4e98daeaf28cffc Mon Sep 17 00:00:00 2001
-From: Marek Belisko <marek.belisko@open-nandra.com>
-Date: Mon, 1 Oct 2012 22:46:09 +0200
-Subject: ARM: at91/dts: at91sam9g20ek_common: Fix typos in buttons labels.
-
-commit b6edfbeacd5804038ea7ea8821a83ad704c107cc upstream.
-
-Signed-off-by: Marek Belisko <marek.belisko@open-nandra.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/boot/dts/at91sam9g20ek_common.dtsi | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
-index 6820417..e24116d 100644
---- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
-+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
-@@ -141,14 +141,14 @@
- #size-cells = <0>;
-
- btn3 {
-- label = "Buttin 3";
-+ label = "Button 3";
- gpios = <&pioA 30 1>;
- linux,code = <0x103>;
- gpio-key,wakeup;
- };
-
- btn4 {
-- label = "Buttin 4";
-+ label = "Button 4";
- gpios = <&pioA 31 1>;
- linux,code = <0x104>;
- gpio-key,wakeup;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From abf14fdfedb328e664222c2d7b6951d9d9c69a50 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Wed, 24 Oct 2012 16:19:47 +0200
-Subject: ARM: at91: fix external interrupt specification in board code
-
-commit 69e7ea04c9365626c0963ff09bbaa3a1b49e293a upstream.
-
-Since the switch to sparse irq, we have to add the NR_IRQS_LEGACY
-offset to static irq numbers. It has been forgotten on these
-SPI irq definitions in board code.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Cc: stable <stable@vger.kernel.org> [v3.6]
----
- arch/arm/mach-at91/board-neocore926.c | 2 +-
- arch/arm/mach-at91/board-sam9261ek.c | 2 +-
- arch/arm/mach-at91/board-sam9263ek.c | 2 +-
- 3 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
-index 7fb2a8f..05e2566 100644
---- a/arch/arm/mach-at91/board-neocore926.c
-+++ b/arch/arm/mach-at91/board-neocore926.c
-@@ -131,7 +131,7 @@ static struct spi_board_info neocore926_spi_devices[] = {
- .max_speed_hz = 125000 * 16,
- .bus_num = 0,
- .platform_data = &ads_info,
-- .irq = AT91SAM9263_ID_IRQ1,
-+ .irq = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1,
- },
- #endif
- };
-diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
-index b8900d5..a043192 100644
---- a/arch/arm/mach-at91/board-sam9261ek.c
-+++ b/arch/arm/mach-at91/board-sam9261ek.c
-@@ -311,7 +311,7 @@ static struct spi_board_info ek_spi_devices[] = {
- .max_speed_hz = 125000 * 26, /* (max sample rate @ 3V) * (cmd + data + overhead) */
- .bus_num = 0,
- .platform_data = &ads_info,
-- .irq = AT91SAM9261_ID_IRQ0,
-+ .irq = NR_IRQS_LEGACY + AT91SAM9261_ID_IRQ0,
- .controller_data = (void *) AT91_PIN_PA28, /* CS pin */
- },
- #endif
-diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
-index d4dd017..e0cef65 100644
---- a/arch/arm/mach-at91/board-sam9263ek.c
-+++ b/arch/arm/mach-at91/board-sam9263ek.c
-@@ -134,7 +134,7 @@ static struct spi_board_info ek_spi_devices[] = {
- .max_speed_hz = 125000 * 26, /* (max sample rate @ 3V) * (cmd + data + overhead) */
- .bus_num = 0,
- .platform_data = &ads_info,
-- .irq = AT91SAM9263_ID_IRQ1,
-+ .irq = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1,
- },
- #endif
- };
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 028918cfee7f910c65cf0dc9b126cb391700293b Mon Sep 17 00:00:00 2001
-From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Date: Wed, 24 Oct 2012 18:31:50 +0200
-Subject: ARM: at91: drop duplicated config SOC_AT91SAM9 entry
-
-commit 08d04a135a1c2e24c4d4bc7bbafee5e0e58f80c6 upstream.
-
-Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- arch/arm/mach-at91/Kconfig | 12 +++---------
- 1 file changed, 3 insertions(+), 9 deletions(-)
-
-diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
-index 79d08ed..b2ce9c4 100644
---- a/arch/arm/mach-at91/Kconfig
-+++ b/arch/arm/mach-at91/Kconfig
-@@ -19,21 +19,15 @@ config AT91_SAM9G45_RESET
-
- config SOC_AT91SAM9
- bool
-- select GENERIC_CLOCKEVENTS
- select CPU_ARM926T
-+ select GENERIC_CLOCKEVENTS
-+ select MULTI_IRQ_HANDLER
-+ select SPARSE_IRQ
-
- menu "Atmel AT91 System-on-Chip"
-
- comment "Atmel AT91 Processor"
-
--config SOC_AT91SAM9
-- bool
-- select CPU_ARM926T
-- select MULTI_IRQ_HANDLER
-- select SPARSE_IRQ
-- select AT91_SAM9_TIME
-- select AT91_SAM9_SMC
--
- config SOC_AT91RM9200
- bool "AT91RM9200"
- select CPU_ARM920T
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 66147723d43199d5aa36937cfaf5080bba782063 Mon Sep 17 00:00:00 2001
-From: Arnd Bergmann <arnd@arndb.de>
-Date: Fri, 26 Oct 2012 22:49:09 +0200
-Subject: ARM: at91: fix at91x40 build
-
-commit 0654f4ab2baa6100dc6b0b26f4f1fa3f02d10245 upstream.
-
-patch 738a0fd7 "ARM: at91: fix external interrupts in non-DT case"
-fixed a run-time error on some at91 platforms but did not apply
-the same change to at91x40, which now doesn't build.
-
-This changes at91x40 in the same way that the other platforms
-were changed.
-
-Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
----
- arch/arm/mach-at91/at91x40.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-at91/at91x40.c b/arch/arm/mach-at91/at91x40.c
-index 46090e6..efbb93f 100644
---- a/arch/arm/mach-at91/at91x40.c
-+++ b/arch/arm/mach-at91/at91x40.c
-@@ -88,6 +88,6 @@ void __init at91x40_init_interrupts(unsigned int priority[NR_AIC_IRQS])
- if (!priority)
- priority = at91x40_default_irq_priority;
-
-- at91_aic_init(priority);
-+ at91_aic_init(priority, at91_extern_irq);
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 998f85c1d457709bf7decfd45760879aa8e182df Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Wed, 24 Oct 2012 16:09:57 +0200
-Subject: ARM: at91: fix external interrupts in non-DT case
-
-commit 738a0fd752dc60e20beeda6f2f0f62e58dc0e344 upstream.
-
-Management of external interrupts has changed but the
-non-DT code has not integrated these changes.
-Add a mask to pass external irq specification from SoC
-specific code to the at91_aic_init() function.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Ludovic Desroches <ludovic.desroches@atmel.com>
-Cc: stable <stable@vger.kernel.org> [v3.6]
----
- arch/arm/mach-at91/generic.h | 3 ++-
- arch/arm/mach-at91/irq.c | 9 +++++++--
- arch/arm/mach-at91/setup.c | 2 +-
- 3 files changed, 10 insertions(+), 4 deletions(-)
-
-diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
-index f496506..b62f560e 100644
---- a/arch/arm/mach-at91/generic.h
-+++ b/arch/arm/mach-at91/generic.h
-@@ -26,7 +26,8 @@ extern void __init at91_dt_initialize(void);
- extern void __init at91_init_irq_default(void);
- extern void __init at91_init_interrupts(unsigned int priority[]);
- extern void __init at91x40_init_interrupts(unsigned int priority[]);
--extern void __init at91_aic_init(unsigned int priority[]);
-+extern void __init at91_aic_init(unsigned int priority[],
-+ unsigned int ext_irq_mask);
- extern int __init at91_aic_of_init(struct device_node *node,
- struct device_node *parent);
- extern int __init at91_aic5_of_init(struct device_node *node,
-diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
-index 1e02c0e..febc2ee 100644
---- a/arch/arm/mach-at91/irq.c
-+++ b/arch/arm/mach-at91/irq.c
-@@ -502,14 +502,19 @@ int __init at91_aic5_of_init(struct device_node *node,
- /*
- * Initialize the AIC interrupt controller.
- */
--void __init at91_aic_init(unsigned int *priority)
-+void __init at91_aic_init(unsigned int *priority, unsigned int ext_irq_mask)
- {
- unsigned int i;
- int irq_base;
-
-- if (at91_aic_pm_init())
-+ at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs)
-+ * sizeof(*at91_extern_irq), GFP_KERNEL);
-+
-+ if (at91_aic_pm_init() || at91_extern_irq == NULL)
- panic("Unable to allocate bit maps\n");
-
-+ *at91_extern_irq = ext_irq_mask;
-+
- at91_aic_base = ioremap(AT91_AIC, 512);
- if (!at91_aic_base)
- panic("Unable to ioremap AIC registers\n");
-diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
-index a37bebc..7cf3fef 100644
---- a/arch/arm/mach-at91/setup.c
-+++ b/arch/arm/mach-at91/setup.c
-@@ -48,7 +48,7 @@ void __init at91_init_irq_default(void)
- void __init at91_init_interrupts(unsigned int *priority)
- {
- /* Initialize the AIC interrupt controller */
-- at91_aic_init(priority);
-+ at91_aic_init(priority, at91_extern_irq);
-
- /* Enable GPIO interrupts */
- at91_gpio_irq_setup();
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 71baa91ada877611e15e180b123a33e1cf92caed Mon Sep 17 00:00:00 2001
-From: Bo Shen <voice.shen@atmel.com>
-Date: Mon, 15 Oct 2012 17:30:28 +0800
-Subject: ARM: at91/i2c: change id to let i2c-at91 work
-
-commit 302090a66b85bb82023b07a715f9c9a347be2ac8 upstream.
-
-The i2c core driver will turn the platform device ID to busnum
-When using platfrom device ID as -1, it means dynamically assigned
-the busnum. When writing code, we need to make sure the busnum,
-and call i2c_register_board_info(int busnum, ...) to register device
-if using -1, we do not know the value of busnum
-
-In order to solve this issue, set the platform device ID as a fix number
-Here using 0 to match the busnum used in i2c_regsiter_board_info()
-
-Signed-off-by: Bo Shen <voice.shen@atmel.com>
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
-Acked-by: Ludovic Desroches <ludovic.desroches@atmel.com>
----
- arch/arm/mach-at91/at91rm9200.c | 2 +-
- arch/arm/mach-at91/at91rm9200_devices.c | 2 +-
- arch/arm/mach-at91/at91sam9260.c | 4 ++--
- arch/arm/mach-at91/at91sam9260_devices.c | 2 +-
- arch/arm/mach-at91/at91sam9261.c | 4 ++--
- arch/arm/mach-at91/at91sam9261_devices.c | 2 +-
- arch/arm/mach-at91/at91sam9263.c | 2 +-
- arch/arm/mach-at91/at91sam9263_devices.c | 2 +-
- arch/arm/mach-at91/at91sam9rl_devices.c | 2 +-
- 9 files changed, 11 insertions(+), 11 deletions(-)
-
-diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
-index a454734..a3e4710 100644
---- a/arch/arm/mach-at91/at91rm9200.c
-+++ b/arch/arm/mach-at91/at91rm9200.c
-@@ -187,7 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
-- CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200", &twi_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200.0", &twi_clk),
- /* fake hclk clock */
- CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
- CLKDEV_CON_ID("pioA", &pioA_clk),
-diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
-index 7cd8053..1e122bc 100644
---- a/arch/arm/mach-at91/at91rm9200_devices.c
-+++ b/arch/arm/mach-at91/at91rm9200_devices.c
-@@ -512,7 +512,7 @@ static struct resource twi_resources[] = {
-
- static struct platform_device at91rm9200_twi_device = {
- .name = "i2c-at91rm9200",
-- .id = -1,
-+ .id = 0,
- .resource = twi_resources,
- .num_resources = ARRAY_SIZE(twi_resources),
- };
-diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
-index 23a8cfb..50b27d0 100644
---- a/arch/arm/mach-at91/at91sam9260.c
-+++ b/arch/arm/mach-at91/at91sam9260.c
-@@ -203,8 +203,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
- CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
-- CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
-- CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20", &twi_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi_clk),
- /* more usart lookup table for DT entries */
- CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
- CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
-diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
-index b169d64..e2a3e14 100644
---- a/arch/arm/mach-at91/at91sam9260_devices.c
-+++ b/arch/arm/mach-at91/at91sam9260_devices.c
-@@ -418,7 +418,7 @@ static struct resource twi_resources[] = {
- };
-
- static struct platform_device at91sam9260_twi_device = {
-- .id = -1,
-+ .id = 0,
- .resource = twi_resources,
- .num_resources = ARRAY_SIZE(twi_resources),
- };
-diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
-index 93a24e9..4d262f3 100644
---- a/arch/arm/mach-at91/at91sam9261.c
-+++ b/arch/arm/mach-at91/at91sam9261.c
-@@ -178,8 +178,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
- CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
- CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
-- CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261", &twi_clk),
-- CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10", &twi_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261.0", &twi_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi_clk),
- CLKDEV_CON_ID("pioA", &pioA_clk),
- CLKDEV_CON_ID("pioB", &pioB_clk),
- CLKDEV_CON_ID("pioC", &pioC_clk),
-diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
-index ac212e9..cf444a6 100644
---- a/arch/arm/mach-at91/at91sam9261_devices.c
-+++ b/arch/arm/mach-at91/at91sam9261_devices.c
-@@ -319,7 +319,7 @@ static struct resource twi_resources[] = {
- };
-
- static struct platform_device at91sam9261_twi_device = {
-- .id = -1,
-+ .id = 0,
- .resource = twi_resources,
- .num_resources = ARRAY_SIZE(twi_resources),
- };
-diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
-index 7639f6b..ed390f6 100644
---- a/arch/arm/mach-at91/at91sam9263.c
-+++ b/arch/arm/mach-at91/at91sam9263.c
-@@ -193,7 +193,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
- CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
- CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
- CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
-- CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
-+ CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
- /* fake hclk clock */
- CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
- CLKDEV_CON_ID("pioA", &pioA_clk),
-diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
-index ac61544..095ecc9e 100644
---- a/arch/arm/mach-at91/at91sam9263_devices.c
-+++ b/arch/arm/mach-at91/at91sam9263_devices.c
-@@ -602,7 +602,7 @@ static struct resource twi_resources[] = {
-
- static struct platform_device at91sam9263_twi_device = {
- .name = "i2c-at91sam9260",
-- .id = -1,
-+ .id = 0,
- .resource = twi_resources,
- .num_resources = ARRAY_SIZE(twi_resources),
- };
-diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
-index a3e9b08..5374e24 100644
---- a/arch/arm/mach-at91/at91sam9rl_devices.c
-+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
-@@ -349,7 +349,7 @@ static struct resource twi_resources[] = {
-
- static struct platform_device at91sam9rl_twi_device = {
- .name = "i2c-at91sam9g20",
-- .id = -1,
-+ .id = 0,
- .resource = twi_resources,
- .num_resources = ARRAY_SIZE(twi_resources),
- };
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 067de7270b3433afc244ba4a607f3491f0d0fc5c Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Fri, 16 Nov 2012 16:47:44 +0100
-Subject: net/macb: align ring buffer function with mainline
-
-Available number of descriptors in ring buffer function by David Laight.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/net/ethernet/cadence/macb.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
-index e3168bf..1f7b3a3 100644
---- a/drivers/net/ethernet/cadence/macb.c
-+++ b/drivers/net/ethernet/cadence/macb.c
-@@ -31,12 +31,12 @@
- #include "macb.h"
-
- #define RX_BUFFER_SIZE 128
--#define RX_RING_SIZE 512
-+#define RX_RING_SIZE 512 /* must be power of 2 */
- #define RX_RING_BYTES (sizeof(struct macb_dma_desc) * RX_RING_SIZE)
- #define RX_BUFFERS_PER_PAGE (PAGE_SIZE / RX_BUFFER_SIZE)
- #define RX_RING_PAGES (RX_RING_SIZE / RX_BUFFERS_PER_PAGE)
-
--#define TX_RING_SIZE 128
-+#define TX_RING_SIZE 128 /* must be power of 2 */
- #define TX_RING_BYTES (sizeof(struct macb_dma_desc) * TX_RING_SIZE)
-
- /* minimum number of free TX descriptors before waking up TX process */
-@@ -63,7 +63,7 @@ static unsigned int macb_tx_ring_wrap(unsigned int index)
-
- static unsigned int macb_tx_ring_avail(struct macb *bp)
- {
-- return TX_RING_SIZE - (bp->tx_head - bp->tx_tail);
-+ return (bp->tx_tail - bp->tx_head) & (TX_RING_SIZE - 1);
- }
-
- static struct macb_dma_desc *macb_tx_desc(struct macb *bp, unsigned int index)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b89a2bd3ff16d088eca080c6ba298e097c786287 Mon Sep 17 00:00:00 2001
-From: Nicolas Ferre <nicolas.ferre@atmel.com>
-Date: Mon, 19 Nov 2012 16:05:28 +0100
-Subject: net/macb: move to circ_buf macros and fix initial condition
-
-Move to circular buffers management macro and correct an error
-with circular buffer initial condition.
-
-Without this patch, the macb_tx_ring_avail() function was
-not reporting the proper ring availability at startup:
-macb macb: eth0: BUG! Tx Ring full when queue awake!
-macb macb: eth0: tx_head = 0, tx_tail = 0
-And hanginig forever...
-
-I remove the macb_tx_ring_avail() function and use the
-proven macros from circ_buf.h. CIRC_CNT() is used in the
-"consumer" part of the driver: macb_tx_interrupt() to match
-advice from Documentation/circular-buffers.txt.
-
-Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
----
- drivers/net/ethernet/cadence/macb.c | 17 +++++++----------
- 1 file changed, 7 insertions(+), 10 deletions(-)
-
-diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
-index 1f7b3a3..9647d37 100644
---- a/drivers/net/ethernet/cadence/macb.c
-+++ b/drivers/net/ethernet/cadence/macb.c
-@@ -15,6 +15,7 @@
- #include <linux/moduleparam.h>
- #include <linux/kernel.h>
- #include <linux/types.h>
-+#include <linux/circ_buf.h>
- #include <linux/slab.h>
- #include <linux/init.h>
- #include <linux/interrupt.h>
-@@ -39,8 +40,8 @@
- #define TX_RING_SIZE 128 /* must be power of 2 */
- #define TX_RING_BYTES (sizeof(struct macb_dma_desc) * TX_RING_SIZE)
-
--/* minimum number of free TX descriptors before waking up TX process */
--#define MACB_TX_WAKEUP_THRESH (TX_RING_SIZE / 4)
-+/* level of occupied TX descriptors under which we wake up TX process */
-+#define MACB_TX_WAKEUP_THRESH (3 * TX_RING_SIZE / 4)
-
- #define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \
- | MACB_BIT(ISR_ROVR))
-@@ -61,11 +62,6 @@ static unsigned int macb_tx_ring_wrap(unsigned int index)
- return index & (TX_RING_SIZE - 1);
- }
-
--static unsigned int macb_tx_ring_avail(struct macb *bp)
--{
-- return (bp->tx_tail - bp->tx_head) & (TX_RING_SIZE - 1);
--}
--
- static struct macb_dma_desc *macb_tx_desc(struct macb *bp, unsigned int index)
- {
- return &bp->tx_ring[macb_tx_ring_wrap(index)];
-@@ -495,7 +491,8 @@ static void macb_tx_interrupt(struct macb *bp)
-
- bp->tx_tail = tail;
- if (netif_queue_stopped(bp->dev)
-- && macb_tx_ring_avail(bp) > MACB_TX_WAKEUP_THRESH)
-+ && CIRC_CNT(bp->tx_head, bp->tx_tail,
-+ TX_RING_SIZE) <= MACB_TX_WAKEUP_THRESH)
- netif_wake_queue(bp->dev);
- }
-
-@@ -808,7 +805,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
- spin_lock_irqsave(&bp->lock, flags);
-
- /* This is a hard error, log it. */
-- if (macb_tx_ring_avail(bp) < 1) {
-+ if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < 1) {
- netif_stop_queue(dev);
- spin_unlock_irqrestore(&bp->lock, flags);
- netdev_err(bp->dev, "BUG! Tx Ring full when queue awake!\n");
-@@ -845,7 +842,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
-
- macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
-
-- if (macb_tx_ring_avail(bp) < 1)
-+ if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < 1)
- netif_stop_queue(dev);
-
- spin_unlock_irqrestore(&bp->lock, flags);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:50:56 2012
-From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Date: Fri, 23 Nov 2012 17:15:14 +0530
-Subject: [PATCH v2 RESEND 14/15] AXFS: Add documentation
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
-Message-ID: <50AF61CA.4020603@ap.sony.com>
-
-
-From: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
-
-Documentation for AXFS.
-
-Signed-off-by: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
----
- Documentation/filesystems/axfs.txt | 333 +++++++++++++++++++++++++++++++++++++
- 1 file changed, 333 insertions(+)
- create mode 100644 Documentation/filesystems/axfs.txt
-
---- /dev/null
-+++ b/Documentation/filesystems/axfs.txt
-@@ -0,0 +1,333 @@
-+AXFS user manual
-+
-+
-+1. Overview
-+===========
-+
-+Advanced XIP File System (AXFS) is readonly file system for
-+Linux. AXFS supports compression of file and execution of XIP
-+(eXecute-In-Place).
-+
-+XIP can reduce system memory requirements. It doesn't load binary
-+text to RAM and executes text directly from memory where they are
-+stored. Devices such as NOR flash and memory which is directly
-+addressable can be used.
-+
-+Whether a file is XIP or compressed can be specified in 1 page (4KB)
-+units. By this, it is possible to make the image size smaller than a
-+file system which is specified in file unit such as cramfs-xip.
-+
-+To determine which page in a file is XIP or compressed, AXFS provides
-+profile utility.
-+
-+Refer to the following link for details of AXFS.
-+
-+ http://axfs.sourceforge.net/wordpress/
-+ or:
-+ http://elinux.org/AXFS
-+
-+
-+2. AXFS specification overview
-+==============================
-+
-+ Item | cramfs-xip | AXFS
-+-----------+------------------------+----------------+----------------
-+ | Compression of data | Y | Y
-+ +------------------------+----------------+----------------
-+ |Compression of metadata | N | N
-+Compression+------------------------+----------------+----------------
-+related + Fragment processing | N | Y
-+ +------------------------+----------------+----------------
-+ |Change of compression | N | Y
-+ | algorithm| |
-+-----------+------------------------+----------------+----------------
-+ |Restoration of mode | Y | Y
-+ +------------------------+----------------+----------------
-+ |Restoration of uid ,gid | N | Y
-+ +------------------------+----------------+----------------
-+File |Restoration of file | N | N
-+related | modify date & time| |
-+ +------------------------+----------------+----------------
-+ |Max Length of file name | 252 characters | 255 characters
-+ +------------------------+----------------+----------------
-+ |The maximum size of file| Less than 16MB | Less than 2GB *1
-+ +------------------------+----------------+----------------
-+ |The maximum size | 256MB | Less than 2GB *1
-+ | of file system| |
-+-----------+------------------------+----------------+----------------
-+ |XIP Unit | File | Page, file
-+ +------------------------+----------------+----------------
-+XIP related|Binary XIP | Y | Y
-+ +------------------------+----------------+----------------
-+ |Shared Library XIP | Y | Y
-+ +------------------------+----------------+----------------
-+ |XIP profile | N | Y
-+-----------+------------------------+----------------+----------------
-+ |Supporting byte order | N | Y *2
-+Others +------------------------+----------------+----------------
-+ |Writable | N | N
-+-----------+------------------------+----------------+----------------
-+
-+ *1. It is not confirmed on the actual device
-+ *2. It is confirmed on source code but not tested on the actual device.
-+
-+
-+3. AXFS configuration of kernel
-+===============================
-+
-+Set it from make menuconfig of kernel as follows in order to use AXFS.
-+
-+ File systems --->
-+ Miscellaneous filesystems --->
-+ <*> Advanced XIP File System (AXFS) support (EXPERIMENTAL)
-+ [*] Profiling extensions for AXFS (EXPERIMENTAL)
-+ [ ] First Mount AXFS as Rootfs
-+ [ ] AXFS debugging support
-+
-+Enabling "Profiling extensions for AXFS" makes profile function of
-+AXFS valid. A CSV file which specifies which file and which page of
-+this file to be XIP can be created based on the profile information
-+which can be acquired by this configuration.
-+
-+In case of making AXFS image as rootfs, kernel mounts AXFS image prior
-+to NFS when booting if "First Mount AXFS as Rootfs" is set.
-+
-+
-+4. Using AXFS
-+=============
-+
-+There are 2 tools for AXFS. They are mkfs.axfs and axfs_csv2xml.rb.
-+mkfs.axfs is a tool to create AXFS image. axfs_csv2xml.rb is a tool to
-+convert profile data of AXFS to XML format file which can be read by
-+mkfs.axfs. mkfs.axfs reads the specified XML file and set the pages to
-+be XIP. The mkfs.axfs tool can also read the csv file format and set
-+the pages to be XIP.
-+
-+4.1. Creating AXFS image
-+------------------------
-+
-+AXFS image can be created by mkfs.axfs tool. Usage of mkfs.axfs is as
-+follows :
-+
-+ mkfs.axfs [-h] [-i infile] dirname outfile
-+
-+ -h : Output of help
-+ -i infile: Specifies XML/CSV file of XIP information
-+
-+4.2. AXFS image
-+---------------
-+
-+For example:
-+
-+ $ mkfs.axfs -i axfs-xip-profile.csv axfs-root-dir axfs-rootfs.image
-+
-+If it is successful, the following message will be outputted :
-+
-+ ......
-+ number of files: 501
-+ number of 4KB nodes: 2910
-+ number of 4KB xip nodes: 235 <-
-+ number of xip files: 9 <-
-+ ......
-+ Total image size: 8363941
-+
-+The above arrow parts are XIP information. In this case there are 9
-+XIP files and the number of pages inside these XIP files are 235.
-+
-+4.3. Mounting and unmounting AXFS image
-+---------------------------------------
-+
-+4.3.1. Mounting method
-+----------------------
-+
-+The examples for mounting AXFS image are given below.
-+
-+4.3.1.1. AXFS mount on an embedded board: KZM-ARM11
-+---------------------------------------------------
-+
-+The following example is to write AXFS image to NOR flash of KZM-ARM11
-+target and then mount it.
-+
-+In this example, the AXFS image will be written to "root" partition of
-+NOR flash. From the following output of the kernel booting message,
-+
-+ physmap platform flash device: 04000000 at a0000000
-+ ...
-+ 5 RedBoot partitions found on MTD device physmap-flash.0
-+ Creating 5 MTD partitions on "physmap-flash.0":
-+ 0x00000000-0x00060000 : "RedBoot"
-+ 0x00080000-0x00280000 : "zImage"
-+ 0x00400000-0x01400000 : "root" <- /dev/mtd2
-+ 0x01400000-0x01600000 : "kernel"
-+ 0x03fe0000-0x03fff000 : "FIS directory"
-+
-+It is clear that the "root" partition size is 16MB and its physical
-+address is between
-+ 0xa0400000-0xa1400000.
-+
-+AXFS image is assumed to be stored in /tmp/axfs.image.
-+
-+Flashcp is used in target.
-+
-+ $ flashcp -v /tmp/axfs.image /dev/mtd2
-+ $ mount -t axfs -o physaddr=0xA0400000 none /mnt
-+
-+AXFS image can be unmounted by the following command :
-+
-+ $ umount /mnt
-+
-+4.3.1.2. AXFS mount on an embedded board : KZM-A9
-+-------------------------------------------------
-+
-+The following example is to write AXFS image to RAM of KZM-A9
-+and then mount it.
-+
-+From the following output of iomem that is read from proc entry
-+
-+ physmap platform RAM device: 0x50000000 to 0x5effffff
-+
-+ $ cat /proc/iomem
-+ 20000000-2000ffff : smsc911x.0
-+ 20000000-2000ffff : smsc911x
-+ 40000000-486fffff : System RAM
-+ 40020000-40375023 : Kernel text
-+ 4038e000-403f0ae3 : Kernel data
-+ 50000000-5effffff : System RAM <--Load to RAM start address + 256MB offset
-+ e1020000-e102002b : serial
-+ e1030000-e103002b : serial
-+ ...
-+
-+Boot the target with following boot parameter and load axfs.image to RAM
-+address 0x50000000.
-+
-+ console=ttyS1,115200n8 mem=240M rootfstype=axfs ip=on
-+
-+AXFS.image is assumed to stored in /tmp/axfs.image
-+
-+tools/axfs/bload.c is used to load axfs.image to System RAM address.
-+
-+ $ bload /tmp/axfs.image 0x50000000
-+ $ mount -t axfs -o physaddr=0x50000000 none /mnt/
-+
-+AXFS image can be unmounted by the following command
-+
-+ $ umount /mnt/
-+
-+4.3.2. In case of rootfs
-+------------------------
-+
-+The examples for mounting AXFS image as rootfs are given below.
-+
-+4.3.2.1. Mount AXFS as rootfs on KZM-ARM11
-+------------------------------------------
-+
-+The following is an example of specifying /dev/mtd2 which is
-+same as example in section 4.3.1.1 as rootfs in KZM-ARM11.
-+Set the booting parameter of kernel as follows.
-+
-+ "console=ttymxc0 mem=128M root=/dev/null rootflags=physaddr=0xa0400000
-+ rootfstype=axfs ip=on"
-+
-+If kernel option "First Mount AXFS as Rootfs" is set , kernel mounts
-+AXFS image prior to NFS.
-+
-+4.3.2.2. Mount AXFS as rootfs on KZM-A9
-+---------------------------------------
-+
-+Set the booting parameters of kernel as follows to mount axfs
-+as rootfs for KZM-A9 Board.
-+
-+ "console=ttyS1,115200n8 root=/dev/null rootflags=physaddr=0x50000000
-+ mem=240M rootfstype=axfs ip=on"
-+
-+kernel mounts AXFS prior to NFS on KZM-A9.
-+
-+4.4. XIP of AXFS
-+----------------
-+
-+4.4.1. XIP of AXFS
-+------------------
-+
-+XIP image can be created by specifying CSV file which contains the XIP
-+information by "-i infile" option when creating AXFS image by
-+mkfs.axfs tool.
-+
-+CSV file contains the following XIP information: file name to be XIP,
-+size in page(4KB) unit and offset(page alignment) to be XIP in the
-+file.
-+
-+In case of specifying the file size which is aligned by 4KB to size,
-+the whole file becomes XIP.
-+
-+Whether to make the file in AXFS image compressed or XIP can be
-+decided by profiling utility of AXFS.
-+
-+4.5. Profile utility of AXFS
-+----------------------------
-+
-+Profile utility can be used if kernel option "Profiling extensions for
-+AXFS" is set.
-+
-+With this option set, when AXFS image is mounted, /proc/ interface for
-+profile will be created for each mounted image under /proc/axfs/.
-+(e.g.: /proc/axfs/volume0)
-+
-+When Non-XIP program or library in AXFS image is executed, the
-+information of executable pages which are paged in and out of RAM are
-+recorded to profile.
-+
-+4.5.1. Acquiring profile data
-+-----------------------------
-+
-+Data of this profile can be obtained by the following command.
-+
-+ $ cat /proc/axfs/volume0 > /tmp/axfs-xip.profile
-+
-+4.5.2. Converting profile data
-+------------------------------
-+
-+Profile data of AXFS in CSV file format can be used by mkfs.axfs tool.
-+
-+
-+5. Known problems
-+=================
-+
-+ - 32 bit device file is not supported
-+
-+ A part of file system from Linux 2.6 supports 32 bit device file.
-+ By using this, the value more than 255 can be set for major number
-+ and minor number of device file.
-+
-+ AXFS supports only 16 bit device file.
-+
-+ - Sequence of mounting and unmounting several AXFS images
-+
-+ When AXFS profile option is set and several AXFS images are
-+ mounted, error message will be outputted and profile of
-+ /proc/axfs/ will not be deleted correctly unless unmounting is
-+ done in the opposite sequence to the one of mounting.
-+
-+ e.g.:
-+ When the following operation is done,
-+
-+ mount image 1 -> mount image 2 -> umount image 1 -> umount image 2
-+
-+ the following error message is outputted.
-+
-+ "axfs: Error removing proc file private data was NULL."
-+
-+ In this case, operate in the following sequence.
-+
-+ mount image 1 -> mount image 2 -> umount image 2 -> umount image 1
-+
-+
-+6. Hints on using AXFS
-+======================
-+
-+ - When using sytem RAM instead of NOR flash for loading and mounting
-+ AXFS image, it should be made sure that the location where AXFS image
-+ is being loaded is not used by any other component in the system.
-+ For e.g. Just after the regular system RAM ('System RAM' from /proc/iomem)
-+ there may be a memory which is reserved/isolated by dirvers using
-+ memblock_remove().
-+
+++ /dev/null
-From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:32:57 2012
-From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Date: Fri, 23 Nov 2012 16:57:13 +0530
-Subject: [PATCH v2 RESEND 02/15] AXFS: axfs.h
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
-Message-ID: <50AF5D91.3080207@ap.sony.com>
-
-
-From: Jared Hulbert <jaredeh@gmail.com>
-
-The AXFS header.
-
-Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
-Signed-off-by: Thomas Rony Jose <thomas.jose@ap.sony.com>
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
----
- fs/axfs/axfs.h | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 96 insertions(+)
- create mode 100644 fs/axfs/axfs.h
-
---- /dev/null
-+++ b/fs/axfs/axfs.h
-@@ -0,0 +1,96 @@
-+/*
-+ * Advanced XIP File System for Linux - AXFS
-+ * Readonly, compressed, and XIP filesystem for Linux systems big and small
-+ *
-+ * Copyright(c) 2008 Numonyx
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * Authors:
-+ * Eric Anderson
-+ * Jared Hulbert <jaredeh@gmail.com>
-+ * Sujaya Srinivasan
-+ * Justin Treon
-+ *
-+ * Project url: http://axfs.sourceforge.net
-+ */
-+
-+#ifndef AXFS_H
-+#define AXFS_H
-+
-+#include <linux/axfs_fs.h>
-+#include <linux/axfs_fs_sb.h>
-+
-+#include <linux/pagemap.h>
-+#include <linux/fs.h>
-+#include <linux/mount.h>
-+
-+/* axfs_inode.c */
-+struct inode *axfs_create_vfs_inode(struct super_block *, int);
-+u64 axfs_get_mode(struct axfs_super *sbi, u64 index);
-+u64 axfs_get_uid(struct axfs_super *sbi, u64 index);
-+u64 axfs_get_gid(struct axfs_super *sbi, u64 index);
-+u64 axfs_get_inode_name_offset(struct axfs_super *sbi, u64 index);
-+u64 axfs_get_inode_num_entries(struct axfs_super *sbi, u64 index);
-+u64 axfs_get_inode_mode_index(struct axfs_super *sbi, u64 index);
-+u64 axfs_get_inode_array_index(struct axfs_super *sbi, u64 index);
-+char *axfs_get_inode_name(struct axfs_super *sbi, u64 index);
-+
-+/* axfs_super.c */
-+u64 axfs_get_io_dev_size(struct super_block *sb);
-+int axfs_fill_super(struct super_block *sb, void *data, int silent);
-+
-+struct dentry *axfs_get_sb(struct file_system_type *,
-+ int, const char *, void *);
-+int axfs_physaddr_is_valid(struct axfs_super *sbi);
-+int axfs_virtaddr_is_valid(struct axfs_super *sbi);
-+int axfs_is_iomem(struct axfs_super *sbi);
-+int axfs_is_pointed(struct axfs_super *sbi);
-+int axfs_can_xip(struct axfs_super *sbi);
-+int axfs_is_physmem(struct axfs_super *sbi);
-+int axfs_nodev(struct super_block *sb);
-+u64 axfs_fsoffset_to_devoffset(struct axfs_super *sbi, u64 fsoffset);
-+extern void kfree(const void *objp);
-+
-+/* axfs_profiling.c */
-+void axfs_profiling_add(struct axfs_super *, unsigned long, unsigned int);
-+int axfs_init_profiling(struct axfs_super *);
-+int axfs_shutdown_profiling(struct axfs_super *);
-+
-+/* axfs_mtd.c */
-+int axfs_copy_mtd(struct super_block *, void *, u64, u64);
-+struct dentry *axfs_get_sb_mtd(struct file_system_type *, int ,
-+ const char *, struct axfs_super *);
-+
-+void axfs_kill_mtd_super(struct super_block *);
-+int axfs_is_dev_mtd(char *, int *);
-+int axfs_verify_mtd_sizes(struct super_block *sb, int *err);
-+int axfs_map_mtd(struct super_block *);
-+void axfs_unmap_mtd(struct super_block *);
-+struct mtd_info *axfs_mtd(struct super_block *sb);
-+struct mtd_info *axfs_mtd0(struct super_block *sb);
-+struct mtd_info *axfs_mtd1(struct super_block *sb);
-+int axfs_has_mtd(struct super_block *sb);
-+
-+/* axfs_bdev.c */
-+void axfs_copy_block(struct super_block *, void *, u64, u64);
-+struct dentry *axfs_get_sb_bdev(struct file_system_type *, int,
-+ const char *, struct axfs_super *);
-+void axfs_kill_block_super(struct super_block *);
-+int axfs_is_dev_bdev(char *);
-+int axfs_verify_bdev_sizes(struct super_block *sb, int *err);
-+struct block_device *axfs_bdev(struct super_block *sb);
-+int axfs_has_bdev(struct super_block *sb);
-+
-+/* axfs_uml.c */
-+int axfs_get_uml_address(char *, unsigned long *, unsigned long *);
-+
-+#ifndef NO_PHYSMEM
-+/* axfs_physmem.c */
-+void axfs_map_physmem(struct axfs_super *, unsigned long);
-+void axfs_unmap_physmem(struct super_block *);
-+#endif
-+
-+#endif
+++ /dev/null
-From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:49:36 2012
-From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Date: Fri, 23 Nov 2012 17:13:54 +0530
-Subject: [PATCH v2 RESEND 12/15] AXFS: axfs_bdev.c
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
-Message-ID: <50AF617A.9000300@ap.sony.com>
-
-
-From: Jared Hulbert <jaredeh@gmail.com>
-
-Allows axfs to use block devices or has dummy functions if block
-device support is compiled out of the kernel.
-
-Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
-Signed-off-by: Thomas Rony Jose <thomas.jose@ap.sony.com>
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
----
- fs/axfs/axfs_bdev.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 170 insertions(+)
- create mode 100644 fs/axfs/axfs_bdev.c
-
---- /dev/null
-+++ b/fs/axfs/axfs_bdev.c
-@@ -0,0 +1,170 @@
-+/*
-+ * Advanced XIP File System for Linux - AXFS
-+ * Readonly, compressed, and XIP filesystem for Linux systems big and small
-+ *
-+ * Copyright(c) 2008 Numonyx
-+ * Copyright 2011 Sony Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * Authors:
-+ * Jared Hulbert <jaredeh@gmail.com>
-+ *
-+ * Project url: http://axfs.sourceforge.net
-+ *
-+ * axfs_bdev.c -
-+ * Allows axfs to use block devices or has dummy functions if block
-+ * device support is compiled out of the kernel.
-+ *
-+ */
-+#include "axfs.h"
-+
-+#include <linux/mount.h>
-+#ifdef CONFIG_BLOCK
-+#include <linux/buffer_head.h>
-+#include <linux/namei.h>
-+
-+struct block_device *axfs_bdev(struct super_block *sb)
-+{
-+ return sb->s_bdev;
-+}
-+
-+int axfs_has_bdev(struct super_block *sb)
-+{
-+ if (axfs_bdev(sb) == NULL)
-+ return false;
-+
-+ return true;
-+}
-+
-+struct dentry *axfs_get_sb_bdev(struct file_system_type *fs_type, int flags,
-+ const char *dev_name, struct axfs_super *sbi)
-+{
-+ return mount_bdev(fs_type, flags, dev_name, sbi, axfs_fill_super);
-+}
-+
-+void axfs_kill_block_super(struct super_block *sb)
-+{
-+ kill_block_super(sb);
-+}
-+
-+void axfs_copy_block(struct super_block *sb, void *dst_addr, u64 fsoffset,
-+ u64 len)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ u64 boffset = axfs_fsoffset_to_devoffset(sbi, fsoffset);
-+ u64 blksize = sb->s_blocksize;
-+ unsigned long dst;
-+ unsigned long src;
-+ sector_t block;
-+ size_t bytes;
-+ struct buffer_head *bh;
-+ u64 copied = 0;
-+
-+ if (len == 0)
-+ return;
-+
-+ while (copied < len) {
-+ /* Explicit casting for ARM linker errors. */
-+ block = (sector_t) boffset + (sector_t) copied;
-+ block = div64_u64(block, (sector_t) blksize);
-+ bh = sb_bread(sb, block);
-+ src = (unsigned long)bh->b_data;
-+ dst = (unsigned long)dst_addr;
-+ if (copied == 0) {
-+ /* Explicit casting for ARM linker errors. */
-+ bytes = (size_t) blksize;
-+ bytes -= (size_t) boffset % (size_t) blksize;
-+ if (bytes > len)
-+ bytes = len;
-+ /* Explicit casting for ARM linker errors. */
-+ src += (unsigned long)boffset % (unsigned long)blksize;
-+ } else {
-+ dst += copied;
-+ if ((len - copied) < blksize)
-+ bytes = len - copied;
-+ else
-+ bytes = blksize;
-+ }
-+ memcpy((void *)dst, (void *)src, bytes);
-+ copied += bytes;
-+ brelse(bh);
-+ }
-+}
-+
-+int axfs_is_dev_bdev(char *path)
-+{
-+ struct nameidata nd;
-+ int ret = false;
-+
-+ if (!path)
-+ return false;
-+ nd.flags |= LOOKUP_FOLLOW;
-+ if (kern_path_parent(path, &nd))
-+ return false;
-+
-+ if (S_ISBLK(nd.path.dentry->d_inode->i_mode))
-+ ret = true;
-+
-+ path_put(&nd.path);
-+ return ret;
-+}
-+
-+int axfs_verify_bdev_sizes(struct super_block *sb, int *err)
-+{
-+ u64 io_dev_size;
-+ loff_t bdev_size;
-+
-+ *err = 0;
-+
-+ if (!axfs_has_bdev(sb))
-+ return false;
-+
-+ io_dev_size = axfs_get_io_dev_size(sb);
-+
-+ if (!io_dev_size)
-+ return false;
-+
-+ bdev_size = i_size_read(axfs_bdev(sb)->bd_inode);
-+ if (io_dev_size <= bdev_size)
-+ return true;
-+
-+ printk(KERN_ERR "axfs: image (%lluB) doesn't fit in blkdev(%lluB)\n",
-+ io_dev_size, bdev_size);
-+ *err = -EIO;
-+ return true;
-+}
-+
-+#else
-+
-+int axfs_get_sb_bdev(struct file_system_type *fs_type, int flags,
-+ const char *dev_name, struct axfs_super *sbi,
-+ struct vfsmount *mnt, int *err)
-+{
-+ return false;
-+}
-+
-+void axfs_kill_block_super(struct super_block *sb)
-+{
-+}
-+
-+int axfs_copy_block(struct super_block *sb, void *dst_addr, u64 fsoffset,
-+ u64 len)
-+{
-+ return -EINVAL;
-+}
-+
-+int axfs_is_dev_bdev(char *path)
-+{
-+ return false;
-+}
-+
-+int axfs_verify_bdev_sizes(struct super_block *sb, int *err)
-+{
-+ *err = 0;
-+ return true;
-+}
-+
-+#endif /* CONFIG_BLOCK */
+++ /dev/null
-From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:34:37 2012
-From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Date: Fri, 23 Nov 2012 16:58:55 +0530
-Subject: [PATCH v2 RESEND 03/15] AXFS: axfs_fs.h
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
-Message-ID: <50AF5DF7.1040709@ap.sony.com>
-
-
-From: Jared Hulbert <jaredeh@gmail.com>
-
-The AXFS on media superblock declaration.
-
-Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
----
- include/linux/axfs_fs.h | 124 ++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 124 insertions(+)
- create mode 100644 include/linux/axfs_fs.h
-
---- /dev/null
-+++ b/include/linux/axfs_fs.h
-@@ -0,0 +1,124 @@
-+/*
-+ * Advanced XIP File System for Linux - AXFS
-+ * Readonly, compressed, and XIP filesystem for Linux systems big and small
-+ *
-+ * Copyright(c) 2008 Numonyx
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * Authors:
-+ * Eric Anderson
-+ * Jared Hulbert <jaredeh@gmail.com>
-+ * Sujaya Srinivasan
-+ * Justin Treon
-+ *
-+ * Project url: http://axfs.sourceforge.net
-+ */
-+
-+#ifndef AXFS_FS_H
-+#define AXFS_FS_H
-+
-+#include <linux/axfs_fs_sb.h>
-+
-+#ifdef __KERNEL__
-+#include <linux/rwsem.h>
-+#endif
-+#include <linux/errno.h>
-+#include <linux/time.h>
-+
-+#include <linux/pagemap.h>
-+#include <linux/fs.h>
-+#include <linux/mount.h>
-+
-+#define AXFS_MAGIC 0x48A0E4CD /* some random number */
-+#define AXFS_SIGNATURE "Advanced XIP FS"
-+#define AXFS_MAXPATHLEN 255
-+
-+
-+/* Uncompression interfaces to the underlying zlib */
-+int axfs_uncompress_block(void *, int, void *, int);
-+int axfs_uncompress_init(void);
-+int axfs_uncompress_exit(void);
-+
-+struct axfs_profiling_data {
-+ u64 inode_number;
-+ unsigned long count;
-+};
-+
-+enum axfs_node_types {
-+ XIP = 0,
-+ Compressed,
-+ Byte_Aligned,
-+};
-+
-+enum axfs_compression_types {
-+ ZLIB = 0
-+};
-+
-+/* on media struct describing a data region */
-+struct axfs_region_desc_onmedia {
-+ u64 fsoffset;
-+ u64 size;
-+ u64 compressed_size;
-+ u64 max_index;
-+ u8 table_byte_depth;
-+ u8 incore;
-+};
-+
-+/* on media format for the super block */
-+struct axfs_super_onmedia {
-+ __be32 magic; /* 0x48A0E4CD - random number */
-+ u8 signature[16]; /* "Advanced XIP FS" */
-+ u8 digest[40]; /* sha1 digest for checking data integrity */
-+ __be32 cblock_size; /* maximum size of the block being compressed */
-+ __be64 files; /* number of inodes/files in fs */
-+ __be64 size; /* total image size */
-+ __be64 blocks; /* number of nodes in fs */
-+ __be64 mmap_size; /* size of the memory mapped part of image */
-+ __be64 strings; /* offset to strings region descriptor */
-+ __be64 xip; /* offset to xip region descriptor */
-+ __be64 byte_aligned; /* offset to the byte aligned region desc */
-+ __be64 compressed; /* offset to the compressed region desc */
-+ __be64 node_type; /* offset to node type region desc */
-+ __be64 node_index; /* offset to node index region desc */
-+ __be64 cnode_offset; /* offset to cnode offset region desc */
-+ __be64 cnode_index; /* offset to cnode index region desc */
-+ __be64 banode_offset; /* offset to banode offset region desc */
-+ __be64 cblock_offset; /* offset to cblock offset region desc */
-+ __be64 inode_file_size; /* offset to inode file size desc */
-+ __be64 inode_name_offset;/* offset to inode num_entries region desc */
-+ __be64 inode_num_entries;/* offset to inode num_entries region desc */
-+ __be64 inode_mode_index;/* offset to inode mode index region desc */
-+ __be64 inode_array_index;/* offset to inode node index region desc */
-+ __be64 modes; /* offset to mode mode region desc */
-+ __be64 uids; /* offset to mode uid index region desc */
-+ __be64 gids; /* offset to mode gid index region desc */
-+ u8 version_major;
-+ u8 version_minor;
-+ u8 version_sub;
-+ u8 compression_type; /* Identifies type of compression used on FS */
-+ __be64 timestamp; /* UNIX time_t of filesystem build time */
-+ u8 page_shift;
-+};
-+
-+#define AXFS_SB(sb) ((struct axfs_super *)((sb)->s_fs_info))
-+
-+static inline u64 axfs_bytetable_stitch(u8 depth, u8 *table, u64 index)
-+{
-+ u64 i;
-+ u64 output = 0;
-+ u64 byte = 0;
-+ u64 j;
-+ u64 bits;
-+
-+ for (i = 0; i < depth; i++) {
-+ j = index * depth + i;
-+ bits = 8 * (depth - i - 1);
-+ byte = table[j];
-+ output += byte << bits;
-+ }
-+ return output;
-+}
-+#endif
+++ /dev/null
-From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:37:53 2012
-From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Date: Fri, 23 Nov 2012 17:02:11 +0530
-Subject: [PATCH v2 RESEND 04/15] AXFS: axfs_fs_sb.h
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
-Message-ID: <50AF5EBB.7080202@ap.sony.com>
-
-
-From: Jared Hulbert <jaredeh@gmail.com>
-
-The AXFS superblock declaration.
-
-Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
----
- include/linux/axfs_fs_sb.h | 87 +++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 87 insertions(+)
- create mode 100644 include/linux/axfs_fs_sb.h
-
---- /dev/null
-+++ b/include/linux/axfs_fs_sb.h
-@@ -0,0 +1,87 @@
-+/*
-+ * Advanced XIP File System for Linux - AXFS
-+ * Readonly, compressed, and XIP filesystem for Linux systems big and small
-+ *
-+ * Copyright(c) 2008 Numonyx
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * Authors:
-+ * Eric Anderson
-+ * Jared Hulbert <jaredeh@gmail.com>
-+ * Sujaya Srinivasan
-+ * Justin Treon
-+ *
-+ * Project url: http://axfs.sourceforge.net
-+ */
-+
-+#ifndef AXFS_FS_SB_H
-+#define AXFS_FS_SB_H
-+
-+#ifdef __KERNEL__
-+#include <linux/rwsem.h>
-+#endif
-+#include <linux/errno.h>
-+#include <linux/time.h>
-+
-+/* in memory region descriptor */
-+struct axfs_region_desc {
-+ u64 fsoffset;
-+ u64 size;
-+ u64 compressed_size;
-+ u64 max_index;
-+ void *virt_addr;
-+ u8 table_byte_depth;
-+ u8 incore;
-+};
-+
-+/* axfs super-block data in memory */
-+struct axfs_super {
-+ u32 magic;
-+ u8 version_major;
-+ u8 version_minor;
-+ u8 version_sub;
-+ u8 padding;
-+ u64 files;
-+ u64 size;
-+ u64 blocks;
-+ u64 mmap_size;
-+ struct axfs_region_desc strings;
-+ struct axfs_region_desc xip;
-+ struct axfs_region_desc compressed;
-+ struct axfs_region_desc byte_aligned;
-+ struct axfs_region_desc node_type;
-+ struct axfs_region_desc node_index;
-+ struct axfs_region_desc cnode_offset;
-+ struct axfs_region_desc cnode_index;
-+ struct axfs_region_desc banode_offset;
-+ struct axfs_region_desc cblock_offset;
-+ struct axfs_region_desc inode_file_size;
-+ struct axfs_region_desc inode_name_offset;
-+ struct axfs_region_desc inode_num_entries;
-+ struct axfs_region_desc inode_mode_index;
-+ struct axfs_region_desc inode_array_index;
-+ struct axfs_region_desc modes;
-+ struct axfs_region_desc uids;
-+ struct axfs_region_desc gids;
-+ unsigned long phys_start_addr;
-+ unsigned long virt_start_addr;
-+ char *second_dev;
-+ unsigned long iomem_size;
-+ void *mtd0; /* primary device */
-+ void *mtd1; /* secondary device */
-+ u32 cblock_size;
-+ u64 current_cnode_index;
-+ void *cblock_buffer[2];
-+ struct rw_semaphore lock;
-+ struct axfs_profiling_data *profile_data_ptr;
-+ u8 profiling_on; /* Determines if profiling is on or off */
-+ u8 mtd_pointed;
-+ u8 compression_type;
-+ struct timespec timestamp;
-+ u8 page_shift;
-+};
-+
-+#endif
+++ /dev/null
-From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:39:18 2012
-From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Date: Fri, 23 Nov 2012 17:03:35 +0530
-Subject: [PATCH v2 RESEND 05/15] AXFS: axfs_inode.c
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
-Message-ID: <50AF5F0F.8010403@ap.sony.com>
-
-
-From: Jared Hulbert <jaredeh@gmail.com>
-
-Contains the most of the filesystem logic with the major exception
-of the mounting infrastructure.
-
-Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
----
- fs/axfs/axfs_inode.c | 636 +++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 636 insertions(+)
- create mode 100644 fs/axfs/axfs_inode.c
-
---- /dev/null
-+++ b/fs/axfs/axfs_inode.c
-@@ -0,0 +1,636 @@
-+/*
-+ * Advanced XIP File System for Linux - AXFS
-+ * Readonly, compressed, and XIP filesystem for Linux systems big and small
-+ *
-+ * Copyright(c) 2008 Numonyx
-+ * Copyright 2009, 2011 Sony Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * Authors:
-+ * Eric Anderson
-+ * Jared Hulbert <jaredeh@gmail.com>
-+ * Sujaya Srinivasan
-+ * Justin Treon
-+ *
-+ * Project url: http://axfs.sourceforge.net
-+ *
-+ * Borrowed heavily from fs/cramfs/inode.c by Linus Torvalds
-+ *
-+ * axfs_inode.c -
-+ * Contains the most of the filesystem logic with the major exception of the
-+ * mounting infrastructure.
-+ *
-+ */
-+#include "axfs.h"
-+
-+
-+static const struct file_operations axfs_directory_operations;
-+static const struct file_operations axfs_fops;
-+static const struct address_space_operations axfs_aops;
-+static struct inode_operations axfs_dir_inode_operations;
-+static struct vm_operations_struct axfs_vm_ops;
-+
-+static inline u64 axfs_get_node_type(struct axfs_super *sbi, u64 index)
-+{
-+ u64 depth = sbi->node_type.table_byte_depth;
-+ u8 *vaddr = (u8 *) sbi->node_type.virt_addr;
-+
-+ return axfs_bytetable_stitch(depth, vaddr, index);
-+}
-+
-+static inline u64 axfs_get_node_index(struct axfs_super *sbi, u64 index)
-+{
-+ u64 depth = sbi->node_index.table_byte_depth;
-+ u8 *vaddr = (u8 *) sbi->node_index.virt_addr;
-+
-+ return axfs_bytetable_stitch(depth, vaddr, index);
-+}
-+
-+static inline u64 axfs_is_node_xip(struct axfs_super *sbi, u64 index)
-+{
-+ if (axfs_get_node_type(sbi, index) == XIP)
-+ return true;
-+
-+ return false;
-+}
-+
-+static inline u64 axfs_get_cnode_index(struct axfs_super *sbi, u64 index)
-+{
-+ u64 depth = sbi->cnode_index.table_byte_depth;
-+ u8 *vaddr = (u8 *) sbi->cnode_index.virt_addr;
-+
-+ return axfs_bytetable_stitch(depth, vaddr, index);
-+}
-+
-+static inline u64 axfs_get_cnode_offset(struct axfs_super *sbi, u64 index)
-+{
-+ u64 depth = sbi->cnode_offset.table_byte_depth;
-+ u8 *vaddr = (u8 *) sbi->cnode_offset.virt_addr;
-+
-+ return axfs_bytetable_stitch(depth, vaddr, index);
-+}
-+
-+static inline u64 axfs_get_banode_offset(struct axfs_super *sbi, u64 index)
-+{
-+ u64 depth = sbi->banode_offset.table_byte_depth;
-+ u8 *vaddr = (u8 *) sbi->banode_offset.virt_addr;
-+
-+ return axfs_bytetable_stitch(depth, vaddr, index);
-+}
-+
-+static inline u64 axfs_get_cblock_offset(struct axfs_super *sbi, u64 index)
-+{
-+ u64 depth = sbi->cblock_offset.table_byte_depth;
-+ u8 *vaddr = (u8 *) sbi->cblock_offset.virt_addr;
-+
-+ return axfs_bytetable_stitch(depth, vaddr, index);
-+}
-+
-+static inline u64 axfs_get_inode_file_size(struct axfs_super *sbi, u64 index)
-+{
-+ u64 depth = sbi->inode_file_size.table_byte_depth;
-+ u8 *vaddr = (u8 *) sbi->inode_file_size.virt_addr;
-+
-+ return axfs_bytetable_stitch(depth, vaddr, index);
-+}
-+
-+u64 axfs_get_mode(struct axfs_super *sbi, u64 index)
-+{
-+ u64 mode = axfs_get_inode_mode_index(sbi, index);
-+ u64 depth = sbi->modes.table_byte_depth;
-+ u8 *vaddr = (u8 *) sbi->modes.virt_addr;
-+
-+ return axfs_bytetable_stitch(depth, vaddr, mode);
-+}
-+
-+u64 axfs_get_uid(struct axfs_super *sbi, u64 index)
-+{
-+ u64 mode = axfs_get_inode_mode_index(sbi, index);
-+ u64 depth = sbi->uids.table_byte_depth;
-+ u8 *vaddr = (u8 *) sbi->uids.virt_addr;
-+
-+ return axfs_bytetable_stitch(depth, vaddr, mode);
-+}
-+
-+u64 axfs_get_gid(struct axfs_super *sbi, u64 index)
-+{
-+ u64 mode = axfs_get_inode_mode_index(sbi, index);
-+ u64 depth = sbi->gids.table_byte_depth;
-+ u8 *vaddr = (u8 *) sbi->gids.virt_addr;
-+
-+ return axfs_bytetable_stitch(depth, vaddr, mode);
-+}
-+
-+u64 axfs_get_inode_name_offset(struct axfs_super *sbi, u64 index)
-+{
-+ u64 depth = sbi->inode_name_offset.table_byte_depth;
-+ u8 *vaddr = (u8 *) sbi->inode_name_offset.virt_addr;
-+
-+ return axfs_bytetable_stitch(depth, vaddr, index);
-+}
-+
-+u64 axfs_get_inode_num_entries(struct axfs_super *sbi, u64 index)
-+{
-+ u64 depth = sbi->inode_num_entries.table_byte_depth;
-+ u8 *vaddr = (u8 *) sbi->inode_num_entries.virt_addr;
-+
-+ return axfs_bytetable_stitch(depth, vaddr, index);
-+}
-+
-+u64 axfs_get_inode_mode_index(struct axfs_super *sbi, u64 index)
-+{
-+ u64 depth = sbi->inode_mode_index.table_byte_depth;
-+ u8 *vaddr = (u8 *) sbi->inode_mode_index.virt_addr;
-+
-+ return axfs_bytetable_stitch(depth, vaddr, index);
-+}
-+
-+u64 axfs_get_inode_array_index(struct axfs_super *sbi, u64 index)
-+{
-+ u64 depth = sbi->inode_array_index.table_byte_depth;
-+ u8 *vaddr = (u8 *) sbi->inode_array_index.virt_addr;
-+
-+ return axfs_bytetable_stitch(depth, vaddr, index);
-+}
-+
-+char *axfs_get_inode_name(struct axfs_super *sbi, u64 index)
-+{
-+ u64 ofs = axfs_get_inode_name_offset(sbi, index);
-+ u8 *virt = sbi->strings.virt_addr;
-+
-+ return (char *)(ofs + virt);
-+}
-+
-+static inline u64 axfs_get_xip_region_physaddr(struct axfs_super *sbi)
-+{
-+ return sbi->phys_start_addr + sbi->xip.fsoffset;
-+}
-+
-+static inline int axfs_region_is_vmalloc(struct axfs_super *sbi,
-+ struct axfs_region_desc *region)
-+{
-+ u64 va = (u32) region->virt_addr;
-+ u64 vo = (u64) region->fsoffset + (u64) sbi->virt_start_addr;
-+
-+ if (va == 0)
-+ return false;
-+
-+ if (vo != va)
-+ return true;
-+
-+ return false;
-+}
-+
-+static int axfs_copy_data(struct super_block *sb, void *dst,
-+ struct axfs_region_desc *region, u64 offset, u64 len)
-+{
-+ u64 mmapped = 0;
-+ u64 end = region->fsoffset + offset + len;
-+ u64 begin = region->fsoffset + offset;
-+ u64 left;
-+ void *addr;
-+ void *newdst;
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+
-+ if (len == 0)
-+ return 0;
-+
-+ if (axfs_region_is_vmalloc(sbi, region)) {
-+ mmapped = len;
-+ } else if (region->virt_addr) {
-+ if (sbi->mmap_size >= end)
-+ mmapped = len;
-+ else if (sbi->mmap_size > begin)
-+ mmapped = sbi->mmap_size - begin;
-+ }
-+
-+ if (mmapped) {
-+ addr = (void *)(region->virt_addr + offset);
-+ memcpy(dst, addr, mmapped);
-+ }
-+
-+ newdst = (void *)(dst + mmapped);
-+ left = len - mmapped;
-+
-+ if (left == 0)
-+ return len;
-+
-+ if (axfs_has_bdev(sb))
-+ axfs_copy_block(sb, newdst, begin + mmapped, left);
-+ else if (axfs_has_mtd(sb))
-+ return axfs_copy_mtd(sb, newdst, begin + mmapped, left);
-+
-+ return 0;
-+}
-+
-+static int axfs_iget5_test(struct inode *inode, void *opaque)
-+{
-+ u64 *inode_number = (u64 *) opaque;
-+
-+ if (inode->i_sb == NULL) {
-+ printk(KERN_ERR "axfs_iget5_test:"
-+ " the super block is set to null\n");
-+ }
-+ if (inode->i_ino == *inode_number)
-+ return 1; /* matches */
-+ else
-+ return 0; /* does not match */
-+}
-+
-+static int axfs_iget5_set(struct inode *inode, void *opaque)
-+{
-+ u64 *inode_number = (u64 *) opaque;
-+
-+ if (inode->i_sb == NULL) {
-+ printk(KERN_ERR "axfs_iget5_set:"
-+ " the super block is set to null\n");
-+ }
-+ inode->i_ino = *inode_number;
-+ return 0;
-+}
-+
-+struct inode *axfs_create_vfs_inode(struct super_block *sb, int ino)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ struct inode *inode;
-+ u64 size;
-+
-+ inode = iget5_locked(sb, ino, axfs_iget5_test, axfs_iget5_set, &ino);
-+
-+ if (!(inode && (inode->i_state & I_NEW)))
-+ return inode;
-+
-+ inode->i_mode = axfs_get_mode(sbi, ino);
-+ inode->i_uid = axfs_get_uid(sbi, ino);
-+ size = axfs_get_inode_file_size(sbi, ino);
-+ inode->i_size = size;
-+ inode->i_blocks = axfs_get_inode_num_entries(sbi, ino);
-+ inode->i_blkbits = PAGE_CACHE_SHIFT;
-+ inode->i_gid = axfs_get_gid(sbi, ino);
-+
-+ inode->i_mtime = inode->i_atime = inode->i_ctime = sbi->timestamp;
-+ inode->i_ino = ino;
-+
-+ if (S_ISREG(inode->i_mode)) {
-+ inode->i_fop = &axfs_fops;
-+ inode->i_data.a_ops = &axfs_aops;
-+ inode->i_mapping->a_ops = &axfs_aops;
-+ } else if (S_ISDIR(inode->i_mode)) {
-+ inode->i_op = &axfs_dir_inode_operations;
-+ inode->i_fop = &axfs_directory_operations;
-+ } else if (S_ISLNK(inode->i_mode)) {
-+ inode->i_op = &page_symlink_inode_operations;
-+ inode->i_data.a_ops = &axfs_aops;
-+ } else {
-+ inode->i_size = 0;
-+ inode->i_blocks = 0;
-+ init_special_inode(inode, inode->i_mode, old_decode_dev(size));
-+ }
-+ unlock_new_inode(inode);
-+
-+ return inode;
-+}
-+
-+static int axfs_get_xip_mem(struct address_space *mapping, pgoff_t offset,
-+ int create, void **kaddr, unsigned long *pfn)
-+{
-+ struct inode *inode = mapping->host;
-+ struct super_block *sb = inode->i_sb;
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ u64 ino_number = inode->i_ino;
-+ u64 ino_index, node_index;
-+
-+ ino_index = axfs_get_inode_array_index(sbi, ino_number);
-+ ino_index += offset;
-+
-+ node_index = axfs_get_node_index(sbi, ino_index);
-+
-+ *kaddr = (void *)(sbi->xip.virt_addr + (node_index << PAGE_SHIFT));
-+
-+ if (axfs_region_is_vmalloc(sbi, &(sbi->xip))) {
-+ *pfn = vmalloc_to_pfn(*kaddr);
-+ } else if (axfs_physaddr_is_valid(sbi)) {
-+ *pfn = (axfs_get_xip_region_physaddr(sbi) >> PAGE_SHIFT);
-+ *pfn += node_index;
-+ } else {
-+ *pfn = page_to_pfn(virt_to_page(*kaddr));
-+ }
-+
-+ return 0;
-+}
-+
-+static int axfs_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+
-+ file_accessed(file);
-+
-+ vma->vm_ops = &axfs_vm_ops;
-+
-+#ifdef VM_MIXEDMAP
-+#ifdef VM_CAN_NONLINEAR
-+ vma->vm_flags |= VM_CAN_NONLINEAR | VM_MIXEDMAP;
-+#else
-+ vma->vm_flags |= VM_IO | VM_MIXEDMAP;
-+#endif
-+#else
-+#ifdef VM_PFNMAP
-+ vma->vm_flags |= VM_IO | VM_PFNMAP;
-+#else
-+ vma->vm_flags |= VM_IO;
-+#endif
-+#endif
-+#ifdef VM_XIP
-+ vma->vm_flags |= VM_XIP;
-+#endif
-+
-+ return 0;
-+}
-+
-+/* The loop does a handful of things:
-+ * - First we see if they're the same length, if not we don't care.
-+ * - Then, we do a strncmp on two same-length strings:
-+ * > -1 -> If the entry was in this directory, it would have been
-+ * right before this one.
-+ * > 1 -> It's somewhere farther along in this directory.
-+ */
-+static struct dentry *axfs_lookup(struct inode *dir, struct dentry *dentry,
-+ struct nameidata *nd)
-+{
-+ struct super_block *sb = dir->i_sb;
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ u64 ino_number = dir->i_ino;
-+ u64 dir_index = 0;
-+ u64 entry;
-+ char *name;
-+ int namelen, err;
-+
-+ while (dir_index < axfs_get_inode_num_entries(sbi, ino_number)) {
-+ entry = axfs_get_inode_array_index(sbi, ino_number);
-+ entry += dir_index;
-+
-+ name = axfs_get_inode_name(sbi, entry);
-+ namelen = strlen(name);
-+
-+ dir_index++;
-+
-+ if (dentry->d_name.len != namelen)
-+ continue;
-+
-+ err = strncmp(dentry->d_name.name, name, namelen);
-+
-+ if (err < 0)
-+ break;
-+
-+ if (err > 0)
-+ continue;
-+
-+ d_add(dentry, axfs_create_vfs_inode(dir->i_sb, entry));
-+ goto out;
-+
-+ }
-+ d_add(dentry, NULL);
-+
-+out:
-+ return NULL;
-+}
-+
-+static int axfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
-+{
-+ struct inode *inode = filp->f_dentry->d_inode;
-+ struct super_block *sb = inode->i_sb;
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ u64 ino_number = inode->i_ino;
-+ u64 entry;
-+ loff_t dir_index;
-+ char *name;
-+ int namelen, mode;
-+ int err = 0;
-+
-+ /*
-+ * Get the current index into the directory and verify it is not beyond
-+ * the end of the list
-+ */
-+ dir_index = filp->f_pos;
-+ if (dir_index >= axfs_get_inode_num_entries(sbi, ino_number))
-+ goto out;
-+
-+ while (dir_index < axfs_get_inode_num_entries(sbi, ino_number)) {
-+ entry = axfs_get_inode_array_index(sbi, ino_number) + dir_index;
-+
-+ name = axfs_get_inode_name(sbi, entry);
-+ namelen = strlen(name);
-+
-+ mode = (int)axfs_get_mode(sbi, entry);
-+ err = filldir(dirent, name, namelen, dir_index, entry, mode);
-+
-+ if (err)
-+ break;
-+
-+ dir_index++;
-+ filp->f_pos = dir_index;
-+ }
-+
-+out:
-+ return 0;
-+}
-+
-+/******************************************************************************
-+ *
-+ * axfs_fault
-+ *
-+ * Description: This function is mapped into the VMA operations vector, and
-+ * gets called on a page fault. Depending on whether the page
-+ * is XIP or compressed, xip_file_fault or filemap_fault is
-+ * called. This function also logs when a fault occurs when
-+ * profiling is on.
-+ *
-+ * Parameters:
-+ * (IN) vma - The virtual memory area corresponding to a file
-+ *
-+ * (IN) vmf - The fault info pass in by the fault handler
-+ *
-+ * Returns:
-+ * 0 or error number
-+ *
-+ *****************************************************************************/
-+static int axfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-+{
-+ struct file *file = vma->vm_file;
-+ struct inode *inode = file->f_dentry->d_inode;
-+ struct super_block *sb = inode->i_sb;
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ u64 ino_number = inode->i_ino;
-+ u64 array_index;
-+
-+ array_index = axfs_get_inode_array_index(sbi, ino_number) + vmf->pgoff;
-+
-+ /*
-+ * if that pages are marked for write they will probably end up in RAM
-+ * therefore we don't want their counts for being XIP'd
-+ */
-+ if (!(vma->vm_flags & VM_WRITE))
-+ axfs_profiling_add(sbi, array_index, ino_number);
-+
-+ /*
-+ * figure out if the node is XIP or compressed and call the
-+ * appropriate function
-+ */
-+ if (axfs_is_node_xip(sbi, array_index))
-+ return xip_file_fault(vma, vmf);
-+ return filemap_fault(vma, vmf);
-+}
-+
-+/******************************************************************************
-+ *
-+ * axfs_file_read
-+ *
-+ * Description: axfs_file_read is mapped into the file_operations vector for
-+ * all axfs files. It loops through the pages to be read and calls
-+ * either do_sync_read (if the page is a compressed one) or
-+ * xip_file_read (if the page is XIP).
-+ *
-+ * Parameters:
-+ * (IN) filp - file to be read
-+ *
-+ * (OUT) buf - user buffer that is filled with the data that we read.
-+ *
-+ * (IN) len - length of file to be read
-+ *
-+ * (IN) ppos - offset within the file to read from
-+ *
-+ * Returns:
-+ * actual size of data read.
-+ *
-+ *****************************************************************************/
-+static ssize_t axfs_file_read(struct file *filp, char __user *buf, size_t len,
-+ loff_t *ppos)
-+{
-+ struct inode *inode = filp->f_dentry->d_inode;
-+ struct super_block *sb = inode->i_sb;
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ size_t read = 0, total_read = 0;
-+ size_t readlength, actual_size, file_size, remaining;
-+ u64 ino_number = inode->i_ino;
-+ u64 size, array_index;
-+
-+ file_size = axfs_get_inode_file_size(sbi, ino_number);
-+ remaining = file_size - *ppos;
-+ actual_size = len > remaining ? remaining : len;
-+ readlength = actual_size < PAGE_SIZE ? actual_size : PAGE_SIZE;
-+
-+ for (size = actual_size; size > 0; size -= read) {
-+ array_index = axfs_get_inode_array_index(sbi, ino_number);
-+ array_index += *ppos >> PAGE_SHIFT;
-+
-+ if (axfs_is_node_xip(sbi, array_index))
-+ read = xip_file_read(filp, buf, readlength, ppos);
-+ else
-+ read = do_sync_read(filp, buf, readlength, ppos);
-+
-+ buf += read;
-+ total_read += read;
-+
-+ if ((len - total_read < PAGE_SIZE) && (total_read != len))
-+ readlength = len - total_read;
-+ }
-+
-+ return total_read;
-+}
-+
-+static int axfs_readpage(struct file *file, struct page *page)
-+{
-+ struct inode *inode = page->mapping->host;
-+ struct super_block *sb = inode->i_sb;
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ u64 array_index, node_index, cnode_index, maxblock, ofs;
-+ u64 ino_number = inode->i_ino;
-+ u32 max_len, cnode_offset;
-+ u32 cblk_size = sbi->cblock_size;
-+ u32 len = 0;
-+ u8 node_type;
-+ void *pgdata;
-+ void *src;
-+ void *cblk0 = sbi->cblock_buffer[0];
-+ void *cblk1 = sbi->cblock_buffer[1];
-+
-+ maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-+ pgdata = kmap(page);
-+
-+ if (page->index >= maxblock)
-+ goto out;
-+
-+ array_index = axfs_get_inode_array_index(sbi, ino_number);
-+ array_index += page->index;
-+
-+ node_index = axfs_get_node_index(sbi, array_index);
-+ node_type = axfs_get_node_type(sbi, array_index);
-+
-+ if (node_type == Compressed) {
-+ /* node is in compessed region */
-+ cnode_offset = axfs_get_cnode_offset(sbi, node_index);
-+ cnode_index = axfs_get_cnode_index(sbi, node_index);
-+ down_write(&sbi->lock);
-+ if (cnode_index != sbi->current_cnode_index) {
-+ /* uncompress only necessary if different cblock */
-+ ofs = axfs_get_cblock_offset(sbi, cnode_index);
-+ len = axfs_get_cblock_offset(sbi, cnode_index + 1);
-+ len -= ofs;
-+ axfs_copy_data(sb, cblk1, &(sbi->compressed), ofs, len);
-+ axfs_uncompress_block(cblk0, cblk_size, cblk1, len);
-+ sbi->current_cnode_index = cnode_index;
-+ }
-+ downgrade_write(&sbi->lock);
-+ max_len = cblk_size - cnode_offset;
-+ len = max_len > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : max_len;
-+ src = (void *)((unsigned long)cblk0 + cnode_offset);
-+ memcpy(pgdata, src, len);
-+ up_read(&sbi->lock);
-+ } else if (node_type == Byte_Aligned) {
-+ /* node is in BA region */
-+ ofs = axfs_get_banode_offset(sbi, node_index);
-+ max_len = sbi->byte_aligned.size - ofs;
-+ len = max_len > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : max_len;
-+ axfs_copy_data(sb, pgdata, &(sbi->byte_aligned), ofs, len);
-+ } else {
-+ /* node is XIP */
-+ ofs = node_index << PAGE_SHIFT;
-+ len = PAGE_CACHE_SIZE;
-+ axfs_copy_data(sb, pgdata, &(sbi->xip), ofs, len);
-+ }
-+
-+out:
-+ memset(pgdata + len, 0, PAGE_CACHE_SIZE - len);
-+ kunmap(page);
-+ flush_dcache_page(page);
-+ SetPageUptodate(page);
-+ unlock_page(page);
-+ return 0;
-+}
-+
-+static const struct file_operations axfs_directory_operations = {
-+ .llseek = generic_file_llseek,
-+ .read = generic_read_dir,
-+ .readdir = axfs_readdir,
-+};
-+
-+static const struct file_operations axfs_fops = {
-+ .read = axfs_file_read,
-+ .aio_read = generic_file_aio_read,
-+ .mmap = axfs_mmap,
-+};
-+
-+static const struct address_space_operations axfs_aops = {
-+ .readpage = axfs_readpage,
-+ .get_xip_mem = axfs_get_xip_mem,
-+};
-+
-+static struct inode_operations axfs_dir_inode_operations = {
-+ .lookup = axfs_lookup,
-+};
-+
-+static struct vm_operations_struct axfs_vm_ops = {
-+ .fault = axfs_fault,
-+};
+++ /dev/null
-From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:40:42 2012
-From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Date: Fri, 23 Nov 2012 17:04:58 +0530
-Subject: [PATCH v2 RESEND 06/15] AXFS: axfs_mtd.c
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
-Message-ID: <50AF5F62.3030809@ap.sony.com>
-
-
-From: Jared Hulbert <jaredeh@gmail.com>
-
-Allows axfs to use mtd devices or has dummy functions if mtd
-device support is compiled out of the kernel.
-
-Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
-Signed-off-by: Thomas Rony Jose <thomas.jose@ap.sony.com>
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
----
- fs/axfs/axfs_mtd.c | 351 +++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 351 insertions(+)
- create mode 100644 fs/axfs/axfs_mtd.c
-
---- /dev/null
-+++ b/fs/axfs/axfs_mtd.c
-@@ -0,0 +1,351 @@
-+/*
-+ * Advanced XIP File System for Linux - AXFS
-+ * Readonly, compressed, and XIP filesystem for Linux systems big and small
-+ *
-+ * Copyright(c) 2008 Numonyx
-+ * Copyright 2011 Sony Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * Authors:
-+ * Jared Hulbert <jaredeh@gmail.com>
-+ *
-+ * Project url: http://axfs.sourceforge.net
-+ *
-+ * axfs_mtd.c -
-+ * Allows axfs to use mtd devices or has dummy functions if mtd
-+ * device support is compiled out of the kernel.
-+ */
-+#include "axfs.h"
-+
-+#include <linux/fs.h>
-+#include <linux/mount.h>
-+#include <linux/ctype.h>
-+#include <linux/namei.h>
-+
-+#ifdef CONFIG_MTD
-+#define AXFS_CONFIG_MTD
-+#endif
-+
-+#ifdef AXFS_CONFIG_MTD
-+#include <linux/mtd/super.h>
-+
-+struct mtd_info *axfs_mtd(struct super_block *sb)
-+{
-+ return (void *)sb->s_mtd;
-+}
-+
-+struct mtd_info *axfs_mtd0(struct super_block *sb)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+
-+ if (sbi->mtd0 != NULL)
-+ return sbi->mtd0;
-+ else
-+ return axfs_mtd(sb);
-+}
-+
-+struct mtd_info *axfs_mtd1(struct super_block *sb)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+
-+ return sbi->mtd1;
-+}
-+
-+int axfs_has_mtd(struct super_block *sb)
-+{
-+ if (sb->s_fs_info == NULL)
-+ return false;
-+
-+ if (axfs_mtd0(sb))
-+ return true;
-+
-+ if (axfs_mtd1(sb))
-+ return true;
-+
-+ if (axfs_mtd(sb))
-+ return true;
-+
-+ return false;
-+}
-+
-+struct mtd_info *axfs_get_mtd_device(int mtdnr)
-+{
-+ struct mtd_info *device;
-+
-+ device = get_mtd_device(NULL, mtdnr);
-+
-+ if (!PTR_ERR(device))
-+ return NULL;
-+
-+ return device;
-+}
-+
-+int axfs_is_dev_mtd(char *path, int *mtdnr)
-+{
-+ char *off = NULL;
-+ char *endptr = NULL;
-+ char dev[] = "/dev/\0";
-+ char mtd[] = "mtd\0";
-+ char mtdblk[] = "mtdblock\0";
-+
-+ if (!path || !*path)
-+ return false;
-+
-+ off = path;
-+
-+ if (strncmp(dev, off, strlen(dev)) == 0)
-+ off += strlen(dev);
-+
-+ if (!strncmp(mtd, off, strlen(mtd)) && isdigit(off[strlen(mtd)]))
-+ off += strlen(mtd);
-+
-+ if (!strncmp(mtdblk, off, strlen(mtdblk))
-+ && isdigit(off[strlen(mtdblk)]))
-+ off += strlen(mtdblk);
-+
-+ *mtdnr = simple_strtoul(off, &endptr, 0);
-+
-+ if (!*endptr)
-+ return true;
-+
-+ return false;
-+}
-+
-+static struct mtd_info *axfs_get_mtd_info(struct super_block *sb, u64 fsoffset)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+
-+ if (fsoffset == 0)
-+ return (struct mtd_info *)axfs_mtd0(sb);
-+
-+ if (fsoffset < sbi->mmap_size)
-+ return (struct mtd_info *)axfs_mtd0(sb);
-+
-+ if (axfs_mtd1(sb) != NULL)
-+ return (struct mtd_info *)axfs_mtd1(sb);
-+
-+ return (struct mtd_info *)axfs_mtd0(sb);
-+}
-+
-+int axfs_copy_mtd(struct super_block *sb, void *dst, u64 fsoffset, u64 len)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ u64 offset = axfs_fsoffset_to_devoffset(sbi, fsoffset);
-+ struct mtd_info *mtd;
-+ u_char *mtdbuf = (u_char *) dst;
-+ size_t retlen;
-+ int err = 0;
-+
-+ if (len == 0)
-+ return 0;
-+
-+ mtd = axfs_get_mtd_info(sb, fsoffset);
-+ err = mtd_read(mtd, (loff_t) offset, (size_t) len, &retlen, mtdbuf);
-+
-+ if (len != retlen)
-+ return -EIO;
-+
-+ return err;
-+}
-+
-+/******************************************************************************
-+ *
-+ * axfs_map_mtd
-+ *
-+ * Description: When provided, uses the mtd point() capability to map allow
-+ * axfs a direct memory access to the filesystem.
-+ *
-+ * Parameters:
-+ * (IN) sb - pointer to the super_block structure
-+ *
-+ * Returns:
-+ * 0 or error number
-+ *
-+ *****************************************************************************/
-+int axfs_map_mtd(struct super_block *sb)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ struct mtd_info *mtd = (struct mtd_info *)axfs_mtd0(sb);
-+ size_t retlen;
-+ int err = 0;
-+ void *virt;
-+ resource_size_t phys;
-+
-+ err = mtd_point(mtd, 0, sbi->mmap_size, &retlen, &virt, &phys);
-+ if (err)
-+ return err;
-+
-+ if (retlen != sbi->mmap_size) {
-+ mtd_unpoint(mtd, 0, retlen);
-+ return -EINVAL;
-+ }
-+
-+ sbi->virt_start_addr = (unsigned long)virt;
-+ sbi->phys_start_addr = (unsigned long)phys;
-+ sbi->mtd_pointed = true;
-+
-+ return 0;
-+}
-+
-+void axfs_unmap_mtd(struct super_block *sb)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ struct mtd_info *mtd = (struct mtd_info *)axfs_mtd0(sb);
-+
-+ if (!sbi)
-+ return;
-+
-+ if (axfs_mtd1(sb))
-+ put_mtd_device((struct mtd_info *)axfs_mtd1(sb));
-+
-+ if (axfs_is_pointed(sbi)) {
-+ mtd_unpoint(mtd, 0, sbi->mmap_size);
-+ } else {
-+ if (axfs_mtd0(sb))
-+ put_mtd_device((struct mtd_info *)axfs_mtd0(sb));
-+ }
-+}
-+
-+int axfs_verify_mtd_sizes(struct super_block *sb, int *err)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ struct mtd_info *mtd0 = (struct mtd_info *)axfs_mtd0(sb);
-+ struct mtd_info *mtd1 = (struct mtd_info *)axfs_mtd1(sb);
-+ u64 io_dev_size;
-+
-+ *err = 0;
-+ io_dev_size = axfs_get_io_dev_size(sb);
-+
-+ if (!mtd0 && !mtd1)
-+ return false;
-+
-+ /* One mtd device entirely mmaped */
-+ if (sbi->mtd_pointed && !io_dev_size) {
-+ if (sbi->mmap_size != sbi->size) {
-+ *err = -EINVAL;
-+ return false;
-+ }
-+
-+ return true;
-+ }
-+
-+ if (!io_dev_size)
-+ return false;
-+
-+ /* filesystem split across two mtd devs */
-+ if (mtd1) {
-+ if (io_dev_size > mtd1->size)
-+ goto too_small;
-+ else
-+ return true;
-+ }
-+
-+ /* One mtd device partially mmaped, partially io */
-+ if (sbi->mtd_pointed) {
-+ if (sbi->size > mtd0->size)
-+ goto too_small;
-+ else
-+ return true;
-+ }
-+
-+ /* One mtd device as a IO dev or split with physaddr */
-+ if (io_dev_size > mtd0->size)
-+ goto too_small;
-+
-+ return true;
-+
-+too_small:
-+ printk(KERN_ERR "axfs: filesystem extends beyond end of MTD, ");
-+ printk(KERN_ERR "expected 0x%llx ", io_dev_size);
-+ printk(KERN_ERR "got 0x%llu\n", (mtd1) ? mtd1->size : mtd0->size);
-+ *err = -EINVAL;
-+ return true;
-+}
-+
-+struct dentry *axfs_get_sb_mtd(struct file_system_type *fs_type, int flags,
-+ const char *dev_name, struct axfs_super *sbi)
-+{
-+ int *err = ERR_PTR(-EINVAL);
-+ int nflags, mtdnr;
-+
-+ if (axfs_is_dev_mtd(sbi->second_dev, &mtdnr)) {
-+ sbi->mtd1 = (void *)axfs_get_mtd_device(mtdnr);
-+ if (!sbi->mtd1) {
-+ *err = -EINVAL;
-+ return false;
-+ }
-+ }
-+ nflags = flags & MS_SILENT;
-+
-+ return mount_mtd(fs_type, nflags, dev_name, sbi, axfs_fill_super);
-+}
-+
-+void axfs_kill_mtd_super(struct super_block *sb)
-+{
-+ kill_mtd_super(sb);
-+}
-+#else
-+struct mtd_info *axfs_mtd(struct super_block *sb)
-+{
-+ return NULL;
-+}
-+
-+struct mtd_info *axfs_mtd0(struct super_block *sb)
-+{
-+ return NULL;
-+}
-+
-+struct mtd_info *axfs_mtd1(struct super_block *sb)
-+{
-+ return NULL;
-+}
-+
-+int axfs_has_mtd(struct super_block *sb)
-+{
-+ return false;
-+}
-+
-+struct mtd_info *axfs_get_mtd_device(int mtdnr)
-+{
-+ return NULL;
-+}
-+
-+int axfs_map_mtd(struct super_block *sb)
-+{
-+ return 0;
-+}
-+
-+void axfs_unmap_mtd(struct super_block *sb)
-+{
-+}
-+
-+int axfs_copy_mtd(struct super_block *sb, void *dst, u64 fsoffset, u64 len)
-+{
-+ return -EINVAL;
-+}
-+
-+struct dentry *axfs_get_sb_mtd(struct file_system_type *fs_type, int flags,
-+ const char *dev_name, struct axfs_super *sbi)
-+{
-+ return false;
-+}
-+
-+int axfs_is_dev_mtd(char *path, int *mtdnr)
-+{
-+ return false;
-+}
-+
-+void axfs_kill_mtd_super(struct super_block *sb)
-+{
-+}
-+
-+int axfs_verify_mtd_sizes(struct super_block *sb, int *err)
-+{
-+ *err = 0;
-+ return true;
-+}
-+
-+#endif /* CONFIG_MTD */
+++ /dev/null
-From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:42:02 2012
-From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Date: Fri, 23 Nov 2012 17:06:20 +0530
-Subject: [PATCH v2 RESEND 07/15] AXFS: axfs_physmem.c
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
-Message-ID: <50AF5FB4.4000102@ap.sony.com>
-
-
-From: Jared Hulbert <jaredeh@gmail.com>
-
-Allows axfs to use striaght memory or has dummy functions if
-this is a UML system.
-
-Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
----
- fs/axfs/axfs_physmem.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 65 insertions(+)
- create mode 100644 fs/axfs/axfs_physmem.c
-
---- /dev/null
-+++ b/fs/axfs/axfs_physmem.c
-@@ -0,0 +1,65 @@
-+/*
-+ * Advanced XIP File System for Linux - AXFS
-+ * Readonly, compressed, and XIP filesystem for Linux systems big and small
-+ *
-+ * Copyright(c) 2008 Numonyx
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * Authors:
-+ * Jared Hulbert <jaredeh@gmail.com>
-+ *
-+ * Project url: http://axfs.sourceforge.net
-+ *
-+ * axfs_physmem.c -
-+ * Allows axfs to use striaght memory or has dummy functions if
-+ * this is a UML system.
-+ */
-+#include "axfs.h"
-+
-+#include <linux/fs.h>
-+#ifdef CONFIG_UML
-+
-+void axfs_map_physmem(struct axfs_super *sbi, unsigned long size)
-+{
-+}
-+
-+void axfs_unmap_physmem(struct super_block *sb)
-+{
-+}
-+
-+#else
-+#include <linux/io.h>
-+
-+#ifdef ioremap_cached
-+#define AXFS_REMAP(a, b) (void __force *)ioremap_cached((a), (b))
-+#else
-+#define AXFS_REMAP(a, b) (void __force *)ioremap((a), (b))
-+#endif /* ioremap_cached */
-+
-+void axfs_map_physmem(struct axfs_super *sbi, unsigned long size)
-+{
-+ void *addr;
-+
-+ if (axfs_is_physmem(sbi)) {
-+ addr = AXFS_REMAP(sbi->phys_start_addr, size);
-+ sbi->virt_start_addr = (unsigned long)addr;
-+ }
-+}
-+
-+void axfs_unmap_physmem(struct super_block *sb)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+
-+ if (!sbi)
-+ return;
-+
-+ if (axfs_is_physmem(sbi) && axfs_virtaddr_is_valid(sbi)) {
-+ iounmap((void *)(sbi->virt_start_addr));
-+ sbi->virt_start_addr = 0;
-+ }
-+}
-+
-+#endif /* CONFIG_UML */
+++ /dev/null
-From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:43:37 2012
-From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Date: Fri, 23 Nov 2012 17:07:55 +0530
-Subject: [PATCH v2 RESEND 08/15] AXFS: axfs_profiling.c
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
-Message-ID: <50AF6013.3080100@ap.sony.com>
-
-
-From: Jared Hulbert <jaredeh@gmail.com>
-
-Tracks pages of files that enter the page cache. Outputs through a proc
-file which generates a comma separated data file with path, page offset,
-count of times entered page cache.
-
-Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
----
- fs/axfs/axfs_profiling.c | 605 +++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 605 insertions(+)
- create mode 100644 fs/axfs/axfs_profiling.c
-
---- /dev/null
-+++ b/fs/axfs/axfs_profiling.c
-@@ -0,0 +1,605 @@
-+/*
-+ * Advanced XIP File System for Linux - AXFS
-+ * Readonly, compressed, and XIP filesystem for Linux systems big and small
-+ *
-+ * Copyright(c) 2008 Numonyx
-+ * Copyright 2011 Sony Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * Authors:
-+ * Eric Anderson
-+ * Jared Hulbert <jaredeh@gmail.com>
-+ * Sujaya Srinivasan
-+ * Justin Treon
-+ *
-+ * More info and current contacts at http://axfs.sourceforge.net
-+ *
-+ * axfs_profiling.c -
-+ * Tracks pages of files that enter the page cache. Outputs through a proc
-+ * file which generates a comma separated data file with path, page offset,
-+ * count of times entered page cache.
-+ */
-+#include "axfs.h"
-+
-+#ifdef CONFIG_AXFS_PROFILING
-+#include <linux/module.h>
-+#include <linux/vmalloc.h>
-+#include <linux/proc_fs.h>
-+
-+#define AXFS_PROC_DIR_NAME "axfs"
-+
-+struct axfs_profiling_manager {
-+ struct axfs_profiling_data *profiling_data;
-+ struct axfs_super *sbi;
-+ u32 *dir_structure;
-+ u32 size;
-+};
-+
-+#define MAX_STRING_LEN 1024
-+
-+/* Handles for our Directory and File */
-+static struct proc_dir_entry *axfs_proc_dir;
-+static u32 proc_name_inc;
-+
-+/******************************************************************************
-+ *
-+ * axfs_init_profile_dir_structure
-+ *
-+ * Description:
-+ * Creates the structures for tracking the page usage data and creates the
-+ * proc file that will be used to get the data.
-+ *
-+ * Parameters:
-+ * (IN) manager - pointer to the profile manager for the filing system
-+ *
-+ * (IN) num_inodes - number of files in the system
-+ *
-+ * Returns:
-+ * 0
-+ *
-+ *****************************************************************************/
-+static int axfs_init_profile_dir_structure(struct axfs_profiling_manager
-+ *manager, u32 num_inodes)
-+{
-+
-+ struct axfs_super *sbi = (struct axfs_super *)manager->sbi;
-+ u32 child_index = 0, i, j;
-+ u32 *dir_structure = manager->dir_structure;
-+
-+ /*
-+ * loop through each inode in the image and find all
-+ * of the directories and mark their children
-+ */
-+ for (i = 0; i < num_inodes; i++) {
-+ /* determine if the entry is a directory */
-+ if (!S_ISDIR(axfs_get_mode(sbi, i)))
-+ continue;
-+
-+ /* get the index number for this directory */
-+ child_index = axfs_get_inode_array_index(sbi, i);
-+
-+ /* get the offset to its children */
-+ for (j = 0; j < axfs_get_inode_num_entries(sbi, i); j++) {
-+ if (dir_structure[child_index + j] != 0) {
-+ printk(KERN_ERR
-+ "axfs: ERROR inode was already set old "
-+ "%lu new %lu\n", (unsigned long)
-+ dir_structure[child_index + j],
-+ (unsigned long)i);
-+ }
-+ dir_structure[child_index + j] = i;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+/******************************************************************************
-+ *
-+ * axfs_get_directory_path
-+ *
-+ * Description:
-+ * Determines the directory path of every file for printing the spreadsheet.
-+ *
-+ * Parameters:
-+ * (IN) manager - Pointer to axfs profile manager
-+ *
-+ * (OUT) buffer - Pointer to the printable directory path for each file
-+ *
-+ * (IN) inode_number - Inode number of file to look up
-+ *
-+ * Returns:
-+ * Size of the path to the file
-+ *
-+ *
-+ **************************************************************************/
-+static int axfs_get_directory_path(struct axfs_profiling_manager *manager,
-+ char *buffer, u32 inode_number)
-+{
-+ u32 path_depth = 0;
-+ u32 path_size = 0;
-+ u32 string_len = 0;
-+ u32 index = inode_number;
-+ u32 dir_number;
-+ u8 **path_array = NULL;
-+ struct axfs_super *sbi = (struct axfs_super *)manager->sbi;
-+ int i;
-+
-+ /*
-+ * determine how deep the directory path is and how big the name
-+ * string will be walk back until the root directory index is found
-+ * (index 0 is root)
-+ */
-+ while (manager->dir_structure[index] != 0) {
-+ path_depth++;
-+ /* set the index to the index of the parent directory */
-+ index = manager->dir_structure[index];
-+ }
-+
-+ if (path_depth != 0) {
-+ /*
-+ * create an array that will hold a pointer for each of the
-+ * directories names
-+ */
-+ path_array = vmalloc(path_depth * sizeof(*path_array));
-+ if (path_array == NULL) {
-+ printk(KERN_DEBUG
-+ "axfs: directory_path vmalloc failed.\n");
-+ goto out;
-+ }
-+ }
-+
-+ index = manager->dir_structure[inode_number];
-+ for (i = path_depth; i > 0; i--) {
-+ /*
-+ * get the array_index for the directory corresponding to
-+ * index
-+ */
-+ dir_number = axfs_get_inode_array_index(sbi, index);
-+
-+ /* store a pointer to the name in the array */
-+ path_array[(i - 1)] = (u8 *) axfs_get_inode_name(sbi, index);
-+
-+ index = manager->dir_structure[index];
-+ }
-+
-+ /* now print out the directory structure from the begining */
-+ string_len = sprintf(buffer, "./");
-+ path_size += string_len;
-+ for (i = 0; i < path_depth; i++) {
-+ buffer = buffer + string_len;
-+ string_len = sprintf(buffer, "%s/", (char *)path_array[i]);
-+ path_size += string_len;
-+ }
-+
-+ vfree(path_array);
-+
-+out:
-+ return path_size;
-+
-+}
-+
-+static ssize_t axfs_procfile_read(char *buffer,
-+ char **buffer_location,
-+ off_t offset, int buffer_length, int *eof,
-+ void *data)
-+{
-+ struct axfs_profiling_manager *man;
-+ struct axfs_profiling_data *profile;
-+ struct axfs_super *sbi;
-+ u64 array_index;
-+ u64 loop_size, inode_page_offset, node_offset, inode_number;
-+ u64 print_len = 0;
-+ unsigned long addr;
-+ int len = 0;
-+ int i;
-+ char *buff, *name = NULL;
-+
-+ man = (struct axfs_profiling_manager *)data;
-+ sbi = man->sbi;
-+
-+ loop_size = man->size / sizeof(*profile);
-+
-+ /* If all data has been returned set EOF */
-+ if (offset >= loop_size) {
-+ *eof = 1;
-+ return 0;
-+ }
-+
-+ buff = buffer;
-+ /* print as much as the buffer can take */
-+ for (i = offset; i < loop_size; i++) {
-+
-+ if ((print_len + MAX_STRING_LEN) > buffer_length)
-+ break;
-+ /* get the first profile data structure */
-+ profile = &(man->profiling_data[i]);
-+
-+ if (profile->count == 0)
-+ continue;
-+
-+ inode_number = profile->inode_number;
-+
-+ /* file names can be duplicated so we must print out the path */
-+ len = axfs_get_directory_path(man, buff, inode_number);
-+
-+ print_len += len;
-+ buff += len;
-+
-+ /* get a pointer to the inode name */
-+ array_index = axfs_get_inode_array_index(sbi, inode_number);
-+ name = axfs_get_inode_name(sbi, inode_number);
-+
-+ /*
-+ * need to convert the page number in the node area to
-+ * the page number within the file
-+ */
-+ node_offset = i;
-+ /*
-+ * gives the offset of the node in the node list area
-+ * then substract that from the
-+ */
-+ inode_page_offset = node_offset - array_index;
-+
-+ /* set everything up to print out */
-+ addr = (unsigned long)(inode_page_offset * PAGE_SIZE);
-+ len = sprintf(buff, "%s,%lu,%lu\n", name, addr, profile->count);
-+
-+ print_len += len;
-+ buff += len;
-+ }
-+
-+ /*
-+ * return the number of items printed. This will be
-+ * added to offset and passed back to us
-+ */
-+ *buffer_location = (char *)(i - offset);
-+
-+ return print_len;
-+}
-+
-+static ssize_t axfs_procfile_write(struct file *file,
-+ const char *buffer, unsigned long count,
-+ void *data)
-+{
-+ struct axfs_profiling_manager *man_ptr =
-+ (struct axfs_profiling_manager *)data;
-+
-+ if ((count >= 2) && (0 == memcmp(buffer, "on", 2))) {
-+ man_ptr->sbi->profiling_on = true;
-+ } else if ((count >= 3) && (0 == memcmp(buffer, "off", 3))) {
-+ man_ptr->sbi->profiling_on = false;
-+ } else if ((count >= 5) && (0 == memcmp(buffer, "clear", 5))) {
-+ memset(man_ptr->profiling_data, 0, man_ptr->size);
-+ } else {
-+ printk(KERN_INFO
-+ "axfs: Unknown command. Supported options are:\n");
-+ printk(KERN_INFO "\t\"on\"\tTurn on profiling\n");
-+ printk(KERN_INFO "\t\"off\"\tTurn off profiling\n");
-+ printk(KERN_INFO "\t\"clear\"\tClear profiling buffer\n");
-+ }
-+
-+ return count;
-+}
-+
-+static int axfs_create_proc_directory(void)
-+{
-+ if (axfs_proc_dir == NULL) {
-+ axfs_proc_dir = proc_mkdir(AXFS_PROC_DIR_NAME, NULL);
-+ if (!axfs_proc_dir) {
-+ printk(KERN_WARNING
-+ "axfs: Failed to create directory\n");
-+ return false;
-+ }
-+ }
-+ return true;
-+}
-+
-+static void axfs_delete_proc_directory(void)
-+{
-+ /*
-+ * Determine if there are any directory elements
-+ * and remove if all of the proc files are removed.
-+ */
-+ if (axfs_proc_dir != NULL) {
-+ if (axfs_proc_dir->subdir == NULL) {
-+ remove_proc_entry(AXFS_PROC_DIR_NAME, NULL);
-+ axfs_proc_dir = NULL;
-+ }
-+ }
-+}
-+
-+/******************************************************************************
-+ *
-+ * axfs_delete_proc_file
-+ *
-+ * Description:
-+ * Will search through the proc directory for the correct proc file,
-+ * then delete it
-+ *
-+ * Parameters:
-+ * (IN) sbi- axfs superblock pointer to determine which proc file to remove
-+ *
-+ * Returns:
-+ * The profiling manager pointer for the proc file.
-+ *
-+ *****************************************************************************/
-+static struct axfs_profiling_manager *axfs_delete_proc_file(struct axfs_super
-+ *sbi)
-+{
-+ struct proc_dir_entry *current_proc_file;
-+ struct axfs_profiling_manager *manager;
-+ void *rv = NULL;
-+
-+ if (!axfs_proc_dir)
-+ return NULL;
-+
-+ /* Walk through the proc file entries to find the matching sbi */
-+ current_proc_file = axfs_proc_dir->subdir;
-+
-+ while (current_proc_file != NULL) {
-+ manager = current_proc_file->data;
-+ if (manager == NULL) {
-+ printk(KERN_WARNING
-+ "axfs: Error removing proc file private "
-+ "data was NULL.\n");
-+ rv = NULL;
-+ break;
-+ }
-+ if (manager->sbi == sbi) {
-+ /* we found the match */
-+ remove_proc_entry(current_proc_file->name,
-+ axfs_proc_dir);
-+ rv = (void *)manager;
-+ break;
-+ }
-+ current_proc_file = axfs_proc_dir->next;
-+ }
-+ return (struct axfs_profiling_manager *)rv;
-+}
-+
-+/******************************************************************************
-+ *
-+ * axfs_register_profiling_proc
-+ *
-+ * Description:
-+ * Will register the instance of the proc file for a given volume.
-+ *
-+ * Parameters:
-+ * (IN) manager - Pointer to the profiling manager for the axfs volume
-+ *
-+ * Returns:
-+ * 0 or error number
-+ *
-+ *****************************************************************************/
-+static int axfs_register_profiling_proc(struct axfs_profiling_manager *manager)
-+{
-+ int rv = 0;
-+ struct proc_dir_entry *proc_file;
-+ char file_name[20];
-+
-+ if (!axfs_create_proc_directory()) {
-+ rv = -ENOMEM;
-+ goto out;
-+ }
-+
-+ sprintf(file_name, "volume%d", proc_name_inc);
-+ proc_file = create_proc_entry(file_name, (mode_t) 0644, axfs_proc_dir);
-+ if (proc_file == NULL) {
-+ remove_proc_entry(file_name, axfs_proc_dir);
-+ axfs_delete_proc_directory();
-+ rv = -ENOMEM;
-+ goto out;
-+ }
-+
-+ proc_name_inc++;
-+ proc_file->read_proc = axfs_procfile_read;
-+ proc_file->write_proc = axfs_procfile_write;
-+ proc_file->mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
-+ proc_file->uid = 0;
-+ proc_file->gid = 0;
-+ proc_file->data = manager;
-+
-+ printk(KERN_DEBUG "axfs: Proc entry created\n");
-+
-+out:
-+ return rv;
-+}
-+
-+/******************************************************************************
-+ *
-+ * axfs_unregister_profiling_proc
-+ *
-+ * Description:
-+ * Will unregister the instance of the proc file for the volume that was
-+ * mounted. If this is the last volume mounted then the proc directory
-+ * will also be removed.
-+ *
-+ * Parameters:
-+ * (IN) sbi- axfs superblock pointer to determine which proc file to remove
-+ *
-+ * Returns:
-+ * The profiling manager pointer for the proc file.
-+ *
-+ *****************************************************************************/
-+static struct axfs_profiling_manager *axfs_unregister_profiling_proc(struct
-+ axfs_super
-+ *sbi)
-+{
-+ struct axfs_profiling_manager *manager;
-+ manager = axfs_delete_proc_file(sbi);
-+ axfs_delete_proc_directory();
-+ return manager;
-+}
-+
-+/******************************************************************************
-+ *
-+ * axfs_init_profiling
-+ *
-+ * Description:
-+ * Creates the structures for tracking the page usage data and creates the
-+ * proc file that will be used to get the data.
-+ *
-+ * Parameters:
-+ * (IN) sbi- axfs superblock pointer
-+ *
-+ * Returns:
-+ * true or false
-+ *
-+ *****************************************************************************/
-+int axfs_init_profiling(struct axfs_super *sbi)
-+{
-+
-+ u32 num_nodes, num_inodes;
-+ struct axfs_profiling_manager *manager = NULL;
-+ struct axfs_profiling_data *profile_data = NULL;
-+ int err = -ENOMEM;
-+
-+ /* determine the max number of pages in the FS */
-+ num_nodes = sbi->blocks;
-+ if (!num_nodes)
-+ return 0;
-+
-+ manager = vmalloc(sizeof(*manager));
-+ if (!manager)
-+ goto out;
-+
-+ profile_data = vmalloc(num_nodes * sizeof(*profile_data));
-+ if (!profile_data)
-+ goto out;
-+
-+ memset(profile_data, 0, num_nodes * sizeof(*profile_data));
-+
-+ /* determine the max number of inodes in the FS */
-+ num_inodes = sbi->files;
-+
-+ manager->dir_structure = vmalloc(num_inodes * sizeof(u32 *));
-+ if (!manager->dir_structure)
-+ goto out;
-+
-+ memset(manager->dir_structure, 0, (num_inodes * sizeof(u32 *)));
-+
-+ manager->profiling_data = profile_data;
-+ manager->size = num_nodes * sizeof(*profile_data);
-+ manager->sbi = sbi;
-+ sbi->profiling_on = true; /* Turn on profiling by default */
-+ sbi->profile_data_ptr = profile_data;
-+
-+ err = axfs_init_profile_dir_structure(manager, num_inodes);
-+ if (err)
-+ goto out;
-+
-+ err = axfs_register_profiling_proc(manager);
-+ if (err)
-+ goto out;
-+
-+ return 0;
-+
-+out:
-+ vfree(manager->dir_structure);
-+ vfree(profile_data);
-+ vfree(manager);
-+ return err;
-+}
-+
-+/******************************************************************************
-+ *
-+ * axfs_shutdown_profiling
-+ *
-+ * Description:
-+ * Remove the proc file for this volume and release the memory in the
-+ * profiling manager
-+ *
-+ * Parameters:
-+ * (IN) sbi- axfs superblock pointer
-+ *
-+ * Returns:
-+ * true or false
-+ *
-+ *****************************************************************************/
-+int axfs_shutdown_profiling(struct axfs_super *sbi)
-+{
-+ struct axfs_profiling_manager *manager;
-+ /*
-+ * remove the proc file for this volume and release the memory in the
-+ * profiling manager
-+ */
-+
-+ if (!sbi)
-+ return true;
-+
-+ if (!sbi->profile_data_ptr)
-+ return true;
-+
-+ manager = axfs_unregister_profiling_proc(sbi);
-+
-+ if (manager == NULL)
-+ return false;
-+
-+ vfree(manager->dir_structure);
-+ vfree(manager->profiling_data);
-+ vfree(manager);
-+ return true;
-+}
-+
-+/******************************************************************************
-+ *
-+ * axfs_profiling_add
-+ *
-+ * Description:
-+ * Log when a node is paged into memory by incrementing the count in the
-+ * array profile data structure.
-+ *
-+ * Parameters:
-+ * (IN) sbi- axfs superblock pointer
-+ *
-+ * (IN) array_index - The offset into the nodes table of file (node number)
-+ *
-+ * (IN) axfs_inode_number - Inode of the node to determine file name later
-+ *
-+ * Returns:
-+ * none
-+ *
-+ *****************************************************************************/
-+void axfs_profiling_add(struct axfs_super *sbi, unsigned long array_index,
-+ unsigned int axfs_inode_number)
-+{
-+ unsigned long addr;
-+ struct axfs_profiling_data *profile_data;
-+
-+ if (sbi->profiling_on != true)
-+ return;
-+
-+ addr = (unsigned long)sbi->profile_data_ptr;
-+ addr += array_index * sizeof(*profile_data);
-+
-+ profile_data = (struct axfs_profiling_data *)addr;
-+
-+ /* Record the inode number to determine the file name later. */
-+ profile_data->inode_number = axfs_inode_number;
-+
-+ /* Increment the number of times the node has been paged in */
-+ profile_data->count++;
-+}
-+
-+#else
-+
-+int axfs_init_profiling(struct axfs_super *sbi)
-+{
-+ return 0;
-+}
-+
-+int axfs_shutdown_profiling(struct axfs_super *sbi)
-+{
-+ return 0;
-+}
-+
-+void axfs_profiling_add(struct axfs_super *sbi, unsigned long array_index,
-+ unsigned int axfs_inode_number)
-+{
-+}
-+
-+#endif /* CONFIG_AXFS_PROFILING */
+++ /dev/null
-From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:44:39 2012
-From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Date: Fri, 23 Nov 2012 17:08:56 +0530
-Subject: [PATCH v2 RESEND 09/15] AXFS: axfs_super.c
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
-Message-ID: <50AF6050.1060605@ap.sony.com>
-
-
-From: Jared Hulbert <jaredeh@gmail.com>
-
-Contains the core code used to mount the fs.
-
-Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
-Signed-off-by: Thomas Rony Jose <thomas.jose@ap.sony.com>
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
----
- fs/axfs/axfs_super.c | 987 +++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 987 insertions(+)
- create mode 100644 fs/axfs/axfs_super.c
-
---- /dev/null
-+++ b/fs/axfs/axfs_super.c
-@@ -0,0 +1,987 @@
-+/*
-+ * Advanced XIP File System for Linux - AXFS
-+ * Readonly, compressed, and XIP filesystem for Linux systems big and small
-+ *
-+ * Copyright(c) 2008 Numonyx
-+ * Copyright 2011 Sony Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * Authors:
-+ * Eric Anderson
-+ * Jared Hulbert <jaredeh@gmail.com>
-+ * Sujaya Srinivasan
-+ * Justin Treon
-+ *
-+ * More info and current contacts at http://axfs.sourceforge.net
-+ *
-+ * axfs_super.c -
-+ * Contains the core code used to mount the fs.
-+ *
-+ */
-+#include "axfs.h"
-+
-+#include <linux/vmalloc.h>
-+#include <linux/parser.h>
-+#include <linux/statfs.h>
-+#include <linux/module.h>
-+#include <linux/mount.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/slab.h>
-+
-+static struct super_operations axfs_sops;
-+
-+static int axfs_is_region_compressed(struct axfs_region_desc *region)
-+{
-+ if (region->compressed_size > 0)
-+ return true;
-+
-+ return false;
-+}
-+
-+static int axfs_is_mmapable(struct axfs_super *sbi, u64 offset)
-+{
-+ if (sbi->mmap_size > offset)
-+ return true;
-+
-+ return false;
-+}
-+
-+static int axfs_is_region_mmapable(struct axfs_super *sbi,
-+ struct axfs_region_desc *region)
-+{
-+ if (axfs_is_mmapable(sbi, region->fsoffset))
-+ if (axfs_virtaddr_is_valid(sbi))
-+ return true;
-+
-+ return false;
-+}
-+
-+static int axfs_is_offset_mmapable(struct axfs_super *sbi, u64 offset)
-+{
-+ if (axfs_is_mmapable(sbi, offset))
-+ if (axfs_virtaddr_is_valid(sbi))
-+ return true;
-+
-+ return false;
-+}
-+
-+static int axfs_is_region_incore(struct axfs_region_desc *region)
-+{
-+ if (region->incore > 0)
-+ return true;
-+
-+ return false;
-+}
-+
-+static int axfs_is_region_xip(struct axfs_super *sbi,
-+ struct axfs_region_desc *region)
-+{
-+ if (!axfs_can_xip(sbi))
-+ return false;
-+
-+ if (!axfs_is_region_mmapable(sbi, region))
-+ return false;
-+
-+ if (axfs_is_region_compressed(region))
-+ return false;
-+
-+ if (axfs_is_region_incore(region))
-+ return false;
-+
-+ return true;
-+}
-+
-+int axfs_physaddr_is_valid(struct axfs_super *sbi)
-+{
-+ if (sbi->phys_start_addr > 0)
-+ return true;
-+
-+ return false;
-+}
-+
-+int axfs_virtaddr_is_valid(struct axfs_super *sbi)
-+{
-+ if (sbi->virt_start_addr > 0)
-+ return true;
-+
-+ return false;
-+}
-+
-+int axfs_is_iomem(struct axfs_super *sbi)
-+{
-+ if (sbi->iomem_size > 0)
-+ return true;
-+
-+ return false;
-+}
-+
-+int axfs_is_pointed(struct axfs_super *sbi)
-+{
-+ if (sbi->mtd_pointed > 0)
-+ return true;
-+
-+ return false;
-+}
-+
-+int axfs_can_xip(struct axfs_super *sbi)
-+{
-+ if (axfs_is_pointed(sbi)) {
-+ if (!axfs_physaddr_is_valid(sbi))
-+ return false;
-+ }
-+
-+ if (!axfs_virtaddr_is_valid(sbi))
-+ return false;
-+
-+ return true;
-+}
-+
-+int axfs_is_physmem(struct axfs_super *sbi)
-+{
-+ int phys = axfs_physaddr_is_valid(sbi);
-+ int iomem = axfs_is_iomem(sbi);
-+ int point = axfs_is_pointed(sbi);
-+
-+ if (phys && !iomem && !point)
-+ return true;
-+
-+ return false;
-+}
-+
-+u64 axfs_fsoffset_to_devoffset(struct axfs_super *sbi, u64 fsoffset)
-+{
-+ if (sbi->phys_start_addr == 0)
-+ return fsoffset;
-+
-+ if (sbi->mtd1 == NULL || sbi->second_dev == NULL)
-+ return fsoffset;
-+
-+ if (fsoffset >= sbi->mmap_size)
-+ return fsoffset - sbi->mmap_size;
-+
-+ return fsoffset;
-+}
-+
-+int axfs_nodev(struct super_block *sb)
-+{
-+ if (!axfs_has_mtd(sb) && !axfs_has_bdev(sb))
-+ return true;
-+
-+ return false;
-+}
-+
-+static void axfs_free_region(struct axfs_super *sbi,
-+ struct axfs_region_desc *region)
-+{
-+ if (!region)
-+ return;
-+
-+ if (axfs_is_region_xip(sbi, region))
-+ return;
-+
-+ vfree(region->virt_addr);
-+}
-+
-+static struct axfs_super *axfs_get_sbi(void)
-+{
-+ struct axfs_super *sbi;
-+
-+ sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
-+ if (sbi)
-+ return sbi;
-+
-+ return ERR_PTR(-ENOMEM);
-+}
-+
-+static void axfs_put_sbi(struct axfs_super *sbi)
-+{
-+ if (!sbi)
-+ return;
-+
-+ axfs_shutdown_profiling(sbi);
-+
-+ axfs_free_region(sbi, &sbi->strings);
-+ axfs_free_region(sbi, &sbi->xip);
-+ axfs_free_region(sbi, &sbi->compressed);
-+ axfs_free_region(sbi, &sbi->byte_aligned);
-+ axfs_free_region(sbi, &sbi->node_type);
-+ axfs_free_region(sbi, &sbi->node_index);
-+ axfs_free_region(sbi, &sbi->cnode_offset);
-+ axfs_free_region(sbi, &sbi->cnode_index);
-+ axfs_free_region(sbi, &sbi->banode_offset);
-+ axfs_free_region(sbi, &sbi->cblock_offset);
-+ axfs_free_region(sbi, &sbi->inode_file_size);
-+ axfs_free_region(sbi, &sbi->inode_name_offset);
-+ axfs_free_region(sbi, &sbi->inode_num_entries);
-+ axfs_free_region(sbi, &sbi->inode_mode_index);
-+ axfs_free_region(sbi, &sbi->inode_array_index);
-+ axfs_free_region(sbi, &sbi->modes);
-+ axfs_free_region(sbi, &sbi->uids);
-+ axfs_free_region(sbi, &sbi->gids);
-+
-+ kfree(sbi->second_dev);
-+ vfree(sbi->cblock_buffer[0]);
-+ vfree(sbi->cblock_buffer[1]);
-+ kfree(sbi);
-+}
-+
-+static void axfs_put_super(struct super_block *sb)
-+{
-+ axfs_unmap_mtd(sb);
-+ axfs_put_sbi(AXFS_SB(sb));
-+
-+#ifndef NO_PHYSMEM
-+ axfs_unmap_physmem(sb);
-+#endif
-+ sb->s_fs_info = NULL;
-+}
-+
-+static void axfs_copy_mem(struct super_block *sb, void *buf, u64 fsoffset,
-+ u64 len)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ unsigned long addr;
-+
-+ addr = sbi->virt_start_addr + (unsigned long)fsoffset;
-+
-+ memcpy(buf, (void *)addr, (size_t) len);
-+}
-+
-+static int axfs_copy_metadata(struct super_block *sb, void *buf, u64 fsoffset,
-+ u64 len)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ u64 end = fsoffset + len;
-+ u64 a = sbi->mmap_size - fsoffset;
-+ u64 b = end - sbi->mmap_size;
-+ void *bb = (void *)((unsigned long)buf + (unsigned long)a);
-+ int err = 0;
-+
-+ /* Catches case where sbi is not yet fully initialized. */
-+ if ((sbi->magic == 0) && (sbi->virt_start_addr != 0)) {
-+ axfs_copy_mem(sb, buf, fsoffset, len);
-+ return 0;
-+ }
-+
-+ if (fsoffset < sbi->mmap_size) {
-+ if (end > sbi->mmap_size) {
-+ err = axfs_copy_metadata(sb, buf, fsoffset, a);
-+ if (err)
-+ return err;
-+ err = axfs_copy_metadata(sb, bb, sbi->mmap_size, b);
-+ } else {
-+ if (axfs_is_offset_mmapable(sbi, fsoffset))
-+ axfs_copy_mem(sb, buf, fsoffset, len);
-+ else if (axfs_has_bdev(sb))
-+ axfs_copy_block(sb, buf, fsoffset, len);
-+ else if (axfs_has_mtd(sb))
-+ err = axfs_copy_mtd(sb, buf, fsoffset, len);
-+ }
-+ } else {
-+ if (axfs_nodev(sb))
-+ axfs_copy_mem(sb, buf, fsoffset, len);
-+ else if (axfs_has_bdev(sb))
-+ axfs_copy_block(sb, buf, fsoffset, len);
-+ else if (axfs_has_mtd(sb))
-+ err = axfs_copy_mtd(sb, buf, fsoffset, len);
-+ }
-+ return err;
-+}
-+
-+static int axfs_fill_region_data(struct super_block *sb,
-+ struct axfs_region_desc *region, int force)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ unsigned long addr;
-+ void *buff = NULL;
-+ void *vaddr;
-+ int err = -ENOMEM;
-+ u64 size = region->size;
-+ u64 fsoffset = region->fsoffset;
-+ u64 end = fsoffset + size;
-+ u64 c_size = region->compressed_size;
-+
-+ if (size == 0)
-+ return 0;
-+
-+ if (axfs_is_region_incore(region))
-+ goto incore;
-+
-+ if (axfs_is_region_compressed(region))
-+ goto incore;
-+
-+ if (axfs_is_region_xip(sbi, region)) {
-+ if ((end > sbi->mmap_size) && (force))
-+ goto incore;
-+ addr = sbi->virt_start_addr;
-+ addr += (unsigned long)fsoffset;
-+ region->virt_addr = (void *)addr;
-+ return 0;
-+ }
-+
-+ if (force)
-+ goto incore;
-+
-+ region->virt_addr = NULL;
-+ return 0;
-+
-+incore:
-+ region->virt_addr = vmalloc(size);
-+ if (!region->virt_addr)
-+ goto out;
-+ vaddr = region->virt_addr;
-+
-+ if (axfs_is_region_compressed(region)) {
-+ buff = vmalloc(c_size);
-+ if (!buff)
-+ goto out;
-+ axfs_copy_metadata(sb, buff, fsoffset, c_size);
-+ err = axfs_uncompress_block(vaddr, size, buff, c_size);
-+ if (!err)
-+ goto out;
-+ vfree(buff);
-+ } else {
-+ axfs_copy_metadata(sb, vaddr, fsoffset, size);
-+ }
-+
-+ return 0;
-+
-+out:
-+ vfree(buff);
-+ vfree(region->virt_addr);
-+ return err;
-+}
-+
-+static int axfs_fill_region_data_ptrs(struct super_block *sb)
-+{
-+ int err;
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+
-+ err = axfs_fill_region_data(sb, &sbi->strings, true);
-+ if (err)
-+ goto out;
-+
-+ err = axfs_fill_region_data(sb, &sbi->xip, true);
-+ if (err)
-+ goto out;
-+
-+ err = axfs_fill_region_data(sb, &sbi->compressed, false);
-+ if (err)
-+ goto out;
-+
-+ err = axfs_fill_region_data(sb, &sbi->byte_aligned, false);
-+ if (err)
-+ goto out;
-+
-+ err = axfs_fill_region_data(sb, &sbi->node_type, true);
-+ if (err)
-+ goto out;
-+ err = axfs_fill_region_data(sb, &sbi->node_index, true);
-+ if (err)
-+ goto out;
-+ err = axfs_fill_region_data(sb, &sbi->cnode_offset, true);
-+ if (err)
-+ goto out;
-+ err = axfs_fill_region_data(sb, &sbi->cnode_index, true);
-+ if (err)
-+ goto out;
-+ err = axfs_fill_region_data(sb, &sbi->banode_offset, true);
-+ if (err)
-+ goto out;
-+ err = axfs_fill_region_data(sb, &sbi->cblock_offset, true);
-+ if (err)
-+ goto out;
-+ err = axfs_fill_region_data(sb, &sbi->inode_file_size, true);
-+ if (err)
-+ goto out;
-+ err = axfs_fill_region_data(sb, &sbi->inode_name_offset, true);
-+ if (err)
-+ goto out;
-+ err = axfs_fill_region_data(sb, &sbi->inode_num_entries, true);
-+ if (err)
-+ goto out;
-+ err = axfs_fill_region_data(sb, &sbi->inode_mode_index, true);
-+ if (err)
-+ goto out;
-+ err = axfs_fill_region_data(sb, &sbi->inode_array_index, true);
-+ if (err)
-+ goto out;
-+ err = axfs_fill_region_data(sb, &sbi->modes, true);
-+ if (err)
-+ goto out;
-+ err = axfs_fill_region_data(sb, &sbi->uids, true);
-+ if (err)
-+ goto out;
-+ err = axfs_fill_region_data(sb, &sbi->gids, true);
-+ if (err)
-+ goto out;
-+
-+out:
-+ return err;
-+}
-+
-+static int axfs_init_cblock_buffers(struct axfs_super *sbi)
-+{
-+ sbi->current_cnode_index = -1;
-+ sbi->cblock_buffer[0] = vmalloc(sbi->cblock_size);
-+ sbi->cblock_buffer[1] = vmalloc(sbi->cblock_size);
-+ if ((!sbi->cblock_buffer[0]) || (!sbi->cblock_buffer[1]))
-+ return -ENOMEM;
-+
-+ return 0;
-+}
-+
-+static int axfs_fixup_devices(struct super_block *sb)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ int err = 0;
-+
-+#ifndef NO_PHYSMEM
-+ if (axfs_is_physmem(sbi)) {
-+ axfs_map_physmem(sbi, sbi->mmap_size);
-+ } else if (axfs_has_mtd(sb)) {
-+#else
-+ if (axfs_has_mtd(sb)) {
-+#endif
-+ err = axfs_map_mtd(sb);
-+ } else if (axfs_is_iomem(sbi)) {
-+ sbi->phys_start_addr = 0;
-+ }
-+
-+ if (!(axfs_virtaddr_is_valid(sbi)))
-+ sbi->mmap_size = 0;
-+
-+ return err;
-+}
-+
-+static void axfs_fill_region_desc(struct super_block *sb,
-+ struct axfs_region_desc_onmedia *out,
-+ __be64 offset_be, struct axfs_region_desc *in)
-+{
-+ u64 offset = be64_to_cpu(offset_be);
-+
-+ axfs_copy_metadata(sb, (void *)out, offset, sizeof(*out));
-+
-+ in->fsoffset = be64_to_cpu(out->fsoffset);
-+ in->size = be64_to_cpu(out->size);
-+ in->compressed_size = be64_to_cpu(out->compressed_size);
-+ in->max_index = be64_to_cpu(out->max_index);
-+ in->table_byte_depth = out->table_byte_depth;
-+ in->incore = out->incore;
-+}
-+
-+static int axfs_fill_region_descriptors(struct super_block *sb,
-+ struct axfs_super_onmedia *sbo)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ struct axfs_region_desc_onmedia *out;
-+
-+ out = kzalloc(sizeof(*out), GFP_KERNEL);
-+ if (!out)
-+ return -ENOMEM;
-+
-+ axfs_fill_region_desc(sb, out, sbo->strings, &sbi->strings);
-+ axfs_fill_region_desc(sb, out, sbo->xip, &sbi->xip);
-+ axfs_fill_region_desc(sb, out, sbo->compressed, &sbi->compressed);
-+ axfs_fill_region_desc(sb, out, sbo->byte_aligned, &sbi->byte_aligned);
-+ axfs_fill_region_desc(sb, out, sbo->node_type, &sbi->node_type);
-+ axfs_fill_region_desc(sb, out, sbo->node_index, &sbi->node_index);
-+ axfs_fill_region_desc(sb, out, sbo->cnode_offset, &sbi->cnode_offset);
-+ axfs_fill_region_desc(sb, out, sbo->cnode_index, &sbi->cnode_index);
-+ axfs_fill_region_desc(sb, out, sbo->banode_offset, &sbi->banode_offset);
-+ axfs_fill_region_desc(sb, out, sbo->cblock_offset, &sbi->cblock_offset);
-+ axfs_fill_region_desc(sb, out, sbo->inode_file_size,
-+ &sbi->inode_file_size);
-+ axfs_fill_region_desc(sb, out, sbo->inode_name_offset,
-+ &sbi->inode_name_offset);
-+ axfs_fill_region_desc(sb, out, sbo->inode_num_entries,
-+ &sbi->inode_num_entries);
-+ axfs_fill_region_desc(sb, out, sbo->inode_mode_index,
-+ &sbi->inode_mode_index);
-+ axfs_fill_region_desc(sb, out, sbo->inode_array_index,
-+ &sbi->inode_array_index);
-+ axfs_fill_region_desc(sb, out, sbo->modes, &sbi->modes);
-+ axfs_fill_region_desc(sb, out, sbo->uids, &sbi->uids);
-+ axfs_fill_region_desc(sb, out, sbo->gids, &sbi->gids);
-+
-+ kfree(out);
-+
-+ return 0;
-+}
-+
-+static int axfs_check_page_shift(struct axfs_super *sbi)
-+{
-+ if (sbi->page_shift != PAGE_SHIFT) {
-+ printk(KERN_ERR "axfs: Filesystem is AXFS, however "
-+ "the page size does not match that\n"
-+ "of the system. Cowardly refusing "
-+ "to mount.\n");
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static int axfs_check_compression_type(struct axfs_super *sbi)
-+{
-+ if (sbi->compression_type != ZLIB) {
-+ printk(KERN_ERR "axfs: Unknown compression type "
-+ "specified in super block.\n");
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static int axfs_get_onmedia_super(struct super_block *sb)
-+{
-+ int err;
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ struct axfs_super_onmedia *sbo;
-+
-+ sbo = kmalloc(sizeof(*sbo), GFP_KERNEL);
-+ if (!sbo)
-+ return -ENOMEM;
-+
-+#ifndef NO_PHYSMEM
-+ axfs_map_physmem(sbi, sizeof(*sbo));
-+#endif
-+ axfs_copy_metadata(sb, (void *)sbo, 0, sizeof(*sbo));
-+
-+ /* Do sanity checks on the superblock */
-+ if (be32_to_cpu(sbo->magic) != AXFS_MAGIC) {
-+ printk(KERN_ERR "axfs: wrong magic: got %x, expected %x\n",
-+ be32_to_cpu(sbo->magic), AXFS_MAGIC);
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ /* verify the signiture is correct */
-+ if (strncmp(sbo->signature, AXFS_SIGNATURE, sizeof(AXFS_SIGNATURE))) {
-+ printk(KERN_ERR "axfs: wrong signature: "
-+ "got '%s', expected '%s'\n",
-+ sbo->signature, AXFS_SIGNATURE);
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ sbi->magic = be32_to_cpu(sbo->magic);
-+ sbi->version_major = sbo->version_major;
-+ sbi->version_minor = sbo->version_minor;
-+ sbi->version_sub = sbo->version_sub;
-+ sbi->files = be64_to_cpu(sbo->files);
-+ sbi->size = be64_to_cpu(sbo->size);
-+ sbi->blocks = be64_to_cpu(sbo->blocks);
-+ sbi->mmap_size = be64_to_cpu(sbo->mmap_size);
-+ sbi->cblock_size = be32_to_cpu(sbo->cblock_size);
-+ sbi->timestamp.tv_sec = be64_to_cpu(sbo->timestamp);
-+ sbi->timestamp.tv_nsec = 0;
-+ sbi->compression_type = sbo->compression_type;
-+ sbi->page_shift = sbo->page_shift;
-+
-+ err = axfs_check_page_shift(sbi);
-+ if (err)
-+ goto out;
-+
-+ err = axfs_check_compression_type(sbi);
-+ if (err)
-+ goto out;
-+
-+ /* If no block or MTD device, adjust mmapable to cover all image */
-+ if (axfs_nodev(sb))
-+ sbi->mmap_size = sbi->size;
-+
-+ err = axfs_fill_region_descriptors(sb, sbo);
-+
-+out:
-+ kfree(sbo);
-+#ifndef NO_PHYSMEM
-+ axfs_unmap_physmem(sb);
-+#endif
-+ return err;
-+}
-+
-+u64 axfs_get_io_dev_size(struct super_block *sb)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ return sbi->size - sbi->mmap_size;
-+}
-+
-+/*
-+ * Verify that the size of the IO segment of a split filesystem
-+ * is less than or equal to that of the device containing it.
-+ */
-+static int axfs_verify_device_sizes(struct super_block *sb)
-+{
-+ int err;
-+
-+ if (axfs_verify_bdev_sizes(sb, &err))
-+ goto out;
-+
-+ if (axfs_verify_mtd_sizes(sb, &err))
-+ goto out;
-+
-+out:
-+ return err;
-+}
-+
-+/*
-+ * Read the last four bytes of the volume and make sure the
-+ * AXFS magic is present.
-+ */
-+static int axfs_verify_eofs_magic(struct super_block *sb)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ u32 eof_magic;
-+ u64 fsoffset = sbi->size - sizeof(eof_magic);
-+
-+ if (axfs_copy_metadata(sb, &eof_magic, fsoffset, sizeof(eof_magic)))
-+ return -EINVAL;
-+
-+ if (be32_to_cpu(eof_magic) == AXFS_MAGIC)
-+ return 0;
-+
-+ printk(KERN_ERR "axfs: bad magic at end of image: got %x expected %x\n",
-+ be32_to_cpu(eof_magic), AXFS_MAGIC);
-+ return -EINVAL;
-+}
-+
-+static int axfs_do_fill_super(struct super_block *sb)
-+{
-+ struct axfs_super *sbi = AXFS_SB(sb);
-+ int err;
-+
-+ err = axfs_get_onmedia_super(sb);
-+ if (err)
-+ goto out;
-+
-+ err = axfs_fixup_devices(sb);
-+ if (err)
-+ goto out;
-+
-+ err = axfs_verify_device_sizes(sb);
-+ if (err)
-+ goto out;
-+
-+ err = axfs_verify_eofs_magic(sb);
-+ if (err)
-+ goto out;
-+
-+ err = axfs_fill_region_data_ptrs(sb);
-+ if (err)
-+ goto out;
-+
-+ /* Check that the root inode is in a sane state */
-+ if (!S_ISDIR(axfs_get_mode(sbi, 0))) {
-+ printk(KERN_ERR "axfs: root is not a directory\n");
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ if (axfs_get_inode_num_entries(sbi, 0) == 0) {
-+ printk(KERN_INFO "axfs: empty filesystem\n");
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ err = axfs_init_cblock_buffers(sbi);
-+ if (err)
-+ goto out;
-+
-+ init_rwsem(&sbi->lock);
-+
-+ return 0;
-+
-+out:
-+ return err;
-+}
-+
-+int axfs_fill_super(struct super_block *sb, void *data, int silent)
-+{
-+ struct axfs_super *sbi;
-+ struct inode *root;
-+ int err;
-+ struct axfs_super *sbi_in = (struct axfs_super *)data;
-+
-+ sbi = axfs_get_sbi();
-+ if (IS_ERR(sbi))
-+ return PTR_ERR(sbi);
-+
-+ sb->s_fs_info = (void *)sbi;
-+
-+ memcpy(sbi, sbi_in, sizeof(*sbi));
-+
-+ /* fully populate the incore superblock structures */
-+ err = axfs_do_fill_super(sb);
-+ if (err)
-+ goto out;
-+
-+ sb->s_flags |= MS_RDONLY;
-+
-+ /* Setup the VFS super block now */
-+ sb->s_op = &axfs_sops;
-+ root = axfs_create_vfs_inode(sb, 0);
-+ if (!root) {
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ sb->s_root = d_make_root(root);
-+ if (!sb->s_root) {
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ err = axfs_init_profiling(sbi);
-+ if (err)
-+ goto out;
-+
-+ if (axfs_has_mtd(sb))
-+ sbi->mtd0 = axfs_mtd(sb);
-+ return 0;
-+
-+out:
-+ axfs_put_super(sb);
-+ return err;
-+}
-+
-+static struct dentry *
-+axfs_get_sb_address(struct file_system_type *fs_type,
-+ int flags, struct axfs_super *sbi)
-+{
-+ int mtdnr;
-+ char *sd = sbi->second_dev;
-+
-+ if (sbi->phys_start_addr == 0)
-+ return false;
-+
-+ if (sbi->phys_start_addr & (PAGE_SIZE - 1)) {
-+ printk(KERN_ERR
-+ "axfs: address 0x%lx for axfs image isn't aligned "
-+ "to a page boundary\n", sbi->phys_start_addr);
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ if (axfs_is_dev_mtd(sd, &mtdnr))
-+ return axfs_get_sb_mtd(fs_type, flags, sd, sbi);
-+ else if (axfs_is_dev_bdev(sd))
-+ return axfs_get_sb_bdev(fs_type, flags, sd, sbi);
-+ else
-+ return mount_nodev(fs_type, flags, sbi, axfs_fill_super);
-+
-+}
-+
-+/* helpers for parse_axfs_options */
-+enum {
-+ OPTION_ERR,
-+ OPTION_SECOND_DEV,
-+ OPTION_PHYSICAL_ADDRESS_LOWER_X,
-+ OPTION_PHYSICAL_ADDRESS_UPPER_X,
-+ OPTION_IOMEM
-+};
-+
-+/* helpers for parse_axfs_options */
-+static match_table_t tokens = {
-+ {OPTION_SECOND_DEV, "second_dev=%s"},
-+ {OPTION_PHYSICAL_ADDRESS_LOWER_X, "physaddr=0x%s"},
-+ {OPTION_PHYSICAL_ADDRESS_UPPER_X, "physaddr=0X%s"},
-+ {OPTION_IOMEM, "iomem=%s"},
-+ {OPTION_ERR, NULL}
-+};
-+
-+static int axfs_check_options(char *options, struct axfs_super *sbi)
-+{
-+ int err = -EINVAL;
-+ unsigned long address = 0;
-+ char *iomem = NULL;
-+ unsigned long length = 0;
-+ char *p;
-+ substring_t args[MAX_OPT_ARGS];
-+
-+ if (!options)
-+ return 0;
-+
-+ if (!*options)
-+ return 0;
-+
-+ while ((p = strsep(&options, ",")) != NULL) {
-+ int token;
-+ if (!*p)
-+ continue;
-+
-+ token = match_token(p, tokens, args);
-+ switch (token) {
-+ case OPTION_SECOND_DEV:
-+ sbi->second_dev = match_strdup(&args[0]);
-+ if (!(sbi->second_dev)) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+ if (!*(sbi->second_dev))
-+ goto bad_value;
-+ break;
-+ case OPTION_IOMEM:
-+ iomem = match_strdup(&args[0]);
-+ if (!(iomem)) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+ if (!*iomem)
-+ goto bad_value;
-+ break;
-+ case OPTION_PHYSICAL_ADDRESS_LOWER_X:
-+ case OPTION_PHYSICAL_ADDRESS_UPPER_X:
-+ if (match_hex(&args[0], (int *)&address))
-+ goto out;
-+ if (!address)
-+ goto bad_value;
-+ break;
-+ default:
-+ printk(KERN_ERR
-+ "axfs: unrecognized mount option '%s' "
-+ "or missing value\n", p);
-+ goto out;
-+ }
-+ }
-+
-+ if (iomem) {
-+ if (address)
-+ goto out;
-+ err = axfs_get_uml_address(iomem, &address, &length);
-+ kfree(iomem);
-+ sbi->iomem_size = length;
-+ sbi->virt_start_addr = address;
-+ }
-+
-+ sbi->phys_start_addr = address;
-+ return 0;
-+
-+bad_value:
-+ printk(KERN_ERR
-+ "axfs: unrecognized mount option '%s' "
-+ "or missing value\n", p);
-+
-+out:
-+ kfree(iomem);
-+ return err;
-+}
-+
-+struct dentry *axfs_get_sb(struct file_system_type *fs_type, int flags,
-+ const char *dev_name, void *data)
-+{
-+ struct axfs_super *sbi;
-+ int err;
-+ struct dentry *ret = ERR_PTR(-EINVAL);
-+
-+ sbi = axfs_get_sbi();
-+ if (IS_ERR(sbi))
-+ return ret;
-+
-+ err = axfs_check_options((char *)data, sbi);
-+ if (err)
-+ goto out;
-+
-+ /* First we check if we are mounting directly to memory */
-+ ret = axfs_get_sb_address(fs_type, flags, sbi);
-+ if (!(IS_ERR_OR_NULL(ret)))
-+ goto out;
-+
-+ /* Next we assume there's a MTD device */
-+ ret = axfs_get_sb_mtd(fs_type, flags, dev_name, sbi);
-+ if (!(IS_ERR_OR_NULL(ret)))
-+ goto out;
-+
-+ /* Now we assume it's a block device */
-+ if (sbi->second_dev) {
-+ printk(KERN_ERR
-+ "axfs: can't specify secondary block device %s because "
-+ "%s is assumed to be a block device\n", sbi->second_dev,
-+ dev_name);
-+ err = -EINVAL;
-+ goto out;
-+ }
-+ ret = axfs_get_sb_bdev(fs_type, flags, dev_name, sbi);
-+ if (!(IS_ERR_OR_NULL(ret)))
-+ goto out;
-+ err = -EINVAL;
-+
-+out:
-+ axfs_put_sbi(sbi);
-+ return ret;
-+}
-+
-+static void axfs_kill_super(struct super_block *sb)
-+{
-+ if (axfs_nodev(sb))
-+ return kill_anon_super(sb);
-+
-+ if (axfs_has_mtd(sb))
-+ axfs_kill_mtd_super(sb);
-+
-+ if (axfs_has_bdev(sb))
-+ axfs_kill_block_super(sb);
-+}
-+
-+static int axfs_remount(struct super_block *sb, int *flags, char *data)
-+{
-+ *flags |= MS_RDONLY;
-+ return 0;
-+}
-+
-+static int axfs_statfs(struct dentry *dentry, struct kstatfs *buf)
-+{
-+ struct axfs_super *sbi = AXFS_SB(dentry->d_sb);
-+
-+ buf->f_type = AXFS_MAGIC;
-+ buf->f_bsize = (1 << sbi->page_shift);
-+ buf->f_blocks = sbi->blocks;
-+ buf->f_bfree = 0;
-+ buf->f_bavail = 0;
-+ buf->f_files = sbi->files;
-+ buf->f_ffree = 0;
-+ buf->f_namelen = AXFS_MAXPATHLEN;
-+ return 0;
-+}
-+
-+static struct super_operations axfs_sops = {
-+ .put_super = axfs_put_super,
-+ .remount_fs = axfs_remount,
-+ .statfs = axfs_statfs,
-+};
-+
-+static struct file_system_type axfs_fs_type = {
-+ .owner = THIS_MODULE,
-+ .name = "axfs",
-+ .mount = axfs_get_sb,
-+ .kill_sb = axfs_kill_super,
-+};
-+
-+static int __init init_axfs_fs(void)
-+{
-+ int err;
-+
-+ err = axfs_uncompress_init();
-+ if (err)
-+ return err;
-+
-+ err = register_filesystem(&axfs_fs_type);
-+
-+ if (!err)
-+ return 0;
-+
-+ axfs_uncompress_exit();
-+ return err;
-+}
-+
-+static void __exit exit_axfs_fs(void)
-+{
-+ axfs_uncompress_exit();
-+ unregister_filesystem(&axfs_fs_type);
-+}
-+
-+module_init(init_axfs_fs);
-+module_exit(exit_axfs_fs);
-+MODULE_LICENSE("GPL");
+++ /dev/null
-From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:46:32 2012
-From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Date: Fri, 23 Nov 2012 17:10:49 +0530
-Subject: [PATCH v2 RESEND 10/15] AXFS: axfs_uml.c
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
-Message-ID: <50AF60C1.5050301@ap.sony.com>
-
-
-From: Jared Hulbert <jaredeh@gmail.com>
-
-Allows axfs in a UML kernel to use find_iomem() interface for the XIP device
-or dummy functions if this is not a UML build.
-
-Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
----
- fs/axfs/axfs_uml.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 47 insertions(+)
- create mode 100644 fs/axfs/axfs_uml.c
-
---- /dev/null
-+++ b/fs/axfs/axfs_uml.c
-@@ -0,0 +1,47 @@
-+/*
-+ * Advanced XIP File System for Linux - AXFS
-+ * Readonly, compressed, and XIP filesystem for Linux systems big and small
-+ *
-+ * Copyright(c) 2008 Numonyx
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * Authors:
-+ * Jared Hulbert <jaredeh@gmail.com>
-+ *
-+ * Project url: http://axfs.sourceforge.net
-+ *
-+ * axfs_uml.c -
-+ * Allows axfs to a UML kernels find_iomem() interface as an XIP device or
-+ * dummy functions if this is not a UML build.
-+ */
-+#include "axfs.h"
-+
-+#ifdef CONFIG_UML
-+#include <mem_user.h>
-+int axfs_get_uml_address(char *iomem, unsigned long *address,
-+ unsigned long *length)
-+{
-+ *address = find_iomem(iomem, length);
-+ if (!(*address)) {
-+ printk(KERN_DEBUG "axfs: find_iomem() failed\n");
-+ return -EINVAL;
-+ }
-+
-+ if (*length < PAGE_SIZE) {
-+ printk(KERN_DEBUG
-+ "axfs: iomem() too small, must be at least %li Bytes\n",
-+ PAGE_SIZE);
-+ return -EINVAL;
-+ }
-+ return 0;
-+}
-+#else
-+int axfs_get_uml_address(char *iomem, unsigned long *address,
-+ unsigned long *length)
-+{
-+ return 0;
-+}
-+#endif /* CONFIG_UML */
+++ /dev/null
-From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:47:49 2012
-From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Date: Fri, 23 Nov 2012 17:12:07 +0530
-Subject: [PATCH v2 RESEND 11/15] AXFS: axfs_uncompress.c
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
-Message-ID: <50AF610F.3000208@ap.sony.com>
-
-
-From: Jared Hulbert <jaredeh@gmail.com>
-
-AXFS interfaces to the uncompression library
-
-Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
----
- fs/axfs/axfs_uncompress.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 90 insertions(+)
- create mode 100644 fs/axfs/axfs_uncompress.c
-
---- /dev/null
-+++ b/fs/axfs/axfs_uncompress.c
-@@ -0,0 +1,90 @@
-+/*
-+ * Advanced XIP File System for Linux - AXFS
-+ * Readonly, compressed, and XIP filesystem for Linux systems big and small
-+ *
-+ * Modified in 2006 by Eric Anderson
-+ * from the cramfs sources fs/cramfs/uncompress.c
-+ *
-+ * (C) Copyright 1999 Linus Torvalds
-+ *
-+ * axfs_uncompress.c -
-+ * axfs interfaces to the uncompression library. There's really just
-+ * three entrypoints:
-+ *
-+ * - axfs_uncompress_init() - called to initialize the thing.
-+ * - axfs_uncompress_exit() - tell me when you're done
-+ * - axfs_uncompress_block() - uncompress a block.
-+ *
-+ * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We
-+ * only have one stream, and we'll initialize it only once even if it
-+ * then is used by multiple filesystems.
-+ *
-+ */
-+
-+#include <linux/errno.h>
-+#include <linux/vmalloc.h>
-+#include <linux/zlib.h>
-+#include <linux/init.h>
-+#include <linux/mutex.h>
-+
-+static z_stream stream;
-+static DEFINE_MUTEX(axfs_uncmp_mutex);
-+
-+int axfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
-+{
-+ int err;
-+ int out;
-+
-+ mutex_lock(&axfs_uncmp_mutex);
-+
-+ stream.next_in = src;
-+ stream.avail_in = srclen;
-+
-+ stream.next_out = dst;
-+ stream.avail_out = dstlen;
-+
-+ err = zlib_inflateReset(&stream);
-+ if (err != Z_OK) {
-+ printk(KERN_ERR "axfs: zlib_inflateReset error %d\n", err);
-+ zlib_inflateEnd(&stream);
-+ zlib_inflateInit(&stream);
-+ }
-+
-+ err = zlib_inflate(&stream, Z_FINISH);
-+ if (err != Z_STREAM_END)
-+ goto err;
-+
-+ out = stream.total_out;
-+
-+ mutex_unlock(&axfs_uncmp_mutex);
-+
-+ return out;
-+
-+err:
-+
-+ mutex_unlock(&axfs_uncmp_mutex);
-+
-+ printk(KERN_ERR "axfs: error %d while decompressing!\n", err);
-+ printk(KERN_ERR "%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
-+ return 0;
-+}
-+
-+int __init axfs_uncompress_init(void)
-+{
-+
-+ stream.workspace = vmalloc(zlib_inflate_workspacesize());
-+ if (!stream.workspace)
-+ return -ENOMEM;
-+ stream.next_in = NULL;
-+ stream.avail_in = 0;
-+ zlib_inflateInit(&stream);
-+
-+ return 0;
-+}
-+
-+int axfs_uncompress_exit(void)
-+{
-+ zlib_inflateEnd(&stream);
-+ vfree(stream.workspace);
-+ return 0;
-+}
+++ /dev/null
-From aaditya.kumar.30@gmail.com Fri Dec 21 15:46:49 2012
-From: Aaditya Kumar <aaditya.kumar.30@gmail.com>
-Date: Sat, 22 Dec 2012 05:16:48 +0530
-Subject: AXFS: fix build failure due to undefined symbol axfs_xip_record()
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: ltsi-dev@lists.linuxfoundation.org, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Message-ID: <CAEtiSavV8fDKpY+5krVPqoMwGwB6C20rLa5Cz-gqWqJj2+rryA@mail.gmail.com>
-Status: RO
-X-Status: A
-Content-Length: 1955
-Lines: 72
-
-
-This patch fixes following build failure when axfs is compiled
-as a module. The build failure is caused by
-Commit-ID: a7e526129f6ea298513ef4ce7aa6db08fc069d14
-
-ERROR: "axfs_xip_record" [fs/axfs/axfs.ko] undefined!
-
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-
-
----
- fs/axfs/Makefile | 3 +--
- fs/axfs/axfs.h | 2 ++
- fs/axfs/axfs_super.c | 4 +++-
- fs/axfs/axfs_xip_profile.c | 9 ++++++---
- 4 files changed, 12 insertions(+), 6 deletions(-)
-
---- a/fs/axfs/Makefile
-+++ b/fs/axfs/Makefile
-@@ -5,6 +5,5 @@
- obj-$(CONFIG_AXFS) += axfs.o
-
- axfs-y := axfs_inode.o axfs_super.o axfs_uncompress.o axfs_profiling.o \
-- axfs_uml.o axfs_mtd.o axfs_bdev.o axfs_physmem.o
-+ axfs_uml.o axfs_mtd.o axfs_bdev.o axfs_physmem.o axfs_xip_profile.o
-
--obj-$(CONFIG_AXFS_DEBUG) += axfs_xip_profile.o
---- a/fs/axfs/axfs.h
-+++ b/fs/axfs/axfs.h
-@@ -93,4 +93,6 @@ void axfs_map_physmem(struct axfs_super
- void axfs_unmap_physmem(struct super_block *);
- #endif
-
-+/* axfs_xip_profile.c */
-+extern int __init axfs_xip_proc_profile(void);
- #endif
---- a/fs/axfs/axfs_super.c
-+++ b/fs/axfs/axfs_super.c
-@@ -975,8 +975,10 @@ static int __init init_axfs_fs(void)
-
- err = register_filesystem(&axfs_fs_type);
-
-- if (!err)
-+ if (!err) {
-+ axfs_xip_proc_profile();
- return 0;
-+ }
-
- axfs_uncompress_exit();
- return err;
---- a/fs/axfs/axfs_xip_profile.c
-+++ b/fs/axfs/axfs_xip_profile.c
-@@ -137,7 +137,7 @@ static int axfs_xip_proc_write(struct fi
- return count;
- }
-
--static int __init axfs_xip_proc_profile(void)
-+int __init axfs_xip_proc_profile(void)
- {
- struct proc_dir_entry *ent;
- ent = create_proc_entry("axfs_xip", S_IFREG|S_IRUGO|S_IWUSR, NULL);
-@@ -149,6 +149,9 @@ static int __init axfs_xip_proc_profile(
- ent->write_proc = axfs_xip_proc_write;
- return 0;
- }
--late_initcall(axfs_xip_proc_profile);
--
-+#else
-+int __init axfs_xip_proc_profile(void)
-+{
-+ return 0;
-+}
- #endif /* CONFIG_AXFS_DEBUG */
+++ /dev/null
-From aaditya.kumar.30@gmail.com Fri Dec 21 15:43:41 2012
-From: Aaditya Kumar <aaditya.kumar.30@gmail.com>
-Date: Sat, 22 Dec 2012 05:13:40 +0530
-Subject: AXFS: fix build failure due to undefined symbol kern_path_parent()
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: ltsi-dev@lists.linuxfoundation.org, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Message-ID: <CAEtiSasvwemeCYkjeagSPb-chs=cDeNeH1jJqVRxW0qnomij8Q@mail.gmail.com>
-
-
-This patch fixes following build failure when axfs is compiled
-as a module. The build failure is caused by
-Commit-ID: a7e526129f6ea298513ef4ce7aa6db08fc069d14
-
-ERROR: "kern_path_parent" [fs/axfs/axfs.ko] undefined!
-
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-
----
-Changes from v2:
-- Address checkpatch.pl errors.
-
-Changes from v1:
-- AXFS should not be using kernel_path() or kenel_path_parent() and
- actually there is no need for these functions, we can do without these
- functions also, so change the mounting code to not use it.
-
----
- fs/axfs/axfs_bdev.c | 18 ------------------
- fs/axfs/axfs_super.c | 10 ++++++----
- 2 files changed, 6 insertions(+), 22 deletions(-)
-
---- a/fs/axfs/axfs_bdev.c
-+++ b/fs/axfs/axfs_bdev.c
-@@ -94,24 +94,6 @@ void axfs_copy_block(struct super_block
- }
- }
-
--int axfs_is_dev_bdev(char *path)
--{
-- struct nameidata nd;
-- int ret = false;
--
-- if (!path)
-- return false;
-- nd.flags |= LOOKUP_FOLLOW;
-- if (kern_path_parent(path, &nd))
-- return false;
--
-- if (S_ISBLK(nd.path.dentry->d_inode->i_mode))
-- ret = true;
--
-- path_put(&nd.path);
-- return ret;
--}
--
- int axfs_verify_bdev_sizes(struct super_block *sb, int *err)
- {
- u64 io_dev_size;
---- a/fs/axfs/axfs_super.c
-+++ b/fs/axfs/axfs_super.c
-@@ -754,6 +754,7 @@ axfs_get_sb_address(struct file_system_t
- {
- int mtdnr;
- char *sd = sbi->second_dev;
-+ struct dentry *dp = NULL;
-
- if (sbi->phys_start_addr == 0)
- return false;
-@@ -767,11 +768,12 @@ axfs_get_sb_address(struct file_system_t
-
- if (axfs_is_dev_mtd(sd, &mtdnr))
- return axfs_get_sb_mtd(fs_type, flags, sd, sbi);
-- else if (axfs_is_dev_bdev(sd))
-- return axfs_get_sb_bdev(fs_type, flags, sd, sbi);
-- else
-- return mount_nodev(fs_type, flags, sbi, axfs_fill_super);
-
-+ dp = axfs_get_sb_bdev(fs_type, flags, sd, sbi);
-+ if (!IS_ERR_OR_NULL(dp))
-+ return dp;
-+
-+ return mount_nodev(fs_type, flags, sbi, axfs_fill_super);
- }
-
- /* helpers for parse_axfs_options */
+++ /dev/null
-From aaditya.kumar.30@gmail.com Fri Dec 21 15:55:12 2012
-From: Aaditya Kumar <aaditya.kumar.30@gmail.com>
-Date: Sat, 22 Dec 2012 05:25:10 +0530
-Subject: AXFS: fix type cast warning in axfs_region_is_vmalloc()
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: ltsi-dev@lists.linuxfoundation.org, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Message-ID: <CAEtiSasb7hLcp63zjRg2gQAmYgKE-F8rKwu==T=jQAxCYQWSbQ@mail.gmail.com>
-
-
-This patch fixes following compilation warning caused by
-Commit-ID: a7e526129f6ea298513ef4ce7aa6db08fc069d14
-
-fs/axfs/axfs_inode.c: In function \91axfs_region_is_vmalloc\92:
-fs/axfs/axfs_inode.c:175:11: warning: cast from pointer to integer of\r
-different size [-Wpointer-to-int-cast]\r
-
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>\r
----\r
-Changes from v1:\r
- - Use unsigned long type cast.\r
-
----\r
- fs/axfs/axfs_inode.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/fs/axfs/axfs_inode.c
-+++ b/fs/axfs/axfs_inode.c
-@@ -172,7 +172,7 @@ static inline u64 axfs_get_xip_region_ph
- static inline int axfs_region_is_vmalloc(struct axfs_super *sbi,
- struct axfs_region_desc *region)
- {
-- u64 va = (u32) region->virt_addr;
-+ u64 va = (unsigned long) region->virt_addr;
- u64 vo = (u64) region->fsoffset + (u64) sbi->virt_start_addr;
-
- if (va == 0)
+++ /dev/null
-From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:29:51 2012
-From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Date: Fri, 23 Nov 2012 16:54:09 +0530
-Subject: [PATCH v2 RESEND 01/15] AXFS: Kconfigs and Makefiles
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
-Message-ID: <50AF5CD9.2040206@ap.sony.com>
-
-
-From: Jared Hulbert <jaredeh@gmail.com>
-
-The Kconfigs and Makefiles for AXFS
-
-Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
----
- fs/Kconfig | 3 ++-
- fs/Makefile | 1 +
- fs/axfs/Kconfig | 18 ++++++++++++++++++
- fs/axfs/Makefile | 8 ++++++++
- 4 files changed, 29 insertions(+), 1 deletion(-)
- create mode 100644 fs/axfs/Kconfig
- create mode 100644 fs/axfs/Makefile
-
---- a/fs/Kconfig
-+++ b/fs/Kconfig
-@@ -17,7 +17,7 @@ source "fs/ext4/Kconfig"
- config FS_XIP
- # execute in place
- bool
-- depends on EXT2_FS_XIP || PRAMFS_XIP
-+ depends on EXT2_FS_XIP || PRAMFS_XIP || AXFS
- default y
-
- source "fs/jbd/Kconfig"
-@@ -221,6 +221,7 @@ source "fs/pstore/Kconfig"
- source "fs/sysv/Kconfig"
- source "fs/ufs/Kconfig"
- source "fs/pramfs/Kconfig"
-+source "fs/axfs/Kconfig"
- source "fs/exofs/Kconfig"
-
- endif # MISC_FILESYSTEMS
---- a/fs/Makefile
-+++ b/fs/Makefile
-@@ -72,6 +72,7 @@ obj-$(CONFIG_EXT4_FS) += ext4/
- obj-$(CONFIG_JBD) += jbd/
- obj-$(CONFIG_JBD2) += jbd2/
- obj-$(CONFIG_CRAMFS) += cramfs/
-+obj-$(CONFIG_AXFS) += axfs/
- obj-$(CONFIG_SQUASHFS) += squashfs/
- obj-y += ramfs/
- obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
---- /dev/null
-+++ b/fs/axfs/Kconfig
-@@ -0,0 +1,18 @@
-+config AXFS
-+ tristate "Advanced XIP File System (AXFS) support (EXPERIMENTAL)"
-+ select FS_XIP
-+ select ZLIB_INFLATE
-+ help
-+ The Advanced XIP File System or (AXFS) is a highly compressed
-+ readonly filesystem like cramfs or squashfs. It also can be
-+ configured to store individual pages of files compressed or
-+ uncompressed as XIP pages. This allows for faster boot up and
-+ application launch time with a smaller memory footprint.
-+
-+config AXFS_PROFILING
-+ bool "Profiling extensions for AXFS (EXPERIMENTAL)"
-+ depends on AXFS
-+ help
-+ Profiling tooling used to identify what pages in the filesystem
-+ image are actually accessed and how much.
-+
---- /dev/null
-+++ b/fs/axfs/Makefile
-@@ -0,0 +1,8 @@
-+#
-+# Makefile for axfs
-+#
-+
-+obj-$(CONFIG_AXFS) += axfs.o
-+
-+axfs-y := axfs_inode.o axfs_super.o axfs_uncompress.o axfs_profiling.o \
-+ axfs_uml.o axfs_mtd.o axfs_bdev.o axfs_physmem.o
+++ /dev/null
-From foo@baz Wed Dec 5 14:39:44 PST 2012
-Date: Wed, 05 Dec 2012 14:39:44 -0800
-To: Greg KH <gregkh@linuxfoundation.org>
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Subject: axfs: mark it broken
-
-It doesn't build properly in 3.4, so let's not even try.
-
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
----
- fs/axfs/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/fs/axfs/Kconfig
-+++ b/fs/axfs/Kconfig
-@@ -1,5 +1,6 @@
- config AXFS
- tristate "Advanced XIP File System (AXFS) support (EXPERIMENTAL)"
-+ depends on BROKEN
- select FS_XIP
- select ZLIB_INFLATE
- help
+++ /dev/null
-From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:51:22 2012
-From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Date: Fri, 23 Nov 2012 17:15:41 +0530
-Subject: [PATCH v2 RESEND 15/15] AXFS: mount as rootfs
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
-Message-ID: <50AF61E5.4080108@ap.sony.com>
-
-
-From: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
-
-Add support to mount AXFS as root file system first.
-
-Signed-off-by: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
----
- fs/axfs/Kconfig | 15 +++++++++++++++
- fs/axfs/axfs_super.c | 6 ++++++
- init/do_mounts.c | 20 ++++++++++++++++++++
- 3 files changed, 41 insertions(+)
-
---- a/fs/axfs/Kconfig
-+++ b/fs/axfs/Kconfig
-@@ -34,3 +34,18 @@ config AXFS_DEBUG_XIP_RECORDS_NUM
- help
- The number of records which /porc/axfs_xip can record. one record
- takes about 64 bytes of memory.
-+
-+config AXFS_FIRST_MOUNT_AXFS_AS_ROOTFS
-+ bool "First Mount AXFS as Rootfs"
-+ depends on AXFS
-+ help
-+ Say Y if you have enabled axfs, and you want to mount the axfs
-+ image as a root file system first when the kernel boots. This option
-+ makes the kernel boottime a little faster when the command line is
-+ properly set. Before having the kernel mount this axfs image
-+ as a root file system, you must pass the command line parameter:
-+ "root=/dev/null rootflags=physaddr=0x********" to the kernel
-+ (replace 0x******** with the physical address location of the
-+ axfs image to boot with).
-+
-+ If unsure, say N.
---- a/fs/axfs/axfs_super.c
-+++ b/fs/axfs/axfs_super.c
-@@ -884,6 +884,12 @@ struct dentry *axfs_get_sb(struct file_s
- if (err)
- goto out;
-
-+#ifdef CONFIG_AXFS_FIRST_MOUNT_AXFS_AS_ROOTFS
-+ printk(KERN_INFO "AXFS: Checking AXFS filesystem at virtaddr: 0x%08lx "
-+ "(physaddr=0x%08lx).\n", sbi->virt_start_addr,
-+ sbi->phys_start_addr);
-+#endif
-+
- /* First we check if we are mounting directly to memory */
- ret = axfs_get_sb_address(fs_type, flags, sbi);
- if (!(IS_ERR_OR_NULL(ret)))
---- a/init/do_mounts.c
-+++ b/init/do_mounts.c
-@@ -439,6 +439,19 @@ static int __init mount_nfs_root(void)
- }
- #endif
-
-+#ifdef CONFIG_AXFS_FIRST_MOUNT_AXFS_AS_ROOTFS
-+static int __init mount_axfs_root(void)
-+{
-+ create_dev("/dev/root", ROOT_DEV);
-+ if (root_mount_data &&
-+ do_mount_root("/dev/root", "axfs", root_mountflags,
-+ root_mount_data) == 0)
-+ return 1;
-+ return 0;
-+}
-+#endif
-+
-+
- #if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD)
- void __init change_floppy(char *fmt, ...)
- {
-@@ -471,6 +484,13 @@ void __init change_floppy(char *fmt, ...
-
- void __init mount_root(void)
- {
-+#ifdef CONFIG_AXFS_FIRST_MOUNT_AXFS_AS_ROOTFS
-+ if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
-+ if (mount_axfs_root())
-+ return;
-+ printk(KERN_ERR "VFS: Unable to mount axfs root.\n");
-+ }
-+#endif
- #ifdef CONFIG_ROOT_NFS
- if (ROOT_DEV == Root_NFS) {
- if (mount_nfs_root())
+++ /dev/null
-From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:50:07 2012
-From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
-Date: Fri, 23 Nov 2012 17:14:25 +0530
-Subject: [PATCH v2 RESEND 13/15] AXFS: XIP debugging support.
-To: Greg KH <gregkh@linuxfoundation.org>
-Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
-Message-ID: <50AF6199.7040801@ap.sony.com>
-
-
-From: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
-
-This code augments debugg infrastructure for AXFS.
-It captures access of XIP mapped pages of files in a
-proc entry at /proc/axfs_xip.
-
-Signed-off-by: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
-Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
----
- fs/axfs/Kconfig | 18 +++++
- fs/axfs/Makefile | 2
- fs/axfs/axfs_inode.c | 35 +++++++++-
- fs/axfs/axfs_super.c | 4 -
- fs/axfs/axfs_xip_profile.c | 154 +++++++++++++++++++++++++++++++++++++++++++++
- include/linux/axfs_fs.h | 7 ++
- 6 files changed, 216 insertions(+), 4 deletions(-)
- create mode 100644 fs/axfs/axfs_xip_profile.c
-
---- a/fs/axfs/Kconfig
-+++ b/fs/axfs/Kconfig
-@@ -16,3 +16,21 @@ config AXFS_PROFILING
- Profiling tooling used to identify what pages in the filesystem
- image are actually accessed and how much.
-
-+config AXFS_DEBUG
-+ bool "AXFS debugging support"
-+ depends on AXFS
-+ help
-+ If you are experiencing any problems with the AXFS filesystem, say
-+ Y here. This will create a profile entry at /proc/axfs_xip. In this
-+ profile, the XIP mapped pages of files are recorded.
-+
-+ If unsure, say N.
-+
-+config AXFS_DEBUG_XIP_RECORDS_NUM
-+ int "Number of axfs xip profile records (100 - 1000)"
-+ range 100 1000
-+ depends on AXFS_DEBUG
-+ default 500
-+ help
-+ The number of records which /porc/axfs_xip can record. one record
-+ takes about 64 bytes of memory.
---- a/fs/axfs/Makefile
-+++ b/fs/axfs/Makefile
-@@ -6,3 +6,5 @@ obj-$(CONFIG_AXFS) += axfs.o
-
- axfs-y := axfs_inode.o axfs_super.o axfs_uncompress.o axfs_profiling.o \
- axfs_uml.o axfs_mtd.o axfs_bdev.o axfs_physmem.o
-+
-+obj-$(CONFIG_AXFS_DEBUG) += axfs_xip_profile.o
---- a/fs/axfs/axfs_inode.c
-+++ b/fs/axfs/axfs_inode.c
-@@ -464,6 +464,10 @@ static int axfs_fault(struct vm_area_str
- struct axfs_super *sbi = AXFS_SB(sb);
- u64 ino_number = inode->i_ino;
- u64 array_index;
-+#ifdef CONFIG_AXFS_DEBUG
-+ unsigned long xip_node_address, offset, length;
-+ unsigned int numpages, count;
-+#endif
-
- array_index = axfs_get_inode_array_index(sbi, ino_number) + vmf->pgoff;
-
-@@ -474,12 +478,39 @@ static int axfs_fault(struct vm_area_str
- if (!(vma->vm_flags & VM_WRITE))
- axfs_profiling_add(sbi, array_index, ino_number);
-
-+#ifdef CONFIG_AXFS_DEBUG
-+ offset = vma->vm_pgoff;
-+ length = vma->vm_end - vma->vm_start;
-+
-+ if (length > inode->i_size)
-+ length = inode->i_size;
-+
-+ length = PAGE_ALIGN(length);
-+ numpages = length >> PAGE_SHIFT;
-+#endif
-+
- /*
- * figure out if the node is XIP or compressed and call the
- * appropriate function
- */
-- if (axfs_is_node_xip(sbi, array_index))
-- return xip_file_fault(vma, vmf);
-+#ifdef CONFIG_AXFS_DEBUG
-+ for (count = 0; count < numpages; count++, array_index++) {
-+#endif
-+ if (axfs_is_node_xip(sbi, array_index)) {
-+#ifdef CONFIG_AXFS_DEBUG
-+ xip_node_address = axfs_get_xip_region_physaddr(sbi);
-+ xip_node_address += ((axfs_get_inode_num_entries(sbi, array_index)) << PAGE_SHIFT);
-+ axfs_xip_record((unsigned char *)file->f_dentry->d_name.name,
-+ xip_node_address,
-+ vma->vm_start + (PAGE_SIZE * count),
-+ (unsigned int)(PAGE_SIZE),
-+ pgprot_val(vma->vm_page_prot));
-+#endif
-+ return xip_file_fault(vma, vmf);
-+ }
-+#ifdef CONFIG_AXFS_DEBUG
-+ }
-+#endif
- return filemap_fault(vma, vmf);
- }
-
---- a/fs/axfs/axfs_super.c
-+++ b/fs/axfs/axfs_super.c
-@@ -681,11 +681,11 @@ static int axfs_do_fill_super(struct sup
- goto out;
- }
-
-+#ifdef CONFIG_AXFS_DEBUG
- if (axfs_get_inode_num_entries(sbi, 0) == 0) {
- printk(KERN_INFO "axfs: empty filesystem\n");
-- err = -EINVAL;
-- goto out;
- }
-+#endif
-
- err = axfs_init_cblock_buffers(sbi);
- if (err)
---- /dev/null
-+++ b/fs/axfs/axfs_xip_profile.c
-@@ -0,0 +1,154 @@
-+/*
-+ * fs/axfs/axfs_xip_profile.c
-+ *
-+ * profiler: /proc/axfs_xip
-+ *
-+ * Copyright 2005-2007 Sony Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2
-+ * of the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-+ * MA 02110-1301, USA.
-+ *
-+ *
-+ */
-+
-+#ifdef CONFIG_AXFS_DEBUG
-+
-+#include <linux/types.h>
-+#include <linux/proc_fs.h>
-+
-+
-+#ifndef CONFIG_AXFS_DEBUG_XIP_RECORDS_NUM
-+#define CONFIG_AXFS_DEBUG_XIP_RECORDS_NUM 500
-+#endif
-+
-+#define RECORDS CONFIG_AXFS_DEBUG_XIP_RECORDS_NUM
-+
-+#define MAX_FILE_NAME_LEN 48
-+
-+static DEFINE_SEMAPHORE(record_index_sem);
-+
-+/* each record is 64 bytes */
-+struct axfs_xip_record {
-+ char filename[MAX_FILE_NAME_LEN]; /* XIP mapped file name */
-+ unsigned long physaddr; /* XIP mapped physaddr */
-+ unsigned long virtaddr; /* XIP mapped virtaddr */
-+ unsigned int size; /* XIP mapped size */
-+ unsigned long pgprot; /* XIP mapped page prot */
-+};
-+
-+static struct axfs_xip_record axfs_xip_records[RECORDS];
-+static unsigned long record_index;
-+
-+/* record function */
-+int axfs_xip_record(unsigned char *name, unsigned long physaddr,
-+ unsigned long virtaddr, unsigned int size,
-+ unsigned long pgprot)
-+{
-+
-+ int namelen = 0;
-+ if (down_interruptible(&record_index_sem))
-+ return -EINTR;
-+
-+ if (record_index >= RECORDS)
-+ goto out;
-+
-+ axfs_xip_records[record_index].physaddr = physaddr;
-+ axfs_xip_records[record_index].virtaddr = virtaddr;
-+ axfs_xip_records[record_index].size = size;
-+ axfs_xip_records[record_index].pgprot = pgprot;
-+ memset(axfs_xip_records[record_index].filename, 0, MAX_FILE_NAME_LEN);
-+ namelen = strlen(name);
-+ strncpy(axfs_xip_records[record_index].filename, name,
-+ (namelen >= MAX_FILE_NAME_LEN) ? MAX_FILE_NAME_LEN-1 : namelen);
-+
-+ record_index++;
-+
-+out:
-+ up(&record_index_sem);
-+ return 0;
-+}
-+
-+static int axfs_xip_record_to_string(struct axfs_xip_record *record,
-+ char *buf, int len)
-+{
-+
-+ return snprintf(buf, len,
-+ "0x%08lx to 0x%08lx 0x%x 0x%lx %s\n",
-+ record->physaddr, record->virtaddr,
-+ record->size, record->pgprot, record->filename) ;
-+}
-+
-+
-+static unsigned int is_first_line = 1;
-+#define PROFILE_HEADINGS "\nXIP: physaddr, virtaddr, size, pgprot, filename\n"
-+#define HEADINGS_LEN sizeof(PROFILE_HEADINGS)
-+
-+static int axfs_xip_proc_read(char *page, char **start, off_t off, int count,
-+ int *eof, void *data)
-+{
-+ unsigned long tlen = 0;
-+ unsigned long index = record_index;
-+ struct axfs_xip_record *record;
-+
-+ if (down_interruptible(&record_index_sem))
-+ return -EINTR;
-+
-+ if (off >= index) {
-+ *eof = 1;
-+ is_first_line = 1;
-+ goto out;
-+ }
-+ record = &axfs_xip_records[off];
-+
-+ if (is_first_line) {
-+ strncpy(page+tlen, PROFILE_HEADINGS, HEADINGS_LEN);
-+ tlen += HEADINGS_LEN - 1;
-+ is_first_line = 0;
-+ }
-+ tlen += axfs_xip_record_to_string(record, page+tlen, PAGE_SIZE-tlen);
-+ *start = (char *)1;
-+ out:
-+ up(&record_index_sem);
-+ return tlen > count ? 0 : tlen;
-+}
-+
-+/* Write to Clear */
-+static int axfs_xip_proc_write(struct file *file, const char *buffer,
-+ unsigned long count, void *data)
-+{
-+ if (down_interruptible(&record_index_sem))
-+ return -EINTR;
-+
-+ record_index = 0;
-+
-+ up(&record_index_sem);
-+ return count;
-+}
-+
-+static int __init axfs_xip_proc_profile(void)
-+{
-+ struct proc_dir_entry *ent;
-+ ent = create_proc_entry("axfs_xip", S_IFREG|S_IRUGO|S_IWUSR, NULL);
-+ if (!ent) {
-+ printk(KERN_ERR "create axfs_xip proc entry failed\n");
-+ return -ENOMEM;
-+ }
-+ ent->read_proc = axfs_xip_proc_read;
-+ ent->write_proc = axfs_xip_proc_write;
-+ return 0;
-+}
-+late_initcall(axfs_xip_proc_profile);
-+
-+#endif /* CONFIG_AXFS_DEBUG */
---- a/include/linux/axfs_fs.h
-+++ b/include/linux/axfs_fs.h
-@@ -42,6 +42,13 @@ int axfs_uncompress_block(void *, int, v
- int axfs_uncompress_init(void);
- int axfs_uncompress_exit(void);
-
-+#ifdef CONFIG_AXFS_DEBUG
-+int axfs_xip_record(unsigned char *name, unsigned long physaddr,
-+ unsigned long virtaddr,
-+ unsigned int size,
-+ unsigned long pgprot);
-+#endif
-+
- struct axfs_profiling_data {
- u64 inode_number;
- unsigned long count;
+++ /dev/null
-From 4f84a660ea97014e1293c8690657329e016198a8 Mon Sep 17 00:00:00 2001
-From: Eric Dumazet <edumazet@google.com>
-Date: Thu, 10 May 2012 07:51:25 +0000
-Subject: [PATCH] codel: Controlled Delay AQM
-
-commit 76e3cc126bb223013a6b9a0e2a51238d1ef2e409 upstream.
-
-An implementation of CoDel AQM, from Kathleen Nichols and Van Jacobson.
-
-http://queue.acm.org/detail.cfm?id=2209336
-
-This AQM main input is no longer queue size in bytes or packets, but the
-delay packets stay in (FIFO) queue.
-
-As we don't have infinite memory, we still can drop packets in enqueue()
-in case of massive load, but mean of CoDel is to drop packets in
-dequeue(), using a control law based on two simple parameters :
-
-target : target sojourn time (default 5ms)
-interval : width of moving time window (default 100ms)
-
-Based on initial work from Dave Taht.
-
-Refactored to help future codel inclusion as a plugin for other linux
-qdisc (FQ_CODEL, ...), like RED.
-
-include/net/codel.h contains codel algorithm as close as possible than
-Kathleen reference.
-
-net/sched/sch_codel.c contains the linux qdisc specific glue.
-
-Separate structures permit a memory efficient implementation of fq_codel
-(to be sent as a separate work) : Each flow has its own struct
-codel_vars.
-
-timestamps are taken at enqueue() time with 1024 ns precision, allowing
-a range of 2199 seconds in queue, and 100Gb links support. iproute2 uses
-usec as base unit.
-
-Selected packets are dropped, unless ECN is enabled and packets can get
-ECN mark instead.
-
-Tested from 2Mb to 10Gb speeds with no particular problems, on ixgbe and
-tg3 drivers (BQL enabled).
-
-Usage: tc qdisc ... codel [ limit PACKETS ] [ target TIME ]
- [ interval TIME ] [ ecn ]
-
-qdisc codel 10: parent 1:1 limit 2000p target 3.0ms interval 60.0ms ecn
- Sent 13347099587 bytes 8815805 pkt (dropped 0, overlimits 0 requeues 0)
- rate 202365Kbit 16708pps backlog 113550b 75p requeues 0
- count 116 lastcount 98 ldelay 4.3ms dropping drop_next 816us
- maxpacket 1514 ecn_mark 84399 drop_overlimit 0
-
-CoDel must be seen as a base module, and should be used keeping in mind
-there is still a FIFO queue. So a typical setup will probably need a
-hierarchy of several qdiscs and packet classifiers to be able to meet
-whatever constraints a user might have.
-
-One possible example would be to use fq_codel, which combines Fair
-Queueing and CoDel, in replacement of sfq / sfq_red.
-
-Signed-off-by: Eric Dumazet <edumazet@google.com>
-Signed-off-by: Dave Taht <dave.taht@bufferbloat.net>
-Cc: Kathleen Nichols <nichols@pollere.com>
-Cc: Van Jacobson <van@pollere.net>
-Cc: Tom Herbert <therbert@google.com>
-Cc: Matt Mathis <mattmathis@google.com>
-Cc: Yuchung Cheng <ycheng@google.com>
-Cc: Stephen Hemminger <shemminger@vyatta.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-
----
- include/linux/pkt_sched.h | 26 +++
- include/net/codel.h | 332 ++++++++++++++++++++++++++++++++++++++++++++++
- net/sched/Kconfig | 11 +
- net/sched/Makefile | 1
- net/sched/sch_codel.c | 275 ++++++++++++++++++++++++++++++++++++++
- 5 files changed, 645 insertions(+)
-
---- a/include/linux/pkt_sched.h
-+++ b/include/linux/pkt_sched.h
-@@ -655,4 +655,30 @@ struct tc_qfq_stats {
- __u32 lmax;
- };
-
-+/* CODEL */
-+
-+enum {
-+ TCA_CODEL_UNSPEC,
-+ TCA_CODEL_TARGET,
-+ TCA_CODEL_LIMIT,
-+ TCA_CODEL_INTERVAL,
-+ TCA_CODEL_ECN,
-+ __TCA_CODEL_MAX
-+};
-+
-+#define TCA_CODEL_MAX (__TCA_CODEL_MAX - 1)
-+
-+struct tc_codel_xstats {
-+ __u32 maxpacket; /* largest packet we've seen so far */
-+ __u32 count; /* how many drops we've done since the last time we
-+ * entered dropping state
-+ */
-+ __u32 lastcount; /* count at entry to dropping state */
-+ __u32 ldelay; /* in-queue delay seen by most recently dequeued packet */
-+ __s32 drop_next; /* time to drop next packet */
-+ __u32 drop_overlimit; /* number of time max qdisc packet limit was hit */
-+ __u32 ecn_mark; /* number of packets we ECN marked instead of dropped */
-+ __u32 dropping; /* are we in dropping state ? */
-+};
-+
- #endif
---- /dev/null
-+++ b/include/net/codel.h
-@@ -0,0 +1,332 @@
-+#ifndef __NET_SCHED_CODEL_H
-+#define __NET_SCHED_CODEL_H
-+
-+/*
-+ * Codel - The Controlled-Delay Active Queue Management algorithm
-+ *
-+ * Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
-+ * Copyright (C) 2011-2012 Van Jacobson <van@pollere.net>
-+ * Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
-+ * Copyright (C) 2012 Eric Dumazet <edumazet@google.com>
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions, and the following disclaimer,
-+ * without modification.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in the
-+ * documentation and/or other materials provided with the distribution.
-+ * 3. The names of the authors may not be used to endorse or promote products
-+ * derived from this software without specific prior written permission.
-+ *
-+ * Alternatively, provided that this notice is retained in full, this
-+ * software may be distributed under the terms of the GNU General
-+ * Public License ("GPL") version 2, in which case the provisions of the
-+ * GPL apply INSTEAD OF those given above.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-+ * DAMAGE.
-+ *
-+ */
-+
-+#include <linux/types.h>
-+#include <linux/ktime.h>
-+#include <linux/skbuff.h>
-+#include <net/pkt_sched.h>
-+#include <net/inet_ecn.h>
-+
-+/* Controlling Queue Delay (CoDel) algorithm
-+ * =========================================
-+ * Source : Kathleen Nichols and Van Jacobson
-+ * http://queue.acm.org/detail.cfm?id=2209336
-+ *
-+ * Implemented on linux by Dave Taht and Eric Dumazet
-+ */
-+
-+
-+/* CoDel uses a 1024 nsec clock, encoded in u32
-+ * This gives a range of 2199 seconds, because of signed compares
-+ */
-+typedef u32 codel_time_t;
-+typedef s32 codel_tdiff_t;
-+#define CODEL_SHIFT 10
-+#define MS2TIME(a) ((a * NSEC_PER_MSEC) >> CODEL_SHIFT)
-+
-+static inline codel_time_t codel_get_time(void)
-+{
-+ u64 ns = ktime_to_ns(ktime_get());
-+
-+ return ns >> CODEL_SHIFT;
-+}
-+
-+#define codel_time_after(a, b) ((s32)(a) - (s32)(b) > 0)
-+#define codel_time_after_eq(a, b) ((s32)(a) - (s32)(b) >= 0)
-+#define codel_time_before(a, b) ((s32)(a) - (s32)(b) < 0)
-+#define codel_time_before_eq(a, b) ((s32)(a) - (s32)(b) <= 0)
-+
-+/* Qdiscs using codel plugin must use codel_skb_cb in their own cb[] */
-+struct codel_skb_cb {
-+ codel_time_t enqueue_time;
-+};
-+
-+static struct codel_skb_cb *get_codel_cb(const struct sk_buff *skb)
-+{
-+ qdisc_cb_private_validate(skb, sizeof(struct codel_skb_cb));
-+ return (struct codel_skb_cb *)qdisc_skb_cb(skb)->data;
-+}
-+
-+static codel_time_t codel_get_enqueue_time(const struct sk_buff *skb)
-+{
-+ return get_codel_cb(skb)->enqueue_time;
-+}
-+
-+static void codel_set_enqueue_time(struct sk_buff *skb)
-+{
-+ get_codel_cb(skb)->enqueue_time = codel_get_time();
-+}
-+
-+static inline u32 codel_time_to_us(codel_time_t val)
-+{
-+ u64 valns = ((u64)val << CODEL_SHIFT);
-+
-+ do_div(valns, NSEC_PER_USEC);
-+ return (u32)valns;
-+}
-+
-+/**
-+ * struct codel_params - contains codel parameters
-+ * @target: target queue size (in time units)
-+ * @interval: width of moving time window
-+ * @ecn: is Explicit Congestion Notification enabled
-+ */
-+struct codel_params {
-+ codel_time_t target;
-+ codel_time_t interval;
-+ bool ecn;
-+};
-+
-+/**
-+ * struct codel_vars - contains codel variables
-+ * @count: how many drops we've done since the last time we
-+ * entered dropping state
-+ * @lastcount: count at entry to dropping state
-+ * @dropping: set to true if in dropping state
-+ * @first_above_time: when we went (or will go) continuously above target
-+ * for interval
-+ * @drop_next: time to drop next packet, or when we dropped last
-+ * @ldelay: sojourn time of last dequeued packet
-+ */
-+struct codel_vars {
-+ u32 count;
-+ u32 lastcount;
-+ bool dropping;
-+ codel_time_t first_above_time;
-+ codel_time_t drop_next;
-+ codel_time_t ldelay;
-+};
-+
-+/**
-+ * struct codel_stats - contains codel shared variables and stats
-+ * @maxpacket: largest packet we've seen so far
-+ * @drop_count: temp count of dropped packets in dequeue()
-+ * ecn_mark: number of packets we ECN marked instead of dropping
-+ */
-+struct codel_stats {
-+ u32 maxpacket;
-+ u32 drop_count;
-+ u32 ecn_mark;
-+};
-+
-+static void codel_params_init(struct codel_params *params)
-+{
-+ params->interval = MS2TIME(100);
-+ params->target = MS2TIME(5);
-+ params->ecn = false;
-+}
-+
-+static void codel_vars_init(struct codel_vars *vars)
-+{
-+ vars->drop_next = 0;
-+ vars->first_above_time = 0;
-+ vars->dropping = false; /* exit dropping state */
-+ vars->count = 0;
-+ vars->lastcount = 0;
-+}
-+
-+static void codel_stats_init(struct codel_stats *stats)
-+{
-+ stats->maxpacket = 256;
-+}
-+
-+/* return interval/sqrt(x) with good precision
-+ * relies on int_sqrt(unsigned long x) kernel implementation
-+ */
-+static u32 codel_inv_sqrt(u32 _interval, u32 _x)
-+{
-+ u64 interval = _interval;
-+ unsigned long x = _x;
-+
-+ /* Scale operands for max precision */
-+
-+#if BITS_PER_LONG == 64
-+ x <<= 32; /* On 64bit arches, we can prescale x by 32bits */
-+ interval <<= 16;
-+#endif
-+
-+ while (x < (1UL << (BITS_PER_LONG - 2))) {
-+ x <<= 2;
-+ interval <<= 1;
-+ }
-+ do_div(interval, int_sqrt(x));
-+ return (u32)interval;
-+}
-+
-+static codel_time_t codel_control_law(codel_time_t t,
-+ codel_time_t interval,
-+ u32 count)
-+{
-+ return t + codel_inv_sqrt(interval, count);
-+}
-+
-+
-+static bool codel_should_drop(struct sk_buff *skb,
-+ unsigned int *backlog,
-+ struct codel_vars *vars,
-+ struct codel_params *params,
-+ struct codel_stats *stats,
-+ codel_time_t now)
-+{
-+ bool ok_to_drop;
-+
-+ if (!skb) {
-+ vars->first_above_time = 0;
-+ return false;
-+ }
-+
-+ vars->ldelay = now - codel_get_enqueue_time(skb);
-+ *backlog -= qdisc_pkt_len(skb);
-+
-+ if (unlikely(qdisc_pkt_len(skb) > stats->maxpacket))
-+ stats->maxpacket = qdisc_pkt_len(skb);
-+
-+ if (codel_time_before(vars->ldelay, params->target) ||
-+ *backlog <= stats->maxpacket) {
-+ /* went below - stay below for at least interval */
-+ vars->first_above_time = 0;
-+ return false;
-+ }
-+ ok_to_drop = false;
-+ if (vars->first_above_time == 0) {
-+ /* just went above from below. If we stay above
-+ * for at least interval we'll say it's ok to drop
-+ */
-+ vars->first_above_time = now + params->interval;
-+ } else if (codel_time_after(now, vars->first_above_time)) {
-+ ok_to_drop = true;
-+ }
-+ return ok_to_drop;
-+}
-+
-+typedef struct sk_buff * (*codel_skb_dequeue_t)(struct codel_vars *vars,
-+ struct Qdisc *sch);
-+
-+static struct sk_buff *codel_dequeue(struct Qdisc *sch,
-+ struct codel_params *params,
-+ struct codel_vars *vars,
-+ struct codel_stats *stats,
-+ codel_skb_dequeue_t dequeue_func,
-+ u32 *backlog)
-+{
-+ struct sk_buff *skb = dequeue_func(vars, sch);
-+ codel_time_t now;
-+ bool drop;
-+
-+ if (!skb) {
-+ vars->dropping = false;
-+ return skb;
-+ }
-+ now = codel_get_time();
-+ drop = codel_should_drop(skb, backlog, vars, params, stats, now);
-+ if (vars->dropping) {
-+ if (!drop) {
-+ /* sojourn time below target - leave dropping state */
-+ vars->dropping = false;
-+ } else if (codel_time_after_eq(now, vars->drop_next)) {
-+ /* It's time for the next drop. Drop the current
-+ * packet and dequeue the next. The dequeue might
-+ * take us out of dropping state.
-+ * If not, schedule the next drop.
-+ * A large backlog might result in drop rates so high
-+ * that the next drop should happen now,
-+ * hence the while loop.
-+ */
-+ while (vars->dropping &&
-+ codel_time_after_eq(now, vars->drop_next)) {
-+ if (++vars->count == 0) /* avoid zero divides */
-+ vars->count = ~0U;
-+ if (params->ecn && INET_ECN_set_ce(skb)) {
-+ stats->ecn_mark++;
-+ vars->drop_next =
-+ codel_control_law(vars->drop_next,
-+ params->interval,
-+ vars->count);
-+ goto end;
-+ }
-+ qdisc_drop(skb, sch);
-+ stats->drop_count++;
-+ skb = dequeue_func(vars, sch);
-+ if (!codel_should_drop(skb, backlog,
-+ vars, params, stats, now)) {
-+ /* leave dropping state */
-+ vars->dropping = false;
-+ } else {
-+ /* and schedule the next drop */
-+ vars->drop_next =
-+ codel_control_law(vars->drop_next,
-+ params->interval,
-+ vars->count);
-+ }
-+ }
-+ }
-+ } else if (drop) {
-+ if (params->ecn && INET_ECN_set_ce(skb)) {
-+ stats->ecn_mark++;
-+ } else {
-+ qdisc_drop(skb, sch);
-+ stats->drop_count++;
-+
-+ skb = dequeue_func(vars, sch);
-+ drop = codel_should_drop(skb, backlog, vars, params,
-+ stats, now);
-+ }
-+ vars->dropping = true;
-+ /* if min went above target close to when we last went below it
-+ * assume that the drop rate that controlled the queue on the
-+ * last cycle is a good starting point to control it now.
-+ */
-+ if (codel_time_before(now - vars->drop_next,
-+ 16 * params->interval)) {
-+ vars->count = (vars->count - vars->lastcount) | 1;
-+ } else {
-+ vars->count = 1;
-+ }
-+ vars->lastcount = vars->count;
-+ vars->drop_next = codel_control_law(now, params->interval,
-+ vars->count);
-+ }
-+end:
-+ return skb;
-+}
-+#endif
---- a/net/sched/Kconfig
-+++ b/net/sched/Kconfig
-@@ -250,6 +250,17 @@ config NET_SCH_QFQ
-
- If unsure, say N.
-
-+config NET_SCH_CODEL
-+ tristate "Controlled Delay AQM (CODEL)"
-+ help
-+ Say Y here if you want to use the Controlled Delay (CODEL)
-+ packet scheduling algorithm.
-+
-+ To compile this driver as a module, choose M here: the module
-+ will be called sch_codel.
-+
-+ If unsure, say N.
-+
- config NET_SCH_INGRESS
- tristate "Ingress Qdisc"
- depends on NET_CLS_ACT
---- a/net/sched/Makefile
-+++ b/net/sched/Makefile
-@@ -37,6 +37,7 @@ obj-$(CONFIG_NET_SCH_PLUG) += sch_plug.o
- obj-$(CONFIG_NET_SCH_MQPRIO) += sch_mqprio.o
- obj-$(CONFIG_NET_SCH_CHOKE) += sch_choke.o
- obj-$(CONFIG_NET_SCH_QFQ) += sch_qfq.o
-+obj-$(CONFIG_NET_SCH_CODEL) += sch_codel.o
-
- obj-$(CONFIG_NET_CLS_U32) += cls_u32.o
- obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o
---- /dev/null
-+++ b/net/sched/sch_codel.c
-@@ -0,0 +1,275 @@
-+/*
-+ * Codel - The Controlled-Delay Active Queue Management algorithm
-+ *
-+ * Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
-+ * Copyright (C) 2011-2012 Van Jacobson <van@pollere.net>
-+ *
-+ * Implemented on linux by :
-+ * Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
-+ * Copyright (C) 2012 Eric Dumazet <edumazet@google.com>
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions, and the following disclaimer,
-+ * without modification.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in the
-+ * documentation and/or other materials provided with the distribution.
-+ * 3. The names of the authors may not be used to endorse or promote products
-+ * derived from this software without specific prior written permission.
-+ *
-+ * Alternatively, provided that this notice is retained in full, this
-+ * software may be distributed under the terms of the GNU General
-+ * Public License ("GPL") version 2, in which case the provisions of the
-+ * GPL apply INSTEAD OF those given above.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-+ * DAMAGE.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/errno.h>
-+#include <linux/skbuff.h>
-+#include <net/pkt_sched.h>
-+#include <net/codel.h>
-+
-+
-+#define DEFAULT_CODEL_LIMIT 1000
-+
-+struct codel_sched_data {
-+ struct codel_params params;
-+ struct codel_vars vars;
-+ struct codel_stats stats;
-+ u32 drop_overlimit;
-+};
-+
-+/* This is the specific function called from codel_dequeue()
-+ * to dequeue a packet from queue. Note: backlog is handled in
-+ * codel, we dont need to reduce it here.
-+ */
-+static struct sk_buff *dequeue(struct codel_vars *vars, struct Qdisc *sch)
-+{
-+ struct sk_buff *skb = __skb_dequeue(&sch->q);
-+
-+ prefetch(&skb->end); /* we'll need skb_shinfo() */
-+ return skb;
-+}
-+
-+static struct sk_buff *codel_qdisc_dequeue(struct Qdisc *sch)
-+{
-+ struct codel_sched_data *q = qdisc_priv(sch);
-+ struct sk_buff *skb;
-+
-+ skb = codel_dequeue(sch, &q->params, &q->vars, &q->stats,
-+ dequeue, &sch->qstats.backlog);
-+ /* We cant call qdisc_tree_decrease_qlen() if our qlen is 0,
-+ * or HTB crashes. Defer it for next round.
-+ */
-+ if (q->stats.drop_count && sch->q.qlen) {
-+ qdisc_tree_decrease_qlen(sch, q->stats.drop_count);
-+ q->stats.drop_count = 0;
-+ }
-+ if (skb)
-+ qdisc_bstats_update(sch, skb);
-+ return skb;
-+}
-+
-+static int codel_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
-+{
-+ struct codel_sched_data *q;
-+
-+ if (likely(qdisc_qlen(sch) < sch->limit)) {
-+ codel_set_enqueue_time(skb);
-+ return qdisc_enqueue_tail(skb, sch);
-+ }
-+ q = qdisc_priv(sch);
-+ q->drop_overlimit++;
-+ return qdisc_drop(skb, sch);
-+}
-+
-+static const struct nla_policy codel_policy[TCA_CODEL_MAX + 1] = {
-+ [TCA_CODEL_TARGET] = { .type = NLA_U32 },
-+ [TCA_CODEL_LIMIT] = { .type = NLA_U32 },
-+ [TCA_CODEL_INTERVAL] = { .type = NLA_U32 },
-+ [TCA_CODEL_ECN] = { .type = NLA_U32 },
-+};
-+
-+static int codel_change(struct Qdisc *sch, struct nlattr *opt)
-+{
-+ struct codel_sched_data *q = qdisc_priv(sch);
-+ struct nlattr *tb[TCA_CODEL_MAX + 1];
-+ unsigned int qlen;
-+ int err;
-+
-+ if (!opt)
-+ return -EINVAL;
-+
-+ err = nla_parse_nested(tb, TCA_CODEL_MAX, opt, codel_policy);
-+ if (err < 0)
-+ return err;
-+
-+ sch_tree_lock(sch);
-+
-+ if (tb[TCA_CODEL_TARGET]) {
-+ u32 target = nla_get_u32(tb[TCA_CODEL_TARGET]);
-+
-+ q->params.target = ((u64)target * NSEC_PER_USEC) >> CODEL_SHIFT;
-+ }
-+
-+ if (tb[TCA_CODEL_INTERVAL]) {
-+ u32 interval = nla_get_u32(tb[TCA_CODEL_INTERVAL]);
-+
-+ q->params.interval = ((u64)interval * NSEC_PER_USEC) >> CODEL_SHIFT;
-+ }
-+
-+ if (tb[TCA_CODEL_LIMIT])
-+ sch->limit = nla_get_u32(tb[TCA_CODEL_LIMIT]);
-+
-+ if (tb[TCA_CODEL_ECN])
-+ q->params.ecn = !!nla_get_u32(tb[TCA_CODEL_ECN]);
-+
-+ qlen = sch->q.qlen;
-+ while (sch->q.qlen > sch->limit) {
-+ struct sk_buff *skb = __skb_dequeue(&sch->q);
-+
-+ sch->qstats.backlog -= qdisc_pkt_len(skb);
-+ qdisc_drop(skb, sch);
-+ }
-+ qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
-+
-+ sch_tree_unlock(sch);
-+ return 0;
-+}
-+
-+static int codel_init(struct Qdisc *sch, struct nlattr *opt)
-+{
-+ struct codel_sched_data *q = qdisc_priv(sch);
-+
-+ sch->limit = DEFAULT_CODEL_LIMIT;
-+
-+ codel_params_init(&q->params);
-+ codel_vars_init(&q->vars);
-+ codel_stats_init(&q->stats);
-+
-+ if (opt) {
-+ int err = codel_change(sch, opt);
-+
-+ if (err)
-+ return err;
-+ }
-+
-+ if (sch->limit >= 1)
-+ sch->flags |= TCQ_F_CAN_BYPASS;
-+ else
-+ sch->flags &= ~TCQ_F_CAN_BYPASS;
-+
-+ return 0;
-+}
-+
-+static int codel_dump(struct Qdisc *sch, struct sk_buff *skb)
-+{
-+ struct codel_sched_data *q = qdisc_priv(sch);
-+ struct nlattr *opts;
-+
-+ opts = nla_nest_start(skb, TCA_OPTIONS);
-+ if (opts == NULL)
-+ goto nla_put_failure;
-+
-+ if (nla_put_u32(skb, TCA_CODEL_TARGET,
-+ codel_time_to_us(q->params.target)) ||
-+ nla_put_u32(skb, TCA_CODEL_LIMIT,
-+ sch->limit) ||
-+ nla_put_u32(skb, TCA_CODEL_INTERVAL,
-+ codel_time_to_us(q->params.interval)) ||
-+ nla_put_u32(skb, TCA_CODEL_ECN,
-+ q->params.ecn))
-+ goto nla_put_failure;
-+
-+ return nla_nest_end(skb, opts);
-+
-+nla_put_failure:
-+ nla_nest_cancel(skb, opts);
-+ return -1;
-+}
-+
-+static int codel_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
-+{
-+ const struct codel_sched_data *q = qdisc_priv(sch);
-+ struct tc_codel_xstats st = {
-+ .maxpacket = q->stats.maxpacket,
-+ .count = q->vars.count,
-+ .lastcount = q->vars.lastcount,
-+ .drop_overlimit = q->drop_overlimit,
-+ .ldelay = codel_time_to_us(q->vars.ldelay),
-+ .dropping = q->vars.dropping,
-+ .ecn_mark = q->stats.ecn_mark,
-+ };
-+
-+ if (q->vars.dropping) {
-+ codel_tdiff_t delta = q->vars.drop_next - codel_get_time();
-+
-+ if (delta >= 0)
-+ st.drop_next = codel_time_to_us(delta);
-+ else
-+ st.drop_next = -codel_time_to_us(-delta);
-+ }
-+
-+ return gnet_stats_copy_app(d, &st, sizeof(st));
-+}
-+
-+static void codel_reset(struct Qdisc *sch)
-+{
-+ struct codel_sched_data *q = qdisc_priv(sch);
-+
-+ qdisc_reset_queue(sch);
-+ codel_vars_init(&q->vars);
-+}
-+
-+static struct Qdisc_ops codel_qdisc_ops __read_mostly = {
-+ .id = "codel",
-+ .priv_size = sizeof(struct codel_sched_data),
-+
-+ .enqueue = codel_qdisc_enqueue,
-+ .dequeue = codel_qdisc_dequeue,
-+ .peek = qdisc_peek_dequeued,
-+ .init = codel_init,
-+ .reset = codel_reset,
-+ .change = codel_change,
-+ .dump = codel_dump,
-+ .dump_stats = codel_dump_stats,
-+ .owner = THIS_MODULE,
-+};
-+
-+static int __init codel_module_init(void)
-+{
-+ return register_qdisc(&codel_qdisc_ops);
-+}
-+
-+static void __exit codel_module_exit(void)
-+{
-+ unregister_qdisc(&codel_qdisc_ops);
-+}
-+
-+module_init(codel_module_init)
-+module_exit(codel_module_exit)
-+
-+MODULE_DESCRIPTION("Controlled Delay queue discipline");
-+MODULE_AUTHOR("Dave Taht");
-+MODULE_AUTHOR("Eric Dumazet");
-+MODULE_LICENSE("Dual BSD/GPL");
+++ /dev/null
-From 2359a47671fc4fb0fe5e9945f76c2cb10792c0f8 Mon Sep 17 00:00:00 2001
-From: Eric Dumazet <edumazet@google.com>
-Date: Sun, 29 Jul 2012 20:52:21 +0000
-Subject: [PATCH] codel: refine one condition to avoid a nul rec_inv_sqrt
-
-commit 2359a47671fc4fb0fe5e9945f76c2cb10792c0f8 upstream.
-
-One condition before codel_Newton_step() was not good if
-we never left the dropping state for a flow. As a result
-rec_inv_sqrt was 0, instead of the ~0 initial value.
-
-codel control law was then set to a very aggressive mode, dropping
-many packets before reaching 'target' and recovering from this problem.
-
-To keep codel_vars_init() as efficient as possible, refine
-the condition to make sure rec_inv_sqrt initial value is correct
-
-Many thanks to Anton Mich for discovering the issue and suggesting
-a fix.
-
-Reported-by: Anton Mich <lp2s1h@gmail.com>
-Signed-off-by: Eric Dumazet <edumazet@google.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-
----
- include/net/codel.h | 8 ++++++--
- 1 file changed, 6 insertions(+), 2 deletions(-)
-
---- a/include/net/codel.h
-+++ b/include/net/codel.h
-@@ -305,6 +305,8 @@ static struct sk_buff *codel_dequeue(str
- }
- }
- } else if (drop) {
-+ u32 delta;
-+
- if (params->ecn && INET_ECN_set_ce(skb)) {
- stats->ecn_mark++;
- } else {
-@@ -320,9 +322,11 @@ static struct sk_buff *codel_dequeue(str
- * assume that the drop rate that controlled the queue on the
- * last cycle is a good starting point to control it now.
- */
-- if (codel_time_before(now - vars->drop_next,
-+ delta = vars->count - vars->lastcount;
-+ if (delta > 1 &&
-+ codel_time_before(now - vars->drop_next,
- 16 * params->interval)) {
-- vars->count = (vars->count - vars->lastcount) | 1;
-+ vars->count = delta;
- /* we dont care if rec_inv_sqrt approximation
- * is not very precise :
- * Next Newton steps will correct it quadratically.
+++ /dev/null
-From 536edd67109df5e0cdb2c4ee759e9bade7976367 Mon Sep 17 00:00:00 2001
-From: Eric Dumazet <edumazet@google.com>
-Date: Sat, 12 May 2012 03:32:13 +0000
-Subject: [PATCH] codel: use Newton method instead of sqrt() and divides
-
-commit 536edd67109df5e0cdb2c4ee759e9bade7976367 upstream.
-
-As Van pointed out, interval/sqrt(count) can be implemented using
-multiplies only.
-
-http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
-
-This patch implements the Newton method and reciprocal divide.
-
-Total cost is 15 cycles instead of 120 on my Corei5 machine (64bit
-kernel).
-
-There is a small 'error' for count values < 5, but we don't really care.
-
-I reuse a hole in struct codel_vars :
- - pack the dropping boolean into one bit
- - use 31bit to store the reciprocal value of sqrt(count).
-
-Suggested-by: Van Jacobson <van@pollere.net>
-Signed-off-by: Eric Dumazet <edumazet@google.com>
-Cc: Dave Taht <dave.taht@bufferbloat.net>
-Cc: Kathleen Nichols <nichols@pollere.com>
-Cc: Tom Herbert <therbert@google.com>
-Cc: Matt Mathis <mattmathis@google.com>
-Cc: Yuchung Cheng <ycheng@google.com>
-Cc: Nandita Dukkipati <nanditad@google.com>
-Cc: Stephen Hemminger <shemminger@vyatta.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-
----
- include/net/codel.h | 68 ++++++++++++++++++++++++++++------------------------
- 1 file changed, 37 insertions(+), 31 deletions(-)
-
---- a/include/net/codel.h
-+++ b/include/net/codel.h
-@@ -46,6 +46,7 @@
- #include <linux/skbuff.h>
- #include <net/pkt_sched.h>
- #include <net/inet_ecn.h>
-+#include <linux/reciprocal_div.h>
-
- /* Controlling Queue Delay (CoDel) algorithm
- * =========================================
-@@ -123,6 +124,7 @@ struct codel_params {
- * entered dropping state
- * @lastcount: count at entry to dropping state
- * @dropping: set to true if in dropping state
-+ * @rec_inv_sqrt: reciprocal value of sqrt(count) >> 1
- * @first_above_time: when we went (or will go) continuously above target
- * for interval
- * @drop_next: time to drop next packet, or when we dropped last
-@@ -131,7 +133,8 @@ struct codel_params {
- struct codel_vars {
- u32 count;
- u32 lastcount;
-- bool dropping;
-+ bool dropping:1;
-+ u32 rec_inv_sqrt:31;
- codel_time_t first_above_time;
- codel_time_t drop_next;
- codel_time_t ldelay;
-@@ -158,11 +161,7 @@ static void codel_params_init(struct cod
-
- static void codel_vars_init(struct codel_vars *vars)
- {
-- vars->drop_next = 0;
-- vars->first_above_time = 0;
-- vars->dropping = false; /* exit dropping state */
-- vars->count = 0;
-- vars->lastcount = 0;
-+ memset(vars, 0, sizeof(*vars));
- }
-
- static void codel_stats_init(struct codel_stats *stats)
-@@ -170,38 +169,37 @@ static void codel_stats_init(struct code
- stats->maxpacket = 256;
- }
-
--/* return interval/sqrt(x) with good precision
-- * relies on int_sqrt(unsigned long x) kernel implementation
-+/*
-+ * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
-+ * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2)
-+ *
-+ * Here, invsqrt is a fixed point number (< 1.0), 31bit mantissa)
- */
--static u32 codel_inv_sqrt(u32 _interval, u32 _x)
-+static void codel_Newton_step(struct codel_vars *vars)
- {
-- u64 interval = _interval;
-- unsigned long x = _x;
--
-- /* Scale operands for max precision */
-+ u32 invsqrt = vars->rec_inv_sqrt;
-+ u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 31;
-+ u64 val = (3LL << 31) - ((u64)vars->count * invsqrt2);
-
--#if BITS_PER_LONG == 64
-- x <<= 32; /* On 64bit arches, we can prescale x by 32bits */
-- interval <<= 16;
--#endif
-+ val = (val * invsqrt) >> 32;
-
-- while (x < (1UL << (BITS_PER_LONG - 2))) {
-- x <<= 2;
-- interval <<= 1;
-- }
-- do_div(interval, int_sqrt(x));
-- return (u32)interval;
-+ vars->rec_inv_sqrt = val;
- }
-
-+/*
-+ * CoDel control_law is t + interval/sqrt(count)
-+ * We maintain in rec_inv_sqrt the reciprocal value of sqrt(count) to avoid
-+ * both sqrt() and divide operation.
-+ */
- static codel_time_t codel_control_law(codel_time_t t,
- codel_time_t interval,
-- u32 count)
-+ u32 rec_inv_sqrt)
- {
-- return t + codel_inv_sqrt(interval, count);
-+ return t + reciprocal_divide(interval, rec_inv_sqrt << 1);
- }
-
-
--static bool codel_should_drop(struct sk_buff *skb,
-+static bool codel_should_drop(const struct sk_buff *skb,
- unsigned int *backlog,
- struct codel_vars *vars,
- struct codel_params *params,
-@@ -274,14 +272,16 @@ static struct sk_buff *codel_dequeue(str
- */
- while (vars->dropping &&
- codel_time_after_eq(now, vars->drop_next)) {
-- if (++vars->count == 0) /* avoid zero divides */
-- vars->count = ~0U;
-+ vars->count++; /* dont care of possible wrap
-+ * since there is no more divide
-+ */
-+ codel_Newton_step(vars);
- if (params->ecn && INET_ECN_set_ce(skb)) {
- stats->ecn_mark++;
- vars->drop_next =
- codel_control_law(vars->drop_next,
- params->interval,
-- vars->count);
-+ vars->rec_inv_sqrt);
- goto end;
- }
- qdisc_drop(skb, sch);
-@@ -296,7 +296,7 @@ static struct sk_buff *codel_dequeue(str
- vars->drop_next =
- codel_control_law(vars->drop_next,
- params->interval,
-- vars->count);
-+ vars->rec_inv_sqrt);
- }
- }
- }
-@@ -319,12 +319,18 @@ static struct sk_buff *codel_dequeue(str
- if (codel_time_before(now - vars->drop_next,
- 16 * params->interval)) {
- vars->count = (vars->count - vars->lastcount) | 1;
-+ /* we dont care if rec_inv_sqrt approximation
-+ * is not very precise :
-+ * Next Newton steps will correct it quadratically.
-+ */
-+ codel_Newton_step(vars);
- } else {
- vars->count = 1;
-+ vars->rec_inv_sqrt = 0x7fffffff;
- }
- vars->lastcount = vars->count;
- vars->drop_next = codel_control_law(now, params->interval,
-- vars->count);
-+ vars->rec_inv_sqrt);
- }
- end:
- return skb;
+++ /dev/null
-From 6ff272c9ad65eda219cd975b9da2dbc31cc812ee Mon Sep 17 00:00:00 2001
-From: Eric Dumazet <eric.dumazet@gmail.com>
-Date: Sat, 12 May 2012 21:23:23 +0000
-Subject: [PATCH] codel: use u16 field instead of 31bits for rec_inv_sqrt
-
-commit 6ff272c9ad65eda219cd975b9da2dbc31cc812ee upstream.
-
-David pointed out gcc might generate poor code with 31bit fields.
-
-Using u16 is more than enough and permits a better code output.
-
-Also make the code intent more readable using constants, fixed point arithmetic
-not being trivial for everybody.
-
-Suggested-by: David Miller <davem@davemloft.net>
-Signed-off-by: Eric Dumazet <edumazet@google.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-
----
- include/net/codel.h | 25 +++++++++++++++----------
- 1 file changed, 15 insertions(+), 10 deletions(-)
-
---- a/include/net/codel.h
-+++ b/include/net/codel.h
-@@ -133,13 +133,17 @@ struct codel_params {
- struct codel_vars {
- u32 count;
- u32 lastcount;
-- bool dropping:1;
-- u32 rec_inv_sqrt:31;
-+ bool dropping;
-+ u16 rec_inv_sqrt;
- codel_time_t first_above_time;
- codel_time_t drop_next;
- codel_time_t ldelay;
- };
-
-+#define REC_INV_SQRT_BITS (8 * sizeof(u16)) /* or sizeof_in_bits(rec_inv_sqrt) */
-+/* needed shift to get a Q0.32 number from rec_inv_sqrt */
-+#define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS)
-+
- /**
- * struct codel_stats - contains codel shared variables and stats
- * @maxpacket: largest packet we've seen so far
-@@ -173,17 +177,18 @@ static void codel_stats_init(struct code
- * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
- * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2)
- *
-- * Here, invsqrt is a fixed point number (< 1.0), 31bit mantissa)
-+ * Here, invsqrt is a fixed point number (< 1.0), 32bit mantissa, aka Q0.32
- */
- static void codel_Newton_step(struct codel_vars *vars)
- {
-- u32 invsqrt = vars->rec_inv_sqrt;
-- u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 31;
-- u64 val = (3LL << 31) - ((u64)vars->count * invsqrt2);
-+ u32 invsqrt = ((u32)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT;
-+ u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 32;
-+ u64 val = (3LL << 32) - ((u64)vars->count * invsqrt2);
-
-- val = (val * invsqrt) >> 32;
-+ val >>= 2; /* avoid overflow in following multiply */
-+ val = (val * invsqrt) >> (32 - 2 + 1);
-
-- vars->rec_inv_sqrt = val;
-+ vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT;
- }
-
- /*
-@@ -195,7 +200,7 @@ static codel_time_t codel_control_law(co
- codel_time_t interval,
- u32 rec_inv_sqrt)
- {
-- return t + reciprocal_divide(interval, rec_inv_sqrt << 1);
-+ return t + reciprocal_divide(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT);
- }
-
-
-@@ -326,7 +331,7 @@ static struct sk_buff *codel_dequeue(str
- codel_Newton_step(vars);
- } else {
- vars->count = 1;
-- vars->rec_inv_sqrt = 0x7fffffff;
-+ vars->rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT;
- }
- vars->lastcount = vars->count;
- vars->drop_next = codel_control_law(now, params->interval,
+++ /dev/null
-From 4b549a2ef4bef9965d97cbd992ba67930cd3e0fe Mon Sep 17 00:00:00 2001
-From: Eric Dumazet <edumazet@google.com>
-Date: Fri, 11 May 2012 09:30:50 +0000
-Subject: [PATCH] fq_codel: Fair Queue Codel AQM
-
-commit 4b549a2ef4bef9965d97cbd992ba67930cd3e0fe upstream.
-
-Fair Queue Codel packet scheduler
-
-Principles :
-
-- Packets are classified (internal classifier or external) on flows.
-- This is a Stochastic model (as we use a hash, several flows might
- be hashed on same slot)
-- Each flow has a CoDel managed queue.
-- Flows are linked onto two (Round Robin) lists,
- so that new flows have priority on old ones.
-
-- For a given flow, packets are not reordered (CoDel uses a FIFO)
-- head drops only.
-- ECN capability is on by default.
-- Very low memory footprint (64 bytes per flow)
-
-tc qdisc ... fq_codel [ limit PACKETS ] [ flows number ]
- [ target TIME ] [ interval TIME ] [ noecn ]
- [ quantum BYTES ]
-
-defaults : 1024 flows, 10240 packets limit, quantum : device MTU
- target : 5ms (CoDel default)
- interval : 100ms (CoDel default)
-
-Impressive results on load :
-
-class htb 1:1 root leaf 10: prio 0 quantum 1514 rate 200000Kbit ceil 200000Kbit burst 1475b/8 mpu 0b overhead 0b cburst 1475b/8 mpu 0b overhead 0b level 0
- Sent 43304920109 bytes 33063109 pkt (dropped 0, overlimits 0 requeues 0)
- rate 201691Kbit 28595pps backlog 0b 312p requeues 0
- lended: 33063109 borrowed: 0 giants: 0
- tokens: -912 ctokens: -912
-
-class fq_codel 10:1735 parent 10:
- (dropped 1292, overlimits 0 requeues 0)
- backlog 15140b 10p requeues 0
- deficit 1514 count 1 lastcount 1 ldelay 7.1ms
-class fq_codel 10:4524 parent 10:
- (dropped 1291, overlimits 0 requeues 0)
- backlog 16654b 11p requeues 0
- deficit 1514 count 1 lastcount 1 ldelay 7.1ms
-class fq_codel 10:4e74 parent 10:
- (dropped 1290, overlimits 0 requeues 0)
- backlog 6056b 4p requeues 0
- deficit 1514 count 1 lastcount 1 ldelay 6.4ms dropping drop_next 92.0ms
-class fq_codel 10:628a parent 10:
- (dropped 1289, overlimits 0 requeues 0)
- backlog 7570b 5p requeues 0
- deficit 1514 count 1 lastcount 1 ldelay 5.4ms dropping drop_next 90.9ms
-class fq_codel 10:a4b3 parent 10:
- (dropped 302, overlimits 0 requeues 0)
- backlog 16654b 11p requeues 0
- deficit 1514 count 1 lastcount 1 ldelay 7.1ms
-class fq_codel 10:c3c2 parent 10:
- (dropped 1284, overlimits 0 requeues 0)
- backlog 13626b 9p requeues 0
- deficit 1514 count 1 lastcount 1 ldelay 5.9ms
-class fq_codel 10:d331 parent 10:
- (dropped 299, overlimits 0 requeues 0)
- backlog 15140b 10p requeues 0
- deficit 1514 count 1 lastcount 1 ldelay 7.0ms
-class fq_codel 10:d526 parent 10:
- (dropped 12160, overlimits 0 requeues 0)
- backlog 35870b 211p requeues 0
- deficit 1508 count 12160 lastcount 1 ldelay 15.3ms dropping drop_next 247us
-class fq_codel 10:e2c6 parent 10:
- (dropped 1288, overlimits 0 requeues 0)
- backlog 15140b 10p requeues 0
- deficit 1514 count 1 lastcount 1 ldelay 7.1ms
-class fq_codel 10:eab5 parent 10:
- (dropped 1285, overlimits 0 requeues 0)
- backlog 16654b 11p requeues 0
- deficit 1514 count 1 lastcount 1 ldelay 5.9ms
-class fq_codel 10:f220 parent 10:
- (dropped 1289, overlimits 0 requeues 0)
- backlog 15140b 10p requeues 0
- deficit 1514 count 1 lastcount 1 ldelay 7.1ms
-
-qdisc htb 1: root refcnt 6 r2q 10 default 1 direct_packets_stat 0 ver 3.17
- Sent 43331086547 bytes 33092812 pkt (dropped 0, overlimits 66063544 requeues 71)
- rate 201697Kbit 28602pps backlog 0b 260p requeues 71
-qdisc fq_codel 10: parent 1:1 limit 10240p flows 65536 target 5.0ms interval 100.0ms ecn
- Sent 43331086547 bytes 33092812 pkt (dropped 949359, overlimits 0 requeues 0)
- rate 201697Kbit 28602pps backlog 189352b 260p requeues 0
- maxpacket 1514 drop_overlimit 0 new_flow_count 5582 ecn_mark 125593
- new_flows_len 0 old_flows_len 11
-
-PING 172.30.42.18 (172.30.42.18) 56(84) bytes of data.
-64 bytes from 172.30.42.18: icmp_req=1 ttl=64 time=0.227 ms
-64 bytes from 172.30.42.18: icmp_req=2 ttl=64 time=0.165 ms
-64 bytes from 172.30.42.18: icmp_req=3 ttl=64 time=0.166 ms
-64 bytes from 172.30.42.18: icmp_req=4 ttl=64 time=0.151 ms
-64 bytes from 172.30.42.18: icmp_req=5 ttl=64 time=0.164 ms
-64 bytes from 172.30.42.18: icmp_req=6 ttl=64 time=0.172 ms
-64 bytes from 172.30.42.18: icmp_req=7 ttl=64 time=0.175 ms
-64 bytes from 172.30.42.18: icmp_req=8 ttl=64 time=0.183 ms
-64 bytes from 172.30.42.18: icmp_req=9 ttl=64 time=0.158 ms
-64 bytes from 172.30.42.18: icmp_req=10 ttl=64 time=0.200 ms
-
-10 packets transmitted, 10 received, 0% packet loss, time 8999ms
-rtt min/avg/max/mdev = 0.151/0.176/0.227/0.022 ms
-
-Much better than SFQ because of priority given to new flows, and fast
-path dirtying less cache lines.
-
-Signed-off-by: Eric Dumazet <edumazet@google.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-
----
- include/linux/pkt_sched.h | 54 +++
- net/sched/Kconfig | 11
- net/sched/Makefile | 1
- net/sched/sch_fq_codel.c | 624 ++++++++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 690 insertions(+)
-
---- a/include/linux/pkt_sched.h
-+++ b/include/linux/pkt_sched.h
-@@ -681,4 +681,58 @@ struct tc_codel_xstats {
- __u32 dropping; /* are we in dropping state ? */
- };
-
-+/* FQ_CODEL */
-+
-+enum {
-+ TCA_FQ_CODEL_UNSPEC,
-+ TCA_FQ_CODEL_TARGET,
-+ TCA_FQ_CODEL_LIMIT,
-+ TCA_FQ_CODEL_INTERVAL,
-+ TCA_FQ_CODEL_ECN,
-+ TCA_FQ_CODEL_FLOWS,
-+ TCA_FQ_CODEL_QUANTUM,
-+ __TCA_FQ_CODEL_MAX
-+};
-+
-+#define TCA_FQ_CODEL_MAX (__TCA_FQ_CODEL_MAX - 1)
-+
-+enum {
-+ TCA_FQ_CODEL_XSTATS_QDISC,
-+ TCA_FQ_CODEL_XSTATS_CLASS,
-+};
-+
-+struct tc_fq_codel_qd_stats {
-+ __u32 maxpacket; /* largest packet we've seen so far */
-+ __u32 drop_overlimit; /* number of time max qdisc
-+ * packet limit was hit
-+ */
-+ __u32 ecn_mark; /* number of packets we ECN marked
-+ * instead of being dropped
-+ */
-+ __u32 new_flow_count; /* number of time packets
-+ * created a 'new flow'
-+ */
-+ __u32 new_flows_len; /* count of flows in new list */
-+ __u32 old_flows_len; /* count of flows in old list */
-+};
-+
-+struct tc_fq_codel_cl_stats {
-+ __s32 deficit;
-+ __u32 ldelay; /* in-queue delay seen by most recently
-+ * dequeued packet
-+ */
-+ __u32 count;
-+ __u32 lastcount;
-+ __u32 dropping;
-+ __s32 drop_next;
-+};
-+
-+struct tc_fq_codel_xstats {
-+ __u32 type;
-+ union {
-+ struct tc_fq_codel_qd_stats qdisc_stats;
-+ struct tc_fq_codel_cl_stats class_stats;
-+ };
-+};
-+
- #endif
---- a/net/sched/Kconfig
-+++ b/net/sched/Kconfig
-@@ -261,6 +261,17 @@ config NET_SCH_CODEL
-
- If unsure, say N.
-
-+config NET_SCH_FQ_CODEL
-+ tristate "Fair Queue Controlled Delay AQM (FQ_CODEL)"
-+ help
-+ Say Y here if you want to use the FQ Controlled Delay (FQ_CODEL)
-+ packet scheduling algorithm.
-+
-+ To compile this driver as a module, choose M here: the module
-+ will be called sch_fq_codel.
-+
-+ If unsure, say N.
-+
- config NET_SCH_INGRESS
- tristate "Ingress Qdisc"
- depends on NET_CLS_ACT
---- a/net/sched/Makefile
-+++ b/net/sched/Makefile
-@@ -38,6 +38,7 @@ obj-$(CONFIG_NET_SCH_MQPRIO) += sch_mqpr
- obj-$(CONFIG_NET_SCH_CHOKE) += sch_choke.o
- obj-$(CONFIG_NET_SCH_QFQ) += sch_qfq.o
- obj-$(CONFIG_NET_SCH_CODEL) += sch_codel.o
-+obj-$(CONFIG_NET_SCH_FQ_CODEL) += sch_fq_codel.o
-
- obj-$(CONFIG_NET_CLS_U32) += cls_u32.o
- obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o
---- /dev/null
-+++ b/net/sched/sch_fq_codel.c
-@@ -0,0 +1,624 @@
-+/*
-+ * Fair Queue CoDel discipline
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * Copyright (C) 2012 Eric Dumazet <edumazet@google.com>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/jiffies.h>
-+#include <linux/string.h>
-+#include <linux/in.h>
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/skbuff.h>
-+#include <linux/jhash.h>
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+#include <net/netlink.h>
-+#include <net/pkt_sched.h>
-+#include <net/flow_keys.h>
-+#include <net/codel.h>
-+
-+/* Fair Queue CoDel.
-+ *
-+ * Principles :
-+ * Packets are classified (internal classifier or external) on flows.
-+ * This is a Stochastic model (as we use a hash, several flows
-+ * might be hashed on same slot)
-+ * Each flow has a CoDel managed queue.
-+ * Flows are linked onto two (Round Robin) lists,
-+ * so that new flows have priority on old ones.
-+ *
-+ * For a given flow, packets are not reordered (CoDel uses a FIFO)
-+ * head drops only.
-+ * ECN capability is on by default.
-+ * Low memory footprint (64 bytes per flow)
-+ */
-+
-+struct fq_codel_flow {
-+ struct sk_buff *head;
-+ struct sk_buff *tail;
-+ struct list_head flowchain;
-+ int deficit;
-+ u32 dropped; /* number of drops (or ECN marks) on this flow */
-+ struct codel_vars cvars;
-+}; /* please try to keep this structure <= 64 bytes */
-+
-+struct fq_codel_sched_data {
-+ struct tcf_proto *filter_list; /* optional external classifier */
-+ struct fq_codel_flow *flows; /* Flows table [flows_cnt] */
-+ u32 *backlogs; /* backlog table [flows_cnt] */
-+ u32 flows_cnt; /* number of flows */
-+ u32 perturbation; /* hash perturbation */
-+ u32 quantum; /* psched_mtu(qdisc_dev(sch)); */
-+ struct codel_params cparams;
-+ struct codel_stats cstats;
-+ u32 drop_overlimit;
-+ u32 new_flow_count;
-+
-+ struct list_head new_flows; /* list of new flows */
-+ struct list_head old_flows; /* list of old flows */
-+};
-+
-+static unsigned int fq_codel_hash(const struct fq_codel_sched_data *q,
-+ const struct sk_buff *skb)
-+{
-+ struct flow_keys keys;
-+ unsigned int hash;
-+
-+ skb_flow_dissect(skb, &keys);
-+ hash = jhash_3words((__force u32)keys.dst,
-+ (__force u32)keys.src ^ keys.ip_proto,
-+ (__force u32)keys.ports, q->perturbation);
-+ return ((u64)hash * q->flows_cnt) >> 32;
-+}
-+
-+static unsigned int fq_codel_classify(struct sk_buff *skb, struct Qdisc *sch,
-+ int *qerr)
-+{
-+ struct fq_codel_sched_data *q = qdisc_priv(sch);
-+ struct tcf_result res;
-+ int result;
-+
-+ if (TC_H_MAJ(skb->priority) == sch->handle &&
-+ TC_H_MIN(skb->priority) > 0 &&
-+ TC_H_MIN(skb->priority) <= q->flows_cnt)
-+ return TC_H_MIN(skb->priority);
-+
-+ if (!q->filter_list)
-+ return fq_codel_hash(q, skb) + 1;
-+
-+ *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
-+ result = tc_classify(skb, q->filter_list, &res);
-+ if (result >= 0) {
-+#ifdef CONFIG_NET_CLS_ACT
-+ switch (result) {
-+ case TC_ACT_STOLEN:
-+ case TC_ACT_QUEUED:
-+ *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
-+ case TC_ACT_SHOT:
-+ return 0;
-+ }
-+#endif
-+ if (TC_H_MIN(res.classid) <= q->flows_cnt)
-+ return TC_H_MIN(res.classid);
-+ }
-+ return 0;
-+}
-+
-+/* helper functions : might be changed when/if skb use a standard list_head */
-+
-+/* remove one skb from head of slot queue */
-+static inline struct sk_buff *dequeue_head(struct fq_codel_flow *flow)
-+{
-+ struct sk_buff *skb = flow->head;
-+
-+ flow->head = skb->next;
-+ skb->next = NULL;
-+ return skb;
-+}
-+
-+/* add skb to flow queue (tail add) */
-+static inline void flow_queue_add(struct fq_codel_flow *flow,
-+ struct sk_buff *skb)
-+{
-+ if (flow->head == NULL)
-+ flow->head = skb;
-+ else
-+ flow->tail->next = skb;
-+ flow->tail = skb;
-+ skb->next = NULL;
-+}
-+
-+static unsigned int fq_codel_drop(struct Qdisc *sch)
-+{
-+ struct fq_codel_sched_data *q = qdisc_priv(sch);
-+ struct sk_buff *skb;
-+ unsigned int maxbacklog = 0, idx = 0, i, len;
-+ struct fq_codel_flow *flow;
-+
-+ /* Queue is full! Find the fat flow and drop packet from it.
-+ * This might sound expensive, but with 1024 flows, we scan
-+ * 4KB of memory, and we dont need to handle a complex tree
-+ * in fast path (packet queue/enqueue) with many cache misses.
-+ */
-+ for (i = 0; i < q->flows_cnt; i++) {
-+ if (q->backlogs[i] > maxbacklog) {
-+ maxbacklog = q->backlogs[i];
-+ idx = i;
-+ }
-+ }
-+ flow = &q->flows[idx];
-+ skb = dequeue_head(flow);
-+ len = qdisc_pkt_len(skb);
-+ q->backlogs[idx] -= len;
-+ kfree_skb(skb);
-+ sch->q.qlen--;
-+ sch->qstats.drops++;
-+ sch->qstats.backlog -= len;
-+ flow->dropped++;
-+ return idx;
-+}
-+
-+static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
-+{
-+ struct fq_codel_sched_data *q = qdisc_priv(sch);
-+ unsigned int idx;
-+ struct fq_codel_flow *flow;
-+ int uninitialized_var(ret);
-+
-+ idx = fq_codel_classify(skb, sch, &ret);
-+ if (idx == 0) {
-+ if (ret & __NET_XMIT_BYPASS)
-+ sch->qstats.drops++;
-+ kfree_skb(skb);
-+ return ret;
-+ }
-+ idx--;
-+
-+ codel_set_enqueue_time(skb);
-+ flow = &q->flows[idx];
-+ flow_queue_add(flow, skb);
-+ q->backlogs[idx] += qdisc_pkt_len(skb);
-+ sch->qstats.backlog += qdisc_pkt_len(skb);
-+
-+ if (list_empty(&flow->flowchain)) {
-+ list_add_tail(&flow->flowchain, &q->new_flows);
-+ codel_vars_init(&flow->cvars);
-+ q->new_flow_count++;
-+ flow->deficit = q->quantum;
-+ flow->dropped = 0;
-+ }
-+ if (++sch->q.qlen < sch->limit)
-+ return NET_XMIT_SUCCESS;
-+
-+ q->drop_overlimit++;
-+ /* Return Congestion Notification only if we dropped a packet
-+ * from this flow.
-+ */
-+ if (fq_codel_drop(sch) == idx)
-+ return NET_XMIT_CN;
-+
-+ /* As we dropped a packet, better let upper stack know this */
-+ qdisc_tree_decrease_qlen(sch, 1);
-+ return NET_XMIT_SUCCESS;
-+}
-+
-+/* This is the specific function called from codel_dequeue()
-+ * to dequeue a packet from queue. Note: backlog is handled in
-+ * codel, we dont need to reduce it here.
-+ */
-+static struct sk_buff *dequeue(struct codel_vars *vars, struct Qdisc *sch)
-+{
-+ struct fq_codel_flow *flow;
-+ struct sk_buff *skb = NULL;
-+
-+ flow = container_of(vars, struct fq_codel_flow, cvars);
-+ if (flow->head) {
-+ skb = dequeue_head(flow);
-+ sch->qstats.backlog -= qdisc_pkt_len(skb);
-+ sch->q.qlen--;
-+ }
-+ return skb;
-+}
-+
-+static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch)
-+{
-+ struct fq_codel_sched_data *q = qdisc_priv(sch);
-+ struct sk_buff *skb;
-+ struct fq_codel_flow *flow;
-+ struct list_head *head;
-+ u32 prev_drop_count, prev_ecn_mark;
-+
-+begin:
-+ head = &q->new_flows;
-+ if (list_empty(head)) {
-+ head = &q->old_flows;
-+ if (list_empty(head))
-+ return NULL;
-+ }
-+ flow = list_first_entry(head, struct fq_codel_flow, flowchain);
-+
-+ if (flow->deficit <= 0) {
-+ flow->deficit += q->quantum;
-+ list_move_tail(&flow->flowchain, &q->old_flows);
-+ goto begin;
-+ }
-+
-+ prev_drop_count = q->cstats.drop_count;
-+ prev_ecn_mark = q->cstats.ecn_mark;
-+
-+ skb = codel_dequeue(sch, &q->cparams, &flow->cvars, &q->cstats,
-+ dequeue, &q->backlogs[flow - q->flows]);
-+
-+ flow->dropped += q->cstats.drop_count - prev_drop_count;
-+ flow->dropped += q->cstats.ecn_mark - prev_ecn_mark;
-+
-+ if (!skb) {
-+ /* force a pass through old_flows to prevent starvation */
-+ if ((head == &q->new_flows) && !list_empty(&q->old_flows))
-+ list_move_tail(&flow->flowchain, &q->old_flows);
-+ else
-+ list_del_init(&flow->flowchain);
-+ goto begin;
-+ }
-+ qdisc_bstats_update(sch, skb);
-+ flow->deficit -= qdisc_pkt_len(skb);
-+ /* We cant call qdisc_tree_decrease_qlen() if our qlen is 0,
-+ * or HTB crashes. Defer it for next round.
-+ */
-+ if (q->cstats.drop_count && sch->q.qlen) {
-+ qdisc_tree_decrease_qlen(sch, q->cstats.drop_count);
-+ q->cstats.drop_count = 0;
-+ }
-+ return skb;
-+}
-+
-+static void fq_codel_reset(struct Qdisc *sch)
-+{
-+ struct sk_buff *skb;
-+
-+ while ((skb = fq_codel_dequeue(sch)) != NULL)
-+ kfree_skb(skb);
-+}
-+
-+static const struct nla_policy fq_codel_policy[TCA_FQ_CODEL_MAX + 1] = {
-+ [TCA_FQ_CODEL_TARGET] = { .type = NLA_U32 },
-+ [TCA_FQ_CODEL_LIMIT] = { .type = NLA_U32 },
-+ [TCA_FQ_CODEL_INTERVAL] = { .type = NLA_U32 },
-+ [TCA_FQ_CODEL_ECN] = { .type = NLA_U32 },
-+ [TCA_FQ_CODEL_FLOWS] = { .type = NLA_U32 },
-+ [TCA_FQ_CODEL_QUANTUM] = { .type = NLA_U32 },
-+};
-+
-+static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt)
-+{
-+ struct fq_codel_sched_data *q = qdisc_priv(sch);
-+ struct nlattr *tb[TCA_FQ_CODEL_MAX + 1];
-+ int err;
-+
-+ if (!opt)
-+ return -EINVAL;
-+
-+ err = nla_parse_nested(tb, TCA_FQ_CODEL_MAX, opt, fq_codel_policy);
-+ if (err < 0)
-+ return err;
-+ if (tb[TCA_FQ_CODEL_FLOWS]) {
-+ if (q->flows)
-+ return -EINVAL;
-+ q->flows_cnt = nla_get_u32(tb[TCA_FQ_CODEL_FLOWS]);
-+ if (!q->flows_cnt ||
-+ q->flows_cnt > 65536)
-+ return -EINVAL;
-+ }
-+ sch_tree_lock(sch);
-+
-+ if (tb[TCA_FQ_CODEL_TARGET]) {
-+ u64 target = nla_get_u32(tb[TCA_FQ_CODEL_TARGET]);
-+
-+ q->cparams.target = (target * NSEC_PER_USEC) >> CODEL_SHIFT;
-+ }
-+
-+ if (tb[TCA_FQ_CODEL_INTERVAL]) {
-+ u64 interval = nla_get_u32(tb[TCA_FQ_CODEL_INTERVAL]);
-+
-+ q->cparams.interval = (interval * NSEC_PER_USEC) >> CODEL_SHIFT;
-+ }
-+
-+ if (tb[TCA_FQ_CODEL_LIMIT])
-+ sch->limit = nla_get_u32(tb[TCA_FQ_CODEL_LIMIT]);
-+
-+ if (tb[TCA_FQ_CODEL_ECN])
-+ q->cparams.ecn = !!nla_get_u32(tb[TCA_FQ_CODEL_ECN]);
-+
-+ if (tb[TCA_FQ_CODEL_QUANTUM])
-+ q->quantum = max(256U, nla_get_u32(tb[TCA_FQ_CODEL_QUANTUM]));
-+
-+ while (sch->q.qlen > sch->limit) {
-+ struct sk_buff *skb = fq_codel_dequeue(sch);
-+
-+ kfree_skb(skb);
-+ q->cstats.drop_count++;
-+ }
-+ qdisc_tree_decrease_qlen(sch, q->cstats.drop_count);
-+ q->cstats.drop_count = 0;
-+
-+ sch_tree_unlock(sch);
-+ return 0;
-+}
-+
-+static void *fq_codel_zalloc(size_t sz)
-+{
-+ void *ptr = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN);
-+
-+ if (!ptr)
-+ ptr = vzalloc(sz);
-+ return ptr;
-+}
-+
-+static void fq_codel_free(void *addr)
-+{
-+ if (addr) {
-+ if (is_vmalloc_addr(addr))
-+ vfree(addr);
-+ else
-+ kfree(addr);
-+ }
-+}
-+
-+static void fq_codel_destroy(struct Qdisc *sch)
-+{
-+ struct fq_codel_sched_data *q = qdisc_priv(sch);
-+
-+ tcf_destroy_chain(&q->filter_list);
-+ fq_codel_free(q->backlogs);
-+ fq_codel_free(q->flows);
-+}
-+
-+static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt)
-+{
-+ struct fq_codel_sched_data *q = qdisc_priv(sch);
-+ int i;
-+
-+ sch->limit = 10*1024;
-+ q->flows_cnt = 1024;
-+ q->quantum = psched_mtu(qdisc_dev(sch));
-+ q->perturbation = net_random();
-+ INIT_LIST_HEAD(&q->new_flows);
-+ INIT_LIST_HEAD(&q->old_flows);
-+ codel_params_init(&q->cparams);
-+ codel_stats_init(&q->cstats);
-+ q->cparams.ecn = true;
-+
-+ if (opt) {
-+ int err = fq_codel_change(sch, opt);
-+ if (err)
-+ return err;
-+ }
-+
-+ if (!q->flows) {
-+ q->flows = fq_codel_zalloc(q->flows_cnt *
-+ sizeof(struct fq_codel_flow));
-+ if (!q->flows)
-+ return -ENOMEM;
-+ q->backlogs = fq_codel_zalloc(q->flows_cnt * sizeof(u32));
-+ if (!q->backlogs) {
-+ fq_codel_free(q->flows);
-+ return -ENOMEM;
-+ }
-+ for (i = 0; i < q->flows_cnt; i++) {
-+ struct fq_codel_flow *flow = q->flows + i;
-+
-+ INIT_LIST_HEAD(&flow->flowchain);
-+ }
-+ }
-+ if (sch->limit >= 1)
-+ sch->flags |= TCQ_F_CAN_BYPASS;
-+ else
-+ sch->flags &= ~TCQ_F_CAN_BYPASS;
-+ return 0;
-+}
-+
-+static int fq_codel_dump(struct Qdisc *sch, struct sk_buff *skb)
-+{
-+ struct fq_codel_sched_data *q = qdisc_priv(sch);
-+ struct nlattr *opts;
-+
-+ opts = nla_nest_start(skb, TCA_OPTIONS);
-+ if (opts == NULL)
-+ goto nla_put_failure;
-+
-+ if (nla_put_u32(skb, TCA_FQ_CODEL_TARGET,
-+ codel_time_to_us(q->cparams.target)) ||
-+ nla_put_u32(skb, TCA_FQ_CODEL_LIMIT,
-+ sch->limit) ||
-+ nla_put_u32(skb, TCA_FQ_CODEL_INTERVAL,
-+ codel_time_to_us(q->cparams.interval)) ||
-+ nla_put_u32(skb, TCA_FQ_CODEL_ECN,
-+ q->cparams.ecn) ||
-+ nla_put_u32(skb, TCA_FQ_CODEL_QUANTUM,
-+ q->quantum) ||
-+ nla_put_u32(skb, TCA_FQ_CODEL_FLOWS,
-+ q->flows_cnt))
-+ goto nla_put_failure;
-+
-+ nla_nest_end(skb, opts);
-+ return skb->len;
-+
-+nla_put_failure:
-+ return -1;
-+}
-+
-+static int fq_codel_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
-+{
-+ struct fq_codel_sched_data *q = qdisc_priv(sch);
-+ struct tc_fq_codel_xstats st = {
-+ .type = TCA_FQ_CODEL_XSTATS_QDISC,
-+ .qdisc_stats.maxpacket = q->cstats.maxpacket,
-+ .qdisc_stats.drop_overlimit = q->drop_overlimit,
-+ .qdisc_stats.ecn_mark = q->cstats.ecn_mark,
-+ .qdisc_stats.new_flow_count = q->new_flow_count,
-+ };
-+ struct list_head *pos;
-+
-+ list_for_each(pos, &q->new_flows)
-+ st.qdisc_stats.new_flows_len++;
-+
-+ list_for_each(pos, &q->old_flows)
-+ st.qdisc_stats.old_flows_len++;
-+
-+ return gnet_stats_copy_app(d, &st, sizeof(st));
-+}
-+
-+static struct Qdisc *fq_codel_leaf(struct Qdisc *sch, unsigned long arg)
-+{
-+ return NULL;
-+}
-+
-+static unsigned long fq_codel_get(struct Qdisc *sch, u32 classid)
-+{
-+ return 0;
-+}
-+
-+static unsigned long fq_codel_bind(struct Qdisc *sch, unsigned long parent,
-+ u32 classid)
-+{
-+ /* we cannot bypass queue discipline anymore */
-+ sch->flags &= ~TCQ_F_CAN_BYPASS;
-+ return 0;
-+}
-+
-+static void fq_codel_put(struct Qdisc *q, unsigned long cl)
-+{
-+}
-+
-+static struct tcf_proto **fq_codel_find_tcf(struct Qdisc *sch, unsigned long cl)
-+{
-+ struct fq_codel_sched_data *q = qdisc_priv(sch);
-+
-+ if (cl)
-+ return NULL;
-+ return &q->filter_list;
-+}
-+
-+static int fq_codel_dump_class(struct Qdisc *sch, unsigned long cl,
-+ struct sk_buff *skb, struct tcmsg *tcm)
-+{
-+ tcm->tcm_handle |= TC_H_MIN(cl);
-+ return 0;
-+}
-+
-+static int fq_codel_dump_class_stats(struct Qdisc *sch, unsigned long cl,
-+ struct gnet_dump *d)
-+{
-+ struct fq_codel_sched_data *q = qdisc_priv(sch);
-+ u32 idx = cl - 1;
-+ struct gnet_stats_queue qs = { 0 };
-+ struct tc_fq_codel_xstats xstats;
-+
-+ if (idx < q->flows_cnt) {
-+ const struct fq_codel_flow *flow = &q->flows[idx];
-+ const struct sk_buff *skb = flow->head;
-+
-+ memset(&xstats, 0, sizeof(xstats));
-+ xstats.type = TCA_FQ_CODEL_XSTATS_CLASS;
-+ xstats.class_stats.deficit = flow->deficit;
-+ xstats.class_stats.ldelay =
-+ codel_time_to_us(flow->cvars.ldelay);
-+ xstats.class_stats.count = flow->cvars.count;
-+ xstats.class_stats.lastcount = flow->cvars.lastcount;
-+ xstats.class_stats.dropping = flow->cvars.dropping;
-+ if (flow->cvars.dropping) {
-+ codel_tdiff_t delta = flow->cvars.drop_next -
-+ codel_get_time();
-+
-+ xstats.class_stats.drop_next = (delta >= 0) ?
-+ codel_time_to_us(delta) :
-+ -codel_time_to_us(-delta);
-+ }
-+ while (skb) {
-+ qs.qlen++;
-+ skb = skb->next;
-+ }
-+ qs.backlog = q->backlogs[idx];
-+ qs.drops = flow->dropped;
-+ }
-+ if (gnet_stats_copy_queue(d, &qs) < 0)
-+ return -1;
-+ if (idx < q->flows_cnt)
-+ return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
-+ return 0;
-+}
-+
-+static void fq_codel_walk(struct Qdisc *sch, struct qdisc_walker *arg)
-+{
-+ struct fq_codel_sched_data *q = qdisc_priv(sch);
-+ unsigned int i;
-+
-+ if (arg->stop)
-+ return;
-+
-+ for (i = 0; i < q->flows_cnt; i++) {
-+ if (list_empty(&q->flows[i].flowchain) ||
-+ arg->count < arg->skip) {
-+ arg->count++;
-+ continue;
-+ }
-+ if (arg->fn(sch, i + 1, arg) < 0) {
-+ arg->stop = 1;
-+ break;
-+ }
-+ arg->count++;
-+ }
-+}
-+
-+static const struct Qdisc_class_ops fq_codel_class_ops = {
-+ .leaf = fq_codel_leaf,
-+ .get = fq_codel_get,
-+ .put = fq_codel_put,
-+ .tcf_chain = fq_codel_find_tcf,
-+ .bind_tcf = fq_codel_bind,
-+ .unbind_tcf = fq_codel_put,
-+ .dump = fq_codel_dump_class,
-+ .dump_stats = fq_codel_dump_class_stats,
-+ .walk = fq_codel_walk,
-+};
-+
-+static struct Qdisc_ops fq_codel_qdisc_ops __read_mostly = {
-+ .cl_ops = &fq_codel_class_ops,
-+ .id = "fq_codel",
-+ .priv_size = sizeof(struct fq_codel_sched_data),
-+ .enqueue = fq_codel_enqueue,
-+ .dequeue = fq_codel_dequeue,
-+ .peek = qdisc_peek_dequeued,
-+ .drop = fq_codel_drop,
-+ .init = fq_codel_init,
-+ .reset = fq_codel_reset,
-+ .destroy = fq_codel_destroy,
-+ .change = fq_codel_change,
-+ .dump = fq_codel_dump,
-+ .dump_stats = fq_codel_dump_stats,
-+ .owner = THIS_MODULE,
-+};
-+
-+static int __init fq_codel_module_init(void)
-+{
-+ return register_qdisc(&fq_codel_qdisc_ops);
-+}
-+
-+static void __exit fq_codel_module_exit(void)
-+{
-+ unregister_qdisc(&fq_codel_qdisc_ops);
-+}
-+
-+module_init(fq_codel_module_init)
-+module_exit(fq_codel_module_exit)
-+MODULE_AUTHOR("Eric Dumazet");
-+MODULE_LICENSE("GPL");
+++ /dev/null
-From 865ec5523dadbedefbc5710a68969f686a28d928 Mon Sep 17 00:00:00 2001
-From: Eric Dumazet <edumazet@google.com>
-Date: Wed, 16 May 2012 04:39:09 +0000
-Subject: [PATCH] fq_codel: should use qdisc backlog as threshold
-
-commit 865ec5523dadbedefbc5710a68969f686a28d928 upstream.
-
-codel_should_drop() logic allows a packet being not dropped if queue
-size is under max packet size.
-
-In fq_codel, we have two possible backlogs : The qdisc global one, and
-the flow local one.
-
-The meaningful one for codel_should_drop() should be the global backlog,
-not the per flow one, so that thin flows can have a non zero drop/mark
-probability.
-
-Signed-off-by: Eric Dumazet <edumazet@google.com>
-Cc: Dave Taht <dave.taht@bufferbloat.net>
-Cc: Kathleen Nichols <nichols@pollere.com>
-Cc: Van Jacobson <van@pollere.net>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-
----
- include/net/codel.h | 15 +++++++--------
- net/sched/sch_codel.c | 4 ++--
- net/sched/sch_fq_codel.c | 5 +++--
- 3 files changed, 12 insertions(+), 12 deletions(-)
-
---- a/include/net/codel.h
-+++ b/include/net/codel.h
-@@ -205,7 +205,7 @@ static codel_time_t codel_control_law(co
-
-
- static bool codel_should_drop(const struct sk_buff *skb,
-- unsigned int *backlog,
-+ struct Qdisc *sch,
- struct codel_vars *vars,
- struct codel_params *params,
- struct codel_stats *stats,
-@@ -219,13 +219,13 @@ static bool codel_should_drop(const stru
- }
-
- vars->ldelay = now - codel_get_enqueue_time(skb);
-- *backlog -= qdisc_pkt_len(skb);
-+ sch->qstats.backlog -= qdisc_pkt_len(skb);
-
- if (unlikely(qdisc_pkt_len(skb) > stats->maxpacket))
- stats->maxpacket = qdisc_pkt_len(skb);
-
- if (codel_time_before(vars->ldelay, params->target) ||
-- *backlog <= stats->maxpacket) {
-+ sch->qstats.backlog <= stats->maxpacket) {
- /* went below - stay below for at least interval */
- vars->first_above_time = 0;
- return false;
-@@ -249,8 +249,7 @@ static struct sk_buff *codel_dequeue(str
- struct codel_params *params,
- struct codel_vars *vars,
- struct codel_stats *stats,
-- codel_skb_dequeue_t dequeue_func,
-- u32 *backlog)
-+ codel_skb_dequeue_t dequeue_func)
- {
- struct sk_buff *skb = dequeue_func(vars, sch);
- codel_time_t now;
-@@ -261,7 +260,7 @@ static struct sk_buff *codel_dequeue(str
- return skb;
- }
- now = codel_get_time();
-- drop = codel_should_drop(skb, backlog, vars, params, stats, now);
-+ drop = codel_should_drop(skb, sch, vars, params, stats, now);
- if (vars->dropping) {
- if (!drop) {
- /* sojourn time below target - leave dropping state */
-@@ -292,7 +291,7 @@ static struct sk_buff *codel_dequeue(str
- qdisc_drop(skb, sch);
- stats->drop_count++;
- skb = dequeue_func(vars, sch);
-- if (!codel_should_drop(skb, backlog,
-+ if (!codel_should_drop(skb, sch,
- vars, params, stats, now)) {
- /* leave dropping state */
- vars->dropping = false;
-@@ -313,7 +312,7 @@ static struct sk_buff *codel_dequeue(str
- stats->drop_count++;
-
- skb = dequeue_func(vars, sch);
-- drop = codel_should_drop(skb, backlog, vars, params,
-+ drop = codel_should_drop(skb, sch, vars, params,
- stats, now);
- }
- vars->dropping = true;
---- a/net/sched/sch_codel.c
-+++ b/net/sched/sch_codel.c
-@@ -77,8 +77,8 @@ static struct sk_buff *codel_qdisc_deque
- struct codel_sched_data *q = qdisc_priv(sch);
- struct sk_buff *skb;
-
-- skb = codel_dequeue(sch, &q->params, &q->vars, &q->stats,
-- dequeue, &sch->qstats.backlog);
-+ skb = codel_dequeue(sch, &q->params, &q->vars, &q->stats, dequeue);
-+
- /* We cant call qdisc_tree_decrease_qlen() if our qlen is 0,
- * or HTB crashes. Defer it for next round.
- */
---- a/net/sched/sch_fq_codel.c
-+++ b/net/sched/sch_fq_codel.c
-@@ -217,13 +217,14 @@ static int fq_codel_enqueue(struct sk_bu
- */
- static struct sk_buff *dequeue(struct codel_vars *vars, struct Qdisc *sch)
- {
-+ struct fq_codel_sched_data *q = qdisc_priv(sch);
- struct fq_codel_flow *flow;
- struct sk_buff *skb = NULL;
-
- flow = container_of(vars, struct fq_codel_flow, cvars);
- if (flow->head) {
- skb = dequeue_head(flow);
-- sch->qstats.backlog -= qdisc_pkt_len(skb);
-+ q->backlogs[flow - q->flows] -= qdisc_pkt_len(skb);
- sch->q.qlen--;
- }
- return skb;
-@@ -256,7 +257,7 @@ begin:
- prev_ecn_mark = q->cstats.ecn_mark;
-
- skb = codel_dequeue(sch, &q->cparams, &flow->cvars, &q->cstats,
-- dequeue, &q->backlogs[flow - q->flows]);
-+ dequeue);
-
- flow->dropped += q->cstats.drop_count - prev_drop_count;
- flow->dropped += q->cstats.ecn_mark - prev_ecn_mark;
+++ /dev/null
-From ce5b4b977127ee20c3f9c3fd3637cd3796f649f5 Mon Sep 17 00:00:00 2001
-From: Geert Uytterhoeven <geert@linux-m68k.org>
-Date: Mon, 14 May 2012 09:47:05 +0000
-Subject: [PATCH] net/codel: Add missing #include <linux/prefetch.h>
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-commit ce5b4b977127ee20c3f9c3fd3637cd3796f649f5 upstream.
-
-m68k allmodconfig:
-
-net/sched/sch_codel.c: In function ‘dequeue’:
-net/sched/sch_codel.c:70: error: implicit declaration of function ‘prefetch’
-make[1]: *** [net/sched/sch_codel.o] Error 1
-
-Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
-Acked-by: Eric Dumazet <edumazet@google.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-
----
- net/sched/sch_codel.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/net/sched/sch_codel.c
-+++ b/net/sched/sch_codel.c
-@@ -46,6 +46,7 @@
- #include <linux/kernel.h>
- #include <linux/errno.h>
- #include <linux/skbuff.h>
-+#include <linux/prefetch.h>
- #include <net/pkt_sched.h>
- #include <net/codel.h>
-
+++ /dev/null
-From 669d67bf777def468970f2dcba1537edf3b2d329 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <levinsasha928@gmail.com>
-Date: Mon, 14 May 2012 11:57:06 +0000
-Subject: [PATCH] net: codel: fix build errors
-
-commit 669d67bf777def468970f2dcba1537edf3b2d329 upstream.
-
-Fix the following build error:
-
-net/sched/sch_fq_codel.c: In function 'fq_codel_dump_stats':
-net/sched/sch_fq_codel.c:464:3: error: unknown field 'qdisc_stats' specified in initializer
-net/sched/sch_fq_codel.c:464:3: warning: missing braces around initializer
-net/sched/sch_fq_codel.c:464:3: warning: (near initialization for 'st.<anonymous>')
-net/sched/sch_fq_codel.c:465:3: error: unknown field 'qdisc_stats' specified in initializer
-net/sched/sch_fq_codel.c:465:3: warning: excess elements in struct initializer
-net/sched/sch_fq_codel.c:465:3: warning: (near initialization for 'st')
-net/sched/sch_fq_codel.c:466:3: error: unknown field 'qdisc_stats' specified in initializer
-net/sched/sch_fq_codel.c:466:3: warning: excess elements in struct initializer
-net/sched/sch_fq_codel.c:466:3: warning: (near initialization for 'st')
-net/sched/sch_fq_codel.c:467:3: error: unknown field 'qdisc_stats' specified in initializer
-net/sched/sch_fq_codel.c:467:3: warning: excess elements in struct initializer
-net/sched/sch_fq_codel.c:467:3: warning: (near initialization for 'st')
-make[1]: *** [net/sched/sch_fq_codel.o] Error 1
-
-Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-
----
- net/sched/sch_fq_codel.c | 9 +++++----
- 1 file changed, 5 insertions(+), 4 deletions(-)
-
---- a/net/sched/sch_fq_codel.c
-+++ b/net/sched/sch_fq_codel.c
-@@ -461,13 +461,14 @@ static int fq_codel_dump_stats(struct Qd
- struct fq_codel_sched_data *q = qdisc_priv(sch);
- struct tc_fq_codel_xstats st = {
- .type = TCA_FQ_CODEL_XSTATS_QDISC,
-- .qdisc_stats.maxpacket = q->cstats.maxpacket,
-- .qdisc_stats.drop_overlimit = q->drop_overlimit,
-- .qdisc_stats.ecn_mark = q->cstats.ecn_mark,
-- .qdisc_stats.new_flow_count = q->new_flow_count,
- };
- struct list_head *pos;
-
-+ st.qdisc_stats.maxpacket = q->cstats.maxpacket;
-+ st.qdisc_stats.drop_overlimit = q->drop_overlimit;
-+ st.qdisc_stats.ecn_mark = q->cstats.ecn_mark;
-+ st.qdisc_stats.new_flow_count = q->new_flow_count;
-+
- list_for_each(pos, &q->new_flows)
- st.qdisc_stats.new_flows_len++;
-
+++ /dev/null
-From 7c960a26b2c7abeb31df195d81453f08bda401f1 Mon Sep 17 00:00:00 2001
-From: Eric Dumazet <edumazet@google.com>
-Date: Mon, 30 Apr 2012 23:11:05 +0000
-Subject: [PATCH] netem: add ECN capability
-
-commit e4ae004b84b315dd4b762e474f97403eac70f76a upstream.
-
-Add ECN (Explicit Congestion Notification) marking capability to netem
-
-tc qdisc add dev eth0 root netem drop 0.5 ecn
-
-Instead of dropping packets, try to ECN mark them.
-
-Signed-off-by: Eric Dumazet <edumazet@google.com>
-Cc: Neal Cardwell <ncardwell@google.com>
-Cc: Tom Herbert <therbert@google.com>
-Cc: Hagen Paul Pfeifer <hagen@jauu.net>
-Cc: Stephen Hemminger <shemminger@vyatta.com>
-Acked-by: Hagen Paul Pfeifer <hagen@jauu.net>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-
----
- include/linux/pkt_sched.h | 1 +
- net/sched/sch_netem.c | 18 +++++++++++++++---
- 2 files changed, 16 insertions(+), 3 deletions(-)
-
---- a/include/linux/pkt_sched.h
-+++ b/include/linux/pkt_sched.h
-@@ -509,6 +509,7 @@ enum {
- TCA_NETEM_CORRUPT,
- TCA_NETEM_LOSS,
- TCA_NETEM_RATE,
-+ TCA_NETEM_ECN,
- __TCA_NETEM_MAX,
- };
-
---- a/net/sched/sch_netem.c
-+++ b/net/sched/sch_netem.c
-@@ -26,6 +26,7 @@
-
- #include <net/netlink.h>
- #include <net/pkt_sched.h>
-+#include <net/inet_ecn.h>
-
- #define VERSION "1.3"
-
-@@ -78,6 +79,7 @@ struct netem_sched_data {
- psched_tdiff_t jitter;
-
- u32 loss;
-+ u32 ecn;
- u32 limit;
- u32 counter;
- u32 gap;
-@@ -366,9 +368,12 @@ static int netem_enqueue(struct sk_buff
- ++count;
-
- /* Drop packet? */
-- if (loss_event(q))
-- --count;
--
-+ if (loss_event(q)) {
-+ if (q->ecn && INET_ECN_set_ce(skb))
-+ sch->qstats.drops++; /* mark packet */
-+ else
-+ --count;
-+ }
- if (count == 0) {
- sch->qstats.drops++;
- kfree_skb(skb);
-@@ -692,6 +697,7 @@ static const struct nla_policy netem_pol
- [TCA_NETEM_CORRUPT] = { .len = sizeof(struct tc_netem_corrupt) },
- [TCA_NETEM_RATE] = { .len = sizeof(struct tc_netem_rate) },
- [TCA_NETEM_LOSS] = { .type = NLA_NESTED },
-+ [TCA_NETEM_ECN] = { .type = NLA_U32 },
- };
-
- static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
-@@ -762,6 +768,9 @@ static int netem_change(struct Qdisc *sc
- if (tb[TCA_NETEM_RATE])
- get_rate(sch, tb[TCA_NETEM_RATE]);
-
-+ if (tb[TCA_NETEM_ECN])
-+ q->ecn = nla_get_u32(tb[TCA_NETEM_ECN]);
-+
- q->loss_model = CLG_RANDOM;
- if (tb[TCA_NETEM_LOSS])
- ret = get_loss_clg(sch, tb[TCA_NETEM_LOSS]);
-@@ -881,6 +890,9 @@ static int netem_dump(struct Qdisc *sch,
- rate.cell_overhead = q->cell_overhead;
- NLA_PUT(skb, TCA_NETEM_RATE, sizeof(rate), &rate);
-
-+ if (q->ecn && nla_put_u32(skb, TCA_NETEM_ECN, q->ecn))
-+ goto nla_put_failure;
-+
- if (dump_loss_model(q, skb) != 0)
- goto nla_put_failure;
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:54:00 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:10 +0900
-Subject: [PATCH v2 53/58] ARM: DMA-Mapping: add function for setting coherent pool size from platform code
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-54-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-Some platforms might require to increase atomic coherent pool to make
-sure that their device will be able to allocate all their buffers from
-atomic context. This function can be also used to decrease atomic
-coherent pool size if coherent allocations are not used for the given
-sub-platform.
-
-Suggested-by: Josh Coombs <josh.coombs@gmail.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit 6e5267aa543817015edb4a65c66e15f9809f92bd)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/include/asm/dma-mapping.h | 7 +++++++
- arch/arm/mm/dma-mapping.c | 19 ++++++++++++++++++-
- 2 files changed, 25 insertions(+), 1 deletions(-)
-
-diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
-index a048033..b5745a8 100644
---- a/arch/arm/include/asm/dma-mapping.h
-+++ b/arch/arm/include/asm/dma-mapping.h
-@@ -203,6 +203,13 @@ static inline void dma_free_writecombine(struct device *dev, size_t size,
- }
-
- /*
-+ * This can be called during early boot to increase the size of the atomic
-+ * coherent DMA pool above the default value of 256KiB. It must be called
-+ * before postcore_initcall.
-+ */
-+extern void __init init_dma_coherent_pool_size(unsigned long size);
-+
-+/*
- * This can be called during boot to increase the size of the consistent
- * DMA region above it's default value of 2MB. It must be called before the
- * memory allocator is initialised, i.e. before any core_initcall.
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index 258da10..3ff2585 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -266,6 +266,8 @@ static void __dma_free_remap(void *cpu_addr, size_t size)
- vunmap(cpu_addr);
- }
-
-+#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K
-+
- struct dma_pool {
- size_t size;
- spinlock_t lock;
-@@ -276,7 +278,7 @@ struct dma_pool {
- };
-
- static struct dma_pool atomic_pool = {
-- .size = SZ_256K,
-+ .size = DEFAULT_DMA_COHERENT_POOL_SIZE,
- };
-
- static int __init early_coherent_pool(char *p)
-@@ -286,6 +288,21 @@ static int __init early_coherent_pool(char *p)
- }
- early_param("coherent_pool", early_coherent_pool);
-
-+void __init init_dma_coherent_pool_size(unsigned long size)
-+{
-+ /*
-+ * Catch any attempt to set the pool size too late.
-+ */
-+ BUG_ON(atomic_pool.vaddr);
-+
-+ /*
-+ * Set architecture specific coherent pool size only if
-+ * it has not been changed by kernel command line parameter.
-+ */
-+ if (atomic_pool.size == DEFAULT_DMA_COHERENT_POOL_SIZE)
-+ atomic_pool.size = size;
-+}
-+
- /*
- * Initialise the coherent pool for atomic allocations.
- */
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:04 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:48 +0900
-Subject: [PATCH v2 31/58] ARM: dma-mapping: Add missing static storage class specifier
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-32-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Sachin Kamat <sachin.kamat@linaro.org>
-
-Fixes the following sparse warnings:
-arch/arm/mm/dma-mapping.c:231:15: warning: symbol 'consistent_base' was not
-declared. Should it be static?
-arch/arm/mm/dma-mapping.c:326:8: warning: symbol 'coherent_pool_size' was not
-declared. Should it be static?
-
-Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit e53f517ff236a0ec5413ff3935c53406b69bc1e2)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/mm/dma-mapping.c | 4 ++--
- 1 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index 106c4c0..d766e42 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -228,7 +228,7 @@ static pte_t **consistent_pte;
-
- #define DEFAULT_CONSISTENT_DMA_SIZE SZ_2M
-
--unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE;
-+static unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE;
-
- void __init init_consistent_dma_size(unsigned long size)
- {
-@@ -321,7 +321,7 @@ static struct arm_vmregion_head coherent_head = {
- .vm_list = LIST_HEAD_INIT(coherent_head.vm_list),
- };
-
--size_t coherent_pool_size = DEFAULT_CONSISTENT_DMA_SIZE / 8;
-+static size_t coherent_pool_size = DEFAULT_CONSISTENT_DMA_SIZE / 8;
-
- static int __init early_coherent_pool(char *p)
- {
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:33 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:59 +0900
-Subject: [PATCH v2 42/58] ARM: dma-mapping: add more sanity checks in arm_dma_mmap()
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-43-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-Add some sanity checks and forbid mmaping of buffers into vma areas larger
-than allocated dma buffer.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit 50262a4bf38dd70486e9fce2b8235d5ae3e0f627)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mm/dma-mapping.c | 14 ++++++++++----
- 1 files changed, 10 insertions(+), 4 deletions(-)
-
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index d1dff4a3..6a94d17 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -611,16 +611,22 @@ int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
- {
- int ret = -ENXIO;
- #ifdef CONFIG_MMU
-+ unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-+ unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
- unsigned long pfn = dma_to_pfn(dev, dma_addr);
-+ unsigned long off = vma->vm_pgoff;
-+
- vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
-
- if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
- return ret;
-
-- ret = remap_pfn_range(vma, vma->vm_start,
-- pfn + vma->vm_pgoff,
-- vma->vm_end - vma->vm_start,
-- vma->vm_page_prot);
-+ if (off < nr_pages && nr_vma_pages <= (nr_pages - off)) {
-+ ret = remap_pfn_range(vma, vma->vm_start,
-+ pfn + off,
-+ vma->vm_end - vma->vm_start,
-+ vma->vm_page_prot);
-+ }
- #endif /* CONFIG_MMU */
-
- return ret;
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:58 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:45 +0900
-Subject: [PATCH v2 28/58] ARM: dma-mapping: add support for IOMMU mapper
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-29-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-This patch add a complete implementation of DMA-mapping API for
-devices which have IOMMU support.
-
-This implementation tries to optimize dma address space usage by remapping
-all possible physical memory chunks into a single dma address space chunk.
-
-DMA address space is managed on top of the bitmap stored in the
-dma_iommu_mapping structure stored in device->archdata. Platform setup
-code has to initialize parameters of the dma address space (base address,
-size, allocation precision order) with arm_iommu_create_mapping() function.
-To reduce the size of the bitmap, all allocations are aligned to the
-specified order of base 4 KiB pages.
-
-dma_alloc_* functions allocate physical memory in chunks, each with
-alloc_pages() function to avoid failing if the physical memory gets
-fragmented. In worst case the allocated buffer is composed of 4 KiB page
-chunks.
-
-dma_map_sg() function minimizes the total number of dma address space
-chunks by merging of physical memory chunks into one larger dma address
-space chunk. If requested chunk (scatter list entry) boundaries
-match physical page boundaries, most calls to dma_map_sg() requests will
-result in creating only one chunk in dma address space.
-
-dma_map_page() simply creates a mapping for the given page(s) in the dma
-address space.
-
-All dma functions also perform required cache operation like their
-counterparts from the arm linear physical memory mapping version.
-
-This patch contains code and fixes kindly provided by:
-- Krishna Reddy <vdumpa@nvidia.com>,
-- Andrzej Pietrasiewicz <andrzej.p@samsung.com>,
-- Hiroshi DOYU <hdoyu@nvidia.com>
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
-Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-Tested-By: Subash Patel <subash.ramaswamy@linaro.org>
-(cherry picked from commit 4ce63fcd919c32d22528e54dcd89506962933719)
-
-Conflicts:
-
- arch/arm/mm/dma-mapping.c
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/Kconfig | 8
- arch/arm/include/asm/device.h | 3
- arch/arm/include/asm/dma-iommu.h | 34 +
- arch/arm/mm/dma-mapping.c | 694 ++++++++++++++++++++++++++++++++++++++-
- arch/arm/mm/vmregion.h | 2
- 5 files changed, 736 insertions(+), 5 deletions(-)
- create mode 100644 arch/arm/include/asm/dma-iommu.h
-
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -48,6 +48,14 @@ config ARM
- config ARM_HAS_SG_CHAIN
- bool
-
-+config NEED_SG_DMA_LENGTH
-+ bool
-+
-+config ARM_DMA_USE_IOMMU
-+ select NEED_SG_DMA_LENGTH
-+ select ARM_HAS_SG_CHAIN
-+ bool
-+
- config HAVE_PWM
- bool
-
---- a/arch/arm/include/asm/device.h
-+++ b/arch/arm/include/asm/device.h
-@@ -14,6 +14,9 @@ struct dev_archdata {
- #ifdef CONFIG_IOMMU_API
- void *iommu; /* private IOMMU data */
- #endif
-+#ifdef CONFIG_ARM_DMA_USE_IOMMU
-+ struct dma_iommu_mapping *mapping;
-+#endif
- };
-
- struct omap_device;
---- /dev/null
-+++ b/arch/arm/include/asm/dma-iommu.h
-@@ -0,0 +1,34 @@
-+#ifndef ASMARM_DMA_IOMMU_H
-+#define ASMARM_DMA_IOMMU_H
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/mm_types.h>
-+#include <linux/scatterlist.h>
-+#include <linux/dma-debug.h>
-+#include <linux/kmemcheck.h>
-+
-+struct dma_iommu_mapping {
-+ /* iommu specific data */
-+ struct iommu_domain *domain;
-+
-+ void *bitmap;
-+ size_t bits;
-+ unsigned int order;
-+ dma_addr_t base;
-+
-+ spinlock_t lock;
-+ struct kref kref;
-+};
-+
-+struct dma_iommu_mapping *
-+arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size,
-+ int order);
-+
-+void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping);
-+
-+int arm_iommu_attach_device(struct device *dev,
-+ struct dma_iommu_mapping *mapping);
-+
-+#endif /* __KERNEL__ */
-+#endif
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -21,6 +21,8 @@
- #include <linux/highmem.h>
- #include <linux/memblock.h>
- #include <linux/slab.h>
-+#include <linux/iommu.h>
-+#include <linux/vmalloc.h>
-
- #include <asm/memory.h>
- #include <asm/highmem.h>
-@@ -28,6 +30,7 @@
- #include <asm/tlbflush.h>
- #include <asm/sizes.h>
- #include <asm/mach/arch.h>
-+#include <asm/dma-iommu.h>
- #include <asm/mach/map.h>
- #include <asm/system_info.h>
- #include <asm/dma-contiguous.h>
-@@ -168,9 +171,11 @@ static void __dma_clear_buffer(struct pa
- * lurking in the kernel direct-mapped region is invalidated.
- */
- ptr = page_address(page);
-- memset(ptr, 0, size);
-- dmac_flush_range(ptr, ptr + size);
-- outer_flush_range(__pa(ptr), __pa(ptr) + size);
-+ if (ptr) {
-+ memset(ptr, 0, size);
-+ dmac_flush_range(ptr, ptr + size);
-+ outer_flush_range(__pa(ptr), __pa(ptr) + size);
-+ }
- }
-
- /*
-@@ -263,8 +268,10 @@ static int __init consistent_init(void)
- unsigned long base = consistent_base;
- unsigned long num_ptes = (CONSISTENT_END - base) >> PMD_SHIFT;
-
-+#ifndef CONFIG_ARM_DMA_USE_IOMMU
- if (cpu_architecture() >= CPU_ARCH_ARMv6)
- return 0;
-+#endif
-
- consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL);
- if (!consistent_pte) {
-@@ -437,7 +444,7 @@ __dma_alloc_remap(struct page *page, siz
- u32 off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);
-
- pte = consistent_pte[idx] + off;
-- c->vm_pages = page;
-+ c->priv = page;
-
- do {
- BUG_ON(!pte_none(*pte));
-@@ -891,6 +898,9 @@ int arm_dma_map_sg(struct device *dev, s
- int i, j;
-
- for_each_sg(sg, s, nents, i) {
-+#ifdef CONFIG_NEED_SG_DMA_LENGTH
-+ s->dma_length = s->length;
-+#endif
- s->dma_address = ops->map_page(dev, sg_page(s), s->offset,
- s->length, dir, attrs);
- if (dma_mapping_error(dev, s->dma_address))
-@@ -999,3 +1009,679 @@ static int __init dma_debug_do_init(void
- return 0;
- }
- fs_initcall(dma_debug_do_init);
-+
-+#ifdef CONFIG_ARM_DMA_USE_IOMMU
-+
-+/* IOMMU */
-+
-+static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping,
-+ size_t size)
-+{
-+ unsigned int order = get_order(size);
-+ unsigned int align = 0;
-+ unsigned int count, start;
-+ unsigned long flags;
-+
-+ count = ((PAGE_ALIGN(size) >> PAGE_SHIFT) +
-+ (1 << mapping->order) - 1) >> mapping->order;
-+
-+ if (order > mapping->order)
-+ align = (1 << (order - mapping->order)) - 1;
-+
-+ spin_lock_irqsave(&mapping->lock, flags);
-+ start = bitmap_find_next_zero_area(mapping->bitmap, mapping->bits, 0,
-+ count, align);
-+ if (start > mapping->bits) {
-+ spin_unlock_irqrestore(&mapping->lock, flags);
-+ return DMA_ERROR_CODE;
-+ }
-+
-+ bitmap_set(mapping->bitmap, start, count);
-+ spin_unlock_irqrestore(&mapping->lock, flags);
-+
-+ return mapping->base + (start << (mapping->order + PAGE_SHIFT));
-+}
-+
-+static inline void __free_iova(struct dma_iommu_mapping *mapping,
-+ dma_addr_t addr, size_t size)
-+{
-+ unsigned int start = (addr - mapping->base) >>
-+ (mapping->order + PAGE_SHIFT);
-+ unsigned int count = ((size >> PAGE_SHIFT) +
-+ (1 << mapping->order) - 1) >> mapping->order;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&mapping->lock, flags);
-+ bitmap_clear(mapping->bitmap, start, count);
-+ spin_unlock_irqrestore(&mapping->lock, flags);
-+}
-+
-+static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t gfp)
-+{
-+ struct page **pages;
-+ int count = size >> PAGE_SHIFT;
-+ int array_size = count * sizeof(struct page *);
-+ int i = 0;
-+
-+ if (array_size <= PAGE_SIZE)
-+ pages = kzalloc(array_size, gfp);
-+ else
-+ pages = vzalloc(array_size);
-+ if (!pages)
-+ return NULL;
-+
-+ while (count) {
-+ int j, order = __ffs(count);
-+
-+ pages[i] = alloc_pages(gfp | __GFP_NOWARN, order);
-+ while (!pages[i] && order)
-+ pages[i] = alloc_pages(gfp | __GFP_NOWARN, --order);
-+ if (!pages[i])
-+ goto error;
-+
-+ if (order)
-+ split_page(pages[i], order);
-+ j = 1 << order;
-+ while (--j)
-+ pages[i + j] = pages[i] + j;
-+
-+ __dma_clear_buffer(pages[i], PAGE_SIZE << order);
-+ i += 1 << order;
-+ count -= 1 << order;
-+ }
-+
-+ return pages;
-+error:
-+ while (--i)
-+ if (pages[i])
-+ __free_pages(pages[i], 0);
-+ if (array_size < PAGE_SIZE)
-+ kfree(pages);
-+ else
-+ vfree(pages);
-+ return NULL;
-+}
-+
-+static int __iommu_free_buffer(struct device *dev, struct page **pages, size_t size)
-+{
-+ int count = size >> PAGE_SHIFT;
-+ int array_size = count * sizeof(struct page *);
-+ int i;
-+ for (i = 0; i < count; i++)
-+ if (pages[i])
-+ __free_pages(pages[i], 0);
-+ if (array_size < PAGE_SIZE)
-+ kfree(pages);
-+ else
-+ vfree(pages);
-+ return 0;
-+}
-+
-+/*
-+ * Create a CPU mapping for a specified pages
-+ */
-+static void *
-+__iommu_alloc_remap(struct page **pages, size_t size, gfp_t gfp, pgprot_t prot)
-+{
-+ struct arm_vmregion *c;
-+ size_t align;
-+ size_t count = size >> PAGE_SHIFT;
-+ int bit;
-+
-+ if (!consistent_pte[0]) {
-+ pr_err("%s: not initialised\n", __func__);
-+ dump_stack();
-+ return NULL;
-+ }
-+
-+ /*
-+ * Align the virtual region allocation - maximum alignment is
-+ * a section size, minimum is a page size. This helps reduce
-+ * fragmentation of the DMA space, and also prevents allocations
-+ * smaller than a section from crossing a section boundary.
-+ */
-+ bit = fls(size - 1);
-+ if (bit > SECTION_SHIFT)
-+ bit = SECTION_SHIFT;
-+ align = 1 << bit;
-+
-+ /*
-+ * Allocate a virtual address in the consistent mapping region.
-+ */
-+ c = arm_vmregion_alloc(&consistent_head, align, size,
-+ gfp & ~(__GFP_DMA | __GFP_HIGHMEM), NULL);
-+ if (c) {
-+ pte_t *pte;
-+ int idx = CONSISTENT_PTE_INDEX(c->vm_start);
-+ int i = 0;
-+ u32 off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);
-+
-+ pte = consistent_pte[idx] + off;
-+ c->priv = pages;
-+
-+ do {
-+ BUG_ON(!pte_none(*pte));
-+
-+ set_pte_ext(pte, mk_pte(pages[i], prot), 0);
-+ pte++;
-+ off++;
-+ i++;
-+ if (off >= PTRS_PER_PTE) {
-+ off = 0;
-+ pte = consistent_pte[++idx];
-+ }
-+ } while (i < count);
-+
-+ dsb();
-+
-+ return (void *)c->vm_start;
-+ }
-+ return NULL;
-+}
-+
-+/*
-+ * Create a mapping in device IO address space for specified pages
-+ */
-+static dma_addr_t
-+__iommu_create_mapping(struct device *dev, struct page **pages, size_t size)
-+{
-+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
-+ unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-+ dma_addr_t dma_addr, iova;
-+ int i, ret = DMA_ERROR_CODE;
-+
-+ dma_addr = __alloc_iova(mapping, size);
-+ if (dma_addr == DMA_ERROR_CODE)
-+ return dma_addr;
-+
-+ iova = dma_addr;
-+ for (i = 0; i < count; ) {
-+ unsigned int next_pfn = page_to_pfn(pages[i]) + 1;
-+ phys_addr_t phys = page_to_phys(pages[i]);
-+ unsigned int len, j;
-+
-+ for (j = i + 1; j < count; j++, next_pfn++)
-+ if (page_to_pfn(pages[j]) != next_pfn)
-+ break;
-+
-+ len = (j - i) << PAGE_SHIFT;
-+ ret = iommu_map(mapping->domain, iova, phys, len, 0);
-+ if (ret < 0)
-+ goto fail;
-+ iova += len;
-+ i = j;
-+ }
-+ return dma_addr;
-+fail:
-+ iommu_unmap(mapping->domain, dma_addr, iova-dma_addr);
-+ __free_iova(mapping, dma_addr, size);
-+ return DMA_ERROR_CODE;
-+}
-+
-+static int __iommu_remove_mapping(struct device *dev, dma_addr_t iova, size_t size)
-+{
-+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
-+
-+ /*
-+ * add optional in-page offset from iova to size and align
-+ * result to page size
-+ */
-+ size = PAGE_ALIGN((iova & ~PAGE_MASK) + size);
-+ iova &= PAGE_MASK;
-+
-+ iommu_unmap(mapping->domain, iova, size);
-+ __free_iova(mapping, iova, size);
-+ return 0;
-+}
-+
-+static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
-+ dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
-+{
-+ pgprot_t prot = __get_dma_pgprot(attrs, pgprot_kernel);
-+ struct page **pages;
-+ void *addr = NULL;
-+
-+ *handle = DMA_ERROR_CODE;
-+ size = PAGE_ALIGN(size);
-+
-+ pages = __iommu_alloc_buffer(dev, size, gfp);
-+ if (!pages)
-+ return NULL;
-+
-+ *handle = __iommu_create_mapping(dev, pages, size);
-+ if (*handle == DMA_ERROR_CODE)
-+ goto err_buffer;
-+
-+ addr = __iommu_alloc_remap(pages, size, gfp, prot);
-+ if (!addr)
-+ goto err_mapping;
-+
-+ return addr;
-+
-+err_mapping:
-+ __iommu_remove_mapping(dev, *handle, size);
-+err_buffer:
-+ __iommu_free_buffer(dev, pages, size);
-+ return NULL;
-+}
-+
-+static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
-+ void *cpu_addr, dma_addr_t dma_addr, size_t size,
-+ struct dma_attrs *attrs)
-+{
-+ struct arm_vmregion *c;
-+
-+ vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
-+ c = arm_vmregion_find(&consistent_head, (unsigned long)cpu_addr);
-+
-+ if (c) {
-+ struct page **pages = c->priv;
-+
-+ unsigned long uaddr = vma->vm_start;
-+ unsigned long usize = vma->vm_end - vma->vm_start;
-+ int i = 0;
-+
-+ do {
-+ int ret;
-+
-+ ret = vm_insert_page(vma, uaddr, pages[i++]);
-+ if (ret) {
-+ pr_err("Remapping memory, error: %d\n", ret);
-+ return ret;
-+ }
-+
-+ uaddr += PAGE_SIZE;
-+ usize -= PAGE_SIZE;
-+ } while (usize > 0);
-+ }
-+ return 0;
-+}
-+
-+/*
-+ * free a page as defined by the above mapping.
-+ * Must not be called with IRQs disabled.
-+ */
-+void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
-+ dma_addr_t handle, struct dma_attrs *attrs)
-+{
-+ struct arm_vmregion *c;
-+ size = PAGE_ALIGN(size);
-+
-+ c = arm_vmregion_find(&consistent_head, (unsigned long)cpu_addr);
-+ if (c) {
-+ struct page **pages = c->priv;
-+ __dma_free_remap(cpu_addr, size);
-+ __iommu_remove_mapping(dev, handle, size);
-+ __iommu_free_buffer(dev, pages, size);
-+ }
-+}
-+
-+/*
-+ * Map a part of the scatter-gather list into contiguous io address space
-+ */
-+static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
-+ size_t size, dma_addr_t *handle,
-+ enum dma_data_direction dir)
-+{
-+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
-+ dma_addr_t iova, iova_base;
-+ int ret = 0;
-+ unsigned int count;
-+ struct scatterlist *s;
-+
-+ size = PAGE_ALIGN(size);
-+ *handle = DMA_ERROR_CODE;
-+
-+ iova_base = iova = __alloc_iova(mapping, size);
-+ if (iova == DMA_ERROR_CODE)
-+ return -ENOMEM;
-+
-+ for (count = 0, s = sg; count < (size >> PAGE_SHIFT); s = sg_next(s)) {
-+ phys_addr_t phys = page_to_phys(sg_page(s));
-+ unsigned int len = PAGE_ALIGN(s->offset + s->length);
-+
-+ if (!arch_is_coherent())
-+ __dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir);
-+
-+ ret = iommu_map(mapping->domain, iova, phys, len, 0);
-+ if (ret < 0)
-+ goto fail;
-+ count += len >> PAGE_SHIFT;
-+ iova += len;
-+ }
-+ *handle = iova_base;
-+
-+ return 0;
-+fail:
-+ iommu_unmap(mapping->domain, iova_base, count * PAGE_SIZE);
-+ __free_iova(mapping, iova_base, size);
-+ return ret;
-+}
-+
-+/**
-+ * arm_iommu_map_sg - map a set of SG buffers for streaming mode DMA
-+ * @dev: valid struct device pointer
-+ * @sg: list of buffers
-+ * @nents: number of buffers to map
-+ * @dir: DMA transfer direction
-+ *
-+ * Map a set of buffers described by scatterlist in streaming mode for DMA.
-+ * The scatter gather list elements are merged together (if possible) and
-+ * tagged with the appropriate dma address and length. They are obtained via
-+ * sg_dma_{address,length}.
-+ */
-+int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-+ enum dma_data_direction dir, struct dma_attrs *attrs)
-+{
-+ struct scatterlist *s = sg, *dma = sg, *start = sg;
-+ int i, count = 0;
-+ unsigned int offset = s->offset;
-+ unsigned int size = s->offset + s->length;
-+ unsigned int max = dma_get_max_seg_size(dev);
-+
-+ for (i = 1; i < nents; i++) {
-+ s = sg_next(s);
-+
-+ s->dma_address = DMA_ERROR_CODE;
-+ s->dma_length = 0;
-+
-+ if (s->offset || (size & ~PAGE_MASK) || size + s->length > max) {
-+ if (__map_sg_chunk(dev, start, size, &dma->dma_address,
-+ dir) < 0)
-+ goto bad_mapping;
-+
-+ dma->dma_address += offset;
-+ dma->dma_length = size - offset;
-+
-+ size = offset = s->offset;
-+ start = s;
-+ dma = sg_next(dma);
-+ count += 1;
-+ }
-+ size += s->length;
-+ }
-+ if (__map_sg_chunk(dev, start, size, &dma->dma_address, dir) < 0)
-+ goto bad_mapping;
-+
-+ dma->dma_address += offset;
-+ dma->dma_length = size - offset;
-+
-+ return count+1;
-+
-+bad_mapping:
-+ for_each_sg(sg, s, count, i)
-+ __iommu_remove_mapping(dev, sg_dma_address(s), sg_dma_len(s));
-+ return 0;
-+}
-+
-+/**
-+ * arm_iommu_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
-+ * @dev: valid struct device pointer
-+ * @sg: list of buffers
-+ * @nents: number of buffers to unmap (same as was passed to dma_map_sg)
-+ * @dir: DMA transfer direction (same as was passed to dma_map_sg)
-+ *
-+ * Unmap a set of streaming mode DMA translations. Again, CPU access
-+ * rules concerning calls here are the same as for dma_unmap_single().
-+ */
-+void arm_iommu_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
-+ enum dma_data_direction dir, struct dma_attrs *attrs)
-+{
-+ struct scatterlist *s;
-+ int i;
-+
-+ for_each_sg(sg, s, nents, i) {
-+ if (sg_dma_len(s))
-+ __iommu_remove_mapping(dev, sg_dma_address(s),
-+ sg_dma_len(s));
-+ if (!arch_is_coherent())
-+ __dma_page_dev_to_cpu(sg_page(s), s->offset,
-+ s->length, dir);
-+ }
-+}
-+
-+/**
-+ * arm_iommu_sync_sg_for_cpu
-+ * @dev: valid struct device pointer
-+ * @sg: list of buffers
-+ * @nents: number of buffers to map (returned from dma_map_sg)
-+ * @dir: DMA transfer direction (same as was passed to dma_map_sg)
-+ */
-+void arm_iommu_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
-+ int nents, enum dma_data_direction dir)
-+{
-+ struct scatterlist *s;
-+ int i;
-+
-+ for_each_sg(sg, s, nents, i)
-+ if (!arch_is_coherent())
-+ __dma_page_dev_to_cpu(sg_page(s), s->offset, s->length, dir);
-+
-+}
-+
-+/**
-+ * arm_iommu_sync_sg_for_device
-+ * @dev: valid struct device pointer
-+ * @sg: list of buffers
-+ * @nents: number of buffers to map (returned from dma_map_sg)
-+ * @dir: DMA transfer direction (same as was passed to dma_map_sg)
-+ */
-+void arm_iommu_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
-+ int nents, enum dma_data_direction dir)
-+{
-+ struct scatterlist *s;
-+ int i;
-+
-+ for_each_sg(sg, s, nents, i)
-+ if (!arch_is_coherent())
-+ __dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir);
-+}
-+
-+
-+/**
-+ * arm_iommu_map_page
-+ * @dev: valid struct device pointer
-+ * @page: page that buffer resides in
-+ * @offset: offset into page for start of buffer
-+ * @size: size of buffer to map
-+ * @dir: DMA transfer direction
-+ *
-+ * IOMMU aware version of arm_dma_map_page()
-+ */
-+static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
-+ unsigned long offset, size_t size, enum dma_data_direction dir,
-+ struct dma_attrs *attrs)
-+{
-+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
-+ dma_addr_t dma_addr;
-+ int ret, len = PAGE_ALIGN(size + offset);
-+
-+ if (!arch_is_coherent())
-+ __dma_page_cpu_to_dev(page, offset, size, dir);
-+
-+ dma_addr = __alloc_iova(mapping, len);
-+ if (dma_addr == DMA_ERROR_CODE)
-+ return dma_addr;
-+
-+ ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, 0);
-+ if (ret < 0)
-+ goto fail;
-+
-+ return dma_addr + offset;
-+fail:
-+ __free_iova(mapping, dma_addr, len);
-+ return DMA_ERROR_CODE;
-+}
-+
-+/**
-+ * arm_iommu_unmap_page
-+ * @dev: valid struct device pointer
-+ * @handle: DMA address of buffer
-+ * @size: size of buffer (same as passed to dma_map_page)
-+ * @dir: DMA transfer direction (same as passed to dma_map_page)
-+ *
-+ * IOMMU aware version of arm_dma_unmap_page()
-+ */
-+static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
-+ size_t size, enum dma_data_direction dir,
-+ struct dma_attrs *attrs)
-+{
-+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
-+ dma_addr_t iova = handle & PAGE_MASK;
-+ struct page *page = phys_to_page(iommu_iova_to_phys(mapping->domain, iova));
-+ int offset = handle & ~PAGE_MASK;
-+ int len = PAGE_ALIGN(size + offset);
-+
-+ if (!iova)
-+ return;
-+
-+ if (!arch_is_coherent())
-+ __dma_page_dev_to_cpu(page, offset, size, dir);
-+
-+ iommu_unmap(mapping->domain, iova, len);
-+ __free_iova(mapping, iova, len);
-+}
-+
-+static void arm_iommu_sync_single_for_cpu(struct device *dev,
-+ dma_addr_t handle, size_t size, enum dma_data_direction dir)
-+{
-+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
-+ dma_addr_t iova = handle & PAGE_MASK;
-+ struct page *page = phys_to_page(iommu_iova_to_phys(mapping->domain, iova));
-+ unsigned int offset = handle & ~PAGE_MASK;
-+
-+ if (!iova)
-+ return;
-+
-+ if (!arch_is_coherent())
-+ __dma_page_dev_to_cpu(page, offset, size, dir);
-+}
-+
-+static void arm_iommu_sync_single_for_device(struct device *dev,
-+ dma_addr_t handle, size_t size, enum dma_data_direction dir)
-+{
-+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
-+ dma_addr_t iova = handle & PAGE_MASK;
-+ struct page *page = phys_to_page(iommu_iova_to_phys(mapping->domain, iova));
-+ unsigned int offset = handle & ~PAGE_MASK;
-+
-+ if (!iova)
-+ return;
-+
-+ __dma_page_cpu_to_dev(page, offset, size, dir);
-+}
-+
-+struct dma_map_ops iommu_ops = {
-+ .alloc = arm_iommu_alloc_attrs,
-+ .free = arm_iommu_free_attrs,
-+ .mmap = arm_iommu_mmap_attrs,
-+
-+ .map_page = arm_iommu_map_page,
-+ .unmap_page = arm_iommu_unmap_page,
-+ .sync_single_for_cpu = arm_iommu_sync_single_for_cpu,
-+ .sync_single_for_device = arm_iommu_sync_single_for_device,
-+
-+ .map_sg = arm_iommu_map_sg,
-+ .unmap_sg = arm_iommu_unmap_sg,
-+ .sync_sg_for_cpu = arm_iommu_sync_sg_for_cpu,
-+ .sync_sg_for_device = arm_iommu_sync_sg_for_device,
-+};
-+
-+/**
-+ * arm_iommu_create_mapping
-+ * @bus: pointer to the bus holding the client device (for IOMMU calls)
-+ * @base: start address of the valid IO address space
-+ * @size: size of the valid IO address space
-+ * @order: accuracy of the IO addresses allocations
-+ *
-+ * Creates a mapping structure which holds information about used/unused
-+ * IO address ranges, which is required to perform memory allocation and
-+ * mapping with IOMMU aware functions.
-+ *
-+ * The client device need to be attached to the mapping with
-+ * arm_iommu_attach_device function.
-+ */
-+struct dma_iommu_mapping *
-+arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size,
-+ int order)
-+{
-+ unsigned int count = size >> (PAGE_SHIFT + order);
-+ unsigned int bitmap_size = BITS_TO_LONGS(count) * sizeof(long);
-+ struct dma_iommu_mapping *mapping;
-+ int err = -ENOMEM;
-+
-+ if (!count)
-+ return ERR_PTR(-EINVAL);
-+
-+ mapping = kzalloc(sizeof(struct dma_iommu_mapping), GFP_KERNEL);
-+ if (!mapping)
-+ goto err;
-+
-+ mapping->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-+ if (!mapping->bitmap)
-+ goto err2;
-+
-+ mapping->base = base;
-+ mapping->bits = BITS_PER_BYTE * bitmap_size;
-+ mapping->order = order;
-+ spin_lock_init(&mapping->lock);
-+
-+ mapping->domain = iommu_domain_alloc(bus);
-+ if (!mapping->domain)
-+ goto err3;
-+
-+ kref_init(&mapping->kref);
-+ return mapping;
-+err3:
-+ kfree(mapping->bitmap);
-+err2:
-+ kfree(mapping);
-+err:
-+ return ERR_PTR(err);
-+}
-+
-+static void release_iommu_mapping(struct kref *kref)
-+{
-+ struct dma_iommu_mapping *mapping =
-+ container_of(kref, struct dma_iommu_mapping, kref);
-+
-+ iommu_domain_free(mapping->domain);
-+ kfree(mapping->bitmap);
-+ kfree(mapping);
-+}
-+
-+void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping)
-+{
-+ if (mapping)
-+ kref_put(&mapping->kref, release_iommu_mapping);
-+}
-+
-+/**
-+ * arm_iommu_attach_device
-+ * @dev: valid struct device pointer
-+ * @mapping: io address space mapping structure (returned from
-+ * arm_iommu_create_mapping)
-+ *
-+ * Attaches specified io address space mapping to the provided device,
-+ * this replaces the dma operations (dma_map_ops pointer) with the
-+ * IOMMU aware version. More than one client might be attached to
-+ * the same io address space mapping.
-+ */
-+int arm_iommu_attach_device(struct device *dev,
-+ struct dma_iommu_mapping *mapping)
-+{
-+ int err;
-+
-+ err = iommu_attach_device(mapping->domain, dev);
-+ if (err)
-+ return err;
-+
-+ kref_get(&mapping->kref);
-+ dev->archdata.mapping = mapping;
-+ set_dma_ops(dev, &iommu_ops);
-+
-+ pr_info("Attached IOMMU controller to %s device.\n", dev_name(dev));
-+ return 0;
-+}
-+
-+#endif
---- a/arch/arm/mm/vmregion.h
-+++ b/arch/arm/mm/vmregion.h
-@@ -17,7 +17,7 @@ struct arm_vmregion {
- struct list_head vm_list;
- unsigned long vm_start;
- unsigned long vm_end;
-- struct page *vm_pages;
-+ void *priv;
- int vm_active;
- const void *caller;
- };
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:54:10 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:14 +0900
-Subject: [PATCH v2 57/58] ARM: dma-mapping: atomic_pool with struct page **pages
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-58-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Hiroshi Doyu <hdoyu@nvidia.com>
-
-struct page **pages is necessary to align with non atomic path in
-__iommu_get_pages(). atomic_pool() has the intialized **pages instead
-of just *page.
-
-Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit 6b3fe47264262fa082897ebe8ae01041eae65e14)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mm/dma-mapping.c | 17 ++++++++++++++---
- 1 files changed, 14 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index dc16881..ba294a3 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -274,7 +274,7 @@ struct dma_pool {
- unsigned long *bitmap;
- unsigned long nr_pages;
- void *vaddr;
-- struct page *page;
-+ struct page **pages;
- };
-
- static struct dma_pool atomic_pool = {
-@@ -313,6 +313,7 @@ static int __init atomic_pool_init(void)
- unsigned long nr_pages = pool->size >> PAGE_SHIFT;
- unsigned long *bitmap;
- struct page *page;
-+ struct page **pages;
- void *ptr;
- int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
-
-@@ -320,21 +321,31 @@ static int __init atomic_pool_init(void)
- if (!bitmap)
- goto no_bitmap;
-
-+ pages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
-+ if (!pages)
-+ goto no_pages;
-+
- if (IS_ENABLED(CONFIG_CMA))
- ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page);
- else
- ptr = __alloc_remap_buffer(NULL, pool->size, GFP_KERNEL, prot,
- &page, NULL);
- if (ptr) {
-+ int i;
-+
-+ for (i = 0; i < nr_pages; i++)
-+ pages[i] = page + i;
-+
- spin_lock_init(&pool->lock);
- pool->vaddr = ptr;
-- pool->page = page;
-+ pool->pages = pages;
- pool->bitmap = bitmap;
- pool->nr_pages = nr_pages;
- pr_info("DMA: preallocated %u KiB pool for atomic coherent allocations\n",
- (unsigned)pool->size / 1024);
- return 0;
- }
-+no_pages:
- kfree(bitmap);
- no_bitmap:
- pr_err("DMA: failed to allocate %u KiB pool for atomic coherent allocation\n",
-@@ -459,7 +470,7 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page)
- if (pageno < pool->nr_pages) {
- bitmap_set(pool->bitmap, pageno, count);
- ptr = pool->vaddr + PAGE_SIZE * pageno;
-- *ret_page = pool->page + pageno;
-+ *ret_page = pool->pages[pageno];
- } else {
- pr_err_once("ERROR: %u KiB atomic DMA coherent pool is too small!\n"
- "Please increase it with coherent_pool= kernel parameter!\n",
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:53 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:07 +0900
-Subject: [PATCH v2 50/58] ARM: dma-mapping: fix atomic allocation alignment
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-51-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Aaro Koskinen <aaro.koskinen@iki.fi>
-
-The alignment mask is calculated incorrectly. Fixing the calculation
-makes strange hangs/lockups disappear during the boot with Amstrad E3
-and 3.6-rc1 kernel.
-
-Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit e4ea6918c93b9f59d34e8ca2124b2b64b1afe73b)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mm/dma-mapping.c | 6 +++---
- 1 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index 1ce34ba..80491d3 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -422,7 +422,7 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page)
- unsigned int pageno;
- unsigned long flags;
- void *ptr = NULL;
-- size_t align;
-+ unsigned long align_mask;
-
- if (!pool->vaddr) {
- WARN(1, "coherent pool not initialised!\n");
-@@ -434,11 +434,11 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page)
- * small, so align them to their order in pages, minimum is a page
- * size. This helps reduce fragmentation of the DMA space.
- */
-- align = PAGE_SIZE << get_order(size);
-+ align_mask = (1 << get_order(size)) - 1;
-
- spin_lock_irqsave(&pool->lock, flags);
- pageno = bitmap_find_next_zero_area(pool->bitmap, pool->nr_pages,
-- 0, count, (1 << align) - 1);
-+ 0, count, align_mask);
- if (pageno < pool->nr_pages) {
- bitmap_set(pool->bitmap, pageno, count);
- ptr = pool->vaddr + PAGE_SIZE * pageno;
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:48 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:05 +0900
-Subject: [PATCH v2 48/58] ARM: dma-mapping: fix buffer chunk allocation order
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-49-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-IOMMU-aware dma_alloc_attrs() implementation allocates buffers in
-power-of-two chunks to improve performance and take advantage of large
-page mappings provided by some IOMMU hardware. However current code, due
-to a subtle bug, allocated those chunks in the smallest-to-largest
-order, what completely killed all the advantages of using larger than
-page chunks. If a 4KiB chunk has been mapped as a first chunk, the
-consecutive chunks are not aligned correctly to the power-of-two which
-match their size and IOMMU drivers were not able to use internal
-mappings of size other than the 4KiB (largest common denominator of
-alignment and chunk size).
-
-This patch fixes this issue by changing to the correct largest-to-smallest
-chunk size allocation sequence.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit 593f47355467b9ef44293698817e2bdb347e2d11)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mm/dma-mapping.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -942,7 +942,7 @@ static struct page **__iommu_alloc_buffe
- return NULL;
-
- while (count) {
-- int j, order = __ffs(count);
-+ int j, order = __fls(count);
-
- pages[i] = alloc_pages(gfp | __GFP_NOWARN, order);
- while (!pages[i] && order)
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:10 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:50 +0900
-Subject: [PATCH v2 33/58] ARM: dma-mapping: fix debug messages in dmabounce code
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-34-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-This patch fixes the usage of uninitialized variables in dmabounce code
-intoduced by commit a227fb92 ('ARM: dma-mapping: remove offset parameter
-to prepare for generic dma_ops'):
-arch/arm/common/dmabounce.c: In function ‘dmabounce_sync_for_device’:
-arch/arm/common/dmabounce.c:409: warning: ‘off’ may be used uninitialized in this function
-arch/arm/common/dmabounce.c:407: note: ‘off’ was declared here
-arch/arm/common/dmabounce.c: In function ‘dmabounce_sync_for_cpu’:
-arch/arm/common/dmabounce.c:369: warning: ‘off’ may be used uninitialized in this function
-arch/arm/common/dmabounce.c:367: note: ‘off’ was declared here
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit fdb1117325ad719dc39e81209bc622d511db70e0)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/common/dmabounce.c | 16 ++++++++--------
- 1 files changed, 8 insertions(+), 8 deletions(-)
-
-diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
-index 9d7eb53..aa07f59 100644
---- a/arch/arm/common/dmabounce.c
-+++ b/arch/arm/common/dmabounce.c
-@@ -366,8 +366,8 @@ static int __dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
- struct safe_buffer *buf;
- unsigned long off;
-
-- dev_dbg(dev, "%s(dma=%#x,off=%#lx,sz=%zx,dir=%x)\n",
-- __func__, addr, off, sz, dir);
-+ dev_dbg(dev, "%s(dma=%#x,sz=%zx,dir=%x)\n",
-+ __func__, addr, sz, dir);
-
- buf = find_safe_buffer_dev(dev, addr, __func__);
- if (!buf)
-@@ -377,8 +377,8 @@ static int __dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
-
- BUG_ON(buf->direction != dir);
-
-- dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
-- __func__, buf->ptr, virt_to_dma(dev, buf->ptr),
-+ dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x off=%#lx) mapped to %p (dma=%#x)\n",
-+ __func__, buf->ptr, virt_to_dma(dev, buf->ptr), off,
- buf->safe, buf->safe_dma_addr);
-
- DO_STATS(dev->archdata.dmabounce->bounce_count++);
-@@ -406,8 +406,8 @@ static int __dmabounce_sync_for_device(struct device *dev, dma_addr_t addr,
- struct safe_buffer *buf;
- unsigned long off;
-
-- dev_dbg(dev, "%s(dma=%#x,off=%#lx,sz=%zx,dir=%x)\n",
-- __func__, addr, off, sz, dir);
-+ dev_dbg(dev, "%s(dma=%#x,sz=%zx,dir=%x)\n",
-+ __func__, addr, sz, dir);
-
- buf = find_safe_buffer_dev(dev, addr, __func__);
- if (!buf)
-@@ -417,8 +417,8 @@ static int __dmabounce_sync_for_device(struct device *dev, dma_addr_t addr,
-
- BUG_ON(buf->direction != dir);
-
-- dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
-- __func__, buf->ptr, virt_to_dma(dev, buf->ptr),
-+ dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x off=%#lx) mapped to %p (dma=%#x)\n",
-+ __func__, buf->ptr, virt_to_dma(dev, buf->ptr), off,
- buf->safe, buf->safe_dma_addr);
-
- DO_STATS(dev->archdata.dmabounce->bounce_count++);
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:35 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:00 +0900
-Subject: [PATCH v2 43/58] ARM: dma-mapping: fix error path for memory allocation failure
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-44-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-This patch fixes incorrect check in error path. When the allocation of
-first page fails, the kernel ops appears due to accessing -1 element of
-the pages array.
-
-Reported-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit 9fa8af91f0679f2abbebe1382b937264f3a8b981)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mm/dma-mapping.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -963,7 +963,7 @@ static struct page **__iommu_alloc_buffe
-
- return pages;
- error:
-- while (--i)
-+ while (i--)
- if (pages[i])
- __free_pages(pages[i], 0);
- if (array_size <= PAGE_SIZE)
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:56 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:08 +0900
-Subject: [PATCH v2 51/58] ARM: dma-mapping: fix incorrect freeing of atomic allocations
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-52-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Aaro Koskinen <aaro.koskinen@iki.fi>
-
-Commit e9da6e9905e639b0f842a244bc770b48ad0523e9 (ARM: dma-mapping:
-remove custom consistent dma region) changed the way atomic allocations
-are handled. However, arm_dma_free() was not modified accordingly, and
-as a result freeing of atomic allocations does not work correctly when
-CMA is disabled. Memory is leaked and following WARNINGs are seen:
-
-[ 57.698911] ------------[ cut here ]------------
-[ 57.753518] WARNING: at arch/arm/mm/dma-mapping.c:263 arm_dma_free+0x88/0xe4()
-[ 57.811473] trying to free invalid coherent area: e0848000
-[ 57.867398] Modules linked in: sata_mv(-)
-[ 57.921373] [<c000d270>] (unwind_backtrace+0x0/0xf0) from [<c0015430>] (warn_slowpath_common+0x50/0x68)
-[ 58.033924] [<c0015430>] (warn_slowpath_common+0x50/0x68) from [<c00154dc>] (warn_slowpath_fmt+0x30/0x40)
-[ 58.152024] [<c00154dc>] (warn_slowpath_fmt+0x30/0x40) from [<c000dc18>] (arm_dma_free+0x88/0xe4)
-[ 58.219592] [<c000dc18>] (arm_dma_free+0x88/0xe4) from [<c008fa30>] (dma_pool_destroy+0x100/0x148)
-[ 58.345526] [<c008fa30>] (dma_pool_destroy+0x100/0x148) from [<c019a64c>] (release_nodes+0x144/0x218)
-[ 58.475782] [<c019a64c>] (release_nodes+0x144/0x218) from [<c0197e10>] (__device_release_driver+0x60/0xb8)
-[ 58.614260] [<c0197e10>] (__device_release_driver+0x60/0xb8) from [<c0198608>] (driver_detach+0xd8/0xec)
-[ 58.756527] [<c0198608>] (driver_detach+0xd8/0xec) from [<c0197c54>] (bus_remove_driver+0x7c/0xc4)
-[ 58.901648] [<c0197c54>] (bus_remove_driver+0x7c/0xc4) from [<c004bfac>] (sys_delete_module+0x19c/0x220)
-[ 59.051447] [<c004bfac>] (sys_delete_module+0x19c/0x220) from [<c0009140>] (ret_fast_syscall+0x0/0x2c)
-[ 59.207996] ---[ end trace 0745420412c0325a ]---
-[ 59.287110] ------------[ cut here ]------------
-[ 59.366324] WARNING: at arch/arm/mm/dma-mapping.c:263 arm_dma_free+0x88/0xe4()
-[ 59.450511] trying to free invalid coherent area: e0847000
-[ 59.534357] Modules linked in: sata_mv(-)
-[ 59.616785] [<c000d270>] (unwind_backtrace+0x0/0xf0) from [<c0015430>] (warn_slowpath_common+0x50/0x68)
-[ 59.790030] [<c0015430>] (warn_slowpath_common+0x50/0x68) from [<c00154dc>] (warn_slowpath_fmt+0x30/0x40)
-[ 59.972322] [<c00154dc>] (warn_slowpath_fmt+0x30/0x40) from [<c000dc18>] (arm_dma_free+0x88/0xe4)
-[ 60.070701] [<c000dc18>] (arm_dma_free+0x88/0xe4) from [<c008fa30>] (dma_pool_destroy+0x100/0x148)
-[ 60.256817] [<c008fa30>] (dma_pool_destroy+0x100/0x148) from [<c019a64c>] (release_nodes+0x144/0x218)
-[ 60.445201] [<c019a64c>] (release_nodes+0x144/0x218) from [<c0197e10>] (__device_release_driver+0x60/0xb8)
-[ 60.634148] [<c0197e10>] (__device_release_driver+0x60/0xb8) from [<c0198608>] (driver_detach+0xd8/0xec)
-[ 60.823623] [<c0198608>] (driver_detach+0xd8/0xec) from [<c0197c54>] (bus_remove_driver+0x7c/0xc4)
-[ 61.013268] [<c0197c54>] (bus_remove_driver+0x7c/0xc4) from [<c004bfac>] (sys_delete_module+0x19c/0x220)
-[ 61.203472] [<c004bfac>] (sys_delete_module+0x19c/0x220) from [<c0009140>] (ret_fast_syscall+0x0/0x2c)
-[ 61.393390] ---[ end trace 0745420412c0325b ]---
-
-The patch fixes this.
-
-Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit d9e0d149b5dcc2ef4688afc572b9906bcda941ef)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mm/dma-mapping.c | 4 ++--
- 1 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index 80491d3..258da10 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -647,12 +647,12 @@ void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
-
- if (arch_is_coherent() || nommu()) {
- __dma_free_buffer(page, size);
-+ } else if (__free_from_pool(cpu_addr, size)) {
-+ return;
- } else if (!IS_ENABLED(CONFIG_CMA)) {
- __dma_free_remap(cpu_addr, size);
- __dma_free_buffer(page, size);
- } else {
-- if (__free_from_pool(cpu_addr, size))
-- return;
- /*
- * Non-atomic allocations cannot be freed with IRQs disabled
- */
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:54:13 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:15 +0900
-Subject: [PATCH v2 58/58] ARM: dma-mapping: Fix potential memory leak in atomic_pool_init()
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-59-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Sachin Kamat <sachin.kamat@linaro.org>
-
-When either of __alloc_from_contiguous or __alloc_remap_buffer fails
-to provide a valid pointer, allocated memory is freed up and an error
-is returned. 'pages' was however not freed before returning error.
-
-Cc: Arnd Bergmann <arnd@arndb.de>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit ec10665cbf271fb1f60daeb194ad4f2cdcdc59d9)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mm/dma-mapping.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -345,6 +345,8 @@ static int __init atomic_pool_init(void)
- (unsigned)pool->size / 1024);
- return 0;
- }
-+
-+ kfree(pages);
- no_pages:
- kfree(bitmap);
- no_bitmap:
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:47 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:41 +0900
-Subject: [PATCH v2 24/58] ARM: dma-mapping: implement dma sg methods on top of any generic dma ops
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-25-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-This patch converts all dma_sg methods to be generic (independent of the
-current DMA mapping implementation for ARM architecture). All dma sg
-operations are now implemented on top of respective
-dma_map_page/dma_sync_single_for* operations from dma_map_ops structure.
-
-Before this patch there were custom methods for all scatter/gather
-related operations. They iterated over the whole scatter list and called
-cache related operations directly (which in turn checked if we use dma
-bounce code or not and called respective version). This patch changes
-them not to use such shortcut. Instead it provides similar loop over
-scatter list and calls methods from the device's dma_map_ops structure.
-This enables us to use device dependent implementations of cache related
-operations (direct linear or dma bounce) depending on the provided
-dma_map_ops structure.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
-Tested-By: Subash Patel <subash.ramaswamy@linaro.org>
-(cherry picked from commit 2a550e73d3e5f040a3e8eb733c942ab352eafb36)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/mm/dma-mapping.c | 43 +++++++++++++++++++------------------------
- 1 file changed, 19 insertions(+), 24 deletions(-)
-
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -860,7 +860,7 @@ void ___dma_page_dev_to_cpu(struct page
- EXPORT_SYMBOL(___dma_page_dev_to_cpu);
-
- /**
-- * dma_map_sg - map a set of SG buffers for streaming mode DMA
-+ * arm_dma_map_sg - map a set of SG buffers for streaming mode DMA
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @sg: list of buffers
- * @nents: number of buffers to map
-@@ -878,12 +878,13 @@ EXPORT_SYMBOL(___dma_page_dev_to_cpu);
- int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, struct dma_attrs *attrs)
- {
-+ struct dma_map_ops *ops = get_dma_ops(dev);
- struct scatterlist *s;
- int i, j;
-
- for_each_sg(sg, s, nents, i) {
-- s->dma_address = __dma_map_page(dev, sg_page(s), s->offset,
-- s->length, dir);
-+ s->dma_address = ops->map_page(dev, sg_page(s), s->offset,
-+ s->length, dir, attrs);
- if (dma_mapping_error(dev, s->dma_address))
- goto bad_mapping;
- }
-@@ -891,12 +892,12 @@ int arm_dma_map_sg(struct device *dev, s
-
- bad_mapping:
- for_each_sg(sg, s, i, j)
-- __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
-+ ops->unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir, attrs);
- return 0;
- }
-
- /**
-- * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
-+ * arm_dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @sg: list of buffers
- * @nents: number of buffers to unmap (same as was passed to dma_map_sg)
-@@ -908,15 +909,17 @@ int arm_dma_map_sg(struct device *dev, s
- void arm_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, struct dma_attrs *attrs)
- {
-+ struct dma_map_ops *ops = get_dma_ops(dev);
- struct scatterlist *s;
-+
- int i;
-
- for_each_sg(sg, s, nents, i)
-- __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
-+ ops->unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir, attrs);
- }
-
- /**
-- * dma_sync_sg_for_cpu
-+ * arm_dma_sync_sg_for_cpu
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @sg: list of buffers
- * @nents: number of buffers to map (returned from dma_map_sg)
-@@ -925,21 +928,17 @@ void arm_dma_unmap_sg(struct device *dev
- void arm_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir)
- {
-+ struct dma_map_ops *ops = get_dma_ops(dev);
- struct scatterlist *s;
- int i;
-
-- for_each_sg(sg, s, nents, i) {
-- if (!dmabounce_sync_for_cpu(dev, sg_dma_address(s),
-- sg_dma_len(s), dir))
-- continue;
--
-- __dma_page_dev_to_cpu(sg_page(s), s->offset,
-- s->length, dir);
-- }
-+ for_each_sg(sg, s, nents, i)
-+ ops->sync_single_for_cpu(dev, sg_dma_address(s), s->length,
-+ dir);
- }
-
- /**
-- * dma_sync_sg_for_device
-+ * arm_dma_sync_sg_for_device
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @sg: list of buffers
- * @nents: number of buffers to map (returned from dma_map_sg)
-@@ -948,17 +947,13 @@ void arm_dma_sync_sg_for_cpu(struct devi
- void arm_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir)
- {
-+ struct dma_map_ops *ops = get_dma_ops(dev);
- struct scatterlist *s;
- int i;
-
-- for_each_sg(sg, s, nents, i) {
-- if (!dmabounce_sync_for_device(dev, sg_dma_address(s),
-- sg_dma_len(s), dir))
-- continue;
--
-- __dma_page_cpu_to_dev(sg_page(s), s->offset,
-- s->length, dir);
-- }
-+ for_each_sg(sg, s, nents, i)
-+ ops->sync_single_for_device(dev, sg_dma_address(s), s->length,
-+ dir);
- }
-
- /*
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:39 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:38 +0900
-Subject: [PATCH v2 21/58] ARM: dma-mapping: introduce DMA_ERROR_CODE constant
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-22-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-Replace all uses of ~0 with DMA_ERROR_CODE, what should make the code
-easier to read.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
-Tested-By: Subash Patel <subash.ramaswamy@linaro.org>
-(cherry picked from commit 553ac78877242b6d8b591323731df304140d0f99)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/common/dmabounce.c | 6 +++---
- arch/arm/include/asm/dma-mapping.h | 4 +++-
- arch/arm/mm/dma-mapping.c | 2 +-
- 3 files changed, 7 insertions(+), 5 deletions(-)
-
-diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
-index 595ecd29..210ad1b 100644
---- a/arch/arm/common/dmabounce.c
-+++ b/arch/arm/common/dmabounce.c
-@@ -254,7 +254,7 @@ static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
- if (buf == NULL) {
- dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
- __func__, ptr);
-- return ~0;
-+ return DMA_ERROR_CODE;
- }
-
- dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
-@@ -320,7 +320,7 @@ dma_addr_t __dma_map_page(struct device *dev, struct page *page,
-
- ret = needs_bounce(dev, dma_addr, size);
- if (ret < 0)
-- return ~0;
-+ return DMA_ERROR_CODE;
-
- if (ret == 0) {
- __dma_page_cpu_to_dev(page, offset, size, dir);
-@@ -329,7 +329,7 @@ dma_addr_t __dma_map_page(struct device *dev, struct page *page,
-
- if (PageHighMem(page)) {
- dev_err(dev, "DMA buffer bouncing of HIGHMEM pages is not supported\n");
-- return ~0;
-+ return DMA_ERROR_CODE;
- }
-
- return map_single(dev, page_address(page) + offset, size, dir);
-diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
-index cb3b7c9..6a838da 100644
---- a/arch/arm/include/asm/dma-mapping.h
-+++ b/arch/arm/include/asm/dma-mapping.h
-@@ -10,6 +10,8 @@
- #include <asm-generic/dma-coherent.h>
- #include <asm/memory.h>
-
-+#define DMA_ERROR_CODE (~0)
-+
- #ifdef __arch_page_to_dma
- #error Please update to __arch_pfn_to_dma
- #endif
-@@ -123,7 +125,7 @@ extern int dma_set_mask(struct device *, u64);
- */
- static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
- {
-- return dma_addr == ~0;
-+ return dma_addr == DMA_ERROR_CODE;
- }
-
- /*
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index bb19804..fab24ec 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -584,7 +584,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
- */
- gfp &= ~(__GFP_COMP);
-
-- *handle = ~0;
-+ *handle = DMA_ERROR_CODE;
- size = PAGE_ALIGN(size);
-
- if (arch_is_coherent() || nommu())
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:20 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:54 +0900
-Subject: [PATCH v2 37/58] ARM: dma-mapping: modify condition check while freeing pages
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-38-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Prathyush K <prathyush.k@samsung.com>
-
-WARNING: at mm/vmalloc.c:1471 __iommu_free_buffer+0xcc/0xd0()
-Trying to vfree() nonexistent vm area (ef095000)
-Modules linked in:
-[<c0015a18>] (unwind_backtrace+0x0/0xfc) from [<c0025a94>] (warn_slowpath_common+0x54/0x64)
-[<c0025a94>] (warn_slowpath_common+0x54/0x64) from [<c0025b38>] (warn_slowpath_fmt+0x30/0x40)
-[<c0025b38>] (warn_slowpath_fmt+0x30/0x40) from [<c0016de0>] (__iommu_free_buffer+0xcc/0xd0)
-[<c0016de0>] (__iommu_free_buffer+0xcc/0xd0) from [<c0229a5c>] (exynos_drm_free_buf+0xe4/0x138)
-[<c0229a5c>] (exynos_drm_free_buf+0xe4/0x138) from [<c022b358>] (exynos_drm_gem_destroy+0x80/0xfc)
-[<c022b358>] (exynos_drm_gem_destroy+0x80/0xfc) from [<c0211230>] (drm_gem_object_free+0x28/0x34)
-[<c0211230>] (drm_gem_object_free+0x28/0x34) from [<c0211bd0>] (drm_gem_object_release_handle+0xcc/0xd8)
-[<c0211bd0>] (drm_gem_object_release_handle+0xcc/0xd8) from [<c01abe10>] (idr_for_each+0x74/0xb8)
-[<c01abe10>] (idr_for_each+0x74/0xb8) from [<c02114e4>] (drm_gem_release+0x1c/0x30)
-[<c02114e4>] (drm_gem_release+0x1c/0x30) from [<c0210ae8>] (drm_release+0x608/0x694)
-[<c0210ae8>] (drm_release+0x608/0x694) from [<c00b75a0>] (fput+0xb8/0x228)
-[<c00b75a0>] (fput+0xb8/0x228) from [<c00b40c4>] (filp_close+0x64/0x84)
-[<c00b40c4>] (filp_close+0x64/0x84) from [<c0029d54>] (put_files_struct+0xe8/0x104)
-[<c0029d54>] (put_files_struct+0xe8/0x104) from [<c002b930>] (do_exit+0x608/0x774)
-[<c002b930>] (do_exit+0x608/0x774) from [<c002bae4>] (do_group_exit+0x48/0xb4)
-[<c002bae4>] (do_group_exit+0x48/0xb4) from [<c002bb60>] (sys_exit_group+0x10/0x18)
-[<c002bb60>] (sys_exit_group+0x10/0x18) from [<c000ee80>] (ret_fast_syscall+0x0/0x30)
-
-This patch modifies the condition while freeing to match the condition
-used while allocation. This fixes the above warning which arises when
-array size is equal to PAGE_SIZE where allocation is done using kzalloc
-but free is done using vfree.
-
-Signed-off-by: Prathyush K <prathyush.k@samsung.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit 46c87852e99cf8ce97e207b11cde19085837e39c)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/mm/dma-mapping.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -1093,7 +1093,7 @@ error:
- while (--i)
- if (pages[i])
- __free_pages(pages[i], 0);
-- if (array_size < PAGE_SIZE)
-+ if (array_size <= PAGE_SIZE)
- kfree(pages);
- else
- vfree(pages);
-@@ -1108,7 +1108,7 @@ static int __iommu_free_buffer(struct de
- for (i = 0; i < count; i++)
- if (pages[i])
- __free_pages(pages[i], 0);
-- if (array_size < PAGE_SIZE)
-+ if (array_size <= PAGE_SIZE)
- kfree(pages);
- else
- vfree(pages);
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:50 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:42 +0900
-Subject: [PATCH v2 25/58] ARM: dma-mapping: move all dma bounce code to separate dma ops structure
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-26-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-This patch removes dma bounce hooks from the common dma mapping
-implementation on ARM architecture and creates a separate set of
-dma_map_ops for dma bounce devices.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
-Tested-By: Subash Patel <subash.ramaswamy@linaro.org>
-(cherry picked from commit 15237e1f505b3e5c2276f240b01cd2133e110cbc)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/common/dmabounce.c | 62 ++++++++++++++++++-----
- arch/arm/include/asm/dma-mapping.h | 99 -------------------------------------
- arch/arm/mm/dma-mapping.c | 79 +++++++++++++++++++++++++----
- 3 files changed, 120 insertions(+), 120 deletions(-)
-
---- a/arch/arm/common/dmabounce.c
-+++ b/arch/arm/common/dmabounce.c
-@@ -308,8 +308,9 @@ static inline void unmap_single(struct d
- * substitute the safe buffer for the unsafe one.
- * (basically move the buffer from an unsafe area to a safe one)
- */
--dma_addr_t __dma_map_page(struct device *dev, struct page *page,
-- unsigned long offset, size_t size, enum dma_data_direction dir)
-+static dma_addr_t dmabounce_map_page(struct device *dev, struct page *page,
-+ unsigned long offset, size_t size, enum dma_data_direction dir,
-+ struct dma_attrs *attrs)
- {
- dma_addr_t dma_addr;
- int ret;
-@@ -324,7 +325,7 @@ dma_addr_t __dma_map_page(struct device
- return DMA_ERROR_CODE;
-
- if (ret == 0) {
-- __dma_page_cpu_to_dev(page, offset, size, dir);
-+ arm_dma_ops.sync_single_for_device(dev, dma_addr, size, dir);
- return dma_addr;
- }
-
-@@ -335,7 +336,6 @@ dma_addr_t __dma_map_page(struct device
-
- return map_single(dev, page_address(page) + offset, size, dir);
- }
--EXPORT_SYMBOL(__dma_map_page);
-
- /*
- * see if a mapped address was really a "safe" buffer and if so, copy
-@@ -343,8 +343,8 @@ EXPORT_SYMBOL(__dma_map_page);
- * the safe buffer. (basically return things back to the way they
- * should be)
- */
--void __dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
-- enum dma_data_direction dir)
-+static void dmabounce_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
-+ enum dma_data_direction dir, struct dma_attrs *attrs)
- {
- struct safe_buffer *buf;
-
-@@ -353,16 +353,14 @@ void __dma_unmap_page(struct device *dev
-
- buf = find_safe_buffer_dev(dev, dma_addr, __func__);
- if (!buf) {
-- __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, dma_addr)),
-- dma_addr & ~PAGE_MASK, size, dir);
-+ arm_dma_ops.sync_single_for_cpu(dev, dma_addr, size, dir);
- return;
- }
-
- unmap_single(dev, buf, size, dir);
- }
--EXPORT_SYMBOL(__dma_unmap_page);
-
--int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
-+static int __dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
- size_t sz, enum dma_data_direction dir)
- {
- struct safe_buffer *buf;
-@@ -392,9 +390,17 @@ int dmabounce_sync_for_cpu(struct device
- }
- return 0;
- }
--EXPORT_SYMBOL(dmabounce_sync_for_cpu);
-
--int dmabounce_sync_for_device(struct device *dev, dma_addr_t addr,
-+static void dmabounce_sync_for_cpu(struct device *dev,
-+ dma_addr_t handle, size_t size, enum dma_data_direction dir)
-+{
-+ if (!__dmabounce_sync_for_cpu(dev, handle, size, dir))
-+ return;
-+
-+ arm_dma_ops.sync_single_for_cpu(dev, handle, size, dir);
-+}
-+
-+static int __dmabounce_sync_for_device(struct device *dev, dma_addr_t addr,
- size_t sz, enum dma_data_direction dir)
- {
- struct safe_buffer *buf;
-@@ -424,7 +430,35 @@ int dmabounce_sync_for_device(struct dev
- }
- return 0;
- }
--EXPORT_SYMBOL(dmabounce_sync_for_device);
-+
-+static void dmabounce_sync_for_device(struct device *dev,
-+ dma_addr_t handle, size_t size, enum dma_data_direction dir)
-+{
-+ if (!__dmabounce_sync_for_device(dev, handle, size, dir))
-+ return;
-+
-+ arm_dma_ops.sync_single_for_device(dev, handle, size, dir);
-+}
-+
-+static int dmabounce_set_mask(struct device *dev, u64 dma_mask)
-+{
-+ if (dev->archdata.dmabounce)
-+ return 0;
-+
-+ return arm_dma_ops.set_dma_mask(dev, dma_mask);
-+}
-+
-+static struct dma_map_ops dmabounce_ops = {
-+ .map_page = dmabounce_map_page,
-+ .unmap_page = dmabounce_unmap_page,
-+ .sync_single_for_cpu = dmabounce_sync_for_cpu,
-+ .sync_single_for_device = dmabounce_sync_for_device,
-+ .map_sg = arm_dma_map_sg,
-+ .unmap_sg = arm_dma_unmap_sg,
-+ .sync_sg_for_cpu = arm_dma_sync_sg_for_cpu,
-+ .sync_sg_for_device = arm_dma_sync_sg_for_device,
-+ .set_dma_mask = dmabounce_set_mask,
-+};
-
- static int dmabounce_init_pool(struct dmabounce_pool *pool, struct device *dev,
- const char *name, unsigned long size)
-@@ -486,6 +520,7 @@ int dmabounce_register_dev(struct device
- #endif
-
- dev->archdata.dmabounce = device_info;
-+ set_dma_ops(dev, &dmabounce_ops);
-
- dev_info(dev, "dmabounce: registered device\n");
-
-@@ -504,6 +539,7 @@ void dmabounce_unregister_dev(struct dev
- struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
-
- dev->archdata.dmabounce = NULL;
-+ set_dma_ops(dev, NULL);
-
- if (!device_info) {
- dev_warn(dev,
---- a/arch/arm/include/asm/dma-mapping.h
-+++ b/arch/arm/include/asm/dma-mapping.h
-@@ -85,62 +85,6 @@ static inline dma_addr_t virt_to_dma(str
- #endif
-
- /*
-- * The DMA API is built upon the notion of "buffer ownership". A buffer
-- * is either exclusively owned by the CPU (and therefore may be accessed
-- * by it) or exclusively owned by the DMA device. These helper functions
-- * represent the transitions between these two ownership states.
-- *
-- * Note, however, that on later ARMs, this notion does not work due to
-- * speculative prefetches. We model our approach on the assumption that
-- * the CPU does do speculative prefetches, which means we clean caches
-- * before transfers and delay cache invalidation until transfer completion.
-- *
-- * Private support functions: these are not part of the API and are
-- * liable to change. Drivers must not use these.
-- */
--static inline void __dma_single_cpu_to_dev(const void *kaddr, size_t size,
-- enum dma_data_direction dir)
--{
-- extern void ___dma_single_cpu_to_dev(const void *, size_t,
-- enum dma_data_direction);
--
-- if (!arch_is_coherent())
-- ___dma_single_cpu_to_dev(kaddr, size, dir);
--}
--
--static inline void __dma_single_dev_to_cpu(const void *kaddr, size_t size,
-- enum dma_data_direction dir)
--{
-- extern void ___dma_single_dev_to_cpu(const void *, size_t,
-- enum dma_data_direction);
--
-- if (!arch_is_coherent())
-- ___dma_single_dev_to_cpu(kaddr, size, dir);
--}
--
--static inline void __dma_page_cpu_to_dev(struct page *page, unsigned long off,
-- size_t size, enum dma_data_direction dir)
--{
-- extern void ___dma_page_cpu_to_dev(struct page *, unsigned long,
-- size_t, enum dma_data_direction);
--
-- if (!arch_is_coherent())
-- ___dma_page_cpu_to_dev(page, off, size, dir);
--}
--
--static inline void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
-- size_t size, enum dma_data_direction dir)
--{
-- extern void ___dma_page_dev_to_cpu(struct page *, unsigned long,
-- size_t, enum dma_data_direction);
--
-- if (!arch_is_coherent())
-- ___dma_page_dev_to_cpu(page, off, size, dir);
--}
--
--extern int dma_supported(struct device *, u64);
--extern int dma_set_mask(struct device *, u64);
--/*
- * DMA errors are defined by all-bits-set in the DMA address.
- */
- static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-@@ -163,6 +107,8 @@ static inline void dma_free_noncoherent(
- {
- }
-
-+extern int dma_supported(struct device *dev, u64 mask);
-+
- /**
- * dma_alloc_coherent - allocate consistent memory for DMA
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
-@@ -235,7 +181,6 @@ int dma_mmap_writecombine(struct device
- extern void __init init_consistent_dma_size(unsigned long size);
-
-
--#ifdef CONFIG_DMABOUNCE
- /*
- * For SA-1111, IXP425, and ADI systems the dma-mapping functions are "magic"
- * and utilize bounce buffers as needed to work around limited DMA windows.
-@@ -275,48 +220,8 @@ extern int dmabounce_register_dev(struct
- */
- extern void dmabounce_unregister_dev(struct device *);
-
--/*
-- * The DMA API, implemented by dmabounce.c. See below for descriptions.
-- */
--extern dma_addr_t __dma_map_page(struct device *, struct page *,
-- unsigned long, size_t, enum dma_data_direction);
--extern void __dma_unmap_page(struct device *, dma_addr_t, size_t,
-- enum dma_data_direction);
--
--/*
-- * Private functions
-- */
--int dmabounce_sync_for_cpu(struct device *, dma_addr_t, size_t, enum dma_data_direction);
--int dmabounce_sync_for_device(struct device *, dma_addr_t, size_t, enum dma_data_direction);
--#else
--static inline int dmabounce_sync_for_cpu(struct device *d, dma_addr_t addr,
-- size_t size, enum dma_data_direction dir)
--{
-- return 1;
--}
--
--static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
-- size_t size, enum dma_data_direction dir)
--{
-- return 1;
--}
-
-
--static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
-- unsigned long offset, size_t size, enum dma_data_direction dir)
--{
-- __dma_page_cpu_to_dev(page, offset, size, dir);
-- return pfn_to_dma(dev, page_to_pfn(page)) + offset;
--}
--
--static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
-- size_t size, enum dma_data_direction dir)
--{
-- __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
-- handle & ~PAGE_MASK, size, dir);
--}
--#endif /* CONFIG_DMABOUNCE */
--
- /*
- * The scatter list versions of the above methods.
- */
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -34,6 +34,75 @@
-
- #include "mm.h"
-
-+/*
-+ * The DMA API is built upon the notion of "buffer ownership". A buffer
-+ * is either exclusively owned by the CPU (and therefore may be accessed
-+ * by it) or exclusively owned by the DMA device. These helper functions
-+ * represent the transitions between these two ownership states.
-+ *
-+ * Note, however, that on later ARMs, this notion does not work due to
-+ * speculative prefetches. We model our approach on the assumption that
-+ * the CPU does do speculative prefetches, which means we clean caches
-+ * before transfers and delay cache invalidation until transfer completion.
-+ *
-+ * Private support functions: these are not part of the API and are
-+ * liable to change. Drivers must not use these.
-+ */
-+static inline void __dma_single_cpu_to_dev(const void *kaddr, size_t size,
-+ enum dma_data_direction dir)
-+{
-+ extern void ___dma_single_cpu_to_dev(const void *, size_t,
-+ enum dma_data_direction);
-+
-+ if (!arch_is_coherent())
-+ ___dma_single_cpu_to_dev(kaddr, size, dir);
-+}
-+
-+static inline void __dma_single_dev_to_cpu(const void *kaddr, size_t size,
-+ enum dma_data_direction dir)
-+{
-+ extern void ___dma_single_dev_to_cpu(const void *, size_t,
-+ enum dma_data_direction);
-+
-+ if (!arch_is_coherent())
-+ ___dma_single_dev_to_cpu(kaddr, size, dir);
-+}
-+
-+static inline void __dma_page_cpu_to_dev(struct page *page, unsigned long off,
-+ size_t size, enum dma_data_direction dir)
-+{
-+ extern void ___dma_page_cpu_to_dev(struct page *, unsigned long,
-+ size_t, enum dma_data_direction);
-+
-+ if (!arch_is_coherent())
-+ ___dma_page_cpu_to_dev(page, off, size, dir);
-+}
-+
-+static inline void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
-+ size_t size, enum dma_data_direction dir)
-+{
-+ extern void ___dma_page_dev_to_cpu(struct page *, unsigned long,
-+ size_t, enum dma_data_direction);
-+
-+ if (!arch_is_coherent())
-+ ___dma_page_dev_to_cpu(page, off, size, dir);
-+}
-+
-+
-+static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
-+ unsigned long offset, size_t size, enum dma_data_direction dir)
-+{
-+ __dma_page_cpu_to_dev(page, offset, size, dir);
-+ return pfn_to_dma(dev, page_to_pfn(page)) + offset;
-+}
-+
-+static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
-+ size_t size, enum dma_data_direction dir)
-+{
-+ __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
-+ handle & ~PAGE_MASK, size, dir);
-+}
-+
- /**
- * arm_dma_map_page - map a portion of a page for streaming DMA
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
-@@ -81,9 +150,6 @@ static inline void arm_dma_sync_single_f
- {
- unsigned int offset = handle & (PAGE_SIZE - 1);
- struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
-- if (!dmabounce_sync_for_cpu(dev, handle, size, dir))
-- return;
--
- __dma_page_dev_to_cpu(page, offset, size, dir);
- }
-
-@@ -92,9 +158,6 @@ static inline void arm_dma_sync_single_f
- {
- unsigned int offset = handle & (PAGE_SIZE - 1);
- struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
-- if (!dmabounce_sync_for_device(dev, handle, size, dir))
-- return;
--
- __dma_page_cpu_to_dev(page, offset, size, dir);
- }
-
-@@ -837,7 +900,6 @@ void ___dma_page_cpu_to_dev(struct page
- }
- /* FIXME: non-speculating: flush on bidirectional mappings? */
- }
--EXPORT_SYMBOL(___dma_page_cpu_to_dev);
-
- void ___dma_page_dev_to_cpu(struct page *page, unsigned long off,
- size_t size, enum dma_data_direction dir)
-@@ -857,7 +919,6 @@ void ___dma_page_dev_to_cpu(struct page
- if (dir != DMA_TO_DEVICE && off == 0 && size >= PAGE_SIZE)
- set_bit(PG_dcache_clean, &page->flags);
- }
--EXPORT_SYMBOL(___dma_page_dev_to_cpu);
-
- /**
- * arm_dma_map_sg - map a set of SG buffers for streaming mode DMA
-@@ -975,9 +1036,7 @@ static int arm_dma_set_mask(struct devic
- if (!dev->dma_mask || !dma_supported(dev, dma_mask))
- return -EIO;
-
--#ifndef CONFIG_DMABOUNCE
- *dev->dma_mask = dma_mask;
--#endif
-
- return 0;
- }
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:54:03 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:11 +0900
-Subject: [PATCH v2 54/58] ARM: DMA-Mapping: print warning when atomic coherent allocation fails
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-55-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-Print a loud warning when system runs out of memory from atomic DMA
-coherent pool to let users notice the potential problem.
-
-Reported-by: Aaro Koskinen <aaro.koskinen@iki.fi>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit fb71285f0c1633a85544784aae7577502274b77a)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mm/dma-mapping.c | 4 ++++
- 1 files changed, 4 insertions(+), 0 deletions(-)
-
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index 3ff2585..e597c89 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -460,6 +460,10 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page)
- bitmap_set(pool->bitmap, pageno, count);
- ptr = pool->vaddr + PAGE_SIZE * pageno;
- *ret_page = pool->page + pageno;
-+ } else {
-+ pr_err_once("ERROR: %u KiB atomic DMA coherent pool is too small!\n"
-+ "Please increase it with coherent_pool= kernel parameter!\n",
-+ (unsigned)pool->size / 1024);
- }
- spin_unlock_irqrestore(&pool->lock, flags);
-
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:54:05 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:12 +0900
-Subject: [PATCH v2 55/58] ARM: dma-mapping: Refactor out to introduce __in_atomic_pool
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-56-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Hiroshi Doyu <hdoyu@nvidia.com>
-
-Check the given range("start", "size") is included in "atomic_pool" or not.
-
-Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit 21d0a75951ccf71f671eb24b61a8ad2b497be4b4)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mm/dma-mapping.c | 26 ++++++++++++++++++++------
- 1 files changed, 20 insertions(+), 6 deletions(-)
-
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index e597c89..94b7b78 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -470,20 +470,34 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page)
- return ptr;
- }
-
-+static bool __in_atomic_pool(void *start, size_t size)
-+{
-+ struct dma_pool *pool = &atomic_pool;
-+ void *end = start + size;
-+ void *pool_start = pool->vaddr;
-+ void *pool_end = pool->vaddr + pool->size;
-+
-+ if (start < pool_start || start > pool_end)
-+ return false;
-+
-+ if (end <= pool_end)
-+ return true;
-+
-+ WARN(1, "Wrong coherent size(%p-%p) from atomic pool(%p-%p)\n",
-+ start, end - 1, pool_start, pool_end - 1);
-+
-+ return false;
-+}
-+
- static int __free_from_pool(void *start, size_t size)
- {
- struct dma_pool *pool = &atomic_pool;
- unsigned long pageno, count;
- unsigned long flags;
-
-- if (start < pool->vaddr || start > pool->vaddr + pool->size)
-+ if (!__in_atomic_pool(start, size))
- return 0;
-
-- if (start + size > pool->vaddr + pool->size) {
-- WARN(1, "freeing wrong coherent size from pool\n");
-- return 0;
-- }
--
- pageno = (start - pool->vaddr) >> PAGE_SHIFT;
- count = size >> PAGE_SHIFT;
-
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:31 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:58 +0900
-Subject: [PATCH v2 41/58] ARM: dma-mapping: remove custom consistent dma region
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-42-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-This patch changes dma-mapping subsystem to use generic vmalloc areas
-for all consistent dma allocations. This increases the total size limit
-of the consistent allocations and removes platform hacks and a lot of
-duplicated code.
-
-Atomic allocations are served from special pool preallocated on boot,
-because vmalloc areas cannot be reliably created in atomic context.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com>
-Reviewed-by: Minchan Kim <minchan@kernel.org>
-(cherry picked from commit e9da6e9905e639b0f842a244bc770b48ad0523e9)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- Documentation/kernel-parameters.txt | 2
- arch/arm/include/asm/dma-mapping.h | 2
- arch/arm/mm/dma-mapping.c | 492 ++++++++++++------------------------
- arch/arm/mm/mm.h | 3
- include/linux/vmalloc.h | 1
- mm/vmalloc.c | 10
- 6 files changed, 184 insertions(+), 326 deletions(-)
-
---- a/Documentation/kernel-parameters.txt
-+++ b/Documentation/kernel-parameters.txt
-@@ -522,7 +522,7 @@ bytes respectively. Such letter suffixes
-
- coherent_pool=nn[KMG] [ARM,KNL]
- Sets the size of memory pool for coherent, atomic dma
-- allocations if Contiguous Memory Allocator (CMA) is used.
-+ allocations, by default set to 256K.
-
- code_bytes [X86] How many bytes of object code to print
- in an oops report.
---- a/arch/arm/include/asm/dma-mapping.h
-+++ b/arch/arm/include/asm/dma-mapping.h
-@@ -226,7 +226,7 @@ static inline int dma_mmap_writecombine(
- * DMA region above it's default value of 2MB. It must be called before the
- * memory allocator is initialised, i.e. before any core_initcall.
- */
--extern void __init init_consistent_dma_size(unsigned long size);
-+static inline void init_consistent_dma_size(unsigned long size) { }
-
- /*
- * For SA-1111, IXP425, and ADI systems the dma-mapping functions are "magic"
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -22,6 +22,7 @@
- #include <linux/memblock.h>
- #include <linux/slab.h>
- #include <linux/iommu.h>
-+#include <linux/io.h>
- #include <linux/vmalloc.h>
-
- #include <asm/memory.h>
-@@ -217,115 +218,70 @@ static void __dma_free_buffer(struct pag
- }
-
- #ifdef CONFIG_MMU
-+#ifdef CONFIG_HUGETLB_PAGE
-+#error ARM Coherent DMA allocator does not (yet) support huge TLB
-+#endif
-
--#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - consistent_base) >> PAGE_SHIFT)
--#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - consistent_base) >> PMD_SHIFT)
--
--/*
-- * These are the page tables (2MB each) covering uncached, DMA consistent allocations
-- */
--static pte_t **consistent_pte;
--
--#define DEFAULT_CONSISTENT_DMA_SIZE SZ_2M
-+static void *__alloc_from_contiguous(struct device *dev, size_t size,
-+ pgprot_t prot, struct page **ret_page);
-
--static unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE;
-+static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp,
-+ pgprot_t prot, struct page **ret_page,
-+ const void *caller);
-
--void __init init_consistent_dma_size(unsigned long size)
-+static void *
-+__dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot,
-+ const void *caller)
- {
-- unsigned long base = CONSISTENT_END - ALIGN(size, SZ_2M);
-+ struct vm_struct *area;
-+ unsigned long addr;
-
-- BUG_ON(consistent_pte); /* Check we're called before DMA region init */
-- BUG_ON(base < VMALLOC_END);
-+ /*
-+ * DMA allocation can be mapped to user space, so lets
-+ * set VM_USERMAP flags too.
-+ */
-+ area = get_vm_area_caller(size, VM_ARM_DMA_CONSISTENT | VM_USERMAP,
-+ caller);
-+ if (!area)
-+ return NULL;
-+ addr = (unsigned long)area->addr;
-+ area->phys_addr = __pfn_to_phys(page_to_pfn(page));
-
-- /* Grow region to accommodate specified size */
-- if (base < consistent_base)
-- consistent_base = base;
-+ if (ioremap_page_range(addr, addr + size, area->phys_addr, prot)) {
-+ vunmap((void *)addr);
-+ return NULL;
-+ }
-+ return (void *)addr;
- }
-
--#include "vmregion.h"
--
--static struct arm_vmregion_head consistent_head = {
-- .vm_lock = __SPIN_LOCK_UNLOCKED(&consistent_head.vm_lock),
-- .vm_list = LIST_HEAD_INIT(consistent_head.vm_list),
-- .vm_end = CONSISTENT_END,
--};
--
--#ifdef CONFIG_HUGETLB_PAGE
--#error ARM Coherent DMA allocator does not (yet) support huge TLB
--#endif
--
--/*
-- * Initialise the consistent memory allocation.
-- */
--static int __init consistent_init(void)
-+static void __dma_free_remap(void *cpu_addr, size_t size)
- {
-- int ret = 0;
-- pgd_t *pgd;
-- pud_t *pud;
-- pmd_t *pmd;
-- pte_t *pte;
-- int i = 0;
-- unsigned long base = consistent_base;
-- unsigned long num_ptes = (CONSISTENT_END - base) >> PMD_SHIFT;
--
-- if (IS_ENABLED(CONFIG_CMA) && !IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU))
-- return 0;
--
-- consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL);
-- if (!consistent_pte) {
-- pr_err("%s: no memory\n", __func__);
-- return -ENOMEM;
-+ unsigned int flags = VM_ARM_DMA_CONSISTENT | VM_USERMAP;
-+ struct vm_struct *area = find_vm_area(cpu_addr);
-+ if (!area || (area->flags & flags) != flags) {
-+ WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr);
-+ return;
- }
--
-- pr_debug("DMA memory: 0x%08lx - 0x%08lx:\n", base, CONSISTENT_END);
-- consistent_head.vm_start = base;
--
-- do {
-- pgd = pgd_offset(&init_mm, base);
--
-- pud = pud_alloc(&init_mm, pgd, base);
-- if (!pud) {
-- pr_err("%s: no pud tables\n", __func__);
-- ret = -ENOMEM;
-- break;
-- }
--
-- pmd = pmd_alloc(&init_mm, pud, base);
-- if (!pmd) {
-- pr_err("%s: no pmd tables\n", __func__);
-- ret = -ENOMEM;
-- break;
-- }
-- WARN_ON(!pmd_none(*pmd));
--
-- pte = pte_alloc_kernel(pmd, base);
-- if (!pte) {
-- pr_err("%s: no pte tables\n", __func__);
-- ret = -ENOMEM;
-- break;
-- }
--
-- consistent_pte[i++] = pte;
-- base += PMD_SIZE;
-- } while (base < CONSISTENT_END);
--
-- return ret;
-+ unmap_kernel_range((unsigned long)cpu_addr, size);
-+ vunmap(cpu_addr);
- }
--core_initcall(consistent_init);
-
--static void *__alloc_from_contiguous(struct device *dev, size_t size,
-- pgprot_t prot, struct page **ret_page);
--
--static struct arm_vmregion_head coherent_head = {
-- .vm_lock = __SPIN_LOCK_UNLOCKED(&coherent_head.vm_lock),
-- .vm_list = LIST_HEAD_INIT(coherent_head.vm_list),
-+struct dma_pool {
-+ size_t size;
-+ spinlock_t lock;
-+ unsigned long *bitmap;
-+ unsigned long nr_pages;
-+ void *vaddr;
-+ struct page *page;
- };
-
--static size_t coherent_pool_size = DEFAULT_CONSISTENT_DMA_SIZE / 8;
-+static struct dma_pool atomic_pool = {
-+ .size = SZ_256K,
-+};
-
- static int __init early_coherent_pool(char *p)
- {
-- coherent_pool_size = memparse(p, &p);
-+ atomic_pool.size = memparse(p, &p);
- return 0;
- }
- early_param("coherent_pool", early_coherent_pool);
-@@ -333,32 +289,45 @@ early_param("coherent_pool", early_coher
- /*
- * Initialise the coherent pool for atomic allocations.
- */
--static int __init coherent_init(void)
-+static int __init atomic_pool_init(void)
- {
-+ struct dma_pool *pool = &atomic_pool;
- pgprot_t prot = pgprot_dmacoherent(pgprot_kernel);
-- size_t size = coherent_pool_size;
-+ unsigned long nr_pages = pool->size >> PAGE_SHIFT;
-+ unsigned long *bitmap;
- struct page *page;
- void *ptr;
-+ int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
-
-- if (!IS_ENABLED(CONFIG_CMA))
-- return 0;
-+ bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-+ if (!bitmap)
-+ goto no_bitmap;
-
-- ptr = __alloc_from_contiguous(NULL, size, prot, &page);
-+ if (IS_ENABLED(CONFIG_CMA))
-+ ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page);
-+ else
-+ ptr = __alloc_remap_buffer(NULL, pool->size, GFP_KERNEL, prot,
-+ &page, NULL);
- if (ptr) {
-- coherent_head.vm_start = (unsigned long) ptr;
-- coherent_head.vm_end = (unsigned long) ptr + size;
-- printk(KERN_INFO "DMA: preallocated %u KiB pool for atomic coherent allocations\n",
-- (unsigned)size / 1024);
-+ spin_lock_init(&pool->lock);
-+ pool->vaddr = ptr;
-+ pool->page = page;
-+ pool->bitmap = bitmap;
-+ pool->nr_pages = nr_pages;
-+ pr_info("DMA: preallocated %u KiB pool for atomic coherent allocations\n",
-+ (unsigned)pool->size / 1024);
- return 0;
- }
-- printk(KERN_ERR "DMA: failed to allocate %u KiB pool for atomic coherent allocation\n",
-- (unsigned)size / 1024);
-+ kfree(bitmap);
-+no_bitmap:
-+ pr_err("DMA: failed to allocate %u KiB pool for atomic coherent allocation\n",
-+ (unsigned)pool->size / 1024);
- return -ENOMEM;
- }
- /*
- * CMA is activated by core_initcall, so we must be called after it.
- */
--postcore_initcall(coherent_init);
-+postcore_initcall(atomic_pool_init);
-
- struct dma_contig_early_reserve {
- phys_addr_t base;
-@@ -406,112 +375,6 @@ void __init dma_contiguous_remap(void)
- }
- }
-
--static void *
--__dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot,
-- const void *caller)
--{
-- struct arm_vmregion *c;
-- size_t align;
-- int bit;
--
-- if (!consistent_pte) {
-- pr_err("%s: not initialised\n", __func__);
-- dump_stack();
-- return NULL;
-- }
--
-- /*
-- * Align the virtual region allocation - maximum alignment is
-- * a section size, minimum is a page size. This helps reduce
-- * fragmentation of the DMA space, and also prevents allocations
-- * smaller than a section from crossing a section boundary.
-- */
-- bit = fls(size - 1);
-- if (bit > SECTION_SHIFT)
-- bit = SECTION_SHIFT;
-- align = 1 << bit;
--
-- /*
-- * Allocate a virtual address in the consistent mapping region.
-- */
-- c = arm_vmregion_alloc(&consistent_head, align, size,
-- gfp & ~(__GFP_DMA | __GFP_HIGHMEM), caller);
-- if (c) {
-- pte_t *pte;
-- int idx = CONSISTENT_PTE_INDEX(c->vm_start);
-- u32 off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);
--
-- pte = consistent_pte[idx] + off;
-- c->priv = page;
--
-- do {
-- BUG_ON(!pte_none(*pte));
--
-- set_pte_ext(pte, mk_pte(page, prot), 0);
-- page++;
-- pte++;
-- off++;
-- if (off >= PTRS_PER_PTE) {
-- off = 0;
-- pte = consistent_pte[++idx];
-- }
-- } while (size -= PAGE_SIZE);
--
-- dsb();
--
-- return (void *)c->vm_start;
-- }
-- return NULL;
--}
--
--static void __dma_free_remap(void *cpu_addr, size_t size)
--{
-- struct arm_vmregion *c;
-- unsigned long addr;
-- pte_t *ptep;
-- int idx;
-- u32 off;
--
-- c = arm_vmregion_find_remove(&consistent_head, (unsigned long)cpu_addr);
-- if (!c) {
-- pr_err("%s: trying to free invalid coherent area: %p\n",
-- __func__, cpu_addr);
-- dump_stack();
-- return;
-- }
--
-- if ((c->vm_end - c->vm_start) != size) {
-- pr_err("%s: freeing wrong coherent size (%ld != %d)\n",
-- __func__, c->vm_end - c->vm_start, size);
-- dump_stack();
-- size = c->vm_end - c->vm_start;
-- }
--
-- idx = CONSISTENT_PTE_INDEX(c->vm_start);
-- off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);
-- ptep = consistent_pte[idx] + off;
-- addr = c->vm_start;
-- do {
-- pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
--
-- ptep++;
-- addr += PAGE_SIZE;
-- off++;
-- if (off >= PTRS_PER_PTE) {
-- off = 0;
-- ptep = consistent_pte[++idx];
-- }
--
-- if (pte_none(pte) || !pte_present(pte))
-- pr_crit("%s: bad page in kernel page table\n",
-- __func__);
-- } while (size -= PAGE_SIZE);
--
-- flush_tlb_kernel_range(c->vm_start, c->vm_end);
--
-- arm_vmregion_free(&consistent_head, c);
--}
--
- static int __dma_update_pte(pte_t *pte, pgtable_t token, unsigned long addr,
- void *data)
- {
-@@ -552,16 +415,17 @@ static void *__alloc_remap_buffer(struct
- return ptr;
- }
-
--static void *__alloc_from_pool(struct device *dev, size_t size,
-- struct page **ret_page, const void *caller)
-+static void *__alloc_from_pool(size_t size, struct page **ret_page)
- {
-- struct arm_vmregion *c;
-+ struct dma_pool *pool = &atomic_pool;
-+ unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-+ unsigned int pageno;
-+ unsigned long flags;
-+ void *ptr = NULL;
- size_t align;
-
-- if (!coherent_head.vm_start) {
-- printk(KERN_ERR "%s: coherent pool not initialised!\n",
-- __func__);
-- dump_stack();
-+ if (!pool->vaddr) {
-+ WARN(1, "coherent pool not initialised!\n");
- return NULL;
- }
-
-@@ -571,35 +435,41 @@ static void *__alloc_from_pool(struct de
- * size. This helps reduce fragmentation of the DMA space.
- */
- align = PAGE_SIZE << get_order(size);
-- c = arm_vmregion_alloc(&coherent_head, align, size, 0, caller);
-- if (c) {
-- void *ptr = (void *)c->vm_start;
-- struct page *page = virt_to_page(ptr);
-- *ret_page = page;
-- return ptr;
-+
-+ spin_lock_irqsave(&pool->lock, flags);
-+ pageno = bitmap_find_next_zero_area(pool->bitmap, pool->nr_pages,
-+ 0, count, (1 << align) - 1);
-+ if (pageno < pool->nr_pages) {
-+ bitmap_set(pool->bitmap, pageno, count);
-+ ptr = pool->vaddr + PAGE_SIZE * pageno;
-+ *ret_page = pool->page + pageno;
- }
-- return NULL;
-+ spin_unlock_irqrestore(&pool->lock, flags);
-+
-+ return ptr;
- }
-
--static int __free_from_pool(void *cpu_addr, size_t size)
-+static int __free_from_pool(void *start, size_t size)
- {
-- unsigned long start = (unsigned long)cpu_addr;
-- unsigned long end = start + size;
-- struct arm_vmregion *c;
-+ struct dma_pool *pool = &atomic_pool;
-+ unsigned long pageno, count;
-+ unsigned long flags;
-
-- if (start < coherent_head.vm_start || end > coherent_head.vm_end)
-+ if (start < pool->vaddr || start > pool->vaddr + pool->size)
- return 0;
-
-- c = arm_vmregion_find_remove(&coherent_head, (unsigned long)start);
--
-- if ((c->vm_end - c->vm_start) != size) {
-- printk(KERN_ERR "%s: freeing wrong coherent size (%ld != %d)\n",
-- __func__, c->vm_end - c->vm_start, size);
-- dump_stack();
-- size = c->vm_end - c->vm_start;
-+ if (start + size > pool->vaddr + pool->size) {
-+ WARN(1, "freeing wrong coherent size from pool\n");
-+ return 0;
- }
-
-- arm_vmregion_free(&coherent_head, c);
-+ pageno = (start - pool->vaddr) >> PAGE_SHIFT;
-+ count = size >> PAGE_SHIFT;
-+
-+ spin_lock_irqsave(&pool->lock, flags);
-+ bitmap_clear(pool->bitmap, pageno, count);
-+ spin_unlock_irqrestore(&pool->lock, flags);
-+
- return 1;
- }
-
-@@ -644,7 +514,7 @@ static inline pgprot_t __get_dma_pgprot(
-
- #define __get_dma_pgprot(attrs, prot) __pgprot(0)
- #define __alloc_remap_buffer(dev, size, gfp, prot, ret, c) NULL
--#define __alloc_from_pool(dev, size, ret_page, c) NULL
-+#define __alloc_from_pool(size, ret_page) NULL
- #define __alloc_from_contiguous(dev, size, prot, ret) NULL
- #define __free_from_pool(cpu_addr, size) 0
- #define __free_from_contiguous(dev, page, size) do { } while (0)
-@@ -702,10 +572,10 @@ static void *__dma_alloc(struct device *
-
- if (arch_is_coherent() || nommu())
- addr = __alloc_simple_buffer(dev, size, gfp, &page);
-+ else if (gfp & GFP_ATOMIC)
-+ addr = __alloc_from_pool(size, &page);
- else if (!IS_ENABLED(CONFIG_CMA))
- addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
-- else if (gfp & GFP_ATOMIC)
-- addr = __alloc_from_pool(dev, size, &page, caller);
- else
- addr = __alloc_from_contiguous(dev, size, prot, &page);
-
-@@ -1000,9 +870,6 @@ static int arm_dma_set_mask(struct devic
-
- static int __init dma_debug_do_init(void)
- {
--#ifdef CONFIG_MMU
-- arm_vmregion_create_proc("dma-mappings", &consistent_head);
--#endif
- dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
- return 0;
- }
-@@ -1119,61 +986,32 @@ static int __iommu_free_buffer(struct de
- * Create a CPU mapping for a specified pages
- */
- static void *
--__iommu_alloc_remap(struct page **pages, size_t size, gfp_t gfp, pgprot_t prot)
-+__iommu_alloc_remap(struct page **pages, size_t size, gfp_t gfp, pgprot_t prot,
-+ const void *caller)
- {
-- struct arm_vmregion *c;
-- size_t align;
-- size_t count = size >> PAGE_SHIFT;
-- int bit;
--
-- if (!consistent_pte[0]) {
-- pr_err("%s: not initialised\n", __func__);
-- dump_stack();
-+ unsigned int i, nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
-+ struct vm_struct *area;
-+ unsigned long p;
-+
-+ area = get_vm_area_caller(size, VM_ARM_DMA_CONSISTENT | VM_USERMAP,
-+ caller);
-+ if (!area)
- return NULL;
-- }
--
-- /*
-- * Align the virtual region allocation - maximum alignment is
-- * a section size, minimum is a page size. This helps reduce
-- * fragmentation of the DMA space, and also prevents allocations
-- * smaller than a section from crossing a section boundary.
-- */
-- bit = fls(size - 1);
-- if (bit > SECTION_SHIFT)
-- bit = SECTION_SHIFT;
-- align = 1 << bit;
--
-- /*
-- * Allocate a virtual address in the consistent mapping region.
-- */
-- c = arm_vmregion_alloc(&consistent_head, align, size,
-- gfp & ~(__GFP_DMA | __GFP_HIGHMEM), NULL);
-- if (c) {
-- pte_t *pte;
-- int idx = CONSISTENT_PTE_INDEX(c->vm_start);
-- int i = 0;
-- u32 off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);
--
-- pte = consistent_pte[idx] + off;
-- c->priv = pages;
--
-- do {
-- BUG_ON(!pte_none(*pte));
--
-- set_pte_ext(pte, mk_pte(pages[i], prot), 0);
-- pte++;
-- off++;
-- i++;
-- if (off >= PTRS_PER_PTE) {
-- off = 0;
-- pte = consistent_pte[++idx];
-- }
-- } while (i < count);
--
-- dsb();
-
-- return (void *)c->vm_start;
-- }
-+ area->pages = pages;
-+ area->nr_pages = nr_pages;
-+ p = (unsigned long)area->addr;
-+
-+ for (i = 0; i < nr_pages; i++) {
-+ phys_addr_t phys = __pfn_to_phys(page_to_pfn(pages[i]));
-+ if (ioremap_page_range(p, p + PAGE_SIZE, phys, prot))
-+ goto err;
-+ p += PAGE_SIZE;
-+ }
-+ return area->addr;
-+err:
-+ unmap_kernel_range((unsigned long)area->addr, size);
-+ vunmap(area->addr);
- return NULL;
- }
-
-@@ -1232,6 +1070,16 @@ static int __iommu_remove_mapping(struct
- return 0;
- }
-
-+static struct page **__iommu_get_pages(void *cpu_addr)
-+{
-+ struct vm_struct *area;
-+
-+ area = find_vm_area(cpu_addr);
-+ if (area && (area->flags & VM_ARM_DMA_CONSISTENT))
-+ return area->pages;
-+ return NULL;
-+}
-+
- static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
- dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
- {
-@@ -1250,7 +1098,8 @@ static void *arm_iommu_alloc_attrs(struc
- if (*handle == DMA_ERROR_CODE)
- goto err_buffer;
-
-- addr = __iommu_alloc_remap(pages, size, gfp, prot);
-+ addr = __iommu_alloc_remap(pages, size, gfp, prot,
-+ __builtin_return_address(0));
- if (!addr)
- goto err_mapping;
-
-@@ -1267,31 +1116,25 @@ static int arm_iommu_mmap_attrs(struct d
- void *cpu_addr, dma_addr_t dma_addr, size_t size,
- struct dma_attrs *attrs)
- {
-- struct arm_vmregion *c;
-+ unsigned long uaddr = vma->vm_start;
-+ unsigned long usize = vma->vm_end - vma->vm_start;
-+ struct page **pages = __iommu_get_pages(cpu_addr);
-
- vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
-- c = arm_vmregion_find(&consistent_head, (unsigned long)cpu_addr);
-
-- if (c) {
-- struct page **pages = c->priv;
-+ if (!pages)
-+ return -ENXIO;
-
-- unsigned long uaddr = vma->vm_start;
-- unsigned long usize = vma->vm_end - vma->vm_start;
-- int i = 0;
--
-- do {
-- int ret;
--
-- ret = vm_insert_page(vma, uaddr, pages[i++]);
-- if (ret) {
-- pr_err("Remapping memory, error: %d\n", ret);
-- return ret;
-- }
-+ do {
-+ int ret = vm_insert_page(vma, uaddr, *pages++);
-+ if (ret) {
-+ pr_err("Remapping memory failed: %d\n", ret);
-+ return ret;
-+ }
-+ uaddr += PAGE_SIZE;
-+ usize -= PAGE_SIZE;
-+ } while (usize > 0);
-
-- uaddr += PAGE_SIZE;
-- usize -= PAGE_SIZE;
-- } while (usize > 0);
-- }
- return 0;
- }
-
-@@ -1302,16 +1145,19 @@ static int arm_iommu_mmap_attrs(struct d
- void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
- dma_addr_t handle, struct dma_attrs *attrs)
- {
-- struct arm_vmregion *c;
-+ struct page **pages = __iommu_get_pages(cpu_addr);
- size = PAGE_ALIGN(size);
-
-- c = arm_vmregion_find(&consistent_head, (unsigned long)cpu_addr);
-- if (c) {
-- struct page **pages = c->priv;
-- __dma_free_remap(cpu_addr, size);
-- __iommu_remove_mapping(dev, handle, size);
-- __iommu_free_buffer(dev, pages, size);
-+ if (!pages) {
-+ WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr);
-+ return;
- }
-+
-+ unmap_kernel_range((unsigned long)cpu_addr, size);
-+ vunmap(cpu_addr);
-+
-+ __iommu_remove_mapping(dev, handle, size);
-+ __iommu_free_buffer(dev, pages, size);
- }
-
- /*
---- a/arch/arm/mm/mm.h
-+++ b/arch/arm/mm/mm.h
-@@ -62,6 +62,9 @@ extern void __flush_dcache_page(struct a
- #define VM_ARM_MTYPE(mt) ((mt) << 20)
- #define VM_ARM_MTYPE_MASK (0x1f << 20)
-
-+/* consistent regions used by dma_alloc_attrs() */
-+#define VM_ARM_DMA_CONSISTENT 0x20000000
-+
- #endif
-
- #ifdef CONFIG_ZONE_DMA
---- a/include/linux/vmalloc.h
-+++ b/include/linux/vmalloc.h
-@@ -93,6 +93,7 @@ extern struct vm_struct *__get_vm_area_c
- unsigned long start, unsigned long end,
- const void *caller);
- extern struct vm_struct *remove_vm_area(const void *addr);
-+extern struct vm_struct *find_vm_area(const void *addr);
-
- extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
- struct page ***pages);
---- a/mm/vmalloc.c
-+++ b/mm/vmalloc.c
-@@ -1403,7 +1403,15 @@ struct vm_struct *get_vm_area_caller(uns
- -1, GFP_KERNEL, caller);
- }
-
--static struct vm_struct *find_vm_area(const void *addr)
-+/**
-+ * find_vm_area - find a continuous kernel virtual area
-+ * @addr: base address
-+ *
-+ * Search for the kernel VM area starting at @addr, and return it.
-+ * It is up to the caller to do all required locking to keep the returned
-+ * pointer valid.
-+ */
-+struct vm_struct *find_vm_area(const void *addr)
- {
- struct vmap_area *va;
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:42 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:39 +0900
-Subject: [PATCH v2 22/58] ARM: dma-mapping: remove offset parameter to prepare for generic dma_ops
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-23-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-This patch removes the need for the offset parameter in dma bounce
-functions. This is required to let dma-mapping framework on ARM
-architecture to use common, generic dma_map_ops based dma-mapping
-helpers.
-
-Background and more detailed explaination:
-
-dma_*_range_* functions are available from the early days of the dma
-mapping api. They are the correct way of doing a partial syncs on the
-buffer (usually used by the network device drivers). This patch changes
-only the internal implementation of the dma bounce functions to let
-them tunnel through dma_map_ops structure. The driver api stays
-unchanged, so driver are obliged to call dma_*_range_* functions to
-keep code clean and easy to understand.
-
-The only drawback from this patch is reduced detection of the dma api
-abuse. Let us consider the following code:
-
-dma_addr = dma_map_single(dev, ptr, 64, DMA_TO_DEVICE);
-dma_sync_single_range_for_cpu(dev, dma_addr+16, 0, 32, DMA_TO_DEVICE);
-
-Without the patch such code fails, because dma bounce code is unable
-to find the bounce buffer for the given dma_address. After the patch
-the above sync call will be equivalent to:
-
-dma_sync_single_range_for_cpu(dev, dma_addr, 16, 32, DMA_TO_DEVICE);
-
-which succeeds.
-
-I don't consider this as a real problem, because DMA API abuse should be
-caught by debug_dma_* function family. This patch lets us to simplify
-the internal low-level implementation without chaning the driver visible
-API.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
-Tested-By: Subash Patel <subash.ramaswamy@linaro.org>
-(cherry picked from commit a227fb92a0f5f0dd8282719386e9b3a29f0d16b2)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/common/dmabounce.c | 13 +++++--
- arch/arm/include/asm/dma-mapping.h | 67 ++++++++++++++++++-------------------
- arch/arm/mm/dma-mapping.c | 4 +-
- 3 files changed, 45 insertions(+), 39 deletions(-)
-
---- a/arch/arm/common/dmabounce.c
-+++ b/arch/arm/common/dmabounce.c
-@@ -173,7 +173,8 @@ find_safe_buffer(struct dmabounce_device
- read_lock_irqsave(&device_info->lock, flags);
-
- list_for_each_entry(b, &device_info->safe_buffers, node)
-- if (b->safe_dma_addr == safe_dma_addr) {
-+ if (b->safe_dma_addr <= safe_dma_addr &&
-+ b->safe_dma_addr + b->size > safe_dma_addr) {
- rb = b;
- break;
- }
-@@ -362,9 +363,10 @@ void __dma_unmap_page(struct device *dev
- EXPORT_SYMBOL(__dma_unmap_page);
-
- int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
-- unsigned long off, size_t sz, enum dma_data_direction dir)
-+ size_t sz, enum dma_data_direction dir)
- {
- struct safe_buffer *buf;
-+ unsigned long off;
-
- dev_dbg(dev, "%s(dma=%#x,off=%#lx,sz=%zx,dir=%x)\n",
- __func__, addr, off, sz, dir);
-@@ -373,6 +375,8 @@ int dmabounce_sync_for_cpu(struct device
- if (!buf)
- return 1;
-
-+ off = addr - buf->safe_dma_addr;
-+
- BUG_ON(buf->direction != dir);
-
- dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
-@@ -391,9 +395,10 @@ int dmabounce_sync_for_cpu(struct device
- EXPORT_SYMBOL(dmabounce_sync_for_cpu);
-
- int dmabounce_sync_for_device(struct device *dev, dma_addr_t addr,
-- unsigned long off, size_t sz, enum dma_data_direction dir)
-+ size_t sz, enum dma_data_direction dir)
- {
- struct safe_buffer *buf;
-+ unsigned long off;
-
- dev_dbg(dev, "%s(dma=%#x,off=%#lx,sz=%zx,dir=%x)\n",
- __func__, addr, off, sz, dir);
-@@ -402,6 +407,8 @@ int dmabounce_sync_for_device(struct dev
- if (!buf)
- return 1;
-
-+ off = addr - buf->safe_dma_addr;
-+
- BUG_ON(buf->direction != dir);
-
- dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
---- a/arch/arm/include/asm/dma-mapping.h
-+++ b/arch/arm/include/asm/dma-mapping.h
-@@ -266,19 +266,17 @@ extern void __dma_unmap_page(struct devi
- /*
- * Private functions
- */
--int dmabounce_sync_for_cpu(struct device *, dma_addr_t, unsigned long,
-- size_t, enum dma_data_direction);
--int dmabounce_sync_for_device(struct device *, dma_addr_t, unsigned long,
-- size_t, enum dma_data_direction);
-+int dmabounce_sync_for_cpu(struct device *, dma_addr_t, size_t, enum dma_data_direction);
-+int dmabounce_sync_for_device(struct device *, dma_addr_t, size_t, enum dma_data_direction);
- #else
- static inline int dmabounce_sync_for_cpu(struct device *d, dma_addr_t addr,
-- unsigned long offset, size_t size, enum dma_data_direction dir)
-+ size_t size, enum dma_data_direction dir)
- {
- return 1;
- }
-
- static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
-- unsigned long offset, size_t size, enum dma_data_direction dir)
-+ size_t size, enum dma_data_direction dir)
- {
- return 1;
- }
-@@ -401,6 +399,33 @@ static inline void dma_unmap_page(struct
- __dma_unmap_page(dev, handle, size, dir);
- }
-
-+
-+static inline void dma_sync_single_for_cpu(struct device *dev,
-+ dma_addr_t handle, size_t size, enum dma_data_direction dir)
-+{
-+ BUG_ON(!valid_dma_direction(dir));
-+
-+ debug_dma_sync_single_for_cpu(dev, handle, size, dir);
-+
-+ if (!dmabounce_sync_for_cpu(dev, handle, size, dir))
-+ return;
-+
-+ __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
-+}
-+
-+static inline void dma_sync_single_for_device(struct device *dev,
-+ dma_addr_t handle, size_t size, enum dma_data_direction dir)
-+{
-+ BUG_ON(!valid_dma_direction(dir));
-+
-+ debug_dma_sync_single_for_device(dev, handle, size, dir);
-+
-+ if (!dmabounce_sync_for_device(dev, handle, size, dir))
-+ return;
-+
-+ __dma_single_cpu_to_dev(dma_to_virt(dev, handle), size, dir);
-+}
-+
- /**
- * dma_sync_single_range_for_cpu
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
-@@ -423,40 +448,14 @@ static inline void dma_sync_single_range
- dma_addr_t handle, unsigned long offset, size_t size,
- enum dma_data_direction dir)
- {
-- BUG_ON(!valid_dma_direction(dir));
--
-- debug_dma_sync_single_for_cpu(dev, handle + offset, size, dir);
--
-- if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir))
-- return;
--
-- __dma_single_dev_to_cpu(dma_to_virt(dev, handle) + offset, size, dir);
-+ dma_sync_single_for_cpu(dev, handle + offset, size, dir);
- }
-
- static inline void dma_sync_single_range_for_device(struct device *dev,
- dma_addr_t handle, unsigned long offset, size_t size,
- enum dma_data_direction dir)
- {
-- BUG_ON(!valid_dma_direction(dir));
--
-- debug_dma_sync_single_for_device(dev, handle + offset, size, dir);
--
-- if (!dmabounce_sync_for_device(dev, handle, offset, size, dir))
-- return;
--
-- __dma_single_cpu_to_dev(dma_to_virt(dev, handle) + offset, size, dir);
--}
--
--static inline void dma_sync_single_for_cpu(struct device *dev,
-- dma_addr_t handle, size_t size, enum dma_data_direction dir)
--{
-- dma_sync_single_range_for_cpu(dev, handle, 0, size, dir);
--}
--
--static inline void dma_sync_single_for_device(struct device *dev,
-- dma_addr_t handle, size_t size, enum dma_data_direction dir)
--{
-- dma_sync_single_range_for_device(dev, handle, 0, size, dir);
-+ dma_sync_single_for_device(dev, handle + offset, size, dir);
- }
-
- /*
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -898,7 +898,7 @@ void dma_sync_sg_for_cpu(struct device *
- int i;
-
- for_each_sg(sg, s, nents, i) {
-- if (!dmabounce_sync_for_cpu(dev, sg_dma_address(s), 0,
-+ if (!dmabounce_sync_for_cpu(dev, sg_dma_address(s),
- sg_dma_len(s), dir))
- continue;
-
-@@ -924,7 +924,7 @@ void dma_sync_sg_for_device(struct devic
- int i;
-
- for_each_sg(sg, s, nents, i) {
-- if (!dmabounce_sync_for_device(dev, sg_dma_address(s), 0,
-+ if (!dmabounce_sync_for_device(dev, sg_dma_address(s),
- sg_dma_len(s), dir))
- continue;
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:52 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:43 +0900
-Subject: [PATCH v2 26/58] ARM: dma-mapping: remove redundant code and do the cleanup
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-27-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-This patch just performs a global cleanup in DMA mapping implementation
-for ARM architecture. Some of the tiny helper functions have been moved
-to the caller code, some have been merged together.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Tested-By: Subash Patel <subash.ramaswamy@linaro.org>
-(cherry picked from commit 51fde3499b531d4cf278f4d2eaa6c45b2865b16b)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/mm/dma-mapping.c | 88 ++++++++++++----------------------------------
- 1 file changed, 24 insertions(+), 64 deletions(-)
-
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -45,64 +45,12 @@
- * the CPU does do speculative prefetches, which means we clean caches
- * before transfers and delay cache invalidation until transfer completion.
- *
-- * Private support functions: these are not part of the API and are
-- * liable to change. Drivers must not use these.
- */
--static inline void __dma_single_cpu_to_dev(const void *kaddr, size_t size,
-- enum dma_data_direction dir)
--{
-- extern void ___dma_single_cpu_to_dev(const void *, size_t,
-- enum dma_data_direction);
--
-- if (!arch_is_coherent())
-- ___dma_single_cpu_to_dev(kaddr, size, dir);
--}
--
--static inline void __dma_single_dev_to_cpu(const void *kaddr, size_t size,
-- enum dma_data_direction dir)
--{
-- extern void ___dma_single_dev_to_cpu(const void *, size_t,
-- enum dma_data_direction);
--
-- if (!arch_is_coherent())
-- ___dma_single_dev_to_cpu(kaddr, size, dir);
--}
--
--static inline void __dma_page_cpu_to_dev(struct page *page, unsigned long off,
-- size_t size, enum dma_data_direction dir)
--{
-- extern void ___dma_page_cpu_to_dev(struct page *, unsigned long,
-+static void __dma_page_cpu_to_dev(struct page *, unsigned long,
- size_t, enum dma_data_direction);
--
-- if (!arch_is_coherent())
-- ___dma_page_cpu_to_dev(page, off, size, dir);
--}
--
--static inline void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
-- size_t size, enum dma_data_direction dir)
--{
-- extern void ___dma_page_dev_to_cpu(struct page *, unsigned long,
-+static void __dma_page_dev_to_cpu(struct page *, unsigned long,
- size_t, enum dma_data_direction);
-
-- if (!arch_is_coherent())
-- ___dma_page_dev_to_cpu(page, off, size, dir);
--}
--
--
--static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
-- unsigned long offset, size_t size, enum dma_data_direction dir)
--{
-- __dma_page_cpu_to_dev(page, offset, size, dir);
-- return pfn_to_dma(dev, page_to_pfn(page)) + offset;
--}
--
--static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
-- size_t size, enum dma_data_direction dir)
--{
-- __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
-- handle & ~PAGE_MASK, size, dir);
--}
--
- /**
- * arm_dma_map_page - map a portion of a page for streaming DMA
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
-@@ -117,11 +65,13 @@ static inline void __dma_unmap_page(stru
- * The device owns this memory once this call has completed. The CPU
- * can regain ownership by calling dma_unmap_page().
- */
--static inline dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
-+static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
- {
-- return __dma_map_page(dev, page, offset, size, dir);
-+ if (!arch_is_coherent())
-+ __dma_page_cpu_to_dev(page, offset, size, dir);
-+ return pfn_to_dma(dev, page_to_pfn(page)) + offset;
- }
-
- /**
-@@ -138,27 +88,31 @@ static inline dma_addr_t arm_dma_map_pag
- * After this call, reads by the CPU to the buffer are guaranteed to see
- * whatever the device wrote there.
- */
--static inline void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
-+static void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
- {
-- __dma_unmap_page(dev, handle, size, dir);
-+ if (!arch_is_coherent())
-+ __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
-+ handle & ~PAGE_MASK, size, dir);
- }
-
--static inline void arm_dma_sync_single_for_cpu(struct device *dev,
-+static void arm_dma_sync_single_for_cpu(struct device *dev,
- dma_addr_t handle, size_t size, enum dma_data_direction dir)
- {
- unsigned int offset = handle & (PAGE_SIZE - 1);
- struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
-- __dma_page_dev_to_cpu(page, offset, size, dir);
-+ if (!arch_is_coherent())
-+ __dma_page_dev_to_cpu(page, offset, size, dir);
- }
-
--static inline void arm_dma_sync_single_for_device(struct device *dev,
-+static void arm_dma_sync_single_for_device(struct device *dev,
- dma_addr_t handle, size_t size, enum dma_data_direction dir)
- {
- unsigned int offset = handle & (PAGE_SIZE - 1);
- struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
-- __dma_page_cpu_to_dev(page, offset, size, dir);
-+ if (!arch_is_coherent())
-+ __dma_page_cpu_to_dev(page, offset, size, dir);
- }
-
- static int arm_dma_set_mask(struct device *dev, u64 dma_mask);
-@@ -885,7 +839,13 @@ static void dma_cache_maint_page(struct
- } while (left);
- }
-
--void ___dma_page_cpu_to_dev(struct page *page, unsigned long off,
-+/*
-+ * Make an area consistent for devices.
-+ * Note: Drivers should NOT use this function directly, as it will break
-+ * platforms with CONFIG_DMABOUNCE.
-+ * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
-+ */
-+static void __dma_page_cpu_to_dev(struct page *page, unsigned long off,
- size_t size, enum dma_data_direction dir)
- {
- unsigned long paddr;
-@@ -901,7 +861,7 @@ void ___dma_page_cpu_to_dev(struct page
- /* FIXME: non-speculating: flush on bidirectional mappings? */
- }
-
--void ___dma_page_dev_to_cpu(struct page *page, unsigned long off,
-+static void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
- size_t size, enum dma_data_direction dir)
- {
- unsigned long paddr = page_to_phys(page) + off;
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:59 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:46 +0900
-Subject: [PATCH v2 29/58] ARM: dma-mapping: remove unconditional dependency on CMA
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-30-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-CMA has been enabled unconditionally on all ARMv6+ systems to solve the
-long standing issue of double kernel mappings for all dma coherent
-buffers. This however created a dependency on CONFIG_EXPERIMENTAL for
-the whole ARM architecture what should be really avoided. This patch
-removes this dependency and lets one use old, well-tested dma-mapping
-implementation also on ARMv6+ systems without the need to use
-EXPERIMENTAL stuff.
-
-Reported-by: Russell King <linux@arm.linux.org.uk>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit f1ae98da8525c6b8b1c301c3a2b0bd2b6515cca2)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/Kconfig | 1 -
- arch/arm/mm/dma-mapping.c | 10 ++++------
- 2 files changed, 4 insertions(+), 7 deletions(-)
-
-diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
-index c7a542c..5c0c50e 100644
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -6,7 +6,6 @@ config ARM
- select HAVE_IDE if PCI || ISA || PCMCIA
- select HAVE_DMA_ATTRS
- select HAVE_DMA_CONTIGUOUS if (CPU_V6 || CPU_V6K || CPU_V7)
-- select CMA if (CPU_V6 || CPU_V6K || CPU_V7)
- select HAVE_MEMBLOCK
- select RTC_LIB
- select SYS_SUPPORTS_APM_EMULATION
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index ea6b431..106c4c0 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -268,10 +268,8 @@ static int __init consistent_init(void)
- unsigned long base = consistent_base;
- unsigned long num_ptes = (CONSISTENT_END - base) >> PMD_SHIFT;
-
--#ifndef CONFIG_ARM_DMA_USE_IOMMU
-- if (cpu_architecture() >= CPU_ARCH_ARMv6)
-+ if (IS_ENABLED(CONFIG_CMA) && !IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU))
- return 0;
--#endif
-
- consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL);
- if (!consistent_pte) {
-@@ -342,7 +340,7 @@ static int __init coherent_init(void)
- struct page *page;
- void *ptr;
-
-- if (cpu_architecture() < CPU_ARCH_ARMv6)
-+ if (!IS_ENABLED(CONFIG_CMA))
- return 0;
-
- ptr = __alloc_from_contiguous(NULL, size, prot, &page);
-@@ -704,7 +702,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
-
- if (arch_is_coherent() || nommu())
- addr = __alloc_simple_buffer(dev, size, gfp, &page);
-- else if (cpu_architecture() < CPU_ARCH_ARMv6)
-+ else if (!IS_ENABLED(CONFIG_CMA))
- addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
- else if (gfp & GFP_ATOMIC)
- addr = __alloc_from_pool(dev, size, &page, caller);
-@@ -773,7 +771,7 @@ void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
-
- if (arch_is_coherent() || nommu()) {
- __dma_free_buffer(page, size);
-- } else if (cpu_architecture() < CPU_ARCH_ARMv6) {
-+ } else if (!IS_ENABLED(CONFIG_CMA)) {
- __dma_free_remap(cpu_addr, size);
- __dma_free_buffer(page, size);
- } else {
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:55 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:44 +0900
-Subject: [PATCH v2 27/58] ARM: dma-mapping: use alloc, mmap, free from dma_ops
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-28-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-This patch converts dma_alloc/free/mmap_{coherent,writecombine}
-functions to use generic alloc/free/mmap methods from dma_map_ops
-structure. A new DMA_ATTR_WRITE_COMBINE DMA attribute have been
-introduced to implement writecombine methods.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Tested-By: Subash Patel <subash.ramaswamy@linaro.org>
-(cherry picked from commit f99d60341238fe73fc514129cd9ae4e44e1b2c47)
-
-Conflicts:
-
- arch/arm/mm/dma-mapping.c
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/common/dmabounce.c | 3 +
- arch/arm/include/asm/dma-mapping.h | 107 ++++++++++++++++++++++++++----------
- arch/arm/mm/dma-mapping.c | 61 ++++++++------------
- 3 files changed, 104 insertions(+), 67 deletions(-)
-
-diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
-index 813c29d..9d7eb53 100644
---- a/arch/arm/common/dmabounce.c
-+++ b/arch/arm/common/dmabounce.c
-@@ -449,6 +449,9 @@ static int dmabounce_set_mask(struct device *dev, u64 dma_mask)
- }
-
- static struct dma_map_ops dmabounce_ops = {
-+ .alloc = arm_dma_alloc,
-+ .free = arm_dma_free,
-+ .mmap = arm_dma_mmap,
- .map_page = dmabounce_map_page,
- .unmap_page = dmabounce_unmap_page,
- .sync_single_for_cpu = dmabounce_sync_for_cpu,
-diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
-index 7a7c3c7..bbef15d 100644
---- a/arch/arm/include/asm/dma-mapping.h
-+++ b/arch/arm/include/asm/dma-mapping.h
-@@ -5,6 +5,7 @@
-
- #include <linux/mm_types.h>
- #include <linux/scatterlist.h>
-+#include <linux/dma-attrs.h>
- #include <linux/dma-debug.h>
-
- #include <asm-generic/dma-coherent.h>
-@@ -110,68 +111,115 @@ static inline void dma_free_noncoherent(struct device *dev, size_t size,
- extern int dma_supported(struct device *dev, u64 mask);
-
- /**
-- * dma_alloc_coherent - allocate consistent memory for DMA
-+ * arm_dma_alloc - allocate consistent memory for DMA
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @size: required memory size
- * @handle: bus-specific DMA address
-+ * @attrs: optinal attributes that specific mapping properties
- *
-- * Allocate some uncached, unbuffered memory for a device for
-- * performing DMA. This function allocates pages, and will
-- * return the CPU-viewed address, and sets @handle to be the
-- * device-viewed address.
-+ * Allocate some memory for a device for performing DMA. This function
-+ * allocates pages, and will return the CPU-viewed address, and sets @handle
-+ * to be the device-viewed address.
- */
--extern void *dma_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t);
-+extern void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
-+ gfp_t gfp, struct dma_attrs *attrs);
-+
-+#define dma_alloc_coherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
-+
-+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
-+ dma_addr_t *dma_handle, gfp_t flag,
-+ struct dma_attrs *attrs)
-+{
-+ struct dma_map_ops *ops = get_dma_ops(dev);
-+ void *cpu_addr;
-+ BUG_ON(!ops);
-+
-+ cpu_addr = ops->alloc(dev, size, dma_handle, flag, attrs);
-+ debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr);
-+ return cpu_addr;
-+}
-
- /**
-- * dma_free_coherent - free memory allocated by dma_alloc_coherent
-+ * arm_dma_free - free memory allocated by arm_dma_alloc
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @size: size of memory originally requested in dma_alloc_coherent
- * @cpu_addr: CPU-view address returned from dma_alloc_coherent
- * @handle: device-view address returned from dma_alloc_coherent
-+ * @attrs: optinal attributes that specific mapping properties
- *
- * Free (and unmap) a DMA buffer previously allocated by
-- * dma_alloc_coherent().
-+ * arm_dma_alloc().
- *
- * References to memory and mappings associated with cpu_addr/handle
- * during and after this call executing are illegal.
- */
--extern void dma_free_coherent(struct device *, size_t, void *, dma_addr_t);
-+extern void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
-+ dma_addr_t handle, struct dma_attrs *attrs);
-+
-+#define dma_free_coherent(d, s, c, h) dma_free_attrs(d, s, c, h, NULL)
-+
-+static inline void dma_free_attrs(struct device *dev, size_t size,
-+ void *cpu_addr, dma_addr_t dma_handle,
-+ struct dma_attrs *attrs)
-+{
-+ struct dma_map_ops *ops = get_dma_ops(dev);
-+ BUG_ON(!ops);
-+
-+ debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
-+ ops->free(dev, size, cpu_addr, dma_handle, attrs);
-+}
-
- /**
-- * dma_mmap_coherent - map a coherent DMA allocation into user space
-+ * arm_dma_mmap - map a coherent DMA allocation into user space
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @vma: vm_area_struct describing requested user mapping
- * @cpu_addr: kernel CPU-view address returned from dma_alloc_coherent
- * @handle: device-view address returned from dma_alloc_coherent
- * @size: size of memory originally requested in dma_alloc_coherent
-+ * @attrs: optinal attributes that specific mapping properties
- *
- * Map a coherent DMA buffer previously allocated by dma_alloc_coherent
- * into user space. The coherent DMA buffer must not be freed by the
- * driver until the user space mapping has been released.
- */
--int dma_mmap_coherent(struct device *, struct vm_area_struct *,
-- void *, dma_addr_t, size_t);
-+extern int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
-+ void *cpu_addr, dma_addr_t dma_addr, size_t size,
-+ struct dma_attrs *attrs);
-
-+#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, NULL)
-
--/**
-- * dma_alloc_writecombine - allocate writecombining memory for DMA
-- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
-- * @size: required memory size
-- * @handle: bus-specific DMA address
-- *
-- * Allocate some uncached, buffered memory for a device for
-- * performing DMA. This function allocates pages, and will
-- * return the CPU-viewed address, and sets @handle to be the
-- * device-viewed address.
-- */
--extern void *dma_alloc_writecombine(struct device *, size_t, dma_addr_t *,
-- gfp_t);
-+static inline int dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
-+ void *cpu_addr, dma_addr_t dma_addr,
-+ size_t size, struct dma_attrs *attrs)
-+{
-+ struct dma_map_ops *ops = get_dma_ops(dev);
-+ BUG_ON(!ops);
-+ return ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
-+}
-
--#define dma_free_writecombine(dev,size,cpu_addr,handle) \
-- dma_free_coherent(dev,size,cpu_addr,handle)
-+static inline void *dma_alloc_writecombine(struct device *dev, size_t size,
-+ dma_addr_t *dma_handle, gfp_t flag)
-+{
-+ DEFINE_DMA_ATTRS(attrs);
-+ dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
-+ return dma_alloc_attrs(dev, size, dma_handle, flag, &attrs);
-+}
-
--int dma_mmap_writecombine(struct device *, struct vm_area_struct *,
-- void *, dma_addr_t, size_t);
-+static inline void dma_free_writecombine(struct device *dev, size_t size,
-+ void *cpu_addr, dma_addr_t dma_handle)
-+{
-+ DEFINE_DMA_ATTRS(attrs);
-+ dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
-+ return dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
-+}
-+
-+static inline int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma,
-+ void *cpu_addr, dma_addr_t dma_addr, size_t size)
-+{
-+ DEFINE_DMA_ATTRS(attrs);
-+ dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
-+ return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs);
-+}
-
- /*
- * This can be called during boot to increase the size of the consistent
-@@ -180,7 +228,6 @@ int dma_mmap_writecombine(struct device *, struct vm_area_struct *,
- */
- extern void __init init_consistent_dma_size(unsigned long size);
-
--
- /*
- * For SA-1111, IXP425, and ADI systems the dma-mapping functions are "magic"
- * and utilize bounce buffers as needed to work around limited DMA windows.
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index f7fbbda..ee4cb48 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -118,6 +118,9 @@ static void arm_dma_sync_single_for_device(struct device *dev,
- static int arm_dma_set_mask(struct device *dev, u64 dma_mask);
-
- struct dma_map_ops arm_dma_ops = {
-+ .alloc = arm_dma_alloc,
-+ .free = arm_dma_free,
-+ .mmap = arm_dma_mmap,
- .map_page = arm_dma_map_page,
- .unmap_page = arm_dma_unmap_page,
- .map_sg = arm_dma_map_sg,
-@@ -620,12 +623,21 @@ static void __free_from_contiguous(struct device *dev, struct page *page,
- dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
- }
-
-+static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot)
-+{
-+ prot = dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs) ?
-+ pgprot_writecombine(prot) :
-+ pgprot_dmacoherent(prot);
-+ return prot;
-+}
-+
- #define nommu() 0
-
- #else /* !CONFIG_MMU */
-
- #define nommu() 1
-
-+#define __get_dma_pgprot(attrs, prot) __pgprot(0)
- #define __alloc_remap_buffer(dev, size, gfp, prot, ret, c) NULL
- #define __alloc_from_pool(dev, size, ret_page, c) NULL
- #define __alloc_from_contiguous(dev, size, prot, ret) NULL
-@@ -702,39 +714,31 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
- * Allocate DMA-coherent memory space and return both the kernel remapped
- * virtual and bus address for that space.
- */
--void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle,
-- gfp_t gfp)
-+void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
-+ gfp_t gfp, struct dma_attrs *attrs)
- {
-+ pgprot_t prot = __get_dma_pgprot(attrs, pgprot_kernel);
- void *memory;
-
- if (dma_alloc_from_coherent(dev, size, handle, &memory))
- return memory;
-
-- return __dma_alloc(dev, size, handle, gfp,
-- pgprot_dmacoherent(pgprot_kernel),
-+ return __dma_alloc(dev, size, handle, gfp, prot,
- __builtin_return_address(0));
- }
--EXPORT_SYMBOL(dma_alloc_coherent);
-
- /*
-- * Allocate a writecombining region, in much the same way as
-- * dma_alloc_coherent above.
-+ * Create userspace mapping for the DMA-coherent memory.
- */
--void *
--dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
--{
-- return __dma_alloc(dev, size, handle, gfp,
-- pgprot_writecombine(pgprot_kernel),
-- __builtin_return_address(0));
--}
--EXPORT_SYMBOL(dma_alloc_writecombine);
--
--static int dma_mmap(struct device *dev, struct vm_area_struct *vma,
-- void *cpu_addr, dma_addr_t dma_addr, size_t size)
-+int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
-+ void *cpu_addr, dma_addr_t dma_addr, size_t size,
-+ struct dma_attrs *attrs)
- {
- int ret = -ENXIO;
- #ifdef CONFIG_MMU
- unsigned long pfn = dma_to_pfn(dev, dma_addr);
-+ vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
-+
- if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
- return ret;
-
-@@ -747,27 +751,11 @@ static int dma_mmap(struct device *dev, struct vm_area_struct *vma,
- return ret;
- }
-
--int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
-- void *cpu_addr, dma_addr_t dma_addr, size_t size)
--{
-- vma->vm_page_prot = pgprot_dmacoherent(vma->vm_page_prot);
-- return dma_mmap(dev, vma, cpu_addr, dma_addr, size);
--}
--EXPORT_SYMBOL(dma_mmap_coherent);
--
--int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma,
-- void *cpu_addr, dma_addr_t dma_addr, size_t size)
--{
-- vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-- return dma_mmap(dev, vma, cpu_addr, dma_addr, size);
--}
--EXPORT_SYMBOL(dma_mmap_writecombine);
--
--
- /*
- * Free a buffer as defined by the above mapping.
- */
--void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle)
-+void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
-+ dma_addr_t handle, struct dma_attrs *attrs)
- {
- struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
-
-@@ -791,7 +779,6 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
- __free_from_contiguous(dev, page, size);
- }
- }
--EXPORT_SYMBOL(dma_free_coherent);
-
- static void dma_cache_maint_page(struct page *page, unsigned long offset,
- size_t size, enum dma_data_direction dir,
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:45 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:40 +0900
-Subject: [PATCH v2 23/58] ARM: dma-mapping: use asm-generic/dma-mapping-common.h
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-24-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-This patch modifies dma-mapping implementation on ARM architecture to
-use common dma_map_ops structure and asm-generic/dma-mapping-common.h
-helpers.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
-Tested-By: Subash Patel <subash.ramaswamy@linaro.org>
-(cherry picked from commit 2dc6a016bbedf18f18ad73997e5338307d6dbde9)
-
-Conflicts:
-
- arch/arm/Kconfig
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/Kconfig | 1
- arch/arm/include/asm/device.h | 1
- arch/arm/include/asm/dma-mapping.h | 196 +++++--------------------------------
- arch/arm/mm/dma-mapping.c | 148 ++++++++++++++++-----------
- 4 files changed, 115 insertions(+), 231 deletions(-)
-
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -4,6 +4,7 @@ config ARM
- select HAVE_AOUT
- select HAVE_DMA_API_DEBUG
- select HAVE_IDE if PCI || ISA || PCMCIA
-+ select HAVE_DMA_ATTRS
- select HAVE_DMA_CONTIGUOUS if (CPU_V6 || CPU_V6K || CPU_V7)
- select CMA if (CPU_V6 || CPU_V6K || CPU_V7)
- select HAVE_MEMBLOCK
---- a/arch/arm/include/asm/device.h
-+++ b/arch/arm/include/asm/device.h
-@@ -7,6 +7,7 @@
- #define ASMARM_DEVICE_H
-
- struct dev_archdata {
-+ struct dma_map_ops *dma_ops;
- #ifdef CONFIG_DMABOUNCE
- struct dmabounce_device_info *dmabounce;
- #endif
---- a/arch/arm/include/asm/dma-mapping.h
-+++ b/arch/arm/include/asm/dma-mapping.h
-@@ -11,6 +11,27 @@
- #include <asm/memory.h>
-
- #define DMA_ERROR_CODE (~0)
-+extern struct dma_map_ops arm_dma_ops;
-+
-+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
-+{
-+ if (dev && dev->archdata.dma_ops)
-+ return dev->archdata.dma_ops;
-+ return &arm_dma_ops;
-+}
-+
-+static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
-+{
-+ BUG_ON(!dev);
-+ dev->archdata.dma_ops = ops;
-+}
-+
-+#include <asm-generic/dma-mapping-common.h>
-+
-+static inline int dma_set_mask(struct device *dev, u64 mask)
-+{
-+ return get_dma_ops(dev)->set_dma_mask(dev, mask);
-+}
-
- #ifdef __arch_page_to_dma
- #error Please update to __arch_pfn_to_dma
-@@ -119,7 +140,6 @@ static inline void __dma_page_dev_to_cpu
-
- extern int dma_supported(struct device *, u64);
- extern int dma_set_mask(struct device *, u64);
--
- /*
- * DMA errors are defined by all-bits-set in the DMA address.
- */
-@@ -297,179 +317,17 @@ static inline void __dma_unmap_page(stru
- }
- #endif /* CONFIG_DMABOUNCE */
-
--/**
-- * dma_map_single - map a single buffer for streaming DMA
-- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
-- * @cpu_addr: CPU direct mapped address of buffer
-- * @size: size of buffer to map
-- * @dir: DMA transfer direction
-- *
-- * Ensure that any data held in the cache is appropriately discarded
-- * or written back.
-- *
-- * The device owns this memory once this call has completed. The CPU
-- * can regain ownership by calling dma_unmap_single() or
-- * dma_sync_single_for_cpu().
-- */
--static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
-- size_t size, enum dma_data_direction dir)
--{
-- unsigned long offset;
-- struct page *page;
-- dma_addr_t addr;
--
-- BUG_ON(!virt_addr_valid(cpu_addr));
-- BUG_ON(!virt_addr_valid(cpu_addr + size - 1));
-- BUG_ON(!valid_dma_direction(dir));
--
-- page = virt_to_page(cpu_addr);
-- offset = (unsigned long)cpu_addr & ~PAGE_MASK;
-- addr = __dma_map_page(dev, page, offset, size, dir);
-- debug_dma_map_page(dev, page, offset, size, dir, addr, true);
--
-- return addr;
--}
--
--/**
-- * dma_map_page - map a portion of a page for streaming DMA
-- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
-- * @page: page that buffer resides in
-- * @offset: offset into page for start of buffer
-- * @size: size of buffer to map
-- * @dir: DMA transfer direction
-- *
-- * Ensure that any data held in the cache is appropriately discarded
-- * or written back.
-- *
-- * The device owns this memory once this call has completed. The CPU
-- * can regain ownership by calling dma_unmap_page().
-- */
--static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
-- unsigned long offset, size_t size, enum dma_data_direction dir)
--{
-- dma_addr_t addr;
--
-- BUG_ON(!valid_dma_direction(dir));
--
-- addr = __dma_map_page(dev, page, offset, size, dir);
-- debug_dma_map_page(dev, page, offset, size, dir, addr, false);
--
-- return addr;
--}
--
--/**
-- * dma_unmap_single - unmap a single buffer previously mapped
-- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
-- * @handle: DMA address of buffer
-- * @size: size of buffer (same as passed to dma_map_single)
-- * @dir: DMA transfer direction (same as passed to dma_map_single)
-- *
-- * Unmap a single streaming mode DMA translation. The handle and size
-- * must match what was provided in the previous dma_map_single() call.
-- * All other usages are undefined.
-- *
-- * After this call, reads by the CPU to the buffer are guaranteed to see
-- * whatever the device wrote there.
-- */
--static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
-- size_t size, enum dma_data_direction dir)
--{
-- debug_dma_unmap_page(dev, handle, size, dir, true);
-- __dma_unmap_page(dev, handle, size, dir);
--}
--
--/**
-- * dma_unmap_page - unmap a buffer previously mapped through dma_map_page()
-- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
-- * @handle: DMA address of buffer
-- * @size: size of buffer (same as passed to dma_map_page)
-- * @dir: DMA transfer direction (same as passed to dma_map_page)
-- *
-- * Unmap a page streaming mode DMA translation. The handle and size
-- * must match what was provided in the previous dma_map_page() call.
-- * All other usages are undefined.
-- *
-- * After this call, reads by the CPU to the buffer are guaranteed to see
-- * whatever the device wrote there.
-- */
--static inline void dma_unmap_page(struct device *dev, dma_addr_t handle,
-- size_t size, enum dma_data_direction dir)
--{
-- debug_dma_unmap_page(dev, handle, size, dir, false);
-- __dma_unmap_page(dev, handle, size, dir);
--}
--
--
--static inline void dma_sync_single_for_cpu(struct device *dev,
-- dma_addr_t handle, size_t size, enum dma_data_direction dir)
--{
-- BUG_ON(!valid_dma_direction(dir));
--
-- debug_dma_sync_single_for_cpu(dev, handle, size, dir);
--
-- if (!dmabounce_sync_for_cpu(dev, handle, size, dir))
-- return;
--
-- __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
--}
--
--static inline void dma_sync_single_for_device(struct device *dev,
-- dma_addr_t handle, size_t size, enum dma_data_direction dir)
--{
-- BUG_ON(!valid_dma_direction(dir));
--
-- debug_dma_sync_single_for_device(dev, handle, size, dir);
--
-- if (!dmabounce_sync_for_device(dev, handle, size, dir))
-- return;
--
-- __dma_single_cpu_to_dev(dma_to_virt(dev, handle), size, dir);
--}
--
--/**
-- * dma_sync_single_range_for_cpu
-- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
-- * @handle: DMA address of buffer
-- * @offset: offset of region to start sync
-- * @size: size of region to sync
-- * @dir: DMA transfer direction (same as passed to dma_map_single)
-- *
-- * Make physical memory consistent for a single streaming mode DMA
-- * translation after a transfer.
-- *
-- * If you perform a dma_map_single() but wish to interrogate the
-- * buffer using the cpu, yet do not wish to teardown the PCI dma
-- * mapping, you must call this function before doing so. At the
-- * next point you give the PCI dma address back to the card, you
-- * must first the perform a dma_sync_for_device, and then the
-- * device again owns the buffer.
-- */
--static inline void dma_sync_single_range_for_cpu(struct device *dev,
-- dma_addr_t handle, unsigned long offset, size_t size,
-- enum dma_data_direction dir)
--{
-- dma_sync_single_for_cpu(dev, handle + offset, size, dir);
--}
--
--static inline void dma_sync_single_range_for_device(struct device *dev,
-- dma_addr_t handle, unsigned long offset, size_t size,
-- enum dma_data_direction dir)
--{
-- dma_sync_single_for_device(dev, handle + offset, size, dir);
--}
--
- /*
- * The scatter list versions of the above methods.
- */
--extern int dma_map_sg(struct device *, struct scatterlist *, int,
-- enum dma_data_direction);
--extern void dma_unmap_sg(struct device *, struct scatterlist *, int,
-+extern int arm_dma_map_sg(struct device *, struct scatterlist *, int,
-+ enum dma_data_direction, struct dma_attrs *attrs);
-+extern void arm_dma_unmap_sg(struct device *, struct scatterlist *, int,
-+ enum dma_data_direction, struct dma_attrs *attrs);
-+extern void arm_dma_sync_sg_for_cpu(struct device *, struct scatterlist *, int,
- enum dma_data_direction);
--extern void dma_sync_sg_for_cpu(struct device *, struct scatterlist *, int,
-+extern void arm_dma_sync_sg_for_device(struct device *, struct scatterlist *, int,
- enum dma_data_direction);
--extern void dma_sync_sg_for_device(struct device *, struct scatterlist *, int,
-- enum dma_data_direction);
--
-
- #endif /* __KERNEL__ */
- #endif
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -34,6 +34,85 @@
-
- #include "mm.h"
-
-+/**
-+ * arm_dma_map_page - map a portion of a page for streaming DMA
-+ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
-+ * @page: page that buffer resides in
-+ * @offset: offset into page for start of buffer
-+ * @size: size of buffer to map
-+ * @dir: DMA transfer direction
-+ *
-+ * Ensure that any data held in the cache is appropriately discarded
-+ * or written back.
-+ *
-+ * The device owns this memory once this call has completed. The CPU
-+ * can regain ownership by calling dma_unmap_page().
-+ */
-+static inline dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
-+ unsigned long offset, size_t size, enum dma_data_direction dir,
-+ struct dma_attrs *attrs)
-+{
-+ return __dma_map_page(dev, page, offset, size, dir);
-+}
-+
-+/**
-+ * arm_dma_unmap_page - unmap a buffer previously mapped through dma_map_page()
-+ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
-+ * @handle: DMA address of buffer
-+ * @size: size of buffer (same as passed to dma_map_page)
-+ * @dir: DMA transfer direction (same as passed to dma_map_page)
-+ *
-+ * Unmap a page streaming mode DMA translation. The handle and size
-+ * must match what was provided in the previous dma_map_page() call.
-+ * All other usages are undefined.
-+ *
-+ * After this call, reads by the CPU to the buffer are guaranteed to see
-+ * whatever the device wrote there.
-+ */
-+static inline void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
-+ size_t size, enum dma_data_direction dir,
-+ struct dma_attrs *attrs)
-+{
-+ __dma_unmap_page(dev, handle, size, dir);
-+}
-+
-+static inline void arm_dma_sync_single_for_cpu(struct device *dev,
-+ dma_addr_t handle, size_t size, enum dma_data_direction dir)
-+{
-+ unsigned int offset = handle & (PAGE_SIZE - 1);
-+ struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
-+ if (!dmabounce_sync_for_cpu(dev, handle, size, dir))
-+ return;
-+
-+ __dma_page_dev_to_cpu(page, offset, size, dir);
-+}
-+
-+static inline void arm_dma_sync_single_for_device(struct device *dev,
-+ dma_addr_t handle, size_t size, enum dma_data_direction dir)
-+{
-+ unsigned int offset = handle & (PAGE_SIZE - 1);
-+ struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
-+ if (!dmabounce_sync_for_device(dev, handle, size, dir))
-+ return;
-+
-+ __dma_page_cpu_to_dev(page, offset, size, dir);
-+}
-+
-+static int arm_dma_set_mask(struct device *dev, u64 dma_mask);
-+
-+struct dma_map_ops arm_dma_ops = {
-+ .map_page = arm_dma_map_page,
-+ .unmap_page = arm_dma_unmap_page,
-+ .map_sg = arm_dma_map_sg,
-+ .unmap_sg = arm_dma_unmap_sg,
-+ .sync_single_for_cpu = arm_dma_sync_single_for_cpu,
-+ .sync_single_for_device = arm_dma_sync_single_for_device,
-+ .sync_sg_for_cpu = arm_dma_sync_sg_for_cpu,
-+ .sync_sg_for_device = arm_dma_sync_sg_for_device,
-+ .set_dma_mask = arm_dma_set_mask,
-+};
-+EXPORT_SYMBOL(arm_dma_ops);
-+
- static u64 get_coherent_dma_mask(struct device *dev)
- {
- u64 mask = (u64)arm_dma_limit;
-@@ -697,47 +776,6 @@ void dma_free_coherent(struct device *de
- }
- EXPORT_SYMBOL(dma_free_coherent);
-
--/*
-- * Make an area consistent for devices.
-- * Note: Drivers should NOT use this function directly, as it will break
-- * platforms with CONFIG_DMABOUNCE.
-- * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
-- */
--void ___dma_single_cpu_to_dev(const void *kaddr, size_t size,
-- enum dma_data_direction dir)
--{
-- unsigned long paddr;
--
-- BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1));
--
-- dmac_map_area(kaddr, size, dir);
--
-- paddr = __pa(kaddr);
-- if (dir == DMA_FROM_DEVICE) {
-- outer_inv_range(paddr, paddr + size);
-- } else {
-- outer_clean_range(paddr, paddr + size);
-- }
-- /* FIXME: non-speculating: flush on bidirectional mappings? */
--}
--EXPORT_SYMBOL(___dma_single_cpu_to_dev);
--
--void ___dma_single_dev_to_cpu(const void *kaddr, size_t size,
-- enum dma_data_direction dir)
--{
-- BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1));
--
-- /* FIXME: non-speculating: not required */
-- /* don't bother invalidating if DMA to device */
-- if (dir != DMA_TO_DEVICE) {
-- unsigned long paddr = __pa(kaddr);
-- outer_inv_range(paddr, paddr + size);
-- }
--
-- dmac_unmap_area(kaddr, size, dir);
--}
--EXPORT_SYMBOL(___dma_single_dev_to_cpu);
--
- static void dma_cache_maint_page(struct page *page, unsigned long offset,
- size_t size, enum dma_data_direction dir,
- void (*op)(const void *, size_t, int))
-@@ -837,21 +875,18 @@ EXPORT_SYMBOL(___dma_page_dev_to_cpu);
- * Device ownership issues as mentioned for dma_map_single are the same
- * here.
- */
--int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-- enum dma_data_direction dir)
-+int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-+ enum dma_data_direction dir, struct dma_attrs *attrs)
- {
- struct scatterlist *s;
- int i, j;
-
-- BUG_ON(!valid_dma_direction(dir));
--
- for_each_sg(sg, s, nents, i) {
- s->dma_address = __dma_map_page(dev, sg_page(s), s->offset,
- s->length, dir);
- if (dma_mapping_error(dev, s->dma_address))
- goto bad_mapping;
- }
-- debug_dma_map_sg(dev, sg, nents, nents, dir);
- return nents;
-
- bad_mapping:
-@@ -859,7 +894,6 @@ int dma_map_sg(struct device *dev, struc
- __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
- return 0;
- }
--EXPORT_SYMBOL(dma_map_sg);
-
- /**
- * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
-@@ -871,18 +905,15 @@ EXPORT_SYMBOL(dma_map_sg);
- * Unmap a set of streaming mode DMA translations. Again, CPU access
- * rules concerning calls here are the same as for dma_unmap_single().
- */
--void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
-- enum dma_data_direction dir)
-+void arm_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
-+ enum dma_data_direction dir, struct dma_attrs *attrs)
- {
- struct scatterlist *s;
- int i;
-
-- debug_dma_unmap_sg(dev, sg, nents, dir);
--
- for_each_sg(sg, s, nents, i)
- __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
- }
--EXPORT_SYMBOL(dma_unmap_sg);
-
- /**
- * dma_sync_sg_for_cpu
-@@ -891,7 +922,7 @@ EXPORT_SYMBOL(dma_unmap_sg);
- * @nents: number of buffers to map (returned from dma_map_sg)
- * @dir: DMA transfer direction (same as was passed to dma_map_sg)
- */
--void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
-+void arm_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir)
- {
- struct scatterlist *s;
-@@ -905,10 +936,7 @@ void dma_sync_sg_for_cpu(struct device *
- __dma_page_dev_to_cpu(sg_page(s), s->offset,
- s->length, dir);
- }
--
-- debug_dma_sync_sg_for_cpu(dev, sg, nents, dir);
- }
--EXPORT_SYMBOL(dma_sync_sg_for_cpu);
-
- /**
- * dma_sync_sg_for_device
-@@ -917,7 +945,7 @@ EXPORT_SYMBOL(dma_sync_sg_for_cpu);
- * @nents: number of buffers to map (returned from dma_map_sg)
- * @dir: DMA transfer direction (same as was passed to dma_map_sg)
- */
--void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
-+void arm_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir)
- {
- struct scatterlist *s;
-@@ -931,10 +959,7 @@ void dma_sync_sg_for_device(struct devic
- __dma_page_cpu_to_dev(sg_page(s), s->offset,
- s->length, dir);
- }
--
-- debug_dma_sync_sg_for_device(dev, sg, nents, dir);
- }
--EXPORT_SYMBOL(dma_sync_sg_for_device);
-
- /*
- * Return whether the given device DMA address mask can be supported
-@@ -950,7 +975,7 @@ int dma_supported(struct device *dev, u6
- }
- EXPORT_SYMBOL(dma_supported);
-
--int dma_set_mask(struct device *dev, u64 dma_mask)
-+static int arm_dma_set_mask(struct device *dev, u64 dma_mask)
- {
- if (!dev->dma_mask || !dma_supported(dev, dma_mask))
- return -EIO;
-@@ -961,7 +986,6 @@ int dma_set_mask(struct device *dev, u64
-
- return 0;
- }
--EXPORT_SYMBOL(dma_set_mask);
-
- #define PREALLOC_DMA_DEBUG_ENTRIES 4096
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:33 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:36 +0900
-Subject: [PATCH v2 19/58] ARM: dma-mapping: use dma_mmap_from_coherent()
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-20-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit 47142f07eea32e9c108f548a4b06c28bec7df6e4)
-
-Conflicts:
-
- arch/arm/mm/dma-mapping.c
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/mm/dma-mapping.c | 3 +++
- 1 files changed, 3 insertions(+), 0 deletions(-)
-
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index 153f555..210dd10 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -639,6 +639,9 @@ static int dma_mmap(struct device *dev, struct vm_area_struct *vma,
- int ret = -ENXIO;
- #ifdef CONFIG_MMU
- unsigned long pfn = dma_to_pfn(dev, dma_addr);
-+ if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
-+ return ret;
-+
- ret = remap_pfn_range(vma, vma->vm_start,
- pfn + vma->vm_pgoff,
- vma->vm_end - vma->vm_start,
---
-1.7.5.4
-
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Mon Oct 29 00:52:30 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:34 +0900
-Subject: [PATCH v2 17/58] ARM: dma-mapping: use PMD size for section unmap
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org
-Message-ID: <1351497075-32717-18-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Vitaly Andrianov <vitalya@ti.com>
-
-The dma_contiguous_remap() function clears existing section maps using
-the wrong size (PGDIR_SIZE instead of PMD_SIZE). This is a bug which
-does not affect non-LPAE systems, where PGDIR_SIZE and PMD_SIZE are the same.
-On LPAE systems, however, this bug causes the kernel to hang at this point.
-
-This fix has been tested on both LPAE and non-LPAE kernel builds.
-
-Signed-off-by: Vitaly Andrianov <vitalya@ti.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit 61f6c7a47a2f84b7ba4b65240ffe9247df772b06)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/mm/dma-mapping.c | 2 +-
- 1 files changed, 1 insertions(+), 1 deletions(-)
-
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index 302f5bf..153f555 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -295,7 +295,7 @@ void __init dma_contiguous_remap(void)
- * Clear previous low-memory mapping
- */
- for (addr = __phys_to_virt(start); addr < __phys_to_virt(end);
-- addr += PGDIR_SIZE)
-+ addr += PMD_SIZE)
- pmd_clear(pmd_off_k(addr));
-
- iotable_init(&map, 1);
---
-1.7.5.4
-
-_______________________________________________
-LTSI-dev mailing list
-LTSI-dev@lists.linuxfoundation.org
-https://lists.linuxfoundation.org/mailman/listinfo/ltsi-dev
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:36 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:37 +0900
-Subject: [PATCH v2 20/58] ARM: dma-mapping: use pr_* instread of printk
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-21-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-Replace all calls to printk with pr_* functions family.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Tested-By: Subash Patel <subash.ramaswamy@linaro.org>
-(cherry picked from commit 6b6f770b573903f8a7d1cfab1fc662685653f413)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/mm/dma-mapping.c | 16 ++++++++--------
- 1 files changed, 8 insertions(+), 8 deletions(-)
-
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index 210dd10..bb19804 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -181,14 +181,14 @@ static int __init consistent_init(void)
-
- pud = pud_alloc(&init_mm, pgd, base);
- if (!pud) {
-- printk(KERN_ERR "%s: no pud tables\n", __func__);
-+ pr_err("%s: no pud tables\n", __func__);
- ret = -ENOMEM;
- break;
- }
-
- pmd = pmd_alloc(&init_mm, pud, base);
- if (!pmd) {
-- printk(KERN_ERR "%s: no pmd tables\n", __func__);
-+ pr_err("%s: no pmd tables\n", __func__);
- ret = -ENOMEM;
- break;
- }
-@@ -196,7 +196,7 @@ static int __init consistent_init(void)
-
- pte = pte_alloc_kernel(pmd, base);
- if (!pte) {
-- printk(KERN_ERR "%s: no pte tables\n", __func__);
-+ pr_err("%s: no pte tables\n", __func__);
- ret = -ENOMEM;
- break;
- }
-@@ -311,7 +311,7 @@ __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot,
- int bit;
-
- if (!consistent_pte) {
-- printk(KERN_ERR "%s: not initialised\n", __func__);
-+ pr_err("%s: not initialised\n", __func__);
- dump_stack();
- return NULL;
- }
-@@ -370,14 +370,14 @@ static void __dma_free_remap(void *cpu_addr, size_t size)
-
- c = arm_vmregion_find_remove(&consistent_head, (unsigned long)cpu_addr);
- if (!c) {
-- printk(KERN_ERR "%s: trying to free invalid coherent area: %p\n",
-+ pr_err("%s: trying to free invalid coherent area: %p\n",
- __func__, cpu_addr);
- dump_stack();
- return;
- }
-
- if ((c->vm_end - c->vm_start) != size) {
-- printk(KERN_ERR "%s: freeing wrong coherent size (%ld != %d)\n",
-+ pr_err("%s: freeing wrong coherent size (%ld != %d)\n",
- __func__, c->vm_end - c->vm_start, size);
- dump_stack();
- size = c->vm_end - c->vm_start;
-@@ -399,8 +399,8 @@ static void __dma_free_remap(void *cpu_addr, size_t size)
- }
-
- if (pte_none(pte) || !pte_present(pte))
-- printk(KERN_CRIT "%s: bad page in kernel page table\n",
-- __func__);
-+ pr_crit("%s: bad page in kernel page table\n",
-+ __func__);
- } while (size -= PAGE_SIZE);
-
- flush_tlb_kernel_range(c->vm_start, c->vm_end);
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:52 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:06 +0900
-Subject: [PATCH v2 49/58] ARM: fix warning caused by wrongly typed arm_dma_limit
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-50-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Russell King <rmk+kernel@arm.linux.org.uk>
-
-arch/arm/mm/init.c: In function 'arm_memblock_init':
-arch/arm/mm/init.c:380: warning: comparison of distinct pointer types lacks a cast
-
-by fixing the typecast in its definition when DMA_ZONE is disabled.
-This was missed in 4986e5c7c (ARM: mm: fix type of the arm_dma_limit
-global variable).
-
-Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-(cherry picked from commit 09b2ad13da3ac7c717dd86bfca7072d9b36f7449)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mm/mm.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/mm/mm.h
-+++ b/arch/arm/mm/mm.h
-@@ -70,7 +70,7 @@ extern void __flush_dcache_page(struct a
- #ifdef CONFIG_ZONE_DMA
- extern phys_addr_t arm_dma_limit;
- #else
--#define arm_dma_limit ((u32)~0)
-+#define arm_dma_limit ((phys_addr_t)~0)
- #endif
-
- extern phys_addr_t arm_lowmem_limit;
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:24 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:32 +0900
-Subject: [PATCH v2 15/58] ARM: integrate CMA with DMA-mapping subsystem
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-16-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-This patch adds support for CMA to dma-mapping subsystem for ARM
-architecture. By default a global CMA area is used, but specific devices
-are allowed to have their private memory areas if required (they can be
-created with dma_declare_contiguous() function during board
-initialisation).
-
-Contiguous memory areas reserved for DMA are remapped with 2-level page
-tables on boot. Once a buffer is requested, a low memory kernel mapping
-is updated to to match requested memory access type.
-
-GFP_ATOMIC allocations are performed from special pool which is created
-early during boot. This way remapping page attributes is not needed on
-allocation time.
-
-CMA has been enabled unconditionally for ARMv6+ systems.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
-CC: Michal Nazarewicz <mina86@mina86.com>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Tested-by: Rob Clark <rob.clark@linaro.org>
-Tested-by: Ohad Ben-Cohen <ohad@wizery.com>
-Tested-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-Tested-by: Robert Nelson <robertcnelson@gmail.com>
-Tested-by: Barry Song <Baohua.Song@csr.com>
-(cherry picked from commit c79095092834a18ae74cfc08def1a5a101dc106c)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- Documentation/kernel-parameters.txt | 4
- arch/arm/Kconfig | 2
- arch/arm/include/asm/dma-contiguous.h | 15 +
- arch/arm/include/asm/mach/map.h | 1
- arch/arm/kernel/setup.c | 9
- arch/arm/mm/dma-mapping.c | 370 +++++++++++++++++++++++++++-------
- arch/arm/mm/init.c | 23 +-
- arch/arm/mm/mm.h | 3
- arch/arm/mm/mmu.c | 31 +-
- 9 files changed, 370 insertions(+), 88 deletions(-)
- create mode 100644 arch/arm/include/asm/dma-contiguous.h
-
---- a/Documentation/kernel-parameters.txt
-+++ b/Documentation/kernel-parameters.txt
-@@ -520,6 +520,10 @@ bytes respectively. Such letter suffixes
- a hypervisor.
- Default: yes
-
-+ coherent_pool=nn[KMG] [ARM,KNL]
-+ Sets the size of memory pool for coherent, atomic dma
-+ allocations if Contiguous Memory Allocator (CMA) is used.
-+
- code_bytes [X86] How many bytes of object code to print
- in an oops report.
- Range: 0 - 8192
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -4,6 +4,8 @@ config ARM
- select HAVE_AOUT
- select HAVE_DMA_API_DEBUG
- select HAVE_IDE if PCI || ISA || PCMCIA
-+ select HAVE_DMA_CONTIGUOUS if (CPU_V6 || CPU_V6K || CPU_V7)
-+ select CMA if (CPU_V6 || CPU_V6K || CPU_V7)
- select HAVE_MEMBLOCK
- select RTC_LIB
- select SYS_SUPPORTS_APM_EMULATION
---- /dev/null
-+++ b/arch/arm/include/asm/dma-contiguous.h
-@@ -0,0 +1,15 @@
-+#ifndef ASMARM_DMA_CONTIGUOUS_H
-+#define ASMARM_DMA_CONTIGUOUS_H
-+
-+#ifdef __KERNEL__
-+#ifdef CONFIG_CMA
-+
-+#include <linux/types.h>
-+#include <asm-generic/dma-contiguous.h>
-+
-+void dma_contiguous_early_fixup(phys_addr_t base, unsigned long size);
-+
-+#endif
-+#endif
-+
-+#endif
---- a/arch/arm/include/asm/mach/map.h
-+++ b/arch/arm/include/asm/mach/map.h
-@@ -30,6 +30,7 @@ struct map_desc {
- #define MT_MEMORY_DTCM 12
- #define MT_MEMORY_ITCM 13
- #define MT_MEMORY_SO 14
-+#define MT_MEMORY_DMA_READY 15
-
- #ifdef CONFIG_MMU
- extern void iotable_init(struct map_desc *, int);
---- a/arch/arm/kernel/setup.c
-+++ b/arch/arm/kernel/setup.c
-@@ -81,6 +81,7 @@ __setup("fpe=", fpe_setup);
- extern void paging_init(struct machine_desc *desc);
- extern void sanity_check_meminfo(void);
- extern void reboot_setup(char *str);
-+extern void setup_dma_zone(struct machine_desc *desc);
-
- unsigned int processor_id;
- EXPORT_SYMBOL(processor_id);
-@@ -939,12 +940,8 @@ void __init setup_arch(char **cmdline_p)
- machine_desc = mdesc;
- machine_name = mdesc->name;
-
--#ifdef CONFIG_ZONE_DMA
-- if (mdesc->dma_zone_size) {
-- extern unsigned long arm_dma_zone_size;
-- arm_dma_zone_size = mdesc->dma_zone_size;
-- }
--#endif
-+ setup_dma_zone(mdesc);
-+
- if (mdesc->restart_mode)
- reboot_setup(&mdesc->restart_mode);
-
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -17,7 +17,9 @@
- #include <linux/init.h>
- #include <linux/device.h>
- #include <linux/dma-mapping.h>
-+#include <linux/dma-contiguous.h>
- #include <linux/highmem.h>
-+#include <linux/memblock.h>
- #include <linux/slab.h>
-
- #include <asm/memory.h>
-@@ -26,6 +28,9 @@
- #include <asm/tlbflush.h>
- #include <asm/sizes.h>
- #include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/system_info.h>
-+#include <asm/dma-contiguous.h>
-
- #include "mm.h"
-
-@@ -56,6 +61,19 @@ static u64 get_coherent_dma_mask(struct
- return mask;
- }
-
-+static void __dma_clear_buffer(struct page *page, size_t size)
-+{
-+ void *ptr;
-+ /*
-+ * Ensure that the allocated pages are zeroed, and that any data
-+ * lurking in the kernel direct-mapped region is invalidated.
-+ */
-+ ptr = page_address(page);
-+ memset(ptr, 0, size);
-+ dmac_flush_range(ptr, ptr + size);
-+ outer_flush_range(__pa(ptr), __pa(ptr) + size);
-+}
-+
- /*
- * Allocate a DMA buffer for 'dev' of size 'size' using the
- * specified gfp mask. Note that 'size' must be page aligned.
-@@ -64,23 +82,6 @@ static struct page *__dma_alloc_buffer(s
- {
- unsigned long order = get_order(size);
- struct page *page, *p, *e;
-- void *ptr;
-- u64 mask = get_coherent_dma_mask(dev);
--
--#ifdef CONFIG_DMA_API_DEBUG
-- u64 limit = (mask + 1) & ~mask;
-- if (limit && size >= limit) {
-- dev_warn(dev, "coherent allocation too big (requested %#x mask %#llx)\n",
-- size, mask);
-- return NULL;
-- }
--#endif
--
-- if (!mask)
-- return NULL;
--
-- if (mask < 0xffffffffULL)
-- gfp |= GFP_DMA;
-
- page = alloc_pages(gfp, order);
- if (!page)
-@@ -93,14 +94,7 @@ static struct page *__dma_alloc_buffer(s
- for (p = page + (size >> PAGE_SHIFT), e = page + (1 << order); p < e; p++)
- __free_page(p);
-
-- /*
-- * Ensure that the allocated pages are zeroed, and that any data
-- * lurking in the kernel direct-mapped region is invalidated.
-- */
-- ptr = page_address(page);
-- memset(ptr, 0, size);
-- dmac_flush_range(ptr, ptr + size);
-- outer_flush_range(__pa(ptr), __pa(ptr) + size);
-+ __dma_clear_buffer(page, size);
-
- return page;
- }
-@@ -170,6 +164,9 @@ static int __init consistent_init(void)
- unsigned long base = consistent_base;
- unsigned long num_ptes = (CONSISTENT_END - base) >> PMD_SHIFT;
-
-+ if (cpu_architecture() >= CPU_ARCH_ARMv6)
-+ return 0;
-+
- consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL);
- if (!consistent_pte) {
- pr_err("%s: no memory\n", __func__);
-@@ -210,9 +207,101 @@ static int __init consistent_init(void)
-
- return ret;
- }
--
- core_initcall(consistent_init);
-
-+static void *__alloc_from_contiguous(struct device *dev, size_t size,
-+ pgprot_t prot, struct page **ret_page);
-+
-+static struct arm_vmregion_head coherent_head = {
-+ .vm_lock = __SPIN_LOCK_UNLOCKED(&coherent_head.vm_lock),
-+ .vm_list = LIST_HEAD_INIT(coherent_head.vm_list),
-+};
-+
-+size_t coherent_pool_size = DEFAULT_CONSISTENT_DMA_SIZE / 8;
-+
-+static int __init early_coherent_pool(char *p)
-+{
-+ coherent_pool_size = memparse(p, &p);
-+ return 0;
-+}
-+early_param("coherent_pool", early_coherent_pool);
-+
-+/*
-+ * Initialise the coherent pool for atomic allocations.
-+ */
-+static int __init coherent_init(void)
-+{
-+ pgprot_t prot = pgprot_dmacoherent(pgprot_kernel);
-+ size_t size = coherent_pool_size;
-+ struct page *page;
-+ void *ptr;
-+
-+ if (cpu_architecture() < CPU_ARCH_ARMv6)
-+ return 0;
-+
-+ ptr = __alloc_from_contiguous(NULL, size, prot, &page);
-+ if (ptr) {
-+ coherent_head.vm_start = (unsigned long) ptr;
-+ coherent_head.vm_end = (unsigned long) ptr + size;
-+ printk(KERN_INFO "DMA: preallocated %u KiB pool for atomic coherent allocations\n",
-+ (unsigned)size / 1024);
-+ return 0;
-+ }
-+ printk(KERN_ERR "DMA: failed to allocate %u KiB pool for atomic coherent allocation\n",
-+ (unsigned)size / 1024);
-+ return -ENOMEM;
-+}
-+/*
-+ * CMA is activated by core_initcall, so we must be called after it.
-+ */
-+postcore_initcall(coherent_init);
-+
-+struct dma_contig_early_reserve {
-+ phys_addr_t base;
-+ unsigned long size;
-+};
-+
-+static struct dma_contig_early_reserve dma_mmu_remap[MAX_CMA_AREAS] __initdata;
-+
-+static int dma_mmu_remap_num __initdata;
-+
-+void __init dma_contiguous_early_fixup(phys_addr_t base, unsigned long size)
-+{
-+ dma_mmu_remap[dma_mmu_remap_num].base = base;
-+ dma_mmu_remap[dma_mmu_remap_num].size = size;
-+ dma_mmu_remap_num++;
-+}
-+
-+void __init dma_contiguous_remap(void)
-+{
-+ int i;
-+ for (i = 0; i < dma_mmu_remap_num; i++) {
-+ phys_addr_t start = dma_mmu_remap[i].base;
-+ phys_addr_t end = start + dma_mmu_remap[i].size;
-+ struct map_desc map;
-+ unsigned long addr;
-+
-+ if (end > arm_lowmem_limit)
-+ end = arm_lowmem_limit;
-+ if (start >= end)
-+ return;
-+
-+ map.pfn = __phys_to_pfn(start);
-+ map.virtual = __phys_to_virt(start);
-+ map.length = end - start;
-+ map.type = MT_MEMORY_DMA_READY;
-+
-+ /*
-+ * Clear previous low-memory mapping
-+ */
-+ for (addr = __phys_to_virt(start); addr < __phys_to_virt(end);
-+ addr += PGDIR_SIZE)
-+ pmd_clear(pmd_off_k(addr));
-+
-+ iotable_init(&map, 1);
-+ }
-+}
-+
- static void *
- __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot,
- const void *caller)
-@@ -319,20 +408,173 @@ static void __dma_free_remap(void *cpu_a
- arm_vmregion_free(&consistent_head, c);
- }
-
-+static int __dma_update_pte(pte_t *pte, pgtable_t token, unsigned long addr,
-+ void *data)
-+{
-+ struct page *page = virt_to_page(addr);
-+ pgprot_t prot = *(pgprot_t *)data;
-+
-+ set_pte_ext(pte, mk_pte(page, prot), 0);
-+ return 0;
-+}
-+
-+static void __dma_remap(struct page *page, size_t size, pgprot_t prot)
-+{
-+ unsigned long start = (unsigned long) page_address(page);
-+ unsigned end = start + size;
-+
-+ apply_to_page_range(&init_mm, start, size, __dma_update_pte, &prot);
-+ dsb();
-+ flush_tlb_kernel_range(start, end);
-+}
-+
-+static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp,
-+ pgprot_t prot, struct page **ret_page,
-+ const void *caller)
-+{
-+ struct page *page;
-+ void *ptr;
-+ page = __dma_alloc_buffer(dev, size, gfp);
-+ if (!page)
-+ return NULL;
-+
-+ ptr = __dma_alloc_remap(page, size, gfp, prot, caller);
-+ if (!ptr) {
-+ __dma_free_buffer(page, size);
-+ return NULL;
-+ }
-+
-+ *ret_page = page;
-+ return ptr;
-+}
-+
-+static void *__alloc_from_pool(struct device *dev, size_t size,
-+ struct page **ret_page, const void *caller)
-+{
-+ struct arm_vmregion *c;
-+ size_t align;
-+
-+ if (!coherent_head.vm_start) {
-+ printk(KERN_ERR "%s: coherent pool not initialised!\n",
-+ __func__);
-+ dump_stack();
-+ return NULL;
-+ }
-+
-+ /*
-+ * Align the region allocation - allocations from pool are rather
-+ * small, so align them to their order in pages, minimum is a page
-+ * size. This helps reduce fragmentation of the DMA space.
-+ */
-+ align = PAGE_SIZE << get_order(size);
-+ c = arm_vmregion_alloc(&coherent_head, align, size, 0, caller);
-+ if (c) {
-+ void *ptr = (void *)c->vm_start;
-+ struct page *page = virt_to_page(ptr);
-+ *ret_page = page;
-+ return ptr;
-+ }
-+ return NULL;
-+}
-+
-+static int __free_from_pool(void *cpu_addr, size_t size)
-+{
-+ unsigned long start = (unsigned long)cpu_addr;
-+ unsigned long end = start + size;
-+ struct arm_vmregion *c;
-+
-+ if (start < coherent_head.vm_start || end > coherent_head.vm_end)
-+ return 0;
-+
-+ c = arm_vmregion_find_remove(&coherent_head, (unsigned long)start);
-+
-+ if ((c->vm_end - c->vm_start) != size) {
-+ printk(KERN_ERR "%s: freeing wrong coherent size (%ld != %d)\n",
-+ __func__, c->vm_end - c->vm_start, size);
-+ dump_stack();
-+ size = c->vm_end - c->vm_start;
-+ }
-+
-+ arm_vmregion_free(&coherent_head, c);
-+ return 1;
-+}
-+
-+static void *__alloc_from_contiguous(struct device *dev, size_t size,
-+ pgprot_t prot, struct page **ret_page)
-+{
-+ unsigned long order = get_order(size);
-+ size_t count = size >> PAGE_SHIFT;
-+ struct page *page;
-+
-+ page = dma_alloc_from_contiguous(dev, count, order);
-+ if (!page)
-+ return NULL;
-+
-+ __dma_clear_buffer(page, size);
-+ __dma_remap(page, size, prot);
-+
-+ *ret_page = page;
-+ return page_address(page);
-+}
-+
-+static void __free_from_contiguous(struct device *dev, struct page *page,
-+ size_t size)
-+{
-+ __dma_remap(page, size, pgprot_kernel);
-+ dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
-+}
-+
-+#define nommu() 0
-+
- #else /* !CONFIG_MMU */
-
--#define __dma_alloc_remap(page, size, gfp, prot, c) page_address(page)
--#define __dma_free_remap(addr, size) do { } while (0)
-+#define nommu() 1
-+
-+#define __alloc_remap_buffer(dev, size, gfp, prot, ret, c) NULL
-+#define __alloc_from_pool(dev, size, ret_page, c) NULL
-+#define __alloc_from_contiguous(dev, size, prot, ret) NULL
-+#define __free_from_pool(cpu_addr, size) 0
-+#define __free_from_contiguous(dev, page, size) do { } while (0)
-+#define __dma_free_remap(cpu_addr, size) do { } while (0)
-
- #endif /* CONFIG_MMU */
-
--static void *
--__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
-- pgprot_t prot, const void *caller)
-+static void *__alloc_simple_buffer(struct device *dev, size_t size, gfp_t gfp,
-+ struct page **ret_page)
-+{
-+ struct page *page;
-+ page = __dma_alloc_buffer(dev, size, gfp);
-+ if (!page)
-+ return NULL;
-+
-+ *ret_page = page;
-+ return page_address(page);
-+}
-+
-+
-+
-+static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
-+ gfp_t gfp, pgprot_t prot, const void *caller)
- {
-+ u64 mask = get_coherent_dma_mask(dev);
- struct page *page;
- void *addr;
-
-+#ifdef CONFIG_DMA_API_DEBUG
-+ u64 limit = (mask + 1) & ~mask;
-+ if (limit && size >= limit) {
-+ dev_warn(dev, "coherent allocation too big (requested %#x mask %#llx)\n",
-+ size, mask);
-+ return NULL;
-+ }
-+#endif
-+
-+ if (!mask)
-+ return NULL;
-+
-+ if (mask < 0xffffffffULL)
-+ gfp |= GFP_DMA;
-+
- /*
- * Following is a work-around (a.k.a. hack) to prevent pages
- * with __GFP_COMP being passed to split_page() which cannot
-@@ -345,19 +587,17 @@ __dma_alloc(struct device *dev, size_t s
- *handle = ~0;
- size = PAGE_ALIGN(size);
-
-- page = __dma_alloc_buffer(dev, size, gfp);
-- if (!page)
-- return NULL;
--
-- if (!arch_is_coherent())
-- addr = __dma_alloc_remap(page, size, gfp, prot, caller);
-+ if (arch_is_coherent() || nommu())
-+ addr = __alloc_simple_buffer(dev, size, gfp, &page);
-+ else if (cpu_architecture() < CPU_ARCH_ARMv6)
-+ addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
-+ else if (gfp & GFP_ATOMIC)
-+ addr = __alloc_from_pool(dev, size, &page, caller);
- else
-- addr = page_address(page);
-+ addr = __alloc_from_contiguous(dev, size, prot, &page);
-
- if (addr)
- *handle = pfn_to_dma(dev, page_to_pfn(page));
-- else
-- __dma_free_buffer(page, size);
-
- return addr;
- }
-@@ -366,8 +606,8 @@ __dma_alloc(struct device *dev, size_t s
- * Allocate DMA-coherent memory space and return both the kernel remapped
- * virtual and bus address for that space.
- */
--void *
--dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
-+void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle,
-+ gfp_t gfp)
- {
- void *memory;
-
-@@ -398,25 +638,11 @@ static int dma_mmap(struct device *dev,
- {
- int ret = -ENXIO;
- #ifdef CONFIG_MMU
-- unsigned long user_size, kern_size;
-- struct arm_vmregion *c;
--
-- user_size = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
--
-- c = arm_vmregion_find(&consistent_head, (unsigned long)cpu_addr);
-- if (c) {
-- unsigned long off = vma->vm_pgoff;
--
-- kern_size = (c->vm_end - c->vm_start) >> PAGE_SHIFT;
--
-- if (off < kern_size &&
-- user_size <= (kern_size - off)) {
-- ret = remap_pfn_range(vma, vma->vm_start,
-- page_to_pfn(c->vm_pages) + off,
-- user_size << PAGE_SHIFT,
-- vma->vm_page_prot);
-- }
-- }
-+ unsigned long pfn = dma_to_pfn(dev, dma_addr);
-+ ret = remap_pfn_range(vma, vma->vm_start,
-+ pfn + vma->vm_pgoff,
-+ vma->vm_end - vma->vm_start,
-+ vma->vm_page_prot);
- #endif /* CONFIG_MMU */
-
- return ret;
-@@ -438,23 +664,33 @@ int dma_mmap_writecombine(struct device
- }
- EXPORT_SYMBOL(dma_mmap_writecombine);
-
-+
- /*
-- * free a page as defined by the above mapping.
-- * Must not be called with IRQs disabled.
-+ * Free a buffer as defined by the above mapping.
- */
- void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle)
- {
-- WARN_ON(irqs_disabled());
-+ struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
-
- if (dma_release_from_coherent(dev, get_order(size), cpu_addr))
- return;
-
- size = PAGE_ALIGN(size);
-
-- if (!arch_is_coherent())
-+ if (arch_is_coherent() || nommu()) {
-+ __dma_free_buffer(page, size);
-+ } else if (cpu_architecture() < CPU_ARCH_ARMv6) {
- __dma_free_remap(cpu_addr, size);
--
-- __dma_free_buffer(pfn_to_page(dma_to_pfn(dev, handle)), size);
-+ __dma_free_buffer(page, size);
-+ } else {
-+ if (__free_from_pool(cpu_addr, size))
-+ return;
-+ /*
-+ * Non-atomic allocations cannot be freed with IRQs disabled
-+ */
-+ WARN_ON(irqs_disabled());
-+ __free_from_contiguous(dev, page, size);
-+ }
- }
- EXPORT_SYMBOL(dma_free_coherent);
-
---- a/arch/arm/mm/init.c
-+++ b/arch/arm/mm/init.c
-@@ -20,6 +20,7 @@
- #include <linux/highmem.h>
- #include <linux/gfp.h>
- #include <linux/memblock.h>
-+#include <linux/dma-contiguous.h>
-
- #include <asm/mach-types.h>
- #include <asm/memblock.h>
-@@ -226,6 +227,17 @@ static void __init arm_adjust_dma_zone(u
- }
- #endif
-
-+void __init setup_dma_zone(struct machine_desc *mdesc)
-+{
-+#ifdef CONFIG_ZONE_DMA
-+ if (mdesc->dma_zone_size) {
-+ arm_dma_zone_size = mdesc->dma_zone_size;
-+ arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1;
-+ } else
-+ arm_dma_limit = 0xffffffff;
-+#endif
-+}
-+
- static void __init arm_bootmem_free(unsigned long min, unsigned long max_low,
- unsigned long max_high)
- {
-@@ -273,12 +285,9 @@ static void __init arm_bootmem_free(unsi
- * Adjust the sizes according to any special requirements for
- * this machine type.
- */
-- if (arm_dma_zone_size) {
-+ if (arm_dma_zone_size)
- arm_adjust_dma_zone(zone_size, zhole_size,
- arm_dma_zone_size >> PAGE_SHIFT);
-- arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1;
-- } else
-- arm_dma_limit = 0xffffffff;
- #endif
-
- free_area_init_node(0, zone_size, min, zhole_size);
-@@ -364,6 +373,12 @@ void __init arm_memblock_init(struct mem
- if (mdesc->reserve)
- mdesc->reserve();
-
-+ /*
-+ * reserve memory for DMA contigouos allocations,
-+ * must come from DMA area inside low memory
-+ */
-+ dma_contiguous_reserve(min(arm_dma_limit, arm_lowmem_limit));
-+
- arm_memblock_steal_permitted = false;
- memblock_allow_resize();
- memblock_dump_all();
---- a/arch/arm/mm/mm.h
-+++ b/arch/arm/mm/mm.h
-@@ -70,5 +70,8 @@ extern u32 arm_dma_limit;
- #define arm_dma_limit ((u32)~0)
- #endif
-
-+extern phys_addr_t arm_lowmem_limit;
-+
- void __init bootmem_init(void);
- void arm_mm_memblock_reserve(void);
-+void dma_contiguous_remap(void);
---- a/arch/arm/mm/mmu.c
-+++ b/arch/arm/mm/mmu.c
-@@ -288,6 +288,11 @@ static struct mem_type mem_types[] = {
- PMD_SECT_UNCACHED | PMD_SECT_XN,
- .domain = DOMAIN_KERNEL,
- },
-+ [MT_MEMORY_DMA_READY] = {
-+ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
-+ .prot_l1 = PMD_TYPE_TABLE,
-+ .domain = DOMAIN_KERNEL,
-+ },
- };
-
- const struct mem_type *get_mem_type(unsigned int type)
-@@ -429,6 +434,7 @@ static void __init build_mem_type_table(
- if (arch_is_coherent() && cpu_is_xsc3()) {
- mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
- mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
-+ mem_types[MT_MEMORY_DMA_READY].prot_pte |= L_PTE_SHARED;
- mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
- mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED;
- }
-@@ -460,6 +466,7 @@ static void __init build_mem_type_table(
- mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED;
- mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
- mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
-+ mem_types[MT_MEMORY_DMA_READY].prot_pte |= L_PTE_SHARED;
- mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
- mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED;
- }
-@@ -512,6 +519,7 @@ static void __init build_mem_type_table(
- mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
- mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd;
- mem_types[MT_MEMORY].prot_pte |= kern_pgprot;
-+ mem_types[MT_MEMORY_DMA_READY].prot_pte |= kern_pgprot;
- mem_types[MT_MEMORY_NONCACHED].prot_sect |= ecc_mask;
- mem_types[MT_ROM].prot_sect |= cp->pmd;
-
-@@ -596,7 +604,7 @@ static void __init alloc_init_section(pu
- * L1 entries, whereas PGDs refer to a group of L1 entries making
- * up one logical pointer to an L2 table.
- */
-- if (((addr | end | phys) & ~SECTION_MASK) == 0) {
-+ if (type->prot_sect && ((addr | end | phys) & ~SECTION_MASK) == 0) {
- pmd_t *p = pmd;
-
- #ifndef CONFIG_ARM_LPAE
-@@ -887,7 +895,7 @@ static int __init early_vmalloc(char *ar
- }
- early_param("vmalloc", early_vmalloc);
-
--static phys_addr_t lowmem_limit __initdata = 0;
-+phys_addr_t arm_lowmem_limit __initdata = 0;
-
- void __init sanity_check_meminfo(void)
- {
-@@ -970,8 +978,8 @@ void __init sanity_check_meminfo(void)
- bank->size = newsize;
- }
- #endif
-- if (!bank->highmem && bank->start + bank->size > lowmem_limit)
-- lowmem_limit = bank->start + bank->size;
-+ if (!bank->highmem && bank->start + bank->size > arm_lowmem_limit)
-+ arm_lowmem_limit = bank->start + bank->size;
-
- j++;
- }
-@@ -996,8 +1004,8 @@ void __init sanity_check_meminfo(void)
- }
- #endif
- meminfo.nr_banks = j;
-- high_memory = __va(lowmem_limit - 1) + 1;
-- memblock_set_current_limit(lowmem_limit);
-+ high_memory = __va(arm_lowmem_limit - 1) + 1;
-+ memblock_set_current_limit(arm_lowmem_limit);
- }
-
- static inline void prepare_page_table(void)
-@@ -1022,8 +1030,8 @@ static inline void prepare_page_table(vo
- * Find the end of the first block of lowmem.
- */
- end = memblock.memory.regions[0].base + memblock.memory.regions[0].size;
-- if (end >= lowmem_limit)
-- end = lowmem_limit;
-+ if (end >= arm_lowmem_limit)
-+ end = arm_lowmem_limit;
-
- /*
- * Clear out all the kernel space mappings, except for the first
-@@ -1167,8 +1175,8 @@ static void __init map_lowmem(void)
- phys_addr_t end = start + reg->size;
- struct map_desc map;
-
-- if (end > lowmem_limit)
-- end = lowmem_limit;
-+ if (end > arm_lowmem_limit)
-+ end = arm_lowmem_limit;
- if (start >= end)
- break;
-
-@@ -1189,11 +1197,12 @@ void __init paging_init(struct machine_d
- {
- void *zero_page;
-
-- memblock_set_current_limit(lowmem_limit);
-+ memblock_set_current_limit(arm_lowmem_limit);
-
- build_mem_type_table();
- prepare_page_table();
- map_lowmem();
-+ dma_contiguous_remap();
- devicemaps_init(mdesc);
- kmap_init();
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:54:08 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:13 +0900
-Subject: [PATCH v2 56/58] arm: mm: fix DMA pool affiliation check
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-57-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
-
-The __free_from_pool() function was changed in
-e9da6e9905e639b0f842a244bc770b48ad0523e9. Unfortunately, the test that
-checks whether the provided (start,size) is within the DMA pool has
-been improperly modified. It used to be:
-
- if (start < coherent_head.vm_start || end > coherent_head.vm_end)
-
-Where coherent_head.vm_end was non-inclusive (i.e, it did not include
-the first byte after the pool). The test has been changed to:
-
- if (start < pool->vaddr || start > pool->vaddr + pool->size)
-
-So now pool->vaddr + pool->size is inclusive (i.e, it includes the
-first byte after the pool), so the test should be >= instead of >.
-
-This bug causes the following message when freeing the *first* DMA
-coherent buffer that has been allocated, because its virtual address
-is exactly equal to pool->vaddr + pool->size :
-
-WARNING: at /home/thomas/projets/linux-2.6/arch/arm/mm/dma-mapping.c:463 __free_from_pool+0xa4/0xc0()
-freeing wrong coherent size from pool
-
-Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Cc: Russell King <linux@arm.linux.org.uk>
-Cc: Lior Amsalem <alior@marvell.com>
-Cc: Maen Suleiman <maen@marvell.com>
-Cc: Tawfik Bayouk <tawfik@marvell.com>
-Cc: Shadi Ammouri <shadi@marvell.com>
-Cc: Eran Ben-Avi <benavi@marvell.com>
-Cc: Yehuda Yitschak <yehuday@marvell.com>
-Cc: Nadav Haklai <nadavh@marvell.com>
-[m.szyprowski: rebased onto v3.6-rc5 and resolved conflict]
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit f3d87524975f01b885fc3d009c6ab6afd0d00746)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/mm/dma-mapping.c | 2 +-
- 1 files changed, 1 insertions(+), 1 deletions(-)
-
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index 94b7b78..dc16881 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -477,7 +477,7 @@ static bool __in_atomic_pool(void *start, size_t size)
- void *pool_start = pool->vaddr;
- void *pool_end = pool->vaddr + pool->size;
-
-- if (start < pool_start || start > pool_end)
-+ if (start < pool_start || start >= pool_end)
- return false;
-
- if (end <= pool_end)
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:23 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:55 +0900
-Subject: [PATCH v2 38/58] ARM: mm: fix MMU mapping of CMA regions
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-39-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Chris Brand <cbrand@broadcom.com>
-
-Fix dma_contiguous_remap() so that it continues through all the
-regions, even after encountering one that is outside lowmem.
-Without this change, if you have two CMA regions, the first outside
-lowmem and the seocnd inside lowmem, only the second one will get
-set up in the MMU. Data written to that region then doesn't get
-automatically flushed from the cache into memory.
-
-Signed-off-by: Chris Brand <cbrand@broadcom.com>
-[extended patch subject with 'fix' word]
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit 39f78e70567a07a6fc0d7a4ca9e3331e44dd400d)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/mm/dma-mapping.c | 2 +-
- 1 files changed, 1 insertions(+), 1 deletions(-)
-
-diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
-index 6f85d3d..cce3c0d 100644
---- a/arch/arm/mm/dma-mapping.c
-+++ b/arch/arm/mm/dma-mapping.c
-@@ -388,7 +388,7 @@ void __init dma_contiguous_remap(void)
- if (end > arm_lowmem_limit)
- end = arm_lowmem_limit;
- if (start >= end)
-- return;
-+ continue;
-
- map.pfn = __phys_to_pfn(start);
- map.virtual = __phys_to_virt(start);
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:07 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:49 +0900
-Subject: [PATCH v2 32/58] ARM: mm: fix type of the arm_dma_limit global variable
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-33-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-arm_dma_limit stores physical address of maximal address accessible by DMA,
-so the phys_addr_t type makes much more sense for it instead of u32. This
-patch fixes the following build warning:
-
-arch/arm/mm/init.c:380: warning: comparison of distinct pointer types lacks a cast
-
-Reported-by: Russell King <linux@arm.linux.org.uk>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit 4986e5c7cd91817d0f58dd15073c9080d47980cf)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/mm/init.c | 2 +-
- arch/arm/mm/mm.h | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
---- a/arch/arm/mm/init.c
-+++ b/arch/arm/mm/init.c
-@@ -212,7 +212,7 @@ EXPORT_SYMBOL(arm_dma_zone_size);
- * allocations. This must be the smallest DMA mask in the system,
- * so a successful GFP_DMA allocation will always satisfy this.
- */
--u32 arm_dma_limit;
-+phys_addr_t arm_dma_limit;
-
- static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole,
- unsigned long dma_size)
---- a/arch/arm/mm/mm.h
-+++ b/arch/arm/mm/mm.h
-@@ -65,7 +65,7 @@ extern void __flush_dcache_page(struct a
- #endif
-
- #ifdef CONFIG_ZONE_DMA
--extern u32 arm_dma_limit;
-+extern phys_addr_t arm_dma_limit;
- #else
- #define arm_dma_limit ((u32)~0)
- #endif
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:25 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:56 +0900
-Subject: [PATCH v2 39/58] ARM: relax conditions required for enabling Contiguous Memory Allocator
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-40-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-Contiguous Memory Allocator requires only paging and MMU enabled not
-particular CPU architectures, so there is no need for strict dependency
-on CPU type. This enables to use CMA on some older ARM v5 systems which
-also might need large contiguous blocks for the multimedia processing hw
-modules.
-
-Reported-by: Prabhakar Lad <prabhakar.lad@ti.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Tested-by: Prabhakar Lad <prabhakar.lad@ti.com>
-(cherry picked from commit e092705bcd53de3bafc3053b0b55bf83e5d6711f)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/arm/Kconfig | 2 +-
- 1 files changed, 1 insertions(+), 1 deletions(-)
-
-diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
-index 5c0c50e..dce63cb 100644
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -5,7 +5,7 @@ config ARM
- select HAVE_DMA_API_DEBUG
- select HAVE_IDE if PCI || ISA || PCMCIA
- select HAVE_DMA_ATTRS
-- select HAVE_DMA_CONTIGUOUS if (CPU_V6 || CPU_V6K || CPU_V7)
-+ select HAVE_DMA_CONTIGUOUS if MMU
- select HAVE_MEMBLOCK
- select RTC_LIB
- select SYS_SUPPORTS_APM_EMULATION
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:25 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:33 +0900
-Subject: [PATCH v2 16/58] cma: fix migration mode
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-17-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Minchan Kim <minchan.kim@gmail.com>
-
-__alloc_contig_migrate_range calls migrate_pages with wrong argument
-for migrate_mode. Fix it.
-
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Signed-off-by: Minchan Kim <minchan@kernel.org>
-Acked-by: Michal Nazarewicz <mina86@mina86.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit 58f42fd54144346898e6dc6d6ae3acd4c591b42f)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- mm/page_alloc.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -5685,7 +5685,7 @@ static int __alloc_contig_migrate_range(
-
- ret = migrate_pages(&cc.migratepages,
- __alloc_contig_migrate_alloc,
-- 0, false, true);
-+ 0, false, MIGRATE_SYNC);
- }
-
- putback_lru_pages(&cc.migratepages);
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:31 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:35 +0900
-Subject: [PATCH v2 18/58] common: add dma_mmap_from_coherent() function
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-19-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-Add a common helper for dma-mapping core for mapping a coherent buffer
-to userspace.
-
-Reported-by: Subash Patel <subashrp@gmail.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
-Tested-By: Subash Patel <subash.ramaswamy@linaro.org>
-(cherry picked from commit bca0fa5f12a6744a2b2e53154af65a51402b3426)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- drivers/base/dma-coherent.c | 42 ++++++++++++++++++++++++++++++++++++
- include/asm-generic/dma-coherent.h | 4 ++-
- 2 files changed, 45 insertions(+), 1 deletions(-)
-
-diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c
-index bb0025c..1b85949 100644
---- a/drivers/base/dma-coherent.c
-+++ b/drivers/base/dma-coherent.c
-@@ -10,6 +10,7 @@
- struct dma_coherent_mem {
- void *virt_base;
- dma_addr_t device_base;
-+ phys_addr_t pfn_base;
- int size;
- int flags;
- unsigned long *bitmap;
-@@ -44,6 +45,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
-
- dev->dma_mem->virt_base = mem_base;
- dev->dma_mem->device_base = device_addr;
-+ dev->dma_mem->pfn_base = PFN_DOWN(bus_addr);
- dev->dma_mem->size = pages;
- dev->dma_mem->flags = flags;
-
-@@ -176,3 +178,43 @@ int dma_release_from_coherent(struct device *dev, int order, void *vaddr)
- return 0;
- }
- EXPORT_SYMBOL(dma_release_from_coherent);
-+
-+/**
-+ * dma_mmap_from_coherent() - try to mmap the memory allocated from
-+ * per-device coherent memory pool to userspace
-+ * @dev: device from which the memory was allocated
-+ * @vma: vm_area for the userspace memory
-+ * @vaddr: cpu address returned by dma_alloc_from_coherent
-+ * @size: size of the memory buffer allocated by dma_alloc_from_coherent
-+ *
-+ * This checks whether the memory was allocated from the per-device
-+ * coherent memory pool and if so, maps that memory to the provided vma.
-+ *
-+ * Returns 1 if we correctly mapped the memory, or 0 if
-+ * dma_release_coherent() should proceed with mapping memory from
-+ * generic pools.
-+ */
-+int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
-+ void *vaddr, size_t size, int *ret)
-+{
-+ struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
-+
-+ if (mem && vaddr >= mem->virt_base && vaddr + size <=
-+ (mem->virt_base + (mem->size << PAGE_SHIFT))) {
-+ unsigned long off = vma->vm_pgoff;
-+ int start = (vaddr - mem->virt_base) >> PAGE_SHIFT;
-+ int user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-+ int count = size >> PAGE_SHIFT;
-+
-+ *ret = -ENXIO;
-+ if (off < count && user_count <= count - off) {
-+ unsigned pfn = mem->pfn_base + start + off;
-+ *ret = remap_pfn_range(vma, vma->vm_start, pfn,
-+ user_count << PAGE_SHIFT,
-+ vma->vm_page_prot);
-+ }
-+ return 1;
-+ }
-+ return 0;
-+}
-+EXPORT_SYMBOL(dma_mmap_from_coherent);
-diff --git a/include/asm-generic/dma-coherent.h b/include/asm-generic/dma-coherent.h
-index 85a3ffa..abfb268 100644
---- a/include/asm-generic/dma-coherent.h
-+++ b/include/asm-generic/dma-coherent.h
-@@ -3,13 +3,15 @@
-
- #ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT
- /*
-- * These two functions are only for dma allocator.
-+ * These three functions are only for dma allocator.
- * Don't use them in device drivers.
- */
- int dma_alloc_from_coherent(struct device *dev, ssize_t size,
- dma_addr_t *dma_handle, void **ret);
- int dma_release_from_coherent(struct device *dev, int order, void *vaddr);
-
-+int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
-+ void *cpu_addr, size_t size, int *ret);
- /*
- * Standard interface
- */
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:38 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:01 +0900
-Subject: [PATCH v2 44/58] common: dma-mapping: add support for generic dma_mmap_* calls
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-45-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-Commit 9adc5374 ('common: dma-mapping: introduce mmap method') added a
-generic method for implementing mmap user call to dma_map_ops structure.
-
-This patch converts ARM and PowerPC architectures (the only providers of
-dma_mmap_coherent/dma_mmap_writecombine calls) to use this generic
-dma_map_ops based call and adds a generic cross architecture
-definition for dma_mmap_attrs, dma_mmap_coherent, dma_mmap_writecombine
-functions.
-
-The generic mmap virt_to_page-based fallback implementation is provided for
-architectures which don't provide their own implementation for mmap method.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com>
-(cherry picked from commit 64ccc9c033c6089b2d426dad3c56477ab066c999)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- arch/arm/include/asm/dma-mapping.h | 19 ---------------
- arch/powerpc/include/asm/dma-mapping.h | 8 +++---
- arch/powerpc/kernel/dma-iommu.c | 1 +
- arch/powerpc/kernel/dma-swiotlb.c | 1 +
- arch/powerpc/kernel/dma.c | 36 +++++++++++++++-------------
- arch/powerpc/kernel/vio.c | 1 +
- drivers/base/dma-mapping.c | 31 +++++++++++++++++++++++++
- include/asm-generic/dma-coherent.h | 1 +
- include/asm-generic/dma-mapping-common.h | 37 ++++++++++++++++++++++++++++++
- 9 files changed, 95 insertions(+), 40 deletions(-)
-
-diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
-index 80777d87..a048033 100644
---- a/arch/arm/include/asm/dma-mapping.h
-+++ b/arch/arm/include/asm/dma-mapping.h
-@@ -186,17 +186,6 @@ extern int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
- void *cpu_addr, dma_addr_t dma_addr, size_t size,
- struct dma_attrs *attrs);
-
--#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, NULL)
--
--static inline int dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
-- void *cpu_addr, dma_addr_t dma_addr,
-- size_t size, struct dma_attrs *attrs)
--{
-- struct dma_map_ops *ops = get_dma_ops(dev);
-- BUG_ON(!ops);
-- return ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
--}
--
- static inline void *dma_alloc_writecombine(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
- {
-@@ -213,14 +202,6 @@ static inline void dma_free_writecombine(struct device *dev, size_t size,
- return dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
- }
-
--static inline int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma,
-- void *cpu_addr, dma_addr_t dma_addr, size_t size)
--{
-- DEFINE_DMA_ATTRS(attrs);
-- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
-- return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs);
--}
--
- /*
- * This can be called during boot to increase the size of the consistent
- * DMA region above it's default value of 2MB. It must be called before the
-diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
-index 62678e3..7816087 100644
---- a/arch/powerpc/include/asm/dma-mapping.h
-+++ b/arch/powerpc/include/asm/dma-mapping.h
-@@ -27,7 +27,10 @@ extern void *dma_direct_alloc_coherent(struct device *dev, size_t size,
- extern void dma_direct_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs);
--
-+extern int dma_direct_mmap_coherent(struct device *dev,
-+ struct vm_area_struct *vma,
-+ void *cpu_addr, dma_addr_t handle,
-+ size_t size, struct dma_attrs *attrs);
-
- #ifdef CONFIG_NOT_COHERENT_CACHE
- /*
-@@ -207,11 +210,8 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
- #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
- #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-
--extern int dma_mmap_coherent(struct device *, struct vm_area_struct *,
-- void *, dma_addr_t, size_t);
- #define ARCH_HAS_DMA_MMAP_COHERENT
-
--
- static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
- enum dma_data_direction direction)
- {
-diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
-index bcfdcd2..2d7bb8c 100644
---- a/arch/powerpc/kernel/dma-iommu.c
-+++ b/arch/powerpc/kernel/dma-iommu.c
-@@ -109,6 +109,7 @@ static u64 dma_iommu_get_required_mask(struct device *dev)
- struct dma_map_ops dma_iommu_ops = {
- .alloc = dma_iommu_alloc_coherent,
- .free = dma_iommu_free_coherent,
-+ .mmap = dma_direct_mmap_coherent,
- .map_sg = dma_iommu_map_sg,
- .unmap_sg = dma_iommu_unmap_sg,
- .dma_supported = dma_iommu_dma_supported,
-diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c
-index 4ab88da..4694365 100644
---- a/arch/powerpc/kernel/dma-swiotlb.c
-+++ b/arch/powerpc/kernel/dma-swiotlb.c
-@@ -49,6 +49,7 @@ static u64 swiotlb_powerpc_get_required(struct device *dev)
- struct dma_map_ops swiotlb_dma_ops = {
- .alloc = dma_direct_alloc_coherent,
- .free = dma_direct_free_coherent,
-+ .mmap = dma_direct_mmap_coherent,
- .map_sg = swiotlb_map_sg_attrs,
- .unmap_sg = swiotlb_unmap_sg_attrs,
- .dma_supported = swiotlb_dma_supported,
-diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
-index b1ec983..062bf20 100644
---- a/arch/powerpc/kernel/dma.c
-+++ b/arch/powerpc/kernel/dma.c
-@@ -65,6 +65,24 @@ void dma_direct_free_coherent(struct device *dev, size_t size,
- #endif
- }
-
-+int dma_direct_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
-+ void *cpu_addr, dma_addr_t handle, size_t size,
-+ struct dma_attrs *attrs)
-+{
-+ unsigned long pfn;
-+
-+#ifdef CONFIG_NOT_COHERENT_CACHE
-+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-+ pfn = __dma_get_coherent_pfn((unsigned long)cpu_addr);
-+#else
-+ pfn = page_to_pfn(virt_to_page(cpu_addr));
-+#endif
-+ return remap_pfn_range(vma, vma->vm_start,
-+ pfn + vma->vm_pgoff,
-+ vma->vm_end - vma->vm_start,
-+ vma->vm_page_prot);
-+}
-+
- static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
- int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
-@@ -154,6 +172,7 @@ static inline void dma_direct_sync_single(struct device *dev,
- struct dma_map_ops dma_direct_ops = {
- .alloc = dma_direct_alloc_coherent,
- .free = dma_direct_free_coherent,
-+ .mmap = dma_direct_mmap_coherent,
- .map_sg = dma_direct_map_sg,
- .unmap_sg = dma_direct_unmap_sg,
- .dma_supported = dma_direct_dma_supported,
-@@ -211,20 +230,3 @@ static int __init dma_init(void)
- }
- fs_initcall(dma_init);
-
--int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
-- void *cpu_addr, dma_addr_t handle, size_t size)
--{
-- unsigned long pfn;
--
--#ifdef CONFIG_NOT_COHERENT_CACHE
-- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-- pfn = __dma_get_coherent_pfn((unsigned long)cpu_addr);
--#else
-- pfn = page_to_pfn(virt_to_page(cpu_addr));
--#endif
-- return remap_pfn_range(vma, vma->vm_start,
-- pfn + vma->vm_pgoff,
-- vma->vm_end - vma->vm_start,
-- vma->vm_page_prot);
--}
--EXPORT_SYMBOL_GPL(dma_mmap_coherent);
-diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
-index ea6081a..544a03a 100644
---- a/arch/powerpc/kernel/vio.c
-+++ b/arch/powerpc/kernel/vio.c
-@@ -611,6 +611,7 @@ static u64 vio_dma_get_required_mask(struct device *dev)
- struct dma_map_ops vio_dma_mapping_ops = {
- .alloc = vio_dma_iommu_alloc_coherent,
- .free = vio_dma_iommu_free_coherent,
-+ .mmap = dma_direct_mmap_coherent,
- .map_sg = vio_dma_iommu_map_sg,
- .unmap_sg = vio_dma_iommu_unmap_sg,
- .map_page = vio_dma_iommu_map_page,
-diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
-index 6f3676f..db5db02 100644
---- a/drivers/base/dma-mapping.c
-+++ b/drivers/base/dma-mapping.c
-@@ -10,6 +10,7 @@
- #include <linux/dma-mapping.h>
- #include <linux/export.h>
- #include <linux/gfp.h>
-+#include <asm-generic/dma-coherent.h>
-
- /*
- * Managed DMA API
-@@ -218,3 +219,33 @@ void dmam_release_declared_memory(struct device *dev)
- EXPORT_SYMBOL(dmam_release_declared_memory);
-
- #endif
-+
-+/*
-+ * Create userspace mapping for the DMA-coherent memory.
-+ */
-+int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
-+ void *cpu_addr, dma_addr_t dma_addr, size_t size)
-+{
-+ int ret = -ENXIO;
-+#ifdef CONFIG_MMU
-+ unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-+ unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-+ unsigned long pfn = page_to_pfn(virt_to_page(cpu_addr));
-+ unsigned long off = vma->vm_pgoff;
-+
-+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-+
-+ if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
-+ return ret;
-+
-+ if (off < count && user_count <= (count - off)) {
-+ ret = remap_pfn_range(vma, vma->vm_start,
-+ pfn + off,
-+ user_count << PAGE_SHIFT,
-+ vma->vm_page_prot);
-+ }
-+#endif /* CONFIG_MMU */
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL(dma_common_mmap);
-diff --git a/include/asm-generic/dma-coherent.h b/include/asm-generic/dma-coherent.h
-index abfb268..2be8a2d 100644
---- a/include/asm-generic/dma-coherent.h
-+++ b/include/asm-generic/dma-coherent.h
-@@ -29,6 +29,7 @@ dma_mark_declared_memory_occupied(struct device *dev,
- #else
- #define dma_alloc_from_coherent(dev, size, handle, ret) (0)
- #define dma_release_from_coherent(dev, order, vaddr) (0)
-+#define dma_mmap_from_coherent(dev, vma, vaddr, order, ret) (0)
- #endif
-
- #endif
-diff --git a/include/asm-generic/dma-mapping-common.h b/include/asm-generic/dma-mapping-common.h
-index 2e248d8..9073aeb 100644
---- a/include/asm-generic/dma-mapping-common.h
-+++ b/include/asm-generic/dma-mapping-common.h
-@@ -176,4 +176,41 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
- #define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, NULL)
- #define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, NULL)
-
-+extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
-+ void *cpu_addr, dma_addr_t dma_addr, size_t size);
-+
-+/**
-+ * dma_mmap_attrs - map a coherent DMA allocation into user space
-+ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
-+ * @vma: vm_area_struct describing requested user mapping
-+ * @cpu_addr: kernel CPU-view address returned from dma_alloc_attrs
-+ * @handle: device-view address returned from dma_alloc_attrs
-+ * @size: size of memory originally requested in dma_alloc_attrs
-+ * @attrs: attributes of mapping properties requested in dma_alloc_attrs
-+ *
-+ * Map a coherent DMA buffer previously allocated by dma_alloc_attrs
-+ * into user space. The coherent DMA buffer must not be freed by the
-+ * driver until the user space mapping has been released.
-+ */
-+static inline int
-+dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void *cpu_addr,
-+ dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs)
-+{
-+ struct dma_map_ops *ops = get_dma_ops(dev);
-+ BUG_ON(!ops);
-+ if (ops->mmap)
-+ return ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
-+ return dma_common_mmap(dev, vma, cpu_addr, dma_addr, size);
-+}
-+
-+#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, NULL)
-+
-+static inline int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma,
-+ void *cpu_addr, dma_addr_t dma_addr, size_t size)
-+{
-+ DEFINE_DMA_ATTRS(attrs);
-+ dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
-+ return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs);
-+}
-+
- #endif
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:45 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:04 +0900
-Subject: [PATCH v2 47/58] driver core: fix some kernel-doc warnings in dma*.c
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-48-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Randy Dunlap <rdunlap@xenotime.net>
-
-Fix kernel-doc warnings in drivers/base/dma*.c:
-
-Warning(drivers/base/dma-buf.c:498): No description found for parameter 'vaddr'
-Warning(drivers/base/dma-coherent.c:199): No description found for parameter 'ret'
-
-Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-(cherry picked from commit 6e7b4a59b3d7bb2dcd11c019354bf0c91037dadd)
-
-Conflicts:
-
- drivers/base/dma-buf.c
-
-Backported patch only addresses dma-coherent.c warning, as dma-buf.c warning is
-not present in 3.4 kernel.
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- drivers/base/dma-coherent.c | 1 +
- 1 files changed, 1 insertions(+), 0 deletions(-)
-
-diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c
-index 1b85949..560a717 100644
---- a/drivers/base/dma-coherent.c
-+++ b/drivers/base/dma-coherent.c
-@@ -186,6 +186,7 @@ EXPORT_SYMBOL(dma_release_from_coherent);
- * @vma: vm_area for the userspace memory
- * @vaddr: cpu address returned by dma_alloc_from_coherent
- * @size: size of the memory buffer allocated by dma_alloc_from_coherent
-+ * @ret: result from remap_pfn_range()
- *
- * This checks whether the memory was allocated from the per-device
- * coherent memory pool and if so, maps that memory to the provided vma.
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:19 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:30 +0900
-Subject: [PATCH v2 13/58] drivers: add Contiguous Memory Allocator
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-14-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-The Contiguous Memory Allocator is a set of helper functions for DMA
-mapping framework that improves allocations of contiguous memory chunks.
-
-CMA grabs memory on system boot, marks it with MIGRATE_CMA migrate type
-and gives back to the system. Kernel is allowed to allocate only movable
-pages within CMA's managed memory so that it can be used for example for
-page cache when DMA mapping do not use it. On
-dma_alloc_from_contiguous() request such pages are migrated out of CMA
-area to free required contiguous block and fulfill the request. This
-allows to allocate large contiguous chunks of memory at any time
-assuming that there is enough free memory available in the system.
-
-This code is heavily based on earlier works by Michal Nazarewicz.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Tested-by: Rob Clark <rob.clark@linaro.org>
-Tested-by: Ohad Ben-Cohen <ohad@wizery.com>
-Tested-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-Tested-by: Robert Nelson <robertcnelson@gmail.com>
-Tested-by: Barry Song <Baohua.Song@csr.com>
-(cherry picked from commit c64be2bb1c6eb43c838b2c6d57b074078be208dd)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- Documentation/kernel-parameters.txt | 5
- arch/Kconfig | 3
- drivers/base/Kconfig | 89 +++++++
- drivers/base/Makefile | 1
- drivers/base/dma-contiguous.c | 401 +++++++++++++++++++++++++++++++++++
- include/asm-generic/dma-contiguous.h | 28 ++
- include/linux/device.h | 4
- include/linux/dma-contiguous.h | 110 +++++++++
- 8 files changed, 641 insertions(+)
- create mode 100644 drivers/base/dma-contiguous.c
- create mode 100644 include/asm-generic/dma-contiguous.h
- create mode 100644 include/linux/dma-contiguous.h
-
---- a/Documentation/kernel-parameters.txt
-+++ b/Documentation/kernel-parameters.txt
-@@ -508,6 +508,11 @@ bytes respectively. Such letter suffixes
- Also note the kernel might malfunction if you disable
- some critical bits.
-
-+ cma=nn[MG] [ARM,KNL]
-+ Sets the size of kernel global memory area for contiguous
-+ memory allocations. For more information, see
-+ include/linux/dma-contiguous.h
-+
- cmo_free_hint= [PPC] Format: { yes | no }
- Specify whether pages are marked as being inactive
- when they are freed. This is used in CMO environments
---- a/arch/Kconfig
-+++ b/arch/Kconfig
-@@ -145,6 +145,9 @@ config HAVE_ARCH_TRACEHOOK
- config HAVE_DMA_ATTRS
- bool
-
-+config HAVE_DMA_CONTIGUOUS
-+ bool
-+
- config USE_GENERIC_SMP_HELPERS
- bool
-
---- a/drivers/base/Kconfig
-+++ b/drivers/base/Kconfig
-@@ -192,4 +192,93 @@ config DMA_SHARED_BUFFER
- APIs extension; the file's descriptor can then be passed on to other
- driver.
-
-+config CMA
-+ bool "Contiguous Memory Allocator (EXPERIMENTAL)"
-+ depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK && EXPERIMENTAL
-+ select MIGRATION
-+ help
-+ This enables the Contiguous Memory Allocator which allows drivers
-+ to allocate big physically-contiguous blocks of memory for use with
-+ hardware components that do not support I/O map nor scatter-gather.
-+
-+ For more information see <include/linux/dma-contiguous.h>.
-+ If unsure, say "n".
-+
-+if CMA
-+
-+config CMA_DEBUG
-+ bool "CMA debug messages (DEVELOPMENT)"
-+ depends on DEBUG_KERNEL
-+ help
-+ Turns on debug messages in CMA. This produces KERN_DEBUG
-+ messages for every CMA call as well as various messages while
-+ processing calls such as dma_alloc_from_contiguous().
-+ This option does not affect warning and error messages.
-+
-+comment "Default contiguous memory area size:"
-+
-+config CMA_SIZE_MBYTES
-+ int "Size in Mega Bytes"
-+ depends on !CMA_SIZE_SEL_PERCENTAGE
-+ default 16
-+ help
-+ Defines the size (in MiB) of the default memory area for Contiguous
-+ Memory Allocator.
-+
-+config CMA_SIZE_PERCENTAGE
-+ int "Percentage of total memory"
-+ depends on !CMA_SIZE_SEL_MBYTES
-+ default 10
-+ help
-+ Defines the size of the default memory area for Contiguous Memory
-+ Allocator as a percentage of the total memory in the system.
-+
-+choice
-+ prompt "Selected region size"
-+ default CMA_SIZE_SEL_ABSOLUTE
-+
-+config CMA_SIZE_SEL_MBYTES
-+ bool "Use mega bytes value only"
-+
-+config CMA_SIZE_SEL_PERCENTAGE
-+ bool "Use percentage value only"
-+
-+config CMA_SIZE_SEL_MIN
-+ bool "Use lower value (minimum)"
-+
-+config CMA_SIZE_SEL_MAX
-+ bool "Use higher value (maximum)"
-+
-+endchoice
-+
-+config CMA_ALIGNMENT
-+ int "Maximum PAGE_SIZE order of alignment for contiguous buffers"
-+ range 4 9
-+ default 8
-+ help
-+ DMA mapping framework by default aligns all buffers to the smallest
-+ PAGE_SIZE order which is greater than or equal to the requested buffer
-+ size. This works well for buffers up to a few hundreds kilobytes, but
-+ for larger buffers it just a memory waste. With this parameter you can
-+ specify the maximum PAGE_SIZE order for contiguous buffers. Larger
-+ buffers will be aligned only to this specified order. The order is
-+ expressed as a power of two multiplied by the PAGE_SIZE.
-+
-+ For example, if your system defaults to 4KiB pages, the order value
-+ of 8 means that the buffers will be aligned up to 1MiB only.
-+
-+ If unsure, leave the default value "8".
-+
-+config CMA_AREAS
-+ int "Maximum count of the CMA device-private areas"
-+ default 7
-+ help
-+ CMA allows to create CMA areas for particular devices. This parameter
-+ sets the maximum number of such device private CMA areas in the
-+ system.
-+
-+ If unsure, leave the default value "7".
-+
-+endif
-+
- endmenu
---- a/drivers/base/Makefile
-+++ b/drivers/base/Makefile
-@@ -6,6 +6,7 @@ obj-y := core.o bus.o dd.o syscore.o \
- attribute_container.o transport_class.o \
- topology.o
- obj-$(CONFIG_DEVTMPFS) += devtmpfs.o
-+obj-$(CONFIG_CMA) += dma-contiguous.o
- obj-y += power/
- obj-$(CONFIG_HAS_DMA) += dma-mapping.o
- obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
---- /dev/null
-+++ b/drivers/base/dma-contiguous.c
-@@ -0,0 +1,401 @@
-+/*
-+ * Contiguous Memory Allocator for DMA mapping framework
-+ * Copyright (c) 2010-2011 by Samsung Electronics.
-+ * Written by:
-+ * Marek Szyprowski <m.szyprowski@samsung.com>
-+ * Michal Nazarewicz <mina86@mina86.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of the
-+ * License or (at your optional) any later version of the license.
-+ */
-+
-+#define pr_fmt(fmt) "cma: " fmt
-+
-+#ifdef CONFIG_CMA_DEBUG
-+#ifndef DEBUG
-+# define DEBUG
-+#endif
-+#endif
-+
-+#include <asm/page.h>
-+#include <asm/dma-contiguous.h>
-+
-+#include <linux/memblock.h>
-+#include <linux/err.h>
-+#include <linux/mm.h>
-+#include <linux/mutex.h>
-+#include <linux/page-isolation.h>
-+#include <linux/slab.h>
-+#include <linux/swap.h>
-+#include <linux/mm_types.h>
-+#include <linux/dma-contiguous.h>
-+
-+#ifndef SZ_1M
-+#define SZ_1M (1 << 20)
-+#endif
-+
-+struct cma {
-+ unsigned long base_pfn;
-+ unsigned long count;
-+ unsigned long *bitmap;
-+};
-+
-+struct cma *dma_contiguous_default_area;
-+
-+#ifdef CONFIG_CMA_SIZE_MBYTES
-+#define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES
-+#else
-+#define CMA_SIZE_MBYTES 0
-+#endif
-+
-+/*
-+ * Default global CMA area size can be defined in kernel's .config.
-+ * This is usefull mainly for distro maintainers to create a kernel
-+ * that works correctly for most supported systems.
-+ * The size can be set in bytes or as a percentage of the total memory
-+ * in the system.
-+ *
-+ * Users, who want to set the size of global CMA area for their system
-+ * should use cma= kernel parameter.
-+ */
-+static const unsigned long size_bytes = CMA_SIZE_MBYTES * SZ_1M;
-+static long size_cmdline = -1;
-+
-+static int __init early_cma(char *p)
-+{
-+ pr_debug("%s(%s)\n", __func__, p);
-+ size_cmdline = memparse(p, &p);
-+ return 0;
-+}
-+early_param("cma", early_cma);
-+
-+#ifdef CONFIG_CMA_SIZE_PERCENTAGE
-+
-+static unsigned long __init __maybe_unused cma_early_percent_memory(void)
-+{
-+ struct memblock_region *reg;
-+ unsigned long total_pages = 0;
-+
-+ /*
-+ * We cannot use memblock_phys_mem_size() here, because
-+ * memblock_analyze() has not been called yet.
-+ */
-+ for_each_memblock(memory, reg)
-+ total_pages += memblock_region_memory_end_pfn(reg) -
-+ memblock_region_memory_base_pfn(reg);
-+
-+ return (total_pages * CONFIG_CMA_SIZE_PERCENTAGE / 100) << PAGE_SHIFT;
-+}
-+
-+#else
-+
-+static inline __maybe_unused unsigned long cma_early_percent_memory(void)
-+{
-+ return 0;
-+}
-+
-+#endif
-+
-+/**
-+ * dma_contiguous_reserve() - reserve area for contiguous memory handling
-+ * @limit: End address of the reserved memory (optional, 0 for any).
-+ *
-+ * This function reserves memory from early allocator. It should be
-+ * called by arch specific code once the early allocator (memblock or bootmem)
-+ * has been activated and all other subsystems have already allocated/reserved
-+ * memory.
-+ */
-+void __init dma_contiguous_reserve(phys_addr_t limit)
-+{
-+ unsigned long selected_size = 0;
-+
-+ pr_debug("%s(limit %08lx)\n", __func__, (unsigned long)limit);
-+
-+ if (size_cmdline != -1) {
-+ selected_size = size_cmdline;
-+ } else {
-+#ifdef CONFIG_CMA_SIZE_SEL_MBYTES
-+ selected_size = size_bytes;
-+#elif defined(CONFIG_CMA_SIZE_SEL_PERCENTAGE)
-+ selected_size = cma_early_percent_memory();
-+#elif defined(CONFIG_CMA_SIZE_SEL_MIN)
-+ selected_size = min(size_bytes, cma_early_percent_memory());
-+#elif defined(CONFIG_CMA_SIZE_SEL_MAX)
-+ selected_size = max(size_bytes, cma_early_percent_memory());
-+#endif
-+ }
-+
-+ if (selected_size) {
-+ pr_debug("%s: reserving %ld MiB for global area\n", __func__,
-+ selected_size / SZ_1M);
-+
-+ dma_declare_contiguous(NULL, selected_size, 0, limit);
-+ }
-+};
-+
-+static DEFINE_MUTEX(cma_mutex);
-+
-+static __init int cma_activate_area(unsigned long base_pfn, unsigned long count)
-+{
-+ unsigned long pfn = base_pfn;
-+ unsigned i = count >> pageblock_order;
-+ struct zone *zone;
-+
-+ WARN_ON_ONCE(!pfn_valid(pfn));
-+ zone = page_zone(pfn_to_page(pfn));
-+
-+ do {
-+ unsigned j;
-+ base_pfn = pfn;
-+ for (j = pageblock_nr_pages; j; --j, pfn++) {
-+ WARN_ON_ONCE(!pfn_valid(pfn));
-+ if (page_zone(pfn_to_page(pfn)) != zone)
-+ return -EINVAL;
-+ }
-+ init_cma_reserved_pageblock(pfn_to_page(base_pfn));
-+ } while (--i);
-+ return 0;
-+}
-+
-+static __init struct cma *cma_create_area(unsigned long base_pfn,
-+ unsigned long count)
-+{
-+ int bitmap_size = BITS_TO_LONGS(count) * sizeof(long);
-+ struct cma *cma;
-+ int ret = -ENOMEM;
-+
-+ pr_debug("%s(base %08lx, count %lx)\n", __func__, base_pfn, count);
-+
-+ cma = kmalloc(sizeof *cma, GFP_KERNEL);
-+ if (!cma)
-+ return ERR_PTR(-ENOMEM);
-+
-+ cma->base_pfn = base_pfn;
-+ cma->count = count;
-+ cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-+
-+ if (!cma->bitmap)
-+ goto no_mem;
-+
-+ ret = cma_activate_area(base_pfn, count);
-+ if (ret)
-+ goto error;
-+
-+ pr_debug("%s: returned %p\n", __func__, (void *)cma);
-+ return cma;
-+
-+error:
-+ kfree(cma->bitmap);
-+no_mem:
-+ kfree(cma);
-+ return ERR_PTR(ret);
-+}
-+
-+static struct cma_reserved {
-+ phys_addr_t start;
-+ unsigned long size;
-+ struct device *dev;
-+} cma_reserved[MAX_CMA_AREAS] __initdata;
-+static unsigned cma_reserved_count __initdata;
-+
-+static int __init cma_init_reserved_areas(void)
-+{
-+ struct cma_reserved *r = cma_reserved;
-+ unsigned i = cma_reserved_count;
-+
-+ pr_debug("%s()\n", __func__);
-+
-+ for (; i; --i, ++r) {
-+ struct cma *cma;
-+ cma = cma_create_area(PFN_DOWN(r->start),
-+ r->size >> PAGE_SHIFT);
-+ if (!IS_ERR(cma))
-+ dev_set_cma_area(r->dev, cma);
-+ }
-+ return 0;
-+}
-+core_initcall(cma_init_reserved_areas);
-+
-+/**
-+ * dma_declare_contiguous() - reserve area for contiguous memory handling
-+ * for particular device
-+ * @dev: Pointer to device structure.
-+ * @size: Size of the reserved memory.
-+ * @base: Start address of the reserved memory (optional, 0 for any).
-+ * @limit: End address of the reserved memory (optional, 0 for any).
-+ *
-+ * This function reserves memory for specified device. It should be
-+ * called by board specific code when early allocator (memblock or bootmem)
-+ * is still activate.
-+ */
-+int __init dma_declare_contiguous(struct device *dev, unsigned long size,
-+ phys_addr_t base, phys_addr_t limit)
-+{
-+ struct cma_reserved *r = &cma_reserved[cma_reserved_count];
-+ unsigned long alignment;
-+
-+ pr_debug("%s(size %lx, base %08lx, limit %08lx)\n", __func__,
-+ (unsigned long)size, (unsigned long)base,
-+ (unsigned long)limit);
-+
-+ /* Sanity checks */
-+ if (cma_reserved_count == ARRAY_SIZE(cma_reserved)) {
-+ pr_err("Not enough slots for CMA reserved regions!\n");
-+ return -ENOSPC;
-+ }
-+
-+ if (!size)
-+ return -EINVAL;
-+
-+ /* Sanitise input arguments */
-+ alignment = PAGE_SIZE << max(MAX_ORDER, pageblock_order);
-+ base = ALIGN(base, alignment);
-+ size = ALIGN(size, alignment);
-+ limit &= ~(alignment - 1);
-+
-+ /* Reserve memory */
-+ if (base) {
-+ if (memblock_is_region_reserved(base, size) ||
-+ memblock_reserve(base, size) < 0) {
-+ base = -EBUSY;
-+ goto err;
-+ }
-+ } else {
-+ /*
-+ * Use __memblock_alloc_base() since
-+ * memblock_alloc_base() panic()s.
-+ */
-+ phys_addr_t addr = __memblock_alloc_base(size, alignment, limit);
-+ if (!addr) {
-+ base = -ENOMEM;
-+ goto err;
-+ } else if (addr + size > ~(unsigned long)0) {
-+ memblock_free(addr, size);
-+ base = -EINVAL;
-+ goto err;
-+ } else {
-+ base = addr;
-+ }
-+ }
-+
-+ /*
-+ * Each reserved area must be initialised later, when more kernel
-+ * subsystems (like slab allocator) are available.
-+ */
-+ r->start = base;
-+ r->size = size;
-+ r->dev = dev;
-+ cma_reserved_count++;
-+ pr_info("CMA: reserved %ld MiB at %08lx\n", size / SZ_1M,
-+ (unsigned long)base);
-+
-+ /* Architecture specific contiguous memory fixup. */
-+ dma_contiguous_early_fixup(base, size);
-+ return 0;
-+err:
-+ pr_err("CMA: failed to reserve %ld MiB\n", size / SZ_1M);
-+ return base;
-+}
-+
-+/**
-+ * dma_alloc_from_contiguous() - allocate pages from contiguous area
-+ * @dev: Pointer to device for which the allocation is performed.
-+ * @count: Requested number of pages.
-+ * @align: Requested alignment of pages (in PAGE_SIZE order).
-+ *
-+ * This function allocates memory buffer for specified device. It uses
-+ * device specific contiguous memory area if available or the default
-+ * global one. Requires architecture specific get_dev_cma_area() helper
-+ * function.
-+ */
-+struct page *dma_alloc_from_contiguous(struct device *dev, int count,
-+ unsigned int align)
-+{
-+ unsigned long mask, pfn, pageno, start = 0;
-+ struct cma *cma = dev_get_cma_area(dev);
-+ int ret;
-+
-+ if (!cma || !cma->count)
-+ return NULL;
-+
-+ if (align > CONFIG_CMA_ALIGNMENT)
-+ align = CONFIG_CMA_ALIGNMENT;
-+
-+ pr_debug("%s(cma %p, count %d, align %d)\n", __func__, (void *)cma,
-+ count, align);
-+
-+ if (!count)
-+ return NULL;
-+
-+ mask = (1 << align) - 1;
-+
-+ mutex_lock(&cma_mutex);
-+
-+ for (;;) {
-+ pageno = bitmap_find_next_zero_area(cma->bitmap, cma->count,
-+ start, count, mask);
-+ if (pageno >= cma->count) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ pfn = cma->base_pfn + pageno;
-+ ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA);
-+ if (ret == 0) {
-+ bitmap_set(cma->bitmap, pageno, count);
-+ break;
-+ } else if (ret != -EBUSY) {
-+ goto error;
-+ }
-+ pr_debug("%s(): memory range at %p is busy, retrying\n",
-+ __func__, pfn_to_page(pfn));
-+ /* try again with a bit different memory target */
-+ start = pageno + mask + 1;
-+ }
-+
-+ mutex_unlock(&cma_mutex);
-+
-+ pr_debug("%s(): returned %p\n", __func__, pfn_to_page(pfn));
-+ return pfn_to_page(pfn);
-+error:
-+ mutex_unlock(&cma_mutex);
-+ return NULL;
-+}
-+
-+/**
-+ * dma_release_from_contiguous() - release allocated pages
-+ * @dev: Pointer to device for which the pages were allocated.
-+ * @pages: Allocated pages.
-+ * @count: Number of allocated pages.
-+ *
-+ * This function releases memory allocated by dma_alloc_from_contiguous().
-+ * It returns false when provided pages do not belong to contiguous area and
-+ * true otherwise.
-+ */
-+bool dma_release_from_contiguous(struct device *dev, struct page *pages,
-+ int count)
-+{
-+ struct cma *cma = dev_get_cma_area(dev);
-+ unsigned long pfn;
-+
-+ if (!cma || !pages)
-+ return false;
-+
-+ pr_debug("%s(page %p)\n", __func__, (void *)pages);
-+
-+ pfn = page_to_pfn(pages);
-+
-+ if (pfn < cma->base_pfn || pfn >= cma->base_pfn + cma->count)
-+ return false;
-+
-+ VM_BUG_ON(pfn + count > cma->base_pfn + cma->count);
-+
-+ mutex_lock(&cma_mutex);
-+ bitmap_clear(cma->bitmap, pfn - cma->base_pfn, count);
-+ free_contig_range(pfn, count);
-+ mutex_unlock(&cma_mutex);
-+
-+ return true;
-+}
---- /dev/null
-+++ b/include/asm-generic/dma-contiguous.h
-@@ -0,0 +1,28 @@
-+#ifndef ASM_DMA_CONTIGUOUS_H
-+#define ASM_DMA_CONTIGUOUS_H
-+
-+#ifdef __KERNEL__
-+#ifdef CONFIG_CMA
-+
-+#include <linux/device.h>
-+#include <linux/dma-contiguous.h>
-+
-+static inline struct cma *dev_get_cma_area(struct device *dev)
-+{
-+ if (dev && dev->cma_area)
-+ return dev->cma_area;
-+ return dma_contiguous_default_area;
-+}
-+
-+static inline void dev_set_cma_area(struct device *dev, struct cma *cma)
-+{
-+ if (dev)
-+ dev->cma_area = cma;
-+ if (!dev || !dma_contiguous_default_area)
-+ dma_contiguous_default_area = cma;
-+}
-+
-+#endif
-+#endif
-+
-+#endif
---- a/include/linux/device.h
-+++ b/include/linux/device.h
-@@ -661,6 +661,10 @@ struct device {
-
- struct dma_coherent_mem *dma_mem; /* internal for coherent mem
- override */
-+#ifdef CONFIG_CMA
-+ struct cma *cma_area; /* contiguous memory area for dma
-+ allocations */
-+#endif
- /* arch specific additions */
- struct dev_archdata archdata;
-
---- /dev/null
-+++ b/include/linux/dma-contiguous.h
-@@ -0,0 +1,110 @@
-+#ifndef __LINUX_CMA_H
-+#define __LINUX_CMA_H
-+
-+/*
-+ * Contiguous Memory Allocator for DMA mapping framework
-+ * Copyright (c) 2010-2011 by Samsung Electronics.
-+ * Written by:
-+ * Marek Szyprowski <m.szyprowski@samsung.com>
-+ * Michal Nazarewicz <mina86@mina86.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of the
-+ * License or (at your optional) any later version of the license.
-+ */
-+
-+/*
-+ * Contiguous Memory Allocator
-+ *
-+ * The Contiguous Memory Allocator (CMA) makes it possible to
-+ * allocate big contiguous chunks of memory after the system has
-+ * booted.
-+ *
-+ * Why is it needed?
-+ *
-+ * Various devices on embedded systems have no scatter-getter and/or
-+ * IO map support and require contiguous blocks of memory to
-+ * operate. They include devices such as cameras, hardware video
-+ * coders, etc.
-+ *
-+ * Such devices often require big memory buffers (a full HD frame
-+ * is, for instance, more then 2 mega pixels large, i.e. more than 6
-+ * MB of memory), which makes mechanisms such as kmalloc() or
-+ * alloc_page() ineffective.
-+ *
-+ * At the same time, a solution where a big memory region is
-+ * reserved for a device is suboptimal since often more memory is
-+ * reserved then strictly required and, moreover, the memory is
-+ * inaccessible to page system even if device drivers don't use it.
-+ *
-+ * CMA tries to solve this issue by operating on memory regions
-+ * where only movable pages can be allocated from. This way, kernel
-+ * can use the memory for pagecache and when device driver requests
-+ * it, allocated pages can be migrated.
-+ *
-+ * Driver usage
-+ *
-+ * CMA should not be used by the device drivers directly. It is
-+ * only a helper framework for dma-mapping subsystem.
-+ *
-+ * For more information, see kernel-docs in drivers/base/dma-contiguous.c
-+ */
-+
-+#ifdef __KERNEL__
-+
-+struct cma;
-+struct page;
-+struct device;
-+
-+#ifdef CONFIG_CMA
-+
-+/*
-+ * There is always at least global CMA area and a few optional device
-+ * private areas configured in kernel .config.
-+ */
-+#define MAX_CMA_AREAS (1 + CONFIG_CMA_AREAS)
-+
-+extern struct cma *dma_contiguous_default_area;
-+
-+void dma_contiguous_reserve(phys_addr_t addr_limit);
-+int dma_declare_contiguous(struct device *dev, unsigned long size,
-+ phys_addr_t base, phys_addr_t limit);
-+
-+struct page *dma_alloc_from_contiguous(struct device *dev, int count,
-+ unsigned int order);
-+bool dma_release_from_contiguous(struct device *dev, struct page *pages,
-+ int count);
-+
-+#else
-+
-+#define MAX_CMA_AREAS (0)
-+
-+static inline void dma_contiguous_reserve(phys_addr_t limit) { }
-+
-+static inline
-+int dma_declare_contiguous(struct device *dev, unsigned long size,
-+ phys_addr_t base, phys_addr_t limit)
-+{
-+ return -ENOSYS;
-+}
-+
-+static inline
-+struct page *dma_alloc_from_contiguous(struct device *dev, int count,
-+ unsigned int order)
-+{
-+ return NULL;
-+}
-+
-+static inline
-+bool dma_release_from_contiguous(struct device *dev, struct page *pages,
-+ int count)
-+{
-+ return false;
-+}
-+
-+#endif
-+
-+#endif
-+
-+#endif
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:04 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:47 +0900
-Subject: [PATCH v2 30/58] iommu/core: pass a user-provided token to fault handlers
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-31-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Ohad Ben-Cohen <ohad@wizery.com>
-
-Sometimes a single IOMMU user may have to deal with several
-different IOMMU devices (e.g. remoteproc).
-
-When an IOMMU fault happens, such users have to regain their
-context in order to deal with the fault.
-
-Users can't use the private fields of neither the iommu_domain nor
-the IOMMU device, because those are already used by the IOMMU core
-and low level driver (respectively).
-
-This patch just simply allows users to pass a private token (most
-notably their own context pointer) to iommu_set_fault_handler(),
-and then makes sure it is provided back to the users whenever
-an IOMMU fault happens.
-
-The patch also adopts remoteproc to the new fault handling
-interface, but the real functionality using this (recovery of
-remote processors) will only be added later in a subsequent patch
-set.
-
-Cc: Fernando Guzman Lugo <fernando.lugo@ti.com>
-Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
-Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
-(cherry picked from commit 77ca23323594589ac8cba1c8d59bfe7e85d3cb8b)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- drivers/iommu/iommu.c | 5 ++++-
- drivers/remoteproc/remoteproc_core.c | 4 ++--
- include/linux/iommu.h | 10 ++++++----
- 3 files changed, 12 insertions(+), 7 deletions(-)
-
-diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
-index 2198b2d..8b9ded8 100644
---- a/drivers/iommu/iommu.c
-+++ b/drivers/iommu/iommu.c
-@@ -119,6 +119,7 @@ EXPORT_SYMBOL_GPL(iommu_present);
- * iommu_set_fault_handler() - set a fault handler for an iommu domain
- * @domain: iommu domain
- * @handler: fault handler
-+ * @token: user data, will be passed back to the fault handler
- *
- * This function should be used by IOMMU users which want to be notified
- * whenever an IOMMU fault happens.
-@@ -127,11 +128,13 @@ EXPORT_SYMBOL_GPL(iommu_present);
- * error code otherwise.
- */
- void iommu_set_fault_handler(struct iommu_domain *domain,
-- iommu_fault_handler_t handler)
-+ iommu_fault_handler_t handler,
-+ void *token)
- {
- BUG_ON(!domain);
-
- domain->handler = handler;
-+ domain->handler_token = token;
- }
- EXPORT_SYMBOL_GPL(iommu_set_fault_handler);
-
-diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
-index 7591b97..0142e52 100644
---- a/drivers/remoteproc/remoteproc_core.c
-+++ b/drivers/remoteproc/remoteproc_core.c
-@@ -78,7 +78,7 @@ typedef int (*rproc_handle_resource_t)(struct rproc *rproc, void *, int avail);
- * the recovery of the remote processor.
- */
- static int rproc_iommu_fault(struct iommu_domain *domain, struct device *dev,
-- unsigned long iova, int flags)
-+ unsigned long iova, int flags, void *token)
- {
- dev_err(dev, "iommu fault: da 0x%lx flags 0x%x\n", iova, flags);
-
-@@ -117,7 +117,7 @@ static int rproc_enable_iommu(struct rproc *rproc)
- return -ENOMEM;
- }
-
-- iommu_set_fault_handler(domain, rproc_iommu_fault);
-+ iommu_set_fault_handler(domain, rproc_iommu_fault, rproc);
-
- ret = iommu_attach_device(domain, dev);
- if (ret) {
-diff --git a/include/linux/iommu.h b/include/linux/iommu.h
-index d937580..450293f 100644
---- a/include/linux/iommu.h
-+++ b/include/linux/iommu.h
-@@ -35,12 +35,13 @@ struct iommu_domain;
- #define IOMMU_FAULT_WRITE 0x1
-
- typedef int (*iommu_fault_handler_t)(struct iommu_domain *,
-- struct device *, unsigned long, int);
-+ struct device *, unsigned long, int, void *);
-
- struct iommu_domain {
- struct iommu_ops *ops;
- void *priv;
- iommu_fault_handler_t handler;
-+ void *handler_token;
- };
-
- #define IOMMU_CAP_CACHE_COHERENCY 0x1
-@@ -95,7 +96,7 @@ extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
- extern int iommu_domain_has_cap(struct iommu_domain *domain,
- unsigned long cap);
- extern void iommu_set_fault_handler(struct iommu_domain *domain,
-- iommu_fault_handler_t handler);
-+ iommu_fault_handler_t handler, void *token);
- extern int iommu_device_group(struct device *dev, unsigned int *groupid);
-
- /**
-@@ -132,7 +133,8 @@ static inline int report_iommu_fault(struct iommu_domain *domain,
- * invoke it.
- */
- if (domain->handler)
-- ret = domain->handler(domain, dev, iova, flags);
-+ ret = domain->handler(domain, dev, iova, flags,
-+ domain->handler_token);
-
- return ret;
- }
-@@ -191,7 +193,7 @@ static inline int domain_has_cap(struct iommu_domain *domain,
- }
-
- static inline void iommu_set_fault_handler(struct iommu_domain *domain,
-- iommu_fault_handler_t handler)
-+ iommu_fault_handler_t handler, void *token)
- {
- }
-
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:40 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:02 +0900
-Subject: [PATCH v2 45/58] mm: clean up __count_immobile_pages()
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-46-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Minchan Kim <minchan@kernel.org>
-
-The __count_immobile_pages() naming is rather awkward. Choose a more
-clear name and add a comment.
-
-Signed-off-by: Minchan Kim <minchan@kernel.org>
-Cc: Andrea Arcangeli <aarcange@redhat.com>
-Cc: Mel Gorman <mgorman@suse.de>
-Cc: Michal Hocko <mhocko@suse.cz>
-Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
-Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-(cherry picked from commit 80934513b230bfcf70265f2ef0fdae89fb391633)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- mm/page_alloc.c | 34 ++++++++++++++++++----------------
- 1 file changed, 18 insertions(+), 16 deletions(-)
-
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -5474,26 +5474,28 @@ void set_pageblock_flags_group(struct pa
- }
-
- /*
-- * This is designed as sub function...plz see page_isolation.c also.
-- * set/clear page block's type to be ISOLATE.
-- * page allocater never alloc memory from ISOLATE block.
-+ * This function checks whether pageblock includes unmovable pages or not.
-+ * If @count is not zero, it is okay to include less @count unmovable pages
-+ *
-+ * PageLRU check wihtout isolation or lru_lock could race so that
-+ * MIGRATE_MOVABLE block might include unmovable pages. It means you can't
-+ * expect this function should be exact.
- */
--
--static int
--__count_immobile_pages(struct zone *zone, struct page *page, int count)
-+static bool
-+__has_unmovable_pages(struct zone *zone, struct page *page, int count)
- {
- unsigned long pfn, iter, found;
- int mt;
-
- /*
- * For avoiding noise data, lru_add_drain_all() should be called
-- * If ZONE_MOVABLE, the zone never contains immobile pages
-+ * If ZONE_MOVABLE, the zone never contains unmovable pages
- */
- if (zone_idx(zone) == ZONE_MOVABLE)
-- return true;
-+ return false;
- mt = get_pageblock_migratetype(page);
- if (mt == MIGRATE_MOVABLE || is_migrate_cma(mt))
-- return true;
-+ return false;
-
- pfn = page_to_pfn(page);
- for (found = 0, iter = 0; iter < pageblock_nr_pages; iter++) {
-@@ -5524,9 +5526,9 @@ __count_immobile_pages(struct zone *zone
- * page at boot.
- */
- if (found > count)
-- return false;
-+ return true;
- }
-- return true;
-+ return false;
- }
-
- bool is_pageblock_removable_nolock(struct page *page)
-@@ -5550,7 +5552,7 @@ bool is_pageblock_removable_nolock(struc
- zone->zone_start_pfn + zone->spanned_pages <= pfn)
- return false;
-
-- return __count_immobile_pages(zone, page, 0);
-+ return !__has_unmovable_pages(zone, page, 0);
- }
-
- int set_migratetype_isolate(struct page *page)
-@@ -5589,12 +5591,12 @@ int set_migratetype_isolate(struct page
- * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself.
- * We just check MOVABLE pages.
- */
-- if (__count_immobile_pages(zone, page, arg.pages_found))
-+ if (!__has_unmovable_pages(zone, page, arg.pages_found))
- ret = 0;
--
- /*
-- * immobile means "not-on-lru" paes. If immobile is larger than
-- * removable-by-driver pages reported by notifier, we'll fail.
-+ * Unmovable means "not-on-lru" pages. If Unmovable pages are
-+ * larger than removable-by-driver pages reported by notifier,
-+ * we'll fail.
- */
-
- out:
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:17 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:52 +0900
-Subject: [PATCH v2 35/58] mm: cma: don't replace lowmem pages with highmem
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-36-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Rabin Vincent <rabin@rab.in>
-
-The filesystem layer expects pages in the block device's mapping to not
-be in highmem (the mapping's gfp mask is set in bdget()), but CMA can
-currently replace lowmem pages with highmem pages, leading to crashes in
-filesystem code such as the one below:
-
- Unable to handle kernel NULL pointer dereference at virtual address 00000400
- pgd = c0c98000
- [00000400] *pgd=00c91831, *pte=00000000, *ppte=00000000
- Internal error: Oops: 817 [#1] PREEMPT SMP ARM
- CPU: 0 Not tainted (3.5.0-rc5+ #80)
- PC is at __memzero+0x24/0x80
- ...
- Process fsstress (pid: 323, stack limit = 0xc0cbc2f0)
- Backtrace:
- [<c010e3f0>] (ext4_getblk+0x0/0x180) from [<c010e58c>] (ext4_bread+0x1c/0x98)
- [<c010e570>] (ext4_bread+0x0/0x98) from [<c0117944>] (ext4_mkdir+0x160/0x3bc)
- r4:c15337f0
- [<c01177e4>] (ext4_mkdir+0x0/0x3bc) from [<c00c29e0>] (vfs_mkdir+0x8c/0x98)
- [<c00c2954>] (vfs_mkdir+0x0/0x98) from [<c00c2a60>] (sys_mkdirat+0x74/0xac)
- r6:00000000 r5:c152eb40 r4:000001ff r3:c14b43f0
- [<c00c29ec>] (sys_mkdirat+0x0/0xac) from [<c00c2ab8>] (sys_mkdir+0x20/0x24)
- r6:beccdcf0 r5:00074000 r4:beccdbbc
- [<c00c2a98>] (sys_mkdir+0x0/0x24) from [<c000e3c0>] (ret_fast_syscall+0x0/0x30)
-
-Fix this by replacing only highmem pages with highmem.
-
-Reported-by: Laura Abbott <lauraa@codeaurora.org>
-Signed-off-by: Rabin Vincent <rabin@rab.in>
-Acked-by: Michal Nazarewicz <mina86@mina86.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit 6a6dccba2fdc2a69f1f36b8f1c0acc8598e7221b)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- mm/page_alloc.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -5641,7 +5641,12 @@ static struct page *
- __alloc_contig_migrate_alloc(struct page *page, unsigned long private,
- int **resultp)
- {
-- return alloc_page(GFP_HIGHUSER_MOVABLE);
-+ gfp_t gfp_mask = GFP_USER | __GFP_MOVABLE;
-+
-+ if (PageHighMem(page))
-+ gfp_mask |= __GFP_HIGHMEM;
-+
-+ return alloc_page(gfp_mask);
- }
-
- /* [start, end) must belong to a single zone. */
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:58 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:09 +0900
-Subject: [PATCH v2 52/58] mm: cma: fix alignment requirements for contiguous regions
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-53-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-Contiguous Memory Allocator requires each of its regions to be aligned
-in such a way that it is possible to change migration type for all
-pageblocks holding it and then isolate page of largest possible order from
-the buddy allocator (which is MAX_ORDER-1). This patch relaxes alignment
-requirements by one order, because MAX_ORDER alignment is not really
-needed.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-CC: Michal Nazarewicz <mina86@mina86.com>
-Acked-by: Michal Nazarewicz <mina86@mina86.com>
-(cherry picked from commit 7ce9bf1f4785dab0598a19a7fcb0733a18193e4e)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- drivers/base/dma-contiguous.c | 2 +-
- 1 files changed, 1 insertions(+), 1 deletions(-)
-
-diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
-index 78efb03..34d94c7 100644
---- a/drivers/base/dma-contiguous.c
-+++ b/drivers/base/dma-contiguous.c
-@@ -250,7 +250,7 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size,
- return -EINVAL;
-
- /* Sanitise input arguments */
-- alignment = PAGE_SIZE << max(MAX_ORDER, pageblock_order);
-+ alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
- base = ALIGN(base, alignment);
- size = ALIGN(size, alignment);
- limit &= ~(alignment - 1);
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:18 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:53 +0900
-Subject: [PATCH v2 36/58] mm: cma: fix condition check when setting global cma area
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-37-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-dev_set_cma_area incorrectly assigned cma to global area on first call
-due to incorrect check. This patch fixes this issue.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-(cherry picked from commit cc2caea5b6152b8ce66dc2bbe83dc72b60612da8)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- include/asm-generic/dma-contiguous.h | 2 +-
- 1 files changed, 1 insertions(+), 1 deletions(-)
-
-diff --git a/include/asm-generic/dma-contiguous.h b/include/asm-generic/dma-contiguous.h
-index c544356..294b1e7 100644
---- a/include/asm-generic/dma-contiguous.h
-+++ b/include/asm-generic/dma-contiguous.h
-@@ -18,7 +18,7 @@ static inline void dev_set_cma_area(struct device *dev, struct cma *cma)
- {
- if (dev)
- dev->cma_area = cma;
-- if (!dev || !dma_contiguous_default_area)
-+ if (!dev && !dma_contiguous_default_area)
- dma_contiguous_default_area = cma;
- }
-
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:51:58 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:22 +0900
-Subject: [PATCH v2 05/58] mm: compaction: export some of the functions
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-6-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Michal Nazarewicz <mina86@mina86.com>
-
-This commit exports some of the functions from compaction.c file
-outside of it adding their declaration into internal.h header
-file so that other mm related code can use them.
-
-This forced compaction.c to always be compiled (as opposed to being
-compiled only if CONFIG_COMPACTION is defined) but as to avoid
-introducing code that user did not ask for, part of the compaction.c
-is now wrapped in on #ifdef.
-
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Mel Gorman <mel@csn.ul.ie>
-Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
-Tested-by: Rob Clark <rob.clark@linaro.org>
-Tested-by: Ohad Ben-Cohen <ohad@wizery.com>
-Tested-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-Tested-by: Robert Nelson <robertcnelson@gmail.com>
-Tested-by: Barry Song <Baohua.Song@csr.com>
-(cherry picked from commit ff9543fd32060917beb080b1eb2d1d41ec7f39e0)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- mm/Makefile | 3
- mm/compaction.c | 328 ++++++++++++++++++++++++++------------------------------
- mm/internal.h | 33 +++++
- 3 files changed, 191 insertions(+), 173 deletions(-)
-
---- a/mm/Makefile
-+++ b/mm/Makefile
-@@ -13,7 +13,7 @@ obj-y := filemap.o mempool.o oom_kill.
- readahead.o swap.o truncate.o vmscan.o shmem.o \
- prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
- page_isolation.o mm_init.o mmu_context.o percpu.o \
-- $(mmu-y)
-+ compaction.o $(mmu-y)
- obj-y += init-mm.o
-
- ifdef CONFIG_NO_BOOTMEM
-@@ -32,7 +32,6 @@ obj-$(CONFIG_NUMA) += mempolicy.o
- obj-$(CONFIG_SPARSEMEM) += sparse.o
- obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o
- obj-$(CONFIG_SLOB) += slob.o
--obj-$(CONFIG_COMPACTION) += compaction.o
- obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o
- obj-$(CONFIG_KSM) += ksm.o
- obj-$(CONFIG_PAGE_POISONING) += debug-pagealloc.o
---- a/mm/compaction.c
-+++ b/mm/compaction.c
-@@ -16,30 +16,11 @@
- #include <linux/sysfs.h>
- #include "internal.h"
-
-+#if defined CONFIG_COMPACTION || defined CONFIG_CMA
-+
- #define CREATE_TRACE_POINTS
- #include <trace/events/compaction.h>
-
--/*
-- * compact_control is used to track pages being migrated and the free pages
-- * they are being migrated to during memory compaction. The free_pfn starts
-- * at the end of a zone and migrate_pfn begins at the start. Movable pages
-- * are moved to the end of a zone during a compaction run and the run
-- * completes when free_pfn <= migrate_pfn
-- */
--struct compact_control {
-- struct list_head freepages; /* List of free pages to migrate to */
-- struct list_head migratepages; /* List of pages being migrated */
-- unsigned long nr_freepages; /* Number of isolated free pages */
-- unsigned long nr_migratepages; /* Number of pages to migrate */
-- unsigned long free_pfn; /* isolate_freepages search base */
-- unsigned long migrate_pfn; /* isolate_migratepages search base */
-- bool sync; /* Synchronous migration */
--
-- int order; /* order a direct compactor needs */
-- int migratetype; /* MOVABLE, RECLAIMABLE etc */
-- struct zone *zone;
--};
--
- static unsigned long release_freepages(struct list_head *freelist)
- {
- struct page *page, *next;
-@@ -54,6 +35,16 @@ static unsigned long release_freepages(s
- return count;
- }
-
-+static void map_pages(struct list_head *list)
-+{
-+ struct page *page;
-+
-+ list_for_each_entry(page, list, lru) {
-+ arch_alloc_page(page, 0);
-+ kernel_map_pages(page, 1, 1);
-+ }
-+}
-+
- /*
- * Isolate free pages onto a private freelist. Caller must hold zone->lock.
- * If @strict is true, will abort returning 0 on any invalid PFNs or non-free
-@@ -122,7 +113,7 @@ static unsigned long isolate_freepages_b
- * (which may be greater then end_pfn if end fell in a middle of
- * a free page).
- */
--static unsigned long
-+unsigned long
- isolate_freepages_range(unsigned long start_pfn, unsigned long end_pfn)
- {
- unsigned long isolated, pfn, block_end_pfn, flags;
-@@ -176,127 +167,6 @@ isolate_freepages_range(unsigned long st
- return pfn;
- }
-
--/* Returns true if the page is within a block suitable for migration to */
--static bool suitable_migration_target(struct page *page)
--{
--
-- int migratetype = get_pageblock_migratetype(page);
--
-- /* Don't interfere with memory hot-remove or the min_free_kbytes blocks */
-- if (migratetype == MIGRATE_ISOLATE || migratetype == MIGRATE_RESERVE)
-- return false;
--
-- /* If the page is a large free page, then allow migration */
-- if (PageBuddy(page) && page_order(page) >= pageblock_order)
-- return true;
--
-- /* If the block is MIGRATE_MOVABLE, allow migration */
-- if (migratetype == MIGRATE_MOVABLE)
-- return true;
--
-- /* Otherwise skip the block */
-- return false;
--}
--
--static void map_pages(struct list_head *list)
--{
-- struct page *page;
--
-- list_for_each_entry(page, list, lru) {
-- arch_alloc_page(page, 0);
-- kernel_map_pages(page, 1, 1);
-- }
--}
--
--/*
-- * Based on information in the current compact_control, find blocks
-- * suitable for isolating free pages from and then isolate them.
-- */
--static void isolate_freepages(struct zone *zone,
-- struct compact_control *cc)
--{
-- struct page *page;
-- unsigned long high_pfn, low_pfn, pfn, zone_end_pfn, end_pfn;
-- unsigned long flags;
-- int nr_freepages = cc->nr_freepages;
-- struct list_head *freelist = &cc->freepages;
--
-- /*
-- * Initialise the free scanner. The starting point is where we last
-- * scanned from (or the end of the zone if starting). The low point
-- * is the end of the pageblock the migration scanner is using.
-- */
-- pfn = cc->free_pfn;
-- low_pfn = cc->migrate_pfn + pageblock_nr_pages;
--
-- /*
-- * Take care that if the migration scanner is at the end of the zone
-- * that the free scanner does not accidentally move to the next zone
-- * in the next isolation cycle.
-- */
-- high_pfn = min(low_pfn, pfn);
--
-- zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
--
-- /*
-- * Isolate free pages until enough are available to migrate the
-- * pages on cc->migratepages. We stop searching if the migrate
-- * and free page scanners meet or enough free pages are isolated.
-- */
-- for (; pfn > low_pfn && cc->nr_migratepages > nr_freepages;
-- pfn -= pageblock_nr_pages) {
-- unsigned long isolated;
--
-- if (!pfn_valid(pfn))
-- continue;
--
-- /*
-- * Check for overlapping nodes/zones. It's possible on some
-- * configurations to have a setup like
-- * node0 node1 node0
-- * i.e. it's possible that all pages within a zones range of
-- * pages do not belong to a single zone.
-- */
-- page = pfn_to_page(pfn);
-- if (page_zone(page) != zone)
-- continue;
--
-- /* Check the block is suitable for migration */
-- if (!suitable_migration_target(page))
-- continue;
--
-- /*
-- * Found a block suitable for isolating free pages from. Now
-- * we disabled interrupts, double check things are ok and
-- * isolate the pages. This is to minimise the time IRQs
-- * are disabled
-- */
-- isolated = 0;
-- spin_lock_irqsave(&zone->lock, flags);
-- if (suitable_migration_target(page)) {
-- end_pfn = min(pfn + pageblock_nr_pages, zone_end_pfn);
-- isolated = isolate_freepages_block(pfn, end_pfn,
-- freelist, false);
-- nr_freepages += isolated;
-- }
-- spin_unlock_irqrestore(&zone->lock, flags);
--
-- /*
-- * Record the highest PFN we isolated pages from. When next
-- * looking for free pages, the search will restart here as
-- * page migration may have returned some pages to the allocator
-- */
-- if (isolated)
-- high_pfn = max(high_pfn, pfn);
-- }
--
-- /* split_free_page does not map the pages */
-- map_pages(freelist);
--
-- cc->free_pfn = high_pfn;
-- cc->nr_freepages = nr_freepages;
--}
--
- /* Update the number of anon and file isolated pages in the zone */
- static void acct_isolated(struct zone *zone, struct compact_control *cc)
- {
-@@ -325,13 +195,6 @@ static bool too_many_isolated(struct zon
- return isolated > (inactive + active) / 2;
- }
-
--/* possible outcome of isolate_migratepages */
--typedef enum {
-- ISOLATE_ABORT, /* Abort compaction now */
-- ISOLATE_NONE, /* No pages isolated, continue scanning */
-- ISOLATE_SUCCESS, /* Pages isolated, migrate */
--} isolate_migrate_t;
--
- /**
- * isolate_migratepages_range() - isolate all migrate-able pages in range.
- * @zone: Zone pages are in.
-@@ -351,7 +214,7 @@ typedef enum {
- * does not modify any cc's fields, in particular it does not modify
- * (or read for that matter) cc->migrate_pfn.
- */
--static unsigned long
-+unsigned long
- isolate_migratepages_range(struct zone *zone, struct compact_control *cc,
- unsigned long low_pfn, unsigned long end_pfn)
- {
-@@ -487,35 +350,118 @@ isolate_migratepages_range(struct zone *
- return low_pfn;
- }
-
-+#endif /* CONFIG_COMPACTION || CONFIG_CMA */
-+#ifdef CONFIG_COMPACTION
-+
-+/* Returns true if the page is within a block suitable for migration to */
-+static bool suitable_migration_target(struct page *page)
-+{
-+
-+ int migratetype = get_pageblock_migratetype(page);
-+
-+ /* Don't interfere with memory hot-remove or the min_free_kbytes blocks */
-+ if (migratetype == MIGRATE_ISOLATE || migratetype == MIGRATE_RESERVE)
-+ return false;
-+
-+ /* If the page is a large free page, then allow migration */
-+ if (PageBuddy(page) && page_order(page) >= pageblock_order)
-+ return true;
-+
-+ /* If the block is MIGRATE_MOVABLE, allow migration */
-+ if (migratetype == MIGRATE_MOVABLE)
-+ return true;
-+
-+ /* Otherwise skip the block */
-+ return false;
-+}
-+
- /*
-- * Isolate all pages that can be migrated from the block pointed to by
-- * the migrate scanner within compact_control.
-+ * Based on information in the current compact_control, find blocks
-+ * suitable for isolating free pages from and then isolate them.
- */
--static isolate_migrate_t isolate_migratepages(struct zone *zone,
-- struct compact_control *cc)
-+static void isolate_freepages(struct zone *zone,
-+ struct compact_control *cc)
- {
-- unsigned long low_pfn, end_pfn;
-+ struct page *page;
-+ unsigned long high_pfn, low_pfn, pfn, zone_end_pfn, end_pfn;
-+ unsigned long flags;
-+ int nr_freepages = cc->nr_freepages;
-+ struct list_head *freelist = &cc->freepages;
-
-- /* Do not scan outside zone boundaries */
-- low_pfn = max(cc->migrate_pfn, zone->zone_start_pfn);
-+ /*
-+ * Initialise the free scanner. The starting point is where we last
-+ * scanned from (or the end of the zone if starting). The low point
-+ * is the end of the pageblock the migration scanner is using.
-+ */
-+ pfn = cc->free_pfn;
-+ low_pfn = cc->migrate_pfn + pageblock_nr_pages;
-
-- /* Only scan within a pageblock boundary */
-- end_pfn = ALIGN(low_pfn + pageblock_nr_pages, pageblock_nr_pages);
-+ /*
-+ * Take care that if the migration scanner is at the end of the zone
-+ * that the free scanner does not accidentally move to the next zone
-+ * in the next isolation cycle.
-+ */
-+ high_pfn = min(low_pfn, pfn);
-
-- /* Do not cross the free scanner or scan within a memory hole */
-- if (end_pfn > cc->free_pfn || !pfn_valid(low_pfn)) {
-- cc->migrate_pfn = end_pfn;
-- return ISOLATE_NONE;
-- }
-+ zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
-
-- /* Perform the isolation */
-- low_pfn = isolate_migratepages_range(zone, cc, low_pfn, end_pfn);
-- if (!low_pfn)
-- return ISOLATE_ABORT;
-+ /*
-+ * Isolate free pages until enough are available to migrate the
-+ * pages on cc->migratepages. We stop searching if the migrate
-+ * and free page scanners meet or enough free pages are isolated.
-+ */
-+ for (; pfn > low_pfn && cc->nr_migratepages > nr_freepages;
-+ pfn -= pageblock_nr_pages) {
-+ unsigned long isolated;
-
-- cc->migrate_pfn = low_pfn;
-+ if (!pfn_valid(pfn))
-+ continue;
-
-- return ISOLATE_SUCCESS;
-+ /*
-+ * Check for overlapping nodes/zones. It's possible on some
-+ * configurations to have a setup like
-+ * node0 node1 node0
-+ * i.e. it's possible that all pages within a zones range of
-+ * pages do not belong to a single zone.
-+ */
-+ page = pfn_to_page(pfn);
-+ if (page_zone(page) != zone)
-+ continue;
-+
-+ /* Check the block is suitable for migration */
-+ if (!suitable_migration_target(page))
-+ continue;
-+
-+ /*
-+ * Found a block suitable for isolating free pages from. Now
-+ * we disabled interrupts, double check things are ok and
-+ * isolate the pages. This is to minimise the time IRQs
-+ * are disabled
-+ */
-+ isolated = 0;
-+ spin_lock_irqsave(&zone->lock, flags);
-+ if (suitable_migration_target(page)) {
-+ end_pfn = min(pfn + pageblock_nr_pages, zone_end_pfn);
-+ isolated = isolate_freepages_block(pfn, end_pfn,
-+ freelist, false);
-+ nr_freepages += isolated;
-+ }
-+ spin_unlock_irqrestore(&zone->lock, flags);
-+
-+ /*
-+ * Record the highest PFN we isolated pages from. When next
-+ * looking for free pages, the search will restart here as
-+ * page migration may have returned some pages to the allocator
-+ */
-+ if (isolated)
-+ high_pfn = max(high_pfn, pfn);
-+ }
-+
-+ /* split_free_page does not map the pages */
-+ map_pages(freelist);
-+
-+ cc->free_pfn = high_pfn;
-+ cc->nr_freepages = nr_freepages;
- }
-
- /*
-@@ -564,6 +510,44 @@ static void update_nr_listpages(struct c
- cc->nr_freepages = nr_freepages;
- }
-
-+/* possible outcome of isolate_migratepages */
-+typedef enum {
-+ ISOLATE_ABORT, /* Abort compaction now */
-+ ISOLATE_NONE, /* No pages isolated, continue scanning */
-+ ISOLATE_SUCCESS, /* Pages isolated, migrate */
-+} isolate_migrate_t;
-+
-+/*
-+ * Isolate all pages that can be migrated from the block pointed to by
-+ * the migrate scanner within compact_control.
-+ */
-+static isolate_migrate_t isolate_migratepages(struct zone *zone,
-+ struct compact_control *cc)
-+{
-+ unsigned long low_pfn, end_pfn;
-+
-+ /* Do not scan outside zone boundaries */
-+ low_pfn = max(cc->migrate_pfn, zone->zone_start_pfn);
-+
-+ /* Only scan within a pageblock boundary */
-+ end_pfn = ALIGN(low_pfn + pageblock_nr_pages, pageblock_nr_pages);
-+
-+ /* Do not cross the free scanner or scan within a memory hole */
-+ if (end_pfn > cc->free_pfn || !pfn_valid(low_pfn)) {
-+ cc->migrate_pfn = end_pfn;
-+ return ISOLATE_NONE;
-+ }
-+
-+ /* Perform the isolation */
-+ low_pfn = isolate_migratepages_range(zone, cc, low_pfn, end_pfn);
-+ if (!low_pfn)
-+ return ISOLATE_ABORT;
-+
-+ cc->migrate_pfn = low_pfn;
-+
-+ return ISOLATE_SUCCESS;
-+}
-+
- static int compact_finished(struct zone *zone,
- struct compact_control *cc)
- {
-@@ -911,3 +895,5 @@ void compaction_unregister_node(struct n
- return device_remove_file(&node->dev, &dev_attr_compact);
- }
- #endif /* CONFIG_SYSFS && CONFIG_NUMA */
-+
-+#endif /* CONFIG_COMPACTION */
---- a/mm/internal.h
-+++ b/mm/internal.h
-@@ -100,6 +100,39 @@ extern void prep_compound_page(struct pa
- extern bool is_free_buddy_page(struct page *page);
- #endif
-
-+#if defined CONFIG_COMPACTION || defined CONFIG_CMA
-+
-+/*
-+ * in mm/compaction.c
-+ */
-+/*
-+ * compact_control is used to track pages being migrated and the free pages
-+ * they are being migrated to during memory compaction. The free_pfn starts
-+ * at the end of a zone and migrate_pfn begins at the start. Movable pages
-+ * are moved to the end of a zone during a compaction run and the run
-+ * completes when free_pfn <= migrate_pfn
-+ */
-+struct compact_control {
-+ struct list_head freepages; /* List of free pages to migrate to */
-+ struct list_head migratepages; /* List of pages being migrated */
-+ unsigned long nr_freepages; /* Number of isolated free pages */
-+ unsigned long nr_migratepages; /* Number of pages to migrate */
-+ unsigned long free_pfn; /* isolate_freepages search base */
-+ unsigned long migrate_pfn; /* isolate_migratepages search base */
-+ bool sync; /* Synchronous migration */
-+
-+ int order; /* order a direct compactor needs */
-+ int migratetype; /* MOVABLE, RECLAIMABLE etc */
-+ struct zone *zone;
-+};
-+
-+unsigned long
-+isolate_freepages_range(unsigned long start_pfn, unsigned long end_pfn);
-+unsigned long
-+isolate_migratepages_range(struct zone *zone, struct compact_control *cc,
-+ unsigned long low_pfn, unsigned long end_pfn);
-+
-+#endif
-
- /*
- * function for dealing with page's order in buddy system.
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:51:55 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:21 +0900
-Subject: [PATCH v2 04/58] mm: compaction: introduce isolate_freepages_range()
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-5-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Michal Nazarewicz <mina86@mina86.com>
-
-This commit introduces isolate_freepages_range() function which
-generalises isolate_freepages_block() so that it can be used on
-arbitrary PFN ranges.
-
-isolate_freepages_block() is left with only minor changes.
-
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Mel Gorman <mel@csn.ul.ie>
-Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
-Tested-by: Rob Clark <rob.clark@linaro.org>
-Tested-by: Ohad Ben-Cohen <ohad@wizery.com>
-Tested-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-Tested-by: Robert Nelson <robertcnelson@gmail.com>
-Tested-by: Barry Song <Baohua.Song@csr.com>
-(cherry picked from commit 85aa125f001f87f96a72e9e6ee515490843b1202)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- mm/compaction.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++---------
- 1 files changed, 93 insertions(+), 18 deletions(-)
-
-diff --git a/mm/compaction.c b/mm/compaction.c
-index f740488..b150a62 100644
---- a/mm/compaction.c
-+++ b/mm/compaction.c
-@@ -54,24 +54,20 @@ static unsigned long release_freepages(struct list_head *freelist)
- return count;
- }
-
--/* Isolate free pages onto a private freelist. Must hold zone->lock */
--static unsigned long isolate_freepages_block(struct zone *zone,
-- unsigned long blockpfn,
-- struct list_head *freelist)
-+/*
-+ * Isolate free pages onto a private freelist. Caller must hold zone->lock.
-+ * If @strict is true, will abort returning 0 on any invalid PFNs or non-free
-+ * pages inside of the pageblock (even though it may still end up isolating
-+ * some pages).
-+ */
-+static unsigned long isolate_freepages_block(unsigned long blockpfn,
-+ unsigned long end_pfn,
-+ struct list_head *freelist,
-+ bool strict)
- {
-- unsigned long zone_end_pfn, end_pfn;
- int nr_scanned = 0, total_isolated = 0;
- struct page *cursor;
-
-- /* Get the last PFN we should scan for free pages at */
-- zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
-- end_pfn = min(blockpfn + pageblock_nr_pages, zone_end_pfn);
--
-- /* Find the first usable PFN in the block to initialse page cursor */
-- for (; blockpfn < end_pfn; blockpfn++) {
-- if (pfn_valid_within(blockpfn))
-- break;
-- }
- cursor = pfn_to_page(blockpfn);
-
- /* Isolate free pages. This assumes the block is valid */
-@@ -79,15 +75,23 @@ static unsigned long isolate_freepages_block(struct zone *zone,
- int isolated, i;
- struct page *page = cursor;
-
-- if (!pfn_valid_within(blockpfn))
-+ if (!pfn_valid_within(blockpfn)) {
-+ if (strict)
-+ return 0;
- continue;
-+ }
- nr_scanned++;
-
-- if (!PageBuddy(page))
-+ if (!PageBuddy(page)) {
-+ if (strict)
-+ return 0;
- continue;
-+ }
-
- /* Found a free page, break it into order-0 pages */
- isolated = split_free_page(page);
-+ if (!isolated && strict)
-+ return 0;
- total_isolated += isolated;
- for (i = 0; i < isolated; i++) {
- list_add(&page->lru, freelist);
-@@ -105,6 +109,73 @@ static unsigned long isolate_freepages_block(struct zone *zone,
- return total_isolated;
- }
-
-+/**
-+ * isolate_freepages_range() - isolate free pages.
-+ * @start_pfn: The first PFN to start isolating.
-+ * @end_pfn: The one-past-last PFN.
-+ *
-+ * Non-free pages, invalid PFNs, or zone boundaries within the
-+ * [start_pfn, end_pfn) range are considered errors, cause function to
-+ * undo its actions and return zero.
-+ *
-+ * Otherwise, function returns one-past-the-last PFN of isolated page
-+ * (which may be greater then end_pfn if end fell in a middle of
-+ * a free page).
-+ */
-+static unsigned long
-+isolate_freepages_range(unsigned long start_pfn, unsigned long end_pfn)
-+{
-+ unsigned long isolated, pfn, block_end_pfn, flags;
-+ struct zone *zone = NULL;
-+ LIST_HEAD(freelist);
-+
-+ if (pfn_valid(start_pfn))
-+ zone = page_zone(pfn_to_page(start_pfn));
-+
-+ for (pfn = start_pfn; pfn < end_pfn; pfn += isolated) {
-+ if (!pfn_valid(pfn) || zone != page_zone(pfn_to_page(pfn)))
-+ break;
-+
-+ /*
-+ * On subsequent iterations ALIGN() is actually not needed,
-+ * but we keep it that we not to complicate the code.
-+ */
-+ block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
-+ block_end_pfn = min(block_end_pfn, end_pfn);
-+
-+ spin_lock_irqsave(&zone->lock, flags);
-+ isolated = isolate_freepages_block(pfn, block_end_pfn,
-+ &freelist, true);
-+ spin_unlock_irqrestore(&zone->lock, flags);
-+
-+ /*
-+ * In strict mode, isolate_freepages_block() returns 0 if
-+ * there are any holes in the block (ie. invalid PFNs or
-+ * non-free pages).
-+ */
-+ if (!isolated)
-+ break;
-+
-+ /*
-+ * If we managed to isolate pages, it is always (1 << n) *
-+ * pageblock_nr_pages for some non-negative n. (Max order
-+ * page may span two pageblocks).
-+ */
-+ }
-+
-+ /* split_free_page does not map the pages */
-+ map_pages(&freelist);
-+
-+ if (pfn < end_pfn) {
-+ /* Loop terminated early, cleanup. */
-+ release_freepages(&freelist);
-+ return 0;
-+ }
-+
-+ /* We don't use freelists for anything. */
-+ return pfn;
-+}
-+
- /* Returns true if the page is within a block suitable for migration to */
- static bool suitable_migration_target(struct page *page)
- {
-@@ -145,7 +216,7 @@ static void isolate_freepages(struct zone *zone,
- struct compact_control *cc)
- {
- struct page *page;
-- unsigned long high_pfn, low_pfn, pfn;
-+ unsigned long high_pfn, low_pfn, pfn, zone_end_pfn, end_pfn;
- unsigned long flags;
- int nr_freepages = cc->nr_freepages;
- struct list_head *freelist = &cc->freepages;
-@@ -165,6 +236,8 @@ static void isolate_freepages(struct zone *zone,
- */
- high_pfn = min(low_pfn, pfn);
-
-+ zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
-+
- /*
- * Isolate free pages until enough are available to migrate the
- * pages on cc->migratepages. We stop searching if the migrate
-@@ -201,7 +274,9 @@ static void isolate_freepages(struct zone *zone,
- isolated = 0;
- spin_lock_irqsave(&zone->lock, flags);
- if (suitable_migration_target(page)) {
-- isolated = isolate_freepages_block(zone, pfn, freelist);
-+ end_pfn = min(pfn + pageblock_nr_pages, zone_end_pfn);
-+ isolated = isolate_freepages_block(pfn, end_pfn,
-+ freelist, false);
- nr_freepages += isolated;
- }
- spin_unlock_irqrestore(&zone->lock, flags);
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:51:51 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:19 +0900
-Subject: [PATCH v2 02/58] mm: compaction: introduce isolate_migratepages_range()
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-3-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Michal Nazarewicz <mina86@mina86.com>
-
-This commit introduces isolate_migratepages_range() function which
-extracts functionality from isolate_migratepages() so that it can be
-used on arbitrary PFN ranges.
-
-isolate_migratepages() function is implemented as a simple wrapper
-around isolate_migratepages_range().
-
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Mel Gorman <mel@csn.ul.ie>
-Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
-Tested-by: Rob Clark <rob.clark@linaro.org>
-Tested-by: Ohad Ben-Cohen <ohad@wizery.com>
-Tested-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-Tested-by: Robert Nelson <robertcnelson@gmail.com>
-Tested-by: Barry Song <Baohua.Song@csr.com>
-(cherry picked from commit 2fe86e0004076128f05d5a774b5c9c03d9dc3de2)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- mm/compaction.c | 75 +++++++++++++++++++++++++++++++++++++++---------------
- 1 files changed, 54 insertions(+), 21 deletions(-)
-
-diff --git a/mm/compaction.c b/mm/compaction.c
-index 459b0ab..0304ff6 100644
---- a/mm/compaction.c
-+++ b/mm/compaction.c
-@@ -250,31 +250,34 @@ typedef enum {
- ISOLATE_SUCCESS, /* Pages isolated, migrate */
- } isolate_migrate_t;
-
--/*
-- * Isolate all pages that can be migrated from the block pointed to by
-- * the migrate scanner within compact_control.
-+/**
-+ * isolate_migratepages_range() - isolate all migrate-able pages in range.
-+ * @zone: Zone pages are in.
-+ * @cc: Compaction control structure.
-+ * @low_pfn: The first PFN of the range.
-+ * @end_pfn: The one-past-the-last PFN of the range.
-+ *
-+ * Isolate all pages that can be migrated from the range specified by
-+ * [low_pfn, end_pfn). Returns zero if there is a fatal signal
-+ * pending), otherwise PFN of the first page that was not scanned
-+ * (which may be both less, equal to or more then end_pfn).
-+ *
-+ * Assumes that cc->migratepages is empty and cc->nr_migratepages is
-+ * zero.
-+ *
-+ * Apart from cc->migratepages and cc->nr_migratetypes this function
-+ * does not modify any cc's fields, in particular it does not modify
-+ * (or read for that matter) cc->migrate_pfn.
- */
--static isolate_migrate_t isolate_migratepages(struct zone *zone,
-- struct compact_control *cc)
-+static unsigned long
-+isolate_migratepages_range(struct zone *zone, struct compact_control *cc,
-+ unsigned long low_pfn, unsigned long end_pfn)
- {
-- unsigned long low_pfn, end_pfn;
- unsigned long last_pageblock_nr = 0, pageblock_nr;
- unsigned long nr_scanned = 0, nr_isolated = 0;
- struct list_head *migratelist = &cc->migratepages;
- isolate_mode_t mode = ISOLATE_ACTIVE|ISOLATE_INACTIVE;
-
-- /* Do not scan outside zone boundaries */
-- low_pfn = max(cc->migrate_pfn, zone->zone_start_pfn);
--
-- /* Only scan within a pageblock boundary */
-- end_pfn = ALIGN(low_pfn + pageblock_nr_pages, pageblock_nr_pages);
--
-- /* Do not cross the free scanner or scan within a memory hole */
-- if (end_pfn > cc->free_pfn || !pfn_valid(low_pfn)) {
-- cc->migrate_pfn = end_pfn;
-- return ISOLATE_NONE;
-- }
--
- /*
- * Ensure that there are not too many pages isolated from the LRU
- * list by either parallel reclaimers or compaction. If there are,
-@@ -283,12 +286,12 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
- while (unlikely(too_many_isolated(zone))) {
- /* async migration should just abort */
- if (!cc->sync)
-- return ISOLATE_ABORT;
-+ return 0;
-
- congestion_wait(BLK_RW_ASYNC, HZ/10);
-
- if (fatal_signal_pending(current))
-- return ISOLATE_ABORT;
-+ return 0;
- }
-
- /* Time to isolate some pages for migration */
-@@ -396,10 +399,40 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
- acct_isolated(zone, cc);
-
- spin_unlock_irq(&zone->lru_lock);
-- cc->migrate_pfn = low_pfn;
-
- trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated);
-
-+ return low_pfn;
-+}
-+
-+/*
-+ * Isolate all pages that can be migrated from the block pointed to by
-+ * the migrate scanner within compact_control.
-+ */
-+static isolate_migrate_t isolate_migratepages(struct zone *zone,
-+ struct compact_control *cc)
-+{
-+ unsigned long low_pfn, end_pfn;
-+
-+ /* Do not scan outside zone boundaries */
-+ low_pfn = max(cc->migrate_pfn, zone->zone_start_pfn);
-+
-+ /* Only scan within a pageblock boundary */
-+ end_pfn = ALIGN(low_pfn + pageblock_nr_pages, pageblock_nr_pages);
-+
-+ /* Do not cross the free scanner or scan within a memory hole */
-+ if (end_pfn > cc->free_pfn || !pfn_valid(low_pfn)) {
-+ cc->migrate_pfn = end_pfn;
-+ return ISOLATE_NONE;
-+ }
-+
-+ /* Perform the isolation */
-+ low_pfn = isolate_migratepages_range(zone, cc, low_pfn, end_pfn);
-+ if (!low_pfn)
-+ return ISOLATE_ABORT;
-+
-+ cc->migrate_pfn = low_pfn;
-+
- return ISOLATE_SUCCESS;
- }
-
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:51:53 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:20 +0900
-Subject: [PATCH v2 03/58] mm: compaction: introduce map_pages()
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-4-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Michal Nazarewicz <mina86@mina86.com>
-
-This commit creates a map_pages() function which map pages freed
-using split_free_pages(). This merely moves some code from
-isolate_freepages() so that it can be reused in other places.
-
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Mel Gorman <mel@csn.ul.ie>
-Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
-Tested-by: Robert Nelson <robertcnelson@gmail.com>
-Tested-by: Barry Song <Baohua.Song@csr.com>
-(cherry picked from commit 03d44192f69a45d780ba124f691e76020a44ebae)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- mm/compaction.c | 15 +++++++++++----
- 1 files changed, 11 insertions(+), 4 deletions(-)
-
-diff --git a/mm/compaction.c b/mm/compaction.c
-index 0304ff6..f740488 100644
---- a/mm/compaction.c
-+++ b/mm/compaction.c
-@@ -127,6 +127,16 @@ static bool suitable_migration_target(struct page *page)
- return false;
- }
-
-+static void map_pages(struct list_head *list)
-+{
-+ struct page *page;
-+
-+ list_for_each_entry(page, list, lru) {
-+ arch_alloc_page(page, 0);
-+ kernel_map_pages(page, 1, 1);
-+ }
-+}
-+
- /*
- * Based on information in the current compact_control, find blocks
- * suitable for isolating free pages from and then isolate them.
-@@ -206,10 +216,7 @@ static void isolate_freepages(struct zone *zone,
- }
-
- /* split_free_page does not map the pages */
-- list_for_each_entry(page, freelist, lru) {
-- arch_alloc_page(page, 0);
-- kernel_map_pages(page, 1, 1);
-- }
-+ map_pages(freelist);
-
- cc->free_pfn = high_pfn;
- cc->nr_freepages = nr_freepages;
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:12 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:28 +0900
-Subject: [PATCH v2 11/58] mm: extract reclaim code from __alloc_pages_direct_reclaim()
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-12-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-This patch extracts common reclaim code from __alloc_pages_direct_reclaim()
-function to separate function: __perform_reclaim() which can be later used
-by alloc_contig_range().
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
-Cc: Michal Nazarewicz <mina86@mina86.com>
-Acked-by: Mel Gorman <mel@csn.ul.ie>
-Tested-by: Rob Clark <rob.clark@linaro.org>
-Tested-by: Ohad Ben-Cohen <ohad@wizery.com>
-Tested-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-Tested-by: Robert Nelson <robertcnelson@gmail.com>
-Tested-by: Barry Song <Baohua.Song@csr.com>
-(cherry picked from commit bba9071087108d3de70bea274e35064cc480487b)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- mm/page_alloc.c | 30 +++++++++++++++++++++---------
- 1 files changed, 21 insertions(+), 9 deletions(-)
-
-diff --git a/mm/page_alloc.c b/mm/page_alloc.c
-index 8be37bc..4615531 100644
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -2130,16 +2130,13 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
- }
- #endif /* CONFIG_COMPACTION */
-
--/* The really slow allocator path where we enter direct reclaim */
--static inline struct page *
--__alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
-- struct zonelist *zonelist, enum zone_type high_zoneidx,
-- nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone,
-- int migratetype, unsigned long *did_some_progress)
-+/* Perform direct synchronous page reclaim */
-+static int
-+__perform_reclaim(gfp_t gfp_mask, unsigned int order, struct zonelist *zonelist,
-+ nodemask_t *nodemask)
- {
-- struct page *page = NULL;
- struct reclaim_state reclaim_state;
-- bool drained = false;
-+ int progress;
-
- cond_resched();
-
-@@ -2150,7 +2147,7 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
- reclaim_state.reclaimed_slab = 0;
- current->reclaim_state = &reclaim_state;
-
-- *did_some_progress = try_to_free_pages(zonelist, order, gfp_mask, nodemask);
-+ progress = try_to_free_pages(zonelist, order, gfp_mask, nodemask);
-
- current->reclaim_state = NULL;
- lockdep_clear_current_reclaim_state();
-@@ -2158,6 +2155,21 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
-
- cond_resched();
-
-+ return progress;
-+}
-+
-+/* The really slow allocator path where we enter direct reclaim */
-+static inline struct page *
-+__alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
-+ struct zonelist *zonelist, enum zone_type high_zoneidx,
-+ nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone,
-+ int migratetype, unsigned long *did_some_progress)
-+{
-+ struct page *page = NULL;
-+ bool drained = false;
-+
-+ *did_some_progress = __perform_reclaim(gfp_mask, order, zonelist,
-+ nodemask);
- if (unlikely(!(*did_some_progress)))
- return NULL;
-
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:43 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:51:03 +0900
-Subject: [PATCH v2 46/58] mm: factor out memory isolate functions
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-47-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Minchan Kim <minchan@kernel.org>
-
-mm/page_alloc.c has some memory isolation functions but they are used only
-when we enable CONFIG_{CMA|MEMORY_HOTPLUG|MEMORY_FAILURE}. So let's make
-it configurable by new CONFIG_MEMORY_ISOLATION so that it can reduce
-binary size and we can check it simple by CONFIG_MEMORY_ISOLATION, not if
-defined CONFIG_{CMA|MEMORY_HOTPLUG|MEMORY_FAILURE}.
-
-Signed-off-by: Minchan Kim <minchan@kernel.org>
-Cc: Andi Kleen <andi@firstfloor.org>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
-Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
-Cc: Mel Gorman <mgorman@suse.de>
-Cc: Michal Hocko <mhocko@suse.cz>
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-(cherry picked from commit ee6f509c3274014d1f52e7a7a10aee9f85393c5e)
-
-Conflicts:
-
- mm/Makefile
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- drivers/base/Kconfig | 1
- include/linux/page-isolation.h | 13 ++++--
- mm/Kconfig | 5 ++
- mm/Makefile | 4 +-
- mm/page_alloc.c | 80 ++---------------------------------------
- mm/page_isolation.c | 71 ++++++++++++++++++++++++++++++++++++
- 6 files changed, 93 insertions(+), 81 deletions(-)
-
---- a/drivers/base/Kconfig
-+++ b/drivers/base/Kconfig
-@@ -196,6 +196,7 @@ config CMA
- bool "Contiguous Memory Allocator (EXPERIMENTAL)"
- depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK && EXPERIMENTAL
- select MIGRATION
-+ select MEMORY_ISOLATION
- help
- This enables the Contiguous Memory Allocator which allows drivers
- to allocate big physically-contiguous blocks of memory for use with
---- a/include/linux/page-isolation.h
-+++ b/include/linux/page-isolation.h
-@@ -1,6 +1,11 @@
- #ifndef __LINUX_PAGEISOLATION_H
- #define __LINUX_PAGEISOLATION_H
-
-+
-+bool has_unmovable_pages(struct zone *zone, struct page *page, int count);
-+void set_pageblock_migratetype(struct page *page, int migratetype);
-+int move_freepages_block(struct zone *zone, struct page *page,
-+ int migratetype);
- /*
- * Changes migrate type in [start_pfn, end_pfn) to be MIGRATE_ISOLATE.
- * If specified range includes migrate types other than MOVABLE or CMA,
-@@ -10,7 +15,7 @@
- * free all pages in the range. test_page_isolated() can be used for
- * test it.
- */
--extern int
-+int
- start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
- unsigned migratetype);
-
-@@ -18,7 +23,7 @@ start_isolate_page_range(unsigned long s
- * Changes MIGRATE_ISOLATE to MIGRATE_MOVABLE.
- * target range is [start_pfn, end_pfn)
- */
--extern int
-+int
- undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
- unsigned migratetype);
-
-@@ -30,8 +35,8 @@ int test_pages_isolated(unsigned long st
- /*
- * Internal functions. Changes pageblock's migrate type.
- */
--extern int set_migratetype_isolate(struct page *page);
--extern void unset_migratetype_isolate(struct page *page, unsigned migratetype);
-+int set_migratetype_isolate(struct page *page);
-+void unset_migratetype_isolate(struct page *page, unsigned migratetype);
-
-
- #endif
---- a/mm/Kconfig
-+++ b/mm/Kconfig
-@@ -140,9 +140,13 @@ config ARCH_DISCARD_MEMBLOCK
- config NO_BOOTMEM
- boolean
-
-+config MEMORY_ISOLATION
-+ boolean
-+
- # eventually, we can have this option just 'select SPARSEMEM'
- config MEMORY_HOTPLUG
- bool "Allow for memory hot-add"
-+ select MEMORY_ISOLATION
- depends on SPARSEMEM || X86_64_ACPI_NUMA
- depends on HOTPLUG && ARCH_ENABLE_MEMORY_HOTPLUG
- depends on (IA64 || X86 || PPC_BOOK3S_64 || SUPERH || S390)
-@@ -272,6 +276,7 @@ config MEMORY_FAILURE
- depends on MMU
- depends on ARCH_SUPPORTS_MEMORY_FAILURE
- bool "Enable recovery from hardware memory errors"
-+ select MEMORY_ISOLATION
- help
- Enables code to recover from some memory failures on systems
- with MCA recovery. This allows a system to continue running
---- a/mm/Makefile
-+++ b/mm/Makefile
-@@ -12,8 +12,9 @@ obj-y := filemap.o mempool.o oom_kill.
- maccess.o page_alloc.o page-writeback.o \
- readahead.o swap.o truncate.o vmscan.o shmem.o \
- prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
-- page_isolation.o mm_init.o mmu_context.o percpu.o \
-+ mm_init.o mmu_context.o percpu.o \
- compaction.o $(mmu-y)
-+
- obj-y += init-mm.o
-
- ifdef CONFIG_NO_BOOTMEM
-@@ -50,3 +51,4 @@ obj-$(CONFIG_HWPOISON_INJECT) += hwpoiso
- obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o
- obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o
- obj-$(CONFIG_CLEANCACHE) += cleancache.o
-+obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -51,7 +51,6 @@
- #include <linux/page_cgroup.h>
- #include <linux/debugobjects.h>
- #include <linux/kmemleak.h>
--#include <linux/memory.h>
- #include <linux/compaction.h>
- #include <trace/events/kmem.h>
- #include <linux/ftrace_event.h>
-@@ -219,7 +218,7 @@ EXPORT_SYMBOL(nr_online_nodes);
-
- int page_group_by_mobility_disabled __read_mostly;
-
--static void set_pageblock_migratetype(struct page *page, int migratetype)
-+void set_pageblock_migratetype(struct page *page, int migratetype)
- {
-
- if (unlikely(page_group_by_mobility_disabled))
-@@ -954,7 +953,7 @@ static int move_freepages(struct zone *z
- return pages_moved;
- }
-
--static int move_freepages_block(struct zone *zone, struct page *page,
-+int move_freepages_block(struct zone *zone, struct page *page,
- int migratetype)
- {
- unsigned long start_pfn, end_pfn;
-@@ -5481,8 +5480,7 @@ void set_pageblock_flags_group(struct pa
- * MIGRATE_MOVABLE block might include unmovable pages. It means you can't
- * expect this function should be exact.
- */
--static bool
--__has_unmovable_pages(struct zone *zone, struct page *page, int count)
-+bool has_unmovable_pages(struct zone *zone, struct page *page, int count)
- {
- unsigned long pfn, iter, found;
- int mt;
-@@ -5552,77 +5550,7 @@ bool is_pageblock_removable_nolock(struc
- zone->zone_start_pfn + zone->spanned_pages <= pfn)
- return false;
-
-- return !__has_unmovable_pages(zone, page, 0);
--}
--
--int set_migratetype_isolate(struct page *page)
--{
-- struct zone *zone;
-- unsigned long flags, pfn;
-- struct memory_isolate_notify arg;
-- int notifier_ret;
-- int ret = -EBUSY;
--
-- zone = page_zone(page);
--
-- spin_lock_irqsave(&zone->lock, flags);
--
-- pfn = page_to_pfn(page);
-- arg.start_pfn = pfn;
-- arg.nr_pages = pageblock_nr_pages;
-- arg.pages_found = 0;
--
-- /*
-- * It may be possible to isolate a pageblock even if the
-- * migratetype is not MIGRATE_MOVABLE. The memory isolation
-- * notifier chain is used by balloon drivers to return the
-- * number of pages in a range that are held by the balloon
-- * driver to shrink memory. If all the pages are accounted for
-- * by balloons, are free, or on the LRU, isolation can continue.
-- * Later, for example, when memory hotplug notifier runs, these
-- * pages reported as "can be isolated" should be isolated(freed)
-- * by the balloon driver through the memory notifier chain.
-- */
-- notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg);
-- notifier_ret = notifier_to_errno(notifier_ret);
-- if (notifier_ret)
-- goto out;
-- /*
-- * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself.
-- * We just check MOVABLE pages.
-- */
-- if (!__has_unmovable_pages(zone, page, arg.pages_found))
-- ret = 0;
-- /*
-- * Unmovable means "not-on-lru" pages. If Unmovable pages are
-- * larger than removable-by-driver pages reported by notifier,
-- * we'll fail.
-- */
--
--out:
-- if (!ret) {
-- set_pageblock_migratetype(page, MIGRATE_ISOLATE);
-- move_freepages_block(zone, page, MIGRATE_ISOLATE);
-- }
--
-- spin_unlock_irqrestore(&zone->lock, flags);
-- if (!ret)
-- drain_all_pages();
-- return ret;
--}
--
--void unset_migratetype_isolate(struct page *page, unsigned migratetype)
--{
-- struct zone *zone;
-- unsigned long flags;
-- zone = page_zone(page);
-- spin_lock_irqsave(&zone->lock, flags);
-- if (get_pageblock_migratetype(page) != MIGRATE_ISOLATE)
-- goto out;
-- set_pageblock_migratetype(page, migratetype);
-- move_freepages_block(zone, page, migratetype);
--out:
-- spin_unlock_irqrestore(&zone->lock, flags);
-+ return !has_unmovable_pages(zone, page, 0);
- }
-
- #ifdef CONFIG_CMA
---- a/mm/page_isolation.c
-+++ b/mm/page_isolation.c
-@@ -5,8 +5,79 @@
- #include <linux/mm.h>
- #include <linux/page-isolation.h>
- #include <linux/pageblock-flags.h>
-+#include <linux/memory.h>
- #include "internal.h"
-
-+int set_migratetype_isolate(struct page *page)
-+{
-+ struct zone *zone;
-+ unsigned long flags, pfn;
-+ struct memory_isolate_notify arg;
-+ int notifier_ret;
-+ int ret = -EBUSY;
-+
-+ zone = page_zone(page);
-+
-+ spin_lock_irqsave(&zone->lock, flags);
-+
-+ pfn = page_to_pfn(page);
-+ arg.start_pfn = pfn;
-+ arg.nr_pages = pageblock_nr_pages;
-+ arg.pages_found = 0;
-+
-+ /*
-+ * It may be possible to isolate a pageblock even if the
-+ * migratetype is not MIGRATE_MOVABLE. The memory isolation
-+ * notifier chain is used by balloon drivers to return the
-+ * number of pages in a range that are held by the balloon
-+ * driver to shrink memory. If all the pages are accounted for
-+ * by balloons, are free, or on the LRU, isolation can continue.
-+ * Later, for example, when memory hotplug notifier runs, these
-+ * pages reported as "can be isolated" should be isolated(freed)
-+ * by the balloon driver through the memory notifier chain.
-+ */
-+ notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg);
-+ notifier_ret = notifier_to_errno(notifier_ret);
-+ if (notifier_ret)
-+ goto out;
-+ /*
-+ * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself.
-+ * We just check MOVABLE pages.
-+ */
-+ if (!has_unmovable_pages(zone, page, arg.pages_found))
-+ ret = 0;
-+
-+ /*
-+ * immobile means "not-on-lru" paes. If immobile is larger than
-+ * removable-by-driver pages reported by notifier, we'll fail.
-+ */
-+
-+out:
-+ if (!ret) {
-+ set_pageblock_migratetype(page, MIGRATE_ISOLATE);
-+ move_freepages_block(zone, page, MIGRATE_ISOLATE);
-+ }
-+
-+ spin_unlock_irqrestore(&zone->lock, flags);
-+ if (!ret)
-+ drain_all_pages();
-+ return ret;
-+}
-+
-+void unset_migratetype_isolate(struct page *page, unsigned migratetype)
-+{
-+ struct zone *zone;
-+ unsigned long flags;
-+ zone = page_zone(page);
-+ spin_lock_irqsave(&zone->lock, flags);
-+ if (get_pageblock_migratetype(page) != MIGRATE_ISOLATE)
-+ goto out;
-+ set_pageblock_migratetype(page, migratetype);
-+ move_freepages_block(zone, page, migratetype);
-+out:
-+ spin_unlock_irqrestore(&zone->lock, flags);
-+}
-+
- static inline struct page *
- __first_valid_page(unsigned long pfn, unsigned long nr_pages)
- {
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:06 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:25 +0900
-Subject: [PATCH v2 08/58] mm: mmzone: MIGRATE_CMA migration type added
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-9-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Michal Nazarewicz <mina86@mina86.com>
-
-The MIGRATE_CMA migration type has two main characteristics:
-(i) only movable pages can be allocated from MIGRATE_CMA
-pageblocks and (ii) page allocator will never change migration
-type of MIGRATE_CMA pageblocks.
-
-This guarantees (to some degree) that page in a MIGRATE_CMA page
-block can always be migrated somewhere else (unless there's no
-memory left in the system).
-
-It is designed to be used for allocating big chunks (eg. 10MiB)
-of physically contiguous memory. Once driver requests
-contiguous memory, pages from MIGRATE_CMA pageblocks may be
-migrated away to create a contiguous block.
-
-To minimise number of migrations, MIGRATE_CMA migration type
-is the last type tried when page allocator falls back to other
-migration types when requested.
-
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
-Acked-by: Mel Gorman <mel@csn.ul.ie>
-Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
-Tested-by: Rob Clark <rob.clark@linaro.org>
-Tested-by: Ohad Ben-Cohen <ohad@wizery.com>
-Tested-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-Tested-by: Robert Nelson <robertcnelson@gmail.com>
-Tested-by: Barry Song <Baohua.Song@csr.com>
-(cherry picked from commit 47118af076f64844b4f423bc2f545b2da9dab50d)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- include/linux/gfp.h | 3 +
- include/linux/mmzone.h | 38 +++++++++++++++++++-----
- mm/Kconfig | 2 -
- mm/compaction.c | 11 +++++--
- mm/page_alloc.c | 76 ++++++++++++++++++++++++++++++++++++++-----------
- mm/vmstat.c | 3 +
- 6 files changed, 106 insertions(+), 27 deletions(-)
-
---- a/include/linux/gfp.h
-+++ b/include/linux/gfp.h
-@@ -397,6 +397,9 @@ static inline bool pm_suspended_storage(
- extern int alloc_contig_range(unsigned long start, unsigned long end);
- extern void free_contig_range(unsigned long pfn, unsigned nr_pages);
-
-+/* CMA stuff */
-+extern void init_cma_reserved_pageblock(struct page *page);
-+
- #endif
-
- #endif /* __LINUX_GFP_H */
---- a/include/linux/mmzone.h
-+++ b/include/linux/mmzone.h
-@@ -35,13 +35,37 @@
- */
- #define PAGE_ALLOC_COSTLY_ORDER 3
-
--#define MIGRATE_UNMOVABLE 0
--#define MIGRATE_RECLAIMABLE 1
--#define MIGRATE_MOVABLE 2
--#define MIGRATE_PCPTYPES 3 /* the number of types on the pcp lists */
--#define MIGRATE_RESERVE 3
--#define MIGRATE_ISOLATE 4 /* can't allocate from here */
--#define MIGRATE_TYPES 5
-+enum {
-+ MIGRATE_UNMOVABLE,
-+ MIGRATE_RECLAIMABLE,
-+ MIGRATE_MOVABLE,
-+ MIGRATE_PCPTYPES, /* the number of types on the pcp lists */
-+ MIGRATE_RESERVE = MIGRATE_PCPTYPES,
-+#ifdef CONFIG_CMA
-+ /*
-+ * MIGRATE_CMA migration type is designed to mimic the way
-+ * ZONE_MOVABLE works. Only movable pages can be allocated
-+ * from MIGRATE_CMA pageblocks and page allocator never
-+ * implicitly change migration type of MIGRATE_CMA pageblock.
-+ *
-+ * The way to use it is to change migratetype of a range of
-+ * pageblocks to MIGRATE_CMA which can be done by
-+ * __free_pageblock_cma() function. What is important though
-+ * is that a range of pageblocks must be aligned to
-+ * MAX_ORDER_NR_PAGES should biggest page be bigger then
-+ * a single pageblock.
-+ */
-+ MIGRATE_CMA,
-+#endif
-+ MIGRATE_ISOLATE, /* can't allocate from here */
-+ MIGRATE_TYPES
-+};
-+
-+#ifdef CONFIG_CMA
-+# define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
-+#else
-+# define is_migrate_cma(migratetype) false
-+#endif
-
- #define for_each_migratetype_order(order, type) \
- for (order = 0; order < MAX_ORDER; order++) \
---- a/mm/Kconfig
-+++ b/mm/Kconfig
-@@ -198,7 +198,7 @@ config COMPACTION
- config MIGRATION
- bool "Page migration"
- def_bool y
-- depends on NUMA || ARCH_ENABLE_MEMORY_HOTREMOVE || COMPACTION
-+ depends on NUMA || ARCH_ENABLE_MEMORY_HOTREMOVE || COMPACTION || CMA
- help
- Allows the migration of the physical location of pages of processes
- while the virtual addresses are not changed. This is useful in
---- a/mm/compaction.c
-+++ b/mm/compaction.c
-@@ -45,6 +45,11 @@ static void map_pages(struct list_head *
- }
- }
-
-+static inline bool migrate_async_suitable(int migratetype)
-+{
-+ return is_migrate_cma(migratetype) || migratetype == MIGRATE_MOVABLE;
-+}
-+
- /*
- * Isolate free pages onto a private freelist. Caller must hold zone->lock.
- * If @strict is true, will abort returning 0 on any invalid PFNs or non-free
-@@ -299,7 +304,7 @@ isolate_migratepages_range(struct zone *
- */
- pageblock_nr = low_pfn >> pageblock_order;
- if (!cc->sync && last_pageblock_nr != pageblock_nr &&
-- get_pageblock_migratetype(page) != MIGRATE_MOVABLE) {
-+ !migrate_async_suitable(get_pageblock_migratetype(page))) {
- low_pfn += pageblock_nr_pages;
- low_pfn = ALIGN(low_pfn, pageblock_nr_pages) - 1;
- last_pageblock_nr = pageblock_nr;
-@@ -367,8 +372,8 @@ static bool suitable_migration_target(st
- if (PageBuddy(page) && page_order(page) >= pageblock_order)
- return true;
-
-- /* If the block is MIGRATE_MOVABLE, allow migration */
-- if (migratetype == MIGRATE_MOVABLE)
-+ /* If the block is MIGRATE_MOVABLE or MIGRATE_CMA, allow migration */
-+ if (migrate_async_suitable(migratetype))
- return true;
-
- /* Otherwise skip the block */
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -750,6 +750,24 @@ void __meminit __free_pages_bootmem(stru
- __free_pages(page, order);
- }
-
-+#ifdef CONFIG_CMA
-+/* Free whole pageblock and set it's migration type to MIGRATE_CMA. */
-+void __init init_cma_reserved_pageblock(struct page *page)
-+{
-+ unsigned i = pageblock_nr_pages;
-+ struct page *p = page;
-+
-+ do {
-+ __ClearPageReserved(p);
-+ set_page_count(p, 0);
-+ } while (++p, --i);
-+
-+ set_page_refcounted(page);
-+ set_pageblock_migratetype(page, MIGRATE_CMA);
-+ __free_pages(page, pageblock_order);
-+ totalram_pages += pageblock_nr_pages;
-+}
-+#endif
-
- /*
- * The order of subdivision here is critical for the IO subsystem.
-@@ -875,10 +893,15 @@ struct page *__rmqueue_smallest(struct z
- * This array describes the order lists are fallen back to when
- * the free lists for the desirable migrate type are depleted
- */
--static int fallbacks[MIGRATE_TYPES][3] = {
-- [MIGRATE_UNMOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
-- [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
-- [MIGRATE_MOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },
-+static int fallbacks[MIGRATE_TYPES][4] = {
-+ [MIGRATE_UNMOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
-+ [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
-+#ifdef CONFIG_CMA
-+ [MIGRATE_MOVABLE] = { MIGRATE_CMA, MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },
-+ [MIGRATE_CMA] = { MIGRATE_RESERVE }, /* Never used */
-+#else
-+ [MIGRATE_MOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },
-+#endif
- [MIGRATE_RESERVE] = { MIGRATE_RESERVE }, /* Never used */
- [MIGRATE_ISOLATE] = { MIGRATE_RESERVE }, /* Never used */
- };
-@@ -995,11 +1018,18 @@ __rmqueue_fallback(struct zone *zone, in
- * pages to the preferred allocation list. If falling
- * back for a reclaimable kernel allocation, be more
- * aggressive about taking ownership of free pages
-+ *
-+ * On the other hand, never change migration
-+ * type of MIGRATE_CMA pageblocks nor move CMA
-+ * pages on different free lists. We don't
-+ * want unmovable pages to be allocated from
-+ * MIGRATE_CMA areas.
- */
-- if (unlikely(current_order >= (pageblock_order >> 1)) ||
-- start_migratetype == MIGRATE_RECLAIMABLE ||
-- page_group_by_mobility_disabled) {
-- unsigned long pages;
-+ if (!is_migrate_cma(migratetype) &&
-+ (unlikely(current_order >= pageblock_order / 2) ||
-+ start_migratetype == MIGRATE_RECLAIMABLE ||
-+ page_group_by_mobility_disabled)) {
-+ int pages;
- pages = move_freepages_block(zone, page,
- start_migratetype);
-
-@@ -1017,11 +1047,14 @@ __rmqueue_fallback(struct zone *zone, in
- rmv_page_order(page);
-
- /* Take ownership for orders >= pageblock_order */
-- if (current_order >= pageblock_order)
-+ if (current_order >= pageblock_order &&
-+ !is_migrate_cma(migratetype))
- change_pageblock_range(page, current_order,
- start_migratetype);
-
-- expand(zone, page, order, current_order, area, migratetype);
-+ expand(zone, page, order, current_order, area,
-+ is_migrate_cma(migratetype)
-+ ? migratetype : start_migratetype);
-
- trace_mm_page_alloc_extfrag(page, order, current_order,
- start_migratetype, migratetype);
-@@ -1072,7 +1105,7 @@ static int rmqueue_bulk(struct zone *zon
- unsigned long count, struct list_head *list,
- int migratetype, int cold)
- {
-- int i;
-+ int mt = migratetype, i;
-
- spin_lock(&zone->lock);
- for (i = 0; i < count; ++i) {
-@@ -1093,7 +1126,12 @@ static int rmqueue_bulk(struct zone *zon
- list_add(&page->lru, list);
- else
- list_add_tail(&page->lru, list);
-- set_page_private(page, migratetype);
-+ if (IS_ENABLED(CONFIG_CMA)) {
-+ mt = get_pageblock_migratetype(page);
-+ if (!is_migrate_cma(mt) && mt != MIGRATE_ISOLATE)
-+ mt = migratetype;
-+ }
-+ set_page_private(page, mt);
- list = &page->lru;
- }
- __mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order));
-@@ -1373,8 +1411,12 @@ int split_free_page(struct page *page)
-
- if (order >= pageblock_order - 1) {
- struct page *endpage = page + (1 << order) - 1;
-- for (; page < endpage; page += pageblock_nr_pages)
-- set_pageblock_migratetype(page, MIGRATE_MOVABLE);
-+ for (; page < endpage; page += pageblock_nr_pages) {
-+ int mt = get_pageblock_migratetype(page);
-+ if (mt != MIGRATE_ISOLATE && !is_migrate_cma(mt))
-+ set_pageblock_migratetype(page,
-+ MIGRATE_MOVABLE);
-+ }
- }
-
- return 1 << order;
-@@ -5417,14 +5459,16 @@ static int
- __count_immobile_pages(struct zone *zone, struct page *page, int count)
- {
- unsigned long pfn, iter, found;
-+ int mt;
-+
- /*
- * For avoiding noise data, lru_add_drain_all() should be called
- * If ZONE_MOVABLE, the zone never contains immobile pages
- */
- if (zone_idx(zone) == ZONE_MOVABLE)
- return true;
--
-- if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE)
-+ mt = get_pageblock_migratetype(page);
-+ if (mt == MIGRATE_MOVABLE || is_migrate_cma(mt))
- return true;
-
- pfn = page_to_pfn(page);
---- a/mm/vmstat.c
-+++ b/mm/vmstat.c
-@@ -613,6 +613,9 @@ static char * const migratetype_names[MI
- "Reclaimable",
- "Movable",
- "Reserve",
-+#ifdef CONFIG_CMA
-+ "CMA",
-+#endif
- "Isolate",
- };
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:02 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:24 +0900
-Subject: [PATCH v2 07/58] mm: page_alloc: change fallbacks array handling
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-8-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Michal Nazarewicz <mina86@mina86.com>
-
-This commit adds a row for MIGRATE_ISOLATE type to the fallbacks array
-which was missing from it. It also, changes the array traversal logic
-a little making MIGRATE_RESERVE an end marker. The letter change,
-removes the implicit MIGRATE_UNMOVABLE from the end of each row which
-was read by __rmqueue_fallback() function.
-
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Mel Gorman <mel@csn.ul.ie>
-Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
-Tested-by: Rob Clark <rob.clark@linaro.org>
-Tested-by: Ohad Ben-Cohen <ohad@wizery.com>
-Tested-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-Tested-by: Robert Nelson <robertcnelson@gmail.com>
-Tested-by: Barry Song <Baohua.Song@csr.com>
-(cherry picked from commit 6d4a49160de2c684fb59fa627bce80e200224331)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- mm/page_alloc.c | 9 +++++----
- 1 files changed, 5 insertions(+), 4 deletions(-)
-
-diff --git a/mm/page_alloc.c b/mm/page_alloc.c
-index 2c38a30..d6b580c 100644
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -875,11 +875,12 @@ struct page *__rmqueue_smallest(struct zone *zone, unsigned int order,
- * This array describes the order lists are fallen back to when
- * the free lists for the desirable migrate type are depleted
- */
--static int fallbacks[MIGRATE_TYPES][MIGRATE_TYPES-1] = {
-+static int fallbacks[MIGRATE_TYPES][3] = {
- [MIGRATE_UNMOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
- [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
- [MIGRATE_MOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },
-- [MIGRATE_RESERVE] = { MIGRATE_RESERVE, MIGRATE_RESERVE, MIGRATE_RESERVE }, /* Never used */
-+ [MIGRATE_RESERVE] = { MIGRATE_RESERVE }, /* Never used */
-+ [MIGRATE_ISOLATE] = { MIGRATE_RESERVE }, /* Never used */
- };
-
- /*
-@@ -974,12 +975,12 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype)
- /* Find the largest possible block of pages in the other list */
- for (current_order = MAX_ORDER-1; current_order >= order;
- --current_order) {
-- for (i = 0; i < MIGRATE_TYPES - 1; i++) {
-+ for (i = 0;; i++) {
- migratetype = fallbacks[start_migratetype][i];
-
- /* MIGRATE_RESERVE handled later if necessary */
- if (migratetype == MIGRATE_RESERVE)
-- continue;
-+ break;
-
- area = &(zone->free_area[current_order]);
- if (list_empty(&area->free_list[migratetype]))
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:00 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:23 +0900
-Subject: [PATCH v2 06/58] mm: page_alloc: introduce alloc_contig_range()
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-7-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Michal Nazarewicz <mina86@mina86.com>
-
-This commit adds the alloc_contig_range() function which tries
-to allocate given range of pages. It tries to migrate all
-already allocated pages that fall in the range thus freeing them.
-Once all pages in the range are freed they are removed from the
-buddy system thus allocated for the caller to use.
-
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Mel Gorman <mel@csn.ul.ie>
-Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
-Tested-by: Rob Clark <rob.clark@linaro.org>
-Tested-by: Ohad Ben-Cohen <ohad@wizery.com>
-Tested-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-Tested-by: Robert Nelson <robertcnelson@gmail.com>
-Tested-by: Barry Song <Baohua.Song@csr.com>
-(cherry picked from commit 041d3a8cdc18dc375a128d90bbb753949a81b1fb)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- include/linux/gfp.h | 8 ++
- mm/page_alloc.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 196 insertions(+)
-
---- a/include/linux/gfp.h
-+++ b/include/linux/gfp.h
-@@ -391,4 +391,12 @@ static inline bool pm_suspended_storage(
- }
- #endif /* CONFIG_PM_SLEEP */
-
-+#ifdef CONFIG_CMA
-+
-+/* The below functions must be run on a range from a single zone. */
-+extern int alloc_contig_range(unsigned long start, unsigned long end);
-+extern void free_contig_range(unsigned long pfn, unsigned nr_pages);
-+
-+#endif
-+
- #endif /* __LINUX_GFP_H */
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -57,6 +57,7 @@
- #include <linux/ftrace_event.h>
- #include <linux/memcontrol.h>
- #include <linux/prefetch.h>
-+#include <linux/migrate.h>
- #include <linux/page-debug-flags.h>
-
- #include <asm/tlbflush.h>
-@@ -5553,6 +5554,193 @@ out:
- spin_unlock_irqrestore(&zone->lock, flags);
- }
-
-+#ifdef CONFIG_CMA
-+
-+static unsigned long pfn_max_align_down(unsigned long pfn)
-+{
-+ return pfn & ~(max_t(unsigned long, MAX_ORDER_NR_PAGES,
-+ pageblock_nr_pages) - 1);
-+}
-+
-+static unsigned long pfn_max_align_up(unsigned long pfn)
-+{
-+ return ALIGN(pfn, max_t(unsigned long, MAX_ORDER_NR_PAGES,
-+ pageblock_nr_pages));
-+}
-+
-+static struct page *
-+__alloc_contig_migrate_alloc(struct page *page, unsigned long private,
-+ int **resultp)
-+{
-+ return alloc_page(GFP_HIGHUSER_MOVABLE);
-+}
-+
-+/* [start, end) must belong to a single zone. */
-+static int __alloc_contig_migrate_range(unsigned long start, unsigned long end)
-+{
-+ /* This function is based on compact_zone() from compaction.c. */
-+
-+ unsigned long pfn = start;
-+ unsigned int tries = 0;
-+ int ret = 0;
-+
-+ struct compact_control cc = {
-+ .nr_migratepages = 0,
-+ .order = -1,
-+ .zone = page_zone(pfn_to_page(start)),
-+ .sync = true,
-+ };
-+ INIT_LIST_HEAD(&cc.migratepages);
-+
-+ migrate_prep_local();
-+
-+ while (pfn < end || !list_empty(&cc.migratepages)) {
-+ if (fatal_signal_pending(current)) {
-+ ret = -EINTR;
-+ break;
-+ }
-+
-+ if (list_empty(&cc.migratepages)) {
-+ cc.nr_migratepages = 0;
-+ pfn = isolate_migratepages_range(cc.zone, &cc,
-+ pfn, end);
-+ if (!pfn) {
-+ ret = -EINTR;
-+ break;
-+ }
-+ tries = 0;
-+ } else if (++tries == 5) {
-+ ret = ret < 0 ? ret : -EBUSY;
-+ break;
-+ }
-+
-+ ret = migrate_pages(&cc.migratepages,
-+ __alloc_contig_migrate_alloc,
-+ 0, false, true);
-+ }
-+
-+ putback_lru_pages(&cc.migratepages);
-+ return ret > 0 ? 0 : ret;
-+}
-+
-+/**
-+ * alloc_contig_range() -- tries to allocate given range of pages
-+ * @start: start PFN to allocate
-+ * @end: one-past-the-last PFN to allocate
-+ *
-+ * The PFN range does not have to be pageblock or MAX_ORDER_NR_PAGES
-+ * aligned, however it's the caller's responsibility to guarantee that
-+ * we are the only thread that changes migrate type of pageblocks the
-+ * pages fall in.
-+ *
-+ * The PFN range must belong to a single zone.
-+ *
-+ * Returns zero on success or negative error code. On success all
-+ * pages which PFN is in [start, end) are allocated for the caller and
-+ * need to be freed with free_contig_range().
-+ */
-+int alloc_contig_range(unsigned long start, unsigned long end)
-+{
-+ struct zone *zone = page_zone(pfn_to_page(start));
-+ unsigned long outer_start, outer_end;
-+ int ret = 0, order;
-+
-+ /*
-+ * What we do here is we mark all pageblocks in range as
-+ * MIGRATE_ISOLATE. Because pageblock and max order pages may
-+ * have different sizes, and due to the way page allocator
-+ * work, we align the range to biggest of the two pages so
-+ * that page allocator won't try to merge buddies from
-+ * different pageblocks and change MIGRATE_ISOLATE to some
-+ * other migration type.
-+ *
-+ * Once the pageblocks are marked as MIGRATE_ISOLATE, we
-+ * migrate the pages from an unaligned range (ie. pages that
-+ * we are interested in). This will put all the pages in
-+ * range back to page allocator as MIGRATE_ISOLATE.
-+ *
-+ * When this is done, we take the pages in range from page
-+ * allocator removing them from the buddy system. This way
-+ * page allocator will never consider using them.
-+ *
-+ * This lets us mark the pageblocks back as
-+ * MIGRATE_CMA/MIGRATE_MOVABLE so that free pages in the
-+ * aligned range but not in the unaligned, original range are
-+ * put back to page allocator so that buddy can use them.
-+ */
-+
-+ ret = start_isolate_page_range(pfn_max_align_down(start),
-+ pfn_max_align_up(end));
-+ if (ret)
-+ goto done;
-+
-+ ret = __alloc_contig_migrate_range(start, end);
-+ if (ret)
-+ goto done;
-+
-+ /*
-+ * Pages from [start, end) are within a MAX_ORDER_NR_PAGES
-+ * aligned blocks that are marked as MIGRATE_ISOLATE. What's
-+ * more, all pages in [start, end) are free in page allocator.
-+ * What we are going to do is to allocate all pages from
-+ * [start, end) (that is remove them from page allocator).
-+ *
-+ * The only problem is that pages at the beginning and at the
-+ * end of interesting range may be not aligned with pages that
-+ * page allocator holds, ie. they can be part of higher order
-+ * pages. Because of this, we reserve the bigger range and
-+ * once this is done free the pages we are not interested in.
-+ *
-+ * We don't have to hold zone->lock here because the pages are
-+ * isolated thus they won't get removed from buddy.
-+ */
-+
-+ lru_add_drain_all();
-+ drain_all_pages();
-+
-+ order = 0;
-+ outer_start = start;
-+ while (!PageBuddy(pfn_to_page(outer_start))) {
-+ if (++order >= MAX_ORDER) {
-+ ret = -EBUSY;
-+ goto done;
-+ }
-+ outer_start &= ~0UL << order;
-+ }
-+
-+ /* Make sure the range is really isolated. */
-+ if (test_pages_isolated(outer_start, end)) {
-+ pr_warn("alloc_contig_range test_pages_isolated(%lx, %lx) failed\n",
-+ outer_start, end);
-+ ret = -EBUSY;
-+ goto done;
-+ }
-+
-+ outer_end = isolate_freepages_range(outer_start, end);
-+ if (!outer_end) {
-+ ret = -EBUSY;
-+ goto done;
-+ }
-+
-+ /* Free head and tail (if any) */
-+ if (start != outer_start)
-+ free_contig_range(outer_start, start - outer_start);
-+ if (end != outer_end)
-+ free_contig_range(end, outer_end - end);
-+
-+done:
-+ undo_isolate_page_range(pfn_max_align_down(start),
-+ pfn_max_align_up(end));
-+ return ret;
-+}
-+
-+void free_contig_range(unsigned long pfn, unsigned nr_pages)
-+{
-+ for (; nr_pages--; ++pfn)
-+ __free_page(pfn_to_page(pfn));
-+}
-+#endif
-+
- #ifdef CONFIG_MEMORY_HOTREMOVE
- /*
- * All pages in the range must be isolated before calling this.
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:51:50 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:18 +0900
-Subject: [PATCH v2 01/58] mm: page_alloc: remove trailing whitespace
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-2-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Michal Nazarewicz <mina86@mina86.com>
-
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Mel Gorman <mel@csn.ul.ie>
-(cherry picked from commit 5f63b720b62925ef3c6a85473dcd547b0fd90616)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- mm/page_alloc.c | 14 +++++++-------
- 1 file changed, 7 insertions(+), 7 deletions(-)
-
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -513,10 +513,10 @@ static inline int page_is_buddy(struct p
- * free pages of length of (1 << order) and marked with _mapcount -2. Page's
- * order is recorded in page_private(page) field.
- * So when we are allocating or freeing one, we can derive the state of the
-- * other. That is, if we allocate a small block, and both were
-- * free, the remainder of the region must be split into blocks.
-+ * other. That is, if we allocate a small block, and both were
-+ * free, the remainder of the region must be split into blocks.
- * If a block is freed, and its buddy is also free, then this
-- * triggers coalescing into a block of larger size.
-+ * triggers coalescing into a block of larger size.
- *
- * -- wli
- */
-@@ -1061,17 +1061,17 @@ retry_reserve:
- return page;
- }
-
--/*
-+/*
- * Obtain a specified number of elements from the buddy allocator, all under
- * a single hold of the lock, for efficiency. Add them to the supplied list.
- * Returns the number of new pages which were placed at *list.
- */
--static int rmqueue_bulk(struct zone *zone, unsigned int order,
-+static int rmqueue_bulk(struct zone *zone, unsigned int order,
- unsigned long count, struct list_head *list,
- int migratetype, int cold)
- {
- int i;
--
-+
- spin_lock(&zone->lock);
- for (i = 0; i < count; ++i) {
- struct page *page = __rmqueue(zone, order, migratetype);
-@@ -4304,7 +4304,7 @@ static void __paginginit free_area_init_
- init_waitqueue_head(&pgdat->kswapd_wait);
- pgdat->kswapd_max_order = 0;
- pgdat_page_cgroup_init(pgdat);
--
-+
- for (j = 0; j < MAX_NR_ZONES; j++) {
- struct zone *zone = pgdat->node_zones + j;
- unsigned long size, realsize, memmap_pages;
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:08 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:26 +0900
-Subject: [PATCH v2 09/58] mm: page_isolation: MIGRATE_CMA isolation functions added
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-10-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Michal Nazarewicz <mina86@mina86.com>
-
-This commit changes various functions that change pages and
-pageblocks migrate type between MIGRATE_ISOLATE and
-MIGRATE_MOVABLE in such a way as to allow to work with
-MIGRATE_CMA migrate type.
-
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
-Tested-by: Rob Clark <rob.clark@linaro.org>
-Tested-by: Ohad Ben-Cohen <ohad@wizery.com>
-Tested-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-Tested-by: Robert Nelson <robertcnelson@gmail.com>
-Tested-by: Barry Song <Baohua.Song@csr.com>
-(cherry picked from commit 0815f3d81d76dfbf2abcfd93a85ff0a6008fe4c0)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- include/linux/gfp.h | 3 ++-
- include/linux/page-isolation.h | 18 +++++++++---------
- mm/memory-failure.c | 2 +-
- mm/memory_hotplug.c | 6 +++---
- mm/page_alloc.c | 17 +++++++++++------
- mm/page_isolation.c | 15 ++++++++-------
- 6 files changed, 34 insertions(+), 27 deletions(-)
-
---- a/include/linux/gfp.h
-+++ b/include/linux/gfp.h
-@@ -394,7 +394,8 @@ static inline bool pm_suspended_storage(
- #ifdef CONFIG_CMA
-
- /* The below functions must be run on a range from a single zone. */
--extern int alloc_contig_range(unsigned long start, unsigned long end);
-+extern int alloc_contig_range(unsigned long start, unsigned long end,
-+ unsigned migratetype);
- extern void free_contig_range(unsigned long pfn, unsigned nr_pages);
-
- /* CMA stuff */
---- a/include/linux/page-isolation.h
-+++ b/include/linux/page-isolation.h
-@@ -3,7 +3,7 @@
-
- /*
- * Changes migrate type in [start_pfn, end_pfn) to be MIGRATE_ISOLATE.
-- * If specified range includes migrate types other than MOVABLE,
-+ * If specified range includes migrate types other than MOVABLE or CMA,
- * this will fail with -EBUSY.
- *
- * For isolating all pages in the range finally, the caller have to
-@@ -11,27 +11,27 @@
- * test it.
- */
- extern int
--start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn);
-+start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
-+ unsigned migratetype);
-
- /*
- * Changes MIGRATE_ISOLATE to MIGRATE_MOVABLE.
- * target range is [start_pfn, end_pfn)
- */
- extern int
--undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn);
-+undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
-+ unsigned migratetype);
-
- /*
-- * test all pages in [start_pfn, end_pfn)are isolated or not.
-+ * Test all pages in [start_pfn, end_pfn) are isolated or not.
- */
--extern int
--test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn);
-+int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn);
-
- /*
-- * Internal funcs.Changes pageblock's migrate type.
-- * Please use make_pagetype_isolated()/make_pagetype_movable().
-+ * Internal functions. Changes pageblock's migrate type.
- */
- extern int set_migratetype_isolate(struct page *page);
--extern void unset_migratetype_isolate(struct page *page);
-+extern void unset_migratetype_isolate(struct page *page, unsigned migratetype);
-
-
- #endif
---- a/mm/memory-failure.c
-+++ b/mm/memory-failure.c
-@@ -1406,7 +1406,7 @@ static int get_any_page(struct page *p,
- /* Not a free page */
- ret = 1;
- }
-- unset_migratetype_isolate(p);
-+ unset_migratetype_isolate(p, MIGRATE_MOVABLE);
- unlock_memory_hotplug();
- return ret;
- }
---- a/mm/memory_hotplug.c
-+++ b/mm/memory_hotplug.c
-@@ -895,7 +895,7 @@ static int __ref offline_pages(unsigned
- nr_pages = end_pfn - start_pfn;
-
- /* set above range as isolated */
-- ret = start_isolate_page_range(start_pfn, end_pfn);
-+ ret = start_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
- if (ret)
- goto out;
-
-@@ -960,7 +960,7 @@ repeat:
- We cannot do rollback at this point. */
- offline_isolated_pages(start_pfn, end_pfn);
- /* reset pagetype flags and makes migrate type to be MOVABLE */
-- undo_isolate_page_range(start_pfn, end_pfn);
-+ undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
- /* removal success */
- zone->present_pages -= offlined_pages;
- zone->zone_pgdat->node_present_pages -= offlined_pages;
-@@ -985,7 +985,7 @@ failed_removal:
- start_pfn, end_pfn);
- memory_notify(MEM_CANCEL_OFFLINE, &arg);
- /* pushback to free area */
-- undo_isolate_page_range(start_pfn, end_pfn);
-+ undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
-
- out:
- unlock_memory_hotplug();
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -5585,7 +5585,7 @@ out:
- return ret;
- }
-
--void unset_migratetype_isolate(struct page *page)
-+void unset_migratetype_isolate(struct page *page, unsigned migratetype)
- {
- struct zone *zone;
- unsigned long flags;
-@@ -5593,8 +5593,8 @@ void unset_migratetype_isolate(struct pa
- spin_lock_irqsave(&zone->lock, flags);
- if (get_pageblock_migratetype(page) != MIGRATE_ISOLATE)
- goto out;
-- set_pageblock_migratetype(page, MIGRATE_MOVABLE);
-- move_freepages_block(zone, page, MIGRATE_MOVABLE);
-+ set_pageblock_migratetype(page, migratetype);
-+ move_freepages_block(zone, page, migratetype);
- out:
- spin_unlock_irqrestore(&zone->lock, flags);
- }
-@@ -5672,6 +5672,10 @@ static int __alloc_contig_migrate_range(
- * alloc_contig_range() -- tries to allocate given range of pages
- * @start: start PFN to allocate
- * @end: one-past-the-last PFN to allocate
-+ * @migratetype: migratetype of the underlaying pageblocks (either
-+ * #MIGRATE_MOVABLE or #MIGRATE_CMA). All pageblocks
-+ * in range must have the same migratetype and it must
-+ * be either of the two.
- *
- * The PFN range does not have to be pageblock or MAX_ORDER_NR_PAGES
- * aligned, however it's the caller's responsibility to guarantee that
-@@ -5684,7 +5688,8 @@ static int __alloc_contig_migrate_range(
- * pages which PFN is in [start, end) are allocated for the caller and
- * need to be freed with free_contig_range().
- */
--int alloc_contig_range(unsigned long start, unsigned long end)
-+int alloc_contig_range(unsigned long start, unsigned long end,
-+ unsigned migratetype)
- {
- struct zone *zone = page_zone(pfn_to_page(start));
- unsigned long outer_start, outer_end;
-@@ -5715,7 +5720,7 @@ int alloc_contig_range(unsigned long sta
- */
-
- ret = start_isolate_page_range(pfn_max_align_down(start),
-- pfn_max_align_up(end));
-+ pfn_max_align_up(end), migratetype);
- if (ret)
- goto done;
-
-@@ -5775,7 +5780,7 @@ int alloc_contig_range(unsigned long sta
-
- done:
- undo_isolate_page_range(pfn_max_align_down(start),
-- pfn_max_align_up(end));
-+ pfn_max_align_up(end), migratetype);
- return ret;
- }
-
---- a/mm/page_isolation.c
-+++ b/mm/page_isolation.c
-@@ -24,6 +24,7 @@ __first_valid_page(unsigned long pfn, un
- * to be MIGRATE_ISOLATE.
- * @start_pfn: The lower PFN of the range to be isolated.
- * @end_pfn: The upper PFN of the range to be isolated.
-+ * @migratetype: migrate type to set in error recovery.
- *
- * Making page-allocation-type to be MIGRATE_ISOLATE means free pages in
- * the range will never be allocated. Any free pages and pages freed in the
-@@ -32,8 +33,8 @@ __first_valid_page(unsigned long pfn, un
- * start_pfn/end_pfn must be aligned to pageblock_order.
- * Returns 0 on success and -EBUSY if any part of range cannot be isolated.
- */
--int
--start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn)
-+int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
-+ unsigned migratetype)
- {
- unsigned long pfn;
- unsigned long undo_pfn;
-@@ -56,7 +57,7 @@ undo:
- for (pfn = start_pfn;
- pfn < undo_pfn;
- pfn += pageblock_nr_pages)
-- unset_migratetype_isolate(pfn_to_page(pfn));
-+ unset_migratetype_isolate(pfn_to_page(pfn), migratetype);
-
- return -EBUSY;
- }
-@@ -64,8 +65,8 @@ undo:
- /*
- * Make isolated pages available again.
- */
--int
--undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn)
-+int undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
-+ unsigned migratetype)
- {
- unsigned long pfn;
- struct page *page;
-@@ -77,7 +78,7 @@ undo_isolate_page_range(unsigned long st
- page = __first_valid_page(pfn, pageblock_nr_pages);
- if (!page || get_pageblock_migratetype(page) != MIGRATE_ISOLATE)
- continue;
-- unset_migratetype_isolate(page);
-+ unset_migratetype_isolate(page, migratetype);
- }
- return 0;
- }
-@@ -86,7 +87,7 @@ undo_isolate_page_range(unsigned long st
- * all pages in [start_pfn...end_pfn) must be in the same zone.
- * zone->lock must be held before call this.
- *
-- * Returns 1 if all pages in the range is isolated.
-+ * Returns 1 if all pages in the range are isolated.
- */
- static int
- __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn)
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:10 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:27 +0900
-Subject: [PATCH v2 10/58] mm: Serialize access to min_free_kbytes
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-11-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Mel Gorman <mgorman@suse.de>
-
-There is a race between the min_free_kbytes sysctl, memory hotplug
-and transparent hugepage support enablement. Memory hotplug uses a
-zonelists_mutex to avoid a race when building zonelists. Reuse it to
-serialise watermark updates.
-
-[a.p.zijlstra@chello.nl: Older patch fixed the race with spinlock]
-Signed-off-by: Mel Gorman <mgorman@suse.de>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
-Tested-by: Barry Song <Baohua.Song@csr.com>
-(cherry picked from commit cfd3da1e49bb95c355c01c0f502d657deb3d34a4)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- mm/page_alloc.c | 23 +++++++++++++++--------
- 1 file changed, 15 insertions(+), 8 deletions(-)
-
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -5023,14 +5023,7 @@ static void setup_per_zone_lowmem_reserv
- calculate_totalreserve_pages();
- }
-
--/**
-- * setup_per_zone_wmarks - called when min_free_kbytes changes
-- * or when memory is hot-{added|removed}
-- *
-- * Ensures that the watermark[min,low,high] values for each zone are set
-- * correctly with respect to min_free_kbytes.
-- */
--void setup_per_zone_wmarks(void)
-+static void __setup_per_zone_wmarks(void)
- {
- unsigned long pages_min = min_free_kbytes >> (PAGE_SHIFT - 10);
- unsigned long lowmem_pages = 0;
-@@ -5085,6 +5078,20 @@ void setup_per_zone_wmarks(void)
- calculate_totalreserve_pages();
- }
-
-+/**
-+ * setup_per_zone_wmarks - called when min_free_kbytes changes
-+ * or when memory is hot-{added|removed}
-+ *
-+ * Ensures that the watermark[min,low,high] values for each zone are set
-+ * correctly with respect to min_free_kbytes.
-+ */
-+void setup_per_zone_wmarks(void)
-+{
-+ mutex_lock(&zonelists_mutex);
-+ __setup_per_zone_wmarks();
-+ mutex_unlock(&zonelists_mutex);
-+}
-+
- /*
- * The inactive anon list should be small enough that the VM never has to
- * do too much work, but large enough that each inactive page has a chance
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:15 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:29 +0900
-Subject: [PATCH v2 12/58] mm: trigger page reclaim in alloc_contig_range() to stabilise watermarks
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-13-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-alloc_contig_range() performs memory allocation so it also should keep
-track on keeping the correct level of memory watermarks. This commit adds
-a call to *_slowpath style reclaim to grab enough pages to make sure that
-the final collection of contiguous pages from freelists will not starve
-the system.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
-CC: Michal Nazarewicz <mina86@mina86.com>
-Tested-by: Rob Clark <rob.clark@linaro.org>
-Tested-by: Ohad Ben-Cohen <ohad@wizery.com>
-Tested-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-Tested-by: Robert Nelson <robertcnelson@gmail.com>
-Tested-by: Barry Song <Baohua.Song@csr.com>
-(cherry picked from commit 49f223a9cd96c7293d7258ff88c2bdf83065f69c)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- include/linux/mmzone.h | 9 +++++++
- mm/page_alloc.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 69 insertions(+)
-
---- a/include/linux/mmzone.h
-+++ b/include/linux/mmzone.h
-@@ -63,8 +63,10 @@ enum {
-
- #ifdef CONFIG_CMA
- # define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
-+# define cma_wmark_pages(zone) zone->min_cma_pages
- #else
- # define is_migrate_cma(migratetype) false
-+# define cma_wmark_pages(zone) 0
- #endif
-
- #define for_each_migratetype_order(order, type) \
-@@ -371,6 +373,13 @@ struct zone {
- /* see spanned/present_pages for more description */
- seqlock_t span_seqlock;
- #endif
-+#ifdef CONFIG_CMA
-+ /*
-+ * CMA needs to increase watermark levels during the allocation
-+ * process to make sure that the system is not starved.
-+ */
-+ unsigned long min_cma_pages;
-+#endif
- struct free_area free_area[MAX_ORDER];
-
- #ifndef CONFIG_SPARSEMEM
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -5082,6 +5082,11 @@ static void __setup_per_zone_wmarks(void
-
- zone->watermark[WMARK_LOW] = min_wmark_pages(zone) + (tmp >> 2);
- zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) + (tmp >> 1);
-+
-+ zone->watermark[WMARK_MIN] += cma_wmark_pages(zone);
-+ zone->watermark[WMARK_LOW] += cma_wmark_pages(zone);
-+ zone->watermark[WMARK_HIGH] += cma_wmark_pages(zone);
-+
- setup_zone_migrate_reserve(zone);
- spin_unlock_irqrestore(&zone->lock, flags);
- }
-@@ -5687,6 +5692,54 @@ static int __alloc_contig_migrate_range(
- return ret > 0 ? 0 : ret;
- }
-
-+/*
-+ * Update zone's cma pages counter used for watermark level calculation.
-+ */
-+static inline void __update_cma_watermarks(struct zone *zone, int count)
-+{
-+ unsigned long flags;
-+ spin_lock_irqsave(&zone->lock, flags);
-+ zone->min_cma_pages += count;
-+ spin_unlock_irqrestore(&zone->lock, flags);
-+ setup_per_zone_wmarks();
-+}
-+
-+/*
-+ * Trigger memory pressure bump to reclaim some pages in order to be able to
-+ * allocate 'count' pages in single page units. Does similar work as
-+ *__alloc_pages_slowpath() function.
-+ */
-+static int __reclaim_pages(struct zone *zone, gfp_t gfp_mask, int count)
-+{
-+ enum zone_type high_zoneidx = gfp_zone(gfp_mask);
-+ struct zonelist *zonelist = node_zonelist(0, gfp_mask);
-+ int did_some_progress = 0;
-+ int order = 1;
-+
-+ /*
-+ * Increase level of watermarks to force kswapd do his job
-+ * to stabilise at new watermark level.
-+ */
-+ __update_cma_watermarks(zone, count);
-+
-+ /* Obey watermarks as if the page was being allocated */
-+ while (!zone_watermark_ok(zone, 0, low_wmark_pages(zone), 0, 0)) {
-+ wake_all_kswapd(order, zonelist, high_zoneidx, zone_idx(zone));
-+
-+ did_some_progress = __perform_reclaim(gfp_mask, order, zonelist,
-+ NULL);
-+ if (!did_some_progress) {
-+ /* Exhausted what can be done so it's blamo time */
-+ out_of_memory(zonelist, gfp_mask, order, NULL, false);
-+ }
-+ }
-+
-+ /* Restore original watermark levels. */
-+ __update_cma_watermarks(zone, -count);
-+
-+ return count;
-+}
-+
- /**
- * alloc_contig_range() -- tries to allocate given range of pages
- * @start: start PFN to allocate
-@@ -5785,6 +5838,13 @@ int alloc_contig_range(unsigned long sta
- goto done;
- }
-
-+ /*
-+ * Reclaim enough pages to make sure that contiguous allocation
-+ * will not starve the system.
-+ */
-+ __reclaim_pages(zone, GFP_HIGHUSER_MOVABLE, end-start);
-+
-+ /* Grab isolated pages from freelists. */
- outer_end = isolate_freepages_range(outer_start, end);
- if (!outer_end) {
- ret = -EBUSY;
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:28 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:57 +0900
-Subject: [PATCH v2 40/58] mm: vmalloc: use const void * for caller argument
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-41-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-'const void *' is a safer type for caller function type. This patch
-updates all references to caller function type.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com>
-Reviewed-by: Minchan Kim <minchan@kernel.org>
-(cherry picked from commit 5e6cafc83e30f0f70c79a2b7aef237dc57e29f02)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- include/linux/vmalloc.h | 8 ++++----
- mm/vmalloc.c | 18 +++++++++---------
- 2 files changed, 13 insertions(+), 13 deletions(-)
-
-diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
-index dcdfc2b..2e28f4d 100644
---- a/include/linux/vmalloc.h
-+++ b/include/linux/vmalloc.h
-@@ -32,7 +32,7 @@ struct vm_struct {
- struct page **pages;
- unsigned int nr_pages;
- phys_addr_t phys_addr;
-- void *caller;
-+ const void *caller;
- };
-
- /*
-@@ -62,7 +62,7 @@ extern void *vmalloc_32_user(unsigned long size);
- extern void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot);
- extern void *__vmalloc_node_range(unsigned long size, unsigned long align,
- unsigned long start, unsigned long end, gfp_t gfp_mask,
-- pgprot_t prot, int node, void *caller);
-+ pgprot_t prot, int node, const void *caller);
- extern void vfree(const void *addr);
-
- extern void *vmap(struct page **pages, unsigned int count,
-@@ -85,13 +85,13 @@ static inline size_t get_vm_area_size(const struct vm_struct *area)
-
- extern struct vm_struct *get_vm_area(unsigned long size, unsigned long flags);
- extern struct vm_struct *get_vm_area_caller(unsigned long size,
-- unsigned long flags, void *caller);
-+ unsigned long flags, const void *caller);
- extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
- unsigned long start, unsigned long end);
- extern struct vm_struct *__get_vm_area_caller(unsigned long size,
- unsigned long flags,
- unsigned long start, unsigned long end,
-- void *caller);
-+ const void *caller);
- extern struct vm_struct *remove_vm_area(const void *addr);
-
- extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
-diff --git a/mm/vmalloc.c b/mm/vmalloc.c
-index 1196c77..389e77c 100644
---- a/mm/vmalloc.c
-+++ b/mm/vmalloc.c
-@@ -1280,7 +1280,7 @@ DEFINE_RWLOCK(vmlist_lock);
- struct vm_struct *vmlist;
-
- static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
-- unsigned long flags, void *caller)
-+ unsigned long flags, const void *caller)
- {
- vm->flags = flags;
- vm->addr = (void *)va->va_start;
-@@ -1306,7 +1306,7 @@ static void insert_vmalloc_vmlist(struct vm_struct *vm)
- }
-
- static void insert_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
-- unsigned long flags, void *caller)
-+ unsigned long flags, const void *caller)
- {
- setup_vmalloc_vm(vm, va, flags, caller);
- insert_vmalloc_vmlist(vm);
-@@ -1314,7 +1314,7 @@ static void insert_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
-
- static struct vm_struct *__get_vm_area_node(unsigned long size,
- unsigned long align, unsigned long flags, unsigned long start,
-- unsigned long end, int node, gfp_t gfp_mask, void *caller)
-+ unsigned long end, int node, gfp_t gfp_mask, const void *caller)
- {
- struct vmap_area *va;
- struct vm_struct *area;
-@@ -1375,7 +1375,7 @@ EXPORT_SYMBOL_GPL(__get_vm_area);
-
- struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags,
- unsigned long start, unsigned long end,
-- void *caller)
-+ const void *caller)
- {
- return __get_vm_area_node(size, 1, flags, start, end, -1, GFP_KERNEL,
- caller);
-@@ -1397,7 +1397,7 @@ struct vm_struct *get_vm_area(unsigned long size, unsigned long flags)
- }
-
- struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags,
-- void *caller)
-+ const void *caller)
- {
- return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END,
- -1, GFP_KERNEL, caller);
-@@ -1568,9 +1568,9 @@ EXPORT_SYMBOL(vmap);
-
- static void *__vmalloc_node(unsigned long size, unsigned long align,
- gfp_t gfp_mask, pgprot_t prot,
-- int node, void *caller);
-+ int node, const void *caller);
- static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
-- pgprot_t prot, int node, void *caller)
-+ pgprot_t prot, int node, const void *caller)
- {
- const int order = 0;
- struct page **pages;
-@@ -1643,7 +1643,7 @@ fail:
- */
- void *__vmalloc_node_range(unsigned long size, unsigned long align,
- unsigned long start, unsigned long end, gfp_t gfp_mask,
-- pgprot_t prot, int node, void *caller)
-+ pgprot_t prot, int node, const void *caller)
- {
- struct vm_struct *area;
- void *addr;
-@@ -1699,7 +1699,7 @@ fail:
- */
- static void *__vmalloc_node(unsigned long size, unsigned long align,
- gfp_t gfp_mask, pgprot_t prot,
-- int node, void *caller)
-+ int node, const void *caller)
- {
- return __vmalloc_node_range(size, align, VMALLOC_START, VMALLOC_END,
- gfp_mask, prot, node, caller);
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:53:15 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:51 +0900
-Subject: [PATCH v2 34/58] x86: dma-mapping: fix broken allocation when dma_mask has been provided
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-35-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-Commit 0a2b9a6ea93 ("X86: integrate CMA with DMA-mapping subsystem")
-broke memory allocation with dma_mask. This patch fixes possible kernel
-ops caused by lack of resetting page variable when jumping to 'again' label.
-
-Reported-by: Konrad Rzeszutek Wilk <konrad@darnok.org>
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Acked-by: Michal Nazarewicz <mina86@mina86.com>
-(cherry picked from commit c080e26edc3a2a3cdfa4c430c663ee1c3bbd8fae)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/x86/kernel/pci-dma.c | 3 ++-
- 1 files changed, 2 insertions(+), 1 deletions(-)
-
-diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
-index 62c9457..c0f420f 100644
---- a/arch/x86/kernel/pci-dma.c
-+++ b/arch/x86/kernel/pci-dma.c
-@@ -100,7 +100,7 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size,
- struct dma_attrs *attrs)
- {
- unsigned long dma_mask;
-- struct page *page = NULL;
-+ struct page *page;
- unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
- dma_addr_t addr;
-
-@@ -108,6 +108,7 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size,
-
- flag |= __GFP_ZERO;
- again:
-+ page = NULL;
- if (!(flag & GFP_ATOMIC))
- page = dma_alloc_from_contiguous(dev, count, get_order(size));
- if (!page)
---
-1.7.5.4
-
+++ /dev/null
-From dhobsong@igel.co.jp Mon Oct 29 00:52:21 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Mon, 29 Oct 2012 16:50:31 +0900
-Subject: [PATCH v2 14/58] X86: integrate CMA with DMA-mapping subsystem
-To: greg@kroah.com, laurent.pinchart@ideasonboard.com, horms@verge.net.au
-Cc: ltsi-dev@lists.linuxfoundation.org, dhobsong@igel.co.jp
-Message-ID: <1351497075-32717-15-git-send-email-dhobsong@igel.co.jp>
-
-
-From: Marek Szyprowski <m.szyprowski@samsung.com>
-
-This patch adds support for CMA to dma-mapping subsystem for x86
-architecture that uses common pci-dma/pci-nommu implementation. This
-allows to test CMA on KVM/QEMU and a lot of common x86 boxes.
-
-Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
-CC: Michal Nazarewicz <mina86@mina86.com>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-(cherry picked from commit 0a2b9a6ea93650b8a00f9fd5ee8fdd25671e2df6)
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----
- arch/x86/Kconfig | 1 +
- arch/x86/include/asm/dma-contiguous.h | 13 +++++++++++++
- arch/x86/include/asm/dma-mapping.h | 5 +++++
- arch/x86/kernel/pci-dma.c | 18 ++++++++++++++++--
- arch/x86/kernel/pci-nommu.c | 8 +-------
- arch/x86/kernel/setup.c | 2 ++
- 6 files changed, 38 insertions(+), 9 deletions(-)
- create mode 100644 arch/x86/include/asm/dma-contiguous.h
-
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -32,6 +32,7 @@ config X86
- select ARCH_WANT_OPTIONAL_GPIOLIB
- select ARCH_WANT_FRAME_POINTERS
- select HAVE_DMA_ATTRS
-+ select HAVE_DMA_CONTIGUOUS if !SWIOTLB
- select HAVE_KRETPROBES
- select HAVE_OPTPROBES
- select HAVE_FTRACE_MCOUNT_RECORD
---- /dev/null
-+++ b/arch/x86/include/asm/dma-contiguous.h
-@@ -0,0 +1,13 @@
-+#ifndef ASMX86_DMA_CONTIGUOUS_H
-+#define ASMX86_DMA_CONTIGUOUS_H
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/types.h>
-+#include <asm-generic/dma-contiguous.h>
-+
-+static inline void
-+dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) { }
-+
-+#endif
-+#endif
---- a/arch/x86/include/asm/dma-mapping.h
-+++ b/arch/x86/include/asm/dma-mapping.h
-@@ -13,6 +13,7 @@
- #include <asm/io.h>
- #include <asm/swiotlb.h>
- #include <asm-generic/dma-coherent.h>
-+#include <linux/dma-contiguous.h>
-
- #ifdef CONFIG_ISA
- # define ISA_DMA_BIT_MASK DMA_BIT_MASK(24)
-@@ -62,6 +63,10 @@ extern void *dma_generic_alloc_coherent(
- dma_addr_t *dma_addr, gfp_t flag,
- struct dma_attrs *attrs);
-
-+extern void dma_generic_free_coherent(struct device *dev, size_t size,
-+ void *vaddr, dma_addr_t dma_addr,
-+ struct dma_attrs *attrs);
-+
- static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
- {
- if (!dev->dma_mask)
---- a/arch/x86/kernel/pci-dma.c
-+++ b/arch/x86/kernel/pci-dma.c
-@@ -100,14 +100,18 @@ void *dma_generic_alloc_coherent(struct
- struct dma_attrs *attrs)
- {
- unsigned long dma_mask;
-- struct page *page;
-+ struct page *page = NULL;
-+ unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
- dma_addr_t addr;
-
- dma_mask = dma_alloc_coherent_mask(dev, flag);
-
- flag |= __GFP_ZERO;
- again:
-- page = alloc_pages_node(dev_to_node(dev), flag, get_order(size));
-+ if (!(flag & GFP_ATOMIC))
-+ page = dma_alloc_from_contiguous(dev, count, get_order(size));
-+ if (!page)
-+ page = alloc_pages_node(dev_to_node(dev), flag, get_order(size));
- if (!page)
- return NULL;
-
-@@ -127,6 +131,16 @@ again:
- return page_address(page);
- }
-
-+void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr,
-+ dma_addr_t dma_addr, struct dma_attrs *attrs)
-+{
-+ unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-+ struct page *page = virt_to_page(vaddr);
-+
-+ if (!dma_release_from_contiguous(dev, page, count))
-+ free_pages((unsigned long)vaddr, get_order(size));
-+}
-+
- /*
- * See <Documentation/x86/x86_64/boot-options.txt> for the iommu kernel
- * parameter documentation.
---- a/arch/x86/kernel/pci-nommu.c
-+++ b/arch/x86/kernel/pci-nommu.c
-@@ -74,12 +74,6 @@ static int nommu_map_sg(struct device *h
- return nents;
- }
-
--static void nommu_free_coherent(struct device *dev, size_t size, void *vaddr,
-- dma_addr_t dma_addr, struct dma_attrs *attrs)
--{
-- free_pages((unsigned long)vaddr, get_order(size));
--}
--
- static void nommu_sync_single_for_device(struct device *dev,
- dma_addr_t addr, size_t size,
- enum dma_data_direction dir)
-@@ -97,7 +91,7 @@ static void nommu_sync_sg_for_device(str
-
- struct dma_map_ops nommu_dma_ops = {
- .alloc = dma_generic_alloc_coherent,
-- .free = nommu_free_coherent,
-+ .free = dma_generic_free_coherent,
- .map_sg = nommu_map_sg,
- .map_page = nommu_map_page,
- .sync_single_for_device = nommu_sync_single_for_device,
---- a/arch/x86/kernel/setup.c
-+++ b/arch/x86/kernel/setup.c
-@@ -50,6 +50,7 @@
- #include <asm/pci-direct.h>
- #include <linux/init_ohci1394_dma.h>
- #include <linux/kvm_para.h>
-+#include <linux/dma-contiguous.h>
-
- #include <linux/errno.h>
- #include <linux/kernel.h>
-@@ -1028,6 +1029,7 @@ void __init setup_arch(char **cmdline_p)
- }
- #endif
- memblock.current_limit = get_max_mapped();
-+ dma_contiguous_reserve(0);
-
- /*
- * NOTE: On x86-32, only from this point on, fixmaps are ready for use.
+++ /dev/null
-From 9354861d155a84b6326ff48f0ee9f37a83285f50 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 2 Oct 2012 19:08:53 -0700
-Subject: ASoC: fsi: fixup channels_min/max
-
-FSI can support 1 - 8 channel input/output,
-but current driver is supporting 2 channel format only.
-This patch fixes channel mismatch
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-(cherry picked from commit 2a8c8a569ff3631f6b6d82ea17c57b9f064b2a7b)
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- sound/soc/sh/fsi.c | 18 +++++++++---------
- 1 file changed, 9 insertions(+), 9 deletions(-)
-
---- a/sound/soc/sh/fsi.c
-+++ b/sound/soc/sh/fsi.c
-@@ -1498,7 +1498,7 @@ static struct snd_pcm_hardware fsi_pcm_h
- .rates = FSI_RATES,
- .rate_min = 8000,
- .rate_max = 192000,
-- .channels_min = 1,
-+ .channels_min = 2,
- .channels_max = 2,
- .buffer_bytes_max = 64 * 1024,
- .period_bytes_min = 32,
-@@ -1586,14 +1586,14 @@ static struct snd_soc_dai_driver fsi_soc
- .playback = {
- .rates = FSI_RATES,
- .formats = FSI_FMTS,
-- .channels_min = 1,
-- .channels_max = 8,
-+ .channels_min = 2,
-+ .channels_max = 2,
- },
- .capture = {
- .rates = FSI_RATES,
- .formats = FSI_FMTS,
-- .channels_min = 1,
-- .channels_max = 8,
-+ .channels_min = 2,
-+ .channels_max = 2,
- },
- .ops = &fsi_dai_ops,
- },
-@@ -1602,14 +1602,14 @@ static struct snd_soc_dai_driver fsi_soc
- .playback = {
- .rates = FSI_RATES,
- .formats = FSI_FMTS,
-- .channels_min = 1,
-- .channels_max = 8,
-+ .channels_min = 2,
-+ .channels_max = 2,
- },
- .capture = {
- .rates = FSI_RATES,
- .formats = FSI_FMTS,
-- .channels_min = 1,
-- .channels_max = 8,
-+ .channels_min = 2,
-+ .channels_max = 2,
- },
- .ops = &fsi_dai_ops,
- },
+++ /dev/null
-From a9e8131d2d9acdd20e597ac769fdedce04db4db9 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 10 Dec 2012 22:43:45 -0800
-Subject: usb: renesas_usbhs: gadget: remove usbhsg_uep_init()
-
-Current driver always initialized uep->pipe to NULL on usbhsg_try_start().
-But it breaks relationship with
-usb_ep_ops :: enable/disable functions when suspend/resume.
-This patch solved this issue by initializing uep->pipe on probe()
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- drivers/usb/renesas_usbhs/mod_gadget.c | 11 +----------
- 1 file changed, 1 insertion(+), 10 deletions(-)
-
---- a/drivers/usb/renesas_usbhs/mod_gadget.c
-+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
-@@ -541,15 +541,6 @@ static int usbhsg_pipe_disable(struct us
- return 0;
- }
-
--static void usbhsg_uep_init(struct usbhsg_gpriv *gpriv)
--{
-- int i;
-- struct usbhsg_uep *uep;
--
-- usbhsg_for_each_uep_with_dcp(uep, gpriv, i)
-- uep->pipe = NULL;
--}
--
- /*
- *
- * usb_ep_ops
-@@ -757,7 +748,6 @@ static int usbhsg_try_start(struct usbhs
- usbhs_pipe_init(priv,
- usbhsg_dma_map_ctrl);
- usbhs_fifo_init(priv);
-- usbhsg_uep_init(gpriv);
-
- /* dcp init */
- dcp->pipe = usbhs_dcp_malloc(priv);
-@@ -970,6 +960,7 @@ int usbhs_mod_gadget_probe(struct usbhs_
- */
- usbhsg_for_each_uep_with_dcp(uep, gpriv, i) {
- uep->gpriv = gpriv;
-+ uep->pipe = NULL;
- snprintf(uep->ep_name, EP_NAME_SIZE, "ep%d", i);
-
- uep->ep.name = uep->ep_name;
+++ /dev/null
-From ed0a408a51295f69c3b17417b7789f0e8b42abd7 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 10 Dec 2012 22:44:07 -0800
-Subject: usb: renesas_usbhs: gadget: usbhsg_ep_disable() care pipe settings
-
-Current usbhsg_ep_disable() didn't care
-uep->pipe and pipe->mod_private variable which is used on usbhsg_ep_enable().
-It breaks renesas_usbhs gadget when resume.
-This patch fixes it.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- drivers/usb/renesas_usbhs/mod_gadget.c | 11 ++++++++---
- 1 file changed, 8 insertions(+), 3 deletions(-)
-
---- a/drivers/usb/renesas_usbhs/mod_gadget.c
-+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
-@@ -597,7 +597,12 @@ static int usbhsg_ep_disable(struct usb_
- {
- struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
-
-- return usbhsg_pipe_disable(uep);
-+ usbhsg_pipe_disable(uep);
-+
-+ uep->pipe->mod_private = NULL;
-+ uep->pipe = NULL;
-+
-+ return 0;
- }
-
- static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep,
-@@ -749,7 +754,7 @@ static int usbhsg_try_start(struct usbhs
- usbhsg_dma_map_ctrl);
- usbhs_fifo_init(priv);
-
-- /* dcp init */
-+ /* dcp init instead of usbhsg_ep_enable() */
- dcp->pipe = usbhs_dcp_malloc(priv);
- dcp->pipe->mod_private = dcp;
- usbhs_pipe_config_update(dcp->pipe, 0, 0, 64);
-@@ -811,7 +816,7 @@ static int usbhsg_try_stop(struct usbhs_
- usbhs_sys_set_test_mode(priv, 0);
- usbhs_sys_function_ctrl(priv, 0);
-
-- usbhsg_pipe_disable(dcp);
-+ usbhsg_ep_disable(&dcp->ep);
-
- dev_dbg(dev, "stop gadget\n");
-
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Wed Feb 20 14:11:19 2013
-From: Simon Horman <horms+renesas@verge.net.au>
-Date: Wed, 20 Feb 2013 14:06:18 -0800
-Subject: ARM: shmobile: r8a7779: Correct TMU clock support again
-To: ltsi-dev@lists.linuxfoundation.org
-Cc: Denis Oliver Kropp <dok@directfb.org>, Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Message-ID: <1361397978-15092-2-git-send-email-horms+renesas@verge.net.au>
-
-
-After discussion on the linux-sh mailing list and reference to the
-hardware documentation it appears that 'TMU00', 'TMU01' and 'TMU02'
-use a common clock.
-
-The sh_tmu.1 portion of this change resolves a regression introduced in
-58079fa7d54a0929d304054ee759187a2ccd3cdf (ARM: shmobile: r8a7779: Correct
-TMU clock support) and fixes a regression introduced by that patch. That
-patch is queued up for v3.9.
-
-...
-hub 4-0:1.0: USB hub found
-hub 4-0:1.0: 2 ports detected
-INFO: rcu_sched self-detected stall on CPUINFO: rcu_sched detected stalls on
-+CPUs/tasks: { 1} (detected by 2, t=279640 jiffies, g=4294967052, c=4294967051,
-+q=38)
-Task dump for CPU 1:
-swapper/0 R running 0 1 0 0x00000002
-[<c02b8f5c>] (__schedule+0x1b0/0x4c0) from [<c013c590>] (__loop_delay+0x4/0xc)
-
- { 1} (t=279640 jiffies g=4294967052 c=4294967052 q=37)
-[<c000ef9c>] (unwind_backtrace+0x0/0xf8) from [<c0068488>]
-+(rcu_check_callbacks+0x218/0x6b8)
-[<c0068488>] (rcu_check_callbacks+0x218/0x6b8) from [<c0026774>]
-+(update_process_times+0x38/0x4c)
-[<c0026774>] (update_process_times+0x38/0x4c) from [<c00569e0>]
-+(tick_nohz_handler+0xb4/0x11c)
-[<c00569e0>] (tick_nohz_handler+0xb4/0x11c) from [<c000e518>]
-+(twd_handler+0x34/0x44)
-[<c000e518>] (twd_handler+0x34/0x44) from [<c0063484>]
-+(handle_percpu_devid_irq+0x68/0x80)
-[<c0063484>] (handle_percpu_devid_irq+0x68/0x80) from [<c005febc>]
-+(generic_handle_irq+0x20/0x30)
-[<c005febc>] (generic_handle_irq+0x20/0x30) from [<c000a5ec>]
-+(handle_IRQ+0x40/0x90)
-[<c000a5ec>] (handle_IRQ+0x40/0x90) from [<c000934c>] (gic_handle_irq+0x2c/0x5c)
-[<c000934c>] (gic_handle_irq+0x2c/0x5c) from [<c0009a40>] (__irq_svc+0x40/0x50)
-Exception stack(0xef03ddf8 to 0xef03de40)
-dde0: 000001c1 ffffffff
-de00: 000001d8 01bf01bf ef35ec40 ef35e800 ef35ec6c 0000002b ef35ec68 c013c560
-de20: c0392994 60000113 00000000 ef03de40 c01a5d40 c013c590 20000113 ffffffff
-[<c0009a40>] (__irq_svc+0x40/0x50) from [<c013c590>] (__loop_delay+0x4/0xc)
-
-Cc: Denis Oliver Kropp <dok@directfb.org>
-Cc: Magnus Damm <damm@opensource.se>
-Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Cc: Paul Mundt <lethal@linux-sh.org>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-(cherry picked from commit f9047306fd7332d682898dd689152bb3b45a3e73)
-
-Conflicts:
- arch/arm/mach-shmobile/clock-r8a7779.c
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- arch/arm/mach-shmobile/clock-r8a7779.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/arch/arm/mach-shmobile/clock-r8a7779.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
-@@ -146,8 +146,8 @@ static struct clk_lookup lookups[] = {
- CLKDEV_DEV_ID("sata_rcar", &mstp_clks[MSTP115]), /* SATA */
- CLKDEV_DEV_ID("fc600000.sata", &mstp_clks[MSTP115]), /* SATA w/DT */
- CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP016]), /* TMU00 */
-- CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP015]), /* TMU01 */
-- CLKDEV_DEV_ID("sh_tmu.2", &mstp_clks[MSTP014]), /* TMU02 */
-+ CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP016]), /* TMU01 */
-+ CLKDEV_DEV_ID("sh_tmu.2", &mstp_clks[MSTP016]), /* TMU02 */
- CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
- CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
- CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Thu Feb 14 20:37:39 2013
-From: Do Quang Thang <dq-thang@jinso.co.jp>
-Date: Fri, 15 Feb 2013 13:37:03 +0900
-Subject: [PATCH 2/2] ASoC: shmobile: armadillo800eva: enable clock inversion on FSI-A
-To: ltsi-dev@lists.linuxfoundation.org
-Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Message-ID: <1360903023-19758-3-git-send-email-dq-thang@jinso.co.jp>
-
-
-Since board flags were updated with simple-card driver in upstream kernel on
-a4a2992c531f6ca0aa00ce0deb31e51c1b7ae69b
-(ASoC: simple-card: add asoc_simple_dai for initializing)
-fixup patch for an "old style" does not exist.
-This patch is for LTSI kernel
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Nguyen Viet Dung <nv-dung@jinso.co.jp>
----
- arch/arm/mach-shmobile/board-armadillo800eva.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm/mach-shmobile/board-armadillo800eva.c
-+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
-@@ -795,6 +795,7 @@ static int fsi_hdmi_set_rate(struct devi
- static struct sh_fsi_platform_info fsi_info = {
- /* FSI-WM8978 */
- .port_a = {
-+ .flags = SH_FSI_BRS_INV,
- .tx_id = SHDMA_SLAVE_FSIA_TX,
- },
- /* FSI-HDMI */
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Tue Feb 12 20:55:41 2013
-From: Do Quang Thang <dq-thang@jinso.co.jp>
-Date: Wed, 13 Feb 2013 13:23:50 +0900
-Subject: [PATCH 02/10] Revert "usb: renesas_usbhs: gadget: remove usbhsg_uep_init()"
-To: ltsi-dev@lists.linuxfoundation.org
-Message-ID: <1360729438-10731-3-git-send-email-dq-thang@jinso.co.jp>
-
-
-This reverts commit f1b8894e20b3b92524473ab7e8f2eee3e581d708.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-Signed-off-by: Do Quang Thang <dq-thang@jinso.co.jp>
----
- drivers/usb/renesas_usbhs/mod_gadget.c | 11 ++++++++++-
- 1 file changed, 10 insertions(+), 1 deletion(-)
-
---- a/drivers/usb/renesas_usbhs/mod_gadget.c
-+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
-@@ -541,6 +541,15 @@ static int usbhsg_pipe_disable(struct us
- return 0;
- }
-
-+static void usbhsg_uep_init(struct usbhsg_gpriv *gpriv)
-+{
-+ int i;
-+ struct usbhsg_uep *uep;
-+
-+ usbhsg_for_each_uep_with_dcp(uep, gpriv, i)
-+ uep->pipe = NULL;
-+}
-+
- /*
- *
- * usb_ep_ops
-@@ -748,6 +757,7 @@ static int usbhsg_try_start(struct usbhs
- usbhs_pipe_init(priv,
- usbhsg_dma_map_ctrl);
- usbhs_fifo_init(priv);
-+ usbhsg_uep_init(gpriv);
-
- /* dcp init */
- dcp->pipe = usbhs_dcp_malloc(priv);
-@@ -960,7 +970,6 @@ int usbhs_mod_gadget_probe(struct usbhs_
- */
- usbhsg_for_each_uep_with_dcp(uep, gpriv, i) {
- uep->gpriv = gpriv;
-- uep->pipe = NULL;
- snprintf(uep->ep_name, EP_NAME_SIZE, "ep%d", i);
-
- uep->ep.name = uep->ep_name;
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Tue Feb 12 20:55:46 2013
-From: Do Quang Thang <dq-thang@jinso.co.jp>
-Date: Wed, 13 Feb 2013 13:23:49 +0900
-Subject: [PATCH 01/10] Revert "usb: renesas_usbhs: gadget: usbhsg_ep_disable() care pipe settings"
-To: ltsi-dev@lists.linuxfoundation.org
-Message-ID: <1360729438-10731-2-git-send-email-dq-thang@jinso.co.jp>
-
-
-This reverts commit 8983431340203180a6712d3ff3da6770a53cedca.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-Signed-off-by: Do Quang Thang <dq-thang@jinso.co.jp>
----
- drivers/usb/renesas_usbhs/mod_gadget.c | 11 +++--------
- 1 file changed, 3 insertions(+), 8 deletions(-)
-
---- a/drivers/usb/renesas_usbhs/mod_gadget.c
-+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
-@@ -597,12 +597,7 @@ static int usbhsg_ep_disable(struct usb_
- {
- struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
-
-- usbhsg_pipe_disable(uep);
--
-- uep->pipe->mod_private = NULL;
-- uep->pipe = NULL;
--
-- return 0;
-+ return usbhsg_pipe_disable(uep);
- }
-
- static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep,
-@@ -754,7 +749,7 @@ static int usbhsg_try_start(struct usbhs
- usbhsg_dma_map_ctrl);
- usbhs_fifo_init(priv);
-
-- /* dcp init instead of usbhsg_ep_enable() */
-+ /* dcp init */
- dcp->pipe = usbhs_dcp_malloc(priv);
- dcp->pipe->mod_private = dcp;
- usbhs_pipe_config_update(dcp->pipe, 0, 0, 64);
-@@ -816,7 +811,7 @@ static int usbhsg_try_stop(struct usbhs_
- usbhs_sys_set_test_mode(priv, 0);
- usbhs_sys_function_ctrl(priv, 0);
-
-- usbhsg_ep_disable(&dcp->ep);
-+ usbhsg_pipe_disable(dcp);
-
- dev_dbg(dev, "stop gadget\n");
-
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Thu Feb 14 20:37:35 2013
-From: Do Quang Thang <dq-thang@jinso.co.jp>
-Date: Fri, 15 Feb 2013 13:37:02 +0900
-Subject: [PATCH 1/2] sh: clkfwk: bugfix: sh_clk_div_enable() care sh_clk_div_set_rate() if div6
-To: ltsi-dev@lists.linuxfoundation.org
-Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Message-ID: <1360903023-19758-2-git-send-email-dq-thang@jinso.co.jp>
-
-
-764f4e4e33d18cde4dcaf8a0d860b749c6d6d08b
-(sh: clkfwk: Use shared sh_clk_div_enable/disable())
-shared enable/disable funcions for div4/div6.
-But new sh_clk_div_enable() didn't care sh_clk_div_set_rate()
-which is required on div6 clock.
-This patch fixes it.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 5a799b824b6046befa7e10107a3d65f40816f645)
-
-Signed-off-by: Do Quang Thang <dq-thang@jinso.co.jp>
----
- drivers/sh/clk/cpg.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/sh/clk/cpg.c
-+++ b/drivers/sh/clk/cpg.c
-@@ -126,6 +126,12 @@ static int sh_clk_div_set_rate(struct cl
-
- static int sh_clk_div_enable(struct clk *clk)
- {
-+ if (clk->div_mask == SH_CLK_DIV6_MSK) {
-+ int ret = sh_clk_div_set_rate(clk, clk->rate);
-+ if (ret < 0)
-+ return ret;
-+ }
-+
- sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk);
- return 0;
- }
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sun Feb 17 18:06:24 2013
-From: Do Quang Thang <dq-thang@jinso.co.jp>
-Date: Mon, 18 Feb 2013 11:05:36 +0900
-Subject: usb: gadget: acm_ms: need to set max_speed
-To: Greg KH <greg@kroah.com>
-Cc: ltsi-dev@lists.linuxfoundation.org
-Message-ID: <1361153138-5365-6-git-send-email-dq-thang@jinso.co.jp>
-
-
-From: Steve Bennett <steveb@workware.net.au>
-
-Failing to set max_speed prevents g_acm_ms working with many drivers which
-check for driver->max_speed < USB_SPEED_FULL, including pxa25x_udc
-
-Signed-off-by: Steve Bennett <steveb@workware.net.au>
-Signed-off-by: Felipe Balbi <balbi@ti.com>
-(cherry picked from commit 6f47209b271661ecd5929397cbe646ff247f01b6)
-
-Signed-off-by: Do Quang Thang <dq-thang@jinso.co.jp>
----
- drivers/usb/gadget/acm_ms.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/usb/gadget/acm_ms.c
-+++ b/drivers/usb/gadget/acm_ms.c
-@@ -235,6 +235,7 @@ static int __exit acm_ms_unbind(struct u
- static struct usb_composite_driver acm_ms_driver = {
- .name = "g_acm_ms",
- .dev = &device_desc,
-+ .max_speed = USB_SPEED_SUPER,
- .strings = dev_strings,
- .unbind = __exit_p(acm_ms_unbind),
- };
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sun Feb 17 18:06:06 2013
-From: Do Quang Thang <dq-thang@jinso.co.jp>
-Date: Mon, 18 Feb 2013 11:05:33 +0900
-Subject: usb: gadget: composite: fix ep->maxburst initialization
-To: Greg KH <greg@kroah.com>
-Cc: ltsi-dev@lists.linuxfoundation.org
-Message-ID: <1361153138-5365-3-git-send-email-dq-thang@jinso.co.jp>
-
-
-From: Felipe Balbi <balbi@ti.com>
-
-bMaxBurst field on endpoint companion descriptor
-is supposed to contain the number of burst minus
-1. When passing that to controller drivers, we
-should be passing the real number instead (by
-incrementing 1).
-
-While doing that, also fix the assumption on
-dwc3 that value comes decremented by one.
-
-Signed-off-by: Felipe Balbi <balbi@ti.com>
-(cherry picked from commit b785ea7ce662c47f6208071320638a4813722803)
-
-Signed-off-by: Do Quang Thang <dq-thang@jinso.co.jp>
----
- drivers/usb/dwc3/gadget.c | 2 +-
- drivers/usb/gadget/composite.c | 7 +++++--
- 2 files changed, 6 insertions(+), 3 deletions(-)
-
---- a/drivers/usb/dwc3/gadget.c
-+++ b/drivers/usb/dwc3/gadget.c
-@@ -390,7 +390,7 @@ static int dwc3_gadget_set_ep_config(str
-
- params.param0 = DWC3_DEPCFG_EP_TYPE(usb_endpoint_type(desc))
- | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc))
-- | DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst);
-+ | DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst - 1);
-
- params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN
- | DWC3_DEPCFG_XFER_NOT_READY_EN;
---- a/drivers/usb/gadget/composite.c
-+++ b/drivers/usb/gadget/composite.c
-@@ -117,6 +117,7 @@ int config_ep_by_speed(struct usb_gadget
- struct usb_function *f,
- struct usb_ep *_ep)
- {
-+ struct usb_composite_dev *cdev = get_gadget_data(g);
- struct usb_endpoint_descriptor *chosen_desc = NULL;
- struct usb_descriptor_header **speed_desc = NULL;
-
-@@ -180,10 +181,12 @@ ep_found:
- _ep->mult = comp_desc->bmAttributes & 0x3;
- case USB_ENDPOINT_XFER_BULK:
- case USB_ENDPOINT_XFER_INT:
-- _ep->maxburst = comp_desc->bMaxBurst;
-+ _ep->maxburst = comp_desc->bMaxBurst + 1;
- break;
- default:
-- /* Do nothing for control endpoints */
-+ if (comp_desc->bMaxBurst != 0)
-+ ERROR(cdev, "ep0 bMaxBurst must be 0\n");
-+ _ep->maxburst = 1;
- break;
- }
- }
+++ /dev/null
-From dq-thang@jinso.co.jp Sun Feb 17 18:06:07 2013
-From: Do Quang Thang <dq-thang@jinso.co.jp>
-Date: Mon, 18 Feb 2013 11:05:32 +0900
-Subject: usb: gadget: f_mass_storage: change default value of the removable parameter
-To: Greg KH <greg@kroah.com>
-Cc: ltsi-dev@lists.linuxfoundation.org
-Message-ID: <1361153138-5365-2-git-send-email-dq-thang@jinso.co.jp>
-
-
-From: Michal Nazarewicz <mina86@mina86.com>
-
-This commit changes the default value of the removable module parameter
-from “y” to “n”. This comes with line with file_storag's default and
-seems to be a better default.
-
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Signed-off-by: Felipe Balbi <balbi@ti.com>
-(cherry picked from commit fa84c57516f6da93ebc2601348043e9bcb7b4b4d)
-
-Signed-off-by: Do Quang Thang <dq-thang@jinso.co.jp>
----
- drivers/usb/gadget/f_mass_storage.c | 6 ++----
- 1 file changed, 2 insertions(+), 4 deletions(-)
-
---- a/drivers/usb/gadget/f_mass_storage.c
-+++ b/drivers/usb/gadget/f_mass_storage.c
-@@ -124,7 +124,7 @@
- * backing storage.
- * ro=b[,b...] Default false, boolean for read-only access.
- * removable=b[,b...]
-- * Default true, boolean for removable media.
-+ * Default false, boolean for removable media.
- * cdrom=b[,b...] Default false, boolean for whether to emulate
- * a CD-ROM drive.
- * nofua=b[,b...] Default false, booleans for ignore FUA flag
-@@ -3174,8 +3174,7 @@ fsg_config_from_params(struct fsg_config
- for (i = 0, lun = cfg->luns; i < cfg->nluns; ++i, ++lun) {
- lun->ro = !!params->ro[i];
- lun->cdrom = !!params->cdrom[i];
-- lun->removable = /* Removable by default */
-- params->removable_count <= i || params->removable[i];
-+ lun->removable = !!params->removable[i];
- lun->filename =
- params->file_count > i && params->file[i][0]
- ? params->file[i]
-@@ -3210,4 +3209,3 @@ fsg_common_from_params(struct fsg_common
- fsg_config_from_params(&cfg, params);
- return fsg_common_init(common, cdev, &cfg);
- }
--
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sun Feb 17 18:06:16 2013
-From: Do Quang Thang <dq-thang@jinso.co.jp>
-Date: Mon, 18 Feb 2013 11:05:35 +0900
-Subject: usb: gadget: mass_storage: add documentation
-To: Greg KH <greg@kroah.com>
-Cc: ltsi-dev@lists.linuxfoundation.org
-Message-ID: <1361153138-5365-5-git-send-email-dq-thang@jinso.co.jp>
-
-
-From: Michal Nazarewicz <mina86@mina86.com>
-
-This commit adds Documentation/usb/mass-storage.txt file. It contains
-description of how to use the mass storage gadget from user space. It
-elaborates on madule parameters and sysfs interface more then it was
-written in the comments in the source code.
-
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Acked-by: Alan Stern <stern@rowland.harvard.edu>
-Signed-off-by: Felipe Balbi <balbi@ti.com>
-(cherry picked from commit a8287a4ed543494c121050dc453972902637e6de)
-
-Signed-off-by: Do Quang Thang <dq-thang@jinso.co.jp>
----
- Documentation/usb/mass-storage.txt | 226 ++++++++++++++++++++++++++++++++++++
- drivers/usb/gadget/f_mass_storage.c | 69 +---------
- 2 files changed, 233 insertions(+), 62 deletions(-)
- create mode 100644 Documentation/usb/mass-storage.txt
-
---- /dev/null
-+++ b/Documentation/usb/mass-storage.txt
-@@ -0,0 +1,226 @@
-+* Overview
-+
-+ Mass Storage Gadget (or MSG) acts as a USB Mass Storage device,
-+ appearing to the host as a disk or a CD-ROM drive. It supports
-+ multiple logical units (LUNs). Backing storage for each LUN is
-+ provided by a regular file or a block device, access can be limited
-+ to read-only, and gadget can indicate that it is removable and/or
-+ CD-ROM (the latter implies read-only access).
-+
-+ Its requirements are modest; only a bulk-in and a bulk-out endpoint
-+ are needed. The memory requirement amounts to two 16K buffers.
-+ Support is included for full-speed, high-speed and SuperSpeed
-+ operation.
-+
-+ Note that the driver is slightly non-portable in that it assumes
-+ a single memory/DMA buffer will be useable for bulk-in and bulk-out
-+ endpoints. With most device controllers this is not an issue, but
-+ there may be some with hardware restrictions that prevent a buffer
-+ from being used by more than one endpoint.
-+
-+ This document describes how to use the gadget from user space, its
-+ relation to mass storage function (or MSF) and different gadgets
-+ using it, and how it differs from File Storage Gadget (or FSG). It
-+ will talk only briefly about how to use MSF within composite
-+ gadgets.
-+
-+* Module parameters
-+
-+ The mass storage gadget accepts the following mass storage specific
-+ module parameters:
-+
-+ - file=filename[,filename...]
-+
-+ This parameter lists paths to files or block devices used for
-+ backing storage for each logical unit. There may be at most
-+ FSG_MAX_LUNS (8) LUNs set. If more files are specified, they will
-+ be silently ignored. See also “luns” parameter.
-+
-+ *BEWARE* that if a file is used as a backing storage, it may not
-+ be modified by any other process. This is because the host
-+ assumes the data does not change without its knowledge. It may be
-+ read, but (if the logical unit is writable) due to buffering on
-+ the host side, the contents are not well defined.
-+
-+ The size of the logical unit will be rounded down to a full
-+ logical block. The logical block size is 2048 bytes for LUNs
-+ simulating CD-ROM, block size of the device if the backing file is
-+ a block device, or 512 bytes otherwise.
-+
-+ - removable=b[,b...]
-+
-+ This parameter specifies whether each logical unit should be
-+ removable. “b” here is either “y”, “Y” or “1” for true or “n”,
-+ “N” or “0” for false.
-+
-+ If this option is set for a logical unit, gadget will accept an
-+ “eject” SCSI request (Start/Stop Unit). When it is sent, the
-+ backing file will be closed to simulate ejection and the logical
-+ unit will not be mountable by the host until a new backing file is
-+ specified by userspace on the device (see “sysfs entries”
-+ section).
-+
-+ If a logical unit is not removable (the default), a backing file
-+ must be specified for it with the “file” parameter as the module
-+ is loaded. The same applies if the module is built in, no
-+ exceptions.
-+
-+ The default value of the flag is false, *HOWEVER* it used to be
-+ true. This has been changed to better match File Storage Gadget
-+ and because it seems like a saner default after all. Thus to
-+ maintain compatibility with older kernels, it's best to specify
-+ the default values. Also, if one relied on old default, explicit
-+ “n” needs to be specified now.
-+
-+ Note that “removable” means the logical unit's media can be
-+ ejected or removed (as is true for a CD-ROM drive or a card
-+ reader). It does *not* mean that the entire gadget can be
-+ unplugged from the host; the proper term for that is
-+ “hot-unpluggable”.
-+
-+ - cdrom=b[,b...]
-+
-+ This parameter specifies whether each logical unit should simulate
-+ CD-ROM. The default is false.
-+
-+ - ro=b[,b...]
-+
-+ This parameter specifies whether each logical unit should be
-+ reported as read only. This will prevent host from modifying the
-+ backing files.
-+
-+ Note that if this flag for given logical unit is false but the
-+ backing file could not be opened in read/write mode, the gadget
-+ will fall back to read only mode anyway.
-+
-+ The default value for non-CD-ROM logical units is false; for
-+ logical units simulating CD-ROM it is forced to true.
-+
-+ - nofua=b[,b...]
-+
-+ This parameter specifies whether FUA flag should be ignored in SCSI
-+ Write10 and Write12 commands sent to given logical units.
-+
-+ MS Windows mounts removable storage in “Removal optimised mode” by
-+ default. All the writes to the media are synchronous, which is
-+ achieved by setting the FUA (Force Unit Access) bit in SCSI
-+ Write(10,12) commands. This forces each write to wait until the
-+ data has actually been written out and prevents I/O requests
-+ aggregation in block layer dramatically decreasing performance.
-+
-+ Note that this may mean that if the device is powered from USB and
-+ the user unplugs the device without unmounting it first (which at
-+ least some Windows users do), the data may be lost.
-+
-+ The default value is false.
-+
-+ - luns=N
-+
-+ This parameter specifies number of logical units the gadget will
-+ have. It is limited by FSG_MAX_LUNS (8) and higher value will be
-+ capped.
-+
-+ If this parameter is provided, and the number of files specified
-+ in “file” argument is greater then the value of “luns”, all excess
-+ files will be ignored.
-+
-+ If this parameter is not present, the number of logical units will
-+ be deduced from the number of files specified in the “file”
-+ parameter. If the file parameter is missing as well, one is
-+ assumed.
-+
-+ - stall=b
-+
-+ Specifies whether the gadget is allowed to halt bulk endpoints.
-+ The default is determined according to the type of USB device
-+ controller, but usually true.
-+
-+ In addition to the above, the gadget also accepts the following
-+ parameters defined by the composite framework (they are common to
-+ all composite gadgets so just a quick listing):
-+
-+ - idVendor -- USB Vendor ID (16 bit integer)
-+ - idProduct -- USB Product ID (16 bit integer)
-+ - bcdDevice -- USB Device version (BCD) (16 bit integer)
-+ - iManufacturer -- USB Manufacturer string (string)
-+ - iProduct -- USB Product string (string)
-+ - iSerialNumber -- SerialNumber string (sting)
-+
-+* sysfs entries
-+
-+ For each logical unit, the gadget creates a directory in the sysfs
-+ hierarchy. Inside of it the following three files are created:
-+
-+ - file
-+
-+ When read it returns the path to the backing file for the given
-+ logical unit. If there is no backing file (possible only if the
-+ logical unit is removable), the content is empty.
-+
-+ When written into, it changes the backing file for given logical
-+ unit. This change can be performed even if given logical unit is
-+ not specified as removable (but that may look strange to the
-+ host). It may fail, however, if host disallowed medium removal
-+ with the Prevent-Allow Medium Removal SCSI command.
-+
-+ - ro
-+
-+ Reflects the state of ro flag for the given logical unit. It can
-+ be read any time, and written to when there is no backing file
-+ open for given logical unit.
-+
-+ - nofua
-+
-+ Reflects the state of nofua flag for given logical unit. It can
-+ be read and written.
-+
-+ Other then those, as usual, the values of module parameters can be
-+ read from /sys/module/g_mass_storage/parameters/* files.
-+
-+* Other gadgets using mass storage function
-+
-+ The Mass Storage Gadget uses the Mass Storage Function to handle
-+ mass storage protocol. As a composite function, MSF may be used by
-+ other gadgets as well (eg. g_multi and acm_ms).
-+
-+ All of the information in previous sections are valid for other
-+ gadgets using MSF, except that support for mass storage related
-+ module parameters may be missing, or the parameters may have
-+ a prefix. To figure out whether any of this is true one needs to
-+ consult the gadget's documentation or its source code.
-+
-+ For examples of how to include mass storage function in gadgets, one
-+ may take a look at mass_storage.c, acm_ms.c and multi.c (sorted by
-+ complexity).
-+
-+* Relation to file storage gadget
-+
-+ The Mass Storage Function and thus the Mass Storage Gadget has been
-+ based on the File Storage Gadget. The difference between the two is
-+ that MSG is a composite gadget (ie. uses the composite framework)
-+ while file storage gadget is a traditional gadget. From userspace
-+ point of view this distinction does not really matter, but from
-+ kernel hacker's point of view, this means that (i) MSG does not
-+ duplicate code needed for handling basic USB protocol commands and
-+ (ii) MSF can be used in any other composite gadget.
-+
-+ Because of that, File Storage Gadget has been deprecated and
-+ scheduled to be removed in Linux 3.8. All users need to transition
-+ to the Mass Storage Gadget by that time. The two gadgets behave
-+ mostly the same from the outside except:
-+
-+ 1. In FSG the “removable” and “cdrom” module parameters set the flag
-+ for all logical units whereas in MSG they accept a list of y/n
-+ values for each logical unit. If one uses only a single logical
-+ unit this does not matter, but if there are more, the y/n value
-+ needs to be repeated for each logical unit.
-+
-+ 2. FSG's “serial”, “vendor”, “product” and “release” module
-+ parameters are handled in MSG by the composite layer's parameters
-+ named respectively: “iSerialnumber”, “idVendor”, “idProduct” and
-+ “bcdDevice”.
-+
-+ 3. MSG does not support FSG's test mode, thus “transport”,
-+ “protocol” and “buflen” FSG's module parameters are not
-+ supported. MSG always uses SCSI protocol with bulk only
-+ transport mode and 16 KiB buffers.
---- a/drivers/usb/gadget/f_mass_storage.c
-+++ b/drivers/usb/gadget/f_mass_storage.c
-@@ -44,12 +44,12 @@
- * function for a USB device, it also illustrates a technique of
- * double-buffering for increased throughput.
- *
-- * Function supports multiple logical units (LUNs). Backing storage
-- * for each LUN is provided by a regular file or a block device.
-- * Access for each LUN can be limited to read-only. Moreover, the
-- * function can indicate that LUN is removable and/or CD-ROM. (The
-- * later implies read-only access.)
-- *
-+ * For more information about MSF and in particular its module
-+ * parameters and sysfs interface read the
-+ * <Documentation/usb/mass-storage.txt> file.
-+ */
-+
-+/*
- * MSF is configured by specifying a fsg_config structure. It has the
- * following fields:
- *
-@@ -95,61 +95,6 @@
- * data track and no audio tracks; hence there need be only one
- * backing file per LUN.
- *
-- *
-- * MSF includes support for module parameters. If gadget using it
-- * decides to use it, the following module parameters will be
-- * available:
-- *
-- * file=filename[,filename...]
-- * Names of the files or block devices used for
-- * backing storage.
-- * ro=b[,b...] Default false, boolean for read-only access.
-- * removable=b[,b...]
-- * Default false, boolean for removable media.
-- * cdrom=b[,b...] Default false, boolean for whether to emulate
-- * a CD-ROM drive.
-- * nofua=b[,b...] Default false, booleans for ignore FUA flag
-- * in SCSI WRITE(10,12) commands
-- * luns=N Default N = number of filenames, number of
-- * LUNs to support.
-- * stall Default determined according to the type of
-- * USB device controller (usually true),
-- * boolean to permit the driver to halt
-- * bulk endpoints.
-- *
-- * The module parameters may be prefixed with some string. You need
-- * to consult gadget's documentation or source to verify whether it is
-- * using those module parameters and if it does what are the prefixes
-- * (look for FSG_MODULE_PARAMETERS() macro usage, what's inside it is
-- * the prefix).
-- *
-- *
-- * Requirements are modest; only a bulk-in and a bulk-out endpoint are
-- * needed. The memory requirement amounts to two 16K buffers, size
-- * configurable by a parameter. Support is included for both
-- * full-speed and high-speed operation.
-- *
-- * Note that the driver is slightly non-portable in that it assumes a
-- * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
-- * interrupt-in endpoints. With most device controllers this isn't an
-- * issue, but there may be some with hardware restrictions that prevent
-- * a buffer from being used by more than one endpoint.
-- *
-- *
-- * The pathnames of the backing files, the ro settings and nofua
-- * settings are available in the attribute files "file", "ro" and
-- * "nofua" in the lun<n> subdirectory of the gadget's sysfs directory.
-- * If the "removable" option is set, writing to these files will
-- * simulate ejecting/loading the medium (writing an empty line means
-- * eject) and adjusting a write-enable tab. Changes to the ro setting
-- * are not allowed when the medium is loaded or if CD-ROM emulation is
-- * being used.
-- *
-- * When a LUN receive an "eject" SCSI request (Start/Stop Unit),
-- * if the LUN is removable, the backing file is released to simulate
-- * ejection.
-- *
-- *
- * This function is heavily based on "File-backed Storage Gadget" by
- * Alan Stern which in turn is heavily based on "Gadget Zero" by David
- * Brownell. The driver's SCSI command interface was based on the
-@@ -191,7 +136,7 @@
- * In normal operation the main thread is started during the gadget's
- * fsg_bind() callback and stopped during fsg_unbind(). But it can
- * also exit when it receives a signal, and there's no point leaving
-- * the gadget running when the thread is dead. At of this moment, MSF
-+ * the gadget running when the thread is dead. As of this moment, MSF
- * provides no way to deregister the gadget when thread dies -- maybe
- * a callback functions is needed.
- *
+++ /dev/null
-From dq-thang@jinso.co.jp Sun Feb 17 18:06:37 2013
-From: Do Quang Thang <dq-thang@jinso.co.jp>
-Date: Mon, 18 Feb 2013 11:05:38 +0900
-Subject: usb: gadget: mass_storage: fail fsg_store_file() early if colud not open file
-To: Greg KH <greg@kroah.com>
-Cc: ltsi-dev@lists.linuxfoundation.org
-Message-ID: <1361153138-5365-8-git-send-email-dq-thang@jinso.co.jp>
-
-
-From: Michal Nazarewicz <mina86@mina86.com>
-
-Currently, when a new value is stored to the “file” sysfs entry,
-fsg_store_file() will release existing backing file and only then attempt to
-open a new one. If that fails, no new backing file is open.
-
-This commit changes the fsg_lun_open() so that it closes existing backing file
-only after the new backing file has been successfully opened. With that
-change, fsg_store_file() may use it to perform an atomic open operation with
-guarantee that logical unit will either point to the new backing file or still
-to the old one.
-
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Acked-by: Alan Stern <stern@rowland.harvard.edu
-Signed-off-by: Felipe Balbi <balbi@ti.com>
-(cherry picked from commit d6e16a89578fcc8834be634c85c5c5ddc2d13229)
-
-Signed-off-by: Do Quang Thang <dq-thang@jinso.co.jp>
----
- drivers/usb/gadget/storage_common.c | 52 ++++++++++++++++++++----------------
- 1 file changed, 29 insertions(+), 23 deletions(-)
-
---- a/drivers/usb/gadget/storage_common.c
-+++ b/drivers/usb/gadget/storage_common.c
-@@ -617,6 +617,16 @@ static struct usb_gadget_strings fsg_str
- * the caller must own fsg->filesem for writing.
- */
-
-+static void fsg_lun_close(struct fsg_lun *curlun)
-+{
-+ if (curlun->filp) {
-+ LDBG(curlun, "close backing file\n");
-+ fput(curlun->filp);
-+ curlun->filp = NULL;
-+ }
-+}
-+
-+
- static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
- {
- int ro;
-@@ -626,6 +636,8 @@ static int fsg_lun_open(struct fsg_lun *
- loff_t size;
- loff_t num_sectors;
- loff_t min_sectors;
-+ unsigned int blkbits;
-+ unsigned int blksize;
-
- /* R/W if we can, R/O if we must */
- ro = curlun->initially_ro;
-@@ -670,17 +682,17 @@ static int fsg_lun_open(struct fsg_lun *
- }
-
- if (curlun->cdrom) {
-- curlun->blksize = 2048;
-- curlun->blkbits = 11;
-+ blksize = 2048;
-+ blkbits = 11;
- } else if (inode->i_bdev) {
-- curlun->blksize = bdev_logical_block_size(inode->i_bdev);
-- curlun->blkbits = blksize_bits(curlun->blksize);
-+ blksize = bdev_logical_block_size(inode->i_bdev);
-+ blkbits = blksize_bits(blksize);
- } else {
-- curlun->blksize = 512;
-- curlun->blkbits = 9;
-+ blksize = 512;
-+ blkbits = 9;
- }
-
-- num_sectors = size >> curlun->blkbits; /* File size in logic-block-size blocks */
-+ num_sectors = size >> blkbits; /* File size in logic-block-size blocks */
- min_sectors = 1;
- if (curlun->cdrom) {
- min_sectors = 300; /* Smallest track is 300 frames */
-@@ -697,7 +709,12 @@ static int fsg_lun_open(struct fsg_lun *
- goto out;
- }
-
-+ if (fsg_lun_is_open(curlun))
-+ fsg_lun_close(curlun);
-+
- get_file(filp);
-+ curlun->blksize = blksize;
-+ curlun->blkbits = blkbits;
- curlun->ro = ro;
- curlun->filp = filp;
- curlun->file_length = size;
-@@ -711,16 +728,6 @@ out:
- }
-
-
--static void fsg_lun_close(struct fsg_lun *curlun)
--{
-- if (curlun->filp) {
-- LDBG(curlun, "close backing file\n");
-- fput(curlun->filp);
-- curlun->filp = NULL;
-- }
--}
--
--
- /*-------------------------------------------------------------------------*/
-
- /*
-@@ -871,19 +878,18 @@ static ssize_t fsg_store_file(struct dev
- if (count > 0 && buf[count-1] == '\n')
- ((char *) buf)[count-1] = 0; /* Ugh! */
-
-- /* Eject current medium */
-- down_write(filesem);
-- if (fsg_lun_is_open(curlun)) {
-- fsg_lun_close(curlun);
-- curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
-- }
-
- /* Load new medium */
-+ down_write(filesem);
- if (count > 0 && buf[0]) {
-+ /* fsg_lun_open() will close existing file if any. */
- rc = fsg_lun_open(curlun, buf);
- if (rc == 0)
- curlun->unit_attention_data =
- SS_NOT_READY_TO_READY_TRANSITION;
-+ } else if (fsg_lun_is_open(curlun)) {
-+ fsg_lun_close(curlun);
-+ curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
- }
- up_write(filesem);
- return (rc < 0 ? rc : count);
+++ /dev/null
-From dq-thang@jinso.co.jp Sun Feb 17 18:40:19 2013
-From: Do Quang Thang <dq-thang@jinso.co.jp>
-Date: Mon, 18 Feb 2013 11:40:10 +0900
-Subject: usb: gadget: mass_storage: make "file" and "ro" read only in some cases
-To: Greg KH <greg@kroah.com>
-Cc: ltsi-dev@lists.linuxfoundation.org
-Message-ID: <1361155210-5674-1-git-send-email-dq-thang@jinso.co.jp>
-
-
-From: Michal Nazarewicz <mina86@mina86.com>
-
-The “file” sysfs entry for LUNs was writable even for non-removable
-LUNs and the fsg_store_file() function did not check whether LUN is
-removable or not. This made it possible to change or even close
-LUN's backing file.
-
-The same is true for “ro” sysfs entry and LUNs simulating CD-ROM.
-For those LUNs, the file should not be writable.
-
-This commit introduces two new device_attribute structures for those
-two special cases so that the file/ro sysfs entries are made
-non-writable when not desired.
-
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Signed-off-by: Felipe Balbi <balbi@ti.com>
-(cherry picked from commit 48a31af74404e6460eabca410bf0b4a625bfd372)
-
-Signed-off-by: Do Quang Thang <dq-thang@jinso.co.jp>
----
- drivers/usb/gadget/f_mass_storage.c | 26 +++++++++++++++++++++-----
- drivers/usb/gadget/storage_common.c | 1 -
- 2 files changed, 21 insertions(+), 6 deletions(-)
-
---- a/drivers/usb/gadget/f_mass_storage.c
-+++ b/drivers/usb/gadget/f_mass_storage.c
-@@ -2609,11 +2609,15 @@ static int fsg_main_thread(void *common_
-
- /*************************** DEVICE ATTRIBUTES ***************************/
-
--/* Write permission is checked per LUN in store_*() functions. */
- static DEVICE_ATTR(ro, 0644, fsg_show_ro, fsg_store_ro);
- static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, fsg_store_nofua);
- static DEVICE_ATTR(file, 0644, fsg_show_file, fsg_store_file);
-
-+static struct device_attribute dev_attr_ro_cdrom =
-+ __ATTR(ro, 0444, fsg_show_ro, NULL);
-+static struct device_attribute dev_attr_file_nonremovable =
-+ __ATTR(file, 0444, fsg_show_file, NULL);
-+
-
- /****************************** FSG COMMON ******************************/
-
-@@ -2724,10 +2728,16 @@ static struct fsg_common *fsg_common_ini
- goto error_release;
- }
-
-- rc = device_create_file(&curlun->dev, &dev_attr_ro);
-+ rc = device_create_file(&curlun->dev,
-+ curlun->cdrom
-+ ? &dev_attr_ro_cdrom
-+ : &dev_attr_ro);
- if (rc)
- goto error_luns;
-- rc = device_create_file(&curlun->dev, &dev_attr_file);
-+ rc = device_create_file(&curlun->dev,
-+ curlun->removable
-+ ? &dev_attr_file
-+ : &dev_attr_file_nonremovable);
- if (rc)
- goto error_luns;
- rc = device_create_file(&curlun->dev, &dev_attr_nofua);
-@@ -2862,8 +2872,14 @@ static void fsg_common_release(struct kr
- /* In error recovery common->nluns may be zero. */
- for (; i; --i, ++lun) {
- device_remove_file(&lun->dev, &dev_attr_nofua);
-- device_remove_file(&lun->dev, &dev_attr_ro);
-- device_remove_file(&lun->dev, &dev_attr_file);
-+ device_remove_file(&lun->dev,
-+ lun->cdrom
-+ ? &dev_attr_ro_cdrom
-+ : &dev_attr_ro);
-+ device_remove_file(&lun->dev,
-+ lun->removable
-+ ? &dev_attr_file
-+ : &dev_attr_file_nonremovable);
- fsg_lun_close(lun);
- device_unregister(&lun->dev);
- }
---- a/drivers/usb/gadget/storage_common.c
-+++ b/drivers/usb/gadget/storage_common.c
-@@ -878,7 +878,6 @@ static ssize_t fsg_store_file(struct dev
- if (count > 0 && buf[count-1] == '\n')
- ((char *) buf)[count-1] = 0; /* Ugh! */
-
--
- /* Load new medium */
- down_write(filesem);
- if (count > 0 && buf[0]) {
+++ /dev/null
-From dq-thang@jinso.co.jp Sun Feb 17 18:09:16 2013
-From: Do Quang Thang <dq-thang@jinso.co.jp>
-Date: Mon, 18 Feb 2013 11:05:34 +0900
-Subject: usb: gadget: mass_storage: remove unused options
-To: Greg KH <greg@kroah.com>
-Cc: ltsi-dev@lists.linuxfoundation.org
-Message-ID: <1361153138-5365-4-git-send-email-dq-thang@jinso.co.jp>
-
-
-From: Michal Nazarewicz <mina86@mina86.com>
-
-This commit removes thread_name and lun_name_format fields from the
-fsg_config structure. Those fields are not used by any in-tree code
-and their usefulness is rather theoretical.
-
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Signed-off-by: Felipe Balbi <balbi@ti.com>
-(cherry picked from commit 1a12af1a751311e129ff8e8ca18f83613b78a83c)
-
-Signed-off-by: Do Quang Thang <dq-thang@jinso.co.jp>
----
- drivers/usb/gadget/f_mass_storage.c | 50 +++++++-----------------------------
- 1 file changed, 10 insertions(+), 40 deletions(-)
-
---- a/drivers/usb/gadget/f_mass_storage.c
-+++ b/drivers/usb/gadget/f_mass_storage.c
-@@ -75,25 +75,6 @@
- * ->nofua Flag specifying that FUA flag in SCSI WRITE(10,12)
- * commands for this LUN shall be ignored.
- *
-- * lun_name_format A printf-like format for names of the LUN
-- * devices. This determines how the
-- * directory in sysfs will be named.
-- * Unless you are using several MSFs in
-- * a single gadget (as opposed to single
-- * MSF in many configurations) you may
-- * leave it as NULL (in which case
-- * "lun%d" will be used). In the format
-- * you can use "%d" to index LUNs for
-- * MSF's with more than one LUN. (Beware
-- * that there is only one integer given
-- * as an argument for the format and
-- * specifying invalid format may cause
-- * unspecified behaviour.)
-- * thread_name Name of the kernel thread process used by the
-- * MSF. You can safely set it to NULL
-- * (in which case default "file-storage"
-- * will be used).
-- *
- * vendor_name
- * product_name
- * release Information used as a reply to INQUIRY
-@@ -155,15 +136,14 @@
- * a buffer from being used by more than one endpoint.
- *
- *
-- * The pathnames of the backing files and the ro settings are
-- * available in the attribute files "file" and "ro" in the lun<n> (or
-- * to be more precise in a directory which name comes from
-- * "lun_name_format" option!) subdirectory of the gadget's sysfs
-- * directory. If the "removable" option is set, writing to these
-- * files will simulate ejecting/loading the medium (writing an empty
-- * line means eject) and adjusting a write-enable tab. Changes to the
-- * ro setting are not allowed when the medium is loaded or if CD-ROM
-- * emulation is being used.
-+ * The pathnames of the backing files, the ro settings and nofua
-+ * settings are available in the attribute files "file", "ro" and
-+ * "nofua" in the lun<n> subdirectory of the gadget's sysfs directory.
-+ * If the "removable" option is set, writing to these files will
-+ * simulate ejecting/loading the medium (writing an empty line means
-+ * eject) and adjusting a write-enable tab. Changes to the ro setting
-+ * are not allowed when the medium is loaded or if CD-ROM emulation is
-+ * being used.
- *
- * When a LUN receive an "eject" SCSI request (Start/Stop Unit),
- * if the LUN is removable, the backing file is released to simulate
-@@ -417,9 +397,6 @@ struct fsg_config {
- char nofua;
- } luns[FSG_MAX_LUNS];
-
-- const char *lun_name_format;
-- const char *thread_name;
--
- /* Callback functions. */
- const struct fsg_operations *ops;
- /* Gadget's private data. */
-@@ -2792,11 +2769,7 @@ static struct fsg_common *fsg_common_ini
- curlun->dev.parent = &gadget->dev;
- /* curlun->dev.driver = &fsg_driver.driver; XXX */
- dev_set_drvdata(&curlun->dev, &common->filesem);
-- dev_set_name(&curlun->dev,
-- cfg->lun_name_format
-- ? cfg->lun_name_format
-- : "lun%d",
-- i);
-+ dev_set_name(&curlun->dev, "lun%d", i);
-
- rc = device_register(&curlun->dev);
- if (rc) {
-@@ -2878,8 +2851,7 @@ buffhds_first_it:
-
- /* Tell the thread to start working */
- common->thread_task =
-- kthread_create(fsg_main_thread, common,
-- cfg->thread_name ?: "file-storage");
-+ kthread_create(fsg_main_thread, common, "file-storage");
- if (IS_ERR(common->thread_task)) {
- rc = PTR_ERR(common->thread_task);
- goto error_release;
-@@ -3182,8 +3154,6 @@ fsg_config_from_params(struct fsg_config
- }
-
- /* Let MSF use defaults */
-- cfg->lun_name_format = 0;
-- cfg->thread_name = 0;
- cfg->vendor_name = 0;
- cfg->product_name = 0;
- cfg->release = 0xffff;
+++ /dev/null
-From dq-thang@jinso.co.jp Sun Feb 17 18:07:09 2013
-From: Do Quang Thang <dq-thang@jinso.co.jp>
-Date: Mon, 18 Feb 2013 11:05:37 +0900
-Subject: usb: gadget: storage_common: remove FSG_BUFFHD_STATIC_BUFFER support
-To: Greg KH <greg@kroah.com>
-Cc: ltsi-dev@lists.linuxfoundation.org
-Message-ID: <1361153138-5365-7-git-send-email-dq-thang@jinso.co.jp>
-
-
-From: Michal Nazarewicz <mina86@mina86.com>
-
-Since f_mass_storage stopped using FSG_BUFFHD_STATIC_BUFFER (because it
-caused buffers not to be page aligned which did not work well with at
-least some UDCs), no code was using it. Removing not to bloat the code
-too much.
-
-Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
-Signed-off-by: Felipe Balbi <balbi@ti.com>
-(cherry picked from commit f87cabf4d56e1fc5d08434df9d54ef3450a756f0)
-
-Signed-off-by: Do Quang Thang <dq-thang@jinso.co.jp>
----
- drivers/usb/gadget/storage_common.c | 10 ----------
- 1 file changed, 10 deletions(-)
-
---- a/drivers/usb/gadget/storage_common.c
-+++ b/drivers/usb/gadget/storage_common.c
-@@ -38,12 +38,6 @@
- */
-
- /*
-- * When FSG_BUFFHD_STATIC_BUFFER is defined when this file is included
-- * the fsg_buffhd structure's buf field will be an array of FSG_BUFLEN
-- * characters rather then a pointer to void.
-- */
--
--/*
- * When USB_GADGET_DEBUG_FILES is defined the module param num_buffers
- * sets the number of pipeline buffers (length of the fsg_buffhd array).
- * The valid range of num_buffers is: num >= 2 && num <= 4.
-@@ -260,11 +254,7 @@ enum fsg_buffer_state {
- };
-
- struct fsg_buffhd {
--#ifdef FSG_BUFFHD_STATIC_BUFFER
-- char buf[FSG_BUFLEN];
--#else
- void *buf;
--#endif
- enum fsg_buffer_state state;
- struct fsg_buffhd *next;
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:30:37 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:18 +0900
-Subject: [PATCH 26/26] ARM: mach-shmobile: Fix build when SMP is enabled and EMEV2 is not enabled
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-27-git-send-email-koba@kmckk.co.jp>
-
-
-From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
-
-Build failed, when SMP is enabled and EMEV2 is not enabled.
-
-arch/arm/mach-shmobile/built-in.o: In function `shmobile_platform_cpu_kill':
-/home/iwamatsu/work/kernel/sh-2.6-devel/arch/arm/mach-shmobile/platsmp.c:62: undefined reference to `emev2_platform_cpu_kill'
-arch/arm/mach-shmobile/built-in.o: In function `shmobile_smp_get_core_count':
-/home/iwamatsu/work/kernel/sh-2.6-devel/arch/arm/mach-shmobile/platsmp.c:39: undefined reference to `emev2_get_core_count'
-arch/arm/mach-shmobile/built-in.o: In function `shmobile_smp_prepare_cpus':
-/home/iwamatsu/work/kernel/sh-2.6-devel/arch/arm/mach-shmobile/platsmp.c:53: undefined reference to `emev2_smp_prepare_cpus'
-arch/arm/mach-shmobile/built-in.o: In function `platform_secondary_init':
-/home/iwamatsu/work/kernel/sh-2.6-devel/arch/arm/mach-shmobile/platsmp.c:78: undefined reference to `emev2_secondary_init'
-arch/arm/mach-shmobile/built-in.o: In function `boot_secondary':
-/home/iwamatsu/work/kernel/sh-2.6-devel/arch/arm/mach-shmobile/platsmp.c:90: undefined reference to `emev2_boot_secondary
-
-This is the cause by when EMEV2 is disabled, that the check by OF of EMEV2 is
-performed in platsmp.c.
-This patch revise what the function about EMEV2 may not be used in this file,
-when EMEV2 is not enabled.
-
-Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
-Acked-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 6ae42bb22b40254e6488bbfe47f970620ab6d433)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/platsmp.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/arch/arm/mach-shmobile/platsmp.c
-+++ b/arch/arm/mach-shmobile/platsmp.c
-@@ -30,7 +30,12 @@
- #endif
-
- #define is_r8a7779() machine_is_marzen()
-+
-+#ifdef CONFIG_ARCH_EMEV2
- #define is_emev2() of_machine_is_compatible("renesas,emev2")
-+#else
-+#define is_emev2() (0)
-+#endif
-
- static unsigned int __init shmobile_smp_get_core_count(void)
- {
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:30:14 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:15 +0900
-Subject: [PATCH 23/26] ARM: mach-shmobile: kzm9d: Add defconfig
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-24-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-Original work by Magnus Damm, tested and tweaked by Simon Horman
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Simon Horman <horms@verge.net.au>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit d252f644789188743b55339f5756a8bcc86fbaa5)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/configs/kzm9d_defconfig | 89 ++++++++++++++++++++++++++++++++++++++
- 1 file changed, 89 insertions(+)
- create mode 100644 arch/arm/configs/kzm9d_defconfig
-
-diff --git a/arch/arm/configs/kzm9d_defconfig b/arch/arm/configs/kzm9d_defconfig
-new file mode 100644
-index 0000000..26146ff
---- /dev/null
-+++ b/arch/arm/configs/kzm9d_defconfig
-@@ -0,0 +1,89 @@
-+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
-+CONFIG_EXPERIMENTAL=y
-+CONFIG_SYSVIPC=y
-+CONFIG_NO_HZ=y
-+CONFIG_IKCONFIG=y
-+CONFIG_IKCONFIG_PROC=y
-+CONFIG_LOG_BUF_SHIFT=16
-+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-+CONFIG_SYSCTL_SYSCALL=y
-+CONFIG_EMBEDDED=y
-+CONFIG_SLAB=y
-+# CONFIG_BLK_DEV_BSG is not set
-+# CONFIG_IOSCHED_DEADLINE is not set
-+# CONFIG_IOSCHED_CFQ is not set
-+CONFIG_ARCH_SHMOBILE=y
-+CONFIG_ARCH_EMEV2=y
-+CONFIG_MACH_KZM9D=y
-+CONFIG_MEMORY_START=0x40000000
-+CONFIG_MEMORY_SIZE=0x10000000
-+# CONFIG_SH_TIMER_TMU is not set
-+# CONFIG_SWP_EMULATE is not set
-+# CONFIG_CACHE_L2X0 is not set
-+CONFIG_SMP=y
-+CONFIG_NR_CPUS=2
-+CONFIG_HOTPLUG_CPU=y
-+# CONFIG_LOCAL_TIMERS is not set
-+CONFIG_AEABI=y
-+# CONFIG_OABI_COMPAT is not set
-+# CONFIG_CROSS_MEMORY_ATTACH is not set
-+CONFIG_FORCE_MAX_ZONEORDER=13
-+CONFIG_ZBOOT_ROM_TEXT=0x0
-+CONFIG_ZBOOT_ROM_BSS=0x0
-+CONFIG_ARM_APPENDED_DTB=y
-+CONFIG_CMDLINE="console=tty0 console=ttyS1,115200n81 earlyprintk=serial8250-em.1,115200n81 mem=128M@0x40000000 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096"
-+CONFIG_CMDLINE_FORCE=y
-+CONFIG_VFP=y
-+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-+# CONFIG_SUSPEND is not set
-+CONFIG_NET=y
-+CONFIG_PACKET=y
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-+# CONFIG_INET_XFRM_MODE_BEET is not set
-+# CONFIG_INET_LRO is not set
-+# CONFIG_INET_DIAG is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_WIRELESS is not set
-+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-+# CONFIG_BLK_DEV is not set
-+CONFIG_NETDEVICES=y
-+# CONFIG_NET_VENDOR_BROADCOM is not set
-+# CONFIG_NET_VENDOR_CHELSIO is not set
-+# CONFIG_NET_VENDOR_CIRRUS is not set
-+# CONFIG_NET_VENDOR_FARADAY is not set
-+# CONFIG_NET_VENDOR_INTEL is not set
-+# CONFIG_NET_VENDOR_MARVELL is not set
-+# CONFIG_NET_VENDOR_MICREL is not set
-+# CONFIG_NET_VENDOR_NATSEMI is not set
-+# CONFIG_NET_VENDOR_SEEQ is not set
-+CONFIG_SMSC911X=y
-+# CONFIG_NET_VENDOR_STMICRO is not set
-+# CONFIG_NET_VENDOR_WIZNET is not set
-+# CONFIG_WLAN is not set
-+# CONFIG_INPUT_MOUSEDEV 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_8250=y
-+CONFIG_SERIAL_8250_CONSOLE=y
-+CONFIG_SERIAL_8250_EM=y
-+# CONFIG_HW_RANDOM is not set
-+CONFIG_GPIOLIB=y
-+CONFIG_GPIO_EM=y
-+# CONFIG_HWMON is not set
-+# CONFIG_HID_SUPPORT is not set
-+# CONFIG_USB_SUPPORT is not set
-+# CONFIG_IOMMU_SUPPORT is not set
-+# CONFIG_DNOTIFY is not set
-+CONFIG_TMPFS=y
-+# CONFIG_MISC_FILESYSTEMS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_ROOT_NFS=y
-+# CONFIG_FTRACE is not set
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:27:56 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:04 +0900
-Subject: [PATCH 12/26] clockevents: Make clockevents_config() a global symbol
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Magnus Damm <magnus.damm@gmail.com>, arnd@arndb.de, johnstul@us.ibm.com, rjw@sisk.pl, lethal@linux-sh.org, gregkh@linuxfoundation.org, olof@lixom.net, Thomas Gleixner <tglx@linutronix.de>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-13-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <magnus.damm@gmail.com>
-
-Make clockevents_config() into a global symbol to allow it to be used
-by compiled-in clockevent drivers. This is needed by drivers that want
-to update the timer frequency after registration time.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Tested-by: Simon Horman <horms@verge.net.au>
-Cc: arnd@arndb.de
-Cc: johnstul@us.ibm.com
-Cc: rjw@sisk.pl
-Cc: lethal@linux-sh.org
-Cc: gregkh@linuxfoundation.org
-Cc: olof@lixom.net
-Cc: Magnus Damm <magnus.damm@gmail.com>
-Link: http://lkml.kernel.org/r/20120509143934.27521.46553.sendpatchset@w520
-Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-(cherry picked from commit e5400321a6f15ce0fe77c8455954f213ef7dcc54)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- include/linux/clockchips.h | 1 +
- kernel/time/clockevents.c | 3 +--
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
-index 81e803e..acba8943 100644
---- a/include/linux/clockchips.h
-+++ b/include/linux/clockchips.h
-@@ -132,6 +132,7 @@ extern u64 clockevent_delta2ns(unsigned long latch,
- struct clock_event_device *evt);
- extern void clockevents_register_device(struct clock_event_device *dev);
-
-+extern void clockevents_config(struct clock_event_device *dev, u32 freq);
- extern void clockevents_config_and_register(struct clock_event_device *dev,
- u32 freq, unsigned long min_delta,
- unsigned long max_delta);
-diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
-index 9cd928f..7e1ce01 100644
---- a/kernel/time/clockevents.c
-+++ b/kernel/time/clockevents.c
-@@ -297,8 +297,7 @@ void clockevents_register_device(struct clock_event_device *dev)
- }
- EXPORT_SYMBOL_GPL(clockevents_register_device);
-
--static void clockevents_config(struct clock_event_device *dev,
-- u32 freq)
-+void clockevents_config(struct clock_event_device *dev, u32 freq)
- {
- u64 sec;
-
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:28:36 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:06 +0900
-Subject: [PATCH 14/26] clocksource: em_sti: Add DT support
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Magnus Damm <magnus.damm@gmail.com>, arnd@arndb.de, johnstul@us.ibm.com, rjw@sisk.pl, lethal@linux-sh.org, gregkh@linuxfoundation.org, olof@lixom.net, Thomas Gleixner <tglx@linutronix.de>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-15-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <magnus.damm@gmail.com>
-
-Update the em-sti driver to support DT.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Cc: arnd@arndb.de
-Cc: horms@verge.net.au
-Cc: johnstul@us.ibm.com
-Cc: rjw@sisk.pl
-Cc: lethal@linux-sh.org
-Cc: gregkh@linuxfoundation.org
-Cc: olof@lixom.net
-Link: http://lkml.kernel.org/r/20120509143950.27521.7949.sendpatchset@w520
-Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-(cherry picked from commit fc0830fe017d02b7b4995b5c402b484b65d9dfc6)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- drivers/clocksource/em_sti.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c
-index 719584a..372051d 100644
---- a/drivers/clocksource/em_sti.c
-+++ b/drivers/clocksource/em_sti.c
-@@ -384,11 +384,18 @@ static int __devexit em_sti_remove(struct platform_device *pdev)
- return -EBUSY; /* cannot unregister clockevent and clocksource */
- }
-
-+static const struct of_device_id em_sti_dt_ids[] __devinitconst = {
-+ { .compatible = "renesas,em-sti", },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, em_sti_dt_ids);
-+
- static struct platform_driver em_sti_device_driver = {
- .probe = em_sti_probe,
- .remove = __devexit_p(em_sti_remove),
- .driver = {
- .name = "em_sti",
-+ .of_match_table = em_sti_dt_ids,
- }
- };
-
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:28:15 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:05 +0900
-Subject: [PATCH 13/26] clocksource: em_sti: Emma Mobile STI driver
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Magnus Damm <magnus.damm@gmail.com>, arnd@arndb.de, johnstul@us.ibm.com, rjw@sisk.pl, lethal@linux-sh.org, gregkh@linuxfoundation.org, olof@lixom.net, Thomas Gleixner <tglx@linutronix.de>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-14-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <magnus.damm@gmail.com>
-
-The STI hardware is based on a single 48-bit 32kHz
-counter that together with two individual compare
-registers can generate interrupts. There are no
-timer operating modes selectable which means that
-the timer can not clear on match.
-
-This driver is providing clocksource support for the
-48-bit counter. Clockevents are also supported using
-the same timer in oneshot mode.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Cc: horms@verge.net.au
-Cc: arnd@arndb.de
-Cc: johnstul@us.ibm.com
-Cc: rjw@sisk.pl
-Cc: lethal@linux-sh.org
-Cc: gregkh@linuxfoundation.org
-Cc: olof@lixom.net
-Link: http://lkml.kernel.org/r/20120525070344.23443.69756.sendpatchset@w520
-Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-(cherry picked from commit b9dbf9517784084ee9496f9f17f9754c1d021a9e)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/Kconfig | 6
- drivers/clocksource/Makefile | 1
- drivers/clocksource/em_sti.c | 399 +++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 406 insertions(+)
- create mode 100644 drivers/clocksource/em_sti.c
-
---- a/arch/arm/mach-shmobile/Kconfig
-+++ b/arch/arm/mach-shmobile/Kconfig
-@@ -177,6 +177,12 @@ config SH_TIMER_TMU
- help
- This enables build of the TMU timer driver.
-
-+config EM_TIMER_STI
-+ bool "STI timer driver"
-+ default y
-+ help
-+ This enables build of the STI timer driver.
-+
- endmenu
-
- config SH_CLK_CPG
---- a/drivers/clocksource/Makefile
-+++ b/drivers/clocksource/Makefile
-@@ -6,6 +6,7 @@ obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC) +=
- obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o
- obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o
- obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o
-+obj-$(CONFIG_EM_TIMER_STI) += em_sti.o
- obj-$(CONFIG_CLKBLD_I8253) += i8253.o
- obj-$(CONFIG_CLKSRC_MMIO) += mmio.o
- obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o
---- /dev/null
-+++ b/drivers/clocksource/em_sti.c
-@@ -0,0 +1,399 @@
-+/*
-+ * Emma Mobile Timer Support - STI
-+ *
-+ * Copyright (C) 2012 Magnus Damm
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/platform_device.h>
-+#include <linux/spinlock.h>
-+#include <linux/interrupt.h>
-+#include <linux/ioport.h>
-+#include <linux/io.h>
-+#include <linux/clk.h>
-+#include <linux/irq.h>
-+#include <linux/err.h>
-+#include <linux/delay.h>
-+#include <linux/clocksource.h>
-+#include <linux/clockchips.h>
-+#include <linux/slab.h>
-+#include <linux/module.h>
-+
-+enum { USER_CLOCKSOURCE, USER_CLOCKEVENT, USER_NR };
-+
-+struct em_sti_priv {
-+ void __iomem *base;
-+ struct clk *clk;
-+ struct platform_device *pdev;
-+ unsigned int active[USER_NR];
-+ unsigned long rate;
-+ raw_spinlock_t lock;
-+ struct clock_event_device ced;
-+ struct clocksource cs;
-+};
-+
-+#define STI_CONTROL 0x00
-+#define STI_COMPA_H 0x10
-+#define STI_COMPA_L 0x14
-+#define STI_COMPB_H 0x18
-+#define STI_COMPB_L 0x1c
-+#define STI_COUNT_H 0x20
-+#define STI_COUNT_L 0x24
-+#define STI_COUNT_RAW_H 0x28
-+#define STI_COUNT_RAW_L 0x2c
-+#define STI_SET_H 0x30
-+#define STI_SET_L 0x34
-+#define STI_INTSTATUS 0x40
-+#define STI_INTRAWSTATUS 0x44
-+#define STI_INTENSET 0x48
-+#define STI_INTENCLR 0x4c
-+#define STI_INTFFCLR 0x50
-+
-+static inline unsigned long em_sti_read(struct em_sti_priv *p, int offs)
-+{
-+ return ioread32(p->base + offs);
-+}
-+
-+static inline void em_sti_write(struct em_sti_priv *p, int offs,
-+ unsigned long value)
-+{
-+ iowrite32(value, p->base + offs);
-+}
-+
-+static int em_sti_enable(struct em_sti_priv *p)
-+{
-+ int ret;
-+
-+ /* enable clock */
-+ ret = clk_enable(p->clk);
-+ if (ret) {
-+ dev_err(&p->pdev->dev, "cannot enable clock\n");
-+ return ret;
-+ }
-+
-+ /* configure channel, periodic mode and maximum timeout */
-+ p->rate = clk_get_rate(p->clk);
-+
-+ /* reset the counter */
-+ em_sti_write(p, STI_SET_H, 0x40000000);
-+ em_sti_write(p, STI_SET_L, 0x00000000);
-+
-+ /* mask and clear pending interrupts */
-+ em_sti_write(p, STI_INTENCLR, 3);
-+ em_sti_write(p, STI_INTFFCLR, 3);
-+
-+ /* enable updates of counter registers */
-+ em_sti_write(p, STI_CONTROL, 1);
-+
-+ return 0;
-+}
-+
-+static void em_sti_disable(struct em_sti_priv *p)
-+{
-+ /* mask interrupts */
-+ em_sti_write(p, STI_INTENCLR, 3);
-+
-+ /* stop clock */
-+ clk_disable(p->clk);
-+}
-+
-+static cycle_t em_sti_count(struct em_sti_priv *p)
-+{
-+ cycle_t ticks;
-+ unsigned long flags;
-+
-+ /* the STI hardware buffers the 48-bit count, but to
-+ * break it out into two 32-bit access the registers
-+ * must be accessed in a certain order.
-+ * Always read STI_COUNT_H before STI_COUNT_L.
-+ */
-+ raw_spin_lock_irqsave(&p->lock, flags);
-+ ticks = (cycle_t)(em_sti_read(p, STI_COUNT_H) & 0xffff) << 32;
-+ ticks |= em_sti_read(p, STI_COUNT_L);
-+ raw_spin_unlock_irqrestore(&p->lock, flags);
-+
-+ return ticks;
-+}
-+
-+static cycle_t em_sti_set_next(struct em_sti_priv *p, cycle_t next)
-+{
-+ unsigned long flags;
-+
-+ raw_spin_lock_irqsave(&p->lock, flags);
-+
-+ /* mask compare A interrupt */
-+ em_sti_write(p, STI_INTENCLR, 1);
-+
-+ /* update compare A value */
-+ em_sti_write(p, STI_COMPA_H, next >> 32);
-+ em_sti_write(p, STI_COMPA_L, next & 0xffffffff);
-+
-+ /* clear compare A interrupt source */
-+ em_sti_write(p, STI_INTFFCLR, 1);
-+
-+ /* unmask compare A interrupt */
-+ em_sti_write(p, STI_INTENSET, 1);
-+
-+ raw_spin_unlock_irqrestore(&p->lock, flags);
-+
-+ return next;
-+}
-+
-+static irqreturn_t em_sti_interrupt(int irq, void *dev_id)
-+{
-+ struct em_sti_priv *p = dev_id;
-+
-+ p->ced.event_handler(&p->ced);
-+ return IRQ_HANDLED;
-+}
-+
-+static int em_sti_start(struct em_sti_priv *p, unsigned int user)
-+{
-+ unsigned long flags;
-+ int used_before;
-+ int ret = 0;
-+
-+ raw_spin_lock_irqsave(&p->lock, flags);
-+ used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT];
-+ if (!used_before)
-+ ret = em_sti_enable(p);
-+
-+ if (!ret)
-+ p->active[user] = 1;
-+ raw_spin_unlock_irqrestore(&p->lock, flags);
-+
-+ return ret;
-+}
-+
-+static void em_sti_stop(struct em_sti_priv *p, unsigned int user)
-+{
-+ unsigned long flags;
-+ int used_before, used_after;
-+
-+ raw_spin_lock_irqsave(&p->lock, flags);
-+ used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT];
-+ p->active[user] = 0;
-+ used_after = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT];
-+
-+ if (used_before && !used_after)
-+ em_sti_disable(p);
-+ raw_spin_unlock_irqrestore(&p->lock, flags);
-+}
-+
-+static struct em_sti_priv *cs_to_em_sti(struct clocksource *cs)
-+{
-+ return container_of(cs, struct em_sti_priv, cs);
-+}
-+
-+static cycle_t em_sti_clocksource_read(struct clocksource *cs)
-+{
-+ return em_sti_count(cs_to_em_sti(cs));
-+}
-+
-+static int em_sti_clocksource_enable(struct clocksource *cs)
-+{
-+ int ret;
-+ struct em_sti_priv *p = cs_to_em_sti(cs);
-+
-+ ret = em_sti_start(p, USER_CLOCKSOURCE);
-+ if (!ret)
-+ __clocksource_updatefreq_hz(cs, p->rate);
-+ return ret;
-+}
-+
-+static void em_sti_clocksource_disable(struct clocksource *cs)
-+{
-+ em_sti_stop(cs_to_em_sti(cs), USER_CLOCKSOURCE);
-+}
-+
-+static void em_sti_clocksource_resume(struct clocksource *cs)
-+{
-+ em_sti_clocksource_enable(cs);
-+}
-+
-+static int em_sti_register_clocksource(struct em_sti_priv *p)
-+{
-+ struct clocksource *cs = &p->cs;
-+
-+ memset(cs, 0, sizeof(*cs));
-+ cs->name = dev_name(&p->pdev->dev);
-+ cs->rating = 200;
-+ cs->read = em_sti_clocksource_read;
-+ cs->enable = em_sti_clocksource_enable;
-+ cs->disable = em_sti_clocksource_disable;
-+ cs->suspend = em_sti_clocksource_disable;
-+ cs->resume = em_sti_clocksource_resume;
-+ cs->mask = CLOCKSOURCE_MASK(48);
-+ cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
-+
-+ dev_info(&p->pdev->dev, "used as clock source\n");
-+
-+ /* Register with dummy 1 Hz value, gets updated in ->enable() */
-+ clocksource_register_hz(cs, 1);
-+ return 0;
-+}
-+
-+static struct em_sti_priv *ced_to_em_sti(struct clock_event_device *ced)
-+{
-+ return container_of(ced, struct em_sti_priv, ced);
-+}
-+
-+static void em_sti_clock_event_mode(enum clock_event_mode mode,
-+ struct clock_event_device *ced)
-+{
-+ struct em_sti_priv *p = ced_to_em_sti(ced);
-+
-+ /* deal with old setting first */
-+ switch (ced->mode) {
-+ case CLOCK_EVT_MODE_ONESHOT:
-+ em_sti_stop(p, USER_CLOCKEVENT);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ switch (mode) {
-+ case CLOCK_EVT_MODE_ONESHOT:
-+ dev_info(&p->pdev->dev, "used for oneshot clock events\n");
-+ em_sti_start(p, USER_CLOCKEVENT);
-+ clockevents_config(&p->ced, p->rate);
-+ break;
-+ case CLOCK_EVT_MODE_SHUTDOWN:
-+ case CLOCK_EVT_MODE_UNUSED:
-+ em_sti_stop(p, USER_CLOCKEVENT);
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+static int em_sti_clock_event_next(unsigned long delta,
-+ struct clock_event_device *ced)
-+{
-+ struct em_sti_priv *p = ced_to_em_sti(ced);
-+ cycle_t next;
-+ int safe;
-+
-+ next = em_sti_set_next(p, em_sti_count(p) + delta);
-+ safe = em_sti_count(p) < (next - 1);
-+
-+ return !safe;
-+}
-+
-+static void em_sti_register_clockevent(struct em_sti_priv *p)
-+{
-+ struct clock_event_device *ced = &p->ced;
-+
-+ memset(ced, 0, sizeof(*ced));
-+ ced->name = dev_name(&p->pdev->dev);
-+ ced->features = CLOCK_EVT_FEAT_ONESHOT;
-+ ced->rating = 200;
-+ ced->cpumask = cpumask_of(0);
-+ ced->set_next_event = em_sti_clock_event_next;
-+ ced->set_mode = em_sti_clock_event_mode;
-+
-+ dev_info(&p->pdev->dev, "used for clock events\n");
-+
-+ /* Register with dummy 1 Hz value, gets updated in ->set_mode() */
-+ clockevents_config_and_register(ced, 1, 2, 0xffffffff);
-+}
-+
-+static int __devinit em_sti_probe(struct platform_device *pdev)
-+{
-+ struct em_sti_priv *p;
-+ struct resource *res;
-+ int irq, ret;
-+
-+ p = kzalloc(sizeof(*p), GFP_KERNEL);
-+ if (p == NULL) {
-+ dev_err(&pdev->dev, "failed to allocate driver data\n");
-+ ret = -ENOMEM;
-+ goto err0;
-+ }
-+
-+ p->pdev = pdev;
-+ platform_set_drvdata(pdev, p);
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!res) {
-+ dev_err(&pdev->dev, "failed to get I/O memory\n");
-+ ret = -EINVAL;
-+ goto err0;
-+ }
-+
-+ irq = platform_get_irq(pdev, 0);
-+ if (irq < 0) {
-+ dev_err(&pdev->dev, "failed to get irq\n");
-+ ret = -EINVAL;
-+ goto err0;
-+ }
-+
-+ /* map memory, let base point to the STI instance */
-+ p->base = ioremap_nocache(res->start, resource_size(res));
-+ if (p->base == NULL) {
-+ dev_err(&pdev->dev, "failed to remap I/O memory\n");
-+ ret = -ENXIO;
-+ goto err0;
-+ }
-+
-+ /* get hold of clock */
-+ p->clk = clk_get(&pdev->dev, "sclk");
-+ if (IS_ERR(p->clk)) {
-+ dev_err(&pdev->dev, "cannot get clock\n");
-+ ret = PTR_ERR(p->clk);
-+ goto err1;
-+ }
-+
-+ if (request_irq(irq, em_sti_interrupt,
-+ IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
-+ dev_name(&pdev->dev), p)) {
-+ dev_err(&pdev->dev, "failed to request low IRQ\n");
-+ ret = -ENOENT;
-+ goto err2;
-+ }
-+
-+ raw_spin_lock_init(&p->lock);
-+ em_sti_register_clockevent(p);
-+ em_sti_register_clocksource(p);
-+ return 0;
-+
-+err2:
-+ clk_put(p->clk);
-+err1:
-+ iounmap(p->base);
-+err0:
-+ kfree(p);
-+ return ret;
-+}
-+
-+static int __devexit em_sti_remove(struct platform_device *pdev)
-+{
-+ return -EBUSY; /* cannot unregister clockevent and clocksource */
-+}
-+
-+static struct platform_driver em_sti_device_driver = {
-+ .probe = em_sti_probe,
-+ .remove = __devexit_p(em_sti_remove),
-+ .driver = {
-+ .name = "em_sti",
-+ }
-+};
-+
-+module_platform_driver(em_sti_device_driver);
-+
-+MODULE_AUTHOR("Magnus Damm");
-+MODULE_DESCRIPTION("Renesas Emma Mobile STI Timer Driver");
-+MODULE_LICENSE("GPL v2");
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:29:20 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:09 +0900
-Subject: [PATCH 17/26] gpio: Emma Mobile GPIO driver V2
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-18-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-This patch is V2 of the Emma Mobile GPIO driver. This
-driver is designed to be reusable between multiple SoCs
-that share the same basic building block, but so far it
-has only been used on Emma Mobile EV2.
-
-Each driver instance handles 32 GPIOs with individually
-maskable IRQs. The driver operates on two I/O memory
-ranges and the 32 GPIOs are hooked up to two interrupts.
-
-In the case of Emma Mobile EV2 this GPIO building block
-is used as main external interrupt controller hooking up
-159 GPIOS as 159 interrupts via 5 driver instances and
-10 interrupts to the GIC and the Cortex-A9 Dual.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Acked-by: Linus Walleij <linus.walleij@linaro.org>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit a07e103ef08c6907d695a06467d7ee950796fccf)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- drivers/gpio/Kconfig | 6
- drivers/gpio/Makefile | 1
- drivers/gpio/gpio-em.c | 418 ++++++++++++++++++++++++++++++++++
- include/linux/platform_data/gpio-em.h | 10
- 4 files changed, 435 insertions(+)
- create mode 100644 drivers/gpio/gpio-em.c
- create mode 100644 include/linux/platform_data/gpio-em.h
-
---- a/drivers/gpio/Kconfig
-+++ b/drivers/gpio/Kconfig
-@@ -91,6 +91,12 @@ config GPIO_IT8761E
- help
- Say yes here to support GPIO functionality of IT8761E super I/O chip.
-
-+config GPIO_EM
-+ tristate "Emma Mobile GPIO"
-+ depends on ARM
-+ help
-+ Say yes here to support GPIO on Renesas Emma Mobile SoCs.
-+
- config GPIO_EP93XX
- def_bool y
- depends on ARCH_EP93XX
---- a/drivers/gpio/Makefile
-+++ b/drivers/gpio/Makefile
-@@ -15,6 +15,7 @@ obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
- obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
- obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
- obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o
-+obj-$(CONFIG_GPIO_EM) += gpio-em.o
- obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
- obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
- obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
---- /dev/null
-+++ b/drivers/gpio/gpio-em.c
-@@ -0,0 +1,418 @@
-+/*
-+ * Emma Mobile GPIO Support - GIO
-+ *
-+ * Copyright (C) 2012 Magnus Damm
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/platform_device.h>
-+#include <linux/spinlock.h>
-+#include <linux/interrupt.h>
-+#include <linux/ioport.h>
-+#include <linux/io.h>
-+#include <linux/irq.h>
-+#include <linux/irqdomain.h>
-+#include <linux/bitops.h>
-+#include <linux/err.h>
-+#include <linux/gpio.h>
-+#include <linux/slab.h>
-+#include <linux/module.h>
-+#include <linux/platform_data/gpio-em.h>
-+
-+struct em_gio_priv {
-+ void __iomem *base0;
-+ void __iomem *base1;
-+ unsigned int irq_base;
-+ spinlock_t sense_lock;
-+ struct platform_device *pdev;
-+ struct gpio_chip gpio_chip;
-+ struct irq_chip irq_chip;
-+ struct irq_domain *irq_domain;
-+};
-+
-+#define GIO_E1 0x00
-+#define GIO_E0 0x04
-+#define GIO_EM 0x04
-+#define GIO_OL 0x08
-+#define GIO_OH 0x0c
-+#define GIO_I 0x10
-+#define GIO_IIA 0x14
-+#define GIO_IEN 0x18
-+#define GIO_IDS 0x1c
-+#define GIO_IIM 0x1c
-+#define GIO_RAW 0x20
-+#define GIO_MST 0x24
-+#define GIO_IIR 0x28
-+
-+#define GIO_IDT0 0x40
-+#define GIO_IDT1 0x44
-+#define GIO_IDT2 0x48
-+#define GIO_IDT3 0x4c
-+#define GIO_RAWBL 0x50
-+#define GIO_RAWBH 0x54
-+#define GIO_IRBL 0x58
-+#define GIO_IRBH 0x5c
-+
-+#define GIO_IDT(n) (GIO_IDT0 + ((n) * 4))
-+
-+static inline unsigned long em_gio_read(struct em_gio_priv *p, int offs)
-+{
-+ if (offs < GIO_IDT0)
-+ return ioread32(p->base0 + offs);
-+ else
-+ return ioread32(p->base1 + (offs - GIO_IDT0));
-+}
-+
-+static inline void em_gio_write(struct em_gio_priv *p, int offs,
-+ unsigned long value)
-+{
-+ if (offs < GIO_IDT0)
-+ iowrite32(value, p->base0 + offs);
-+ else
-+ iowrite32(value, p->base1 + (offs - GIO_IDT0));
-+}
-+
-+static inline struct em_gio_priv *irq_to_priv(struct irq_data *d)
-+{
-+ struct irq_chip *chip = irq_data_get_irq_chip(d);
-+ return container_of(chip, struct em_gio_priv, irq_chip);
-+}
-+
-+static void em_gio_irq_disable(struct irq_data *d)
-+{
-+ struct em_gio_priv *p = irq_to_priv(d);
-+
-+ em_gio_write(p, GIO_IDS, BIT(irqd_to_hwirq(d)));
-+}
-+
-+static void em_gio_irq_enable(struct irq_data *d)
-+{
-+ struct em_gio_priv *p = irq_to_priv(d);
-+
-+ em_gio_write(p, GIO_IEN, BIT(irqd_to_hwirq(d)));
-+}
-+
-+#define GIO_ASYNC(x) (x + 8)
-+
-+static unsigned char em_gio_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
-+ [IRQ_TYPE_EDGE_RISING] = GIO_ASYNC(0x00),
-+ [IRQ_TYPE_EDGE_FALLING] = GIO_ASYNC(0x01),
-+ [IRQ_TYPE_LEVEL_HIGH] = GIO_ASYNC(0x02),
-+ [IRQ_TYPE_LEVEL_LOW] = GIO_ASYNC(0x03),
-+ [IRQ_TYPE_EDGE_BOTH] = GIO_ASYNC(0x04),
-+};
-+
-+static int em_gio_irq_set_type(struct irq_data *d, unsigned int type)
-+{
-+ unsigned char value = em_gio_sense_table[type & IRQ_TYPE_SENSE_MASK];
-+ struct em_gio_priv *p = irq_to_priv(d);
-+ unsigned int reg, offset, shift;
-+ unsigned long flags;
-+ unsigned long tmp;
-+
-+ if (!value)
-+ return -EINVAL;
-+
-+ offset = irqd_to_hwirq(d);
-+
-+ pr_debug("gio: sense irq = %d, mode = %d\n", offset, value);
-+
-+ /* 8 x 4 bit fields in 4 IDT registers */
-+ reg = GIO_IDT(offset >> 3);
-+ shift = (offset & 0x07) << 4;
-+
-+ spin_lock_irqsave(&p->sense_lock, flags);
-+
-+ /* disable the interrupt in IIA */
-+ tmp = em_gio_read(p, GIO_IIA);
-+ tmp &= ~BIT(offset);
-+ em_gio_write(p, GIO_IIA, tmp);
-+
-+ /* change the sense setting in IDT */
-+ tmp = em_gio_read(p, reg);
-+ tmp &= ~(0xf << shift);
-+ tmp |= value << shift;
-+ em_gio_write(p, reg, tmp);
-+
-+ /* clear pending interrupts */
-+ em_gio_write(p, GIO_IIR, BIT(offset));
-+
-+ /* enable the interrupt in IIA */
-+ tmp = em_gio_read(p, GIO_IIA);
-+ tmp |= BIT(offset);
-+ em_gio_write(p, GIO_IIA, tmp);
-+
-+ spin_unlock_irqrestore(&p->sense_lock, flags);
-+
-+ return 0;
-+}
-+
-+static irqreturn_t em_gio_irq_handler(int irq, void *dev_id)
-+{
-+ struct em_gio_priv *p = dev_id;
-+ unsigned long pending;
-+ unsigned int offset, irqs_handled = 0;
-+
-+ while ((pending = em_gio_read(p, GIO_MST))) {
-+ offset = __ffs(pending);
-+ em_gio_write(p, GIO_IIR, BIT(offset));
-+ generic_handle_irq(irq_find_mapping(p->irq_domain, offset));
-+ irqs_handled++;
-+ }
-+
-+ return irqs_handled ? IRQ_HANDLED : IRQ_NONE;
-+}
-+
-+static inline struct em_gio_priv *gpio_to_priv(struct gpio_chip *chip)
-+{
-+ return container_of(chip, struct em_gio_priv, gpio_chip);
-+}
-+
-+static int em_gio_direction_input(struct gpio_chip *chip, unsigned offset)
-+{
-+ em_gio_write(gpio_to_priv(chip), GIO_E0, BIT(offset));
-+ return 0;
-+}
-+
-+static int em_gio_get(struct gpio_chip *chip, unsigned offset)
-+{
-+ return (int)(em_gio_read(gpio_to_priv(chip), GIO_I) & BIT(offset));
-+}
-+
-+static void __em_gio_set(struct gpio_chip *chip, unsigned int reg,
-+ unsigned shift, int value)
-+{
-+ /* upper 16 bits contains mask and lower 16 actual value */
-+ em_gio_write(gpio_to_priv(chip), reg,
-+ (1 << (shift + 16)) | (value << shift));
-+}
-+
-+static void em_gio_set(struct gpio_chip *chip, unsigned offset, int value)
-+{
-+ /* output is split into two registers */
-+ if (offset < 16)
-+ __em_gio_set(chip, GIO_OL, offset, value);
-+ else
-+ __em_gio_set(chip, GIO_OH, offset - 16, value);
-+}
-+
-+static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset,
-+ int value)
-+{
-+ /* write GPIO value to output before selecting output mode of pin */
-+ em_gio_set(chip, offset, value);
-+ em_gio_write(gpio_to_priv(chip), GIO_E1, BIT(offset));
-+ return 0;
-+}
-+
-+static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset)
-+{
-+ return irq_find_mapping(gpio_to_priv(chip)->irq_domain, offset);
-+}
-+
-+static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq,
-+ irq_hw_number_t hw)
-+{
-+ struct em_gio_priv *p = h->host_data;
-+
-+ pr_debug("gio: map hw irq = %d, virq = %d\n", (int)hw, virq);
-+
-+ irq_set_chip_data(virq, h->host_data);
-+ irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
-+ set_irq_flags(virq, IRQF_VALID); /* kill me now */
-+ return 0;
-+}
-+
-+static struct irq_domain_ops em_gio_irq_domain_ops = {
-+ .map = em_gio_irq_domain_map,
-+};
-+
-+static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p)
-+{
-+ struct platform_device *pdev = p->pdev;
-+ struct gpio_em_config *pdata = pdev->dev.platform_data;
-+
-+ p->irq_base = irq_alloc_descs(pdata->irq_base, 0,
-+ pdata->number_of_pins, numa_node_id());
-+ if (IS_ERR_VALUE(p->irq_base)) {
-+ dev_err(&pdev->dev, "cannot get irq_desc\n");
-+ return -ENXIO;
-+ }
-+ pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n",
-+ pdata->gpio_base, pdata->number_of_pins, p->irq_base);
-+
-+ p->irq_domain = irq_domain_add_legacy(pdev->dev.of_node,
-+ pdata->number_of_pins,
-+ p->irq_base, 0,
-+ &em_gio_irq_domain_ops, p);
-+ if (!p->irq_domain) {
-+ irq_free_descs(p->irq_base, pdata->number_of_pins);
-+ return -ENXIO;
-+ }
-+
-+ return 0;
-+}
-+
-+static void __devexit em_gio_irq_domain_cleanup(struct em_gio_priv *p)
-+{
-+ struct gpio_em_config *pdata = p->pdev->dev.platform_data;
-+
-+ irq_free_descs(p->irq_base, pdata->number_of_pins);
-+ /* FIXME: irq domain wants to be freed! */
-+}
-+
-+static int __devinit em_gio_probe(struct platform_device *pdev)
-+{
-+ struct gpio_em_config *pdata = pdev->dev.platform_data;
-+ struct em_gio_priv *p;
-+ struct resource *io[2], *irq[2];
-+ struct gpio_chip *gpio_chip;
-+ struct irq_chip *irq_chip;
-+ const char *name = dev_name(&pdev->dev);
-+ int ret;
-+
-+ p = kzalloc(sizeof(*p), GFP_KERNEL);
-+ if (!p) {
-+ dev_err(&pdev->dev, "failed to allocate driver data\n");
-+ ret = -ENOMEM;
-+ goto err0;
-+ }
-+
-+ p->pdev = pdev;
-+ platform_set_drvdata(pdev, p);
-+ spin_lock_init(&p->sense_lock);
-+
-+ io[0] = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ io[1] = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+ irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-+ irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
-+
-+ if (!io[0] || !io[1] || !irq[0] || !irq[1] || !pdata) {
-+ dev_err(&pdev->dev, "missing IRQ, IOMEM or configuration\n");
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ p->base0 = ioremap_nocache(io[0]->start, resource_size(io[0]));
-+ if (!p->base0) {
-+ dev_err(&pdev->dev, "failed to remap low I/O memory\n");
-+ ret = -ENXIO;
-+ goto err1;
-+ }
-+
-+ p->base1 = ioremap_nocache(io[1]->start, resource_size(io[1]));
-+ if (!p->base1) {
-+ dev_err(&pdev->dev, "failed to remap high I/O memory\n");
-+ ret = -ENXIO;
-+ goto err2;
-+ }
-+
-+ gpio_chip = &p->gpio_chip;
-+ gpio_chip->direction_input = em_gio_direction_input;
-+ gpio_chip->get = em_gio_get;
-+ gpio_chip->direction_output = em_gio_direction_output;
-+ gpio_chip->set = em_gio_set;
-+ gpio_chip->to_irq = em_gio_to_irq;
-+ gpio_chip->label = name;
-+ gpio_chip->owner = THIS_MODULE;
-+ gpio_chip->base = pdata->gpio_base;
-+ gpio_chip->ngpio = pdata->number_of_pins;
-+
-+ irq_chip = &p->irq_chip;
-+ irq_chip->name = name;
-+ irq_chip->irq_mask = em_gio_irq_disable;
-+ irq_chip->irq_unmask = em_gio_irq_enable;
-+ irq_chip->irq_enable = em_gio_irq_enable;
-+ irq_chip->irq_disable = em_gio_irq_disable;
-+ irq_chip->irq_set_type = em_gio_irq_set_type;
-+ irq_chip->flags = IRQCHIP_SKIP_SET_WAKE;
-+
-+ ret = em_gio_irq_domain_init(p);
-+ if (ret) {
-+ dev_err(&pdev->dev, "cannot initialize irq domain\n");
-+ goto err3;
-+ }
-+
-+ if (request_irq(irq[0]->start, em_gio_irq_handler, 0, name, p)) {
-+ dev_err(&pdev->dev, "failed to request low IRQ\n");
-+ ret = -ENOENT;
-+ goto err4;
-+ }
-+
-+ if (request_irq(irq[1]->start, em_gio_irq_handler, 0, name, p)) {
-+ dev_err(&pdev->dev, "failed to request high IRQ\n");
-+ ret = -ENOENT;
-+ goto err5;
-+ }
-+
-+ ret = gpiochip_add(gpio_chip);
-+ if (ret) {
-+ dev_err(&pdev->dev, "failed to add GPIO controller\n");
-+ goto err6;
-+ }
-+ return 0;
-+
-+err6:
-+ free_irq(irq[1]->start, pdev);
-+err5:
-+ free_irq(irq[0]->start, pdev);
-+err4:
-+ em_gio_irq_domain_cleanup(p);
-+err3:
-+ iounmap(p->base1);
-+err2:
-+ iounmap(p->base0);
-+err1:
-+ kfree(p);
-+err0:
-+ return ret;
-+}
-+
-+static int __devexit em_gio_remove(struct platform_device *pdev)
-+{
-+ struct em_gio_priv *p = platform_get_drvdata(pdev);
-+ struct resource *irq[2];
-+ int ret;
-+
-+ ret = gpiochip_remove(&p->gpio_chip);
-+ if (ret)
-+ return ret;
-+
-+ irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-+ irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
-+
-+ free_irq(irq[1]->start, pdev);
-+ free_irq(irq[0]->start, pdev);
-+ em_gio_irq_domain_cleanup(p);
-+ iounmap(p->base1);
-+ iounmap(p->base0);
-+ kfree(p);
-+ return 0;
-+}
-+
-+static struct platform_driver em_gio_device_driver = {
-+ .probe = em_gio_probe,
-+ .remove = __devexit_p(em_gio_remove),
-+ .driver = {
-+ .name = "em_gio",
-+ }
-+};
-+
-+module_platform_driver(em_gio_device_driver);
-+
-+MODULE_AUTHOR("Magnus Damm");
-+MODULE_DESCRIPTION("Renesas Emma Mobile GIO Driver");
-+MODULE_LICENSE("GPL v2");
---- /dev/null
-+++ b/include/linux/platform_data/gpio-em.h
-@@ -0,0 +1,10 @@
-+#ifndef __GPIO_EM_H__
-+#define __GPIO_EM_H__
-+
-+struct gpio_em_config {
-+ unsigned int gpio_base;
-+ unsigned int irq_base;
-+ unsigned int number_of_pins;
-+};
-+
-+#endif /* __GPIO_EM_H__ */
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:30:22 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:16 +0900
-Subject: [PATCH 24/26] mach-shmobile: Emma Mobile EV2 DT support V3
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-25-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-This is EMEV2 DT support V3. The support is limited to
-whatever devices that are complied in the kernel. At this
-point we have UARTs handled by "em-uart" and a timer
-handled by "em-sti". Clocks and SMP are not supported.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 3d5de27174955702bc874302ba9e72d71d5acd58)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/boot/dts/emev2.dtsi | 63 ++++++++++++++++++++++++++++++++++
- arch/arm/mach-shmobile/clock-emev2.c | 5 +++
- arch/arm/mach-shmobile/setup-emev2.c | 47 ++++++++++++++++++++++++-
- 3 files changed, 114 insertions(+), 1 deletion(-)
- create mode 100644 arch/arm/boot/dts/emev2.dtsi
-
-diff --git a/arch/arm/boot/dts/emev2.dtsi b/arch/arm/boot/dts/emev2.dtsi
-new file mode 100644
-index 0000000..eb504a6
---- /dev/null
-+++ b/arch/arm/boot/dts/emev2.dtsi
-@@ -0,0 +1,63 @@
-+/*
-+ * Device Tree Source for the EMEV2 SoC
-+ *
-+ * Copyright (C) 2012 Renesas Solutions Corp.
-+ *
-+ * 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/ "skeleton.dtsi"
-+
-+/ {
-+ compatible = "renesas,emev2";
-+ interrupt-parent = <&gic>;
-+
-+ cpus {
-+ cpu@0 {
-+ compatible = "arm,cortex-a9";
-+ };
-+ cpu@1 {
-+ compatible = "arm,cortex-a9";
-+ };
-+ };
-+
-+ gic: interrupt-controller@e0020000 {
-+ compatible = "arm,cortex-a9-gic";
-+ interrupt-controller;
-+ #interrupt-cells = <3>;
-+ reg = <0xe0028000 0x1000>,
-+ <0xe0020000 0x0100>;
-+ };
-+
-+ sti@e0180000 {
-+ compatible = "renesas,em-sti";
-+ reg = <0xe0180000 0x54>;
-+ interrupts = <0 125 0>;
-+ };
-+
-+ uart@e1020000 {
-+ compatible = "renesas,em-uart";
-+ reg = <0xe1020000 0x38>;
-+ interrupts = <0 8 0>;
-+ };
-+
-+ uart@e1030000 {
-+ compatible = "renesas,em-uart";
-+ reg = <0xe1030000 0x38>;
-+ interrupts = <0 9 0>;
-+ };
-+
-+ uart@e1040000 {
-+ compatible = "renesas,em-uart";
-+ reg = <0xe1040000 0x38>;
-+ interrupts = <0 10 0>;
-+ };
-+
-+ uart@e1050000 {
-+ compatible = "renesas,em-uart";
-+ reg = <0xe1050000 0x38>;
-+ interrupts = <0 11 0>;
-+ };
-+};
-diff --git a/arch/arm/mach-shmobile/clock-emev2.c b/arch/arm/mach-shmobile/clock-emev2.c
-index 5bc97de..4710f18 100644
---- a/arch/arm/mach-shmobile/clock-emev2.c
-+++ b/arch/arm/mach-shmobile/clock-emev2.c
-@@ -191,10 +191,15 @@ static int __init emev2_sclkdiv_register(struct clk *clks, int nr)
-
- static struct clk_lookup lookups[] = {
- CLKDEV_DEV_ID("serial8250-em.0", &gclk_clks[GCLK_USIAU0_SCLK]),
-+ CLKDEV_DEV_ID("e1020000.uart", &gclk_clks[GCLK_USIAU0_SCLK]),
- CLKDEV_DEV_ID("serial8250-em.1", &gclk_clks[GCLK_USIBU1_SCLK]),
-+ CLKDEV_DEV_ID("e1030000.uart", &gclk_clks[GCLK_USIBU1_SCLK]),
- CLKDEV_DEV_ID("serial8250-em.2", &gclk_clks[GCLK_USIBU2_SCLK]),
-+ CLKDEV_DEV_ID("e1040000.uart", &gclk_clks[GCLK_USIBU2_SCLK]),
- CLKDEV_DEV_ID("serial8250-em.3", &gclk_clks[GCLK_USIBU3_SCLK]),
-+ CLKDEV_DEV_ID("e1050000.uart", &gclk_clks[GCLK_USIBU3_SCLK]),
- CLKDEV_DEV_ID("em_sti.0", &gclk_clks[GCLK_STI_SCLK]),
-+ CLKDEV_DEV_ID("e0180000.sti", &gclk_clks[GCLK_STI_SCLK]),
- };
-
- void __init emev2_clock_init(void)
-diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
-index d40fede..dae9aa6 100644
---- a/arch/arm/mach-shmobile/setup-emev2.c
-+++ b/arch/arm/mach-shmobile/setup-emev2.c
-@@ -22,9 +22,11 @@
- #include <linux/irq.h>
- #include <linux/platform_device.h>
- #include <linux/platform_data/gpio-em.h>
-+#include <linux/of_platform.h>
- #include <linux/delay.h>
- #include <linux/input.h>
- #include <linux/io.h>
-+#include <linux/of_irq.h>
- #include <mach/hardware.h>
- #include <mach/common.h>
- #include <mach/emev2.h>
-@@ -381,9 +383,14 @@ void __init emev2_add_standard_devices(void)
- ARRAY_SIZE(emev2_late_devices));
- }
-
--void __init emev2_add_early_devices(void)
-+void __init emev2_init_delay(void)
- {
- shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */
-+}
-+
-+void __init emev2_add_early_devices(void)
-+{
-+ emev2_init_delay();
-
- early_platform_add_devices(emev2_early_devices,
- ARRAY_SIZE(emev2_early_devices));
-@@ -405,3 +412,41 @@ void __init emev2_init_irq(void)
- /* Use GIC to handle interrupts */
- gic_init(0, 29, gic_dist_base, gic_cpu_base);
- }
-+
-+#ifdef CONFIG_USE_OF
-+static const struct of_dev_auxdata emev2_auxdata_lookup[] __initconst = {
-+ { }
-+};
-+
-+void __init emev2_add_standard_devices_dt(void)
-+{
-+ of_platform_populate(NULL, of_default_bus_match_table,
-+ emev2_auxdata_lookup, NULL);
-+}
-+
-+static const struct of_device_id emev2_dt_irq_match[] = {
-+ { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
-+ {},
-+};
-+
-+static const char *emev2_boards_compat_dt[] __initdata = {
-+ "renesas,emev2",
-+ NULL,
-+};
-+
-+void __init emev2_init_irq_dt(void)
-+{
-+ of_irq_init(emev2_dt_irq_match);
-+}
-+
-+DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
-+ .init_early = emev2_init_delay,
-+ .nr_irqs = NR_IRQS_LEGACY,
-+ .init_irq = emev2_init_irq_dt,
-+ .handle_irq = gic_handle_irq,
-+ .init_machine = emev2_add_standard_devices_dt,
-+ .timer = &shmobile_timer,
-+ .dt_compat = emev2_boards_compat_dt,
-+MACHINE_END
-+
-+#endif /* CONFIG_USE_OF */
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:30:00 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:13 +0900
-Subject: [PATCH 21/26] mach-shmobile: Emma Mobile EV2 GPIO support V3
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-22-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-Tie in the Emma Mobile GPIO driver "em-gio" to
-support the GPIOs on Emma Mobile EV2.
-
-A static IRQ range is used to allow boards to
-hook up their platform devices to the GPIOs.
-
-DT support is still on the TODO for the GPIO driver,
-so only platform device support is included here.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 088efd9273b5076a0aead479aa31f1066d182b3e)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/Kconfig | 1 +
- arch/arm/mach-shmobile/include/mach/emev2.h | 3 +
- arch/arm/mach-shmobile/setup-emev2.c | 203 +++++++++++++++++++++++++++
- 3 files changed, 207 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
-index 577fbad..95ecfad 100644
---- a/arch/arm/mach-shmobile/Kconfig
-+++ b/arch/arm/mach-shmobile/Kconfig
-@@ -45,6 +45,7 @@ config ARCH_EMEV2
- bool "Emma Mobile EV2"
- select CPU_V7
- select ARM_GIC
-+ select ARCH_WANT_OPTIONAL_GPIOLIB
-
- comment "SH-Mobile Board Type"
-
-diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h
-index 3fc7184..e6b0c1b 100644
---- a/arch/arm/mach-shmobile/include/mach/emev2.h
-+++ b/arch/arm/mach-shmobile/include/mach/emev2.h
-@@ -13,4 +13,7 @@ extern void emev2_secondary_init(unsigned int cpu);
- extern int emev2_boot_secondary(unsigned int cpu);
- extern void emev2_smp_prepare_cpus(void);
-
-+#define EMEV2_GPIO_BASE 200
-+#define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n))
-+
- #endif /* __ASM_EMEV2_H__ */
-diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
-index 2a03a78..d40fede 100644
---- a/arch/arm/mach-shmobile/setup-emev2.c
-+++ b/arch/arm/mach-shmobile/setup-emev2.c
-@@ -21,6 +21,7 @@
- #include <linux/interrupt.h>
- #include <linux/irq.h>
- #include <linux/platform_device.h>
-+#include <linux/platform_data/gpio-em.h>
- #include <linux/delay.h>
- #include <linux/input.h>
- #include <linux/io.h>
-@@ -156,6 +157,203 @@ static struct platform_device sti_device = {
- .num_resources = ARRAY_SIZE(sti_resources),
- };
-
-+
-+/* GIO */
-+static struct gpio_em_config gio0_config = {
-+ .gpio_base = 0,
-+ .irq_base = EMEV2_GPIO_IRQ(0),
-+ .number_of_pins = 32,
-+};
-+
-+static struct resource gio0_resources[] = {
-+ [0] = {
-+ .name = "GIO_000",
-+ .start = 0xe0050000,
-+ .end = 0xe005002b,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .name = "GIO_000",
-+ .start = 0xe0050040,
-+ .end = 0xe005005f,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [2] = {
-+ .start = 99,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [3] = {
-+ .start = 100,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device gio0_device = {
-+ .name = "em_gio",
-+ .id = 0,
-+ .resource = gio0_resources,
-+ .num_resources = ARRAY_SIZE(gio0_resources),
-+ .dev = {
-+ .platform_data = &gio0_config,
-+ },
-+};
-+
-+static struct gpio_em_config gio1_config = {
-+ .gpio_base = 32,
-+ .irq_base = EMEV2_GPIO_IRQ(32),
-+ .number_of_pins = 32,
-+};
-+
-+static struct resource gio1_resources[] = {
-+ [0] = {
-+ .name = "GIO_032",
-+ .start = 0xe0050080,
-+ .end = 0xe00500ab,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .name = "GIO_032",
-+ .start = 0xe00500c0,
-+ .end = 0xe00500df,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [2] = {
-+ .start = 101,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [3] = {
-+ .start = 102,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device gio1_device = {
-+ .name = "em_gio",
-+ .id = 1,
-+ .resource = gio1_resources,
-+ .num_resources = ARRAY_SIZE(gio1_resources),
-+ .dev = {
-+ .platform_data = &gio1_config,
-+ },
-+};
-+
-+static struct gpio_em_config gio2_config = {
-+ .gpio_base = 64,
-+ .irq_base = EMEV2_GPIO_IRQ(64),
-+ .number_of_pins = 32,
-+};
-+
-+static struct resource gio2_resources[] = {
-+ [0] = {
-+ .name = "GIO_064",
-+ .start = 0xe0050100,
-+ .end = 0xe005012b,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .name = "GIO_064",
-+ .start = 0xe0050140,
-+ .end = 0xe005015f,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [2] = {
-+ .start = 103,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [3] = {
-+ .start = 104,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device gio2_device = {
-+ .name = "em_gio",
-+ .id = 2,
-+ .resource = gio2_resources,
-+ .num_resources = ARRAY_SIZE(gio2_resources),
-+ .dev = {
-+ .platform_data = &gio2_config,
-+ },
-+};
-+
-+static struct gpio_em_config gio3_config = {
-+ .gpio_base = 96,
-+ .irq_base = EMEV2_GPIO_IRQ(96),
-+ .number_of_pins = 32,
-+};
-+
-+static struct resource gio3_resources[] = {
-+ [0] = {
-+ .name = "GIO_096",
-+ .start = 0xe0050100,
-+ .end = 0xe005012b,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .name = "GIO_096",
-+ .start = 0xe0050140,
-+ .end = 0xe005015f,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [2] = {
-+ .start = 105,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [3] = {
-+ .start = 106,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device gio3_device = {
-+ .name = "em_gio",
-+ .id = 3,
-+ .resource = gio3_resources,
-+ .num_resources = ARRAY_SIZE(gio3_resources),
-+ .dev = {
-+ .platform_data = &gio3_config,
-+ },
-+};
-+
-+static struct gpio_em_config gio4_config = {
-+ .gpio_base = 128,
-+ .irq_base = EMEV2_GPIO_IRQ(128),
-+ .number_of_pins = 31,
-+};
-+
-+static struct resource gio4_resources[] = {
-+ [0] = {
-+ .name = "GIO_128",
-+ .start = 0xe0050200,
-+ .end = 0xe005022b,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .name = "GIO_128",
-+ .start = 0xe0050240,
-+ .end = 0xe005025f,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [2] = {
-+ .start = 107,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [3] = {
-+ .start = 108,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device gio4_device = {
-+ .name = "em_gio",
-+ .id = 4,
-+ .resource = gio4_resources,
-+ .num_resources = ARRAY_SIZE(gio4_resources),
-+ .dev = {
-+ .platform_data = &gio4_config,
-+ },
-+};
-+
- static struct platform_device *emev2_early_devices[] __initdata = {
- &uart0_device,
- &uart1_device,
-@@ -165,6 +363,11 @@ static struct platform_device *emev2_early_devices[] __initdata = {
-
- static struct platform_device *emev2_late_devices[] __initdata = {
- &sti_device,
-+ &gio0_device,
-+ &gio1_device,
-+ &gio2_device,
-+ &gio3_device,
-+ &gio4_device,
- };
-
- void __init emev2_add_standard_devices(void)
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:29:51 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:12 +0900
-Subject: [PATCH 20/26] mach-shmobile: Emma Mobile EV2 SMP support V3
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-21-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-This is V3 of Emma Mobile EV2 SMP support.
-
-At this point only the most basic form of SMP operation
-is supported. TWD and CPU Hotplug support is excluded.
-
-Tied to both the Emma Mobile EV2 and the KZM9D board
-due to the need to switch on board in platsmp.c and
-the newly introduced need for static mappings.
-
-The static mappings are needed to allow hardware
-acces early during boot when SMP is initialized.
-This early requirement forces us to also map in
-the SMU registers.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit bd5a875d90c878be4d23f54ea565253734ae2377)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/Makefile | 1 +
- arch/arm/mach-shmobile/board-kzm9d.c | 1 +
- arch/arm/mach-shmobile/clock-emev2.c | 18 +++++
- arch/arm/mach-shmobile/include/mach/emev2.h | 7 ++
- arch/arm/mach-shmobile/platsmp.c | 17 +++++
- arch/arm/mach-shmobile/setup-emev2.c | 24 +++++++
- arch/arm/mach-shmobile/smp-emev2.c | 97 +++++++++++++++++++++++++++
- 7 files changed, 165 insertions(+)
- create mode 100644 arch/arm/mach-shmobile/smp-emev2.c
-
-diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
-index 2e6ff96..a93bcf0 100644
---- a/arch/arm/mach-shmobile/Makefile
-+++ b/arch/arm/mach-shmobile/Makefile
-@@ -19,6 +19,7 @@ smp-y := platsmp.o headsmp.o
- smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o
- smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o
- smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o
-+smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o
-
- # Pinmux setup
- pfc-y :=
-diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c
-index e743f90..42fc479 100644
---- a/arch/arm/mach-shmobile/board-kzm9d.c
-+++ b/arch/arm/mach-shmobile/board-kzm9d.c
-@@ -27,6 +27,7 @@
- #include <asm/hardware/gic.h>
-
- MACHINE_START(KZM9D, "kzm9d")
-+ .map_io = emev2_map_io,
- .init_early = emev2_add_early_devices,
- .nr_irqs = NR_IRQS_LEGACY,
- .init_irq = emev2_init_irq,
-diff --git a/arch/arm/mach-shmobile/clock-emev2.c b/arch/arm/mach-shmobile/clock-emev2.c
-index 73a1216..5bc97de 100644
---- a/arch/arm/mach-shmobile/clock-emev2.c
-+++ b/arch/arm/mach-shmobile/clock-emev2.c
-@@ -40,6 +40,7 @@
- #define USIB2SCLKDIV 0x65c
- #define USIB3SCLKDIV 0x660
- #define STI_CLKSEL 0x688
-+#define SMU_GENERAL_REG0 0x7c0
-
- /* not pretty, but hey */
- static void __iomem *smu_base;
-@@ -50,6 +51,11 @@ static void emev2_smu_write(unsigned long value, int offs)
- iowrite32(value, smu_base + offs);
- }
-
-+void emev2_set_boot_vector(unsigned long value)
-+{
-+ emev2_smu_write(value, SMU_GENERAL_REG0);
-+}
-+
- static struct clk_mapping smu_mapping = {
- .phys = EMEV2_SMU_BASE,
- .len = PAGE_SIZE,
-@@ -194,6 +200,18 @@ static struct clk_lookup lookups[] = {
- void __init emev2_clock_init(void)
- {
- int k, ret = 0;
-+ static int is_setup;
-+
-+ /* yuck, this is ugly as hell, but the non-smp case of clocks
-+ * code is now designed to rely on ioremap() instead of static
-+ * entity maps. in the case of smp we need access to the SMU
-+ * register earlier than ioremap() is actually working without
-+ * any static maps. to enable SMP in ugly but with dynamic
-+ * mappings we have to call emev2_clock_init() from different
-+ * places depending on UP and SMP...
-+ */
-+ if (is_setup++)
-+ return;
-
- smu_base = ioremap(EMEV2_SMU_BASE, PAGE_SIZE);
- BUG_ON(!smu_base);
-diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h
-index 92646c1..3fc7184 100644
---- a/arch/arm/mach-shmobile/include/mach/emev2.h
-+++ b/arch/arm/mach-shmobile/include/mach/emev2.h
-@@ -1,9 +1,16 @@
- #ifndef __ASM_EMEV2_H__
- #define __ASM_EMEV2_H__
-
-+extern void emev2_map_io(void);
- extern void emev2_init_irq(void);
- extern void emev2_add_early_devices(void);
- extern void emev2_add_standard_devices(void);
- extern void emev2_clock_init(void);
-+extern void emev2_set_boot_vector(unsigned long value);
-+extern unsigned int emev2_get_core_count(void);
-+extern int emev2_platform_cpu_kill(unsigned int cpu);
-+extern void emev2_secondary_init(unsigned int cpu);
-+extern int emev2_boot_secondary(unsigned int cpu);
-+extern void emev2_smp_prepare_cpus(void);
-
- #endif /* __ASM_EMEV2_H__ */
-diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
-index 932ac8f..af24bbd 100644
---- a/arch/arm/mach-shmobile/platsmp.c
-+++ b/arch/arm/mach-shmobile/platsmp.c
-@@ -20,6 +20,7 @@
- #include <asm/hardware/gic.h>
- #include <asm/mach-types.h>
- #include <mach/common.h>
-+#include <mach/emev2.h>
-
- #ifdef CONFIG_ARCH_SH73A0
- #define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2() || \
-@@ -29,6 +30,7 @@
- #endif
-
- #define is_r8a7779() machine_is_marzen()
-+#define is_emev2() machine_is_kzm9d()
-
- static unsigned int __init shmobile_smp_get_core_count(void)
- {
-@@ -38,6 +40,9 @@ static unsigned int __init shmobile_smp_get_core_count(void)
- if (is_r8a7779())
- return r8a7779_get_core_count();
-
-+ if (is_emev2())
-+ return emev2_get_core_count();
-+
- return 1;
- }
-
-@@ -48,6 +53,9 @@ static void __init shmobile_smp_prepare_cpus(void)
-
- if (is_r8a7779())
- r8a7779_smp_prepare_cpus();
-+
-+ if (is_emev2())
-+ emev2_smp_prepare_cpus();
- }
-
- int shmobile_platform_cpu_kill(unsigned int cpu)
-@@ -55,6 +63,9 @@ int shmobile_platform_cpu_kill(unsigned int cpu)
- if (is_r8a7779())
- return r8a7779_platform_cpu_kill(cpu);
-
-+ if (is_emev2())
-+ return emev2_platform_cpu_kill(cpu);
-+
- return 1;
- }
-
-@@ -67,6 +78,9 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
-
- if (is_r8a7779())
- r8a7779_secondary_init(cpu);
-+
-+ if (is_emev2())
-+ emev2_secondary_init(cpu);
- }
-
- int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
-@@ -77,6 +91,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
- if (is_r8a7779())
- return r8a7779_boot_secondary(cpu);
-
-+ if (is_emev2())
-+ return emev2_boot_secondary(cpu);
-+
- return -ENOSYS;
- }
-
-diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
-index 9fff623..2a03a78 100644
---- a/arch/arm/mach-shmobile/setup-emev2.c
-+++ b/arch/arm/mach-shmobile/setup-emev2.c
-@@ -34,6 +34,30 @@
- #include <asm/mach/time.h>
- #include <asm/hardware/gic.h>
-
-+static struct map_desc emev2_io_desc[] __initdata = {
-+#ifdef CONFIG_SMP
-+ /* 128K entity map for 0xe0100000 (SMU) */
-+ {
-+ .virtual = 0xe0100000,
-+ .pfn = __phys_to_pfn(0xe0100000),
-+ .length = SZ_128K,
-+ .type = MT_DEVICE
-+ },
-+ /* 2M mapping for SCU + L2 controller */
-+ {
-+ .virtual = 0xf0000000,
-+ .pfn = __phys_to_pfn(0x1e000000),
-+ .length = SZ_2M,
-+ .type = MT_DEVICE
-+ },
-+#endif
-+};
-+
-+void __init emev2_map_io(void)
-+{
-+ iotable_init(emev2_io_desc, ARRAY_SIZE(emev2_io_desc));
-+}
-+
- /* UART */
- static struct resource uart0_resources[] = {
- [0] = {
-diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c
-new file mode 100644
-index 0000000..6a35c4a
---- /dev/null
-+++ b/arch/arm/mach-shmobile/smp-emev2.c
-@@ -0,0 +1,97 @@
-+/*
-+ * SMP support for Emma Mobile EV2
-+ *
-+ * Copyright (C) 2012 Renesas Solutions Corp.
-+ * Copyright (C) 2012 Magnus Damm
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; version 2 of the License.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/smp.h>
-+#include <linux/spinlock.h>
-+#include <linux/io.h>
-+#include <linux/delay.h>
-+#include <mach/common.h>
-+#include <mach/emev2.h>
-+#include <asm/smp_plat.h>
-+#include <asm/smp_scu.h>
-+#include <asm/hardware/gic.h>
-+#include <asm/cacheflush.h>
-+
-+#define EMEV2_SCU_BASE 0x1e000000
-+
-+static DEFINE_SPINLOCK(scu_lock);
-+static void __iomem *scu_base;
-+
-+static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
-+{
-+ unsigned long tmp;
-+
-+ /* we assume this code is running on a different cpu
-+ * than the one that is changing coherency setting */
-+ spin_lock(&scu_lock);
-+ tmp = readl(scu_base + 8);
-+ tmp &= ~clr;
-+ tmp |= set;
-+ writel(tmp, scu_base + 8);
-+ spin_unlock(&scu_lock);
-+
-+}
-+
-+unsigned int __init emev2_get_core_count(void)
-+{
-+ if (!scu_base) {
-+ scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
-+ emev2_clock_init(); /* need ioremapped SMU */
-+ }
-+
-+ WARN_ON_ONCE(!scu_base);
-+
-+ return scu_base ? scu_get_core_count(scu_base) : 1;
-+}
-+
-+int emev2_platform_cpu_kill(unsigned int cpu)
-+{
-+ return 0; /* not supported yet */
-+}
-+
-+void __cpuinit emev2_secondary_init(unsigned int cpu)
-+{
-+ gic_secondary_init(0);
-+}
-+
-+int __cpuinit emev2_boot_secondary(unsigned int cpu)
-+{
-+ cpu = cpu_logical_map(cpu);
-+
-+ /* enable cache coherency */
-+ modify_scu_cpu_psr(0, 3 << (cpu * 8));
-+
-+ /* Tell ROM loader about our vector (in headsmp.S) */
-+ emev2_set_boot_vector(__pa(shmobile_secondary_vector));
-+
-+ gic_raise_softirq(cpumask_of(cpu), 1);
-+ return 0;
-+}
-+
-+void __init emev2_smp_prepare_cpus(void)
-+{
-+ int cpu = cpu_logical_map(0);
-+
-+ scu_enable(scu_base);
-+
-+ /* enable cache coherency on CPU0 */
-+ modify_scu_cpu_psr(0, 3 << (cpu * 8));
-+}
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:29:27 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:10 +0900
-Subject: [PATCH 18/26] mach-shmobile: Emma Mobile EV2 SoC base support V3
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-19-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-This is V3 of the Emma Mobile EV2 SoC support.
-Included here is support for serial and timer
-devices which is just about enough to boot a kernel.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 7f627f0380cb5ba3e05bcaac31ecf40c1f508ec1)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/Kconfig | 5 +
- arch/arm/mach-shmobile/Makefile | 1 +
- arch/arm/mach-shmobile/clock-emev2.c | 226 +++++++++++++++++++++++++++
- arch/arm/mach-shmobile/include/mach/emev2.h | 9 ++
- arch/arm/mach-shmobile/setup-emev2.c | 180 +++++++++++++++++++++
- 5 files changed, 421 insertions(+)
- create mode 100644 arch/arm/mach-shmobile/clock-emev2.c
- create mode 100644 arch/arm/mach-shmobile/include/mach/emev2.h
- create mode 100644 arch/arm/mach-shmobile/setup-emev2.c
-
-diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
-index 80b64c5..3031ff8 100644
---- a/arch/arm/mach-shmobile/Kconfig
-+++ b/arch/arm/mach-shmobile/Kconfig
-@@ -41,6 +41,11 @@ config ARCH_R8A7779
- select ARM_GIC
- select ARCH_WANT_OPTIONAL_GPIOLIB
-
-+config ARCH_EMEV2
-+ bool "Emma Mobile EV2"
-+ select CPU_V7
-+ select ARM_GIC
-+
- comment "SH-Mobile Board Type"
-
- config MACH_G3EVM
-diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
-index 015c2d4..91f4470 100644
---- a/arch/arm/mach-shmobile/Makefile
-+++ b/arch/arm/mach-shmobile/Makefile
-@@ -12,6 +12,7 @@ obj-$(CONFIG_ARCH_SH7372) += setup-sh7372.o clock-sh7372.o intc-sh7372.o
- obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o
- obj-$(CONFIG_ARCH_R8A7740) += setup-r8a7740.o clock-r8a7740.o intc-r8a7740.o
- obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o clock-r8a7779.o intc-r8a7779.o
-+obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o clock-emev2.o
-
- # SMP objects
- smp-y := platsmp.o headsmp.o
-diff --git a/arch/arm/mach-shmobile/clock-emev2.c b/arch/arm/mach-shmobile/clock-emev2.c
-new file mode 100644
-index 0000000..73a1216
---- /dev/null
-+++ b/arch/arm/mach-shmobile/clock-emev2.c
-@@ -0,0 +1,226 @@
-+/*
-+ * Emma Mobile EV2 clock framework support
-+ *
-+ * Copyright (C) 2012 Magnus Damm
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; version 2 of the License.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/io.h>
-+#include <linux/sh_clk.h>
-+#include <linux/clkdev.h>
-+#include <mach/common.h>
-+
-+#define EMEV2_SMU_BASE 0xe0110000
-+
-+/* EMEV2 SMU registers */
-+#define USIAU0_RSTCTRL 0x094
-+#define USIBU1_RSTCTRL 0x0ac
-+#define USIBU2_RSTCTRL 0x0b0
-+#define USIBU3_RSTCTRL 0x0b4
-+#define STI_RSTCTRL 0x124
-+#define USIAU0GCLKCTRL 0x4a0
-+#define USIBU1GCLKCTRL 0x4b8
-+#define USIBU2GCLKCTRL 0x4bc
-+#define USIBU3GCLKCTRL 0x04c0
-+#define STIGCLKCTRL 0x528
-+#define USIAU0SCLKDIV 0x61c
-+#define USIB2SCLKDIV 0x65c
-+#define USIB3SCLKDIV 0x660
-+#define STI_CLKSEL 0x688
-+
-+/* not pretty, but hey */
-+static void __iomem *smu_base;
-+
-+static void emev2_smu_write(unsigned long value, int offs)
-+{
-+ BUG_ON(!smu_base || (offs >= PAGE_SIZE));
-+ iowrite32(value, smu_base + offs);
-+}
-+
-+static struct clk_mapping smu_mapping = {
-+ .phys = EMEV2_SMU_BASE,
-+ .len = PAGE_SIZE,
-+};
-+
-+/* Fixed 32 KHz root clock from C32K pin */
-+static struct clk c32k_clk = {
-+ .rate = 32768,
-+ .mapping = &smu_mapping,
-+};
-+
-+/* PLL3 multiplies C32K with 7000 */
-+static unsigned long pll3_recalc(struct clk *clk)
-+{
-+ return clk->parent->rate * 7000;
-+}
-+
-+static struct sh_clk_ops pll3_clk_ops = {
-+ .recalc = pll3_recalc,
-+};
-+
-+static struct clk pll3_clk = {
-+ .ops = &pll3_clk_ops,
-+ .parent = &c32k_clk,
-+};
-+
-+static struct clk *main_clks[] = {
-+ &c32k_clk,
-+ &pll3_clk,
-+};
-+
-+enum { SCLKDIV_USIAU0, SCLKDIV_USIBU2, SCLKDIV_USIBU1, SCLKDIV_USIBU3,
-+ SCLKDIV_NR };
-+
-+#define SCLKDIV(_reg, _shift) \
-+{ \
-+ .parent = &pll3_clk, \
-+ .enable_reg = IOMEM(EMEV2_SMU_BASE + (_reg)), \
-+ .enable_bit = _shift, \
-+}
-+
-+static struct clk sclkdiv_clks[SCLKDIV_NR] = {
-+ [SCLKDIV_USIAU0] = SCLKDIV(USIAU0SCLKDIV, 0),
-+ [SCLKDIV_USIBU2] = SCLKDIV(USIB2SCLKDIV, 16),
-+ [SCLKDIV_USIBU1] = SCLKDIV(USIB2SCLKDIV, 0),
-+ [SCLKDIV_USIBU3] = SCLKDIV(USIB3SCLKDIV, 0),
-+};
-+
-+enum { GCLK_USIAU0_SCLK, GCLK_USIBU1_SCLK, GCLK_USIBU2_SCLK, GCLK_USIBU3_SCLK,
-+ GCLK_STI_SCLK,
-+ GCLK_NR };
-+
-+#define GCLK_SCLK(_parent, _reg) \
-+{ \
-+ .parent = _parent, \
-+ .enable_reg = IOMEM(EMEV2_SMU_BASE + (_reg)), \
-+ .enable_bit = 1, /* SCLK_GCC */ \
-+}
-+
-+static struct clk gclk_clks[GCLK_NR] = {
-+ [GCLK_USIAU0_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIAU0],
-+ USIAU0GCLKCTRL),
-+ [GCLK_USIBU1_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU1],
-+ USIBU1GCLKCTRL),
-+ [GCLK_USIBU2_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU2],
-+ USIBU2GCLKCTRL),
-+ [GCLK_USIBU3_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU3],
-+ USIBU3GCLKCTRL),
-+ [GCLK_STI_SCLK] = GCLK_SCLK(&c32k_clk, STIGCLKCTRL),
-+};
-+
-+static int emev2_gclk_enable(struct clk *clk)
-+{
-+ iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
-+ clk->mapped_reg);
-+ return 0;
-+}
-+
-+static void emev2_gclk_disable(struct clk *clk)
-+{
-+ iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
-+ clk->mapped_reg);
-+}
-+
-+static struct sh_clk_ops emev2_gclk_clk_ops = {
-+ .enable = emev2_gclk_enable,
-+ .disable = emev2_gclk_disable,
-+ .recalc = followparent_recalc,
-+};
-+
-+static int __init emev2_gclk_register(struct clk *clks, int nr)
-+{
-+ struct clk *clkp;
-+ int ret = 0;
-+ int k;
-+
-+ for (k = 0; !ret && (k < nr); k++) {
-+ clkp = clks + k;
-+ clkp->ops = &emev2_gclk_clk_ops;
-+ ret |= clk_register(clkp);
-+ }
-+
-+ return ret;
-+}
-+
-+static unsigned long emev2_sclkdiv_recalc(struct clk *clk)
-+{
-+ unsigned int sclk_div;
-+
-+ sclk_div = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0xff;
-+
-+ return clk->parent->rate / (sclk_div + 1);
-+}
-+
-+static struct sh_clk_ops emev2_sclkdiv_clk_ops = {
-+ .recalc = emev2_sclkdiv_recalc,
-+};
-+
-+static int __init emev2_sclkdiv_register(struct clk *clks, int nr)
-+{
-+ struct clk *clkp;
-+ int ret = 0;
-+ int k;
-+
-+ for (k = 0; !ret && (k < nr); k++) {
-+ clkp = clks + k;
-+ clkp->ops = &emev2_sclkdiv_clk_ops;
-+ ret |= clk_register(clkp);
-+ }
-+
-+ return ret;
-+}
-+
-+static struct clk_lookup lookups[] = {
-+ CLKDEV_DEV_ID("serial8250-em.0", &gclk_clks[GCLK_USIAU0_SCLK]),
-+ CLKDEV_DEV_ID("serial8250-em.1", &gclk_clks[GCLK_USIBU1_SCLK]),
-+ CLKDEV_DEV_ID("serial8250-em.2", &gclk_clks[GCLK_USIBU2_SCLK]),
-+ CLKDEV_DEV_ID("serial8250-em.3", &gclk_clks[GCLK_USIBU3_SCLK]),
-+ CLKDEV_DEV_ID("em_sti.0", &gclk_clks[GCLK_STI_SCLK]),
-+};
-+
-+void __init emev2_clock_init(void)
-+{
-+ int k, ret = 0;
-+
-+ smu_base = ioremap(EMEV2_SMU_BASE, PAGE_SIZE);
-+ BUG_ON(!smu_base);
-+
-+ /* setup STI timer to run on 37.768 kHz and deassert reset */
-+ emev2_smu_write(0, STI_CLKSEL);
-+ emev2_smu_write(1, STI_RSTCTRL);
-+
-+ /* deassert reset for UART0->UART3 */
-+ emev2_smu_write(2, USIAU0_RSTCTRL);
-+ emev2_smu_write(2, USIBU1_RSTCTRL);
-+ emev2_smu_write(2, USIBU2_RSTCTRL);
-+ emev2_smu_write(2, USIBU3_RSTCTRL);
-+
-+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
-+ ret = clk_register(main_clks[k]);
-+
-+ if (!ret)
-+ ret = emev2_sclkdiv_register(sclkdiv_clks, SCLKDIV_NR);
-+
-+ if (!ret)
-+ ret = emev2_gclk_register(gclk_clks, GCLK_NR);
-+
-+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-+
-+ if (!ret)
-+ shmobile_clk_init();
-+ else
-+ panic("failed to setup emev2 clocks\n");
-+}
-diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h
-new file mode 100644
-index 0000000..92646c1
---- /dev/null
-+++ b/arch/arm/mach-shmobile/include/mach/emev2.h
-@@ -0,0 +1,9 @@
-+#ifndef __ASM_EMEV2_H__
-+#define __ASM_EMEV2_H__
-+
-+extern void emev2_init_irq(void);
-+extern void emev2_add_early_devices(void);
-+extern void emev2_add_standard_devices(void);
-+extern void emev2_clock_init(void);
-+
-+#endif /* __ASM_EMEV2_H__ */
-diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
-new file mode 100644
-index 0000000..9fff623
---- /dev/null
-+++ b/arch/arm/mach-shmobile/setup-emev2.c
-@@ -0,0 +1,180 @@
-+/*
-+ * Emma Mobile EV2 processor support
-+ *
-+ * Copyright (C) 2012 Magnus Damm
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; version 2 of the License.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/irq.h>
-+#include <linux/platform_device.h>
-+#include <linux/delay.h>
-+#include <linux/input.h>
-+#include <linux/io.h>
-+#include <mach/hardware.h>
-+#include <mach/common.h>
-+#include <mach/emev2.h>
-+#include <mach/irqs.h>
-+#include <asm/mach-types.h>
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/mach/time.h>
-+#include <asm/hardware/gic.h>
-+
-+/* UART */
-+static struct resource uart0_resources[] = {
-+ [0] = {
-+ .start = 0xe1020000,
-+ .end = 0xe1020037,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = 40,
-+ .flags = IORESOURCE_IRQ,
-+ }
-+};
-+
-+static struct platform_device uart0_device = {
-+ .name = "serial8250-em",
-+ .id = 0,
-+ .num_resources = ARRAY_SIZE(uart0_resources),
-+ .resource = uart0_resources,
-+};
-+
-+static struct resource uart1_resources[] = {
-+ [0] = {
-+ .start = 0xe1030000,
-+ .end = 0xe1030037,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = 41,
-+ .flags = IORESOURCE_IRQ,
-+ }
-+};
-+
-+static struct platform_device uart1_device = {
-+ .name = "serial8250-em",
-+ .id = 1,
-+ .num_resources = ARRAY_SIZE(uart1_resources),
-+ .resource = uart1_resources,
-+};
-+
-+static struct resource uart2_resources[] = {
-+ [0] = {
-+ .start = 0xe1040000,
-+ .end = 0xe1040037,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = 42,
-+ .flags = IORESOURCE_IRQ,
-+ }
-+};
-+
-+static struct platform_device uart2_device = {
-+ .name = "serial8250-em",
-+ .id = 2,
-+ .num_resources = ARRAY_SIZE(uart2_resources),
-+ .resource = uart2_resources,
-+};
-+
-+static struct resource uart3_resources[] = {
-+ [0] = {
-+ .start = 0xe1050000,
-+ .end = 0xe1050037,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = 43,
-+ .flags = IORESOURCE_IRQ,
-+ }
-+};
-+
-+static struct platform_device uart3_device = {
-+ .name = "serial8250-em",
-+ .id = 3,
-+ .num_resources = ARRAY_SIZE(uart3_resources),
-+ .resource = uart3_resources,
-+};
-+
-+/* STI */
-+static struct resource sti_resources[] = {
-+ [0] = {
-+ .name = "STI",
-+ .start = 0xe0180000,
-+ .end = 0xe0180053,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = 157,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device sti_device = {
-+ .name = "em_sti",
-+ .id = 0,
-+ .resource = sti_resources,
-+ .num_resources = ARRAY_SIZE(sti_resources),
-+};
-+
-+static struct platform_device *emev2_early_devices[] __initdata = {
-+ &uart0_device,
-+ &uart1_device,
-+ &uart2_device,
-+ &uart3_device,
-+};
-+
-+static struct platform_device *emev2_late_devices[] __initdata = {
-+ &sti_device,
-+};
-+
-+void __init emev2_add_standard_devices(void)
-+{
-+ emev2_clock_init();
-+
-+ platform_add_devices(emev2_early_devices,
-+ ARRAY_SIZE(emev2_early_devices));
-+
-+ platform_add_devices(emev2_late_devices,
-+ ARRAY_SIZE(emev2_late_devices));
-+}
-+
-+void __init emev2_add_early_devices(void)
-+{
-+ shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */
-+
-+ early_platform_add_devices(emev2_early_devices,
-+ ARRAY_SIZE(emev2_early_devices));
-+
-+ /* setup early console here as well */
-+ shmobile_setup_console();
-+}
-+
-+void __init emev2_init_irq(void)
-+{
-+ void __iomem *gic_dist_base;
-+ void __iomem *gic_cpu_base;
-+
-+ /* Static mappings, never released */
-+ gic_dist_base = ioremap(0xe0028000, PAGE_SIZE);
-+ gic_cpu_base = ioremap(0xe0020000, PAGE_SIZE);
-+ BUG_ON(!gic_dist_base || !gic_cpu_base);
-+
-+ /* Use GIC to handle interrupts */
-+ gic_init(0, 29, gic_dist_base, gic_cpu_base);
-+}
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:30:07 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:14 +0900
-Subject: [PATCH 22/26] mach-shmobile: KZM9D board Ethernet support V3
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-23-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-Tie in the on-board Ethernet controller on KZM9D
-and make use of the GPIO controller for external
-IRQ pin support.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 0c73f7bc124e1657a583d9dfb0d168a69005e2d3)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/board-kzm9d.c | 44 +++++++++++++++++++++++++++++++++-
- 1 file changed, 43 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c
-index 42fc479..be81f0f 100644
---- a/arch/arm/mach-shmobile/board-kzm9d.c
-+++ b/arch/arm/mach-shmobile/board-kzm9d.c
-@@ -20,18 +20,60 @@
-
- #include <linux/kernel.h>
- #include <linux/interrupt.h>
-+#include <linux/platform_device.h>
-+#include <linux/smsc911x.h>
- #include <mach/common.h>
- #include <mach/emev2.h>
- #include <asm/mach-types.h>
- #include <asm/mach/arch.h>
- #include <asm/hardware/gic.h>
-
-+/* Ether */
-+static struct resource smsc911x_resources[] = {
-+ [0] = {
-+ .start = 0x20000000,
-+ .end = 0x2000ffff,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = EMEV2_GPIO_IRQ(1),
-+ .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
-+ },
-+};
-+
-+static struct smsc911x_platform_config smsc911x_platdata = {
-+ .flags = SMSC911X_USE_32BIT,
-+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
-+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
-+};
-+
-+static struct platform_device smsc91x_device = {
-+ .name = "smsc911x",
-+ .id = 0,
-+ .dev = {
-+ .platform_data = &smsc911x_platdata,
-+ },
-+ .num_resources = ARRAY_SIZE(smsc911x_resources),
-+ .resource = smsc911x_resources,
-+};
-+
-+static struct platform_device *kzm9d_devices[] __initdata = {
-+ &smsc91x_device,
-+};
-+
-+void __init kzm9d_add_standard_devices(void)
-+{
-+ emev2_add_standard_devices();
-+
-+ platform_add_devices(kzm9d_devices, ARRAY_SIZE(kzm9d_devices));
-+}
-+
- MACHINE_START(KZM9D, "kzm9d")
- .map_io = emev2_map_io,
- .init_early = emev2_add_early_devices,
- .nr_irqs = NR_IRQS_LEGACY,
- .init_irq = emev2_init_irq,
- .handle_irq = gic_handle_irq,
-- .init_machine = emev2_add_standard_devices,
-+ .init_machine = kzm9d_add_standard_devices,
- .timer = &shmobile_timer,
- MACHINE_END
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:29:37 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:11 +0900
-Subject: [PATCH 19/26] mach-shmobile: KZM9D board support V3
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-20-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-V3 of basic KZM9D board support. At this point a quite
-thin layer that makes use of the Emma Mobile EV2 SoC code.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit c050fb10c425cf189da5ca9b84e948ec2fc99049)
-
-Conflicts:
-
- arch/arm/mach-shmobile/Kconfig
- arch/arm/mach-shmobile/Makefile
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/Kconfig | 4 +++
- arch/arm/mach-shmobile/Makefile | 1
- arch/arm/mach-shmobile/board-kzm9d.c | 36 +++++++++++++++++++++++++++++++++++
- 3 files changed, 41 insertions(+)
- create mode 100644 arch/arm/mach-shmobile/board-kzm9d.c
-
---- a/arch/arm/mach-shmobile/Kconfig
-+++ b/arch/arm/mach-shmobile/Kconfig
-@@ -112,6 +112,10 @@ config MACH_MARZEN
- depends on ARCH_R8A7779
- select ARCH_REQUIRE_GPIOLIB
-
-+config MACH_KZM9D
-+ bool "KZM9D board"
-+ depends on ARCH_EMEV2
-+
- config MACH_KZM9G
- bool "KZM-A9-GT board"
- depends on ARCH_SH73A0
---- a/arch/arm/mach-shmobile/Makefile
-+++ b/arch/arm/mach-shmobile/Makefile
-@@ -53,6 +53,7 @@ obj-$(CONFIG_MACH_KOTA2) += board-kota2.
- obj-$(CONFIG_MACH_BONITO) += board-bonito.o
- obj-$(CONFIG_MACH_MARZEN) += board-marzen.o
- obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o
-+obj-$(CONFIG_MACH_KZM9D) += board-kzm9d.o
- obj-$(CONFIG_MACH_KZM9G) += board-kzm9g.o
-
- # Framework support
---- /dev/null
-+++ b/arch/arm/mach-shmobile/board-kzm9d.c
-@@ -0,0 +1,36 @@
-+/*
-+ * kzm9d board support
-+ *
-+ * Copyright (C) 2012 Renesas Solutions Corp.
-+ * Copyright (C) 2012 Magnus Damm
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; version 2 of the License.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/interrupt.h>
-+#include <mach/common.h>
-+#include <mach/emev2.h>
-+#include <asm/mach-types.h>
-+#include <asm/mach/arch.h>
-+#include <asm/hardware/gic.h>
-+
-+MACHINE_START(KZM9D, "kzm9d")
-+ .init_early = emev2_add_early_devices,
-+ .nr_irqs = NR_IRQS_LEGACY,
-+ .init_irq = emev2_init_irq,
-+ .handle_irq = gic_handle_irq,
-+ .init_machine = emev2_add_standard_devices,
-+ .timer = &shmobile_timer,
-+MACHINE_END
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:30:29 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:17 +0900
-Subject: [PATCH 25/26] mach-shmobile: Use DT_MACHINE for KZM9D V3
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-26-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-Use DT_MACHINE_START() on the emev2 based KZM9D board.
-
-Also include a tiny DTS file to describe the board and
-update the Kconfig dependencies to select CONFIG_USE_OF.
-
-Update the SMP glue code to use OF for matching.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 450cca47d65b7500ba05d56770adbf8c758dc87d)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/boot/dts/emev2-kzm9d.dts | 26 ++++++++++++++++++++++++++
- arch/arm/mach-shmobile/Kconfig | 1 +
- arch/arm/mach-shmobile/board-kzm9d.c | 8 +++++++-
- arch/arm/mach-shmobile/platsmp.c | 2 +-
- 4 files changed, 35 insertions(+), 2 deletions(-)
- create mode 100644 arch/arm/boot/dts/emev2-kzm9d.dts
-
---- /dev/null
-+++ b/arch/arm/boot/dts/emev2-kzm9d.dts
-@@ -0,0 +1,26 @@
-+/*
-+ * Device Tree Source for the KZM9D board
-+ *
-+ * Copyright (C) 2012 Renesas Solutions Corp.
-+ *
-+ * 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.
-+ */
-+/dts-v1/;
-+
-+/include/ "emev2.dtsi"
-+
-+/ {
-+ model = "EMEV2 KZM9D Board";
-+ compatible = "renesas,kzm9d", "renesas,emev2";
-+
-+ memory {
-+ device_type = "memory";
-+ reg = <0x40000000 0x8000000>;
-+ };
-+
-+ chosen {
-+ bootargs = "console=ttyS1,115200n81";
-+ };
-+};
---- a/arch/arm/mach-shmobile/Kconfig
-+++ b/arch/arm/mach-shmobile/Kconfig
-@@ -116,6 +116,7 @@ config MACH_MARZEN
- config MACH_KZM9D
- bool "KZM9D board"
- depends on ARCH_EMEV2
-+ select USE_OF
-
- config MACH_KZM9G
- bool "KZM-A9-GT board"
---- a/arch/arm/mach-shmobile/board-kzm9d.c
-+++ b/arch/arm/mach-shmobile/board-kzm9d.c
-@@ -68,7 +68,12 @@ void __init kzm9d_add_standard_devices(v
- platform_add_devices(kzm9d_devices, ARRAY_SIZE(kzm9d_devices));
- }
-
--MACHINE_START(KZM9D, "kzm9d")
-+static const char *kzm9d_boards_compat_dt[] __initdata = {
-+ "renesas,kzm9d",
-+ NULL,
-+};
-+
-+DT_MACHINE_START(KZM9D_DT, "kzm9d")
- .map_io = emev2_map_io,
- .init_early = emev2_add_early_devices,
- .nr_irqs = NR_IRQS_LEGACY,
-@@ -76,4 +81,5 @@ MACHINE_START(KZM9D, "kzm9d")
- .handle_irq = gic_handle_irq,
- .init_machine = kzm9d_add_standard_devices,
- .timer = &shmobile_timer,
-+ .dt_compat = kzm9d_boards_compat_dt,
- MACHINE_END
---- a/arch/arm/mach-shmobile/platsmp.c
-+++ b/arch/arm/mach-shmobile/platsmp.c
-@@ -30,7 +30,7 @@
- #endif
-
- #define is_r8a7779() machine_is_marzen()
--#define is_emev2() machine_is_kzm9d()
-+#define is_emev2() of_machine_is_compatible("renesas,emev2")
-
- static unsigned int __init shmobile_smp_get_core_count(void)
- {
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:26:23 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:22:54 +0900
-Subject: [PATCH 02/26] serial/8250_pci: Clear FIFOs for Intel ME Serial Over Lan device on BI
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Sudhakar Mamillapalli <sudhakar@fb.com>, Nhan H Mai <nhan.h.mai@intel.com>, Dan Williams <dan.j.williams@intel.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-3-git-send-email-koba@kmckk.co.jp>
-
-
-From: Sudhakar Mamillapalli <sudhakar@fb.com>
-
-When using Serial Over Lan (SOL) over the virtual serial port in a Intel
-management engine (ME) device, on device reset the serial FIFOs need to
-be cleared to keep the FIFO indexes in-sync between the host and the
-engine.
-
-On a reset the serial device assertes BI, so using that as a cue FIFOs
-are cleared. So for this purpose a new handle_break callback has been
-added. One other problem is that the serial registers might temporarily
-go to 0 on reset of this device. So instead of using the IER register
-read, if 0 returned use the ier value in uart_8250_port. This is hidden
-under a custom serial_in.
-
-Cc: Nhan H Mai <nhan.h.mai@intel.com>
-Signed-off-by: Sudhakar Mamillapalli <sudhakar@fb.com>
-Acked-by: Alan Cox <alan@linux.intel.com>
-Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-(cherry picked from commit 0ad372b962d109323d18ac2aa118b2ad100eb8dd)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- drivers/tty/serial/8250/8250.c | 10 +++++++++
- drivers/tty/serial/8250/8250.h | 2 ++
- drivers/tty/serial/8250/8250_pci.c | 39 ++++++++++++++++++++++++++++++++++++
- 3 files changed, 51 insertions(+)
-
-diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
-index aed9363..c9ac4ea 100644
---- a/drivers/tty/serial/8250/8250.c
-+++ b/drivers/tty/serial/8250/8250.c
-@@ -568,6 +568,16 @@ static void serial8250_clear_fifos(struct uart_8250_port *p)
- }
- }
-
-+void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
-+{
-+ unsigned char fcr;
-+
-+ serial8250_clear_fifos(p);
-+ fcr = uart_config[p->port.type].fcr;
-+ serial_out(p, UART_FCR, fcr);
-+}
-+EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
-+
- /*
- * IER sleep support. UARTs which have EFRs need the "extended
- * capability" bit enabled. Note that on XR16C850s, we need to
-diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
-index 2868a1d..c9d0ebe 100644
---- a/drivers/tty/serial/8250/8250.h
-+++ b/drivers/tty/serial/8250/8250.h
-@@ -96,6 +96,8 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value)
- up->port.serial_out(&up->port, offset, value);
- }
-
-+void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p);
-+
- #if defined(__alpha__) && !defined(CONFIG_PCI)
- /*
- * Digital did something really horribly wrong with the OUT1 and OUT2
-diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
-index 3614973..5a4de9a 100644
---- a/drivers/tty/serial/8250/8250_pci.c
-+++ b/drivers/tty/serial/8250/8250_pci.c
-@@ -17,6 +17,7 @@
- #include <linux/slab.h>
- #include <linux/delay.h>
- #include <linux/tty.h>
-+#include <linux/serial_reg.h>
- #include <linux/serial_core.h>
- #include <linux/8250_pci.h>
- #include <linux/bitops.h>
-@@ -1092,11 +1093,49 @@ static int skip_tx_en_setup(struct serial_private *priv,
- return pci_default_setup(priv, board, port, idx);
- }
-
-+static void kt_handle_break(struct uart_port *p)
-+{
-+ struct uart_8250_port *up =
-+ container_of(p, struct uart_8250_port, port);
-+ /*
-+ * On receipt of a BI, serial device in Intel ME (Intel
-+ * management engine) needs to have its fifos cleared for sane
-+ * SOL (Serial Over Lan) output.
-+ */
-+ serial8250_clear_and_reinit_fifos(up);
-+}
-+
-+static unsigned int kt_serial_in(struct uart_port *p, int offset)
-+{
-+ struct uart_8250_port *up =
-+ container_of(p, struct uart_8250_port, port);
-+ unsigned int val;
-+
-+ /*
-+ * When the Intel ME (management engine) gets reset its serial
-+ * port registers could return 0 momentarily. Functions like
-+ * serial8250_console_write, read and save the IER, perform
-+ * some operation and then restore it. In order to avoid
-+ * setting IER register inadvertently to 0, if the value read
-+ * is 0, double check with ier value in uart_8250_port and use
-+ * that instead. up->ier should be the same value as what is
-+ * currently configured.
-+ */
-+ val = inb(p->iobase + offset);
-+ if (offset == UART_IER) {
-+ if (val == 0)
-+ val = up->ier;
-+ }
-+ return val;
-+}
-+
- static int kt_serial_setup(struct serial_private *priv,
- const struct pciserial_board *board,
- struct uart_port *port, int idx)
- {
- port->flags |= UPF_BUG_THRE;
-+ port->serial_in = kt_serial_in;
-+ port->handle_break = kt_handle_break;
- return skip_tx_en_setup(priv, board, port, idx);
- }
-
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:26:47 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:22:55 +0900
-Subject: [PATCH 03/26] serial/8250_pci: fix suspend/resume vs init/exit quirks
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Dan Williams <dan.j.williams@intel.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-4-git-send-email-koba@kmckk.co.jp>
-
-
-From: Dan Williams <dan.j.williams@intel.com>
-
-Commit e86ff4a6 "serial/8250_pci: init-quirk msi support for kt serial
-controller" introduced a regression in suspend/resume by causing msi's
-to be enabled twice without an intervening disable.
-
-00:16.3 Serial controller: Intel Corporation Patsburg KT Controller (rev 05) (prog-if 02 [16550])
- Subsystem: Intel Corporation Device 7270
- Flags: bus master, 66MHz, fast devsel, latency 0, IRQ 72
- I/O ports at 4080 [size=8]
- Memory at d1c30000 (32-bit, non-prefetchable) [size=4K]
- Capabilities: [c8] Power Management version 3
- Capabilities: [d0] MSI: Enable+ Count=1/1 Maskable- 64bit+
- Kernel driver in use: serial
-
-[ 365.250523] sysfs: cannot create duplicate filename '/devices/pci0000:00/0000:00:16.3/msi_irqs'
-[ 365.250525] Modules linked in: nls_utf8 ipv6 uinput sg iTCO_wdt
- iTCO_vendor_support ioatdma dca i2c_i801 i2c_core wmi sd_mod ahci libahci isci
- libsas libata scsi_transport_sas [last unloaded: scsi_wait_scan]
-[ 365.250540] Pid: 9030, comm: kworker/u:1 Tainted: G W 3.3.0-isci-3.0.213+ #1
-[ 365.250542] Call Trace:
-[ 365.250545] [<ffffffff8115e955>] ? sysfs_add_one+0x99/0xad
-[ 365.250548] [<ffffffff8102db8b>] warn_slowpath_common+0x85/0x9e
-[ 365.250551] [<ffffffff8102dc96>] warn_slowpath_fmt+0x6e/0x70
-[ 365.250555] [<ffffffff8115e8fa>] ? sysfs_add_one+0x3e/0xad
-[ 365.250558] [<ffffffff8115e8b4>] ? sysfs_pathname+0x3c/0x44
-[ 365.250561] [<ffffffff8115e8b4>] ? sysfs_pathname+0x3c/0x44
-[ 365.250564] [<ffffffff8115e8b4>] ? sysfs_pathname+0x3c/0x44
-[ 365.250567] [<ffffffff8115e8b4>] ? sysfs_pathname+0x3c/0x44
-[ 365.250570] [<ffffffff8115e955>] sysfs_add_one+0x99/0xad
-[ 365.250573] [<ffffffff8115f031>] create_dir+0x72/0xa5
-[ 365.250577] [<ffffffff8115f194>] sysfs_create_dir+0xa2/0xbe
-[ 365.250581] [<ffffffff81262463>] kobject_add_internal+0x126/0x1f8
-[ 365.250585] [<ffffffff8126255b>] kset_register+0x26/0x3f
-[ 365.250588] [<ffffffff8126275a>] kset_create_and_add+0x62/0x7c
-[ 365.250592] [<ffffffff81293619>] populate_msi_sysfs+0x34/0x103
-[ 365.250595] [<ffffffff81293e1c>] pci_enable_msi_block+0x1b3/0x216
-[ 365.250599] [<ffffffff81303f7c>] try_enable_msi+0x13/0x17
-[ 365.250603] [<ffffffff81303fb3>] pciserial_resume_ports+0x21/0x42
-[ 365.250607] [<ffffffff81304041>] pciserial_resume_one+0x50/0x57
-[ 365.250610] [<ffffffff81283e1a>] pci_legacy_resume+0x38/0x47
-[ 365.250613] [<ffffffff81283e7d>] pci_pm_restore+0x54/0x87
-[ 365.250616] [<ffffffff81283e29>] ? pci_legacy_resume+0x47/0x47
-[ 365.250619] [<ffffffff8131e9e8>] dpm_run_callback+0x48/0x7b
-[ 365.250623] [<ffffffff8131f39a>] device_resume+0x342/0x394
-[ 365.250626] [<ffffffff8131f5b7>] async_resume+0x21/0x49
-
-That patch has since been reverted, but by inspection it seems that
-pciserial_suspend_ports() should be invoking .exit() quirks to release
-resources acquired during .init().
-
-Acked-by: Alan Cox <alan@linux.intel.com>
-Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-(cherry picked from commit 5f1a38952b7e932a1c169c28917b9a831f641bcc)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- drivers/tty/serial/8250/8250_pci.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/tty/serial/8250/8250_pci.c
-+++ b/drivers/tty/serial/8250/8250_pci.c
-@@ -2834,6 +2834,12 @@ void pciserial_suspend_ports(struct seri
- for (i = 0; i < priv->nr; i++)
- if (priv->line[i] >= 0)
- serial8250_suspend_port(priv->line[i]);
-+
-+ /*
-+ * Ensure that every init quirk is properly torn down
-+ */
-+ if (priv->quirk->exit)
-+ priv->quirk->exit(priv->dev);
- }
- EXPORT_SYMBOL_GPL(pciserial_suspend_ports);
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:26:58 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:22:56 +0900
-Subject: [PATCH 04/26] serial8250: Add dl_read()/dl_write() callbacks
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-5-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-Convert serial_dl_read() and serial_dl_write() from macro
-to 8250 specific callbacks. This change makes it easier to
-support 8250 hardware with non-standard DLL and DLM register
-configurations such as Alchemy, RM9K and upcoming Emma Mobile
-UART hardware.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Acked-by: Alan Cox <alan@linux.intel.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-(cherry picked from commit cc419fa0d38c425e4ea7bffeed931b07b0a3e461)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- drivers/tty/serial/8250/8250.c | 117 ++++++++++++++++++++++------------------
- drivers/tty/serial/8250/8250.h | 14 +++++
- 2 files changed, 78 insertions(+), 53 deletions(-)
-
-diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
-index c9ac4ea..590ee85 100644
---- a/drivers/tty/serial/8250/8250.c
-+++ b/drivers/tty/serial/8250/8250.c
-@@ -284,6 +284,66 @@ static const struct serial8250_config uart_config[] = {
- },
- };
-
-+/* Uart divisor latch read */
-+static int default_dl_read(struct uart_8250_port *up)
-+{
-+ return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
-+}
-+
-+/* Uart divisor latch write */
-+static void default_dl_write(struct uart_8250_port *up, int value)
-+{
-+ serial_out(up, UART_DLL, value & 0xff);
-+ serial_out(up, UART_DLM, value >> 8 & 0xff);
-+}
-+
-+#if defined(CONFIG_MIPS_ALCHEMY)
-+/* Au1x00 haven't got a standard divisor latch */
-+static int _serial_dl_read(struct uart_8250_port *up)
-+{
-+ if (up->port.iotype == UPIO_AU)
-+ return __raw_readl(up->port.membase + 0x28);
-+ else
-+ return default_dl_read(up);
-+}
-+
-+static void _serial_dl_write(struct uart_8250_port *up, int value)
-+{
-+ if (up->port.iotype == UPIO_AU)
-+ __raw_writel(value, up->port.membase + 0x28);
-+ else
-+ default_dl_write(up, value);
-+}
-+#elif defined(CONFIG_SERIAL_8250_RM9K)
-+static int _serial_dl_read(struct uart_8250_port *up)
-+{
-+ return (up->port.iotype == UPIO_RM9000) ?
-+ (((__raw_readl(up->port.membase + 0x10) << 8) |
-+ (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
-+ default_dl_read(up);
-+}
-+
-+static void _serial_dl_write(struct uart_8250_port *up, int value)
-+{
-+ if (up->port.iotype == UPIO_RM9000) {
-+ __raw_writel(value, up->port.membase + 0x08);
-+ __raw_writel(value >> 8, up->port.membase + 0x10);
-+ } else {
-+ default_dl_write(up, value);
-+ }
-+}
-+#else
-+static int _serial_dl_read(struct uart_8250_port *up)
-+{
-+ return default_dl_read(up);
-+}
-+
-+static void _serial_dl_write(struct uart_8250_port *up, int value)
-+{
-+ default_dl_write(up, value);
-+}
-+#endif
-+
- #if defined(CONFIG_MIPS_ALCHEMY)
-
- /* Au1x00 UART hardware has a weird register layout */
-@@ -434,6 +494,10 @@ static void set_io_from_upio(struct uart_port *p)
- {
- struct uart_8250_port *up =
- container_of(p, struct uart_8250_port, port);
-+
-+ up->dl_read = _serial_dl_read;
-+ up->dl_write = _serial_dl_write;
-+
- switch (p->iotype) {
- case UPIO_HUB6:
- p->serial_in = hub6_serial_in;
-@@ -481,59 +545,6 @@ serial_port_out_sync(struct uart_port *p, int offset, int value)
- }
- }
-
--/* Uart divisor latch read */
--static inline int _serial_dl_read(struct uart_8250_port *up)
--{
-- return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
--}
--
--/* Uart divisor latch write */
--static inline void _serial_dl_write(struct uart_8250_port *up, int value)
--{
-- serial_out(up, UART_DLL, value & 0xff);
-- serial_out(up, UART_DLM, value >> 8 & 0xff);
--}
--
--#if defined(CONFIG_MIPS_ALCHEMY)
--/* Au1x00 haven't got a standard divisor latch */
--static int serial_dl_read(struct uart_8250_port *up)
--{
-- if (up->port.iotype == UPIO_AU)
-- return __raw_readl(up->port.membase + 0x28);
-- else
-- return _serial_dl_read(up);
--}
--
--static void serial_dl_write(struct uart_8250_port *up, int value)
--{
-- if (up->port.iotype == UPIO_AU)
-- __raw_writel(value, up->port.membase + 0x28);
-- else
-- _serial_dl_write(up, value);
--}
--#elif defined(CONFIG_SERIAL_8250_RM9K)
--static int serial_dl_read(struct uart_8250_port *up)
--{
-- return (up->port.iotype == UPIO_RM9000) ?
-- (((__raw_readl(up->port.membase + 0x10) << 8) |
-- (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
-- _serial_dl_read(up);
--}
--
--static void serial_dl_write(struct uart_8250_port *up, int value)
--{
-- if (up->port.iotype == UPIO_RM9000) {
-- __raw_writel(value, up->port.membase + 0x08);
-- __raw_writel(value >> 8, up->port.membase + 0x10);
-- } else {
-- _serial_dl_write(up, value);
-- }
--}
--#else
--#define serial_dl_read(up) _serial_dl_read(up)
--#define serial_dl_write(up, value) _serial_dl_write(up, value)
--#endif
--
- /*
- * For the 16C950
- */
-diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
-index c9d0ebe..f9719d1 100644
---- a/drivers/tty/serial/8250/8250.h
-+++ b/drivers/tty/serial/8250/8250.h
-@@ -37,6 +37,10 @@ struct uart_8250_port {
- unsigned char lsr_saved_flags;
- #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
- unsigned char msr_saved_flags;
-+
-+ /* 8250 specific callbacks */
-+ int (*dl_read)(struct uart_8250_port *);
-+ void (*dl_write)(struct uart_8250_port *, int);
- };
-
- struct old_serial_port {
-@@ -98,6 +102,16 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value)
-
- void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p);
-
-+static inline int serial_dl_read(struct uart_8250_port *up)
-+{
-+ return up->dl_read(up);
-+}
-+
-+static inline void serial_dl_write(struct uart_8250_port *up, int value)
-+{
-+ up->dl_write(up, value);
-+}
-+
- #if defined(__alpha__) && !defined(CONFIG_PCI)
- /*
- * Digital did something really horribly wrong with the OUT1 and OUT2
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:27:25 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:22:59 +0900
-Subject: [PATCH 07/26] serial8250: Clean up default map and dl code
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-8-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-Get rid of unused functions and macros now when
-Alchemy and RM9K are converted over to callbacks.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Acked-by: Alan Cox <alan@linux.intel.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-(cherry picked from commit e8155629ff19e05722ba057d1521baec270d780e)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- drivers/tty/serial/8250/8250.c | 38 ++++++++++++--------------------------
- 1 file changed, 12 insertions(+), 26 deletions(-)
-
-diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
-index cc398b1..662188d 100644
---- a/drivers/tty/serial/8250/8250.c
-+++ b/drivers/tty/serial/8250/8250.c
-@@ -285,28 +285,18 @@ static const struct serial8250_config uart_config[] = {
- };
-
- /* Uart divisor latch read */
--static int default_dl_read(struct uart_8250_port *up)
-+static int default_serial_dl_read(struct uart_8250_port *up)
- {
- return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
- }
-
- /* Uart divisor latch write */
--static void default_dl_write(struct uart_8250_port *up, int value)
-+static void default_serial_dl_write(struct uart_8250_port *up, int value)
- {
- serial_out(up, UART_DLL, value & 0xff);
- serial_out(up, UART_DLM, value >> 8 & 0xff);
- }
-
--static int _serial_dl_read(struct uart_8250_port *up)
--{
-- return default_dl_read(up);
--}
--
--static void _serial_dl_write(struct uart_8250_port *up, int value)
--{
-- default_dl_write(up, value);
--}
--
- #ifdef CONFIG_MIPS_ALCHEMY
-
- /* Au1x00 UART hardware has a weird register layout */
-@@ -403,57 +393,53 @@ static void rm9k_serial_dl_write(struct uart_8250_port *up, int value)
-
- #endif
-
--/* sane hardware needs no mapping */
--#define map_8250_in_reg(up, offset) (offset)
--#define map_8250_out_reg(up, offset) (offset)
--
- static unsigned int hub6_serial_in(struct uart_port *p, int offset)
- {
-- offset = map_8250_in_reg(p, offset) << p->regshift;
-+ offset = offset << p->regshift;
- outb(p->hub6 - 1 + offset, p->iobase);
- return inb(p->iobase + 1);
- }
-
- static void hub6_serial_out(struct uart_port *p, int offset, int value)
- {
-- offset = map_8250_out_reg(p, offset) << p->regshift;
-+ offset = offset << p->regshift;
- outb(p->hub6 - 1 + offset, p->iobase);
- outb(value, p->iobase + 1);
- }
-
- static unsigned int mem_serial_in(struct uart_port *p, int offset)
- {
-- offset = map_8250_in_reg(p, offset) << p->regshift;
-+ offset = offset << p->regshift;
- return readb(p->membase + offset);
- }
-
- static void mem_serial_out(struct uart_port *p, int offset, int value)
- {
-- offset = map_8250_out_reg(p, offset) << p->regshift;
-+ offset = offset << p->regshift;
- writeb(value, p->membase + offset);
- }
-
- static void mem32_serial_out(struct uart_port *p, int offset, int value)
- {
-- offset = map_8250_out_reg(p, offset) << p->regshift;
-+ offset = offset << p->regshift;
- writel(value, p->membase + offset);
- }
-
- static unsigned int mem32_serial_in(struct uart_port *p, int offset)
- {
-- offset = map_8250_in_reg(p, offset) << p->regshift;
-+ offset = offset << p->regshift;
- return readl(p->membase + offset);
- }
-
- static unsigned int io_serial_in(struct uart_port *p, int offset)
- {
-- offset = map_8250_in_reg(p, offset) << p->regshift;
-+ offset = offset << p->regshift;
- return inb(p->iobase + offset);
- }
-
- static void io_serial_out(struct uart_port *p, int offset, int value)
- {
-- offset = map_8250_out_reg(p, offset) << p->regshift;
-+ offset = offset << p->regshift;
- outb(value, p->iobase + offset);
- }
-
-@@ -464,8 +450,8 @@ static void set_io_from_upio(struct uart_port *p)
- struct uart_8250_port *up =
- container_of(p, struct uart_8250_port, port);
-
-- up->dl_read = _serial_dl_read;
-- up->dl_write = _serial_dl_write;
-+ up->dl_read = default_serial_dl_read;
-+ up->dl_write = default_serial_dl_write;
-
- switch (p->iotype) {
- case UPIO_HUB6:
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:27:39 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:03 +0900
-Subject: [PATCH 11/26] serial8250-em: Add DT support
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-12-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-Update the 8250_em driver to support DT.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-(cherry picked from commit 3e62c413fb0c75c8cfaf086d00a9ecc6b55009d6)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- drivers/tty/serial/8250/8250_em.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
-index be6c289..3a0363e 100644
---- a/drivers/tty/serial/8250/8250_em.c
-+++ b/drivers/tty/serial/8250/8250_em.c
-@@ -163,9 +163,16 @@ static int __devexit serial8250_em_remove(struct platform_device *pdev)
- return 0;
- }
-
-+static const struct of_device_id serial8250_em_dt_ids[] __devinitconst = {
-+ { .compatible = "renesas,em-uart", },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, serial8250_em_dt_ids);
-+
- static struct platform_driver serial8250_em_platform_driver = {
- .driver = {
- .name = "serial8250-em",
-+ .of_match_table = serial8250_em_dt_ids,
- .owner = THIS_MODULE,
- },
- .probe = serial8250_em_probe,
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:27:34 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:02 +0900
-Subject: [PATCH 10/26] serial8250-em: clk_get() IS_ERR() error handling fix
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-11-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-Update the 8250_em driver to correctly handle the case
-where no clock is associated with the device.
-
-The return value of clk_get() needs to be checked with
-IS_ERR() to avoid NULL pointer referencing.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-(cherry picked from commit 94e792ab66d696aad2e52c91bae4cfbeefe4c9f6)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- drivers/tty/serial/8250/8250_em.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
-index ff42542..be6c289 100644
---- a/drivers/tty/serial/8250/8250_em.c
-+++ b/drivers/tty/serial/8250/8250_em.c
-@@ -110,8 +110,9 @@ static int __devinit serial8250_em_probe(struct platform_device *pdev)
- }
-
- priv->sclk = clk_get(&pdev->dev, "sclk");
-- if (!priv->sclk) {
-+ if (IS_ERR(priv->sclk)) {
- dev_err(&pdev->dev, "unable to get clock\n");
-+ ret = PTR_ERR(priv->sclk);
- goto err1;
- }
-
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:27:32 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:01 +0900
-Subject: [PATCH 09/26] serial8250-em: Emma Mobile UART driver V2
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-10-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-This is V2 of the Emma Mobile 8250 platform driver.
-
-The hardware itself has according to the data sheet
-up to 64 byte FIFOs but at this point we only make
-use of the 16550 compatible mode.
-
-To support this piece of hardware the common UART
-registers need to be remapped, and the access size
-differences need to be handled.
-
-The DLL and DLM registers can due to offset collision
-not be remapped easily, and because of that this
-driver makes use of ->dl_read() and ->dl_write()
-callbacks. This in turn requires a registration
-function that takes 8250-specific paramenters.
-
-Future potential enhancements include DT support,
-early platform driver console and fine grained PM.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Acked-by: Alan Cox <alan@linux.intel.com>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-(cherry picked from commit 22886ee96895b7a9f9d06da4dc9420b61b4ef1f7)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- drivers/tty/serial/8250/8250_em.c | 178 +++++++++++++++++++++++++++++++++++++
- drivers/tty/serial/8250/Kconfig | 8 ++
- drivers/tty/serial/8250/Makefile | 1 +
- 3 files changed, 187 insertions(+)
- create mode 100644 drivers/tty/serial/8250/8250_em.c
-
-diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
-new file mode 100644
-index 0000000..ff42542
---- /dev/null
-+++ b/drivers/tty/serial/8250/8250_em.c
-@@ -0,0 +1,178 @@
-+/*
-+ * Renesas Emma Mobile 8250 driver
-+ *
-+ * Copyright (C) 2012 Magnus Damm
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/device.h>
-+#include <linux/init.h>
-+#include <linux/io.h>
-+#include <linux/module.h>
-+#include <linux/serial_8250.h>
-+#include <linux/serial_core.h>
-+#include <linux/serial_reg.h>
-+#include <linux/platform_device.h>
-+#include <linux/clk.h>
-+#include <linux/slab.h>
-+
-+#include "8250.h"
-+
-+#define UART_DLL_EM 9
-+#define UART_DLM_EM 10
-+
-+struct serial8250_em_priv {
-+ struct clk *sclk;
-+ int line;
-+};
-+
-+static void serial8250_em_serial_out(struct uart_port *p, int offset, int value)
-+{
-+ switch (offset) {
-+ case UART_TX: /* TX @ 0x00 */
-+ writeb(value, p->membase);
-+ break;
-+ case UART_FCR: /* FCR @ 0x0c (+1) */
-+ case UART_LCR: /* LCR @ 0x10 (+1) */
-+ case UART_MCR: /* MCR @ 0x14 (+1) */
-+ case UART_SCR: /* SCR @ 0x20 (+1) */
-+ writel(value, p->membase + ((offset + 1) << 2));
-+ break;
-+ case UART_IER: /* IER @ 0x04 */
-+ value &= 0x0f; /* only 4 valid bits - not Xscale */
-+ /* fall-through */
-+ case UART_DLL_EM: /* DLL @ 0x24 (+9) */
-+ case UART_DLM_EM: /* DLM @ 0x28 (+9) */
-+ writel(value, p->membase + (offset << 2));
-+ }
-+}
-+
-+static unsigned int serial8250_em_serial_in(struct uart_port *p, int offset)
-+{
-+ switch (offset) {
-+ case UART_RX: /* RX @ 0x00 */
-+ return readb(p->membase);
-+ case UART_MCR: /* MCR @ 0x14 (+1) */
-+ case UART_LSR: /* LSR @ 0x18 (+1) */
-+ case UART_MSR: /* MSR @ 0x1c (+1) */
-+ case UART_SCR: /* SCR @ 0x20 (+1) */
-+ return readl(p->membase + ((offset + 1) << 2));
-+ case UART_IER: /* IER @ 0x04 */
-+ case UART_IIR: /* IIR @ 0x08 */
-+ case UART_DLL_EM: /* DLL @ 0x24 (+9) */
-+ case UART_DLM_EM: /* DLM @ 0x28 (+9) */
-+ return readl(p->membase + (offset << 2));
-+ }
-+ return 0;
-+}
-+
-+static int serial8250_em_serial_dl_read(struct uart_8250_port *up)
-+{
-+ return serial_in(up, UART_DLL_EM) | serial_in(up, UART_DLM_EM) << 8;
-+}
-+
-+static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value)
-+{
-+ serial_out(up, UART_DLL_EM, value & 0xff);
-+ serial_out(up, UART_DLM_EM, value >> 8 & 0xff);
-+}
-+
-+static int __devinit serial8250_em_probe(struct platform_device *pdev)
-+{
-+ struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-+ struct serial8250_em_priv *priv;
-+ struct uart_8250_port up;
-+ int ret = -EINVAL;
-+
-+ if (!regs || !irq) {
-+ dev_err(&pdev->dev, "missing registers or irq\n");
-+ goto err0;
-+ }
-+
-+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-+ if (!priv) {
-+ dev_err(&pdev->dev, "unable to allocate private data\n");
-+ ret = -ENOMEM;
-+ goto err0;
-+ }
-+
-+ priv->sclk = clk_get(&pdev->dev, "sclk");
-+ if (!priv->sclk) {
-+ dev_err(&pdev->dev, "unable to get clock\n");
-+ goto err1;
-+ }
-+
-+ memset(&up, 0, sizeof(up));
-+ up.port.mapbase = regs->start;
-+ up.port.irq = irq->start;
-+ up.port.type = PORT_UNKNOWN;
-+ up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP;
-+ up.port.dev = &pdev->dev;
-+ up.port.private_data = priv;
-+
-+ clk_enable(priv->sclk);
-+ up.port.uartclk = clk_get_rate(priv->sclk);
-+
-+ up.port.iotype = UPIO_MEM32;
-+ up.port.serial_in = serial8250_em_serial_in;
-+ up.port.serial_out = serial8250_em_serial_out;
-+ up.dl_read = serial8250_em_serial_dl_read;
-+ up.dl_write = serial8250_em_serial_dl_write;
-+
-+ ret = serial8250_register_8250_port(&up);
-+ if (ret < 0) {
-+ dev_err(&pdev->dev, "unable to register 8250 port\n");
-+ goto err2;
-+ }
-+
-+ priv->line = ret;
-+ platform_set_drvdata(pdev, priv);
-+ return 0;
-+
-+ err2:
-+ clk_disable(priv->sclk);
-+ clk_put(priv->sclk);
-+ err1:
-+ kfree(priv);
-+ err0:
-+ return ret;
-+}
-+
-+static int __devexit serial8250_em_remove(struct platform_device *pdev)
-+{
-+ struct serial8250_em_priv *priv = platform_get_drvdata(pdev);
-+
-+ serial8250_unregister_port(priv->line);
-+ clk_disable(priv->sclk);
-+ clk_put(priv->sclk);
-+ kfree(priv);
-+ return 0;
-+}
-+
-+static struct platform_driver serial8250_em_platform_driver = {
-+ .driver = {
-+ .name = "serial8250-em",
-+ .owner = THIS_MODULE,
-+ },
-+ .probe = serial8250_em_probe,
-+ .remove = __devexit_p(serial8250_em_remove),
-+};
-+
-+module_platform_driver(serial8250_em_platform_driver);
-+
-+MODULE_AUTHOR("Magnus Damm");
-+MODULE_DESCRIPTION("Renesas Emma Mobile 8250 Driver");
-+MODULE_LICENSE("GPL v2");
-diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
-index 591f801..8bc7ecb 100644
---- a/drivers/tty/serial/8250/Kconfig
-+++ b/drivers/tty/serial/8250/Kconfig
-@@ -278,3 +278,11 @@ config SERIAL_8250_DW
- help
- Selecting this option will enable handling of the extra features
- present in the Synopsys DesignWare APB UART.
-+
-+config SERIAL_8250_EM
-+ tristate "Support for Emma Mobile intergrated serial port"
-+ depends on SERIAL_8250 && ARM && HAVE_CLK
-+ help
-+ Selecting this option will add support for the integrated serial
-+ port hardware found on the Emma Mobile line of processors.
-+ If unsure, say N.
-diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
-index 867bba7..3f35eac 100644
---- a/drivers/tty/serial/8250/Makefile
-+++ b/drivers/tty/serial/8250/Makefile
-@@ -18,3 +18,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
- obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
- obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o
- obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o
-+obj-$(CONFIG_SERIAL_8250_EM) += 8250_em.o
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:27:28 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:23:00 +0900
-Subject: [PATCH 08/26] serial8250: Introduce serial8250_register_8250_port()
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-9-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-Introduce yet another 8250 registration function.
-This time it is serial8250_register_8250_port() and it
-allows us to register 8250 hardware instances using struct
-uart_8250_port. The new function makes it possible to
-register 8250 hardware that makes use of 8250 specific
-callbacks such as ->dl_read() and ->dl_write().
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Acked-by: Alan Cox <alan@linux.intel.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-(cherry picked from commit f73fa05b90eb8c0dd3230c364cf1107f4f8f3848)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- drivers/tty/serial/8250/8250.c | 91 ++++++++++++++++++++++++++--------------
- include/linux/serial_8250.h | 1 +
- 2 files changed, 60 insertions(+), 32 deletions(-)
-
-diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
-index 662188d..47d061b 100644
---- a/drivers/tty/serial/8250/8250.c
-+++ b/drivers/tty/serial/8250/8250.c
-@@ -3112,7 +3112,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
- }
-
- /**
-- * serial8250_register_port - register a serial port
-+ * serial8250_register_8250_port - register a serial port
- * @port: serial port template
- *
- * Configure the serial port specified by the request. If the
-@@ -3124,52 +3124,56 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
- *
- * On success the port is ready to use and the line number is returned.
- */
--int serial8250_register_port(struct uart_port *port)
-+int serial8250_register_8250_port(struct uart_8250_port *up)
- {
- struct uart_8250_port *uart;
- int ret = -ENOSPC;
-
-- if (port->uartclk == 0)
-+ if (up->port.uartclk == 0)
- return -EINVAL;
-
- mutex_lock(&serial_mutex);
-
-- uart = serial8250_find_match_or_unused(port);
-+ uart = serial8250_find_match_or_unused(&up->port);
- if (uart) {
- uart_remove_one_port(&serial8250_reg, &uart->port);
-
-- uart->port.iobase = port->iobase;
-- uart->port.membase = port->membase;
-- uart->port.irq = port->irq;
-- uart->port.irqflags = port->irqflags;
-- uart->port.uartclk = port->uartclk;
-- uart->port.fifosize = port->fifosize;
-- uart->port.regshift = port->regshift;
-- uart->port.iotype = port->iotype;
-- uart->port.flags = port->flags | UPF_BOOT_AUTOCONF;
-- uart->port.mapbase = port->mapbase;
-- uart->port.private_data = port->private_data;
-- if (port->dev)
-- uart->port.dev = port->dev;
--
-- if (port->flags & UPF_FIXED_TYPE)
-- serial8250_init_fixed_type_port(uart, port->type);
-+ uart->port.iobase = up->port.iobase;
-+ uart->port.membase = up->port.membase;
-+ uart->port.irq = up->port.irq;
-+ uart->port.irqflags = up->port.irqflags;
-+ uart->port.uartclk = up->port.uartclk;
-+ uart->port.fifosize = up->port.fifosize;
-+ uart->port.regshift = up->port.regshift;
-+ uart->port.iotype = up->port.iotype;
-+ uart->port.flags = up->port.flags | UPF_BOOT_AUTOCONF;
-+ uart->port.mapbase = up->port.mapbase;
-+ uart->port.private_data = up->port.private_data;
-+ if (up->port.dev)
-+ uart->port.dev = up->port.dev;
-+
-+ if (up->port.flags & UPF_FIXED_TYPE)
-+ serial8250_init_fixed_type_port(uart, up->port.type);
-
- set_io_from_upio(&uart->port);
- /* Possibly override default I/O functions. */
-- if (port->serial_in)
-- uart->port.serial_in = port->serial_in;
-- if (port->serial_out)
-- uart->port.serial_out = port->serial_out;
-- if (port->handle_irq)
-- uart->port.handle_irq = port->handle_irq;
-+ if (up->port.serial_in)
-+ uart->port.serial_in = up->port.serial_in;
-+ if (up->port.serial_out)
-+ uart->port.serial_out = up->port.serial_out;
-+ if (up->port.handle_irq)
-+ uart->port.handle_irq = up->port.handle_irq;
- /* Possibly override set_termios call */
-- if (port->set_termios)
-- uart->port.set_termios = port->set_termios;
-- if (port->pm)
-- uart->port.pm = port->pm;
-- if (port->handle_break)
-- uart->port.handle_break = port->handle_break;
-+ if (up->port.set_termios)
-+ uart->port.set_termios = up->port.set_termios;
-+ if (up->port.pm)
-+ uart->port.pm = up->port.pm;
-+ if (up->port.handle_break)
-+ uart->port.handle_break = up->port.handle_break;
-+ if (up->dl_read)
-+ uart->dl_read = up->dl_read;
-+ if (up->dl_write)
-+ uart->dl_write = up->dl_write;
-
- if (serial8250_isa_config != NULL)
- serial8250_isa_config(0, &uart->port,
-@@ -3183,6 +3187,29 @@ int serial8250_register_port(struct uart_port *port)
-
- return ret;
- }
-+EXPORT_SYMBOL(serial8250_register_8250_port);
-+
-+/**
-+ * serial8250_register_port - register a serial port
-+ * @port: serial port template
-+ *
-+ * Configure the serial port specified by the request. If the
-+ * port exists and is in use, it is hung up and unregistered
-+ * first.
-+ *
-+ * The port is then probed and if necessary the IRQ is autodetected
-+ * If this fails an error is returned.
-+ *
-+ * On success the port is ready to use and the line number is returned.
-+ */
-+int serial8250_register_port(struct uart_port *port)
-+{
-+ struct uart_8250_port up;
-+
-+ memset(&up, 0, sizeof(up));
-+ memcpy(&up.port, port, sizeof(*port));
-+ return serial8250_register_8250_port(&up);
-+}
- EXPORT_SYMBOL(serial8250_register_port);
-
- /**
-diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
-index a522fd9..10dbce5 100644
---- a/include/linux/serial_8250.h
-+++ b/include/linux/serial_8250.h
-@@ -69,6 +69,7 @@ enum {
- struct uart_port;
- struct uart_8250_port;
-
-+int serial8250_register_8250_port(struct uart_8250_port *);
- int serial8250_register_port(struct uart_port *);
- void serial8250_unregister_port(int line);
- void serial8250_suspend_port(int line);
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:27:03 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:22:57 +0900
-Subject: [PATCH 05/26] serial8250: Use dl_read()/dl_write() on Alchemy
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-6-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-Convert the 8250 Alchemy support code to make
-use of the new dl_read()/dl_write() callbacks.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Acked-by: Alan Cox <alan@linux.intel.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-(cherry picked from commit 6b4160313c239d61c3907b2aaaeeec156911c9d1)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- drivers/tty/serial/8250/8250.c | 67 ++++++++++++++++------------------------
- 1 file changed, 26 insertions(+), 41 deletions(-)
-
-diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
-index 590ee85..2d62c89 100644
---- a/drivers/tty/serial/8250/8250.c
-+++ b/drivers/tty/serial/8250/8250.c
-@@ -297,24 +297,7 @@ static void default_dl_write(struct uart_8250_port *up, int value)
- serial_out(up, UART_DLM, value >> 8 & 0xff);
- }
-
--#if defined(CONFIG_MIPS_ALCHEMY)
--/* Au1x00 haven't got a standard divisor latch */
--static int _serial_dl_read(struct uart_8250_port *up)
--{
-- if (up->port.iotype == UPIO_AU)
-- return __raw_readl(up->port.membase + 0x28);
-- else
-- return default_dl_read(up);
--}
--
--static void _serial_dl_write(struct uart_8250_port *up, int value)
--{
-- if (up->port.iotype == UPIO_AU)
-- __raw_writel(value, up->port.membase + 0x28);
-- else
-- default_dl_write(up, value);
--}
--#elif defined(CONFIG_SERIAL_8250_RM9K)
-+#if defined(CONFIG_SERIAL_8250_RM9K)
- static int _serial_dl_read(struct uart_8250_port *up)
- {
- return (up->port.iotype == UPIO_RM9000) ?
-@@ -344,7 +327,7 @@ static void _serial_dl_write(struct uart_8250_port *up, int value)
- }
- #endif
-
--#if defined(CONFIG_MIPS_ALCHEMY)
-+#ifdef CONFIG_MIPS_ALCHEMY
-
- /* Au1x00 UART hardware has a weird register layout */
- static const u8 au_io_in_map[] = {
-@@ -365,22 +348,32 @@ static const u8 au_io_out_map[] = {
- [UART_MCR] = 6,
- };
-
--/* sane hardware needs no mapping */
--static inline int map_8250_in_reg(struct uart_port *p, int offset)
-+static unsigned int au_serial_in(struct uart_port *p, int offset)
- {
-- if (p->iotype != UPIO_AU)
-- return offset;
-- return au_io_in_map[offset];
-+ offset = au_io_in_map[offset] << p->regshift;
-+ return __raw_readl(p->membase + offset);
- }
-
--static inline int map_8250_out_reg(struct uart_port *p, int offset)
-+static void au_serial_out(struct uart_port *p, int offset, int value)
- {
-- if (p->iotype != UPIO_AU)
-- return offset;
-- return au_io_out_map[offset];
-+ offset = au_io_out_map[offset] << p->regshift;
-+ __raw_writel(value, p->membase + offset);
-+}
-+
-+/* Au1x00 haven't got a standard divisor latch */
-+static int au_serial_dl_read(struct uart_8250_port *up)
-+{
-+ return __raw_readl(up->port.membase + 0x28);
- }
-
--#elif defined(CONFIG_SERIAL_8250_RM9K)
-+static void au_serial_dl_write(struct uart_8250_port *up, int value)
-+{
-+ __raw_writel(value, up->port.membase + 0x28);
-+}
-+
-+#endif
-+
-+#if defined(CONFIG_SERIAL_8250_RM9K)
-
- static const u8
- regmap_in[8] = {
-@@ -464,18 +457,6 @@ static unsigned int mem32_serial_in(struct uart_port *p, int offset)
- return readl(p->membase + offset);
- }
-
--static unsigned int au_serial_in(struct uart_port *p, int offset)
--{
-- offset = map_8250_in_reg(p, offset) << p->regshift;
-- return __raw_readl(p->membase + offset);
--}
--
--static void au_serial_out(struct uart_port *p, int offset, int value)
--{
-- offset = map_8250_out_reg(p, offset) << p->regshift;
-- __raw_writel(value, p->membase + offset);
--}
--
- static unsigned int io_serial_in(struct uart_port *p, int offset)
- {
- offset = map_8250_in_reg(p, offset) << p->regshift;
-@@ -515,10 +496,14 @@ static void set_io_from_upio(struct uart_port *p)
- p->serial_out = mem32_serial_out;
- break;
-
-+#ifdef CONFIG_MIPS_ALCHEMY
- case UPIO_AU:
- p->serial_in = au_serial_in;
- p->serial_out = au_serial_out;
-+ up->dl_read = au_serial_dl_read;
-+ up->dl_write = au_serial_dl_write;
- break;
-+#endif
-
- default:
- p->serial_in = io_serial_in;
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:27:18 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:22:58 +0900
-Subject: [PATCH 06/26] serial8250: Use dl_read()/dl_write() on RM9K
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-7-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-Convert the 8250 RM9K support code to make
-use of the new dl_read()/dl_write() callbacks.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Acked-by: Alan Cox <alan@linux.intel.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-(cherry picked from commit 28bf4cf22dcd936f93dd6063696b1accdc1d5207)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- drivers/tty/serial/8250/8250.c | 62 +++++++++++++++++++---------------------
- 1 file changed, 29 insertions(+), 33 deletions(-)
-
-diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
-index 2d62c89..cc398b1 100644
---- a/drivers/tty/serial/8250/8250.c
-+++ b/drivers/tty/serial/8250/8250.c
-@@ -297,25 +297,6 @@ static void default_dl_write(struct uart_8250_port *up, int value)
- serial_out(up, UART_DLM, value >> 8 & 0xff);
- }
-
--#if defined(CONFIG_SERIAL_8250_RM9K)
--static int _serial_dl_read(struct uart_8250_port *up)
--{
-- return (up->port.iotype == UPIO_RM9000) ?
-- (((__raw_readl(up->port.membase + 0x10) << 8) |
-- (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
-- default_dl_read(up);
--}
--
--static void _serial_dl_write(struct uart_8250_port *up, int value)
--{
-- if (up->port.iotype == UPIO_RM9000) {
-- __raw_writel(value, up->port.membase + 0x08);
-- __raw_writel(value >> 8, up->port.membase + 0x10);
-- } else {
-- default_dl_write(up, value);
-- }
--}
--#else
- static int _serial_dl_read(struct uart_8250_port *up)
- {
- return default_dl_read(up);
-@@ -325,7 +306,6 @@ static void _serial_dl_write(struct uart_8250_port *up, int value)
- {
- default_dl_write(up, value);
- }
--#endif
-
- #ifdef CONFIG_MIPS_ALCHEMY
-
-@@ -373,7 +353,7 @@ static void au_serial_dl_write(struct uart_8250_port *up, int value)
-
- #endif
-
--#if defined(CONFIG_SERIAL_8250_RM9K)
-+#ifdef CONFIG_SERIAL_8250_RM9K
-
- static const u8
- regmap_in[8] = {
-@@ -397,28 +377,36 @@ static const u8
- [UART_SCR] = 0x2c
- };
-
--static inline int map_8250_in_reg(struct uart_port *p, int offset)
-+static unsigned int rm9k_serial_in(struct uart_port *p, int offset)
- {
-- if (p->iotype != UPIO_RM9000)
-- return offset;
-- return regmap_in[offset];
-+ offset = regmap_in[offset] << p->regshift;
-+ return readl(p->membase + offset);
- }
-
--static inline int map_8250_out_reg(struct uart_port *p, int offset)
-+static void rm9k_serial_out(struct uart_port *p, int offset, int value)
- {
-- if (p->iotype != UPIO_RM9000)
-- return offset;
-- return regmap_out[offset];
-+ offset = regmap_out[offset] << p->regshift;
-+ writel(value, p->membase + offset);
- }
-
--#else
-+static int rm9k_serial_dl_read(struct uart_8250_port *up)
-+{
-+ return ((__raw_readl(up->port.membase + 0x10) << 8) |
-+ (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff;
-+}
-+
-+static void rm9k_serial_dl_write(struct uart_8250_port *up, int value)
-+{
-+ __raw_writel(value, up->port.membase + 0x08);
-+ __raw_writel(value >> 8, up->port.membase + 0x10);
-+}
-+
-+#endif
-
- /* sane hardware needs no mapping */
- #define map_8250_in_reg(up, offset) (offset)
- #define map_8250_out_reg(up, offset) (offset)
-
--#endif
--
- static unsigned int hub6_serial_in(struct uart_port *p, int offset)
- {
- offset = map_8250_in_reg(p, offset) << p->regshift;
-@@ -490,12 +478,20 @@ static void set_io_from_upio(struct uart_port *p)
- p->serial_out = mem_serial_out;
- break;
-
-- case UPIO_RM9000:
- case UPIO_MEM32:
- p->serial_in = mem32_serial_in;
- p->serial_out = mem32_serial_out;
- break;
-
-+#ifdef CONFIG_SERIAL_8250_RM9K
-+ case UPIO_RM9000:
-+ p->serial_in = rm9k_serial_in;
-+ p->serial_out = rm9k_serial_out;
-+ up->dl_read = rm9k_serial_dl_read;
-+ up->dl_write = rm9k_serial_dl_write;
-+ break;
-+#endif
-+
- #ifdef CONFIG_MIPS_ALCHEMY
- case UPIO_AU:
- p->serial_in = au_serial_in;
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Wed Oct 3 04:24:29 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Wed, 3 Oct 2012 20:22:53 +0900
-Subject: [PATCH 01/26] tegra, serial8250: add ->handle_break() uart_port op
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Dan Williams <dan.j.williams@intel.com>, Nhan H Mai <nhan.h.mai@intel.com>, Colin Cross <ccross@android.com>, Olof Johansson <olof@lixom.net>, Grant Likely <grant.likely@secretlab.ca>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349263398-13152-2-git-send-email-koba@kmckk.co.jp>
-
-
-From: Dan Williams <dan.j.williams@intel.com>
-
-The "KT" serial port has another use case for a "received break" quirk,
-so before adding another special case to the 8250 core take this
-opportunity to push such quirks out of the core and into a uart_port op.
-
-Stephen says:
-"If the callback function is to no longer live in 8250.c itself,
- arch/arm/mach-tegra/devices.c isn't logically a good place to put it,
- and that file will be going away once we get rid of all the board files
- and move solely to device tree."
-
-...so since 8250_pci.c houses all the quirks for pci serial devices this
-quirk is similarly housed in of_serial.c. Once the open firmware
-conversion completes the infrastructure details
-(include/linux/of_serial.h, and the export) can all be removed to make
-this self contained to of_serial.c.
-
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-Cc: Nhan H Mai <nhan.h.mai@intel.com>
-Cc: Colin Cross <ccross@android.com>
-Cc: Olof Johansson <olof@lixom.net>
-[stephen: kill CONFIG_SERIAL_TEGRA in favor just using CONFIG_ARCH_TEGRA]
-Cc: Grant Likely <grant.likely@secretlab.ca>
-Acked-by: Sudhakar Mamillapalli <sudhakar@fb.com>
-Reported-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
-Acked-by: Alan Cox <alan@linux.intel.com>
-Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-Acked-by: Stephen Warren <swarren@wwwdotorg.org>
-Tested-by: Stephen Warren <swarren@wwwdotorg.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-(cherry picked from commit bf03f65b7967df5807ddef7b99f8a41d4c94fc70)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-tegra/board-harmony.c | 2 ++
- arch/arm/mach-tegra/board-paz00.c | 3 +++
- arch/arm/mach-tegra/board-seaboard.c | 2 ++
- arch/arm/mach-tegra/board-trimslice.c | 2 ++
- drivers/tty/serial/8250/8250.c | 34 +++------------------------------
- drivers/tty/serial/of_serial.c | 26 +++++++++++++++++++++++++
- include/linux/of_serial.h | 17 +++++++++++++++++
- include/linux/serial_8250.h | 1 +
- include/linux/serial_core.h | 5 +++++
- 9 files changed, 61 insertions(+), 31 deletions(-)
- create mode 100644 include/linux/of_serial.h
-
-diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
-index c00aadb..222182e 100644
---- a/arch/arm/mach-tegra/board-harmony.c
-+++ b/arch/arm/mach-tegra/board-harmony.c
-@@ -19,6 +19,7 @@
- #include <linux/init.h>
- #include <linux/platform_device.h>
- #include <linux/serial_8250.h>
-+#include <linux/of_serial.h>
- #include <linux/clk.h>
- #include <linux/dma-mapping.h>
- #include <linux/pda_power.h>
-@@ -52,6 +53,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
- .irq = INT_UARTD,
- .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
- .type = PORT_TEGRA,
-+ .handle_break = tegra_serial_handle_break,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = 216000000,
-diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
-index 330afdf..d0735c7 100644
---- a/arch/arm/mach-tegra/board-paz00.c
-+++ b/arch/arm/mach-tegra/board-paz00.c
-@@ -21,6 +21,7 @@
- #include <linux/init.h>
- #include <linux/platform_device.h>
- #include <linux/serial_8250.h>
-+#include <linux/of_serial.h>
- #include <linux/clk.h>
- #include <linux/dma-mapping.h>
- #include <linux/gpio_keys.h>
-@@ -55,6 +56,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
- .irq = INT_UARTA,
- .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
- .type = PORT_TEGRA,
-+ .handle_break = tegra_serial_handle_break,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = 216000000,
-@@ -65,6 +67,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
- .irq = INT_UARTC,
- .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
- .type = PORT_TEGRA,
-+ .handle_break = tegra_serial_handle_break,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = 216000000,
-diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c
-index d669847..5b687b8 100644
---- a/arch/arm/mach-tegra/board-seaboard.c
-+++ b/arch/arm/mach-tegra/board-seaboard.c
-@@ -18,6 +18,7 @@
- #include <linux/init.h>
- #include <linux/platform_device.h>
- #include <linux/serial_8250.h>
-+#include <linux/of_serial.h>
- #include <linux/i2c.h>
- #include <linux/delay.h>
- #include <linux/input.h>
-@@ -47,6 +48,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
- /* Memory and IRQ filled in before registration */
- .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
- .type = PORT_TEGRA,
-+ .handle_break = tegra_serial_handle_break,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = 216000000,
-diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c
-index cd52820a..f735858 100644
---- a/arch/arm/mach-tegra/board-trimslice.c
-+++ b/arch/arm/mach-tegra/board-trimslice.c
-@@ -22,6 +22,7 @@
- #include <linux/init.h>
- #include <linux/platform_device.h>
- #include <linux/serial_8250.h>
-+#include <linux/of_serial.h>
- #include <linux/io.h>
- #include <linux/i2c.h>
- #include <linux/gpio.h>
-@@ -48,6 +49,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
- .irq = INT_UARTA,
- .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
- .type = PORT_TEGRA,
-+ .handle_break = tegra_serial_handle_break,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = 216000000,
-diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
-index d537431..aed9363 100644
---- a/drivers/tty/serial/8250/8250.c
-+++ b/drivers/tty/serial/8250/8250.c
-@@ -1332,27 +1332,6 @@ static void serial8250_enable_ms(struct uart_port *port)
- }
-
- /*
-- * Clear the Tegra rx fifo after a break
-- *
-- * FIXME: This needs to become a port specific callback once we have a
-- * framework for this
-- */
--static void clear_rx_fifo(struct uart_8250_port *up)
--{
-- unsigned int status, tmout = 10000;
-- do {
-- status = serial_in(up, UART_LSR);
-- if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
-- status = serial_in(up, UART_RX);
-- else
-- break;
-- if (--tmout == 0)
-- break;
-- udelay(1);
-- } while (1);
--}
--
--/*
- * serial8250_rx_chars: processes according to the passed in LSR
- * value, and returns the remaining LSR bits not handled
- * by this Rx routine.
-@@ -1386,20 +1365,10 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
- up->lsr_saved_flags = 0;
-
- if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
-- /*
-- * For statistics only
-- */
- if (lsr & UART_LSR_BI) {
- lsr &= ~(UART_LSR_FE | UART_LSR_PE);
- port->icount.brk++;
- /*
-- * If tegra port then clear the rx fifo to
-- * accept another break/character.
-- */
-- if (port->type == PORT_TEGRA)
-- clear_rx_fifo(up);
--
-- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
-@@ -3038,6 +3007,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
- port.serial_in = p->serial_in;
- port.serial_out = p->serial_out;
- port.handle_irq = p->handle_irq;
-+ port.handle_break = p->handle_break;
- port.set_termios = p->set_termios;
- port.pm = p->pm;
- port.dev = &dev->dev;
-@@ -3210,6 +3180,8 @@ int serial8250_register_port(struct uart_port *port)
- uart->port.set_termios = port->set_termios;
- if (port->pm)
- uart->port.pm = port->pm;
-+ if (port->handle_break)
-+ uart->port.handle_break = port->handle_break;
-
- if (serial8250_isa_config != NULL)
- serial8250_isa_config(0, &uart->port,
-diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
-index e8c9cee..5410c06 100644
---- a/drivers/tty/serial/of_serial.c
-+++ b/drivers/tty/serial/of_serial.c
-@@ -12,10 +12,13 @@
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/slab.h>
-+#include <linux/delay.h>
- #include <linux/serial_core.h>
- #include <linux/serial_8250.h>
-+#include <linux/serial_reg.h>
- #include <linux/of_address.h>
- #include <linux/of_irq.h>
-+#include <linux/of_serial.h>
- #include <linux/of_platform.h>
- #include <linux/nwpserial.h>
-
-@@ -24,6 +27,26 @@ struct of_serial_info {
- int line;
- };
-
-+#ifdef CONFIG_ARCH_TEGRA
-+void tegra_serial_handle_break(struct uart_port *p)
-+{
-+ unsigned int status, tmout = 10000;
-+
-+ do {
-+ status = p->serial_in(p, UART_LSR);
-+ if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
-+ status = p->serial_in(p, UART_RX);
-+ else
-+ break;
-+ if (--tmout == 0)
-+ break;
-+ udelay(1);
-+ } while (1);
-+}
-+/* FIXME remove this export when tegra finishes conversion to open firmware */
-+EXPORT_SYMBOL_GPL(tegra_serial_handle_break);
-+#endif
-+
- /*
- * Fill a struct uart_port for a given device node
- */
-@@ -84,6 +107,9 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
- | UPF_FIXED_PORT | UPF_FIXED_TYPE;
- port->dev = &ofdev->dev;
-
-+ if (type == PORT_TEGRA)
-+ port->handle_break = tegra_serial_handle_break;
-+
- return 0;
- }
-
-diff --git a/include/linux/of_serial.h b/include/linux/of_serial.h
-new file mode 100644
-index 0000000..4a73ed8
---- /dev/null
-+++ b/include/linux/of_serial.h
-@@ -0,0 +1,17 @@
-+#ifndef __LINUX_OF_SERIAL_H
-+#define __LINUX_OF_SERIAL_H
-+
-+/*
-+ * FIXME remove this file when tegra finishes conversion to open firmware,
-+ * expectation is that all quirks will then be self-contained in
-+ * drivers/tty/serial/of_serial.c.
-+ */
-+#ifdef CONFIG_ARCH_TEGRA
-+extern void tegra_serial_handle_break(struct uart_port *port);
-+#else
-+static inline void tegra_serial_handle_break(struct uart_port *port)
-+{
-+}
-+#endif
-+
-+#endif /* __LINUX_OF_SERIAL */
-diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
-index 8f012f8..a522fd9 100644
---- a/include/linux/serial_8250.h
-+++ b/include/linux/serial_8250.h
-@@ -38,6 +38,7 @@ struct plat_serial8250_port {
- int (*handle_irq)(struct uart_port *);
- void (*pm)(struct uart_port *, unsigned int state,
- unsigned old);
-+ void (*handle_break)(struct uart_port *);
- };
-
- /*
-diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
-index 2db407a..65db992 100644
---- a/include/linux/serial_core.h
-+++ b/include/linux/serial_core.h
-@@ -310,6 +310,7 @@ struct uart_port {
- int (*handle_irq)(struct uart_port *);
- void (*pm)(struct uart_port *, unsigned int state,
- unsigned int old);
-+ void (*handle_break)(struct uart_port *);
- unsigned int irq; /* irq number */
- unsigned long irqflags; /* irq flags */
- unsigned int uartclk; /* base uart clock */
-@@ -533,6 +534,10 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
- static inline int uart_handle_break(struct uart_port *port)
- {
- struct uart_state *state = port->state;
-+
-+ if (port->handle_break)
-+ port->handle_break(port);
-+
- #ifdef SUPPORT_SYSRQ
- if (port->cons && port->cons->index == port->line) {
- if (!port->sysrq) {
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:10:13 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:57 +0900
-Subject: [PATCH 21/21] ARM: mach-shmobile: Add compilation support for dtbs using 'make dtbs'
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-22-git-send-email-koba@kmckk.co.jp>
-
-
-Add compilation support for dtbs using 'make dtbs'
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/Makefile.boot | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot
-index 498efd9..5e41019 100644
---- a/arch/arm/mach-shmobile/Makefile.boot
-+++ b/arch/arm/mach-shmobile/Makefile.boot
-@@ -7,3 +7,7 @@ __ZRELADDR := $(shell /bin/bash -c 'printf "0x%08x" \
- #
- #params_phys-y (Instead: Pass atags pointer in r2)
- #initrd_phys-y (Instead: Use compiled-in initramfs)
-+
-+dtb-$(CONFIG_MACH_KZM9G) += sh73a0-kzm9g.dtb
-+dtb-$(CONFIG_MACH_KZM9D) += emev2-kzm9d.dtb
-+dtb-$(CONFIG_MACH_ARMADILLO800EVA) += r8a7740-armadillo800eva.dtb
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:08:50 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:38 +0900
-Subject: [PATCH 02/21] ARM: mach-shmobile: add KZM-A9-GT board support
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-3-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-This adds very basic KZM-A9-GT board (SH73a0) support
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 9b93e244fa056fadbe9f108c057c027b5cfbddf2)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/Kconfig | 5 ++
- arch/arm/mach-shmobile/Makefile | 1
- arch/arm/mach-shmobile/board-kzm9g.c | 60 +++++++++++++++++++++++++++++++++++
- 3 files changed, 66 insertions(+)
- create mode 100644 arch/arm/mach-shmobile/board-kzm9g.c
-
---- a/arch/arm/mach-shmobile/Kconfig
-+++ b/arch/arm/mach-shmobile/Kconfig
-@@ -107,6 +107,11 @@ config MACH_MARZEN
- depends on ARCH_R8A7779
- select ARCH_REQUIRE_GPIOLIB
-
-+config MACH_KZM9G
-+ bool "KZM-A9-GT board"
-+ depends on ARCH_SH73A0
-+ select ARCH_REQUIRE_GPIOLIB
-+
- comment "SH-Mobile System Configuration"
-
- config CPU_HAS_INTEVT
---- a/arch/arm/mach-shmobile/Makefile
-+++ b/arch/arm/mach-shmobile/Makefile
-@@ -52,6 +52,7 @@ obj-$(CONFIG_MACH_KOTA2) += board-kota2.
- obj-$(CONFIG_MACH_BONITO) += board-bonito.o
- obj-$(CONFIG_MACH_MARZEN) += board-marzen.o
- obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o
-+obj-$(CONFIG_MACH_KZM9G) += board-kzm9g.o
-
- # Framework support
- obj-$(CONFIG_SMP) += $(smp-y)
---- /dev/null
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -0,0 +1,60 @@
-+/*
-+ * KZM-A9-GT board support
-+ *
-+ * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; version 2 of the License.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+#include <linux/gpio.h>
-+#include <linux/io.h>
-+#include <linux/irq.h>
-+#include <linux/platform_device.h>
-+#include <mach/sh73a0.h>
-+#include <mach/common.h>
-+#include <asm/hardware/cache-l2x0.h>
-+#include <asm/hardware/gic.h>
-+#include <asm/mach-types.h>
-+#include <asm/mach/arch.h>
-+
-+static struct platform_device *kzm_devices[] __initdata = {
-+};
-+
-+static void __init kzm_init(void)
-+{
-+ sh73a0_pinmux_init();
-+
-+ /* enable SCIFA4 */
-+ gpio_request(GPIO_FN_SCIFA4_TXD, NULL);
-+ gpio_request(GPIO_FN_SCIFA4_RXD, NULL);
-+ gpio_request(GPIO_FN_SCIFA4_RTS_, NULL);
-+ gpio_request(GPIO_FN_SCIFA4_CTS_, NULL);
-+
-+#ifdef CONFIG_CACHE_L2X0
-+ /* Early BRESP enable, Shared attribute override enable, 64K*8way */
-+ l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
-+#endif
-+
-+ sh73a0_add_standard_devices();
-+ platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices));
-+}
-+
-+MACHINE_START(KZM9G, "kzm9g")
-+ .map_io = sh73a0_map_io,
-+ .init_early = sh73a0_add_early_devices,
-+ .nr_irqs = NR_IRQS_LEGACY,
-+ .init_irq = sh73a0_init_irq,
-+ .handle_irq = gic_handle_irq,
-+ .init_machine = kzm_init,
-+ .timer = &shmobile_timer,
-+MACHINE_END
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Mon Sep 24 22:09:03 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:39 +0900
-Subject: [PATCH 03/21] ARM: mach-shmobile: kzm9g: add defconfig
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, "Rafael J. Wysocki" <rjw@sisk.pl>
-Message-ID: <1348549677-1458-4-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 6d3c9135cc4da91ea6cebcc1aefc33d13a50957e)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/configs/kzm9g_defconfig | 127 ++++++++++++++++++++++++++++++++++++++
- 1 file changed, 127 insertions(+)
- create mode 100644 arch/arm/configs/kzm9g_defconfig
-
-diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig
-new file mode 100644
-index 0000000..164c5d2
---- /dev/null
-+++ b/arch/arm/configs/kzm9g_defconfig
-@@ -0,0 +1,127 @@
-+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_LOCALVERSION_AUTO is not set
-+CONFIG_SYSVIPC=y
-+CONFIG_IKCONFIG=y
-+CONFIG_IKCONFIG_PROC=y
-+CONFIG_LOG_BUF_SHIFT=16
-+CONFIG_NAMESPACES=y
-+# CONFIG_UTS_NS is not set
-+# CONFIG_IPC_NS is not set
-+# CONFIG_USER_NS is not set
-+# CONFIG_PID_NS is not set
-+# CONFIG_NET_NS is not set
-+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-+CONFIG_SYSCTL_SYSCALL=y
-+CONFIG_EMBEDDED=y
-+CONFIG_SLAB=y
-+CONFIG_MODULES=y
-+CONFIG_MODULE_FORCE_LOAD=y
-+CONFIG_MODULE_UNLOAD=y
-+# CONFIG_BLK_DEV_BSG is not set
-+# CONFIG_IOSCHED_DEADLINE is not set
-+# CONFIG_IOSCHED_CFQ is not set
-+CONFIG_ARCH_SHMOBILE=y
-+CONFIG_ARCH_SH73A0=y
-+CONFIG_MACH_KZM9G=y
-+CONFIG_MEMORY_START=0x41000000
-+CONFIG_MEMORY_SIZE=0x1f000000
-+CONFIG_ARM_ERRATA_743622=y
-+CONFIG_ARM_ERRATA_754322=y
-+CONFIG_NO_HZ=y
-+CONFIG_HIGH_RES_TIMERS=y
-+CONFIG_PREEMPT=y
-+CONFIG_AEABI=y
-+# CONFIG_OABI_COMPAT is not set
-+CONFIG_HIGHMEM=y
-+CONFIG_ZBOOT_ROM_TEXT=0x0
-+CONFIG_ZBOOT_ROM_BSS=0x0
-+CONFIG_CMDLINE="console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel earlyprintk=serial"
-+CONFIG_KEXEC=y
-+CONFIG_VFP=y
-+CONFIG_NEON=y
-+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-+CONFIG_PM_RUNTIME=y
-+CONFIG_NET=y
-+CONFIG_PACKET=y
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-+# CONFIG_INET_XFRM_MODE_BEET is not set
-+# CONFIG_INET_LRO is not set
-+# CONFIG_INET_DIAG is not set
-+# CONFIG_IPV6 is not set
-+CONFIG_IRDA=y
-+CONFIG_SH_IRDA=y
-+# CONFIG_WIRELESS is not set
-+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-+CONFIG_SCSI=y
-+CONFIG_BLK_DEV_SD=y
-+CONFIG_NETDEVICES=y
-+CONFIG_SMSC911X=y
-+# CONFIG_WLAN is not set
-+CONFIG_INPUT_SPARSEKMAP=y
-+# CONFIG_INPUT_MOUSEDEV is not set
-+CONFIG_INPUT_EVDEV=y
-+# CONFIG_KEYBOARD_ATKBD is not set
-+CONFIG_KEYBOARD_GPIO=y
-+CONFIG_KEYBOARD_SH_KEYSC=y
-+# CONFIG_INPUT_MOUSE is not set
-+CONFIG_INPUT_TOUCHSCREEN=y
-+CONFIG_TOUCHSCREEN_ST1232=y
-+# CONFIG_LEGACY_PTYS is not set
-+CONFIG_SERIAL_SH_SCI=y
-+CONFIG_SERIAL_SH_SCI_NR_UARTS=9
-+CONFIG_SERIAL_SH_SCI_CONSOLE=y
-+# CONFIG_HW_RANDOM is not set
-+CONFIG_I2C_CHARDEV=y
-+CONFIG_I2C_SH_MOBILE=y
-+CONFIG_POWER_SUPPLY=y
-+# CONFIG_HWMON is not set
-+CONFIG_FB=y
-+CONFIG_FB_SH_MOBILE_LCDC=y
-+CONFIG_FRAMEBUFFER_CONSOLE=y
-+CONFIG_LOGO=y
-+CONFIG_FB_SH_MOBILE_MERAM=y
-+# CONFIG_HID_SUPPORT is not set
-+CONFIG_USB=y
-+CONFIG_USB_DEVICEFS=y
-+CONFIG_USB_R8A66597_HCD=y
-+CONFIG_USB_STORAGE=y
-+CONFIG_MMC=y
-+# CONFIG_MMC_BLOCK_BOUNCE is not set
-+CONFIG_MMC_SDHI=y
-+CONFIG_MMC_SH_MMCIF=y
-+CONFIG_NEW_LEDS=y
-+CONFIG_LEDS_CLASS=y
-+CONFIG_RTC_CLASS=y
-+CONFIG_DMADEVICES=y
-+CONFIG_SH_DMAE=y
-+CONFIG_ASYNC_TX_DMA=y
-+CONFIG_STAGING=y
-+# CONFIG_DNOTIFY is not set
-+# CONFIG_INOTIFY_USER is not set
-+CONFIG_VFAT_FS=y
-+CONFIG_TMPFS=y
-+# CONFIG_MISC_FILESYSTEMS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+CONFIG_NFS_V3_ACL=y
-+CONFIG_NFS_V4=y
-+CONFIG_NFS_V4_1=y
-+CONFIG_ROOT_NFS=y
-+CONFIG_NLS_CODEPAGE_437=y
-+CONFIG_NLS_ISO8859_1=y
-+CONFIG_MAGIC_SYSRQ=y
-+CONFIG_DETECT_HUNG_TASK=y
-+CONFIG_DEBUG_INFO=y
-+# CONFIG_FTRACE is not set
-+CONFIG_DEBUG_USER=y
-+CONFIG_CRYPTO=y
-+CONFIG_CRYPTO_CBC=y
-+CONFIG_CRYPTO_MD5=y
-+CONFIG_CRYPTO_DES=y
-+CONFIG_CRC16=y
---
-1.7.9.5
-
-_______________________________________________
-LTSI-dev mailing list
-LTSI-dev@lists.linuxfoundation.org
-https://lists.linuxfoundation.org/mailman/listinfo/ltsi-dev
-
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Mon Sep 24 22:09:21 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:41 +0900
-Subject: [PATCH 05/21] ARM: mach-shmobile: kzm9g: add external USB Host support
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, "Rafael J. Wysocki" <rjw@sisk.pl>
-Message-ID: <1348549677-1458-6-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-This patch uses r8a66597_hcd driver,
-since renesas_usbhs driver doesn't support external R8A66597 chip.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit dd818180f9303eed270513e8ccd4516bb3a577f5)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/board-kzm9g.c | 31 +++++++++++++++++++++++++++++++
- 1 file changed, 31 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
-index a46aec1..f48db23 100644
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -21,6 +21,7 @@
- #include <linux/irq.h>
- #include <linux/platform_device.h>
- #include <linux/smsc911x.h>
-+#include <linux/usb/r8a66597.h>
- #include <mach/irqs.h>
- #include <mach/sh73a0.h>
- #include <mach/common.h>
-@@ -58,8 +59,38 @@ static struct platform_device smsc_device = {
- .num_resources = ARRAY_SIZE(smsc9221_resources),
- };
-
-+/* USB external chip */
-+static struct r8a66597_platdata usb_host_data = {
-+ .on_chip = 0,
-+ .xtal = R8A66597_PLATDATA_XTAL_48MHZ,
-+};
-+
-+static struct resource usb_resources[] = {
-+ [0] = {
-+ .start = 0x10010000,
-+ .end = 0x1001ffff - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = intcs_evt2irq(0x220), /* IRQ1 */
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device usb_host_device = {
-+ .name = "r8a66597_hcd",
-+ .dev = {
-+ .platform_data = &usb_host_data,
-+ .dma_mask = NULL,
-+ .coherent_dma_mask = 0xffffffff,
-+ },
-+ .num_resources = ARRAY_SIZE(usb_resources),
-+ .resource = usb_resources,
-+};
-+
- static struct platform_device *kzm_devices[] __initdata = {
- &smsc_device,
-+ &usb_host_device,
- };
-
- static void __init kzm_init(void)
---
-1.7.9.5
-
-_______________________________________________
-LTSI-dev mailing list
-LTSI-dev@lists.linuxfoundation.org
-https://lists.linuxfoundation.org/mailman/listinfo/ltsi-dev
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:09:19 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:42 +0900
-Subject: [PATCH 06/21] ARM: mach-shmobile: kzm9g: add LCDC support
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-7-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-AS3711 chip initalization is required for enabling LCDC backlight,
-but there is no driver for this chip.
-So, this patch sends its settings when boot.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 26786111f9f291c8ab313ea31d90efdf6cfde792)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/board-kzm9g.c | 143 ++++++++++++++++++++++++++++++++++
- 1 file changed, 143 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
-index f48db23..145341d 100644
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -16,12 +16,15 @@
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-+
-+#include <linux/delay.h>
- #include <linux/gpio.h>
- #include <linux/io.h>
- #include <linux/irq.h>
- #include <linux/platform_device.h>
- #include <linux/smsc911x.h>
- #include <linux/usb/r8a66597.h>
-+#include <linux/videodev2.h>
- #include <mach/irqs.h>
- #include <mach/sh73a0.h>
- #include <mach/common.h>
-@@ -29,6 +32,7 @@
- #include <asm/hardware/gic.h>
- #include <asm/mach-types.h>
- #include <asm/mach/arch.h>
-+#include <video/sh_mobile_lcdc.h>
-
- /* SMSC 9221 */
- static struct resource smsc9221_resources[] = {
-@@ -88,11 +92,119 @@ static struct platform_device usb_host_device = {
- .resource = usb_resources,
- };
-
-+/* LCDC */
-+static struct fb_videomode kzm_lcdc_mode = {
-+ .name = "WVGA Panel",
-+ .xres = 800,
-+ .yres = 480,
-+ .left_margin = 220,
-+ .right_margin = 110,
-+ .hsync_len = 70,
-+ .upper_margin = 20,
-+ .lower_margin = 5,
-+ .vsync_len = 5,
-+ .sync = 0,
-+};
-+
-+static struct sh_mobile_lcdc_info lcdc_info = {
-+ .clock_source = LCDC_CLK_BUS,
-+ .ch[0] = {
-+ .chan = LCDC_CHAN_MAINLCD,
-+ .fourcc = V4L2_PIX_FMT_RGB565,
-+ .interface_type = RGB24,
-+ .lcd_modes = &kzm_lcdc_mode,
-+ .num_modes = 1,
-+ .clock_divider = 5,
-+ .flags = 0,
-+ .panel_cfg = {
-+ .width = 152,
-+ .height = 91,
-+ },
-+ }
-+};
-+
-+static struct resource lcdc_resources[] = {
-+ [0] = {
-+ .name = "LCDC",
-+ .start = 0xfe940000,
-+ .end = 0xfe943fff,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = intcs_evt2irq(0x580),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device lcdc_device = {
-+ .name = "sh_mobile_lcdc_fb",
-+ .num_resources = ARRAY_SIZE(lcdc_resources),
-+ .resource = lcdc_resources,
-+ .dev = {
-+ .platform_data = &lcdc_info,
-+ .coherent_dma_mask = ~0,
-+ },
-+};
-+
- static struct platform_device *kzm_devices[] __initdata = {
- &smsc_device,
- &usb_host_device,
-+ &lcdc_device,
- };
-
-+/*
-+ * FIXME
-+ *
-+ * This is quick hack for enabling LCDC backlight
-+ */
-+static int __init as3711_enable_lcdc_backlight(void)
-+{
-+ struct i2c_adapter *a = i2c_get_adapter(0);
-+ struct i2c_msg msg;
-+ int i, ret;
-+ __u8 magic[] = {
-+ 0x40, 0x2a,
-+ 0x43, 0x3c,
-+ 0x44, 0x3c,
-+ 0x45, 0x3c,
-+ 0x54, 0x03,
-+ 0x51, 0x00,
-+ 0x51, 0x01,
-+ 0xff, 0x00, /* wait */
-+ 0x43, 0xf0,
-+ 0x44, 0xf0,
-+ 0x45, 0xf0,
-+ };
-+
-+ if (!machine_is_kzm9g())
-+ return 0;
-+
-+ if (!a)
-+ return 0;
-+
-+ msg.addr = 0x40;
-+ msg.len = 2;
-+ msg.flags = 0;
-+
-+ for (i = 0; i < ARRAY_SIZE(magic); i += 2) {
-+ msg.buf = magic + i;
-+
-+ if (0xff == msg.buf[0]) {
-+ udelay(500);
-+ continue;
-+ }
-+
-+ ret = i2c_transfer(a, &msg, 1);
-+ if (ret < 0) {
-+ pr_err("i2c transfer fail\n");
-+ break;
-+ }
-+ }
-+
-+ return 0;
-+}
-+device_initcall(as3711_enable_lcdc_backlight);
-+
- static void __init kzm_init(void)
- {
- sh73a0_pinmux_init();
-@@ -110,6 +222,37 @@ static void __init kzm_init(void)
- gpio_request(GPIO_PORT224, NULL); /* IRQ3 */
- gpio_direction_input(GPIO_PORT224);
-
-+ /* LCDC */
-+ gpio_request(GPIO_FN_LCDD23, NULL);
-+ gpio_request(GPIO_FN_LCDD22, NULL);
-+ gpio_request(GPIO_FN_LCDD21, NULL);
-+ gpio_request(GPIO_FN_LCDD20, NULL);
-+ gpio_request(GPIO_FN_LCDD19, NULL);
-+ gpio_request(GPIO_FN_LCDD18, NULL);
-+ gpio_request(GPIO_FN_LCDD17, NULL);
-+ gpio_request(GPIO_FN_LCDD16, NULL);
-+ gpio_request(GPIO_FN_LCDD15, NULL);
-+ gpio_request(GPIO_FN_LCDD14, NULL);
-+ gpio_request(GPIO_FN_LCDD13, NULL);
-+ gpio_request(GPIO_FN_LCDD12, NULL);
-+ gpio_request(GPIO_FN_LCDD11, NULL);
-+ gpio_request(GPIO_FN_LCDD10, NULL);
-+ gpio_request(GPIO_FN_LCDD9, NULL);
-+ gpio_request(GPIO_FN_LCDD8, NULL);
-+ gpio_request(GPIO_FN_LCDD7, NULL);
-+ gpio_request(GPIO_FN_LCDD6, NULL);
-+ gpio_request(GPIO_FN_LCDD5, NULL);
-+ gpio_request(GPIO_FN_LCDD4, NULL);
-+ gpio_request(GPIO_FN_LCDD3, NULL);
-+ gpio_request(GPIO_FN_LCDD2, NULL);
-+ gpio_request(GPIO_FN_LCDD1, NULL);
-+ gpio_request(GPIO_FN_LCDD0, NULL);
-+ gpio_request(GPIO_FN_LCDDISP, NULL);
-+ gpio_request(GPIO_FN_LCDDCK, NULL);
-+
-+ gpio_request(GPIO_PORT222, NULL);
-+ gpio_direction_output(GPIO_PORT222, 1);
-+
- #ifdef CONFIG_CACHE_L2X0
- /* Early BRESP enable, Shared attribute override enable, 64K*8way */
- l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:09:39 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:47 +0900
-Subject: [PATCH 11/21] ARM: mach-shmobile: kzm9g: add MMCIF support
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-12-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit cc2512bc67104efdd913fe655171667cd1ce942a)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/board-kzm9g.c | 49 ++++++++++++++++++++++++++++++++++
- 1 file changed, 49 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
-index 545d633..57c391a 100644
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -22,6 +22,8 @@
- #include <linux/io.h>
- #include <linux/irq.h>
- #include <linux/i2c.h>
-+#include <linux/mmc/host.h>
-+#include <linux/mmc/sh_mmcif.h>
- #include <linux/platform_device.h>
- #include <linux/smsc911x.h>
- #include <linux/usb/r8a66597.h>
-@@ -147,6 +149,40 @@ static struct platform_device lcdc_device = {
- },
- };
-
-+/* MMCIF */
-+static struct resource sh_mmcif_resources[] = {
-+ [0] = {
-+ .name = "MMCIF",
-+ .start = 0xe6bd0000,
-+ .end = 0xe6bd00ff,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = gic_spi(141),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [2] = {
-+ .start = gic_spi(140),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct sh_mmcif_plat_data sh_mmcif_platdata = {
-+ .ocr = MMC_VDD_165_195,
-+ .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
-+};
-+
-+static struct platform_device mmc_device = {
-+ .name = "sh_mmcif",
-+ .dev = {
-+ .dma_mask = NULL,
-+ .coherent_dma_mask = 0xffffffff,
-+ .platform_data = &sh_mmcif_platdata,
-+ },
-+ .num_resources = ARRAY_SIZE(sh_mmcif_resources),
-+ .resource = sh_mmcif_resources,
-+};
-+
- static struct i2c_board_info i2c1_devices[] = {
- {
- I2C_BOARD_INFO("st1232-ts", 0x55),
-@@ -158,6 +194,7 @@ static struct platform_device *kzm_devices[] __initdata = {
- &smsc_device,
- &usb_host_device,
- &lcdc_device,
-+ &mmc_device,
- };
-
- /*
-@@ -267,6 +304,18 @@ static void __init kzm_init(void)
- gpio_request(GPIO_PORT223, NULL); /* IRQ8 */
- gpio_direction_input(GPIO_PORT223);
-
-+ /* enable MMCIF */
-+ gpio_request(GPIO_FN_MMCCLK0, NULL);
-+ gpio_request(GPIO_FN_MMCCMD0_PU, NULL);
-+ gpio_request(GPIO_FN_MMCD0_0_PU, NULL);
-+ gpio_request(GPIO_FN_MMCD0_1_PU, NULL);
-+ gpio_request(GPIO_FN_MMCD0_2_PU, NULL);
-+ gpio_request(GPIO_FN_MMCD0_3_PU, NULL);
-+ gpio_request(GPIO_FN_MMCD0_4_PU, NULL);
-+ gpio_request(GPIO_FN_MMCD0_5_PU, NULL);
-+ gpio_request(GPIO_FN_MMCD0_6_PU, NULL);
-+ gpio_request(GPIO_FN_MMCD0_7_PU, NULL);
-+
- #ifdef CONFIG_CACHE_L2X0
- /* Early BRESP enable, Shared attribute override enable, 64K*8way */
- l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:09:44 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:49 +0900
-Subject: [PATCH 13/21] ARM: mach-shmobile: kzm9g: add PCF8757 gpio-key
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-14-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-This patch adds extra GPIO via PCF8757 chip,
-and use it as gpio-key.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 1e35464125a71cb6a46a20862dcbcd196e779921)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/board-kzm9g.c | 59 ++++++++++++++++++++++++++++++++++
- 1 file changed, 59 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
-index 657ba64..78e9850 100644
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -19,9 +19,12 @@
-
- #include <linux/delay.h>
- #include <linux/gpio.h>
-+#include <linux/gpio_keys.h>
- #include <linux/io.h>
- #include <linux/irq.h>
- #include <linux/i2c.h>
-+#include <linux/i2c/pcf857x.h>
-+#include <linux/input.h>
- #include <linux/mmc/host.h>
- #include <linux/mmc/sh_mmcif.h>
- #include <linux/mmc/sh_mobile_sdhi.h>
-@@ -39,6 +42,18 @@
- #include <asm/mach/arch.h>
- #include <video/sh_mobile_lcdc.h>
-
-+/*
-+ * external GPIO
-+ */
-+#define GPIO_PCF8575_BASE (GPIO_NR)
-+#define GPIO_PCF8575_PORT10 (GPIO_NR + 8)
-+#define GPIO_PCF8575_PORT11 (GPIO_NR + 9)
-+#define GPIO_PCF8575_PORT12 (GPIO_NR + 10)
-+#define GPIO_PCF8575_PORT13 (GPIO_NR + 11)
-+#define GPIO_PCF8575_PORT14 (GPIO_NR + 12)
-+#define GPIO_PCF8575_PORT15 (GPIO_NR + 13)
-+#define GPIO_PCF8575_PORT16 (GPIO_NR + 14)
-+
- /* SMSC 9221 */
- static struct resource smsc9221_resources[] = {
- [0] = {
-@@ -225,7 +240,38 @@ static struct platform_device sdhi0_device = {
- },
- };
-
-+/* KEY */
-+#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
-+
-+static struct gpio_keys_button gpio_buttons[] = {
-+ GPIO_KEY(KEY_BACK, GPIO_PCF8575_PORT10, "SW3"),
-+ GPIO_KEY(KEY_RIGHT, GPIO_PCF8575_PORT11, "SW2-R"),
-+ GPIO_KEY(KEY_LEFT, GPIO_PCF8575_PORT12, "SW2-L"),
-+ GPIO_KEY(KEY_ENTER, GPIO_PCF8575_PORT13, "SW2-P"),
-+ GPIO_KEY(KEY_UP, GPIO_PCF8575_PORT14, "SW2-U"),
-+ GPIO_KEY(KEY_DOWN, GPIO_PCF8575_PORT15, "SW2-D"),
-+ GPIO_KEY(KEY_HOME, GPIO_PCF8575_PORT16, "SW1"),
-+};
-+
-+static struct gpio_keys_platform_data gpio_key_info = {
-+ .buttons = gpio_buttons,
-+ .nbuttons = ARRAY_SIZE(gpio_buttons),
-+ .poll_interval = 250, /* poling at this point */
-+};
-+
-+static struct platform_device gpio_keys_device = {
-+ /* gpio-pcf857x.c driver doesn't support gpio_to_irq() */
-+ .name = "gpio-keys-polled",
-+ .dev = {
-+ .platform_data = &gpio_key_info,
-+ },
-+};
-+
- /* I2C */
-+static struct pcf857x_platform_data pcf8575_pdata = {
-+ .gpio_base = GPIO_PCF8575_BASE,
-+};
-+
- static struct i2c_board_info i2c1_devices[] = {
- {
- I2C_BOARD_INFO("st1232-ts", 0x55),
-@@ -233,12 +279,20 @@ static struct i2c_board_info i2c1_devices[] = {
- },
- };
-
-+static struct i2c_board_info i2c3_devices[] = {
-+ {
-+ I2C_BOARD_INFO("pcf8575", 0x20),
-+ .platform_data = &pcf8575_pdata,
-+ },
-+};
-+
- static struct platform_device *kzm_devices[] __initdata = {
- &smsc_device,
- &usb_host_device,
- &lcdc_device,
- &mmc_device,
- &sdhi0_device,
-+ &gpio_keys_device,
- };
-
- /*
-@@ -373,12 +427,17 @@ static void __init kzm_init(void)
- gpio_request(GPIO_PORT15, NULL);
- gpio_direction_output(GPIO_PORT15, 1); /* power */
-
-+ /* I2C 3 */
-+ gpio_request(GPIO_FN_PORT27_I2C_SCL3, NULL);
-+ gpio_request(GPIO_FN_PORT28_I2C_SDA3, NULL);
-+
- #ifdef CONFIG_CACHE_L2X0
- /* Early BRESP enable, Shared attribute override enable, 64K*8way */
- l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
- #endif
-
- i2c_register_board_info(1, i2c1_devices, ARRAY_SIZE(i2c1_devices));
-+ i2c_register_board_info(3, i2c3_devices, ARRAY_SIZE(i2c3_devices));
-
- sh73a0_add_standard_devices();
- platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices));
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:09:41 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:48 +0900
-Subject: [PATCH 12/21] ARM: mach-shmobile: kzm9g: add SDHI support
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-13-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 7775a93363e0bacb8a29b357429562063b42796b)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/board-kzm9g.c | 57 ++++++++++++++++++++++++++++++++++
- 1 file changed, 57 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
-index 57c391a..657ba64 100644
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -24,6 +24,8 @@
- #include <linux/i2c.h>
- #include <linux/mmc/host.h>
- #include <linux/mmc/sh_mmcif.h>
-+#include <linux/mmc/sh_mobile_sdhi.h>
-+#include <linux/mfd/tmio.h>
- #include <linux/platform_device.h>
- #include <linux/smsc911x.h>
- #include <linux/usb/r8a66597.h>
-@@ -183,6 +185,47 @@ static struct platform_device mmc_device = {
- .resource = sh_mmcif_resources,
- };
-
-+/* SDHI */
-+static struct sh_mobile_sdhi_info sdhi0_info = {
-+ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
-+ .tmio_caps = MMC_CAP_SD_HIGHSPEED,
-+ .tmio_ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
-+};
-+
-+static struct resource sdhi0_resources[] = {
-+ [0] = {
-+ .name = "SDHI0",
-+ .start = 0xee100000,
-+ .end = 0xee1000ff,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT,
-+ .start = gic_spi(83),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [2] = {
-+ .name = SH_MOBILE_SDHI_IRQ_SDCARD,
-+ .start = gic_spi(84),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [3] = {
-+ .name = SH_MOBILE_SDHI_IRQ_SDIO,
-+ .start = gic_spi(85),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device sdhi0_device = {
-+ .name = "sh_mobile_sdhi",
-+ .num_resources = ARRAY_SIZE(sdhi0_resources),
-+ .resource = sdhi0_resources,
-+ .dev = {
-+ .platform_data = &sdhi0_info,
-+ },
-+};
-+
-+/* I2C */
- static struct i2c_board_info i2c1_devices[] = {
- {
- I2C_BOARD_INFO("st1232-ts", 0x55),
-@@ -195,6 +238,7 @@ static struct platform_device *kzm_devices[] __initdata = {
- &usb_host_device,
- &lcdc_device,
- &mmc_device,
-+ &sdhi0_device,
- };
-
- /*
-@@ -316,6 +360,19 @@ static void __init kzm_init(void)
- gpio_request(GPIO_FN_MMCD0_6_PU, NULL);
- gpio_request(GPIO_FN_MMCD0_7_PU, NULL);
-
-+ /* enable SD */
-+ gpio_request(GPIO_FN_SDHIWP0, NULL);
-+ gpio_request(GPIO_FN_SDHICD0, NULL);
-+ gpio_request(GPIO_FN_SDHICMD0, NULL);
-+ gpio_request(GPIO_FN_SDHICLK0, NULL);
-+ gpio_request(GPIO_FN_SDHID0_3, NULL);
-+ gpio_request(GPIO_FN_SDHID0_2, NULL);
-+ gpio_request(GPIO_FN_SDHID0_1, NULL);
-+ gpio_request(GPIO_FN_SDHID0_0, NULL);
-+ gpio_request(GPIO_FN_SDHI0_VCCQ_MC0_ON, NULL);
-+ gpio_request(GPIO_PORT15, NULL);
-+ gpio_direction_output(GPIO_PORT15, 1); /* power */
-+
- #ifdef CONFIG_CACHE_L2X0
- /* Early BRESP enable, Shared attribute override enable, 64K*8way */
- l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:09:04 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:40 +0900
-Subject: [PATCH 04/21] ARM: mach-shmobile: kzm9g: add SMSC 9221 support
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-5-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit c15c4257a7858c6670f54c667f804df86a9fff1c)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/board-kzm9g.c | 39 ++++++++++++++++++++++++++++++++++
- 1 file changed, 39 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
-index 55dad87..a46aec1 100644
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -20,6 +20,8 @@
- #include <linux/io.h>
- #include <linux/irq.h>
- #include <linux/platform_device.h>
-+#include <linux/smsc911x.h>
-+#include <mach/irqs.h>
- #include <mach/sh73a0.h>
- #include <mach/common.h>
- #include <asm/hardware/cache-l2x0.h>
-@@ -27,7 +29,37 @@
- #include <asm/mach-types.h>
- #include <asm/mach/arch.h>
-
-+/* SMSC 9221 */
-+static struct resource smsc9221_resources[] = {
-+ [0] = {
-+ .start = 0x10000000, /* CS4 */
-+ .end = 0x100000ff,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = intcs_evt2irq(0x260), /* IRQ3 */
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct smsc911x_platform_config smsc9221_platdata = {
-+ .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
-+ .phy_interface = PHY_INTERFACE_MODE_MII,
-+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
-+};
-+
-+static struct platform_device smsc_device = {
-+ .name = "smsc911x",
-+ .dev = {
-+ .platform_data = &smsc9221_platdata,
-+ },
-+ .resource = smsc9221_resources,
-+ .num_resources = ARRAY_SIZE(smsc9221_resources),
-+};
-+
- static struct platform_device *kzm_devices[] __initdata = {
-+ &smsc_device,
- };
-
- static void __init kzm_init(void)
-@@ -40,6 +72,13 @@ static void __init kzm_init(void)
- gpio_request(GPIO_FN_SCIFA4_RTS_, NULL);
- gpio_request(GPIO_FN_SCIFA4_CTS_, NULL);
-
-+ /* CS4 for SMSC/USB */
-+ gpio_request(GPIO_FN_CS4_, NULL); /* CS4 */
-+
-+ /* SMSC */
-+ gpio_request(GPIO_PORT224, NULL); /* IRQ3 */
-+ gpio_direction_input(GPIO_PORT224);
-+
- #ifdef CONFIG_CACHE_L2X0
- /* Early BRESP enable, Shared attribute override enable, 64K*8way */
- l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
---
-1.7.9.5
-
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Mon Sep 24 22:09:30 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:43 +0900
-Subject: [PATCH 07/21] ARM: mach-shmobile: kzm9g: add ST1232 Touchscreen support
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, "Rafael J. Wysocki" <rjw@sisk.pl>
-Message-ID: <1348549677-1458-8-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 407c05266cd6e5db8ba77921fabdf9e04779088c)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/board-kzm9g.c | 14 ++++++++++++++
- 1 file changed, 14 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
-index 145341d..c846531 100644
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -21,6 +21,7 @@
- #include <linux/gpio.h>
- #include <linux/io.h>
- #include <linux/irq.h>
-+#include <linux/i2c.h>
- #include <linux/platform_device.h>
- #include <linux/smsc911x.h>
- #include <linux/usb/r8a66597.h>
-@@ -146,6 +147,13 @@ static struct platform_device lcdc_device = {
- },
- };
-
-+static struct i2c_board_info i2c1_devices[] = {
-+ {
-+ I2C_BOARD_INFO("st1232-ts", 0x55),
-+ .irq = intcs_evt2irq(0x300), /* IRQ8 */
-+ },
-+};
-+
- static struct platform_device *kzm_devices[] __initdata = {
- &smsc_device,
- &usb_host_device,
-@@ -253,11 +261,17 @@ static void __init kzm_init(void)
- gpio_request(GPIO_PORT222, NULL);
- gpio_direction_output(GPIO_PORT222, 1);
-
-+ /* Touchscreen */
-+ gpio_request(GPIO_PORT223, NULL); /* IRQ8 */
-+ gpio_direction_input(GPIO_PORT223);
-+
- #ifdef CONFIG_CACHE_L2X0
- /* Early BRESP enable, Shared attribute override enable, 64K*8way */
- l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
- #endif
-
-+ i2c_register_board_info(1, i2c1_devices, ARRAY_SIZE(i2c1_devices));
-+
- sh73a0_add_standard_devices();
- platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices));
- }
---
-1.7.9.5
-
-_______________________________________________
-LTSI-dev mailing list
-LTSI-dev@lists.linuxfoundation.org
-https://lists.linuxfoundation.org/mailman/listinfo/ltsi-dev
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:09:36 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:46 +0900
-Subject: [PATCH 10/21] ARM: mach-shmobile: kzm9g: correct screen direction
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-11-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-The correct screen direction of KZM9G board needs
-PORT226/SC settings.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 601df61657d4f762a99b155b695379fcc18f36e7)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/board-kzm9g.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
-index c846531..545d633 100644
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -258,8 +258,10 @@ static void __init kzm_init(void)
- gpio_request(GPIO_FN_LCDDISP, NULL);
- gpio_request(GPIO_FN_LCDDCK, NULL);
-
-- gpio_request(GPIO_PORT222, NULL);
-+ gpio_request(GPIO_PORT222, NULL); /* LCDCDON */
-+ gpio_request(GPIO_PORT226, NULL); /* SC */
- gpio_direction_output(GPIO_PORT222, 1);
-+ gpio_direction_output(GPIO_PORT226, 1);
-
- /* Touchscreen */
- gpio_request(GPIO_PORT223, NULL); /* IRQ8 */
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:09:46 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:50 +0900
-Subject: [PATCH 14/21] ARM: mach-shmobile: kzm9g: defconfig update
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-15-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-This patch enable GPIO-KEY/FSI,
-and remove debug settings,
-and be cleanuped by c2330e286f68f1c408b4aa6515ba49d57f05beae script
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit cc2504524b5b14dc03682dc1f04fb1644f692767)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/configs/kzm9g_defconfig | 24 +++++++++++++++++-------
- 1 file changed, 17 insertions(+), 7 deletions(-)
-
-diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig
-index 164c5d2..4bbea36 100644
---- a/arch/arm/configs/kzm9g_defconfig
-+++ b/arch/arm/configs/kzm9g_defconfig
-@@ -22,6 +22,7 @@ CONFIG_MODULE_UNLOAD=y
- # CONFIG_IOSCHED_DEADLINE is not set
- # CONFIG_IOSCHED_CFQ is not set
- CONFIG_ARCH_SHMOBILE=y
-+CONFIG_KEYBOARD_GPIO_POLLED=y
- CONFIG_ARCH_SH73A0=y
- CONFIG_MACH_KZM9G=y
- CONFIG_MEMORY_START=0x41000000
-@@ -67,8 +68,6 @@ CONFIG_INPUT_SPARSEKMAP=y
- # CONFIG_INPUT_MOUSEDEV is not set
- CONFIG_INPUT_EVDEV=y
- # CONFIG_KEYBOARD_ATKBD is not set
--CONFIG_KEYBOARD_GPIO=y
--CONFIG_KEYBOARD_SH_KEYSC=y
- # CONFIG_INPUT_MOUSE is not set
- CONFIG_INPUT_TOUCHSCREEN=y
- CONFIG_TOUCHSCREEN_ST1232=y
-@@ -79,13 +78,22 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
- # CONFIG_HW_RANDOM is not set
- CONFIG_I2C_CHARDEV=y
- CONFIG_I2C_SH_MOBILE=y
--CONFIG_POWER_SUPPLY=y
-+CONFIG_GPIO_PCF857X=y
- # CONFIG_HWMON is not set
- CONFIG_FB=y
- CONFIG_FB_SH_MOBILE_LCDC=y
- CONFIG_FRAMEBUFFER_CONSOLE=y
- CONFIG_LOGO=y
- CONFIG_FB_SH_MOBILE_MERAM=y
-+CONFIG_SOUND=y
-+CONFIG_SND=y
-+# CONFIG_SND_SUPPORT_OLD_API is not set
-+# CONFIG_SND_VERBOSE_PROCFS is not set
-+# CONFIG_SND_DRIVERS is not set
-+# CONFIG_SND_ARM is not set
-+# CONFIG_SND_USB is not set
-+CONFIG_SND_SOC=y
-+CONFIG_SND_SOC_SH4_FSI=y
- # CONFIG_HID_SUPPORT is not set
- CONFIG_USB=y
- CONFIG_USB_DEVICEFS=y
-@@ -115,11 +123,13 @@ CONFIG_NFS_V4_1=y
- CONFIG_ROOT_NFS=y
- CONFIG_NLS_CODEPAGE_437=y
- CONFIG_NLS_ISO8859_1=y
--CONFIG_MAGIC_SYSRQ=y
--CONFIG_DETECT_HUNG_TASK=y
--CONFIG_DEBUG_INFO=y
-+# CONFIG_ENABLE_WARN_DEPRECATED is not set
-+# CONFIG_ENABLE_MUST_CHECK is not set
-+# CONFIG_SCHED_DEBUG is not set
-+# CONFIG_DEBUG_PREEMPT is not set
-+# CONFIG_DEBUG_BUGVERBOSE is not set
- # CONFIG_FTRACE is not set
--CONFIG_DEBUG_USER=y
-+# CONFIG_ARM_UNWIND is not set
- CONFIG_CRYPTO=y
- CONFIG_CRYPTO_CBC=y
- CONFIG_CRYPTO_MD5=y
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:09:48 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:51 +0900
-Subject: [PATCH 15/21] ARM: mach-shmobile: kzm9g: enable SMP boot
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-16-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-Update the KZM9G defconfig and the code in platsmp.c to support SMP on
-the sh73a0 based KZM9G board. Also fix up the earlyprintk setting that
-was previously incorrect.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit fecf84c14fa755b0e30ba64a290db658a06c76fb)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/configs/kzm9g_defconfig | 4 +++-
- arch/arm/mach-shmobile/platsmp.c | 2 +-
- 2 files changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig
-index 4bbea36..e3ebc20 100644
---- a/arch/arm/configs/kzm9g_defconfig
-+++ b/arch/arm/configs/kzm9g_defconfig
-@@ -31,13 +31,15 @@ CONFIG_ARM_ERRATA_743622=y
- CONFIG_ARM_ERRATA_754322=y
- CONFIG_NO_HZ=y
- CONFIG_HIGH_RES_TIMERS=y
-+CONFIG_SMP=y
-+CONFIG_SCHED_MC=y
- CONFIG_PREEMPT=y
- CONFIG_AEABI=y
- # CONFIG_OABI_COMPAT is not set
- CONFIG_HIGHMEM=y
- CONFIG_ZBOOT_ROM_TEXT=0x0
- CONFIG_ZBOOT_ROM_BSS=0x0
--CONFIG_CMDLINE="console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel earlyprintk=serial"
-+CONFIG_CMDLINE="console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel earlyprintk=sh-sci.4,115200"
- CONFIG_KEXEC=y
- CONFIG_VFP=y
- CONFIG_NEON=y
-diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
-index 45fa392..d959f07 100644
---- a/arch/arm/mach-shmobile/platsmp.c
-+++ b/arch/arm/mach-shmobile/platsmp.c
-@@ -20,7 +20,7 @@
- #include <asm/mach-types.h>
- #include <mach/common.h>
-
--#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2())
-+#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2() || machine_is_kzm9g())
- #define is_r8a7779() machine_is_marzen()
-
- static unsigned int __init shmobile_smp_get_core_count(void)
---
-1.7.9.5
-
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Mon Sep 24 22:09:32 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:44 +0900
-Subject: [PATCH 08/21] ARM: mach-shmobile: pfc-sh73a0: fixup MSEL2CR MSEL18 for I2C-3
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, "Rafael J. Wysocki" <rjw@sisk.pl>
-Message-ID: <1348549677-1458-9-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-MSEL2CR MSEL18 should be 1 if I2C-3
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 03f804251c837bc0902f0b77c1ec6f8a29b1cd6e)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/pfc-sh73a0.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/pfc-sh73a0.c b/arch/arm/mach-shmobile/pfc-sh73a0.c
-index e05634c..4a547b8 100644
---- a/arch/arm/mach-shmobile/pfc-sh73a0.c
-+++ b/arch/arm/mach-shmobile/pfc-sh73a0.c
-@@ -829,14 +829,14 @@ static pinmux_enum_t pinmux_data[] = {
- PINMUX_DATA(PORT27_I2C_SCL2_MARK, PORT27_FN2, MSEL2CR_MSEL17_0,
- MSEL2CR_MSEL16_1), \
- PINMUX_DATA(PORT27_I2C_SCL3_MARK, PORT27_FN3, MSEL2CR_MSEL19_0,
-- MSEL2CR_MSEL18_0), \
-+ MSEL2CR_MSEL18_1), \
- PINMUX_DATA(MFG0_OUT1_MARK, PORT27_FN4), \
- PINMUX_DATA(PORT27_IROUT_MARK, PORT27_FN7),
- PINMUX_DATA(XDVFS2_MARK, PORT28_FN1), \
- PINMUX_DATA(PORT28_I2C_SDA2_MARK, PORT28_FN2, MSEL2CR_MSEL17_0,
- MSEL2CR_MSEL16_1), \
- PINMUX_DATA(PORT28_I2C_SDA3_MARK, PORT28_FN3, MSEL2CR_MSEL19_0,
-- MSEL2CR_MSEL18_0), \
-+ MSEL2CR_MSEL18_1), \
- PINMUX_DATA(PORT28_TPU1TO1_MARK, PORT28_FN7),
- PINMUX_DATA(SIM_RST_MARK, PORT29_FN1), \
- PINMUX_DATA(PORT29_TPU1TO1_MARK, PORT29_FN4),
---
-1.7.9.5
-
-_______________________________________________
-LTSI-dev mailing list
-LTSI-dev@lists.linuxfoundation.org
-https://lists.linuxfoundation.org/mailman/listinfo/ltsi-dev
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:10:02 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:54 +0900
-Subject: [PATCH 18/21] ARM: mach-shmobile: sh73a0: fixup PINT/IRQ16-IRQ31 irq number conflict
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-19-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-Current IRQ16-IRQ31 irq number are located around 800 from
-1ee8299a9ec1ce5137a044c7768293007b9a3267
-(ARM: mach-shmobile: Use 0x3400 as INTCS vector offset)
-
-But, the PINT0/1 IRQ number are also located around 800 from
-0df1a838d678fc6ab49f983a19e905f6a42297a0
-(ARM: mach-shmobile: sh73a0 PINT IRQ base fix)
-
-This patch relocates PINT0/1 IRQ number to around 700 where is not used,
-and adds current IRQ location table in comment area.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 4da773193414788b52ae14bc246543390faca5ce)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/include/mach/sh73a0.h | 34 +++++++++++++++++++++++---
- 1 file changed, 31 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h
-index ac75857..398e2c1 100644
---- a/arch/arm/mach-shmobile/include/mach/sh73a0.h
-+++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h
-@@ -518,8 +518,36 @@ enum {
- SHDMA_SLAVE_MMCIF_RX,
- };
-
--/* PINT interrupts are located at Linux IRQ 800 and up */
--#define SH73A0_PINT0_IRQ(irq) ((irq) + 800)
--#define SH73A0_PINT1_IRQ(irq) ((irq) + 832)
-+/*
-+ * SH73A0 IRQ LOCATION TABLE
-+ *
-+ * 416 -----------------------------------------
-+ * IRQ0-IRQ15
-+ * 431 -----------------------------------------
-+ * ...
-+ * 448 -----------------------------------------
-+ * sh73a0-intcs
-+ * sh73a0-intca-irq-pins
-+ * 680 -----------------------------------------
-+ * ...
-+ * 700 -----------------------------------------
-+ * sh73a0-pint0
-+ * 731 -----------------------------------------
-+ * 732 -----------------------------------------
-+ * sh73a0-pint1
-+ * 739 -----------------------------------------
-+ * ...
-+ * 800 -----------------------------------------
-+ * IRQ16-IRQ31
-+ * 815 -----------------------------------------
-+ * ...
-+ * 928 -----------------------------------------
-+ * sh73a0-intca-irq-pins
-+ * 943 -----------------------------------------
-+ */
-+
-+/* PINT interrupts are located at Linux IRQ 700 and up */
-+#define SH73A0_PINT0_IRQ(irq) ((irq) + 700)
-+#define SH73A0_PINT1_IRQ(irq) ((irq) + 732)
-
- #endif /* __ASM_SH73A0_H__ */
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:09:30 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:45 +0900
-Subject: [PATCH 09/21] ARM: mach-shmobile: sh73a0.h: add GPIO_NR
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-10-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-GPIO_NR is added in order to clarify end of GPIO array.
-We can add extra GPIO from it.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit bd8639b3885d2ac33b7e13d83d7849372a85fd07)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/include/mach/sh73a0.h | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h
-index cad5757..ac75857 100644
---- a/arch/arm/mach-shmobile/include/mach/sh73a0.h
-+++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h
-@@ -482,6 +482,9 @@ enum {
- GPIO_FN_FSIAILR_PU,
- GPIO_FN_FSIAIBT_PU,
- GPIO_FN_FSIAISLD_PU,
-+
-+ /* end of GPIO */
-+ GPIO_NR,
- };
-
- /* DMA slave IDs */
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:09:51 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:52 +0900
-Subject: [PATCH 16/21] ARM: mach-shmobile: Use DT_MACHINE for KZM9G
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-17-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-Use DT_MACHINE_START() on the sh73a0 based KZM9G board.
-
-Also include a tiny DTS file to describe the board and
-update the Kconfig dependencies to select CONFIG_USE_OF.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 7296d93201710865233fbebf7c9853d2f95d7716)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/boot/dts/sh73a0-kzm9g.dts | 22 ++++++++++++++++++++++
- arch/arm/mach-shmobile/Kconfig | 1 +
- arch/arm/mach-shmobile/board-kzm9g.c | 8 +++++++-
- 3 files changed, 30 insertions(+), 1 deletion(-)
- create mode 100644 arch/arm/boot/dts/sh73a0-kzm9g.dts
-
---- /dev/null
-+++ b/arch/arm/boot/dts/sh73a0-kzm9g.dts
-@@ -0,0 +1,22 @@
-+/*
-+ * Device Tree Source for the KZM-A9-GT board
-+ *
-+ * Copyright (C) 2012 Renesas Solutions Corp.
-+ *
-+ * 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.
-+ */
-+
-+/dts-v1/;
-+/include/ "skeleton.dtsi"
-+
-+/ {
-+ model = "KZM-A9-GT";
-+ compatible = "renesas,kzm9g";
-+
-+ memory {
-+ device_type = "memory";
-+ reg = <0x41000000 0x1e800000>;
-+ };
-+};
---- a/arch/arm/mach-shmobile/Kconfig
-+++ b/arch/arm/mach-shmobile/Kconfig
-@@ -111,6 +111,7 @@ config MACH_KZM9G
- bool "KZM-A9-GT board"
- depends on ARCH_SH73A0
- select ARCH_REQUIRE_GPIOLIB
-+ select USE_OF
-
- comment "SH-Mobile System Configuration"
-
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -443,7 +443,12 @@ static void __init kzm_init(void)
- platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices));
- }
-
--MACHINE_START(KZM9G, "kzm9g")
-+static const char *kzm9g_boards_compat_dt[] __initdata = {
-+ "renesas,kzm9g",
-+ NULL,
-+};
-+
-+DT_MACHINE_START(KZM9G_DT, "kzm9g")
- .map_io = sh73a0_map_io,
- .init_early = sh73a0_add_early_devices,
- .nr_irqs = NR_IRQS_LEGACY,
-@@ -451,4 +456,5 @@ MACHINE_START(KZM9G, "kzm9g")
- .handle_irq = gic_handle_irq,
- .init_machine = kzm_init,
- .timer = &shmobile_timer,
-+ .dt_compat = kzm9g_boards_compat_dt,
- MACHINE_END
+++ /dev/null
-From koba@kmckk.co.jp Mon Nov 19 00:51:57 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Mon, 19 Nov 2012 17:51:06 +0900
-Subject: [PATCH 4/5] ARM: shmobile: add new __iomem annotation for new code
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Arnd Bergmann <arnd@arndb.de>, Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>, Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>, Simon Horman <horms@verge.net.au>
-Message-ID: <1353315067-7771-5-git-send-email-koba@kmckk.co.jp>
-
-
-From: Arnd Bergmann <arnd@arndb.de>
-
-This is back port to LTSI 3.4.
-
-While we fixed up all instances that were already present in v3.6,
-this one came in through new code.
-
-Without this patch, building kzm9g_defconfig results in:
-
-arch/arm/mach-shmobile/board-kzm9g.c: In function 'kzm9g_restart':
-arch/arm/mach-shmobile/board-kzm9g.c:781:2: warning: passing argument 2 of '__raw_writel' makes pointer from integer without a cast [enabled by default]
-
-Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-Cc: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
-Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Cc: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Cc: Simon Horman <horms@verge.net.au>
-(cherry picked from commit 28901c1fed11dfeab65f640878e85a9b61d311ed)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/board-kzm9g.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
-index 4e62227..af4d760 100644
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -733,7 +733,7 @@ static void __init kzm_init(void)
-
- static void kzm9g_restart(char mode, const char *cmd)
- {
--#define RESCNT2 0xe6188020
-+#define RESCNT2 IOMEM(0xe6188020)
- /* Do soft power on reset */
- writel((1 << 31), RESCNT2);
- }
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:10:10 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:56 +0900
-Subject: [PATCH 20/21] ARM: shmobile: fix platsmp.c build when ARCH_SH73A0=n
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, Arnd Bergmann <arnd@arndb.de>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-21-git-send-email-koba@kmckk.co.jp>
-
-
-From: Magnus Damm <damm@opensource.se>
-
-Fix build error in the case of SMP=y but ARCH_SH73A0=n
-introduced by:
-
-9601e87 ARM: shmobile: fix smp build
-
-The use of of_machine_is_compatible() will link in the
-the SoC-specific symbols:
-"sh73a0_get_core_count", "sh73a0_smp_prepare_cpus",
-"sh73a0_secondary_init" and "sh73a0_boot_secondary".
-
-This patch adds an ugly #ifdef wrapper as a stop-gap
-solution.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Tested-by: Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: "Rafael J. Wysocki" <rjw@sisk.pl>
-Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-(cherry picked from commit 873e9f7a3b8a5ca36085437da364654bfe3e5974)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/platsmp.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
-index 5a2b69c..932ac8f 100644
---- a/arch/arm/mach-shmobile/platsmp.c
-+++ b/arch/arm/mach-shmobile/platsmp.c
-@@ -21,8 +21,13 @@
- #include <asm/mach-types.h>
- #include <mach/common.h>
-
-+#ifdef CONFIG_ARCH_SH73A0
- #define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2() || \
- of_machine_is_compatible("renesas,sh73a0"))
-+#else
-+#define is_sh73a0() (0)
-+#endif
-+
- #define is_r8a7779() machine_is_marzen()
-
- static unsigned int __init shmobile_smp_get_core_count(void)
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:09:59 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:53 +0900
-Subject: [PATCH 17/21] ARM: shmobile: fix smp build
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, Arnd Bergmann <arnd@arndb.de>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-18-git-send-email-koba@kmckk.co.jp>
-
-
-From: Arnd Bergmann <arnd@arndb.de>
-
-I got build errors with the new version now because machine_is_kzm9g is no longer
-defined:
-
-arch/arm/mach-shmobile/platsmp.c: In function 'shmobile_smp_get_core_count':
-arch/arm/mach-shmobile/platsmp.c:29:2: error: implicit declaration of function 'of_machine_is_compatible'
-
-Replace the missing function with a call to of_machine_is_compatible.
-
-Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-Acked-by: "Rafael J. Wysocki" <rjw@sisk.pl>
-Acked-by: Magnus Damm <magnus.damm@gmail.com>
-(cherry picked from commit 9601e87388f4969a80b021a40215d24c4e78d5b3)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/boot/dts/sh73a0-kzm9g.dts | 2 +-
- arch/arm/mach-shmobile/platsmp.c | 4 +++-
- 2 files changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm/boot/dts/sh73a0-kzm9g.dts b/arch/arm/boot/dts/sh73a0-kzm9g.dts
-index ed1bae5..bcb9119 100644
---- a/arch/arm/boot/dts/sh73a0-kzm9g.dts
-+++ b/arch/arm/boot/dts/sh73a0-kzm9g.dts
-@@ -13,7 +13,7 @@
-
- / {
- model = "KZM-A9-GT";
-- compatible = "renesas,kzm9g";
-+ compatible = "renesas,kzm9g", "renesas,sh73a0";
-
- memory {
- device_type = "memory";
-diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
-index d959f07..5a2b69c 100644
---- a/arch/arm/mach-shmobile/platsmp.c
-+++ b/arch/arm/mach-shmobile/platsmp.c
-@@ -16,11 +16,13 @@
- #include <linux/device.h>
- #include <linux/smp.h>
- #include <linux/io.h>
-+#include <linux/of.h>
- #include <asm/hardware/gic.h>
- #include <asm/mach-types.h>
- #include <mach/common.h>
-
--#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2() || machine_is_kzm9g())
-+#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2() || \
-+ of_machine_is_compatible("renesas,sh73a0"))
- #define is_r8a7779() machine_is_marzen()
-
- static unsigned int __init shmobile_smp_get_core_count(void)
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Nov 19 00:51:45 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Mon, 19 Nov 2012 17:51:05 +0900
-Subject: [PATCH 3/5] ARM: shmobile: kzm9g: bugfix: correct mmcif interrupt settings
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Tetsuyuki Kobayashi <koba@kmckk.co.jp>, Simon Horman <horms@verge.net.au>
-Message-ID: <1353315067-7771-4-git-send-email-koba@kmckk.co.jp>
-
-
-This is back port to LTSI 3.4.
-Correct interrupt settings of sh_mmc:int and sh_mmc:error in board-kzm9g.c.
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Simon Horman <horms@verge.net.au>
-(cherry picked from commit a704835d6a7a8254067a1be60d614cd5c0c73e44)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/board-kzm9g.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
-index 9b69a95..4e62227 100644
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -331,11 +331,11 @@ static struct resource sh_mmcif_resources[] = {
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = gic_spi(141),
-+ .start = gic_spi(140),
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
-- .start = gic_spi(140),
-+ .start = gic_spi(141),
- .flags = IORESOURCE_IRQ,
- },
- };
---
-1.7.9.5
-
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Mon Oct 1 01:13:03 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Mon, 1 Oct 2012 17:09:26 +0900
-Subject: [PATCH 22/23] ARM: shmobile: kzm9g: defconfig enable INOTIFY_USER
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, "Rafael J. Wysocki" <rjw@sisk.pl>
-Message-ID: <1349078967-16437-23-git-send-email-koba@kmckk.co.jp>
-
-
-From: Simon Horman <horms@verge.net.au>
-
-This is required for udev to run which is common to many user-spaces.
-
-It is my understanding that this is a requirement for automated
-testing conducted by Iwamatsu-san.
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
-Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit ec29174ad2069d6768a7229eab0453e7b7343abe)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/configs/kzm9g_defconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig
-index 7b2eecd..2388c86 100644
---- a/arch/arm/configs/kzm9g_defconfig
-+++ b/arch/arm/configs/kzm9g_defconfig
-@@ -119,7 +119,7 @@ CONFIG_SH_DMAE=y
- CONFIG_ASYNC_TX_DMA=y
- CONFIG_STAGING=y
- # CONFIG_DNOTIFY is not set
--# CONFIG_INOTIFY_USER is not set
-+CONFIG_INOTIFY_USER=y
- CONFIG_VFAT_FS=y
- CONFIG_TMPFS=y
- # CONFIG_MISC_FILESYSTEMS is not set
---
-1.7.9.5
-
-_______________________________________________
-LTSI-dev mailing list
-LTSI-dev@lists.linuxfoundation.org
-https://lists.linuxfoundation.org/mailman/listinfo/ltsi-dev
-
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Mon Oct 1 01:13:00 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Mon, 1 Oct 2012 17:09:25 +0900
-Subject: [PATCH 21/23] ARM: shmobile: kzm9g: enable DMAEngine on FSI
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, "Rafael J. Wysocki" <rjw@sisk.pl>
-Message-ID: <1349078967-16437-22-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-It is possible to reduce CPU load if FSI playback used DMAEngine.
-This patch enabled it.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 76b80329177c4b4675b00256844804d09038e2ad)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/board-kzm9g.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
-index b056b7a..212c524 100644
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -470,6 +470,7 @@ static struct platform_device gpio_keys_device = {
- /* FSI-AK4648 */
- static struct sh_fsi_platform_info fsi_info = {
- .port_a = {
-+ .tx_id = SHDMA_SLAVE_FSI2A_TX,
- },
- };
-
---
-1.7.9.5
-
-_______________________________________________
-LTSI-dev mailing list
-LTSI-dev@lists.linuxfoundation.org
-https://lists.linuxfoundation.org/mailman/listinfo/ltsi-dev
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Oct 1 01:11:13 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Mon, 1 Oct 2012 17:09:08 +0900
-Subject: [PATCH 04/23] ARM: shmobile: kzm9g: enable FSI-AK4648
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349078967-16437-5-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-This patch enable sound playback/capture on CN9/CN10.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit accb90c8f3b5c22c9d2893c775e98abb4a0d6bd3)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/Kconfig | 1
- arch/arm/mach-shmobile/board-kzm9g.c | 79 +++++++++++++++++++++++++++++++++++
- 2 files changed, 80 insertions(+)
-
---- a/arch/arm/mach-shmobile/Kconfig
-+++ b/arch/arm/mach-shmobile/Kconfig
-@@ -112,6 +112,7 @@ config MACH_KZM9G
- depends on ARCH_SH73A0
- select ARCH_REQUIRE_GPIOLIB
- select USE_OF
-+ select SND_SOC_AK4642 if SND_SIMPLE_CARD
-
- comment "SH-Mobile System Configuration"
-
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -33,6 +33,8 @@
- #include <linux/smsc911x.h>
- #include <linux/usb/r8a66597.h>
- #include <linux/videodev2.h>
-+#include <sound/sh_fsi.h>
-+#include <sound/simple_card.h>
- #include <mach/irqs.h>
- #include <mach/sh73a0.h>
- #include <mach/common.h>
-@@ -54,6 +56,14 @@
- #define GPIO_PCF8575_PORT15 (GPIO_NR + 13)
- #define GPIO_PCF8575_PORT16 (GPIO_NR + 14)
-
-+/*
-+ * FSI-AK4648
-+ *
-+ * this command is required when playback.
-+ *
-+ * # amixer set "LINEOUT Mixer DACL" on
-+ */
-+
- /* SMSC 9221 */
- static struct resource smsc9221_resources[] = {
- [0] = {
-@@ -267,11 +277,70 @@ static struct platform_device gpio_keys_
- },
- };
-
-+/* FSI-AK4648 */
-+static struct sh_fsi_platform_info fsi_info = {
-+ .port_a = {
-+ },
-+};
-+
-+static struct resource fsi_resources[] = {
-+ [0] = {
-+ .name = "FSI",
-+ .start = 0xEC230000,
-+ .end = 0xEC230400 - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = gic_spi(146),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device fsi_device = {
-+ .name = "sh_fsi2",
-+ .id = -1,
-+ .num_resources = ARRAY_SIZE(fsi_resources),
-+ .resource = fsi_resources,
-+ .dev = {
-+ .platform_data = &fsi_info,
-+ },
-+};
-+
-+static struct asoc_simple_dai_init_info fsi2_ak4648_init_info = {
-+ .fmt = SND_SOC_DAIFMT_LEFT_J,
-+ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM,
-+ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS,
-+ .sysclk = 11289600,
-+};
-+
-+static struct asoc_simple_card_info fsi2_ak4648_info = {
-+ .name = "AK4648",
-+ .card = "FSI2A-AK4648",
-+ .cpu_dai = "fsia-dai",
-+ .codec = "ak4642-codec.0-0012",
-+ .platform = "sh_fsi2",
-+ .codec_dai = "ak4642-hifi",
-+ .init = &fsi2_ak4648_init_info,
-+};
-+
-+static struct platform_device fsi_ak4648_device = {
-+ .name = "asoc-simple-card",
-+ .dev = {
-+ .platform_data = &fsi2_ak4648_info,
-+ },
-+};
-+
- /* I2C */
- static struct pcf857x_platform_data pcf8575_pdata = {
- .gpio_base = GPIO_PCF8575_BASE,
- };
-
-+static struct i2c_board_info i2c0_devices[] = {
-+ {
-+ I2C_BOARD_INFO("ak4648", 0x12),
-+ }
-+};
-+
- static struct i2c_board_info i2c1_devices[] = {
- {
- I2C_BOARD_INFO("st1232-ts", 0x55),
-@@ -293,6 +362,8 @@ static struct platform_device *kzm_devic
- &mmc_device,
- &sdhi0_device,
- &gpio_keys_device,
-+ &fsi_device,
-+ &fsi_ak4648_device,
- };
-
- /*
-@@ -431,11 +502,19 @@ static void __init kzm_init(void)
- gpio_request(GPIO_FN_PORT27_I2C_SCL3, NULL);
- gpio_request(GPIO_FN_PORT28_I2C_SDA3, NULL);
-
-+ /* enable FSI2 port A (ak4648) */
-+ gpio_request(GPIO_FN_FSIACK, NULL);
-+ gpio_request(GPIO_FN_FSIAILR, NULL);
-+ gpio_request(GPIO_FN_FSIAIBT, NULL);
-+ gpio_request(GPIO_FN_FSIAISLD, NULL);
-+ gpio_request(GPIO_FN_FSIAOSLD, NULL);
-+
- #ifdef CONFIG_CACHE_L2X0
- /* Early BRESP enable, Shared attribute override enable, 64K*8way */
- l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
- #endif
-
-+ i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices));
- i2c_register_board_info(1, i2c1_devices, ARRAY_SIZE(i2c1_devices));
- i2c_register_board_info(3, i2c3_devices, ARRAY_SIZE(i2c3_devices));
-
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Mon Oct 1 01:12:10 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Mon, 1 Oct 2012 17:09:13 +0900
-Subject: [PATCH 09/23] ARM: shmobile: kzm9g: enable MicroSD
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, "Rafael J. Wysocki" <rjw@sisk.pl>
-Message-ID: <1349078967-16437-10-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-This patch enable MicroSD on CN20
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 425d6940b967c874dd76f4e5b9c81e201b83bc3b)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/board-kzm9g.c | 55 ++++++++++++++++++++++++++++++++++
- 1 file changed, 55 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
-index 27194bc..b056b7a 100644
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -396,6 +396,50 @@ static struct platform_device sdhi0_device = {
- },
- };
-
-+/* Micro SD */
-+static struct sh_mobile_sdhi_info sdhi2_info = {
-+ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT |
-+ TMIO_MMC_USE_GPIO_CD |
-+ TMIO_MMC_WRPROTECT_DISABLE,
-+ .tmio_caps = MMC_CAP_SD_HIGHSPEED,
-+ .tmio_ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
-+ .cd_gpio = GPIO_PORT13,
-+};
-+
-+static struct resource sdhi2_resources[] = {
-+ [0] = {
-+ .name = "SDHI2",
-+ .start = 0xee140000,
-+ .end = 0xee1400ff,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT,
-+ .start = gic_spi(103),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [2] = {
-+ .name = SH_MOBILE_SDHI_IRQ_SDCARD,
-+ .start = gic_spi(104),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [3] = {
-+ .name = SH_MOBILE_SDHI_IRQ_SDIO,
-+ .start = gic_spi(105),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device sdhi2_device = {
-+ .name = "sh_mobile_sdhi",
-+ .id = 2,
-+ .num_resources = ARRAY_SIZE(sdhi2_resources),
-+ .resource = sdhi2_resources,
-+ .dev = {
-+ .platform_data = &sdhi2_info,
-+ },
-+};
-+
- /* KEY */
- #define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
-
-@@ -511,6 +555,7 @@ static struct platform_device *kzm_devices[] __initdata = {
- &lcdc_device,
- &mmc_device,
- &sdhi0_device,
-+ &sdhi2_device,
- &gpio_keys_device,
- &fsi_device,
- &fsi_ak4648_device,
-@@ -648,6 +693,16 @@ static void __init kzm_init(void)
- gpio_request(GPIO_PORT15, NULL);
- gpio_direction_output(GPIO_PORT15, 1); /* power */
-
-+ /* enable Micro SD */
-+ gpio_request(GPIO_FN_SDHID2_0, NULL);
-+ gpio_request(GPIO_FN_SDHID2_1, NULL);
-+ gpio_request(GPIO_FN_SDHID2_2, NULL);
-+ gpio_request(GPIO_FN_SDHID2_3, NULL);
-+ gpio_request(GPIO_FN_SDHICMD2, NULL);
-+ gpio_request(GPIO_FN_SDHICLK2, NULL);
-+ gpio_request(GPIO_PORT14, NULL);
-+ gpio_direction_output(GPIO_PORT14, 1); /* power */
-+
- /* I2C 3 */
- gpio_request(GPIO_FN_PORT27_I2C_SCL3, NULL);
- gpio_request(GPIO_FN_PORT28_I2C_SDA3, NULL);
---
-1.7.9.5
-
-_______________________________________________
-LTSI-dev mailing list
-LTSI-dev@lists.linuxfoundation.org
-https://lists.linuxfoundation.org/mailman/listinfo/ltsi-dev
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Nov 19 00:51:36 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Mon, 19 Nov 2012 17:51:03 +0900
-Subject: [PATCH 1/5] ARM: shmobile: kzm9g: enable restarting
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Tetsuyuki Kobayashi <koba@kmckk.co.jp>, Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>, Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>, Simon Horman <horms@verge.net.au>
-Message-ID: <1353315067-7771-2-git-send-email-koba@kmckk.co.jp>
-
-
-This is back port to LTSI 3.4.
-Do soft-power-on-reset in sys_reboot system call.
-
-How to test this patch
- Execute "sudo reboot" from command line. The system will start shutdown
- sequence and finally reboot and U-Boot restarts.
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Cc: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
-Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Simon Horman <horms@verge.net.au>
-(cherry picked from commit 7952717adb69efc1d2443a1858f96d23c2fb93e0)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/board-kzm9g.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
-index 212c524..9b69a95 100644
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -731,6 +731,13 @@ static void __init kzm_init(void)
- platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices));
- }
-
-+static void kzm9g_restart(char mode, const char *cmd)
-+{
-+#define RESCNT2 0xe6188020
-+ /* Do soft power on reset */
-+ writel((1 << 31), RESCNT2);
-+}
-+
- static const char *kzm9g_boards_compat_dt[] __initdata = {
- "renesas,kzm9g",
- NULL,
-@@ -744,5 +751,6 @@ DT_MACHINE_START(KZM9G_DT, "kzm9g")
- .handle_irq = gic_handle_irq,
- .init_machine = kzm_init,
- .timer = &shmobile_timer,
-+ .restart = kzm9g_restart,
- .dt_compat = kzm9g_boards_compat_dt,
- MACHINE_END
---
-1.7.9.5
-
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Mon Oct 1 01:11:52 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Mon, 1 Oct 2012 17:09:11 +0900
-Subject: [PATCH 07/23] ARM: shmobile: kzm9g: enable USB function
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, "Rafael J. Wysocki" <rjw@sisk.pl>
-Message-ID: <1349078967-16437-8-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-This patch enable USB function on CN17
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 77bcefd90c52b6806046b71212dcd5983475265b)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/configs/kzm9g_defconfig | 5 ++
- arch/arm/mach-shmobile/board-kzm9g.c | 150 ++++++++++++++++++++++++++++++++++
- 2 files changed, 155 insertions(+)
-
-diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig
-index 686129f..7b2eecd 100644
---- a/arch/arm/configs/kzm9g_defconfig
-+++ b/arch/arm/configs/kzm9g_defconfig
-@@ -100,7 +100,12 @@ CONFIG_SND_SOC_SH4_FSI=y
- CONFIG_USB=y
- CONFIG_USB_DEVICEFS=y
- CONFIG_USB_R8A66597_HCD=y
-+CONFIG_USB_RENESAS_USBHS=y
- CONFIG_USB_STORAGE=y
-+CONFIG_USB_GADGET=y
-+CONFIG_USB_RENESAS_USBHS_UDC=y
-+CONFIG_USB_ETH=m
-+CONFIG_USB_MASS_STORAGE=m
- CONFIG_MMC=y
- # CONFIG_MMC_BLOCK_BOUNCE is not set
- CONFIG_MMC_SDHI=y
-diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
-index a5cb113..27194bc 100644
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -32,6 +32,7 @@
- #include <linux/platform_device.h>
- #include <linux/smsc911x.h>
- #include <linux/usb/r8a66597.h>
-+#include <linux/usb/renesas_usbhs.h>
- #include <linux/videodev2.h>
- #include <sound/sh_fsi.h>
- #include <sound/simple_card.h>
-@@ -122,6 +123,151 @@ static struct platform_device usb_host_device = {
- .resource = usb_resources,
- };
-
-+/* USB Func CN17 */
-+struct usbhs_private {
-+ unsigned int phy;
-+ unsigned int cr2;
-+ struct renesas_usbhs_platform_info info;
-+};
-+
-+#define IRQ15 intcs_evt2irq(0x03e0)
-+#define USB_PHY_MODE (1 << 4)
-+#define USB_PHY_INT_EN ((1 << 3) | (1 << 2))
-+#define USB_PHY_ON (1 << 1)
-+#define USB_PHY_OFF (1 << 0)
-+#define USB_PHY_INT_CLR (USB_PHY_ON | USB_PHY_OFF)
-+
-+#define usbhs_get_priv(pdev) \
-+ container_of(renesas_usbhs_get_info(pdev), struct usbhs_private, info)
-+
-+static int usbhs_get_vbus(struct platform_device *pdev)
-+{
-+ struct usbhs_private *priv = usbhs_get_priv(pdev);
-+
-+ return !((1 << 7) & __raw_readw(priv->cr2));
-+}
-+
-+static void usbhs_phy_reset(struct platform_device *pdev)
-+{
-+ struct usbhs_private *priv = usbhs_get_priv(pdev);
-+
-+ /* init phy */
-+ __raw_writew(0x8a0a, priv->cr2);
-+}
-+
-+static int usbhs_get_id(struct platform_device *pdev)
-+{
-+ return USBHS_GADGET;
-+}
-+
-+static irqreturn_t usbhs_interrupt(int irq, void *data)
-+{
-+ struct platform_device *pdev = data;
-+ struct usbhs_private *priv = usbhs_get_priv(pdev);
-+
-+ renesas_usbhs_call_notify_hotplug(pdev);
-+
-+ /* clear status */
-+ __raw_writew(__raw_readw(priv->phy) | USB_PHY_INT_CLR, priv->phy);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static int usbhs_hardware_init(struct platform_device *pdev)
-+{
-+ struct usbhs_private *priv = usbhs_get_priv(pdev);
-+ int ret;
-+
-+ /* clear interrupt status */
-+ __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy);
-+
-+ ret = request_irq(IRQ15, usbhs_interrupt, IRQF_TRIGGER_HIGH,
-+ dev_name(&pdev->dev), pdev);
-+ if (ret) {
-+ dev_err(&pdev->dev, "request_irq err\n");
-+ return ret;
-+ }
-+
-+ /* enable USB phy interrupt */
-+ __raw_writew(USB_PHY_MODE | USB_PHY_INT_EN, priv->phy);
-+
-+ return 0;
-+}
-+
-+static void usbhs_hardware_exit(struct platform_device *pdev)
-+{
-+ struct usbhs_private *priv = usbhs_get_priv(pdev);
-+
-+ /* clear interrupt status */
-+ __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy);
-+
-+ free_irq(IRQ15, pdev);
-+}
-+
-+static u32 usbhs_pipe_cfg[] = {
-+ USB_ENDPOINT_XFER_CONTROL,
-+ USB_ENDPOINT_XFER_ISOC,
-+ USB_ENDPOINT_XFER_ISOC,
-+ USB_ENDPOINT_XFER_BULK,
-+ USB_ENDPOINT_XFER_BULK,
-+ USB_ENDPOINT_XFER_BULK,
-+ USB_ENDPOINT_XFER_INT,
-+ USB_ENDPOINT_XFER_INT,
-+ USB_ENDPOINT_XFER_INT,
-+ USB_ENDPOINT_XFER_BULK,
-+ USB_ENDPOINT_XFER_BULK,
-+ USB_ENDPOINT_XFER_BULK,
-+ USB_ENDPOINT_XFER_BULK,
-+ USB_ENDPOINT_XFER_BULK,
-+ USB_ENDPOINT_XFER_BULK,
-+ USB_ENDPOINT_XFER_BULK,
-+};
-+
-+static struct usbhs_private usbhs_private = {
-+ .phy = 0xe60781e0, /* USBPHYINT */
-+ .cr2 = 0xe605810c, /* USBCR2 */
-+ .info = {
-+ .platform_callback = {
-+ .hardware_init = usbhs_hardware_init,
-+ .hardware_exit = usbhs_hardware_exit,
-+ .get_id = usbhs_get_id,
-+ .phy_reset = usbhs_phy_reset,
-+ .get_vbus = usbhs_get_vbus,
-+ },
-+ .driver_param = {
-+ .buswait_bwait = 4,
-+ .has_otg = 1,
-+ .pipe_type = usbhs_pipe_cfg,
-+ .pipe_size = ARRAY_SIZE(usbhs_pipe_cfg),
-+ },
-+ },
-+};
-+
-+static struct resource usbhs_resources[] = {
-+ [0] = {
-+ .start = 0xE6890000,
-+ .end = 0xE68900e6 - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = gic_spi(62),
-+ .end = gic_spi(62),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device usbhs_device = {
-+ .name = "renesas_usbhs",
-+ .id = -1,
-+ .dev = {
-+ .dma_mask = NULL,
-+ .coherent_dma_mask = 0xffffffff,
-+ .platform_data = &usbhs_private.info,
-+ },
-+ .num_resources = ARRAY_SIZE(usbhs_resources),
-+ .resource = usbhs_resources,
-+};
-+
- /* LCDC */
- static struct fb_videomode kzm_lcdc_mode = {
- .name = "WVGA Panel",
-@@ -361,6 +507,7 @@ static struct i2c_board_info i2c3_devices[] = {
- static struct platform_device *kzm_devices[] __initdata = {
- &smsc_device,
- &usb_host_device,
-+ &usbhs_device,
- &lcdc_device,
- &mmc_device,
- &sdhi0_device,
-@@ -512,6 +659,9 @@ static void __init kzm_init(void)
- gpio_request(GPIO_FN_FSIAISLD, NULL);
- gpio_request(GPIO_FN_FSIAOSLD, NULL);
-
-+ /* enable USB */
-+ gpio_request(GPIO_FN_VBUS_0, NULL);
-+
- #ifdef CONFIG_CACHE_L2X0
- /* Early BRESP enable, Shared attribute override enable, 64K*8way */
- l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
---
-1.7.9.5
-
-_______________________________________________
-LTSI-dev mailing list
-LTSI-dev@lists.linuxfoundation.org
-https://lists.linuxfoundation.org/mailman/listinfo/ltsi-dev
-
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Mon Oct 1 01:11:25 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Mon, 1 Oct 2012 17:09:09 +0900
-Subject: [PATCH 05/23] ARM: shmobile: kzm9g: Support Real Time Clock
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, "Rafael J. Wysocki" <rjw@sisk.pl>
-Message-ID: <1349078967-16437-6-git-send-email-koba@kmckk.co.jp>
-
-
-KZM-A9-GT board has RTC device r2025d at I2C channel 0
-with slave address 0x64.
-
-This patch enables reading and writing hardware real time clock on
-KZM-A9-GT board. Interrupt is not yet supported.
-
-How to test this patch using user space command.
-
-Read RTC
- # hwclock -r
-
-Copy system clock to RTC
- # hwclock -w
-
-Shutdown and power off the board, and wait a while, then power on again.
-Check RTC still keeps correct date.
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 080e0d1384a3fce16b7d5324dbfc47c136cc3573)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/configs/kzm9g_defconfig | 1 +
- arch/arm/mach-shmobile/board-kzm9g.c | 3 +++
- 2 files changed, 4 insertions(+)
-
-diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig
-index e3ebc20..686129f 100644
---- a/arch/arm/configs/kzm9g_defconfig
-+++ b/arch/arm/configs/kzm9g_defconfig
-@@ -108,6 +108,7 @@ CONFIG_MMC_SH_MMCIF=y
- CONFIG_NEW_LEDS=y
- CONFIG_LEDS_CLASS=y
- CONFIG_RTC_CLASS=y
-+CONFIG_RTC_DRV_RS5C372=y
- CONFIG_DMADEVICES=y
- CONFIG_SH_DMAE=y
- CONFIG_ASYNC_TX_DMA=y
-diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
-index 7523e9e..a5cb113 100644
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -338,6 +338,9 @@ static struct pcf857x_platform_data pcf8575_pdata = {
- static struct i2c_board_info i2c0_devices[] = {
- {
- I2C_BOARD_INFO("ak4648", 0x12),
-+ },
-+ {
-+ I2C_BOARD_INFO("r2025sd", 0x32),
- }
- };
-
---
-1.7.9.5
-
-_______________________________________________
-LTSI-dev mailing list
-LTSI-dev@lists.linuxfoundation.org
-https://lists.linuxfoundation.org/mailman/listinfo/ltsi-dev
-
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Mon Oct 1 01:12:52 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Mon, 1 Oct 2012 17:09:22 +0900
-Subject: [PATCH 18/23] ARM: shmobile: sh73a0: add DMAEngine support for MPDMAC
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, "Rafael J. Wysocki" <rjw@sisk.pl>
-Message-ID: <1349078967-16437-19-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-Current shdmac can support MPDMAC (= sound DMA) on sh73a0.
-This support reduce CPU load when sound was playback.
-
-On v2.0 manual, MPDMAC MID/RID number were wrong.
-This patch is using the number which seems correct.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 832290b25e20e0c3a6da056f7d0999de51311f2c)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/clock-sh73a0.c | 4 +-
- arch/arm/mach-shmobile/include/mach/sh73a0.h | 7 ++
- arch/arm/mach-shmobile/setup-sh73a0.c | 111 ++++++++++++++++++++++++++
- 3 files changed, 121 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
-index 06ffa4a..37ba014 100644
---- a/arch/arm/mach-shmobile/clock-sh73a0.c
-+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
-@@ -475,7 +475,7 @@ static struct clk *late_main_clks[] = {
-
- enum { MSTP001,
- MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP100,
-- MSTP219, MSTP218,
-+ MSTP219, MSTP218, MSTP217,
- MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
- MSTP331, MSTP329, MSTP328, MSTP325, MSTP323, MSTP322,
- MSTP314, MSTP313, MSTP312, MSTP311,
-@@ -498,6 +498,7 @@ static struct clk mstp_clks[MSTP_NR] = {
- [MSTP100] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */
- [MSTP219] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 19, 0), /* SCIFA7 */
- [MSTP218] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* SY-DMAC */
-+ [MSTP217] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* MP-DMAC */
- [MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */
- [MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */
- [MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */
-@@ -555,6 +556,7 @@ static struct clk_lookup lookups[] = {
- CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */
- CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP219]), /* SCIFA7 */
- CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), /* SY-DMAC */
-+ CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), /* MP-DMAC */
- CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */
- CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), /* SCIFB */
- CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
-diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h
-index 398e2c1..fe950f2 100644
---- a/arch/arm/mach-shmobile/include/mach/sh73a0.h
-+++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h
-@@ -516,6 +516,13 @@ enum {
- SHDMA_SLAVE_SDHI2_RX,
- SHDMA_SLAVE_MMCIF_TX,
- SHDMA_SLAVE_MMCIF_RX,
-+ SHDMA_SLAVE_FSI2A_TX,
-+ SHDMA_SLAVE_FSI2A_RX,
-+ SHDMA_SLAVE_FSI2B_TX,
-+ SHDMA_SLAVE_FSI2B_RX,
-+ SHDMA_SLAVE_FSI2C_TX,
-+ SHDMA_SLAVE_FSI2C_RX,
-+ SHDMA_SLAVE_FSI2D_RX,
- };
-
- /*
-diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
-index 04a0dfe..2c7bb03 100644
---- a/arch/arm/mach-shmobile/setup-sh73a0.c
-+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
-@@ -651,6 +651,116 @@ static struct platform_device dma0_device = {
- },
- };
-
-+/* MPDMAC */
-+static const struct sh_dmae_slave_config sh73a0_mpdma_slaves[] = {
-+ {
-+ .slave_id = SHDMA_SLAVE_FSI2A_RX,
-+ .addr = 0xec230020,
-+ .chcr = CHCR_RX(XMIT_SZ_32BIT),
-+ .mid_rid = 0xd6, /* CHECK ME */
-+ }, {
-+ .slave_id = SHDMA_SLAVE_FSI2A_TX,
-+ .addr = 0xec230024,
-+ .chcr = CHCR_TX(XMIT_SZ_32BIT),
-+ .mid_rid = 0xd5, /* CHECK ME */
-+ }, {
-+ .slave_id = SHDMA_SLAVE_FSI2C_RX,
-+ .addr = 0xec230060,
-+ .chcr = CHCR_RX(XMIT_SZ_32BIT),
-+ .mid_rid = 0xda, /* CHECK ME */
-+ }, {
-+ .slave_id = SHDMA_SLAVE_FSI2C_TX,
-+ .addr = 0xec230064,
-+ .chcr = CHCR_TX(XMIT_SZ_32BIT),
-+ .mid_rid = 0xd9, /* CHECK ME */
-+ }, {
-+ .slave_id = SHDMA_SLAVE_FSI2B_RX,
-+ .addr = 0xec240020,
-+ .chcr = CHCR_RX(XMIT_SZ_32BIT),
-+ .mid_rid = 0x8e, /* CHECK ME */
-+ }, {
-+ .slave_id = SHDMA_SLAVE_FSI2B_TX,
-+ .addr = 0xec240024,
-+ .chcr = CHCR_RX(XMIT_SZ_32BIT),
-+ .mid_rid = 0x8d, /* CHECK ME */
-+ }, {
-+ .slave_id = SHDMA_SLAVE_FSI2D_RX,
-+ .addr = 0xec240060,
-+ .chcr = CHCR_RX(XMIT_SZ_32BIT),
-+ .mid_rid = 0x9a, /* CHECK ME */
-+ },
-+};
-+
-+#define MPDMA_CHANNEL(a, b, c) \
-+{ \
-+ .offset = a, \
-+ .dmars = b, \
-+ .dmars_bit = c, \
-+ .chclr_offset = (0x220 - 0x20) + a \
-+}
-+
-+static const struct sh_dmae_channel sh73a0_mpdma_channels[] = {
-+ MPDMA_CHANNEL(0x00, 0, 0),
-+ MPDMA_CHANNEL(0x10, 0, 8),
-+ MPDMA_CHANNEL(0x20, 4, 0),
-+ MPDMA_CHANNEL(0x30, 4, 8),
-+ MPDMA_CHANNEL(0x50, 8, 0),
-+ MPDMA_CHANNEL(0x70, 8, 8),
-+};
-+
-+static struct sh_dmae_pdata sh73a0_mpdma_platform_data = {
-+ .slave = sh73a0_mpdma_slaves,
-+ .slave_num = ARRAY_SIZE(sh73a0_mpdma_slaves),
-+ .channel = sh73a0_mpdma_channels,
-+ .channel_num = ARRAY_SIZE(sh73a0_mpdma_channels),
-+ .ts_low_shift = 3,
-+ .ts_low_mask = 0x18,
-+ .ts_high_shift = (20 - 2), /* 2 bits for shifted low TS */
-+ .ts_high_mask = 0x00300000,
-+ .ts_shift = ts_shift,
-+ .ts_shift_num = ARRAY_SIZE(ts_shift),
-+ .dmaor_init = DMAOR_DME,
-+ .chclr_present = 1,
-+};
-+
-+/* Resource order important! */
-+static struct resource sh73a0_mpdma_resources[] = {
-+ {
-+ /* Channel registers and DMAOR */
-+ .start = 0xec618020,
-+ .end = 0xec61828f,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ /* DMARSx */
-+ .start = 0xec619000,
-+ .end = 0xec61900b,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ {
-+ .name = "error_irq",
-+ .start = gic_spi(181),
-+ .end = gic_spi(181),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ {
-+ /* IRQ for channels 0-5 */
-+ .start = gic_spi(175),
-+ .end = gic_spi(180),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device mpdma0_device = {
-+ .name = "sh-dma-engine",
-+ .id = 1,
-+ .resource = sh73a0_mpdma_resources,
-+ .num_resources = ARRAY_SIZE(sh73a0_mpdma_resources),
-+ .dev = {
-+ .platform_data = &sh73a0_mpdma_platform_data,
-+ },
-+};
-+
- static struct platform_device *sh73a0_early_devices[] __initdata = {
- &scif0_device,
- &scif1_device,
-@@ -673,6 +783,7 @@ static struct platform_device *sh73a0_late_devices[] __initdata = {
- &i2c3_device,
- &i2c4_device,
- &dma0_device,
-+ &mpdma0_device,
- };
-
- #define SRCR2 0xe61580b0
---
-1.7.9.5
-
-_______________________________________________
-LTSI-dev mailing list
-LTSI-dev@lists.linuxfoundation.org
-https://lists.linuxfoundation.org/mailman/listinfo/ltsi-dev
-
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Mon Oct 1 01:11:13 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Mon, 1 Oct 2012 17:09:07 +0900
-Subject: [PATCH 03/23] ARM: shmobile: sh73a0: add FSI clock
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, "Rafael J. Wysocki" <rjw@sisk.pl>
-Message-ID: <1349078967-16437-4-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-This patch is required from FSI sound driver
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit ea7e1a5ab569e80f32e849d36918cc3a3dabab1f)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/clock-sh73a0.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
---- a/arch/arm/mach-shmobile/clock-sh73a0.c
-+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
-@@ -477,7 +477,7 @@ enum { MSTP001,
- MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP100,
- MSTP219, MSTP218,
- MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
-- MSTP331, MSTP329, MSTP325, MSTP323,
-+ MSTP331, MSTP329, MSTP328, MSTP325, MSTP323,
- MSTP314, MSTP313, MSTP312, MSTP311,
- MSTP303, MSTP302, MSTP301, MSTP300,
- MSTP411, MSTP410, MSTP403,
-@@ -507,6 +507,7 @@ static struct clk mstp_clks[MSTP_NR] = {
- [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
- [MSTP331] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 31, 0), /* SCIFA6 */
- [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
-+ [MSTP328] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /*FSI*/
- [MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IrDA */
- [MSTP323] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */
- [MSTP314] = MSTP(&div6_clks[DIV6_SDHI0], SMSTPCR3, 14, 0), /* SDHI0 */
-@@ -562,6 +563,7 @@ static struct clk_lookup lookups[] = {
- CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
- CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */
- CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
-+ CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI */
- CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */
- CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */
- CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
+++ /dev/null
-From koba@kmckk.co.jp Mon Oct 1 01:11:25 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Mon, 1 Oct 2012 17:09:10 +0900
-Subject: [PATCH 06/23] ARM: shmobile: sh73a0: add USB clock support
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349078967-16437-7-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-It is required from renesas_usbhs driver.
-This patch is based on v2.0 manual.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 12a7cfef5625ef03c6fdc9bf8a9857dd30d8a11d)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/clock-sh73a0.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
-index ad6f9ad..06ffa4a 100644
---- a/arch/arm/mach-shmobile/clock-sh73a0.c
-+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
-@@ -477,7 +477,7 @@ enum { MSTP001,
- MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP100,
- MSTP219, MSTP218,
- MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
-- MSTP331, MSTP329, MSTP328, MSTP325, MSTP323,
-+ MSTP331, MSTP329, MSTP328, MSTP325, MSTP323, MSTP322,
- MSTP314, MSTP313, MSTP312, MSTP311,
- MSTP303, MSTP302, MSTP301, MSTP300,
- MSTP411, MSTP410, MSTP403,
-@@ -510,6 +510,7 @@ static struct clk mstp_clks[MSTP_NR] = {
- [MSTP328] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /*FSI*/
- [MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IrDA */
- [MSTP323] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */
-+ [MSTP322] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 22, 0), /* USB */
- [MSTP314] = MSTP(&div6_clks[DIV6_SDHI0], SMSTPCR3, 14, 0), /* SDHI0 */
- [MSTP313] = MSTP(&div6_clks[DIV6_SDHI1], SMSTPCR3, 13, 0), /* SDHI1 */
- [MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */
-@@ -566,6 +567,7 @@ static struct clk_lookup lookups[] = {
- CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI */
- CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */
- CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */
-+ CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP322]), /* USB */
- CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
- CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
- CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */
---
-1.7.9.5
-
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Mon Sep 24 22:10:09 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:55 +0900
-Subject: [PATCH 19/21] ARM: shmobile: sh73a0: bugfix: SY-DMAC number
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, "Rafael J. Wysocki" <rjw@sisk.pl>
-Message-ID: <1348549677-1458-20-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-681e1b3eeb3606e06a7c4984e8058df84296f8bb
-(ARM: mach-shmobile: sh73a0 DMA Engine support for SY-DMAC)
-adds SY-DMAC, but it is 218, not 318
-
-This patch is based on v2.0 manual
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 32103c7ba7d274bcb3ace48bc3366e1df37ebb56)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/clock-sh73a0.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
-index 472d1f5..3946c4b 100644
---- a/arch/arm/mach-shmobile/clock-sh73a0.c
-+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
-@@ -475,9 +475,9 @@ static struct clk *late_main_clks[] = {
-
- enum { MSTP001,
- MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP100,
-- MSTP219,
-+ MSTP219, MSTP218,
- MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
-- MSTP331, MSTP329, MSTP325, MSTP323, MSTP318,
-+ MSTP331, MSTP329, MSTP325, MSTP323,
- MSTP314, MSTP313, MSTP312, MSTP311,
- MSTP303, MSTP302, MSTP301, MSTP300,
- MSTP411, MSTP410, MSTP403,
-@@ -497,6 +497,7 @@ static struct clk mstp_clks[MSTP_NR] = {
- [MSTP116] = MSTP(&div4_clks[DIV4_HP], SMSTPCR1, 16, 0), /* IIC0 */
- [MSTP100] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */
- [MSTP219] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 19, 0), /* SCIFA7 */
-+ [MSTP218] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* SY-DMAC */
- [MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */
- [MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */
- [MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */
-@@ -508,7 +509,6 @@ static struct clk mstp_clks[MSTP_NR] = {
- [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
- [MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IrDA */
- [MSTP323] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */
-- [MSTP318] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 18, 0), /* SY-DMAC */
- [MSTP314] = MSTP(&div6_clks[DIV6_SDHI0], SMSTPCR3, 14, 0), /* SDHI0 */
- [MSTP313] = MSTP(&div6_clks[DIV6_SDHI1], SMSTPCR3, 13, 0), /* SDHI1 */
- [MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */
-@@ -552,6 +552,7 @@ static struct clk_lookup lookups[] = {
- CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* I2C0 */
- CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */
- CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP219]), /* SCIFA7 */
-+ CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), /* SY-DMAC */
- CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */
- CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), /* SCIFB */
- CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
-@@ -563,7 +564,6 @@ static struct clk_lookup lookups[] = {
- CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
- CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */
- CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */
-- CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP318]), /* SY-DMAC */
- CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
- CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
- CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */
---
-1.7.9.5
-
-_______________________________________________
-LTSI-dev mailing list
-LTSI-dev@lists.linuxfoundation.org
-https://lists.linuxfoundation.org/mailman/listinfo/ltsi-dev
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Nov 19 00:51:41 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Mon, 19 Nov 2012 17:51:04 +0900
-Subject: [PATCH 2/5] ARM: shmobile: sh73a0: enable PMU(Performance Monitoring Unit)
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Tetsuyuki Kobayashi <koba@kmckk.co.jp>, Simon Horman <horms@verge.net.au>
-Message-ID: <1353315067-7771-3-git-send-email-koba@kmckk.co.jp>
-
-
-This is back port to LTSI 3.4.
-This patch enables PMU(Performance Monitoring Unit) for sh73a0.
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Signed-off-by: Simon Horman <horms@verge.net.au>
-(cherry picked from commit f23f5be0ed87f1c53420086c936385d0a80c7e4d)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/configs/kzm9g_defconfig | 1 +
- arch/arm/mach-shmobile/setup-sh73a0.c | 21 +++++++++++++++++++++
- 2 files changed, 22 insertions(+)
-
-diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig
-index 2388c86..5d0c667 100644
---- a/arch/arm/configs/kzm9g_defconfig
-+++ b/arch/arm/configs/kzm9g_defconfig
-@@ -14,6 +14,7 @@ CONFIG_NAMESPACES=y
- CONFIG_CC_OPTIMIZE_FOR_SIZE=y
- CONFIG_SYSCTL_SYSCALL=y
- CONFIG_EMBEDDED=y
-+CONFIG_PERF_EVENTS=y
- CONFIG_SLAB=y
- CONFIG_MODULES=y
- CONFIG_MODULE_FORCE_LOAD=y
-diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
-index d230af6..38ed2dd 100644
---- a/arch/arm/mach-shmobile/setup-sh73a0.c
-+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
-@@ -734,6 +734,26 @@ static struct platform_device mpdma0_device = {
- },
- };
-
-+static struct resource pmu_resources[] = {
-+ [0] = {
-+ .start = gic_spi(55),
-+ .end = gic_spi(55),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+ [1] = {
-+ .start = gic_spi(56),
-+ .end = gic_spi(56),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device pmu_device = {
-+ .name = "arm-pmu",
-+ .id = -1,
-+ .num_resources = ARRAY_SIZE(pmu_resources),
-+ .resource = pmu_resources,
-+};
-+
- static struct platform_device *sh73a0_early_devices[] __initdata = {
- &scif0_device,
- &scif1_device,
-@@ -757,6 +777,7 @@ static struct platform_device *sh73a0_late_devices[] __initdata = {
- &i2c4_device,
- &dma0_device,
- &mpdma0_device,
-+ &pmu_device,
- };
-
- #define SRCR2 0xe61580b0
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Oct 1 01:13:00 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Mon, 1 Oct 2012 17:09:27 +0900
-Subject: [PATCH 23/23] ARM: shmobile: sh73a0: fixup RELOC_BASE of intca_irq_pins_desc
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349078967-16437-24-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-sh73a0 :: intca_irq_pins_desc irq table had conflict
-from irq 552 to irq 557 before.
-But the second controller was simply trampling the
-first one by way of the -EEXIST case from irq_alloc_desc_at().
-
-But now, we have irqdomain support from
-1d6a21b0a672fb29b01ccf397d478e0541e17716
-(sh: intc: initial irqdomain support)
-
-The irqdomain code has simply tightened down the sanity checks and
-error path. So, sh73a0 CPU board got some WARNING when booting now.
-This patch fixup RELOC_BASE to solve this issue.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 6c0274cbe63ec265f842537825684a619e6cce93)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/intc-sh73a0.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c
-index ee44740..588555a 100644
---- a/arch/arm/mach-shmobile/intc-sh73a0.c
-+++ b/arch/arm/mach-shmobile/intc-sh73a0.c
-@@ -259,9 +259,9 @@ static int sh73a0_set_wake(struct irq_data *data, unsigned int on)
- return 0; /* always allow wakeup */
- }
-
--#define RELOC_BASE 0x1000
-+#define RELOC_BASE 0x1200
-
--/* INTCA IRQ pins at INTCS + 0x1000 to make space for GIC+INTC handling */
-+/* INTCA IRQ pins at INTCS + RELOC_BASE to make space for GIC+INTC handling */
- #define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE)
-
- INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
---
-1.7.9.5
-
+++ /dev/null
-From koba@kmckk.co.jp Mon Oct 1 01:12:54 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Mon, 1 Oct 2012 17:09:24 +0900
-Subject: [PATCH 20/23] ARM: shmobile: use common DMAEngine definitions on sh73a0
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1349078967-16437-21-git-send-email-koba@kmckk.co.jp>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-This patch switch over to use common DMAEngine definitions,
-and reduced a waste of code.
-
-It is easy to understand if sh_dmae_pdata / sh_dmae_slave_config
-settings are used defined value instead of direct value.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 6088b422706af496d72065e8c539929f2d4a7e8b)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/mach-shmobile/setup-sh73a0.c | 53 ++++++++--------------------------
- 1 file changed, 13 insertions(+), 40 deletions(-)
-
---- a/arch/arm/mach-shmobile/setup-sh73a0.c
-+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
-@@ -30,6 +30,7 @@
- #include <linux/sh_dma.h>
- #include <linux/sh_intc.h>
- #include <linux/sh_timer.h>
-+#include <mach/dma-register.h>
- #include <mach/hardware.h>
- #include <mach/irqs.h>
- #include <mach/sh73a0.h>
-@@ -415,32 +416,6 @@ static struct platform_device i2c4_devic
- .num_resources = ARRAY_SIZE(i2c4_resources),
- };
-
--/* Transmit sizes and respective CHCR register values */
--enum {
-- XMIT_SZ_8BIT = 0,
-- XMIT_SZ_16BIT = 1,
-- XMIT_SZ_32BIT = 2,
-- XMIT_SZ_64BIT = 7,
-- XMIT_SZ_128BIT = 3,
-- XMIT_SZ_256BIT = 4,
-- XMIT_SZ_512BIT = 5,
--};
--
--/* log2(size / 8) - used to calculate number of transfers */
--#define TS_SHIFT { \
-- [XMIT_SZ_8BIT] = 0, \
-- [XMIT_SZ_16BIT] = 1, \
-- [XMIT_SZ_32BIT] = 2, \
-- [XMIT_SZ_64BIT] = 3, \
-- [XMIT_SZ_128BIT] = 4, \
-- [XMIT_SZ_256BIT] = 5, \
-- [XMIT_SZ_512BIT] = 6, \
--}
--
--#define TS_INDEX2VAL(i) ((((i) & 3) << 3) | (((i) & 0xc) << (20 - 2)))
--#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz)))
--#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz)))
--
- static const struct sh_dmae_slave_config sh73a0_dmae_slaves[] = {
- {
- .slave_id = SHDMA_SLAVE_SCIF0_TX,
-@@ -604,19 +579,17 @@ static const struct sh_dmae_channel sh73
- DMAE_CHANNEL(0x8980),
- };
-
--static const unsigned int ts_shift[] = TS_SHIFT;
--
- static struct sh_dmae_pdata sh73a0_dmae_platform_data = {
- .slave = sh73a0_dmae_slaves,
- .slave_num = ARRAY_SIZE(sh73a0_dmae_slaves),
- .channel = sh73a0_dmae_channels,
- .channel_num = ARRAY_SIZE(sh73a0_dmae_channels),
-- .ts_low_shift = 3,
-- .ts_low_mask = 0x18,
-- .ts_high_shift = (20 - 2), /* 2 bits for shifted low TS */
-- .ts_high_mask = 0x00300000,
-- .ts_shift = ts_shift,
-- .ts_shift_num = ARRAY_SIZE(ts_shift),
-+ .ts_low_shift = TS_LOW_SHIFT,
-+ .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT,
-+ .ts_high_shift = TS_HI_SHIFT,
-+ .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT,
-+ .ts_shift = dma_ts_shift,
-+ .ts_shift_num = ARRAY_SIZE(dma_ts_shift),
- .dmaor_init = DMAOR_DME,
- };
-
-@@ -713,12 +686,12 @@ static struct sh_dmae_pdata sh73a0_mpdma
- .slave_num = ARRAY_SIZE(sh73a0_mpdma_slaves),
- .channel = sh73a0_mpdma_channels,
- .channel_num = ARRAY_SIZE(sh73a0_mpdma_channels),
-- .ts_low_shift = 3,
-- .ts_low_mask = 0x18,
-- .ts_high_shift = (20 - 2), /* 2 bits for shifted low TS */
-- .ts_high_mask = 0x00300000,
-- .ts_shift = ts_shift,
-- .ts_shift_num = ARRAY_SIZE(ts_shift),
-+ .ts_low_shift = TS_LOW_SHIFT,
-+ .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT,
-+ .ts_high_shift = TS_HI_SHIFT,
-+ .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT,
-+ .ts_shift = dma_ts_shift,
-+ .ts_shift_num = ARRAY_SIZE(dma_ts_shift),
- .dmaor_init = DMAOR_DME,
- .chclr_present = 1,
- };
+++ /dev/null
-From koba@kmckk.co.jp Mon Sep 24 22:08:53 2012
-From: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Date: Tue, 25 Sep 2012 14:07:37 +0900
-Subject: [PATCH 01/21] ARM: Update mach-types
-To: greg@kroah.com
-Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, kuninori.morimoto.gx@renesas.com, Russell King <rmk+kernel@arm.linux.org.uk>, Tetsuyuki Kobayashi <koba@kmckk.co.jp>
-Message-ID: <1348549677-1458-2-git-send-email-koba@kmckk.co.jp>
-
-
-From: Russell King <rmk+kernel@arm.linux.org.uk>
-
-Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-(cherry picked from commit d098bc7d58ebda22a6554b6c9df1056802d9900f)
-
-Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp>
----
- arch/arm/tools/mach-types | 505 ++++++++++++++++++++++++---------------------
- 1 file changed, 271 insertions(+), 234 deletions(-)
-
-diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
-index f9c9f33..2997e56 100644
---- a/arch/arm/tools/mach-types
-+++ b/arch/arm/tools/mach-types
-@@ -16,7 +16,7 @@
- # are merged into mainline or have been edited in the machine database
- # within the last 12 months. References to machine_is_NAME() do not count!
- #
--# Last update: Tue Dec 6 11:07:38 2011
-+# Last update: Thu Apr 26 08:44:23 2012
- #
- # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
- #
-@@ -205,6 +205,7 @@ omap_fsample MACH_OMAP_FSAMPLE OMAP_FSAMPLE 970
- snapper_cl15 MACH_SNAPPER_CL15 SNAPPER_CL15 986
- omap_palmz71 MACH_OMAP_PALMZ71 OMAP_PALMZ71 993
- smdk2412 MACH_SMDK2412 SMDK2412 1009
-+bkde303 MACH_BKDE303 BKDE303 1021
- smdk2413 MACH_SMDK2413 SMDK2413 1022
- aml_m5900 MACH_AML_M5900 AML_M5900 1024
- balloon3 MACH_BALLOON3 BALLOON3 1029
-@@ -381,8 +382,6 @@ davinci_da850_evm MACH_DAVINCI_DA850_EVM DAVINCI_DA850_EVM 2157
- at91sam9g10ek MACH_AT91SAM9G10EK AT91SAM9G10EK 2159
- omap_4430sdp MACH_OMAP_4430SDP OMAP_4430SDP 2160
- magx_zn5 MACH_MAGX_ZN5 MAGX_ZN5 2162
--btmavb101 MACH_BTMAVB101 BTMAVB101 2172
--btmawb101 MACH_BTMAWB101 BTMAWB101 2173
- tx25 MACH_TX25 TX25 2177
- omap3_torpedo MACH_OMAP3_TORPEDO OMAP3_TORPEDO 2178
- anw6410 MACH_ANW6410 ANW6410 2183
-@@ -397,7 +396,6 @@ net2big_v2 MACH_NET2BIG_V2 NET2BIG_V2 2204
- net5big_v2 MACH_NET5BIG_V2 NET5BIG_V2 2206
- inetspace_v2 MACH_INETSPACE_V2 INETSPACE_V2 2208
- at91sam9g45ekes MACH_AT91SAM9G45EKES AT91SAM9G45EKES 2212
--pc7302 MACH_PC7302 PC7302 2220
- spear600 MACH_SPEAR600 SPEAR600 2236
- spear300 MACH_SPEAR300 SPEAR300 2237
- lilly1131 MACH_LILLY1131 LILLY1131 2239
-@@ -407,7 +405,6 @@ d2net MACH_D2NET D2NET 2282
- bigdisk MACH_BIGDISK BIGDISK 2283
- at91sam9g20ek_2mmc MACH_AT91SAM9G20EK_2MMC AT91SAM9G20EK_2MMC 2288
- bcmring MACH_BCMRING BCMRING 2289
--dp6xx MACH_DP6XX DP6XX 2302
- mahimahi MACH_MAHIMAHI MAHIMAHI 2304
- smdk6442 MACH_SMDK6442 SMDK6442 2324
- openrd_base MACH_OPENRD_BASE OPENRD_BASE 2325
-@@ -444,8 +441,6 @@ mx28evk MACH_MX28EVK MX28EVK 2531
- smartq5 MACH_SMARTQ5 SMARTQ5 2534
- davinci_dm6467tevm MACH_DAVINCI_DM6467TEVM DAVINCI_DM6467TEVM 2548
- mxt_td60 MACH_MXT_TD60 MXT_TD60 2550
--riot_bei2 MACH_RIOT_BEI2 RIOT_BEI2 2576
--riot_x37 MACH_RIOT_X37 RIOT_X37 2578
- pca101 MACH_PCA101 PCA101 2595
- capc7117 MACH_CAPC7117 CAPC7117 2612
- icontrol MACH_ICONTROL ICONTROL 2624
-@@ -460,7 +455,6 @@ spear320 MACH_SPEAR320 SPEAR320 2661
- aquila MACH_AQUILA AQUILA 2676
- esata_sheevaplug MACH_ESATA_SHEEVAPLUG ESATA_SHEEVAPLUG 2678
- msm7x30_surf MACH_MSM7X30_SURF MSM7X30_SURF 2679
--ea2478devkit MACH_EA2478DEVKIT EA2478DEVKIT 2683
- terastation_wxl MACH_TERASTATION_WXL TERASTATION_WXL 2697
- msm7x25_surf MACH_MSM7X25_SURF MSM7X25_SURF 2703
- msm7x25_ffa MACH_MSM7X25_FFA MSM7X25_FFA 2704
-@@ -479,8 +473,6 @@ wbd222 MACH_WBD222 WBD222 2753
- msm8x60_surf MACH_MSM8X60_SURF MSM8X60_SURF 2755
- msm8x60_sim MACH_MSM8X60_SIM MSM8X60_SIM 2756
- tcc8000_sdk MACH_TCC8000_SDK TCC8000_SDK 2758
--nanos MACH_NANOS NANOS 2759
--stamp9g45 MACH_STAMP9G45 STAMP9G45 2761
- cns3420vb MACH_CNS3420VB CNS3420VB 2776
- omap4_panda MACH_OMAP4_PANDA OMAP4_PANDA 2791
- ti8168evm MACH_TI8168EVM TI8168EVM 2800
-@@ -490,12 +482,9 @@ eukrea_cpuimx35sd MACH_EUKREA_CPUIMX35SD EUKREA_CPUIMX35SD 2821
- eukrea_cpuimx51sd MACH_EUKREA_CPUIMX51SD EUKREA_CPUIMX51SD 2822
- eukrea_cpuimx51 MACH_EUKREA_CPUIMX51 EUKREA_CPUIMX51 2823
- smdkc210 MACH_SMDKC210 SMDKC210 2838
--pca102 MACH_PCA102 PCA102 2843
-+pcaal1 MACH_PCAAL1 PCAAL1 2843
- t5325 MACH_T5325 T5325 2846
- income MACH_INCOME INCOME 2849
--vvbox_sdorig2 MACH_VVBOX_SDORIG2 VVBOX_SDORIG2 2857
--vvbox_sdlite2 MACH_VVBOX_SDLITE2 VVBOX_SDLITE2 2858
--vvbox_sdpro4 MACH_VVBOX_SDPRO4 VVBOX_SDPRO4 2859
- mx257sx MACH_MX257SX MX257SX 2861
- goni MACH_GONI GONI 2862
- bv07 MACH_BV07 BV07 2882
-@@ -504,6 +493,7 @@ devixp MACH_DEVIXP DEVIXP 2885
- miccpt MACH_MICCPT MICCPT 2886
- mic256 MACH_MIC256 MIC256 2887
- u5500 MACH_U5500 U5500 2890
-+pov15hd MACH_POV15HD POV15HD 2910
- linkstation_lschl MACH_LINKSTATION_LSCHL LINKSTATION_LSCHL 2913
- smdkv310 MACH_SMDKV310 SMDKV310 2925
- wm8505_7in_netbook MACH_WM8505_7IN_NETBOOK WM8505_7IN_NETBOOK 2928
-@@ -537,243 +527,24 @@ trimslice MACH_TRIMSLICE TRIMSLICE 3209
- mackerel MACH_MACKEREL MACKEREL 3211
- kaen MACH_KAEN KAEN 3217
- nokia_rm680 MACH_NOKIA_RM680 NOKIA_RM680 3220
--dm6446_adbox MACH_DM6446_ADBOX DM6446_ADBOX 3226
--quad_salsa MACH_QUAD_SALSA QUAD_SALSA 3227
--abb_gma_1_1 MACH_ABB_GMA_1_1 ABB_GMA_1_1 3228
--svcid MACH_SVCID SVCID 3229
- msm8960_sim MACH_MSM8960_SIM MSM8960_SIM 3230
- msm8960_rumi3 MACH_MSM8960_RUMI3 MSM8960_RUMI3 3231
--icon_g MACH_ICON_G ICON_G 3232
--mb3 MACH_MB3 MB3 3233
- gsia18s MACH_GSIA18S GSIA18S 3234
--pivicc MACH_PIVICC PIVICC 3235
--pcm048 MACH_PCM048 PCM048 3236
--dds MACH_DDS DDS 3237
--chalten_xa1 MACH_CHALTEN_XA1 CHALTEN_XA1 3238
--ts48xx MACH_TS48XX TS48XX 3239
--tonga2_tfttimer MACH_TONGA2_TFTTIMER TONGA2_TFTTIMER 3240
--whistler MACH_WHISTLER WHISTLER 3241
--asl_phoenix MACH_ASL_PHOENIX ASL_PHOENIX 3242
--at91sam9263otlite MACH_AT91SAM9263OTLITE AT91SAM9263OTLITE 3243
--ddplug MACH_DDPLUG DDPLUG 3244
--d2plug MACH_D2PLUG D2PLUG 3245
--kzm9d MACH_KZM9D KZM9D 3246
--verdi_lte MACH_VERDI_LTE VERDI_LTE 3247
--nanozoom MACH_NANOZOOM NANOZOOM 3248
--dm3730_som_lv MACH_DM3730_SOM_LV DM3730_SOM_LV 3249
--dm3730_torpedo MACH_DM3730_TORPEDO DM3730_TORPEDO 3250
--anchovy MACH_ANCHOVY ANCHOVY 3251
--re2rev20 MACH_RE2REV20 RE2REV20 3253
--re2rev21 MACH_RE2REV21 RE2REV21 3254
--cns21xx MACH_CNS21XX CNS21XX 3255
--rider MACH_RIDER RIDER 3257
--nsk330 MACH_NSK330 NSK330 3258
--cns2133evb MACH_CNS2133EVB CNS2133EVB 3259
--z3_816x_mod MACH_Z3_816X_MOD Z3_816X_MOD 3260
--z3_814x_mod MACH_Z3_814X_MOD Z3_814X_MOD 3261
--beect MACH_BEECT BEECT 3262
--dma_thunderbug MACH_DMA_THUNDERBUG DMA_THUNDERBUG 3263
--omn_at91sam9g20 MACH_OMN_AT91SAM9G20 OMN_AT91SAM9G20 3264
--mx25_e2s_uc MACH_MX25_E2S_UC MX25_E2S_UC 3265
--mione MACH_MIONE MIONE 3266
--top9000_tcu MACH_TOP9000_TCU TOP9000_TCU 3267
--top9000_bsl MACH_TOP9000_BSL TOP9000_BSL 3268
--kingdom MACH_KINGDOM KINGDOM 3269
--armadillo460 MACH_ARMADILLO460 ARMADILLO460 3270
--lq2 MACH_LQ2 LQ2 3271
--sweda_tms2 MACH_SWEDA_TMS2 SWEDA_TMS2 3272
- mx53_loco MACH_MX53_LOCO MX53_LOCO 3273
--acer_a8 MACH_ACER_A8 ACER_A8 3275
--acer_gauguin MACH_ACER_GAUGUIN ACER_GAUGUIN 3276
--guppy MACH_GUPPY GUPPY 3277
--mx61_ard MACH_MX61_ARD MX61_ARD 3278
- tx53 MACH_TX53 TX53 3279
--omapl138_case_a3 MACH_OMAPL138_CASE_A3 OMAPL138_CASE_A3 3280
--uemd MACH_UEMD UEMD 3281
--ccwmx51mut MACH_CCWMX51MUT CCWMX51MUT 3282
--rockhopper MACH_ROCKHOPPER ROCKHOPPER 3283
- encore MACH_ENCORE ENCORE 3284
--hkdkc100 MACH_HKDKC100 HKDKC100 3285
--ts42xx MACH_TS42XX TS42XX 3286
--aebl MACH_AEBL AEBL 3287
- wario MACH_WARIO WARIO 3288
--gfs_spm MACH_GFS_SPM GFS_SPM 3289
- cm_t3730 MACH_CM_T3730 CM_T3730 3290
--isc3 MACH_ISC3 ISC3 3291
--rascal MACH_RASCAL RASCAL 3292
- hrefv60 MACH_HREFV60 HREFV60 3293
--tpt_2_0 MACH_TPT_2_0 TPT_2_0 3294
--splendor MACH_SPLENDOR SPLENDOR 3296
--msm8x60_qt MACH_MSM8X60_QT MSM8X60_QT 3298
--htc_hd_mini MACH_HTC_HD_MINI HTC_HD_MINI 3299
--athene MACH_ATHENE ATHENE 3300
--deep_r_ek_1 MACH_DEEP_R_EK_1 DEEP_R_EK_1 3301
--vivow_ct MACH_VIVOW_CT VIVOW_CT 3302
--nery_1000 MACH_NERY_1000 NERY_1000 3303
--rfl109145_ssrv MACH_RFL109145_SSRV RFL109145_SSRV 3304
--nmh MACH_NMH NMH 3305
--wn802t MACH_WN802T WN802T 3306
--dragonet MACH_DRAGONET DRAGONET 3307
--at91sam9263desk16l MACH_AT91SAM9263DESK16L AT91SAM9263DESK16L 3309
--bcmhana_sv MACH_BCMHANA_SV BCMHANA_SV 3310
--bcmhana_tablet MACH_BCMHANA_TABLET BCMHANA_TABLET 3311
--koi MACH_KOI KOI 3312
--ts4800 MACH_TS4800 TS4800 3313
--tqma9263 MACH_TQMA9263 TQMA9263 3314
--holiday MACH_HOLIDAY HOLIDAY 3315
--pcats_overlay MACH_PCATS_OVERLAY PCATS_OVERLAY 3317
--hwgw6410 MACH_HWGW6410 HWGW6410 3318
--shenzhou MACH_SHENZHOU SHENZHOU 3319
--cwme9210 MACH_CWME9210 CWME9210 3320
--cwme9210js MACH_CWME9210JS CWME9210JS 3321
--colibri_tegra2 MACH_COLIBRI_TEGRA2 COLIBRI_TEGRA2 3323
--w21 MACH_W21 W21 3324
--polysat1 MACH_POLYSAT1 POLYSAT1 3325
--dataway MACH_DATAWAY DATAWAY 3326
--cobral138 MACH_COBRAL138 COBRAL138 3327
--roverpcs8 MACH_ROVERPCS8 ROVERPCS8 3328
--marvelc MACH_MARVELC MARVELC 3329
--navefihid MACH_NAVEFIHID NAVEFIHID 3330
--dm365_cv100 MACH_DM365_CV100 DM365_CV100 3331
--able MACH_ABLE ABLE 3332
--legacy MACH_LEGACY LEGACY 3333
--icong MACH_ICONG ICONG 3334
--rover_g8 MACH_ROVER_G8 ROVER_G8 3335
--t5388p MACH_T5388P T5388P 3336
--dingo MACH_DINGO DINGO 3337
--goflexhome MACH_GOFLEXHOME GOFLEXHOME 3338
--lanreadyfn511 MACH_LANREADYFN511 LANREADYFN511 3340
--omap3_baia MACH_OMAP3_BAIA OMAP3_BAIA 3341
--omap3smartdisplay MACH_OMAP3SMARTDISPLAY OMAP3SMARTDISPLAY 3342
--xilinx MACH_XILINX XILINX 3343
--a2f MACH_A2F A2F 3344
--sky25 MACH_SKY25 SKY25 3345
--ccmx53 MACH_CCMX53 CCMX53 3346
--ccmx53js MACH_CCMX53JS CCMX53JS 3347
--ccwmx53 MACH_CCWMX53 CCWMX53 3348
--ccwmx53js MACH_CCWMX53JS CCWMX53JS 3349
--frisms MACH_FRISMS FRISMS 3350
--msm7x27a_ffa MACH_MSM7X27A_FFA MSM7X27A_FFA 3351
--msm7x27a_surf MACH_MSM7X27A_SURF MSM7X27A_SURF 3352
--msm7x27a_rumi3 MACH_MSM7X27A_RUMI3 MSM7X27A_RUMI3 3353
--dimmsam9g20 MACH_DIMMSAM9G20 DIMMSAM9G20 3354
--dimm_imx28 MACH_DIMM_IMX28 DIMM_IMX28 3355
--amk_a4 MACH_AMK_A4 AMK_A4 3356
--gnet_sgme MACH_GNET_SGME GNET_SGME 3357
--shooter_u MACH_SHOOTER_U SHOOTER_U 3358
--vmx53 MACH_VMX53 VMX53 3359
--rhino MACH_RHINO RHINO 3360
- armlex4210 MACH_ARMLEX4210 ARMLEX4210 3361
--swarcoextmodem MACH_SWARCOEXTMODEM SWARCOEXTMODEM 3362
- snowball MACH_SNOWBALL SNOWBALL 3363
--pcm049 MACH_PCM049 PCM049 3364
--vigor MACH_VIGOR VIGOR 3365
--oslo_amundsen MACH_OSLO_AMUNDSEN OSLO_AMUNDSEN 3366
--gsl_diamond MACH_GSL_DIAMOND GSL_DIAMOND 3367
--cv2201 MACH_CV2201 CV2201 3368
--cv2202 MACH_CV2202 CV2202 3369
--cv2203 MACH_CV2203 CV2203 3370
--vit_ibox MACH_VIT_IBOX VIT_IBOX 3371
--dm6441_esp MACH_DM6441_ESP DM6441_ESP 3372
--at91sam9x5ek MACH_AT91SAM9X5EK AT91SAM9X5EK 3373
--libra MACH_LIBRA LIBRA 3374
--easycrrh MACH_EASYCRRH EASYCRRH 3375
--tripel MACH_TRIPEL TRIPEL 3376
--endian_mini MACH_ENDIAN_MINI ENDIAN_MINI 3377
- xilinx_ep107 MACH_XILINX_EP107 XILINX_EP107 3378
- nuri MACH_NURI NURI 3379
--janus MACH_JANUS JANUS 3380
--ddnas MACH_DDNAS DDNAS 3381
--tag MACH_TAG TAG 3382
--tagw MACH_TAGW TAGW 3383
--nitrogen_vm_imx51 MACH_NITROGEN_VM_IMX51 NITROGEN_VM_IMX51 3384
--viprinet MACH_VIPRINET VIPRINET 3385
--bockw MACH_BOCKW BOCKW 3386
--eva2000 MACH_EVA2000 EVA2000 3387
--steelyard MACH_STEELYARD STEELYARD 3388
--nsslsboard MACH_NSSLSBOARD NSSLSBOARD 3392
--geneva_b5 MACH_GENEVA_B5 GENEVA_B5 3393
--spear1340 MACH_SPEAR1340 SPEAR1340 3394
--rexmas MACH_REXMAS REXMAS 3395
--msm8960_cdp MACH_MSM8960_CDP MSM8960_CDP 3396
--msm8960_fluid MACH_MSM8960_FLUID MSM8960_FLUID 3398
--msm8960_apq MACH_MSM8960_APQ MSM8960_APQ 3399
--helios_v2 MACH_HELIOS_V2 HELIOS_V2 3400
--mif10p MACH_MIF10P MIF10P 3401
--iam28 MACH_IAM28 IAM28 3402
--picasso MACH_PICASSO PICASSO 3403
--mr301a MACH_MR301A MR301A 3404
--notle MACH_NOTLE NOTLE 3405
--eelx2 MACH_EELX2 EELX2 3406
--moon MACH_MOON MOON 3407
--ruby MACH_RUBY RUBY 3408
--goldengate MACH_GOLDENGATE GOLDENGATE 3409
--ctbu_gen2 MACH_CTBU_GEN2 CTBU_GEN2 3410
--kmp_am17_01 MACH_KMP_AM17_01 KMP_AM17_01 3411
- wtplug MACH_WTPLUG WTPLUG 3412
--mx27su2 MACH_MX27SU2 MX27SU2 3413
--nb31 MACH_NB31 NB31 3414
--hjsdu MACH_HJSDU HJSDU 3415
--td3_rev1 MACH_TD3_REV1 TD3_REV1 3416
--eag_ci4000 MACH_EAG_CI4000 EAG_CI4000 3417
--net5big_nand_v2 MACH_NET5BIG_NAND_V2 NET5BIG_NAND_V2 3418
--cpx2 MACH_CPX2 CPX2 3419
--net2big_nand_v2 MACH_NET2BIG_NAND_V2 NET2BIG_NAND_V2 3420
--ecuv5 MACH_ECUV5 ECUV5 3421
--hsgx6d MACH_HSGX6D HSGX6D 3422
--dawad7 MACH_DAWAD7 DAWAD7 3423
--sam9repeater MACH_SAM9REPEATER SAM9REPEATER 3424
--gt_i5700 MACH_GT_I5700 GT_I5700 3425
--ctera_plug_c2 MACH_CTERA_PLUG_C2 CTERA_PLUG_C2 3426
--marvelct MACH_MARVELCT MARVELCT 3427
--ag11005 MACH_AG11005 AG11005 3428
--vangogh MACH_VANGOGH VANGOGH 3430
--matrix505 MACH_MATRIX505 MATRIX505 3431
--oce_nigma MACH_OCE_NIGMA OCE_NIGMA 3432
--t55 MACH_T55 T55 3433
--bio3k MACH_BIO3K BIO3K 3434
--expressct MACH_EXPRESSCT EXPRESSCT 3435
--cardhu MACH_CARDHU CARDHU 3436
--aruba MACH_ARUBA ARUBA 3437
--bonaire MACH_BONAIRE BONAIRE 3438
--nuc700evb MACH_NUC700EVB NUC700EVB 3439
--nuc710evb MACH_NUC710EVB NUC710EVB 3440
--nuc740evb MACH_NUC740EVB NUC740EVB 3441
--nuc745evb MACH_NUC745EVB NUC745EVB 3442
--transcede MACH_TRANSCEDE TRANSCEDE 3443
--mora MACH_MORA MORA 3444
--nda_evm MACH_NDA_EVM NDA_EVM 3445
--timu MACH_TIMU TIMU 3446
--expressh MACH_EXPRESSH EXPRESSH 3447
- veridis_a300 MACH_VERIDIS_A300 VERIDIS_A300 3448
--dm368_leopard MACH_DM368_LEOPARD DM368_LEOPARD 3449
--omap_mcop MACH_OMAP_MCOP OMAP_MCOP 3450
--tritip MACH_TRITIP TRITIP 3451
--sm1k MACH_SM1K SM1K 3452
--monch MACH_MONCH MONCH 3453
--curacao MACH_CURACAO CURACAO 3454
- origen MACH_ORIGEN ORIGEN 3455
--epc10 MACH_EPC10 EPC10 3456
--sgh_i740 MACH_SGH_I740 SGH_I740 3457
--tuna MACH_TUNA TUNA 3458
--mx51_tulip MACH_MX51_TULIP MX51_TULIP 3459
--mx51_aster7 MACH_MX51_ASTER7 MX51_ASTER7 3460
--acro37xbrd MACH_ACRO37XBRD ACRO37XBRD 3461
--elke MACH_ELKE ELKE 3462
--sbc6000x MACH_SBC6000X SBC6000X 3463
--r1801e MACH_R1801E R1801E 3464
--h1600 MACH_H1600 H1600 3465
--mini210 MACH_MINI210 MINI210 3466
--mini8168 MACH_MINI8168 MINI8168 3467
--pc7308 MACH_PC7308 PC7308 3468
--kmm2m01 MACH_KMM2M01 KMM2M01 3470
--mx51erebus MACH_MX51EREBUS MX51EREBUS 3471
- wm8650refboard MACH_WM8650REFBOARD WM8650REFBOARD 3472
--tuxrail MACH_TUXRAIL TUXRAIL 3473
--arthur MACH_ARTHUR ARTHUR 3474
--doorboy MACH_DOORBOY DOORBOY 3475
- xarina MACH_XARINA XARINA 3476
--roverx7 MACH_ROVERX7 ROVERX7 3477
- sdvr MACH_SDVR SDVR 3478
- acer_maya MACH_ACER_MAYA ACER_MAYA 3479
- pico MACH_PICO PICO 3480
-@@ -999,6 +770,7 @@ promwad_jade MACH_PROMWAD_JADE PROMWAD_JADE 3708
- amp MACH_AMP AMP 3709
- gnet_amp MACH_GNET_AMP GNET_AMP 3710
- toques MACH_TOQUES TOQUES 3711
-+apx4devkit MACH_APX4DEVKIT APX4DEVKIT 3712
- dct_storm MACH_DCT_STORM DCT_STORM 3713
- owl MACH_OWL OWL 3715
- cogent_csb1741 MACH_COGENT_CSB1741 COGENT_CSB1741 3716
-@@ -1063,7 +835,6 @@ shelter MACH_SHELTER SHELTER 3778
- omap3_devkit8500 MACH_OMAP3_DEVKIT8500 OMAP3_DEVKIT8500 3779
- edgetd MACH_EDGETD EDGETD 3780
- copperyard MACH_COPPERYARD COPPERYARD 3781
--edge MACH_EDGE EDGE 3782
- edge_u MACH_EDGE_U EDGE_U 3783
- edge_td MACH_EDGE_TD EDGE_TD 3784
- wdss MACH_WDSS WDSS 3785
-@@ -1169,3 +940,269 @@ elite_ulk MACH_ELITE_ULK ELITE_ULK 3888
- pov2 MACH_POV2 POV2 3889
- ipod_touch_2g MACH_IPOD_TOUCH_2G IPOD_TOUCH_2G 3890
- da850_pqab MACH_DA850_PQAB DA850_PQAB 3891
-+fermi MACH_FERMI FERMI 3892
-+ccardwmx28 MACH_CCARDWMX28 CCARDWMX28 3893
-+ccardmx28 MACH_CCARDMX28 CCARDMX28 3894
-+fs20_fcm2050 MACH_FS20_FCM2050 FS20_FCM2050 3895
-+kinetis MACH_KINETIS KINETIS 3896
-+kai MACH_KAI KAI 3897
-+bcthb2 MACH_BCTHB2 BCTHB2 3898
-+inels3_cu MACH_INELS3_CU INELS3_CU 3899
-+da850_apollo MACH_DA850_APOLLO DA850_APOLLO 3901
-+tracnas MACH_TRACNAS TRACNAS 3902
-+mityarm335x MACH_MITYARM335X MITYARM335X 3903
-+xcgz7x MACH_XCGZ7X XCGZ7X 3904
-+cubox MACH_CUBOX CUBOX 3905
-+terminator MACH_TERMINATOR TERMINATOR 3906
-+eye03 MACH_EYE03 EYE03 3907
-+kota3 MACH_KOTA3 KOTA3 3908
-+pscpe MACH_PSCPE PSCPE 3910
-+akt1100 MACH_AKT1100 AKT1100 3911
-+pcaaxl2 MACH_PCAAXL2 PCAAXL2 3912
-+primodd_ct MACH_PRIMODD_CT PRIMODD_CT 3913
-+nsbc MACH_NSBC NSBC 3914
-+meson2_skt MACH_MESON2_SKT MESON2_SKT 3915
-+meson2_ref MACH_MESON2_REF MESON2_REF 3916
-+ccardwmx28js MACH_CCARDWMX28JS CCARDWMX28JS 3917
-+ccardmx28js MACH_CCARDMX28JS CCARDMX28JS 3918
-+indico MACH_INDICO INDICO 3919
-+msm8960dt MACH_MSM8960DT MSM8960DT 3920
-+primods MACH_PRIMODS PRIMODS 3921
-+beluga_m1388 MACH_BELUGA_M1388 BELUGA_M1388 3922
-+primotd MACH_PRIMOTD PRIMOTD 3923
-+varan_master MACH_VARAN_MASTER VARAN_MASTER 3924
-+primodd MACH_PRIMODD PRIMODD 3925
-+jetduo MACH_JETDUO JETDUO 3926
-+mx53_umobo MACH_MX53_UMOBO MX53_UMOBO 3927
-+trats MACH_TRATS TRATS 3928
-+starcraft MACH_STARCRAFT STARCRAFT 3929
-+qseven_tegra2 MACH_QSEVEN_TEGRA2 QSEVEN_TEGRA2 3930
-+lichee_sun4i_devbd MACH_LICHEE_SUN4I_DEVBD LICHEE_SUN4I_DEVBD 3931
-+movenow MACH_MOVENOW MOVENOW 3932
-+golf_u MACH_GOLF_U GOLF_U 3933
-+msm7627a_evb MACH_MSM7627A_EVB MSM7627A_EVB 3934
-+rambo MACH_RAMBO RAMBO 3935
-+golfu MACH_GOLFU GOLFU 3936
-+mango310 MACH_MANGO310 MANGO310 3937
-+dns343 MACH_DNS343 DNS343 3938
-+var_som_om44 MACH_VAR_SOM_OM44 VAR_SOM_OM44 3939
-+naon MACH_NAON NAON 3940
-+vp4000 MACH_VP4000 VP4000 3941
-+impcard MACH_IMPCARD IMPCARD 3942
-+smoovcam MACH_SMOOVCAM SMOOVCAM 3943
-+cobham3725 MACH_COBHAM3725 COBHAM3725 3944
-+cobham3730 MACH_COBHAM3730 COBHAM3730 3945
-+cobham3703 MACH_COBHAM3703 COBHAM3703 3946
-+quetzal MACH_QUETZAL QUETZAL 3947
-+apq8064_cdp MACH_APQ8064_CDP APQ8064_CDP 3948
-+apq8064_mtp MACH_APQ8064_MTP APQ8064_MTP 3949
-+apq8064_fluid MACH_APQ8064_FLUID APQ8064_FLUID 3950
-+apq8064_liquid MACH_APQ8064_LIQUID APQ8064_LIQUID 3951
-+mango210 MACH_MANGO210 MANGO210 3952
-+mango100 MACH_MANGO100 MANGO100 3953
-+mango24 MACH_MANGO24 MANGO24 3954
-+mango64 MACH_MANGO64 MANGO64 3955
-+nsa320 MACH_NSA320 NSA320 3956
-+elv_ccu2 MACH_ELV_CCU2 ELV_CCU2 3957
-+triton_x00 MACH_TRITON_X00 TRITON_X00 3958
-+triton_1500_2000 MACH_TRITON_1500_2000 TRITON_1500_2000 3959
-+pogoplugv4 MACH_POGOPLUGV4 POGOPLUGV4 3960
-+venus_cl MACH_VENUS_CL VENUS_CL 3961
-+vulcano_g20 MACH_VULCANO_G20 VULCANO_G20 3962
-+sgs_i9100 MACH_SGS_I9100 SGS_I9100 3963
-+stsv2 MACH_STSV2 STSV2 3964
-+csb1724 MACH_CSB1724 CSB1724 3965
-+omapl138_lcdk MACH_OMAPL138_LCDK OMAPL138_LCDK 3966
-+pvd_mx25 MACH_PVD_MX25 PVD_MX25 3968
-+meson6_skt MACH_MESON6_SKT MESON6_SKT 3969
-+meson6_ref MACH_MESON6_REF MESON6_REF 3970
-+pxm MACH_PXM PXM 3971
-+pogoplugv3 MACH_POGOPLUGV3 POGOPLUGV3 3973
-+mlp89626 MACH_MLP89626 MLP89626 3974
-+iomegahmndce MACH_IOMEGAHMNDCE IOMEGAHMNDCE 3975
-+pogoplugv3pci MACH_POGOPLUGV3PCI POGOPLUGV3PCI 3976
-+bntv250 MACH_BNTV250 BNTV250 3977
-+mx53_qseven MACH_MX53_QSEVEN MX53_QSEVEN 3978
-+gtl_it1100 MACH_GTL_IT1100 GTL_IT1100 3979
-+mx6q_sabresd MACH_MX6Q_SABRESD MX6Q_SABRESD 3980
-+mt4 MACH_MT4 MT4 3981
-+jumbo_d MACH_JUMBO_D JUMBO_D 3982
-+jumbo_i MACH_JUMBO_I JUMBO_I 3983
-+fs20_dmp MACH_FS20_DMP FS20_DMP 3984
-+dns320 MACH_DNS320 DNS320 3985
-+mx28bacos MACH_MX28BACOS MX28BACOS 3986
-+tl80 MACH_TL80 TL80 3987
-+polatis_nic_1001 MACH_POLATIS_NIC_1001 POLATIS_NIC_1001 3988
-+tely MACH_TELY TELY 3989
-+u8520 MACH_U8520 U8520 3990
-+manta MACH_MANTA MANTA 3991
-+mpq8064_cdp MACH_MPQ8064_CDP MPQ8064_CDP 3993
-+mpq8064_dtv MACH_MPQ8064_DTV MPQ8064_DTV 3995
-+dm368som MACH_DM368SOM DM368SOM 3996
-+gprisb2 MACH_GPRISB2 GPRISB2 3997
-+chammid MACH_CHAMMID CHAMMID 3998
-+seoul2 MACH_SEOUL2 SEOUL2 3999
-+omap4_nooktablet MACH_OMAP4_NOOKTABLET OMAP4_NOOKTABLET 4000
-+aalto MACH_AALTO AALTO 4001
-+metro MACH_METRO METRO 4002
-+cydm3730 MACH_CYDM3730 CYDM3730 4003
-+tqma53 MACH_TQMA53 TQMA53 4004
-+msm7627a_qrd3 MACH_MSM7627A_QRD3 MSM7627A_QRD3 4005
-+mx28_canby MACH_MX28_CANBY MX28_CANBY 4006
-+tiger MACH_TIGER TIGER 4007
-+pcats_9307_type_a MACH_PCATS_9307_TYPE_A PCATS_9307_TYPE_A 4008
-+pcats_9307_type_o MACH_PCATS_9307_TYPE_O PCATS_9307_TYPE_O 4009
-+pcats_9307_type_r MACH_PCATS_9307_TYPE_R PCATS_9307_TYPE_R 4010
-+streamplug MACH_STREAMPLUG STREAMPLUG 4011
-+icechicken_dev MACH_ICECHICKEN_DEV ICECHICKEN_DEV 4012
-+hedgehog MACH_HEDGEHOG HEDGEHOG 4013
-+yusend_obc MACH_YUSEND_OBC YUSEND_OBC 4014
-+imxninja MACH_IMXNINJA IMXNINJA 4015
-+omap4_jarod MACH_OMAP4_JAROD OMAP4_JAROD 4016
-+eco5_pk MACH_ECO5_PK ECO5_PK 4017
-+qj2440 MACH_QJ2440 QJ2440 4018
-+mx6q_mercury MACH_MX6Q_MERCURY MX6Q_MERCURY 4019
-+cm6810 MACH_CM6810 CM6810 4020
-+omap4_torpedo MACH_OMAP4_TORPEDO OMAP4_TORPEDO 4021
-+nsa310 MACH_NSA310 NSA310 4022
-+tmx536 MACH_TMX536 TMX536 4023
-+ktt20 MACH_KTT20 KTT20 4024
-+dragonix MACH_DRAGONIX DRAGONIX 4025
-+lungching MACH_LUNGCHING LUNGCHING 4026
-+bulogics MACH_BULOGICS BULOGICS 4027
-+mx535_sx MACH_MX535_SX MX535_SX 4028
-+ngui3250 MACH_NGUI3250 NGUI3250 4029
-+salutec_dac MACH_SALUTEC_DAC SALUTEC_DAC 4030
-+loco MACH_LOCO LOCO 4031
-+ctera_plug_usi MACH_CTERA_PLUG_USI CTERA_PLUG_USI 4032
-+scepter MACH_SCEPTER SCEPTER 4033
-+sga MACH_SGA SGA 4034
-+p_81_j5 MACH_P_81_J5 P_81_J5 4035
-+p_81_o4 MACH_P_81_O4 P_81_O4 4036
-+msm8625_surf MACH_MSM8625_SURF MSM8625_SURF 4037
-+carallon_shark MACH_CARALLON_SHARK CARALLON_SHARK 4038
-+ordog MACH_ORDOG ORDOG 4040
-+puente_io MACH_PUENTE_IO PUENTE_IO 4041
-+msm8625_evb MACH_MSM8625_EVB MSM8625_EVB 4042
-+ev_am1707 MACH_EV_AM1707 EV_AM1707 4043
-+ev_am1707e2 MACH_EV_AM1707E2 EV_AM1707E2 4044
-+ev_am3517e2 MACH_EV_AM3517E2 EV_AM3517E2 4045
-+calabria MACH_CALABRIA CALABRIA 4046
-+ev_imx287 MACH_EV_IMX287 EV_IMX287 4047
-+erau MACH_ERAU ERAU 4048
-+sichuan MACH_SICHUAN SICHUAN 4049
-+davinci_da850 MACH_DAVINCI_DA850 DAVINCI_DA850 4051
-+omap138_trunarc MACH_OMAP138_TRUNARC OMAP138_TRUNARC 4052
-+bcm4761 MACH_BCM4761 BCM4761 4053
-+picasso_e2 MACH_PICASSO_E2 PICASSO_E2 4054
-+picasso_mf MACH_PICASSO_MF PICASSO_MF 4055
-+miro MACH_MIRO MIRO 4056
-+at91sam9g20ewon3 MACH_AT91SAM9G20EWON3 AT91SAM9G20EWON3 4057
-+yoyo MACH_YOYO YOYO 4058
-+windjkl MACH_WINDJKL WINDJKL 4059
-+monarudo MACH_MONARUDO MONARUDO 4060
-+batan MACH_BATAN BATAN 4061
-+tadao MACH_TADAO TADAO 4062
-+baso MACH_BASO BASO 4063
-+mahon MACH_MAHON MAHON 4064
-+villec2 MACH_VILLEC2 VILLEC2 4065
-+asi1230 MACH_ASI1230 ASI1230 4066
-+alaska MACH_ALASKA ALASKA 4067
-+swarco_shdsl2 MACH_SWARCO_SHDSL2 SWARCO_SHDSL2 4068
-+oxrtu MACH_OXRTU OXRTU 4069
-+omap5_panda MACH_OMAP5_PANDA OMAP5_PANDA 4070
-+c8000 MACH_C8000 C8000 4072
-+bje_display3_5 MACH_BJE_DISPLAY3_5 BJE_DISPLAY3_5 4073
-+picomod7 MACH_PICOMOD7 PICOMOD7 4074
-+picocom5 MACH_PICOCOM5 PICOCOM5 4075
-+qblissa8 MACH_QBLISSA8 QBLISSA8 4076
-+armstonea8 MACH_ARMSTONEA8 ARMSTONEA8 4077
-+netdcu14 MACH_NETDCU14 NETDCU14 4078
-+at91sam9x5_epiphan MACH_AT91SAM9X5_EPIPHAN AT91SAM9X5_EPIPHAN 4079
-+p2u MACH_P2U P2U 4080
-+doris MACH_DORIS DORIS 4081
-+j49 MACH_J49 J49 4082
-+vdss2e MACH_VDSS2E VDSS2E 4083
-+vc300 MACH_VC300 VC300 4084
-+ns115_pad_test MACH_NS115_PAD_TEST NS115_PAD_TEST 4085
-+ns115_pad_ref MACH_NS115_PAD_REF NS115_PAD_REF 4086
-+ns115_phone_test MACH_NS115_PHONE_TEST NS115_PHONE_TEST 4087
-+ns115_phone_ref MACH_NS115_PHONE_REF NS115_PHONE_REF 4088
-+golfc MACH_GOLFC GOLFC 4089
-+xerox_olympus MACH_XEROX_OLYMPUS XEROX_OLYMPUS 4090
-+mx6sl_arm2 MACH_MX6SL_ARM2 MX6SL_ARM2 4091
-+csb1701_csb1726 MACH_CSB1701_CSB1726 CSB1701_CSB1726 4092
-+at91sam9xeek MACH_AT91SAM9XEEK AT91SAM9XEEK 4093
-+ebv210 MACH_EBV210 EBV210 4094
-+msm7627a_qrd7 MACH_MSM7627A_QRD7 MSM7627A_QRD7 4095
-+svthin MACH_SVTHIN SVTHIN 4096
-+duovero MACH_DUOVERO DUOVERO 4097
-+chupacabra MACH_CHUPACABRA CHUPACABRA 4098
-+scorpion MACH_SCORPION SCORPION 4099
-+davinci_he_hmi10 MACH_DAVINCI_HE_HMI10 DAVINCI_HE_HMI10 4100
-+topkick MACH_TOPKICK TOPKICK 4101
-+m3_auguestrush MACH_M3_AUGUESTRUSH M3_AUGUESTRUSH 4102
-+ipc335x MACH_IPC335X IPC335X 4103
-+sun4i MACH_SUN4I SUN4I 4104
-+imx233_olinuxino MACH_IMX233_OLINUXINO IMX233_OLINUXINO 4105
-+k2_wl MACH_K2_WL K2_WL 4106
-+k2_ul MACH_K2_UL K2_UL 4107
-+k2_cl MACH_K2_CL K2_CL 4108
-+minbari_w MACH_MINBARI_W MINBARI_W 4109
-+minbari_m MACH_MINBARI_M MINBARI_M 4110
-+k035 MACH_K035 K035 4111
-+ariel MACH_ARIEL ARIEL 4112
-+arielsaarc MACH_ARIELSAARC ARIELSAARC 4113
-+arieldkb MACH_ARIELDKB ARIELDKB 4114
-+armadillo810 MACH_ARMADILLO810 ARMADILLO810 4115
-+tam335x MACH_TAM335X TAM335X 4116
-+grouper MACH_GROUPER GROUPER 4117
-+mpcsa21_9g20 MACH_MPCSA21_9G20 MPCSA21_9G20 4118
-+m6u_cpu MACH_M6U_CPU M6U_CPU 4119
-+davinci_dp10 MACH_DAVINCI_DP10 DAVINCI_DP10 4120
-+ginkgo MACH_GINKGO GINKGO 4121
-+cgt_qmx6 MACH_CGT_QMX6 CGT_QMX6 4122
-+profpga MACH_PROFPGA PROFPGA 4123
-+acfx100oc MACH_ACFX100OC ACFX100OC 4124
-+acfx100nb MACH_ACFX100NB ACFX100NB 4125
-+capricorn MACH_CAPRICORN CAPRICORN 4126
-+pisces MACH_PISCES PISCES 4127
-+aries MACH_ARIES ARIES 4128
-+cancer MACH_CANCER CANCER 4129
-+leo MACH_LEO LEO 4130
-+virgo MACH_VIRGO VIRGO 4131
-+sagittarius MACH_SAGITTARIUS SAGITTARIUS 4132
-+devil MACH_DEVIL DEVIL 4133
-+ballantines MACH_BALLANTINES BALLANTINES 4134
-+omap3_procerusvpu MACH_OMAP3_PROCERUSVPU OMAP3_PROCERUSVPU 4135
-+my27 MACH_MY27 MY27 4136
-+sun6i MACH_SUN6I SUN6I 4137
-+sun5i MACH_SUN5I SUN5I 4138
-+mx512_mx MACH_MX512_MX MX512_MX 4139
-+kzm9g MACH_KZM9G KZM9G 4140
-+vdstbn MACH_VDSTBN VDSTBN 4141
-+cfa10036 MACH_CFA10036 CFA10036 4142
-+cfa10049 MACH_CFA10049 CFA10049 4143
-+pcm051 MACH_PCM051 PCM051 4144
-+vybrid_vf7xx MACH_VYBRID_VF7XX VYBRID_VF7XX 4145
-+vybrid_vf6xx MACH_VYBRID_VF6XX VYBRID_VF6XX 4146
-+vybrid_vf5xx MACH_VYBRID_VF5XX VYBRID_VF5XX 4147
-+vybrid_vf4xx MACH_VYBRID_VF4XX VYBRID_VF4XX 4148
-+aria_g25 MACH_ARIA_G25 ARIA_G25 4149
-+bcm21553 MACH_BCM21553 BCM21553 4150
-+smdk5410 MACH_SMDK5410 SMDK5410 4151
-+lpc18xx MACH_LPC18XX LPC18XX 4152
-+oratisparty MACH_ORATISPARTY ORATISPARTY 4153
-+qseven MACH_QSEVEN QSEVEN 4154
-+gmv_generic MACH_GMV_GENERIC GMV_GENERIC 4155
-+th_link_eth MACH_TH_LINK_ETH TH_LINK_ETH 4156
-+tn_muninn MACH_TN_MUNINN TN_MUNINN 4157
-+rampage MACH_RAMPAGE RAMPAGE 4158
-+visstrim_mv10 MACH_VISSTRIM_MV10 VISSTRIM_MV10 4159
-+mx28_wilma MACH_MX28_WILMA MX28_WILMA 4164
-+msm8625_ffa MACH_MSM8625_FFA MSM8625_FFA 4166
-+vpu101 MACH_VPU101 VPU101 4167
-+baileys MACH_BAILEYS BAILEYS 4169
-+familybox MACH_FAMILYBOX FAMILYBOX 4170
-+ensemble_mx35 MACH_ENSEMBLE_MX35 ENSEMBLE_MX35 4171
-+sc_sps_1 MACH_SC_SPS_1 SC_SPS_1 4172
---
-1.7.9.5
-
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 3
- PATCHLEVEL = 4
- SUBLEVEL = 46
+ PATCHLEVEL = 10
+ SUBLEVEL = 11
-EXTRAVERSION =
+EXTRAVERSION = -ltsi
- NAME = Saber-toothed Squirrel
+ NAME = TOSSUG Baby Fish
# *DOCUMENTATION*
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
-@@ -64,6 +64,8 @@ source "drivers/staging/phison/Kconfig"
+@@ -140,4 +140,6 @@ source "drivers/staging/netlogic/Kconfig
- source "drivers/staging/line6/Kconfig"
+ source "drivers/staging/dwc2/Kconfig"
+source "drivers/staging/lttng/Kconfig"
+
- source "drivers/staging/octeon/Kconfig"
-
- source "drivers/staging/serqt_usb2/Kconfig"
+ endif # STAGING
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
-@@ -24,6 +24,7 @@ obj-$(CONFIG_RTS5139) += rts5139/
- obj-$(CONFIG_TRANZPORT) += frontier/
- obj-$(CONFIG_IDE_PHISON) += phison/
- obj-$(CONFIG_LINE6_USB) += line6/
+@@ -62,3 +62,4 @@ obj-$(CONFIG_FIREWIRE_SERIAL) += fwseria
+ obj-$(CONFIG_ZCACHE) += zcache/
+ obj-$(CONFIG_GOLDFISH) += goldfish/
+ obj-$(CONFIG_USB_DWC2) += dwc2/
+obj-$(CONFIG_LTTNG) += lttng/
- obj-$(CONFIG_USB_SERIAL_QUATECH2) += serqt_usb2/
- obj-$(CONFIG_USB_SERIAL_QUATECH_USB2) += quatech_usb2/
- obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -4248,6 +4248,13 @@ T: git git://github.com/linux-test-proje
+@@ -5079,6 +5079,13 @@ T: git git://github.com/linux-test-proje
T: git git://ltp.git.sourceforge.net/gitroot/ltp/ltp-dev
S: Maintained
+++ /dev/null
-From aa9210ec33e000900e3ad25d7b98c7897027b1f2 Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Wed, 11 Apr 2012 12:05:50 +0900
-Subject: sh: clkfwk: Support variable size accesses for MSTP clocks.
-
-The bulk of the MSTP users require 32-bit access, but this isn't the case
-for some of the SH-2A parts, so add in some basic infrastructure to let
-the CPU define its required access size in preparation.
-
-Requested-by: Phil Edworthy <phil.edworthy@renesas.com>
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 4d6ddb08acc48368c5b7ac431f9d00db7227d2ed)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/sh/clk/cpg.c | 38 +++++++++++++++++++++++++++-----------
- include/linux/sh_clk.h | 34 +++++++++++++++++++++++++++++++---
- 2 files changed, 58 insertions(+), 14 deletions(-)
-
-diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
-index 91b6d52..6cbda48 100644
---- a/drivers/sh/clk/cpg.c
-+++ b/drivers/sh/clk/cpg.c
-@@ -2,6 +2,7 @@
- * Helper routines for SuperH Clock Pulse Generator blocks (CPG).
- *
- * Copyright (C) 2010 Magnus Damm
-+ * Copyright (C) 2010 - 2012 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
-@@ -13,26 +14,41 @@
- #include <linux/io.h>
- #include <linux/sh_clk.h>
-
--static int sh_clk_mstp32_enable(struct clk *clk)
-+static int sh_clk_mstp_enable(struct clk *clk)
- {
-- iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
-- clk->mapped_reg);
-+ if (clk->flags & CLK_ENABLE_REG_8BIT)
-+ iowrite8(ioread8(clk->mapped_reg) & ~(1 << clk->enable_bit),
-+ clk->mapped_reg);
-+ else if (clk->flags & CLK_ENABLE_REG_16BIT)
-+ iowrite16(ioread16(clk->mapped_reg) & ~(1 << clk->enable_bit),
-+ clk->mapped_reg);
-+ else
-+ iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
-+ clk->mapped_reg);
-+
- return 0;
- }
-
--static void sh_clk_mstp32_disable(struct clk *clk)
-+static void sh_clk_mstp_disable(struct clk *clk)
- {
-- iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
-- clk->mapped_reg);
-+ if (clk->flags & CLK_ENABLE_REG_8BIT)
-+ iowrite8(ioread8(clk->mapped_reg) | (1 << clk->enable_bit),
-+ clk->mapped_reg);
-+ else if (clk->flags & CLK_ENABLE_REG_16BIT)
-+ iowrite16(ioread16(clk->mapped_reg) | (1 << clk->enable_bit),
-+ clk->mapped_reg);
-+ else
-+ iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
-+ clk->mapped_reg);
- }
-
--static struct sh_clk_ops sh_clk_mstp32_clk_ops = {
-- .enable = sh_clk_mstp32_enable,
-- .disable = sh_clk_mstp32_disable,
-+static struct sh_clk_ops sh_clk_mstp_clk_ops = {
-+ .enable = sh_clk_mstp_enable,
-+ .disable = sh_clk_mstp_disable,
- .recalc = followparent_recalc,
- };
-
--int __init sh_clk_mstp32_register(struct clk *clks, int nr)
-+int __init sh_clk_mstp_register(struct clk *clks, int nr)
- {
- struct clk *clkp;
- int ret = 0;
-@@ -40,7 +56,7 @@ int __init sh_clk_mstp32_register(struct clk *clks, int nr)
-
- for (k = 0; !ret && (k < nr); k++) {
- clkp = clks + k;
-- clkp->ops = &sh_clk_mstp32_clk_ops;
-+ clkp->ops = &sh_clk_mstp_clk_ops;
- ret |= clk_register(clkp);
- }
-
-diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h
-index 0a9d8f2..c513b73 100644
---- a/include/linux/sh_clk.h
-+++ b/include/linux/sh_clk.h
-@@ -59,7 +59,15 @@ struct clk {
- unsigned int nr_freqs;
- };
-
--#define CLK_ENABLE_ON_INIT (1 << 0)
-+#define CLK_ENABLE_ON_INIT BIT(0)
-+
-+#define CLK_ENABLE_REG_32BIT BIT(1) /* default access size */
-+#define CLK_ENABLE_REG_16BIT BIT(2)
-+#define CLK_ENABLE_REG_8BIT BIT(3)
-+
-+#define CLK_ENABLE_REG_MASK (CLK_ENABLE_REG_32BIT | \
-+ CLK_ENABLE_REG_16BIT | \
-+ CLK_ENABLE_REG_8BIT)
-
- /* drivers/sh/clk.c */
- unsigned long followparent_recalc(struct clk *);
-@@ -102,7 +110,7 @@ long clk_round_parent(struct clk *clk, unsigned long target,
- unsigned long *best_freq, unsigned long *parent_freq,
- unsigned int div_min, unsigned int div_max);
-
--#define SH_CLK_MSTP32(_parent, _enable_reg, _enable_bit, _flags) \
-+#define SH_CLK_MSTP(_parent, _enable_reg, _enable_bit, _flags) \
- { \
- .parent = _parent, \
- .enable_reg = (void __iomem *)_enable_reg, \
-@@ -110,7 +118,27 @@ long clk_round_parent(struct clk *clk, unsigned long target,
- .flags = _flags, \
- }
-
--int sh_clk_mstp32_register(struct clk *clks, int nr);
-+#define SH_CLK_MSTP32(_p, _r, _b, _f) \
-+ SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_32BIT)
-+
-+#define SH_CLK_MSTP16(_p, _r, _b, _f) \
-+ SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_16BIT)
-+
-+#define SH_CLK_MSTP8(_p, _r, _b, _f) \
-+ SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_8BIT)
-+
-+int sh_clk_mstp_register(struct clk *clks, int nr);
-+
-+/*
-+ * MSTP registration never really cared about access size, despite the
-+ * original enable/disable pairs assuming a 32-bit access. Clocks are
-+ * responsible for defining their access sizes either directly or via the
-+ * clock definition wrappers.
-+ */
-+static inline int __deprecated sh_clk_mstp32_register(struct clk *clks, int nr)
-+{
-+ return sh_clk_mstp_register(clks, nr);
-+}
-
- #define SH_CLK_DIV4(_parent, _reg, _shift, _div_bitmap, _flags) \
- { \
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 5a1639b2287a62e965e2355c68ef52da597b9a3c Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Thu, 12 Apr 2012 19:50:40 +0900
-Subject: sh: clkfwk: Support variable size accesses for div4/div6 clocks.
-
-This follows the MSTP clock change and implements variable access size
-support for the rest of the CPG clocks, too. Upcoming SH-2A support has
-need of this for 16-bit div4 clocks, while others will follow.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 104fa61a7dd83197160d5cafedc0e94ad9cd7fcc)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/sh/clk/cpg.c | 71 +++++++++++++++++++++++++++-------------------------
- 1 file changed, 37 insertions(+), 34 deletions(-)
-
-diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
-index 6cbda48..f0d015d 100644
---- a/drivers/sh/clk/cpg.c
-+++ b/drivers/sh/clk/cpg.c
-@@ -14,32 +14,35 @@
- #include <linux/io.h>
- #include <linux/sh_clk.h>
-
--static int sh_clk_mstp_enable(struct clk *clk)
-+static unsigned int sh_clk_read(struct clk *clk)
- {
- if (clk->flags & CLK_ENABLE_REG_8BIT)
-- iowrite8(ioread8(clk->mapped_reg) & ~(1 << clk->enable_bit),
-- clk->mapped_reg);
-+ return ioread8(clk->mapped_reg);
- else if (clk->flags & CLK_ENABLE_REG_16BIT)
-- iowrite16(ioread16(clk->mapped_reg) & ~(1 << clk->enable_bit),
-- clk->mapped_reg);
-- else
-- iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
-- clk->mapped_reg);
-+ return ioread16(clk->mapped_reg);
-
-- return 0;
-+ return ioread32(clk->mapped_reg);
- }
-
--static void sh_clk_mstp_disable(struct clk *clk)
-+static void sh_clk_write(int value, struct clk *clk)
- {
- if (clk->flags & CLK_ENABLE_REG_8BIT)
-- iowrite8(ioread8(clk->mapped_reg) | (1 << clk->enable_bit),
-- clk->mapped_reg);
-+ iowrite8(value, clk->mapped_reg);
- else if (clk->flags & CLK_ENABLE_REG_16BIT)
-- iowrite16(ioread16(clk->mapped_reg) | (1 << clk->enable_bit),
-- clk->mapped_reg);
-+ iowrite16(value, clk->mapped_reg);
- else
-- iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
-- clk->mapped_reg);
-+ iowrite32(value, clk->mapped_reg);
-+}
-+
-+static int sh_clk_mstp_enable(struct clk *clk)
-+{
-+ sh_clk_write(sh_clk_read(clk) & ~(1 << clk->enable_bit), clk);
-+ return 0;
-+}
-+
-+static void sh_clk_mstp_disable(struct clk *clk)
-+{
-+ sh_clk_write(sh_clk_read(clk) | (1 << clk->enable_bit), clk);
- }
-
- static struct sh_clk_ops sh_clk_mstp_clk_ops = {
-@@ -88,7 +91,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk)
- clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
- table, NULL);
-
-- idx = ioread32(clk->mapped_reg) & 0x003f;
-+ idx = sh_clk_read(clk) & 0x003f;
-
- return clk->freq_table[idx].frequency;
- }
-@@ -114,10 +117,10 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
- if (ret < 0)
- return ret;
-
-- value = ioread32(clk->mapped_reg) &
-+ value = sh_clk_read(clk) &
- ~(((1 << clk->src_width) - 1) << clk->src_shift);
-
-- iowrite32(value | (i << clk->src_shift), clk->mapped_reg);
-+ sh_clk_write(value | (i << clk->src_shift), clk);
-
- /* Rebuild the frequency table */
- clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
-@@ -135,10 +138,10 @@ static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate)
- if (idx < 0)
- return idx;
-
-- value = ioread32(clk->mapped_reg);
-+ value = sh_clk_read(clk);
- value &= ~0x3f;
- value |= idx;
-- iowrite32(value, clk->mapped_reg);
-+ sh_clk_write(value, clk);
- return 0;
- }
-
-@@ -149,9 +152,9 @@ static int sh_clk_div6_enable(struct clk *clk)
-
- ret = sh_clk_div6_set_rate(clk, clk->rate);
- if (ret == 0) {
-- value = ioread32(clk->mapped_reg);
-+ value = sh_clk_read(clk);
- value &= ~0x100; /* clear stop bit to enable clock */
-- iowrite32(value, clk->mapped_reg);
-+ sh_clk_write(value, clk);
- }
- return ret;
- }
-@@ -160,10 +163,10 @@ static void sh_clk_div6_disable(struct clk *clk)
- {
- unsigned long value;
-
-- value = ioread32(clk->mapped_reg);
-+ value = sh_clk_read(clk);
- value |= 0x100; /* stop clock */
- value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
-- iowrite32(value, clk->mapped_reg);
-+ sh_clk_write(value, clk);
- }
-
- static struct sh_clk_ops sh_clk_div6_clk_ops = {
-@@ -198,7 +201,7 @@ static int __init sh_clk_init_parent(struct clk *clk)
- return -EINVAL;
- }
-
-- val = (ioread32(clk->mapped_reg) >> clk->src_shift);
-+ val = (sh_clk_read(clk) >> clk->src_shift);
- val &= (1 << clk->src_width) - 1;
-
- if (val >= clk->parent_num) {
-@@ -268,7 +271,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk)
- clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
- table, &clk->arch_flags);
-
-- idx = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0x000f;
-+ idx = (sh_clk_read(clk) >> clk->enable_bit) & 0x000f;
-
- return clk->freq_table[idx].frequency;
- }
-@@ -286,15 +289,15 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
- */
-
- if (parent->flags & CLK_ENABLE_ON_INIT)
-- value = ioread32(clk->mapped_reg) & ~(1 << 7);
-+ value = sh_clk_read(clk) & ~(1 << 7);
- else
-- value = ioread32(clk->mapped_reg) | (1 << 7);
-+ value = sh_clk_read(clk) | (1 << 7);
-
- ret = clk_reparent(clk, parent);
- if (ret < 0)
- return ret;
-
-- iowrite32(value, clk->mapped_reg);
-+ sh_clk_write(value, clk);
-
- /* Rebiuld the frequency table */
- clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
-@@ -311,10 +314,10 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
- if (idx < 0)
- return idx;
-
-- value = ioread32(clk->mapped_reg);
-+ value = sh_clk_read(clk);
- value &= ~(0xf << clk->enable_bit);
- value |= (idx << clk->enable_bit);
-- iowrite32(value, clk->mapped_reg);
-+ sh_clk_write(value, clk);
-
- if (d4t->kick)
- d4t->kick(clk);
-@@ -324,13 +327,13 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
-
- static int sh_clk_div4_enable(struct clk *clk)
- {
-- iowrite32(ioread32(clk->mapped_reg) & ~(1 << 8), clk->mapped_reg);
-+ sh_clk_write(sh_clk_read(clk) & ~(1 << 8), clk);
- return 0;
- }
-
- static void sh_clk_div4_disable(struct clk *clk)
- {
-- iowrite32(ioread32(clk->mapped_reg) | (1 << 8), clk->mapped_reg);
-+ sh_clk_write(sh_clk_read(clk) | (1 << 8), clk);
- }
-
- static struct sh_clk_ops sh_clk_div4_clk_ops = {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From cd33eef0c195fa40494a8115aa1202bdaed860a0 Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Fri, 25 May 2012 14:59:26 +0900
-Subject: sh: clkfwk: Move to common clk_div_table accessors for div4/div6.
-
-This plugs in a generic clk_div_table, based on the div4 version. div6 is
-then adopted to use it for encapsulating its div table, which permits us
-to start div6/4 unification, as well as preparation for other div types.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit a60977a51333a8108f0574aa26094d66b7fedf34)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/sh/clk/cpg.c | 46 +++++++++++++++++++++++++++++++++++-----------
- include/linux/sh_clk.h | 5 +++--
- 2 files changed, 38 insertions(+), 13 deletions(-)
-
-diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
-index f0d015d..9dea329 100644
---- a/drivers/sh/clk/cpg.c
-+++ b/drivers/sh/clk/cpg.c
-@@ -71,6 +71,22 @@ static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
- return clk_rate_table_round(clk, clk->freq_table, rate);
- }
-
-+/*
-+ * Div/mult table lookup helpers
-+ */
-+static inline struct clk_div_table *clk_to_div_table(struct clk *clk)
-+{
-+ return clk->priv;
-+}
-+
-+static inline struct clk_div_mult_table *clk_to_div_mult_table(struct clk *clk)
-+{
-+ return clk_to_div_table(clk)->div_mult_table;
-+}
-+
-+/*
-+ * div6 support
-+ */
- static int sh_clk_div6_divisors[64] = {
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
-@@ -78,14 +94,18 @@ static int sh_clk_div6_divisors[64] = {
- 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
- };
-
--static struct clk_div_mult_table sh_clk_div6_table = {
-+static struct clk_div_mult_table div6_div_mult_table = {
- .divisors = sh_clk_div6_divisors,
- .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors),
- };
-
-+static struct clk_div_table sh_clk_div6_table = {
-+ .div_mult_table = &div6_div_mult_table,
-+};
-+
- static unsigned long sh_clk_div6_recalc(struct clk *clk)
- {
-- struct clk_div_mult_table *table = &sh_clk_div6_table;
-+ struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
- unsigned int idx;
-
- clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
-@@ -98,7 +118,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk)
-
- static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
- {
-- struct clk_div_mult_table *table = &sh_clk_div6_table;
-+ struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
- u32 value;
- int ret, i;
-
-@@ -223,7 +243,8 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
- {
- struct clk *clkp;
- void *freq_table;
-- int nr_divs = sh_clk_div6_table.nr_divisors;
-+ struct clk_div_table *table = &sh_clk_div6_table;
-+ int nr_divs = table->div_mult_table->nr_divisors;
- int freq_table_size = sizeof(struct cpufreq_frequency_table);
- int ret = 0;
- int k;
-@@ -239,6 +260,7 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
- clkp = clks + k;
-
- clkp->ops = ops;
-+ clkp->priv = table;
- clkp->freq_table = freq_table + (k * freq_table_size);
- clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
- ret = clk_register(clkp);
-@@ -262,10 +284,12 @@ int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
- &sh_clk_div6_reparent_clk_ops);
- }
-
-+/*
-+ * div4 support
-+ */
- static unsigned long sh_clk_div4_recalc(struct clk *clk)
- {
-- struct clk_div4_table *d4t = clk->priv;
-- struct clk_div_mult_table *table = d4t->div_mult_table;
-+ struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
- unsigned int idx;
-
- clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
-@@ -278,8 +302,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk)
-
- static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
- {
-- struct clk_div4_table *d4t = clk->priv;
-- struct clk_div_mult_table *table = d4t->div_mult_table;
-+ struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
- u32 value;
- int ret;
-
-@@ -308,7 +331,7 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
-
- static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
- {
-- struct clk_div4_table *d4t = clk->priv;
-+ struct clk_div_table *dt = clk_to_div_table(clk);
- unsigned long value;
- int idx = clk_rate_table_find(clk, clk->freq_table, rate);
- if (idx < 0)
-@@ -319,8 +342,9 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
- value |= (idx << clk->enable_bit);
- sh_clk_write(value, clk);
-
-- if (d4t->kick)
-- d4t->kick(clk);
-+ /* XXX: Should use a post-change notifier */
-+ if (dt->kick)
-+ dt->kick(clk);
-
- return 0;
- }
-diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h
-index c513b73..706b803 100644
---- a/include/linux/sh_clk.h
-+++ b/include/linux/sh_clk.h
-@@ -18,7 +18,6 @@ struct clk_mapping {
- struct kref ref;
- };
-
--
- struct sh_clk_ops {
- #ifdef CONFIG_SH_CLK_CPG_LEGACY
- void (*init)(struct clk *clk);
-@@ -149,11 +148,13 @@ static inline int __deprecated sh_clk_mstp32_register(struct clk *clks, int nr)
- .flags = _flags, \
- }
-
--struct clk_div4_table {
-+struct clk_div_table {
- struct clk_div_mult_table *div_mult_table;
- void (*kick)(struct clk *clk);
- };
-
-+#define clk_div4_table clk_div_table
-+
- int sh_clk_div4_register(struct clk *clks, int nr,
- struct clk_div4_table *table);
- int sh_clk_div4_enable_register(struct clk *clks, int nr,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a0643bdb2770016b5930f9cbe5dee7a36e6951fc Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Fri, 25 May 2012 15:21:43 +0900
-Subject: sh: clkfwk: Introduce a div_mask for variable div types.
-
-This plugs in a div_mask for the clock and sets it up for the existing
-div6/4 cases. This will make it possible to support other div types, as
-well as share more div6/4 infrastructure.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 1111cc1e8080b5ff46f5b945acb2f99d6176b2d1)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/sh/clk/cpg.c | 10 +++++-----
- include/linux/sh_clk.h | 8 ++++++++
- 2 files changed, 13 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
-index 9dea329..9386bd2 100644
---- a/drivers/sh/clk/cpg.c
-+++ b/drivers/sh/clk/cpg.c
-@@ -111,7 +111,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk)
- clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
- table, NULL);
-
-- idx = sh_clk_read(clk) & 0x003f;
-+ idx = sh_clk_read(clk) & clk->div_mask;
-
- return clk->freq_table[idx].frequency;
- }
-@@ -159,7 +159,7 @@ static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate)
- return idx;
-
- value = sh_clk_read(clk);
-- value &= ~0x3f;
-+ value &= ~clk->div_mask;
- value |= idx;
- sh_clk_write(value, clk);
- return 0;
-@@ -185,7 +185,7 @@ static void sh_clk_div6_disable(struct clk *clk)
-
- value = sh_clk_read(clk);
- value |= 0x100; /* stop clock */
-- value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
-+ value |= clk->div_mask; /* VDIV bits must be non-zero, overwrite divider */
- sh_clk_write(value, clk);
- }
-
-@@ -295,7 +295,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk)
- clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
- table, &clk->arch_flags);
-
-- idx = (sh_clk_read(clk) >> clk->enable_bit) & 0x000f;
-+ idx = (sh_clk_read(clk) >> clk->enable_bit) & clk->div_mask;
-
- return clk->freq_table[idx].frequency;
- }
-@@ -338,7 +338,7 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
- return idx;
-
- value = sh_clk_read(clk);
-- value &= ~(0xf << clk->enable_bit);
-+ value &= ~(clk->div_mask << clk->enable_bit);
- value |= (idx << clk->enable_bit);
- sh_clk_write(value, clk);
-
-diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h
-index 706b803..d540b81 100644
---- a/include/linux/sh_clk.h
-+++ b/include/linux/sh_clk.h
-@@ -30,6 +30,10 @@ struct sh_clk_ops {
- long (*round_rate)(struct clk *clk, unsigned long rate);
- };
-
-+#define SH_CLK_DIV_MSK(div) ((1 << (div)) - 1)
-+#define SH_CLK_DIV4_MSK SH_CLK_DIV_MSK(4)
-+#define SH_CLK_DIV6_MSK SH_CLK_DIV_MSK(6)
-+
- struct clk {
- struct list_head node;
- struct clk *parent;
-@@ -51,6 +55,7 @@ struct clk {
- unsigned int enable_bit;
- void __iomem *mapped_reg;
-
-+ unsigned int div_mask;
- unsigned long arch_flags;
- void *priv;
- struct clk_mapping *mapping;
-@@ -145,6 +150,7 @@ static inline int __deprecated sh_clk_mstp32_register(struct clk *clks, int nr)
- .enable_reg = (void __iomem *)_reg, \
- .enable_bit = _shift, \
- .arch_flags = _div_bitmap, \
-+ .div_mask = SH_CLK_DIV4_MSK, \
- .flags = _flags, \
- }
-
-@@ -167,6 +173,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
- { \
- .enable_reg = (void __iomem *)_reg, \
- .flags = _flags, \
-+ .div_mask = SH_CLK_DIV6_MSK, \
- .parent_table = _parents, \
- .parent_num = _num_parents, \
- .src_shift = _src_shift, \
-@@ -177,6 +184,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
- { \
- .parent = _parent, \
- .enable_reg = (void __iomem *)_reg, \
-+ .div_mask = SH_CLK_DIV6_MSK, \
- .flags = _flags, \
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 4a3185214cc3715feff6d802b0df478e7e61901e Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Fri, 25 May 2012 15:26:01 +0900
-Subject: sh: clkfwk: Use shared sh_clk_div_recalc().
-
-This generalizes the div4 recalc routine for use by div6 and others, then
-makes it the default.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 75f5f8a56e0fdf6d32b3ae9c44c10bc0acd3857c)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/sh/clk/cpg.c | 62 +++++++++++++++++++++-----------------------------
- include/linux/sh_clk.h | 2 ++
- 2 files changed, 28 insertions(+), 36 deletions(-)
-
-diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
-index 9386bd2..84aeeb8 100644
---- a/drivers/sh/clk/cpg.c
-+++ b/drivers/sh/clk/cpg.c
-@@ -66,11 +66,6 @@ int __init sh_clk_mstp_register(struct clk *clks, int nr)
- return ret;
- }
-
--static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
--{
-- return clk_rate_table_round(clk, clk->freq_table, rate);
--}
--
- /*
- * Div/mult table lookup helpers
- */
-@@ -85,6 +80,27 @@ static inline struct clk_div_mult_table *clk_to_div_mult_table(struct clk *clk)
- }
-
- /*
-+ * Common div ops
-+ */
-+static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
-+{
-+ return clk_rate_table_round(clk, clk->freq_table, rate);
-+}
-+
-+static unsigned long sh_clk_div_recalc(struct clk *clk)
-+{
-+ struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
-+ unsigned int idx;
-+
-+ clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
-+ table, clk->arch_flags ? &clk->arch_flags : NULL);
-+
-+ idx = (sh_clk_read(clk) >> clk->enable_bit) & clk->div_mask;
-+
-+ return clk->freq_table[idx].frequency;
-+}
-+
-+/*
- * div6 support
- */
- static int sh_clk_div6_divisors[64] = {
-@@ -103,19 +119,6 @@ static struct clk_div_table sh_clk_div6_table = {
- .div_mult_table = &div6_div_mult_table,
- };
-
--static unsigned long sh_clk_div6_recalc(struct clk *clk)
--{
-- struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
-- unsigned int idx;
--
-- clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
-- table, NULL);
--
-- idx = sh_clk_read(clk) & clk->div_mask;
--
-- return clk->freq_table[idx].frequency;
--}
--
- static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
- {
- struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
-@@ -190,7 +193,7 @@ static void sh_clk_div6_disable(struct clk *clk)
- }
-
- static struct sh_clk_ops sh_clk_div6_clk_ops = {
-- .recalc = sh_clk_div6_recalc,
-+ .recalc = sh_clk_div_recalc,
- .round_rate = sh_clk_div_round_rate,
- .set_rate = sh_clk_div6_set_rate,
- .enable = sh_clk_div6_enable,
-@@ -198,7 +201,7 @@ static struct sh_clk_ops sh_clk_div6_clk_ops = {
- };
-
- static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
-- .recalc = sh_clk_div6_recalc,
-+ .recalc = sh_clk_div_recalc,
- .round_rate = sh_clk_div_round_rate,
- .set_rate = sh_clk_div6_set_rate,
- .enable = sh_clk_div6_enable,
-@@ -287,19 +290,6 @@ int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
- /*
- * div4 support
- */
--static unsigned long sh_clk_div4_recalc(struct clk *clk)
--{
-- struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
-- unsigned int idx;
--
-- clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
-- table, &clk->arch_flags);
--
-- idx = (sh_clk_read(clk) >> clk->enable_bit) & clk->div_mask;
--
-- return clk->freq_table[idx].frequency;
--}
--
- static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
- {
- struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
-@@ -361,13 +351,13 @@ static void sh_clk_div4_disable(struct clk *clk)
- }
-
- static struct sh_clk_ops sh_clk_div4_clk_ops = {
-- .recalc = sh_clk_div4_recalc,
-+ .recalc = sh_clk_div_recalc,
- .set_rate = sh_clk_div4_set_rate,
- .round_rate = sh_clk_div_round_rate,
- };
-
- static struct sh_clk_ops sh_clk_div4_enable_clk_ops = {
-- .recalc = sh_clk_div4_recalc,
-+ .recalc = sh_clk_div_recalc,
- .set_rate = sh_clk_div4_set_rate,
- .round_rate = sh_clk_div_round_rate,
- .enable = sh_clk_div4_enable,
-@@ -375,7 +365,7 @@ static struct sh_clk_ops sh_clk_div4_enable_clk_ops = {
- };
-
- static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = {
-- .recalc = sh_clk_div4_recalc,
-+ .recalc = sh_clk_div_recalc,
- .set_rate = sh_clk_div4_set_rate,
- .round_rate = sh_clk_div_round_rate,
- .enable = sh_clk_div4_enable,
-diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h
-index d540b81..35a04f1 100644
---- a/include/linux/sh_clk.h
-+++ b/include/linux/sh_clk.h
-@@ -172,6 +172,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
- _num_parents, _src_shift, _src_width) \
- { \
- .enable_reg = (void __iomem *)_reg, \
-+ .enable_bit = 0, /* unused */ \
- .flags = _flags, \
- .div_mask = SH_CLK_DIV6_MSK, \
- .parent_table = _parents, \
-@@ -184,6 +185,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
- { \
- .parent = _parent, \
- .enable_reg = (void __iomem *)_reg, \
-+ .enable_bit = 0, /* unused */ \
- .div_mask = SH_CLK_DIV6_MSK, \
- .flags = _flags, \
- }
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From df94ddc15bc18c4fd96707fce2b3983e6f013f83 Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Fri, 25 May 2012 15:52:10 +0900
-Subject: sh: clkfwk: Use shared sh_clk_div_set_rate()
-
-Follows the sh_clk_div_recalc() change.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 0fa22168e00106797f28b2655aaefd0d16a6e67b)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/sh/clk/cpg.c | 70 +++++++++++++++++++++-------------------------------
- 1 file changed, 28 insertions(+), 42 deletions(-)
-
-diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
-index 84aeeb8..29ee5f7 100644
---- a/drivers/sh/clk/cpg.c
-+++ b/drivers/sh/clk/cpg.c
-@@ -100,6 +100,28 @@ static unsigned long sh_clk_div_recalc(struct clk *clk)
- return clk->freq_table[idx].frequency;
- }
-
-+static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate)
-+{
-+ struct clk_div_table *dt = clk_to_div_table(clk);
-+ unsigned long value;
-+ int idx;
-+
-+ idx = clk_rate_table_find(clk, clk->freq_table, rate);
-+ if (idx < 0)
-+ return idx;
-+
-+ value = sh_clk_read(clk);
-+ value &= ~(clk->div_mask << clk->enable_bit);
-+ value |= (idx << clk->enable_bit);
-+ sh_clk_write(value, clk);
-+
-+ /* XXX: Should use a post-change notifier */
-+ if (dt->kick)
-+ dt->kick(clk);
-+
-+ return 0;
-+}
-+
- /*
- * div6 support
- */
-@@ -152,28 +174,12 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
- return 0;
- }
-
--static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate)
--{
-- unsigned long value;
-- int idx;
--
-- idx = clk_rate_table_find(clk, clk->freq_table, rate);
-- if (idx < 0)
-- return idx;
--
-- value = sh_clk_read(clk);
-- value &= ~clk->div_mask;
-- value |= idx;
-- sh_clk_write(value, clk);
-- return 0;
--}
--
- static int sh_clk_div6_enable(struct clk *clk)
- {
- unsigned long value;
- int ret;
-
-- ret = sh_clk_div6_set_rate(clk, clk->rate);
-+ ret = sh_clk_div_set_rate(clk, clk->rate);
- if (ret == 0) {
- value = sh_clk_read(clk);
- value &= ~0x100; /* clear stop bit to enable clock */
-@@ -195,7 +201,7 @@ static void sh_clk_div6_disable(struct clk *clk)
- static struct sh_clk_ops sh_clk_div6_clk_ops = {
- .recalc = sh_clk_div_recalc,
- .round_rate = sh_clk_div_round_rate,
-- .set_rate = sh_clk_div6_set_rate,
-+ .set_rate = sh_clk_div_set_rate,
- .enable = sh_clk_div6_enable,
- .disable = sh_clk_div6_disable,
- };
-@@ -203,7 +209,7 @@ static struct sh_clk_ops sh_clk_div6_clk_ops = {
- static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
- .recalc = sh_clk_div_recalc,
- .round_rate = sh_clk_div_round_rate,
-- .set_rate = sh_clk_div6_set_rate,
-+ .set_rate = sh_clk_div_set_rate,
- .enable = sh_clk_div6_enable,
- .disable = sh_clk_div6_disable,
- .set_parent = sh_clk_div6_set_parent,
-@@ -319,26 +325,6 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
- return 0;
- }
-
--static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
--{
-- struct clk_div_table *dt = clk_to_div_table(clk);
-- unsigned long value;
-- int idx = clk_rate_table_find(clk, clk->freq_table, rate);
-- if (idx < 0)
-- return idx;
--
-- value = sh_clk_read(clk);
-- value &= ~(clk->div_mask << clk->enable_bit);
-- value |= (idx << clk->enable_bit);
-- sh_clk_write(value, clk);
--
-- /* XXX: Should use a post-change notifier */
-- if (dt->kick)
-- dt->kick(clk);
--
-- return 0;
--}
--
- static int sh_clk_div4_enable(struct clk *clk)
- {
- sh_clk_write(sh_clk_read(clk) & ~(1 << 8), clk);
-@@ -352,13 +338,13 @@ static void sh_clk_div4_disable(struct clk *clk)
-
- static struct sh_clk_ops sh_clk_div4_clk_ops = {
- .recalc = sh_clk_div_recalc,
-- .set_rate = sh_clk_div4_set_rate,
-+ .set_rate = sh_clk_div_set_rate,
- .round_rate = sh_clk_div_round_rate,
- };
-
- static struct sh_clk_ops sh_clk_div4_enable_clk_ops = {
- .recalc = sh_clk_div_recalc,
-- .set_rate = sh_clk_div4_set_rate,
-+ .set_rate = sh_clk_div_set_rate,
- .round_rate = sh_clk_div_round_rate,
- .enable = sh_clk_div4_enable,
- .disable = sh_clk_div4_disable,
-@@ -366,7 +352,7 @@ static struct sh_clk_ops sh_clk_div4_enable_clk_ops = {
-
- static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = {
- .recalc = sh_clk_div_recalc,
-- .set_rate = sh_clk_div4_set_rate,
-+ .set_rate = sh_clk_div_set_rate,
- .round_rate = sh_clk_div_round_rate,
- .enable = sh_clk_div4_enable,
- .disable = sh_clk_div4_disable,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From c4dd62f54d65dfd226383c7c2aab74d9b33e71f5 Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Fri, 25 May 2012 16:34:48 +0900
-Subject: sh: clkfwk: Use shared sh_clk_div_enable/disable().
-
-This introduces a new flag for clocks that need to have their divisor
-ratio set back to their initial mask at disable time to prevent
-interactivity problems with the clock stop bit (presently div6 only).
-With this in place it's possible to handle the corner case on top of the
-div4 op without any particular need for leaving things split out.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 764f4e4e33d18cde4dcaf8a0d860b749c6d6d08b)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/sh/clk/cpg.c | 77 ++++++++++++++++++++++----------------------------
- include/linux/sh_clk.h | 6 ++--
- 2 files changed, 38 insertions(+), 45 deletions(-)
-
-diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
-index 29ee5f7..06537f2 100644
---- a/drivers/sh/clk/cpg.c
-+++ b/drivers/sh/clk/cpg.c
-@@ -14,6 +14,8 @@
- #include <linux/io.h>
- #include <linux/sh_clk.h>
-
-+#define CPG_CKSTP_BIT BIT(8)
-+
- static unsigned int sh_clk_read(struct clk *clk)
- {
- if (clk->flags & CLK_ENABLE_REG_8BIT)
-@@ -122,6 +124,30 @@ static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate)
- return 0;
- }
-
-+static int sh_clk_div_enable(struct clk *clk)
-+{
-+ sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk);
-+ return 0;
-+}
-+
-+static void sh_clk_div_disable(struct clk *clk)
-+{
-+ unsigned int val;
-+
-+ val = sh_clk_read(clk);
-+ val |= CPG_CKSTP_BIT;
-+
-+ /*
-+ * div6 clocks require the divisor field to be non-zero or the
-+ * above CKSTP toggle silently fails. Ensure that the divisor
-+ * array is reset to its initial state on disable.
-+ */
-+ if (clk->flags & CLK_MASK_DIV_ON_DISABLE)
-+ val |= clk->div_mask;
-+
-+ sh_clk_write(val, clk);
-+}
-+
- /*
- * div6 support
- */
-@@ -174,44 +200,20 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
- return 0;
- }
-
--static int sh_clk_div6_enable(struct clk *clk)
--{
-- unsigned long value;
-- int ret;
--
-- ret = sh_clk_div_set_rate(clk, clk->rate);
-- if (ret == 0) {
-- value = sh_clk_read(clk);
-- value &= ~0x100; /* clear stop bit to enable clock */
-- sh_clk_write(value, clk);
-- }
-- return ret;
--}
--
--static void sh_clk_div6_disable(struct clk *clk)
--{
-- unsigned long value;
--
-- value = sh_clk_read(clk);
-- value |= 0x100; /* stop clock */
-- value |= clk->div_mask; /* VDIV bits must be non-zero, overwrite divider */
-- sh_clk_write(value, clk);
--}
--
- static struct sh_clk_ops sh_clk_div6_clk_ops = {
- .recalc = sh_clk_div_recalc,
- .round_rate = sh_clk_div_round_rate,
- .set_rate = sh_clk_div_set_rate,
-- .enable = sh_clk_div6_enable,
-- .disable = sh_clk_div6_disable,
-+ .enable = sh_clk_div_enable,
-+ .disable = sh_clk_div_disable,
- };
-
- static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
- .recalc = sh_clk_div_recalc,
- .round_rate = sh_clk_div_round_rate,
- .set_rate = sh_clk_div_set_rate,
-- .enable = sh_clk_div6_enable,
-- .disable = sh_clk_div6_disable,
-+ .enable = sh_clk_div_enable,
-+ .disable = sh_clk_div_disable,
- .set_parent = sh_clk_div6_set_parent,
- };
-
-@@ -325,17 +327,6 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
- return 0;
- }
-
--static int sh_clk_div4_enable(struct clk *clk)
--{
-- sh_clk_write(sh_clk_read(clk) & ~(1 << 8), clk);
-- return 0;
--}
--
--static void sh_clk_div4_disable(struct clk *clk)
--{
-- sh_clk_write(sh_clk_read(clk) | (1 << 8), clk);
--}
--
- static struct sh_clk_ops sh_clk_div4_clk_ops = {
- .recalc = sh_clk_div_recalc,
- .set_rate = sh_clk_div_set_rate,
-@@ -346,16 +337,16 @@ static struct sh_clk_ops sh_clk_div4_enable_clk_ops = {
- .recalc = sh_clk_div_recalc,
- .set_rate = sh_clk_div_set_rate,
- .round_rate = sh_clk_div_round_rate,
-- .enable = sh_clk_div4_enable,
-- .disable = sh_clk_div4_disable,
-+ .enable = sh_clk_div_enable,
-+ .disable = sh_clk_div_disable,
- };
-
- static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = {
- .recalc = sh_clk_div_recalc,
- .set_rate = sh_clk_div_set_rate,
- .round_rate = sh_clk_div_round_rate,
-- .enable = sh_clk_div4_enable,
-- .disable = sh_clk_div4_disable,
-+ .enable = sh_clk_div_enable,
-+ .disable = sh_clk_div_disable,
- .set_parent = sh_clk_div4_set_parent,
- };
-
-diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h
-index 35a04f1..5091091 100644
---- a/include/linux/sh_clk.h
-+++ b/include/linux/sh_clk.h
-@@ -69,6 +69,8 @@ struct clk {
- #define CLK_ENABLE_REG_16BIT BIT(2)
- #define CLK_ENABLE_REG_8BIT BIT(3)
-
-+#define CLK_MASK_DIV_ON_DISABLE BIT(4)
-+
- #define CLK_ENABLE_REG_MASK (CLK_ENABLE_REG_32BIT | \
- CLK_ENABLE_REG_16BIT | \
- CLK_ENABLE_REG_8BIT)
-@@ -173,7 +175,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
- { \
- .enable_reg = (void __iomem *)_reg, \
- .enable_bit = 0, /* unused */ \
-- .flags = _flags, \
-+ .flags = _flags | CLK_MASK_DIV_ON_DISABLE, \
- .div_mask = SH_CLK_DIV6_MSK, \
- .parent_table = _parents, \
- .parent_num = _num_parents, \
-@@ -187,7 +189,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
- .enable_reg = (void __iomem *)_reg, \
- .enable_bit = 0, /* unused */ \
- .div_mask = SH_CLK_DIV6_MSK, \
-- .flags = _flags, \
-+ .flags = _flags | CLK_MASK_DIV_ON_DISABLE, \
- }
-
- int sh_clk_div6_register(struct clk *clks, int nr);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From d50dd1ccae270ab558c081c9a7697137a92afdce Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Fri, 25 May 2012 16:43:42 +0900
-Subject: sh: clkfwk: Consolidate div6/div4 clk_ops definitions.
-
-Everything with the exception of the _reparent ops are now shared, so
-switch everything over to common types.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit e3c87607731e1a8937567e92a52eedee1bec622d)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/sh/clk/cpg.c | 42 +++++++++++++++++-------------------------
- 1 file changed, 17 insertions(+), 25 deletions(-)
-
-diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
-index 06537f2..eeaec79 100644
---- a/drivers/sh/clk/cpg.c
-+++ b/drivers/sh/clk/cpg.c
-@@ -148,6 +148,20 @@ static void sh_clk_div_disable(struct clk *clk)
- sh_clk_write(val, clk);
- }
-
-+static struct sh_clk_ops sh_clk_div_clk_ops = {
-+ .recalc = sh_clk_div_recalc,
-+ .set_rate = sh_clk_div_set_rate,
-+ .round_rate = sh_clk_div_round_rate,
-+};
-+
-+static struct sh_clk_ops sh_clk_div_enable_clk_ops = {
-+ .recalc = sh_clk_div_recalc,
-+ .set_rate = sh_clk_div_set_rate,
-+ .round_rate = sh_clk_div_round_rate,
-+ .enable = sh_clk_div_enable,
-+ .disable = sh_clk_div_disable,
-+};
-+
- /*
- * div6 support
- */
-@@ -200,14 +214,6 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
- return 0;
- }
-
--static struct sh_clk_ops sh_clk_div6_clk_ops = {
-- .recalc = sh_clk_div_recalc,
-- .round_rate = sh_clk_div_round_rate,
-- .set_rate = sh_clk_div_set_rate,
-- .enable = sh_clk_div_enable,
-- .disable = sh_clk_div_disable,
--};
--
- static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
- .recalc = sh_clk_div_recalc,
- .round_rate = sh_clk_div_round_rate,
-@@ -286,7 +292,7 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
-
- int __init sh_clk_div6_register(struct clk *clks, int nr)
- {
-- return sh_clk_div6_register_ops(clks, nr, &sh_clk_div6_clk_ops);
-+ return sh_clk_div6_register_ops(clks, nr, &sh_clk_div_enable_clk_ops);
- }
-
- int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
-@@ -327,20 +333,6 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
- return 0;
- }
-
--static struct sh_clk_ops sh_clk_div4_clk_ops = {
-- .recalc = sh_clk_div_recalc,
-- .set_rate = sh_clk_div_set_rate,
-- .round_rate = sh_clk_div_round_rate,
--};
--
--static struct sh_clk_ops sh_clk_div4_enable_clk_ops = {
-- .recalc = sh_clk_div_recalc,
-- .set_rate = sh_clk_div_set_rate,
-- .round_rate = sh_clk_div_round_rate,
-- .enable = sh_clk_div_enable,
-- .disable = sh_clk_div_disable,
--};
--
- static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = {
- .recalc = sh_clk_div_recalc,
- .set_rate = sh_clk_div_set_rate,
-@@ -385,14 +377,14 @@ static int __init sh_clk_div4_register_ops(struct clk *clks, int nr,
- int __init sh_clk_div4_register(struct clk *clks, int nr,
- struct clk_div4_table *table)
- {
-- return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops);
-+ return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div_clk_ops);
- }
-
- int __init sh_clk_div4_enable_register(struct clk *clks, int nr,
- struct clk_div4_table *table)
- {
- return sh_clk_div4_register_ops(clks, nr, table,
-- &sh_clk_div4_enable_clk_ops);
-+ &sh_clk_div_enable_clk_ops);
- }
-
- int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 14bb73c341fd8f669c5c48c59811c8e27f3fefce Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Fri, 25 May 2012 16:55:05 +0900
-Subject: sh: clkfwk: Consolidate div clk registration helper.
-
-This consolidates the div6/4 versions of the clk registration wrapper.
-The existing wrappers with their own sh_clk_ops are maintained for API
-compatability, though in the future it should be possible to be rid of
-them entirely.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 609d7558f232e583a31951c65a6ee43d81c65720)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/sh/clk/cpg.c | 182 +++++++++++++++++++++------------------------------
- 1 file changed, 75 insertions(+), 107 deletions(-)
-
-diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
-index eeaec79..07e9fb4 100644
---- a/drivers/sh/clk/cpg.c
-+++ b/drivers/sh/clk/cpg.c
-@@ -162,6 +162,72 @@ static struct sh_clk_ops sh_clk_div_enable_clk_ops = {
- .disable = sh_clk_div_disable,
- };
-
-+static int __init sh_clk_init_parent(struct clk *clk)
-+{
-+ u32 val;
-+
-+ if (clk->parent)
-+ return 0;
-+
-+ if (!clk->parent_table || !clk->parent_num)
-+ return 0;
-+
-+ if (!clk->src_width) {
-+ pr_err("sh_clk_init_parent: cannot select parent clock\n");
-+ return -EINVAL;
-+ }
-+
-+ val = (sh_clk_read(clk) >> clk->src_shift);
-+ val &= (1 << clk->src_width) - 1;
-+
-+ if (val >= clk->parent_num) {
-+ pr_err("sh_clk_init_parent: parent table size failed\n");
-+ return -EINVAL;
-+ }
-+
-+ clk_reparent(clk, clk->parent_table[val]);
-+ if (!clk->parent) {
-+ pr_err("sh_clk_init_parent: unable to set parent");
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static int __init sh_clk_div_register_ops(struct clk *clks, int nr,
-+ struct clk_div_table *table, struct sh_clk_ops *ops)
-+{
-+ struct clk *clkp;
-+ void *freq_table;
-+ int nr_divs = table->div_mult_table->nr_divisors;
-+ int freq_table_size = sizeof(struct cpufreq_frequency_table);
-+ int ret = 0;
-+ int k;
-+
-+ freq_table_size *= (nr_divs + 1);
-+ freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
-+ if (!freq_table) {
-+ pr_err("%s: unable to alloc memory\n", __func__);
-+ return -ENOMEM;
-+ }
-+
-+ for (k = 0; !ret && (k < nr); k++) {
-+ clkp = clks + k;
-+
-+ clkp->ops = ops;
-+ clkp->priv = table;
-+
-+ clkp->freq_table = freq_table + (k * freq_table_size);
-+ clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
-+
-+ ret = clk_register(clkp);
-+ if (ret == 0)
-+ ret = sh_clk_init_parent(clkp);
-+ }
-+
-+ return ret;
-+}
-+
- /*
- * div6 support
- */
-@@ -223,82 +289,16 @@ static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
- .set_parent = sh_clk_div6_set_parent,
- };
-
--static int __init sh_clk_init_parent(struct clk *clk)
--{
-- u32 val;
--
-- if (clk->parent)
-- return 0;
--
-- if (!clk->parent_table || !clk->parent_num)
-- return 0;
--
-- if (!clk->src_width) {
-- pr_err("sh_clk_init_parent: cannot select parent clock\n");
-- return -EINVAL;
-- }
--
-- val = (sh_clk_read(clk) >> clk->src_shift);
-- val &= (1 << clk->src_width) - 1;
--
-- if (val >= clk->parent_num) {
-- pr_err("sh_clk_init_parent: parent table size failed\n");
-- return -EINVAL;
-- }
--
-- clk_reparent(clk, clk->parent_table[val]);
-- if (!clk->parent) {
-- pr_err("sh_clk_init_parent: unable to set parent");
-- return -EINVAL;
-- }
--
-- return 0;
--}
--
--static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
-- struct sh_clk_ops *ops)
--{
-- struct clk *clkp;
-- void *freq_table;
-- struct clk_div_table *table = &sh_clk_div6_table;
-- int nr_divs = table->div_mult_table->nr_divisors;
-- int freq_table_size = sizeof(struct cpufreq_frequency_table);
-- int ret = 0;
-- int k;
--
-- freq_table_size *= (nr_divs + 1);
-- freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
-- if (!freq_table) {
-- pr_err("sh_clk_div6_register: unable to alloc memory\n");
-- return -ENOMEM;
-- }
--
-- for (k = 0; !ret && (k < nr); k++) {
-- clkp = clks + k;
--
-- clkp->ops = ops;
-- clkp->priv = table;
-- clkp->freq_table = freq_table + (k * freq_table_size);
-- clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
-- ret = clk_register(clkp);
-- if (ret < 0)
-- break;
--
-- ret = sh_clk_init_parent(clkp);
-- }
--
-- return ret;
--}
--
- int __init sh_clk_div6_register(struct clk *clks, int nr)
- {
-- return sh_clk_div6_register_ops(clks, nr, &sh_clk_div_enable_clk_ops);
-+ return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table,
-+ &sh_clk_div_enable_clk_ops);
- }
-
- int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
- {
-- return sh_clk_div6_register_ops(clks, nr,
-- &sh_clk_div6_reparent_clk_ops);
-+ return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table,
-+ &sh_clk_div6_reparent_clk_ops);
- }
-
- /*
-@@ -342,54 +342,22 @@ static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = {
- .set_parent = sh_clk_div4_set_parent,
- };
-
--static int __init sh_clk_div4_register_ops(struct clk *clks, int nr,
-- struct clk_div4_table *table, struct sh_clk_ops *ops)
--{
-- struct clk *clkp;
-- void *freq_table;
-- int nr_divs = table->div_mult_table->nr_divisors;
-- int freq_table_size = sizeof(struct cpufreq_frequency_table);
-- int ret = 0;
-- int k;
--
-- freq_table_size *= (nr_divs + 1);
-- freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
-- if (!freq_table) {
-- pr_err("sh_clk_div4_register: unable to alloc memory\n");
-- return -ENOMEM;
-- }
--
-- for (k = 0; !ret && (k < nr); k++) {
-- clkp = clks + k;
--
-- clkp->ops = ops;
-- clkp->priv = table;
--
-- clkp->freq_table = freq_table + (k * freq_table_size);
-- clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
--
-- ret = clk_register(clkp);
-- }
--
-- return ret;
--}
--
- int __init sh_clk_div4_register(struct clk *clks, int nr,
- struct clk_div4_table *table)
- {
-- return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div_clk_ops);
-+ return sh_clk_div_register_ops(clks, nr, table, &sh_clk_div_clk_ops);
- }
-
- int __init sh_clk_div4_enable_register(struct clk *clks, int nr,
- struct clk_div4_table *table)
- {
-- return sh_clk_div4_register_ops(clks, nr, table,
-- &sh_clk_div_enable_clk_ops);
-+ return sh_clk_div_register_ops(clks, nr, table,
-+ &sh_clk_div_enable_clk_ops);
- }
-
- int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
- struct clk_div4_table *table)
- {
-- return sh_clk_div4_register_ops(clks, nr, table,
-- &sh_clk_div4_reparent_clk_ops);
-+ return sh_clk_div_register_ops(clks, nr, table,
-+ &sh_clk_div4_reparent_clk_ops);
- }
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 0ee607349ba34cf8cdb94370c297faed58f64e39 Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Sat, 19 May 2012 15:11:41 +0900
-Subject: irqdomain: Support removal of IRQ domains.
-
-Now that IRQ domains are being used by modules it's necessary to support
-removing them, too. This adds a new irq_domain_remove() routine for doing
-the bulk of the heavy lifting. It's left as an exercise to the caller to
-ensure all mappings have been appropriatey disposed of before attempting
-to remove the domain.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-(cherry picked from commit 58ee99ada293b5ed971a023304fcfbc1a0ccdb1c)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- include/linux/irqdomain.h | 4 +++-
- kernel/irq/irqdomain.c | 61 +++++++++++++++++++++++++++++++++++++++++++++--
- 2 files changed, 62 insertions(+), 3 deletions(-)
-
-diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
-index c65740d..a796dbf 100644
---- a/include/linux/irqdomain.h
-+++ b/include/linux/irqdomain.h
-@@ -141,10 +141,12 @@ static inline struct irq_domain *irq_domain_add_legacy_isa(
- return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS, 0, 0, ops,
- host_data);
- }
-+
-+extern void irq_domain_remove(struct irq_domain *host);
-+
- extern struct irq_domain *irq_find_host(struct device_node *node);
- extern void irq_set_default_host(struct irq_domain *host);
-
--
- extern unsigned int irq_create_mapping(struct irq_domain *host,
- irq_hw_number_t hwirq);
- extern void irq_dispose_mapping(unsigned int virq);
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index 0e0ba5f..9cae0b2 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -56,6 +56,12 @@ static struct irq_domain *irq_domain_alloc(struct device_node *of_node,
- return domain;
- }
-
-+static void irq_domain_free(struct irq_domain *domain)
-+{
-+ of_node_put(domain->of_node);
-+ kfree(domain);
-+}
-+
- static void irq_domain_add(struct irq_domain *domain)
- {
- mutex_lock(&irq_domain_mutex);
-@@ -65,6 +71,58 @@ static void irq_domain_add(struct irq_domain *domain)
- domain->revmap_type, domain);
- }
-
-+/**
-+ * irq_domain_remove() - Remove an irq domain.
-+ * @domain: domain to remove
-+ *
-+ * This routine is used to remove an irq domain. The caller must ensure
-+ * that all mappings within the domain have been disposed of prior to
-+ * use, depending on the revmap type.
-+ */
-+void irq_domain_remove(struct irq_domain *domain)
-+{
-+ mutex_lock(&irq_domain_mutex);
-+
-+ switch (domain->revmap_type) {
-+ case IRQ_DOMAIN_MAP_LEGACY:
-+ /*
-+ * Legacy domains don't manage their own irq_desc
-+ * allocations, we expect the caller to handle irq_desc
-+ * freeing on their own.
-+ */
-+ break;
-+ case IRQ_DOMAIN_MAP_TREE:
-+ /*
-+ * radix_tree_delete() takes care of destroying the root
-+ * node when all entries are removed. Shout if there are
-+ * any mappings left.
-+ */
-+ WARN_ON(domain->revmap_data.tree.height);
-+ break;
-+ case IRQ_DOMAIN_MAP_LINEAR:
-+ kfree(domain->revmap_data.linear.revmap);
-+ domain->revmap_data.linear.size = 0;
-+ break;
-+ case IRQ_DOMAIN_MAP_NOMAP:
-+ break;
-+ }
-+
-+ list_del(&domain->link);
-+
-+ /*
-+ * If the going away domain is the default one, reset it.
-+ */
-+ if (unlikely(irq_default_domain == domain))
-+ irq_set_default_host(NULL);
-+
-+ mutex_unlock(&irq_domain_mutex);
-+
-+ pr_debug("irq: Removed domain of type %d @0x%p\n",
-+ domain->revmap_type, domain);
-+
-+ irq_domain_free(domain);
-+}
-+
- static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
- irq_hw_number_t hwirq)
- {
-@@ -117,8 +175,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
-
- if (WARN_ON(!irq_data || irq_data->domain)) {
- mutex_unlock(&irq_domain_mutex);
-- of_node_put(domain->of_node);
-- kfree(domain);
-+ irq_domain_free(domain);
- return NULL;
- }
- }
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From fd54923383b7dee6af8b53a91d2c6768d2726d77 Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Sat, 19 May 2012 15:11:42 +0900
-Subject: irqdomain: Export remaining public API symbols.
-
-modules making use of irq domains at the very least need access to the
-add/remove/lookup routines, though there's nothing preventing them from
-using the remainder of the public API, either.
-
-The current set of exports seem primarily geared at DT-enabled platforms
-using DT-backed IRQ domains, where many of the API accesses are hidden
-away in OF code. The non-DT cases need to do most of this on their own.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-(cherry picked from commit ecd84eb20a08841197d6bbda5961dcf5f4e424fc)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- kernel/irq/irqdomain.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index 9cae0b2..01d4a0d 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -122,6 +122,7 @@ void irq_domain_remove(struct irq_domain *domain)
-
- irq_domain_free(domain);
- }
-+EXPORT_SYMBOL_GPL(irq_domain_remove);
-
- static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
- irq_hw_number_t hwirq)
-@@ -209,6 +210,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
- irq_domain_add(domain);
- return domain;
- }
-+EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
-
- /**
- * irq_domain_add_linear() - Allocate and register a legacy revmap irq_domain.
-@@ -238,6 +240,7 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
- irq_domain_add(domain);
- return domain;
- }
-+EXPORT_SYMBOL_GPL(irq_domain_add_linear);
-
- struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
- unsigned int max_irq,
-@@ -252,6 +255,7 @@ struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
- }
- return domain;
- }
-+EXPORT_SYMBOL_GPL(irq_domain_add_nomap);
-
- /**
- * irq_domain_add_tree()
-@@ -273,6 +277,7 @@ struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
- }
- return domain;
- }
-+EXPORT_SYMBOL_GPL(irq_domain_add_tree);
-
- /**
- * irq_find_host() - Locates a domain for a given device node
-@@ -320,6 +325,7 @@ void irq_set_default_host(struct irq_domain *domain)
-
- irq_default_domain = domain;
- }
-+EXPORT_SYMBOL_GPL(irq_set_default_host);
-
- static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
- irq_hw_number_t hwirq)
-@@ -378,6 +384,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
-
- return virq;
- }
-+EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
-
- /**
- * irq_create_mapping() - Map a hardware interrupt into linux irq space
-@@ -617,6 +624,7 @@ unsigned int irq_radix_revmap_lookup(struct irq_domain *domain,
- */
- return irq_data ? irq_data->irq : irq_find_mapping(domain, hwirq);
- }
-+EXPORT_SYMBOL_GPL(irq_radix_revmap_lookup);
-
- /**
- * irq_radix_revmap_insert() - Insert a hw irq to linux irq number mapping.
-@@ -641,6 +649,7 @@ void irq_radix_revmap_insert(struct irq_domain *domain, unsigned int virq,
- mutex_unlock(&revmap_trees_mutex);
- }
- }
-+EXPORT_SYMBOL_GPL(irq_radix_revmap_insert);
-
- /**
- * irq_linear_revmap() - Find a linux irq from a hw irq number.
-@@ -674,6 +683,7 @@ unsigned int irq_linear_revmap(struct irq_domain *domain,
-
- return revmap[hwirq];
- }
-+EXPORT_SYMBOL_GPL(irq_linear_revmap);
-
- #ifdef CONFIG_IRQ_DOMAIN_DEBUG
- static int virq_debug_show(struct seq_file *m, void *private)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 5cfad4570d46fe50c16ce73dcf3f2d6bf76f2b33 Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Sat, 19 May 2012 15:11:43 +0900
-Subject: irqdomain: Make irq_domain_simple_map() static.
-
-Presently irq_domain_simple_map() isn't labelled as static, but there's
-no definition for it in the public irqdomain header either. At present
-all in-tree ->map users have meaningful work to do, and all others are
-using irq_domain_simple_ops directly. Make it static for now, as it can
-always be exported and added to the public API later.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-(cherry picked from commit 5c5806e50b9fd4ca435acdf0eceddda64da9be5b)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- kernel/irq/irqdomain.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index 01d4a0d..92e06442 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -758,8 +758,8 @@ static int __init irq_debugfs_init(void)
- __initcall(irq_debugfs_init);
- #endif /* CONFIG_IRQ_DOMAIN_DEBUG */
-
--int irq_domain_simple_map(struct irq_domain *d, unsigned int irq,
-- irq_hw_number_t hwirq)
-+static int irq_domain_simple_map(struct irq_domain *d, unsigned int irq,
-+ irq_hw_number_t hwirq)
- {
- return 0;
- }
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 4eb9577004521127daa39444ae35279e8f07eccd Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Sat, 19 May 2012 15:11:45 +0900
-Subject: irqdomain: Kill off duplicate definitions.
-
-Presently irqdomain.h has duplicate definitions for irq_find_host() and
-irq_set_default_host(), presumably from merge damage. Kill off the
-duplicates.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-(cherry picked from commit cb5557bec9f14d05204a9014ae1b23aca8b04f1d)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- include/linux/irqdomain.h | 3 ---
- 1 file changed, 3 deletions(-)
-
-diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
-index a796dbf..5abb533 100644
---- a/include/linux/irqdomain.h
-+++ b/include/linux/irqdomain.h
-@@ -144,9 +144,6 @@ static inline struct irq_domain *irq_domain_add_legacy_isa(
-
- extern void irq_domain_remove(struct irq_domain *host);
-
--extern struct irq_domain *irq_find_host(struct device_node *node);
--extern void irq_set_default_host(struct irq_domain *host);
--
- extern unsigned int irq_create_mapping(struct irq_domain *host,
- irq_hw_number_t hwirq);
- extern void irq_dispose_mapping(unsigned int virq);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From acccf0bbf24e13673a3d5d76e49f389d736d4882 Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Sat, 19 May 2012 15:11:47 +0900
-Subject: irqdomain: trivial pr_fmt conversion.
-
-Convert to pr_fmt before things start to get out of hand and some
-janitors start getting overly excited.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-(cherry picked from commit 54a9058860f2b7ed8d2fe5bf7be19bb901866dc2)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- kernel/irq/irqdomain.c | 32 +++++++++++++++++---------------
- 1 file changed, 17 insertions(+), 15 deletions(-)
-
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index 92e06442..9a6e8a8 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -1,3 +1,5 @@
-+#define pr_fmt(fmt) "irq: " fmt
-+
- #include <linux/debugfs.h>
- #include <linux/hardirq.h>
- #include <linux/interrupt.h>
-@@ -67,7 +69,7 @@ static void irq_domain_add(struct irq_domain *domain)
- mutex_lock(&irq_domain_mutex);
- list_add(&domain->link, &irq_domain_list);
- mutex_unlock(&irq_domain_mutex);
-- pr_debug("irq: Allocated domain of type %d @0x%p\n",
-+ pr_debug("Allocated domain of type %d @0x%p\n",
- domain->revmap_type, domain);
- }
-
-@@ -117,7 +119,7 @@ void irq_domain_remove(struct irq_domain *domain)
-
- mutex_unlock(&irq_domain_mutex);
-
-- pr_debug("irq: Removed domain of type %d @0x%p\n",
-+ pr_debug("Removed domain of type %d @0x%p\n",
- domain->revmap_type, domain);
-
- irq_domain_free(domain);
-@@ -321,7 +323,7 @@ EXPORT_SYMBOL_GPL(irq_find_host);
- */
- void irq_set_default_host(struct irq_domain *domain)
- {
-- pr_debug("irq: Default domain set to @0x%p\n", domain);
-+ pr_debug("Default domain set to @0x%p\n", domain);
-
- irq_default_domain = domain;
- }
-@@ -335,7 +337,7 @@ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
- irq_data->hwirq = hwirq;
- irq_data->domain = domain;
- if (domain->ops->map(domain, virq, hwirq)) {
-- pr_debug("irq: -> mapping failed, freeing\n");
-+ pr_debug("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq);
- irq_data->domain = NULL;
- irq_data->hwirq = 0;
- return -1;
-@@ -366,7 +368,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
-
- virq = irq_alloc_desc_from(1, 0);
- if (!virq) {
-- pr_debug("irq: create_direct virq allocation failed\n");
-+ pr_debug("create_direct virq allocation failed\n");
- return 0;
- }
- if (virq >= domain->revmap_data.nomap.max_irq) {
-@@ -375,7 +377,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
- irq_free_desc(virq);
- return 0;
- }
-- pr_debug("irq: create_direct obtained virq %d\n", virq);
-+ pr_debug("create_direct obtained virq %d\n", virq);
-
- if (irq_setup_virq(domain, virq, virq)) {
- irq_free_desc(virq);
-@@ -402,23 +404,23 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
- unsigned int hint;
- int virq;
-
-- pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
-+ pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
-
- /* Look for default domain if nececssary */
- if (domain == NULL)
- domain = irq_default_domain;
- if (domain == NULL) {
-- printk(KERN_WARNING "irq_create_mapping called for"
-- " NULL domain, hwirq=%lx\n", hwirq);
-+ pr_warning("irq_create_mapping called for"
-+ " NULL domain, hwirq=%lx\n", hwirq);
- WARN_ON(1);
- return 0;
- }
-- pr_debug("irq: -> using domain @%p\n", domain);
-+ pr_debug("-> using domain @%p\n", domain);
-
- /* Check if mapping already exists */
- virq = irq_find_mapping(domain, hwirq);
- if (virq) {
-- pr_debug("irq: -> existing mapping on virq %d\n", virq);
-+ pr_debug("-> existing mapping on virq %d\n", virq);
- return virq;
- }
-
-@@ -434,7 +436,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
- if (virq <= 0)
- virq = irq_alloc_desc_from(1, 0);
- if (virq <= 0) {
-- pr_debug("irq: -> virq allocation failed\n");
-+ pr_debug("-> virq allocation failed\n");
- return 0;
- }
-
-@@ -444,7 +446,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
- return 0;
- }
-
-- pr_debug("irq: irq %lu on domain %s mapped to virtual irq %u\n",
-+ pr_debug("irq %lu on domain %s mapped to virtual irq %u\n",
- hwirq, domain->of_node ? domain->of_node->full_name : "null", virq);
-
- return virq;
-@@ -473,8 +475,8 @@ unsigned int irq_create_of_mapping(struct device_node *controller,
- if (intsize > 0)
- return intspec[0];
- #endif
-- printk(KERN_WARNING "irq: no irq domain found for %s !\n",
-- controller->full_name);
-+ pr_warning("no irq domain found for %s !\n",
-+ controller->full_name);
- return 0;
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b1308eaacaa94b41421129c2cd44b69e4e83f2de Mon Sep 17 00:00:00 2001
-From: Mark Brown <broonie@opensource.wolfsonmicro.com>
-Date: Sat, 19 May 2012 12:15:35 +0100
-Subject: irqdomain: Document size parameter of irq_domain_add_linear()
-
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-(cherry picked from commit a87487e687ceafdc696b8cb1fb27e37cc463586b)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- kernel/irq/irqdomain.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index 9a6e8a8..41c1564 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -217,6 +217,7 @@ EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
- /**
- * irq_domain_add_linear() - Allocate and register a legacy revmap irq_domain.
- * @of_node: pointer to interrupt controller's device tree node.
-+ * @size: Number of interrupts in the domain.
- * @ops: map/unmap domain callbacks
- * @host_data: Controller private data pointer
- */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e572a45ad1741b29429e38cfd2be60e23e1ebc57 Mon Sep 17 00:00:00 2001
-From: Grant Likely <grant.likely@secretlab.ca>
-Date: Fri, 15 Jun 2012 11:50:25 -0600
-Subject: devicetree: add helper inline for retrieving a node's full name
-
-The pattern (np ? np->full_name : "<none>") is rather common in the
-kernel, but can also make for quite long lines. This patch adds a new
-inline function, of_node_full_name() so that the test for a valid node
-pointer doesn't need to be open coded at all call sites.
-
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-Cc: Paul Mundt <lethal@linux-sh.org>
-Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Signed-off-by: Rob Herring <rob.herring@calxeda.com>
-(cherry picked from commit 74a7f08448adea6cb47cd9b260c98ff168117e92)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/microblaze/pci/pci-common.c | 6 ++----
- arch/powerpc/kernel/pci-common.c | 6 ++----
- arch/powerpc/kernel/vio.c | 5 ++---
- arch/powerpc/platforms/cell/iommu.c | 3 +--
- arch/powerpc/platforms/pseries/iommu.c | 2 +-
- arch/sparc/kernel/of_device_64.c | 2 +-
- drivers/of/base.c | 2 +-
- drivers/of/irq.c | 2 +-
- include/linux/of.h | 10 ++++++++++
- kernel/irq/irqdomain.c | 8 ++++----
- 10 files changed, 25 insertions(+), 21 deletions(-)
-
---- a/arch/microblaze/pci/pci-common.c
-+++ b/arch/microblaze/pci/pci-common.c
-@@ -249,8 +249,7 @@ int pci_read_irq_line(struct pci_dev *pc
- } else {
- pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
- oirq.size, oirq.specifier[0], oirq.specifier[1],
-- oirq.controller ? oirq.controller->full_name :
-- "<default>");
-+ of_node_full_name(oirq.controller));
-
- virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
- oirq.size);
-@@ -1492,8 +1491,7 @@ static void __devinit pcibios_scan_phb(s
- struct pci_bus *bus;
- struct device_node *node = hose->dn;
-
-- pr_debug("PCI: Scanning PHB %s\n",
-- node ? node->full_name : "<NO NAME>");
-+ pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(node));
-
- pcibios_setup_phb_resources(hose, &resources);
-
---- a/arch/powerpc/kernel/pci-common.c
-+++ b/arch/powerpc/kernel/pci-common.c
-@@ -248,8 +248,7 @@ static int pci_read_irq_line(struct pci_
- } else {
- pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
- oirq.size, oirq.specifier[0], oirq.specifier[1],
-- oirq.controller ? oirq.controller->full_name :
-- "<default>");
-+ of_node_full_name(oirq.controller));
-
- virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
- oirq.size);
-@@ -1628,8 +1627,7 @@ void __devinit pcibios_scan_phb(struct p
- struct device_node *node = hose->dn;
- int mode;
-
-- pr_debug("PCI: Scanning PHB %s\n",
-- node ? node->full_name : "<NO NAME>");
-+ pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(node));
-
- /* Get some IO space for the new PHB */
- pcibios_setup_phb_io_space(hose);
---- a/arch/powerpc/kernel/vio.c
-+++ b/arch/powerpc/kernel/vio.c
-@@ -1194,8 +1194,7 @@ static void __devinit vio_dev_release(st
- struct iommu_table *tbl = get_iommu_table_base(dev);
-
- if (tbl)
-- iommu_free_table(tbl, dev->of_node ?
-- dev->of_node->full_name : dev_name(dev));
-+ iommu_free_table(tbl, of_node_full_name(dev->of_node));
- of_node_put(dev->of_node);
- kfree(to_vio_dev(dev));
- }
-@@ -1331,7 +1330,7 @@ static ssize_t devspec_show(struct devic
- {
- struct device_node *of_node = dev->of_node;
-
-- return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none");
-+ return sprintf(buf, "%s\n", of_node_full_name(of_node));
- }
-
- static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
---- a/arch/powerpc/platforms/cell/iommu.c
-+++ b/arch/powerpc/platforms/cell/iommu.c
-@@ -552,8 +552,7 @@ static struct iommu_table *cell_get_iomm
- iommu = cell_iommu_for_node(dev_to_node(dev));
- if (iommu == NULL || list_empty(&iommu->windows)) {
- printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n",
-- dev->of_node ? dev->of_node->full_name : "?",
-- dev_to_node(dev));
-+ of_node_full_name(dev->of_node), dev_to_node(dev));
- return NULL;
- }
- window = list_entry(iommu->windows.next, struct iommu_window, list);
---- a/arch/powerpc/platforms/pseries/iommu.c
-+++ b/arch/powerpc/platforms/pseries/iommu.c
-@@ -1051,7 +1051,7 @@ static void pci_dma_dev_setup_pSeriesLP(
- if (!pdn || !PCI_DN(pdn)) {
- printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: "
- "no DMA window found for pci dev=%s dn=%s\n",
-- pci_name(dev), dn? dn->full_name : "<null>");
-+ pci_name(dev), of_node_full_name(dn));
- return;
- }
- pr_debug(" parent is %s\n", pdn->full_name);
---- a/arch/sparc/kernel/of_device_64.c
-+++ b/arch/sparc/kernel/of_device_64.c
-@@ -580,7 +580,7 @@ static unsigned int __init build_one_dev
- printk("%s: Apply [%s:%x] imap --> [%s:%x]\n",
- op->dev.of_node->full_name,
- pp->full_name, this_orig_irq,
-- (iret ? iret->full_name : "NULL"), irq);
-+ of_node_full_name(iret), irq);
-
- if (!iret)
- break;
---- a/drivers/of/base.c
-+++ b/drivers/of/base.c
-@@ -1173,7 +1173,7 @@ static void of_alias_add(struct alias_pr
- ap->stem[stem_len] = 0;
- list_add_tail(&ap->link, &aliases_lookup);
- pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
-- ap->alias, ap->stem, ap->id, np ? np->full_name : NULL);
-+ ap->alias, ap->stem, ap->id, of_node_full_name(np));
- }
-
- /**
---- a/drivers/of/irq.c
-+++ b/drivers/of/irq.c
-@@ -255,7 +255,7 @@ int of_irq_map_raw(struct device_node *p
-
- skiplevel:
- /* Iterate again with new parent */
-- pr_debug(" -> new parent: %s\n", newpar ? newpar->full_name : "<>");
-+ pr_debug(" -> new parent: %s\n", of_node_full_name(newpar));
- of_node_put(ipar);
- ipar = newpar;
- newpar = NULL;
---- a/include/linux/of.h
-+++ b/include/linux/of.h
-@@ -163,6 +163,11 @@ static inline int of_node_to_nid(struct
- #define of_node_to_nid of_node_to_nid
- #endif
-
-+static inline const char* of_node_full_name(struct device_node *np)
-+{
-+ return np ? np->full_name : "<no-node>";
-+}
-+
- extern struct device_node *of_find_node_by_name(struct device_node *from,
- const char *name);
- #define for_each_node_by_name(dn, name) \
-@@ -261,6 +266,11 @@ extern void of_detach_node(struct device
- #define of_match_ptr(_ptr) (_ptr)
- #else /* CONFIG_OF */
-
-+static inline const char* of_node_full_name(struct device_node *np)
-+{
-+ return "<no-node>";
-+}
-+
- static inline bool of_have_populated_dt(void)
- {
- return false;
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -448,7 +448,7 @@ unsigned int irq_create_mapping(struct i
- }
-
- pr_debug("irq %lu on domain %s mapped to virtual irq %u\n",
-- hwirq, domain->of_node ? domain->of_node->full_name : "null", virq);
-+ hwirq, of_node_full_name(domain->of_node), virq);
-
- return virq;
- }
-@@ -477,7 +477,7 @@ unsigned int irq_create_of_mapping(struc
- return intspec[0];
- #endif
- pr_warning("no irq domain found for %s !\n",
-- controller->full_name);
-+ of_node_full_name(controller));
- return 0;
- }
-
-@@ -725,8 +725,8 @@ static int virq_debug_show(struct seq_fi
- data = irq_desc_get_chip_data(desc);
- seq_printf(m, data ? "0x%p " : " %p ", data);
-
-- if (desc->irq_data.domain && desc->irq_data.domain->of_node)
-- p = desc->irq_data.domain->of_node->full_name;
-+ if (desc->irq_data.domain)
-+ p = of_node_full_name(desc->irq_data.domain->of_node);
- else
- p = none;
- seq_printf(m, "%s\n", p);
+++ /dev/null
-From 249521995c6f0647ab54b64f89103ba3389edfea Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Sun, 3 Jun 2012 22:04:34 -0700
-Subject: irqdomain: Simple NUMA awareness.
-
-While common irqdesc allocation is node aware, the irqdomain code is not.
-
-Presently we observe a number of regressions/inconsistencies on
-NUMA-capable platforms:
-
-- Platforms using irqdomains with legacy mappings, where the
- irq_descs are allocated node-local and the irqdomain data
- structure is not.
-
-- Drivers implementing irqdomains will lose node locality
- regardless of the underlying struct device's node id.
-
-This plugs in NUMA node id proliferation across the various allocation
-callsites by way of_node_to_nid() node lookup. While of_node_to_nid()
-does the right thing for OF-capable platforms it doesn't presently handle
-the non-DT case. This is trivially dealt with by simply wraping in to
-numa_node_id() unconditionally.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Rob Herring <rob.herring@calxeda.com>
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-(cherry picked from commit 5ca4db61e859526b2dbee3bcea3626d3de49a0b2)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- include/linux/of.h | 15 ++++++++++-----
- kernel/irq/irqdomain.c | 13 ++++++++-----
- 2 files changed, 18 insertions(+), 10 deletions(-)
-
-diff --git a/include/linux/of.h b/include/linux/of.h
-index 284d117..e24c5cc 100644
---- a/include/linux/of.h
-+++ b/include/linux/of.h
-@@ -21,6 +21,7 @@
- #include <linux/kref.h>
- #include <linux/mod_devicetable.h>
- #include <linux/spinlock.h>
-+#include <linux/topology.h>
-
- #include <asm/byteorder.h>
- #include <asm/errno.h>
-@@ -158,11 +159,6 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
-
- #define OF_BAD_ADDR ((u64)-1)
-
--#ifndef of_node_to_nid
--static inline int of_node_to_nid(struct device_node *np) { return -1; }
--#define of_node_to_nid of_node_to_nid
--#endif
--
- static inline const char* of_node_full_name(struct device_node *np)
- {
- return np ? np->full_name : "<no-node>";
-@@ -361,6 +357,15 @@ static inline int of_machine_is_compatible(const char *compat)
- #define of_match_node(_matches, _node) NULL
- #endif /* CONFIG_OF */
-
-+#ifndef of_node_to_nid
-+static inline int of_node_to_nid(struct device_node *np)
-+{
-+ return numa_node_id();
-+}
-+
-+#define of_node_to_nid of_node_to_nid
-+#endif
-+
- /**
- * of_property_read_bool - Findfrom a property
- * @np: device node from which the property value is to be read.
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index 38c5eb8..79ae0eb 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -10,6 +10,7 @@
- #include <linux/mutex.h>
- #include <linux/of.h>
- #include <linux/of_address.h>
-+#include <linux/topology.h>
- #include <linux/seq_file.h>
- #include <linux/slab.h>
- #include <linux/smp.h>
-@@ -45,7 +46,8 @@ static struct irq_domain *irq_domain_alloc(struct device_node *of_node,
- {
- struct irq_domain *domain;
-
-- domain = kzalloc(sizeof(*domain), GFP_KERNEL);
-+ domain = kzalloc_node(sizeof(*domain), GFP_KERNEL,
-+ of_node_to_nid(of_node));
- if (WARN_ON(!domain))
- return NULL;
-
-@@ -229,7 +231,8 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
- struct irq_domain *domain;
- unsigned int *revmap;
-
-- revmap = kzalloc(sizeof(*revmap) * size, GFP_KERNEL);
-+ revmap = kzalloc_node(sizeof(*revmap) * size, GFP_KERNEL,
-+ of_node_to_nid(of_node));
- if (WARN_ON(!revmap))
- return NULL;
-
-@@ -367,7 +370,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
- BUG_ON(domain == NULL);
- WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP);
-
-- virq = irq_alloc_desc_from(1, 0);
-+ virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node));
- if (!virq) {
- pr_debug("create_direct virq allocation failed\n");
- return 0;
-@@ -433,9 +436,9 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
- hint = hwirq % nr_irqs;
- if (hint == 0)
- hint++;
-- virq = irq_alloc_desc_from(hint, 0);
-+ virq = irq_alloc_desc_from(hint, of_node_to_nid(domain->of_node));
- if (virq <= 0)
-- virq = irq_alloc_desc_from(1, 0);
-+ virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node));
- if (virq <= 0) {
- pr_debug("-> virq allocation failed\n");
- return 0;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e023d517b8a6bdbb4083914ec6519fa6486d437d Mon Sep 17 00:00:00 2001
-From: Grant Likely <grant.likely@secretlab.ca>
-Date: Sun, 3 Jun 2012 22:04:35 -0700
-Subject: irqdomain: Remove unnecessary test for IRQ_DOMAIN_MAP_LEGACY
-
-Where irq_domain_associate() is called in irq_create_mapping, there is
-no need to test for IRQ_DOMAIN_MAP_LEGACY because it is already tested
-for earlier in the routine.
-
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-Cc: Paul Mundt <lethal@linux-sh.org>
-Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Rob Herring <rob.herring@calxeda.com>
-
-(cherry picked from commit 732557047128e5c200c3590efba39f10ac46bcb2)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- kernel/irq/irqdomain.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index 79ae0eb..b1f774c 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -445,8 +445,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
- }
-
- if (irq_setup_virq(domain, virq, hwirq)) {
-- if (domain->revmap_type != IRQ_DOMAIN_MAP_LEGACY)
-- irq_free_desc(virq);
-+ irq_free_desc(virq);
- return 0;
- }
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 421754810bdf0283c6f75bffdc96a0795bdf340d Mon Sep 17 00:00:00 2001
-From: Grant Likely <grant.likely@secretlab.ca>
-Date: Sun, 3 Jun 2012 22:04:39 -0700
-Subject: irqdomain: Make ops->map hook optional
-
-There isn't a really compelling reason to force ->map to be populated,
-so allow it to be left unset.
-
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-Cc: Paul Mundt <lethal@linux-sh.org>
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Rob Herring <rob.herring@calxeda.com>
-(cherry picked from commit aed98048bd1c83469d96932c1901e867d9ba519a)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- kernel/irq/irqdomain.c | 14 ++++----------
- 1 file changed, 4 insertions(+), 10 deletions(-)
-
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index b1f774c..d3968e9 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -205,7 +205,8 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
- * one can then use irq_create_mapping() to
- * explicitly change them
- */
-- ops->map(domain, irq, hwirq);
-+ if (ops->map)
-+ ops->map(domain, irq, hwirq);
-
- /* Clear norequest flags */
- irq_clear_status_flags(irq, IRQ_NOREQUEST);
-@@ -340,8 +341,8 @@ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
-
- irq_data->hwirq = hwirq;
- irq_data->domain = domain;
-- if (domain->ops->map(domain, virq, hwirq)) {
-- pr_debug("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq);
-+ if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) {
-+ pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq);
- irq_data->domain = NULL;
- irq_data->hwirq = 0;
- return -1;
-@@ -763,12 +764,6 @@ static int __init irq_debugfs_init(void)
- __initcall(irq_debugfs_init);
- #endif /* CONFIG_IRQ_DOMAIN_DEBUG */
-
--static int irq_domain_simple_map(struct irq_domain *d, unsigned int irq,
-- irq_hw_number_t hwirq)
--{
-- return 0;
--}
--
- /**
- * irq_domain_xlate_onecell() - Generic xlate for direct one cell bindings
- *
-@@ -831,7 +826,6 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d,
- EXPORT_SYMBOL_GPL(irq_domain_xlate_onetwocell);
-
- const struct irq_domain_ops irq_domain_simple_ops = {
-- .map = irq_domain_simple_map,
- .xlate = irq_domain_xlate_onetwocell,
- };
- EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From c9055637ff0ca4029e5bf18053b65172b27f63b0 Mon Sep 17 00:00:00 2001
-From: Mark Brown <broonie@opensource.wolfsonmicro.com>
-Date: Thu, 5 Jul 2012 12:19:19 +0100
-Subject: irq_domain: Standardise legacy/linear domain selection
-
-A large proportion of interrupt controllers that support legacy mappings
-do so because non-DT systems need to use fixed IRQ numbers when registering
-devices via buses but can otherwise use a linear mapping. The interrupt
-controller itself typically is not affected by the mapping used and best
-practice is to use a linear mapping where possible so drivers frequently
-select at runtime depending on if a legacy range has been allocated to
-them.
-
-Standardise this behaviour by providing irq_domain_register_simple() which
-will allocate a linear mapping unless a positive first_irq is provided in
-which case it will fall back to a legacy mapping. This helps make best
-practice for irq_domain adoption clearer.
-
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-(cherry picked from commit 781d0f46d81e2c26c70649903b503bcfe817efc8)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- Documentation/IRQ-domain.txt | 5 +++++
- include/linux/irqdomain.h | 5 +++++
- kernel/irq/irqdomain.c | 30 ++++++++++++++++++++++++++++++
- 3 files changed, 40 insertions(+)
-
-diff --git a/Documentation/IRQ-domain.txt b/Documentation/IRQ-domain.txt
-index 27dcaab..1401cec 100644
---- a/Documentation/IRQ-domain.txt
-+++ b/Documentation/IRQ-domain.txt
-@@ -93,6 +93,7 @@ Linux IRQ number into the hardware.
- Most drivers cannot use this mapping.
-
- ==== Legacy ====
-+irq_domain_add_simple()
- irq_domain_add_legacy()
- irq_domain_add_legacy_isa()
-
-@@ -115,3 +116,7 @@ The legacy map should only be used if fixed IRQ mappings must be
- supported. For example, ISA controllers would use the legacy map for
- mapping Linux IRQs 0-15 so that existing ISA drivers get the correct IRQ
- numbers.
-+
-+Most users of legacy mappings should use irq_domain_add_simple() which
-+will use a legacy domain only if an IRQ range is supplied by the
-+system and will otherwise use a linear domain mapping.
-diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
-index 5abb533..17b60be 100644
---- a/include/linux/irqdomain.h
-+++ b/include/linux/irqdomain.h
-@@ -112,6 +112,11 @@ struct irq_domain {
- };
-
- #ifdef CONFIG_IRQ_DOMAIN
-+struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
-+ unsigned int size,
-+ unsigned int first_irq,
-+ const struct irq_domain_ops *ops,
-+ void *host_data);
- struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
- unsigned int size,
- unsigned int first_irq,
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index d3968e9..0c51958 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -140,6 +140,36 @@ static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
- }
-
- /**
-+ * irq_domain_add_simple() - Allocate and register a simple irq_domain.
-+ * @of_node: pointer to interrupt controller's device tree node.
-+ * @size: total number of irqs in mapping
-+ * @first_irq: first number of irq block assigned to the domain
-+ * @ops: map/unmap domain callbacks
-+ * @host_data: Controller private data pointer
-+ *
-+ * Allocates a legacy irq_domain if irq_base is positive or a linear
-+ * domain otherwise.
-+ *
-+ * This is intended to implement the expected behaviour for most
-+ * interrupt controllers which is that a linear mapping should
-+ * normally be used unless the system requires a legacy mapping in
-+ * order to support supplying interrupt numbers during non-DT
-+ * registration of devices.
-+ */
-+struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
-+ unsigned int size,
-+ unsigned int first_irq,
-+ const struct irq_domain_ops *ops,
-+ void *host_data)
-+{
-+ if (first_irq > 0)
-+ return irq_domain_add_legacy(of_node, size, first_irq, 0,
-+ ops, host_data);
-+ else
-+ return irq_domain_add_linear(of_node, size, ops, host_data);
-+}
-+
-+/**
- * irq_domain_add_legacy() - Allocate and register a legacy revmap irq_domain.
- * @of_node: pointer to interrupt controller's device tree node.
- * @size: total number of irqs in legacy mapping
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 709c8d22171cc90cc30e4528312bcc0e31b870b2 Mon Sep 17 00:00:00 2001
-From: Dong Aisheng <dong.aisheng@linaro.org>
-Date: Wed, 20 Jun 2012 17:00:30 +0800
-Subject: irq_domain: correct a minor wrong comment for linear revmap
-
-The revmap type should be linear for irq_domain_add_linear function.
-
-Signed-off-by: Dong Aisheng <dong.aisheng@linaro.org>
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-(cherry picked from commit 22076c7712be29a602de45b1c573f31adbd428a9)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- kernel/irq/irqdomain.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index 0c51958..622fdf4 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -248,7 +248,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
- EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
-
- /**
-- * irq_domain_add_linear() - Allocate and register a legacy revmap irq_domain.
-+ * irq_domain_add_linear() - Allocate and register a linear revmap irq_domain.
- * @of_node: pointer to interrupt controller's device tree node.
- * @size: Number of interrupts in the domain.
- * @ops: map/unmap domain callbacks
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 077e92f0d6cc5991a052116eb8d66539dd49a995 Mon Sep 17 00:00:00 2001
-From: Grant Likely <grant.likely@secretlab.ca>
-Date: Sun, 3 Jun 2012 22:04:36 -0700
-Subject: irqdomain: Always update revmap when setting up a virq
-
-At irq_setup_virq() time all of the data needed to update the reverse
-map is available, but the current code ignores it and relies upon the
-slow path to insert revmap records. This patch adds revmap updating
-to the setup path so the slow path will no longer be necessary.
-
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-Cc: Paul Mundt <lethal@linux-sh.org>
-Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Rob Herring <rob.herring@calxeda.com>
-(cherry picked from commit 2a71a1a9da40dfbd5b23d4312aa1641385581f4a)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/powerpc/sysdev/xics/xics-common.c | 3 ---
- kernel/irq/irqdomain.c | 12 ++++++++++++
- 2 files changed, 12 insertions(+), 3 deletions(-)
-
-diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c
-index cd1d18d..9049d9f 100644
---- a/arch/powerpc/sysdev/xics/xics-common.c
-+++ b/arch/powerpc/sysdev/xics/xics-common.c
-@@ -329,9 +329,6 @@ static int xics_host_map(struct irq_domain *h, unsigned int virq,
-
- pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
-
-- /* Insert the interrupt mapping into the radix tree for fast lookup */
-- irq_radix_revmap_insert(xics_host, virq, hw);
--
- /* They aren't all level sensitive but we just don't really know */
- irq_set_status_flags(virq, IRQ_LEVEL);
-
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index 622fdf4..648177c 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -378,6 +378,18 @@ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
- return -1;
- }
-
-+ switch (domain->revmap_type) {
-+ case IRQ_DOMAIN_MAP_LINEAR:
-+ if (hwirq < domain->revmap_data.linear.size)
-+ domain->revmap_data.linear.revmap[hwirq] = virq;
-+ break;
-+ case IRQ_DOMAIN_MAP_TREE:
-+ mutex_lock(&revmap_trees_mutex);
-+ irq_radix_revmap_insert(domain, virq, hwirq);
-+ mutex_unlock(&revmap_trees_mutex);
-+ break;
-+ }
-+
- irq_clear_status_flags(virq, IRQ_NOREQUEST);
-
- return 0;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From d3a8f8cf4ad2e5416f53db8963f3ff153feec161 Mon Sep 17 00:00:00 2001
-From: Grant Likely <grant.likely@secretlab.ca>
-Date: Sun, 3 Jun 2012 22:04:35 -0700
-Subject: irqdomain: Split disassociating code into separate function
-
-This patch moves the irq disassociation code out into a separate
-function in preparation to extend irq_setup_virq to handle multiple
-irqs and rename it for use by interrupt controller drivers. The new
-function will be used by irq_setup_virq() in its error path.
-
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-Cc: Paul Mundt <lethal@linux-sh.org>
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Rob Herring <rob.herring@calxeda.com>
-(cherry picked from commit 913af2070731bfc1bd39bb35c5cd2fd66f5eff12)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- kernel/irq/irqdomain.c | 75 +++++++++++++++++++++++++++++++-------------------
- 1 file changed, 47 insertions(+), 28 deletions(-)
-
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index 648177c..091732c 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -364,6 +364,52 @@ void irq_set_default_host(struct irq_domain *domain)
- }
- EXPORT_SYMBOL_GPL(irq_set_default_host);
-
-+static void irq_domain_disassociate_many(struct irq_domain *domain,
-+ unsigned int irq_base, int count)
-+{
-+ /*
-+ * disassociate in reverse order;
-+ * not strictly necessary, but nice for unwinding
-+ */
-+ while (count--) {
-+ int irq = irq_base + count;
-+ struct irq_data *irq_data = irq_get_irq_data(irq);
-+ irq_hw_number_t hwirq = irq_data->hwirq;
-+
-+ if (WARN_ON(!irq_data || irq_data->domain != domain))
-+ continue;
-+
-+ irq_set_status_flags(irq, IRQ_NOREQUEST);
-+
-+ /* remove chip and handler */
-+ irq_set_chip_and_handler(irq, NULL, NULL);
-+
-+ /* Make sure it's completed */
-+ synchronize_irq(irq);
-+
-+ /* Tell the PIC about it */
-+ if (domain->ops->unmap)
-+ domain->ops->unmap(domain, irq);
-+ smp_mb();
-+
-+ irq_data->domain = NULL;
-+ irq_data->hwirq = 0;
-+
-+ /* Clear reverse map */
-+ switch(domain->revmap_type) {
-+ case IRQ_DOMAIN_MAP_LINEAR:
-+ if (hwirq < domain->revmap_data.linear.size)
-+ domain->revmap_data.linear.revmap[hwirq] = 0;
-+ break;
-+ case IRQ_DOMAIN_MAP_TREE:
-+ mutex_lock(&revmap_trees_mutex);
-+ radix_tree_delete(&domain->revmap_data.tree, hwirq);
-+ mutex_unlock(&revmap_trees_mutex);
-+ break;
-+ }
-+ }
-+}
-+
- static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
- irq_hw_number_t hwirq)
- {
-@@ -556,7 +602,6 @@ void irq_dispose_mapping(unsigned int virq)
- {
- struct irq_data *irq_data = irq_get_irq_data(virq);
- struct irq_domain *domain;
-- irq_hw_number_t hwirq;
-
- if (!virq || !irq_data)
- return;
-@@ -569,33 +614,7 @@ void irq_dispose_mapping(unsigned int virq)
- if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY)
- return;
-
-- irq_set_status_flags(virq, IRQ_NOREQUEST);
--
-- /* remove chip and handler */
-- irq_set_chip_and_handler(virq, NULL, NULL);
--
-- /* Make sure it's completed */
-- synchronize_irq(virq);
--
-- /* Tell the PIC about it */
-- if (domain->ops->unmap)
-- domain->ops->unmap(domain, virq);
-- smp_mb();
--
-- /* Clear reverse map */
-- hwirq = irq_data->hwirq;
-- switch(domain->revmap_type) {
-- case IRQ_DOMAIN_MAP_LINEAR:
-- if (hwirq < domain->revmap_data.linear.size)
-- domain->revmap_data.linear.revmap[hwirq] = 0;
-- break;
-- case IRQ_DOMAIN_MAP_TREE:
-- mutex_lock(&revmap_trees_mutex);
-- radix_tree_delete(&domain->revmap_data.tree, hwirq);
-- mutex_unlock(&revmap_trees_mutex);
-- break;
-- }
--
-+ irq_domain_disassociate_many(domain, virq, 1);
- irq_free_desc(virq);
- }
- EXPORT_SYMBOL_GPL(irq_dispose_mapping);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 5f4e2248df9a3128a3e81755f87b12dd211ead30 Mon Sep 17 00:00:00 2001
-From: Grant Likely <grant.likely@secretlab.ca>
-Date: Sun, 17 Jun 2012 16:17:04 -0600
-Subject: irqdomain: Support for static IRQ mapping and association.
-
-This adds a new strict mapping API for supporting creation of linux IRQs
-at existing positions within the domain. The new routines are as follows:
-
-For dynamic allocation and insertion to specified ranges:
-
- - irq_create_identity_mapping()
- - irq_create_strict_mappings()
-
-These will allocate and associate a range of linux IRQs at the specified
-location. This can be used by controllers that have their own static linux IRQ
-definitions to map a hwirq range to, as well as for platforms that wish to
-establish 1:1 identity mapping between linux and hwirq space.
-
-For insertion to specified ranges by platforms that do their own irq_desc
-management:
-
- - irq_domain_associate()
- - irq_domain_associate_many()
-
-These in turn call back in to the domain's ->map() routine, for further
-processing by the platform. Disassociation of IRQs get handled through
-irq_dispose_mapping() as normal.
-
-With these in place it should be possible to begin migration of legacy IRQ
-domains to linear ones, without requiring special handling for static vs
-dynamic IRQ definitions in DT vs non-DT paths. This also makes it possible
-for domains with static mappings to adopt whichever tree model best fits
-their needs, rather than simply restricting them to linear revmaps.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-[grant.likely: Reorganized irq_domain_associate{,_many} to have all logic in one place]
-[grant.likely: Add error checking for unallocated irq_descs at associate time]
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Rob Herring <rob.herring@calxeda.com>(cherry picked from commit 98aa468e045a0091a7c34d9f5205a629634fabf4)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- include/linux/irqdomain.h | 19 ++++++++
- kernel/irq/irqdomain.c | 113 ++++++++++++++++++++++++++++++++++++----------
- 2 files changed, 107 insertions(+), 25 deletions(-)
-
-diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
-index 17b60be..eab8a0e 100644
---- a/include/linux/irqdomain.h
-+++ b/include/linux/irqdomain.h
-@@ -149,12 +149,31 @@ static inline struct irq_domain *irq_domain_add_legacy_isa(
-
- extern void irq_domain_remove(struct irq_domain *host);
-
-+extern int irq_domain_associate_many(struct irq_domain *domain,
-+ unsigned int irq_base,
-+ irq_hw_number_t hwirq_base, int count);
-+static inline int irq_domain_associate(struct irq_domain *domain, unsigned int irq,
-+ irq_hw_number_t hwirq)
-+{
-+ return irq_domain_associate_many(domain, irq, hwirq, 1);
-+}
-+
- extern unsigned int irq_create_mapping(struct irq_domain *host,
- irq_hw_number_t hwirq);
- extern void irq_dispose_mapping(unsigned int virq);
- extern unsigned int irq_find_mapping(struct irq_domain *host,
- irq_hw_number_t hwirq);
- extern unsigned int irq_create_direct_mapping(struct irq_domain *host);
-+extern int irq_create_strict_mappings(struct irq_domain *domain,
-+ unsigned int irq_base,
-+ irq_hw_number_t hwirq_base, int count);
-+
-+static inline int irq_create_identity_mapping(struct irq_domain *host,
-+ irq_hw_number_t hwirq)
-+{
-+ return irq_create_strict_mappings(host, hwirq, hwirq, 1);
-+}
-+
- extern void irq_radix_revmap_insert(struct irq_domain *host, unsigned int virq,
- irq_hw_number_t hwirq);
- extern unsigned int irq_radix_revmap_lookup(struct irq_domain *host,
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index 091732c..a07d924 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -410,36 +410,61 @@ static void irq_domain_disassociate_many(struct irq_domain *domain,
- }
- }
-
--static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
-- irq_hw_number_t hwirq)
-+int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
-+ irq_hw_number_t hwirq_base, int count)
- {
-- struct irq_data *irq_data = irq_get_irq_data(virq);
-+ unsigned int virq = irq_base;
-+ irq_hw_number_t hwirq = hwirq_base;
-+ int i;
-
-- irq_data->hwirq = hwirq;
-- irq_data->domain = domain;
-- if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) {
-- pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq);
-- irq_data->domain = NULL;
-- irq_data->hwirq = 0;
-- return -1;
-- }
-+ pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__,
-+ of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count);
-
-- switch (domain->revmap_type) {
-- case IRQ_DOMAIN_MAP_LINEAR:
-- if (hwirq < domain->revmap_data.linear.size)
-- domain->revmap_data.linear.revmap[hwirq] = virq;
-- break;
-- case IRQ_DOMAIN_MAP_TREE:
-- mutex_lock(&revmap_trees_mutex);
-- irq_radix_revmap_insert(domain, virq, hwirq);
-- mutex_unlock(&revmap_trees_mutex);
-- break;
-- }
-+ for (i = 0; i < count; i++) {
-+ struct irq_data *irq_data = irq_get_irq_data(virq + i);
-+
-+ if (WARN(!irq_data, "error: irq_desc not allocated; "
-+ "irq=%i hwirq=0x%x\n", virq + i, (int)hwirq + i))
-+ return -EINVAL;
-+ if (WARN(irq_data->domain, "error: irq_desc already associated; "
-+ "irq=%i hwirq=0x%x\n", virq + i, (int)hwirq + i))
-+ return -EINVAL;
-+ };
-+
-+ for (i = 0; i < count; i++, virq++, hwirq++) {
-+ struct irq_data *irq_data = irq_get_irq_data(virq);
-+
-+ irq_data->hwirq = hwirq;
-+ irq_data->domain = domain;
-+ if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) {
-+ pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq);
-+ irq_data->domain = NULL;
-+ irq_data->hwirq = 0;
-+ goto err_unmap;
-+ }
-+
-+ switch (domain->revmap_type) {
-+ case IRQ_DOMAIN_MAP_LINEAR:
-+ if (hwirq < domain->revmap_data.linear.size)
-+ domain->revmap_data.linear.revmap[hwirq] = virq;
-+ break;
-+ case IRQ_DOMAIN_MAP_TREE:
-+ mutex_lock(&revmap_trees_mutex);
-+ irq_radix_revmap_insert(domain, virq, hwirq);
-+ mutex_unlock(&revmap_trees_mutex);
-+ break;
-+ }
-
-- irq_clear_status_flags(virq, IRQ_NOREQUEST);
-+ irq_clear_status_flags(virq, IRQ_NOREQUEST);
-+ }
-
- return 0;
-+
-+ err_unmap:
-+ irq_domain_disassociate_many(domain, irq_base, i);
-+ return -EINVAL;
- }
-+EXPORT_SYMBOL_GPL(irq_domain_associate_many);
-
- /**
- * irq_create_direct_mapping() - Allocate an irq for direct mapping
-@@ -472,7 +497,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
- }
- pr_debug("create_direct obtained virq %d\n", virq);
-
-- if (irq_setup_virq(domain, virq, virq)) {
-+ if (irq_domain_associate(domain, virq, virq)) {
- irq_free_desc(virq);
- return 0;
- }
-@@ -533,7 +558,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
- return 0;
- }
-
-- if (irq_setup_virq(domain, virq, hwirq)) {
-+ if (irq_domain_associate(domain, virq, hwirq)) {
- irq_free_desc(virq);
- return 0;
- }
-@@ -545,6 +570,44 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
- }
- EXPORT_SYMBOL_GPL(irq_create_mapping);
-
-+/**
-+ * irq_create_strict_mappings() - Map a range of hw irqs to fixed linux irqs
-+ * @domain: domain owning the interrupt range
-+ * @irq_base: beginning of linux IRQ range
-+ * @hwirq_base: beginning of hardware IRQ range
-+ * @count: Number of interrupts to map
-+ *
-+ * This routine is used for allocating and mapping a range of hardware
-+ * irqs to linux irqs where the linux irq numbers are at pre-defined
-+ * locations. For use by controllers that already have static mappings
-+ * to insert in to the domain.
-+ *
-+ * Non-linear users can use irq_create_identity_mapping() for IRQ-at-a-time
-+ * domain insertion.
-+ *
-+ * 0 is returned upon success, while any failure to establish a static
-+ * mapping is treated as an error.
-+ */
-+int irq_create_strict_mappings(struct irq_domain *domain, unsigned int irq_base,
-+ irq_hw_number_t hwirq_base, int count)
-+{
-+ int ret;
-+
-+ ret = irq_alloc_descs(irq_base, irq_base, count,
-+ of_node_to_nid(domain->of_node));
-+ if (unlikely(ret < 0))
-+ return ret;
-+
-+ ret = irq_domain_associate_many(domain, irq_base, hwirq_base, count);
-+ if (unlikely(ret < 0)) {
-+ irq_free_descs(irq_base, count);
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(irq_create_strict_mappings);
-+
- unsigned int irq_create_of_mapping(struct device_node *controller,
- const u32 *intspec, unsigned int intsize)
- {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 5b89c7072aeb8b3f6f16a675fafb342c2dd3e1b6 Mon Sep 17 00:00:00 2001
-From: Grant Likely <grant.likely@secretlab.ca>
-Date: Sun, 3 Jun 2012 22:04:37 -0700
-Subject: irqdomain: Eliminate dedicated radix lookup functions
-
-In preparation to remove the slow revmap path, eliminate the public
-radix revmap lookup functions. This simplifies the code and makes the
-slowpath removal patch a lot simpler.
-
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-Cc: Paul Mundt <lethal@linux-sh.org>
-Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Rob Herring <rob.herring@calxeda.com>
-(cherry picked from commit d6b0d1f7058f7cf818138cd7fd116dca3f3576d9)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/powerpc/sysdev/xics/icp-hv.c | 2 +-
- arch/powerpc/sysdev/xics/icp-native.c | 2 +-
- include/linux/irqdomain.h | 4 ---
- kernel/irq/irqdomain.c | 60 +----------------------------------
- 4 files changed, 3 insertions(+), 65 deletions(-)
-
-diff --git a/arch/powerpc/sysdev/xics/icp-hv.c b/arch/powerpc/sysdev/xics/icp-hv.c
-index 762c5ca..df0fc58 100644
---- a/arch/powerpc/sysdev/xics/icp-hv.c
-+++ b/arch/powerpc/sysdev/xics/icp-hv.c
-@@ -115,7 +115,7 @@ static unsigned int icp_hv_get_irq(void)
- if (vec == XICS_IRQ_SPURIOUS)
- return NO_IRQ;
-
-- irq = irq_radix_revmap_lookup(xics_host, vec);
-+ irq = irq_find_mapping(xics_host, vec);
- if (likely(irq != NO_IRQ)) {
- xics_push_cppr(vec);
- return irq;
-diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c
-index 4c79b6f..48861d3 100644
---- a/arch/powerpc/sysdev/xics/icp-native.c
-+++ b/arch/powerpc/sysdev/xics/icp-native.c
-@@ -119,7 +119,7 @@ static unsigned int icp_native_get_irq(void)
- if (vec == XICS_IRQ_SPURIOUS)
- return NO_IRQ;
-
-- irq = irq_radix_revmap_lookup(xics_host, vec);
-+ irq = irq_find_mapping(xics_host, vec);
- if (likely(irq != NO_IRQ)) {
- xics_push_cppr(vec);
- return irq;
-diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
-index eab8a0e..0d5b17b 100644
---- a/include/linux/irqdomain.h
-+++ b/include/linux/irqdomain.h
-@@ -174,10 +174,6 @@ static inline int irq_create_identity_mapping(struct irq_domain *host,
- return irq_create_strict_mappings(host, hwirq, hwirq, 1);
- }
-
--extern void irq_radix_revmap_insert(struct irq_domain *host, unsigned int virq,
-- irq_hw_number_t hwirq);
--extern unsigned int irq_radix_revmap_lookup(struct irq_domain *host,
-- irq_hw_number_t hwirq);
- extern unsigned int irq_linear_revmap(struct irq_domain *host,
- irq_hw_number_t hwirq);
-
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index a07d924..f540bb1 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -450,7 +450,7 @@ int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
- break;
- case IRQ_DOMAIN_MAP_TREE:
- mutex_lock(&revmap_trees_mutex);
-- irq_radix_revmap_insert(domain, virq, hwirq);
-+ radix_tree_insert(&domain->revmap_data.tree, hwirq, irq_data);
- mutex_unlock(&revmap_trees_mutex);
- break;
- }
-@@ -724,64 +724,6 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
- EXPORT_SYMBOL_GPL(irq_find_mapping);
-
- /**
-- * irq_radix_revmap_lookup() - Find a linux irq from a hw irq number.
-- * @domain: domain owning this hardware interrupt
-- * @hwirq: hardware irq number in that domain space
-- *
-- * This is a fast path, for use by irq controller code that uses radix tree
-- * revmaps
-- */
--unsigned int irq_radix_revmap_lookup(struct irq_domain *domain,
-- irq_hw_number_t hwirq)
--{
-- struct irq_data *irq_data;
--
-- if (WARN_ON_ONCE(domain->revmap_type != IRQ_DOMAIN_MAP_TREE))
-- return irq_find_mapping(domain, hwirq);
--
-- /*
-- * Freeing an irq can delete nodes along the path to
-- * do the lookup via call_rcu.
-- */
-- rcu_read_lock();
-- irq_data = radix_tree_lookup(&domain->revmap_data.tree, hwirq);
-- rcu_read_unlock();
--
-- /*
-- * If found in radix tree, then fine.
-- * Else fallback to linear lookup - this should not happen in practice
-- * as it means that we failed to insert the node in the radix tree.
-- */
-- return irq_data ? irq_data->irq : irq_find_mapping(domain, hwirq);
--}
--EXPORT_SYMBOL_GPL(irq_radix_revmap_lookup);
--
--/**
-- * irq_radix_revmap_insert() - Insert a hw irq to linux irq number mapping.
-- * @domain: domain owning this hardware interrupt
-- * @virq: linux irq number
-- * @hwirq: hardware irq number in that domain space
-- *
-- * This is for use by irq controllers that use a radix tree reverse
-- * mapping for fast lookup.
-- */
--void irq_radix_revmap_insert(struct irq_domain *domain, unsigned int virq,
-- irq_hw_number_t hwirq)
--{
-- struct irq_data *irq_data = irq_get_irq_data(virq);
--
-- if (WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_TREE))
-- return;
--
-- if (virq) {
-- mutex_lock(&revmap_trees_mutex);
-- radix_tree_insert(&domain->revmap_data.tree, hwirq, irq_data);
-- mutex_unlock(&revmap_trees_mutex);
-- }
--}
--EXPORT_SYMBOL_GPL(irq_radix_revmap_insert);
--
--/**
- * irq_linear_revmap() - Find a linux irq from a hw irq number.
- * @domain: domain owning this hardware interrupt
- * @hwirq: hardware irq number in that domain space
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 669724cfa76709814c46bac8ba50f1a52d15ffd7 Mon Sep 17 00:00:00 2001
-From: Grant Likely <grant.likely@secretlab.ca>
-Date: Sun, 3 Jun 2012 22:04:38 -0700
-Subject: irqdomain: Fix irq_create_direct_mapping() to test irq_domain type.
-
-irq_create_direct_mapping can only be used with the NOMAP type. Make
-the function test to ensure it is passed the correct type of
-irq_domain.
-
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-Cc: Paul Mundt <lethal@linux-sh.org>
-Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Rob Herring <rob.herring@calxeda.com>
-(cherry picked from commit 9844a5524ec532aee826c35e3031637c7fc8287b)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- kernel/irq/irqdomain.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index f540bb1..c0e638b 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -481,8 +481,8 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
- if (domain == NULL)
- domain = irq_default_domain;
-
-- BUG_ON(domain == NULL);
-- WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP);
-+ if (WARN_ON(!domain || domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP))
-+ return 0;
-
- virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node));
- if (!virq) {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 026250e1fad07349b34213260492cecee3b32eae Mon Sep 17 00:00:00 2001
-From: Grant Likely <grant.likely@secretlab.ca>
-Date: Sun, 3 Jun 2012 22:04:39 -0700
-Subject: irqdomain: eliminate slow-path revmap lookups
-
-With the current state of irq_domain, the reverse map is always updated
-when new IRQs get mapped. This means that the irq_find_mapping() function
-can be simplified to execute the revmap lookup functions unconditionally
-
-This patch adds lookup functions for the revmaps that don't yet have one
-and removes the slow path lookup code path.
-
-v8: Broke out unrelated changes into separate patches. Rebased on Paul's irq
- association patches.
-v7: Rebased to irqdomain/next for v3.4 and applied before the removal of 'hint'
-v6: Remove the slow path entirely. The only place where the slow path
- could get called is for a linear mapping if the hwirq number is larger
- than the linear revmap size. There shouldn't be any interrupt
- controllers that do that.
-v5: rewrite to not use a ->revmap() callback. It is simpler, smaller,
- safer and faster to open code each of the revmap lookups directly into
- irq_find_mapping() via a switch statement.
-v4: Fix build failure on incorrect variable reference.
-
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Milton Miller <miltonm@bga.com>
-Cc: Paul Mundt <lethal@linux-sh.org>
-Cc: Rob Herring <rob.herring@calxeda.com>
-(cherry picked from commit 4c0946c47463defa681b83294383dc996d255bb7)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- kernel/irq/irqdomain.c | 65 +++++++++++++++++++-------------------------------
- 1 file changed, 25 insertions(+), 40 deletions(-)
-
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index c0e638b..170724a 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -686,16 +686,11 @@ EXPORT_SYMBOL_GPL(irq_dispose_mapping);
- * irq_find_mapping() - Find a linux irq from an hw irq number.
- * @domain: domain owning this hardware interrupt
- * @hwirq: hardware irq number in that domain space
-- *
-- * This is a slow path, for use by generic code. It's expected that an
-- * irq controller implementation directly calls the appropriate low level
-- * mapping function.
- */
- unsigned int irq_find_mapping(struct irq_domain *domain,
- irq_hw_number_t hwirq)
- {
-- unsigned int i;
-- unsigned int hint = hwirq % nr_irqs;
-+ struct irq_data *data;
-
- /* Look for default domain if nececssary */
- if (domain == NULL)
-@@ -703,22 +698,25 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
- if (domain == NULL)
- return 0;
-
-- /* legacy -> bail early */
-- if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY)
-+ switch (domain->revmap_type) {
-+ case IRQ_DOMAIN_MAP_LEGACY:
- return irq_domain_legacy_revmap(domain, hwirq);
--
-- /* Slow path does a linear search of the map */
-- if (hint == 0)
-- hint = 1;
-- i = hint;
-- do {
-- struct irq_data *data = irq_get_irq_data(i);
-+ case IRQ_DOMAIN_MAP_LINEAR:
-+ return irq_linear_revmap(domain, hwirq);
-+ case IRQ_DOMAIN_MAP_TREE:
-+ rcu_read_lock();
-+ data = radix_tree_lookup(&domain->revmap_data.tree, hwirq);
-+ rcu_read_unlock();
-+ if (data)
-+ return data->irq;
-+ break;
-+ case IRQ_DOMAIN_MAP_NOMAP:
-+ data = irq_get_irq_data(hwirq);
- if (data && (data->domain == domain) && (data->hwirq == hwirq))
-- return i;
-- i++;
-- if (i >= nr_irqs)
-- i = 1;
-- } while(i != hint);
-+ return hwirq;
-+ break;
-+ }
-+
- return 0;
- }
- EXPORT_SYMBOL_GPL(irq_find_mapping);
-@@ -728,32 +726,19 @@ EXPORT_SYMBOL_GPL(irq_find_mapping);
- * @domain: domain owning this hardware interrupt
- * @hwirq: hardware irq number in that domain space
- *
-- * This is a fast path, for use by irq controller code that uses linear
-- * revmaps. It does fallback to the slow path if the revmap doesn't exist
-- * yet and will create the revmap entry with appropriate locking
-+ * This is a fast path that can be called directly by irq controller code to
-+ * save a handful of instructions.
- */
- unsigned int irq_linear_revmap(struct irq_domain *domain,
- irq_hw_number_t hwirq)
- {
-- unsigned int *revmap;
-+ BUG_ON(domain->revmap_type != IRQ_DOMAIN_MAP_LINEAR);
-
-- if (WARN_ON_ONCE(domain->revmap_type != IRQ_DOMAIN_MAP_LINEAR))
-- return irq_find_mapping(domain, hwirq);
--
-- /* Check revmap bounds */
-- if (unlikely(hwirq >= domain->revmap_data.linear.size))
-- return irq_find_mapping(domain, hwirq);
--
-- /* Check if revmap was allocated */
-- revmap = domain->revmap_data.linear.revmap;
-- if (unlikely(revmap == NULL))
-- return irq_find_mapping(domain, hwirq);
--
-- /* Fill up revmap with slow path if no mapping found */
-- if (unlikely(!revmap[hwirq]))
-- revmap[hwirq] = irq_find_mapping(domain, hwirq);
-+ /* Check revmap bounds; complain if exceeded */
-+ if (WARN_ON(hwirq >= domain->revmap_data.linear.size))
-+ return 0;
-
-- return revmap[hwirq];
-+ return domain->revmap_data.linear.revmap[hwirq];
- }
- EXPORT_SYMBOL_GPL(irq_linear_revmap);
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 6a3157b4d4a0df782066f610807c4288ed52ec43 Mon Sep 17 00:00:00 2001
-From: Mark Brown <broonie@opensource.wolfsonmicro.com>
-Date: Fri, 20 Jul 2012 10:33:19 +0100
-Subject: irqdomain: Improve diagnostics when a domain mapping fails
-
-When the map operation fails log the error code we get and add a WARN_ON()
-so we get a backtrace (which should help work out which interrupt is the
-source of the issue).
-
-Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-(cherry picked from commit f5a1ad057e6da5d0fc9c5677ff44797d193d3e62)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- kernel/irq/irqdomain.c | 17 +++++++++++------
- 1 file changed, 11 insertions(+), 6 deletions(-)
-
-diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
-index 170724a..49a7772 100644
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -415,7 +415,7 @@ int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
- {
- unsigned int virq = irq_base;
- irq_hw_number_t hwirq = hwirq_base;
-- int i;
-+ int i, ret;
-
- pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__,
- of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count);
-@@ -436,11 +436,16 @@ int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
-
- irq_data->hwirq = hwirq;
- irq_data->domain = domain;
-- if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) {
-- pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq);
-- irq_data->domain = NULL;
-- irq_data->hwirq = 0;
-- goto err_unmap;
-+ if (domain->ops->map) {
-+ ret = domain->ops->map(domain, virq, hwirq);
-+ if (ret != 0) {
-+ pr_err("irq-%i==>hwirq-0x%lx mapping failed: %d\n",
-+ virq, hwirq, ret);
-+ WARN_ON(1);
-+ irq_data->domain = NULL;
-+ irq_data->hwirq = 0;
-+ goto err_unmap;
-+ }
- }
-
- switch (domain->revmap_type) {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From f2f3cb0fe8263325798302e1b431e38cf4e153e8 Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Wed, 28 Mar 2012 19:22:46 +0900
-Subject: ARM: mach-shmobile: Introduce INTC_IRQ_PINS_16H
-
-Add INTC_IRQ_PINS_16H to allow broken out support of the
-the high 16 external interrupt pins. On SoCs with 32 external
-interrupt pins the interrupt vectors for the low 16 and the
-high 16 interrupt pins are sparesly populated. The low 16 are
-at 0x0200 and high 16 are at 0x3200 which with current macros
-results in a separation of 384 linux interrupts. This sparse
-population makes it unsuitable with a single IRQ domain to
-cover the full IRQ range, so this macro breaks out the 32 pins
-into two separate 16 bit controllers to allow two independent
-INTC instances with two separate IRQ domains.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit d7e7e4ffc64f700e876a9f3b2727febaa2041221)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/include/mach/intc.h | 44 ++++++++++++++++++++++++++++++
- 1 file changed, 44 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/include/mach/intc.h b/arch/arm/mach-shmobile/include/mach/intc.h
-index 8b22258..a5603c7 100644
---- a/arch/arm/mach-shmobile/include/mach/intc.h
-+++ b/arch/arm/mach-shmobile/include/mach/intc.h
-@@ -142,6 +142,50 @@ static struct intc_desc p ## _desc __initdata = { \
- p ## _sense_registers, p ## _ack_registers) \
- }
-
-+#define INTC_IRQ_PINS_16H(p, base, vect, str) \
-+ \
-+static struct resource p ## _resources[] __initdata = { \
-+ [0] = { \
-+ .start = base, \
-+ .end = base + 0x64, \
-+ .flags = IORESOURCE_MEM, \
-+ }, \
-+}; \
-+ \
-+enum { \
-+ p ## _UNUSED = 0, \
-+ INTC_IRQ_PINS_ENUM_16H(p), \
-+}; \
-+ \
-+static struct intc_vect p ## _vectors[] __initdata = { \
-+ INTC_IRQ_PINS_VECT_16H(p, vect), \
-+}; \
-+ \
-+static struct intc_mask_reg p ## _mask_registers[] __initdata = { \
-+ INTC_IRQ_PINS_MASK_16H(p, base), \
-+}; \
-+ \
-+static struct intc_prio_reg p ## _prio_registers[] __initdata = { \
-+ INTC_IRQ_PINS_PRIO_16H(p, base), \
-+}; \
-+ \
-+static struct intc_sense_reg p ## _sense_registers[] __initdata = { \
-+ INTC_IRQ_PINS_SENSE_16H(p, base), \
-+}; \
-+ \
-+static struct intc_mask_reg p ## _ack_registers[] __initdata = { \
-+ INTC_IRQ_PINS_ACK_16H(p, base), \
-+}; \
-+ \
-+static struct intc_desc p ## _desc __initdata = { \
-+ .name = str, \
-+ .resource = p ## _resources, \
-+ .num_resources = ARRAY_SIZE(p ## _resources), \
-+ .hw = INTC_HW_DESC(p ## _vectors, NULL, \
-+ p ## _mask_registers, p ## _prio_registers, \
-+ p ## _sense_registers, p ## _ack_registers) \
-+}
-+
- #define INTC_IRQ_PINS_32(p, base, vect, str) \
- \
- static struct resource p ## _resources[] __initdata = { \
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From cba1bcc0a91c91fb5b503e6a718801a0eca41b3f Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Tue, 22 May 2012 19:07:55 +0900
-Subject: sh: intc: Kill off special reservation interface.
-
-At present reserving the IRLs in the IRQ bitmap in addition to the
-dropping of the legacy IRQ pre-allocation prevent IRL IRQs from being
-allocated for the x3proto board.
-
-The only reason to permit reservations was to lock down possible hardware
-vectors prior to dynamic IRQ scanning, but this doesn't matter much given
-that the hardware controller configuration is sorted before we get around
-to doing any dynamic IRQ allocation anyways. Beyond that, all of the
-tables are __init annotated, so quite a bit more work would need to be
-done to support reconfiguring things like IRL controllers on the fly,
-much more than would ever make it worth the hassle.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 5f19f14fed7786652b9617c633db101d26a42251)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/sh/kernel/cpu/sh4a/setup-shx3.c | 3 ---
- drivers/sh/intc/dynamic.c | 8 --------
- include/linux/sh_intc.h | 1 -
- 3 files changed, 12 deletions(-)
-
-diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
-index bb20880..674531e 100644
---- a/arch/sh/kernel/cpu/sh4a/setup-shx3.c
-+++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
-@@ -484,9 +484,6 @@ void __init plat_irq_setup_pins(int mode)
-
- void __init plat_irq_setup(void)
- {
-- reserve_intc_vectors(vectors_irq, ARRAY_SIZE(vectors_irq));
-- reserve_intc_vectors(vectors_irl, ARRAY_SIZE(vectors_irl));
--
- register_intc_controller(&intc_desc);
- }
-
-diff --git a/drivers/sh/intc/dynamic.c b/drivers/sh/intc/dynamic.c
-index 5fea1ee..14eb01e 100644
---- a/drivers/sh/intc/dynamic.c
-+++ b/drivers/sh/intc/dynamic.c
-@@ -55,11 +55,3 @@ void destroy_irq(unsigned int irq)
- {
- irq_free_desc(irq);
- }
--
--void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs)
--{
-- int i;
--
-- for (i = 0; i < nr_vecs; i++)
-- irq_reserve_irq(evt2irq(vectors[i].vect));
--}
-diff --git a/include/linux/sh_intc.h b/include/linux/sh_intc.h
-index 6aed080..3238328 100644
---- a/include/linux/sh_intc.h
-+++ b/include/linux/sh_intc.h
-@@ -133,7 +133,6 @@ struct intc_desc symbol __initdata = { \
- }
-
- int register_intc_controller(struct intc_desc *desc);
--void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs);
- int intc_set_priority(unsigned int irq, unsigned int prio);
- int intc_irq_lookup(const char *chipname, intc_enum enum_id);
- void intc_finalize(void);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 42251498a3ddced1d93aae4fc44936663d7079a5 Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Thu, 24 May 2012 19:24:18 +0900
-Subject: sh: intc: Allocate subgroup virq backing desc directly.
-
-This switches to using irq_alloc_desc() directly for subgroup IRQs.
-We still need to call activate_irq() on these in order to make them
-requestable, at least up until these get moved in to their own irq
-domain..
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 123df01e8e046d6065089e1bff29aa3fc48d4420)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/sh/intc/virq.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/sh/intc/virq.c b/drivers/sh/intc/virq.c
-index 93cec21..f30ac93 100644
---- a/drivers/sh/intc/virq.c
-+++ b/drivers/sh/intc/virq.c
-@@ -219,12 +219,14 @@ restart:
- if (radix_tree_deref_retry(entry))
- goto restart;
-
-- irq = create_irq();
-+ irq = irq_alloc_desc(numa_node_id());
- if (unlikely(irq < 0)) {
- pr_err("no more free IRQs, bailing..\n");
- break;
- }
-
-+ activate_irq(irq);
-+
- pr_info("Setting up a chained VIRQ from %d -> %d\n",
- irq, entry->pirq);
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 53b1c0647bb113f4c1edfdfc8c40b7bf8f258628 Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Wed, 1 Aug 2012 17:13:46 +0900
-Subject: sh: intc: initial irqdomain support.
-
-Trivial support for irq domains, using either a linear map or radix tree
-depending on the vector layout.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 1d6a21b0a672fb29b01ccf397d478e0541e17716)
-
-Conflicts:
- drivers/sh/intc/Makefile
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/sh/intc/Kconfig | 4 +++
- drivers/sh/intc/Makefile | 2 +-
- drivers/sh/intc/core.c | 11 +++++---
- drivers/sh/intc/internals.h | 5 ++++
- drivers/sh/intc/irqdomain.c | 68 +++++++++++++++++++++++++++++++++++++++++++++
- 5 files changed, 85 insertions(+), 5 deletions(-)
- create mode 100644 drivers/sh/intc/irqdomain.c
-
-diff --git a/drivers/sh/intc/Kconfig b/drivers/sh/intc/Kconfig
-index c88cbcc..a305731 100644
---- a/drivers/sh/intc/Kconfig
-+++ b/drivers/sh/intc/Kconfig
-@@ -1,3 +1,7 @@
-+config SH_INTC
-+ def_bool y
-+ select IRQ_DOMAIN
-+
- comment "Interrupt controller options"
-
- config INTC_USERIMASK
-diff --git a/drivers/sh/intc/Makefile b/drivers/sh/intc/Makefile
-index bb5df86..44cf2cd 100644
---- a/drivers/sh/intc/Makefile
-+++ b/drivers/sh/intc/Makefile
-@@ -1,4 +1,4 @@
--obj-y := access.o chip.o core.o dynamic.o handle.o virq.o
-+obj-y := access.o chip.o core.o dynamic.o handle.o irqdomain.o virq.o
-
- obj-$(CONFIG_INTC_BALANCING) += balancing.o
- obj-$(CONFIG_INTC_USERIMASK) += userimask.o
-diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
-index 7e562cc..2374468 100644
---- a/drivers/sh/intc/core.c
-+++ b/drivers/sh/intc/core.c
-@@ -25,6 +25,7 @@
- #include <linux/stat.h>
- #include <linux/interrupt.h>
- #include <linux/sh_intc.h>
-+#include <linux/irqdomain.h>
- #include <linux/device.h>
- #include <linux/syscore_ops.h>
- #include <linux/list.h>
-@@ -310,6 +311,8 @@ int __init register_intc_controller(struct intc_desc *desc)
-
- BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
-
-+ intc_irq_domain_init(d, hw);
-+
- /* register the vectors one by one */
- for (i = 0; i < hw->nr_vectors; i++) {
- struct intc_vect *vect = hw->vectors + i;
-@@ -319,8 +322,8 @@ int __init register_intc_controller(struct intc_desc *desc)
- if (!vect->enum_id)
- continue;
-
-- res = irq_alloc_desc_at(irq, numa_node_id());
-- if (res != irq && res != -EEXIST) {
-+ res = irq_create_identity_mapping(d->domain, irq);
-+ if (unlikely(res)) {
- pr_err("can't get irq_desc for %d\n", irq);
- continue;
- }
-@@ -340,8 +343,8 @@ int __init register_intc_controller(struct intc_desc *desc)
- * IRQ support, each vector still needs to have
- * its own backing irq_desc.
- */
-- res = irq_alloc_desc_at(irq2, numa_node_id());
-- if (res != irq2 && res != -EEXIST) {
-+ res = irq_create_identity_mapping(d->domain, irq2);
-+ if (unlikely(res)) {
- pr_err("can't get irq_desc for %d\n", irq2);
- continue;
- }
-diff --git a/drivers/sh/intc/internals.h b/drivers/sh/intc/internals.h
-index f034a97..7dff08e 100644
---- a/drivers/sh/intc/internals.h
-+++ b/drivers/sh/intc/internals.h
-@@ -1,5 +1,6 @@
- #include <linux/sh_intc.h>
- #include <linux/irq.h>
-+#include <linux/irqdomain.h>
- #include <linux/list.h>
- #include <linux/kernel.h>
- #include <linux/types.h>
-@@ -66,6 +67,7 @@ struct intc_desc_int {
- unsigned int nr_sense;
- struct intc_window *window;
- unsigned int nr_windows;
-+ struct irq_domain *domain;
- struct irq_chip chip;
- bool skip_suspend;
- };
-@@ -187,6 +189,9 @@ unsigned long intc_get_ack_handle(unsigned int irq);
- void intc_enable_disable_enum(struct intc_desc *desc, struct intc_desc_int *d,
- intc_enum enum_id, int enable);
-
-+/* irqdomain.c */
-+void intc_irq_domain_init(struct intc_desc_int *d, struct intc_hw_desc *hw);
-+
- /* virq.c */
- void intc_subgroup_init(struct intc_desc *desc, struct intc_desc_int *d);
- void intc_irq_xlate_set(unsigned int irq, intc_enum id, struct intc_desc_int *d);
-diff --git a/drivers/sh/intc/irqdomain.c b/drivers/sh/intc/irqdomain.c
-new file mode 100644
-index 0000000..3968f1c
---- /dev/null
-+++ b/drivers/sh/intc/irqdomain.c
-@@ -0,0 +1,68 @@
-+/*
-+ * IRQ domain support for SH INTC subsystem
-+ *
-+ * Copyright (C) 2012 Paul Mundt
-+ *
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ */
-+#define pr_fmt(fmt) "intc: " fmt
-+
-+#include <linux/irqdomain.h>
-+#include <linux/sh_intc.h>
-+#include <linux/export.h>
-+#include "internals.h"
-+
-+/**
-+ * intc_irq_domain_evt_xlate() - Generic xlate for vectored IRQs.
-+ *
-+ * This takes care of exception vector to hwirq translation through
-+ * by way of evt2irq() translation.
-+ *
-+ * Note: For platforms that use a flat vector space without INTEVT this
-+ * basically just mimics irq_domain_xlate_onecell() by way of a nopped
-+ * out evt2irq() implementation.
-+ */
-+static int intc_evt_xlate(struct irq_domain *d, struct device_node *ctrlr,
-+ const u32 *intspec, unsigned int intsize,
-+ unsigned long *out_hwirq, unsigned int *out_type)
-+{
-+ if (WARN_ON(intsize < 1))
-+ return -EINVAL;
-+
-+ *out_hwirq = evt2irq(intspec[0]);
-+ *out_type = IRQ_TYPE_NONE;
-+
-+ return 0;
-+}
-+
-+static const struct irq_domain_ops intc_evt_ops = {
-+ .xlate = intc_evt_xlate,
-+};
-+
-+void __init intc_irq_domain_init(struct intc_desc_int *d,
-+ struct intc_hw_desc *hw)
-+{
-+ unsigned int irq_base, irq_end;
-+
-+ /*
-+ * Quick linear revmap check
-+ */
-+ irq_base = evt2irq(hw->vectors[0].vect);
-+ irq_end = evt2irq(hw->vectors[hw->nr_vectors - 1].vect);
-+
-+ /*
-+ * Linear domains have a hard-wired assertion that IRQs start at
-+ * 0 in order to make some performance optimizations. Lamely
-+ * restrict the linear case to these conditions here, taking the
-+ * tree penalty for linear cases with non-zero hwirq bases.
-+ */
-+ if (irq_base == 0 && irq_end == (irq_base + hw->nr_vectors - 1))
-+ d->domain = irq_domain_add_linear(NULL, hw->nr_vectors,
-+ &intc_evt_ops, NULL);
-+ else
-+ d->domain = irq_domain_add_tree(NULL, &intc_evt_ops, NULL);
-+
-+ BUG_ON(!d->domain);
-+}
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From f4c7cdd9100a1141390e3cea9c3ef8a104c420ae Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Thu, 9 Aug 2012 12:59:40 +0900
-Subject: sh: intc: Handle domain association for sparseirq pre-allocated
- vectors.
-
-Presently it's assumed that the irqdomain code handles the irq_desc
-allocation for us, but this isn't necessarily the case when we've
-pre-allocated IRQs via sparseirq. Previously we had a -EEXIST check in
-the code that attempted to trap these cases and simply update them
-in-place, but this behaviour was inadvertently lost in the transition to
-irqdomains.
-
-This simply restores the previous behaviour, first attempting to let the
-irqdomain core fetch the allocation for us, and falling back to an
-in-place domain association in the extant IRQ case. Fixes up regressions
-on platforms that pre-allocate legacy IRQs (specifically ARM-based
-SH-Mobile platforms, as SH stopped pre-allocating vectors some time ago).
-
-Reported-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 1026023705b0baa2b37df2a0d1da0022fc7b985e)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/sh/intc/core.c | 27 +++++++++++++++++++++++----
- 1 file changed, 23 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
-index 2374468..32c26d7 100644
---- a/drivers/sh/intc/core.c
-+++ b/drivers/sh/intc/core.c
-@@ -324,8 +324,16 @@ int __init register_intc_controller(struct intc_desc *desc)
-
- res = irq_create_identity_mapping(d->domain, irq);
- if (unlikely(res)) {
-- pr_err("can't get irq_desc for %d\n", irq);
-- continue;
-+ if (res == -EEXIST) {
-+ res = irq_domain_associate(d->domain, irq, irq);
-+ if (unlikely(res)) {
-+ pr_err("domain association failure\n");
-+ continue;
-+ }
-+ } else {
-+ pr_err("can't identity map IRQ %d\n", irq);
-+ continue;
-+ }
- }
-
- intc_irq_xlate_set(irq, vect->enum_id, d);
-@@ -345,8 +353,19 @@ int __init register_intc_controller(struct intc_desc *desc)
- */
- res = irq_create_identity_mapping(d->domain, irq2);
- if (unlikely(res)) {
-- pr_err("can't get irq_desc for %d\n", irq2);
-- continue;
-+ if (res == -EEXIST) {
-+ res = irq_domain_associate(d->domain,
-+ irq, irq);
-+ if (unlikely(res)) {
-+ pr_err("domain association "
-+ "failure\n");
-+ continue;
-+ }
-+ } else {
-+ pr_err("can't identity map IRQ %d\n",
-+ irq);
-+ continue;
-+ }
- }
-
- vect2->enum_id = 0;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e36191f0adc5ef8bafb24f3612367b5648ee279a Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Mon, 20 Aug 2012 14:51:50 +0900
-Subject: sh: intc: Fix up multi-evt irq association.
-
-In the multi-evt case we were accidentally associating the parent IRQ,
-fix this up.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit d4b7c5db429fbfd3c79120b27ccf66d583606b57)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/sh/intc/core.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
-index 32c26d7..8f32a13 100644
---- a/drivers/sh/intc/core.c
-+++ b/drivers/sh/intc/core.c
-@@ -355,7 +355,7 @@ int __init register_intc_controller(struct intc_desc *desc)
- if (unlikely(res)) {
- if (res == -EEXIST) {
- res = irq_domain_associate(d->domain,
-- irq, irq);
-+ irq2, irq2);
- if (unlikely(res)) {
- pr_err("domain association "
- "failure\n");
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From faa2b6a185dbc63fb27624543fb4e6dc3498eb90 Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Wed, 28 Mar 2012 19:22:30 +0900
-Subject: ARM: mach-shmobile: Introduce shmobile_setup_delay()
-
-Add the function shmobile_setup_delay() to let platforms
-configure their maximum loops per jiffy delay. With this
-jiffies calculation done the dependency on early timer
-is removed.
-
-In the future this allows us to assign timers
-using the regular driver model via the device tree.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 0f2c9f20e4e339de30cfd5613dfa9505e7b9c58b)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/include/mach/common.h | 2 ++
- arch/arm/mach-shmobile/timer.c | 17 +++++++++++++++++
- 2 files changed, 19 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
-index c85e6ec..ff5f12f 100644
---- a/arch/arm/mach-shmobile/include/mach/common.h
-+++ b/arch/arm/mach-shmobile/include/mach/common.h
-@@ -3,6 +3,8 @@
-
- extern void shmobile_earlytimer_init(void);
- extern struct sys_timer shmobile_timer;
-+extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
-+ unsigned int mult, unsigned int div);
- struct twd_local_timer;
- extern void shmobile_setup_console(void);
- extern void shmobile_secondary_vector(void);
-diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
-index 8b79e79..cba39d8 100644
---- a/arch/arm/mach-shmobile/timer.c
-+++ b/arch/arm/mach-shmobile/timer.c
-@@ -19,9 +19,26 @@
- *
- */
- #include <linux/platform_device.h>
-+#include <linux/delay.h>
- #include <asm/mach/time.h>
- #include <asm/smp_twd.h>
-
-+void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz,
-+ unsigned int mult, unsigned int div)
-+{
-+ /* calculate a worst-case loops-per-jiffy value
-+ * based on maximum cpu core mhz setting and the
-+ * __delay() implementation in arch/arm/lib/delay.S
-+ *
-+ * this will result in a longer delay than expected
-+ * when the cpu core runs on lower frequencies.
-+ */
-+
-+ unsigned int value = (1000000 * mult) / (HZ * div);
-+
-+ lpj_fine = max_cpu_core_mhz * value;
-+}
-+
- static void __init shmobile_late_time_init(void)
- {
- /*
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 08bdac8dff053868074871b3bc6318d6d95d476e Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Wed, 28 Mar 2012 19:22:54 +0900
-Subject: ARM: mach-shmobile: Use 0x3400 as INTCS vector offset
-
-Update mach-shmobile to use 0x3400 as INTCS_VECT_BASE.
-
-Since the ARM architecture a little while back added support
-for 10 bit irqs we can now undo the previously merged commit
-9b7c23adb350a108737a993c9c781463c1439dc6 and use 0x3400 as
-INTCS vector base.
-
-This change is necessary to avoid overlapping of interrupt
-ranges so separate IRQ domains can be used for different INTC
-instances. Without this fix the vectors used by various INTC
-instances are overlapping on for instance sh7372 which works
-at the moment but breaks upcoming IRQ domain support.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 1ee8299a9ec1ce5137a044c7768293007b9a3267)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/include/mach/irqs.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-shmobile/include/mach/irqs.h b/arch/arm/mach-shmobile/include/mach/irqs.h
-index 4e686cc2..06a5da3 100644
---- a/arch/arm/mach-shmobile/include/mach/irqs.h
-+++ b/arch/arm/mach-shmobile/include/mach/irqs.h
-@@ -7,7 +7,7 @@
- #define gic_spi(nr) ((nr) + 32)
-
- /* INTCS */
--#define INTCS_VECT_BASE 0x2200
-+#define INTCS_VECT_BASE 0x3400
- #define INTCS_VECT(n, vect) INTC_VECT((n), INTCS_VECT_BASE + (vect))
- #define intcs_evt2irq(evt) evt2irq(INTCS_VECT_BASE + (evt))
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 8635adab79f5f8e8287e93cc19442556cab55d06 Mon Sep 17 00:00:00 2001
-From: Shawn Guo <shawn.guo@linaro.org>
-Date: Wed, 25 Apr 2012 22:24:44 +0800
-Subject: ARM: provide a late_initcall hook for platform initialization
-
-This allows platforms to set up things that need to be done at
-late_initcall time.
-
-Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
-Tested-by: Robert Lee <rob.lee@linaro.org>
-Tested-by: Stephen Warren <swarren@wwwdotorg.org>
-Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com>
-Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
-(cherry picked from commit 90de41375ccf8373c0a39d04547f3e3c65d90ec0)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/include/asm/mach/arch.h | 1 +
- arch/arm/kernel/setup.c | 8 ++++++++
- 2 files changed, 9 insertions(+)
-
---- a/arch/arm/include/asm/mach/arch.h
-+++ b/arch/arm/include/asm/mach/arch.h
-@@ -43,6 +43,7 @@ struct machine_desc {
- void (*init_irq)(void);
- struct sys_timer *timer; /* system tick timer */
- void (*init_machine)(void);
-+ void (*init_late)(void);
- #ifdef CONFIG_MULTI_IRQ_HANDLER
- void (*handle_irq)(struct pt_regs *);
- #endif
---- a/arch/arm/kernel/setup.c
-+++ b/arch/arm/kernel/setup.c
-@@ -801,6 +801,14 @@ static int __init customize_machine(void
- }
- arch_initcall(customize_machine);
-
-+static int __init init_machine_late(void)
-+{
-+ if (machine_desc->init_late)
-+ machine_desc->init_late();
-+ return 0;
-+}
-+late_initcall(init_machine_late);
-+
- #ifdef CONFIG_KEXEC
- static inline unsigned long long get_total_mem(void)
- {
+++ /dev/null
-From 7f963c76f63cde6c48ce88a3b6a964b316e6d8ed Mon Sep 17 00:00:00 2001
-From: Shawn Guo <shawn.guo@linaro.org>
-Date: Thu, 26 Apr 2012 21:58:41 +0800
-Subject: ARM: shmobile: use machine specific hook for late init
-
-Cc: Paul Mundt <lethal@linux-sh.org>
-Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
-Acked-by: Magnus Damm <damm@opensource.se>
-Acked-by: "Rafael J. Wysocki" <rjw@sisk.pl>
-(cherry picked from commit 21cc1b7ede3cf456cf1d51f8a906093261f7c111)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/Makefile | 2 +-
- arch/arm/mach-shmobile/board-ag5evm.c | 1 +
- arch/arm/mach-shmobile/board-ap4evb.c | 1 +
- arch/arm/mach-shmobile/board-bonito.c | 1 +
- arch/arm/mach-shmobile/board-g3evm.c | 1 +
- arch/arm/mach-shmobile/board-g4evm.c | 1 +
- arch/arm/mach-shmobile/board-kota2.c | 1 +
- arch/arm/mach-shmobile/board-mackerel.c | 1 +
- arch/arm/mach-shmobile/board-marzen.c | 1 +
- arch/arm/mach-shmobile/common.c | 24 ++++++++++++++++++++++++
- arch/arm/mach-shmobile/cpuidle.c | 3 +--
- arch/arm/mach-shmobile/include/mach/common.h | 14 ++++++++++++++
- arch/arm/mach-shmobile/suspend.c | 3 +--
- 13 files changed, 49 insertions(+), 5 deletions(-)
- create mode 100644 arch/arm/mach-shmobile/common.c
-
-diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
-index e7c2590..93d62fb 100644
---- a/arch/arm/mach-shmobile/Makefile
-+++ b/arch/arm/mach-shmobile/Makefile
-@@ -3,7 +3,7 @@
- #
-
- # Common objects
--obj-y := timer.o console.o clock.o
-+obj-y := timer.o console.o clock.o common.o
-
- # CPU objects
- obj-$(CONFIG_ARCH_SH7367) += setup-sh7367.o clock-sh7367.o intc-sh7367.o
-diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
-index 0891ec6..5a6f22f 100644
---- a/arch/arm/mach-shmobile/board-ag5evm.c
-+++ b/arch/arm/mach-shmobile/board-ag5evm.c
-@@ -580,5 +580,6 @@ MACHINE_START(AG5EVM, "ag5evm")
- .init_irq = sh73a0_init_irq,
- .handle_irq = gic_handle_irq,
- .init_machine = ag5evm_init,
-+ .init_late = shmobile_init_late,
- .timer = &shmobile_timer,
- MACHINE_END
-diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
-index b56dde2..522866d 100644
---- a/arch/arm/mach-shmobile/board-ap4evb.c
-+++ b/arch/arm/mach-shmobile/board-ap4evb.c
-@@ -1440,5 +1440,6 @@ MACHINE_START(AP4EVB, "ap4evb")
- .init_irq = sh7372_init_irq,
- .handle_irq = shmobile_handle_irq_intc,
- .init_machine = ap4evb_init,
-+ .init_late = shmobile_init_late,
- .timer = &shmobile_timer,
- MACHINE_END
-diff --git a/arch/arm/mach-shmobile/board-bonito.c b/arch/arm/mach-shmobile/board-bonito.c
-index 81fd95f..e6b1fd3 100644
---- a/arch/arm/mach-shmobile/board-bonito.c
-+++ b/arch/arm/mach-shmobile/board-bonito.c
-@@ -500,5 +500,6 @@ MACHINE_START(BONITO, "bonito")
- .init_irq = r8a7740_init_irq,
- .handle_irq = shmobile_handle_irq_intc,
- .init_machine = bonito_init,
-+ .init_late = shmobile_init_late,
- .timer = &shmobile_timer,
- MACHINE_END
-diff --git a/arch/arm/mach-shmobile/board-g3evm.c b/arch/arm/mach-shmobile/board-g3evm.c
-index 39b6cf8..796fa00 100644
---- a/arch/arm/mach-shmobile/board-g3evm.c
-+++ b/arch/arm/mach-shmobile/board-g3evm.c
-@@ -338,5 +338,6 @@ MACHINE_START(G3EVM, "g3evm")
- .init_irq = sh7367_init_irq,
- .handle_irq = shmobile_handle_irq_intc,
- .init_machine = g3evm_init,
-+ .init_late = shmobile_init_late,
- .timer = &shmobile_timer,
- MACHINE_END
-diff --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c
-index 0e5a39c..f125732 100644
---- a/arch/arm/mach-shmobile/board-g4evm.c
-+++ b/arch/arm/mach-shmobile/board-g4evm.c
-@@ -381,5 +381,6 @@ MACHINE_START(G4EVM, "g4evm")
- .init_irq = sh7377_init_irq,
- .handle_irq = shmobile_handle_irq_intc,
- .init_machine = g4evm_init,
-+ .init_late = shmobile_init_late,
- .timer = &shmobile_timer,
- MACHINE_END
-diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c
-index 200dcd4..f60f1b2 100644
---- a/arch/arm/mach-shmobile/board-kota2.c
-+++ b/arch/arm/mach-shmobile/board-kota2.c
-@@ -521,5 +521,6 @@ MACHINE_START(KOTA2, "kota2")
- .init_irq = sh73a0_init_irq,
- .handle_irq = gic_handle_irq,
- .init_machine = kota2_init,
-+ .init_late = shmobile_init_late,
- .timer = &shmobile_timer,
- MACHINE_END
-diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
-index 8c6202b..656d351 100644
---- a/arch/arm/mach-shmobile/board-mackerel.c
-+++ b/arch/arm/mach-shmobile/board-mackerel.c
-@@ -1605,5 +1605,6 @@ MACHINE_START(MACKEREL, "mackerel")
- .init_irq = sh7372_init_irq,
- .handle_irq = shmobile_handle_irq_intc,
- .init_machine = mackerel_init,
-+ .init_late = shmobile_init_late,
- .timer = &shmobile_timer,
- MACHINE_END
-diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
-index ef0e13b..14de378 100644
---- a/arch/arm/mach-shmobile/board-marzen.c
-+++ b/arch/arm/mach-shmobile/board-marzen.c
-@@ -98,5 +98,6 @@ MACHINE_START(MARZEN, "marzen")
- .init_irq = r8a7779_init_irq,
- .handle_irq = gic_handle_irq,
- .init_machine = marzen_init,
-+ .init_late = shmobile_init_late,
- .timer = &shmobile_timer,
- MACHINE_END
-diff --git a/arch/arm/mach-shmobile/common.c b/arch/arm/mach-shmobile/common.c
-new file mode 100644
-index 0000000..608aba9
---- /dev/null
-+++ b/arch/arm/mach-shmobile/common.c
-@@ -0,0 +1,24 @@
-+/*
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; version 2 of the License.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ */
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <mach/common.h>
-+
-+void __init shmobile_init_late(void)
-+{
-+ shmobile_suspend_init();
-+ shmobile_cpuidle_init();
-+}
-diff --git a/arch/arm/mach-shmobile/cpuidle.c b/arch/arm/mach-shmobile/cpuidle.c
-index 7e65591..7b541e9 100644
---- a/arch/arm/mach-shmobile/cpuidle.c
-+++ b/arch/arm/mach-shmobile/cpuidle.c
-@@ -46,7 +46,7 @@ static struct cpuidle_driver shmobile_cpuidle_driver = {
-
- void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv);
-
--static int shmobile_cpuidle_init(void)
-+int shmobile_cpuidle_init(void)
- {
- struct cpuidle_device *dev = &shmobile_cpuidle_dev;
- struct cpuidle_driver *drv = &shmobile_cpuidle_driver;
-@@ -65,4 +65,3 @@ static int shmobile_cpuidle_init(void)
-
- return 0;
- }
--late_initcall(shmobile_cpuidle_init);
-diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
-index ff5f12f..01e2bc0 100644
---- a/arch/arm/mach-shmobile/include/mach/common.h
-+++ b/arch/arm/mach-shmobile/include/mach/common.h
-@@ -85,4 +85,18 @@ extern int r8a7779_boot_secondary(unsigned int cpu);
- extern void r8a7779_smp_prepare_cpus(void);
- extern void r8a7779_register_twd(void);
-
-+extern void shmobile_init_late(void);
-+
-+#ifdef CONFIG_SUSPEND
-+int shmobile_suspend_init(void);
-+#else
-+static inline int shmobile_suspend_init(void) { return 0; }
-+#endif
-+
-+#ifdef CONFIG_CPU_IDLE
-+int shmobile_cpuidle_init(void);
-+#else
-+static inline int shmobile_cpuidle_init(void) { return 0; }
-+#endif
-+
- #endif /* __ARCH_MACH_COMMON_H */
-diff --git a/arch/arm/mach-shmobile/suspend.c b/arch/arm/mach-shmobile/suspend.c
-index 4d1b86a..47d83f7 100644
---- a/arch/arm/mach-shmobile/suspend.c
-+++ b/arch/arm/mach-shmobile/suspend.c
-@@ -39,9 +39,8 @@ struct platform_suspend_ops shmobile_suspend_ops = {
- .valid = suspend_valid_only_mem,
- };
-
--static int __init shmobile_suspend_init(void)
-+int __init shmobile_suspend_init(void)
- {
- suspend_set_ops(&shmobile_suspend_ops);
- return 0;
- }
--late_initcall(shmobile_suspend_init);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From d85b38a67ee3f87c9ac4d814d091f6bacd77745a Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Thu, 10 May 2012 00:37:48 +0200
-Subject: ARM / mach-shmobile: Use preset_lpj with calibrate_delay()
-
-Update the mach-shmobile shared delay calibration code for late
-timers. All existing in-tree non-DT socs are however using early
-timers today and they are unaffected by this change.
-
-The patch modifies shmobile_setup_delay() from using lpj_fine
-to preset_lpj. This change allows us to preset the worst case
-loops-per-jiffy value to all CPU cores on the system.
-
-The old code which made use of lpj_fine did not affect the
-secondary CPU cores which made it impossible to boot on SMP
-without early timers.
-
-Needed for SMP SoCs using late timers like EMEV2 or any other
-mach-shmobile SMP SoC that makes use of late timers via DT.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 173bf69a7af142e0325fa514954f6eeb2d20cc1d)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/timer.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
-index cba39d8..a689197 100644
---- a/arch/arm/mach-shmobile/timer.c
-+++ b/arch/arm/mach-shmobile/timer.c
-@@ -36,7 +36,8 @@ void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz,
-
- unsigned int value = (1000000 * mult) / (HZ * div);
-
-- lpj_fine = max_cpu_core_mhz * value;
-+ if (!preset_lpj)
-+ preset_lpj = max_cpu_core_mhz * value;
- }
-
- static void __init shmobile_late_time_init(void)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 357b31146983e768c408a833731f6b5c614286df Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Tue, 12 Jun 2012 02:36:21 -0700
-Subject: ARM: shmobile: r8a7740: add MERAM work-around
-
-r8a7740 chip has lasting errata on MERAM buffer, and this patch adds
-its work-around on setup-r8a7740.c
-It solved CEU/VIO6C/2D-DMAC/VCP1/VPU5F/JPU/DISP memroy access error.
-
-But MERAM driver can't control this issue,
-since this work-around requires access to non-MERAM register address.
-So, This it will be called as board specific code at this point.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit d49679e5928709bce8937dce396458b139c4b34d)
-
-Conflicts:
- arch/arm/mach-shmobile/board-armadillo800eva.c
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/include/mach/common.h | 1 +
- arch/arm/mach-shmobile/setup-r8a7740.c | 18 ++++++++++++++++++
- 2 files changed, 19 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
-index 01e2bc0..45e61da 100644
---- a/arch/arm/mach-shmobile/include/mach/common.h
-+++ b/arch/arm/mach-shmobile/include/mach/common.h
-@@ -77,6 +77,7 @@ extern void r8a7779_add_standard_devices(void);
- extern void r8a7779_clock_init(void);
- extern void r8a7779_pinmux_init(void);
- extern void r8a7779_pm_init(void);
-+extern void r8a7740_meram_workaround(void);
-
- extern unsigned int r8a7779_get_core_count(void);
- extern int r8a7779_platform_cpu_kill(unsigned int cpu);
-diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
-index 14edb5c..4ba8721 100644
---- a/arch/arm/mach-shmobile/setup-r8a7740.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
-@@ -317,6 +317,24 @@ static struct platform_device *r8a7740_late_devices[] __initdata = {
- &i2c1_device,
- };
-
-+/*
-+ * r8a7740 chip has lasting errata on MERAM buffer.
-+ * this is work-around for it.
-+ * see
-+ * "Media RAM (MERAM)" on r8a7740 documentation
-+ */
-+#define MEBUFCNTR 0xFE950098
-+void r8a7740_meram_workaround(void)
-+{
-+ void __iomem *reg;
-+
-+ reg = ioremap_nocache(MEBUFCNTR, 4);
-+ if (reg) {
-+ iowrite32(0x01600164, reg);
-+ iounmap(reg);
-+ }
-+}
-+
- #define ICCR 0x0004
- #define ICSTART 0x0070
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2a3e278e5c92a6143bc2a57f5c2d5093e26f4208 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Mon, 25 Jun 2012 03:41:09 -0700
-Subject: ARM: shmobile: add common extra gpio functions
-
-Current gpio frame work doesn't have the method to control
-just pull up/down/free, but some SH-ARM boards need such kind of operation.
-This patch adds common extra gpio functions for SH-ARM.
-
-But these functions should be replaced by correct
-gpio function in the future.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 4f3d7f65e9d541566c87de2af2d3b066bae78116)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/include/mach/gpio.h | 32 ++++++++++++++++++++++++++++++
- 1 file changed, 32 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/include/mach/gpio.h b/arch/arm/mach-shmobile/include/mach/gpio.h
-index de795b4..844507d 100644
---- a/arch/arm/mach-shmobile/include/mach/gpio.h
-+++ b/arch/arm/mach-shmobile/include/mach/gpio.h
-@@ -13,6 +13,7 @@
- #include <linux/kernel.h>
- #include <linux/errno.h>
- #include <linux/sh_pfc.h>
-+#include <linux/io.h>
-
- #ifdef CONFIG_GPIOLIB
-
-@@ -27,4 +28,35 @@ static inline int irq_to_gpio(unsigned int irq)
-
- #endif /* CONFIG_GPIOLIB */
-
-+/*
-+ * FIXME !!
-+ *
-+ * current gpio frame work doesn't have
-+ * the method to control only pull up/down/free.
-+ * this function should be replaced by correct gpio function
-+ */
-+static inline void __init gpio_direction_none(u32 addr)
-+{
-+ __raw_writeb(0x00, addr);
-+}
-+
-+static inline void __init gpio_request_pullup(u32 addr)
-+{
-+ u8 data = __raw_readb(addr);
-+
-+ data &= 0x0F;
-+ data |= 0xC0;
-+ __raw_writeb(data, addr);
-+}
-+
-+static inline void __init gpio_request_pulldown(u32 addr)
-+{
-+ u8 data = __raw_readb(addr);
-+
-+ data &= 0x0F;
-+ data |= 0xA0;
-+
-+ __raw_writeb(data, addr);
-+}
-+
- #endif /* __ASM_ARCH_GPIO_H */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 585b51f2c85ca9c6523a2fca74cc9c6beae3a00a Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 27 Jun 2012 00:32:32 +0200
-Subject: ARM: mach-shmobile: add fixed voltage regulators to marzen
-
-On marzen provide a dummy regulator for the smsc911x driver.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit b354e2272ac6fddd19cfd5732bda23974f7b4ee6)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-marzen.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
-index 14de378..3a528cf 100644
---- a/arch/arm/mach-shmobile/board-marzen.c
-+++ b/arch/arm/mach-shmobile/board-marzen.c
-@@ -27,6 +27,8 @@
- #include <linux/io.h>
- #include <linux/gpio.h>
- #include <linux/dma-mapping.h>
-+#include <linux/regulator/fixed.h>
-+#include <linux/regulator/machine.h>
- #include <linux/smsc911x.h>
- #include <mach/hardware.h>
- #include <mach/r8a7779.h>
-@@ -37,6 +39,12 @@
- #include <asm/hardware/gic.h>
- #include <asm/traps.h>
-
-+/* Dummy supplies, where voltage doesn't matter */
-+static struct regulator_consumer_supply dummy_supplies[] = {
-+ REGULATOR_SUPPLY("vddvario", "smsc911x"),
-+ REGULATOR_SUPPLY("vdd33a", "smsc911x"),
-+};
-+
- /* SMSC LAN89218 */
- static struct resource smsc911x_resources[] = {
- [0] = {
-@@ -73,6 +81,8 @@ static struct platform_device *marzen_devices[] __initdata = {
-
- static void __init marzen_init(void)
- {
-+ regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-+
- r8a7779_pinmux_init();
-
- /* SCIF2 (CN18: DEBUG0) */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b7bf36d36b723ef18c515a031fb762d72ce06c38 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Wed, 29 Aug 2012 18:58:01 -0700
-Subject: ARM: shmobile: marzen: fixup smsc911x id for regulator
-
-dummy_supplies for smsc911x are registered as "smsc911x".
-smsc911x driver needs id = -1
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Simon Horman <horms@verge.net.au>
-(cherry picked from commit 497dcf6fc355f0734faf851662b6957386715d24)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/board-marzen.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
-index 3a528cf..fcf5a47 100644
---- a/arch/arm/mach-shmobile/board-marzen.c
-+++ b/arch/arm/mach-shmobile/board-marzen.c
-@@ -67,7 +67,7 @@ static struct smsc911x_platform_config smsc911x_platdata = {
-
- static struct platform_device eth_device = {
- .name = "smsc911x",
-- .id = 0,
-+ .id = -1,
- .dev = {
- .platform_data = &smsc911x_platdata,
- },
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From d84794f3aa3f4214afb08fa52df3ad592965ddba Mon Sep 17 00:00:00 2001
-From: Phil Edworthy <phil.edworthy@renesas.com>
-Date: Sat, 23 Jun 2012 01:12:09 +0200
-Subject: ARM: shmobile: r8a7779: Route all interrupts to ARM
-
-Without this, the interrupts for I2C, VIN, GPIO, SDHC, HSCIF and
-HPB-DMAC are sent to the SH processor.
-
-Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
-Acked-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-(cherry picked from commit 86f887c105b909a2cea7b06f2136d66b3438b038)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/intc-r8a7779.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/arch/arm/mach-shmobile/intc-r8a7779.c b/arch/arm/mach-shmobile/intc-r8a7779.c
-index 550b23d..f04fad4 100644
---- a/arch/arm/mach-shmobile/intc-r8a7779.c
-+++ b/arch/arm/mach-shmobile/intc-r8a7779.c
-@@ -35,6 +35,9 @@
- #define INT2SMSKCR3 0xfe7822ac
- #define INT2SMSKCR4 0xfe7822b0
-
-+#define INT2NTSR0 0xfe700060
-+#define INT2NTSR1 0xfe700064
-+
- static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
- {
- return 0; /* always allow wakeup */
-@@ -49,6 +52,10 @@ void __init r8a7779_init_irq(void)
- gic_init(0, 29, gic_dist_base, gic_cpu_base);
- gic_arch_extn.irq_set_wake = r8a7779_set_wake;
-
-+ /* route all interrupts to ARM */
-+ __raw_writel(0xffffffff, INT2NTSR0);
-+ __raw_writel(0x3fffffff, INT2NTSR1);
-+
- /* unmask all known interrupts in INTCS2 */
- __raw_writel(0xfffffff0, INT2SMSKCR0);
- __raw_writel(0xfff7ffff, INT2SMSKCR1);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 35d53ddd33da54b2ac40aa2b73e93832f9f72c28 Mon Sep 17 00:00:00 2001
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Date: Wed, 25 Apr 2012 20:50:53 +0200
-Subject: dmaengine: Fixup dmaengine_prep_slave_single() to be actually useful
-
-dmaengine_prep_slave_single() is a helper function which is supposed to be used
-to prepare a transfer of a single contingous buffer. Currently the function
-takes a pointer to such a buffer from which it builds a scatterlist and passes
-it on to device_prep_slave_sg. The dmaengine framework requires that any
-scatterlist that is passed to device_prep_slave_sg is mapped and it may not be
-unmapped until the DMA operation has completed. This is not the here and any use
-of dmaengine_prep_slave_single() will lead to undefined behaviour (Most likely a
-system crash).
-
-This patch changes dmaengine_prep_slave_single() to take a dma_addr_t instead of
-a pointer to a buffer and moves the responsibility of mapping and unmapping the
-buffer up to the caller.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
-Acked-by: Linus Walleij <linus.walleij@linaro.org>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit 922ee08baad2052d0759f100e026d49798c51fef)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- include/linux/dmaengine.h | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
-index f9a2e5e..d3fec58 100644
---- a/include/linux/dmaengine.h
-+++ b/include/linux/dmaengine.h
-@@ -615,11 +615,13 @@ static inline int dmaengine_slave_config(struct dma_chan *chan,
- }
-
- static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single(
-- struct dma_chan *chan, void *buf, size_t len,
-+ struct dma_chan *chan, dma_addr_t buf, size_t len,
- enum dma_transfer_direction dir, unsigned long flags)
- {
- struct scatterlist sg;
-- sg_init_one(&sg, buf, len);
-+ sg_init_table(&sg, 1);
-+ sg_dma_address(&sg) = buf;
-+ sg_dma_len(&sg) = len;
-
- return chan->device->device_prep_slave_sg(chan, &sg, 1,
- dir, flags, NULL);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a41ee881d86159d8d44d481f10c3288bdbc38a47 Mon Sep 17 00:00:00 2001
-From: Laxman Dewangan <ldewangan@nvidia.com>
-Date: Wed, 6 Jun 2012 10:55:26 +0530
-Subject: dma: dmaengine: add slave req id in slave_config
-
-The DMA controller like Nvidia's Tegra Dma controller
-supports the different slave requestor id from different slave.
-This need to be configure in dma controller to handle the request
-properly.
-
-Adding the slave-id in the slave configuration so that information
-can be passed from client when configuring for slave.
-
-Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit 4fd1e324b7b5f80bd521b58593ada74ef89e80c4)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- include/linux/dmaengine.h | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
-index d3fec58..2fad917 100644
---- a/include/linux/dmaengine.h
-+++ b/include/linux/dmaengine.h
-@@ -338,6 +338,9 @@ enum dma_slave_buswidth {
- * @device_fc: Flow Controller Settings. Only valid for slave channels. Fill
- * with 'true' if peripheral should be flow controller. Direction will be
- * selected at Runtime.
-+ * @slave_id: Slave requester id. Only valid for slave channels. The dma
-+ * slave peripheral will have unique id as dma requester which need to be
-+ * pass as slave config.
- *
- * This struct is passed in as configuration data to a DMA engine
- * in order to set up a certain channel for DMA transport at runtime.
-@@ -365,6 +368,7 @@ struct dma_slave_config {
- u32 src_maxburst;
- u32 dst_maxburst;
- bool device_fc;
-+ unsigned int slave_id;
- };
-
- static inline const char *dma_chan_name(struct dma_chan *chan)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From c5e667d5b33e041c7dff155e548083c2a176c31a Mon Sep 17 00:00:00 2001
-From: Lars-Peter Clausen <lars@metafoo.de>
-Date: Mon, 11 Jun 2012 20:11:40 +0200
-Subject: dmaengine: Add wrapper for device_tx_status callback
-
-This patch adds a small inline wrapper for the devivce_tx_status callback of a
-dma device. This makes the source code of users of this function a bit more
-compact and a bit more legible.
-
-E.g.:
--status = chan->device->device_tx_status(chan, cookie, &state)
-+status = dmaengine_tx_status(chan, cookie, &state)
-
-Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit 3052cc2c92f11875d111d5b7b9b3ad535b3128b9)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- include/linux/dmaengine.h | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
-index 2fad917..d1d6ef2 100644
---- a/include/linux/dmaengine.h
-+++ b/include/linux/dmaengine.h
-@@ -662,6 +662,12 @@ static inline int dmaengine_resume(struct dma_chan *chan)
- return dmaengine_device_control(chan, DMA_RESUME, 0);
- }
-
-+static inline enum dma_status dmaengine_tx_status(struct dma_chan *chan,
-+ dma_cookie_t cookie, struct dma_tx_state *state)
-+{
-+ return chan->device->device_tx_status(chan, cookie, state);
-+}
-+
- static inline dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc)
- {
- return desc->tx_submit(desc);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 35a2e575d9dbacd1fdd88ca6c032d9c87de43622 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Mon, 2 Jul 2012 22:30:53 +0200
-Subject: dma: move shdma driver to an own directory
-
-The shdma driver is going to be split into multiple files. To make this more
-convenient move it to an own directory.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit e95be94b8c25220aca09ed78c176f9b55a1482c8)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/dma/Makefile | 2 +-
- drivers/dma/sh/Makefile | 1 +
- drivers/dma/{ => sh}/shdma.c | 2 +-
- drivers/dma/{ => sh}/shdma.h | 0
- 4 files changed, 3 insertions(+), 2 deletions(-)
- create mode 100644 drivers/dma/sh/Makefile
- rename drivers/dma/{ => sh}/shdma.c (99%)
- rename drivers/dma/{ => sh}/shdma.h (100%)
-
-diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
-index 86b795b..59c10e5 100644
---- a/drivers/dma/Makefile
-+++ b/drivers/dma/Makefile
-@@ -14,7 +14,7 @@ obj-$(CONFIG_DW_DMAC) += dw_dmac.o
- obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
- obj-$(CONFIG_MX3_IPU) += ipu/
- obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o
--obj-$(CONFIG_SH_DMAE) += shdma.o
-+obj-$(CONFIG_SH_DMAE) += sh/
- obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o
- obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/
- obj-$(CONFIG_IMX_SDMA) += imx-sdma.o
-diff --git a/drivers/dma/sh/Makefile b/drivers/dma/sh/Makefile
-new file mode 100644
-index 0000000..ad4981a
---- /dev/null
-+++ b/drivers/dma/sh/Makefile
-@@ -0,0 +1 @@
-+obj-$(CONFIG_SH_DMAE) += shdma.o
-diff --git a/drivers/dma/shdma.c b/drivers/dma/sh/shdma.c
-similarity index 99%
-rename from drivers/dma/shdma.c
-rename to drivers/dma/sh/shdma.c
-index 19d7a8d..8ab4a1f 100644
---- a/drivers/dma/shdma.c
-+++ b/drivers/dma/sh/shdma.c
-@@ -31,7 +31,7 @@
- #include <linux/spinlock.h>
- #include <linux/rculist.h>
-
--#include "dmaengine.h"
-+#include "../dmaengine.h"
- #include "shdma.h"
-
- /* DMA descriptor control */
-diff --git a/drivers/dma/shdma.h b/drivers/dma/sh/shdma.h
-similarity index 100%
-rename from drivers/dma/shdma.h
-rename to drivers/dma/sh/shdma.h
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From cb331142a15a186173bb23463c591780e82f0a67 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 9 May 2012 17:09:13 +0200
-Subject: dmaengine: add an shdma-base library
-
-This patch extracts code from shdma.c, that does not directly deal with
-hardware implementation details and can be re-used with diverse DMA
-controller variants, found on SH-based SoCs.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Cc: Sascha Hauer <s.hauer@pengutronix.de>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit 9a7b8e002e331d0599127f16613c32f425a14f2c)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/dma/sh/Makefile | 1 +
- drivers/dma/sh/shdma-base.c | 868 ++++++++++++++++++++++++++++++++++++++++++++
- include/linux/shdma-base.h | 123 +++++++
- 3 files changed, 992 insertions(+)
- create mode 100644 drivers/dma/sh/shdma-base.c
- create mode 100644 include/linux/shdma-base.h
-
-diff --git a/drivers/dma/sh/Makefile b/drivers/dma/sh/Makefile
-index ad4981a..54ae957 100644
---- a/drivers/dma/sh/Makefile
-+++ b/drivers/dma/sh/Makefile
-@@ -1 +1,2 @@
-+obj-$(CONFIG_SH_DMAE) += shdma-base.o
- obj-$(CONFIG_SH_DMAE) += shdma.o
-diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
-new file mode 100644
-index 0000000..ff060d0
---- /dev/null
-+++ b/drivers/dma/sh/shdma-base.c
-@@ -0,0 +1,868 @@
-+/*
-+ * Dmaengine driver base library for DMA controllers, found on SH-based SoCs
-+ *
-+ * extracted from shdma.c
-+ *
-+ * Copyright (C) 2011-2012 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-+ * Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
-+ * Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved.
-+ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
-+ *
-+ * This is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/delay.h>
-+#include <linux/shdma-base.h>
-+#include <linux/dmaengine.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/module.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/slab.h>
-+#include <linux/spinlock.h>
-+
-+#include "../dmaengine.h"
-+
-+/* DMA descriptor control */
-+enum shdma_desc_status {
-+ DESC_IDLE,
-+ DESC_PREPARED,
-+ DESC_SUBMITTED,
-+ DESC_COMPLETED, /* completed, have to call callback */
-+ DESC_WAITING, /* callback called, waiting for ack / re-submit */
-+};
-+
-+#define NR_DESCS_PER_CHANNEL 32
-+
-+#define to_shdma_chan(c) container_of(c, struct shdma_chan, dma_chan)
-+#define to_shdma_dev(d) container_of(d, struct shdma_dev, dma_dev)
-+
-+/*
-+ * For slave DMA we assume, that there is a finite number of DMA slaves in the
-+ * system, and that each such slave can only use a finite number of channels.
-+ * We use slave channel IDs to make sure, that no such slave channel ID is
-+ * allocated more than once.
-+ */
-+static unsigned int slave_num = 256;
-+module_param(slave_num, uint, 0444);
-+
-+/* A bitmask with slave_num bits */
-+static unsigned long *shdma_slave_used;
-+
-+/* Called under spin_lock_irq(&schan->chan_lock") */
-+static void shdma_chan_xfer_ld_queue(struct shdma_chan *schan)
-+{
-+ struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
-+ const struct shdma_ops *ops = sdev->ops;
-+ struct shdma_desc *sdesc;
-+
-+ /* DMA work check */
-+ if (ops->channel_busy(schan))
-+ return;
-+
-+ /* Find the first not transferred descriptor */
-+ list_for_each_entry(sdesc, &schan->ld_queue, node)
-+ if (sdesc->mark == DESC_SUBMITTED) {
-+ ops->start_xfer(schan, sdesc);
-+ break;
-+ }
-+}
-+
-+static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
-+{
-+ struct shdma_desc *chunk, *c, *desc =
-+ container_of(tx, struct shdma_desc, async_tx),
-+ *last = desc;
-+ struct shdma_chan *schan = to_shdma_chan(tx->chan);
-+ struct shdma_slave *slave = tx->chan->private;
-+ dma_async_tx_callback callback = tx->callback;
-+ dma_cookie_t cookie;
-+ bool power_up;
-+
-+ spin_lock_irq(&schan->chan_lock);
-+
-+ power_up = list_empty(&schan->ld_queue);
-+
-+ cookie = dma_cookie_assign(tx);
-+
-+ /* Mark all chunks of this descriptor as submitted, move to the queue */
-+ list_for_each_entry_safe(chunk, c, desc->node.prev, node) {
-+ /*
-+ * All chunks are on the global ld_free, so, we have to find
-+ * the end of the chain ourselves
-+ */
-+ if (chunk != desc && (chunk->mark == DESC_IDLE ||
-+ chunk->async_tx.cookie > 0 ||
-+ chunk->async_tx.cookie == -EBUSY ||
-+ &chunk->node == &schan->ld_free))
-+ break;
-+ chunk->mark = DESC_SUBMITTED;
-+ /* Callback goes to the last chunk */
-+ chunk->async_tx.callback = NULL;
-+ chunk->cookie = cookie;
-+ list_move_tail(&chunk->node, &schan->ld_queue);
-+ last = chunk;
-+
-+ dev_dbg(schan->dev, "submit #%d@%p on %d\n",
-+ tx->cookie, &last->async_tx, schan->id);
-+ }
-+
-+ last->async_tx.callback = callback;
-+ last->async_tx.callback_param = tx->callback_param;
-+
-+ if (power_up) {
-+ int ret;
-+ schan->pm_state = SHDMA_PM_BUSY;
-+
-+ ret = pm_runtime_get(schan->dev);
-+
-+ spin_unlock_irq(&schan->chan_lock);
-+ if (ret < 0)
-+ dev_err(schan->dev, "%s(): GET = %d\n", __func__, ret);
-+
-+ pm_runtime_barrier(schan->dev);
-+
-+ spin_lock_irq(&schan->chan_lock);
-+
-+ /* Have we been reset, while waiting? */
-+ if (schan->pm_state != SHDMA_PM_ESTABLISHED) {
-+ struct shdma_dev *sdev =
-+ to_shdma_dev(schan->dma_chan.device);
-+ const struct shdma_ops *ops = sdev->ops;
-+ dev_dbg(schan->dev, "Bring up channel %d\n",
-+ schan->id);
-+ /*
-+ * TODO: .xfer_setup() might fail on some platforms.
-+ * Make it int then, on error remove chunks from the
-+ * queue again
-+ */
-+ ops->setup_xfer(schan, slave);
-+
-+ if (schan->pm_state == SHDMA_PM_PENDING)
-+ shdma_chan_xfer_ld_queue(schan);
-+ schan->pm_state = SHDMA_PM_ESTABLISHED;
-+ }
-+ } else {
-+ /*
-+ * Tell .device_issue_pending() not to run the queue, interrupts
-+ * will do it anyway
-+ */
-+ schan->pm_state = SHDMA_PM_PENDING;
-+ }
-+
-+ spin_unlock_irq(&schan->chan_lock);
-+
-+ return cookie;
-+}
-+
-+/* Called with desc_lock held */
-+static struct shdma_desc *shdma_get_desc(struct shdma_chan *schan)
-+{
-+ struct shdma_desc *sdesc;
-+
-+ list_for_each_entry(sdesc, &schan->ld_free, node)
-+ if (sdesc->mark != DESC_PREPARED) {
-+ BUG_ON(sdesc->mark != DESC_IDLE);
-+ list_del(&sdesc->node);
-+ return sdesc;
-+ }
-+
-+ return NULL;
-+}
-+
-+static int shdma_alloc_chan_resources(struct dma_chan *chan)
-+{
-+ struct shdma_chan *schan = to_shdma_chan(chan);
-+ struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
-+ const struct shdma_ops *ops = sdev->ops;
-+ struct shdma_desc *desc;
-+ struct shdma_slave *slave = chan->private;
-+ int ret, i;
-+
-+ /*
-+ * This relies on the guarantee from dmaengine that alloc_chan_resources
-+ * never runs concurrently with itself or free_chan_resources.
-+ */
-+ if (slave) {
-+ if (slave->slave_id >= slave_num) {
-+ ret = -EINVAL;
-+ goto evalid;
-+ }
-+
-+ if (test_and_set_bit(slave->slave_id, shdma_slave_used)) {
-+ ret = -EBUSY;
-+ goto etestused;
-+ }
-+
-+ ret = ops->set_slave(schan, slave);
-+ if (ret < 0)
-+ goto esetslave;
-+ }
-+
-+ schan->desc = kcalloc(NR_DESCS_PER_CHANNEL,
-+ sdev->desc_size, GFP_KERNEL);
-+ if (!schan->desc) {
-+ ret = -ENOMEM;
-+ goto edescalloc;
-+ }
-+ schan->desc_num = NR_DESCS_PER_CHANNEL;
-+
-+ for (i = 0; i < NR_DESCS_PER_CHANNEL; i++) {
-+ desc = ops->embedded_desc(schan->desc, i);
-+ dma_async_tx_descriptor_init(&desc->async_tx,
-+ &schan->dma_chan);
-+ desc->async_tx.tx_submit = shdma_tx_submit;
-+ desc->mark = DESC_IDLE;
-+
-+ list_add(&desc->node, &schan->ld_free);
-+ }
-+
-+ return NR_DESCS_PER_CHANNEL;
-+
-+edescalloc:
-+ if (slave)
-+esetslave:
-+ clear_bit(slave->slave_id, shdma_slave_used);
-+etestused:
-+evalid:
-+ chan->private = NULL;
-+ return ret;
-+}
-+
-+static dma_async_tx_callback __ld_cleanup(struct shdma_chan *schan, bool all)
-+{
-+ struct shdma_desc *desc, *_desc;
-+ /* Is the "exposed" head of a chain acked? */
-+ bool head_acked = false;
-+ dma_cookie_t cookie = 0;
-+ dma_async_tx_callback callback = NULL;
-+ void *param = NULL;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&schan->chan_lock, flags);
-+ list_for_each_entry_safe(desc, _desc, &schan->ld_queue, node) {
-+ struct dma_async_tx_descriptor *tx = &desc->async_tx;
-+
-+ BUG_ON(tx->cookie > 0 && tx->cookie != desc->cookie);
-+ BUG_ON(desc->mark != DESC_SUBMITTED &&
-+ desc->mark != DESC_COMPLETED &&
-+ desc->mark != DESC_WAITING);
-+
-+ /*
-+ * queue is ordered, and we use this loop to (1) clean up all
-+ * completed descriptors, and to (2) update descriptor flags of
-+ * any chunks in a (partially) completed chain
-+ */
-+ if (!all && desc->mark == DESC_SUBMITTED &&
-+ desc->cookie != cookie)
-+ break;
-+
-+ if (tx->cookie > 0)
-+ cookie = tx->cookie;
-+
-+ if (desc->mark == DESC_COMPLETED && desc->chunks == 1) {
-+ if (schan->dma_chan.completed_cookie != desc->cookie - 1)
-+ dev_dbg(schan->dev,
-+ "Completing cookie %d, expected %d\n",
-+ desc->cookie,
-+ schan->dma_chan.completed_cookie + 1);
-+ schan->dma_chan.completed_cookie = desc->cookie;
-+ }
-+
-+ /* Call callback on the last chunk */
-+ if (desc->mark == DESC_COMPLETED && tx->callback) {
-+ desc->mark = DESC_WAITING;
-+ callback = tx->callback;
-+ param = tx->callback_param;
-+ dev_dbg(schan->dev, "descriptor #%d@%p on %d callback\n",
-+ tx->cookie, tx, schan->id);
-+ BUG_ON(desc->chunks != 1);
-+ break;
-+ }
-+
-+ if (tx->cookie > 0 || tx->cookie == -EBUSY) {
-+ if (desc->mark == DESC_COMPLETED) {
-+ BUG_ON(tx->cookie < 0);
-+ desc->mark = DESC_WAITING;
-+ }
-+ head_acked = async_tx_test_ack(tx);
-+ } else {
-+ switch (desc->mark) {
-+ case DESC_COMPLETED:
-+ desc->mark = DESC_WAITING;
-+ /* Fall through */
-+ case DESC_WAITING:
-+ if (head_acked)
-+ async_tx_ack(&desc->async_tx);
-+ }
-+ }
-+
-+ dev_dbg(schan->dev, "descriptor %p #%d completed.\n",
-+ tx, tx->cookie);
-+
-+ if (((desc->mark == DESC_COMPLETED ||
-+ desc->mark == DESC_WAITING) &&
-+ async_tx_test_ack(&desc->async_tx)) || all) {
-+ /* Remove from ld_queue list */
-+ desc->mark = DESC_IDLE;
-+
-+ list_move(&desc->node, &schan->ld_free);
-+
-+ if (list_empty(&schan->ld_queue)) {
-+ dev_dbg(schan->dev, "Bring down channel %d\n", schan->id);
-+ pm_runtime_put(schan->dev);
-+ schan->pm_state = SHDMA_PM_ESTABLISHED;
-+ }
-+ }
-+ }
-+
-+ if (all && !callback)
-+ /*
-+ * Terminating and the loop completed normally: forgive
-+ * uncompleted cookies
-+ */
-+ schan->dma_chan.completed_cookie = schan->dma_chan.cookie;
-+
-+ spin_unlock_irqrestore(&schan->chan_lock, flags);
-+
-+ if (callback)
-+ callback(param);
-+
-+ return callback;
-+}
-+
-+/*
-+ * shdma_chan_ld_cleanup - Clean up link descriptors
-+ *
-+ * Clean up the ld_queue of DMA channel.
-+ */
-+static void shdma_chan_ld_cleanup(struct shdma_chan *schan, bool all)
-+{
-+ while (__ld_cleanup(schan, all))
-+ ;
-+}
-+
-+/*
-+ * shdma_free_chan_resources - Free all resources of the channel.
-+ */
-+static void shdma_free_chan_resources(struct dma_chan *chan)
-+{
-+ struct shdma_chan *schan = to_shdma_chan(chan);
-+ struct shdma_dev *sdev = to_shdma_dev(chan->device);
-+ const struct shdma_ops *ops = sdev->ops;
-+ LIST_HEAD(list);
-+
-+ /* Protect against ISR */
-+ spin_lock_irq(&schan->chan_lock);
-+ ops->halt_channel(schan);
-+ spin_unlock_irq(&schan->chan_lock);
-+
-+ /* Now no new interrupts will occur */
-+
-+ /* Prepared and not submitted descriptors can still be on the queue */
-+ if (!list_empty(&schan->ld_queue))
-+ shdma_chan_ld_cleanup(schan, true);
-+
-+ if (chan->private) {
-+ /* The caller is holding dma_list_mutex */
-+ struct shdma_slave *slave = chan->private;
-+ clear_bit(slave->slave_id, shdma_slave_used);
-+ chan->private = NULL;
-+ }
-+
-+ spin_lock_irq(&schan->chan_lock);
-+
-+ list_splice_init(&schan->ld_free, &list);
-+ schan->desc_num = 0;
-+
-+ spin_unlock_irq(&schan->chan_lock);
-+
-+ kfree(schan->desc);
-+}
-+
-+/**
-+ * shdma_add_desc - get, set up and return one transfer descriptor
-+ * @schan: DMA channel
-+ * @flags: DMA transfer flags
-+ * @dst: destination DMA address, incremented when direction equals
-+ * DMA_DEV_TO_MEM or DMA_MEM_TO_MEM
-+ * @src: source DMA address, incremented when direction equals
-+ * DMA_MEM_TO_DEV or DMA_MEM_TO_MEM
-+ * @len: DMA transfer length
-+ * @first: if NULL, set to the current descriptor and cookie set to -EBUSY
-+ * @direction: needed for slave DMA to decide which address to keep constant,
-+ * equals DMA_MEM_TO_MEM for MEMCPY
-+ * Returns 0 or an error
-+ * Locks: called with desc_lock held
-+ */
-+static struct shdma_desc *shdma_add_desc(struct shdma_chan *schan,
-+ unsigned long flags, dma_addr_t *dst, dma_addr_t *src, size_t *len,
-+ struct shdma_desc **first, enum dma_transfer_direction direction)
-+{
-+ struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
-+ const struct shdma_ops *ops = sdev->ops;
-+ struct shdma_desc *new;
-+ size_t copy_size = *len;
-+
-+ if (!copy_size)
-+ return NULL;
-+
-+ /* Allocate the link descriptor from the free list */
-+ new = shdma_get_desc(schan);
-+ if (!new) {
-+ dev_err(schan->dev, "No free link descriptor available\n");
-+ return NULL;
-+ }
-+
-+ ops->desc_setup(schan, new, *src, *dst, ©_size);
-+
-+ if (!*first) {
-+ /* First desc */
-+ new->async_tx.cookie = -EBUSY;
-+ *first = new;
-+ } else {
-+ /* Other desc - invisible to the user */
-+ new->async_tx.cookie = -EINVAL;
-+ }
-+
-+ dev_dbg(schan->dev,
-+ "chaining (%u/%u)@%x -> %x with %p, cookie %d\n",
-+ copy_size, *len, *src, *dst, &new->async_tx,
-+ new->async_tx.cookie);
-+
-+ new->mark = DESC_PREPARED;
-+ new->async_tx.flags = flags;
-+ new->direction = direction;
-+
-+ *len -= copy_size;
-+ if (direction == DMA_MEM_TO_MEM || direction == DMA_MEM_TO_DEV)
-+ *src += copy_size;
-+ if (direction == DMA_MEM_TO_MEM || direction == DMA_DEV_TO_MEM)
-+ *dst += copy_size;
-+
-+ return new;
-+}
-+
-+/*
-+ * shdma_prep_sg - prepare transfer descriptors from an SG list
-+ *
-+ * Common routine for public (MEMCPY) and slave DMA. The MEMCPY case is also
-+ * converted to scatter-gather to guarantee consistent locking and a correct
-+ * list manipulation. For slave DMA direction carries the usual meaning, and,
-+ * logically, the SG list is RAM and the addr variable contains slave address,
-+ * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_MEM_TO_MEM
-+ * and the SG list contains only one element and points at the source buffer.
-+ */
-+static struct dma_async_tx_descriptor *shdma_prep_sg(struct shdma_chan *schan,
-+ struct scatterlist *sgl, unsigned int sg_len, dma_addr_t *addr,
-+ enum dma_transfer_direction direction, unsigned long flags)
-+{
-+ struct scatterlist *sg;
-+ struct shdma_desc *first = NULL, *new = NULL /* compiler... */;
-+ LIST_HEAD(tx_list);
-+ int chunks = 0;
-+ unsigned long irq_flags;
-+ int i;
-+
-+ for_each_sg(sgl, sg, sg_len, i)
-+ chunks += DIV_ROUND_UP(sg_dma_len(sg), schan->max_xfer_len);
-+
-+ /* Have to lock the whole loop to protect against concurrent release */
-+ spin_lock_irqsave(&schan->chan_lock, irq_flags);
-+
-+ /*
-+ * Chaining:
-+ * first descriptor is what user is dealing with in all API calls, its
-+ * cookie is at first set to -EBUSY, at tx-submit to a positive
-+ * number
-+ * if more than one chunk is needed further chunks have cookie = -EINVAL
-+ * the last chunk, if not equal to the first, has cookie = -ENOSPC
-+ * all chunks are linked onto the tx_list head with their .node heads
-+ * only during this function, then they are immediately spliced
-+ * back onto the free list in form of a chain
-+ */
-+ for_each_sg(sgl, sg, sg_len, i) {
-+ dma_addr_t sg_addr = sg_dma_address(sg);
-+ size_t len = sg_dma_len(sg);
-+
-+ if (!len)
-+ goto err_get_desc;
-+
-+ do {
-+ dev_dbg(schan->dev, "Add SG #%d@%p[%d], dma %llx\n",
-+ i, sg, len, (unsigned long long)sg_addr);
-+
-+ if (direction == DMA_DEV_TO_MEM)
-+ new = shdma_add_desc(schan, flags,
-+ &sg_addr, addr, &len, &first,
-+ direction);
-+ else
-+ new = shdma_add_desc(schan, flags,
-+ addr, &sg_addr, &len, &first,
-+ direction);
-+ if (!new)
-+ goto err_get_desc;
-+
-+ new->chunks = chunks--;
-+ list_add_tail(&new->node, &tx_list);
-+ } while (len);
-+ }
-+
-+ if (new != first)
-+ new->async_tx.cookie = -ENOSPC;
-+
-+ /* Put them back on the free list, so, they don't get lost */
-+ list_splice_tail(&tx_list, &schan->ld_free);
-+
-+ spin_unlock_irqrestore(&schan->chan_lock, irq_flags);
-+
-+ return &first->async_tx;
-+
-+err_get_desc:
-+ list_for_each_entry(new, &tx_list, node)
-+ new->mark = DESC_IDLE;
-+ list_splice(&tx_list, &schan->ld_free);
-+
-+ spin_unlock_irqrestore(&schan->chan_lock, irq_flags);
-+
-+ return NULL;
-+}
-+
-+static struct dma_async_tx_descriptor *shdma_prep_memcpy(
-+ struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
-+ size_t len, unsigned long flags)
-+{
-+ struct shdma_chan *schan = to_shdma_chan(chan);
-+ struct scatterlist sg;
-+
-+ if (!chan || !len)
-+ return NULL;
-+
-+ BUG_ON(!schan->desc_num);
-+
-+ sg_init_table(&sg, 1);
-+ sg_set_page(&sg, pfn_to_page(PFN_DOWN(dma_src)), len,
-+ offset_in_page(dma_src));
-+ sg_dma_address(&sg) = dma_src;
-+ sg_dma_len(&sg) = len;
-+
-+ return shdma_prep_sg(schan, &sg, 1, &dma_dest, DMA_MEM_TO_MEM, flags);
-+}
-+
-+static struct dma_async_tx_descriptor *shdma_prep_slave_sg(
-+ struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
-+ enum dma_transfer_direction direction, unsigned long flags, void *context)
-+{
-+ struct shdma_chan *schan = to_shdma_chan(chan);
-+ struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
-+ const struct shdma_ops *ops = sdev->ops;
-+ struct shdma_slave *slave = chan->private;
-+ dma_addr_t slave_addr;
-+
-+ if (!chan)
-+ return NULL;
-+
-+ BUG_ON(!schan->desc_num);
-+
-+ /* Someone calling slave DMA on a generic channel? */
-+ if (!slave || !sg_len) {
-+ dev_warn(schan->dev, "%s: bad parameter: %p, %d, %d\n",
-+ __func__, slave, sg_len, slave ? slave->slave_id : -1);
-+ return NULL;
-+ }
-+
-+ slave_addr = ops->slave_addr(schan);
-+
-+ return shdma_prep_sg(schan, sgl, sg_len, &slave_addr,
-+ direction, flags);
-+}
-+
-+static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
-+ unsigned long arg)
-+{
-+ struct shdma_chan *schan = to_shdma_chan(chan);
-+ struct shdma_dev *sdev = to_shdma_dev(chan->device);
-+ const struct shdma_ops *ops = sdev->ops;
-+ unsigned long flags;
-+
-+ /* Only supports DMA_TERMINATE_ALL */
-+ if (cmd != DMA_TERMINATE_ALL)
-+ return -ENXIO;
-+
-+ if (!chan)
-+ return -EINVAL;
-+
-+ spin_lock_irqsave(&schan->chan_lock, flags);
-+
-+ ops->halt_channel(schan);
-+
-+ spin_unlock_irqrestore(&schan->chan_lock, flags);
-+
-+ shdma_chan_ld_cleanup(schan, true);
-+
-+ return 0;
-+}
-+
-+static void shdma_issue_pending(struct dma_chan *chan)
-+{
-+ struct shdma_chan *schan = to_shdma_chan(chan);
-+
-+ spin_lock_irq(&schan->chan_lock);
-+ if (schan->pm_state == SHDMA_PM_ESTABLISHED)
-+ shdma_chan_xfer_ld_queue(schan);
-+ else
-+ schan->pm_state = SHDMA_PM_PENDING;
-+ spin_unlock_irq(&schan->chan_lock);
-+}
-+
-+static enum dma_status shdma_tx_status(struct dma_chan *chan,
-+ dma_cookie_t cookie,
-+ struct dma_tx_state *txstate)
-+{
-+ struct shdma_chan *schan = to_shdma_chan(chan);
-+ enum dma_status status;
-+ unsigned long flags;
-+
-+ shdma_chan_ld_cleanup(schan, false);
-+
-+ spin_lock_irqsave(&schan->chan_lock, flags);
-+
-+ status = dma_cookie_status(chan, cookie, txstate);
-+
-+ /*
-+ * If we don't find cookie on the queue, it has been aborted and we have
-+ * to report error
-+ */
-+ if (status != DMA_SUCCESS) {
-+ struct shdma_desc *sdesc;
-+ status = DMA_ERROR;
-+ list_for_each_entry(sdesc, &schan->ld_queue, node)
-+ if (sdesc->cookie == cookie) {
-+ status = DMA_IN_PROGRESS;
-+ break;
-+ }
-+ }
-+
-+ spin_unlock_irqrestore(&schan->chan_lock, flags);
-+
-+ return status;
-+}
-+
-+/* Called from error IRQ or NMI */
-+bool shdma_reset(struct shdma_dev *sdev)
-+{
-+ const struct shdma_ops *ops = sdev->ops;
-+ struct shdma_chan *schan;
-+ unsigned int handled = 0;
-+ int i;
-+
-+ /* Reset all channels */
-+ shdma_for_each_chan(schan, sdev, i) {
-+ struct shdma_desc *sdesc;
-+ LIST_HEAD(dl);
-+
-+ if (!schan)
-+ continue;
-+
-+ spin_lock(&schan->chan_lock);
-+
-+ /* Stop the channel */
-+ ops->halt_channel(schan);
-+
-+ list_splice_init(&schan->ld_queue, &dl);
-+
-+ if (!list_empty(&dl)) {
-+ dev_dbg(schan->dev, "Bring down channel %d\n", schan->id);
-+ pm_runtime_put(schan->dev);
-+ }
-+ schan->pm_state = SHDMA_PM_ESTABLISHED;
-+
-+ spin_unlock(&schan->chan_lock);
-+
-+ /* Complete all */
-+ list_for_each_entry(sdesc, &dl, node) {
-+ struct dma_async_tx_descriptor *tx = &sdesc->async_tx;
-+ sdesc->mark = DESC_IDLE;
-+ if (tx->callback)
-+ tx->callback(tx->callback_param);
-+ }
-+
-+ spin_lock(&schan->chan_lock);
-+ list_splice(&dl, &schan->ld_free);
-+ spin_unlock(&schan->chan_lock);
-+
-+ handled++;
-+ }
-+
-+ return !!handled;
-+}
-+EXPORT_SYMBOL(shdma_reset);
-+
-+static irqreturn_t chan_irq(int irq, void *dev)
-+{
-+ struct shdma_chan *schan = dev;
-+ const struct shdma_ops *ops =
-+ to_shdma_dev(schan->dma_chan.device)->ops;
-+ irqreturn_t ret;
-+
-+ spin_lock(&schan->chan_lock);
-+
-+ ret = ops->chan_irq(schan, irq) ? IRQ_WAKE_THREAD : IRQ_NONE;
-+
-+ spin_unlock(&schan->chan_lock);
-+
-+ return ret;
-+}
-+
-+static irqreturn_t chan_irqt(int irq, void *dev)
-+{
-+ struct shdma_chan *schan = dev;
-+ const struct shdma_ops *ops =
-+ to_shdma_dev(schan->dma_chan.device)->ops;
-+ struct shdma_desc *sdesc;
-+
-+ spin_lock_irq(&schan->chan_lock);
-+ list_for_each_entry(sdesc, &schan->ld_queue, node) {
-+ if (sdesc->mark == DESC_SUBMITTED &&
-+ ops->desc_completed(schan, sdesc)) {
-+ dev_dbg(schan->dev, "done #%d@%p\n",
-+ sdesc->async_tx.cookie, &sdesc->async_tx);
-+ sdesc->mark = DESC_COMPLETED;
-+ break;
-+ }
-+ }
-+ /* Next desc */
-+ shdma_chan_xfer_ld_queue(schan);
-+ spin_unlock_irq(&schan->chan_lock);
-+
-+ shdma_chan_ld_cleanup(schan, false);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+int shdma_request_irq(struct shdma_chan *schan, int irq,
-+ unsigned long flags, const char *name)
-+{
-+ int ret = request_threaded_irq(irq, chan_irq, chan_irqt,
-+ flags, name, schan);
-+
-+ schan->irq = ret < 0 ? ret : irq;
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL(shdma_request_irq);
-+
-+void shdma_free_irq(struct shdma_chan *schan)
-+{
-+ if (schan->irq >= 0)
-+ free_irq(schan->irq, schan);
-+}
-+EXPORT_SYMBOL(shdma_free_irq);
-+
-+void shdma_chan_probe(struct shdma_dev *sdev,
-+ struct shdma_chan *schan, int id)
-+{
-+ schan->pm_state = SHDMA_PM_ESTABLISHED;
-+
-+ /* reference struct dma_device */
-+ schan->dma_chan.device = &sdev->dma_dev;
-+ dma_cookie_init(&schan->dma_chan);
-+
-+ schan->dev = sdev->dma_dev.dev;
-+ schan->id = id;
-+
-+ if (!schan->max_xfer_len)
-+ schan->max_xfer_len = PAGE_SIZE;
-+
-+ spin_lock_init(&schan->chan_lock);
-+
-+ /* Init descripter manage list */
-+ INIT_LIST_HEAD(&schan->ld_queue);
-+ INIT_LIST_HEAD(&schan->ld_free);
-+
-+ /* Add the channel to DMA device channel list */
-+ list_add_tail(&schan->dma_chan.device_node,
-+ &sdev->dma_dev.channels);
-+ sdev->schan[sdev->dma_dev.chancnt++] = schan;
-+}
-+EXPORT_SYMBOL(shdma_chan_probe);
-+
-+void shdma_chan_remove(struct shdma_chan *schan)
-+{
-+ list_del(&schan->dma_chan.device_node);
-+}
-+EXPORT_SYMBOL(shdma_chan_remove);
-+
-+int shdma_init(struct device *dev, struct shdma_dev *sdev,
-+ int chan_num)
-+{
-+ struct dma_device *dma_dev = &sdev->dma_dev;
-+
-+ /*
-+ * Require all call-backs for now, they can trivially be made optional
-+ * later as required
-+ */
-+ if (!sdev->ops ||
-+ !sdev->desc_size ||
-+ !sdev->ops->embedded_desc ||
-+ !sdev->ops->start_xfer ||
-+ !sdev->ops->setup_xfer ||
-+ !sdev->ops->set_slave ||
-+ !sdev->ops->desc_setup ||
-+ !sdev->ops->slave_addr ||
-+ !sdev->ops->channel_busy ||
-+ !sdev->ops->halt_channel ||
-+ !sdev->ops->desc_completed)
-+ return -EINVAL;
-+
-+ sdev->schan = kcalloc(chan_num, sizeof(*sdev->schan), GFP_KERNEL);
-+ if (!sdev->schan)
-+ return -ENOMEM;
-+
-+ INIT_LIST_HEAD(&dma_dev->channels);
-+
-+ /* Common and MEMCPY operations */
-+ dma_dev->device_alloc_chan_resources
-+ = shdma_alloc_chan_resources;
-+ dma_dev->device_free_chan_resources = shdma_free_chan_resources;
-+ dma_dev->device_prep_dma_memcpy = shdma_prep_memcpy;
-+ dma_dev->device_tx_status = shdma_tx_status;
-+ dma_dev->device_issue_pending = shdma_issue_pending;
-+
-+ /* Compulsory for DMA_SLAVE fields */
-+ dma_dev->device_prep_slave_sg = shdma_prep_slave_sg;
-+ dma_dev->device_control = shdma_control;
-+
-+ dma_dev->dev = dev;
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(shdma_init);
-+
-+void shdma_cleanup(struct shdma_dev *sdev)
-+{
-+ kfree(sdev->schan);
-+}
-+EXPORT_SYMBOL(shdma_cleanup);
-+
-+static int __init shdma_enter(void)
-+{
-+ shdma_slave_used = kzalloc(DIV_ROUND_UP(slave_num, BITS_PER_LONG) *
-+ sizeof(long), GFP_KERNEL);
-+ if (!shdma_slave_used)
-+ return -ENOMEM;
-+ return 0;
-+}
-+module_init(shdma_enter);
-+
-+static void __exit shdma_exit(void)
-+{
-+ kfree(shdma_slave_used);
-+}
-+module_exit(shdma_exit);
-+
-+MODULE_LICENSE("GPL v2");
-+MODULE_DESCRIPTION("SH-DMA driver base library");
-+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
-diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
-new file mode 100644
-index 0000000..83efd13
---- /dev/null
-+++ b/include/linux/shdma-base.h
-@@ -0,0 +1,123 @@
-+/*
-+ * Dmaengine driver base library for DMA controllers, found on SH-based SoCs
-+ *
-+ * extracted from shdma.c and headers
-+ *
-+ * Copyright (C) 2011-2012 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-+ * Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
-+ * Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved.
-+ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
-+ *
-+ * This is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef SHDMA_BASE_H
-+#define SHDMA_BASE_H
-+
-+#include <linux/dmaengine.h>
-+#include <linux/interrupt.h>
-+#include <linux/list.h>
-+#include <linux/types.h>
-+
-+/**
-+ * shdma_pm_state - DMA channel PM state
-+ * SHDMA_PM_ESTABLISHED: either idle or during data transfer
-+ * SHDMA_PM_BUSY: during the transfer preparation, when we have to
-+ * drop the lock temporarily
-+ * SHDMA_PM_PENDING: transfers pending
-+ */
-+enum shdma_pm_state {
-+ SHDMA_PM_ESTABLISHED,
-+ SHDMA_PM_BUSY,
-+ SHDMA_PM_PENDING,
-+};
-+
-+struct device;
-+
-+/*
-+ * Drivers, using this library are expected to embed struct shdma_dev,
-+ * struct shdma_chan, struct shdma_desc, and struct shdma_slave
-+ * in their respective device, channel, descriptor and slave objects.
-+ */
-+
-+struct shdma_slave {
-+ unsigned int slave_id;
-+};
-+
-+struct shdma_desc {
-+ struct list_head node;
-+ struct dma_async_tx_descriptor async_tx;
-+ enum dma_transfer_direction direction;
-+ dma_cookie_t cookie;
-+ int chunks;
-+ int mark;
-+};
-+
-+struct shdma_chan {
-+ spinlock_t chan_lock; /* Channel operation lock */
-+ struct list_head ld_queue; /* Link descriptors queue */
-+ struct list_head ld_free; /* Free link descriptors */
-+ struct dma_chan dma_chan; /* DMA channel */
-+ struct device *dev; /* Channel device */
-+ void *desc; /* buffer for descriptor array */
-+ int desc_num; /* desc count */
-+ size_t max_xfer_len; /* max transfer length */
-+ int id; /* Raw id of this channel */
-+ int irq; /* Channel IRQ */
-+ enum shdma_pm_state pm_state;
-+};
-+
-+/**
-+ * struct shdma_ops - simple DMA driver operations
-+ * desc_completed: return true, if this is the descriptor, that just has
-+ * completed (atomic)
-+ * halt_channel: stop DMA channel operation (atomic)
-+ * channel_busy: return true, if the channel is busy (atomic)
-+ * slave_addr: return slave DMA address
-+ * desc_setup: set up the hardware specific descriptor portion (atomic)
-+ * set_slave: bind channel to a slave
-+ * setup_xfer: configure channel hardware for operation (atomic)
-+ * start_xfer: start the DMA transfer (atomic)
-+ * embedded_desc: return Nth struct shdma_desc pointer from the
-+ * descriptor array
-+ * chan_irq: process channel IRQ, return true if a transfer has
-+ * completed (atomic)
-+ */
-+struct shdma_ops {
-+ bool (*desc_completed)(struct shdma_chan *, struct shdma_desc *);
-+ void (*halt_channel)(struct shdma_chan *);
-+ bool (*channel_busy)(struct shdma_chan *);
-+ dma_addr_t (*slave_addr)(struct shdma_chan *);
-+ int (*desc_setup)(struct shdma_chan *, struct shdma_desc *,
-+ dma_addr_t, dma_addr_t, size_t *);
-+ int (*set_slave)(struct shdma_chan *, struct shdma_slave *);
-+ void (*setup_xfer)(struct shdma_chan *, struct shdma_slave *);
-+ void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
-+ struct shdma_desc *(*embedded_desc)(void *, int);
-+ bool (*chan_irq)(struct shdma_chan *, int);
-+};
-+
-+struct shdma_dev {
-+ struct dma_device dma_dev;
-+ struct shdma_chan **schan;
-+ const struct shdma_ops *ops;
-+ size_t desc_size;
-+};
-+
-+#define shdma_for_each_chan(c, d, i) for (i = 0, c = (d)->schan[0]; \
-+ i < (d)->dma_dev.chancnt; c = (d)->schan[++i])
-+
-+int shdma_request_irq(struct shdma_chan *, int,
-+ unsigned long, const char *);
-+void shdma_free_irq(struct shdma_chan *);
-+bool shdma_reset(struct shdma_dev *sdev);
-+void shdma_chan_probe(struct shdma_dev *sdev,
-+ struct shdma_chan *schan, int id);
-+void shdma_chan_remove(struct shdma_chan *schan);
-+int shdma_init(struct device *dev, struct shdma_dev *sdev,
-+ int chan_num);
-+void shdma_cleanup(struct shdma_dev *sdev);
-+
-+#endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ede599a5d672322a39cf12cc4fdb59fe67898908 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 9 May 2012 17:09:14 +0200
-Subject: dma: shdma: prepare for conversion to the shdma base library
-
-By placing an anonymous union at the top of struct sh_dmae_slave we can
-transparently prepare all device and client drivers for the upcoming
-shdma-base conversion.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit 5902c9a7a2a9c2520af54af1ba7a9c7831664a17)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- include/linux/sh_dma.h | 8 ++++++--
- 1 file changed, 6 insertions(+), 2 deletions(-)
-
-diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
-index 425450b..e081e8e 100644
---- a/include/linux/sh_dma.h
-+++ b/include/linux/sh_dma.h
-@@ -10,12 +10,16 @@
- #ifndef SH_DMA_H
- #define SH_DMA_H
-
--#include <linux/list.h>
- #include <linux/dmaengine.h>
-+#include <linux/list.h>
-+#include <linux/shdma-base.h>
-
- /* Used by slave DMA clients to request DMA to/from a specific peripheral */
- struct sh_dmae_slave {
-- unsigned int slave_id; /* Set by the platform */
-+ union {
-+ unsigned int slave_id; /* Set by the platform */
-+ struct shdma_slave shdma_slave;
-+ };
- struct device *dma_dev; /* Set by the platform */
- const struct sh_dmae_slave_config *config; /* Set by the driver */
- };
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 6381d33c361574132c3152d0cfa56278a67d40f7 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 9 May 2012 17:09:20 +0200
-Subject: ASoC: fsi: prepare for conversion to the shdma base library
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Cc: Liam Girdwood <lrg@ti.com>
-Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
-Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit b8373147ed3ca01a968d81f22688f2836a9aeb6b)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- sound/soc/sh/fsi.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/sound/soc/sh/fsi.c
-+++ b/sound/soc/sh/fsi.c
-@@ -1533,8 +1533,8 @@ static void fsi_handler_init(struct fsi_
- fsi->capture.priv = fsi;
-
- if (fsi->info->tx_id) {
-- fsi->playback.slave.slave_id = fsi->info->tx_id;
-- fsi->playback.handler = &fsi_dma_push_handler;
-+ fsi->playback.slave.shdma_slave.slave_id = fsi->info->tx_id;
-+ fsi->playback.handler = &fsi_dma_push_handler;
- }
- }
-
+++ /dev/null
-From a840c360c6d890060307ee970d8630f9bf812af1 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 9 May 2012 17:09:19 +0200
-Subject: usb: renesas_usbhs: prepare for conversion to the shdma base library
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit f19b7e0db7744dd1ed6052cc58a90b74a29772b8)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/usb/renesas_usbhs/fifo.c | 10 +++++-----
- 1 file changed, 5 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
-index 6ec7f83..fc597a4 100644
---- a/drivers/usb/renesas_usbhs/fifo.c
-+++ b/drivers/usb/renesas_usbhs/fifo.c
-@@ -994,7 +994,7 @@ static bool usbhsf_dma_filter(struct dma_chan *chan, void *param)
- *
- * usbhs doesn't recognize id = 0 as valid DMA
- */
-- if (0 == slave->slave_id)
-+ if (0 == slave->shdma_slave.slave_id)
- return false;
-
- chan->private = slave;
-@@ -1173,8 +1173,8 @@ int usbhs_fifo_probe(struct usbhs_priv *priv)
- fifo->port = D0FIFO;
- fifo->sel = D0FIFOSEL;
- fifo->ctr = D0FIFOCTR;
-- fifo->tx_slave.slave_id = usbhs_get_dparam(priv, d0_tx_id);
-- fifo->rx_slave.slave_id = usbhs_get_dparam(priv, d0_rx_id);
-+ fifo->tx_slave.shdma_slave.slave_id = usbhs_get_dparam(priv, d0_tx_id);
-+ fifo->rx_slave.shdma_slave.slave_id = usbhs_get_dparam(priv, d0_rx_id);
-
- /* D1FIFO */
- fifo = usbhsf_get_d1fifo(priv);
-@@ -1182,8 +1182,8 @@ int usbhs_fifo_probe(struct usbhs_priv *priv)
- fifo->port = D1FIFO;
- fifo->sel = D1FIFOSEL;
- fifo->ctr = D1FIFOCTR;
-- fifo->tx_slave.slave_id = usbhs_get_dparam(priv, d1_tx_id);
-- fifo->rx_slave.slave_id = usbhs_get_dparam(priv, d1_rx_id);
-+ fifo->tx_slave.shdma_slave.slave_id = usbhs_get_dparam(priv, d1_tx_id);
-+ fifo->rx_slave.shdma_slave.slave_id = usbhs_get_dparam(priv, d1_rx_id);
-
- return 0;
- }
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 67976cd109fc26028e9fbcede6badbf236d865e8 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 9 May 2012 17:09:21 +0200
-Subject: dma: shdma: convert to the shdma base library
-
-The shdma base library has originally been extracted from the shdma driver,
-which now can be converted to actually use it.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit ce3a1ab74264b860450709e4bd0dcfc2d0bfc7f8)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/dma/sh/shdma.c | 1122 ++++++++++++------------------------------------
- drivers/dma/sh/shdma.h | 44 +-
- include/linux/sh_dma.h | 33 +-
- 3 files changed, 302 insertions(+), 897 deletions(-)
-
-diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
-index 8ab4a1f..c393b35 100644
---- a/drivers/dma/sh/shdma.c
-+++ b/drivers/dma/sh/shdma.c
-@@ -3,6 +3,7 @@
- *
- * base is drivers/dma/flsdma.c
- *
-+ * Copyright (C) 2011-2012 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- * Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
- * Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved.
- * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
-@@ -34,18 +35,12 @@
- #include "../dmaengine.h"
- #include "shdma.h"
-
--/* DMA descriptor control */
--enum sh_dmae_desc_status {
-- DESC_IDLE,
-- DESC_PREPARED,
-- DESC_SUBMITTED,
-- DESC_COMPLETED, /* completed, have to call callback */
-- DESC_WAITING, /* callback called, waiting for ack / re-submit */
--};
-+#define SH_DMAE_DRV_NAME "sh-dma-engine"
-
--#define NR_DESCS_PER_CHANNEL 32
- /* Default MEMCPY transfer size = 2^2 = 4 bytes */
- #define LOG2_DEFAULT_XFER_SIZE 2
-+#define SH_DMA_SLAVE_NUMBER 256
-+#define SH_DMA_TCR_MAX (16 * 1024 * 1024 - 1)
-
- /*
- * Used for write-side mutual exclusion for the global device list,
-@@ -54,18 +49,12 @@ enum sh_dmae_desc_status {
- static DEFINE_SPINLOCK(sh_dmae_lock);
- static LIST_HEAD(sh_dmae_devices);
-
--/* A bitmask with bits enough for enum sh_dmae_slave_chan_id */
--static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)];
--
--static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all);
--static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan);
--
- static void chclr_write(struct sh_dmae_chan *sh_dc, u32 data)
- {
- struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
-
- __raw_writel(data, shdev->chan_reg +
-- shdev->pdata->channel[sh_dc->id].chclr_offset);
-+ shdev->pdata->channel[sh_dc->shdma_chan.id].chclr_offset);
- }
-
- static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg)
-@@ -155,11 +144,11 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev)
- spin_unlock_irqrestore(&sh_dmae_lock, flags);
-
- if (dmaor & (DMAOR_AE | DMAOR_NMIF)) {
-- dev_warn(shdev->common.dev, "Can't initialize DMAOR.\n");
-+ dev_warn(shdev->shdma_dev.dma_dev.dev, "Can't initialize DMAOR.\n");
- return -EIO;
- }
- if (shdev->pdata->dmaor_init & ~dmaor)
-- dev_warn(shdev->common.dev,
-+ dev_warn(shdev->shdma_dev.dma_dev.dev,
- "DMAOR=0x%x hasn't latched the initial value 0x%x.\n",
- dmaor, shdev->pdata->dmaor_init);
- return 0;
-@@ -224,15 +213,6 @@ static void dmae_start(struct sh_dmae_chan *sh_chan)
- chcr_write(sh_chan, chcr & ~CHCR_TE);
- }
-
--static void dmae_halt(struct sh_dmae_chan *sh_chan)
--{
-- struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
-- u32 chcr = chcr_read(sh_chan);
--
-- chcr &= ~(CHCR_DE | CHCR_TE | shdev->chcr_ie_bit);
-- chcr_write(sh_chan, chcr);
--}
--
- static void dmae_init(struct sh_dmae_chan *sh_chan)
- {
- /*
-@@ -261,7 +241,7 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
- {
- struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
- struct sh_dmae_pdata *pdata = shdev->pdata;
-- const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id];
-+ const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->shdma_chan.id];
- u16 __iomem *addr = shdev->dmars;
- unsigned int shift = chan_pdata->dmars_bit;
-
-@@ -282,706 +262,142 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
- return 0;
- }
-
--static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
-+static void sh_dmae_start_xfer(struct shdma_chan *schan,
-+ struct shdma_desc *sdesc)
- {
-- struct sh_desc *desc = tx_to_sh_desc(tx), *chunk, *last = desc, *c;
-- struct sh_dmae_chan *sh_chan = to_sh_chan(tx->chan);
-- struct sh_dmae_slave *param = tx->chan->private;
-- dma_async_tx_callback callback = tx->callback;
-- dma_cookie_t cookie;
-- bool power_up;
--
-- spin_lock_irq(&sh_chan->desc_lock);
--
-- if (list_empty(&sh_chan->ld_queue))
-- power_up = true;
-- else
-- power_up = false;
--
-- cookie = dma_cookie_assign(tx);
--
-- /* Mark all chunks of this descriptor as submitted, move to the queue */
-- list_for_each_entry_safe(chunk, c, desc->node.prev, node) {
-- /*
-- * All chunks are on the global ld_free, so, we have to find
-- * the end of the chain ourselves
-- */
-- if (chunk != desc && (chunk->mark == DESC_IDLE ||
-- chunk->async_tx.cookie > 0 ||
-- chunk->async_tx.cookie == -EBUSY ||
-- &chunk->node == &sh_chan->ld_free))
-- break;
-- chunk->mark = DESC_SUBMITTED;
-- /* Callback goes to the last chunk */
-- chunk->async_tx.callback = NULL;
-- chunk->cookie = cookie;
-- list_move_tail(&chunk->node, &sh_chan->ld_queue);
-- last = chunk;
-- }
--
-- last->async_tx.callback = callback;
-- last->async_tx.callback_param = tx->callback_param;
--
-- dev_dbg(sh_chan->dev, "submit #%d@%p on %d: %x[%d] -> %x\n",
-- tx->cookie, &last->async_tx, sh_chan->id,
-- desc->hw.sar, desc->hw.tcr, desc->hw.dar);
--
-- if (power_up) {
-- sh_chan->pm_state = DMAE_PM_BUSY;
--
-- pm_runtime_get(sh_chan->dev);
--
-- spin_unlock_irq(&sh_chan->desc_lock);
--
-- pm_runtime_barrier(sh_chan->dev);
--
-- spin_lock_irq(&sh_chan->desc_lock);
--
-- /* Have we been reset, while waiting? */
-- if (sh_chan->pm_state != DMAE_PM_ESTABLISHED) {
-- dev_dbg(sh_chan->dev, "Bring up channel %d\n",
-- sh_chan->id);
-- if (param) {
-- const struct sh_dmae_slave_config *cfg =
-- param->config;
--
-- dmae_set_dmars(sh_chan, cfg->mid_rid);
-- dmae_set_chcr(sh_chan, cfg->chcr);
-- } else {
-- dmae_init(sh_chan);
-- }
--
-- if (sh_chan->pm_state == DMAE_PM_PENDING)
-- sh_chan_xfer_ld_queue(sh_chan);
-- sh_chan->pm_state = DMAE_PM_ESTABLISHED;
-- }
-- } else {
-- sh_chan->pm_state = DMAE_PM_PENDING;
-- }
--
-- spin_unlock_irq(&sh_chan->desc_lock);
--
-- return cookie;
-+ struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
-+ shdma_chan);
-+ struct sh_dmae_desc *sh_desc = container_of(sdesc,
-+ struct sh_dmae_desc, shdma_desc);
-+ dev_dbg(sh_chan->shdma_chan.dev, "Queue #%d to %d: %u@%x -> %x\n",
-+ sdesc->async_tx.cookie, sh_chan->shdma_chan.id,
-+ sh_desc->hw.tcr, sh_desc->hw.sar, sh_desc->hw.dar);
-+ /* Get the ld start address from ld_queue */
-+ dmae_set_reg(sh_chan, &sh_desc->hw);
-+ dmae_start(sh_chan);
- }
-
--/* Called with desc_lock held */
--static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan)
-+static bool sh_dmae_channel_busy(struct shdma_chan *schan)
- {
-- struct sh_desc *desc;
--
-- list_for_each_entry(desc, &sh_chan->ld_free, node)
-- if (desc->mark != DESC_PREPARED) {
-- BUG_ON(desc->mark != DESC_IDLE);
-- list_del(&desc->node);
-- return desc;
-- }
--
-- return NULL;
-+ struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
-+ shdma_chan);
-+ return dmae_is_busy(sh_chan);
- }
-
--static const struct sh_dmae_slave_config *sh_dmae_find_slave(
-- struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *param)
-+static void sh_dmae_setup_xfer(struct shdma_chan *schan,
-+ struct shdma_slave *sslave)
- {
-- struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
-- struct sh_dmae_pdata *pdata = shdev->pdata;
-- int i;
-+ struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
-+ shdma_chan);
-
-- if (param->slave_id >= SH_DMA_SLAVE_NUMBER)
-- return NULL;
--
-- for (i = 0; i < pdata->slave_num; i++)
-- if (pdata->slave[i].slave_id == param->slave_id)
-- return pdata->slave + i;
--
-- return NULL;
--}
--
--static int sh_dmae_alloc_chan_resources(struct dma_chan *chan)
--{
-- struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
-- struct sh_desc *desc;
-- struct sh_dmae_slave *param = chan->private;
-- int ret;
-+ if (sslave) {
-+ struct sh_dmae_slave *slave = container_of(sslave,
-+ struct sh_dmae_slave, shdma_slave);
-+ const struct sh_dmae_slave_config *cfg =
-+ slave->config;
-
-- /*
-- * This relies on the guarantee from dmaengine that alloc_chan_resources
-- * never runs concurrently with itself or free_chan_resources.
-- */
-- if (param) {
-- const struct sh_dmae_slave_config *cfg;
--
-- cfg = sh_dmae_find_slave(sh_chan, param);
-- if (!cfg) {
-- ret = -EINVAL;
-- goto efindslave;
-- }
--
-- if (test_and_set_bit(param->slave_id, sh_dmae_slave_used)) {
-- ret = -EBUSY;
-- goto etestused;
-- }
--
-- param->config = cfg;
-- }
--
-- while (sh_chan->descs_allocated < NR_DESCS_PER_CHANNEL) {
-- desc = kzalloc(sizeof(struct sh_desc), GFP_KERNEL);
-- if (!desc)
-- break;
-- dma_async_tx_descriptor_init(&desc->async_tx,
-- &sh_chan->common);
-- desc->async_tx.tx_submit = sh_dmae_tx_submit;
-- desc->mark = DESC_IDLE;
--
-- list_add(&desc->node, &sh_chan->ld_free);
-- sh_chan->descs_allocated++;
-- }
--
-- if (!sh_chan->descs_allocated) {
-- ret = -ENOMEM;
-- goto edescalloc;
-- }
--
-- return sh_chan->descs_allocated;
--
--edescalloc:
-- if (param)
-- clear_bit(param->slave_id, sh_dmae_slave_used);
--etestused:
--efindslave:
-- chan->private = NULL;
-- return ret;
--}
--
--/*
-- * sh_dma_free_chan_resources - Free all resources of the channel.
-- */
--static void sh_dmae_free_chan_resources(struct dma_chan *chan)
--{
-- struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
-- struct sh_desc *desc, *_desc;
-- LIST_HEAD(list);
--
-- /* Protect against ISR */
-- spin_lock_irq(&sh_chan->desc_lock);
-- dmae_halt(sh_chan);
-- spin_unlock_irq(&sh_chan->desc_lock);
--
-- /* Now no new interrupts will occur */
--
-- /* Prepared and not submitted descriptors can still be on the queue */
-- if (!list_empty(&sh_chan->ld_queue))
-- sh_dmae_chan_ld_cleanup(sh_chan, true);
--
-- if (chan->private) {
-- /* The caller is holding dma_list_mutex */
-- struct sh_dmae_slave *param = chan->private;
-- clear_bit(param->slave_id, sh_dmae_slave_used);
-- chan->private = NULL;
-- }
--
-- spin_lock_irq(&sh_chan->desc_lock);
--
-- list_splice_init(&sh_chan->ld_free, &list);
-- sh_chan->descs_allocated = 0;
--
-- spin_unlock_irq(&sh_chan->desc_lock);
--
-- list_for_each_entry_safe(desc, _desc, &list, node)
-- kfree(desc);
--}
--
--/**
-- * sh_dmae_add_desc - get, set up and return one transfer descriptor
-- * @sh_chan: DMA channel
-- * @flags: DMA transfer flags
-- * @dest: destination DMA address, incremented when direction equals
-- * DMA_DEV_TO_MEM
-- * @src: source DMA address, incremented when direction equals
-- * DMA_MEM_TO_DEV
-- * @len: DMA transfer length
-- * @first: if NULL, set to the current descriptor and cookie set to -EBUSY
-- * @direction: needed for slave DMA to decide which address to keep constant,
-- * equals DMA_MEM_TO_MEM for MEMCPY
-- * Returns 0 or an error
-- * Locks: called with desc_lock held
-- */
--static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan,
-- unsigned long flags, dma_addr_t *dest, dma_addr_t *src, size_t *len,
-- struct sh_desc **first, enum dma_transfer_direction direction)
--{
-- struct sh_desc *new;
-- size_t copy_size;
--
-- if (!*len)
-- return NULL;
--
-- /* Allocate the link descriptor from the free list */
-- new = sh_dmae_get_desc(sh_chan);
-- if (!new) {
-- dev_err(sh_chan->dev, "No free link descriptor available\n");
-- return NULL;
-- }
--
-- copy_size = min(*len, (size_t)SH_DMA_TCR_MAX + 1);
--
-- new->hw.sar = *src;
-- new->hw.dar = *dest;
-- new->hw.tcr = copy_size;
--
-- if (!*first) {
-- /* First desc */
-- new->async_tx.cookie = -EBUSY;
-- *first = new;
-+ dmae_set_dmars(sh_chan, cfg->mid_rid);
-+ dmae_set_chcr(sh_chan, cfg->chcr);
- } else {
-- /* Other desc - invisible to the user */
-- new->async_tx.cookie = -EINVAL;
-+ dmae_init(sh_chan);
- }
--
-- dev_dbg(sh_chan->dev,
-- "chaining (%u/%u)@%x -> %x with %p, cookie %d, shift %d\n",
-- copy_size, *len, *src, *dest, &new->async_tx,
-- new->async_tx.cookie, sh_chan->xmit_shift);
--
-- new->mark = DESC_PREPARED;
-- new->async_tx.flags = flags;
-- new->direction = direction;
--
-- *len -= copy_size;
-- if (direction == DMA_MEM_TO_MEM || direction == DMA_MEM_TO_DEV)
-- *src += copy_size;
-- if (direction == DMA_MEM_TO_MEM || direction == DMA_DEV_TO_MEM)
-- *dest += copy_size;
--
-- return new;
- }
-
--/*
-- * sh_dmae_prep_sg - prepare transfer descriptors from an SG list
-- *
-- * Common routine for public (MEMCPY) and slave DMA. The MEMCPY case is also
-- * converted to scatter-gather to guarantee consistent locking and a correct
-- * list manipulation. For slave DMA direction carries the usual meaning, and,
-- * logically, the SG list is RAM and the addr variable contains slave address,
-- * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_MEM_TO_MEM
-- * and the SG list contains only one element and points at the source buffer.
-- */
--static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_chan,
-- struct scatterlist *sgl, unsigned int sg_len, dma_addr_t *addr,
-- enum dma_transfer_direction direction, unsigned long flags)
-+static const struct sh_dmae_slave_config *dmae_find_slave(
-+ struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *slave)
- {
-- struct scatterlist *sg;
-- struct sh_desc *first = NULL, *new = NULL /* compiler... */;
-- LIST_HEAD(tx_list);
-- int chunks = 0;
-- unsigned long irq_flags;
-+ struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
-+ struct sh_dmae_pdata *pdata = shdev->pdata;
-+ const struct sh_dmae_slave_config *cfg;
- int i;
-
-- if (!sg_len)
-+ if (slave->shdma_slave.slave_id >= SH_DMA_SLAVE_NUMBER)
- return NULL;
-
-- for_each_sg(sgl, sg, sg_len, i)
-- chunks += (sg_dma_len(sg) + SH_DMA_TCR_MAX) /
-- (SH_DMA_TCR_MAX + 1);
--
-- /* Have to lock the whole loop to protect against concurrent release */
-- spin_lock_irqsave(&sh_chan->desc_lock, irq_flags);
--
-- /*
-- * Chaining:
-- * first descriptor is what user is dealing with in all API calls, its
-- * cookie is at first set to -EBUSY, at tx-submit to a positive
-- * number
-- * if more than one chunk is needed further chunks have cookie = -EINVAL
-- * the last chunk, if not equal to the first, has cookie = -ENOSPC
-- * all chunks are linked onto the tx_list head with their .node heads
-- * only during this function, then they are immediately spliced
-- * back onto the free list in form of a chain
-- */
-- for_each_sg(sgl, sg, sg_len, i) {
-- dma_addr_t sg_addr = sg_dma_address(sg);
-- size_t len = sg_dma_len(sg);
--
-- if (!len)
-- goto err_get_desc;
--
-- do {
-- dev_dbg(sh_chan->dev, "Add SG #%d@%p[%d], dma %llx\n",
-- i, sg, len, (unsigned long long)sg_addr);
--
-- if (direction == DMA_DEV_TO_MEM)
-- new = sh_dmae_add_desc(sh_chan, flags,
-- &sg_addr, addr, &len, &first,
-- direction);
-- else
-- new = sh_dmae_add_desc(sh_chan, flags,
-- addr, &sg_addr, &len, &first,
-- direction);
-- if (!new)
-- goto err_get_desc;
--
-- new->chunks = chunks--;
-- list_add_tail(&new->node, &tx_list);
-- } while (len);
-- }
--
-- if (new != first)
-- new->async_tx.cookie = -ENOSPC;
--
-- /* Put them back on the free list, so, they don't get lost */
-- list_splice_tail(&tx_list, &sh_chan->ld_free);
--
-- spin_unlock_irqrestore(&sh_chan->desc_lock, irq_flags);
--
-- return &first->async_tx;
--
--err_get_desc:
-- list_for_each_entry(new, &tx_list, node)
-- new->mark = DESC_IDLE;
-- list_splice(&tx_list, &sh_chan->ld_free);
--
-- spin_unlock_irqrestore(&sh_chan->desc_lock, irq_flags);
-+ for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++)
-+ if (cfg->slave_id == slave->shdma_slave.slave_id)
-+ return cfg;
-
- return NULL;
- }
-
--static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
-- struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
-- size_t len, unsigned long flags)
-+static int sh_dmae_set_slave(struct shdma_chan *schan,
-+ struct shdma_slave *sslave)
- {
-- struct sh_dmae_chan *sh_chan;
-- struct scatterlist sg;
--
-- if (!chan || !len)
-- return NULL;
--
-- sh_chan = to_sh_chan(chan);
--
-- sg_init_table(&sg, 1);
-- sg_set_page(&sg, pfn_to_page(PFN_DOWN(dma_src)), len,
-- offset_in_page(dma_src));
-- sg_dma_address(&sg) = dma_src;
-- sg_dma_len(&sg) = len;
--
-- return sh_dmae_prep_sg(sh_chan, &sg, 1, &dma_dest, DMA_MEM_TO_MEM,
-- flags);
--}
--
--static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg(
-- struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
-- enum dma_transfer_direction direction, unsigned long flags,
-- void *context)
--{
-- struct sh_dmae_slave *param;
-- struct sh_dmae_chan *sh_chan;
-- dma_addr_t slave_addr;
--
-- if (!chan)
-- return NULL;
--
-- sh_chan = to_sh_chan(chan);
-- param = chan->private;
--
-- /* Someone calling slave DMA on a public channel? */
-- if (!param || !sg_len) {
-- dev_warn(sh_chan->dev, "%s: bad parameter: %p, %d, %d\n",
-- __func__, param, sg_len, param ? param->slave_id : -1);
-- return NULL;
-- }
--
-- slave_addr = param->config->addr;
--
-- /*
-- * if (param != NULL), this is a successfully requested slave channel,
-- * therefore param->config != NULL too.
-- */
-- return sh_dmae_prep_sg(sh_chan, sgl, sg_len, &slave_addr,
-- direction, flags);
--}
--
--static int sh_dmae_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
-- unsigned long arg)
--{
-- struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
-- unsigned long flags;
--
-- /* Only supports DMA_TERMINATE_ALL */
-- if (cmd != DMA_TERMINATE_ALL)
-- return -ENXIO;
--
-- if (!chan)
-- return -EINVAL;
--
-- spin_lock_irqsave(&sh_chan->desc_lock, flags);
-- dmae_halt(sh_chan);
--
-- if (!list_empty(&sh_chan->ld_queue)) {
-- /* Record partial transfer */
-- struct sh_desc *desc = list_entry(sh_chan->ld_queue.next,
-- struct sh_desc, node);
-- desc->partial = (desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) <<
-- sh_chan->xmit_shift;
-- }
-- spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
-+ struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
-+ shdma_chan);
-+ struct sh_dmae_slave *slave = container_of(sslave, struct sh_dmae_slave,
-+ shdma_slave);
-+ const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave);
-+ if (!cfg)
-+ return -ENODEV;
-
-- sh_dmae_chan_ld_cleanup(sh_chan, true);
-+ slave->config = cfg;
-
- return 0;
- }
-
--static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all)
-+static void dmae_halt(struct sh_dmae_chan *sh_chan)
- {
-- struct sh_desc *desc, *_desc;
-- /* Is the "exposed" head of a chain acked? */
-- bool head_acked = false;
-- dma_cookie_t cookie = 0;
-- dma_async_tx_callback callback = NULL;
-- void *param = NULL;
-- unsigned long flags;
--
-- spin_lock_irqsave(&sh_chan->desc_lock, flags);
-- list_for_each_entry_safe(desc, _desc, &sh_chan->ld_queue, node) {
-- struct dma_async_tx_descriptor *tx = &desc->async_tx;
--
-- BUG_ON(tx->cookie > 0 && tx->cookie != desc->cookie);
-- BUG_ON(desc->mark != DESC_SUBMITTED &&
-- desc->mark != DESC_COMPLETED &&
-- desc->mark != DESC_WAITING);
--
-- /*
-- * queue is ordered, and we use this loop to (1) clean up all
-- * completed descriptors, and to (2) update descriptor flags of
-- * any chunks in a (partially) completed chain
-- */
-- if (!all && desc->mark == DESC_SUBMITTED &&
-- desc->cookie != cookie)
-- break;
--
-- if (tx->cookie > 0)
-- cookie = tx->cookie;
--
-- if (desc->mark == DESC_COMPLETED && desc->chunks == 1) {
-- if (sh_chan->common.completed_cookie != desc->cookie - 1)
-- dev_dbg(sh_chan->dev,
-- "Completing cookie %d, expected %d\n",
-- desc->cookie,
-- sh_chan->common.completed_cookie + 1);
-- sh_chan->common.completed_cookie = desc->cookie;
-- }
--
-- /* Call callback on the last chunk */
-- if (desc->mark == DESC_COMPLETED && tx->callback) {
-- desc->mark = DESC_WAITING;
-- callback = tx->callback;
-- param = tx->callback_param;
-- dev_dbg(sh_chan->dev, "descriptor #%d@%p on %d callback\n",
-- tx->cookie, tx, sh_chan->id);
-- BUG_ON(desc->chunks != 1);
-- break;
-- }
--
-- if (tx->cookie > 0 || tx->cookie == -EBUSY) {
-- if (desc->mark == DESC_COMPLETED) {
-- BUG_ON(tx->cookie < 0);
-- desc->mark = DESC_WAITING;
-- }
-- head_acked = async_tx_test_ack(tx);
-- } else {
-- switch (desc->mark) {
-- case DESC_COMPLETED:
-- desc->mark = DESC_WAITING;
-- /* Fall through */
-- case DESC_WAITING:
-- if (head_acked)
-- async_tx_ack(&desc->async_tx);
-- }
-- }
--
-- dev_dbg(sh_chan->dev, "descriptor %p #%d completed.\n",
-- tx, tx->cookie);
--
-- if (((desc->mark == DESC_COMPLETED ||
-- desc->mark == DESC_WAITING) &&
-- async_tx_test_ack(&desc->async_tx)) || all) {
-- /* Remove from ld_queue list */
-- desc->mark = DESC_IDLE;
--
-- list_move(&desc->node, &sh_chan->ld_free);
--
-- if (list_empty(&sh_chan->ld_queue)) {
-- dev_dbg(sh_chan->dev, "Bring down channel %d\n", sh_chan->id);
-- pm_runtime_put(sh_chan->dev);
-- }
-- }
-- }
--
-- if (all && !callback)
-- /*
-- * Terminating and the loop completed normally: forgive
-- * uncompleted cookies
-- */
-- sh_chan->common.completed_cookie = sh_chan->common.cookie;
--
-- spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
--
-- if (callback)
-- callback(param);
-+ struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
-+ u32 chcr = chcr_read(sh_chan);
-
-- return callback;
-+ chcr &= ~(CHCR_DE | CHCR_TE | shdev->chcr_ie_bit);
-+ chcr_write(sh_chan, chcr);
- }
-
--/*
-- * sh_chan_ld_cleanup - Clean up link descriptors
-- *
-- * This function cleans up the ld_queue of DMA channel.
-- */
--static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all)
-+static int sh_dmae_desc_setup(struct shdma_chan *schan,
-+ struct shdma_desc *sdesc,
-+ dma_addr_t src, dma_addr_t dst, size_t *len)
- {
-- while (__ld_cleanup(sh_chan, all))
-- ;
--}
-+ struct sh_dmae_desc *sh_desc = container_of(sdesc,
-+ struct sh_dmae_desc, shdma_desc);
-
--/* Called under spin_lock_irq(&sh_chan->desc_lock) */
--static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
--{
-- struct sh_desc *desc;
-+ if (*len > schan->max_xfer_len)
-+ *len = schan->max_xfer_len;
-
-- /* DMA work check */
-- if (dmae_is_busy(sh_chan))
-- return;
--
-- /* Find the first not transferred descriptor */
-- list_for_each_entry(desc, &sh_chan->ld_queue, node)
-- if (desc->mark == DESC_SUBMITTED) {
-- dev_dbg(sh_chan->dev, "Queue #%d to %d: %u@%x -> %x\n",
-- desc->async_tx.cookie, sh_chan->id,
-- desc->hw.tcr, desc->hw.sar, desc->hw.dar);
-- /* Get the ld start address from ld_queue */
-- dmae_set_reg(sh_chan, &desc->hw);
-- dmae_start(sh_chan);
-- break;
-- }
--}
-+ sh_desc->hw.sar = src;
-+ sh_desc->hw.dar = dst;
-+ sh_desc->hw.tcr = *len;
-
--static void sh_dmae_memcpy_issue_pending(struct dma_chan *chan)
--{
-- struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
--
-- spin_lock_irq(&sh_chan->desc_lock);
-- if (sh_chan->pm_state == DMAE_PM_ESTABLISHED)
-- sh_chan_xfer_ld_queue(sh_chan);
-- else
-- sh_chan->pm_state = DMAE_PM_PENDING;
-- spin_unlock_irq(&sh_chan->desc_lock);
-+ return 0;
- }
-
--static enum dma_status sh_dmae_tx_status(struct dma_chan *chan,
-- dma_cookie_t cookie,
-- struct dma_tx_state *txstate)
-+static void sh_dmae_halt(struct shdma_chan *schan)
- {
-- struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
-- enum dma_status status;
-- unsigned long flags;
--
-- sh_dmae_chan_ld_cleanup(sh_chan, false);
--
-- spin_lock_irqsave(&sh_chan->desc_lock, flags);
--
-- status = dma_cookie_status(chan, cookie, txstate);
--
-- /*
-- * If we don't find cookie on the queue, it has been aborted and we have
-- * to report error
-- */
-- if (status != DMA_SUCCESS) {
-- struct sh_desc *desc;
-- status = DMA_ERROR;
-- list_for_each_entry(desc, &sh_chan->ld_queue, node)
-- if (desc->cookie == cookie) {
-- status = DMA_IN_PROGRESS;
-- break;
-- }
-- }
--
-- spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
--
-- return status;
-+ struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
-+ shdma_chan);
-+ dmae_halt(sh_chan);
- }
-
--static irqreturn_t sh_dmae_interrupt(int irq, void *data)
-+static bool sh_dmae_chan_irq(struct shdma_chan *schan, int irq)
- {
-- irqreturn_t ret = IRQ_NONE;
-- struct sh_dmae_chan *sh_chan = data;
-- u32 chcr;
--
-- spin_lock(&sh_chan->desc_lock);
--
-- chcr = chcr_read(sh_chan);
-+ struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
-+ shdma_chan);
-
-- if (chcr & CHCR_TE) {
-- /* DMA stop */
-- dmae_halt(sh_chan);
--
-- ret = IRQ_HANDLED;
-- tasklet_schedule(&sh_chan->tasklet);
-- }
-+ if (!(chcr_read(sh_chan) & CHCR_TE))
-+ return false;
-
-- spin_unlock(&sh_chan->desc_lock);
-+ /* DMA stop */
-+ dmae_halt(sh_chan);
-
-- return ret;
-+ return true;
- }
-
- /* Called from error IRQ or NMI */
- static bool sh_dmae_reset(struct sh_dmae_device *shdev)
- {
-- unsigned int handled = 0;
-- int i;
-+ bool ret;
-
- /* halt the dma controller */
- sh_dmae_ctl_stop(shdev);
-
- /* We cannot detect, which channel caused the error, have to reset all */
-- for (i = 0; i < SH_DMAC_MAX_CHANNELS; i++) {
-- struct sh_dmae_chan *sh_chan = shdev->chan[i];
-- struct sh_desc *desc;
-- LIST_HEAD(dl);
--
-- if (!sh_chan)
-- continue;
--
-- spin_lock(&sh_chan->desc_lock);
--
-- /* Stop the channel */
-- dmae_halt(sh_chan);
--
-- list_splice_init(&sh_chan->ld_queue, &dl);
--
-- if (!list_empty(&dl)) {
-- dev_dbg(sh_chan->dev, "Bring down channel %d\n", sh_chan->id);
-- pm_runtime_put(sh_chan->dev);
-- }
-- sh_chan->pm_state = DMAE_PM_ESTABLISHED;
--
-- spin_unlock(&sh_chan->desc_lock);
--
-- /* Complete all */
-- list_for_each_entry(desc, &dl, node) {
-- struct dma_async_tx_descriptor *tx = &desc->async_tx;
-- desc->mark = DESC_IDLE;
-- if (tx->callback)
-- tx->callback(tx->callback_param);
-- }
--
-- spin_lock(&sh_chan->desc_lock);
-- list_splice(&dl, &sh_chan->ld_free);
-- spin_unlock(&sh_chan->desc_lock);
--
-- handled++;
-- }
-+ ret = shdma_reset(&shdev->shdma_dev);
-
- sh_dmae_rst(shdev);
-
-- return !!handled;
-+ return ret;
- }
-
- static irqreturn_t sh_dmae_err(int irq, void *data)
-@@ -991,35 +407,24 @@ static irqreturn_t sh_dmae_err(int irq, void *data)
- if (!(dmaor_read(shdev) & DMAOR_AE))
- return IRQ_NONE;
-
-- sh_dmae_reset(data);
-+ sh_dmae_reset(shdev);
- return IRQ_HANDLED;
- }
-
--static void dmae_do_tasklet(unsigned long data)
-+static bool sh_dmae_desc_completed(struct shdma_chan *schan,
-+ struct shdma_desc *sdesc)
- {
-- struct sh_dmae_chan *sh_chan = (struct sh_dmae_chan *)data;
-- struct sh_desc *desc;
-+ struct sh_dmae_chan *sh_chan = container_of(schan,
-+ struct sh_dmae_chan, shdma_chan);
-+ struct sh_dmae_desc *sh_desc = container_of(sdesc,
-+ struct sh_dmae_desc, shdma_desc);
- u32 sar_buf = sh_dmae_readl(sh_chan, SAR);
- u32 dar_buf = sh_dmae_readl(sh_chan, DAR);
-
-- spin_lock_irq(&sh_chan->desc_lock);
-- list_for_each_entry(desc, &sh_chan->ld_queue, node) {
-- if (desc->mark == DESC_SUBMITTED &&
-- ((desc->direction == DMA_DEV_TO_MEM &&
-- (desc->hw.dar + desc->hw.tcr) == dar_buf) ||
-- (desc->hw.sar + desc->hw.tcr) == sar_buf)) {
-- dev_dbg(sh_chan->dev, "done #%d@%p dst %u\n",
-- desc->async_tx.cookie, &desc->async_tx,
-- desc->hw.dar);
-- desc->mark = DESC_COMPLETED;
-- break;
-- }
-- }
-- /* Next desc */
-- sh_chan_xfer_ld_queue(sh_chan);
-- spin_unlock_irq(&sh_chan->desc_lock);
--
-- sh_dmae_chan_ld_cleanup(sh_chan, false);
-+ return (sdesc->direction == DMA_DEV_TO_MEM &&
-+ (sh_desc->hw.dar + sh_desc->hw.tcr) == dar_buf) ||
-+ (sdesc->direction != DMA_DEV_TO_MEM &&
-+ (sh_desc->hw.sar + sh_desc->hw.tcr) == sar_buf);
- }
-
- static bool sh_dmae_nmi_notify(struct sh_dmae_device *shdev)
-@@ -1073,97 +478,174 @@ static struct notifier_block sh_dmae_nmi_notifier __read_mostly = {
- static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
- int irq, unsigned long flags)
- {
-- int err;
- const struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id];
-- struct platform_device *pdev = to_platform_device(shdev->common.dev);
-- struct sh_dmae_chan *new_sh_chan;
-+ struct shdma_dev *sdev = &shdev->shdma_dev;
-+ struct platform_device *pdev = to_platform_device(sdev->dma_dev.dev);
-+ struct sh_dmae_chan *sh_chan;
-+ struct shdma_chan *schan;
-+ int err;
-
-- /* alloc channel */
-- new_sh_chan = kzalloc(sizeof(struct sh_dmae_chan), GFP_KERNEL);
-- if (!new_sh_chan) {
-- dev_err(shdev->common.dev,
-+ sh_chan = kzalloc(sizeof(struct sh_dmae_chan), GFP_KERNEL);
-+ if (!sh_chan) {
-+ dev_err(sdev->dma_dev.dev,
- "No free memory for allocating dma channels!\n");
- return -ENOMEM;
- }
-
-- new_sh_chan->pm_state = DMAE_PM_ESTABLISHED;
--
-- /* reference struct dma_device */
-- new_sh_chan->common.device = &shdev->common;
-- dma_cookie_init(&new_sh_chan->common);
-+ schan = &sh_chan->shdma_chan;
-+ schan->max_xfer_len = SH_DMA_TCR_MAX + 1;
-
-- new_sh_chan->dev = shdev->common.dev;
-- new_sh_chan->id = id;
-- new_sh_chan->irq = irq;
-- new_sh_chan->base = shdev->chan_reg + chan_pdata->offset / sizeof(u32);
-+ shdma_chan_probe(sdev, schan, id);
-
-- /* Init DMA tasklet */
-- tasklet_init(&new_sh_chan->tasklet, dmae_do_tasklet,
-- (unsigned long)new_sh_chan);
--
-- spin_lock_init(&new_sh_chan->desc_lock);
--
-- /* Init descripter manage list */
-- INIT_LIST_HEAD(&new_sh_chan->ld_queue);
-- INIT_LIST_HEAD(&new_sh_chan->ld_free);
--
-- /* Add the channel to DMA device channel list */
-- list_add_tail(&new_sh_chan->common.device_node,
-- &shdev->common.channels);
-- shdev->common.chancnt++;
-+ sh_chan->base = shdev->chan_reg + chan_pdata->offset / sizeof(u32);
-
-+ /* set up channel irq */
- if (pdev->id >= 0)
-- snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id),
-- "sh-dmae%d.%d", pdev->id, new_sh_chan->id);
-+ snprintf(sh_chan->dev_id, sizeof(sh_chan->dev_id),
-+ "sh-dmae%d.%d", pdev->id, id);
- else
-- snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id),
-- "sh-dma%d", new_sh_chan->id);
-+ snprintf(sh_chan->dev_id, sizeof(sh_chan->dev_id),
-+ "sh-dma%d", id);
-
-- /* set up channel irq */
-- err = request_irq(irq, &sh_dmae_interrupt, flags,
-- new_sh_chan->dev_id, new_sh_chan);
-+ err = shdma_request_irq(schan, irq, flags, sh_chan->dev_id);
- if (err) {
-- dev_err(shdev->common.dev, "DMA channel %d request_irq error "
-- "with return %d\n", id, err);
-+ dev_err(sdev->dma_dev.dev,
-+ "DMA channel %d request_irq error %d\n",
-+ id, err);
- goto err_no_irq;
- }
-
-- shdev->chan[id] = new_sh_chan;
-+ shdev->chan[id] = sh_chan;
- return 0;
-
- err_no_irq:
- /* remove from dmaengine device node */
-- list_del(&new_sh_chan->common.device_node);
-- kfree(new_sh_chan);
-+ shdma_chan_remove(schan);
-+ kfree(sh_chan);
- return err;
- }
-
- static void sh_dmae_chan_remove(struct sh_dmae_device *shdev)
- {
-+ struct dma_device *dma_dev = &shdev->shdma_dev.dma_dev;
-+ struct shdma_chan *schan;
- int i;
-
-- for (i = shdev->common.chancnt - 1 ; i >= 0 ; i--) {
-- if (shdev->chan[i]) {
-- struct sh_dmae_chan *sh_chan = shdev->chan[i];
-+ shdma_for_each_chan(schan, &shdev->shdma_dev, i) {
-+ struct sh_dmae_chan *sh_chan = container_of(schan,
-+ struct sh_dmae_chan, shdma_chan);
-+ BUG_ON(!schan);
-
-- free_irq(sh_chan->irq, sh_chan);
-+ shdma_free_irq(&sh_chan->shdma_chan);
-
-- list_del(&sh_chan->common.device_node);
-- kfree(sh_chan);
-- shdev->chan[i] = NULL;
-+ shdma_chan_remove(schan);
-+ kfree(sh_chan);
-+ }
-+ dma_dev->chancnt = 0;
-+}
-+
-+static void sh_dmae_shutdown(struct platform_device *pdev)
-+{
-+ struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
-+ sh_dmae_ctl_stop(shdev);
-+}
-+
-+static int sh_dmae_runtime_suspend(struct device *dev)
-+{
-+ return 0;
-+}
-+
-+static int sh_dmae_runtime_resume(struct device *dev)
-+{
-+ struct sh_dmae_device *shdev = dev_get_drvdata(dev);
-+
-+ return sh_dmae_rst(shdev);
-+}
-+
-+#ifdef CONFIG_PM
-+static int sh_dmae_suspend(struct device *dev)
-+{
-+ return 0;
-+}
-+
-+static int sh_dmae_resume(struct device *dev)
-+{
-+ struct sh_dmae_device *shdev = dev_get_drvdata(dev);
-+ int i, ret;
-+
-+ ret = sh_dmae_rst(shdev);
-+ if (ret < 0)
-+ dev_err(dev, "Failed to reset!\n");
-+
-+ for (i = 0; i < shdev->pdata->channel_num; i++) {
-+ struct sh_dmae_chan *sh_chan = shdev->chan[i];
-+ struct sh_dmae_slave *param = sh_chan->shdma_chan.dma_chan.private;
-+
-+ if (!sh_chan->shdma_chan.desc_num)
-+ continue;
-+
-+ if (param) {
-+ const struct sh_dmae_slave_config *cfg = param->config;
-+ dmae_set_dmars(sh_chan, cfg->mid_rid);
-+ dmae_set_chcr(sh_chan, cfg->chcr);
-+ } else {
-+ dmae_init(sh_chan);
- }
- }
-- shdev->common.chancnt = 0;
-+
-+ return 0;
- }
-+#else
-+#define sh_dmae_suspend NULL
-+#define sh_dmae_resume NULL
-+#endif
-
--static int __init sh_dmae_probe(struct platform_device *pdev)
-+const struct dev_pm_ops sh_dmae_pm = {
-+ .suspend = sh_dmae_suspend,
-+ .resume = sh_dmae_resume,
-+ .runtime_suspend = sh_dmae_runtime_suspend,
-+ .runtime_resume = sh_dmae_runtime_resume,
-+};
-+
-+static dma_addr_t sh_dmae_slave_addr(struct shdma_chan *schan)
-+{
-+ struct sh_dmae_slave *param = schan->dma_chan.private;
-+
-+ /*
-+ * Implicit BUG_ON(!param)
-+ * if (param != NULL), this is a successfully requested slave channel,
-+ * therefore param->config != NULL too.
-+ */
-+ return param->config->addr;
-+}
-+
-+static struct shdma_desc *sh_dmae_embedded_desc(void *buf, int i)
-+{
-+ return &((struct sh_dmae_desc *)buf)[i].shdma_desc;
-+}
-+
-+static const struct shdma_ops sh_dmae_shdma_ops = {
-+ .desc_completed = sh_dmae_desc_completed,
-+ .halt_channel = sh_dmae_halt,
-+ .channel_busy = sh_dmae_channel_busy,
-+ .slave_addr = sh_dmae_slave_addr,
-+ .desc_setup = sh_dmae_desc_setup,
-+ .set_slave = sh_dmae_set_slave,
-+ .setup_xfer = sh_dmae_setup_xfer,
-+ .start_xfer = sh_dmae_start_xfer,
-+ .embedded_desc = sh_dmae_embedded_desc,
-+ .chan_irq = sh_dmae_chan_irq,
-+};
-+
-+static int __devinit sh_dmae_probe(struct platform_device *pdev)
- {
- struct sh_dmae_pdata *pdata = pdev->dev.platform_data;
- unsigned long irqflags = IRQF_DISABLED,
-- chan_flag[SH_DMAC_MAX_CHANNELS] = {};
-- int errirq, chan_irq[SH_DMAC_MAX_CHANNELS];
-+ chan_flag[SH_DMAE_MAX_CHANNELS] = {};
-+ int errirq, chan_irq[SH_DMAE_MAX_CHANNELS];
- int err, i, irq_cnt = 0, irqres = 0, irq_cap = 0;
- struct sh_dmae_device *shdev;
-+ struct dma_device *dma_dev;
- struct resource *chan, *dmars, *errirq_res, *chanirq_res;
-
- /* get platform data */
-@@ -1211,6 +693,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
- goto ealloc;
- }
-
-+ dma_dev = &shdev->shdma_dev.dma_dev;
-+
- shdev->chan_reg = ioremap(chan->start, resource_size(chan));
- if (!shdev->chan_reg)
- goto emapchan;
-@@ -1220,8 +704,23 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
- goto emapdmars;
- }
-
-+ if (!pdata->slave_only)
-+ dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
-+ if (pdata->slave && pdata->slave_num)
-+ dma_cap_set(DMA_SLAVE, dma_dev->cap_mask);
-+
-+ /* Default transfer size of 32 bytes requires 32-byte alignment */
-+ dma_dev->copy_align = LOG2_DEFAULT_XFER_SIZE;
-+
-+ shdev->shdma_dev.ops = &sh_dmae_shdma_ops;
-+ shdev->shdma_dev.desc_size = sizeof(struct sh_dmae_desc);
-+ err = shdma_init(&pdev->dev, &shdev->shdma_dev,
-+ pdata->channel_num);
-+ if (err < 0)
-+ goto eshdma;
-+
- /* platform data */
-- shdev->pdata = pdata;
-+ shdev->pdata = pdev->dev.platform_data;
-
- if (pdata->chcr_offset)
- shdev->chcr_offset = pdata->chcr_offset;
-@@ -1235,10 +734,10 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
-
- platform_set_drvdata(pdev, shdev);
-
-- shdev->common.dev = &pdev->dev;
--
- pm_runtime_enable(&pdev->dev);
-- pm_runtime_get_sync(&pdev->dev);
-+ err = pm_runtime_get_sync(&pdev->dev);
-+ if (err < 0)
-+ dev_err(&pdev->dev, "%s(): GET = %d\n", __func__, err);
-
- spin_lock_irq(&sh_dmae_lock);
- list_add_tail_rcu(&shdev->node, &sh_dmae_devices);
-@@ -1249,27 +748,6 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
- if (err)
- goto rst_err;
-
-- INIT_LIST_HEAD(&shdev->common.channels);
--
-- if (!pdata->slave_only)
-- dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
-- if (pdata->slave && pdata->slave_num)
-- dma_cap_set(DMA_SLAVE, shdev->common.cap_mask);
--
-- shdev->common.device_alloc_chan_resources
-- = sh_dmae_alloc_chan_resources;
-- shdev->common.device_free_chan_resources = sh_dmae_free_chan_resources;
-- shdev->common.device_prep_dma_memcpy = sh_dmae_prep_memcpy;
-- shdev->common.device_tx_status = sh_dmae_tx_status;
-- shdev->common.device_issue_pending = sh_dmae_memcpy_issue_pending;
--
-- /* Compulsory for DMA_SLAVE fields */
-- shdev->common.device_prep_slave_sg = sh_dmae_prep_slave_sg;
-- shdev->common.device_control = sh_dmae_control;
--
-- /* Default transfer size of 32 bytes requires 32-byte alignment */
-- shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE;
--
- #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
- chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
-
-@@ -1301,7 +779,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
- !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) {
- /* Special case - all multiplexed */
- for (; irq_cnt < pdata->channel_num; irq_cnt++) {
-- if (irq_cnt < SH_DMAC_MAX_CHANNELS) {
-+ if (irq_cnt < SH_DMAE_MAX_CHANNELS) {
- chan_irq[irq_cnt] = chanirq_res->start;
- chan_flag[irq_cnt] = IRQF_SHARED;
- } else {
-@@ -1312,7 +790,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
- } else {
- do {
- for (i = chanirq_res->start; i <= chanirq_res->end; i++) {
-- if (irq_cnt >= SH_DMAC_MAX_CHANNELS) {
-+ if (irq_cnt >= SH_DMAE_MAX_CHANNELS) {
- irq_cap = 1;
- break;
- }
-@@ -1328,7 +806,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
- chan_irq[irq_cnt++] = i;
- }
-
-- if (irq_cnt >= SH_DMAC_MAX_CHANNELS)
-+ if (irq_cnt >= SH_DMAE_MAX_CHANNELS)
- break;
-
- chanirq_res = platform_get_resource(pdev,
-@@ -1346,14 +824,19 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
- if (irq_cap)
- dev_notice(&pdev->dev, "Attempting to register %d DMA "
- "channels when a maximum of %d are supported.\n",
-- pdata->channel_num, SH_DMAC_MAX_CHANNELS);
-+ pdata->channel_num, SH_DMAE_MAX_CHANNELS);
-
- pm_runtime_put(&pdev->dev);
-
-- dma_async_device_register(&shdev->common);
-+ err = dma_async_device_register(&shdev->shdma_dev.dma_dev);
-+ if (err < 0)
-+ goto edmadevreg;
-
- return err;
-
-+edmadevreg:
-+ pm_runtime_get(&pdev->dev);
-+
- chan_probe_err:
- sh_dmae_chan_remove(shdev);
-
-@@ -1369,10 +852,11 @@ rst_err:
- pm_runtime_put(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
-
-+ platform_set_drvdata(pdev, NULL);
-+ shdma_cleanup(&shdev->shdma_dev);
-+eshdma:
- if (dmars)
- iounmap(shdev->dmars);
--
-- platform_set_drvdata(pdev, NULL);
- emapdmars:
- iounmap(shdev->chan_reg);
- synchronize_rcu();
-@@ -1387,13 +871,14 @@ ermrdmars:
- return err;
- }
-
--static int __exit sh_dmae_remove(struct platform_device *pdev)
-+static int __devexit sh_dmae_remove(struct platform_device *pdev)
- {
- struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
-+ struct dma_device *dma_dev = &shdev->shdma_dev.dma_dev;
- struct resource *res;
- int errirq = platform_get_irq(pdev, 0);
-
-- dma_async_device_unregister(&shdev->common);
-+ dma_async_device_unregister(dma_dev);
-
- if (errirq > 0)
- free_irq(errirq, shdev);
-@@ -1402,11 +887,11 @@ static int __exit sh_dmae_remove(struct platform_device *pdev)
- list_del_rcu(&shdev->node);
- spin_unlock_irq(&sh_dmae_lock);
-
-- /* channel data remove */
-- sh_dmae_chan_remove(shdev);
--
- pm_runtime_disable(&pdev->dev);
-
-+ sh_dmae_chan_remove(shdev);
-+ shdma_cleanup(&shdev->shdma_dev);
-+
- if (shdev->dmars)
- iounmap(shdev->dmars);
- iounmap(shdev->chan_reg);
-@@ -1426,77 +911,14 @@ static int __exit sh_dmae_remove(struct platform_device *pdev)
- return 0;
- }
-
--static void sh_dmae_shutdown(struct platform_device *pdev)
--{
-- struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
-- sh_dmae_ctl_stop(shdev);
--}
--
--static int sh_dmae_runtime_suspend(struct device *dev)
--{
-- return 0;
--}
--
--static int sh_dmae_runtime_resume(struct device *dev)
--{
-- struct sh_dmae_device *shdev = dev_get_drvdata(dev);
--
-- return sh_dmae_rst(shdev);
--}
--
--#ifdef CONFIG_PM
--static int sh_dmae_suspend(struct device *dev)
--{
-- return 0;
--}
--
--static int sh_dmae_resume(struct device *dev)
--{
-- struct sh_dmae_device *shdev = dev_get_drvdata(dev);
-- int i, ret;
--
-- ret = sh_dmae_rst(shdev);
-- if (ret < 0)
-- dev_err(dev, "Failed to reset!\n");
--
-- for (i = 0; i < shdev->pdata->channel_num; i++) {
-- struct sh_dmae_chan *sh_chan = shdev->chan[i];
-- struct sh_dmae_slave *param = sh_chan->common.private;
--
-- if (!sh_chan->descs_allocated)
-- continue;
--
-- if (param) {
-- const struct sh_dmae_slave_config *cfg = param->config;
-- dmae_set_dmars(sh_chan, cfg->mid_rid);
-- dmae_set_chcr(sh_chan, cfg->chcr);
-- } else {
-- dmae_init(sh_chan);
-- }
-- }
--
-- return 0;
--}
--#else
--#define sh_dmae_suspend NULL
--#define sh_dmae_resume NULL
--#endif
--
--const struct dev_pm_ops sh_dmae_pm = {
-- .suspend = sh_dmae_suspend,
-- .resume = sh_dmae_resume,
-- .runtime_suspend = sh_dmae_runtime_suspend,
-- .runtime_resume = sh_dmae_runtime_resume,
--};
--
- static struct platform_driver sh_dmae_driver = {
-- .remove = __exit_p(sh_dmae_remove),
-- .shutdown = sh_dmae_shutdown,
-- .driver = {
-+ .driver = {
- .owner = THIS_MODULE,
-- .name = "sh-dma-engine",
- .pm = &sh_dmae_pm,
-+ .name = SH_DMAE_DRV_NAME,
- },
-+ .remove = __devexit_p(sh_dmae_remove),
-+ .shutdown = sh_dmae_shutdown,
- };
-
- static int __init sh_dmae_init(void)
-@@ -1521,4 +943,4 @@ module_exit(sh_dmae_exit);
- MODULE_AUTHOR("Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>");
- MODULE_DESCRIPTION("Renesas SH DMA Engine driver");
- MODULE_LICENSE("GPL");
--MODULE_ALIAS("platform:sh-dma-engine");
-+MODULE_ALIAS("platform:" SH_DMAE_DRV_NAME);
-diff --git a/drivers/dma/sh/shdma.h b/drivers/dma/sh/shdma.h
-index 0b1d2c1..840e47d 100644
---- a/drivers/dma/sh/shdma.h
-+++ b/drivers/dma/sh/shdma.h
-@@ -13,42 +13,27 @@
- #ifndef __DMA_SHDMA_H
- #define __DMA_SHDMA_H
-
-+#include <linux/shdma-base.h>
- #include <linux/dmaengine.h>
- #include <linux/interrupt.h>
- #include <linux/list.h>
-
--#define SH_DMAC_MAX_CHANNELS 20
--#define SH_DMA_SLAVE_NUMBER 256
--#define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */
-+#define SH_DMAE_MAX_CHANNELS 20
-+#define SH_DMAE_TCR_MAX 0x00FFFFFF /* 16MB */
-
- struct device;
-
--enum dmae_pm_state {
-- DMAE_PM_ESTABLISHED,
-- DMAE_PM_BUSY,
-- DMAE_PM_PENDING,
--};
--
- struct sh_dmae_chan {
-- spinlock_t desc_lock; /* Descriptor operation lock */
-- struct list_head ld_queue; /* Link descriptors queue */
-- struct list_head ld_free; /* Link descriptors free */
-- struct dma_chan common; /* DMA common channel */
-- struct device *dev; /* Channel device */
-- struct tasklet_struct tasklet; /* Tasklet */
-- int descs_allocated; /* desc count */
-+ struct shdma_chan shdma_chan;
- int xmit_shift; /* log_2(bytes_per_xfer) */
-- int irq;
-- int id; /* Raw id of this channel */
- u32 __iomem *base;
- char dev_id[16]; /* unique name per DMAC of channel */
- int pm_error;
-- enum dmae_pm_state pm_state;
- };
-
- struct sh_dmae_device {
-- struct dma_device common;
-- struct sh_dmae_chan *chan[SH_DMAC_MAX_CHANNELS];
-+ struct shdma_dev shdma_dev;
-+ struct sh_dmae_chan *chan[SH_DMAE_MAX_CHANNELS];
- struct sh_dmae_pdata *pdata;
- struct list_head node;
- u32 __iomem *chan_reg;
-@@ -57,10 +42,21 @@ struct sh_dmae_device {
- u32 chcr_ie_bit;
- };
-
--#define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, common)
-+struct sh_dmae_regs {
-+ u32 sar; /* SAR / source address */
-+ u32 dar; /* DAR / destination address */
-+ u32 tcr; /* TCR / transfer count */
-+};
-+
-+struct sh_dmae_desc {
-+ struct sh_dmae_regs hw;
-+ struct shdma_desc shdma_desc;
-+};
-+
-+#define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, shdma_chan)
- #define to_sh_desc(lh) container_of(lh, struct sh_desc, node)
- #define tx_to_sh_desc(tx) container_of(tx, struct sh_desc, async_tx)
--#define to_sh_dev(chan) container_of(chan->common.device,\
-- struct sh_dmae_device, common)
-+#define to_sh_dev(chan) container_of(chan->shdma_chan.dma_chan.device,\
-+ struct sh_dmae_device, shdma_dev.dma_dev)
-
- #endif /* __DMA_SHDMA_H */
-diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
-index e081e8e..7c8ca41 100644
---- a/include/linux/sh_dma.h
-+++ b/include/linux/sh_dma.h
-@@ -13,34 +13,21 @@
- #include <linux/dmaengine.h>
- #include <linux/list.h>
- #include <linux/shdma-base.h>
-+#include <linux/types.h>
-+
-+struct device;
-
- /* Used by slave DMA clients to request DMA to/from a specific peripheral */
- struct sh_dmae_slave {
-- union {
-- unsigned int slave_id; /* Set by the platform */
-- struct shdma_slave shdma_slave;
-- };
-- struct device *dma_dev; /* Set by the platform */
-- const struct sh_dmae_slave_config *config; /* Set by the driver */
--};
--
--struct sh_dmae_regs {
-- u32 sar; /* SAR / source address */
-- u32 dar; /* DAR / destination address */
-- u32 tcr; /* TCR / transfer count */
--};
--
--struct sh_desc {
-- struct sh_dmae_regs hw;
-- struct list_head node;
-- struct dma_async_tx_descriptor async_tx;
-- enum dma_transfer_direction direction;
-- dma_cookie_t cookie;
-- size_t partial;
-- int chunks;
-- int mark;
-+ struct shdma_slave shdma_slave; /* Set by the platform */
-+ struct device *dma_dev; /* Set by the platform */
-+ const struct sh_dmae_slave_config *config; /* Set by the driver */
- };
-
-+/*
-+ * Supplied by platforms to specify, how a DMA channel has to be configured for
-+ * a certain peripheral
-+ */
- struct sh_dmae_slave_config {
- unsigned int slave_id;
- dma_addr_t addr;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a2071a25b2853b85f682b5a37d87faa4659141c6 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Thu, 5 Jul 2012 12:29:40 +0200
-Subject: dmaengine: shdma: prepare to stop using struct dma_chan::private
-
-Using struct dma_chan::private is deprecated. To update the shdma driver to
-stop using it we first have to eliminate internal runtime uses of it. After
-that we will also be able to stop using it for channel configuration.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit ecf90fbbdc66cde6f5fa25d88541112b9baac459)
-
-Conflicts:
- drivers/dma/sh/shdma.c
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/dma/sh/shdma-base.c | 9 +++++----
- drivers/dma/sh/shdma.c | 24 ++++++++++--------------
- drivers/dma/sh/shdma.h | 2 ++
- include/linux/sh_dma.h | 2 --
- include/linux/shdma-base.h | 1 +
- 5 files changed, 18 insertions(+), 20 deletions(-)
-
-diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
-index ff060d0..f75ebfa 100644
---- a/drivers/dma/sh/shdma-base.c
-+++ b/drivers/dma/sh/shdma-base.c
-@@ -76,7 +76,7 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
- container_of(tx, struct shdma_desc, async_tx),
- *last = desc;
- struct shdma_chan *schan = to_shdma_chan(tx->chan);
-- struct shdma_slave *slave = tx->chan->private;
-+ struct shdma_slave *slave = schan->slave;
- dma_async_tx_callback callback = tx->callback;
- dma_cookie_t cookie;
- bool power_up;
-@@ -208,6 +208,7 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
- goto edescalloc;
- }
- schan->desc_num = NR_DESCS_PER_CHANNEL;
-+ schan->slave = slave;
-
- for (i = 0; i < NR_DESCS_PER_CHANNEL; i++) {
- desc = ops->embedded_desc(schan->desc, i);
-@@ -365,9 +366,9 @@ static void shdma_free_chan_resources(struct dma_chan *chan)
- if (!list_empty(&schan->ld_queue))
- shdma_chan_ld_cleanup(schan, true);
-
-- if (chan->private) {
-+ if (schan->slave) {
- /* The caller is holding dma_list_mutex */
-- struct shdma_slave *slave = chan->private;
-+ struct shdma_slave *slave = schan->slave;
- clear_bit(slave->slave_id, shdma_slave_used);
- chan->private = NULL;
- }
-@@ -558,7 +559,7 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg(
- struct shdma_chan *schan = to_shdma_chan(chan);
- struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
- const struct shdma_ops *ops = sdev->ops;
-- struct shdma_slave *slave = chan->private;
-+ struct shdma_slave *slave = schan->slave;
- dma_addr_t slave_addr;
-
- if (!chan)
-diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
-index c393b35..305e77a 100644
---- a/drivers/dma/sh/shdma.c
-+++ b/drivers/dma/sh/shdma.c
-@@ -291,10 +291,8 @@ static void sh_dmae_setup_xfer(struct shdma_chan *schan,
- shdma_chan);
-
- if (sslave) {
-- struct sh_dmae_slave *slave = container_of(sslave,
-- struct sh_dmae_slave, shdma_slave);
- const struct sh_dmae_slave_config *cfg =
-- slave->config;
-+ sh_chan->config;
-
- dmae_set_dmars(sh_chan, cfg->mid_rid);
- dmae_set_chcr(sh_chan, cfg->chcr);
-@@ -326,13 +324,11 @@ static int sh_dmae_set_slave(struct shdma_chan *schan,
- {
- struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
- shdma_chan);
-- struct sh_dmae_slave *slave = container_of(sslave, struct sh_dmae_slave,
-- shdma_slave);
- const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave);
- if (!cfg)
- return -ENODEV;
-
-- slave->config = cfg;
-+ sh_chan->config = cfg;
-
- return 0;
- }
-@@ -579,13 +575,12 @@ static int sh_dmae_resume(struct device *dev)
-
- for (i = 0; i < shdev->pdata->channel_num; i++) {
- struct sh_dmae_chan *sh_chan = shdev->chan[i];
-- struct sh_dmae_slave *param = sh_chan->shdma_chan.dma_chan.private;
-
- if (!sh_chan->shdma_chan.desc_num)
- continue;
-
-- if (param) {
-- const struct sh_dmae_slave_config *cfg = param->config;
-+ if (sh_chan->shdma_chan.slave) {
-+ const struct sh_dmae_slave_config *cfg = sh_chan->config;
- dmae_set_dmars(sh_chan, cfg->mid_rid);
- dmae_set_chcr(sh_chan, cfg->chcr);
- } else {
-@@ -609,14 +604,15 @@ const struct dev_pm_ops sh_dmae_pm = {
-
- static dma_addr_t sh_dmae_slave_addr(struct shdma_chan *schan)
- {
-- struct sh_dmae_slave *param = schan->dma_chan.private;
-+ struct sh_dmae_chan *sh_chan = container_of(schan,
-+ struct sh_dmae_chan, shdma_chan);
-
- /*
-- * Implicit BUG_ON(!param)
-- * if (param != NULL), this is a successfully requested slave channel,
-- * therefore param->config != NULL too.
-+ * Implicit BUG_ON(!sh_chan->config)
-+ * This is an exclusive slave DMA operation, may only be called after a
-+ * successful slave configuration.
- */
-- return param->config->addr;
-+ return sh_chan->config->addr;
- }
-
- static struct shdma_desc *sh_dmae_embedded_desc(void *buf, int i)
-diff --git a/drivers/dma/sh/shdma.h b/drivers/dma/sh/shdma.h
-index 840e47d..9314e93 100644
---- a/drivers/dma/sh/shdma.h
-+++ b/drivers/dma/sh/shdma.h
-@@ -13,6 +13,7 @@
- #ifndef __DMA_SHDMA_H
- #define __DMA_SHDMA_H
-
-+#include <linux/sh_dma.h>
- #include <linux/shdma-base.h>
- #include <linux/dmaengine.h>
- #include <linux/interrupt.h>
-@@ -25,6 +26,7 @@ struct device;
-
- struct sh_dmae_chan {
- struct shdma_chan shdma_chan;
-+ const struct sh_dmae_slave_config *config; /* Slave DMA configuration */
- int xmit_shift; /* log_2(bytes_per_xfer) */
- u32 __iomem *base;
- char dev_id[16]; /* unique name per DMAC of channel */
-diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
-index 7c8ca41..a79f10a 100644
---- a/include/linux/sh_dma.h
-+++ b/include/linux/sh_dma.h
-@@ -20,8 +20,6 @@ struct device;
- /* Used by slave DMA clients to request DMA to/from a specific peripheral */
- struct sh_dmae_slave {
- struct shdma_slave shdma_slave; /* Set by the platform */
-- struct device *dma_dev; /* Set by the platform */
-- const struct sh_dmae_slave_config *config; /* Set by the driver */
- };
-
- /*
-diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
-index 83efd13..c3a19e9 100644
---- a/include/linux/shdma-base.h
-+++ b/include/linux/shdma-base.h
-@@ -66,6 +66,7 @@ struct shdma_chan {
- size_t max_xfer_len; /* max transfer length */
- int id; /* Raw id of this channel */
- int irq; /* Channel IRQ */
-+ struct shdma_slave *slave; /* Client data for slave DMA */
- enum shdma_pm_state pm_state;
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From fc5aa8d8ebed522f219c9a368306cbe41fe75ca9 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Thu, 5 Jul 2012 12:29:37 +0200
-Subject: dmaengine: shdma: (cosmetic) simplify a static function
-
-dmae_find_slave() needs only the slave_id field from the slave object, no
-need to pass the pointer to the object, pass the slave_id directly.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit 341f4dc5dcecbf60f038055db177845b9af480ed)
-
-Conflicts:
- drivers/dma/sh/shdma.c
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/dma/sh/shdma.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
-index 305e77a..9f0a2e5 100644
---- a/drivers/dma/sh/shdma.c
-+++ b/drivers/dma/sh/shdma.c
-@@ -302,18 +302,18 @@ static void sh_dmae_setup_xfer(struct shdma_chan *schan,
- }
-
- static const struct sh_dmae_slave_config *dmae_find_slave(
-- struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *slave)
-+ struct sh_dmae_chan *sh_chan, unsigned int slave_id)
- {
- struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
- struct sh_dmae_pdata *pdata = shdev->pdata;
- const struct sh_dmae_slave_config *cfg;
- int i;
-
-- if (slave->shdma_slave.slave_id >= SH_DMA_SLAVE_NUMBER)
-+ if (slave_id >= SH_DMA_SLAVE_NUMBER)
- return NULL;
-
- for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++)
-- if (cfg->slave_id == slave->shdma_slave.slave_id)
-+ if (cfg->slave_id == slave_id)
- return cfg;
-
- return NULL;
-@@ -324,7 +324,7 @@ static int sh_dmae_set_slave(struct shdma_chan *schan,
- {
- struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
- shdma_chan);
-- const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave);
-+ const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, sslave->slave_id);
- if (!cfg)
- return -ENODEV;
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 994962e925ac52b6a5c870d02f537c5e3dd535ca Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Thu, 5 Jul 2012 12:29:41 +0200
-Subject: dma: sh: use an integer slave ID to improve API compatibility
-
-Initially struct shdma_slave has been introduced with the only member - an
-unsigned slave ID - to describe common properties of DMA slaves in an
-extensible way. However, experience shows, that a slave ID is indeed the
-only parameter, needed to identify DMA slaves. This is also, what is used
-by the core dmaengine API in struct dma_slave_config. We switch to using
-the slave_id directly, instead of passing a pointer to struct shdma_slave
-to improve compatibility with the core. We also make the slave_id signed
-for easier error checking.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit c2cdb7e4d16394fc51dc5c2c5b3e7c3733bdfaac)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/dma/sh/shdma-base.c | 25 +++++++++++++------------
- drivers/dma/sh/shdma.c | 12 ++++++------
- include/linux/sh_dma.h | 8 ++++----
- include/linux/shdma-base.h | 8 ++++----
- 4 files changed, 27 insertions(+), 26 deletions(-)
-
-diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
-index f75ebfa..73db282 100644
---- a/drivers/dma/sh/shdma-base.c
-+++ b/drivers/dma/sh/shdma-base.c
-@@ -76,7 +76,6 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
- container_of(tx, struct shdma_desc, async_tx),
- *last = desc;
- struct shdma_chan *schan = to_shdma_chan(tx->chan);
-- struct shdma_slave *slave = schan->slave;
- dma_async_tx_callback callback = tx->callback;
- dma_cookie_t cookie;
- bool power_up;
-@@ -138,7 +137,7 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
- * Make it int then, on error remove chunks from the
- * queue again
- */
-- ops->setup_xfer(schan, slave);
-+ ops->setup_xfer(schan, schan->slave_id);
-
- if (schan->pm_state == SHDMA_PM_PENDING)
- shdma_chan_xfer_ld_queue(schan);
-@@ -186,7 +185,7 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
- * never runs concurrently with itself or free_chan_resources.
- */
- if (slave) {
-- if (slave->slave_id >= slave_num) {
-+ if (slave->slave_id < 0 || slave->slave_id >= slave_num) {
- ret = -EINVAL;
- goto evalid;
- }
-@@ -196,9 +195,13 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
- goto etestused;
- }
-
-- ret = ops->set_slave(schan, slave);
-+ ret = ops->set_slave(schan, slave->slave_id);
- if (ret < 0)
- goto esetslave;
-+
-+ schan->slave_id = slave->slave_id;
-+ } else {
-+ schan->slave_id = -EINVAL;
- }
-
- schan->desc = kcalloc(NR_DESCS_PER_CHANNEL,
-@@ -208,7 +211,6 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
- goto edescalloc;
- }
- schan->desc_num = NR_DESCS_PER_CHANNEL;
-- schan->slave = slave;
-
- for (i = 0; i < NR_DESCS_PER_CHANNEL; i++) {
- desc = ops->embedded_desc(schan->desc, i);
-@@ -366,10 +368,9 @@ static void shdma_free_chan_resources(struct dma_chan *chan)
- if (!list_empty(&schan->ld_queue))
- shdma_chan_ld_cleanup(schan, true);
-
-- if (schan->slave) {
-+ if (schan->slave_id >= 0) {
- /* The caller is holding dma_list_mutex */
-- struct shdma_slave *slave = schan->slave;
-- clear_bit(slave->slave_id, shdma_slave_used);
-+ clear_bit(schan->slave_id, shdma_slave_used);
- chan->private = NULL;
- }
-
-@@ -559,7 +560,7 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg(
- struct shdma_chan *schan = to_shdma_chan(chan);
- struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
- const struct shdma_ops *ops = sdev->ops;
-- struct shdma_slave *slave = schan->slave;
-+ int slave_id = schan->slave_id;
- dma_addr_t slave_addr;
-
- if (!chan)
-@@ -568,9 +569,9 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg(
- BUG_ON(!schan->desc_num);
-
- /* Someone calling slave DMA on a generic channel? */
-- if (!slave || !sg_len) {
-- dev_warn(schan->dev, "%s: bad parameter: %p, %d, %d\n",
-- __func__, slave, sg_len, slave ? slave->slave_id : -1);
-+ if (slave_id < 0 || !sg_len) {
-+ dev_warn(schan->dev, "%s: bad parameter: len=%d, id=%d\n",
-+ __func__, sg_len, slave_id);
- return NULL;
- }
-
-diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
-index 9f0a2e5..9a10d8b 100644
---- a/drivers/dma/sh/shdma.c
-+++ b/drivers/dma/sh/shdma.c
-@@ -285,12 +285,12 @@ static bool sh_dmae_channel_busy(struct shdma_chan *schan)
- }
-
- static void sh_dmae_setup_xfer(struct shdma_chan *schan,
-- struct shdma_slave *sslave)
-+ int slave_id)
- {
- struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
- shdma_chan);
-
-- if (sslave) {
-+ if (slave_id >= 0) {
- const struct sh_dmae_slave_config *cfg =
- sh_chan->config;
-
-@@ -302,7 +302,7 @@ static void sh_dmae_setup_xfer(struct shdma_chan *schan,
- }
-
- static const struct sh_dmae_slave_config *dmae_find_slave(
-- struct sh_dmae_chan *sh_chan, unsigned int slave_id)
-+ struct sh_dmae_chan *sh_chan, int slave_id)
- {
- struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
- struct sh_dmae_pdata *pdata = shdev->pdata;
-@@ -320,11 +320,11 @@ static const struct sh_dmae_slave_config *dmae_find_slave(
- }
-
- static int sh_dmae_set_slave(struct shdma_chan *schan,
-- struct shdma_slave *sslave)
-+ int slave_id)
- {
- struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
- shdma_chan);
-- const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, sslave->slave_id);
-+ const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave_id);
- if (!cfg)
- return -ENODEV;
-
-@@ -579,7 +579,7 @@ static int sh_dmae_resume(struct device *dev)
- if (!sh_chan->shdma_chan.desc_num)
- continue;
-
-- if (sh_chan->shdma_chan.slave) {
-+ if (sh_chan->shdma_chan.slave_id >= 0) {
- const struct sh_dmae_slave_config *cfg = sh_chan->config;
- dmae_set_dmars(sh_chan, cfg->mid_rid);
- dmae_set_chcr(sh_chan, cfg->chcr);
-diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
-index a79f10a..4e83f3e 100644
---- a/include/linux/sh_dma.h
-+++ b/include/linux/sh_dma.h
-@@ -27,10 +27,10 @@ struct sh_dmae_slave {
- * a certain peripheral
- */
- struct sh_dmae_slave_config {
-- unsigned int slave_id;
-- dma_addr_t addr;
-- u32 chcr;
-- char mid_rid;
-+ int slave_id;
-+ dma_addr_t addr;
-+ u32 chcr;
-+ char mid_rid;
- };
-
- struct sh_dmae_channel {
-diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
-index c3a19e9..6263ad2 100644
---- a/include/linux/shdma-base.h
-+++ b/include/linux/shdma-base.h
-@@ -43,7 +43,7 @@ struct device;
- */
-
- struct shdma_slave {
-- unsigned int slave_id;
-+ int slave_id;
- };
-
- struct shdma_desc {
-@@ -66,7 +66,7 @@ struct shdma_chan {
- size_t max_xfer_len; /* max transfer length */
- int id; /* Raw id of this channel */
- int irq; /* Channel IRQ */
-- struct shdma_slave *slave; /* Client data for slave DMA */
-+ int slave_id; /* Client ID for slave DMA */
- enum shdma_pm_state pm_state;
- };
-
-@@ -93,8 +93,8 @@ struct shdma_ops {
- dma_addr_t (*slave_addr)(struct shdma_chan *);
- int (*desc_setup)(struct shdma_chan *, struct shdma_desc *,
- dma_addr_t, dma_addr_t, size_t *);
-- int (*set_slave)(struct shdma_chan *, struct shdma_slave *);
-- void (*setup_xfer)(struct shdma_chan *, struct shdma_slave *);
-+ int (*set_slave)(struct shdma_chan *, int);
-+ void (*setup_xfer)(struct shdma_chan *, int);
- void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
- struct shdma_desc *(*embedded_desc)(void *, int);
- bool (*chan_irq)(struct shdma_chan *, int);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 3f976e575c229dad477f66090af9286700b35b3e Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Thu, 5 Jul 2012 12:29:42 +0200
-Subject: dma: sh: provide a migration path for slave drivers to stop using
- .private
-
-This patch extends the sh dmaengine driver to support the preferred channel
-selection and configuration method, instead of using the "private" field
-from struct dma_chan. We add a standard filter function to be used by
-slave drivers instead of implementing their own ones, and add support for
-the DMA_SLAVE_CONFIG control operation, which must accompany the new
-channel selection method. We still support the legacy .private channel
-allocation method to cater for a smooth driver migration.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-[applied a trvial checkpath fix]
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit 1ff8df4f5388ad66bd7d0199b5839a2e3345c055)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/dma/sh/shdma-base.c | 114 ++++++++++++++++++++++++++++++++++----------
- drivers/dma/sh/shdma.c | 5 +-
- include/linux/sh_dma.h | 2 +
- include/linux/shdma-base.h | 2 +-
- 4 files changed, 95 insertions(+), 28 deletions(-)
-
-diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
-index 73db282..27f5c78 100644
---- a/drivers/dma/sh/shdma-base.c
-+++ b/drivers/dma/sh/shdma-base.c
-@@ -171,6 +171,65 @@ static struct shdma_desc *shdma_get_desc(struct shdma_chan *schan)
- return NULL;
- }
-
-+static int shdma_setup_slave(struct shdma_chan *schan, int slave_id)
-+{
-+ struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
-+ const struct shdma_ops *ops = sdev->ops;
-+ int ret;
-+
-+ if (slave_id < 0 || slave_id >= slave_num)
-+ return -EINVAL;
-+
-+ if (test_and_set_bit(slave_id, shdma_slave_used))
-+ return -EBUSY;
-+
-+ ret = ops->set_slave(schan, slave_id, false);
-+ if (ret < 0) {
-+ clear_bit(slave_id, shdma_slave_used);
-+ return ret;
-+ }
-+
-+ schan->slave_id = slave_id;
-+
-+ return 0;
-+}
-+
-+/*
-+ * This is the standard shdma filter function to be used as a replacement to the
-+ * "old" method, using the .private pointer. If for some reason you allocate a
-+ * channel without slave data, use something like ERR_PTR(-EINVAL) as a filter
-+ * parameter. If this filter is used, the slave driver, after calling
-+ * dma_request_channel(), will also have to call dmaengine_slave_config() with
-+ * .slave_id, .direction, and either .src_addr or .dst_addr set.
-+ * NOTE: this filter doesn't support multiple DMAC drivers with the DMA_SLAVE
-+ * capability! If this becomes a requirement, hardware glue drivers, using this
-+ * services would have to provide their own filters, which first would check
-+ * the device driver, similar to how other DMAC drivers, e.g., sa11x0-dma.c, do
-+ * this, and only then, in case of a match, call this common filter.
-+ */
-+bool shdma_chan_filter(struct dma_chan *chan, void *arg)
-+{
-+ struct shdma_chan *schan = to_shdma_chan(chan);
-+ struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
-+ const struct shdma_ops *ops = sdev->ops;
-+ int slave_id = (int)arg;
-+ int ret;
-+
-+ if (slave_id < 0)
-+ /* No slave requested - arbitrary channel */
-+ return true;
-+
-+ if (slave_id >= slave_num)
-+ return false;
-+
-+ ret = ops->set_slave(schan, slave_id, true);
-+ if (ret < 0)
-+ return false;
-+
-+ return true;
-+}
-+EXPORT_SYMBOL(shdma_chan_filter);
-+
- static int shdma_alloc_chan_resources(struct dma_chan *chan)
- {
- struct shdma_chan *schan = to_shdma_chan(chan);
-@@ -185,21 +244,10 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
- * never runs concurrently with itself or free_chan_resources.
- */
- if (slave) {
-- if (slave->slave_id < 0 || slave->slave_id >= slave_num) {
-- ret = -EINVAL;
-- goto evalid;
-- }
--
-- if (test_and_set_bit(slave->slave_id, shdma_slave_used)) {
-- ret = -EBUSY;
-- goto etestused;
-- }
--
-- ret = ops->set_slave(schan, slave->slave_id);
-+ /* Legacy mode: .private is set in filter */
-+ ret = shdma_setup_slave(schan, slave->slave_id);
- if (ret < 0)
- goto esetslave;
--
-- schan->slave_id = slave->slave_id;
- } else {
- schan->slave_id = -EINVAL;
- }
-@@ -228,8 +276,6 @@ edescalloc:
- if (slave)
- esetslave:
- clear_bit(slave->slave_id, shdma_slave_used);
--etestused:
--evalid:
- chan->private = NULL;
- return ret;
- }
-@@ -587,22 +633,40 @@ static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
- struct shdma_chan *schan = to_shdma_chan(chan);
- struct shdma_dev *sdev = to_shdma_dev(chan->device);
- const struct shdma_ops *ops = sdev->ops;
-+ struct dma_slave_config *config;
- unsigned long flags;
--
-- /* Only supports DMA_TERMINATE_ALL */
-- if (cmd != DMA_TERMINATE_ALL)
-- return -ENXIO;
-+ int ret;
-
- if (!chan)
- return -EINVAL;
-
-- spin_lock_irqsave(&schan->chan_lock, flags);
--
-- ops->halt_channel(schan);
--
-- spin_unlock_irqrestore(&schan->chan_lock, flags);
-+ switch (cmd) {
-+ case DMA_TERMINATE_ALL:
-+ spin_lock_irqsave(&schan->chan_lock, flags);
-+ ops->halt_channel(schan);
-+ spin_unlock_irqrestore(&schan->chan_lock, flags);
-
-- shdma_chan_ld_cleanup(schan, true);
-+ shdma_chan_ld_cleanup(schan, true);
-+ break;
-+ case DMA_SLAVE_CONFIG:
-+ /*
-+ * So far only .slave_id is used, but the slave drivers are
-+ * encouraged to also set a transfer direction and an address.
-+ */
-+ if (!arg)
-+ return -EINVAL;
-+ /*
-+ * We could lock this, but you shouldn't be configuring the
-+ * channel, while using it...
-+ */
-+ config = (struct dma_slave_config *)arg;
-+ ret = shdma_setup_slave(schan, config->slave_id);
-+ if (ret < 0)
-+ return ret;
-+ break;
-+ default:
-+ return -ENXIO;
-+ }
-
- return 0;
- }
-diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
-index 9a10d8b..027c9be 100644
---- a/drivers/dma/sh/shdma.c
-+++ b/drivers/dma/sh/shdma.c
-@@ -320,7 +320,7 @@ static const struct sh_dmae_slave_config *dmae_find_slave(
- }
-
- static int sh_dmae_set_slave(struct shdma_chan *schan,
-- int slave_id)
-+ int slave_id, bool try)
- {
- struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
- shdma_chan);
-@@ -328,7 +328,8 @@ static int sh_dmae_set_slave(struct shdma_chan *schan,
- if (!cfg)
- return -ENODEV;
-
-- sh_chan->config = cfg;
-+ if (!try)
-+ sh_chan->config = cfg;
-
- return 0;
- }
-diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
-index 4e83f3e..b64d6be 100644
---- a/include/linux/sh_dma.h
-+++ b/include/linux/sh_dma.h
-@@ -99,4 +99,6 @@ struct sh_dmae_pdata {
- #define CHCR_TE 0x00000002
- #define CHCR_IE 0x00000004
-
-+bool shdma_chan_filter(struct dma_chan *chan, void *arg);
-+
- #endif
-diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
-index 6263ad2..93f9821 100644
---- a/include/linux/shdma-base.h
-+++ b/include/linux/shdma-base.h
-@@ -93,7 +93,7 @@ struct shdma_ops {
- dma_addr_t (*slave_addr)(struct shdma_chan *);
- int (*desc_setup)(struct shdma_chan *, struct shdma_desc *,
- dma_addr_t, dma_addr_t, size_t *);
-- int (*set_slave)(struct shdma_chan *, int);
-+ int (*set_slave)(struct shdma_chan *, int, bool);
- void (*setup_xfer)(struct shdma_chan *, int);
- void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
- struct shdma_desc *(*embedded_desc)(void *, int);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b1cb8efea85092e5441a428691a36d9fec40ca0f Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Mon, 30 Jul 2012 21:28:27 +0200
-Subject: dmaengine: shdma: restore partial transfer calculation
-
-The recent shdma driver split has mistakenly removed support for partial
-DMA transfer size calculation on forced termination. This patch restores
-it.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Acked-by: Vinod Koul <vinod.koul@linux.intel.com>
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 4f46f8ac80416b0e8fd3aba6a0d842205fb29140)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/dma/sh/shdma-base.c | 9 +++++++++
- drivers/dma/sh/shdma.c | 12 ++++++++++++
- include/linux/shdma-base.h | 2 ++
- 3 files changed, 23 insertions(+)
-
-diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
-index 27f5c78..f4cd946 100644
---- a/drivers/dma/sh/shdma-base.c
-+++ b/drivers/dma/sh/shdma-base.c
-@@ -483,6 +483,7 @@ static struct shdma_desc *shdma_add_desc(struct shdma_chan *schan,
- new->mark = DESC_PREPARED;
- new->async_tx.flags = flags;
- new->direction = direction;
-+ new->partial = 0;
-
- *len -= copy_size;
- if (direction == DMA_MEM_TO_MEM || direction == DMA_MEM_TO_DEV)
-@@ -644,6 +645,14 @@ static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
- case DMA_TERMINATE_ALL:
- spin_lock_irqsave(&schan->chan_lock, flags);
- ops->halt_channel(schan);
-+
-+ if (ops->get_partial && !list_empty(&schan->ld_queue)) {
-+ /* Record partial transfer */
-+ struct shdma_desc *desc = list_first_entry(&schan->ld_queue,
-+ struct shdma_desc, node);
-+ desc->partial = ops->get_partial(schan, desc);
-+ }
-+
- spin_unlock_irqrestore(&schan->chan_lock, flags);
-
- shdma_chan_ld_cleanup(schan, true);
-diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
-index 027c9be..f41bcc5 100644
---- a/drivers/dma/sh/shdma.c
-+++ b/drivers/dma/sh/shdma.c
-@@ -381,6 +381,17 @@ static bool sh_dmae_chan_irq(struct shdma_chan *schan, int irq)
- return true;
- }
-
-+static size_t sh_dmae_get_partial(struct shdma_chan *schan,
-+ struct shdma_desc *sdesc)
-+{
-+ struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
-+ shdma_chan);
-+ struct sh_dmae_desc *sh_desc = container_of(sdesc,
-+ struct sh_dmae_desc, shdma_desc);
-+ return (sh_desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) <<
-+ sh_chan->xmit_shift;
-+}
-+
- /* Called from error IRQ or NMI */
- static bool sh_dmae_reset(struct sh_dmae_device *shdev)
- {
-@@ -632,6 +643,7 @@ static const struct shdma_ops sh_dmae_shdma_ops = {
- .start_xfer = sh_dmae_start_xfer,
- .embedded_desc = sh_dmae_embedded_desc,
- .chan_irq = sh_dmae_chan_irq,
-+ .get_partial = sh_dmae_get_partial,
- };
-
- static int __devinit sh_dmae_probe(struct platform_device *pdev)
-diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
-index 93f9821..a3728bf 100644
---- a/include/linux/shdma-base.h
-+++ b/include/linux/shdma-base.h
-@@ -50,6 +50,7 @@ struct shdma_desc {
- struct list_head node;
- struct dma_async_tx_descriptor async_tx;
- enum dma_transfer_direction direction;
-+ size_t partial;
- dma_cookie_t cookie;
- int chunks;
- int mark;
-@@ -98,6 +99,7 @@ struct shdma_ops {
- void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
- struct shdma_desc *(*embedded_desc)(void *, int);
- bool (*chan_irq)(struct shdma_chan *, int);
-+ size_t (*get_partial)(struct shdma_chan *, struct shdma_desc *);
- };
-
- struct shdma_dev {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From f51d4dcccbe271ab892444ddb9821b2e8b976c04 Mon Sep 17 00:00:00 2001
-From: "Shimoda, Yoshihiro" <yoshihiro.shimoda.uh@renesas.com>
-Date: Fri, 6 Apr 2012 09:59:14 +0900
-Subject: serial: sh-sci: modify sci_break_ctl()
-
-SCIF modules which have SCSPTR can output the break signal. Now that we
-have a way of determining port features/capabilities, add trivial break
-control via SCSPTR support. Tested on sh7757lcr.
-
-Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Reviewed-by: Simon Horman <horms@verge.net.au>
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit bbb4ce50f3169b08764f9965fd5b9655646d545a)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/tty/serial/sh-sci.c | 30 ++++++++++++++++++++++++++----
- include/linux/serial_sci.h | 2 ++
- 2 files changed, 28 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
-index 3158e17..3e471fc 100644
---- a/drivers/tty/serial/sh-sci.c
-+++ b/drivers/tty/serial/sh-sci.c
-@@ -1564,10 +1564,32 @@ static void sci_enable_ms(struct uart_port *port)
-
- static void sci_break_ctl(struct uart_port *port, int break_state)
- {
-- /*
-- * Not supported by hardware. Most parts couple break and rx
-- * interrupts together, with break detection always enabled.
-- */
-+ struct sci_port *s = to_sci_port(port);
-+ unsigned short scscr, scsptr;
-+
-+ switch (s->cfg->regtype) {
-+ case SCIx_SH4_SCIF_REGTYPE:
-+ scsptr = serial_port_in(port, SCSPTR);
-+ scscr = serial_port_in(port, SCSCR);
-+
-+ if (break_state == -1) {
-+ scsptr = (scsptr | SCSPTR_SPB2IO) & ~SCSPTR_SPB2DT;
-+ scscr &= ~SCSCR_TE;
-+ } else {
-+ scsptr = (scsptr | SCSPTR_SPB2DT) & ~SCSPTR_SPB2IO;
-+ scscr |= SCSCR_TE;
-+ }
-+
-+ serial_port_out(port, SCSPTR, scsptr);
-+ serial_port_out(port, SCSCR, scscr);
-+ break;
-+ default:
-+ /*
-+ * Not supported by hardware. Most parts couple break and rx
-+ * interrupts together, with break detection always enabled.
-+ */
-+ break;
-+ }
- }
-
- #ifdef CONFIG_SERIAL_SH_SCI_DMA
-diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h
-index 7877907..eb763ad 100644
---- a/include/linux/serial_sci.h
-+++ b/include/linux/serial_sci.h
-@@ -52,6 +52,8 @@ enum {
- /* SCSPTR, optional */
- #define SCSPTR_RTSIO (1 << 7)
- #define SCSPTR_CTSIO (1 << 5)
-+#define SCSPTR_SPB2IO (1 << 1)
-+#define SCSPTR_SPB2DT (1 << 0)
-
- /* Offsets into the sci_port->irqs array */
- enum {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 771d21f0510973f1da8789ad877a0fa806aa1ec7 Mon Sep 17 00:00:00 2001
-From: "Shimoda, Yoshihiro" <yoshihiro.shimoda.uh@renesas.com>
-Date: Thu, 12 Apr 2012 19:19:21 +0900
-Subject: serial: sh-sci: Update break_ctl handling for all SCSPTR-capable
- regtypes.
-
-This updates the earlier break_ctl support regardless of regtype so long
-as the requisite SCSPTR exists. This is the same approach used by
-sci_init_pins() for providing a generic solution now that we're able to
-detect register capabilities on a per-port basis.
-
-Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit a4e02f6d83d4fcdb13bcaba76878fc5ea0da9911)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/tty/serial/sh-sci.c | 36 ++++++++++++++++++------------------
- 1 file changed, 18 insertions(+), 18 deletions(-)
-
-diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
-index 3e471fc..be31d85 100644
---- a/drivers/tty/serial/sh-sci.c
-+++ b/drivers/tty/serial/sh-sci.c
-@@ -1565,31 +1565,31 @@ static void sci_enable_ms(struct uart_port *port)
- static void sci_break_ctl(struct uart_port *port, int break_state)
- {
- struct sci_port *s = to_sci_port(port);
-+ struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
- unsigned short scscr, scsptr;
-
-- switch (s->cfg->regtype) {
-- case SCIx_SH4_SCIF_REGTYPE:
-- scsptr = serial_port_in(port, SCSPTR);
-- scscr = serial_port_in(port, SCSCR);
--
-- if (break_state == -1) {
-- scsptr = (scsptr | SCSPTR_SPB2IO) & ~SCSPTR_SPB2DT;
-- scscr &= ~SCSCR_TE;
-- } else {
-- scsptr = (scsptr | SCSPTR_SPB2DT) & ~SCSPTR_SPB2IO;
-- scscr |= SCSCR_TE;
-- }
--
-- serial_port_out(port, SCSPTR, scsptr);
-- serial_port_out(port, SCSCR, scscr);
-- break;
-- default:
-+ /* check wheter the port has SCSPTR */
-+ if (!reg->size) {
- /*
- * Not supported by hardware. Most parts couple break and rx
- * interrupts together, with break detection always enabled.
- */
-- break;
-+ return;
- }
-+
-+ scsptr = serial_port_in(port, SCSPTR);
-+ scscr = serial_port_in(port, SCSCR);
-+
-+ if (break_state == -1) {
-+ scsptr = (scsptr | SCSPTR_SPB2IO) & ~SCSPTR_SPB2DT;
-+ scscr &= ~SCSCR_TE;
-+ } else {
-+ scsptr = (scsptr | SCSPTR_SPB2DT) & ~SCSPTR_SPB2IO;
-+ scscr |= SCSCR_TE;
-+ }
-+
-+ serial_port_out(port, SCSPTR, scsptr);
-+ serial_port_out(port, SCSCR, scscr);
- }
-
- #ifdef CONFIG_SERIAL_SH_SCI_DMA
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 0491f004737edadd928f7d46f5e9f0f8f5f054e0 Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Fri, 18 May 2012 18:21:06 +0900
-Subject: serial: sh-sci: Fix for port types without BRI interrupts.
-
-In doing the evt2irq() + muxed vector conversion for various port types
-it became apparent that some of the legacy port types will presently
-error out due to the irq requesting logic attempting to acquire the
-non-existent BRI IRQ. This adds some sanity checks to the request/free
-path to ensure that non-existence of a source in itself is not an error.
-
-This should restore functionality for legacy PORT_SCI ports.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 0e8963de1fe95e7fbc30c79c1dbc7cb1ea0cf699)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/tty/serial/sh-sci.c | 19 ++++++++++++++++++-
- 1 file changed, 18 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
-index be31d85..4604153 100644
---- a/drivers/tty/serial/sh-sci.c
-+++ b/drivers/tty/serial/sh-sci.c
-@@ -1052,9 +1052,17 @@ static int sci_request_irq(struct sci_port *port)
- if (SCIx_IRQ_IS_MUXED(port)) {
- i = SCIx_MUX_IRQ;
- irq = up->irq;
-- } else
-+ } else {
- irq = port->cfg->irqs[i];
-
-+ /*
-+ * Certain port types won't support all of the
-+ * available interrupt sources.
-+ */
-+ if (unlikely(!irq))
-+ continue;
-+ }
-+
- desc = sci_irq_desc + i;
- port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
- dev_name(up->dev), desc->desc);
-@@ -1094,6 +1102,15 @@ static void sci_free_irq(struct sci_port *port)
- * IRQ first.
- */
- for (i = 0; i < SCIx_NR_IRQS; i++) {
-+ unsigned int irq = port->cfg->irqs[i];
-+
-+ /*
-+ * Certain port types won't support all of the available
-+ * interrupt sources.
-+ */
-+ if (unlikely(!irq))
-+ continue;
-+
- free_irq(port->cfg->irqs[i], port);
- kfree(port->irqstr[i]);
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 61760a1e6363eeb42b29b76176e3ec4ac837753b Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Wed, 13 Jun 2012 00:28:23 +0200
-Subject: serial: sh-sci: Fix probe error paths
-
-When probing fails, the driver must not try to cleanup resources that
-have not been initialized. Fix this.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 6dae14216c85eea13db7b12c469475c5d30e5499)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/tty/serial/sh-sci.c | 36 +++++++++++++++++++++++-------------
- 1 file changed, 23 insertions(+), 13 deletions(-)
-
-diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
-index 4604153..27df2ad 100644
---- a/drivers/tty/serial/sh-sci.c
-+++ b/drivers/tty/serial/sh-sci.c
-@@ -2179,6 +2179,16 @@ static int __devinit sci_init_single(struct platform_device *dev,
- return 0;
- }
-
-+static void sci_cleanup_single(struct sci_port *port)
-+{
-+ sci_free_gpios(port);
-+
-+ clk_put(port->iclk);
-+ clk_put(port->fclk);
-+
-+ pm_runtime_disable(port->port.dev);
-+}
-+
- #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
- static void serial_console_putchar(struct uart_port *port, int ch)
- {
-@@ -2360,14 +2370,10 @@ static int sci_remove(struct platform_device *dev)
- cpufreq_unregister_notifier(&port->freq_transition,
- CPUFREQ_TRANSITION_NOTIFIER);
-
-- sci_free_gpios(port);
--
- uart_remove_one_port(&sci_uart_driver, &port->port);
-
-- clk_put(port->iclk);
-- clk_put(port->fclk);
-+ sci_cleanup_single(port);
-
-- pm_runtime_disable(&dev->dev);
- return 0;
- }
-
-@@ -2392,7 +2398,13 @@ static int __devinit sci_probe_single(struct platform_device *dev,
- if (ret)
- return ret;
-
-- return uart_add_one_port(&sci_uart_driver, &sciport->port);
-+ ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
-+ if (ret) {
-+ sci_cleanup_single(sciport);
-+ return ret;
-+ }
-+
-+ return 0;
- }
-
- static int __devinit sci_probe(struct platform_device *dev)
-@@ -2413,24 +2425,22 @@ static int __devinit sci_probe(struct platform_device *dev)
-
- ret = sci_probe_single(dev, dev->id, p, sp);
- if (ret)
-- goto err_unreg;
-+ return ret;
-
- sp->freq_transition.notifier_call = sci_notifier;
-
- ret = cpufreq_register_notifier(&sp->freq_transition,
- CPUFREQ_TRANSITION_NOTIFIER);
-- if (unlikely(ret < 0))
-- goto err_unreg;
-+ if (unlikely(ret < 0)) {
-+ sci_cleanup_single(sp);
-+ return ret;
-+ }
-
- #ifdef CONFIG_SH_STANDARD_BIOS
- sh_bios_gdb_detach();
- #endif
-
- return 0;
--
--err_unreg:
-- sci_remove(dev);
-- return ret;
- }
-
- static int sci_suspend(struct device *dev)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e78402772bb6c357710275ae6958fd9eaab70036 Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Wed, 13 Jun 2012 00:28:24 +0200
-Subject: serial: sh-sci: Make probe fail for ports that exceed the maximum
- count
-
-The driver supports a maximum number of ports configurable at compile
-time. Make sure the probe() method fails when registering a port that
-exceeds the maximum instead of returning success without registering the
-port.
-
-This fixes a crash at system suspend time, when the driver tried to
-suspend a non-registered port using the UART core.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit b6c5ef6f6d3e46d6200b141c30ac000a11b851df)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/tty/serial/sh-sci.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
-index 27df2ad..1bd9163 100644
---- a/drivers/tty/serial/sh-sci.c
-+++ b/drivers/tty/serial/sh-sci.c
-@@ -2391,7 +2391,7 @@ static int __devinit sci_probe_single(struct platform_device *dev,
- index+1, SCI_NPORTS);
- dev_notice(&dev->dev, "Consider bumping "
- "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
-- return 0;
-+ return -EINVAL;
- }
-
- ret = sci_init_single(dev, sciport, index, p);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From d9a397f8913cef21e0cc251856d5e3e709d057f8 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 9 May 2012 17:09:17 +0200
-Subject: serial: sh-sci: prepare for conversion to the shdma base library
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Cc: Alan Cox <alan@linux.intel.com>
-Acked-by: Paul Mundt <lethal@linux-sh.org>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit d6fa5a4e7ab605370fd6c982782f84ef2e6660e7)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/tty/serial/sh-sci.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
-index 1bd9163..d4d8c94 100644
---- a/drivers/tty/serial/sh-sci.c
-+++ b/drivers/tty/serial/sh-sci.c
-@@ -1615,9 +1615,9 @@ static bool filter(struct dma_chan *chan, void *slave)
- struct sh_dmae_slave *param = slave;
-
- dev_dbg(chan->device->dev, "%s: slave ID %d\n", __func__,
-- param->slave_id);
-+ param->shdma_slave.slave_id);
-
-- chan->private = param;
-+ chan->private = ¶m->shdma_slave;
- return true;
- }
-
-@@ -1656,7 +1656,7 @@ static void sci_request_dma(struct uart_port *port)
- param = &s->param_tx;
-
- /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */
-- param->slave_id = s->cfg->dma_slave_tx;
-+ param->shdma_slave.slave_id = s->cfg->dma_slave_tx;
-
- s->cookie_tx = -EINVAL;
- chan = dma_request_channel(mask, filter, param);
-@@ -1684,7 +1684,7 @@ static void sci_request_dma(struct uart_port *port)
- param = &s->param_rx;
-
- /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */
-- param->slave_id = s->cfg->dma_slave_rx;
-+ param->shdma_slave.slave_id = s->cfg->dma_slave_rx;
-
- chan = dma_request_channel(mask, filter, param);
- dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 3e91d8139916610c1a34ff1359fb866b2bc82bab Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Mon, 30 Jul 2012 21:28:47 +0200
-Subject: serial: sh-sci: fix compilation breakage, when DMA is enabled
-
-A recent commit:
-
-commit d6fa5a4e7ab605370fd6c982782f84ef2e6660e7
-Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- serial: sh-sci: prepare for conversion to the shdma base library
-
-is not sufficient to update the sh-sci driver to the new shdma driver
-layout. This caused compilation breakage, when CONFIG_SERIAL_SH_SCI_DMA
-is enabled. This patch trivially fixes the problem by updating the DMA
-descriptor manipulation code.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit 4dc4c51675c137c30838425ecc8d471ff5eb138b)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/tty/serial/sh-sci.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
-index d4d8c94..9be296c 100644
---- a/drivers/tty/serial/sh-sci.c
-+++ b/drivers/tty/serial/sh-sci.c
-@@ -25,6 +25,7 @@
-
- #include <linux/module.h>
- #include <linux/errno.h>
-+#include <linux/sh_dma.h>
- #include <linux/timer.h>
- #include <linux/interrupt.h>
- #include <linux/tty.h>
-@@ -1410,8 +1411,8 @@ static void work_fn_rx(struct work_struct *work)
- /* Handle incomplete DMA receive */
- struct tty_struct *tty = port->state->port.tty;
- struct dma_chan *chan = s->chan_rx;
-- struct sh_desc *sh_desc = container_of(desc, struct sh_desc,
-- async_tx);
-+ struct shdma_desc *sh_desc = container_of(desc,
-+ struct shdma_desc, async_tx);
- unsigned long flags;
- int count;
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 925ce819e01d210634e6108067368107fe17fd8c Mon Sep 17 00:00:00 2001
-From: Lee Jones <lee.jones@linaro.org>
-Date: Tue, 29 May 2012 18:47:37 +0000
-Subject: net/smsc911x: Repair broken failure paths
-
-Current failure paths attempt to free resources which we failed to request
-and disable resources which we failed to enable ones. This leads to kernel
-oops/panic. This patch does some simple re-ordering to prevent this from
-happening.
-
-Cc: netdev@vger.kernel.org
-Signed-off-by: Lee Jones <lee.jones@linaro.org>
-Acked-by: Linus Walleij <linus.walleij@linaro.org>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-(cherry picked from commit 2e1d4a065a77d076a679df22a4eddbc7e33cad98)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/net/ethernet/smsc/smsc911x.c | 7 ++++---
- 1 file changed, 4 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
-index cd3defb..245c700 100644
---- a/drivers/net/ethernet/smsc/smsc911x.c
-+++ b/drivers/net/ethernet/smsc/smsc911x.c
-@@ -2389,11 +2389,11 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
-
- retval = smsc911x_request_resources(pdev);
- if (retval)
-- goto out_return_resources;
-+ goto out_request_resources_fail;
-
- retval = smsc911x_enable_resources(pdev);
- if (retval)
-- goto out_disable_resources;
-+ goto out_enable_resources_fail;
-
- if (pdata->ioaddr == NULL) {
- SMSC_WARN(pdata, probe, "Error smsc911x base address invalid");
-@@ -2500,8 +2500,9 @@ out_free_irq:
- free_irq(dev->irq, dev);
- out_disable_resources:
- (void)smsc911x_disable_resources(pdev);
--out_return_resources:
-+out_enable_resources_fail:
- smsc911x_free_resources(pdev);
-+out_request_resources_fail:
- platform_set_drvdata(pdev, NULL);
- iounmap(pdata->ioaddr);
- free_netdev(dev);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 89b2c2592f45401b0862a70a6d71e4c81274c1a3 Mon Sep 17 00:00:00 2001
-From: Matthias Brugger <mbrugger@iseebcn.com>
-Date: Fri, 22 Jun 2012 01:10:15 +0000
-Subject: smsc911x.c: encapsulate enable irq calls
-
-We encapsulate enbale irq functionality in a function call.
-As on probe the interrupts will be disabled twice, we delete
-one.
-
-Signed-off-by: Matthias Brugger <mbrugger@iseebcn.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-(cherry picked from commit 8e27628ecf883b9e5825103e40e6f86bf8225f1a)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/net/ethernet/smsc/smsc911x.c | 17 ++++++++++-------
- 1 file changed, 10 insertions(+), 7 deletions(-)
-
-diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
-index 245c700..759e9b4 100644
---- a/drivers/net/ethernet/smsc/smsc911x.c
-+++ b/drivers/net/ethernet/smsc/smsc911x.c
-@@ -1442,6 +1442,14 @@ smsc911x_set_hw_mac_address(struct smsc911x_data *pdata, u8 dev_addr[6])
- smsc911x_mac_write(pdata, ADDRL, mac_low32);
- }
-
-+static void smsc911x_disable_irq_chip(struct net_device *dev)
-+{
-+ struct smsc911x_data *pdata = netdev_priv(dev);
-+
-+ smsc911x_reg_write(pdata, INT_EN, 0);
-+ smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF);
-+}
-+
- static int smsc911x_open(struct net_device *dev)
- {
- struct smsc911x_data *pdata = netdev_priv(dev);
-@@ -1494,8 +1502,7 @@ static int smsc911x_open(struct net_device *dev)
- spin_unlock_irq(&pdata->mac_lock);
-
- /* Initialise irqs, but leave all sources disabled */
-- smsc911x_reg_write(pdata, INT_EN, 0);
-- smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF);
-+ smsc911x_disable_irq_chip(dev);
-
- /* Set interrupt deassertion to 100uS */
- intcfg = ((10 << 24) | INT_CFG_IRQ_EN_);
-@@ -2214,9 +2221,6 @@ static int __devinit smsc911x_init(struct net_device *dev)
- if (smsc911x_soft_reset(pdata))
- return -ENODEV;
-
-- /* Disable all interrupt sources until we bring the device up */
-- smsc911x_reg_write(pdata, INT_EN, 0);
--
- ether_setup(dev);
- dev->flags |= IFF_MULTICAST;
- netif_napi_add(dev, &pdata->napi, smsc911x_poll, SMSC_NAPI_WEIGHT);
-@@ -2433,8 +2437,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
- smsc911x_reg_write(pdata, INT_CFG, intcfg);
-
- /* Ensure interrupts are globally disabled before connecting ISR */
-- smsc911x_reg_write(pdata, INT_EN, 0);
-- smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF);
-+ smsc911x_disable_irq_chip(dev);
-
- retval = request_irq(dev->irq, smsc911x_irqhandler,
- irq_flags | IRQF_SHARED, dev->name, dev);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 3dc719e07177476e63995abda41f8d86f7c6056d Mon Sep 17 00:00:00 2001
-From: Paul Mundt <lethal@linux-sh.org>
-Date: Fri, 25 May 2012 13:39:09 +0900
-Subject: clocksource: sh_tmu: Convert timer lock to raw spinlock.
-
-Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-(cherry picked from commit c2225a57e596a308424e59abc7e864f866fe4493)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/clocksource/sh_tmu.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
-index 97f54b6..852b3f1 100644
---- a/drivers/clocksource/sh_tmu.c
-+++ b/drivers/clocksource/sh_tmu.c
-@@ -45,7 +45,7 @@ struct sh_tmu_priv {
- struct clocksource cs;
- };
-
--static DEFINE_SPINLOCK(sh_tmu_lock);
-+static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
-
- #define TSTR -1 /* shared register */
- #define TCOR 0 /* channel register */
-@@ -95,7 +95,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start)
- unsigned long flags, value;
-
- /* start stop register shared by multiple timer channels */
-- spin_lock_irqsave(&sh_tmu_lock, flags);
-+ raw_spin_lock_irqsave(&sh_tmu_lock, flags);
- value = sh_tmu_read(p, TSTR);
-
- if (start)
-@@ -104,7 +104,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start)
- value &= ~(1 << cfg->timer_bit);
-
- sh_tmu_write(p, TSTR, value);
-- spin_unlock_irqrestore(&sh_tmu_lock, flags);
-+ raw_spin_unlock_irqrestore(&sh_tmu_lock, flags);
- }
-
- static int sh_tmu_enable(struct sh_tmu_priv *p)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 611af69d5a747a3c8d6268a006dd0d913257fe02 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 20 Jun 2012 19:10:35 +0200
-Subject: mmc: tmio: use MMC opcode defines instead of numbers
-
-mmc.h defines macros for most frequently used MMC opcodes. Use them instead
-of hard-coded numbers.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit 0f506a96693d8ad4aeccbd98dbd54a3c7357cfa8)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/tmio_mmc_pio.c | 7 ++++---
- 1 file changed, 4 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
-index 9a7996a..0ad3917 100644
---- a/drivers/mmc/host/tmio_mmc_pio.c
-+++ b/drivers/mmc/host/tmio_mmc_pio.c
-@@ -36,6 +36,7 @@
- #include <linux/mfd/tmio.h>
- #include <linux/mmc/cd-gpio.h>
- #include <linux/mmc/host.h>
-+#include <linux/mmc/mmc.h>
- #include <linux/mmc/tmio.h>
- #include <linux/module.h>
- #include <linux/pagemap.h>
-@@ -305,8 +306,8 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command
- int c = cmd->opcode;
- u32 irq_mask = TMIO_MASK_CMD;
-
-- /* Command 12 is handled by hardware */
-- if (cmd->opcode == 12 && !cmd->arg) {
-+ /* CMD12 is handled by hardware */
-+ if (cmd->opcode == MMC_STOP_TRANSMISSION && !cmd->arg) {
- sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x001);
- return 0;
- }
-@@ -449,7 +450,7 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
- }
-
- if (stop) {
-- if (stop->opcode == 12 && !stop->arg)
-+ if (stop->opcode == MMC_STOP_TRANSMISSION && !stop->arg)
- sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x000);
- else
- BUG();
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a43c0fe8cb2e7a3312b979c3b1fe1ab5b762994a Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Tue, 10 Jul 2012 22:54:11 -0400
-Subject: mmc: cd-gpio: pass IRQF_ONESHOT to request_threaded_irq()
-
-Fix a boot regression on Mackerel boards with sh_mobile_sdhi
-in existing kernels causing:
-
-genirq: Threaded irq requested with handler=NULL and !ONESHOT for irq XXX
-
-caused by 1c6c6952 (genirq: Reject bogus threaded irq requests).
-
-This is backported from Guennadi's patch:
-"mmc: extend and rename cd-gpio helpers to handle more slot GPIO functions"
-
-Reported-by: Rafael J. Wysocki <rjw@sisk.pl>
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit 623b51fc8642fd3c795fa9903be3adaa537ad9c5)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/core/cd-gpio.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/cd-gpio.c
-index f13e38d..8f5dc08 100644
---- a/drivers/mmc/core/cd-gpio.c
-+++ b/drivers/mmc/core/cd-gpio.c
-@@ -50,8 +50,8 @@ int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio)
- goto egpioreq;
-
- ret = request_threaded_irq(irq, NULL, mmc_cd_gpio_irqt,
-- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-- cd->label, host);
-+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
-+ IRQF_ONESHOT, cd->label, host);
- if (ret < 0)
- goto eirqreq;
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 06a2252e0baf7bc5e4dd3b8c31898edcc838b518 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Mon, 30 Apr 2012 23:31:57 +0200
-Subject: mmc: extend and rename cd-gpio helpers to handle more slot GPIO
- functions
-
-GPIOs can be used in MMC/SD-card slots not only for hotplug detection, but
-also to implement the write-protection pin. Rename cd-gpio helpers to
-slot-gpio to make addition of further slot GPIO functions possible.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit fd0ea65d3e675e479e022b6cfc9ebe1864c76afc)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/core/Makefile | 2 +-
- drivers/mmc/core/{cd-gpio.c => slot-gpio.c} | 48 ++++++++++++++--------------
- drivers/mmc/host/tmio_mmc_pio.c | 6 ++--
- include/linux/mmc/{cd-gpio.h => slot-gpio.h} | 8 ++---
- 4 files changed, 32 insertions(+), 32 deletions(-)
- rename drivers/mmc/core/{cd-gpio.c => slot-gpio.c} (53%)
- rename include/linux/mmc/{cd-gpio.h => slot-gpio.h} (68%)
-
-diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
-index dca4428..38ed210 100644
---- a/drivers/mmc/core/Makefile
-+++ b/drivers/mmc/core/Makefile
-@@ -7,6 +7,6 @@ mmc_core-y := core.o bus.o host.o \
- mmc.o mmc_ops.o sd.o sd_ops.o \
- sdio.o sdio_ops.o sdio_bus.o \
- sdio_cis.o sdio_io.o sdio_irq.o \
-- quirks.o cd-gpio.o
-+ quirks.o slot-gpio.o
-
- mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o
-diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/slot-gpio.c
-similarity index 53%
-rename from drivers/mmc/core/cd-gpio.c
-rename to drivers/mmc/core/slot-gpio.c
-index 8f5dc08..9796710 100644
---- a/drivers/mmc/core/cd-gpio.c
-+++ b/drivers/mmc/core/slot-gpio.c
-@@ -12,72 +12,72 @@
- #include <linux/gpio.h>
- #include <linux/interrupt.h>
- #include <linux/jiffies.h>
--#include <linux/mmc/cd-gpio.h>
- #include <linux/mmc/host.h>
-+#include <linux/mmc/slot-gpio.h>
- #include <linux/module.h>
- #include <linux/slab.h>
-
--struct mmc_cd_gpio {
-- unsigned int gpio;
-- char label[0];
-+struct mmc_gpio {
-+ unsigned int cd_gpio;
-+ char cd_label[0];
- };
-
--static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id)
-+static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
- {
- /* Schedule a card detection after a debounce timeout */
- mmc_detect_change(dev_id, msecs_to_jiffies(100));
- return IRQ_HANDLED;
- }
-
--int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio)
-+int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
- {
- size_t len = strlen(dev_name(host->parent)) + 4;
-- struct mmc_cd_gpio *cd;
-+ struct mmc_gpio *ctx;
- int irq = gpio_to_irq(gpio);
- int ret;
-
- if (irq < 0)
- return irq;
-
-- cd = kmalloc(sizeof(*cd) + len, GFP_KERNEL);
-- if (!cd)
-+ ctx = kmalloc(sizeof(*ctx) + len, GFP_KERNEL);
-+ if (!ctx)
- return -ENOMEM;
-
-- snprintf(cd->label, len, "%s cd", dev_name(host->parent));
-+ snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
-
-- ret = gpio_request_one(gpio, GPIOF_DIR_IN, cd->label);
-+ ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label);
- if (ret < 0)
- goto egpioreq;
-
-- ret = request_threaded_irq(irq, NULL, mmc_cd_gpio_irqt,
-- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
-- IRQF_ONESHOT, cd->label, host);
-+ ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt,
-+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-+ ctx->cd_label, host);
- if (ret < 0)
- goto eirqreq;
-
-- cd->gpio = gpio;
-+ ctx->cd_gpio = gpio;
- host->hotplug.irq = irq;
-- host->hotplug.handler_priv = cd;
-+ host->hotplug.handler_priv = ctx;
-
- return 0;
-
- eirqreq:
- gpio_free(gpio);
- egpioreq:
-- kfree(cd);
-+ kfree(ctx);
- return ret;
- }
--EXPORT_SYMBOL(mmc_cd_gpio_request);
-+EXPORT_SYMBOL(mmc_gpio_request_cd);
-
--void mmc_cd_gpio_free(struct mmc_host *host)
-+void mmc_gpio_free_cd(struct mmc_host *host)
- {
-- struct mmc_cd_gpio *cd = host->hotplug.handler_priv;
-+ struct mmc_gpio *ctx = host->hotplug.handler_priv;
-
-- if (!cd)
-+ if (!ctx)
- return;
-
- free_irq(host->hotplug.irq, host);
-- gpio_free(cd->gpio);
-- kfree(cd);
-+ gpio_free(ctx->cd_gpio);
-+ kfree(ctx);
- }
--EXPORT_SYMBOL(mmc_cd_gpio_free);
-+EXPORT_SYMBOL(mmc_gpio_free_cd);
-diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
-index 0ad3917..7ffc489 100644
---- a/drivers/mmc/host/tmio_mmc_pio.c
-+++ b/drivers/mmc/host/tmio_mmc_pio.c
-@@ -34,9 +34,9 @@
- #include <linux/io.h>
- #include <linux/irq.h>
- #include <linux/mfd/tmio.h>
--#include <linux/mmc/cd-gpio.h>
- #include <linux/mmc/host.h>
- #include <linux/mmc/mmc.h>
-+#include <linux/mmc/slot-gpio.h>
- #include <linux/mmc/tmio.h>
- #include <linux/module.h>
- #include <linux/pagemap.h>
-@@ -977,7 +977,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
- tmio_mmc_enable_mmc_irqs(_host, irq_mask);
-
- if (pdata->flags & TMIO_MMC_USE_GPIO_CD) {
-- ret = mmc_cd_gpio_request(mmc, pdata->cd_gpio);
-+ ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio);
- if (ret < 0) {
- tmio_mmc_host_remove(_host);
- return ret;
-@@ -1009,7 +1009,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
- * This means we can miss a card-eject, but this is anyway
- * possible, because of delayed processing of hotplug events.
- */
-- mmc_cd_gpio_free(mmc);
-+ mmc_gpio_free_cd(mmc);
-
- if (!host->native_hotplug)
- pm_runtime_get_sync(&pdev->dev);
-diff --git a/include/linux/mmc/cd-gpio.h b/include/linux/mmc/slot-gpio.h
-similarity index 68%
-rename from include/linux/mmc/cd-gpio.h
-rename to include/linux/mmc/slot-gpio.h
-index cefaba0..edfaa32 100644
---- a/include/linux/mmc/cd-gpio.h
-+++ b/include/linux/mmc/slot-gpio.h
-@@ -8,11 +8,11 @@
- * published by the Free Software Foundation.
- */
-
--#ifndef MMC_CD_GPIO_H
--#define MMC_CD_GPIO_H
-+#ifndef MMC_SLOT_GPIO_H
-+#define MMC_SLOT_GPIO_H
-
- struct mmc_host;
--int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio);
--void mmc_cd_gpio_free(struct mmc_host *host);
-+int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio);
-+void mmc_gpio_free_cd(struct mmc_host *host);
-
- #endif
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From b1c9b658ce7354835934388f45df16bfd25a37fc Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Tue, 12 Jun 2012 23:29:35 +0200
-Subject: mmc: tmio: Don't access hardware registers after stopping clocks
-
-The tmio_mmc_set_ios() function configures the MMC power, clock and bus
-width. When the mmc core requests the driver to power off the card, we
-inform runtime PM, that the controller can be suspended. This can lead
-to the MSTP clock being turned off.
-
-Writing to any 16-bit hardware registers with the MSTP clock off leads
-to timeouts and errors being printed to the kernel log. This can occur
-both when stopping the MMC clock and when configuring the bus width.
-
-To fix this, stop the MMC clock before calling put_runtime_pm(), and
-skip bus width configuration when power is off.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Tested-by: Simon Horman <horms@verge.net.au>
-Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit 6de707f200f73af7a58b58b3a5b956cff7b6e228)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/tmio_mmc_pio.c | 18 ++++++++++--------
- 1 file changed, 10 insertions(+), 8 deletions(-)
-
-diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
-index 7ffc489..4f26edf 100644
---- a/drivers/mmc/host/tmio_mmc_pio.c
-+++ b/drivers/mmc/host/tmio_mmc_pio.c
-@@ -811,19 +811,21 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
- if (host->set_pwr && ios->power_mode == MMC_POWER_OFF)
- host->set_pwr(host->pdev, 0);
- if (host->power) {
-+ tmio_mmc_clk_stop(host);
- host->power = false;
- pm_runtime_put(dev);
- }
-- tmio_mmc_clk_stop(host);
- }
-
-- switch (ios->bus_width) {
-- case MMC_BUS_WIDTH_1:
-- sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
-- break;
-- case MMC_BUS_WIDTH_4:
-- sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0);
-- break;
-+ if (host->power) {
-+ switch (ios->bus_width) {
-+ case MMC_BUS_WIDTH_1:
-+ sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
-+ break;
-+ case MMC_BUS_WIDTH_4:
-+ sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0);
-+ break;
-+ }
- }
-
- /* Let things settle. delay taken from winCE driver */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 13b6cca29fb687ec7821001eb9bc38ba8a6270a1 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 20 Jun 2012 19:10:30 +0200
-Subject: mmc: tmio: don't needlessly enable interrupts during probing
-
-We don't have to force-enable MMC interrupts in our .probe() method,
-mmc_add_host() will trigger card detection, that will enable all the
-necessary interrupts.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit e0337cc8b02fcb3f725746735db84d6d1b6b9196)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/tmio_mmc_pio.c | 21 +++++++++++----------
- 1 file changed, 11 insertions(+), 10 deletions(-)
-
-diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
-index 4f26edf..4318c1a 100644
---- a/drivers/mmc/host/tmio_mmc_pio.c
-+++ b/drivers/mmc/host/tmio_mmc_pio.c
-@@ -951,6 +951,17 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
-
- _host->sdcard_irq_mask = sd_ctrl_read32(_host, CTL_IRQ_MASK);
- tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL);
-+
-+ /* Unmask the IRQs we want to know about */
-+ if (!_host->chan_rx)
-+ irq_mask |= TMIO_MASK_READOP;
-+ if (!_host->chan_tx)
-+ irq_mask |= TMIO_MASK_WRITEOP;
-+ if (!_host->native_hotplug)
-+ irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT);
-+
-+ _host->sdcard_irq_mask &= ~irq_mask;
-+
- if (pdata->flags & TMIO_MMC_SDIO_IRQ)
- tmio_mmc_enable_sdio_irq(mmc, 0);
-
-@@ -968,16 +979,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
-
- dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
-
-- /* Unmask the IRQs we want to know about */
-- if (!_host->chan_rx)
-- irq_mask |= TMIO_MASK_READOP;
-- if (!_host->chan_tx)
-- irq_mask |= TMIO_MASK_WRITEOP;
-- if (!_host->native_hotplug)
-- irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT);
--
-- tmio_mmc_enable_mmc_irqs(_host, irq_mask);
--
- if (pdata->flags & TMIO_MMC_USE_GPIO_CD) {
- ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio);
- if (ret < 0) {
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 9000384872b9fb65e1fb9b7042da31d2d4023c7b Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 20 Jun 2012 19:10:32 +0200
-Subject: mmc: sdhi: implement tmio-mmc clock enable-update and disable
- callbacks
-
-Instead of delivering one static clock frequency value, read from the
-hardware during probing, enable the tmio-mmc driver to re-read the
-frequency dynamically.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit 56c492879318f43b1a7911675ff30fb0ede123b5)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/sh_mobile_sdhi.c | 24 +++++++++++++++++++++++-
- 1 file changed, 23 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
-index 934b68e..d8b167c 100644
---- a/drivers/mmc/host/sh_mobile_sdhi.c
-+++ b/drivers/mmc/host/sh_mobile_sdhi.c
-@@ -39,6 +39,27 @@ struct sh_mobile_sdhi {
- struct tmio_mmc_dma dma_priv;
- };
-
-+static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int *f)
-+{
-+ struct mmc_host *mmc = dev_get_drvdata(&pdev->dev);
-+ struct tmio_mmc_host *host = mmc_priv(mmc);
-+ struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
-+ int ret = clk_enable(priv->clk);
-+ if (ret < 0)
-+ return ret;
-+
-+ *f = clk_get_rate(priv->clk);
-+ return 0;
-+}
-+
-+static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev)
-+{
-+ struct mmc_host *mmc = dev_get_drvdata(&pdev->dev);
-+ struct tmio_mmc_host *host = mmc_priv(mmc);
-+ struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
-+ clk_disable(priv->clk);
-+}
-+
- static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state)
- {
- struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
-@@ -132,9 +153,10 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
- goto eclkget;
- }
-
-- mmc_data->hclk = clk_get_rate(priv->clk);
- mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
- mmc_data->get_cd = sh_mobile_sdhi_get_cd;
-+ mmc_data->clk_enable = sh_mobile_sdhi_clk_enable;
-+ mmc_data->clk_disable = sh_mobile_sdhi_clk_disable;
- mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
- if (p) {
- mmc_data->flags = p->tmio_flags;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2351d645d302b589c88ca21a2ea3198fd7bfa752 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 20 Jun 2012 19:10:31 +0200
-Subject: mmc: tmio: add callbacks to enable-update and disable the interface
- clock
-
-Every time the clock is enabled after possibly being disabled, we have
-to re-read its frequency and update our configuration.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit 8c102a964655b1a8df41b1f9e2355657471a45e3)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/tmio_mmc_pio.c | 35 ++++++++++++++++++++++++++++++++---
- include/linux/mfd/tmio.h | 3 +++
- 2 files changed, 35 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
-index 4318c1a..c6c0334 100644
---- a/drivers/mmc/host/tmio_mmc_pio.c
-+++ b/drivers/mmc/host/tmio_mmc_pio.c
-@@ -752,6 +752,22 @@ fail:
- mmc_request_done(mmc, mrq);
- }
-
-+static int tmio_mmc_clk_update(struct mmc_host *mmc)
-+{
-+ struct tmio_mmc_host *host = mmc_priv(mmc);
-+ struct tmio_mmc_data *pdata = host->pdata;
-+ int ret;
-+
-+ if (!pdata->clk_enable)
-+ return -ENOTSUPP;
-+
-+ ret = pdata->clk_enable(host->pdev, &mmc->f_max);
-+ if (!ret)
-+ mmc->f_min = mmc->f_max / 512;
-+
-+ return ret;
-+}
-+
- /* Set MMC clock / power.
- * Note: This controller uses a simple divider scheme therefore it cannot
- * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
-@@ -798,6 +814,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
- */
- if (ios->power_mode == MMC_POWER_ON && ios->clock) {
- if (!host->power) {
-+ tmio_mmc_clk_update(mmc);
- pm_runtime_get_sync(dev);
- host->power = true;
- }
-@@ -811,9 +828,12 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
- if (host->set_pwr && ios->power_mode == MMC_POWER_OFF)
- host->set_pwr(host->pdev, 0);
- if (host->power) {
-+ struct tmio_mmc_data *pdata = host->pdata;
- tmio_mmc_clk_stop(host);
- host->power = false;
- pm_runtime_put(dev);
-+ if (pdata->clk_disable)
-+ pdata->clk_disable(host->pdev);
- }
- }
-
-@@ -907,8 +927,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
-
- mmc->ops = &tmio_mmc_ops;
- mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities;
-- mmc->f_max = pdata->hclk;
-- mmc->f_min = mmc->f_max / 512;
- mmc->max_segs = 32;
- mmc->max_blk_size = 512;
- mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) *
-@@ -930,6 +948,11 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
- if (ret < 0)
- goto pm_disable;
-
-+ if (tmio_mmc_clk_update(mmc) < 0) {
-+ mmc->f_max = pdata->hclk;
-+ mmc->f_min = mmc->f_max / 512;
-+ }
-+
- /*
- * There are 4 different scenarios for the card detection:
- * 1) an external gpio irq handles the cd (best for power savings)
-@@ -975,7 +998,13 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
- /* See if we also get DMA */
- tmio_mmc_request_dma(_host, pdata);
-
-- mmc_add_host(mmc);
-+ ret = mmc_add_host(mmc);
-+ if (pdata->clk_disable)
-+ pdata->clk_disable(pdev);
-+ if (ret < 0) {
-+ tmio_mmc_host_remove(_host);
-+ return ret;
-+ }
-
- dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
-
-diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
-index f5171db..b332c4c 100644
---- a/include/linux/mfd/tmio.h
-+++ b/include/linux/mfd/tmio.h
-@@ -110,6 +110,9 @@ struct tmio_mmc_data {
- void (*set_clk_div)(struct platform_device *host, int state);
- int (*get_cd)(struct platform_device *host);
- int (*write16_hook)(struct tmio_mmc_host *host, int addr);
-+ /* clock management callbacks */
-+ int (*clk_enable)(struct platform_device *pdev, unsigned int *f);
-+ void (*clk_disable)(struct platform_device *pdev);
- };
-
- /*
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 399a8f308acebcabaa5c10f336668cd3f73ac273 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 20 Jun 2012 19:10:34 +0200
-Subject: mmc: sdhi: do not install dummy callbacks
-
-Currently the SDHI glue for the TMIO MMC driver installs dummy .get_cd() and
-.set_pwr() callbacks even if the platform didn't supply them. This is not
-necessary, since the TMIO MMC driver itself checks for NULL callbacks. This
-is also dubious if the platform provides a regulator for SD-card power
-switching. It is better to only install those callbacks, if they are really
-provided by the platform.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit 71da63e767c393c0ebbd3c65df428df0ce42a16c)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/sh_mobile_sdhi.c | 14 ++++++--------
- 1 file changed, 6 insertions(+), 8 deletions(-)
-
-diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
-index d8b167c..42f07fa 100644
---- a/drivers/mmc/host/sh_mobile_sdhi.c
-+++ b/drivers/mmc/host/sh_mobile_sdhi.c
-@@ -64,18 +64,14 @@ static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state)
- {
- struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
-
-- if (p && p->set_pwr)
-- p->set_pwr(pdev, state);
-+ p->set_pwr(pdev, state);
- }
-
- static int sh_mobile_sdhi_get_cd(struct platform_device *pdev)
- {
- struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
-
-- if (p && p->get_cd)
-- return p->get_cd(pdev);
-- else
-- return -ENOSYS;
-+ return p->get_cd(pdev);
- }
-
- static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
-@@ -153,8 +149,10 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
- goto eclkget;
- }
-
-- mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
-- mmc_data->get_cd = sh_mobile_sdhi_get_cd;
-+ if (p->set_pwr)
-+ mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
-+ if (p->get_cd)
-+ mmc_data->get_cd = sh_mobile_sdhi_get_cd;
- mmc_data->clk_enable = sh_mobile_sdhi_clk_enable;
- mmc_data->clk_disable = sh_mobile_sdhi_clk_disable;
- mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 23b39f743c1d33128add46201409eb6709b10a4f Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 20 Jun 2012 02:28:43 -0400
-Subject: mmc: add a function to get regulators, supplying card's power
-
-Add a function to get regulators, supplying card's Vdd and Vccq on a
-specific host. If a Vdd supplying regulator is found, the function checks,
-whether a valid OCR mask can be obtained from it. The Vccq regulator is
-optional. A failure to get it is not fatal.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Reviwed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit e137788dd115dd9d21759a768dba5fff9685e587)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/core/core.c | 23 +++++++++++++++++++++++
- include/linux/mmc/host.h | 16 ++++++++++++++--
- 2 files changed, 37 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
-index ba821fe..1db77e7 100644
---- a/drivers/mmc/core/core.c
-+++ b/drivers/mmc/core/core.c
-@@ -1012,6 +1012,29 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
- }
- EXPORT_SYMBOL(mmc_regulator_set_ocr);
-
-+int mmc_regulator_get_supply(struct mmc_host *mmc)
-+{
-+ struct device *dev = mmc_dev(mmc);
-+ struct regulator *supply;
-+ int ret;
-+
-+ supply = devm_regulator_get(dev, "vmmc");
-+ mmc->supply.vmmc = supply;
-+ mmc->supply.vqmmc = devm_regulator_get(dev, "vqmmc");
-+
-+ if (IS_ERR(supply))
-+ return PTR_ERR(supply);
-+
-+ ret = mmc_regulator_get_ocrmask(supply);
-+ if (ret > 0)
-+ mmc->ocr_avail = ret;
-+ else
-+ dev_warn(mmc_dev(mmc), "Failed getting OCR mask: %d\n", ret);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(mmc_regulator_get_supply);
-+
- #endif /* CONFIG_REGULATOR */
-
- /*
-diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
-index 0707d22..9deb725 100644
---- a/include/linux/mmc/host.h
-+++ b/include/linux/mmc/host.h
-@@ -155,6 +155,13 @@ struct mmc_hotplug {
- void *handler_priv;
- };
-
-+struct regulator;
-+
-+struct mmc_supply {
-+ struct regulator *vmmc; /* Card power supply */
-+ struct regulator *vqmmc; /* Optional Vccq supply */
-+};
-+
- struct mmc_host {
- struct device *parent;
- struct device class_dev;
-@@ -309,6 +316,7 @@ struct mmc_host {
- #ifdef CONFIG_REGULATOR
- bool regulator_enabled; /* regulator state */
- #endif
-+ struct mmc_supply supply;
-
- struct dentry *debugfs_root;
-
-@@ -357,13 +365,12 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)
- wake_up_process(host->sdio_irq_thread);
- }
-
--struct regulator;
--
- #ifdef CONFIG_REGULATOR
- int mmc_regulator_get_ocrmask(struct regulator *supply);
- int mmc_regulator_set_ocr(struct mmc_host *mmc,
- struct regulator *supply,
- unsigned short vdd_bit);
-+int mmc_regulator_get_supply(struct mmc_host *mmc);
- #else
- static inline int mmc_regulator_get_ocrmask(struct regulator *supply)
- {
-@@ -376,6 +383,11 @@ static inline int mmc_regulator_set_ocr(struct mmc_host *mmc,
- {
- return 0;
- }
-+
-+static inline int mmc_regulator_get_supply(struct mmc_host *mmc)
-+{
-+ return 0;
-+}
- #endif
-
- int mmc_card_awake(struct mmc_host *host);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2f82c1eaa54c5b6eb2d1bc04cd04add57ca9ad05 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 20 Jun 2012 19:10:33 +0200
-Subject: mmc: tmio: add regulator support
-
-Currently the TMIO MMC driver derives the OCR mask from the platform data
-and uses a platform callback to turn card power on and off. This patch adds
-regulator support to the driver.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Cc: Liam Girdwood <lrg@ti.com>
-Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit b958a67c6bbe0a886bebc618aac7a059cdbab418)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/tmio_mmc_pio.c | 37 +++++++++++++++++++++++++++++--------
- 1 file changed, 29 insertions(+), 8 deletions(-)
-
-diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
-index c6c0334..b5c32b4 100644
---- a/drivers/mmc/host/tmio_mmc_pio.c
-+++ b/drivers/mmc/host/tmio_mmc_pio.c
-@@ -768,6 +768,18 @@ static int tmio_mmc_clk_update(struct mmc_host *mmc)
- return ret;
- }
-
-+static void tmio_mmc_set_power(struct tmio_mmc_host *host, struct mmc_ios *ios)
-+{
-+ struct mmc_host *mmc = host->mmc;
-+
-+ if (host->set_pwr)
-+ host->set_pwr(host->pdev, ios->power_mode != MMC_POWER_OFF);
-+ if (!IS_ERR(mmc->supply.vmmc))
-+ /* Errors ignored... */
-+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
-+ ios->power_mode ? ios->vdd : 0);
-+}
-+
- /* Set MMC clock / power.
- * Note: This controller uses a simple divider scheme therefore it cannot
- * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
-@@ -820,13 +832,12 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
- }
- tmio_mmc_set_clock(host, ios->clock);
- /* power up SD bus */
-- if (host->set_pwr)
-- host->set_pwr(host->pdev, 1);
-+ tmio_mmc_set_power(host, ios);
- /* start bus clock */
- tmio_mmc_clk_start(host);
- } else if (ios->power_mode != MMC_POWER_UP) {
-- if (host->set_pwr && ios->power_mode == MMC_POWER_OFF)
-- host->set_pwr(host->pdev, 0);
-+ if (ios->power_mode == MMC_POWER_OFF)
-+ tmio_mmc_set_power(host, ios);
- if (host->power) {
- struct tmio_mmc_data *pdata = host->pdata;
- tmio_mmc_clk_stop(host);
-@@ -888,6 +899,19 @@ static const struct mmc_host_ops tmio_mmc_ops = {
- .enable_sdio_irq = tmio_mmc_enable_sdio_irq,
- };
-
-+static void tmio_mmc_init_ocr(struct tmio_mmc_host *host)
-+{
-+ struct tmio_mmc_data *pdata = host->pdata;
-+ struct mmc_host *mmc = host->mmc;
-+
-+ mmc_regulator_get_supply(mmc);
-+
-+ if (!mmc->ocr_avail)
-+ mmc->ocr_avail = pdata->ocr_mask ? : MMC_VDD_32_33 | MMC_VDD_33_34;
-+ else if (pdata->ocr_mask)
-+ dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
-+}
-+
- int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
- struct platform_device *pdev,
- struct tmio_mmc_data *pdata)
-@@ -933,10 +957,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
- mmc->max_segs;
- mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
- mmc->max_seg_size = mmc->max_req_size;
-- if (pdata->ocr_mask)
-- mmc->ocr_avail = pdata->ocr_mask;
-- else
-- mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-+ tmio_mmc_init_ocr(_host);
-
- _host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD ||
- mmc->caps & MMC_CAP_NEEDS_POLL ||
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From edc14a6a575b9ed664f5618b40bb720801514acc Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 20 Jun 2012 19:10:36 +0200
-Subject: mmc: tmio: remove a duplicated comment line
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit 944640d0fffb2ee2961a24c3747b1fc87c4157a8)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/tmio_mmc_pio.c | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
-index b5c32b4..b204012f 100644
---- a/drivers/mmc/host/tmio_mmc_pio.c
-+++ b/drivers/mmc/host/tmio_mmc_pio.c
-@@ -984,7 +984,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
- * While we increment the runtime PM counter for all scenarios when
- * the mmc core activates us by calling an appropriate set_ios(), we
- * must additionally ensure that in case 2) the tmio mmc hardware stays
-- * additionally ensure that in case 2) the tmio mmc hardware stays
- * powered on during runtime for the card detection to work.
- */
- if (_host->native_hotplug)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 84ff72e8bc8a05f00821fa782bda46ba105ce831 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 23 May 2012 10:44:37 +0200
-Subject: mmc: tmio: support caps2 flags
-
-Allow tmio mmc glue drivers to pass mmc_host::caps2 flags down to
-the mmc layer.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit 02cb3221d5bb351ad9f7469453dcca7594a0fabf)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/tmio_mmc_pio.c | 1 +
- include/linux/mfd/tmio.h | 1 +
- 2 files changed, 2 insertions(+)
-
-diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
-index b204012f..f8df021 100644
---- a/drivers/mmc/host/tmio_mmc_pio.c
-+++ b/drivers/mmc/host/tmio_mmc_pio.c
-@@ -951,6 +951,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
-
- mmc->ops = &tmio_mmc_ops;
- mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities;
-+ mmc->caps2 = pdata->capabilities2;
- mmc->max_segs = 32;
- mmc->max_blk_size = 512;
- mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) *
-diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
-index b332c4c..d83af39 100644
---- a/include/linux/mfd/tmio.h
-+++ b/include/linux/mfd/tmio.h
-@@ -101,6 +101,7 @@ struct tmio_mmc_host;
- struct tmio_mmc_data {
- unsigned int hclk;
- unsigned long capabilities;
-+ unsigned long capabilities2;
- unsigned long flags;
- u32 ocr_mask; /* available voltages */
- struct tmio_mmc_dma *dma;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ab7669dbefddb9148fbda646fe4746a1a33f914f Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 23 May 2012 11:05:33 +0200
-Subject: mmc: sh_mobile_sdhi: support caps2 flags
-
-Let SDHI platforms specify mmc_host::caps2 flags in their platform data.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit d7d8d500bc03891c4a86da49858c46e2db256581)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/sh_mobile_sdhi.c | 1 +
- include/linux/mmc/sh_mobile_sdhi.h | 1 +
- 2 files changed, 2 insertions(+)
-
-diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
-index 42f07fa..1e7c5c4 100644
---- a/drivers/mmc/host/sh_mobile_sdhi.c
-+++ b/drivers/mmc/host/sh_mobile_sdhi.c
-@@ -162,6 +162,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
- mmc_data->write16_hook = sh_mobile_sdhi_write16_hook;
- mmc_data->ocr_mask = p->tmio_ocr_mask;
- mmc_data->capabilities |= p->tmio_caps;
-+ mmc_data->capabilities2 |= p->tmio_caps2;
- mmc_data->cd_gpio = p->cd_gpio;
-
- if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
-diff --git a/include/linux/mmc/sh_mobile_sdhi.h b/include/linux/mmc/sh_mobile_sdhi.h
-index e94e620..b65679f 100644
---- a/include/linux/mmc/sh_mobile_sdhi.h
-+++ b/include/linux/mmc/sh_mobile_sdhi.h
-@@ -23,6 +23,7 @@ struct sh_mobile_sdhi_info {
- int dma_slave_rx;
- unsigned long tmio_flags;
- unsigned long tmio_caps;
-+ unsigned long tmio_caps2;
- u32 tmio_ocr_mask; /* available MMC voltages */
- unsigned int cd_gpio;
- struct tmio_mmc_data *pdata;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a19323115f3cf3e2e7f0b56ce75752ed2e682bfb Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Tue, 1 May 2012 18:03:43 +0200
-Subject: mmc: sdhi: add OF support, make platform data optional
-
-Add primitive support for OF to the SDHI TMIO glue, which also makes it
-necessary to be able to run without platform data.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit c7bb4487a3474c03986758595fcae1cfb771b3b0)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/sh_mobile_sdhi.c | 35 +++++++++++++++++++++++------------
- 1 file changed, 23 insertions(+), 12 deletions(-)
-
-diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
-index 1e7c5c4..a842939 100644
---- a/drivers/mmc/host/sh_mobile_sdhi.c
-+++ b/drivers/mmc/host/sh_mobile_sdhi.c
-@@ -21,6 +21,7 @@
- #include <linux/kernel.h>
- #include <linux/clk.h>
- #include <linux/slab.h>
-+#include <linux/mod_devicetable.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/mmc/host.h>
-@@ -133,12 +134,14 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
- }
-
- mmc_data = &priv->mmc_data;
-- p->pdata = mmc_data;
-
-- if (p->init) {
-- ret = p->init(pdev, &sdhi_ops);
-- if (ret)
-- goto einit;
-+ if (p) {
-+ p->pdata = mmc_data;
-+ if (p->init) {
-+ ret = p->init(pdev, &sdhi_ops);
-+ if (ret)
-+ goto einit;
-+ }
- }
-
- snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id);
-@@ -149,10 +152,6 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
- goto eclkget;
- }
-
-- if (p->set_pwr)
-- mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
-- if (p->get_cd)
-- mmc_data->get_cd = sh_mobile_sdhi_get_cd;
- mmc_data->clk_enable = sh_mobile_sdhi_clk_enable;
- mmc_data->clk_disable = sh_mobile_sdhi_clk_disable;
- mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
-@@ -164,6 +163,10 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
- mmc_data->capabilities |= p->tmio_caps;
- mmc_data->capabilities2 |= p->tmio_caps2;
- mmc_data->cd_gpio = p->cd_gpio;
-+ if (p->set_pwr)
-+ mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
-+ if (p->get_cd)
-+ mmc_data->get_cd = sh_mobile_sdhi_get_cd;
-
- if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
- priv->param_tx.slave_id = p->dma_slave_tx;
-@@ -269,7 +272,7 @@ eirq_card_detect:
- eprobe:
- clk_put(priv->clk);
- eclkget:
-- if (p->cleanup)
-+ if (p && p->cleanup)
- p->cleanup(pdev);
- einit:
- kfree(priv);
-@@ -284,7 +287,8 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
- struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
- int i = 0, irq;
-
-- p->pdata = NULL;
-+ if (p)
-+ p->pdata = NULL;
-
- tmio_mmc_host_remove(host);
-
-@@ -297,7 +301,7 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
-
- clk_put(priv->clk);
-
-- if (p->cleanup)
-+ if (p && p->cleanup)
- p->cleanup(pdev);
-
- kfree(priv);
-@@ -312,11 +316,18 @@ static const struct dev_pm_ops tmio_mmc_dev_pm_ops = {
- .runtime_resume = tmio_mmc_host_runtime_resume,
- };
-
-+static const struct of_device_id sh_mobile_sdhi_of_match[] = {
-+ { .compatible = "renesas,shmobile-sdhi" },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match);
-+
- static struct platform_driver sh_mobile_sdhi_driver = {
- .driver = {
- .name = "sh_mobile_sdhi",
- .owner = THIS_MODULE,
- .pm = &tmio_mmc_dev_pm_ops,
-+ .of_match_table = sh_mobile_sdhi_of_match,
- },
- .probe = sh_mobile_sdhi_probe,
- .remove = __devexit_p(sh_mobile_sdhi_remove),
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 3383b414d84936e9695df242dbe081140e7b0fbd Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Tue, 1 May 2012 15:40:15 +0200
-Subject: mmc: core: use a more generic name for slot function types and fields
-
-struct mmc_host::hotplug is becoming a generic hook for slot functions.
-Rename it accordingly.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit 27410ee7e391ce650d6d0242805f080599be7ad7)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/core/host.c | 2 ++
- drivers/mmc/core/slot-gpio.c | 8 ++++----
- include/linux/mmc/host.h | 17 ++++++++++++++---
- 3 files changed, 20 insertions(+), 7 deletions(-)
-
-diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
-index 91c84c7..b8c5290 100644
---- a/drivers/mmc/core/host.c
-+++ b/drivers/mmc/core/host.c
-@@ -327,6 +327,8 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
-
- mmc_host_clk_init(host);
-
-+ host->slot.cd_irq = -EINVAL;
-+
- spin_lock_init(&host->lock);
- init_waitqueue_head(&host->wq);
- INIT_DELAYED_WORK(&host->detect, mmc_rescan);
-diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
-index 9796710..468e5a0 100644
---- a/drivers/mmc/core/slot-gpio.c
-+++ b/drivers/mmc/core/slot-gpio.c
-@@ -56,8 +56,8 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
- goto eirqreq;
-
- ctx->cd_gpio = gpio;
-- host->hotplug.irq = irq;
-- host->hotplug.handler_priv = ctx;
-+ host->slot.cd_irq = irq;
-+ host->slot.handler_priv = ctx;
-
- return 0;
-
-@@ -71,12 +71,12 @@ EXPORT_SYMBOL(mmc_gpio_request_cd);
-
- void mmc_gpio_free_cd(struct mmc_host *host)
- {
-- struct mmc_gpio *ctx = host->hotplug.handler_priv;
-+ struct mmc_gpio *ctx = host->slot.handler_priv;
-
- if (!ctx)
- return;
-
-- free_irq(host->hotplug.irq, host);
-+ free_irq(host->slot.cd_irq, host);
- gpio_free(ctx->cd_gpio);
- kfree(ctx);
- }
-diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
-index 9deb725..90b6a38 100644
---- a/include/linux/mmc/host.h
-+++ b/include/linux/mmc/host.h
-@@ -150,8 +150,19 @@ struct mmc_async_req {
- int (*err_check) (struct mmc_card *, struct mmc_async_req *);
- };
-
--struct mmc_hotplug {
-- unsigned int irq;
-+/**
-+ * struct mmc_slot - MMC slot functions
-+ *
-+ * @cd_irq: MMC/SD-card slot hotplug detection IRQ or -EINVAL
-+ * @handler_priv: MMC/SD-card slot context
-+ *
-+ * Some MMC/SD host controllers implement slot-functions like card and
-+ * write-protect detection natively. However, a large number of controllers
-+ * leave these functions to the CPU. This struct provides a hook to attach
-+ * such slot-function drivers.
-+ */
-+struct mmc_slot {
-+ int cd_irq;
- void *handler_priv;
- };
-
-@@ -297,7 +308,7 @@ struct mmc_host {
-
- struct delayed_work detect;
- int detect_change; /* card detect flag */
-- struct mmc_hotplug hotplug;
-+ struct mmc_slot slot;
-
- const struct mmc_bus_ops *bus_ops; /* current bus driver */
- unsigned int bus_refs; /* reference counter */
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From ecce3df848ddf973eae9260a50fdd16cbb860f3f Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Tue, 1 May 2012 15:49:52 +0200
-Subject: mmc: add two capability flags for CD and WP signal polarity
-
-To handle CD and WP SD/MMC slot pins we need generic flags to specify their
-polarity.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit 5c08d7fae0815cd163a98e05c8d94fc0de77ff67)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- include/linux/mmc/host.h | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
-index 90b6a38..c1a03ee 100644
---- a/include/linux/mmc/host.h
-+++ b/include/linux/mmc/host.h
-@@ -256,6 +256,8 @@ struct mmc_host {
- #define MMC_CAP2_BROKEN_VOLTAGE (1 << 7) /* Use the broken voltage */
- #define MMC_CAP2_DETECT_ON_ERR (1 << 8) /* On I/O err check card removal */
- #define MMC_CAP2_HC_ERASE_SZ (1 << 9) /* High-capacity erase size */
-+#define MMC_CAP2_CD_ACTIVE_HIGH (1 << 10) /* Card-detect signal active high */
-+#define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */
-
- mmc_pm_flag_t pm_caps; /* supported pm features */
- unsigned int power_notify_type;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 2d3824e27d90f5cd81a034798596e8d6963c2b1f Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Tue, 1 May 2012 16:27:25 +0200
-Subject: mmc: add CD GPIO polling support to slot functions
-
-A simple extension of mmc slot functions add support for CD GPIO polling
-for cases where the GPIO cannot produce interrupts, or where this is not
-desired for some reason.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit befe4048d8d20483a62636e20f3dbffebf85a1c1)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/core/slot-gpio.c | 56 +++++++++++++++++++++++++++++++++----------
- include/linux/mmc/slot-gpio.h | 2 ++
- 2 files changed, 45 insertions(+), 13 deletions(-)
-
-diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
-index 468e5a0..92cba02 100644
---- a/drivers/mmc/core/slot-gpio.c
-+++ b/drivers/mmc/core/slot-gpio.c
-@@ -18,7 +18,7 @@
- #include <linux/slab.h>
-
- struct mmc_gpio {
-- unsigned int cd_gpio;
-+ int cd_gpio;
- char cd_label[0];
- };
-
-@@ -29,6 +29,18 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
- return IRQ_HANDLED;
- }
-
-+int mmc_gpio_get_cd(struct mmc_host *host)
-+{
-+ struct mmc_gpio *ctx = host->slot.handler_priv;
-+
-+ if (!ctx || !gpio_is_valid(ctx->cd_gpio))
-+ return -ENOSYS;
-+
-+ return !gpio_get_value_cansleep(ctx->cd_gpio) ^
-+ !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
-+}
-+EXPORT_SYMBOL(mmc_gpio_get_cd);
-+
- int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
- {
- size_t len = strlen(dev_name(host->parent)) + 4;
-@@ -36,9 +48,6 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
- int irq = gpio_to_irq(gpio);
- int ret;
-
-- if (irq < 0)
-- return irq;
--
- ctx = kmalloc(sizeof(*ctx) + len, GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
-@@ -49,20 +58,32 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
- if (ret < 0)
- goto egpioreq;
-
-- ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt,
-+ /*
-+ * Even if gpio_to_irq() returns a valid IRQ number, the platform might
-+ * still prefer to poll, e.g., because that IRQ number is already used
-+ * by another unit and cannot be shared.
-+ */
-+ if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL)
-+ irq = -EINVAL;
-+
-+ if (irq >= 0) {
-+ ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- ctx->cd_label, host);
-- if (ret < 0)
-- goto eirqreq;
-+ if (ret < 0)
-+ irq = ret;
-+ }
-
-- ctx->cd_gpio = gpio;
- host->slot.cd_irq = irq;
-+
-+ if (irq < 0)
-+ host->caps |= MMC_CAP_NEEDS_POLL;
-+
-+ ctx->cd_gpio = gpio;
- host->slot.handler_priv = ctx;
-
- return 0;
-
--eirqreq:
-- gpio_free(gpio);
- egpioreq:
- kfree(ctx);
- return ret;
-@@ -72,12 +93,21 @@ EXPORT_SYMBOL(mmc_gpio_request_cd);
- void mmc_gpio_free_cd(struct mmc_host *host)
- {
- struct mmc_gpio *ctx = host->slot.handler_priv;
-+ int gpio;
-
-- if (!ctx)
-+ if (!ctx || !gpio_is_valid(ctx->cd_gpio))
- return;
-
-- free_irq(host->slot.cd_irq, host);
-- gpio_free(ctx->cd_gpio);
-+ if (host->slot.cd_irq >= 0) {
-+ free_irq(host->slot.cd_irq, host);
-+ host->slot.cd_irq = -EINVAL;
-+ }
-+
-+ gpio = ctx->cd_gpio;
-+ ctx->cd_gpio = -EINVAL;
-+
-+ gpio_free(gpio);
-+ host->slot.handler_priv = NULL;
- kfree(ctx);
- }
- EXPORT_SYMBOL(mmc_gpio_free_cd);
-diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h
-index edfaa32..1a977d7 100644
---- a/include/linux/mmc/slot-gpio.h
-+++ b/include/linux/mmc/slot-gpio.h
-@@ -12,6 +12,8 @@
- #define MMC_SLOT_GPIO_H
-
- struct mmc_host;
-+
-+int mmc_gpio_get_cd(struct mmc_host *host);
- int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio);
- void mmc_gpio_free_cd(struct mmc_host *host);
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 1acb00ed4e37416f9e71be4588be8fab3e03d1ee Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Tue, 1 May 2012 16:51:38 +0200
-Subject: mmc: core: convert slot functions to managed allocation
-
-This prepares for the addition of further slot functions.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit a7d1a1ebd8f5858a812ac3d5fbbc178b4959a63b)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/core/host.c | 2 ++
- drivers/mmc/core/slot-gpio.c | 51 +++++++++++++++++++++++++++++++++-----------
- include/linux/mmc/host.h | 3 +++
- 3 files changed, 43 insertions(+), 13 deletions(-)
-
-diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
-index b8c5290..74cf29a 100644
---- a/drivers/mmc/core/host.c
-+++ b/drivers/mmc/core/host.c
-@@ -32,6 +32,7 @@
- static void mmc_host_classdev_release(struct device *dev)
- {
- struct mmc_host *host = cls_dev_to_mmc_host(dev);
-+ mutex_destroy(&host->slot.lock);
- kfree(host);
- }
-
-@@ -327,6 +328,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
-
- mmc_host_clk_init(host);
-
-+ mutex_init(&host->slot.lock);
- host->slot.cd_irq = -EINVAL;
-
- spin_lock_init(&host->lock);
-diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
-index 92cba02..41689da 100644
---- a/drivers/mmc/core/slot-gpio.c
-+++ b/drivers/mmc/core/slot-gpio.c
-@@ -29,6 +29,34 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
- return IRQ_HANDLED;
- }
-
-+static int mmc_gpio_alloc(struct mmc_host *host)
-+{
-+ size_t len = strlen(dev_name(host->parent)) + 4;
-+ struct mmc_gpio *ctx;
-+
-+ mutex_lock(&host->slot.lock);
-+
-+ ctx = host->slot.handler_priv;
-+ if (!ctx) {
-+ /*
-+ * devm_kzalloc() can be called after device_initialize(), even
-+ * before device_add(), i.e., between mmc_alloc_host() and
-+ * mmc_add_host()
-+ */
-+ ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + len,
-+ GFP_KERNEL);
-+ if (ctx) {
-+ snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
-+ ctx->cd_gpio = -EINVAL;
-+ host->slot.handler_priv = ctx;
-+ }
-+ }
-+
-+ mutex_unlock(&host->slot.lock);
-+
-+ return ctx ? 0 : -ENOMEM;
-+}
-+
- int mmc_gpio_get_cd(struct mmc_host *host)
- {
- struct mmc_gpio *ctx = host->slot.handler_priv;
-@@ -43,20 +71,24 @@ EXPORT_SYMBOL(mmc_gpio_get_cd);
-
- int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
- {
-- size_t len = strlen(dev_name(host->parent)) + 4;
- struct mmc_gpio *ctx;
- int irq = gpio_to_irq(gpio);
- int ret;
-
-- ctx = kmalloc(sizeof(*ctx) + len, GFP_KERNEL);
-- if (!ctx)
-- return -ENOMEM;
-+ ret = mmc_gpio_alloc(host);
-+ if (ret < 0)
-+ return ret;
-
-- snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
-+ ctx = host->slot.handler_priv;
-
- ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label);
- if (ret < 0)
-- goto egpioreq;
-+ /*
-+ * don't bother freeing memory. It might still get used by other
-+ * slot functions, in any case it will be freed, when the device
-+ * is destroyed.
-+ */
-+ return ret;
-
- /*
- * Even if gpio_to_irq() returns a valid IRQ number, the platform might
-@@ -80,13 +112,8 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
- host->caps |= MMC_CAP_NEEDS_POLL;
-
- ctx->cd_gpio = gpio;
-- host->slot.handler_priv = ctx;
-
- return 0;
--
--egpioreq:
-- kfree(ctx);
-- return ret;
- }
- EXPORT_SYMBOL(mmc_gpio_request_cd);
-
-@@ -107,7 +134,5 @@ void mmc_gpio_free_cd(struct mmc_host *host)
- ctx->cd_gpio = -EINVAL;
-
- gpio_free(gpio);
-- host->slot.handler_priv = NULL;
-- kfree(ctx);
- }
- EXPORT_SYMBOL(mmc_gpio_free_cd);
-diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
-index c1a03ee..65c64ee 100644
---- a/include/linux/mmc/host.h
-+++ b/include/linux/mmc/host.h
-@@ -11,6 +11,7 @@
- #define LINUX_MMC_HOST_H
-
- #include <linux/leds.h>
-+#include <linux/mutex.h>
- #include <linux/sched.h>
- #include <linux/device.h>
- #include <linux/fault-inject.h>
-@@ -154,6 +155,7 @@ struct mmc_async_req {
- * struct mmc_slot - MMC slot functions
- *
- * @cd_irq: MMC/SD-card slot hotplug detection IRQ or -EINVAL
-+ * @lock: protect the @handler_priv pointer
- * @handler_priv: MMC/SD-card slot context
- *
- * Some MMC/SD host controllers implement slot-functions like card and
-@@ -163,6 +165,7 @@ struct mmc_async_req {
- */
- struct mmc_slot {
- int cd_irq;
-+ struct mutex lock;
- void *handler_priv;
- };
-
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e26593f54711c1135d3d1fd0994224e9dba0dee2 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Tue, 1 May 2012 16:59:38 +0200
-Subject: mmc: core: add WP pin handler to slot functions
-
-Card Write-Protect pin is often implemented, using a GPIO, which makes
-it simple to provide a generic handler for it.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit 5aa7dad305594ea30d21e23b3036565042adf50c)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/core/slot-gpio.c | 52 ++++++++++++++++++++++++++++++++++++++++++-
- include/linux/mmc/slot-gpio.h | 4 ++++
- 2 files changed, 55 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
-index 41689da..0582429 100644
---- a/drivers/mmc/core/slot-gpio.c
-+++ b/drivers/mmc/core/slot-gpio.c
-@@ -18,7 +18,9 @@
- #include <linux/slab.h>
-
- struct mmc_gpio {
-+ int ro_gpio;
- int cd_gpio;
-+ char *ro_label;
- char cd_label[0];
- };
-
-@@ -43,11 +45,14 @@ static int mmc_gpio_alloc(struct mmc_host *host)
- * before device_add(), i.e., between mmc_alloc_host() and
- * mmc_add_host()
- */
-- ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + len,
-+ ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + 2 * len,
- GFP_KERNEL);
- if (ctx) {
-+ ctx->ro_label = ctx->cd_label + len;
- snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
-+ snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent));
- ctx->cd_gpio = -EINVAL;
-+ ctx->ro_gpio = -EINVAL;
- host->slot.handler_priv = ctx;
- }
- }
-@@ -57,6 +62,18 @@ static int mmc_gpio_alloc(struct mmc_host *host)
- return ctx ? 0 : -ENOMEM;
- }
-
-+int mmc_gpio_get_ro(struct mmc_host *host)
-+{
-+ struct mmc_gpio *ctx = host->slot.handler_priv;
-+
-+ if (!ctx || !gpio_is_valid(ctx->ro_gpio))
-+ return -ENOSYS;
-+
-+ return !gpio_get_value_cansleep(ctx->ro_gpio) ^
-+ !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
-+}
-+EXPORT_SYMBOL(mmc_gpio_get_ro);
-+
- int mmc_gpio_get_cd(struct mmc_host *host)
- {
- struct mmc_gpio *ctx = host->slot.handler_priv;
-@@ -69,6 +86,24 @@ int mmc_gpio_get_cd(struct mmc_host *host)
- }
- EXPORT_SYMBOL(mmc_gpio_get_cd);
-
-+int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio)
-+{
-+ struct mmc_gpio *ctx;
-+ int ret;
-+
-+ if (!gpio_is_valid(gpio))
-+ return -EINVAL;
-+
-+ ret = mmc_gpio_alloc(host);
-+ if (ret < 0)
-+ return ret;
-+
-+ ctx = host->slot.handler_priv;
-+
-+ return gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label);
-+}
-+EXPORT_SYMBOL(mmc_gpio_request_ro);
-+
- int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
- {
- struct mmc_gpio *ctx;
-@@ -117,6 +152,21 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
- }
- EXPORT_SYMBOL(mmc_gpio_request_cd);
-
-+void mmc_gpio_free_ro(struct mmc_host *host)
-+{
-+ struct mmc_gpio *ctx = host->slot.handler_priv;
-+ int gpio;
-+
-+ if (!ctx || !gpio_is_valid(ctx->ro_gpio))
-+ return;
-+
-+ gpio = ctx->ro_gpio;
-+ ctx->ro_gpio = -EINVAL;
-+
-+ gpio_free(gpio);
-+}
-+EXPORT_SYMBOL(mmc_gpio_free_ro);
-+
- void mmc_gpio_free_cd(struct mmc_host *host)
- {
- struct mmc_gpio *ctx = host->slot.handler_priv;
-diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h
-index 1a977d7..7d88d27 100644
---- a/include/linux/mmc/slot-gpio.h
-+++ b/include/linux/mmc/slot-gpio.h
-@@ -13,6 +13,10 @@
-
- struct mmc_host;
-
-+int mmc_gpio_get_ro(struct mmc_host *host);
-+int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio);
-+void mmc_gpio_free_ro(struct mmc_host *host);
-+
- int mmc_gpio_get_cd(struct mmc_host *host);
- int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio);
- void mmc_gpio_free_cd(struct mmc_host *host);
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From faee1eb43fa5fa4ab009588d46a5e5b4da3be529 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Tue, 1 May 2012 17:11:56 +0200
-Subject: mmc: tmio: use generic GPIO CD and WP handlers
-
-The tmio-mmc driver is already using the generic GPIO CD handler in IRQ
-mode. This patch adds support for CD polling mode and also checks for
-availability of a WP GPIO.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit 3071cafb7f6f9cbb52b1b7eb308c8b45cae0dcf8)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/tmio_mmc_pio.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
-index f8df021..0d8a9bb 100644
---- a/drivers/mmc/host/tmio_mmc_pio.c
-+++ b/drivers/mmc/host/tmio_mmc_pio.c
-@@ -875,6 +875,9 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc)
- {
- struct tmio_mmc_host *host = mmc_priv(mmc);
- struct tmio_mmc_data *pdata = host->pdata;
-+ int ret = mmc_gpio_get_ro(mmc);
-+ if (ret >= 0)
-+ return ret;
-
- return !((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||
- (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT));
-@@ -884,6 +887,9 @@ static int tmio_mmc_get_cd(struct mmc_host *mmc)
- {
- struct tmio_mmc_host *host = mmc_priv(mmc);
- struct tmio_mmc_data *pdata = host->pdata;
-+ int ret = mmc_gpio_get_cd(mmc);
-+ if (ret >= 0)
-+ return ret;
-
- if (!pdata->get_cd)
- return -ENOSYS;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e4f6cf57b801d98e400bc52f4c3eb372b7703feb Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 9 May 2012 17:09:16 +0200
-Subject: mmc: sh_mobile_sdhi: prepare for conversion to the shdma base library
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Cc: Chris Ball <cjb@laptop.org>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit c471270d7a4161a8f1794202ad8338c0ec55759e)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/sh_mobile_sdhi.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
-index a842939..0bdc146 100644
---- a/drivers/mmc/host/sh_mobile_sdhi.c
-+++ b/drivers/mmc/host/sh_mobile_sdhi.c
-@@ -169,10 +169,10 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
- mmc_data->get_cd = sh_mobile_sdhi_get_cd;
-
- if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
-- priv->param_tx.slave_id = p->dma_slave_tx;
-- priv->param_rx.slave_id = p->dma_slave_rx;
-- priv->dma_priv.chan_priv_tx = &priv->param_tx;
-- priv->dma_priv.chan_priv_rx = &priv->param_rx;
-+ priv->param_tx.shdma_slave.slave_id = p->dma_slave_tx;
-+ priv->param_rx.shdma_slave.slave_id = p->dma_slave_rx;
-+ priv->dma_priv.chan_priv_tx = &priv->param_tx.shdma_slave;
-+ priv->dma_priv.chan_priv_rx = &priv->param_rx.shdma_slave;
- priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */
- mmc_data->dma = &priv->dma_priv;
- }
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 52ffe4e5679653a9bb539a438d6521768fd70e25 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Wed, 9 May 2012 17:09:15 +0200
-Subject: mmc: sh_mmcif: remove unneeded struct sh_mmcif_dma, prepare to shdma
- conversion
-
-Now that all users have been updated to use the embedded in struct
-sh_mmcif_plat_data DMA slave IDs, struct sh_mmcif_dma is no longer needed
-and can be removed. This also makes preparation to the shdma base library
-conversion easier.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Cc: Chris Ball <cjb@laptop.org>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit 916001fe33b7b4dc797f7b29ec8bc346c4369fa6)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/sh_mmcif.c | 24 ++++++++++--------------
- include/linux/mmc/sh_mmcif.h | 8 +-------
- 2 files changed, 11 insertions(+), 21 deletions(-)
-
-diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
-index 724b35e..9e3b9b1 100644
---- a/drivers/mmc/host/sh_mmcif.c
-+++ b/drivers/mmc/host/sh_mmcif.c
-@@ -385,31 +385,27 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
- host->dma_active = false;
-
- /* We can only either use DMA for both Tx and Rx or not use it at all */
-- if (pdata->dma) {
-- dev_warn(&host->pd->dev,
-- "Update your platform to use embedded DMA slave IDs\n");
-- tx = &pdata->dma->chan_priv_tx;
-- rx = &pdata->dma->chan_priv_rx;
-- } else {
-- tx = &host->dma_slave_tx;
-- tx->slave_id = pdata->slave_id_tx;
-- rx = &host->dma_slave_rx;
-- rx->slave_id = pdata->slave_id_rx;
-- }
-- if (tx->slave_id > 0 && rx->slave_id > 0) {
-+ tx = &host->dma_slave_tx;
-+ tx->shdma_slave.slave_id = pdata->slave_id_tx;
-+ rx = &host->dma_slave_rx;
-+ rx->shdma_slave.slave_id = pdata->slave_id_rx;
-+
-+ if (tx->shdma_slave.slave_id > 0 && rx->shdma_slave.slave_id > 0) {
- dma_cap_mask_t mask;
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
-- host->chan_tx = dma_request_channel(mask, sh_mmcif_filter, tx);
-+ host->chan_tx = dma_request_channel(mask, sh_mmcif_filter,
-+ &tx->shdma_slave);
- dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
- host->chan_tx);
-
- if (!host->chan_tx)
- return;
-
-- host->chan_rx = dma_request_channel(mask, sh_mmcif_filter, rx);
-+ host->chan_rx = dma_request_channel(mask, sh_mmcif_filter,
-+ &rx->shdma_slave);
- dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
- host->chan_rx);
-
-diff --git a/include/linux/mmc/sh_mmcif.h b/include/linux/mmc/sh_mmcif.h
-index 05f0e3d..c37956c 100644
---- a/include/linux/mmc/sh_mmcif.h
-+++ b/include/linux/mmc/sh_mmcif.h
-@@ -32,17 +32,11 @@
- * 1111 : Peripheral clock (sup_pclk set '1')
- */
-
--struct sh_mmcif_dma {
-- struct sh_dmae_slave chan_priv_tx;
-- struct sh_dmae_slave chan_priv_rx;
--};
--
- struct sh_mmcif_plat_data {
- void (*set_pwr)(struct platform_device *pdev, int state);
- void (*down_pwr)(struct platform_device *pdev);
- int (*get_cd)(struct platform_device *pdef);
-- struct sh_mmcif_dma *dma; /* Deprecated. Instead */
-- unsigned int slave_id_tx; /* use embedded slave_id_[tr]x */
-+ unsigned int slave_id_tx; /* embedded slave_id_[tr]x */
- unsigned int slave_id_rx;
- u8 sup_pclk; /* 1 :SH7757, 0: SH7724/SH7372 */
- unsigned long caps;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From e528d448bb2c6e6b4c1ea80b809ffdc734806290 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Thu, 5 Jul 2012 12:29:43 +0200
-Subject: mmc: sh_mmcif: switch to the new DMA channel allocation and
- configuration
-
-Using the "private" field from struct dma_chan is deprecated. The sh
-dmaengine driver now also supports the preferred DMA channel allocation
-and configuration method, using a standard filter function and a channel
-configuration operation. This patch updates sh_mmcif to use this new
-method.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Cc: Chris Ball <cjb@laptop.org>
-Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
-(cherry picked from commit 0e79f9ae1610c15f5e5959c39d7c39071619de97)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/sh_mmcif.c | 82 ++++++++++++++++++++++++++-------------------
- 1 file changed, 47 insertions(+), 35 deletions(-)
-
-diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
-index 9e3b9b1..0f07d28 100644
---- a/drivers/mmc/host/sh_mmcif.c
-+++ b/drivers/mmc/host/sh_mmcif.c
-@@ -211,8 +211,6 @@ struct sh_mmcif_host {
- struct mmc_host *mmc;
- struct mmc_request *mrq;
- struct platform_device *pd;
-- struct sh_dmae_slave dma_slave_tx;
-- struct sh_dmae_slave dma_slave_rx;
- struct clk *hclk;
- unsigned int clk;
- int bus_width;
-@@ -371,52 +369,66 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
- desc, cookie);
- }
-
--static bool sh_mmcif_filter(struct dma_chan *chan, void *arg)
--{
-- dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg);
-- chan->private = arg;
-- return true;
--}
--
- static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
- struct sh_mmcif_plat_data *pdata)
- {
-- struct sh_dmae_slave *tx, *rx;
-+ struct resource *res = platform_get_resource(host->pd, IORESOURCE_MEM, 0);
-+ struct dma_slave_config cfg;
-+ dma_cap_mask_t mask;
-+ int ret;
-+
- host->dma_active = false;
-
-+ if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0)
-+ return;
-+
- /* We can only either use DMA for both Tx and Rx or not use it at all */
-- tx = &host->dma_slave_tx;
-- tx->shdma_slave.slave_id = pdata->slave_id_tx;
-- rx = &host->dma_slave_rx;
-- rx->shdma_slave.slave_id = pdata->slave_id_rx;
-+ dma_cap_zero(mask);
-+ dma_cap_set(DMA_SLAVE, mask);
-+
-+ host->chan_tx = dma_request_channel(mask, shdma_chan_filter,
-+ (void *)pdata->slave_id_tx);
-+ dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
-+ host->chan_tx);
-
-- if (tx->shdma_slave.slave_id > 0 && rx->shdma_slave.slave_id > 0) {
-- dma_cap_mask_t mask;
-+ if (!host->chan_tx)
-+ return;
-
-- dma_cap_zero(mask);
-- dma_cap_set(DMA_SLAVE, mask);
-+ cfg.slave_id = pdata->slave_id_tx;
-+ cfg.direction = DMA_MEM_TO_DEV;
-+ cfg.dst_addr = res->start + MMCIF_CE_DATA;
-+ cfg.src_addr = 0;
-+ ret = dmaengine_slave_config(host->chan_tx, &cfg);
-+ if (ret < 0)
-+ goto ecfgtx;
-
-- host->chan_tx = dma_request_channel(mask, sh_mmcif_filter,
-- &tx->shdma_slave);
-- dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
-- host->chan_tx);
-+ host->chan_rx = dma_request_channel(mask, shdma_chan_filter,
-+ (void *)pdata->slave_id_rx);
-+ dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
-+ host->chan_rx);
-
-- if (!host->chan_tx)
-- return;
-+ if (!host->chan_rx)
-+ goto erqrx;
-
-- host->chan_rx = dma_request_channel(mask, sh_mmcif_filter,
-- &rx->shdma_slave);
-- dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
-- host->chan_rx);
-+ cfg.slave_id = pdata->slave_id_rx;
-+ cfg.direction = DMA_DEV_TO_MEM;
-+ cfg.dst_addr = 0;
-+ cfg.src_addr = res->start + MMCIF_CE_DATA;
-+ ret = dmaengine_slave_config(host->chan_rx, &cfg);
-+ if (ret < 0)
-+ goto ecfgrx;
-
-- if (!host->chan_rx) {
-- dma_release_channel(host->chan_tx);
-- host->chan_tx = NULL;
-- return;
-- }
-+ init_completion(&host->dma_complete);
-
-- init_completion(&host->dma_complete);
-- }
-+ return;
-+
-+ecfgrx:
-+ dma_release_channel(host->chan_rx);
-+ host->chan_rx = NULL;
-+erqrx:
-+ecfgtx:
-+ dma_release_channel(host->chan_tx);
-+ host->chan_tx = NULL;
- }
-
- static void sh_mmcif_release_dma(struct sh_mmcif_host *host)
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From a582cd28240bd5aca4462da1dacd8dd8e9ee0dbc Mon Sep 17 00:00:00 2001
-From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Date: Tue, 12 Jun 2012 22:56:09 +0200
-Subject: mmc: sh_mmcif: Support MMC_SLEEP_AWAKE command
-
-The MMC_SLEEP_AWAKE and SD_IO_SEND_OP_COND commands share the same
-opcode. SD_IO_SEND_OP_COND isn't supported by the SH MMCIF, but
-MMC_SLEEP_AWAKE is. Discriminate between the two commands using the
-command flags, and reject SD_IO_SEND_OP_COND only.
-
-Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit 7541ca98477862e2e9988c6c2ceadbdccefa9d77)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/sh_mmcif.c | 14 ++++----------
- 1 file changed, 4 insertions(+), 10 deletions(-)
-
-diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
-index 0f07d28..1eb23a7 100644
---- a/drivers/mmc/host/sh_mmcif.c
-+++ b/drivers/mmc/host/sh_mmcif.c
-@@ -900,21 +900,15 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
-
- switch (mrq->cmd->opcode) {
- /* MMCIF does not support SD/SDIO command */
-- case SD_IO_SEND_OP_COND:
-+ case MMC_SLEEP_AWAKE: /* = SD_IO_SEND_OP_COND (5) */
-+ case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */
-+ if ((mrq->cmd->flags & MMC_CMD_MASK) != MMC_CMD_BCR)
-+ break;
- case MMC_APP_CMD:
- host->state = STATE_IDLE;
- mrq->cmd->error = -ETIMEDOUT;
- mmc_request_done(mmc, mrq);
- return;
-- case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */
-- if (!mrq->data) {
-- /* send_if_cond cmd (not support) */
-- host->state = STATE_IDLE;
-- mrq->cmd->error = -ETIMEDOUT;
-- mmc_request_done(mmc, mrq);
-- return;
-- }
-- break;
- default:
- break;
- }
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From 31a4301b36511da303ad36da908f462f057f0e73 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Thu, 19 Apr 2012 16:15:52 +0200
-Subject: mmc: sh_mmcif: simplify and use meaningful label names in
- error-handling
-
-A check for NULL platform data can be conveniently made in the very
-beginning of probing. Replace numbered error-handling labels in .probe()
-with meaningful names to make any future reorganisation simpler.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Reviewed-by: Simon Horman <horms@verge.net.au>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit e1aae2eb3f7c446a2680a3a0ccd05aa50521b4e2)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/sh_mmcif.c | 41 ++++++++++++++++++++---------------------
- 1 file changed, 20 insertions(+), 21 deletions(-)
-
---- a/drivers/mmc/host/sh_mmcif.c
-+++ b/drivers/mmc/host/sh_mmcif.c
-@@ -1249,11 +1249,16 @@ static int __devinit sh_mmcif_probe(stru
- int ret = 0, irq[2];
- struct mmc_host *mmc;
- struct sh_mmcif_host *host;
-- struct sh_mmcif_plat_data *pd;
-+ struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;
- struct resource *res;
- void __iomem *reg;
- char clk_name[8];
-
-+ if (!pd) {
-+ dev_err(&pdev->dev, "sh_mmcif plat data error.\n");
-+ return -ENXIO;
-+ }
-+
- irq[0] = platform_get_irq(pdev, 0);
- irq[1] = platform_get_irq(pdev, 1);
- if (irq[0] < 0 || irq[1] < 0) {
-@@ -1270,16 +1275,11 @@ static int __devinit sh_mmcif_probe(stru
- dev_err(&pdev->dev, "ioremap error.\n");
- return -ENOMEM;
- }
-- pd = pdev->dev.platform_data;
-- if (!pd) {
-- dev_err(&pdev->dev, "sh_mmcif plat data error.\n");
-- ret = -ENXIO;
-- goto clean_up;
-- }
-+
- mmc = mmc_alloc_host(sizeof(struct sh_mmcif_host), &pdev->dev);
- if (!mmc) {
- ret = -ENOMEM;
-- goto clean_up;
-+ goto ealloch;
- }
- host = mmc_priv(mmc);
- host->mmc = mmc;
-@@ -1291,7 +1291,7 @@ static int __devinit sh_mmcif_probe(stru
- if (IS_ERR(host->hclk)) {
- dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
- ret = PTR_ERR(host->hclk);
-- goto clean_up1;
-+ goto eclkget;
- }
- clk_enable(host->hclk);
- host->clk = clk_get_rate(host->hclk);
-@@ -1321,7 +1321,7 @@ static int __devinit sh_mmcif_probe(stru
-
- ret = pm_runtime_resume(&pdev->dev);
- if (ret < 0)
-- goto clean_up2;
-+ goto eresume;
-
- INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
-
-@@ -1330,17 +1330,17 @@ static int __devinit sh_mmcif_probe(stru
- ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host);
- if (ret) {
- dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n");
-- goto clean_up3;
-+ goto ereqirq0;
- }
- ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host);
- if (ret) {
- dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
-- goto clean_up4;
-+ goto ereqirq1;
- }
-
- ret = mmc_add_host(mmc);
- if (ret < 0)
-- goto clean_up5;
-+ goto emmcaddh;
-
- dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
-
-@@ -1349,20 +1349,19 @@ static int __devinit sh_mmcif_probe(stru
- sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
- return ret;
-
--clean_up5:
-+emmcaddh:
- free_irq(irq[1], host);
--clean_up4:
-+ereqirq1:
- free_irq(irq[0], host);
--clean_up3:
-+ereqirq0:
- pm_runtime_suspend(&pdev->dev);
--clean_up2:
-+eresume:
- pm_runtime_disable(&pdev->dev);
- clk_disable(host->hclk);
--clean_up1:
-+eclkget:
- mmc_free_host(mmc);
--clean_up:
-- if (reg)
-- iounmap(reg);
-+ealloch:
-+ iounmap(reg);
- return ret;
- }
-
+++ /dev/null
-From f504bc8e96b3633271ee5e623c35e026a6db62e7 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Thu, 19 Apr 2012 18:02:05 +0200
-Subject: mmc: sh_mmcif: fix clock management
-
-Regardless of whether the MMC bus clock is the same as the PM clock on
-this specific interface, it has to be managed separately. Its proper
-management should also include enabling and disabling of the clock,
-whenever the interface is becoming active or going idle respectively.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Reviewed-by: Simon Horman <horms@verge.net.au>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit b289174ff70a591545a054d52ae081a75a73f085)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/sh_mmcif.c | 46 ++++++++++++++++++++++----------------------
- 1 file changed, 23 insertions(+), 23 deletions(-)
-
---- a/drivers/mmc/host/sh_mmcif.c
-+++ b/drivers/mmc/host/sh_mmcif.c
-@@ -950,6 +950,7 @@ static void sh_mmcif_set_ios(struct mmc_
- }
- if (host->power) {
- pm_runtime_put(&host->pd->dev);
-+ clk_disable(host->hclk);
- host->power = false;
- if (p->down_pwr && ios->power_mode == MMC_POWER_OFF)
- p->down_pwr(host->pd);
-@@ -962,6 +963,7 @@ static void sh_mmcif_set_ios(struct mmc_
- if (!host->power) {
- if (p->set_pwr)
- p->set_pwr(host->pd, ios->power_mode);
-+ clk_enable(host->hclk);
- pm_runtime_get_sync(&host->pd->dev);
- host->power = true;
- sh_mmcif_sync_reset(host);
-@@ -1286,22 +1288,11 @@ static int __devinit sh_mmcif_probe(stru
- host->addr = reg;
- host->timeout = 1000;
-
-- snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id);
-- host->hclk = clk_get(&pdev->dev, clk_name);
-- if (IS_ERR(host->hclk)) {
-- dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
-- ret = PTR_ERR(host->hclk);
-- goto eclkget;
-- }
-- clk_enable(host->hclk);
-- host->clk = clk_get_rate(host->hclk);
- host->pd = pdev;
-
- spin_lock_init(&host->lock);
-
- mmc->ops = &sh_mmcif_ops;
-- mmc->f_max = host->clk / 2;
-- mmc->f_min = host->clk / 512;
- if (pd->ocr)
- mmc->ocr_avail = pd->ocr;
- mmc->caps = MMC_CAP_MMC_HIGHSPEED;
-@@ -1313,18 +1304,30 @@ static int __devinit sh_mmcif_probe(stru
- mmc->max_blk_count = mmc->max_req_size / mmc->max_blk_size;
- mmc->max_seg_size = mmc->max_req_size;
-
-- sh_mmcif_sync_reset(host);
- platform_set_drvdata(pdev, host);
-
- pm_runtime_enable(&pdev->dev);
- host->power = false;
-
-+ snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id);
-+ host->hclk = clk_get(&pdev->dev, clk_name);
-+ if (IS_ERR(host->hclk)) {
-+ ret = PTR_ERR(host->hclk);
-+ dev_err(&pdev->dev, "cannot get clock \"%s\": %d\n", clk_name, ret);
-+ goto eclkget;
-+ }
-+ clk_enable(host->hclk);
-+ host->clk = clk_get_rate(host->hclk);
-+ mmc->f_max = host->clk / 2;
-+ mmc->f_min = host->clk / 512;
-+
- ret = pm_runtime_resume(&pdev->dev);
- if (ret < 0)
- goto eresume;
-
- INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
-
-+ sh_mmcif_sync_reset(host);
- sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
-
- ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host);
-@@ -1338,6 +1341,7 @@ static int __devinit sh_mmcif_probe(stru
- goto ereqirq1;
- }
-
-+ clk_disable(host->hclk);
- ret = mmc_add_host(mmc);
- if (ret < 0)
- goto emmcaddh;
-@@ -1356,9 +1360,10 @@ ereqirq1:
- ereqirq0:
- pm_runtime_suspend(&pdev->dev);
- eresume:
-- pm_runtime_disable(&pdev->dev);
- clk_disable(host->hclk);
-+ clk_put(host->hclk);
- eclkget:
-+ pm_runtime_disable(&pdev->dev);
- mmc_free_host(mmc);
- ealloch:
- iounmap(reg);
-@@ -1371,6 +1376,7 @@ static int __devexit sh_mmcif_remove(str
- int irq[2];
-
- host->dying = true;
-+ clk_enable(host->hclk);
- pm_runtime_get_sync(&pdev->dev);
-
- dev_pm_qos_hide_latency_limit(&pdev->dev);
-@@ -1396,9 +1402,9 @@ static int __devexit sh_mmcif_remove(str
-
- platform_set_drvdata(pdev, NULL);
-
-- clk_disable(host->hclk);
- mmc_free_host(host->mmc);
- pm_runtime_put_sync(&pdev->dev);
-+ clk_disable(host->hclk);
- pm_runtime_disable(&pdev->dev);
-
- return 0;
-@@ -1407,24 +1413,18 @@ static int __devexit sh_mmcif_remove(str
- #ifdef CONFIG_PM
- static int sh_mmcif_suspend(struct device *dev)
- {
-- struct platform_device *pdev = to_platform_device(dev);
-- struct sh_mmcif_host *host = platform_get_drvdata(pdev);
-+ struct sh_mmcif_host *host = dev_get_drvdata(dev);
- int ret = mmc_suspend_host(host->mmc);
-
-- if (!ret) {
-+ if (!ret)
- sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
-- clk_disable(host->hclk);
-- }
-
- return ret;
- }
-
- static int sh_mmcif_resume(struct device *dev)
- {
-- struct platform_device *pdev = to_platform_device(dev);
-- struct sh_mmcif_host *host = platform_get_drvdata(pdev);
--
-- clk_enable(host->hclk);
-+ struct sh_mmcif_host *host = dev_get_drvdata(dev);
-
- return mmc_resume_host(host->mmc);
- }
+++ /dev/null
-From 417f01ebd88111d61e507af5d9cab347ffa41861 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Thu, 19 Apr 2012 18:02:50 +0200
-Subject: mmc: sh_mmcif: re-read the clock frequency every time it is turned on
-
-With aggressive clock gating the clock can be disabled during interface
-inactivity. During this time its frequency can be changed by another its
-user. Therefore when the interface is activated again and the clock is
-re-enabled, its frequency has to be re-read.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Reviewed-by: Simon Horman <horms@verge.net.au>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit a6609267107ecc5598b79aa353036c1f57e7257e)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/sh_mmcif.c | 23 ++++++++++++++++++-----
- 1 file changed, 18 insertions(+), 5 deletions(-)
-
---- a/drivers/mmc/host/sh_mmcif.c
-+++ b/drivers/mmc/host/sh_mmcif.c
-@@ -918,6 +918,19 @@ static void sh_mmcif_request(struct mmc_
- sh_mmcif_start_cmd(host, mrq);
- }
-
-+static int sh_mmcif_clk_update(struct sh_mmcif_host *host)
-+{
-+ int ret = clk_enable(host->hclk);
-+
-+ if (!ret) {
-+ host->clk = clk_get_rate(host->hclk);
-+ host->mmc->f_max = host->clk / 2;
-+ host->mmc->f_min = host->clk / 512;
-+ }
-+
-+ return ret;
-+}
-+
- static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
- {
- struct sh_mmcif_host *host = mmc_priv(mmc);
-@@ -963,7 +976,7 @@ static void sh_mmcif_set_ios(struct mmc_
- if (!host->power) {
- if (p->set_pwr)
- p->set_pwr(host->pd, ios->power_mode);
-- clk_enable(host->hclk);
-+ sh_mmcif_clk_update(host);
- pm_runtime_get_sync(&host->pd->dev);
- host->power = true;
- sh_mmcif_sync_reset(host);
-@@ -1316,10 +1329,9 @@ static int __devinit sh_mmcif_probe(stru
- dev_err(&pdev->dev, "cannot get clock \"%s\": %d\n", clk_name, ret);
- goto eclkget;
- }
-- clk_enable(host->hclk);
-- host->clk = clk_get_rate(host->hclk);
-- mmc->f_max = host->clk / 2;
-- mmc->f_min = host->clk / 512;
-+ ret = sh_mmcif_clk_update(host);
-+ if (ret < 0)
-+ goto eclkupdate;
-
- ret = pm_runtime_resume(&pdev->dev);
- if (ret < 0)
-@@ -1361,6 +1373,7 @@ ereqirq0:
- pm_runtime_suspend(&pdev->dev);
- eresume:
- clk_disable(host->hclk);
-+eclkupdate:
- clk_put(host->hclk);
- eclkget:
- pm_runtime_disable(&pdev->dev);
+++ /dev/null
-From 57a9e156b943508dc6ee4ac85e43d90f0888985f Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Fri, 20 Apr 2012 09:01:05 +0200
-Subject: mmc: sh_mmcif: remove redundant .down_pwr() callback
-
-From the original version of sh_mmcif the .set_pwr() callback has only been
-used to turn the card's power on, and the .down_pwr() callback has been
-used to turn it off. .set_pwr() can be used for both these tasks, which is
-also how it is implemented by the only user of this API: the SH7724 ecovec
-board.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Reviewed-by: Simon Horman <horms@verge.net.au>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit e2ee996eaad64c149cb7cfd344789c7e0c1577dc)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/sh_mmcif.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
-index 29d908a..10c5fcd 100644
---- a/drivers/mmc/host/sh_mmcif.c
-+++ b/drivers/mmc/host/sh_mmcif.c
-@@ -965,8 +965,8 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
- pm_runtime_put(&host->pd->dev);
- clk_disable(host->hclk);
- host->power = false;
-- if (p->down_pwr && ios->power_mode == MMC_POWER_OFF)
-- p->down_pwr(host->pd);
-+ if (p->set_pwr && ios->power_mode == MMC_POWER_OFF)
-+ p->set_pwr(host->pd, 0);
- }
- host->state = STATE_IDLE;
- return;
---
-1.8.0.197.g5a90748
-
+++ /dev/null
-From d573e549e130bfe6200b70a36ab44767943b52a2 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Fri, 20 Apr 2012 18:27:13 +0200
-Subject: mmc: sh_mmcif: add regulator support
-
-Add regulator support to the sh_mmcif driver, but also preserve the current
-power-callback.
-
-Also note, that the card power is not switched off during clock gating
-periods, hence there's no need to power it on every time the card is
-re-activated.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Reviwed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-Reviewed-by: Simon Horman <horms@verge.net.au>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit 7d17baa05da6a2e64ee15011cdf4319bd3e0ff61)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/sh_mmcif.c | 38 +++++++++++++++++++++++++++++++-------
- 1 file changed, 31 insertions(+), 7 deletions(-)
-
---- a/drivers/mmc/host/sh_mmcif.c
-+++ b/drivers/mmc/host/sh_mmcif.c
-@@ -931,10 +931,22 @@ static int sh_mmcif_clk_update(struct sh
- return ret;
- }
-
-+static void sh_mmcif_set_power(struct sh_mmcif_host *host, struct mmc_ios *ios)
-+{
-+ struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data;
-+ struct mmc_host *mmc = host->mmc;
-+
-+ if (pd->set_pwr)
-+ pd->set_pwr(host->pd, ios->power_mode != MMC_POWER_OFF);
-+ if (!IS_ERR(mmc->supply.vmmc))
-+ /* Errors ignored... */
-+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
-+ ios->power_mode ? ios->vdd : 0);
-+}
-+
- static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
- {
- struct sh_mmcif_host *host = mmc_priv(mmc);
-- struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
- unsigned long flags;
-
- spin_lock_irqsave(&host->lock, flags);
-@@ -952,6 +964,7 @@ static void sh_mmcif_set_ios(struct mmc_
- sh_mmcif_request_dma(host, host->pd->dev.platform_data);
- host->card_present = true;
- }
-+ sh_mmcif_set_power(host, ios);
- } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
- /* clock stop */
- sh_mmcif_clock_control(host, 0);
-@@ -965,8 +978,8 @@ static void sh_mmcif_set_ios(struct mmc_
- pm_runtime_put(&host->pd->dev);
- clk_disable(host->hclk);
- host->power = false;
-- if (p->set_pwr && ios->power_mode == MMC_POWER_OFF)
-- p->set_pwr(host->pd, 0);
-+ if (ios->power_mode == MMC_POWER_OFF)
-+ sh_mmcif_set_power(host, ios);
- }
- host->state = STATE_IDLE;
- return;
-@@ -974,8 +987,6 @@ static void sh_mmcif_set_ios(struct mmc_
-
- if (ios->clock) {
- if (!host->power) {
-- if (p->set_pwr)
-- p->set_pwr(host->pd, ios->power_mode);
- sh_mmcif_clk_update(host);
- pm_runtime_get_sync(&host->pd->dev);
- host->power = true;
-@@ -1259,6 +1270,19 @@ static void mmcif_timeout_work(struct wo
- mmc_request_done(host->mmc, mrq);
- }
-
-+static void sh_mmcif_init_ocr(struct sh_mmcif_host *host)
-+{
-+ struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data;
-+ struct mmc_host *mmc = host->mmc;
-+
-+ mmc_regulator_get_supply(mmc);
-+
-+ if (!mmc->ocr_avail)
-+ mmc->ocr_avail = pd->ocr;
-+ else if (pd->ocr)
-+ dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
-+}
-+
- static int __devinit sh_mmcif_probe(struct platform_device *pdev)
- {
- int ret = 0, irq[2];
-@@ -1306,8 +1330,8 @@ static int __devinit sh_mmcif_probe(stru
- spin_lock_init(&host->lock);
-
- mmc->ops = &sh_mmcif_ops;
-- if (pd->ocr)
-- mmc->ocr_avail = pd->ocr;
-+ sh_mmcif_init_ocr(host);
-+
- mmc->caps = MMC_CAP_MMC_HIGHSPEED;
- if (pd->caps)
- mmc->caps |= pd->caps;
+++ /dev/null
-From 7feedc26deff116af14317bfba8356724b71a362 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Tue, 1 May 2012 18:18:16 +0200
-Subject: mmc: sh-mmcif: add OF support, make platform data optional
-
-Add primitive OF support to the sh-mmcif driver, which also makes it
-necessary to be able to run without platform data.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit bf68a812f06ca40bccfa2e792055141f2c3948c7)
-
-Conflicts:
- drivers/mmc/host/sh_mmcif.c
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/sh_mmcif.c | 29 ++++++++++++++++++++---------
- 1 file changed, 20 insertions(+), 9 deletions(-)
-
---- a/drivers/mmc/host/sh_mmcif.c
-+++ b/drivers/mmc/host/sh_mmcif.c
-@@ -54,6 +54,7 @@
- #include <linux/mmc/mmc.h>
- #include <linux/mmc/sdio.h>
- #include <linux/mmc/sh_mmcif.h>
-+#include <linux/mod_devicetable.h>
- #include <linux/pagemap.h>
- #include <linux/platform_device.h>
- #include <linux/pm_qos.h>
-@@ -379,6 +380,9 @@ static void sh_mmcif_request_dma(struct
-
- host->dma_active = false;
-
-+ if (!pdata)
-+ return;
-+
- if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0)
- return;
-
-@@ -452,13 +456,14 @@ static void sh_mmcif_release_dma(struct
- static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)
- {
- struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
-+ bool sup_pclk = p ? p->sup_pclk : false;
-
- sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE);
- sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR);
-
- if (!clk)
- return;
-- if (p->sup_pclk && clk == host->clk)
-+ if (sup_pclk && clk == host->clk)
- sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK);
- else
- sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR &
-@@ -936,7 +941,7 @@ static void sh_mmcif_set_power(struct sh
- struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data;
- struct mmc_host *mmc = host->mmc;
-
-- if (pd->set_pwr)
-+ if (pd && pd->set_pwr)
- pd->set_pwr(host->pd, ios->power_mode != MMC_POWER_OFF);
- if (!IS_ERR(mmc->supply.vmmc))
- /* Errors ignored... */
-@@ -1004,7 +1009,7 @@ static int sh_mmcif_get_cd(struct mmc_ho
- struct sh_mmcif_host *host = mmc_priv(mmc);
- struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
-
-- if (!p->get_cd)
-+ if (!p || !p->get_cd)
- return -ENOSYS;
- else
- return p->get_cd(host->pd);
-@@ -1277,6 +1282,9 @@ static void sh_mmcif_init_ocr(struct sh_
-
- mmc_regulator_get_supply(mmc);
-
-+ if (!pd)
-+ return;
-+
- if (!mmc->ocr_avail)
- mmc->ocr_avail = pd->ocr;
- else if (pd->ocr)
-@@ -1293,11 +1301,6 @@ static int __devinit sh_mmcif_probe(stru
- void __iomem *reg;
- char clk_name[8];
-
-- if (!pd) {
-- dev_err(&pdev->dev, "sh_mmcif plat data error.\n");
-- return -ENXIO;
-- }
--
- irq[0] = platform_get_irq(pdev, 0);
- irq[1] = platform_get_irq(pdev, 1);
- if (irq[0] < 0 || irq[1] < 0) {
-@@ -1333,7 +1336,7 @@ static int __devinit sh_mmcif_probe(stru
- sh_mmcif_init_ocr(host);
-
- mmc->caps = MMC_CAP_MMC_HIGHSPEED;
-- if (pd->caps)
-+ if (pd && pd->caps)
- mmc->caps |= pd->caps;
- mmc->max_segs = 32;
- mmc->max_blk_size = 512;
-@@ -1470,6 +1473,12 @@ static int sh_mmcif_resume(struct device
- #define sh_mmcif_resume NULL
- #endif /* CONFIG_PM */
-
-+static const struct of_device_id mmcif_of_match[] = {
-+ { .compatible = "renesas,sh-mmcif" },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, mmcif_of_match);
-+
- static const struct dev_pm_ops sh_mmcif_dev_pm_ops = {
- .suspend = sh_mmcif_suspend,
- .resume = sh_mmcif_resume,
-@@ -1481,6 +1490,8 @@ static struct platform_driver sh_mmcif_d
- .driver = {
- .name = DRIVER_NAME,
- .pm = &sh_mmcif_dev_pm_ops,
-+ .owner = THIS_MODULE,
-+ .of_match_table = mmcif_of_match,
- },
- };
-
+++ /dev/null
-From 4156a922e2e32baccd17cb76ba388cecb1790299 Mon Sep 17 00:00:00 2001
-From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Date: Thu, 14 Jun 2012 14:24:35 +0200
-Subject: mmc: sh_mmcif: support generic card-detection
-
-Extend the sh_mmcif driver to support GPIO card detection, provided by the
-slot function module. The original .get_cd() platform callback is also
-preserved for now.
-
-Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Chris Ball <cjb@laptop.org>
-(cherry picked from commit e480606ad43bb72fd82a9bd99cdcf21829a6e9c0)
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- drivers/mmc/host/sh_mmcif.c | 18 ++++++++++++++++++
- include/linux/mmc/sh_mmcif.h | 2 ++
- 2 files changed, 20 insertions(+)
-
---- a/drivers/mmc/host/sh_mmcif.c
-+++ b/drivers/mmc/host/sh_mmcif.c
-@@ -54,6 +54,7 @@
- #include <linux/mmc/mmc.h>
- #include <linux/mmc/sdio.h>
- #include <linux/mmc/sh_mmcif.h>
-+#include <linux/mmc/slot-gpio.h>
- #include <linux/mod_devicetable.h>
- #include <linux/pagemap.h>
- #include <linux/platform_device.h>
-@@ -1008,6 +1009,10 @@ static int sh_mmcif_get_cd(struct mmc_ho
- {
- struct sh_mmcif_host *host = mmc_priv(mmc);
- struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
-+ int ret = mmc_gpio_get_cd(mmc);
-+
-+ if (ret >= 0)
-+ return ret;
-
- if (!p || !p->get_cd)
- return -ENOSYS;
-@@ -1380,6 +1385,12 @@ static int __devinit sh_mmcif_probe(stru
- goto ereqirq1;
- }
-
-+ if (pd && pd->use_cd_gpio) {
-+ ret = mmc_gpio_request_cd(mmc, pd->cd_gpio);
-+ if (ret < 0)
-+ goto erqcd;
-+ }
-+
- clk_disable(host->hclk);
- ret = mmc_add_host(mmc);
- if (ret < 0)
-@@ -1393,6 +1404,9 @@ static int __devinit sh_mmcif_probe(stru
- return ret;
-
- emmcaddh:
-+ if (pd && pd->use_cd_gpio)
-+ mmc_gpio_free_cd(mmc);
-+erqcd:
- free_irq(irq[1], host);
- ereqirq1:
- free_irq(irq[0], host);
-@@ -1413,6 +1427,7 @@ ealloch:
- static int __devexit sh_mmcif_remove(struct platform_device *pdev)
- {
- struct sh_mmcif_host *host = platform_get_drvdata(pdev);
-+ struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;
- int irq[2];
-
- host->dying = true;
-@@ -1421,6 +1436,9 @@ static int __devexit sh_mmcif_remove(str
-
- dev_pm_qos_hide_latency_limit(&pdev->dev);
-
-+ if (pd && pd->use_cd_gpio)
-+ mmc_gpio_free_cd(host->mmc);
-+
- mmc_remove_host(host->mmc);
- sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
-
---- a/include/linux/mmc/sh_mmcif.h
-+++ b/include/linux/mmc/sh_mmcif.h
-@@ -38,6 +38,8 @@ struct sh_mmcif_plat_data {
- int (*get_cd)(struct platform_device *pdef);
- unsigned int slave_id_tx; /* embedded slave_id_[tr]x */
- unsigned int slave_id_rx;
-+ bool use_cd_gpio : 1;
-+ unsigned int cd_gpio;
- u8 sup_pclk; /* 1 :SH7757, 0: SH7724/SH7372 */
- unsigned long caps;
- u32 ocr;
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 11 14:26:47 2013
-From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
-Date: Sun, 12 May 2013 01:26:55 +0400
-Subject: ARM: mach-shmobile: marzen: add SATA support
-To: ltsi-dev@lists.linuxfoundation.org
-Cc: vladimir.barinov@cogentembedded.com
-Message-ID: <201305120126.55306.sergei.shtylyov@cogentembedded.com>
-
-
-From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
-
-Add SATA support to marzen_defconfig.
-
-Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
-Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-(cherry picked from commit db30abdf3c07c564d4af0f991bb7f38b728f9035)
-
----
-This patch (already merged by Linus) is intended for the Marzen patch series.
-
-Changes from the upstream version:
-- resolved reject due to missing interim patches.
-
- arch/arm/configs/marzen_defconfig | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/arch/arm/configs/marzen_defconfig
-+++ b/arch/arm/configs/marzen_defconfig
-@@ -47,6 +47,10 @@ CONFIG_DEVTMPFS_MOUNT=y
- # CONFIG_STANDALONE is not set
- # CONFIG_PREVENT_FIRMWARE_BUILD is not set
- # CONFIG_FW_LOADER is not set
-+CONFIG_ATA=y
-+CONFIG_ATA_SFF=y
-+CONFIG_ATA_BMDMA=y
-+CONFIG_SATA_RCAR=y
- CONFIG_NETDEVICES=y
- # CONFIG_NET_VENDOR_BROADCOM is not set
- # CONFIG_NET_VENDOR_FARADAY is not set
+++ /dev/null
-From horms@vergenet.net Mon Dec 3 20:53:03 2012
-From: Simon Horman <horms+renesas@verge.net.au>
-Date: Tue, 4 Dec 2012 13:52:50 +0900
-Subject: [PATCH 1/2] ARM: mach-shmobile: marzen: defconfig update
-To: ltsi-dev@lists.linuxfoundation.org
-Cc: Greg KH <gregkh@linuxfoundation.org>
-Message-ID: <1354596771-7290-2-git-send-email-horms+renesas@verge.net.au>
-
-
-From: Simon Horman <horms@verge.net.au>
-
-Update marzen defconfig
-* Enable MMC Block device as SDHI hw is now supported.
-* Default to NFS root, this is consistent with many other
- shmobile boards
-* Enable UNIX which is required by udevd
-* Enable SDHI
-
-Other changes are noise due to using make savedefconfig
-to create the new defconfig.
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
-Cc: Phil Edworthy <phil.edworthy@renesas.com>
-Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-(cherry picked from commit f0a1f1c226b64859448bfc247dbf8835c4c5cf06)
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- arch/arm/configs/marzen_defconfig | 15 ++++++++++-----
- 1 file changed, 10 insertions(+), 5 deletions(-)
-
-diff --git a/arch/arm/configs/marzen_defconfig b/arch/arm/configs/marzen_defconfig
-index 864f9a5..737e498 100644
---- a/arch/arm/configs/marzen_defconfig
-+++ b/arch/arm/configs/marzen_defconfig
-@@ -1,13 +1,14 @@
- # CONFIG_ARM_PATCH_PHYS_VIRT is not set
- CONFIG_EXPERIMENTAL=y
- CONFIG_KERNEL_LZMA=y
-+CONFIG_NO_HZ=y
- CONFIG_IKCONFIG=y
- CONFIG_IKCONFIG_PROC=y
- CONFIG_LOG_BUF_SHIFT=16
- CONFIG_SYSCTL_SYSCALL=y
- CONFIG_EMBEDDED=y
- CONFIG_SLAB=y
--# CONFIG_BLOCK is not set
-+# CONFIG_IOSCHED_CFQ is not set
- CONFIG_ARCH_SHMOBILE=y
- CONFIG_ARCH_R8A7779=y
- CONFIG_MACH_MARZEN=y
-@@ -21,7 +22,6 @@ CONFIG_ARM_ERRATA_458693=y
- CONFIG_ARM_ERRATA_460075=y
- CONFIG_ARM_ERRATA_743622=y
- CONFIG_ARM_ERRATA_754322=y
--CONFIG_NO_HZ=y
- CONFIG_SMP=y
- # CONFIG_ARM_CPU_TOPOLOGY is not set
- CONFIG_AEABI=y
-@@ -29,13 +29,16 @@ CONFIG_AEABI=y
- CONFIG_HIGHMEM=y
- CONFIG_ZBOOT_ROM_TEXT=0x0
- CONFIG_ZBOOT_ROM_BSS=0x0
--CONFIG_CMDLINE="console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel"
-+CONFIG_CMDLINE="console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel root=/dev/nfs ip=on"
- CONFIG_CMDLINE_FORCE=y
- CONFIG_KEXEC=y
- # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
- CONFIG_PM_RUNTIME=y
- CONFIG_NET=y
-+CONFIG_UNIX=y
- CONFIG_INET=y
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
- # CONFIG_IPV6 is not set
- # CONFIG_WIRELESS is not set
- CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-@@ -69,16 +72,18 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
- CONFIG_GPIO_SYSFS=y
- # CONFIG_HWMON is not set
- CONFIG_SSB=y
--# CONFIG_HID_SUPPORT is not set
- # CONFIG_USB_SUPPORT is not set
-+CONFIG_MMC=y
-+CONFIG_MMC_SDHI=y
- CONFIG_UIO=y
- CONFIG_UIO_PDRV_GENIRQ=y
- # CONFIG_IOMMU_SUPPORT is not set
--# CONFIG_FILE_LOCKING is not set
- # CONFIG_DNOTIFY is not set
- # CONFIG_INOTIFY_USER is not set
- CONFIG_TMPFS=y
- # CONFIG_MISC_FILESYSTEMS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_ROOT_NFS=y
- CONFIG_MAGIC_SYSRQ=y
- CONFIG_DEBUG_INFO=y
- CONFIG_DEBUG_INFO_REDUCED=y
---
-1.7.10.4
-
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 11 14:25:45 2013
-From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
-Date: Sun, 12 May 2013 01:25:50 +0400
-Subject: ARM: mach-shmobile: r8a7779: add SATA support
-To: ltsi-dev@lists.linuxfoundation.org
-Cc: vladimir.barinov@cogentembedded.com
-Message-ID: <201305120125.51117.sergei.shtylyov@cogentembedded.com>
-
-
-From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
-
-Add SATA clock for r8a7779 SoC (for both device tree and usual cases).
-Register SATA controller as a "late" platform device on r8a7779 SoC.
-
-Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
-Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-(cherry picked from commit a7b9837c7749bf3333151a7d060d239caff1569d)
-
----
-This patch (already merged by Linus) is intended for the Marzen patch series.
-
-Changes from the upstream version:
-- added SATA platform device to the "early" device table instead of "late";
-- resolved 4 rejects due to missing interim patches.
-
- arch/arm/mach-shmobile/clock-r8a7779.c | 6 +++++-
- arch/arm/mach-shmobile/setup-r8a7779.c | 26 ++++++++++++++++++++++++++
- 2 files changed, 31 insertions(+), 1 deletion(-)
-
---- a/arch/arm/mach-shmobile/clock-r8a7779.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
-@@ -86,11 +86,13 @@ static struct clk div4_clks[DIV4_NR] = {
- 0x0300, CLK_ENABLE_ON_INIT),
- };
-
--enum { MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
-+enum { MSTP115,
-+ MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
- MSTP016, MSTP015, MSTP014,
- MSTP_NR };
-
- static struct clk mstp_clks[MSTP_NR] = {
-+ [MSTP115] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 15, 0), /* SATA */
- [MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0), /* SCIF0 */
- [MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0), /* SCIF1 */
- [MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0), /* SCIF2 */
-@@ -141,6 +143,8 @@ static struct clk_lookup lookups[] = {
- CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
-
- /* MSTP32 clocks */
-+ CLKDEV_DEV_ID("sata_rcar", &mstp_clks[MSTP115]), /* SATA */
-+ CLKDEV_DEV_ID("fc600000.sata", &mstp_clks[MSTP115]), /* SATA w/DT */
- CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP016]), /* TMU00 */
- CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP015]), /* TMU01 */
- CLKDEV_DEV_ID("sh_tmu.2", &mstp_clks[MSTP014]), /* TMU02 */
---- a/arch/arm/mach-shmobile/setup-r8a7779.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
-@@ -28,6 +28,7 @@
- #include <linux/serial_sci.h>
- #include <linux/sh_intc.h>
- #include <linux/sh_timer.h>
-+#include <linux/dma-mapping.h>
- #include <mach/hardware.h>
- #include <mach/irqs.h>
- #include <mach/r8a7779.h>
-@@ -302,6 +303,30 @@ static struct platform_device i2c3_devic
- .num_resources = ARRAY_SIZE(rcar_i2c3_res),
- };
-
-+static struct resource sata_resources[] = {
-+ [0] = {
-+ .name = "rcar-sata",
-+ .start = 0xfc600000,
-+ .end = 0xfc601fff,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = gic_spi(100),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device sata_device = {
-+ .name = "sata_rcar",
-+ .id = -1,
-+ .resource = sata_resources,
-+ .num_resources = ARRAY_SIZE(sata_resources),
-+ .dev = {
-+ .dma_mask = &sata_device.dev.coherent_dma_mask,
-+ .coherent_dma_mask = DMA_BIT_MASK(32),
-+ },
-+};
-+
- static struct platform_device *r8a7779_early_devices[] __initdata = {
- &scif0_device,
- &scif1_device,
-@@ -315,6 +340,7 @@ static struct platform_device *r8a7779_e
- &i2c1_device,
- &i2c2_device,
- &i2c3_device,
-+ &sata_device,
- };
-
- static struct platform_device *r8a7779_late_devices[] __initdata = {
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Wed Feb 27 20:03:20 2013
-From: Simon Horman <horms+renesas@verge.net.au>
-Date: Thu, 28 Feb 2013 13:03:04 +0900
-Subject: [PATCH 4/4] ARM: shmobile: r8a7779: add I2C driver support
-To: ltsi-dev@lists.linuxfoundation.org
-Cc: Magnus Damm <magnus.damm@gmail.com>, Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Message-ID: <1362024184-27864-5-git-send-email-horms+renesas@verge.net.au>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-This patch enable R-Car I2C driver
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Simon Horman <horms@verge.net.au>
-(cherry picked from commit ccc2a27b15c978334927cea9f1156f019a01b833)
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- arch/arm/configs/marzen_defconfig | 2
- arch/arm/mach-shmobile/setup-r8a7779.c | 77 +++++++++++++++++++++++++++++++++
- 2 files changed, 79 insertions(+)
-
---- a/arch/arm/configs/marzen_defconfig
-+++ b/arch/arm/configs/marzen_defconfig
-@@ -69,6 +69,8 @@ CONFIG_SERIAL_SH_SCI=y
- CONFIG_SERIAL_SH_SCI_NR_UARTS=6
- CONFIG_SERIAL_SH_SCI_CONSOLE=y
- # CONFIG_HW_RANDOM is not set
-+CONFIG_I2C=y
-+CONFIG_I2C_RCAR=y
- CONFIG_GPIO_SYSFS=y
- # CONFIG_HWMON is not set
- CONFIG_SSB=y
---- a/arch/arm/mach-shmobile/setup-r8a7779.c
-+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
-@@ -229,6 +229,79 @@ static struct platform_device tmu01_devi
- .num_resources = ARRAY_SIZE(tmu01_resources),
- };
-
-+/* I2C */
-+static struct resource rcar_i2c0_res[] = {
-+ {
-+ .start = 0xffc70000,
-+ .end = 0xffc70fff,
-+ .flags = IORESOURCE_MEM,
-+ }, {
-+ .start = gic_spi(79),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device i2c0_device = {
-+ .name = "i2c-rcar",
-+ .id = 0,
-+ .resource = rcar_i2c0_res,
-+ .num_resources = ARRAY_SIZE(rcar_i2c0_res),
-+};
-+
-+static struct resource rcar_i2c1_res[] = {
-+ {
-+ .start = 0xffc71000,
-+ .end = 0xffc71fff,
-+ .flags = IORESOURCE_MEM,
-+ }, {
-+ .start = gic_spi(82),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device i2c1_device = {
-+ .name = "i2c-rcar",
-+ .id = 1,
-+ .resource = rcar_i2c1_res,
-+ .num_resources = ARRAY_SIZE(rcar_i2c1_res),
-+};
-+
-+static struct resource rcar_i2c2_res[] = {
-+ {
-+ .start = 0xffc72000,
-+ .end = 0xffc72fff,
-+ .flags = IORESOURCE_MEM,
-+ }, {
-+ .start = gic_spi(80),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device i2c2_device = {
-+ .name = "i2c-rcar",
-+ .id = 2,
-+ .resource = rcar_i2c2_res,
-+ .num_resources = ARRAY_SIZE(rcar_i2c2_res),
-+};
-+
-+static struct resource rcar_i2c3_res[] = {
-+ {
-+ .start = 0xffc73000,
-+ .end = 0xffc73fff,
-+ .flags = IORESOURCE_MEM,
-+ }, {
-+ .start = gic_spi(81),
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device i2c3_device = {
-+ .name = "i2c-rcar",
-+ .id = 3,
-+ .resource = rcar_i2c3_res,
-+ .num_resources = ARRAY_SIZE(rcar_i2c3_res),
-+};
-+
- static struct platform_device *r8a7779_early_devices[] __initdata = {
- &scif0_device,
- &scif1_device,
-@@ -238,6 +311,10 @@ static struct platform_device *r8a7779_e
- &scif5_device,
- &tmu00_device,
- &tmu01_device,
-+ &i2c0_device,
-+ &i2c1_device,
-+ &i2c2_device,
-+ &i2c3_device,
- };
-
- static struct platform_device *r8a7779_late_devices[] __initdata = {
+++ /dev/null
-From horms@vergenet.net Mon Feb 4 19:50:02 2013
-From: Simon Horman <horms+renesas@verge.net.au>
-Date: Tue, 5 Feb 2013 12:49:54 +0900
-Subject: ARM: shmobile: r8a7779: Correct TMU clock support
-To: ltsi-dev@lists.linuxfoundation.org
-Cc: Greg KH <gregkh@linuxfoundation.org>
-Message-ID: <1360036194-3787-2-git-send-email-horms+renesas@verge.net.au>
-
-
-During code review it was noticed that the clock value for
-TMU01 was incorrect and the value for TMU02 was missing.
-
-For reference: As of 3.8-rc6 there are no in-tree consumes of these clocks.
-
-Reported-by: Denis Oliver Kropp <dok@directfb.org>
-Reviewed-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-(cherry picked from commit 58079fa7d54a0929d304054ee759187a2ccd3cdf)
-
-Conflicts:
- arch/arm/mach-shmobile/clock-r8a7779.c
-
-N.B: commit is in the renesas tree on kernel.org and intended
-for inclusion in 3.9.
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- arch/arm/mach-shmobile/clock-r8a7779.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/arch/arm/mach-shmobile/clock-r8a7779.c
-+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
-@@ -142,7 +142,8 @@ static struct clk_lookup lookups[] = {
-
- /* MSTP32 clocks */
- CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP016]), /* TMU00 */
-- CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP016]), /* TMU01 */
-+ CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP015]), /* TMU01 */
-+ CLKDEV_DEV_ID("sh_tmu.2", &mstp_clks[MSTP014]), /* TMU02 */
- CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
- CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
- CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Wed Feb 27 20:03:27 2013
-From: Simon Horman <horms+renesas@verge.net.au>
-Date: Thu, 28 Feb 2013 13:03:01 +0900
-Subject: [PATCH 1/4] i2c: add Renesas R-Car I2C driver
-To: ltsi-dev@lists.linuxfoundation.org
-Cc: Magnus Damm <magnus.damm@gmail.com>, Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Message-ID: <1362024184-27864-2-git-send-email-horms+renesas@verge.net.au>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-R-Car I2C is similar with SH7760 I2C.
-But the SH7760 I2C driver had many workaround operations, since H/W had bugs.
-Thus, it was pointless to keep compatible between SH7760 and R-Car I2C drivers.
-This patch creates new Renesas R-Car I2C driver.
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-(cherry picked from commit 6ccbe607132bd823abbad8d32b13af89161707da)
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- drivers/i2c/busses/Kconfig | 10
- drivers/i2c/busses/Makefile | 1
- drivers/i2c/busses/i2c-rcar.c | 709 ++++++++++++++++++++++++++++++++++++++++++
- include/linux/i2c/i2c-rcar.h | 10
- 4 files changed, 730 insertions(+)
- create mode 100644 drivers/i2c/busses/i2c-rcar.c
- create mode 100644 include/linux/i2c/i2c-rcar.h
-
---- a/drivers/i2c/busses/Kconfig
-+++ b/drivers/i2c/busses/Kconfig
-@@ -723,6 +723,16 @@ config I2C_XLR
- This driver can also be built as a module. If so, the module
- will be called i2c-xlr.
-
-+config I2C_RCAR
-+ tristate "Renesas R-Car I2C Controller"
-+ depends on ARCH_SHMOBILE && I2C
-+ help
-+ If you say yes to this option, support will be included for the
-+ R-Car I2C controller.
-+
-+ This driver can also be built as a module. If so, the module
-+ will be called i2c-rcar.
-+
- comment "External I2C/SMBus adapter drivers"
-
- config I2C_DIOLAN_U2C
---- a/drivers/i2c/busses/Makefile
-+++ b/drivers/i2c/busses/Makefile
-@@ -72,6 +72,7 @@ obj-$(CONFIG_I2C_VERSATILE) += i2c-versa
- obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
- obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o
- obj-$(CONFIG_I2C_XLR) += i2c-xlr.o
-+obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o
-
- # External I2C/SMBus adapter drivers
- obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o
---- /dev/null
-+++ b/drivers/i2c/busses/i2c-rcar.c
-@@ -0,0 +1,709 @@
-+/*
-+ * drivers/i2c/busses/i2c-rcar.c
-+ *
-+ * Copyright (C) 2012 Renesas Solutions Corp.
-+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-+ *
-+ * This file is based on the drivers/i2c/busses/i2c-sh7760.c
-+ * (c) 2005-2008 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau@msc-ge.com>
-+ *
-+ * This file used out-of-tree driver i2c-rcar.c
-+ * Copyright (C) 2011-2012 Renesas Electronics Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+#include <linux/clk.h>
-+#include <linux/delay.h>
-+#include <linux/err.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/i2c.h>
-+#include <linux/i2c/i2c-rcar.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/slab.h>
-+#include <linux/spinlock.h>
-+
-+/* register offsets */
-+#define ICSCR 0x00 /* slave ctrl */
-+#define ICMCR 0x04 /* master ctrl */
-+#define ICSSR 0x08 /* slave status */
-+#define ICMSR 0x0C /* master status */
-+#define ICSIER 0x10 /* slave irq enable */
-+#define ICMIER 0x14 /* master irq enable */
-+#define ICCCR 0x18 /* clock dividers */
-+#define ICSAR 0x1C /* slave address */
-+#define ICMAR 0x20 /* master address */
-+#define ICRXTX 0x24 /* data port */
-+
-+/* ICMCR */
-+#define MDBS (1 << 7) /* non-fifo mode switch */
-+#define FSCL (1 << 6) /* override SCL pin */
-+#define FSDA (1 << 5) /* override SDA pin */
-+#define OBPC (1 << 4) /* override pins */
-+#define MIE (1 << 3) /* master if enable */
-+#define TSBE (1 << 2)
-+#define FSB (1 << 1) /* force stop bit */
-+#define ESG (1 << 0) /* en startbit gen */
-+
-+/* ICMSR */
-+#define MNR (1 << 6) /* nack received */
-+#define MAL (1 << 5) /* arbitration lost */
-+#define MST (1 << 4) /* sent a stop */
-+#define MDE (1 << 3)
-+#define MDT (1 << 2)
-+#define MDR (1 << 1)
-+#define MAT (1 << 0) /* slave addr xfer done */
-+
-+/* ICMIE */
-+#define MNRE (1 << 6) /* nack irq en */
-+#define MALE (1 << 5) /* arblos irq en */
-+#define MSTE (1 << 4) /* stop irq en */
-+#define MDEE (1 << 3)
-+#define MDTE (1 << 2)
-+#define MDRE (1 << 1)
-+#define MATE (1 << 0) /* address sent irq en */
-+
-+
-+enum {
-+ RCAR_BUS_PHASE_ADDR,
-+ RCAR_BUS_PHASE_DATA,
-+ RCAR_BUS_PHASE_STOP,
-+};
-+
-+enum {
-+ RCAR_IRQ_CLOSE,
-+ RCAR_IRQ_OPEN_FOR_SEND,
-+ RCAR_IRQ_OPEN_FOR_RECV,
-+ RCAR_IRQ_OPEN_FOR_STOP,
-+};
-+
-+/*
-+ * flags
-+ */
-+#define ID_LAST_MSG (1 << 0)
-+#define ID_IOERROR (1 << 1)
-+#define ID_DONE (1 << 2)
-+#define ID_ARBLOST (1 << 3)
-+#define ID_NACK (1 << 4)
-+
-+struct rcar_i2c_priv {
-+ void __iomem *io;
-+ struct i2c_adapter adap;
-+ struct i2c_msg *msg;
-+
-+ spinlock_t lock;
-+ wait_queue_head_t wait;
-+
-+ int pos;
-+ int irq;
-+ u32 icccr;
-+ u32 flags;
-+};
-+
-+#define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent)
-+#define rcar_i2c_is_recv(p) ((p)->msg->flags & I2C_M_RD)
-+
-+#define rcar_i2c_flags_set(p, f) ((p)->flags |= (f))
-+#define rcar_i2c_flags_has(p, f) ((p)->flags & (f))
-+
-+#define LOOP_TIMEOUT 1024
-+
-+/*
-+ * basic functions
-+ */
-+static void rcar_i2c_write(struct rcar_i2c_priv *priv, int reg, u32 val)
-+{
-+ writel(val, priv->io + reg);
-+}
-+
-+static u32 rcar_i2c_read(struct rcar_i2c_priv *priv, int reg)
-+{
-+ return readl(priv->io + reg);
-+}
-+
-+static void rcar_i2c_init(struct rcar_i2c_priv *priv)
-+{
-+ /*
-+ * reset slave mode.
-+ * slave mode is not used on this driver
-+ */
-+ rcar_i2c_write(priv, ICSIER, 0);
-+ rcar_i2c_write(priv, ICSAR, 0);
-+ rcar_i2c_write(priv, ICSCR, 0);
-+ rcar_i2c_write(priv, ICSSR, 0);
-+
-+ /* reset master mode */
-+ rcar_i2c_write(priv, ICMIER, 0);
-+ rcar_i2c_write(priv, ICMCR, 0);
-+ rcar_i2c_write(priv, ICMSR, 0);
-+ rcar_i2c_write(priv, ICMAR, 0);
-+}
-+
-+static void rcar_i2c_irq_mask(struct rcar_i2c_priv *priv, int open)
-+{
-+ u32 val = MNRE | MALE | MSTE | MATE; /* default */
-+
-+ switch (open) {
-+ case RCAR_IRQ_OPEN_FOR_SEND:
-+ val |= MDEE; /* default + send */
-+ break;
-+ case RCAR_IRQ_OPEN_FOR_RECV:
-+ val |= MDRE; /* default + read */
-+ break;
-+ case RCAR_IRQ_OPEN_FOR_STOP:
-+ val = MSTE; /* stop irq only */
-+ break;
-+ case RCAR_IRQ_CLOSE:
-+ default:
-+ val = 0; /* all close */
-+ break;
-+ }
-+ rcar_i2c_write(priv, ICMIER, val);
-+}
-+
-+static void rcar_i2c_set_addr(struct rcar_i2c_priv *priv, u32 recv)
-+{
-+ rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | recv);
-+}
-+
-+/*
-+ * bus control functions
-+ */
-+static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
-+{
-+ int i;
-+
-+ for (i = 0; i < LOOP_TIMEOUT; i++) {
-+ /* make sure that bus is not busy */
-+ if (!(rcar_i2c_read(priv, ICMCR) & FSDA))
-+ return 0;
-+ udelay(1);
-+ }
-+
-+ return -EBUSY;
-+}
-+
-+static void rcar_i2c_bus_phase(struct rcar_i2c_priv *priv, int phase)
-+{
-+ switch (phase) {
-+ case RCAR_BUS_PHASE_ADDR:
-+ rcar_i2c_write(priv, ICMCR, MDBS | MIE | ESG);
-+ break;
-+ case RCAR_BUS_PHASE_DATA:
-+ rcar_i2c_write(priv, ICMCR, MDBS | MIE);
-+ break;
-+ case RCAR_BUS_PHASE_STOP:
-+ rcar_i2c_write(priv, ICMCR, MDBS | MIE | FSB);
-+ break;
-+ }
-+}
-+
-+/*
-+ * clock function
-+ */
-+static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
-+ u32 bus_speed,
-+ struct device *dev)
-+{
-+ struct clk *clkp = clk_get(NULL, "peripheral_clk");
-+ u32 scgd, cdf;
-+ u32 round, ick;
-+ u32 scl;
-+
-+ if (!clkp) {
-+ dev_err(dev, "there is no peripheral_clk\n");
-+ return -EIO;
-+ }
-+
-+ /*
-+ * calculate SCL clock
-+ * see
-+ * ICCCR
-+ *
-+ * ick = clkp / (1 + CDF)
-+ * SCL = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick])
-+ *
-+ * ick : I2C internal clock < 20 MHz
-+ * ticf : I2C SCL falling time = 35 ns here
-+ * tr : I2C SCL rising time = 200 ns here
-+ * intd : LSI internal delay = 50 ns here
-+ * clkp : peripheral_clk
-+ * F[] : integer up-valuation
-+ */
-+ for (cdf = 0; cdf < 4; cdf++) {
-+ ick = clk_get_rate(clkp) / (1 + cdf);
-+ if (ick < 20000000)
-+ goto ick_find;
-+ }
-+ dev_err(dev, "there is no best CDF\n");
-+ return -EIO;
-+
-+ick_find:
-+ /*
-+ * it is impossible to calculate large scale
-+ * number on u32. separate it
-+ *
-+ * F[(ticf + tr + intd) * ick]
-+ * = F[(35 + 200 + 50)ns * ick]
-+ * = F[285 * ick / 1000000000]
-+ * = F[(ick / 1000000) * 285 / 1000]
-+ */
-+ round = (ick + 500000) / 1000000 * 285;
-+ round = (round + 500) / 1000;
-+
-+ /*
-+ * SCL = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick])
-+ *
-+ * Calculation result (= SCL) should be less than
-+ * bus_speed for hardware safety
-+ */
-+ for (scgd = 0; scgd < 0x40; scgd++) {
-+ scl = ick / (20 + (scgd * 8) + round);
-+ if (scl <= bus_speed)
-+ goto scgd_find;
-+ }
-+ dev_err(dev, "it is impossible to calculate best SCL\n");
-+ return -EIO;
-+
-+scgd_find:
-+ dev_dbg(dev, "clk %d/%d(%lu), round %u, CDF:0x%x, SCGD: 0x%x\n",
-+ scl, bus_speed, clk_get_rate(clkp), round, cdf, scgd);
-+
-+ /*
-+ * keep icccr value
-+ */
-+ priv->icccr = (scgd << 2 | cdf);
-+
-+ return 0;
-+}
-+
-+static void rcar_i2c_clock_start(struct rcar_i2c_priv *priv)
-+{
-+ rcar_i2c_write(priv, ICCCR, priv->icccr);
-+}
-+
-+/*
-+ * status functions
-+ */
-+static u32 rcar_i2c_status_get(struct rcar_i2c_priv *priv)
-+{
-+ return rcar_i2c_read(priv, ICMSR);
-+}
-+
-+#define rcar_i2c_status_clear(priv) rcar_i2c_status_bit_clear(priv, 0xffffffff)
-+static void rcar_i2c_status_bit_clear(struct rcar_i2c_priv *priv, u32 bit)
-+{
-+ rcar_i2c_write(priv, ICMSR, ~bit);
-+}
-+
-+/*
-+ * recv/send functions
-+ */
-+static int rcar_i2c_recv(struct rcar_i2c_priv *priv)
-+{
-+ rcar_i2c_set_addr(priv, 1);
-+ rcar_i2c_status_clear(priv);
-+ rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_ADDR);
-+ rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_RECV);
-+
-+ return 0;
-+}
-+
-+static int rcar_i2c_send(struct rcar_i2c_priv *priv)
-+{
-+ int ret;
-+
-+ /*
-+ * It should check bus status when send case
-+ */
-+ ret = rcar_i2c_bus_barrier(priv);
-+ if (ret < 0)
-+ return ret;
-+
-+ rcar_i2c_set_addr(priv, 0);
-+ rcar_i2c_status_clear(priv);
-+ rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_ADDR);
-+ rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_SEND);
-+
-+ return 0;
-+}
-+
-+#define rcar_i2c_send_restart(priv) rcar_i2c_status_bit_clear(priv, (MAT | MDE))
-+#define rcar_i2c_recv_restart(priv) rcar_i2c_status_bit_clear(priv, (MAT | MDR))
-+
-+/*
-+ * interrupt functions
-+ */
-+static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
-+{
-+ struct i2c_msg *msg = priv->msg;
-+
-+ /*
-+ * FIXME
-+ * sometimes, unknown interrupt happened.
-+ * Do nothing
-+ */
-+ if (!(msr & MDE))
-+ return 0;
-+
-+ /*
-+ * If address transfer phase finished,
-+ * goto data phase.
-+ */
-+ if (msr & MAT)
-+ rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_DATA);
-+
-+ if (priv->pos < msg->len) {
-+ /*
-+ * Prepare next data to ICRXTX register.
-+ * This data will go to _SHIFT_ register.
-+ *
-+ * *
-+ * [ICRXTX] -> [SHIFT] -> [I2C bus]
-+ */
-+ rcar_i2c_write(priv, ICRXTX, msg->buf[priv->pos]);
-+ priv->pos++;
-+
-+ } else {
-+ /*
-+ * The last data was pushed to ICRXTX on _PREV_ empty irq.
-+ * It is on _SHIFT_ register, and will sent to I2C bus.
-+ *
-+ * *
-+ * [ICRXTX] -> [SHIFT] -> [I2C bus]
-+ */
-+
-+ if (priv->flags & ID_LAST_MSG)
-+ /*
-+ * If current msg is the _LAST_ msg,
-+ * prepare stop condition here.
-+ * ID_DONE will be set on STOP irq.
-+ */
-+ rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP);
-+ else
-+ /*
-+ * If current msg is _NOT_ last msg,
-+ * it doesn't call stop phase.
-+ * thus, there is no STOP irq.
-+ * return ID_DONE here.
-+ */
-+ return ID_DONE;
-+ }
-+
-+ rcar_i2c_send_restart(priv);
-+
-+ return 0;
-+}
-+
-+static int rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
-+{
-+ struct i2c_msg *msg = priv->msg;
-+
-+ /*
-+ * FIXME
-+ * sometimes, unknown interrupt happened.
-+ * Do nothing
-+ */
-+ if (!(msr & MDR))
-+ return 0;
-+
-+ if (msr & MAT) {
-+ /*
-+ * Address transfer phase finished,
-+ * but, there is no data at this point.
-+ * Do nothing.
-+ */
-+ } else if (priv->pos < msg->len) {
-+ /*
-+ * get received data
-+ */
-+ msg->buf[priv->pos] = rcar_i2c_read(priv, ICRXTX);
-+ priv->pos++;
-+ }
-+
-+ /*
-+ * If next received data is the _LAST_,
-+ * go to STOP phase,
-+ * otherwise, go to DATA phase.
-+ */
-+ if (priv->pos + 1 >= msg->len)
-+ rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP);
-+ else
-+ rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_DATA);
-+
-+ rcar_i2c_recv_restart(priv);
-+
-+ return 0;
-+}
-+
-+static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
-+{
-+ struct rcar_i2c_priv *priv = ptr;
-+ struct device *dev = rcar_i2c_priv_to_dev(priv);
-+ u32 msr;
-+
-+ /*-------------- spin lock -----------------*/
-+ spin_lock(&priv->lock);
-+
-+ msr = rcar_i2c_status_get(priv);
-+
-+ /*
-+ * Arbitration lost
-+ */
-+ if (msr & MAL) {
-+ /*
-+ * CAUTION
-+ *
-+ * When arbitration lost, device become _slave_ mode.
-+ */
-+ dev_dbg(dev, "Arbitration Lost\n");
-+ rcar_i2c_flags_set(priv, (ID_DONE | ID_ARBLOST));
-+ goto out;
-+ }
-+
-+ /*
-+ * Stop
-+ */
-+ if (msr & MST) {
-+ dev_dbg(dev, "Stop\n");
-+ rcar_i2c_flags_set(priv, ID_DONE);
-+ goto out;
-+ }
-+
-+ /*
-+ * Nack
-+ */
-+ if (msr & MNR) {
-+ dev_dbg(dev, "Nack\n");
-+
-+ /* go to stop phase */
-+ rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP);
-+ rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_STOP);
-+ rcar_i2c_flags_set(priv, ID_NACK);
-+ goto out;
-+ }
-+
-+ /*
-+ * recv/send
-+ */
-+ if (rcar_i2c_is_recv(priv))
-+ rcar_i2c_flags_set(priv, rcar_i2c_irq_recv(priv, msr));
-+ else
-+ rcar_i2c_flags_set(priv, rcar_i2c_irq_send(priv, msr));
-+
-+out:
-+ if (rcar_i2c_flags_has(priv, ID_DONE)) {
-+ rcar_i2c_irq_mask(priv, RCAR_IRQ_CLOSE);
-+ rcar_i2c_status_clear(priv);
-+ wake_up(&priv->wait);
-+ }
-+
-+ spin_unlock(&priv->lock);
-+ /*-------------- spin unlock -----------------*/
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
-+ struct i2c_msg *msgs,
-+ int num)
-+{
-+ struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
-+ struct device *dev = rcar_i2c_priv_to_dev(priv);
-+ unsigned long flags;
-+ int i, ret, timeout;
-+
-+ pm_runtime_get_sync(dev);
-+
-+ /*-------------- spin lock -----------------*/
-+ spin_lock_irqsave(&priv->lock, flags);
-+
-+ rcar_i2c_init(priv);
-+ rcar_i2c_clock_start(priv);
-+
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+ /*-------------- spin unlock -----------------*/
-+
-+ ret = -EINVAL;
-+ for (i = 0; i < num; i++) {
-+ /*-------------- spin lock -----------------*/
-+ spin_lock_irqsave(&priv->lock, flags);
-+
-+ /* init each data */
-+ priv->msg = &msgs[i];
-+ priv->pos = 0;
-+ priv->flags = 0;
-+ if (priv->msg == &msgs[num - 1])
-+ rcar_i2c_flags_set(priv, ID_LAST_MSG);
-+
-+ /* start send/recv */
-+ if (rcar_i2c_is_recv(priv))
-+ ret = rcar_i2c_recv(priv);
-+ else
-+ ret = rcar_i2c_send(priv);
-+
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+ /*-------------- spin unlock -----------------*/
-+
-+ if (ret < 0)
-+ break;
-+
-+ /*
-+ * wait result
-+ */
-+ timeout = wait_event_timeout(priv->wait,
-+ rcar_i2c_flags_has(priv, ID_DONE),
-+ 5 * HZ);
-+ if (!timeout) {
-+ ret = -ETIMEDOUT;
-+ break;
-+ }
-+
-+ /*
-+ * error handling
-+ */
-+ if (rcar_i2c_flags_has(priv, ID_NACK)) {
-+ ret = -EREMOTEIO;
-+ break;
-+ }
-+
-+ if (rcar_i2c_flags_has(priv, ID_ARBLOST)) {
-+ ret = -EAGAIN;
-+ break;
-+ }
-+
-+ if (rcar_i2c_flags_has(priv, ID_IOERROR)) {
-+ ret = -EIO;
-+ break;
-+ }
-+
-+ ret = i + 1; /* The number of transfer */
-+ }
-+
-+ pm_runtime_put(dev);
-+
-+ if (ret < 0)
-+ dev_err(dev, "error %d : %x\n", ret, priv->flags);
-+
-+ return ret;
-+}
-+
-+static u32 rcar_i2c_func(struct i2c_adapter *adap)
-+{
-+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-+}
-+
-+static const struct i2c_algorithm rcar_i2c_algo = {
-+ .master_xfer = rcar_i2c_master_xfer,
-+ .functionality = rcar_i2c_func,
-+};
-+
-+static int __devinit rcar_i2c_probe(struct platform_device *pdev)
-+{
-+ struct i2c_rcar_platform_data *pdata = pdev->dev.platform_data;
-+ struct rcar_i2c_priv *priv;
-+ struct i2c_adapter *adap;
-+ struct resource *res;
-+ struct device *dev = &pdev->dev;
-+ u32 bus_speed;
-+ int ret;
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!res) {
-+ dev_err(dev, "no mmio resources\n");
-+ return -ENODEV;
-+ }
-+
-+ priv = devm_kzalloc(dev, sizeof(struct rcar_i2c_priv), GFP_KERNEL);
-+ if (!priv) {
-+ dev_err(dev, "no mem for private data\n");
-+ return -ENOMEM;
-+ }
-+
-+ bus_speed = 100000; /* default 100 kHz */
-+ if (pdata && pdata->bus_speed)
-+ bus_speed = pdata->bus_speed;
-+ ret = rcar_i2c_clock_calculate(priv, bus_speed, dev);
-+ if (ret < 0)
-+ return ret;
-+
-+ priv->io = devm_ioremap(dev, res->start, resource_size(res));
-+ if (!priv->io) {
-+ dev_err(dev, "cannot ioremap\n");
-+ return -ENODEV;
-+ }
-+
-+ priv->irq = platform_get_irq(pdev, 0);
-+ init_waitqueue_head(&priv->wait);
-+ spin_lock_init(&priv->lock);
-+
-+ adap = &priv->adap;
-+ adap->nr = pdev->id;
-+ adap->algo = &rcar_i2c_algo;
-+ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
-+ adap->retries = 3;
-+ adap->dev.parent = dev;
-+ i2c_set_adapdata(adap, priv);
-+ strlcpy(adap->name, pdev->name, sizeof(adap->name));
-+
-+ ret = devm_request_irq(dev, priv->irq, rcar_i2c_irq, 0,
-+ dev_name(dev), priv);
-+ if (ret < 0) {
-+ dev_err(dev, "cannot get irq %d\n", priv->irq);
-+ return ret;
-+ }
-+
-+ ret = i2c_add_numbered_adapter(adap);
-+ if (ret < 0) {
-+ dev_err(dev, "reg adap failed: %d\n", ret);
-+ return ret;
-+ }
-+
-+ pm_runtime_enable(dev);
-+ platform_set_drvdata(pdev, priv);
-+
-+ dev_info(dev, "probed\n");
-+
-+ return 0;
-+}
-+
-+static int __devexit rcar_i2c_remove(struct platform_device *pdev)
-+{
-+ struct rcar_i2c_priv *priv = platform_get_drvdata(pdev);
-+ struct device *dev = &pdev->dev;
-+
-+ i2c_del_adapter(&priv->adap);
-+ pm_runtime_disable(dev);
-+
-+ return 0;
-+}
-+
-+static struct platform_driver rcar_i2c_drv = {
-+ .driver = {
-+ .name = "i2c-rcar",
-+ .owner = THIS_MODULE,
-+ },
-+ .probe = rcar_i2c_probe,
-+ .remove = __devexit_p(rcar_i2c_remove),
-+};
-+
-+module_platform_driver(rcar_i2c_drv);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Renesas R-Car I2C bus driver");
-+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
---- /dev/null
-+++ b/include/linux/i2c/i2c-rcar.h
-@@ -0,0 +1,10 @@
-+#ifndef __I2C_R_CAR_H__
-+#define __I2C_R_CAR_H__
-+
-+#include <linux/platform_device.h>
-+
-+struct i2c_rcar_platform_data {
-+ u32 bus_speed;
-+};
-+
-+#endif /* __I2C_R_CAR_H__ */
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Wed Feb 27 20:03:23 2013
-From: Simon Horman <horms+renesas@verge.net.au>
-Date: Thu, 28 Feb 2013 13:03:03 +0900
-Subject: [PATCH 3/4] i2c: rcar: fix section mismatch
-To: ltsi-dev@lists.linuxfoundation.org
-Cc: Magnus Damm <magnus.damm@gmail.com>, Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Message-ID: <1362024184-27864-4-git-send-email-horms+renesas@verge.net.au>
-
-
-From: Wolfram Sang <w.sang@pengutronix.de>
-
-Give the driver struct a name according to the 'standard' to fix:
-
-WARNING: vmlinux.o(.data+0x11798): Section mismatch in reference from the variable rcar_i2c_drv to the function .devinit.text:rcar_i2c_probe()
-...
-WARNING: vmlinux.o(.data+0x1179c): Section mismatch in reference from the variable rcar_i2c_drv to the function .devexit.text:rcar_i2c_remove()
-
-Reported-by: Simon Horman <horms@verge.net.au>
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-(cherry picked from commit 45fd5e4ad2052101b4ceda5fdf4b003c428ebdfc)
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- drivers/i2c/busses/i2c-rcar.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/i2c/busses/i2c-rcar.c
-+++ b/drivers/i2c/busses/i2c-rcar.c
-@@ -693,7 +693,7 @@ static int __devexit rcar_i2c_remove(str
- return 0;
- }
-
--static struct platform_driver rcar_i2c_drv = {
-+static struct platform_driver rcar_i2c_driver = {
- .driver = {
- .name = "i2c-rcar",
- .owner = THIS_MODULE,
-@@ -702,7 +702,7 @@ static struct platform_driver rcar_i2c_d
- .remove = __devexit_p(rcar_i2c_remove),
- };
-
--module_platform_driver(rcar_i2c_drv);
-+module_platform_driver(rcar_i2c_driver);
-
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("Renesas R-Car I2C bus driver");
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Wed Feb 27 20:03:30 2013
-From: Simon Horman <horms+renesas@verge.net.au>
-Date: Thu, 28 Feb 2013 13:03:02 +0900
-Subject: [PATCH 2/4] i2c: rcar: used devm_request_and_ioremap() instead of devm_ioremap()
-To: ltsi-dev@lists.linuxfoundation.org
-Cc: Magnus Damm <magnus.damm@gmail.com>, Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Message-ID: <1362024184-27864-3-git-send-email-horms+renesas@verge.net.au>
-
-
-From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-
-Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-(cherry picked from commit b53f4baf8b26303fc75ef3b00cf5e7398b58efd4)
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- drivers/i2c/busses/i2c-rcar.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/i2c/busses/i2c-rcar.c
-+++ b/drivers/i2c/busses/i2c-rcar.c
-@@ -642,7 +642,7 @@ static int __devinit rcar_i2c_probe(stru
- if (ret < 0)
- return ret;
-
-- priv->io = devm_ioremap(dev, res->start, resource_size(res));
-+ priv->io = devm_request_and_ioremap(dev, res);
- if (!priv->io) {
- dev_err(dev, "cannot ioremap\n");
- return -ENODEV;
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Mon Feb 25 14:26:17 2013
-From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
-Date: Tue, 26 Feb 2013 02:26:44 +0300
-Subject: libata: add R-Car SATA driver
-To: ltsi-dev@lists.linuxfoundation.org
-Cc: vladimir.barinov@cogentembedded.com
-Message-ID: <201302260226.45183.sergei.shtylyov@cogentembedded.com>
-
-
-From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
-
-Add Renesas R-Car on-chip 3Gbps SATA controller driver.
-
-Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
-[Sergei: few bugs fixed, significant cleanup]
-Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
-Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-(cherry picked from commit 163cf81d266f017d718ef786fbbb6b2513ce7ec3)
-
----
-This driver (already merged by Linus) is intended for the Marzen patch series.
-The platform code, device tree node, and the 'marzen_defconfig' change will
-hopefully follow...
-
-Changes from the upstream version:
-- devm_clk_get() is not available in 3.4, so had to replace the call with
- clk_{get|put}() calls.
-
- drivers/ata/Kconfig | 8
- drivers/ata/Makefile | 1
- drivers/ata/sata_rcar.c | 912 ++++++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 921 insertions(+)
-
---- a/drivers/ata/Kconfig
-+++ b/drivers/ata/Kconfig
-@@ -239,6 +239,14 @@ config SATA_PROMISE
-
- If unsure, say N.
-
-+config SATA_RCAR
-+ tristate "Renesas R-Car SATA support"
-+ depends on ARCH_SHMOBILE && ARCH_R8A7779
-+ help
-+ This option enables support for Renesas R-Car Serial ATA.
-+
-+ If unsure, say N.
-+
- config SATA_SIL
- tristate "Silicon Image SATA support"
- depends on PCI
---- a/drivers/ata/Makefile
-+++ b/drivers/ata/Makefile
-@@ -22,6 +22,7 @@ obj-$(CONFIG_ATA_PIIX) += ata_piix.o
- obj-$(CONFIG_SATA_MV) += sata_mv.o
- obj-$(CONFIG_SATA_NV) += sata_nv.o
- obj-$(CONFIG_SATA_PROMISE) += sata_promise.o
-+obj-$(CONFIG_SATA_RCAR) += sata_rcar.o
- obj-$(CONFIG_SATA_SIL) += sata_sil.o
- obj-$(CONFIG_SATA_SIS) += sata_sis.o
- obj-$(CONFIG_SATA_SVW) += sata_svw.o
---- /dev/null
-+++ b/drivers/ata/sata_rcar.c
-@@ -0,0 +1,912 @@
-+/*
-+ * Renesas R-Car SATA driver
-+ *
-+ * Author: Vladimir Barinov <source@cogentembedded.com>
-+ * Copyright (C) 2013 Cogent Embedded, Inc.
-+ * Copyright (C) 2013 Renesas Solutions Corp.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2 of the License, or (at your
-+ * option) any later version.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/ata.h>
-+#include <linux/libata.h>
-+#include <linux/platform_device.h>
-+#include <linux/clk.h>
-+
-+#define DRV_NAME "sata_rcar"
-+
-+/* SH-Navi2G/ATAPI-ATA compatible task registers */
-+#define DATA_REG 0x100
-+#define SDEVCON_REG 0x138
-+
-+/* SH-Navi2G/ATAPI module compatible control registers */
-+#define ATAPI_CONTROL1_REG 0x180
-+#define ATAPI_STATUS_REG 0x184
-+#define ATAPI_INT_ENABLE_REG 0x188
-+#define ATAPI_DTB_ADR_REG 0x198
-+#define ATAPI_DMA_START_ADR_REG 0x19C
-+#define ATAPI_DMA_TRANS_CNT_REG 0x1A0
-+#define ATAPI_CONTROL2_REG 0x1A4
-+#define ATAPI_SIG_ST_REG 0x1B0
-+#define ATAPI_BYTE_SWAP_REG 0x1BC
-+
-+/* ATAPI control 1 register (ATAPI_CONTROL1) bits */
-+#define ATAPI_CONTROL1_ISM BIT(16)
-+#define ATAPI_CONTROL1_DTA32M BIT(11)
-+#define ATAPI_CONTROL1_RESET BIT(7)
-+#define ATAPI_CONTROL1_DESE BIT(3)
-+#define ATAPI_CONTROL1_RW BIT(2)
-+#define ATAPI_CONTROL1_STOP BIT(1)
-+#define ATAPI_CONTROL1_START BIT(0)
-+
-+/* ATAPI status register (ATAPI_STATUS) bits */
-+#define ATAPI_STATUS_SATAINT BIT(11)
-+#define ATAPI_STATUS_DNEND BIT(6)
-+#define ATAPI_STATUS_DEVTRM BIT(5)
-+#define ATAPI_STATUS_DEVINT BIT(4)
-+#define ATAPI_STATUS_ERR BIT(2)
-+#define ATAPI_STATUS_NEND BIT(1)
-+#define ATAPI_STATUS_ACT BIT(0)
-+
-+/* Interrupt enable register (ATAPI_INT_ENABLE) bits */
-+#define ATAPI_INT_ENABLE_SATAINT BIT(11)
-+#define ATAPI_INT_ENABLE_DNEND BIT(6)
-+#define ATAPI_INT_ENABLE_DEVTRM BIT(5)
-+#define ATAPI_INT_ENABLE_DEVINT BIT(4)
-+#define ATAPI_INT_ENABLE_ERR BIT(2)
-+#define ATAPI_INT_ENABLE_NEND BIT(1)
-+#define ATAPI_INT_ENABLE_ACT BIT(0)
-+
-+/* Access control registers for physical layer control register */
-+#define SATAPHYADDR_REG 0x200
-+#define SATAPHYWDATA_REG 0x204
-+#define SATAPHYACCEN_REG 0x208
-+#define SATAPHYRESET_REG 0x20C
-+#define SATAPHYRDATA_REG 0x210
-+#define SATAPHYACK_REG 0x214
-+
-+/* Physical layer control address command register (SATAPHYADDR) bits */
-+#define SATAPHYADDR_PHYRATEMODE BIT(10)
-+#define SATAPHYADDR_PHYCMD_READ BIT(9)
-+#define SATAPHYADDR_PHYCMD_WRITE BIT(8)
-+
-+/* Physical layer control enable register (SATAPHYACCEN) bits */
-+#define SATAPHYACCEN_PHYLANE BIT(0)
-+
-+/* Physical layer control reset register (SATAPHYRESET) bits */
-+#define SATAPHYRESET_PHYRST BIT(1)
-+#define SATAPHYRESET_PHYSRES BIT(0)
-+
-+/* Physical layer control acknowledge register (SATAPHYACK) bits */
-+#define SATAPHYACK_PHYACK BIT(0)
-+
-+/* Serial-ATA HOST control registers */
-+#define BISTCONF_REG 0x102C
-+#define SDATA_REG 0x1100
-+#define SSDEVCON_REG 0x1204
-+
-+#define SCRSSTS_REG 0x1400
-+#define SCRSERR_REG 0x1404
-+#define SCRSCON_REG 0x1408
-+#define SCRSACT_REG 0x140C
-+
-+#define SATAINTSTAT_REG 0x1508
-+#define SATAINTMASK_REG 0x150C
-+
-+/* SATA INT status register (SATAINTSTAT) bits */
-+#define SATAINTSTAT_SERR BIT(3)
-+#define SATAINTSTAT_ATA BIT(0)
-+
-+/* SATA INT mask register (SATAINTSTAT) bits */
-+#define SATAINTMASK_SERRMSK BIT(3)
-+#define SATAINTMASK_ERRMSK BIT(2)
-+#define SATAINTMASK_ERRCRTMSK BIT(1)
-+#define SATAINTMASK_ATAMSK BIT(0)
-+
-+#define SATA_RCAR_INT_MASK (SATAINTMASK_SERRMSK | \
-+ SATAINTMASK_ATAMSK)
-+
-+/* Physical Layer Control Registers */
-+#define SATAPCTLR1_REG 0x43
-+#define SATAPCTLR2_REG 0x52
-+#define SATAPCTLR3_REG 0x5A
-+#define SATAPCTLR4_REG 0x60
-+
-+/* Descriptor table word 0 bit (when DTA32M = 1) */
-+#define SATA_RCAR_DTEND BIT(0)
-+
-+struct sata_rcar_priv {
-+ void __iomem *base;
-+ struct clk *clk;
-+};
-+
-+static void sata_rcar_phy_initialize(struct sata_rcar_priv *priv)
-+{
-+ /* idle state */
-+ iowrite32(0, priv->base + SATAPHYADDR_REG);
-+ /* reset */
-+ iowrite32(SATAPHYRESET_PHYRST, priv->base + SATAPHYRESET_REG);
-+ udelay(10);
-+ /* deassert reset */
-+ iowrite32(0, priv->base + SATAPHYRESET_REG);
-+}
-+
-+static void sata_rcar_phy_write(struct sata_rcar_priv *priv, u16 reg, u32 val,
-+ int group)
-+{
-+ int timeout;
-+
-+ /* deassert reset */
-+ iowrite32(0, priv->base + SATAPHYRESET_REG);
-+ /* lane 1 */
-+ iowrite32(SATAPHYACCEN_PHYLANE, priv->base + SATAPHYACCEN_REG);
-+ /* write phy register value */
-+ iowrite32(val, priv->base + SATAPHYWDATA_REG);
-+ /* set register group */
-+ if (group)
-+ reg |= SATAPHYADDR_PHYRATEMODE;
-+ /* write command */
-+ iowrite32(SATAPHYADDR_PHYCMD_WRITE | reg, priv->base + SATAPHYADDR_REG);
-+ /* wait for ack */
-+ for (timeout = 0; timeout < 100; timeout++) {
-+ val = ioread32(priv->base + SATAPHYACK_REG);
-+ if (val & SATAPHYACK_PHYACK)
-+ break;
-+ }
-+ if (timeout >= 100)
-+ pr_err("%s timeout\n", __func__);
-+ /* idle state */
-+ iowrite32(0, priv->base + SATAPHYADDR_REG);
-+}
-+
-+static void sata_rcar_freeze(struct ata_port *ap)
-+{
-+ struct sata_rcar_priv *priv = ap->host->private_data;
-+
-+ /* mask */
-+ iowrite32(0x7ff, priv->base + SATAINTMASK_REG);
-+
-+ ata_sff_freeze(ap);
-+}
-+
-+static void sata_rcar_thaw(struct ata_port *ap)
-+{
-+ struct sata_rcar_priv *priv = ap->host->private_data;
-+
-+ /* ack */
-+ iowrite32(~SATA_RCAR_INT_MASK, priv->base + SATAINTSTAT_REG);
-+
-+ ata_sff_thaw(ap);
-+
-+ /* unmask */
-+ iowrite32(0x7ff & ~SATA_RCAR_INT_MASK, priv->base + SATAINTMASK_REG);
-+}
-+
-+static void sata_rcar_ioread16_rep(void __iomem *reg, void *buffer, int count)
-+{
-+ u16 *ptr = buffer;
-+
-+ while (count--) {
-+ u16 data = ioread32(reg);
-+
-+ *ptr++ = data;
-+ }
-+}
-+
-+static void sata_rcar_iowrite16_rep(void __iomem *reg, void *buffer, int count)
-+{
-+ const u16 *ptr = buffer;
-+
-+ while (count--)
-+ iowrite32(*ptr++, reg);
-+}
-+
-+static u8 sata_rcar_check_status(struct ata_port *ap)
-+{
-+ return ioread32(ap->ioaddr.status_addr);
-+}
-+
-+static u8 sata_rcar_check_altstatus(struct ata_port *ap)
-+{
-+ return ioread32(ap->ioaddr.altstatus_addr);
-+}
-+
-+static void sata_rcar_set_devctl(struct ata_port *ap, u8 ctl)
-+{
-+ iowrite32(ctl, ap->ioaddr.ctl_addr);
-+}
-+
-+static void sata_rcar_dev_select(struct ata_port *ap, unsigned int device)
-+{
-+ iowrite32(ATA_DEVICE_OBS, ap->ioaddr.device_addr);
-+ ata_sff_pause(ap); /* needed; also flushes, for mmio */
-+}
-+
-+static unsigned int sata_rcar_ata_devchk(struct ata_port *ap,
-+ unsigned int device)
-+{
-+ struct ata_ioports *ioaddr = &ap->ioaddr;
-+ u8 nsect, lbal;
-+
-+ sata_rcar_dev_select(ap, device);
-+
-+ iowrite32(0x55, ioaddr->nsect_addr);
-+ iowrite32(0xaa, ioaddr->lbal_addr);
-+
-+ iowrite32(0xaa, ioaddr->nsect_addr);
-+ iowrite32(0x55, ioaddr->lbal_addr);
-+
-+ iowrite32(0x55, ioaddr->nsect_addr);
-+ iowrite32(0xaa, ioaddr->lbal_addr);
-+
-+ nsect = ioread32(ioaddr->nsect_addr);
-+ lbal = ioread32(ioaddr->lbal_addr);
-+
-+ if (nsect == 0x55 && lbal == 0xaa)
-+ return 1; /* found a device */
-+
-+ return 0; /* nothing found */
-+}
-+
-+static int sata_rcar_wait_after_reset(struct ata_link *link,
-+ unsigned long deadline)
-+{
-+ struct ata_port *ap = link->ap;
-+
-+ ata_msleep(ap, ATA_WAIT_AFTER_RESET);
-+
-+ return ata_sff_wait_ready(link, deadline);
-+}
-+
-+static int sata_rcar_bus_softreset(struct ata_port *ap, unsigned long deadline)
-+{
-+ struct ata_ioports *ioaddr = &ap->ioaddr;
-+
-+ DPRINTK("ata%u: bus reset via SRST\n", ap->print_id);
-+
-+ /* software reset. causes dev0 to be selected */
-+ iowrite32(ap->ctl, ioaddr->ctl_addr);
-+ udelay(20);
-+ iowrite32(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
-+ udelay(20);
-+ iowrite32(ap->ctl, ioaddr->ctl_addr);
-+ ap->last_ctl = ap->ctl;
-+
-+ /* wait the port to become ready */
-+ return sata_rcar_wait_after_reset(&ap->link, deadline);
-+}
-+
-+static int sata_rcar_softreset(struct ata_link *link, unsigned int *classes,
-+ unsigned long deadline)
-+{
-+ struct ata_port *ap = link->ap;
-+ unsigned int devmask = 0;
-+ int rc;
-+ u8 err;
-+
-+ /* determine if device 0 is present */
-+ if (sata_rcar_ata_devchk(ap, 0))
-+ devmask |= 1 << 0;
-+
-+ /* issue bus reset */
-+ DPRINTK("about to softreset, devmask=%x\n", devmask);
-+ rc = sata_rcar_bus_softreset(ap, deadline);
-+ /* if link is occupied, -ENODEV too is an error */
-+ if (rc && (rc != -ENODEV || sata_scr_valid(link))) {
-+ ata_link_err(link, "SRST failed (errno=%d)\n", rc);
-+ return rc;
-+ }
-+
-+ /* determine by signature whether we have ATA or ATAPI devices */
-+ classes[0] = ata_sff_dev_classify(&link->device[0], devmask, &err);
-+
-+ DPRINTK("classes[0]=%u\n", classes[0]);
-+ return 0;
-+}
-+
-+static void sata_rcar_tf_load(struct ata_port *ap,
-+ const struct ata_taskfile *tf)
-+{
-+ struct ata_ioports *ioaddr = &ap->ioaddr;
-+ unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
-+
-+ if (tf->ctl != ap->last_ctl) {
-+ iowrite32(tf->ctl, ioaddr->ctl_addr);
-+ ap->last_ctl = tf->ctl;
-+ ata_wait_idle(ap);
-+ }
-+
-+ if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
-+ iowrite32(tf->hob_feature, ioaddr->feature_addr);
-+ iowrite32(tf->hob_nsect, ioaddr->nsect_addr);
-+ iowrite32(tf->hob_lbal, ioaddr->lbal_addr);
-+ iowrite32(tf->hob_lbam, ioaddr->lbam_addr);
-+ iowrite32(tf->hob_lbah, ioaddr->lbah_addr);
-+ VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
-+ tf->hob_feature,
-+ tf->hob_nsect,
-+ tf->hob_lbal,
-+ tf->hob_lbam,
-+ tf->hob_lbah);
-+ }
-+
-+ if (is_addr) {
-+ iowrite32(tf->feature, ioaddr->feature_addr);
-+ iowrite32(tf->nsect, ioaddr->nsect_addr);
-+ iowrite32(tf->lbal, ioaddr->lbal_addr);
-+ iowrite32(tf->lbam, ioaddr->lbam_addr);
-+ iowrite32(tf->lbah, ioaddr->lbah_addr);
-+ VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
-+ tf->feature,
-+ tf->nsect,
-+ tf->lbal,
-+ tf->lbam,
-+ tf->lbah);
-+ }
-+
-+ if (tf->flags & ATA_TFLAG_DEVICE) {
-+ iowrite32(tf->device, ioaddr->device_addr);
-+ VPRINTK("device 0x%X\n", tf->device);
-+ }
-+
-+ ata_wait_idle(ap);
-+}
-+
-+static void sata_rcar_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
-+{
-+ struct ata_ioports *ioaddr = &ap->ioaddr;
-+
-+ tf->command = sata_rcar_check_status(ap);
-+ tf->feature = ioread32(ioaddr->error_addr);
-+ tf->nsect = ioread32(ioaddr->nsect_addr);
-+ tf->lbal = ioread32(ioaddr->lbal_addr);
-+ tf->lbam = ioread32(ioaddr->lbam_addr);
-+ tf->lbah = ioread32(ioaddr->lbah_addr);
-+ tf->device = ioread32(ioaddr->device_addr);
-+
-+ if (tf->flags & ATA_TFLAG_LBA48) {
-+ iowrite32(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
-+ tf->hob_feature = ioread32(ioaddr->error_addr);
-+ tf->hob_nsect = ioread32(ioaddr->nsect_addr);
-+ tf->hob_lbal = ioread32(ioaddr->lbal_addr);
-+ tf->hob_lbam = ioread32(ioaddr->lbam_addr);
-+ tf->hob_lbah = ioread32(ioaddr->lbah_addr);
-+ iowrite32(tf->ctl, ioaddr->ctl_addr);
-+ ap->last_ctl = tf->ctl;
-+ }
-+}
-+
-+static void sata_rcar_exec_command(struct ata_port *ap,
-+ const struct ata_taskfile *tf)
-+{
-+ DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
-+
-+ iowrite32(tf->command, ap->ioaddr.command_addr);
-+ ata_sff_pause(ap);
-+}
-+
-+static unsigned int sata_rcar_data_xfer(struct ata_device *dev,
-+ unsigned char *buf,
-+ unsigned int buflen, int rw)
-+{
-+ struct ata_port *ap = dev->link->ap;
-+ void __iomem *data_addr = ap->ioaddr.data_addr;
-+ unsigned int words = buflen >> 1;
-+
-+ /* Transfer multiple of 2 bytes */
-+ if (rw == READ)
-+ sata_rcar_ioread16_rep(data_addr, buf, words);
-+ else
-+ sata_rcar_iowrite16_rep(data_addr, buf, words);
-+
-+ /* Transfer trailing byte, if any. */
-+ if (unlikely(buflen & 0x01)) {
-+ unsigned char pad[2] = { };
-+
-+ /* Point buf to the tail of buffer */
-+ buf += buflen - 1;
-+
-+ /*
-+ * Use io*16_rep() accessors here as well to avoid pointlessly
-+ * swapping bytes to and from on the big endian machines...
-+ */
-+ if (rw == READ) {
-+ sata_rcar_ioread16_rep(data_addr, pad, 1);
-+ *buf = pad[0];
-+ } else {
-+ pad[0] = *buf;
-+ sata_rcar_iowrite16_rep(data_addr, pad, 1);
-+ }
-+ words++;
-+ }
-+
-+ return words << 1;
-+}
-+
-+static void sata_rcar_drain_fifo(struct ata_queued_cmd *qc)
-+{
-+ int count;
-+ struct ata_port *ap;
-+
-+ /* We only need to flush incoming data when a command was running */
-+ if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE)
-+ return;
-+
-+ ap = qc->ap;
-+ /* Drain up to 64K of data before we give up this recovery method */
-+ for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ) &&
-+ count < 65536; count += 2)
-+ ioread32(ap->ioaddr.data_addr);
-+
-+ /* Can become DEBUG later */
-+ if (count)
-+ ata_port_dbg(ap, "drained %d bytes to clear DRQ\n", count);
-+}
-+
-+static int sata_rcar_scr_read(struct ata_link *link, unsigned int sc_reg,
-+ u32 *val)
-+{
-+ if (sc_reg > SCR_ACTIVE)
-+ return -EINVAL;
-+
-+ *val = ioread32(link->ap->ioaddr.scr_addr + (sc_reg << 2));
-+ return 0;
-+}
-+
-+static int sata_rcar_scr_write(struct ata_link *link, unsigned int sc_reg,
-+ u32 val)
-+{
-+ if (sc_reg > SCR_ACTIVE)
-+ return -EINVAL;
-+
-+ iowrite32(val, link->ap->ioaddr.scr_addr + (sc_reg << 2));
-+ return 0;
-+}
-+
-+static void sata_rcar_bmdma_fill_sg(struct ata_queued_cmd *qc)
-+{
-+ struct ata_port *ap = qc->ap;
-+ struct ata_bmdma_prd *prd = ap->bmdma_prd;
-+ struct scatterlist *sg;
-+ unsigned int si, pi;
-+
-+ pi = 0;
-+ for_each_sg(qc->sg, sg, qc->n_elem, si) {
-+ u32 addr, sg_len, len;
-+
-+ /*
-+ * Note: h/w doesn't support 64-bit, so we unconditionally
-+ * truncate dma_addr_t to u32.
-+ */
-+ addr = (u32)sg_dma_address(sg);
-+ sg_len = sg_dma_len(sg);
-+
-+ /* H/w transfer count is only 29 bits long, let's be careful */
-+ while (sg_len) {
-+ len = sg_len;
-+ if (len > 0x1ffffffe)
-+ len = 0x1ffffffe;
-+
-+ prd[pi].addr = cpu_to_le32(addr);
-+ prd[pi].flags_len = cpu_to_le32(len);
-+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
-+
-+ pi++;
-+ sg_len -= len;
-+ addr += len;
-+ }
-+ }
-+
-+ /* end-of-table flag */
-+ prd[pi - 1].addr |= cpu_to_le32(SATA_RCAR_DTEND);
-+}
-+
-+static void sata_rcar_qc_prep(struct ata_queued_cmd *qc)
-+{
-+ if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-+ return;
-+
-+ sata_rcar_bmdma_fill_sg(qc);
-+}
-+
-+static void sata_rcar_bmdma_setup(struct ata_queued_cmd *qc)
-+{
-+ struct ata_port *ap = qc->ap;
-+ unsigned int rw = qc->tf.flags & ATA_TFLAG_WRITE;
-+ u32 dmactl;
-+ struct sata_rcar_priv *priv = ap->host->private_data;
-+
-+ /* load PRD table addr. */
-+ mb(); /* make sure PRD table writes are visible to controller */
-+ iowrite32(ap->bmdma_prd_dma, priv->base + ATAPI_DTB_ADR_REG);
-+
-+ /* specify data direction, triple-check start bit is clear */
-+ dmactl = ioread32(priv->base + ATAPI_CONTROL1_REG);
-+ dmactl &= ~(ATAPI_CONTROL1_RW | ATAPI_CONTROL1_STOP);
-+ if (dmactl & ATAPI_CONTROL1_START) {
-+ dmactl &= ~ATAPI_CONTROL1_START;
-+ dmactl |= ATAPI_CONTROL1_STOP;
-+ }
-+ if (!rw)
-+ dmactl |= ATAPI_CONTROL1_RW;
-+ iowrite32(dmactl, priv->base + ATAPI_CONTROL1_REG);
-+
-+ /* issue r/w command */
-+ ap->ops->sff_exec_command(ap, &qc->tf);
-+}
-+
-+static void sata_rcar_bmdma_start(struct ata_queued_cmd *qc)
-+{
-+ struct ata_port *ap = qc->ap;
-+ u32 dmactl;
-+ struct sata_rcar_priv *priv = ap->host->private_data;
-+
-+ /* start host DMA transaction */
-+ dmactl = ioread32(priv->base + ATAPI_CONTROL1_REG);
-+ dmactl |= ATAPI_CONTROL1_START;
-+ iowrite32(dmactl, priv->base + ATAPI_CONTROL1_REG);
-+}
-+
-+static void sata_rcar_bmdma_stop(struct ata_queued_cmd *qc)
-+{
-+ struct ata_port *ap = qc->ap;
-+ struct sata_rcar_priv *priv = ap->host->private_data;
-+ u32 dmactl;
-+
-+ /* force termination of DMA transfer if active */
-+ dmactl = ioread32(priv->base + ATAPI_CONTROL1_REG);
-+ if (dmactl & ATAPI_CONTROL1_START) {
-+ dmactl &= ~ATAPI_CONTROL1_START;
-+ dmactl |= ATAPI_CONTROL1_STOP;
-+ iowrite32(dmactl, priv->base + ATAPI_CONTROL1_REG);
-+ }
-+
-+ /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
-+ ata_sff_dma_pause(ap);
-+}
-+
-+static u8 sata_rcar_bmdma_status(struct ata_port *ap)
-+{
-+ struct sata_rcar_priv *priv = ap->host->private_data;
-+ u32 status;
-+ u8 host_stat = 0;
-+
-+ status = ioread32(priv->base + ATAPI_STATUS_REG);
-+ if (status & ATAPI_STATUS_DEVINT)
-+ host_stat |= ATA_DMA_INTR;
-+ if (status & ATAPI_STATUS_ACT)
-+ host_stat |= ATA_DMA_ACTIVE;
-+
-+ return host_stat;
-+}
-+
-+static struct scsi_host_template sata_rcar_sht = {
-+ ATA_BMDMA_SHT(DRV_NAME),
-+};
-+
-+static struct ata_port_operations sata_rcar_port_ops = {
-+ .inherits = &ata_bmdma_port_ops,
-+
-+ .freeze = sata_rcar_freeze,
-+ .thaw = sata_rcar_thaw,
-+ .softreset = sata_rcar_softreset,
-+
-+ .scr_read = sata_rcar_scr_read,
-+ .scr_write = sata_rcar_scr_write,
-+
-+ .sff_dev_select = sata_rcar_dev_select,
-+ .sff_set_devctl = sata_rcar_set_devctl,
-+ .sff_check_status = sata_rcar_check_status,
-+ .sff_check_altstatus = sata_rcar_check_altstatus,
-+ .sff_tf_load = sata_rcar_tf_load,
-+ .sff_tf_read = sata_rcar_tf_read,
-+ .sff_exec_command = sata_rcar_exec_command,
-+ .sff_data_xfer = sata_rcar_data_xfer,
-+ .sff_drain_fifo = sata_rcar_drain_fifo,
-+
-+ .qc_prep = sata_rcar_qc_prep,
-+
-+ .bmdma_setup = sata_rcar_bmdma_setup,
-+ .bmdma_start = sata_rcar_bmdma_start,
-+ .bmdma_stop = sata_rcar_bmdma_stop,
-+ .bmdma_status = sata_rcar_bmdma_status,
-+};
-+
-+static int sata_rcar_serr_interrupt(struct ata_port *ap)
-+{
-+ struct sata_rcar_priv *priv = ap->host->private_data;
-+ struct ata_eh_info *ehi = &ap->link.eh_info;
-+ int freeze = 0;
-+ int handled = 0;
-+ u32 serror;
-+
-+ serror = ioread32(priv->base + SCRSERR_REG);
-+ if (!serror)
-+ return 0;
-+
-+ DPRINTK("SError @host_intr: 0x%x\n", serror);
-+
-+ /* first, analyze and record host port events */
-+ ata_ehi_clear_desc(ehi);
-+
-+ if (serror & (SERR_DEV_XCHG | SERR_PHYRDY_CHG)) {
-+ /* Setup a soft-reset EH action */
-+ ata_ehi_hotplugged(ehi);
-+ ata_ehi_push_desc(ehi, "%s", "hotplug");
-+
-+ freeze = serror & SERR_COMM_WAKE ? 0 : 1;
-+ handled = 1;
-+ }
-+
-+ /* freeze or abort */
-+ if (freeze)
-+ ata_port_freeze(ap);
-+ else
-+ ata_port_abort(ap);
-+
-+ return handled;
-+}
-+
-+static int sata_rcar_ata_interrupt(struct ata_port *ap)
-+{
-+ struct ata_queued_cmd *qc;
-+ int handled = 0;
-+
-+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
-+ if (qc)
-+ handled |= ata_bmdma_port_intr(ap, qc);
-+
-+ return handled;
-+}
-+
-+static irqreturn_t sata_rcar_interrupt(int irq, void *dev_instance)
-+{
-+ struct ata_host *host = dev_instance;
-+ struct sata_rcar_priv *priv = host->private_data;
-+ struct ata_port *ap;
-+ unsigned int handled = 0;
-+ u32 sataintstat;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&host->lock, flags);
-+
-+ sataintstat = ioread32(priv->base + SATAINTSTAT_REG);
-+ if (!sataintstat)
-+ goto done;
-+ /* ack */
-+ iowrite32(sataintstat & ~SATA_RCAR_INT_MASK,
-+ priv->base + SATAINTSTAT_REG);
-+
-+ ap = host->ports[0];
-+
-+ if (sataintstat & SATAINTSTAT_ATA)
-+ handled |= sata_rcar_ata_interrupt(ap);
-+
-+ if (sataintstat & SATAINTSTAT_SERR)
-+ handled |= sata_rcar_serr_interrupt(ap);
-+
-+done:
-+ spin_unlock_irqrestore(&host->lock, flags);
-+
-+ return IRQ_RETVAL(handled);
-+}
-+
-+static void sata_rcar_setup_port(struct ata_host *host)
-+{
-+ struct ata_port *ap = host->ports[0];
-+ struct ata_ioports *ioaddr = &ap->ioaddr;
-+ struct sata_rcar_priv *priv = host->private_data;
-+
-+ ap->ops = &sata_rcar_port_ops;
-+ ap->pio_mask = ATA_PIO4;
-+ ap->udma_mask = ATA_UDMA6;
-+ ap->flags |= ATA_FLAG_SATA;
-+
-+ ioaddr->cmd_addr = priv->base + SDATA_REG;
-+ ioaddr->ctl_addr = priv->base + SSDEVCON_REG;
-+ ioaddr->scr_addr = priv->base + SCRSSTS_REG;
-+ ioaddr->altstatus_addr = ioaddr->ctl_addr;
-+
-+ ioaddr->data_addr = ioaddr->cmd_addr + (ATA_REG_DATA << 2);
-+ ioaddr->error_addr = ioaddr->cmd_addr + (ATA_REG_ERR << 2);
-+ ioaddr->feature_addr = ioaddr->cmd_addr + (ATA_REG_FEATURE << 2);
-+ ioaddr->nsect_addr = ioaddr->cmd_addr + (ATA_REG_NSECT << 2);
-+ ioaddr->lbal_addr = ioaddr->cmd_addr + (ATA_REG_LBAL << 2);
-+ ioaddr->lbam_addr = ioaddr->cmd_addr + (ATA_REG_LBAM << 2);
-+ ioaddr->lbah_addr = ioaddr->cmd_addr + (ATA_REG_LBAH << 2);
-+ ioaddr->device_addr = ioaddr->cmd_addr + (ATA_REG_DEVICE << 2);
-+ ioaddr->status_addr = ioaddr->cmd_addr + (ATA_REG_STATUS << 2);
-+ ioaddr->command_addr = ioaddr->cmd_addr + (ATA_REG_CMD << 2);
-+}
-+
-+static void sata_rcar_init_controller(struct ata_host *host)
-+{
-+ struct sata_rcar_priv *priv = host->private_data;
-+ u32 val;
-+
-+ /* reset and setup phy */
-+ sata_rcar_phy_initialize(priv);
-+ sata_rcar_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 0);
-+ sata_rcar_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 1);
-+ sata_rcar_phy_write(priv, SATAPCTLR3_REG, 0x0000A061, 0);
-+ sata_rcar_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 0);
-+ sata_rcar_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 1);
-+ sata_rcar_phy_write(priv, SATAPCTLR4_REG, 0x28E80000, 0);
-+
-+ /* SATA-IP reset state */
-+ val = ioread32(priv->base + ATAPI_CONTROL1_REG);
-+ val |= ATAPI_CONTROL1_RESET;
-+ iowrite32(val, priv->base + ATAPI_CONTROL1_REG);
-+
-+ /* ISM mode, PRD mode, DTEND flag at bit 0 */
-+ val = ioread32(priv->base + ATAPI_CONTROL1_REG);
-+ val |= ATAPI_CONTROL1_ISM;
-+ val |= ATAPI_CONTROL1_DESE;
-+ val |= ATAPI_CONTROL1_DTA32M;
-+ iowrite32(val, priv->base + ATAPI_CONTROL1_REG);
-+
-+ /* Release the SATA-IP from the reset state */
-+ val = ioread32(priv->base + ATAPI_CONTROL1_REG);
-+ val &= ~ATAPI_CONTROL1_RESET;
-+ iowrite32(val, priv->base + ATAPI_CONTROL1_REG);
-+
-+ /* ack and mask */
-+ iowrite32(0, priv->base + SATAINTSTAT_REG);
-+ iowrite32(0x7ff, priv->base + SATAINTMASK_REG);
-+ /* enable interrupts */
-+ iowrite32(ATAPI_INT_ENABLE_SATAINT, priv->base + ATAPI_INT_ENABLE_REG);
-+}
-+
-+static int sata_rcar_probe(struct platform_device *pdev)
-+{
-+ struct ata_host *host;
-+ struct sata_rcar_priv *priv;
-+ struct resource *mem;
-+ int irq;
-+ int ret = 0;
-+
-+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (mem == NULL)
-+ return -EINVAL;
-+
-+ irq = platform_get_irq(pdev, 0);
-+ if (irq <= 0)
-+ return -EINVAL;
-+
-+ priv = devm_kzalloc(&pdev->dev, sizeof(struct sata_rcar_priv),
-+ GFP_KERNEL);
-+ if (!priv)
-+ return -ENOMEM;
-+
-+ priv->clk = clk_get(&pdev->dev, NULL);
-+ if (IS_ERR(priv->clk)) {
-+ dev_err(&pdev->dev, "failed to get access to sata clock\n");
-+ return PTR_ERR(priv->clk);
-+ }
-+ clk_enable(priv->clk);
-+
-+ host = ata_host_alloc(&pdev->dev, 1);
-+ if (!host) {
-+ dev_err(&pdev->dev, "ata_host_alloc failed\n");
-+ ret = -ENOMEM;
-+ goto cleanup;
-+ }
-+
-+ host->private_data = priv;
-+
-+ priv->base = devm_request_and_ioremap(&pdev->dev, mem);
-+ if (!priv->base) {
-+ ret = -EADDRNOTAVAIL;
-+ goto cleanup;
-+ }
-+
-+ /* setup port */
-+ sata_rcar_setup_port(host);
-+
-+ /* initialize host controller */
-+ sata_rcar_init_controller(host);
-+
-+ ret = ata_host_activate(host, irq, sata_rcar_interrupt, 0,
-+ &sata_rcar_sht);
-+ if (!ret)
-+ return 0;
-+
-+cleanup:
-+ clk_disable(priv->clk);
-+ clk_put(priv->clk);
-+
-+ return ret;
-+}
-+
-+static int sata_rcar_remove(struct platform_device *pdev)
-+{
-+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
-+ struct sata_rcar_priv *priv = host->private_data;
-+
-+ ata_host_detach(host);
-+
-+ /* disable interrupts */
-+ iowrite32(0, priv->base + ATAPI_INT_ENABLE_REG);
-+ /* ack and mask */
-+ iowrite32(0, priv->base + SATAINTSTAT_REG);
-+ iowrite32(0x7ff, priv->base + SATAINTMASK_REG);
-+
-+ clk_disable(priv->clk);
-+ clk_put(priv->clk);
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+static int sata_rcar_suspend(struct device *dev)
-+{
-+ struct ata_host *host = dev_get_drvdata(dev);
-+ struct sata_rcar_priv *priv = host->private_data;
-+ int ret;
-+
-+ ret = ata_host_suspend(host, PMSG_SUSPEND);
-+ if (!ret) {
-+ /* disable interrupts */
-+ iowrite32(0, priv->base + ATAPI_INT_ENABLE_REG);
-+ /* mask */
-+ iowrite32(0x7ff, priv->base + SATAINTMASK_REG);
-+
-+ clk_disable(priv->clk);
-+ }
-+
-+ return ret;
-+}
-+
-+static int sata_rcar_resume(struct device *dev)
-+{
-+ struct ata_host *host = dev_get_drvdata(dev);
-+ struct sata_rcar_priv *priv = host->private_data;
-+
-+ clk_enable(priv->clk);
-+
-+ /* ack and mask */
-+ iowrite32(0, priv->base + SATAINTSTAT_REG);
-+ iowrite32(0x7ff, priv->base + SATAINTMASK_REG);
-+ /* enable interrupts */
-+ iowrite32(ATAPI_INT_ENABLE_SATAINT, priv->base + ATAPI_INT_ENABLE_REG);
-+
-+ ata_host_resume(host);
-+
-+ return 0;
-+}
-+
-+static const struct dev_pm_ops sata_rcar_pm_ops = {
-+ .suspend = sata_rcar_suspend,
-+ .resume = sata_rcar_resume,
-+};
-+#endif
-+
-+static struct of_device_id sata_rcar_match[] = {
-+ { .compatible = "renesas,rcar-sata", },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, sata_rcar_match);
-+
-+static struct platform_driver sata_rcar_driver = {
-+ .probe = sata_rcar_probe,
-+ .remove = sata_rcar_remove,
-+ .driver = {
-+ .name = DRV_NAME,
-+ .owner = THIS_MODULE,
-+ .of_match_table = sata_rcar_match,
-+#ifdef CONFIG_PM
-+ .pm = &sata_rcar_pm_ops,
-+#endif
-+ },
-+};
-+
-+module_platform_driver(sata_rcar_driver);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Vladimir Barinov");
-+MODULE_DESCRIPTION("Renesas R-Car SATA controller low level driver");
+++ /dev/null
-From ec84d795c3d26160bba23ec9f37e1d6e484afc8a Mon Sep 17 00:00:00 2001
-From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
-Date: Tue, 20 Nov 2012 23:00:52 +0100
-Subject: irqchip: add basic infrastructure
-
-With the recent creation of the drivers/irqchip/ directory, it is
-desirable to move irq controller drivers here. At the moment, the only
-driver here is irq-bcm2835, the driver for the irq controller found in
-the ARM BCM2835 SoC, present in Rasberry Pi systems. This irq
-controller driver was exporting its initialization function and its
-irq handling function through a header file in
-<linux/irqchip/bcm2835.h>.
-
-When proposing to also move another irq controller driver in
-drivers/irqchip, Rob Herring raised the very valid point that moving
-things to drivers/irqchip was good in order to remove more stuff from
-arch/arm, but if it means adding gazillions of headers files in
-include/linux/irqchip/, it would not be very nice.
-
-So, upon the suggestion of Rob Herring and Arnd Bergmann, this commit
-introduces a small infrastructure that defines a central
-irqchip_init() function in drivers/irqchip/irqchip.c, which is meant
-to be called as the ->init_irq() callback of ARM platforms. This
-function calls of_irq_init() with an array of match strings and init
-functions generated from a special linker section.
-
-Note that the irq controller driver initialization function is
-responsible for setting the global handle_arch_irq() variable, so that
-ARM platforms no longer have to define the ->handle_irq field in their
-DT_MACHINE structure.
-
-A global header, <linux/irqchip.h> is also added to expose the single
-irqchip_init() function to the reset of the kernel.
-
-A further commit moves the BCM2835 irq controller driver to this new
-small infrastructure, therefore removing the include/linux/irqchip/
-directory.
-
-Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
-Reviewed-by: Stephen Warren <swarren@wwwdotorg.org>
-Reviewed-by: Rob Herring <rob.herring@calxeda.com>
-Acked-by: Arnd Bergmann <arnd@arndb.de>
-[rob.herring: reword commit message to reflect use of linker sections.]
-Signed-off-by: Rob Herring <rob.herring@calxeda.com>
-(cherry picked from commit f6e916b82022cba67bdd0ec7df84e2bce2ef3f73)
-
-Conflicts:
- drivers/Kconfig
- drivers/Makefile
- drivers/irqchip/Kconfig
- drivers/irqchip/Makefile
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- drivers/Kconfig | 1 +
- drivers/Makefile | 2 ++
- drivers/irqchip/Kconfig | 3 +++
- drivers/irqchip/Makefile | 1 +
- drivers/irqchip/irqchip.c | 30 ++++++++++++++++++++++++++++++
- drivers/irqchip/irqchip.h | 29 +++++++++++++++++++++++++++++
- include/asm-generic/vmlinux.lds.h | 12 +++++++++++-
- include/linux/irqchip.h | 16 ++++++++++++++++
- 8 files changed, 93 insertions(+), 1 deletion(-)
- create mode 100644 drivers/irqchip/Kconfig
- create mode 100644 drivers/irqchip/Makefile
- create mode 100644 drivers/irqchip/irqchip.c
- create mode 100644 drivers/irqchip/irqchip.h
- create mode 100644 include/linux/irqchip.h
-
---- a/drivers/Kconfig
-+++ b/drivers/Kconfig
-@@ -140,4 +140,5 @@ source "drivers/virt/Kconfig"
-
- source "drivers/devfreq/Kconfig"
-
-+source "drivers/irqchip/Kconfig"
- endmenu
---- a/drivers/Makefile
-+++ b/drivers/Makefile
-@@ -134,3 +134,5 @@ obj-$(CONFIG_VIRT_DRIVERS) += virt/
- obj-$(CONFIG_HYPERV) += hv/
-
- obj-$(CONFIG_PM_DEVFREQ) += devfreq/
-+
-+obj-y += irqchip/
---- /dev/null
-+++ b/drivers/irqchip/Kconfig
-@@ -0,0 +1,3 @@
-+config IRQCHIP
-+ def_bool y
-+ depends on OF_IRQ
---- /dev/null
-+++ b/drivers/irqchip/Makefile
-@@ -0,0 +1 @@
-+obj-$(CONFIG_IRQCHIP) += irqchip.o
---- /dev/null
-+++ b/drivers/irqchip/irqchip.c
-@@ -0,0 +1,30 @@
-+/*
-+ * Copyright (C) 2012 Thomas Petazzoni
-+ *
-+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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 <linux/init.h>
-+#include <linux/of_irq.h>
-+
-+#include "irqchip.h"
-+
-+/*
-+ * This special of_device_id is the sentinel at the end of the
-+ * of_device_id[] array of all irqchips. It is automatically placed at
-+ * the end of the array by the linker, thanks to being part of a
-+ * special section.
-+ */
-+static const struct of_device_id
-+irqchip_of_match_end __used __section(__irqchip_of_end);
-+
-+extern struct of_device_id __irqchip_begin[];
-+
-+void __init irqchip_init(void)
-+{
-+ of_irq_init(__irqchip_begin);
-+}
---- /dev/null
-+++ b/drivers/irqchip/irqchip.h
-@@ -0,0 +1,29 @@
-+/*
-+ * Copyright (C) 2012 Thomas Petazzoni
-+ *
-+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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.
-+ */
-+
-+#ifndef _IRQCHIP_H
-+#define _IRQCHIP_H
-+
-+/*
-+ * This macro must be used by the different irqchip drivers to declare
-+ * the association between their DT compatible string and their
-+ * initialization function.
-+ *
-+ * @name: name that must be unique accross all IRQCHIP_DECLARE of the
-+ * same file.
-+ * @compstr: compatible string of the irqchip driver
-+ * @fn: initialization function
-+ */
-+#define IRQCHIP_DECLARE(name,compstr,fn) \
-+ static const struct of_device_id irqchip_of_match_##name \
-+ __used __section(__irqchip_of_table) \
-+ = { .compatible = compstr, .data = fn }
-+
-+#endif
---- a/include/asm-generic/vmlinux.lds.h
-+++ b/include/asm-generic/vmlinux.lds.h
-@@ -149,6 +149,15 @@
- #define TRACE_SYSCALLS()
- #endif
-
-+#ifdef CONFIG_IRQCHIP
-+#define IRQCHIP_OF_MATCH_TABLE() \
-+ . = ALIGN(8); \
-+ VMLINUX_SYMBOL(__irqchip_begin) = .; \
-+ *(__irqchip_of_table) \
-+ *(__irqchip_of_end)
-+#else
-+#define IRQCHIP_OF_MATCH_TABLE()
-+#endif
-
- #define KERNEL_DTB() \
- STRUCT_ALIGN(); \
-@@ -493,7 +502,8 @@
- DEV_DISCARD(init.rodata) \
- CPU_DISCARD(init.rodata) \
- MEM_DISCARD(init.rodata) \
-- KERNEL_DTB()
-+ KERNEL_DTB() \
-+ IRQCHIP_OF_MATCH_TABLE()
-
- #define INIT_TEXT \
- *(.init.text) \
---- /dev/null
-+++ b/include/linux/irqchip.h
-@@ -0,0 +1,16 @@
-+/*
-+ * Copyright (C) 2012 Thomas Petazzoni
-+ *
-+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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.
-+ */
-+
-+#ifndef _LINUX_IRQCHIP_H
-+#define _LINUX_IRQCHIP_H
-+
-+void irqchip_init(void);
-+
-+#endif
+++ /dev/null
-From 6d044f57896d098e437879dae9993aefe7ad60e0 Mon Sep 17 00:00:00 2001
-From: Linus Walleij <linus.walleij@linaro.org>
-Date: Thu, 27 Sep 2012 14:59:39 +0200
-Subject: irqdomain: augment add_simple() to allocate descs
-
-Currently we rely on all IRQ chip instances to dynamically
-allocate their IRQ descriptors unless they use the linear
-IRQ domain. So for irqdomain_add_legacy() and
-irqdomain_add_simple() the caller need to make sure that
-descriptors are allocated.
-
-Let's slightly augment the yet unused irqdomain_add_simple()
-to also allocate descriptors as a means to simplify usage
-and avoid code duplication throughout the kernel.
-
-We warn if descriptors cannot be allocated, e.g. if a
-platform has the bad habit of hogging descriptors at boot
-time.
-
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Grant Likely <grant.likely@secretlab.ca>
-Cc: Paul Mundt <lethal@linux-sh.org>
-Cc: Russell King <linux@arm.linux.org.uk>
-Cc: Lee Jones <lee.jones@linaro.org>
-Reviewed-by: Rob Herring <rob.herring@calxeda.com>
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-(cherry picked from commit 2854d167cc545d0642277bf8b77f972a91146fc6)
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- kernel/irq/irqdomain.c | 33 ++++++++++++++++++++++++++++-----
- 1 file changed, 28 insertions(+), 5 deletions(-)
-
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -148,7 +148,8 @@ static unsigned int irq_domain_legacy_re
- * @host_data: Controller private data pointer
- *
- * Allocates a legacy irq_domain if irq_base is positive or a linear
-- * domain otherwise.
-+ * domain otherwise. For the legacy domain, IRQ descriptors will also
-+ * be allocated.
- *
- * This is intended to implement the expected behaviour for most
- * interrupt controllers which is that a linear mapping should
-@@ -162,11 +163,33 @@ struct irq_domain *irq_domain_add_simple
- const struct irq_domain_ops *ops,
- void *host_data)
- {
-- if (first_irq > 0)
-- return irq_domain_add_legacy(of_node, size, first_irq, 0,
-+ if (first_irq > 0) {
-+ int irq_base;
-+
-+ if (IS_ENABLED(CONFIG_SPARSE_IRQ)) {
-+ /*
-+ * Set the descriptor allocator to search for a
-+ * 1-to-1 mapping, such as irq_alloc_desc_at().
-+ * Use of_node_to_nid() which is defined to
-+ * numa_node_id() on platforms that have no custom
-+ * implementation.
-+ */
-+ irq_base = irq_alloc_descs(first_irq, first_irq, size,
-+ of_node_to_nid(of_node));
-+ if (irq_base < 0) {
-+ WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
-+ first_irq);
-+ irq_base = first_irq;
-+ }
-+ } else
-+ irq_base = first_irq;
-+
-+ return irq_domain_add_legacy(of_node, size, irq_base, 0,
- ops, host_data);
-- else
-- return irq_domain_add_linear(of_node, size, ops, host_data);
-+ }
-+
-+ /* A linear domain is the default */
-+ return irq_domain_add_linear(of_node, size, ops, host_data);
- }
-
- /**
+++ /dev/null
-From cfb1c1582aada77bfe7294b7ec4f60c6bf74ceac Mon Sep 17 00:00:00 2001
-From: Linus Walleij <linus.walleij@linaro.org>
-Date: Tue, 27 Nov 2012 01:20:32 +0100
-Subject: irqdomain: stop screaming about preallocated irqdescs
-
-In the simple irqdomain: don't shout warnings to the user,
-there is no point. An informational print is sufficient.
-
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-(cherry picked from commit d202b7b970b2a21278505c2467919fd441a7b6c8)
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- kernel/irq/irqdomain.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/kernel/irq/irqdomain.c
-+++ b/kernel/irq/irqdomain.c
-@@ -177,8 +177,8 @@ struct irq_domain *irq_domain_add_simple
- irq_base = irq_alloc_descs(first_irq, first_irq, size,
- of_node_to_nid(of_node));
- if (irq_base < 0) {
-- WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
-- first_irq);
-+ pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
-+ first_irq);
- irq_base = first_irq;
- }
- } else
+++ /dev/null
-From a19094353a6fc670c1ff007a56698a088bcb2cbd Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Mon, 18 Feb 2013 23:28:34 +0900
-Subject: irqchip: Renesas INTC External IRQ pin driver
-
-This patch adds a driver for external IRQ pins connected
-to the INTC block on recent SoCs from Renesas.
-
-The INTC hardware block usually contains a rather wide
-range of features ranging from external IRQ pin handling
-to legacy interrupt controller support. On older SoCs
-the INTC is used as a general purpose interrupt controller
-both for external IRQ pins and on-chip devices.
-
-On more recent ARM based SoCs with Cortex-A9 the main
-interrupt controller is the GIC, but IRQ trigger setup
-still need to happen in the INTC hardware block.
-
-This driver implements the glue code needed to configure
-IRQ trigger and also handle mask/unmask and demux of
-external IRQ pins hooked up from the INTC to the GIC.
-
-Tested on sh73a0 and r8a7779. The hardware varies quite
-a bit with SoC model, for instance register width and
-bitfield widths vary wildly. The driver requires one GIC
-SPI per external IRQ pin to operate. Each driver instance
-will handle up to 8 external IRQ pins.
-
-The SoCs using this driver are currently mainly used
-together with regular platform devices so this driver
-allows configuration via platform data to support things
-like static interrupt base address. DT support will
-be added incrementally in the not so distant future.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-(cherry picked from commit 0ed30c2820e229e0334f20d93ec75ca196a69162)
-
-Conflicts:
- drivers/irqchip/Kconfig
- drivers/irqchip/Makefile
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- drivers/irqchip/Kconfig | 4
- drivers/irqchip/Makefile | 2
- drivers/irqchip/irq-renesas-intc-irqpin.c | 464 ++++++++++++++++++
- include/linux/platform_data/irq-renesas-intc-irqpin.h | 10
- 4 files changed, 480 insertions(+)
- create mode 100644 drivers/irqchip/irq-renesas-intc-irqpin.c
- create mode 100644 include/linux/platform_data/irq-renesas-intc-irqpin.h
-
---- a/drivers/irqchip/Kconfig
-+++ b/drivers/irqchip/Kconfig
-@@ -1,3 +1,7 @@
- config IRQCHIP
- def_bool y
- depends on OF_IRQ
-+
-+config RENESAS_INTC_IRQPIN
-+ bool
-+ select IRQ_DOMAIN
---- a/drivers/irqchip/Makefile
-+++ b/drivers/irqchip/Makefile
-@@ -1 +1,3 @@
- obj-$(CONFIG_IRQCHIP) += irqchip.o
-+
-+obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o
---- /dev/null
-+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
-@@ -0,0 +1,464 @@
-+/*
-+ * Renesas INTC External IRQ Pin Driver
-+ *
-+ * Copyright (C) 2013 Magnus Damm
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/platform_device.h>
-+#include <linux/spinlock.h>
-+#include <linux/interrupt.h>
-+#include <linux/ioport.h>
-+#include <linux/io.h>
-+#include <linux/irq.h>
-+#include <linux/irqdomain.h>
-+#include <linux/err.h>
-+#include <linux/slab.h>
-+#include <linux/module.h>
-+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
-+
-+#define INTC_IRQPIN_MAX 8 /* maximum 8 interrupts per driver instance */
-+
-+#define INTC_IRQPIN_REG_SENSE 0 /* ICRn */
-+#define INTC_IRQPIN_REG_PRIO 1 /* INTPRInn */
-+#define INTC_IRQPIN_REG_SOURCE 2 /* INTREQnn */
-+#define INTC_IRQPIN_REG_MASK 3 /* INTMSKnn */
-+#define INTC_IRQPIN_REG_CLEAR 4 /* INTMSKCLRnn */
-+#define INTC_IRQPIN_REG_NR 5
-+
-+/* INTC external IRQ PIN hardware register access:
-+ *
-+ * SENSE is read-write 32-bit with 2-bits or 4-bits per IRQ (*)
-+ * PRIO is read-write 32-bit with 4-bits per IRQ (**)
-+ * SOURCE is read-only 32-bit or 8-bit with 1-bit per IRQ (***)
-+ * MASK is write-only 32-bit or 8-bit with 1-bit per IRQ (***)
-+ * CLEAR is write-only 32-bit or 8-bit with 1-bit per IRQ (***)
-+ *
-+ * (*) May be accessed by more than one driver instance - lock needed
-+ * (**) Read-modify-write access by one driver instance - lock needed
-+ * (***) Accessed by one driver instance only - no locking needed
-+ */
-+
-+struct intc_irqpin_iomem {
-+ void __iomem *iomem;
-+ unsigned long (*read)(void __iomem *iomem);
-+ void (*write)(void __iomem *iomem, unsigned long data);
-+ int width;
-+};
-+
-+struct intc_irqpin_irq {
-+ int hw_irq;
-+ int irq;
-+ struct intc_irqpin_priv *p;
-+};
-+
-+struct intc_irqpin_priv {
-+ struct intc_irqpin_iomem iomem[INTC_IRQPIN_REG_NR];
-+ struct intc_irqpin_irq irq[INTC_IRQPIN_MAX];
-+ struct renesas_intc_irqpin_config config;
-+ unsigned int number_of_irqs;
-+ struct platform_device *pdev;
-+ struct irq_chip irq_chip;
-+ struct irq_domain *irq_domain;
-+};
-+
-+static unsigned long intc_irqpin_read32(void __iomem *iomem)
-+{
-+ return ioread32(iomem);
-+}
-+
-+static unsigned long intc_irqpin_read8(void __iomem *iomem)
-+{
-+ return ioread8(iomem);
-+}
-+
-+static void intc_irqpin_write32(void __iomem *iomem, unsigned long data)
-+{
-+ iowrite32(data, iomem);
-+}
-+
-+static void intc_irqpin_write8(void __iomem *iomem, unsigned long data)
-+{
-+ iowrite8(data, iomem);
-+}
-+
-+static inline unsigned long intc_irqpin_read(struct intc_irqpin_priv *p,
-+ int reg)
-+{
-+ struct intc_irqpin_iomem *i = &p->iomem[reg];
-+ return i->read(i->iomem);
-+}
-+
-+static inline void intc_irqpin_write(struct intc_irqpin_priv *p,
-+ int reg, unsigned long data)
-+{
-+ struct intc_irqpin_iomem *i = &p->iomem[reg];
-+ i->write(i->iomem, data);
-+}
-+
-+static inline unsigned long intc_irqpin_hwirq_mask(struct intc_irqpin_priv *p,
-+ int reg, int hw_irq)
-+{
-+ return BIT((p->iomem[reg].width - 1) - hw_irq);
-+}
-+
-+static inline void intc_irqpin_irq_write_hwirq(struct intc_irqpin_priv *p,
-+ int reg, int hw_irq)
-+{
-+ intc_irqpin_write(p, reg, intc_irqpin_hwirq_mask(p, reg, hw_irq));
-+}
-+
-+static DEFINE_RAW_SPINLOCK(intc_irqpin_lock); /* only used by slow path */
-+
-+static void intc_irqpin_read_modify_write(struct intc_irqpin_priv *p,
-+ int reg, int shift,
-+ int width, int value)
-+{
-+ unsigned long flags;
-+ unsigned long tmp;
-+
-+ raw_spin_lock_irqsave(&intc_irqpin_lock, flags);
-+
-+ tmp = intc_irqpin_read(p, reg);
-+ tmp &= ~(((1 << width) - 1) << shift);
-+ tmp |= value << shift;
-+ intc_irqpin_write(p, reg, tmp);
-+
-+ raw_spin_unlock_irqrestore(&intc_irqpin_lock, flags);
-+}
-+
-+static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
-+ int irq, int do_mask)
-+{
-+ int bitfield_width = 4; /* PRIO assumed to have fixed bitfield width */
-+ int shift = (7 - irq) * bitfield_width; /* PRIO assumed to be 32-bit */
-+
-+ intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_PRIO,
-+ shift, bitfield_width,
-+ do_mask ? 0 : (1 << bitfield_width) - 1);
-+}
-+
-+static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value)
-+{
-+ int bitfield_width = p->config.sense_bitfield_width;
-+ int shift = (7 - irq) * bitfield_width; /* SENSE assumed to be 32-bit */
-+
-+ dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value);
-+
-+ if (value >= (1 << bitfield_width))
-+ return -EINVAL;
-+
-+ intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_SENSE, shift,
-+ bitfield_width, value);
-+ return 0;
-+}
-+
-+static void intc_irqpin_dbg(struct intc_irqpin_irq *i, char *str)
-+{
-+ dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n",
-+ str, i->irq, i->hw_irq,
-+ irq_find_mapping(i->p->irq_domain, i->hw_irq));
-+}
-+
-+static void intc_irqpin_irq_enable(struct irq_data *d)
-+{
-+ struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
-+ int hw_irq = irqd_to_hwirq(d);
-+
-+ intc_irqpin_dbg(&p->irq[hw_irq], "enable");
-+ intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_CLEAR, hw_irq);
-+}
-+
-+static void intc_irqpin_irq_disable(struct irq_data *d)
-+{
-+ struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
-+ int hw_irq = irqd_to_hwirq(d);
-+
-+ intc_irqpin_dbg(&p->irq[hw_irq], "disable");
-+ intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_MASK, hw_irq);
-+}
-+
-+static void intc_irqpin_irq_enable_force(struct irq_data *d)
-+{
-+ struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
-+ int irq = p->irq[irqd_to_hwirq(d)].irq;
-+
-+ intc_irqpin_irq_enable(d);
-+ irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
-+}
-+
-+static void intc_irqpin_irq_disable_force(struct irq_data *d)
-+{
-+ struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
-+ int irq = p->irq[irqd_to_hwirq(d)].irq;
-+
-+ irq_get_chip(irq)->irq_mask(irq_get_irq_data(irq));
-+ intc_irqpin_irq_disable(d);
-+}
-+
-+#define INTC_IRQ_SENSE_VALID 0x10
-+#define INTC_IRQ_SENSE(x) (x + INTC_IRQ_SENSE_VALID)
-+
-+static unsigned char intc_irqpin_sense[IRQ_TYPE_SENSE_MASK + 1] = {
-+ [IRQ_TYPE_EDGE_FALLING] = INTC_IRQ_SENSE(0x00),
-+ [IRQ_TYPE_EDGE_RISING] = INTC_IRQ_SENSE(0x01),
-+ [IRQ_TYPE_LEVEL_LOW] = INTC_IRQ_SENSE(0x02),
-+ [IRQ_TYPE_LEVEL_HIGH] = INTC_IRQ_SENSE(0x03),
-+ [IRQ_TYPE_EDGE_BOTH] = INTC_IRQ_SENSE(0x04),
-+};
-+
-+static int intc_irqpin_irq_set_type(struct irq_data *d, unsigned int type)
-+{
-+ unsigned char value = intc_irqpin_sense[type & IRQ_TYPE_SENSE_MASK];
-+ struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
-+
-+ if (!(value & INTC_IRQ_SENSE_VALID))
-+ return -EINVAL;
-+
-+ return intc_irqpin_set_sense(p, irqd_to_hwirq(d),
-+ value ^ INTC_IRQ_SENSE_VALID);
-+}
-+
-+static irqreturn_t intc_irqpin_irq_handler(int irq, void *dev_id)
-+{
-+ struct intc_irqpin_irq *i = dev_id;
-+ struct intc_irqpin_priv *p = i->p;
-+ unsigned long bit;
-+
-+ intc_irqpin_dbg(i, "demux1");
-+ bit = intc_irqpin_hwirq_mask(p, INTC_IRQPIN_REG_SOURCE, i->hw_irq);
-+
-+ if (intc_irqpin_read(p, INTC_IRQPIN_REG_SOURCE) & bit) {
-+ intc_irqpin_write(p, INTC_IRQPIN_REG_SOURCE, ~bit);
-+ intc_irqpin_dbg(i, "demux2");
-+ generic_handle_irq(irq_find_mapping(p->irq_domain, i->hw_irq));
-+ return IRQ_HANDLED;
-+ }
-+ return IRQ_NONE;
-+}
-+
-+static int intc_irqpin_irq_domain_map(struct irq_domain *h, unsigned int virq,
-+ irq_hw_number_t hw)
-+{
-+ struct intc_irqpin_priv *p = h->host_data;
-+
-+ intc_irqpin_dbg(&p->irq[hw], "map");
-+ irq_set_chip_data(virq, h->host_data);
-+ irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
-+ set_irq_flags(virq, IRQF_VALID); /* kill me now */
-+ return 0;
-+}
-+
-+static struct irq_domain_ops intc_irqpin_irq_domain_ops = {
-+ .map = intc_irqpin_irq_domain_map,
-+};
-+
-+static int intc_irqpin_probe(struct platform_device *pdev)
-+{
-+ struct renesas_intc_irqpin_config *pdata = pdev->dev.platform_data;
-+ struct intc_irqpin_priv *p;
-+ struct intc_irqpin_iomem *i;
-+ struct resource *io[INTC_IRQPIN_REG_NR];
-+ struct resource *irq;
-+ struct irq_chip *irq_chip;
-+ void (*enable_fn)(struct irq_data *d);
-+ void (*disable_fn)(struct irq_data *d);
-+ const char *name = dev_name(&pdev->dev);
-+ int ret;
-+ int k;
-+
-+ p = kzalloc(sizeof(*p), GFP_KERNEL);
-+ if (!p) {
-+ dev_err(&pdev->dev, "failed to allocate driver data\n");
-+ ret = -ENOMEM;
-+ goto err0;
-+ }
-+
-+ /* deal with driver instance configuration */
-+ if (pdata)
-+ memcpy(&p->config, pdata, sizeof(*pdata));
-+ if (!p->config.sense_bitfield_width)
-+ p->config.sense_bitfield_width = 4; /* default to 4 bits */
-+
-+ p->pdev = pdev;
-+ platform_set_drvdata(pdev, p);
-+
-+ /* get hold of manadatory IOMEM */
-+ for (k = 0; k < INTC_IRQPIN_REG_NR; k++) {
-+ io[k] = platform_get_resource(pdev, IORESOURCE_MEM, k);
-+ if (!io[k]) {
-+ dev_err(&pdev->dev, "not enough IOMEM resources\n");
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+ }
-+
-+ /* allow any number of IRQs between 1 and INTC_IRQPIN_MAX */
-+ for (k = 0; k < INTC_IRQPIN_MAX; k++) {
-+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, k);
-+ if (!irq)
-+ break;
-+
-+ p->irq[k].hw_irq = k;
-+ p->irq[k].p = p;
-+ p->irq[k].irq = irq->start;
-+ }
-+
-+ p->number_of_irqs = k;
-+ if (p->number_of_irqs < 1) {
-+ dev_err(&pdev->dev, "not enough IRQ resources\n");
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ /* ioremap IOMEM and setup read/write callbacks */
-+ for (k = 0; k < INTC_IRQPIN_REG_NR; k++) {
-+ i = &p->iomem[k];
-+
-+ switch (resource_size(io[k])) {
-+ case 1:
-+ i->width = 8;
-+ i->read = intc_irqpin_read8;
-+ i->write = intc_irqpin_write8;
-+ break;
-+ case 4:
-+ i->width = 32;
-+ i->read = intc_irqpin_read32;
-+ i->write = intc_irqpin_write32;
-+ break;
-+ default:
-+ dev_err(&pdev->dev, "IOMEM size mismatch\n");
-+ ret = -EINVAL;
-+ goto err2;
-+ }
-+
-+ i->iomem = ioremap_nocache(io[k]->start, resource_size(io[k]));
-+ if (!i->iomem) {
-+ dev_err(&pdev->dev, "failed to remap IOMEM\n");
-+ ret = -ENXIO;
-+ goto err2;
-+ }
-+ }
-+
-+ /* mask all interrupts using priority */
-+ for (k = 0; k < p->number_of_irqs; k++)
-+ intc_irqpin_mask_unmask_prio(p, k, 1);
-+
-+ /* use more severe masking method if requested */
-+ if (p->config.control_parent) {
-+ enable_fn = intc_irqpin_irq_enable_force;
-+ disable_fn = intc_irqpin_irq_disable_force;
-+ } else {
-+ enable_fn = intc_irqpin_irq_enable;
-+ disable_fn = intc_irqpin_irq_disable;
-+ }
-+
-+ irq_chip = &p->irq_chip;
-+ irq_chip->name = name;
-+ irq_chip->irq_mask = disable_fn;
-+ irq_chip->irq_unmask = enable_fn;
-+ irq_chip->irq_enable = enable_fn;
-+ irq_chip->irq_disable = disable_fn;
-+ irq_chip->irq_set_type = intc_irqpin_irq_set_type;
-+ irq_chip->flags = IRQCHIP_SKIP_SET_WAKE;
-+
-+ p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
-+ p->number_of_irqs,
-+ p->config.irq_base,
-+ &intc_irqpin_irq_domain_ops, p);
-+ if (!p->irq_domain) {
-+ ret = -ENXIO;
-+ dev_err(&pdev->dev, "cannot initialize irq domain\n");
-+ goto err2;
-+ }
-+
-+ /* request and set priority on interrupts one by one */
-+ for (k = 0; k < p->number_of_irqs; k++) {
-+ if (request_irq(p->irq[k].irq, intc_irqpin_irq_handler,
-+ 0, name, &p->irq[k])) {
-+ dev_err(&pdev->dev, "failed to request low IRQ\n");
-+ ret = -ENOENT;
-+ goto err3;
-+ }
-+ intc_irqpin_mask_unmask_prio(p, k, 0);
-+ }
-+
-+ dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs);
-+
-+ /* warn in case of mismatch if irq base is specified */
-+ if (p->config.irq_base) {
-+ k = irq_find_mapping(p->irq_domain, 0);
-+ if (p->config.irq_base != k)
-+ dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
-+ p->config.irq_base, k);
-+ }
-+
-+ return 0;
-+
-+err3:
-+ for (; k >= 0; k--)
-+ free_irq(p->irq[k - 1].irq, &p->irq[k - 1]);
-+
-+ irq_domain_remove(p->irq_domain);
-+err2:
-+ for (k = 0; k < INTC_IRQPIN_REG_NR; k++)
-+ iounmap(p->iomem[k].iomem);
-+err1:
-+ kfree(p);
-+err0:
-+ return ret;
-+}
-+
-+static int intc_irqpin_remove(struct platform_device *pdev)
-+{
-+ struct intc_irqpin_priv *p = platform_get_drvdata(pdev);
-+ int k;
-+
-+ for (k = 0; k < p->number_of_irqs; k++)
-+ free_irq(p->irq[k].irq, &p->irq[k]);
-+
-+ irq_domain_remove(p->irq_domain);
-+
-+ for (k = 0; k < INTC_IRQPIN_REG_NR; k++)
-+ iounmap(p->iomem[k].iomem);
-+
-+ kfree(p);
-+ return 0;
-+}
-+
-+static struct platform_driver intc_irqpin_device_driver = {
-+ .probe = intc_irqpin_probe,
-+ .remove = intc_irqpin_remove,
-+ .driver = {
-+ .name = "renesas_intc_irqpin",
-+ }
-+};
-+
-+static int __init intc_irqpin_init(void)
-+{
-+ return platform_driver_register(&intc_irqpin_device_driver);
-+}
-+postcore_initcall(intc_irqpin_init);
-+
-+static void __exit intc_irqpin_exit(void)
-+{
-+ platform_driver_unregister(&intc_irqpin_device_driver);
-+}
-+module_exit(intc_irqpin_exit);
-+
-+MODULE_AUTHOR("Magnus Damm");
-+MODULE_DESCRIPTION("Renesas INTC External IRQ Pin Driver");
-+MODULE_LICENSE("GPL v2");
---- /dev/null
-+++ b/include/linux/platform_data/irq-renesas-intc-irqpin.h
-@@ -0,0 +1,10 @@
-+#ifndef __IRQ_RENESAS_INTC_IRQPIN_H__
-+#define __IRQ_RENESAS_INTC_IRQPIN_H__
-+
-+struct renesas_intc_irqpin_config {
-+ unsigned int sense_bitfield_width;
-+ unsigned int irq_base;
-+ bool control_parent;
-+};
-+
-+#endif /* __IRQ_RENESAS_INTC_IRQPIN_H__ */
+++ /dev/null
-From 12395af649b20eb8a23d1e69b2ba8aa6ba6ae8f9 Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Tue, 26 Feb 2013 20:58:54 +0900
-Subject: irqchip: intc-irqpin: Cache mapped IRQ
-
-Cache IRQ in domain_irq variable instead of
-making use of irq_find_mapping(). While at it
-rename the irq variable to requested_irq.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-(cherry picked from commit 325a9c2426dd7144fc3d56397286ce1e69713c12)
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- drivers/irqchip/irq-renesas-intc-irqpin.c | 30 ++++++++++++++++--------------
- 1 file changed, 16 insertions(+), 14 deletions(-)
-
---- a/drivers/irqchip/irq-renesas-intc-irqpin.c
-+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
-@@ -61,7 +61,8 @@ struct intc_irqpin_iomem {
-
- struct intc_irqpin_irq {
- int hw_irq;
-- int irq;
-+ int requested_irq;
-+ int domain_irq;
- struct intc_irqpin_priv *p;
- };
-
-@@ -169,8 +170,7 @@ static int intc_irqpin_set_sense(struct
- static void intc_irqpin_dbg(struct intc_irqpin_irq *i, char *str)
- {
- dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n",
-- str, i->irq, i->hw_irq,
-- irq_find_mapping(i->p->irq_domain, i->hw_irq));
-+ str, i->requested_irq, i->hw_irq, i->domain_irq);
- }
-
- static void intc_irqpin_irq_enable(struct irq_data *d)
-@@ -194,7 +194,7 @@ static void intc_irqpin_irq_disable(stru
- static void intc_irqpin_irq_enable_force(struct irq_data *d)
- {
- struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
-- int irq = p->irq[irqd_to_hwirq(d)].irq;
-+ int irq = p->irq[irqd_to_hwirq(d)].requested_irq;
-
- intc_irqpin_irq_enable(d);
- irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
-@@ -203,7 +203,7 @@ static void intc_irqpin_irq_enable_force
- static void intc_irqpin_irq_disable_force(struct irq_data *d)
- {
- struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
-- int irq = p->irq[irqd_to_hwirq(d)].irq;
-+ int irq = p->irq[irqd_to_hwirq(d)].requested_irq;
-
- irq_get_chip(irq)->irq_mask(irq_get_irq_data(irq));
- intc_irqpin_irq_disable(d);
-@@ -244,7 +244,7 @@ static irqreturn_t intc_irqpin_irq_handl
- if (intc_irqpin_read(p, INTC_IRQPIN_REG_SOURCE) & bit) {
- intc_irqpin_write(p, INTC_IRQPIN_REG_SOURCE, ~bit);
- intc_irqpin_dbg(i, "demux2");
-- generic_handle_irq(irq_find_mapping(p->irq_domain, i->hw_irq));
-+ generic_handle_irq(i->domain_irq);
- return IRQ_HANDLED;
- }
- return IRQ_NONE;
-@@ -255,6 +255,9 @@ static int intc_irqpin_irq_domain_map(st
- {
- struct intc_irqpin_priv *p = h->host_data;
-
-+ p->irq[hw].domain_irq = virq;
-+ p->irq[hw].hw_irq = hw;
-+
- intc_irqpin_dbg(&p->irq[hw], "map");
- irq_set_chip_data(virq, h->host_data);
- irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
-@@ -312,9 +315,8 @@ static int intc_irqpin_probe(struct plat
- if (!irq)
- break;
-
-- p->irq[k].hw_irq = k;
- p->irq[k].p = p;
-- p->irq[k].irq = irq->start;
-+ p->irq[k].requested_irq = irq->start;
- }
-
- p->number_of_irqs = k;
-@@ -387,7 +389,8 @@ static int intc_irqpin_probe(struct plat
-
- /* request and set priority on interrupts one by one */
- for (k = 0; k < p->number_of_irqs; k++) {
-- if (request_irq(p->irq[k].irq, intc_irqpin_irq_handler,
-+ if (request_irq(p->irq[k].requested_irq,
-+ intc_irqpin_irq_handler,
- 0, name, &p->irq[k])) {
- dev_err(&pdev->dev, "failed to request low IRQ\n");
- ret = -ENOENT;
-@@ -400,17 +403,16 @@ static int intc_irqpin_probe(struct plat
-
- /* warn in case of mismatch if irq base is specified */
- if (p->config.irq_base) {
-- k = irq_find_mapping(p->irq_domain, 0);
-- if (p->config.irq_base != k)
-+ if (p->config.irq_base != p->irq[0].domain_irq)
- dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
-- p->config.irq_base, k);
-+ p->config.irq_base, p->irq[0].domain_irq);
- }
-
- return 0;
-
- err3:
- for (; k >= 0; k--)
-- free_irq(p->irq[k - 1].irq, &p->irq[k - 1]);
-+ free_irq(p->irq[k - 1].requested_irq, &p->irq[k - 1]);
-
- irq_domain_remove(p->irq_domain);
- err2:
-@@ -428,7 +430,7 @@ static int intc_irqpin_remove(struct pla
- int k;
-
- for (k = 0; k < p->number_of_irqs; k++)
-- free_irq(p->irq[k].irq, &p->irq[k]);
-+ free_irq(p->irq[k].requested_irq, &p->irq[k]);
-
- irq_domain_remove(p->irq_domain);
-
+++ /dev/null
-From d0f1eb80c491e8e0d13f6c413cf16f1f6cc609a0 Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Tue, 26 Feb 2013 12:00:59 +0900
-Subject: ARM: shmobile: irq_pin() for static IRQ pin assignment
-
-Add the macro irq_pin() to let board-specific code using
-platform devices tie in external IRQn pins in a common way.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-(cherry picked from commit a877feb63cb49b7fa4722f9a0e61949bd46d4577)
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- arch/arm/mach-shmobile/include/mach/irqs.h | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/arch/arm/mach-shmobile/include/mach/irqs.h
-+++ b/arch/arm/mach-shmobile/include/mach/irqs.h
-@@ -11,4 +11,8 @@
- #define INTCS_VECT(n, vect) INTC_VECT((n), INTCS_VECT_BASE + (vect))
- #define intcs_evt2irq(evt) evt2irq(INTCS_VECT_BASE + (evt))
-
-+/* External IRQ pins */
-+#define IRQPIN_BASE 2000
-+#define irq_pin(nr) ((nr) + IRQPIN_BASE)
-+
- #endif /* __ASM_MACH_IRQS_H */
+++ /dev/null
-From 25598603d52c830b2c317ab1b94155525b11c09c Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Tue, 26 Feb 2013 12:01:18 +0900
-Subject: ARM: shmobile: INTC External IRQ pin driver on r8a7779
-
-Update the r8a7779 IRQ code to make use of the
-INTC External IRQ pin driver for external
-interrupt pins IRQ0 -> IRQ3.
-
-The r8a7779 SoC can like older SH SoCs configure
-to use the IRQ0 -> IRQ3 signals as individual
-interrupts or a combined IRL mode.
-
-Without this patch the r8a7779 SoC code does
-not fully support external IRQ pins in individual
-IRQ mode. The r8a7779 PFC code does not yet have
-gpio_to_irq() support so no need to update such
-code.
-
-At this point the DT reference implementations
-are not covered. In the future such code shall
-tie in the INTC External IRQ pin driver via
-DT, so this kind of verbose code is not needed
-for the long term DT case.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-(cherry picked from commit dd9e1fa565b335a5fd2768b772c673a4860196d7)
-
-Conflicts:
- arch/arm/mach-shmobile/Kconfig
- arch/arm/mach-shmobile/include/mach/common.h
- arch/arm/mach-shmobile/intc-r8a7779.c
-
-Signed-off-by: Simon Horman <horms@verge.net.au>
----
- arch/arm/mach-shmobile/Kconfig | 1
- arch/arm/mach-shmobile/board-marzen.c | 3 +
- arch/arm/mach-shmobile/include/mach/common.h | 2 +
- arch/arm/mach-shmobile/intc-r8a7779.c | 52 +++++++++++++++++++++++++++
- 4 files changed, 57 insertions(+), 1 deletion(-)
-
---- a/arch/arm/mach-shmobile/Kconfig
-+++ b/arch/arm/mach-shmobile/Kconfig
-@@ -40,6 +40,7 @@ config ARCH_R8A7779
- select SH_CLK_CPG
- select ARM_GIC
- select ARCH_WANT_OPTIONAL_GPIOLIB
-+ select RENESAS_INTC_IRQPIN
-
- config ARCH_EMEV2
- bool "Emma Mobile EV2"
---- a/arch/arm/mach-shmobile/board-marzen.c
-+++ b/arch/arm/mach-shmobile/board-marzen.c
-@@ -53,7 +53,7 @@ static struct resource smsc911x_resource
- .flags = IORESOURCE_MEM,
- },
- [1] = {
-- .start = gic_spi(28), /* IRQ 1 */
-+ .start = irq_pin(1), /* IRQ1 */
- .flags = IORESOURCE_IRQ,
- },
- };
-@@ -84,6 +84,7 @@ static void __init marzen_init(void)
- regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-
- r8a7779_pinmux_init();
-+ r8a7779_init_irq_extpin(1); /* IRQ1 as individual interrupt */
-
- /* SCIF2 (CN18: DEBUG0) */
- gpio_request(GPIO_FN_TX2_C, NULL);
---- a/arch/arm/mach-shmobile/include/mach/common.h
-+++ b/arch/arm/mach-shmobile/include/mach/common.h
-@@ -66,6 +66,8 @@ extern void r8a7740_reserve_memory(void)
- extern void r8a7740_pinmux_init(void);
-
- extern void r8a7779_init_irq(void);
-+extern void r8a7779_init_irq_extpin(int irlm);
-+extern void r8a7779_init_irq_dt(void);
- extern void r8a7779_map_io(void);
- extern void r8a7779_add_early_devices(void);
- extern void r8a7779_add_standard_devices(void);
---- a/arch/arm/mach-shmobile/intc-r8a7779.c
-+++ b/arch/arm/mach-shmobile/intc-r8a7779.c
-@@ -19,11 +19,15 @@
- */
- #include <linux/kernel.h>
- #include <linux/init.h>
-+#include <linux/platform_device.h>
- #include <linux/interrupt.h>
- #include <linux/irq.h>
- #include <linux/io.h>
-+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
-+#include <linux/irqchip.h>
- #include <mach/common.h>
- #include <mach/intc.h>
-+#include <mach/irqs.h>
- #include <mach/r8a7779.h>
- #include <asm/hardware/gic.h>
- #include <asm/mach-types.h>
-@@ -38,6 +42,54 @@
- #define INT2NTSR0 0xfe700060
- #define INT2NTSR1 0xfe700064
-
-+struct renesas_intc_irqpin_config irqpin0_platform_data = {
-+ .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
-+ .sense_bitfield_width = 2,
-+};
-+
-+static struct resource irqpin0_resources[] = {
-+ DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */
-+ DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */
-+ DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */
-+ DEFINE_RES_MEM(0xfe780044, 4), /* INTMSK0 */
-+ DEFINE_RES_MEM(0xfe780064, 4), /* INTMSKCLR0 */
-+ DEFINE_RES_IRQ(gic_spi(27)), /* IRQ0 */
-+ DEFINE_RES_IRQ(gic_spi(28)), /* IRQ1 */
-+ DEFINE_RES_IRQ(gic_spi(29)), /* IRQ2 */
-+ DEFINE_RES_IRQ(gic_spi(30)), /* IRQ3 */
-+};
-+
-+static struct platform_device irqpin0_device = {
-+ .name = "renesas_intc_irqpin",
-+ .id = 0,
-+ .resource = irqpin0_resources,
-+ .num_resources = ARRAY_SIZE(irqpin0_resources),
-+ .dev = {
-+ .platform_data = &irqpin0_platform_data,
-+ },
-+};
-+
-+void __init r8a7779_init_irq_extpin(int irlm)
-+{
-+ void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE);
-+ unsigned long tmp;
-+
-+ if (icr0) {
-+ tmp = ioread32(icr0);
-+ if (irlm)
-+ tmp |= 1 << 23; /* IRQ0 -> IRQ3 as individual pins */
-+ else
-+ tmp &= ~(1 << 23); /* IRL mode - not supported */
-+ tmp |= (1 << 21); /* LVLMODE = 1 */
-+ iowrite32(tmp, icr0);
-+ iounmap(icr0);
-+
-+ if (irlm)
-+ platform_device_register(&irqpin0_device);
-+ } else
-+ pr_warn("r8a7779: unable to setup external irq pin mode\n");
-+}
-+
- static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
- {
- return 0; /* always allow wakeup */
+++ /dev/null
-From fe6c5fcec31e66f5b03f0380c0644bb7a1637ea4 Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Tue, 26 Feb 2013 20:58:44 +0900
-Subject: irqchip: intc-irqpin: Whitespace fixes
-
-Remove whitespace damage and add newline
-between variables and code.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
-Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- drivers/irqchip/irq-renesas-intc-irqpin.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/irqchip/irq-renesas-intc-irqpin.c
-+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
-@@ -100,6 +100,7 @@ static inline unsigned long intc_irqpin_
- int reg)
- {
- struct intc_irqpin_iomem *i = &p->iomem[reg];
-+
- return i->read(i->iomem);
- }
-
-@@ -107,6 +108,7 @@ static inline void intc_irqpin_write(str
- int reg, unsigned long data)
- {
- struct intc_irqpin_iomem *i = &p->iomem[reg];
-+
- i->write(i->iomem, data);
- }
-
+++ /dev/null
-From b0791671eb6cc3c794f3649dd37dfbd88980e355 Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Tue, 26 Feb 2013 20:59:04 +0900
-Subject: irqchip: intc-irqpin: Add force comments
-
-Add comments to describe the special case for
-"force" versions of enable and disable functions.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
-Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- drivers/irqchip/irq-renesas-intc-irqpin.c | 9 +++++++++
- 1 file changed, 9 insertions(+)
-
---- a/drivers/irqchip/irq-renesas-intc-irqpin.c
-+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
-@@ -199,6 +199,11 @@ static void intc_irqpin_irq_enable_force
- int irq = p->irq[irqd_to_hwirq(d)].requested_irq;
-
- intc_irqpin_irq_enable(d);
-+
-+ /* enable interrupt through parent interrupt controller,
-+ * assumes non-shared interrupt with 1:1 mapping
-+ * needed for busted IRQs on some SoCs like sh73a0
-+ */
- irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
- }
-
-@@ -207,6 +212,10 @@ static void intc_irqpin_irq_disable_forc
- struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
- int irq = p->irq[irqd_to_hwirq(d)].requested_irq;
-
-+ /* disable interrupt through parent interrupt controller,
-+ * assumes non-shared interrupt with 1:1 mapping
-+ * needed for busted IRQs on some SoCs like sh73a0
-+ */
- irq_get_chip(irq)->irq_mask(irq_get_irq_data(irq));
- intc_irqpin_irq_disable(d);
- }
+++ /dev/null
-From e89972262ef0aa2b47a1be58aa72fb6d17c4125e Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Tue, 26 Feb 2013 20:59:13 +0900
-Subject: irqchip: intc-irqpin: Make use of devm functions
-
-Use devm_kzalloc(), devm_ioremap_nocache()
-and devm_request_irq() to simplify error
-handling.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
-Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- drivers/irqchip/irq-renesas-intc-irqpin.c | 41 +++++++++---------------------
- 1 file changed, 13 insertions(+), 28 deletions(-)
-
---- a/drivers/irqchip/irq-renesas-intc-irqpin.c
-+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
-@@ -294,7 +294,7 @@ static int intc_irqpin_probe(struct plat
- int ret;
- int k;
-
-- p = kzalloc(sizeof(*p), GFP_KERNEL);
-+ p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
- if (!p) {
- dev_err(&pdev->dev, "failed to allocate driver data\n");
- ret = -ENOMEM;
-@@ -316,7 +316,7 @@ static int intc_irqpin_probe(struct plat
- if (!io[k]) {
- dev_err(&pdev->dev, "not enough IOMEM resources\n");
- ret = -EINVAL;
-- goto err1;
-+ goto err0;
- }
- }
-
-@@ -334,7 +334,7 @@ static int intc_irqpin_probe(struct plat
- if (p->number_of_irqs < 1) {
- dev_err(&pdev->dev, "not enough IRQ resources\n");
- ret = -EINVAL;
-- goto err1;
-+ goto err0;
- }
-
- /* ioremap IOMEM and setup read/write callbacks */
-@@ -355,14 +355,15 @@ static int intc_irqpin_probe(struct plat
- default:
- dev_err(&pdev->dev, "IOMEM size mismatch\n");
- ret = -EINVAL;
-- goto err2;
-+ goto err0;
- }
-
-- i->iomem = ioremap_nocache(io[k]->start, resource_size(io[k]));
-+ i->iomem = devm_ioremap_nocache(&pdev->dev, io[k]->start,
-+ resource_size(io[k]));
- if (!i->iomem) {
- dev_err(&pdev->dev, "failed to remap IOMEM\n");
- ret = -ENXIO;
-- goto err2;
-+ goto err0;
- }
- }
-
-@@ -395,17 +396,17 @@ static int intc_irqpin_probe(struct plat
- if (!p->irq_domain) {
- ret = -ENXIO;
- dev_err(&pdev->dev, "cannot initialize irq domain\n");
-- goto err2;
-+ goto err0;
- }
-
- /* request and set priority on interrupts one by one */
- for (k = 0; k < p->number_of_irqs; k++) {
-- if (request_irq(p->irq[k].requested_irq,
-- intc_irqpin_irq_handler,
-- 0, name, &p->irq[k])) {
-+ if (devm_request_irq(&pdev->dev, p->irq[k].requested_irq,
-+ intc_irqpin_irq_handler,
-+ 0, name, &p->irq[k])) {
- dev_err(&pdev->dev, "failed to request low IRQ\n");
- ret = -ENOENT;
-- goto err3;
-+ goto err1;
- }
- intc_irqpin_mask_unmask_prio(p, k, 0);
- }
-@@ -421,16 +422,8 @@ static int intc_irqpin_probe(struct plat
-
- return 0;
-
--err3:
-- for (; k >= 0; k--)
-- free_irq(p->irq[k - 1].requested_irq, &p->irq[k - 1]);
--
-- irq_domain_remove(p->irq_domain);
--err2:
-- for (k = 0; k < INTC_IRQPIN_REG_NR; k++)
-- iounmap(p->iomem[k].iomem);
- err1:
-- kfree(p);
-+ irq_domain_remove(p->irq_domain);
- err0:
- return ret;
- }
-@@ -438,17 +431,9 @@ err0:
- static int intc_irqpin_remove(struct platform_device *pdev)
- {
- struct intc_irqpin_priv *p = platform_get_drvdata(pdev);
-- int k;
--
-- for (k = 0; k < p->number_of_irqs; k++)
-- free_irq(p->irq[k].requested_irq, &p->irq[k]);
-
- irq_domain_remove(p->irq_domain);
-
-- for (k = 0; k < INTC_IRQPIN_REG_NR; k++)
-- iounmap(p->iomem[k].iomem);
--
-- kfree(p);
- return 0;
- }
-
+++ /dev/null
-From 8143994e7681c68def57a0b57bfd8c789912eca1 Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Tue, 26 Feb 2013 20:59:23 +0900
-Subject: irqchip: intc-irqpin: GPL header for platform data
-
-Add GPL header to platform data include file.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
-Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- include/linux/platform_data/irq-renesas-intc-irqpin.h | 19 ++++++++++++++++++
- 1 file changed, 19 insertions(+)
-
---- a/include/linux/platform_data/irq-renesas-intc-irqpin.h
-+++ b/include/linux/platform_data/irq-renesas-intc-irqpin.h
-@@ -1,3 +1,22 @@
-+/*
-+ * Renesas INTC External IRQ Pin Driver
-+ *
-+ * Copyright (C) 2013 Magnus Damm
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
- #ifndef __IRQ_RENESAS_INTC_IRQPIN_H__
- #define __IRQ_RENESAS_INTC_IRQPIN_H__
-
+++ /dev/null
-From ce9327175f66480b635210af8c2b38a7780fc573 Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Wed, 27 Feb 2013 17:15:01 +0900
-Subject: irqchip: Renesas IRQC driver
-
-This patch adds a driver for external IRQ pins connected
-to the IRQC hardware block on recent SoCs from Renesas.
-
-The IRQC hardware block is used together with more
-recent ARM based SoCs using the GIC. As usual the GIC
-requires external IRQ trigger setup somewhere else
-which in this particular case happens to be IRQC.
-
-This driver implements the glue code needed to configure
-IRQ trigger and also handle mask/unmask and demux of
-external IRQ pins hooked up from the IRQC to the GIC.
-
-Tested on r8a73a4 but is designed to work with a wide
-range of SoCs. The driver requires one GIC SPI per
-external IRQ pin to operate. Each driver instance
-will handle up to 32 external IRQ pins.
-
-The SoCs using this driver are currently mainly used
-together with regular platform devices so this driver
-allows configuration via platform data to support things
-like static interrupt base address. DT support will
-be added incrementally in the not so distant future.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-(cherry picked from commit beda1f77bba50a4c78ce17bbcec3a0fdab454e88)
-
-Conflicts:
- drivers/irqchip/Kconfig
- drivers/irqchip/Makefile
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- drivers/irqchip/Kconfig | 4
- drivers/irqchip/Makefile | 1
- drivers/irqchip/irq-renesas-irqc.c | 298 +++++++++++++++++++++++++
- include/linux/platform_data/irq-renesas-irqc.h | 27 ++
- 4 files changed, 330 insertions(+)
- create mode 100644 drivers/irqchip/irq-renesas-irqc.c
- create mode 100644 include/linux/platform_data/irq-renesas-irqc.h
-
---- a/drivers/irqchip/Kconfig
-+++ b/drivers/irqchip/Kconfig
-@@ -5,3 +5,7 @@ config IRQCHIP
- config RENESAS_INTC_IRQPIN
- bool
- select IRQ_DOMAIN
-+
-+config RENESAS_IRQC
-+ bool
-+ select IRQ_DOMAIN
---- a/drivers/irqchip/Makefile
-+++ b/drivers/irqchip/Makefile
-@@ -1,3 +1,4 @@
- obj-$(CONFIG_IRQCHIP) += irqchip.o
-
- obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o
-+obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o
---- /dev/null
-+++ b/drivers/irqchip/irq-renesas-irqc.c
-@@ -0,0 +1,298 @@
-+/*
-+ * Renesas IRQC Driver
-+ *
-+ * Copyright (C) 2013 Magnus Damm
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/platform_device.h>
-+#include <linux/spinlock.h>
-+#include <linux/interrupt.h>
-+#include <linux/ioport.h>
-+#include <linux/io.h>
-+#include <linux/irq.h>
-+#include <linux/irqdomain.h>
-+#include <linux/err.h>
-+#include <linux/slab.h>
-+#include <linux/module.h>
-+#include <linux/platform_data/irq-renesas-irqc.h>
-+
-+#define IRQC_IRQ_MAX 32 /* maximum 32 interrupts per driver instance */
-+
-+#define IRQC_REQ_STS 0x00
-+#define IRQC_EN_STS 0x04
-+#define IRQC_EN_SET 0x08
-+#define IRQC_INT_CPU_BASE(n) (0x000 + ((n) * 0x10))
-+#define DETECT_STATUS 0x100
-+#define IRQC_CONFIG(n) (0x180 + ((n) * 0x04))
-+
-+struct irqc_irq {
-+ int hw_irq;
-+ int requested_irq;
-+ int domain_irq;
-+ struct irqc_priv *p;
-+};
-+
-+struct irqc_priv {
-+ void __iomem *iomem;
-+ void __iomem *cpu_int_base;
-+ struct irqc_irq irq[IRQC_IRQ_MAX];
-+ struct renesas_irqc_config config;
-+ unsigned int number_of_irqs;
-+ struct platform_device *pdev;
-+ struct irq_chip irq_chip;
-+ struct irq_domain *irq_domain;
-+};
-+
-+static void irqc_dbg(struct irqc_irq *i, char *str)
-+{
-+ dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n",
-+ str, i->requested_irq, i->hw_irq, i->domain_irq);
-+}
-+
-+static void irqc_irq_enable(struct irq_data *d)
-+{
-+ struct irqc_priv *p = irq_data_get_irq_chip_data(d);
-+ int hw_irq = irqd_to_hwirq(d);
-+
-+ irqc_dbg(&p->irq[hw_irq], "enable");
-+ iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_SET);
-+}
-+
-+static void irqc_irq_disable(struct irq_data *d)
-+{
-+ struct irqc_priv *p = irq_data_get_irq_chip_data(d);
-+ int hw_irq = irqd_to_hwirq(d);
-+
-+ irqc_dbg(&p->irq[hw_irq], "disable");
-+ iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_STS);
-+}
-+
-+#define INTC_IRQ_SENSE_VALID 0x10
-+#define INTC_IRQ_SENSE(x) (x + INTC_IRQ_SENSE_VALID)
-+
-+static unsigned char irqc_sense[IRQ_TYPE_SENSE_MASK + 1] = {
-+ [IRQ_TYPE_LEVEL_LOW] = INTC_IRQ_SENSE(0x01),
-+ [IRQ_TYPE_LEVEL_HIGH] = INTC_IRQ_SENSE(0x02),
-+ [IRQ_TYPE_EDGE_FALLING] = INTC_IRQ_SENSE(0x04), /* Synchronous */
-+ [IRQ_TYPE_EDGE_RISING] = INTC_IRQ_SENSE(0x08), /* Synchronous */
-+ [IRQ_TYPE_EDGE_BOTH] = INTC_IRQ_SENSE(0x0c), /* Synchronous */
-+};
-+
-+static int irqc_irq_set_type(struct irq_data *d, unsigned int type)
-+{
-+ struct irqc_priv *p = irq_data_get_irq_chip_data(d);
-+ int hw_irq = irqd_to_hwirq(d);
-+ unsigned char value = irqc_sense[type & IRQ_TYPE_SENSE_MASK];
-+ unsigned long tmp;
-+
-+ irqc_dbg(&p->irq[hw_irq], "sense");
-+
-+ if (!(value & INTC_IRQ_SENSE_VALID))
-+ return -EINVAL;
-+
-+ tmp = ioread32(p->iomem + IRQC_CONFIG(hw_irq));
-+ tmp &= ~0x3f;
-+ tmp |= value ^ INTC_IRQ_SENSE_VALID;
-+ iowrite32(tmp, p->iomem + IRQC_CONFIG(hw_irq));
-+ return 0;
-+}
-+
-+static irqreturn_t irqc_irq_handler(int irq, void *dev_id)
-+{
-+ struct irqc_irq *i = dev_id;
-+ struct irqc_priv *p = i->p;
-+ unsigned long bit = BIT(i->hw_irq);
-+
-+ irqc_dbg(i, "demux1");
-+
-+ if (ioread32(p->iomem + DETECT_STATUS) & bit) {
-+ iowrite32(bit, p->iomem + DETECT_STATUS);
-+ irqc_dbg(i, "demux2");
-+ generic_handle_irq(i->domain_irq);
-+ return IRQ_HANDLED;
-+ }
-+ return IRQ_NONE;
-+}
-+
-+static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq,
-+ irq_hw_number_t hw)
-+{
-+ struct irqc_priv *p = h->host_data;
-+
-+ p->irq[hw].domain_irq = virq;
-+ p->irq[hw].hw_irq = hw;
-+
-+ irqc_dbg(&p->irq[hw], "map");
-+ irq_set_chip_data(virq, h->host_data);
-+ irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
-+ set_irq_flags(virq, IRQF_VALID); /* kill me now */
-+ return 0;
-+}
-+
-+static struct irq_domain_ops irqc_irq_domain_ops = {
-+ .map = irqc_irq_domain_map,
-+};
-+
-+static int irqc_probe(struct platform_device *pdev)
-+{
-+ struct renesas_irqc_config *pdata = pdev->dev.platform_data;
-+ struct irqc_priv *p;
-+ struct resource *io;
-+ struct resource *irq;
-+ struct irq_chip *irq_chip;
-+ const char *name = dev_name(&pdev->dev);
-+ int ret;
-+ int k;
-+
-+ p = kzalloc(sizeof(*p), GFP_KERNEL);
-+ if (!p) {
-+ dev_err(&pdev->dev, "failed to allocate driver data\n");
-+ ret = -ENOMEM;
-+ goto err0;
-+ }
-+
-+ /* deal with driver instance configuration */
-+ if (pdata)
-+ memcpy(&p->config, pdata, sizeof(*pdata));
-+
-+ p->pdev = pdev;
-+ platform_set_drvdata(pdev, p);
-+
-+ /* get hold of manadatory IOMEM */
-+ io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!io) {
-+ dev_err(&pdev->dev, "not enough IOMEM resources\n");
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ /* allow any number of IRQs between 1 and IRQC_IRQ_MAX */
-+ for (k = 0; k < IRQC_IRQ_MAX; k++) {
-+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, k);
-+ if (!irq)
-+ break;
-+
-+ p->irq[k].p = p;
-+ p->irq[k].requested_irq = irq->start;
-+ }
-+
-+ p->number_of_irqs = k;
-+ if (p->number_of_irqs < 1) {
-+ dev_err(&pdev->dev, "not enough IRQ resources\n");
-+ ret = -EINVAL;
-+ goto err1;
-+ }
-+
-+ /* ioremap IOMEM and setup read/write callbacks */
-+ p->iomem = ioremap_nocache(io->start, resource_size(io));
-+ if (!p->iomem) {
-+ dev_err(&pdev->dev, "failed to remap IOMEM\n");
-+ ret = -ENXIO;
-+ goto err2;
-+ }
-+
-+ p->cpu_int_base = p->iomem + IRQC_INT_CPU_BASE(0); /* SYS-SPI */
-+
-+ irq_chip = &p->irq_chip;
-+ irq_chip->name = name;
-+ irq_chip->irq_mask = irqc_irq_disable;
-+ irq_chip->irq_unmask = irqc_irq_enable;
-+ irq_chip->irq_enable = irqc_irq_enable;
-+ irq_chip->irq_disable = irqc_irq_disable;
-+ irq_chip->irq_set_type = irqc_irq_set_type;
-+ irq_chip->flags = IRQCHIP_SKIP_SET_WAKE;
-+
-+ p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
-+ p->number_of_irqs,
-+ p->config.irq_base,
-+ &irqc_irq_domain_ops, p);
-+ if (!p->irq_domain) {
-+ ret = -ENXIO;
-+ dev_err(&pdev->dev, "cannot initialize irq domain\n");
-+ goto err2;
-+ }
-+
-+ /* request interrupts one by one */
-+ for (k = 0; k < p->number_of_irqs; k++) {
-+ if (request_irq(p->irq[k].requested_irq, irqc_irq_handler,
-+ 0, name, &p->irq[k])) {
-+ dev_err(&pdev->dev, "failed to request IRQ\n");
-+ ret = -ENOENT;
-+ goto err3;
-+ }
-+ }
-+
-+ dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs);
-+
-+ /* warn in case of mismatch if irq base is specified */
-+ if (p->config.irq_base) {
-+ if (p->config.irq_base != p->irq[0].domain_irq)
-+ dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
-+ p->config.irq_base, p->irq[0].domain_irq);
-+ }
-+
-+ return 0;
-+err3:
-+ for (; k >= 0; k--)
-+ free_irq(p->irq[k - 1].requested_irq, &p->irq[k - 1]);
-+
-+ irq_domain_remove(p->irq_domain);
-+err2:
-+ iounmap(p->iomem);
-+err1:
-+ kfree(p);
-+err0:
-+ return ret;
-+}
-+
-+static int irqc_remove(struct platform_device *pdev)
-+{
-+ struct irqc_priv *p = platform_get_drvdata(pdev);
-+ int k;
-+
-+ for (k = 0; k < p->number_of_irqs; k++)
-+ free_irq(p->irq[k].requested_irq, &p->irq[k]);
-+
-+ irq_domain_remove(p->irq_domain);
-+ iounmap(p->iomem);
-+ kfree(p);
-+ return 0;
-+}
-+
-+static struct platform_driver irqc_device_driver = {
-+ .probe = irqc_probe,
-+ .remove = irqc_remove,
-+ .driver = {
-+ .name = "renesas_irqc",
-+ }
-+};
-+
-+static int __init irqc_init(void)
-+{
-+ return platform_driver_register(&irqc_device_driver);
-+}
-+postcore_initcall(irqc_init);
-+
-+static void __exit irqc_exit(void)
-+{
-+ platform_driver_unregister(&irqc_device_driver);
-+}
-+module_exit(irqc_exit);
-+
-+MODULE_AUTHOR("Magnus Damm");
-+MODULE_DESCRIPTION("Renesas IRQC Driver");
-+MODULE_LICENSE("GPL v2");
---- /dev/null
-+++ b/include/linux/platform_data/irq-renesas-irqc.h
-@@ -0,0 +1,27 @@
-+/*
-+ * Renesas IRQC Driver
-+ *
-+ * Copyright (C) 2013 Magnus Damm
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#ifndef __IRQ_RENESAS_IRQC_H__
-+#define __IRQ_RENESAS_IRQC_H__
-+
-+struct renesas_irqc_config {
-+ unsigned int irq_base;
-+};
-+
-+#endif /* __IRQ_RENESAS_IRQC_H__ */
+++ /dev/null
-From 51d6f21fe0236a78f3a53d2603d62a2df88a3902 Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Wed, 6 Mar 2013 15:10:06 +0900
-Subject: ARM: shmobile: Make r8a7779 INTC irqpin platform data static
-
-The platform data for the INTC irq pin driver
-seems to be global symbols, make it static to
-allow multi-soc build.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-(cherry picked from commit dd09a3e6cc0c5f7cc5a05612535e55e78820f404)
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- arch/arm/mach-shmobile/intc-r8a7779.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/mach-shmobile/intc-r8a7779.c
-+++ b/arch/arm/mach-shmobile/intc-r8a7779.c
-@@ -42,7 +42,7 @@
- #define INT2NTSR0 0xfe700060
- #define INT2NTSR1 0xfe700064
-
--struct renesas_intc_irqpin_config irqpin0_platform_data = {
-+static struct renesas_intc_irqpin_config irqpin0_platform_data = {
- .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
- .sense_bitfield_width = 2,
- };
+++ /dev/null
-From c13fcfb98291d86e1f47fcb93a419f11952a873d Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Wed, 6 Mar 2013 15:16:08 +0900
-Subject: irqchip: intc-irqpin: Initial DT support
-
-Add initial DT support to the INTC External IRQ Pin
-driver. At this point only hardware with 4-bit wide
-sense registers is supported via DT.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-(cherry picked from commit 9d833bbe49953a9a07f9ebd7a9ad170c308bd692)
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- drivers/irqchip/irq-renesas-intc-irqpin.c | 9 +++++++++
- 1 file changed, 9 insertions(+)
-
---- a/drivers/irqchip/irq-renesas-intc-irqpin.c
-+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
-@@ -278,6 +278,7 @@ static int intc_irqpin_irq_domain_map(st
-
- static struct irq_domain_ops intc_irqpin_irq_domain_ops = {
- .map = intc_irqpin_irq_domain_map,
-+ .xlate = irq_domain_xlate_twocell,
- };
-
- static int intc_irqpin_probe(struct platform_device *pdev)
-@@ -437,11 +438,19 @@ static int intc_irqpin_remove(struct pla
- return 0;
- }
-
-+static const struct of_device_id intc_irqpin_dt_ids[] = {
-+ { .compatible = "renesas,intc-irqpin", },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids);
-+
- static struct platform_driver intc_irqpin_device_driver = {
- .probe = intc_irqpin_probe,
- .remove = intc_irqpin_remove,
- .driver = {
- .name = "renesas_intc_irqpin",
-+ .of_match_table = intc_irqpin_dt_ids,
-+ .owner = THIS_MODULE,
- }
- };
-
+++ /dev/null
-From 14bd4f0bc85992add01373d6ebed7dfabd85f07a Mon Sep 17 00:00:00 2001
-From: Magnus Damm <damm@opensource.se>
-Date: Wed, 6 Mar 2013 15:23:39 +0900
-Subject: irqchip: irqc: Add DT support
-
-Add DT support to the IRQC External IRQ Pin driver.
-
-Signed-off-by: Magnus Damm <damm@opensource.se>
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-(cherry picked from commit 3b8dfa7c2f8af7613dae28ac0f3419bf75ead5d0)
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- drivers/irqchip/irq-renesas-irqc.c | 9 +++++++++
- 1 file changed, 9 insertions(+)
-
---- a/drivers/irqchip/irq-renesas-irqc.c
-+++ b/drivers/irqchip/irq-renesas-irqc.c
-@@ -145,6 +145,7 @@ static int irqc_irq_domain_map(struct ir
-
- static struct irq_domain_ops irqc_irq_domain_ops = {
- .map = irqc_irq_domain_map,
-+ .xlate = irq_domain_xlate_twocell,
- };
-
- static int irqc_probe(struct platform_device *pdev)
-@@ -273,11 +274,19 @@ static int irqc_remove(struct platform_d
- return 0;
- }
-
-+static const struct of_device_id irqc_dt_ids[] = {
-+ { .compatible = "renesas,irqc", },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, irqc_dt_ids);
-+
- static struct platform_driver irqc_device_driver = {
- .probe = irqc_probe,
- .remove = irqc_remove,
- .driver = {
- .name = "renesas_irqc",
-+ .of_match_table = irqc_dt_ids,
-+ .owner = THIS_MODULE,
- }
- };
-
+++ /dev/null
-From horms@vergenet.net Tue Mar 26 21:37:55 2013
-From: Simon Horman <horms+renesas@verge.net.au>
-Date: Wed, 27 Mar 2013 13:37:49 +0900
-Subject: [PATCH 1/2] ARM: SoC: add per-platform SMP operations
-To: ltsi-dev@lists.linuxfoundation.org
-Cc: Greg KH <gregkh@linuxfoundation.org>
-Message-ID: <1364359070-7002-2-git-send-email-horms+renesas@verge.net.au>
-
-
-From: Marc Zyngier <marc.zyngier@arm.com>
-
-This adds a 'struct smp_operations' to abstract the CPU initialization
-and hot plugging functions on SMP systems, which otherwise conflict
-in a multiplatform kernel. This also helps shmobile and potentially
-others that have more than one method to do these.
-
-To allow the kernel to continue building, the platform hooks are
-defined as weak symbols which are overrided by the platform code.
-Once all platforms are converted, the "weak" attribute will be
-removed and the function made static.
-
-Unlike the original version from Marc, this new version from Arnd
-does not use a generalized abstraction for per-soc data structures
-but only tries to solve the problem for the SMP operations. This
-way, we can collapse the previous four data structures into a
-single struct, which is less systematic but also easier to follow
-as a causal reader.
-
-Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-Acked-by: Nicolas Pitre <nico@fluxnic.net>
-Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-(cherry picked from commit abcee5fb0dfbb248d883a2f6bdb4820abe3ac524)
-
-Conflicts:
- arch/arm/kernel/smp.c
-
-Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
----
- arch/arm/include/asm/mach/arch.h | 7 ++++
- arch/arm/include/asm/smp.h | 33 ++++++++++++++++++++
- arch/arm/kernel/setup.c | 4 +-
- arch/arm/kernel/smp.c | 62 ++++++++++++++++++++++++++++++++++++++-
- 4 files changed, 104 insertions(+), 2 deletions(-)
-
---- a/arch/arm/include/asm/mach/arch.h
-+++ b/arch/arm/include/asm/mach/arch.h
-@@ -14,6 +14,12 @@ struct tag;
- struct meminfo;
- struct sys_timer;
- struct pt_regs;
-+struct smp_operations;
-+#ifdef CONFIG_SMP
-+#define smp_ops(ops) (&(ops))
-+#else
-+#define smp_ops(ops) (struct smp_operations *)NULL
-+#endif
-
- struct machine_desc {
- unsigned int nr; /* architecture number */
-@@ -35,6 +41,7 @@ struct machine_desc {
- unsigned char reserve_lp1 :1; /* never has lp1 */
- unsigned char reserve_lp2 :1; /* never has lp2 */
- char restart_mode; /* default restart mode */
-+ struct smp_operations *smp; /* SMP operations */
- void (*fixup)(struct tag *, char **,
- struct meminfo *);
- void (*reserve)(void);/* reserve mem blocks */
---- a/arch/arm/include/asm/smp.h
-+++ b/arch/arm/include/asm/smp.h
-@@ -93,4 +93,37 @@ extern void platform_cpu_enable(unsigned
- extern void arch_send_call_function_single_ipi(int cpu);
- extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
-
-+struct smp_operations {
-+#ifdef CONFIG_SMP
-+ /*
-+ * Setup the set of possible CPUs (via set_cpu_possible)
-+ */
-+ void (*smp_init_cpus)(void);
-+ /*
-+ * Initialize cpu_possible map, and enable coherency
-+ */
-+ void (*smp_prepare_cpus)(unsigned int max_cpus);
-+
-+ /*
-+ * Perform platform specific initialisation of the specified CPU.
-+ */
-+ void (*smp_secondary_init)(unsigned int cpu);
-+ /*
-+ * Boot a secondary CPU, and assign it the specified idle task.
-+ * This also gives us the initial stack to use for this CPU.
-+ */
-+ int (*smp_boot_secondary)(unsigned int cpu, struct task_struct *idle);
-+#ifdef CONFIG_HOTPLUG_CPU
-+ int (*cpu_kill)(unsigned int cpu);
-+ void (*cpu_die)(unsigned int cpu);
-+ int (*cpu_disable)(unsigned int cpu);
-+#endif
-+#endif
-+};
-+
-+/*
-+ * set platform specific SMP operations
-+ */
-+extern void smp_set_ops(struct smp_operations *);
-+
- #endif /* ifndef __ASM_ARM_SMP_H */
---- a/arch/arm/kernel/setup.c
-+++ b/arch/arm/kernel/setup.c
-@@ -977,8 +977,10 @@ void __init setup_arch(char **cmdline_p)
- unflatten_device_tree();
-
- #ifdef CONFIG_SMP
-- if (is_smp())
-+ if (is_smp()) {
-+ smp_set_ops(mdesc->smp);
- smp_init_cpus();
-+ }
- #endif
- reserve_crashkernel();
-
---- a/arch/arm/kernel/smp.c
-+++ b/arch/arm/kernel/smp.c
-@@ -19,7 +19,6 @@
- #include <linux/mm.h>
- #include <linux/err.h>
- #include <linux/cpu.h>
--#include <linux/smp.h>
- #include <linux/seq_file.h>
- #include <linux/irq.h>
- #include <linux/percpu.h>
-@@ -27,6 +26,7 @@
- #include <linux/completion.h>
-
- #include <linux/atomic.h>
-+#include <asm/smp.h>
- #include <asm/cacheflush.h>
- #include <asm/cpu.h>
- #include <asm/cputype.h>
-@@ -42,6 +42,7 @@
- #include <asm/ptrace.h>
- #include <asm/localtimer.h>
- #include <asm/smp_plat.h>
-+#include <asm/mach/arch.h>
-
- /*
- * as from 2.5, kernels no longer have an init_tasks structure
-@@ -60,6 +61,14 @@ enum ipi_msg_type {
-
- static DECLARE_COMPLETION(cpu_running);
-
-+static struct smp_operations smp_ops;
-+
-+void __init smp_set_ops(struct smp_operations *ops)
-+{
-+ if (ops)
-+ smp_ops = *ops;
-+};
-+
- int __cpuinit __cpu_up(unsigned int cpu)
- {
- struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
-@@ -121,9 +130,60 @@ int __cpuinit __cpu_up(unsigned int cpu)
- return ret;
- }
-
-+/* platform specific SMP operations */
-+void __attribute__((weak)) __init smp_init_cpus(void)
-+{
-+ if (smp_ops.smp_init_cpus)
-+ smp_ops.smp_init_cpus();
-+}
-+
-+void __attribute__((weak)) __init platform_smp_prepare_cpus(unsigned int max_cpus)
-+{
-+ if (smp_ops.smp_prepare_cpus)
-+ smp_ops.smp_prepare_cpus(max_cpus);
-+}
-+
-+void __attribute__((weak)) __cpuinit platform_secondary_init(unsigned int cpu)
-+{
-+ if (smp_ops.smp_secondary_init)
-+ smp_ops.smp_secondary_init(cpu);
-+}
-+
-+int __attribute__((weak)) __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
-+{
-+ if (smp_ops.smp_boot_secondary)
-+ return smp_ops.smp_boot_secondary(cpu, idle);
-+ return -ENOSYS;
-+}
-+
- #ifdef CONFIG_HOTPLUG_CPU
- static void percpu_timer_stop(void);
-
-+int __attribute__((weak)) platform_cpu_kill(unsigned int cpu)
-+{
-+ if (smp_ops.cpu_kill)
-+ return smp_ops.cpu_kill(cpu);
-+ return 1;
-+}
-+
-+void __attribute__((weak)) platform_cpu_die(unsigned int cpu)
-+{
-+ if (smp_ops.cpu_die)
-+ smp_ops.cpu_die(cpu);
-+}
-+
-+int __attribute__((weak)) platform_cpu_disable(unsigned int cpu)
-+{
-+ if (smp_ops.cpu_disable)
-+ return smp_ops.cpu_disable(cpu);
-+
-+ /*
-+ * By default, allow disabling all CPUs except the first one,
-+ * since this is special on a lot of platforms, e.g. because
-+ * of clock tick interrupts.
-+ */
-+ return cpu == 0 ? -EPERM : 0;
-+}
- /*
- * __cpu_disable runs on the processor to be shutdown.
- */
+++ /dev/null
-From horms@vergenet.net Tue Mar 26 21:37:56 2013
-From: Simon Horman <horms+renesas@verge.net.au>
-Date: Wed, 27 Mar 2013 13:37:50 +0900
-Subject: [PATCH 2/2] ARM: SoC: convert shmobile SMP to SMP operations
-To: ltsi-dev@lists.linuxfoundation.org
-Cc: Greg KH <gregkh@linuxfoundation.org>
-Message-ID: <1364359070-7002-3-git-send-email-horms+renesas@verge.net.au>
-
-
-From: Marc Zyngier <marc.zyngier@arm.com>
-
-Convert shmobile SMP platforms to use struct smp_operations to provide
-their SMP and CPU hotplug operations.
-
-Cc: Paul Mundt <lethal@linux-sh.org>
-Cc: Magnus Damm <magnus.damm@gmail.com>
-Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-Acked-by: Nicolas Pitre <nico@linaro.org>
-Signed-off-by: Arnd Bergmann <arnd@arndb.de>
----
- arch/arm/mach-shmobile/board-ag5evm.c | 1
- arch/arm/mach-shmobile/board-kota2.c | 1
- arch/arm/mach-shmobile/board-kzm9d.c | 1
- arch/arm/mach-shmobile/board-kzm9g.c | 1
- arch/arm/mach-shmobile/board-marzen.c | 1
- arch/arm/mach-shmobile/hotplug.c | 31 ++------
- arch/arm/mach-shmobile/include/mach/common.h | 24 +++---
- arch/arm/mach-shmobile/include/mach/emev2.h | 7 -
- arch/arm/mach-shmobile/include/mach/r8a7779.h | 2
- arch/arm/mach-shmobile/include/mach/sh73a0.h | 2
- arch/arm/mach-shmobile/platsmp.c | 96 --------------------------
- arch/arm/mach-shmobile/setup-emev2.c | 1
- arch/arm/mach-shmobile/smp-emev2.c | 47 +++++++++++-
- arch/arm/mach-shmobile/smp-r8a7779.c | 48 +++++++++++--
- arch/arm/mach-shmobile/smp-sh73a0.c | 48 +++++++++++--
- 15 files changed, 165 insertions(+), 146 deletions(-)
-
---- a/arch/arm/mach-shmobile/board-ag5evm.c
-+++ b/arch/arm/mach-shmobile/board-ag5evm.c
-@@ -574,6 +574,7 @@ static void __init ag5evm_init(void)
- }
-
- MACHINE_START(AG5EVM, "ag5evm")
-+ .smp = smp_ops(sh73a0_smp_ops),
- .map_io = sh73a0_map_io,
- .init_early = sh73a0_add_early_devices,
- .nr_irqs = NR_IRQS_LEGACY,
---- a/arch/arm/mach-shmobile/board-kota2.c
-+++ b/arch/arm/mach-shmobile/board-kota2.c
-@@ -515,6 +515,7 @@ static void __init kota2_init(void)
- }
-
- MACHINE_START(KOTA2, "kota2")
-+ .smp = smp_ops(sh73a0_smp_ops),
- .map_io = sh73a0_map_io,
- .init_early = sh73a0_add_early_devices,
- .nr_irqs = NR_IRQS_LEGACY,
---- a/arch/arm/mach-shmobile/board-kzm9d.c
-+++ b/arch/arm/mach-shmobile/board-kzm9d.c
-@@ -74,6 +74,7 @@ static const char *kzm9d_boards_compat_d
- };
-
- DT_MACHINE_START(KZM9D_DT, "kzm9d")
-+ .smp = smp_ops(emev2_smp_ops),
- .map_io = emev2_map_io,
- .init_early = emev2_add_early_devices,
- .nr_irqs = NR_IRQS_LEGACY,
---- a/arch/arm/mach-shmobile/board-kzm9g.c
-+++ b/arch/arm/mach-shmobile/board-kzm9g.c
-@@ -744,6 +744,7 @@ static const char *kzm9g_boards_compat_d
- };
-
- DT_MACHINE_START(KZM9G_DT, "kzm9g")
-+ .smp = smp_ops(sh73a0_smp_ops),
- .map_io = sh73a0_map_io,
- .init_early = sh73a0_add_early_devices,
- .nr_irqs = NR_IRQS_LEGACY,
---- a/arch/arm/mach-shmobile/board-marzen.c
-+++ b/arch/arm/mach-shmobile/board-marzen.c
-@@ -102,6 +102,7 @@ static void __init marzen_init(void)
- }
-
- MACHINE_START(MARZEN, "marzen")
-+ .smp = smp_ops(r8a7779_smp_ops),
- .map_io = r8a7779_map_io,
- .init_early = r8a7779_add_early_devices,
- .nr_irqs = NR_IRQS_LEGACY,
---- a/arch/arm/mach-shmobile/hotplug.c
-+++ b/arch/arm/mach-shmobile/hotplug.c
-@@ -14,30 +14,16 @@
- #include <linux/smp.h>
- #include <linux/cpumask.h>
- #include <linux/delay.h>
-+#include <linux/of.h>
- #include <mach/common.h>
-+#include <mach/r8a7779.h>
-+#include <mach/emev2.h>
- #include <asm/cacheflush.h>
-+#include <asm/mach-types.h>
-
- static cpumask_t dead_cpus;
-
--int platform_cpu_kill(unsigned int cpu)
--{
-- int k;
--
-- /* this function is running on another CPU than the offline target,
-- * here we need wait for shutdown code in platform_cpu_die() to
-- * finish before asking SoC-specific code to power off the CPU core.
-- */
-- for (k = 0; k < 1000; k++) {
-- if (cpumask_test_cpu(cpu, &dead_cpus))
-- return shmobile_platform_cpu_kill(cpu);
--
-- mdelay(1);
-- }
--
-- return 0;
--}
--
--void platform_cpu_die(unsigned int cpu)
-+void shmobile_cpu_die(unsigned int cpu)
- {
- /* hardware shutdown code running on the CPU that is being offlined */
- flush_cache_all();
-@@ -60,7 +46,7 @@ void platform_cpu_die(unsigned int cpu)
- }
- }
-
--int platform_cpu_disable(unsigned int cpu)
-+int shmobile_cpu_disable(unsigned int cpu)
- {
- cpumask_clear_cpu(cpu, &dead_cpus);
- /*
-@@ -69,3 +55,8 @@ int platform_cpu_disable(unsigned int cp
- */
- return cpu == 0 ? -EPERM : 0;
- }
-+
-+int shmobile_cpu_is_dead(unsigned int cpu)
-+{
-+ return cpumask_test_cpu(cpu, &dead_cpus);
-+}
---- a/arch/arm/mach-shmobile/include/mach/common.h
-+++ b/arch/arm/mach-shmobile/include/mach/common.h
-@@ -4,11 +4,10 @@
- extern void shmobile_earlytimer_init(void);
- extern struct sys_timer shmobile_timer;
- extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
-- unsigned int mult, unsigned int div);
-+ unsigned int mult, unsigned int div);
- struct twd_local_timer;
- extern void shmobile_setup_console(void);
- extern void shmobile_secondary_vector(void);
--extern int shmobile_platform_cpu_kill(unsigned int cpu);
- struct clk;
- extern int shmobile_clk_init(void);
- extern void shmobile_handle_irq_intc(struct pt_regs *);
-@@ -58,11 +57,6 @@ extern struct clk sh73a0_extal2_clk;
- extern struct clk sh73a0_extcki_clk;
- extern struct clk sh73a0_extalr_clk;
-
--extern unsigned int sh73a0_get_core_count(void);
--extern void sh73a0_secondary_init(unsigned int cpu);
--extern int sh73a0_boot_secondary(unsigned int cpu);
--extern void sh73a0_smp_prepare_cpus(void);
--
- extern void r8a7740_init_irq(void);
- extern void r8a7740_map_io(void);
- extern void r8a7740_add_early_devices(void);
-@@ -80,11 +74,6 @@ extern void r8a7779_pinmux_init(void);
- extern void r8a7779_pm_init(void);
- extern void r8a7740_meram_workaround(void);
-
--extern unsigned int r8a7779_get_core_count(void);
--extern int r8a7779_platform_cpu_kill(unsigned int cpu);
--extern void r8a7779_secondary_init(unsigned int cpu);
--extern int r8a7779_boot_secondary(unsigned int cpu);
--extern void r8a7779_smp_prepare_cpus(void);
- extern void r8a7779_register_twd(void);
-
- extern void shmobile_init_late(void);
-@@ -101,4 +90,15 @@ int shmobile_cpuidle_init(void);
- static inline int shmobile_cpuidle_init(void) { return 0; }
- #endif
-
-+extern void shmobile_cpu_die(unsigned int cpu);
-+extern int shmobile_cpu_disable(unsigned int cpu);
-+
-+#ifdef CONFIG_HOTPLUG_CPU
-+extern int shmobile_cpu_is_dead(unsigned int cpu);
-+#else
-+static inline int shmobile_cpu_is_dead(unsigned int cpu) { return 1; }
-+#endif
-+
-+extern void shmobile_smp_init_cpus(unsigned int ncores);
-+
- #endif /* __ARCH_MACH_COMMON_H */
---- a/arch/arm/mach-shmobile/include/mach/emev2.h
-+++ b/arch/arm/mach-shmobile/include/mach/emev2.h
-@@ -7,13 +7,10 @@ extern void emev2_add_early_devices(void
- extern void emev2_add_standard_devices(void);
- extern void emev2_clock_init(void);
- extern void emev2_set_boot_vector(unsigned long value);
--extern unsigned int emev2_get_core_count(void);
--extern int emev2_platform_cpu_kill(unsigned int cpu);
--extern void emev2_secondary_init(unsigned int cpu);
--extern int emev2_boot_secondary(unsigned int cpu);
--extern void emev2_smp_prepare_cpus(void);
-
- #define EMEV2_GPIO_BASE 200
- #define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n))
-
-+extern struct smp_operations emev2_smp_ops;
-+
- #endif /* __ASM_EMEV2_H__ */
---- a/arch/arm/mach-shmobile/include/mach/r8a7779.h
-+++ b/arch/arm/mach-shmobile/include/mach/r8a7779.h
-@@ -360,4 +360,6 @@ extern void r8a7779_add_device_to_domain
- #define r8a7779_add_device_to_domain(pd, pdev) do { } while (0)
- #endif /* CONFIG_PM */
-
-+extern struct smp_operations r8a7779_smp_ops;
-+
- #endif /* __ASM_R8A7779_H__ */
---- a/arch/arm/mach-shmobile/include/mach/sh73a0.h
-+++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h
-@@ -557,4 +557,6 @@ enum {
- #define SH73A0_PINT0_IRQ(irq) ((irq) + 700)
- #define SH73A0_PINT1_IRQ(irq) ((irq) + 732)
-
-+extern struct smp_operations sh73a0_smp_ops;
-+
- #endif /* __ASM_SH73A0_H__ */
---- a/arch/arm/mach-shmobile/platsmp.c
-+++ b/arch/arm/mach-shmobile/platsmp.c
-@@ -11,100 +11,11 @@
- * published by the Free Software Foundation.
- */
- #include <linux/init.h>
--#include <linux/errno.h>
--#include <linux/delay.h>
--#include <linux/device.h>
- #include <linux/smp.h>
--#include <linux/io.h>
--#include <linux/of.h>
- #include <asm/hardware/gic.h>
--#include <asm/mach-types.h>
--#include <mach/common.h>
--#include <mach/emev2.h>
-
--#ifdef CONFIG_ARCH_SH73A0
--#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2() || \
-- of_machine_is_compatible("renesas,sh73a0"))
--#else
--#define is_sh73a0() (0)
--#endif
--
--#define is_r8a7779() machine_is_marzen()
--
--#ifdef CONFIG_ARCH_EMEV2
--#define is_emev2() of_machine_is_compatible("renesas,emev2")
--#else
--#define is_emev2() (0)
--#endif
--
--static unsigned int __init shmobile_smp_get_core_count(void)
--{
-- if (is_sh73a0())
-- return sh73a0_get_core_count();
--
-- if (is_r8a7779())
-- return r8a7779_get_core_count();
--
-- if (is_emev2())
-- return emev2_get_core_count();
--
-- return 1;
--}
--
--static void __init shmobile_smp_prepare_cpus(void)
--{
-- if (is_sh73a0())
-- sh73a0_smp_prepare_cpus();
--
-- if (is_r8a7779())
-- r8a7779_smp_prepare_cpus();
--
-- if (is_emev2())
-- emev2_smp_prepare_cpus();
--}
--
--int shmobile_platform_cpu_kill(unsigned int cpu)
--{
-- if (is_r8a7779())
-- return r8a7779_platform_cpu_kill(cpu);
--
-- if (is_emev2())
-- return emev2_platform_cpu_kill(cpu);
--
-- return 1;
--}
--
--void __cpuinit platform_secondary_init(unsigned int cpu)
-+void __init shmobile_smp_init_cpus(unsigned int ncores)
- {
-- trace_hardirqs_off();
--
-- if (is_sh73a0())
-- sh73a0_secondary_init(cpu);
--
-- if (is_r8a7779())
-- r8a7779_secondary_init(cpu);
--
-- if (is_emev2())
-- emev2_secondary_init(cpu);
--}
--
--int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
--{
-- if (is_sh73a0())
-- return sh73a0_boot_secondary(cpu);
--
-- if (is_r8a7779())
-- return r8a7779_boot_secondary(cpu);
--
-- if (is_emev2())
-- return emev2_boot_secondary(cpu);
--
-- return -ENOSYS;
--}
--
--void __init smp_init_cpus(void)
--{
-- unsigned int ncores = shmobile_smp_get_core_count();
- unsigned int i;
-
- if (ncores > nr_cpu_ids) {
-@@ -118,8 +29,3 @@ void __init smp_init_cpus(void)
-
- set_smp_cross_call(gic_raise_softirq);
- }
--
--void __init platform_smp_prepare_cpus(unsigned int max_cpus)
--{
-- shmobile_smp_prepare_cpus();
--}
---- a/arch/arm/mach-shmobile/setup-emev2.c
-+++ b/arch/arm/mach-shmobile/setup-emev2.c
-@@ -440,6 +440,7 @@ void __init emev2_init_irq_dt(void)
- }
-
- DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
-+ .smp = smp_ops(emev2_smp_ops),
- .init_early = emev2_init_delay,
- .nr_irqs = NR_IRQS_LEGACY,
- .init_irq = emev2_init_irq_dt,
---- a/arch/arm/mach-shmobile/smp-emev2.c
-+++ b/arch/arm/mach-shmobile/smp-emev2.c
-@@ -50,7 +50,7 @@ static void modify_scu_cpu_psr(unsigned
-
- }
-
--unsigned int __init emev2_get_core_count(void)
-+static unsigned int __init emev2_get_core_count(void)
- {
- if (!scu_base) {
- scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
-@@ -62,17 +62,35 @@ unsigned int __init emev2_get_core_count
- return scu_base ? scu_get_core_count(scu_base) : 1;
- }
-
--int emev2_platform_cpu_kill(unsigned int cpu)
-+static int emev2_platform_cpu_kill(unsigned int cpu)
- {
- return 0; /* not supported yet */
- }
-
--void __cpuinit emev2_secondary_init(unsigned int cpu)
-+static int __maybe_unused emev2_cpu_kill(unsigned int cpu)
-+{
-+ int k;
-+
-+ /* this function is running on another CPU than the offline target,
-+ * here we need wait for shutdown code in platform_cpu_die() to
-+ * finish before asking SoC-specific code to power off the CPU core.
-+ */
-+ for (k = 0; k < 1000; k++) {
-+ if (shmobile_cpu_is_dead(cpu))
-+ return emev2_platform_cpu_kill(cpu);
-+ mdelay(1);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static void __cpuinit emev2_secondary_init(unsigned int cpu)
- {
- gic_secondary_init(0);
- }
-
--int __cpuinit emev2_boot_secondary(unsigned int cpu)
-+static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
- {
- cpu = cpu_logical_map(cpu);
-
-@@ -86,7 +104,7 @@ int __cpuinit emev2_boot_secondary(unsig
- return 0;
- }
-
--void __init emev2_smp_prepare_cpus(void)
-+static void __init emev2_smp_prepare_cpus(unsigned int max_cpus)
- {
- int cpu = cpu_logical_map(0);
-
-@@ -95,3 +113,22 @@ void __init emev2_smp_prepare_cpus(void)
- /* enable cache coherency on CPU0 */
- modify_scu_cpu_psr(0, 3 << (cpu * 8));
- }
-+
-+static void __init emev2_smp_init_cpus(void)
-+{
-+ unsigned int ncores = emev2_get_core_count();
-+
-+ shmobile_smp_init_cpus(ncores);
-+}
-+
-+struct smp_operations emev2_smp_ops __initdata = {
-+ .smp_init_cpus = emev2_smp_init_cpus,
-+ .smp_prepare_cpus = emev2_smp_prepare_cpus,
-+ .smp_secondary_init = emev2_secondary_init,
-+ .smp_boot_secondary = emev2_boot_secondary,
-+#ifdef CONFIG_HOTPLUG_CPU
-+ .cpu_kill = emev2_cpu_kill,
-+ .cpu_die = shmobile_cpu_die,
-+ .cpu_disable = shmobile_cpu_disable,
-+#endif
-+};
---- a/arch/arm/mach-shmobile/smp-r8a7779.c
-+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
-@@ -87,14 +87,14 @@ static void modify_scu_cpu_psr(unsigned
- __raw_writel(tmp, scu_base + 8);
- }
-
--unsigned int __init r8a7779_get_core_count(void)
-+static unsigned int __init r8a7779_get_core_count(void)
- {
- void __iomem *scu_base = scu_base_addr();
-
- return scu_get_core_count(scu_base);
- }
-
--int r8a7779_platform_cpu_kill(unsigned int cpu)
-+static int r8a7779_platform_cpu_kill(unsigned int cpu)
- {
- struct r8a7779_pm_ch *ch = NULL;
- int ret = -EIO;
-@@ -113,12 +113,31 @@ int r8a7779_platform_cpu_kill(unsigned i
- return ret ? ret : 1;
- }
-
--void __cpuinit r8a7779_secondary_init(unsigned int cpu)
-+static int __maybe_unused r8a7779_cpu_kill(unsigned int cpu)
-+{
-+ int k;
-+
-+ /* this function is running on another CPU than the offline target,
-+ * here we need wait for shutdown code in platform_cpu_die() to
-+ * finish before asking SoC-specific code to power off the CPU core.
-+ */
-+ for (k = 0; k < 1000; k++) {
-+ if (shmobile_cpu_is_dead(cpu))
-+ return r8a7779_platform_cpu_kill(cpu);
-+
-+ mdelay(1);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static void __cpuinit r8a7779_secondary_init(unsigned int cpu)
- {
- gic_secondary_init(0);
- }
-
--int __cpuinit r8a7779_boot_secondary(unsigned int cpu)
-+static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
- {
- struct r8a7779_pm_ch *ch = NULL;
- int ret = -EIO;
-@@ -137,7 +156,7 @@ int __cpuinit r8a7779_boot_secondary(uns
- return ret;
- }
-
--void __init r8a7779_smp_prepare_cpus(void)
-+static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
- {
- int cpu = cpu_logical_map(0);
-
-@@ -156,3 +175,22 @@ void __init r8a7779_smp_prepare_cpus(voi
- r8a7779_platform_cpu_kill(2);
- r8a7779_platform_cpu_kill(3);
- }
-+
-+static void __init r8a7779_smp_init_cpus(void)
-+{
-+ unsigned int ncores = r8a7779_get_core_count();
-+
-+ shmobile_smp_init_cpus(ncores);
-+}
-+
-+struct smp_operations r8a7779_smp_ops __initdata = {
-+ .smp_init_cpus = r8a7779_smp_init_cpus,
-+ .smp_prepare_cpus = r8a7779_smp_prepare_cpus,
-+ .smp_secondary_init = r8a7779_secondary_init,
-+ .smp_boot_secondary = r8a7779_boot_secondary,
-+#ifdef CONFIG_HOTPLUG_CPU
-+ .cpu_kill = r8a7779_cpu_kill,
-+ .cpu_die = shmobile_cpu_die,
-+ .cpu_disable = shmobile_cpu_disable,
-+#endif
-+};
---- a/arch/arm/mach-shmobile/smp-sh73a0.c
-+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
-@@ -22,8 +22,10 @@
- #include <linux/smp.h>
- #include <linux/spinlock.h>
- #include <linux/io.h>
-+#include <linux/delay.h>
- #include <mach/common.h>
- #include <asm/smp_plat.h>
-+#include <mach/sh73a0.h>
- #include <asm/smp_scu.h>
- #include <asm/smp_twd.h>
- #include <asm/hardware/gic.h>
-@@ -64,19 +66,19 @@ static void modify_scu_cpu_psr(unsigned
- __raw_writel(tmp, scu_base + 8);
- }
-
--unsigned int __init sh73a0_get_core_count(void)
-+static unsigned int __init sh73a0_get_core_count(void)
- {
- void __iomem *scu_base = scu_base_addr();
-
- return scu_get_core_count(scu_base);
- }
-
--void __cpuinit sh73a0_secondary_init(unsigned int cpu)
-+static void __cpuinit sh73a0_secondary_init(unsigned int cpu)
- {
- gic_secondary_init(0);
- }
-
--int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
-+static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
- {
- cpu = cpu_logical_map(cpu);
-
-@@ -91,7 +93,7 @@ int __cpuinit sh73a0_boot_secondary(unsi
- return 0;
- }
-
--void __init sh73a0_smp_prepare_cpus(void)
-+static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
- {
- int cpu = cpu_logical_map(0);
-
-@@ -104,3 +106,41 @@ void __init sh73a0_smp_prepare_cpus(void
- /* enable cache coherency on CPU0 */
- modify_scu_cpu_psr(0, 3 << (cpu * 8));
- }
-+
-+static void __init sh73a0_smp_init_cpus(void)
-+{
-+ unsigned int ncores = sh73a0_get_core_count();
-+
-+ shmobile_smp_init_cpus(ncores);
-+}
-+
-+static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu)
-+{
-+ int k;
-+
-+ /* this function is running on another CPU than the offline target,
-+ * here we need wait for shutdown code in platform_cpu_die() to
-+ * finish before asking SoC-specific code to power off the CPU core.
-+ */
-+ for (k = 0; k < 1000; k++) {
-+ if (shmobile_cpu_is_dead(cpu))
-+ return 1;
-+
-+ mdelay(1);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+struct smp_operations sh73a0_smp_ops __initdata = {
-+ .smp_init_cpus = sh73a0_smp_init_cpus,
-+ .smp_prepare_cpus = sh73a0_smp_prepare_cpus,
-+ .smp_secondary_init = sh73a0_secondary_init,
-+ .smp_boot_secondary = sh73a0_boot_secondary,
-+#ifdef CONFIG_HOTPLUG_CPU
-+ .cpu_kill = sh73a0_cpu_kill,
-+ .cpu_die = shmobile_cpu_die,
-+ .cpu_disable = shmobile_cpu_disable,
-+#endif
-+};
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:15:53 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:09:16 +0200
-Subject: pramfs: documentation
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FAE993C.4050601@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-Documentation for PRAMFS.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
----
- Documentation/filesystems/pramfs.txt | 179 +++++++++++++++++++++++++++++++++++
- Documentation/filesystems/xip.txt | 2
- 2 files changed, 181 insertions(+)
-
---- /dev/null
-+++ b/Documentation/filesystems/pramfs.txt
-@@ -0,0 +1,179 @@
-+
-+PRAMFS Overview
-+===============
-+
-+Many embedded systems have a block of non-volatile RAM separate from
-+normal system memory, i.e. of which the kernel maintains no memory page
-+descriptors. For such systems it would be beneficial to mount a
-+fast read/write filesystem over this "I/O memory", for storing frequently
-+accessed data that must survive system reboots and power cycles or volatile
-+data avoiding to write on a disk or flash. An example usage might be system
-+logs under /var/log or debug information of a flight-recorder.
-+
-+Linux traditionally had no support for a persistent, non-volatile RAM-based
-+filesystem, persistent meaning the filesystem survives a system reboot
-+or power cycle intact. The RAM-based filesystems such as tmpfs and ramfs
-+have no actual backing store but exist entirely in the page and buffer
-+caches, hence the filesystem disappears after a system reboot or
-+power cycle.
-+
-+A relatively straightforward solution is to write a simple block driver
-+for the non-volatile RAM, and mount over it any disk-based filesystem such
-+as ext2, ext3, ext4, etc.
-+
-+But the disk-based fs over non-volatile RAM block driver approach has
-+some drawbacks:
-+
-+1. Complexity of disk-based fs: disk-based filesystems such as ext2/ext3/ext4
-+ were designed for optimum performance on spinning disk media, so they
-+ implement features such as block groups, which attempts to group inode data
-+ into a contiguous set of data blocks to minimize disk seeking when accessing
-+ files. For RAM there is no such concern; a file's data blocks can be
-+ scattered throughout the media with no access speed penalty at all. So block
-+ groups in a filesystem mounted over RAM just adds unnecessary
-+ complexity. A better approach is to use a filesystem specifically
-+ tailored to RAM media which does away with these disk-based features.
-+ This increases the efficient use of space on the media, i.e. more
-+ space is dedicated to actual file data storage and less to meta-data
-+ needed to maintain that file data.
-+
-+2. Different problems between disks and RAM: Because PRAMFS attempts to avoid
-+ filesystem corruption caused by kernel bugs, dirty pages in the page cache
-+ are not allowed to be written back to the backing-store RAM. This way, an
-+ errant write into the page cache will not get written back to the filesystem.
-+ However, if the backing-store RAM is comparable in access speed to system
-+ memory, the penalty of not using caching is minimal. With this consideration
-+ it's better to move file data directly between the user buffers and the backing
-+ store RAM, i.e. use direct I/O. This prevents the unnecessary populating of
-+ the page cache with dirty pages. However direct I/O has to be enabled at
-+ every file open. To enable direct I/O at all times for all regular files
-+ requires either that applications be modified to include the O_DIRECT flag on
-+ all file opens, or that the filesystem used performs direct I/O by default.
-+
-+The Persistent/Protected RAM Special Filesystem (PRAMFS) is a read/write
-+filesystem that has been designed to address these issues. PRAMFS is targeted
-+to fast I/O memory, and if the memory is non-volatile, the filesystem will be
-+persistent.
-+
-+In PRAMFS, direct I/O is enabled across all files in the filesystem, in other
-+words the O_DIRECT flag is forced on every open of a PRAMFS file. Also, file
-+I/O in the PRAMFS is always synchronous. There is no need to block the current
-+process while the transfer to/from the PRAMFS is in progress, since one of
-+the requirements of the PRAMFS is that the filesystem exists in fast RAM. So
-+file I/O in PRAMFS is always direct, synchronous, and never blocks.
-+
-+The data organization in PRAMFS can be thought of as an extremely simplified
-+version of ext2, such that the ratio of data to meta-data is very high.
-+
-+PRAMFS supports the execute-in-place. With XIP, instead of keeping data in the
-+page cache, the need to have a page cache copy is eliminated completely.
-+Read&write type operations are performed directly from/to the memory. For file
-+mappings, the RAM itself is mapped directly into userspace. XIP, in addition,
-+speed up the applications start-up time because it removes the needs of any
-+copies.
-+
-+PRAMFS is write protected. The page table entries that map the backing-store
-+RAM are normally marked read-only. Write operations into the filesystem
-+temporarily mark the affected pages as writeable, the write operation is
-+carried out with locks held, and then the page table entries is
-+marked read-only again.
-+This feature provides protection against filesystem corruption caused by errant
-+writes into the RAM due to kernel bugs for instance. In case there are systems
-+where the write protection is not possible (for instance the RAM cannot be
-+mapped with page tables), this feature can be disabled via the
-+CONFIG_PRAMFS_WRITE_PROTECT config option.
-+
-+PRAMFS supports extended attributes, ACLs and security labels.
-+
-+In summary, PRAMFS is a light-weight, space-efficient special filesystem that
-+is ideal for systems with a block of fast non-volatile RAM that need to access
-+data on it using a standard filesytem interface.
-+
-+Supported mount options
-+=======================
-+
-+The PRAMFS currently requires one mount option, and there are several
-+optional mount options:
-+
-+physaddr= Required. It tells PRAMFS the physical address of the
-+ start of the RAM that makes up the filesystem. The
-+ physical address must be located on a page boundary.
-+
-+init= Optional. It is used to initialize the memory to an
-+ empty filesystem. Any data in an existing filesystem
-+ will be lost if this option is given. The parameter to
-+ "init=" is the RAM in kilo/mega/giga bytes.
-+
-+bs= Optional. It is used to specify a block size. It is
-+ ignored if the "init=" option is not specified, since
-+ otherwise the block size is read from the PRAMFS
-+ super-block. The default blocksize is 2048 bytes,
-+ and the allowed block sizes are 512, 1024, 2048, and
-+ 4096.
-+
-+bpi= Optional. It is used to specify the bytes per inode
-+ ratio, i.e. for every N bytes in the filesystem, an
-+ inode will be created. This behaves the same as the "-i"
-+ option to mke2fs. It is ignored if the "init=" option is
-+ not specified.
-+
-+N= Optional. It is used to specify the number of inodes to
-+ allocate in the inode table. If the option is not
-+ specified, the bytes-per-inode ratio is used to
-+ calculate the number of inodes. If neither the "N=" or
-+ "bpi=" options are specified, the default behavior is to
-+ reserve 5% of the total space in the filesystem for the
-+ inode table. This option behaves the same as the "-N"
-+ option to mke2fs. It is ignored if the "init=" option is
-+ not specified.
-+
-+errors= Optional. It can be "cont", "remount-ro" and "panic". With the
-+ first value no action is done in case of error. With the second
-+ one the fs is mounted read-only. with the third one a kernel
-+ panic happens. Default action is to continue on error.
-+
-+acl,noacl Optional. Enable/disable the support for access control lists
-+ (disabled by default).
-+
-+user_xattr, Optional. Enable/disable the support for the user extended
-+user_noxattr attributes (disabled by default).
-+
-+noprotect Optional. Disable the memory protection (enabled by default).
-+
-+xip Optional. Enable the execute-in-place (disabled by default).
-+
-+Examples:
-+
-+mount -t pramfs -o physaddr=0x20000000,init=1M,bs=1k none /mnt/pram
-+
-+This example locates the filesystem at physical address 0x20000000, and
-+also requests an empty filesystem be initialized, of total size of one
-+megabyte and blocksize of one kilobyte. The mount point is /mnt/pram.
-+
-+mount -t pramfs -o physaddr=0x20000000 none /mnt/pram
-+
-+This example locates the filesystem at physical address 0x20000000 as in
-+the first example, but uses the intact filesystem that already exists.
-+
-+Current Limitations
-+===================
-+
-+- The RAM used for PRAMFS must be directly addressable.
-+
-+- PRAMFS does not support hard links.
-+
-+- PRAMFS supports only private memory mappings. This allows most
-+ executables to run, but programs that attempt shared memory
-+ mappings, such as X apps that use X shared memory, will fail.
-+
-+- PRAMFS does not support quota settings.
-+
-+Further Documentation
-+=====================
-+
-+If you are interested in the internal design of PRAMFS, there is
-+documentation available at the Sourceforge PRAMFS home page at
-+http://pramfs.sourceforge.net/.
-+
-+Please send bug reports/comments/feedback to the pramfs development
-+list at sourceforge: pramfs-devel@lists.sourceforge.net.
---- a/Documentation/filesystems/xip.txt
-+++ b/Documentation/filesystems/xip.txt
-@@ -48,6 +48,8 @@ blocks if needed.
- This address space operation is mutually exclusive with readpage&writepage that
- do page cache read/write operations.
- The following filesystems support it as of today:
-+- pramfs: persistent and protected RAM filesystem, see
-+ Documentation/filesystems/pramfs.txt
- - ext2: the second extended filesystem, see Documentation/filesystems/ext2.txt
-
- A set of file operations that do utilize get_xip_page can be found in
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:16:06 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:09:30 +0200
-Subject: pramfs: super operations
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FAE994A.40008@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-Super block operations.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
----
- fs/pramfs/super.c | 977 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 977 insertions(+)
-
---- /dev/null
-+++ b/fs/pramfs/super.c
-@@ -0,0 +1,977 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Super block operations.
-+ *
-+ * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ * Copyright 2003 Sony Corporation
-+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
-+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
-+ * 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 <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/parser.h>
-+#include <linux/vfs.h>
-+#include <linux/uaccess.h>
-+#include <linux/io.h>
-+#include <linux/seq_file.h>
-+#include <linux/mount.h>
-+#include <linux/mm.h>
-+#include <linux/ctype.h>
-+#include <linux/bitops.h>
-+#include <linux/magic.h>
-+#include <linux/exportfs.h>
-+#include <linux/random.h>
-+#include <linux/cred.h>
-+#include <linux/backing-dev.h>
-+#include <linux/ioport.h>
-+#include "xattr.h"
-+#include "pram.h"
-+
-+static struct super_operations pram_sops;
-+static const struct export_operations pram_export_ops;
-+static struct kmem_cache *pram_inode_cachep;
-+
-+#ifdef CONFIG_PRAMFS_TEST
-+static void *first_pram_super;
-+
-+struct pram_super_block *get_pram_super(void)
-+{
-+ return (struct pram_super_block *)first_pram_super;
-+}
-+EXPORT_SYMBOL(get_pram_super);
-+#endif
-+
-+void pram_error_mng(struct super_block *sb, const char *fmt, ...)
-+{
-+ va_list args;
-+
-+ va_start(args, fmt);
-+ printk(KERN_ERR "pramfs error: ");
-+ vprintk(fmt, args);
-+ printk("\n");
-+ va_end(args);
-+
-+ if (test_opt(sb, ERRORS_PANIC))
-+ panic("pramfs: panic from previous error\n");
-+ if (test_opt(sb, ERRORS_RO)) {
-+ printk(KERN_CRIT "pramfs err: remounting filesystem read-only");
-+ sb->s_flags |= MS_RDONLY;
-+ }
-+}
-+
-+static void pram_set_blocksize(struct super_block *sb, unsigned long size)
-+{
-+ int bits;
-+
-+ /*
-+ * We've already validated the user input and the value here must be
-+ * between PRAM_MAX_BLOCK_SIZE and PRAM_MIN_BLOCK_SIZE
-+ * and it must be a power of 2.
-+ */
-+ bits = fls(size) - 1;
-+ sb->s_blocksize_bits = bits;
-+ sb->s_blocksize = (1<<bits);
-+}
-+
-+static inline void *pram_ioremap(phys_addr_t phys_addr, ssize_t size,
-+ bool protect)
-+{
-+ void *retval;
-+
-+ /*
-+ * NOTE: Userland may not map this resource, we will mark the region so
-+ * /dev/mem and the sysfs MMIO access will not be allowed. This
-+ * restriction depends on STRICT_DEVMEM option. If this option is
-+ * disabled or not available we mark the region only as busy.
-+ */
-+ retval = request_mem_region_exclusive(phys_addr, size, "pramfs");
-+ if (!retval)
-+ goto fail;
-+
-+ retval = (__force void *)ioremap_nocache(phys_addr, size);
-+
-+ if (retval && protect)
-+ pram_writeable(retval, size, 0);
-+fail:
-+ return retval;
-+}
-+
-+static loff_t pram_max_size(int bits)
-+{
-+ loff_t res;
-+ res = (1ULL << (3*bits - 6)) - 1;
-+
-+ if (res > MAX_LFS_FILESIZE)
-+ res = MAX_LFS_FILESIZE;
-+
-+ pram_info("max file size %llu bytes\n", res);
-+ return res;
-+}
-+
-+enum {
-+ Opt_addr, Opt_bpi, Opt_size,
-+ Opt_num_inodes, Opt_mode, Opt_uid,
-+ Opt_gid, Opt_blocksize, Opt_user_xattr,
-+ Opt_nouser_xattr, Opt_noprotect,
-+ Opt_acl, Opt_noacl, Opt_xip,
-+ Opt_err_cont, Opt_err_panic, Opt_err_ro,
-+ Opt_err
-+};
-+
-+static const match_table_t tokens = {
-+ {Opt_bpi, "physaddr=%x"},
-+ {Opt_bpi, "bpi=%u"},
-+ {Opt_size, "init=%s"},
-+ {Opt_num_inodes, "N=%u"},
-+ {Opt_mode, "mode=%o"},
-+ {Opt_uid, "uid=%u"},
-+ {Opt_gid, "gid=%u"},
-+ {Opt_blocksize, "bs=%s"},
-+ {Opt_user_xattr, "user_xattr"},
-+ {Opt_user_xattr, "nouser_xattr"},
-+ {Opt_noprotect, "noprotect"},
-+ {Opt_acl, "acl"},
-+ {Opt_acl, "noacl"},
-+ {Opt_xip, "xip"},
-+ {Opt_err_cont, "errors=continue"},
-+ {Opt_err_panic, "errors=panic"},
-+ {Opt_err_ro, "errors=remount-ro"},
-+ {Opt_err, NULL},
-+};
-+
-+static phys_addr_t get_phys_addr(void **data)
-+{
-+ phys_addr_t phys_addr;
-+ char *options = (char *) *data;
-+ unsigned long long ulltmp;
-+ char *end;
-+ char org_end;
-+ int err;
-+
-+ if (!options || strncmp(options, "physaddr=", 9) != 0)
-+ return (phys_addr_t)ULLONG_MAX;
-+ options += 9;
-+ end = strchr(options, ',') ?: options + strlen(options);
-+ org_end = *end;
-+ *end = '\0';
-+ err = kstrtoull(options, 0, &ulltmp);
-+ *end = org_end;
-+ options = end;
-+ phys_addr = (phys_addr_t)ulltmp;
-+ if (err) {
-+ printk(KERN_ERR "Invalid phys addr specification: %s\n",
-+ (char *) *data);
-+ return (phys_addr_t)ULLONG_MAX;
-+ }
-+ if (phys_addr & (PAGE_SIZE - 1)) {
-+ printk(KERN_ERR "physical address 0x%16llx for pramfs isn't "
-+ "aligned to a page boundary\n",
-+ (u64)phys_addr);
-+ return (phys_addr_t)ULLONG_MAX;
-+ }
-+ if (*options == ',')
-+ options++;
-+ *data = (void *) options;
-+ return phys_addr;
-+}
-+
-+static int pram_parse_options(char *options, struct pram_sb_info *sbi,
-+ bool remount)
-+{
-+ char *p, *rest;
-+ substring_t args[MAX_OPT_ARGS];
-+ int option;
-+
-+ if (!options)
-+ return 0;
-+
-+ while ((p = strsep(&options, ",")) != NULL) {
-+ int token;
-+ if (!*p)
-+ continue;
-+
-+ token = match_token(p, tokens, args);
-+ switch (token) {
-+ case Opt_addr:
-+ if (remount)
-+ goto bad_opt;
-+ /* physaddr managed in get_phys_addr() */
-+ break;
-+ case Opt_bpi:
-+ if (remount)
-+ goto bad_opt;
-+ if (match_int(&args[0], &option))
-+ goto bad_val;
-+ sbi->bpi = option;
-+ break;
-+ case Opt_uid:
-+ if (remount)
-+ goto bad_opt;
-+ if (match_int(&args[0], &option))
-+ goto bad_val;
-+ sbi->uid = option;
-+ break;
-+ case Opt_gid:
-+ if (match_int(&args[0], &option))
-+ goto bad_val;
-+ sbi->gid = option;
-+ break;
-+ case Opt_mode:
-+ if (match_octal(&args[0], &option))
-+ goto bad_val;
-+ sbi->mode = option & 01777U;
-+ break;
-+ case Opt_size:
-+ if (remount)
-+ goto bad_opt;
-+ /* memparse() will accept a K/M/G without a digit */
-+ if (!isdigit(*args[0].from))
-+ goto bad_val;
-+ sbi->initsize = memparse(args[0].from, &rest);
-+ break;
-+ case Opt_num_inodes:
-+ if (remount)
-+ goto bad_opt;
-+ if (match_int(&args[0], &option))
-+ goto bad_val;
-+ sbi->num_inodes = option;
-+ break;
-+ case Opt_blocksize:
-+ if (remount)
-+ goto bad_opt;
-+ /* memparse() will accept a K/M/G without a digit */
-+ if (!isdigit(*args[0].from))
-+ goto bad_val;
-+ sbi->blocksize = memparse(args[0].from, &rest);
-+ if (sbi->blocksize < PRAM_MIN_BLOCK_SIZE ||
-+ sbi->blocksize > PRAM_MAX_BLOCK_SIZE ||
-+ !is_power_of_2(sbi->blocksize))
-+ goto bad_val;
-+ break;
-+ case Opt_err_panic:
-+ clear_opt(sbi->s_mount_opt, ERRORS_CONT);
-+ clear_opt(sbi->s_mount_opt, ERRORS_RO);
-+ set_opt(sbi->s_mount_opt, ERRORS_PANIC);
-+ break;
-+ case Opt_err_ro:
-+ clear_opt(sbi->s_mount_opt, ERRORS_CONT);
-+ clear_opt(sbi->s_mount_opt, ERRORS_PANIC);
-+ set_opt(sbi->s_mount_opt, ERRORS_RO);
-+ break;
-+ case Opt_err_cont:
-+ clear_opt(sbi->s_mount_opt, ERRORS_RO);
-+ clear_opt(sbi->s_mount_opt, ERRORS_PANIC);
-+ set_opt(sbi->s_mount_opt, ERRORS_CONT);
-+ break;
-+ case Opt_noprotect:
-+#ifdef CONFIG_PRAMFS_WRITE_PROTECT
-+ if (remount)
-+ goto bad_opt;
-+ clear_opt(sbi->s_mount_opt, PROTECT);
-+#endif
-+ break;
-+#ifdef CONFIG_PRAMFS_XATTR
-+ case Opt_user_xattr:
-+ set_opt(sbi->s_mount_opt, XATTR_USER);
-+ break;
-+ case Opt_nouser_xattr:
-+ clear_opt(sbi->s_mount_opt, XATTR_USER);
-+ break;
-+#else
-+ case Opt_user_xattr:
-+ case Opt_nouser_xattr:
-+ pram_info("(no)user_xattr options not supported\n");
-+ break;
-+#endif
-+#ifdef CONFIG_PRAMFS_POSIX_ACL
-+ case Opt_acl:
-+ set_opt(sbi->s_mount_opt, POSIX_ACL);
-+ break;
-+ case Opt_noacl:
-+ clear_opt(sbi->s_mount_opt, POSIX_ACL);
-+ break;
-+#else
-+ case Opt_acl:
-+ case Opt_noacl:
-+ pram_info("(no)acl options not supported\n");
-+ break;
-+#endif
-+ case Opt_xip:
-+#ifdef CONFIG_PRAMFS_XIP
-+ if (remount)
-+ goto bad_opt;
-+ set_opt(sbi->s_mount_opt, XIP);
-+ break;
-+#else
-+ pram_info("xip option not supported\n");
-+ break;
-+#endif
-+ default: {
-+ goto bad_opt;
-+ }
-+ }
-+ }
-+
-+ return 0;
-+
-+bad_val:
-+ printk(KERN_ERR "Bad value '%s' for mount option '%s'\n", args[0].from,
-+ p);
-+ return -EINVAL;
-+bad_opt:
-+ printk(KERN_ERR "Bad mount option: \"%s\"\n", p);
-+ return -EINVAL;
-+}
-+
-+static struct pram_inode *pram_init(struct super_block *sb, unsigned long size)
-+{
-+ unsigned long bpi, num_inodes, bitmap_size, blocksize, num_blocks;
-+ u64 bitmap_start;
-+ struct pram_inode *root_i;
-+ struct pram_super_block *super;
-+ struct pram_sb_info *sbi = PRAM_SB(sb);
-+
-+ pram_info("creating an empty pramfs of size %lu\n", size);
-+ sbi->virt_addr = pram_ioremap(sbi->phys_addr, size,
-+ pram_is_protected(sb));
-+
-+ if (!sbi->virt_addr) {
-+ printk(KERN_ERR "ioremap of the pramfs image failed\n");
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+#ifdef CONFIG_PRAMFS_TEST
-+ if (!first_pram_super)
-+ first_pram_super = sbi->virt_addr;
-+#endif
-+
-+ if (!sbi->blocksize)
-+ blocksize = PRAM_DEF_BLOCK_SIZE;
-+ else
-+ blocksize = sbi->blocksize;
-+
-+ pram_set_blocksize(sb, blocksize);
-+ blocksize = sb->s_blocksize;
-+
-+ if (sbi->blocksize && sbi->blocksize != blocksize)
-+ sbi->blocksize = blocksize;
-+
-+ if (size < blocksize) {
-+ printk(KERN_ERR "size smaller then block size\n");
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ if (!sbi->bpi)
-+ /*
-+ * default is that 5% of the filesystem is
-+ * devoted to the inode table
-+ */
-+ bpi = 20 * PRAM_INODE_SIZE;
-+ else
-+ bpi = sbi->bpi;
-+
-+ if (!sbi->num_inodes)
-+ num_inodes = size / bpi;
-+ else
-+ num_inodes = sbi->num_inodes;
-+
-+ /*
-+ * up num_inodes such that the end of the inode table
-+ * (and start of bitmap) is on a block boundary
-+ */
-+ bitmap_start = (PRAM_SB_SIZE*2) + (num_inodes<<PRAM_INODE_BITS);
-+ if (bitmap_start & (blocksize - 1))
-+ bitmap_start = (bitmap_start + blocksize) &
-+ ~(blocksize-1);
-+ num_inodes = (bitmap_start - (PRAM_SB_SIZE*2)) >> PRAM_INODE_BITS;
-+
-+ if (sbi->num_inodes && num_inodes != sbi->num_inodes)
-+ sbi->num_inodes = num_inodes;
-+
-+ num_blocks = (size - bitmap_start) >> sb->s_blocksize_bits;
-+
-+ if (!num_blocks) {
-+ printk(KERN_ERR "num blocks equals to zero\n");
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ /* calc the data blocks in-use bitmap size in bytes */
-+ if (num_blocks & 7)
-+ bitmap_size = ((num_blocks + 8) & ~7) >> 3;
-+ else
-+ bitmap_size = num_blocks >> 3;
-+ /* round it up to the nearest blocksize boundary */
-+ if (bitmap_size & (blocksize - 1))
-+ bitmap_size = (bitmap_size + blocksize) & ~(blocksize-1);
-+
-+ pram_info("blocksize %lu, num inodes %lu, num blocks %lu\n",
-+ blocksize, num_inodes, num_blocks);
-+ pram_dbg("bitmap start 0x%08x, bitmap size %lu\n",
-+ (unsigned int)bitmap_start, bitmap_size);
-+ pram_dbg("max name length %d\n", (unsigned int)PRAM_NAME_LEN);
-+
-+ super = pram_get_super(sb);
-+ pram_memunlock_range(sb, super, bitmap_start + bitmap_size);
-+
-+ /* clear out super-block and inode table */
-+ memset(super, 0, bitmap_start);
-+ super->s_size = cpu_to_be64(size);
-+ super->s_blocksize = cpu_to_be32(blocksize);
-+ super->s_inodes_count = cpu_to_be32(num_inodes);
-+ super->s_blocks_count = cpu_to_be32(num_blocks);
-+ super->s_free_inodes_count = cpu_to_be32(num_inodes - 1);
-+ super->s_bitmap_blocks = cpu_to_be32(bitmap_size >>
-+ sb->s_blocksize_bits);
-+ super->s_free_blocks_count =
-+ cpu_to_be32(num_blocks - be32_to_cpu(super->s_bitmap_blocks));
-+ super->s_free_inode_hint = cpu_to_be32(1);
-+ super->s_bitmap_start = cpu_to_be64(bitmap_start);
-+ super->s_magic = cpu_to_be16(PRAM_SUPER_MAGIC);
-+ pram_sync_super(super);
-+
-+ root_i = pram_get_inode(sb, PRAM_ROOT_INO);
-+
-+ root_i->i_mode = cpu_to_be16(sbi->mode | S_IFDIR);
-+ root_i->i_uid = cpu_to_be32(sbi->uid);
-+ root_i->i_gid = cpu_to_be32(sbi->gid);
-+ root_i->i_links_count = cpu_to_be16(2);
-+ root_i->i_d.d_parent = cpu_to_be64(PRAM_ROOT_INO);
-+ pram_sync_inode(root_i);
-+
-+ pram_init_bitmap(sb);
-+
-+ pram_memlock_range(sb, super, bitmap_start + bitmap_size);
-+
-+ return root_i;
-+}
-+
-+static inline void set_default_opts(struct pram_sb_info *sbi)
-+{
-+ set_opt(sbi->s_mount_opt, PROTECT);
-+ set_opt(sbi->s_mount_opt, ERRORS_CONT);
-+}
-+
-+static void pram_root_check(struct super_block *sb, struct pram_inode *root_pi)
-+{
-+ pram_memunlock_inode(sb, root_pi);
-+
-+ if (root_pi->i_d.d_next) {
-+ pram_warn("root->next not NULL, trying to fix\n");
-+ goto fail1;
-+ }
-+
-+ if (!S_ISDIR(be16_to_cpu(root_pi->i_mode))) {
-+ pram_warn("root is not a directory, trying to fix\n");
-+ goto fail2;
-+ }
-+
-+ if (pram_calc_checksum((u8 *)root_pi, PRAM_INODE_SIZE)) {
-+ pram_warn("checksum error in root inode, trying to fix\n");
-+ goto fail3;
-+ }
-+ fail1:
-+ root_pi->i_d.d_next = 0;
-+ fail2:
-+ root_pi->i_mode = cpu_to_be16(S_IRWXUGO|S_ISVTX|S_IFDIR);
-+ fail3:
-+ root_pi->i_d.d_parent = cpu_to_be64(PRAM_ROOT_INO);
-+ pram_memlock_inode(sb, root_pi);
-+}
-+
-+static int pram_fill_super(struct super_block *sb, void *data, int silent)
-+{
-+ struct pram_super_block *super, *super_redund;
-+ struct pram_inode *root_pi;
-+ struct pram_sb_info *sbi = NULL;
-+ struct inode *root_i = NULL;
-+ unsigned long blocksize, initsize = 0;
-+ u32 random = 0;
-+ int retval = -EINVAL;
-+
-+ BUILD_BUG_ON(sizeof(struct pram_super_block) > PRAM_SB_SIZE);
-+ BUILD_BUG_ON(sizeof(struct pram_inode) > PRAM_INODE_SIZE);
-+
-+ sbi = kzalloc(sizeof(struct pram_sb_info), GFP_KERNEL);
-+ if (!sbi)
-+ return -ENOMEM;
-+ sb->s_fs_info = sbi;
-+
-+ set_default_opts(sbi);
-+
-+#ifdef CONFIG_PRAMFS_XATTR
-+ spin_lock_init(&sbi->desc_tree_lock);
-+ sbi->desc_tree.rb_node = NULL;
-+#endif
-+
-+ sbi->phys_addr = get_phys_addr(&data);
-+ if (sbi->phys_addr == (phys_addr_t)ULLONG_MAX)
-+ goto out;
-+
-+ get_random_bytes(&random, sizeof(u32));
-+ atomic_set(&sbi->next_generation, random);
-+
-+ /* Init with default values */
-+ sbi->mode = (S_IRWXUGO | S_ISVTX);
-+ sbi->uid = current_fsuid();
-+ sbi->gid = current_fsgid();
-+
-+ if (pram_parse_options(data, sbi, 0))
-+ goto out;
-+
-+ if (test_opt(sb, XIP) && test_opt(sb, PROTECT)) {
-+ printk(KERN_ERR "xip and protect options both enabled\n");
-+ goto out;
-+ }
-+
-+ if (test_opt(sb, XIP) && sbi->blocksize != PAGE_SIZE) {
-+ printk(KERN_ERR "blocksize not equal to page size "
-+ "and xip enabled\n");
-+ goto out;
-+ }
-+
-+ initsize = sbi->initsize;
-+
-+ /* Init a new pramfs instance */
-+ if (initsize) {
-+ root_pi = pram_init(sb, initsize);
-+
-+ if (IS_ERR(root_pi))
-+ goto out;
-+
-+ super = pram_get_super(sb);
-+
-+ goto setup_sb;
-+ }
-+
-+ pram_dbg("checking physical address 0x%016llx for pramfs image\n",
-+ (u64)sbi->phys_addr);
-+
-+ /* Map only one page for now. Will remap it when fs size is known. */
-+ initsize = PAGE_SIZE;
-+ sbi->virt_addr = pram_ioremap(sbi->phys_addr, initsize,
-+ pram_is_protected(sb));
-+ if (!sbi->virt_addr) {
-+ printk(KERN_ERR "ioremap of the pramfs image failed\n");
-+ goto out;
-+ }
-+
-+ super = pram_get_super(sb);
-+ super_redund = pram_get_redund_super(sb);
-+
-+ /* Do sanity checks on the superblock */
-+ if (be16_to_cpu(super->s_magic) != PRAM_SUPER_MAGIC) {
-+ if (be16_to_cpu(super_redund->s_magic) != PRAM_SUPER_MAGIC) {
-+ if (!silent)
-+ printk(KERN_ERR "Can't find a valid pramfs "
-+ "partition\n");
-+ goto out;
-+ } else {
-+ pram_warn("Error in super block: try to repair it with "
-+ "the redundant copy");
-+ /* Try to auto-recover the super block */
-+ pram_memunlock_super(sb, super);
-+ memcpy(super, super_redund, PRAM_SB_SIZE);
-+ pram_memlock_super(sb, super);
-+ }
-+ }
-+
-+ /* Read the superblock */
-+ if (pram_calc_checksum((u8 *)super, PRAM_SB_SIZE)) {
-+ if (pram_calc_checksum((u8 *)super_redund, PRAM_SB_SIZE)) {
-+ printk(KERN_ERR "checksum error in super block\n");
-+ goto out;
-+ } else {
-+ pram_warn("Error in super block: try to repair it with "
-+ "the redundant copy");
-+ /* Try to auto-recover the super block */
-+ pram_memunlock_super(sb, super);
-+ memcpy(super, super_redund, PRAM_SB_SIZE);
-+ pram_memlock_super(sb, super);
-+ }
-+ }
-+
-+ blocksize = be32_to_cpu(super->s_blocksize);
-+ pram_set_blocksize(sb, blocksize);
-+
-+ initsize = be64_to_cpu(super->s_size);
-+ pram_info("pramfs image appears to be %lu KB in size\n", initsize>>10);
-+ pram_info("blocksize %lu\n", blocksize);
-+
-+ /* Read the root inode */
-+ root_pi = pram_get_inode(sb, PRAM_ROOT_INO);
-+
-+ /* Check that the root inode is in a sane state */
-+ pram_root_check(sb, root_pi);
-+
-+ /* Remap the whole filesystem now */
-+ if (pram_is_protected(sb))
-+ pram_writeable(sbi->virt_addr, PAGE_SIZE, 1);
-+ iounmap((void __iomem *)sbi->virt_addr);
-+ release_mem_region(sbi->phys_addr, PAGE_SIZE);
-+ sbi->virt_addr = pram_ioremap(sbi->phys_addr, initsize,
-+ pram_is_protected(sb));
-+ if (!sbi->virt_addr) {
-+ printk(KERN_ERR "ioremap of the pramfs image failed\n");
-+ goto out;
-+ }
-+ super = pram_get_super(sb);
-+
-+#ifdef CONFIG_PRAMFS_TEST
-+ if (!first_pram_super)
-+ first_pram_super = sbi->virt_addr;
-+#endif
-+
-+ /* Set it all up.. */
-+ setup_sb:
-+ sb->s_magic = be16_to_cpu(super->s_magic);
-+ sb->s_op = &pram_sops;
-+ sb->s_maxbytes = pram_max_size(sb->s_blocksize_bits);
-+ sb->s_time_gran = 1;
-+ sb->s_export_op = &pram_export_ops;
-+ sb->s_xattr = pram_xattr_handlers;
-+#ifdef CONFIG_PRAMFS_POSIX_ACL
-+ sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
-+ (sbi->s_mount_opt & PRAM_MOUNT_POSIX_ACL) ?
-+ MS_POSIXACL : 0;
-+#endif
-+ sb->s_flags |= MS_NOSEC;
-+ root_i = pram_iget(sb, PRAM_ROOT_INO);
-+ if (IS_ERR(root_i)) {
-+ retval = PTR_ERR(root_i);
-+ goto out;
-+ }
-+
-+ sb->s_root = d_alloc_root(root_i);
-+ if (!sb->s_root) {
-+ iput(root_i);
-+ printk(KERN_ERR "get pramfs root inode failed\n");
-+ retval = -ENOMEM;
-+ goto out;
-+ }
-+
-+ retval = 0;
-+ return retval;
-+ out:
-+ if (sbi->virt_addr) {
-+ if (pram_is_protected(sb))
-+ pram_writeable(sbi->virt_addr, initsize, 1);
-+ iounmap((void __iomem *)sbi->virt_addr);
-+ release_mem_region(sbi->phys_addr, initsize);
-+ }
-+
-+ kfree(sbi);
-+ return retval;
-+}
-+
-+int pram_statfs(struct dentry *d, struct kstatfs *buf)
-+{
-+ struct super_block *sb = d->d_sb;
-+ struct pram_super_block *ps = pram_get_super(sb);
-+
-+ buf->f_type = PRAM_SUPER_MAGIC;
-+ buf->f_bsize = sb->s_blocksize;
-+ buf->f_blocks = be32_to_cpu(ps->s_blocks_count);
-+ buf->f_bfree = buf->f_bavail = pram_count_free_blocks(sb);
-+ buf->f_files = be32_to_cpu(ps->s_inodes_count);
-+ buf->f_ffree = be32_to_cpu(ps->s_free_inodes_count);
-+ buf->f_namelen = PRAM_NAME_LEN;
-+ return 0;
-+}
-+
-+static int pram_show_options(struct seq_file *seq, struct vfsmount *vfs)
-+{
-+ struct pram_sb_info *sbi = PRAM_SB(vfs->mnt_sb);
-+
-+ seq_printf(seq, ",physaddr=0x%016llx", (u64)sbi->phys_addr);
-+ if (sbi->initsize)
-+ seq_printf(seq, ",init=%luk", sbi->initsize >> 10);
-+ if (sbi->blocksize)
-+ seq_printf(seq, ",bs=%lu", sbi->blocksize);
-+ if (sbi->bpi)
-+ seq_printf(seq, ",bpi=%lu", sbi->bpi);
-+ if (sbi->num_inodes)
-+ seq_printf(seq, ",N=%lu", sbi->num_inodes);
-+ if (sbi->mode != (S_IRWXUGO | S_ISVTX))
-+ seq_printf(seq, ",mode=%03o", sbi->mode);
-+ if (sbi->uid != 0)
-+ seq_printf(seq, ",uid=%u", sbi->uid);
-+ if (sbi->gid != 0)
-+ seq_printf(seq, ",gid=%u", sbi->gid);
-+ if (test_opt(vfs->mnt_sb, ERRORS_RO))
-+ seq_puts(seq, ",errors=remount-ro");
-+ if (test_opt(vfs->mnt_sb, ERRORS_PANIC))
-+ seq_puts(seq, ",errors=panic");
-+#ifdef CONFIG_PRAMFS_WRITE_PROTECT
-+ /* memory protection enabled by default */
-+ if (!test_opt(vfs->mnt_sb, PROTECT))
-+ seq_puts(seq, ",noprotect");
-+#else
-+ /*
-+ * If it's not compiled say to the user that there
-+ * isn't the protection.
-+ */
-+ seq_puts(seq, ",noprotect");
-+#endif
-+
-+#ifdef CONFIG_PRAMFS_XATTR
-+ /* user xattr not enabled by default */
-+ if (test_opt(vfs->mnt_sb, XATTR_USER))
-+ seq_puts(seq, ",user_xattr");
-+#endif
-+
-+#ifdef CONFIG_PRAMFS_POSIX_ACL
-+ /* acl not enabled by default */
-+ if (test_opt(vfs->mnt_sb, POSIX_ACL))
-+ seq_puts(seq, ",acl");
-+#endif
-+
-+#ifdef CONFIG_PRAMFS_XIP
-+ /* xip not enabled by default */
-+ if (test_opt(vfs->mnt_sb, XIP))
-+ seq_puts(seq, ",xip");
-+#endif
-+
-+ return 0;
-+}
-+
-+int pram_remount(struct super_block *sb, int *mntflags, char *data)
-+{
-+ unsigned long old_sb_flags;
-+ unsigned long old_mount_opt;
-+ struct pram_super_block *ps;
-+ struct pram_sb_info *sbi = PRAM_SB(sb);
-+ int ret = -EINVAL;
-+
-+ /* Store the old options */
-+ lock_super(sb);
-+ old_sb_flags = sb->s_flags;
-+ old_mount_opt = sbi->s_mount_opt;
-+
-+ if (pram_parse_options(data, sbi, 1))
-+ goto restore_opt;
-+
-+ sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
-+ ((sbi->s_mount_opt & PRAM_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
-+
-+ if ((*mntflags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {
-+ ps = pram_get_super(sb);
-+ pram_memunlock_super(sb, ps);
-+ /* update mount time */
-+ ps->s_mtime = cpu_to_be32(get_seconds());
-+ pram_memlock_super(sb, ps);
-+ }
-+
-+ unlock_super(sb);
-+ ret = 0;
-+ return ret;
-+
-+ restore_opt:
-+ sb->s_flags = old_sb_flags;
-+ sbi->s_mount_opt = old_mount_opt;
-+ unlock_super(sb);
-+ return ret;
-+}
-+
-+static void pram_put_super(struct super_block *sb)
-+{
-+ struct pram_sb_info *sbi = PRAM_SB(sb);
-+ struct pram_super_block *ps = pram_get_super(sb);
-+ u64 size = be64_to_cpu(ps->s_size);
-+
-+#ifdef CONFIG_PRAMFS_TEST
-+ if (first_pram_super == sbi->virt_addr)
-+ first_pram_super = NULL;
-+#endif
-+
-+ pram_xattr_put_super(sb);
-+ /* It's unmount time, so unmap the pramfs memory */
-+ if (sbi->virt_addr) {
-+ if (pram_is_protected(sb))
-+ pram_writeable(sbi->virt_addr, size, 1);
-+ iounmap(sbi->virt_addr);
-+ sbi->virt_addr = NULL;
-+ release_mem_region(sbi->phys_addr, size);
-+ }
-+
-+ sb->s_fs_info = NULL;
-+ kfree(sbi);
-+}
-+
-+static struct inode *pram_alloc_inode(struct super_block *sb)
-+{
-+ struct pram_inode_vfs *vi = (struct pram_inode_vfs *)
-+ kmem_cache_alloc(pram_inode_cachep, GFP_NOFS);
-+ if (!vi)
-+ return NULL;
-+ vi->vfs_inode.i_version = 1;
-+ return &vi->vfs_inode;
-+}
-+
-+static void pram_i_callback(struct rcu_head *head)
-+{
-+ struct inode *inode = container_of(head, struct inode, i_rcu);
-+ INIT_LIST_HEAD(&inode->i_dentry);
-+ kmem_cache_free(pram_inode_cachep, PRAM_I(inode));
-+}
-+
-+static void pram_destroy_inode(struct inode *inode)
-+{
-+ call_rcu(&inode->i_rcu, pram_i_callback);
-+}
-+
-+static void init_once(void *foo)
-+{
-+ struct pram_inode_vfs *vi = (struct pram_inode_vfs *) foo;
-+
-+#ifdef CONFIG_PRAMFS_XATTR
-+ init_rwsem(&vi->xattr_sem);
-+#endif
-+ mutex_init(&vi->i_meta_mutex);
-+ mutex_init(&vi->i_link_mutex);
-+ inode_init_once(&vi->vfs_inode);
-+}
-+
-+static int __init init_inodecache(void)
-+{
-+ pram_inode_cachep = kmem_cache_create("pram_inode_cache",
-+ sizeof(struct pram_inode_vfs),
-+ 0, (SLAB_RECLAIM_ACCOUNT|
-+ SLAB_MEM_SPREAD),
-+ init_once);
-+ if (pram_inode_cachep == NULL)
-+ return -ENOMEM;
-+ return 0;
-+}
-+
-+static void destroy_inodecache(void)
-+{
-+ kmem_cache_destroy(pram_inode_cachep);
-+}
-+
-+/*
-+ * the super block writes are all done "on the fly", so the
-+ * super block is never in a "dirty" state, so there's no need
-+ * for write_super.
-+ */
-+static struct super_operations pram_sops = {
-+ .alloc_inode = pram_alloc_inode,
-+ .destroy_inode = pram_destroy_inode,
-+ .write_inode = pram_write_inode,
-+ .dirty_inode = pram_dirty_inode,
-+ .evict_inode = pram_evict_inode,
-+ .put_super = pram_put_super,
-+ .statfs = pram_statfs,
-+ .remount_fs = pram_remount,
-+ .show_options = pram_show_options,
-+};
-+
-+static struct dentry *pram_mount(struct file_system_type *fs_type,
-+ int flags, const char *dev_name, void *data)
-+{
-+ return mount_nodev(fs_type, flags, data, pram_fill_super);
-+}
-+
-+static struct file_system_type pram_fs_type = {
-+ .owner = THIS_MODULE,
-+ .name = "pramfs",
-+ .mount = pram_mount,
-+ .kill_sb = kill_anon_super,
-+};
-+
-+static struct inode *pram_nfs_get_inode(struct super_block *sb,
-+ u64 ino, u32 generation)
-+{
-+ struct pram_super_block *ps = pram_get_super(sb);
-+ struct inode *inode;
-+
-+ if (ino < PRAM_ROOT_INO)
-+ return ERR_PTR(-ESTALE);
-+ if (((ino - PRAM_ROOT_INO) >> PRAM_INODE_BITS) >
-+ be32_to_cpu(ps->s_inodes_count))
-+ return ERR_PTR(-ESTALE);
-+
-+ inode = pram_iget(sb, ino);
-+ if (IS_ERR(inode))
-+ return ERR_CAST(inode);
-+ if (generation && inode->i_generation != generation) {
-+ /* we didn't find the right inode.. */
-+ iput(inode);
-+ return ERR_PTR(-ESTALE);
-+ }
-+ return inode;
-+}
-+
-+static struct dentry *
-+pram_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
-+ int fh_type)
-+{
-+ return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
-+ pram_nfs_get_inode);
-+}
-+
-+static struct dentry *
-+pram_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len,
-+ int fh_type)
-+{
-+ return generic_fh_to_parent(sb, fid, fh_len, fh_type,
-+ pram_nfs_get_inode);
-+}
-+
-+static const struct export_operations pram_export_ops = {
-+ .fh_to_dentry = pram_fh_to_dentry,
-+ .fh_to_parent = pram_fh_to_parent,
-+ .get_parent = pram_get_parent,
-+};
-+
-+static int __init init_pram_fs(void)
-+{
-+ int rc = 0;
-+
-+ rc = init_pram_xattr();
-+ if (rc)
-+ return rc;
-+
-+ rc = init_inodecache();
-+ if (rc)
-+ goto out1;
-+
-+ rc = bdi_init(&pram_backing_dev_info);
-+ if (rc)
-+ goto out2;
-+
-+ rc = register_filesystem(&pram_fs_type);
-+ if (rc)
-+ goto out3;
-+
-+ return 0;
-+
-+out3:
-+ bdi_destroy(&pram_backing_dev_info);
-+out2:
-+ destroy_inodecache();
-+out1:
-+ exit_pram_xattr();
-+ return rc;
-+}
-+
-+static void __exit exit_pram_fs(void)
-+{
-+ unregister_filesystem(&pram_fs_type);
-+ bdi_destroy(&pram_backing_dev_info);
-+ destroy_inodecache();
-+ exit_pram_xattr();
-+}
-+
-+MODULE_AUTHOR("Marco Stornelli <marco.stornelli@gmail.com>");
-+MODULE_DESCRIPTION("Protected/Persistent RAM Filesystem");
-+MODULE_LICENSE("GPL");
-+
-+module_init(init_pram_fs)
-+module_exit(exit_pram_fs)
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:16:22 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:09:45 +0200
-Subject: pramfs: inode operations
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FAE9959.8090902@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-Inode methods (allocate/free/read/write).
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
----
- fs/pramfs/inode.c | 803 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 803 insertions(+)
-
---- /dev/null
-+++ b/fs/pramfs/inode.c
-@@ -0,0 +1,803 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Inode methods (allocate/free/read/write).
-+ *
-+ * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ * Copyright 2003 Sony Corporation
-+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
-+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
-+ * 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 <linux/fs.h>
-+#include <linux/sched.h>
-+#include <linux/highuid.h>
-+#include <linux/module.h>
-+#include <linux/mpage.h>
-+#include <linux/backing-dev.h>
-+#include"pram.h"
-+#include"xattr.h"
-+#include"xip.h"
-+#include"acl.h"
-+
-+struct backing_dev_info pram_backing_dev_info __read_mostly = {
-+ .ra_pages = 0,/* No readahead */
-+ .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK,
-+};
-+
-+/*
-+ * allocate a data blockfor inode andreturn it's absolute blocknr.
-+ * Zeroes out the blockif zero set. Increments inode->i_blocks.
-+ */
-+static int pram_new_data_block(struct inode *inode,unsigned long *blocknr,
-+ int zero)
-+{
-+ int errval = pram_new_block(inode->i_sb, blocknr, zero);
-+
-+ if (!errval) {
-+ struct pram_inode *pi = pram_get_inode(inode->i_sb,
-+ inode->i_ino);
-+ inode->i_blocks++;
-+ pram_memunlock_inode(inode->i_sb, pi);
-+ pi->i_blocks = cpu_to_be32(inode->i_blocks);
-+ pram_memlock_inode(inode->i_sb, pi);
-+ }
-+
-+ return errval;
-+}
-+
-+/*
-+ * find the offset to the block represented by the given inode's file
-+ * relative block number.
-+ */
-+u64 pram_find_data_block(struct inode *inode,unsigned long file_blocknr)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_inode *pi;
-+ u64 *row;/* ptr to row block */
-+ u64 *col;/* ptr to column blocks */
-+ u64 bp = 0;
-+ unsigned int i_row, i_col;
-+ unsigned int N = sb->s_blocksize >> 3;/* num block ptrs per block */
-+ unsigned int Nbits = sb->s_blocksize_bits - 3;
-+
-+ pi = pram_get_inode(sb, inode->i_ino);
-+
-+ i_row = file_blocknr >> Nbits;
-+ i_col = file_blocknr & (N-1);
-+
-+ row = pram_get_block(sb, be64_to_cpu(pi->i_type.reg.row_block));
-+ if (row) {
-+ col = pram_get_block(sb, be64_to_cpu(row[i_row]));
-+ if (col)
-+ bp = be64_to_cpu(col[i_col]);
-+ }
-+
-+ return bp;
-+}
-+
-+/*
-+ * Free data blocks from inode in the range start <=> end
-+ */
-+static void __pram_truncate_blocks(struct inode *inode, loff_t start,
-+ loff_t end)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_inode *pi = pram_get_inode(sb, inode->i_ino);
-+ int N = sb->s_blocksize >> 3;/* num block ptrs per block */
-+ int Nbits = sb->s_blocksize_bits - 3;
-+ int first_row_index, last_row_index, i, j;
-+ unsigned long blocknr, first_blocknr, last_blocknr;
-+ unsigned int freed = 0;
-+ u64 *row;/* ptr to row block */
-+ u64 *col;/* ptr to column blocks */
-+
-+ if (!pi->i_type.reg.row_block)
-+ return;
-+
-+ first_blocknr = (start + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
-+
-+ if (pi->i_flags & cpu_to_be32(PRAM_EOFBLOCKS_FL))
-+ last_blocknr = (1UL << (2*sb->s_blocksize_bits - 6)) - 1;
-+ else
-+ last_blocknr = end >> sb->s_blocksize_bits;
-+
-+ if (first_blocknr > last_blocknr)
-+ return;
-+
-+ first_row_index = first_blocknr >> Nbits;
-+ last_row_index = last_blocknr >> Nbits;
-+
-+ row = pram_get_block(sb, be64_to_cpu(pi->i_type.reg.row_block));
-+
-+ for (i = first_row_index; i <= last_row_index; i++) {
-+ int first_col_index = (i == first_row_index) ?
-+ first_blocknr & (N-1) : 0;
-+ int last_col_index = (i == last_row_index) ?
-+ last_blocknr & (N-1) : N-1;
-+
-+ if (unlikely(!row[i]))
-+ continue;
-+
-+ col = pram_get_block(sb, be64_to_cpu(row[i]));
-+
-+ for (j = first_col_index; j <= last_col_index; j++) {
-+
-+ if (unlikely(!col[j]))
-+ continue;
-+
-+ blocknr = pram_get_blocknr(sb, be64_to_cpu(col[j]));
-+ pram_free_block(sb, blocknr);
-+ freed++;
-+ pram_memunlock_block(sb, col);
-+ col[j] = 0;
-+ pram_memlock_block(sb, col);
-+ }
-+
-+ if (first_col_index == 0) {
-+ blocknr = pram_get_blocknr(sb, be64_to_cpu(row[i]));
-+ pram_free_block(sb, blocknr);
-+ pram_memunlock_block(sb, row);
-+ row[i] = 0;
-+ pram_memlock_block(sb, row);
-+ }
-+ }
-+
-+ inode->i_blocks -= freed;
-+
-+ if (start == 0) {
-+ blocknr = pram_get_blocknr(sb,
-+ be64_to_cpu(pi->i_type.reg.row_block));
-+ pram_free_block(sb, blocknr);
-+ pram_memunlock_inode(sb, pi);
-+ pi->i_type.reg.row_block = 0;
-+ goto update_blocks;
-+ }
-+ pram_memunlock_inode(sb, pi);
-+
-+ update_blocks:
-+ pi->i_blocks = cpu_to_be32(inode->i_blocks);
-+ pram_memlock_inode(sb, pi);
-+}
-+
-+static void pram_truncate_blocks(struct inode *inode, loff_t start, loff_t end)
-+{
-+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-+ S_ISLNK(inode->i_mode)))
-+ return;
-+ if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-+ return;
-+
-+ __pram_truncate_blocks(inode, start, end);
-+ inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
-+ pram_update_inode(inode);
-+}
-+
-+/*
-+ * Allocate num data blocksfor inode, starting at given file-relative
-+ * block number.
-+ */
-+int pram_alloc_blocks(struct inode *inode,int file_blocknr,unsigned int num)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_inode *pi = pram_get_inode(sb, inode->i_ino);
-+ int N = sb->s_blocksize >> 3;/* num block ptrs per block */
-+ int Nbits = sb->s_blocksize_bits - 3;
-+ int first_file_blocknr;
-+ int last_file_blocknr;
-+ int first_row_index, last_row_index;
-+ int i, j, errval;
-+ unsigned long blocknr;
-+ u64 *row;
-+ u64 *col;
-+
-+ if (!pi->i_type.reg.row_block) {
-+ /* alloc the 2nd order array block */
-+ errval = pram_new_block(sb, &blocknr, 1);
-+ if (errval) {
-+ pram_dbg("failed to alloc 2nd order array block\n");
-+ goto fail;
-+ }
-+ pram_memunlock_inode(sb, pi);
-+ pi->i_type.reg.row_block = cpu_to_be64(pram_get_block_off(sb,
-+ blocknr));
-+ pram_memlock_inode(sb, pi);
-+ }
-+
-+ row = pram_get_block(sb, be64_to_cpu(pi->i_type.reg.row_block));
-+
-+ first_file_blocknr = file_blocknr;
-+ last_file_blocknr = file_blocknr + num - 1;
-+
-+ first_row_index = first_file_blocknr >> Nbits;
-+ last_row_index = last_file_blocknr >> Nbits;
-+
-+ for (i = first_row_index; i <= last_row_index; i++) {
-+ int first_col_index, last_col_index;
-+
-+ /*
-+ * we are starting anew row, so make sure
-+ * there is a block allocatedfor the row.
-+ */
-+ if (!row[i]) {
-+ /* allocate the row block */
-+ errval = pram_new_block(sb, &blocknr, 1);
-+ if (errval) {
-+ pram_dbg("failed to alloc row block\n");
-+ goto fail;
-+ }
-+ pram_memunlock_block(sb, row);
-+ row[i] = cpu_to_be64(pram_get_block_off(sb, blocknr));
-+ pram_memlock_block(sb, row);
-+ }
-+ col = pram_get_block(sb, be64_to_cpu(row[i]));
-+
-+ first_col_index = (i == first_row_index) ?
-+ first_file_blocknr & (N-1) : 0;
-+
-+ last_col_index = (i == last_row_index) ?
-+ last_file_blocknr & (N-1) : N-1;
-+
-+ for (j = first_col_index; j <= last_col_index; j++) {
-+ if (!col[j]) {
-+ errval = pram_new_data_block(inode, &blocknr,
-+ 1);
-+ if (errval) {
-+ pram_dbg("fail to alloc data block\n");
-+ /* For later recovery in truncate... */
-+ pram_memunlock_inode(inode->i_sb, pi);
-+ pi->i_flags |= cpu_to_be32(PRAM_EOFBLOCKS_FL);
-+ pram_memlock_inode(inode->i_sb, pi);
-+ goto fail;
-+ }
-+ pram_memunlock_block(sb, col);
-+ col[j] = cpu_to_be64(pram_get_block_off(sb,
-+ blocknr));
-+ pram_memlock_block(sb, col);
-+ }
-+ }
-+ }
-+
-+ errval = 0;
-+ fail:
-+ return errval;
-+}
-+
-+static int pram_read_inode(struct inode *inode,struct pram_inode *pi)
-+{
-+ int ret = -EIO;
-+
-+ mutex_lock(&PRAM_I(inode)->i_meta_mutex);
-+
-+ if (pram_calc_checksum((u8 *)pi, PRAM_INODE_SIZE)) {
-+ pram_err(inode->i_sb,"checksum error in inode %08x\n",
-+ (u32)inode->i_ino);
-+ goto bad_inode;
-+ }
-+
-+ inode->i_mode = be16_to_cpu(pi->i_mode);
-+ inode->i_uid = be32_to_cpu(pi->i_uid);
-+ inode->i_gid = be32_to_cpu(pi->i_gid);
-+ inode->i_nlink = be16_to_cpu(pi->i_links_count);
-+ inode->i_size = be32_to_cpu(pi->i_size);
-+ inode->i_atime.tv_sec = be32_to_cpu(pi->i_atime);
-+ inode->i_ctime.tv_sec = be32_to_cpu(pi->i_ctime);
-+ inode->i_mtime.tv_sec = be32_to_cpu(pi->i_mtime);
-+ inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec =
-+ inode->i_ctime.tv_nsec = 0;
-+ inode->i_generation = be32_to_cpu(pi->i_generation);
-+ pram_set_inode_flags(inode, pi);
-+
-+ /* checkif the inode is active. */
-+ if (inode->i_nlink == 0 && (inode->i_mode == 0 ||
-+ be32_to_cpu(pi->i_dtime))) {
-+ /*this inode is deleted */
-+ pram_dbg("read inode: inode %lu not active", inode->i_ino);
-+ ret = -ESTALE;
-+ goto bad_inode;
-+ }
-+
-+ inode->i_blocks = be32_to_cpu(pi->i_blocks);
-+ inode->i_ino = pram_get_inodenr(inode->i_sb, pi);
-+ inode->i_mapping->a_ops = &pram_aops;
-+ inode->i_mapping->backing_dev_info = &pram_backing_dev_info;
-+
-+ switch (inode->i_mode & S_IFMT) {
-+ case S_IFREG:
-+ if (pram_use_xip(inode->i_sb)) {
-+ inode->i_mapping->a_ops = &pram_aops_xip;
-+ inode->i_fop = &pram_xip_file_operations;
-+ }else {
-+ inode->i_op = &pram_file_inode_operations;
-+ inode->i_fop = &pram_file_operations;
-+ }
-+ break;
-+ case S_IFDIR:
-+ inode->i_op = &pram_dir_inode_operations;
-+ inode->i_fop = &pram_dir_operations;
-+ break;
-+ case S_IFLNK:
-+ inode->i_op = &pram_symlink_inode_operations;
-+ break;
-+ default:
-+ inode->i_size = 0;
-+ inode->i_op = &pram_special_inode_operations;
-+ init_special_inode(inode, inode->i_mode,
-+ be32_to_cpu(pi->i_type.dev.rdev));
-+ break;
-+ }
-+
-+ mutex_unlock(&PRAM_I(inode)->i_meta_mutex);
-+ return 0;
-+
-+ bad_inode:
-+ make_bad_inode(inode);
-+ mutex_unlock(&PRAM_I(inode)->i_meta_mutex);
-+ return ret;
-+}
-+
-+int pram_update_inode(struct inode *inode)
-+{
-+ struct pram_inode *pi;
-+ int retval = 0;
-+
-+ pi = pram_get_inode(inode->i_sb, inode->i_ino);
-+ if (!pi)
-+ return -EACCES;
-+
-+ mutex_lock(&PRAM_I(inode)->i_meta_mutex);
-+
-+ pram_memunlock_inode(inode->i_sb, pi);
-+ pi->i_mode = cpu_to_be16(inode->i_mode);
-+ pi->i_uid = cpu_to_be32(inode->i_uid);
-+ pi->i_gid = cpu_to_be32(inode->i_gid);
-+ pi->i_links_count = cpu_to_be16(inode->i_nlink);
-+ pi->i_size = cpu_to_be32(inode->i_size);
-+ pi->i_blocks = cpu_to_be32(inode->i_blocks);
-+ pi->i_atime = cpu_to_be32(inode->i_atime.tv_sec);
-+ pi->i_ctime = cpu_to_be32(inode->i_ctime.tv_sec);
-+ pi->i_mtime = cpu_to_be32(inode->i_mtime.tv_sec);
-+ pi->i_generation = cpu_to_be32(inode->i_generation);
-+ pram_get_inode_flags(inode, pi);
-+
-+ if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-+ pi->i_type.dev.rdev = cpu_to_be32(inode->i_rdev);
-+
-+ pram_memlock_inode(inode->i_sb, pi);
-+
-+ mutex_unlock(&PRAM_I(inode)->i_meta_mutex);
-+ return retval;
-+}
-+
-+/*
-+ * NOTE! When we get the inode, we're the only people
-+ * that have access to it, and as such there are no
-+ * race conditions we have to worry about. The inode
-+ * is not on the hash-lists, and it cannot be reached
-+ * through the filesystem because the directory entry
-+ * has been deleted earlier.
-+ */
-+static void pram_free_inode(struct inode *inode)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_super_block *ps;
-+ struct pram_inode *pi;
-+ unsigned long inode_nr;
-+
-+ pram_xattr_delete_inode(inode);
-+
-+ lock_super(sb);
-+
-+ inode_nr = (inode->i_ino - PRAM_ROOT_INO) >> PRAM_INODE_BITS;
-+
-+ pi = pram_get_inode(sb, inode->i_ino);
-+ pram_memunlock_inode(sb, pi);
-+ pi->i_dtime = cpu_to_be32(get_seconds());
-+ pi->i_type.reg.row_block = 0;
-+ pi->i_xattr = 0;
-+ pram_memlock_inode(sb, pi);
-+
-+ /* increment s_free_inodes_count */
-+ ps = pram_get_super(sb);
-+ pram_memunlock_super(sb, ps);
-+ if (inode_nr < be32_to_cpu(ps->s_free_inode_hint))
-+ ps->s_free_inode_hint = cpu_to_be32(inode_nr);
-+ be32_add_cpu(&ps->s_free_inodes_count, 1);
-+ if (be32_to_cpu(ps->s_free_inodes_count) ==
-+ be32_to_cpu(ps->s_inodes_count) - 1) {
-+ /* filesystem is empty */
-+ pram_dbg("fs is empty!\n");
-+ ps->s_free_inode_hint = cpu_to_be32(1);
-+ }
-+ pram_memlock_super(sb, ps);
-+
-+ unlock_super(sb);
-+}
-+
-+struct inode *pram_iget(struct super_block *sb,unsigned long ino)
-+{
-+ struct inode *inode;
-+ struct pram_inode *pi;
-+ int err;
-+
-+ inode = iget_locked(sb, ino);
-+ if (unlikely(!inode))
-+ return ERR_PTR(-ENOMEM);
-+ if (!(inode->i_state & I_NEW))
-+ return inode;
-+
-+ pi = pram_get_inode(sb, ino);
-+ if (!pi) {
-+ err = -EACCES;
-+ goto fail;
-+ }
-+ err = pram_read_inode(inode, pi);
-+ if (unlikely(err))
-+ goto fail;
-+
-+ unlock_new_inode(inode);
-+ return inode;
-+fail:
-+ iget_failed(inode);
-+ return ERR_PTR(err);
-+}
-+
-+void pram_evict_inode(struct inode *inode)
-+{
-+ int want_delete = 0;
-+
-+ if (!inode->i_nlink && !is_bad_inode(inode))
-+ want_delete = 1;
-+
-+ truncate_inode_pages(&inode->i_data, 0);
-+
-+ if (want_delete) {
-+ /* unlink from chain in the inode's directory */
-+ pram_remove_link(inode);
-+ pram_truncate_blocks(inode, 0, inode->i_size);
-+ inode->i_size = 0;
-+ }
-+
-+ end_writeback(inode);
-+
-+ if (want_delete)
-+ pram_free_inode(inode);
-+}
-+
-+
-+
-+struct inode *pram_new_inode(struct inode *dir,int mode,
-+ const struct qstr *qstr)
-+{
-+ struct super_block *sb;
-+ struct pram_sb_info *sbi;
-+ struct pram_super_block *ps;
-+ struct inode *inode;
-+ struct pram_inode *pi =NULL;
-+ struct pram_inode *diri =NULL;
-+ int i, errval;
-+ ino_t ino = 0;
-+
-+ sb = dir->i_sb;
-+ sbi = (struct pram_sb_info *)sb->s_fs_info;
-+ inode = new_inode(sb);
-+ if (!inode)
-+ return ERR_PTR(-ENOMEM);
-+
-+ lock_super(sb);
-+ ps = pram_get_super(sb);
-+
-+ if (ps->s_free_inodes_count) {
-+ /* find the oldest unused pram inode */
-+ for (i = be32_to_cpu(ps->s_free_inode_hint);
-+ i < be32_to_cpu(ps->s_inodes_count); i++) {
-+ ino = PRAM_ROOT_INO + (i << PRAM_INODE_BITS);
-+ pi = pram_get_inode(sb, ino);
-+ /* checkif the inode is active. */
-+ if (be16_to_cpu(pi->i_links_count) == 0 &&
-+ (be16_to_cpu(pi->i_mode) == 0 ||
-+ be32_to_cpu(pi->i_dtime))) {
-+ /*this inode is deleted */
-+ break;
-+ }
-+ }
-+
-+ if (unlikely(i >= be32_to_cpu(ps->s_inodes_count))) {
-+ pram_err(sb,"free inodes count!=0 but none free!?\n");
-+ errval = -ENOSPC;
-+ goto fail1;
-+ }
-+
-+ pram_dbg("allocating inode %lu\n", ino);
-+ }else {
-+ pram_dbg("no space left to createnew inode!\n");
-+ errval = -ENOSPC;
-+ goto fail1;
-+ }
-+
-+ diri = pram_get_inode(sb, dir->i_ino);
-+ if (!diri) {
-+ errval = -EACCES;
-+ goto fail1;
-+ }
-+
-+ /* chosen inode is in ino */
-+ inode->i_ino = ino;
-+ inode_init_owner(inode, dir, mode);
-+ inode->i_blocks = inode->i_size = 0;
-+ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-+
-+ inode->i_generation = atomic_add_return(1, &sbi->next_generation);
-+
-+ pram_memunlock_inode(sb, pi);
-+ pi->i_d.d_next = 0;
-+ pi->i_d.d_prev = 0;
-+ pi->i_dtime = 0;
-+ pi->i_flags = pram_mask_flags(mode, diri->i_flags);
-+ pram_memlock_inode(sb, pi);
-+
-+ pram_set_inode_flags(inode, pi);
-+
-+ if (insert_inode_locked(inode) < 0) {
-+ errval = -EINVAL;
-+ goto fail2;
-+ }
-+ errval = pram_write_inode(inode,NULL);
-+ if (errval)
-+ goto fail2;
-+
-+ errval = pram_init_acl(inode, dir);
-+ if (errval)
-+ goto fail2;
-+
-+ errval = pram_init_security(inode, dir, qstr);
-+ if (errval)
-+ goto fail2;
-+
-+ pram_memunlock_super(sb, ps);
-+ be32_add_cpu(&ps->s_free_inodes_count, -1);
-+ if (i < be32_to_cpu(ps->s_inodes_count)-1)
-+ ps->s_free_inode_hint = cpu_to_be32(i+1);
-+ else
-+ ps->s_free_inode_hint = 0;
-+ pram_memlock_super(sb, ps);
-+
-+ unlock_super(sb);
-+
-+ return inode;
-+fail2:
-+ unlock_super(sb);
-+ inode->i_nlink = 0;
-+ unlock_new_inode(inode);
-+ iput(inode);
-+ return ERR_PTR(errval);
-+fail1:
-+ unlock_super(sb);
-+ make_bad_inode(inode);
-+ iput(inode);
-+ return ERR_PTR(errval);
-+}
-+
-+int pram_write_inode(struct inode *inode,struct writeback_control *wbc)
-+{
-+ return pram_update_inode(inode);
-+}
-+
-+/*
-+ * dirty_inode() is called from __mark_inode_dirty()
-+ */
-+void pram_dirty_inode(struct inode *inode,int flags)
-+{
-+ pram_update_inode(inode);
-+}
-+
-+static int pram_readpage(struct file *file,struct page *page)
-+{
-+ struct inode *inode = page->mapping->host;
-+ struct super_block *sb = inode->i_sb;
-+ loff_t offset, size;
-+ unsigned long fillsize, blocknr, bytes_filled;
-+ u64 block;
-+ void *buf, *bp;
-+ int ret;
-+
-+ buf = kmap(page);
-+ if (!buf)
-+ return -ENOMEM;
-+
-+ offset = page_offset(page);
-+ size = i_size_read(inode);
-+ blocknr = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
-+ fillsize = 0;
-+ bytes_filled = 0;
-+ ret = 0;
-+ if (offset < size) {
-+ size -= offset;
-+ fillsize = size > PAGE_SIZE ? PAGE_SIZE : size;
-+ while (fillsize) {
-+ int count = fillsize > sb->s_blocksize ?
-+ sb->s_blocksize : fillsize;
-+ block = pram_find_data_block(inode, blocknr);
-+ if (likely(block)) {
-+ bp = pram_get_block(sb, block);
-+ if (!bp) {
-+ SetPageError(page);
-+ bytes_filled = 0;
-+ ret = -EIO;
-+ goto out;
-+ }
-+ memcpy(buf + bytes_filled, bp, count);
-+ }else {
-+ memset(buf + bytes_filled, 0, count);
-+ }
-+ bytes_filled += count;
-+ fillsize -= count;
-+ blocknr++;
-+ }
-+ }
-+ out:
-+ if (bytes_filled < PAGE_SIZE)
-+ memset(buf + bytes_filled, 0, PAGE_SIZE - bytes_filled);
-+ if (ret == 0)
-+ SetPageUptodate(page);
-+
-+ flush_dcache_page(page);
-+ kunmap(page);
-+ unlock_page(page);
-+ return ret;
-+}
-+
-+/*
-+ * Called to zeros out a single block. It's used in the"resize"
-+ * to avoid to keep data incase the file grow up again.
-+ */
-+static int pram_block_truncate_page(struct inode *inode, loff_t newsize)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ unsigned long offset = newsize & (sb->s_blocksize - 1);
-+ unsigned long blocknr, length;
-+ u64 blockoff;
-+ char *bp;
-+ int ret = 0;
-+
-+ /* Block boundary or extending ? */
-+ if (!offset || newsize > inode->i_size)
-+ goto out;
-+
-+ length = sb->s_blocksize - offset;
-+ blocknr = newsize >> sb->s_blocksize_bits;
-+
-+ blockoff = pram_find_data_block(inode, blocknr);
-+
-+ /* Hole ? */
-+ if (!blockoff)
-+ goto out;
-+
-+ bp = pram_get_block(inode->i_sb, blockoff);
-+ if (!bp) {
-+ ret = -EACCES;
-+ goto out;
-+ }
-+ pram_memunlock_block(sb, bp);
-+ memset(bp + offset, 0, length);
-+ pram_memlock_block(sb, bp);
-+out:
-+ return ret;
-+}
-+
-+static int pram_setsize(struct inode *inode, loff_t newsize)
-+{
-+ int ret = 0;
-+ loff_t oldsize = inode->i_size;
-+
-+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-+ S_ISLNK(inode->i_mode)))
-+ return -EINVAL;
-+ if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-+ return -EPERM;
-+
-+ if (newsize != oldsize) {
-+ if (mapping_is_xip(inode->i_mapping))
-+ ret = xip_truncate_page(inode->i_mapping, newsize);
-+ else
-+ ret = pram_block_truncate_page(inode, newsize);
-+
-+ if (ret)
-+ return ret;
-+ i_size_write(inode, newsize);
-+ }
-+ /*
-+ * Waitfor any concurrent readers to finish before to truncate the
-+ * blocks. Anynew reader will see thenew i_size so no problem.
-+ * In addition we have to wait, in xipcase, the call of xip_file_fault.
-+ */
-+ synchronize_rcu();
-+ truncate_pagecache(inode, oldsize, newsize);
-+ __pram_truncate_blocks(inode, newsize, oldsize);
-+ /* Checkfor the flag EOFBLOCKS is still valid after the set size */
-+ check_eof_blocks(inode, newsize);
-+ inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
-+ pram_update_inode(inode);
-+
-+ return ret;
-+}
-+
-+int pram_notify_change(struct dentry *dentry,struct iattr *attr)
-+{
-+ struct inode *inode = dentry->d_inode;
-+ struct pram_inode *pi = pram_get_inode(inode->i_sb, inode->i_ino);
-+ int error;
-+
-+ if (!pi)
-+ return -EACCES;
-+
-+ error = inode_change_ok(inode, attr);
-+ if (error)
-+ return error;
-+
-+ if (attr->ia_valid & ATTR_SIZE &&
-+ (attr->ia_size != inode->i_size ||
-+ pi->i_flags & cpu_to_be32(PRAM_EOFBLOCKS_FL))) {
-+ error = pram_setsize(inode, attr->ia_size);
-+ if (error)
-+ return error;
-+ }
-+ setattr_copy(inode, attr);
-+ if (attr->ia_valid & ATTR_MODE)
-+ error = pram_acl_chmod(inode);
-+ error = pram_update_inode(inode);
-+
-+ return error;
-+}
-+
-+void pram_set_inode_flags(struct inode *inode,struct pram_inode *pi)
-+{
-+ unsigned int flags = be32_to_cpu(pi->i_flags);
-+
-+ inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
-+ if (flags & FS_SYNC_FL)
-+ inode->i_flags |= S_SYNC;
-+ if (flags & FS_APPEND_FL)
-+ inode->i_flags |= S_APPEND;
-+ if (flags & FS_IMMUTABLE_FL)
-+ inode->i_flags |= S_IMMUTABLE;
-+ if (flags & FS_NOATIME_FL)
-+ inode->i_flags |= S_NOATIME;
-+ if (flags & FS_DIRSYNC_FL)
-+ inode->i_flags |= S_DIRSYNC;
-+ if (!pi->i_xattr)
-+ inode_has_no_xattr(inode);
-+}
-+
-+void pram_get_inode_flags(struct inode *inode,struct pram_inode *pi)
-+{
-+ unsigned int flags = inode->i_flags;
-+ unsigned int pram_flags = be32_to_cpu(pi->i_flags);
-+
-+ pram_flags &= ~(FS_SYNC_FL|FS_APPEND_FL|FS_IMMUTABLE_FL|
-+ FS_NOATIME_FL|FS_DIRSYNC_FL);
-+ if (flags & S_SYNC)
-+ pram_flags |= FS_SYNC_FL;
-+ if (flags & S_APPEND)
-+ pram_flags |= FS_APPEND_FL;
-+ if (flags & S_IMMUTABLE)
-+ pram_flags |= FS_IMMUTABLE_FL;
-+ if (flags & S_NOATIME)
-+ pram_flags |= FS_NOATIME_FL;
-+ if (flags & S_DIRSYNC)
-+ pram_flags |= FS_DIRSYNC_FL;
-+
-+ pi->i_flags = cpu_to_be32(pram_flags);
-+}
-+
-+const struct address_space_operations pram_aops = {
-+ .readpage = pram_readpage,
-+ .direct_IO = pram_direct_IO,
-+};
-+
-+const struct address_space_operations pram_aops_xip = {
-+ .get_xip_mem = pram_get_xip_mem,
-+};
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:16:34 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:09:59 +0200
-Subject: pramfs: file operations
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FAE9967.40809@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-File operations.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
----
- fs/pramfs/file.c | 398 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 398 insertions(+)
-
---- /dev/null
-+++ b/fs/pramfs/file.c
-@@ -0,0 +1,398 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * File operations for files.
-+ *
-+ * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ * Copyright 2003 Sony Corporation
-+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
-+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
-+ * 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 <linux/fs.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/uio.h>
-+#include <linux/mm.h>
-+#include <linux/uaccess.h>
-+#include <linux/falloc.h>
-+#include "pram.h"
-+#include "acl.h"
-+#include "xip.h"
-+#include "xattr.h"
-+
-+/*
-+ * The following functions are helper routines to copy to/from
-+ * user space and iter over io vectors (mainly for readv/writev).
-+ * They are used in the direct IO path.
-+ */
-+static size_t __pram_iov_copy_from(char *vaddr,
-+ const struct iovec *iov, size_t base, size_t bytes)
-+{
-+ size_t copied = 0, left = 0;
-+
-+ while (bytes) {
-+ char __user *buf = iov->iov_base + base;
-+ int copy = min(bytes, iov->iov_len - base);
-+
-+ base = 0;
-+ left = __copy_from_user(vaddr, buf, copy);
-+ copied += copy;
-+ bytes -= copy;
-+ vaddr += copy;
-+ iov++;
-+
-+ if (unlikely(left))
-+ break;
-+ }
-+ return copied - left;
-+}
-+
-+static size_t __pram_iov_copy_to(char *vaddr,
-+ const struct iovec *iov, size_t base, size_t bytes)
-+{
-+ size_t copied = 0, left = 0;
-+
-+ while (bytes) {
-+ char __user *buf = iov->iov_base + base;
-+ int copy = min(bytes, iov->iov_len - base);
-+
-+ base = 0;
-+ left = __copy_to_user(buf, vaddr, copy);
-+ copied += copy;
-+ bytes -= copy;
-+ vaddr += copy;
-+ iov++;
-+
-+ if (unlikely(left))
-+ break;
-+ }
-+ return copied - left;
-+}
-+
-+static size_t pram_iov_copy_from(void *to, struct iov_iter *i, size_t bytes)
-+{
-+ size_t copied;
-+
-+ if (likely(i->nr_segs == 1)) {
-+ int left;
-+ char __user *buf = i->iov->iov_base + i->iov_offset;
-+ left = __copy_from_user(to, buf, bytes);
-+ copied = bytes - left;
-+ } else {
-+ copied = __pram_iov_copy_from(to, i->iov, i->iov_offset, bytes);
-+ }
-+
-+ return copied;
-+}
-+
-+static size_t pram_iov_copy_to(void *from, struct iov_iter *i, size_t bytes)
-+{
-+ size_t copied;
-+
-+ if (likely(i->nr_segs == 1)) {
-+ int left;
-+ char __user *buf = i->iov->iov_base + i->iov_offset;
-+ left = __copy_to_user(buf, from, bytes);
-+ copied = bytes - left;
-+ } else {
-+ copied = __pram_iov_copy_to(from, i->iov, i->iov_offset, bytes);
-+ }
-+
-+ return copied;
-+}
-+
-+static size_t __pram_clear_user(const struct iovec *iov, size_t base,
-+ size_t bytes)
-+{
-+ size_t claened = 0, left = 0;
-+
-+ while (bytes) {
-+ char __user *buf = iov->iov_base + base;
-+ int clear = min(bytes, iov->iov_len - base);
-+
-+ base = 0;
-+ left = __clear_user(buf, clear);
-+ claened += clear;
-+ bytes -= clear;
-+ iov++;
-+
-+ if (unlikely(left))
-+ break;
-+ }
-+ return claened - left;
-+}
-+
-+static size_t pram_clear_user(struct iov_iter *i, size_t bytes)
-+{
-+ size_t clear;
-+
-+ if (likely(i->nr_segs == 1)) {
-+ int left;
-+ char __user *buf = i->iov->iov_base + i->iov_offset;
-+ left = __clear_user(buf, bytes);
-+ clear = bytes - left;
-+ } else {
-+ clear = __pram_clear_user(i->iov, i->iov_offset, bytes);
-+ }
-+
-+ return clear;
-+}
-+
-+static int pram_open_file(struct inode *inode, struct file *filp)
-+{
-+ filp->f_flags |= O_DIRECT;
-+ return generic_file_open(inode, filp);
-+}
-+
-+ssize_t pram_direct_IO(int rw, struct kiocb *iocb,
-+ const struct iovec *iov,
-+ loff_t offset, unsigned long nr_segs)
-+{
-+ struct file *file = iocb->ki_filp;
-+ struct inode *inode = file->f_mapping->host;
-+ struct super_block *sb = inode->i_sb;
-+ int progress = 0, hole = 0, alloc_once = 1;
-+ ssize_t retval = 0;
-+ void *tmp = NULL;
-+ unsigned long blocknr, blockoff, blocknr_start;
-+ struct iov_iter iter;
-+ unsigned int num_blocks;
-+ size_t length = iov_length(iov, nr_segs);
-+ loff_t size;
-+
-+ /*
-+ * If we are in the write path we are under i_mutex but no lock held
-+ * in the read, so we need to be sync with truncate to avoid race
-+ * conditions.
-+ */
-+ if (rw == READ)
-+ rcu_read_lock();
-+
-+ size = i_size_read(inode);
-+
-+ if (length < 0) {
-+ retval = -EINVAL;
-+ goto out;
-+ }
-+ if ((rw == READ) && (offset + length > size))
-+ length = size - offset;
-+ if (!length)
-+ goto out;
-+
-+ /* find starting block number to access */
-+ blocknr = offset >> sb->s_blocksize_bits;
-+ /* find starting offset within starting block */
-+ blockoff = offset & (sb->s_blocksize - 1);
-+ /* find number of blocks to access */
-+ num_blocks = (blockoff + length + sb->s_blocksize - 1) >>
-+ sb->s_blocksize_bits;
-+ blocknr_start = blocknr;
-+
-+ if (rw == WRITE) {
-+ /* prepare a temporary buffer to hold a user data block
-+ for writing. */
-+ tmp = kmalloc(sb->s_blocksize, GFP_KERNEL);
-+ if (!tmp) {
-+ retval = -ENOMEM;
-+ goto out;
-+ }
-+ }
-+
-+ iov_iter_init(&iter, iov, nr_segs, length, 0);
-+
-+ while (length) {
-+ int count;
-+ u8 *bp = NULL;
-+ u64 block = pram_find_data_block(inode, blocknr);
-+ if (!block) {
-+ if (alloc_once && rw == WRITE) {
-+ /*
-+ * Allocate the data blocks starting from
-+ * blocknr to the end.
-+ */
-+ retval = pram_alloc_blocks(inode, blocknr,
-+ num_blocks - (blocknr -
-+ blocknr_start));
-+ if (retval)
-+ goto fail;
-+ /* retry....*/
-+ block = pram_find_data_block(inode, blocknr);
-+ BUG_ON(!block);
-+ alloc_once = 0;
-+ } else if (unlikely(rw == READ)) {
-+ /* We are falling in a hole */
-+ hole = 1;
-+ goto hole;
-+ }
-+ }
-+ bp = (u8 *)pram_get_block(sb, block);
-+ if (!bp) {
-+ retval = -EACCES;
-+ goto fail;
-+ }
-+ hole:
-+ ++blocknr;
-+
-+ count = blockoff + length > sb->s_blocksize ?
-+ sb->s_blocksize - blockoff : length;
-+
-+ if (rw == READ) {
-+ if (unlikely(hole)) {
-+ retval = pram_clear_user(&iter, count);
-+ if (retval != count) {
-+ retval = -EFAULT;
-+ goto fail;
-+ }
-+ } else {
-+ retval = pram_iov_copy_to(&bp[blockoff], &iter,
-+ count);
-+ if (retval != count) {
-+ retval = -EFAULT;
-+ goto fail;
-+ }
-+ }
-+ } else {
-+ retval = pram_iov_copy_from(tmp, &iter, count);
-+ if (retval != count) {
-+ retval = -EFAULT;
-+ goto fail;
-+ }
-+
-+ pram_memunlock_block(inode->i_sb, bp);
-+ memcpy(&bp[blockoff], tmp, count);
-+ pram_memlock_block(inode->i_sb, bp);
-+ }
-+
-+ progress += count;
-+ iov_iter_advance(&iter, count);
-+ length -= count;
-+ blockoff = 0;
-+ hole = 0;
-+ }
-+
-+ retval = progress;
-+ /*
-+ * Check for the flag EOFBLOCKS is still valid after the extending
-+ * write.
-+ */
-+ if (rw == WRITE && (offset + length >= size))
-+ check_eof_blocks(inode, size + retval);
-+ fail:
-+ kfree(tmp);
-+ out:
-+ if (rw == READ)
-+ rcu_read_unlock();
-+ return retval;
-+}
-+
-+static int pram_check_flags(int flags)
-+{
-+ if (!(flags & O_DIRECT))
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+static long pram_fallocate(struct file *file, int mode, loff_t offset,
-+ loff_t len)
-+{
-+ struct inode *inode = file->f_path.dentry->d_inode;
-+ long ret = 0;
-+ unsigned long blocknr, blockoff;
-+ int num_blocks, blocksize_mask;
-+ struct pram_inode *pi;
-+ loff_t new_size;
-+
-+ /* We only support the FALLOC_FL_KEEP_SIZE mode */
-+ if (mode & ~FALLOC_FL_KEEP_SIZE)
-+ return -EOPNOTSUPP;
-+
-+ if (S_ISDIR(inode->i_mode))
-+ return -ENODEV;
-+
-+ mutex_lock(&inode->i_mutex);
-+
-+ new_size = len + offset;
-+ if (!(mode & FALLOC_FL_KEEP_SIZE) && new_size > inode->i_size) {
-+ ret = inode_newsize_ok(inode, new_size);
-+ if (ret)
-+ goto out;
-+ }
-+
-+ blocksize_mask = (1 << inode->i_sb->s_blocksize_bits) - 1;
-+ blocknr = offset >> inode->i_sb->s_blocksize_bits;
-+ blockoff = offset & blocksize_mask;
-+ num_blocks = (blockoff + len + blocksize_mask) >>
-+ inode->i_sb->s_blocksize_bits;
-+ ret = pram_alloc_blocks(inode, blocknr, num_blocks);
-+ if (ret)
-+ goto out;
-+
-+ if (mode & FALLOC_FL_KEEP_SIZE) {
-+ pi = pram_get_inode(inode->i_sb, inode->i_ino);
-+ if (!pi) {
-+ ret = -EACCES;
-+ goto out;
-+ }
-+ pram_memunlock_inode(inode->i_sb, pi);
-+ pi->i_flags |= cpu_to_be32(PRAM_EOFBLOCKS_FL);
-+ pram_memlock_inode(inode->i_sb, pi);
-+ }
-+
-+ inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
-+ if (!(mode & FALLOC_FL_KEEP_SIZE) && new_size > inode->i_size)
-+ inode->i_size = new_size;
-+ ret = pram_update_inode(inode);
-+ out:
-+ mutex_unlock(&inode->i_mutex);
-+ return ret;
-+}
-+
-+const struct file_operations pram_file_operations = {
-+ .llseek = generic_file_llseek,
-+ .read = do_sync_read,
-+ .write = do_sync_write,
-+ .aio_read = generic_file_aio_read,
-+ .aio_write = generic_file_aio_write,
-+ .mmap = generic_file_readonly_mmap,
-+ .open = pram_open_file,
-+ .fsync = noop_fsync,
-+ .check_flags = pram_check_flags,
-+ .unlocked_ioctl = pram_ioctl,
-+ .splice_read = generic_file_splice_read,
-+ .fallocate = pram_fallocate,
-+#ifdef CONFIG_COMPAT
-+ .compat_ioctl = pram_compat_ioctl,
-+#endif
-+};
-+
-+#ifdef CONFIG_PRAMFS_XIP
-+const struct file_operations pram_xip_file_operations = {
-+ .llseek = generic_file_llseek,
-+ .read = pram_xip_file_read,
-+ .write = xip_file_write,
-+ .mmap = pram_xip_file_mmap,
-+ .open = generic_file_open,
-+ .fsync = noop_fsync,
-+ .unlocked_ioctl = pram_ioctl,
-+ .fallocate = pram_fallocate,
-+#ifdef CONFIG_COMPAT
-+ .compat_ioctl = pram_compat_ioctl,
-+#endif
-+};
-+#endif
-+
-+const struct inode_operations pram_file_inode_operations = {
-+#ifdef CONFIG_PRAMFS_XATTR
-+ .setxattr = generic_setxattr,
-+ .getxattr = generic_getxattr,
-+ .listxattr = pram_listxattr,
-+ .removexattr = generic_removexattr,
-+#endif
-+ .setattr = pram_notify_change,
-+ .check_acl = pram_check_acl,
-+};
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:16:46 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:10:11 +0200
-Subject: pramfs: block allocation
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FAE9973.3020402@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-Block allocation operations.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
----
- fs/pramfs/balloc.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 160 insertions(+)
-
---- /dev/null
-+++ b/fs/pramfs/balloc.c
-@@ -0,0 +1,160 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * The blocks allocation and deallocation routines.
-+ *
-+ * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ * Copyright 2003 Sony Corporation
-+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
-+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
-+ * 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 <linux/fs.h>
-+#include <linux/bitops.h>
-+#include "pram.h"
-+
-+void pram_bitmap_fill(unsigned long *dst, int nbits)
-+{
-+ size_t nlongs = BITS_TO_LONGS(nbits);
-+ if (!small_const_nbits(nbits)) {
-+ int len = (nlongs - 1) * sizeof(unsigned long);
-+ memset(dst, 0xff, len);
-+ }
-+ if (BITS_PER_LONG == 64)
-+ dst[nlongs - 1] = cpu_to_le64(BITMAP_LAST_WORD_MASK(nbits));
-+ else
-+ dst[nlongs - 1] = cpu_to_le32(BITMAP_LAST_WORD_MASK(nbits));
-+}
-+
-+/*
-+ * This just marks in-use the blocks that make up the bitmap.
-+ * The bitmap must be writeable before calling.
-+ */
-+void pram_init_bitmap(struct super_block *sb)
-+{
-+ struct pram_super_block *ps = pram_get_super(sb);
-+ unsigned long *bitmap = pram_get_bitmap(sb);
-+ int blocks = be32_to_cpu(ps->s_bitmap_blocks);
-+
-+ memset(bitmap, 0, blocks << sb->s_blocksize_bits);
-+
-+ pram_bitmap_fill(bitmap, blocks);
-+}
-+
-+
-+/* Free absolute blocknr */
-+void pram_free_block(struct super_block *sb, unsigned long blocknr)
-+{
-+ struct pram_super_block *ps;
-+ u64 bitmap_block;
-+ unsigned long bitmap_bnr;
-+ void *bitmap;
-+ void *bp;
-+
-+ lock_super(sb);
-+
-+ bitmap = pram_get_bitmap(sb);
-+ /*
-+ * find the block within the bitmap that contains the inuse bit
-+ * for the block we need to free. We need to unlock this bitmap
-+ * block to clear the inuse bit.
-+ */
-+ bitmap_bnr = blocknr >> (3 + sb->s_blocksize_bits);
-+ bitmap_block = pram_get_block_off(sb, bitmap_bnr);
-+ bp = pram_get_block(sb, bitmap_block);
-+
-+ pram_memunlock_block(sb, bp);
-+ pram_clear_bit(blocknr, bitmap); /* mark the block free */
-+ pram_memlock_block(sb, bp);
-+
-+ ps = pram_get_super(sb);
-+ pram_memunlock_super(sb, ps);
-+
-+ if (blocknr < be32_to_cpu(ps->s_free_blocknr_hint))
-+ ps->s_free_blocknr_hint = cpu_to_be32(blocknr);
-+ be32_add_cpu(&ps->s_free_blocks_count, 1);
-+ pram_memlock_super(sb, ps);
-+
-+ unlock_super(sb);
-+}
-+
-+
-+/*
-+ * allocate a block and return it's absolute blocknr. Zeroes out the
-+ * block if zero set.
-+ */
-+int pram_new_block(struct super_block *sb, unsigned long *blocknr, int zero)
-+{
-+ struct pram_super_block *ps;
-+ u64 bitmap_block;
-+ unsigned long bnr, bitmap_bnr;
-+ int errval;
-+ void *bitmap;
-+ void *bp;
-+
-+ lock_super(sb);
-+ ps = pram_get_super(sb);
-+ bitmap = pram_get_bitmap(sb);
-+
-+ if (ps->s_free_blocks_count) {
-+ /* find the oldest unused block */
-+ bnr = pram_find_next_zero_bit(bitmap,
-+ be32_to_cpu(ps->s_blocks_count),
-+ be32_to_cpu(ps->s_free_blocknr_hint));
-+
-+ if (bnr < be32_to_cpu(ps->s_bitmap_blocks) ||
-+ bnr >= be32_to_cpu(ps->s_blocks_count)) {
-+ pram_dbg("no free blocks found!\n");
-+ errval = -ENOSPC;
-+ goto fail;
-+ }
-+
-+ pram_memunlock_super(sb, ps);
-+ be32_add_cpu(&ps->s_free_blocks_count, -1);
-+ if (bnr < (be32_to_cpu(ps->s_blocks_count)-1))
-+ ps->s_free_blocknr_hint = cpu_to_be32(bnr+1);
-+ else
-+ ps->s_free_blocknr_hint = 0;
-+ pram_memlock_super(sb, ps);
-+ } else {
-+ pram_dbg("all blocks allocated\n");
-+ errval = -ENOSPC;
-+ goto fail;
-+ }
-+
-+ /*
-+ * find the block within the bitmap that contains the inuse bit
-+ * for the unused block we just found. We need to unlock it to
-+ * set the inuse bit.
-+ */
-+ bitmap_bnr = bnr >> (3 + sb->s_blocksize_bits);
-+ bitmap_block = pram_get_block_off(sb, bitmap_bnr);
-+ bp = pram_get_block(sb, bitmap_block);
-+
-+ pram_memunlock_block(sb, bp);
-+ pram_set_bit(bnr, bitmap); /* mark the new block in use */
-+ pram_memlock_block(sb, bp);
-+
-+ if (zero) {
-+ bp = pram_get_block(sb, pram_get_block_off(sb, bnr));
-+ pram_memunlock_block(sb, bp);
-+ memset(bp, 0, sb->s_blocksize);
-+ pram_memlock_block(sb, bp);
-+ }
-+
-+ *blocknr = bnr;
-+ pram_dbg("allocated blocknr %lu", bnr);
-+ errval = 0;
-+ fail:
-+ unlock_super(sb);
-+ return errval;
-+}
-+
-+unsigned long pram_count_free_blocks(struct super_block *sb)
-+{
-+ struct pram_super_block *ps = pram_get_super(sb);
-+ return be32_to_cpu(ps->s_free_blocks_count);
-+}
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:16:57 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:10:23 +0200
-Subject: pramfs: inode operations for dirs
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FAE997F.6020507@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-Inode operations for directories.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
----
- fs/pramfs/namei.c | 376 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 376 insertions(+)
-
---- /dev/null
-+++ b/fs/pramfs/namei.c
-@@ -0,0 +1,376 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Inode operations for directories.
-+ *
-+ * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ * Copyright 2003 Sony Corporation
-+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
-+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
-+ * 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 <linux/fs.h>
-+#include <linux/pagemap.h>
-+#include "pram.h"
-+#include "acl.h"
-+#include "xattr.h"
-+#include "xip.h"
-+
-+/*
-+ * Couple of helper functions - make the code slightly cleaner.
-+ */
-+
-+static inline void pram_inc_count(struct inode *inode)
-+{
-+ inode->i_nlink++;
-+ pram_write_inode(inode, NULL);
-+}
-+
-+static inline void pram_dec_count(struct inode *inode)
-+{
-+ if (inode->i_nlink) {
-+ inode->i_nlink--;
-+ pram_write_inode(inode, NULL);
-+ }
-+}
-+
-+static inline int pram_add_nondir(struct inode *dir,
-+ struct dentry *dentry,
-+ struct inode *inode)
-+{
-+ int err = pram_add_link(dentry, inode);
-+ if (!err) {
-+ d_instantiate(dentry, inode);
-+ unlock_new_inode(inode);
-+ return 0;
-+ }
-+ pram_dec_count(inode);
-+ unlock_new_inode(inode);
-+ iput(inode);
-+ return err;
-+}
-+
-+/*
-+ * Methods themselves.
-+ */
-+
-+static ino_t pram_inode_by_name(struct inode *dir, struct dentry *dentry)
-+{
-+ struct pram_inode *pi;
-+ ino_t ino;
-+ int namelen;
-+
-+ pi = pram_get_inode(dir->i_sb, dir->i_ino);
-+ ino = be64_to_cpu(pi->i_type.dir.head);
-+
-+ while (ino) {
-+ pi = pram_get_inode(dir->i_sb, ino);
-+
-+ if (pi->i_links_count) {
-+ namelen = strlen(pi->i_d.d_name);
-+
-+ if (namelen == dentry->d_name.len &&
-+ !memcmp(dentry->d_name.name,
-+ pi->i_d.d_name, namelen))
-+ break;
-+ }
-+
-+ ino = be64_to_cpu(pi->i_d.d_next);
-+ }
-+
-+ return ino;
-+}
-+
-+static struct dentry *pram_lookup(struct inode *dir, struct dentry *dentry,
-+ struct nameidata *nd)
-+{
-+ struct inode *inode = NULL;
-+ ino_t ino;
-+
-+ if (dentry->d_name.len > PRAM_NAME_LEN)
-+ return ERR_PTR(-ENAMETOOLONG);
-+
-+ ino = pram_inode_by_name(dir, dentry);
-+ if (ino) {
-+ inode = pram_iget(dir->i_sb, ino);
-+ if (inode == ERR_PTR(-ESTALE)) {
-+ pram_err(dir->i_sb, __func__,
-+ "deleted inode referenced: %lu",
-+ (unsigned long) ino);
-+ return ERR_PTR(-EIO);
-+ }
-+ }
-+
-+ return d_splice_alias(inode, dentry);
-+}
-+
-+
-+/*
-+ * By the time this is called, we already have created
-+ * the directory cache entry for the new file, but it
-+ * is so far negative - it has no inode.
-+ *
-+ * If the create succeeds, we fill in the inode information
-+ * with d_instantiate().
-+ */
-+static int pram_create(struct inode *dir, struct dentry *dentry, int mode,
-+ struct nameidata *nd)
-+{
-+ struct inode *inode = pram_new_inode(dir, mode, &dentry->d_name);
-+ int err = PTR_ERR(inode);
-+ if (!IS_ERR(inode)) {
-+ inode->i_op = &pram_file_inode_operations;
-+ if (pram_use_xip(inode->i_sb)) {
-+ inode->i_mapping->a_ops = &pram_aops_xip;
-+ inode->i_fop = &pram_xip_file_operations;
-+ } else {
-+ inode->i_fop = &pram_file_operations;
-+ inode->i_mapping->a_ops = &pram_aops;
-+ }
-+ err = pram_add_nondir(dir, dentry, inode);
-+ }
-+ return err;
-+}
-+
-+static int pram_mknod(struct inode *dir, struct dentry *dentry, int mode,
-+ dev_t rdev)
-+{
-+ struct inode *inode = pram_new_inode(dir, mode, &dentry->d_name);
-+ int err = PTR_ERR(inode);
-+ if (!IS_ERR(inode)) {
-+ init_special_inode(inode, mode, rdev);
-+ inode->i_op = &pram_special_inode_operations;
-+ pram_write_inode(inode, NULL); /* update rdev */
-+ err = pram_add_nondir(dir, dentry, inode);
-+ }
-+ return err;
-+}
-+
-+static int pram_symlink(struct inode *dir, struct dentry *dentry,
-+ const char *symname)
-+{
-+ struct super_block *sb = dir->i_sb;
-+ int err = -ENAMETOOLONG;
-+ unsigned len = strlen(symname);
-+ struct inode *inode;
-+
-+ if (len+1 > sb->s_blocksize)
-+ goto out;
-+
-+ inode = pram_new_inode(dir, S_IFLNK | S_IRWXUGO, &dentry->d_name);
-+ err = PTR_ERR(inode);
-+ if (IS_ERR(inode))
-+ goto out;
-+
-+ inode->i_op = &pram_symlink_inode_operations;
-+ inode->i_mapping->a_ops = &pram_aops;
-+
-+ err = pram_block_symlink(inode, symname, len);
-+ if (err)
-+ goto out_fail;
-+
-+ inode->i_size = len;
-+ pram_write_inode(inode, NULL);
-+
-+ err = pram_add_nondir(dir, dentry, inode);
-+out:
-+ return err;
-+
-+out_fail:
-+ pram_dec_count(inode);
-+ unlock_new_inode(inode);
-+ iput(inode);
-+ goto out;
-+}
-+
-+static int pram_link(struct dentry *dest_dentry, struct inode *dir,
-+ struct dentry *dentry)
-+{
-+ pram_dbg("hard links not supported\n");
-+ return -EOPNOTSUPP;
-+}
-+
-+static int pram_unlink(struct inode *dir, struct dentry *dentry)
-+{
-+ struct inode *inode = dentry->d_inode;
-+ inode->i_ctime = dir->i_ctime;
-+ pram_dec_count(inode);
-+ return 0;
-+}
-+
-+static int pram_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-+{
-+ struct inode *inode;
-+ struct pram_inode *pi;
-+ int err = -EMLINK;
-+
-+ if (dir->i_nlink >= PRAM_LINK_MAX)
-+ goto out;
-+
-+ pram_inc_count(dir);
-+
-+ inode = pram_new_inode(dir, S_IFDIR | mode, &dentry->d_name);
-+ err = PTR_ERR(inode);
-+ if (IS_ERR(inode))
-+ goto out_dir;
-+
-+ inode->i_op = &pram_dir_inode_operations;
-+ inode->i_fop = &pram_dir_operations;
-+ inode->i_mapping->a_ops = &pram_aops;
-+
-+ pram_inc_count(inode);
-+
-+ /* make the new directory empty */
-+ pi = pram_get_inode(dir->i_sb, inode->i_ino);
-+ pram_memunlock_inode(dir->i_sb, pi);
-+ pi->i_type.dir.head = pi->i_type.dir.tail = 0;
-+ pram_memlock_inode(dir->i_sb, pi);
-+
-+ err = pram_add_link(dentry, inode);
-+ if (err)
-+ goto out_fail;
-+
-+ d_instantiate(dentry, inode);
-+ unlock_new_inode(inode);
-+out:
-+ return err;
-+
-+out_fail:
-+ pram_dec_count(inode);
-+ pram_dec_count(inode);
-+ unlock_new_inode(inode);
-+ iput(inode);
-+out_dir:
-+ pram_dec_count(dir);
-+ goto out;
-+}
-+
-+static int pram_rmdir(struct inode *dir, struct dentry *dentry)
-+{
-+ struct inode *inode = dentry->d_inode;
-+ struct pram_inode *pi;
-+ int err = -ENOTEMPTY;
-+
-+ if (!inode)
-+ return -ENOENT;
-+
-+ pi = pram_get_inode(dir->i_sb, inode->i_ino);
-+
-+ /* directory to delete is empty? */
-+ if (pi->i_type.dir.tail == 0) {
-+ inode->i_ctime = dir->i_ctime;
-+ inode->i_size = 0;
-+ inode->i_nlink = 0;
-+ pram_write_inode(inode, NULL);
-+ pram_dec_count(dir);
-+ err = 0;
-+ } else {
-+ pram_dbg("dir not empty\n");
-+ }
-+
-+ return err;
-+}
-+
-+static int pram_rename(struct inode *old_dir,
-+ struct dentry *old_dentry,
-+ struct inode *new_dir,
-+ struct dentry *new_dentry)
-+{
-+ struct inode *old_inode = old_dentry->d_inode;
-+ struct inode *new_inode = new_dentry->d_inode;
-+ struct pram_inode *pi_new;
-+ int err = -ENOENT;
-+
-+ if (new_inode) {
-+ err = -ENOTEMPTY;
-+ pi_new = pram_get_inode(new_dir->i_sb, new_inode->i_ino);
-+ if (S_ISDIR(old_inode->i_mode)) {
-+ if (pi_new->i_type.dir.tail != 0)
-+ goto out;
-+ if (new_inode->i_nlink)
-+ drop_nlink(new_inode);
-+ }
-+
-+ new_inode->i_ctime = CURRENT_TIME;
-+ pram_dec_count(new_inode);
-+ } else {
-+ if (S_ISDIR(old_inode->i_mode)) {
-+ err = -EMLINK;
-+ if (new_dir->i_nlink >= PRAM_LINK_MAX)
-+ goto out;
-+ pram_dec_count(old_dir);
-+ pram_inc_count(new_dir);
-+ }
-+ }
-+
-+ /* unlink the inode from the old directory ... */
-+ err = pram_remove_link(old_inode);
-+ if (err)
-+ goto out;
-+
-+ /* and link it into the new directory. */
-+ err = pram_add_link(new_dentry, old_inode);
-+ if (err)
-+ goto out;
-+
-+ err = 0;
-+ out:
-+ return err;
-+}
-+
-+struct dentry *pram_get_parent(struct dentry *child)
-+{
-+ struct inode *inode;
-+ struct pram_inode *pi, *piparent;
-+ ino_t ino;
-+
-+ pi = pram_get_inode(child->d_inode->i_sb, child->d_inode->i_ino);
-+ if (!pi)
-+ return ERR_PTR(-EACCES);
-+
-+ piparent = pram_get_inode(child->d_inode->i_sb,
-+ be64_to_cpu(pi->i_d.d_parent));
-+ if (!pi)
-+ return ERR_PTR(-ENOENT);
-+
-+ ino = pram_get_inodenr(child->d_inode->i_sb, piparent);
-+ if (ino)
-+ inode = pram_iget(child->d_inode->i_sb, ino);
-+ else
-+ return ERR_PTR(-ENOENT);
-+
-+ return d_obtain_alias(inode);
-+}
-+
-+const struct inode_operations pram_dir_inode_operations = {
-+ .create = pram_create,
-+ .lookup = pram_lookup,
-+ .link = pram_link,
-+ .unlink = pram_unlink,
-+ .symlink = pram_symlink,
-+ .mkdir = pram_mkdir,
-+ .rmdir = pram_rmdir,
-+ .mknod = pram_mknod,
-+ .rename = pram_rename,
-+#ifdef CONFIG_PRAMFS_XATTR
-+ .setxattr = generic_setxattr,
-+ .getxattr = generic_getxattr,
-+ .listxattr = pram_listxattr,
-+ .removexattr = generic_removexattr,
-+#endif
-+ .setattr = pram_notify_change,
-+ .check_acl = pram_check_acl,
-+};
-+
-+const struct inode_operations pram_special_inode_operations = {
-+#ifdef CONFIG_PRAMFS_XATTR
-+ .setxattr = generic_setxattr,
-+ .getxattr = generic_getxattr,
-+ .listxattr = pram_listxattr,
-+ .removexattr = generic_removexattr,
-+#endif
-+ .setattr = pram_notify_change,
-+ .check_acl = pram_check_acl,
-+};
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:17:09 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:10:36 +0200
-Subject: pramfs: symlinks
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FAE998C.1040504@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-Symlink operations.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
----
- fs/pramfs/symlink.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 76 insertions(+)
-
---- /dev/null
-+++ b/fs/pramfs/symlink.c
-@@ -0,0 +1,76 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Symlink operations
-+ *
-+ * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ * Copyright 2003 Sony Corporation
-+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
-+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
-+ * 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 <linux/fs.h>
-+#include "pram.h"
-+#include "xattr.h"
-+
-+int pram_block_symlink(struct inode *inode, const char *symname, int len)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ u64 block;
-+ char *blockp;
-+ int err;
-+
-+ err = pram_alloc_blocks(inode, 0, 1);
-+ if (err)
-+ return err;
-+
-+ block = pram_find_data_block(inode, 0);
-+ blockp = pram_get_block(sb, block);
-+
-+ pram_memunlock_block(sb, blockp);
-+ memcpy(blockp, symname, len);
-+ blockp[len] = '\0';
-+ pram_memlock_block(sb, blockp);
-+ return 0;
-+}
-+
-+static int pram_readlink(struct dentry *dentry, char __user *buffer, int buflen)
-+{
-+ struct inode *inode = dentry->d_inode;
-+ struct super_block *sb = inode->i_sb;
-+ u64 block;
-+ char *blockp;
-+
-+ block = pram_find_data_block(inode, 0);
-+ blockp = pram_get_block(sb, block);
-+ return vfs_readlink(dentry, buffer, buflen, blockp);
-+}
-+
-+static void *pram_follow_link(struct dentry *dentry, struct nameidata *nd)
-+{
-+ struct inode *inode = dentry->d_inode;
-+ struct super_block *sb = inode->i_sb;
-+ off_t block;
-+ int status;
-+ char *blockp;
-+
-+ block = pram_find_data_block(inode, 0);
-+ blockp = pram_get_block(sb, block);
-+ status = vfs_follow_link(nd, blockp);
-+ return ERR_PTR(status);
-+}
-+
-+const struct inode_operations pram_symlink_inode_operations = {
-+ .readlink = pram_readlink,
-+ .follow_link = pram_follow_link,
-+ .setattr = pram_notify_change,
-+#ifdef CONFIG_PRAMFS_XATTR
-+ .setxattr = generic_setxattr,
-+ .getxattr = generic_getxattr,
-+ .listxattr = pram_listxattr,
-+ .removexattr = generic_removexattr,
-+#endif
-+};
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:17:23 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:10:49 +0200
-Subject: pramfs: headers
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FAE9999.8000104@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-Definitions for the PRAMFS filesystem.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
----
- fs/pramfs/pram.h | 283 +++++++++++++++++++++++++++++++++++++++++++++
- include/linux/fs.h | 2
- include/linux/magic.h | 1
- include/linux/pram_fs.h | 130 ++++++++++++++++++++
- include/linux/pram_fs_sb.h | 45 +++++++
- 5 files changed, 461 insertions(+)
-
---- /dev/null
-+++ b/fs/pramfs/pram.h
-@@ -0,0 +1,283 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Definitions for the PRAMFS filesystem.
-+ *
-+ * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ * Copyright 2003 Sony Corporation
-+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
-+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
-+ * 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.
-+ */
-+#ifndef __PRAM_H
-+#define __PRAM_H
-+
-+#include <linux/buffer_head.h>
-+#include <linux/pram_fs.h>
-+#include <linux/pram_fs_sb.h>
-+#include <linux/crc16.h>
-+#include <linux/mutex.h>
-+#include <linux/rcupdate.h>
-+#include <linux/types.h>
-+#include "wprotect.h"
-+
-+/*
-+ * Debug code
-+ */
-+#ifdef pr_fmt
-+#undef pr_fmt
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+#endif
-+
-+#define pram_dbg(s, args...) pr_debug(s, ## args)
-+#define pram_err(sb, s, args...) pram_error_mng(sb, s, ## args)
-+#define pram_warn(s, args...) pr_warning(s, ## args)
-+#define pram_info(s, args...) pr_info(s, ## args)
-+
-+#define pram_set_bit __test_and_set_bit_le
-+#define pram_clear_bit __test_and_clear_bit_le
-+#define pram_find_next_zero_bit find_next_zero_bit_le
-+
-+#define clear_opt(o, opt) (o &= ~PRAM_MOUNT_##opt)
-+#define set_opt(o, opt) (o |= PRAM_MOUNT_##opt)
-+#define test_opt(sb, opt) (PRAM_SB(sb)->s_mount_opt & PRAM_MOUNT_##opt)
-+
-+/*
-+ * Pram inode flags
-+ *
-+ * PRAM_EOFBLOCKS_FL There are blocks allocated beyond eof
-+ */
-+#define PRAM_EOFBLOCKS_FL 0x20000000
-+/* Flags that should be inherited by new inodes from their parent. */
-+#define PRAM_FL_INHERITED (FS_SECRM_FL | FS_UNRM_FL | FS_COMPR_FL |\
-+ FS_SYNC_FL | FS_IMMUTABLE_FL | FS_APPEND_FL |\
-+ FS_NODUMP_FL | FS_NOATIME_FL | FS_COMPRBLK_FL |\
-+ FS_NOCOMP_FL | FS_JOURNAL_DATA_FL |\
-+ FS_NOTAIL_FL | FS_DIRSYNC_FL)
-+/* Flags that are appropriate for regular files (all but dir-specific ones). */
-+#define PRAM_REG_FLMASK (~(FS_DIRSYNC_FL | FS_TOPDIR_FL))
-+/* Flags that are appropriate for non-directories/regular files. */
-+#define PRAM_OTHER_FLMASK (FS_NODUMP_FL | FS_NOATIME_FL)
-+#define PRAM_FL_USER_VISIBLE (FS_FL_USER_VISIBLE | PRAM_EOFBLOCKS_FL)
-+
-+/* Function Prototypes */
-+extern void pram_error_mng(struct super_block *sb, const char *fmt, ...);
-+
-+/* file.c */
-+extern ssize_t pram_direct_IO(int rw, struct kiocb *iocb,
-+ const struct iovec *iov,
-+ loff_t offset, unsigned long nr_segs);
-+extern int pram_mmap(struct file *file, struct vm_area_struct *vma);
-+
-+/* balloc.c */
-+extern void pram_init_bitmap(struct super_block *sb);
-+extern void pram_free_block(struct super_block *sb, unsigned long blocknr);
-+extern int pram_new_block(struct super_block *sb, unsigned long *blocknr,
-+ int zero);
-+extern unsigned long pram_count_free_blocks(struct super_block *sb);
-+
-+/* dir.c */
-+extern int pram_add_link(struct dentry *dentry, struct inode *inode);
-+extern int pram_remove_link(struct inode *inode);
-+
-+/* namei.c */
-+extern struct dentry *pram_get_parent(struct dentry *child);
-+
-+/* inode.c */
-+extern int pram_alloc_blocks(struct inode *inode, int file_blocknr,
-+ unsigned int num);
-+extern u64 pram_find_data_block(struct inode *inode,
-+ unsigned long file_blocknr);
-+
-+extern struct inode *pram_iget(struct super_block *sb, unsigned long ino);
-+extern void pram_put_inode(struct inode *inode);
-+extern void pram_evict_inode(struct inode *inode);
-+extern struct inode *pram_new_inode(struct inode *dir, int mode,
-+ const struct qstr *qstr);
-+extern int pram_update_inode(struct inode *inode);
-+extern int pram_write_inode(struct inode *inode, struct writeback_control *wbc);
-+extern void pram_dirty_inode(struct inode *inode, int flags);
-+extern int pram_notify_change(struct dentry *dentry, struct iattr *attr);
-+extern void pram_set_inode_flags(struct inode *inode, struct pram_inode *pi);
-+extern void pram_get_inode_flags(struct inode *inode, struct pram_inode *pi);
-+
-+/* ioctl.c */
-+extern long pram_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-+#ifdef CONFIG_COMPAT
-+extern long pram_compat_ioctl(struct file *file, unsigned int cmd,
-+ unsigned long arg);
-+#endif
-+
-+/* super.c */
-+#ifdef CONFIG_PRAMFS_TEST
-+extern struct pram_super_block *get_pram_super(void);
-+#endif
-+extern struct super_block *pram_read_super(struct super_block *sb,
-+ void *data,
-+ int silent);
-+extern int pram_statfs(struct dentry *d, struct kstatfs *buf);
-+extern int pram_remount(struct super_block *sb, int *flags, char *data);
-+
-+/* symlink.c */
-+extern int pram_block_symlink(struct inode *inode,
-+ const char *symname, int len);
-+
-+/* Inline functions start here */
-+
-+/* Mask out flags that are inappropriate for the given type of inode. */
-+static inline __be32 pram_mask_flags(umode_t mode, __be32 flags)
-+{
-+ flags &= cpu_to_be32(PRAM_FL_INHERITED);
-+ if (S_ISDIR(mode))
-+ return flags;
-+ else if (S_ISREG(mode))
-+ return flags & cpu_to_be32(PRAM_REG_FLMASK);
-+ else
-+ return flags & cpu_to_be32(PRAM_OTHER_FLMASK);
-+}
-+
-+static inline int pram_calc_checksum(u8 *data, int n)
-+{
-+ u16 crc = 0;
-+ crc = crc16(~0, (__u8 *)data + sizeof(__be16), n - sizeof(__be16));
-+ if (*((__be16 *)data) == cpu_to_be16(crc))
-+ return 0;
-+ else
-+ return 1;
-+}
-+
-+struct pram_inode_vfs {
-+#ifdef CONFIG_PRAMFS_XATTR
-+ /*
-+ * Extended attributes can be read independently of the main file
-+ * data. Taking i_mutex even when reading would cause contention
-+ * between readers of EAs and writers of regular file data, so
-+ * instead we synchronize on xattr_sem when reading or changing
-+ * EAs.
-+ */
-+ struct rw_semaphore xattr_sem;
-+#endif
-+ struct mutex i_meta_mutex;
-+ struct mutex i_link_mutex;
-+ struct inode vfs_inode;
-+};
-+
-+static inline struct pram_sb_info *PRAM_SB(struct super_block *sb)
-+{
-+ return sb->s_fs_info;
-+}
-+
-+static inline struct pram_inode_vfs *PRAM_I(struct inode *inode)
-+{
-+ return container_of(inode, struct pram_inode_vfs, vfs_inode);
-+}
-+
-+/* If this is part of a read-modify-write of the super block,
-+ pram_memunlock_super() before calling! */
-+static inline struct pram_super_block *
-+pram_get_super(struct super_block *sb)
-+{
-+ struct pram_sb_info *sbi = PRAM_SB(sb);
-+ return (struct pram_super_block *)sbi->virt_addr;
-+}
-+
-+static inline struct pram_super_block *
-+pram_get_redund_super(struct super_block *sb)
-+{
-+ struct pram_sb_info *sbi = PRAM_SB(sb);
-+ return (struct pram_super_block *)(sbi->virt_addr + PRAM_SB_SIZE);
-+}
-+
-+static inline void *
-+pram_get_bitmap(struct super_block *sb)
-+{
-+ struct pram_super_block *ps = pram_get_super(sb);
-+ return (void *)ps + be64_to_cpu(ps->s_bitmap_start);
-+}
-+
-+/* If this is part of a read-modify-write of the inode metadata,
-+ pram_memunlock_inode() before calling! */
-+static inline struct pram_inode *
-+pram_get_inode(struct super_block *sb, u64 ino)
-+{
-+ struct pram_super_block *ps = pram_get_super(sb);
-+ return ino ? (struct pram_inode *)((void *)ps + ino) : NULL;
-+}
-+
-+static inline ino_t
-+pram_get_inodenr(struct super_block *sb, struct pram_inode *pi)
-+{
-+ struct pram_super_block *ps = pram_get_super(sb);
-+ return (ino_t)((unsigned long)pi - (unsigned long)ps);
-+}
-+
-+static inline u64
-+pram_get_block_off(struct super_block *sb, unsigned long blocknr)
-+{
-+ struct pram_super_block *ps = pram_get_super(sb);
-+ return (u64)(be64_to_cpu(ps->s_bitmap_start) +
-+ (blocknr << sb->s_blocksize_bits));
-+}
-+
-+static inline unsigned long
-+pram_get_blocknr(struct super_block *sb, u64 block)
-+{
-+ struct pram_super_block *ps = pram_get_super(sb);
-+ return (block - be64_to_cpu(ps->s_bitmap_start)) >>
-+ sb->s_blocksize_bits;
-+}
-+
-+/* If this is part of a read-modify-write of the block,
-+ pram_memunlock_block() before calling! */
-+static inline void *
-+pram_get_block(struct super_block *sb, u64 block)
-+{
-+ struct pram_super_block *ps = pram_get_super(sb);
-+ return block ? ((void *)ps + block) : NULL;
-+}
-+
-+static inline unsigned long
-+pram_get_pfn(struct super_block *sb, u64 block)
-+{
-+ return (PRAM_SB(sb)->phys_addr + block) >> PAGE_SHIFT;
-+}
-+
-+static inline void check_eof_blocks(struct inode *inode, loff_t size)
-+{
-+ struct pram_inode *pi = pram_get_inode(inode->i_sb, inode->i_ino);
-+ if (unlikely(!pi))
-+ return;
-+ if ((pi->i_flags & cpu_to_be32(PRAM_EOFBLOCKS_FL)) &&
-+ size + inode->i_sb->s_blocksize >=
-+ (inode->i_blocks << inode->i_sb->s_blocksize_bits))
-+ pi->i_flags &= cpu_to_be32(~PRAM_EOFBLOCKS_FL);
-+}
-+
-+/*
-+ * Inodes and files operations
-+ */
-+
-+/* dir.c */
-+extern const struct file_operations pram_dir_operations;
-+
-+/* file.c */
-+extern const struct inode_operations pram_file_inode_operations;
-+extern const struct file_operations pram_file_operations;
-+extern const struct file_operations pram_xip_file_operations;
-+
-+/* inode.c */
-+extern const struct address_space_operations pram_aops;
-+extern const struct address_space_operations pram_aops_xip;
-+
-+/* namei.c */
-+extern const struct inode_operations pram_dir_inode_operations;
-+extern const struct inode_operations pram_special_inode_operations;
-+
-+/* symlink.c */
-+extern const struct inode_operations pram_symlink_inode_operations;
-+
-+extern struct backing_dev_info pram_backing_dev_info;
-+
-+#endif /* __PRAM_H */
---- a/include/linux/fs.h
-+++ b/include/linux/fs.h
-@@ -414,6 +414,7 @@ struct kobject;
- struct pipe_inode_info;
- struct poll_table_struct;
- struct kstatfs;
-+struct vm_fault;
- struct vm_area_struct;
- struct vfsmount;
- struct cred;
-@@ -2409,6 +2410,7 @@ extern int nonseekable_open(struct inode
- #ifdef CONFIG_FS_XIP
- extern ssize_t xip_file_read(struct file *filp, char __user *buf, size_t len,
- loff_t *ppos);
-+extern int xip_file_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
- extern int xip_file_mmap(struct file * file, struct vm_area_struct * vma);
- extern ssize_t xip_file_write(struct file *filp, const char __user *buf,
- size_t len, loff_t *ppos);
---- a/include/linux/magic.h
-+++ b/include/linux/magic.h
-@@ -68,5 +68,6 @@
- #define MTD_INODE_FS_MAGIC 0x11307854
- #define ANON_INODE_FS_MAGIC 0x09041934
-
-+#define PRAM_SUPER_MAGIC 0xEFFA
-
- #endif /* __LINUX_MAGIC_H__ */
---- /dev/null
-+++ b/include/linux/pram_fs.h
-@@ -0,0 +1,130 @@
-+/*
-+ * FILE NAME include/linux/pram_fs.h
-+ *
-+ * BRIEF DESCRIPTION
-+ *
-+ * Definitions for the PRAMFS filesystem.
-+ *
-+ * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ * Copyright 2003 Sony Corporation
-+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
-+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
-+ * 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.
-+ */
-+#ifndef _LINUX_PRAM_FS_H
-+#define _LINUX_PRAM_FS_H
-+
-+#include <linux/types.h>
-+#include <linux/magic.h>
-+
-+/*
-+ * The PRAM filesystem constants/structures
-+ */
-+
-+/*
-+ * Mount flags
-+ */
-+#define PRAM_MOUNT_PROTECT 0x000001 /* Use memory protection */
-+#define PRAM_MOUNT_XATTR_USER 0x000002 /* Extended user attributes */
-+#define PRAM_MOUNT_POSIX_ACL 0x000004 /* POSIX ACL */
-+#define PRAM_MOUNT_XIP 0x000008 /* Execute in place */
-+#define PRAM_MOUNT_ERRORS_CONT 0x000010 /* Continue on errors */
-+#define PRAM_MOUNT_ERRORS_RO 0x000020 /* Remount fs ro on errors */
-+#define PRAM_MOUNT_ERRORS_PANIC 0x000040 /* Panic on errors */
-+
-+/*
-+ * Maximal count of links to a file
-+ */
-+#define PRAM_LINK_MAX 32000
-+
-+#define PRAM_MIN_BLOCK_SIZE 512
-+#define PRAM_MAX_BLOCK_SIZE 4096
-+#define PRAM_DEF_BLOCK_SIZE 2048
-+
-+#define PRAM_INODE_SIZE 128 /* must be power of two */
-+#define PRAM_INODE_BITS 7
-+
-+/*
-+ * Structure of a directory entry in PRAMFS.
-+ * Offsets are to the inode that holds the referenced dentry.
-+ */
-+struct pram_dentry {
-+ __be64 d_next; /* next dentry in this directory */
-+ __be64 d_prev; /* previous dentry in this directory */
-+ __be64 d_parent; /* parent directory */
-+ char d_name[0];
-+};
-+
-+
-+/*
-+ * Structure of an inode in PRAMFS
-+ */
-+struct pram_inode {
-+ __be16 i_sum; /* checksum of this inode */
-+ __be32 i_uid; /* Owner Uid */
-+ __be32 i_gid; /* Group Id */
-+ __be16 i_mode; /* File mode */
-+ __be16 i_links_count; /* Links count */
-+ __be32 i_blocks; /* Blocks count */
-+ __be32 i_size; /* Size of data in bytes */
-+ __be32 i_atime; /* Access time */
-+ __be32 i_ctime; /* Creation time */
-+ __be32 i_mtime; /* Modification time */
-+ __be32 i_dtime; /* Deletion Time */
-+ __be64 i_xattr; /* Extended attribute block */
-+ __be32 i_generation; /* File version (for NFS) */
-+ __be32 i_flags; /* Inode flags */
-+
-+ union {
-+ struct {
-+ /*
-+ * ptr to row block of 2D block pointer array,
-+ * file block #'s 0 to (blocksize/8)^2 - 1.
-+ */
-+ __be64 row_block;
-+ } reg; /* regular file or symlink inode */
-+ struct {
-+ __be64 head; /* first entry in this directory */
-+ __be64 tail; /* last entry in this directory */
-+ } dir;
-+ struct {
-+ __be32 rdev; /* major/minor # */
-+ } dev; /* device inode */
-+ } i_type;
-+
-+ struct pram_dentry i_d;
-+};
-+
-+#define PRAM_NAME_LEN \
-+ (PRAM_INODE_SIZE - offsetof(struct pram_inode, i_d.d_name) - 1)
-+
-+
-+#define PRAM_SB_SIZE 128 /* must be power of two */
-+
-+/*
-+ * Structure of the super block in PRAMFS
-+ */
-+struct pram_super_block {
-+ __be16 s_sum; /* checksum of this sb, including padding */
-+ __be64 s_size; /* total size of fs in bytes */
-+ __be32 s_blocksize; /* blocksize in bytes */
-+ __be32 s_inodes_count; /* total inodes count (used or free) */
-+ __be32 s_free_inodes_count;/* free inodes count */
-+ __be32 s_free_inode_hint; /* start hint for locating free inodes */
-+ __be32 s_blocks_count; /* total data blocks count (used or free) */
-+ __be32 s_free_blocks_count;/* free data blocks count */
-+ __be32 s_free_blocknr_hint;/* free data blocks count */
-+ __be64 s_bitmap_start; /* data block in-use bitmap location */
-+ __be32 s_bitmap_blocks;/* size of bitmap in number of blocks */
-+ __be32 s_mtime; /* Mount time */
-+ __be32 s_wtime; /* Write time */
-+ __be16 s_magic; /* Magic signature */
-+ char s_volume_name[16]; /* volume name */
-+};
-+
-+/* The root inode follows immediately after the redundant super block */
-+#define PRAM_ROOT_INO (PRAM_SB_SIZE*2)
-+
-+#endif /* _LINUX_PRAM_FS_H */
---- /dev/null
-+++ b/include/linux/pram_fs_sb.h
-@@ -0,0 +1,45 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Definitions for the PRAM filesystem.
-+ *
-+ * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ * Copyright 2003 Sony Corporation
-+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
-+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
-+ * 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.
-+ */
-+
-+#ifndef _LINUX_PRAM_FS_SB
-+#define _LINUX_PRAM_FS_SB
-+
-+/*
-+ * PRAM filesystem super-block data in memory
-+ */
-+struct pram_sb_info {
-+ /*
-+ * base physical and virtual address of PRAMFS (which is also
-+ * the pointer to the super block)
-+ */
-+ phys_addr_t phys_addr;
-+ void *virt_addr;
-+
-+ /* Mount options */
-+ unsigned long bpi;
-+ unsigned long num_inodes;
-+ unsigned long blocksize;
-+ unsigned long initsize;
-+ unsigned long s_mount_opt;
-+ uid_t uid; /* Mount uid for root directory */
-+ gid_t gid; /* Mount gid for root directory */
-+ mode_t mode; /* Mount mode for root directory */
-+ atomic_t next_generation;
-+#ifdef CONFIG_PRAMFS_XATTR
-+ struct rb_root desc_tree;
-+ spinlock_t desc_tree_lock;
-+#endif
-+};
-+
-+#endif /* _LINUX_PRAM_FS_SB */
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:17:35 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:11:01 +0200
-Subject: pramfs: dir operations
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FAE99A5.30806@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-File operations for directories.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
----
- fs/pramfs/dir.c | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 221 insertions(+)
-
---- /dev/null
-+++ b/fs/pramfs/dir.c
-@@ -0,0 +1,221 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * File operations for directories.
-+ *
-+ * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ * Copyright 2003 Sony Corporation
-+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
-+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
-+ * 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 <linux/fs.h>
-+#include <linux/pagemap.h>
-+#include "pram.h"
-+
-+/*
-+ * Parent is locked.
-+ */
-+int pram_add_link(struct dentry *dentry, struct inode *inode)
-+{
-+ struct inode *dir = dentry->d_parent->d_inode;
-+ struct pram_inode *pidir, *pi, *pitail = NULL;
-+ u64 tail_ino, prev_ino;
-+
-+ const char *name = dentry->d_name.name;
-+
-+ int namelen = min_t(unsigned int, dentry->d_name.len, PRAM_NAME_LEN);
-+
-+ pidir = pram_get_inode(dir->i_sb, dir->i_ino);
-+
-+ mutex_lock(&PRAM_I(dir)->i_link_mutex);
-+
-+ pi = pram_get_inode(dir->i_sb, inode->i_ino);
-+
-+ dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-+
-+ tail_ino = be64_to_cpu(pidir->i_type.dir.tail);
-+ if (tail_ino != 0) {
-+ pitail = pram_get_inode(dir->i_sb, tail_ino);
-+ pram_memunlock_inode(dir->i_sb, pitail);
-+ pitail->i_d.d_next = cpu_to_be64(inode->i_ino);
-+ pram_memlock_inode(dir->i_sb, pitail);
-+
-+ prev_ino = tail_ino;
-+
-+ pram_memunlock_inode(dir->i_sb, pidir);
-+ pidir->i_type.dir.tail = cpu_to_be64(inode->i_ino);
-+ pidir->i_mtime = cpu_to_be32(dir->i_mtime.tv_sec);
-+ pidir->i_ctime = cpu_to_be32(dir->i_ctime.tv_sec);
-+ pram_memlock_inode(dir->i_sb, pidir);
-+ } else {
-+ /* the directory is empty */
-+ prev_ino = 0;
-+
-+ pram_memunlock_inode(dir->i_sb, pidir);
-+ pidir->i_type.dir.tail = cpu_to_be64(inode->i_ino);
-+ pidir->i_type.dir.head = cpu_to_be64(inode->i_ino);
-+ pidir->i_mtime = cpu_to_be32(dir->i_mtime.tv_sec);
-+ pidir->i_ctime = cpu_to_be32(dir->i_ctime.tv_sec);
-+ pram_memlock_inode(dir->i_sb, pidir);
-+ }
-+
-+
-+ pram_memunlock_inode(dir->i_sb, pi);
-+ pi->i_d.d_prev = cpu_to_be64(prev_ino);
-+ pi->i_d.d_parent = cpu_to_be64(dir->i_ino);
-+ memcpy(pi->i_d.d_name, name, namelen);
-+ pi->i_d.d_name[namelen] = '\0';
-+ pram_memlock_inode(dir->i_sb, pi);
-+ mutex_unlock(&PRAM_I(dir)->i_link_mutex);
-+ return 0;
-+}
-+
-+int pram_remove_link(struct inode *inode)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_inode *prev = NULL;
-+ struct pram_inode *next = NULL;
-+ struct pram_inode *pidir, *pi;
-+ struct inode *dir = NULL;
-+
-+ pi = pram_get_inode(sb, inode->i_ino);
-+ pidir = pram_get_inode(sb, be64_to_cpu(pi->i_d.d_parent));
-+ if (!pidir)
-+ return -EACCES;
-+
-+ dir = pram_iget(inode->i_sb, be64_to_cpu(pi->i_d.d_parent));
-+ if (IS_ERR(dir))
-+ return -EACCES;
-+ mutex_lock(&PRAM_I(dir)->i_link_mutex);
-+
-+ if (inode->i_ino == be64_to_cpu(pidir->i_type.dir.head)) {
-+ /* first inode in directory */
-+ next = pram_get_inode(sb, be64_to_cpu(pi->i_d.d_next));
-+
-+ if (next) {
-+ pram_memunlock_inode(sb, next);
-+ next->i_d.d_prev = 0;
-+ pram_memlock_inode(sb, next);
-+
-+ pram_memunlock_inode(sb, pidir);
-+ pidir->i_type.dir.head = pi->i_d.d_next;
-+ } else {
-+ pram_memunlock_inode(sb, pidir);
-+ pidir->i_type.dir.head = 0;
-+ pidir->i_type.dir.tail = 0;
-+ }
-+ pram_memlock_inode(sb, pidir);
-+ } else if (inode->i_ino == be64_to_cpu(pidir->i_type.dir.tail)) {
-+ /* last inode in directory */
-+ prev = pram_get_inode(sb, be64_to_cpu(pi->i_d.d_prev));
-+
-+ pram_memunlock_inode(sb, prev);
-+ prev->i_d.d_next = 0;
-+ pram_memlock_inode(sb, prev);
-+
-+ pram_memunlock_inode(sb, pidir);
-+ pidir->i_type.dir.tail = pi->i_d.d_prev;
-+ pram_memlock_inode(sb, pidir);
-+ } else {
-+ /* somewhere in the middle */
-+ prev = pram_get_inode(sb, be64_to_cpu(pi->i_d.d_prev));
-+ next = pram_get_inode(sb, be64_to_cpu(pi->i_d.d_next));
-+
-+ if (prev && next) {
-+ pram_memunlock_inode(sb, prev);
-+ prev->i_d.d_next = pi->i_d.d_next;
-+ pram_memlock_inode(sb, prev);
-+
-+ pram_memunlock_inode(sb, next);
-+ next->i_d.d_prev = pi->i_d.d_prev;
-+ pram_memlock_inode(sb, next);
-+ }
-+ }
-+
-+ pram_memunlock_inode(sb, pi);
-+ pi->i_d.d_next = 0;
-+ pi->i_d.d_prev = 0;
-+ pi->i_d.d_parent = 0;
-+ pram_memlock_inode(sb, pi);
-+ mutex_unlock(&PRAM_I(dir)->i_link_mutex);
-+ iput(dir);
-+
-+ return 0;
-+}
-+
-+#define DT2IF(dt) (((dt) << 12) & S_IFMT)
-+#define IF2DT(sif) (((sif) & S_IFMT) >> 12)
-+
-+static int pram_readdir(struct file *filp, void *dirent, filldir_t filldir)
-+{
-+ struct inode *inode = filp->f_dentry->d_inode;
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_inode *pi;
-+ int namelen, ret = 0;
-+ char *name;
-+ ino_t ino;
-+
-+ pi = pram_get_inode(sb, inode->i_ino);
-+
-+ switch ((unsigned long)filp->f_pos) {
-+ case 0:
-+ ret = filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR);
-+ filp->f_pos++;
-+ return ret;
-+ case 1:
-+ ret = filldir(dirent, "..", 2, 1, be64_to_cpu(pi->i_d.d_parent),
-+ DT_DIR);
-+ ino = be64_to_cpu(pi->i_type.dir.head);
-+ filp->f_pos = ino ? ino : 2;
-+ return ret;
-+ case 2:
-+ ino = be64_to_cpu(pi->i_type.dir.head);
-+ if (ino) {
-+ filp->f_pos = ino;
-+ pi = pram_get_inode(sb, ino);
-+ break;
-+ } else {
-+ /* the directory is empty */
-+ filp->f_pos = 2;
-+ return 0;
-+ }
-+ case 3:
-+ return 0;
-+ default:
-+ ino = filp->f_pos;
-+ pi = pram_get_inode(sb, ino);
-+ break;
-+ }
-+
-+ while (pi && !be16_to_cpu(pi->i_links_count)) {
-+ ino = filp->f_pos = be64_to_cpu(pi->i_d.d_next);
-+ pi = pram_get_inode(sb, ino);
-+ }
-+
-+ if (pi) {
-+ name = pi->i_d.d_name;
-+ namelen = strlen(name);
-+
-+ ret = filldir(dirent, name, namelen,
-+ filp->f_pos, ino,
-+ IF2DT(be16_to_cpu(pi->i_mode)));
-+ filp->f_pos = pi->i_d.d_next ? be64_to_cpu(pi->i_d.d_next) : 3;
-+ } else
-+ filp->f_pos = 3;
-+
-+ return ret;
-+}
-+
-+const struct file_operations pram_dir_operations = {
-+ .read = generic_read_dir,
-+ .readdir = pram_readdir,
-+ .fsync = noop_fsync,
-+ .unlocked_ioctl = pram_ioctl,
-+#ifdef CONFIG_COMPAT
-+ .compat_ioctl = pram_compat_ioctl,
-+#endif
-+};
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:17:49 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:11:14 +0200
-Subject: pramfs: xip support
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FAE99B2.1050508@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-XIP operations.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
-
----
- fs/pramfs/xip.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
- fs/pramfs/xip.h | 33 +++++++++++++++
- mm/filemap_xip.c | 3 -
- 3 files changed, 152 insertions(+), 1 deletion(-)
-
---- /dev/null
-+++ b/fs/pramfs/xip.c
-@@ -0,0 +1,117 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * XIP operations.
-+ *
-+ * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.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 <linux/mm.h>
-+#include <linux/fs.h>
-+#include <linux/buffer_head.h>
-+#include "pram.h"
-+#include "xip.h"
-+
-+/*
-+ * Wrappers. We need to use the rcu read lock to avoid
-+ * concurrent truncate operation. No problem for write because we held
-+ * i_mutex.
-+ */
-+ssize_t pram_xip_file_read(struct file *filp, char __user *buf,
-+ size_t len, loff_t *ppos)
-+{
-+ ssize_t res;
-+ rcu_read_lock();
-+ res = xip_file_read(filp, buf, len, ppos);
-+ rcu_read_unlock();
-+ return res;
-+}
-+
-+static int pram_xip_file_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-+{
-+ int ret = 0;
-+ rcu_read_lock();
-+ ret = xip_file_fault(vma, vmf);
-+ rcu_read_unlock();
-+ return ret;
-+}
-+
-+static const struct vm_operations_struct pram_xip_vm_ops = {
-+ .fault = pram_xip_file_fault,
-+};
-+
-+int pram_xip_file_mmap(struct file * file, struct vm_area_struct * vma)
-+{
-+ BUG_ON(!file->f_mapping->a_ops->get_xip_mem);
-+
-+ file_accessed(file);
-+ vma->vm_ops = &pram_xip_vm_ops;
-+ vma->vm_flags |= VM_CAN_NONLINEAR | VM_MIXEDMAP;
-+ return 0;
-+}
-+
-+static int pram_find_and_alloc_blocks(struct inode *inode, sector_t iblock,
-+ sector_t *data_block, int create)
-+{
-+ int err = -EIO;
-+ u64 block;
-+
-+ block = pram_find_data_block(inode, iblock);
-+
-+ if (!block) {
-+ if (!create) {
-+ err = -ENODATA;
-+ goto err;
-+ }
-+
-+ err = pram_alloc_blocks(inode, iblock, 1);
-+ if (err)
-+ goto err;
-+
-+ block = pram_find_data_block(inode, iblock);
-+ if (!block) {
-+ err = -ENODATA;
-+ goto err;
-+ }
-+ }
-+
-+ *data_block = block;
-+ err = 0;
-+
-+ err:
-+ return err;
-+}
-+
-+static inline int __pram_get_block(struct inode *inode, pgoff_t pgoff,
-+ int create, sector_t *result)
-+{
-+ int rc = 0;
-+
-+ rc = pram_find_and_alloc_blocks(inode, (sector_t)pgoff, result, create);
-+
-+ if (rc == -ENODATA)
-+ BUG_ON(create);
-+
-+ return rc;
-+}
-+
-+int pram_get_xip_mem(struct address_space *mapping, pgoff_t pgoff, int create,
-+ void **kmem, unsigned long *pfn)
-+{
-+ int rc;
-+ sector_t block = 0;
-+
-+ /* first, retrieve the block */
-+ rc = __pram_get_block(mapping->host, pgoff, create, &block);
-+ if (rc)
-+ goto exit;
-+
-+ *kmem = pram_get_block(mapping->host->i_sb, block);
-+ *pfn = pram_get_pfn(mapping->host->i_sb, block);
-+
-+exit:
-+ return rc;
-+}
---- /dev/null
-+++ b/fs/pramfs/xip.h
-@@ -0,0 +1,33 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * XIP operations.
-+ *
-+ * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.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.
-+ */
-+
-+#ifdef CONFIG_PRAMFS_XIP
-+int pram_get_xip_mem(struct address_space *, pgoff_t, int, void **,
-+ unsigned long *);
-+ssize_t pram_xip_file_read(struct file *filp, char __user *buf,
-+ size_t len, loff_t *ppos);
-+int pram_xip_file_mmap(struct file * file, struct vm_area_struct * vma);
-+static inline int pram_use_xip(struct super_block *sb)
-+{
-+ struct pram_sb_info *sbi = PRAM_SB(sb);
-+ return sbi->s_mount_opt & PRAM_MOUNT_XIP;
-+}
-+#define mapping_is_xip(map) (map->a_ops->get_xip_mem)
-+
-+#else
-+
-+#define mapping_is_xip(map) 0
-+#define pram_use_xip(sb) 0
-+#define pram_get_xip_mem NULL
-+#define pram_xip_file_read NULL
-+#define pram_xip_file_mmap NULL
-+
-+#endif
---- a/mm/filemap_xip.c
-+++ b/mm/filemap_xip.c
-@@ -218,7 +218,7 @@ retry:
- *
- * This function is derived from filemap_fault, but used for execute in place
- */
--static int xip_file_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-+int xip_file_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
- {
- struct file *file = vma->vm_file;
- struct address_space *mapping = file->f_mapping;
-@@ -302,6 +302,7 @@ out:
- }
- }
-
-+EXPORT_SYMBOL_GPL(xip_file_fault);
- static const struct vm_operations_struct xip_file_vm_ops = {
- .fault = xip_file_fault,
- };
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:18:05 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:11:30 +0200
-Subject: pramfs: ACL support
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-ACL operations.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
-
----
- fs/pramfs/acl.c | 441 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- fs/pramfs/acl.h | 86 ++++++++++
- 2 files changed, 527 insertions(+)
-
---- /dev/null
-+++ b/fs/pramfs/acl.c
-@@ -0,0 +1,441 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * POSIX ACL operations
-+ *
-+ * Copyright 2010-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ *
-+ * based on fs/ext2/acl.c with the following copyright:
-+ *
-+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
-+ *
-+ * 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 <linux/capability.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/fs.h>
-+#include "pram.h"
-+#include "xattr.h"
-+#include "acl.h"
-+
-+/*
-+ * Load ACL information from filesystem.
-+ */
-+static struct posix_acl *pram_acl_load(const void *value, size_t size)
-+{
-+ const char *end = (char *)value + size;
-+ int n, count;
-+ struct posix_acl *acl;
-+
-+ if (!value)
-+ return NULL;
-+ if (size < sizeof(struct pram_acl_header))
-+ return ERR_PTR(-EINVAL);
-+ if (((struct pram_acl_header *)value)->a_version !=
-+ cpu_to_be32(PRAM_ACL_VERSION))
-+ return ERR_PTR(-EINVAL);
-+ value = (char *)value + sizeof(struct pram_acl_header);
-+ count = pram_acl_count(size);
-+ if (count < 0)
-+ return ERR_PTR(-EINVAL);
-+ if (count == 0)
-+ return NULL;
-+ acl = posix_acl_alloc(count, GFP_KERNEL);
-+ if (!acl)
-+ return ERR_PTR(-ENOMEM);
-+ for (n = 0; n < count; n++) {
-+ struct pram_acl_entry *entry = (struct pram_acl_entry *)value;
-+ if ((char *)value + sizeof(struct pram_acl_entry_short) > end)
-+ goto fail;
-+ acl->a_entries[n].e_tag = be16_to_cpu(entry->e_tag);
-+ acl->a_entries[n].e_perm = be16_to_cpu(entry->e_perm);
-+ switch (acl->a_entries[n].e_tag) {
-+ case ACL_USER_OBJ:
-+ case ACL_GROUP_OBJ:
-+ case ACL_MASK:
-+ case ACL_OTHER:
-+ value = (char *)value +
-+ sizeof(struct pram_acl_entry_short);
-+ acl->a_entries[n].e_id = ACL_UNDEFINED_ID;
-+ break;
-+ case ACL_USER:
-+ case ACL_GROUP:
-+ value = (char *)value + sizeof(struct pram_acl_entry);
-+ if ((char *)value > end)
-+ goto fail;
-+ acl->a_entries[n].e_id =
-+ be32_to_cpu(entry->e_id);
-+ break;
-+ default:
-+ goto fail;
-+ }
-+ }
-+ if (value != end)
-+ goto fail;
-+ return acl;
-+
-+fail:
-+ posix_acl_release(acl);
-+ return ERR_PTR(-EINVAL);
-+}
-+
-+/*
-+ * Save ACL information into the filesystem.
-+ */
-+static void *pram_acl_save(const struct posix_acl *acl, size_t *size)
-+{
-+ struct pram_acl_header *ext_acl;
-+ char *e;
-+ size_t n;
-+
-+ *size = pram_acl_size(acl->a_count);
-+ ext_acl = kmalloc(sizeof(struct pram_acl_header) + acl->a_count *
-+ sizeof(struct pram_acl_entry), GFP_KERNEL);
-+ if (!ext_acl)
-+ return ERR_PTR(-ENOMEM);
-+ ext_acl->a_version = cpu_to_be32(PRAM_ACL_VERSION);
-+ e = (char *)ext_acl + sizeof(struct pram_acl_header);
-+ for (n = 0; n < acl->a_count; n++) {
-+ struct pram_acl_entry *entry = (struct pram_acl_entry *)e;
-+ entry->e_tag = cpu_to_be16(acl->a_entries[n].e_tag);
-+ entry->e_perm = cpu_to_be16(acl->a_entries[n].e_perm);
-+ switch (acl->a_entries[n].e_tag) {
-+ case ACL_USER:
-+ case ACL_GROUP:
-+ entry->e_id =
-+ cpu_to_be32(acl->a_entries[n].e_id);
-+ e += sizeof(struct pram_acl_entry);
-+ break;
-+ case ACL_USER_OBJ:
-+ case ACL_GROUP_OBJ:
-+ case ACL_MASK:
-+ case ACL_OTHER:
-+ e += sizeof(struct pram_acl_entry_short);
-+ break;
-+ default:
-+ goto fail;
-+ }
-+ }
-+ return (char *)ext_acl;
-+
-+fail:
-+ kfree(ext_acl);
-+ return ERR_PTR(-EINVAL);
-+}
-+
-+/*
-+ * inode->i_mutex: don't care
-+ */
-+static struct posix_acl *pram_get_acl(struct inode *inode, int type)
-+{
-+ int name_index;
-+ char *value = NULL;
-+ struct posix_acl *acl;
-+ int retval;
-+
-+ if (!test_opt(inode->i_sb, POSIX_ACL))
-+ return NULL;
-+
-+ acl = get_cached_acl(inode, type);
-+ if (acl != ACL_NOT_CACHED)
-+ return acl;
-+
-+ switch (type) {
-+ case ACL_TYPE_ACCESS:
-+ name_index = PRAM_XATTR_INDEX_POSIX_ACL_ACCESS;
-+ break;
-+ case ACL_TYPE_DEFAULT:
-+ name_index = PRAM_XATTR_INDEX_POSIX_ACL_DEFAULT;
-+ break;
-+ default:
-+ BUG();
-+ }
-+ retval = pram_xattr_get(inode, name_index, "", NULL, 0);
-+ if (retval > 0) {
-+ value = kmalloc(retval, GFP_KERNEL);
-+ if (!value)
-+ return ERR_PTR(-ENOMEM);
-+ retval = pram_xattr_get(inode, name_index, "", value, retval);
-+ }
-+ if (retval > 0)
-+ acl = pram_acl_load(value, retval);
-+ else if (retval == -ENODATA || retval == -ENOSYS)
-+ acl = NULL;
-+ else
-+ acl = ERR_PTR(retval);
-+ kfree(value);
-+
-+ if (!IS_ERR(acl))
-+ set_cached_acl(inode, type, acl);
-+
-+ return acl;
-+}
-+
-+/*
-+ * inode->i_mutex: down
-+ */
-+static int pram_set_acl(struct inode *inode, int type, struct posix_acl *acl)
-+{
-+ int name_index;
-+ void *value = NULL;
-+ size_t size = 0;
-+ int error;
-+
-+ if (S_ISLNK(inode->i_mode))
-+ return -EOPNOTSUPP;
-+ if (!test_opt(inode->i_sb, POSIX_ACL))
-+ return 0;
-+
-+ switch (type) {
-+ case ACL_TYPE_ACCESS:
-+ name_index = PRAM_XATTR_INDEX_POSIX_ACL_ACCESS;
-+ if (acl) {
-+ mode_t mode = inode->i_mode;
-+ error = posix_acl_equiv_mode(acl, &mode);
-+ if (error < 0)
-+ return error;
-+ else {
-+ inode->i_mode = mode;
-+ inode->i_ctime = CURRENT_TIME_SEC;
-+ mark_inode_dirty(inode);
-+ if (error == 0)
-+ acl = NULL;
-+ }
-+ }
-+ break;
-+ case ACL_TYPE_DEFAULT:
-+ name_index = PRAM_XATTR_INDEX_POSIX_ACL_DEFAULT;
-+ if (!S_ISDIR(inode->i_mode))
-+ return acl ? -EACCES : 0;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ if (acl) {
-+ value = pram_acl_save(acl, &size);
-+ if (IS_ERR(value))
-+ return (int)PTR_ERR(value);
-+ }
-+
-+ error = pram_xattr_set(inode, name_index, "", value, size, 0);
-+
-+ kfree(value);
-+ if (!error)
-+ set_cached_acl(inode, type, acl);
-+ return error;
-+}
-+
-+int pram_check_acl(struct inode *inode, int mask, unsigned int flags)
-+{
-+ struct posix_acl *acl;
-+
-+ if (flags & IPERM_FLAG_RCU) {
-+ if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
-+ return -ECHILD;
-+ return -EAGAIN;
-+ }
-+
-+ acl = pram_get_acl(inode, ACL_TYPE_ACCESS);
-+ if (IS_ERR(acl))
-+ return PTR_ERR(acl);
-+ if (acl) {
-+ int error = posix_acl_permission(inode, acl, mask);
-+ posix_acl_release(acl);
-+ return error;
-+ }
-+
-+ return -EAGAIN;
-+}
-+
-+/*
-+ * Initialize the ACLs of a new inode. Called from pram_new_inode.
-+ *
-+ * dir->i_mutex: down
-+ * inode->i_mutex: up (access to inode is still exclusive)
-+ */
-+int pram_init_acl(struct inode *inode, struct inode *dir)
-+{
-+ struct posix_acl *acl = NULL;
-+ int error = 0;
-+
-+ if (!S_ISLNK(inode->i_mode)) {
-+ if (test_opt(dir->i_sb, POSIX_ACL)) {
-+ acl = pram_get_acl(dir, ACL_TYPE_DEFAULT);
-+ if (IS_ERR(acl))
-+ return PTR_ERR(acl);
-+ }
-+ if (!acl)
-+ inode->i_mode &= ~current_umask();
-+ }
-+
-+ if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
-+ struct posix_acl *clone;
-+ mode_t mode;
-+
-+ if (S_ISDIR(inode->i_mode)) {
-+ error = pram_set_acl(inode, ACL_TYPE_DEFAULT, acl);
-+ if (error)
-+ goto cleanup;
-+ }
-+ clone = posix_acl_clone(acl, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (!clone)
-+ goto cleanup;
-+ mode = inode->i_mode;
-+ error = posix_acl_create_masq(clone, &mode);
-+ if (error >= 0) {
-+ inode->i_mode = mode;
-+ if (error > 0) {
-+ /* This is an extended ACL */
-+ error = pram_set_acl(inode,
-+ ACL_TYPE_ACCESS, clone);
-+ }
-+ }
-+ posix_acl_release(clone);
-+ }
-+cleanup:
-+ posix_acl_release(acl);
-+ return error;
-+}
-+
-+/*
-+ * Does chmod for an inode that may have an Access Control List. The
-+ * inode->i_mode field must be updated to the desired value by the caller
-+ * before calling this function.
-+ * Returns 0 on success, or a negative error number.
-+ *
-+ * We change the ACL rather than storing some ACL entries in the file
-+ * mode permission bits (which would be more efficient), because that
-+ * would break once additional permissions (like ACL_APPEND, ACL_DELETE
-+ * for directories) are added. There are no more bits available in the
-+ * file mode.
-+ *
-+ * inode->i_mutex: down
-+ */
-+int pram_acl_chmod(struct inode *inode)
-+{
-+ struct posix_acl *acl, *clone;
-+ int error;
-+
-+ if (!test_opt(inode->i_sb, POSIX_ACL))
-+ return 0;
-+ if (S_ISLNK(inode->i_mode))
-+ return -EOPNOTSUPP;
-+ acl = pram_get_acl(inode, ACL_TYPE_ACCESS);
-+ if (IS_ERR(acl) || !acl)
-+ return PTR_ERR(acl);
-+ clone = posix_acl_clone(acl, GFP_KERNEL);
-+ posix_acl_release(acl);
-+ if (!clone)
-+ return -ENOMEM;
-+ error = posix_acl_chmod_masq(clone, inode->i_mode);
-+ if (!error)
-+ error = pram_set_acl(inode, ACL_TYPE_ACCESS, clone);
-+ posix_acl_release(clone);
-+ return error;
-+}
-+
-+/*
-+ * Extended attribut handlers
-+ */
-+static size_t pram_xattr_list_acl_access(struct dentry *dentry, char *list,
-+ size_t list_size, const char *name,
-+ size_t name_len, int type)
-+{
-+ const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
-+
-+ if (!test_opt(dentry->d_sb, POSIX_ACL))
-+ return 0;
-+ if (list && size <= list_size)
-+ memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
-+ return size;
-+}
-+
-+static size_t pram_xattr_list_acl_default(struct dentry *dentry, char *list,
-+ size_t list_size, const char *name,
-+ size_t name_len, int type)
-+{
-+ const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
-+
-+ if (!test_opt(dentry->d_sb, POSIX_ACL))
-+ return 0;
-+ if (list && size <= list_size)
-+ memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
-+ return size;
-+}
-+
-+static int pram_xattr_get_acl(struct dentry *dentry, const char *name,
-+ void *buffer, size_t size, int type)
-+{
-+ struct posix_acl *acl;
-+ int error;
-+
-+ if (strcmp(name, "") != 0)
-+ return -EINVAL;
-+ if (!test_opt(dentry->d_sb, POSIX_ACL))
-+ return -EOPNOTSUPP;
-+
-+ acl = pram_get_acl(dentry->d_inode, type);
-+ if (IS_ERR(acl))
-+ return PTR_ERR(acl);
-+ if (acl == NULL)
-+ return -ENODATA;
-+ error = posix_acl_to_xattr(acl, buffer, size);
-+ posix_acl_release(acl);
-+
-+ return error;
-+}
-+
-+static int pram_xattr_set_acl(struct dentry *dentry, const char *name,
-+ const void *value, size_t size, int flags,
-+ int type)
-+{
-+ struct posix_acl *acl;
-+ int error;
-+
-+ if (strcmp(name, "") != 0)
-+ return -EINVAL;
-+ if (!test_opt(dentry->d_sb, POSIX_ACL))
-+ return -EOPNOTSUPP;
-+ if (!inode_owner_or_capable(dentry->d_inode))
-+ return -EPERM;
-+
-+ if (value) {
-+ acl = posix_acl_from_xattr(value, size);
-+ if (IS_ERR(acl))
-+ return PTR_ERR(acl);
-+ else if (acl) {
-+ error = posix_acl_valid(acl);
-+ if (error)
-+ goto release_and_out;
-+ }
-+ } else
-+ acl = NULL;
-+
-+ error = pram_set_acl(dentry->d_inode, type, acl);
-+
-+release_and_out:
-+ posix_acl_release(acl);
-+ return error;
-+}
-+
-+const struct xattr_handler pram_xattr_acl_access_handler = {
-+ .prefix = POSIX_ACL_XATTR_ACCESS,
-+ .flags = ACL_TYPE_ACCESS,
-+ .list = pram_xattr_list_acl_access,
-+ .get = pram_xattr_get_acl,
-+ .set = pram_xattr_set_acl,
-+};
-+
-+const struct xattr_handler pram_xattr_acl_default_handler = {
-+ .prefix = POSIX_ACL_XATTR_DEFAULT,
-+ .flags = ACL_TYPE_DEFAULT,
-+ .list = pram_xattr_list_acl_default,
-+ .get = pram_xattr_get_acl,
-+ .set = pram_xattr_set_acl,
-+};
---- /dev/null
-+++ b/fs/pramfs/acl.h
-@@ -0,0 +1,86 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * POSIX ACL operations
-+ *
-+ * Copyright 2010-2011 Marco Stornelli <marco.stornelli@gmail.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.
-+ *
-+ * Based on fs/ext2/acl.h with the following copyright:
-+ *
-+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
-+ *
-+ */
-+
-+#include <linux/posix_acl_xattr.h>
-+
-+#define PRAM_ACL_VERSION 0x0001
-+
-+struct pram_acl_entry {
-+ __be16 e_tag;
-+ __be16 e_perm;
-+ __be32 e_id;
-+};
-+
-+struct pram_acl_entry_short {
-+ __be16 e_tag;
-+ __be16 e_perm;
-+};
-+
-+struct pram_acl_header {
-+ __be32 a_version;
-+};
-+
-+static inline size_t pram_acl_size(int count)
-+{
-+ if (count <= 4) {
-+ return sizeof(struct pram_acl_header) +
-+ count * sizeof(struct pram_acl_entry_short);
-+ } else {
-+ return sizeof(struct pram_acl_header) +
-+ 4 * sizeof(struct pram_acl_entry_short) +
-+ (count - 4) * sizeof(struct pram_acl_entry);
-+ }
-+}
-+
-+static inline int pram_acl_count(size_t size)
-+{
-+ ssize_t s;
-+ size -= sizeof(struct pram_acl_header);
-+ s = size - 4 * sizeof(struct pram_acl_entry_short);
-+ if (s < 0) {
-+ if (size % sizeof(struct pram_acl_entry_short))
-+ return -1;
-+ return size / sizeof(struct pram_acl_entry_short);
-+ } else {
-+ if (s % sizeof(struct pram_acl_entry))
-+ return -1;
-+ return s / sizeof(struct pram_acl_entry) + 4;
-+ }
-+}
-+
-+#ifdef CONFIG_PRAMFS_POSIX_ACL
-+
-+/* acl.c */
-+extern int pram_check_acl(struct inode *, int, unsigned int);
-+extern int pram_acl_chmod(struct inode *);
-+extern int pram_init_acl(struct inode *, struct inode *);
-+
-+#else
-+#include <linux/sched.h>
-+#define pram_check_acl NULL
-+#define pram_get_acl NULL
-+#define pram_set_acl NULL
-+
-+static inline int pram_acl_chmod(struct inode *inode)
-+{
-+ return 0;
-+}
-+
-+static inline int pram_init_acl(struct inode *inode, struct inode *dir)
-+{
-+ return 0;
-+}
-+#endif
+++ /dev/null
-From marco.stornelli@gmail.com Wed May 16 08:53:27 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Wed, 16 May 2012 17:46:49 +0200
-Subject: pramfs: extended attributes support
-To: gregkh@linuxfoundation.org
-Cc: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FB3CBE9.9060404@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-Extended attributes operations.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
----
----
- fs/pramfs/xattr.c | 1118 +++++++++++++++++++++++++++++++++++++++++++++
- fs/pramfs/xattr.h | 134 +++++
- fs/pramfs/xattr_security.c | 79 +++
- fs/pramfs/xattr_trusted.c | 65 ++
- fs/pramfs/xattr_user.c | 69 ++
- 5 files changed, 1465 insertions(+)
-
---- /dev/null
-+++ b/fs/pramfs/xattr.c
-@@ -0,0 +1,1118 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Extended attributes operations.
-+ *
-+ * Copyright 2010-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ *
-+ * based on fs/ext2/xattr.c with the following copyright:
-+ *
-+ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
-+ * Extended attributes for symlinks and special files added per
-+ * suggestion of Luka Renko <luka.renko@hermes.si>.
-+ * xattr consolidation Copyright (c) 2004 James Morris <jmorris@redhat.com>,
-+ * Red Hat Inc.
-+ *
-+ * 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.
-+ */
-+
-+/*
-+ * Extended attributes are stored in blocks allocated outside of
-+ * any inode. The i_xattr field is then made to point to this allocated
-+ * block. If all extended attributes of an inode are identical, these
-+ * inodes may share the same extended attribute block. Such situations
-+ * are automatically detected by keeping a cache of recent attribute block
-+ * numbers and hashes over the block's contents in memory.
-+ *
-+ *
-+ * Extended attribute block layout:
-+ *
-+ * +------------------+
-+ * | header |
-+ * | entry 1 | |
-+ * | entry 2 | | growing downwards
-+ * | entry 3 | v
-+ * | four null bytes |
-+ * | . . . |
-+ * | value 1 | ^
-+ * | value 3 | | growing upwards
-+ * | value 2 | |
-+ * +------------------+
-+ *
-+ * The block header is followed by multiple entry descriptors. These entry
-+ * descriptors are variable in size, and aligned to PRAM_XATTR_PAD
-+ * byte boundaries. The entry descriptors are sorted by attribute name,
-+ * so that two extended attribute blocks can be compared efficiently.
-+ *
-+ * Attribute values are aligned to the end of the block, stored in
-+ * no specific order. They are also padded to PRAM_XATTR_PAD byte
-+ * boundaries. No additional gaps are left between them.
-+ *
-+ * Locking strategy
-+ * ----------------
-+ * pi->i_xattr is protected by PRAM_I(inode)->xattr_sem.
-+ * EA blocks are only changed if they are exclusive to an inode, so
-+ * holding xattr_sem also means that nothing but the EA block's reference
-+ * count will change. Multiple writers to an EA block are synchronized
-+ * by the mutex in each block descriptor. Block descriptors are kept in a
-+ * red black tree and the key is the absolute block number.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/mbcache.h>
-+#include <linux/rwsem.h>
-+#include <linux/security.h>
-+#include "pram.h"
-+#include "xattr.h"
-+#include "acl.h"
-+#include "desctree.h"
-+
-+#define HDR(bp) ((struct pram_xattr_header *)(bp))
-+#define ENTRY(ptr) ((struct pram_xattr_entry *)(ptr))
-+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
-+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
-+#define GET_DESC(sbi, blocknr) \
-+ lookup_xblock_desc(sbi, blocknr, pram_xblock_desc_cache, 1)
-+#define LOOKUP_DESC(sbi, blocknr) lookup_xblock_desc(sbi, blocknr, NULL, 0)
-+
-+#ifdef PRAM_XATTR_DEBUG
-+# define ea_idebug(inode, f...) do { \
-+ printk(KERN_DEBUG "inode %ld: ", inode->i_ino); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+# define ea_bdebug(blocknr, f...) do { \
-+ printk(KERN_DEBUG "block %lu: ", blocknr); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+#else
-+# define ea_idebug(f...)
-+# define ea_bdebug(f...)
-+#endif
-+
-+static int pram_xattr_set2(struct inode *, char *, struct pram_xblock_desc *,
-+ struct pram_xattr_header *);
-+
-+static int pram_xattr_cache_insert(struct super_block *sb,
-+ unsigned long blocknr, u32 xhash);
-+static struct pram_xblock_desc *pram_xattr_cache_find(struct inode *,
-+ struct pram_xattr_header *);
-+static void pram_xattr_rehash(struct pram_xattr_header *,
-+ struct pram_xattr_entry *);
-+
-+static struct mb_cache *pram_xattr_cache;
-+static struct kmem_cache *pram_xblock_desc_cache;
-+
-+static const struct xattr_handler *pram_xattr_handler_map[] = {
-+ [PRAM_XATTR_INDEX_USER] = &pram_xattr_user_handler,
-+#ifdef CONFIG_PRAMFS_POSIX_ACL
-+ [PRAM_XATTR_INDEX_POSIX_ACL_ACCESS] = &pram_xattr_acl_access_handler,
-+ [PRAM_XATTR_INDEX_POSIX_ACL_DEFAULT] = &pram_xattr_acl_default_handler,
-+#endif
-+ [PRAM_XATTR_INDEX_TRUSTED] = &pram_xattr_trusted_handler,
-+#ifdef CONFIG_PRAMFS_SECURITY
-+ [PRAM_XATTR_INDEX_SECURITY] = &pram_xattr_security_handler,
-+#endif
-+};
-+
-+const struct xattr_handler *pram_xattr_handlers[] = {
-+ &pram_xattr_user_handler,
-+ &pram_xattr_trusted_handler,
-+#ifdef CONFIG_PRAMFS_POSIX_ACL
-+ &pram_xattr_acl_access_handler,
-+ &pram_xattr_acl_default_handler,
-+#endif
-+#ifdef CONFIG_PRAMFS_SECURITY
-+ &pram_xattr_security_handler,
-+#endif
-+ NULL
-+};
-+
-+static void desc_put(struct super_block *sb, struct pram_xblock_desc *desc)
-+{
-+ struct pram_sb_info *sbi = PRAM_SB(sb);
-+ if (!put_xblock_desc(sbi, desc)) {
-+ /* Ok we can free the block and its descriptor */
-+ pram_dbg("freeing block %lu and its descriptor", desc->blocknr);
-+ pram_free_block(sb, desc->blocknr);
-+ kmem_cache_free(pram_xblock_desc_cache, desc);
-+ }
-+}
-+
-+static inline const struct xattr_handler *pram_xattr_handler(int name_index)
-+{
-+ const struct xattr_handler *handler = NULL;
-+
-+ if (name_index > 0 && name_index < ARRAY_SIZE(pram_xattr_handler_map))
-+ handler = pram_xattr_handler_map[name_index];
-+ return handler;
-+}
-+
-+/*
-+ * pram_xattr_get()
-+ *
-+ * Copy an extended attribute into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int pram_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t buffer_size)
-+{
-+ char *bp = NULL;
-+ struct pram_xattr_entry *entry;
-+ struct pram_xblock_desc *desc;
-+ struct pram_inode *pi;
-+ size_t name_len, size;
-+ char *end;
-+ int error = 0;
-+ unsigned long blocknr;
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_sb_info *sbi = PRAM_SB(sb);
-+
-+ ea_idebug(inode, "name=%d<%s>, buffer=%p, buffer_size=%ld",
-+ name_index, name, buffer, (long)buffer_size);
-+
-+ pi = pram_get_inode(sb, inode->i_ino);
-+ if (!pi)
-+ return -EINVAL;
-+ if (name == NULL)
-+ return -EINVAL;
-+ name_len = strlen(name);
-+ if (name_len > 255)
-+ return -ERANGE;
-+ down_read(&PRAM_I(inode)->xattr_sem);
-+ error = -ENODATA;
-+ if (!pi->i_xattr)
-+ goto cleanup;
-+ ea_idebug(inode, "reading block %llu", be64_to_cpu(pi->i_xattr));
-+ bp = pram_get_block(sb, be64_to_cpu(pi->i_xattr));
-+ error = -EIO;
-+ if (!bp)
-+ goto cleanup;
-+ end = bp + sb->s_blocksize;
-+ blocknr = pram_get_blocknr(sb, be64_to_cpu(pi->i_xattr));
-+ ea_bdebug(blocknr, "refcount=%d", be32_to_cpu(HDR(bp)->h_refcount));
-+ if (HDR(bp)->h_magic != cpu_to_be32(PRAM_XATTR_MAGIC)) {
-+bad_block: pram_err(sb, "inode %ld: bad block %llu", inode->i_ino,
-+ be64_to_cpu(pi->i_xattr));
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* find named attribute */
-+ entry = FIRST_ENTRY(bp);
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct pram_xattr_entry *next =
-+ PRAM_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (name_index == entry->e_name_index &&
-+ name_len == entry->e_name_len &&
-+ memcmp(name, entry->e_name, name_len) == 0)
-+ goto found;
-+ entry = next;
-+ }
-+
-+ desc = GET_DESC(sbi, blocknr);
-+ if (IS_ERR(desc)) {
-+ error = -ENOMEM;
-+ goto cleanup;
-+ }
-+ desc_put(sb, desc);
-+ if (pram_xattr_cache_insert(sb, blocknr,
-+ be32_to_cpu(HDR(bp)->h_hash)))
-+ ea_idebug(inode, "cache insert failed");
-+ error = -ENODATA;
-+ goto cleanup;
-+found:
-+ /* check the buffer size */
-+ if (entry->e_value_block != 0)
-+ goto bad_block;
-+ size = be32_to_cpu(entry->e_value_size);
-+ if (size > inode->i_sb->s_blocksize ||
-+ be16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
-+ goto bad_block;
-+
-+ desc = GET_DESC(sbi, blocknr);
-+ if (IS_ERR(desc)) {
-+ error = -ENOMEM;
-+ goto cleanup;
-+ }
-+ desc_put(sb, desc);
-+ if (pram_xattr_cache_insert(sb, blocknr,
-+ be32_to_cpu(HDR(bp)->h_hash)))
-+ ea_idebug(inode, "cache insert failed");
-+ if (buffer) {
-+ error = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ /* return value of attribute */
-+ memcpy(buffer, bp + be16_to_cpu(entry->e_value_offs),
-+ size);
-+ }
-+ error = size;
-+
-+cleanup:
-+ up_read(&PRAM_I(inode)->xattr_sem);
-+
-+ return error;
-+}
-+
-+/*
-+ * pram_xattr_list()
-+ *
-+ * Copy a list of attribute names into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+static int pram_xattr_list(struct dentry *dentry, char *buffer,
-+ size_t buffer_size)
-+{
-+ struct inode *inode = dentry->d_inode;
-+ char *bp = NULL;
-+ struct pram_xattr_entry *entry;
-+ struct pram_xblock_desc *desc;
-+ struct pram_inode *pi;
-+ char *end;
-+ size_t rest = buffer_size;
-+ int error = 0;
-+ unsigned long blocknr;
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_sb_info *sbi = PRAM_SB(sb);
-+
-+ ea_idebug(inode, "buffer=%p, buffer_size=%ld",
-+ buffer, (long)buffer_size);
-+
-+ pi = pram_get_inode(sb, inode->i_ino);
-+ if (!pi)
-+ return error;
-+ down_read(&PRAM_I(inode)->xattr_sem);
-+ error = 0;
-+ if (!pi->i_xattr)
-+ goto cleanup;
-+ ea_idebug(inode, "reading block %llu", be64_to_cpu(pi->i_xattr));
-+ bp = pram_get_block(sb, be64_to_cpu(pi->i_xattr));
-+ blocknr = pram_get_blocknr(sb, be64_to_cpu(pi->i_xattr));
-+ error = -EIO;
-+ if (!bp)
-+ goto cleanup;
-+ ea_bdebug(blocknr, "refcount=%d", be32_to_cpu(HDR(bp)->h_refcount));
-+ end = bp + sb->s_blocksize;
-+ if (HDR(bp)->h_magic != cpu_to_be32(PRAM_XATTR_MAGIC)) {
-+bad_block: pram_err(sb, "inode %ld: bad block %llu", inode->i_ino,
-+ be64_to_cpu(pi->i_xattr));
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+
-+ /* check the on-disk data structure */
-+ entry = FIRST_ENTRY(bp);
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct pram_xattr_entry *next = PRAM_XATTR_NEXT(entry);
-+
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ entry = next;
-+ }
-+
-+ desc = GET_DESC(sbi, blocknr);
-+ if (IS_ERR(desc)) {
-+ error = -ENOMEM;
-+ goto cleanup;
-+ }
-+ desc_put(sb, desc);
-+ if (pram_xattr_cache_insert(sb, blocknr,
-+ be32_to_cpu(HDR(bp)->h_hash)))
-+ ea_idebug(inode, "cache insert failed");
-+
-+ /* list the attribute names */
-+ for (entry = FIRST_ENTRY(bp); !IS_LAST_ENTRY(entry);
-+ entry = PRAM_XATTR_NEXT(entry)) {
-+ const struct xattr_handler *handler =
-+ pram_xattr_handler(entry->e_name_index);
-+
-+ if (handler) {
-+ size_t size = handler->list(dentry, buffer, rest,
-+ entry->e_name,
-+ entry->e_name_len,
-+ handler->flags);
-+ if (buffer) {
-+ if (size > rest) {
-+ error = -ERANGE;
-+ goto cleanup;
-+ }
-+ buffer += size;
-+ }
-+ rest -= size;
-+ }
-+ }
-+ error = buffer_size - rest; /* total size */
-+
-+cleanup:
-+ up_read(&PRAM_I(inode)->xattr_sem);
-+
-+ return error;
-+}
-+
-+/*
-+ * Inode operation listxattr()
-+ *
-+ * dentry->d_inode->i_mutex: don't care
-+ */
-+ssize_t pram_listxattr(struct dentry *dentry, char *buffer, size_t size)
-+{
-+ return pram_xattr_list(dentry, buffer, size);
-+}
-+
-+/*
-+ * pram_xattr_set()
-+ *
-+ * Create, replace or remove an extended attribute for this inode. Value
-+ * is NULL to remove an existing extended attribute, and non-NULL to
-+ * either replace an existing extended attribute, or create a new extended
-+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE
-+ * specify that an extended attribute must exist and must not exist
-+ * previous to the call, respectively.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+int pram_xattr_set(struct inode *inode, int name_index, const char *name,
-+ const void *value, size_t value_len, int flags)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_sb_info *sbi = PRAM_SB(sb);
-+ struct pram_xattr_header *header = NULL;
-+ struct pram_xattr_entry *here, *last;
-+ struct pram_inode *pi;
-+ struct pram_xblock_desc *desc = NULL;
-+ size_t name_len, free, min_offs = sb->s_blocksize;
-+ int not_found = 1, error;
-+ char *end;
-+ char *bp = NULL;
-+ unsigned long blocknr = 0;
-+
-+ /*
-+ * header -- Points either into bp, or to a temporarily
-+ * allocated buffer.
-+ * here -- The named entry found, or the place for inserting, within
-+ * the block pointed to by header.
-+ * last -- Points right after the last named entry within the block
-+ * pointed to by header.
-+ * min_offs -- The offset of the first value (values are aligned
-+ * towards the end of the block).
-+ * end -- Points right after the block pointed to by header.
-+ */
-+
-+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
-+ name_index, name, value, (long)value_len);
-+
-+ if (value == NULL)
-+ value_len = 0;
-+ if (name == NULL)
-+ return -EINVAL;
-+ name_len = strlen(name);
-+ if (name_len > 255 || value_len > sb->s_blocksize)
-+ return -ERANGE;
-+ pi = pram_get_inode(sb, inode->i_ino);
-+ if (!pi)
-+ return -EINVAL;
-+ down_write(&PRAM_I(inode)->xattr_sem);
-+ if (pi->i_xattr) {
-+ /* The inode already has an extended attribute block. */
-+ bp = pram_get_block(sb, be64_to_cpu(pi->i_xattr));
-+ error = -EIO;
-+ if (!bp)
-+ goto cleanup;
-+ blocknr = pram_get_blocknr(sb, be64_to_cpu(pi->i_xattr));
-+ ea_bdebug(blocknr, "refcount=%d",
-+ be32_to_cpu(HDR(bp)->h_refcount));
-+ header = HDR(bp);
-+ end = bp + sb->s_blocksize;
-+ if (header->h_magic != cpu_to_be32(PRAM_XATTR_MAGIC)) {
-+bad_block:
-+ pram_err(sb, "inode %ld: bad block %llu", inode->i_ino,
-+ be64_to_cpu(pi->i_xattr));
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* Find the named attribute. */
-+ here = FIRST_ENTRY(bp);
-+ while (!IS_LAST_ENTRY(here)) {
-+ struct pram_xattr_entry *next = PRAM_XATTR_NEXT(here);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!here->e_value_block && here->e_value_size) {
-+ size_t offs = be16_to_cpu(here->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ not_found = name_index - here->e_name_index;
-+ if (!not_found)
-+ not_found = name_len - here->e_name_len;
-+ if (!not_found)
-+ not_found = memcmp(name, here->e_name,
-+ name_len);
-+ if (not_found <= 0)
-+ break;
-+ here = next;
-+ }
-+ last = here;
-+ /* We still need to compute min_offs and last. */
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct pram_xattr_entry *next = PRAM_XATTR_NEXT(last);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!last->e_value_block && last->e_value_size) {
-+ size_t offs = be16_to_cpu(last->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ last = next;
-+ }
-+
-+ /* Check whether we have enough space left. */
-+ free = min_offs - ((char *)last - (char *)header) -
-+ sizeof(__u32);
-+ } else {
-+ /* We will use a new extended attribute block. */
-+ free = sb->s_blocksize -
-+ sizeof(struct pram_xattr_header) - sizeof(__u32);
-+ here = last = NULL; /* avoid gcc uninitialized warning. */
-+ }
-+
-+ if (not_found) {
-+ /* Request to remove a nonexistent attribute? */
-+ error = -ENODATA;
-+ if (flags & XATTR_REPLACE)
-+ goto cleanup;
-+ error = 0;
-+ if (value == NULL)
-+ goto cleanup;
-+ } else {
-+ /* Request to create an existing attribute? */
-+ error = -EEXIST;
-+ if (flags & XATTR_CREATE)
-+ goto cleanup;
-+ if (!here->e_value_block && here->e_value_size) {
-+ size_t size = be32_to_cpu(here->e_value_size);
-+
-+ if (be16_to_cpu(here->e_value_offs) + size >
-+ sb->s_blocksize || size > sb->s_blocksize)
-+ goto bad_block;
-+ free += PRAM_XATTR_SIZE(size);
-+ }
-+ free += PRAM_XATTR_LEN(name_len);
-+ }
-+ error = -ENOSPC;
-+ if (free < PRAM_XATTR_LEN(name_len) + PRAM_XATTR_SIZE(value_len))
-+ goto cleanup;
-+
-+ /* Here we know that we can set the new attribute. */
-+
-+ if (header) {
-+ struct mb_cache_entry *ce;
-+
-+ desc = GET_DESC(sbi, blocknr);
-+ if (IS_ERR(desc)) {
-+ error = -ENOMEM;
-+ goto cleanup;
-+ }
-+
-+ /* assert(header == HDR(bp)); */
-+ ce = mb_cache_entry_get(pram_xattr_cache,
-+ (struct block_device *)sbi,
-+ blocknr);
-+ mutex_lock(&desc->lock);
-+ pram_memunlock_block(sb, bp);
-+ if (header->h_refcount == cpu_to_be32(1)) {
-+ ea_bdebug(blocknr, "modifying in-place");
-+ if (ce)
-+ mb_cache_entry_free(ce);
-+ /* keep it locked while modifying it. */
-+ } else {
-+ int offset;
-+
-+ if (ce)
-+ mb_cache_entry_release(ce);
-+ pram_memlock_block(sb, bp);
-+ mutex_unlock(&desc->lock);
-+ ea_bdebug(desc->blocknr, "cloning");
-+ header = kmalloc(inode->i_sb->s_blocksize, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ memcpy(header, HDR(bp), inode->i_sb->s_blocksize);
-+ header->h_refcount = cpu_to_be32(1);
-+
-+ offset = (char *)here - bp;
-+ here = ENTRY((char *)header + offset);
-+ offset = (char *)last - bp;
-+ last = ENTRY((char *)header + offset);
-+ }
-+ } else {
-+ /* Allocate a buffer where we construct the new block. */
-+ header = kzalloc(sb->s_blocksize, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ end = (char *)header + sb->s_blocksize;
-+ header->h_magic = cpu_to_be32(PRAM_XATTR_MAGIC);
-+ header->h_refcount = cpu_to_be32(1);
-+ last = here = ENTRY(header+1);
-+ }
-+
-+ /* Iff we are modifying the block in-place, the block is locked here. */
-+
-+ if (not_found) {
-+ /* Insert the new name. */
-+ size_t size = PRAM_XATTR_LEN(name_len);
-+ size_t rest = (char *)last - (char *)here;
-+ memmove((char *)here + size, here, rest);
-+ memset(here, 0, size);
-+ here->e_name_index = name_index;
-+ here->e_name_len = name_len;
-+ memcpy(here->e_name, name, name_len);
-+ } else {
-+ if (!here->e_value_block && here->e_value_size) {
-+ char *first_val = (char *)header + min_offs;
-+ size_t offs = be16_to_cpu(here->e_value_offs);
-+ char *val = (char *)header + offs;
-+ size_t size = PRAM_XATTR_SIZE(
-+ be32_to_cpu(here->e_value_size));
-+
-+ if (size == PRAM_XATTR_SIZE(value_len)) {
-+ /* The old and the new value have the same
-+ size. Just replace. */
-+ here->e_value_size = cpu_to_be32(value_len);
-+ memset(val + size - PRAM_XATTR_PAD, 0,
-+ PRAM_XATTR_PAD); /* Clear pad bytes. */
-+ memcpy(val, value, value_len);
-+ goto skip_replace;
-+ }
-+
-+ /* Remove the old value. */
-+ memmove(first_val + size, first_val, val - first_val);
-+ memset(first_val, 0, size);
-+ here->e_value_offs = 0;
-+ min_offs += size;
-+
-+ /* Adjust all value offsets. */
-+ last = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(last)) {
-+ size_t o = be16_to_cpu(last->e_value_offs);
-+ if (!last->e_value_block && o < offs)
-+ last->e_value_offs =
-+ cpu_to_be16(o + size);
-+ last = PRAM_XATTR_NEXT(last);
-+ }
-+ }
-+ if (value == NULL) {
-+ /* Remove the old name. */
-+ size_t size = PRAM_XATTR_LEN(name_len);
-+ last = ENTRY((char *)last - size);
-+ memmove(here, (char *)here + size,
-+ (char *)last - (char *)here);
-+ memset(last, 0, size);
-+ }
-+ }
-+
-+ if (value != NULL) {
-+ /* Insert the new value. */
-+ here->e_value_size = cpu_to_be32(value_len);
-+ if (value_len) {
-+ size_t size = PRAM_XATTR_SIZE(value_len);
-+ char *val = (char *)header + min_offs - size;
-+ here->e_value_offs =
-+ cpu_to_be16((char *)val - (char *)header);
-+ memset(val + size - PRAM_XATTR_PAD, 0,
-+ PRAM_XATTR_PAD); /* Clear the pad bytes. */
-+ memcpy(val, value, value_len);
-+ }
-+ }
-+
-+skip_replace:
-+ if (IS_LAST_ENTRY(ENTRY(header+1))) {
-+ /* This block is now empty. */
-+ if (bp && header == HDR(bp)) {
-+ /* we were modifying in-place. */
-+ pram_memlock_block(sb, bp);
-+ mutex_unlock(&desc->lock);
-+ }
-+ error = pram_xattr_set2(inode, bp, desc, NULL);
-+ } else {
-+ pram_xattr_rehash(header, here);
-+ if (bp && header == HDR(bp)) {
-+ /* we were modifying in-place. */
-+ pram_memlock_block(sb, bp);
-+ mutex_unlock(&desc->lock);
-+ }
-+ error = pram_xattr_set2(inode, bp, desc, header);
-+ }
-+
-+cleanup:
-+ desc_put(sb, desc);
-+ if (!(bp && header == HDR(bp)))
-+ kfree(header);
-+ up_write(&PRAM_I(inode)->xattr_sem);
-+
-+ return error;
-+}
-+
-+/*
-+ * Second half of pram_xattr_set(): Update the file system.
-+ */
-+static int pram_xattr_set2(struct inode *inode, char *old_bp,
-+ struct pram_xblock_desc *old_desc,
-+ struct pram_xattr_header *header)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_sb_info *sbi = PRAM_SB(sb);
-+ struct pram_xblock_desc *new_desc = NULL;
-+ unsigned long blocknr;
-+ struct pram_inode *pi;
-+ int error;
-+ char *new_bp = NULL;
-+
-+ if (header) {
-+ new_desc = pram_xattr_cache_find(inode, header);
-+ if (new_desc) {
-+ new_bp = pram_get_block(sb,
-+ pram_get_block_off(sb, new_desc->blocknr));
-+ /* We found an identical block in the cache. */
-+ if (new_bp == old_bp) {
-+ ea_bdebug(new_desc->blocknr,
-+ "keeping this block");
-+ } else {
-+ /* The old block is released after updating
-+ the inode. */
-+ ea_bdebug(new_desc->blocknr, "reusing block");
-+ pram_memunlock_block(sb, new_bp);
-+ be32_add_cpu(&HDR(new_bp)->h_refcount, 1);
-+ pram_memlock_block(sb, new_bp);
-+ ea_bdebug(new_desc->blocknr, "refcount now=%d",
-+ be32_to_cpu(HDR(new_bp)->h_refcount));
-+ }
-+ blocknr = new_desc->blocknr;
-+ mutex_unlock(&new_desc->lock);
-+ desc_put(sb, new_desc);
-+ } else if (old_bp && header == HDR(old_bp)) {
-+ /* Keep this block. No need to lock the block as we
-+ don't need to change the reference count. */
-+ new_bp = old_bp;
-+ pram_xattr_cache_insert(sb, old_desc->blocknr,
-+ HDR(new_bp)->h_hash);
-+ blocknr = old_desc->blocknr;
-+ } else {
-+ /* We need to allocate a new block */
-+ struct pram_xblock_desc *new_desc;
-+
-+ error = pram_new_block(sb, &blocknr, 1);
-+ if (error)
-+ goto out;
-+ ea_idebug(inode, "creating block %lu", blocknr);
-+ new_desc = kmem_cache_alloc(pram_xblock_desc_cache,
-+ GFP_KERNEL);
-+ if (!new_desc) {
-+ pram_free_block(sb, blocknr);
-+ error = -EIO;
-+ goto out;
-+ }
-+ xblock_desc_init_always(new_desc);
-+ new_desc->blocknr = blocknr;
-+ new_bp = pram_get_block(sb,
-+ pram_get_block_off(sb, blocknr));
-+ if (!new_bp) {
-+ pram_free_block(sb, blocknr);
-+ kmem_cache_free(pram_xblock_desc_cache,
-+ new_desc);
-+ error = -EIO;
-+ goto out;
-+ }
-+ pram_memunlock_block(sb, new_bp);
-+ memcpy(new_bp, header, sb->s_blocksize);
-+ pram_memlock_block(sb, new_bp);
-+ insert_xblock_desc(sbi, new_desc);
-+ pram_xattr_cache_insert(sb, new_desc->blocknr,
-+ HDR(new_bp)->h_hash);
-+ }
-+ }
-+
-+ /* Update the inode. */
-+ pi = pram_get_inode(sb, inode->i_ino);
-+ pram_memunlock_inode(sb, pi);
-+ pi->i_xattr = new_bp ? be64_to_cpu(pram_get_block_off(sb, blocknr)) : 0;
-+ inode->i_ctime = CURRENT_TIME_SEC;
-+ pi->i_ctime = cpu_to_be32(inode->i_ctime.tv_sec);
-+ pram_memlock_inode(sb, pi);
-+
-+ error = 0;
-+ if (old_bp && old_bp != new_bp) {
-+ struct mb_cache_entry *ce;
-+
-+ /* Here old_desc MUST be valid or we have a bug */
-+ BUG_ON(!old_desc);
-+
-+ /*
-+ * If there was an old block and we are no longer using it,
-+ * release the old block.
-+ */
-+ ce = mb_cache_entry_get(pram_xattr_cache,
-+ (struct block_device *)sbi,
-+ old_desc->blocknr);
-+ mutex_lock(&old_desc->lock);
-+ if (HDR(old_bp)->h_refcount == cpu_to_be32(1)) {
-+ /* Free the old block. */
-+ if (ce)
-+ mb_cache_entry_free(ce);
-+ ea_bdebug(old_desc->blocknr, "freeing");
-+ mutex_unlock(&old_desc->lock);
-+ /* Caller will call desc_put later */
-+ mark_free_desc(old_desc);
-+ } else {
-+ /* Decrement the refcount only. */
-+ pram_memunlock_block(sb, old_bp);
-+ be32_add_cpu(&HDR(old_bp)->h_refcount, -1);
-+ pram_memlock_block(sb, old_bp);
-+ if (ce)
-+ mb_cache_entry_release(ce);
-+ ea_bdebug(old_desc->blocknr, "refcount now=%d",
-+ be32_to_cpu(HDR(old_bp)->h_refcount));
-+ mutex_unlock(&old_desc->lock);
-+ }
-+ }
-+
-+out:
-+ return error;
-+}
-+
-+/*
-+ * pram_xattr_delete_inode()
-+ *
-+ * Free extended attribute resources associated with this inode. This
-+ * is called immediately before an inode is freed.
-+ */
-+void pram_xattr_delete_inode(struct inode *inode)
-+{
-+ char *bp = NULL;
-+ struct mb_cache_entry *ce;
-+ struct pram_inode *pi;
-+ struct pram_xblock_desc *desc;
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_sb_info *sbi = PRAM_SB(sb);
-+ unsigned long blocknr;
-+
-+ pi = pram_get_inode(sb, inode->i_ino);
-+ if (!pi)
-+ goto cleanup;
-+ down_write(&PRAM_I(inode)->xattr_sem);
-+ if (!pi->i_xattr)
-+ goto cleanup;
-+ bp = pram_get_block(sb, be64_to_cpu(pi->i_xattr));
-+ if (!bp) {
-+ pram_err(sb, "inode %ld: block %llu read error", inode->i_ino,
-+ be64_to_cpu(pi->i_xattr));
-+ goto cleanup;
-+ }
-+ blocknr = pram_get_blocknr(sb, be64_to_cpu(pi->i_xattr));
-+ if (HDR(bp)->h_magic != cpu_to_be32(PRAM_XATTR_MAGIC)) {
-+ pram_err(sb, "inode %ld: bad block %llu", inode->i_ino,
-+ be64_to_cpu(pi->i_xattr));
-+ goto cleanup;
-+ }
-+ ce = mb_cache_entry_get(pram_xattr_cache,
-+ (struct block_device *)sbi, blocknr);
-+ desc = GET_DESC(sbi, blocknr);
-+ if (IS_ERR(desc))
-+ goto cleanup;
-+ mutex_lock(&desc->lock);
-+ if (HDR(bp)->h_refcount == cpu_to_be32(1)) {
-+ if (ce)
-+ mb_cache_entry_free(ce);
-+ mark_free_desc(desc);
-+ } else {
-+ be32_add_cpu(&HDR(bp)->h_refcount, -1);
-+ if (ce)
-+ mb_cache_entry_release(ce);
-+ ea_bdebug(blocknr, "refcount now=%d",
-+ be32_to_cpu(HDR(bp)->h_refcount));
-+ mutex_unlock(&desc->lock);
-+ }
-+ desc_put(sb, desc);
-+
-+cleanup:
-+ up_write(&PRAM_I(inode)->xattr_sem);
-+}
-+
-+/*
-+ * pram_xattr_put_super()
-+ *
-+ * This is called when a file system is unmounted.
-+ */
-+void pram_xattr_put_super(struct super_block *sb)
-+{
-+ struct pram_sb_info *sbi = PRAM_SB(sb);
-+ /*
-+ * NOTE: we haven't got any block device to use with mb. Mb code
-+ * doesn't use the pointer but it uses only the address as unique
-+ * key so it's safe to use a "general purpose" address. We use
-+ * super block info data as unique key. Maybe it'd be better to
-+ * change mb code in order to use a generic void pointer to a
-+ * generic id.
-+ */
-+ mb_cache_shrink((struct block_device *)sbi);
-+ erase_tree(sbi, pram_xblock_desc_cache);
-+ kmem_cache_shrink(pram_xblock_desc_cache);
-+}
-+
-+
-+/*
-+ * pram_xattr_cache_insert()
-+ *
-+ * Create a new entry in the extended attribute cache, and insert
-+ * it unless such an entry is already in the cache.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+static int pram_xattr_cache_insert(struct super_block *sb,
-+ unsigned long blocknr, u32 xhash)
-+{
-+ struct pram_sb_info *sbi = PRAM_SB(sb);
-+ __u32 hash = be32_to_cpu(xhash);
-+ struct mb_cache_entry *ce;
-+ int error;
-+
-+ ce = mb_cache_entry_alloc(pram_xattr_cache, GFP_NOFS);
-+ if (!ce)
-+ return -ENOMEM;
-+ error = mb_cache_entry_insert(ce, (struct block_device *)sbi, blocknr,
-+ hash);
-+ if (error) {
-+ mb_cache_entry_free(ce);
-+ if (error == -EBUSY) {
-+ ea_bdebug(blocknr, "already in cache");
-+ error = 0;
-+ }
-+ } else {
-+ ea_bdebug(blocknr, "inserting [%x]", (int)hash);
-+ mb_cache_entry_release(ce);
-+ }
-+ return error;
-+}
-+
-+/*
-+ * pram_xattr_cmp()
-+ *
-+ * Compare two extended attribute blocks for equality.
-+ *
-+ * Returns 0 if the blocks are equal, 1 if they differ, and
-+ * a negative error number on errors.
-+ */
-+static int pram_xattr_cmp(struct pram_xattr_header *header1,
-+ struct pram_xattr_header *header2)
-+{
-+ struct pram_xattr_entry *entry1, *entry2;
-+
-+ entry1 = ENTRY(header1+1);
-+ entry2 = ENTRY(header2+1);
-+ while (!IS_LAST_ENTRY(entry1)) {
-+ if (IS_LAST_ENTRY(entry2))
-+ return 1;
-+ if (entry1->e_hash != entry2->e_hash ||
-+ entry1->e_name_index != entry2->e_name_index ||
-+ entry1->e_name_len != entry2->e_name_len ||
-+ entry1->e_value_size != entry2->e_value_size ||
-+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
-+ return 1;
-+ if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
-+ return -EIO;
-+ if (memcmp((char *)header1 + be16_to_cpu(entry1->e_value_offs),
-+ (char *)header2 + be16_to_cpu(entry2->e_value_offs),
-+ be32_to_cpu(entry1->e_value_size)))
-+ return 1;
-+
-+ entry1 = PRAM_XATTR_NEXT(entry1);
-+ entry2 = PRAM_XATTR_NEXT(entry2);
-+ }
-+ if (!IS_LAST_ENTRY(entry2))
-+ return 1;
-+ return 0;
-+}
-+
-+/*
-+ * pram_xattr_cache_find()
-+ *
-+ * Find an identical extended attribute block.
-+ *
-+ * Returns a locked extended block descriptor for the block found, or
-+ * NULL if such a block was not found or an error occurred.
-+ * The block, however, is not memory unlocked.
-+ */
-+static struct pram_xblock_desc *pram_xattr_cache_find(struct inode *inode,
-+ struct pram_xattr_header *header)
-+{
-+ __u32 hash = be32_to_cpu(header->h_hash);
-+ struct mb_cache_entry *ce;
-+ struct pram_xblock_desc *desc;
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_sb_info *sbi = PRAM_SB(sb);
-+
-+ if (!header->h_hash)
-+ return NULL; /* never share */
-+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
-+again:
-+ ce = mb_cache_entry_find_first(pram_xattr_cache,
-+ (struct block_device *)sbi, hash);
-+ while (ce) {
-+ char *bp;
-+
-+ if (IS_ERR(ce)) {
-+ if (PTR_ERR(ce) == -EAGAIN)
-+ goto again;
-+ break;
-+ }
-+
-+ bp = pram_get_block(sb, pram_get_block_off(sb, (unsigned long)ce->e_block));
-+ if (!bp) {
-+ pram_err(sb, "inode %ld: block %ld read error",
-+ inode->i_ino, (unsigned long) ce->e_block);
-+ } else {
-+ desc = LOOKUP_DESC(sbi, ce->e_block);
-+ if (!desc) {
-+ mb_cache_entry_release(ce);
-+ return NULL;
-+ }
-+ mutex_lock(&desc->lock);
-+ if (be32_to_cpu(HDR(bp)->h_refcount) >
-+ PRAM_XATTR_REFCOUNT_MAX) {
-+ ea_idebug(inode, "block %ld refcount %d>%d",
-+ (unsigned long) ce->e_block,
-+ be32_to_cpu(HDR(bp)->h_refcount),
-+ PRAM_XATTR_REFCOUNT_MAX);
-+ } else if (!pram_xattr_cmp(header, HDR(bp))) {
-+ mb_cache_entry_release(ce);
-+ return desc;
-+ }
-+ mutex_unlock(&desc->lock);
-+ }
-+ ce = mb_cache_entry_find_next(ce,
-+ (struct block_device *)sbi,
-+ hash);
-+ }
-+ return NULL;
-+}
-+
-+#define NAME_HASH_SHIFT 5
-+#define VALUE_HASH_SHIFT 16
-+
-+/*
-+ * pram_xattr_hash_entry()
-+ *
-+ * Compute the hash of an extended attribute.
-+ */
-+static inline void pram_xattr_hash_entry(struct pram_xattr_header *header,
-+ struct pram_xattr_entry *entry)
-+{
-+ __u32 hash = 0;
-+ char *name = entry->e_name;
-+ int n;
-+
-+ for (n = 0; n < entry->e_name_len; n++) {
-+ hash = (hash << NAME_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
-+ *name++;
-+ }
-+
-+ if (entry->e_value_block == 0 && entry->e_value_size != 0) {
-+ __be32 *value = (__be32 *)((char *)header +
-+ be16_to_cpu(entry->e_value_offs));
-+ for (n = (be32_to_cpu(entry->e_value_size) +
-+ PRAM_XATTR_ROUND) >> PRAM_XATTR_PAD_BITS; n; n--) {
-+ hash = (hash << VALUE_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
-+ be32_to_cpu(*value++);
-+ }
-+ }
-+ entry->e_hash = cpu_to_be32(hash);
-+}
-+
-+#undef NAME_HASH_SHIFT
-+#undef VALUE_HASH_SHIFT
-+
-+#define BLOCK_HASH_SHIFT 16
-+
-+/*
-+ * pram_xattr_rehash()
-+ *
-+ * Re-compute the extended attribute hash value after an entry has changed.
-+ */
-+static void pram_xattr_rehash(struct pram_xattr_header *header,
-+ struct pram_xattr_entry *entry)
-+{
-+ struct pram_xattr_entry *here;
-+ __u32 hash = 0;
-+
-+ pram_xattr_hash_entry(header, entry);
-+ here = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(here)) {
-+ if (!here->e_hash) {
-+ /* Block is not shared if an entry's hash value == 0 */
-+ hash = 0;
-+ break;
-+ }
-+ hash = (hash << BLOCK_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
-+ be32_to_cpu(here->e_hash);
-+ here = PRAM_XATTR_NEXT(here);
-+ }
-+ header->h_hash = cpu_to_be32(hash);
-+}
-+
-+#undef BLOCK_HASH_SHIFT
-+
-+static void init_xblock_desc_once(void *foo)
-+{
-+ struct pram_xblock_desc *desc = (struct pram_xblock_desc *) foo;
-+
-+ xblock_desc_init_once(desc);
-+}
-+
-+int __init init_pram_xattr(void)
-+{
-+ int ret = 0;
-+ pram_xattr_cache = mb_cache_create("pram_xattr", 6);
-+ if (!pram_xattr_cache) {
-+ ret = -ENOMEM;
-+ goto fail1;
-+ }
-+
-+ pram_xblock_desc_cache = kmem_cache_create("pram_xblock_desc",
-+ sizeof(struct pram_xblock_desc),
-+ 0, (SLAB_RECLAIM_ACCOUNT|
-+ SLAB_MEM_SPREAD),
-+ init_xblock_desc_once);
-+ if (!pram_xblock_desc_cache) {
-+ ret = -ENOMEM;
-+ goto fail2;
-+ }
-+
-+ return 0;
-+fail2:
-+ mb_cache_destroy(pram_xattr_cache);
-+fail1:
-+ return ret;
-+}
-+
-+void exit_pram_xattr(void)
-+{
-+ mb_cache_destroy(pram_xattr_cache);
-+ kmem_cache_destroy(pram_xblock_desc_cache);
-+}
---- /dev/null
-+++ b/fs/pramfs/xattr.h
-@@ -0,0 +1,134 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Extended attributes for the pram filesystem.
-+ *
-+ * Copyright 2010-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ *
-+ * based on fs/ext2/xattr.h with the following copyright:
-+ *
-+ *(C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ *
-+ * 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 <linux/init.h>
-+#include <linux/xattr.h>
-+
-+/* Magic value in attribute blocks */
-+#define PRAM_XATTR_MAGIC 0x6d617270
-+
-+/* Maximum number of references to one attribute block */
-+#define PRAM_XATTR_REFCOUNT_MAX 1024
-+
-+/* Name indexes */
-+#define PRAM_XATTR_INDEX_USER 1
-+#define PRAM_XATTR_INDEX_POSIX_ACL_ACCESS 2
-+#define PRAM_XATTR_INDEX_POSIX_ACL_DEFAULT 3
-+#define PRAM_XATTR_INDEX_TRUSTED 4
-+#define PRAM_XATTR_INDEX_SECURITY 5
-+
-+struct pram_xattr_header {
-+ __be32 h_magic; /* magic number for identification */
-+ __be32 h_refcount; /* reference count */
-+ __be32 h_hash; /* hash value of all attributes */
-+ __u32 h_reserved[4]; /* zero right now */
-+};
-+
-+struct pram_xattr_entry {
-+ __u8 e_name_len; /* length of name */
-+ __u8 e_name_index; /* attribute name index */
-+ __be16 e_value_offs; /* offset in disk block of value */
-+ __be32 e_value_block; /* disk block attribute is stored on (n/i) */
-+ __be32 e_value_size; /* size of attribute value */
-+ __be32 e_hash; /* hash value of name and value */
-+ char e_name[0]; /* attribute name */
-+};
-+
-+#define PRAM_XATTR_PAD_BITS 2
-+#define PRAM_XATTR_PAD (1<<PRAM_XATTR_PAD_BITS)
-+#define PRAM_XATTR_ROUND (PRAM_XATTR_PAD-1)
-+#define PRAM_XATTR_LEN(name_len) \
-+ (((name_len) + PRAM_XATTR_ROUND + \
-+ sizeof(struct pram_xattr_entry)) & ~PRAM_XATTR_ROUND)
-+#define PRAM_XATTR_NEXT(entry) \
-+ ((struct pram_xattr_entry *)( \
-+ (char *)(entry) + PRAM_XATTR_LEN((entry)->e_name_len)))
-+#define PRAM_XATTR_SIZE(size) \
-+ (((size) + PRAM_XATTR_ROUND) & ~PRAM_XATTR_ROUND)
-+
-+#ifdef CONFIG_PRAMFS_XATTR
-+
-+extern const struct xattr_handler pram_xattr_user_handler;
-+extern const struct xattr_handler pram_xattr_trusted_handler;
-+extern const struct xattr_handler pram_xattr_acl_access_handler;
-+extern const struct xattr_handler pram_xattr_acl_default_handler;
-+extern const struct xattr_handler pram_xattr_security_handler;
-+
-+extern ssize_t pram_listxattr(struct dentry *, char *, size_t);
-+
-+extern int pram_xattr_get(struct inode *, int, const char *, void *, size_t);
-+extern int pram_xattr_set(struct inode *, int, const char *, const void *,
-+ size_t, int);
-+
-+extern void pram_xattr_delete_inode(struct inode *);
-+extern void pram_xattr_put_super(struct super_block *);
-+
-+extern int init_pram_xattr(void) __init;
-+extern void exit_pram_xattr(void);
-+
-+extern const struct xattr_handler *pram_xattr_handlers[];
-+
-+# else /* CONFIG_PRAMFS_XATTR */
-+
-+static inline int
-+pram_xattr_get(struct inode *inode, int name_index,
-+ const char *name, void *buffer, size_t size)
-+{
-+ return -EOPNOTSUPP;
-+}
-+
-+static inline int
-+pram_xattr_set(struct inode *inode, int name_index, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ return -EOPNOTSUPP;
-+}
-+
-+static inline void
-+pram_xattr_delete_inode(struct inode *inode)
-+{
-+}
-+
-+static inline void
-+pram_xattr_put_super(struct super_block *sb)
-+{
-+}
-+
-+static inline int
-+init_pram_xattr(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_pram_xattr(void)
-+{
-+}
-+
-+#define pram_xattr_handlers NULL
-+
-+# endif /* CONFIG_PRAMFS_XATTR */
-+
-+#ifdef CONFIG_PRAMFS_SECURITY
-+extern int pram_init_security(struct inode *inode, struct inode *dir,
-+ const struct qstr *qstr);
-+#else
-+static inline int pram_init_security(struct inode *inode, struct inode *dir,
-+ const struct qstr *qstr)
-+{
-+ return 0;
-+}
-+#endif
---- /dev/null
-+++ b/fs/pramfs/xattr_security.c
-@@ -0,0 +1,79 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Handler for storing security labels as extended attributes.
-+ *
-+ * Copyright 2010-2011 Marco Stornelli <marco.stornelli@gmail.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 <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/string.h>
-+#include <linux/fs.h>
-+#include <linux/pram_fs.h>
-+#include <linux/security.h>
-+#include "xattr.h"
-+
-+static size_t pram_xattr_security_list(struct dentry *dentry, char *list,
-+ size_t list_size, const char *name,
-+ size_t name_len, int type)
-+{
-+ const int prefix_len = XATTR_SECURITY_PREFIX_LEN;
-+ const size_t total_len = prefix_len + name_len + 1;
-+
-+ if (list && total_len <= list_size) {
-+ memcpy(list, XATTR_SECURITY_PREFIX, prefix_len);
-+ memcpy(list+prefix_len, name, name_len);
-+ list[prefix_len + name_len] = '\0';
-+ }
-+ return total_len;
-+}
-+
-+static int pram_xattr_security_get(struct dentry *dentry, const char *name,
-+ void *buffer, size_t size, int type)
-+{
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ return pram_xattr_get(dentry->d_inode, PRAM_XATTR_INDEX_SECURITY, name,
-+ buffer, size);
-+}
-+
-+static int pram_xattr_security_set(struct dentry *dentry, const char *name,
-+ const void *value, size_t size, int flags, int type)
-+{
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ return pram_xattr_set(dentry->d_inode, PRAM_XATTR_INDEX_SECURITY, name,
-+ value, size, flags);
-+}
-+
-+int pram_init_security(struct inode *inode, struct inode *dir,
-+ const struct qstr *qstr)
-+{
-+ int err;
-+ size_t len;
-+ void *value;
-+ char *name;
-+
-+ err = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
-+ if (err) {
-+ if (err == -EOPNOTSUPP)
-+ return 0;
-+ return err;
-+ }
-+ err = pram_xattr_set(inode, PRAM_XATTR_INDEX_SECURITY,
-+ name, value, len, 0);
-+ kfree(name);
-+ kfree(value);
-+ return err;
-+}
-+
-+const struct xattr_handler pram_xattr_security_handler = {
-+ .prefix = XATTR_SECURITY_PREFIX,
-+ .list = pram_xattr_security_list,
-+ .get = pram_xattr_security_get,
-+ .set = pram_xattr_security_set,
-+};
---- /dev/null
-+++ b/fs/pramfs/xattr_trusted.c
-@@ -0,0 +1,65 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Handler for trusted extended attributes.
-+ *
-+ * Copyright 2010-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ *
-+ * based on fs/ext2/xattr_trusted.c with the following copyright:
-+ *
-+ * Copyright (C) 2003 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ *
-+ * 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 <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/capability.h>
-+#include <linux/fs.h>
-+#include <linux/pram_fs.h>
-+#include "xattr.h"
-+
-+static size_t pram_xattr_trusted_list(struct dentry *dentry, char *list,
-+ size_t list_size, const char *name,
-+ size_t name_len, int type)
-+{
-+ const int prefix_len = XATTR_TRUSTED_PREFIX_LEN;
-+ const size_t total_len = prefix_len + name_len + 1;
-+
-+ if (!capable(CAP_SYS_ADMIN))
-+ return 0;
-+
-+ if (list && total_len <= list_size) {
-+ memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len);
-+ memcpy(list+prefix_len, name, name_len);
-+ list[prefix_len + name_len] = '\0';
-+ }
-+ return total_len;
-+}
-+
-+static int pram_xattr_trusted_get(struct dentry *dentry, const char *name,
-+ void *buffer, size_t size, int type)
-+{
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ return pram_xattr_get(dentry->d_inode, PRAM_XATTR_INDEX_TRUSTED, name,
-+ buffer, size);
-+}
-+
-+static int pram_xattr_trusted_set(struct dentry *dentry, const char *name,
-+ const void *value, size_t size, int flags, int type)
-+{
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ return pram_xattr_set(dentry->d_inode, PRAM_XATTR_INDEX_TRUSTED, name,
-+ value, size, flags);
-+}
-+
-+const struct xattr_handler pram_xattr_trusted_handler = {
-+ .prefix = XATTR_TRUSTED_PREFIX,
-+ .list = pram_xattr_trusted_list,
-+ .get = pram_xattr_trusted_get,
-+ .set = pram_xattr_trusted_set,
-+};
---- /dev/null
-+++ b/fs/pramfs/xattr_user.c
-@@ -0,0 +1,69 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Handler for extended user attributes.
-+ *
-+ * Copyright 2010-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ *
-+ * based on fs/ext2/xattr_user.c with the following copyright:
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ *
-+ * 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 <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include "pram.h"
-+#include "xattr.h"
-+
-+static size_t pram_xattr_user_list(struct dentry *dentry, char *list,
-+ size_t list_size, const char *name,
-+ size_t name_len, int type)
-+{
-+ const size_t prefix_len = XATTR_USER_PREFIX_LEN;
-+ const size_t total_len = prefix_len + name_len + 1;
-+
-+ if (!test_opt(dentry->d_sb, XATTR_USER))
-+ return 0;
-+
-+ if (list && total_len <= list_size) {
-+ memcpy(list, XATTR_USER_PREFIX, prefix_len);
-+ memcpy(list+prefix_len, name, name_len);
-+ list[prefix_len + name_len] = '\0';
-+ }
-+ return total_len;
-+}
-+
-+static int pram_xattr_user_get(struct dentry *dentry, const char *name,
-+ void *buffer, size_t size, int type)
-+{
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!test_opt(dentry->d_sb, XATTR_USER))
-+ return -EOPNOTSUPP;
-+ return pram_xattr_get(dentry->d_inode, PRAM_XATTR_INDEX_USER,
-+ name, buffer, size);
-+}
-+
-+static int pram_xattr_user_set(struct dentry *dentry, const char *name,
-+ const void *value, size_t size, int flags, int type)
-+{
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!test_opt(dentry->d_sb, XATTR_USER))
-+ return -EOPNOTSUPP;
-+
-+ return pram_xattr_set(dentry->d_inode, PRAM_XATTR_INDEX_USER,
-+ name, value, size, flags);
-+}
-+
-+const struct xattr_handler pram_xattr_user_handler = {
-+ .prefix = XATTR_USER_PREFIX,
-+ .list = pram_xattr_user_list,
-+ .get = pram_xattr_user_get,
-+ .set = pram_xattr_user_set,
-+};
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:18:39 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:12:02 +0200
-Subject: pramfs: extended attributes descriptors tree
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FAE99E2.9000206@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-Extended attributes block descriptors tree.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
-
----
- fs/pramfs/desctree.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++
- fs/pramfs/desctree.h | 44 ++++++++++++
- 2 files changed, 225 insertions(+)
-
---- /dev/null
-+++ b/fs/pramfs/desctree.c
-@@ -0,0 +1,181 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Extended attributes block descriptors tree.
-+ *
-+ * Copyright 2010-2011 Marco Stornelli <marco.stornelli@gmail.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 <linux/spinlock.h>
-+#include "desctree.h"
-+#include "pram.h"
-+
-+/* xblock_desc_init_always()
-+ *
-+ * These are initializations that need to be done on every
-+ * descriptor allocation as the fields are not initialised
-+ * by slab allocation.
-+ */
-+void xblock_desc_init_always(struct pram_xblock_desc *desc)
-+{
-+ atomic_set(&desc->refcount, 0);
-+ desc->blocknr = 0;
-+ desc->flags = 0;
-+}
-+
-+/* xblock_desc_init_once()
-+ *
-+ * These are initializations that only need to be done
-+ * once, because the fields are idempotent across use
-+ * of the descriptor, so let the slab aware of that.
-+ */
-+void xblock_desc_init_once(struct pram_xblock_desc *desc)
-+{
-+ mutex_init(&desc->lock);
-+}
-+
-+/* __insert_xblock_desc()
-+ *
-+ * Insert a new descriptor in the tree.
-+ */
-+static void __insert_xblock_desc(struct pram_sb_info *sbi,
-+ unsigned long blocknr, struct rb_node *node)
-+{
-+ struct rb_node **p = &(sbi->desc_tree.rb_node);
-+ struct rb_node *parent = NULL;
-+ struct pram_xblock_desc *desc;
-+
-+ while (*p) {
-+ parent = *p;
-+ desc = rb_entry(parent, struct pram_xblock_desc, node);
-+
-+ if (blocknr < desc->blocknr)
-+ p = &(*p)->rb_left;
-+ else if (blocknr > desc->blocknr)
-+ p = &(*p)->rb_right;
-+ else
-+ /* Oops...an other descriptor for the same block ? */
-+ BUG();
-+ }
-+
-+ rb_link_node(node, parent, p);
-+ rb_insert_color(node, &sbi->desc_tree);
-+}
-+
-+void insert_xblock_desc(struct pram_sb_info *sbi, struct pram_xblock_desc *desc)
-+{
-+ spin_lock(&sbi->desc_tree_lock);
-+ __insert_xblock_desc(sbi, desc->blocknr, &desc->node);
-+ spin_unlock(&sbi->desc_tree_lock);
-+};
-+
-+/* __lookup_xblock_desc()
-+ *
-+ * Search an extended attribute descriptor in the tree via the
-+ * block number. It returns the descriptor if it's found or
-+ * NULL. If not found it creates a new descriptor if create is not 0.
-+ */
-+static struct pram_xblock_desc *__lookup_xblock_desc(struct pram_sb_info *sbi,
-+ unsigned long blocknr,
-+ struct kmem_cache *cache,
-+ int create)
-+{
-+ struct rb_node *n = sbi->desc_tree.rb_node;
-+ struct pram_xblock_desc *desc = NULL;
-+
-+ while (n) {
-+ desc = rb_entry(n, struct pram_xblock_desc, node);
-+
-+ if (blocknr < desc->blocknr)
-+ n = n->rb_left;
-+ else if (blocknr > desc->blocknr)
-+ n = n->rb_right;
-+ else {
-+ atomic_inc(&desc->refcount);
-+ goto out;
-+ }
-+ }
-+
-+ /* not found */
-+ if (create) {
-+ desc = kmem_cache_alloc(cache, GFP_NOFS);
-+ if (!desc)
-+ return ERR_PTR(-ENOMEM);
-+ xblock_desc_init_always(desc);
-+ atomic_set(&desc->refcount, 1);
-+ desc->blocknr = blocknr;
-+ __insert_xblock_desc(sbi, desc->blocknr, &desc->node);
-+ }
-+out:
-+ return desc;
-+}
-+
-+struct pram_xblock_desc *lookup_xblock_desc(struct pram_sb_info *sbi,
-+ unsigned long blocknr,
-+ struct kmem_cache *cache,
-+ int create)
-+{
-+ struct pram_xblock_desc *desc = NULL;
-+
-+ spin_lock(&sbi->desc_tree_lock);
-+ desc = __lookup_xblock_desc(sbi, blocknr, cache, create);
-+ spin_unlock(&sbi->desc_tree_lock);
-+ return desc;
-+}
-+
-+/* put_xblock_desc()
-+ *
-+ * Decrement the reference count and if it reaches zero and the
-+ * desciptor has been marked to be free, then we free it.
-+ * It returns 0 if the descriptor has been deleted and 1 otherwise.
-+ */
-+int put_xblock_desc(struct pram_sb_info *sbi, struct pram_xblock_desc *desc)
-+{
-+ int ret = 1;
-+ if (!desc)
-+ return ret;
-+
-+ if (atomic_dec_and_lock(&desc->refcount, &sbi->desc_tree_lock)) {
-+ if (test_bit(FREEING, &desc->flags)) {
-+ rb_erase(&desc->node, &sbi->desc_tree);
-+ pram_dbg("erasing desc for block %lu\n", desc->blocknr);
-+ ret = 0;
-+ }
-+ spin_unlock(&sbi->desc_tree_lock);
-+ }
-+ return ret;
-+};
-+
-+/* mark_free_desc()
-+ *
-+ * Mark free a descriptor. The descriptor will be deleted later in the
-+ * put_xblock_desc().
-+ */
-+void mark_free_desc(struct pram_xblock_desc *desc)
-+{
-+ set_bit(FREEING, &desc->flags);
-+}
-+
-+/* erase_tree()
-+ *
-+ * Free all objects in the tree.
-+ */
-+void erase_tree(struct pram_sb_info *sbi, struct kmem_cache *cachep)
-+{
-+ struct rb_node *n;
-+ struct pram_xblock_desc *desc;
-+
-+ spin_lock(&sbi->desc_tree_lock);
-+ n = rb_first(&sbi->desc_tree);
-+ while (n) {
-+ desc = rb_entry(n, struct pram_xblock_desc, node);
-+ rb_erase(n, &sbi->desc_tree);
-+ kmem_cache_free(cachep, desc);
-+ n = rb_next(n);
-+ }
-+ spin_unlock(&sbi->desc_tree_lock);
-+}
---- /dev/null
-+++ b/fs/pramfs/desctree.h
-@@ -0,0 +1,44 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Extended attributes block descriptors tree.
-+ *
-+ * Copyright 2010-2011 Marco Stornelli <marco.stornelli@gmail.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 <linux/atomic.h>
-+#include <linux/slab.h>
-+#include "pram.h"
-+
-+struct pram_xblock_desc {
-+#define FREEING (1UL << 1)
-+ unsigned long flags; /* descriptor flags */
-+ atomic_t refcount; /* users count of this descriptor */
-+ unsigned long blocknr; /* absolute block number */
-+ struct mutex lock; /* block lock */
-+ struct rb_node node; /* node in the rb tree */
-+};
-+
-+extern struct pram_xblock_desc *lookup_xblock_desc(struct pram_sb_info *sbi,
-+ unsigned long blocknr,
-+ struct kmem_cache *, int);
-+extern void insert_xblock_desc(struct pram_sb_info *sbi,
-+ struct pram_xblock_desc *desc);
-+extern void mark_free_desc(struct pram_xblock_desc *desc);
-+extern int put_xblock_desc(struct pram_sb_info *sbi,
-+ struct pram_xblock_desc *desc);
-+extern void xblock_desc_init_always(struct pram_xblock_desc *desc);
-+extern void xblock_desc_init_once(struct pram_xblock_desc *desc);
-+extern void erase_tree(struct pram_sb_info *sbi,
-+ struct kmem_cache *);
-+
-+static inline void xblock_desc_init(struct pram_xblock_desc *desc)
-+{
-+ xblock_desc_init_always(desc);
-+ xblock_desc_init_once(desc);
-+};
-+
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:18:51 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:12:16 +0200
-Subject: pramfs: memory write protection
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FAE99F0.6020105@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-Memory write protection.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
-
----
- fs/pramfs/wprotect.c | 41 +++++++++++++
- fs/pramfs/wprotect.h | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 194 insertions(+)
-
---- /dev/null
-+++ b/fs/pramfs/wprotect.c
-@@ -0,0 +1,41 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Write protection for the filesystem pages.
-+ *
-+ * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ * Copyright 2003 Sony Corporation
-+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
-+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
-+ * 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 <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/io.h>
-+#include "pram.h"
-+
-+DEFINE_SPINLOCK(writeable_lock);
-+
-+void pram_writeable(void *vaddr, unsigned long size, int rw)
-+{
-+ int ret = 0;
-+ unsigned long nrpages = size >> PAGE_SHIFT;
-+ unsigned long addr = (unsigned long)vaddr;
-+
-+ /* Page aligned */
-+ addr &= PAGE_MASK;
-+
-+ if (size & (PAGE_SIZE - 1))
-+ nrpages++;
-+
-+ if (rw)
-+ ret = set_memory_rw(addr, nrpages);
-+ else
-+ ret = set_memory_ro(addr, nrpages);
-+
-+ BUG_ON(ret);
-+}
---- /dev/null
-+++ b/fs/pramfs/wprotect.h
-@@ -0,0 +1,153 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Memory protection definitions for the PRAMFS filesystem.
-+ *
-+ * Copyright 2010-2011 Marco Stornelli <marco.stornelli@gmail.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.
-+ */
-+
-+#ifndef __WPROTECT_H
-+#define __WPROTECT_H
-+
-+#include <linux/pram_fs.h>
-+
-+/* pram_memunlock_super() before calling! */
-+static inline void pram_sync_super(struct pram_super_block *ps)
-+{
-+ u16 crc = 0;
-+ ps->s_wtime = cpu_to_be32(get_seconds());
-+ ps->s_sum = 0;
-+ crc = crc16(~0, (__u8 *)ps + sizeof(__be16), PRAM_SB_SIZE -
-+ sizeof(__be16));
-+ ps->s_sum = cpu_to_be16(crc);
-+ /* Keep sync redundant super block */
-+ memcpy((void *)ps + PRAM_SB_SIZE, (void *)ps, PRAM_SB_SIZE);
-+}
-+
-+/* pram_memunlock_inode() before calling! */
-+static inline void pram_sync_inode(struct pram_inode *pi)
-+{
-+ u16 crc = 0;
-+ pi->i_sum = 0;
-+ crc = crc16(~0, (__u8 *)pi + sizeof(__be16), PRAM_INODE_SIZE -
-+ sizeof(__be16));
-+ pi->i_sum = cpu_to_be16(crc);
-+}
-+
-+#ifdef CONFIG_PRAMFS_WRITE_PROTECT
-+extern void pram_writeable(void *vaddr, unsigned long size, int rw);
-+extern spinlock_t writeable_lock;
-+static inline int pram_is_protected(struct super_block *sb)
-+{
-+ struct pram_sb_info *sbi = (struct pram_sb_info *)sb->s_fs_info;
-+ return sbi->s_mount_opt & PRAM_MOUNT_PROTECT;
-+}
-+
-+static inline void __pram_memunlock_range(void *p, unsigned long len)
-+{
-+ /*
-+ * NOTE: Ideally we should lock all the kernel to be memory safe
-+ * and avoid to write in the protected memory,
-+ * obviously it's not possible, so we only serialize
-+ * the operations at fs level. We can't disable the interrupts
-+ * because we could have a deadlock in this path.
-+ */
-+ spin_lock(&writeable_lock);
-+ pram_writeable(p, len, 1);
-+}
-+
-+static inline void __pram_memlock_range(void *p, unsigned long len)
-+{
-+ pram_writeable(p, len, 0);
-+ spin_unlock(&writeable_lock);
-+}
-+
-+static inline void pram_memunlock_range(struct super_block *sb, void *p,
-+ unsigned long len)
-+{
-+ if (pram_is_protected(sb))
-+ __pram_memunlock_range(p, len);
-+}
-+
-+static inline void pram_memlock_range(struct super_block *sb, void *p,
-+ unsigned long len)
-+{
-+ if (pram_is_protected(sb))
-+ __pram_memlock_range(p, len);
-+}
-+
-+static inline void pram_memunlock_super(struct super_block *sb,
-+ struct pram_super_block *ps)
-+{
-+ if (pram_is_protected(sb))
-+ __pram_memunlock_range(ps, PRAM_SB_SIZE);
-+}
-+
-+static inline void pram_memlock_super(struct super_block *sb,
-+ struct pram_super_block *ps)
-+{
-+ pram_sync_super(ps);
-+ if (pram_is_protected(sb))
-+ __pram_memlock_range(ps, PRAM_SB_SIZE);
-+}
-+
-+static inline void pram_memunlock_inode(struct super_block *sb,
-+ struct pram_inode *pi)
-+{
-+ if (pram_is_protected(sb))
-+ __pram_memunlock_range(pi, PRAM_SB_SIZE);
-+}
-+
-+static inline void pram_memlock_inode(struct super_block *sb,
-+ struct pram_inode *pi)
-+{
-+ pram_sync_inode(pi);
-+ if (pram_is_protected(sb))
-+ __pram_memlock_range(pi, PRAM_SB_SIZE);
-+}
-+
-+static inline void pram_memunlock_block(struct super_block *sb,
-+ void *bp)
-+{
-+ if (pram_is_protected(sb))
-+ __pram_memunlock_range(bp, sb->s_blocksize);
-+}
-+
-+static inline void pram_memlock_block(struct super_block *sb,
-+ void *bp)
-+{
-+ if (pram_is_protected(sb))
-+ __pram_memlock_range(bp, sb->s_blocksize);
-+}
-+
-+#else
-+#define pram_is_protected(sb) 0
-+#define pram_writeable(vaddr, size, rw) do {} while (0)
-+static inline void pram_memunlock_range(struct super_block *sb, void *p,
-+ unsigned long len) {}
-+static inline void pram_memlock_range(struct super_block *sb, void *p,
-+ unsigned long len) {}
-+static inline void pram_memunlock_super(struct super_block *sb,
-+ struct pram_super_block *ps) {}
-+static inline void pram_memlock_super(struct super_block *sb,
-+ struct pram_super_block *ps)
-+{
-+ pram_sync_super(ps);
-+}
-+static inline void pram_memunlock_inode(struct super_block *sb,
-+ struct pram_inode *pi) {}
-+static inline void pram_memlock_inode(struct super_block *sb,
-+ struct pram_inode *pi)
-+{
-+ pram_sync_inode(pi);
-+}
-+static inline void pram_memunlock_block(struct super_block *sb,
-+ void *bp) {}
-+static inline void pram_memlock_block(struct super_block *sb,
-+ void *bp) {}
-+
-+#endif /* CONFIG PRAMFS_WRITE_PROTECT */
-+#endif
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:19:02 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:12:29 +0200
-Subject: pramfs: test module
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FAE99FD.4040508@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-Test module.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
-
----
- fs/pramfs/pramfs_test.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 47 insertions(+)
-
---- /dev/null
-+++ b/fs/pramfs/pramfs_test.c
-@@ -0,0 +1,47 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Pramfs test module.
-+ *
-+ * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.com>
-+ * Copyright 2003 Sony Corporation
-+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
-+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
-+ * 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 <linux/module.h>
-+#include <linux/version.h>
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include "pram.h"
-+
-+int __init test_pramfs_write(void)
-+{
-+ struct pram_super_block *psb;
-+
-+ psb = get_pram_super();
-+ if (!psb) {
-+ printk(KERN_ERR
-+ "%s: PRAMFS super block not found (not mounted?)\n",
-+ __func__);
-+ return 1;
-+ }
-+
-+ /*
-+ * Attempt an unprotected clear of checksum information in the
-+ * superblock, this should cause a kernel page protection fault.
-+ */
-+ printk("%s: writing to kernel VA %p\n", __func__, psb);
-+ psb->s_sum = 0;
-+
-+ return 0;
-+}
-+
-+void test_pramfs_write_cleanup(void) {}
-+
-+/* Module information */
-+MODULE_LICENSE("GPL");
-+module_init(test_pramfs_write);
-+module_exit(test_pramfs_write_cleanup);
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:19:17 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:12:42 +0200
-Subject: pramfs: ioctl operations
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FAE9A0A.2080201@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-Ioctl operations.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
-
----
- fs/pramfs/ioctl.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 121 insertions(+)
-
---- /dev/null
-+++ b/fs/pramfs/ioctl.c
-@@ -0,0 +1,121 @@
-+/*
-+ * BRIEF DESCRIPTION
-+ *
-+ * Ioctl operations.
-+ *
-+ * Copyright 2010-2011 Marco Stornelli <marco.stornelli@gmail.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 <linux/capability.h>
-+#include <linux/time.h>
-+#include <linux/sched.h>
-+#include <linux/compat.h>
-+#include <linux/mount.h>
-+#include "pram.h"
-+
-+long pram_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-+{
-+ struct inode *inode = filp->f_dentry->d_inode;
-+ struct pram_inode *pi;
-+ unsigned int flags;
-+ int ret;
-+
-+ pi = pram_get_inode(inode->i_sb, inode->i_ino);
-+ if (!pi)
-+ return -EACCES;
-+
-+ switch (cmd) {
-+ case FS_IOC_GETFLAGS:
-+ flags = be32_to_cpu(pi->i_flags) & PRAM_FL_USER_VISIBLE;
-+ return put_user(flags, (int __user *) arg);
-+ case FS_IOC_SETFLAGS: {
-+ unsigned int oldflags;
-+
-+ ret = mnt_want_write(filp->f_path.mnt);
-+ if (ret)
-+ return ret;
-+
-+ if (!inode_owner_or_capable(inode)) {
-+ ret = -EPERM;
-+ goto flags_out;
-+ }
-+
-+ if (get_user(flags, (int __user *) arg)) {
-+ ret = -EFAULT;
-+ goto flags_out;
-+ }
-+
-+ mutex_lock(&inode->i_mutex);
-+ oldflags = be32_to_cpu(pi->i_flags);
-+
-+ if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
-+ if (!capable(CAP_LINUX_IMMUTABLE)) {
-+ mutex_unlock(&inode->i_mutex);
-+ ret = -EPERM;
-+ goto flags_out;
-+ }
-+ }
-+
-+ if (!S_ISDIR(inode->i_mode))
-+ flags &= ~FS_DIRSYNC_FL;
-+
-+ flags = flags & FS_FL_USER_MODIFIABLE;
-+ flags |= oldflags & ~FS_FL_USER_MODIFIABLE;
-+ pram_memunlock_inode(inode->i_sb, pi);
-+ pi->i_flags = cpu_to_be32(flags);
-+ inode->i_ctime = CURRENT_TIME_SEC;
-+ pi->i_ctime = cpu_to_be32(inode->i_ctime.tv_sec);
-+ pram_set_inode_flags(inode, pi);
-+ pram_memlock_inode(inode->i_sb, pi);
-+ mutex_unlock(&inode->i_mutex);
-+flags_out:
-+ mnt_drop_write(filp->f_path.mnt);
-+ return ret;
-+ }
-+ case FS_IOC_GETVERSION:
-+ return put_user(inode->i_generation, (int __user *) arg);
-+ case FS_IOC_SETVERSION:
-+ if (!inode_owner_or_capable(inode))
-+ return -EPERM;
-+ ret = mnt_want_write(filp->f_path.mnt);
-+ if (ret)
-+ return ret;
-+ if (get_user(inode->i_generation, (int __user *) arg)) {
-+ ret = -EFAULT;
-+ } else {
-+ inode->i_ctime = CURRENT_TIME_SEC;
-+ pram_update_inode(inode);
-+ }
-+ mnt_drop_write(filp->f_path.mnt);
-+ return ret;
-+ default:
-+ return -ENOTTY;
-+ }
-+}
-+
-+#ifdef CONFIG_COMPAT
-+long pram_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+ switch (cmd) {
-+ case FS_IOC32_GETFLAGS:
-+ cmd = FS_IOC_GETFLAGS;
-+ break;
-+ case FS_IOC32_SETFLAGS:
-+ cmd = FS_IOC_SETFLAGS;
-+ break;
-+ case FS_IOC32_GETVERSION:
-+ cmd = FS_IOC_GETVERSION;
-+ break;
-+ case FS_IOC32_SETVERSION:
-+ cmd = FS_IOC_SETVERSION;
-+ break;
-+ default:
-+ return -ENOIOCTLCMD;
-+ }
-+ return pram_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
-+}
-+#endif
+++ /dev/null
-From ltsi-dev-bounces@lists.linuxfoundation.org Sat May 12 10:19:31 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 12 May 2012 19:12:54 +0200
-Subject: pramfs: Makefile and Kconfig
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Message-ID: <4FAE9A16.4000501@gmail.com>
-
-
-From: Marco Stornelli <marco.stornelli@gmail.com>
-
-Makefile and Kconfig.
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
-
----
- MAINTAINERS | 9 ++++++
- arch/Kconfig | 3 ++
- arch/x86/Kconfig | 1
- fs/Kconfig | 6 ++--
- fs/Makefile | 1
- fs/pramfs/Kconfig | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++
- fs/pramfs/Makefile | 14 ++++++++++
- 7 files changed, 104 insertions(+), 2 deletions(-)
-
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -5351,6 +5351,15 @@ S: Maintained
- F: drivers/net/ppp/pptp.c
- W: http://sourceforge.net/projects/accel-pptp
-
-+PRAM FILE SYSTEM
-+M: Marco Stornelli <marco.stornelli@gmail.com>
-+W: http://pramfs.sourceforge.net
-+L: pramfs-devel@lists.sourceforge.net (subscribers-only)
-+S: Maintained
-+F: Documentation/filesystems/pramfs.txt
-+F: fs/pramfs/
-+F: include/linux/pram*
-+
- PREEMPTIBLE KERNEL
- M: Robert Love <rml@tech9.net>
- L: kpreempt-tech@lists.sourceforge.net
---- a/arch/Kconfig
-+++ b/arch/Kconfig
-@@ -112,6 +112,9 @@ config USER_RETURN_NOTIFIER
- config HAVE_IOREMAP_PROT
- bool
-
-+config HAVE_SET_MEMORY_RO
-+ bool
-+
- config HAVE_KPROBES
- bool
-
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -23,6 +23,7 @@ config X86
- select HAVE_PCSPKR_PLATFORM
- select HAVE_PERF_EVENTS
- select HAVE_IRQ_WORK
-+ select HAVE_SET_MEMORY_RO
- select HAVE_IOREMAP_PROT
- select HAVE_KPROBES
- select HAVE_MEMBLOCK
---- a/fs/Kconfig
-+++ b/fs/Kconfig
-@@ -17,7 +17,7 @@ source "fs/ext4/Kconfig"
- config FS_XIP
- # execute in place
- bool
-- depends on EXT2_FS_XIP
-+ depends on EXT2_FS_XIP || PRAMFS_XIP
- default y
-
- source "fs/jbd/Kconfig"
-@@ -29,7 +29,8 @@ config FS_MBCACHE
- default y if EXT2_FS=y && EXT2_FS_XATTR
- default y if EXT3_FS=y && EXT3_FS_XATTR
- default y if EXT4_FS=y && EXT4_FS_XATTR
-- default m if EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4_FS_XATTR
-+ default y if PRAMFS=y && PRAMFS_XATTR
-+ default m if EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4_FS_XATTR || PRAMFS_XATTR
-
- source "fs/reiserfs/Kconfig"
- source "fs/jfs/Kconfig"
-@@ -219,6 +220,7 @@ source "fs/romfs/Kconfig"
- source "fs/pstore/Kconfig"
- source "fs/sysv/Kconfig"
- source "fs/ufs/Kconfig"
-+source "fs/pramfs/Kconfig"
- source "fs/exofs/Kconfig"
-
- endif # MISC_FILESYSTEMS
---- a/fs/Makefile
-+++ b/fs/Makefile
-@@ -125,3 +125,4 @@ obj-$(CONFIG_GFS2_FS) += gfs2/
- obj-y += exofs/ # Multiple modules
- obj-$(CONFIG_CEPH_FS) += ceph/
- obj-$(CONFIG_PSTORE) += pstore/
-+obj-$(CONFIG_PRAMFS) += pramfs/
---- /dev/null
-+++ b/fs/pramfs/Kconfig
-@@ -0,0 +1,72 @@
-+config PRAMFS
-+ tristate "Persistent and Protected RAM file system support"
-+ depends on HAS_IOMEM && EXPERIMENTAL
-+ select CRC16
-+ help
-+ If your system has a block of fast (comparable in access speed to
-+ system memory) and non-volatile RAM and you wish to mount a
-+ light-weight, full-featured, and space-efficient filesystem over it,
-+ say Y here, and read <file:Documentation/filesystems/pramfs.txt>.
-+
-+ To compile this as a module, choose M here: the module will be
-+ called pramfs.
-+
-+config PRAMFS_XIP
-+ bool "Execute-in-place in PRAMFS"
-+ depends on PRAMFS && BLOCK
-+ help
-+ Say Y here to enable XIP feature of PRAMFS.
-+
-+config PRAMFS_WRITE_PROTECT
-+ bool "PRAMFS write protection"
-+ depends on PRAMFS && MMU && HAVE_SET_MEMORY_RO
-+ default y
-+ help
-+ Say Y here to enable the write protect feature of PRAMFS.
-+
-+config PRAMFS_XATTR
-+ bool "PRAMFS extended attributes"
-+ depends on PRAMFS && BLOCK
-+ help
-+ Extended attributes are name:value pairs associated with inodes by
-+ the kernel or by users (see the attr(5) manual page, or visit
-+ <http://acl.bestbits.at/> for details).
-+
-+ If unsure, say N.
-+
-+config PRAMFS_POSIX_ACL
-+ bool "PRAMFS POSIX Access Control Lists"
-+ depends on PRAMFS_XATTR
-+ select FS_POSIX_ACL
-+ help
-+ Posix Access Control Lists (ACLs) support permissions for users and
-+ groups beyond the owner/group/world scheme.
-+
-+ To learn more about Access Control Lists, visit the Posix ACLs for
-+ Linux website <http://acl.bestbits.at/>.
-+
-+ If you don't know what Access Control Lists are, say N.
-+
-+config PRAMFS_SECURITY
-+ bool "PRAMFS Security Labels"
-+ depends on PRAMFS_XATTR
-+ help
-+ Security labels support alternative access control models
-+ implemented by security modules like SELinux. This option
-+ enables an extended attribute handler for file security
-+ labels in the pram filesystem.
-+
-+ If you are not using a security module that requires using
-+ extended attributes for file security labels, say N.
-+
-+config PRAMFS_TEST
-+ boolean
-+ depends on PRAMFS
-+
-+config PRAMFS_TEST_MODULE
-+ tristate "PRAMFS Test"
-+ depends on PRAMFS && PRAMFS_WRITE_PROTECT && m
-+ select PRAMFS_TEST
-+ help
-+ Say Y here to build a simple module to test the protection of
-+ PRAMFS. The module will be called pramfs_test.
---- /dev/null
-+++ b/fs/pramfs/Makefile
-@@ -0,0 +1,14 @@
-+#
-+# Makefile for the linux pram-filesystem routines.
-+#
-+
-+obj-$(CONFIG_PRAMFS) += pramfs.o
-+obj-$(CONFIG_PRAMFS_TEST_MODULE) += pramfs_test.o
-+
-+pramfs-y := balloc.o dir.o file.o inode.o namei.o super.o symlink.o ioctl.o
-+
-+pramfs-$(CONFIG_PRAMFS_WRITE_PROTECT) += wprotect.o
-+pramfs-$(CONFIG_PRAMFS_XIP) += xip.o
-+pramfs-$(CONFIG_PRAMFS_XATTR) += xattr.o xattr_user.o xattr_trusted.o desctree.o
-+pramfs-$(CONFIG_PRAMFS_POSIX_ACL) += acl.o
-+pramfs-$(CONFIG_PRAMFS_SECURITY) += xattr_security.o
+++ /dev/null
-From marco.stornelli@gmail.com Sat Dec 15 00:46:14 2012
-From: Marco Stornelli <marco.stornelli@gmail.com>
-Date: Sat, 15 Dec 2012 09:39:21 +0100
-Subject: pramfs: fix build for kernel 3.4
-To: LTSI <ltsi-dev@lists.linuxfoundation.org>
-Cc: Greg KH <gregkh@linuxfoundation.org>
-Message-ID: <50CC3739.7070001@gmail.com>
-
-
-Upgrade pramfs code for kernel 3.4
-
-Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
----
- fs/pramfs/acl.c | 66 +---
- fs/pramfs/acl.h | 3
- fs/pramfs/balloc.c | 2
- fs/pramfs/file.c | 47 +++
- fs/pramfs/inode.c | 612 ++++++++++++++++++++++++++-------------------
- fs/pramfs/ioctl.c | 24 +
- fs/pramfs/namei.c | 24 -
- fs/pramfs/pram.h | 8
- fs/pramfs/super.c | 27 +
- fs/pramfs/xattr_security.c | 33 +-
- include/linux/pram_fs_sb.h | 2
- 11 files changed, 478 insertions(+), 370 deletions(-)
-
---- a/fs/pramfs/acl.c
-+++ b/fs/pramfs/acl.c
-@@ -131,7 +131,7 @@ fail:
- /*
- * inode->i_mutex: don't care
- */
--static struct posix_acl *pram_get_acl(struct inode *inode, int type)
-+struct posix_acl *pram_get_acl(struct inode *inode, int type)
- {
- int name_index;
- char *value = NULL;
-@@ -195,12 +195,10 @@ static int pram_set_acl(struct inode *in
- case ACL_TYPE_ACCESS:
- name_index = PRAM_XATTR_INDEX_POSIX_ACL_ACCESS;
- if (acl) {
-- mode_t mode = inode->i_mode;
-- error = posix_acl_equiv_mode(acl, &mode);
-+ error = posix_acl_equiv_mode(acl, &inode->i_mode);
- if (error < 0)
- return error;
- else {
-- inode->i_mode = mode;
- inode->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(inode);
- if (error == 0)
-@@ -230,28 +228,6 @@ static int pram_set_acl(struct inode *in
- return error;
- }
-
--int pram_check_acl(struct inode *inode, int mask, unsigned int flags)
--{
-- struct posix_acl *acl;
--
-- if (flags & IPERM_FLAG_RCU) {
-- if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
-- return -ECHILD;
-- return -EAGAIN;
-- }
--
-- acl = pram_get_acl(inode, ACL_TYPE_ACCESS);
-- if (IS_ERR(acl))
-- return PTR_ERR(acl);
-- if (acl) {
-- int error = posix_acl_permission(inode, acl, mask);
-- posix_acl_release(acl);
-- return error;
-- }
--
-- return -EAGAIN;
--}
--
- /*
- * Initialize the ACLs of a new inode. Called from pram_new_inode.
- *
-@@ -274,29 +250,20 @@ int pram_init_acl(struct inode *inode, s
- }
-
- if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
-- struct posix_acl *clone;
-- mode_t mode;
--
-+ umode_t mode = inode->i_mode;
- if (S_ISDIR(inode->i_mode)) {
- error = pram_set_acl(inode, ACL_TYPE_DEFAULT, acl);
- if (error)
- goto cleanup;
- }
-- clone = posix_acl_clone(acl, GFP_KERNEL);
-- error = -ENOMEM;
-- if (!clone)
-- goto cleanup;
-- mode = inode->i_mode;
-- error = posix_acl_create_masq(clone, &mode);
-- if (error >= 0) {
-- inode->i_mode = mode;
-- if (error > 0) {
-- /* This is an extended ACL */
-- error = pram_set_acl(inode,
-- ACL_TYPE_ACCESS, clone);
-- }
-+ error = posix_acl_create(&acl, GFP_KERNEL, &mode);
-+ if (error < 0)
-+ return error;
-+ inode->i_mode = mode;
-+ if (error > 0) {
-+ /* This is an extended ACL */
-+ error = pram_set_acl(inode, ACL_TYPE_ACCESS, acl);
- }
-- posix_acl_release(clone);
- }
- cleanup:
- posix_acl_release(acl);
-@@ -319,7 +286,7 @@ cleanup:
- */
- int pram_acl_chmod(struct inode *inode)
- {
-- struct posix_acl *acl, *clone;
-+ struct posix_acl *acl;
- int error;
-
- if (!test_opt(inode->i_sb, POSIX_ACL))
-@@ -329,14 +296,11 @@ int pram_acl_chmod(struct inode *inode)
- acl = pram_get_acl(inode, ACL_TYPE_ACCESS);
- if (IS_ERR(acl) || !acl)
- return PTR_ERR(acl);
-- clone = posix_acl_clone(acl, GFP_KERNEL);
-+ error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
-+ if (error)
-+ return error;
-+ error = pram_set_acl(inode, ACL_TYPE_ACCESS, acl);
- posix_acl_release(acl);
-- if (!clone)
-- return -ENOMEM;
-- error = posix_acl_chmod_masq(clone, inode->i_mode);
-- if (!error)
-- error = pram_set_acl(inode, ACL_TYPE_ACCESS, clone);
-- posix_acl_release(clone);
- return error;
- }
-
---- a/fs/pramfs/acl.h
-+++ b/fs/pramfs/acl.h
-@@ -64,13 +64,12 @@ static inline int pram_acl_count(size_t
- #ifdef CONFIG_PRAMFS_POSIX_ACL
-
- /* acl.c */
--extern int pram_check_acl(struct inode *, int, unsigned int);
-+extern struct posix_acl *pram_get_acl(struct inode *inode, int type);
- extern int pram_acl_chmod(struct inode *);
- extern int pram_init_acl(struct inode *, struct inode *);
-
- #else
- #include <linux/sched.h>
--#define pram_check_acl NULL
- #define pram_get_acl NULL
- #define pram_set_acl NULL
-
---- a/fs/pramfs/balloc.c
-+++ b/fs/pramfs/balloc.c
-@@ -77,7 +77,7 @@ void pram_free_block(struct super_block
- ps->s_free_blocknr_hint = cpu_to_be32(blocknr);
- be32_add_cpu(&ps->s_free_blocks_count, 1);
- pram_memlock_super(sb, ps);
--
-+
- unlock_super(sb);
- }
-
---- a/fs/pramfs/file.c
-+++ b/fs/pramfs/file.c
-@@ -352,8 +352,49 @@ static long pram_fallocate(struct file *
- return ret;
- }
-
-+loff_t pram_llseek(struct file *file, loff_t offset, int origin)
-+{
-+ struct inode *inode = file->f_path.dentry->d_inode;
-+ int retval;
-+
-+ if (origin != SEEK_DATA && origin != SEEK_HOLE)
-+ return generic_file_llseek(file, offset, origin);
-+
-+ mutex_lock(&inode->i_mutex);
-+ switch (origin) {
-+ case SEEK_DATA:
-+ retval = pram_find_region(inode, &offset, 0);
-+ if (retval) {
-+ mutex_unlock(&inode->i_mutex);
-+ return retval;
-+ }
-+ break;
-+ case SEEK_HOLE:
-+ retval = pram_find_region(inode, &offset, 1);
-+ if (retval) {
-+ mutex_unlock(&inode->i_mutex);
-+ return retval;
-+ }
-+ break;
-+ }
-+
-+ if ((offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) ||
-+ offset > inode->i_sb->s_maxbytes) {
-+ mutex_unlock(&inode->i_mutex);
-+ return -EINVAL;
-+ }
-+
-+ if (offset != file->f_pos) {
-+ file->f_pos = offset;
-+ file->f_version = 0;
-+ }
-+
-+ mutex_unlock(&inode->i_mutex);
-+ return offset;
-+}
-+
- const struct file_operations pram_file_operations = {
-- .llseek = generic_file_llseek,
-+ .llseek = pram_llseek,
- .read = do_sync_read,
- .write = do_sync_write,
- .aio_read = generic_file_aio_read,
-@@ -372,7 +413,7 @@ const struct file_operations pram_file_o
-
- #ifdef CONFIG_PRAMFS_XIP
- const struct file_operations pram_xip_file_operations = {
-- .llseek = generic_file_llseek,
-+ .llseek = pram_llseek,
- .read = pram_xip_file_read,
- .write = xip_file_write,
- .mmap = pram_xip_file_mmap,
-@@ -394,5 +435,5 @@ const struct inode_operations pram_file_
- .removexattr = generic_removexattr,
- #endif
- .setattr = pram_notify_change,
-- .check_acl = pram_check_acl,
-+ .get_acl = pram_get_acl,
- };
---- a/fs/pramfs/inode.c
-+++ b/fs/pramfs/inode.c
-@@ -8,7 +8,7 @@
- * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
- * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
- * This file is licensed under the terms of the GNU General Public
-- * License version 2. This program is licensed"as is" without any
-+ * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-@@ -18,27 +18,27 @@
- #include <linux/module.h>
- #include <linux/mpage.h>
- #include <linux/backing-dev.h>
--#include"pram.h"
--#include"xattr.h"
--#include"xip.h"
--#include"acl.h"
-+#include "pram.h"
-+#include "xattr.h"
-+#include "xip.h"
-+#include "acl.h"
-
--struct backing_dev_info pram_backing_dev_info __read_mostly = {
-- .ra_pages = 0,/* No readahead */
-+struct backing_dev_info pram_backing_dev_info __read_mostly = {
-+ .ra_pages = 0, /* No readahead */
- .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK,
- };
-
- /*
-- * allocate a data blockfor inode andreturn it's absolute blocknr.
-- * Zeroes out the blockif zero set. Increments inode->i_blocks.
-+ * allocate a data block for inode and return it's absolute blocknr.
-+ * Zeroes out the block if zero set. Increments inode->i_blocks.
- */
--static int pram_new_data_block(struct inode *inode,unsigned long *blocknr,
-- int zero)
-+static int pram_new_data_block(struct inode *inode, unsigned long *blocknr,
-+ int zero)
- {
-- int errval = pram_new_block(inode->i_sb, blocknr, zero);
-+ int errval = pram_new_block(inode->i_sb, blocknr, zero);
-
-- if (!errval) {
-- struct pram_inode *pi = pram_get_inode(inode->i_sb,
-+ if (!errval) {
-+ struct pram_inode *pi = pram_get_inode(inode->i_sb,
- inode->i_ino);
- inode->i_blocks++;
- pram_memunlock_inode(inode->i_sb, pi);
-@@ -46,23 +46,23 @@ static int pram_new_data_block(struct
- pram_memlock_inode(inode->i_sb, pi);
- }
-
-- return errval;
-+ return errval;
- }
-
- /*
- * find the offset to the block represented by the given inode's file
- * relative block number.
- */
--u64 pram_find_data_block(struct inode *inode,unsigned long file_blocknr)
-+u64 pram_find_data_block(struct inode *inode, unsigned long file_blocknr)
- {
-- struct super_block *sb = inode->i_sb;
-- struct pram_inode *pi;
-- u64 *row;/* ptr to row block */
-- u64 *col;/* ptr to column blocks */
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_inode *pi;
-+ u64 *row; /* ptr to row block */
-+ u64 *col; /* ptr to column blocks */
- u64 bp = 0;
-- unsigned int i_row, i_col;
-- unsigned int N = sb->s_blocksize >> 3;/* num block ptrs per block */
-- unsigned int Nbits = sb->s_blocksize_bits - 3;
-+ unsigned int i_row, i_col;
-+ unsigned int N = sb->s_blocksize >> 3; /* num block ptrs per block */
-+ unsigned int Nbits = sb->s_blocksize_bits - 3;
-
- pi = pram_get_inode(sb, inode->i_ino);
-
-@@ -70,42 +70,143 @@ u64 pram_find_data_block(struct inode *
- i_col = file_blocknr & (N-1);
-
- row = pram_get_block(sb, be64_to_cpu(pi->i_type.reg.row_block));
-- if (row) {
-+ if (row) {
- col = pram_get_block(sb, be64_to_cpu(row[i_row]));
-- if (col)
-+ if (col)
- bp = be64_to_cpu(col[i_col]);
- }
-
-- return bp;
-+ return bp;
-+}
-+
-+/*
-+ * find the file offset for SEEK_DATA/SEEK_HOLE
-+ */
-+int pram_find_region(struct inode *inode, loff_t *offset, int hole)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_inode *pi = pram_get_inode(sb, inode->i_ino);
-+ int N = sb->s_blocksize >> 3; /* num block ptrs per block */
-+ int first_row_index, last_row_index, i, j;
-+ unsigned long first_blocknr, last_blocknr, blocks = 0, offset_in_block;
-+ u64 *row; /* ptr to row block */
-+ u64 *col; /* ptr to column blocks */
-+ int data_found = 0, hole_found = 0;
-+
-+ if (*offset >= inode->i_size)
-+ return -ENXIO;
-+
-+ if (!inode->i_blocks || !pi->i_type.reg.row_block) {
-+ if (hole)
-+ return inode->i_size;
-+ else
-+ return -ENXIO;
-+ }
-+
-+ offset_in_block = *offset & (sb->s_blocksize - 1);
-+
-+ first_blocknr = *offset >> sb->s_blocksize_bits;
-+ last_blocknr = inode->i_size >> sb->s_blocksize_bits;
-+
-+ first_row_index = first_blocknr >> (sb->s_blocksize_bits - 3);
-+ last_row_index = last_blocknr >> (sb->s_blocksize_bits - 3);
-+
-+ row = pram_get_block(sb, be64_to_cpu(pi->i_type.reg.row_block));
-+
-+ for (i = first_row_index; i <= last_row_index; i++) {
-+ int first_col_index = (i == first_row_index) ?
-+ first_blocknr & (N-1) : 0;
-+ int last_col_index = (i == last_row_index) ?
-+ last_blocknr & (N-1) : N-1;
-+
-+ if (!row[i]) {
-+ hole_found = 1;
-+ if (!hole)
-+ blocks += sb->s_blocksize >> 3;
-+ continue;
-+ }
-+
-+ col = pram_get_block(sb, be64_to_cpu(row[i]));
-+
-+ for (j = first_col_index; j <= last_col_index; j++) {
-+
-+ if (col[j]) {
-+ data_found = 1;
-+ if (!hole)
-+ goto out;
-+ } else
-+ hole_found = 1;
-+
-+ if (!hole_found || !hole)
-+ blocks++;
-+ }
-+ cond_resched();
-+ }
-+ out:
-+ /* Searching data but only hole found till the end */
-+ if (!hole && !data_found && hole_found)
-+ return -ENXIO;
-+
-+ if (data_found && !hole_found) {
-+ /* Searching data but we are alredy into them */
-+ if (!hole)
-+ return 0;
-+ /* Searching hole but only data found, go to the end */
-+ else {
-+ *offset = inode->i_size;
-+ return 0;
-+ }
-+ }
-+
-+ /* Searching for hole, hole found and starting inside an hole */
-+ if (hole && hole_found && !blocks) {
-+ /* we found data after it */
-+ if (data_found)
-+ return 0;
-+ else {
-+ /* last hole */
-+ *offset = inode->i_size;
-+ return 0;
-+ }
-+ }
-+
-+ if (offset_in_block) {
-+ blocks--;
-+ *offset += (blocks << sb->s_blocksize_bits) +
-+ (sb->s_blocksize - offset_in_block);
-+ } else
-+ *offset += blocks << sb->s_blocksize_bits;
-+
-+ return 0;
- }
-
- /*
- * Free data blocks from inode in the range start <=> end
- */
--static void __pram_truncate_blocks(struct inode *inode, loff_t start,
-+static void __pram_truncate_blocks(struct inode *inode, loff_t start,
- loff_t end)
- {
-- struct super_block *sb = inode->i_sb;
-- struct pram_inode *pi = pram_get_inode(sb, inode->i_ino);
-- int N = sb->s_blocksize >> 3;/* num block ptrs per block */
-- int Nbits = sb->s_blocksize_bits - 3;
-- int first_row_index, last_row_index, i, j;
-- unsigned long blocknr, first_blocknr, last_blocknr;
-- unsigned int freed = 0;
-- u64 *row;/* ptr to row block */
-- u64 *col;/* ptr to column blocks */
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_inode *pi = pram_get_inode(sb, inode->i_ino);
-+ int N = sb->s_blocksize >> 3; /* num block ptrs per block */
-+ int Nbits = sb->s_blocksize_bits - 3;
-+ int first_row_index, last_row_index, i, j;
-+ unsigned long blocknr, first_blocknr, last_blocknr;
-+ unsigned int freed = 0;
-+ u64 *row; /* ptr to row block */
-+ u64 *col; /* ptr to column blocks */
-
-- if (!pi->i_type.reg.row_block)
-+ if (!pi->i_type.reg.row_block)
- return;
-
- first_blocknr = (start + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
-
-- if (pi->i_flags & cpu_to_be32(PRAM_EOFBLOCKS_FL))
-+ if (pi->i_flags & cpu_to_be32(PRAM_EOFBLOCKS_FL))
- last_blocknr = (1UL << (2*sb->s_blocksize_bits - 6)) - 1;
- else
- last_blocknr = end >> sb->s_blocksize_bits;
-
-- if (first_blocknr > last_blocknr)
-+ if (first_blocknr > last_blocknr)
- return;
-
- first_row_index = first_blocknr >> Nbits;
-@@ -113,20 +214,20 @@ static void __pram_truncate_blocks(str
-
- row = pram_get_block(sb, be64_to_cpu(pi->i_type.reg.row_block));
-
-- for (i = first_row_index; i <= last_row_index; i++) {
-- int first_col_index = (i == first_row_index) ?
-+ for (i = first_row_index; i <= last_row_index; i++) {
-+ int first_col_index = (i == first_row_index) ?
- first_blocknr & (N-1) : 0;
-- int last_col_index = (i == last_row_index) ?
-+ int last_col_index = (i == last_row_index) ?
- last_blocknr & (N-1) : N-1;
-
-- if (unlikely(!row[i]))
-+ if (unlikely(!row[i]))
- continue;
-
- col = pram_get_block(sb, be64_to_cpu(row[i]));
-
-- for (j = first_col_index; j <= last_col_index; j++) {
-+ for (j = first_col_index; j <= last_col_index; j++) {
-
-- if (unlikely(!col[j]))
-+ if (unlikely(!col[j]))
- continue;
-
- blocknr = pram_get_blocknr(sb, be64_to_cpu(col[j]));
-@@ -137,7 +238,9 @@ static void __pram_truncate_blocks(str
- pram_memlock_block(sb, col);
- }
-
-- if (first_col_index == 0) {
-+ cond_resched();
-+
-+ if (first_col_index == 0) {
- blocknr = pram_get_blocknr(sb, be64_to_cpu(row[i]));
- pram_free_block(sb, blocknr);
- pram_memunlock_block(sb, row);
-@@ -148,13 +251,13 @@ static void __pram_truncate_blocks(str
-
- inode->i_blocks -= freed;
-
-- if (start == 0) {
-+ if (start == 0) {
- blocknr = pram_get_blocknr(sb,
- be64_to_cpu(pi->i_type.reg.row_block));
- pram_free_block(sb, blocknr);
- pram_memunlock_inode(sb, pi);
- pi->i_type.reg.row_block = 0;
-- goto update_blocks;
-+ goto update_blocks;
- }
- pram_memunlock_inode(sb, pi);
-
-@@ -163,13 +266,11 @@ static void __pram_truncate_blocks(str
- pram_memlock_inode(sb, pi);
- }
-
--static void pram_truncate_blocks(struct inode *inode, loff_t start, loff_t end)
-+static void pram_truncate_blocks(struct inode *inode, loff_t start, loff_t end)
- {
-- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
-- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-- return;
-
- __pram_truncate_blocks(inode, start, end);
- inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
-@@ -177,29 +278,29 @@ static void pram_truncate_blocks(struc
- }
-
- /*
-- * Allocate num data blocksfor inode, starting at given file-relative
-+ * Allocate num data blocks for inode, starting at given file-relative
- * block number.
- */
--int pram_alloc_blocks(struct inode *inode,int file_blocknr,unsigned int num)
-+int pram_alloc_blocks(struct inode *inode, int file_blocknr, unsigned int num)
- {
-- struct super_block *sb = inode->i_sb;
-- struct pram_inode *pi = pram_get_inode(sb, inode->i_ino);
-- int N = sb->s_blocksize >> 3;/* num block ptrs per block */
-- int Nbits = sb->s_blocksize_bits - 3;
-- int first_file_blocknr;
-- int last_file_blocknr;
-- int first_row_index, last_row_index;
-- int i, j, errval;
-- unsigned long blocknr;
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_inode *pi = pram_get_inode(sb, inode->i_ino);
-+ int N = sb->s_blocksize >> 3; /* num block ptrs per block */
-+ int Nbits = sb->s_blocksize_bits - 3;
-+ int first_file_blocknr;
-+ int last_file_blocknr;
-+ int first_row_index, last_row_index;
-+ int i, j, errval;
-+ unsigned long blocknr;
- u64 *row;
- u64 *col;
-
-- if (!pi->i_type.reg.row_block) {
-+ if (!pi->i_type.reg.row_block) {
- /* alloc the 2nd order array block */
- errval = pram_new_block(sb, &blocknr, 1);
-- if (errval) {
-+ if (errval) {
- pram_dbg("failed to alloc 2nd order array block\n");
-- goto fail;
-+ goto fail;
- }
- pram_memunlock_inode(sb, pi);
- pi->i_type.reg.row_block = cpu_to_be64(pram_get_block_off(sb,
-@@ -215,19 +316,19 @@ int pram_alloc_blocks(struct inode *in
- first_row_index = first_file_blocknr >> Nbits;
- last_row_index = last_file_blocknr >> Nbits;
-
-- for (i = first_row_index; i <= last_row_index; i++) {
-- int first_col_index, last_col_index;
-+ for (i = first_row_index; i <= last_row_index; i++) {
-+ int first_col_index, last_col_index;
-
- /*
-- * we are starting anew row, so make sure
-- * there is a block allocatedfor the row.
-+ * we are starting a new row, so make sure
-+ * there is a block allocated for the row.
- */
-- if (!row[i]) {
-+ if (!row[i]) {
- /* allocate the row block */
- errval = pram_new_block(sb, &blocknr, 1);
-- if (errval) {
-+ if (errval) {
- pram_dbg("failed to alloc row block\n");
-- goto fail;
-+ goto fail;
- }
- pram_memunlock_block(sb, row);
- row[i] = cpu_to_be64(pram_get_block_off(sb, blocknr));
-@@ -241,17 +342,19 @@ int pram_alloc_blocks(struct inode *in
- last_col_index = (i == last_row_index) ?
- last_file_blocknr & (N-1) : N-1;
-
-- for (j = first_col_index; j <= last_col_index; j++) {
-- if (!col[j]) {
-+ for (j = first_col_index; j <= last_col_index; j++) {
-+ if (!col[j]) {
- errval = pram_new_data_block(inode, &blocknr,
- 1);
-- if (errval) {
-+ if (errval) {
- pram_dbg("fail to alloc data block\n");
-- /* For later recovery in truncate... */
-- pram_memunlock_inode(inode->i_sb, pi);
-- pi->i_flags |= cpu_to_be32(PRAM_EOFBLOCKS_FL);
-- pram_memlock_inode(inode->i_sb, pi);
-- goto fail;
-+ if (j != first_col_index) {
-+ __pram_truncate_blocks(inode,
-+ inode->i_size,
-+ inode->i_size + ((j - first_col_index)
-+ << inode->i_sb->s_blocksize_bits));
-+ }
-+ goto fail;
- }
- pram_memunlock_block(sb, col);
- col[j] = cpu_to_be64(pram_get_block_off(sb,
-@@ -263,25 +366,25 @@ int pram_alloc_blocks(struct inode *in
-
- errval = 0;
- fail:
-- return errval;
-+ return errval;
- }
-
--static int pram_read_inode(struct inode *inode,struct pram_inode *pi)
-+static int pram_read_inode(struct inode *inode, struct pram_inode *pi)
- {
-- int ret = -EIO;
-+ int ret = -EIO;
-
- mutex_lock(&PRAM_I(inode)->i_meta_mutex);
-
-- if (pram_calc_checksum((u8 *)pi, PRAM_INODE_SIZE)) {
-- pram_err(inode->i_sb,"checksum error in inode %08x\n",
-+ if (pram_calc_checksum((u8 *)pi, PRAM_INODE_SIZE)) {
-+ pram_err(inode->i_sb, "checksum error in inode %08x\n",
- (u32)inode->i_ino);
-- goto bad_inode;
-+ goto bad_inode;
- }
-
- inode->i_mode = be16_to_cpu(pi->i_mode);
- inode->i_uid = be32_to_cpu(pi->i_uid);
- inode->i_gid = be32_to_cpu(pi->i_gid);
-- inode->i_nlink = be16_to_cpu(pi->i_links_count);
-+ set_nlink(inode, be16_to_cpu(pi->i_links_count));
- inode->i_size = be32_to_cpu(pi->i_size);
- inode->i_atime.tv_sec = be32_to_cpu(pi->i_atime);
- inode->i_ctime.tv_sec = be32_to_cpu(pi->i_ctime);
-@@ -291,13 +394,13 @@ static int pram_read_inode(struct ino
- inode->i_generation = be32_to_cpu(pi->i_generation);
- pram_set_inode_flags(inode, pi);
-
-- /* checkif the inode is active. */
-- if (inode->i_nlink == 0 && (inode->i_mode == 0 ||
-+ /* check if the inode is active. */
-+ if (inode->i_nlink == 0 && (inode->i_mode == 0 ||
- be32_to_cpu(pi->i_dtime))) {
-- /*this inode is deleted */
-+ /* this inode is deleted */
- pram_dbg("read inode: inode %lu not active", inode->i_ino);
- ret = -ESTALE;
-- goto bad_inode;
-+ goto bad_inode;
- }
-
- inode->i_blocks = be32_to_cpu(pi->i_blocks);
-@@ -305,21 +408,21 @@ static int pram_read_inode(struct ino
- inode->i_mapping->a_ops = &pram_aops;
- inode->i_mapping->backing_dev_info = &pram_backing_dev_info;
-
-- switch (inode->i_mode & S_IFMT) {
-- case S_IFREG:
-- if (pram_use_xip(inode->i_sb)) {
-+ switch (inode->i_mode & S_IFMT) {
-+ case S_IFREG:
-+ if (pram_use_xip(inode->i_sb)) {
- inode->i_mapping->a_ops = &pram_aops_xip;
- inode->i_fop = &pram_xip_file_operations;
-- }else {
-+ } else {
- inode->i_op = &pram_file_inode_operations;
- inode->i_fop = &pram_file_operations;
- }
- break;
-- case S_IFDIR:
-+ case S_IFDIR:
- inode->i_op = &pram_dir_inode_operations;
- inode->i_fop = &pram_dir_operations;
- break;
-- case S_IFLNK:
-+ case S_IFLNK:
- inode->i_op = &pram_symlink_inode_operations;
- break;
- default:
-@@ -331,22 +434,22 @@ static int pram_read_inode(struct ino
- }
-
- mutex_unlock(&PRAM_I(inode)->i_meta_mutex);
-- return 0;
-+ return 0;
-
- bad_inode:
- make_bad_inode(inode);
- mutex_unlock(&PRAM_I(inode)->i_meta_mutex);
-- return ret;
-+ return ret;
- }
-
--int pram_update_inode(struct inode *inode)
-+int pram_update_inode(struct inode *inode)
- {
-- struct pram_inode *pi;
-- int retval = 0;
-+ struct pram_inode *pi;
-+ int retval = 0;
-
- pi = pram_get_inode(inode->i_sb, inode->i_ino);
-- if (!pi)
-- return -EACCES;
-+ if (!pi)
-+ return -EACCES;
-
- mutex_lock(&PRAM_I(inode)->i_meta_mutex);
-
-@@ -363,13 +466,13 @@ int pram_update_inode(struct inode *in
- pi->i_generation = cpu_to_be32(inode->i_generation);
- pram_get_inode_flags(inode, pi);
-
-- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-+ if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- pi->i_type.dev.rdev = cpu_to_be32(inode->i_rdev);
-
- pram_memlock_inode(inode->i_sb, pi);
-
- mutex_unlock(&PRAM_I(inode)->i_meta_mutex);
-- return retval;
-+ return retval;
- }
-
- /*
-@@ -380,12 +483,12 @@ int pram_update_inode(struct inode *in
- * through the filesystem because the directory entry
- * has been deleted earlier.
- */
--static void pram_free_inode(struct inode *inode)
-+static void pram_free_inode(struct inode *inode)
- {
-- struct super_block *sb = inode->i_sb;
-- struct pram_super_block *ps;
-- struct pram_inode *pi;
-- unsigned long inode_nr;
-+ struct super_block *sb = inode->i_sb;
-+ struct pram_super_block *ps;
-+ struct pram_inode *pi;
-+ unsigned long inode_nr;
-
- pram_xattr_delete_inode(inode);
-
-@@ -403,10 +506,10 @@ static void pram_free_inode(struct in
- /* increment s_free_inodes_count */
- ps = pram_get_super(sb);
- pram_memunlock_super(sb, ps);
-- if (inode_nr < be32_to_cpu(ps->s_free_inode_hint))
-+ if (inode_nr < be32_to_cpu(ps->s_free_inode_hint))
- ps->s_free_inode_hint = cpu_to_be32(inode_nr);
- be32_add_cpu(&ps->s_free_inodes_count, 1);
-- if (be32_to_cpu(ps->s_free_inodes_count) ==
-+ if (be32_to_cpu(ps->s_free_inodes_count) ==
- be32_to_cpu(ps->s_inodes_count) - 1) {
- /* filesystem is empty */
- pram_dbg("fs is empty!\n");
-@@ -417,44 +520,44 @@ static void pram_free_inode(struct in
- unlock_super(sb);
- }
-
--struct inode *pram_iget(struct super_block *sb,unsigned long ino)
-+struct inode *pram_iget(struct super_block *sb, unsigned long ino)
- {
-- struct inode *inode;
-- struct pram_inode *pi;
-- int err;
-+ struct inode *inode;
-+ struct pram_inode *pi;
-+ int err;
-
- inode = iget_locked(sb, ino);
-- if (unlikely(!inode))
-- return ERR_PTR(-ENOMEM);
-- if (!(inode->i_state & I_NEW))
-- return inode;
-+ if (unlikely(!inode))
-+ return ERR_PTR(-ENOMEM);
-+ if (!(inode->i_state & I_NEW))
-+ return inode;
-
- pi = pram_get_inode(sb, ino);
-- if (!pi) {
-+ if (!pi) {
- err = -EACCES;
-- goto fail;
-+ goto fail;
- }
- err = pram_read_inode(inode, pi);
-- if (unlikely(err))
-- goto fail;
-+ if (unlikely(err))
-+ goto fail;
-
- unlock_new_inode(inode);
-- return inode;
-+ return inode;
- fail:
- iget_failed(inode);
-- return ERR_PTR(err);
-+ return ERR_PTR(err);
- }
-
--void pram_evict_inode(struct inode *inode)
-+void pram_evict_inode(struct inode *inode)
- {
-- int want_delete = 0;
-+ int want_delete = 0;
-
-- if (!inode->i_nlink && !is_bad_inode(inode))
-+ if (!inode->i_nlink && !is_bad_inode(inode))
- want_delete = 1;
-
- truncate_inode_pages(&inode->i_data, 0);
-
-- if (want_delete) {
-+ if (want_delete) {
- /* unlink from chain in the inode's directory */
- pram_remove_link(inode);
- pram_truncate_blocks(inode, 0, inode->i_size);
-@@ -463,65 +566,64 @@ void pram_evict_inode(struct inode *in
-
- end_writeback(inode);
-
-- if (want_delete)
-+ if (want_delete)
- pram_free_inode(inode);
- }
-
-
--
--struct inode *pram_new_inode(struct inode *dir,int mode,
-- const struct qstr *qstr)
-+struct inode *pram_new_inode(struct inode *dir, umode_t mode,
-+ const struct qstr *qstr)
- {
-- struct super_block *sb;
-- struct pram_sb_info *sbi;
-- struct pram_super_block *ps;
-- struct inode *inode;
-- struct pram_inode *pi =NULL;
-- struct pram_inode *diri =NULL;
-- int i, errval;
-+ struct super_block *sb;
-+ struct pram_sb_info *sbi;
-+ struct pram_super_block *ps;
-+ struct inode *inode;
-+ struct pram_inode *pi = NULL;
-+ struct pram_inode *diri = NULL;
-+ int i, errval;
- ino_t ino = 0;
-
- sb = dir->i_sb;
-- sbi = (struct pram_sb_info *)sb->s_fs_info;
-+ sbi = (struct pram_sb_info *)sb->s_fs_info;
- inode = new_inode(sb);
-- if (!inode)
-- return ERR_PTR(-ENOMEM);
-+ if (!inode)
-+ return ERR_PTR(-ENOMEM);
-
- lock_super(sb);
- ps = pram_get_super(sb);
-
-- if (ps->s_free_inodes_count) {
-+ if (ps->s_free_inodes_count) {
- /* find the oldest unused pram inode */
-- for (i = be32_to_cpu(ps->s_free_inode_hint);
-+ for (i = be32_to_cpu(ps->s_free_inode_hint);
- i < be32_to_cpu(ps->s_inodes_count); i++) {
- ino = PRAM_ROOT_INO + (i << PRAM_INODE_BITS);
- pi = pram_get_inode(sb, ino);
-- /* checkif the inode is active. */
-- if (be16_to_cpu(pi->i_links_count) == 0 &&
-+ /* check if the inode is active. */
-+ if (be16_to_cpu(pi->i_links_count) == 0 &&
- (be16_to_cpu(pi->i_mode) == 0 ||
- be32_to_cpu(pi->i_dtime))) {
-- /*this inode is deleted */
-+ /* this inode is deleted */
- break;
- }
- }
-
-- if (unlikely(i >= be32_to_cpu(ps->s_inodes_count))) {
-- pram_err(sb,"free inodes count!=0 but none free!?\n");
-+ if (unlikely(i >= be32_to_cpu(ps->s_inodes_count))) {
-+ pram_err(sb, "free inodes count!=0 but none free!?\n");
- errval = -ENOSPC;
-- goto fail1;
-+ goto fail1;
- }
-
- pram_dbg("allocating inode %lu\n", ino);
-- }else {
-- pram_dbg("no space left to createnew inode!\n");
-+ } else {
-+ pram_dbg("no space left to create new inode!\n");
- errval = -ENOSPC;
-- goto fail1;
-+ goto fail1;
- }
-
- diri = pram_get_inode(sb, dir->i_ino);
-- if (!diri) {
-+ if (!diri) {
- errval = -EACCES;
-- goto fail1;
-+ goto fail1;
- }
-
- /* chosen inode is in ino */
-@@ -541,25 +643,25 @@ struct inode *pram_new_inode(struct in
-
- pram_set_inode_flags(inode, pi);
-
-- if (insert_inode_locked(inode) < 0) {
-+ if (insert_inode_locked(inode) < 0) {
- errval = -EINVAL;
-- goto fail2;
-+ goto fail1;
- }
-- errval = pram_write_inode(inode,NULL);
-- if (errval)
-- goto fail2;
-+ errval = pram_write_inode(inode, NULL);
-+ if (errval)
-+ goto fail2;
-
- errval = pram_init_acl(inode, dir);
-- if (errval)
-- goto fail2;
-+ if (errval)
-+ goto fail2;
-
- errval = pram_init_security(inode, dir, qstr);
-- if (errval)
-- goto fail2;
-+ if (errval)
-+ goto fail2;
-
- pram_memunlock_super(sb, ps);
- be32_add_cpu(&ps->s_free_inodes_count, -1);
-- if (i < be32_to_cpu(ps->s_inodes_count)-1)
-+ if (i < be32_to_cpu(ps->s_inodes_count)-1)
- ps->s_free_inode_hint = cpu_to_be32(i+1);
- else
- ps->s_free_inode_hint = 0;
-@@ -567,46 +669,46 @@ struct inode *pram_new_inode(struct in
-
- unlock_super(sb);
-
-- return inode;
-+ return inode;
- fail2:
- unlock_super(sb);
-- inode->i_nlink = 0;
-+ clear_nlink(inode);
- unlock_new_inode(inode);
- iput(inode);
-- return ERR_PTR(errval);
-+ return ERR_PTR(errval);
- fail1:
- unlock_super(sb);
- make_bad_inode(inode);
- iput(inode);
-- return ERR_PTR(errval);
-+ return ERR_PTR(errval);
- }
-
--int pram_write_inode(struct inode *inode,struct writeback_control *wbc)
-+int pram_write_inode(struct inode *inode, struct writeback_control *wbc)
- {
-- return pram_update_inode(inode);
-+ return pram_update_inode(inode);
- }
-
- /*
- * dirty_inode() is called from __mark_inode_dirty()
- */
--void pram_dirty_inode(struct inode *inode,int flags)
-+void pram_dirty_inode(struct inode *inode, int flags)
- {
- pram_update_inode(inode);
- }
-
--static int pram_readpage(struct file *file,struct page *page)
-+static int pram_readpage(struct file *file, struct page *page)
- {
-- struct inode *inode = page->mapping->host;
-- struct super_block *sb = inode->i_sb;
-+ struct inode *inode = page->mapping->host;
-+ struct super_block *sb = inode->i_sb;
- loff_t offset, size;
-- unsigned long fillsize, blocknr, bytes_filled;
-+ unsigned long fillsize, blocknr, bytes_filled;
- u64 block;
-- void *buf, *bp;
-- int ret;
-+ void *buf, *bp;
-+ int ret;
-
- buf = kmap(page);
-- if (!buf)
-- return -ENOMEM;
-+ if (!buf)
-+ return -ENOMEM;
-
- offset = page_offset(page);
- size = i_size_read(inode);
-@@ -614,23 +716,23 @@ static int pram_readpage(struct file
- fillsize = 0;
- bytes_filled = 0;
- ret = 0;
-- if (offset < size) {
-+ if (offset < size) {
- size -= offset;
- fillsize = size > PAGE_SIZE ? PAGE_SIZE : size;
-- while (fillsize) {
-- int count = fillsize > sb->s_blocksize ?
-+ while (fillsize) {
-+ int count = fillsize > sb->s_blocksize ?
- sb->s_blocksize : fillsize;
- block = pram_find_data_block(inode, blocknr);
-- if (likely(block)) {
-+ if (likely(block)) {
- bp = pram_get_block(sb, block);
-- if (!bp) {
-+ if (!bp) {
- SetPageError(page);
- bytes_filled = 0;
- ret = -EIO;
-- goto out;
-+ goto out;
- }
- memcpy(buf + bytes_filled, bp, count);
-- }else {
-+ } else {
- memset(buf + bytes_filled, 0, count);
- }
- bytes_filled += count;
-@@ -639,33 +741,33 @@ static int pram_readpage(struct file
- }
- }
- out:
-- if (bytes_filled < PAGE_SIZE)
-+ if (bytes_filled < PAGE_SIZE)
- memset(buf + bytes_filled, 0, PAGE_SIZE - bytes_filled);
-- if (ret == 0)
-+ if (ret == 0)
- SetPageUptodate(page);
-
- flush_dcache_page(page);
- kunmap(page);
- unlock_page(page);
-- return ret;
-+ return ret;
- }
-
- /*
-- * Called to zeros out a single block. It's used in the"resize"
-- * to avoid to keep data incase the file grow up again.
-+ * Called to zeros out a single block. It's used in the "resize"
-+ * to avoid to keep data in case the file grow up again.
- */
--static int pram_block_truncate_page(struct inode *inode, loff_t newsize)
-+static int pram_block_truncate_page(struct inode *inode, loff_t newsize)
- {
-- struct super_block *sb = inode->i_sb;
-- unsigned long offset = newsize & (sb->s_blocksize - 1);
-- unsigned long blocknr, length;
-+ struct super_block *sb = inode->i_sb;
-+ unsigned long offset = newsize & (sb->s_blocksize - 1);
-+ unsigned long blocknr, length;
- u64 blockoff;
-- char *bp;
-- int ret = 0;
-+ char *bp;
-+ int ret = 0;
-
- /* Block boundary or extending ? */
-- if (!offset || newsize > inode->i_size)
-- goto out;
-+ if (!offset || newsize > inode->i_size)
-+ goto out;
-
- length = sb->s_blocksize - offset;
- blocknr = newsize >> sb->s_blocksize_bits;
-@@ -673,131 +775,131 @@ static int pram_block_truncate_page(st
- blockoff = pram_find_data_block(inode, blocknr);
-
- /* Hole ? */
-- if (!blockoff)
-- goto out;
-+ if (!blockoff)
-+ goto out;
-
- bp = pram_get_block(inode->i_sb, blockoff);
-- if (!bp) {
-+ if (!bp) {
- ret = -EACCES;
-- goto out;
-+ goto out;
- }
- pram_memunlock_block(sb, bp);
- memset(bp + offset, 0, length);
- pram_memlock_block(sb, bp);
- out:
-- return ret;
-+ return ret;
- }
-
--static int pram_setsize(struct inode *inode, loff_t newsize)
-+static int pram_setsize(struct inode *inode, loff_t newsize)
- {
-- int ret = 0;
-+ int ret = 0;
- loff_t oldsize = inode->i_size;
-
-- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
-- return -EINVAL;
-- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-- return -EPERM;
-+ return -EINVAL;
-+ if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-+ return -EPERM;
-
-- if (newsize != oldsize) {
-- if (mapping_is_xip(inode->i_mapping))
-+ if (newsize != oldsize) {
-+ if (mapping_is_xip(inode->i_mapping))
- ret = xip_truncate_page(inode->i_mapping, newsize);
- else
- ret = pram_block_truncate_page(inode, newsize);
-
-- if (ret)
-- return ret;
-+ if (ret)
-+ return ret;
- i_size_write(inode, newsize);
- }
- /*
-- * Waitfor any concurrent readers to finish before to truncate the
-- * blocks. Anynew reader will see thenew i_size so no problem.
-- * In addition we have to wait, in xipcase, the call of xip_file_fault.
-+ * Wait for any concurrent readers to finish before to truncate the
-+ * blocks. Any new reader will see the new i_size so no problem.
-+ * In addition we have to wait, in xip case, the call of xip_file_fault.
- */
- synchronize_rcu();
- truncate_pagecache(inode, oldsize, newsize);
- __pram_truncate_blocks(inode, newsize, oldsize);
-- /* Checkfor the flag EOFBLOCKS is still valid after the set size */
-+ /* Check for the flag EOFBLOCKS is still valid after the set size */
- check_eof_blocks(inode, newsize);
- inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
- pram_update_inode(inode);
-
-- return ret;
-+ return ret;
- }
-
--int pram_notify_change(struct dentry *dentry,struct iattr *attr)
-+int pram_notify_change(struct dentry *dentry, struct iattr *attr)
- {
-- struct inode *inode = dentry->d_inode;
-- struct pram_inode *pi = pram_get_inode(inode->i_sb, inode->i_ino);
-- int error;
-+ struct inode *inode = dentry->d_inode;
-+ struct pram_inode *pi = pram_get_inode(inode->i_sb, inode->i_ino);
-+ int error;
-
-- if (!pi)
-- return -EACCES;
-+ if (!pi)
-+ return -EACCES;
-
- error = inode_change_ok(inode, attr);
-- if (error)
-- return error;
-+ if (error)
-+ return error;
-
-- if (attr->ia_valid & ATTR_SIZE &&
-+ if (attr->ia_valid & ATTR_SIZE &&
- (attr->ia_size != inode->i_size ||
- pi->i_flags & cpu_to_be32(PRAM_EOFBLOCKS_FL))) {
- error = pram_setsize(inode, attr->ia_size);
-- if (error)
-- return error;
-+ if (error)
-+ return error;
- }
- setattr_copy(inode, attr);
-- if (attr->ia_valid & ATTR_MODE)
-+ if (attr->ia_valid & ATTR_MODE)
- error = pram_acl_chmod(inode);
- error = pram_update_inode(inode);
-
-- return error;
-+ return error;
- }
-
--void pram_set_inode_flags(struct inode *inode,struct pram_inode *pi)
-+void pram_set_inode_flags(struct inode *inode, struct pram_inode *pi)
- {
-- unsigned int flags = be32_to_cpu(pi->i_flags);
-+ unsigned int flags = be32_to_cpu(pi->i_flags);
-
- inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
-- if (flags & FS_SYNC_FL)
-+ if (flags & FS_SYNC_FL)
- inode->i_flags |= S_SYNC;
-- if (flags & FS_APPEND_FL)
-+ if (flags & FS_APPEND_FL)
- inode->i_flags |= S_APPEND;
-- if (flags & FS_IMMUTABLE_FL)
-+ if (flags & FS_IMMUTABLE_FL)
- inode->i_flags |= S_IMMUTABLE;
-- if (flags & FS_NOATIME_FL)
-+ if (flags & FS_NOATIME_FL)
- inode->i_flags |= S_NOATIME;
-- if (flags & FS_DIRSYNC_FL)
-+ if (flags & FS_DIRSYNC_FL)
- inode->i_flags |= S_DIRSYNC;
-- if (!pi->i_xattr)
-+ if (!pi->i_xattr)
- inode_has_no_xattr(inode);
- }
-
--void pram_get_inode_flags(struct inode *inode,struct pram_inode *pi)
-+void pram_get_inode_flags(struct inode *inode, struct pram_inode *pi)
- {
-- unsigned int flags = inode->i_flags;
-- unsigned int pram_flags = be32_to_cpu(pi->i_flags);
-+ unsigned int flags = inode->i_flags;
-+ unsigned int pram_flags = be32_to_cpu(pi->i_flags);
-
- pram_flags &= ~(FS_SYNC_FL|FS_APPEND_FL|FS_IMMUTABLE_FL|
- FS_NOATIME_FL|FS_DIRSYNC_FL);
-- if (flags & S_SYNC)
-+ if (flags & S_SYNC)
- pram_flags |= FS_SYNC_FL;
-- if (flags & S_APPEND)
-+ if (flags & S_APPEND)
- pram_flags |= FS_APPEND_FL;
-- if (flags & S_IMMUTABLE)
-+ if (flags & S_IMMUTABLE)
- pram_flags |= FS_IMMUTABLE_FL;
-- if (flags & S_NOATIME)
-+ if (flags & S_NOATIME)
- pram_flags |= FS_NOATIME_FL;
-- if (flags & S_DIRSYNC)
-+ if (flags & S_DIRSYNC)
- pram_flags |= FS_DIRSYNC_FL;
-
- pi->i_flags = cpu_to_be32(pram_flags);
- }
-
--const struct address_space_operations pram_aops = {
-+const struct address_space_operations pram_aops = {
- .readpage = pram_readpage,
- .direct_IO = pram_direct_IO,
- };
-
--const struct address_space_operations pram_aops_xip = {
-+const struct address_space_operations pram_aops_xip = {
- .get_xip_mem = pram_get_xip_mem,
- };
---- a/fs/pramfs/ioctl.c
-+++ b/fs/pramfs/ioctl.c
-@@ -35,7 +35,7 @@ long pram_ioctl(struct file *filp, unsig
- case FS_IOC_SETFLAGS: {
- unsigned int oldflags;
-
-- ret = mnt_want_write(filp->f_path.mnt);
-+ ret = mnt_want_write_file(filp);
- if (ret)
- return ret;
-
-@@ -73,25 +73,31 @@ long pram_ioctl(struct file *filp, unsig
- pram_memlock_inode(inode->i_sb, pi);
- mutex_unlock(&inode->i_mutex);
- flags_out:
-- mnt_drop_write(filp->f_path.mnt);
-+ mnt_drop_write_file(filp);
- return ret;
- }
- case FS_IOC_GETVERSION:
- return put_user(inode->i_generation, (int __user *) arg);
-- case FS_IOC_SETVERSION:
-+ case FS_IOC_SETVERSION: {
-+ __u32 generation;
- if (!inode_owner_or_capable(inode))
- return -EPERM;
-- ret = mnt_want_write(filp->f_path.mnt);
-+ ret = mnt_want_write_file(filp);
- if (ret)
- return ret;
-- if (get_user(inode->i_generation, (int __user *) arg)) {
-+ if (get_user(generation, (int __user *) arg)) {
- ret = -EFAULT;
-- } else {
-- inode->i_ctime = CURRENT_TIME_SEC;
-- pram_update_inode(inode);
-+ goto setversion_out;
- }
-- mnt_drop_write(filp->f_path.mnt);
-+ mutex_lock(&inode->i_mutex);
-+ inode->i_ctime = CURRENT_TIME_SEC;
-+ inode->i_generation = generation;
-+ pram_update_inode(inode);
-+ mutex_unlock(&inode->i_mutex);
-+setversion_out:
-+ mnt_drop_write_file(filp);
- return ret;
-+ }
- default:
- return -ENOTTY;
- }
---- a/fs/pramfs/namei.c
-+++ b/fs/pramfs/namei.c
-@@ -24,14 +24,14 @@
-
- static inline void pram_inc_count(struct inode *inode)
- {
-- inode->i_nlink++;
-+ inc_nlink(inode);
- pram_write_inode(inode, NULL);
- }
-
- static inline void pram_dec_count(struct inode *inode)
- {
- if (inode->i_nlink) {
-- inode->i_nlink--;
-+ drop_nlink(inode);
- pram_write_inode(inode, NULL);
- }
- }
-@@ -115,7 +115,7 @@ static struct dentry *pram_lookup(struct
- * If the create succeeds, we fill in the inode information
- * with d_instantiate().
- */
--static int pram_create(struct inode *dir, struct dentry *dentry, int mode,
-+static int pram_create(struct inode *dir, struct dentry *dentry, umode_t mode,
- struct nameidata *nd)
- {
- struct inode *inode = pram_new_inode(dir, mode, &dentry->d_name);
-@@ -134,7 +134,7 @@ static int pram_create(struct inode *dir
- return err;
- }
-
--static int pram_mknod(struct inode *dir, struct dentry *dentry, int mode,
-+static int pram_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
- dev_t rdev)
- {
- struct inode *inode = pram_new_inode(dir, mode, &dentry->d_name);
-@@ -200,14 +200,11 @@ static int pram_unlink(struct inode *dir
- return 0;
- }
-
--static int pram_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-+static int pram_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
- {
- struct inode *inode;
- struct pram_inode *pi;
-- int err = -EMLINK;
--
-- if (dir->i_nlink >= PRAM_LINK_MAX)
-- goto out;
-+ int err = 0;
-
- pram_inc_count(dir);
-
-@@ -262,7 +259,7 @@ static int pram_rmdir(struct inode *dir,
- if (pi->i_type.dir.tail == 0) {
- inode->i_ctime = dir->i_ctime;
- inode->i_size = 0;
-- inode->i_nlink = 0;
-+ clear_nlink(inode);
- pram_write_inode(inode, NULL);
- pram_dec_count(dir);
- err = 0;
-@@ -297,9 +294,6 @@ static int pram_rename(struct inode *ol
- pram_dec_count(new_inode);
- } else {
- if (S_ISDIR(old_inode->i_mode)) {
-- err = -EMLINK;
-- if (new_dir->i_nlink >= PRAM_LINK_MAX)
-- goto out;
- pram_dec_count(old_dir);
- pram_inc_count(new_dir);
- }
-@@ -361,7 +355,7 @@ const struct inode_operations pram_dir_i
- .removexattr = generic_removexattr,
- #endif
- .setattr = pram_notify_change,
-- .check_acl = pram_check_acl,
-+ .get_acl = pram_get_acl,
- };
-
- const struct inode_operations pram_special_inode_operations = {
-@@ -372,5 +366,5 @@ const struct inode_operations pram_speci
- .removexattr = generic_removexattr,
- #endif
- .setattr = pram_notify_change,
-- .check_acl = pram_check_acl,
-+ .get_acl = pram_get_acl,
- };
---- a/fs/pramfs/pram.h
-+++ b/fs/pramfs/pram.h
-@@ -52,9 +52,8 @@
- #define PRAM_EOFBLOCKS_FL 0x20000000
- /* Flags that should be inherited by new inodes from their parent. */
- #define PRAM_FL_INHERITED (FS_SECRM_FL | FS_UNRM_FL | FS_COMPR_FL |\
-- FS_SYNC_FL | FS_IMMUTABLE_FL | FS_APPEND_FL |\
-- FS_NODUMP_FL | FS_NOATIME_FL | FS_COMPRBLK_FL |\
-- FS_NOCOMP_FL | FS_JOURNAL_DATA_FL |\
-+ FS_SYNC_FL | FS_NODUMP_FL | FS_NOATIME_FL | \
-+ FS_COMPRBLK_FL | FS_NOCOMP_FL | FS_JOURNAL_DATA_FL |\
- FS_NOTAIL_FL | FS_DIRSYNC_FL)
- /* Flags that are appropriate for regular files (all but dir-specific ones). */
- #define PRAM_REG_FLMASK (~(FS_DIRSYNC_FL | FS_TOPDIR_FL))
-@@ -94,7 +93,7 @@ extern u64 pram_find_data_block(struct i
- extern struct inode *pram_iget(struct super_block *sb, unsigned long ino);
- extern void pram_put_inode(struct inode *inode);
- extern void pram_evict_inode(struct inode *inode);
--extern struct inode *pram_new_inode(struct inode *dir, int mode,
-+extern struct inode *pram_new_inode(struct inode *dir, umode_t mode,
- const struct qstr *qstr);
- extern int pram_update_inode(struct inode *inode);
- extern int pram_write_inode(struct inode *inode, struct writeback_control *wbc);
-@@ -102,6 +101,7 @@ extern void pram_dirty_inode(struct inod
- extern int pram_notify_change(struct dentry *dentry, struct iattr *attr);
- extern void pram_set_inode_flags(struct inode *inode, struct pram_inode *pi);
- extern void pram_get_inode_flags(struct inode *inode, struct pram_inode *pi);
-+extern int pram_find_region(struct inode *inode, loff_t *offset, int hole);
-
- /* ioctl.c */
- extern long pram_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
---- a/fs/pramfs/super.c
-+++ b/fs/pramfs/super.c
-@@ -454,7 +454,9 @@ static struct pram_inode *pram_init(stru
-
- static inline void set_default_opts(struct pram_sb_info *sbi)
- {
-+#ifdef CONFIG_PRAMFS_WRITE_PROTECT
- set_opt(sbi->s_mount_opt, PROTECT);
-+#endif
- set_opt(sbi->s_mount_opt, ERRORS_CONT);
- }
-
-@@ -471,7 +473,7 @@ static void pram_root_check(struct super
- pram_warn("root is not a directory, trying to fix\n");
- goto fail2;
- }
--
-+
- if (pram_calc_checksum((u8 *)root_pi, PRAM_INODE_SIZE)) {
- pram_warn("checksum error in root inode, trying to fix\n");
- goto fail3;
-@@ -633,6 +635,7 @@ static int pram_fill_super(struct super_
- sb->s_magic = be16_to_cpu(super->s_magic);
- sb->s_op = &pram_sops;
- sb->s_maxbytes = pram_max_size(sb->s_blocksize_bits);
-+ sb->s_max_links = PRAM_LINK_MAX;
- sb->s_time_gran = 1;
- sb->s_export_op = &pram_export_ops;
- sb->s_xattr = pram_xattr_handlers;
-@@ -647,10 +650,9 @@ static int pram_fill_super(struct super_
- retval = PTR_ERR(root_i);
- goto out;
- }
--
-- sb->s_root = d_alloc_root(root_i);
-+
-+ sb->s_root = d_make_root(root_i);
- if (!sb->s_root) {
-- iput(root_i);
- printk(KERN_ERR "get pramfs root inode failed\n");
- retval = -ENOMEM;
- goto out;
-@@ -685,9 +687,9 @@ int pram_statfs(struct dentry *d, struct
- return 0;
- }
-
--static int pram_show_options(struct seq_file *seq, struct vfsmount *vfs)
-+static int pram_show_options(struct seq_file *seq, struct dentry *root)
- {
-- struct pram_sb_info *sbi = PRAM_SB(vfs->mnt_sb);
-+ struct pram_sb_info *sbi = PRAM_SB(root->d_sb);
-
- seq_printf(seq, ",physaddr=0x%016llx", (u64)sbi->phys_addr);
- if (sbi->initsize)
-@@ -704,13 +706,13 @@ static int pram_show_options(struct seq_
- seq_printf(seq, ",uid=%u", sbi->uid);
- if (sbi->gid != 0)
- seq_printf(seq, ",gid=%u", sbi->gid);
-- if (test_opt(vfs->mnt_sb, ERRORS_RO))
-+ if (test_opt(root->d_sb, ERRORS_RO))
- seq_puts(seq, ",errors=remount-ro");
-- if (test_opt(vfs->mnt_sb, ERRORS_PANIC))
-+ if (test_opt(root->d_sb, ERRORS_PANIC))
- seq_puts(seq, ",errors=panic");
- #ifdef CONFIG_PRAMFS_WRITE_PROTECT
- /* memory protection enabled by default */
-- if (!test_opt(vfs->mnt_sb, PROTECT))
-+ if (!test_opt(root->d_sb, PROTECT))
- seq_puts(seq, ",noprotect");
- #else
- /*
-@@ -722,19 +724,19 @@ static int pram_show_options(struct seq_
-
- #ifdef CONFIG_PRAMFS_XATTR
- /* user xattr not enabled by default */
-- if (test_opt(vfs->mnt_sb, XATTR_USER))
-+ if (test_opt(root->d_sb, XATTR_USER))
- seq_puts(seq, ",user_xattr");
- #endif
-
- #ifdef CONFIG_PRAMFS_POSIX_ACL
- /* acl not enabled by default */
-- if (test_opt(vfs->mnt_sb, POSIX_ACL))
-+ if (test_opt(root->d_sb, POSIX_ACL))
- seq_puts(seq, ",acl");
- #endif
-
- #ifdef CONFIG_PRAMFS_XIP
- /* xip not enabled by default */
-- if (test_opt(vfs->mnt_sb, XIP))
-+ if (test_opt(root->d_sb, XIP))
- seq_puts(seq, ",xip");
- #endif
-
-@@ -817,7 +819,6 @@ static struct inode *pram_alloc_inode(st
- static void pram_i_callback(struct rcu_head *head)
- {
- struct inode *inode = container_of(head, struct inode, i_rcu);
-- INIT_LIST_HEAD(&inode->i_dentry);
- kmem_cache_free(pram_inode_cachep, PRAM_I(inode));
- }
-
---- a/fs/pramfs/xattr_security.c
-+++ b/fs/pramfs/xattr_security.c
-@@ -50,27 +50,28 @@ static int pram_xattr_security_set(struc
- value, size, flags);
- }
-
--int pram_init_security(struct inode *inode, struct inode *dir,
-- const struct qstr *qstr)
-+int pram_initxattrs(struct inode *inode, const struct xattr *xattr_array,
-+ void *fs_info)
- {
-- int err;
-- size_t len;
-- void *value;
-- char *name;
--
-- err = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
-- if (err) {
-- if (err == -EOPNOTSUPP)
-- return 0;
-- return err;
-+ const struct xattr *xattr;
-+ int err = 0;
-+ for (xattr = xattr_array; xattr->name != NULL; xattr++) {
-+ err = pram_xattr_set(inode, PRAM_XATTR_INDEX_SECURITY,
-+ xattr->name, xattr->value,
-+ xattr->value_len, 0);
-+ if (err < 0)
-+ break;
- }
-- err = pram_xattr_set(inode, PRAM_XATTR_INDEX_SECURITY,
-- name, value, len, 0);
-- kfree(name);
-- kfree(value);
- return err;
- }
-
-+int pram_init_security(struct inode *inode, struct inode *dir,
-+ const struct qstr *qstr)
-+{
-+ return security_inode_init_security(inode, dir, qstr,
-+ &pram_initxattrs, NULL);
-+}
-+
- const struct xattr_handler pram_xattr_security_handler = {
- .prefix = XATTR_SECURITY_PREFIX,
- .list = pram_xattr_security_list,
---- a/include/linux/pram_fs_sb.h
-+++ b/include/linux/pram_fs_sb.h
-@@ -34,7 +34,7 @@ struct pram_sb_info {
- unsigned long s_mount_opt;
- uid_t uid; /* Mount uid for root directory */
- gid_t gid; /* Mount gid for root directory */
-- mode_t mode; /* Mount mode for root directory */
-+ umode_t mode; /* Mount mode for root directory */
- atomic_t next_generation;
- #ifdef CONFIG_PRAMFS_XATTR
- struct rb_root desc_tree;
+++ /dev/null
-From dhobsong@igel.co.jp Wed Nov 21 18:27:13 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Thu, 22 Nov 2012 11:26:48 +0900
-Subject: [PATCH 1/6] drivers: uio: Add new uio device for dynamic memory allocation
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Message-ID: <1353551213-17996-2-git-send-email-dhobsong@igel.co.jp>
-
-
-This device extends the uio_pdrv_genirq driver to provide limited
-dynamic memory allocation for UIO devices. This allows UIO devices
-to use CMA and IOMMU allocated memory regions. This driver is based
-on the uio_pdrv_genirq driver and provides the same generic interrupt
-handling capabilities. Like uio_prdv_genirq,
-a fixed number of memory regions, defined in the platform device's
-.resources field are exported to userpace. This driver adds the ability
-to export additional regions whose number and size are known at boot time,
-but whose memory is not allocated until the uio device file is opened for
-the first time. When the device file is closed, the allocated memory block
-is freed. Physical (DMA) addresses for the dynamic regions are provided to
-the userspace via /sys/class/uio/uioX/maps/mapY/addr in the same way as
-static addresses are when the uio device file is open, when no processes
-are holding the device file open, the address returned to userspace is
-DMA_ERROR_CODE.
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- drivers/uio/Kconfig | 16 +
- drivers/uio/Makefile | 1
- drivers/uio/uio_dmem_genirq.c | 354 ++++++++++++++++++++++++++
- include/linux/platform_data/uio_dmem_genirq.h | 26 +
- 4 files changed, 397 insertions(+)
- create mode 100644 drivers/uio/uio_dmem_genirq.c
- create mode 100644 include/linux/platform_data/uio_dmem_genirq.h
-
---- a/drivers/uio/Kconfig
-+++ b/drivers/uio/Kconfig
-@@ -44,6 +44,22 @@ config UIO_PDRV_GENIRQ
-
- If you don't know what to do here, say N.
-
-+config UIO_DMEM_GENIRQ
-+ tristate "Userspace platform driver with generic irq and dynamic memory"
-+ help
-+ Platform driver for Userspace I/O devices, including generic
-+ interrupt handling code. Shared interrupts are not supported.
-+
-+ Memory regions can be specified with the same platform device
-+ resources as the UIO_PDRV drivers, but dynamic regions can also
-+ be specified.
-+ The number and size of these regions is static,
-+ but the memory allocation is not performed until
-+ the associated device file is opened. The
-+ memory is freed once the uio device is closed.
-+
-+ If you don't know what to do here, say N.
-+
- config UIO_AEC
- tristate "AEC video timestamp device"
- depends on PCI
---- a/drivers/uio/Makefile
-+++ b/drivers/uio/Makefile
-@@ -2,6 +2,7 @@ obj-$(CONFIG_UIO) += uio.o
- obj-$(CONFIG_UIO_CIF) += uio_cif.o
- obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o
- obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o
-+obj-$(CONFIG_UIO_DMEM_GENIRQ) += uio_dmem_genirq.o
- obj-$(CONFIG_UIO_AEC) += uio_aec.o
- obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
- obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o
---- /dev/null
-+++ b/drivers/uio/uio_dmem_genirq.c
-@@ -0,0 +1,354 @@
-+/*
-+ * drivers/uio/uio_dmem_genirq.c
-+ *
-+ * Userspace I/O platform driver with generic IRQ handling code.
-+ *
-+ * Copyright (C) 2012 Damian Hobson-Garcia
-+ *
-+ * Based on uio_pdrv_genirq.c by Magnus Damm
-+ *
-+ * 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/platform_device.h>
-+#include <linux/uio_driver.h>
-+#include <linux/spinlock.h>
-+#include <linux/bitops.h>
-+#include <linux/module.h>
-+#include <linux/interrupt.h>
-+#include <linux/platform_data/uio_dmem_genirq.h>
-+#include <linux/stringify.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/slab.h>
-+
-+#include <linux/of.h>
-+#include <linux/of_platform.h>
-+#include <linux/of_address.h>
-+
-+#define DRIVER_NAME "uio_dmem_genirq"
-+
-+struct uio_dmem_genirq_platdata {
-+ struct uio_info *uioinfo;
-+ spinlock_t lock;
-+ unsigned long flags;
-+ struct platform_device *pdev;
-+ unsigned int dmem_region_start;
-+ unsigned int num_dmem_regions;
-+ struct mutex alloc_lock;
-+ unsigned int refcnt;
-+};
-+
-+static int uio_dmem_genirq_open(struct uio_info *info, struct inode *inode)
-+{
-+ struct uio_dmem_genirq_platdata *priv = info->priv;
-+ struct uio_mem *uiomem;
-+ int ret = 0;
-+
-+ uiomem = &priv->uioinfo->mem[priv->dmem_region_start];
-+
-+ mutex_lock(&priv->alloc_lock);
-+ while (!priv->refcnt && uiomem < &priv->uioinfo->mem[MAX_UIO_MAPS]) {
-+ void *addr;
-+ if (!uiomem->size)
-+ break;
-+
-+ addr = dma_alloc_coherent(&priv->pdev->dev, uiomem->size,
-+ (dma_addr_t *)&uiomem->addr, GFP_KERNEL);
-+ if (!addr) {
-+ ret = -ENOMEM;
-+ break;
-+ }
-+
-+ uiomem->internal_addr = addr;
-+ ++uiomem;
-+ }
-+ priv->refcnt++;
-+
-+ mutex_unlock(&priv->alloc_lock);
-+ /* Wait until the Runtime PM code has woken up the device */
-+ pm_runtime_get_sync(&priv->pdev->dev);
-+ return ret;
-+}
-+
-+static int uio_dmem_genirq_release(struct uio_info *info, struct inode *inode)
-+{
-+ struct uio_dmem_genirq_platdata *priv = info->priv;
-+ struct uio_mem *uiomem;
-+
-+ /* Tell the Runtime PM code that the device has become idle */
-+ pm_runtime_put_sync(&priv->pdev->dev);
-+
-+ uiomem = &priv->uioinfo->mem[priv->dmem_region_start];
-+
-+ mutex_lock(&priv->alloc_lock);
-+
-+ priv->refcnt--;
-+ while (!priv->refcnt && uiomem < &priv->uioinfo->mem[MAX_UIO_MAPS]) {
-+ if (!uiomem->size)
-+ break;
-+
-+ dma_free_coherent(&priv->pdev->dev, uiomem->size,
-+ uiomem->internal_addr, uiomem->addr);
-+ uiomem->addr = DMA_ERROR_CODE;
-+ ++uiomem;
-+ }
-+
-+ mutex_unlock(&priv->alloc_lock);
-+ return 0;
-+}
-+
-+static irqreturn_t uio_dmem_genirq_handler(int irq, struct uio_info *dev_info)
-+{
-+ struct uio_dmem_genirq_platdata *priv = dev_info->priv;
-+
-+ /* Just disable the interrupt in the interrupt controller, and
-+ * remember the state so we can allow user space to enable it later.
-+ */
-+
-+ if (!test_and_set_bit(0, &priv->flags))
-+ disable_irq_nosync(irq);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on)
-+{
-+ struct uio_dmem_genirq_platdata *priv = dev_info->priv;
-+ unsigned long flags;
-+
-+ /* Allow user space to enable and disable the interrupt
-+ * in the interrupt controller, but keep track of the
-+ * state to prevent per-irq depth damage.
-+ *
-+ * Serialize this operation to support multiple tasks.
-+ */
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+ if (irq_on) {
-+ if (test_and_clear_bit(0, &priv->flags))
-+ enable_irq(dev_info->irq);
-+ } else {
-+ if (!test_and_set_bit(0, &priv->flags))
-+ disable_irq(dev_info->irq);
-+ }
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ return 0;
-+}
-+
-+static int uio_dmem_genirq_probe(struct platform_device *pdev)
-+{
-+ struct uio_dmem_genirq_pdata *pdata = pdev->dev.platform_data;
-+ struct uio_info *uioinfo = &pdata->uioinfo;
-+ struct uio_dmem_genirq_platdata *priv;
-+ struct uio_mem *uiomem;
-+ int ret = -EINVAL;
-+ int i;
-+
-+ if (!uioinfo) {
-+ int irq;
-+
-+ /* alloc uioinfo for one device */
-+ uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL);
-+ if (!uioinfo) {
-+ ret = -ENOMEM;
-+ dev_err(&pdev->dev, "unable to kmalloc\n");
-+ goto bad2;
-+ }
-+ uioinfo->name = pdev->dev.of_node->name;
-+ uioinfo->version = "devicetree";
-+
-+ /* Multiple IRQs are not supported */
-+ irq = platform_get_irq(pdev, 0);
-+ if (irq == -ENXIO)
-+ uioinfo->irq = UIO_IRQ_NONE;
-+ else
-+ uioinfo->irq = irq;
-+ }
-+
-+ if (!uioinfo || !uioinfo->name || !uioinfo->version) {
-+ dev_err(&pdev->dev, "missing platform_data\n");
-+ goto bad0;
-+ }
-+
-+ if (uioinfo->handler || uioinfo->irqcontrol ||
-+ uioinfo->irq_flags & IRQF_SHARED) {
-+ dev_err(&pdev->dev, "interrupt configuration error\n");
-+ goto bad0;
-+ }
-+
-+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-+ if (!priv) {
-+ ret = -ENOMEM;
-+ dev_err(&pdev->dev, "unable to kmalloc\n");
-+ goto bad0;
-+ }
-+
-+ dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
-+
-+ priv->uioinfo = uioinfo;
-+ spin_lock_init(&priv->lock);
-+ priv->flags = 0; /* interrupt is enabled to begin with */
-+ priv->pdev = pdev;
-+ mutex_init(&priv->alloc_lock);
-+
-+ if (!uioinfo->irq) {
-+ ret = platform_get_irq(pdev, 0);
-+ if (ret < 0) {
-+ dev_err(&pdev->dev, "failed to get IRQ\n");
-+ goto bad0;
-+ }
-+ uioinfo->irq = ret;
-+ }
-+ uiomem = &uioinfo->mem[0];
-+
-+ for (i = 0; i < pdev->num_resources; ++i) {
-+ struct resource *r = &pdev->resource[i];
-+
-+ if (r->flags != IORESOURCE_MEM)
-+ continue;
-+
-+ if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
-+ dev_warn(&pdev->dev, "device has more than "
-+ __stringify(MAX_UIO_MAPS)
-+ " I/O memory resources.\n");
-+ break;
-+ }
-+
-+ uiomem->memtype = UIO_MEM_PHYS;
-+ uiomem->addr = r->start;
-+ uiomem->size = resource_size(r);
-+ ++uiomem;
-+ }
-+
-+ priv->dmem_region_start = i;
-+ priv->num_dmem_regions = pdata->num_dynamic_regions;
-+
-+ for (i = 0; i < pdata->num_dynamic_regions; ++i) {
-+ if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
-+ dev_warn(&pdev->dev, "device has more than "
-+ __stringify(MAX_UIO_MAPS)
-+ " dynamic and fixed memory regions.\n");
-+ break;
-+ }
-+ uiomem->memtype = UIO_MEM_PHYS;
-+ uiomem->addr = DMA_ERROR_CODE;
-+ uiomem->size = pdata->dynamic_region_sizes[i];
-+ ++uiomem;
-+ }
-+
-+ while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) {
-+ uiomem->size = 0;
-+ ++uiomem;
-+ }
-+
-+ /* This driver requires no hardware specific kernel code to handle
-+ * interrupts. Instead, the interrupt handler simply disables the
-+ * interrupt in the interrupt controller. User space is responsible
-+ * for performing hardware specific acknowledge and re-enabling of
-+ * the interrupt in the interrupt controller.
-+ *
-+ * Interrupt sharing is not supported.
-+ */
-+
-+ uioinfo->handler = uio_dmem_genirq_handler;
-+ uioinfo->irqcontrol = uio_dmem_genirq_irqcontrol;
-+ uioinfo->open = uio_dmem_genirq_open;
-+ uioinfo->release = uio_dmem_genirq_release;
-+ uioinfo->priv = priv;
-+
-+ /* Enable Runtime PM for this device:
-+ * The device starts in suspended state to allow the hardware to be
-+ * turned off by default. The Runtime PM bus code should power on the
-+ * hardware and enable clocks at open().
-+ */
-+ pm_runtime_enable(&pdev->dev);
-+
-+ ret = uio_register_device(&pdev->dev, priv->uioinfo);
-+ if (ret) {
-+ dev_err(&pdev->dev, "unable to register uio device\n");
-+ goto bad1;
-+ }
-+
-+ platform_set_drvdata(pdev, priv);
-+ return 0;
-+ bad1:
-+ kfree(priv);
-+ pm_runtime_disable(&pdev->dev);
-+ bad0:
-+ /* kfree uioinfo for OF */
-+ if (pdev->dev.of_node)
-+ kfree(uioinfo);
-+ bad2:
-+ return ret;
-+}
-+
-+static int uio_dmem_genirq_remove(struct platform_device *pdev)
-+{
-+ struct uio_dmem_genirq_platdata *priv = platform_get_drvdata(pdev);
-+
-+ uio_unregister_device(priv->uioinfo);
-+ pm_runtime_disable(&pdev->dev);
-+
-+ priv->uioinfo->handler = NULL;
-+ priv->uioinfo->irqcontrol = NULL;
-+
-+ /* kfree uioinfo for OF */
-+ if (pdev->dev.of_node)
-+ kfree(priv->uioinfo);
-+
-+ kfree(priv);
-+ return 0;
-+}
-+
-+static int uio_dmem_genirq_runtime_nop(struct device *dev)
-+{
-+ /* Runtime PM callback shared between ->runtime_suspend()
-+ * and ->runtime_resume(). Simply returns success.
-+ *
-+ * In this driver pm_runtime_get_sync() and pm_runtime_put_sync()
-+ * are used at open() and release() time. This allows the
-+ * Runtime PM code to turn off power to the device while the
-+ * device is unused, ie before open() and after release().
-+ *
-+ * This Runtime PM callback does not need to save or restore
-+ * any registers since user space is responsbile for hardware
-+ * register reinitialization after open().
-+ */
-+ return 0;
-+}
-+
-+static const struct dev_pm_ops uio_dmem_genirq_dev_pm_ops = {
-+ .runtime_suspend = uio_dmem_genirq_runtime_nop,
-+ .runtime_resume = uio_dmem_genirq_runtime_nop,
-+};
-+
-+#ifdef CONFIG_OF
-+static const struct of_device_id uio_of_genirq_match[] = {
-+ { /* empty for now */ },
-+};
-+MODULE_DEVICE_TABLE(of, uio_of_genirq_match);
-+#else
-+# define uio_of_genirq_match NULL
-+#endif
-+
-+static struct platform_driver uio_dmem_genirq = {
-+ .probe = uio_dmem_genirq_probe,
-+ .remove = uio_dmem_genirq_remove,
-+ .driver = {
-+ .name = DRIVER_NAME,
-+ .owner = THIS_MODULE,
-+ .pm = &uio_dmem_genirq_dev_pm_ops,
-+ .of_match_table = uio_of_genirq_match,
-+ },
-+};
-+
-+module_platform_driver(uio_dmem_genirq);
-+
-+MODULE_AUTHOR("Damian Hobson-Garcia");
-+MODULE_DESCRIPTION("Userspace I/O platform driver with dynamic memory.");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:" DRIVER_NAME);
---- /dev/null
-+++ b/include/linux/platform_data/uio_dmem_genirq.h
-@@ -0,0 +1,26 @@
-+/*
-+ * include/linux/platform_data/uio_dmem_genirq.h
-+ *
-+ * Copyright (C) 2012 Damian Hobson-Garcia
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation version 2.
-+ *
-+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
-+ * kind, whether express or implied; without even the implied warranty
-+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _UIO_DMEM_GENIRQ_H
-+#define _UIO_DMEM_GENIRQ_H
-+
-+#include <linux/uio_driver.h>
-+
-+struct uio_dmem_genirq_pdata {
-+ struct uio_info uioinfo;
-+ unsigned int *dynamic_region_sizes;
-+ unsigned int num_dynamic_regions;
-+};
-+#endif /* _UIO_DMEM_GENIRQ_H */
+++ /dev/null
-From dhobsong@igel.co.jp Wed Nov 21 18:27:15 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Thu, 22 Nov 2012 11:26:49 +0900
-Subject: [PATCH 2/6] drivers: uio: Add uio_dmem_genirq description to UIO documentation
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Message-ID: <1353551213-17996-3-git-send-email-dhobsong@igel.co.jp>
-
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- Documentation/DocBook/uio-howto.tmpl | 56 +++++++++++++++++++++++++++++++++++
- 1 file changed, 56 insertions(+)
-
---- a/Documentation/DocBook/uio-howto.tmpl
-+++ b/Documentation/DocBook/uio-howto.tmpl
-@@ -719,6 +719,62 @@ framework to set up sysfs files for this
- </para>
- </sect1>
-
-+<sect1 id="using uio_dmem_genirq">
-+<title>Using uio_dmem_genirq for platform devices</title>
-+ <para>
-+ In addition to statically allocated memory ranges, they may also be
-+ a desire to use dynamically allocated regions in a user space driver.
-+ In particular, being able to access memory made available through the
-+ dma-mapping API, may be particularly useful. The
-+ <varname>uio_dmem_genirq</varname> driver provides a way to accomplish
-+ this.
-+ </para>
-+ <para>
-+ This driver is used in a similar manner to the
-+ <varname>"uio_pdrv_genirq"</varname> driver with respect to interrupt
-+ configuration and handling.
-+ </para>
-+ <para>
-+ Set the <varname>.name</varname> element of
-+ <varname>struct platform_device</varname> to
-+ <varname>"uio_dmem_genirq"</varname> to use this driver.
-+ </para>
-+ <para>
-+ When using this driver, fill in the <varname>.platform_data</varname>
-+ element of <varname>struct platform_device</varname>, which is of type
-+ <varname>struct uio_dmem_genirq_pdata</varname> and which contains the
-+ following elements:
-+ </para>
-+ <itemizedlist>
-+ <listitem><varname>struct uio_info uioinfo</varname>: The same
-+ structure used as the <varname>uio_pdrv_genirq</varname> platform
-+ data</listitem>
-+ <listitem><varname>unsigned int *dynamic_region_sizes</varname>:
-+ Pointer to list of sizes of dynamic memory regions to be mapped into
-+ user space.
-+ </listitem>
-+ <listitem><varname>unsigned int num_dynamic_regions</varname>:
-+ Number of elements in <varname>dynamic_region_sizes</varname> array.
-+ </listitem>
-+ </itemizedlist>
-+ <para>
-+ The dynamic regions defined in the platform data will be appended to
-+ the <varname> mem[] </varname> array after the platform device
-+ resources, which implies that the total number of static and dynamic
-+ memory regions cannot exceed <varname>MAX_UIO_MAPS</varname>.
-+ </para>
-+ <para>
-+ The dynamic memory regions will be allocated when the UIO device file,
-+ <varname>/dev/uioX</varname> is opened.
-+ Simiar to static memory resources, the memory region information for
-+ dynamic regions is then visible via sysfs at
-+ <varname>/sys/class/uio/uioX/maps/mapY/*</varname>.
-+ The dynmaic memory regions will be freed when the UIO device file is
-+ closed. When no processes are holding the device file open, the address
-+ returned to userspace is DMA_ERROR_CODE.
-+ </para>
-+</sect1>
-+
- </chapter>
-
- <chapter id="userspace_driver" xreflabel="Writing a driver in user space">
+++ /dev/null
-From dhobsong@igel.co.jp Wed Nov 21 18:27:25 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Thu, 22 Nov 2012 11:26:53 +0900
-Subject: [PATCH 6/6] drivers: uio: Only allocate new private data when probing device tree node
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Message-ID: <1353551213-17996-7-git-send-email-dhobsong@igel.co.jp>
-
-
-The same condition should be used both when allocating and freeing the
-driver private data. When dev.of_node is non NULL, allocate a new
-private data structure, otherwise use the values from the platform data.
-
-Reported-by: Fengguang Wu <fengguang.wu@intel.com>
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- drivers/uio/uio_dmem_genirq.c | 2 +-
- drivers/uio/uio_pdrv_genirq.c | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/uio/uio_dmem_genirq.c
-+++ b/drivers/uio/uio_dmem_genirq.c
-@@ -153,7 +153,7 @@ static int uio_dmem_genirq_probe(struct
- int ret = -EINVAL;
- int i;
-
-- if (!uioinfo) {
-+ if (pdev->dev.of_node) {
- int irq;
-
- /* alloc uioinfo for one device */
---- a/drivers/uio/uio_pdrv_genirq.c
-+++ b/drivers/uio/uio_pdrv_genirq.c
-@@ -102,7 +102,7 @@ static int uio_pdrv_genirq_probe(struct
- int ret = -EINVAL;
- int i;
-
-- if (!uioinfo) {
-+ if (pdev->dev.of_node) {
- int irq;
-
- /* alloc uioinfo for one device */
+++ /dev/null
-From dhobsong@igel.co.jp Wed Nov 21 18:27:22 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Thu, 22 Nov 2012 11:26:52 +0900
-Subject: [PATCH 5/6] drivers: uio_dmem_genirq: Allow partial success when opening device
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Message-ID: <1353551213-17996-6-git-send-email-dhobsong@igel.co.jp>
-
-
-The uio device should not fail on open just because one memory allocation
-fails. The device might export several regions, the failure of some of
-which may or may not be a problem for the user space driver. Failing
-regions will remain unmapped, and successful regions will be mapped and
-exported to user space. Also deals with the case where failing to map
-a region after successfully allocating others would not unmap the
-successfully allocated regions before dying.
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- drivers/uio/uio_dmem_genirq.c | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
-
---- a/drivers/uio/uio_dmem_genirq.c
-+++ b/drivers/uio/uio_dmem_genirq.c
-@@ -62,8 +62,6 @@ static int uio_dmem_genirq_open(struct u
- (dma_addr_t *)&uiomem->addr, GFP_KERNEL);
- if (!addr) {
- uiomem->addr = DMEM_MAP_ERROR;
-- ret = -ENOMEM;
-- break;
- }
- priv->dmem_region_vaddr[dmem_region++] = addr;
- ++uiomem;
-@@ -93,11 +91,13 @@ static int uio_dmem_genirq_release(struc
- while (!priv->refcnt && uiomem < &priv->uioinfo->mem[MAX_UIO_MAPS]) {
- if (!uiomem->size)
- break;
--
-- dma_free_coherent(&priv->pdev->dev, uiomem->size,
-- priv->dmem_region_vaddr[dmem_region++],
-- uiomem->addr);
-+ if (priv->dmem_region_vaddr[dmem_region]) {
-+ dma_free_coherent(&priv->pdev->dev, uiomem->size,
-+ priv->dmem_region_vaddr[dmem_region],
-+ uiomem->addr);
-+ }
- uiomem->addr = DMEM_MAP_ERROR;
-+ ++dmem_region;
- ++uiomem;
- }
-
+++ /dev/null
-From dhobsong@igel.co.jp Wed Nov 21 18:27:18 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Thu, 22 Nov 2012 11:26:50 +0900
-Subject: [PATCH 3/6] drivers: uio_dmem_genirq: Don't mix address spaces for dynamic region vaddr
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Message-ID: <1353551213-17996-4-git-send-email-dhobsong@igel.co.jp>
-
-
-Assigning the virtual address returned from dma_alloc_coherent to the the
-internal_addr element of uioinfo produces the following sparse errors since
-internal_addr is a void __iomem * and dma_alloc_coherent returns void *.
-
-+ drivers/uio/uio_dmem_genirq.c:65:39: sparse: incorrect type in assignment (different address spaces)
-drivers/uio/uio_dmem_genirq.c:65:39: expected void [noderef] <asn:2>*internal_addr
-drivers/uio/uio_dmem_genirq.c:65:39: got void *[assigned] addr
-+ drivers/uio/uio_dmem_genirq.c:93:17: sparse: incorrect type in argument 3 (different address spaces)
-drivers/uio/uio_dmem_genirq.c:93:17: expected void *vaddr
-drivers/uio/uio_dmem_genirq.c:93:17: got void [noderef] <asn:2>*internal_addr
-
-Store the void * in the driver's private data instead.
-
-Reported-by: Fengguang Wu <fengguang.wu@intel.com>
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- drivers/uio/uio_dmem_genirq.c | 9 ++++++---
- 1 file changed, 6 insertions(+), 3 deletions(-)
-
---- a/drivers/uio/uio_dmem_genirq.c
-+++ b/drivers/uio/uio_dmem_genirq.c
-@@ -37,6 +37,7 @@ struct uio_dmem_genirq_platdata {
- struct platform_device *pdev;
- unsigned int dmem_region_start;
- unsigned int num_dmem_regions;
-+ void *dmem_region_vaddr[MAX_UIO_MAPS];
- struct mutex alloc_lock;
- unsigned int refcnt;
- };
-@@ -46,6 +47,7 @@ static int uio_dmem_genirq_open(struct u
- struct uio_dmem_genirq_platdata *priv = info->priv;
- struct uio_mem *uiomem;
- int ret = 0;
-+ int dmem_region = priv->dmem_region_start;
-
- uiomem = &priv->uioinfo->mem[priv->dmem_region_start];
-
-@@ -61,8 +63,7 @@ static int uio_dmem_genirq_open(struct u
- ret = -ENOMEM;
- break;
- }
--
-- uiomem->internal_addr = addr;
-+ priv->dmem_region_vaddr[dmem_region++] = addr;
- ++uiomem;
- }
- priv->refcnt++;
-@@ -77,6 +78,7 @@ static int uio_dmem_genirq_release(struc
- {
- struct uio_dmem_genirq_platdata *priv = info->priv;
- struct uio_mem *uiomem;
-+ int dmem_region = priv->dmem_region_start;
-
- /* Tell the Runtime PM code that the device has become idle */
- pm_runtime_put_sync(&priv->pdev->dev);
-@@ -91,7 +93,8 @@ static int uio_dmem_genirq_release(struc
- break;
-
- dma_free_coherent(&priv->pdev->dev, uiomem->size,
-- uiomem->internal_addr, uiomem->addr);
-+ priv->dmem_region_vaddr[dmem_region++],
-+ uiomem->addr);
- uiomem->addr = DMA_ERROR_CODE;
- ++uiomem;
- }
+++ /dev/null
-From dhobsong@igel.co.jp Wed Nov 21 18:27:20 2012
-From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Date: Thu, 22 Nov 2012 11:26:51 +0900
-Subject: [PATCH 4/6] drivers: uio_dmem_genirq: Don't use DMA_ERROR_CODE to indicate unmapped regions
-To: gregkh@linuxfoundation.org
-Cc: ltsi-dev@lists.linuxfoundation.org, Damian Hobson-Garcia <dhobsong@igel.co.jp>
-Message-ID: <1353551213-17996-5-git-send-email-dhobsong@igel.co.jp>
-
-
-DMA_ERROR_CODE is not defined on all architectures and is architecture
-specific. Instead, use the constant, ~0 to indicate unmapped regions.
-
-Reported-by: Fengguang Wu <fengguang.wu@intel.com>
-Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
-
-Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
----
- Documentation/DocBook/uio-howto.tmpl | 2 +-
- drivers/uio/uio_dmem_genirq.c | 6 ++++--
- 2 files changed, 5 insertions(+), 3 deletions(-)
-
---- a/Documentation/DocBook/uio-howto.tmpl
-+++ b/Documentation/DocBook/uio-howto.tmpl
-@@ -771,7 +771,7 @@ framework to set up sysfs files for this
- <varname>/sys/class/uio/uioX/maps/mapY/*</varname>.
- The dynmaic memory regions will be freed when the UIO device file is
- closed. When no processes are holding the device file open, the address
-- returned to userspace is DMA_ERROR_CODE.
-+ returned to userspace is ~0.
- </para>
- </sect1>
-
---- a/drivers/uio/uio_dmem_genirq.c
-+++ b/drivers/uio/uio_dmem_genirq.c
-@@ -29,6 +29,7 @@
- #include <linux/of_address.h>
-
- #define DRIVER_NAME "uio_dmem_genirq"
-+#define DMEM_MAP_ERROR (~0)
-
- struct uio_dmem_genirq_platdata {
- struct uio_info *uioinfo;
-@@ -60,6 +61,7 @@ static int uio_dmem_genirq_open(struct u
- addr = dma_alloc_coherent(&priv->pdev->dev, uiomem->size,
- (dma_addr_t *)&uiomem->addr, GFP_KERNEL);
- if (!addr) {
-+ uiomem->addr = DMEM_MAP_ERROR;
- ret = -ENOMEM;
- break;
- }
-@@ -95,7 +97,7 @@ static int uio_dmem_genirq_release(struc
- dma_free_coherent(&priv->pdev->dev, uiomem->size,
- priv->dmem_region_vaddr[dmem_region++],
- uiomem->addr);
-- uiomem->addr = DMA_ERROR_CODE;
-+ uiomem->addr = DMEM_MAP_ERROR;
- ++uiomem;
- }
-
-@@ -238,7 +240,7 @@ static int uio_dmem_genirq_probe(struct
- break;
- }
- uiomem->memtype = UIO_MEM_PHYS;
-- uiomem->addr = DMA_ERROR_CODE;
-+ uiomem->addr = DMEM_MAP_ERROR;
- uiomem->size = pdata->dynamic_region_sizes[i];
- ++uiomem;
- }
patches.lttng/lttng-fix-reference-to-obsolete-rt-kconfig-variable.patch
-#############################################################################
-# AF_BUS
-#
-# DBUS in the kernel patches. Rejected by upstream, but people need this
-# (GENEVI and the like), so while they are being reworked into upstream
-# acceptable format, we include them here for people who need/want them.
-#
-patches.af_bus/0001-net-bus-add-the-AF_BUS-socket-address-family.patch
-patches.af_bus/0002-net-bus-Add-AF_BUS-documentation.patch
-patches.af_bus/0003-net-bus-add-af_bus-address-and-af_bus-socket-address.patch
-patches.af_bus/0004-security-Add-Linux-Security-Modules-hook-for-AF_BUS-.patch
-patches.af_bus/0005-security-selinux-Add-AF_BUS-socket-SELinux-hooks.patch
-patches.af_bus/0006-netfilter-add-NFPROTO_BUS-hook-constant-for-AF_BUS-s.patch
-patches.af_bus/0007-scm-allow-AF_BUS-sockets-to-send-ancillary-data.patch
-patches.af_bus/0008-net-bus-Add-implementation-of-Bus-domain-sockets.patch
-patches.af_bus/0009-net-bus-Add-garbage-collector-for-AF_BUS-sockets.patch
-patches.af_bus/0010-net-bus-Add-the-AF_BUS-socket-address-family-to-KBui.patch
-patches.af_bus/0011-netlink-connector-implement-cn_netlink_reply.patch
-patches.af_bus/0012-netlink-connector-Add-idx-and-val-identifiers-for-ne.patch
-patches.af_bus/0013-netfilter-nfdbus-Add-D-bus-message-parsing.patch
-patches.af_bus/0014-netfilter-nfdbus-Add-D-bus-match-rule-implementation.patch
-patches.af_bus/0015-netfilter-add-netfilter-D-Bus-module.patch
-patches.af_bus/af_bus-make-netfilter_dbus-depend-on-netfilter.patch
-
-#############################################################################
-# pramfs
-#
-# Currently broken, so don't enable, but leave here for the placeholder.
-#
-patches.pramfs/01-pramfs-documentation.patch
-patches.pramfs/02-pramfs-super-operations.patch
-patches.pramfs/03-pramfs-inode-operations.patch
-patches.pramfs/04-pramfs-file-operations.patch
-patches.pramfs/05-pramfs-block-allocation.patch
-patches.pramfs/06-pramfs-inode-operations-for-dirs.patch
-patches.pramfs/07-pramfs-symlinks.patch
-patches.pramfs/08-pramfs-headers.patch
-patches.pramfs/09-pramfs-dir-operations.patch
-patches.pramfs/10-pramfs-xip-support.patch
-patches.pramfs/11-pramfs-acl-support.patch
-patches.pramfs/12-pramfs-extended-attributes-support.patch
-patches.pramfs/13-pramfs-extended-attributes-descriptors-tree.patch
-patches.pramfs/14-pramfs-memory-write-protection.patch
-patches.pramfs/15-pramfs-test-module.patch
-patches.pramfs/16-pramfs-ioctl-operations.patch
-patches.pramfs/17-pramfs-makefile-and-kconfig.patch
-patches.pramfs/pramfs-fix-build-for-kernel-3.4.patch
-
-
-#############################################################################
-# axfs
-#
-# Currently broken, so don't enable, but leave here for the placeholder.
-#
-patches.axfs/axfs-kconfigs-and-makefiles.patch
-patches.axfs/axfs-axfs.h.patch
-patches.axfs/axfs-axfs_fs.h.patch
-patches.axfs/axfs-axfs_fs_sb.h.patch
-patches.axfs/axfs-axfs_inode.c.patch
-patches.axfs/axfs-axfs_mtd.c.patch
-patches.axfs/axfs-axfs_physmem.c.patch
-patches.axfs/axfs-axfs_profiling.c.patch
-patches.axfs/axfs-axfs_super.c.patch
-patches.axfs/axfs-axfs_uml.c.patch
-patches.axfs/axfs-axfs_uncompress.c.patch
-patches.axfs/axfs-axfs_bdev.c.patch
-patches.axfs/axfs-xip-debugging-support.patch
-patches.axfs/axfs-add-documentation.patch
-patches.axfs/axfs-mount-as-rootfs.patch
-#patches.axfs/axfs-mark-it-broken.patch
-patches.axfs/axfs-fix-build-failure-due-to-undefined-symbol-axfs_xip_record.patch
-patches.axfs/axfs-fix-build-failure-due-to-undefined-symbol-kern_path_parent.patch
-patches.axfs/axfs-fix-type-cast-warning-in-axfs_region_is_vmalloc.patch
-
-
-#############################################################################
-# dma-mapping and CMA and IOMMU memory allocation feature
-#
-patches.dma-mapping/mm-page_alloc-remove-trailing-whitespace.patch
-patches.dma-mapping/mm-compaction-introduce-isolate_migratepages_range.patch
-patches.dma-mapping/mm-compaction-introduce-map_pages.patch
-patches.dma-mapping/mm-compaction-introduce-isolate_freepages_range.patch
-patches.dma-mapping/mm-compaction-export-some-of-the-functions.patch
-patches.dma-mapping/mm-page_alloc-introduce-alloc_contig_range.patch
-patches.dma-mapping/mm-page_alloc-change-fallbacks-array-handling.patch
-patches.dma-mapping/mm-mmzone-migrate_cma-migration-type-added.patch
-patches.dma-mapping/mm-page_isolation-migrate_cma-isolation-functions-added.patch
-patches.dma-mapping/mm-serialize-access-to-min_free_kbytes.patch
-patches.dma-mapping/mm-extract-reclaim-code-from-__alloc_pages_direct_reclaim.patch
-patches.dma-mapping/mm-trigger-page-reclaim-in-alloc_contig_range-to-stabilise-watermarks.patch
-patches.dma-mapping/drivers-add-contiguous-memory-allocator.patch
-patches.dma-mapping/x86-integrate-cma-with-dma-mapping-subsystem.patch
-patches.dma-mapping/arm-integrate-cma-with-dma-mapping-subsystem.patch
-patches.dma-mapping/cma-fix-migration-mode.patch
-patches.dma-mapping/arm-dma-mapping-use-pmd-size-for-section-unmap.patch
-patches.dma-mapping/common-add-dma_mmap_from_coherent-function.patch
-patches.dma-mapping/arm-dma-mapping-use-dma_mmap_from_coherent.patch
-patches.dma-mapping/arm-dma-mapping-use-pr_-instread-of-printk.patch
-patches.dma-mapping/arm-dma-mapping-introduce-dma_error_code-constant.patch
-patches.dma-mapping/arm-dma-mapping-remove-offset-parameter-to-prepare-for-generic-dma_ops.patch
-patches.dma-mapping/arm-dma-mapping-use-asm-generic-dma-mapping-common.h.patch
-patches.dma-mapping/arm-dma-mapping-implement-dma-sg-methods-on-top-of-any-generic-dma-ops.patch
-patches.dma-mapping/arm-dma-mapping-move-all-dma-bounce-code-to-separate-dma-ops-structure.patch
-patches.dma-mapping/arm-dma-mapping-remove-redundant-code-and-do-the-cleanup.patch
-patches.dma-mapping/arm-dma-mapping-use-alloc-mmap-free-from-dma_ops.patch
-patches.dma-mapping/arm-dma-mapping-add-support-for-iommu-mapper.patch
-patches.dma-mapping/arm-dma-mapping-remove-unconditional-dependency-on-cma.patch
-patches.dma-mapping/iommu-core-pass-a-user-provided-token-to-fault-handlers.patch
-patches.dma-mapping/arm-dma-mapping-add-missing-static-storage-class-specifier.patch
-patches.dma-mapping/arm-mm-fix-type-of-the-arm_dma_limit-global-variable.patch
-patches.dma-mapping/arm-dma-mapping-fix-debug-messages-in-dmabounce-code.patch
-patches.dma-mapping/x86-dma-mapping-fix-broken-allocation-when-dma_mask-has-been-provided.patch
-patches.dma-mapping/mm-cma-don-t-replace-lowmem-pages-with-highmem.patch
-patches.dma-mapping/mm-cma-fix-condition-check-when-setting-global-cma-area.patch
-patches.dma-mapping/arm-dma-mapping-modify-condition-check-while-freeing-pages.patch
-patches.dma-mapping/arm-mm-fix-mmu-mapping-of-cma-regions.patch
-patches.dma-mapping/arm-relax-conditions-required-for-enabling-contiguous-memory-allocator.patch
-patches.dma-mapping/mm-vmalloc-use-const-void-for-caller-argument.patch
-patches.dma-mapping/arm-dma-mapping-remove-custom-consistent-dma-region.patch
-patches.dma-mapping/arm-dma-mapping-add-more-sanity-checks-in-arm_dma_mmap.patch
-patches.dma-mapping/arm-dma-mapping-fix-error-path-for-memory-allocation-failure.patch
-patches.dma-mapping/common-dma-mapping-add-support-for-generic-dma_mmap_-calls.patch
-patches.dma-mapping/mm-clean-up-__count_immobile_pages.patch
-patches.dma-mapping/mm-factor-out-memory-isolate-functions.patch
-patches.dma-mapping/driver-core-fix-some-kernel-doc-warnings-in-dma-.c.patch
-patches.dma-mapping/arm-dma-mapping-fix-buffer-chunk-allocation-order.patch
-patches.dma-mapping/arm-fix-warning-caused-by-wrongly-typed-arm_dma_limit.patch
-patches.dma-mapping/arm-dma-mapping-fix-atomic-allocation-alignment.patch
-patches.dma-mapping/arm-dma-mapping-fix-incorrect-freeing-of-atomic-allocations.patch
-patches.dma-mapping/mm-cma-fix-alignment-requirements-for-contiguous-regions.patch
-patches.dma-mapping/arm-dma-mapping-add-function-for-setting-coherent-pool-size-from-platform-code.patch
-patches.dma-mapping/arm-dma-mapping-print-warning-when-atomic-coherent-allocation-fails.patch
-patches.dma-mapping/arm-dma-mapping-refactor-out-to-introduce-__in_atomic_pool.patch
-patches.dma-mapping/arm-mm-fix-dma-pool-affiliation-check.patch
-patches.dma-mapping/arm-dma-mapping-atomic_pool-with-struct-page-pages.patch
-patches.dma-mapping/arm-dma-mapping-fix-potential-memory-leak-in-atomic_pool_init.patch
-
-
-#############################################################################
-# Marzen board support
-#
-patches.marzen/0001-sh-clkfwk-Support-variable-size-accesses-for-MSTP-cl.patch
-patches.marzen/0002-sh-clkfwk-Support-variable-size-accesses-for-div4-di.patch
-patches.marzen/0003-sh-clkfwk-Move-to-common-clk_div_table-accessors-for.patch
-patches.marzen/0004-sh-clkfwk-Introduce-a-div_mask-for-variable-div-type.patch
-patches.marzen/0005-sh-clkfwk-Use-shared-sh_clk_div_recalc.patch
-patches.marzen/0006-sh-clkfwk-Use-shared-sh_clk_div_set_rate.patch
-patches.marzen/0007-sh-clkfwk-Use-shared-sh_clk_div_enable-disable.patch
-patches.marzen/0008-sh-clkfwk-Consolidate-div6-div4-clk_ops-definitions.patch
-patches.marzen/0009-sh-clkfwk-Consolidate-div-clk-registration-helper.patch
-patches.marzen/0010-irqdomain-Support-removal-of-IRQ-domains.patch
-patches.marzen/0011-irqdomain-Export-remaining-public-API-symbols.patch
-patches.marzen/0012-irqdomain-Make-irq_domain_simple_map-static.patch
-patches.marzen/0013-irqdomain-Kill-off-duplicate-definitions.patch
-patches.marzen/0014-irqdomain-trivial-pr_fmt-conversion.patch
-patches.marzen/0015-irqdomain-Document-size-parameter-of-irq_domain_add_.patch
-patches.marzen/0016-devicetree-add-helper-inline-for-retrieving-a-node-s.patch
-patches.marzen/0017-irqdomain-Simple-NUMA-awareness.patch
-patches.marzen/0018-irqdomain-Remove-unnecessary-test-for-IRQ_DOMAIN_MAP.patch
-patches.marzen/0019-irqdomain-Make-ops-map-hook-optional.patch
-patches.marzen/0020-irq_domain-Standardise-legacy-linear-domain-selectio.patch
-patches.marzen/0021-irq_domain-correct-a-minor-wrong-comment-for-linear-.patch
-patches.marzen/0022-irqdomain-Always-update-revmap-when-setting-up-a-vir.patch
-patches.marzen/0023-irqdomain-Split-disassociating-code-into-separate-fu.patch
-patches.marzen/0024-irqdomain-Support-for-static-IRQ-mapping-and-associa.patch
-patches.marzen/0025-irqdomain-Eliminate-dedicated-radix-lookup-functions.patch
-patches.marzen/0026-irqdomain-Fix-irq_create_direct_mapping-to-test-irq_.patch
-patches.marzen/0027-irqdomain-eliminate-slow-path-revmap-lookups.patch
-patches.marzen/0028-irqdomain-Improve-diagnostics-when-a-domain-mapping-.patch
-patches.marzen/0029-ARM-mach-shmobile-Introduce-INTC_IRQ_PINS_16H.patch
-patches.marzen/0030-sh-intc-Kill-off-special-reservation-interface.patch
-patches.marzen/0031-sh-intc-Allocate-subgroup-virq-backing-desc-directly.patch
-patches.marzen/0032-sh-intc-initial-irqdomain-support.patch
-patches.marzen/0033-sh-intc-Handle-domain-association-for-sparseirq-pre-.patch
-patches.marzen/0034-sh-intc-Fix-up-multi-evt-irq-association.patch
-patches.marzen/0035-ARM-mach-shmobile-Introduce-shmobile_setup_delay.patch
-patches.marzen/0036-ARM-mach-shmobile-Use-0x3400-as-INTCS-vector-offset.patch
-patches.marzen/0037-ARM-provide-a-late_initcall-hook-for-platform-initia.patch
-patches.marzen/0038-ARM-shmobile-use-machine-specific-hook-for-late-init.patch
-patches.marzen/0039-ARM-mach-shmobile-Use-preset_lpj-with-calibrate_dela.patch
-patches.marzen/0040-ARM-shmobile-r8a7740-add-MERAM-work-around.patch
-patches.marzen/0041-ARM-shmobile-add-common-extra-gpio-functions.patch
-patches.marzen/0042-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ma.patch
-patches.marzen/0043-ARM-shmobile-marzen-fixup-smsc911x-id-for-regulator.patch
-patches.marzen/0044-ARM-shmobile-r8a7779-Route-all-interrupts-to-ARM.patch
-patches.marzen/0045-dmaengine-Fixup-dmaengine_prep_slave_single-to-be-ac.patch
-patches.marzen/0046-dma-dmaengine-add-slave-req-id-in-slave_config.patch
-patches.marzen/0047-dmaengine-Add-wrapper-for-device_tx_status-callback.patch
-patches.marzen/0048-dma-move-shdma-driver-to-an-own-directory.patch
-patches.marzen/0049-dmaengine-add-an-shdma-base-library.patch
-patches.marzen/0050-dma-shdma-prepare-for-conversion-to-the-shdma-base-l.patch
-patches.marzen/0051-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch
-patches.marzen/0052-usb-renesas_usbhs-prepare-for-conversion-to-the-shdm.patch
-patches.marzen/0053-dma-shdma-convert-to-the-shdma-base-library.patch
-patches.marzen/0054-dmaengine-shdma-prepare-to-stop-using-struct-dma_cha.patch
-patches.marzen/0055-dmaengine-shdma-cosmetic-simplify-a-static-function.patch
-patches.marzen/0056-dma-sh-use-an-integer-slave-ID-to-improve-API-compat.patch
-patches.marzen/0057-dma-sh-provide-a-migration-path-for-slave-drivers-to.patch
-patches.marzen/0058-dmaengine-shdma-restore-partial-transfer-calculation.patch
-patches.marzen/0059-serial-sh-sci-modify-sci_break_ctl.patch
-patches.marzen/0060-serial-sh-sci-Update-break_ctl-handling-for-all-SCSP.patch
-patches.marzen/0061-serial-sh-sci-Fix-for-port-types-without-BRI-interru.patch
-patches.marzen/0062-serial-sh-sci-Fix-probe-error-paths.patch
-patches.marzen/0063-serial-sh-sci-Make-probe-fail-for-ports-that-exceed-.patch
-patches.marzen/0064-serial-sh-sci-prepare-for-conversion-to-the-shdma-ba.patch
-patches.marzen/0065-serial-sh-sci-fix-compilation-breakage-when-DMA-is-e.patch
-patches.marzen/0066-net-smsc911x-Repair-broken-failure-paths.patch
-patches.marzen/0067-smsc911x.c-encapsulate-enable-irq-calls.patch
-patches.marzen/0068-clocksource-sh_tmu-Convert-timer-lock-to-raw-spinloc.patch
-patches.marzen/0069-mmc-tmio-use-MMC-opcode-defines-instead-of-numbers.patch
-patches.marzen/0070-mmc-cd-gpio-pass-IRQF_ONESHOT-to-request_threaded_ir.patch
-patches.marzen/0071-mmc-extend-and-rename-cd-gpio-helpers-to-handle-more.patch
-patches.marzen/0072-mmc-tmio-Don-t-access-hardware-registers-after-stopp.patch
-patches.marzen/0073-mmc-tmio-don-t-needlessly-enable-interrupts-during-p.patch
-patches.marzen/0074-mmc-sdhi-implement-tmio-mmc-clock-enable-update-and-.patch
-patches.marzen/0075-mmc-tmio-add-callbacks-to-enable-update-and-disable-.patch
-patches.marzen/0076-mmc-sdhi-do-not-install-dummy-callbacks.patch
-patches.marzen/0077-mmc-add-a-function-to-get-regulators-supplying-card-.patch
-patches.marzen/0078-mmc-tmio-add-regulator-support.patch
-patches.marzen/0079-mmc-tmio-remove-a-duplicated-comment-line.patch
-patches.marzen/0080-mmc-tmio-support-caps2-flags.patch
-patches.marzen/0081-mmc-sh_mobile_sdhi-support-caps2-flags.patch
-patches.marzen/0082-mmc-sdhi-add-OF-support-make-platform-data-optional.patch
-patches.marzen/0083-mmc-core-use-a-more-generic-name-for-slot-function-t.patch
-patches.marzen/0084-mmc-add-two-capability-flags-for-CD-and-WP-signal-po.patch
-patches.marzen/0085-mmc-add-CD-GPIO-polling-support-to-slot-functions.patch
-patches.marzen/0086-mmc-core-convert-slot-functions-to-managed-allocatio.patch
-patches.marzen/0087-mmc-core-add-WP-pin-handler-to-slot-functions.patch
-patches.marzen/0088-mmc-tmio-use-generic-GPIO-CD-and-WP-handlers.patch
-patches.marzen/0089-mmc-sh_mobile_sdhi-prepare-for-conversion-to-the-shd.patch
-patches.marzen/0090-mmc-sh_mmcif-remove-unneeded-struct-sh_mmcif_dma-pre.patch
-patches.marzen/0091-mmc-sh_mmcif-switch-to-the-new-DMA-channel-allocatio.patch
-patches.marzen/0092-mmc-sh_mmcif-Support-MMC_SLEEP_AWAKE-command.patch
-patches.marzen/0093-mmc-sh_mmcif-simplify-and-use-meaningful-label-names.patch
-patches.marzen/0094-mmc-sh_mmcif-fix-clock-management.patch
-patches.marzen/0095-mmc-sh_mmcif-re-read-the-clock-frequency-every-time-.patch
-patches.marzen/0096-mmc-sh_mmcif-remove-redundant-.down_pwr-callback.patch
-patches.marzen/0097-mmc-sh_mmcif-add-regulator-support.patch
-patches.marzen/0098-mmc-sh-mmcif-add-OF-support-make-platform-data-optio.patch
-patches.marzen/0099-mmc-sh_mmcif-support-generic-card-detection.patch
-patches.marzen/arm-mach-shmobile-marzen-defconfig-update.patch
-patches.marzen/arm-shmobile-r8a7779-correct-tmu-clock-support.patch
-patches.marzen/libata-add-r-car-sata-driver.patch
-patches.marzen/i2c-add-renesas-r-car-i2c-driver.patch
-patches.marzen/i2c-rcar-used-devm_request_and_ioremap-instead-of-devm_ioremap.patch
-patches.marzen/i2c-rcar-fix-section-mismatch.patch
-patches.marzen/arm-shmobile-r8a7779-add-i2c-driver-support.patch
-patches.marzen/arm-mach-shmobile-r8a7779-add-sata-support.patch
-patches.marzen/arm-mach-shmobile-marzen-add-sata-support.patch
-
-#############################################################################
-# Armadillo 800 board support
-#
-patches.armadillo800/0001-ARM-shmobile-add-common-DMAEngine-definitions.patch
-patches.armadillo800/0002-ARM-shmobile-soc-core-add-R-mobile-PM-domain-common-.patch
-patches.armadillo800/0003-media-V4L2-sh_mobile_ceu-manage-lower-8bit-bus.patch
-patches.armadillo800/0004-regulator-support-multiple-dummy-fixed-regulators.patch
-patches.armadillo800/0005-regulator-extend-the-fixed-dummy-voltage-regulator-t.patch
-patches.armadillo800/0006-Input-gpio_keys-remove-useless-reinitialization-of-p.patch
-patches.armadillo800/0007-Input-st1232-add-device-tree-support.patch
-patches.armadillo800/0008-Input-st1232-switch-to-using-SIMPLE_DEV_PM_OPS.patch
-patches.armadillo800/0009-net-sh_eth-add-support-R8A7740.patch
-patches.armadillo800/0010-net-sh_eth-fix-the-rxdesc-pointer-when-rx-descriptor.patch
-patches.armadillo800/0011-net-sh_eth-fix-the-condition-to-fix-the-cur_tx-dirty.patch
-patches.armadillo800/0012-net-sh-eth-Add-support-selecting-MII-function-for-SH.patch
-patches.armadillo800/0013-net-sh-eth-Check-return-value-of-sh_eth_reset-when-c.patch
-patches.armadillo800/0014-net-sh_eth-remove-unnecessary-function.patch
-patches.armadillo800/0015-net-sh_eth-remove-unnecessary-members-definitions.patch
-patches.armadillo800/0016-net-sh_eth-fix-up-the-buffer-pointers.patch
-patches.armadillo800/0017-net-sh_eth-add-support-for-set_ringparam-get_ringpar.patch
-patches.armadillo800/0018-net-sh_eth-Add-eth-support-for-R8A7779-device.patch
-patches.armadillo800/0019-ASoC-add-generic-simple-card-support.patch
-patches.armadillo800/0020-ASoC-sh-fsi-use-simple-card-instead-of-fsi-ak4642.patch
-patches.armadillo800/0021-ASoC-sh-fsi-use-simple-card-instead-of-fsi-hdmi.patch
-patches.armadillo800/0022-ASoC-sh-fsi-use-simple-card-instead-of-fsi-da7210.patch
-patches.armadillo800/0023-ASoC-sh-fsi-use-register-field-macro-name-on-IN-OUT_.patch
-patches.armadillo800/0024-ASoC-sh-fsi-add-fsi_version-and-removed-meaningless-.patch
-patches.armadillo800/0025-ASoC-sh-fsi-use-same-format-for-IN-OUT.patch
-patches.armadillo800/0026-ASoC-sh-fsi-call-fsi_hw_startup-shutdown-from-fsi_da.patch
-patches.armadillo800/0027-ASoC-sh-fsi-enable-chip-specific-data-transfer-mode.patch
-patches.armadillo800/0028-ASoC-fsi-bugfix-enable-master-clock-control-on-DMA-s.patch
-patches.armadillo800/0029-ASoC-fsi-bugfix-correct-dma-area.patch
-patches.armadillo800/0030-ASoC-fsi-bugfix-ensure-dma-is-terminated.patch
-patches.armadillo800/0031-ASoC-fsi-use-dmaengine-helper-functions.patch
-patches.armadillo800/0032-ASoC-fsi-use-PIO-handler-if-DMA-handler-was-invalid.patch
-#patches.armadillo800/0033-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch
-patches.armadillo800/0034-fbdev-sh_mobile_hdmi-add-hdmi_bit_set-function.patch
-patches.armadillo800/0035-fbdev-sh_mobile_hdmi-add-interrupt-output-option.patch
-patches.armadillo800/0036-fbdev-sh_mobile_hdmi-32bit-register-access-support.patch
-patches.armadillo800/0037-fbdev-sh_mobile_hdmi-add-HDMI-Control-Register-suppo.patch
-patches.armadillo800/0038-fbdev-sh_mipi_dsi-fix-a-section-mismatch.patch
-patches.armadillo800/0039-fbdev-sh_mobile_lcdc-Constify-sh_mobile_lcdc_fix-str.patch
-patches.armadillo800/0040-fbdev-sh_mobile_lcdc-Rename-fb-operation-handlers-wi.patch
-patches.armadillo800/0041-fbdev-sh_mobile_lcdc-Implement-overlays-support.patch
-patches.armadillo800/0042-sh_mobile_meram-Rename-operations-to-cache_-alloc-fr.patch
-patches.armadillo800/0043-sh_mobile_meram-Use-direct-function-calls-for-the-pu.patch
-patches.armadillo800/0044-sh_mobile_meram-Add-direct-MERAM-allocation-API.patch
-patches.armadillo800/0045-fbdev-sh_mobile_lcdc-Destroy-mutex-at-remove-time.patch
-patches.armadillo800/0046-fbdev-sh_mobile_lcdc-Fix-line-pitch-computation.patch
-patches.armadillo800/0047-fbdev-sh_mobile_lcdc-Use-channel-configuration-to-in.patch
-patches.armadillo800/0048-fbdev-sh_mobile_lcdc-Support-horizontal-panning.patch
-patches.armadillo800/0049-fbdev-sh_mobile_lcdc-Fix-overlay-registers-update-du.patch
-patches.armadillo800/0050-fbdev-sh_mobile_lcdc-Fix-pan-offset-computation-in-Y.patch
-patches.armadillo800/0051-fbdev-sh_mobile_lcdc-Fix-vertical-panning-step.patch
-patches.armadillo800/0052-ARM-mach-shmobile-r8a7740-add-gpio_irq-support.patch
-patches.armadillo800/0053-ARM-mach-shmobile-r8a7740-cleanup-I2C-workaround-met.patch
-patches.armadillo800/0054-ARM-mach-shmobile-clock-r8a7740-add-FSI-clock.patch
-patches.armadillo800/0055-ARM-mach-shmobile-clock-r8a7740-add-USB-clock.patch
-patches.armadillo800/0056-ARM-mach-shmobile-clock-r8a7740-add-SDHI-clock.patch
-patches.armadillo800/0057-ARM-mach-shmobile-clock-r8a7740-add-MMCIF-clock.patch
-patches.armadillo800/0058-ARM-mach-shmobile-clock-r8a7740-use-followparent_rec.patch
-patches.armadillo800/0059-ARM-mach-shmobile-add-armadillo800eva-board-support.patch
-patches.armadillo800/0060-ARM-mach-shmobile-armadillo800eva-add-defconfig.patch
-patches.armadillo800/0061-ARM-mach-shmobile-armadillo800eva-add-support-LCDC0.patch
-patches.armadillo800/0062-ARM-mach-shmobile-armadillo800eva-add-support-gpio_k.patch
-patches.armadillo800/0063-ARM-mach-shmobile-armadillo800eva-add-support-sh_eth.patch
-patches.armadillo800/0064-ARM-mach-shmobile-armadillo800eva-add-support-ST1232.patch
-patches.armadillo800/0065-ARM-mach-shmobile-armadillo800eva-add-USB-function-s.patch
-patches.armadillo800/0066-ARM-mach-shmobile-armadillo800eva-add-SDHI0-support.patch
-patches.armadillo800/0067-ARM-mach-shmobile-armadillo800eva-add-SDHI1-support.patch
-patches.armadillo800/0068-ARM-mach-shmobile-armadillo800eva-add-MMCIF-support.patch
-patches.armadillo800/0069-ARM-mach-shmobile-r8a7740-reserve-DMA-memory-for-the.patch
-patches.armadillo800/0070-ARM-mach-shmobile-clock-r8a7740-add-sh-eth-clock.patch
-patches.armadillo800/0071-ARM-mach-shmobile-armadillo800eva-defconfig-update.patch
-patches.armadillo800/0072-ARM-mach-shmobile-Use-DT_MACHINE-for-armadillo-800-e.patch
-patches.armadillo800/0073-ARM-shmobile-r8a7740-add-HDMI-interrupt-support.patch
-patches.armadillo800/0074-ARM-shmobile-r8a7740-add-HDMI-clock-support.patch
-patches.armadillo800/0075-ARM-shmobile-r8a7740-add-HDMI-GPIO-support.patch
-patches.armadillo800/0076-ARM-shmobile-r8a7740-add-MERAM-work-around.patch
-patches.armadillo800/0077-ARM-shmobile-r8a7740-add-CEU-clock-support.patch
-patches.armadillo800/0078-ARM-shmobile-r8a7740-add-FSI-parent-clock-support.patch
-patches.armadillo800/0079-ARM-shmobile-r8a7740-add-FSI-B-for-HDMI-GPIO-support.patch
-patches.armadillo800/0080-ARM-shmobile-armadillo800eva-enable-HDMI.patch
-patches.armadillo800/0081-ARM-mach-shmobile-armadillo800eva-Use-late-init-mach.patch
-patches.armadillo800/0082-ARM-shmobile-armadillo800eva-enable-camera.patch
-patches.armadillo800/0083-ARM-shmobile-r8a7740-add-DMAEngine-support-for-FSI.patch
-patches.armadillo800/0084-ARM-shmobile-r8a7740-add-DMAEngine-support-for-SDHI.patch
-patches.armadillo800/0085-ARM-shmobile-r8a7740-add-DMAEngine-support-for-USB.patch
-patches.armadillo800/0086-ARM-shmobile-use-common-DMAEngine-definitions-on-r8a.patch
-patches.armadillo800/0087-ARM-shmobile-armadillo800eva-enable-FSI-WM8978-sound.patch
-patches.armadillo800/0088-ARM-shmobile-armadillo800eva-enable-FSI-HDMI-sound.patch
-patches.armadillo800/0089-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-FSI.patch
-patches.armadillo800/0090-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-SDH.patch
-patches.armadillo800/0091-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-USB.patch
-patches.armadillo800/0092-ARM-shmobile-use-common-extra-gpio-functions-on-arma.patch
-patches.armadillo800/0093-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ar.patch
-patches.armadillo800/0094-ARM-mach-shmobile-Convert-sh_clk_mstp32_register-to-.patch
-patches.armadillo800/0095-ARM-shmobile-r8a7740-fixup-MSEL1CR-7bit-control.patch
-patches.armadillo800/0096-ARM-shmobile-r8a7740-add-A4S-pm-domain-support.patch
-patches.armadillo800/0097-ARM-shmobile-r8a7740-add-A3SP-pm-domain-support.patch
-patches.armadillo800/0098-ARM-shmobile-r8a7740-add-A4LC-pm-domain-support.patch
-patches.armadillo800/0099-ARM-shmobile-armadillo800eva-USB-Func-enables-extern.patch
-patches.armadillo800/0100-ARM-shmobile-armadillo800eva-A4LC-domain-includes-LC.patch
-patches.armadillo800/0101-ARM-shmobile-armadillo800eva-A3SP-domain-includes-US.patch
-patches.armadillo800/0102-ARM-mach-shmobile-r8a7740-generic-board-support-via-.patch
-patches.armadillo800/0103-ARM-mach-shmobile-armadillo800eva-defconfig-Allow-us.patch
-patches.armadillo800/0104-ARM-mach-shmobile-armadillo800eva-Fix-GPIO-buttons-d.patch
-patches.armadillo800/0105-ARM-mach-shmobile-armadillo800eva-Enable-power-butto.patch
-patches.armadillo800/0107-ARM-shmobile-armadillo800eva-enable-rw-rootfs-mount.patch
-patches.armadillo800/asoc-sh-fsi-select-simple-card-on-kconfig.patch
-
-patches.armadillo800/shmobile-r8a7740-add-support-for-vcp-1-vpu-vpc-vio-multimedia-ip.patch
-patches.armadillo800/shmobile-armadillo800eva-set-lcd-color-depth-to-32-bpp.patch
-patches.armadillo800/iommu-shmobile-add-iommu-driver-for-renesas-ipmmu-modules.patch
-patches.armadillo800/shmobile-armadillo800eva-enable-iommu-support.patch
-patches.armadillo800/shmobile-ipmmu-add-basic-pmb-support.patch
-patches.armadillo800/shmobile-r8a7740-set-up-meram-address-range.patch
-patches.armadillo800/shmobile-r8a7740-add-meram-uio-device.patch
-patches.armadillo800/shmobile-iommu-only-enable-driver-on-arm-based-shmobile-configuration.patch
-patches.armadillo800/armadillo800eva-defconfig-enable-drivers-used-with-multimedia.patch
-
-
-#############################################################################
-# AT91 board support
-#
-patches.at91/0001-MAINTAINERS-add-entry-for-Atmel-isi-driver.patch
-patches.at91/0002-MAINTAINERS-add-entry-for-Atmel-touch-screen-ADC-con.patch
-patches.at91/0003-MAINTAINERS-add-entry-for-Atmel-DMA-driver.patch
-patches.at91/0004-MAINTAINERS-add-entry-for-Atmel-timer-counter-TC.patch
-patches.at91/0005-MAINTAINERS-remove-non-responding-web-link-for-atmel.patch
-patches.at91/0006-ARM-at91-change-AT91-Kconfig-entry-comment.patch
-patches.at91/0007-ARM-at91-Kconfig-change-at91sam9g45-entry.patch
-patches.at91/0008-ARM-at91-Kconfig-add-comment-to-at91sam9x5-family-en.patch
-patches.at91/0009-ARM-at91-Kconfig-add-clarifications-to-AT91SAM9M10G4.patch
-patches.at91/0010-ARM-at91-Kconfig-add-AT91SAM9x5-family-to-AT91_EARLY.patch
-patches.at91/0011-ARM-at91-Kconfig-website-link-for-AT91SAM9G20-EK.patch
-patches.at91/0012-rtc-Kconfig-remove-dependency-for-AT91-rtc-driver.patch
-patches.at91/0013-Input-Kconfig-remove-dependency-for-atmel_tsadcc-dri.patch
-patches.at91/0014-hwrng-Kconfig-remove-dependency-for-atmel-rng-driver.patch
-patches.at91/0015-ARM-at91-uncompress-Store-UART-address-in-a-variable.patch
-patches.at91/0016-ARM-at91-uncompress-autodetect-the-uart-to-use.patch
-patches.at91/0017-ARM-at91-drop-at91_set_serial_console.patch
-patches.at91/0018-ARM-at91-do-not-pin-mux-the-UARTs-in-init_early.patch
-patches.at91/0019-ARM-at91-move-at91_init_leds-to-board-init.patch
-patches.at91/0020-ARM-at91-pm-select-memory-controler-at-runtime.patch
-patches.at91/0021-ARM-at91-add-SOC_AT91SAM9-kconfig-option-to-factoris.patch
-patches.at91/0022-ARN-at91-introduce-SOC_AT91xxx-define-to-allow-to-co.patch
-patches.at91/0023-ARM-at91-dt-do-not-specify-the-board-any-more.patch
-patches.at91/0024-ARM-at91-add-defconfig-for-device-tree.patch
-patches.at91/0025-ARM-at91-add-at91sam9260-DT-support.patch
-patches.at91/0026-arm-at91-add-Calao-TNY-A9260-and-TNY-A9G20-board-sup.patch
-patches.at91/0027-ARM-at91-add-at91sam9g20ek-boards-dt-support.patch
-patches.at91/0028-ARM-at91-USB-A926x-update-nand-partition.patch
-patches.at91/0029-ARM-at91-Calao-USB-A926x-factorize-common-binding-in.patch
-patches.at91/0030-ARM-at91-DT-add-Calao-USB-A9260-DT-support.patch
-patches.at91/0031-ARM-at91-standard-device-init-only-if-DT-is-not-popu.patch
-patches.at91/0032-ARM-at91-add-at91sam9263-DT-support.patch
-patches.at91/0033-ARM-at91-add-at91sam9263ek-DT-support.patch
-patches.at91/0034-ARM-at91-DT-add-Calao-USB-A9263-board-support.patch
-patches.at91/0035-ARM-at91-DT-add-Calao-TNY-A9263-board-support.patch
-patches.at91/0036-ARM-at91-add-kizbox-board-dt-support.patch
-patches.at91/0037-Ethernut-5-board-support.patch
-patches.at91/0038-ARM-at91-Add-machine-header-file-for-AT91SAM9N12-SoC.patch
-patches.at91/0039-ARM-at91-Add-machine-files-for-AT91SAM9N12-SoC.patch
-patches.at91/0040-ARM-at91-Add-DT-description-files-for-AT91SAM9N12-EK.patch
-patches.at91/0041-ARM-at91-remove-two-unused-headers.patch
-patches.at91/0042-ARM-at91-fix-at91_aic_write-macro.patch
-patches.at91/0043-USB-ohci-at91-use-resource_size-for-memory-io-resour.patch
-patches.at91/0044-ARM-at91-clock-fix-PLLA-overclock-warning.patch
-patches.at91/0045-ARM-at91-dts-remove-partial-parameter-in-at91sam9g25.patch
-patches.at91/0046-ARM-at91-set-i2c_board_info.type-to-ds1339-directly.patch
-patches.at91/0047-ARM-at91-defconfig-Remove-unaffected-config-option.patch
-patches.at91/0048-ARM-at91-fix-missing-interrupt-cells-on-gpio-control.patch
-patches.at91/0050-ARM-at91-missing-header-file-for-rtc-at91rm9200.c.patch
-patches.at91/0051-ASoC-atmel-ssc-include-linux-io.h-for-raw-io.patch
-patches.at91/0052-ARM-at91-aic-can-use-fast-eoi-handler-type.patch
-patches.at91/0053-ARM-at91-aic-add-dt-support-for-external-irqs.patch
-patches.at91/0054-ARM-at91-add-of-irq-priorities-support.patch
-patches.at91/0055-ARM-at91-remove-static-irq-priorities-for-sam9x5.patch
-patches.at91/0056-ARM-at91-at91-based-machines-specify-their-own-irq-h.patch
-patches.at91/0057-ARM-at91-sparse-irq-support.patch
-patches.at91/0058-ARM-at91-remove-mach-irqs.h.patch
-patches.at91/0059-ARM-at91-add-AIC5-support.patch
-patches.at91/0060-dt-add-property-iteration-helpers.patch
-patches.at91/0061-ARM-at91-fix-new-build-errors.patch
-patches.at91/0062-dmaengine-at_hdmac-remove-some-at_dma_slave-comments.patch
-patches.at91/0063-dmaengine-at_hdmac-remove-ATC_DEFAULT_CTRLA-constant.patch
-patches.at91/0064-dmaengine-at_hdmac-take-maxburst-from-slave-configur.patch
-patches.at91/0065-dmaengine-at_hdmac-trivial-fix-comment-in-header.patch
-patches.at91/0068-AT91-Remove-fixed-mapping-for-AT91RM9200-ethernet.patch
-patches.at91/0069-net-at91_ether-use-gpio_to_irq-for-phy-IRQ-line.patch
-patches.at91/0070-net-macb-manage-carrier-state-with-call-to-netif_car.patch
-patches.at91/0071-ALSA-atmel-ac97c-correct-the-unexpected-behavior-whe.patch
-patches.at91/0072-MTD-at91-extract-hw-ecc-initialization-to-one-functi.patch
-patches.at91/0073-MTD-at91-add-dt-parameters-for-Atmel-PMECC.patch
-patches.at91/0074-MTD-at91-atmel_nand-Update-driver-to-support-Program.patch
-patches.at91/0075-MTD-nand-add-return-value-for-write_page-write_page_.patch
-patches.at91/0076-MTD-atmel-nand-fix-gpio-missing-request.patch
-patches.at91/0077-usb-gadget-at91_udc-move-the-dereference-below-the-N.patch
-patches.at91/0079-USB-ohci-at91-fix-PIO-handling-in-relation-with-numb.patch
-patches.at91/0080-usb-gadget-at91_udc-Propagate-devicetree-to-gadget-d.patch
-patches.at91/0081-USB-ohci-at91.c-remove-err-usage.patch
-patches.at91/0083-MTD-atmel_nand-revet-the-oob_required-parameter-in-e.patch
-patches.at91/0084-USB-Kconfig-add-Atmel-usba-driver-entry.patch
-patches.at91/0085-pinctrl-core-device-tree-mapping-table-parsing-suppo.patch
-patches.at91/0086-pinctrl-fix-build-when-CONFIG_OF-CONFIG_PINCTRL.patch
-patches.at91/0087-pinctrl-fix-dangling-comment.patch
-patches.at91/0088-pinctrl-implement-devm_pinctrl_get-put.patch
-patches.at91/0089-pinctrl-add-pinctrl_provide_dummies-interface-for-pl.patch
-patches.at91/0090-pinctrl-remove-pinctrl_remove_gpio_range.patch
-patches.at91/0091-pinctrl-add-pinctrl_add_gpio_ranges-function.patch
-patches.at91/0092-pinctrl-support-gpio-request-deferred-probing.patch
-patches.at91/0093-pinctrl-propagate-map-validation-errors.patch
-patches.at91/0094-pinctrl-mark-non-EXPERIMENTAL.patch
-patches.at91/0095-pinctrl-implement-pinctrl-deferred-probing.patch
-patches.at91/0096-pinctrl-replace-list_-with-get_-_count.patch
-patches.at91/0097-pinctrl-show-pin-name-when-request-pins.patch
-patches.at91/0098-pinctrl-show-pin-name-for-pingroups-in-sysfs.patch
-patches.at91/0099-dt-add-of_get_child_count-helper-function.patch
-patches.at91/0100-MTD-atmel_nand-add-9x5-to-list-of-SoC-with-DMA.patch
-patches.at91/0101-MTD-atmel_nand-POI-fall-back-is-not-an-issue-change-.patch
-patches.at91/0102-MTD-atmel_nand-add-9n12-to-list-of-SoC-with-DMA.patch
-patches.at91/0103-input-atmel_tsadcc-add-support-for-ARCH_AT91SAM9X5.patch
-patches.at91/0104-input-atmel_tsadcc-add-touch-screen-pressure-measure.patch
-patches.at91/0105-input-atmel_tsadcc-enable-touchscreen-averaging-and-.patch
-patches.at91/0106-input-atmel_tsadcc-add-ACR-register-and-change-trigg.patch
-patches.at91/0107-AT91-input-atmel_tsadcc-rework-irq-infrastructure-an.patch
-patches.at91/0108-input-at91-add-tsadcc_data-for-9x5.patch
-patches.at91/0109-input-at91-add-dt-support-for-atmel-touch-screen-adc.patch
-patches.at91/0110-net-macb-Add-support-for-Gigabit-Ethernet-mode.patch
-patches.at91/0111-net-macb-memory-barriers-cleanup.patch
-patches.at91/0112-net-macb-change-debugging-messages.patch
-patches.at91/0113-net-macb-remove-macb_get_drvinfo.patch
-patches.at91/0114-net-macb-tx-status-is-more-than-8-bits-now.patch
-patches.at91/0115-net-macb-clean-up-ring-buffer-logic.patch
-patches.at91/0116-net-macb-ethtool-interface-add-register-dump-feature.patch
-patches.at91/0117-net-macb-better-manage-tx-errors.patch
-patches.at91/0118-net-macb-Offset-first-RX-buffer-by-two-bytes.patch
-patches.at91/0119-net-macb-GEM-DMA-configuration-register-update.patch
-patches.at91/0120-net-macb-Use-non-coherent-memory-for-rx-buffers.patch
-patches.at91/0121-phy-micrel-Use-proper-phy-in-gmac.patch
-patches.at91/0122-phy-micrel-we-need-to-register-ks8051-phy-for-emac.patch
-patches.at91/0123-media-video-atmel-isi-add-dumb-set_parm.patch
-patches.at91/0124-video-atmel_lcdfb-add-support-for-AT91SAM9x5.patch
-patches.at91/0125-video-atmel_lcdfb-The-output-bpp-should-not-change-a.patch
-patches.at91/0126-video-atmelfb-initially-split-atmelfb-into-a-driver-.patch
-patches.at91/0127-video-atmelfb-refactor-core-setup.patch
-patches.at91/0128-video-atmelfb-refactor-start-stop.patch
-patches.at91/0129-video-atmelfb-refactor-isr.patch
-patches.at91/0130-video-atmelfb-refactor-backlight-routines.patch
-patches.at91/0131-video-atmelfb-refactor-dma_update.patch
-patches.at91/0132-video-atmelfb-refactor-LUT.patch
-patches.at91/0133-video-atmelfb-refactor-limit_screeninfo.patch
-patches.at91/0134-arm-at91-refactor-lcdc-includes.patch
-patches.at91/0135-video-atmel_hlcdfb-add-new-driver.patch
-patches.at91/0136-WIP-add-clut-resource.patch
-patches.at91/0137-video-atmel_lcdfb-add-error-msg-when-out-of-memory.patch
-patches.at91/0138-video-atmel_lcdfb-HLCD-modifications.patch
-patches.at91/0139-atmel_lcdfb-change-pixel-clock-ratio-calculation.patch
-patches.at91/0140-media-at91sam9x5-video-new-driver-for-the-high-end-o.patch
-patches.at91/0141-video-atmel_lcdfb-protect-bl_power-with-CONFIG_BACKL.patch
-patches.at91/0142-ARM-at91-9x5-modify-consistent-DMA-size.patch
-patches.at91/0143-video-atmel_lcdfb-adapt-to-all-IP-configurations.patch
-patches.at91/0144-media-at91sam9x5-video-cleanup-modifications.patch
-patches.at91/0145-media-at91sam9x5-video-align-DMA-descriptors-on-64-b.patch
-patches.at91/0146-media-at91sam9x5-video-change-scaling-factor-calcula.patch
-patches.at91/0147-media-at91sam9x5-video-add-device-tree-support.patch
-patches.at91/0148-ARM-at91-video-Atmel-HLCD-is-only-selected-by-newer-.patch
-patches.at91/0149-mmc-atmel-mci-the-r-w-proof-capability-lack-was-not-.patch
-patches.at91/0150-mmc-atmel-mci-change-the-state-machine-for-compatibi.patch
-patches.at91/0151-mmc-atmel-mci-add-support-for-version-lower-than-v2x.patch
-patches.at91/0152-mmc-atmel-mci-add-debug-logs.patch
-patches.at91/0153-mmc-atmel-mci-fix-data-timeout-issue.patch
-patches.at91/0154-ARM-at91-add-atmel-mci-support-for-chips-and-boards-.patch
-patches.at91/0155-ARM-at91-defconfig-change-the-MCI-driver-to-use-in-d.patch
-patches.at91/0156-mmc-atmel-mci-fix-burst-chunk-size-modification.patch
-patches.at91/0157-mmc-atmel-mci-add-device-tree-support.patch
-patches.at91/0158-ARM-at91-add-clocks-for-DT-entries.patch
-patches.at91/0159-ARM-dts-add-nodes-for-atmel-hsmci-controllers-for-at.patch
-patches.at91/0160-ARM-dts-add-nodes-for-atmel-hsmci-controllers-for-at.patch
-patches.at91/0161-mmc-atmel-mci-remove-not-needed-DMA-capability-test.patch
-patches.at91/0162-ARM-at91-atmel-mci-remove-unused-setup_dma_addr-macr.patch
-patches.at91/0164-ARM-dts-fix-add-mmc-irq-priority.patch
-patches.at91/0165-mmc-atmel-mci-support-8-bit-buswidth.patch
-patches.at91/0166-mmc-atmel-mci-fix-incorrect-setting-of-host-data-to-.patch
-patches.at91/0167-mmc-block-fix-the-data-timeout-issue-with-ACMD22.patch
-patches.at91/0168-mmc-atmel-mci-modify-CLKDIV-displaying-in-debugfs.patch
-patches.at91/0169-mmc-atmel-mci-increase-dma-threshold.patch
-patches.at91/0170-mmc-atmel-mci-not-busy-flag-has-also-to-be-used-for-.patch
-patches.at91/0171-Replace-clk_lookup.con_id-with-clk_lookup.dev_id-ent.patch
-patches.at91/0172-i2c-at91-remove-old-polling-driver.patch
-patches.at91/0173-i2c-at91-add-new-driver.patch
-patches.at91/0174-arm-at91-G45-TWI-remove-open-drain-setting-for-twi-f.patch
-patches.at91/0175-ARM-at91-do-not-configure-at91sam9g10-twi-pio-as-ope.patch
-patches.at91/0176-i2c-at91-add-dt-support-to-i2c-at91.patch
-patches.at91/0177-ARM-at91-add-clocks-for-I2C-DT-entries.patch
-patches.at91/0178-ARM-dts-add-twi-nodes-for-atmel-SoCs.patch
-patches.at91/0179-ARM-dts-add-twi-nodes-for-atmel-boards.patch
-patches.at91/0180-i2c-at91-add-dma-support.patch
-patches.at91/0181-i2c-at91-backport-fix-for-devm_clk_get.patch
-patches.at91/0182-i2c-at91-add-dt-property-for-DMA-configuration.patch
-patches.at91/0183-ARM-at91-add-MCI-DMA-for-at91sam9x5.dtsi.patch
-patches.at91/0184-ARM-at91-add-i2c-and-qt1070-pin-muxing.patch
-patches.at91/0185-AT91-board-dt-add-mci-pinmux-for-9x5.patch
-patches.at91/0186-mtd-atmel_nand-add-4k-page-nand-flash-support-for-PM.patch
-patches.at91/0187-mtd-atmel_nand-incease-the-chip_delay-time-tR-for-su.patch
-patches.at91/0188-at91-9x5-add-DT-parameters-to-enable-PMECC.patch
-patches.at91/0189-ARM-at91-split-9x5-dts-dtsi-in-a-common-set-of-perip.patch
-patches.at91/0190-ARM-at91-9x5-family-add-at91sam9x25ek.dts.patch
-patches.at91/0191-ARM-at91-add-new-at91sam9g35ek.dts.patch
-patches.at91/0192-ARM-at91-add-pinmux-for-9x5-LCD.patch
-patches.at91/0193-ARM-at91-add-LCD-HEO-DT-entry-for-at91sam9x5.patch
-patches.at91/0194-AT91SAM9G45-add-crypto-peripherals.patch
-patches.at91/0195-crypto-add-Atmel-AES-driver.patch
-patches.at91/0196-crypto-add-Atmel-DES-TDES-driver.patch
-patches.at91/0197-crypto-add-Atmel-SHA1-SHA256-driver.patch
-patches.at91/0198-crypto-add-atmel-test-driver.patch
-patches.at91/0199-crypto-add-new-tests-to-tcrypt.patch
-patches.at91/0200-AT91SAM9G45-crypto-same-platform-data-header-for-all.patch
-patches.at91/0201-AT91SAM9G45-dts-add-crypto-peripherals.patch
-patches.at91/0202-AT91SAM9N12-add-crypto-peripherals.patch
-patches.at91/0203-AT91SAM9N12-dts-add-crypto-peripherals.patch
-patches.at91/0204-crypto-Atmel-AES-add-device-tree-support.patch
-patches.at91/0205-crypto-Atmel-TDES-add-device-tree-support.patch
-patches.at91/0206-crypto-Atmel-SHA-add-device-tree-support.patch
-patches.at91/0207-crypto-Atmel-Test-add-SHA224-SHA384-and-SHA512-suppo.patch
-patches.at91/0208-arm-at91-use-macro-to-declare-soc-boot-data.patch
-patches.at91/0209-ARM-at91-gpio-implement-request.patch
-patches.at91/0210-at91-regroup-gpio-and-pinctrl-under-the-same-ranges.patch
-patches.at91/0211-arm-at91-at91sam9x5-fix-gpio-number-per-bank.patch
-patches.at91/0212-ARM-at91-add-dummies-pinctrl-for-non-dt-platform.patch
-patches.at91/0213-ARM-at91-add-pinctrl-support.patch
-patches.at91/0214-arm-at91-dt-at91sam9-add-pinctrl-support.patch
-patches.at91/0215-tty-atmel_serial-add-pinctrl-support.patch
-patches.at91/0216-arm-at91-dt-sam9m10g45ek-use-rts-cts-pinctrl-group-f.patch
-patches.at91/0217-arm-at91-dt-sam9263ek-use-rts-cts-pinctrl-group-for-.patch
-patches.at91/0218-arm-at91-dt-sam9g20ek-use-rts-cts-dtr-dsr-dcd-ri-pin.patch
-patches.at91/0219-arm-at91-dt-at91sam9-add-nand-pinctrl-support.patch
-patches.at91/0220-MTD-atmel_nand-add-pinctrl-consumer-support.patch
-patches.at91/0221-pinctrl-at91-add-deglitch-debounce-pull-down-and-sch.patch
-patches.at91/0222-mtd-atmel_nand-fix-the-compile-error-which-miss-labe.patch
-patches.at91/0223-pinctrl-at91-fix-compatible-order.patch
-patches.at91/0224-pinctrl-at91-fix-gpio-irq-support.patch
-patches.at91/0225-i2c-at91-add-pinctrl.patch
-patches.at91/0226-media-atmel_isi-add-pinctrl.patch
-patches.at91/0227-mmc-at91-add-pinctrl.patch
-patches.at91/0228-video-atmel_lcdfb-add-pinctrl.patch
-patches.at91/0229-arm-at91sam9g45-add-missing-uart-pinctrl-node.patch
-patches.at91/0230-arm-at91sam9263-add-missing-uart-pinctrl-node.patch
-patches.at91/0231-arm-at91sam9260-add-missing-uart-pinctrl-node.patch
-patches.at91/0232-arm-at91sam9x5-sync-with-the-mainline.patch
-patches.at91/0233-ARM-at91-DT-add-i2c-mmc-nand-pinctrl-in-device-tree-.patch
-patches.at91/0234-at91sam9x5-add-lcd-pinctrl-support.patch
-patches.at91/0235-arm-at91sam9x5ek-drop-temporary-pinmux.patch
-patches.at91/0236-video-atmel-lcd-only-request-the-pinctrl-once.patch
-patches.at91/0237-ARM-at91-add-at91-3.4-trunk-contents.txt-file.patch
-patches.at91/0238-ARM-at91-add-defconfig-for-sam9x5-family.patch
-patches.at91/0239-MMC-atmel-mci-add-device-tree-property-for-configura.patch
-patches.at91/0240-pinctrl-at19-fix-typo-on-PULL_UP.patch
-patches.at91/0241-pinctrl-at91-fix-pull-down-support.patch
-patches.at91/0242-arm-at91sam9xcm-add-specific-nand-pinctrl.patch
-patches.at91/0243-pinctrl-at91-fix-debounce-support.patch
-patches.at91/0245-ARM-at91-dts-at91sam9g20ek_common-Fix-typos-in-butto.patch
-patches.at91/0246-ARM-at91-fix-external-interrupt-specification-in-boa.patch
-patches.at91/0248-ARM-at91-drop-duplicated-config-SOC_AT91SAM9-entry.patch
-patches.at91/0249-ARM-at91-fix-at91x40-build.patch
-patches.at91/0250-ARM-at91-fix-external-interrupts-in-non-DT-case.patch
-patches.at91/0251-ARM-at91-i2c-change-id-to-let-i2c-at91-work.patch
-patches.at91/0252-net-macb-align-ring-buffer-function-with-mainline.patch
-patches.at91/0253-net-macb-move-to-circ_buf-macros-and-fix-initial-con.patch
-
-
-#############################################################################
-# kzm9g board support
-#
-patches.kzm9g/arm-update-mach-types.patch
-patches.kzm9g/arm-mach-shmobile-add-kzm-a9-gt-board-support.patch
-patches.kzm9g/arm-mach-shmobile-kzm9g-add-defconfig.patch
-patches.kzm9g/arm-mach-shmobile-kzm9g-add-smsc-9221-support.patch
-patches.kzm9g/arm-mach-shmobile-kzm9g-add-external-usb-host-support.patch
-patches.kzm9g/arm-mach-shmobile-kzm9g-add-lcdc-support.patch
-patches.kzm9g/arm-mach-shmobile-kzm9g-add-st1232-touchscreen-support.patch
-patches.kzm9g/arm-mach-shmobile-pfc-sh73a0-fixup-msel2cr-msel18-for-i2c-3.patch
-patches.kzm9g/arm-mach-shmobile-sh73a0.h-add-gpio_nr.patch
-patches.kzm9g/arm-mach-shmobile-kzm9g-correct-screen-direction.patch
-patches.kzm9g/arm-mach-shmobile-kzm9g-add-mmcif-support.patch
-patches.kzm9g/arm-mach-shmobile-kzm9g-add-sdhi-support.patch
-patches.kzm9g/arm-mach-shmobile-kzm9g-add-pcf8757-gpio-key.patch
-patches.kzm9g/arm-mach-shmobile-kzm9g-defconfig-update.patch
-patches.kzm9g/arm-mach-shmobile-kzm9g-enable-smp-boot.patch
-patches.kzm9g/arm-mach-shmobile-use-dt_machine-for-kzm9g.patch
-patches.kzm9g/arm-shmobile-fix-smp-build.patch
-patches.kzm9g/arm-mach-shmobile-sh73a0-fixup-pint-irq16-irq31-irq-number-conflict.patch
-patches.kzm9g/arm-shmobile-sh73a0-bugfix-sy-dmac-number.patch
-patches.kzm9g/arm-shmobile-fix-platsmp.c-build-when-arch_sh73a0-n.patch
-patches.kzm9g/arm-mach-shmobile-add-compilation-support-for-dtbs-using-make-dtbs.patch
-patches.kzm9g/arm-shmobile-sh73a0-add-fsi-clock.patch
-patches.kzm9g/arm-shmobile-kzm9g-enable-fsi-ak4648.patch
-patches.kzm9g/arm-shmobile-kzm9g-support-real-time-clock.patch
-patches.kzm9g/arm-shmobile-sh73a0-add-usb-clock-support.patch
-patches.kzm9g/arm-shmobile-kzm9g-enable-usb-function.patch
-patches.kzm9g/arm-shmobile-kzm9g-enable-microsd.patch
-patches.kzm9g/arm-shmobile-sh73a0-add-dmaengine-support-for-mpdmac.patch
-patches.kzm9g/arm-shmobile-use-common-dmaengine-definitions-on-sh73a0.patch
-patches.kzm9g/arm-shmobile-kzm9g-enable-dmaengine-on-fsi.patch
-patches.kzm9g/arm-shmobile-kzm9g-defconfig-enable-inotify_user.patch
-patches.kzm9g/arm-shmobile-sh73a0-fixup-reloc_base-of-intca_irq_pins_desc.patch
-patches.kzm9g/arm-shmobile-kzm9g-enable-restarting.patch
-patches.kzm9g/arm-shmobile-sh73a0-enable-pmu-performance-monitoring-unit.patch
-patches.kzm9g/arm-shmobile-kzm9g-bugfix-correct-mmcif-interrupt-settings.patch
-patches.kzm9g/arm-shmobile-add-new-__iomem-annotation-for-new-code.patch
-
-
-#############################################################################
-# kzm9d board support
-#
-patches.kzm9d/tegra-serial8250-add-handle_break-uart_port-op.patch
-patches.kzm9d/serial-8250_pci-clear-fifos-for-intel-me-serial-over-lan-device-on-bi.patch
-patches.kzm9d/serial-8250_pci-fix-suspend-resume-vs-init-exit-quirks.patch
-patches.kzm9d/serial8250-add-dl_read-dl_write-callbacks.patch
-patches.kzm9d/serial8250-use-dl_read-dl_write-on-alchemy.patch
-patches.kzm9d/serial8250-use-dl_read-dl_write-on-rm9k.patch
-patches.kzm9d/serial8250-clean-up-default-map-and-dl-code.patch
-patches.kzm9d/serial8250-introduce-serial8250_register_8250_port.patch
-patches.kzm9d/serial8250-em-emma-mobile-uart-driver-v2.patch
-patches.kzm9d/serial8250-em-clk_get-is_err-error-handling-fix.patch
-patches.kzm9d/serial8250-em-add-dt-support.patch
-patches.kzm9d/clockevents-make-clockevents_config-a-global-symbol.patch
-patches.kzm9d/clocksource-em_sti-emma-mobile-sti-driver.patch
-patches.kzm9d/clocksource-em_sti-add-dt-support.patch
-patches.kzm9d/gpio-emma-mobile-gpio-driver-v2.patch
-patches.kzm9d/mach-shmobile-emma-mobile-ev2-soc-base-support-v3.patch
-patches.kzm9d/mach-shmobile-kzm9d-board-support-v3.patch
-patches.kzm9d/mach-shmobile-emma-mobile-ev2-smp-support-v3.patch
-patches.kzm9d/mach-shmobile-emma-mobile-ev2-gpio-support-v3.patch
-patches.kzm9d/mach-shmobile-kzm9d-board-ethernet-support-v3.patch
-patches.kzm9d/arm-mach-shmobile-kzm9d-add-defconfig.patch
-patches.kzm9d/mach-shmobile-emma-mobile-ev2-dt-support-v3.patch
-patches.kzm9d/mach-shmobile-use-dt_machine-for-kzm9d-v3.patch
-patches.kzm9d/arm-mach-shmobile-fix-build-when-smp-is-enabled-and-emev2-is-not-enabled.patch
-
-
-#############################################################################
-# UIO driver patches
-#
-patches.uio/drivers-uio-add-new-uio-device-for-dynamic-memory-allocation.patch
-patches.uio/drivers-uio-add-uio_dmem_genirq-description-to-uio-documentation.patch
-patches.uio/drivers-uio_dmem_genirq-don-t-mix-address-spaces-for-dynamic-region-vaddr.patch
-patches.uio/drivers-uio_dmem_genirq-don-t-use-dma_error_code-to-indicate-unmapped-regions.patch
-patches.uio/drivers-uio_dmem_genirq-allow-partial-success-when-opening-device.patch
-patches.uio/drivers-uio-only-allocate-new-private-data-when-probing-device-tree-node.patch
-
-
-#############################################################################
-# CoDEL
-# Controlled Delay active queue management
-#
-patches.codel/netem-add-ECN-capability.patch
-patches.codel/codel-Controlled-Delay-AQM.patch
-patches.codel/fq_codel-Fair-Queue-Codel-AQM.patch
-patches.codel/codel-use-Newton-method-instead-of-sqrt-and-divides.patch
-patches.codel/codel-use-u16-field-instead-of-31bits-for-rec_inv_sq.patch
-patches.codel/net-codel-Add-missing-include-linux-prefetch.h.patch
-patches.codel/net-codel-fix-build-errors.patch
-patches.codel/fq_codel-should-use-qdisc-backlog-as-threshold.patch
-patches.codel/codel-refine-one-condition-to-avoid-a-nul-rec_inv_sq.patch
-
-
-#############################################################################
-# Misc patches that don't fit into the above categories.
-#
-patches.misc/arm-soc-add-per-platform-smp-operations.patch
-patches.misc/arm-soc-convert-shmobile-smp-to-smp-operations.patch
-patches.misc/0001-irqchip-add-basic-infrastructure.patch
-patches.misc/0002-irqdomain-augment-add_simple-to-allocate-descs.patch
-patches.misc/0003-irqdomain-stop-screaming-about-preallocated-irqdescs.patch
-patches.misc/0004-irqchip-Renesas-INTC-External-IRQ-pin-driver.patch
-patches.misc/0005-irqchip-intc-irqpin-Cache-mapped-IRQ.patch
-patches.misc/0006-ARM-shmobile-irq_pin-for-static-IRQ-pin-assignment.patch
-patches.misc/0007-ARM-shmobile-INTC-External-IRQ-pin-driver-on-r8a7779.patch
-patches.misc/0008-irqchip-intc-irqpin-Whitespace-fixes.patch
-patches.misc/0009-irqchip-intc-irqpin-Add-force-comments.patch
-patches.misc/0010-irqchip-intc-irqpin-Make-use-of-devm-functions.patch
-patches.misc/0011-irqchip-intc-irqpin-GPL-header-for-platform-data.patch
-patches.misc/0012-irqchip-Renesas-IRQC-driver.patch
-patches.misc/0013-ARM-shmobile-Make-r8a7779-INTC-irqpin-platform-data-.patch
-patches.misc/0014-irqchip-intc-irqpin-Initial-DT-support.patch
-patches.misc/0015-irqchip-irqc-Add-DT-support.patch
-
#############################################################################
# fixes that go after all of the above
#
-patches.fixes/0001-ASoC-fsi-fixup-channels_min-max.patch
-patches.fixes/0002-usb-renesas_usbhs-gadget-remove-usbhsg_uep_init.patch
-patches.fixes/0003-usb-renesas_usbhs-gadget-usbhsg_ep_disable-care-pipe.patch
-patches.fixes/revert-usb-renesas_usbhs-gadget-usbhsg_ep_disable-care-pipe-settings.patch
-patches.fixes/revert-usb-renesas_usbhs-gadget-remove-usbhsg_uep_init.patch
-patches.fixes/sh-clkfwk-bugfix-sh_clk_div_enable-care-sh_clk_div_set_rate-if-div6.patch
-patches.fixes/asoc-shmobile-armadillo800eva-enable-clock-inversion-on-fsi-a.patch
-patches.fixes/usb-gadget-f_mass_storage-change-default-value-of-the-removable-parameter.patch
-patches.fixes/usb-gadget-composite-fix-ep-maxburst-initialization.patch
-patches.fixes/usb-gadget-mass_storage-remove-unused-options.patch
-patches.fixes/usb-gadget-mass_storage-add-documentation.patch
-patches.fixes/usb-gadget-acm_ms-need-to-set-max_speed.patch
-patches.fixes/usb-gadget-storage_common-remove-fsg_buffhd_static_buffer-support.patch
-patches.fixes/usb-gadget-mass_storage-fail-fsg_store_file-early-if-colud-not-open-file.patch
-patches.fixes/usb-gadget-mass_storage-make-file-and-ro-read-only-in-some-cases.patch
-patches.fixes/arm-shmobile-r8a7779-correct-tmu-clock-support-again.patch