Merge branch 'for-linus' into for-next
Merged upstream branch to make further fireworks development easier (and avoid conflicts earlier). Conflicts: sound/firewire/bebob/bebob_focusrite.c
This commit is contained in:
Коммит
85c24cd8d3
|
@ -17,7 +17,7 @@ User addresses have bits 63:48 set to 0 while the kernel addresses have
|
|||
the same bits set to 1. TTBRx selection is given by bit 63 of the
|
||||
virtual address. The swapper_pg_dir contains only kernel (global)
|
||||
mappings while the user pgd contains only user (non-global) mappings.
|
||||
The swapper_pgd_dir address is written to TTBR1 and never written to
|
||||
The swapper_pg_dir address is written to TTBR1 and never written to
|
||||
TTBR0.
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
* Generic Mailbox Controller and client driver bindings
|
||||
|
||||
Generic binding to provide a way for Mailbox controller drivers to
|
||||
assign appropriate mailbox channel to client drivers.
|
||||
|
||||
* Mailbox Controller
|
||||
|
||||
Required property:
|
||||
- #mbox-cells: Must be at least 1. Number of cells in a mailbox
|
||||
specifier.
|
||||
|
||||
Example:
|
||||
mailbox: mailbox {
|
||||
...
|
||||
#mbox-cells = <1>;
|
||||
};
|
||||
|
||||
|
||||
* Mailbox Client
|
||||
|
||||
Required property:
|
||||
- mboxes: List of phandle and mailbox channel specifiers.
|
||||
|
||||
Optional property:
|
||||
- mbox-names: List of identifier strings for each mailbox channel
|
||||
required by the client. The use of this property
|
||||
is discouraged in favor of using index in list of
|
||||
'mboxes' while requesting a mailbox. Instead the
|
||||
platforms may define channel indices, in DT headers,
|
||||
to something legible.
|
||||
|
||||
Example:
|
||||
pwr_cntrl: power {
|
||||
...
|
||||
mbox-names = "pwr-ctrl", "rpc";
|
||||
mboxes = <&mailbox 0
|
||||
&mailbox 1>;
|
||||
};
|
|
@ -1,5 +1,20 @@
|
|||
Freescale FlexTimer Module (FTM) PWM controller
|
||||
|
||||
The same FTM PWM device can have a different endianness on different SoCs. The
|
||||
device tree provides a property to describing this so that an operating system
|
||||
device driver can handle all variants of the device. Refer to the table below
|
||||
for the endianness of the FTM PWM block as integrated into the existing SoCs:
|
||||
|
||||
SoC | FTM-PWM endianness
|
||||
--------+-------------------
|
||||
Vybrid | LE
|
||||
LS1 | BE
|
||||
LS2 | LE
|
||||
|
||||
Please see ../regmap/regmap.txt for more detail about how to specify endian
|
||||
modes in device tree.
|
||||
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "fsl,vf610-ftm-pwm".
|
||||
- reg: Physical base address and length of the controller's registers
|
||||
|
@ -16,7 +31,8 @@ Required properties:
|
|||
- pinctrl-names: Must contain a "default" entry.
|
||||
- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
|
||||
See pinctrl/pinctrl-bindings.txt for details of the property values.
|
||||
|
||||
- big-endian: Boolean property, required if the FTM PWM registers use a big-
|
||||
endian rather than little-endian layout.
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -32,4 +48,5 @@ pwm0: pwm@40038000 {
|
|||
<&clks VF610_CLK_FTM0_EXT_FIX_EN>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_pwm0_1>;
|
||||
big-endian;
|
||||
};
|
||||
|
|
|
@ -7,8 +7,8 @@ Required properties:
|
|||
"rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
|
||||
- reg: physical base address and length of the controller's registers
|
||||
- clocks: phandle and clock specifier of the PWM reference clock
|
||||
- #pwm-cells: should be 2. See pwm.txt in this directory for a
|
||||
description of the cell format.
|
||||
- #pwm-cells: must be 2 (rk2928) or 3 (rk3288). See pwm.txt in this directory
|
||||
for a description of the cell format.
|
||||
|
||||
Example:
|
||||
|
||||
|
|
|
@ -7,10 +7,20 @@ Required properties:
|
|||
|
||||
- clocks : the clock provider of SYS_MCLK
|
||||
|
||||
- VDDA-supply : the regulator provider of VDDA
|
||||
|
||||
- VDDIO-supply: the regulator provider of VDDIO
|
||||
|
||||
Optional properties:
|
||||
|
||||
- VDDD-supply : the regulator provider of VDDD
|
||||
|
||||
Example:
|
||||
|
||||
codec: sgtl5000@0a {
|
||||
compatible = "fsl,sgtl5000";
|
||||
reg = <0x0a>;
|
||||
clocks = <&clks 150>;
|
||||
VDDA-supply = <®_3p3v>;
|
||||
VDDIO-supply = <®_3p3v>;
|
||||
};
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
* Temperature Monitor (TEMPMON) on Freescale i.MX SoCs
|
||||
|
||||
Required properties:
|
||||
- compatible : "fsl,imx6q-thermal"
|
||||
- compatible : "fsl,imx6q-tempmon" for i.MX6Q, "fsl,imx6sx-tempmon" for i.MX6SX.
|
||||
i.MX6SX has two more IRQs than i.MX6Q, one is IRQ_LOW and the other is IRQ_PANIC,
|
||||
when temperature is below than low threshold, IRQ_LOW will be triggered, when temperature
|
||||
is higher than panic threshold, system will auto reboot by SRC module.
|
||||
- fsl,tempmon : phandle pointer to system controller that contains TEMPMON
|
||||
control registers, e.g. ANATOP on imx6q.
|
||||
- fsl,tempmon-data : phandle pointer to fuse controller that contains TEMPMON
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
Zynq Watchdog Device Tree Bindings
|
||||
-------------------------------------------
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "cdns,wdt-r1p2".
|
||||
- clocks : This is pclk (APB clock).
|
||||
- interrupts : This is wd_irq - watchdog timeout interrupt.
|
||||
- interrupt-parent : Must be core interrupt controller.
|
||||
|
||||
Optional properties
|
||||
- reset-on-timeout : If this property exists, then a reset is done
|
||||
when watchdog times out.
|
||||
- timeout-sec : Watchdog timeout value (in seconds).
|
||||
|
||||
Example:
|
||||
watchdog@f8005000 {
|
||||
compatible = "cdns,wdt-r1p2";
|
||||
clocks = <&clkc 45>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 9 1>;
|
||||
reg = <0xf8005000 0x1000>;
|
||||
reset-on-timeout;
|
||||
timeout-sec = <10>;
|
||||
};
|
|
@ -7,7 +7,8 @@ Required properties:
|
|||
|
||||
Optional property:
|
||||
- big-endian: If present the watchdog device's registers are implemented
|
||||
in big endian mode, otherwise in little mode.
|
||||
in big endian mode, otherwise in native mode(same with CPU), for more
|
||||
detail please see: Documentation/devicetree/bindings/regmap/regmap.txt.
|
||||
|
||||
Examples:
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
Meson SoCs Watchdog timer
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be "amlogic,meson6-wdt"
|
||||
- reg : Specifies base physical address and size of the registers.
|
||||
|
||||
Example:
|
||||
|
||||
wdt: watchdog@c1109900 {
|
||||
compatible = "amlogic,meson6-wdt";
|
||||
reg = <0xc1109900 0x8>;
|
||||
};
|
|
@ -0,0 +1,24 @@
|
|||
Qualcomm Krait Processor Sub-system (KPSS) Watchdog
|
||||
---------------------------------------------------
|
||||
|
||||
Required properties :
|
||||
- compatible : shall contain only one of the following:
|
||||
|
||||
"qcom,kpss-wdt-msm8960"
|
||||
"qcom,kpss-wdt-apq8064"
|
||||
"qcom,kpss-wdt-ipq8064"
|
||||
|
||||
- reg : shall contain base register location and length
|
||||
- clocks : shall contain the input clock
|
||||
|
||||
Optional properties :
|
||||
- timeout-sec : shall contain the default watchdog timeout in seconds,
|
||||
if unset, the default timeout is 30 seconds
|
||||
|
||||
Example:
|
||||
watchdog@208a038 {
|
||||
compatible = "qcom,kpss-wdt-ipq8064";
|
||||
reg = <0x0208a038 0x40>;
|
||||
clocks = <&sleep_clk>;
|
||||
timeout-sec = <10>;
|
||||
};
|
|
@ -9,6 +9,7 @@ Required properties:
|
|||
(a) "samsung,s3c2410-wdt" for Exynos4 and previous SoCs
|
||||
(b) "samsung,exynos5250-wdt" for Exynos5250
|
||||
(c) "samsung,exynos5420-wdt" for Exynos5420
|
||||
(c) "samsung,exynos7-wdt" for Exynos7
|
||||
|
||||
- reg : base physical address of the controller and length of memory mapped
|
||||
region.
|
||||
|
|
|
@ -67,6 +67,7 @@ prototypes:
|
|||
struct file *, unsigned open_flag,
|
||||
umode_t create_mode, int *opened);
|
||||
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
|
||||
int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
|
||||
|
||||
locking rules:
|
||||
all may block
|
||||
|
@ -96,6 +97,7 @@ fiemap: no
|
|||
update_time: no
|
||||
atomic_open: yes
|
||||
tmpfile: no
|
||||
dentry_open: no
|
||||
|
||||
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
|
||||
victim.
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
Written by: Neil Brown <neilb@suse.de>
|
||||
|
||||
Overlay Filesystem
|
||||
==================
|
||||
|
||||
This document describes a prototype for a new approach to providing
|
||||
overlay-filesystem functionality in Linux (sometimes referred to as
|
||||
union-filesystems). An overlay-filesystem tries to present a
|
||||
filesystem which is the result over overlaying one filesystem on top
|
||||
of the other.
|
||||
|
||||
The result will inevitably fail to look exactly like a normal
|
||||
filesystem for various technical reasons. The expectation is that
|
||||
many use cases will be able to ignore these differences.
|
||||
|
||||
This approach is 'hybrid' because the objects that appear in the
|
||||
filesystem do not all appear to belong to that filesystem. In many
|
||||
cases an object accessed in the union will be indistinguishable
|
||||
from accessing the corresponding object from the original filesystem.
|
||||
This is most obvious from the 'st_dev' field returned by stat(2).
|
||||
|
||||
While directories will report an st_dev from the overlay-filesystem,
|
||||
all non-directory objects will report an st_dev from the lower or
|
||||
upper filesystem that is providing the object. Similarly st_ino will
|
||||
only be unique when combined with st_dev, and both of these can change
|
||||
over the lifetime of a non-directory object. Many applications and
|
||||
tools ignore these values and will not be affected.
|
||||
|
||||
Upper and Lower
|
||||
---------------
|
||||
|
||||
An overlay filesystem combines two filesystems - an 'upper' filesystem
|
||||
and a 'lower' filesystem. When a name exists in both filesystems, the
|
||||
object in the 'upper' filesystem is visible while the object in the
|
||||
'lower' filesystem is either hidden or, in the case of directories,
|
||||
merged with the 'upper' object.
|
||||
|
||||
It would be more correct to refer to an upper and lower 'directory
|
||||
tree' rather than 'filesystem' as it is quite possible for both
|
||||
directory trees to be in the same filesystem and there is no
|
||||
requirement that the root of a filesystem be given for either upper or
|
||||
lower.
|
||||
|
||||
The lower filesystem can be any filesystem supported by Linux and does
|
||||
not need to be writable. The lower filesystem can even be another
|
||||
overlayfs. The upper filesystem will normally be writable and if it
|
||||
is it must support the creation of trusted.* extended attributes, and
|
||||
must provide valid d_type in readdir responses, so NFS is not suitable.
|
||||
|
||||
A read-only overlay of two read-only filesystems may use any
|
||||
filesystem type.
|
||||
|
||||
Directories
|
||||
-----------
|
||||
|
||||
Overlaying mainly involves directories. If a given name appears in both
|
||||
upper and lower filesystems and refers to a non-directory in either,
|
||||
then the lower object is hidden - the name refers only to the upper
|
||||
object.
|
||||
|
||||
Where both upper and lower objects are directories, a merged directory
|
||||
is formed.
|
||||
|
||||
At mount time, the two directories given as mount options "lowerdir" and
|
||||
"upperdir" are combined into a merged directory:
|
||||
|
||||
mount -t overlayfs overlayfs -olowerdir=/lower,upperdir=/upper,\
|
||||
workdir=/work /merged
|
||||
|
||||
The "workdir" needs to be an empty directory on the same filesystem
|
||||
as upperdir.
|
||||
|
||||
Then whenever a lookup is requested in such a merged directory, the
|
||||
lookup is performed in each actual directory and the combined result
|
||||
is cached in the dentry belonging to the overlay filesystem. If both
|
||||
actual lookups find directories, both are stored and a merged
|
||||
directory is created, otherwise only one is stored: the upper if it
|
||||
exists, else the lower.
|
||||
|
||||
Only the lists of names from directories are merged. Other content
|
||||
such as metadata and extended attributes are reported for the upper
|
||||
directory only. These attributes of the lower directory are hidden.
|
||||
|
||||
whiteouts and opaque directories
|
||||
--------------------------------
|
||||
|
||||
In order to support rm and rmdir without changing the lower
|
||||
filesystem, an overlay filesystem needs to record in the upper filesystem
|
||||
that files have been removed. This is done using whiteouts and opaque
|
||||
directories (non-directories are always opaque).
|
||||
|
||||
A whiteout is created as a character device with 0/0 device number.
|
||||
When a whiteout is found in the upper level of a merged directory, any
|
||||
matching name in the lower level is ignored, and the whiteout itself
|
||||
is also hidden.
|
||||
|
||||
A directory is made opaque by setting the xattr "trusted.overlay.opaque"
|
||||
to "y". Where the upper filesystem contains an opaque directory, any
|
||||
directory in the lower filesystem with the same name is ignored.
|
||||
|
||||
readdir
|
||||
-------
|
||||
|
||||
When a 'readdir' request is made on a merged directory, the upper and
|
||||
lower directories are each read and the name lists merged in the
|
||||
obvious way (upper is read first, then lower - entries that already
|
||||
exist are not re-added). This merged name list is cached in the
|
||||
'struct file' and so remains as long as the file is kept open. If the
|
||||
directory is opened and read by two processes at the same time, they
|
||||
will each have separate caches. A seekdir to the start of the
|
||||
directory (offset 0) followed by a readdir will cause the cache to be
|
||||
discarded and rebuilt.
|
||||
|
||||
This means that changes to the merged directory do not appear while a
|
||||
directory is being read. This is unlikely to be noticed by many
|
||||
programs.
|
||||
|
||||
seek offsets are assigned sequentially when the directories are read.
|
||||
Thus if
|
||||
- read part of a directory
|
||||
- remember an offset, and close the directory
|
||||
- re-open the directory some time later
|
||||
- seek to the remembered offset
|
||||
|
||||
there may be little correlation between the old and new locations in
|
||||
the list of filenames, particularly if anything has changed in the
|
||||
directory.
|
||||
|
||||
Readdir on directories that are not merged is simply handled by the
|
||||
underlying directory (upper or lower).
|
||||
|
||||
|
||||
Non-directories
|
||||
---------------
|
||||
|
||||
Objects that are not directories (files, symlinks, device-special
|
||||
files etc.) are presented either from the upper or lower filesystem as
|
||||
appropriate. When a file in the lower filesystem is accessed in a way
|
||||
the requires write-access, such as opening for write access, changing
|
||||
some metadata etc., the file is first copied from the lower filesystem
|
||||
to the upper filesystem (copy_up). Note that creating a hard-link
|
||||
also requires copy_up, though of course creation of a symlink does
|
||||
not.
|
||||
|
||||
The copy_up may turn out to be unnecessary, for example if the file is
|
||||
opened for read-write but the data is not modified.
|
||||
|
||||
The copy_up process first makes sure that the containing directory
|
||||
exists in the upper filesystem - creating it and any parents as
|
||||
necessary. It then creates the object with the same metadata (owner,
|
||||
mode, mtime, symlink-target etc.) and then if the object is a file, the
|
||||
data is copied from the lower to the upper filesystem. Finally any
|
||||
extended attributes are copied up.
|
||||
|
||||
Once the copy_up is complete, the overlay filesystem simply
|
||||
provides direct access to the newly created file in the upper
|
||||
filesystem - future operations on the file are barely noticed by the
|
||||
overlay filesystem (though an operation on the name of the file such as
|
||||
rename or unlink will of course be noticed and handled).
|
||||
|
||||
|
||||
Non-standard behavior
|
||||
---------------------
|
||||
|
||||
The copy_up operation essentially creates a new, identical file and
|
||||
moves it over to the old name. The new file may be on a different
|
||||
filesystem, so both st_dev and st_ino of the file may change.
|
||||
|
||||
Any open files referring to this inode will access the old data and
|
||||
metadata. Similarly any file locks obtained before copy_up will not
|
||||
apply to the copied up file.
|
||||
|
||||
On a file opened with O_RDONLY fchmod(2), fchown(2), futimesat(2) and
|
||||
fsetxattr(2) will fail with EROFS.
|
||||
|
||||
If a file with multiple hard links is copied up, then this will
|
||||
"break" the link. Changes will not be propagated to other names
|
||||
referring to the same inode.
|
||||
|
||||
Symlinks in /proc/PID/ and /proc/PID/fd which point to a non-directory
|
||||
object in overlayfs will not contain valid absolute paths, only
|
||||
relative paths leading up to the filesystem's root. This will be
|
||||
fixed in the future.
|
||||
|
||||
Some operations are not atomic, for example a crash during copy_up or
|
||||
rename will leave the filesystem in an inconsistent state. This will
|
||||
be addressed in the future.
|
||||
|
||||
Changes to underlying filesystems
|
||||
---------------------------------
|
||||
|
||||
Offline changes, when the overlay is not mounted, are allowed to either
|
||||
the upper or the lower trees.
|
||||
|
||||
Changes to the underlying filesystems while part of a mounted overlay
|
||||
filesystem are not allowed. If the underlying filesystem is changed,
|
||||
the behavior of the overlay is undefined, though it will not result in
|
||||
a crash or deadlock.
|
|
@ -364,6 +364,7 @@ struct inode_operations {
|
|||
int (*atomic_open)(struct inode *, struct dentry *, struct file *,
|
||||
unsigned open_flag, umode_t create_mode, int *opened);
|
||||
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
|
||||
int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
|
||||
};
|
||||
|
||||
Again, all methods are called without any locks being held, unless
|
||||
|
@ -696,6 +697,12 @@ struct address_space_operations {
|
|||
but instead uses bmap to find out where the blocks in the file
|
||||
are and uses those addresses directly.
|
||||
|
||||
dentry_open: *WARNING: probably going away soon, do not use!* This is an
|
||||
alternative to f_op->open(), the difference is that this method may open
|
||||
a file not necessarily originating from the same filesystem as the one
|
||||
i_op->open() was called on. It may be useful for stacking filesystems
|
||||
which want to allow native I/O directly on underlying files.
|
||||
|
||||
|
||||
invalidatepage: If a page has PagePrivate set, then invalidatepage
|
||||
will be called when part or all of the page is to be removed
|
||||
|
|
|
@ -1015,10 +1015,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
Format: {"off" | "on" | "skip[mbr]"}
|
||||
|
||||
efi= [EFI]
|
||||
Format: { "old_map" }
|
||||
Format: { "old_map", "nochunk", "noruntime" }
|
||||
old_map [X86-64]: switch to the old ioremap-based EFI
|
||||
runtime services mapping. 32-bit still uses this one by
|
||||
default.
|
||||
nochunk: disable reading files in "chunks" in the EFI
|
||||
boot stub, as chunking can cause problems with some
|
||||
firmware implementations.
|
||||
noruntime : disable EFI runtime services support
|
||||
|
||||
efi_no_storage_paranoia [EFI; X86]
|
||||
Using this parameter you can use more than 50% of
|
||||
|
@ -2232,7 +2236,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
|
||||
nodsp [SH] Disable hardware DSP at boot time.
|
||||
|
||||
noefi [X86] Disable EFI runtime services support.
|
||||
noefi Disable EFI runtime services support.
|
||||
|
||||
noexec [IA-64]
|
||||
|
||||
|
@ -3465,6 +3469,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
e.g. base its process migration decisions on it.
|
||||
Default is on.
|
||||
|
||||
topology_updates= [KNL, PPC, NUMA]
|
||||
Format: {off}
|
||||
Specify if the kernel should ignore (off)
|
||||
topology updates sent by the hypervisor to this
|
||||
LPAR.
|
||||
|
||||
tp720= [HW,PS2]
|
||||
|
||||
tpm_suspend_pcr=[HW,TPM]
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
The Common Mailbox Framework
|
||||
Jassi Brar <jaswinder.singh@linaro.org>
|
||||
|
||||
This document aims to help developers write client and controller
|
||||
drivers for the API. But before we start, let us note that the
|
||||
client (especially) and controller drivers are likely going to be
|
||||
very platform specific because the remote firmware is likely to be
|
||||
proprietary and implement non-standard protocol. So even if two
|
||||
platforms employ, say, PL320 controller, the client drivers can't
|
||||
be shared across them. Even the PL320 driver might need to accommodate
|
||||
some platform specific quirks. So the API is meant mainly to avoid
|
||||
similar copies of code written for each platform. Having said that,
|
||||
nothing prevents the remote f/w to also be Linux based and use the
|
||||
same api there. However none of that helps us locally because we only
|
||||
ever deal at client's protocol level.
|
||||
Some of the choices made during implementation are the result of this
|
||||
peculiarity of this "common" framework.
|
||||
|
||||
|
||||
|
||||
Part 1 - Controller Driver (See include/linux/mailbox_controller.h)
|
||||
|
||||
Allocate mbox_controller and the array of mbox_chan.
|
||||
Populate mbox_chan_ops, except peek_data() all are mandatory.
|
||||
The controller driver might know a message has been consumed
|
||||
by the remote by getting an IRQ or polling some hardware flag
|
||||
or it can never know (the client knows by way of the protocol).
|
||||
The method in order of preference is IRQ -> Poll -> None, which
|
||||
the controller driver should set via 'txdone_irq' or 'txdone_poll'
|
||||
or neither.
|
||||
|
||||
|
||||
Part 2 - Client Driver (See include/linux/mailbox_client.h)
|
||||
|
||||
The client might want to operate in blocking mode (synchronously
|
||||
send a message through before returning) or non-blocking/async mode (submit
|
||||
a message and a callback function to the API and return immediately).
|
||||
|
||||
|
||||
struct demo_client {
|
||||
struct mbox_client cl;
|
||||
struct mbox_chan *mbox;
|
||||
struct completion c;
|
||||
bool async;
|
||||
/* ... */
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the handler for data received from remote. The behaviour is purely
|
||||
* dependent upon the protocol. This is just an example.
|
||||
*/
|
||||
static void message_from_remote(struct mbox_client *cl, void *mssg)
|
||||
{
|
||||
struct demo_client *dc = container_of(mbox_client,
|
||||
struct demo_client, cl);
|
||||
if (dc->aysnc) {
|
||||
if (is_an_ack(mssg)) {
|
||||
/* An ACK to our last sample sent */
|
||||
return; /* Or do something else here */
|
||||
} else { /* A new message from remote */
|
||||
queue_req(mssg);
|
||||
}
|
||||
} else {
|
||||
/* Remote f/w sends only ACK packets on this channel */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void sample_sent(struct mbox_client *cl, void *mssg, int r)
|
||||
{
|
||||
struct demo_client *dc = container_of(mbox_client,
|
||||
struct demo_client, cl);
|
||||
complete(&dc->c);
|
||||
}
|
||||
|
||||
static void client_demo(struct platform_device *pdev)
|
||||
{
|
||||
struct demo_client *dc_sync, *dc_async;
|
||||
/* The controller already knows async_pkt and sync_pkt */
|
||||
struct async_pkt ap;
|
||||
struct sync_pkt sp;
|
||||
|
||||
dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL);
|
||||
dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL);
|
||||
|
||||
/* Populate non-blocking mode client */
|
||||
dc_async->cl.dev = &pdev->dev;
|
||||
dc_async->cl.rx_callback = message_from_remote;
|
||||
dc_async->cl.tx_done = sample_sent;
|
||||
dc_async->cl.tx_block = false;
|
||||
dc_async->cl.tx_tout = 0; /* doesn't matter here */
|
||||
dc_async->cl.knows_txdone = false; /* depending upon protocol */
|
||||
dc_async->async = true;
|
||||
init_completion(&dc_async->c);
|
||||
|
||||
/* Populate blocking mode client */
|
||||
dc_sync->cl.dev = &pdev->dev;
|
||||
dc_sync->cl.rx_callback = message_from_remote;
|
||||
dc_sync->cl.tx_done = NULL; /* operate in blocking mode */
|
||||
dc_sync->cl.tx_block = true;
|
||||
dc_sync->cl.tx_tout = 500; /* by half a second */
|
||||
dc_sync->cl.knows_txdone = false; /* depending upon protocol */
|
||||
dc_sync->async = false;
|
||||
|
||||
/* ASync mailbox is listed second in 'mboxes' property */
|
||||
dc_async->mbox = mbox_request_channel(&dc_async->cl, 1);
|
||||
/* Populate data packet */
|
||||
/* ap.xxx = 123; etc */
|
||||
/* Send async message to remote */
|
||||
mbox_send_message(dc_async->mbox, &ap);
|
||||
|
||||
/* Sync mailbox is listed first in 'mboxes' property */
|
||||
dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0);
|
||||
/* Populate data packet */
|
||||
/* sp.abc = 123; etc */
|
||||
/* Send message to remote in blocking mode */
|
||||
mbox_send_message(dc_sync->mbox, &sp);
|
||||
/* At this point 'sp' has been sent */
|
||||
|
||||
/* Now wait for async chan to be done */
|
||||
wait_for_completion(&dc_async->c);
|
||||
}
|
|
@ -5,7 +5,8 @@ performance expectations by drivers, subsystems and user space applications on
|
|||
one of the parameters.
|
||||
|
||||
Two different PM QoS frameworks are available:
|
||||
1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput.
|
||||
1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput,
|
||||
memory_bandwidth.
|
||||
2. the per-device PM QoS framework provides the API to manage the per-device latency
|
||||
constraints and PM QoS flags.
|
||||
|
||||
|
@ -13,6 +14,7 @@ Each parameters have defined units:
|
|||
* latency: usec
|
||||
* timeout: usec
|
||||
* throughput: kbs (kilo bit / sec)
|
||||
* memory bandwidth: mbs (mega bit / sec)
|
||||
|
||||
|
||||
1. PM QoS framework
|
||||
|
|
|
@ -184,8 +184,7 @@ Any problems, questions, bug reports, lonely OSD nights, please email:
|
|||
More up-to-date information can be found on:
|
||||
http://open-osd.org
|
||||
|
||||
Boaz Harrosh <bharrosh@panasas.com>
|
||||
Benny Halevy <bhalevy@panasas.com>
|
||||
Boaz Harrosh <ooo@electrozaur.com>
|
||||
|
||||
References
|
||||
==========
|
||||
|
|
|
@ -0,0 +1,378 @@
|
|||
Contents:
|
||||
|
||||
1) TCM Userspace Design
|
||||
a) Background
|
||||
b) Benefits
|
||||
c) Design constraints
|
||||
d) Implementation overview
|
||||
i. Mailbox
|
||||
ii. Command ring
|
||||
iii. Data Area
|
||||
e) Device discovery
|
||||
f) Device events
|
||||
g) Other contingencies
|
||||
2) Writing a user pass-through handler
|
||||
a) Discovering and configuring TCMU uio devices
|
||||
b) Waiting for events on the device(s)
|
||||
c) Managing the command ring
|
||||
3) Command filtering and pass_level
|
||||
4) A final note
|
||||
|
||||
|
||||
TCM Userspace Design
|
||||
--------------------
|
||||
|
||||
TCM is another name for LIO, an in-kernel iSCSI target (server).
|
||||
Existing TCM targets run in the kernel. TCMU (TCM in Userspace)
|
||||
allows userspace programs to be written which act as iSCSI targets.
|
||||
This document describes the design.
|
||||
|
||||
The existing kernel provides modules for different SCSI transport
|
||||
protocols. TCM also modularizes the data storage. There are existing
|
||||
modules for file, block device, RAM or using another SCSI device as
|
||||
storage. These are called "backstores" or "storage engines". These
|
||||
built-in modules are implemented entirely as kernel code.
|
||||
|
||||
Background:
|
||||
|
||||
In addition to modularizing the transport protocol used for carrying
|
||||
SCSI commands ("fabrics"), the Linux kernel target, LIO, also modularizes
|
||||
the actual data storage as well. These are referred to as "backstores"
|
||||
or "storage engines". The target comes with backstores that allow a
|
||||
file, a block device, RAM, or another SCSI device to be used for the
|
||||
local storage needed for the exported SCSI LUN. Like the rest of LIO,
|
||||
these are implemented entirely as kernel code.
|
||||
|
||||
These backstores cover the most common use cases, but not all. One new
|
||||
use case that other non-kernel target solutions, such as tgt, are able
|
||||
to support is using Gluster's GLFS or Ceph's RBD as a backstore. The
|
||||
target then serves as a translator, allowing initiators to store data
|
||||
in these non-traditional networked storage systems, while still only
|
||||
using standard protocols themselves.
|
||||
|
||||
If the target is a userspace process, supporting these is easy. tgt,
|
||||
for example, needs only a small adapter module for each, because the
|
||||
modules just use the available userspace libraries for RBD and GLFS.
|
||||
|
||||
Adding support for these backstores in LIO is considerably more
|
||||
difficult, because LIO is entirely kernel code. Instead of undertaking
|
||||
the significant work to port the GLFS or RBD APIs and protocols to the
|
||||
kernel, another approach is to create a userspace pass-through
|
||||
backstore for LIO, "TCMU".
|
||||
|
||||
|
||||
Benefits:
|
||||
|
||||
In addition to allowing relatively easy support for RBD and GLFS, TCMU
|
||||
will also allow easier development of new backstores. TCMU combines
|
||||
with the LIO loopback fabric to become something similar to FUSE
|
||||
(Filesystem in Userspace), but at the SCSI layer instead of the
|
||||
filesystem layer. A SUSE, if you will.
|
||||
|
||||
The disadvantage is there are more distinct components to configure, and
|
||||
potentially to malfunction. This is unavoidable, but hopefully not
|
||||
fatal if we're careful to keep things as simple as possible.
|
||||
|
||||
Design constraints:
|
||||
|
||||
- Good performance: high throughput, low latency
|
||||
- Cleanly handle if userspace:
|
||||
1) never attaches
|
||||
2) hangs
|
||||
3) dies
|
||||
4) misbehaves
|
||||
- Allow future flexibility in user & kernel implementations
|
||||
- Be reasonably memory-efficient
|
||||
- Simple to configure & run
|
||||
- Simple to write a userspace backend
|
||||
|
||||
|
||||
Implementation overview:
|
||||
|
||||
The core of the TCMU interface is a memory region that is shared
|
||||
between kernel and userspace. Within this region is: a control area
|
||||
(mailbox); a lockless producer/consumer circular buffer for commands
|
||||
to be passed up, and status returned; and an in/out data buffer area.
|
||||
|
||||
TCMU uses the pre-existing UIO subsystem. UIO allows device driver
|
||||
development in userspace, and this is conceptually very close to the
|
||||
TCMU use case, except instead of a physical device, TCMU implements a
|
||||
memory-mapped layout designed for SCSI commands. Using UIO also
|
||||
benefits TCMU by handling device introspection (e.g. a way for
|
||||
userspace to determine how large the shared region is) and signaling
|
||||
mechanisms in both directions.
|
||||
|
||||
There are no embedded pointers in the memory region. Everything is
|
||||
expressed as an offset from the region's starting address. This allows
|
||||
the ring to still work if the user process dies and is restarted with
|
||||
the region mapped at a different virtual address.
|
||||
|
||||
See target_core_user.h for the struct definitions.
|
||||
|
||||
The Mailbox:
|
||||
|
||||
The mailbox is always at the start of the shared memory region, and
|
||||
contains a version, details about the starting offset and size of the
|
||||
command ring, and head and tail pointers to be used by the kernel and
|
||||
userspace (respectively) to put commands on the ring, and indicate
|
||||
when the commands are completed.
|
||||
|
||||
version - 1 (userspace should abort if otherwise)
|
||||
flags - none yet defined.
|
||||
cmdr_off - The offset of the start of the command ring from the start
|
||||
of the memory region, to account for the mailbox size.
|
||||
cmdr_size - The size of the command ring. This does *not* need to be a
|
||||
power of two.
|
||||
cmd_head - Modified by the kernel to indicate when a command has been
|
||||
placed on the ring.
|
||||
cmd_tail - Modified by userspace to indicate when it has completed
|
||||
processing of a command.
|
||||
|
||||
The Command Ring:
|
||||
|
||||
Commands are placed on the ring by the kernel incrementing
|
||||
mailbox.cmd_head by the size of the command, modulo cmdr_size, and
|
||||
then signaling userspace via uio_event_notify(). Once the command is
|
||||
completed, userspace updates mailbox.cmd_tail in the same way and
|
||||
signals the kernel via a 4-byte write(). When cmd_head equals
|
||||
cmd_tail, the ring is empty -- no commands are currently waiting to be
|
||||
processed by userspace.
|
||||
|
||||
TCMU commands start with a common header containing "len_op", a 32-bit
|
||||
value that stores the length, as well as the opcode in the lowest
|
||||
unused bits. Currently only two opcodes are defined, TCMU_OP_PAD and
|
||||
TCMU_OP_CMD. When userspace encounters a command with PAD opcode, it
|
||||
should skip ahead by the bytes in "length". (The kernel inserts PAD
|
||||
entries to ensure each CMD entry fits contigously into the circular
|
||||
buffer.)
|
||||
|
||||
When userspace handles a CMD, it finds the SCSI CDB (Command Data
|
||||
Block) via tcmu_cmd_entry.req.cdb_off. This is an offset from the
|
||||
start of the overall shared memory region, not the entry. The data
|
||||
in/out buffers are accessible via tht req.iov[] array. Note that
|
||||
each iov.iov_base is also an offset from the start of the region.
|
||||
|
||||
TCMU currently does not support BIDI operations.
|
||||
|
||||
When completing a command, userspace sets rsp.scsi_status, and
|
||||
rsp.sense_buffer if necessary. Userspace then increments
|
||||
mailbox.cmd_tail by entry.hdr.length (mod cmdr_size) and signals the
|
||||
kernel via the UIO method, a 4-byte write to the file descriptor.
|
||||
|
||||
The Data Area:
|
||||
|
||||
This is shared-memory space after the command ring. The organization
|
||||
of this area is not defined in the TCMU interface, and userspace
|
||||
should access only the parts referenced by pending iovs.
|
||||
|
||||
|
||||
Device Discovery:
|
||||
|
||||
Other devices may be using UIO besides TCMU. Unrelated user processes
|
||||
may also be handling different sets of TCMU devices. TCMU userspace
|
||||
processes must find their devices by scanning sysfs
|
||||
class/uio/uio*/name. For TCMU devices, these names will be of the
|
||||
format:
|
||||
|
||||
tcm-user/<hba_num>/<device_name>/<subtype>/<path>
|
||||
|
||||
where "tcm-user" is common for all TCMU-backed UIO devices. <hba_num>
|
||||
and <device_name> allow userspace to find the device's path in the
|
||||
kernel target's configfs tree. Assuming the usual mount point, it is
|
||||
found at:
|
||||
|
||||
/sys/kernel/config/target/core/user_<hba_num>/<device_name>
|
||||
|
||||
This location contains attributes such as "hw_block_size", that
|
||||
userspace needs to know for correct operation.
|
||||
|
||||
<subtype> will be a userspace-process-unique string to identify the
|
||||
TCMU device as expecting to be backed by a certain handler, and <path>
|
||||
will be an additional handler-specific string for the user process to
|
||||
configure the device, if needed. The name cannot contain ':', due to
|
||||
LIO limitations.
|
||||
|
||||
For all devices so discovered, the user handler opens /dev/uioX and
|
||||
calls mmap():
|
||||
|
||||
mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)
|
||||
|
||||
where size must be equal to the value read from
|
||||
/sys/class/uio/uioX/maps/map0/size.
|
||||
|
||||
|
||||
Device Events:
|
||||
|
||||
If a new device is added or removed, a notification will be broadcast
|
||||
over netlink, using a generic netlink family name of "TCM-USER" and a
|
||||
multicast group named "config". This will include the UIO name as
|
||||
described in the previous section, as well as the UIO minor
|
||||
number. This should allow userspace to identify both the UIO device and
|
||||
the LIO device, so that after determining the device is supported
|
||||
(based on subtype) it can take the appropriate action.
|
||||
|
||||
|
||||
Other contingencies:
|
||||
|
||||
Userspace handler process never attaches:
|
||||
|
||||
- TCMU will post commands, and then abort them after a timeout period
|
||||
(30 seconds.)
|
||||
|
||||
Userspace handler process is killed:
|
||||
|
||||
- It is still possible to restart and re-connect to TCMU
|
||||
devices. Command ring is preserved. However, after the timeout period,
|
||||
the kernel will abort pending tasks.
|
||||
|
||||
Userspace handler process hangs:
|
||||
|
||||
- The kernel will abort pending tasks after a timeout period.
|
||||
|
||||
Userspace handler process is malicious:
|
||||
|
||||
- The process can trivially break the handling of devices it controls,
|
||||
but should not be able to access kernel memory outside its shared
|
||||
memory areas.
|
||||
|
||||
|
||||
Writing a user pass-through handler (with example code)
|
||||
-------------------------------------------------------
|
||||
|
||||
A user process handing a TCMU device must support the following:
|
||||
|
||||
a) Discovering and configuring TCMU uio devices
|
||||
b) Waiting for events on the device(s)
|
||||
c) Managing the command ring: Parsing operations and commands,
|
||||
performing work as needed, setting response fields (scsi_status and
|
||||
possibly sense_buffer), updating cmd_tail, and notifying the kernel
|
||||
that work has been finished
|
||||
|
||||
First, consider instead writing a plugin for tcmu-runner. tcmu-runner
|
||||
implements all of this, and provides a higher-level API for plugin
|
||||
authors.
|
||||
|
||||
TCMU is designed so that multiple unrelated processes can manage TCMU
|
||||
devices separately. All handlers should make sure to only open their
|
||||
devices, based opon a known subtype string.
|
||||
|
||||
a) Discovering and configuring TCMU UIO devices:
|
||||
|
||||
(error checking omitted for brevity)
|
||||
|
||||
int fd, dev_fd;
|
||||
char buf[256];
|
||||
unsigned long long map_len;
|
||||
void *map;
|
||||
|
||||
fd = open("/sys/class/uio/uio0/name", O_RDONLY);
|
||||
ret = read(fd, buf, sizeof(buf));
|
||||
close(fd);
|
||||
buf[ret-1] = '\0'; /* null-terminate and chop off the \n */
|
||||
|
||||
/* we only want uio devices whose name is a format we expect */
|
||||
if (strncmp(buf, "tcm-user", 8))
|
||||
exit(-1);
|
||||
|
||||
/* Further checking for subtype also needed here */
|
||||
|
||||
fd = open(/sys/class/uio/%s/maps/map0/size, O_RDONLY);
|
||||
ret = read(fd, buf, sizeof(buf));
|
||||
close(fd);
|
||||
str_buf[ret-1] = '\0'; /* null-terminate and chop off the \n */
|
||||
|
||||
map_len = strtoull(buf, NULL, 0);
|
||||
|
||||
dev_fd = open("/dev/uio0", O_RDWR);
|
||||
map = mmap(NULL, map_len, PROT_READ|PROT_WRITE, MAP_SHARED, dev_fd, 0);
|
||||
|
||||
|
||||
b) Waiting for events on the device(s)
|
||||
|
||||
while (1) {
|
||||
char buf[4];
|
||||
|
||||
int ret = read(dev_fd, buf, 4); /* will block */
|
||||
|
||||
handle_device_events(dev_fd, map);
|
||||
}
|
||||
|
||||
|
||||
c) Managing the command ring
|
||||
|
||||
#include <linux/target_core_user.h>
|
||||
|
||||
int handle_device_events(int fd, void *map)
|
||||
{
|
||||
struct tcmu_mailbox *mb = map;
|
||||
struct tcmu_cmd_entry *ent = (void *) mb + mb->cmdr_off + mb->cmd_tail;
|
||||
int did_some_work = 0;
|
||||
|
||||
/* Process events from cmd ring until we catch up with cmd_head */
|
||||
while (ent != (void *)mb + mb->cmdr_off + mb->cmd_head) {
|
||||
|
||||
if (tcmu_hdr_get_op(&ent->hdr) == TCMU_OP_CMD) {
|
||||
uint8_t *cdb = (void *)mb + ent->req.cdb_off;
|
||||
bool success = true;
|
||||
|
||||
/* Handle command here. */
|
||||
printf("SCSI opcode: 0x%x\n", cdb[0]);
|
||||
|
||||
/* Set response fields */
|
||||
if (success)
|
||||
ent->rsp.scsi_status = SCSI_NO_SENSE;
|
||||
else {
|
||||
/* Also fill in rsp->sense_buffer here */
|
||||
ent->rsp.scsi_status = SCSI_CHECK_CONDITION;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Do nothing for PAD entries */
|
||||
}
|
||||
|
||||
/* update cmd_tail */
|
||||
mb->cmd_tail = (mb->cmd_tail + tcmu_hdr_get_len(&ent->hdr)) % mb->cmdr_size;
|
||||
ent = (void *) mb + mb->cmdr_off + mb->cmd_tail;
|
||||
did_some_work = 1;
|
||||
}
|
||||
|
||||
/* Notify the kernel that work has been finished */
|
||||
if (did_some_work) {
|
||||
uint32_t buf = 0;
|
||||
|
||||
write(fd, &buf, 4);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Command filtering and pass_level
|
||||
--------------------------------
|
||||
|
||||
TCMU supports a "pass_level" option with valid values of 0 or 1. When
|
||||
the value is 0 (the default), nearly all SCSI commands received for
|
||||
the device are passed through to the handler. This allows maximum
|
||||
flexibility but increases the amount of code required by the handler,
|
||||
to support all mandatory SCSI commands. If pass_level is set to 1,
|
||||
then only IO-related commands are presented, and the rest are handled
|
||||
by LIO's in-kernel command emulation. The commands presented at level
|
||||
1 include all versions of:
|
||||
|
||||
READ
|
||||
WRITE
|
||||
WRITE_VERIFY
|
||||
XDWRITEREAD
|
||||
WRITE_SAME
|
||||
COMPARE_AND_WRITE
|
||||
SYNCHRONIZE_CACHE
|
||||
UNMAP
|
||||
|
||||
|
||||
A final note
|
||||
------------
|
||||
|
||||
Please be careful to return codes as defined by the SCSI
|
||||
specifications. These are different than some values defined in the
|
||||
scsi/scsi.h include file. For example, CHECK CONDITION's status code
|
||||
is 2, not 1.
|
24
MAINTAINERS
24
MAINTAINERS
|
@ -1749,6 +1749,13 @@ M: Nicolas Ferre <nicolas.ferre@atmel.com>
|
|||
S: Supported
|
||||
F: drivers/spi/spi-atmel.*
|
||||
|
||||
ATMEL SSC DRIVER
|
||||
M: Bo Shen <voice.shen@atmel.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
F: drivers/misc/atmel-ssc.c
|
||||
F: include/linux/atmel-ssc.h
|
||||
|
||||
ATMEL Timer Counter (TC) AND CLOCKSOURCE DRIVERS
|
||||
M: Nicolas Ferre <nicolas.ferre@atmel.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
|
@ -5834,6 +5841,14 @@ S: Maintained
|
|||
F: drivers/net/macvlan.c
|
||||
F: include/linux/if_macvlan.h
|
||||
|
||||
MAILBOX API
|
||||
M: Jassi Brar <jassisinghbrar@gmail.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/mailbox/
|
||||
F: include/linux/mailbox_client.h
|
||||
F: include/linux/mailbox_controller.h
|
||||
|
||||
MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
|
||||
M: Michael Kerrisk <mtk.manpages@gmail.com>
|
||||
W: http://www.kernel.org/doc/man-pages
|
||||
|
@ -6822,7 +6837,7 @@ S: Orphan
|
|||
F: drivers/net/wireless/orinoco/
|
||||
|
||||
OSD LIBRARY and FILESYSTEM
|
||||
M: Boaz Harrosh <bharrosh@panasas.com>
|
||||
M: Boaz Harrosh <ooo@electrozaur.com>
|
||||
M: Benny Halevy <bhalevy@primarydata.com>
|
||||
L: osd-dev@open-osd.org
|
||||
W: http://open-osd.org
|
||||
|
@ -6832,6 +6847,13 @@ F: drivers/scsi/osd/
|
|||
F: include/scsi/osd_*
|
||||
F: fs/exofs/
|
||||
|
||||
OVERLAYFS FILESYSTEM
|
||||
M: Miklos Szeredi <miklos@szeredi.hu>
|
||||
L: linux-fsdevel@vger.kernel.org
|
||||
S: Supported
|
||||
F: fs/overlayfs/*
|
||||
F: Documentation/filesystems/overlayfs.txt
|
||||
|
||||
P54 WIRELESS DRIVER
|
||||
M: Christian Lamparter <chunkeey@googlemail.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
VERSION = 3
|
||||
PATCHLEVEL = 18
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc1
|
||||
EXTRAVERSION = -rc2
|
||||
NAME = Shuffling Zombie Juror
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
config ARC
|
||||
def_bool y
|
||||
select BUILDTIME_EXTABLE_SORT
|
||||
select COMMON_CLK
|
||||
select CLONE_BACKWARDS
|
||||
# ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev
|
||||
select DEVTMPFS if !INITRAMFS_SOURCE=""
|
||||
|
@ -73,9 +74,6 @@ config STACKTRACE_SUPPORT
|
|||
config HAVE_LATENCYTOP_SUPPORT
|
||||
def_bool y
|
||||
|
||||
config NO_DMA
|
||||
def_bool n
|
||||
|
||||
source "init/Kconfig"
|
||||
source "kernel/Kconfig.freezer"
|
||||
|
||||
|
@ -354,7 +352,7 @@ config ARC_CURR_IN_REG
|
|||
kernel mode. This saves memory access for each such access
|
||||
|
||||
|
||||
config ARC_MISALIGN_ACCESS
|
||||
config ARC_EMUL_UNALIGNED
|
||||
bool "Emulate unaligned memory access (userspace only)"
|
||||
select SYSCTL_ARCH_UNALIGN_NO_WARN
|
||||
select SYSCTL_ARCH_UNALIGN_ALLOW
|
||||
|
|
|
@ -25,7 +25,6 @@ ifdef CONFIG_ARC_CURR_IN_REG
|
|||
LINUXINCLUDE += -include ${src}/arch/arc/include/asm/current.h
|
||||
endif
|
||||
|
||||
upto_gcc42 := $(call cc-ifversion, -le, 0402, y)
|
||||
upto_gcc44 := $(call cc-ifversion, -le, 0404, y)
|
||||
atleast_gcc44 := $(call cc-ifversion, -ge, 0404, y)
|
||||
atleast_gcc48 := $(call cc-ifversion, -ge, 0408, y)
|
||||
|
@ -60,25 +59,11 @@ ldflags-$(CONFIG_CPU_BIG_ENDIAN) += -EB
|
|||
# --build-id w/o "-marclinux". Default arc-elf32-ld is OK
|
||||
ldflags-$(upto_gcc44) += -marclinux
|
||||
|
||||
ARC_LIBGCC := -mA7
|
||||
cflags-$(CONFIG_ARC_HAS_HW_MPY) += -multcost=16
|
||||
|
||||
ifndef CONFIG_ARC_HAS_HW_MPY
|
||||
cflags-y += -mno-mpy
|
||||
|
||||
# newlib for ARC700 assumes MPY to be always present, which is generally true
|
||||
# However, if someone really doesn't want MPY, we need to use the 600 ver
|
||||
# which coupled with -mno-mpy will use mpy emulation
|
||||
# With gcc 4.4.7, -mno-mpy is enough to make any other related adjustments,
|
||||
# e.g. increased cost of MPY. With gcc 4.2.1 this had to be explicitly hinted
|
||||
|
||||
ifeq ($(upto_gcc42),y)
|
||||
ARC_LIBGCC := -marc600
|
||||
cflags-y += -multcost=30
|
||||
endif
|
||||
endif
|
||||
|
||||
LIBGCC := $(shell $(CC) $(ARC_LIBGCC) $(cflags-y) --print-libgcc-file-name)
|
||||
LIBGCC := $(shell $(CC) $(cflags-y) --print-libgcc-file-name)
|
||||
|
||||
# Modules with short calls might break for calls into builtin-kernel
|
||||
KBUILD_CFLAGS_MODULE += -mlong-calls
|
||||
|
|
|
@ -24,11 +24,6 @@
|
|||
serial0 = &arcuart0;
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x10000000>; /* 256M */
|
||||
};
|
||||
|
||||
fpga {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
|
|
|
@ -20,18 +20,13 @@
|
|||
/* this is for console on PGU */
|
||||
/* bootargs = "console=tty0 consoleblank=0"; */
|
||||
/* this is for console on serial */
|
||||
bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=ttyS0,115200n8 consoleblank=0 debug";
|
||||
bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug";
|
||||
};
|
||||
|
||||
aliases {
|
||||
serial0 = &uart0;
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0x80000000 0x10000000>; /* 256M */
|
||||
};
|
||||
|
||||
fpga {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
|
|
|
@ -23,7 +23,6 @@ CONFIG_MODULES=y
|
|||
# CONFIG_IOSCHED_DEADLINE is not set
|
||||
# CONFIG_IOSCHED_CFQ is not set
|
||||
CONFIG_ARC_PLAT_FPGA_LEGACY=y
|
||||
CONFIG_ARC_BOARD_ML509=y
|
||||
# CONFIG_ARC_HAS_RTSC is not set
|
||||
CONFIG_ARC_BUILTIN_DTB_NAME="angel4"
|
||||
CONFIG_PREEMPT=y
|
||||
|
|
|
@ -20,7 +20,6 @@ CONFIG_MODULES=y
|
|||
# CONFIG_IOSCHED_DEADLINE is not set
|
||||
# CONFIG_IOSCHED_CFQ is not set
|
||||
CONFIG_ARC_PLAT_FPGA_LEGACY=y
|
||||
CONFIG_ARC_BOARD_ML509=y
|
||||
# CONFIG_ARC_HAS_RTSC is not set
|
||||
CONFIG_ARC_BUILTIN_DTB_NAME="angel4"
|
||||
CONFIG_PREEMPT=y
|
||||
|
|
|
@ -21,7 +21,6 @@ CONFIG_MODULES=y
|
|||
# CONFIG_IOSCHED_DEADLINE is not set
|
||||
# CONFIG_IOSCHED_CFQ is not set
|
||||
CONFIG_ARC_PLAT_FPGA_LEGACY=y
|
||||
CONFIG_ARC_BOARD_ML509=y
|
||||
# CONFIG_ARC_IDE is not set
|
||||
# CONFIG_ARCTANGENT_EMAC is not set
|
||||
# CONFIG_ARC_HAS_RTSC is not set
|
||||
|
|
|
@ -9,19 +9,16 @@
|
|||
#ifndef _ASM_ARC_ARCREGS_H
|
||||
#define _ASM_ARC_ARCREGS_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* Build Configuration Registers */
|
||||
#define ARC_REG_DCCMBASE_BCR 0x61 /* DCCM Base Addr */
|
||||
#define ARC_REG_CRC_BCR 0x62
|
||||
#define ARC_REG_DVFB_BCR 0x64
|
||||
#define ARC_REG_EXTARITH_BCR 0x65
|
||||
#define ARC_REG_VECBASE_BCR 0x68
|
||||
#define ARC_REG_PERIBASE_BCR 0x69
|
||||
#define ARC_REG_FP_BCR 0x6B /* Single-Precision FPU */
|
||||
#define ARC_REG_DPFP_BCR 0x6C /* Dbl Precision FPU */
|
||||
#define ARC_REG_FP_BCR 0x6B /* ARCompact: Single-Precision FPU */
|
||||
#define ARC_REG_DPFP_BCR 0x6C /* ARCompact: Dbl Precision FPU */
|
||||
#define ARC_REG_DCCM_BCR 0x74 /* DCCM Present + SZ */
|
||||
#define ARC_REG_TIMERS_BCR 0x75
|
||||
#define ARC_REG_AP_BCR 0x76
|
||||
#define ARC_REG_ICCM_BCR 0x78
|
||||
#define ARC_REG_XY_MEM_BCR 0x79
|
||||
#define ARC_REG_MAC_BCR 0x7a
|
||||
|
@ -31,6 +28,9 @@
|
|||
#define ARC_REG_MIXMAX_BCR 0x7e
|
||||
#define ARC_REG_BARREL_BCR 0x7f
|
||||
#define ARC_REG_D_UNCACH_BCR 0x6A
|
||||
#define ARC_REG_BPU_BCR 0xc0
|
||||
#define ARC_REG_ISA_CFG_BCR 0xc1
|
||||
#define ARC_REG_SMART_BCR 0xFF
|
||||
|
||||
/* status32 Bits Positions */
|
||||
#define STATUS_AE_BIT 5 /* Exception active */
|
||||
|
@ -191,14 +191,6 @@
|
|||
#define PAGES_TO_KB(n_pages) ((n_pages) << (PAGE_SHIFT - 10))
|
||||
#define PAGES_TO_MB(n_pages) (PAGES_TO_KB(n_pages) >> 10)
|
||||
|
||||
#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
|
||||
/* These DPFP regs need to be saved/restored across ctx-sw */
|
||||
struct arc_fpu {
|
||||
struct {
|
||||
unsigned int l, h;
|
||||
} aux_dpfp[2];
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
***************************************************************
|
||||
|
@ -212,27 +204,19 @@ struct bcr_identity {
|
|||
#endif
|
||||
};
|
||||
|
||||
#define EXTN_SWAP_VALID 0x1
|
||||
#define EXTN_NORM_VALID 0x2
|
||||
#define EXTN_MINMAX_VALID 0x2
|
||||
#define EXTN_BARREL_VALID 0x2
|
||||
|
||||
struct bcr_extn {
|
||||
struct bcr_isa {
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
unsigned int pad:20, crc:1, ext_arith:2, mul:2, barrel:2, minmax:2,
|
||||
norm:2, swap:1;
|
||||
unsigned int pad1:23, atomic1:1, ver:8;
|
||||
#else
|
||||
unsigned int swap:1, norm:2, minmax:2, barrel:2, mul:2, ext_arith:2,
|
||||
crc:1, pad:20;
|
||||
unsigned int ver:8, atomic1:1, pad1:23;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* DSP Options Ref Manual */
|
||||
struct bcr_extn_mac_mul {
|
||||
struct bcr_mpy {
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
unsigned int pad:16, type:8, ver:8;
|
||||
unsigned int pad:8, x1616:8, dsp:4, cycles:2, type:2, ver:8;
|
||||
#else
|
||||
unsigned int ver:8, type:8, pad:16;
|
||||
unsigned int ver:8, type:2, cycles:2, dsp:4, x1616:8, pad:8;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -251,6 +235,7 @@ struct bcr_perip {
|
|||
unsigned int pad:8, sz:8, pad2:8, start:8;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct bcr_iccm {
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
unsigned int base:16, pad:5, sz:3, ver:8;
|
||||
|
@ -277,8 +262,8 @@ struct bcr_dccm {
|
|||
#endif
|
||||
};
|
||||
|
||||
/* Both SP and DP FPU BCRs have same format */
|
||||
struct bcr_fp {
|
||||
/* ARCompact: Both SP and DP FPU BCRs have same format */
|
||||
struct bcr_fp_arcompact {
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
unsigned int fast:1, ver:8;
|
||||
#else
|
||||
|
@ -286,6 +271,30 @@ struct bcr_fp {
|
|||
#endif
|
||||
};
|
||||
|
||||
struct bcr_timer {
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
unsigned int pad2:15, rtsc:1, pad1:6, t1:1, t0:1, ver:8;
|
||||
#else
|
||||
unsigned int ver:8, t0:1, t1:1, pad1:6, rtsc:1, pad2:15;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct bcr_bpu_arcompact {
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
unsigned int pad2:19, fam:1, pad:2, ent:2, ver:8;
|
||||
#else
|
||||
unsigned int ver:8, ent:2, pad:2, fam:1, pad2:19;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct bcr_generic {
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
unsigned int pad:24, ver:8;
|
||||
#else
|
||||
unsigned int ver:8, pad:24;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
*******************************************************************
|
||||
* Generic structures to hold build configuration used at runtime
|
||||
|
@ -299,6 +308,10 @@ struct cpuinfo_arc_cache {
|
|||
unsigned int sz_k:8, line_len:8, assoc:4, ver:4, alias:1, vipt:1, pad:6;
|
||||
};
|
||||
|
||||
struct cpuinfo_arc_bpu {
|
||||
unsigned int ver, full, num_cache, num_pred;
|
||||
};
|
||||
|
||||
struct cpuinfo_arc_ccm {
|
||||
unsigned int base_addr, sz;
|
||||
};
|
||||
|
@ -306,21 +319,25 @@ struct cpuinfo_arc_ccm {
|
|||
struct cpuinfo_arc {
|
||||
struct cpuinfo_arc_cache icache, dcache;
|
||||
struct cpuinfo_arc_mmu mmu;
|
||||
struct cpuinfo_arc_bpu bpu;
|
||||
struct bcr_identity core;
|
||||
unsigned int timers;
|
||||
struct bcr_isa isa;
|
||||
struct bcr_timer timers;
|
||||
unsigned int vec_base;
|
||||
unsigned int uncached_base;
|
||||
struct cpuinfo_arc_ccm iccm, dccm;
|
||||
struct bcr_extn extn;
|
||||
struct {
|
||||
unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, pad1:3,
|
||||
fpu_sp:1, fpu_dp:1, pad2:6,
|
||||
debug:1, ap:1, smart:1, rtt:1, pad3:4,
|
||||
pad4:8;
|
||||
} extn;
|
||||
struct bcr_mpy extn_mpy;
|
||||
struct bcr_extn_xymem extn_xymem;
|
||||
struct bcr_extn_mac_mul extn_mac_mul;
|
||||
struct bcr_fp fp, dpfp;
|
||||
};
|
||||
|
||||
extern struct cpuinfo_arc cpuinfo_arc700[];
|
||||
|
||||
#endif /* __ASEMBLY__ */
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _ASM_ARC_ARCREGS_H */
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
#ifndef _ASM_ARC_ATOMIC_H
|
||||
#define _ASM_ARC_ATOMIC_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
@ -170,5 +168,3 @@ ATOMIC_OP(and, &=, and)
|
|||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
#error only <linux/bitops.h> can be included directly
|
||||
#endif
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
@ -508,6 +506,4 @@ static inline __attribute__ ((const)) int __ffs(unsigned long word)
|
|||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,10 +21,9 @@ void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
|
|||
unsigned long address);
|
||||
void die(const char *str, struct pt_regs *regs, unsigned long address);
|
||||
|
||||
#define BUG() do { \
|
||||
dump_stack(); \
|
||||
pr_warn("Kernel BUG in %s: %s: %d!\n", \
|
||||
__FILE__, __func__, __LINE__); \
|
||||
#define BUG() do { \
|
||||
pr_warn("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
|
||||
dump_stack(); \
|
||||
} while (0)
|
||||
|
||||
#define HAVE_ARCH_BUG
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#define CACHE_LINE_MASK (~(L1_CACHE_BYTES - 1))
|
||||
|
||||
/*
|
||||
* ARC700 doesn't cache any access in top 256M.
|
||||
* ARC700 doesn't cache any access in top 1G (0xc000_0000 to 0xFFFF_FFFF)
|
||||
* Ideal for wiring memory mapped peripherals as we don't need to do
|
||||
* explicit uncached accesses (LD.di/ST.di) hence more portable drivers
|
||||
*/
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
#ifndef _ASM_ARC_CURRENT_H
|
||||
#define _ASM_ARC_CURRENT_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#ifdef CONFIG_ARC_CURR_IN_REG
|
||||
|
@ -27,6 +25,4 @@ register struct task_struct *curr_arc asm("r25");
|
|||
|
||||
#endif /* ! __ASSEMBLY__ */
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _ASM_ARC_CURRENT_H */
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
* -Conditionally disable interrupts (if they are not enabled, don't disable)
|
||||
*/
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <asm/arcregs.h>
|
||||
|
||||
/* status32 Reg bits related to Interrupt Handling */
|
||||
|
@ -169,6 +167,4 @@ static inline int arch_irqs_disabled(void)
|
|||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
* register API yet */
|
||||
#undef DBG_MAX_REG_NUM
|
||||
|
||||
#define GDB_MAX_REGS 39
|
||||
#define GDB_MAX_REGS 87
|
||||
|
||||
#define BREAK_INSTR_SIZE 2
|
||||
#define CACHE_FLUSH_IS_SAFE 1
|
||||
|
@ -33,23 +33,27 @@ static inline void arch_kgdb_breakpoint(void)
|
|||
|
||||
extern void kgdb_trap(struct pt_regs *regs);
|
||||
|
||||
enum arc700_linux_regnums {
|
||||
/* This is the numbering of registers according to the GDB. See GDB's
|
||||
* arc-tdep.h for details.
|
||||
*
|
||||
* Registers are ordered for GDB 7.5. It is incompatible with GDB 6.8. */
|
||||
enum arc_linux_regnums {
|
||||
_R0 = 0,
|
||||
_R1, _R2, _R3, _R4, _R5, _R6, _R7, _R8, _R9, _R10, _R11, _R12, _R13,
|
||||
_R14, _R15, _R16, _R17, _R18, _R19, _R20, _R21, _R22, _R23, _R24,
|
||||
_R25, _R26,
|
||||
_BTA = 27,
|
||||
_LP_START = 28,
|
||||
_LP_END = 29,
|
||||
_LP_COUNT = 30,
|
||||
_STATUS32 = 31,
|
||||
_BLINK = 32,
|
||||
_FP = 33,
|
||||
__SP = 34,
|
||||
_EFA = 35,
|
||||
_RET = 36,
|
||||
_ORIG_R8 = 37,
|
||||
_STOP_PC = 38
|
||||
_FP = 27,
|
||||
__SP = 28,
|
||||
_R30 = 30,
|
||||
_BLINK = 31,
|
||||
_LP_COUNT = 60,
|
||||
_STOP_PC = 64,
|
||||
_RET = 64,
|
||||
_LP_START = 65,
|
||||
_LP_END = 66,
|
||||
_STATUS32 = 67,
|
||||
_ECR = 76,
|
||||
_BTA = 82,
|
||||
};
|
||||
|
||||
#else
|
||||
|
|
|
@ -14,12 +14,19 @@
|
|||
#ifndef __ASM_ARC_PROCESSOR_H
|
||||
#define __ASM_ARC_PROCESSOR_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
|
||||
/* These DPFP regs need to be saved/restored across ctx-sw */
|
||||
struct arc_fpu {
|
||||
struct {
|
||||
unsigned int l, h;
|
||||
} aux_dpfp[2];
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Arch specific stuff which needs to be saved per task.
|
||||
* However these items are not so important so as to earn a place in
|
||||
* struct thread_info
|
||||
|
@ -128,6 +135,4 @@ extern unsigned int get_wchan(struct task_struct *p);
|
|||
*/
|
||||
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __ASM_ARC_PROCESSOR_H */
|
||||
|
|
|
@ -29,7 +29,6 @@ struct cpuinfo_data {
|
|||
};
|
||||
|
||||
extern int root_mountflags, end_mem;
|
||||
extern int running_on_hw;
|
||||
|
||||
void setup_processor(void);
|
||||
void __init setup_arch_memory(void);
|
||||
|
|
|
@ -59,7 +59,15 @@ struct plat_smp_ops {
|
|||
/* TBD: stop exporting it for direct population by platform */
|
||||
extern struct plat_smp_ops plat_smp_ops;
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
#else /* CONFIG_SMP */
|
||||
|
||||
static inline void smp_init_cpus(void) {}
|
||||
static inline const char *arc_platform_smp_cpuinfo(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_SMP */
|
||||
|
||||
/*
|
||||
* ARC700 doesn't support atomic Read-Modify-Write ops.
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define __HAVE_ARCH_MEMSET
|
||||
#define __HAVE_ARCH_MEMCPY
|
||||
#define __HAVE_ARCH_MEMCMP
|
||||
|
@ -36,5 +34,4 @@ extern char *strcpy(char *dest, const char *src);
|
|||
extern int strcmp(const char *cs, const char *ct);
|
||||
extern __kernel_size_t strlen(const char *);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_ARC_STRING_H */
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
#ifndef _ASM_ARC_SYSCALLS_H
|
||||
#define _ASM_ARC_SYSCALLS_H 1
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/types.h>
|
||||
|
@ -22,6 +20,4 @@ int sys_arc_gettls(void);
|
|||
|
||||
#include <asm-generic/syscalls.h>
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
#ifndef _ASM_THREAD_INFO_H
|
||||
#define _ASM_THREAD_INFO_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <asm/page.h>
|
||||
|
||||
#ifdef CONFIG_16KSTACKS
|
||||
|
@ -114,6 +112,4 @@ static inline __attribute_const__ struct thread_info *current_thread_info(void)
|
|||
* syscall, so all that reamins to be tested is _TIF_WORK_MASK
|
||||
*/
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _ASM_THREAD_INFO_H */
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <asm-generic/unaligned.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
#ifdef CONFIG_ARC_MISALIGN_ACCESS
|
||||
#ifdef CONFIG_ARC_EMUL_UNALIGNED
|
||||
int misaligned_fixup(unsigned long address, struct pt_regs *regs,
|
||||
struct callee_regs *cregs);
|
||||
#else
|
||||
|
|
|
@ -16,7 +16,7 @@ obj-$(CONFIG_MODULES) += arcksyms.o module.o
|
|||
obj-$(CONFIG_SMP) += smp.o
|
||||
obj-$(CONFIG_ARC_DW2_UNWIND) += unwind.o
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o
|
||||
obj-$(CONFIG_ARC_MISALIGN_ACCESS) += unaligned.o
|
||||
obj-$(CONFIG_ARC_EMUL_UNALIGNED) += unaligned.o
|
||||
obj-$(CONFIG_KGDB) += kgdb.o
|
||||
obj-$(CONFIG_ARC_METAWARE_HLINK) += arc_hostlink.o
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_event.o
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include <linux/uaccess.h>
|
||||
#include <asm/disasm.h>
|
||||
|
||||
#if defined(CONFIG_KGDB) || defined(CONFIG_ARC_MISALIGN_ACCESS) || \
|
||||
#if defined(CONFIG_KGDB) || defined(CONFIG_ARC_EMUL_UNALIGNED) || \
|
||||
defined(CONFIG_KPROBES)
|
||||
|
||||
/* disasm_instr: Analyses instruction at addr, stores
|
||||
|
@ -535,4 +535,4 @@ int __kprobes disasm_next_pc(unsigned long pc, struct pt_regs *regs,
|
|||
return instr.is_branch;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_KGDB || CONFIG_ARC_MISALIGN_ACCESS || CONFIG_KPROBES */
|
||||
#endif /* CONFIG_KGDB || CONFIG_ARC_EMUL_UNALIGNED || CONFIG_KPROBES */
|
||||
|
|
|
@ -91,16 +91,6 @@ stext:
|
|||
st r0, [@uboot_tag]
|
||||
st r2, [@uboot_arg]
|
||||
|
||||
; Identify if running on ISS vs Silicon
|
||||
; IDENTITY Reg [ 3 2 1 0 ]
|
||||
; (chip-id) ^^^^^ ==> 0xffff for ISS
|
||||
lr r0, [identity]
|
||||
lsr r3, r0, 16
|
||||
cmp r3, 0xffff
|
||||
mov.z r4, 0
|
||||
mov.nz r4, 1
|
||||
st r4, [@running_on_hw]
|
||||
|
||||
; setup "current" tsk and optionally cache it in dedicated r25
|
||||
mov r9, @init_task
|
||||
SET_CURR_TASK_ON_CPU r9, r0 ; r9 = tsk, r0 = scratch
|
||||
|
|
|
@ -158,11 +158,6 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
|
|||
return -1;
|
||||
}
|
||||
|
||||
unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
|
||||
{
|
||||
return instruction_pointer(regs);
|
||||
}
|
||||
|
||||
int kgdb_arch_init(void)
|
||||
{
|
||||
single_step_data.armed = 0;
|
||||
|
|
|
@ -244,25 +244,23 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
|
|||
pr_err("This core does not have performance counters!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
BUG_ON(pct_bcr.c > ARC_PMU_MAX_HWEVENTS);
|
||||
|
||||
arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu),
|
||||
GFP_KERNEL);
|
||||
READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
|
||||
if (!cc_bcr.v) {
|
||||
pr_err("Performance counters exist, but no countable conditions?\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu), GFP_KERNEL);
|
||||
if (!arc_pmu)
|
||||
return -ENOMEM;
|
||||
|
||||
arc_pmu->n_counters = pct_bcr.c;
|
||||
BUG_ON(arc_pmu->n_counters > ARC_PMU_MAX_HWEVENTS);
|
||||
|
||||
arc_pmu->counter_size = 32 + (pct_bcr.s << 4);
|
||||
pr_info("ARC PMU found with %d counters of size %d bits\n",
|
||||
arc_pmu->n_counters, arc_pmu->counter_size);
|
||||
|
||||
READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
|
||||
|
||||
if (!cc_bcr.v)
|
||||
pr_err("Strange! Performance counters exist, but no countable conditions?\n");
|
||||
|
||||
pr_info("ARC PMU has %d countable conditions\n", cc_bcr.c);
|
||||
pr_info("ARC perf\t: %d counters (%d bits), %d countable conditions\n",
|
||||
arc_pmu->n_counters, arc_pmu->counter_size, cc_bcr.c);
|
||||
|
||||
cc_name.str[8] = 0;
|
||||
for (i = 0; i < PERF_COUNT_HW_MAX; i++)
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
#include <linux/console.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/cache.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/arcregs.h>
|
||||
|
@ -24,11 +26,10 @@
|
|||
#include <asm/unwind.h>
|
||||
#include <asm/clk.h>
|
||||
#include <asm/mach_desc.h>
|
||||
#include <asm/smp.h>
|
||||
|
||||
#define FIX_PTR(x) __asm__ __volatile__(";" : "+r"(x))
|
||||
|
||||
int running_on_hw = 1; /* vs. on ISS */
|
||||
|
||||
/* Part of U-boot ABI: see head.S */
|
||||
int __initdata uboot_tag;
|
||||
char __initdata *uboot_arg;
|
||||
|
@ -42,26 +43,26 @@ struct cpuinfo_arc cpuinfo_arc700[NR_CPUS];
|
|||
static void read_arc_build_cfg_regs(void)
|
||||
{
|
||||
struct bcr_perip uncached_space;
|
||||
struct bcr_generic bcr;
|
||||
struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
|
||||
FIX_PTR(cpu);
|
||||
|
||||
READ_BCR(AUX_IDENTITY, cpu->core);
|
||||
READ_BCR(ARC_REG_ISA_CFG_BCR, cpu->isa);
|
||||
|
||||
cpu->timers = read_aux_reg(ARC_REG_TIMERS_BCR);
|
||||
READ_BCR(ARC_REG_TIMERS_BCR, cpu->timers);
|
||||
cpu->vec_base = read_aux_reg(AUX_INTR_VEC_BASE);
|
||||
|
||||
READ_BCR(ARC_REG_D_UNCACH_BCR, uncached_space);
|
||||
cpu->uncached_base = uncached_space.start << 24;
|
||||
|
||||
cpu->extn.mul = read_aux_reg(ARC_REG_MUL_BCR);
|
||||
cpu->extn.swap = read_aux_reg(ARC_REG_SWAP_BCR);
|
||||
cpu->extn.norm = read_aux_reg(ARC_REG_NORM_BCR);
|
||||
cpu->extn.minmax = read_aux_reg(ARC_REG_MIXMAX_BCR);
|
||||
cpu->extn.barrel = read_aux_reg(ARC_REG_BARREL_BCR);
|
||||
READ_BCR(ARC_REG_MAC_BCR, cpu->extn_mac_mul);
|
||||
READ_BCR(ARC_REG_MUL_BCR, cpu->extn_mpy);
|
||||
|
||||
cpu->extn.ext_arith = read_aux_reg(ARC_REG_EXTARITH_BCR);
|
||||
cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR);
|
||||
cpu->extn.norm = read_aux_reg(ARC_REG_NORM_BCR) > 1 ? 1 : 0; /* 2,3 */
|
||||
cpu->extn.barrel = read_aux_reg(ARC_REG_BARREL_BCR) > 1 ? 1 : 0; /* 2,3 */
|
||||
cpu->extn.swap = read_aux_reg(ARC_REG_SWAP_BCR) ? 1 : 0; /* 1,3 */
|
||||
cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR) ? 1 : 0;
|
||||
cpu->extn.minmax = read_aux_reg(ARC_REG_MIXMAX_BCR) > 1 ? 1 : 0; /* 2 */
|
||||
|
||||
/* Note that we read the CCM BCRs independent of kernel config
|
||||
* This is to catch the cases where user doesn't know that
|
||||
|
@ -95,43 +96,76 @@ static void read_arc_build_cfg_regs(void)
|
|||
read_decode_mmu_bcr();
|
||||
read_decode_cache_bcr();
|
||||
|
||||
READ_BCR(ARC_REG_FP_BCR, cpu->fp);
|
||||
READ_BCR(ARC_REG_DPFP_BCR, cpu->dpfp);
|
||||
{
|
||||
struct bcr_fp_arcompact sp, dp;
|
||||
struct bcr_bpu_arcompact bpu;
|
||||
|
||||
READ_BCR(ARC_REG_FP_BCR, sp);
|
||||
READ_BCR(ARC_REG_DPFP_BCR, dp);
|
||||
cpu->extn.fpu_sp = sp.ver ? 1 : 0;
|
||||
cpu->extn.fpu_dp = dp.ver ? 1 : 0;
|
||||
|
||||
READ_BCR(ARC_REG_BPU_BCR, bpu);
|
||||
cpu->bpu.ver = bpu.ver;
|
||||
cpu->bpu.full = bpu.fam ? 1 : 0;
|
||||
if (bpu.ent) {
|
||||
cpu->bpu.num_cache = 256 << (bpu.ent - 1);
|
||||
cpu->bpu.num_pred = 256 << (bpu.ent - 1);
|
||||
}
|
||||
}
|
||||
|
||||
READ_BCR(ARC_REG_AP_BCR, bcr);
|
||||
cpu->extn.ap = bcr.ver ? 1 : 0;
|
||||
|
||||
READ_BCR(ARC_REG_SMART_BCR, bcr);
|
||||
cpu->extn.smart = bcr.ver ? 1 : 0;
|
||||
|
||||
cpu->extn.debug = cpu->extn.ap | cpu->extn.smart;
|
||||
}
|
||||
|
||||
static const struct cpuinfo_data arc_cpu_tbl[] = {
|
||||
{ {0x10, "ARCTangent A5"}, 0x1F},
|
||||
{ {0x20, "ARC 600" }, 0x2F},
|
||||
{ {0x30, "ARC 700" }, 0x33},
|
||||
{ {0x34, "ARC 700 R4.10"}, 0x34},
|
||||
{ {0x35, "ARC 700 R4.11"}, 0x35},
|
||||
{ {0x00, NULL } }
|
||||
};
|
||||
|
||||
#define IS_AVAIL1(v, str) ((v) ? str : "")
|
||||
#define IS_USED(cfg) (IS_ENABLED(cfg) ? "" : "(not used) ")
|
||||
#define IS_AVAIL2(v, str, cfg) IS_AVAIL1(v, str), IS_AVAIL1(v, IS_USED(cfg))
|
||||
|
||||
static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
|
||||
{
|
||||
int n = 0;
|
||||
struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
|
||||
struct bcr_identity *core = &cpu->core;
|
||||
const struct cpuinfo_data *tbl;
|
||||
int be = 0;
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
be = 1;
|
||||
#endif
|
||||
char *isa_nm;
|
||||
int i, be, atomic;
|
||||
int n = 0;
|
||||
|
||||
FIX_PTR(cpu);
|
||||
|
||||
{
|
||||
isa_nm = "ARCompact";
|
||||
be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN);
|
||||
|
||||
atomic = cpu->isa.atomic1;
|
||||
if (!cpu->isa.ver) /* ISA BCR absent, use Kconfig info */
|
||||
atomic = IS_ENABLED(CONFIG_ARC_HAS_LLSC);
|
||||
}
|
||||
|
||||
n += scnprintf(buf + n, len - n,
|
||||
"\nARC IDENTITY\t: Family [%#02x]"
|
||||
" Cpu-id [%#02x] Chip-id [%#4x]\n",
|
||||
core->family, core->cpu_id,
|
||||
core->chip_id);
|
||||
"\nIDENTITY\t: ARCVER [%#02x] ARCNUM [%#02x] CHIPID [%#4x]\n",
|
||||
core->family, core->cpu_id, core->chip_id);
|
||||
|
||||
for (tbl = &arc_cpu_tbl[0]; tbl->info.id != 0; tbl++) {
|
||||
if ((core->family >= tbl->info.id) &&
|
||||
(core->family <= tbl->up_range)) {
|
||||
n += scnprintf(buf + n, len - n,
|
||||
"processor\t: %s %s\n",
|
||||
tbl->info.str,
|
||||
be ? "[Big Endian]" : "");
|
||||
"processor [%d]\t: %s (%s ISA) %s\n",
|
||||
cpu_id, tbl->info.str, isa_nm,
|
||||
IS_AVAIL1(be, "[Big-Endian]"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -143,102 +177,82 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
|
|||
(unsigned int)(arc_get_core_freq() / 1000000),
|
||||
(unsigned int)(arc_get_core_freq() / 10000) % 100);
|
||||
|
||||
n += scnprintf(buf + n, len - n, "Timers\t\t: %s %s\n",
|
||||
(cpu->timers & 0x200) ? "TIMER1" : "",
|
||||
(cpu->timers & 0x100) ? "TIMER0" : "");
|
||||
n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s\nISA Extn\t: ",
|
||||
IS_AVAIL1(cpu->timers.t0, "Timer0 "),
|
||||
IS_AVAIL1(cpu->timers.t1, "Timer1 "),
|
||||
IS_AVAIL2(cpu->timers.rtsc, "64-bit RTSC ", CONFIG_ARC_HAS_RTSC));
|
||||
|
||||
n += scnprintf(buf + n, len - n, "Vect Tbl Base\t: %#x\n",
|
||||
cpu->vec_base);
|
||||
n += i = scnprintf(buf + n, len - n, "%s%s",
|
||||
IS_AVAIL2(atomic, "atomic ", CONFIG_ARC_HAS_LLSC));
|
||||
|
||||
n += scnprintf(buf + n, len - n, "UNCACHED Base\t: %#x\n",
|
||||
cpu->uncached_base);
|
||||
if (i)
|
||||
n += scnprintf(buf + n, len - n, "\n\t\t: ");
|
||||
|
||||
n += scnprintf(buf + n, len - n, "%s%s%s%s%s%s%s%s\n",
|
||||
IS_AVAIL1(cpu->extn_mpy.ver, "mpy "),
|
||||
IS_AVAIL1(cpu->extn.norm, "norm "),
|
||||
IS_AVAIL1(cpu->extn.barrel, "barrel-shift "),
|
||||
IS_AVAIL1(cpu->extn.swap, "swap "),
|
||||
IS_AVAIL1(cpu->extn.minmax, "minmax "),
|
||||
IS_AVAIL1(cpu->extn.crc, "crc "),
|
||||
IS_AVAIL2(1, "swape", CONFIG_ARC_HAS_SWAPE));
|
||||
|
||||
if (cpu->bpu.ver)
|
||||
n += scnprintf(buf + n, len - n,
|
||||
"BPU\t\t: %s%s match, cache:%d, Predict Table:%d\n",
|
||||
IS_AVAIL1(cpu->bpu.full, "full"),
|
||||
IS_AVAIL1(!cpu->bpu.full, "partial"),
|
||||
cpu->bpu.num_cache, cpu->bpu.num_pred);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const struct id_to_str mul_type_nm[] = {
|
||||
{ 0x0, "N/A"},
|
||||
{ 0x1, "32x32 (spl Result Reg)" },
|
||||
{ 0x2, "32x32 (ANY Result Reg)" }
|
||||
};
|
||||
|
||||
static const struct id_to_str mac_mul_nm[] = {
|
||||
{0x0, "N/A"},
|
||||
{0x1, "N/A"},
|
||||
{0x2, "Dual 16 x 16"},
|
||||
{0x3, "N/A"},
|
||||
{0x4, "32x16"},
|
||||
{0x5, "N/A"},
|
||||
{0x6, "Dual 16x16 and 32x16"}
|
||||
};
|
||||
|
||||
static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
|
||||
{
|
||||
int n = 0;
|
||||
struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
|
||||
|
||||
FIX_PTR(cpu);
|
||||
#define IS_AVAIL1(var, str) ((var) ? str : "")
|
||||
#define IS_AVAIL2(var, str) ((var == 0x2) ? str : "")
|
||||
#define IS_USED(cfg) (IS_ENABLED(cfg) ? "(in-use)" : "(not used)")
|
||||
|
||||
n += scnprintf(buf + n, len - n,
|
||||
"Extn [700-Base]\t: %s %s %s %s %s %s\n",
|
||||
IS_AVAIL2(cpu->extn.norm, "norm,"),
|
||||
IS_AVAIL2(cpu->extn.barrel, "barrel-shift,"),
|
||||
IS_AVAIL1(cpu->extn.swap, "swap,"),
|
||||
IS_AVAIL2(cpu->extn.minmax, "minmax,"),
|
||||
IS_AVAIL1(cpu->extn.crc, "crc,"),
|
||||
IS_AVAIL2(cpu->extn.ext_arith, "ext-arith"));
|
||||
"Vector Table\t: %#x\nUncached Base\t: %#x\n",
|
||||
cpu->vec_base, cpu->uncached_base);
|
||||
|
||||
n += scnprintf(buf + n, len - n, "Extn [700-MPY]\t: %s",
|
||||
mul_type_nm[cpu->extn.mul].str);
|
||||
if (cpu->extn.fpu_sp || cpu->extn.fpu_dp)
|
||||
n += scnprintf(buf + n, len - n, "FPU\t\t: %s%s\n",
|
||||
IS_AVAIL1(cpu->extn.fpu_sp, "SP "),
|
||||
IS_AVAIL1(cpu->extn.fpu_dp, "DP "));
|
||||
|
||||
n += scnprintf(buf + n, len - n, " MAC MPY: %s\n",
|
||||
mac_mul_nm[cpu->extn_mac_mul.type].str);
|
||||
if (cpu->extn.debug)
|
||||
n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s%s\n",
|
||||
IS_AVAIL1(cpu->extn.ap, "ActionPoint "),
|
||||
IS_AVAIL1(cpu->extn.smart, "smaRT "),
|
||||
IS_AVAIL1(cpu->extn.rtt, "RTT "));
|
||||
|
||||
if (cpu->core.family == 0x34) {
|
||||
n += scnprintf(buf + n, len - n,
|
||||
"Extn [700-4.10]\t: LLOCK/SCOND %s, SWAPE %s, RTSC %s\n",
|
||||
IS_USED(CONFIG_ARC_HAS_LLSC),
|
||||
IS_USED(CONFIG_ARC_HAS_SWAPE),
|
||||
IS_USED(CONFIG_ARC_HAS_RTSC));
|
||||
}
|
||||
|
||||
n += scnprintf(buf + n, len - n, "Extn [CCM]\t: %s",
|
||||
!(cpu->dccm.sz || cpu->iccm.sz) ? "N/A" : "");
|
||||
|
||||
if (cpu->dccm.sz)
|
||||
n += scnprintf(buf + n, len - n, "DCCM: @ %x, %d KB ",
|
||||
cpu->dccm.base_addr, TO_KB(cpu->dccm.sz));
|
||||
|
||||
if (cpu->iccm.sz)
|
||||
n += scnprintf(buf + n, len - n, "ICCM: @ %x, %d KB",
|
||||
if (cpu->dccm.sz || cpu->iccm.sz)
|
||||
n += scnprintf(buf + n, len - n, "Extn [CCM]\t: DCCM @ %x, %d KB / ICCM: @ %x, %d KB\n",
|
||||
cpu->dccm.base_addr, TO_KB(cpu->dccm.sz),
|
||||
cpu->iccm.base_addr, TO_KB(cpu->iccm.sz));
|
||||
|
||||
n += scnprintf(buf + n, len - n, "\nExtn [FPU]\t: %s",
|
||||
!(cpu->fp.ver || cpu->dpfp.ver) ? "N/A" : "");
|
||||
|
||||
if (cpu->fp.ver)
|
||||
n += scnprintf(buf + n, len - n, "SP [v%d] %s",
|
||||
cpu->fp.ver, cpu->fp.fast ? "(fast)" : "");
|
||||
|
||||
if (cpu->dpfp.ver)
|
||||
n += scnprintf(buf + n, len - n, "DP [v%d] %s",
|
||||
cpu->dpfp.ver, cpu->dpfp.fast ? "(fast)" : "");
|
||||
|
||||
n += scnprintf(buf + n, len - n, "\n");
|
||||
|
||||
n += scnprintf(buf + n, len - n,
|
||||
"OS ABI [v3]\t: no-legacy-syscalls\n");
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void arc_chk_ccms(void)
|
||||
static void arc_chk_core_config(void)
|
||||
{
|
||||
#if defined(CONFIG_ARC_HAS_DCCM) || defined(CONFIG_ARC_HAS_ICCM)
|
||||
struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
|
||||
int fpu_enabled;
|
||||
|
||||
if (!cpu->timers.t0)
|
||||
panic("Timer0 is not present!\n");
|
||||
|
||||
if (!cpu->timers.t1)
|
||||
panic("Timer1 is not present!\n");
|
||||
|
||||
if (IS_ENABLED(CONFIG_ARC_HAS_RTSC) && !cpu->timers.rtsc)
|
||||
panic("RTSC is not present\n");
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_DCCM
|
||||
/*
|
||||
|
@ -256,33 +270,20 @@ static void arc_chk_ccms(void)
|
|||
if (CONFIG_ARC_ICCM_SZ != cpu->iccm.sz)
|
||||
panic("Linux built with incorrect ICCM Size\n");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that FP hardware and kernel config match
|
||||
* -If hardware contains DPFP, kernel needs to save/restore FPU state
|
||||
* across context switches
|
||||
* -If hardware lacks DPFP, but kernel configured to save FPU state then
|
||||
* kernel trying to access non-existant DPFP regs will crash
|
||||
*
|
||||
* We only check for Dbl precision Floating Point, because only DPFP
|
||||
* hardware has dedicated regs which need to be saved/restored on ctx-sw
|
||||
* (Single Precision uses core regs), thus kernel is kind of oblivious to it
|
||||
*/
|
||||
static void arc_chk_fpu(void)
|
||||
{
|
||||
struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
|
||||
/*
|
||||
* FP hardware/software config sanity
|
||||
* -If hardware contains DPFP, kernel needs to save/restore FPU state
|
||||
* -If not, it will crash trying to save/restore the non-existant regs
|
||||
*
|
||||
* (only DPDP checked since SP has no arch visible regs)
|
||||
*/
|
||||
fpu_enabled = IS_ENABLED(CONFIG_ARC_FPU_SAVE_RESTORE);
|
||||
|
||||
if (cpu->dpfp.ver) {
|
||||
#ifndef CONFIG_ARC_FPU_SAVE_RESTORE
|
||||
pr_warn("DPFP support broken in this kernel...\n");
|
||||
#endif
|
||||
} else {
|
||||
#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
|
||||
panic("H/w lacks DPFP support, apps won't work\n");
|
||||
#endif
|
||||
}
|
||||
if (cpu->extn.fpu_dp && !fpu_enabled)
|
||||
pr_warn("CONFIG_ARC_FPU_SAVE_RESTORE needed for working apps\n");
|
||||
else if (!cpu->extn.fpu_dp && fpu_enabled)
|
||||
panic("FPU non-existent, disable CONFIG_ARC_FPU_SAVE_RESTORE\n");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -303,15 +304,11 @@ void setup_processor(void)
|
|||
|
||||
arc_mmu_init();
|
||||
arc_cache_init();
|
||||
arc_chk_ccms();
|
||||
|
||||
printk(arc_extn_mumbojumbo(cpu_id, str, sizeof(str)));
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
printk(arc_platform_smp_cpuinfo());
|
||||
#endif
|
||||
|
||||
arc_chk_fpu();
|
||||
arc_chk_core_config();
|
||||
}
|
||||
|
||||
static inline int is_kernel(unsigned long addr)
|
||||
|
@ -360,11 +357,7 @@ void __init setup_arch(char **cmdline_p)
|
|||
machine_desc->init_early();
|
||||
|
||||
setup_processor();
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
smp_init_cpus();
|
||||
#endif
|
||||
|
||||
setup_arch_memory();
|
||||
|
||||
/* copy flat DT out of .init and then unflatten it */
|
||||
|
@ -385,7 +378,13 @@ void __init setup_arch(char **cmdline_p)
|
|||
|
||||
static int __init customize_machine(void)
|
||||
{
|
||||
/* Add platform devices */
|
||||
of_clk_init(NULL);
|
||||
/*
|
||||
* Traverses flattened DeviceTree - registering platform devices
|
||||
* (if any) complete with their resources
|
||||
*/
|
||||
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
||||
|
||||
if (machine_desc->init_machine)
|
||||
machine_desc->init_machine();
|
||||
|
||||
|
@ -419,19 +418,14 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||
|
||||
seq_printf(m, arc_cpu_mumbojumbo(cpu_id, str, PAGE_SIZE));
|
||||
|
||||
seq_printf(m, "Bogo MIPS : \t%lu.%02lu\n",
|
||||
seq_printf(m, "Bogo MIPS\t: %lu.%02lu\n",
|
||||
loops_per_jiffy / (500000 / HZ),
|
||||
(loops_per_jiffy / (5000 / HZ)) % 100);
|
||||
|
||||
seq_printf(m, arc_mmu_mumbojumbo(cpu_id, str, PAGE_SIZE));
|
||||
|
||||
seq_printf(m, arc_cache_mumbojumbo(cpu_id, str, PAGE_SIZE));
|
||||
|
||||
seq_printf(m, arc_extn_mumbojumbo(cpu_id, str, PAGE_SIZE));
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
seq_printf(m, arc_platform_smp_cpuinfo());
|
||||
#endif
|
||||
|
||||
free_page((unsigned long)str);
|
||||
done:
|
||||
|
|
|
@ -101,7 +101,7 @@ void __weak arc_platform_smp_wait_to_boot(int cpu)
|
|||
|
||||
const char *arc_platform_smp_cpuinfo(void)
|
||||
{
|
||||
return plat_smp_ops.info;
|
||||
return plat_smp_ops.info ? : "";
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -530,16 +530,9 @@ EXPORT_SYMBOL(dma_cache_wback);
|
|||
*/
|
||||
void flush_icache_range(unsigned long kstart, unsigned long kend)
|
||||
{
|
||||
unsigned int tot_sz, off, sz;
|
||||
unsigned long phy, pfn;
|
||||
unsigned int tot_sz;
|
||||
|
||||
/* printk("Kernel Cache Cohenercy: %lx to %lx\n",kstart, kend); */
|
||||
|
||||
/* This is not the right API for user virtual address */
|
||||
if (kstart < TASK_SIZE) {
|
||||
BUG_ON("Flush icache range for user virtual addr space");
|
||||
return;
|
||||
}
|
||||
WARN(kstart < TASK_SIZE, "%s() can't handle user vaddr", __func__);
|
||||
|
||||
/* Shortcut for bigger flush ranges.
|
||||
* Here we don't care if this was kernel virtual or phy addr
|
||||
|
@ -572,6 +565,9 @@ void flush_icache_range(unsigned long kstart, unsigned long kend)
|
|||
* straddles across 2 virtual pages and hence need for loop
|
||||
*/
|
||||
while (tot_sz > 0) {
|
||||
unsigned int off, sz;
|
||||
unsigned long phy, pfn;
|
||||
|
||||
off = kstart % PAGE_SIZE;
|
||||
pfn = vmalloc_to_pfn((void *)kstart);
|
||||
phy = (pfn << PAGE_SHIFT) + off;
|
||||
|
|
|
@ -609,14 +609,12 @@ char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len)
|
|||
int n = 0;
|
||||
struct cpuinfo_arc_mmu *p_mmu = &cpuinfo_arc700[cpu_id].mmu;
|
||||
|
||||
n += scnprintf(buf + n, len - n, "ARC700 MMU [v%x]\t: %dk PAGE, ",
|
||||
p_mmu->ver, TO_KB(p_mmu->pg_sz));
|
||||
|
||||
n += scnprintf(buf + n, len - n,
|
||||
"J-TLB %d (%dx%d), uDTLB %d, uITLB %d, %s\n",
|
||||
"MMU [v%x]\t: %dk PAGE, JTLB %d (%dx%d), uDTLB %d, uITLB %d %s\n",
|
||||
p_mmu->ver, TO_KB(p_mmu->pg_sz),
|
||||
p_mmu->num_tlb, p_mmu->sets, p_mmu->ways,
|
||||
p_mmu->u_dtlb, p_mmu->u_itlb,
|
||||
IS_ENABLED(CONFIG_ARC_MMU_SASID) ? "SASID" : "");
|
||||
IS_ENABLED(CONFIG_ARC_MMU_SASID) ? ",SASID" : "");
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
menuconfig ARC_PLAT_FPGA_LEGACY
|
||||
bool "\"Legacy\" ARC FPGA dev Boards"
|
||||
select ISS_SMP_EXTN if SMP
|
||||
select ARC_HAS_COH_CACHES if SMP
|
||||
help
|
||||
Support for ARC development boards, provided by Synopsys.
|
||||
These are based on FPGA or ISS. e.g.
|
||||
|
@ -18,17 +18,6 @@ menuconfig ARC_PLAT_FPGA_LEGACY
|
|||
|
||||
if ARC_PLAT_FPGA_LEGACY
|
||||
|
||||
config ARC_BOARD_ANGEL4
|
||||
bool "ARC Angel4"
|
||||
default y
|
||||
help
|
||||
ARC Angel4 FPGA Ref Platform (Xilinx Virtex Based)
|
||||
|
||||
config ARC_BOARD_ML509
|
||||
bool "ML509"
|
||||
help
|
||||
ARC ML509 FPGA Ref Platform (Xilinx Virtex-5 Based)
|
||||
|
||||
config ISS_SMP_EXTN
|
||||
bool "ARC SMP Extensions (ISS Models only)"
|
||||
default n
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* vineetg: Feb 2009
|
||||
* -For AA4 board, IRQ assignments to peripherals
|
||||
*/
|
||||
|
||||
#ifndef __PLAT_IRQ_H
|
||||
#define __PLAT_IRQ_H
|
||||
|
||||
#define UART0_IRQ 5
|
||||
#define UART1_IRQ 10
|
||||
#define UART2_IRQ 11
|
||||
|
||||
#define IDE_IRQ 13
|
||||
#define PCI_IRQ 14
|
||||
#define PS2_IRQ 15
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define IDU_INTERRUPT_0 16
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* vineetg: Feb 2009
|
||||
* -For AA4 board, System Memory Map for Peripherals etc
|
||||
*/
|
||||
|
||||
#ifndef __PLAT_MEMMAP_H
|
||||
#define __PLAT_MEMMAP_H
|
||||
|
||||
#define UART0_BASE 0xC0FC1000
|
||||
#define UART1_BASE 0xC0FC1100
|
||||
|
||||
#define IDE_CONTROLLER_BASE 0xC0FC9000
|
||||
|
||||
#define AHB_PCI_HOST_BRG_BASE 0xC0FD0000
|
||||
|
||||
#define PGU_BASEADDR 0xC0FC8000
|
||||
#define VLCK_ADDR 0xC0FCF028
|
||||
|
||||
#define BVCI_LAT_UNIT_BASE 0xC0FED000
|
||||
|
||||
#define PS2_BASE_ADDR 0xC0FCC000
|
||||
|
||||
#endif
|
|
@ -8,37 +8,9 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/clk.h>
|
||||
#include <asm/mach_desc.h>
|
||||
#include <plat/memmap.h>
|
||||
#include <plat/smp.h>
|
||||
#include <plat/irq.h>
|
||||
|
||||
static void __init plat_fpga_early_init(void)
|
||||
{
|
||||
pr_info("[plat-arcfpga]: registering early dev resources\n");
|
||||
|
||||
#ifdef CONFIG_ISS_SMP_EXTN
|
||||
iss_model_init_early_smp();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __init plat_fpga_populate_dev(void)
|
||||
{
|
||||
/*
|
||||
* Traverses flattened DeviceTree - registering platform devices
|
||||
* (if any) complete with their resources
|
||||
*/
|
||||
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
||||
}
|
||||
|
||||
/*----------------------- Machine Descriptions ------------------------------
|
||||
*
|
||||
|
@ -48,41 +20,26 @@ static void __init plat_fpga_populate_dev(void)
|
|||
* callback set, by matching the DT compatible name.
|
||||
*/
|
||||
|
||||
static const char *aa4_compat[] __initconst = {
|
||||
static const char *legacy_fpga_compat[] __initconst = {
|
||||
"snps,arc-angel4",
|
||||
NULL,
|
||||
};
|
||||
|
||||
MACHINE_START(ANGEL4, "angel4")
|
||||
.dt_compat = aa4_compat,
|
||||
.init_early = plat_fpga_early_init,
|
||||
.init_machine = plat_fpga_populate_dev,
|
||||
#ifdef CONFIG_ISS_SMP_EXTN
|
||||
.init_smp = iss_model_init_smp,
|
||||
#endif
|
||||
MACHINE_END
|
||||
|
||||
static const char *ml509_compat[] __initconst = {
|
||||
"snps,arc-ml509",
|
||||
NULL,
|
||||
};
|
||||
|
||||
MACHINE_START(ML509, "ml509")
|
||||
.dt_compat = ml509_compat,
|
||||
.init_early = plat_fpga_early_init,
|
||||
.init_machine = plat_fpga_populate_dev,
|
||||
#ifdef CONFIG_SMP
|
||||
MACHINE_START(LEGACY_FPGA, "legacy_fpga")
|
||||
.dt_compat = legacy_fpga_compat,
|
||||
#ifdef CONFIG_ISS_SMP_EXTN
|
||||
.init_early = iss_model_init_early_smp,
|
||||
.init_smp = iss_model_init_smp,
|
||||
#endif
|
||||
MACHINE_END
|
||||
|
||||
static const char *nsimosci_compat[] __initconst = {
|
||||
static const char *simulation_compat[] __initconst = {
|
||||
"snps,nsim",
|
||||
"snps,nsimosci",
|
||||
NULL,
|
||||
};
|
||||
|
||||
MACHINE_START(NSIMOSCI, "nsimosci")
|
||||
.dt_compat = nsimosci_compat,
|
||||
.init_early = NULL,
|
||||
.init_machine = plat_fpga_populate_dev,
|
||||
MACHINE_START(SIMULATION, "simulation")
|
||||
.dt_compat = simulation_compat,
|
||||
MACHINE_END
|
||||
|
|
|
@ -13,9 +13,10 @@
|
|||
|
||||
#include <linux/smp.h>
|
||||
#include <linux/irq.h>
|
||||
#include <plat/irq.h>
|
||||
#include <plat/smp.h>
|
||||
|
||||
#define IDU_INTERRUPT_0 16
|
||||
|
||||
static char smp_cpuinfo_buf[128];
|
||||
|
||||
/*
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
menuconfig ARC_PLAT_TB10X
|
||||
bool "Abilis TB10x"
|
||||
select COMMON_CLK
|
||||
select PINCTRL
|
||||
select PINCTRL_TB10X
|
||||
select PINMUX
|
||||
|
|
|
@ -19,21 +19,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
#include <asm/mach_desc.h>
|
||||
|
||||
|
||||
static void __init tb10x_platform_init(void)
|
||||
{
|
||||
of_clk_init(NULL);
|
||||
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
||||
}
|
||||
|
||||
static const char *tb10x_compat[] __initdata = {
|
||||
"abilis,arc-tb10x",
|
||||
NULL,
|
||||
|
@ -41,5 +29,4 @@ static const char *tb10x_compat[] __initdata = {
|
|||
|
||||
MACHINE_START(TB10x, "tb10x")
|
||||
.dt_compat = tb10x_compat,
|
||||
.init_machine = tb10x_platform_init,
|
||||
MACHINE_END
|
||||
|
|
|
@ -122,9 +122,10 @@
|
|||
interrupts-extended = <&pmc AT91_PMC_LOCKB>;
|
||||
clocks = <&main>;
|
||||
reg = <1>;
|
||||
atmel,clk-input-range = <1000000 5000000>;
|
||||
atmel,clk-input-range = <1000000 32000000>;
|
||||
#atmel,pll-clk-output-range-cells = <4>;
|
||||
atmel,pll-clk-output-ranges = <70000000 130000000 1 1>;
|
||||
atmel,pll-clk-output-ranges = <80000000 200000000 0 1>,
|
||||
<190000000 240000000 2 1>;
|
||||
};
|
||||
|
||||
mck: masterck {
|
||||
|
|
|
@ -193,7 +193,6 @@
|
|||
i2c0: i2c@80058000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c0_pins_a>;
|
||||
clock-frequency = <400000>;
|
||||
status = "okay";
|
||||
|
||||
sgtl5000: codec@0a {
|
||||
|
|
|
@ -547,7 +547,7 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio@ff708000 {
|
||||
gpio0: gpio@ff708000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "snps,dw-apb-gpio";
|
||||
|
@ -555,7 +555,7 @@
|
|||
clocks = <&per_base_clk>;
|
||||
status = "disabled";
|
||||
|
||||
gpio0: gpio-controller@0 {
|
||||
porta: gpio-controller@0 {
|
||||
compatible = "snps,dw-apb-gpio-port";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
@ -567,7 +567,7 @@
|
|||
};
|
||||
};
|
||||
|
||||
gpio@ff709000 {
|
||||
gpio1: gpio@ff709000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "snps,dw-apb-gpio";
|
||||
|
@ -575,7 +575,7 @@
|
|||
clocks = <&per_base_clk>;
|
||||
status = "disabled";
|
||||
|
||||
gpio1: gpio-controller@0 {
|
||||
portb: gpio-controller@0 {
|
||||
compatible = "snps,dw-apb-gpio-port";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
@ -587,7 +587,7 @@
|
|||
};
|
||||
};
|
||||
|
||||
gpio@ff70a000 {
|
||||
gpio2: gpio@ff70a000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "snps,dw-apb-gpio";
|
||||
|
@ -595,7 +595,7 @@
|
|||
clocks = <&per_base_clk>;
|
||||
status = "disabled";
|
||||
|
||||
gpio2: gpio-controller@0 {
|
||||
portc: gpio-controller@0 {
|
||||
compatible = "snps,dw-apb-gpio-port";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
};
|
||||
};
|
||||
|
||||
dwmmc0@ff704000 {
|
||||
mmc0: dwmmc0@ff704000 {
|
||||
num-slots = <1>;
|
||||
broken-cd;
|
||||
bus-width = <4>;
|
||||
|
|
|
@ -37,6 +37,13 @@
|
|||
*/
|
||||
ethernet0 = &gmac1;
|
||||
};
|
||||
|
||||
regulator_3_3v: 3-3-v-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "3.3V";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
};
|
||||
|
||||
&gmac1 {
|
||||
|
@ -68,6 +75,11 @@
|
|||
};
|
||||
};
|
||||
|
||||
&mmc0 {
|
||||
vmmc-supply = <®ulator_3_3v>;
|
||||
vqmmc-supply = <®ulator_3_3v>;
|
||||
};
|
||||
|
||||
&usb1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
|
|
@ -37,6 +37,13 @@
|
|||
*/
|
||||
ethernet0 = &gmac1;
|
||||
};
|
||||
|
||||
regulator_3_3v: 3-3-v-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "3.3V";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
};
|
||||
|
||||
&gmac1 {
|
||||
|
@ -53,6 +60,10 @@
|
|||
rxc-skew-ps = <2000>;
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
status = "okay";
|
||||
|
||||
|
@ -69,7 +80,9 @@
|
|||
};
|
||||
|
||||
&mmc0 {
|
||||
cd-gpios = <&gpio1 18 0>;
|
||||
cd-gpios = <&portb 18 0>;
|
||||
vmmc-supply = <®ulator_3_3v>;
|
||||
vqmmc-supply = <®ulator_3_3v>;
|
||||
};
|
||||
|
||||
&usb1 {
|
||||
|
|
|
@ -37,6 +37,13 @@
|
|||
*/
|
||||
ethernet0 = &gmac1;
|
||||
};
|
||||
|
||||
regulator_3_3v: vcc3p3-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "VCC3P3";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
};
|
||||
|
||||
&gmac1 {
|
||||
|
@ -53,6 +60,11 @@
|
|||
rxc-skew-ps = <2000>;
|
||||
};
|
||||
|
||||
&mmc0 {
|
||||
vmmc-supply = <®ulator_3_3v>;
|
||||
vqmmc-supply = <®ulator_3_3v>;
|
||||
};
|
||||
|
||||
&usb1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
/* kHz uV */
|
||||
666667 1000000
|
||||
333334 1000000
|
||||
222223 1000000
|
||||
>;
|
||||
};
|
||||
|
||||
|
@ -65,7 +64,7 @@
|
|||
interrupt-parent = <&intc>;
|
||||
ranges;
|
||||
|
||||
adc@f8007100 {
|
||||
adc: adc@f8007100 {
|
||||
compatible = "xlnx,zynq-xadc-1.00.a";
|
||||
reg = <0xf8007100 0x20>;
|
||||
interrupts = <0 7 4>;
|
||||
|
@ -137,7 +136,7 @@
|
|||
<0xF8F00100 0x100>;
|
||||
};
|
||||
|
||||
L2: cache-controller {
|
||||
L2: cache-controller@f8f02000 {
|
||||
compatible = "arm,pl310-cache";
|
||||
reg = <0xF8F02000 0x1000>;
|
||||
arm,data-latency = <3 2 2>;
|
||||
|
@ -146,10 +145,10 @@
|
|||
cache-level = <2>;
|
||||
};
|
||||
|
||||
memory-controller@f8006000 {
|
||||
mc: memory-controller@f8006000 {
|
||||
compatible = "xlnx,zynq-ddrc-a05";
|
||||
reg = <0xf8006000 0x1000>;
|
||||
} ;
|
||||
};
|
||||
|
||||
uart0: serial@e0000000 {
|
||||
compatible = "xlnx,xuartps", "cdns,uart-r1p8";
|
||||
|
@ -195,7 +194,7 @@
|
|||
|
||||
gem0: ethernet@e000b000 {
|
||||
compatible = "cdns,gem";
|
||||
reg = <0xe000b000 0x4000>;
|
||||
reg = <0xe000b000 0x1000>;
|
||||
status = "disabled";
|
||||
interrupts = <0 22 4>;
|
||||
clocks = <&clkc 30>, <&clkc 30>, <&clkc 13>;
|
||||
|
@ -206,7 +205,7 @@
|
|||
|
||||
gem1: ethernet@e000c000 {
|
||||
compatible = "cdns,gem";
|
||||
reg = <0xe000c000 0x4000>;
|
||||
reg = <0xe000c000 0x1000>;
|
||||
status = "disabled";
|
||||
interrupts = <0 45 4>;
|
||||
clocks = <&clkc 31>, <&clkc 31>, <&clkc 14>;
|
||||
|
@ -315,5 +314,16 @@
|
|||
reg = <0xf8f00600 0x20>;
|
||||
clocks = <&clkc 4>;
|
||||
};
|
||||
|
||||
watchdog0: watchdog@f8005000 {
|
||||
clocks = <&clkc 45>;
|
||||
compatible = "xlnx,zynq-wdt-r1p2";
|
||||
device_type = "watchdog";
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 9 1>;
|
||||
reg = <0xf8005000 0x1000>;
|
||||
reset = <0>;
|
||||
timeout-sec = <10>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -261,6 +261,7 @@ CONFIG_WATCHDOG=y
|
|||
CONFIG_XILINX_WATCHDOG=y
|
||||
CONFIG_ORION_WATCHDOG=y
|
||||
CONFIG_SUNXI_WATCHDOG=y
|
||||
CONFIG_MESON_WATCHDOG=y
|
||||
CONFIG_MFD_AS3722=y
|
||||
CONFIG_MFD_BCM590XX=y
|
||||
CONFIG_MFD_CROS_EC=y
|
||||
|
@ -353,6 +354,7 @@ CONFIG_MMC_MVSDIO=y
|
|||
CONFIG_MMC_SUNXI=y
|
||||
CONFIG_MMC_DW=y
|
||||
CONFIG_MMC_DW_EXYNOS=y
|
||||
CONFIG_MMC_DW_ROCKCHIP=y
|
||||
CONFIG_NEW_LEDS=y
|
||||
CONFIG_LEDS_CLASS=y
|
||||
CONFIG_LEDS_GPIO=y
|
||||
|
|
|
@ -76,6 +76,7 @@ CONFIG_WATCHDOG=y
|
|||
CONFIG_SUNXI_WATCHDOG=y
|
||||
CONFIG_MFD_AXP20X=y
|
||||
CONFIG_REGULATOR=y
|
||||
CONFIG_REGULATOR_FIXED_VOLTAGE=y
|
||||
CONFIG_REGULATOR_GPIO=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <linux/input.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/mailbox.h>
|
||||
#include <linux/pl320-ipc.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
|
|
@ -50,8 +50,8 @@ static const char *pcie_axi_sels[] = { "axi", "ahb", };
|
|||
static const char *ssi_sels[] = { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_audio_div", };
|
||||
static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
|
||||
static const char *enfc_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", };
|
||||
static const char *emi_sels[] = { "pll2_pfd2_396m", "pll3_usb_otg", "axi", "pll2_pfd0_352m", };
|
||||
static const char *emi_slow_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", };
|
||||
static const char *eim_sels[] = { "pll2_pfd2_396m", "pll3_usb_otg", "axi", "pll2_pfd0_352m", };
|
||||
static const char *eim_slow_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", };
|
||||
static const char *vdo_axi_sels[] = { "axi", "ahb", };
|
||||
static const char *vpu_axi_sels[] = { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m", };
|
||||
static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div",
|
||||
|
@ -302,8 +302,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
|
|||
clk[IMX6QDL_CLK_USDHC3_SEL] = imx_clk_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
|
||||
clk[IMX6QDL_CLK_USDHC4_SEL] = imx_clk_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
|
||||
clk[IMX6QDL_CLK_ENFC_SEL] = imx_clk_mux("enfc_sel", base + 0x2c, 16, 2, enfc_sels, ARRAY_SIZE(enfc_sels));
|
||||
clk[IMX6QDL_CLK_EMI_SEL] = imx_clk_fixup_mux("emi_sel", base + 0x1c, 27, 2, emi_sels, ARRAY_SIZE(emi_sels), imx_cscmr1_fixup);
|
||||
clk[IMX6QDL_CLK_EMI_SLOW_SEL] = imx_clk_fixup_mux("emi_slow_sel", base + 0x1c, 29, 2, emi_slow_sels, ARRAY_SIZE(emi_slow_sels), imx_cscmr1_fixup);
|
||||
clk[IMX6QDL_CLK_EIM_SEL] = imx_clk_fixup_mux("eim_sel", base + 0x1c, 27, 2, eim_sels, ARRAY_SIZE(eim_sels), imx_cscmr1_fixup);
|
||||
clk[IMX6QDL_CLK_EIM_SLOW_SEL] = imx_clk_fixup_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels, ARRAY_SIZE(eim_slow_sels), imx_cscmr1_fixup);
|
||||
clk[IMX6QDL_CLK_VDO_AXI_SEL] = imx_clk_mux("vdo_axi_sel", base + 0x18, 11, 1, vdo_axi_sels, ARRAY_SIZE(vdo_axi_sels));
|
||||
clk[IMX6QDL_CLK_VPU_AXI_SEL] = imx_clk_mux("vpu_axi_sel", base + 0x18, 14, 2, vpu_axi_sels, ARRAY_SIZE(vpu_axi_sels));
|
||||
clk[IMX6QDL_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", base + 0x60, 0, 4, cko1_sels, ARRAY_SIZE(cko1_sels));
|
||||
|
@ -354,8 +354,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
|
|||
clk[IMX6QDL_CLK_USDHC4_PODF] = imx_clk_divider("usdhc4_podf", "usdhc4_sel", base + 0x24, 22, 3);
|
||||
clk[IMX6QDL_CLK_ENFC_PRED] = imx_clk_divider("enfc_pred", "enfc_sel", base + 0x2c, 18, 3);
|
||||
clk[IMX6QDL_CLK_ENFC_PODF] = imx_clk_divider("enfc_podf", "enfc_pred", base + 0x2c, 21, 6);
|
||||
clk[IMX6QDL_CLK_EMI_PODF] = imx_clk_fixup_divider("emi_podf", "emi_sel", base + 0x1c, 20, 3, imx_cscmr1_fixup);
|
||||
clk[IMX6QDL_CLK_EMI_SLOW_PODF] = imx_clk_fixup_divider("emi_slow_podf", "emi_slow_sel", base + 0x1c, 23, 3, imx_cscmr1_fixup);
|
||||
clk[IMX6QDL_CLK_EIM_PODF] = imx_clk_fixup_divider("eim_podf", "eim_sel", base + 0x1c, 20, 3, imx_cscmr1_fixup);
|
||||
clk[IMX6QDL_CLK_EIM_SLOW_PODF] = imx_clk_fixup_divider("eim_slow_podf", "eim_slow_sel", base + 0x1c, 23, 3, imx_cscmr1_fixup);
|
||||
clk[IMX6QDL_CLK_VPU_AXI_PODF] = imx_clk_divider("vpu_axi_podf", "vpu_axi_sel", base + 0x24, 25, 3);
|
||||
clk[IMX6QDL_CLK_CKO1_PODF] = imx_clk_divider("cko1_podf", "cko1_sel", base + 0x60, 4, 3);
|
||||
clk[IMX6QDL_CLK_CKO2_PODF] = imx_clk_divider("cko2_podf", "cko2_sel", base + 0x60, 21, 3);
|
||||
|
@ -456,7 +456,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
|
|||
clk[IMX6QDL_CLK_USDHC2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4);
|
||||
clk[IMX6QDL_CLK_USDHC3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6);
|
||||
clk[IMX6QDL_CLK_USDHC4] = imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8);
|
||||
clk[IMX6QDL_CLK_EIM_SLOW] = imx_clk_gate2("eim_slow", "emi_slow_podf", base + 0x80, 10);
|
||||
clk[IMX6QDL_CLK_EIM_SLOW] = imx_clk_gate2("eim_slow", "eim_slow_podf", base + 0x80, 10);
|
||||
clk[IMX6QDL_CLK_VDO_AXI] = imx_clk_gate2("vdo_axi", "vdo_axi_sel", base + 0x80, 12);
|
||||
clk[IMX6QDL_CLK_VPU_AXI] = imx_clk_gate2("vpu_axi", "vpu_axi_podf", base + 0x80, 14);
|
||||
clk[IMX6QDL_CLK_CKO1] = imx_clk_gate("cko1", "cko1_podf", base + 0x60, 7);
|
||||
|
|
|
@ -40,7 +40,7 @@ extern void __iomem *rst_manager_base_addr;
|
|||
extern struct smp_operations socfpga_smp_ops;
|
||||
extern char secondary_trampoline, secondary_trampoline_end;
|
||||
|
||||
extern unsigned long cpu1start_addr;
|
||||
extern unsigned long socfpga_cpu1start_addr;
|
||||
|
||||
#define SOCFPGA_SCU_VIRT_BASE 0xfffec000
|
||||
|
||||
|
|
|
@ -9,21 +9,26 @@
|
|||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/memory.h>
|
||||
|
||||
.arch armv7-a
|
||||
|
||||
ENTRY(secondary_trampoline)
|
||||
movw r2, #:lower16:cpu1start_addr
|
||||
movt r2, #:upper16:cpu1start_addr
|
||||
|
||||
/* The socfpga VT cannot handle a 0xC0000000 page offset when loading
|
||||
the cpu1start_addr, we bit clear it. Tested on HW and VT. */
|
||||
bic r2, r2, #0x40000000
|
||||
|
||||
ldr r0, [r2]
|
||||
ldr r1, [r0]
|
||||
bx r1
|
||||
/* CPU1 will always fetch from 0x0 when it is brought out of reset.
|
||||
* Thus, we can just subtract the PAGE_OFFSET to get the physical
|
||||
* address of &cpu1start_addr. This would not work for platforms
|
||||
* where the physical memory does not start at 0x0.
|
||||
*/
|
||||
adr r0, 1f
|
||||
ldmia r0, {r1, r2}
|
||||
sub r2, r2, #PAGE_OFFSET
|
||||
ldr r3, [r2]
|
||||
ldr r4, [r3]
|
||||
bx r4
|
||||
|
||||
.align
|
||||
1: .long .
|
||||
.long socfpga_cpu1start_addr
|
||||
ENTRY(secondary_trampoline_end)
|
||||
|
||||
ENTRY(socfpga_secondary_startup)
|
||||
|
|
|
@ -33,11 +33,11 @@ static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|||
{
|
||||
int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
|
||||
|
||||
if (cpu1start_addr) {
|
||||
if (socfpga_cpu1start_addr) {
|
||||
memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
|
||||
|
||||
__raw_writel(virt_to_phys(socfpga_secondary_startup),
|
||||
(sys_manager_base_addr + (cpu1start_addr & 0x000000ff)));
|
||||
(sys_manager_base_addr + (socfpga_cpu1start_addr & 0x000000ff)));
|
||||
|
||||
flush_cache_all();
|
||||
smp_wmb();
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
|
||||
void __iomem *sys_manager_base_addr;
|
||||
void __iomem *rst_manager_base_addr;
|
||||
unsigned long cpu1start_addr;
|
||||
unsigned long socfpga_cpu1start_addr;
|
||||
|
||||
static struct map_desc scu_io_desc __initdata = {
|
||||
.virtual = SOCFPGA_SCU_VIRT_BASE,
|
||||
|
@ -70,7 +70,7 @@ void __init socfpga_sysmgr_init(void)
|
|||
np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr");
|
||||
|
||||
if (of_property_read_u32(np, "cpu1-start-addr",
|
||||
(u32 *) &cpu1start_addr))
|
||||
(u32 *) &socfpga_cpu1start_addr))
|
||||
pr_err("SMP: Need cpu1-start-addr in device tree.\n");
|
||||
|
||||
sys_manager_base_addr = of_iomap(np, 0);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
config ARM64
|
||||
def_bool y
|
||||
select ARCH_BINFMT_ELF_RANDOMIZE_PIE
|
||||
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
|
||||
select ARCH_HAS_SG_CHAIN
|
||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||
|
@ -232,7 +233,7 @@ config ARM64_VA_BITS_42
|
|||
|
||||
config ARM64_VA_BITS_48
|
||||
bool "48-bit"
|
||||
depends on BROKEN
|
||||
depends on !ARM_SMMU
|
||||
|
||||
endchoice
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
bank-width = <4>;
|
||||
};
|
||||
|
||||
vram@2,00000000 {
|
||||
v2m_video_ram: vram@2,00000000 {
|
||||
compatible = "arm,vexpress-vram";
|
||||
reg = <2 0x00000000 0x00800000>;
|
||||
};
|
||||
|
@ -179,9 +179,42 @@
|
|||
clcd@1f0000 {
|
||||
compatible = "arm,pl111", "arm,primecell";
|
||||
reg = <0x1f0000 0x1000>;
|
||||
interrupt-names = "combined";
|
||||
interrupts = <14>;
|
||||
clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>;
|
||||
clock-names = "clcdclk", "apb_pclk";
|
||||
arm,pl11x,framebuffer = <0x18000000 0x00180000>;
|
||||
memory-region = <&v2m_video_ram>;
|
||||
max-memory-bandwidth = <130000000>; /* 16bpp @ 63.5MHz */
|
||||
|
||||
port {
|
||||
v2m_clcd_pads: endpoint {
|
||||
remote-endpoint = <&v2m_clcd_panel>;
|
||||
arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
|
||||
};
|
||||
};
|
||||
|
||||
panel {
|
||||
compatible = "panel-dpi";
|
||||
|
||||
port {
|
||||
v2m_clcd_panel: endpoint {
|
||||
remote-endpoint = <&v2m_clcd_pads>;
|
||||
};
|
||||
};
|
||||
|
||||
panel-timing {
|
||||
clock-frequency = <63500127>;
|
||||
hactive = <1024>;
|
||||
hback-porch = <152>;
|
||||
hfront-porch = <48>;
|
||||
hsync-len = <104>;
|
||||
vactive = <768>;
|
||||
vback-porch = <23>;
|
||||
vfront-porch = <3>;
|
||||
vsync-len = <4>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
virtio_block@0130000 {
|
||||
|
|
|
@ -78,6 +78,7 @@ CONFIG_NET_XGENE=y
|
|||
# CONFIG_WLAN is not set
|
||||
CONFIG_INPUT_EVDEV=y
|
||||
# CONFIG_SERIO_SERPORT is not set
|
||||
CONFIG_SERIO_AMBAKMI=y
|
||||
CONFIG_LEGACY_PTY_COUNT=16
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
|
@ -90,6 +91,7 @@ CONFIG_VIRTIO_CONSOLE=y
|
|||
CONFIG_REGULATOR=y
|
||||
CONFIG_REGULATOR_FIXED_VOLTAGE=y
|
||||
CONFIG_FB=y
|
||||
CONFIG_FB_ARMCLCD=y
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
CONFIG_LOGO=y
|
||||
# CONFIG_LOGO_LINUX_MONO is not set
|
||||
|
|
|
@ -37,8 +37,8 @@ typedef s32 compat_ssize_t;
|
|||
typedef s32 compat_time_t;
|
||||
typedef s32 compat_clock_t;
|
||||
typedef s32 compat_pid_t;
|
||||
typedef u32 __compat_uid_t;
|
||||
typedef u32 __compat_gid_t;
|
||||
typedef u16 __compat_uid_t;
|
||||
typedef u16 __compat_gid_t;
|
||||
typedef u16 __compat_uid16_t;
|
||||
typedef u16 __compat_gid16_t;
|
||||
typedef u32 __compat_uid32_t;
|
||||
|
|
|
@ -126,7 +126,7 @@ typedef struct user_fpsimd_state elf_fpregset_t;
|
|||
* that it will "exec", and that there is sufficient room for the brk.
|
||||
*/
|
||||
extern unsigned long randomize_et_dyn(unsigned long base);
|
||||
#define ELF_ET_DYN_BASE (randomize_et_dyn(2 * TASK_SIZE_64 / 3))
|
||||
#define ELF_ET_DYN_BASE (2 * TASK_SIZE_64 / 3)
|
||||
|
||||
/*
|
||||
* When the program starts, a1 contains a pointer to a function to be
|
||||
|
@ -169,7 +169,7 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm);
|
|||
#define COMPAT_ELF_PLATFORM ("v8l")
|
||||
#endif
|
||||
|
||||
#define COMPAT_ELF_ET_DYN_BASE (randomize_et_dyn(2 * TASK_SIZE_32 / 3))
|
||||
#define COMPAT_ELF_ET_DYN_BASE (2 * TASK_SIZE_32 / 3)
|
||||
|
||||
/* AArch32 registers. */
|
||||
#define COMPAT_ELF_NGREG 18
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef __ASM_IRQ_WORK_H
|
||||
#define __ASM_IRQ_WORK_H
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
#include <asm/smp.h>
|
||||
|
||||
static inline bool arch_irq_work_has_interrupt(void)
|
||||
|
@ -8,4 +10,13 @@ static inline bool arch_irq_work_has_interrupt(void)
|
|||
return !!__smp_cross_call;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline bool arch_irq_work_has_interrupt(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_IRQ_WORK_H */
|
||||
|
|
|
@ -89,7 +89,8 @@ static int __init uefi_init(void)
|
|||
*/
|
||||
if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
|
||||
pr_err("System table signature incorrect\n");
|
||||
return -EINVAL;
|
||||
retval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if ((efi.systab->hdr.revision >> 16) < 2)
|
||||
pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
|
||||
|
@ -103,6 +104,7 @@ static int __init uefi_init(void)
|
|||
for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
|
||||
vendor[i] = c16[i];
|
||||
vendor[i] = '\0';
|
||||
early_memunmap(c16, sizeof(vendor));
|
||||
}
|
||||
|
||||
pr_info("EFI v%u.%.02u by %s\n",
|
||||
|
@ -113,29 +115,11 @@ static int __init uefi_init(void)
|
|||
if (retval == 0)
|
||||
set_bit(EFI_CONFIG_TABLES, &efi.flags);
|
||||
|
||||
early_memunmap(c16, sizeof(vendor));
|
||||
out:
|
||||
early_memunmap(efi.systab, sizeof(efi_system_table_t));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static __initdata char memory_type_name[][32] = {
|
||||
{"Reserved"},
|
||||
{"Loader Code"},
|
||||
{"Loader Data"},
|
||||
{"Boot Code"},
|
||||
{"Boot Data"},
|
||||
{"Runtime Code"},
|
||||
{"Runtime Data"},
|
||||
{"Conventional Memory"},
|
||||
{"Unusable Memory"},
|
||||
{"ACPI Reclaim Memory"},
|
||||
{"ACPI Memory NVS"},
|
||||
{"Memory Mapped I/O"},
|
||||
{"MMIO Port Space"},
|
||||
{"PAL Code"},
|
||||
};
|
||||
|
||||
/*
|
||||
* Return true for RAM regions we want to permanently reserve.
|
||||
*/
|
||||
|
@ -166,10 +150,13 @@ static __init void reserve_regions(void)
|
|||
paddr = md->phys_addr;
|
||||
npages = md->num_pages;
|
||||
|
||||
if (uefi_debug)
|
||||
pr_info(" 0x%012llx-0x%012llx [%s]",
|
||||
if (uefi_debug) {
|
||||
char buf[64];
|
||||
|
||||
pr_info(" 0x%012llx-0x%012llx %s",
|
||||
paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
|
||||
memory_type_name[md->type]);
|
||||
efi_md_typeattr_format(buf, sizeof(buf), md));
|
||||
}
|
||||
|
||||
memrange_efi_to_native(&paddr, &npages);
|
||||
size = npages << PAGE_SHIFT;
|
||||
|
@ -393,11 +380,16 @@ static int __init arm64_enter_virtual_mode(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
pr_info("Remapping and enabling EFI services.\n");
|
||||
|
||||
/* replace early memmap mapping with permanent mapping */
|
||||
mapsize = memmap.map_end - memmap.map;
|
||||
early_memunmap(memmap.map, mapsize);
|
||||
|
||||
if (efi_runtime_disabled()) {
|
||||
pr_info("EFI runtime services will be disabled.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pr_info("Remapping and enabling EFI services.\n");
|
||||
/* replace early memmap mapping with permanent mapping */
|
||||
memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map,
|
||||
mapsize);
|
||||
memmap.map_end = memmap.map + mapsize;
|
||||
|
|
|
@ -378,8 +378,3 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
|
|||
{
|
||||
return randomize_base(mm->brk);
|
||||
}
|
||||
|
||||
unsigned long randomize_et_dyn(unsigned long base)
|
||||
{
|
||||
return randomize_base(base);
|
||||
}
|
||||
|
|
|
@ -105,10 +105,10 @@ EXPORT_SYMBOL(ioremap_cache);
|
|||
|
||||
static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
|
||||
#if CONFIG_ARM64_PGTABLE_LEVELS > 2
|
||||
static pte_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss;
|
||||
static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss;
|
||||
#endif
|
||||
#if CONFIG_ARM64_PGTABLE_LEVELS > 3
|
||||
static pte_t bm_pud[PTRS_PER_PUD] __page_aligned_bss;
|
||||
static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss;
|
||||
#endif
|
||||
|
||||
static inline pud_t * __init early_ioremap_pud(unsigned long addr)
|
||||
|
|
|
@ -297,11 +297,15 @@ static void __init map_mem(void)
|
|||
* create_mapping requires puds, pmds and ptes to be allocated from
|
||||
* memory addressable from the initial direct kernel mapping.
|
||||
*
|
||||
* The initial direct kernel mapping, located at swapper_pg_dir,
|
||||
* gives us PUD_SIZE memory starting from PHYS_OFFSET (which must be
|
||||
* aligned to 2MB as per Documentation/arm64/booting.txt).
|
||||
* The initial direct kernel mapping, located at swapper_pg_dir, gives
|
||||
* us PUD_SIZE (4K pages) or PMD_SIZE (64K pages) memory starting from
|
||||
* PHYS_OFFSET (which must be aligned to 2MB as per
|
||||
* Documentation/arm64/booting.txt).
|
||||
*/
|
||||
limit = PHYS_OFFSET + PUD_SIZE;
|
||||
if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
|
||||
limit = PHYS_OFFSET + PMD_SIZE;
|
||||
else
|
||||
limit = PHYS_OFFSET + PUD_SIZE;
|
||||
memblock_set_current_limit(limit);
|
||||
|
||||
/* map all the memory banks */
|
||||
|
|
|
@ -30,12 +30,14 @@
|
|||
|
||||
#define PGD_SIZE (PTRS_PER_PGD * sizeof(pgd_t))
|
||||
|
||||
static struct kmem_cache *pgd_cache;
|
||||
|
||||
pgd_t *pgd_alloc(struct mm_struct *mm)
|
||||
{
|
||||
if (PGD_SIZE == PAGE_SIZE)
|
||||
return (pgd_t *)get_zeroed_page(GFP_KERNEL);
|
||||
else
|
||||
return kzalloc(PGD_SIZE, GFP_KERNEL);
|
||||
return kmem_cache_zalloc(pgd_cache, GFP_KERNEL);
|
||||
}
|
||||
|
||||
void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
||||
|
@ -43,5 +45,17 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
|||
if (PGD_SIZE == PAGE_SIZE)
|
||||
free_page((unsigned long)pgd);
|
||||
else
|
||||
kfree(pgd);
|
||||
kmem_cache_free(pgd_cache, pgd);
|
||||
}
|
||||
|
||||
static int __init pgd_cache_init(void)
|
||||
{
|
||||
/*
|
||||
* Naturally aligned pgds required by the architecture.
|
||||
*/
|
||||
if (PGD_SIZE != PAGE_SIZE)
|
||||
pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE,
|
||||
SLAB_PANIC, NULL);
|
||||
return 0;
|
||||
}
|
||||
core_initcall(pgd_cache_init);
|
||||
|
|
|
@ -144,8 +144,12 @@
|
|||
|
||||
/* Data-processing (2 source) */
|
||||
/* Rd = Rn OP Rm */
|
||||
#define A64_UDIV(sf, Rd, Rn, Rm) aarch64_insn_gen_data2(Rd, Rn, Rm, \
|
||||
A64_VARIANT(sf), AARCH64_INSN_DATA2_UDIV)
|
||||
#define A64_DATA2(sf, Rd, Rn, Rm, type) aarch64_insn_gen_data2(Rd, Rn, Rm, \
|
||||
A64_VARIANT(sf), AARCH64_INSN_DATA2_##type)
|
||||
#define A64_UDIV(sf, Rd, Rn, Rm) A64_DATA2(sf, Rd, Rn, Rm, UDIV)
|
||||
#define A64_LSLV(sf, Rd, Rn, Rm) A64_DATA2(sf, Rd, Rn, Rm, LSLV)
|
||||
#define A64_LSRV(sf, Rd, Rn, Rm) A64_DATA2(sf, Rd, Rn, Rm, LSRV)
|
||||
#define A64_ASRV(sf, Rd, Rn, Rm) A64_DATA2(sf, Rd, Rn, Rm, ASRV)
|
||||
|
||||
/* Data-processing (3 source) */
|
||||
/* Rd = Ra + Rn * Rm */
|
||||
|
|
|
@ -19,12 +19,13 @@
|
|||
#define pr_fmt(fmt) "bpf_jit: " fmt
|
||||
|
||||
#include <linux/filter.h>
|
||||
#include <linux/moduleloader.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/debug-monitors.h>
|
||||
|
||||
#include "bpf_jit.h"
|
||||
|
||||
|
@ -119,6 +120,14 @@ static inline int bpf2a64_offset(int bpf_to, int bpf_from,
|
|||
return to - from;
|
||||
}
|
||||
|
||||
static void jit_fill_hole(void *area, unsigned int size)
|
||||
{
|
||||
u32 *ptr;
|
||||
/* We are guaranteed to have aligned memory. */
|
||||
for (ptr = area; size >= sizeof(u32); size -= sizeof(u32))
|
||||
*ptr++ = cpu_to_le32(AARCH64_BREAK_FAULT);
|
||||
}
|
||||
|
||||
static inline int epilogue_offset(const struct jit_ctx *ctx)
|
||||
{
|
||||
int to = ctx->offset[ctx->prog->len - 1];
|
||||
|
@ -196,6 +205,12 @@ static void build_epilogue(struct jit_ctx *ctx)
|
|||
emit(A64_RET(A64_LR), ctx);
|
||||
}
|
||||
|
||||
/* JITs an eBPF instruction.
|
||||
* Returns:
|
||||
* 0 - successfully JITed an 8-byte eBPF instruction.
|
||||
* >0 - successfully JITed a 16-byte eBPF instruction.
|
||||
* <0 - failed to JIT.
|
||||
*/
|
||||
static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
||||
{
|
||||
const u8 code = insn->code;
|
||||
|
@ -252,6 +267,18 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
|||
emit(A64_MUL(is64, tmp, tmp, src), ctx);
|
||||
emit(A64_SUB(is64, dst, dst, tmp), ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_LSH | BPF_X:
|
||||
case BPF_ALU64 | BPF_LSH | BPF_X:
|
||||
emit(A64_LSLV(is64, dst, dst, src), ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_RSH | BPF_X:
|
||||
case BPF_ALU64 | BPF_RSH | BPF_X:
|
||||
emit(A64_LSRV(is64, dst, dst, src), ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_ARSH | BPF_X:
|
||||
case BPF_ALU64 | BPF_ARSH | BPF_X:
|
||||
emit(A64_ASRV(is64, dst, dst, src), ctx);
|
||||
break;
|
||||
/* dst = -dst */
|
||||
case BPF_ALU | BPF_NEG:
|
||||
case BPF_ALU64 | BPF_NEG:
|
||||
|
@ -443,6 +470,27 @@ emit_cond_jmp:
|
|||
emit(A64_B(jmp_offset), ctx);
|
||||
break;
|
||||
|
||||
/* dst = imm64 */
|
||||
case BPF_LD | BPF_IMM | BPF_DW:
|
||||
{
|
||||
const struct bpf_insn insn1 = insn[1];
|
||||
u64 imm64;
|
||||
|
||||
if (insn1.code != 0 || insn1.src_reg != 0 ||
|
||||
insn1.dst_reg != 0 || insn1.off != 0) {
|
||||
/* Note: verifier in BPF core must catch invalid
|
||||
* instructions.
|
||||
*/
|
||||
pr_err_once("Invalid BPF_LD_IMM64 instruction\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
imm64 = (u64)insn1.imm << 32 | imm;
|
||||
emit_a64_mov_i64(dst, imm64, ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* LDX: dst = *(size *)(src + off) */
|
||||
case BPF_LDX | BPF_MEM | BPF_W:
|
||||
case BPF_LDX | BPF_MEM | BPF_H:
|
||||
|
@ -594,6 +642,10 @@ static int build_body(struct jit_ctx *ctx)
|
|||
ctx->offset[i] = ctx->idx;
|
||||
|
||||
ret = build_insn(insn, ctx);
|
||||
if (ret > 0) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -613,8 +665,10 @@ void bpf_jit_compile(struct bpf_prog *prog)
|
|||
|
||||
void bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
{
|
||||
struct bpf_binary_header *header;
|
||||
struct jit_ctx ctx;
|
||||
int image_size;
|
||||
u8 *image_ptr;
|
||||
|
||||
if (!bpf_jit_enable)
|
||||
return;
|
||||
|
@ -636,23 +690,25 @@ void bpf_int_jit_compile(struct bpf_prog *prog)
|
|||
goto out;
|
||||
|
||||
build_prologue(&ctx);
|
||||
|
||||
build_epilogue(&ctx);
|
||||
|
||||
/* Now we know the actual image size. */
|
||||
image_size = sizeof(u32) * ctx.idx;
|
||||
ctx.image = module_alloc(image_size);
|
||||
if (unlikely(ctx.image == NULL))
|
||||
header = bpf_jit_binary_alloc(image_size, &image_ptr,
|
||||
sizeof(u32), jit_fill_hole);
|
||||
if (header == NULL)
|
||||
goto out;
|
||||
|
||||
/* 2. Now, the actual pass. */
|
||||
|
||||
ctx.image = (u32 *)image_ptr;
|
||||
ctx.idx = 0;
|
||||
|
||||
build_prologue(&ctx);
|
||||
|
||||
ctx.body_offset = ctx.idx;
|
||||
if (build_body(&ctx)) {
|
||||
module_free(NULL, ctx.image);
|
||||
bpf_jit_binary_free(header);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -663,17 +719,25 @@ void bpf_int_jit_compile(struct bpf_prog *prog)
|
|||
bpf_jit_dump(prog->len, image_size, 2, ctx.image);
|
||||
|
||||
bpf_flush_icache(ctx.image, ctx.image + ctx.idx);
|
||||
prog->bpf_func = (void *)ctx.image;
|
||||
prog->jited = 1;
|
||||
|
||||
set_memory_ro((unsigned long)header, header->pages);
|
||||
prog->bpf_func = (void *)ctx.image;
|
||||
prog->jited = true;
|
||||
out:
|
||||
kfree(ctx.offset);
|
||||
}
|
||||
|
||||
void bpf_jit_free(struct bpf_prog *prog)
|
||||
{
|
||||
if (prog->jited)
|
||||
module_free(NULL, prog->bpf_func);
|
||||
unsigned long addr = (unsigned long)prog->bpf_func & PAGE_MASK;
|
||||
struct bpf_binary_header *header = (void *)addr;
|
||||
|
||||
kfree(prog);
|
||||
if (!prog->jited)
|
||||
goto free_filter;
|
||||
|
||||
set_memory_rw(addr, header->pages);
|
||||
bpf_jit_binary_free(header);
|
||||
|
||||
free_filter:
|
||||
bpf_prog_unlock_free(prog);
|
||||
}
|
||||
|
|
|
@ -568,6 +568,7 @@ efi_init (void)
|
|||
{
|
||||
const char *unit;
|
||||
unsigned long size;
|
||||
char buf[64];
|
||||
|
||||
md = p;
|
||||
size = md->num_pages << EFI_PAGE_SHIFT;
|
||||
|
@ -586,9 +587,10 @@ efi_init (void)
|
|||
unit = "KB";
|
||||
}
|
||||
|
||||
printk("mem%02d: type=%2u, attr=0x%016lx, "
|
||||
printk("mem%02d: %s "
|
||||
"range=[0x%016lx-0x%016lx) (%4lu%s)\n",
|
||||
i, md->type, md->attribute, md->phys_addr,
|
||||
i, efi_md_typeattr_format(buf, sizeof(buf), md),
|
||||
md->phys_addr,
|
||||
md->phys_addr + efi_md_size(md), size, unit);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2066,6 +2066,7 @@ config MIPS_CPS
|
|||
support is unavailable.
|
||||
|
||||
config MIPS_CPS_PM
|
||||
depends on MIPS_CPS
|
||||
select MIPS_CPC
|
||||
bool
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ static void __init db120_pci_init(u8 *eeprom)
|
|||
ath79_register_pci();
|
||||
}
|
||||
#else
|
||||
static inline void db120_pci_init(void) {}
|
||||
static inline void db120_pci_init(u8 *eeprom) {}
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
static void __init db120_setup(void)
|
||||
|
|
|
@ -806,15 +806,6 @@ void __init prom_init(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
if (octeon_is_simulation()) {
|
||||
/*
|
||||
* The simulator uses a mtdram device pre filled with
|
||||
* the filesystem. Also specify the calibration delay
|
||||
* to avoid calculating it every time.
|
||||
*/
|
||||
strcat(arcs_cmdline, " rw root=1f00 slram=root,0x40000000,+1073741824");
|
||||
}
|
||||
|
||||
mips_hpt_frequency = octeon_get_clock_rate();
|
||||
|
||||
octeon_init_cvmcount();
|
||||
|
|
|
@ -37,15 +37,15 @@ extern void nlm_cop2_restore(struct nlm_cop2_state *);
|
|||
|
||||
#define cop2_present 1
|
||||
#define cop2_lazy_restore 1
|
||||
#define cop2_save(r) do { (r); } while (0)
|
||||
#define cop2_restore(r) do { (r); } while (0)
|
||||
#define cop2_save(r) do { (void)(r); } while (0)
|
||||
#define cop2_restore(r) do { (void)(r); } while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define cop2_present 0
|
||||
#define cop2_lazy_restore 0
|
||||
#define cop2_save(r) do { (r); } while (0)
|
||||
#define cop2_restore(r) do { (r); } while (0)
|
||||
#define cop2_save(r) do { (void)(r); } while (0)
|
||||
#define cop2_restore(r) do { (void)(r); } while (0)
|
||||
#endif
|
||||
|
||||
enum cu2_ops {
|
||||
|
|
|
@ -24,7 +24,7 @@ do { \
|
|||
asm volatile ( \
|
||||
"1: " load " %[tmp_dst], 0(%[tmp_src])\n" \
|
||||
" li %[tmp_err], 0\n" \
|
||||
"2:\n" \
|
||||
"2: .insn\n" \
|
||||
\
|
||||
".section .fixup, \"ax\"\n" \
|
||||
"3: li %[tmp_err], 1\n" \
|
||||
|
@ -46,7 +46,7 @@ do { \
|
|||
asm volatile ( \
|
||||
"1: " store " %[tmp_src], 0(%[tmp_dst])\n"\
|
||||
" li %[tmp_err], 0\n" \
|
||||
"2:\n" \
|
||||
"2: .insn\n" \
|
||||
\
|
||||
".section .fixup, \"ax\"\n" \
|
||||
"3: li %[tmp_err], 1\n" \
|
||||
|
|
|
@ -8,19 +8,12 @@ extern void (*cpu_wait)(void);
|
|||
extern void r4k_wait(void);
|
||||
extern asmlinkage void __r4k_wait(void);
|
||||
extern void r4k_wait_irqoff(void);
|
||||
extern void __pastwait(void);
|
||||
|
||||
static inline int using_rollback_handler(void)
|
||||
{
|
||||
return cpu_wait == r4k_wait;
|
||||
}
|
||||
|
||||
static inline int address_is_in_r4k_wait_irqoff(unsigned long addr)
|
||||
{
|
||||
return addr >= (unsigned long)r4k_wait_irqoff &&
|
||||
addr < (unsigned long)__pastwait;
|
||||
}
|
||||
|
||||
extern int mips_cpuidle_wait_enter(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv, int index);
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#ifndef _UAPI_ASM_PTRACE_H
|
||||
#define _UAPI_ASM_PTRACE_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* 0 - 31 are integer registers, 32 - 63 are fp registers. */
|
||||
#define FPR_BASE 32
|
||||
#define PC 64
|
||||
|
|
|
@ -68,9 +68,6 @@ void r4k_wait_irqoff(void)
|
|||
" wait \n"
|
||||
" .set pop \n");
|
||||
local_irq_enable();
|
||||
__asm__(
|
||||
" .globl __pastwait \n"
|
||||
"__pastwait: \n");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -4,7 +4,7 @@ config PICVUE
|
|||
|
||||
config PICVUE_PROC
|
||||
tristate "PICVUE LCD display driver /proc interface"
|
||||
depends on PICVUE
|
||||
depends on PICVUE && PROC_FS
|
||||
|
||||
config DS1603
|
||||
bool "DS1603 RTC driver"
|
||||
|
|
|
@ -91,6 +91,7 @@ EXPORT_SYMBOL(clk_put);
|
|||
|
||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned int rate_khz = rate / 1000;
|
||||
struct cpufreq_frequency_table *pos;
|
||||
int ret = 0;
|
||||
int regval;
|
||||
|
@ -107,9 +108,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
|
|||
propagate_rate(clk);
|
||||
|
||||
cpufreq_for_each_valid_entry(pos, loongson2_clockmod_table)
|
||||
if (rate == pos->frequency)
|
||||
if (rate_khz == pos->frequency)
|
||||
break;
|
||||
if (rate != pos->frequency)
|
||||
if (rate_khz != pos->frequency)
|
||||
return -ENOTSUPP;
|
||||
|
||||
clk->rate = rate;
|
||||
|
|
|
@ -1023,7 +1023,7 @@ emul:
|
|||
goto emul;
|
||||
|
||||
case cop1x_op:
|
||||
if (cpu_has_mips_4_5 || cpu_has_mips64)
|
||||
if (cpu_has_mips_4_5 || cpu_has_mips64 || cpu_has_mips32r2)
|
||||
/* its one of ours */
|
||||
goto emul;
|
||||
|
||||
|
@ -1068,7 +1068,7 @@ emul:
|
|||
break;
|
||||
|
||||
case cop1x_op:
|
||||
if (!cpu_has_mips_4_5 && !cpu_has_mips64)
|
||||
if (!cpu_has_mips_4_5 && !cpu_has_mips64 && !cpu_has_mips32r2)
|
||||
return SIGILL;
|
||||
|
||||
sig = fpux_emu(xcp, ctx, ir, fault_addr);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче