From 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 10 May 2024 07:44:59 +0000
Subject: [PATCH] gmac get mac form eeprom
---
kernel/drivers/soc/rockchip/rockchip_pm_config.c | 345 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 316 insertions(+), 29 deletions(-)
diff --git a/kernel/drivers/soc/rockchip/rockchip_pm_config.c b/kernel/drivers/soc/rockchip/rockchip_pm_config.c
index 6c12ef8..c319b79 100644
--- a/kernel/drivers/soc/rockchip/rockchip_pm_config.c
+++ b/kernel/drivers/soc/rockchip/rockchip_pm_config.c
@@ -17,6 +17,7 @@
#include <linux/pm.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
+#include <linux/rockchip/rockchip_pm_config.h>
#include <linux/rockchip/rockchip_sip.h>
#include <linux/suspend.h>
#include <dt-bindings/input/input.h>
@@ -27,6 +28,10 @@
#define MAX_ON_OFF_REG_PROP_NAME_LEN 60
#define MAX_CONFIG_PROP_NAME_LEN 60
+#define RK_ATAG_MCU_SLP_CORE 0x526b0001
+#define RK_ATAG_MCU_SLP_MAX 0x526b00ff
+#define RK_ATAG_NONE 0x00000000
+
enum rk_pm_state {
RK_PM_MEM = 0,
RK_PM_MEM_LITE,
@@ -34,6 +39,7 @@
RK_PM_STATE_MAX
};
+#ifndef MODULE
static const char * const pm_state_str[RK_PM_STATE_MAX] = {
[RK_PM_MEM] = "mem",
[RK_PM_MEM_LITE] = "mem-lite",
@@ -44,13 +50,37 @@
struct regulator_dev *on_reg_list[MAX_ON_OFF_REG_NUM];
struct regulator_dev *off_reg_list[MAX_ON_OFF_REG_NUM];
} on_off_regs_list[RK_PM_STATE_MAX];
+#endif
-static struct rk_sleep_config {
- u32 mode_config;
- u32 wakeup_config;
-} sleep_config[RK_PM_STATE_MAX];
+/* rk_tag related defines */
+#define sleep_tag_next(t) \
+ ((struct rk_sleep_tag *)((__u32 *)(t) + (t)->hdr.size))
+
+struct rk_tag_header {
+ u32 size;
+ u32 tag;
+};
+
+struct rk_sleep_tag {
+ struct rk_tag_header hdr;
+ u32 params[];
+};
+
+struct rk_mcu_sleep_core_tag {
+ struct rk_tag_header hdr;
+ u32 total_size;
+ u32 reserve[13];
+};
+
+struct rk_mcu_sleep_tags {
+ struct rk_mcu_sleep_core_tag core;
+ struct rk_sleep_tag slp_tags;
+};
+
+struct rk_sleep_config *sleep_config;
static const struct of_device_id pm_match_table[] = {
+ { .compatible = "rockchip,pm-config",},
{ .compatible = "rockchip,pm-px30",},
{ .compatible = "rockchip,pm-rk1808",},
{ .compatible = "rockchip,pm-rk322x",},
@@ -60,25 +90,88 @@
{ .compatible = "rockchip,pm-rk3368",},
{ .compatible = "rockchip,pm-rk3399",},
{ .compatible = "rockchip,pm-rk3528",},
+ { .compatible = "rockchip,pm-rk3562",},
{ .compatible = "rockchip,pm-rk3568",},
+ { .compatible = "rockchip,pm-rk3588",},
{ .compatible = "rockchip,pm-rv1126",},
{ },
};
+#ifndef MODULE
+enum {
+ RK_PM_VIRT_PWROFF_EN = 0,
+ RK_PM_VIRT_PWROFF_IRQ_CFG = 1,
+ RK_PM_VIRT_PWROFF_MAX,
+};
+
+static u32 *virtual_pwroff_irqs;
+
static void rockchip_pm_virt_pwroff_prepare(void)
{
- int error;
+ int error, i;
+
+ pm_wakeup_clear(0);
regulator_suspend_prepare(PM_SUSPEND_MEM);
- error = disable_nonboot_cpus();
+ error = suspend_disable_secondary_cpus();
if (error) {
pr_err("Disable nonboot cpus failed!\n");
return;
}
- sip_smc_set_suspend_mode(VIRTUAL_POWEROFF, 0, 1);
+ sip_smc_set_suspend_mode(VIRTUAL_POWEROFF, RK_PM_VIRT_PWROFF_EN, 1);
+
+ if (virtual_pwroff_irqs) {
+ for (i = 0; virtual_pwroff_irqs[i]; i++) {
+ error = sip_smc_set_suspend_mode(VIRTUAL_POWEROFF,
+ RK_PM_VIRT_PWROFF_IRQ_CFG,
+ virtual_pwroff_irqs[i]);
+ if (error) {
+ pr_err("%s: config virtual_pwroff_irqs[%d] error, overflow or update trust!\n",
+ __func__, i);
+ break;
+ }
+ }
+ }
+
sip_smc_virtual_poweroff();
+}
+
+static int parse_virtual_pwroff_config(struct device_node *node)
+{
+ int ret = 0, cnt;
+ u32 virtual_poweroff_en = 0;
+
+ if (!of_property_read_u32_array(node,
+ "rockchip,virtual-poweroff",
+ &virtual_poweroff_en, 1) &&
+ virtual_poweroff_en)
+ pm_power_off_prepare = rockchip_pm_virt_pwroff_prepare;
+
+ if (!virtual_poweroff_en)
+ return 0;
+
+ cnt = of_property_count_u32_elems(node, "rockchip,virtual-poweroff-irqs");
+ if (cnt > 0) {
+ /* 0 as the last element of virtual_pwroff_irqs */
+ virtual_pwroff_irqs = kzalloc((cnt + 1) * sizeof(u32), GFP_KERNEL);
+ if (!virtual_pwroff_irqs) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = of_property_read_u32_array(node, "rockchip,virtual-poweroff-irqs",
+ virtual_pwroff_irqs, cnt);
+ if (ret) {
+ pr_err("%s: get rockchip,virtual-poweroff-irqs error\n",
+ __func__);
+ goto out;
+ }
+ }
+
+out:
+ return ret;
}
static int parse_sleep_config(struct device_node *node, enum rk_pm_state state)
@@ -160,19 +253,170 @@
return 0;
}
+const struct rk_sleep_config *rockchip_get_cur_sleep_config(void)
+{
+ suspend_state_t suspend_state = mem_sleep_current;
+ enum rk_pm_state state = suspend_state - PM_SUSPEND_MEM;
+
+ if (state >= RK_PM_STATE_MAX)
+ return NULL;
+
+ return &sleep_config[state];
+}
+EXPORT_SYMBOL_GPL(rockchip_get_cur_sleep_config);
+#endif
+
+static int parse_mcu_sleep_config(struct device_node *node)
+{
+ int ret, cnt;
+ struct arm_smccc_res res;
+ struct device_node *mcu_sleep_node;
+ struct device_node *child;
+ struct rk_mcu_sleep_tags *config;
+ struct rk_sleep_tag *slp_tag;
+ char *end;
+
+ mcu_sleep_node = of_find_node_by_name(node, "rockchip-mcu-sleep-cfg");
+ if (IS_ERR_OR_NULL(mcu_sleep_node)) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ cnt = of_get_child_count(mcu_sleep_node);
+ if (!cnt) {
+ ret = -EINVAL;
+ goto free_mcu_mode;
+ }
+
+ /*
+ * 4kb for sleep parameters
+ */
+ res = sip_smc_request_share_mem(1, SHARE_PAGE_TYPE_SLEEP);
+ if (res.a0 != 0) {
+ pr_err("%s: no trust memory for mcu_sleep\n", __func__);
+ ret = -ENOMEM;
+ goto free_mcu_mode;
+ }
+
+ /* Initialize core tag */
+ memset((void *)res.a1, 0, sizeof(struct rk_mcu_sleep_tags));
+ config = (struct rk_mcu_sleep_tags *)res.a1;
+ config->core.hdr.tag = RK_ATAG_MCU_SLP_CORE;
+ config->core.hdr.size = sizeof(struct rk_mcu_sleep_core_tag) / sizeof(u32);
+ config->core.total_size = sizeof(struct rk_mcu_sleep_tags) -
+ sizeof(struct rk_sleep_tag);
+
+ slp_tag = &config->slp_tags;
+
+ /* End point of sleep data */
+ end = (char *)config + PAGE_SIZE - sizeof(struct rk_sleep_tag);
+
+ for_each_available_child_of_node(mcu_sleep_node, child) {
+ /* Is overflow? */
+ if ((char *)slp_tag->params >= end)
+ break;
+
+ ret = of_property_read_u32_array(child, "rockchip,tag",
+ &slp_tag->hdr.tag, 1);
+ if (ret ||
+ slp_tag->hdr.tag <= RK_ATAG_MCU_SLP_CORE ||
+ slp_tag->hdr.tag >= RK_ATAG_MCU_SLP_MAX) {
+ pr_info("%s: no or invalid rockchip,tag in %s\n",
+ __func__, child->name);
+
+ continue;
+ }
+
+ cnt = of_property_count_u32_elems(child, "rockchip,params");
+ if (cnt > 0) {
+ /* Is overflow? */
+ if ((char *)(slp_tag->params + cnt) >= end) {
+ pr_warn("%s: no more space for rockchip,tag in %s\n",
+ __func__, child->name);
+ break;
+ }
+
+ ret = of_property_read_u32_array(child, "rockchip,params",
+ slp_tag->params, cnt);
+ if (ret) {
+ pr_err("%s: rockchip,params error in %s\n",
+ __func__, child->name);
+ break;
+ }
+
+ slp_tag->hdr.size =
+ cnt + sizeof(struct rk_tag_header) / sizeof(u32);
+ } else if (cnt == 0) {
+ slp_tag->hdr.size = 0;
+ } else {
+ continue;
+ }
+
+ config->core.total_size += slp_tag->hdr.size * sizeof(u32);
+
+ slp_tag = sleep_tag_next(slp_tag);
+ }
+
+ /* Add none tag.
+ * Compiler will combine the follow code as "str xzr, [x28]", but
+ * "slp->hdr" may not be 8-byte alignment. So we use memset_io instead:
+ * slp_tag->hdr.size = 0;
+ * slp_tag->hdr.tag = RK_ATAG_NONE;
+ */
+ memset_io(&slp_tag->hdr, 0, sizeof(slp_tag->hdr));
+
+ config->core.total_size += sizeof(struct rk_sleep_tag);
+
+ ret = 0;
+
+free_mcu_mode:
+ of_node_put(mcu_sleep_node);
+out:
+ return ret;
+}
+
+static int parse_io_config(struct device *dev)
+{
+ int ret = 0, cnt;
+ struct device_node *node = dev->of_node;
+ struct rk_sleep_config *config = &sleep_config[RK_PM_MEM];
+
+ cnt = of_property_count_u32_elems(node, "rockchip,sleep-io-config");
+ if (cnt > 0) {
+ /* 0 as the last element of virtual_pwroff_irqs */
+ config->sleep_io_config =
+ devm_kmalloc_array(dev, cnt, sizeof(u32), GFP_KERNEL);
+ if (!config->sleep_io_config) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = of_property_read_u32_array(node, "rockchip,sleep-io-config",
+ config->sleep_io_config, cnt);
+ if (ret) {
+ dev_err(dev, "get rockchip,sleep-io-config error\n");
+ goto out;
+ }
+
+ config->sleep_io_config_cnt = cnt;
+ } else {
+ dev_dbg(dev, "not set sleep-pin-config\n");
+ }
+
+out:
+ return ret;
+}
+
static int pm_config_probe(struct platform_device *pdev)
{
const struct of_device_id *match_id;
struct device_node *node;
- struct rk_sleep_config *config = &sleep_config[RK_PM_MEM];
- u32 pwm_regulator_config = 0;
- int gpio_temp[10];
- u32 sleep_debug_en = 0;
- u32 apios_suspend = 0;
- u32 virtual_poweroff_en = 0;
+ struct rk_sleep_config *config;
+
enum of_gpio_flags flags;
int i = 0;
int length;
+ int ret;
match_id = of_match_node(pm_match_table, pdev->dev.of_node);
if (!match_id)
@@ -184,6 +428,14 @@
dev_err(&pdev->dev, "%s dev node err\n", __func__);
return -ENODEV;
}
+
+ sleep_config =
+ devm_kmalloc_array(&pdev->dev, RK_PM_STATE_MAX,
+ sizeof(*sleep_config), GFP_KERNEL);
+ if (!sleep_config)
+ return -ENOMEM;
+
+ config = &sleep_config[RK_PM_MEM];
if (of_property_read_u32_array(node,
"rockchip,sleep-mode-config",
@@ -201,58 +453,90 @@
if (of_property_read_u32_array(node,
"rockchip,pwm-regulator-config",
- &pwm_regulator_config, 1))
+ &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,
+ config->pwm_regulator_config,
0);
length = of_gpio_named_count(node, "rockchip,power-ctrl");
if (length > 0 && length < 10) {
+ config->power_ctrl_config_cnt = length;
+ config->power_ctrl_config =
+ devm_kmalloc_array(&pdev->dev, length,
+ sizeof(u32), GFP_KERNEL);
+ if (!config->power_ctrl_config)
+ return -ENOMEM;
+
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]))
+ config->power_ctrl_config[i] =
+ of_get_named_gpio_flags(node,
+ "rockchip,power-ctrl",
+ i,
+ &flags);
+ if (!gpio_is_valid(config->power_ctrl_config[i]))
break;
sip_smc_set_suspend_mode(GPIO_POWER_CONFIG,
i,
- gpio_temp[i]);
+ config->power_ctrl_config[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))
+ &config->sleep_debug_en, 1))
sip_smc_set_suspend_mode(SUSPEND_DEBUG_ENABLE,
- sleep_debug_en,
+ config->sleep_debug_en,
0);
if (!of_property_read_u32_array(node,
"rockchip,apios-suspend",
- &apios_suspend, 1))
+ &config->apios_suspend, 1))
sip_smc_set_suspend_mode(APIOS_SUSPEND_CONFIG,
- apios_suspend,
+ config->apios_suspend,
0);
if (!of_property_read_u32_array(node,
- "rockchip,virtual-poweroff",
- &virtual_poweroff_en, 1) &&
- virtual_poweroff_en)
- pm_power_off_prepare = rockchip_pm_virt_pwroff_prepare;
+ "rockchip,sleep-io-ret-config",
+ &config->io_ret_config, 1)) {
+ ret = sip_smc_set_suspend_mode(SUSPEND_IO_RET_CONFIG, config->io_ret_config, 0);
+ if (ret)
+ dev_warn(&pdev->dev,
+ "sleep-io-ret-config failed (%d), check parameters or update trust\n",
+ ret);
+ }
+
+ if (!of_property_read_u32_array(node,
+ "rockchip,sleep-pin-config",
+ config->sleep_pin_config, 2)) {
+ ret = sip_smc_set_suspend_mode(SLEEP_PIN_CONFIG,
+ config->sleep_pin_config[0],
+ config->sleep_pin_config[1]);
+ if (ret)
+ dev_warn(&pdev->dev,
+ "sleep-pin-config failed (%d), check parameters or update trust\n",
+ ret);
+ }
+
+ parse_io_config(&pdev->dev);
+ parse_mcu_sleep_config(node);
+
+#ifndef MODULE
+ parse_virtual_pwroff_config(node);
for (i = RK_PM_MEM; i < RK_PM_STATE_MAX; i++) {
parse_sleep_config(node, i);
parse_on_off_regulator(node, i);
}
+#endif
return 0;
}
+#ifndef MODULE
static int pm_config_prepare(struct device *dev)
{
int i;
@@ -300,13 +584,16 @@
static const struct dev_pm_ops rockchip_pm_ops = {
.prepare = pm_config_prepare,
};
+#endif
static struct platform_driver pm_driver = {
.probe = pm_config_probe,
.driver = {
.name = "rockchip-pm",
.of_match_table = pm_match_table,
+#ifndef MODULE
.pm = &rockchip_pm_ops,
+#endif
},
};
--
Gitblit v1.6.2