uboot/drivers/reboot-mode/reboot-mode-uclass.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c), Vaisala Oyj
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <dm/device_compat.h>
   9#include <dm/devres.h>
  10#include <exports.h>
  11#include <reboot-mode/reboot-mode.h>
  12
  13int dm_reboot_mode_update(struct udevice *dev)
  14{
  15        struct reboot_mode_ops *ops = reboot_mode_get_ops(dev);
  16        u32 rebootmode;
  17        int ret, i;
  18
  19        assert(ops);
  20
  21        if (!ops->get)
  22                return -ENOSYS;
  23
  24        ret = ops->get(dev, &rebootmode);
  25        if (ret < 0) {
  26                dev_err(dev, "Failed to retrieve the reboot mode value\n");
  27                return ret;
  28        }
  29
  30        const struct reboot_mode_uclass_platdata *plat_data =
  31                dev_get_uclass_plat(dev);
  32
  33        for (i = 0; i < plat_data->count; i++) {
  34                if (plat_data->modes[i].mode_id == rebootmode) {
  35                        ret = env_set(plat_data->env_variable,
  36                                      plat_data->modes[i].mode_name);
  37                        if (ret) {
  38                                dev_err(dev, "Failed to set env: %s\n",
  39                                        plat_data->env_variable);
  40                                return ret;
  41                        }
  42                }
  43        }
  44
  45        if (ops->set) {
  46                /* Clear the value */
  47                rebootmode = 0;
  48                ret = ops->set(dev, rebootmode);
  49                if (ret) {
  50                        dev_err(dev, "Failed to clear the reboot mode\n");
  51                        return ret;
  52                }
  53        }
  54
  55        return 0;
  56}
  57
  58int dm_reboot_mode_pre_probe(struct udevice *dev)
  59{
  60        struct reboot_mode_uclass_platdata *plat_data;
  61
  62        plat_data = dev_get_uclass_plat(dev);
  63        if (!plat_data)
  64                return -EINVAL;
  65
  66#if CONFIG_IS_ENABLED(OF_CONTROL)
  67        const char *mode_prefix = "mode-";
  68        const int mode_prefix_len = strlen(mode_prefix);
  69        struct ofprop property;
  70        const u32 *propvalue;
  71        const char *propname;
  72
  73        plat_data->env_variable = dev_read_string(dev, "u-boot,env-variable");
  74        if (!plat_data->env_variable)
  75                plat_data->env_variable = "reboot-mode";
  76
  77        plat_data->count = 0;
  78
  79        dev_for_each_property(property, dev) {
  80                propvalue = dev_read_prop_by_prop(&property, &propname, NULL);
  81                if (!propvalue) {
  82                        dev_err(dev, "Could not get the value for property %s\n",
  83                                propname);
  84                        return -EINVAL;
  85                }
  86
  87                if (!strncmp(propname, mode_prefix, mode_prefix_len))
  88                        plat_data->count++;
  89        }
  90
  91        plat_data->modes = devm_kcalloc(dev, plat_data->count,
  92                                        sizeof(struct reboot_mode_mode), 0);
  93
  94        struct reboot_mode_mode *next = plat_data->modes;
  95
  96        dev_for_each_property(property, dev) {
  97                propvalue = dev_read_prop_by_prop(&property, &propname, NULL);
  98                if (!propvalue) {
  99                        dev_err(dev, "Could not get the value for property %s\n",
 100                                propname);
 101                        return -EINVAL;
 102                }
 103
 104                if (!strncmp(propname, mode_prefix, mode_prefix_len)) {
 105                        next->mode_name = &propname[mode_prefix_len];
 106                        next->mode_id = fdt32_to_cpu(*propvalue);
 107
 108                        next++;
 109                }
 110        }
 111#else
 112        if (!plat_data->env_variable)
 113                plat_data->env_variable = "reboot-mode";
 114
 115#endif
 116
 117        return 0;
 118}
 119
 120UCLASS_DRIVER(reboot_mode) = {
 121        .name   = "reboot-mode",
 122        .id     = UCLASS_REBOOT_MODE,
 123        .pre_probe      = dm_reboot_mode_pre_probe,
 124        .per_device_plat_auto =
 125                sizeof(struct reboot_mode_uclass_platdata),
 126};
 127