diff options
Diffstat (limited to 'target/linux/bcm27xx/patches-5.10/950-0622-Add-Raspberry-Pi-PoE-HAT-support.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.10/950-0622-Add-Raspberry-Pi-PoE-HAT-support.patch | 394 |
1 files changed, 0 insertions, 394 deletions
diff --git a/target/linux/bcm27xx/patches-5.10/950-0622-Add-Raspberry-Pi-PoE-HAT-support.patch b/target/linux/bcm27xx/patches-5.10/950-0622-Add-Raspberry-Pi-PoE-HAT-support.patch deleted file mode 100644 index 121914c6a6..0000000000 --- a/target/linux/bcm27xx/patches-5.10/950-0622-Add-Raspberry-Pi-PoE-HAT-support.patch +++ /dev/null @@ -1,394 +0,0 @@ -From 2150bf813a64c18cdc56ae6b84036377c242cebd Mon Sep 17 00:00:00 2001 -From: Serge Schneider <serge@raspberrypi.com> -Date: Mon, 2 Dec 2019 14:48:05 +0000 -Subject: [PATCH] Add Raspberry Pi PoE+ HAT support - -Signed-off-by: Serge Schneider <serge@raspberrypi.com> ---- - drivers/hwmon/rpi-poe-fan.c | 35 +++- - drivers/power/supply/Kconfig | 6 + - drivers/power/supply/Makefile | 1 + - drivers/power/supply/rpi_poe_power.c | 227 +++++++++++++++++++++ - include/soc/bcm2835/raspberrypi-firmware.h | 3 +- - 5 files changed, 261 insertions(+), 11 deletions(-) - create mode 100644 drivers/power/supply/rpi_poe_power.c - ---- a/drivers/hwmon/rpi-poe-fan.c -+++ b/drivers/hwmon/rpi-poe-fan.c -@@ -28,6 +28,7 @@ - struct rpi_poe_fan_ctx { - struct mutex lock; - struct rpi_firmware *fw; -+ u32 set_tag; - unsigned int pwm_value; - unsigned int def_pwm_value; - unsigned int rpi_poe_fan_state; -@@ -43,13 +44,15 @@ struct fw_tag_data_s{ - u32 ret; - }; - --static int write_reg(struct rpi_firmware *fw, u32 reg, u32 *val){ -+static int write_reg(struct rpi_firmware *fw, u32 reg, u32 *val, u32 set_tag) -+{ - struct fw_tag_data_s fw_tag_data = { - .reg = reg, - .val = *val - }; - int ret; -- ret = rpi_firmware_property(fw, RPI_FIRMWARE_SET_POE_HAT_VAL, -+ -+ ret = rpi_firmware_property(fw, set_tag, - &fw_tag_data, sizeof(fw_tag_data)); - if (ret) { - return ret; -@@ -82,7 +85,7 @@ static int rpi_poe_reboot(struct notifie - nb); - - if (ctx->pwm_value != ctx->def_pwm_value) -- write_reg(ctx->fw, POE_CUR_PWM, &ctx->def_pwm_value); -+ write_reg(ctx->fw, POE_CUR_PWM, &ctx->def_pwm_value, ctx->set_tag); - - return NOTIFY_DONE; - } -@@ -95,7 +98,7 @@ static int __set_pwm(struct rpi_poe_fan - if (ctx->pwm_value == pwm) - goto exit_set_pwm_err; - -- ret = write_reg(ctx->fw, POE_CUR_PWM, &pwm); -+ ret = write_reg(ctx->fw, POE_CUR_PWM, &pwm, ctx->set_tag); - if (!ret) - ctx->pwm_value = pwm; - exit_set_pwm_err: -@@ -110,7 +113,7 @@ static int __set_def_pwm(struct rpi_poe - if (ctx->def_pwm_value == def_pwm) - goto exit_set_def_pwm_err; - -- ret = write_reg(ctx->fw, POE_DEF_PWM, &def_pwm); -+ ret = write_reg(ctx->fw, POE_DEF_PWM, &def_pwm, ctx->set_tag); - if (!ret) - ctx->def_pwm_value = def_pwm; - exit_set_def_pwm_err: -@@ -297,6 +300,7 @@ static int rpi_poe_fan_probe(struct plat - struct device *hwmon; - struct device_node *np = pdev->dev.of_node; - struct device_node *fw_node; -+ u32 revision; - int ret; - - fw_node = of_parse_phandle(np, "firmware", 0); -@@ -314,6 +318,17 @@ static int rpi_poe_fan_probe(struct plat - ctx->fw = rpi_firmware_get(fw_node); - if (!ctx->fw) - return -EPROBE_DEFER; -+ ret = rpi_firmware_property(ctx->fw, -+ RPI_FIRMWARE_GET_FIRMWARE_REVISION, -+ &revision, sizeof(revision)); -+ if (ret) { -+ dev_err(&pdev->dev, "Failed to get firmware revision: %i\n", ret); -+ return ret; -+ } -+ if (revision < 0x60af72e8) -+ ctx->set_tag = RPI_FIRMWARE_SET_POE_HAT_VAL_OLD; -+ else -+ ctx->set_tag = RPI_FIRMWARE_SET_POE_HAT_VAL; - - platform_set_drvdata(pdev, ctx); - -@@ -378,9 +393,9 @@ static int rpi_poe_fan_remove(struct pla - - unregister_reboot_notifier(&ctx->nb); - thermal_cooling_device_unregister(ctx->cdev); -- if (ctx->pwm_value != value) { -- write_reg(ctx->fw, POE_CUR_PWM, &value); -- } -+ if (ctx->pwm_value != value) -+ write_reg(ctx->fw, POE_CUR_PWM, &value, ctx->set_tag); -+ - return 0; - } - -@@ -392,7 +407,7 @@ static int rpi_poe_fan_suspend(struct de - int ret = 0; - - if (ctx->pwm_value != value) -- ret = write_reg(ctx->fw, POE_CUR_PWM, &value); -+ ret = write_reg(ctx->fw, POE_CUR_PWM, &value, ctx->set_tag); - return ret; - } - -@@ -403,7 +418,7 @@ static int rpi_poe_fan_resume(struct dev - int ret = 0; - - if (value != 0) -- ret = write_reg(ctx->fw, POE_CUR_PWM, &value); -+ ret = write_reg(ctx->fw, POE_CUR_PWM, &value, ctx->set_tag); - - return ret; - } ---- a/drivers/power/supply/Kconfig -+++ b/drivers/power/supply/Kconfig -@@ -28,6 +28,12 @@ config POWER_SUPPLY_HWMON - Say 'Y' here if you want power supplies to - have hwmon sysfs interface too. - -+config RPI_POE_POWER -+ tristate "Raspberry Pi PoE+ HAT power supply driver" -+ depends on RASPBERRYPI_FIRMWARE -+ help -+ Say Y here to enable support for Raspberry Pi PoE+ (Power over Ethernet -+ Plus) HAT current measurement. - - config PDA_POWER - tristate "Generic PDA/phone power driver" ---- a/drivers/power/supply/Makefile -+++ b/drivers/power/supply/Makefile -@@ -9,6 +9,7 @@ obj-$(CONFIG_POWER_SUPPLY) += power_supp - obj-$(CONFIG_POWER_SUPPLY_HWMON) += power_supply_hwmon.o - obj-$(CONFIG_GENERIC_ADC_BATTERY) += generic-adc-battery.o - -+obj-$(CONFIG_RPI_POE_POWER) += rpi_poe_power.o - obj-$(CONFIG_PDA_POWER) += pda_power.o - obj-$(CONFIG_APM_POWER) += apm_power.o - obj-$(CONFIG_AXP20X_POWER) += axp20x_usb_power.o ---- /dev/null -+++ b/drivers/power/supply/rpi_poe_power.c -@@ -0,0 +1,227 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * rpi-poe-power.c - Raspberry Pi PoE+ HAT power supply driver. -+ * -+ * Copyright (C) 2019 Raspberry Pi (Trading) Ltd. -+ * Based on axp20x_ac_power.c by Quentin Schulz <quentin.schulz@free-electrons.com> -+ * -+ * Author: Serge Schneider <serge@raspberrypi.org> -+ */ -+ -+#include <linux/module.h> -+#include <linux/of.h> -+#include <linux/platform_device.h> -+#include <linux/power_supply.h> -+#include <soc/bcm2835/raspberrypi-firmware.h> -+ -+#define RPI_POE_ADC_REG 0x2 -+#define RPI_POE_FLAG_REG 0x4 -+ -+#define RPI_POE_FLAG_AT BIT(0) -+#define RPI_POE_FLAG_OC BIT(1) -+ -+#define RPI_POE_CURRENT_AF_MAX (2500 * 1000) -+#define RPI_POE_CURRENT_AT_MAX (5000 * 1000) -+ -+#define DRVNAME "rpi-poe-power-supply" -+ -+struct rpi_poe_power_supply_ctx { -+ struct power_supply *supply; -+ struct rpi_firmware *fw; -+}; -+ -+struct fw_tag_data_s { -+ u32 reg; -+ u32 val; -+ u32 ret; -+}; -+ -+static int write_reg(struct rpi_firmware *fw, u32 reg, u32 *val) -+{ -+ struct fw_tag_data_s fw_tag_data = { -+ .reg = reg, -+ .val = *val -+ }; -+ int ret; -+ -+ ret = rpi_firmware_property(fw, RPI_FIRMWARE_SET_POE_HAT_VAL, -+ &fw_tag_data, sizeof(fw_tag_data)); -+ if (ret) -+ return ret; -+ else if (fw_tag_data.ret) -+ return -EIO; -+ return 0; -+} -+ -+static int read_reg(struct rpi_firmware *fw, u32 reg, u32 *val) -+{ -+ struct fw_tag_data_s fw_tag_data = { -+ .reg = reg, -+ .val = *val -+ }; -+ int ret; -+ -+ ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_POE_HAT_VAL, -+ &fw_tag_data, sizeof(fw_tag_data)); -+ if (ret) -+ return ret; -+ else if (fw_tag_data.ret) -+ return -EIO; -+ -+ *val = fw_tag_data.val; -+ return 0; -+} -+ -+static int rpi_poe_power_supply_get_property(struct power_supply *psy, -+ enum power_supply_property psp, -+ union power_supply_propval *r_val) -+{ -+ struct rpi_poe_power_supply_ctx *ctx = power_supply_get_drvdata(psy); -+ int ret; -+ unsigned int val = 0; -+ -+ switch (psp) { -+ case POWER_SUPPLY_PROP_HEALTH: -+ ret = read_reg(ctx->fw, RPI_POE_FLAG_REG, &val); -+ if (ret) -+ return ret; -+ -+ if (val & RPI_POE_FLAG_OC) { -+ r_val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; -+ val = RPI_POE_FLAG_OC; -+ ret = write_reg(ctx->fw, RPI_POE_FLAG_REG, &val); -+ if (ret) -+ return ret; -+ return 0; -+ } -+ -+ r_val->intval = POWER_SUPPLY_HEALTH_GOOD; -+ return 0; -+ -+ case POWER_SUPPLY_PROP_ONLINE: -+ ret = read_reg(ctx->fw, RPI_POE_ADC_REG, &val); -+ if (ret) -+ return ret; -+ -+ r_val->intval = (val > 5); -+ return 0; -+ -+ case POWER_SUPPLY_PROP_CURRENT_AVG: -+ val = 50; -+ ret = read_reg(ctx->fw, RPI_POE_ADC_REG, &val); -+ if (ret) -+ return ret; -+ val = (val * 3300)/9821; -+ r_val->intval = val * 1000; -+ return 0; -+ -+ case POWER_SUPPLY_PROP_CURRENT_NOW: -+ ret = read_reg(ctx->fw, RPI_POE_ADC_REG, &val); -+ if (ret) -+ return ret; -+ val = (val * 3300)/9821; -+ r_val->intval = val * 1000; -+ return 0; -+ -+ case POWER_SUPPLY_PROP_CURRENT_MAX: -+ ret = read_reg(ctx->fw, RPI_POE_FLAG_REG, &val); -+ if (ret) -+ return ret; -+ -+ if (val & RPI_POE_FLAG_AT) { -+ r_val->intval = RPI_POE_CURRENT_AT_MAX; -+ return 0; -+ } -+ r_val->intval = RPI_POE_CURRENT_AF_MAX; -+ return 0; -+ -+ default: -+ return -EINVAL; -+ } -+ -+ return -EINVAL; -+} -+ -+static enum power_supply_property rpi_poe_power_supply_properties[] = { -+ POWER_SUPPLY_PROP_HEALTH, -+ POWER_SUPPLY_PROP_ONLINE, -+ POWER_SUPPLY_PROP_CURRENT_AVG, -+ POWER_SUPPLY_PROP_CURRENT_NOW, -+ POWER_SUPPLY_PROP_CURRENT_MAX, -+}; -+ -+static const struct power_supply_desc rpi_poe_power_supply_desc = { -+ .name = "rpi-poe", -+ .type = POWER_SUPPLY_TYPE_MAINS, -+ .properties = rpi_poe_power_supply_properties, -+ .num_properties = ARRAY_SIZE(rpi_poe_power_supply_properties), -+ .get_property = rpi_poe_power_supply_get_property, -+}; -+ -+static int rpi_poe_power_supply_probe(struct platform_device *pdev) -+{ -+ struct power_supply_config psy_cfg = {}; -+ struct rpi_poe_power_supply_ctx *ctx; -+ struct device_node *fw_node; -+ u32 revision; -+ -+ if (!of_device_is_available(pdev->dev.of_node)) -+ return -ENODEV; -+ -+ fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); -+ if (!fw_node) { -+ dev_err(&pdev->dev, "Missing firmware node\n"); -+ return -ENOENT; -+ } -+ -+ ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); -+ if (!ctx) -+ return -ENOMEM; -+ -+ ctx->fw = rpi_firmware_get(fw_node); -+ if (!ctx->fw) -+ return -EPROBE_DEFER; -+ if (rpi_firmware_property(ctx->fw, -+ RPI_FIRMWARE_GET_FIRMWARE_REVISION, -+ &revision, sizeof(revision))) { -+ dev_err(&pdev->dev, "Failed to get firmware revision\n"); -+ return -ENOENT; -+ } -+ if (revision < 0x60af72e8) { -+ dev_err(&pdev->dev, "Unsupported firmware\n"); -+ return -ENOENT; -+ } -+ platform_set_drvdata(pdev, ctx); -+ -+ psy_cfg.of_node = pdev->dev.of_node; -+ psy_cfg.drv_data = ctx; -+ -+ ctx->supply = devm_power_supply_register(&pdev->dev, -+ &rpi_poe_power_supply_desc, -+ &psy_cfg); -+ if (IS_ERR(ctx->supply)) -+ return PTR_ERR(ctx->supply); -+ -+ return 0; -+} -+ -+static const struct of_device_id of_rpi_poe_power_supply_match[] = { -+ { .compatible = "raspberrypi,rpi-poe-power-supply", }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, of_rpi_poe_power_supply_match); -+ -+static struct platform_driver rpi_poe_power_supply_driver = { -+ .probe = rpi_poe_power_supply_probe, -+ .driver = { -+ .name = DRVNAME, -+ .of_match_table = of_rpi_poe_power_supply_match -+ }, -+}; -+ -+module_platform_driver(rpi_poe_power_supply_driver); -+ -+MODULE_AUTHOR("Serge Schneider <serge@raspberrypi.org>"); -+MODULE_ALIAS("platform:" DRVNAME); -+MODULE_DESCRIPTION("Raspberry Pi PoE+ HAT power supply driver"); -+MODULE_LICENSE("GPL"); ---- a/include/soc/bcm2835/raspberrypi-firmware.h -+++ b/include/soc/bcm2835/raspberrypi-firmware.h -@@ -94,7 +94,8 @@ enum rpi_firmware_property_tag { - RPI_FIRMWARE_GET_PERIPH_REG = 0x00030045, - RPI_FIRMWARE_SET_PERIPH_REG = 0x00038045, - RPI_FIRMWARE_GET_POE_HAT_VAL = 0x00030049, -- RPI_FIRMWARE_SET_POE_HAT_VAL = 0x00030050, -+ RPI_FIRMWARE_SET_POE_HAT_VAL = 0x00038049, -+ RPI_FIRMWARE_SET_POE_HAT_VAL_OLD = 0x00030050, - RPI_FIRMWARE_NOTIFY_XHCI_RESET = 0x00030058, - RPI_FIRMWARE_GET_REBOOT_FLAGS = 0x00030064, - RPI_FIRMWARE_SET_REBOOT_FLAGS = 0x00038064, |