mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-29 09:13:38 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR. No conflicts and no adjacent changes. Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
f66ebf37d6
@ -3,29 +3,52 @@ dm-delay
|
||||
========
|
||||
|
||||
Device-Mapper's "delay" target delays reads and/or writes
|
||||
and maps them to different devices.
|
||||
and/or flushs and optionally maps them to different devices.
|
||||
|
||||
Parameters::
|
||||
Arguments::
|
||||
|
||||
<device> <offset> <delay> [<write_device> <write_offset> <write_delay>
|
||||
[<flush_device> <flush_offset> <flush_delay>]]
|
||||
|
||||
With separate write parameters, the first set is only used for reads.
|
||||
Table line has to either have 3, 6 or 9 arguments:
|
||||
|
||||
3: apply offset and delay to read, write and flush operations on device
|
||||
|
||||
6: apply offset and delay to device, also apply write_offset and write_delay
|
||||
to write and flush operations on optionally different write_device with
|
||||
optionally different sector offset
|
||||
|
||||
9: same as 6 arguments plus define flush_offset and flush_delay explicitely
|
||||
on/with optionally different flush_device/flush_offset.
|
||||
|
||||
Offsets are specified in sectors.
|
||||
|
||||
Delays are specified in milliseconds.
|
||||
|
||||
|
||||
Example scripts
|
||||
===============
|
||||
|
||||
::
|
||||
|
||||
#!/bin/sh
|
||||
# Create device delaying rw operation for 500ms
|
||||
echo "0 `blockdev --getsz $1` delay $1 0 500" | dmsetup create delayed
|
||||
#
|
||||
# Create mapped device named "delayed" delaying read, write and flush operations for 500ms.
|
||||
#
|
||||
dmsetup create delayed --table "0 `blockdev --getsz $1` delay $1 0 500"
|
||||
|
||||
::
|
||||
|
||||
#!/bin/sh
|
||||
# Create device delaying only write operation for 500ms and
|
||||
# splitting reads and writes to different devices $1 $2
|
||||
echo "0 `blockdev --getsz $1` delay $1 0 0 $2 0 500" | dmsetup create delayed
|
||||
#
|
||||
# Create mapped device delaying write and flush operations for 400ms and
|
||||
# splitting reads to device $1 but writes and flushs to different device $2
|
||||
# to different offsets of 2048 and 4096 sectors respectively.
|
||||
#
|
||||
dmsetup create delayed --table "0 `blockdev --getsz $1` delay $1 2048 0 $2 4096 400"
|
||||
|
||||
::
|
||||
#!/bin/sh
|
||||
#
|
||||
# Create mapped device delaying reads for 50ms, writes for 100ms and flushs for 333ms
|
||||
# onto the same backing device at offset 0 sectors.
|
||||
#
|
||||
dmsetup create delayed --table "0 `blockdev --getsz $1` delay $1 0 50 $2 0 100 $1 0 333"
|
||||
|
@ -160,6 +160,10 @@ iv_large_sectors
|
||||
The <iv_offset> must be multiple of <sector_size> (in 512 bytes units)
|
||||
if this flag is specified.
|
||||
|
||||
integrity_key_size:<bytes>
|
||||
Use an integrity key of <bytes> size instead of using an integrity key size
|
||||
of the digest size of the used HMAC algorithm.
|
||||
|
||||
|
||||
Module parameters::
|
||||
max_read_size
|
||||
|
@ -251,7 +251,12 @@ The messages are:
|
||||
by the vdostats userspace program to interpret the output
|
||||
buffer.
|
||||
|
||||
dump:
|
||||
config:
|
||||
Outputs useful vdo configuration information. Mostly used
|
||||
by users who want to recreate a similar VDO volume and
|
||||
want to know the creation configuration used.
|
||||
|
||||
dump:
|
||||
Dumps many internal structures to the system log. This is
|
||||
not always safe to run, so it should only be used to debug
|
||||
a hung vdo. Optional parameters to specify structures to
|
||||
|
@ -2677,6 +2677,23 @@
|
||||
|
||||
Default is Y (on).
|
||||
|
||||
kvm.enable_virt_at_load=[KVM,ARM64,LOONGARCH,MIPS,RISCV,X86]
|
||||
If enabled, KVM will enable virtualization in hardware
|
||||
when KVM is loaded, and disable virtualization when KVM
|
||||
is unloaded (if KVM is built as a module).
|
||||
|
||||
If disabled, KVM will dynamically enable and disable
|
||||
virtualization on-demand when creating and destroying
|
||||
VMs, i.e. on the 0=>1 and 1=>0 transitions of the
|
||||
number of VMs.
|
||||
|
||||
Enabling virtualization at module lode avoids potential
|
||||
latency for creation of the 0=>1 VM, as KVM serializes
|
||||
virtualization enabling across all online CPUs. The
|
||||
"cost" of enabling virtualization when KVM is loaded,
|
||||
is that doing so may interfere with using out-of-tree
|
||||
hypervisors that want to "own" virtualization hardware.
|
||||
|
||||
kvm.enable_vmware_backdoor=[KVM] Support VMware backdoor PV interface.
|
||||
Default is false (don't support).
|
||||
|
||||
|
@ -12,7 +12,7 @@ ones.
|
||||
|
||||
Of course this is a bad idea to rely on the alignment trap to perform
|
||||
unaligned memory access in general. If those access are predictable, you
|
||||
are better to use the macros provided by include/asm/unaligned.h. The
|
||||
are better to use the macros provided by include/linux/unaligned.h. The
|
||||
alignment trap can fixup misaligned access for the exception cases, but at
|
||||
a high performance cost. It better be rare.
|
||||
|
||||
|
@ -85,6 +85,38 @@ to CPUINTC directly::
|
||||
| Devices |
|
||||
+---------+
|
||||
|
||||
Advanced Extended IRQ model
|
||||
===========================
|
||||
|
||||
In this model, IPI (Inter-Processor Interrupt) and CPU Local Timer interrupt go
|
||||
to CPUINTC directly, CPU UARTS interrupts go to LIOINTC, PCH-MSI interrupts go
|
||||
to AVECINTC, and then go to CPUINTC directly, while all other devices interrupts
|
||||
go to PCH-PIC/PCH-LPC and gathered by EIOINTC, and then go to CPUINTC directly::
|
||||
|
||||
+-----+ +-----------------------+ +-------+
|
||||
| IPI | --> | CPUINTC | <-- | Timer |
|
||||
+-----+ +-----------------------+ +-------+
|
||||
^ ^ ^
|
||||
| | |
|
||||
+---------+ +----------+ +---------+ +-------+
|
||||
| EIOINTC | | AVECINTC | | LIOINTC | <-- | UARTs |
|
||||
+---------+ +----------+ +---------+ +-------+
|
||||
^ ^
|
||||
| |
|
||||
+---------+ +---------+
|
||||
| PCH-PIC | | PCH-MSI |
|
||||
+---------+ +---------+
|
||||
^ ^ ^
|
||||
| | |
|
||||
+---------+ +---------+ +---------+
|
||||
| Devices | | PCH-LPC | | Devices |
|
||||
+---------+ +---------+ +---------+
|
||||
^
|
||||
|
|
||||
+---------+
|
||||
| Devices |
|
||||
+---------+
|
||||
|
||||
ACPI-related definitions
|
||||
========================
|
||||
|
||||
|
@ -999,6 +999,36 @@ the vfio_ap mediated device to which it is assigned as long as each new APQN
|
||||
resulting from plugging it in references a queue device bound to the vfio_ap
|
||||
device driver.
|
||||
|
||||
Driver Features
|
||||
===============
|
||||
The vfio_ap driver exposes a sysfs file containing supported features.
|
||||
This exists so third party tools (like Libvirt and mdevctl) can query the
|
||||
availability of specific features.
|
||||
|
||||
The features list can be found here: /sys/bus/matrix/devices/matrix/features
|
||||
|
||||
Entries are space delimited. Each entry consists of a combination of
|
||||
alphanumeric and underscore characters.
|
||||
|
||||
Example:
|
||||
cat /sys/bus/matrix/devices/matrix/features
|
||||
guest_matrix dyn ap_config
|
||||
|
||||
the following features are advertised:
|
||||
|
||||
---------------+---------------------------------------------------------------+
|
||||
| Flag | Description |
|
||||
+==============+===============================================================+
|
||||
| guest_matrix | guest_matrix attribute exists. It reports the matrix of |
|
||||
| | adapters and domains that are or will be passed through to a |
|
||||
| | guest when the mdev is attached to it. |
|
||||
+--------------+---------------------------------------------------------------+
|
||||
| dyn | Indicates hot plug/unplug of AP adapters, domains and control |
|
||||
| | domains for a guest to which the mdev is attached. |
|
||||
+------------+-----------------------------------------------------------------+
|
||||
| ap_config | ap_config interface for one-shot modifications to mdev config |
|
||||
+--------------+---------------------------------------------------------------+
|
||||
|
||||
Limitations
|
||||
===========
|
||||
Live guest migration is not supported for guests using AP devices without
|
||||
|
8
Documentation/core-api/cleanup.rst
Normal file
8
Documentation/core-api/cleanup.rst
Normal file
@ -0,0 +1,8 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
===========================
|
||||
Scope-based Cleanup Helpers
|
||||
===========================
|
||||
|
||||
.. kernel-doc:: include/linux/cleanup.h
|
||||
:doc: scope-based cleanup helpers
|
212
Documentation/core-api/folio_queue.rst
Normal file
212
Documentation/core-api/folio_queue.rst
Normal file
@ -0,0 +1,212 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
===========
|
||||
Folio Queue
|
||||
===========
|
||||
|
||||
:Author: David Howells <dhowells@redhat.com>
|
||||
|
||||
.. Contents:
|
||||
|
||||
* Overview
|
||||
* Initialisation
|
||||
* Adding and removing folios
|
||||
* Querying information about a folio
|
||||
* Querying information about a folio_queue
|
||||
* Folio queue iteration
|
||||
* Folio marks
|
||||
* Lockless simultaneous production/consumption issues
|
||||
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The folio_queue struct forms a single segment in a segmented list of folios
|
||||
that can be used to form an I/O buffer. As such, the list can be iterated over
|
||||
using the ITER_FOLIOQ iov_iter type.
|
||||
|
||||
The publicly accessible members of the structure are::
|
||||
|
||||
struct folio_queue {
|
||||
struct folio_queue *next;
|
||||
struct folio_queue *prev;
|
||||
...
|
||||
};
|
||||
|
||||
A pair of pointers are provided, ``next`` and ``prev``, that point to the
|
||||
segments on either side of the segment being accessed. Whilst this is a
|
||||
doubly-linked list, it is intentionally not a circular list; the outward
|
||||
sibling pointers in terminal segments should be NULL.
|
||||
|
||||
Each segment in the list also stores:
|
||||
|
||||
* an ordered sequence of folio pointers,
|
||||
* the size of each folio and
|
||||
* three 1-bit marks per folio,
|
||||
|
||||
but hese should not be accessed directly as the underlying data structure may
|
||||
change, but rather the access functions outlined below should be used.
|
||||
|
||||
The facility can be made accessible by::
|
||||
|
||||
#include <linux/folio_queue.h>
|
||||
|
||||
and to use the iterator::
|
||||
|
||||
#include <linux/uio.h>
|
||||
|
||||
|
||||
Initialisation
|
||||
==============
|
||||
|
||||
A segment should be initialised by calling::
|
||||
|
||||
void folioq_init(struct folio_queue *folioq);
|
||||
|
||||
with a pointer to the segment to be initialised. Note that this will not
|
||||
necessarily initialise all the folio pointers, so care must be taken to check
|
||||
the number of folios added.
|
||||
|
||||
|
||||
Adding and removing folios
|
||||
==========================
|
||||
|
||||
Folios can be set in the next unused slot in a segment struct by calling one
|
||||
of::
|
||||
|
||||
unsigned int folioq_append(struct folio_queue *folioq,
|
||||
struct folio *folio);
|
||||
|
||||
unsigned int folioq_append_mark(struct folio_queue *folioq,
|
||||
struct folio *folio);
|
||||
|
||||
Both functions update the stored folio count, store the folio and note its
|
||||
size. The second function also sets the first mark for the folio added. Both
|
||||
functions return the number of the slot used. [!] Note that no attempt is made
|
||||
to check that the capacity wasn't overrun and the list will not be extended
|
||||
automatically.
|
||||
|
||||
A folio can be excised by calling::
|
||||
|
||||
void folioq_clear(struct folio_queue *folioq, unsigned int slot);
|
||||
|
||||
This clears the slot in the array and also clears all the marks for that folio,
|
||||
but doesn't change the folio count - so future accesses of that slot must check
|
||||
if the slot is occupied.
|
||||
|
||||
|
||||
Querying information about a folio
|
||||
==================================
|
||||
|
||||
Information about the folio in a particular slot may be queried by the
|
||||
following function::
|
||||
|
||||
struct folio *folioq_folio(const struct folio_queue *folioq,
|
||||
unsigned int slot);
|
||||
|
||||
If a folio has not yet been set in that slot, this may yield an undefined
|
||||
pointer. The size of the folio in a slot may be queried with either of::
|
||||
|
||||
unsigned int folioq_folio_order(const struct folio_queue *folioq,
|
||||
unsigned int slot);
|
||||
|
||||
size_t folioq_folio_size(const struct folio_queue *folioq,
|
||||
unsigned int slot);
|
||||
|
||||
The first function returns the size as an order and the second as a number of
|
||||
bytes.
|
||||
|
||||
|
||||
Querying information about a folio_queue
|
||||
========================================
|
||||
|
||||
Information may be retrieved about a particular segment with the following
|
||||
functions::
|
||||
|
||||
unsigned int folioq_nr_slots(const struct folio_queue *folioq);
|
||||
|
||||
unsigned int folioq_count(struct folio_queue *folioq);
|
||||
|
||||
bool folioq_full(struct folio_queue *folioq);
|
||||
|
||||
The first function returns the maximum capacity of a segment. It must not be
|
||||
assumed that this won't vary between segments. The second returns the number
|
||||
of folios added to a segments and the third is a shorthand to indicate if the
|
||||
segment has been filled to capacity.
|
||||
|
||||
Not that the count and fullness are not affected by clearing folios from the
|
||||
segment. These are more about indicating how many slots in the array have been
|
||||
initialised, and it assumed that slots won't get reused, but rather the segment
|
||||
will get discarded as the queue is consumed.
|
||||
|
||||
|
||||
Folio marks
|
||||
===========
|
||||
|
||||
Folios within a queue can also have marks assigned to them. These marks can be
|
||||
used to note information such as if a folio needs folio_put() calling upon it.
|
||||
There are three marks available to be set for each folio.
|
||||
|
||||
The marks can be set by::
|
||||
|
||||
void folioq_mark(struct folio_queue *folioq, unsigned int slot);
|
||||
void folioq_mark2(struct folio_queue *folioq, unsigned int slot);
|
||||
void folioq_mark3(struct folio_queue *folioq, unsigned int slot);
|
||||
|
||||
Cleared by::
|
||||
|
||||
void folioq_unmark(struct folio_queue *folioq, unsigned int slot);
|
||||
void folioq_unmark2(struct folio_queue *folioq, unsigned int slot);
|
||||
void folioq_unmark3(struct folio_queue *folioq, unsigned int slot);
|
||||
|
||||
And the marks can be queried by::
|
||||
|
||||
bool folioq_is_marked(const struct folio_queue *folioq, unsigned int slot);
|
||||
bool folioq_is_marked2(const struct folio_queue *folioq, unsigned int slot);
|
||||
bool folioq_is_marked3(const struct folio_queue *folioq, unsigned int slot);
|
||||
|
||||
The marks can be used for any purpose and are not interpreted by this API.
|
||||
|
||||
|
||||
Folio queue iteration
|
||||
=====================
|
||||
|
||||
A list of segments may be iterated over using the I/O iterator facility using
|
||||
an ``iov_iter`` iterator of ``ITER_FOLIOQ`` type. The iterator may be
|
||||
initialised with::
|
||||
|
||||
void iov_iter_folio_queue(struct iov_iter *i, unsigned int direction,
|
||||
const struct folio_queue *folioq,
|
||||
unsigned int first_slot, unsigned int offset,
|
||||
size_t count);
|
||||
|
||||
This may be told to start at a particular segment, slot and offset within a
|
||||
queue. The iov iterator functions will follow the next pointers when advancing
|
||||
and prev pointers when reverting when needed.
|
||||
|
||||
|
||||
Lockless simultaneous production/consumption issues
|
||||
===================================================
|
||||
|
||||
If properly managed, the list can be extended by the producer at the head end
|
||||
and shortened by the consumer at the tail end simultaneously without the need
|
||||
to take locks. The ITER_FOLIOQ iterator inserts appropriate barriers to aid
|
||||
with this.
|
||||
|
||||
Care must be taken when simultaneously producing and consuming a list. If the
|
||||
last segment is reached and the folios it refers to are entirely consumed by
|
||||
the IOV iterators, an iov_iter struct will be left pointing to the last segment
|
||||
with a slot number equal to the capacity of that segment. The iterator will
|
||||
try to continue on from this if there's another segment available when it is
|
||||
used again, but care must be taken lest the segment got removed and freed by
|
||||
the consumer before the iterator was advanced.
|
||||
|
||||
It is recommended that the queue always contain at least one segment, even if
|
||||
that segment has never been filled or is entirely spent. This prevents the
|
||||
head and tail pointers from collapsing.
|
||||
|
||||
|
||||
API Function Reference
|
||||
======================
|
||||
|
||||
.. kernel-doc:: include/linux/folio_queue.h
|
@ -35,7 +35,9 @@ Library functionality that is used throughout the kernel.
|
||||
|
||||
kobject
|
||||
kref
|
||||
cleanup
|
||||
assoc_array
|
||||
folio_queue
|
||||
xarray
|
||||
maple_tree
|
||||
idr
|
||||
|
@ -203,7 +203,7 @@ Avoiding unaligned accesses
|
||||
===========================
|
||||
|
||||
The easiest way to avoid unaligned access is to use the get_unaligned() and
|
||||
put_unaligned() macros provided by the <asm/unaligned.h> header file.
|
||||
put_unaligned() macros provided by the <linux/unaligned.h> header file.
|
||||
|
||||
Going back to an earlier example of code that potentially causes unaligned
|
||||
access::
|
||||
|
@ -0,0 +1,38 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/arm/cirrus/cirrus,ep9301.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cirrus Logic EP93xx platforms
|
||||
|
||||
description:
|
||||
The EP93xx SoC is a ARMv4T-based with 200 MHz ARM9 CPU.
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
const: '/'
|
||||
compatible:
|
||||
oneOf:
|
||||
- description: The TS-7250 is a compact, full-featured Single Board
|
||||
Computer (SBC) based upon the Cirrus EP9302 ARM9 CPU
|
||||
items:
|
||||
- const: technologic,ts7250
|
||||
- const: cirrus,ep9301
|
||||
|
||||
- description: The Liebherr BK3 is a derivate from ts7250 board
|
||||
items:
|
||||
- const: liebherr,bk3
|
||||
- const: cirrus,ep9301
|
||||
|
||||
- description: EDB302 is an evaluation board by Cirrus Logic,
|
||||
based on a Cirrus Logic EP9302 CPU
|
||||
items:
|
||||
- const: cirrus,edb9302
|
||||
- const: cirrus,ep9301
|
||||
|
||||
additionalProperties: true
|
@ -0,0 +1,42 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/ata/cirrus,ep9312-pata.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cirrus Logic EP9312 PATA controller
|
||||
|
||||
maintainers:
|
||||
- Damien Le Moal <dlemoal@kernel.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: cirrus,ep9312-pata
|
||||
- items:
|
||||
- const: cirrus,ep9315-pata
|
||||
- const: cirrus,ep9312-pata
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
ide@800a0000 {
|
||||
compatible = "cirrus,ep9312-pata";
|
||||
reg = <0x800a0000 0x38>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <8>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&ide_default_pins>;
|
||||
};
|
@ -0,0 +1,84 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/dma/cirrus,ep9301-dma-m2m.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cirrus Logic ep93xx SoC DMA controller
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
allOf:
|
||||
- $ref: dma-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: cirrus,ep9301-dma-m2m
|
||||
- items:
|
||||
- enum:
|
||||
- cirrus,ep9302-dma-m2m
|
||||
- cirrus,ep9307-dma-m2m
|
||||
- cirrus,ep9312-dma-m2m
|
||||
- cirrus,ep9315-dma-m2m
|
||||
- const: cirrus,ep9301-dma-m2m
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: m2m0 channel registers
|
||||
- description: m2m1 channel registers
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: m2m0 channel gate clock
|
||||
- description: m2m1 channel gate clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: m2m0
|
||||
- const: m2m1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: m2m0 channel interrupt
|
||||
- description: m2m1 channel interrupt
|
||||
|
||||
'#dma-cells':
|
||||
const: 2
|
||||
description: |
|
||||
The first cell is the unique device channel number as indicated by this
|
||||
table for ep93xx:
|
||||
|
||||
10: SPI controller
|
||||
11: IDE controller
|
||||
|
||||
The second cell is the DMA direction line number:
|
||||
|
||||
1: Memory to device
|
||||
2: Device to memory
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/cirrus,ep9301-syscon.h>
|
||||
dma-controller@80000100 {
|
||||
compatible = "cirrus,ep9301-dma-m2m";
|
||||
reg = <0x80000100 0x0040>,
|
||||
<0x80000140 0x0040>;
|
||||
clocks = <&syscon EP93XX_CLK_M2M0>,
|
||||
<&syscon EP93XX_CLK_M2M1>;
|
||||
clock-names = "m2m0", "m2m1";
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <17>, <18>;
|
||||
#dma-cells = <2>;
|
||||
};
|
144
Documentation/devicetree/bindings/dma/cirrus,ep9301-dma-m2p.yaml
Normal file
144
Documentation/devicetree/bindings/dma/cirrus,ep9301-dma-m2p.yaml
Normal file
@ -0,0 +1,144 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/dma/cirrus,ep9301-dma-m2p.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cirrus Logic ep93xx SoC M2P DMA controller
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
allOf:
|
||||
- $ref: dma-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: cirrus,ep9301-dma-m2p
|
||||
- items:
|
||||
- enum:
|
||||
- cirrus,ep9302-dma-m2p
|
||||
- cirrus,ep9307-dma-m2p
|
||||
- cirrus,ep9312-dma-m2p
|
||||
- cirrus,ep9315-dma-m2p
|
||||
- const: cirrus,ep9301-dma-m2p
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: m2p0 channel registers
|
||||
- description: m2p1 channel registers
|
||||
- description: m2p2 channel registers
|
||||
- description: m2p3 channel registers
|
||||
- description: m2p4 channel registers
|
||||
- description: m2p5 channel registers
|
||||
- description: m2p6 channel registers
|
||||
- description: m2p7 channel registers
|
||||
- description: m2p8 channel registers
|
||||
- description: m2p9 channel registers
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: m2p0 channel gate clock
|
||||
- description: m2p1 channel gate clock
|
||||
- description: m2p2 channel gate clock
|
||||
- description: m2p3 channel gate clock
|
||||
- description: m2p4 channel gate clock
|
||||
- description: m2p5 channel gate clock
|
||||
- description: m2p6 channel gate clock
|
||||
- description: m2p7 channel gate clock
|
||||
- description: m2p8 channel gate clock
|
||||
- description: m2p9 channel gate clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: m2p0
|
||||
- const: m2p1
|
||||
- const: m2p2
|
||||
- const: m2p3
|
||||
- const: m2p4
|
||||
- const: m2p5
|
||||
- const: m2p6
|
||||
- const: m2p7
|
||||
- const: m2p8
|
||||
- const: m2p9
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: m2p0 channel interrupt
|
||||
- description: m2p1 channel interrupt
|
||||
- description: m2p2 channel interrupt
|
||||
- description: m2p3 channel interrupt
|
||||
- description: m2p4 channel interrupt
|
||||
- description: m2p5 channel interrupt
|
||||
- description: m2p6 channel interrupt
|
||||
- description: m2p7 channel interrupt
|
||||
- description: m2p8 channel interrupt
|
||||
- description: m2p9 channel interrupt
|
||||
|
||||
'#dma-cells':
|
||||
const: 2
|
||||
description: |
|
||||
The first cell is the unique device channel number as indicated by this
|
||||
table for ep93xx:
|
||||
|
||||
0: I2S channel 1
|
||||
1: I2S channel 2 (unused)
|
||||
2: AC97 channel 1 (unused)
|
||||
3: AC97 channel 2 (unused)
|
||||
4: AC97 channel 3 (unused)
|
||||
5: I2S channel 3 (unused)
|
||||
6: UART1 (unused)
|
||||
7: UART2 (unused)
|
||||
8: UART3 (unused)
|
||||
9: IRDA (unused)
|
||||
|
||||
The second cell is the DMA direction line number:
|
||||
|
||||
1: Memory to device
|
||||
2: Device to memory
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/cirrus,ep9301-syscon.h>
|
||||
dma-controller@80000000 {
|
||||
compatible = "cirrus,ep9301-dma-m2p";
|
||||
reg = <0x80000000 0x0040>,
|
||||
<0x80000040 0x0040>,
|
||||
<0x80000080 0x0040>,
|
||||
<0x800000c0 0x0040>,
|
||||
<0x80000240 0x0040>,
|
||||
<0x80000200 0x0040>,
|
||||
<0x800002c0 0x0040>,
|
||||
<0x80000280 0x0040>,
|
||||
<0x80000340 0x0040>,
|
||||
<0x80000300 0x0040>;
|
||||
clocks = <&syscon EP93XX_CLK_M2P0>,
|
||||
<&syscon EP93XX_CLK_M2P1>,
|
||||
<&syscon EP93XX_CLK_M2P2>,
|
||||
<&syscon EP93XX_CLK_M2P3>,
|
||||
<&syscon EP93XX_CLK_M2P4>,
|
||||
<&syscon EP93XX_CLK_M2P5>,
|
||||
<&syscon EP93XX_CLK_M2P6>,
|
||||
<&syscon EP93XX_CLK_M2P7>,
|
||||
<&syscon EP93XX_CLK_M2P8>,
|
||||
<&syscon EP93XX_CLK_M2P9>;
|
||||
clock-names = "m2p0", "m2p1",
|
||||
"m2p2", "m2p3",
|
||||
"m2p4", "m2p5",
|
||||
"m2p6", "m2p7",
|
||||
"m2p8", "m2p9";
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <7>, <8>, <9>, <10>, <11>, <12>, <13>, <14>, <15>, <16>;
|
||||
#dma-cells = <2>;
|
||||
};
|
@ -73,9 +73,10 @@ examples:
|
||||
reg-names = "data", "dir", "intr";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <27>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <27>;
|
||||
};
|
||||
|
||||
gpio@80840004 {
|
||||
@ -87,6 +88,7 @@ examples:
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <27>;
|
||||
};
|
||||
@ -127,6 +129,7 @@ examples:
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts-extended = <&vic0 19>, <&vic0 20>,
|
||||
<&vic0 21>, <&vic0 22>,
|
||||
<&vic1 15>, <&vic1 16>,
|
||||
|
@ -0,0 +1,87 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/cirrus,ep9307-keypad.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cirrus ep93xx keypad
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/input/matrix-keymap.yaml#
|
||||
|
||||
description:
|
||||
The KPP is designed to interface with a keypad matrix with 2-point contact
|
||||
or 3-point contact keys. The KPP is designed to simplify the software task
|
||||
of scanning a keypad matrix. The KPP is capable of detecting, debouncing,
|
||||
and decoding one or multiple keys pressed simultaneously on a keypad.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: cirrus,ep9307-keypad
|
||||
- items:
|
||||
- enum:
|
||||
- cirrus,ep9312-keypad
|
||||
- cirrus,ep9315-keypad
|
||||
- const: cirrus,ep9307-keypad
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
debounce-delay-ms:
|
||||
description: |
|
||||
Time in microseconds that key must be pressed or
|
||||
released for state change interrupt to trigger.
|
||||
|
||||
cirrus,prescale:
|
||||
description: row/column counter pre-scaler load value
|
||||
$ref: /schemas/types.yaml#/definitions/uint16
|
||||
maximum: 1023
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- linux,keymap
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/clock/cirrus,ep9301-syscon.h>
|
||||
keypad@800f0000 {
|
||||
compatible = "cirrus,ep9307-keypad";
|
||||
reg = <0x800f0000 0x0c>;
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <29>;
|
||||
clocks = <&eclk EP93XX_CLK_KEYPAD>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&keypad_default_pins>;
|
||||
linux,keymap = <KEY_UP>,
|
||||
<KEY_DOWN>,
|
||||
<KEY_VOLUMEDOWN>,
|
||||
<KEY_HOME>,
|
||||
<KEY_RIGHT>,
|
||||
<KEY_LEFT>,
|
||||
<KEY_ENTER>,
|
||||
<KEY_VOLUMEUP>,
|
||||
<KEY_F6>,
|
||||
<KEY_F8>,
|
||||
<KEY_F9>,
|
||||
<KEY_F10>,
|
||||
<KEY_F1>,
|
||||
<KEY_F2>,
|
||||
<KEY_F3>,
|
||||
<KEY_POWER>;
|
||||
};
|
@ -17,9 +17,15 @@ description: |
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mediatek,mt8195-adsp-mbox
|
||||
- mediatek,mt8186-adsp-mbox
|
||||
oneOf:
|
||||
- enum:
|
||||
- mediatek,mt8186-adsp-mbox
|
||||
- mediatek,mt8195-adsp-mbox
|
||||
- items:
|
||||
- enum:
|
||||
- mediatek,mt8188-adsp-mbox
|
||||
- const: mediatek,mt8186-adsp-mbox
|
||||
|
||||
|
||||
"#mbox-cells":
|
||||
const: 0
|
||||
|
@ -24,7 +24,9 @@ properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- qcom,qcs8300-ipcc
|
||||
- qcom,qdu1000-ipcc
|
||||
- qcom,sa8255p-ipcc
|
||||
- qcom,sa8775p-ipcc
|
||||
- qcom,sc7280-ipcc
|
||||
- qcom,sc8280xp-ipcc
|
||||
|
45
Documentation/devicetree/bindings/mtd/technologic,nand.yaml
Normal file
45
Documentation/devicetree/bindings/mtd/technologic,nand.yaml
Normal file
@ -0,0 +1,45 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mtd/technologic,nand.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Technologic Systems NAND controller
|
||||
|
||||
maintainers:
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
allOf:
|
||||
- $ref: nand-controller.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: technologic,ts7200-nand
|
||||
- items:
|
||||
- enum:
|
||||
- technologic,ts7300-nand
|
||||
- technologic,ts7260-nand
|
||||
- technologic,ts7250-nand
|
||||
- const: technologic,ts7200-nand
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
nand-controller@60000000 {
|
||||
compatible = "technologic,ts7200-nand";
|
||||
reg = <0x60000000 0x8000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
nand@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
59
Documentation/devicetree/bindings/net/cirrus,ep9301-eth.yaml
Normal file
59
Documentation/devicetree/bindings/net/cirrus,ep9301-eth.yaml
Normal file
@ -0,0 +1,59 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/cirrus,ep9301-eth.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: EP93xx SoC Ethernet Controller
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
allOf:
|
||||
- $ref: ethernet-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: cirrus,ep9301-eth
|
||||
- items:
|
||||
- enum:
|
||||
- cirrus,ep9302-eth
|
||||
- cirrus,ep9307-eth
|
||||
- cirrus,ep9312-eth
|
||||
- cirrus,ep9315-eth
|
||||
- const: cirrus,ep9301-eth
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: The physical base address and size of IO range
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: Combined signal for various interrupt events
|
||||
|
||||
phy-handle: true
|
||||
|
||||
mdio:
|
||||
$ref: mdio.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: optional node for embedded MDIO controller
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- phy-handle
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
ethernet@80010000 {
|
||||
compatible = "cirrus,ep9301-eth";
|
||||
reg = <0x80010000 0x10000>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <7>;
|
||||
phy-handle = <&phy0>;
|
||||
};
|
@ -34,6 +34,7 @@ properties:
|
||||
and length of the AXI DMA controller IO space, unless
|
||||
axistream-connected is specified, in which case the reg
|
||||
attribute of the node referenced by it is used.
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupts:
|
||||
@ -181,7 +182,7 @@ examples:
|
||||
clock-names = "s_axi_lite_clk", "axis_clk", "ref_clk", "mgt_clk";
|
||||
clocks = <&axi_clk>, <&axi_clk>, <&pl_enet_ref_clk>, <&mgt_clk>;
|
||||
phy-mode = "mii";
|
||||
reg = <0x00 0x40000000 0x00 0x40000>;
|
||||
reg = <0x40000000 0x40000>;
|
||||
xlnx,rxcsum = <0x2>;
|
||||
xlnx,rxmem = <0x800>;
|
||||
xlnx,txcsum = <0x2>;
|
||||
|
53
Documentation/devicetree/bindings/pwm/cirrus,ep9301-pwm.yaml
Normal file
53
Documentation/devicetree/bindings/pwm/cirrus,ep9301-pwm.yaml
Normal file
@ -0,0 +1,53 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pwm/cirrus,ep9301-pwm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cirrus Logic ep93xx PWM controller
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
allOf:
|
||||
- $ref: pwm.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: cirrus,ep9301-pwm
|
||||
- items:
|
||||
- enum:
|
||||
- cirrus,ep9302-pwm
|
||||
- cirrus,ep9307-pwm
|
||||
- cirrus,ep9312-pwm
|
||||
- cirrus,ep9315-pwm
|
||||
- const: cirrus,ep9301-pwm
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: SoC PWM clock
|
||||
|
||||
"#pwm-cells":
|
||||
const: 3
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/cirrus,ep9301-syscon.h>
|
||||
pwm@80910000 {
|
||||
compatible = "cirrus,ep9301-pwm";
|
||||
reg = <0x80910000 0x10>;
|
||||
clocks = <&syscon EP93XX_CLK_PWM>;
|
||||
#pwm-cells = <3>;
|
||||
};
|
@ -0,0 +1,94 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/soc/cirrus/cirrus,ep9301-syscon.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cirrus Logic EP93xx Platforms System Controller
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
description: |
|
||||
Central resources are controlled by a set of software-locked registers,
|
||||
which can be used to prevent accidental accesses. Syscon generates
|
||||
the various bus and peripheral clocks and controls the system startup
|
||||
configuration.
|
||||
|
||||
The System Controller (Syscon) provides:
|
||||
- Clock control
|
||||
- Power management
|
||||
- System configuration management
|
||||
|
||||
Syscon registers are common for all EP93xx SoC's, through some actual peripheral
|
||||
may be missing depending on actual SoC model.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- cirrus,ep9302-syscon
|
||||
- cirrus,ep9307-syscon
|
||||
- cirrus,ep9312-syscon
|
||||
- cirrus,ep9315-syscon
|
||||
- const: cirrus,ep9301-syscon
|
||||
- const: syscon
|
||||
- items:
|
||||
- const: cirrus,ep9301-syscon
|
||||
- const: syscon
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#clock-cells":
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: reference clock
|
||||
|
||||
patternProperties:
|
||||
'^pins-':
|
||||
type: object
|
||||
description: pin node
|
||||
$ref: /schemas/pinctrl/pinmux-node.yaml
|
||||
|
||||
properties:
|
||||
function:
|
||||
enum: [ spi, ac97, i2s, pwm, keypad, pata, lcd, gpio ]
|
||||
|
||||
groups:
|
||||
enum: [ ssp, ac97, i2s_on_ssp, i2s_on_ac97, pwm1, gpio1agrp,
|
||||
gpio2agrp, gpio3agrp, gpio4agrp, gpio6agrp, gpio7agrp,
|
||||
rasteronsdram0grp, rasteronsdram3grp, keypadgrp, idegrp ]
|
||||
|
||||
required:
|
||||
- function
|
||||
- groups
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#clock-cells"
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
syscon@80930000 {
|
||||
compatible = "cirrus,ep9301-syscon", "syscon";
|
||||
reg = <0x80930000 0x1000>;
|
||||
|
||||
#clock-cells = <1>;
|
||||
clocks = <&xtali>;
|
||||
|
||||
spi_default_pins: pins-spi {
|
||||
function = "spi";
|
||||
groups = "ssp";
|
||||
};
|
||||
};
|
@ -40,6 +40,20 @@ properties:
|
||||
- const: sclk
|
||||
- const: lrclk
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: out DMA channel
|
||||
- description: in DMA channel
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: tx
|
||||
- const: rx
|
||||
|
||||
port:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- '#sound-dai-cells'
|
||||
@ -61,6 +75,8 @@ examples:
|
||||
<&syscon 30>,
|
||||
<&syscon 31>;
|
||||
clock-names = "mclk", "sclk", "lrclk";
|
||||
dmas = <&dma0 0 1>, <&dma0 0 2>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
||||
...
|
||||
|
70
Documentation/devicetree/bindings/spi/cirrus,ep9301-spi.yaml
Normal file
70
Documentation/devicetree/bindings/spi/cirrus,ep9301-spi.yaml
Normal file
@ -0,0 +1,70 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/cirrus,ep9301-spi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: EP93xx SoC SPI controller
|
||||
|
||||
maintainers:
|
||||
- Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
- Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: cirrus,ep9301-spi
|
||||
- items:
|
||||
- enum:
|
||||
- cirrus,ep9302-spi
|
||||
- cirrus,ep9307-spi
|
||||
- cirrus,ep9312-spi
|
||||
- cirrus,ep9315-spi
|
||||
- const: cirrus,ep9301-spi
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: SPI registers region
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: SPI Controller reference clock source
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: rx DMA channel
|
||||
- description: tx DMA channel
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx
|
||||
- const: tx
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/clock/cirrus,ep9301-syscon.h>
|
||||
spi@808a0000 {
|
||||
compatible = "cirrus,ep9301-spi";
|
||||
reg = <0x808a0000 0x18>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <21>;
|
||||
clocks = <&syscon EP93XX_CLK_SPI>;
|
||||
dmas = <&dma1 10 2>, <&dma1 10 1>;
|
||||
dma-names = "rx", "tx";
|
||||
cs-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
|
||||
};
|
91
Documentation/driver-api/cxl/access-coordinates.rst
Normal file
91
Documentation/driver-api/cxl/access-coordinates.rst
Normal file
@ -0,0 +1,91 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. include:: <isonum.txt>
|
||||
|
||||
==================================
|
||||
CXL Access Coordinates Computation
|
||||
==================================
|
||||
|
||||
Shared Upstream Link Calculation
|
||||
================================
|
||||
For certain CXL region construction with endpoints behind CXL switches (SW) or
|
||||
Root Ports (RP), there is the possibility of the total bandwidth for all
|
||||
the endpoints behind a switch being more than the switch upstream link.
|
||||
A similar situation can occur within the host, upstream of the root ports.
|
||||
The CXL driver performs an additional pass after all the targets have
|
||||
arrived for a region in order to recalculate the bandwidths with possible
|
||||
upstream link being a limiting factor in mind.
|
||||
|
||||
The algorithm assumes the configuration is a symmetric topology as that
|
||||
maximizes performance. When asymmetric topology is detected, the calculation
|
||||
is aborted. An asymmetric topology is detected during topology walk where the
|
||||
number of RPs detected as a grandparent is not equal to the number of devices
|
||||
iterated in the same iteration loop. The assumption is made that subtle
|
||||
asymmetry in properties does not happen and all paths to EPs are equal.
|
||||
|
||||
There can be multiple switches under an RP. There can be multiple RPs under
|
||||
a CXL Host Bridge (HB). There can be multiple HBs under a CXL Fixed Memory
|
||||
Window Structure (CFMWS).
|
||||
|
||||
An example hierarchy:
|
||||
|
||||
> CFMWS 0
|
||||
> |
|
||||
> _________|_________
|
||||
> | |
|
||||
> ACPI0017-0 ACPI0017-1
|
||||
> GP0/HB0/ACPI0016-0 GP1/HB1/ACPI0016-1
|
||||
> | | | |
|
||||
> RP0 RP1 RP2 RP3
|
||||
> | | | |
|
||||
> SW 0 SW 1 SW 2 SW 3
|
||||
> | | | | | | | |
|
||||
> EP0 EP1 EP2 EP3 EP4 EP5 EP6 EP7
|
||||
|
||||
Computation for the example hierarchy:
|
||||
|
||||
Min (GP0 to CPU BW,
|
||||
Min(SW 0 Upstream Link to RP0 BW,
|
||||
Min(SW0SSLBIS for SW0DSP0 (EP0), EP0 DSLBIS, EP0 Upstream Link) +
|
||||
Min(SW0SSLBIS for SW0DSP1 (EP1), EP1 DSLBIS, EP1 Upstream link)) +
|
||||
Min(SW 1 Upstream Link to RP1 BW,
|
||||
Min(SW1SSLBIS for SW1DSP0 (EP2), EP2 DSLBIS, EP2 Upstream Link) +
|
||||
Min(SW1SSLBIS for SW1DSP1 (EP3), EP3 DSLBIS, EP3 Upstream link))) +
|
||||
Min (GP1 to CPU BW,
|
||||
Min(SW 2 Upstream Link to RP2 BW,
|
||||
Min(SW2SSLBIS for SW2DSP0 (EP4), EP4 DSLBIS, EP4 Upstream Link) +
|
||||
Min(SW2SSLBIS for SW2DSP1 (EP5), EP5 DSLBIS, EP5 Upstream link)) +
|
||||
Min(SW 3 Upstream Link to RP3 BW,
|
||||
Min(SW3SSLBIS for SW3DSP0 (EP6), EP6 DSLBIS, EP6 Upstream Link) +
|
||||
Min(SW3SSLBIS for SW3DSP1 (EP7), EP7 DSLBIS, EP7 Upstream link))))
|
||||
|
||||
The calculation starts at cxl_region_shared_upstream_perf_update(). A xarray
|
||||
is created to collect all the endpoint bandwidths via the
|
||||
cxl_endpoint_gather_bandwidth() function. The min() of bandwidth from the
|
||||
endpoint CDAT and the upstream link bandwidth is calculated. If the endpoint
|
||||
has a CXL switch as a parent, then min() of calculated bandwidth and the
|
||||
bandwidth from the SSLBIS for the switch downstream port that is associated
|
||||
with the endpoint is calculated. The final bandwidth is stored in a
|
||||
'struct cxl_perf_ctx' in the xarray indexed by a device pointer. If the
|
||||
endpoint is direct attached to a root port (RP), the device pointer would be an
|
||||
RP device. If the endpoint is behind a switch, the device pointer would be the
|
||||
upstream device of the parent switch.
|
||||
|
||||
At the next stage, the code walks through one or more switches if they exist
|
||||
in the topology. For endpoints directly attached to RPs, this step is skipped.
|
||||
If there is another switch upstream, the code takes the min() of the current
|
||||
gathered bandwidth and the upstream link bandwidth. If there's a switch
|
||||
upstream, then the SSLBIS of the upstream switch.
|
||||
|
||||
Once the topology walk reaches the RP, whether it's direct attached endpoints
|
||||
or walking through the switch(es), cxl_rp_gather_bandwidth() is called. At
|
||||
this point all the bandwidths are aggregated per each host bridge, which is
|
||||
also the index for the resulting xarray.
|
||||
|
||||
The next step is to take the min() of the per host bridge bandwidth and the
|
||||
bandwidth from the Generic Port (GP). The bandwidths for the GP is retrieved
|
||||
via ACPI tables SRAT/HMAT. The min bandwidth are aggregated under the same
|
||||
ACPI0017 device to form a new xarray.
|
||||
|
||||
Finally, the cxl_region_update_bandwidth() is called and the aggregated
|
||||
bandwidth from all the members of the last xarray is updated for the
|
||||
access coordinates residing in the cxl region (cxlr) context.
|
@ -8,6 +8,7 @@ Compute Express Link
|
||||
:maxdepth: 1
|
||||
|
||||
memory-devices
|
||||
access-coordinates
|
||||
|
||||
maturity-map
|
||||
|
||||
|
@ -144,9 +144,8 @@ IRQ should only be unmasked after a successful call to napi_complete_done():
|
||||
|
||||
napi_schedule_irqoff() is a variant of napi_schedule() which takes advantage
|
||||
of guarantees given by being invoked in IRQ context (no need to
|
||||
mask interrupts). Note that PREEMPT_RT forces all interrupts
|
||||
to be threaded so the interrupt may need to be marked ``IRQF_NO_THREAD``
|
||||
to avoid issues on real-time kernel configurations.
|
||||
mask interrupts). napi_schedule_irqoff() will fall back to napi_schedule() if
|
||||
IRQs are threaded (such as if ``PREEMPT_RT`` is enabled).
|
||||
|
||||
Instance to queue mapping
|
||||
-------------------------
|
||||
|
@ -87,6 +87,38 @@ PCH-LPC/PCH-MSI,然后被EIOINTC统一收集,再直接到达CPUINTC::
|
||||
| Devices |
|
||||
+---------+
|
||||
|
||||
高级扩展IRQ模型
|
||||
===============
|
||||
|
||||
在这种模型里面,IPI(Inter-Processor Interrupt)和CPU本地时钟中断直接发送到CPUINTC,
|
||||
CPU串口(UARTs)中断发送到LIOINTC,PCH-MSI中断发送到AVECINTC,而后通过AVECINTC直接
|
||||
送达CPUINTC,而其他所有设备的中断则分别发送到所连接的PCH-PIC/PCH-LPC,然后由EIOINTC
|
||||
统一收集,再直接到达CPUINTC::
|
||||
|
||||
+-----+ +-----------------------+ +-------+
|
||||
| IPI | --> | CPUINTC | <-- | Timer |
|
||||
+-----+ +-----------------------+ +-------+
|
||||
^ ^ ^
|
||||
| | |
|
||||
+---------+ +----------+ +---------+ +-------+
|
||||
| EIOINTC | | AVECINTC | | LIOINTC | <-- | UARTs |
|
||||
+---------+ +----------+ +---------+ +-------+
|
||||
^ ^
|
||||
| |
|
||||
+---------+ +---------+
|
||||
| PCH-PIC | | PCH-MSI |
|
||||
+---------+ +---------+
|
||||
^ ^ ^
|
||||
| | |
|
||||
+---------+ +---------+ +---------+
|
||||
| Devices | | PCH-LPC | | Devices |
|
||||
+---------+ +---------+ +---------+
|
||||
^
|
||||
|
|
||||
+---------+
|
||||
| Devices |
|
||||
+---------+
|
||||
|
||||
ACPI相关的定义
|
||||
==============
|
||||
|
||||
|
@ -175,7 +175,7 @@ field2会导致非对齐访问,这并不是不合理的。你会期望field2
|
||||
避免非对齐访问
|
||||
==============
|
||||
|
||||
避免非对齐访问的最简单方法是使用<asm/unaligned.h>头文件提供的get_unaligned()和
|
||||
避免非对齐访问的最简单方法是使用<linux/unaligned.h>头文件提供的get_unaligned()和
|
||||
put_unaligned()宏。
|
||||
|
||||
回到前面的一个可能导致非对齐访问的代码例子::
|
||||
|
@ -4214,7 +4214,9 @@ whether or not KVM_CAP_X86_USER_SPACE_MSR's KVM_MSR_EXIT_REASON_FILTER is
|
||||
enabled. If KVM_MSR_EXIT_REASON_FILTER is enabled, KVM will exit to userspace
|
||||
on denied accesses, i.e. userspace effectively intercepts the MSR access. If
|
||||
KVM_MSR_EXIT_REASON_FILTER is not enabled, KVM will inject a #GP into the guest
|
||||
on denied accesses.
|
||||
on denied accesses. Note, if an MSR access is denied during emulation of MSR
|
||||
load/stores during VMX transitions, KVM ignores KVM_MSR_EXIT_REASON_FILTER.
|
||||
See the below warning for full details.
|
||||
|
||||
If an MSR access is allowed by userspace, KVM will emulate and/or virtualize
|
||||
the access in accordance with the vCPU model. Note, KVM may still ultimately
|
||||
@ -4229,9 +4231,22 @@ filtering. In that mode, ``KVM_MSR_FILTER_DEFAULT_DENY`` is invalid and causes
|
||||
an error.
|
||||
|
||||
.. warning::
|
||||
MSR accesses as part of nested VM-Enter/VM-Exit are not filtered.
|
||||
This includes both writes to individual VMCS fields and reads/writes
|
||||
through the MSR lists pointed to by the VMCS.
|
||||
MSR accesses that are side effects of instruction execution (emulated or
|
||||
native) are not filtered as hardware does not honor MSR bitmaps outside of
|
||||
RDMSR and WRMSR, and KVM mimics that behavior when emulating instructions
|
||||
to avoid pointless divergence from hardware. E.g. RDPID reads MSR_TSC_AUX,
|
||||
SYSENTER reads the SYSENTER MSRs, etc.
|
||||
|
||||
MSRs that are loaded/stored via dedicated VMCS fields are not filtered as
|
||||
part of VM-Enter/VM-Exit emulation.
|
||||
|
||||
MSRs that are loaded/store via VMX's load/store lists _are_ filtered as part
|
||||
of VM-Enter/VM-Exit emulation. If an MSR access is denied on VM-Enter, KVM
|
||||
synthesizes a consistency check VM-Exit(EXIT_REASON_MSR_LOAD_FAIL). If an
|
||||
MSR access is denied on VM-Exit, KVM synthesizes a VM-Abort. In short, KVM
|
||||
extends Intel's architectural list of MSRs that cannot be loaded/saved via
|
||||
the VM-Enter/VM-Exit MSR list. It is platform owner's responsibility to
|
||||
to communicate any such restrictions to their end users.
|
||||
|
||||
x2APIC MSR accesses cannot be filtered (KVM silently ignores filters that
|
||||
cover any x2APIC MSRs).
|
||||
@ -8082,6 +8097,14 @@ KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS By default, KVM emulates MONITOR/MWAIT (if
|
||||
guest CPUID on writes to MISC_ENABLE if
|
||||
KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT is
|
||||
disabled.
|
||||
|
||||
KVM_X86_QUIRK_SLOT_ZAP_ALL By default, KVM invalidates all SPTEs in
|
||||
fast way for memslot deletion when VM type
|
||||
is KVM_X86_DEFAULT_VM.
|
||||
When this quirk is disabled or when VM type
|
||||
is other than KVM_X86_DEFAULT_VM, KVM zaps
|
||||
only leaf SPTEs that are within the range of
|
||||
the memslot being deleted.
|
||||
=================================== ============================================
|
||||
|
||||
7.32 KVM_CAP_MAX_VCPU_ID
|
||||
|
@ -11,6 +11,8 @@ The acquisition orders for mutexes are as follows:
|
||||
|
||||
- cpus_read_lock() is taken outside kvm_lock
|
||||
|
||||
- kvm_usage_lock is taken outside cpus_read_lock()
|
||||
|
||||
- kvm->lock is taken outside vcpu->mutex
|
||||
|
||||
- kvm->lock is taken outside kvm->slots_lock and kvm->irq_lock
|
||||
@ -24,6 +26,13 @@ The acquisition orders for mutexes are as follows:
|
||||
are taken on the waiting side when modifying memslots, so MMU notifiers
|
||||
must not take either kvm->slots_lock or kvm->slots_arch_lock.
|
||||
|
||||
cpus_read_lock() vs kvm_lock:
|
||||
|
||||
- Taking cpus_read_lock() outside of kvm_lock is problematic, despite that
|
||||
being the official ordering, as it is quite easy to unknowingly trigger
|
||||
cpus_read_lock() while holding kvm_lock. Use caution when walking vm_list,
|
||||
e.g. avoid complex operations when possible.
|
||||
|
||||
For SRCU:
|
||||
|
||||
- ``synchronize_srcu(&kvm->srcu)`` is called inside critical sections
|
||||
@ -227,10 +236,16 @@ time it will be set using the Dirty tracking mechanism described above.
|
||||
:Type: mutex
|
||||
:Arch: any
|
||||
:Protects: - vm_list
|
||||
- kvm_usage_count
|
||||
|
||||
``kvm_usage_lock``
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:Type: mutex
|
||||
:Arch: any
|
||||
:Protects: - kvm_usage_count
|
||||
- hardware virtualization enable/disable
|
||||
:Comment: KVM also disables CPU hotplug via cpus_read_lock() during
|
||||
enable/disable.
|
||||
:Comment: Exists to allow taking cpus_read_lock() while kvm_usage_count is
|
||||
protected, which simplifies the virtualization enabling logic.
|
||||
|
||||
``kvm->mn_invalidate_lock``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -290,11 +305,12 @@ time it will be set using the Dirty tracking mechanism described above.
|
||||
wakeup.
|
||||
|
||||
``vendor_module_lock``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
:Type: mutex
|
||||
:Arch: x86
|
||||
:Protects: loading a vendor module (kvm_amd or kvm_intel)
|
||||
:Comment: Exists because using kvm_lock leads to deadlock. cpu_hotplug_lock is
|
||||
taken outside of kvm_lock, e.g. in KVM's CPU online/offline callbacks, and
|
||||
many operations need to take cpu_hotplug_lock when loading a vendor module,
|
||||
e.g. updating static calls.
|
||||
:Comment: Exists because using kvm_lock leads to deadlock. kvm_lock is taken
|
||||
in notifiers, e.g. __kvmclock_cpufreq_notifier(), that may be invoked while
|
||||
cpu_hotplug_lock is held, e.g. from cpufreq_boost_trigger_state(), and many
|
||||
operations need to take cpu_hotplug_lock when loading a vendor module, e.g.
|
||||
updating static calls.
|
||||
|
@ -217,6 +217,8 @@ remote UML and other VM instances.
|
||||
+-----------+--------+------------------------------------+------------+
|
||||
| fd | vector | dependent on fd type | varies |
|
||||
+-----------+--------+------------------------------------+------------+
|
||||
| vde | vector | dep. on VDE VPN: Virt.Net Locator | varies |
|
||||
+-----------+--------+------------------------------------+------------+
|
||||
| tuntap | legacy | none | ~ 500Mbit |
|
||||
+-----------+--------+------------------------------------+------------+
|
||||
| daemon | legacy | none | ~ 450Mbit |
|
||||
@ -573,6 +575,41 @@ https://github.com/NetSys/bess/wiki/Built-In-Modules-and-Ports
|
||||
|
||||
BESS transport does not require any special privileges.
|
||||
|
||||
VDE vector transport
|
||||
--------------------
|
||||
|
||||
Virtual Distributed Ethernet (VDE) is a project whose main goal is to provide a
|
||||
highly flexible support for virtual networking.
|
||||
|
||||
http://wiki.virtualsquare.org/#/tutorials/vdebasics
|
||||
|
||||
Common usages of VDE include fast prototyping and teaching.
|
||||
|
||||
Examples:
|
||||
|
||||
``vecX:transport=vde,vnl=tap://tap0``
|
||||
|
||||
use tap0
|
||||
|
||||
``vecX:transport=vde,vnl=slirp://``
|
||||
|
||||
use slirp
|
||||
|
||||
``vec0:transport=vde,vnl=vde:///tmp/switch``
|
||||
|
||||
connect to a vde switch
|
||||
|
||||
``vecX:transport=\"vde,vnl=cmd://ssh remote.host //tmp/sshlirp\"``
|
||||
|
||||
connect to a remote slirp (instant VPN: convert ssh to VPN, it uses sshlirp)
|
||||
https://github.com/virtualsquare/sshlirp
|
||||
|
||||
``vec0:transport=vde,vnl=vxvde://234.0.0.1``
|
||||
|
||||
connect to a local area cloud (all the UML nodes using the same
|
||||
multicast address running on hosts in the same multicast domain (LAN)
|
||||
will be automagically connected together to a virtual LAN.
|
||||
|
||||
Configuring Legacy transports
|
||||
=============================
|
||||
|
||||
|
@ -75,7 +75,6 @@ Example conversion::
|
||||
|
||||
-static const struct file_operations s3c2410wdt_fops = {
|
||||
- .owner = THIS_MODULE,
|
||||
- .llseek = no_llseek,
|
||||
- .write = s3c2410wdt_write,
|
||||
- .unlocked_ioctl = s3c2410wdt_ioctl,
|
||||
- .open = s3c2410wdt_open,
|
||||
|
12
MAINTAINERS
12
MAINTAINERS
@ -2272,6 +2272,7 @@ N: clps711x
|
||||
ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE
|
||||
M: Hartley Sweeten <hsweeten@visionengravers.com>
|
||||
M: Alexander Sverdlin <alexander.sverdlin@gmail.com>
|
||||
M: Nikita Shubin <nikita.shubin@maquefel.me>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/adc/cirrus,ep9301-adc.yaml
|
||||
@ -5727,8 +5728,7 @@ L: linux-cxl@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/driver-api/cxl
|
||||
F: drivers/cxl/
|
||||
F: include/linux/einj-cxl.h
|
||||
F: include/linux/cxl-event.h
|
||||
F: include/cxl/
|
||||
F: include/uapi/linux/cxl_mem.h
|
||||
F: tools/testing/cxl/
|
||||
|
||||
@ -15678,6 +15678,9 @@ F: include/dt-bindings/clock/mobileye,eyeq5-clk.h
|
||||
|
||||
MODULE SUPPORT
|
||||
M: Luis Chamberlain <mcgrof@kernel.org>
|
||||
R: Petr Pavlu <petr.pavlu@suse.com>
|
||||
R: Sami Tolvanen <samitolvanen@google.com>
|
||||
R: Daniel Gomez <da.gomez@samsung.com>
|
||||
L: linux-modules@vger.kernel.org
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
@ -19344,10 +19347,7 @@ F: drivers/char/random.c
|
||||
F: include/linux/random.h
|
||||
F: include/uapi/linux/random.h
|
||||
F: drivers/virt/vmgenid.c
|
||||
F: include/vdso/getrandom.h
|
||||
F: lib/vdso/getrandom.c
|
||||
F: arch/x86/entry/vdso/vgetrandom*
|
||||
F: arch/x86/include/asm/vdso/getrandom*
|
||||
N: ^.*/vdso/[^/]*getrandom[^/]+$
|
||||
|
||||
RAPIDIO SUBSYSTEM
|
||||
M: Matt Porter <mporter@kernel.crashing.org>
|
||||
|
4
Makefile
4
Makefile
@ -1,8 +1,8 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 11
|
||||
PATCHLEVEL = 12
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION =
|
||||
EXTRAVERSION = -rc1
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
@ -3,17 +3,232 @@
|
||||
#define _ALPHA_CMPXCHG_H
|
||||
|
||||
/*
|
||||
* Atomic exchange routines.
|
||||
* Atomic exchange.
|
||||
* Since it can be used to implement critical sections
|
||||
* it must clobber "memory" (also for interrupts in UP).
|
||||
*/
|
||||
|
||||
#define ____xchg(type, args...) __arch_xchg ## type ## _local(args)
|
||||
#define ____cmpxchg(type, args...) __cmpxchg ## type ## _local(args)
|
||||
#include <asm/xchg.h>
|
||||
static inline unsigned long
|
||||
____xchg_u8(volatile char *m, unsigned long val)
|
||||
{
|
||||
unsigned long ret, tmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %4,7,%3\n"
|
||||
" insbl %1,%4,%1\n"
|
||||
"1: ldq_l %2,0(%3)\n"
|
||||
" extbl %2,%4,%0\n"
|
||||
" mskbl %2,%4,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%3)\n"
|
||||
" beq %2,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "1" (val) : "memory");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____xchg_u16(volatile short *m, unsigned long val)
|
||||
{
|
||||
unsigned long ret, tmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %4,7,%3\n"
|
||||
" inswl %1,%4,%1\n"
|
||||
"1: ldq_l %2,0(%3)\n"
|
||||
" extwl %2,%4,%0\n"
|
||||
" mskwl %2,%4,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%3)\n"
|
||||
" beq %2,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "1" (val) : "memory");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____xchg_u32(volatile int *m, unsigned long val)
|
||||
{
|
||||
unsigned long dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldl_l %0,%4\n"
|
||||
" bis $31,%3,%1\n"
|
||||
" stl_c %1,%2\n"
|
||||
" beq %1,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (val), "=&r" (dummy), "=m" (*m)
|
||||
: "rI" (val), "m" (*m) : "memory");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____xchg_u64(volatile long *m, unsigned long val)
|
||||
{
|
||||
unsigned long dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldq_l %0,%4\n"
|
||||
" bis $31,%3,%1\n"
|
||||
" stq_c %1,%2\n"
|
||||
" beq %1,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (val), "=&r" (dummy), "=m" (*m)
|
||||
: "rI" (val), "m" (*m) : "memory");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* This function doesn't exist, so you'll get a linker error
|
||||
if something tries to do an invalid xchg(). */
|
||||
extern void __xchg_called_with_bad_pointer(void);
|
||||
|
||||
static __always_inline unsigned long
|
||||
____xchg(volatile void *ptr, unsigned long x, int size)
|
||||
{
|
||||
return
|
||||
size == 1 ? ____xchg_u8(ptr, x) :
|
||||
size == 2 ? ____xchg_u16(ptr, x) :
|
||||
size == 4 ? ____xchg_u32(ptr, x) :
|
||||
size == 8 ? ____xchg_u64(ptr, x) :
|
||||
(__xchg_called_with_bad_pointer(), x);
|
||||
}
|
||||
|
||||
/*
|
||||
* Atomic compare and exchange. Compare OLD with MEM, if identical,
|
||||
* store NEW in MEM. Return the initial value in MEM. Success is
|
||||
* indicated by comparing RETURN with OLD.
|
||||
*/
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg_u8(volatile char *m, unsigned char old, unsigned char new)
|
||||
{
|
||||
unsigned long prev, tmp, cmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %5,7,%4\n"
|
||||
" insbl %1,%5,%1\n"
|
||||
"1: ldq_l %2,0(%4)\n"
|
||||
" extbl %2,%5,%0\n"
|
||||
" cmpeq %0,%6,%3\n"
|
||||
" beq %3,2f\n"
|
||||
" mskbl %2,%5,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%4)\n"
|
||||
" beq %2,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "Ir" (old), "1" (new) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg_u16(volatile short *m, unsigned short old, unsigned short new)
|
||||
{
|
||||
unsigned long prev, tmp, cmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %5,7,%4\n"
|
||||
" inswl %1,%5,%1\n"
|
||||
"1: ldq_l %2,0(%4)\n"
|
||||
" extwl %2,%5,%0\n"
|
||||
" cmpeq %0,%6,%3\n"
|
||||
" beq %3,2f\n"
|
||||
" mskwl %2,%5,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%4)\n"
|
||||
" beq %2,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "Ir" (old), "1" (new) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg_u32(volatile int *m, int old, int new)
|
||||
{
|
||||
unsigned long prev, cmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldl_l %0,%5\n"
|
||||
" cmpeq %0,%3,%1\n"
|
||||
" beq %1,2f\n"
|
||||
" mov %4,%1\n"
|
||||
" stl_c %1,%2\n"
|
||||
" beq %1,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
||||
: "r"((long) old), "r"(new), "m"(*m) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
|
||||
{
|
||||
unsigned long prev, cmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldq_l %0,%5\n"
|
||||
" cmpeq %0,%3,%1\n"
|
||||
" beq %1,2f\n"
|
||||
" mov %4,%1\n"
|
||||
" stq_c %1,%2\n"
|
||||
" beq %1,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
||||
: "r"((long) old), "r"(new), "m"(*m) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
/* This function doesn't exist, so you'll get a linker error
|
||||
if something tries to do an invalid cmpxchg(). */
|
||||
extern void __cmpxchg_called_with_bad_pointer(void);
|
||||
|
||||
static __always_inline unsigned long
|
||||
____cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
|
||||
int size)
|
||||
{
|
||||
return
|
||||
size == 1 ? ____cmpxchg_u8(ptr, old, new) :
|
||||
size == 2 ? ____cmpxchg_u16(ptr, old, new) :
|
||||
size == 4 ? ____cmpxchg_u32(ptr, old, new) :
|
||||
size == 8 ? ____cmpxchg_u64(ptr, old, new) :
|
||||
(__cmpxchg_called_with_bad_pointer(), old);
|
||||
}
|
||||
|
||||
#define xchg_local(ptr, x) \
|
||||
({ \
|
||||
__typeof__(*(ptr)) _x_ = (x); \
|
||||
(__typeof__(*(ptr))) __arch_xchg_local((ptr), (unsigned long)_x_,\
|
||||
(__typeof__(*(ptr))) ____xchg((ptr), (unsigned long)_x_, \
|
||||
sizeof(*(ptr))); \
|
||||
})
|
||||
|
||||
@ -21,7 +236,7 @@
|
||||
({ \
|
||||
__typeof__(*(ptr)) _o_ = (o); \
|
||||
__typeof__(*(ptr)) _n_ = (n); \
|
||||
(__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_, \
|
||||
(__typeof__(*(ptr))) ____cmpxchg((ptr), (unsigned long)_o_, \
|
||||
(unsigned long)_n_, \
|
||||
sizeof(*(ptr))); \
|
||||
})
|
||||
@ -32,12 +247,6 @@
|
||||
cmpxchg_local((ptr), (o), (n)); \
|
||||
})
|
||||
|
||||
#undef ____xchg
|
||||
#undef ____cmpxchg
|
||||
#define ____xchg(type, args...) __arch_xchg ##type(args)
|
||||
#define ____cmpxchg(type, args...) __cmpxchg ##type(args)
|
||||
#include <asm/xchg.h>
|
||||
|
||||
/*
|
||||
* The leading and the trailing memory barriers guarantee that these
|
||||
* operations are fully ordered.
|
||||
@ -48,7 +257,7 @@
|
||||
__typeof__(*(ptr)) _x_ = (x); \
|
||||
smp_mb(); \
|
||||
__ret = (__typeof__(*(ptr))) \
|
||||
__arch_xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \
|
||||
____xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \
|
||||
smp_mb(); \
|
||||
__ret; \
|
||||
})
|
||||
@ -59,7 +268,7 @@
|
||||
__typeof__(*(ptr)) _o_ = (o); \
|
||||
__typeof__(*(ptr)) _n_ = (n); \
|
||||
smp_mb(); \
|
||||
__ret = (__typeof__(*(ptr))) __cmpxchg((ptr), \
|
||||
__ret = (__typeof__(*(ptr))) ____cmpxchg((ptr), \
|
||||
(unsigned long)_o_, (unsigned long)_n_, sizeof(*(ptr)));\
|
||||
smp_mb(); \
|
||||
__ret; \
|
||||
@ -71,6 +280,4 @@
|
||||
arch_cmpxchg((ptr), (o), (n)); \
|
||||
})
|
||||
|
||||
#undef ____cmpxchg
|
||||
|
||||
#endif /* _ALPHA_CMPXCHG_H */
|
||||
|
@ -1,246 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ALPHA_CMPXCHG_H
|
||||
#error Do not include xchg.h directly!
|
||||
#else
|
||||
/*
|
||||
* xchg/xchg_local and cmpxchg/cmpxchg_local share the same code
|
||||
* except that local version do not have the expensive memory barrier.
|
||||
* So this file is included twice from asm/cmpxchg.h.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Atomic exchange.
|
||||
* Since it can be used to implement critical sections
|
||||
* it must clobber "memory" (also for interrupts in UP).
|
||||
*/
|
||||
|
||||
static inline unsigned long
|
||||
____xchg(_u8, volatile char *m, unsigned long val)
|
||||
{
|
||||
unsigned long ret, tmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %4,7,%3\n"
|
||||
" insbl %1,%4,%1\n"
|
||||
"1: ldq_l %2,0(%3)\n"
|
||||
" extbl %2,%4,%0\n"
|
||||
" mskbl %2,%4,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%3)\n"
|
||||
" beq %2,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "1" (val) : "memory");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____xchg(_u16, volatile short *m, unsigned long val)
|
||||
{
|
||||
unsigned long ret, tmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %4,7,%3\n"
|
||||
" inswl %1,%4,%1\n"
|
||||
"1: ldq_l %2,0(%3)\n"
|
||||
" extwl %2,%4,%0\n"
|
||||
" mskwl %2,%4,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%3)\n"
|
||||
" beq %2,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "1" (val) : "memory");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____xchg(_u32, volatile int *m, unsigned long val)
|
||||
{
|
||||
unsigned long dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldl_l %0,%4\n"
|
||||
" bis $31,%3,%1\n"
|
||||
" stl_c %1,%2\n"
|
||||
" beq %1,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (val), "=&r" (dummy), "=m" (*m)
|
||||
: "rI" (val), "m" (*m) : "memory");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____xchg(_u64, volatile long *m, unsigned long val)
|
||||
{
|
||||
unsigned long dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldq_l %0,%4\n"
|
||||
" bis $31,%3,%1\n"
|
||||
" stq_c %1,%2\n"
|
||||
" beq %1,2f\n"
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (val), "=&r" (dummy), "=m" (*m)
|
||||
: "rI" (val), "m" (*m) : "memory");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* This function doesn't exist, so you'll get a linker error
|
||||
if something tries to do an invalid xchg(). */
|
||||
extern void __xchg_called_with_bad_pointer(void);
|
||||
|
||||
static __always_inline unsigned long
|
||||
____xchg(, volatile void *ptr, unsigned long x, int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
return ____xchg(_u8, ptr, x);
|
||||
case 2:
|
||||
return ____xchg(_u16, ptr, x);
|
||||
case 4:
|
||||
return ____xchg(_u32, ptr, x);
|
||||
case 8:
|
||||
return ____xchg(_u64, ptr, x);
|
||||
}
|
||||
__xchg_called_with_bad_pointer();
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Atomic compare and exchange. Compare OLD with MEM, if identical,
|
||||
* store NEW in MEM. Return the initial value in MEM. Success is
|
||||
* indicated by comparing RETURN with OLD.
|
||||
*/
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg(_u8, volatile char *m, unsigned char old, unsigned char new)
|
||||
{
|
||||
unsigned long prev, tmp, cmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %5,7,%4\n"
|
||||
" insbl %1,%5,%1\n"
|
||||
"1: ldq_l %2,0(%4)\n"
|
||||
" extbl %2,%5,%0\n"
|
||||
" cmpeq %0,%6,%3\n"
|
||||
" beq %3,2f\n"
|
||||
" mskbl %2,%5,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%4)\n"
|
||||
" beq %2,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "Ir" (old), "1" (new) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg(_u16, volatile short *m, unsigned short old, unsigned short new)
|
||||
{
|
||||
unsigned long prev, tmp, cmp, addr64;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" andnot %5,7,%4\n"
|
||||
" inswl %1,%5,%1\n"
|
||||
"1: ldq_l %2,0(%4)\n"
|
||||
" extwl %2,%5,%0\n"
|
||||
" cmpeq %0,%6,%3\n"
|
||||
" beq %3,2f\n"
|
||||
" mskwl %2,%5,%2\n"
|
||||
" or %1,%2,%2\n"
|
||||
" stq_c %2,0(%4)\n"
|
||||
" beq %2,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64)
|
||||
: "r" ((long)m), "Ir" (old), "1" (new) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg(_u32, volatile int *m, int old, int new)
|
||||
{
|
||||
unsigned long prev, cmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldl_l %0,%5\n"
|
||||
" cmpeq %0,%3,%1\n"
|
||||
" beq %1,2f\n"
|
||||
" mov %4,%1\n"
|
||||
" stl_c %1,%2\n"
|
||||
" beq %1,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
||||
: "r"((long) old), "r"(new), "m"(*m) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
____cmpxchg(_u64, volatile long *m, unsigned long old, unsigned long new)
|
||||
{
|
||||
unsigned long prev, cmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldq_l %0,%5\n"
|
||||
" cmpeq %0,%3,%1\n"
|
||||
" beq %1,2f\n"
|
||||
" mov %4,%1\n"
|
||||
" stq_c %1,%2\n"
|
||||
" beq %1,3f\n"
|
||||
"2:\n"
|
||||
".subsection 2\n"
|
||||
"3: br 1b\n"
|
||||
".previous"
|
||||
: "=&r"(prev), "=&r"(cmp), "=m"(*m)
|
||||
: "r"((long) old), "r"(new), "m"(*m) : "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
/* This function doesn't exist, so you'll get a linker error
|
||||
if something tries to do an invalid cmpxchg(). */
|
||||
extern void __cmpxchg_called_with_bad_pointer(void);
|
||||
|
||||
static __always_inline unsigned long
|
||||
____cmpxchg(, volatile void *ptr, unsigned long old, unsigned long new,
|
||||
int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
return ____cmpxchg(_u8, ptr, old, new);
|
||||
case 2:
|
||||
return ____cmpxchg(_u16, ptr, old, new);
|
||||
case 4:
|
||||
return ____cmpxchg(_u32, ptr, old, new);
|
||||
case 8:
|
||||
return ____cmpxchg(_u64, ptr, old, new);
|
||||
}
|
||||
__cmpxchg_called_with_bad_pointer();
|
||||
return old;
|
||||
}
|
||||
|
||||
#endif
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include <asm/gentrap.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <asm/sysinfo.h>
|
||||
#include <asm/hwrpb.h>
|
||||
#include <asm/mmu_context.h>
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
|
||||
#ifdef CONFIG_ISA_ARCV2
|
||||
#include <asm/barrier.h>
|
||||
|
@ -14,6 +14,7 @@ typedef struct {
|
||||
unsigned long asid[NR_CPUS]; /* 8 bit MMU PID + Generation cycle */
|
||||
} mm_context_t;
|
||||
|
||||
struct pt_regs;
|
||||
extern void do_tlb_overlap_fault(unsigned long, unsigned long, struct pt_regs *);
|
||||
|
||||
#endif
|
||||
|
@ -1,27 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
|
||||
*/
|
||||
|
||||
#ifndef _ASM_ARC_UNALIGNED_H
|
||||
#define _ASM_ARC_UNALIGNED_H
|
||||
|
||||
/* ARC700 can't handle unaligned Data accesses. */
|
||||
|
||||
#include <asm-generic/unaligned.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
#ifdef CONFIG_ARC_EMUL_UNALIGNED
|
||||
int misaligned_fixup(unsigned long address, struct pt_regs *regs,
|
||||
struct callee_regs *cregs);
|
||||
#else
|
||||
static inline int
|
||||
misaligned_fixup(unsigned long address, struct pt_regs *regs,
|
||||
struct callee_regs *cregs)
|
||||
{
|
||||
/* Not fixed */
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_ARC_UNALIGNED_H */
|
@ -18,8 +18,9 @@
|
||||
#include <linux/kgdb.h>
|
||||
#include <asm/entry.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <asm/kprobes.h>
|
||||
#include "unaligned.h"
|
||||
|
||||
void die(const char *str, struct pt_regs *regs, unsigned long address)
|
||||
{
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/disasm.h>
|
||||
#include "unaligned.h"
|
||||
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
#define BE 1
|
||||
|
16
arch/arc/kernel/unaligned.h
Normal file
16
arch/arc/kernel/unaligned.h
Normal file
@ -0,0 +1,16 @@
|
||||
struct pt_regs;
|
||||
struct callee_regs;
|
||||
|
||||
#ifdef CONFIG_ARC_EMUL_UNALIGNED
|
||||
int misaligned_fixup(unsigned long address, struct pt_regs *regs,
|
||||
struct callee_regs *cregs);
|
||||
#else
|
||||
static inline int
|
||||
misaligned_fixup(unsigned long address, struct pt_regs *regs,
|
||||
struct callee_regs *cregs)
|
||||
{
|
||||
/* Not fixed */
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <asm/unwind.h>
|
||||
|
||||
extern char __start_unwind[], __end_unwind[];
|
||||
|
@ -183,7 +183,6 @@ machine-$(CONFIG_ARCH_CLPS711X) += clps711x
|
||||
machine-$(CONFIG_ARCH_DAVINCI) += davinci
|
||||
machine-$(CONFIG_ARCH_DIGICOLOR) += digicolor
|
||||
machine-$(CONFIG_ARCH_DOVE) += dove
|
||||
machine-$(CONFIG_ARCH_EP93XX) += ep93xx
|
||||
machine-$(CONFIG_ARCH_EXYNOS) += exynos
|
||||
machine-$(CONFIG_ARCH_FOOTBRIDGE) += footbridge
|
||||
machine-$(CONFIG_ARCH_GEMINI) += gemini
|
||||
|
@ -3,3 +3,7 @@ dtb-$(CONFIG_ARCH_CLPS711X) += \
|
||||
ep7211-edb7211.dtb
|
||||
dtb-$(CONFIG_ARCH_CLPS711X) += \
|
||||
ep7211-edb7211.dtb
|
||||
dtb-$(CONFIG_ARCH_EP93XX) += \
|
||||
ep93xx-edb9302.dtb \
|
||||
ep93xx-bk3.dtb \
|
||||
ep93xx-ts7250.dtb
|
||||
|
125
arch/arm/boot/dts/cirrus/ep93xx-bk3.dts
Normal file
125
arch/arm/boot/dts/cirrus/ep93xx-bk3.dts
Normal file
@ -0,0 +1,125 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Device Tree file for Liebherr controller BK3.1 based on Cirrus EP9302 SoC
|
||||
*/
|
||||
/dts-v1/;
|
||||
#include "ep93xx.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Liebherr controller BK3.1";
|
||||
compatible = "liebherr,bk3", "cirrus,ep9301";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
chosen {
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
/* should be set from ATAGS */
|
||||
reg = <0x00000000 0x02000000>,
|
||||
<0x000530c0 0x01fdd000>;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
led-0 {
|
||||
label = "grled";
|
||||
gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "heartbeat";
|
||||
function = LED_FUNCTION_HEARTBEAT;
|
||||
};
|
||||
|
||||
led-1 {
|
||||
label = "rdled";
|
||||
gpios = <&gpio4 1 GPIO_ACTIVE_HIGH>;
|
||||
function = LED_FUNCTION_FAULT;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&ebi {
|
||||
nand-controller@60000000 {
|
||||
compatible = "technologic,ts7200-nand";
|
||||
reg = <0x60000000 0x8000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
nand@0 {
|
||||
reg = <0>;
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "System";
|
||||
reg = <0x00000000 0x01e00000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@1e00000 {
|
||||
label = "Data";
|
||||
reg = <0x01e00000 0x05f20000>;
|
||||
};
|
||||
|
||||
partition@7d20000 {
|
||||
label = "RedBoot";
|
||||
reg = <0x07d20000 0x002e0000>;
|
||||
read-only;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ð0 {
|
||||
phy-handle = <&phy0>;
|
||||
};
|
||||
|
||||
&i2s {
|
||||
dmas = <&dma0 0 1>, <&dma0 0 2>;
|
||||
dma-names = "tx", "rx";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2s_on_ac97_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
/* PWM */
|
||||
gpio-ranges = <&syscon 6 163 1>;
|
||||
};
|
||||
|
||||
&gpio4 {
|
||||
gpio-ranges = <&syscon 0 97 2>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio6 {
|
||||
gpio-ranges = <&syscon 0 87 2>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio7 {
|
||||
gpio-ranges = <&syscon 2 199 4>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mdio0 {
|
||||
phy0: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb0 {
|
||||
status = "okay";
|
||||
};
|
181
arch/arm/boot/dts/cirrus/ep93xx-edb9302.dts
Normal file
181
arch/arm/boot/dts/cirrus/ep93xx-edb9302.dts
Normal file
@ -0,0 +1,181 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
/*
|
||||
* Device Tree file for Cirrus Logic EDB9302 board based on EP9302 SoC
|
||||
*/
|
||||
/dts-v1/;
|
||||
#include "ep93xx.dtsi"
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "cirrus,edb9302", "cirrus,ep9301";
|
||||
model = "cirrus,edb9302";
|
||||
|
||||
chosen {
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
/* should be set from ATAGS */
|
||||
reg = <0x0000000 0x800000>,
|
||||
<0x1000000 0x800000>,
|
||||
<0x4000000 0x800000>,
|
||||
<0x5000000 0x800000>;
|
||||
};
|
||||
|
||||
sound {
|
||||
compatible = "audio-graph-card2";
|
||||
label = "EDB93XX";
|
||||
links = <&i2s_port>;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
led-0 {
|
||||
label = "grled";
|
||||
gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "heartbeat";
|
||||
function = LED_FUNCTION_HEARTBEAT;
|
||||
};
|
||||
|
||||
led-1 {
|
||||
label = "rdled";
|
||||
gpios = <&gpio4 1 GPIO_ACTIVE_HIGH>;
|
||||
function = LED_FUNCTION_FAULT;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&adc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&ebi {
|
||||
flash@60000000 {
|
||||
compatible = "cfi-flash";
|
||||
reg = <0x60000000 0x1000000>;
|
||||
bank-width = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
ð0 {
|
||||
phy-handle = <&phy0>;
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
gpio-ranges = <&syscon 0 153 1>,
|
||||
<&syscon 1 152 1>,
|
||||
<&syscon 2 151 1>,
|
||||
<&syscon 3 148 1>,
|
||||
<&syscon 4 147 1>,
|
||||
<&syscon 5 146 1>,
|
||||
<&syscon 6 145 1>,
|
||||
<&syscon 7 144 1>;
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
gpio-ranges = <&syscon 0 143 1>,
|
||||
<&syscon 1 142 1>,
|
||||
<&syscon 2 141 1>,
|
||||
<&syscon 3 140 1>,
|
||||
<&syscon 4 165 1>,
|
||||
<&syscon 5 164 1>,
|
||||
<&syscon 6 163 1>,
|
||||
<&syscon 7 160 1>;
|
||||
};
|
||||
|
||||
&gpio2 {
|
||||
gpio-ranges = <&syscon 0 115 1>;
|
||||
};
|
||||
|
||||
/* edb9302 doesn't have GPIO Port D present */
|
||||
&gpio3 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&gpio4 {
|
||||
gpio-ranges = <&syscon 0 97 2>;
|
||||
};
|
||||
|
||||
&gpio5 {
|
||||
gpio-ranges = <&syscon 1 170 1>,
|
||||
<&syscon 2 169 1>,
|
||||
<&syscon 3 168 1>;
|
||||
};
|
||||
|
||||
&gpio6 {
|
||||
gpio-ranges = <&syscon 0 87 2>;
|
||||
};
|
||||
|
||||
&gpio7 {
|
||||
gpio-ranges = <&syscon 2 199 4>;
|
||||
};
|
||||
|
||||
&i2s {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2s_on_ac97_pins>;
|
||||
status = "okay";
|
||||
i2s_port: port {
|
||||
i2s_ep: endpoint {
|
||||
system-clock-direction-out;
|
||||
frame-master;
|
||||
bitclock-master;
|
||||
mclk-fs = <256>;
|
||||
dai-format = "i2s";
|
||||
convert-channels = <2>;
|
||||
convert-sample-format = "s32_le";
|
||||
remote-endpoint = <&codec_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&mdio0 {
|
||||
phy0: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
cs-gpios = <&gpio0 6 GPIO_ACTIVE_LOW
|
||||
&gpio0 7 GPIO_ACTIVE_LOW>;
|
||||
dmas = <&dma1 10 2>, <&dma1 10 1>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "okay";
|
||||
|
||||
cs4271: codec@0 {
|
||||
compatible = "cirrus,cs4271";
|
||||
reg = <0>;
|
||||
#sound-dai-cells = <0>;
|
||||
spi-max-frequency = <6000000>;
|
||||
spi-cpol;
|
||||
spi-cpha;
|
||||
reset-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
|
||||
port {
|
||||
codec_ep: endpoint {
|
||||
remote-endpoint = <&i2s_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
at25f1024: eeprom@1 {
|
||||
compatible = "atmel,at25";
|
||||
reg = <1>;
|
||||
address-width = <8>;
|
||||
size = <0x20000>;
|
||||
pagesize = <256>;
|
||||
spi-max-frequency = <20000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb0 {
|
||||
status = "okay";
|
||||
};
|
145
arch/arm/boot/dts/cirrus/ep93xx-ts7250.dts
Normal file
145
arch/arm/boot/dts/cirrus/ep93xx-ts7250.dts
Normal file
@ -0,0 +1,145 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Device Tree file for Technologic Systems ts7250 board based on Cirrus EP9302 SoC
|
||||
*/
|
||||
/dts-v1/;
|
||||
#include "ep93xx.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "technologic,ts7250", "cirrus,ep9301";
|
||||
model = "TS-7250 SBC";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
chosen {
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
/* should be set from ATAGS */
|
||||
reg = <0x00000000 0x02000000>,
|
||||
<0x000530c0 0x01fdd000>;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
led-0 {
|
||||
label = "grled";
|
||||
gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "heartbeat";
|
||||
function = LED_FUNCTION_HEARTBEAT;
|
||||
};
|
||||
|
||||
led-1 {
|
||||
label = "rdled";
|
||||
gpios = <&gpio4 1 GPIO_ACTIVE_HIGH>;
|
||||
function = LED_FUNCTION_FAULT;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&ebi {
|
||||
nand-controller@60000000 {
|
||||
compatible = "technologic,ts7200-nand";
|
||||
reg = <0x60000000 0x8000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
nand@0 {
|
||||
reg = <0>;
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "TS-BOOTROM";
|
||||
reg = <0x00000000 0x00020000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@20000 {
|
||||
label = "Linux";
|
||||
reg = <0x00020000 0x07d00000>;
|
||||
};
|
||||
|
||||
partition@7d20000 {
|
||||
label = "RedBoot";
|
||||
reg = <0x07d20000 0x002e0000>;
|
||||
read-only;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
rtc@10800000 {
|
||||
compatible = "st,m48t86";
|
||||
reg = <0x10800000 0x1>,
|
||||
<0x11700000 0x1>;
|
||||
};
|
||||
|
||||
watchdog@23800000 {
|
||||
compatible = "technologic,ts7200-wdt";
|
||||
reg = <0x23800000 0x01>,
|
||||
<0x23c00000 0x01>;
|
||||
timeout-sec = <30>;
|
||||
};
|
||||
};
|
||||
|
||||
ð0 {
|
||||
phy-handle = <&phy0>;
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
/* PWM */
|
||||
gpio-ranges = <&syscon 6 163 1>;
|
||||
};
|
||||
|
||||
/* ts7250 doesn't have GPIO Port D present */
|
||||
&gpio3 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&gpio4 {
|
||||
gpio-ranges = <&syscon 0 97 2>;
|
||||
};
|
||||
|
||||
&gpio6 {
|
||||
gpio-ranges = <&syscon 0 87 2>;
|
||||
};
|
||||
|
||||
&gpio7 {
|
||||
gpio-ranges = <&syscon 2 199 4>;
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
cs-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
|
||||
dmas = <&dma1 10 2>, <&dma1 10 1>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "okay";
|
||||
|
||||
tmp122: temperature-sensor@0 {
|
||||
compatible = "ti,tmp122";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <2000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&mdio0 {
|
||||
phy0: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb0 {
|
||||
status = "okay";
|
||||
};
|
444
arch/arm/boot/dts/cirrus/ep93xx.dtsi
Normal file
444
arch/arm/boot/dts/cirrus/ep93xx.dtsi
Normal file
@ -0,0 +1,444 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Device Tree file for Cirrus Logic systems EP93XX SoC
|
||||
*/
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/clock/cirrus,ep9301-syscon.h>
|
||||
/ {
|
||||
soc: soc {
|
||||
compatible = "simple-bus";
|
||||
ranges;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
syscon: syscon@80930000 {
|
||||
compatible = "cirrus,ep9301-syscon", "syscon";
|
||||
reg = <0x80930000 0x1000>;
|
||||
|
||||
#clock-cells = <1>;
|
||||
clocks = <&xtali>;
|
||||
|
||||
spi_default_pins: pins-spi {
|
||||
function = "spi";
|
||||
groups = "ssp";
|
||||
};
|
||||
|
||||
ac97_default_pins: pins-ac97 {
|
||||
function = "ac97";
|
||||
groups = "ac97";
|
||||
};
|
||||
|
||||
i2s_on_ssp_pins: pins-i2sonssp {
|
||||
function = "i2s";
|
||||
groups = "i2s_on_ssp";
|
||||
};
|
||||
|
||||
i2s_on_ac97_pins: pins-i2sonac97 {
|
||||
function = "i2s";
|
||||
groups = "i2s_on_ac97";
|
||||
};
|
||||
|
||||
gpio1_default_pins: pins-gpio1 {
|
||||
function = "gpio";
|
||||
groups = "gpio1agrp";
|
||||
};
|
||||
|
||||
pwm1_default_pins: pins-pwm1 {
|
||||
function = "pwm";
|
||||
groups = "pwm1";
|
||||
};
|
||||
|
||||
gpio2_default_pins: pins-gpio2 {
|
||||
function = "gpio";
|
||||
groups = "gpio2agrp";
|
||||
};
|
||||
|
||||
gpio3_default_pins: pins-gpio3 {
|
||||
function = "gpio";
|
||||
groups = "gpio3agrp";
|
||||
};
|
||||
|
||||
keypad_default_pins: pins-keypad {
|
||||
function = "keypad";
|
||||
groups = "keypadgrp";
|
||||
};
|
||||
|
||||
gpio4_default_pins: pins-gpio4 {
|
||||
function = "gpio";
|
||||
groups = "gpio4agrp";
|
||||
};
|
||||
|
||||
gpio6_default_pins: pins-gpio6 {
|
||||
function = "gpio";
|
||||
groups = "gpio6agrp";
|
||||
};
|
||||
|
||||
gpio7_default_pins: pins-gpio7 {
|
||||
function = "gpio";
|
||||
groups = "gpio7agrp";
|
||||
};
|
||||
|
||||
ide_default_pins: pins-ide {
|
||||
function = "pata";
|
||||
groups = "idegrp";
|
||||
};
|
||||
|
||||
lcd_on_dram0_pins: pins-rasteronsdram0 {
|
||||
function = "lcd";
|
||||
groups = "rasteronsdram0grp";
|
||||
};
|
||||
|
||||
lcd_on_dram3_pins: pins-rasteronsdram3 {
|
||||
function = "lcd";
|
||||
groups = "rasteronsdram3grp";
|
||||
};
|
||||
};
|
||||
|
||||
adc: adc@80900000 {
|
||||
compatible = "cirrus,ep9301-adc";
|
||||
reg = <0x80900000 0x28>;
|
||||
clocks = <&syscon EP93XX_CLK_ADC>;
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <30>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
/*
|
||||
* The EP93XX expansion bus is a set of up to 7 each up to 16MB
|
||||
* windows in the 256MB space from 0x50000000 to 0x5fffffff.
|
||||
* But since we don't require to setup it in any way, we can
|
||||
* represent it as a simple-bus.
|
||||
*/
|
||||
ebi: bus@80080000 {
|
||||
compatible = "simple-bus";
|
||||
reg = <0x80080000 0x20>;
|
||||
native-endian;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
};
|
||||
|
||||
dma0: dma-controller@80000000 {
|
||||
compatible = "cirrus,ep9301-dma-m2p";
|
||||
reg = <0x80000000 0x0040>,
|
||||
<0x80000040 0x0040>,
|
||||
<0x80000080 0x0040>,
|
||||
<0x800000c0 0x0040>,
|
||||
<0x80000240 0x0040>,
|
||||
<0x80000200 0x0040>,
|
||||
<0x800002c0 0x0040>,
|
||||
<0x80000280 0x0040>,
|
||||
<0x80000340 0x0040>,
|
||||
<0x80000300 0x0040>;
|
||||
clocks = <&syscon EP93XX_CLK_M2P0>,
|
||||
<&syscon EP93XX_CLK_M2P1>,
|
||||
<&syscon EP93XX_CLK_M2P2>,
|
||||
<&syscon EP93XX_CLK_M2P3>,
|
||||
<&syscon EP93XX_CLK_M2P4>,
|
||||
<&syscon EP93XX_CLK_M2P5>,
|
||||
<&syscon EP93XX_CLK_M2P6>,
|
||||
<&syscon EP93XX_CLK_M2P7>,
|
||||
<&syscon EP93XX_CLK_M2P8>,
|
||||
<&syscon EP93XX_CLK_M2P9>;
|
||||
clock-names = "m2p0", "m2p1",
|
||||
"m2p2", "m2p3",
|
||||
"m2p4", "m2p5",
|
||||
"m2p6", "m2p7",
|
||||
"m2p8", "m2p9";
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <7>, <8>, <9>, <10>, <11>,
|
||||
<12>, <13>, <14>, <15>, <16>;
|
||||
#dma-cells = <2>;
|
||||
};
|
||||
|
||||
dma1: dma-controller@80000100 {
|
||||
compatible = "cirrus,ep9301-dma-m2m";
|
||||
reg = <0x80000100 0x0040>,
|
||||
<0x80000140 0x0040>;
|
||||
clocks = <&syscon EP93XX_CLK_M2M0>,
|
||||
<&syscon EP93XX_CLK_M2M1>;
|
||||
clock-names = "m2m0", "m2m1";
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <17>, <18>;
|
||||
#dma-cells = <2>;
|
||||
};
|
||||
|
||||
eth0: ethernet@80010000 {
|
||||
compatible = "cirrus,ep9301-eth";
|
||||
reg = <0x80010000 0x10000>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <7>;
|
||||
mdio0: mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio0: gpio@80840000 {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x80840000 0x04>,
|
||||
<0x80840010 0x04>,
|
||||
<0x80840090 0x1c>;
|
||||
reg-names = "data", "dir", "intr";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <27>;
|
||||
};
|
||||
|
||||
gpio1: gpio@80840004 {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x80840004 0x04>,
|
||||
<0x80840014 0x04>,
|
||||
<0x808400ac 0x1c>;
|
||||
reg-names = "data", "dir", "intr";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <27>;
|
||||
};
|
||||
|
||||
gpio2: gpio@80840008 {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x80840008 0x04>,
|
||||
<0x80840018 0x04>;
|
||||
reg-names = "data", "dir";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gpio2_default_pins>;
|
||||
};
|
||||
|
||||
gpio3: gpio@8084000c {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x8084000c 0x04>,
|
||||
<0x8084001c 0x04>;
|
||||
reg-names = "data", "dir";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gpio3_default_pins>;
|
||||
};
|
||||
|
||||
gpio4: gpio@80840020 {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x80840020 0x04>,
|
||||
<0x80840024 0x04>;
|
||||
reg-names = "data", "dir";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gpio4_default_pins>;
|
||||
};
|
||||
|
||||
gpio5: gpio@80840030 {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x80840030 0x04>,
|
||||
<0x80840034 0x04>,
|
||||
<0x8084004c 0x1c>;
|
||||
reg-names = "data", "dir", "intr";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts-extended = <&vic0 19>, <&vic0 20>,
|
||||
<&vic0 21>, <&vic0 22>,
|
||||
<&vic1 15>, <&vic1 16>,
|
||||
<&vic1 17>, <&vic1 18>;
|
||||
};
|
||||
|
||||
gpio6: gpio@80840038 {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x80840038 0x04>,
|
||||
<0x8084003c 0x04>;
|
||||
reg-names = "data", "dir";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gpio6_default_pins>;
|
||||
};
|
||||
|
||||
gpio7: gpio@80840040 {
|
||||
compatible = "cirrus,ep9301-gpio";
|
||||
reg = <0x80840040 0x04>,
|
||||
<0x80840044 0x04>;
|
||||
reg-names = "data", "dir";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gpio7_default_pins>;
|
||||
};
|
||||
|
||||
i2s: i2s@80820000 {
|
||||
compatible = "cirrus,ep9301-i2s";
|
||||
reg = <0x80820000 0x100>;
|
||||
#sound-dai-cells = <0>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <28>;
|
||||
clocks = <&syscon EP93XX_CLK_I2S_MCLK>,
|
||||
<&syscon EP93XX_CLK_I2S_SCLK>,
|
||||
<&syscon EP93XX_CLK_I2S_LRCLK>;
|
||||
clock-names = "mclk", "sclk", "lrclk";
|
||||
dmas = <&dma0 0 1>, <&dma0 0 2>;
|
||||
dma-names = "tx", "rx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ide: ide@800a0000 {
|
||||
compatible = "cirrus,ep9312-pata";
|
||||
reg = <0x800a0000 0x38>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <8>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&ide_default_pins>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
vic0: interrupt-controller@800b0000 {
|
||||
compatible = "arm,pl192-vic";
|
||||
reg = <0x800b0000 0x1000>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
valid-mask = <0x7ffffffc>;
|
||||
valid-wakeup-mask = <0x0>;
|
||||
};
|
||||
|
||||
vic1: interrupt-controller@800c0000 {
|
||||
compatible = "arm,pl192-vic";
|
||||
reg = <0x800c0000 0x1000>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
valid-mask = <0x1fffffff>;
|
||||
valid-wakeup-mask = <0x0>;
|
||||
};
|
||||
|
||||
keypad: keypad@800f0000 {
|
||||
compatible = "cirrus,ep9307-keypad";
|
||||
reg = <0x800f0000 0x0c>;
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <29>;
|
||||
clocks = <&syscon EP93XX_CLK_KEYPAD>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&keypad_default_pins>;
|
||||
linux,keymap = <KEY_UP>,
|
||||
<KEY_DOWN>,
|
||||
<KEY_VOLUMEDOWN>,
|
||||
<KEY_HOME>,
|
||||
<KEY_RIGHT>,
|
||||
<KEY_LEFT>,
|
||||
<KEY_ENTER>,
|
||||
<KEY_VOLUMEUP>,
|
||||
<KEY_F6>,
|
||||
<KEY_F8>,
|
||||
<KEY_F9>,
|
||||
<KEY_F10>,
|
||||
<KEY_F1>,
|
||||
<KEY_F2>,
|
||||
<KEY_F3>,
|
||||
<KEY_POWER>;
|
||||
};
|
||||
|
||||
pwm0: pwm@80910000 {
|
||||
compatible = "cirrus,ep9301-pwm";
|
||||
reg = <0x80910000 0x10>;
|
||||
clocks = <&syscon EP93XX_CLK_PWM>;
|
||||
#pwm-cells = <3>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pwm1: pwm@80910020 {
|
||||
compatible = "cirrus,ep9301-pwm";
|
||||
reg = <0x80910020 0x10>;
|
||||
clocks = <&syscon EP93XX_CLK_PWM>;
|
||||
#pwm-cells = <3>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pwm1_default_pins>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
rtc0: rtc@80920000 {
|
||||
compatible = "cirrus,ep9301-rtc";
|
||||
reg = <0x80920000 0x100>;
|
||||
};
|
||||
|
||||
spi0: spi@808a0000 {
|
||||
compatible = "cirrus,ep9301-spi";
|
||||
reg = <0x808a0000 0x18>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <21>;
|
||||
clocks = <&syscon EP93XX_CLK_SPI>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&spi_default_pins>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
timer: timer@80810000 {
|
||||
compatible = "cirrus,ep9301-timer";
|
||||
reg = <0x80810000 0x100>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <19>;
|
||||
};
|
||||
|
||||
uart0: serial@808c0000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x808c0000 0x1000>;
|
||||
arm,primecell-periphid = <0x00041010>;
|
||||
clocks = <&syscon EP93XX_CLK_UART1>, <&syscon EP93XX_CLK_UART>;
|
||||
clock-names = "uartclk", "apb_pclk";
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <20>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart1: uart@808d0000 {
|
||||
compatible = "arm,primecell";
|
||||
reg = <0x808d0000 0x1000>;
|
||||
arm,primecell-periphid = <0x00041010>;
|
||||
clocks = <&syscon EP93XX_CLK_UART2>, <&syscon EP93XX_CLK_UART>;
|
||||
clock-names = "apb:uart2", "apb_pclk";
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <22>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart2: uart@808b0000 {
|
||||
compatible = "arm,primecell";
|
||||
reg = <0x808b0000 0x1000>;
|
||||
arm,primecell-periphid = <0x00041010>;
|
||||
clocks = <&syscon EP93XX_CLK_UART3>, <&syscon EP93XX_CLK_UART>;
|
||||
clock-names = "apb:uart3", "apb_pclk";
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <23>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb0: usb@80020000 {
|
||||
compatible = "generic-ohci";
|
||||
reg = <0x80020000 0x10000>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <24>;
|
||||
clocks = <&syscon EP93XX_CLK_USB>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
watchdog0: watchdog@80940000 {
|
||||
compatible = "cirrus,ep9301-wdt";
|
||||
reg = <0x80940000 0x08>;
|
||||
};
|
||||
};
|
||||
|
||||
xtali: oscillator {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <14745600>;
|
||||
clock-output-names = "xtali";
|
||||
};
|
||||
};
|
@ -8,7 +8,7 @@
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <crypto/aes.h>
|
||||
#include <crypto/ctr.h>
|
||||
#include <crypto/internal/simd.h>
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
|
||||
#define PMULL_MIN_LEN 64L /* minimum size of buffer
|
||||
* for crc32_pmull_le_16 */
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <crypto/aes.h>
|
||||
#include <crypto/gcm.h>
|
||||
#include <crypto/b128ops.h>
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <crypto/internal/poly1305.h>
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/neon.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
|
||||
#include "sha256_glue.h"
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <linux/string.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/domain.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <asm/unified.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/proc-fns.h>
|
||||
|
@ -3,27 +3,27 @@ menuconfig ARCH_EP93XX
|
||||
bool "EP93xx-based"
|
||||
depends on ATAGS
|
||||
depends on ARCH_MULTI_V4T
|
||||
# CONFIG_ARCH_MULTI_V7 is not set
|
||||
depends on CPU_LITTLE_ENDIAN
|
||||
select ARCH_HAS_RESET_CONTROLLER
|
||||
select ARCH_SPARSEMEM_ENABLE
|
||||
select ARM_AMBA
|
||||
select ARM_VIC
|
||||
select ARM_APPENDED_DTB # Old Redboot bootloaders deployed
|
||||
select ARM_ATAG_DTB_COMPAT # we need this to update dt memory node
|
||||
select COMMON_CLK_EP93XX
|
||||
select EP93XX_TIMER
|
||||
select CLKSRC_MMIO
|
||||
select CPU_ARM920T
|
||||
select GPIOLIB
|
||||
select PINCTRL
|
||||
select PINCTRL_EP93XX
|
||||
help
|
||||
This enables support for the Cirrus EP93xx series of CPUs.
|
||||
|
||||
if ARCH_EP93XX
|
||||
|
||||
menu "Cirrus EP93xx Implementation Options"
|
||||
|
||||
config EP93XX_SOC_COMMON
|
||||
bool
|
||||
default y
|
||||
select SOC_BUS
|
||||
select LEDS_GPIO_REGISTER
|
||||
|
||||
comment "EP93xx Platforms"
|
||||
# menu "EP93xx Platforms"
|
||||
|
||||
config MACH_BK3
|
||||
bool "Support Liebherr BK3.1"
|
||||
@ -103,6 +103,6 @@ config MACH_VISION_EP9307
|
||||
Say 'Y' here if you want your kernel to support the
|
||||
Vision Engraving Systems EP9307 SoM.
|
||||
|
||||
endmenu
|
||||
# endmenu
|
||||
|
||||
endif
|
||||
|
@ -1,11 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
obj-y := core.o clock.o timer-ep93xx.o
|
||||
|
||||
obj-$(CONFIG_EP93XX_DMA) += dma.o
|
||||
|
||||
obj-$(CONFIG_MACH_EDB93XX) += edb93xx.o
|
||||
obj-$(CONFIG_MACH_TS72XX) += ts72xx.o
|
||||
obj-$(CONFIG_MACH_VISION_EP9307)+= vision_ep9307.o
|
@ -1,733 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/clock.c
|
||||
* Clock control for Cirrus EP93xx chips.
|
||||
*
|
||||
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/soc/cirrus/ep93xx.h>
|
||||
|
||||
#include "hardware.h"
|
||||
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include "soc.h"
|
||||
|
||||
static DEFINE_SPINLOCK(clk_lock);
|
||||
|
||||
static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
|
||||
static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
|
||||
static char pclk_divisors[] = { 1, 2, 4, 8 };
|
||||
|
||||
static char adc_divisors[] = { 16, 4 };
|
||||
static char sclk_divisors[] = { 2, 4 };
|
||||
static char lrclk_divisors[] = { 32, 64, 128 };
|
||||
|
||||
static const char * const mux_parents[] = {
|
||||
"xtali",
|
||||
"pll1",
|
||||
"pll2"
|
||||
};
|
||||
|
||||
/*
|
||||
* PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
|
||||
*/
|
||||
static unsigned long calc_pll_rate(unsigned long long rate, u32 config_word)
|
||||
{
|
||||
int i;
|
||||
|
||||
rate *= ((config_word >> 11) & 0x1f) + 1; /* X1FBD */
|
||||
rate *= ((config_word >> 5) & 0x3f) + 1; /* X2FBD */
|
||||
do_div(rate, (config_word & 0x1f) + 1); /* X2IPD */
|
||||
for (i = 0; i < ((config_word >> 16) & 3); i++) /* PS */
|
||||
rate >>= 1;
|
||||
|
||||
return (unsigned long)rate;
|
||||
}
|
||||
|
||||
struct clk_psc {
|
||||
struct clk_hw hw;
|
||||
void __iomem *reg;
|
||||
u8 bit_idx;
|
||||
u32 mask;
|
||||
u8 shift;
|
||||
u8 width;
|
||||
char *div;
|
||||
u8 num_div;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
|
||||
#define to_clk_psc(_hw) container_of(_hw, struct clk_psc, hw)
|
||||
|
||||
static int ep93xx_clk_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
u32 val = readl(psc->reg);
|
||||
|
||||
return (val & BIT(psc->bit_idx)) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int ep93xx_clk_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
unsigned long flags = 0;
|
||||
u32 val;
|
||||
|
||||
if (psc->lock)
|
||||
spin_lock_irqsave(psc->lock, flags);
|
||||
|
||||
val = __raw_readl(psc->reg);
|
||||
val |= BIT(psc->bit_idx);
|
||||
|
||||
ep93xx_syscon_swlocked_write(val, psc->reg);
|
||||
|
||||
if (psc->lock)
|
||||
spin_unlock_irqrestore(psc->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ep93xx_clk_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
unsigned long flags = 0;
|
||||
u32 val;
|
||||
|
||||
if (psc->lock)
|
||||
spin_lock_irqsave(psc->lock, flags);
|
||||
|
||||
val = __raw_readl(psc->reg);
|
||||
val &= ~BIT(psc->bit_idx);
|
||||
|
||||
ep93xx_syscon_swlocked_write(val, psc->reg);
|
||||
|
||||
if (psc->lock)
|
||||
spin_unlock_irqrestore(psc->lock, flags);
|
||||
}
|
||||
|
||||
static const struct clk_ops clk_ep93xx_gate_ops = {
|
||||
.enable = ep93xx_clk_enable,
|
||||
.disable = ep93xx_clk_disable,
|
||||
.is_enabled = ep93xx_clk_is_enabled,
|
||||
};
|
||||
|
||||
static struct clk_hw *ep93xx_clk_register_gate(const char *name,
|
||||
const char *parent_name,
|
||||
void __iomem *reg,
|
||||
u8 bit_idx)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
struct clk_psc *psc;
|
||||
struct clk *clk;
|
||||
|
||||
psc = kzalloc(sizeof(*psc), GFP_KERNEL);
|
||||
if (!psc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &clk_ep93xx_gate_ops;
|
||||
init.flags = CLK_SET_RATE_PARENT;
|
||||
init.parent_names = (parent_name ? &parent_name : NULL);
|
||||
init.num_parents = (parent_name ? 1 : 0);
|
||||
|
||||
psc->reg = reg;
|
||||
psc->bit_idx = bit_idx;
|
||||
psc->hw.init = &init;
|
||||
psc->lock = &clk_lock;
|
||||
|
||||
clk = clk_register(NULL, &psc->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(psc);
|
||||
return ERR_CAST(clk);
|
||||
}
|
||||
|
||||
return &psc->hw;
|
||||
}
|
||||
|
||||
static u8 ep93xx_mux_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
u32 val = __raw_readl(psc->reg);
|
||||
|
||||
if (!(val & EP93XX_SYSCON_CLKDIV_ESEL))
|
||||
return 0;
|
||||
|
||||
if (!(val & EP93XX_SYSCON_CLKDIV_PSEL))
|
||||
return 1;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int ep93xx_mux_set_parent_lock(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
unsigned long flags = 0;
|
||||
u32 val;
|
||||
|
||||
if (index >= ARRAY_SIZE(mux_parents))
|
||||
return -EINVAL;
|
||||
|
||||
if (psc->lock)
|
||||
spin_lock_irqsave(psc->lock, flags);
|
||||
|
||||
val = __raw_readl(psc->reg);
|
||||
val &= ~(EP93XX_SYSCON_CLKDIV_ESEL | EP93XX_SYSCON_CLKDIV_PSEL);
|
||||
|
||||
|
||||
if (index != 0) {
|
||||
val |= EP93XX_SYSCON_CLKDIV_ESEL;
|
||||
val |= (index - 1) ? EP93XX_SYSCON_CLKDIV_PSEL : 0;
|
||||
}
|
||||
|
||||
ep93xx_syscon_swlocked_write(val, psc->reg);
|
||||
|
||||
if (psc->lock)
|
||||
spin_unlock_irqrestore(psc->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_best(unsigned long rate, unsigned long now,
|
||||
unsigned long best)
|
||||
{
|
||||
return abs(rate - now) < abs(rate - best);
|
||||
}
|
||||
|
||||
static int ep93xx_mux_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
unsigned long rate = req->rate;
|
||||
struct clk *best_parent = NULL;
|
||||
unsigned long __parent_rate;
|
||||
unsigned long best_rate = 0, actual_rate, mclk_rate;
|
||||
unsigned long best_parent_rate;
|
||||
int __div = 0, __pdiv = 0;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Try the two pll's and the external clock
|
||||
* Because the valid predividers are 2, 2.5 and 3, we multiply
|
||||
* all the clocks by 2 to avoid floating point math.
|
||||
*
|
||||
* This is based on the algorithm in the ep93xx raster guide:
|
||||
* http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf
|
||||
*
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(mux_parents); i++) {
|
||||
struct clk *parent = clk_get_sys(mux_parents[i], NULL);
|
||||
|
||||
__parent_rate = clk_get_rate(parent);
|
||||
mclk_rate = __parent_rate * 2;
|
||||
|
||||
/* Try each predivider value */
|
||||
for (__pdiv = 4; __pdiv <= 6; __pdiv++) {
|
||||
__div = mclk_rate / (rate * __pdiv);
|
||||
if (__div < 2 || __div > 127)
|
||||
continue;
|
||||
|
||||
actual_rate = mclk_rate / (__pdiv * __div);
|
||||
if (is_best(rate, actual_rate, best_rate)) {
|
||||
best_rate = actual_rate;
|
||||
best_parent_rate = __parent_rate;
|
||||
best_parent = parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!best_parent)
|
||||
return -EINVAL;
|
||||
|
||||
req->best_parent_rate = best_parent_rate;
|
||||
req->best_parent_hw = __clk_get_hw(best_parent);
|
||||
req->rate = best_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long ep93xx_ddiv_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
unsigned long rate = 0;
|
||||
u32 val = __raw_readl(psc->reg);
|
||||
int __pdiv = ((val >> EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) & 0x03);
|
||||
int __div = val & 0x7f;
|
||||
|
||||
if (__div > 0)
|
||||
rate = (parent_rate * 2) / ((__pdiv + 3) * __div);
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static int ep93xx_ddiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
int pdiv = 0, div = 0;
|
||||
unsigned long best_rate = 0, actual_rate, mclk_rate;
|
||||
int __div = 0, __pdiv = 0;
|
||||
u32 val;
|
||||
|
||||
mclk_rate = parent_rate * 2;
|
||||
|
||||
for (__pdiv = 4; __pdiv <= 6; __pdiv++) {
|
||||
__div = mclk_rate / (rate * __pdiv);
|
||||
if (__div < 2 || __div > 127)
|
||||
continue;
|
||||
|
||||
actual_rate = mclk_rate / (__pdiv * __div);
|
||||
if (is_best(rate, actual_rate, best_rate)) {
|
||||
pdiv = __pdiv - 3;
|
||||
div = __div;
|
||||
best_rate = actual_rate;
|
||||
}
|
||||
}
|
||||
|
||||
if (!best_rate)
|
||||
return -EINVAL;
|
||||
|
||||
val = __raw_readl(psc->reg);
|
||||
|
||||
/* Clear old dividers */
|
||||
val &= ~0x37f;
|
||||
|
||||
/* Set the new pdiv and div bits for the new clock rate */
|
||||
val |= (pdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | div;
|
||||
ep93xx_syscon_swlocked_write(val, psc->reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops clk_ddiv_ops = {
|
||||
.enable = ep93xx_clk_enable,
|
||||
.disable = ep93xx_clk_disable,
|
||||
.is_enabled = ep93xx_clk_is_enabled,
|
||||
.get_parent = ep93xx_mux_get_parent,
|
||||
.set_parent = ep93xx_mux_set_parent_lock,
|
||||
.determine_rate = ep93xx_mux_determine_rate,
|
||||
.recalc_rate = ep93xx_ddiv_recalc_rate,
|
||||
.set_rate = ep93xx_ddiv_set_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw *clk_hw_register_ddiv(const char *name,
|
||||
void __iomem *reg,
|
||||
u8 bit_idx)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
struct clk_psc *psc;
|
||||
struct clk *clk;
|
||||
|
||||
psc = kzalloc(sizeof(*psc), GFP_KERNEL);
|
||||
if (!psc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &clk_ddiv_ops;
|
||||
init.flags = 0;
|
||||
init.parent_names = mux_parents;
|
||||
init.num_parents = ARRAY_SIZE(mux_parents);
|
||||
|
||||
psc->reg = reg;
|
||||
psc->bit_idx = bit_idx;
|
||||
psc->lock = &clk_lock;
|
||||
psc->hw.init = &init;
|
||||
|
||||
clk = clk_register(NULL, &psc->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(psc);
|
||||
return ERR_CAST(clk);
|
||||
}
|
||||
return &psc->hw;
|
||||
}
|
||||
|
||||
static unsigned long ep93xx_div_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
u32 val = __raw_readl(psc->reg);
|
||||
u8 index = (val & psc->mask) >> psc->shift;
|
||||
|
||||
if (index > psc->num_div)
|
||||
return 0;
|
||||
|
||||
return DIV_ROUND_UP_ULL(parent_rate, psc->div[index]);
|
||||
}
|
||||
|
||||
static long ep93xx_div_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
unsigned long best = 0, now, maxdiv;
|
||||
int i;
|
||||
|
||||
maxdiv = psc->div[psc->num_div - 1];
|
||||
|
||||
for (i = 0; i < psc->num_div; i++) {
|
||||
if ((rate * psc->div[i]) == *parent_rate)
|
||||
return DIV_ROUND_UP_ULL((u64)*parent_rate, psc->div[i]);
|
||||
|
||||
now = DIV_ROUND_UP_ULL((u64)*parent_rate, psc->div[i]);
|
||||
|
||||
if (is_best(rate, now, best))
|
||||
best = now;
|
||||
}
|
||||
|
||||
if (!best)
|
||||
best = DIV_ROUND_UP_ULL(*parent_rate, maxdiv);
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
static int ep93xx_div_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_psc *psc = to_clk_psc(hw);
|
||||
u32 val = __raw_readl(psc->reg) & ~psc->mask;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < psc->num_div; i++)
|
||||
if (rate == parent_rate / psc->div[i]) {
|
||||
val |= i << psc->shift;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == psc->num_div)
|
||||
return -EINVAL;
|
||||
|
||||
ep93xx_syscon_swlocked_write(val, psc->reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops ep93xx_div_ops = {
|
||||
.enable = ep93xx_clk_enable,
|
||||
.disable = ep93xx_clk_disable,
|
||||
.is_enabled = ep93xx_clk_is_enabled,
|
||||
.recalc_rate = ep93xx_div_recalc_rate,
|
||||
.round_rate = ep93xx_div_round_rate,
|
||||
.set_rate = ep93xx_div_set_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw *clk_hw_register_div(const char *name,
|
||||
const char *parent_name,
|
||||
void __iomem *reg,
|
||||
u8 enable_bit,
|
||||
u8 shift,
|
||||
u8 width,
|
||||
char *clk_divisors,
|
||||
u8 num_div)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
struct clk_psc *psc;
|
||||
struct clk *clk;
|
||||
|
||||
psc = kzalloc(sizeof(*psc), GFP_KERNEL);
|
||||
if (!psc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &ep93xx_div_ops;
|
||||
init.flags = 0;
|
||||
init.parent_names = (parent_name ? &parent_name : NULL);
|
||||
init.num_parents = 1;
|
||||
|
||||
psc->reg = reg;
|
||||
psc->bit_idx = enable_bit;
|
||||
psc->mask = GENMASK(shift + width - 1, shift);
|
||||
psc->shift = shift;
|
||||
psc->div = clk_divisors;
|
||||
psc->num_div = num_div;
|
||||
psc->lock = &clk_lock;
|
||||
psc->hw.init = &init;
|
||||
|
||||
clk = clk_register(NULL, &psc->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(psc);
|
||||
return ERR_CAST(clk);
|
||||
}
|
||||
return &psc->hw;
|
||||
}
|
||||
|
||||
struct ep93xx_gate {
|
||||
unsigned int bit;
|
||||
const char *dev_id;
|
||||
const char *con_id;
|
||||
};
|
||||
|
||||
static struct ep93xx_gate ep93xx_uarts[] = {
|
||||
{EP93XX_SYSCON_DEVCFG_U1EN, "apb:uart1", NULL},
|
||||
{EP93XX_SYSCON_DEVCFG_U2EN, "apb:uart2", NULL},
|
||||
{EP93XX_SYSCON_DEVCFG_U3EN, "apb:uart3", NULL},
|
||||
};
|
||||
|
||||
static void __init ep93xx_uart_clock_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
struct clk_hw *hw;
|
||||
u32 value;
|
||||
unsigned int clk_uart_div;
|
||||
|
||||
value = __raw_readl(EP93XX_SYSCON_PWRCNT);
|
||||
if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD)
|
||||
clk_uart_div = 1;
|
||||
else
|
||||
clk_uart_div = 2;
|
||||
|
||||
hw = clk_hw_register_fixed_factor(NULL, "uart", "xtali", 0, 1, clk_uart_div);
|
||||
|
||||
/* parenting uart gate clocks to uart clock */
|
||||
for (i = 0; i < ARRAY_SIZE(ep93xx_uarts); i++) {
|
||||
hw = ep93xx_clk_register_gate(ep93xx_uarts[i].dev_id,
|
||||
"uart",
|
||||
EP93XX_SYSCON_DEVCFG,
|
||||
ep93xx_uarts[i].bit);
|
||||
|
||||
clk_hw_register_clkdev(hw, NULL, ep93xx_uarts[i].dev_id);
|
||||
}
|
||||
}
|
||||
|
||||
static struct ep93xx_gate ep93xx_dmas[] = {
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P0, NULL, "m2p0"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P1, NULL, "m2p1"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P2, NULL, "m2p2"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P3, NULL, "m2p3"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P4, NULL, "m2p4"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P5, NULL, "m2p5"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P6, NULL, "m2p6"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P7, NULL, "m2p7"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P8, NULL, "m2p8"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2P9, NULL, "m2p9"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2M0, NULL, "m2m0"},
|
||||
{EP93XX_SYSCON_PWRCNT_DMA_M2M1, NULL, "m2m1"},
|
||||
};
|
||||
|
||||
static void __init ep93xx_dma_clock_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
struct clk_hw *hw;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ep93xx_dmas); i++) {
|
||||
hw = clk_hw_register_gate(NULL, ep93xx_dmas[i].con_id,
|
||||
"hclk", 0,
|
||||
EP93XX_SYSCON_PWRCNT,
|
||||
ep93xx_dmas[i].bit,
|
||||
0,
|
||||
&clk_lock);
|
||||
|
||||
ret = clk_hw_register_clkdev(hw, ep93xx_dmas[i].con_id, NULL);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register lookup %s\n",
|
||||
__func__, ep93xx_dmas[i].con_id);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init ep93xx_clock_init(void)
|
||||
{
|
||||
u32 value;
|
||||
struct clk_hw *hw;
|
||||
unsigned long clk_pll1_rate;
|
||||
unsigned long clk_f_rate;
|
||||
unsigned long clk_h_rate;
|
||||
unsigned long clk_p_rate;
|
||||
unsigned long clk_pll2_rate;
|
||||
unsigned int clk_f_div;
|
||||
unsigned int clk_h_div;
|
||||
unsigned int clk_p_div;
|
||||
unsigned int clk_usb_div;
|
||||
unsigned long clk_spi_div;
|
||||
|
||||
hw = clk_hw_register_fixed_rate(NULL, "xtali", NULL, 0, EP93XX_EXT_CLK_RATE);
|
||||
clk_hw_register_clkdev(hw, NULL, "xtali");
|
||||
|
||||
/* Determine the bootloader configured pll1 rate */
|
||||
value = __raw_readl(EP93XX_SYSCON_CLKSET1);
|
||||
if (!(value & EP93XX_SYSCON_CLKSET1_NBYP1))
|
||||
clk_pll1_rate = EP93XX_EXT_CLK_RATE;
|
||||
else
|
||||
clk_pll1_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value);
|
||||
|
||||
hw = clk_hw_register_fixed_rate(NULL, "pll1", "xtali", 0, clk_pll1_rate);
|
||||
clk_hw_register_clkdev(hw, NULL, "pll1");
|
||||
|
||||
/* Initialize the pll1 derived clocks */
|
||||
clk_f_div = fclk_divisors[(value >> 25) & 0x7];
|
||||
clk_h_div = hclk_divisors[(value >> 20) & 0x7];
|
||||
clk_p_div = pclk_divisors[(value >> 18) & 0x3];
|
||||
|
||||
hw = clk_hw_register_fixed_factor(NULL, "fclk", "pll1", 0, 1, clk_f_div);
|
||||
clk_f_rate = clk_get_rate(hw->clk);
|
||||
hw = clk_hw_register_fixed_factor(NULL, "hclk", "pll1", 0, 1, clk_h_div);
|
||||
clk_h_rate = clk_get_rate(hw->clk);
|
||||
hw = clk_hw_register_fixed_factor(NULL, "pclk", "hclk", 0, 1, clk_p_div);
|
||||
clk_p_rate = clk_get_rate(hw->clk);
|
||||
|
||||
clk_hw_register_clkdev(hw, "apb_pclk", NULL);
|
||||
|
||||
ep93xx_dma_clock_init();
|
||||
|
||||
/* Determine the bootloader configured pll2 rate */
|
||||
value = __raw_readl(EP93XX_SYSCON_CLKSET2);
|
||||
if (!(value & EP93XX_SYSCON_CLKSET2_NBYP2))
|
||||
clk_pll2_rate = EP93XX_EXT_CLK_RATE;
|
||||
else if (value & EP93XX_SYSCON_CLKSET2_PLL2_EN)
|
||||
clk_pll2_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value);
|
||||
else
|
||||
clk_pll2_rate = 0;
|
||||
|
||||
hw = clk_hw_register_fixed_rate(NULL, "pll2", "xtali", 0, clk_pll2_rate);
|
||||
clk_hw_register_clkdev(hw, NULL, "pll2");
|
||||
|
||||
/* Initialize the pll2 derived clocks */
|
||||
/*
|
||||
* These four bits set the divide ratio between the PLL2
|
||||
* output and the USB clock.
|
||||
* 0000 - Divide by 1
|
||||
* 0001 - Divide by 2
|
||||
* 0010 - Divide by 3
|
||||
* 0011 - Divide by 4
|
||||
* 0100 - Divide by 5
|
||||
* 0101 - Divide by 6
|
||||
* 0110 - Divide by 7
|
||||
* 0111 - Divide by 8
|
||||
* 1000 - Divide by 9
|
||||
* 1001 - Divide by 10
|
||||
* 1010 - Divide by 11
|
||||
* 1011 - Divide by 12
|
||||
* 1100 - Divide by 13
|
||||
* 1101 - Divide by 14
|
||||
* 1110 - Divide by 15
|
||||
* 1111 - Divide by 1
|
||||
* On power-on-reset these bits are reset to 0000b.
|
||||
*/
|
||||
clk_usb_div = (((value >> 28) & 0xf) + 1);
|
||||
hw = clk_hw_register_fixed_factor(NULL, "usb_clk", "pll2", 0, 1, clk_usb_div);
|
||||
hw = clk_hw_register_gate(NULL, "ohci-platform",
|
||||
"usb_clk", 0,
|
||||
EP93XX_SYSCON_PWRCNT,
|
||||
EP93XX_SYSCON_PWRCNT_USH_EN,
|
||||
0,
|
||||
&clk_lock);
|
||||
clk_hw_register_clkdev(hw, NULL, "ohci-platform");
|
||||
|
||||
/*
|
||||
* EP93xx SSP clock rate was doubled in version E2. For more information
|
||||
* see:
|
||||
* http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf
|
||||
*/
|
||||
clk_spi_div = 1;
|
||||
if (ep93xx_chip_revision() < EP93XX_CHIP_REV_E2)
|
||||
clk_spi_div = 2;
|
||||
hw = clk_hw_register_fixed_factor(NULL, "ep93xx-spi.0", "xtali", 0, 1, clk_spi_div);
|
||||
clk_hw_register_clkdev(hw, NULL, "ep93xx-spi.0");
|
||||
|
||||
/* pwm clock */
|
||||
hw = clk_hw_register_fixed_factor(NULL, "pwm_clk", "xtali", 0, 1, 1);
|
||||
clk_hw_register_clkdev(hw, "pwm_clk", NULL);
|
||||
|
||||
pr_info("PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
|
||||
clk_pll1_rate / 1000000, clk_pll2_rate / 1000000);
|
||||
pr_info("FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
|
||||
clk_f_rate / 1000000, clk_h_rate / 1000000,
|
||||
clk_p_rate / 1000000);
|
||||
|
||||
ep93xx_uart_clock_init();
|
||||
|
||||
/* touchscreen/adc clock */
|
||||
hw = clk_hw_register_div("ep93xx-adc",
|
||||
"xtali",
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV,
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV_TSEN,
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV_ADIV,
|
||||
1,
|
||||
adc_divisors,
|
||||
ARRAY_SIZE(adc_divisors));
|
||||
|
||||
clk_hw_register_clkdev(hw, NULL, "ep93xx-adc");
|
||||
|
||||
/* keypad clock */
|
||||
hw = clk_hw_register_div("ep93xx-keypad",
|
||||
"xtali",
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV,
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
|
||||
EP93XX_SYSCON_KEYTCHCLKDIV_KDIV,
|
||||
1,
|
||||
adc_divisors,
|
||||
ARRAY_SIZE(adc_divisors));
|
||||
|
||||
clk_hw_register_clkdev(hw, NULL, "ep93xx-keypad");
|
||||
|
||||
/* On reset PDIV and VDIV is set to zero, while PDIV zero
|
||||
* means clock disable, VDIV shouldn't be zero.
|
||||
* So i set both dividers to minimum.
|
||||
*/
|
||||
/* ENA - Enable CLK divider. */
|
||||
/* PDIV - 00 - Disable clock */
|
||||
/* VDIV - at least 2 */
|
||||
/* Check and enable video clk registers */
|
||||
value = __raw_readl(EP93XX_SYSCON_VIDCLKDIV);
|
||||
value |= (1 << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2;
|
||||
ep93xx_syscon_swlocked_write(value, EP93XX_SYSCON_VIDCLKDIV);
|
||||
|
||||
/* check and enable i2s clk registers */
|
||||
value = __raw_readl(EP93XX_SYSCON_I2SCLKDIV);
|
||||
value |= (1 << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2;
|
||||
ep93xx_syscon_swlocked_write(value, EP93XX_SYSCON_I2SCLKDIV);
|
||||
|
||||
/* video clk */
|
||||
hw = clk_hw_register_ddiv("ep93xx-fb",
|
||||
EP93XX_SYSCON_VIDCLKDIV,
|
||||
EP93XX_SYSCON_CLKDIV_ENABLE);
|
||||
|
||||
clk_hw_register_clkdev(hw, NULL, "ep93xx-fb");
|
||||
|
||||
/* i2s clk */
|
||||
hw = clk_hw_register_ddiv("mclk",
|
||||
EP93XX_SYSCON_I2SCLKDIV,
|
||||
EP93XX_SYSCON_CLKDIV_ENABLE);
|
||||
|
||||
clk_hw_register_clkdev(hw, "mclk", "ep93xx-i2s");
|
||||
|
||||
/* i2s sclk */
|
||||
#define EP93XX_I2SCLKDIV_SDIV_SHIFT 16
|
||||
#define EP93XX_I2SCLKDIV_SDIV_WIDTH 1
|
||||
hw = clk_hw_register_div("sclk",
|
||||
"mclk",
|
||||
EP93XX_SYSCON_I2SCLKDIV,
|
||||
EP93XX_SYSCON_I2SCLKDIV_SENA,
|
||||
EP93XX_I2SCLKDIV_SDIV_SHIFT,
|
||||
EP93XX_I2SCLKDIV_SDIV_WIDTH,
|
||||
sclk_divisors,
|
||||
ARRAY_SIZE(sclk_divisors));
|
||||
|
||||
clk_hw_register_clkdev(hw, "sclk", "ep93xx-i2s");
|
||||
|
||||
/* i2s lrclk */
|
||||
#define EP93XX_I2SCLKDIV_LRDIV32_SHIFT 17
|
||||
#define EP93XX_I2SCLKDIV_LRDIV32_WIDTH 3
|
||||
hw = clk_hw_register_div("lrclk",
|
||||
"sclk",
|
||||
EP93XX_SYSCON_I2SCLKDIV,
|
||||
EP93XX_SYSCON_I2SCLKDIV_SENA,
|
||||
EP93XX_I2SCLKDIV_LRDIV32_SHIFT,
|
||||
EP93XX_I2SCLKDIV_LRDIV32_WIDTH,
|
||||
lrclk_divisors,
|
||||
ARRAY_SIZE(lrclk_divisors));
|
||||
|
||||
clk_hw_register_clkdev(hw, "lrclk", "ep93xx-i2s");
|
||||
|
||||
return 0;
|
||||
}
|
||||
postcore_initcall(ep93xx_clock_init);
|
File diff suppressed because it is too large
Load Diff
@ -1,114 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/dma.c
|
||||
*
|
||||
* Platform support code for the EP93xx dmaengine driver.
|
||||
*
|
||||
* Copyright (C) 2011 Mika Westerberg
|
||||
*
|
||||
* This work is based on the original dma-m2p implementation with
|
||||
* following copyrights:
|
||||
*
|
||||
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
|
||||
* Copyright (C) 2006 Applied Data Systems
|
||||
* Copyright (C) 2009 Ryan Mallon <rmallon@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/platform_data/dma-ep93xx.h>
|
||||
#include "hardware.h"
|
||||
|
||||
#include "soc.h"
|
||||
|
||||
#define DMA_CHANNEL(_name, _base, _irq) \
|
||||
{ .name = (_name), .base = (_base), .irq = (_irq) }
|
||||
|
||||
/*
|
||||
* DMA M2P channels.
|
||||
*
|
||||
* On the EP93xx chip the following peripherals my be allocated to the 10
|
||||
* Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive).
|
||||
*
|
||||
* I2S contains 3 Tx and 3 Rx DMA Channels
|
||||
* AAC contains 3 Tx and 3 Rx DMA Channels
|
||||
* UART1 contains 1 Tx and 1 Rx DMA Channels
|
||||
* UART2 contains 1 Tx and 1 Rx DMA Channels
|
||||
* UART3 contains 1 Tx and 1 Rx DMA Channels
|
||||
* IrDA contains 1 Tx and 1 Rx DMA Channels
|
||||
*
|
||||
* Registers are mapped statically in ep93xx_map_io().
|
||||
*/
|
||||
static struct ep93xx_dma_chan_data ep93xx_dma_m2p_channels[] = {
|
||||
DMA_CHANNEL("m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0),
|
||||
DMA_CHANNEL("m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1),
|
||||
DMA_CHANNEL("m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2),
|
||||
DMA_CHANNEL("m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3),
|
||||
DMA_CHANNEL("m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4),
|
||||
DMA_CHANNEL("m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5),
|
||||
DMA_CHANNEL("m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6),
|
||||
DMA_CHANNEL("m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7),
|
||||
DMA_CHANNEL("m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8),
|
||||
DMA_CHANNEL("m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9),
|
||||
};
|
||||
|
||||
static struct ep93xx_dma_platform_data ep93xx_dma_m2p_data = {
|
||||
.channels = ep93xx_dma_m2p_channels,
|
||||
.num_channels = ARRAY_SIZE(ep93xx_dma_m2p_channels),
|
||||
};
|
||||
|
||||
static u64 ep93xx_dma_m2p_mask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct platform_device ep93xx_dma_m2p_device = {
|
||||
.name = "ep93xx-dma-m2p",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &ep93xx_dma_m2p_data,
|
||||
.dma_mask = &ep93xx_dma_m2p_mask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* DMA M2M channels.
|
||||
*
|
||||
* There are 2 M2M channels which support memcpy/memset and in addition simple
|
||||
* hardware requests from/to SSP and IDE. We do not implement an external
|
||||
* hardware requests.
|
||||
*
|
||||
* Registers are mapped statically in ep93xx_map_io().
|
||||
*/
|
||||
static struct ep93xx_dma_chan_data ep93xx_dma_m2m_channels[] = {
|
||||
DMA_CHANNEL("m2m0", EP93XX_DMA_BASE + 0x0100, IRQ_EP93XX_DMAM2M0),
|
||||
DMA_CHANNEL("m2m1", EP93XX_DMA_BASE + 0x0140, IRQ_EP93XX_DMAM2M1),
|
||||
};
|
||||
|
||||
static struct ep93xx_dma_platform_data ep93xx_dma_m2m_data = {
|
||||
.channels = ep93xx_dma_m2m_channels,
|
||||
.num_channels = ARRAY_SIZE(ep93xx_dma_m2m_channels),
|
||||
};
|
||||
|
||||
static u64 ep93xx_dma_m2m_mask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct platform_device ep93xx_dma_m2m_device = {
|
||||
.name = "ep93xx-dma-m2m",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &ep93xx_dma_m2m_data,
|
||||
.dma_mask = &ep93xx_dma_m2m_mask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
};
|
||||
|
||||
static int __init ep93xx_dma_init(void)
|
||||
{
|
||||
platform_device_register(&ep93xx_dma_m2p_device);
|
||||
platform_device_register(&ep93xx_dma_m2m_device);
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(ep93xx_dma_init);
|
@ -1,368 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/edb93xx.c
|
||||
* Cirrus Logic EDB93xx Development Board support.
|
||||
*
|
||||
* EDB93XX, EDB9301, EDB9307A
|
||||
* Copyright (C) 2008-2009 H Hartley Sweeten <hsweeten@visionengravers.com>
|
||||
*
|
||||
* EDB9302
|
||||
* Copyright (C) 2006 George Kashperko <george@chas.com.ua>
|
||||
*
|
||||
* EDB9302A, EDB9315, EDB9315A
|
||||
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
|
||||
*
|
||||
* EDB9307
|
||||
* Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
|
||||
*
|
||||
* EDB9312
|
||||
* Copyright (C) 2006 Infosys Technologies Limited
|
||||
* Toufeeq Hussain <toufeeq_hussain@infosys.com>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
|
||||
#include <sound/cs4271.h>
|
||||
|
||||
#include "hardware.h"
|
||||
#include <linux/platform_data/video-ep93xx.h>
|
||||
#include <linux/platform_data/spi-ep93xx.h>
|
||||
#include "gpio-ep93xx.h"
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include "soc.h"
|
||||
|
||||
static void __init edb93xx_register_flash(void)
|
||||
{
|
||||
if (machine_is_edb9307() || machine_is_edb9312() ||
|
||||
machine_is_edb9315()) {
|
||||
ep93xx_register_flash(4, EP93XX_CS6_PHYS_BASE, SZ_32M);
|
||||
} else {
|
||||
ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_16M);
|
||||
}
|
||||
}
|
||||
|
||||
static struct ep93xx_eth_data __initdata edb93xx_eth_data = {
|
||||
.phy_id = 1,
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* EDB93xx i2c peripheral handling
|
||||
*************************************************************************/
|
||||
|
||||
static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("isl1208", 0x6f),
|
||||
},
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata edb93xx_i2c_board_info[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("ds1337", 0x68),
|
||||
},
|
||||
};
|
||||
|
||||
static void __init edb93xx_register_i2c(void)
|
||||
{
|
||||
if (machine_is_edb9302a() || machine_is_edb9307a() ||
|
||||
machine_is_edb9315a()) {
|
||||
ep93xx_register_i2c(edb93xxa_i2c_board_info,
|
||||
ARRAY_SIZE(edb93xxa_i2c_board_info));
|
||||
} else if (machine_is_edb9302() || machine_is_edb9307()
|
||||
|| machine_is_edb9312() || machine_is_edb9315()) {
|
||||
ep93xx_register_i2c(edb93xx_i2c_board_info,
|
||||
ARRAY_SIZE(edb93xx_i2c_board_info));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* EDB93xx SPI peripheral handling
|
||||
*************************************************************************/
|
||||
static struct cs4271_platform_data edb93xx_cs4271_data = {
|
||||
/* Intentionally left blank */
|
||||
};
|
||||
|
||||
static struct spi_board_info edb93xx_spi_board_info[] __initdata = {
|
||||
{
|
||||
.modalias = "cs4271",
|
||||
.platform_data = &edb93xx_cs4271_data,
|
||||
.max_speed_hz = 6000000,
|
||||
.bus_num = 0,
|
||||
.chip_select = 0,
|
||||
.mode = SPI_MODE_3,
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table edb93xx_spi_cs_gpio_table = {
|
||||
.dev_id = "spi0",
|
||||
.table = {
|
||||
GPIO_LOOKUP("A", 6, "cs", GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct ep93xx_spi_info edb93xx_spi_info __initdata = {
|
||||
/* Intentionally left blank */
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table edb93xx_cs4272_edb9301_gpio_table = {
|
||||
.dev_id = "spi0.0", /* CS0 on SPI0 */
|
||||
.table = {
|
||||
GPIO_LOOKUP("A", 1, "reset", GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table edb93xx_cs4272_edb9302_gpio_table = {
|
||||
.dev_id = "spi0.0", /* CS0 on SPI0 */
|
||||
.table = {
|
||||
GPIO_LOOKUP("H", 2, "reset", GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table edb93xx_cs4272_edb9315_gpio_table = {
|
||||
.dev_id = "spi0.0", /* CS0 on SPI0 */
|
||||
.table = {
|
||||
GPIO_LOOKUP("B", 6, "reset", GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static void __init edb93xx_register_spi(void)
|
||||
{
|
||||
if (machine_is_edb9301() || machine_is_edb9302())
|
||||
gpiod_add_lookup_table(&edb93xx_cs4272_edb9301_gpio_table);
|
||||
else if (machine_is_edb9302a() || machine_is_edb9307a())
|
||||
gpiod_add_lookup_table(&edb93xx_cs4272_edb9302_gpio_table);
|
||||
else if (machine_is_edb9315a())
|
||||
gpiod_add_lookup_table(&edb93xx_cs4272_edb9315_gpio_table);
|
||||
|
||||
gpiod_add_lookup_table(&edb93xx_spi_cs_gpio_table);
|
||||
ep93xx_register_spi(&edb93xx_spi_info, edb93xx_spi_board_info,
|
||||
ARRAY_SIZE(edb93xx_spi_board_info));
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* EDB93xx I2S
|
||||
*************************************************************************/
|
||||
static struct platform_device edb93xx_audio_device = {
|
||||
.name = "edb93xx-audio",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static int __init edb93xx_has_audio(void)
|
||||
{
|
||||
return (machine_is_edb9301() || machine_is_edb9302() ||
|
||||
machine_is_edb9302a() || machine_is_edb9307a() ||
|
||||
machine_is_edb9315a());
|
||||
}
|
||||
|
||||
static void __init edb93xx_register_i2s(void)
|
||||
{
|
||||
if (edb93xx_has_audio()) {
|
||||
ep93xx_register_i2s();
|
||||
platform_device_register(&edb93xx_audio_device);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* EDB93xx pwm
|
||||
*************************************************************************/
|
||||
static void __init edb93xx_register_pwm(void)
|
||||
{
|
||||
if (machine_is_edb9301() ||
|
||||
machine_is_edb9302() || machine_is_edb9302a()) {
|
||||
/* EP9301 and EP9302 only have pwm.1 (EGPIO14) */
|
||||
ep93xx_register_pwm(0, 1);
|
||||
} else if (machine_is_edb9307() || machine_is_edb9307a()) {
|
||||
/* EP9307 only has pwm.0 (PWMOUT) */
|
||||
ep93xx_register_pwm(1, 0);
|
||||
} else {
|
||||
/* EP9312 and EP9315 have both */
|
||||
ep93xx_register_pwm(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* EDB93xx framebuffer
|
||||
*************************************************************************/
|
||||
static struct ep93xxfb_mach_info __initdata edb93xxfb_info = {
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
static int __init edb93xx_has_fb(void)
|
||||
{
|
||||
/* These platforms have an ep93xx with video capability */
|
||||
return machine_is_edb9307() || machine_is_edb9307a() ||
|
||||
machine_is_edb9312() || machine_is_edb9315() ||
|
||||
machine_is_edb9315a();
|
||||
}
|
||||
|
||||
static void __init edb93xx_register_fb(void)
|
||||
{
|
||||
if (!edb93xx_has_fb())
|
||||
return;
|
||||
|
||||
if (machine_is_edb9307a() || machine_is_edb9315a())
|
||||
edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN0;
|
||||
else
|
||||
edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN3;
|
||||
|
||||
ep93xx_register_fb(&edb93xxfb_info);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* EDB93xx IDE
|
||||
*************************************************************************/
|
||||
static int __init edb93xx_has_ide(void)
|
||||
{
|
||||
/*
|
||||
* Although EDB9312 and EDB9315 do have IDE capability, they have
|
||||
* INTRQ line wired as pull-up, which makes using IDE interface
|
||||
* problematic.
|
||||
*/
|
||||
return machine_is_edb9312() || machine_is_edb9315() ||
|
||||
machine_is_edb9315a();
|
||||
}
|
||||
|
||||
static void __init edb93xx_register_ide(void)
|
||||
{
|
||||
if (!edb93xx_has_ide())
|
||||
return;
|
||||
|
||||
ep93xx_register_ide();
|
||||
}
|
||||
|
||||
|
||||
static void __init edb93xx_init_machine(void)
|
||||
{
|
||||
ep93xx_init_devices();
|
||||
edb93xx_register_flash();
|
||||
ep93xx_register_eth(&edb93xx_eth_data, 1);
|
||||
edb93xx_register_i2c();
|
||||
edb93xx_register_spi();
|
||||
edb93xx_register_i2s();
|
||||
edb93xx_register_pwm();
|
||||
edb93xx_register_fb();
|
||||
edb93xx_register_ide();
|
||||
ep93xx_register_adc();
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9301
|
||||
MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board")
|
||||
/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9302
|
||||
MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
|
||||
/* Maintainer: George Kashperko <george@chas.com.ua> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9302A
|
||||
MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
|
||||
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9307
|
||||
MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
|
||||
/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9307A
|
||||
MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
|
||||
/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9312
|
||||
MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
|
||||
/* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9315
|
||||
MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
|
||||
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_EDB9315A
|
||||
MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
|
||||
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = edb93xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
#endif
|
@ -1,38 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_ARCH_EP93XX_REGS_H
|
||||
#define __ASM_ARCH_EP93XX_REGS_H
|
||||
|
||||
/*
|
||||
* EP93xx linux memory map:
|
||||
*
|
||||
* virt phys size
|
||||
* fe800000 5M per-platform mappings
|
||||
* fed00000 80800000 2M APB
|
||||
* fef00000 80000000 1M AHB
|
||||
*/
|
||||
|
||||
#define EP93XX_AHB_PHYS_BASE 0x80000000
|
||||
#define EP93XX_AHB_VIRT_BASE 0xfef00000
|
||||
#define EP93XX_AHB_SIZE 0x00100000
|
||||
|
||||
#define EP93XX_AHB_PHYS(x) (EP93XX_AHB_PHYS_BASE + (x))
|
||||
#define EP93XX_AHB_IOMEM(x) IOMEM(EP93XX_AHB_VIRT_BASE + (x))
|
||||
|
||||
#define EP93XX_APB_PHYS_BASE 0x80800000
|
||||
#define EP93XX_APB_VIRT_BASE 0xfed00000
|
||||
#define EP93XX_APB_SIZE 0x00200000
|
||||
|
||||
#define EP93XX_APB_PHYS(x) (EP93XX_APB_PHYS_BASE + (x))
|
||||
#define EP93XX_APB_IOMEM(x) IOMEM(EP93XX_APB_VIRT_BASE + (x))
|
||||
|
||||
/* APB UARTs */
|
||||
#define EP93XX_UART1_PHYS_BASE EP93XX_APB_PHYS(0x000c0000)
|
||||
#define EP93XX_UART1_BASE EP93XX_APB_IOMEM(0x000c0000)
|
||||
|
||||
#define EP93XX_UART2_PHYS_BASE EP93XX_APB_PHYS(0x000d0000)
|
||||
#define EP93XX_UART2_BASE EP93XX_APB_IOMEM(0x000d0000)
|
||||
|
||||
#define EP93XX_UART3_PHYS_BASE EP93XX_APB_PHYS(0x000e0000)
|
||||
#define EP93XX_UART3_BASE EP93XX_APB_IOMEM(0x000e0000)
|
||||
|
||||
#endif
|
@ -1,111 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Include file for the EP93XX GPIO controller machine specifics */
|
||||
|
||||
#ifndef __GPIO_EP93XX_H
|
||||
#define __GPIO_EP93XX_H
|
||||
|
||||
#include "ep93xx-regs.h"
|
||||
|
||||
#define EP93XX_GPIO_PHYS_BASE EP93XX_APB_PHYS(0x00040000)
|
||||
#define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000)
|
||||
#define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x))
|
||||
#define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c)
|
||||
#define EP93XX_GPIO_A_INT_STATUS EP93XX_GPIO_REG(0xa0)
|
||||
#define EP93XX_GPIO_B_INT_STATUS EP93XX_GPIO_REG(0xbc)
|
||||
#define EP93XX_GPIO_EEDRIVE EP93XX_GPIO_REG(0xc8)
|
||||
|
||||
/* GPIO port A. */
|
||||
#define EP93XX_GPIO_LINE_A(x) ((x) + 0)
|
||||
#define EP93XX_GPIO_LINE_EGPIO0 EP93XX_GPIO_LINE_A(0)
|
||||
#define EP93XX_GPIO_LINE_EGPIO1 EP93XX_GPIO_LINE_A(1)
|
||||
#define EP93XX_GPIO_LINE_EGPIO2 EP93XX_GPIO_LINE_A(2)
|
||||
#define EP93XX_GPIO_LINE_EGPIO3 EP93XX_GPIO_LINE_A(3)
|
||||
#define EP93XX_GPIO_LINE_EGPIO4 EP93XX_GPIO_LINE_A(4)
|
||||
#define EP93XX_GPIO_LINE_EGPIO5 EP93XX_GPIO_LINE_A(5)
|
||||
#define EP93XX_GPIO_LINE_EGPIO6 EP93XX_GPIO_LINE_A(6)
|
||||
#define EP93XX_GPIO_LINE_EGPIO7 EP93XX_GPIO_LINE_A(7)
|
||||
|
||||
/* GPIO port B. */
|
||||
#define EP93XX_GPIO_LINE_B(x) ((x) + 8)
|
||||
#define EP93XX_GPIO_LINE_EGPIO8 EP93XX_GPIO_LINE_B(0)
|
||||
#define EP93XX_GPIO_LINE_EGPIO9 EP93XX_GPIO_LINE_B(1)
|
||||
#define EP93XX_GPIO_LINE_EGPIO10 EP93XX_GPIO_LINE_B(2)
|
||||
#define EP93XX_GPIO_LINE_EGPIO11 EP93XX_GPIO_LINE_B(3)
|
||||
#define EP93XX_GPIO_LINE_EGPIO12 EP93XX_GPIO_LINE_B(4)
|
||||
#define EP93XX_GPIO_LINE_EGPIO13 EP93XX_GPIO_LINE_B(5)
|
||||
#define EP93XX_GPIO_LINE_EGPIO14 EP93XX_GPIO_LINE_B(6)
|
||||
#define EP93XX_GPIO_LINE_EGPIO15 EP93XX_GPIO_LINE_B(7)
|
||||
|
||||
/* GPIO port C. */
|
||||
#define EP93XX_GPIO_LINE_C(x) ((x) + 40)
|
||||
#define EP93XX_GPIO_LINE_ROW0 EP93XX_GPIO_LINE_C(0)
|
||||
#define EP93XX_GPIO_LINE_ROW1 EP93XX_GPIO_LINE_C(1)
|
||||
#define EP93XX_GPIO_LINE_ROW2 EP93XX_GPIO_LINE_C(2)
|
||||
#define EP93XX_GPIO_LINE_ROW3 EP93XX_GPIO_LINE_C(3)
|
||||
#define EP93XX_GPIO_LINE_ROW4 EP93XX_GPIO_LINE_C(4)
|
||||
#define EP93XX_GPIO_LINE_ROW5 EP93XX_GPIO_LINE_C(5)
|
||||
#define EP93XX_GPIO_LINE_ROW6 EP93XX_GPIO_LINE_C(6)
|
||||
#define EP93XX_GPIO_LINE_ROW7 EP93XX_GPIO_LINE_C(7)
|
||||
|
||||
/* GPIO port D. */
|
||||
#define EP93XX_GPIO_LINE_D(x) ((x) + 24)
|
||||
#define EP93XX_GPIO_LINE_COL0 EP93XX_GPIO_LINE_D(0)
|
||||
#define EP93XX_GPIO_LINE_COL1 EP93XX_GPIO_LINE_D(1)
|
||||
#define EP93XX_GPIO_LINE_COL2 EP93XX_GPIO_LINE_D(2)
|
||||
#define EP93XX_GPIO_LINE_COL3 EP93XX_GPIO_LINE_D(3)
|
||||
#define EP93XX_GPIO_LINE_COL4 EP93XX_GPIO_LINE_D(4)
|
||||
#define EP93XX_GPIO_LINE_COL5 EP93XX_GPIO_LINE_D(5)
|
||||
#define EP93XX_GPIO_LINE_COL6 EP93XX_GPIO_LINE_D(6)
|
||||
#define EP93XX_GPIO_LINE_COL7 EP93XX_GPIO_LINE_D(7)
|
||||
|
||||
/* GPIO port E. */
|
||||
#define EP93XX_GPIO_LINE_E(x) ((x) + 32)
|
||||
#define EP93XX_GPIO_LINE_GRLED EP93XX_GPIO_LINE_E(0)
|
||||
#define EP93XX_GPIO_LINE_RDLED EP93XX_GPIO_LINE_E(1)
|
||||
#define EP93XX_GPIO_LINE_DIORn EP93XX_GPIO_LINE_E(2)
|
||||
#define EP93XX_GPIO_LINE_IDECS1n EP93XX_GPIO_LINE_E(3)
|
||||
#define EP93XX_GPIO_LINE_IDECS2n EP93XX_GPIO_LINE_E(4)
|
||||
#define EP93XX_GPIO_LINE_IDEDA0 EP93XX_GPIO_LINE_E(5)
|
||||
#define EP93XX_GPIO_LINE_IDEDA1 EP93XX_GPIO_LINE_E(6)
|
||||
#define EP93XX_GPIO_LINE_IDEDA2 EP93XX_GPIO_LINE_E(7)
|
||||
|
||||
/* GPIO port F. */
|
||||
#define EP93XX_GPIO_LINE_F(x) ((x) + 16)
|
||||
#define EP93XX_GPIO_LINE_WP EP93XX_GPIO_LINE_F(0)
|
||||
#define EP93XX_GPIO_LINE_MCCD1 EP93XX_GPIO_LINE_F(1)
|
||||
#define EP93XX_GPIO_LINE_MCCD2 EP93XX_GPIO_LINE_F(2)
|
||||
#define EP93XX_GPIO_LINE_MCBVD1 EP93XX_GPIO_LINE_F(3)
|
||||
#define EP93XX_GPIO_LINE_MCBVD2 EP93XX_GPIO_LINE_F(4)
|
||||
#define EP93XX_GPIO_LINE_VS1 EP93XX_GPIO_LINE_F(5)
|
||||
#define EP93XX_GPIO_LINE_READY EP93XX_GPIO_LINE_F(6)
|
||||
#define EP93XX_GPIO_LINE_VS2 EP93XX_GPIO_LINE_F(7)
|
||||
|
||||
/* GPIO port G. */
|
||||
#define EP93XX_GPIO_LINE_G(x) ((x) + 48)
|
||||
#define EP93XX_GPIO_LINE_EECLK EP93XX_GPIO_LINE_G(0)
|
||||
#define EP93XX_GPIO_LINE_EEDAT EP93XX_GPIO_LINE_G(1)
|
||||
#define EP93XX_GPIO_LINE_SLA0 EP93XX_GPIO_LINE_G(2)
|
||||
#define EP93XX_GPIO_LINE_SLA1 EP93XX_GPIO_LINE_G(3)
|
||||
#define EP93XX_GPIO_LINE_DD12 EP93XX_GPIO_LINE_G(4)
|
||||
#define EP93XX_GPIO_LINE_DD13 EP93XX_GPIO_LINE_G(5)
|
||||
#define EP93XX_GPIO_LINE_DD14 EP93XX_GPIO_LINE_G(6)
|
||||
#define EP93XX_GPIO_LINE_DD15 EP93XX_GPIO_LINE_G(7)
|
||||
|
||||
/* GPIO port H. */
|
||||
#define EP93XX_GPIO_LINE_H(x) ((x) + 56)
|
||||
#define EP93XX_GPIO_LINE_DD0 EP93XX_GPIO_LINE_H(0)
|
||||
#define EP93XX_GPIO_LINE_DD1 EP93XX_GPIO_LINE_H(1)
|
||||
#define EP93XX_GPIO_LINE_DD2 EP93XX_GPIO_LINE_H(2)
|
||||
#define EP93XX_GPIO_LINE_DD3 EP93XX_GPIO_LINE_H(3)
|
||||
#define EP93XX_GPIO_LINE_DD4 EP93XX_GPIO_LINE_H(4)
|
||||
#define EP93XX_GPIO_LINE_DD5 EP93XX_GPIO_LINE_H(5)
|
||||
#define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6)
|
||||
#define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7)
|
||||
|
||||
/* maximum value for gpio line identifiers */
|
||||
#define EP93XX_GPIO_LINE_MAX EP93XX_GPIO_LINE_H(7)
|
||||
|
||||
/* maximum value for irq capable line identifiers */
|
||||
#define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7)
|
||||
|
||||
#endif /* __GPIO_EP93XX_H */
|
@ -1,25 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/include/mach/hardware.h
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_HARDWARE_H
|
||||
#define __ASM_ARCH_HARDWARE_H
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
/*
|
||||
* The EP93xx has two external crystal oscillators. To generate the
|
||||
* required high-frequency clocks, the processor uses two phase-locked-
|
||||
* loops (PLLs) to multiply the incoming external clock signal to much
|
||||
* higher frequencies that are then divided down by programmable dividers
|
||||
* to produce the needed clocks. The PLLs operate independently of one
|
||||
* another.
|
||||
*/
|
||||
#define EP93XX_EXT_CLK_RATE 14745600
|
||||
#define EP93XX_EXT_RTC_RATE 32768
|
||||
|
||||
#define EP93XX_KEYTCHCLK_DIV4 (EP93XX_EXT_CLK_RATE / 4)
|
||||
#define EP93XX_KEYTCHCLK_DIV16 (EP93XX_EXT_CLK_RATE / 16)
|
||||
|
||||
#endif
|
@ -1,76 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_ARCH_IRQS_H
|
||||
#define __ASM_ARCH_IRQS_H
|
||||
|
||||
#define IRQ_EP93XX_VIC0 1
|
||||
|
||||
#define IRQ_EP93XX_COMMRX (IRQ_EP93XX_VIC0 + 2)
|
||||
#define IRQ_EP93XX_COMMTX (IRQ_EP93XX_VIC0 + 3)
|
||||
#define IRQ_EP93XX_TIMER1 (IRQ_EP93XX_VIC0 + 4)
|
||||
#define IRQ_EP93XX_TIMER2 (IRQ_EP93XX_VIC0 + 5)
|
||||
#define IRQ_EP93XX_AACINTR (IRQ_EP93XX_VIC0 + 6)
|
||||
#define IRQ_EP93XX_DMAM2P0 (IRQ_EP93XX_VIC0 + 7)
|
||||
#define IRQ_EP93XX_DMAM2P1 (IRQ_EP93XX_VIC0 + 8)
|
||||
#define IRQ_EP93XX_DMAM2P2 (IRQ_EP93XX_VIC0 + 9)
|
||||
#define IRQ_EP93XX_DMAM2P3 (IRQ_EP93XX_VIC0 + 10)
|
||||
#define IRQ_EP93XX_DMAM2P4 (IRQ_EP93XX_VIC0 + 11)
|
||||
#define IRQ_EP93XX_DMAM2P5 (IRQ_EP93XX_VIC0 + 12)
|
||||
#define IRQ_EP93XX_DMAM2P6 (IRQ_EP93XX_VIC0 + 13)
|
||||
#define IRQ_EP93XX_DMAM2P7 (IRQ_EP93XX_VIC0 + 14)
|
||||
#define IRQ_EP93XX_DMAM2P8 (IRQ_EP93XX_VIC0 + 15)
|
||||
#define IRQ_EP93XX_DMAM2P9 (IRQ_EP93XX_VIC0 + 16)
|
||||
#define IRQ_EP93XX_DMAM2M0 (IRQ_EP93XX_VIC0 + 17)
|
||||
#define IRQ_EP93XX_DMAM2M1 (IRQ_EP93XX_VIC0 + 18)
|
||||
#define IRQ_EP93XX_GPIO0MUX (IRQ_EP93XX_VIC0 + 19)
|
||||
#define IRQ_EP93XX_GPIO1MUX (IRQ_EP93XX_VIC0 + 20)
|
||||
#define IRQ_EP93XX_GPIO2MUX (IRQ_EP93XX_VIC0 + 21)
|
||||
#define IRQ_EP93XX_GPIO3MUX (IRQ_EP93XX_VIC0 + 22)
|
||||
#define IRQ_EP93XX_UART1RX (IRQ_EP93XX_VIC0 + 23)
|
||||
#define IRQ_EP93XX_UART1TX (IRQ_EP93XX_VIC0 + 24)
|
||||
#define IRQ_EP93XX_UART2RX (IRQ_EP93XX_VIC0 + 25)
|
||||
#define IRQ_EP93XX_UART2TX (IRQ_EP93XX_VIC0 + 26)
|
||||
#define IRQ_EP93XX_UART3RX (IRQ_EP93XX_VIC0 + 27)
|
||||
#define IRQ_EP93XX_UART3TX (IRQ_EP93XX_VIC0 + 28)
|
||||
#define IRQ_EP93XX_KEY (IRQ_EP93XX_VIC0 + 29)
|
||||
#define IRQ_EP93XX_TOUCH (IRQ_EP93XX_VIC0 + 30)
|
||||
#define EP93XX_VIC1_VALID_IRQ_MASK 0x7ffffffc
|
||||
|
||||
#define IRQ_EP93XX_VIC1 (IRQ_EP93XX_VIC0 + 32)
|
||||
|
||||
#define IRQ_EP93XX_EXT0 (IRQ_EP93XX_VIC1 + 0)
|
||||
#define IRQ_EP93XX_EXT1 (IRQ_EP93XX_VIC1 + 1)
|
||||
#define IRQ_EP93XX_EXT2 (IRQ_EP93XX_VIC1 + 2)
|
||||
#define IRQ_EP93XX_64HZ (IRQ_EP93XX_VIC1 + 3)
|
||||
#define IRQ_EP93XX_WATCHDOG (IRQ_EP93XX_VIC1 + 4)
|
||||
#define IRQ_EP93XX_RTC (IRQ_EP93XX_VIC1 + 5)
|
||||
#define IRQ_EP93XX_IRDA (IRQ_EP93XX_VIC1 + 6)
|
||||
#define IRQ_EP93XX_ETHERNET (IRQ_EP93XX_VIC1 + 7)
|
||||
#define IRQ_EP93XX_EXT3 (IRQ_EP93XX_VIC1 + 8)
|
||||
#define IRQ_EP93XX_PROG (IRQ_EP93XX_VIC1 + 9)
|
||||
#define IRQ_EP93XX_1HZ (IRQ_EP93XX_VIC1 + 10)
|
||||
#define IRQ_EP93XX_VSYNC (IRQ_EP93XX_VIC1 + 11)
|
||||
#define IRQ_EP93XX_VIDEO_FIFO (IRQ_EP93XX_VIC1 + 12)
|
||||
#define IRQ_EP93XX_SSP1RX (IRQ_EP93XX_VIC1 + 13)
|
||||
#define IRQ_EP93XX_SSP1TX (IRQ_EP93XX_VIC1 + 14)
|
||||
#define IRQ_EP93XX_GPIO4MUX (IRQ_EP93XX_VIC1 + 15)
|
||||
#define IRQ_EP93XX_GPIO5MUX (IRQ_EP93XX_VIC1 + 16)
|
||||
#define IRQ_EP93XX_GPIO6MUX (IRQ_EP93XX_VIC1 + 17)
|
||||
#define IRQ_EP93XX_GPIO7MUX (IRQ_EP93XX_VIC1 + 18)
|
||||
#define IRQ_EP93XX_TIMER3 (IRQ_EP93XX_VIC1 + 19)
|
||||
#define IRQ_EP93XX_UART1 (IRQ_EP93XX_VIC1 + 20)
|
||||
#define IRQ_EP93XX_SSP (IRQ_EP93XX_VIC1 + 21)
|
||||
#define IRQ_EP93XX_UART2 (IRQ_EP93XX_VIC1 + 22)
|
||||
#define IRQ_EP93XX_UART3 (IRQ_EP93XX_VIC1 + 23)
|
||||
#define IRQ_EP93XX_USB (IRQ_EP93XX_VIC1 + 24)
|
||||
#define IRQ_EP93XX_ETHERNET_PME (IRQ_EP93XX_VIC1 + 25)
|
||||
#define IRQ_EP93XX_DSP (IRQ_EP93XX_VIC1 + 26)
|
||||
#define IRQ_EP93XX_GPIO_AB (IRQ_EP93XX_VIC1 + 27)
|
||||
#define IRQ_EP93XX_SAI (IRQ_EP93XX_VIC1 + 28)
|
||||
#define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff
|
||||
|
||||
#define NR_EP93XX_IRQS (IRQ_EP93XX_VIC1 + 32 + 24)
|
||||
|
||||
#define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x))
|
||||
#define EP93XX_BOARD_IRQS 32
|
||||
|
||||
#endif
|
@ -1,42 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/include/mach/platform.h
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/platform_data/eth-ep93xx.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
struct device;
|
||||
struct i2c_board_info;
|
||||
struct spi_board_info;
|
||||
struct platform_device;
|
||||
struct ep93xxfb_mach_info;
|
||||
struct ep93xx_keypad_platform_data;
|
||||
struct ep93xx_spi_info;
|
||||
|
||||
void ep93xx_map_io(void);
|
||||
void ep93xx_init_irq(void);
|
||||
|
||||
void ep93xx_register_flash(unsigned int width,
|
||||
resource_size_t start, resource_size_t size);
|
||||
|
||||
void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
|
||||
void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
|
||||
void ep93xx_register_spi(struct ep93xx_spi_info *info,
|
||||
struct spi_board_info *devices, int num);
|
||||
void ep93xx_register_fb(struct ep93xxfb_mach_info *data);
|
||||
void ep93xx_register_pwm(int pwm0, int pwm1);
|
||||
void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data);
|
||||
void ep93xx_register_i2s(void);
|
||||
void ep93xx_register_ac97(void);
|
||||
void ep93xx_register_ide(void);
|
||||
void ep93xx_register_adc(void);
|
||||
|
||||
struct device *ep93xx_init_devices(void);
|
||||
extern void ep93xx_timer_init(void);
|
||||
|
||||
void ep93xx_restart(enum reboot_mode, const char *);
|
||||
|
||||
#endif
|
@ -1,212 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/soc.h
|
||||
*
|
||||
* Copyright (C) 2012 Open Kernel Labs <www.ok-labs.com>
|
||||
* Copyright (C) 2012 Ryan Mallon <rmallon@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _EP93XX_SOC_H
|
||||
#define _EP93XX_SOC_H
|
||||
|
||||
#include "ep93xx-regs.h"
|
||||
#include "irqs.h"
|
||||
|
||||
/*
|
||||
* EP93xx Physical Memory Map:
|
||||
*
|
||||
* The ASDO pin is sampled at system reset to select a synchronous or
|
||||
* asynchronous boot configuration. When ASDO is "1" (i.e. pulled-up)
|
||||
* the synchronous boot mode is selected. When ASDO is "0" (i.e
|
||||
* pulled-down) the asynchronous boot mode is selected.
|
||||
*
|
||||
* In synchronous boot mode nSDCE3 is decoded starting at physical address
|
||||
* 0x00000000 and nCS0 is decoded starting at 0xf0000000. For asynchronous
|
||||
* boot mode they are swapped with nCS0 decoded at 0x00000000 ann nSDCE3
|
||||
* decoded at 0xf0000000.
|
||||
*
|
||||
* There is known errata for the EP93xx dealing with External Memory
|
||||
* Configurations. Please refer to "AN273: EP93xx Silicon Rev E Design
|
||||
* Guidelines" for more information. This document can be found at:
|
||||
*
|
||||
* http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf
|
||||
*/
|
||||
|
||||
#define EP93XX_CS0_PHYS_BASE_ASYNC 0x00000000 /* ASDO Pin = 0 */
|
||||
#define EP93XX_SDCE3_PHYS_BASE_SYNC 0x00000000 /* ASDO Pin = 1 */
|
||||
#define EP93XX_CS1_PHYS_BASE 0x10000000
|
||||
#define EP93XX_CS2_PHYS_BASE 0x20000000
|
||||
#define EP93XX_CS3_PHYS_BASE 0x30000000
|
||||
#define EP93XX_PCMCIA_PHYS_BASE 0x40000000
|
||||
#define EP93XX_CS6_PHYS_BASE 0x60000000
|
||||
#define EP93XX_CS7_PHYS_BASE 0x70000000
|
||||
#define EP93XX_SDCE0_PHYS_BASE 0xc0000000
|
||||
#define EP93XX_SDCE1_PHYS_BASE 0xd0000000
|
||||
#define EP93XX_SDCE2_PHYS_BASE 0xe0000000
|
||||
#define EP93XX_SDCE3_PHYS_BASE_ASYNC 0xf0000000 /* ASDO Pin = 0 */
|
||||
#define EP93XX_CS0_PHYS_BASE_SYNC 0xf0000000 /* ASDO Pin = 1 */
|
||||
|
||||
/* AHB peripherals */
|
||||
#define EP93XX_DMA_BASE EP93XX_AHB_IOMEM(0x00000000)
|
||||
|
||||
#define EP93XX_ETHERNET_PHYS_BASE EP93XX_AHB_PHYS(0x00010000)
|
||||
#define EP93XX_ETHERNET_BASE EP93XX_AHB_IOMEM(0x00010000)
|
||||
|
||||
#define EP93XX_USB_PHYS_BASE EP93XX_AHB_PHYS(0x00020000)
|
||||
#define EP93XX_USB_BASE EP93XX_AHB_IOMEM(0x00020000)
|
||||
|
||||
#define EP93XX_RASTER_PHYS_BASE EP93XX_AHB_PHYS(0x00030000)
|
||||
#define EP93XX_RASTER_BASE EP93XX_AHB_IOMEM(0x00030000)
|
||||
|
||||
#define EP93XX_GRAPHICS_ACCEL_BASE EP93XX_AHB_IOMEM(0x00040000)
|
||||
|
||||
#define EP93XX_SDRAM_CONTROLLER_BASE EP93XX_AHB_IOMEM(0x00060000)
|
||||
|
||||
#define EP93XX_PCMCIA_CONTROLLER_BASE EP93XX_AHB_IOMEM(0x00080000)
|
||||
|
||||
#define EP93XX_BOOT_ROM_BASE EP93XX_AHB_IOMEM(0x00090000)
|
||||
|
||||
#define EP93XX_IDE_PHYS_BASE EP93XX_AHB_PHYS(0x000a0000)
|
||||
#define EP93XX_IDE_BASE EP93XX_AHB_IOMEM(0x000a0000)
|
||||
|
||||
#define EP93XX_VIC1_BASE EP93XX_AHB_IOMEM(0x000b0000)
|
||||
|
||||
#define EP93XX_VIC2_BASE EP93XX_AHB_IOMEM(0x000c0000)
|
||||
|
||||
/* APB peripherals */
|
||||
#define EP93XX_TIMER_BASE EP93XX_APB_IOMEM(0x00010000)
|
||||
|
||||
#define EP93XX_I2S_PHYS_BASE EP93XX_APB_PHYS(0x00020000)
|
||||
#define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000)
|
||||
|
||||
#define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000)
|
||||
|
||||
#define EP93XX_AAC_PHYS_BASE EP93XX_APB_PHYS(0x00080000)
|
||||
#define EP93XX_AAC_BASE EP93XX_APB_IOMEM(0x00080000)
|
||||
|
||||
#define EP93XX_SPI_PHYS_BASE EP93XX_APB_PHYS(0x000a0000)
|
||||
#define EP93XX_SPI_BASE EP93XX_APB_IOMEM(0x000a0000)
|
||||
|
||||
#define EP93XX_IRDA_BASE EP93XX_APB_IOMEM(0x000b0000)
|
||||
|
||||
#define EP93XX_KEY_MATRIX_PHYS_BASE EP93XX_APB_PHYS(0x000f0000)
|
||||
#define EP93XX_KEY_MATRIX_BASE EP93XX_APB_IOMEM(0x000f0000)
|
||||
|
||||
#define EP93XX_ADC_PHYS_BASE EP93XX_APB_PHYS(0x00100000)
|
||||
#define EP93XX_ADC_BASE EP93XX_APB_IOMEM(0x00100000)
|
||||
#define EP93XX_TOUCHSCREEN_BASE EP93XX_APB_IOMEM(0x00100000)
|
||||
|
||||
#define EP93XX_PWM_PHYS_BASE EP93XX_APB_PHYS(0x00110000)
|
||||
#define EP93XX_PWM_BASE EP93XX_APB_IOMEM(0x00110000)
|
||||
|
||||
#define EP93XX_RTC_PHYS_BASE EP93XX_APB_PHYS(0x00120000)
|
||||
#define EP93XX_RTC_BASE EP93XX_APB_IOMEM(0x00120000)
|
||||
|
||||
#define EP93XX_WATCHDOG_PHYS_BASE EP93XX_APB_PHYS(0x00140000)
|
||||
#define EP93XX_WATCHDOG_BASE EP93XX_APB_IOMEM(0x00140000)
|
||||
|
||||
/* System controller */
|
||||
#define EP93XX_SYSCON_BASE EP93XX_APB_IOMEM(0x00130000)
|
||||
#define EP93XX_SYSCON_REG(x) (EP93XX_SYSCON_BASE + (x))
|
||||
#define EP93XX_SYSCON_POWER_STATE EP93XX_SYSCON_REG(0x00)
|
||||
#define EP93XX_SYSCON_PWRCNT EP93XX_SYSCON_REG(0x04)
|
||||
#define EP93XX_SYSCON_PWRCNT_FIR_EN (1<<31)
|
||||
#define EP93XX_SYSCON_PWRCNT_UARTBAUD (1<<29)
|
||||
#define EP93XX_SYSCON_PWRCNT_USH_EN 28
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2M1 27
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2M0 26
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P8 25
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P9 24
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P6 23
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P7 22
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P4 21
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P5 20
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P2 19
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P3 18
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P0 17
|
||||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P1 16
|
||||
#define EP93XX_SYSCON_HALT EP93XX_SYSCON_REG(0x08)
|
||||
#define EP93XX_SYSCON_STANDBY EP93XX_SYSCON_REG(0x0c)
|
||||
#define EP93XX_SYSCON_CLKSET1 EP93XX_SYSCON_REG(0x20)
|
||||
#define EP93XX_SYSCON_CLKSET1_NBYP1 (1<<23)
|
||||
#define EP93XX_SYSCON_CLKSET2 EP93XX_SYSCON_REG(0x24)
|
||||
#define EP93XX_SYSCON_CLKSET2_NBYP2 (1<<19)
|
||||
#define EP93XX_SYSCON_CLKSET2_PLL2_EN (1<<18)
|
||||
#define EP93XX_SYSCON_DEVCFG EP93XX_SYSCON_REG(0x80)
|
||||
#define EP93XX_SYSCON_DEVCFG_SWRST (1<<31)
|
||||
#define EP93XX_SYSCON_DEVCFG_D1ONG (1<<30)
|
||||
#define EP93XX_SYSCON_DEVCFG_D0ONG (1<<29)
|
||||
#define EP93XX_SYSCON_DEVCFG_IONU2 (1<<28)
|
||||
#define EP93XX_SYSCON_DEVCFG_GONK (1<<27)
|
||||
#define EP93XX_SYSCON_DEVCFG_TONG (1<<26)
|
||||
#define EP93XX_SYSCON_DEVCFG_MONG (1<<25)
|
||||
#define EP93XX_SYSCON_DEVCFG_U3EN 24
|
||||
#define EP93XX_SYSCON_DEVCFG_CPENA (1<<23)
|
||||
#define EP93XX_SYSCON_DEVCFG_A2ONG (1<<22)
|
||||
#define EP93XX_SYSCON_DEVCFG_A1ONG (1<<21)
|
||||
#define EP93XX_SYSCON_DEVCFG_U2EN 20
|
||||
#define EP93XX_SYSCON_DEVCFG_EXVC (1<<19)
|
||||
#define EP93XX_SYSCON_DEVCFG_U1EN 18
|
||||
#define EP93XX_SYSCON_DEVCFG_TIN (1<<17)
|
||||
#define EP93XX_SYSCON_DEVCFG_HC3IN (1<<15)
|
||||
#define EP93XX_SYSCON_DEVCFG_HC3EN (1<<14)
|
||||
#define EP93XX_SYSCON_DEVCFG_HC1IN (1<<13)
|
||||
#define EP93XX_SYSCON_DEVCFG_HC1EN (1<<12)
|
||||
#define EP93XX_SYSCON_DEVCFG_HONIDE (1<<11)
|
||||
#define EP93XX_SYSCON_DEVCFG_GONIDE (1<<10)
|
||||
#define EP93XX_SYSCON_DEVCFG_PONG (1<<9)
|
||||
#define EP93XX_SYSCON_DEVCFG_EONIDE (1<<8)
|
||||
#define EP93XX_SYSCON_DEVCFG_I2SONSSP (1<<7)
|
||||
#define EP93XX_SYSCON_DEVCFG_I2SONAC97 (1<<6)
|
||||
#define EP93XX_SYSCON_DEVCFG_RASONP3 (1<<4)
|
||||
#define EP93XX_SYSCON_DEVCFG_RAS (1<<3)
|
||||
#define EP93XX_SYSCON_DEVCFG_ADCPD (1<<2)
|
||||
#define EP93XX_SYSCON_DEVCFG_KEYS (1<<1)
|
||||
#define EP93XX_SYSCON_DEVCFG_SHENA (1<<0)
|
||||
#define EP93XX_SYSCON_VIDCLKDIV EP93XX_SYSCON_REG(0x84)
|
||||
#define EP93XX_SYSCON_CLKDIV_ENABLE 15
|
||||
#define EP93XX_SYSCON_CLKDIV_ESEL (1<<14)
|
||||
#define EP93XX_SYSCON_CLKDIV_PSEL (1<<13)
|
||||
#define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8
|
||||
#define EP93XX_SYSCON_I2SCLKDIV EP93XX_SYSCON_REG(0x8c)
|
||||
#define EP93XX_SYSCON_I2SCLKDIV_SENA 31
|
||||
#define EP93XX_SYSCON_I2SCLKDIV_ORIDE (1<<29)
|
||||
#define EP93XX_SYSCON_I2SCLKDIV_SPOL (1<<19)
|
||||
#define EP93XX_I2SCLKDIV_SDIV (1 << 16)
|
||||
#define EP93XX_I2SCLKDIV_LRDIV32 (0 << 17)
|
||||
#define EP93XX_I2SCLKDIV_LRDIV64 (1 << 17)
|
||||
#define EP93XX_I2SCLKDIV_LRDIV128 (2 << 17)
|
||||
#define EP93XX_I2SCLKDIV_LRDIV_MASK (3 << 17)
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90)
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN 31
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV 16
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV_KEN 15
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV_KDIV (1<<0)
|
||||
#define EP93XX_SYSCON_SYSCFG EP93XX_SYSCON_REG(0x9c)
|
||||
#define EP93XX_SYSCON_SYSCFG_REV_MASK (0xf0000000)
|
||||
#define EP93XX_SYSCON_SYSCFG_REV_SHIFT (28)
|
||||
#define EP93XX_SYSCON_SYSCFG_SBOOT (1<<8)
|
||||
#define EP93XX_SYSCON_SYSCFG_LCSN7 (1<<7)
|
||||
#define EP93XX_SYSCON_SYSCFG_LCSN6 (1<<6)
|
||||
#define EP93XX_SYSCON_SYSCFG_LASDO (1<<5)
|
||||
#define EP93XX_SYSCON_SYSCFG_LEEDA (1<<4)
|
||||
#define EP93XX_SYSCON_SYSCFG_LEECLK (1<<3)
|
||||
#define EP93XX_SYSCON_SYSCFG_LCSN2 (1<<1)
|
||||
#define EP93XX_SYSCON_SYSCFG_LCSN1 (1<<0)
|
||||
#define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0)
|
||||
|
||||
/* EP93xx System Controller software locked register write */
|
||||
void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg);
|
||||
void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits);
|
||||
|
||||
static inline void ep93xx_devcfg_set_bits(unsigned int bits)
|
||||
{
|
||||
ep93xx_devcfg_set_clear(bits, 0x00);
|
||||
}
|
||||
|
||||
static inline void ep93xx_devcfg_clear_bits(unsigned int bits)
|
||||
{
|
||||
ep93xx_devcfg_set_clear(0x00, bits);
|
||||
}
|
||||
|
||||
#endif /* _EP93XX_SOC_H */
|
@ -1,143 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/sched_clock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include "soc.h"
|
||||
#include "platform.h"
|
||||
|
||||
/*************************************************************************
|
||||
* Timer handling for EP93xx
|
||||
*************************************************************************
|
||||
* The ep93xx has four internal timers. Timers 1, 2 (both 16 bit) and
|
||||
* 3 (32 bit) count down at 508 kHz, are self-reloading, and can generate
|
||||
* an interrupt on underflow. Timer 4 (40 bit) counts down at 983.04 kHz,
|
||||
* is free-running, and can't generate interrupts.
|
||||
*
|
||||
* The 508 kHz timers are ideal for use for the timer interrupt, as the
|
||||
* most common values of HZ divide 508 kHz nicely. We pick the 32 bit
|
||||
* timer (timer 3) to get as long sleep intervals as possible when using
|
||||
* CONFIG_NO_HZ.
|
||||
*
|
||||
* The higher clock rate of timer 4 makes it a better choice than the
|
||||
* other timers for use as clock source and for sched_clock(), providing
|
||||
* a stable 40 bit time base.
|
||||
*************************************************************************
|
||||
*/
|
||||
#define EP93XX_TIMER_REG(x) (EP93XX_TIMER_BASE + (x))
|
||||
#define EP93XX_TIMER1_LOAD EP93XX_TIMER_REG(0x00)
|
||||
#define EP93XX_TIMER1_VALUE EP93XX_TIMER_REG(0x04)
|
||||
#define EP93XX_TIMER1_CONTROL EP93XX_TIMER_REG(0x08)
|
||||
#define EP93XX_TIMER123_CONTROL_ENABLE (1 << 7)
|
||||
#define EP93XX_TIMER123_CONTROL_MODE (1 << 6)
|
||||
#define EP93XX_TIMER123_CONTROL_CLKSEL (1 << 3)
|
||||
#define EP93XX_TIMER1_CLEAR EP93XX_TIMER_REG(0x0c)
|
||||
#define EP93XX_TIMER2_LOAD EP93XX_TIMER_REG(0x20)
|
||||
#define EP93XX_TIMER2_VALUE EP93XX_TIMER_REG(0x24)
|
||||
#define EP93XX_TIMER2_CONTROL EP93XX_TIMER_REG(0x28)
|
||||
#define EP93XX_TIMER2_CLEAR EP93XX_TIMER_REG(0x2c)
|
||||
#define EP93XX_TIMER4_VALUE_LOW EP93XX_TIMER_REG(0x60)
|
||||
#define EP93XX_TIMER4_VALUE_HIGH EP93XX_TIMER_REG(0x64)
|
||||
#define EP93XX_TIMER4_VALUE_HIGH_ENABLE (1 << 8)
|
||||
#define EP93XX_TIMER3_LOAD EP93XX_TIMER_REG(0x80)
|
||||
#define EP93XX_TIMER3_VALUE EP93XX_TIMER_REG(0x84)
|
||||
#define EP93XX_TIMER3_CONTROL EP93XX_TIMER_REG(0x88)
|
||||
#define EP93XX_TIMER3_CLEAR EP93XX_TIMER_REG(0x8c)
|
||||
|
||||
#define EP93XX_TIMER123_RATE 508469
|
||||
#define EP93XX_TIMER4_RATE 983040
|
||||
|
||||
static u64 notrace ep93xx_read_sched_clock(void)
|
||||
{
|
||||
u64 ret;
|
||||
|
||||
ret = readl(EP93XX_TIMER4_VALUE_LOW);
|
||||
ret |= ((u64) (readl(EP93XX_TIMER4_VALUE_HIGH) & 0xff) << 32);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u64 ep93xx_clocksource_read(struct clocksource *c)
|
||||
{
|
||||
u64 ret;
|
||||
|
||||
ret = readl(EP93XX_TIMER4_VALUE_LOW);
|
||||
ret |= ((u64) (readl(EP93XX_TIMER4_VALUE_HIGH) & 0xff) << 32);
|
||||
return (u64) ret;
|
||||
}
|
||||
|
||||
static int ep93xx_clkevt_set_next_event(unsigned long next,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
/* Default mode: periodic, off, 508 kHz */
|
||||
u32 tmode = EP93XX_TIMER123_CONTROL_MODE |
|
||||
EP93XX_TIMER123_CONTROL_CLKSEL;
|
||||
|
||||
/* Clear timer */
|
||||
writel(tmode, EP93XX_TIMER3_CONTROL);
|
||||
|
||||
/* Set next event */
|
||||
writel(next, EP93XX_TIMER3_LOAD);
|
||||
writel(tmode | EP93XX_TIMER123_CONTROL_ENABLE,
|
||||
EP93XX_TIMER3_CONTROL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ep93xx_clkevt_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
/* Disable timer */
|
||||
writel(0, EP93XX_TIMER3_CONTROL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device ep93xx_clockevent = {
|
||||
.name = "timer1",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_state_shutdown = ep93xx_clkevt_shutdown,
|
||||
.set_state_oneshot = ep93xx_clkevt_shutdown,
|
||||
.tick_resume = ep93xx_clkevt_shutdown,
|
||||
.set_next_event = ep93xx_clkevt_set_next_event,
|
||||
.rating = 300,
|
||||
};
|
||||
|
||||
static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct clock_event_device *evt = dev_id;
|
||||
|
||||
/* Writing any value clears the timer interrupt */
|
||||
writel(1, EP93XX_TIMER3_CLEAR);
|
||||
|
||||
evt->event_handler(evt);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
void __init ep93xx_timer_init(void)
|
||||
{
|
||||
int irq = IRQ_EP93XX_TIMER3;
|
||||
unsigned long flags = IRQF_TIMER | IRQF_IRQPOLL;
|
||||
|
||||
/* Enable and register clocksource and sched_clock on timer 4 */
|
||||
writel(EP93XX_TIMER4_VALUE_HIGH_ENABLE,
|
||||
EP93XX_TIMER4_VALUE_HIGH);
|
||||
clocksource_mmio_init(NULL, "timer4",
|
||||
EP93XX_TIMER4_RATE, 200, 40,
|
||||
ep93xx_clocksource_read);
|
||||
sched_clock_register(ep93xx_read_sched_clock, 40,
|
||||
EP93XX_TIMER4_RATE);
|
||||
|
||||
/* Set up clockevent on timer 3 */
|
||||
if (request_irq(irq, ep93xx_timer_interrupt, flags, "ep93xx timer",
|
||||
&ep93xx_clockevent))
|
||||
pr_err("Failed to request irq %d (ep93xx timer)\n", irq);
|
||||
clockevents_config_and_register(&ep93xx_clockevent,
|
||||
EP93XX_TIMER123_RATE,
|
||||
1,
|
||||
0xffffffffU);
|
||||
}
|
@ -1,422 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/ts72xx.c
|
||||
* Technologic Systems TS72xx SBC support.
|
||||
*
|
||||
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mtd/platnand.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/flash.h>
|
||||
#include <linux/spi/mmc_spi.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/platform_data/spi-ep93xx.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
|
||||
#include "gpio-ep93xx.h"
|
||||
#include "hardware.h"
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include "soc.h"
|
||||
#include "ts72xx.h"
|
||||
|
||||
/*************************************************************************
|
||||
* IO map
|
||||
*************************************************************************/
|
||||
static struct map_desc ts72xx_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = (unsigned long)TS72XX_MODEL_VIRT_BASE,
|
||||
.pfn = __phys_to_pfn(TS72XX_MODEL_PHYS_BASE),
|
||||
.length = TS72XX_MODEL_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)TS72XX_OPTIONS_VIRT_BASE,
|
||||
.pfn = __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE),
|
||||
.length = TS72XX_OPTIONS_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)TS72XX_OPTIONS2_VIRT_BASE,
|
||||
.pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE),
|
||||
.length = TS72XX_OPTIONS2_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = (unsigned long)TS72XX_CPLDVER_VIRT_BASE,
|
||||
.pfn = __phys_to_pfn(TS72XX_CPLDVER_PHYS_BASE),
|
||||
.length = TS72XX_CPLDVER_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
}
|
||||
};
|
||||
|
||||
static void __init ts72xx_map_io(void)
|
||||
{
|
||||
ep93xx_map_io();
|
||||
iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc));
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* NAND flash
|
||||
*************************************************************************/
|
||||
#define TS72XX_NAND_CONTROL_ADDR_LINE 22 /* 0xN0400000 */
|
||||
#define TS72XX_NAND_BUSY_ADDR_LINE 23 /* 0xN0800000 */
|
||||
|
||||
static void ts72xx_nand_hwcontrol(struct nand_chip *chip,
|
||||
int cmd, unsigned int ctrl)
|
||||
{
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
void __iomem *addr = chip->legacy.IO_ADDR_R;
|
||||
unsigned char bits;
|
||||
|
||||
addr += (1 << TS72XX_NAND_CONTROL_ADDR_LINE);
|
||||
|
||||
bits = __raw_readb(addr) & ~0x07;
|
||||
bits |= (ctrl & NAND_NCE) << 2; /* bit 0 -> bit 2 */
|
||||
bits |= (ctrl & NAND_CLE); /* bit 1 -> bit 1 */
|
||||
bits |= (ctrl & NAND_ALE) >> 2; /* bit 2 -> bit 0 */
|
||||
|
||||
__raw_writeb(bits, addr);
|
||||
}
|
||||
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
__raw_writeb(cmd, chip->legacy.IO_ADDR_W);
|
||||
}
|
||||
|
||||
static int ts72xx_nand_device_ready(struct nand_chip *chip)
|
||||
{
|
||||
void __iomem *addr = chip->legacy.IO_ADDR_R;
|
||||
|
||||
addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE);
|
||||
|
||||
return !!(__raw_readb(addr) & 0x20);
|
||||
}
|
||||
|
||||
#define TS72XX_BOOTROM_PART_SIZE (SZ_16K)
|
||||
#define TS72XX_REDBOOT_PART_SIZE (SZ_2M + SZ_1M)
|
||||
|
||||
static struct mtd_partition ts72xx_nand_parts[] = {
|
||||
{
|
||||
.name = "TS-BOOTROM",
|
||||
.offset = 0,
|
||||
.size = TS72XX_BOOTROM_PART_SIZE,
|
||||
.mask_flags = MTD_WRITEABLE, /* force read-only */
|
||||
}, {
|
||||
.name = "Linux",
|
||||
.offset = MTDPART_OFS_RETAIN,
|
||||
.size = TS72XX_REDBOOT_PART_SIZE,
|
||||
/* leave so much for last partition */
|
||||
}, {
|
||||
.name = "RedBoot",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
.mask_flags = MTD_WRITEABLE, /* force read-only */
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_nand_data ts72xx_nand_data = {
|
||||
.chip = {
|
||||
.nr_chips = 1,
|
||||
.chip_offset = 0,
|
||||
.chip_delay = 15,
|
||||
},
|
||||
.ctrl = {
|
||||
.cmd_ctrl = ts72xx_nand_hwcontrol,
|
||||
.dev_ready = ts72xx_nand_device_ready,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource ts72xx_nand_resource[] = {
|
||||
{
|
||||
.start = 0, /* filled in later */
|
||||
.end = 0, /* filled in later */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device ts72xx_nand_flash = {
|
||||
.name = "gen_nand",
|
||||
.id = -1,
|
||||
.dev.platform_data = &ts72xx_nand_data,
|
||||
.resource = ts72xx_nand_resource,
|
||||
.num_resources = ARRAY_SIZE(ts72xx_nand_resource),
|
||||
};
|
||||
|
||||
static void __init ts72xx_register_flash(struct mtd_partition *parts, int n,
|
||||
resource_size_t start)
|
||||
{
|
||||
/*
|
||||
* TS7200 has NOR flash all other TS72xx board have NAND flash.
|
||||
*/
|
||||
if (board_is_ts7200()) {
|
||||
ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_16M);
|
||||
} else {
|
||||
ts72xx_nand_resource[0].start = start;
|
||||
ts72xx_nand_resource[0].end = start + SZ_16M - 1;
|
||||
|
||||
ts72xx_nand_data.chip.partitions = parts;
|
||||
ts72xx_nand_data.chip.nr_partitions = n;
|
||||
|
||||
platform_device_register(&ts72xx_nand_flash);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* RTC M48T86
|
||||
*************************************************************************/
|
||||
#define TS72XX_RTC_INDEX_PHYS_BASE (EP93XX_CS1_PHYS_BASE + 0x00800000)
|
||||
#define TS72XX_RTC_DATA_PHYS_BASE (EP93XX_CS1_PHYS_BASE + 0x01700000)
|
||||
|
||||
static struct resource ts72xx_rtc_resources[] = {
|
||||
DEFINE_RES_MEM(TS72XX_RTC_INDEX_PHYS_BASE, 0x01),
|
||||
DEFINE_RES_MEM(TS72XX_RTC_DATA_PHYS_BASE, 0x01),
|
||||
};
|
||||
|
||||
static struct platform_device ts72xx_rtc_device = {
|
||||
.name = "rtc-m48t86",
|
||||
.id = -1,
|
||||
.resource = ts72xx_rtc_resources,
|
||||
.num_resources = ARRAY_SIZE(ts72xx_rtc_resources),
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* Watchdog (in CPLD)
|
||||
*************************************************************************/
|
||||
#define TS72XX_WDT_CONTROL_PHYS_BASE (EP93XX_CS2_PHYS_BASE + 0x03800000)
|
||||
#define TS72XX_WDT_FEED_PHYS_BASE (EP93XX_CS2_PHYS_BASE + 0x03c00000)
|
||||
|
||||
static struct resource ts72xx_wdt_resources[] = {
|
||||
DEFINE_RES_MEM(TS72XX_WDT_CONTROL_PHYS_BASE, 0x01),
|
||||
DEFINE_RES_MEM(TS72XX_WDT_FEED_PHYS_BASE, 0x01),
|
||||
};
|
||||
|
||||
static struct platform_device ts72xx_wdt_device = {
|
||||
.name = "ts72xx-wdt",
|
||||
.id = -1,
|
||||
.resource = ts72xx_wdt_resources,
|
||||
.num_resources = ARRAY_SIZE(ts72xx_wdt_resources),
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* ETH
|
||||
*************************************************************************/
|
||||
static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
|
||||
.phy_id = 1,
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* SPI SD/MMC host
|
||||
*************************************************************************/
|
||||
#define BK3_EN_SDCARD_PHYS_BASE 0x12400000
|
||||
#define BK3_EN_SDCARD_PWR 0x0
|
||||
#define BK3_DIS_SDCARD_PWR 0x0C
|
||||
static void bk3_mmc_spi_setpower(struct device *dev, unsigned int vdd)
|
||||
{
|
||||
void __iomem *pwr_sd = ioremap(BK3_EN_SDCARD_PHYS_BASE, SZ_4K);
|
||||
|
||||
if (!pwr_sd) {
|
||||
pr_err("Failed to enable SD card power!");
|
||||
return;
|
||||
}
|
||||
|
||||
pr_debug("%s: SD card pwr %s VDD:0x%x\n", __func__,
|
||||
!!vdd ? "ON" : "OFF", vdd);
|
||||
|
||||
if (!!vdd)
|
||||
__raw_writeb(BK3_EN_SDCARD_PWR, pwr_sd);
|
||||
else
|
||||
__raw_writeb(BK3_DIS_SDCARD_PWR, pwr_sd);
|
||||
|
||||
iounmap(pwr_sd);
|
||||
}
|
||||
|
||||
static struct mmc_spi_platform_data bk3_spi_mmc_data = {
|
||||
.detect_delay = 500,
|
||||
.powerup_msecs = 100,
|
||||
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||
.caps = MMC_CAP_NONREMOVABLE,
|
||||
.setpower = bk3_mmc_spi_setpower,
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* SPI Bus - SD card access
|
||||
*************************************************************************/
|
||||
static struct spi_board_info bk3_spi_board_info[] __initdata = {
|
||||
{
|
||||
.modalias = "mmc_spi",
|
||||
.platform_data = &bk3_spi_mmc_data,
|
||||
.max_speed_hz = 7.4E6,
|
||||
.bus_num = 0,
|
||||
.chip_select = 0,
|
||||
.mode = SPI_MODE_0,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* This is a stub -> the FGPIO[3] pin is not connected on the schematic
|
||||
* The all work is performed automatically by !SPI_FRAME (SFRM1) and
|
||||
* goes through CPLD
|
||||
*/
|
||||
static struct gpiod_lookup_table bk3_spi_cs_gpio_table = {
|
||||
.dev_id = "spi0",
|
||||
.table = {
|
||||
GPIO_LOOKUP("F", 3, "cs", GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct ep93xx_spi_info bk3_spi_master __initdata = {
|
||||
.use_dma = 1,
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* TS72XX support code
|
||||
*************************************************************************/
|
||||
#if IS_ENABLED(CONFIG_FPGA_MGR_TS73XX)
|
||||
|
||||
/* Relative to EP93XX_CS1_PHYS_BASE */
|
||||
#define TS73XX_FPGA_LOADER_BASE 0x03c00000
|
||||
|
||||
static struct resource ts73xx_fpga_resources[] = {
|
||||
{
|
||||
.start = EP93XX_CS1_PHYS_BASE + TS73XX_FPGA_LOADER_BASE,
|
||||
.end = EP93XX_CS1_PHYS_BASE + TS73XX_FPGA_LOADER_BASE + 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device ts73xx_fpga_device = {
|
||||
.name = "ts73xx-fpga-mgr",
|
||||
.id = -1,
|
||||
.resource = ts73xx_fpga_resources,
|
||||
.num_resources = ARRAY_SIZE(ts73xx_fpga_resources),
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
* SPI Bus
|
||||
*************************************************************************/
|
||||
static struct spi_board_info ts72xx_spi_devices[] __initdata = {
|
||||
{
|
||||
.modalias = "tmp122",
|
||||
.max_speed_hz = 2 * 1000 * 1000,
|
||||
.bus_num = 0,
|
||||
.chip_select = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table ts72xx_spi_cs_gpio_table = {
|
||||
.dev_id = "spi0",
|
||||
.table = {
|
||||
/* DIO_17 */
|
||||
GPIO_LOOKUP("F", 2, "cs", GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct ep93xx_spi_info ts72xx_spi_info __initdata = {
|
||||
/* Intentionally left blank */
|
||||
};
|
||||
|
||||
static void __init ts72xx_init_machine(void)
|
||||
{
|
||||
ep93xx_init_devices();
|
||||
ts72xx_register_flash(ts72xx_nand_parts, ARRAY_SIZE(ts72xx_nand_parts),
|
||||
is_ts9420_installed() ?
|
||||
EP93XX_CS7_PHYS_BASE : EP93XX_CS6_PHYS_BASE);
|
||||
platform_device_register(&ts72xx_rtc_device);
|
||||
platform_device_register(&ts72xx_wdt_device);
|
||||
|
||||
ep93xx_register_eth(&ts72xx_eth_data, 1);
|
||||
#if IS_ENABLED(CONFIG_FPGA_MGR_TS73XX)
|
||||
if (board_is_ts7300())
|
||||
platform_device_register(&ts73xx_fpga_device);
|
||||
#endif
|
||||
gpiod_add_lookup_table(&ts72xx_spi_cs_gpio_table);
|
||||
ep93xx_register_spi(&ts72xx_spi_info, ts72xx_spi_devices,
|
||||
ARRAY_SIZE(ts72xx_spi_devices));
|
||||
}
|
||||
|
||||
MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
|
||||
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ts72xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = ts72xx_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
||||
|
||||
/*************************************************************************
|
||||
* EP93xx I2S audio peripheral handling
|
||||
*************************************************************************/
|
||||
static struct resource ep93xx_i2s_resource[] = {
|
||||
DEFINE_RES_MEM(EP93XX_I2S_PHYS_BASE, 0x100),
|
||||
DEFINE_RES_IRQ_NAMED(IRQ_EP93XX_SAI, "spilink i2s slave"),
|
||||
};
|
||||
|
||||
static struct platform_device ep93xx_i2s_device = {
|
||||
.name = "ep93xx-spilink-i2s",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(ep93xx_i2s_resource),
|
||||
.resource = ep93xx_i2s_resource,
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* BK3 support code
|
||||
*************************************************************************/
|
||||
static struct mtd_partition bk3_nand_parts[] = {
|
||||
{
|
||||
.name = "System",
|
||||
.offset = 0x00000000,
|
||||
.size = 0x01e00000,
|
||||
}, {
|
||||
.name = "Data",
|
||||
.offset = 0x01e00000,
|
||||
.size = 0x05f20000
|
||||
}, {
|
||||
.name = "RedBoot",
|
||||
.offset = 0x07d20000,
|
||||
.size = 0x002e0000,
|
||||
.mask_flags = MTD_WRITEABLE, /* force RO */
|
||||
},
|
||||
};
|
||||
|
||||
static void __init bk3_init_machine(void)
|
||||
{
|
||||
ep93xx_init_devices();
|
||||
|
||||
ts72xx_register_flash(bk3_nand_parts, ARRAY_SIZE(bk3_nand_parts),
|
||||
EP93XX_CS6_PHYS_BASE);
|
||||
|
||||
ep93xx_register_eth(&ts72xx_eth_data, 1);
|
||||
|
||||
gpiod_add_lookup_table(&bk3_spi_cs_gpio_table);
|
||||
ep93xx_register_spi(&bk3_spi_master, bk3_spi_board_info,
|
||||
ARRAY_SIZE(bk3_spi_board_info));
|
||||
|
||||
/* Configure ep93xx's I2S to use AC97 pins */
|
||||
ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_I2SONAC97);
|
||||
platform_device_register(&ep93xx_i2s_device);
|
||||
}
|
||||
|
||||
MACHINE_START(BK3, "Liebherr controller BK3.1")
|
||||
/* Maintainer: Lukasz Majewski <lukma@denx.de> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS,
|
||||
.map_io = ts72xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = bk3_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
@ -1,94 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/include/mach/ts72xx.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* TS72xx memory map:
|
||||
*
|
||||
* virt phys size
|
||||
* febff000 22000000 4K model number register (bits 0-2)
|
||||
* febfe000 22400000 4K options register
|
||||
* febfd000 22800000 4K options register #2
|
||||
* febfc000 23400000 4K CPLD version register
|
||||
*/
|
||||
|
||||
#ifndef __TS72XX_H_
|
||||
#define __TS72XX_H_
|
||||
|
||||
#define TS72XX_MODEL_PHYS_BASE 0x22000000
|
||||
#define TS72XX_MODEL_VIRT_BASE IOMEM(0xfebff000)
|
||||
#define TS72XX_MODEL_SIZE 0x00001000
|
||||
|
||||
#define TS72XX_MODEL_TS7200 0x00
|
||||
#define TS72XX_MODEL_TS7250 0x01
|
||||
#define TS72XX_MODEL_TS7260 0x02
|
||||
#define TS72XX_MODEL_TS7300 0x03
|
||||
#define TS72XX_MODEL_TS7400 0x04
|
||||
#define TS72XX_MODEL_MASK 0x07
|
||||
|
||||
|
||||
#define TS72XX_OPTIONS_PHYS_BASE 0x22400000
|
||||
#define TS72XX_OPTIONS_VIRT_BASE IOMEM(0xfebfe000)
|
||||
#define TS72XX_OPTIONS_SIZE 0x00001000
|
||||
|
||||
#define TS72XX_OPTIONS_COM2_RS485 0x02
|
||||
#define TS72XX_OPTIONS_MAX197 0x01
|
||||
|
||||
|
||||
#define TS72XX_OPTIONS2_PHYS_BASE 0x22800000
|
||||
#define TS72XX_OPTIONS2_VIRT_BASE IOMEM(0xfebfd000)
|
||||
#define TS72XX_OPTIONS2_SIZE 0x00001000
|
||||
|
||||
#define TS72XX_OPTIONS2_TS9420 0x04
|
||||
#define TS72XX_OPTIONS2_TS9420_BOOT 0x02
|
||||
|
||||
#define TS72XX_CPLDVER_PHYS_BASE 0x23400000
|
||||
#define TS72XX_CPLDVER_VIRT_BASE IOMEM(0xfebfc000)
|
||||
#define TS72XX_CPLDVER_SIZE 0x00001000
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
static inline int ts72xx_model(void)
|
||||
{
|
||||
return __raw_readb(TS72XX_MODEL_VIRT_BASE) & TS72XX_MODEL_MASK;
|
||||
}
|
||||
|
||||
static inline int board_is_ts7200(void)
|
||||
{
|
||||
return ts72xx_model() == TS72XX_MODEL_TS7200;
|
||||
}
|
||||
|
||||
static inline int board_is_ts7250(void)
|
||||
{
|
||||
return ts72xx_model() == TS72XX_MODEL_TS7250;
|
||||
}
|
||||
|
||||
static inline int board_is_ts7260(void)
|
||||
{
|
||||
return ts72xx_model() == TS72XX_MODEL_TS7260;
|
||||
}
|
||||
|
||||
static inline int board_is_ts7300(void)
|
||||
{
|
||||
return ts72xx_model() == TS72XX_MODEL_TS7300;
|
||||
}
|
||||
|
||||
static inline int board_is_ts7400(void)
|
||||
{
|
||||
return ts72xx_model() == TS72XX_MODEL_TS7400;
|
||||
}
|
||||
|
||||
static inline int is_max197_installed(void)
|
||||
{
|
||||
return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
|
||||
TS72XX_OPTIONS_MAX197);
|
||||
}
|
||||
|
||||
static inline int is_ts9420_installed(void)
|
||||
{
|
||||
return !!(__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) &
|
||||
TS72XX_OPTIONS2_TS9420);
|
||||
}
|
||||
#endif
|
||||
#endif /* __TS72XX_H_ */
|
@ -1,319 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/vision_ep9307.c
|
||||
* Vision Engraving Systems EP9307 SoM support.
|
||||
*
|
||||
* Copyright (C) 2008-2011 Vision Engraving Systems
|
||||
* H Hartley Sweeten <hsweeten@visionengravers.com>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_data/pca953x.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/flash.h>
|
||||
#include <linux/spi/mmc_spi.h>
|
||||
#include <linux/mmc/host.h>
|
||||
|
||||
#include <sound/cs4271.h>
|
||||
|
||||
#include "hardware.h"
|
||||
#include <linux/platform_data/video-ep93xx.h>
|
||||
#include <linux/platform_data/spi-ep93xx.h>
|
||||
#include "gpio-ep93xx.h"
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include "soc.h"
|
||||
|
||||
/*************************************************************************
|
||||
* Static I/O mappings for the FPGA
|
||||
*************************************************************************/
|
||||
#define VISION_PHYS_BASE EP93XX_CS7_PHYS_BASE
|
||||
#define VISION_VIRT_BASE 0xfebff000
|
||||
|
||||
static struct map_desc vision_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = VISION_VIRT_BASE,
|
||||
.pfn = __phys_to_pfn(VISION_PHYS_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
};
|
||||
|
||||
static void __init vision_map_io(void)
|
||||
{
|
||||
ep93xx_map_io();
|
||||
|
||||
iotable_init(vision_io_desc, ARRAY_SIZE(vision_io_desc));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Ethernet
|
||||
*************************************************************************/
|
||||
static struct ep93xx_eth_data vision_eth_data __initdata = {
|
||||
.phy_id = 1,
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* Framebuffer
|
||||
*************************************************************************/
|
||||
#define VISION_LCD_ENABLE EP93XX_GPIO_LINE_EGPIO1
|
||||
|
||||
static int vision_lcd_setup(struct platform_device *pdev)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = gpio_request_one(VISION_LCD_ENABLE, GPIOF_OUT_INIT_HIGH, dev_name(&pdev->dev));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_RAS |
|
||||
EP93XX_SYSCON_DEVCFG_RASONP3 |
|
||||
EP93XX_SYSCON_DEVCFG_EXVC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vision_lcd_teardown(struct platform_device *pdev)
|
||||
{
|
||||
gpio_free(VISION_LCD_ENABLE);
|
||||
}
|
||||
|
||||
static void vision_lcd_blank(int blank_mode, struct fb_info *info)
|
||||
{
|
||||
if (blank_mode)
|
||||
gpio_set_value(VISION_LCD_ENABLE, 0);
|
||||
else
|
||||
gpio_set_value(VISION_LCD_ENABLE, 1);
|
||||
}
|
||||
|
||||
static struct ep93xxfb_mach_info ep93xxfb_info __initdata = {
|
||||
.flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING,
|
||||
.setup = vision_lcd_setup,
|
||||
.teardown = vision_lcd_teardown,
|
||||
.blank = vision_lcd_blank,
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* GPIO Expanders
|
||||
*************************************************************************/
|
||||
#define PCA9539_74_GPIO_BASE (EP93XX_GPIO_LINE_MAX + 1)
|
||||
#define PCA9539_75_GPIO_BASE (PCA9539_74_GPIO_BASE + 16)
|
||||
#define PCA9539_76_GPIO_BASE (PCA9539_75_GPIO_BASE + 16)
|
||||
#define PCA9539_77_GPIO_BASE (PCA9539_76_GPIO_BASE + 16)
|
||||
|
||||
static struct pca953x_platform_data pca953x_74_gpio_data = {
|
||||
.gpio_base = PCA9539_74_GPIO_BASE,
|
||||
.irq_base = EP93XX_BOARD_IRQ(0),
|
||||
};
|
||||
|
||||
static struct pca953x_platform_data pca953x_75_gpio_data = {
|
||||
.gpio_base = PCA9539_75_GPIO_BASE,
|
||||
.irq_base = -1,
|
||||
};
|
||||
|
||||
static struct pca953x_platform_data pca953x_76_gpio_data = {
|
||||
.gpio_base = PCA9539_76_GPIO_BASE,
|
||||
.irq_base = -1,
|
||||
};
|
||||
|
||||
static struct pca953x_platform_data pca953x_77_gpio_data = {
|
||||
.gpio_base = PCA9539_77_GPIO_BASE,
|
||||
.irq_base = -1,
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* I2C Bus
|
||||
*************************************************************************/
|
||||
|
||||
static struct i2c_board_info vision_i2c_info[] __initdata = {
|
||||
{
|
||||
I2C_BOARD_INFO("isl1208", 0x6f),
|
||||
.irq = IRQ_EP93XX_EXT1,
|
||||
}, {
|
||||
I2C_BOARD_INFO("pca9539", 0x74),
|
||||
.platform_data = &pca953x_74_gpio_data,
|
||||
}, {
|
||||
I2C_BOARD_INFO("pca9539", 0x75),
|
||||
.platform_data = &pca953x_75_gpio_data,
|
||||
}, {
|
||||
I2C_BOARD_INFO("pca9539", 0x76),
|
||||
.platform_data = &pca953x_76_gpio_data,
|
||||
}, {
|
||||
I2C_BOARD_INFO("pca9539", 0x77),
|
||||
.platform_data = &pca953x_77_gpio_data,
|
||||
},
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* SPI CS4271 Audio Codec
|
||||
*************************************************************************/
|
||||
static struct cs4271_platform_data vision_cs4271_data = {
|
||||
/* Intentionally left blank */
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* SPI Flash
|
||||
*************************************************************************/
|
||||
static struct mtd_partition vision_spi_flash_partitions[] = {
|
||||
{
|
||||
.name = "SPI bootstrap",
|
||||
.offset = 0,
|
||||
.size = SZ_4K,
|
||||
}, {
|
||||
.name = "Bootstrap config",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = SZ_4K,
|
||||
}, {
|
||||
.name = "System config",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
},
|
||||
};
|
||||
|
||||
static struct flash_platform_data vision_spi_flash_data = {
|
||||
.name = "SPI Flash",
|
||||
.parts = vision_spi_flash_partitions,
|
||||
.nr_parts = ARRAY_SIZE(vision_spi_flash_partitions),
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* SPI SD/MMC host
|
||||
*************************************************************************/
|
||||
static struct mmc_spi_platform_data vision_spi_mmc_data = {
|
||||
.detect_delay = 100,
|
||||
.powerup_msecs = 100,
|
||||
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||
.caps2 = MMC_CAP2_RO_ACTIVE_HIGH,
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table vision_spi_mmc_gpio_table = {
|
||||
.dev_id = "mmc_spi.2", /* "mmc_spi @ CS2 */
|
||||
.table = {
|
||||
/* Card detect */
|
||||
GPIO_LOOKUP_IDX("B", 7, NULL, 0, GPIO_ACTIVE_LOW),
|
||||
/* Write protect */
|
||||
GPIO_LOOKUP_IDX("F", 0, NULL, 1, GPIO_ACTIVE_HIGH),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* SPI Bus
|
||||
*************************************************************************/
|
||||
static struct spi_board_info vision_spi_board_info[] __initdata = {
|
||||
{
|
||||
.modalias = "cs4271",
|
||||
.platform_data = &vision_cs4271_data,
|
||||
.max_speed_hz = 6000000,
|
||||
.bus_num = 0,
|
||||
.chip_select = 0,
|
||||
.mode = SPI_MODE_3,
|
||||
}, {
|
||||
.modalias = "sst25l",
|
||||
.platform_data = &vision_spi_flash_data,
|
||||
.max_speed_hz = 20000000,
|
||||
.bus_num = 0,
|
||||
.chip_select = 1,
|
||||
.mode = SPI_MODE_3,
|
||||
}, {
|
||||
.modalias = "mmc_spi",
|
||||
.platform_data = &vision_spi_mmc_data,
|
||||
.max_speed_hz = 20000000,
|
||||
.bus_num = 0,
|
||||
.chip_select = 2,
|
||||
.mode = SPI_MODE_3,
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table vision_spi_cs4271_gpio_table = {
|
||||
.dev_id = "spi0.0", /* cs4271 @ CS0 */
|
||||
.table = {
|
||||
/* RESET */
|
||||
GPIO_LOOKUP_IDX("H", 2, NULL, 0, GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table vision_spi_cs_gpio_table = {
|
||||
.dev_id = "spi0",
|
||||
.table = {
|
||||
GPIO_LOOKUP_IDX("A", 6, "cs", 0, GPIO_ACTIVE_LOW),
|
||||
GPIO_LOOKUP_IDX("A", 7, "cs", 1, GPIO_ACTIVE_LOW),
|
||||
GPIO_LOOKUP_IDX("G", 2, "cs", 2, GPIO_ACTIVE_LOW),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static struct ep93xx_spi_info vision_spi_master __initdata = {
|
||||
.use_dma = 1,
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* I2S Audio
|
||||
*************************************************************************/
|
||||
static struct platform_device vision_audio_device = {
|
||||
.name = "edb93xx-audio",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static void __init vision_register_i2s(void)
|
||||
{
|
||||
ep93xx_register_i2s();
|
||||
platform_device_register(&vision_audio_device);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Machine Initialization
|
||||
*************************************************************************/
|
||||
static void __init vision_init_machine(void)
|
||||
{
|
||||
ep93xx_init_devices();
|
||||
ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_64M);
|
||||
ep93xx_register_eth(&vision_eth_data, 1);
|
||||
ep93xx_register_fb(&ep93xxfb_info);
|
||||
ep93xx_register_pwm(1, 0);
|
||||
|
||||
/*
|
||||
* Request the gpio expander's interrupt gpio line now to prevent
|
||||
* the kernel from doing a WARN in gpiolib:gpio_ensure_requested().
|
||||
*/
|
||||
if (gpio_request_one(EP93XX_GPIO_LINE_F(7), GPIOF_IN, "pca9539:74"))
|
||||
pr_warn("cannot request interrupt gpio for pca9539:74\n");
|
||||
|
||||
vision_i2c_info[1].irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7));
|
||||
|
||||
ep93xx_register_i2c(vision_i2c_info,
|
||||
ARRAY_SIZE(vision_i2c_info));
|
||||
gpiod_add_lookup_table(&vision_spi_cs4271_gpio_table);
|
||||
gpiod_add_lookup_table(&vision_spi_mmc_gpio_table);
|
||||
gpiod_add_lookup_table(&vision_spi_cs_gpio_table);
|
||||
ep93xx_register_spi(&vision_spi_master, vision_spi_board_info,
|
||||
ARRAY_SIZE(vision_spi_board_info));
|
||||
vision_register_i2s();
|
||||
}
|
||||
|
||||
MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307")
|
||||
/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
|
||||
.atag_offset = 0x100,
|
||||
.nr_irqs = NR_EP93XX_IRQS + EP93XX_BOARD_IRQS,
|
||||
.map_io = vision_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.init_time = ep93xx_timer_init,
|
||||
.init_machine = vision_init_machine,
|
||||
.restart = ep93xx_restart,
|
||||
MACHINE_END
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include <asm/cp15.h>
|
||||
#include <asm/system_info.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <asm/opcodes.h>
|
||||
|
||||
#include "fault.h"
|
||||
|
@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
#include <asm/neon.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <crypto/aes.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <crypto/internal/aead.h>
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <crypto/aes.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/internal/simd.h>
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <crypto/aes.h>
|
||||
#include <crypto/gcm.h>
|
||||
#include <crypto/algapi.h>
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <crypto/internal/poly1305.h>
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <crypto/internal/simd.h>
|
||||
#include <crypto/sha1.h>
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <crypto/internal/simd.h>
|
||||
#include <crypto/sha2.h>
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <crypto/internal/simd.h>
|
||||
#include <crypto/sha3.h>
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <crypto/internal/simd.h>
|
||||
#include <crypto/sha2.h>
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <crypto/internal/simd.h>
|
||||
#include <crypto/sm3.h>
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <crypto/internal/simd.h>
|
||||
#include <crypto/sm3.h>
|
||||
|
@ -264,8 +264,7 @@ SECTIONS
|
||||
EXIT_DATA
|
||||
}
|
||||
|
||||
RUNTIME_CONST(shift, d_hash_shift)
|
||||
RUNTIME_CONST(ptr, dentry_hashtable)
|
||||
RUNTIME_CONST_VARIABLES
|
||||
|
||||
PERCPU_SECTION(L1_CACHE_BYTES)
|
||||
HYPERVISOR_PERCPU_SECTION
|
||||
|
@ -2164,7 +2164,7 @@ static void cpu_hyp_uninit(void *discard)
|
||||
}
|
||||
}
|
||||
|
||||
int kvm_arch_hardware_enable(void)
|
||||
int kvm_arch_enable_virtualization_cpu(void)
|
||||
{
|
||||
/*
|
||||
* Most calls to this function are made with migration
|
||||
@ -2184,7 +2184,7 @@ int kvm_arch_hardware_enable(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kvm_arch_hardware_disable(void)
|
||||
void kvm_arch_disable_virtualization_cpu(void)
|
||||
{
|
||||
kvm_timer_cpu_down();
|
||||
kvm_vgic_cpu_down();
|
||||
@ -2380,7 +2380,7 @@ static int __init do_pkvm_init(u32 hyp_va_bits)
|
||||
|
||||
/*
|
||||
* The stub hypercalls are now disabled, so set our local flag to
|
||||
* prevent a later re-init attempt in kvm_arch_hardware_enable().
|
||||
* prevent a later re-init attempt in kvm_arch_enable_virtualization_cpu().
|
||||
*/
|
||||
__this_cpu_write(kvm_hyp_initialized, 1);
|
||||
preempt_enable();
|
||||
|
@ -25,6 +25,8 @@ config LOONGARCH
|
||||
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
|
||||
select ARCH_HAS_PTE_DEVMAP
|
||||
select ARCH_HAS_PTE_SPECIAL
|
||||
select ARCH_HAS_SET_MEMORY
|
||||
select ARCH_HAS_SET_DIRECT_MAP
|
||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||
select ARCH_INLINE_READ_LOCK if !PREEMPTION
|
||||
select ARCH_INLINE_READ_LOCK_BH if !PREEMPTION
|
||||
@ -82,6 +84,7 @@ config LOONGARCH
|
||||
select GENERIC_CMOS_UPDATE
|
||||
select GENERIC_CPU_AUTOPROBE
|
||||
select GENERIC_CPU_DEVICES
|
||||
select GENERIC_CPU_VULNERABILITIES
|
||||
select GENERIC_ENTRY
|
||||
select GENERIC_GETTIMEOFDAY
|
||||
select GENERIC_IOREMAP if !ARCH_IOREMAP
|
||||
@ -147,7 +150,7 @@ config LOONGARCH
|
||||
select HAVE_LIVEPATCH
|
||||
select HAVE_MOD_ARCH_SPECIFIC
|
||||
select HAVE_NMI
|
||||
select HAVE_OBJTOOL if AS_HAS_EXPLICIT_RELOCS && AS_HAS_THIN_ADD_SUB && !CC_IS_CLANG
|
||||
select HAVE_OBJTOOL if AS_HAS_EXPLICIT_RELOCS && AS_HAS_THIN_ADD_SUB
|
||||
select HAVE_PCI
|
||||
select HAVE_PERF_EVENTS
|
||||
select HAVE_PERF_REGS
|
||||
@ -267,7 +270,7 @@ config AS_HAS_FCSR_CLASS
|
||||
def_bool $(as-instr,movfcsr2gr \$t0$(comma)\$fcsr0)
|
||||
|
||||
config AS_HAS_THIN_ADD_SUB
|
||||
def_bool $(cc-option,-Wa$(comma)-mthin-add-sub)
|
||||
def_bool $(cc-option,-Wa$(comma)-mthin-add-sub) || AS_IS_LLVM
|
||||
|
||||
config AS_HAS_LSX_EXTENSION
|
||||
def_bool $(as-instr,vld \$vr0$(comma)\$a0$(comma)0)
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <crypto/internal/hash.h>
|
||||
|
||||
#include <asm/cpu-features.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/unaligned.h>
|
||||
|
||||
#define _CRC32(crc, value, size, type) \
|
||||
do { \
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define __LL "ll.w "
|
||||
#define __SC "sc.w "
|
||||
#define __AMADD "amadd.w "
|
||||
#define __AMOR "amor.w "
|
||||
#define __AMAND_DB "amand_db.w "
|
||||
#define __AMOR_DB "amor_db.w "
|
||||
#define __AMXOR_DB "amxor_db.w "
|
||||
@ -22,6 +23,7 @@
|
||||
#define __LL "ll.d "
|
||||
#define __SC "sc.d "
|
||||
#define __AMADD "amadd.d "
|
||||
#define __AMOR "amor.d "
|
||||
#define __AMAND_DB "amand_db.d "
|
||||
#define __AMOR_DB "amor_db.d "
|
||||
#define __AMXOR_DB "amxor_db.d "
|
||||
|
@ -51,6 +51,7 @@
|
||||
#define cpu_has_lbt_mips cpu_opt(LOONGARCH_CPU_LBT_MIPS)
|
||||
#define cpu_has_lbt (cpu_has_lbt_x86|cpu_has_lbt_arm|cpu_has_lbt_mips)
|
||||
#define cpu_has_csr cpu_opt(LOONGARCH_CPU_CSR)
|
||||
#define cpu_has_iocsr cpu_opt(LOONGARCH_CPU_IOCSR)
|
||||
#define cpu_has_tlb cpu_opt(LOONGARCH_CPU_TLB)
|
||||
#define cpu_has_watch cpu_opt(LOONGARCH_CPU_WATCH)
|
||||
#define cpu_has_vint cpu_opt(LOONGARCH_CPU_VINT)
|
||||
@ -65,6 +66,7 @@
|
||||
#define cpu_has_guestid cpu_opt(LOONGARCH_CPU_GUESTID)
|
||||
#define cpu_has_hypervisor cpu_opt(LOONGARCH_CPU_HYPERVISOR)
|
||||
#define cpu_has_ptw cpu_opt(LOONGARCH_CPU_PTW)
|
||||
#define cpu_has_lspw cpu_opt(LOONGARCH_CPU_LSPW)
|
||||
#define cpu_has_avecint cpu_opt(LOONGARCH_CPU_AVECINT)
|
||||
|
||||
#endif /* __ASM_CPU_FEATURES_H */
|
||||
|
@ -87,19 +87,21 @@ enum cpu_type_enum {
|
||||
#define CPU_FEATURE_LBT_MIPS 12 /* CPU has MIPS Binary Translation */
|
||||
#define CPU_FEATURE_TLB 13 /* CPU has TLB */
|
||||
#define CPU_FEATURE_CSR 14 /* CPU has CSR */
|
||||
#define CPU_FEATURE_WATCH 15 /* CPU has watchpoint registers */
|
||||
#define CPU_FEATURE_VINT 16 /* CPU has vectored interrupts */
|
||||
#define CPU_FEATURE_CSRIPI 17 /* CPU has CSR-IPI */
|
||||
#define CPU_FEATURE_EXTIOI 18 /* CPU has EXT-IOI */
|
||||
#define CPU_FEATURE_PREFETCH 19 /* CPU has prefetch instructions */
|
||||
#define CPU_FEATURE_PMP 20 /* CPU has perfermance counter */
|
||||
#define CPU_FEATURE_SCALEFREQ 21 /* CPU supports cpufreq scaling */
|
||||
#define CPU_FEATURE_FLATMODE 22 /* CPU has flat mode */
|
||||
#define CPU_FEATURE_EIODECODE 23 /* CPU has EXTIOI interrupt pin decode mode */
|
||||
#define CPU_FEATURE_GUESTID 24 /* CPU has GuestID feature */
|
||||
#define CPU_FEATURE_HYPERVISOR 25 /* CPU has hypervisor (running in VM) */
|
||||
#define CPU_FEATURE_PTW 26 /* CPU has hardware page table walker */
|
||||
#define CPU_FEATURE_AVECINT 27 /* CPU has avec interrupt */
|
||||
#define CPU_FEATURE_IOCSR 15 /* CPU has IOCSR */
|
||||
#define CPU_FEATURE_WATCH 16 /* CPU has watchpoint registers */
|
||||
#define CPU_FEATURE_VINT 17 /* CPU has vectored interrupts */
|
||||
#define CPU_FEATURE_CSRIPI 18 /* CPU has CSR-IPI */
|
||||
#define CPU_FEATURE_EXTIOI 19 /* CPU has EXT-IOI */
|
||||
#define CPU_FEATURE_PREFETCH 20 /* CPU has prefetch instructions */
|
||||
#define CPU_FEATURE_PMP 21 /* CPU has perfermance counter */
|
||||
#define CPU_FEATURE_SCALEFREQ 22 /* CPU supports cpufreq scaling */
|
||||
#define CPU_FEATURE_FLATMODE 23 /* CPU has flat mode */
|
||||
#define CPU_FEATURE_EIODECODE 24 /* CPU has EXTIOI interrupt pin decode mode */
|
||||
#define CPU_FEATURE_GUESTID 25 /* CPU has GuestID feature */
|
||||
#define CPU_FEATURE_HYPERVISOR 26 /* CPU has hypervisor (running in VM) */
|
||||
#define CPU_FEATURE_PTW 27 /* CPU has hardware page table walker */
|
||||
#define CPU_FEATURE_LSPW 28 /* CPU has LSPW (lddir/ldpte instructions) */
|
||||
#define CPU_FEATURE_AVECINT 29 /* CPU has AVEC interrupt */
|
||||
|
||||
#define LOONGARCH_CPU_CPUCFG BIT_ULL(CPU_FEATURE_CPUCFG)
|
||||
#define LOONGARCH_CPU_LAM BIT_ULL(CPU_FEATURE_LAM)
|
||||
@ -115,6 +117,7 @@ enum cpu_type_enum {
|
||||
#define LOONGARCH_CPU_LBT_ARM BIT_ULL(CPU_FEATURE_LBT_ARM)
|
||||
#define LOONGARCH_CPU_LBT_MIPS BIT_ULL(CPU_FEATURE_LBT_MIPS)
|
||||
#define LOONGARCH_CPU_TLB BIT_ULL(CPU_FEATURE_TLB)
|
||||
#define LOONGARCH_CPU_IOCSR BIT_ULL(CPU_FEATURE_IOCSR)
|
||||
#define LOONGARCH_CPU_CSR BIT_ULL(CPU_FEATURE_CSR)
|
||||
#define LOONGARCH_CPU_WATCH BIT_ULL(CPU_FEATURE_WATCH)
|
||||
#define LOONGARCH_CPU_VINT BIT_ULL(CPU_FEATURE_VINT)
|
||||
@ -128,6 +131,7 @@ enum cpu_type_enum {
|
||||
#define LOONGARCH_CPU_GUESTID BIT_ULL(CPU_FEATURE_GUESTID)
|
||||
#define LOONGARCH_CPU_HYPERVISOR BIT_ULL(CPU_FEATURE_HYPERVISOR)
|
||||
#define LOONGARCH_CPU_PTW BIT_ULL(CPU_FEATURE_PTW)
|
||||
#define LOONGARCH_CPU_LSPW BIT_ULL(CPU_FEATURE_LSPW)
|
||||
#define LOONGARCH_CPU_AVECINT BIT_ULL(CPU_FEATURE_AVECINT)
|
||||
|
||||
#endif /* _ASM_CPU_H */
|
||||
|
@ -62,6 +62,7 @@
|
||||
#define LOONGARCH_CPUCFG1 0x1
|
||||
#define CPUCFG1_ISGR32 BIT(0)
|
||||
#define CPUCFG1_ISGR64 BIT(1)
|
||||
#define CPUCFG1_ISA GENMASK(1, 0)
|
||||
#define CPUCFG1_PAGING BIT(2)
|
||||
#define CPUCFG1_IOCSR BIT(3)
|
||||
#define CPUCFG1_PABITS GENMASK(11, 4)
|
||||
|
@ -49,12 +49,12 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
|
||||
|
||||
/* Normal, classic get_new_mmu_context */
|
||||
static inline void
|
||||
get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
|
||||
get_new_mmu_context(struct mm_struct *mm, unsigned long cpu, bool *need_flush)
|
||||
{
|
||||
u64 asid = asid_cache(cpu);
|
||||
|
||||
if (!((++asid) & cpu_asid_mask(&cpu_data[cpu])))
|
||||
local_flush_tlb_user(); /* start new asid cycle */
|
||||
*need_flush = true; /* start new asid cycle */
|
||||
|
||||
cpu_context(cpu, mm) = asid_cache(cpu) = asid;
|
||||
}
|
||||
@ -74,21 +74,34 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void atomic_update_pgd_asid(unsigned long asid, unsigned long pgdl)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"csrwr %[pgdl_val], %[pgdl_reg] \n\t"
|
||||
"csrwr %[asid_val], %[asid_reg] \n\t"
|
||||
: [asid_val] "+r" (asid), [pgdl_val] "+r" (pgdl)
|
||||
: [asid_reg] "i" (LOONGARCH_CSR_ASID), [pgdl_reg] "i" (LOONGARCH_CSR_PGDL)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
static inline void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
bool need_flush = false;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
/* Check if our ASID is of an older version and thus invalid */
|
||||
if (!asid_valid(next, cpu))
|
||||
get_new_mmu_context(next, cpu);
|
||||
|
||||
write_csr_asid(cpu_asid(cpu, next));
|
||||
get_new_mmu_context(next, cpu, &need_flush);
|
||||
|
||||
if (next != &init_mm)
|
||||
csr_write64((unsigned long)next->pgd, LOONGARCH_CSR_PGDL);
|
||||
atomic_update_pgd_asid(cpu_asid(cpu, next), (unsigned long)next->pgd);
|
||||
else
|
||||
csr_write64((unsigned long)invalid_pg_dir, LOONGARCH_CSR_PGDL);
|
||||
atomic_update_pgd_asid(cpu_asid(cpu, next), (unsigned long)invalid_pg_dir);
|
||||
|
||||
if (need_flush)
|
||||
local_flush_tlb_user(); /* Flush tlb after update ASID */
|
||||
|
||||
/*
|
||||
* Mark current->active_mm as not "active" anymore.
|
||||
@ -135,9 +148,15 @@ drop_mmu_context(struct mm_struct *mm, unsigned int cpu)
|
||||
asid = read_csr_asid() & cpu_asid_mask(¤t_cpu_data);
|
||||
|
||||
if (asid == cpu_asid(cpu, mm)) {
|
||||
bool need_flush = false;
|
||||
|
||||
if (!current->mm || (current->mm == mm)) {
|
||||
get_new_mmu_context(mm, cpu);
|
||||
get_new_mmu_context(mm, cpu, &need_flush);
|
||||
|
||||
write_csr_asid(cpu_asid(cpu, mm));
|
||||
if (need_flush)
|
||||
local_flush_tlb_user(); /* Flush tlb after update ASID */
|
||||
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
@ -68,75 +68,6 @@ PERCPU_OP(and, and, &)
|
||||
PERCPU_OP(or, or, |)
|
||||
#undef PERCPU_OP
|
||||
|
||||
static __always_inline unsigned long __percpu_read(void __percpu *ptr, int size)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
__asm__ __volatile__ ("ldx.b %[ret], $r21, %[ptr] \n"
|
||||
: [ret] "=&r"(ret)
|
||||
: [ptr] "r"(ptr)
|
||||
: "memory");
|
||||
break;
|
||||
case 2:
|
||||
__asm__ __volatile__ ("ldx.h %[ret], $r21, %[ptr] \n"
|
||||
: [ret] "=&r"(ret)
|
||||
: [ptr] "r"(ptr)
|
||||
: "memory");
|
||||
break;
|
||||
case 4:
|
||||
__asm__ __volatile__ ("ldx.w %[ret], $r21, %[ptr] \n"
|
||||
: [ret] "=&r"(ret)
|
||||
: [ptr] "r"(ptr)
|
||||
: "memory");
|
||||
break;
|
||||
case 8:
|
||||
__asm__ __volatile__ ("ldx.d %[ret], $r21, %[ptr] \n"
|
||||
: [ret] "=&r"(ret)
|
||||
: [ptr] "r"(ptr)
|
||||
: "memory");
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
BUILD_BUG();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __always_inline void __percpu_write(void __percpu *ptr, unsigned long val, int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
__asm__ __volatile__("stx.b %[val], $r21, %[ptr] \n"
|
||||
:
|
||||
: [val] "r" (val), [ptr] "r" (ptr)
|
||||
: "memory");
|
||||
break;
|
||||
case 2:
|
||||
__asm__ __volatile__("stx.h %[val], $r21, %[ptr] \n"
|
||||
:
|
||||
: [val] "r" (val), [ptr] "r" (ptr)
|
||||
: "memory");
|
||||
break;
|
||||
case 4:
|
||||
__asm__ __volatile__("stx.w %[val], $r21, %[ptr] \n"
|
||||
:
|
||||
: [val] "r" (val), [ptr] "r" (ptr)
|
||||
: "memory");
|
||||
break;
|
||||
case 8:
|
||||
__asm__ __volatile__("stx.d %[val], $r21, %[ptr] \n"
|
||||
:
|
||||
: [val] "r" (val), [ptr] "r" (ptr)
|
||||
: "memory");
|
||||
break;
|
||||
default:
|
||||
BUILD_BUG();
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline unsigned long __percpu_xchg(void *ptr, unsigned long val, int size)
|
||||
{
|
||||
switch (size) {
|
||||
@ -157,6 +88,33 @@ static __always_inline unsigned long __percpu_xchg(void *ptr, unsigned long val,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define __pcpu_op_1(op) op ".b "
|
||||
#define __pcpu_op_2(op) op ".h "
|
||||
#define __pcpu_op_4(op) op ".w "
|
||||
#define __pcpu_op_8(op) op ".d "
|
||||
|
||||
#define _percpu_read(size, _pcp) \
|
||||
({ \
|
||||
typeof(_pcp) __pcp_ret; \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
__pcpu_op_##size("ldx") "%[ret], $r21, %[ptr] \n" \
|
||||
: [ret] "=&r"(__pcp_ret) \
|
||||
: [ptr] "r"(&(_pcp)) \
|
||||
: "memory"); \
|
||||
\
|
||||
__pcp_ret; \
|
||||
})
|
||||
|
||||
#define _percpu_write(size, _pcp, _val) \
|
||||
do { \
|
||||
__asm__ __volatile__( \
|
||||
__pcpu_op_##size("stx") "%[val], $r21, %[ptr] \n" \
|
||||
: \
|
||||
: [val] "r"(_val), [ptr] "r"(&(_pcp)) \
|
||||
: "memory"); \
|
||||
} while (0)
|
||||
|
||||
/* this_cpu_cmpxchg */
|
||||
#define _protect_cmpxchg_local(pcp, o, n) \
|
||||
({ \
|
||||
@ -167,18 +125,6 @@ static __always_inline unsigned long __percpu_xchg(void *ptr, unsigned long val,
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#define _percpu_read(pcp) \
|
||||
({ \
|
||||
typeof(pcp) __retval; \
|
||||
__retval = (typeof(pcp))__percpu_read(&(pcp), sizeof(pcp)); \
|
||||
__retval; \
|
||||
})
|
||||
|
||||
#define _percpu_write(pcp, val) \
|
||||
do { \
|
||||
__percpu_write(&(pcp), (unsigned long)(val), sizeof(pcp)); \
|
||||
} while (0) \
|
||||
|
||||
#define _pcp_protect(operation, pcp, val) \
|
||||
({ \
|
||||
typeof(pcp) __retval; \
|
||||
@ -215,15 +161,15 @@ do { \
|
||||
#define this_cpu_or_4(pcp, val) _percpu_or(pcp, val)
|
||||
#define this_cpu_or_8(pcp, val) _percpu_or(pcp, val)
|
||||
|
||||
#define this_cpu_read_1(pcp) _percpu_read(pcp)
|
||||
#define this_cpu_read_2(pcp) _percpu_read(pcp)
|
||||
#define this_cpu_read_4(pcp) _percpu_read(pcp)
|
||||
#define this_cpu_read_8(pcp) _percpu_read(pcp)
|
||||
#define this_cpu_read_1(pcp) _percpu_read(1, pcp)
|
||||
#define this_cpu_read_2(pcp) _percpu_read(2, pcp)
|
||||
#define this_cpu_read_4(pcp) _percpu_read(4, pcp)
|
||||
#define this_cpu_read_8(pcp) _percpu_read(8, pcp)
|
||||
|
||||
#define this_cpu_write_1(pcp, val) _percpu_write(pcp, val)
|
||||
#define this_cpu_write_2(pcp, val) _percpu_write(pcp, val)
|
||||
#define this_cpu_write_4(pcp, val) _percpu_write(pcp, val)
|
||||
#define this_cpu_write_8(pcp, val) _percpu_write(pcp, val)
|
||||
#define this_cpu_write_1(pcp, val) _percpu_write(1, pcp, val)
|
||||
#define this_cpu_write_2(pcp, val) _percpu_write(2, pcp, val)
|
||||
#define this_cpu_write_4(pcp, val) _percpu_write(4, pcp, val)
|
||||
#define this_cpu_write_8(pcp, val) _percpu_write(8, pcp, val)
|
||||
|
||||
#define this_cpu_xchg_1(pcp, val) _percpu_xchg(pcp, val)
|
||||
#define this_cpu_xchg_2(pcp, val) _percpu_xchg(pcp, val)
|
||||
|
@ -331,29 +331,23 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
|
||||
* Make sure the buddy is global too (if it's !none,
|
||||
* it better already be global)
|
||||
*/
|
||||
if (pte_none(ptep_get(buddy))) {
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* For SMP, multiple CPUs can race, so we need to do
|
||||
* this atomically.
|
||||
*/
|
||||
unsigned long page_global = _PAGE_GLOBAL;
|
||||
unsigned long tmp;
|
||||
/*
|
||||
* For SMP, multiple CPUs can race, so we need
|
||||
* to do this atomically.
|
||||
*/
|
||||
__asm__ __volatile__(
|
||||
__AMOR "$zero, %[global], %[buddy] \n"
|
||||
: [buddy] "+ZB" (buddy->pte)
|
||||
: [global] "r" (_PAGE_GLOBAL)
|
||||
: "memory");
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"1:" __LL "%[tmp], %[buddy] \n"
|
||||
" bnez %[tmp], 2f \n"
|
||||
" or %[tmp], %[tmp], %[global] \n"
|
||||
__SC "%[tmp], %[buddy] \n"
|
||||
" beqz %[tmp], 1b \n"
|
||||
" nop \n"
|
||||
"2: \n"
|
||||
__WEAK_LLSC_MB
|
||||
: [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp)
|
||||
: [global] "r" (page_global));
|
||||
DBAR(0b11000); /* o_wrw = 0b11000 */
|
||||
#else /* !CONFIG_SMP */
|
||||
if (pte_none(ptep_get(buddy)))
|
||||
WRITE_ONCE(*buddy, __pte(pte_val(ptep_get(buddy)) | _PAGE_GLOBAL));
|
||||
#endif /* CONFIG_SMP */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
21
arch/loongarch/include/asm/set_memory.h
Normal file
21
arch/loongarch/include/asm/set_memory.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2024 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef _ASM_LOONGARCH_SET_MEMORY_H
|
||||
#define _ASM_LOONGARCH_SET_MEMORY_H
|
||||
|
||||
/*
|
||||
* Functions to change memory attributes.
|
||||
*/
|
||||
int set_memory_x(unsigned long addr, int numpages);
|
||||
int set_memory_nx(unsigned long addr, int numpages);
|
||||
int set_memory_ro(unsigned long addr, int numpages);
|
||||
int set_memory_rw(unsigned long addr, int numpages);
|
||||
|
||||
bool kernel_page_present(struct page *page);
|
||||
int set_direct_map_default_noflush(struct page *page);
|
||||
int set_direct_map_invalid_noflush(struct page *page);
|
||||
|
||||
#endif /* _ASM_LOONGARCH_SET_MEMORY_H */
|
@ -17,5 +17,6 @@
|
||||
#define HWCAP_LOONGARCH_LBT_ARM (1 << 11)
|
||||
#define HWCAP_LOONGARCH_LBT_MIPS (1 << 12)
|
||||
#define HWCAP_LOONGARCH_PTW (1 << 13)
|
||||
#define HWCAP_LOONGARCH_LSPW (1 << 14)
|
||||
|
||||
#endif /* _UAPI_ASM_HWCAP_H */
|
||||
|
@ -9,7 +9,6 @@
|
||||
#define _UAPI_ASM_SIGCONTEXT_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/posix_types.h>
|
||||
|
||||
/* FP context was used */
|
||||
#define SC_USED_FP (1 << 0)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user