Skip to content

Commit

Permalink
Merge tag 'zynqmp-soc-for-v5.1' of https://github.com/Xilinx/linux-xlnx
Browse files Browse the repository at this point in the history
… into arm/drivers

arm64: zynqmp: SoC changes for v5.1

- Extend firmware interface with reset, nvmem,
  power management and power domain support

- Add reset, nvmem driver, power management and
  power domain drivers
-

* tag 'zynqmp-soc-for-v5.1' of https://github.com/Xilinx/linux-xlnx:
  drivers: soc: xilinx: Add ZynqMP power domain driver
  firmware: xilinx: Add APIs to control node status/power
  dt-bindings: power: Add ZynqMP power domain bindings
  drivers: soc: xilinx: Add ZynqMP PM driver
  firmware: xilinx: Implement ZynqMP power management APIs
  dt-bindings: soc: Add ZynqMP PM bindings
  nvmem: zynqmp: Added zynqmp nvmem firmware driver
  dt-bindings: nvmem: Add bindings for ZynqMP nvmem driver
  firmware: xilinx: Add zynqmp_pm_get_chipid() API
  reset: reset-zynqmp: Adding support for Xilinx zynqmp reset controller.
  dt-bindings: reset: Add bindings for ZynqMP reset driver
  firmware: xilinx: Add reset API's

Signed-off-by: Arnd Bergmann <[email protected]>
  • Loading branch information
arndb committed Feb 15, 2019
2 parents 57f87c7 + e23d9c6 commit 59f527d
Show file tree
Hide file tree
Showing 18 changed files with 1,411 additions and 0 deletions.
46 changes: 46 additions & 0 deletions Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
--------------------------------------------------------------------------
= Zynq UltraScale+ MPSoC nvmem firmware driver binding =
--------------------------------------------------------------------------
The nvmem_firmware node provides access to the hardware related data
like soc revision, IDCODE... etc, By using the firmware interface.

Required properties:
- compatible: should be "xlnx,zynqmp-nvmem-fw"

= Data cells =
Are child nodes of silicon id, bindings of which as described in
bindings/nvmem/nvmem.txt

-------
Example
-------
firmware {
zynqmp_firmware: zynqmp-firmware {
compatible = "xlnx,zynqmp-firmware";
method = "smc";

nvmem_firmware {
compatible = "xlnx,zynqmp-nvmem-fw";
#address-cells = <1>;
#size-cells = <1>;

/* Data cells */
soc_revision: soc_revision {
reg = <0x0 0x4>;
};
};
};
};

= Data consumers =
Are device nodes which consume nvmem data cells.

For example:
pcap {
...

nvmem-cells = <&soc_revision>;
nvmem-cell-names = "soc_revision";

...
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--------------------------------------------------------------------
Device Tree Bindings for the Xilinx Zynq MPSoC Power Management
--------------------------------------------------------------------
The zynqmp-power node describes the power management configurations.
It will control remote suspend/shutdown interfaces.

Required properties:
- compatible: Must contain: "xlnx,zynqmp-power"
- interrupts: Interrupt specifier

-------
Example
-------

firmware {
zynqmp_firmware: zynqmp-firmware {
compatible = "xlnx,zynqmp-firmware";
method = "smc";

zynqmp_power: zynqmp-power {
compatible = "xlnx,zynqmp-power";
interrupts = <0 35 4>;
};
};
};
34 changes: 34 additions & 0 deletions Documentation/devicetree/bindings/power/xlnx,zynqmp-genpd.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
-----------------------------------------------------------
Device Tree Bindings for the Xilinx Zynq MPSoC PM domains
-----------------------------------------------------------
The binding for zynqmp-power-controller follow the common
generic PM domain binding[1].

[1] Documentation/devicetree/bindings/power/power_domain.txt

== Zynq MPSoC Generic PM Domain Node ==

Required property:
- Below property should be in zynqmp-firmware node.
- #power-domain-cells: Number of cells in a PM domain specifier. Must be 1.

Power domain ID indexes are mentioned in
include/dt-bindings/power/xlnx-zynqmp-power.h.

-------
Example
-------

firmware {
zynqmp_firmware: zynqmp-firmware {
...
#power-domain-cells = <1>;
...
};
};

sata {
...
power-domains = <&zynqmp_firmware 28>;
...
};
52 changes: 52 additions & 0 deletions Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
--------------------------------------------------------------------------
= Zynq UltraScale+ MPSoC reset driver binding =
--------------------------------------------------------------------------
The Zynq UltraScale+ MPSoC has several different resets.

See Chapter 36 of the Zynq UltraScale+ MPSoC TRM (UG) for more information
about zynqmp resets.

Please also refer to reset.txt in this directory for common reset
controller binding usage.

Required Properties:
- compatible: "xlnx,zynqmp-reset"
- #reset-cells: Specifies the number of cells needed to encode reset
line, should be 1

-------
Example
-------

firmware {
zynqmp_firmware: zynqmp-firmware {
compatible = "xlnx,zynqmp-firmware";
method = "smc";

zynqmp_reset: reset-controller {
compatible = "xlnx,zynqmp-reset";
#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/xlnx-zynqmp-resets.h>

Example:

serdes: zynqmp_phy@fd400000 {
...

resets = <&zynqmp_reset ZYNQMP_RESET_SATA>;
reset-names = "sata_rst";

...
};
1 change: 1 addition & 0 deletions drivers/firmware/xilinx/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ menu "Zynq MPSoC Firmware Drivers"

config ZYNQMP_FIRMWARE
bool "Enable Xilinx Zynq MPSoC firmware interface"
select MFD_CORE
help
Firmware interface driver is used by different
drivers to communicate with the firmware for
Expand Down
166 changes: 166 additions & 0 deletions drivers/firmware/xilinx/zynqmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/compiler.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
Expand All @@ -23,6 +24,12 @@
#include <linux/firmware/xlnx-zynqmp.h>
#include "zynqmp-debug.h"

static const struct mfd_cell firmware_devs[] = {
{
.name = "zynqmp_power_controller",
},
};

/**
* zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes
* @ret_status: PMUFW return code
Expand Down Expand Up @@ -186,6 +193,29 @@ static int zynqmp_pm_get_api_version(u32 *version)
return ret;
}

/**
* zynqmp_pm_get_chipid - Get silicon ID registers
* @idcode: IDCODE register
* @version: version register
*
* Return: Returns the status of the operation and the idcode and version
* registers in @idcode and @version.
*/
static int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
{
u32 ret_payload[PAYLOAD_ARG_CNT];
int ret;

if (!idcode || !version)
return -EINVAL;

ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
*idcode = ret_payload[1];
*version = ret_payload[2];

return ret;
}

/**
* zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
* @version: Returned version value
Expand Down Expand Up @@ -469,8 +499,129 @@ static int zynqmp_pm_ioctl(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2,
arg1, arg2, out);
}

/**
* zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release)
* @reset: Reset to be configured
* @assert_flag: Flag stating should reset be asserted (1) or
* released (0)
*
* Return: Returns status, either success or error+reason
*/
static int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
const enum zynqmp_pm_reset_action assert_flag)
{
return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag,
0, 0, NULL);
}

/**
* zynqmp_pm_reset_get_status - Get status of the reset
* @reset: Reset whose status should be returned
* @status: Returned status
*
* Return: Returns status, either success or error+reason
*/
static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset,
u32 *status)
{
u32 ret_payload[PAYLOAD_ARG_CNT];
int ret;

if (!status)
return -EINVAL;

ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0,
0, 0, ret_payload);
*status = ret_payload[1];

return ret;
}

