summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-02-23 15:03:05 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2023-02-23 15:03:05 -0800
commitc2c23dc7d5f866a8bec3db638fae7f63789303ac (patch)
tree6317ceec34644b5a176e83ee64553922a964796b
parent06e1a81c4806d0b7f75f9d742ebf410718244e03 (diff)
parent59c54c59974649b2e7bc92faae4a21e2b2408db2 (diff)
downloadlinux-c2c23dc7d5f866a8bec3db638fae7f63789303ac.tar.gz
linux-c2c23dc7d5f866a8bec3db638fae7f63789303ac.tar.bz2
linux-c2c23dc7d5f866a8bec3db638fae7f63789303ac.zip
Merge tag 'mfd-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones: "Core Framework: - Change MFD support status from Supported to Maintained New Drivers: - Add support for the Intel Platform Management Component Interface (PMCI) Removed Drivers: - HTC PASIC3 LED/DS1WM - Toshiba T7L66XB, TC6387XB and TC6393XB TMIO New Device Support: - Add support for N6000 Flash to Intel M10 BMC PMCI - Add support for Lenovo Yoga Tab 3 to Intel CHTWC PMIC New Functionality: - Provide Reset support to Syscon Fix-ups: - Explicitly provide missing include files - Pass platform type data/info via the SPI/I2C/DT registration strategy - Lots of DT documentation / adaptions - Replace scnprintf() with preferred sysfs_emit() - Remove unused / superfluous code - Fix some trivial whitesspace / spelling / grammatical issues - Replace pm_power_off with new and improved register_sys_off_handler() API Bug Fixes: - Reintroduce RK808-clkout registration - fixing Wi-Fi and Bluetooth - Repair the order of AXPxxx IRQ PEK RISE/FALL definitions - Refuse to build CS5535 on unsupported UML architectures - Fix memory leaks in error return paths - Prevent refcount leaks in error return paths" * tag 'mfd-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (40 commits) dt-bindings: mfd: qcom,tcsr: Add compatible for IPQ5332 dt-bindings: mfd: Add NXP BBNSM mfd: ntxec: Add version number for EC in Tolino Vision dt-bindings: mfd: syscon: Add mt8365-syscfg mfd: Remove toshiba tmio drivers mfd: arizona: Use pm_runtime_resume_and_get() to prevent refcnt leak mfd: syscon: Allow reset control for syscon devices dt-bindings: mfd/syscon: Add resets property dt-bindings: mfd: syscon: Add amd,pensando-elba-syscon compatible dt-bindings: mfd: qcom,tcsr: Add compatible for MSM8226 mfd: simple-mfd-i2c: Fix incoherent comment regarding DT registration mfd: axp20x: Switch to the sys-off handler API mfd: core: Spelling s/compement/complement/ mfd: max8925: Remove the unused function irq_to_max8925() mfd: qcom-pm8xxx: Remove set but unused variable 'rev' dt-bindings: mfd: syscon: Document GXP register compatible mfd: twl4030-power: Drop empty platform remove function mfd: twl: Fix TWL6032 phy vbus detection mfd: pcf50633-adc: Fix potential memleak in pcf50633_adc_async_read() MAINTAINERS: Move MFD from a Supported to Maintaied state ...
-rw-r--r--Documentation/ABI/testing/sysfs-driver-intel-m10-bmc8
-rw-r--r--Documentation/devicetree/bindings/mfd/google,cros-ec.yaml20
-rw-r--r--Documentation/devicetree/bindings/mfd/nxp,bbnsm.yaml101
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml7
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/syscon.yaml6
-rw-r--r--MAINTAINERS4
-rw-r--r--drivers/extcon/extcon-intel-cht-wc.c1
-rw-r--r--drivers/fpga/Kconfig2
-rw-r--r--drivers/fpga/intel-m10-bmc-sec-update.c415
-rw-r--r--drivers/hwmon/Kconfig2
-rw-r--r--drivers/i2c/busses/i2c-cht-wc.c46
-rw-r--r--drivers/mfd/Kconfig33
-rw-r--r--drivers/mfd/Makefile5
-rw-r--r--drivers/mfd/arizona-core.c2
-rw-r--r--drivers/mfd/axp20x.c27
-rw-r--r--drivers/mfd/intel-m10-bmc-core.c122
-rw-r--r--drivers/mfd/intel-m10-bmc-pmci.c455
-rw-r--r--drivers/mfd/intel-m10-bmc-spi.c168
-rw-r--r--drivers/mfd/intel-m10-bmc.c238
-rw-r--r--drivers/mfd/intel_soc_pmic_chtwc.c8
-rw-r--r--drivers/mfd/kempld-core.c7
-rw-r--r--drivers/mfd/lm3533-core.c2
-rw-r--r--drivers/mfd/max8925-core.c6
-rw-r--r--drivers/mfd/ntxec.c1
-rw-r--r--drivers/mfd/pcf50633-adc.c7
-rw-r--r--drivers/mfd/qcom-pm8xxx.c3
-rw-r--r--drivers/mfd/rk808.c1
-rw-r--r--drivers/mfd/simple-mfd-i2c.c2
-rw-r--r--drivers/mfd/syscon.c27
-rw-r--r--drivers/mfd/twl-core.c9
-rw-r--r--drivers/mfd/twl4030-power.c6
-rw-r--r--include/linux/mfd/axp20x.h15
-rw-r--r--include/linux/mfd/core.h2
-rw-r--r--include/linux/mfd/intel-m10-bmc.h205
-rw-r--r--include/linux/mfd/intel_soc_pmic.h1
-rw-r--r--include/linux/mfd/ntxec.h2
-rw-r--r--include/linux/mfd/twl.h2
38 files changed, 1479 insertions, 491 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
index 9773925138af..a8ab58035c95 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
@@ -1,4 +1,4 @@
-What: /sys/bus/spi/devices/.../bmc_version
+What: /sys/bus/.../drivers/intel-m10-bmc/.../bmc_version
Date: June 2020
KernelVersion: 5.10
Contact: Xu Yilun <yilun.xu@intel.com>
@@ -6,7 +6,7 @@ Description: Read only. Returns the hardware build version of Intel
MAX10 BMC chip.
Format: "0x%x".
-What: /sys/bus/spi/devices/.../bmcfw_version
+What: /sys/bus/.../drivers/intel-m10-bmc/.../bmcfw_version
Date: June 2020
KernelVersion: 5.10
Contact: Xu Yilun <yilun.xu@intel.com>
@@ -14,7 +14,7 @@ Description: Read only. Returns the firmware version of Intel MAX10
BMC chip.
Format: "0x%x".
-What: /sys/bus/spi/devices/.../mac_address
+What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_address
Date: January 2021
KernelVersion: 5.12
Contact: Russ Weight <russell.h.weight@intel.com>
@@ -25,7 +25,7 @@ Description: Read only. Returns the first MAC address in a block
space.
Format: "%02x:%02x:%02x:%02x:%02x:%02x".
-What: /sys/bus/spi/devices/.../mac_count
+What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_count
Date: January 2021
KernelVersion: 5.12
Contact: Russ Weight <russell.h.weight@intel.com>
diff --git a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
index 3d5efa5578d1..cdf1d719efe9 100644
--- a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
+++ b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
@@ -33,6 +33,9 @@ properties:
- description:
For implementations of the EC connected through RPMSG.
const: google,cros-ec-rpmsg
+ - description:
+ For implementations of the EC connected through UART.
+ const: google,cros-ec-uart
controller-data: true
@@ -187,6 +190,15 @@ allOf:
properties:
mediatek,rpmsg-name: false
+ - if:
+ properties:
+ compatible:
+ not:
+ contains:
+ enum:
+ - google,cros-ec-rpmsg
+ - google,cros-ec-uart
+ then:
required:
- reg
- interrupts
@@ -299,4 +311,12 @@ examples:
vdd-supply = <&pp3300_fp_mcu>;
};
};
+
+ # Example for UART
+ - |
+ serial {
+ cros-ec {
+ compatible = "google,cros-ec-uart";
+ };
+ };
...
diff --git a/Documentation/devicetree/bindings/mfd/nxp,bbnsm.yaml b/Documentation/devicetree/bindings/mfd/nxp,bbnsm.yaml
new file mode 100644
index 000000000000..b1ade64a1554
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/nxp,bbnsm.yaml
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/nxp,bbnsm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP Battery-Backed Non-Secure Module
+
+maintainers:
+ - Jacky Bai <ping.bai@nxp.com>
+
+description: |
+ NXP BBNSM serves as non-volatile logic and storage for the system.
+ it Intergrates RTC & ON/OFF control.
+ The RTC can retain its state and continues counting even when the
+ main chip is power down. A time alarm is generated once the most
+ significant 32 bits of the real-time counter match the value in the
+ Time Alarm register.
+ The ON/OFF logic inside the BBNSM allows for connecting directly to
+ a PMIC or other voltage regulator device. both smart PMIC mode and
+ Dumb PMIC mode supported.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - nxp,imx93-bbnsm
+ - const: syscon
+ - const: simple-mfd
+
+ reg:
+ maxItems: 1
+
+ rtc:
+ type: object
+ $ref: /schemas/rtc/rtc.yaml#
+
+ properties:
+ compatible:
+ enum:
+ - nxp,imx93-bbnsm-rtc
+
+ interrupts:
+ maxItems: 1
+
+ start-year: true
+
+ required:
+ - compatible
+ - interrupts
+
+ additionalProperties: false
+
+ pwrkey:
+ type: object
+ $ref: /schemas/input/input.yaml#
+
+ properties:
+ compatible:
+ enum:
+ - nxp,imx93-bbnsm-pwrkey
+
+ interrupts:
+ maxItems: 1
+
+ linux,code: true
+
+ required:
+ - compatible
+ - interrupts
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - rtc
+ - pwrkey
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/input/linux-event-codes.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ bbnsm: bbnsm@44440000 {
+ compatible = "nxp,imx93-bbnsm", "syscon", "simple-mfd";
+ reg = <0x44440000 0x10000>;
+
+ bbnsm_rtc: rtc {
+ compatible = "nxp,imx93-bbnsm-rtc";
+ interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ bbnsm_pwrkey: pwrkey {
+ compatible = "nxp,imx93-bbnsm-pwrkey";
+ interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ linux,code = <KEY_POWER>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
index 37d16e16f444..adf88245c409 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
@@ -44,6 +44,7 @@ properties:
- qcom,pm8004
- qcom,pm8005
- qcom,pm8009
+ - qcom,pm8010
- qcom,pm8019
- qcom,pm8028
- qcom,pm8110
@@ -55,6 +56,10 @@ properties:
- qcom,pm8350
- qcom,pm8350b
- qcom,pm8350c
+ - qcom,pm8550
+ - qcom,pm8550b
+ - qcom,pm8550ve
+ - qcom,pm8550vs
- qcom,pm8841
- qcom,pm8909
- qcom,pm8916
@@ -71,10 +76,12 @@ properties:
- qcom,pmi8998
- qcom,pmk8002
- qcom,pmk8350
+ - qcom,pmk8550
- qcom,pmm8155au
- qcom,pmp8074
- qcom,pmr735a
- qcom,pmr735b
+ - qcom,pmr735d
- qcom,pms405
- qcom,pmx55
- qcom,pmx65
diff --git a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
index adcae6c007d9..2eeebe920e6e 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
@@ -28,9 +28,11 @@ properties:
- qcom,sm8150-tcsr
- qcom,tcsr-apq8064
- qcom,tcsr-apq8084
+ - qcom,tcsr-ipq5332
- qcom,tcsr-ipq6018
- qcom,tcsr-ipq8064
- qcom,tcsr-mdm9615
+ - qcom,tcsr-msm8226
- qcom,tcsr-msm8660
- qcom,tcsr-msm8916
- qcom,tcsr-msm8953
diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index b73ba1ea08f7..c828c4f5e4a7 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -38,6 +38,7 @@ properties:
- allwinner,sun8i-h3-system-controller
- allwinner,sun8i-v3s-system-controller
- allwinner,sun50i-a64-system-controller
+ - amd,pensando-elba-syscon
- brcm,cru-clkset
- freecom,fsg-cs2-system-controller
- fsl,imx93-aonmix-ns-syscfg
@@ -46,10 +47,12 @@ properties:
- hisilicon,hi6220-sramctrl
- hisilicon,pcie-sas-subctrl
- hisilicon,peri-subctrl
+ - hpe,gxp-sysreg
- intel,lgm-syscon
- marvell,armada-3700-usb2-host-misc
- mediatek,mt8135-pctl-a-syscfg
- mediatek,mt8135-pctl-b-syscfg
+ - mediatek,mt8365-syscfg
- microchip,lan966x-cpu-syscon
- microchip,sparx5-cpu-syscon
- mstar,msc313-pmsleep
@@ -81,6 +84,9 @@ properties:
on the device.
enum: [1, 2, 4, 8]
+ resets:
+ maxItems: 1
+
hwlocks:
maxItems: 1
description:
diff --git a/MAINTAINERS b/MAINTAINERS
index c25be6c6041a..7fb2b9c367ea 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10458,7 +10458,7 @@ S: Maintained
F: Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
F: Documentation/hwmon/intel-m10-bmc-hwmon.rst
F: drivers/hwmon/intel-m10-bmc-hwmon.c
-F: drivers/mfd/intel-m10-bmc.c
+F: drivers/mfd/intel-m10-bmc*
F: include/linux/mfd/intel-m10-bmc.h
INTEL MENLOW THERMAL DRIVER
@@ -14181,7 +14181,7 @@ F: drivers/media/i2c/mt9v111.c
MULTIFUNCTION DEVICES (MFD)
M: Lee Jones <lee@kernel.org>
-S: Supported
+S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
F: Documentation/devicetree/bindings/mfd/
F: drivers/mfd/
diff --git a/drivers/extcon/extcon-intel-cht-wc.c b/drivers/extcon/extcon-intel-cht-wc.c
index 89a6449e3f4a..2c55f06ba699 100644
--- a/drivers/extcon/extcon-intel-cht-wc.c
+++ b/drivers/extcon/extcon-intel-cht-wc.c
@@ -537,6 +537,7 @@ static int cht_wc_extcon_probe(struct platform_device *pdev)
cht_wc_extcon_set_5v_boost(ext, false);
break;
case INTEL_CHT_WC_LENOVO_YOGABOOK1:
+ case INTEL_CHT_WC_LENOVO_YT3_X90:
/* Do this first, as it may very well return -EPROBE_DEFER. */
ret = cht_wc_extcon_get_role_sw_and_regulator(ext);
if (ret)
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 6ce143dafd04..0a00763b9f28 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -246,7 +246,7 @@ config FPGA_MGR_VERSAL_FPGA
config FPGA_M10_BMC_SEC_UPDATE
tristate "Intel MAX10 BMC Secure Update driver"
- depends on MFD_INTEL_M10_BMC
+ depends on MFD_INTEL_M10_BMC_CORE
select FW_LOADER
select FW_UPLOAD
help
diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c b/drivers/fpga/intel-m10-bmc-sec-update.c
index 03f1bd81c434..f0acedc80182 100644
--- a/drivers/fpga/intel-m10-bmc-sec-update.c
+++ b/drivers/fpga/intel-m10-bmc-sec-update.c
@@ -14,6 +14,12 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
+struct m10bmc_sec;
+
+struct m10bmc_sec_ops {
+ int (*rsu_status)(struct m10bmc_sec *sec);
+};
+
struct m10bmc_sec {
struct device *dev;
struct intel_m10bmc *m10bmc;
@@ -21,6 +27,7 @@ struct m10bmc_sec {
char *fw_name;
u32 fw_name_id;
bool cancel_request;
+ const struct m10bmc_sec_ops *ops;
};
static DEFINE_XARRAY_ALLOC(fw_upload_xa);
@@ -31,6 +38,71 @@ static DEFINE_XARRAY_ALLOC(fw_upload_xa);
#define REH_MAGIC GENMASK(15, 0)
#define REH_SHA_NUM_BYTES GENMASK(31, 16)
+static int m10bmc_sec_write(struct m10bmc_sec *sec, const u8 *buf, u32 offset, u32 size)
+{
+ struct intel_m10bmc *m10bmc = sec->m10bmc;
+ unsigned int stride = regmap_get_reg_stride(m10bmc->regmap);
+ u32 write_count = size / stride;
+ u32 leftover_offset = write_count * stride;
+ u32 leftover_size = size - leftover_offset;
+ u32 leftover_tmp = 0;
+ int ret;
+
+ if (sec->m10bmc->flash_bulk_ops)
+ return sec->m10bmc->flash_bulk_ops->write(m10bmc, buf, offset, size);
+
+ if (WARN_ON_ONCE(stride > sizeof(leftover_tmp)))
+ return -EINVAL;
+
+ ret = regmap_bulk_write(m10bmc->regmap, M10BMC_STAGING_BASE + offset,
+ buf + offset, write_count);
+ if (ret)
+ return ret;
+
+ /* If size is not aligned to stride, handle the remainder bytes with regmap_write() */
+ if (leftover_size) {
+ memcpy(&leftover_tmp, buf + leftover_offset, leftover_size);
+ ret = regmap_write(m10bmc->regmap, M10BMC_STAGING_BASE + offset + leftover_offset,
+ leftover_tmp);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int m10bmc_sec_read(struct m10bmc_sec *sec, u8 *buf, u32 addr, u32 size)
+{
+ struct intel_m10bmc *m10bmc = sec->m10bmc;
+ unsigned int stride = regmap_get_reg_stride(m10bmc->regmap);
+ u32 read_count = size / stride;
+ u32 leftover_offset = read_count * stride;
+ u32 leftover_size = size - leftover_offset;
+ u32 leftover_tmp;
+ int ret;
+
+ if (sec->m10bmc->flash_bulk_ops)
+ return sec->m10bmc->flash_bulk_ops->read(m10bmc, buf, addr, size);
+
+ if (WARN_ON_ONCE(stride > sizeof(leftover_tmp)))
+ return -EINVAL;
+
+ ret = regmap_bulk_read(m10bmc->regmap, addr, buf, read_count);
+ if (ret)
+ return ret;
+
+ /* If size is not aligned to stride, handle the remainder bytes with regmap_read() */
+ if (leftover_size) {
+ ret = regmap_read(m10bmc->regmap, addr + leftover_offset, &leftover_tmp);
+ if (ret)
+ return ret;
+ memcpy(buf + leftover_offset, &leftover_tmp, leftover_size);
+ }
+
+ return 0;
+}
+
+
static ssize_t
show_root_entry_hash(struct device *dev, u32 exp_magic,
u32 prog_addr, u32 reh_addr, char *buf)
@@ -38,11 +110,9 @@ show_root_entry_hash(struct device *dev, u32 exp_magic,
struct m10bmc_sec *sec = dev_get_drvdata(dev);
int sha_num_bytes, i, ret, cnt = 0;
u8 hash[REH_SHA384_SIZE];
- unsigned int stride;
u32 magic;
- stride = regmap_get_reg_stride(sec->m10bmc->regmap);
- ret = m10bmc_raw_read(sec->m10bmc, prog_addr, &magic);
+ ret = m10bmc_sec_read(sec, (u8 *)&magic, prog_addr, sizeof(magic));
if (ret)
return ret;
@@ -50,19 +120,16 @@ show_root_entry_hash(struct device *dev, u32 exp_magic,
return sysfs_emit(buf, "hash not programmed\n");
sha_num_bytes = FIELD_GET(REH_SHA_NUM_BYTES, magic) / 8;
- if ((sha_num_bytes % stride) ||
- (sha_num_bytes != REH_SHA256_SIZE &&
- sha_num_bytes != REH_SHA384_SIZE)) {
+ if (sha_num_bytes != REH_SHA256_SIZE &&
+ sha_num_bytes != REH_SHA384_SIZE) {
dev_err(sec->dev, "%s bad sha num bytes %d\n", __func__,
sha_num_bytes);
return -EINVAL;
}
- ret = regmap_bulk_read(sec->m10bmc->regmap, reh_addr,
- hash, sha_num_bytes / stride);
+ ret = m10bmc_sec_read(sec, hash, reh_addr, sha_num_bytes);
if (ret) {
- dev_err(dev, "failed to read root entry hash: %x cnt %x: %d\n",
- reh_addr, sha_num_bytes / stride, ret);
+ dev_err(dev, "failed to read root entry hash\n");
return ret;
}
@@ -73,16 +140,24 @@ show_root_entry_hash(struct device *dev, u32 exp_magic,
return cnt;
}
-#define DEVICE_ATTR_SEC_REH_RO(_name, _magic, _prog_addr, _reh_addr) \
+#define DEVICE_ATTR_SEC_REH_RO(_name) \
static ssize_t _name##_root_entry_hash_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
-{ return show_root_entry_hash(dev, _magic, _prog_addr, _reh_addr, buf); } \
+{ \
+ struct m10bmc_sec *sec = dev_get_drvdata(dev); \
+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; \
+ \
+ return show_root_entry_hash(dev, csr_map->_name##_magic, \
+ csr_map->_name##_prog_addr, \
+ csr_map->_name##_reh_addr, \
+ buf); \
+} \
static DEVICE_ATTR_RO(_name##_root_entry_hash)
-DEVICE_ATTR_SEC_REH_RO(bmc, BMC_PROG_MAGIC, BMC_PROG_ADDR, BMC_REH_ADDR);
-DEVICE_ATTR_SEC_REH_RO(sr, SR_PROG_MAGIC, SR_PROG_ADDR, SR_REH_ADDR);
-DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR);
+DEVICE_ATTR_SEC_REH_RO(bmc);
+DEVICE_ATTR_SEC_REH_RO(sr);
+DEVICE_ATTR_SEC_REH_RO(pr);
#define CSK_BIT_LEN 128U
#define CSK_32ARRAY_SIZE DIV_ROUND_UP(CSK_BIT_LEN, 32)
@@ -90,27 +165,16 @@ DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR);
static ssize_t
show_canceled_csk(struct device *dev, u32 addr, char *buf)
{
- unsigned int i, stride, size = CSK_32ARRAY_SIZE * sizeof(u32);
+ unsigned int i, size = CSK_32ARRAY_SIZE * sizeof(u32);
struct m10bmc_sec *sec = dev_get_drvdata(dev);
DECLARE_BITMAP(csk_map, CSK_BIT_LEN);
__le32 csk_le32[CSK_32ARRAY_SIZE];
u32 csk32[CSK_32ARRAY_SIZE];
int ret;
- stride = regmap_get_reg_stride(sec->m10bmc->regmap);
- if (size % stride) {
- dev_err(sec->dev,
- "CSK vector size (0x%x) not aligned to stride (0x%x)\n",
- size, stride);
- WARN_ON_ONCE(1);
- return -EINVAL;
- }
-
- ret = regmap_bulk_read(sec->m10bmc->regmap, addr, csk_le32,
- size / stride);
+ ret = m10bmc_sec_read(sec, (u8 *)&csk_le32, addr, size);
if (ret) {
- dev_err(sec->dev, "failed to read CSK vector: %x cnt %x: %d\n",
- addr, size / stride, ret);
+ dev_err(sec->dev, "failed to read CSK vector\n");
return ret;
}
@@ -122,18 +186,25 @@ show_canceled_csk(struct device *dev, u32 addr, char *buf)
return bitmap_print_to_pagebuf(1, buf, csk_map, CSK_BIT_LEN);
}
-#define DEVICE_ATTR_SEC_CSK_RO(_name, _addr) \
+#define DEVICE_ATTR_SEC_CSK_RO(_name) \
static ssize_t _name##_canceled_csks_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
-{ return show_canceled_csk(dev, _addr, buf); } \
+{ \
+ struct m10bmc_sec *sec = dev_get_drvdata(dev); \
+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; \
+ \
+ return show_canceled_csk(dev, \
+ csr_map->_name##_prog_addr + CSK_VEC_OFFSET, \
+ buf); \
+} \
static DEVICE_ATTR_RO(_name##_canceled_csks)
#define CSK_VEC_OFFSET 0x34
-DEVICE_ATTR_SEC_CSK_RO(bmc, BMC_PROG_ADDR + CSK_VEC_OFFSET);
-DEVICE_ATTR_SEC_CSK_RO(sr, SR_PROG_ADDR + CSK_VEC_OFFSET);
-DEVICE_ATTR_SEC_CSK_RO(pr, PR_PROG_ADDR + CSK_VEC_OFFSET);
+DEVICE_ATTR_SEC_CSK_RO(bmc);
+DEVICE_ATTR_SEC_CSK_RO(sr);
+DEVICE_ATTR_SEC_CSK_RO(pr);
#define FLASH_COUNT_SIZE 4096 /* count stored as inverted bit vector */
@@ -141,31 +212,21 @@ static ssize_t flash_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct m10bmc_sec *sec = dev_get_drvdata(dev);
- unsigned int stride, num_bits;
+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
+ unsigned int num_bits;
u8 *flash_buf;
int cnt, ret;
- stride = regmap_get_reg_stride(sec->m10bmc->regmap);
num_bits = FLASH_COUNT_SIZE * 8;
- if (FLASH_COUNT_SIZE % stride) {
- dev_err(sec->dev,
- "FLASH_COUNT_SIZE (0x%x) not aligned to stride (0x%x)\n",
- FLASH_COUNT_SIZE, stride);
- WARN_ON_ONCE(1);
- return -EINVAL;
- }
-
flash_buf = kmalloc(FLASH_COUNT_SIZE, GFP_KERNEL);
if (!flash_buf)
return -ENOMEM;
- ret = regmap_bulk_read(sec->m10bmc->regmap, STAGING_FLASH_COUNT,
- flash_buf, FLASH_COUNT_SIZE / stride);
+ ret = m10bmc_sec_read(sec, flash_buf, csr_map->rsu_update_counter,
+ FLASH_COUNT_SIZE);
if (ret) {
- dev_err(sec->dev,
- "failed to read flash count: %x cnt %x: %d\n",
- STAGING_FLASH_COUNT, FLASH_COUNT_SIZE / stride, ret);
+ dev_err(sec->dev, "failed to read flash count\n");
goto exit_free;
}
cnt = num_bits - bitmap_weight((unsigned long *)flash_buf, num_bits);
@@ -200,25 +261,94 @@ static const struct attribute_group *m10bmc_sec_attr_groups[] = {
static void log_error_regs(struct m10bmc_sec *sec, u32 doorbell)
{
+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
u32 auth_result;
- dev_err(sec->dev, "RSU error status: 0x%08x\n", doorbell);
+ dev_err(sec->dev, "Doorbell: 0x%08x\n", doorbell);
- if (!m10bmc_sys_read(sec->m10bmc, M10BMC_AUTH_RESULT, &auth_result))
+ if (!m10bmc_sys_read(sec->m10bmc, csr_map->auth_result, &auth_result))
dev_err(sec->dev, "RSU auth result: 0x%08x\n", auth_result);
}
+static int m10bmc_sec_n3000_rsu_status(struct m10bmc_sec *sec)
+{
+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
+ u32 doorbell;
+ int ret;
+
+ ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell);
+ if (ret)
+ return ret;
+
+ return FIELD_GET(DRBL_RSU_STATUS, doorbell);
+}
+
+static int m10bmc_sec_n6000_rsu_status(struct m10bmc_sec *sec)
+{
+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
+ u32 auth_result;
+ int ret;
+
+ ret = m10bmc_sys_read(sec->m10bmc, csr_map->auth_result, &auth_result);
+ if (ret)
+ return ret;
+
+ return FIELD_GET(AUTH_RESULT_RSU_STATUS, auth_result);
+}
+
+static bool rsu_status_ok(u32 status)
+{
+ return (status == RSU_STAT_NORMAL ||
+ status == RSU_STAT_NIOS_OK ||
+ status == RSU_STAT_USER_OK ||
+ status == RSU_STAT_FACTORY_OK);
+}
+
+static bool rsu_progress_done(u32 progress)
+{
+ return (progress == RSU_PROG_IDLE ||
+ progress == RSU_PROG_RSU_DONE);
+}
+
+static bool rsu_progress_busy(u32 progress)
+{
+ return (progress == RSU_PROG_AUTHENTICATING ||
+ progress == RSU_PROG_COPYING ||
+ progress == RSU_PROG_UPDATE_CANCEL ||
+ progress == RSU_PROG_PROGRAM_KEY_HASH);
+}
+
+static int m10bmc_sec_progress_status(struct m10bmc_sec *sec, u32 *doorbell_reg,
+ u32 *progress, u32 *status)
+{
+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
+ int ret;
+
+ ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, doorbell_reg);
+ if (ret)
+ return ret;
+
+ ret = sec->ops->rsu_status(sec);
+ if (ret < 0)
+ return ret;
+
+ *status = ret;
+ *progress = rsu_prog(*doorbell_reg);
+
+ return 0;
+}
+
static enum fw_upload_err rsu_check_idle(struct m10bmc_sec *sec)
{
+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
u32 doorbell;
int ret;
- ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell);
+ ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell);
if (ret)
return FW_UPLOAD_ERR_RW_ERROR;
- if (rsu_prog(doorbell) != RSU_PROG_IDLE &&
- rsu_prog(doorbell) != RSU_PROG_RSU_DONE) {
+ if (!rsu_progress_done(rsu_prog(doorbell))) {
log_error_regs(sec, doorbell);
return FW_UPLOAD_ERR_BUSY;
}
@@ -226,19 +356,15 @@ static enum fw_upload_err rsu_check_idle(struct m10bmc_sec *sec)
return FW_UPLOAD_ERR_NONE;
}
-static inline bool rsu_start_done(u32 doorbell)
+static inline bool rsu_start_done(u32 doorbell_reg, u32 progress, u32 status)
{
- u32 status, progress;
-
- if (doorbell & DRBL_RSU_REQUEST)
+ if (doorbell_reg & DRBL_RSU_REQUEST)
return false;
- status = rsu_stat(doorbell);
if (status == RSU_STAT_ERASE_FAIL || status == RSU_STAT_WEAROUT)
return true;
- progress = rsu_prog(doorbell);
- if (progress != RSU_PROG_IDLE && progress != RSU_PROG_RSU_DONE)
+ if (!rsu_progress_done(progress))
return true;
return false;