Re: [PATCH v8 2/4] SFH: PCIe driver to add support of AMD sensor fusion hub

From: Richard Neumann
Date: Thu Oct 22 2020 - 06:46:30 EST


Hi all,

on a quick glance, I noticed, that the sensor masks (*_EN) are no
longer derived from their indices:

amd_sfh_pcie.h:

enum sensor_idx {
accel_idx = 0,
gyro_idx = 1,
mag_idx = 2,
als_idx = 19
};

amd_sfh_pcie.c:

#define ACEL_EN BIT(1)
#define GYRO_EN BIT(2)
#define MAGNO_EN BIT(3)
#define ALS_EN BIT(19)

Why were all except ALS_EN shifted by one?
Is this intentional or a bug?

I have received an email by a user, suggesting that this change breaks
correct sensors detection when compared to activestatus. Can you
confirm this?

Also I wonder why the structures "enum desc_type", "struct
_hid_report_descriptor" and "struct _hid_device_descriptor" have been
introduced in amd_sfh_hid_desc.h as they aren't used anywhere in the
code.

Kind regards,

Richard

Am Samstag, den 10.10.2020, 01:31 +0530 schrieb Sandeep Singh:
> From: Sandeep Singh <sandeep.singh@xxxxxxx>
>
> AMD SFH (Sensor Fusion Hub) is a solution running on MP2
> (which is ARM core connected to x86 for processing sensor data).
> AMD SFH uses HID over PCI bus to form the HID descriptors and
> talks to HID clients like the monitor-sensor/iio-proxy. MP2 which
> is exposed as a PCI device to the x86, uses mailboxes to talk to
> MP2 firmware to send/receive commands.
>
> Co-developed-by: Nehal Shah <Nehal-bakulchandra.Shah@xxxxxxx>
> Signed-off-by: Nehal Shah <Nehal-bakulchandra.Shah@xxxxxxx>
> Signed-off-by: Sandeep Singh <sandeep.singh@xxxxxxx>
> ---
>  drivers/hid/Kconfig                    |   2 +
>  drivers/hid/Makefile                   |   2 +
>  drivers/hid/amd-sfh-hid/Kconfig        |  18 +++
>  drivers/hid/amd-sfh-hid/Makefile       |  13 +++
>  drivers/hid/amd-sfh-hid/amd_sfh_pcie.c | 152
> +++++++++++++++++++++++++
>  drivers/hid/amd-sfh-hid/amd_sfh_pcie.h |  79 +++++++++++++
>  6 files changed, 266 insertions(+)
>  create mode 100644 drivers/hid/amd-sfh-hid/Kconfig
>  create mode 100644 drivers/hid/amd-sfh-hid/Makefile
>  create mode 100644 drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
>  create mode 100644 drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 05315b434276..1b5f5e9b8d0d 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -1174,4 +1174,6 @@ source "drivers/hid/i2c-hid/Kconfig"
>  
>  source "drivers/hid/intel-ish-hid/Kconfig"
>  
> +source "drivers/hid/amd-sfh-hid/Kconfig"
> +
>  endmenu
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index d8ea4b8c95af..7d8ca4e34572 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -141,3 +141,5 @@ obj-$(CONFIG_I2C_HID)               += i2c-hid/
>  
>  obj-$(CONFIG_INTEL_ISH_HID)    += intel-ish-hid/
>  obj-$(INTEL_ISH_FIRMWARE_DOWNLOADER)   += intel-ish-hid/
> +
> +obj-$(CONFIG_AMD_SFH_HID)       += amd-sfh-hid/
> diff --git a/drivers/hid/amd-sfh-hid/Kconfig b/drivers/hid/amd-sfh-
> hid/Kconfig
> new file mode 100644
> index 000000000000..db069a83e9a2
> --- /dev/null
> +++ b/drivers/hid/amd-sfh-hid/Kconfig
> @@ -0,0 +1,18 @@
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +menu "AMD SFH HID Support"
> +       depends on X86_64 || COMPILE_TEST
> +       depends on PCI
> +       depends on HID
> +
> +config AMD_SFH_HID
> +       tristate "AMD Sensor Fusion Hub"
> +       help
> +         If you say yes to this option, support will be included for
> the
> +         AMD Sensor Fusion Hub.
> +         This driver will enable sensors functionality on AMD
> platforms
> +         starting from 17h family of RYZEN parts.
> +
> +         This driver can also be built as a module. If so, the
> module will
> +         be called amd-sfh.
> +         Say Y or M here if you want to support AMD SFH. If unsure,
> say N.
> +endmenu
> diff --git a/drivers/hid/amd-sfh-hid/Makefile b/drivers/hid/amd-sfh-
> hid/Makefile
> new file mode 100644
> index 000000000000..35e704da5612
> --- /dev/null
> +++ b/drivers/hid/amd-sfh-hid/Makefile
> @@ -0,0 +1,13 @@
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +#
> +# Makefile - AMD SFH HID drivers
> +# Copyright (c) 2019-2020, Advanced Micro Devices, Inc.
> +#
> +#
> +obj-$(CONFIG_AMD_SFH_HID) += amd_sfh.o
> +amd_sfh-objs := amd_sfh_hid.o
> +amd_sfh-objs += amd_sfh_client.o
> +amd_sfh-objs += amd_sfh_pcie.o
> +amd_sfh-objs += hid_descriptor/amd_sfh_hid_desc.o
> +
> +ccflags-y += -I $(srctree)/$(src)/
> diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
> b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
> new file mode 100644
> index 000000000000..9c5eb442e1a6
> --- /dev/null
> +++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
> @@ -0,0 +1,152 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * AMD MP2 PCIe communication driver
> + * Copyright 2020 Advanced Micro Devices, Inc.
> + *
> + * Authors: Shyam Sundar S K <Shyam-sundar.S-k@xxxxxxx>
> + *         Sandeep Singh <Sandeep.singh@xxxxxxx>
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/delay.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/interrupt.h>
> +#include <linux/io-64-nonatomic-lo-hi.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +
> +#include "amd_sfh_pcie.h"
> +
> +#define DRIVER_NAME    "pcie_mp2_amd"
> +#define DRIVER_DESC    "AMD(R) PCIe MP2 Communication Driver"
> +
> +#define ACEL_EN                BIT(1)
> +#define GYRO_EN                BIT(2)
> +#define MAGNO_EN       BIT(3)
> +#define ALS_EN         BIT(19)
> +
> +void amd_start_sensor(struct amd_mp2_dev *privdata, struct
> amd_mp2_sensor_info info)
> +{
> +       union sfh_cmd_param cmd_param;
> +       union sfh_cmd_base cmd_base;
> +
> +       /* fill up command register */
> +       memset(&cmd_base, 0, sizeof(cmd_base));
> +       cmd_base.s.cmd_id = ENABLE_SENSOR;
> +       cmd_base.s.period = info.period;
> +       cmd_base.s.sensor_id = info.sensor_idx;
> +
> +       /* fill up command param register */
> +       memset(&cmd_param, 0, sizeof(cmd_param));
> +       cmd_param.s.buf_layout = 1;
> +       cmd_param.s.buf_length = 16;
> +
> +       writeq(info.phys_address, privdata->mmio + AMD_C2P_MSG2);
> +       writel(cmd_param.ul, privdata->mmio + AMD_C2P_MSG1);
> +       writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
> +}
> +
> +void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx)
> +{
> +       union sfh_cmd_base cmd_base;
> +
> +       /* fill up command register */
> +       memset(&cmd_base, 0, sizeof(cmd_base));
> +       cmd_base.s.cmd_id = DISABLE_SENSOR;
> +       cmd_base.s.period = 0;
> +       cmd_base.s.sensor_id = sensor_idx;
> +
> +       writeq(0x0, privdata->mmio + AMD_C2P_MSG2);
> +       writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
> +}
> +
> +void amd_stop_all_sensors(struct amd_mp2_dev *privdata)
> +{
> +       union sfh_cmd_base cmd_base;
> +
> +       /* fill up command register */
> +       memset(&cmd_base, 0, sizeof(cmd_base));
> +       cmd_base.s.cmd_id = STOP_ALL_SENSORS;
> +       cmd_base.s.period = 0;
> +       cmd_base.s.sensor_id = 0;
> +
> +       writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
> +}
> +
> +int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8
> *sensor_id)
> +{
> +       int activestatus, num_of_sensors = 0;
> +
> +       privdata->activecontrolstatus = readl(privdata->mmio +
> AMD_P2C_MSG3);
> +       activestatus = privdata->activecontrolstatus >> 4;
> +       if (ACEL_EN  & activestatus)
> +               sensor_id[num_of_sensors++] = accel_idx;
> +
> +       if (GYRO_EN & activestatus)
> +               sensor_id[num_of_sensors++] = gyro_idx;
> +
> +       if (MAGNO_EN & activestatus)
> +               sensor_id[num_of_sensors++] = mag_idx;
> +
> +       if (ALS_EN & activestatus)
> +               sensor_id[num_of_sensors++] = als_idx;
> +
> +       return num_of_sensors;
> +}
> +
> +static void amd_mp2_pci_remove(void *privdata)
> +{
> +       amd_sfh_hid_client_deinit(privdata);
> +       amd_stop_all_sensors(privdata);
> +}
> +
> +static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct
> pci_device_id *id)
> +{
> +       struct amd_mp2_dev *privdata;
> +       int rc;
> +
> +       privdata = devm_kzalloc(&pdev->dev, sizeof(*privdata),
> GFP_KERNEL);
> +       if (!privdata)
> +               return -ENOMEM;
> +
> +       privdata->pdev = pdev;
> +       pci_set_drvdata(pdev, privdata);
> +       rc = pcim_enable_device(pdev);
> +       if (rc)
> +               return rc;
> +
> +       rc = pcim_iomap_regions(pdev, BIT(2), DRIVER_NAME);
> +       if (rc)
> +               return rc;
> +
> +       privdata->mmio = pcim_iomap_table(pdev)[2];
> +       pci_set_master(pdev);
> +       rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
> +       if (rc) {
> +               rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
> +               return rc;
> +       }
> +       rc = devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove,
> privdata);
> +       if (rc)
> +               return rc;
> +
> +       return amd_sfh_hid_client_init(privdata);
> +}
> +
> +static const struct pci_device_id amd_mp2_pci_tbl[] = {
> +       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MP2) },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(pci, amd_mp2_pci_tbl);
> +
> +static struct pci_driver amd_mp2_pci_driver = {
> +       .name           = DRIVER_NAME,
> +       .id_table       = amd_mp2_pci_tbl,
> +       .probe          = amd_mp2_pci_probe,
> +};
> +module_pci_driver(amd_mp2_pci_driver);
> +
> +MODULE_DESCRIPTION(DRIVER_DESC);
> +MODULE_LICENSE("Dual BSD/GPL");
> +MODULE_AUTHOR("Shyam Sundar S K <Shyam-sundar.S-k@xxxxxxx>");
> +MODULE_AUTHOR("Sandeep Singh <Sandeep.singh@xxxxxxx>");
> diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
> b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
> new file mode 100644
> index 000000000000..e8be94f935b7
> --- /dev/null
> +++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
> @@ -0,0 +1,79 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * AMD MP2 PCIe communication driver
> + * Copyright 2020 Advanced Micro Devices, Inc.
> + * Authors: Shyam Sundar S K <Shyam-sundar.S-k@xxxxxxx>
> + *         Sandeep Singh <Sandeep.singh@xxxxxxx>
> + */
> +
> +#ifndef PCIE_MP2_AMD_H
> +#define PCIE_MP2_AMD_H
> +
> +#include <linux/pci.h>
> +
> +#define PCI_DEVICE_ID_AMD_MP2  0x15E4
> +
> +#define ENABLE_SENSOR          1
> +#define DISABLE_SENSOR         2
> +#define STOP_ALL_SENSORS       8
> +
> +/* MP2 C2P Message Registers */
> +#define AMD_C2P_MSG0   0x10500
> +#define AMD_C2P_MSG1   0x10504
> +#define AMD_C2P_MSG2   0x10508
> +
> +/* MP2 P2C Message Registers */
> +#define AMD_P2C_MSG3   0x1068C /* Supported Sensors info */
> +
> +/* SFH Command register */
> +union sfh_cmd_base {
> +       u32 ul;
> +       struct {
> +               u32 cmd_id : 8;
> +               u32 sensor_id : 8;
> +               u32 period : 16;
> +       } s;
> +};
> +
> +union sfh_cmd_param {
> +       u32 ul;
> +       struct {
> +               u32 buf_layout : 2;
> +               u32 buf_length : 6;
> +               u32 rsvd : 24;
> +       } s;
> +};
> +
> +struct sfh_cmd_reg {
> +       union sfh_cmd_base cmd_base;
> +       union sfh_cmd_param cmd_param;
> +       phys_addr_t phys_addr;
> +};
> +
> +enum sensor_idx {
> +       accel_idx = 0,
> +       gyro_idx = 1,
> +       mag_idx = 2,
> +       als_idx = 19
> +};
> +
> +struct amd_mp2_dev {
> +       struct pci_dev *pdev;
> +       struct amdtp_cl_data *cl_data;
> +       void __iomem *mmio;
> +       u32 activecontrolstatus;
> +};
> +
> +struct amd_mp2_sensor_info {
> +       u8 sensor_idx;
> +       u32 period;
> +       phys_addr_t phys_address;
> +};
> +
> +void amd_start_sensor(struct amd_mp2_dev *privdata, struct
> amd_mp2_sensor_info info);
> +void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx);
> +void amd_stop_all_sensors(struct amd_mp2_dev *privdata);
> +int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8
> *sensor_id);
> +int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata);
> +int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata);
> +#endif