Linux 3.18-rc2
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJUTYhlAAoJEHm+PkMAQRiG/0EIAIH7EnEdRojqYvnu0ndh3+vM exEd8X9gnHTx2u7nKR+6J1/c96pFMK2Ap9x0ucipnIpeB7mBdY3/tSAU1oyxdSrY IxbKb1wSpbvFP2gRUDeBpTWYLraYl0w5mNgbMKJ0Y3/52JtrHOKQmtHql3WTKtXu x9S3cp5M6KJmqbPTKfVxPsiO14KQ4tX5HbxSy0NxUgBBCK/0M92j6XCJpF9F0aGW esfhmYYFhvdxXWsacowCw44md/J6fsxGS2E7VTSnjUV7+NwqxNevc1opNY2givNI v2rEKfFiYF8qpVyBB/tp9O253KCthj63ZRjC3TwFPY9uo2KklhIukelrUb8poXY= =0UfP -----END PGP SIGNATURE----- Merge tag 'v3.18-rc2' into asoc-sgtl5000 Linux 3.18-rc2
This commit is contained in:
commit
a7339126fd
|
@ -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
|
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)
|
virtual address. The swapper_pg_dir contains only kernel (global)
|
||||||
mappings while the user pgd contains only user (non-global) mappings.
|
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.
|
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
|
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:
|
Required properties:
|
||||||
- compatible: Should be "fsl,vf610-ftm-pwm".
|
- compatible: Should be "fsl,vf610-ftm-pwm".
|
||||||
- reg: Physical base address and length of the controller's registers
|
- 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-names: Must contain a "default" entry.
|
||||||
- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
|
- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
|
||||||
See pinctrl/pinctrl-bindings.txt for details of the property values.
|
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:
|
Example:
|
||||||
|
|
||||||
|
@ -32,4 +48,5 @@ pwm0: pwm@40038000 {
|
||||||
<&clks VF610_CLK_FTM0_EXT_FIX_EN>;
|
<&clks VF610_CLK_FTM0_EXT_FIX_EN>;
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
pinctrl-0 = <&pinctrl_pwm0_1>;
|
pinctrl-0 = <&pinctrl_pwm0_1>;
|
||||||
|
big-endian;
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,8 +7,8 @@ Required properties:
|
||||||
"rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
|
"rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
|
||||||
- reg: physical base address and length of the controller's registers
|
- reg: physical base address and length of the controller's registers
|
||||||
- clocks: phandle and clock specifier of the PWM reference clock
|
- clocks: phandle and clock specifier of the PWM reference clock
|
||||||
- #pwm-cells: should be 2. See pwm.txt in this directory for a
|
- #pwm-cells: must be 2 (rk2928) or 3 (rk3288). See pwm.txt in this directory
|
||||||
description of the cell format.
|
for a description of the cell format.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
* Temperature Monitor (TEMPMON) on Freescale i.MX SoCs
|
* Temperature Monitor (TEMPMON) on Freescale i.MX SoCs
|
||||||
|
|
||||||
Required properties:
|
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
|
- fsl,tempmon : phandle pointer to system controller that contains TEMPMON
|
||||||
control registers, e.g. ANATOP on imx6q.
|
control registers, e.g. ANATOP on imx6q.
|
||||||
- fsl,tempmon-data : phandle pointer to fuse controller that contains TEMPMON
|
- 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:
|
Optional property:
|
||||||
- big-endian: If present the watchdog device's registers are implemented
|
- 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:
|
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
|
(a) "samsung,s3c2410-wdt" for Exynos4 and previous SoCs
|
||||||
(b) "samsung,exynos5250-wdt" for Exynos5250
|
(b) "samsung,exynos5250-wdt" for Exynos5250
|
||||||
(c) "samsung,exynos5420-wdt" for Exynos5420
|
(c) "samsung,exynos5420-wdt" for Exynos5420
|
||||||
|
(c) "samsung,exynos7-wdt" for Exynos7
|
||||||
|
|
||||||
- reg : base physical address of the controller and length of memory mapped
|
- reg : base physical address of the controller and length of memory mapped
|
||||||
region.
|
region.
|
||||||
|
|
|
@ -67,6 +67,7 @@ prototypes:
|
||||||
struct file *, unsigned open_flag,
|
struct file *, unsigned open_flag,
|
||||||
umode_t create_mode, int *opened);
|
umode_t create_mode, int *opened);
|
||||||
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
|
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
|
||||||
|
int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
|
||||||
|
|
||||||
locking rules:
|
locking rules:
|
||||||
all may block
|
all may block
|
||||||
|
@ -96,6 +97,7 @@ fiemap: no
|
||||||
update_time: no
|
update_time: no
|
||||||
atomic_open: yes
|
atomic_open: yes
|
||||||
tmpfile: no
|
tmpfile: no
|
||||||
|
dentry_open: no
|
||||||
|
|
||||||
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
|
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
|
||||||
victim.
|
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 *,
|
int (*atomic_open)(struct inode *, struct dentry *, struct file *,
|
||||||
unsigned open_flag, umode_t create_mode, int *opened);
|
unsigned open_flag, umode_t create_mode, int *opened);
|
||||||
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
|
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
|
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
|
but instead uses bmap to find out where the blocks in the file
|
||||||
are and uses those addresses directly.
|
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
|
invalidatepage: If a page has PagePrivate set, then invalidatepage
|
||||||
will be called when part or all of the page is to be removed
|
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]"}
|
Format: {"off" | "on" | "skip[mbr]"}
|
||||||
|
|
||||||
efi= [EFI]
|
efi= [EFI]
|
||||||
Format: { "old_map" }
|
Format: { "old_map", "nochunk", "noruntime" }
|
||||||
old_map [X86-64]: switch to the old ioremap-based EFI
|
old_map [X86-64]: switch to the old ioremap-based EFI
|
||||||
runtime services mapping. 32-bit still uses this one by
|
runtime services mapping. 32-bit still uses this one by
|
||||||
default.
|
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]
|
efi_no_storage_paranoia [EFI; X86]
|
||||||
Using this parameter you can use more than 50% of
|
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.
|
nodsp [SH] Disable hardware DSP at boot time.
|
||||||
|
|
||||||
noefi [X86] Disable EFI runtime services support.
|
noefi Disable EFI runtime services support.
|
||||||
|
|
||||||
noexec [IA-64]
|
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.
|
e.g. base its process migration decisions on it.
|
||||||
Default is on.
|
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]
|
tp720= [HW,PS2]
|
||||||
|
|
||||||
tpm_suspend_pcr=[HW,TPM]
|
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.
|
one of the parameters.
|
||||||
|
|
||||||
Two different PM QoS frameworks are available:
|
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
|
2. the per-device PM QoS framework provides the API to manage the per-device latency
|
||||||
constraints and PM QoS flags.
|
constraints and PM QoS flags.
|
||||||
|
|
||||||
|
@ -13,6 +14,7 @@ Each parameters have defined units:
|
||||||
* latency: usec
|
* latency: usec
|
||||||
* timeout: usec
|
* timeout: usec
|
||||||
* throughput: kbs (kilo bit / sec)
|
* throughput: kbs (kilo bit / sec)
|
||||||
|
* memory bandwidth: mbs (mega bit / sec)
|
||||||
|
|
||||||
|
|
||||||
1. PM QoS framework
|
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:
|
More up-to-date information can be found on:
|
||||||
http://open-osd.org
|
http://open-osd.org
|
||||||
|
|
||||||
Boaz Harrosh <bharrosh@panasas.com>
|
Boaz Harrosh <ooo@electrozaur.com>
|
||||||
Benny Halevy <bhalevy@panasas.com>
|
|
||||||
|
|
||||||
References
|
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
|
S: Supported
|
||||||
F: drivers/spi/spi-atmel.*
|
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
|
ATMEL Timer Counter (TC) AND CLOCKSOURCE DRIVERS
|
||||||
M: Nicolas Ferre <nicolas.ferre@atmel.com>
|
M: Nicolas Ferre <nicolas.ferre@atmel.com>
|
||||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||||
|
@ -5834,6 +5841,14 @@ S: Maintained
|
||||||
F: drivers/net/macvlan.c
|
F: drivers/net/macvlan.c
|
||||||
F: include/linux/if_macvlan.h
|
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
|
MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
|
||||||
M: Michael Kerrisk <mtk.manpages@gmail.com>
|
M: Michael Kerrisk <mtk.manpages@gmail.com>
|
||||||
W: http://www.kernel.org/doc/man-pages
|
W: http://www.kernel.org/doc/man-pages
|
||||||
|
@ -6822,7 +6837,7 @@ S: Orphan
|
||||||
F: drivers/net/wireless/orinoco/
|
F: drivers/net/wireless/orinoco/
|
||||||
|
|
||||||
OSD LIBRARY and FILESYSTEM
|
OSD LIBRARY and FILESYSTEM
|
||||||
M: Boaz Harrosh <bharrosh@panasas.com>
|
M: Boaz Harrosh <ooo@electrozaur.com>
|
||||||
M: Benny Halevy <bhalevy@primarydata.com>
|
M: Benny Halevy <bhalevy@primarydata.com>
|
||||||
L: osd-dev@open-osd.org
|
L: osd-dev@open-osd.org
|
||||||
W: http://open-osd.org
|
W: http://open-osd.org
|
||||||
|
@ -6832,6 +6847,13 @@ F: drivers/scsi/osd/
|
||||||
F: include/scsi/osd_*
|
F: include/scsi/osd_*
|
||||||
F: fs/exofs/
|
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
|
P54 WIRELESS DRIVER
|
||||||
M: Christian Lamparter <chunkeey@googlemail.com>
|
M: Christian Lamparter <chunkeey@googlemail.com>
|
||||||
L: linux-wireless@vger.kernel.org
|
L: linux-wireless@vger.kernel.org
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
||||||
VERSION = 3
|
VERSION = 3
|
||||||
PATCHLEVEL = 18
|
PATCHLEVEL = 18
|
||||||
SUBLEVEL = 0
|
SUBLEVEL = 0
|
||||||
EXTRAVERSION = -rc1
|
EXTRAVERSION = -rc2
|
||||||
NAME = Shuffling Zombie Juror
|
NAME = Shuffling Zombie Juror
|
||||||
|
|
||||||
# *DOCUMENTATION*
|
# *DOCUMENTATION*
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
config ARC
|
config ARC
|
||||||
def_bool y
|
def_bool y
|
||||||
select BUILDTIME_EXTABLE_SORT
|
select BUILDTIME_EXTABLE_SORT
|
||||||
|
select COMMON_CLK
|
||||||
select CLONE_BACKWARDS
|
select CLONE_BACKWARDS
|
||||||
# ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev
|
# ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev
|
||||||
select DEVTMPFS if !INITRAMFS_SOURCE=""
|
select DEVTMPFS if !INITRAMFS_SOURCE=""
|
||||||
|
@ -73,9 +74,6 @@ config STACKTRACE_SUPPORT
|
||||||
config HAVE_LATENCYTOP_SUPPORT
|
config HAVE_LATENCYTOP_SUPPORT
|
||||||
def_bool y
|
def_bool y
|
||||||
|
|
||||||
config NO_DMA
|
|
||||||
def_bool n
|
|
||||||
|
|
||||||
source "init/Kconfig"
|
source "init/Kconfig"
|
||||||
source "kernel/Kconfig.freezer"
|
source "kernel/Kconfig.freezer"
|
||||||
|
|
||||||
|
@ -354,7 +352,7 @@ config ARC_CURR_IN_REG
|
||||||
kernel mode. This saves memory access for each such access
|
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)"
|
bool "Emulate unaligned memory access (userspace only)"
|
||||||
select SYSCTL_ARCH_UNALIGN_NO_WARN
|
select SYSCTL_ARCH_UNALIGN_NO_WARN
|
||||||
select SYSCTL_ARCH_UNALIGN_ALLOW
|
select SYSCTL_ARCH_UNALIGN_ALLOW
|
||||||
|
|
|
@ -25,7 +25,6 @@ ifdef CONFIG_ARC_CURR_IN_REG
|
||||||
LINUXINCLUDE += -include ${src}/arch/arc/include/asm/current.h
|
LINUXINCLUDE += -include ${src}/arch/arc/include/asm/current.h
|
||||||
endif
|
endif
|
||||||
|
|
||||||
upto_gcc42 := $(call cc-ifversion, -le, 0402, y)
|
|
||||||
upto_gcc44 := $(call cc-ifversion, -le, 0404, y)
|
upto_gcc44 := $(call cc-ifversion, -le, 0404, y)
|
||||||
atleast_gcc44 := $(call cc-ifversion, -ge, 0404, y)
|
atleast_gcc44 := $(call cc-ifversion, -ge, 0404, y)
|
||||||
atleast_gcc48 := $(call cc-ifversion, -ge, 0408, 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
|
# --build-id w/o "-marclinux". Default arc-elf32-ld is OK
|
||||||
ldflags-$(upto_gcc44) += -marclinux
|
ldflags-$(upto_gcc44) += -marclinux
|
||||||
|
|
||||||
ARC_LIBGCC := -mA7
|
|
||||||
cflags-$(CONFIG_ARC_HAS_HW_MPY) += -multcost=16
|
|
||||||
|
|
||||||
ifndef CONFIG_ARC_HAS_HW_MPY
|
ifndef CONFIG_ARC_HAS_HW_MPY
|
||||||
cflags-y += -mno-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
|
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
|
# Modules with short calls might break for calls into builtin-kernel
|
||||||
KBUILD_CFLAGS_MODULE += -mlong-calls
|
KBUILD_CFLAGS_MODULE += -mlong-calls
|
||||||
|
|
|
@ -24,11 +24,6 @@
|
||||||
serial0 = &arcuart0;
|
serial0 = &arcuart0;
|
||||||
};
|
};
|
||||||
|
|
||||||
memory {
|
|
||||||
device_type = "memory";
|
|
||||||
reg = <0x00000000 0x10000000>; /* 256M */
|
|
||||||
};
|
|
||||||
|
|
||||||
fpga {
|
fpga {
|
||||||
compatible = "simple-bus";
|
compatible = "simple-bus";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
|
|
|
@ -20,18 +20,13 @@
|
||||||
/* this is for console on PGU */
|
/* this is for console on PGU */
|
||||||
/* bootargs = "console=tty0 consoleblank=0"; */
|
/* bootargs = "console=tty0 consoleblank=0"; */
|
||||||
/* this is for console on serial */
|
/* 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 {
|
aliases {
|
||||||
serial0 = &uart0;
|
serial0 = &uart0;
|
||||||
};
|
};
|
||||||
|
|
||||||
memory {
|
|
||||||
device_type = "memory";
|
|
||||||
reg = <0x80000000 0x10000000>; /* 256M */
|
|
||||||
};
|
|
||||||
|
|
||||||
fpga {
|
fpga {
|
||||||
compatible = "simple-bus";
|
compatible = "simple-bus";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
|
|
|
@ -23,7 +23,6 @@ CONFIG_MODULES=y
|
||||||
# CONFIG_IOSCHED_DEADLINE is not set
|
# CONFIG_IOSCHED_DEADLINE is not set
|
||||||
# CONFIG_IOSCHED_CFQ is not set
|
# CONFIG_IOSCHED_CFQ is not set
|
||||||
CONFIG_ARC_PLAT_FPGA_LEGACY=y
|
CONFIG_ARC_PLAT_FPGA_LEGACY=y
|
||||||
CONFIG_ARC_BOARD_ML509=y
|
|
||||||
# CONFIG_ARC_HAS_RTSC is not set
|
# CONFIG_ARC_HAS_RTSC is not set
|
||||||
CONFIG_ARC_BUILTIN_DTB_NAME="angel4"
|
CONFIG_ARC_BUILTIN_DTB_NAME="angel4"
|
||||||
CONFIG_PREEMPT=y
|
CONFIG_PREEMPT=y
|
||||||
|
|
|
@ -20,7 +20,6 @@ CONFIG_MODULES=y
|
||||||
# CONFIG_IOSCHED_DEADLINE is not set
|
# CONFIG_IOSCHED_DEADLINE is not set
|
||||||
# CONFIG_IOSCHED_CFQ is not set
|
# CONFIG_IOSCHED_CFQ is not set
|
||||||
CONFIG_ARC_PLAT_FPGA_LEGACY=y
|
CONFIG_ARC_PLAT_FPGA_LEGACY=y
|
||||||
CONFIG_ARC_BOARD_ML509=y
|
|
||||||
# CONFIG_ARC_HAS_RTSC is not set
|
# CONFIG_ARC_HAS_RTSC is not set
|
||||||
CONFIG_ARC_BUILTIN_DTB_NAME="angel4"
|
CONFIG_ARC_BUILTIN_DTB_NAME="angel4"
|
||||||
CONFIG_PREEMPT=y
|
CONFIG_PREEMPT=y
|
||||||
|
|
|
@ -21,7 +21,6 @@ CONFIG_MODULES=y
|
||||||
# CONFIG_IOSCHED_DEADLINE is not set
|
# CONFIG_IOSCHED_DEADLINE is not set
|
||||||
# CONFIG_IOSCHED_CFQ is not set
|
# CONFIG_IOSCHED_CFQ is not set
|
||||||
CONFIG_ARC_PLAT_FPGA_LEGACY=y
|
CONFIG_ARC_PLAT_FPGA_LEGACY=y
|
||||||
CONFIG_ARC_BOARD_ML509=y
|
|
||||||
# CONFIG_ARC_IDE is not set
|
# CONFIG_ARC_IDE is not set
|
||||||
# CONFIG_ARCTANGENT_EMAC is not set
|
# CONFIG_ARCTANGENT_EMAC is not set
|
||||||
# CONFIG_ARC_HAS_RTSC is not set
|
# CONFIG_ARC_HAS_RTSC is not set
|
||||||
|
|
|
@ -9,19 +9,16 @@
|
||||||
#ifndef _ASM_ARC_ARCREGS_H
|
#ifndef _ASM_ARC_ARCREGS_H
|
||||||
#define _ASM_ARC_ARCREGS_H
|
#define _ASM_ARC_ARCREGS_H
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
|
|
||||||
/* Build Configuration Registers */
|
/* Build Configuration Registers */
|
||||||
#define ARC_REG_DCCMBASE_BCR 0x61 /* DCCM Base Addr */
|
#define ARC_REG_DCCMBASE_BCR 0x61 /* DCCM Base Addr */
|
||||||
#define ARC_REG_CRC_BCR 0x62
|
#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_VECBASE_BCR 0x68
|
||||||
#define ARC_REG_PERIBASE_BCR 0x69
|
#define ARC_REG_PERIBASE_BCR 0x69
|
||||||
#define ARC_REG_FP_BCR 0x6B /* Single-Precision FPU */
|
#define ARC_REG_FP_BCR 0x6B /* ARCompact: Single-Precision FPU */
|
||||||
#define ARC_REG_DPFP_BCR 0x6C /* Dbl Precision FPU */
|
#define ARC_REG_DPFP_BCR 0x6C /* ARCompact: Dbl Precision FPU */
|
||||||
#define ARC_REG_DCCM_BCR 0x74 /* DCCM Present + SZ */
|
#define ARC_REG_DCCM_BCR 0x74 /* DCCM Present + SZ */
|
||||||
#define ARC_REG_TIMERS_BCR 0x75
|
#define ARC_REG_TIMERS_BCR 0x75
|
||||||
|
#define ARC_REG_AP_BCR 0x76
|
||||||
#define ARC_REG_ICCM_BCR 0x78
|
#define ARC_REG_ICCM_BCR 0x78
|
||||||
#define ARC_REG_XY_MEM_BCR 0x79
|
#define ARC_REG_XY_MEM_BCR 0x79
|
||||||
#define ARC_REG_MAC_BCR 0x7a
|
#define ARC_REG_MAC_BCR 0x7a
|
||||||
|
@ -31,6 +28,9 @@
|
||||||
#define ARC_REG_MIXMAX_BCR 0x7e
|
#define ARC_REG_MIXMAX_BCR 0x7e
|
||||||
#define ARC_REG_BARREL_BCR 0x7f
|
#define ARC_REG_BARREL_BCR 0x7f
|
||||||
#define ARC_REG_D_UNCACH_BCR 0x6A
|
#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 */
|
/* status32 Bits Positions */
|
||||||
#define STATUS_AE_BIT 5 /* Exception active */
|
#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_KB(n_pages) ((n_pages) << (PAGE_SHIFT - 10))
|
||||||
#define PAGES_TO_MB(n_pages) (PAGES_TO_KB(n_pages) >> 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
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define EXTN_SWAP_VALID 0x1
|
struct bcr_isa {
|
||||||
#define EXTN_NORM_VALID 0x2
|
|
||||||
#define EXTN_MINMAX_VALID 0x2
|
|
||||||
#define EXTN_BARREL_VALID 0x2
|
|
||||||
|
|
||||||
struct bcr_extn {
|
|
||||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||||
unsigned int pad:20, crc:1, ext_arith:2, mul:2, barrel:2, minmax:2,
|
unsigned int pad1:23, atomic1:1, ver:8;
|
||||||
norm:2, swap:1;
|
|
||||||
#else
|
#else
|
||||||
unsigned int swap:1, norm:2, minmax:2, barrel:2, mul:2, ext_arith:2,
|
unsigned int ver:8, atomic1:1, pad1:23;
|
||||||
crc:1, pad:20;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* DSP Options Ref Manual */
|
struct bcr_mpy {
|
||||||
struct bcr_extn_mac_mul {
|
|
||||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
#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
|
#else
|
||||||
unsigned int ver:8, type:8, pad:16;
|
unsigned int ver:8, type:2, cycles:2, dsp:4, x1616:8, pad:8;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -251,6 +235,7 @@ struct bcr_perip {
|
||||||
unsigned int pad:8, sz:8, pad2:8, start:8;
|
unsigned int pad:8, sz:8, pad2:8, start:8;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bcr_iccm {
|
struct bcr_iccm {
|
||||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||||
unsigned int base:16, pad:5, sz:3, ver:8;
|
unsigned int base:16, pad:5, sz:3, ver:8;
|
||||||
|
@ -277,8 +262,8 @@ struct bcr_dccm {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Both SP and DP FPU BCRs have same format */
|
/* ARCompact: Both SP and DP FPU BCRs have same format */
|
||||||
struct bcr_fp {
|
struct bcr_fp_arcompact {
|
||||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||||
unsigned int fast:1, ver:8;
|
unsigned int fast:1, ver:8;
|
||||||
#else
|
#else
|
||||||
|
@ -286,6 +271,30 @@ struct bcr_fp {
|
||||||
#endif
|
#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
|
* 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;
|
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 {
|
struct cpuinfo_arc_ccm {
|
||||||
unsigned int base_addr, sz;
|
unsigned int base_addr, sz;
|
||||||
};
|
};
|
||||||
|
@ -306,21 +319,25 @@ struct cpuinfo_arc_ccm {
|
||||||
struct cpuinfo_arc {
|
struct cpuinfo_arc {
|
||||||
struct cpuinfo_arc_cache icache, dcache;
|
struct cpuinfo_arc_cache icache, dcache;
|
||||||
struct cpuinfo_arc_mmu mmu;
|
struct cpuinfo_arc_mmu mmu;
|
||||||
|
struct cpuinfo_arc_bpu bpu;
|
||||||
struct bcr_identity core;
|
struct bcr_identity core;
|
||||||
unsigned int timers;
|
struct bcr_isa isa;
|
||||||
|
struct bcr_timer timers;
|
||||||
unsigned int vec_base;
|
unsigned int vec_base;
|
||||||
unsigned int uncached_base;
|
unsigned int uncached_base;
|
||||||
struct cpuinfo_arc_ccm iccm, dccm;
|
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_xymem extn_xymem;
|
||||||
struct bcr_extn_mac_mul extn_mac_mul;
|
|
||||||
struct bcr_fp fp, dpfp;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct cpuinfo_arc cpuinfo_arc700[];
|
extern struct cpuinfo_arc cpuinfo_arc700[];
|
||||||
|
|
||||||
#endif /* __ASEMBLY__ */
|
#endif /* __ASEMBLY__ */
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
|
||||||
|
|
||||||
#endif /* _ASM_ARC_ARCREGS_H */
|
#endif /* _ASM_ARC_ARCREGS_H */
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
#ifndef _ASM_ARC_ATOMIC_H
|
#ifndef _ASM_ARC_ATOMIC_H
|
||||||
#define _ASM_ARC_ATOMIC_H
|
#define _ASM_ARC_ATOMIC_H
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
@ -170,5 +168,3 @@ ATOMIC_OP(and, &=, and)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -13,8 +13,6 @@
|
||||||
#error only <linux/bitops.h> can be included directly
|
#error only <linux/bitops.h> can be included directly
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
@ -508,6 +506,4 @@ static inline __attribute__ ((const)) int __ffs(unsigned long word)
|
||||||
|
|
||||||
#endif /* !__ASSEMBLY__ */
|
#endif /* !__ASSEMBLY__ */
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,10 +21,9 @@ void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
|
||||||
unsigned long address);
|
unsigned long address);
|
||||||
void die(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 { \
|
#define BUG() do { \
|
||||||
dump_stack(); \
|
pr_warn("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
|
||||||
pr_warn("Kernel BUG in %s: %s: %d!\n", \
|
dump_stack(); \
|
||||||
__FILE__, __func__, __LINE__); \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define HAVE_ARCH_BUG
|
#define HAVE_ARCH_BUG
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#define CACHE_LINE_MASK (~(L1_CACHE_BYTES - 1))
|
#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
|
* Ideal for wiring memory mapped peripherals as we don't need to do
|
||||||
* explicit uncached accesses (LD.di/ST.di) hence more portable drivers
|
* explicit uncached accesses (LD.di/ST.di) hence more portable drivers
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -12,8 +12,6 @@
|
||||||
#ifndef _ASM_ARC_CURRENT_H
|
#ifndef _ASM_ARC_CURRENT_H
|
||||||
#define _ASM_ARC_CURRENT_H
|
#define _ASM_ARC_CURRENT_H
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#ifdef CONFIG_ARC_CURR_IN_REG
|
#ifdef CONFIG_ARC_CURR_IN_REG
|
||||||
|
@ -27,6 +25,4 @@ register struct task_struct *curr_arc asm("r25");
|
||||||
|
|
||||||
#endif /* ! __ASSEMBLY__ */
|
#endif /* ! __ASSEMBLY__ */
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
|
||||||
|
|
||||||
#endif /* _ASM_ARC_CURRENT_H */
|
#endif /* _ASM_ARC_CURRENT_H */
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
* -Conditionally disable interrupts (if they are not enabled, don't disable)
|
* -Conditionally disable interrupts (if they are not enabled, don't disable)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
|
|
||||||
#include <asm/arcregs.h>
|
#include <asm/arcregs.h>
|
||||||
|
|
||||||
/* status32 Reg bits related to Interrupt Handling */
|
/* status32 Reg bits related to Interrupt Handling */
|
||||||
|
@ -169,6 +167,4 @@ static inline int arch_irqs_disabled(void)
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
||||||
#endif /* KERNEL */
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* register API yet */
|
* register API yet */
|
||||||
#undef DBG_MAX_REG_NUM
|
#undef DBG_MAX_REG_NUM
|
||||||
|
|
||||||
#define GDB_MAX_REGS 39
|
#define GDB_MAX_REGS 87
|
||||||
|
|
||||||
#define BREAK_INSTR_SIZE 2
|
#define BREAK_INSTR_SIZE 2
|
||||||
#define CACHE_FLUSH_IS_SAFE 1
|
#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);
|
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,
|
_R0 = 0,
|
||||||
_R1, _R2, _R3, _R4, _R5, _R6, _R7, _R8, _R9, _R10, _R11, _R12, _R13,
|
_R1, _R2, _R3, _R4, _R5, _R6, _R7, _R8, _R9, _R10, _R11, _R12, _R13,
|
||||||
_R14, _R15, _R16, _R17, _R18, _R19, _R20, _R21, _R22, _R23, _R24,
|
_R14, _R15, _R16, _R17, _R18, _R19, _R20, _R21, _R22, _R23, _R24,
|
||||||
_R25, _R26,
|
_R25, _R26,
|
||||||
_BTA = 27,
|
_FP = 27,
|
||||||
_LP_START = 28,
|
__SP = 28,
|
||||||
_LP_END = 29,
|
_R30 = 30,
|
||||||
_LP_COUNT = 30,
|
_BLINK = 31,
|
||||||
_STATUS32 = 31,
|
_LP_COUNT = 60,
|
||||||
_BLINK = 32,
|
_STOP_PC = 64,
|
||||||
_FP = 33,
|
_RET = 64,
|
||||||
__SP = 34,
|
_LP_START = 65,
|
||||||
_EFA = 35,
|
_LP_END = 66,
|
||||||
_RET = 36,
|
_STATUS32 = 67,
|
||||||
_ORIG_R8 = 37,
|
_ECR = 76,
|
||||||
_STOP_PC = 38
|
_BTA = 82,
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -14,12 +14,19 @@
|
||||||
#ifndef __ASM_ARC_PROCESSOR_H
|
#ifndef __ASM_ARC_PROCESSOR_H
|
||||||
#define __ASM_ARC_PROCESSOR_H
|
#define __ASM_ARC_PROCESSOR_H
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#include <asm/ptrace.h>
|
#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.
|
/* Arch specific stuff which needs to be saved per task.
|
||||||
* However these items are not so important so as to earn a place in
|
* However these items are not so important so as to earn a place in
|
||||||
* struct thread_info
|
* struct thread_info
|
||||||
|
@ -128,6 +135,4 @@ extern unsigned int get_wchan(struct task_struct *p);
|
||||||
*/
|
*/
|
||||||
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
|
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
|
||||||
|
|
||||||
#endif /* __ASM_ARC_PROCESSOR_H */
|
#endif /* __ASM_ARC_PROCESSOR_H */
|
||||||
|
|
|
@ -29,7 +29,6 @@ struct cpuinfo_data {
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int root_mountflags, end_mem;
|
extern int root_mountflags, end_mem;
|
||||||
extern int running_on_hw;
|
|
||||||
|
|
||||||
void setup_processor(void);
|
void setup_processor(void);
|
||||||
void __init setup_arch_memory(void);
|
void __init setup_arch_memory(void);
|
||||||
|
|
|
@ -59,7 +59,15 @@ struct plat_smp_ops {
|
||||||
/* TBD: stop exporting it for direct population by platform */
|
/* TBD: stop exporting it for direct population by platform */
|
||||||
extern struct plat_smp_ops plat_smp_ops;
|
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.
|
* ARC700 doesn't support atomic Read-Modify-Write ops.
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
|
|
||||||
#define __HAVE_ARCH_MEMSET
|
#define __HAVE_ARCH_MEMSET
|
||||||
#define __HAVE_ARCH_MEMCPY
|
#define __HAVE_ARCH_MEMCPY
|
||||||
#define __HAVE_ARCH_MEMCMP
|
#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 int strcmp(const char *cs, const char *ct);
|
||||||
extern __kernel_size_t strlen(const char *);
|
extern __kernel_size_t strlen(const char *);
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
|
||||||
#endif /* _ASM_ARC_STRING_H */
|
#endif /* _ASM_ARC_STRING_H */
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
#ifndef _ASM_ARC_SYSCALLS_H
|
#ifndef _ASM_ARC_SYSCALLS_H
|
||||||
#define _ASM_ARC_SYSCALLS_H 1
|
#define _ASM_ARC_SYSCALLS_H 1
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
|
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
@ -22,6 +20,4 @@ int sys_arc_gettls(void);
|
||||||
|
|
||||||
#include <asm-generic/syscalls.h>
|
#include <asm-generic/syscalls.h>
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
#ifndef _ASM_THREAD_INFO_H
|
#ifndef _ASM_THREAD_INFO_H
|
||||||
#define _ASM_THREAD_INFO_H
|
#define _ASM_THREAD_INFO_H
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
|
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
|
|
||||||
#ifdef CONFIG_16KSTACKS
|
#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
|
* syscall, so all that reamins to be tested is _TIF_WORK_MASK
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
|
||||||
|
|
||||||
#endif /* _ASM_THREAD_INFO_H */
|
#endif /* _ASM_THREAD_INFO_H */
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include <asm-generic/unaligned.h>
|
#include <asm-generic/unaligned.h>
|
||||||
#include <asm/ptrace.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,
|
int misaligned_fixup(unsigned long address, struct pt_regs *regs,
|
||||||
struct callee_regs *cregs);
|
struct callee_regs *cregs);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -16,7 +16,7 @@ obj-$(CONFIG_MODULES) += arcksyms.o module.o
|
||||||
obj-$(CONFIG_SMP) += smp.o
|
obj-$(CONFIG_SMP) += smp.o
|
||||||
obj-$(CONFIG_ARC_DW2_UNWIND) += unwind.o
|
obj-$(CONFIG_ARC_DW2_UNWIND) += unwind.o
|
||||||
obj-$(CONFIG_KPROBES) += kprobes.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_KGDB) += kgdb.o
|
||||||
obj-$(CONFIG_ARC_METAWARE_HLINK) += arc_hostlink.o
|
obj-$(CONFIG_ARC_METAWARE_HLINK) += arc_hostlink.o
|
||||||
obj-$(CONFIG_PERF_EVENTS) += perf_event.o
|
obj-$(CONFIG_PERF_EVENTS) += perf_event.o
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <asm/disasm.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)
|
defined(CONFIG_KPROBES)
|
||||||
|
|
||||||
/* disasm_instr: Analyses instruction at addr, stores
|
/* 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;
|
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 r0, [@uboot_tag]
|
||||||
st r2, [@uboot_arg]
|
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
|
; setup "current" tsk and optionally cache it in dedicated r25
|
||||||
mov r9, @init_task
|
mov r9, @init_task
|
||||||
SET_CURR_TASK_ON_CPU r9, r0 ; r9 = tsk, r0 = scratch
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
return instruction_pointer(regs);
|
|
||||||
}
|
|
||||||
|
|
||||||
int kgdb_arch_init(void)
|
int kgdb_arch_init(void)
|
||||||
{
|
{
|
||||||
single_step_data.armed = 0;
|
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");
|
pr_err("This core does not have performance counters!\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
BUG_ON(pct_bcr.c > ARC_PMU_MAX_HWEVENTS);
|
||||||
|
|
||||||
arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu),
|
READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
|
||||||
GFP_KERNEL);
|
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)
|
if (!arc_pmu)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
arc_pmu->n_counters = pct_bcr.c;
|
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);
|
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);
|
pr_info("ARC perf\t: %d counters (%d bits), %d countable conditions\n",
|
||||||
|
arc_pmu->n_counters, arc_pmu->counter_size, cc_bcr.c);
|
||||||
if (!cc_bcr.v)
|
|
||||||
pr_err("Strange! Performance counters exist, but no countable conditions?\n");
|
|
||||||
|
|
||||||
pr_info("ARC PMU has %d countable conditions\n", cc_bcr.c);
|
|
||||||
|
|
||||||
cc_name.str[8] = 0;
|
cc_name.str[8] = 0;
|
||||||
for (i = 0; i < PERF_COUNT_HW_MAX; i++)
|
for (i = 0; i < PERF_COUNT_HW_MAX; i++)
|
||||||
|
|
|
@ -13,7 +13,9 @@
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
#include <linux/of_fdt.h>
|
#include <linux/of_fdt.h>
|
||||||
|
#include <linux/of_platform.h>
|
||||||
#include <linux/cache.h>
|
#include <linux/cache.h>
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
#include <asm/arcregs.h>
|
#include <asm/arcregs.h>
|
||||||
|
@ -24,11 +26,10 @@
|
||||||
#include <asm/unwind.h>
|
#include <asm/unwind.h>
|
||||||
#include <asm/clk.h>
|
#include <asm/clk.h>
|
||||||
#include <asm/mach_desc.h>
|
#include <asm/mach_desc.h>
|
||||||
|
#include <asm/smp.h>
|
||||||
|
|
||||||
#define FIX_PTR(x) __asm__ __volatile__(";" : "+r"(x))
|
#define FIX_PTR(x) __asm__ __volatile__(";" : "+r"(x))
|
||||||
|
|
||||||
int running_on_hw = 1; /* vs. on ISS */
|
|
||||||
|
|
||||||
/* Part of U-boot ABI: see head.S */
|
/* Part of U-boot ABI: see head.S */
|
||||||
int __initdata uboot_tag;
|
int __initdata uboot_tag;
|
||||||
char __initdata *uboot_arg;
|
char __initdata *uboot_arg;
|
||||||
|
@ -42,26 +43,26 @@ struct cpuinfo_arc cpuinfo_arc700[NR_CPUS];
|
||||||
static void read_arc_build_cfg_regs(void)
|
static void read_arc_build_cfg_regs(void)
|
||||||
{
|
{
|
||||||
struct bcr_perip uncached_space;
|
struct bcr_perip uncached_space;
|
||||||
|
struct bcr_generic bcr;
|
||||||
struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
|
struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
|
||||||
FIX_PTR(cpu);
|
FIX_PTR(cpu);
|
||||||
|
|
||||||
READ_BCR(AUX_IDENTITY, cpu->core);
|
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);
|
cpu->vec_base = read_aux_reg(AUX_INTR_VEC_BASE);
|
||||||
|
|
||||||
READ_BCR(ARC_REG_D_UNCACH_BCR, uncached_space);
|
READ_BCR(ARC_REG_D_UNCACH_BCR, uncached_space);
|
||||||
cpu->uncached_base = uncached_space.start << 24;
|
cpu->uncached_base = uncached_space.start << 24;
|
||||||
|
|
||||||
cpu->extn.mul = read_aux_reg(ARC_REG_MUL_BCR);
|
READ_BCR(ARC_REG_MUL_BCR, cpu->extn_mpy);
|
||||||
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);
|
|
||||||
|
|
||||||
cpu->extn.ext_arith = read_aux_reg(ARC_REG_EXTARITH_BCR);
|
cpu->extn.norm = read_aux_reg(ARC_REG_NORM_BCR) > 1 ? 1 : 0; /* 2,3 */
|
||||||
cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR);
|
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
|
/* Note that we read the CCM BCRs independent of kernel config
|
||||||
* This is to catch the cases where user doesn't know that
|
* 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_mmu_bcr();
|
||||||
read_decode_cache_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[] = {
|
static const struct cpuinfo_data arc_cpu_tbl[] = {
|
||||||
{ {0x10, "ARCTangent A5"}, 0x1F},
|
|
||||||
{ {0x20, "ARC 600" }, 0x2F},
|
{ {0x20, "ARC 600" }, 0x2F},
|
||||||
{ {0x30, "ARC 700" }, 0x33},
|
{ {0x30, "ARC 700" }, 0x33},
|
||||||
{ {0x34, "ARC 700 R4.10"}, 0x34},
|
{ {0x34, "ARC 700 R4.10"}, 0x34},
|
||||||
|
{ {0x35, "ARC 700 R4.11"}, 0x35},
|
||||||
{ {0x00, NULL } }
|
{ {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)
|
static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
|
||||||
{
|
{
|
||||||
int n = 0;
|
|
||||||
struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
|
struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
|
||||||
struct bcr_identity *core = &cpu->core;
|
struct bcr_identity *core = &cpu->core;
|
||||||
const struct cpuinfo_data *tbl;
|
const struct cpuinfo_data *tbl;
|
||||||
int be = 0;
|
char *isa_nm;
|
||||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
int i, be, atomic;
|
||||||
be = 1;
|
int n = 0;
|
||||||
#endif
|
|
||||||
FIX_PTR(cpu);
|
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,
|
n += scnprintf(buf + n, len - n,
|
||||||
"\nARC IDENTITY\t: Family [%#02x]"
|
"\nIDENTITY\t: ARCVER [%#02x] ARCNUM [%#02x] CHIPID [%#4x]\n",
|
||||||
" Cpu-id [%#02x] Chip-id [%#4x]\n",
|
core->family, core->cpu_id, core->chip_id);
|
||||||
core->family, core->cpu_id,
|
|
||||||
core->chip_id);
|
|
||||||
|
|
||||||
for (tbl = &arc_cpu_tbl[0]; tbl->info.id != 0; tbl++) {
|
for (tbl = &arc_cpu_tbl[0]; tbl->info.id != 0; tbl++) {
|
||||||
if ((core->family >= tbl->info.id) &&
|
if ((core->family >= tbl->info.id) &&
|
||||||
(core->family <= tbl->up_range)) {
|
(core->family <= tbl->up_range)) {
|
||||||
n += scnprintf(buf + n, len - n,
|
n += scnprintf(buf + n, len - n,
|
||||||
"processor\t: %s %s\n",
|
"processor [%d]\t: %s (%s ISA) %s\n",
|
||||||
tbl->info.str,
|
cpu_id, tbl->info.str, isa_nm,
|
||||||
be ? "[Big Endian]" : "");
|
IS_AVAIL1(be, "[Big-Endian]"));
|
||||||
break;
|
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() / 1000000),
|
||||||
(unsigned int)(arc_get_core_freq() / 10000) % 100);
|
(unsigned int)(arc_get_core_freq() / 10000) % 100);
|
||||||
|
|
||||||
n += scnprintf(buf + n, len - n, "Timers\t\t: %s %s\n",
|
n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s\nISA Extn\t: ",
|
||||||
(cpu->timers & 0x200) ? "TIMER1" : "",
|
IS_AVAIL1(cpu->timers.t0, "Timer0 "),
|
||||||
(cpu->timers & 0x100) ? "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",
|
n += i = scnprintf(buf + n, len - n, "%s%s",
|
||||||
cpu->vec_base);
|
IS_AVAIL2(atomic, "atomic ", CONFIG_ARC_HAS_LLSC));
|
||||||
|
|
||||||
n += scnprintf(buf + n, len - n, "UNCACHED Base\t: %#x\n",
|
if (i)
|
||||||
cpu->uncached_base);
|
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;
|
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)
|
static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
|
||||||
{
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
|
struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
|
||||||
|
|
||||||
FIX_PTR(cpu);
|
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,
|
n += scnprintf(buf + n, len - n,
|
||||||
"Extn [700-Base]\t: %s %s %s %s %s %s\n",
|
"Vector Table\t: %#x\nUncached Base\t: %#x\n",
|
||||||
IS_AVAIL2(cpu->extn.norm, "norm,"),
|
cpu->vec_base, cpu->uncached_base);
|
||||||
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"));
|
|
||||||
|
|
||||||
n += scnprintf(buf + n, len - n, "Extn [700-MPY]\t: %s",
|
if (cpu->extn.fpu_sp || cpu->extn.fpu_dp)
|
||||||
mul_type_nm[cpu->extn.mul].str);
|
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",
|
if (cpu->extn.debug)
|
||||||
mac_mul_nm[cpu->extn_mac_mul.type].str);
|
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) {
|
if (cpu->dccm.sz || cpu->iccm.sz)
|
||||||
n += scnprintf(buf + n, len - n,
|
n += scnprintf(buf + n, len - n, "Extn [CCM]\t: DCCM @ %x, %d KB / ICCM: @ %x, %d KB\n",
|
||||||
"Extn [700-4.10]\t: LLOCK/SCOND %s, SWAPE %s, RTSC %s\n",
|
cpu->dccm.base_addr, TO_KB(cpu->dccm.sz),
|
||||||
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",
|
|
||||||
cpu->iccm.base_addr, TO_KB(cpu->iccm.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,
|
n += scnprintf(buf + n, len - n,
|
||||||
"OS ABI [v3]\t: no-legacy-syscalls\n");
|
"OS ABI [v3]\t: no-legacy-syscalls\n");
|
||||||
|
|
||||||
return buf;
|
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()];
|
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
|
#ifdef CONFIG_ARC_HAS_DCCM
|
||||||
/*
|
/*
|
||||||
|
@ -256,33 +270,20 @@ static void arc_chk_ccms(void)
|
||||||
if (CONFIG_ARC_ICCM_SZ != cpu->iccm.sz)
|
if (CONFIG_ARC_ICCM_SZ != cpu->iccm.sz)
|
||||||
panic("Linux built with incorrect ICCM Size\n");
|
panic("Linux built with incorrect ICCM Size\n");
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure that FP hardware and kernel config match
|
* FP hardware/software config sanity
|
||||||
* -If hardware contains DPFP, kernel needs to save/restore FPU state
|
* -If hardware contains DPFP, kernel needs to save/restore FPU state
|
||||||
* across context switches
|
* -If not, it will crash trying to save/restore the non-existant regs
|
||||||
* -If hardware lacks DPFP, but kernel configured to save FPU state then
|
*
|
||||||
* kernel trying to access non-existant DPFP regs will crash
|
* (only DPDP checked since SP has no arch visible regs)
|
||||||
*
|
*/
|
||||||
* We only check for Dbl precision Floating Point, because only DPFP
|
fpu_enabled = IS_ENABLED(CONFIG_ARC_FPU_SAVE_RESTORE);
|
||||||
* 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()];
|
|
||||||
|
|
||||||
if (cpu->dpfp.ver) {
|
if (cpu->extn.fpu_dp && !fpu_enabled)
|
||||||
#ifndef CONFIG_ARC_FPU_SAVE_RESTORE
|
pr_warn("CONFIG_ARC_FPU_SAVE_RESTORE needed for working apps\n");
|
||||||
pr_warn("DPFP support broken in this kernel...\n");
|
else if (!cpu->extn.fpu_dp && fpu_enabled)
|
||||||
#endif
|
panic("FPU non-existent, disable CONFIG_ARC_FPU_SAVE_RESTORE\n");
|
||||||
} else {
|
|
||||||
#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
|
|
||||||
panic("H/w lacks DPFP support, apps won't work\n");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -303,15 +304,11 @@ void setup_processor(void)
|
||||||
|
|
||||||
arc_mmu_init();
|
arc_mmu_init();
|
||||||
arc_cache_init();
|
arc_cache_init();
|
||||||
arc_chk_ccms();
|
|
||||||
|
|
||||||
printk(arc_extn_mumbojumbo(cpu_id, str, sizeof(str)));
|
printk(arc_extn_mumbojumbo(cpu_id, str, sizeof(str)));
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
printk(arc_platform_smp_cpuinfo());
|
printk(arc_platform_smp_cpuinfo());
|
||||||
#endif
|
|
||||||
|
|
||||||
arc_chk_fpu();
|
arc_chk_core_config();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int is_kernel(unsigned long addr)
|
static inline int is_kernel(unsigned long addr)
|
||||||
|
@ -360,11 +357,7 @@ void __init setup_arch(char **cmdline_p)
|
||||||
machine_desc->init_early();
|
machine_desc->init_early();
|
||||||
|
|
||||||
setup_processor();
|
setup_processor();
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
smp_init_cpus();
|
smp_init_cpus();
|
||||||
#endif
|
|
||||||
|
|
||||||
setup_arch_memory();
|
setup_arch_memory();
|
||||||
|
|
||||||
/* copy flat DT out of .init and then unflatten it */
|
/* 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)
|
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)
|
if (machine_desc->init_machine)
|
||||||
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, 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 / (500000 / HZ),
|
||||||
(loops_per_jiffy / (5000 / HZ)) % 100);
|
(loops_per_jiffy / (5000 / HZ)) % 100);
|
||||||
|
|
||||||
seq_printf(m, arc_mmu_mumbojumbo(cpu_id, str, PAGE_SIZE));
|
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_cache_mumbojumbo(cpu_id, str, PAGE_SIZE));
|
||||||
|
|
||||||
seq_printf(m, arc_extn_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());
|
seq_printf(m, arc_platform_smp_cpuinfo());
|
||||||
#endif
|
|
||||||
|
|
||||||
free_page((unsigned long)str);
|
free_page((unsigned long)str);
|
||||||
done:
|
done:
|
||||||
|
|
|
@ -101,7 +101,7 @@ void __weak arc_platform_smp_wait_to_boot(int cpu)
|
||||||
|
|
||||||
const char *arc_platform_smp_cpuinfo(void)
|
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)
|
void flush_icache_range(unsigned long kstart, unsigned long kend)
|
||||||
{
|
{
|
||||||
unsigned int tot_sz, off, sz;
|
unsigned int tot_sz;
|
||||||
unsigned long phy, pfn;
|
|
||||||
|
|
||||||
/* printk("Kernel Cache Cohenercy: %lx to %lx\n",kstart, kend); */
|
WARN(kstart < TASK_SIZE, "%s() can't handle user vaddr", __func__);
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Shortcut for bigger flush ranges.
|
/* Shortcut for bigger flush ranges.
|
||||||
* Here we don't care if this was kernel virtual or phy addr
|
* 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
|
* straddles across 2 virtual pages and hence need for loop
|
||||||
*/
|
*/
|
||||||
while (tot_sz > 0) {
|
while (tot_sz > 0) {
|
||||||
|
unsigned int off, sz;
|
||||||
|
unsigned long phy, pfn;
|
||||||
|
|
||||||
off = kstart % PAGE_SIZE;
|
off = kstart % PAGE_SIZE;
|
||||||
pfn = vmalloc_to_pfn((void *)kstart);
|
pfn = vmalloc_to_pfn((void *)kstart);
|
||||||
phy = (pfn << PAGE_SHIFT) + off;
|
phy = (pfn << PAGE_SHIFT) + off;
|
||||||
|
|
|
@ -609,14 +609,12 @@ char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len)
|
||||||
int n = 0;
|
int n = 0;
|
||||||
struct cpuinfo_arc_mmu *p_mmu = &cpuinfo_arc700[cpu_id].mmu;
|
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,
|
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->num_tlb, p_mmu->sets, p_mmu->ways,
|
||||||
p_mmu->u_dtlb, p_mmu->u_itlb,
|
p_mmu->u_dtlb, p_mmu->u_itlb,
|
||||||
IS_ENABLED(CONFIG_ARC_MMU_SASID) ? "SASID" : "");
|
IS_ENABLED(CONFIG_ARC_MMU_SASID) ? ",SASID" : "");
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
menuconfig ARC_PLAT_FPGA_LEGACY
|
menuconfig ARC_PLAT_FPGA_LEGACY
|
||||||
bool "\"Legacy\" ARC FPGA dev Boards"
|
bool "\"Legacy\" ARC FPGA dev Boards"
|
||||||
select ISS_SMP_EXTN if SMP
|
select ARC_HAS_COH_CACHES if SMP
|
||||||
help
|
help
|
||||||
Support for ARC development boards, provided by Synopsys.
|
Support for ARC development boards, provided by Synopsys.
|
||||||
These are based on FPGA or ISS. e.g.
|
These are based on FPGA or ISS. e.g.
|
||||||
|
@ -18,17 +18,6 @@ menuconfig ARC_PLAT_FPGA_LEGACY
|
||||||
|
|
||||||
if 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
|
config ISS_SMP_EXTN
|
||||||
bool "ARC SMP Extensions (ISS Models only)"
|
bool "ARC SMP Extensions (ISS Models only)"
|
||||||
default n
|
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.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/types.h>
|
|
||||||
#include <linux/init.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 <asm/mach_desc.h>
|
||||||
#include <plat/memmap.h>
|
|
||||||
#include <plat/smp.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 ------------------------------
|
/*----------------------- Machine Descriptions ------------------------------
|
||||||
*
|
*
|
||||||
|
@ -48,41 +20,26 @@ static void __init plat_fpga_populate_dev(void)
|
||||||
* callback set, by matching the DT compatible name.
|
* callback set, by matching the DT compatible name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const char *aa4_compat[] __initconst = {
|
static const char *legacy_fpga_compat[] __initconst = {
|
||||||
"snps,arc-angel4",
|
"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",
|
"snps,arc-ml509",
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
MACHINE_START(ML509, "ml509")
|
MACHINE_START(LEGACY_FPGA, "legacy_fpga")
|
||||||
.dt_compat = ml509_compat,
|
.dt_compat = legacy_fpga_compat,
|
||||||
.init_early = plat_fpga_early_init,
|
#ifdef CONFIG_ISS_SMP_EXTN
|
||||||
.init_machine = plat_fpga_populate_dev,
|
.init_early = iss_model_init_early_smp,
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
.init_smp = iss_model_init_smp,
|
.init_smp = iss_model_init_smp,
|
||||||
#endif
|
#endif
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
|
||||||
static const char *nsimosci_compat[] __initconst = {
|
static const char *simulation_compat[] __initconst = {
|
||||||
|
"snps,nsim",
|
||||||
"snps,nsimosci",
|
"snps,nsimosci",
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
MACHINE_START(NSIMOSCI, "nsimosci")
|
MACHINE_START(SIMULATION, "simulation")
|
||||||
.dt_compat = nsimosci_compat,
|
.dt_compat = simulation_compat,
|
||||||
.init_early = NULL,
|
|
||||||
.init_machine = plat_fpga_populate_dev,
|
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
|
|
@ -13,9 +13,10 @@
|
||||||
|
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <plat/irq.h>
|
|
||||||
#include <plat/smp.h>
|
#include <plat/smp.h>
|
||||||
|
|
||||||
|
#define IDU_INTERRUPT_0 16
|
||||||
|
|
||||||
static char smp_cpuinfo_buf[128];
|
static char smp_cpuinfo_buf[128];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
menuconfig ARC_PLAT_TB10X
|
menuconfig ARC_PLAT_TB10X
|
||||||
bool "Abilis TB10x"
|
bool "Abilis TB10x"
|
||||||
select COMMON_CLK
|
|
||||||
select PINCTRL
|
select PINCTRL
|
||||||
select PINCTRL_TB10X
|
select PINCTRL_TB10X
|
||||||
select PINMUX
|
select PINMUX
|
||||||
|
|
|
@ -19,21 +19,9 @@
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/of_platform.h>
|
|
||||||
#include <linux/clk-provider.h>
|
|
||||||
#include <linux/pinctrl/consumer.h>
|
|
||||||
|
|
||||||
#include <asm/mach_desc.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 = {
|
static const char *tb10x_compat[] __initdata = {
|
||||||
"abilis,arc-tb10x",
|
"abilis,arc-tb10x",
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -41,5 +29,4 @@ static const char *tb10x_compat[] __initdata = {
|
||||||
|
|
||||||
MACHINE_START(TB10x, "tb10x")
|
MACHINE_START(TB10x, "tb10x")
|
||||||
.dt_compat = tb10x_compat,
|
.dt_compat = tb10x_compat,
|
||||||
.init_machine = tb10x_platform_init,
|
|
||||||
MACHINE_END
|
MACHINE_END
|
||||||
|
|
|
@ -122,9 +122,10 @@
|
||||||
interrupts-extended = <&pmc AT91_PMC_LOCKB>;
|
interrupts-extended = <&pmc AT91_PMC_LOCKB>;
|
||||||
clocks = <&main>;
|
clocks = <&main>;
|
||||||
reg = <1>;
|
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-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 {
|
mck: masterck {
|
||||||
|
|
|
@ -193,7 +193,6 @@
|
||||||
i2c0: i2c@80058000 {
|
i2c0: i2c@80058000 {
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
pinctrl-0 = <&i2c0_pins_a>;
|
pinctrl-0 = <&i2c0_pins_a>;
|
||||||
clock-frequency = <400000>;
|
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
|
||||||
sgtl5000: codec@0a {
|
sgtl5000: codec@0a {
|
||||||
|
|
|
@ -547,7 +547,7 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio@ff708000 {
|
gpio0: gpio@ff708000 {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
compatible = "snps,dw-apb-gpio";
|
compatible = "snps,dw-apb-gpio";
|
||||||
|
@ -555,7 +555,7 @@
|
||||||
clocks = <&per_base_clk>;
|
clocks = <&per_base_clk>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
|
|
||||||
gpio0: gpio-controller@0 {
|
porta: gpio-controller@0 {
|
||||||
compatible = "snps,dw-apb-gpio-port";
|
compatible = "snps,dw-apb-gpio-port";
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
#gpio-cells = <2>;
|
#gpio-cells = <2>;
|
||||||
|
@ -567,7 +567,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio@ff709000 {
|
gpio1: gpio@ff709000 {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
compatible = "snps,dw-apb-gpio";
|
compatible = "snps,dw-apb-gpio";
|
||||||
|
@ -575,7 +575,7 @@
|
||||||
clocks = <&per_base_clk>;
|
clocks = <&per_base_clk>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
|
|
||||||
gpio1: gpio-controller@0 {
|
portb: gpio-controller@0 {
|
||||||
compatible = "snps,dw-apb-gpio-port";
|
compatible = "snps,dw-apb-gpio-port";
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
#gpio-cells = <2>;
|
#gpio-cells = <2>;
|
||||||
|
@ -587,7 +587,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio@ff70a000 {
|
gpio2: gpio@ff70a000 {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
compatible = "snps,dw-apb-gpio";
|
compatible = "snps,dw-apb-gpio";
|
||||||
|
@ -595,7 +595,7 @@
|
||||||
clocks = <&per_base_clk>;
|
clocks = <&per_base_clk>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
|
|
||||||
gpio2: gpio-controller@0 {
|
portc: gpio-controller@0 {
|
||||||
compatible = "snps,dw-apb-gpio-port";
|
compatible = "snps,dw-apb-gpio-port";
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
#gpio-cells = <2>;
|
#gpio-cells = <2>;
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
dwmmc0@ff704000 {
|
mmc0: dwmmc0@ff704000 {
|
||||||
num-slots = <1>;
|
num-slots = <1>;
|
||||||
broken-cd;
|
broken-cd;
|
||||||
bus-width = <4>;
|
bus-width = <4>;
|
||||||
|
|
|
@ -37,6 +37,13 @@
|
||||||
*/
|
*/
|
||||||
ethernet0 = &gmac1;
|
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 {
|
&gmac1 {
|
||||||
|
@ -68,6 +75,11 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&mmc0 {
|
||||||
|
vmmc-supply = <®ulator_3_3v>;
|
||||||
|
vqmmc-supply = <®ulator_3_3v>;
|
||||||
|
};
|
||||||
|
|
||||||
&usb1 {
|
&usb1 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,6 +37,13 @@
|
||||||
*/
|
*/
|
||||||
ethernet0 = &gmac1;
|
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 {
|
&gmac1 {
|
||||||
|
@ -53,6 +60,10 @@
|
||||||
rxc-skew-ps = <2000>;
|
rxc-skew-ps = <2000>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&gpio1 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
&i2c0 {
|
&i2c0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
|
||||||
|
@ -69,7 +80,9 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
&mmc0 {
|
&mmc0 {
|
||||||
cd-gpios = <&gpio1 18 0>;
|
cd-gpios = <&portb 18 0>;
|
||||||
|
vmmc-supply = <®ulator_3_3v>;
|
||||||
|
vqmmc-supply = <®ulator_3_3v>;
|
||||||
};
|
};
|
||||||
|
|
||||||
&usb1 {
|
&usb1 {
|
||||||
|
|
|
@ -37,6 +37,13 @@
|
||||||
*/
|
*/
|
||||||
ethernet0 = &gmac1;
|
ethernet0 = &gmac1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
regulator_3_3v: vcc3p3-regulator {
|
||||||
|
compatible = "regulator-fixed";
|
||||||
|
regulator-name = "VCC3P3";
|
||||||
|
regulator-min-microvolt = <3300000>;
|
||||||
|
regulator-max-microvolt = <3300000>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&gmac1 {
|
&gmac1 {
|
||||||
|
@ -53,6 +60,11 @@
|
||||||
rxc-skew-ps = <2000>;
|
rxc-skew-ps = <2000>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&mmc0 {
|
||||||
|
vmmc-supply = <®ulator_3_3v>;
|
||||||
|
vqmmc-supply = <®ulator_3_3v>;
|
||||||
|
};
|
||||||
|
|
||||||
&usb1 {
|
&usb1 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
/* kHz uV */
|
/* kHz uV */
|
||||||
666667 1000000
|
666667 1000000
|
||||||
333334 1000000
|
333334 1000000
|
||||||
222223 1000000
|
|
||||||
>;
|
>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,7 +64,7 @@
|
||||||
interrupt-parent = <&intc>;
|
interrupt-parent = <&intc>;
|
||||||
ranges;
|
ranges;
|
||||||
|
|
||||||
adc@f8007100 {
|
adc: adc@f8007100 {
|
||||||
compatible = "xlnx,zynq-xadc-1.00.a";
|
compatible = "xlnx,zynq-xadc-1.00.a";
|
||||||
reg = <0xf8007100 0x20>;
|
reg = <0xf8007100 0x20>;
|
||||||
interrupts = <0 7 4>;
|
interrupts = <0 7 4>;
|
||||||
|
@ -137,7 +136,7 @@
|
||||||
<0xF8F00100 0x100>;
|
<0xF8F00100 0x100>;
|
||||||
};
|
};
|
||||||
|
|
||||||
L2: cache-controller {
|
L2: cache-controller@f8f02000 {
|
||||||
compatible = "arm,pl310-cache";
|
compatible = "arm,pl310-cache";
|
||||||
reg = <0xF8F02000 0x1000>;
|
reg = <0xF8F02000 0x1000>;
|
||||||
arm,data-latency = <3 2 2>;
|
arm,data-latency = <3 2 2>;
|
||||||
|
@ -146,10 +145,10 @@
|
||||||
cache-level = <2>;
|
cache-level = <2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
memory-controller@f8006000 {
|
mc: memory-controller@f8006000 {
|
||||||
compatible = "xlnx,zynq-ddrc-a05";
|
compatible = "xlnx,zynq-ddrc-a05";
|
||||||
reg = <0xf8006000 0x1000>;
|
reg = <0xf8006000 0x1000>;
|
||||||
} ;
|
};
|
||||||
|
|
||||||
uart0: serial@e0000000 {
|
uart0: serial@e0000000 {
|
||||||
compatible = "xlnx,xuartps", "cdns,uart-r1p8";
|
compatible = "xlnx,xuartps", "cdns,uart-r1p8";
|
||||||
|
@ -195,7 +194,7 @@
|
||||||
|
|
||||||
gem0: ethernet@e000b000 {
|
gem0: ethernet@e000b000 {
|
||||||
compatible = "cdns,gem";
|
compatible = "cdns,gem";
|
||||||
reg = <0xe000b000 0x4000>;
|
reg = <0xe000b000 0x1000>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
interrupts = <0 22 4>;
|
interrupts = <0 22 4>;
|
||||||
clocks = <&clkc 30>, <&clkc 30>, <&clkc 13>;
|
clocks = <&clkc 30>, <&clkc 30>, <&clkc 13>;
|
||||||
|
@ -206,7 +205,7 @@
|
||||||
|
|
||||||
gem1: ethernet@e000c000 {
|
gem1: ethernet@e000c000 {
|
||||||
compatible = "cdns,gem";
|
compatible = "cdns,gem";
|
||||||
reg = <0xe000c000 0x4000>;
|
reg = <0xe000c000 0x1000>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
interrupts = <0 45 4>;
|
interrupts = <0 45 4>;
|
||||||
clocks = <&clkc 31>, <&clkc 31>, <&clkc 14>;
|
clocks = <&clkc 31>, <&clkc 31>, <&clkc 14>;
|
||||||
|
@ -315,5 +314,16 @@
|
||||||
reg = <0xf8f00600 0x20>;
|
reg = <0xf8f00600 0x20>;
|
||||||
clocks = <&clkc 4>;
|
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_XILINX_WATCHDOG=y
|
||||||
CONFIG_ORION_WATCHDOG=y
|
CONFIG_ORION_WATCHDOG=y
|
||||||
CONFIG_SUNXI_WATCHDOG=y
|
CONFIG_SUNXI_WATCHDOG=y
|
||||||
|
CONFIG_MESON_WATCHDOG=y
|
||||||
CONFIG_MFD_AS3722=y
|
CONFIG_MFD_AS3722=y
|
||||||
CONFIG_MFD_BCM590XX=y
|
CONFIG_MFD_BCM590XX=y
|
||||||
CONFIG_MFD_CROS_EC=y
|
CONFIG_MFD_CROS_EC=y
|
||||||
|
@ -353,6 +354,7 @@ CONFIG_MMC_MVSDIO=y
|
||||||
CONFIG_MMC_SUNXI=y
|
CONFIG_MMC_SUNXI=y
|
||||||
CONFIG_MMC_DW=y
|
CONFIG_MMC_DW=y
|
||||||
CONFIG_MMC_DW_EXYNOS=y
|
CONFIG_MMC_DW_EXYNOS=y
|
||||||
|
CONFIG_MMC_DW_ROCKCHIP=y
|
||||||
CONFIG_NEW_LEDS=y
|
CONFIG_NEW_LEDS=y
|
||||||
CONFIG_LEDS_CLASS=y
|
CONFIG_LEDS_CLASS=y
|
||||||
CONFIG_LEDS_GPIO=y
|
CONFIG_LEDS_GPIO=y
|
||||||
|
|
|
@ -76,6 +76,7 @@ CONFIG_WATCHDOG=y
|
||||||
CONFIG_SUNXI_WATCHDOG=y
|
CONFIG_SUNXI_WATCHDOG=y
|
||||||
CONFIG_MFD_AXP20X=y
|
CONFIG_MFD_AXP20X=y
|
||||||
CONFIG_REGULATOR=y
|
CONFIG_REGULATOR=y
|
||||||
|
CONFIG_REGULATOR_FIXED_VOLTAGE=y
|
||||||
CONFIG_REGULATOR_GPIO=y
|
CONFIG_REGULATOR_GPIO=y
|
||||||
CONFIG_USB=y
|
CONFIG_USB=y
|
||||||
CONFIG_USB_EHCI_HCD=y
|
CONFIG_USB_EHCI_HCD=y
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/irqchip.h>
|
#include <linux/irqchip.h>
|
||||||
#include <linux/mailbox.h>
|
#include <linux/pl320-ipc.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/of_platform.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 *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 *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 *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 *eim_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_slow_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", };
|
||||||
static const char *vdo_axi_sels[] = { "axi", "ahb", };
|
static const char *vdo_axi_sels[] = { "axi", "ahb", };
|
||||||
static const char *vpu_axi_sels[] = { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m", };
|
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",
|
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_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_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_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_EIM_SEL] = imx_clk_fixup_mux("eim_sel", base + 0x1c, 27, 2, eim_sels, ARRAY_SIZE(eim_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_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_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_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));
|
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_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_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_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_EIM_PODF] = imx_clk_fixup_divider("eim_podf", "eim_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_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_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_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);
|
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_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_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_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_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_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);
|
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 struct smp_operations socfpga_smp_ops;
|
||||||
extern char secondary_trampoline, secondary_trampoline_end;
|
extern char secondary_trampoline, secondary_trampoline_end;
|
||||||
|
|
||||||
extern unsigned long cpu1start_addr;
|
extern unsigned long socfpga_cpu1start_addr;
|
||||||
|
|
||||||
#define SOCFPGA_SCU_VIRT_BASE 0xfffec000
|
#define SOCFPGA_SCU_VIRT_BASE 0xfffec000
|
||||||
|
|
||||||
|
|
|
@ -9,21 +9,26 @@
|
||||||
*/
|
*/
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <asm/memory.h>
|
||||||
|
|
||||||
.arch armv7-a
|
.arch armv7-a
|
||||||
|
|
||||||
ENTRY(secondary_trampoline)
|
ENTRY(secondary_trampoline)
|
||||||
movw r2, #:lower16:cpu1start_addr
|
/* CPU1 will always fetch from 0x0 when it is brought out of reset.
|
||||||
movt r2, #:upper16:cpu1start_addr
|
* Thus, we can just subtract the PAGE_OFFSET to get the physical
|
||||||
|
* address of &cpu1start_addr. This would not work for platforms
|
||||||
/* The socfpga VT cannot handle a 0xC0000000 page offset when loading
|
* where the physical memory does not start at 0x0.
|
||||||
the cpu1start_addr, we bit clear it. Tested on HW and VT. */
|
*/
|
||||||
bic r2, r2, #0x40000000
|
adr r0, 1f
|
||||||
|
ldmia r0, {r1, r2}
|
||||||
ldr r0, [r2]
|
sub r2, r2, #PAGE_OFFSET
|
||||||
ldr r1, [r0]
|
ldr r3, [r2]
|
||||||
bx r1
|
ldr r4, [r3]
|
||||||
|
bx r4
|
||||||
|
|
||||||
|
.align
|
||||||
|
1: .long .
|
||||||
|
.long socfpga_cpu1start_addr
|
||||||
ENTRY(secondary_trampoline_end)
|
ENTRY(secondary_trampoline_end)
|
||||||
|
|
||||||
ENTRY(socfpga_secondary_startup)
|
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;
|
int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
|
||||||
|
|
||||||
if (cpu1start_addr) {
|
if (socfpga_cpu1start_addr) {
|
||||||
memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
|
memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
|
||||||
|
|
||||||
__raw_writel(virt_to_phys(socfpga_secondary_startup),
|
__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();
|
flush_cache_all();
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
|
void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
|
||||||
void __iomem *sys_manager_base_addr;
|
void __iomem *sys_manager_base_addr;
|
||||||
void __iomem *rst_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 = {
|
static struct map_desc scu_io_desc __initdata = {
|
||||||
.virtual = SOCFPGA_SCU_VIRT_BASE,
|
.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");
|
np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr");
|
||||||
|
|
||||||
if (of_property_read_u32(np, "cpu1-start-addr",
|
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");
|
pr_err("SMP: Need cpu1-start-addr in device tree.\n");
|
||||||
|
|
||||||
sys_manager_base_addr = of_iomap(np, 0);
|
sys_manager_base_addr = of_iomap(np, 0);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
config ARM64
|
config ARM64
|
||||||
def_bool y
|
def_bool y
|
||||||
|
select ARCH_BINFMT_ELF_RANDOMIZE_PIE
|
||||||
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
|
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
|
||||||
select ARCH_HAS_SG_CHAIN
|
select ARCH_HAS_SG_CHAIN
|
||||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||||
|
@ -232,7 +233,7 @@ config ARM64_VA_BITS_42
|
||||||
|
|
||||||
config ARM64_VA_BITS_48
|
config ARM64_VA_BITS_48
|
||||||
bool "48-bit"
|
bool "48-bit"
|
||||||
depends on BROKEN
|
depends on !ARM_SMMU
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
bank-width = <4>;
|
bank-width = <4>;
|
||||||
};
|
};
|
||||||
|
|
||||||
vram@2,00000000 {
|
v2m_video_ram: vram@2,00000000 {
|
||||||
compatible = "arm,vexpress-vram";
|
compatible = "arm,vexpress-vram";
|
||||||
reg = <2 0x00000000 0x00800000>;
|
reg = <2 0x00000000 0x00800000>;
|
||||||
};
|
};
|
||||||
|
@ -179,9 +179,42 @@
|
||||||
clcd@1f0000 {
|
clcd@1f0000 {
|
||||||
compatible = "arm,pl111", "arm,primecell";
|
compatible = "arm,pl111", "arm,primecell";
|
||||||
reg = <0x1f0000 0x1000>;
|
reg = <0x1f0000 0x1000>;
|
||||||
|
interrupt-names = "combined";
|
||||||
interrupts = <14>;
|
interrupts = <14>;
|
||||||
clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>;
|
clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>;
|
||||||
clock-names = "clcdclk", "apb_pclk";
|
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 {
|
virtio_block@0130000 {
|
||||||
|
|
|
@ -78,6 +78,7 @@ CONFIG_NET_XGENE=y
|
||||||
# CONFIG_WLAN is not set
|
# CONFIG_WLAN is not set
|
||||||
CONFIG_INPUT_EVDEV=y
|
CONFIG_INPUT_EVDEV=y
|
||||||
# CONFIG_SERIO_SERPORT is not set
|
# CONFIG_SERIO_SERPORT is not set
|
||||||
|
CONFIG_SERIO_AMBAKMI=y
|
||||||
CONFIG_LEGACY_PTY_COUNT=16
|
CONFIG_LEGACY_PTY_COUNT=16
|
||||||
CONFIG_SERIAL_8250=y
|
CONFIG_SERIAL_8250=y
|
||||||
CONFIG_SERIAL_8250_CONSOLE=y
|
CONFIG_SERIAL_8250_CONSOLE=y
|
||||||
|
@ -90,6 +91,7 @@ CONFIG_VIRTIO_CONSOLE=y
|
||||||
CONFIG_REGULATOR=y
|
CONFIG_REGULATOR=y
|
||||||
CONFIG_REGULATOR_FIXED_VOLTAGE=y
|
CONFIG_REGULATOR_FIXED_VOLTAGE=y
|
||||||
CONFIG_FB=y
|
CONFIG_FB=y
|
||||||
|
CONFIG_FB_ARMCLCD=y
|
||||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||||
CONFIG_LOGO=y
|
CONFIG_LOGO=y
|
||||||
# CONFIG_LOGO_LINUX_MONO is not set
|
# CONFIG_LOGO_LINUX_MONO is not set
|
||||||
|
|
|
@ -37,8 +37,8 @@ typedef s32 compat_ssize_t;
|
||||||
typedef s32 compat_time_t;
|
typedef s32 compat_time_t;
|
||||||
typedef s32 compat_clock_t;
|
typedef s32 compat_clock_t;
|
||||||
typedef s32 compat_pid_t;
|
typedef s32 compat_pid_t;
|
||||||
typedef u32 __compat_uid_t;
|
typedef u16 __compat_uid_t;
|
||||||
typedef u32 __compat_gid_t;
|
typedef u16 __compat_gid_t;
|
||||||
typedef u16 __compat_uid16_t;
|
typedef u16 __compat_uid16_t;
|
||||||
typedef u16 __compat_gid16_t;
|
typedef u16 __compat_gid16_t;
|
||||||
typedef u32 __compat_uid32_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.
|
* that it will "exec", and that there is sufficient room for the brk.
|
||||||
*/
|
*/
|
||||||
extern unsigned long randomize_et_dyn(unsigned long base);
|
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
|
* 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")
|
#define COMPAT_ELF_PLATFORM ("v8l")
|
||||||
#endif
|
#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. */
|
/* AArch32 registers. */
|
||||||
#define COMPAT_ELF_NGREG 18
|
#define COMPAT_ELF_NGREG 18
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef __ASM_IRQ_WORK_H
|
#ifndef __ASM_IRQ_WORK_H
|
||||||
#define __ASM_IRQ_WORK_H
|
#define __ASM_IRQ_WORK_H
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
|
|
||||||
static inline bool arch_irq_work_has_interrupt(void)
|
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;
|
return !!__smp_cross_call;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static inline bool arch_irq_work_has_interrupt(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __ASM_IRQ_WORK_H */
|
#endif /* __ASM_IRQ_WORK_H */
|
||||||
|
|
|
@ -89,7 +89,8 @@ static int __init uefi_init(void)
|
||||||
*/
|
*/
|
||||||
if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
|
if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
|
||||||
pr_err("System table signature incorrect\n");
|
pr_err("System table signature incorrect\n");
|
||||||
return -EINVAL;
|
retval = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
if ((efi.systab->hdr.revision >> 16) < 2)
|
if ((efi.systab->hdr.revision >> 16) < 2)
|
||||||
pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
|
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)
|
for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
|
||||||
vendor[i] = c16[i];
|
vendor[i] = c16[i];
|
||||||
vendor[i] = '\0';
|
vendor[i] = '\0';
|
||||||
|
early_memunmap(c16, sizeof(vendor));
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_info("EFI v%u.%.02u by %s\n",
|
pr_info("EFI v%u.%.02u by %s\n",
|
||||||
|
@ -113,29 +115,11 @@ static int __init uefi_init(void)
|
||||||
if (retval == 0)
|
if (retval == 0)
|
||||||
set_bit(EFI_CONFIG_TABLES, &efi.flags);
|
set_bit(EFI_CONFIG_TABLES, &efi.flags);
|
||||||
|
|
||||||
early_memunmap(c16, sizeof(vendor));
|
out:
|
||||||
early_memunmap(efi.systab, sizeof(efi_system_table_t));
|
early_memunmap(efi.systab, sizeof(efi_system_table_t));
|
||||||
|
|
||||||
return retval;
|
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.
|
* Return true for RAM regions we want to permanently reserve.
|
||||||
*/
|
*/
|
||||||
|
@ -166,10 +150,13 @@ static __init void reserve_regions(void)
|
||||||
paddr = md->phys_addr;
|
paddr = md->phys_addr;
|
||||||
npages = md->num_pages;
|
npages = md->num_pages;
|
||||||
|
|
||||||
if (uefi_debug)
|
if (uefi_debug) {
|
||||||
pr_info(" 0x%012llx-0x%012llx [%s]",
|
char buf[64];
|
||||||
|
|
||||||
|
pr_info(" 0x%012llx-0x%012llx %s",
|
||||||
paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
|
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);
|
memrange_efi_to_native(&paddr, &npages);
|
||||||
size = npages << PAGE_SHIFT;
|
size = npages << PAGE_SHIFT;
|
||||||
|
@ -393,11 +380,16 @@ static int __init arm64_enter_virtual_mode(void)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_info("Remapping and enabling EFI services.\n");
|
|
||||||
|
|
||||||
/* replace early memmap mapping with permanent mapping */
|
|
||||||
mapsize = memmap.map_end - memmap.map;
|
mapsize = memmap.map_end - memmap.map;
|
||||||
early_memunmap(memmap.map, mapsize);
|
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,
|
memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map,
|
||||||
mapsize);
|
mapsize);
|
||||||
memmap.map_end = memmap.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);
|
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;
|
static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
|
||||||
#if CONFIG_ARM64_PGTABLE_LEVELS > 2
|
#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
|
#endif
|
||||||
#if CONFIG_ARM64_PGTABLE_LEVELS > 3
|
#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
|
#endif
|
||||||
|
|
||||||
static inline pud_t * __init early_ioremap_pud(unsigned long addr)
|
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
|
* create_mapping requires puds, pmds and ptes to be allocated from
|
||||||
* memory addressable from the initial direct kernel mapping.
|
* memory addressable from the initial direct kernel mapping.
|
||||||
*
|
*
|
||||||
* The initial direct kernel mapping, located at swapper_pg_dir,
|
* The initial direct kernel mapping, located at swapper_pg_dir, gives
|
||||||
* gives us PUD_SIZE memory starting from PHYS_OFFSET (which must be
|
* us PUD_SIZE (4K pages) or PMD_SIZE (64K pages) memory starting from
|
||||||
* aligned to 2MB as per Documentation/arm64/booting.txt).
|
* 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);
|
memblock_set_current_limit(limit);
|
||||||
|
|
||||||
/* map all the memory banks */
|
/* map all the memory banks */
|
||||||
|
|
|
@ -30,12 +30,14 @@
|
||||||
|
|
||||||
#define PGD_SIZE (PTRS_PER_PGD * sizeof(pgd_t))
|
#define PGD_SIZE (PTRS_PER_PGD * sizeof(pgd_t))
|
||||||
|
|
||||||
|
static struct kmem_cache *pgd_cache;
|
||||||
|
|
||||||
pgd_t *pgd_alloc(struct mm_struct *mm)
|
pgd_t *pgd_alloc(struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
if (PGD_SIZE == PAGE_SIZE)
|
if (PGD_SIZE == PAGE_SIZE)
|
||||||
return (pgd_t *)get_zeroed_page(GFP_KERNEL);
|
return (pgd_t *)get_zeroed_page(GFP_KERNEL);
|
||||||
else
|
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)
|
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)
|
if (PGD_SIZE == PAGE_SIZE)
|
||||||
free_page((unsigned long)pgd);
|
free_page((unsigned long)pgd);
|
||||||
else
|
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) */
|
/* Data-processing (2 source) */
|
||||||
/* Rd = Rn OP Rm */
|
/* Rd = Rn OP Rm */
|
||||||
#define A64_UDIV(sf, Rd, Rn, Rm) aarch64_insn_gen_data2(Rd, Rn, Rm, \
|
#define A64_DATA2(sf, Rd, Rn, Rm, type) aarch64_insn_gen_data2(Rd, Rn, Rm, \
|
||||||
A64_VARIANT(sf), AARCH64_INSN_DATA2_UDIV)
|
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) */
|
/* Data-processing (3 source) */
|
||||||
/* Rd = Ra + Rn * Rm */
|
/* Rd = Ra + Rn * Rm */
|
||||||
|
|
|
@ -19,12 +19,13 @@
|
||||||
#define pr_fmt(fmt) "bpf_jit: " fmt
|
#define pr_fmt(fmt) "bpf_jit: " fmt
|
||||||
|
|
||||||
#include <linux/filter.h>
|
#include <linux/filter.h>
|
||||||
#include <linux/moduleloader.h>
|
|
||||||
#include <linux/printk.h>
|
#include <linux/printk.h>
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/debug-monitors.h>
|
||||||
|
|
||||||
#include "bpf_jit.h"
|
#include "bpf_jit.h"
|
||||||
|
|
||||||
|
@ -119,6 +120,14 @@ static inline int bpf2a64_offset(int bpf_to, int bpf_from,
|
||||||
return to - 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)
|
static inline int epilogue_offset(const struct jit_ctx *ctx)
|
||||||
{
|
{
|
||||||
int to = ctx->offset[ctx->prog->len - 1];
|
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);
|
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)
|
static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
||||||
{
|
{
|
||||||
const u8 code = insn->code;
|
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_MUL(is64, tmp, tmp, src), ctx);
|
||||||
emit(A64_SUB(is64, dst, dst, tmp), ctx);
|
emit(A64_SUB(is64, dst, dst, tmp), ctx);
|
||||||
break;
|
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 */
|
/* dst = -dst */
|
||||||
case BPF_ALU | BPF_NEG:
|
case BPF_ALU | BPF_NEG:
|
||||||
case BPF_ALU64 | BPF_NEG:
|
case BPF_ALU64 | BPF_NEG:
|
||||||
|
@ -443,6 +470,27 @@ emit_cond_jmp:
|
||||||
emit(A64_B(jmp_offset), ctx);
|
emit(A64_B(jmp_offset), ctx);
|
||||||
break;
|
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) */
|
/* LDX: dst = *(size *)(src + off) */
|
||||||
case BPF_LDX | BPF_MEM | BPF_W:
|
case BPF_LDX | BPF_MEM | BPF_W:
|
||||||
case BPF_LDX | BPF_MEM | BPF_H:
|
case BPF_LDX | BPF_MEM | BPF_H:
|
||||||
|
@ -594,6 +642,10 @@ static int build_body(struct jit_ctx *ctx)
|
||||||
ctx->offset[i] = ctx->idx;
|
ctx->offset[i] = ctx->idx;
|
||||||
|
|
||||||
ret = build_insn(insn, ctx);
|
ret = build_insn(insn, ctx);
|
||||||
|
if (ret > 0) {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -613,8 +665,10 @@ void bpf_jit_compile(struct bpf_prog *prog)
|
||||||
|
|
||||||
void bpf_int_jit_compile(struct bpf_prog *prog)
|
void bpf_int_jit_compile(struct bpf_prog *prog)
|
||||||
{
|
{
|
||||||
|
struct bpf_binary_header *header;
|
||||||
struct jit_ctx ctx;
|
struct jit_ctx ctx;
|
||||||
int image_size;
|
int image_size;
|
||||||
|
u8 *image_ptr;
|
||||||
|
|
||||||
if (!bpf_jit_enable)
|
if (!bpf_jit_enable)
|
||||||
return;
|
return;
|
||||||
|
@ -636,23 +690,25 @@ void bpf_int_jit_compile(struct bpf_prog *prog)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
build_prologue(&ctx);
|
build_prologue(&ctx);
|
||||||
|
|
||||||
build_epilogue(&ctx);
|
build_epilogue(&ctx);
|
||||||
|
|
||||||
/* Now we know the actual image size. */
|
/* Now we know the actual image size. */
|
||||||
image_size = sizeof(u32) * ctx.idx;
|
image_size = sizeof(u32) * ctx.idx;
|
||||||
ctx.image = module_alloc(image_size);
|
header = bpf_jit_binary_alloc(image_size, &image_ptr,
|
||||||
if (unlikely(ctx.image == NULL))
|
sizeof(u32), jit_fill_hole);
|
||||||
|
if (header == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* 2. Now, the actual pass. */
|
/* 2. Now, the actual pass. */
|
||||||
|
|
||||||
|
ctx.image = (u32 *)image_ptr;
|
||||||
ctx.idx = 0;
|
ctx.idx = 0;
|
||||||
|
|
||||||
build_prologue(&ctx);
|
build_prologue(&ctx);
|
||||||
|
|
||||||
ctx.body_offset = ctx.idx;
|
ctx.body_offset = ctx.idx;
|
||||||
if (build_body(&ctx)) {
|
if (build_body(&ctx)) {
|
||||||
module_free(NULL, ctx.image);
|
bpf_jit_binary_free(header);
|
||||||
goto out;
|
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_jit_dump(prog->len, image_size, 2, ctx.image);
|
||||||
|
|
||||||
bpf_flush_icache(ctx.image, ctx.image + ctx.idx);
|
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:
|
out:
|
||||||
kfree(ctx.offset);
|
kfree(ctx.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bpf_jit_free(struct bpf_prog *prog)
|
void bpf_jit_free(struct bpf_prog *prog)
|
||||||
{
|
{
|
||||||
if (prog->jited)
|
unsigned long addr = (unsigned long)prog->bpf_func & PAGE_MASK;
|
||||||
module_free(NULL, prog->bpf_func);
|
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;
|
const char *unit;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
md = p;
|
md = p;
|
||||||
size = md->num_pages << EFI_PAGE_SHIFT;
|
size = md->num_pages << EFI_PAGE_SHIFT;
|
||||||
|
@ -586,9 +587,10 @@ efi_init (void)
|
||||||
unit = "KB";
|
unit = "KB";
|
||||||
}
|
}
|
||||||
|
|
||||||
printk("mem%02d: type=%2u, attr=0x%016lx, "
|
printk("mem%02d: %s "
|
||||||
"range=[0x%016lx-0x%016lx) (%4lu%s)\n",
|
"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);
|
md->phys_addr + efi_md_size(md), size, unit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2066,6 +2066,7 @@ config MIPS_CPS
|
||||||
support is unavailable.
|
support is unavailable.
|
||||||
|
|
||||||
config MIPS_CPS_PM
|
config MIPS_CPS_PM
|
||||||
|
depends on MIPS_CPS
|
||||||
select MIPS_CPC
|
select MIPS_CPC
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ static void __init db120_pci_init(u8 *eeprom)
|
||||||
ath79_register_pci();
|
ath79_register_pci();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline void db120_pci_init(void) {}
|
static inline void db120_pci_init(u8 *eeprom) {}
|
||||||
#endif /* CONFIG_PCI */
|
#endif /* CONFIG_PCI */
|
||||||
|
|
||||||
static void __init db120_setup(void)
|
static void __init db120_setup(void)
|
||||||
|
|
|
@ -806,15 +806,6 @@ void __init prom_init(void)
|
||||||
#endif
|
#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();
|
mips_hpt_frequency = octeon_get_clock_rate();
|
||||||
|
|
||||||
octeon_init_cvmcount();
|
octeon_init_cvmcount();
|
||||||
|
|
|
@ -37,15 +37,15 @@ extern void nlm_cop2_restore(struct nlm_cop2_state *);
|
||||||
|
|
||||||
#define cop2_present 1
|
#define cop2_present 1
|
||||||
#define cop2_lazy_restore 1
|
#define cop2_lazy_restore 1
|
||||||
#define cop2_save(r) do { (r); } while (0)
|
#define cop2_save(r) do { (void)(r); } while (0)
|
||||||
#define cop2_restore(r) do { (r); } while (0)
|
#define cop2_restore(r) do { (void)(r); } while (0)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define cop2_present 0
|
#define cop2_present 0
|
||||||
#define cop2_lazy_restore 0
|
#define cop2_lazy_restore 0
|
||||||
#define cop2_save(r) do { (r); } while (0)
|
#define cop2_save(r) do { (void)(r); } while (0)
|
||||||
#define cop2_restore(r) do { (r); } while (0)
|
#define cop2_restore(r) do { (void)(r); } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum cu2_ops {
|
enum cu2_ops {
|
||||||
|
|
|
@ -24,7 +24,7 @@ do { \
|
||||||
asm volatile ( \
|
asm volatile ( \
|
||||||
"1: " load " %[tmp_dst], 0(%[tmp_src])\n" \
|
"1: " load " %[tmp_dst], 0(%[tmp_src])\n" \
|
||||||
" li %[tmp_err], 0\n" \
|
" li %[tmp_err], 0\n" \
|
||||||
"2:\n" \
|
"2: .insn\n" \
|
||||||
\
|
\
|
||||||
".section .fixup, \"ax\"\n" \
|
".section .fixup, \"ax\"\n" \
|
||||||
"3: li %[tmp_err], 1\n" \
|
"3: li %[tmp_err], 1\n" \
|
||||||
|
@ -46,7 +46,7 @@ do { \
|
||||||
asm volatile ( \
|
asm volatile ( \
|
||||||
"1: " store " %[tmp_src], 0(%[tmp_dst])\n"\
|
"1: " store " %[tmp_src], 0(%[tmp_dst])\n"\
|
||||||
" li %[tmp_err], 0\n" \
|
" li %[tmp_err], 0\n" \
|
||||||
"2:\n" \
|
"2: .insn\n" \
|
||||||
\
|
\
|
||||||
".section .fixup, \"ax\"\n" \
|
".section .fixup, \"ax\"\n" \
|
||||||
"3: li %[tmp_err], 1\n" \
|
"3: li %[tmp_err], 1\n" \
|
||||||
|
|
|
@ -8,19 +8,12 @@ extern void (*cpu_wait)(void);
|
||||||
extern void r4k_wait(void);
|
extern void r4k_wait(void);
|
||||||
extern asmlinkage void __r4k_wait(void);
|
extern asmlinkage void __r4k_wait(void);
|
||||||
extern void r4k_wait_irqoff(void);
|
extern void r4k_wait_irqoff(void);
|
||||||
extern void __pastwait(void);
|
|
||||||
|
|
||||||
static inline int using_rollback_handler(void)
|
static inline int using_rollback_handler(void)
|
||||||
{
|
{
|
||||||
return cpu_wait == r4k_wait;
|
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,
|
extern int mips_cpuidle_wait_enter(struct cpuidle_device *dev,
|
||||||
struct cpuidle_driver *drv, int index);
|
struct cpuidle_driver *drv, int index);
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#ifndef _UAPI_ASM_PTRACE_H
|
#ifndef _UAPI_ASM_PTRACE_H
|
||||||
#define _UAPI_ASM_PTRACE_H
|
#define _UAPI_ASM_PTRACE_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
/* 0 - 31 are integer registers, 32 - 63 are fp registers. */
|
/* 0 - 31 are integer registers, 32 - 63 are fp registers. */
|
||||||
#define FPR_BASE 32
|
#define FPR_BASE 32
|
||||||
#define PC 64
|
#define PC 64
|
||||||
|
|
|
@ -68,9 +68,6 @@ void r4k_wait_irqoff(void)
|
||||||
" wait \n"
|
" wait \n"
|
||||||
" .set pop \n");
|
" .set pop \n");
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
__asm__(
|
|
||||||
" .globl __pastwait \n"
|
|
||||||
"__pastwait: \n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -4,7 +4,7 @@ config PICVUE
|
||||||
|
|
||||||
config PICVUE_PROC
|
config PICVUE_PROC
|
||||||
tristate "PICVUE LCD display driver /proc interface"
|
tristate "PICVUE LCD display driver /proc interface"
|
||||||
depends on PICVUE
|
depends on PICVUE && PROC_FS
|
||||||
|
|
||||||
config DS1603
|
config DS1603
|
||||||
bool "DS1603 RTC driver"
|
bool "DS1603 RTC driver"
|
||||||
|
|
|
@ -91,6 +91,7 @@ EXPORT_SYMBOL(clk_put);
|
||||||
|
|
||||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||||
{
|
{
|
||||||
|
unsigned int rate_khz = rate / 1000;
|
||||||
struct cpufreq_frequency_table *pos;
|
struct cpufreq_frequency_table *pos;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int regval;
|
int regval;
|
||||||
|
@ -107,9 +108,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||||
propagate_rate(clk);
|
propagate_rate(clk);
|
||||||
|
|
||||||
cpufreq_for_each_valid_entry(pos, loongson2_clockmod_table)
|
cpufreq_for_each_valid_entry(pos, loongson2_clockmod_table)
|
||||||
if (rate == pos->frequency)
|
if (rate_khz == pos->frequency)
|
||||||
break;
|
break;
|
||||||
if (rate != pos->frequency)
|
if (rate_khz != pos->frequency)
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
|
|
||||||
clk->rate = rate;
|
clk->rate = rate;
|
||||||
|
|
|
@ -1023,7 +1023,7 @@ emul:
|
||||||
goto emul;
|
goto emul;
|
||||||
|
|
||||||
case cop1x_op:
|
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 */
|
/* its one of ours */
|
||||||
goto emul;
|
goto emul;
|
||||||
|
|
||||||
|
@ -1068,7 +1068,7 @@ emul:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cop1x_op:
|
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;
|
return SIGILL;
|
||||||
|
|
||||||
sig = fpux_emu(xcp, ctx, ir, fault_addr);
|
sig = fpux_emu(xcp, ctx, ir, fault_addr);
|
||||||
|
|
|
@ -1062,6 +1062,7 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
|
||||||
struct mips_huge_tlb_info {
|
struct mips_huge_tlb_info {
|
||||||
int huge_pte;
|
int huge_pte;
|
||||||
int restore_scratch;
|
int restore_scratch;
|
||||||
|
bool need_reload_pte;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct mips_huge_tlb_info
|
static struct mips_huge_tlb_info
|
||||||
|
@ -1076,6 +1077,7 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l,
|
||||||
|
|
||||||
rv.huge_pte = scratch;
|
rv.huge_pte = scratch;
|
||||||
rv.restore_scratch = 0;
|
rv.restore_scratch = 0;
|
||||||
|
rv.need_reload_pte = false;
|
||||||
|
|
||||||
if (check_for_high_segbits) {
|
if (check_for_high_segbits) {
|
||||||
UASM_i_MFC0(p, tmp, C0_BADVADDR);
|
UASM_i_MFC0(p, tmp, C0_BADVADDR);
|
||||||
|
@ -1264,6 +1266,7 @@ static void build_r4000_tlb_refill_handler(void)
|
||||||
} else {
|
} else {
|
||||||
htlb_info.huge_pte = K0;
|
htlb_info.huge_pte = K0;
|
||||||
htlb_info.restore_scratch = 0;
|
htlb_info.restore_scratch = 0;
|
||||||
|
htlb_info.need_reload_pte = true;
|
||||||
vmalloc_mode = refill_noscratch;
|
vmalloc_mode = refill_noscratch;
|
||||||
/*
|
/*
|
||||||
* create the plain linear handler
|
* create the plain linear handler
|
||||||
|
@ -1300,7 +1303,8 @@ static void build_r4000_tlb_refill_handler(void)
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
|
#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
|
||||||
uasm_l_tlb_huge_update(&l, p);
|
uasm_l_tlb_huge_update(&l, p);
|
||||||
UASM_i_LW(&p, K0, 0, K1);
|
if (htlb_info.need_reload_pte)
|
||||||
|
UASM_i_LW(&p, htlb_info.huge_pte, 0, K1);
|
||||||
build_huge_update_entries(&p, htlb_info.huge_pte, K1);
|
build_huge_update_entries(&p, htlb_info.huge_pte, K1);
|
||||||
build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random,
|
build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random,
|
||||||
htlb_info.restore_scratch);
|
htlb_info.restore_scratch);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue