imx: add support for i.MX8MQ power domain controller
Add support for the power domain controller that's used on the i.MX8MQ. This will be needed to be able to power on the PCIe controller. Bindings taken from Linux, driver implementation taken from the i.MX8 power domain controller and adjusted for the i.MX8M SoC. Signed-off-by: Patrick Wildt <patrick@blueri.se>
This commit is contained in:
parent
6745dac494
commit
d08a194871
@ -19,6 +19,7 @@
|
|||||||
#include <dt-bindings/input/input.h>
|
#include <dt-bindings/input/input.h>
|
||||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
#include <dt-bindings/pinctrl/pins-imx8mq.h>
|
#include <dt-bindings/pinctrl/pins-imx8mq.h>
|
||||||
|
#include <dt-bindings/power/imx8mq-power.h>
|
||||||
#include <dt-bindings/thermal/thermal.h>
|
#include <dt-bindings/thermal/thermal.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
@ -71,12 +72,6 @@
|
|||||||
interrupt-parent = <&gic>;
|
interrupt-parent = <&gic>;
|
||||||
};
|
};
|
||||||
|
|
||||||
power: power-controller {
|
|
||||||
compatible = "fsl,imx8mq-pm-domain";
|
|
||||||
num-domains = <11>;
|
|
||||||
#power-domain-cells = <1>;
|
|
||||||
};
|
|
||||||
|
|
||||||
pwm2: pwm@30670000 {
|
pwm2: pwm@30670000 {
|
||||||
compatible = "fsl,imx8mq-pwm", "fsl,imx27-pwm";
|
compatible = "fsl,imx8mq-pwm", "fsl,imx27-pwm";
|
||||||
reg = <0x0 0x30670000 0x0 0x10000>;
|
reg = <0x0 0x30670000 0x0 0x10000>;
|
||||||
@ -276,6 +271,37 @@
|
|||||||
interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
#interrupt-cells = <3>;
|
#interrupt-cells = <3>;
|
||||||
interrupt-parent = <&gic>;
|
interrupt-parent = <&gic>;
|
||||||
|
|
||||||
|
pgc {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* As per comment in ATF source code:
|
||||||
|
*
|
||||||
|
* PCIE1 and PCIE2 share the
|
||||||
|
* same reset signal, if we
|
||||||
|
* power down PCIE2, PCIE1
|
||||||
|
* will be held in reset too.
|
||||||
|
*
|
||||||
|
* So instead of creating two
|
||||||
|
* separate power domains for
|
||||||
|
* PCIE1 and PCIE2 we create a
|
||||||
|
* link between both and use
|
||||||
|
* it as a shared PCIE power
|
||||||
|
* domain.
|
||||||
|
*/
|
||||||
|
pgc_pcie: power-domain@1 {
|
||||||
|
#power-domain-cells = <0>;
|
||||||
|
reg = <IMX8M_POWER_DOMAIN_PCIE1>;
|
||||||
|
power-domains = <&pgc_pcie2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
pgc_pcie2: power-domain@a {
|
||||||
|
#power-domain-cells = <0>;
|
||||||
|
reg = <IMX8M_POWER_DOMAIN_PCIE2>;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
usdhc1: usdhc@30b40000 {
|
usdhc1: usdhc@30b40000 {
|
||||||
|
15
arch/arm/include/asm/arch-imx8m/power-domain.h
Normal file
15
arch/arm/include/asm/arch-imx8m/power-domain.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/*
|
||||||
|
* Copyright 2017 NXP
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ASM_ARCH_IMX8M_POWER_DOMAIN_H
|
||||||
|
#define _ASM_ARCH_IMX8M_POWER_DOMAIN_H
|
||||||
|
|
||||||
|
struct imx8m_power_domain_platdata {
|
||||||
|
int resource_id;
|
||||||
|
int has_pd;
|
||||||
|
struct power_domain pd;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -37,6 +37,8 @@ CONFIG_FSL_USDHC=y
|
|||||||
CONFIG_DM_ETH=y
|
CONFIG_DM_ETH=y
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_PINCTRL_IMX8M=y
|
CONFIG_PINCTRL_IMX8M=y
|
||||||
|
CONFIG_POWER_DOMAIN=y
|
||||||
|
CONFIG_IMX8M_POWER_DOMAIN=y
|
||||||
CONFIG_DM_REGULATOR=y
|
CONFIG_DM_REGULATOR=y
|
||||||
CONFIG_DM_REGULATOR_FIXED=y
|
CONFIG_DM_REGULATOR_FIXED=y
|
||||||
CONFIG_DM_REGULATOR_GPIO=y
|
CONFIG_DM_REGULATOR_GPIO=y
|
||||||
|
@ -23,6 +23,13 @@ config IMX8_POWER_DOMAIN
|
|||||||
Enable support for manipulating NXP i.MX8 on-SoC power domains via IPC
|
Enable support for manipulating NXP i.MX8 on-SoC power domains via IPC
|
||||||
requests to the SCU.
|
requests to the SCU.
|
||||||
|
|
||||||
|
config IMX8M_POWER_DOMAIN
|
||||||
|
bool "Enable i.MX8M power domain driver"
|
||||||
|
depends on POWER_DOMAIN && ARCH_IMX8M
|
||||||
|
help
|
||||||
|
Enable support for manipulating NXP i.MX8M on-SoC power domains via
|
||||||
|
requests to the ATF.
|
||||||
|
|
||||||
config MTK_POWER_DOMAIN
|
config MTK_POWER_DOMAIN
|
||||||
bool "Enable the MediaTek power domain driver"
|
bool "Enable the MediaTek power domain driver"
|
||||||
depends on POWER_DOMAIN && ARCH_MEDIATEK
|
depends on POWER_DOMAIN && ARCH_MEDIATEK
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
obj-$(CONFIG_$(SPL_)POWER_DOMAIN) += power-domain-uclass.o
|
obj-$(CONFIG_$(SPL_)POWER_DOMAIN) += power-domain-uclass.o
|
||||||
obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
|
obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
|
||||||
obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain.o
|
obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain.o
|
||||||
|
obj-$(CONFIG_IMX8M_POWER_DOMAIN) += imx8m-power-domain.o
|
||||||
obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
|
obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
|
||||||
obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
|
obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
|
||||||
obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o
|
obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o
|
||||||
|
137
drivers/power/domain/imx8m-power-domain.c
Normal file
137
drivers/power/domain/imx8m-power-domain.c
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/*
|
||||||
|
* Copyright 2017 NXP
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <power-domain-uclass.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <asm/arch/power-domain.h>
|
||||||
|
#include <asm/mach-imx/sys_proto.h>
|
||||||
|
#include <dm/device-internal.h>
|
||||||
|
#include <dm/device.h>
|
||||||
|
#include <imx_sip.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
static int imx8m_power_domain_request(struct power_domain *power_domain)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx8m_power_domain_free(struct power_domain *power_domain)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx8m_power_domain_on(struct power_domain *power_domain)
|
||||||
|
{
|
||||||
|
struct udevice *dev = power_domain->dev;
|
||||||
|
struct imx8m_power_domain_platdata *pdata;
|
||||||
|
pdata = dev_get_platdata(dev);
|
||||||
|
|
||||||
|
if (pdata->resource_id < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (pdata->has_pd)
|
||||||
|
power_domain_on(&pdata->pd);
|
||||||
|
|
||||||
|
call_imx_sip(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN, pdata->resource_id, 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx8m_power_domain_off(struct power_domain *power_domain)
|
||||||
|
{
|
||||||
|
struct udevice *dev = power_domain->dev;
|
||||||
|
struct imx8m_power_domain_platdata *pdata;
|
||||||
|
pdata = dev_get_platdata(dev);
|
||||||
|
|
||||||
|
if (pdata->resource_id < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
call_imx_sip(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN, pdata->resource_id, 0);
|
||||||
|
|
||||||
|
if (pdata->has_pd)
|
||||||
|
power_domain_off(&pdata->pd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx8m_power_domain_of_xlate(struct power_domain *power_domain,
|
||||||
|
struct ofnode_phandle_args *args)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx8m_power_domain_bind(struct udevice *dev)
|
||||||
|
{
|
||||||
|
int offset;
|
||||||
|
const char *name;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
offset = dev_of_offset(dev);
|
||||||
|
for (offset = fdt_first_subnode(gd->fdt_blob, offset); offset > 0;
|
||||||
|
offset = fdt_next_subnode(gd->fdt_blob, offset)) {
|
||||||
|
/* Bind the subnode to this driver */
|
||||||
|
name = fdt_get_name(gd->fdt_blob, offset, NULL);
|
||||||
|
|
||||||
|
ret = device_bind_with_driver_data(dev, dev->driver, name,
|
||||||
|
dev->driver_data,
|
||||||
|
offset_to_ofnode(offset),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (ret == -ENODEV)
|
||||||
|
printf("Driver '%s' refuses to bind\n",
|
||||||
|
dev->driver->name);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
printf("Error binding driver '%s': %d\n",
|
||||||
|
dev->driver->name, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx8m_power_domain_probe(struct udevice *dev)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx8m_power_domain_ofdata_to_platdata(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct imx8m_power_domain_platdata *pdata = dev_get_platdata(dev);
|
||||||
|
|
||||||
|
pdata->resource_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
|
||||||
|
"reg", -1);
|
||||||
|
|
||||||
|
if (!power_domain_get(dev, &pdata->pd))
|
||||||
|
pdata->has_pd = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct udevice_id imx8m_power_domain_ids[] = {
|
||||||
|
{ .compatible = "fsl,imx8mq-gpc" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct power_domain_ops imx8m_power_domain_ops = {
|
||||||
|
.request = imx8m_power_domain_request,
|
||||||
|
.free = imx8m_power_domain_free,
|
||||||
|
.on = imx8m_power_domain_on,
|
||||||
|
.off = imx8m_power_domain_off,
|
||||||
|
.of_xlate = imx8m_power_domain_of_xlate,
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(imx8m_power_domain) = {
|
||||||
|
.name = "imx8m_power_domain",
|
||||||
|
.id = UCLASS_POWER_DOMAIN,
|
||||||
|
.of_match = imx8m_power_domain_ids,
|
||||||
|
.bind = imx8m_power_domain_bind,
|
||||||
|
.probe = imx8m_power_domain_probe,
|
||||||
|
.ofdata_to_platdata = imx8m_power_domain_ofdata_to_platdata,
|
||||||
|
.platdata_auto_alloc_size = sizeof(struct imx8m_power_domain_platdata),
|
||||||
|
.ops = &imx8m_power_domain_ops,
|
||||||
|
};
|
21
include/dt-bindings/power/imx8mq-power.h
Executable file
21
include/dt-bindings/power/imx8mq-power.h
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Pengutronix, Lucas Stach <kernel@pengutronix.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DT_BINDINGS_IMX8MQ_POWER_H__
|
||||||
|
#define __DT_BINDINGS_IMX8MQ_POWER_H__
|
||||||
|
|
||||||
|
#define IMX8M_POWER_DOMAIN_MIPI 0
|
||||||
|
#define IMX8M_POWER_DOMAIN_PCIE1 1
|
||||||
|
#define IMX8M_POWER_DOMAIN_USB_OTG1 2
|
||||||
|
#define IMX8M_POWER_DOMAIN_USB_OTG2 3
|
||||||
|
#define IMX8M_POWER_DOMAIN_DDR1 4
|
||||||
|
#define IMX8M_POWER_DOMAIN_GPU 5
|
||||||
|
#define IMX8M_POWER_DOMAIN_VPU 6
|
||||||
|
#define IMX8M_POWER_DOMAIN_DISP 7
|
||||||
|
#define IMX8M_POWER_DOMAIN_MIPI_CSI1 8
|
||||||
|
#define IMX8M_POWER_DOMAIN_MIPI_CSI2 9
|
||||||
|
#define IMX8M_POWER_DOMAIN_PCIE2 10
|
||||||
|
|
||||||
|
#endif
|
@ -6,6 +6,9 @@
|
|||||||
#ifndef _IMX_SIP_H__
|
#ifndef _IMX_SIP_H__
|
||||||
#define _IMX_SIP_H_
|
#define _IMX_SIP_H_
|
||||||
|
|
||||||
|
#define IMX_SIP_GPC 0xC2000000
|
||||||
|
#define IMX_SIP_GPC_PM_DOMAIN 0x03
|
||||||
|
|
||||||
#define IMX_SIP_SRC 0xC2000005
|
#define IMX_SIP_SRC 0xC2000005
|
||||||
#define IMX_SIP_SRC_M4_START 0x00
|
#define IMX_SIP_SRC_M4_START 0x00
|
||||||
#define IMX_SIP_SRC_M4_STARTED 0x01
|
#define IMX_SIP_SRC_M4_STARTED 0x01
|
||||||
|
Loading…
Reference in New Issue
Block a user