KernelNanopiR5S-6/drivers/soc/rockchip/pm_config.c
2024-09-10 15:59:00 +02:00

151 lines
3.9 KiB
C

/*
* Rockchip Generic power configuration support.
*
* Copyright (c) 2017 ROCKCHIP, Co. Ltd.
*
* 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/arm-smccc.h>
#include <linux/bitops.h>
#include <linux/cpu.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/regulator/machine.h>
#include <linux/suspend.h>
#include <dt-bindings/input/input.h>
#ifdef CONFIG_ROCKCHIP_SIP
#include <linux/rockchip/rockchip_sip.h>
#else
#define SIP_SUSPEND_MODE 0x82000003
/* SIP_SUSPEND_MODE32 call types */
#define SUSPEND_MODE_CONFIG 0x01
#define WKUP_SOURCE_CONFIG 0x02
#define PWM_REGULATOR_CONFIG 0x03
#define GPIO_POWER_CONFIG 0x04
#define SUSPEND_DEBUG_ENABLE 0x05
#define APIOS_SUSPEND_CONFIG 0x06
static int sip_smc_set_suspend_mode(u32 ctrl, u32 config1, u32 config2)
{
struct arm_smccc_res res;
arm_smccc_smc(SIP_SUSPEND_MODE, ctrl, config1, config2, 0, 0, 0, 0, &res);
return res.a0;
}
#endif
#define PM_INVALID_GPIO 0xffff
static const struct of_device_id pm_match_table[] = {
{ .compatible = "rockchip,pm-px30",},
{ .compatible = "rockchip,pm-rk1808",},
{ .compatible = "rockchip,pm-rk322x",},
{ .compatible = "rockchip,pm-rk3288",},
{ .compatible = "rockchip,pm-rk3308",},
{ .compatible = "rockchip,pm-rk3328",},
{ .compatible = "rockchip,pm-rk3368",},
{ .compatible = "rockchip,pm-rk3399",},
{ .compatible = "rockchip,pm-rv1126",},
{ },
};
static int __init pm_config_init(struct platform_device *pdev)
{
const struct of_device_id *match_id;
struct device_node *node;
u32 mode_config = 0;
u32 wakeup_config = 0;
u32 pwm_regulator_config = 0;
int gpio_temp[10];
u32 sleep_debug_en = 0;
u32 apios_suspend = 0;
enum of_gpio_flags flags;
int i = 0;
int length;
match_id = of_match_node(pm_match_table, pdev->dev.of_node);
if (!match_id)
return -ENODEV;
node = of_find_node_by_name(NULL, "rockchip-suspend");
if (IS_ERR_OR_NULL(node)) {
dev_err(&pdev->dev, "%s dev node err\n", __func__);
return -ENODEV;
}
if (of_property_read_u32_array(node,
"rockchip,sleep-mode-config",
&mode_config, 1))
dev_warn(&pdev->dev, "not set sleep mode config\n");
else
sip_smc_set_suspend_mode(SUSPEND_MODE_CONFIG, mode_config, 0);
if (of_property_read_u32_array(node,
"rockchip,wakeup-config",
&wakeup_config, 1))
dev_warn(&pdev->dev, "not set wakeup-config\n");
else
sip_smc_set_suspend_mode(WKUP_SOURCE_CONFIG, wakeup_config, 0);
if (of_property_read_u32_array(node,
"rockchip,pwm-regulator-config",
&pwm_regulator_config, 1))
dev_warn(&pdev->dev, "not set pwm-regulator-config\n");
else
sip_smc_set_suspend_mode(PWM_REGULATOR_CONFIG,
pwm_regulator_config,
0);
length = of_gpio_named_count(node, "rockchip,power-ctrl");
if (length > 0 && length < 10) {
for (i = 0; i < length; i++) {
gpio_temp[i] = of_get_named_gpio_flags(node,
"rockchip,power-ctrl",
i,
&flags);
if (!gpio_is_valid(gpio_temp[i]))
break;
sip_smc_set_suspend_mode(GPIO_POWER_CONFIG,
i,
gpio_temp[i]);
}
}
sip_smc_set_suspend_mode(GPIO_POWER_CONFIG, i, PM_INVALID_GPIO);
if (!of_property_read_u32_array(node,
"rockchip,sleep-debug-en",
&sleep_debug_en, 1))
sip_smc_set_suspend_mode(SUSPEND_DEBUG_ENABLE,
sleep_debug_en,
0);
if (!of_property_read_u32_array(node,
"rockchip,apios-suspend",
&apios_suspend, 1))
sip_smc_set_suspend_mode(APIOS_SUSPEND_CONFIG,
apios_suspend,
0);
return 0;
}
static struct platform_driver pm_driver = {
.driver = {
.name = "rockchip-pm",
.of_match_table = pm_match_table,
},
};
static int __init rockchip_pm_drv_register(void)
{
return platform_driver_probe(&pm_driver, pm_config_init);
}
subsys_initcall(rockchip_pm_drv_register);