mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 13:22:23 +00:00
ARM: SoC driver updates
Some of the larger changes this merge window: - Removal of drivers for Exynos5440, a Samsung SoC that never saw widespread use. - Uniphier support for USB3 and SPI reset handling - Syste control and SRAM drivers and bindings for Allwinner platforms - Qualcomm AOSS (Always-on subsystem) reset controller drivers - Raspberry Pi hwmon driver for voltage - Mediatek pwrap (pmic) support for MT6797 SoC -----BEGIN PGP SIGNATURE----- iQJDBAABCAAtFiEElf+HevZ4QCAJmMQ+jBrnPN6EHHcFAlt+MMkPHG9sb2ZAbGl4 b20ubmV0AAoJEIwa5zzehBx3pB4QAIj7iVxSKEQFz65iXLTfMJKFZ9TSvRgWSDyE CHF+WOQGTnxkvySEHSw/SNqDM+Bas8ijR8b4vWzsXJFB+3HA0ZTGLU379/af1zCE 9k8QjyIWtRWKX9fo7qCHVXlMfxGbOdbCOsh4jnmHqEIDxCHXpIiJRfvUbKIXGpfn tw6QpM70vm6Q6AdKwzmDbMCYnQAMWxBK/G/Q7BfRG+IYWYjFGbiWIc9BV9Ki8+nE 3235ISaTHvAHodoec8tpLxv34GsOP4RCqscGYEuCf22RYfWva4S9e4yoWT8qPoIl IHWNsE3YWjksqpt9rj9Pie/PycthO4E4BUPMtqjMbC2OyKFgVsAcHrmToSdd+7ob t3VNM6RVl8xyWSRlm5ioev15CCOeWRi1nUT7m3UEBWpQ6ihJVpbjf1vVxZRW/E0t cgC+XzjSg26sWx1bSH9lGPFytOblAcZ04GG/Kpz02MmTgMiTdODFZ67AsqtdeQS7 a9wpaQ+DgTqU0VcQx8Kdq8uy9MOztkhXn5yO8fEWjpm0lPcxjhJS4EpN+Ru2T7/Z AMuy5lRJfQzAPU9kY7TE0yZ07pgpZgh7LlWOoKtGD7UklzXVVZrVlpn7bApRN5vg ZLze5OiEiIF5gIiRC8sIyQ9TZdvg4NqwebCqspINixqs7iIpB7TG93WQcy82osSE TXhtx4Sy =ZjwY -----END PGP SIGNATURE----- Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc Pull ARM SoC driver updates from Olof Johansson: "Some of the larger changes this merge window: - Removal of drivers for Exynos5440, a Samsung SoC that never saw widespread use. - Uniphier support for USB3 and SPI reset handling - Syste control and SRAM drivers and bindings for Allwinner platforms - Qualcomm AOSS (Always-on subsystem) reset controller drivers - Raspberry Pi hwmon driver for voltage - Mediatek pwrap (pmic) support for MT6797 SoC" * tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (52 commits) drivers/firmware: psci_checker: stash and use topology_core_cpumask for hotplug tests soc: fsl: cleanup Kconfig menu soc: fsl: dpio: Convert DPIO documentation to .rst staging: fsl-mc: Remove remaining files staging: fsl-mc: Move DPIO from staging to drivers/soc/fsl staging: fsl-dpaa2: eth: move generic FD defines to DPIO soc: fsl: qe: gpio: Add qe_gpio_set_multiple usb: host: exynos: Remove support for Exynos5440 clk: samsung: Remove support for Exynos5440 soc: sunxi: Add the A13, A23 and H3 system control compatibles reset: uniphier: add reset control support for SPI cpufreq: exynos: Remove support for Exynos5440 ata: ahci-platform: Remove support for Exynos5440 soc: imx6qp: Use GENPD_FLAG_ALWAYS_ON for PU errata soc: mediatek: pwrap: add mt6351 driver for mt6797 SoCs soc: mediatek: pwrap: add pwrap driver for mt6797 SoCs soc: mediatek: pwrap: fix cipher init setting error dt-bindings: pwrap: mediatek: add pwrap support for MT6797 reset: uniphier: add USB3 core reset control dt-bindings: reset: uniphier: add USB3 core reset support ...
This commit is contained in:
commit
f3ea496213
@ -189,7 +189,11 @@ Power-Down (SRPD), among other things.
|
||||
|
||||
Required properties:
|
||||
- compatible : should contain one of these
|
||||
"brcm,brcmstb-memc-ddr-rev-b.2.1"
|
||||
"brcm,brcmstb-memc-ddr-rev-b.2.2"
|
||||
"brcm,brcmstb-memc-ddr-rev-b.2.3"
|
||||
"brcm,brcmstb-memc-ddr-rev-b.3.0"
|
||||
"brcm,brcmstb-memc-ddr-rev-b.3.1"
|
||||
"brcm,brcmstb-memc-ddr"
|
||||
- reg : the MEMC DDR register range
|
||||
|
||||
|
@ -17,7 +17,6 @@ Required properties:
|
||||
- "marvell,armada-380-ahci"
|
||||
- "marvell,armada-3700-ahci"
|
||||
- "snps,dwc-ahci"
|
||||
- "snps,exynos5440-ahci"
|
||||
- "snps,spear-ahci"
|
||||
- "generic-ahci"
|
||||
- interrupts : <interrupt mapping for SATA IRQ>
|
||||
|
37
Documentation/devicetree/bindings/bus/sun50i-de2-bus.txt
Normal file
37
Documentation/devicetree/bindings/bus/sun50i-de2-bus.txt
Normal file
@ -0,0 +1,37 @@
|
||||
Device tree bindings for Allwinner A64 DE2 bus
|
||||
|
||||
The Allwinner A64 DE2 is on a special bus, which needs a SRAM region (SRAM C)
|
||||
to be claimed for enabling the access.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: Should contain "allwinner,sun50i-a64-de2"
|
||||
- reg: A resource specifier for the register space
|
||||
- #address-cells: Must be set to 1
|
||||
- #size-cells: Must be set to 1
|
||||
- ranges: Must be set up to map the address space inside the
|
||||
DE2, for the sub-blocks of DE2.
|
||||
- allwinner,sram: the SRAM that needs to be claimed
|
||||
|
||||
Example:
|
||||
|
||||
de2@1000000 {
|
||||
compatible = "allwinner,sun50i-a64-de2";
|
||||
reg = <0x1000000 0x400000>;
|
||||
allwinner,sram = <&de2_sram 1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0 0x1000000 0x400000>;
|
||||
|
||||
display_clocks: clock@0 {
|
||||
compatible = "allwinner,sun50i-a64-de2-clk";
|
||||
reg = <0x0 0x100000>;
|
||||
clocks = <&ccu CLK_DE>,
|
||||
<&ccu CLK_BUS_DE>;
|
||||
clock-names = "mod",
|
||||
"bus";
|
||||
resets = <&ccu RST_BUS_DE>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
};
|
@ -36,6 +36,7 @@ Required standard properties:
|
||||
"ti,sysc-omap-aes"
|
||||
"ti,sysc-mcasp"
|
||||
"ti,sysc-usb-host-fs"
|
||||
"ti,sysc-dra7-mcan"
|
||||
|
||||
- reg shall have register areas implemented for the interconnect
|
||||
target module in question such as revision, sysc and syss
|
||||
|
@ -1,28 +0,0 @@
|
||||
* Samsung Exynos5440 Clock Controller
|
||||
|
||||
The Exynos5440 clock controller generates and supplies clock to various
|
||||
controllers within the Exynos5440 SoC.
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: should be "samsung,exynos5440-clock".
|
||||
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
|
||||
- #clock-cells: should be 1.
|
||||
|
||||
Each clock is assigned an identifier and client nodes can use this identifier
|
||||
to specify the clock which they consume.
|
||||
|
||||
All available clocks are defined as preprocessor macros in
|
||||
dt-bindings/clock/exynos5440.h header and can be used in device
|
||||
tree sources.
|
||||
|
||||
Example: An example of a clock controller node is listed below.
|
||||
|
||||
clock: clock-controller@10010000 {
|
||||
compatible = "samsung,exynos5440-clock";
|
||||
reg = <0x160000 0x10000>;
|
||||
#clock-cells = <1>;
|
||||
};
|
@ -1,28 +0,0 @@
|
||||
|
||||
Exynos5440 cpufreq driver
|
||||
-------------------
|
||||
|
||||
Exynos5440 SoC cpufreq driver for CPU frequency scaling.
|
||||
|
||||
Required properties:
|
||||
- interrupts: Interrupt to know the completion of cpu frequency change.
|
||||
- operating-points: Table of frequencies and voltage CPU could be transitioned into,
|
||||
in the decreasing order. Frequency should be in KHz units and voltage
|
||||
should be in microvolts.
|
||||
|
||||
Optional properties:
|
||||
- clock-latency: Clock monitor latency in microsecond.
|
||||
|
||||
All the required listed above must be defined under node cpufreq.
|
||||
|
||||
Example:
|
||||
--------
|
||||
cpufreq@160000 {
|
||||
compatible = "samsung,exynos5440-cpufreq";
|
||||
reg = <0x160000 0x1000>;
|
||||
interrupts = <0 57 0>;
|
||||
operating-points = <
|
||||
1000000 975000
|
||||
800000 925000>;
|
||||
clock-latency = <100000>;
|
||||
};
|
52
Documentation/devicetree/bindings/reset/qcom,aoss-reset.txt
Normal file
52
Documentation/devicetree/bindings/reset/qcom,aoss-reset.txt
Normal file
@ -0,0 +1,52 @@
|
||||
Qualcomm AOSS Reset Controller
|
||||
======================================
|
||||
|
||||
This binding describes a reset-controller found on AOSS-CC (always on subsystem)
|
||||
for Qualcomm SDM845 SoCs.
|
||||
|
||||
Required properties:
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: must be:
|
||||
"qcom,sdm845-aoss-cc"
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: must specify the base address and size of the register
|
||||
space.
|
||||
|
||||
- #reset-cells:
|
||||
Usage: required
|
||||
Value type: <uint>
|
||||
Definition: must be 1; cell entry represents the reset index.
|
||||
|
||||
Example:
|
||||
|
||||
aoss_reset: reset-controller@c2a0000 {
|
||||
compatible = "qcom,sdm845-aoss-cc";
|
||||
reg = <0xc2a0000 0x31000>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
Specifying reset lines connected to IP modules
|
||||
==============================================
|
||||
|
||||
Device nodes that need access to reset lines should
|
||||
specify them as a reset phandle in their corresponding node as
|
||||
specified in reset.txt.
|
||||
|
||||
For list of all valid reset indicies see
|
||||
<dt-bindings/reset/qcom,sdm845-aoss.h>
|
||||
|
||||
Example:
|
||||
|
||||
modem-pil@4080000 {
|
||||
...
|
||||
|
||||
resets = <&aoss_reset AOSS_CC_MSS_RESTART>;
|
||||
reset-names = "mss_restart";
|
||||
|
||||
...
|
||||
};
|
@ -118,3 +118,59 @@ Example:
|
||||
|
||||
other nodes ...
|
||||
};
|
||||
|
||||
|
||||
USB3 core reset
|
||||
---------------
|
||||
|
||||
USB3 core reset belongs to USB3 glue layer. Before using the core reset,
|
||||
it is necessary to control the clocks and resets to enable this layer.
|
||||
These clocks and resets should be described in each property.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be
|
||||
"socionext,uniphier-pro4-usb3-reset" - for Pro4 SoC
|
||||
"socionext,uniphier-pxs2-usb3-reset" - for PXs2 SoC
|
||||
"socionext,uniphier-ld20-usb3-reset" - for LD20 SoC
|
||||
"socionext,uniphier-pxs3-usb3-reset" - for PXs3 SoC
|
||||
- #reset-cells: Should be 1.
|
||||
- reg: Specifies offset and length of the register set for the device.
|
||||
- clocks: A list of phandles to the clock gate for USB3 glue layer.
|
||||
According to the clock-names, appropriate clocks are required.
|
||||
- clock-names: Should contain
|
||||
"gio", "link" - for Pro4 SoC
|
||||
"link" - for others
|
||||
- resets: A list of phandles to the reset control for USB3 glue layer.
|
||||
According to the reset-names, appropriate resets are required.
|
||||
- reset-names: Should contain
|
||||
"gio", "link" - for Pro4 SoC
|
||||
"link" - for others
|
||||
|
||||
Example:
|
||||
|
||||
usb-glue@65b00000 {
|
||||
compatible = "socionext,uniphier-ld20-dwc3-glue",
|
||||
"simple-mfd";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0 0x65b00000 0x400>;
|
||||
|
||||
usb_rst: reset@0 {
|
||||
compatible = "socionext,uniphier-ld20-usb3-reset";
|
||||
reg = <0x0 0x4>;
|
||||
#reset-cells = <1>;
|
||||
clock-names = "link";
|
||||
clocks = <&sys_clk 14>;
|
||||
reset-names = "link";
|
||||
resets = <&sys_rst 14>;
|
||||
};
|
||||
|
||||
regulator {
|
||||
...
|
||||
};
|
||||
|
||||
phy {
|
||||
...
|
||||
};
|
||||
...
|
||||
};
|
||||
|
@ -19,6 +19,7 @@ IP Pairing
|
||||
Required properties in pwrap device node.
|
||||
- compatible:
|
||||
"mediatek,mt2701-pwrap" for MT2701/7623 SoCs
|
||||
"mediatek,mt6797-pwrap" for MT6797 SoCs
|
||||
"mediatek,mt7622-pwrap" for MT7622 SoCs
|
||||
"mediatek,mt8135-pwrap" for MT8135 SoCs
|
||||
"mediatek,mt8173-pwrap" for MT8173 SoCs
|
||||
|
@ -10,8 +10,14 @@ Controller Node
|
||||
|
||||
Required properties:
|
||||
- compatible : should be:
|
||||
- "allwinner,sun4i-a10-sram-controller"
|
||||
- "allwinner,sun50i-a64-sram-controller"
|
||||
- "allwinner,sun4i-a10-sram-controller" (deprecated)
|
||||
- "allwinner,sun4i-a10-system-control"
|
||||
- "allwinner,sun5i-a13-system-control"
|
||||
- "allwinner,sun7i-a20-system-control", "allwinner,sun4i-a10-system-control"
|
||||
- "allwinner,sun8i-a23-system-control"
|
||||
- "allwinner,sun8i-h3-system-control"
|
||||
- "allwinner,sun50i-a64-sram-controller" (deprecated)
|
||||
- "allwinner,sun50i-a64-system-control"
|
||||
- reg : sram controller register offset + length
|
||||
|
||||
SRAM nodes
|
||||
@ -26,8 +32,25 @@ once again the representation described in the mmio-sram binding.
|
||||
|
||||
The valid sections compatible for A10 are:
|
||||
- allwinner,sun4i-a10-sram-a3-a4
|
||||
- allwinner,sun4i-a10-sram-c1
|
||||
- allwinner,sun4i-a10-sram-d
|
||||
|
||||
The valid sections compatible for A13 are:
|
||||
- allwinner,sun5i-a13-sram-a3-a4, allwinner,sun4i-a10-sram-a3-a4
|
||||
- allwinner,sun5i-a13-sram-c1, allwinner,sun4i-a10-sram-c1
|
||||
- allwinner,sun5i-a13-sram-d, allwinner,sun4i-a10-sram-d
|
||||
|
||||
The valid sections compatible for A20 are:
|
||||
- allwinner,sun7i-a20-sram-a3-a4, allwinner,sun4i-a10-sram-a3-a4
|
||||
- allwinner,sun7i-a20-sram-c1, allwinner,sun4i-a10-sram-c1
|
||||
- allwinner,sun7i-a20-sram-d, allwinner,sun4i-a10-sram-d
|
||||
|
||||
The valid sections compatible for A23/A33 are:
|
||||
- allwinner,sun8i-a23-sram-c1, allwinner,sun4i-a10-sram-c1
|
||||
|
||||
The valid sections compatible for H3 are:
|
||||
- allwinner,sun8i-h3-sram-c1, allwinner,sun4i-a10-sram-c1
|
||||
|
||||
The valid sections compatible for A64 are:
|
||||
- allwinner,sun50i-a64-sram-c
|
||||
|
||||
@ -47,8 +70,8 @@ This valid values for this argument are:
|
||||
|
||||
Example
|
||||
-------
|
||||
sram-controller@1c00000 {
|
||||
compatible = "allwinner,sun4i-a10-sram-controller";
|
||||
system-control@1c00000 {
|
||||
compatible = "allwinner,sun4i-a10-system-control";
|
||||
reg = <0x01c00000 0x30>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
22
Documentation/hwmon/raspberrypi-hwmon
Normal file
22
Documentation/hwmon/raspberrypi-hwmon
Normal file
@ -0,0 +1,22 @@
|
||||
Kernel driver raspberrypi-hwmon
|
||||
===============================
|
||||
|
||||
Supported boards:
|
||||
* Raspberry Pi A+ (via GPIO on SoC)
|
||||
* Raspberry Pi B+ (via GPIO on SoC)
|
||||
* Raspberry Pi 2 B (via GPIO on SoC)
|
||||
* Raspberry Pi 3 B (via GPIO on port expander)
|
||||
* Raspberry Pi 3 B+ (via PMIC)
|
||||
|
||||
Author: Stefan Wahren <stefan.wahren@i2se.com>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver periodically polls a mailbox property of the VC4 firmware to detect
|
||||
undervoltage conditions.
|
||||
|
||||
Sysfs entries
|
||||
-------------
|
||||
|
||||
in0_lcrit_alarm Undervoltage alarm
|
@ -1,7 +1,15 @@
|
||||
Copyright 2016 NXP
|
||||
.. include:: <isonum.txt>
|
||||
|
||||
DPAA2 DPIO (Data Path I/O) Overview
|
||||
===================================
|
||||
|
||||
:Copyright: |copy| 2016-2018 NXP
|
||||
|
||||
This document provides an overview of the Freescale DPAA2 DPIO
|
||||
drivers
|
||||
|
||||
Introduction
|
||||
------------
|
||||
============
|
||||
|
||||
A DPAA2 DPIO (Data Path I/O) is a hardware object that provides
|
||||
interfaces to enqueue and dequeue frames to/from network interfaces
|
||||
@ -27,8 +35,11 @@ provides services that:
|
||||
|
||||
The Linux DPIO driver consists of 3 primary components--
|
||||
DPIO object driver-- fsl-mc driver that manages the DPIO object
|
||||
|
||||
DPIO service-- provides APIs to other Linux drivers for services
|
||||
|
||||
QBman portal interface-- sends portal commands, gets responses
|
||||
::
|
||||
|
||||
fsl-mc other
|
||||
bus drivers
|
||||
@ -45,8 +56,9 @@ The Linux DPIO driver consists of 3 primary components--
|
||||
|
|
||||
hardware
|
||||
|
||||
|
||||
The diagram below shows how the DPIO driver components fit with the other
|
||||
DPAA2 Linux driver components:
|
||||
DPAA2 Linux driver components::
|
||||
+------------+
|
||||
| OS Network |
|
||||
| Stack |
|
||||
@ -98,20 +110,29 @@ DPIO service (dpio-service.c, dpaa2-io.h)
|
||||
|
||||
Notification handling
|
||||
dpaa2_io_service_register()
|
||||
|
||||
dpaa2_io_service_deregister()
|
||||
|
||||
dpaa2_io_service_rearm()
|
||||
|
||||
Queuing
|
||||
dpaa2_io_service_pull_fq()
|
||||
|
||||
dpaa2_io_service_pull_channel()
|
||||
|
||||
dpaa2_io_service_enqueue_fq()
|
||||
|
||||
dpaa2_io_service_enqueue_qd()
|
||||
|
||||
dpaa2_io_store_create()
|
||||
|
||||
dpaa2_io_store_destroy()
|
||||
|
||||
dpaa2_io_store_next()
|
||||
|
||||
Buffer pool management
|
||||
dpaa2_io_service_release()
|
||||
|
||||
dpaa2_io_service_acquire()
|
||||
|
||||
QBman portal interface (qbman-portal.c)
|
||||
@ -120,7 +141,9 @@ QBman portal interface (qbman-portal.c)
|
||||
The qbman-portal component provides APIs to do the low level hardware
|
||||
bit twiddling for operations such as:
|
||||
-initializing Qman software portals
|
||||
|
||||
-building and sending portal commands
|
||||
|
||||
-portal interrupt configuration and processing
|
||||
|
||||
The qbman-portal APIs are not public to other drivers, and are
|
@ -6,3 +6,4 @@ DPAA2 Documentation
|
||||
:maxdepth: 1
|
||||
|
||||
overview
|
||||
dpio-driver
|
||||
|
@ -4512,7 +4512,7 @@ DPAA2 DATAPATH I/O (DPIO) DRIVER
|
||||
M: Roy Pledge <Roy.Pledge@nxp.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/staging/fsl-mc/bus/dpio
|
||||
F: drivers/soc/fsl/dpio
|
||||
|
||||
DPAA2 ETHERNET DRIVER
|
||||
M: Ioana Radulescu <ruxandra.radulescu@nxp.com>
|
||||
|
@ -75,7 +75,6 @@ static const struct of_device_id ahci_of_match[] = {
|
||||
{ .compatible = "generic-ahci", },
|
||||
/* Keep the following compatibles for device tree compatibility */
|
||||
{ .compatible = "snps,spear-ahci", },
|
||||
{ .compatible = "snps,exynos5440-ahci", },
|
||||
{ .compatible = "ibm,476gtr-ahci", },
|
||||
{ .compatible = "snps,dwc-ahci", },
|
||||
{ .compatible = "hisilicon,hisi-ahci", },
|
||||
|
@ -103,6 +103,16 @@ config SIMPLE_PM_BUS
|
||||
Controller (BSC, sometimes called "LBSC within Bus Bridge", or
|
||||
"External Bus Interface") as found on several Renesas ARM SoCs.
|
||||
|
||||
config SUN50I_DE2_BUS
|
||||
bool "Allwinner A64 DE2 Bus Driver"
|
||||
default ARM64
|
||||
depends on ARCH_SUNXI
|
||||
select SUNXI_SRAM
|
||||
help
|
||||
Say y here to enable support for Allwinner A64 DE2 bus driver. It's
|
||||
mostly transparent, but a SRAM region needs to be claimed in the SRAM
|
||||
controller to make the all blocks in the DE2 part accessible.
|
||||
|
||||
config SUNXI_RSB
|
||||
tristate "Allwinner sunXi Reduced Serial Bus Driver"
|
||||
default MACH_SUN8I || MACH_SUN9I || ARM64
|
||||
|
@ -21,6 +21,7 @@ obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
|
||||
|
||||
obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
|
||||
obj-$(CONFIG_QCOM_EBI2) += qcom-ebi2.o
|
||||
obj-$(CONFIG_SUN50I_DE2_BUS) += sun50i-de2.o
|
||||
obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
|
||||
obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
|
||||
obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o
|
||||
|
48
drivers/bus/sun50i-de2.c
Normal file
48
drivers/bus/sun50i-de2.c
Normal file
@ -0,0 +1,48 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Allwinner A64 Display Engine 2.0 Bus Driver
|
||||
*
|
||||
* Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
|
||||
*/
|
||||
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/soc/sunxi/sunxi_sram.h>
|
||||
|
||||
static int sun50i_de2_bus_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
int ret;
|
||||
|
||||
ret = sunxi_sram_claim(&pdev->dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Error couldn't map SRAM to device\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
of_platform_populate(np, NULL, NULL, &pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sun50i_de2_bus_remove(struct platform_device *pdev)
|
||||
{
|
||||
sunxi_sram_release(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id sun50i_de2_bus_of_match[] = {
|
||||
{ .compatible = "allwinner,sun50i-a64-de2", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static struct platform_driver sun50i_de2_bus_driver = {
|
||||
.probe = sun50i_de2_bus_probe,
|
||||
.remove = sun50i_de2_bus_remove,
|
||||
.driver = {
|
||||
.name = "sun50i-de2-bus",
|
||||
.of_match_table = sun50i_de2_bus_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(sun50i_de2_bus_driver);
|
@ -23,11 +23,14 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
#include <linux/platform_data/ti-sysc.h>
|
||||
|
||||
#include <dt-bindings/bus/ti-sysc.h>
|
||||
|
||||
#define MAX_MODULE_SOFTRESET_WAIT 10000
|
||||
|
||||
static const char * const reg_names[] = { "rev", "sysc", "syss", };
|
||||
|
||||
enum sysc_clocks {
|
||||
@ -88,6 +91,11 @@ struct sysc {
|
||||
struct delayed_work idle_work;
|
||||
};
|
||||
|
||||
void sysc_write(struct sysc *ddata, int offset, u32 value)
|
||||
{
|
||||
writel_relaxed(value, ddata->module_va + offset);
|
||||
}
|
||||
|
||||
static u32 sysc_read(struct sysc *ddata, int offset)
|
||||
{
|
||||
if (ddata->cfg.quirks & SYSC_QUIRK_16BIT) {
|
||||
@ -943,6 +951,36 @@ static void sysc_init_revision_quirks(struct sysc *ddata)
|
||||
}
|
||||
}
|
||||
|
||||
static int sysc_reset(struct sysc *ddata)
|
||||
{
|
||||
int offset = ddata->offsets[SYSC_SYSCONFIG];
|
||||
int val;
|
||||
|
||||
if (ddata->legacy_mode || offset < 0 ||
|
||||
ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Currently only support reset status in sysstatus.
|
||||
* Warn and return error in all other cases
|
||||
*/
|
||||
if (!ddata->cfg.syss_mask) {
|
||||
dev_err(ddata->dev, "No ti,syss-mask. Reset failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val = sysc_read(ddata, offset);
|
||||
val |= (0x1 << ddata->cap->regbits->srst_shift);
|
||||
sysc_write(ddata, offset, val);
|
||||
|
||||
/* Poll on reset status */
|
||||
offset = ddata->offsets[SYSC_SYSSTATUS];
|
||||
|
||||
return readl_poll_timeout(ddata->module_va + offset, val,
|
||||
(val & ddata->cfg.syss_mask) == 0x0,
|
||||
100, MAX_MODULE_SOFTRESET_WAIT);
|
||||
}
|
||||
|
||||
/* At this point the module is configured enough to read the revision */
|
||||
static int sysc_init_module(struct sysc *ddata)
|
||||
{
|
||||
@ -960,6 +998,14 @@ static int sysc_init_module(struct sysc *ddata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
error = sysc_reset(ddata);
|
||||
if (error) {
|
||||
dev_err(ddata->dev, "Reset failed with %d\n", error);
|
||||
pm_runtime_put_sync(ddata->dev);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ddata->revision = sysc_read_revision(ddata);
|
||||
pm_runtime_put_sync(ddata->dev);
|
||||
|
||||
@ -1552,6 +1598,23 @@ static const struct sysc_capabilities sysc_omap4_usb_host_fs = {
|
||||
.regbits = &sysc_regbits_omap4_usb_host_fs,
|
||||
};
|
||||
|
||||
static const struct sysc_regbits sysc_regbits_dra7_mcan = {
|
||||
.dmadisable_shift = -ENODEV,
|
||||
.midle_shift = -ENODEV,
|
||||
.sidle_shift = -ENODEV,
|
||||
.clkact_shift = -ENODEV,
|
||||
.enwkup_shift = 4,
|
||||
.srst_shift = 0,
|
||||
.emufree_shift = -ENODEV,
|
||||
.autoidle_shift = -ENODEV,
|
||||
};
|
||||
|
||||
static const struct sysc_capabilities sysc_dra7_mcan = {
|
||||
.type = TI_SYSC_DRA7_MCAN,
|
||||
.sysc_mask = SYSC_DRA7_MCAN_ENAWAKEUP | SYSC_OMAP4_SOFTRESET,
|
||||
.regbits = &sysc_regbits_dra7_mcan,
|
||||
};
|
||||
|
||||
static int sysc_init_pdata(struct sysc *ddata)
|
||||
{
|
||||
struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);
|
||||
@ -1743,6 +1806,7 @@ static const struct of_device_id sysc_match[] = {
|
||||
{ .compatible = "ti,sysc-mcasp", .data = &sysc_omap4_mcasp, },
|
||||
{ .compatible = "ti,sysc-usb-host-fs",
|
||||
.data = &sysc_omap4_usb_host_fs, },
|
||||
{ .compatible = "ti,sysc-dra7-mcan", .data = &sysc_dra7_mcan, },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sysc_match);
|
||||
|
@ -14,7 +14,6 @@ obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o
|
||||
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
|
||||
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5-subcmu.o
|
||||
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos5433.o
|
||||
obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o
|
||||
obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o
|
||||
obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-clkout.o
|
||||
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7.o
|
||||
|
@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* Author: Thomas Abraham <thomas.ab@samsung.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.
|
||||
*
|
||||
* Common Clock Framework support for Exynos5440 SoC.
|
||||
*/
|
||||
|
||||
#include <dt-bindings/clock/exynos5440.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include "clk.h"
|
||||
#include "clk-pll.h"
|
||||
|
||||
#define CLKEN_OV_VAL 0xf8
|
||||
#define CPU_CLK_STATUS 0xfc
|
||||
#define MISC_DOUT1 0x558
|
||||
|
||||
static void __iomem *reg_base;
|
||||
|
||||
/* parent clock name list */
|
||||
PNAME(mout_armclk_p) = { "cplla", "cpllb" };
|
||||
PNAME(mout_spi_p) = { "div125", "div200" };
|
||||
|
||||
/* fixed rate clocks generated outside the soc */
|
||||
static struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = {
|
||||
FRATE(0, "xtal", NULL, 0, 0),
|
||||
};
|
||||
|
||||
/* fixed rate clocks */
|
||||
static const struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initconst = {
|
||||
FRATE(0, "ppll", NULL, 0, 1000000000),
|
||||
FRATE(0, "usb_phy0", NULL, 0, 60000000),
|
||||
FRATE(0, "usb_phy1", NULL, 0, 60000000),
|
||||
FRATE(0, "usb_ohci12", NULL, 0, 12000000),
|
||||
FRATE(0, "usb_ohci48", NULL, 0, 48000000),
|
||||
};
|
||||
|
||||
/* fixed factor clocks */
|
||||
static const struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initconst = {
|
||||
FFACTOR(0, "div250", "ppll", 1, 4, 0),
|
||||
FFACTOR(0, "div200", "ppll", 1, 5, 0),
|
||||
FFACTOR(0, "div125", "div250", 1, 2, 0),
|
||||
};
|
||||
|
||||
/* mux clocks */
|
||||
static const struct samsung_mux_clock exynos5440_mux_clks[] __initconst = {
|
||||
MUX(0, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1),
|
||||
MUX(CLK_ARM_CLK, "arm_clk", mout_armclk_p, CPU_CLK_STATUS, 0, 1),
|
||||
};
|
||||
|
||||
/* divider clocks */
|
||||
static const struct samsung_div_clock exynos5440_div_clks[] __initconst = {
|
||||
DIV(CLK_SPI_BAUD, "div_spi", "mout_spi", MISC_DOUT1, 3, 2),
|
||||
};
|
||||
|
||||
/* gate clocks */
|
||||
static const struct samsung_gate_clock exynos5440_gate_clks[] __initconst = {
|
||||
GATE(CLK_PB0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0),
|
||||
GATE(CLK_PR0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0),
|
||||
GATE(CLK_PR1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0),
|
||||
GATE(CLK_B_250, "b_250", "div250", CLKEN_OV_VAL, 9, 0, 0),
|
||||
GATE(CLK_B_125, "b_125", "div125", CLKEN_OV_VAL, 10, 0, 0),
|
||||
GATE(CLK_B_200, "b_200", "div200", CLKEN_OV_VAL, 11, 0, 0),
|
||||
GATE(CLK_SATA, "sata", "div200", CLKEN_OV_VAL, 12, 0, 0),
|
||||
GATE(CLK_USB, "usb", "div200", CLKEN_OV_VAL, 13, 0, 0),
|
||||
GATE(CLK_GMAC0, "gmac0", "div200", CLKEN_OV_VAL, 14, 0, 0),
|
||||
GATE(CLK_CS250, "cs250", "div250", CLKEN_OV_VAL, 19, 0, 0),
|
||||
GATE(CLK_PB0_250_O, "pb0_250_o", "pb0_250", CLKEN_OV_VAL, 3, 0, 0),
|
||||
GATE(CLK_PR0_250_O, "pr0_250_o", "pr0_250", CLKEN_OV_VAL, 4, 0, 0),
|
||||
GATE(CLK_PR1_250_O, "pr1_250_o", "pr1_250", CLKEN_OV_VAL, 5, 0, 0),
|
||||
GATE(CLK_B_250_O, "b_250_o", "b_250", CLKEN_OV_VAL, 9, 0, 0),
|
||||
GATE(CLK_B_125_O, "b_125_o", "b_125", CLKEN_OV_VAL, 10, 0, 0),
|
||||
GATE(CLK_B_200_O, "b_200_o", "b_200", CLKEN_OV_VAL, 11, 0, 0),
|
||||
GATE(CLK_SATA_O, "sata_o", "sata", CLKEN_OV_VAL, 12, 0, 0),
|
||||
GATE(CLK_USB_O, "usb_o", "usb", CLKEN_OV_VAL, 13, 0, 0),
|
||||
GATE(CLK_GMAC0_O, "gmac0_o", "gmac", CLKEN_OV_VAL, 14, 0, 0),
|
||||
GATE(CLK_CS250_O, "cs250_o", "cs250", CLKEN_OV_VAL, 19, 0, 0),
|
||||
};
|
||||
|
||||
static const struct of_device_id ext_clk_match[] __initconst = {
|
||||
{ .compatible = "samsung,clock-xtal", .data = (void *)0, },
|
||||
{},
|
||||
};
|
||||
|
||||
static int exynos5440_clk_restart_notify(struct notifier_block *this,
|
||||
unsigned long code, void *unused)
|
||||
{
|
||||
u32 val, status;
|
||||
|
||||
status = readl_relaxed(reg_base + 0xbc);
|
||||
val = readl_relaxed(reg_base + 0xcc);
|
||||
val = (val & 0xffff0000) | (status & 0xffff);
|
||||
writel_relaxed(val, reg_base + 0xcc);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exynos5440 Clock restart notifier, handles restart functionality
|
||||
*/
|
||||
static struct notifier_block exynos5440_clk_restart_handler = {
|
||||
.notifier_call = exynos5440_clk_restart_notify,
|
||||
.priority = 128,
|
||||
};
|
||||
|
||||
static const struct samsung_pll_clock exynos5440_plls[] __initconst = {
|
||||
PLL(pll_2550x, CLK_CPLLA, "cplla", "xtal", 0, 0x4c, NULL),
|
||||
PLL(pll_2550x, CLK_CPLLB, "cpllb", "xtal", 0, 0x50, NULL),
|
||||
};
|
||||
|
||||
/*
|
||||
* Clock aliases for legacy clkdev look-up.
|
||||
*/
|
||||
static const struct samsung_clock_alias exynos5440_aliases[] __initconst = {
|
||||
ALIAS(CLK_ARM_CLK, NULL, "armclk"),
|
||||
};
|
||||
|
||||
/* register exynos5440 clocks */
|
||||
static void __init exynos5440_clk_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_clk_provider *ctx;
|
||||
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base) {
|
||||
pr_err("%s: failed to map clock controller registers,"
|
||||
" aborting clock initialization\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
|
||||
|
||||
samsung_clk_of_register_fixed_ext(ctx, exynos5440_fixed_rate_ext_clks,
|
||||
ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match);
|
||||
|
||||
samsung_clk_register_pll(ctx, exynos5440_plls,
|
||||
ARRAY_SIZE(exynos5440_plls), ctx->reg_base);
|
||||
|
||||
samsung_clk_register_fixed_rate(ctx, exynos5440_fixed_rate_clks,
|
||||
ARRAY_SIZE(exynos5440_fixed_rate_clks));
|
||||
samsung_clk_register_fixed_factor(ctx, exynos5440_fixed_factor_clks,
|
||||
ARRAY_SIZE(exynos5440_fixed_factor_clks));
|
||||
samsung_clk_register_mux(ctx, exynos5440_mux_clks,
|
||||
ARRAY_SIZE(exynos5440_mux_clks));
|
||||
samsung_clk_register_div(ctx, exynos5440_div_clks,
|
||||
ARRAY_SIZE(exynos5440_div_clks));
|
||||
samsung_clk_register_gate(ctx, exynos5440_gate_clks,
|
||||
ARRAY_SIZE(exynos5440_gate_clks));
|
||||
samsung_clk_register_alias(ctx, exynos5440_aliases,
|
||||
ARRAY_SIZE(exynos5440_aliases));
|
||||
|
||||
samsung_clk_of_add_provider(np, ctx);
|
||||
|
||||
if (register_restart_handler(&exynos5440_clk_restart_handler))
|
||||
pr_warn("exynos5440 clock can't register restart handler\n");
|
||||
|
||||
pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk"));
|
||||
pr_info("exynos5440 clock initialization complete\n");
|
||||
}
|
||||
CLK_OF_DECLARE(exynos5440_clk, "samsung,exynos5440-clock", exynos5440_clk_init);
|
@ -708,6 +708,7 @@ static const struct omap_clkctrl_reg_data dra7_wkupaon_clkctrl_regs[] __initcons
|
||||
{ DRA7_COUNTER_32K_CLKCTRL, NULL, 0, "wkupaon_iclk_mux" },
|
||||
{ DRA7_UART10_CLKCTRL, dra7_uart10_bit_data, CLKF_SW_SUP, "wkupaon_cm:clk:0060:24" },
|
||||
{ DRA7_DCAN1_CLKCTRL, dra7_dcan1_bit_data, CLKF_SW_SUP, "wkupaon_cm:clk:0068:24" },
|
||||
{ DRA7_ADC_CLKCTRL, NULL, CLKF_SW_SUP, "mcan_clk"},
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
|
@ -71,20 +71,6 @@ config ARM_BRCMSTB_AVS_CPUFREQ
|
||||
|
||||
Say Y, if you have a Broadcom SoC with AVS support for DFS or DVFS.
|
||||
|
||||
config ARM_EXYNOS5440_CPUFREQ
|
||||
tristate "SAMSUNG EXYNOS5440"
|
||||
depends on SOC_EXYNOS5440
|
||||
depends on HAVE_CLK && OF
|
||||
select PM_OPP
|
||||
default y
|
||||
help
|
||||
This adds the CPUFreq driver for Samsung EXYNOS5440
|
||||
SoC. The nature of exynos5440 clock controller is
|
||||
different than previous exynos controllers so not using
|
||||
the common exynos framework.
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
config ARM_HIGHBANK_CPUFREQ
|
||||
tristate "Calxeda Highbank-based"
|
||||
depends on ARCH_HIGHBANK && CPUFREQ_DT && REGULATOR
|
||||
|
@ -56,7 +56,6 @@ obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
|
||||
obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
|
||||
obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
|
||||
obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
|
||||
obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
|
||||
obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
|
||||
obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
|
||||
obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o
|
||||
|
@ -1,452 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Amit Daniel Kachhap <amit.daniel@samsung.com>
|
||||
*
|
||||
* EXYNOS5440 - CPU frequency scaling support
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* Register definitions */
|
||||
#define XMU_DVFS_CTRL 0x0060
|
||||
#define XMU_PMU_P0_7 0x0064
|
||||
#define XMU_C0_3_PSTATE 0x0090
|
||||
#define XMU_P_LIMIT 0x00a0
|
||||
#define XMU_P_STATUS 0x00a4
|
||||
#define XMU_PMUEVTEN 0x00d0
|
||||
#define XMU_PMUIRQEN 0x00d4
|
||||
#define XMU_PMUIRQ 0x00d8
|
||||
|
||||
/* PMU mask and shift definations */
|
||||
#define P_VALUE_MASK 0x7
|
||||
|
||||
#define XMU_DVFS_CTRL_EN_SHIFT 0
|
||||
|
||||
#define P0_7_CPUCLKDEV_SHIFT 21
|
||||
#define P0_7_CPUCLKDEV_MASK 0x7
|
||||
#define P0_7_ATBCLKDEV_SHIFT 18
|
||||
#define P0_7_ATBCLKDEV_MASK 0x7
|
||||
#define P0_7_CSCLKDEV_SHIFT 15
|
||||
#define P0_7_CSCLKDEV_MASK 0x7
|
||||
#define P0_7_CPUEMA_SHIFT 28
|
||||
#define P0_7_CPUEMA_MASK 0xf
|
||||
#define P0_7_L2EMA_SHIFT 24
|
||||
#define P0_7_L2EMA_MASK 0xf
|
||||
#define P0_7_VDD_SHIFT 8
|
||||
#define P0_7_VDD_MASK 0x7f
|
||||
#define P0_7_FREQ_SHIFT 0
|
||||
#define P0_7_FREQ_MASK 0xff
|
||||
|
||||
#define C0_3_PSTATE_VALID_SHIFT 8
|
||||
#define C0_3_PSTATE_CURR_SHIFT 4
|
||||
#define C0_3_PSTATE_NEW_SHIFT 0
|
||||
|
||||
#define PSTATE_CHANGED_EVTEN_SHIFT 0
|
||||
|
||||
#define PSTATE_CHANGED_IRQEN_SHIFT 0
|
||||
|
||||
#define PSTATE_CHANGED_SHIFT 0
|
||||
|
||||
/* some constant values for clock divider calculation */
|
||||
#define CPU_DIV_FREQ_MAX 500
|
||||
#define CPU_DBG_FREQ_MAX 375
|
||||
#define CPU_ATB_FREQ_MAX 500
|
||||
|
||||
#define PMIC_LOW_VOLT 0x30
|
||||
#define PMIC_HIGH_VOLT 0x28
|
||||
|
||||
#define CPUEMA_HIGH 0x2
|
||||
#define CPUEMA_MID 0x4
|
||||
#define CPUEMA_LOW 0x7
|
||||
|
||||
#define L2EMA_HIGH 0x1
|
||||
#define L2EMA_MID 0x3
|
||||
#define L2EMA_LOW 0x4
|
||||
|
||||
#define DIV_TAB_MAX 2
|
||||
/* frequency unit is 20MHZ */
|
||||
#define FREQ_UNIT 20
|
||||
#define MAX_VOLTAGE 1550000 /* In microvolt */
|
||||
#define VOLTAGE_STEP 12500 /* In microvolt */
|
||||
|
||||
#define CPUFREQ_NAME "exynos5440_dvfs"
|
||||
#define DEF_TRANS_LATENCY 100000
|
||||
|
||||
enum cpufreq_level_index {
|
||||
L0, L1, L2, L3, L4,
|
||||
L5, L6, L7, L8, L9,
|
||||
};
|
||||
#define CPUFREQ_LEVEL_END (L7 + 1)
|
||||
|
||||
struct exynos_dvfs_data {
|
||||
void __iomem *base;
|
||||
struct resource *mem;
|
||||
int irq;
|
||||
struct clk *cpu_clk;
|
||||
unsigned int latency;
|
||||
struct cpufreq_frequency_table *freq_table;
|
||||
unsigned int freq_count;
|
||||
struct device *dev;
|
||||
bool dvfs_enabled;
|
||||
struct work_struct irq_work;
|
||||
};
|
||||
|
||||
static struct exynos_dvfs_data *dvfs_info;
|
||||
static DEFINE_MUTEX(cpufreq_lock);
|
||||
static struct cpufreq_freqs freqs;
|
||||
|
||||
static int init_div_table(void)
|
||||
{
|
||||
struct cpufreq_frequency_table *pos, *freq_tbl = dvfs_info->freq_table;
|
||||
unsigned int tmp, clk_div, ema_div, freq, volt_id, idx;
|
||||
struct dev_pm_opp *opp;
|
||||
|
||||
cpufreq_for_each_entry_idx(pos, freq_tbl, idx) {
|
||||
opp = dev_pm_opp_find_freq_exact(dvfs_info->dev,
|
||||
pos->frequency * 1000, true);
|
||||
if (IS_ERR(opp)) {
|
||||
dev_err(dvfs_info->dev,
|
||||
"failed to find valid OPP for %u KHZ\n",
|
||||
pos->frequency);
|
||||
return PTR_ERR(opp);
|
||||
}
|
||||
|
||||
freq = pos->frequency / 1000; /* In MHZ */
|
||||
clk_div = ((freq / CPU_DIV_FREQ_MAX) & P0_7_CPUCLKDEV_MASK)
|
||||
<< P0_7_CPUCLKDEV_SHIFT;
|
||||
clk_div |= ((freq / CPU_ATB_FREQ_MAX) & P0_7_ATBCLKDEV_MASK)
|
||||
<< P0_7_ATBCLKDEV_SHIFT;
|
||||
clk_div |= ((freq / CPU_DBG_FREQ_MAX) & P0_7_CSCLKDEV_MASK)
|
||||
<< P0_7_CSCLKDEV_SHIFT;
|
||||
|
||||
/* Calculate EMA */
|
||||
volt_id = dev_pm_opp_get_voltage(opp);
|
||||
|
||||
volt_id = (MAX_VOLTAGE - volt_id) / VOLTAGE_STEP;
|
||||
if (volt_id < PMIC_HIGH_VOLT) {
|
||||
ema_div = (CPUEMA_HIGH << P0_7_CPUEMA_SHIFT) |
|
||||
(L2EMA_HIGH << P0_7_L2EMA_SHIFT);
|
||||
} else if (volt_id > PMIC_LOW_VOLT) {
|
||||
ema_div = (CPUEMA_LOW << P0_7_CPUEMA_SHIFT) |
|
||||
(L2EMA_LOW << P0_7_L2EMA_SHIFT);
|
||||
} else {
|
||||
ema_div = (CPUEMA_MID << P0_7_CPUEMA_SHIFT) |
|
||||
(L2EMA_MID << P0_7_L2EMA_SHIFT);
|
||||
}
|
||||
|
||||
tmp = (clk_div | ema_div | (volt_id << P0_7_VDD_SHIFT)
|
||||
| ((freq / FREQ_UNIT) << P0_7_FREQ_SHIFT));
|
||||
|
||||
__raw_writel(tmp, dvfs_info->base + XMU_PMU_P0_7 + 4 * idx);
|
||||
dev_pm_opp_put(opp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exynos_enable_dvfs(unsigned int cur_frequency)
|
||||
{
|
||||
unsigned int tmp, cpu;
|
||||
struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table;
|
||||
struct cpufreq_frequency_table *pos;
|
||||
/* Disable DVFS */
|
||||
__raw_writel(0, dvfs_info->base + XMU_DVFS_CTRL);
|
||||
|
||||
/* Enable PSTATE Change Event */
|
||||
tmp = __raw_readl(dvfs_info->base + XMU_PMUEVTEN);
|
||||
tmp |= (1 << PSTATE_CHANGED_EVTEN_SHIFT);
|
||||
__raw_writel(tmp, dvfs_info->base + XMU_PMUEVTEN);
|
||||
|
||||
/* Enable PSTATE Change IRQ */
|
||||
tmp = __raw_readl(dvfs_info->base + XMU_PMUIRQEN);
|
||||
tmp |= (1 << PSTATE_CHANGED_IRQEN_SHIFT);
|
||||
__raw_writel(tmp, dvfs_info->base + XMU_PMUIRQEN);
|
||||
|
||||
/* Set initial performance index */
|
||||
cpufreq_for_each_entry(pos, freq_table)
|
||||
if (pos->frequency == cur_frequency)
|
||||
break;
|
||||
|
||||
if (pos->frequency == CPUFREQ_TABLE_END) {
|
||||
dev_crit(dvfs_info->dev, "Boot up frequency not supported\n");
|
||||
/* Assign the highest frequency */
|
||||
pos = freq_table;
|
||||
cur_frequency = pos->frequency;
|
||||
}
|
||||
|
||||
dev_info(dvfs_info->dev, "Setting dvfs initial frequency = %uKHZ",
|
||||
cur_frequency);
|
||||
|
||||
for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) {
|
||||
tmp = __raw_readl(dvfs_info->base + XMU_C0_3_PSTATE + cpu * 4);
|
||||
tmp &= ~(P_VALUE_MASK << C0_3_PSTATE_NEW_SHIFT);
|
||||
tmp |= ((pos - freq_table) << C0_3_PSTATE_NEW_SHIFT);
|
||||
__raw_writel(tmp, dvfs_info->base + XMU_C0_3_PSTATE + cpu * 4);
|
||||
}
|
||||
|
||||
/* Enable DVFS */
|
||||
__raw_writel(1 << XMU_DVFS_CTRL_EN_SHIFT,
|
||||
dvfs_info->base + XMU_DVFS_CTRL);
|
||||
}
|
||||
|
||||
static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
|
||||
{
|
||||
unsigned int tmp;
|
||||
int i;
|
||||
struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table;
|
||||
|
||||
mutex_lock(&cpufreq_lock);
|
||||
|
||||
freqs.old = policy->cur;
|
||||
freqs.new = freq_table[index].frequency;
|
||||
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
|
||||
/* Set the target frequency in all C0_3_PSTATE register */
|
||||
for_each_cpu(i, policy->cpus) {
|
||||
tmp = __raw_readl(dvfs_info->base + XMU_C0_3_PSTATE + i * 4);
|
||||
tmp &= ~(P_VALUE_MASK << C0_3_PSTATE_NEW_SHIFT);
|
||||
tmp |= (index << C0_3_PSTATE_NEW_SHIFT);
|
||||
|
||||
__raw_writel(tmp, dvfs_info->base + XMU_C0_3_PSTATE + i * 4);
|
||||
}
|
||||
mutex_unlock(&cpufreq_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exynos_cpufreq_work(struct work_struct *work)
|
||||
{
|
||||
unsigned int cur_pstate, index;
|
||||
struct cpufreq_policy *policy = cpufreq_cpu_get(0); /* boot CPU */
|
||||
struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table;
|
||||
|
||||
/* Ensure we can access cpufreq structures */
|
||||
if (unlikely(dvfs_info->dvfs_enabled == false))
|
||||
goto skip_work;
|
||||
|
||||
mutex_lock(&cpufreq_lock);
|
||||
freqs.old = policy->cur;
|
||||
|
||||
cur_pstate = __raw_readl(dvfs_info->base + XMU_P_STATUS);
|
||||
if (cur_pstate >> C0_3_PSTATE_VALID_SHIFT & 0x1)
|
||||
index = (cur_pstate >> C0_3_PSTATE_CURR_SHIFT) & P_VALUE_MASK;
|
||||
else
|
||||
index = (cur_pstate >> C0_3_PSTATE_NEW_SHIFT) & P_VALUE_MASK;
|
||||
|
||||
if (likely(index < dvfs_info->freq_count)) {
|
||||
freqs.new = freq_table[index].frequency;
|
||||
} else {
|
||||
dev_crit(dvfs_info->dev, "New frequency out of range\n");
|
||||
freqs.new = freqs.old;
|
||||
}
|
||||
cpufreq_freq_transition_end(policy, &freqs, 0);
|
||||
|
||||
cpufreq_cpu_put(policy);
|
||||
mutex_unlock(&cpufreq_lock);
|
||||
skip_work:
|
||||
enable_irq(dvfs_info->irq);
|
||||
}
|
||||
|
||||
static irqreturn_t exynos_cpufreq_irq(int irq, void *id)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
tmp = __raw_readl(dvfs_info->base + XMU_PMUIRQ);
|
||||
if (tmp >> PSTATE_CHANGED_SHIFT & 0x1) {
|
||||
__raw_writel(tmp, dvfs_info->base + XMU_PMUIRQ);
|
||||
disable_irq_nosync(irq);
|
||||
schedule_work(&dvfs_info->irq_work);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void exynos_sort_descend_freq_table(void)
|
||||
{
|
||||
struct cpufreq_frequency_table *freq_tbl = dvfs_info->freq_table;
|
||||
int i = 0, index;
|
||||
unsigned int tmp_freq;
|
||||
/*
|
||||
* Exynos5440 clock controller state logic expects the cpufreq table to
|
||||
* be in descending order. But the OPP library constructs the table in
|
||||
* ascending order. So to make the table descending we just need to
|
||||
* swap the i element with the N - i element.
|
||||
*/
|
||||
for (i = 0; i < dvfs_info->freq_count / 2; i++) {
|
||||
index = dvfs_info->freq_count - i - 1;
|
||||
tmp_freq = freq_tbl[i].frequency;
|
||||
freq_tbl[i].frequency = freq_tbl[index].frequency;
|
||||
freq_tbl[index].frequency = tmp_freq;
|
||||
}
|
||||
}
|
||||
|
||||
static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
policy->clk = dvfs_info->cpu_clk;
|
||||
return cpufreq_generic_init(policy, dvfs_info->freq_table,
|
||||
dvfs_info->latency);
|
||||
}
|
||||
|
||||
static struct cpufreq_driver exynos_driver = {
|
||||
.flags = CPUFREQ_STICKY | CPUFREQ_ASYNC_NOTIFICATION |
|
||||
CPUFREQ_NEED_INITIAL_FREQ_CHECK,
|
||||
.verify = cpufreq_generic_frequency_table_verify,
|
||||
.target_index = exynos_target,
|
||||
.get = cpufreq_generic_get,
|
||||
.init = exynos_cpufreq_cpu_init,
|
||||
.name = CPUFREQ_NAME,
|
||||
.attr = cpufreq_generic_attr,
|
||||
};
|
||||
|
||||
static const struct of_device_id exynos_cpufreq_match[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos5440-cpufreq",
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, exynos_cpufreq_match);
|
||||
|
||||
static int exynos_cpufreq_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct device_node *np;
|
||||
struct resource res;
|
||||
unsigned int cur_frequency;
|
||||
|
||||
np = pdev->dev.of_node;
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
dvfs_info = devm_kzalloc(&pdev->dev, sizeof(*dvfs_info), GFP_KERNEL);
|
||||
if (!dvfs_info) {
|
||||
ret = -ENOMEM;
|
||||
goto err_put_node;
|
||||
}
|
||||
|
||||
dvfs_info->dev = &pdev->dev;
|
||||
|
||||
ret = of_address_to_resource(np, 0, &res);
|
||||
if (ret)
|
||||
goto err_put_node;
|
||||
|
||||
dvfs_info->base = devm_ioremap_resource(dvfs_info->dev, &res);
|
||||
if (IS_ERR(dvfs_info->base)) {
|
||||
ret = PTR_ERR(dvfs_info->base);
|
||||
goto err_put_node;
|
||||
}
|
||||
|
||||
dvfs_info->irq = irq_of_parse_and_map(np, 0);
|
||||
if (!dvfs_info->irq) {
|
||||
dev_err(dvfs_info->dev, "No cpufreq irq found\n");
|
||||
ret = -ENODEV;
|
||||
goto err_put_node;
|
||||
}
|
||||
|
||||
ret = dev_pm_opp_of_add_table(dvfs_info->dev);
|
||||
if (ret) {
|
||||
dev_err(dvfs_info->dev, "failed to init OPP table: %d\n", ret);
|
||||
goto err_put_node;
|
||||
}
|
||||
|
||||
ret = dev_pm_opp_init_cpufreq_table(dvfs_info->dev,
|
||||
&dvfs_info->freq_table);
|
||||
if (ret) {
|
||||
dev_err(dvfs_info->dev,
|
||||
"failed to init cpufreq table: %d\n", ret);
|
||||
goto err_free_opp;
|
||||
}
|
||||
dvfs_info->freq_count = dev_pm_opp_get_opp_count(dvfs_info->dev);
|
||||
exynos_sort_descend_freq_table();
|
||||
|
||||
if (of_property_read_u32(np, "clock-latency", &dvfs_info->latency))
|
||||
dvfs_info->latency = DEF_TRANS_LATENCY;
|
||||
|
||||
dvfs_info->cpu_clk = devm_clk_get(dvfs_info->dev, "armclk");
|
||||
if (IS_ERR(dvfs_info->cpu_clk)) {
|
||||
dev_err(dvfs_info->dev, "Failed to get cpu clock\n");
|
||||
ret = PTR_ERR(dvfs_info->cpu_clk);
|
||||
goto err_free_table;
|
||||
}
|
||||
|
||||
cur_frequency = clk_get_rate(dvfs_info->cpu_clk);
|
||||
if (!cur_frequency) {
|
||||
dev_err(dvfs_info->dev, "Failed to get clock rate\n");
|
||||
ret = -EINVAL;
|
||||
goto err_free_table;
|
||||
}
|
||||
cur_frequency /= 1000;
|
||||
|
||||
INIT_WORK(&dvfs_info->irq_work, exynos_cpufreq_work);
|
||||
ret = devm_request_irq(dvfs_info->dev, dvfs_info->irq,
|
||||
exynos_cpufreq_irq, IRQF_TRIGGER_NONE,
|
||||
CPUFREQ_NAME, dvfs_info);
|
||||
if (ret) {
|
||||
dev_err(dvfs_info->dev, "Failed to register IRQ\n");
|
||||
goto err_free_table;
|
||||
}
|
||||
|
||||
ret = init_div_table();
|
||||
if (ret) {
|
||||
dev_err(dvfs_info->dev, "Failed to initialise div table\n");
|
||||
goto err_free_table;
|
||||
}
|
||||
|
||||
exynos_enable_dvfs(cur_frequency);
|
||||
ret = cpufreq_register_driver(&exynos_driver);
|
||||
if (ret) {
|
||||
dev_err(dvfs_info->dev,
|
||||
"%s: failed to register cpufreq driver\n", __func__);
|
||||
goto err_free_table;
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
dvfs_info->dvfs_enabled = true;
|
||||
return 0;
|
||||
|
||||
err_free_table:
|
||||
dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
|
||||
err_free_opp:
|
||||
dev_pm_opp_of_remove_table(dvfs_info->dev);
|
||||
err_put_node:
|
||||
of_node_put(np);
|
||||
dev_err(&pdev->dev, "%s: failed initialization\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int exynos_cpufreq_remove(struct platform_device *pdev)
|
||||
{
|
||||
cpufreq_unregister_driver(&exynos_driver);
|
||||
dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
|
||||
dev_pm_opp_of_remove_table(dvfs_info->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver exynos_cpufreq_platdrv = {
|
||||
.driver = {
|
||||
.name = "exynos5440-cpufreq",
|
||||
.of_match_table = exynos_cpufreq_match,
|
||||
},
|
||||
.probe = exynos_cpufreq_probe,
|
||||
.remove = exynos_cpufreq_remove,
|
||||
};
|
||||
module_platform_driver(exynos_cpufreq_platdrv);
|
||||
|
||||
MODULE_AUTHOR("Amit Daniel Kachhap <amit.daniel@samsung.com>");
|
||||
MODULE_DESCRIPTION("Exynos5440 cpufreq driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -35,7 +35,7 @@
|
||||
#ifndef _SG_SW_QM2_H_
|
||||
#define _SG_SW_QM2_H_
|
||||
|
||||
#include "../../../drivers/staging/fsl-mc/include/dpaa2-fd.h"
|
||||
#include <soc/fsl/dpaa2-fd.h>
|
||||
|
||||
static inline void dma_to_qm_sg_one(struct dpaa2_sg_entry *qm_sg_ptr,
|
||||
dma_addr_t dma, u32 len, u16 offset)
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "ctrl.h"
|
||||
#include "regs.h"
|
||||
#include "sg_sw_qm2.h"
|
||||
#include "../../../drivers/staging/fsl-mc/include/dpaa2-fd.h"
|
||||
#include <soc/fsl/dpaa2-fd.h>
|
||||
|
||||
struct sec4_sg_entry {
|
||||
u64 ptr;
|
||||
|
@ -363,8 +363,6 @@ static int scmi_dvfs_device_opps_add(const struct scmi_handle *handle,
|
||||
return domain;
|
||||
|
||||
dom = pi->dom_info + domain;
|
||||
if (!dom)
|
||||
return -EIO;
|
||||
|
||||
for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) {
|
||||
freq = opp->perf * dom->mult_factor;
|
||||
@ -394,9 +392,6 @@ static int scmi_dvfs_transition_latency_get(const struct scmi_handle *handle,
|
||||
return domain;
|
||||
|
||||
dom = pi->dom_info + domain;
|
||||
if (!dom)
|
||||
return -EIO;
|
||||
|
||||
/* uS to nS */
|
||||
return dom->opp[dom->opp_count - 1].trans_latency_us * 1000;
|
||||
}
|
||||
|
@ -77,28 +77,6 @@ static int psci_ops_check(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int find_cpu_groups(const struct cpumask *cpus,
|
||||
const struct cpumask **cpu_groups)
|
||||
{
|
||||
unsigned int nb = 0;
|
||||
cpumask_var_t tmp;
|
||||
|
||||
if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
cpumask_copy(tmp, cpus);
|
||||
|
||||
while (!cpumask_empty(tmp)) {
|
||||
const struct cpumask *cpu_group =
|
||||
topology_core_cpumask(cpumask_any(tmp));
|
||||
|
||||
cpu_groups[nb++] = cpu_group;
|
||||
cpumask_andnot(tmp, tmp, cpu_group);
|
||||
}
|
||||
|
||||
free_cpumask_var(tmp);
|
||||
return nb;
|
||||
}
|
||||
|
||||
/*
|
||||
* offlined_cpus is a temporary array but passing it as an argument avoids
|
||||
* multiple allocations.
|
||||
@ -166,29 +144,66 @@ static unsigned int down_and_up_cpus(const struct cpumask *cpus,
|
||||
return err;
|
||||
}
|
||||
|
||||
static void free_cpu_groups(int num, cpumask_var_t **pcpu_groups)
|
||||
{
|
||||
int i;
|
||||
cpumask_var_t *cpu_groups = *pcpu_groups;
|
||||
|
||||
for (i = 0; i < num; ++i)
|
||||
free_cpumask_var(cpu_groups[i]);
|
||||
kfree(cpu_groups);
|
||||
}
|
||||
|
||||
static int alloc_init_cpu_groups(cpumask_var_t **pcpu_groups)
|
||||
{
|
||||
int num_groups = 0;
|
||||
cpumask_var_t tmp, *cpu_groups;
|
||||
|
||||
if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
cpu_groups = kcalloc(nb_available_cpus, sizeof(cpu_groups),
|
||||
GFP_KERNEL);
|
||||
if (!cpu_groups)
|
||||
return -ENOMEM;
|
||||
|
||||
cpumask_copy(tmp, cpu_online_mask);
|
||||
|
||||
while (!cpumask_empty(tmp)) {
|
||||
const struct cpumask *cpu_group =
|
||||
topology_core_cpumask(cpumask_any(tmp));
|
||||
|
||||
if (!alloc_cpumask_var(&cpu_groups[num_groups], GFP_KERNEL)) {
|
||||
free_cpu_groups(num_groups, &cpu_groups);
|
||||
return -ENOMEM;
|
||||
}
|
||||
cpumask_copy(cpu_groups[num_groups++], cpu_group);
|
||||
cpumask_andnot(tmp, tmp, cpu_group);
|
||||
}
|
||||
|
||||
free_cpumask_var(tmp);
|
||||
*pcpu_groups = cpu_groups;
|
||||
|
||||
return num_groups;
|
||||
}
|
||||
|
||||
static int hotplug_tests(void)
|
||||
{
|
||||
int err;
|
||||
cpumask_var_t offlined_cpus;
|
||||
int i, nb_cpu_group;
|
||||
const struct cpumask **cpu_groups;
|
||||
int i, nb_cpu_group, err = -ENOMEM;
|
||||
cpumask_var_t offlined_cpus, *cpu_groups;
|
||||
char *page_buf;
|
||||
|
||||
err = -ENOMEM;
|
||||
if (!alloc_cpumask_var(&offlined_cpus, GFP_KERNEL))
|
||||
return err;
|
||||
/* We may have up to nb_available_cpus cpu_groups. */
|
||||
cpu_groups = kmalloc_array(nb_available_cpus, sizeof(*cpu_groups),
|
||||
GFP_KERNEL);
|
||||
if (!cpu_groups)
|
||||
|
||||
nb_cpu_group = alloc_init_cpu_groups(&cpu_groups);
|
||||
if (nb_cpu_group < 0)
|
||||
goto out_free_cpus;
|
||||
page_buf = (char *)__get_free_page(GFP_KERNEL);
|
||||
if (!page_buf)
|
||||
goto out_free_cpu_groups;
|
||||
|
||||
err = 0;
|
||||
nb_cpu_group = find_cpu_groups(cpu_online_mask, cpu_groups);
|
||||
|
||||
/*
|
||||
* Of course the last CPU cannot be powered down and cpu_down() should
|
||||
* refuse doing that.
|
||||
@ -212,7 +227,7 @@ static int hotplug_tests(void)
|
||||
|
||||
free_page((unsigned long)page_buf);
|
||||
out_free_cpu_groups:
|
||||
kfree(cpu_groups);
|
||||
free_cpu_groups(nb_cpu_group, &cpu_groups);
|
||||
out_free_cpus:
|
||||
free_cpumask_var(offlined_cpus);
|
||||
return err;
|
||||
|
@ -21,6 +21,10 @@
|
||||
#define MBOX_DATA28(msg) ((msg) & ~0xf)
|
||||
#define MBOX_CHAN_PROPERTY 8
|
||||
|
||||
#define MAX_RPI_FW_PROP_BUF_SIZE 32
|
||||
|
||||
static struct platform_device *rpi_hwmon;
|
||||
|
||||
struct rpi_firmware {
|
||||
struct mbox_client cl;
|
||||
struct mbox_chan *chan; /* The property channel. */
|
||||
@ -143,18 +147,22 @@ int rpi_firmware_property(struct rpi_firmware *fw,
|
||||
/* Single tags are very small (generally 8 bytes), so the
|
||||
* stack should be safe.
|
||||
*/
|
||||
u8 data[buf_size + sizeof(struct rpi_firmware_property_tag_header)];
|
||||
u8 data[sizeof(struct rpi_firmware_property_tag_header) +
|
||||
MAX_RPI_FW_PROP_BUF_SIZE];
|
||||
struct rpi_firmware_property_tag_header *header =
|
||||
(struct rpi_firmware_property_tag_header *)data;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(buf_size > sizeof(data) - sizeof(*header)))
|
||||
return -EINVAL;
|
||||
|
||||
header->tag = tag;
|
||||
header->buf_size = buf_size;
|
||||
header->req_resp_size = 0;
|
||||
memcpy(data + sizeof(struct rpi_firmware_property_tag_header),
|
||||
tag_data, buf_size);
|
||||
|
||||
ret = rpi_firmware_property_list(fw, &data, sizeof(data));
|
||||
ret = rpi_firmware_property_list(fw, &data, buf_size + sizeof(*header));
|
||||
memcpy(tag_data,
|
||||
data + sizeof(struct rpi_firmware_property_tag_header),
|
||||
buf_size);
|
||||
@ -183,6 +191,20 @@ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
|
||||
{
|
||||
u32 packet;
|
||||
int ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_THROTTLED,
|
||||
&packet, sizeof(packet));
|
||||
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
rpi_hwmon = platform_device_register_data(dev, "raspberrypi-hwmon",
|
||||
-1, NULL, 0);
|
||||
}
|
||||
|
||||
static int rpi_firmware_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -209,6 +231,7 @@ static int rpi_firmware_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, fw);
|
||||
|
||||
rpi_firmware_print_firmware_revision(fw);
|
||||
rpi_register_hwmon_driver(dev, fw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -217,6 +240,8 @@ static int rpi_firmware_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rpi_firmware *fw = platform_get_drvdata(pdev);
|
||||
|
||||
platform_device_unregister(rpi_hwmon);
|
||||
rpi_hwmon = NULL;
|
||||
mbox_free_channel(fw->chan);
|
||||
|
||||
return 0;
|
||||
|
@ -1320,6 +1320,16 @@ config SENSORS_PWM_FAN
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called pwm-fan.
|
||||
|
||||
config SENSORS_RASPBERRYPI_HWMON
|
||||
tristate "Raspberry Pi voltage monitor"
|
||||
depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE)
|
||||
help
|
||||
If you say yes here you get support for voltage sensor on the
|
||||
Raspberry Pi.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called raspberrypi-hwmon.
|
||||
|
||||
config SENSORS_SHT15
|
||||
tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
|
||||
depends on GPIOLIB || COMPILE_TEST
|
||||
|
@ -143,6 +143,7 @@ obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
|
||||
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
|
||||
obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o
|
||||
obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
|
||||
obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
|
||||
obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
|
||||
|
166
drivers/hwmon/raspberrypi-hwmon.c
Normal file
166
drivers/hwmon/raspberrypi-hwmon.c
Normal file
@ -0,0 +1,166 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Raspberry Pi voltage sensor driver
|
||||
*
|
||||
* Based on firmware/raspberrypi.c by Noralf Trønnes
|
||||
*
|
||||
* Copyright (C) 2018 Stefan Wahren <stefan.wahren@i2se.com>
|
||||
*/
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <soc/bcm2835/raspberrypi-firmware.h>
|
||||
|
||||
#define UNDERVOLTAGE_STICKY_BIT BIT(16)
|
||||
|
||||
struct rpi_hwmon_data {
|
||||
struct device *hwmon_dev;
|
||||
struct rpi_firmware *fw;
|
||||
u32 last_throttled;
|
||||
struct delayed_work get_values_poll_work;
|
||||
};
|
||||
|
||||
static void rpi_firmware_get_throttled(struct rpi_hwmon_data *data)
|
||||
{
|
||||
u32 new_uv, old_uv, value;
|
||||
int ret;
|
||||
|
||||
/* Request firmware to clear sticky bits */
|
||||
value = 0xffff;
|
||||
|
||||
ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
|
||||
&value, sizeof(value));
|
||||
if (ret) {
|
||||
dev_err_once(data->hwmon_dev, "Failed to get throttled (%d)\n",
|
||||
ret);
|
||||
return;
|
||||
}
|
||||
|
||||
new_uv = value & UNDERVOLTAGE_STICKY_BIT;
|
||||
old_uv = data->last_throttled & UNDERVOLTAGE_STICKY_BIT;
|
||||
data->last_throttled = value;
|
||||
|
||||
if (new_uv == old_uv)
|
||||
return;
|
||||
|
||||
if (new_uv)
|
||||
dev_crit(data->hwmon_dev, "Undervoltage detected!\n");
|
||||
else
|
||||
dev_info(data->hwmon_dev, "Voltage normalised\n");
|
||||
|
||||
sysfs_notify(&data->hwmon_dev->kobj, NULL, "in0_lcrit_alarm");
|
||||
}
|
||||
|
||||
static void get_values_poll(struct work_struct *work)
|
||||
{
|
||||
struct rpi_hwmon_data *data;
|
||||
|
||||
data = container_of(work, struct rpi_hwmon_data,
|
||||
get_values_poll_work.work);
|
||||
|
||||
rpi_firmware_get_throttled(data);
|
||||
|
||||
/*
|
||||
* We can't run faster than the sticky shift (100ms) since we get
|
||||
* flipping in the sticky bits that are cleared.
|
||||
*/
|
||||
schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
|
||||
}
|
||||
|
||||
static int rpi_read(struct device *dev, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, long *val)
|
||||
{
|
||||
struct rpi_hwmon_data *data = dev_get_drvdata(dev);
|
||||
|
||||
*val = !!(data->last_throttled & UNDERVOLTAGE_STICKY_BIT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static umode_t rpi_is_visible(const void *_data, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel)
|
||||
{
|
||||
return 0444;
|
||||
}
|
||||
|
||||
static const u32 rpi_in_config[] = {
|
||||
HWMON_I_LCRIT_ALARM,
|
||||
0
|
||||
};
|
||||
|
||||
static const struct hwmon_channel_info rpi_in = {
|
||||
.type = hwmon_in,
|
||||
.config = rpi_in_config,
|
||||
};
|
||||
|
||||
static const struct hwmon_channel_info *rpi_info[] = {
|
||||
&rpi_in,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct hwmon_ops rpi_hwmon_ops = {
|
||||
.is_visible = rpi_is_visible,
|
||||
.read = rpi_read,
|
||||
};
|
||||
|
||||
static const struct hwmon_chip_info rpi_chip_info = {
|
||||
.ops = &rpi_hwmon_ops,
|
||||
.info = rpi_info,
|
||||
};
|
||||
|
||||
static int rpi_hwmon_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct rpi_hwmon_data *data;
|
||||
int ret;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Parent driver assure that firmware is correct */
|
||||
data->fw = dev_get_drvdata(dev->parent);
|
||||
|
||||
/* Init throttled */
|
||||
ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
|
||||
&data->last_throttled,
|
||||
sizeof(data->last_throttled));
|
||||
|
||||
data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "rpi_volt",
|
||||
data,
|
||||
&rpi_chip_info,
|
||||
NULL);
|
||||
|
||||
INIT_DELAYED_WORK(&data->get_values_poll_work, get_values_poll);
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
if (!PTR_ERR_OR_ZERO(data->hwmon_dev))
|
||||
schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
|
||||
|
||||
return PTR_ERR_OR_ZERO(data->hwmon_dev);
|
||||
}
|
||||
|
||||
static int rpi_hwmon_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rpi_hwmon_data *data = platform_get_drvdata(pdev);
|
||||
|
||||
cancel_delayed_work_sync(&data->get_values_poll_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rpi_hwmon_driver = {
|
||||
.probe = rpi_hwmon_probe,
|
||||
.remove = rpi_hwmon_remove,
|
||||
.driver = {
|
||||
.name = "raspberrypi-hwmon",
|
||||
},
|
||||
};
|
||||
module_platform_driver(rpi_hwmon_driver);
|
||||
|
||||
MODULE_AUTHOR("Stefan Wahren <stefan.wahren@i2se.com>");
|
||||
MODULE_DESCRIPTION("Raspberry Pi voltage sensor driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -672,13 +672,6 @@ static int tegra_mc_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = tegra_mc_reset_setup(mc);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to register reset controller: %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
|
||||
mc->irq = platform_get_irq(pdev, 0);
|
||||
if (mc->irq < 0) {
|
||||
dev_err(&pdev->dev, "interrupt not specified\n");
|
||||
@ -697,13 +690,16 @@ static int tegra_mc_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = tegra_mc_reset_setup(mc);
|
||||
if (err < 0)
|
||||
dev_err(&pdev->dev, "failed to register reset controller: %d\n",
|
||||
err);
|
||||
|
||||
if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU)) {
|
||||
mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc);
|
||||
if (IS_ERR(mc->smmu)) {
|
||||
if (IS_ERR(mc->smmu))
|
||||
dev_err(&pdev->dev, "failed to probe SMMU: %ld\n",
|
||||
PTR_ERR(mc->smmu));
|
||||
return PTR_ERR(mc->smmu);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -249,6 +249,34 @@ static const struct of_device_id ti_emif_of_match[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ti_emif_of_match);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int ti_emif_resume(struct device *dev)
|
||||
{
|
||||
unsigned long tmp =
|
||||
__raw_readl((void *)emif_instance->ti_emif_sram_virt);
|
||||
|
||||
/*
|
||||
* Check to see if what we are copying is already present in the
|
||||
* first byte at the destination, only copy if it is not which
|
||||
* indicates we have lost context and sram no longer contains
|
||||
* the PM code
|
||||
*/
|
||||
if (tmp != ti_emif_sram)
|
||||
ti_emif_push_sram(dev, emif_instance);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ti_emif_suspend(struct device *dev)
|
||||
{
|
||||
/*
|
||||
* The contents will be present in DDR hence no need to
|
||||
* explicitly save
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static int ti_emif_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
@ -308,12 +336,17 @@ static int ti_emif_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops ti_emif_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(ti_emif_suspend, ti_emif_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver ti_emif_driver = {
|
||||
.probe = ti_emif_probe,
|
||||
.remove = ti_emif_remove,
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.of_match_table = of_match_ptr(ti_emif_of_match),
|
||||
.pm = &ti_emif_pm_ops,
|
||||
},
|
||||
};
|
||||
module_platform_driver(ti_emif_driver);
|
||||
|
@ -82,6 +82,15 @@ config RESET_PISTACHIO
|
||||
help
|
||||
This enables the reset driver for ImgTec Pistachio SoCs.
|
||||
|
||||
config RESET_QCOM_AOSS
|
||||
bool "Qcom AOSS Reset Driver"
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
help
|
||||
This enables the AOSS (always on subsystem) reset driver
|
||||
for Qualcomm SDM845 SoCs. Say Y if you want to control
|
||||
reset signals provided by AOSS for Modem, Venus, ADSP,
|
||||
GPU, Camera, Wireless, Display subsystem. Otherwise, say N.
|
||||
|
||||
config RESET_SIMPLE
|
||||
bool "Simple Reset Controller Driver" if COMPILE_TEST
|
||||
default ARCH_SOCFPGA || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED
|
||||
@ -138,6 +147,16 @@ config RESET_UNIPHIER
|
||||
Say Y if you want to control reset signals provided by System Control
|
||||
block, Media I/O block, Peripheral Block.
|
||||
|
||||
config RESET_UNIPHIER_USB3
|
||||
tristate "USB3 reset driver for UniPhier SoCs"
|
||||
depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF
|
||||
default ARCH_UNIPHIER
|
||||
select RESET_SIMPLE
|
||||
help
|
||||
Support for the USB3 core reset on UniPhier SoCs.
|
||||
Say Y if you want to control reset signals provided by
|
||||
USB3 glue layer.
|
||||
|
||||
config RESET_ZYNQ
|
||||
bool "ZYNQ Reset Driver" if COMPILE_TEST
|
||||
default ARCH_ZYNQ
|
||||
|
@ -14,11 +14,13 @@ obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
|
||||
obj-$(CONFIG_RESET_MESON) += reset-meson.o
|
||||
obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
|
||||
obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
|
||||
obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
|
||||
obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
|
||||
obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
|
||||
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
|
||||
obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
|
||||
obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
|
||||
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
|
||||
obj-$(CONFIG_RESET_UNIPHIER_USB3) += reset-uniphier-usb3.o
|
||||
obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
|
||||
|
||||
|
133
drivers/reset/reset-qcom-aoss.c
Normal file
133
drivers/reset/reset-qcom-aoss.c
Normal file
@ -0,0 +1,133 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2018 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <dt-bindings/reset/qcom,sdm845-aoss.h>
|
||||
|
||||
struct qcom_aoss_reset_map {
|
||||
unsigned int reg;
|
||||
};
|
||||
|
||||
struct qcom_aoss_desc {
|
||||
const struct qcom_aoss_reset_map *resets;
|
||||
size_t num_resets;
|
||||
};
|
||||
|
||||
struct qcom_aoss_reset_data {
|
||||
struct reset_controller_dev rcdev;
|
||||
void __iomem *base;
|
||||
const struct qcom_aoss_desc *desc;
|
||||
};
|
||||
|
||||
static const struct qcom_aoss_reset_map sdm845_aoss_resets[] = {
|
||||
[AOSS_CC_MSS_RESTART] = {0x10000},
|
||||
[AOSS_CC_CAMSS_RESTART] = {0x11000},
|
||||
[AOSS_CC_VENUS_RESTART] = {0x12000},
|
||||
[AOSS_CC_GPU_RESTART] = {0x13000},
|
||||
[AOSS_CC_DISPSS_RESTART] = {0x14000},
|
||||
[AOSS_CC_WCSS_RESTART] = {0x20000},
|
||||
[AOSS_CC_LPASS_RESTART] = {0x30000},
|
||||
};
|
||||
|
||||
static const struct qcom_aoss_desc sdm845_aoss_desc = {
|
||||
.resets = sdm845_aoss_resets,
|
||||
.num_resets = ARRAY_SIZE(sdm845_aoss_resets),
|
||||
};
|
||||
|
||||
static inline struct qcom_aoss_reset_data *to_qcom_aoss_reset_data(
|
||||
struct reset_controller_dev *rcdev)
|
||||
{
|
||||
return container_of(rcdev, struct qcom_aoss_reset_data, rcdev);
|
||||
}
|
||||
|
||||
static int qcom_aoss_control_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long idx)
|
||||
{
|
||||
struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
|
||||
const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
|
||||
|
||||
writel(1, data->base + map->reg);
|
||||
/* Wait 6 32kHz sleep cycles for reset */
|
||||
usleep_range(200, 300);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_aoss_control_deassert(struct reset_controller_dev *rcdev,
|
||||
unsigned long idx)
|
||||
{
|
||||
struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
|
||||
const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
|
||||
|
||||
writel(0, data->base + map->reg);
|
||||
/* Wait 6 32kHz sleep cycles for reset */
|
||||
usleep_range(200, 300);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_aoss_control_reset(struct reset_controller_dev *rcdev,
|
||||
unsigned long idx)
|
||||
{
|
||||
qcom_aoss_control_assert(rcdev, idx);
|
||||
|
||||
return qcom_aoss_control_deassert(rcdev, idx);
|
||||
}
|
||||
|
||||
static const struct reset_control_ops qcom_aoss_reset_ops = {
|
||||
.reset = qcom_aoss_control_reset,
|
||||
.assert = qcom_aoss_control_assert,
|
||||
.deassert = qcom_aoss_control_deassert,
|
||||
};
|
||||
|
||||
static int qcom_aoss_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_aoss_reset_data *data;
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct qcom_aoss_desc *desc;
|
||||
struct resource *res;
|
||||
|
||||
desc = of_device_get_match_data(dev);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->desc = desc;
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
data->base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(data->base))
|
||||
return PTR_ERR(data->base);
|
||||
|
||||
data->rcdev.owner = THIS_MODULE;
|
||||
data->rcdev.ops = &qcom_aoss_reset_ops;
|
||||
data->rcdev.nr_resets = desc->num_resets;
|
||||
data->rcdev.of_node = dev->of_node;
|
||||
|
||||
return devm_reset_controller_register(dev, &data->rcdev);
|
||||
}
|
||||
|
||||
static const struct of_device_id qcom_aoss_reset_of_match[] = {
|
||||
{ .compatible = "qcom,sdm845-aoss-cc", .data = &sdm845_aoss_desc },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver qcom_aoss_reset_driver = {
|
||||
.probe = qcom_aoss_reset_probe,
|
||||
.driver = {
|
||||
.name = "qcom_aoss_reset",
|
||||
.of_match_table = qcom_aoss_reset_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(qcom_aoss_reset_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Qualcomm AOSS Reset Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -87,6 +87,7 @@ const struct reset_control_ops reset_simple_ops = {
|
||||
.deassert = reset_simple_deassert,
|
||||
.status = reset_simple_status,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(reset_simple_ops);
|
||||
|
||||
/**
|
||||
* struct reset_simple_devdata - simple reset controller properties
|
||||
|
171
drivers/reset/reset-uniphier-usb3.c
Normal file
171
drivers/reset/reset-uniphier-usb3.c
Normal file
@ -0,0 +1,171 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// reset-uniphier-usb3.c - USB3 reset driver for UniPhier
|
||||
// Copyright 2018 Socionext Inc.
|
||||
// Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#include "reset-simple.h"
|
||||
|
||||
#define MAX_CLKS 2
|
||||
#define MAX_RSTS 2
|
||||
|
||||
struct uniphier_usb3_reset_soc_data {
|
||||
int nclks;
|
||||
const char * const *clock_names;
|
||||
int nrsts;
|
||||
const char * const *reset_names;
|
||||
};
|
||||
|
||||
struct uniphier_usb3_reset_priv {
|
||||
struct clk_bulk_data clk[MAX_CLKS];
|
||||
struct reset_control *rst[MAX_RSTS];
|
||||
struct reset_simple_data rdata;
|
||||
const struct uniphier_usb3_reset_soc_data *data;
|
||||
};
|
||||
|
||||
static int uniphier_usb3_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct uniphier_usb3_reset_priv *priv;
|
||||
struct resource *res;
|
||||
resource_size_t size;
|
||||
const char *name;
|
||||
int i, ret, nr;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->data = of_device_get_match_data(dev);
|
||||
if (WARN_ON(!priv->data || priv->data->nclks > MAX_CLKS ||
|
||||
priv->data->nrsts > MAX_RSTS))
|
||||
return -EINVAL;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
size = resource_size(res);
|
||||
priv->rdata.membase = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->rdata.membase))
|
||||
return PTR_ERR(priv->rdata.membase);
|
||||
|
||||
for (i = 0; i < priv->data->nclks; i++)
|
||||
priv->clk[i].id = priv->data->clock_names[i];
|
||||
ret = devm_clk_bulk_get(dev, priv->data->nclks, priv->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < priv->data->nrsts; i++) {
|
||||
name = priv->data->reset_names[i];
|
||||
priv->rst[i] = devm_reset_control_get_shared(dev, name);
|
||||
if (IS_ERR(priv->rst[i]))
|
||||
return PTR_ERR(priv->rst[i]);
|
||||
}
|
||||
|
||||
ret = clk_bulk_prepare_enable(priv->data->nclks, priv->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (nr = 0; nr < priv->data->nrsts; nr++) {
|
||||
ret = reset_control_deassert(priv->rst[nr]);
|
||||
if (ret)
|
||||
goto out_rst_assert;
|
||||
}
|
||||
|
||||
spin_lock_init(&priv->rdata.lock);
|
||||
priv->rdata.rcdev.owner = THIS_MODULE;
|
||||
priv->rdata.rcdev.nr_resets = size * BITS_PER_BYTE;
|
||||
priv->rdata.rcdev.ops = &reset_simple_ops;
|
||||
priv->rdata.rcdev.of_node = dev->of_node;
|
||||
priv->rdata.active_low = true;
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
ret = devm_reset_controller_register(dev, &priv->rdata.rcdev);
|
||||
if (ret)
|
||||
goto out_rst_assert;
|
||||
|
||||
return 0;
|
||||
|
||||
out_rst_assert:
|
||||
while (nr--)
|
||||
reset_control_assert(priv->rst[nr]);
|
||||
|
||||
clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uniphier_usb3_reset_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct uniphier_usb3_reset_priv *priv = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->data->nrsts; i++)
|
||||
reset_control_assert(priv->rst[i]);
|
||||
|
||||
clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char * const uniphier_pro4_clock_reset_names[] = {
|
||||
"gio", "link",
|
||||
};
|
||||
|
||||
static const struct uniphier_usb3_reset_soc_data uniphier_pro4_data = {
|
||||
.nclks = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
|
||||
.clock_names = uniphier_pro4_clock_reset_names,
|
||||
.nrsts = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
|
||||
.reset_names = uniphier_pro4_clock_reset_names,
|
||||
};
|
||||
|
||||
static const char * const uniphier_pxs2_clock_reset_names[] = {
|
||||
"link",
|
||||
};
|
||||
|
||||
static const struct uniphier_usb3_reset_soc_data uniphier_pxs2_data = {
|
||||
.nclks = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
|
||||
.clock_names = uniphier_pxs2_clock_reset_names,
|
||||
.nrsts = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
|
||||
.reset_names = uniphier_pxs2_clock_reset_names,
|
||||
};
|
||||
|
||||
static const struct of_device_id uniphier_usb3_reset_match[] = {
|
||||
{
|
||||
.compatible = "socionext,uniphier-pro4-usb3-reset",
|
||||
.data = &uniphier_pro4_data,
|
||||
},
|
||||
{
|
||||
.compatible = "socionext,uniphier-pxs2-usb3-reset",
|
||||
.data = &uniphier_pxs2_data,
|
||||
},
|
||||
{
|
||||
.compatible = "socionext,uniphier-ld20-usb3-reset",
|
||||
.data = &uniphier_pxs2_data,
|
||||
},
|
||||
{
|
||||
.compatible = "socionext,uniphier-pxs3-usb3-reset",
|
||||
.data = &uniphier_pxs2_data,
|
||||
},
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, uniphier_usb3_reset_match);
|
||||
|
||||
static struct platform_driver uniphier_usb3_reset_driver = {
|
||||
.probe = uniphier_usb3_reset_probe,
|
||||
.remove = uniphier_usb3_reset_remove,
|
||||
.driver = {
|
||||
.name = "uniphier-usb3-reset",
|
||||
.of_match_table = uniphier_usb3_reset_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(uniphier_usb3_reset_driver);
|
||||
|
||||
MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
|
||||
MODULE_DESCRIPTION("UniPhier USB3 Reset Driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -202,6 +202,12 @@ static const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
|
||||
#define UNIPHIER_PERI_RESET_FI2C(id, ch) \
|
||||
UNIPHIER_RESETX((id), 0x114, 24 + (ch))
|
||||
|
||||
#define UNIPHIER_PERI_RESET_SCSSI(id) \
|
||||
UNIPHIER_RESETX((id), 0x110, 17)
|
||||
|
||||
#define UNIPHIER_PERI_RESET_MCSSI(id) \
|
||||
UNIPHIER_RESETX((id), 0x114, 14)
|
||||
|
||||
static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
|
||||
UNIPHIER_PERI_RESET_UART(0, 0),
|
||||
UNIPHIER_PERI_RESET_UART(1, 1),
|
||||
@ -212,6 +218,7 @@ static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
|
||||
UNIPHIER_PERI_RESET_I2C(6, 2),
|
||||
UNIPHIER_PERI_RESET_I2C(7, 3),
|
||||
UNIPHIER_PERI_RESET_I2C(8, 4),
|
||||
UNIPHIER_PERI_RESET_SCSSI(11),
|
||||
UNIPHIER_RESET_END,
|
||||
};
|
||||
|
||||
@ -227,6 +234,8 @@ static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
|
||||
UNIPHIER_PERI_RESET_FI2C(8, 4),
|
||||
UNIPHIER_PERI_RESET_FI2C(9, 5),
|
||||
UNIPHIER_PERI_RESET_FI2C(10, 6),
|
||||
UNIPHIER_PERI_RESET_SCSSI(11),
|
||||
UNIPHIER_PERI_RESET_MCSSI(12),
|
||||
UNIPHIER_RESET_END,
|
||||
};
|
||||
|
||||
|
@ -627,10 +627,26 @@ static const struct of_device_id ddr_shimphy_dt_ids[] = {
|
||||
};
|
||||
|
||||
static const struct of_device_id brcmstb_memc_of_match[] = {
|
||||
{
|
||||
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.1",
|
||||
.data = &ddr_seq,
|
||||
},
|
||||
{
|
||||
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.2",
|
||||
.data = &ddr_seq_b22,
|
||||
},
|
||||
{
|
||||
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.3",
|
||||
.data = &ddr_seq_b22,
|
||||
},
|
||||
{
|
||||
.compatible = "brcm,brcmstb-memc-ddr-rev-b.3.0",
|
||||
.data = &ddr_seq_b22,
|
||||
},
|
||||
{
|
||||
.compatible = "brcm,brcmstb-memc-ddr-rev-b.3.1",
|
||||
.data = &ddr_seq_b22,
|
||||
},
|
||||
{
|
||||
.compatible = "brcm,brcmstb-memc-ddr",
|
||||
.data = &ddr_seq,
|
||||
|
@ -1,7 +1,9 @@
|
||||
#
|
||||
# Freescale SOC drivers
|
||||
# NXP/Freescale QorIQ series SOC drivers
|
||||
#
|
||||
|
||||
menu "NXP/Freescale QorIQ SoC drivers"
|
||||
|
||||
source "drivers/soc/fsl/qbman/Kconfig"
|
||||
source "drivers/soc/fsl/qe/Kconfig"
|
||||
|
||||
@ -16,3 +18,14 @@ config FSL_GUTS
|
||||
Initially only reading SVR and registering soc device are supported.
|
||||
Other guts accesses, such as reading RCW, should eventually be moved
|
||||
into this driver as well.
|
||||
|
||||
config FSL_MC_DPIO
|
||||
tristate "QorIQ DPAA2 DPIO driver"
|
||||
depends on FSL_MC_BUS
|
||||
help
|
||||
Driver for the DPAA2 DPIO object. A DPIO provides queue and
|
||||
buffer management facilities for software to interact with
|
||||
other DPAA2 objects. This driver does not expose the DPIO
|
||||
objects individually, but groups them under a service layer
|
||||
API.
|
||||
endmenu
|
||||
|
@ -6,3 +6,4 @@ obj-$(CONFIG_FSL_DPAA) += qbman/
|
||||
obj-$(CONFIG_QUICC_ENGINE) += qe/
|
||||
obj-$(CONFIG_CPM) += qe/
|
||||
obj-$(CONFIG_FSL_GUTS) += guts.o
|
||||
obj-$(CONFIG_FSL_MC_DPIO) += dpio/
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <linux/fsl/mc.h>
|
||||
#include "../../include/dpaa2-io.h"
|
||||
#include <soc/fsl/dpaa2-io.h>
|
||||
|
||||
#include "qbman-portal.h"
|
||||
#include "dpio.h"
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/fsl/mc.h>
|
||||
#include "../../include/dpaa2-io.h"
|
||||
#include <soc/fsl/dpaa2-io.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
@ -8,7 +8,7 @@
|
||||
#include <asm/cacheflush.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include "../../include/dpaa2-global.h"
|
||||
#include <soc/fsl/dpaa2-global.h>
|
||||
|
||||
#include "qbman-portal.h"
|
||||
|
@ -7,7 +7,7 @@
|
||||
#ifndef __FSL_QBMAN_PORTAL_H
|
||||
#define __FSL_QBMAN_PORTAL_H
|
||||
|
||||
#include "../../include/dpaa2-fd.h"
|
||||
#include <soc/fsl/dpaa2-fd.h>
|
||||
|
||||
struct dpaa2_dq;
|
||||
struct qbman_swp;
|
@ -1,5 +1,5 @@
|
||||
menuconfig FSL_DPAA
|
||||
bool "Freescale DPAA 1.x support"
|
||||
bool "QorIQ DPAA1 framework support"
|
||||
depends on (FSL_SOC_BOOKE || ARCH_LAYERSCAPE)
|
||||
select GENERIC_ALLOCATOR
|
||||
help
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
config QUICC_ENGINE
|
||||
bool "Freescale QUICC Engine (QE) Support"
|
||||
bool "QUICC Engine (QE) framework support"
|
||||
depends on FSL_SOC && PPC32
|
||||
select GENERIC_ALLOCATOR
|
||||
select CRC32
|
||||
|
@ -83,6 +83,33 @@ static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
spin_unlock_irqrestore(&qe_gc->lock, flags);
|
||||
}
|
||||
|
||||
static void qe_gpio_set_multiple(struct gpio_chip *gc,
|
||||
unsigned long *mask, unsigned long *bits)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||
struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc);
|
||||
struct qe_pio_regs __iomem *regs = mm_gc->regs;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&qe_gc->lock, flags);
|
||||
|
||||
for (i = 0; i < gc->ngpio; i++) {
|
||||
if (*mask == 0)
|
||||
break;
|
||||
if (__test_and_clear_bit(i, mask)) {
|
||||
if (test_bit(i, bits))
|
||||
qe_gc->cpdata |= (1U << (QE_PIO_PINS - 1 - i));
|
||||
else
|
||||
qe_gc->cpdata &= ~(1U << (QE_PIO_PINS - 1 - i));
|
||||
}
|
||||
}
|
||||
|
||||
out_be32(®s->cpdata, qe_gc->cpdata);
|
||||
|
||||
spin_unlock_irqrestore(&qe_gc->lock, flags);
|
||||
}
|
||||
|
||||
static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||
@ -298,6 +325,7 @@ static int __init qe_add_gpiochips(void)
|
||||
gc->direction_output = qe_gpio_dir_out;
|
||||
gc->get = qe_gpio_get;
|
||||
gc->set = qe_gpio_set;
|
||||
gc->set_multiple = qe_gpio_set_multiple;
|
||||
|
||||
ret = of_mm_gpiochip_add_data(np, mm_gc, qe_gc);
|
||||
if (ret)
|
||||
|
@ -54,7 +54,6 @@ struct imx_pm_domain {
|
||||
unsigned int reg_offs;
|
||||
signed char cntr_pdn_bit;
|
||||
unsigned int ipg_rate_mhz;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
static inline struct imx_pm_domain *
|
||||
@ -69,9 +68,6 @@ static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd)
|
||||
int iso, iso2sw;
|
||||
u32 val;
|
||||
|
||||
if (pd->flags & PGC_DOMAIN_FLAG_NO_PD)
|
||||
return -EBUSY;
|
||||
|
||||
/* Read ISO and ISO2SW power down delays */
|
||||
regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val);
|
||||
iso = val & 0x3f;
|
||||
@ -295,26 +291,31 @@ static struct imx_pm_domain imx_gpc_domains[] = {
|
||||
struct imx_gpc_dt_data {
|
||||
int num_domains;
|
||||
bool err009619_present;
|
||||
bool err006287_present;
|
||||
};
|
||||
|
||||
static const struct imx_gpc_dt_data imx6q_dt_data = {
|
||||
.num_domains = 2,
|
||||
.err009619_present = false,
|
||||
.err006287_present = false,
|
||||
};
|
||||
|
||||
static const struct imx_gpc_dt_data imx6qp_dt_data = {
|
||||
.num_domains = 2,
|
||||
.err009619_present = true,
|
||||
.err006287_present = false,
|
||||
};
|
||||
|
||||
static const struct imx_gpc_dt_data imx6sl_dt_data = {
|
||||
.num_domains = 3,
|
||||
.err009619_present = false,
|
||||
.err006287_present = true,
|
||||
};
|
||||
|
||||
static const struct imx_gpc_dt_data imx6sx_dt_data = {
|
||||
.num_domains = 4,
|
||||
.err009619_present = false,
|
||||
.err006287_present = false,
|
||||
};
|
||||
|
||||
static const struct of_device_id imx_gpc_dt_ids[] = {
|
||||
@ -434,8 +435,13 @@ static int imx_gpc_probe(struct platform_device *pdev)
|
||||
|
||||
/* Disable PU power down in normal operation if ERR009619 is present */
|
||||
if (of_id_data->err009619_present)
|
||||
imx_gpc_domains[GPC_PGC_DOMAIN_PU].flags |=
|
||||
PGC_DOMAIN_FLAG_NO_PD;
|
||||
imx_gpc_domains[GPC_PGC_DOMAIN_PU].base.flags |=
|
||||
GENPD_FLAG_ALWAYS_ON;
|
||||
|
||||
/* Keep DISP always on if ERR006287 is present */
|
||||
if (of_id_data->err006287_present)
|
||||
imx_gpc_domains[GPC_PGC_DOMAIN_DISPLAY].base.flags |=
|
||||
GENPD_FLAG_ALWAYS_ON;
|
||||
|
||||
if (!pgc_node) {
|
||||
ret = imx_gpc_old_dt_init(&pdev->dev, regmap,
|
||||
|
@ -146,6 +146,21 @@ static const u32 mt6397_regs[] = {
|
||||
[PWRAP_DEW_CIPHER_SWRST] = 0xbc24,
|
||||
};
|
||||
|
||||
static const u32 mt6351_regs[] = {
|
||||
[PWRAP_DEW_DIO_EN] = 0x02F2,
|
||||
[PWRAP_DEW_READ_TEST] = 0x02F4,
|
||||
[PWRAP_DEW_WRITE_TEST] = 0x02F6,
|
||||
[PWRAP_DEW_CRC_EN] = 0x02FA,
|
||||
[PWRAP_DEW_CRC_VAL] = 0x02FC,
|
||||
[PWRAP_DEW_CIPHER_KEY_SEL] = 0x0300,
|
||||
[PWRAP_DEW_CIPHER_IV_SEL] = 0x0302,
|
||||
[PWRAP_DEW_CIPHER_EN] = 0x0304,
|
||||
[PWRAP_DEW_CIPHER_RDY] = 0x0306,
|
||||
[PWRAP_DEW_CIPHER_MODE] = 0x0308,
|
||||
[PWRAP_DEW_CIPHER_SWRST] = 0x030A,
|
||||
[PWRAP_DEW_RDDMY_NO] = 0x030C,
|
||||
};
|
||||
|
||||
enum pwrap_regs {
|
||||
PWRAP_MUX_SEL,
|
||||
PWRAP_WRAP_EN,
|
||||
@ -366,6 +381,39 @@ static int mt2701_regs[] = {
|
||||
[PWRAP_ADC_RDATA_ADDR2] = 0x154,
|
||||
};
|
||||
|
||||
static int mt6797_regs[] = {
|
||||
[PWRAP_MUX_SEL] = 0x0,
|
||||
[PWRAP_WRAP_EN] = 0x4,
|
||||
[PWRAP_DIO_EN] = 0x8,
|
||||
[PWRAP_SIDLY] = 0xC,
|
||||
[PWRAP_RDDMY] = 0x10,
|
||||
[PWRAP_CSHEXT_WRITE] = 0x18,
|
||||
[PWRAP_CSHEXT_READ] = 0x1C,
|
||||
[PWRAP_CSLEXT_START] = 0x20,
|
||||
[PWRAP_CSLEXT_END] = 0x24,
|
||||
[PWRAP_STAUPD_PRD] = 0x28,
|
||||
[PWRAP_HARB_HPRIO] = 0x50,
|
||||
[PWRAP_HIPRIO_ARB_EN] = 0x54,
|
||||
[PWRAP_MAN_EN] = 0x60,
|
||||
[PWRAP_MAN_CMD] = 0x64,
|
||||
[PWRAP_WACS0_EN] = 0x70,
|
||||
[PWRAP_WACS1_EN] = 0x84,
|
||||
[PWRAP_WACS2_EN] = 0x98,
|
||||
[PWRAP_INIT_DONE2] = 0x9C,
|
||||
[PWRAP_WACS2_CMD] = 0xA0,
|
||||
[PWRAP_WACS2_RDATA] = 0xA4,
|
||||
[PWRAP_WACS2_VLDCLR] = 0xA8,
|
||||
[PWRAP_INT_EN] = 0xC0,
|
||||
[PWRAP_INT_FLG_RAW] = 0xC4,
|
||||
[PWRAP_INT_FLG] = 0xC8,
|
||||
[PWRAP_INT_CLR] = 0xCC,
|
||||
[PWRAP_TIMER_EN] = 0xF4,
|
||||
[PWRAP_WDT_UNIT] = 0xFC,
|
||||
[PWRAP_WDT_SRC_EN] = 0x100,
|
||||
[PWRAP_DCM_EN] = 0x1CC,
|
||||
[PWRAP_DCM_DBC_PRD] = 0x1D4,
|
||||
};
|
||||
|
||||
static int mt7622_regs[] = {
|
||||
[PWRAP_MUX_SEL] = 0x0,
|
||||
[PWRAP_WRAP_EN] = 0x4,
|
||||
@ -635,12 +683,14 @@ static int mt8135_regs[] = {
|
||||
|
||||
enum pmic_type {
|
||||
PMIC_MT6323,
|
||||
PMIC_MT6351,
|
||||
PMIC_MT6380,
|
||||
PMIC_MT6397,
|
||||
};
|
||||
|
||||
enum pwrap_type {
|
||||
PWRAP_MT2701,
|
||||
PWRAP_MT6797,
|
||||
PWRAP_MT7622,
|
||||
PWRAP_MT8135,
|
||||
PWRAP_MT8173,
|
||||
@ -1067,6 +1117,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
|
||||
pwrap_writel(wrp, 1, PWRAP_CIPHER_START);
|
||||
break;
|
||||
case PWRAP_MT2701:
|
||||
case PWRAP_MT6797:
|
||||
case PWRAP_MT8173:
|
||||
pwrap_writel(wrp, 1, PWRAP_CIPHER_EN);
|
||||
break;
|
||||
@ -1080,8 +1131,6 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_LOAD], 0x1);
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_START], 0x1);
|
||||
|
||||
switch (wrp->slave->type) {
|
||||
case PMIC_MT6397:
|
||||
@ -1091,6 +1140,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
|
||||
0x1);
|
||||
break;
|
||||
case PMIC_MT6323:
|
||||
case PMIC_MT6351:
|
||||
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_EN],
|
||||
0x1);
|
||||
break;
|
||||
@ -1367,6 +1417,15 @@ static const struct pwrap_slv_type pmic_mt6397 = {
|
||||
.pwrap_write = pwrap_write16,
|
||||
};
|
||||
|
||||
static const struct pwrap_slv_type pmic_mt6351 = {
|
||||
.dew_regs = mt6351_regs,
|
||||
.type = PMIC_MT6351,
|
||||
.regmap = &pwrap_regmap_config16,
|
||||
.caps = 0,
|
||||
.pwrap_read = pwrap_read16,
|
||||
.pwrap_write = pwrap_write16,
|
||||
};
|
||||
|
||||
static const struct of_device_id of_slave_match_tbl[] = {
|
||||
{
|
||||
.compatible = "mediatek,mt6323",
|
||||
@ -1380,6 +1439,9 @@ static const struct of_device_id of_slave_match_tbl[] = {
|
||||
}, {
|
||||
.compatible = "mediatek,mt6397",
|
||||
.data = &pmic_mt6397,
|
||||
}, {
|
||||
.compatible = "mediatek,mt6351",
|
||||
.data = &pmic_mt6351,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
@ -1398,6 +1460,18 @@ static const struct pmic_wrapper_type pwrap_mt2701 = {
|
||||
.init_soc_specific = pwrap_mt2701_init_soc_specific,
|
||||
};
|
||||
|
||||
static const struct pmic_wrapper_type pwrap_mt6797 = {
|
||||
.regs = mt6797_regs,
|
||||
.type = PWRAP_MT6797,
|
||||
.arb_en_all = 0x01fff,
|
||||
.int_en_all = 0xffffffc6,
|
||||
.spi_w = PWRAP_MAN_CMD_SPI_WRITE,
|
||||
.wdt_src = PWRAP_WDT_SRC_MASK_ALL,
|
||||
.has_bridge = 0,
|
||||
.init_reg_clock = pwrap_common_init_reg_clock,
|
||||
.init_soc_specific = NULL,
|
||||
};
|
||||
|
||||
static const struct pmic_wrapper_type pwrap_mt7622 = {
|
||||
.regs = mt7622_regs,
|
||||
.type = PWRAP_MT7622,
|
||||
@ -1438,6 +1512,9 @@ static const struct of_device_id of_pwrap_match_tbl[] = {
|
||||
{
|
||||
.compatible = "mediatek,mt2701-pwrap",
|
||||
.data = &pwrap_mt2701,
|
||||
}, {
|
||||
.compatible = "mediatek,mt6797-pwrap",
|
||||
.data = &pwrap_mt6797,
|
||||
}, {
|
||||
.compatible = "mediatek,mt7622-pwrap",
|
||||
.data = &pwrap_mt7622,
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <linux/soc/sunxi/sunxi_sram.h>
|
||||
|
||||
@ -63,6 +64,12 @@ static struct sunxi_sram_desc sun4i_a10_sram_a3_a4 = {
|
||||
SUNXI_SRAM_MAP(1, 1, "emac")),
|
||||
};
|
||||
|
||||
static struct sunxi_sram_desc sun4i_a10_sram_c1 = {
|
||||
.data = SUNXI_SRAM_DATA("C1", 0x0, 0x0, 31,
|
||||
SUNXI_SRAM_MAP(0, 0, "cpu"),
|
||||
SUNXI_SRAM_MAP(0x7fffffff, 1, "ve")),
|
||||
};
|
||||
|
||||
static struct sunxi_sram_desc sun4i_a10_sram_d = {
|
||||
.data = SUNXI_SRAM_DATA("D", 0x4, 0x0, 1,
|
||||
SUNXI_SRAM_MAP(0, 0, "cpu"),
|
||||
@ -80,6 +87,10 @@ static const struct of_device_id sunxi_sram_dt_ids[] = {
|
||||
.compatible = "allwinner,sun4i-a10-sram-a3-a4",
|
||||
.data = &sun4i_a10_sram_a3_a4.data,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun4i-a10-sram-c1",
|
||||
.data = &sun4i_a10_sram_c1.data,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun4i-a10-sram-d",
|
||||
.data = &sun4i_a10_sram_d.data,
|
||||
@ -281,13 +292,51 @@ int sunxi_sram_release(struct device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL(sunxi_sram_release);
|
||||
|
||||
struct sunxi_sramc_variant {
|
||||
bool has_emac_clock;
|
||||
};
|
||||
|
||||
static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
|
||||
/* Nothing special */
|
||||
};
|
||||
|
||||
static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = {
|
||||
.has_emac_clock = true,
|
||||
};
|
||||
|
||||
#define SUNXI_SRAM_EMAC_CLOCK_REG 0x30
|
||||
static bool sunxi_sram_regmap_accessible_reg(struct device *dev,
|
||||
unsigned int reg)
|
||||
{
|
||||
if (reg == SUNXI_SRAM_EMAC_CLOCK_REG)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct regmap_config sunxi_sram_emac_clock_regmap = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
/* last defined register */
|
||||
.max_register = SUNXI_SRAM_EMAC_CLOCK_REG,
|
||||
/* other devices have no business accessing other registers */
|
||||
.readable_reg = sunxi_sram_regmap_accessible_reg,
|
||||
.writeable_reg = sunxi_sram_regmap_accessible_reg,
|
||||
};
|
||||
|
||||
static int sunxi_sram_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
struct dentry *d;
|
||||
struct regmap *emac_clock;
|
||||
const struct sunxi_sramc_variant *variant;
|
||||
|
||||
sram_dev = &pdev->dev;
|
||||
|
||||
variant = of_device_get_match_data(&pdev->dev);
|
||||
if (!variant)
|
||||
return -EINVAL;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(base))
|
||||
@ -300,12 +349,46 @@ static int sunxi_sram_probe(struct platform_device *pdev)
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
if (variant->has_emac_clock) {
|
||||
emac_clock = devm_regmap_init_mmio(&pdev->dev, base,
|
||||
&sunxi_sram_emac_clock_regmap);
|
||||
|
||||
if (IS_ERR(emac_clock))
|
||||
return PTR_ERR(emac_clock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id sunxi_sram_dt_match[] = {
|
||||
{ .compatible = "allwinner,sun4i-a10-sram-controller" },
|
||||
{ .compatible = "allwinner,sun50i-a64-sram-controller" },
|
||||
{
|
||||
.compatible = "allwinner,sun4i-a10-sram-controller",
|
||||
.data = &sun4i_a10_sramc_variant,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun4i-a10-system-control",
|
||||
.data = &sun4i_a10_sramc_variant,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun5i-a13-system-control",
|
||||
.data = &sun4i_a10_sramc_variant,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun8i-a23-system-control",
|
||||
.data = &sun4i_a10_sramc_variant,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun8i-h3-system-control",
|
||||
.data = &sun4i_a10_sramc_variant,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun50i-a64-sram-controller",
|
||||
.data = &sun50i_a64_sramc_variant,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun50i-a64-system-control",
|
||||
.data = &sun50i_a64_sramc_variant,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match);
|
||||
|
@ -46,6 +46,7 @@
|
||||
#define M3_BASELINE_VERSION 0x191
|
||||
#define M3_STATUS_RESP_MASK (0xffff << 16)
|
||||
#define M3_FW_VERSION_MASK 0xffff
|
||||
#define M3_WAKE_SRC_MASK 0xff
|
||||
|
||||
#define M3_STATE_UNKNOWN 0
|
||||
#define M3_STATE_RESET 1
|
||||
@ -55,6 +56,23 @@
|
||||
|
||||
static struct wkup_m3_ipc *m3_ipc_state;
|
||||
|
||||
static const struct wkup_m3_wakeup_src wakeups[] = {
|
||||
{.irq_nr = 35, .src = "USB0_PHY"},
|
||||
{.irq_nr = 36, .src = "USB1_PHY"},
|
||||
{.irq_nr = 40, .src = "I2C0"},
|
||||
{.irq_nr = 41, .src = "RTC Timer"},
|
||||
{.irq_nr = 42, .src = "RTC Alarm"},
|
||||
{.irq_nr = 43, .src = "Timer0"},
|
||||
{.irq_nr = 44, .src = "Timer1"},
|
||||
{.irq_nr = 45, .src = "UART"},
|
||||
{.irq_nr = 46, .src = "GPIO0"},
|
||||
{.irq_nr = 48, .src = "MPU_WAKE"},
|
||||
{.irq_nr = 49, .src = "WDT0"},
|
||||
{.irq_nr = 50, .src = "WDT1"},
|
||||
{.irq_nr = 51, .src = "ADC_TSC"},
|
||||
{.irq_nr = 0, .src = "Unknown"},
|
||||
};
|
||||
|
||||
static void am33xx_txev_eoi(struct wkup_m3_ipc *m3_ipc)
|
||||
{
|
||||
writel(AM33XX_M3_TXEV_ACK,
|
||||
@ -329,12 +347,45 @@ static int wkup_m3_finish_low_power(struct wkup_m3_ipc *m3_ipc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* wkup_m3_request_wake_src - Get the wakeup source info passed from wkup_m3
|
||||
* @m3_ipc: Pointer to wkup_m3_ipc context
|
||||
*/
|
||||
static const char *wkup_m3_request_wake_src(struct wkup_m3_ipc *m3_ipc)
|
||||
{
|
||||
unsigned int wakeup_src_idx;
|
||||
int j, val;
|
||||
|
||||
val = wkup_m3_ctrl_ipc_read(m3_ipc, 6);
|
||||
|
||||
wakeup_src_idx = val & M3_WAKE_SRC_MASK;
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(wakeups) - 1; j++) {
|
||||
if (wakeups[j].irq_nr == wakeup_src_idx)
|
||||
return wakeups[j].src;
|
||||
}
|
||||
return wakeups[j].src;
|
||||
}
|
||||
|
||||
/**
|
||||
* wkup_m3_set_rtc_only - Set the rtc_only flag
|
||||
* @wkup_m3_wakeup: struct wkup_m3_wakeup_src * gets assigned the
|
||||
* wakeup src value
|
||||
*/
|
||||
static void wkup_m3_set_rtc_only(struct wkup_m3_ipc *m3_ipc)
|
||||
{
|
||||
if (m3_ipc_state)
|
||||
m3_ipc_state->is_rtc_only = true;
|
||||
}
|
||||
|
||||
static struct wkup_m3_ipc_ops ipc_ops = {
|
||||
.set_mem_type = wkup_m3_set_mem_type,
|
||||
.set_resume_address = wkup_m3_set_resume_address,
|
||||
.prepare_low_power = wkup_m3_prepare_low_power,
|
||||
.finish_low_power = wkup_m3_finish_low_power,
|
||||
.request_pm_status = wkup_m3_request_pm_status,
|
||||
.request_wake_src = wkup_m3_request_wake_src,
|
||||
.set_rtc_only = wkup_m3_set_rtc_only,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -484,6 +535,30 @@ static int wkup_m3_ipc_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused wkup_m3_ipc_suspend(struct device *dev)
|
||||
{
|
||||
/*
|
||||
* Nothing needs to be done on suspend even with rtc_only flag set
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused wkup_m3_ipc_resume(struct device *dev)
|
||||
{
|
||||
if (m3_ipc_state->is_rtc_only) {
|
||||
rproc_shutdown(m3_ipc_state->rproc);
|
||||
rproc_boot(m3_ipc_state->rproc);
|
||||
}
|
||||
|
||||
m3_ipc_state->is_rtc_only = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops wkup_m3_ipc_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(wkup_m3_ipc_suspend, wkup_m3_ipc_resume)
|
||||
};
|
||||
|
||||
static const struct of_device_id wkup_m3_ipc_of_match[] = {
|
||||
{ .compatible = "ti,am3352-wkup-m3-ipc", },
|
||||
{ .compatible = "ti,am4372-wkup-m3-ipc", },
|
||||
@ -497,6 +572,7 @@ static struct platform_driver wkup_m3_ipc_driver = {
|
||||
.driver = {
|
||||
.name = "wkup_m3_ipc",
|
||||
.of_match_table = wkup_m3_ipc_of_match,
|
||||
.pm = &wkup_m3_ipc_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -90,8 +90,6 @@ source "drivers/staging/clocking-wizard/Kconfig"
|
||||
|
||||
source "drivers/staging/fbtft/Kconfig"
|
||||
|
||||
source "drivers/staging/fsl-mc/Kconfig"
|
||||
|
||||
source "drivers/staging/fsl-dpaa2/Kconfig"
|
||||
|
||||
source "drivers/staging/wilc1000/Kconfig"
|
||||
|
@ -35,7 +35,6 @@ obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/
|
||||
obj-$(CONFIG_UNISYSSPAR) += unisys/
|
||||
obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/
|
||||
obj-$(CONFIG_FB_TFT) += fbtft/
|
||||
obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
|
||||
obj-$(CONFIG_FSL_DPAA2) += fsl-dpaa2/
|
||||
obj-$(CONFIG_WILC1000) += wilc1000/
|
||||
obj-$(CONFIG_MOST) += most/
|
||||
|
@ -426,7 +426,7 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
|
||||
dpaa2_fd_set_format(fd, dpaa2_fd_sg);
|
||||
dpaa2_fd_set_addr(fd, addr);
|
||||
dpaa2_fd_set_len(fd, skb->len);
|
||||
dpaa2_fd_set_ctrl(fd, DPAA2_FD_CTRL_PTA | DPAA2_FD_CTRL_PTV1);
|
||||
dpaa2_fd_set_ctrl(fd, FD_CTRL_PTA | FD_CTRL_PTV1);
|
||||
|
||||
if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
|
||||
enable_tx_tstamp(fd, sgt_buf);
|
||||
@ -479,7 +479,7 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
|
||||
dpaa2_fd_set_offset(fd, (u16)(skb->data - buffer_start));
|
||||
dpaa2_fd_set_len(fd, skb->len);
|
||||
dpaa2_fd_set_format(fd, dpaa2_fd_single);
|
||||
dpaa2_fd_set_ctrl(fd, DPAA2_FD_CTRL_PTA | DPAA2_FD_CTRL_PTV1);
|
||||
dpaa2_fd_set_ctrl(fd, FD_CTRL_PTA | FD_CTRL_PTV1);
|
||||
|
||||
if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
|
||||
enable_tx_tstamp(fd, buffer_start);
|
||||
|
@ -10,8 +10,8 @@
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/fsl/mc.h>
|
||||
|
||||
#include "../../fsl-mc/include/dpaa2-io.h"
|
||||
#include "../../fsl-mc/include/dpaa2-fd.h"
|
||||
#include <soc/fsl/dpaa2-io.h>
|
||||
#include <soc/fsl/dpaa2-fd.h>
|
||||
#include "dpni.h"
|
||||
#include "dpni-cmd.h"
|
||||
|
||||
@ -97,21 +97,13 @@ struct dpaa2_eth_swa {
|
||||
#define DPAA2_FD_FRC_FAICFDV 0x0400
|
||||
|
||||
/* Error bits in FD CTRL */
|
||||
#define DPAA2_FD_CTRL_UFD 0x00000004
|
||||
#define DPAA2_FD_CTRL_SBE 0x00000008
|
||||
#define DPAA2_FD_CTRL_FSE 0x00000020
|
||||
#define DPAA2_FD_CTRL_FAERR 0x00000040
|
||||
|
||||
#define DPAA2_FD_RX_ERR_MASK (DPAA2_FD_CTRL_SBE | \
|
||||
DPAA2_FD_CTRL_FAERR)
|
||||
#define DPAA2_FD_TX_ERR_MASK (DPAA2_FD_CTRL_UFD | \
|
||||
DPAA2_FD_CTRL_SBE | \
|
||||
DPAA2_FD_CTRL_FSE | \
|
||||
DPAA2_FD_CTRL_FAERR)
|
||||
#define DPAA2_FD_RX_ERR_MASK (FD_CTRL_SBE | FD_CTRL_FAERR)
|
||||
#define DPAA2_FD_TX_ERR_MASK (FD_CTRL_UFD | \
|
||||
FD_CTRL_SBE | \
|
||||
FD_CTRL_FSE | \
|
||||
FD_CTRL_FAERR)
|
||||
|
||||
/* Annotation bits in FD CTRL */
|
||||
#define DPAA2_FD_CTRL_PTA 0x00800000
|
||||
#define DPAA2_FD_CTRL_PTV1 0x00400000
|
||||
#define DPAA2_FD_CTRL_ASAL 0x00020000 /* ASAL = 128B */
|
||||
|
||||
/* Frame annotation status */
|
||||
|
@ -1,2 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
source "drivers/staging/fsl-mc/bus/Kconfig"
|
@ -1,3 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Freescale Management Complex (MC) bus drivers
|
||||
obj-$(CONFIG_FSL_MC_BUS) += bus/
|
@ -1,16 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# DPAA2 fsl-mc bus
|
||||
#
|
||||
# Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
|
||||
#
|
||||
|
||||
config FSL_MC_DPIO
|
||||
tristate "QorIQ DPAA2 DPIO driver"
|
||||
depends on FSL_MC_BUS
|
||||
help
|
||||
Driver for the DPAA2 DPIO object. A DPIO provides queue and
|
||||
buffer management facilities for software to interact with
|
||||
other DPAA2 objects. This driver does not expose the DPIO
|
||||
objects individually, but groups them under a service layer
|
||||
API.
|
@ -1,9 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Freescale Management Complex (MC) bus drivers
|
||||
#
|
||||
# Copyright (C) 2014 Freescale Semiconductor, Inc.
|
||||
#
|
||||
|
||||
# MC DPIO driver
|
||||
obj-$(CONFIG_FSL_MC_DPIO) += dpio/
|
@ -5,3 +5,11 @@ config OPTEE
|
||||
help
|
||||
This implements the OP-TEE Trusted Execution Environment (TEE)
|
||||
driver.
|
||||
|
||||
config OPTEE_SHM_NUM_PRIV_PAGES
|
||||
int "Private Shared Memory Pages"
|
||||
default 1
|
||||
depends on OPTEE
|
||||
help
|
||||
This sets the number of private shared memory pages to be
|
||||
used by OP-TEE TEE driver.
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#define DRIVER_NAME "optee"
|
||||
|
||||
#define OPTEE_SHM_NUM_PRIV_PAGES 1
|
||||
#define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
|
||||
|
||||
/**
|
||||
* optee_from_msg_param() - convert from OPTEE_MSG parameters to
|
||||
|
@ -48,7 +48,7 @@ static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg)
|
||||
OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT)
|
||||
goto bad;
|
||||
|
||||
getnstimeofday64(&ts);
|
||||
ktime_get_real_ts64(&ts);
|
||||
arg->params[0].u.value.a = ts.tv_sec;
|
||||
arg->params[0].u.value.b = ts.tv_nsec;
|
||||
|
||||
|
@ -161,16 +161,10 @@ static int exynos_ehci_probe(struct platform_device *pdev)
|
||||
}
|
||||
exynos_ehci = to_exynos_ehci(hcd);
|
||||
|
||||
if (of_device_is_compatible(pdev->dev.of_node,
|
||||
"samsung,exynos5440-ehci"))
|
||||
goto skip_phy;
|
||||
|
||||
err = exynos_ehci_get_phy(&pdev->dev, exynos_ehci);
|
||||
if (err)
|
||||
goto fail_clk;
|
||||
|
||||
skip_phy:
|
||||
|
||||
exynos_ehci->clk = devm_clk_get(&pdev->dev, "usbhost");
|
||||
|
||||
if (IS_ERR(exynos_ehci->clk)) {
|
||||
@ -304,7 +298,6 @@ static const struct dev_pm_ops exynos_ehci_pm_ops = {
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id exynos_ehci_match[] = {
|
||||
{ .compatible = "samsung,exynos4210-ehci" },
|
||||
{ .compatible = "samsung,exynos5440-ehci" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, exynos_ehci_match);
|
||||
|
@ -130,15 +130,10 @@ static int exynos_ohci_probe(struct platform_device *pdev)
|
||||
|
||||
exynos_ohci = to_exynos_ohci(hcd);
|
||||
|
||||
if (of_device_is_compatible(pdev->dev.of_node,
|
||||
"samsung,exynos5440-ohci"))
|
||||
goto skip_phy;
|
||||
|
||||
err = exynos_ohci_get_phy(&pdev->dev, exynos_ohci);
|
||||
if (err)
|
||||
goto fail_clk;
|
||||
|
||||
skip_phy:
|
||||
exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
|
||||
|
||||
if (IS_ERR(exynos_ohci->clk)) {
|
||||
@ -270,7 +265,6 @@ static const struct dev_pm_ops exynos_ohci_pm_ops = {
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id exynos_ohci_match[] = {
|
||||
{ .compatible = "samsung,exynos4210-ohci" },
|
||||
{ .compatible = "samsung,exynos5440-ohci" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, exynos_ohci_match);
|
||||
|
@ -15,6 +15,8 @@
|
||||
/* SmartReflex sysc found on 36xx and later */
|
||||
#define SYSC_OMAP3_SR_ENAWAKEUP (1 << 26)
|
||||
|
||||
#define SYSC_DRA7_MCAN_ENAWAKEUP (1 << 4)
|
||||
|
||||
/* SYSCONFIG STANDBYMODE/MIDLEMODE/SIDLEMODE supported by hardware */
|
||||
#define SYSC_IDLE_FORCE 0
|
||||
#define SYSC_IDLE_NO 1
|
||||
|
@ -168,5 +168,6 @@
|
||||
#define DRA7_COUNTER_32K_CLKCTRL DRA7_CLKCTRL_INDEX(0x50)
|
||||
#define DRA7_UART10_CLKCTRL DRA7_CLKCTRL_INDEX(0x80)
|
||||
#define DRA7_DCAN1_CLKCTRL DRA7_CLKCTRL_INDEX(0x88)
|
||||
#define DRA7_ADC_CLKCTRL DRA7_CLKCTRL_INDEX(0xa0)
|
||||
|
||||
#endif
|
||||
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* Author: Andrzej Hajda <a.hajda@samsung.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.
|
||||
*
|
||||
* Device Tree binding constants for Exynos5440 clock controller.
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_CLOCK_EXYNOS_5440_H
|
||||
#define _DT_BINDINGS_CLOCK_EXYNOS_5440_H
|
||||
|
||||
#define CLK_XTAL 1
|
||||
#define CLK_ARM_CLK 2
|
||||
#define CLK_CPLLA 3
|
||||
#define CLK_CPLLB 4
|
||||
#define CLK_SPI_BAUD 16
|
||||
#define CLK_PB0_250 17
|
||||
#define CLK_PR0_250 18
|
||||
#define CLK_PR1_250 19
|
||||
#define CLK_B_250 20
|
||||
#define CLK_B_125 21
|
||||
#define CLK_B_200 22
|
||||
#define CLK_SATA 23
|
||||
#define CLK_USB 24
|
||||
#define CLK_GMAC0 25
|
||||
#define CLK_CS250 26
|
||||
#define CLK_PB0_250_O 27
|
||||
#define CLK_PR0_250_O 28
|
||||
#define CLK_PR1_250_O 29
|
||||
#define CLK_B_250_O 30
|
||||
#define CLK_B_125_O 31
|
||||
#define CLK_B_200_O 32
|
||||
#define CLK_SATA_O 33
|
||||
#define CLK_USB_O 34
|
||||
#define CLK_GMAC0_O 35
|
||||
#define CLK_CS250_O 36
|
||||
|
||||
/* must be greater than maximal clock id */
|
||||
#define CLK_NR_CLKS 37
|
||||
|
||||
#endif /* _DT_BINDINGS_CLOCK_EXYNOS_5440_H */
|
17
include/dt-bindings/reset/qcom,sdm845-aoss.h
Normal file
17
include/dt-bindings/reset/qcom,sdm845-aoss.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2018 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_RESET_AOSS_SDM_845_H
|
||||
#define _DT_BINDINGS_RESET_AOSS_SDM_845_H
|
||||
|
||||
#define AOSS_CC_MSS_RESTART 0
|
||||
#define AOSS_CC_CAMSS_RESTART 1
|
||||
#define AOSS_CC_VENUS_RESTART 2
|
||||
#define AOSS_CC_GPU_RESTART 3
|
||||
#define AOSS_CC_DISPSS_RESTART 4
|
||||
#define AOSS_CC_WCSS_RESTART 5
|
||||
#define AOSS_CC_LPASS_RESTART 6
|
||||
|
||||
#endif
|
@ -14,6 +14,7 @@ enum ti_sysc_module_type {
|
||||
TI_SYSC_OMAP4_SR,
|
||||
TI_SYSC_OMAP4_MCASP,
|
||||
TI_SYSC_OMAP4_USB_HOST_FS,
|
||||
TI_SYSC_DRA7_MCAN,
|
||||
};
|
||||
|
||||
struct ti_sysc_cookie {
|
||||
|
@ -40,6 +40,12 @@ struct wkup_m3_ipc {
|
||||
struct mbox_chan *mbox;
|
||||
|
||||
struct wkup_m3_ipc_ops *ops;
|
||||
int is_rtc_only;
|
||||
};
|
||||
|
||||
struct wkup_m3_wakeup_src {
|
||||
int irq_nr;
|
||||
char src[10];
|
||||
};
|
||||
|
||||
struct wkup_m3_ipc_ops {
|
||||
@ -48,8 +54,11 @@ struct wkup_m3_ipc_ops {
|
||||
int (*prepare_low_power)(struct wkup_m3_ipc *m3_ipc, int state);
|
||||
int (*finish_low_power)(struct wkup_m3_ipc *m3_ipc);
|
||||
int (*request_pm_status)(struct wkup_m3_ipc *m3_ipc);
|
||||
const char *(*request_wake_src)(struct wkup_m3_ipc *m3_ipc);
|
||||
void (*set_rtc_only)(struct wkup_m3_ipc *m3_ipc);
|
||||
};
|
||||
|
||||
struct wkup_m3_ipc *wkup_m3_ipc_get(void);
|
||||
void wkup_m3_ipc_put(struct wkup_m3_ipc *m3_ipc);
|
||||
void wkup_m3_set_rtc_only_mode(void);
|
||||
#endif /* _LINUX_WKUP_M3_IPC_H */
|
||||
|
@ -75,6 +75,7 @@ enum rpi_firmware_property_tag {
|
||||
RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020,
|
||||
RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021,
|
||||
RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030,
|
||||
RPI_FIRMWARE_GET_THROTTLED = 0x00030046,
|
||||
RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001,
|
||||
RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002,
|
||||
RPI_FIRMWARE_SET_VOLTAGE = 0x00038003,
|
||||
|
@ -67,6 +67,18 @@ struct dpaa2_fd {
|
||||
#define SG_FINAL_FLAG_MASK 0x1
|
||||
#define SG_FINAL_FLAG_SHIFT 15
|
||||
|
||||
/* Error bits in FD CTRL */
|
||||
#define FD_CTRL_ERR_MASK 0x000000FF
|
||||
#define FD_CTRL_UFD 0x00000004
|
||||
#define FD_CTRL_SBE 0x00000008
|
||||
#define FD_CTRL_FLC 0x00000010
|
||||
#define FD_CTRL_FSE 0x00000020
|
||||
#define FD_CTRL_FAERR 0x00000040
|
||||
|
||||
/* Annotation bits in FD CTRL */
|
||||
#define FD_CTRL_PTA 0x00800000
|
||||
#define FD_CTRL_PTV1 0x00400000
|
||||
|
||||
enum dpaa2_fd_format {
|
||||
dpaa2_fd_single = 0,
|
||||
dpaa2_fd_list,
|
Loading…
Reference in New Issue
Block a user