/**
* zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
* master has initialized its own power management
*
* This API function is to be used for notify the power management controller
* about the completed power management initialization.
*
* Return: Returns status, either success or error+reason
*/
static int zynqmp_pm_init_finalize(void)
{
return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL);
}

/**
* zynqmp_pm_set_suspend_mode() - Set system suspend mode
* @mode: Mode to set for system suspend
*
* This API function is used to set mode of system suspend.
*
* Return: Returns status, either success or error+reason
*/
static int zynqmp_pm_set_suspend_mode(u32 mode)
{
return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL);
}

/**
* zynqmp_pm_request_node() - Request a node with specific capabilities
* @node: Node ID of the slave
* @capabilities: Requested capabilities of the slave
* @qos: Quality of service (not supported)
* @ack: Flag to specify whether acknowledge is requested
*
* This function is used by master to request particular node from firmware.
* Every master must request node before using it.
*
* Return: Returns status, either success or error+reason
*/
static int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
const u32 qos,
const enum zynqmp_pm_request_ack ack)
{
return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities,
qos, ack, NULL);
}

/**
* zynqmp_pm_release_node() - Release a node
* @node: Node ID of the slave
*
* This function is used by master to inform firmware that master
* has released node. Once released, master must not use that node
* without re-request.
*
* Return: Returns status, either success or error+reason
*/
static int zynqmp_pm_release_node(const u32 node)
{
return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL);
}

/**
* zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
* @node: Node ID of the slave
* @capabilities: Requested capabilities of the slave
* @qos: Quality of service (not supported)
* @ack: Flag to specify whether acknowledge is requested
*
* This API function is to be used for slaves a PU already has requested
* to change its capabilities.
*
* Return: Returns status, either success or error+reason
*/
static int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
const u32 qos,
const enum zynqmp_pm_request_ack ack)
{
return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities,
qos, ack, NULL);
}

static const struct zynqmp_eemi_ops eemi_ops = {
.get_api_version = zynqmp_pm_get_api_version,
.get_chipid = zynqmp_pm_get_chipid,
.query_data = zynqmp_pm_query_data,
.clock_enable = zynqmp_pm_clock_enable,
.clock_disable = zynqmp_pm_clock_disable,
Expand All @@ -482,6 +633,13 @@ static const struct zynqmp_eemi_ops eemi_ops = {
.clock_setparent = zynqmp_pm_clock_setparent,
.clock_getparent = zynqmp_pm_clock_getparent,
.ioctl = zynqmp_pm_ioctl,
.reset_assert = zynqmp_pm_reset_assert,
.reset_get_status = zynqmp_pm_reset_get_status,
.init_finalize = zynqmp_pm_init_finalize,
.set_suspend_mode = zynqmp_pm_set_suspend_mode,
.request_node = zynqmp_pm_request_node,
.release_node = zynqmp_pm_release_node,
.set_requirement = zynqmp_pm_set_requirement,
};

/**
Expand Down Expand Up @@ -538,11 +696,19 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)

zynqmp_pm_api_debugfs_init();

ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
ARRAY_SIZE(firmware_devs), NULL, 0, NULL);
if (ret) {
dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret);
return ret;
}

return of_platform_populate(dev->of_node, NULL, NULL, dev);
}

static int zynqmp_firmware_remove(struct platform_device *pdev)
{
mfd_remove_devices(&pdev->dev);
zynqmp_pm_api_debugfs_exit();

return 0;
Expand Down
10 changes: 10 additions & 0 deletions drivers/nvmem/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,14 @@ config SC27XX_EFUSE
This driver can also be built as a module. If so, the module
will be called nvmem-sc27xx-efuse.

config NVMEM_ZYNQMP
bool "Xilinx ZYNQMP SoC nvmem firmware support"
depends on ARCH_ZYNQMP
help
This is a driver to access hardware related data like
soc revision, IDCODE... etc by using the firmware
interface.

If sure, say yes. If unsure, say no.

endif
Loading

0 comments on commit 59f527d

Please sign in to comment.