lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <CAHX4x85B9AbVNJgHeKpuZhDKcQQhrHZLuMXRZ4214YCF5tU68Q@mail.gmail.com>
Date:   Tue, 5 Mar 2019 10:11:35 -0700
From:   Nick Crews <ncrews@...omium.org>
To:     Enric Balletbo i Serra <enric.balletbo@...labora.com>,
        Benson Leung <bleung@...omium.org>, sre@...nel.org,
        linux-pm@...r.kernel.org
Cc:     linux-kernel <linux-kernel@...r.kernel.org>,
        Duncan Laurie <dlaurie@...omium.org>,
        Oleh Lamzin <lamzin@...gle.com>,
        Bartosz Fabianowski <bartfab@...gle.com>,
        Daniel Erat <derat@...gle.com>,
        Guenter Roeck <groeck@...gle.com>,
        Dmitry Torokhov <dtor@...gle.com>
Subject: Re: [RFC power_supply 2/2] platform/chrome: Add Peak Shift and Adv
 Batt Charging for Wilco EC

Friendly bump to make sure this doesn't slip down peoples' inboxes.
Any comments would be appreciated :)

-Nick
On Fri, Feb 22, 2019 at 4:10 PM Nick Crews <ncrews@...omium.org> wrote:
>
> This is an example driver that uses the proposed Peak Shift and
> Adv Batt Charging support in the main power supply subsystem.
>
> At this point, there is no actual communication with the EC,
> the point of this is to show the interface that usespace would see,
> and to show the use case for the added properties to the power
> supply susbsystem. To see the location of where the properties
> would appear in userspace, see the Documentation file.
>
> Signed-off-by: Nick Crews <ncrews@...omium.org>
> ---
>  .../ABI/testing/sysfs-class-power-wilco       |  81 +++++++
>  drivers/platform/chrome/wilco_ec/Kconfig      |  14 ++
>  drivers/platform/chrome/wilco_ec/Makefile     |   2 +
>  .../platform/chrome/wilco_ec/advanced_power.c | 199 ++++++++++++++++++
>  drivers/platform/chrome/wilco_ec/core.c       |  14 ++
>  include/linux/platform_data/wilco-ec.h        |   2 +
>  6 files changed, 312 insertions(+)
>  create mode 100644 Documentation/ABI/testing/sysfs-class-power-wilco
>  create mode 100644 drivers/platform/chrome/wilco_ec/advanced_power.c
>
> diff --git a/Documentation/ABI/testing/sysfs-class-power-wilco b/Documentation/ABI/testing/sysfs-class-power-wilco
> new file mode 100644
> index 000000000000..5c96b28aa597
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-class-power-wilco
> @@ -0,0 +1,81 @@
> +What:          /sys/class/power_supply/wilco_adv_power/peak_shift_sched_<day of week>
> +Date:          January 2019
> +KernelVersion: 4.19
> +Description:
> +               For each weekday a start and end time to run in Peak Shift mode
> +               can be set. During these times the system will run from the
> +               battery even if the AC is attached as long as the battery stays
> +               above the threshold specified. After the end time specified the
> +               system will run from AC if attached but will not charge the
> +               battery. The system will again function normally using AC and
> +               recharging the battery after the specified Charge Start time.
> +
> +               The input buffer must have the format "start_hr start_min end_hr
> +               end_min charge_start_hr charge_start_min" The hour fields must
> +               be in the range [0-23], and the minutes must be one of (0, 15,
> +               30, 45). The string must be parseable by sscanf() using the
> +               format string "%d %d %d %d %d %d". An example valid input is
> +               "6 15   009 45 23 0", which corresponds to 6:15, 9:45, and 23:00
> +
> +               The output buffer will be filled with the format "start_hr
> +               start_min end_hr end_min charge_start_hr charge_start_min" The
> +               hour fields will be in the range [0-23], and the minutes will be
> +               one of (0, 15, 30, 45). Each number will be zero padded to two
> +               characters. An example output is "06 15 09 45 23 00", which
> +               corresponds to 6:15, 9:45, and 23:00
> +
> +What:          /sys/class/power_supply/wilco_adv_power/peak_shift_enable
> +Date:          January 2019
> +KernelVersion: 4.19
> +Description:
> +               Enable/disable the peakshift power management policy.
> +
> +               Input should be parseable by kstrtou8().
> +               Output will be either "0\n" or "1\n".
> +
> +What:          /sys/class/power_supply/wilco_adv_power/peak_shift_batt_threshold
> +Date:          January 2019
> +KernelVersion: 4.19
> +Description:
> +               Read/write the battery percentage threshold for which the
> +               peakshift policy is used. The valid range is [15, 50].
> +
> +               Input should be parseable to range [15,50] by kstrtou8().
> +               Output will be two-digit ascii number in range [15, 50].
> +
> +What:          /sys/class/power_supply/wilco_adv_power/adv_batt_charging_sched_<day of week>
> +Date:          January 2019
> +KernelVersion: 4.19
> +Description:
> +               Advanced Charging Mode allows the user to maximize the battery
> +               health. In Advanced Charging Mode the system will use standard
> +               charging algorithm and other techniques during non-work hours to
> +               maximize battery health. During work hours, an express charge is
> +               used. This express charge allows the battery to be charged
> +               faster; therefore, the battery is at full charge sooner. For
> +               each day the time in which the system will be most heavily used
> +               is specified by the start time and the duration.
> +
> +               The input buffer must have the format "start_hr start_min
> +               duration_hr duration_min" The hour fields must be in the range
> +               [0-23], and the minutes must be one of (0, 15, 30, 45). The
> +               string must be parseable by sscanf() using the format string
> +               "%d %d %d %d %d %d". An example valid input is "0006 15  23 45",
> +               which corresponds to a start time of 6:15 and a duration of
> +               23:45.
> +
> +               The output buffer will be filled with the format "start_hr
> +               start_min duration_hr duration_min" The hour fields will be in
> +               the range [0-23], and the minutes will be one of (0, 15, 30,
> +               45). Each number will be zero padded to two characters. An
> +               example output is "06 15 23 45", which corresponds to a start
> +               time of 6:15 and a duration of 23:45
> +
> +What:          /sys/class/power_supply/wilco_adv_power/adv_batt_charging_enable
> ++Date:          January 2019
> ++KernelVersion: 4.19
> ++Description:
> +               Enable/disable the Advanced Battery Charging policy.
> +
> +               Input should be parseable by kstrtou8().
> +               Output will be either "0\n" or "1\n".
> diff --git a/drivers/platform/chrome/wilco_ec/Kconfig b/drivers/platform/chrome/wilco_ec/Kconfig
> index 4a119ced4d0c..0e172076b14e 100644
> --- a/drivers/platform/chrome/wilco_ec/Kconfig
> +++ b/drivers/platform/chrome/wilco_ec/Kconfig
> @@ -18,3 +18,17 @@ config WILCO_EC_DEBUGFS
>           manipulation and allow for testing arbitrary commands.  This
>           interface is intended for debug only and will not be present
>           on production devices.
> +
> +config WILCO_EC_ADV_POWER
> +       tristate "Enable Peak Shift and Adv Batt Charging power policies"
> +       depends on WILCO_EC
> +       help
> +         If you say Y here, you get support to control two power policies
> +         managed by the EC:
> +
> +         Peak Shift is power saving policy that minimizes AC usage during
> +         the peak usage times during the day.
> +
> +         In Advanced Charging Mode the system will use standard
> +         charging algorithms and other techniques during non-work
> +         hours to maximize battery health.
> diff --git a/drivers/platform/chrome/wilco_ec/Makefile b/drivers/platform/chrome/wilco_ec/Makefile
> index 063e7fb4ea17..b7e8df5d3806 100644
> --- a/drivers/platform/chrome/wilco_ec/Makefile
> +++ b/drivers/platform/chrome/wilco_ec/Makefile
> @@ -4,3 +4,5 @@ wilco_ec-objs                           := core.o mailbox.o
>  obj-$(CONFIG_WILCO_EC)                 += wilco_ec.o
>  wilco_ec_debugfs-objs                  := debugfs.o
>  obj-$(CONFIG_WILCO_EC_DEBUGFS)         += wilco_ec_debugfs.o
> +wilco_ec_adv_power-objs                        := advanced_power.o
> +obj-$(CONFIG_WILCO_EC_ADV_POWER)       += wilco_ec_adv_power.o
> diff --git a/drivers/platform/chrome/wilco_ec/advanced_power.c b/drivers/platform/chrome/wilco_ec/advanced_power.c
> new file mode 100644
> index 000000000000..d53c8d60f523
> --- /dev/null
> +++ b/drivers/platform/chrome/wilco_ec/advanced_power.c
> @@ -0,0 +1,199 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Peak Shift and Advanced Battery Charging Power Policies
> + *
> + * Copyright 2018 Google LLC
> + *
> + * Peak Shift is power saving policy that minimizes AC usage during the
> + * peak usage times during the day. For each weekday a start and end time
> + * to run in Peak Shift mode can be set. During these times the system will
> + * run from the battery even if the AC is attached as long as the battery
> + * stays above the threshold specified. After the end time specified the
> + * system will run from AC if attached but will not charge the battery. The
> + * system will again function normally using AC and recharging the battery
> + * after the specified Charge Start time.
> + *
> + * Advanced Charging Mode allows the user to maximize the battery health.
> + * In Advanced Charging Mode the system will use standard charging
> + * algorithm and other techniques during non-work hours to maximize battery
> + * health. During work hours, an express charge is used. This express
> + * charge allows the battery to be charged faster; therefore, the battery
> + * is at full charge sooner. For each day the time in which the system will
> + * be most heavily used is specified by the start time and the duration.
> +
> + */
> +#include <linux/platform_device.h>
> +#include <linux/power_supply.h>
> +#include <linux/module.h>
> +#include <linux/platform_data/wilco-ec.h>
> +
> +#define DRV_NAME "wilco_adv_power"
> +
> +static enum power_supply_property wilco_adv_power_props[] = {
> +       POWER_SUPPLY_PROP_PEAK_SHIFT_ENABLE,
> +       POWER_SUPPLY_PROP_PEAK_SHIFT_BATT_THRESHOLD,
> +       POWER_SUPPLY_PROP_PEAK_SHIFT_SCHED_SUNDAY,
> +       POWER_SUPPLY_PROP_PEAK_SHIFT_SCHED_MONDAY,
> +       POWER_SUPPLY_PROP_PEAK_SHIFT_SCHED_TUESDAY,
> +       POWER_SUPPLY_PROP_PEAK_SHIFT_SCHED_WEDNESDAY,
> +       POWER_SUPPLY_PROP_PEAK_SHIFT_SCHED_THURSDAY,
> +       POWER_SUPPLY_PROP_PEAK_SHIFT_SCHED_FRIDAY,
> +       POWER_SUPPLY_PROP_PEAK_SHIFT_SCHED_SATURDAY,
> +
> +       POWER_SUPPLY_PROP_ADV_BATT_CHARGING_ENABLE,
> +       POWER_SUPPLY_PROP_ADV_BATT_CHARGING_SCHED_SUNDAY,
> +       POWER_SUPPLY_PROP_ADV_BATT_CHARGING_SCHED_MONDAY,
> +       POWER_SUPPLY_PROP_ADV_BATT_CHARGING_SCHED_TUESDAY,
> +       POWER_SUPPLY_PROP_ADV_BATT_CHARGING_SCHED_WEDNESDAY,
> +       POWER_SUPPLY_PROP_ADV_BATT_CHARGING_SCHED_THURSDAY,
> +       POWER_SUPPLY_PROP_ADV_BATT_CHARGING_SCHED_FRIDAY,
> +       POWER_SUPPLY_PROP_ADV_BATT_CHARGING_SCHED_SATURDAY,
> +};
> +
> +struct wilco_adv_power_data {
> +       struct wilco_ec_device *ec;
> +       struct power_supply *psy;
> +};
> +
> +static int wilco_adv_power_get_property(struct power_supply *psy,
> +                                        enum power_supply_property psp,
> +                                        union power_supply_propval *val)
> +{
> +       // struct wilco_adv_power_data *data = power_supply_get_drvdata(psy);
> +       // This is a stub, really will use mailbox() on data->ec...
> +       int ret = 0;
> +
> +       switch (psp) {
> +       case POWER_SUPPLY_PROP_PEAK_SHIFT_ENABLE:
> +               val->intval = 1;
> +               break;
> +       case POWER_SUPPLY_PROP_PEAK_SHIFT_BATT_THRESHOLD:
> +               val->intval = 42;
> +               break;
> +       case POWER_SUPPLY_PROP_PEAK_SHIFT_SCHED_SUNDAY ...
> +            POWER_SUPPLY_PROP_PEAK_SHIFT_SCHED_SATURDAY:
> +               val->psval.start_hours = 23;
> +               val->psval.start_minutes = 0;
> +               val->psval.end_hours = 75;
> +               val->psval.end_minutes = 1;
> +               val->psval.charge_start_hours = 0;
> +               val->psval.charge_start_minutes = 59;
> +               break;
> +       case POWER_SUPPLY_PROP_ADV_BATT_CHARGING_ENABLE:
> +               val->intval = 0;
> +               break;
> +       case POWER_SUPPLY_PROP_ADV_BATT_CHARGING_SCHED_SUNDAY ...
> +            POWER_SUPPLY_PROP_ADV_BATT_CHARGING_SCHED_SATURDAY:
> +               val->abcval.start_hours = 67;
> +               val->abcval.start_minutes = 13;
> +               val->abcval.duration_hours = 0;
> +               val->abcval.duration_minutes = 88;
> +               break;
> +       default:
> +               ret = -EINVAL;
> +               break;
> +       }
> +
> +       return ret;
> +}
> +
> +static int wilco_adv_power_set_property(struct power_supply *psy,
> +                                       enum power_supply_property psp,
> +                                       const union power_supply_propval *val)
> +{
> +       // struct wilco_adv_power_data *data = power_supply_get_drvdata(psy);
> +       // This is a stub, really will use mailbox() on data->ec...
> +
> +       switch (psp) {
> +       case POWER_SUPPLY_PROP_PEAK_SHIFT_ENABLE:
> +               dev_err(&psy->dev, "peak_shift_enable=%d", val->intval);
> +               break;
> +       case POWER_SUPPLY_PROP_PEAK_SHIFT_BATT_THRESHOLD:
> +               dev_err(&psy->dev, "peak_shift_batt_thresh=%d", val->intval);
> +               break;
> +       case POWER_SUPPLY_PROP_PEAK_SHIFT_SCHED_SUNDAY ...
> +            POWER_SUPPLY_PROP_PEAK_SHIFT_SCHED_SATURDAY:
> +               dev_err(&psy->dev, "peak_shift_sched_%d=%d %d %d %d %d %d", psp,
> +                       val->psval.start_hours,
> +                       val->psval.start_minutes,
> +                       val->psval.end_hours,
> +                       val->psval.end_minutes,
> +                       val->psval.charge_start_hours,
> +                       val->psval.charge_start_minutes);
> +               break;
> +       case POWER_SUPPLY_PROP_ADV_BATT_CHARGING_ENABLE:
> +               dev_err(&psy->dev, "adv_batt_charging_enable=%d", val->intval);
> +               break;
> +       case POWER_SUPPLY_PROP_ADV_BATT_CHARGING_SCHED_SUNDAY ...
> +            POWER_SUPPLY_PROP_ADV_BATT_CHARGING_SCHED_SATURDAY:
> +               dev_err(&psy->dev, "adv_batt_charging_sched_%d=%d %d %d %d", psp,
> +                       val->abcval.start_hours,
> +                       val->abcval.start_minutes,
> +                       val->abcval.duration_hours,
> +                       val->abcval.duration_minutes);
> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +
> +       return 0;
> +}
> +
> +static inline int wilco_adv_power_property_is_writeable(struct power_supply *psy,
> +                                       enum power_supply_property psp)
> +{
> +       return 1;
> +}
> +
> +static const struct power_supply_desc wps_desc = {
> +       .properties     = wilco_adv_power_props,
> +       .num_properties = ARRAY_SIZE(wilco_adv_power_props),
> +       .get_property   = wilco_adv_power_get_property,
> +       .set_property   = wilco_adv_power_set_property,
> +       .property_is_writeable = wilco_adv_power_property_is_writeable,
> +       .name           = DRV_NAME,
> +       .type           = POWER_SUPPLY_TYPE_MAINS,
> +};
> +
> +static int wilco_adv_power_probe(struct platform_device *pdev)
> +{
> +       struct wilco_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
> +       struct power_supply_config psy_cfg = {};
> +       struct wilco_adv_power_data *data;
> +
> +       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +       if (data == NULL)
> +               return -ENOMEM;
> +
> +       data->ec = ec;
> +       psy_cfg.drv_data = data;
> +       platform_set_drvdata(pdev, data);
> +
> +       data->psy = power_supply_register(&pdev->dev, &wps_desc, &psy_cfg);
> +       if (IS_ERR(data->psy))
> +               return PTR_ERR(data->psy);
> +
> +       return 0;
> +}
> +
> +static int wilco_adv_power_remove(struct platform_device *pdev)
> +{
> +       struct wilco_adv_power_data *data = platform_get_drvdata(pdev);
> +
> +       power_supply_unregister(data->psy);
> +       return 0;
> +}
> +
> +static struct platform_driver wilco_adv_power_driver = {
> +       .probe          = wilco_adv_power_probe,
> +       .remove         = wilco_adv_power_remove,
> +       .driver = {
> +               .name = DRV_NAME
> +       }
> +};
> +module_platform_driver(wilco_adv_power_driver);
> +
> +MODULE_ALIAS("platform:" DRV_NAME);
> +MODULE_AUTHOR("Nick Crews <ncrews@...omium.org>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("Wilco Peak Shift and Advanced Battery Charging driver");
> diff --git a/drivers/platform/chrome/wilco_ec/core.c b/drivers/platform/chrome/wilco_ec/core.c
> index 05e1e2be1c91..8f53214cbb1e 100644
> --- a/drivers/platform/chrome/wilco_ec/core.c
> +++ b/drivers/platform/chrome/wilco_ec/core.c
> @@ -89,8 +89,21 @@ static int wilco_ec_probe(struct platform_device *pdev)
>                 goto unregister_debugfs;
>         }
>
> +       /* Register child device that will be found by the peak shift driver. */
> +       ec->adv_power_pdev = platform_device_register_data(dev,
> +                                                          "wilco_adv_power",
> +                                                          PLATFORM_DEVID_AUTO,
> +                                                          NULL, 0);
> +       if (IS_ERR(ec->adv_power_pdev)) {
> +               dev_err(dev, "Failed to create adv power platform device\n");
> +               ret = PTR_ERR(ec->adv_power_pdev);
> +               goto unregister_rtc;
> +       }
> +
>         return 0;
>
> +unregister_rtc:
> +       platform_device_unregister(ec->rtc_pdev);
>  unregister_debugfs:
>         if (ec->debugfs_pdev)
>                 platform_device_unregister(ec->debugfs_pdev);
> @@ -102,6 +115,7 @@ static int wilco_ec_remove(struct platform_device *pdev)
>  {
>         struct wilco_ec_device *ec = platform_get_drvdata(pdev);
>
> +       platform_device_unregister(ec->adv_power_pdev);
>         platform_device_unregister(ec->rtc_pdev);
>         if (ec->debugfs_pdev)
>                 platform_device_unregister(ec->debugfs_pdev);
> diff --git a/include/linux/platform_data/wilco-ec.h b/include/linux/platform_data/wilco-ec.h
> index 446473a46b88..84e9aacd3759 100644
> --- a/include/linux/platform_data/wilco-ec.h
> +++ b/include/linux/platform_data/wilco-ec.h
> @@ -36,6 +36,7 @@
>   * @data_size: Size of the data buffer used for EC communication.
>   * @debugfs_pdev: The child platform_device used by the debugfs sub-driver.
>   * @rtc_pdev: The child platform_device used by the RTC sub-driver.
> + * @adv_power_pdev: Child platform_device used by the advanced power sub-driver.
>   */
>  struct wilco_ec_device {
>         struct device *dev;
> @@ -47,6 +48,7 @@ struct wilco_ec_device {
>         size_t data_size;
>         struct platform_device *debugfs_pdev;
>         struct platform_device *rtc_pdev;
> +       struct platform_device *adv_power_pdev;
>  };
>
>  /**
> --
> 2.20.1
>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