From ecc1641aca658ed4140751748f84985ffb6cce28 Mon Sep 17 00:00:00 2001 From: Xu Yilun Date: Wed, 6 Jan 2021 20:37:12 -0800 Subject: fpga: dfl: move dfl bus related APIs to include/linux/dfl.h Now the dfl drivers could be made as independent modules and put in different folders according to their functionalities. In order for scattered dfl device drivers to include dfl bus APIs, move the dfl bus APIs to a new header file in the public folder. [mdf@kernel.org: Fixed up header guards to match filename] Reviewed-by: Tom Rix Acked-by: Wu Hao Signed-off-by: Xu Yilun Signed-off-by: Moritz Fischer Link: https://lore.kernel.org/r/20210107043714.991646-7-mdf@kernel.org Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 546aa66428c9..a044b58eb9ac 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6957,6 +6957,7 @@ S: Maintained F: Documentation/ABI/testing/sysfs-bus-dfl F: Documentation/fpga/dfl.rst F: drivers/fpga/dfl* +F: include/linux/dfl.h F: include/uapi/linux/fpga-dfl.h FPGA MANAGER FRAMEWORK -- cgit v1.2.3 From 56172ab35338e3bb13c6bff65dea96b12e8c41ea Mon Sep 17 00:00:00 2001 From: Xu Yilun Date: Wed, 6 Jan 2021 20:37:13 -0800 Subject: fpga: dfl: add support for N3000 Nios private feature This patch adds support for the Nios handshake private feature on Intel PAC (Programmable Acceleration Card) N3000. The Nios is the embedded processor on the FPGA card. This private feature provides a handshake interface to FPGA Nios firmware, which receives retimer configuration command from host and executes via an internal SPI master (spi-altera). When Nios finishes the configuration, host takes over the ownership of the SPI master to control an Intel MAX10 BMC (Board Management Controller) Chip on the SPI bus. For Nios firmware handshake part, this driver requests the retimer configuration for Nios firmware on probe, and adds some sysfs nodes for user to query the onboard retimer's working mode and Nios firmware version. For SPI part, this driver adds a spi-altera platform device as well as the MAX10 BMC spi slave info. A spi-altera driver will be matched to handle the following SPI work. [mdf@kernel.org: Fixed up ABI doc kernel release] Reviewed-by: Tom Rix Signed-off-by: Xu Yilun Signed-off-by: Wu Hao Signed-off-by: Matthew Gerlach Signed-off-by: Russ Weight Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20210107043714.991646-8-mdf@kernel.org Signed-off-by: Greg Kroah-Hartman --- .../ABI/testing/sysfs-bus-dfl-devices-n3000-nios | 47 ++ MAINTAINERS | 2 +- drivers/fpga/Kconfig | 11 + drivers/fpga/Makefile | 2 + drivers/fpga/dfl-n3000-nios.c | 588 +++++++++++++++++++++ 5 files changed, 649 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-dfl-devices-n3000-nios create mode 100644 drivers/fpga/dfl-n3000-nios.c (limited to 'MAINTAINERS') diff --git a/Documentation/ABI/testing/sysfs-bus-dfl-devices-n3000-nios b/Documentation/ABI/testing/sysfs-bus-dfl-devices-n3000-nios new file mode 100644 index 000000000000..5335d742bcaf --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-dfl-devices-n3000-nios @@ -0,0 +1,47 @@ +What: /sys/bus/dfl/devices/dfl_dev.X/fec_mode +Date: Oct 2020 +KernelVersion: 5.12 +Contact: Xu Yilun +Description: Read-only. Returns the FEC mode of the 25G links of the + ethernet retimers configured by Nios firmware. "rs" for Reed + Solomon FEC, "kr" for Fire Code FEC, "no" for NO FEC. + "not supported" if the FEC mode setting is not supported, this + happens when the Nios firmware version major < 3, or no link is + configured to 25G. + Format: string + +What: /sys/bus/dfl/devices/dfl_dev.X/retimer_A_mode +Date: Oct 2020 +KernelVersion: 5.12 +Contact: Xu Yilun +Description: Read-only. Returns the enumeration value of the working mode of + the retimer A configured by the Nios firmware. The value is + read out from shared registers filled by the Nios firmware. Now + the values could be: + + - "0": Reset + - "1": 4x10G + - "2": 4x25G + - "3": 2x25G + - "4": 2x25G+2x10G + - "5": 1x25G + + If the Nios firmware is updated in future to support more + retimer modes, more enumeration value is expected. + Format: 0x%x + +What: /sys/bus/dfl/devices/dfl_dev.X/retimer_B_mode +Date: Oct 2020 +KernelVersion: 5.12 +Contact: Xu Yilun +Description: Read-only. Returns the enumeration value of the working mode of + the retimer B configured by the Nios firmware. The value format + is the same as retimer_A_mode. + +What: /sys/bus/dfl/devices/dfl_dev.X/nios_fw_version +Date: Oct 2020 +KernelVersion: 5.12 +Contact: Xu Yilun +Description: Read-only. Returns the version of the Nios firmware in the + FPGA. Its format is "major.minor.patch". + Format: %x.%x.%x diff --git a/MAINTAINERS b/MAINTAINERS index a044b58eb9ac..aebb26a7d8f2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6954,7 +6954,7 @@ M: Wu Hao R: Tom Rix L: linux-fpga@vger.kernel.org S: Maintained -F: Documentation/ABI/testing/sysfs-bus-dfl +F: Documentation/ABI/testing/sysfs-bus-dfl* F: Documentation/fpga/dfl.rst F: drivers/fpga/dfl* F: include/linux/dfl.h diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 5645226ca3ce..5ff9438b7b46 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -192,6 +192,17 @@ config FPGA_DFL_AFU to the FPGA infrastructure via a Port. There may be more than one Port/AFU per DFL based FPGA device. +config FPGA_DFL_NIOS_INTEL_PAC_N3000 + tristate "FPGA DFL NIOS Driver for Intel PAC N3000" + depends on FPGA_DFL + select REGMAP + help + This is the driver for the N3000 Nios private feature on Intel + PAC (Programmable Acceleration Card) N3000. It communicates + with the embedded Nios processor to configure the retimers on + the card. It also instantiates the SPI master (spi-altera) for + the card's BMC (Board Management Controller). + config FPGA_DFL_PCI tristate "FPGA DFL PCIe Device Driver" depends on PCI && FPGA_DFL diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index d8e21dfc6778..18dc9885883a 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -44,5 +44,7 @@ dfl-fme-objs += dfl-fme-perf.o dfl-afu-objs := dfl-afu-main.o dfl-afu-region.o dfl-afu-dma-region.o dfl-afu-objs += dfl-afu-error.o +obj-$(CONFIG_FPGA_DFL_NIOS_INTEL_PAC_N3000) += dfl-n3000-nios.o + # Drivers for FPGAs which implement DFL obj-$(CONFIG_FPGA_DFL_PCI) += dfl-pci.o diff --git a/drivers/fpga/dfl-n3000-nios.c b/drivers/fpga/dfl-n3000-nios.c new file mode 100644 index 000000000000..7a95366f6516 --- /dev/null +++ b/drivers/fpga/dfl-n3000-nios.c @@ -0,0 +1,588 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * DFL device driver for Nios private feature on Intel PAC (Programmable + * Acceleration Card) N3000 + * + * Copyright (C) 2019-2020 Intel Corporation, Inc. + * + * Authors: + * Wu Hao + * Xu Yilun + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * N3000 Nios private feature registers, named as NIOS_SPI_XX on spec. + * NS is the abbreviation of NIOS_SPI. + */ +#define N3000_NS_PARAM 0x8 +#define N3000_NS_PARAM_SHIFT_MODE_MSK BIT_ULL(1) +#define N3000_NS_PARAM_SHIFT_MODE_MSB 0 +#define N3000_NS_PARAM_SHIFT_MODE_LSB 1 +#define N3000_NS_PARAM_DATA_WIDTH GENMASK_ULL(7, 2) +#define N3000_NS_PARAM_NUM_CS GENMASK_ULL(13, 8) +#define N3000_NS_PARAM_CLK_POL BIT_ULL(14) +#define N3000_NS_PARAM_CLK_PHASE BIT_ULL(15) +#define N3000_NS_PARAM_PERIPHERAL_ID GENMASK_ULL(47, 32) + +#define N3000_NS_CTRL 0x10 +#define N3000_NS_CTRL_WR_DATA GENMASK_ULL(31, 0) +#define N3000_NS_CTRL_ADDR GENMASK_ULL(44, 32) +#define N3000_NS_CTRL_CMD_MSK GENMASK_ULL(63, 62) +#define N3000_NS_CTRL_CMD_NOP 0 +#define N3000_NS_CTRL_CMD_RD 1 +#define N3000_NS_CTRL_CMD_WR 2 + +#define N3000_NS_STAT 0x18 +#define N3000_NS_STAT_RD_DATA GENMASK_ULL(31, 0) +#define N3000_NS_STAT_RW_VAL BIT_ULL(32) + +/* Nios handshake registers, indirect access */ +#define N3000_NIOS_INIT 0x1000 +#define N3000_NIOS_INIT_DONE BIT(0) +#define N3000_NIOS_INIT_START BIT(1) +/* Mode for retimer A, link 0, the same below */ +#define N3000_NIOS_INIT_REQ_FEC_MODE_A0_MSK GENMASK(9, 8) +#define N3000_NIOS_INIT_REQ_FEC_MODE_A1_MSK GENMASK(11, 10) +#define N3000_NIOS_INIT_REQ_FEC_MODE_A2_MSK GENMASK(13, 12) +#define N3000_NIOS_INIT_REQ_FEC_MODE_A3_MSK GENMASK(15, 14) +#define N3000_NIOS_INIT_REQ_FEC_MODE_B0_MSK GENMASK(17, 16) +#define N3000_NIOS_INIT_REQ_FEC_MODE_B1_MSK GENMASK(19, 18) +#define N3000_NIOS_INIT_REQ_FEC_MODE_B2_MSK GENMASK(21, 20) +#define N3000_NIOS_INIT_REQ_FEC_MODE_B3_MSK GENMASK(23, 22) +#define N3000_NIOS_INIT_REQ_FEC_MODE_NO 0x0 +#define N3000_NIOS_INIT_REQ_FEC_MODE_KR 0x1 +#define N3000_NIOS_INIT_REQ_FEC_MODE_RS 0x2 + +#define N3000_NIOS_FW_VERSION 0x1004 +#define N3000_NIOS_FW_VERSION_PATCH GENMASK(23, 20) +#define N3000_NIOS_FW_VERSION_MINOR GENMASK(27, 24) +#define N3000_NIOS_FW_VERSION_MAJOR GENMASK(31, 28) + +/* The retimers we use on Intel PAC N3000 is Parkvale, abbreviated to PKVL */ +#define N3000_NIOS_PKVL_A_MODE_STS 0x1020 +#define N3000_NIOS_PKVL_B_MODE_STS 0x1024 +#define N3000_NIOS_PKVL_MODE_STS_GROUP_MSK GENMASK(15, 8) +#define N3000_NIOS_PKVL_MODE_STS_GROUP_OK 0x0 +#define N3000_NIOS_PKVL_MODE_STS_ID_MSK GENMASK(7, 0) +/* When GROUP MASK field == GROUP_OK */ +#define N3000_NIOS_PKVL_MODE_ID_RESET 0x0 +#define N3000_NIOS_PKVL_MODE_ID_4X10G 0x1 +#define N3000_NIOS_PKVL_MODE_ID_4X25G 0x2 +#define N3000_NIOS_PKVL_MODE_ID_2X25G 0x3 +#define N3000_NIOS_PKVL_MODE_ID_2X25G_2X10G 0x4 +#define N3000_NIOS_PKVL_MODE_ID_1X25G 0x5 + +#define N3000_NIOS_REGBUS_RETRY_COUNT 10000 /* loop count */ + +#define N3000_NIOS_INIT_TIMEOUT 10000000 /* usec */ +#define N3000_NIOS_INIT_TIME_INTV 100000 /* usec */ + +#define N3000_NIOS_INIT_REQ_FEC_MODE_MSK_ALL \ + (N3000_NIOS_INIT_REQ_FEC_MODE_A0_MSK | \ + N3000_NIOS_INIT_REQ_FEC_MODE_A1_MSK | \ + N3000_NIOS_INIT_REQ_FEC_MODE_A2_MSK | \ + N3000_NIOS_INIT_REQ_FEC_MODE_A3_MSK | \ + N3000_NIOS_INIT_REQ_FEC_MODE_B0_MSK | \ + N3000_NIOS_INIT_REQ_FEC_MODE_B1_MSK | \ + N3000_NIOS_INIT_REQ_FEC_MODE_B2_MSK | \ + N3000_NIOS_INIT_REQ_FEC_MODE_B3_MSK) + +#define N3000_NIOS_INIT_REQ_FEC_MODE_NO_ALL \ + (FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A0_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_NO) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A1_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_NO) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A2_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_NO) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A3_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_NO) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B0_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_NO) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B1_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_NO) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B2_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_NO) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B3_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_NO)) + +#define N3000_NIOS_INIT_REQ_FEC_MODE_KR_ALL \ + (FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A0_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_KR) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A1_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_KR) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A2_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_KR) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A3_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_KR) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B0_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_KR) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B1_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_KR) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B2_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_KR) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B3_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_KR)) + +#define N3000_NIOS_INIT_REQ_FEC_MODE_RS_ALL \ + (FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A0_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_RS) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A1_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_RS) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A2_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_RS) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_A3_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_RS) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B0_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_RS) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B1_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_RS) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B2_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_RS) | \ + FIELD_PREP(N3000_NIOS_INIT_REQ_FEC_MODE_B3_MSK, \ + N3000_NIOS_INIT_REQ_FEC_MODE_RS)) + +struct n3000_nios { + void __iomem *base; + struct regmap *regmap; + struct device *dev; + struct platform_device *altera_spi; +}; + +static ssize_t nios_fw_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct n3000_nios *nn = dev_get_drvdata(dev); + unsigned int val; + int ret; + + ret = regmap_read(nn->regmap, N3000_NIOS_FW_VERSION, &val); + if (ret) + return ret; + + return sysfs_emit(buf, "%x.%x.%x\n", + (u8)FIELD_GET(N3000_NIOS_FW_VERSION_MAJOR, val), + (u8)FIELD_GET(N3000_NIOS_FW_VERSION_MINOR, val), + (u8)FIELD_GET(N3000_NIOS_FW_VERSION_PATCH, val)); +} +static DEVICE_ATTR_RO(nios_fw_version); + +#define IS_MODE_STATUS_OK(mode_stat) \ + (FIELD_GET(N3000_NIOS_PKVL_MODE_STS_GROUP_MSK, (mode_stat)) == \ + N3000_NIOS_PKVL_MODE_STS_GROUP_OK) + +#define IS_RETIMER_FEC_SUPPORTED(retimer_mode) \ + ((retimer_mode) != N3000_NIOS_PKVL_MODE_ID_RESET && \ + (retimer_mode) != N3000_NIOS_PKVL_MODE_ID_4X10G) + +static int get_retimer_mode(struct n3000_nios *nn, unsigned int mode_stat_reg, + unsigned int *retimer_mode) +{ + unsigned int val; + int ret; + + ret = regmap_read(nn->regmap, mode_stat_reg, &val); + if (ret) + return ret; + + if (!IS_MODE_STATUS_OK(val)) + return -EFAULT; + + *retimer_mode = FIELD_GET(N3000_NIOS_PKVL_MODE_STS_ID_MSK, val); + + return 0; +} + +static ssize_t retimer_A_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct n3000_nios *nn = dev_get_drvdata(dev); + unsigned int mode; + int ret; + + ret = get_retimer_mode(nn, N3000_NIOS_PKVL_A_MODE_STS, &mode); + if (ret) + return ret; + + return sysfs_emit(buf, "0x%x\n", mode); +} +static DEVICE_ATTR_RO(retimer_A_mode); + +static ssize_t retimer_B_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct n3000_nios *nn = dev_get_drvdata(dev); + unsigned int mode; + int ret; + + ret = get_retimer_mode(nn, N3000_NIOS_PKVL_B_MODE_STS, &mode); + if (ret) + return ret; + + return sysfs_emit(buf, "0x%x\n", mode); +} +static DEVICE_ATTR_RO(retimer_B_mode); + +static ssize_t fec_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned int val, retimer_a_mode, retimer_b_mode, fec_modes; + struct n3000_nios *nn = dev_get_drvdata(dev); + int ret; + + /* FEC mode setting is not supported in early FW versions */ + ret = regmap_read(nn->regmap, N3000_NIOS_FW_VERSION, &val); + if (ret) + return ret; + + if (FIELD_GET(N3000_NIOS_FW_VERSION_MAJOR, val) < 3) + return sysfs_emit(buf, "not supported\n"); + + /* If no 25G links, FEC mode setting is not supported either */ + ret = get_retimer_mode(nn, N3000_NIOS_PKVL_A_MODE_STS, &retimer_a_mode); + if (ret) + return ret; + + ret = get_retimer_mode(nn, N3000_NIOS_PKVL_B_MODE_STS, &retimer_b_mode); + if (ret) + return ret; + + if (!IS_RETIMER_FEC_SUPPORTED(retimer_a_mode) && + !IS_RETIMER_FEC_SUPPORTED(retimer_b_mode)) + return sysfs_emit(buf, "not supported\n"); + + /* get the valid FEC mode for 25G links */ + ret = regmap_read(nn->regmap, N3000_NIOS_INIT, &val); + if (ret) + return ret; + + /* + * FEC mode should always be the same for all links, as we set them + * in this way. + */ + fec_modes = (val & N3000_NIOS_INIT_REQ_FEC_MODE_MSK_ALL); + if (fec_modes == N3000_NIOS_INIT_REQ_FEC_MODE_NO_ALL) + return sysfs_emit(buf, "no\n"); + else if (fec_modes == N3000_NIOS_INIT_REQ_FEC_MODE_KR_ALL) + return sysfs_emit(buf, "kr\n"); + else if (fec_modes == N3000_NIOS_INIT_REQ_FEC_MODE_RS_ALL) + return sysfs_emit(buf, "rs\n"); + + return -EFAULT; +} +static DEVICE_ATTR_RO(fec_mode); + +static struct attribute *n3000_nios_attrs[] = { + &dev_attr_nios_fw_version.attr, + &dev_attr_retimer_A_mode.attr, + &dev_attr_retimer_B_mode.attr, + &dev_attr_fec_mode.attr, + NULL, +}; +ATTRIBUTE_GROUPS(n3000_nios); + +static int n3000_nios_init_done_check(struct n3000_nios *nn) +{ + unsigned int val, state_a, state_b; + struct device *dev = nn->dev; + int ret, ret2; + + /* + * The SPI is shared by the Nios core inside the FPGA, Nios will use + * this SPI master to do some one time initialization after power up, + * and then release the control to OS. The driver needs to poll on + * INIT_DONE to see when driver could take the control. + * + * Please note that after Nios firmware version 3.0.0, INIT_START is + * introduced, so driver needs to trigger START firstly and then check + * INIT_DONE. + */ + + ret = regmap_read(nn->regmap, N3000_NIOS_FW_VERSION, &val); + if (ret) + return ret; + + /* + * If Nios version register is totally uninitialized(== 0x0), then the + * Nios firmware is missing. So host could take control of SPI master + * safely, but initialization work for Nios is not done. To restore the + * card, we need to reprogram a new Nios firmware via the BMC chip on + * SPI bus. So the driver doesn't error out, it continues to create the + * spi controller device and spi_board_info for BMC. + */ + if (val == 0) { + dev_err(dev, "Nios version reg = 0x%x, skip INIT_DONE check, but the retimer may be uninitialized\n", + val); + return 0; + } + + if (FIELD_GET(N3000_NIOS_FW_VERSION_MAJOR, val) >= 3) { + /* read NIOS_INIT to check if retimer initialization is done */ + ret = regmap_read(nn->regmap, N3000_NIOS_INIT, &val); + if (ret) + return ret; + + /* check if retimers are initialized already */ + if (val & (N3000_NIOS_INIT_DONE | N3000_NIOS_INIT_START)) + goto nios_init_done; + + /* configure FEC mode per module param */ + val = N3000_NIOS_INIT_START; + + /* + * When the retimer is to be set to 10G mode, there is no FEC + * mode setting, so the REQ_FEC_MODE field will be ignored by + * Nios firmware in this case. But we should still fill the FEC + * mode field cause host could not get the retimer working mode + * until the Nios init is done. + * + * For now the driver doesn't support the retimer FEC mode + * switching per user's request. It is always set to Reed + * Solomon FEC. + * + * The driver will set the same FEC mode for all links. + */ + val |= N3000_NIOS_INIT_REQ_FEC_MODE_RS_ALL; + + ret = regmap_write(nn->regmap, N3000_NIOS_INIT, val); + if (ret) + return ret; + } + +nios_init_done: + /* polls on NIOS_INIT_DONE */ + ret = regmap_read_poll_timeout(nn->regmap, N3000_NIOS_INIT, val, + val & N3000_NIOS_INIT_DONE, + N3000_NIOS_INIT_TIME_INTV, + N3000_NIOS_INIT_TIMEOUT); + if (ret) + dev_err(dev, "NIOS_INIT_DONE %s\n", + (ret == -ETIMEDOUT) ? "timed out" : "check error"); + + ret2 = regmap_read(nn->regmap, N3000_NIOS_PKVL_A_MODE_STS, &state_a); + if (ret2) + return ret2; + + ret2 = regmap_read(nn->regmap, N3000_NIOS_PKVL_B_MODE_STS, &state_b); + if (ret2) + return ret2; + + if (!ret) { + /* + * After INIT_DONE is detected, it still needs to check if the + * Nios firmware reports any error during the retimer + * configuration. + */ + if (IS_MODE_STATUS_OK(state_a) && IS_MODE_STATUS_OK(state_b)) + return 0; + + /* + * If the retimer configuration is failed, the Nios firmware + * will still release the spi controller for host to + * communicate with the BMC. It makes possible for people to + * reprogram a new Nios firmware and restore the card. So the + * driver doesn't error out, it continues to create the spi + * controller device and spi_board_info for BMC. + */ + dev_err(dev, "NIOS_INIT_DONE OK, but err on retimer init\n"); + } + + dev_err(nn->dev, "PKVL_A_MODE_STS 0x%x\n", state_a); + dev_err(nn->dev, "PKVL_B_MODE_STS 0x%x\n", state_b); + + return ret; +} + +static struct spi_board_info m10_n3000_info = { + .modalias = "m10-n3000", + .max_speed_hz = 12500000, + .bus_num = 0, + .chip_select = 0, +}; + +static int create_altera_spi_controller(struct n3000_nios *nn) +{ + struct altera_spi_platform_data pdata = { 0 }; + struct platform_device_info pdevinfo = { 0 }; + void __iomem *base = nn->base; + u64 v; + + v = readq(base + N3000_NS_PARAM); + + pdata.mode_bits = SPI_CS_HIGH; + if (FIELD_GET(N3000_NS_PARAM_CLK_POL, v)) + pdata.mode_bits |= SPI_CPOL; + if (FIELD_GET(N3000_NS_PARAM_CLK_PHASE, v)) + pdata.mode_bits |= SPI_CPHA; + + pdata.num_chipselect = FIELD_GET(N3000_NS_PARAM_NUM_CS, v); + pdata.bits_per_word_mask = + SPI_BPW_RANGE_MASK(1, FIELD_GET(N3000_NS_PARAM_DATA_WIDTH, v)); + + pdata.num_devices = 1; + pdata.devices = &m10_n3000_info; + + dev_dbg(nn->dev, "%s cs %u bpm 0x%x mode 0x%x\n", __func__, + pdata.num_chipselect, pdata.bits_per_word_mask, + pdata.mode_bits); + + pdevinfo.name = "subdev_spi_altera"; + pdevinfo.id = PLATFORM_DEVID_AUTO; + pdevinfo.parent = nn->dev; + pdevinfo.data = &pdata; + pdevinfo.size_data = sizeof(pdata); + + nn->altera_spi = platform_device_register_full(&pdevinfo); + return PTR_ERR_OR_ZERO(nn->altera_spi); +} + +static void destroy_altera_spi_controller(struct n3000_nios *nn) +{ + platform_device_unregister(nn->altera_spi); +} + +static int n3000_nios_poll_stat_timeout(void __iomem *base, u64 *v) +{ + int loops; + + /* + * We don't use the time based timeout here for performance. + * + * The regbus read/write is on the critical path of Intel PAC N3000 + * image programing. The time based timeout checking will add too much + * overhead on it. Usually the state changes in 1 or 2 loops on the + * test server, and we set 10000 times loop here for safety. + */ + for (loops = N3000_NIOS_REGBUS_RETRY_COUNT; loops > 0 ; loops--) { + *v = readq(base + N3000_NS_STAT); + if (*v & N3000_NS_STAT_RW_VAL) + break; + cpu_relax(); + } + + return (loops > 0) ? 0 : -ETIMEDOUT; +} + +static int n3000_nios_reg_write(void *context, unsigned int reg, unsigned int val) +{ + struct n3000_nios *nn = context; + u64 v; + int ret; + + v = FIELD_PREP(N3000_NS_CTRL_CMD_MSK, N3000_NS_CTRL_CMD_WR) | + FIELD_PREP(N3000_NS_CTRL_ADDR, reg) | + FIELD_PREP(N3000_NS_CTRL_WR_DATA, val); + writeq(v, nn->base + N3000_NS_CTRL); + + ret = n3000_nios_poll_stat_timeout(nn->base, &v); + if (ret) + dev_err(nn->dev, "fail to write reg 0x%x val 0x%x: %d\n", + reg, val, ret); + + return ret; +} + +static int n3000_nios_reg_read(void *context, unsigned int reg, unsigned int *val) +{ + struct n3000_nios *nn = context; + u64 v; + int ret; + + v = FIELD_PREP(N3000_NS_CTRL_CMD_MSK, N3000_NS_CTRL_CMD_RD) | + FIELD_PREP(N3000_NS_CTRL_ADDR, reg); + writeq(v, nn->base + N3000_NS_CTRL); + + ret = n3000_nios_poll_stat_timeout(nn->base, &v); + if (ret) + dev_err(nn->dev, "fail to read reg 0x%x: %d\n", reg, ret); + else + *val = FIELD_GET(N3000_NS_STAT_RD_DATA, v); + + return ret; +} + +static const struct regmap_config n3000_nios_regbus_cfg = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + + .reg_write = n3000_nios_reg_write, + .reg_read = n3000_nios_reg_read, +}; + +static int n3000_nios_probe(struct dfl_device *ddev) +{ + struct device *dev = &ddev->dev; + struct n3000_nios *nn; + int ret; + + nn = devm_kzalloc(dev, sizeof(*nn), GFP_KERNEL); + if (!nn) + return -ENOMEM; + + dev_set_drvdata(&ddev->dev, nn); + + nn->dev = dev; + + nn->base = devm_ioremap_resource(&ddev->dev, &ddev->mmio_res); + if (IS_ERR(nn->base)) + return PTR_ERR(nn->base); + + nn->regmap = devm_regmap_init(dev, NULL, nn, &n3000_nios_regbus_cfg); + if (IS_ERR(nn->regmap)) + return PTR_ERR(nn->regmap); + + ret = n3000_nios_init_done_check(nn); + if (ret) + return ret; + + ret = create_altera_spi_controller(nn); + if (ret) + dev_err(dev, "altera spi controller create failed: %d\n", ret); + + return ret; +} + +static void n3000_nios_remove(struct dfl_device *ddev) +{ + struct n3000_nios *nn = dev_get_drvdata(&ddev->dev); + + destroy_altera_spi_controller(nn); +} + +#define FME_FEATURE_ID_N3000_NIOS 0xd + +static const struct dfl_device_id n3000_nios_ids[] = { + { FME_ID, FME_FEATURE_ID_N3000_NIOS }, + { } +}; +MODULE_DEVICE_TABLE(dfl, n3000_nios_ids); + +static struct dfl_driver n3000_nios_driver = { + .drv = { + .name = "dfl-n3000-nios", + .dev_groups = n3000_nios_groups, + }, + .id_table = n3000_nios_ids, + .probe = n3000_nios_probe, + .remove = n3000_nios_remove, +}; + +module_dfl_driver(n3000_nios_driver); + +MODULE_DESCRIPTION("Driver for Nios private feature on Intel PAC N3000"); +MODULE_AUTHOR("Intel Corporation"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 33cb6d1ed311af2c1dfd107fa334cfb51113ef35 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 28 Dec 2020 21:30:21 +0100 Subject: dmaengine: at_hdmac: remove platform data header linux/platform_data/dma-atmel.h is only used by the at_hdmac driver. Move the CFG bits definitions back in at_hdmac_regs.h and the remaining definitions in the driver. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20201228203022.2674133-1-alexandre.belloni@bootlin.com Signed-off-by: Vinod Koul --- MAINTAINERS | 1 - drivers/dma/at_hdmac.c | 19 ++++++++++ drivers/dma/at_hdmac_regs.h | 28 +++++++++++++-- include/linux/platform_data/dma-atmel.h | 61 --------------------------------- 4 files changed, 44 insertions(+), 65 deletions(-) delete mode 100644 include/linux/platform_data/dma-atmel.h (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 546aa66428c9..0d62310a31f8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11604,7 +11604,6 @@ F: drivers/dma/at_hdmac.c F: drivers/dma/at_hdmac_regs.h F: drivers/dma/at_xdmac.c F: include/dt-bindings/dma/at91.h -F: include/linux/platform_data/dma-atmel.h MICROCHIP AT91 SERIAL DRIVER M: Richard Genoud diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 7eaee5b705b1..30ae36124b1d 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -54,6 +54,25 @@ module_param(init_nr_desc_per_channel, uint, 0644); MODULE_PARM_DESC(init_nr_desc_per_channel, "initial descriptors per channel (default: 64)"); +/** + * struct at_dma_platform_data - Controller configuration parameters + * @nr_channels: Number of channels supported by hardware (max 8) + * @cap_mask: dma_capability flags supported by the platform + */ +struct at_dma_platform_data { + unsigned int nr_channels; + dma_cap_mask_t cap_mask; +}; + +/** + * struct at_dma_slave - Controller-specific information about a slave + * @dma_dev: required DMA master device + * @cfg: Platform-specific initializer for the CFG register + */ +struct at_dma_slave { + struct device *dma_dev; + u32 cfg; +}; /* prototypes */ static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx); diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index 80fc2fe8c77e..4d1ebc040031 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h @@ -7,8 +7,6 @@ #ifndef AT_HDMAC_REGS_H #define AT_HDMAC_REGS_H -#include - #define AT_DMA_MAX_NR_CHANNELS 8 @@ -148,7 +146,31 @@ #define ATC_AUTO (0x1 << 31) /* Auto multiple buffer tx enable */ /* Bitfields in CFG */ -/* are in at_hdmac.h */ +#define ATC_PER_MSB(h) ((0x30U & (h)) >> 4) /* Extract most significant bits of a handshaking identifier */ + +#define ATC_SRC_PER(h) (0xFU & (h)) /* Channel src rq associated with periph handshaking ifc h */ +#define ATC_DST_PER(h) ((0xFU & (h)) << 4) /* Channel dst rq associated with periph handshaking ifc h */ +#define ATC_SRC_REP (0x1 << 8) /* Source Replay Mod */ +#define ATC_SRC_H2SEL (0x1 << 9) /* Source Handshaking Mod */ +#define ATC_SRC_H2SEL_SW (0x0 << 9) +#define ATC_SRC_H2SEL_HW (0x1 << 9) +#define ATC_SRC_PER_MSB(h) (ATC_PER_MSB(h) << 10) /* Channel src rq (most significant bits) */ +#define ATC_DST_REP (0x1 << 12) /* Destination Replay Mod */ +#define ATC_DST_H2SEL (0x1 << 13) /* Destination Handshaking Mod */ +#define ATC_DST_H2SEL_SW (0x0 << 13) +#define ATC_DST_H2SEL_HW (0x1 << 13) +#define ATC_DST_PER_MSB(h) (ATC_PER_MSB(h) << 14) /* Channel dst rq (most significant bits) */ +#define ATC_SOD (0x1 << 16) /* Stop On Done */ +#define ATC_LOCK_IF (0x1 << 20) /* Interface Lock */ +#define ATC_LOCK_B (0x1 << 21) /* AHB Bus Lock */ +#define ATC_LOCK_IF_L (0x1 << 22) /* Master Interface Arbiter Lock */ +#define ATC_LOCK_IF_L_CHUNK (0x0 << 22) +#define ATC_LOCK_IF_L_BUFFER (0x1 << 22) +#define ATC_AHB_PROT_MASK (0x7 << 24) /* AHB Protection */ +#define ATC_FIFOCFG_MASK (0x3 << 28) /* FIFO Request Configuration */ +#define ATC_FIFOCFG_LARGESTBURST (0x0 << 28) +#define ATC_FIFOCFG_HALFFIFO (0x1 << 28) +#define ATC_FIFOCFG_ENOUGHSPACE (0x2 << 28) /* Bitfields in SPIP */ #define ATC_SPIP_HOLE(x) (0xFFFFU & (x)) diff --git a/include/linux/platform_data/dma-atmel.h b/include/linux/platform_data/dma-atmel.h deleted file mode 100644 index 069637e6004f..000000000000 --- a/include/linux/platform_data/dma-atmel.h +++ /dev/null @@ -1,61 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Header file for the Atmel AHB DMA Controller driver - * - * Copyright (C) 2008 Atmel Corporation - */ -#ifndef AT_HDMAC_H -#define AT_HDMAC_H - -#include - -/** - * struct at_dma_platform_data - Controller configuration parameters - * @nr_channels: Number of channels supported by hardware (max 8) - * @cap_mask: dma_capability flags supported by the platform - */ -struct at_dma_platform_data { - unsigned int nr_channels; - dma_cap_mask_t cap_mask; -}; - -/** - * struct at_dma_slave - Controller-specific information about a slave - * @dma_dev: required DMA master device - * @cfg: Platform-specific initializer for the CFG register - */ -struct at_dma_slave { - struct device *dma_dev; - u32 cfg; -}; - - -/* Platform-configurable bits in CFG */ -#define ATC_PER_MSB(h) ((0x30U & (h)) >> 4) /* Extract most significant bits of a handshaking identifier */ - -#define ATC_SRC_PER(h) (0xFU & (h)) /* Channel src rq associated with periph handshaking ifc h */ -#define ATC_DST_PER(h) ((0xFU & (h)) << 4) /* Channel dst rq associated with periph handshaking ifc h */ -#define ATC_SRC_REP (0x1 << 8) /* Source Replay Mod */ -#define ATC_SRC_H2SEL (0x1 << 9) /* Source Handshaking Mod */ -#define ATC_SRC_H2SEL_SW (0x0 << 9) -#define ATC_SRC_H2SEL_HW (0x1 << 9) -#define ATC_SRC_PER_MSB(h) (ATC_PER_MSB(h) << 10) /* Channel src rq (most significant bits) */ -#define ATC_DST_REP (0x1 << 12) /* Destination Replay Mod */ -#define ATC_DST_H2SEL (0x1 << 13) /* Destination Handshaking Mod */ -#define ATC_DST_H2SEL_SW (0x0 << 13) -#define ATC_DST_H2SEL_HW (0x1 << 13) -#define ATC_DST_PER_MSB(h) (ATC_PER_MSB(h) << 14) /* Channel dst rq (most significant bits) */ -#define ATC_SOD (0x1 << 16) /* Stop On Done */ -#define ATC_LOCK_IF (0x1 << 20) /* Interface Lock */ -#define ATC_LOCK_B (0x1 << 21) /* AHB Bus Lock */ -#define ATC_LOCK_IF_L (0x1 << 22) /* Master Interface Arbiter Lock */ -#define ATC_LOCK_IF_L_CHUNK (0x0 << 22) -#define ATC_LOCK_IF_L_BUFFER (0x1 << 22) -#define ATC_AHB_PROT_MASK (0x7 << 24) /* AHB Protection */ -#define ATC_FIFOCFG_MASK (0x3 << 28) /* FIFO Request Configuration */ -#define ATC_FIFOCFG_LARGESTBURST (0x0 << 28) -#define ATC_FIFOCFG_HALFFIFO (0x1 << 28) -#define ATC_FIFOCFG_ENOUGHSPACE (0x2 << 28) - - -#endif /* AT_HDMAC_H */ -- cgit v1.2.3 From 802fee26d8afd073c630a74dbe1a996970f3fd90 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Sun, 13 Dec 2020 22:50:40 +0900 Subject: riscv: cleanup Canaan Kendryte K210 sysctl driver Introduce the header file include/soc/canaan/k210-sysctl.h to have a common definition of the Canaan Kendryte K210 SoC system controller registers. Simplify the k210 system controller driver code by removing unused register bits definition. The MAINTAINERS file is updated, adding the entry "CANAAN/KENDRYTE K210 SOC SYSTEM CONTROLLER DRIVER" with myself listed as maintainer for this driver. This is a preparatory patch for introducing the K210 clock driver. No functional changes are introduced. Signed-off-by: Damien Le Moal Signed-off-by: Palmer Dabbelt --- MAINTAINERS | 7 +++ drivers/soc/canaan/k210-sysctl.c | 93 +++++++++++----------------------------- include/soc/canaan/k210-sysctl.h | 41 ++++++++++++++++++ 3 files changed, 74 insertions(+), 67 deletions(-) create mode 100644 include/soc/canaan/k210-sysctl.h (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 6eff4f720c72..4aaa7a17016b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3860,6 +3860,13 @@ W: https://github.com/Cascoda/ca8210-linux.git F: Documentation/devicetree/bindings/net/ieee802154/ca8210.txt F: drivers/net/ieee802154/ca8210.c +CANAAN/KENDRYTE K210 SOC SYSTEM CONTROLLER DRIVER +M: Damien Le Moal +L: linux-riscv@lists.infradead.org +S: Maintained +F: drivers/soc/canaan/ +F: include/soc/canaan/ + CACHEFILES: FS-CACHE BACKEND FOR CACHING ON MOUNTED FILESYSTEMS M: David Howells L: linux-cachefs@redhat.com (moderated for non-subscribers) diff --git a/drivers/soc/canaan/k210-sysctl.c b/drivers/soc/canaan/k210-sysctl.c index 4608fbca20e1..60b474c33d45 100644 --- a/drivers/soc/canaan/k210-sysctl.c +++ b/drivers/soc/canaan/k210-sysctl.c @@ -12,74 +12,33 @@ #include #include +#include + #define K210_SYSCTL_CLK0_FREQ 26000000UL /* Registers base address */ #define K210_SYSCTL_SYSCTL_BASE_ADDR 0x50440000ULL -/* Registers */ -#define K210_SYSCTL_PLL0 0x08 -#define K210_SYSCTL_PLL1 0x0c -/* clkr: 4bits, clkf1: 6bits, clkod: 4bits, bwadj: 4bits */ -#define PLL_RESET (1 << 20) -#define PLL_PWR (1 << 21) -#define PLL_INTFB (1 << 22) -#define PLL_BYPASS (1 << 23) -#define PLL_TEST (1 << 24) -#define PLL_OUT_EN (1 << 25) -#define PLL_TEST_EN (1 << 26) -#define K210_SYSCTL_PLL_LOCK 0x18 -#define PLL0_LOCK1 (1 << 0) -#define PLL0_LOCK2 (1 << 1) -#define PLL0_SLIP_CLEAR (1 << 2) -#define PLL0_TEST_CLK_OUT (1 << 3) -#define PLL1_LOCK1 (1 << 8) -#define PLL1_LOCK2 (1 << 9) -#define PLL1_SLIP_CLEAR (1 << 10) -#define PLL1_TEST_CLK_OUT (1 << 11) -#define PLL2_LOCK1 (1 << 16) -#define PLL2_LOCK2 (1 << 16) -#define PLL2_SLIP_CLEAR (1 << 18) -#define PLL2_TEST_CLK_OUT (1 << 19) -#define K210_SYSCTL_CLKSEL0 0x20 -#define CLKSEL_ACLK (1 << 0) -#define K210_SYSCTL_CLKEN_CENT 0x28 -#define CLKEN_CPU (1 << 0) -#define CLKEN_SRAM0 (1 << 1) -#define CLKEN_SRAM1 (1 << 2) -#define CLKEN_APB0 (1 << 3) -#define CLKEN_APB1 (1 << 4) -#define CLKEN_APB2 (1 << 5) -#define K210_SYSCTL_CLKEN_PERI 0x2c -#define CLKEN_ROM (1 << 0) -#define CLKEN_DMA (1 << 1) -#define CLKEN_AI (1 << 2) -#define CLKEN_DVP (1 << 3) -#define CLKEN_FFT (1 << 4) -#define CLKEN_GPIO (1 << 5) -#define CLKEN_SPI0 (1 << 6) -#define CLKEN_SPI1 (1 << 7) -#define CLKEN_SPI2 (1 << 8) -#define CLKEN_SPI3 (1 << 9) -#define CLKEN_I2S0 (1 << 10) -#define CLKEN_I2S1 (1 << 11) -#define CLKEN_I2S2 (1 << 12) -#define CLKEN_I2C0 (1 << 13) -#define CLKEN_I2C1 (1 << 14) -#define CLKEN_I2C2 (1 << 15) -#define CLKEN_UART1 (1 << 16) -#define CLKEN_UART2 (1 << 17) -#define CLKEN_UART3 (1 << 18) -#define CLKEN_AES (1 << 19) -#define CLKEN_FPIO (1 << 20) -#define CLKEN_TIMER0 (1 << 21) -#define CLKEN_TIMER1 (1 << 22) -#define CLKEN_TIMER2 (1 << 23) -#define CLKEN_WDT0 (1 << 24) -#define CLKEN_WDT1 (1 << 25) -#define CLKEN_SHA (1 << 26) -#define CLKEN_OTP (1 << 27) -#define CLKEN_RTC (1 << 29) +/* Register bits */ +/* K210_SYSCTL_PLL1: clkr: 4bits, clkf1: 6bits, clkod: 4bits, bwadj: 4bits */ +#define PLL_RESET (1 << 20) +#define PLL_PWR (1 << 21) +#define PLL_BYPASS (1 << 23) +#define PLL_OUT_EN (1 << 25) +/* K210_SYSCTL_PLL_LOCK */ +#define PLL1_LOCK1 (1 << 8) +#define PLL1_LOCK2 (1 << 9) +#define PLL1_SLIP_CLEAR (1 << 10) +/* K210_SYSCTL_SEL0 */ +#define CLKSEL_ACLK (1 << 0) +/* K210_SYSCTL_CLKEN_CENT */ +#define CLKEN_CPU (1 << 0) +#define CLKEN_SRAM0 (1 << 1) +#define CLKEN_SRAM1 (1 << 2) +/* K210_SYSCTL_EN_PERI */ +#define CLKEN_ROM (1 << 0) +#define CLKEN_TIMER0 (1 << 21) +#define CLKEN_RTC (1 << 29) struct k210_sysctl { void __iomem *regs; @@ -140,7 +99,7 @@ static unsigned long k210_sysctl_clk_recalc_rate(struct clk_hw *hw, * If the clock selector is not set, use the base frequency. * Otherwise, use PLL0 frequency with a frequency divisor. */ - clksel0 = readl(s->regs + K210_SYSCTL_CLKSEL0); + clksel0 = readl(s->regs + K210_SYSCTL_SEL0); if (!(clksel0 & CLKSEL_ACLK)) return K210_SYSCTL_CLK0_FREQ; @@ -237,11 +196,11 @@ static void __init k210_soc_early_init(const void *fdt) k210_set_bits(PLL_OUT_EN, regs + K210_SYSCTL_PLL0); k210_set_bits(CLKEN_CPU | CLKEN_SRAM0 | CLKEN_SRAM1, - regs + K210_SYSCTL_CLKEN_CENT); + regs + K210_SYSCTL_EN_CENT); k210_set_bits(CLKEN_ROM | CLKEN_TIMER0 | CLKEN_RTC, - regs + K210_SYSCTL_CLKEN_PERI); + regs + K210_SYSCTL_EN_PERI); - k210_set_bits(CLKSEL_ACLK, regs + K210_SYSCTL_CLKSEL0); + k210_set_bits(CLKSEL_ACLK, regs + K210_SYSCTL_SEL0); iounmap(regs); } diff --git a/include/soc/canaan/k210-sysctl.h b/include/soc/canaan/k210-sysctl.h new file mode 100644 index 000000000000..2e037db68f35 --- /dev/null +++ b/include/soc/canaan/k210-sysctl.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019-20 Sean Anderson + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + */ +#ifndef K210_SYSCTL_H +#define K210_SYSCTL_H + +/* + * Kendryte K210 SoC system controller registers offsets. + * Taken from Kendryte SDK (kendryte-standalone-sdk). + */ +#define K210_SYSCTL_GIT_ID 0x00 /* Git short commit id */ +#define K210_SYSCTL_UART_BAUD 0x04 /* Default UARTHS baud rate */ +#define K210_SYSCTL_PLL0 0x08 /* PLL0 controller */ +#define K210_SYSCTL_PLL1 0x0C /* PLL1 controller */ +#define K210_SYSCTL_PLL2 0x10 /* PLL2 controller */ +#define K210_SYSCTL_PLL_LOCK 0x18 /* PLL lock tester */ +#define K210_SYSCTL_ROM_ERROR 0x1C /* AXI ROM detector */ +#define K210_SYSCTL_SEL0 0x20 /* Clock select controller 0 */ +#define K210_SYSCTL_SEL1 0x24 /* Clock select controller 1 */ +#define K210_SYSCTL_EN_CENT 0x28 /* Central clock enable */ +#define K210_SYSCTL_EN_PERI 0x2C /* Peripheral clock enable */ +#define K210_SYSCTL_SOFT_RESET 0x30 /* Soft reset ctrl */ +#define K210_SYSCTL_PERI_RESET 0x34 /* Peripheral reset controller */ +#define K210_SYSCTL_THR0 0x38 /* Clock threshold controller 0 */ +#define K210_SYSCTL_THR1 0x3C /* Clock threshold controller 1 */ +#define K210_SYSCTL_THR2 0x40 /* Clock threshold controller 2 */ +#define K210_SYSCTL_THR3 0x44 /* Clock threshold controller 3 */ +#define K210_SYSCTL_THR4 0x48 /* Clock threshold controller 4 */ +#define K210_SYSCTL_THR5 0x4C /* Clock threshold controller 5 */ +#define K210_SYSCTL_THR6 0x50 /* Clock threshold controller 6 */ +#define K210_SYSCTL_MISC 0x54 /* Miscellaneous controller */ +#define K210_SYSCTL_PERI 0x58 /* Peripheral controller */ +#define K210_SYSCTL_SPI_SLEEP 0x5C /* SPI sleep controller */ +#define K210_SYSCTL_RESET_STAT 0x60 /* Reset source status */ +#define K210_SYSCTL_DMA_SEL0 0x64 /* DMA handshake selector 0 */ +#define K210_SYSCTL_DMA_SEL1 0x68 /* DMA handshake selector 1 */ +#define K210_SYSCTL_POWER_SEL 0x6C /* IO Power Mode Select controller */ + +#endif -- cgit v1.2.3 From 5a2308da9f60312addfb5f7bdd15d96ba1299480 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Sun, 13 Dec 2020 22:50:47 +0900 Subject: riscv: Add Canaan Kendryte K210 reset controller Add a reset controller driver for the Canaan Kendryte K210 SoC. This driver relies on its syscon compatible parent node (sysctl) for its register mapping. Default this driver compilation to y when the SOC_CANAAN option is selected. The MAINTAINERS file is updated, adding the entry "CANAAN/KENDRYTE K210 SOC RESET CONTROLLER DRIVER" with myself listed as maintainer for this driver. Signed-off-by: Damien Le Moal Reviewed-by: Philipp Zabel Signed-off-by: Palmer Dabbelt --- MAINTAINERS | 8 +++ arch/riscv/Kconfig.socs | 1 + drivers/reset/Kconfig | 10 ++++ drivers/reset/Makefile | 1 + drivers/reset/reset-k210.c | 131 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 151 insertions(+) create mode 100644 drivers/reset/reset-k210.c (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 4aaa7a17016b..380a446d4d4d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3860,6 +3860,14 @@ W: https://github.com/Cascoda/ca8210-linux.git F: Documentation/devicetree/bindings/net/ieee802154/ca8210.txt F: drivers/net/ieee802154/ca8210.c +CANAAN/KENDRYTE K210 SOC RESET CONTROLLER DRIVER +M: Damien Le Moal +L: linux-kernel@vger.kernel.org +L: linux-riscv@lists.infradead.org +S: Maintained +F: Documentation/devicetree/bindings/reset/canaan,k210-rst.yaml +F: drivers/reset/reset-k210.c + CANAAN/KENDRYTE K210 SOC SYSTEM CONTROLLER DRIVER M: Damien Le Moal L: linux-riscv@lists.infradead.org diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index 027042e4d0af..57e53219c500 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -29,6 +29,7 @@ config SOC_CANAAN select SERIAL_SIFIVE if TTY select SERIAL_SIFIVE_CONSOLE if TTY select SIFIVE_PLIC + select ARCH_HAS_RESET_CONTROLLER help This enables support for Canaan Kendryte K210 SoC platform hardware. diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 71ab75a46491..3db04991a16b 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -89,6 +89,16 @@ config RESET_INTEL_GW Say Y to control the reset signals provided by reset controller. Otherwise, say N. +config RESET_K210 + bool "Reset controller driver for Canaan Kendryte K210 SoC" + depends on (SOC_CANAAN || COMPILE_TEST) && OF + select MFD_SYSCON + default SOC_CANAAN + help + Support for the Canaan Kendryte K210 RISC-V SoC reset controller. + Say Y if you want to control reset signals provided by this + controller. + config RESET_LANTIQ bool "Lantiq XWAY Reset Driver" if COMPILE_TEST default SOC_TYPE_XWAY diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 1054123fd187..65a118a91b27 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o obj-$(CONFIG_RESET_IMX7) += reset-imx7.o obj-$(CONFIG_RESET_INTEL_GW) += reset-intel-gw.o +obj-$(CONFIG_RESET_K210) += reset-k210.o obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o obj-$(CONFIG_RESET_MESON) += reset-meson.o diff --git a/drivers/reset/reset-k210.c b/drivers/reset/reset-k210.c new file mode 100644 index 000000000000..1b6e03522b40 --- /dev/null +++ b/drivers/reset/reset-k210.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define K210_RST_MASK 0x27FFFFFF + +struct k210_rst { + struct regmap *map; + struct reset_controller_dev rcdev; +}; + +static inline struct k210_rst * +to_k210_rst(struct reset_controller_dev *rcdev) +{ + return container_of(rcdev, struct k210_rst, rcdev); +} + +static inline int k210_rst_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct k210_rst *ksr = to_k210_rst(rcdev); + + return regmap_update_bits(ksr->map, K210_SYSCTL_PERI_RESET, BIT(id), 1); +} + +static inline int k210_rst_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct k210_rst *ksr = to_k210_rst(rcdev); + + return regmap_update_bits(ksr->map, K210_SYSCTL_PERI_RESET, BIT(id), 0); +} + +static int k210_rst_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + int ret; + + ret = k210_rst_assert(rcdev, id); + if (ret == 0) { + udelay(10); + ret = k210_rst_deassert(rcdev, id); + } + + return ret; +} + +static int k210_rst_status(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct k210_rst *ksr = to_k210_rst(rcdev); + u32 reg, bit = BIT(id); + int ret; + + ret = regmap_read(ksr->map, K210_SYSCTL_PERI_RESET, ®); + if (ret) + return ret; + + return reg & bit; +} + +static int k210_rst_xlate(struct reset_controller_dev *rcdev, + const struct of_phandle_args *reset_spec) +{ + unsigned long id = reset_spec->args[0]; + + if (!(BIT(id) & K210_RST_MASK)) + return -EINVAL; + + return id; +} + +static const struct reset_control_ops k210_rst_ops = { + .assert = k210_rst_assert, + .deassert = k210_rst_deassert, + .reset = k210_rst_reset, + .status = k210_rst_status, +}; + +static int k210_rst_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *parent_np = of_get_parent(dev->of_node); + struct k210_rst *ksr; + + dev_info(dev, "K210 reset controller\n"); + + ksr = devm_kzalloc(dev, sizeof(*ksr), GFP_KERNEL); + if (!ksr) + return -ENOMEM; + + ksr->map = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); + if (IS_ERR(ksr->map)) + return PTR_ERR(ksr->map); + + ksr->rcdev.owner = THIS_MODULE; + ksr->rcdev.dev = dev; + ksr->rcdev.of_node = dev->of_node; + ksr->rcdev.ops = &k210_rst_ops; + ksr->rcdev.nr_resets = fls(K210_RST_MASK); + ksr->rcdev.of_reset_n_cells = 1; + ksr->rcdev.of_xlate = k210_rst_xlate; + + return devm_reset_controller_register(dev, &ksr->rcdev); +} + +static const struct of_device_id k210_rst_dt_ids[] = { + { .compatible = "canaan,k210-rst" }, + { /* sentinel */ }, +}; + +static struct platform_driver k210_rst_driver = { + .probe = k210_rst_probe, + .driver = { + .name = "k210-rst", + .of_match_table = k210_rst_dt_ids, + }, +}; +builtin_platform_driver(k210_rst_driver); -- cgit v1.2.3 From c219624c50d57e45d0e9d5345eb1c47ab5523b85 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Sun, 17 Jan 2021 12:42:58 +0530 Subject: MAINTAINERS: soundwire: Add soundwire tree Somehow the soundwire MAINTAINERS did not have the tree details, so add it. Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20210117071258.2541484-1-vkoul@kernel.org Signed-off-by: Vinod Koul --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 546aa66428c9..10b234688f22 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16654,6 +16654,7 @@ R: Pierre-Louis Bossart R: Sanyog Kale L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Supported +T: git git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire.git F: Documentation/driver-api/soundwire/ F: drivers/soundwire/ F: include/linux/soundwire/ -- cgit v1.2.3 From 68f1fae62c37ff739c38ac812165cbbab85b65d4 Mon Sep 17 00:00:00 2001 From: Scott Branden Date: Wed, 20 Jan 2021 09:58:26 -0800 Subject: MAINTAINERS: bcm-vk: add maintainer for Broadcom VK Driver Add maintainer entry for new Broadcom VK Driver Acked-by: Olof Johansson Signed-off-by: Scott Branden Link: https://lore.kernel.org/r/20210120175827.14820-13-scott.branden@broadcom.com Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 93d182e4808d..23273a59da6f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3744,6 +3744,13 @@ L: netdev@vger.kernel.org S: Supported F: drivers/net/ethernet/broadcom/tg3.* +BROADCOM VK DRIVER +M: Scott Branden +L: bcm-kernel-feedback-list@broadcom.com +S: Supported +F: drivers/misc/bcm-vk/ +F: include/uapi/linux/misc/bcm_vk.h + BROCADE BFA FC SCSI DRIVER M: Anil Gurumurthy M: Sudarsana Kalluru -- cgit v1.2.3 From 41116775f12cb8c45385525d363ea244e07e4c73 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Sun, 17 Jan 2021 12:38:04 +0530 Subject: MAINTAINERS: dmaengine: add header files directory Somehow dmaengine header files are missed in the entry so update it Link: https://lore.kernel.org/r/20210117070804.2539698-1-vkoul@kernel.org Signed-off-by: Vinod Koul --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 0d62310a31f8..df68078e1da8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5281,6 +5281,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git F: Documentation/devicetree/bindings/dma/ F: Documentation/driver-api/dmaengine/ F: drivers/dma/ +F: include/linux/dma/ F: include/linux/dmaengine.h F: include/linux/of_dma.h -- cgit v1.2.3 From 5699bba18631dcb17588d18be14d3b6c8f44a284 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Sun, 17 Jan 2021 12:32:29 +0530 Subject: MAINTAINERS: ioat: remove dmaengine susbstem files [1] mentions the IOAT entry contains dmaengine subsystem file. So update the entry and remove the dmaengine files 1: https://lwn.net/Articles/842415/ Link: https://lore.kernel.org/r/20210117070229.2537866-1-vkoul@kernel.org Signed-off-by: Vinod Koul --- MAINTAINERS | 2 -- 1 file changed, 2 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index df68078e1da8..882dcc9023c0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2872,9 +2872,7 @@ S: Odd fixes W: http://sourceforge.net/projects/xscaleiop F: Documentation/crypto/async-tx-api.rst F: crypto/async_tx/ -F: drivers/dma/ F: include/linux/async_tx.h -F: include/linux/dmaengine.h AT24 EEPROM DRIVER M: Bartosz Golaszewski -- cgit v1.2.3 From 8544717cdacc2f33f0f53a3b34c5125b37e13ce9 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Thu, 14 Jan 2021 19:07:48 +0200 Subject: bus: fsl-mc: move fsl_mc_command struct in a uapi header Define "struct fsl_mc_command" as a structure that can cross the user/kernel boundary. Acked-by: Laurentiu Tudor Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/20210114170752.2927915-2-ciorneiioana@gmail.com Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 1 + include/linux/fsl/mc.h | 8 +------- include/uapi/linux/fsl_mc.h | 25 +++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 include/uapi/linux/fsl_mc.h (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 23273a59da6f..128455811980 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14652,6 +14652,7 @@ S: Maintained F: Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt F: Documentation/networking/device_drivers/ethernet/freescale/dpaa2/overview.rst F: drivers/bus/fsl-mc/ +F: include/uapi/linux/fsl_mc.h QT1010 MEDIA DRIVER M: Antti Palosaari diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h index db244874e834..63b56aba925a 100644 --- a/include/linux/fsl/mc.h +++ b/include/linux/fsl/mc.h @@ -13,6 +13,7 @@ #include #include #include +#include #define FSL_MC_VENDOR_FREESCALE 0x1957 @@ -209,8 +210,6 @@ struct fsl_mc_device { #define to_fsl_mc_device(_dev) \ container_of(_dev, struct fsl_mc_device, dev) -#define MC_CMD_NUM_OF_PARAMS 7 - struct mc_cmd_header { u8 src_id; u8 flags_hw; @@ -220,11 +219,6 @@ struct mc_cmd_header { __le16 cmd_id; }; -struct fsl_mc_command { - __le64 header; - __le64 params[MC_CMD_NUM_OF_PARAMS]; -}; - enum mc_cmd_status { MC_CMD_STATUS_OK = 0x0, /* Completed successfully */ MC_CMD_STATUS_READY = 0x1, /* Ready to be processed */ diff --git a/include/uapi/linux/fsl_mc.h b/include/uapi/linux/fsl_mc.h new file mode 100644 index 000000000000..cf56d46f052e --- /dev/null +++ b/include/uapi/linux/fsl_mc.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Management Complex (MC) userspace public interface + * + * Copyright 2021 NXP + * + */ +#ifndef _UAPI_FSL_MC_H_ +#define _UAPI_FSL_MC_H_ + +#include + +#define MC_CMD_NUM_OF_PARAMS 7 + +/** + * struct fsl_mc_command - Management Complex (MC) command structure + * @header: MC command header + * @params: MC command parameters + */ +struct fsl_mc_command { + __le64 header; + __le64 params[MC_CMD_NUM_OF_PARAMS]; +}; + +#endif /* _UAPI_FSL_MC_H_ */ -- cgit v1.2.3 From 3f6099438181d269d56f9d4040d93ffae65f9e4c Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Thu, 14 Jan 2021 19:07:51 +0200 Subject: bus: fsl-mc: add bus rescan attribute Introduce the rescan attribute as a bus attribute to synchronize the fsl-mc bus objects and the MC firmware. To rescan the fsl-mc bus, e.g., echo 1 > /sys/bus/fsl-mc/rescan Acked-by: Laurentiu Tudor Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/20210114170752.2927915-5-ciorneiioana@gmail.com Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/stable/sysfs-bus-fsl-mc | 9 +++++++ MAINTAINERS | 1 + drivers/bus/fsl-mc/dprc-driver.c | 4 +-- drivers/bus/fsl-mc/fsl-mc-bus.c | 41 +++++++++++++++++++++++++++++++ drivers/bus/fsl-mc/fsl-mc-private.h | 3 +++ 5 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 Documentation/ABI/stable/sysfs-bus-fsl-mc (limited to 'MAINTAINERS') diff --git a/Documentation/ABI/stable/sysfs-bus-fsl-mc b/Documentation/ABI/stable/sysfs-bus-fsl-mc new file mode 100644 index 000000000000..a4d384df9ba8 --- /dev/null +++ b/Documentation/ABI/stable/sysfs-bus-fsl-mc @@ -0,0 +1,9 @@ +What: /sys/bus/fsl-mc/rescan +Date: January 2021 +KernelVersion: 5.12 +Contact: Ioana Ciornei +Description: Writing a non-zero value to this attribute will + force a rescan of fsl-mc bus in the system and + synchronize the objects under fsl-mc bus and the + Management Complex firmware. +Users: Userspace drivers and management tools diff --git a/MAINTAINERS b/MAINTAINERS index 128455811980..1d9d112af51a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14649,6 +14649,7 @@ M: Stuart Yoder M: Laurentiu Tudor L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/ABI/stable/sysfs-bus-fsl-mc F: Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt F: Documentation/networking/device_drivers/ethernet/freescale/dpaa2/overview.rst F: drivers/bus/fsl-mc/ diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c index ccec375095f2..4adb6f318884 100644 --- a/drivers/bus/fsl-mc/dprc-driver.c +++ b/drivers/bus/fsl-mc/dprc-driver.c @@ -237,8 +237,8 @@ static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev, * populated before they can get allocation requests from probe callbacks * of the device drivers for the non-allocatable devices. */ -static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, - bool alloc_interrupts) +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, + bool alloc_interrupts) { int num_child_objects; int dprc_get_obj_failures; diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c index 5a8fc68d6109..ee3e6252ffc3 100644 --- a/drivers/bus/fsl-mc/fsl-mc-bus.c +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c @@ -208,12 +208,53 @@ static struct attribute *fsl_mc_dev_attrs[] = { ATTRIBUTE_GROUPS(fsl_mc_dev); +static int scan_fsl_mc_bus(struct device *dev, void *data) +{ + struct fsl_mc_device *root_mc_dev; + struct fsl_mc_bus *root_mc_bus; + + if (!fsl_mc_is_root_dprc(dev)) + goto exit; + + root_mc_dev = to_fsl_mc_device(dev); + root_mc_bus = to_fsl_mc_bus(root_mc_dev); + mutex_lock(&root_mc_bus->scan_mutex); + dprc_scan_objects(root_mc_dev, NULL); + mutex_unlock(&root_mc_bus->scan_mutex); + +exit: + return 0; +} + +static ssize_t rescan_store(struct bus_type *bus, + const char *buf, size_t count) +{ + unsigned long val; + + if (kstrtoul(buf, 0, &val) < 0) + return -EINVAL; + + if (val) + bus_for_each_dev(bus, NULL, NULL, scan_fsl_mc_bus); + + return count; +} +static BUS_ATTR_WO(rescan); + +static struct attribute *fsl_mc_bus_attrs[] = { + &bus_attr_rescan.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(fsl_mc_bus); + struct bus_type fsl_mc_bus_type = { .name = "fsl-mc", .match = fsl_mc_bus_match, .uevent = fsl_mc_bus_uevent, .dma_configure = fsl_mc_dma_configure, .dev_groups = fsl_mc_dev_groups, + .bus_groups = fsl_mc_bus_groups, }; EXPORT_SYMBOL_GPL(fsl_mc_bus_type); diff --git a/drivers/bus/fsl-mc/fsl-mc-private.h b/drivers/bus/fsl-mc/fsl-mc-private.h index 6293a24de456..42bdb8679a36 100644 --- a/drivers/bus/fsl-mc/fsl-mc-private.h +++ b/drivers/bus/fsl-mc/fsl-mc-private.h @@ -594,6 +594,9 @@ int __init dprc_driver_init(void); void dprc_driver_exit(void); +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, + bool alloc_interrupts); + int __init fsl_mc_allocator_driver_init(void); void fsl_mc_allocator_driver_exit(void); -- cgit v1.2.3 From 2a0c106a671b2582f7d74cce4e48fd1a9dc7e8c9 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 21 Jan 2021 17:33:50 -0600 Subject: MAINTAINERS: Fix 'ARM/TEXAS INSTRUMENT KEYSTONE CLOCKSOURCE' capitalization Fix capitalization typo in 'ARM/TEXAS INSTRUMENT KEYSTONE CLOCKSOURCE'. Signed-off-by: Bjorn Helgaas --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index cc1e6a5ee6e6..52311efad03e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2603,7 +2603,7 @@ L: linux-kernel@vger.kernel.org S: Maintained F: drivers/clk/keystone/ -ARM/TEXAS INSTRUMENT KEYSTONE ClOCKSOURCE +ARM/TEXAS INSTRUMENT KEYSTONE CLOCKSOURCE M: Santosh Shilimkar L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-kernel@vger.kernel.org -- cgit v1.2.3 From c619a804cc43345be3a1a1c4b46f72a3525cf1af Mon Sep 17 00:00:00 2001 From: Shuo Liu Date: Sun, 7 Feb 2021 11:10:23 +0800 Subject: docs: acrn: Introduce ACRN Add documentation on the following aspects of ACRN: 1) A brief introduction on the architecture of ACRN. 2) I/O request handling in ACRN. 3) CPUID functions of ACRN. To learn more about ACRN, please go to ACRN project website https://projectacrn.org, or the documentation page https://projectacrn.github.io/. Cc: Dave Hansen Cc: Sen Christopherson Cc: Dan Williams Cc: Fengwei Yin Cc: Zhi Wang Cc: Zhenyu Wang Cc: Yu Wang Cc: Reinette Chatre Cc: Greg Kroah-Hartman Cc: Randy Dunlap Reviewed-by: Zhi Wang Reviewed-by: Reinette Chatre Reviewed-by: Borislav Petkov Signed-off-by: Shuo Liu Link: https://lore.kernel.org/r/20210207031040.49576-2-shuo.a.liu@intel.com Signed-off-by: Greg Kroah-Hartman --- Documentation/virt/acrn/cpuid.rst | 46 +++++++++++++++ Documentation/virt/acrn/index.rst | 12 ++++ Documentation/virt/acrn/introduction.rst | 43 ++++++++++++++ Documentation/virt/acrn/io-request.rst | 97 ++++++++++++++++++++++++++++++++ Documentation/virt/index.rst | 1 + MAINTAINERS | 7 +++ 6 files changed, 206 insertions(+) create mode 100644 Documentation/virt/acrn/cpuid.rst create mode 100644 Documentation/virt/acrn/index.rst create mode 100644 Documentation/virt/acrn/introduction.rst create mode 100644 Documentation/virt/acrn/io-request.rst (limited to 'MAINTAINERS') diff --git a/Documentation/virt/acrn/cpuid.rst b/Documentation/virt/acrn/cpuid.rst new file mode 100644 index 000000000000..65fa4b9c1798 --- /dev/null +++ b/Documentation/virt/acrn/cpuid.rst @@ -0,0 +1,46 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=============== +ACRN CPUID bits +=============== + +A guest VM running on an ACRN hypervisor can check some of its features using +CPUID. + +ACRN cpuid functions are: + +function: 0x40000000 + +returns:: + + eax = 0x40000010 + ebx = 0x4e524341 + ecx = 0x4e524341 + edx = 0x4e524341 + +Note that this value in ebx, ecx and edx corresponds to the string +"ACRNACRNACRN". The value in eax corresponds to the maximum cpuid function +present in this leaf, and will be updated if more functions are added in the +future. + +function: define ACRN_CPUID_FEATURES (0x40000001) + +returns:: + + ebx, ecx, edx + eax = an OR'ed group of (1 << flag) + +where ``flag`` is defined as below: + +================================= =========== ================================ +flag value meaning +================================= =========== ================================ +ACRN_FEATURE_PRIVILEGED_VM 0 guest VM is a privileged VM +================================= =========== ================================ + +function: 0x40000010 + +returns:: + + ebx, ecx, edx + eax = (Virtual) TSC frequency in kHz. diff --git a/Documentation/virt/acrn/index.rst b/Documentation/virt/acrn/index.rst new file mode 100644 index 000000000000..b5f793e73df5 --- /dev/null +++ b/Documentation/virt/acrn/index.rst @@ -0,0 +1,12 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=============== +ACRN Hypervisor +=============== + +.. toctree:: + :maxdepth: 1 + + introduction + io-request + cpuid diff --git a/Documentation/virt/acrn/introduction.rst b/Documentation/virt/acrn/introduction.rst new file mode 100644 index 000000000000..f8d081bc084d --- /dev/null +++ b/Documentation/virt/acrn/introduction.rst @@ -0,0 +1,43 @@ +.. SPDX-License-Identifier: GPL-2.0 + +ACRN Hypervisor Introduction +============================ + +The ACRN Hypervisor is a Type 1 hypervisor, running directly on bare-metal +hardware. It has a privileged management VM, called Service VM, to manage User +VMs and do I/O emulation. + +ACRN userspace is an application running in the Service VM that emulates +devices for a User VM based on command line configurations. ACRN Hypervisor +Service Module (HSM) is a kernel module in the Service VM which provides +hypervisor services to the ACRN userspace. + +Below figure shows the architecture. + +:: + + Service VM User VM + +----------------------------+ | +------------------+ + | +--------------+ | | | | + | |ACRN userspace| | | | | + | +--------------+ | | | | + |-----------------ioctl------| | | | ... + |kernel space +----------+ | | | | + | | HSM | | | | Drivers | + | +----------+ | | | | + +--------------------|-------+ | +------------------+ + +---------------------hypercall----------------------------------------+ + | ACRN Hypervisor | + +----------------------------------------------------------------------+ + | Hardware | + +----------------------------------------------------------------------+ + +ACRN userspace allocates memory for the User VM, configures and initializes the +devices used by the User VM, loads the virtual bootloader, initializes the +virtual CPU state and handles I/O request accesses from the User VM. It uses +ioctls to communicate with the HSM. HSM implements hypervisor services by +interacting with the ACRN Hypervisor via hypercalls. HSM exports a char device +interface (/dev/acrn_hsm) to userspace. + +The ACRN hypervisor is open for contribution from anyone. The source repo is +available at https://github.com/projectacrn/acrn-hypervisor. diff --git a/Documentation/virt/acrn/io-request.rst b/Documentation/virt/acrn/io-request.rst new file mode 100644 index 000000000000..6cc3ea0fa1f5 --- /dev/null +++ b/Documentation/virt/acrn/io-request.rst @@ -0,0 +1,97 @@ +.. SPDX-License-Identifier: GPL-2.0 + +I/O request handling +==================== + +An I/O request of a User VM, which is constructed by the hypervisor, is +distributed by the ACRN Hypervisor Service Module to an I/O client +corresponding to the address range of the I/O request. Details of I/O request +handling are described in the following sections. + +1. I/O request +-------------- + +For each User VM, there is a shared 4-KByte memory region used for I/O requests +communication between the hypervisor and Service VM. An I/O request is a +256-byte structure buffer, which is 'struct acrn_io_request', that is filled by +an I/O handler of the hypervisor when a trapped I/O access happens in a User +VM. ACRN userspace in the Service VM first allocates a 4-KByte page and passes +the GPA (Guest Physical Address) of the buffer to the hypervisor. The buffer is +used as an array of 16 I/O request slots with each I/O request slot being 256 +bytes. This array is indexed by vCPU ID. + +2. I/O clients +-------------- + +An I/O client is responsible for handling User VM I/O requests whose accessed +GPA falls in a certain range. Multiple I/O clients can be associated with each +User VM. There is a special client associated with each User VM, called the +default client, that handles all I/O requests that do not fit into the range of +any other clients. The ACRN userspace acts as the default client for each User +VM. + +Below illustration shows the relationship between I/O requests shared buffer, +I/O requests and I/O clients. + +:: + + +------------------------------------------------------+ + | Service VM | + |+--------------------------------------------------+ | + || +----------------------------------------+ | | + || | shared page ACRN userspace | | | + || | +-----------------+ +------------+ | | | + || +----+->| acrn_io_request |<-+ default | | | | + || | | | +-----------------+ | I/O client | | | | + || | | | | ... | +------------+ | | | + || | | | +-----------------+ | | | + || | +-|--------------------------------------+ | | + ||---|----|-----------------------------------------| | + || | | kernel | | + || | | +----------------------+ | | + || | | | +-------------+ HSM | | | + || | +--------------+ | | | | + || | | | I/O clients | | | | + || | | | | | | | + || | | +-------------+ | | | + || | +----------------------+ | | + |+---|----------------------------------------------+ | + +----|-------------------------------------------------+ + | + +----|-------------------------------------------------+ + | +-+-----------+ | + | | I/O handler | ACRN Hypervisor | + | +-------------+ | + +------------------------------------------------------+ + +3. I/O request state transition +------------------------------- + +The state transitions of an ACRN I/O request are as follows. + +:: + + FREE -> PENDING -> PROCESSING -> COMPLETE -> FREE -> ... + +- FREE: this I/O request slot is empty +- PENDING: a valid I/O request is pending in this slot +- PROCESSING: the I/O request is being processed +- COMPLETE: the I/O request has been processed + +An I/O request in COMPLETE or FREE state is owned by the hypervisor. HSM and +ACRN userspace are in charge of processing the others. + +4. Processing flow of I/O requests +---------------------------------- + +a. The I/O handler of the hypervisor will fill an I/O request with PENDING + state when a trapped I/O access happens in a User VM. +b. The hypervisor makes an upcall, which is a notification interrupt, to + the Service VM. +c. The upcall handler schedules a worker to dispatch I/O requests. +d. The worker looks for the PENDING I/O requests, assigns them to different + registered clients based on the address of the I/O accesses, updates + their state to PROCESSING, and notifies the corresponding client to handle. +e. The notified client handles the assigned I/O requests. +f. The HSM updates I/O requests states to COMPLETE and notifies the hypervisor + of the completion via hypercalls. diff --git a/Documentation/virt/index.rst b/Documentation/virt/index.rst index 350f5c869b56..edea7fea95a8 100644 --- a/Documentation/virt/index.rst +++ b/Documentation/virt/index.rst @@ -12,6 +12,7 @@ Linux Virtualization Support paravirt_ops guest-halt-polling ne_overview + acrn/index .. only:: html and subproject diff --git a/MAINTAINERS b/MAINTAINERS index a6f1f5889346..6a3d11233d3c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -436,6 +436,13 @@ S: Orphan F: drivers/platform/x86/wmi.c F: include/uapi/linux/wmi.h +ACRN HYPERVISOR SERVICE MODULE +M: Shuo Liu +L: acrn-dev@lists.projectacrn.org +S: Supported +W: https://projectacrn.org +F: Documentation/virt/acrn/ + AD1889 ALSA SOUND DRIVER L: linux-parisc@vger.kernel.org S: Maintained -- cgit v1.2.3 From 666834c47d3b41da550bbcbc709148e5fc14879c Mon Sep 17 00:00:00 2001 From: Shuo Liu Date: Sun, 7 Feb 2021 11:10:27 +0800 Subject: virt: acrn: Introduce ACRN HSM basic driver ACRN Hypervisor Service Module (HSM) is a kernel module in Service VM which communicates with ACRN userspace through ioctls and talks to ACRN Hypervisor through hypercalls. Add a basic HSM driver which allows Service VM userspace to communicate with ACRN. The following patches will add more ioctls, guest VM memory mapping caching, I/O request processing, ioeventfd and irqfd into this module. HSM exports a char device interface (/dev/acrn_hsm) to userspace. Cc: Dave Hansen Cc: Zhi Wang Cc: Zhenyu Wang Cc: Yu Wang Cc: Reinette Chatre Cc: Greg Kroah-Hartman Reviewed-by: Reinette Chatre Signed-off-by: Shuo Liu Link: https://lore.kernel.org/r/20210207031040.49576-6-shuo.a.liu@intel.com Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 1 + drivers/virt/Kconfig | 2 + drivers/virt/Makefile | 1 + drivers/virt/acrn/Kconfig | 14 +++++++ drivers/virt/acrn/Makefile | 3 ++ drivers/virt/acrn/acrn_drv.h | 18 +++++++++ drivers/virt/acrn/hsm.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 126 insertions(+) create mode 100644 drivers/virt/acrn/Kconfig create mode 100644 drivers/virt/acrn/Makefile create mode 100644 drivers/virt/acrn/acrn_drv.h create mode 100644 drivers/virt/acrn/hsm.c (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 6a3d11233d3c..4ac781da514f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -442,6 +442,7 @@ L: acrn-dev@lists.projectacrn.org S: Supported W: https://projectacrn.org F: Documentation/virt/acrn/ +F: drivers/virt/acrn/ AD1889 ALSA SOUND DRIVER L: linux-parisc@vger.kernel.org diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig index 80c5f9c16ec1..8061e8ef449f 100644 --- a/drivers/virt/Kconfig +++ b/drivers/virt/Kconfig @@ -34,4 +34,6 @@ config FSL_HV_MANAGER source "drivers/virt/vboxguest/Kconfig" source "drivers/virt/nitro_enclaves/Kconfig" + +source "drivers/virt/acrn/Kconfig" endif diff --git a/drivers/virt/Makefile b/drivers/virt/Makefile index f28425ce4b39..3e272ea60cd9 100644 --- a/drivers/virt/Makefile +++ b/drivers/virt/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_FSL_HV_MANAGER) += fsl_hypervisor.o obj-y += vboxguest/ obj-$(CONFIG_NITRO_ENCLAVES) += nitro_enclaves/ +obj-$(CONFIG_ACRN_HSM) += acrn/ diff --git a/drivers/virt/acrn/Kconfig b/drivers/virt/acrn/Kconfig new file mode 100644 index 000000000000..36c80378c30c --- /dev/null +++ b/drivers/virt/acrn/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +config ACRN_HSM + tristate "ACRN Hypervisor Service Module" + depends on ACRN_GUEST + help + ACRN Hypervisor Service Module (HSM) is a kernel module which + communicates with ACRN userspace through ioctls and talks to + the ACRN Hypervisor through hypercalls. HSM will only run in + a privileged management VM, called Service VM, to manage User + VMs and do I/O emulation. Not required for simply running + under ACRN as a User VM. + + To compile as a module, choose M, the module will be called + acrn. If unsure, say N. diff --git a/drivers/virt/acrn/Makefile b/drivers/virt/acrn/Makefile new file mode 100644 index 000000000000..6920ed798aaf --- /dev/null +++ b/drivers/virt/acrn/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_ACRN_HSM) := acrn.o +acrn-y := hsm.o diff --git a/drivers/virt/acrn/acrn_drv.h b/drivers/virt/acrn/acrn_drv.h new file mode 100644 index 000000000000..29eedd696327 --- /dev/null +++ b/drivers/virt/acrn/acrn_drv.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ACRN_HSM_DRV_H +#define __ACRN_HSM_DRV_H + +#include + +#define ACRN_INVALID_VMID (0xffffU) + +/** + * struct acrn_vm - Properties of ACRN User VM. + * @vmid: User VM ID + */ +struct acrn_vm { + u16 vmid; +}; + +#endif /* __ACRN_HSM_DRV_H */ diff --git a/drivers/virt/acrn/hsm.c b/drivers/virt/acrn/hsm.c new file mode 100644 index 000000000000..a8dcb250649d --- /dev/null +++ b/drivers/virt/acrn/hsm.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ACRN Hypervisor Service Module (HSM) + * + * Copyright (C) 2020 Intel Corporation. All rights reserved. + * + * Authors: + * Fengwei Yin + * Yakui Zhao + */ + +#include +#include +#include +#include + +#include +#include + +#include "acrn_drv.h" + +/* + * When /dev/acrn_hsm is opened, a 'struct acrn_vm' object is created to + * represent a VM instance and continues to be associated with the opened file + * descriptor. All ioctl operations on this file descriptor will be targeted to + * the VM instance. Release of this file descriptor will destroy the object. + */ +static int acrn_dev_open(struct inode *inode, struct file *filp) +{ + struct acrn_vm *vm; + + vm = kzalloc(sizeof(*vm), GFP_KERNEL); + if (!vm) + return -ENOMEM; + + vm->vmid = ACRN_INVALID_VMID; + filp->private_data = vm; + return 0; +} + +static int acrn_dev_release(struct inode *inode, struct file *filp) +{ + struct acrn_vm *vm = filp->private_data; + + kfree(vm); + return 0; +} + +static const struct file_operations acrn_fops = { + .owner = THIS_MODULE, + .open = acrn_dev_open, + .release = acrn_dev_release, +}; + +static struct miscdevice acrn_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "acrn_hsm", + .fops = &acrn_fops, +}; + +static int __init hsm_init(void) +{ + int ret; + + if (x86_hyper_type != X86_HYPER_ACRN) + return -ENODEV; + + if (!(cpuid_eax(ACRN_CPUID_FEATURES) & ACRN_FEATURE_PRIVILEGED_VM)) + return -EPERM; + + ret = misc_register(&acrn_dev); + if (ret) + pr_err("Create misc dev failed!\n"); + + return ret; +} + +static void __exit hsm_exit(void) +{ + misc_deregister(&acrn_dev); +} +module_init(hsm_init); +module_exit(hsm_exit); + +MODULE_AUTHOR("Intel Corporation"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ACRN Hypervisor Service Module (HSM)"); -- cgit v1.2.3 From 9c5137aedd112f78a968bdd2325de2ea06df46c0 Mon Sep 17 00:00:00 2001 From: Shuo Liu Date: Sun, 7 Feb 2021 11:10:28 +0800 Subject: virt: acrn: Introduce VM management interfaces The VM management interfaces expose several VM operations to ACRN userspace via ioctls. For example, creating VM, starting VM, destroying VM and so on. The ACRN Hypervisor needs to exchange data with the ACRN userspace during the VM operations. HSM provides VM operation ioctls to the ACRN userspace and communicates with the ACRN Hypervisor for VM operations via hypercalls. HSM maintains a list of User VM. Each User VM will be bound to an existing file descriptor of /dev/acrn_hsm. The User VM will be destroyed when the file descriptor is closed. Cc: Zhi Wang Cc: Zhenyu Wang Cc: Yu Wang Cc: Reinette Chatre Cc: Greg Kroah-Hartman Reviewed-by: Zhi Wang Reviewed-by: Reinette Chatre Signed-off-by: Shuo Liu Link: https://lore.kernel.org/r/20210207031040.49576-7-shuo.a.liu@intel.com Signed-off-by: Greg Kroah-Hartman --- Documentation/userspace-api/ioctl/ioctl-number.rst | 1 + MAINTAINERS | 1 + drivers/virt/acrn/Makefile | 2 +- drivers/virt/acrn/acrn_drv.h | 21 +++++- drivers/virt/acrn/hsm.c | 76 ++++++++++++++++++++- drivers/virt/acrn/hypercall.h | 78 ++++++++++++++++++++++ drivers/virt/acrn/vm.c | 68 +++++++++++++++++++ include/uapi/linux/acrn.h | 58 ++++++++++++++++ 8 files changed, 301 insertions(+), 4 deletions(-) create mode 100644 drivers/virt/acrn/hypercall.h create mode 100644 drivers/virt/acrn/vm.c create mode 100644 include/uapi/linux/acrn.h (limited to 'MAINTAINERS') diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 19d730f9d136..76c27dbae96b 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -320,6 +320,7 @@ Code Seq# Include File Comments 0xA0 all linux/sdp/sdp.h Industrial Device Project 0xA1 0 linux/vtpm_proxy.h TPM Emulator Proxy Driver +0xA2 all uapi/linux/acrn.h ACRN hypervisor 0xA3 80-8F Port ACL in development: 0xA3 90-9F linux/dtlk.h diff --git a/MAINTAINERS b/MAINTAINERS index 4ac781da514f..6b5990a28b44 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -443,6 +443,7 @@ S: Supported W: https://projectacrn.org F: Documentation/virt/acrn/ F: drivers/virt/acrn/ +F: include/uapi/linux/acrn.h AD1889 ALSA SOUND DRIVER L: linux-parisc@vger.kernel.org diff --git a/drivers/virt/acrn/Makefile b/drivers/virt/acrn/Makefile index 6920ed798aaf..cf8b4ed5e74e 100644 --- a/drivers/virt/acrn/Makefile +++ b/drivers/virt/acrn/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_ACRN_HSM) := acrn.o -acrn-y := hsm.o +acrn-y := hsm.o vm.o diff --git a/drivers/virt/acrn/acrn_drv.h b/drivers/virt/acrn/acrn_drv.h index 29eedd696327..e5aba86cad8c 100644 --- a/drivers/virt/acrn/acrn_drv.h +++ b/drivers/virt/acrn/acrn_drv.h @@ -3,16 +3,35 @@ #ifndef __ACRN_HSM_DRV_H #define __ACRN_HSM_DRV_H +#include +#include +#include #include +#include "hypercall.h" + +extern struct miscdevice acrn_dev; + #define ACRN_INVALID_VMID (0xffffU) +#define ACRN_VM_FLAG_DESTROYED 0U /** * struct acrn_vm - Properties of ACRN User VM. + * @list: Entry within global list of all VMs * @vmid: User VM ID + * @vcpu_num: Number of virtual CPUs in the VM + * @flags: Flags (ACRN_VM_FLAG_*) of the VM. This is VM flag management + * in HSM which is different from the &acrn_vm_creation.vm_flag. */ struct acrn_vm { - u16 vmid; + struct list_head list; + u16 vmid; + int vcpu_num; + unsigned long flags; }; +struct acrn_vm *acrn_vm_create(struct acrn_vm *vm, + struct acrn_vm_creation *vm_param); +int acrn_vm_destroy(struct acrn_vm *vm); + #endif /* __ACRN_HSM_DRV_H */ diff --git a/drivers/virt/acrn/hsm.c b/drivers/virt/acrn/hsm.c index a8dcb250649d..5fd933471683 100644 --- a/drivers/virt/acrn/hsm.c +++ b/drivers/virt/acrn/hsm.c @@ -9,7 +9,6 @@ * Yakui Zhao */ -#include #include #include #include @@ -38,10 +37,82 @@ static int acrn_dev_open(struct inode *inode, struct file *filp) return 0; } +/* + * HSM relies on hypercall layer of the ACRN hypervisor to do the + * sanity check against the input parameters. + */ +static long acrn_dev_ioctl(struct file *filp, unsigned int cmd, + unsigned long ioctl_param) +{ + struct acrn_vm *vm = filp->private_data; + struct acrn_vm_creation *vm_param; + int ret = 0; + + if (vm->vmid == ACRN_INVALID_VMID && cmd != ACRN_IOCTL_CREATE_VM) { + dev_dbg(acrn_dev.this_device, + "ioctl 0x%x: Invalid VM state!\n", cmd); + return -EINVAL; + } + + switch (cmd) { + case ACRN_IOCTL_CREATE_VM: + vm_param = memdup_user((void __user *)ioctl_param, + sizeof(struct acrn_vm_creation)); + if (IS_ERR(vm_param)) + return PTR_ERR(vm_param); + + if ((vm_param->reserved0 | vm_param->reserved1) != 0) + return -EINVAL; + + vm = acrn_vm_create(vm, vm_param); + if (!vm) { + ret = -EINVAL; + kfree(vm_param); + break; + } + + if (copy_to_user((void __user *)ioctl_param, vm_param, + sizeof(struct acrn_vm_creation))) { + acrn_vm_destroy(vm); + ret = -EFAULT; + } + + kfree(vm_param); + break; + case ACRN_IOCTL_START_VM: + ret = hcall_start_vm(vm->vmid); + if (ret < 0) + dev_dbg(acrn_dev.this_device, + "Failed to start VM %u!\n", vm->vmid); + break; + case ACRN_IOCTL_PAUSE_VM: + ret = hcall_pause_vm(vm->vmid); + if (ret < 0) + dev_dbg(acrn_dev.this_device, + "Failed to pause VM %u!\n", vm->vmid); + break; + case ACRN_IOCTL_RESET_VM: + ret = hcall_reset_vm(vm->vmid); + if (ret < 0) + dev_dbg(acrn_dev.this_device, + "Failed to restart VM %u!\n", vm->vmid); + break; + case ACRN_IOCTL_DESTROY_VM: + ret = acrn_vm_destroy(vm); + break; + default: + dev_dbg(acrn_dev.this_device, "Unknown IOCTL 0x%x!\n", cmd); + ret = -ENOTTY; + } + + return ret; +} + static int acrn_dev_release(struct inode *inode, struct file *filp) { struct acrn_vm *vm = filp->private_data; + acrn_vm_destroy(vm); kfree(vm); return 0; } @@ -50,9 +121,10 @@ static const struct file_operations acrn_fops = { .owner = THIS_MODULE, .open = acrn_dev_open, .release = acrn_dev_release, + .unlocked_ioctl = acrn_dev_ioctl, }; -static struct miscdevice acrn_dev = { +struct miscdevice acrn_dev = { .minor = MISC_DYNAMIC_MINOR, .name = "acrn_hsm", .fops = &acrn_fops, diff --git a/drivers/virt/acrn/hypercall.h b/drivers/virt/acrn/hypercall.h new file mode 100644 index 000000000000..426b66cadb1f --- /dev/null +++ b/drivers/virt/acrn/hypercall.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ACRN HSM: hypercalls of ACRN Hypervisor + */ +#ifndef __ACRN_HSM_HYPERCALL_H +#define __ACRN_HSM_HYPERCALL_H +#include + +/* + * Hypercall IDs of the ACRN Hypervisor + */ +#define _HC_ID(x, y) (((x) << 24) | (y)) + +#define HC_ID 0x80UL + +#define HC_ID_VM_BASE 0x10UL +#define HC_CREATE_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x00) +#define HC_DESTROY_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x01) +#define HC_START_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x02) +#define HC_PAUSE_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x03) +#define HC_RESET_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x05) + +/** + * hcall_create_vm() - Create a User VM + * @vminfo: Service VM GPA of info of User VM creation + * + * Return: 0 on success, <0 on failure + */ +static inline long hcall_create_vm(u64 vminfo) +{ + return acrn_hypercall1(HC_CREATE_VM, vminfo); +} + +/** + * hcall_start_vm() - Start a User VM + * @vmid: User VM ID + * + * Return: 0 on success, <0 on failure + */ +static inline long hcall_start_vm(u64 vmid) +{ + return acrn_hypercall1(HC_START_VM, vmid); +} + +/** + * hcall_pause_vm() - Pause a User VM + * @vmid: User VM ID + * + * Return: 0 on success, <0 on failure + */ +static inline long hcall_pause_vm(u64 vmid) +{ + return acrn_hypercall1(HC_PAUSE_VM, vmid); +} + +/** + * hcall_destroy_vm() - Destroy a User VM + * @vmid: User VM ID + * + * Return: 0 on success, <0 on failure + */ +static inline long hcall_destroy_vm(u64 vmid) +{ + return acrn_hypercall1(HC_DESTROY_VM, vmid); +} + +/** + * hcall_reset_vm() - Reset a User VM + * @vmid: User VM ID + * + * Return: 0 on success, <0 on failure + */ +static inline long hcall_reset_vm(u64 vmid) +{ + return acrn_hypercall1(HC_RESET_VM, vmid); +} + +#endif /* __ACRN_HSM_HYPERCALL_H */ diff --git a/drivers/virt/acrn/vm.c b/drivers/virt/acrn/vm.c new file mode 100644 index 000000000000..3f667ac8ac1e --- /dev/null +++ b/drivers/virt/acrn/vm.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ACRN_HSM: Virtual Machine management + * + * Copyright (C) 2020 Intel Corporation. All rights reserved. + * + * Authors: + * Jason Chen CJ + * Yakui Zhao + */ +#include +#include +#include + +#include "acrn_drv.h" + +/* List of VMs */ +static LIST_HEAD(acrn_vm_list); +/* To protect acrn_vm_list */ +static DEFINE_MUTEX(acrn_vm_list_lock); + +struct acrn_vm *acrn_vm_create(struct acrn_vm *vm, + struct acrn_vm_creation *vm_param) +{ + int ret; + + ret = hcall_create_vm(virt_to_phys(vm_param)); + if (ret < 0 || vm_param->vmid == ACRN_INVALID_VMID) { + dev_err(acrn_dev.this_device, + "Failed to create VM! Error: %d\n", ret); + return NULL; + } + + vm->vmid = vm_param->vmid; + vm->vcpu_num = vm_param->vcpu_num; + + mutex_lock(&acrn_vm_list_lock); + list_add(&vm->list, &acrn_vm_list); + mutex_unlock(&acrn_vm_list_lock); + + dev_dbg(acrn_dev.this_device, "VM %u created.\n", vm->vmid); + return vm; +} + +int acrn_vm_destroy(struct acrn_vm *vm) +{ + int ret; + + if (vm->vmid == ACRN_INVALID_VMID || + test_and_set_bit(ACRN_VM_FLAG_DESTROYED, &vm->flags)) + return 0; + + /* Remove from global VM list */ + mutex_lock(&acrn_vm_list_lock); + list_del_init(&vm->list); + mutex_unlock(&acrn_vm_list_lock); + + ret = hcall_destroy_vm(vm->vmid); + if (ret < 0) { + dev_err(acrn_dev.this_device, + "Failed to destroy VM %u\n", vm->vmid); + clear_bit(ACRN_VM_FLAG_DESTROYED, &vm->flags); + return ret; + } + dev_dbg(acrn_dev.this_device, "VM %u destroyed.\n", vm->vmid); + vm->vmid = ACRN_INVALID_VMID; + return 0; +} diff --git a/include/uapi/linux/acrn.h b/include/uapi/linux/acrn.h new file mode 100644 index 000000000000..32521168075f --- /dev/null +++ b/include/uapi/linux/acrn.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Userspace interface for /dev/acrn_hsm - ACRN Hypervisor Service Module + * + * This file can be used by applications that need to communicate with the HSM + * via the ioctl interface. + * + * Copyright (C) 2021 Intel Corporation. All rights reserved. + */ + +#ifndef _UAPI_ACRN_H +#define _UAPI_ACRN_H + +#include +#include + +/** + * struct acrn_vm_creation - Info to create a User VM + * @vmid: User VM ID returned from the hypervisor + * @reserved0: Reserved and must be 0 + * @vcpu_num: Number of vCPU in the VM. Return from hypervisor. + * @reserved1: Reserved and must be 0 + * @uuid: UUID of the VM. Pass to hypervisor directly. + * @vm_flag: Flag of the VM creating. Pass to hypervisor directly. + * @ioreq_buf: Service VM GPA of I/O request buffer. Pass to + * hypervisor directly. + * @cpu_affinity: CPU affinity of the VM. Pass to hypervisor directly. + * It's a bitmap which indicates CPUs used by the VM. + */ +struct acrn_vm_creation { + __u16 vmid; + __u16 reserved0; + __u16 vcpu_num; + __u16 reserved1; + guid_t uuid; + __u64 vm_flag; + __u64 ioreq_buf; + __u64 cpu_affinity; +}; + +/* The ioctl type, documented in ioctl-number.rst */ +#define ACRN_IOCTL_TYPE 0xA2 + +/* + * Common IOCTL IDs definition for ACRN userspace + */ +#define ACRN_IOCTL_CREATE_VM \ + _IOWR(ACRN_IOCTL_TYPE, 0x10, struct acrn_vm_creation) +#define ACRN_IOCTL_DESTROY_VM \ + _IO(ACRN_IOCTL_TYPE, 0x11) +#define ACRN_IOCTL_START_VM \ + _IO(ACRN_IOCTL_TYPE, 0x12) +#define ACRN_IOCTL_PAUSE_VM \ + _IO(ACRN_IOCTL_TYPE, 0x13) +#define ACRN_IOCTL_RESET_VM \ + _IO(ACRN_IOCTL_TYPE, 0x15) + +#endif /* _UAPI_ACRN_H */ -- cgit v1.2.3 From ef3c67b6454b8f542f50387ad481633ae30874ac Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 25 Jan 2021 21:39:48 +0200 Subject: mfd: intel_msic: Remove driver for deprecated platform Intel Moorestown and Medfield are quite old Intel Atom based 32-bit platforms, which were in limited use in some Android phones, tablets and consumer electronics more than eight years ago. There are no bugs or problems ever reported outside from Intel for breaking any of that platforms for years. It seems no real users exists who run more or less fresh kernel on it. Commit 05f4434bc130 ("ASoC: Intel: remove mfld_machine") is also in align with this theory. Due to above and to reduce a burden of supporting outdated drivers, remove the support for outdated platforms completely. Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg Acked-by: Linus Walleij Acked-by: Lee Jones Signed-off-by: Rafael J. Wysocki --- MAINTAINERS | 2 - arch/x86/include/asm/intel_scu_ipc_legacy.h | 12 - drivers/mfd/Kconfig | 9 - drivers/mfd/Makefile | 1 - drivers/mfd/intel_msic.c | 425 -------------------------- include/linux/mfd/intel_msic.h | 453 ---------------------------- 6 files changed, 902 deletions(-) delete mode 100644 drivers/mfd/intel_msic.c delete mode 100644 include/linux/mfd/intel_msic.h (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 904eaa52f5f8..8fdb7fe27537 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9098,9 +9098,7 @@ F: drivers/gpio/gpio-*cove.c INTEL PMIC MULTIFUNCTION DEVICE DRIVERS M: Andy Shevchenko S: Maintained -F: drivers/mfd/intel_msic.c F: drivers/mfd/intel_soc_pmic* -F: include/linux/mfd/intel_msic.h F: include/linux/mfd/intel_soc_pmic* INTEL PMT DRIVER diff --git a/arch/x86/include/asm/intel_scu_ipc_legacy.h b/arch/x86/include/asm/intel_scu_ipc_legacy.h index 2232197c24f8..f8b87d8face7 100644 --- a/arch/x86/include/asm/intel_scu_ipc_legacy.h +++ b/arch/x86/include/asm/intel_scu_ipc_legacy.h @@ -16,24 +16,12 @@ /* Don't call these in new code - they will be removed eventually */ -/* Read single register */ -static inline int intel_scu_ipc_ioread8(u16 addr, u8 *data) -{ - return intel_scu_ipc_dev_ioread8(NULL, addr, data); -} - /* Read a vector */ static inline int intel_scu_ipc_readv(u16 *addr, u8 *data, int len) { return intel_scu_ipc_dev_readv(NULL, addr, data, len); } -/* Write single register */ -static inline int intel_scu_ipc_iowrite8(u16 addr, u8 data) -{ - return intel_scu_ipc_dev_iowrite8(NULL, addr, data); -} - /* Write a vector */ static inline int intel_scu_ipc_writev(u16 *addr, u8 *data, int len) { diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index bdfce7b15621..2dc58a92251b 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -659,15 +659,6 @@ config MFD_INTEL_LPSS_PCI I2C, SPI and HS-UART starting from Intel Sunrisepoint (Intel Skylake PCH) in PCI mode. -config MFD_INTEL_MSIC - bool "Intel MSIC" - depends on INTEL_SCU - select MFD_CORE - help - Select this option to enable access to Intel MSIC (Avatele - Passage) chip. This chip embeds audio, battery, GPIO, etc. - devices used in Intel Medfield platforms. - config MFD_INTEL_PMC_BXT tristate "Intel PMC Driver for Broxton" depends on X86 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 14fdb188af02..be19bc799073 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -214,7 +214,6 @@ obj-$(CONFIG_MFD_ATMEL_SMC) += atmel-smc.o obj-$(CONFIG_MFD_INTEL_LPSS) += intel-lpss.o obj-$(CONFIG_MFD_INTEL_LPSS_PCI) += intel-lpss-pci.o obj-$(CONFIG_MFD_INTEL_LPSS_ACPI) += intel-lpss-acpi.o -obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o obj-$(CONFIG_MFD_INTEL_PMC_BXT) += intel_pmc_bxt.o obj-$(CONFIG_MFD_INTEL_PMT) += intel_pmt.o obj-$(CONFIG_MFD_PALMAS) += palmas.o diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c deleted file mode 100644 index daa772f8146b..000000000000 --- a/drivers/mfd/intel_msic.c +++ /dev/null @@ -1,425 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Driver for Intel MSIC - * - * Copyright (C) 2011, Intel Corporation - * Author: Mika Westerberg - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define MSIC_VENDOR(id) ((id >> 6) & 3) -#define MSIC_VERSION(id) (id & 0x3f) -#define MSIC_MAJOR(id) ('A' + ((id >> 3) & 7)) -#define MSIC_MINOR(id) (id & 7) - -/* - * MSIC interrupt tree is readable from SRAM at INTEL_MSIC_IRQ_PHYS_BASE. - * Since IRQ block starts from address 0x002 we need to subtract that from - * the actual IRQ status register address. - */ -#define MSIC_IRQ_STATUS(x) (INTEL_MSIC_IRQ_PHYS_BASE + ((x) - 2)) -#define MSIC_IRQ_STATUS_ACCDET MSIC_IRQ_STATUS(INTEL_MSIC_ACCDET) - -/* - * The SCU hardware has limitation of 16 bytes per read/write buffer on - * Medfield. - */ -#define SCU_IPC_RWBUF_LIMIT 16 - -/** - * struct intel_msic - an MSIC MFD instance - * @pdev: pointer to the platform device - * @vendor: vendor ID - * @version: chip version - * @irq_base: base address of the mapped MSIC SRAM interrupt tree - */ -struct intel_msic { - struct platform_device *pdev; - unsigned vendor; - unsigned version; - void __iomem *irq_base; -}; - -static const struct resource msic_touch_resources[] = { - DEFINE_RES_IRQ(0), -}; - -static const struct resource msic_adc_resources[] = { - DEFINE_RES_IRQ(0), -}; - -static const struct resource msic_battery_resources[] = { - DEFINE_RES_IRQ(0), -}; - -static const struct resource msic_gpio_resources[] = { - DEFINE_RES_IRQ(0), -}; - -static const struct resource msic_audio_resources[] = { - DEFINE_RES_IRQ_NAMED(0, "IRQ"), - /* - * We will pass IRQ_BASE to the driver now but this can be removed - * when/if the driver starts to use intel_msic_irq_read(). - */ - DEFINE_RES_MEM_NAMED(MSIC_IRQ_STATUS_ACCDET, 1, "IRQ_BASE"), -}; - -static const struct resource msic_hdmi_resources[] = { - DEFINE_RES_IRQ(0), -}; - -static const struct resource msic_thermal_resources[] = { - DEFINE_RES_IRQ(0), -}; - -static const struct resource msic_power_btn_resources[] = { - DEFINE_RES_IRQ(0), -}; - -static const struct resource msic_ocd_resources[] = { - DEFINE_RES_IRQ(0), -}; - -/* - * Devices that are part of the MSIC and are available via firmware - * populated SFI DEVS table. - */ -static struct mfd_cell msic_devs[] = { - [INTEL_MSIC_BLOCK_TOUCH] = { - .name = "msic_touch", - .num_resources = ARRAY_SIZE(msic_touch_resources), - .resources = msic_touch_resources, - }, - [INTEL_MSIC_BLOCK_ADC] = { - .name = "msic_adc", - .num_resources = ARRAY_SIZE(msic_adc_resources), - .resources = msic_adc_resources, - }, - [INTEL_MSIC_BLOCK_BATTERY] = { - .name = "msic_battery", - .num_resources = ARRAY_SIZE(msic_battery_resources), - .resources = msic_battery_resources, - }, - [INTEL_MSIC_BLOCK_GPIO] = { - .name = "msic_gpio", - .num_resources = ARRAY_SIZE(msic_gpio_resources), - .resources = msic_gpio_resources, - }, - [INTEL_MSIC_BLOCK_AUDIO] = { - .name = "msic_audio", - .num_resources = ARRAY_SIZE(msic_audio_resources), - .resources = msic_audio_resources, - }, - [INTEL_MSIC_BLOCK_HDMI] = { - .name = "msic_hdmi", - .num_resources = ARRAY_SIZE(msic_hdmi_resources), - .resources = msic_hdmi_resources, - }, - [INTEL_MSIC_BLOCK_THERMAL] = { - .name = "msic_thermal", - .num_resources = ARRAY_SIZE(msic_thermal_resources), - .resources = msic_thermal_resources, - }, - [INTEL_MSIC_BLOCK_POWER_BTN] = { - .name = "msic_power_btn", - .num_resources = ARRAY_SIZE(msic_power_btn_resources), - .resources = msic_power_btn_resources, - }, - [INTEL_MSIC_BLOCK_OCD] = { - .name = "msic_ocd", - .num_resources = ARRAY_SIZE(msic_ocd_resources), - .resources = msic_ocd_resources, - }, -}; - -/* - * Other MSIC related devices which are not directly available via SFI DEVS - * table. These can be pseudo devices, regulators etc. which are needed for - * different purposes. - * - * These devices appear only after the MSIC driver itself is initialized so - * we can guarantee that the SCU IPC interface is ready. - */ -static const struct mfd_cell msic_other_devs[] = { - /* Audio codec in the MSIC */ - { - .id = -1, - .name = "sn95031", - }, -}; - -/** - * intel_msic_reg_read - read a single MSIC register - * @reg: register to read - * @val: register value is placed here - * - * Read a single register from MSIC. Returns %0 on success and negative - * errno in case of failure. - * - * Function may sleep. - */ -int intel_msic_reg_read(unsigned short reg, u8 *val) -{ - return intel_scu_ipc_ioread8(reg, val); -} -EXPORT_SYMBOL_GPL(intel_msic_reg_read); - -/** - * intel_msic_reg_write - write a single MSIC register - * @reg: register to write - * @val: value to write to that register - * - * Write a single MSIC register. Returns 0 on success and negative - * errno in case of failure. - * - * Function may sleep. - */ -int intel_msic_reg_write(unsigned short reg, u8 val) -{ - return intel_scu_ipc_iowrite8(reg, val); -} -EXPORT_SYMBOL_GPL(intel_msic_reg_write); - -/** - * intel_msic_reg_update - update a single MSIC register - * @reg: register to update - * @val: value to write to the register - * @mask: specifies which of the bits are updated (%0 = don't update, - * %1 = update) - * - * Perform an update to a register @reg. @mask is used to specify which - * bits are updated. Returns %0 in case of success and negative errno in - * case of failure. - * - * Function may sleep. - */ -int intel_msic_reg_update(unsigned short reg, u8 val, u8 mask) -{ - return intel_scu_ipc_update_register(reg, val, mask); -} -EXPORT_SYMBOL_GPL(intel_msic_reg_update); - -/** - * intel_msic_bulk_read - read an array of registers - * @reg: array of register addresses to read - * @buf: array where the read values are placed - * @count: number of registers to read - * - * Function reads @count registers from the MSIC using addresses passed in - * @reg. Read values are placed in @buf. Reads are performed atomically - * wrt. MSIC. - * - * Returns %0 in case of success and negative errno in case of failure. - * - * Function may sleep. - */ -int intel_msic_bulk_read(unsigned short *reg, u8 *buf, size_t count) -{ - if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT)) - return -EINVAL; - - return intel_scu_ipc_readv(reg, buf, count); -} -EXPORT_SYMBOL_GPL(intel_msic_bulk_read); - -/** - * intel_msic_bulk_write - write an array of values to the MSIC registers - * @reg: array of registers to write - * @buf: values to write to each register - * @count: number of registers to write - * - * Function writes @count registers in @buf to MSIC. Writes are performed - * atomically wrt MSIC. Returns %0 in case of success and negative errno in - * case of failure. - * - * Function may sleep. - */ -int intel_msic_bulk_write(unsigned short *reg, u8 *buf, size_t count) -{ - if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT)) - return -EINVAL; - - return intel_scu_ipc_writev(reg, buf, count); -} -EXPORT_SYMBOL_GPL(intel_msic_bulk_write); - -/** - * intel_msic_irq_read - read a register from an MSIC interrupt tree - * @msic: MSIC instance - * @reg: interrupt register (between %INTEL_MSIC_IRQLVL1 and - * %INTEL_MSIC_RESETIRQ2) - * @val: value of the register is placed here - * - * This function can be used by an MSIC subdevice interrupt handler to read - * a register value from the MSIC interrupt tree. In this way subdevice - * drivers don't have to map in the interrupt tree themselves but can just - * call this function instead. - * - * Function doesn't sleep and is callable from interrupt context. - * - * Returns %-EINVAL if @reg is outside of the allowed register region. - */ -int intel_msic_irq_read(struct intel_msic *msic, unsigned short reg, u8 *val) -{ - if (WARN_ON(reg < INTEL_MSIC_IRQLVL1 || reg > INTEL_MSIC_RESETIRQ2)) - return -EINVAL; - - *val = readb(msic->irq_base + (reg - INTEL_MSIC_IRQLVL1)); - return 0; -} -EXPORT_SYMBOL_GPL(intel_msic_irq_read); - -static int intel_msic_init_devices(struct intel_msic *msic) -{ - struct platform_device *pdev = msic->pdev; - struct intel_msic_platform_data *pdata = dev_get_platdata(&pdev->dev); - int ret, i; - - if (pdata->gpio) { - struct mfd_cell *cell = &msic_devs[INTEL_MSIC_BLOCK_GPIO]; - - cell->platform_data = pdata->gpio; - cell->pdata_size = sizeof(*pdata->gpio); - } - - if (pdata->ocd) { - unsigned gpio = pdata->ocd->gpio; - - ret = devm_gpio_request_one(&pdev->dev, gpio, - GPIOF_IN, "ocd_gpio"); - if (ret) { - dev_err(&pdev->dev, "failed to register OCD GPIO\n"); - return ret; - } - - ret = gpio_to_irq(gpio); - if (ret < 0) { - dev_err(&pdev->dev, "no IRQ number for OCD GPIO\n"); - return ret; - } - - /* Update the IRQ number for the OCD */ - pdata->irq[INTEL_MSIC_BLOCK_OCD] = ret; - } - - for (i = 0; i < ARRAY_SIZE(msic_devs); i++) { - if (!pdata->irq[i]) - continue; - - ret = mfd_add_devices(&pdev->dev, -1, &msic_devs[i], 1, NULL, - pdata->irq[i], NULL); - if (ret) - goto fail; - } - - ret = mfd_add_devices(&pdev->dev, 0, msic_other_devs, - ARRAY_SIZE(msic_other_devs), NULL, 0, NULL); - if (ret) - goto fail; - - return 0; - -fail: - mfd_remove_devices(&pdev->dev); - - return ret; -} - -static void intel_msic_remove_devices(struct intel_msic *msic) -{ - struct platform_device *pdev = msic->pdev; - - mfd_remove_devices(&pdev->dev); -} - -static int intel_msic_probe(struct platform_device *pdev) -{ - struct intel_msic_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct intel_msic *msic; - struct resource *res; - u8 id0, id1; - int ret; - - if (!pdata) { - dev_err(&pdev->dev, "no platform data passed\n"); - return -EINVAL; - } - - /* First validate that we have an MSIC in place */ - ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID0, &id0); - if (ret) { - dev_err(&pdev->dev, "failed to identify the MSIC chip (ID0)\n"); - return -ENXIO; - } - - ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID1, &id1); - if (ret) { - dev_err(&pdev->dev, "failed to identify the MSIC chip (ID1)\n"); - return -ENXIO; - } - - if (MSIC_VENDOR(id0) != MSIC_VENDOR(id1)) { - dev_err(&pdev->dev, "invalid vendor ID: %x, %x\n", id0, id1); - return -ENXIO; - } - - msic = devm_kzalloc(&pdev->dev, sizeof(*msic), GFP_KERNEL); - if (!msic) - return -ENOMEM; - - msic->vendor = MSIC_VENDOR(id0); - msic->version = MSIC_VERSION(id0); - msic->pdev = pdev; - - /* - * Map in the MSIC interrupt tree area in SRAM. This is exposed to - * the clients via intel_msic_irq_read(). - */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - msic->irq_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(msic->irq_base)) - return PTR_ERR(msic->irq_base); - - platform_set_drvdata(pdev, msic); - - ret = intel_msic_init_devices(msic); - if (ret) { - dev_err(&pdev->dev, "failed to initialize MSIC devices\n"); - return ret; - } - - dev_info(&pdev->dev, "Intel MSIC version %c%d (vendor %#x)\n", - MSIC_MAJOR(msic->version), MSIC_MINOR(msic->version), - msic->vendor); - - return 0; -} - -static int intel_msic_remove(struct platform_device *pdev) -{ - struct intel_msic *msic = platform_get_drvdata(pdev); - - intel_msic_remove_devices(msic); - - return 0; -} - -static struct platform_driver intel_msic_driver = { - .probe = intel_msic_probe, - .remove = intel_msic_remove, - .driver = { - .name = "intel_msic", - }, -}; -builtin_platform_driver(intel_msic_driver); diff --git a/include/linux/mfd/intel_msic.h b/include/linux/mfd/intel_msic.h deleted file mode 100644 index 317e8608cf41..000000000000 --- a/include/linux/mfd/intel_msic.h +++ /dev/null @@ -1,453 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Core interface for Intel MSIC - * - * Copyright (C) 2011, Intel Corporation - * Author: Mika Westerberg - */ - -#ifndef __LINUX_MFD_INTEL_MSIC_H__ -#define __LINUX_MFD_INTEL_MSIC_H__ - -/* ID */ -#define INTEL_MSIC_ID0 0x000 /* RO */ -#define INTEL_MSIC_ID1 0x001 /* RO */ - -/* IRQ */ -#define INTEL_MSIC_IRQLVL1 0x002 -#define INTEL_MSIC_ADC1INT 0x003 -#define INTEL_MSIC_CCINT 0x004 -#define INTEL_MSIC_PWRSRCINT 0x005 -#define INTEL_MSIC_PWRSRCINT1 0x006 -#define INTEL_MSIC_CHRINT 0x007 -#define INTEL_MSIC_CHRINT1 0x008 -#define INTEL_MSIC_RTCIRQ 0x009 -#define INTEL_MSIC_GPIO0LVIRQ 0x00a -#define INTEL_MSIC_GPIO1LVIRQ 0x00b -#define INTEL_MSIC_GPIOHVIRQ 0x00c -#define INTEL_MSIC_VRINT 0x00d -#define INTEL_MSIC_OCAUDIO 0x00e -#define INTEL_MSIC_ACCDET 0x00f -#define INTEL_MSIC_RESETIRQ1 0x010 -#define INTEL_MSIC_RESETIRQ2 0x011 -#define INTEL_MSIC_MADC1INT 0x012 -#define INTEL_MSIC_MCCINT 0x013 -#define INTEL_MSIC_MPWRSRCINT 0x014 -#define INTEL_MSIC_MPWRSRCINT1 0x015 -#define INTEL_MSIC_MCHRINT 0x016 -#define INTEL_MSIC_MCHRINT1 0x017 -#define INTEL_MSIC_RTCIRQMASK 0x018 -#define INTEL_MSIC_GPIO0LVIRQMASK 0x019 -#define INTEL_MSIC_GPIO1LVIRQMASK 0x01a -#define INTEL_MSIC_GPIOHVIRQMASK 0x01b -#define INTEL_MSIC_VRINTMASK 0x01c -#define INTEL_MSIC_OCAUDIOMASK 0x01d -#define INTEL_MSIC_ACCDETMASK 0x01e -#define INTEL_MSIC_RESETIRQ1MASK 0x01f -#define INTEL_MSIC_RESETIRQ2MASK 0x020 -#define INTEL_MSIC_IRQLVL1MSK 0x021 -#define INTEL_MSIC_PBCONFIG 0x03e -#define INTEL_MSIC_PBSTATUS 0x03f /* RO */ - -/* GPIO */ -#define INTEL_MSIC_GPIO0LV7CTLO 0x040 -#define INTEL_MSIC_GPIO0LV6CTLO 0x041 -#define INTEL_MSIC_GPIO0LV5CTLO 0x042 -#define INTEL_MSIC_GPIO0LV4CTLO 0x043 -#define INTEL_MSIC_GPIO0LV3CTLO 0x044 -#define INTEL_MSIC_GPIO0LV2CTLO 0x045 -#define INTEL_MSIC_GPIO0LV1CTLO 0x046 -#define INTEL_MSIC_GPIO0LV0CTLO 0x047 -#define INTEL_MSIC_GPIO1LV7CTLOS 0x048 -#define INTEL_MSIC_GPIO1LV6CTLO 0x049 -#define INTEL_MSIC_GPIO1LV5CTLO 0x04a -#define INTEL_MSIC_GPIO1LV4CTLO 0x04b -#define INTEL_MSIC_GPIO1LV3CTLO 0x04c -#define INTEL_MSIC_GPIO1LV2CTLO 0x04d -#define INTEL_MSIC_GPIO1LV1CTLO 0x04e -#define INTEL_MSIC_GPIO1LV0CTLO 0x04f -#define INTEL_MSIC_GPIO0LV7CTLI 0x050 -#define INTEL_MSIC_GPIO0LV6CTLI 0x051 -#define INTEL_MSIC_GPIO0LV5CTLI 0x052 -#define INTEL_MSIC_GPIO0LV4CTLI 0x053 -#define INTEL_MSIC_GPIO0LV3CTLI 0x054 -#define INTEL_MSIC_GPIO0LV2CTLI 0x055 -#define INTEL_MSIC_GPIO0LV1CTLI 0x056 -#define INTEL_MSIC_GPIO0LV0CTLI 0x057 -#define INTEL_MSIC_GPIO1LV7CTLIS 0x058 -#define INTEL_MSIC_GPIO1LV6CTLI 0x059 -#define INTEL_MSIC_GPIO1LV5CTLI 0x05a -#define INTEL_MSIC_GPIO1LV4CTLI 0x05b -#define INTEL_MSIC_GPIO1LV3CTLI 0x05c -#define INTEL_MSIC_GPIO1LV2CTLI 0x05d -#define INTEL_MSIC_GPIO1LV1CTLI 0x05e -#define INTEL_MSIC_GPIO1LV0CTLI 0x05f -#define INTEL_MSIC_PWM0CLKDIV1 0x061 -#define INTEL_MSIC_PWM0CLKDIV0 0x062 -#define INTEL_MSIC_PWM1CLKDIV1 0x063 -#define INTEL_MSIC_PWM1CLKDIV0 0x064 -#define INTEL_MSIC_PWM2CLKDIV1 0x065 -#define INTEL_MSIC_PWM2CLKDIV0 0x066 -#define INTEL_MSIC_PWM0DUTYCYCLE 0x067 -#define INTEL_MSIC_PWM1DUTYCYCLE 0x068 -#define INTEL_MSIC_PWM2DUTYCYCLE 0x069 -#define INTEL_MSIC_GPIO0HV3CTLO 0x06d -#define INTEL_MSIC_GPIO0HV2CTLO 0x06e -#define INTEL_MSIC_GPIO0HV1CTLO 0x06f -#define INTEL_MSIC_GPIO0HV0CTLO 0x070 -#define INTEL_MSIC_GPIO1HV3CTLO 0x071 -#define INTEL_MSIC_GPIO1HV2CTLO 0x072 -#define INTEL_MSIC_GPIO1HV1CTLO 0x073 -#define INTEL_MSIC_GPIO1HV0CTLO 0x074 -#define INTEL_MSIC_GPIO0HV3CTLI 0x075 -#define INTEL_MSIC_GPIO0HV2CTLI 0x076 -#define INTEL_MSIC_GPIO0HV1CTLI 0x077 -#define INTEL_MSIC_GPIO0HV0CTLI 0x078 -#define INTEL_MSIC_GPIO1HV3CTLI 0x079 -#define INTEL_MSIC_GPIO1HV2CTLI 0x07a -#define INTEL_MSIC_GPIO1HV1CTLI 0x07b -#define INTEL_MSIC_GPIO1HV0CTLI 0x07c - -/* SVID */ -#define INTEL_MSIC_SVIDCTRL0 0x080 -#define INTEL_MSIC_SVIDCTRL1 0x081 -#define INTEL_MSIC_SVIDCTRL2 0x082 -#define INTEL_MSIC_SVIDTXLASTPKT3 0x083 /* RO */ -#define INTEL_MSIC_SVIDTXLASTPKT2 0x084 /* RO */ -#define INTEL_MSIC_SVIDTXLASTPKT1 0x085 /* RO */ -#define INTEL_MSIC_SVIDTXLASTPKT0 0x086 /* RO */ -#define INTEL_MSIC_SVIDPKTOUTBYTE3 0x087 -#define INTEL_MSIC_SVIDPKTOUTBYTE2 0x088 -#define INTEL_MSIC_SVIDPKTOUTBYTE1 0x089 -#define INTEL_MSIC_SVIDPKTOUTBYTE0 0x08a -#define INTEL_MSIC_SVIDRXVPDEBUG1 0x08b -#define INTEL_MSIC_SVIDRXVPDEBUG0 0x08c -#define INTEL_MSIC_SVIDRXLASTPKT3 0x08d /* RO */ -#define INTEL_MSIC_SVIDRXLASTPKT2 0x08e /* RO */ -#define INTEL_MSIC_SVIDRXLASTPKT1 0x08f /* RO */ -#define INTEL_MSIC_SVIDRXLASTPKT0 0x090 /* RO */ -#define INTEL_MSIC_SVIDRXCHKSTATUS3 0x091 /* RO */ -#define INTEL_MSIC_SVIDRXCHKSTATUS2 0x092 /* RO */ -#define INTEL_MSIC_SVIDRXCHKSTATUS1 0x093 /* RO */ -#define INTEL_MSIC_SVIDRXCHKSTATUS0 0x094 /* RO */ - -/* VREG */ -#define INTEL_MSIC_VCCLATCH 0x0c0 -#define INTEL_MSIC_VNNLATCH 0x0c1 -#define INTEL_MSIC_VCCCNT 0x0c2 -#define INTEL_MSIC_SMPSRAMP 0x0c3 -#define INTEL_MSIC_VNNCNT 0x0c4 -#define INTEL_MSIC_VNNAONCNT 0x0c5 -#define INTEL_MSIC_VCC122AONCNT 0x0c6 -#define INTEL_MSIC_V180AONCNT 0x0c7 -#define INTEL_MSIC_V500CNT 0x0c8 -#define INTEL_MSIC_VIHFCNT 0x0c9 -#define INTEL_MSIC_LDORAMP1 0x0ca -#define INTEL_MSIC_LDORAMP2 0x0cb -#define INTEL_MSIC_VCC108AONCNT 0x0cc -#define INTEL_MSIC_VCC108ASCNT 0x0cd -#define INTEL_MSIC_VCC108CNT 0x0ce -#define INTEL_MSIC_VCCA100ASCNT 0x0cf -#define INTEL_MSIC_VCCA100CNT 0x0d0 -#define INTEL_MSIC_VCC180AONCNT 0x0d1 -#define INTEL_MSIC_VCC180CNT 0x0d2 -#define INTEL_MSIC_VCC330CNT 0x0d3 -#define INTEL_MSIC_VUSB330CNT 0x0d4 -#define INTEL_MSIC_VCCSDIOCNT 0x0d5 -#define INTEL_MSIC_VPROG1CNT 0x0d6 -#define INTEL_MSIC_VPROG2CNT 0x0d7 -#define INTEL_MSIC_VEMMCSCNT 0x0d8 -#define INTEL_MSIC_VEMMC1CNT 0x0d9 -#define INTEL_MSIC_VEMMC2CNT 0x0da -#define INTEL_MSIC_VAUDACNT 0x0db -#define INTEL_MSIC_VHSPCNT 0x0dc -#define INTEL_MSIC_VHSNCNT 0x0dd -#define INTEL_MSIC_VHDMICNT 0x0de -#define INTEL_MSIC_VOTGCNT 0x0df -#define INTEL_MSIC_V1P35CNT 0x0e0 -#define INTEL_MSIC_V330AONCNT 0x0e1 - -/* RESET */ -#define INTEL_MSIC_CHIPCNTRL 0x100 /* WO */ -#define INTEL_MSIC_ERCONFIG 0x101 - -/* BURST */ -#define INTEL_MSIC_BATCURRENTLIMIT12 0x102 -#define INTEL_MSIC_BATTIMELIMIT12 0x103 -#define INTEL_MSIC_BATTIMELIMIT3 0x104 -#define INTEL_MSIC_BATTIMEDB 0x105 -#define INTEL_MSIC_BRSTCONFIGOUTPUTS 0x106 -#define INTEL_MSIC_BRSTCONFIGACTIONS 0x107 -#define INTEL_MSIC_BURSTCONTROLSTATUS 0x108 - -/* RTC */ -#define INTEL_MSIC_RTCB1 0x140 /* RO */ -#define INTEL_MSIC_RTCB2 0x141 /* RO */ -#define INTEL_MSIC_RTCB3 0x142 /* RO */ -#define INTEL_MSIC_RTCB4 0x143 /* RO */ -#define INTEL_MSIC_RTCOB1 0x144 -#define INTEL_MSIC_RTCOB2 0x145 -#define INTEL_MSIC_RTCOB3 0x146 -#define INTEL_MSIC_RTCOB4 0x147 -#define INTEL_MSIC_RTCAB1 0x148 -#define INTEL_MSIC_RTCAB2 0x149 -#define INTEL_MSIC_RTCAB3 0x14a -#define INTEL_MSIC_RTCAB4 0x14b -#define INTEL_MSIC_RTCWAB1 0x14c -#define INTEL_MSIC_RTCWAB2 0x14d -#define INTEL_MSIC_RTCWAB3 0x14e -#define INTEL_MSIC_RTCWAB4 0x14f -#define INTEL_MSIC_RTCSC1 0x150 -#define INTEL_MSIC_RTCSC2 0x151 -#define INTEL_MSIC_RTCSC3 0x152 -#define INTEL_MSIC_RTCSC4 0x153 -#define INTEL_MSIC_RTCSTATUS 0x154 /* RO */ -#define INTEL_MSIC_RTCCONFIG1 0x155 -#define INTEL_MSIC_RTCCONFIG2 0x156 - -/* CHARGER */ -#define INTEL_MSIC_BDTIMER 0x180 -#define INTEL_MSIC_BATTRMV 0x181 -#define INTEL_MSIC_VBUSDET 0x182 -#define INTEL_MSIC_VBUSDET1 0x183 -#define INTEL_MSIC_ADPHVDET 0x184 -#define INTEL_MSIC_ADPLVDET 0x185 -#define INTEL_MSIC_ADPDETDBDM 0x186 -#define INTEL_MSIC_LOWBATTDET 0x187 -#define INTEL_MSIC_CHRCTRL 0x188 -#define INTEL_MSIC_CHRCVOLTAGE 0x189 -#define INTEL_MSIC_CHRCCURRENT 0x18a -#define INTEL_MSIC_SPCHARGER 0x18b -#define INTEL_MSIC_CHRTTIME 0x18c -#define INTEL_MSIC_CHRCTRL1 0x18d -#define INTEL_MSIC_PWRSRCLMT 0x18e -#define INTEL_MSIC_CHRSTWDT 0x18f -#define INTEL_MSIC_WDTWRITE 0x190 /* WO */ -#define INTEL_MSIC_CHRSAFELMT 0x191 -#define INTEL_MSIC_SPWRSRCINT 0x192 /* RO */ -#define INTEL_MSIC_SPWRSRCINT1 0x193 /* RO */ -#define INTEL_MSIC_CHRLEDPWM 0x194 -#define INTEL_MSIC_CHRLEDCTRL 0x195 - -/* ADC */ -#define INTEL_MSIC_ADC1CNTL1 0x1c0 -#define INTEL_MSIC_ADC1CNTL2 0x1c1 -#define INTEL_MSIC_ADC1CNTL3 0x1c2 -#define INTEL_MSIC_ADC1OFFSETH 0x1c3 /* RO */ -#define INTEL_MSIC_ADC1OFFSETL 0x1c4 /* RO */ -#define INTEL_MSIC_ADC1ADDR0 0x1c5 -#define INTEL_MSIC_ADC1ADDR1 0x1c6 -#define INTEL_MSIC_ADC1ADDR2 0x1c7 -#define INTEL_MSIC_ADC1ADDR3 0x1c8 -#define INTEL_MSIC_ADC1ADDR4 0x1c9 -#define INTEL_MSIC_ADC1ADDR5 0x1ca -#define INTEL_MSIC_ADC1ADDR6 0x1cb -#define INTEL_MSIC_ADC1ADDR7 0x1cc -#define INTEL_MSIC_ADC1ADDR8 0x1cd -#define INTEL_MSIC_ADC1ADDR9 0x1ce -#define INTEL_MSIC_ADC1ADDR10 0x1cf -#define INTEL_MSIC_ADC1ADDR11 0x1d0 -#define INTEL_MSIC_ADC1ADDR12 0x1d1 -#define INTEL_MSIC_ADC1ADDR13 0x1d2 -#define INTEL_MSIC_ADC1ADDR14 0x1d3 -#define INTEL_MSIC_ADC1SNS0H 0x1d4 /* RO */ -#define INTEL_MSIC_ADC1SNS0L 0x1d5 /* RO */ -#define INTEL_MSIC_ADC1SNS1H 0x1d6 /* RO */ -#define INTEL_MSIC_ADC1SNS1L 0x1d7 /* RO */ -#define INTEL_MSIC_ADC1SNS2H 0x1d8 /* RO */ -#define INTEL_MSIC_ADC1SNS2L 0x1d9 /* RO */ -#define INTEL_MSIC_ADC1SNS3H 0x1da /* RO */ -#define INTEL_MSIC_ADC1SNS3L 0x1db /* RO */ -#define INTEL_MSIC_ADC1SNS4H 0x1dc /* RO */ -#define INTEL_MSIC_ADC1SNS4L 0x1dd /* RO */ -#define INTEL_MSIC_ADC1SNS5H 0x1de /* RO */ -#define INTEL_MSIC_ADC1SNS5L 0x1df /* RO */ -#define INTEL_MSIC_ADC1SNS6H 0x1e0 /* RO */ -#define INTEL_MSIC_ADC1SNS6L 0x1e1 /* RO */ -#define INTEL_MSIC_ADC1SNS7H 0x1e2 /* RO */ -#define INTEL_MSIC_ADC1SNS7L 0x1e3 /* RO */ -#define INTEL_MSIC_ADC1SNS8H 0x1e4 /* RO */ -#define INTEL_MSIC_ADC1SNS8L 0x1e5 /* RO */ -#define INTEL_MSIC_ADC1SNS9H 0x1e6 /* RO */ -#define INTEL_MSIC_ADC1SNS9L 0x1e7 /* RO */ -#define INTEL_MSIC_ADC1SNS10H 0x1e8 /* RO */ -#define INTEL_MSIC_ADC1SNS10L 0x1e9 /* RO */ -#define INTEL_MSIC_ADC1SNS11H 0x1ea /* RO */ -#define INTEL_MSIC_ADC1SNS11L 0x1eb /* RO */ -#define INTEL_MSIC_ADC1SNS12H 0x1ec /* RO */ -#define INTEL_MSIC_ADC1SNS12L 0x1ed /* RO */ -#define INTEL_MSIC_ADC1SNS13H 0x1ee /* RO */ -#define INTEL_MSIC_ADC1SNS13L 0x1ef /* RO */ -#define INTEL_MSIC_ADC1SNS14H 0x1f0 /* RO */ -#define INTEL_MSIC_ADC1SNS14L 0x1f1 /* RO */ -#define INTEL_MSIC_ADC1BV0H 0x1f2 /* RO */ -#define INTEL_MSIC_ADC1BV0L 0x1f3 /* RO */ -#define INTEL_MSIC_ADC1BV1H 0x1f4 /* RO */ -#define INTEL_MSIC_ADC1BV1L 0x1f5 /* RO */ -#define INTEL_MSIC_ADC1BV2H 0x1f6 /* RO */ -#define INTEL_MSIC_ADC1BV2L 0x1f7 /* RO */ -#define INTEL_MSIC_ADC1BV3H 0x1f8 /* RO */ -#define INTEL_MSIC_ADC1BV3L 0x1f9 /* RO */ -#define INTEL_MSIC_ADC1BI0H 0x1fa /* RO */ -#define INTEL_MSIC_ADC1BI0L 0x1fb /* RO */ -#define INTEL_MSIC_ADC1BI1H 0x1fc /* RO */ -#define INTEL_MSIC_ADC1BI1L 0x1fd /* RO */ -#define INTEL_MSIC_ADC1BI2H 0x1fe /* RO */ -#define INTEL_MSIC_ADC1BI2L 0x1ff /* RO */ -#define INTEL_MSIC_ADC1BI3H 0x200 /* RO */ -#define INTEL_MSIC_ADC1BI3L 0x201 /* RO */ -#define INTEL_MSIC_CCCNTL 0x202 -#define INTEL_MSIC_CCOFFSETH 0x203 /* RO */ -#define INTEL_MSIC_CCOFFSETL 0x204 /* RO */ -#define INTEL_MSIC_CCADCHA 0x205 /* RO */ -#define INTEL_MSIC_CCADCLA 0x206 /* RO */ - -/* AUDIO */ -#define INTEL_MSIC_AUDPLLCTRL 0x240 -#define INTEL_MSIC_DMICBUF0123 0x241 -#define INTEL_MSIC_DMICBUF45 0x242 -#define INTEL_MSIC_DMICGPO 0x244 -#define INTEL_MSIC_DMICMUX 0x245 -#define INTEL_MSIC_DMICCLK 0x246 -#define INTEL_MSIC_MICBIAS 0x247 -#define INTEL_MSIC_ADCCONFIG 0x248 -#define INTEL_MSIC_MICAMP1 0x249 -#define INTEL_MSIC_MICAMP2 0x24a -#define INTEL_MSIC_NOISEMUX 0x24b -#define INTEL_MSIC_AUDIOMUX12 0x24c -#define INTEL_MSIC_AUDIOMUX34 0x24d -#define INTEL_MSIC_AUDIOSINC 0x24e -#define INTEL_MSIC_AUDIOTXEN 0x24f -#define INTEL_MSIC_HSEPRXCTRL 0x250 -#define INTEL_MSIC_IHFRXCTRL 0x251 -#define INTEL_MSIC_VOICETXVOL 0x252 -#define INTEL_MSIC_SIDETONEVOL 0x253 -#define INTEL_MSIC_MUSICSHARVOL 0x254 -#define INTEL_MSIC_VOICETXCTRL 0x255 -#define INTEL_MSIC_HSMIXER 0x256 -#define INTEL_MSIC_DACCONFIG 0x257 -#define INTEL_MSIC_SOFTMUTE 0x258 -#define INTEL_MSIC_HSLVOLCTRL 0x259 -#define INTEL_MSIC_HSRVOLCTRL 0x25a -#define INTEL_MSIC_IHFLVOLCTRL 0x25b -#define INTEL_MSIC_IHFRVOLCTRL 0x25c -#define INTEL_MSIC_DRIVEREN 0x25d -#define INTEL_MSIC_LINEOUTCTRL 0x25e -#define INTEL_MSIC_VIB1CTRL1 0x25f -#define INTEL_MSIC_VIB1CTRL2 0x260 -#define INTEL_MSIC_VIB1CTRL3 0x261 -#define INTEL_MSIC_VIB1SPIPCM_1 0x262 -#define INTEL_MSIC_VIB1SPIPCM_2 0x263 -#define INTEL_MSIC_VIB1CTRL5 0x264 -#define INTEL_MSIC_VIB2CTRL1 0x265 -#define INTEL_MSIC_VIB2CTRL2 0x266 -#define INTEL_MSIC_VIB2CTRL3 0x267 -#define INTEL_MSIC_VIB2SPIPCM_1 0x268 -#define INTEL_MSIC_VIB2SPIPCM_2 0x269 -#define INTEL_MSIC_VIB2CTRL5 0x26a -#define INTEL_MSIC_BTNCTRL1 0x26b -#define INTEL_MSIC_BTNCTRL2 0x26c -#define INTEL_MSIC_PCM1TXSLOT01 0x26d -#define INTEL_MSIC_PCM1TXSLOT23 0x26e -#define INTEL_MSIC_PCM1TXSLOT45 0x26f -#define INTEL_MSIC_PCM1RXSLOT0123 0x270 -#define INTEL_MSIC_PCM1RXSLOT045 0x271 -#define INTEL_MSIC_PCM2TXSLOT01 0x272 -#define INTEL_MSIC_PCM2TXSLOT23 0x273 -#define INTEL_MSIC_PCM2TXSLOT45 0x274 -#define INTEL_MSIC_PCM2RXSLOT01 0x275 -#define INTEL_MSIC_PCM2RXSLOT23 0x276 -#define INTEL_MSIC_PCM2RXSLOT45 0x277 -#define INTEL_MSIC_PCM1CTRL1 0x278 -#define INTEL_MSIC_PCM1CTRL2 0x279 -#define INTEL_MSIC_PCM1CTRL3 0x27a -#define INTEL_MSIC_PCM2CTRL1 0x27b -#define INTEL_MSIC_PCM2CTRL2 0x27c - -/* HDMI */ -#define INTEL_MSIC_HDMIPUEN 0x280 -#define INTEL_MSIC_HDMISTATUS 0x281 /* RO */ - -/* Physical address of the start of the MSIC interrupt tree in SRAM */ -#define INTEL_MSIC_IRQ_PHYS_BASE 0xffff7fc0 - -/** - * struct intel_msic_gpio_pdata - platform data for the MSIC GPIO driver - * @gpio_base: base number for the GPIOs - */ -struct intel_msic_gpio_pdata { - unsigned gpio_base; -}; - -/** - * struct intel_msic_ocd_pdata - platform data for the MSIC OCD driver - * @gpio: GPIO number used for OCD interrupts - * - * The MSIC MFD driver converts @gpio into an IRQ number and passes it to - * the OCD driver as %IORESOURCE_IRQ. - */ -struct intel_msic_ocd_pdata { - unsigned gpio; -}; - -/* MSIC embedded blocks (subdevices) */ -enum intel_msic_block { - INTEL_MSIC_BLOCK_TOUCH, - INTEL_MSIC_BLOCK_ADC, - INTEL_MSIC_BLOCK_BATTERY, - INTEL_MSIC_BLOCK_GPIO, - INTEL_MSIC_BLOCK_AUDIO, - INTEL_MSIC_BLOCK_HDMI, - INTEL_MSIC_BLOCK_THERMAL, - INTEL_MSIC_BLOCK_POWER_BTN, - INTEL_MSIC_BLOCK_OCD, - - INTEL_MSIC_BLOCK_LAST, -}; - -/** - * struct intel_msic_platform_data - platform data for the MSIC driver - * @irq: array of interrupt numbers, one per device. If @irq is set to %0 - * for a given block, the corresponding platform device is not - * created. For devices which don't have an interrupt, use %0xff - * (this is same as in SFI spec). - * @gpio: platform data for the MSIC GPIO driver - * @ocd: platform data for the MSIC OCD driver - * - * Once the MSIC driver is initialized, the register interface is ready to - * use. All the platform devices for subdevices are created after the - * register interface is ready so that we can guarantee its availability to - * the subdevice drivers. - * - * Interrupt numbers are passed to the subdevices via %IORESOURCE_IRQ - * resources of the created platform device. - */ -struct intel_msic_platform_data { - int irq[INTEL_MSIC_BLOCK_LAST]; - struct intel_msic_gpio_pdata *gpio; - struct intel_msic_ocd_pdata *ocd; -}; - -struct intel_msic; - -extern int intel_msic_reg_read(unsigned short reg, u8 *val); -extern int intel_msic_reg_write(unsigned short reg, u8 val); -extern int intel_msic_reg_update(unsigned short reg, u8 val, u8 mask); -extern int intel_msic_bulk_read(unsigned short *reg, u8 *buf, size_t count); -extern int intel_msic_bulk_write(unsigned short *reg, u8 *buf, size_t count); - -/* - * pdev_to_intel_msic - gets an MSIC instance from the platform device - * @pdev: platform device pointer - * - * The client drivers need to have pointer to the MSIC instance if they - * want to call intel_msic_irq_read(). This macro can be used for - * convenience to get the MSIC pointer from @pdev where needed. This is - * _only_ valid for devices which are managed by the MSIC. - */ -#define pdev_to_intel_msic(pdev) (dev_get_drvdata(pdev->dev.parent)) - -extern int intel_msic_irq_read(struct intel_msic *msic, unsigned short reg, - u8 *val); - -#endif /* __LINUX_MFD_INTEL_MSIC_H__ */ -- cgit v1.2.3 From 647bd7e7a93c494d7981ae66c8e7262a266d21c8 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Wed, 10 Feb 2021 13:01:16 +0200 Subject: MAINTAINERS: replace my with email with replacements This email will become inactive in a few weeks. This change removes it from the MAINTAINERS file and adds the people that will be responsible for the parts moving forward. Acked-by: Michael Hennerich Acked-by: Nuno Sa Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20210210110116.49955-1-alexandru.ardelean@analog.com Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 6b5990a28b44..65b2a9ea74da 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1025,7 +1025,7 @@ F: Documentation/devicetree/bindings/mux/adi,adgs1408.txt F: drivers/mux/adgs1408.c ANALOG DEVICES INC ADIN DRIVER -M: Alexandru Ardelean +M: Michael Hennerich L: netdev@vger.kernel.org S: Supported W: http://ez.analog.com/community/linux-device-drivers @@ -1033,7 +1033,7 @@ F: Documentation/devicetree/bindings/net/adi,adin.yaml F: drivers/net/phy/adin.c ANALOG DEVICES INC ADIS DRIVER LIBRARY -M: Alexandru Ardelean +M: Nuno Sa L: linux-iio@vger.kernel.org S: Supported F: drivers/iio/imu/adis.c -- cgit v1.2.3 From 48139bad913d660d1f6a72ee215297e6749bc6f1 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 10 Feb 2021 10:34:33 -0800 Subject: ACRN: update MAINTAINERS: mailing list is subscribers-only Mark the acrn-dev mailing list as subscribers-only. Evidence from a previous patch: acrn-dev@lists.projectacrn.org SMTP error from remote mail server after end of data: 510 5.1.1 Your email address, rdunlap@infradead.org, is not subscribed to that group. Cc: Shuo Liu Cc: acrn-dev@lists.projectacrn.org Cc: Andrew Morton Cc: Greg Kroah-Hartman Signed-off-by: Randy Dunlap Link: https://lore.kernel.org/r/20210210183433.18746-1-rdunlap@infradead.org Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 65b2a9ea74da..11d37eb4d914 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -438,7 +438,7 @@ F: include/uapi/linux/wmi.h ACRN HYPERVISOR SERVICE MODULE M: Shuo Liu -L: acrn-dev@lists.projectacrn.org +L: acrn-dev@lists.projectacrn.org (subscribers-only) S: Supported W: https://projectacrn.org F: Documentation/virt/acrn/ -- cgit v1.2.3 From 4590d98f5a4f466d17e5c81d7c9fc796da9a8cee Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 11 Feb 2021 15:40:02 +0200 Subject: sfi: Remove framework for deprecated firmware SFI-based platforms are gone. So does this framework. This removes mention of SFI through the drivers and other code as well. Signed-off-by: Andy Shevchenko Reviewed-by: Hans de Goede Acked-by: Linus Walleij Signed-off-by: Rafael J. Wysocki --- Documentation/ABI/testing/sysfs-firmware-sfi | 15 - Documentation/ABI/testing/sysfs-platform-kim | 2 +- MAINTAINERS | 7 - arch/x86/Kconfig | 7 +- arch/x86/include/asm/intel-mid.h | 37 -- arch/x86/include/asm/intel_scu_ipc_legacy.h | 58 +-- arch/x86/include/asm/platform_sst_audio.h | 2 - arch/x86/kernel/apic/io_apic.c | 4 +- arch/x86/kernel/setup.c | 2 - arch/x86/pci/mmconfig-shared.c | 6 +- arch/x86/platform/Makefile | 1 - arch/x86/platform/intel-mid/Makefile | 5 - arch/x86/platform/intel-mid/device_libs/Makefile | 23 - .../intel-mid/device_libs/platform_bcm43xx.c | 101 ---- .../intel-mid/device_libs/platform_bma023.c | 16 - .../platform/intel-mid/device_libs/platform_bt.c | 101 ---- .../intel-mid/device_libs/platform_emc1403.c | 39 -- .../intel-mid/device_libs/platform_gpio_keys.c | 81 ---- .../intel-mid/device_libs/platform_lis331.c | 37 -- .../intel-mid/device_libs/platform_max7315.c | 77 --- .../intel-mid/device_libs/platform_mpu3050.c | 32 -- .../intel-mid/device_libs/platform_mrfld_pinctrl.c | 39 -- .../intel-mid/device_libs/platform_mrfld_rtc.c | 44 -- .../intel-mid/device_libs/platform_mrfld_sd.c | 43 -- .../intel-mid/device_libs/platform_mrfld_spidev.c | 50 -- .../intel-mid/device_libs/platform_pcal9555a.c | 95 ---- .../intel-mid/device_libs/platform_tc35876x.c | 42 -- .../intel-mid/device_libs/platform_tca6416.c | 53 --- arch/x86/platform/intel-mid/intel-mid.c | 1 - arch/x86/platform/intel-mid/sfi.c | 419 ----------------- arch/x86/platform/sfi/Makefile | 2 - arch/x86/platform/sfi/sfi.c | 100 ---- drivers/Makefile | 2 +- drivers/platform/x86/intel_scu_pcidrv.c | 22 +- drivers/sfi/Kconfig | 18 - drivers/sfi/Makefile | 4 - drivers/sfi/sfi_acpi.c | 214 --------- drivers/sfi/sfi_core.c | 522 --------------------- drivers/sfi/sfi_core.h | 81 ---- include/linux/sfi.h | 210 --------- include/linux/sfi_acpi.h | 93 ---- init/main.c | 2 - 42 files changed, 14 insertions(+), 2695 deletions(-) delete mode 100644 Documentation/ABI/testing/sysfs-firmware-sfi delete mode 100644 arch/x86/platform/intel-mid/device_libs/Makefile delete mode 100644 arch/x86/platform/intel-mid/device_libs/platform_bcm43xx.c delete mode 100644 arch/x86/platform/intel-mid/device_libs/platform_bma023.c delete mode 100644 arch/x86/platform/intel-mid/device_libs/platform_bt.c delete mode 100644 arch/x86/platform/intel-mid/device_libs/platform_emc1403.c delete mode 100644 arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c delete mode 100644 arch/x86/platform/intel-mid/device_libs/platform_lis331.c delete mode 100644 arch/x86/platform/intel-mid/device_libs/platform_max7315.c delete mode 100644 arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c delete mode 100644 arch/x86/platform/intel-mid/device_libs/platform_mrfld_pinctrl.c delete mode 100644 arch/x86/platform/intel-mid/device_libs/platform_mrfld_rtc.c delete mode 100644 arch/x86/platform/intel-mid/device_libs/platform_mrfld_sd.c delete mode 100644 arch/x86/platform/intel-mid/device_libs/platform_mrfld_spidev.c delete mode 100644 arch/x86/platform/intel-mid/device_libs/platform_pcal9555a.c delete mode 100644 arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c delete mode 100644 arch/x86/platform/intel-mid/device_libs/platform_tca6416.c delete mode 100644 arch/x86/platform/intel-mid/sfi.c delete mode 100644 arch/x86/platform/sfi/Makefile delete mode 100644 arch/x86/platform/sfi/sfi.c delete mode 100644 drivers/sfi/Kconfig delete mode 100644 drivers/sfi/Makefile delete mode 100644 drivers/sfi/sfi_acpi.c delete mode 100644 drivers/sfi/sfi_core.c delete mode 100644 drivers/sfi/sfi_core.h delete mode 100644 include/linux/sfi.h delete mode 100644 include/linux/sfi_acpi.h (limited to 'MAINTAINERS') diff --git a/Documentation/ABI/testing/sysfs-firmware-sfi b/Documentation/ABI/testing/sysfs-firmware-sfi deleted file mode 100644 index 5210e0f06ddb..000000000000 --- a/Documentation/ABI/testing/sysfs-firmware-sfi +++ /dev/null @@ -1,15 +0,0 @@ -What: /sys/firmware/sfi/tables/ -Date: May 2010 -Contact: Len Brown -Description: - SFI defines a number of small static memory tables - so the kernel can get platform information from firmware. - - The tables are defined in the latest SFI specification: - http://simplefirmware.org/documentation - - While the tables are used by the kernel, user-space - can observe them this way:: - - # cd /sys/firmware/sfi/tables - # cat $TABLENAME > $TABLENAME.bin diff --git a/Documentation/ABI/testing/sysfs-platform-kim b/Documentation/ABI/testing/sysfs-platform-kim index a7f81de68046..6a52d6d2b601 100644 --- a/Documentation/ABI/testing/sysfs-platform-kim +++ b/Documentation/ABI/testing/sysfs-platform-kim @@ -7,7 +7,7 @@ Description: is connected. example: "/dev/ttyS0". The device name flows down to architecture specific board - initialization file from the SFI/ATAGS bootloader + initialization file from the ATAGS bootloader firmware. The name exposed is read from the user-space dameon and opens the device when install is requested. diff --git a/MAINTAINERS b/MAINTAINERS index 8fdb7fe27537..fd41b96d71bb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16234,13 +16234,6 @@ S: Maintained F: Documentation/fb/sm712fb.rst F: drivers/video/fbdev/sm712* -SIMPLE FIRMWARE INTERFACE (SFI) -S: Obsolete -W: http://simplefirmware.org/ -F: arch/x86/platform/sfi/ -F: drivers/sfi/ -F: include/linux/sfi*.h - SIMPLEFB FB DRIVER M: Hans de Goede L: linux-fbdev@vger.kernel.org diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index cc73f98c3e42..7f5b77055266 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -444,7 +444,7 @@ config X86_X2APIC If you don't know what to do here, say N. config X86_MPPARSE - bool "Enable MPS table" if ACPI || SFI + bool "Enable MPS table" if ACPI default y depends on X86_LOCAL_APIC help @@ -603,7 +603,6 @@ config X86_INTEL_MID depends on PCI depends on X86_64 || (PCI_GOANY && X86_32) depends on X86_IO_APIC - select SFI select I2C select DW_APB_TIMER select APB_TIMER @@ -2457,8 +2456,6 @@ source "kernel/power/Kconfig" source "drivers/acpi/Kconfig" -source "drivers/sfi/Kconfig" - config X86_APM_BOOT def_bool y depends on APM @@ -2645,7 +2642,7 @@ config PCI_DIRECT config PCI_MMCONFIG bool "Support mmconfig PCI config space access" if X86_64 default y - depends on PCI && (ACPI || SFI || JAILHOUSE_GUEST) + depends on PCI && (ACPI || JAILHOUSE_GUEST) depends on X86_64 || (PCI_GOANY || PCI_GOMMCONFIG) config PCI_OLPC diff --git a/arch/x86/include/asm/intel-mid.h b/arch/x86/include/asm/intel-mid.h index 7bda0587cf70..6306fe3e5c4a 100644 --- a/arch/x86/include/asm/intel-mid.h +++ b/arch/x86/include/asm/intel-mid.h @@ -7,7 +7,6 @@ #ifndef _ASM_X86_INTEL_MID_H #define _ASM_X86_INTEL_MID_H -#include #include #include @@ -22,39 +21,6 @@ extern void intel_mid_pwr_power_off(void); extern int intel_mid_pwr_get_lss_id(struct pci_dev *pdev); -extern int get_gpio_by_name(const char *name); - -/* - * Here defines the array of devices platform data that IAFW would export - * through SFI "DEVS" table, we use name and type to match the device and - * its platform data. - */ -struct devs_id { - char name[SFI_NAME_LEN + 1]; - u8 type; - u8 delay; - void *(*get_platform_data)(void *info); -}; - -#define sfi_device(i) \ - static const struct devs_id *const __intel_mid_sfi_##i##_dev __used \ - __section(".x86_intel_mid_dev.init") = &i - -/** -* struct mid_sd_board_info - template for SD device creation -* @name: identifies the driver -* @bus_num: board-specific identifier for a given SD controller -* @max_clk: the maximum frequency device supports -* @platform_data: the particular data stored there is driver-specific -*/ -struct mid_sd_board_info { - char name[SFI_NAME_LEN]; - int bus_num; - unsigned short addr; - u32 max_clk; - void *platform_data; -}; - /* * Medfield is the follow-up of Moorestown, it combines two chip solution into * one. Other than that it also added always-on and constant tsc and lapic @@ -99,7 +65,4 @@ static inline void intel_scu_devices_destroy(void) { } /* FSB 83MHz */ #define BSEL_SOC_FUSE_111 0x7 -/* The offset for the mapping of global gpio pin to irq */ -#define INTEL_MID_IRQ_OFFSET 0x100 - #endif /* _ASM_X86_INTEL_MID_H */ diff --git a/arch/x86/include/asm/intel_scu_ipc_legacy.h b/arch/x86/include/asm/intel_scu_ipc_legacy.h index f8b87d8face7..fa529e5ec142 100644 --- a/arch/x86/include/asm/intel_scu_ipc_legacy.h +++ b/arch/x86/include/asm/intel_scu_ipc_legacy.h @@ -2,73 +2,17 @@ #ifndef _ASM_X86_INTEL_SCU_IPC_LEGACY_H_ #define _ASM_X86_INTEL_SCU_IPC_LEGACY_H_ -#include - -#define IPCMSG_INDIRECT_READ 0x02 -#define IPCMSG_INDIRECT_WRITE 0x05 +#include #define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */ - -#define IPCMSG_WARM_RESET 0xF0 #define IPCMSG_COLD_RESET 0xF1 -#define IPCMSG_SOFT_RESET 0xF2 -#define IPCMSG_COLD_BOOT 0xF3 /* Don't call these in new code - they will be removed eventually */ -/* Read a vector */ -static inline int intel_scu_ipc_readv(u16 *addr, u8 *data, int len) -{ - return intel_scu_ipc_dev_readv(NULL, addr, data, len); -} - -/* Write a vector */ -static inline int intel_scu_ipc_writev(u16 *addr, u8 *data, int len) -{ - return intel_scu_ipc_dev_writev(NULL, addr, data, len); -} - -/* Update single register based on the mask */ -static inline int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask) -{ - return intel_scu_ipc_dev_update(NULL, addr, data, mask); -} - /* Issue commands to the SCU with or without data */ static inline int intel_scu_ipc_simple_command(int cmd, int sub) { return intel_scu_ipc_dev_simple_command(NULL, cmd, sub); } -static inline int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen, - u32 *out, int outlen) -{ - /* New API takes both inlen and outlen as bytes so convert here */ - size_t inbytes = inlen * sizeof(u32); - size_t outbytes = outlen * sizeof(u32); - - return intel_scu_ipc_dev_command_with_size(NULL, cmd, sub, in, inbytes, - inlen, out, outbytes); -} - -extern struct blocking_notifier_head intel_scu_notifier; - -static inline void intel_scu_notifier_add(struct notifier_block *nb) -{ - blocking_notifier_chain_register(&intel_scu_notifier, nb); -} - -static inline void intel_scu_notifier_remove(struct notifier_block *nb) -{ - blocking_notifier_chain_unregister(&intel_scu_notifier, nb); -} - -static inline int intel_scu_notifier_post(unsigned long v, void *p) -{ - return blocking_notifier_call_chain(&intel_scu_notifier, v, p); -} - -#define SCU_AVAILABLE 1 -#define SCU_DOWN 2 - #endif diff --git a/arch/x86/include/asm/platform_sst_audio.h b/arch/x86/include/asm/platform_sst_audio.h index 16b9f220bdeb..40f92270515b 100644 --- a/arch/x86/include/asm/platform_sst_audio.h +++ b/arch/x86/include/asm/platform_sst_audio.h @@ -10,8 +10,6 @@ #ifndef _PLATFORM_SST_AUDIO_H_ #define _PLATFORM_SST_AUDIO_H_ -#include - #define MAX_NUM_STREAMS_MRFLD 25 #define MAX_NUM_STREAMS MAX_NUM_STREAMS_MRFLD diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index e4ab4804b20d..c3b60c37c728 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -198,7 +198,7 @@ static int __init parse_noapic(char *str) } early_param("noapic", parse_noapic); -/* Will be called in mpparse/acpi/sfi codes for saving IRQ info */ +/* Will be called in mpparse/ACPI codes for saving IRQ info */ void mp_save_irq(struct mpc_intsrc *m) { int i; @@ -2863,7 +2863,7 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base, /* * If mp_register_ioapic() is called during early boot stage when - * walking ACPI/SFI/DT tables, it's too early to create irqdomain, + * walking ACPI/DT tables, it's too early to create irqdomain, * we are still using bootmem allocator. So delay it to setup_IO_APIC(). */ if (hotplug) { diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 740f3bdb3f61..d883176ef2ce 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -1185,7 +1184,6 @@ void __init setup_arch(char **cmdline_p) * Read APIC and some other early information from ACPI tables. */ acpi_boot_init(); - sfi_init(); x86_dtb_init(); /* diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 234998f196d4..de6bf0e7e8f8 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -11,9 +11,9 @@ * themselves. */ +#include #include #include -#include #include #include #include @@ -665,7 +665,7 @@ void __init pci_mmcfg_early_init(void) if (pci_mmcfg_check_hostbridge()) known_bridge = 1; else - acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); + acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); __pci_mmcfg_init(1); set_apei_filter(); @@ -683,7 +683,7 @@ void __init pci_mmcfg_late_init(void) /* MMCONFIG hasn't been enabled yet, try again */ if (pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF) { - acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); + acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); __pci_mmcfg_init(0); } } diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile index d0e835470d01..d1f5228225d9 100644 --- a/arch/x86/platform/Makefile +++ b/arch/x86/platform/Makefile @@ -11,6 +11,5 @@ obj-y += intel-mid/ obj-y += intel-quark/ obj-y += olpc/ obj-y += scx200/ -obj-y += sfi/ obj-y += ts5500/ obj-y += uv/ diff --git a/arch/x86/platform/intel-mid/Makefile b/arch/x86/platform/intel-mid/Makefile index 5794e661050c..ddfc08783fb8 100644 --- a/arch/x86/platform/intel-mid/Makefile +++ b/arch/x86/platform/intel-mid/Makefile @@ -1,7 +1,2 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o pwr.o - -# SFI specific code -ifdef CONFIG_X86_INTEL_MID -obj-$(CONFIG_SFI) += sfi.o device_libs/ -endif diff --git a/arch/x86/platform/intel-mid/device_libs/Makefile b/arch/x86/platform/intel-mid/device_libs/Makefile deleted file mode 100644 index 4d008b053ac8..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Family-Level Interface Shim (FLIS) -obj-$(subst m,y,$(CONFIG_PINCTRL_MERRIFIELD)) += platform_mrfld_pinctrl.o -# SDHCI Devices -obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += platform_mrfld_sd.o -# WiFi + BT -obj-$(subst m,y,$(CONFIG_BRCMFMAC_SDIO)) += platform_bcm43xx.o -obj-$(subst m,y,$(CONFIG_BT_HCIUART_BCM)) += platform_bt.o -# SPI Devices -obj-$(subst m,y,$(CONFIG_SPI_SPIDEV)) += platform_mrfld_spidev.o -# I2C Devices -obj-$(subst m,y,$(CONFIG_SENSORS_EMC1403)) += platform_emc1403.o -obj-$(subst m,y,$(CONFIG_SENSORS_LIS3LV02D)) += platform_lis331.o -obj-$(subst m,y,$(CONFIG_MPU3050_I2C)) += platform_mpu3050.o -obj-$(subst m,y,$(CONFIG_INPUT_BMA150)) += platform_bma023.o -obj-$(subst m,y,$(CONFIG_DRM_MEDFIELD)) += platform_tc35876x.o -# I2C GPIO Expanders -obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_max7315.o -obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_pcal9555a.o -obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_tca6416.o -# MISC Devices -obj-$(subst m,y,$(CONFIG_KEYBOARD_GPIO)) += platform_gpio_keys.o -obj-$(subst m,y,$(CONFIG_RTC_DRV_CMOS)) += platform_mrfld_rtc.o diff --git a/arch/x86/platform/intel-mid/device_libs/platform_bcm43xx.c b/arch/x86/platform/intel-mid/device_libs/platform_bcm43xx.c deleted file mode 100644 index 564c47c53f3a..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/platform_bcm43xx.c +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * platform_bcm43xx.c: bcm43xx platform data initialization file - * - * (C) Copyright 2016 Intel Corporation - * Author: Andy Shevchenko - */ - -#include -#include -#include -#include -#include - -#include - -#define WLAN_SFI_GPIO_IRQ_NAME "WLAN-interrupt" -#define WLAN_SFI_GPIO_ENABLE_NAME "WLAN-enable" - -#define WLAN_DEV_NAME "0000:00:01.3" - -static struct regulator_consumer_supply bcm43xx_vmmc_supply = { - .dev_name = WLAN_DEV_NAME, - .supply = "vmmc", -}; - -static struct regulator_init_data bcm43xx_vmmc_data = { - .constraints = { - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = 1, - .consumer_supplies = &bcm43xx_vmmc_supply, -}; - -static struct fixed_voltage_config bcm43xx_vmmc = { - .supply_name = "bcm43xx-vmmc-regulator", - /* - * Announce 2.0V here to be compatible with SDIO specification. The - * real voltage and signaling are still 1.8V. - */ - .microvolts = 2000000, /* 1.8V */ - .startup_delay = 250 * 1000, /* 250ms */ - .enabled_at_boot = 0, /* disabled at boot */ - .init_data = &bcm43xx_vmmc_data, -}; - -static struct platform_device bcm43xx_vmmc_regulator = { - .name = "reg-fixed-voltage", - .id = PLATFORM_DEVID_AUTO, - .dev = { - .platform_data = &bcm43xx_vmmc, - }, -}; - -static struct gpiod_lookup_table bcm43xx_vmmc_gpio_table = { - .dev_id = "reg-fixed-voltage.0", - .table = { - GPIO_LOOKUP("0000:00:0c.0", -1, NULL, GPIO_ACTIVE_LOW), - {} - }, -}; - -static int __init bcm43xx_regulator_register(void) -{ - struct gpiod_lookup_table *table = &bcm43xx_vmmc_gpio_table; - struct gpiod_lookup *lookup = table->table; - int ret; - - lookup[0].chip_hwnum = get_gpio_by_name(WLAN_SFI_GPIO_ENABLE_NAME); - gpiod_add_lookup_table(table); - - ret = platform_device_register(&bcm43xx_vmmc_regulator); - if (ret) { - pr_err("%s: vmmc regulator register failed\n", __func__); - return ret; - } - - return 0; -} - -static void __init *bcm43xx_platform_data(void *info) -{ - int ret; - - ret = bcm43xx_regulator_register(); - if (ret) - return NULL; - - pr_info("Using generic wifi platform data\n"); - - /* For now it's empty */ - return NULL; -} - -static const struct devs_id bcm43xx_clk_vmmc_dev_id __initconst = { - .name = "bcm43xx_clk_vmmc", - .type = SFI_DEV_TYPE_SD, - .get_platform_data = &bcm43xx_platform_data, -}; - -sfi_device(bcm43xx_clk_vmmc_dev_id); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_bma023.c b/arch/x86/platform/intel-mid/device_libs/platform_bma023.c deleted file mode 100644 index 32912a17f68e..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/platform_bma023.c +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * platform_bma023.c: bma023 platform data initialization file - * - * (C) Copyright 2013 Intel Corporation - */ - -#include - -static const struct devs_id bma023_dev_id __initconst = { - .name = "bma023", - .type = SFI_DEV_TYPE_I2C, - .delay = 1, -}; - -sfi_device(bma023_dev_id); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_bt.c b/arch/x86/platform/intel-mid/device_libs/platform_bt.c deleted file mode 100644 index 31dda18bb370..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/platform_bt.c +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Bluetooth platform data initialization file - * - * (C) Copyright 2017 Intel Corporation - * Author: Andy Shevchenko - */ - -#include -#include -#include - -#include -#include -#include - -struct bt_sfi_data { - struct device *dev; - const char *name; - int (*setup)(struct bt_sfi_data *ddata); -}; - -static struct gpiod_lookup_table tng_bt_sfi_gpio_table = { - .dev_id = "hci_bcm", - .table = { - GPIO_LOOKUP("0000:00:0c.0", -1, "device-wakeup", GPIO_ACTIVE_HIGH), - GPIO_LOOKUP("0000:00:0c.0", -1, "shutdown", GPIO_ACTIVE_HIGH), - GPIO_LOOKUP("0000:00:0c.0", -1, "host-wakeup", GPIO_ACTIVE_HIGH), - { }, - }, -}; - -#define TNG_BT_SFI_GPIO_DEVICE_WAKEUP "bt_wakeup" -#define TNG_BT_SFI_GPIO_SHUTDOWN "BT-reset" -#define TNG_BT_SFI_GPIO_HOST_WAKEUP "bt_uart_enable" - -static int __init tng_bt_sfi_setup(struct bt_sfi_data *ddata) -{ - struct gpiod_lookup_table *table = &tng_bt_sfi_gpio_table; - struct gpiod_lookup *lookup = table->table; - struct pci_dev *pdev; - - /* Connected to /dev/ttyS0 */ - pdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(4, 1)); - if (!pdev) - return -ENODEV; - - ddata->dev = &pdev->dev; - ddata->name = table->dev_id; - - lookup[0].chip_hwnum = get_gpio_by_name(TNG_BT_SFI_GPIO_DEVICE_WAKEUP); - lookup[1].chip_hwnum = get_gpio_by_name(TNG_BT_SFI_GPIO_SHUTDOWN); - lookup[2].chip_hwnum = get_gpio_by_name(TNG_BT_SFI_GPIO_HOST_WAKEUP); - - gpiod_add_lookup_table(table); - return 0; -} - -static struct bt_sfi_data tng_bt_sfi_data __initdata = { - .setup = tng_bt_sfi_setup, -}; - -static const struct x86_cpu_id bt_sfi_cpu_ids[] = { - X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID, &tng_bt_sfi_data), - {} -}; - -static int __init bt_sfi_init(void) -{ - struct platform_device_info info; - struct platform_device *pdev; - const struct x86_cpu_id *id; - struct bt_sfi_data *ddata; - int ret; - - id = x86_match_cpu(bt_sfi_cpu_ids); - if (!id) - return -ENODEV; - - ddata = (struct bt_sfi_data *)id->driver_data; - if (!ddata) - return -ENODEV; - - ret = ddata->setup(ddata); - if (ret) - return ret; - - memset(&info, 0, sizeof(info)); - info.fwnode = ddata->dev->fwnode; - info.parent = ddata->dev; - info.name = ddata->name, - info.id = PLATFORM_DEVID_NONE, - - pdev = platform_device_register_full(&info); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); - - dev_info(ddata->dev, "Registered Bluetooth device: %s\n", ddata->name); - return 0; -} -device_initcall(bt_sfi_init); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c b/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c deleted file mode 100644 index a2508582a0b1..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * platform_emc1403.c: emc1403 platform data initialization file - * - * (C) Copyright 2013 Intel Corporation - * Author: Sathyanarayanan Kuppuswamy - */ - -#include -#include -#include -#include - -static void __init *emc1403_platform_data(void *info) -{ - static short intr2nd_pdata; - struct i2c_board_info *i2c_info = info; - int intr = get_gpio_by_name("thermal_int"); - int intr2nd = get_gpio_by_name("thermal_alert"); - - if (intr < 0) - return NULL; - if (intr2nd < 0) - return NULL; - - i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; - intr2nd_pdata = intr2nd + INTEL_MID_IRQ_OFFSET; - - return &intr2nd_pdata; -} - -static const struct devs_id emc1403_dev_id __initconst = { - .name = "emc1403", - .type = SFI_DEV_TYPE_I2C, - .delay = 1, - .get_platform_data = &emc1403_platform_data, -}; - -sfi_device(emc1403_dev_id); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c b/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c deleted file mode 100644 index d9435d2196a4..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * platform_gpio_keys.c: gpio_keys platform data initialization file - * - * (C) Copyright 2013 Intel Corporation - * Author: Sathyanarayanan Kuppuswamy - */ - -#include -#include -#include -#include -#include -#include -#include - -#define DEVICE_NAME "gpio-keys" - -/* - * we will search these buttons in SFI GPIO table (by name) - * and register them dynamically. Please add all possible - * buttons here, we will shrink them if no GPIO found. - */ -static struct gpio_keys_button gpio_button[] = { - {KEY_POWER, -1, 1, "power_btn", EV_KEY, 0, 3000}, - {KEY_PROG1, -1, 1, "prog_btn1", EV_KEY, 0, 20}, - {KEY_PROG2, -1, 1, "prog_btn2", EV_KEY, 0, 20}, - {SW_LID, -1, 1, "lid_switch", EV_SW, 0, 20}, - {KEY_VOLUMEUP, -1, 1, "vol_up", EV_KEY, 0, 20}, - {KEY_VOLUMEDOWN, -1, 1, "vol_down", EV_KEY, 0, 20}, - {KEY_MUTE, -1, 1, "mute_enable", EV_KEY, 0, 20}, - {KEY_VOLUMEUP, -1, 1, "volume_up", EV_KEY, 0, 20}, - {KEY_VOLUMEDOWN, -1, 1, "volume_down", EV_KEY, 0, 20}, - {KEY_CAMERA, -1, 1, "camera_full", EV_KEY, 0, 20}, - {KEY_CAMERA_FOCUS, -1, 1, "camera_half", EV_KEY, 0, 20}, - {SW_KEYPAD_SLIDE, -1, 1, "MagSw1", EV_SW, 0, 20}, - {SW_KEYPAD_SLIDE, -1, 1, "MagSw2", EV_SW, 0, 20}, -}; - -static struct gpio_keys_platform_data gpio_keys = { - .buttons = gpio_button, - .rep = 1, - .nbuttons = -1, /* will fill it after search */ -}; - -static struct platform_device pb_device = { - .name = DEVICE_NAME, - .id = -1, - .dev = { - .platform_data = &gpio_keys, - }, -}; - -/* - * Shrink the non-existent buttons, register the gpio button - * device if there is some - */ -static int __init pb_keys_init(void) -{ - struct gpio_keys_button *gb = gpio_button; - int i, good = 0; - - for (i = 0; i < ARRAY_SIZE(gpio_button); i++) { - gb[i].gpio = get_gpio_by_name(gb[i].desc); - pr_debug("info[%2d]: name = %s, gpio = %d\n", i, gb[i].desc, - gb[i].gpio); - if (gb[i].gpio < 0) - continue; - - if (i != good) - gb[good] = gb[i]; - good++; - } - - if (good) { - gpio_keys.nbuttons = good; - return platform_device_register(&pb_device); - } - return 0; -} -late_initcall(pb_keys_init); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_lis331.c b/arch/x86/platform/intel-mid/device_libs/platform_lis331.c deleted file mode 100644 index a4485cd638c6..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/platform_lis331.c +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * platform_lis331.c: lis331 platform data initialization file - * - * (C) Copyright 2013 Intel Corporation - * Author: Sathyanarayanan Kuppuswamy - */ - -#include -#include -#include - -static void __init *lis331dl_platform_data(void *info) -{ - static short intr2nd_pdata; - struct i2c_board_info *i2c_info = info; - int intr = get_gpio_by_name("accel_int"); - int intr2nd = get_gpio_by_name("accel_2"); - - if (intr < 0) - return NULL; - if (intr2nd < 0) - return NULL; - - i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; - intr2nd_pdata = intr2nd + INTEL_MID_IRQ_OFFSET; - - return &intr2nd_pdata; -} - -static const struct devs_id lis331dl_dev_id __initconst = { - .name = "i2c_accel", - .type = SFI_DEV_TYPE_I2C, - .get_platform_data = &lis331dl_platform_data, -}; - -sfi_device(lis331dl_dev_id); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_max7315.c b/arch/x86/platform/intel-mid/device_libs/platform_max7315.c deleted file mode 100644 index e9287c3184da..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/platform_max7315.c +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * platform_max7315.c: max7315 platform data initialization file - * - * (C) Copyright 2013 Intel Corporation - * Author: Sathyanarayanan Kuppuswamy - */ - -#include -#include -#include -#include -#include - -#define MAX7315_NUM 2 - -static void __init *max7315_platform_data(void *info) -{ - static struct pca953x_platform_data max7315_pdata[MAX7315_NUM]; - static int nr; - struct pca953x_platform_data *max7315 = &max7315_pdata[nr]; - struct i2c_board_info *i2c_info = info; - int gpio_base, intr; - char base_pin_name[SFI_NAME_LEN + 1]; - char intr_pin_name[SFI_NAME_LEN + 1]; - - if (nr == MAX7315_NUM) { - pr_err("too many max7315s, we only support %d\n", - MAX7315_NUM); - return NULL; - } - /* we have several max7315 on the board, we only need load several - * instances of the same pca953x driver to cover them - */ - strcpy(i2c_info->type, "max7315"); - if (nr++) { - snprintf(base_pin_name, sizeof(base_pin_name), - "max7315_%d_base", nr); - snprintf(intr_pin_name, sizeof(intr_pin_name), - "max7315_%d_int", nr); - } else { - strcpy(base_pin_name, "max7315_base"); - strcpy(intr_pin_name, "max7315_int"); - } - - gpio_base = get_gpio_by_name(base_pin_name); - intr = get_gpio_by_name(intr_pin_name); - - if (gpio_base < 0) - return NULL; - max7315->gpio_base = gpio_base; - if (intr != -1) { - i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; - max7315->irq_base = gpio_base + INTEL_MID_IRQ_OFFSET; - } else { - i2c_info->irq = -1; - max7315->irq_base = -1; - } - return max7315; -} - -static const struct devs_id max7315_dev_id __initconst = { - .name = "i2c_max7315", - .type = SFI_DEV_TYPE_I2C, - .delay = 1, - .get_platform_data = &max7315_platform_data, -}; - -static const struct devs_id max7315_2_dev_id __initconst = { - .name = "i2c_max7315_2", - .type = SFI_DEV_TYPE_I2C, - .delay = 1, - .get_platform_data = &max7315_platform_data, -}; - -sfi_device(max7315_dev_id); -sfi_device(max7315_2_dev_id); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c b/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c deleted file mode 100644 index 28a182713934..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * platform_mpu3050.c: mpu3050 platform data initialization file - * - * (C) Copyright 2013 Intel Corporation - * Author: Sathyanarayanan Kuppuswamy - */ - -#include -#include -#include - -static void *mpu3050_platform_data(void *info) -{ - struct i2c_board_info *i2c_info = info; - int intr = get_gpio_by_name("mpu3050_int"); - - if (intr < 0) - return NULL; - - i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; - return NULL; -} - -static const struct devs_id mpu3050_dev_id __initconst = { - .name = "mpu3050", - .type = SFI_DEV_TYPE_I2C, - .delay = 1, - .get_platform_data = &mpu3050_platform_data, -}; - -sfi_device(mpu3050_dev_id); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_pinctrl.c b/arch/x86/platform/intel-mid/device_libs/platform_mrfld_pinctrl.c deleted file mode 100644 index 605e1f94ad89..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_pinctrl.c +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Intel Merrifield FLIS platform device initialization file - * - * Copyright (C) 2016, Intel Corporation - * - * Author: Andy Shevchenko - */ - -#include -#include -#include - -#include - -#define FLIS_BASE_ADDR 0xff0c0000 -#define FLIS_LENGTH 0x8000 - -static struct resource mrfld_pinctrl_mmio_resource = { - .start = FLIS_BASE_ADDR, - .end = FLIS_BASE_ADDR + FLIS_LENGTH - 1, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device mrfld_pinctrl_device = { - .name = "pinctrl-merrifield", - .id = PLATFORM_DEVID_NONE, - .resource = &mrfld_pinctrl_mmio_resource, - .num_resources = 1, -}; - -static int __init mrfld_pinctrl_init(void) -{ - if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER) - return platform_device_register(&mrfld_pinctrl_device); - - return -ENODEV; -} -arch_initcall(mrfld_pinctrl_init); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_rtc.c b/arch/x86/platform/intel-mid/device_libs/platform_mrfld_rtc.c deleted file mode 100644 index 40e9808a9634..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_rtc.c +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Intel Merrifield legacy RTC initialization file - * - * (C) Copyright 2017 Intel Corporation - * - * Author: Andy Shevchenko - */ - -#include - -#include -#include -#include -#include -#include - -static int __init mrfld_legacy_rtc_alloc_irq(void) -{ - struct irq_alloc_info info; - int ret; - - if (!x86_platform.legacy.rtc) - return -ENODEV; - - ioapic_set_alloc_attr(&info, NUMA_NO_NODE, 1, 0); - ret = mp_map_gsi_to_irq(RTC_IRQ, IOAPIC_MAP_ALLOC, &info); - if (ret < 0) { - pr_info("Failed to allocate RTC interrupt. Disabling RTC\n"); - x86_platform.legacy.rtc = 0; - return ret; - } - - return 0; -} - -static int __init mrfld_legacy_rtc_init(void) -{ - if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER) - return -ENODEV; - - return mrfld_legacy_rtc_alloc_irq(); -} -arch_initcall(mrfld_legacy_rtc_init); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_sd.c b/arch/x86/platform/intel-mid/device_libs/platform_mrfld_sd.c deleted file mode 100644 index fe3b7ff975f3..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_sd.c +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * SDHCI platform data initilisation file - * - * (C) Copyright 2016 Intel Corporation - * Author: Andy Shevchenko - */ - -#include -#include - -#include - -#include - -#define INTEL_MRFLD_SD 2 -#define INTEL_MRFLD_SD_CD_GPIO 77 - -static struct sdhci_pci_data mrfld_sdhci_pci_data = { - .rst_n_gpio = -EINVAL, - .cd_gpio = INTEL_MRFLD_SD_CD_GPIO, -}; - -static struct sdhci_pci_data * -mrfld_sdhci_pci_get_data(struct pci_dev *pdev, int slotno) -{ - unsigned int func = PCI_FUNC(pdev->devfn); - - if (func == INTEL_MRFLD_SD) - return &mrfld_sdhci_pci_data; - - return NULL; -} - -static int __init mrfld_sd_init(void) -{ - if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER) - return -ENODEV; - - sdhci_pci_get_data = mrfld_sdhci_pci_get_data; - return 0; -} -arch_initcall(mrfld_sd_init); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_spidev.c b/arch/x86/platform/intel-mid/device_libs/platform_mrfld_spidev.c deleted file mode 100644 index b828f4fd40be..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_spidev.c +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * spidev platform data initialization file - * - * (C) Copyright 2014, 2016 Intel Corporation - * Authors: Andy Shevchenko - * Dan O'Donovan - */ - -#include -#include -#include -#include -#include - -#include - -#define MRFLD_SPI_DEFAULT_DMA_BURST 8 -#define MRFLD_SPI_DEFAULT_TIMEOUT 500 - -/* GPIO pin for spidev chipselect */ -#define MRFLD_SPIDEV_GPIO_CS 111 - -static struct pxa2xx_spi_chip spidev_spi_chip = { - .dma_burst_size = MRFLD_SPI_DEFAULT_DMA_BURST, - .timeout = MRFLD_SPI_DEFAULT_TIMEOUT, - .gpio_cs = MRFLD_SPIDEV_GPIO_CS, -}; - -static void __init *spidev_platform_data(void *info) -{ - struct spi_board_info *spi_info = info; - - if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER) - return ERR_PTR(-ENODEV); - - spi_info->mode = SPI_MODE_0; - spi_info->controller_data = &spidev_spi_chip; - - return NULL; -} - -static const struct devs_id spidev_dev_id __initconst = { - .name = "spidev", - .type = SFI_DEV_TYPE_SPI, - .delay = 0, - .get_platform_data = &spidev_platform_data, -}; - -sfi_device(spidev_dev_id); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_pcal9555a.c b/arch/x86/platform/intel-mid/device_libs/platform_pcal9555a.c deleted file mode 100644 index 5609d8da3978..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/platform_pcal9555a.c +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * PCAL9555a platform data initialization file - * - * Copyright (C) 2016, Intel Corporation - * - * Authors: Andy Shevchenko - * Dan O'Donovan - */ - -#include -#include -#include -#include -#include - -#include - -#define PCAL9555A_NUM 4 - -static struct pca953x_platform_data pcal9555a_pdata[PCAL9555A_NUM]; -static int nr; - -static void __init *pcal9555a_platform_data(void *info) -{ - struct i2c_board_info *i2c_info = info; - char *type = i2c_info->type; - struct pca953x_platform_data *pcal9555a; - char base_pin_name[SFI_NAME_LEN + 1]; - char intr_pin_name[SFI_NAME_LEN + 1]; - int gpio_base, intr; - - snprintf(base_pin_name, sizeof(base_pin_name), "%s_base", type); - snprintf(intr_pin_name, sizeof(intr_pin_name), "%s_int", type); - - gpio_base = get_gpio_by_name(base_pin_name); - intr = get_gpio_by_name(intr_pin_name); - - /* Check if the SFI record valid */ - if (gpio_base == -1) - return NULL; - - if (nr >= PCAL9555A_NUM) { - pr_err("%s: Too many instances, only %d supported\n", __func__, - PCAL9555A_NUM); - return NULL; - } - - pcal9555a = &pcal9555a_pdata[nr++]; - pcal9555a->gpio_base = gpio_base; - - if (intr >= 0) { - i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; - pcal9555a->irq_base = gpio_base + INTEL_MID_IRQ_OFFSET; - } else { - i2c_info->irq = -1; - pcal9555a->irq_base = -1; - } - - strcpy(type, "pcal9555a"); - return pcal9555a; -} - -static const struct devs_id pcal9555a_1_dev_id __initconst = { - .name = "pcal9555a-1", - .type = SFI_DEV_TYPE_I2C, - .delay = 1, - .get_platform_data = &pcal9555a_platform_data, -}; - -static const struct devs_id pcal9555a_2_dev_id __initconst = { - .name = "pcal9555a-2", - .type = SFI_DEV_TYPE_I2C, - .delay = 1, - .get_platform_data = &pcal9555a_platform_data, -}; - -static const struct devs_id pcal9555a_3_dev_id __initconst = { - .name = "pcal9555a-3", - .type = SFI_DEV_TYPE_I2C, - .delay = 1, - .get_platform_data = &pcal9555a_platform_data, -}; - -static const struct devs_id pcal9555a_4_dev_id __initconst = { - .name = "pcal9555a-4", - .type = SFI_DEV_TYPE_I2C, - .delay = 1, - .get_platform_data = &pcal9555a_platform_data, -}; - -sfi_device(pcal9555a_1_dev_id); -sfi_device(pcal9555a_2_dev_id); -sfi_device(pcal9555a_3_dev_id); -sfi_device(pcal9555a_4_dev_id); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c b/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c deleted file mode 100644 index 139738bbdd36..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * platform_tc35876x.c: tc35876x platform data initialization file - * - * (C) Copyright 2013 Intel Corporation - * Author: Sathyanarayanan Kuppuswamy - */ - -#include -#include - -static struct gpiod_lookup_table tc35876x_gpio_table = { - .dev_id = "i2c_disp_brig", - .table = { - GPIO_LOOKUP("0000:00:0c.0", -1, "bridge-reset", GPIO_ACTIVE_HIGH), - GPIO_LOOKUP("0000:00:0c.0", -1, "bl-en", GPIO_ACTIVE_HIGH), - GPIO_LOOKUP("0000:00:0c.0", -1, "vadd", GPIO_ACTIVE_HIGH), - { }, - }, -}; - -/*tc35876x DSI_LVDS bridge chip and panel platform data*/ -static void *tc35876x_platform_data(void *data) -{ - struct gpiod_lookup_table *table = &tc35876x_gpio_table; - struct gpiod_lookup *lookup = table->table; - - lookup[0].chip_hwnum = get_gpio_by_name("LCMB_RXEN"); - lookup[1].chip_hwnum = get_gpio_by_name("6S6P_BL_EN"); - lookup[2].chip_hwnum = get_gpio_by_name("EN_VREG_LCD_V3P3"); - gpiod_add_lookup_table(table); - - return NULL; -} - -static const struct devs_id tc35876x_dev_id __initconst = { - .name = "i2c_disp_brig", - .type = SFI_DEV_TYPE_I2C, - .get_platform_data = &tc35876x_platform_data, -}; - -sfi_device(tc35876x_dev_id); diff --git a/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c b/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c deleted file mode 100644 index e689d8f61059..000000000000 --- a/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * platform_tca6416.c: tca6416 platform data initialization file - * - * (C) Copyright 2013 Intel Corporation - * Author: Sathyanarayanan Kuppuswamy - */ - -#include -#include -#include -#include - -#define TCA6416_NAME "tca6416" -#define TCA6416_BASE "tca6416_base" -#define TCA6416_INTR "tca6416_int" - -static void *tca6416_platform_data(void *info) -{ - static struct pca953x_platform_data tca6416; - struct i2c_board_info *i2c_info = info; - int gpio_base, intr; - char base_pin_name[SFI_NAME_LEN + 1]; - char intr_pin_name[SFI_NAME_LEN + 1]; - - strcpy(i2c_info->type, TCA6416_NAME); - strcpy(base_pin_name, TCA6416_BASE); - strcpy(intr_pin_name, TCA6416_INTR); - - gpio_base = get_gpio_by_name(base_pin_name); - intr = get_gpio_by_name(intr_pin_name); - - if (gpio_base < 0) - return NULL; - tca6416.gpio_base = gpio_base; - if (intr >= 0) { - i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; - tca6416.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET; - } else { - i2c_info->irq = -1; - tca6416.irq_base = -1; - } - return &tca6416; -} - -static const struct devs_id tca6416_dev_id __initconst = { - .name = "tca6416", - .type = SFI_DEV_TYPE_I2C, - .delay = 1, - .get_platform_data = &tca6416_platform_data, -}; - -sfi_device(tca6416_dev_id); diff --git a/arch/x86/platform/intel-mid/intel-mid.c b/arch/x86/platform/intel-mid/intel-mid.c index 864b0c158b2f..2c044e260b4b 100644 --- a/arch/x86/platform/intel-mid/intel-mid.c +++ b/arch/x86/platform/intel-mid/intel-mid.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/platform/intel-mid/sfi.c b/arch/x86/platform/intel-mid/sfi.c deleted file mode 100644 index 63ae342ffb12..000000000000 --- a/arch/x86/platform/intel-mid/sfi.c +++ /dev/null @@ -1,419 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * intel_mid_sfi.c: Intel MID SFI initialization code - * - * (C) Copyright 2013 Intel Corporation - * Author: Sathyanarayanan Kuppuswamy - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SFI_SIG_OEM0 "OEM0" -#define MAX_IPCDEVS 24 -#define MAX_SCU_SPI 24 -#define MAX_SCU_I2C 24 - -static struct platform_device *ipc_devs[MAX_IPCDEVS]; -static struct spi_board_info *spi_devs[MAX_SCU_SPI]; -static struct i2c_board_info *i2c_devs[MAX_SCU_I2C]; -static struct sfi_gpio_table_entry *gpio_table; -static int ipc_next_dev; -static int spi_next_dev; -static int i2c_next_dev; -static int i2c_bus[MAX_SCU_I2C]; -static int gpio_num_entry; - -struct blocking_notifier_head intel_scu_notifier = - BLOCKING_NOTIFIER_INIT(intel_scu_notifier); -EXPORT_SYMBOL_GPL(intel_scu_notifier); - -#define intel_mid_sfi_get_pdata(dev, priv) \ - ((dev)->get_platform_data ? (dev)->get_platform_data(priv) : NULL) - -/* - * Parsing GPIO table first, since the DEVS table will need this table - * to map the pin name to the actual pin. - */ -static int __init sfi_parse_gpio(struct sfi_table_header *table) -{ - struct sfi_table_simple *sb; - struct sfi_gpio_table_entry *pentry; - int num, i; - - if (gpio_table) - return 0; - sb = (struct sfi_table_simple *)table; - num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry); - pentry = (struct sfi_gpio_table_entry *)sb->pentry; - - gpio_table = kmemdup(pentry, num * sizeof(*pentry), GFP_KERNEL); - if (!gpio_table) - return -1; - gpio_num_entry = num; - - pr_debug("GPIO pin info:\n"); - for (i = 0; i < num; i++, pentry++) - pr_debug("info[%2d]: controller = %16.16s, pin_name = %16.16s," - " pin = %d\n", i, - pentry->controller_name, - pentry->pin_name, - pentry->pin_no); - return 0; -} - -int get_gpio_by_name(const char *name) -{ - struct sfi_gpio_table_entry *pentry = gpio_table; - int i; - - if (!pentry) - return -1; - for (i = 0; i < gpio_num_entry; i++, pentry++) { - if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN)) - return pentry->pin_no; - } - return -EINVAL; -} - -static void __init intel_scu_ipc_device_register(struct platform_device *pdev) -{ - if (ipc_next_dev == MAX_IPCDEVS) - pr_err("too many SCU IPC devices"); - else - ipc_devs[ipc_next_dev++] = pdev; -} - -static void __init intel_scu_spi_device_register(struct spi_board_info *sdev) -{ - struct spi_board_info *new_dev; - - if (spi_next_dev == MAX_SCU_SPI) { - pr_err("too many SCU SPI devices"); - return; - } - - new_dev = kzalloc(sizeof(*sdev), GFP_KERNEL); - if (!new_dev) { - pr_err("failed to alloc mem for delayed spi dev %s\n", - sdev->modalias); - return; - } - *new_dev = *sdev; - - spi_devs[spi_next_dev++] = new_dev; -} - -static void __init intel_scu_i2c_device_register(int bus, - struct i2c_board_info *idev) -{ - struct i2c_board_info *new_dev; - - if (i2c_next_dev == MAX_SCU_I2C) { - pr_err("too many SCU I2C devices"); - return; - } - - new_dev = kzalloc(sizeof(*idev), GFP_KERNEL); - if (!new_dev) { - pr_err("failed to alloc mem for delayed i2c dev %s\n", - idev->type); - return; - } - *new_dev = *idev; - - i2c_bus[i2c_next_dev] = bus; - i2c_devs[i2c_next_dev++] = new_dev; -} - -/* Called by IPC driver */ -void intel_scu_devices_create(void) -{ - int i; - - for (i = 0; i < ipc_next_dev; i++) - platform_device_add(ipc_devs[i]); - - for (i = 0; i < spi_next_dev; i++) - spi_register_board_info(spi_devs[i], 1); - - for (i = 0; i < i2c_next_dev; i++) { - struct i2c_adapter *adapter; - struct i2c_client *client; - - adapter = i2c_get_adapter(i2c_bus[i]); - if (adapter) { - client = i2c_new_client_device(adapter, i2c_devs[i]); - if (IS_ERR(client)) - pr_err("can't create i2c device %s\n", - i2c_devs[i]->type); - } else - i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1); - } - intel_scu_notifier_post(SCU_AVAILABLE, NULL); -} -EXPORT_SYMBOL_GPL(intel_scu_devices_create); - -/* Called by IPC driver */ -void intel_scu_devices_destroy(void) -{ - int i; - - intel_scu_notifier_post(SCU_DOWN, NULL); - - for (i = 0; i < ipc_next_dev; i++) - platform_device_del(ipc_devs[i]); -} -EXPORT_SYMBOL_GPL(intel_scu_devices_destroy); - -static void __init install_irq_resource(struct platform_device *pdev, int irq) -{ - /* Single threaded */ - static struct resource res __initdata = { - .name = "IRQ", - .flags = IORESOURCE_IRQ, - }; - res.start = irq; - platform_device_add_resources(pdev, &res, 1); -} - -static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *pentry, - struct devs_id *dev) -{ - struct platform_device *pdev; - void *pdata = NULL; - - pr_debug("IPC bus, name = %16.16s, irq = 0x%2x\n", - pentry->name, pentry->irq); - - /* - * We need to call platform init of IPC devices to fill misc_pdata - * structure. It will be used in msic_init for initialization. - */ - pdata = intel_mid_sfi_get_pdata(dev, pentry); - if (IS_ERR(pdata)) - return; - - pdev = platform_device_alloc(pentry->name, 0); - if (pdev == NULL) { - pr_err("out of memory for SFI platform device '%s'.\n", - pentry->name); - return; - } - install_irq_resource(pdev, pentry->irq); - - pdev->dev.platform_data = pdata; - if (dev->delay) - intel_scu_ipc_device_register(pdev); - else - platform_device_add(pdev); -} - -static void __init sfi_handle_spi_dev(struct sfi_device_table_entry *pentry, - struct devs_id *dev) -{ - struct spi_board_info spi_info; - void *pdata = NULL; - - memset(&spi_info, 0, sizeof(spi_info)); - strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN); - spi_info.irq = ((pentry->irq == (u8)0xff) ? 0 : pentry->irq); - spi_info.bus_num = pentry->host_num; - spi_info.chip_select = pentry->addr; - spi_info.max_speed_hz = pentry->max_freq; - pr_debug("SPI bus=%d, name=%16.16s, irq=0x%2x, max_freq=%d, cs=%d\n", - spi_info.bus_num, - spi_info.modalias, - spi_info.irq, - spi_info.max_speed_hz, - spi_info.chip_select); - - pdata = intel_mid_sfi_get_pdata(dev, &spi_info); - if (IS_ERR(pdata)) - return; - - spi_info.platform_data = pdata; - if (dev->delay) - intel_scu_spi_device_register(&spi_info); - else - spi_register_board_info(&spi_info, 1); -} - -static void __init sfi_handle_i2c_dev(struct sfi_device_table_entry *pentry, - struct devs_id *dev) -{ - struct i2c_board_info i2c_info; - void *pdata = NULL; - - memset(&i2c_info, 0, sizeof(i2c_info)); - strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN); - i2c_info.irq = ((pentry->irq == (u8)0xff) ? 0 : pentry->irq); - i2c_info.addr = pentry->addr; - pr_debug("I2C bus = %d, name = %16.16s, irq = 0x%2x, addr = 0x%x\n", - pentry->host_num, - i2c_info.type, - i2c_info.irq, - i2c_info.addr); - pdata = intel_mid_sfi_get_pdata(dev, &i2c_info); - i2c_info.platform_data = pdata; - if (IS_ERR(pdata)) - return; - - if (dev->delay) - intel_scu_i2c_device_register(pentry->host_num, &i2c_info); - else - i2c_register_board_info(pentry->host_num, &i2c_info, 1); -} - -static void __init sfi_handle_sd_dev(struct sfi_device_table_entry *pentry, - struct devs_id *dev) -{ - struct mid_sd_board_info sd_info; - void *pdata; - - memset(&sd_info, 0, sizeof(sd_info)); - strncpy(sd_info.name, pentry->name, SFI_NAME_LEN); - sd_info.bus_num = pentry->host_num; - sd_info.max_clk = pentry->max_freq; - sd_info.addr = pentry->addr; - pr_debug("SD bus = %d, name = %16.16s, max_clk = %d, addr = 0x%x\n", - sd_info.bus_num, - sd_info.name, - sd_info.max_clk, - sd_info.addr); - pdata = intel_mid_sfi_get_pdata(dev, &sd_info); - if (IS_ERR(pdata)) - return; - - /* Nothing we can do with this for now */ - sd_info.platform_data = pdata; - - pr_debug("Successfully registered %16.16s", sd_info.name); -} - -extern struct devs_id *const __x86_intel_mid_dev_start[], - *const __x86_intel_mid_dev_end[]; - -static struct devs_id __init *get_device_id(u8 type, char *name) -{ - struct devs_id *const *dev_table; - - for (dev_table = __x86_intel_mid_dev_start; - dev_table < __x86_intel_mid_dev_end; dev_table++) { - struct devs_id *dev = *dev_table; - if (dev->type == type && - !strncmp(dev->name, name, SFI_NAME_LEN)) { - return dev; - } - } - - return NULL; -} - -static int __init sfi_parse_devs(struct sfi_table_header *table) -{ - struct sfi_table_simple *sb; - struct sfi_device_table_entry *pentry; - struct devs_id *dev = NULL; - int num, i, ret; - int polarity; - struct irq_alloc_info info; - - sb = (struct sfi_table_simple *)table; - num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry); - pentry = (struct sfi_device_table_entry *)sb->pentry; - - for (i = 0; i < num; i++, pentry++) { - int irq = pentry->irq; - - if (irq != (u8)0xff) { /* native RTE case */ - /* these SPI2 devices are not exposed to system as PCI - * devices, but they have separate RTE entry in IOAPIC - * so we have to enable them one by one here - */ - if (intel_mid_identify_cpu() == - INTEL_MID_CPU_CHIP_TANGIER) { - if (!strncmp(pentry->name, "r69001-ts-i2c", 13)) - /* active low */ - polarity = 1; - else if (!strncmp(pentry->name, - "synaptics_3202", 14)) - /* active low */ - polarity = 1; - else if (irq == 41) - /* fast_int_1 */ - polarity = 1; - else - /* active high */ - polarity = 0; - } else { - /* PNW and CLV go with active low */ - polarity = 1; - } - - ioapic_set_alloc_attr(&info, NUMA_NO_NODE, 1, polarity); - ret = mp_map_gsi_to_irq(irq, IOAPIC_MAP_ALLOC, &info); - WARN_ON(ret < 0); - } - - dev = get_device_id(pentry->type, pentry->name); - - if (!dev) - continue; - - switch (pentry->type) { - case SFI_DEV_TYPE_IPC: - sfi_handle_ipc_dev(pentry, dev); - break; - case SFI_DEV_TYPE_SPI: - sfi_handle_spi_dev(pentry, dev); - break; - case SFI_DEV_TYPE_I2C: - sfi_handle_i2c_dev(pentry, dev); - break; - case SFI_DEV_TYPE_SD: - sfi_handle_sd_dev(pentry, dev); - break; - case SFI_DEV_TYPE_UART: - case SFI_DEV_TYPE_HSI: - default: - break; - } - } - return 0; -} - -static int __init intel_mid_platform_init(void) -{ - sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, sfi_parse_gpio); - sfi_table_parse(SFI_SIG_DEVS, NULL, NULL, sfi_parse_devs); - return 0; -} -arch_initcall(intel_mid_platform_init); diff --git a/arch/x86/platform/sfi/Makefile b/arch/x86/platform/sfi/Makefile deleted file mode 100644 index 4eba24c2af67..000000000000 --- a/arch/x86/platform/sfi/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_SFI) += sfi.o diff --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c deleted file mode 100644 index 6259563760f9..000000000000 --- a/arch/x86/platform/sfi/sfi.c +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * sfi.c - x86 architecture SFI support. - * - * Copyright (c) 2009, Intel Corporation. - */ - -#define KMSG_COMPONENT "SFI" -#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifdef CONFIG_X86_LOCAL_APIC -static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; - -/* All CPUs enumerated by SFI must be present and enabled */ -static void __init mp_sfi_register_lapic(u8 id) -{ - if (MAX_LOCAL_APIC - id <= 0) { - pr_warn("Processor #%d invalid (max %d)\n", id, MAX_LOCAL_APIC); - return; - } - - pr_info("registering lapic[%d]\n", id); - - generic_processor_info(id, GET_APIC_VERSION(apic_read(APIC_LVR))); -} - -static int __init sfi_parse_cpus(struct sfi_table_header *table) -{ - struct sfi_table_simple *sb; - struct sfi_cpu_table_entry *pentry; - int i; - int cpu_num; - - sb = (struct sfi_table_simple *)table; - cpu_num = SFI_GET_NUM_ENTRIES(sb, struct sfi_cpu_table_entry); - pentry = (struct sfi_cpu_table_entry *)sb->pentry; - - for (i = 0; i < cpu_num; i++) { - mp_sfi_register_lapic(pentry->apic_id); - pentry++; - } - - smp_found_config = 1; - return 0; -} -#endif /* CONFIG_X86_LOCAL_APIC */ - -#ifdef CONFIG_X86_IO_APIC - -static int __init sfi_parse_ioapic(struct sfi_table_header *table) -{ - struct sfi_table_simple *sb; - struct sfi_apic_table_entry *pentry; - int i, num; - struct ioapic_domain_cfg cfg = { - .type = IOAPIC_DOMAIN_STRICT, - .ops = &mp_ioapic_irqdomain_ops, - }; - - sb = (struct sfi_table_simple *)table; - num = SFI_GET_NUM_ENTRIES(sb, struct sfi_apic_table_entry); - pentry = (struct sfi_apic_table_entry *)sb->pentry; - - for (i = 0; i < num; i++) { - mp_register_ioapic(i, pentry->phys_addr, gsi_top, &cfg); - pentry++; - } - - WARN(pic_mode, KERN_WARNING - "SFI: pic_mod shouldn't be 1 when IOAPIC table is present\n"); - pic_mode = 0; - return 0; -} -#endif /* CONFIG_X86_IO_APIC */ - -/* - * sfi_platform_init(): register lapics & io-apics - */ -int __init sfi_platform_init(void) -{ -#ifdef CONFIG_X86_LOCAL_APIC - register_lapic_address(sfi_lapic_addr); - sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, sfi_parse_cpus); -#endif -#ifdef CONFIG_X86_IO_APIC - sfi_table_parse(SFI_SIG_APIC, NULL, NULL, sfi_parse_ioapic); -#endif - return 0; -} diff --git a/drivers/Makefile b/drivers/Makefile index fd11b9ac4cc3..b2af1514a6b3 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -27,7 +27,7 @@ obj-y += idle/ obj-y += char/ipmi/ obj-$(CONFIG_ACPI) += acpi/ -obj-$(CONFIG_SFI) += sfi/ + # PnP must come after ACPI since it will eventually need to check if acpi # was used and do nothing if so obj-$(CONFIG_PNP) += pnp/ diff --git a/drivers/platform/x86/intel_scu_pcidrv.c b/drivers/platform/x86/intel_scu_pcidrv.c index 8c5fd8240da9..80abc708e4f2 100644 --- a/drivers/platform/x86/intel_scu_pcidrv.c +++ b/drivers/platform/x86/intel_scu_pcidrv.c @@ -17,7 +17,6 @@ static int intel_scu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - void (*setup_fn)(void) = (void (*)(void))id->driver_data; struct intel_scu_ipc_data scu_data = {}; struct intel_scu_ipc_dev *scu; int ret; @@ -30,27 +29,14 @@ static int intel_scu_pci_probe(struct pci_dev *pdev, scu_data.irq = pdev->irq; scu = intel_scu_ipc_register(&pdev->dev, &scu_data); - if (IS_ERR(scu)) - return PTR_ERR(scu); - - if (setup_fn) - setup_fn(); - return 0; -} - -static void intel_mid_scu_setup(void) -{ - intel_scu_devices_create(); + return PTR_ERR_OR_ZERO(scu); } static const struct pci_device_id pci_ids[] = { - { PCI_VDEVICE(INTEL, 0x080e), - .driver_data = (kernel_ulong_t)intel_mid_scu_setup }, - { PCI_VDEVICE(INTEL, 0x08ea), - .driver_data = (kernel_ulong_t)intel_mid_scu_setup }, + { PCI_VDEVICE(INTEL, 0x080e) }, + { PCI_VDEVICE(INTEL, 0x08ea) }, { PCI_VDEVICE(INTEL, 0x0a94) }, - { PCI_VDEVICE(INTEL, 0x11a0), - .driver_data = (kernel_ulong_t)intel_mid_scu_setup }, + { PCI_VDEVICE(INTEL, 0x11a0) }, { PCI_VDEVICE(INTEL, 0x1a94) }, { PCI_VDEVICE(INTEL, 0x5a94) }, {} diff --git a/drivers/sfi/Kconfig b/drivers/sfi/Kconfig deleted file mode 100644 index 3d0b64db214e..000000000000 --- a/drivers/sfi/Kconfig +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# SFI Configuration -# - -menuconfig SFI - bool "SFI (Simple Firmware Interface) Support" - help - The Simple Firmware Interface (SFI) provides a lightweight method - for platform firmware to pass information to the operating system - via static tables in memory. Kernel SFI support is required to - boot on SFI-only platforms. Currently, all SFI-only platforms are - based on the 2nd generation Intel Atom processor platform, - code-named Moorestown. - - For more information, see http://simplefirmware.org - - Say 'Y' here to enable the kernel to boot on SFI-only platforms. diff --git a/drivers/sfi/Makefile b/drivers/sfi/Makefile deleted file mode 100644 index ca9436b12386..000000000000 --- a/drivers/sfi/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-y += sfi_acpi.o -obj-y += sfi_core.o - diff --git a/drivers/sfi/sfi_acpi.c b/drivers/sfi/sfi_acpi.c deleted file mode 100644 index d277b36eb389..000000000000 --- a/drivers/sfi/sfi_acpi.c +++ /dev/null @@ -1,214 +0,0 @@ -/* sfi_acpi.c Simple Firmware Interface - ACPI extensions */ - -/* - - This file is provided under a dual BSD/GPLv2 license. When using or - redistributing this file, you may do so under either license. - - GPL LICENSE SUMMARY - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - The full GNU General Public License is included in this distribution - in the file called LICENSE.GPL. - - BSD LICENSE - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#define KMSG_COMPONENT "SFI" -#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt - -#include -#include -#include "sfi_core.h" - -/* - * SFI can access ACPI-defined tables via an optional ACPI XSDT. - * - * This allows re-use, and avoids re-definition, of standard tables. - * For example, the "MCFG" table is defined by PCI, reserved by ACPI, - * and is expected to be present many SFI-only systems. - */ - -static struct acpi_table_xsdt *xsdt_va __read_mostly; - -#define XSDT_GET_NUM_ENTRIES(ptable, entry_type) \ - ((ptable->header.length - sizeof(struct acpi_table_header)) / \ - (sizeof(entry_type))) - -static inline struct sfi_table_header *acpi_to_sfi_th( - struct acpi_table_header *th) -{ - return (struct sfi_table_header *)th; -} - -static inline struct acpi_table_header *sfi_to_acpi_th( - struct sfi_table_header *th) -{ - return (struct acpi_table_header *)th; -} - -/* - * sfi_acpi_parse_xsdt() - * - * Parse the ACPI XSDT for later access by sfi_acpi_table_parse(). - */ -static int __init sfi_acpi_parse_xsdt(struct sfi_table_header *th) -{ - struct sfi_table_key key = SFI_ANY_KEY; - int tbl_cnt, i; - void *ret; - - xsdt_va = (struct acpi_table_xsdt *)th; - tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64); - for (i = 0; i < tbl_cnt; i++) { - ret = sfi_check_table(xsdt_va->table_offset_entry[i], &key); - if (IS_ERR(ret)) { - disable_sfi(); - return -1; - } - } - - return 0; -} - -int __init sfi_acpi_init(void) -{ - struct sfi_table_key xsdt_key = { .sig = SFI_SIG_XSDT }; - - sfi_table_parse(SFI_SIG_XSDT, NULL, NULL, sfi_acpi_parse_xsdt); - - /* Only call the get_table to keep the table mapped */ - xsdt_va = (struct acpi_table_xsdt *)sfi_get_table(&xsdt_key); - return 0; -} - -static struct acpi_table_header *sfi_acpi_get_table(struct sfi_table_key *key) -{ - u32 tbl_cnt, i; - void *ret; - - tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64); - for (i = 0; i < tbl_cnt; i++) { - ret = sfi_check_table(xsdt_va->table_offset_entry[i], key); - if (!IS_ERR(ret) && ret) - return sfi_to_acpi_th(ret); - } - - return NULL; -} - -static void sfi_acpi_put_table(struct acpi_table_header *table) -{ - sfi_put_table(acpi_to_sfi_th(table)); -} - -/* - * sfi_acpi_table_parse() - * - * Find specified table in XSDT, run handler on it and return its return value - */ -int sfi_acpi_table_parse(char *signature, char *oem_id, char *oem_table_id, - int(*handler)(struct acpi_table_header *)) -{ - struct acpi_table_header *table = NULL; - struct sfi_table_key key; - int ret = 0; - - if (sfi_disabled) - return -1; - - key.sig = signature; - key.oem_id = oem_id; - key.oem_table_id = oem_table_id; - - table = sfi_acpi_get_table(&key); - if (!table) - return -EINVAL; - - ret = handler(table); - sfi_acpi_put_table(table); - return ret; -} - -static ssize_t sfi_acpi_table_show(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, char *buf, - loff_t offset, size_t count) -{ - struct sfi_table_attr *tbl_attr = - container_of(bin_attr, struct sfi_table_attr, attr); - struct acpi_table_header *th = NULL; - struct sfi_table_key key; - ssize_t cnt; - - key.sig = tbl_attr->name; - key.oem_id = NULL; - key.oem_table_id = NULL; - - th = sfi_acpi_get_table(&key); - if (!th) - return 0; - - cnt = memory_read_from_buffer(buf, count, &offset, - th, th->length); - sfi_acpi_put_table(th); - - return cnt; -} - - -void __init sfi_acpi_sysfs_init(void) -{ - u32 tbl_cnt, i; - struct sfi_table_attr *tbl_attr; - - tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64); - for (i = 0; i < tbl_cnt; i++) { - tbl_attr = - sfi_sysfs_install_table(xsdt_va->table_offset_entry[i]); - tbl_attr->attr.read = sfi_acpi_table_show; - } - - return; -} diff --git a/drivers/sfi/sfi_core.c b/drivers/sfi/sfi_core.c deleted file mode 100644 index a5136901dd8a..000000000000 --- a/drivers/sfi/sfi_core.c +++ /dev/null @@ -1,522 +0,0 @@ -/* sfi_core.c Simple Firmware Interface - core internals */ - -/* - - This file is provided under a dual BSD/GPLv2 license. When using or - redistributing this file, you may do so under either license. - - GPL LICENSE SUMMARY - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - The full GNU General Public License is included in this distribution - in the file called LICENSE.GPL. - - BSD LICENSE - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#define KMSG_COMPONENT "SFI" -#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sfi_core.h" - -#define ON_SAME_PAGE(addr1, addr2) \ - (((unsigned long)(addr1) & PAGE_MASK) == \ - ((unsigned long)(addr2) & PAGE_MASK)) -#define TABLE_ON_PAGE(page, table, size) (ON_SAME_PAGE(page, table) && \ - ON_SAME_PAGE(page, table + size)) - -int sfi_disabled __read_mostly; -EXPORT_SYMBOL(sfi_disabled); - -static u64 syst_pa __read_mostly; -static struct sfi_table_simple *syst_va __read_mostly; - -/* - * FW creates and saves the SFI tables in memory. When these tables get - * used, they may need to be mapped to virtual address space, and the mapping - * can happen before or after the memremap() is ready, so a flag is needed - * to indicating this - */ -static u32 sfi_use_memremap __read_mostly; - -/* - * sfi_un/map_memory calls early_memremap/memunmap which is a __init function - * and introduces section mismatch. So use __ref to make it calm. - */ -static void __iomem * __ref sfi_map_memory(u64 phys, u32 size) -{ - if (!phys || !size) - return NULL; - - if (sfi_use_memremap) - return memremap(phys, size, MEMREMAP_WB); - else - return early_memremap(phys, size); -} - -static void __ref sfi_unmap_memory(void __iomem *virt, u32 size) -{ - if (!virt || !size) - return; - - if (sfi_use_memremap) - memunmap(virt); - else - early_memunmap(virt, size); -} - -static void sfi_print_table_header(unsigned long long pa, - struct sfi_table_header *header) -{ - pr_info("%4.4s %llX, %04X (v%d %6.6s %8.8s)\n", - header->sig, pa, - header->len, header->rev, header->oem_id, - header->oem_table_id); -} - -/* - * sfi_verify_table() - * Sanity check table lengh, calculate checksum - */ -static int sfi_verify_table(struct sfi_table_header *table) -{ - - u8 checksum = 0; - u8 *puchar = (u8 *)table; - u32 length = table->len; - - /* Sanity check table length against arbitrary 1MB limit */ - if (length > 0x100000) { - pr_err("Invalid table length 0x%x\n", length); - return -1; - } - - while (length--) - checksum += *puchar++; - - if (checksum) { - pr_err("Checksum %2.2X should be %2.2X\n", - table->csum, table->csum - checksum); - return -1; - } - return 0; -} - -/* - * sfi_map_table() - * - * Return address of mapped table - * Check for common case that we can re-use mapping to SYST, - * which requires syst_pa, syst_va to be initialized. - */ -static struct sfi_table_header *sfi_map_table(u64 pa) -{ - struct sfi_table_header *th; - u32 length; - - if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header))) - th = sfi_map_memory(pa, sizeof(struct sfi_table_header)); - else - th = (void *)syst_va + (pa - syst_pa); - - /* If table fits on same page as its header, we are done */ - if (TABLE_ON_PAGE(th, th, th->len)) - return th; - - /* Entire table does not fit on same page as SYST */ - length = th->len; - if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header))) - sfi_unmap_memory(th, sizeof(struct sfi_table_header)); - - return sfi_map_memory(pa, length); -} - -/* - * sfi_unmap_table() - * - * Undoes effect of sfi_map_table() by unmapping table - * if it did not completely fit on same page as SYST. - */ -static void sfi_unmap_table(struct sfi_table_header *th) -{ - if (!TABLE_ON_PAGE(syst_va, th, th->len)) - sfi_unmap_memory(th, TABLE_ON_PAGE(th, th, th->len) ? - sizeof(*th) : th->len); -} - -static int sfi_table_check_key(struct sfi_table_header *th, - struct sfi_table_key *key) -{ - - if (strncmp(th->sig, key->sig, SFI_SIGNATURE_SIZE) - || (key->oem_id && strncmp(th->oem_id, - key->oem_id, SFI_OEM_ID_SIZE)) - || (key->oem_table_id && strncmp(th->oem_table_id, - key->oem_table_id, SFI_OEM_TABLE_ID_SIZE))) - return -1; - - return 0; -} - -/* - * This function will be used in 2 cases: - * 1. used to enumerate and verify the tables addressed by SYST/XSDT, - * thus no signature will be given (in kernel boot phase) - * 2. used to parse one specific table, signature must exist, and - * the mapped virt address will be returned, and the virt space - * will be released by call sfi_put_table() later - * - * This two cases are from two different functions with two different - * sections and causes section mismatch warning. So use __ref to tell - * modpost not to make any noise. - * - * Return value: - * NULL: when can't find a table matching the key - * ERR_PTR(error): error value - * virt table address: when a matched table is found - */ -struct sfi_table_header * - __ref sfi_check_table(u64 pa, struct sfi_table_key *key) -{ - struct sfi_table_header *th; - void *ret = NULL; - - th = sfi_map_table(pa); - if (!th) - return ERR_PTR(-ENOMEM); - - if (!key->sig) { - sfi_print_table_header(pa, th); - if (sfi_verify_table(th)) - ret = ERR_PTR(-EINVAL); - } else { - if (!sfi_table_check_key(th, key)) - return th; /* Success */ - } - - sfi_unmap_table(th); - return ret; -} - -/* - * sfi_get_table() - * - * Search SYST for the specified table with the signature in - * the key, and return the mapped table - */ -struct sfi_table_header *sfi_get_table(struct sfi_table_key *key) -{ - struct sfi_table_header *th; - u32 tbl_cnt, i; - - tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64); - for (i = 0; i < tbl_cnt; i++) { - th = sfi_check_table(syst_va->pentry[i], key); - if (!IS_ERR(th) && th) - return th; - } - - return NULL; -} - -void sfi_put_table(struct sfi_table_header *th) -{ - sfi_unmap_table(th); -} - -/* Find table with signature, run handler on it */ -int sfi_table_parse(char *signature, char *oem_id, char *oem_table_id, - sfi_table_handler handler) -{ - struct sfi_table_header *table = NULL; - struct sfi_table_key key; - int ret = -EINVAL; - - if (sfi_disabled || !handler || !signature) - goto exit; - - key.sig = signature; - key.oem_id = oem_id; - key.oem_table_id = oem_table_id; - - table = sfi_get_table(&key); - if (!table) - goto exit; - - ret = handler(table); - sfi_put_table(table); -exit: - return ret; -} -EXPORT_SYMBOL_GPL(sfi_table_parse); - -/* - * sfi_parse_syst() - * Checksum all the tables in SYST and print their headers - * - * success: set syst_va, return 0 - */ -static int __init sfi_parse_syst(void) -{ - struct sfi_table_key key = SFI_ANY_KEY; - int tbl_cnt, i; - void *ret; - - syst_va = sfi_map_memory(syst_pa, sizeof(struct sfi_table_simple)); - if (!syst_va) - return -ENOMEM; - - tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64); - for (i = 0; i < tbl_cnt; i++) { - ret = sfi_check_table(syst_va->pentry[i], &key); - if (IS_ERR(ret)) - return PTR_ERR(ret); - } - - return 0; -} - -/* - * The OS finds the System Table by searching 16-byte boundaries between - * physical address 0x000E0000 and 0x000FFFFF. The OS shall search this region - * starting at the low address and shall stop searching when the 1st valid SFI - * System Table is found. - * - * success: set syst_pa, return 0 - * fail: return -1 - */ -static __init int sfi_find_syst(void) -{ - unsigned long offset, len; - void *start; - - len = SFI_SYST_SEARCH_END - SFI_SYST_SEARCH_BEGIN; - start = sfi_map_memory(SFI_SYST_SEARCH_BEGIN, len); - if (!start) - return -1; - - for (offset = 0; offset < len; offset += 16) { - struct sfi_table_header *syst_hdr; - - syst_hdr = start + offset; - if (strncmp(syst_hdr->sig, SFI_SIG_SYST, - SFI_SIGNATURE_SIZE)) - continue; - - if (syst_hdr->len > PAGE_SIZE) - continue; - - sfi_print_table_header(SFI_SYST_SEARCH_BEGIN + offset, - syst_hdr); - - if (sfi_verify_table(syst_hdr)) - continue; - - /* - * Enforce SFI spec mandate that SYST reside within a page. - */ - if (!ON_SAME_PAGE(syst_pa, syst_pa + syst_hdr->len)) { - pr_info("SYST 0x%llx + 0x%x crosses page\n", - syst_pa, syst_hdr->len); - continue; - } - - /* Success */ - syst_pa = SFI_SYST_SEARCH_BEGIN + offset; - sfi_unmap_memory(start, len); - return 0; - } - - sfi_unmap_memory(start, len); - return -1; -} - -static struct kobject *sfi_kobj; -static struct kobject *tables_kobj; - -static ssize_t sfi_table_show(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, char *buf, - loff_t offset, size_t count) -{ - struct sfi_table_attr *tbl_attr = - container_of(bin_attr, struct sfi_table_attr, attr); - struct sfi_table_header *th = NULL; - struct sfi_table_key key; - ssize_t cnt; - - key.sig = tbl_attr->name; - key.oem_id = NULL; - key.oem_table_id = NULL; - - if (strncmp(SFI_SIG_SYST, tbl_attr->name, SFI_SIGNATURE_SIZE)) { - th = sfi_get_table(&key); - if (!th) - return 0; - - cnt = memory_read_from_buffer(buf, count, &offset, - th, th->len); - sfi_put_table(th); - } else - cnt = memory_read_from_buffer(buf, count, &offset, - syst_va, syst_va->header.len); - - return cnt; -} - -struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa) -{ - struct sfi_table_attr *tbl_attr; - struct sfi_table_header *th; - int ret; - - tbl_attr = kzalloc(sizeof(struct sfi_table_attr), GFP_KERNEL); - if (!tbl_attr) - return NULL; - - th = sfi_map_table(pa); - if (!th || !th->sig[0]) { - kfree(tbl_attr); - return NULL; - } - - sysfs_attr_init(&tbl_attr->attr.attr); - memcpy(tbl_attr->name, th->sig, SFI_SIGNATURE_SIZE); - - tbl_attr->attr.size = 0; - tbl_attr->attr.read = sfi_table_show; - tbl_attr->attr.attr.name = tbl_attr->name; - tbl_attr->attr.attr.mode = 0400; - - ret = sysfs_create_bin_file(tables_kobj, - &tbl_attr->attr); - if (ret) { - kfree(tbl_attr); - tbl_attr = NULL; - } - - sfi_unmap_table(th); - return tbl_attr; -} - -static int __init sfi_sysfs_init(void) -{ - int tbl_cnt, i; - - if (sfi_disabled) - return 0; - - sfi_kobj = kobject_create_and_add("sfi", firmware_kobj); - if (!sfi_kobj) - return 0; - - tables_kobj = kobject_create_and_add("tables", sfi_kobj); - if (!tables_kobj) { - kobject_put(sfi_kobj); - return 0; - } - - sfi_sysfs_install_table(syst_pa); - - tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64); - - for (i = 0; i < tbl_cnt; i++) - sfi_sysfs_install_table(syst_va->pentry[i]); - - sfi_acpi_sysfs_init(); - kobject_uevent(sfi_kobj, KOBJ_ADD); - kobject_uevent(tables_kobj, KOBJ_ADD); - pr_info("SFI sysfs interfaces init success\n"); - return 0; -} - -void __init sfi_init(void) -{ - if (!acpi_disabled) - disable_sfi(); - - if (sfi_disabled) - return; - - pr_info("Simple Firmware Interface v0.81 http://simplefirmware.org\n"); - - if (sfi_find_syst() || sfi_parse_syst() || sfi_platform_init()) - disable_sfi(); - - return; -} - -void __init sfi_init_late(void) -{ - int length; - - if (sfi_disabled) - return; - - length = syst_va->header.len; - sfi_unmap_memory(syst_va, sizeof(struct sfi_table_simple)); - - /* Use memremap now after it is ready */ - sfi_use_memremap = 1; - syst_va = sfi_map_memory(syst_pa, length); - - sfi_acpi_init(); -} - -/* - * The reason we put it here because we need wait till the /sys/firmware - * is setup, then our interface can be registered in /sys/firmware/sfi - */ -core_initcall(sfi_sysfs_init); diff --git a/drivers/sfi/sfi_core.h b/drivers/sfi/sfi_core.h deleted file mode 100644 index 1d5cfe854cf7..000000000000 --- a/drivers/sfi/sfi_core.h +++ /dev/null @@ -1,81 +0,0 @@ -/* sfi_core.h Simple Firmware Interface, internal header */ - -/* - - This file is provided under a dual BSD/GPLv2 license. When using or - redistributing this file, you may do so under either license. - - GPL LICENSE SUMMARY - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - The full GNU General Public License is included in this distribution - in the file called LICENSE.GPL. - - BSD LICENSE - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include - -struct sfi_table_key{ - char *sig; - char *oem_id; - char *oem_table_id; -}; - -/* sysfs interface */ -struct sfi_table_attr { - struct bin_attribute attr; - char name[8]; -}; - -#define SFI_ANY_KEY { .sig = NULL, .oem_id = NULL, .oem_table_id = NULL } - -extern int __init sfi_acpi_init(void); -extern struct sfi_table_header *sfi_check_table(u64 paddr, - struct sfi_table_key *key); -struct sfi_table_header *sfi_get_table(struct sfi_table_key *key); -extern void sfi_put_table(struct sfi_table_header *table); -extern struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa); -extern void __init sfi_acpi_sysfs_init(void); diff --git a/include/linux/sfi.h b/include/linux/sfi.h deleted file mode 100644 index e0e1597ef9e6..000000000000 --- a/include/linux/sfi.h +++ /dev/null @@ -1,210 +0,0 @@ -/* sfi.h Simple Firmware Interface */ - -/* - - This file is provided under a dual BSD/GPLv2 license. When using or - redistributing this file, you may do so under either license. - - GPL LICENSE SUMMARY - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - The full GNU General Public License is included in this distribution - in the file called LICENSE.GPL. - - BSD LICENSE - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef _LINUX_SFI_H -#define _LINUX_SFI_H - -#include -#include - -/* Table signatures reserved by the SFI specification */ -#define SFI_SIG_SYST "SYST" -#define SFI_SIG_FREQ "FREQ" -#define SFI_SIG_IDLE "IDLE" -#define SFI_SIG_CPUS "CPUS" -#define SFI_SIG_MTMR "MTMR" -#define SFI_SIG_MRTC "MRTC" -#define SFI_SIG_MMAP "MMAP" -#define SFI_SIG_APIC "APIC" -#define SFI_SIG_XSDT "XSDT" -#define SFI_SIG_WAKE "WAKE" -#define SFI_SIG_DEVS "DEVS" -#define SFI_SIG_GPIO "GPIO" - -#define SFI_SIGNATURE_SIZE 4 -#define SFI_OEM_ID_SIZE 6 -#define SFI_OEM_TABLE_ID_SIZE 8 - -#define SFI_NAME_LEN 16 - -#define SFI_SYST_SEARCH_BEGIN 0x000E0000 -#define SFI_SYST_SEARCH_END 0x000FFFFF - -#define SFI_GET_NUM_ENTRIES(ptable, entry_type) \ - ((ptable->header.len - sizeof(struct sfi_table_header)) / \ - (sizeof(entry_type))) -/* - * Table structures must be byte-packed to match the SFI specification, - * as they are provided by the BIOS. - */ -struct sfi_table_header { - char sig[SFI_SIGNATURE_SIZE]; - u32 len; - u8 rev; - u8 csum; - char oem_id[SFI_OEM_ID_SIZE]; - char oem_table_id[SFI_OEM_TABLE_ID_SIZE]; -} __packed; - -struct sfi_table_simple { - struct sfi_table_header header; - u64 pentry[1]; -} __packed; - -/* Comply with UEFI spec 2.1 */ -struct sfi_mem_entry { - u32 type; - u64 phys_start; - u64 virt_start; - u64 pages; - u64 attrib; -} __packed; - -struct sfi_cpu_table_entry { - u32 apic_id; -} __packed; - -struct sfi_cstate_table_entry { - u32 hint; /* MWAIT hint */ - u32 latency; /* latency in ms */ -} __packed; - -struct sfi_apic_table_entry { - u64 phys_addr; /* phy base addr for APIC reg */ -} __packed; - -struct sfi_freq_table_entry { - u32 freq_mhz; /* in MHZ */ - u32 latency; /* transition latency in ms */ - u32 ctrl_val; /* value to write to PERF_CTL */ -} __packed; - -struct sfi_wake_table_entry { - u64 phys_addr; /* pointer to where the wake vector locates */ -} __packed; - -struct sfi_timer_table_entry { - u64 phys_addr; /* phy base addr for the timer */ - u32 freq_hz; /* in HZ */ - u32 irq; -} __packed; - -struct sfi_rtc_table_entry { - u64 phys_addr; /* phy base addr for the RTC */ - u32 irq; -} __packed; - -struct sfi_device_table_entry { - u8 type; /* bus type, I2C, SPI or ...*/ -#define SFI_DEV_TYPE_SPI 0 -#define SFI_DEV_TYPE_I2C 1 -#define SFI_DEV_TYPE_UART 2 -#define SFI_DEV_TYPE_HSI 3 -#define SFI_DEV_TYPE_IPC 4 -#define SFI_DEV_TYPE_SD 5 - - u8 host_num; /* attached to host 0, 1...*/ - u16 addr; - u8 irq; - u32 max_freq; - char name[SFI_NAME_LEN]; -} __packed; - -struct sfi_gpio_table_entry { - char controller_name[SFI_NAME_LEN]; - u16 pin_no; - char pin_name[SFI_NAME_LEN]; -} __packed; - -typedef int (*sfi_table_handler) (struct sfi_table_header *table); - -#ifdef CONFIG_SFI -extern void __init sfi_init(void); -extern int __init sfi_platform_init(void); -extern void __init sfi_init_late(void); -extern int sfi_table_parse(char *signature, char *oem_id, char *oem_table_id, - sfi_table_handler handler); - -extern int sfi_disabled; -static inline void disable_sfi(void) -{ - sfi_disabled = 1; -} - -#else /* !CONFIG_SFI */ - -static inline void sfi_init(void) -{ -} - -static inline void sfi_init_late(void) -{ -} - -#define sfi_disabled 0 - -static inline int sfi_table_parse(char *signature, char *oem_id, - char *oem_table_id, - sfi_table_handler handler) -{ - return -1; -} - -#endif /* !CONFIG_SFI */ - -#endif /*_LINUX_SFI_H*/ diff --git a/include/linux/sfi_acpi.h b/include/linux/sfi_acpi.h deleted file mode 100644 index a6e555cbe05c..000000000000 --- a/include/linux/sfi_acpi.h +++ /dev/null @@ -1,93 +0,0 @@ -/* sfi.h Simple Firmware Interface */ - -/* - - This file is provided under a dual BSD/GPLv2 license. When using or - redistributing this file, you may do so under either license. - - GPL LICENSE SUMMARY - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - The full GNU General Public License is included in this distribution - in the file called LICENSE.GPL. - - BSD LICENSE - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef _LINUX_SFI_ACPI_H -#define _LINUX_SFI_ACPI_H - -#include -#include - -#ifdef CONFIG_SFI -extern int sfi_acpi_table_parse(char *signature, char *oem_id, - char *oem_table_id, - int (*handler)(struct acpi_table_header *)); - -static inline int __init acpi_sfi_table_parse(char *signature, - int (*handler)(struct acpi_table_header *)) -{ - if (!acpi_table_parse(signature, handler)) - return 0; - - return sfi_acpi_table_parse(signature, NULL, NULL, handler); -} -#else /* !CONFIG_SFI */ -static inline int sfi_acpi_table_parse(char *signature, char *oem_id, - char *oem_table_id, - int (*handler)(struct acpi_table_header *)) -{ - return -1; -} - -static inline int __init acpi_sfi_table_parse(char *signature, - int (*handler)(struct acpi_table_header *)) -{ - return acpi_table_parse(signature, handler); -} -#endif /* !CONFIG_SFI */ - -#endif /*_LINUX_SFI_ACPI_H*/ diff --git a/init/main.c b/init/main.c index a626e78dbf06..e9933cbf60d4 100644 --- a/init/main.c +++ b/init/main.c @@ -74,7 +74,6 @@ #include #include #include -#include #include #include #include @@ -1054,7 +1053,6 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void) acpi_subsystem_init(); arch_post_acpi_subsys_init(); - sfi_init_late(); kcsan_init(); /* Do the rest non-__init'ed, we're now alive */ -- cgit v1.2.3 From aec6c60a01d3a3170242d6a99372a388e1136dc6 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 16 Jan 2021 08:35:42 +0900 Subject: kbuild: check the minimum compiler version in Kconfig Paul Gortmaker reported a regression in the GCC version check. [1] If you use GCC 4.8, the build breaks before showing the error message "error Sorry, your version of GCC is too old - please use 4.9 or newer." I do not want to apply his fix-up since it implies we would not be able to remove any cc-option test. Anyway, I admit checking the GCC version in is too late. Almost at the same time, Linus also suggested to move the compiler version error to Kconfig time. [2] I unified the two similar scripts, gcc-version.sh and clang-version.sh into cc-version.sh. The old scripts invoked the compiler multiple times (3 times for gcc-version.sh, 4 times for clang-version.sh). I refactored the code so the new one invokes the compiler just once, and also tried my best to use shell-builtin commands where possible. The new script runs faster. $ time ./scripts/clang-version.sh clang 120000 real 0m0.029s user 0m0.012s sys 0m0.021s $ time ./scripts/cc-version.sh clang Clang 120000 real 0m0.009s user 0m0.006s sys 0m0.004s cc-version.sh also shows an error message if the compiler is too old: $ make defconfig CC=clang-9 *** Default configuration is based on 'x86_64_defconfig' *** *** Compiler is too old. *** Your Clang version: 9.0.1 *** Minimum Clang version: 10.0.1 *** scripts/Kconfig.include:46: Sorry, this compiler is not supported. make[1]: *** [scripts/kconfig/Makefile:81: defconfig] Error 1 make: *** [Makefile:602: defconfig] Error 2 The new script takes care of ICC because we have although I am not sure if building the kernel with ICC is well-supported. [1]: https://lore.kernel.org/r/20210110190807.134996-1-paul.gortmaker@windriver.com [2]: https://lore.kernel.org/r/CAHk-=wh-+TMHPTFo1qs-MYyK7tZh-OQovA=pP3=e06aCVp6_kA@mail.gmail.com Fixes: 87de84c9140e ("kbuild: remove cc-option test of -Werror=date-time") Reported-by: Paul Gortmaker Suggested-by: Linus Torvalds Reviewed-by: Nick Desaulniers Tested-by: Nick Desaulniers Reviewed-by: Nathan Chancellor Tested-by: Nathan Chancellor Reviewed-by: Miguel Ojeda Tested-by: Miguel Ojeda Tested-by: Sedat Dilek Signed-off-by: Masahiro Yamada --- MAINTAINERS | 1 - include/linux/compiler-clang.h | 10 ------ include/linux/compiler-gcc.h | 11 ------ init/Kconfig | 9 ++--- scripts/Kconfig.include | 6 ++++ scripts/cc-version.sh | 82 ++++++++++++++++++++++++++++++++++++++++++ scripts/clang-version.sh | 19 ---------- scripts/gcc-version.sh | 20 ----------- 8 files changed, 93 insertions(+), 65 deletions(-) create mode 100755 scripts/cc-version.sh delete mode 100755 scripts/clang-version.sh delete mode 100755 scripts/gcc-version.sh (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 667d03852191..df820969be1f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4314,7 +4314,6 @@ C: irc://chat.freenode.net/clangbuiltlinux F: Documentation/kbuild/llvm.rst F: include/linux/compiler-clang.h F: scripts/clang-tools/ -F: scripts/clang-version.sh F: scripts/lld-version.sh K: \b(?i:clang|llvm)\b diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h index 98cff1b4b088..04c0a5a717f7 100644 --- a/include/linux/compiler-clang.h +++ b/include/linux/compiler-clang.h @@ -3,16 +3,6 @@ #error "Please don't include directly, include instead." #endif -#define CLANG_VERSION (__clang_major__ * 10000 \ - + __clang_minor__ * 100 \ - + __clang_patchlevel__) - -#if CLANG_VERSION < 100001 -#ifndef __BPF_TRACING__ -# error Sorry, your version of Clang is too old - please use 10.0.1 or newer. -#endif -#endif - /* Compiler specific definitions for Clang compiler */ /* same as gcc, this was present in clang-2.6 so we can assume it works diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 555ab0fddbef..48750243db4c 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -10,17 +10,6 @@ + __GNUC_MINOR__ * 100 \ + __GNUC_PATCHLEVEL__) -/* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145 */ -#if GCC_VERSION < 40900 -# error Sorry, your version of GCC is too old - please use 4.9 or newer. -#elif defined(CONFIG_ARM64) && GCC_VERSION < 50100 -/* - * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63293 - * https://lore.kernel.org/r/20210107111841.GN1551@shell.armlinux.org.uk - */ -# error Sorry, your version of GCC is too old - please use 5.1 or newer. -#endif - /* * This macro obfuscates arithmetic on a variable address so that gcc * shouldn't recognize the original var, and make assumptions about it. diff --git a/init/Kconfig b/init/Kconfig index 29ad68325028..7bcfa24524c2 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -26,11 +26,11 @@ config CC_VERSION_TEXT and then every file will be rebuilt. config CC_IS_GCC - def_bool $(success,echo "$(CC_VERSION_TEXT)" | grep -q gcc) + def_bool $(success,test "$(cc-name)" = GCC) config GCC_VERSION int - default $(shell,$(srctree)/scripts/gcc-version.sh $(CC)) if CC_IS_GCC + default $(cc-version) if CC_IS_GCC default 0 config LD_VERSION @@ -38,14 +38,15 @@ config LD_VERSION default $(shell,$(LD) --version | $(srctree)/scripts/ld-version.sh) config CC_IS_CLANG - def_bool $(success,echo "$(CC_VERSION_TEXT)" | grep -q clang) + def_bool $(success,test "$(cc-name)" = Clang) config LD_IS_LLD def_bool $(success,$(LD) -v | head -n 1 | grep -q LLD) config CLANG_VERSION int - default $(shell,$(srctree)/scripts/clang-version.sh $(CC)) + default $(cc-version) if CC_IS_CLANG + default 0 config LLD_VERSION int diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include index a5fe72c504ff..0228cb9c74aa 100644 --- a/scripts/Kconfig.include +++ b/scripts/Kconfig.include @@ -39,6 +39,12 @@ as-instr = $(success,printf "%b\n" "$(1)" | $(CC) $(CLANG_FLAGS) -c -x assembler $(error-if,$(failure,command -v $(CC)),compiler '$(CC)' not found) $(error-if,$(failure,command -v $(LD)),linker '$(LD)' not found) +# Get the compiler name, version, and error out if it is not supported. +cc-info := $(shell,$(srctree)/scripts/cc-version.sh $(CC)) +$(error-if,$(success,test -z "$(cc-info)"),Sorry$(comma) this compiler is not supported.) +cc-name := $(shell,set -- $(cc-info) && echo $1) +cc-version := $(shell,set -- $(cc-info) && echo $2) + # Fail if the linker is gold as it's not capable of linking the kernel proper $(error-if,$(success, $(LD) -v | grep -q gold), gold linker '$(LD)' not supported) diff --git a/scripts/cc-version.sh b/scripts/cc-version.sh new file mode 100755 index 000000000000..3f2ee885b116 --- /dev/null +++ b/scripts/cc-version.sh @@ -0,0 +1,82 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Print the compiler name and its version in a 5 or 6-digit form. +# Also, perform the minimum version check. + +set -e + +# When you raise the minimum compiler version, please update +# Documentation/process/changes.rst as well. +gcc_min_version=4.9.0 +clang_min_version=10.0.1 +icc_min_version=16.0.3 # temporary + +# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63293 +# https://lore.kernel.org/r/20210107111841.GN1551@shell.armlinux.org.uk +if [ "$SRCARCH" = arm64 ]; then + gcc_min_version=5.1.0 +fi + +# Print the compiler name and some version components. +get_compiler_info() +{ + cat <<- EOF | "$@" -E -P -x c - 2>/dev/null + #if defined(__clang__) + Clang __clang_major__ __clang_minor__ __clang_patchlevel__ + #elif defined(__INTEL_COMPILER) + ICC __INTEL_COMPILER __INTEL_COMPILER_UPDATE + #elif defined(__GNUC__) + GCC __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__ + #else + unknown + #endif + EOF +} + +# Convert the version string x.y.z to a canonical 5 or 6-digit form. +get_canonical_version() +{ + IFS=. + set -- $1 + echo $((10000 * $1 + 100 * $2 + $3)) +} + +# $@ instead of $1 because multiple words might be given, e.g. CC="ccache gcc". +orig_args="$@" +set -- $(get_compiler_info "$@") + +name=$1 + +case "$name" in +GCC) + version=$2.$3.$4 + min_version=$gcc_min_version + ;; +Clang) + version=$2.$3.$4 + min_version=$clang_min_version + ;; +ICC) + version=$(($2 / 100)).$(($2 % 100)).$3 + min_version=$icc_min_version + ;; +*) + echo "$orig_args: unknown compiler" >&2 + exit 1 + ;; +esac + +cversion=$(get_canonical_version $version) +min_cversion=$(get_canonical_version $min_version) + +if [ "$cversion" -lt "$min_cversion" ]; then + echo >&2 "***" + echo >&2 "*** Compiler is too old." + echo >&2 "*** Your $name version: $version" + echo >&2 "*** Minimum $name version: $min_version" + echo >&2 "***" + exit 1 +fi + +echo $name $cversion diff --git a/scripts/clang-version.sh b/scripts/clang-version.sh deleted file mode 100755 index 6fabf0695761..000000000000 --- a/scripts/clang-version.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 -# -# clang-version clang-command -# -# Print the compiler version of `clang-command' in a 5 or 6-digit form -# such as `50001' for clang-5.0.1 etc. - -compiler="$*" - -if ! ( $compiler --version | grep -q clang) ; then - echo 0 - exit 1 -fi - -MAJOR=$(echo __clang_major__ | $compiler -E -x c - | tail -n 1) -MINOR=$(echo __clang_minor__ | $compiler -E -x c - | tail -n 1) -PATCHLEVEL=$(echo __clang_patchlevel__ | $compiler -E -x c - | tail -n 1) -printf "%d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL diff --git a/scripts/gcc-version.sh b/scripts/gcc-version.sh deleted file mode 100755 index ae353432539b..000000000000 --- a/scripts/gcc-version.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 -# -# gcc-version gcc-command -# -# Print the gcc version of `gcc-command' in a 5 or 6-digit form -# such as `29503' for gcc-2.95.3, `30301' for gcc-3.3.1, etc. - -compiler="$*" - -if [ ${#compiler} -eq 0 ]; then - echo "Error: No compiler specified." >&2 - printf "Usage:\n\t$0 \n" >&2 - exit 1 -fi - -MAJOR=$(echo __GNUC__ | $compiler -E -x c - | tail -n 1) -MINOR=$(echo __GNUC_MINOR__ | $compiler -E -x c - | tail -n 1) -PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -x c - | tail -n 1) -printf "%d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL -- cgit v1.2.3 From 68a5a9a243354ed52f7b37b057bd5e98cba870c8 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 16 Feb 2021 20:09:57 -0800 Subject: MAINTAINERS: Add maintainers of the CXL driver Signed-off-by: Ben Widawsky Cc: Dan Williams Cc: Vishal Verma Cc: Ira Weiny Cc: Alison Schofield Link: https://lore.kernel.org/r/20210217040958.1354670-9-ben.widawsky@intel.com Signed-off-by: Dan Williams --- MAINTAINERS | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index d3e847f7f3dc..f60e658a7c6e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4445,6 +4445,17 @@ M: Miguel Ojeda S: Maintained F: include/linux/compiler_attributes.h +COMPUTE EXPRESS LINK (CXL) +M: Alison Schofield +M: Vishal Verma +M: Ira Weiny +M: Ben Widawsky +M: Dan Williams +L: linux-cxl@vger.kernel.org +S: Maintained +F: drivers/cxl/ +F: include/uapi/linux/cxl_mem.h + CONEXANT ACCESSRUNNER USB DRIVER L: accessrunner-general@lists.sourceforge.net S: Orphan -- cgit v1.2.3 From d4c34d09ab03e1e631fe195ddf35365a1273be9c Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Tue, 12 Jan 2021 09:58:40 +0900 Subject: pinctrl: Add RISC-V Canaan Kendryte K210 FPIOA driver Add the pinctrl-k210.c pinctrl driver for the Canaan Kendryte K210 field programmable IO array (FPIOA) to allow configuring the SoC pin functions. The K210 has 48 programmable pins which can take any of 256 possible functions. This patch is inspired from the k210 pinctrl driver for the u-boot project and contains many direct contributions from Sean Anderson. The MAINTAINERS file is updated, adding the entry "CANAAN/KENDRYTE K210 SOC FPIOA DRIVER" with myself listed as maintainer for this driver. Cc: Linus Walleij Cc: linux-gpio@vger.kernel.org Signed-off-by: Sean Anderson Signed-off-by: Damien Le Moal Reviewed-by: Linus Walleij Signed-off-by: Palmer Dabbelt --- MAINTAINERS | 7 + arch/riscv/Kconfig.socs | 1 + drivers/pinctrl/Kconfig | 13 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-k210.c | 985 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1007 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-k210.c (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 380a446d4d4d..54f356e67491 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3860,6 +3860,13 @@ W: https://github.com/Cascoda/ca8210-linux.git F: Documentation/devicetree/bindings/net/ieee802154/ca8210.txt F: drivers/net/ieee802154/ca8210.c +CANAAN/KENDRYTE K210 SOC FPIOA DRIVER +M: Damien Le Moal +L: linux-riscv@lists.infradead.org +L: linux-gpio@vger.kernel.org (pinctrl driver) +F: Documentation/devicetree/bindings/pinctrl/canaan,k210-fpioa.yaml +F: drivers/pinctrl/pinctrl-k210.c + CANAAN/KENDRYTE K210 SOC RESET CONTROLLER DRIVER M: Damien Le Moal L: linux-kernel@vger.kernel.org diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index 57e53219c500..6402746c68f3 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -30,6 +30,7 @@ config SOC_CANAAN select SERIAL_SIFIVE_CONSOLE if TTY select SIFIVE_PLIC select ARCH_HAS_RESET_CONTROLLER + select PINCTRL help This enables support for Canaan Kendryte K210 SoC platform hardware. diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index d4b2f2e2ed75..cd437e3cc255 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -394,6 +394,19 @@ config PINCTRL_MICROCHIP_SGPIO connect control signals from SFP modules and to act as an LED controller. +config PINCTRL_K210 + bool "Pinctrl driver for the Canaan Kendryte K210 SoC" + depends on RISCV && SOC_CANAAN && OF + select GENERIC_PINMUX_FUNCTIONS + select GENERIC_PINCONF + select GPIOLIB + select OF_GPIO + select REGMAP_MMIO + default SOC_CANAAN + help + Add support for the Canaan Kendryte K210 RISC-V SOC Field + Programmable IO Array (FPIOA) controller. + source "drivers/pinctrl/actions/Kconfig" source "drivers/pinctrl/aspeed/Kconfig" source "drivers/pinctrl/bcm/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 5bb9bb6cc3ce..152c8fe51726 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o obj-$(CONFIG_PINCTRL_OCELOT) += pinctrl-ocelot.o obj-$(CONFIG_PINCTRL_MICROCHIP_SGPIO) += pinctrl-microchip-sgpio.o obj-$(CONFIG_PINCTRL_EQUILIBRIUM) += pinctrl-equilibrium.o +obj-$(CONFIG_PINCTRL_K210) += pinctrl-k210.o obj-y += actions/ obj-$(CONFIG_ARCH_ASPEED) += aspeed/ diff --git a/drivers/pinctrl/pinctrl-k210.c b/drivers/pinctrl/pinctrl-k210.c new file mode 100644 index 000000000000..8a733cf77ba0 --- /dev/null +++ b/drivers/pinctrl/pinctrl-k210.c @@ -0,0 +1,985 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Sean Anderson + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "core.h" +#include "pinconf.h" +#include "pinctrl-utils.h" + +/* + * The K210 only implements 8 drive levels, even though + * there is register space for 16 + */ +#define K210_PC_DRIVE_MASK GENMASK(11, 8) +#define K210_PC_DRIVE_SHIFT 8 +#define K210_PC_DRIVE_0 (0 << K210_PC_DRIVE_SHIFT) +#define K210_PC_DRIVE_1 (1 << K210_PC_DRIVE_SHIFT) +#define K210_PC_DRIVE_2 (2 << K210_PC_DRIVE_SHIFT) +#define K210_PC_DRIVE_3 (3 << K210_PC_DRIVE_SHIFT) +#define K210_PC_DRIVE_4 (4 << K210_PC_DRIVE_SHIFT) +#define K210_PC_DRIVE_5 (5 << K210_PC_DRIVE_SHIFT) +#define K210_PC_DRIVE_6 (6 << K210_PC_DRIVE_SHIFT) +#define K210_PC_DRIVE_7 (7 << K210_PC_DRIVE_SHIFT) +#define K210_PC_DRIVE_MAX 7 +#define K210_PC_MODE_MASK GENMASK(23, 12) + +/* + * output enabled == PC_OE & (PC_OE_INV ^ FUNCTION_OE) + * where FUNCTION_OE is a physical signal from the function. + */ +#define K210_PC_OE BIT(12) /* Output Enable */ +#define K210_PC_OE_INV BIT(13) /* INVert Output Enable */ +#define K210_PC_DO_OE BIT(14) /* set Data Out to Output Enable sig */ +#define K210_PC_DO_INV BIT(15) /* INVert final Data Output */ +#define K210_PC_PU BIT(16) /* Pull Up */ +#define K210_PC_PD BIT(17) /* Pull Down */ +/* Strong pull up not implemented on K210 */ +#define K210_PC_SL BIT(19) /* reduce SLew rate */ +/* Same semantics as OE above */ +#define K210_PC_IE BIT(20) /* Input Enable */ +#define K210_PC_IE_INV BIT(21) /* INVert Input Enable */ +#define K210_PC_DI_INV BIT(22) /* INVert Data Input */ +#define K210_PC_ST BIT(23) /* Schmitt Trigger */ +#define K210_PC_DI BIT(31) /* raw Data Input */ + +#define K210_PC_BIAS_MASK (K210_PC_PU & K210_PC_PD) + +#define K210_PC_MODE_IN (K210_PC_IE | K210_PC_ST) +#define K210_PC_MODE_OUT (K210_PC_DRIVE_7 | K210_PC_OE) +#define K210_PC_MODE_I2C (K210_PC_MODE_IN | K210_PC_SL | \ + K210_PC_OE | K210_PC_PU) +#define K210_PC_MODE_SCCB (K210_PC_MODE_I2C | \ + K210_PC_OE_INV | K210_PC_IE_INV) +#define K210_PC_MODE_SPI (K210_PC_MODE_IN | K210_PC_IE_INV | \ + K210_PC_MODE_OUT | K210_PC_OE_INV) +#define K210_PC_MODE_GPIO (K210_PC_MODE_IN | K210_PC_MODE_OUT) + +#define K210_PG_FUNC GENMASK(7, 0) +#define K210_PG_DO BIT(8) +#define K210_PG_PIN GENMASK(22, 16) + +/* + * struct k210_fpioa: Kendryte K210 FPIOA memory mapped registers + * @pins: 48 32-bits IO pin registers + * @tie_en: 256 (one per function) input tie enable bits + * @tie_val: 256 (one per function) input tie value bits + */ +struct k210_fpioa { + u32 pins[48]; + u32 tie_en[8]; + u32 tie_val[8]; +}; + +struct k210_fpioa_data { + + struct device *dev; + struct pinctrl_dev *pctl; + + struct k210_fpioa __iomem *fpioa; + struct regmap *sysctl_map; + u32 power_offset; + struct clk *clk; + struct clk *pclk; +}; + +#define K210_PIN_NAME(i) ("IO_" #i) +#define K210_PIN(i) [(i)] = PINCTRL_PIN((i), K210_PIN_NAME(i)) + +static const struct pinctrl_pin_desc k210_pins[] = { + K210_PIN(0), K210_PIN(1), K210_PIN(2), + K210_PIN(3), K210_PIN(4), K210_PIN(5), + K210_PIN(6), K210_PIN(7), K210_PIN(8), + K210_PIN(9), K210_PIN(10), K210_PIN(11), + K210_PIN(12), K210_PIN(13), K210_PIN(14), + K210_PIN(15), K210_PIN(16), K210_PIN(17), + K210_PIN(18), K210_PIN(19), K210_PIN(20), + K210_PIN(21), K210_PIN(22), K210_PIN(23), + K210_PIN(24), K210_PIN(25), K210_PIN(26), + K210_PIN(27), K210_PIN(28), K210_PIN(29), + K210_PIN(30), K210_PIN(31), K210_PIN(32), + K210_PIN(33), K210_PIN(34), K210_PIN(35), + K210_PIN(36), K210_PIN(37), K210_PIN(38), + K210_PIN(39), K210_PIN(40), K210_PIN(41), + K210_PIN(42), K210_PIN(43), K210_PIN(44), + K210_PIN(45), K210_PIN(46), K210_PIN(47) +}; + +#define K210_NPINS ARRAY_SIZE(k210_pins) + +/* + * Pin groups: each of the 48 programmable pins is a group. + * To this are added 8 power domain groups, which for the purposes of + * the pin subsystem, contain no pins. The power domain groups only exist + * to set the power level. The id should never be used (since there are + * no pins 48-55). + */ +static const char *const k210_group_names[] = { + /* The first 48 groups are for pins, one each */ + K210_PIN_NAME(0), K210_PIN_NAME(1), K210_PIN_NAME(2), + K210_PIN_NAME(3), K210_PIN_NAME(4), K210_PIN_NAME(5), + K210_PIN_NAME(6), K210_PIN_NAME(7), K210_PIN_NAME(8), + K210_PIN_NAME(9), K210_PIN_NAME(10), K210_PIN_NAME(11), + K210_PIN_NAME(12), K210_PIN_NAME(13), K210_PIN_NAME(14), + K210_PIN_NAME(15), K210_PIN_NAME(16), K210_PIN_NAME(17), + K210_PIN_NAME(18), K210_PIN_NAME(19), K210_PIN_NAME(20), + K210_PIN_NAME(21), K210_PIN_NAME(22), K210_PIN_NAME(23), + K210_PIN_NAME(24), K210_PIN_NAME(25), K210_PIN_NAME(26), + K210_PIN_NAME(27), K210_PIN_NAME(28), K210_PIN_NAME(29), + K210_PIN_NAME(30), K210_PIN_NAME(31), K210_PIN_NAME(32), + K210_PIN_NAME(33), K210_PIN_NAME(34), K210_PIN_NAME(35), + K210_PIN_NAME(36), K210_PIN_NAME(37), K210_PIN_NAME(38), + K210_PIN_NAME(39), K210_PIN_NAME(40), K210_PIN_NAME(41), + K210_PIN_NAME(42), K210_PIN_NAME(43), K210_PIN_NAME(44), + K210_PIN_NAME(45), K210_PIN_NAME(46), K210_PIN_NAME(47), + [48] = "A0", [49] = "A1", [50] = "A2", + [51] = "B3", [52] = "B4", [53] = "B5", + [54] = "C6", [55] = "C7" +}; + +#define K210_NGROUPS ARRAY_SIZE(k210_group_names) + +enum k210_pinctrl_mode_id { + K210_PC_DEFAULT_DISABLED, + K210_PC_DEFAULT_IN, + K210_PC_DEFAULT_IN_TIE, + K210_PC_DEFAULT_OUT, + K210_PC_DEFAULT_I2C, + K210_PC_DEFAULT_SCCB, + K210_PC_DEFAULT_SPI, + K210_PC_DEFAULT_GPIO, + K210_PC_DEFAULT_INT13, +}; + +#define K210_PC_DEFAULT(mode) \ + [K210_PC_DEFAULT_##mode] = K210_PC_MODE_##mode + +static const u32 k210_pinconf_mode_id_to_mode[] = { + [K210_PC_DEFAULT_DISABLED] = 0, + K210_PC_DEFAULT(IN), + [K210_PC_DEFAULT_IN_TIE] = K210_PC_MODE_IN, + K210_PC_DEFAULT(OUT), + K210_PC_DEFAULT(I2C), + K210_PC_DEFAULT(SCCB), + K210_PC_DEFAULT(SPI), + K210_PC_DEFAULT(GPIO), + [K210_PC_DEFAULT_INT13] = K210_PC_MODE_IN | K210_PC_PU, +}; + +#undef DEFAULT + +/* + * Pin functions configuration information. + */ +struct k210_pcf_info { + char name[15]; + u8 mode_id; +}; + +#define K210_FUNC(id, mode) \ + [K210_PCF_##id] = { \ + .name = #id, \ + .mode_id = K210_PC_DEFAULT_##mode \ + } + +static const struct k210_pcf_info k210_pcf_infos[] = { + K210_FUNC(JTAG_TCLK, IN), + K210_FUNC(JTAG_TDI, IN), + K210_FUNC(JTAG_TMS, IN), + K210_FUNC(JTAG_TDO, OUT), + K210_FUNC(SPI0_D0, SPI), + K210_FUNC(SPI0_D1, SPI), + K210_FUNC(SPI0_D2, SPI), + K210_FUNC(SPI0_D3, SPI), + K210_FUNC(SPI0_D4, SPI), + K210_FUNC(SPI0_D5, SPI), + K210_FUNC(SPI0_D6, SPI), + K210_FUNC(SPI0_D7, SPI), + K210_FUNC(SPI0_SS0, OUT), + K210_FUNC(SPI0_SS1, OUT), + K210_FUNC(SPI0_SS2, OUT), + K210_FUNC(SPI0_SS3, OUT), + K210_FUNC(SPI0_ARB, IN_TIE), + K210_FUNC(SPI0_SCLK, OUT), + K210_FUNC(UARTHS_RX, IN), + K210_FUNC(UARTHS_TX, OUT), + K210_FUNC(RESV6, IN), + K210_FUNC(RESV7, IN), + K210_FUNC(CLK_SPI1, OUT), + K210_FUNC(CLK_I2C1, OUT), + K210_FUNC(GPIOHS0, GPIO), + K210_FUNC(GPIOHS1, GPIO), + K210_FUNC(GPIOHS2, GPIO), + K210_FUNC(GPIOHS3, GPIO), + K210_FUNC(GPIOHS4, GPIO), + K210_FUNC(GPIOHS5, GPIO), + K210_FUNC(GPIOHS6, GPIO), + K210_FUNC(GPIOHS7, GPIO), + K210_FUNC(GPIOHS8, GPIO), + K210_FUNC(GPIOHS9, GPIO), + K210_FUNC(GPIOHS10, GPIO), + K210_FUNC(GPIOHS11, GPIO), + K210_FUNC(GPIOHS12, GPIO), + K210_FUNC(GPIOHS13, GPIO), + K210_FUNC(GPIOHS14, GPIO), + K210_FUNC(GPIOHS15, GPIO), + K210_FUNC(GPIOHS16, GPIO), + K210_FUNC(GPIOHS17, GPIO), + K210_FUNC(GPIOHS18, GPIO), + K210_FUNC(GPIOHS19, GPIO), + K210_FUNC(GPIOHS20, GPIO), + K210_FUNC(GPIOHS21, GPIO), + K210_FUNC(GPIOHS22, GPIO), + K210_FUNC(GPIOHS23, GPIO), + K210_FUNC(GPIOHS24, GPIO), + K210_FUNC(GPIOHS25, GPIO), + K210_FUNC(GPIOHS26, GPIO), + K210_FUNC(GPIOHS27, GPIO), + K210_FUNC(GPIOHS28, GPIO), + K210_FUNC(GPIOHS29, GPIO), + K210_FUNC(GPIOHS30, GPIO), + K210_FUNC(GPIOHS31, GPIO), + K210_FUNC(GPIO0, GPIO), + K210_FUNC(GPIO1, GPIO), + K210_FUNC(GPIO2, GPIO), + K210_FUNC(GPIO3, GPIO), + K210_FUNC(GPIO4, GPIO), + K210_FUNC(GPIO5, GPIO), + K210_FUNC(GPIO6, GPIO), + K210_FUNC(GPIO7, GPIO), + K210_FUNC(UART1_RX, IN), + K210_FUNC(UART1_TX, OUT), + K210_FUNC(UART2_RX, IN), + K210_FUNC(UART2_TX, OUT), + K210_FUNC(UART3_RX, IN), + K210_FUNC(UART3_TX, OUT), + K210_FUNC(SPI1_D0, SPI), + K210_FUNC(SPI1_D1, SPI), + K210_FUNC(SPI1_D2, SPI), + K210_FUNC(SPI1_D3, SPI), + K210_FUNC(SPI1_D4, SPI), + K210_FUNC(SPI1_D5, SPI), + K210_FUNC(SPI1_D6, SPI), + K210_FUNC(SPI1_D7, SPI), + K210_FUNC(SPI1_SS0, OUT), + K210_FUNC(SPI1_SS1, OUT), + K210_FUNC(SPI1_SS2, OUT), + K210_FUNC(SPI1_SS3, OUT), + K210_FUNC(SPI1_ARB, IN_TIE), + K210_FUNC(SPI1_SCLK, OUT), + K210_FUNC(SPI2_D0, SPI), + K210_FUNC(SPI2_SS, IN), + K210_FUNC(SPI2_SCLK, IN), + K210_FUNC(I2S0_MCLK, OUT), + K210_FUNC(I2S0_SCLK, OUT), + K210_FUNC(I2S0_WS, OUT), + K210_FUNC(I2S0_IN_D0, IN), + K210_FUNC(I2S0_IN_D1, IN), + K210_FUNC(I2S0_IN_D2, IN), + K210_FUNC(I2S0_IN_D3, IN), + K210_FUNC(I2S0_OUT_D0, OUT), + K210_FUNC(I2S0_OUT_D1, OUT), + K210_FUNC(I2S0_OUT_D2, OUT), + K210_FUNC(I2S0_OUT_D3, OUT), + K210_FUNC(I2S1_MCLK, OUT), + K210_FUNC(I2S1_SCLK, OUT), + K210_FUNC(I2S1_WS, OUT), + K210_FUNC(I2S1_IN_D0, IN), + K210_FUNC(I2S1_IN_D1, IN), + K210_FUNC(I2S1_IN_D2, IN), + K210_FUNC(I2S1_IN_D3, IN), + K210_FUNC(I2S1_OUT_D0, OUT), + K210_FUNC(I2S1_OUT_D1, OUT), + K210_FUNC(I2S1_OUT_D2, OUT), + K210_FUNC(I2S1_OUT_D3, OUT), + K210_FUNC(I2S2_MCLK, OUT), + K210_FUNC(I2S2_SCLK, OUT), + K210_FUNC(I2S2_WS, OUT), + K210_FUNC(I2S2_IN_D0, IN), + K210_FUNC(I2S2_IN_D1, IN), + K210_FUNC(I2S2_IN_D2, IN), + K210_FUNC(I2S2_IN_D3, IN), + K210_FUNC(I2S2_OUT_D0, OUT), + K210_FUNC(I2S2_OUT_D1, OUT), + K210_FUNC(I2S2_OUT_D2, OUT), + K210_FUNC(I2S2_OUT_D3, OUT), + K210_FUNC(RESV0, DISABLED), + K210_FUNC(RESV1, DISABLED), + K210_FUNC(RESV2, DISABLED), + K210_FUNC(RESV3, DISABLED), + K210_FUNC(RESV4, DISABLED), + K210_FUNC(RESV5, DISABLED), + K210_FUNC(I2C0_SCLK, I2C), + K210_FUNC(I2C0_SDA, I2C), + K210_FUNC(I2C1_SCLK, I2C), + K210_FUNC(I2C1_SDA, I2C), + K210_FUNC(I2C2_SCLK, I2C), + K210_FUNC(I2C2_SDA, I2C), + K210_FUNC(DVP_XCLK, OUT), + K210_FUNC(DVP_RST, OUT), + K210_FUNC(DVP_PWDN, OUT), + K210_FUNC(DVP_VSYNC, IN), + K210_FUNC(DVP_HSYNC, IN), + K210_FUNC(DVP_PCLK, IN), + K210_FUNC(DVP_D0, IN), + K210_FUNC(DVP_D1, IN), + K210_FUNC(DVP_D2, IN), + K210_FUNC(DVP_D3, IN), + K210_FUNC(DVP_D4, IN), + K210_FUNC(DVP_D5, IN), + K210_FUNC(DVP_D6, IN), + K210_FUNC(DVP_D7, IN), + K210_FUNC(SCCB_SCLK, SCCB), + K210_FUNC(SCCB_SDA, SCCB), + K210_FUNC(UART1_CTS, IN), + K210_FUNC(UART1_DSR, IN), + K210_FUNC(UART1_DCD, IN), + K210_FUNC(UART1_RI, IN), + K210_FUNC(UART1_SIR_IN, IN), + K210_FUNC(UART1_DTR, OUT), + K210_FUNC(UART1_RTS, OUT), + K210_FUNC(UART1_OUT2, OUT), + K210_FUNC(UART1_OUT1, OUT), + K210_FUNC(UART1_SIR_OUT, OUT), + K210_FUNC(UART1_BAUD, OUT), + K210_FUNC(UART1_RE, OUT), + K210_FUNC(UART1_DE, OUT), + K210_FUNC(UART1_RS485_EN, OUT), + K210_FUNC(UART2_CTS, IN), + K210_FUNC(UART2_DSR, IN), + K210_FUNC(UART2_DCD, IN), + K210_FUNC(UART2_RI, IN), + K210_FUNC(UART2_SIR_IN, IN), + K210_FUNC(UART2_DTR, OUT), + K210_FUNC(UART2_RTS, OUT), + K210_FUNC(UART2_OUT2, OUT), + K210_FUNC(UART2_OUT1, OUT), + K210_FUNC(UART2_SIR_OUT, OUT), + K210_FUNC(UART2_BAUD, OUT), + K210_FUNC(UART2_RE, OUT), + K210_FUNC(UART2_DE, OUT), + K210_FUNC(UART2_RS485_EN, OUT), + K210_FUNC(UART3_CTS, IN), + K210_FUNC(UART3_DSR, IN), + K210_FUNC(UART3_DCD, IN), + K210_FUNC(UART3_RI, IN), + K210_FUNC(UART3_SIR_IN, IN), + K210_FUNC(UART3_DTR, OUT), + K210_FUNC(UART3_RTS, OUT), + K210_FUNC(UART3_OUT2, OUT), + K210_FUNC(UART3_OUT1, OUT), + K210_FUNC(UART3_SIR_OUT, OUT), + K210_FUNC(UART3_BAUD, OUT), + K210_FUNC(UART3_RE, OUT), + K210_FUNC(UART3_DE, OUT), + K210_FUNC(UART3_RS485_EN, OUT), + K210_FUNC(TIMER0_TOGGLE1, OUT), + K210_FUNC(TIMER0_TOGGLE2, OUT), + K210_FUNC(TIMER0_TOGGLE3, OUT), + K210_FUNC(TIMER0_TOGGLE4, OUT), + K210_FUNC(TIMER1_TOGGLE1, OUT), + K210_FUNC(TIMER1_TOGGLE2, OUT), + K210_FUNC(TIMER1_TOGGLE3, OUT), + K210_FUNC(TIMER1_TOGGLE4, OUT), + K210_FUNC(TIMER2_TOGGLE1, OUT), + K210_FUNC(TIMER2_TOGGLE2, OUT), + K210_FUNC(TIMER2_TOGGLE3, OUT), + K210_FUNC(TIMER2_TOGGLE4, OUT), + K210_FUNC(CLK_SPI2, OUT), + K210_FUNC(CLK_I2C2, OUT), + K210_FUNC(INTERNAL0, OUT), + K210_FUNC(INTERNAL1, OUT), + K210_FUNC(INTERNAL2, OUT), + K210_FUNC(INTERNAL3, OUT), + K210_FUNC(INTERNAL4, OUT), + K210_FUNC(INTERNAL5, OUT), + K210_FUNC(INTERNAL6, OUT), + K210_FUNC(INTERNAL7, OUT), + K210_FUNC(INTERNAL8, OUT), + K210_FUNC(INTERNAL9, IN), + K210_FUNC(INTERNAL10, IN), + K210_FUNC(INTERNAL11, IN), + K210_FUNC(INTERNAL12, IN), + K210_FUNC(INTERNAL13, INT13), + K210_FUNC(INTERNAL14, I2C), + K210_FUNC(INTERNAL15, IN), + K210_FUNC(INTERNAL16, IN), + K210_FUNC(INTERNAL17, IN), + K210_FUNC(CONSTANT, DISABLED), + K210_FUNC(INTERNAL18, IN), + K210_FUNC(DEBUG0, OUT), + K210_FUNC(DEBUG1, OUT), + K210_FUNC(DEBUG2, OUT), + K210_FUNC(DEBUG3, OUT), + K210_FUNC(DEBUG4, OUT), + K210_FUNC(DEBUG5, OUT), + K210_FUNC(DEBUG6, OUT), + K210_FUNC(DEBUG7, OUT), + K210_FUNC(DEBUG8, OUT), + K210_FUNC(DEBUG9, OUT), + K210_FUNC(DEBUG10, OUT), + K210_FUNC(DEBUG11, OUT), + K210_FUNC(DEBUG12, OUT), + K210_FUNC(DEBUG13, OUT), + K210_FUNC(DEBUG14, OUT), + K210_FUNC(DEBUG15, OUT), + K210_FUNC(DEBUG16, OUT), + K210_FUNC(DEBUG17, OUT), + K210_FUNC(DEBUG18, OUT), + K210_FUNC(DEBUG19, OUT), + K210_FUNC(DEBUG20, OUT), + K210_FUNC(DEBUG21, OUT), + K210_FUNC(DEBUG22, OUT), + K210_FUNC(DEBUG23, OUT), + K210_FUNC(DEBUG24, OUT), + K210_FUNC(DEBUG25, OUT), + K210_FUNC(DEBUG26, OUT), + K210_FUNC(DEBUG27, OUT), + K210_FUNC(DEBUG28, OUT), + K210_FUNC(DEBUG29, OUT), + K210_FUNC(DEBUG30, OUT), + K210_FUNC(DEBUG31, OUT), +}; + +#define PIN_CONFIG_OUTPUT_INVERT (PIN_CONFIG_END + 1) +#define PIN_CONFIG_INPUT_INVERT (PIN_CONFIG_END + 2) + +static const struct pinconf_generic_params k210_pinconf_custom_params[] = { + { "output-polarity-invert", PIN_CONFIG_OUTPUT_INVERT, 1 }, + { "input-polarity-invert", PIN_CONFIG_INPUT_INVERT, 1 }, +}; + +/* + * Max drive strength in uA. + */ +static const int k210_pinconf_drive_strength[] = { + [0] = 11200, + [1] = 16800, + [2] = 22300, + [3] = 27800, + [4] = 33300, + [5] = 38700, + [6] = 44100, + [7] = 49500, +}; + +static int k210_pinconf_get_drive(unsigned int max_strength_ua) +{ + int i; + + for (i = K210_PC_DRIVE_MAX; i; i--) { + if (k210_pinconf_drive_strength[i] <= max_strength_ua) + return i; + } + + return -EINVAL; +} + +static void k210_pinmux_set_pin_function(struct pinctrl_dev *pctldev, + u32 pin, u32 func) +{ + struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev); + const struct k210_pcf_info *info = &k210_pcf_infos[func]; + u32 mode = k210_pinconf_mode_id_to_mode[info->mode_id]; + u32 val = func | mode; + + dev_dbg(pdata->dev, "set pin %u function %s (%u) -> 0x%08x\n", + pin, info->name, func, val); + + writel(val, &pdata->fpioa->pins[pin]); +} + +static int k210_pinconf_set_param(struct pinctrl_dev *pctldev, + unsigned int pin, + unsigned int param, unsigned int arg) +{ + struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev); + u32 val = readl(&pdata->fpioa->pins[pin]); + int drive; + + dev_dbg(pdata->dev, "set pin %u param %u, arg 0x%x\n", + pin, param, arg); + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + val &= ~K210_PC_BIAS_MASK; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + if (!arg) + return -EINVAL; + val |= K210_PC_PD; + break; + case PIN_CONFIG_BIAS_PULL_UP: + if (!arg) + return -EINVAL; + val |= K210_PC_PD; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + arg *= 1000; + fallthrough; + case PIN_CONFIG_DRIVE_STRENGTH_UA: + drive = k210_pinconf_get_drive(arg); + if (drive < 0) + return drive; + val &= ~K210_PC_DRIVE_MASK; + val |= FIELD_PREP(K210_PC_DRIVE_MASK, drive); + break; + case PIN_CONFIG_INPUT_ENABLE: + if (arg) + val |= K210_PC_IE; + else + val &= ~K210_PC_IE; + break; + case PIN_CONFIG_INPUT_SCHMITT_ENABLE: + if (arg) + val |= K210_PC_ST; + else + val &= ~K210_PC_ST; + break; + case PIN_CONFIG_OUTPUT: + k210_pinmux_set_pin_function(pctldev, pin, K210_PCF_CONSTANT); + val = readl(&pdata->fpioa->pins[pin]); + val |= K210_PC_MODE_OUT; + if (!arg) + val |= K210_PC_DO_INV; + break; + case PIN_CONFIG_OUTPUT_ENABLE: + if (arg) + val |= K210_PC_OE; + else + val &= ~K210_PC_OE; + break; + case PIN_CONFIG_SLEW_RATE: + if (arg) + val |= K210_PC_SL; + else + val &= ~K210_PC_SL; + break; + case PIN_CONFIG_OUTPUT_INVERT: + if (arg) + val |= K210_PC_DO_INV; + else + val &= ~K210_PC_DO_INV; + break; + case PIN_CONFIG_INPUT_INVERT: + if (arg) + val |= K210_PC_DI_INV; + else + val &= ~K210_PC_DI_INV; + break; + default: + return -EINVAL; + } + + writel(val, &pdata->fpioa->pins[pin]); + + return 0; +} + +static int k210_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *configs, unsigned int num_configs) +{ + unsigned int param, arg; + int i, ret; + + if (WARN_ON(pin >= K210_NPINS)) + return -EINVAL; + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + ret = k210_pinconf_set_param(pctldev, pin, param, arg); + if (ret) + return ret; + } + + return 0; +} + +static void k210_pinconf_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned int pin) +{ + struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev); + + seq_printf(s, "%#x", readl(&pdata->fpioa->pins[pin])); +} + +static int k210_pinconf_group_set(struct pinctrl_dev *pctldev, + unsigned int selector, unsigned long *configs, + unsigned int num_configs) +{ + struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev); + unsigned int param, arg; + u32 bit; + int i; + + /* Pins should be configured with pinmux, not groups*/ + if (selector < K210_NPINS) + return -EINVAL; + + /* Otherwise it's a power domain */ + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + if (param != PIN_CONFIG_POWER_SOURCE) + return -EINVAL; + + arg = pinconf_to_config_argument(configs[i]); + bit = BIT(selector - K210_NPINS); + regmap_update_bits(pdata->sysctl_map, + pdata->power_offset, + bit, arg ? bit : 0); + } + + return 0; +} + +static void k210_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, + unsigned int selector) +{ + struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev); + int ret; + u32 val; + + if (selector < K210_NPINS) + return k210_pinconf_dbg_show(pctldev, s, selector); + + ret = regmap_read(pdata->sysctl_map, pdata->power_offset, &val); + if (ret) { + dev_err(pdata->dev, "Failed to read power reg\n"); + return; + } + + seq_printf(s, "%s: %s V", k210_group_names[selector], + val & BIT(selector - K210_NPINS) ? "1.8" : "3.3"); +} + +static const struct pinconf_ops k210_pinconf_ops = { + .is_generic = true, + .pin_config_set = k210_pinconf_set, + .pin_config_group_set = k210_pinconf_group_set, + .pin_config_dbg_show = k210_pinconf_dbg_show, + .pin_config_group_dbg_show = k210_pinconf_group_dbg_show, +}; + +static int k210_pinmux_get_function_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(k210_pcf_infos); +} + +static const char *k210_pinmux_get_function_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + return k210_pcf_infos[selector].name; +} + +static int k210_pinmux_get_function_groups(struct pinctrl_dev *pctldev, + unsigned int selector, + const char * const **groups, + unsigned int * const num_groups) +{ + /* Any function can be mapped to any pin */ + *groups = k210_group_names; + *num_groups = K210_NPINS; + + return 0; +} + +static int k210_pinmux_set_mux(struct pinctrl_dev *pctldev, + unsigned int function, + unsigned int group) +{ + /* Can't mux power domains */ + if (group >= K210_NPINS) + return -EINVAL; + + k210_pinmux_set_pin_function(pctldev, group, function); + + return 0; +} + +static const struct pinmux_ops k210_pinmux_ops = { + .get_functions_count = k210_pinmux_get_function_count, + .get_function_name = k210_pinmux_get_function_name, + .get_function_groups = k210_pinmux_get_function_groups, + .set_mux = k210_pinmux_set_mux, + .strict = true, +}; + +static int k210_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + return K210_NGROUPS; +} + +static const char *k210_pinctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned int group) +{ + return k210_group_names[group]; +} + +static int k210_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int group, + const unsigned int **pins, + unsigned int *npins) +{ + if (group >= K210_NPINS) { + *pins = NULL; + *npins = 0; + return 0; + } + + *pins = &k210_pins[group].number; + *npins = 1; + + return 0; +} + +static void k210_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned int offset) +{ + seq_printf(s, "%s", dev_name(pctldev->dev)); +} + +static int k210_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, + struct pinctrl_map **map, + unsigned int *reserved_maps, + unsigned int *num_maps) +{ + struct property *prop; + const __be32 *p; + int ret, pinmux_groups; + u32 pinmux_group; + unsigned long *configs = NULL; + unsigned int num_configs = 0; + unsigned int reserve = 0; + + ret = of_property_count_strings(np, "groups"); + if (!ret) + return pinconf_generic_dt_subnode_to_map(pctldev, np, map, + reserved_maps, num_maps, + PIN_MAP_TYPE_CONFIGS_GROUP); + + pinmux_groups = of_property_count_u32_elems(np, "pinmux"); + if (pinmux_groups <= 0) { + /* Ignore this node */ + return 0; + } + + ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, + &num_configs); + if (ret < 0) { + dev_err(pctldev->dev, "%pOF: could not parse node property\n", + np); + return ret; + } + + reserve = pinmux_groups * (1 + num_configs); + ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps, + reserve); + if (ret < 0) + goto exit; + + of_property_for_each_u32(np, "pinmux", prop, p, pinmux_group) { + const char *group_name, *func_name; + u32 pin = FIELD_GET(K210_PG_PIN, pinmux_group); + u32 func = FIELD_GET(K210_PG_FUNC, pinmux_group); + + if (pin >= K210_NPINS) { + ret = -EINVAL; + goto exit; + } + + group_name = k210_group_names[pin]; + func_name = k210_pcf_infos[func].name; + + dev_dbg(pctldev->dev, "Pinmux %s: pin %u func %s\n", + np->name, pin, func_name); + + ret = pinctrl_utils_add_map_mux(pctldev, map, reserved_maps, + num_maps, group_name, + func_name); + if (ret < 0) { + dev_err(pctldev->dev, "%pOF add mux map failed %d\n", + np, ret); + goto exit; + } + + if (num_configs) { + ret = pinctrl_utils_add_map_configs(pctldev, map, + reserved_maps, num_maps, group_name, + configs, num_configs, + PIN_MAP_TYPE_CONFIGS_PIN); + if (ret < 0) { + dev_err(pctldev->dev, + "%pOF add configs map failed %d\n", + np, ret); + goto exit; + } + } + } + + ret = 0; + +exit: + kfree(configs); + return ret; +} + +static int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np_config, + struct pinctrl_map **map, + unsigned int *num_maps) +{ + unsigned int reserved_maps; + struct device_node *np; + int ret; + + reserved_maps = 0; + *map = NULL; + *num_maps = 0; + + ret = k210_pinctrl_dt_subnode_to_map(pctldev, np_config, map, + &reserved_maps, num_maps); + if (ret < 0) + goto err; + + for_each_available_child_of_node(np_config, np) { + ret = k210_pinctrl_dt_subnode_to_map(pctldev, np, map, + &reserved_maps, num_maps); + if (ret < 0) + goto err; + } + return 0; + +err: + pinctrl_utils_free_map(pctldev, *map, *num_maps); + return ret; +} + + +static const struct pinctrl_ops k210_pinctrl_ops = { + .get_groups_count = k210_pinctrl_get_groups_count, + .get_group_name = k210_pinctrl_get_group_name, + .get_group_pins = k210_pinctrl_get_group_pins, + .pin_dbg_show = k210_pinctrl_pin_dbg_show, + .dt_node_to_map = k210_pinctrl_dt_node_to_map, + .dt_free_map = pinconf_generic_dt_free_map, +}; + +static struct pinctrl_desc k210_pinctrl_desc = { + .name = "k210-pinctrl", + .pins = k210_pins, + .npins = K210_NPINS, + .pctlops = &k210_pinctrl_ops, + .pmxops = &k210_pinmux_ops, + .confops = &k210_pinconf_ops, + .custom_params = k210_pinconf_custom_params, + .num_custom_params = ARRAY_SIZE(k210_pinconf_custom_params), +}; + +static void k210_fpioa_init_ties(struct k210_fpioa_data *pdata) +{ + struct k210_fpioa __iomem *fpioa = pdata->fpioa; + u32 val; + int i, j; + + dev_dbg(pdata->dev, "Init pin ties\n"); + + /* Init pin functions input ties */ + for (i = 0; i < ARRAY_SIZE(fpioa->tie_en); i++) { + val = 0; + for (j = 0; j < 32; j++) { + if (k210_pcf_infos[i * 32 + j].mode_id == + K210_PC_DEFAULT_IN_TIE) { + dev_dbg(pdata->dev, + "tie_en function %d (%s)\n", + i * 32 + j, + k210_pcf_infos[i * 32 + j].name); + val |= BIT(j); + } + } + + /* Set value before enable */ + writel(val, &fpioa->tie_val[i]); + writel(val, &fpioa->tie_en[i]); + } +} + +static int k210_fpioa_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct k210_fpioa_data *pdata; + int ret; + + dev_info(dev, "K210 FPIOA pin controller\n"); + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + pdata->dev = dev; + platform_set_drvdata(pdev, pdata); + + pdata->fpioa = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(pdata->fpioa)) + return PTR_ERR(pdata->fpioa); + + pdata->clk = devm_clk_get(dev, "ref"); + if (IS_ERR(pdata->clk)) + return PTR_ERR(pdata->clk); + + ret = clk_prepare_enable(pdata->clk); + if (ret) + return ret; + + pdata->pclk = devm_clk_get_optional(dev, "pclk"); + if (!IS_ERR(pdata->pclk)) + clk_prepare_enable(pdata->pclk); + + pdata->sysctl_map = + syscon_regmap_lookup_by_phandle_args(np, + "canaan,k210-sysctl-power", + 1, &pdata->power_offset); + if (IS_ERR(pdata->sysctl_map)) + return PTR_ERR(pdata->sysctl_map); + + k210_fpioa_init_ties(pdata); + + pdata->pctl = pinctrl_register(&k210_pinctrl_desc, dev, (void *)pdata); + if (IS_ERR(pdata->pctl)) + return PTR_ERR(pdata->pctl); + + return 0; +} + +static const struct of_device_id k210_fpioa_dt_ids[] = { + { .compatible = "canaan,k210-fpioa" }, + { /* sentinel */ }, +}; + +static struct platform_driver k210_fpioa_driver = { + .probe = k210_fpioa_probe, + .driver = { + .name = "k210-fpioa", + .of_match_table = k210_fpioa_dt_ids, + }, +}; +builtin_platform_driver(k210_fpioa_driver); -- cgit v1.2.3 From 02aff85922043cf175ebbe5fc3430acfeaeb8393 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2021 12:10:04 +0900 Subject: kbuild: check the minimum linker version in Kconfig Unify the two scripts/ld-version.sh and scripts/lld-version.sh, and check the minimum linker version like scripts/cc-version.sh did. I tested this script for some corner cases reported in the past: - GNU ld version 2.25-15.fc23 as reported by commit 8083013fc320 ("ld-version: Fix it on Fedora") - GNU ld (GNU Binutils) 2.20.1.20100303 as reported by commit 0d61ed17dd30 ("ld-version: Drop the 4th and 5th version components") This script show an error message if the linker is too old: $ make LD=ld.lld-9 SYNC include/config/auto.conf *** *** Linker is too old. *** Your LLD version: 9.0.1 *** Minimum LLD version: 10.0.1 *** scripts/Kconfig.include:50: Sorry, this linker is not supported. make[2]: *** [scripts/kconfig/Makefile:71: syncconfig] Error 1 make[1]: *** [Makefile:600: syncconfig] Error 2 make: *** [Makefile:708: include/config/auto.conf] Error 2 I also moved the check for gold to this script, so gold is still rejected: $ make LD=gold SYNC include/config/auto.conf gold linker is not supported as it is not capable of linking the kernel proper. scripts/Kconfig.include:50: Sorry, this linker is not supported. make[2]: *** [scripts/kconfig/Makefile:71: syncconfig] Error 1 make[1]: *** [Makefile:600: syncconfig] Error 2 make: *** [Makefile:708: include/config/auto.conf] Error 2 Thanks to David Laight for suggesting shell script improvements. Signed-off-by: Masahiro Yamada Acked-by: Nick Desaulniers Reviewed-by: Nathan Chancellor Tested-by: Nathan Chancellor --- MAINTAINERS | 1 - init/Kconfig | 21 ++++++++----- scripts/Kconfig.include | 7 +++-- scripts/ld-version.sh | 82 +++++++++++++++++++++++++++++++++++++++++++------ scripts/lld-version.sh | 20 ------------ 5 files changed, 90 insertions(+), 41 deletions(-) delete mode 100755 scripts/lld-version.sh (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index df820969be1f..6b82ad6990b7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4314,7 +4314,6 @@ C: irc://chat.freenode.net/clangbuiltlinux F: Documentation/kbuild/llvm.rst F: include/linux/compiler-clang.h F: scripts/clang-tools/ -F: scripts/lld-version.sh K: \b(?i:clang|llvm)\b CLEANCACHE API diff --git a/init/Kconfig b/init/Kconfig index 7bcfa24524c2..42b69ee29dca 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -33,24 +33,29 @@ config GCC_VERSION default $(cc-version) if CC_IS_GCC default 0 -config LD_VERSION - int - default $(shell,$(LD) --version | $(srctree)/scripts/ld-version.sh) - config CC_IS_CLANG def_bool $(success,test "$(cc-name)" = Clang) -config LD_IS_LLD - def_bool $(success,$(LD) -v | head -n 1 | grep -q LLD) - config CLANG_VERSION int default $(cc-version) if CC_IS_CLANG default 0 +config LD_IS_BFD + def_bool $(success,test "$(ld-name)" = BFD) + +config LD_VERSION + int + default $(ld-version) if LD_IS_BFD + default 0 + +config LD_IS_LLD + def_bool $(success,test "$(ld-name)" = LLD) + config LLD_VERSION int - default $(shell,$(srctree)/scripts/lld-version.sh $(LD)) + default $(ld-version) if LD_IS_LLD + default 0 config CC_CAN_LINK bool diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include index 0228cb9c74aa..58fdb5308725 100644 --- a/scripts/Kconfig.include +++ b/scripts/Kconfig.include @@ -45,8 +45,11 @@ $(error-if,$(success,test -z "$(cc-info)"),Sorry$(comma) this compiler is not su cc-name := $(shell,set -- $(cc-info) && echo $1) cc-version := $(shell,set -- $(cc-info) && echo $2) -# Fail if the linker is gold as it's not capable of linking the kernel proper -$(error-if,$(success, $(LD) -v | grep -q gold), gold linker '$(LD)' not supported) +# Get the linker name, version, and error out if it is not supported. +ld-info := $(shell,$(srctree)/scripts/ld-version.sh $(LD)) +$(error-if,$(success,test -z "$(ld-info)"),Sorry$(comma) this linker is not supported.) +ld-name := $(shell,set -- $(ld-info) && echo $1) +ld-version := $(shell,set -- $(ld-info) && echo $2) # machine bit flags # $(m32-flag): -m32 if the compiler supports it, or an empty string otherwise. diff --git a/scripts/ld-version.sh b/scripts/ld-version.sh index 0f8a2c0f9502..a463273509b5 100755 --- a/scripts/ld-version.sh +++ b/scripts/ld-version.sh @@ -1,11 +1,73 @@ -#!/usr/bin/awk -f +#!/bin/sh # SPDX-License-Identifier: GPL-2.0 -# extract linker version number from stdin and turn into single number - { - gsub(".*\\)", ""); - gsub(".*version ", ""); - gsub("-.*", ""); - split($1,a, "."); - print a[1]*10000 + a[2]*100 + a[3]; - exit - } +# +# Print the linker name and its version in a 5 or 6-digit form. +# Also, perform the minimum version check. + +set -e + +# When you raise the minimum linker version, please update +# Documentation/process/changes.rst as well. +bfd_min_version=2.23.0 +lld_min_version=10.0.1 + +# Convert the version string x.y.z to a canonical 5 or 6-digit form. +get_canonical_version() +{ + IFS=. + set -- $1 + + # If the 2nd or 3rd field is missing, fill it with a zero. + # + # The 4th field, if present, is ignored. + # This occurs in development snapshots as in 2.35.1.20201116 + echo $((10000 * $1 + 100 * ${2:-0} + ${3:-0})) +} + +orig_args="$@" + +# Get the first line of the --version output. +IFS=' +' +set -- $("$@" --version) + +# Split the line on spaces. +IFS=' ' +set -- $1 + +if [ "$1" = GNU -a "$2" = ld ]; then + shift $(($# - 1)) + version=$1 + min_version=$bfd_min_version + name=BFD + disp_name="GNU ld" +elif [ "$1" = GNU -a "$2" = gold ]; then + echo "gold linker is not supported as it is not capable of linking the kernel proper." >&2 + exit 1 +elif [ "$1" = LLD ]; then + version=$2 + min_version=$lld_min_version + name=LLD + disp_name=LLD +else + echo "$orig_args: unknown linker" >&2 + exit 1 +fi + +# Some distributions append a package release number, as in 2.34-4.fc32 +# Trim the hyphen and any characters that follow. +version=${version%-*} + +cversion=$(get_canonical_version $version) +min_cversion=$(get_canonical_version $min_version) + +if [ "$cversion" -lt "$min_cversion" ]; then + echo >&2 "***" + echo >&2 "*** Linker is too old." + echo >&2 "*** Your $disp_name version: $version" + echo >&2 "*** Minimum $disp_name version: $min_version" + echo >&2 "***" + exit 1 +fi + +echo $name $cversion diff --git a/scripts/lld-version.sh b/scripts/lld-version.sh deleted file mode 100755 index d70edb4d8a4f..000000000000 --- a/scripts/lld-version.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 -# -# Usage: $ ./scripts/lld-version.sh ld.lld -# -# Print the linker version of `ld.lld' in a 5 or 6-digit form -# such as `100001' for ld.lld 10.0.1 etc. - -linker_string="$($* --version)" - -if ! ( echo $linker_string | grep -q LLD ); then - echo 0 - exit 1 -fi - -VERSION=$(echo $linker_string | cut -d ' ' -f 2) -MAJOR=$(echo $VERSION | cut -d . -f 1) -MINOR=$(echo $VERSION | cut -d . -f 2) -PATCHLEVEL=$(echo $VERSION | cut -d . -f 3) -printf "%d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL -- cgit v1.2.3 From e7d9fea1c78a60c5cc5b0d708b89f1bfebf429b2 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Wed, 10 Feb 2021 14:02:15 +0900 Subject: dt-bindings: update MAINTAINERS file Add a reference to the Canaan K210 system controller driver bindings file Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml in the MAINTAINERS file entry for this driver. Signed-off-by: Damien Le Moal Signed-off-by: Palmer Dabbelt --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 54f356e67491..467c8670d815 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3879,6 +3879,7 @@ CANAAN/KENDRYTE K210 SOC SYSTEM CONTROLLER DRIVER M: Damien Le Moal L: linux-riscv@lists.infradead.org S: Maintained +F: Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml F: drivers/soc/canaan/ F: include/soc/canaan/ -- cgit v1.2.3 From daaaf866587ced121e3d33b4e978ec1fa66c18e9 Mon Sep 17 00:00:00 2001 From: Daire McNamara Date: Mon, 25 Jan 2021 16:29:34 +0000 Subject: MAINTAINERS: Add Daire McNamara as Microchip PCIe driver maintainer Link: https://lore.kernel.org/r/20210125162934.5335-5-daire.mcnamara@microchip.com Signed-off-by: Daire McNamara Signed-off-by: Lorenzo Pieralisi Signed-off-by: Bjorn Helgaas --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index cc1e6a5ee6e6..b6377e128d26 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13830,6 +13830,13 @@ S: Supported F: Documentation/devicetree/bindings/pci/mediatek* F: drivers/pci/controller/*mediatek* +PCIE DRIVER FOR MICROCHIP +M: Daire McNamara +L: linux-pci@vger.kernel.org +S: Supported +F: Documentation/devicetree/bindings/pci/microchip* +F: drivers/pci/controller/*microchip* + PCIE DRIVER FOR QUALCOMM MSM M: Stanimir Varbanov L: linux-pci@vger.kernel.org -- cgit v1.2.3 From 0825c1d57f02e3fb228bbecad827956d4c796d3a Mon Sep 17 00:00:00 2001 From: Marco Elver Date: Thu, 25 Feb 2021 17:19:35 -0800 Subject: MAINTAINERS: add entry for KFENCE Add entry for KFENCE maintainers. Link: https://lkml.kernel.org/r/20201103175841.3495947-10-elver@google.com Signed-off-by: Alexander Potapenko Signed-off-by: Marco Elver Reviewed-by: Dmitry Vyukov Reviewed-by: SeongJae Park Co-developed-by: Alexander Potapenko Cc: Andrey Konovalov Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Catalin Marinas Cc: Christopher Lameter Cc: Dave Hansen Cc: David Rientjes Cc: Eric Dumazet Cc: Greg Kroah-Hartman Cc: Hillf Danton Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Jann Horn Cc: Joern Engel Cc: Jonathan Corbet Cc: Joonsoo Kim Cc: Kees Cook Cc: Mark Rutland Cc: Paul E. McKenney Cc: Pekka Enberg Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Vlastimil Babka Cc: Will Deacon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index c71664ca8bfd..40040db747fc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9867,6 +9867,18 @@ F: include/linux/keyctl.h F: include/uapi/linux/keyctl.h F: security/keys/ +KFENCE +M: Alexander Potapenko +M: Marco Elver +R: Dmitry Vyukov +L: kasan-dev@googlegroups.com +S: Maintained +F: Documentation/dev-tools/kfence.rst +F: arch/*/include/asm/kfence.h +F: include/linux/kfence.h +F: lib/Kconfig.kfence +F: mm/kfence/ + KFIFO M: Stefani Seibold S: Maintained -- cgit v1.2.3 From c131bd0b5448bb577b7a9ed48c4e528807e8d5af Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Thu, 25 Feb 2021 17:21:00 -0800 Subject: treewide: Miguel has moved Update contact info. Link: https://lkml.kernel.org/r/20210206162524.GA11520@kernel.org Signed-off-by: Miguel Ojeda Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- .mailmap | 1 + CREDITS | 9 +++------ Documentation/admin-guide/auxdisplay/cfag12864b.rst | 2 +- Documentation/admin-guide/auxdisplay/ks0108.rst | 2 +- MAINTAINERS | 12 ++++++------ drivers/auxdisplay/cfag12864b.c | 4 ++-- drivers/auxdisplay/cfag12864bfb.c | 4 ++-- drivers/auxdisplay/ks0108.c | 4 ++-- include/linux/cfag12864b.h | 2 +- include/linux/ks0108.h | 2 +- samples/auxdisplay/cfag12864b-example.c | 2 +- 11 files changed, 21 insertions(+), 23 deletions(-) (limited to 'MAINTAINERS') diff --git a/.mailmap b/.mailmap index 87a8bbdbf749..85b93cdefc87 100644 --- a/.mailmap +++ b/.mailmap @@ -237,6 +237,7 @@ Maxime Ripard Mayuresh Janorkar Michael Buesch Michel Dänzer +Miguel Ojeda Mike Rapoport Mike Rapoport Mike Rapoport diff --git a/CREDITS b/CREDITS index be097156bd71..cef83b958cbe 100644 --- a/CREDITS +++ b/CREDITS @@ -2841,14 +2841,11 @@ S: Subiaco, 6008 S: Perth, Western Australia S: Australia -N: Miguel Ojeda Sandonis -E: miguel.ojeda.sandonis@gmail.com -W: http://miguelojeda.es -W: http://jair.lab.fi.uva.es/~migojed/ +N: Miguel Ojeda +E: ojeda@kernel.org +W: https://ojeda.dev D: Author of the ks0108, cfag12864b and cfag12864bfb auxiliary display drivers. D: Maintainer of the auxiliary display drivers tree (drivers/auxdisplay/*) -S: C/ Mieses 20, 9-B -S: Valladolid 47009 S: Spain N: Peter Oruba diff --git a/Documentation/admin-guide/auxdisplay/cfag12864b.rst b/Documentation/admin-guide/auxdisplay/cfag12864b.rst index 18c2865bd322..da385d851acc 100644 --- a/Documentation/admin-guide/auxdisplay/cfag12864b.rst +++ b/Documentation/admin-guide/auxdisplay/cfag12864b.rst @@ -3,7 +3,7 @@ cfag12864b LCD Driver Documentation =================================== :License: GPLv2 -:Author & Maintainer: Miguel Ojeda Sandonis +:Author & Maintainer: Miguel Ojeda :Date: 2006-10-27 diff --git a/Documentation/admin-guide/auxdisplay/ks0108.rst b/Documentation/admin-guide/auxdisplay/ks0108.rst index c0b7faf73136..a7d3fe509373 100644 --- a/Documentation/admin-guide/auxdisplay/ks0108.rst +++ b/Documentation/admin-guide/auxdisplay/ks0108.rst @@ -3,7 +3,7 @@ ks0108 LCD Controller Driver Documentation ========================================== :License: GPLv2 -:Author & Maintainer: Miguel Ojeda Sandonis +:Author & Maintainer: Miguel Ojeda :Date: 2006-10-27 diff --git a/MAINTAINERS b/MAINTAINERS index 40040db747fc..e42082eccf36 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2982,7 +2982,7 @@ F: include/uapi/linux/audit.h F: kernel/audit* AUXILIARY DISPLAY DRIVERS -M: Miguel Ojeda Sandonis +M: Miguel Ojeda S: Maintained F: drivers/auxdisplay/ F: include/linux/cfag12864b.h @@ -4128,13 +4128,13 @@ F: scripts/extract-cert.c F: scripts/sign-file.c CFAG12864B LCD DRIVER -M: Miguel Ojeda Sandonis +M: Miguel Ojeda S: Maintained F: drivers/auxdisplay/cfag12864b.c F: include/linux/cfag12864b.h CFAG12864BFB LCD FRAMEBUFFER DRIVER -M: Miguel Ojeda Sandonis +M: Miguel Ojeda S: Maintained F: drivers/auxdisplay/cfag12864bfb.c F: include/linux/cfag12864b.h @@ -4304,7 +4304,7 @@ S: Supported F: drivers/infiniband/hw/usnic/ CLANG-FORMAT FILE -M: Miguel Ojeda +M: Miguel Ojeda S: Maintained F: .clang-format @@ -4444,7 +4444,7 @@ S: Maintained F: drivers/platform/x86/compal-laptop.c COMPILER ATTRIBUTES -M: Miguel Ojeda +M: Miguel Ojeda S: Maintained F: include/linux/compiler_attributes.h @@ -9939,7 +9939,7 @@ F: include/linux/kprobes.h F: kernel/kprobes.c KS0108 LCD CONTROLLER DRIVER -M: Miguel Ojeda Sandonis +M: Miguel Ojeda S: Maintained F: Documentation/admin-guide/auxdisplay/ks0108.rst F: drivers/auxdisplay/ks0108.c diff --git a/drivers/auxdisplay/cfag12864b.c b/drivers/auxdisplay/cfag12864b.c index 7eebae7e322c..fd430e6866a1 100644 --- a/drivers/auxdisplay/cfag12864b.c +++ b/drivers/auxdisplay/cfag12864b.c @@ -5,7 +5,7 @@ * Description: cfag12864b LCD driver * Depends: ks0108 * - * Author: Copyright (C) Miguel Ojeda Sandonis + * Author: Copyright (C) Miguel Ojeda * Date: 2006-10-31 */ @@ -376,5 +376,5 @@ module_init(cfag12864b_init); module_exit(cfag12864b_exit); MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Miguel Ojeda Sandonis "); +MODULE_AUTHOR("Miguel Ojeda "); MODULE_DESCRIPTION("cfag12864b LCD driver"); diff --git a/drivers/auxdisplay/cfag12864bfb.c b/drivers/auxdisplay/cfag12864bfb.c index 2002291ab338..d66821adf453 100644 --- a/drivers/auxdisplay/cfag12864bfb.c +++ b/drivers/auxdisplay/cfag12864bfb.c @@ -5,7 +5,7 @@ * Description: cfag12864b LCD framebuffer driver * Depends: cfag12864b * - * Author: Copyright (C) Miguel Ojeda Sandonis + * Author: Copyright (C) Miguel Ojeda * Date: 2006-10-31 */ @@ -171,5 +171,5 @@ module_init(cfag12864bfb_init); module_exit(cfag12864bfb_exit); MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Miguel Ojeda Sandonis "); +MODULE_AUTHOR("Miguel Ojeda "); MODULE_DESCRIPTION("cfag12864b LCD framebuffer driver"); diff --git a/drivers/auxdisplay/ks0108.c b/drivers/auxdisplay/ks0108.c index abfe3fa9e6f4..03c95ad4216c 100644 --- a/drivers/auxdisplay/ks0108.c +++ b/drivers/auxdisplay/ks0108.c @@ -5,7 +5,7 @@ * Description: ks0108 LCD Controller driver * Depends: parport * - * Author: Copyright (C) Miguel Ojeda Sandonis + * Author: Copyright (C) Miguel Ojeda * Date: 2006-10-31 */ @@ -182,6 +182,6 @@ module_init(ks0108_init); module_exit(ks0108_exit); MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Miguel Ojeda Sandonis "); +MODULE_AUTHOR("Miguel Ojeda "); MODULE_DESCRIPTION("ks0108 LCD Controller driver"); diff --git a/include/linux/cfag12864b.h b/include/linux/cfag12864b.h index 4060004968c8..6617d9c68d86 100644 --- a/include/linux/cfag12864b.h +++ b/include/linux/cfag12864b.h @@ -4,7 +4,7 @@ * Version: 0.1.0 * Description: cfag12864b LCD driver header * - * Author: Copyright (C) Miguel Ojeda Sandonis + * Author: Copyright (C) Miguel Ojeda * Date: 2006-10-12 */ diff --git a/include/linux/ks0108.h b/include/linux/ks0108.h index 0738389b42b6..1a37a664f915 100644 --- a/include/linux/ks0108.h +++ b/include/linux/ks0108.h @@ -4,7 +4,7 @@ * Version: 0.1.0 * Description: ks0108 LCD Controller driver header * - * Author: Copyright (C) Miguel Ojeda Sandonis + * Author: Copyright (C) Miguel Ojeda * Date: 2006-10-31 */ diff --git a/samples/auxdisplay/cfag12864b-example.c b/samples/auxdisplay/cfag12864b-example.c index bfeab44f81d0..2e3bb7375c99 100644 --- a/samples/auxdisplay/cfag12864b-example.c +++ b/samples/auxdisplay/cfag12864b-example.c @@ -4,7 +4,7 @@ * Version: 0.1.0 * Description: cfag12864b LCD userspace example program * - * Author: Copyright (C) Miguel Ojeda Sandonis + * Author: Copyright (C) Miguel Ojeda * Date: 2006-10-31 */ -- cgit v1.2.3 From 7b4693e644cbdafdb2a2393fee8f81d85edd1b7d Mon Sep 17 00:00:00 2001 From: Vlastimil Babka Date: Thu, 25 Feb 2021 17:21:14 -0800 Subject: MAINTAINERS: add uapi directories to API/ABI section Let's add include/uapi/ and arch/*/include/uapi/ to API/ABI section, so that for patches modifying them, get_maintainers.pl suggests CCing linux-api@ so people don't forget. Link: https://lkml.kernel.org/r/20210217174745.13591-1-vbabka@suse.cz Signed-off-by: Vlastimil Babka Reported-by: David Hildenbrand Cc: Michael Kerrisk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index e42082eccf36..498cc779e354 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -261,6 +261,8 @@ ABI/API L: linux-api@vger.kernel.org F: include/linux/syscalls.h F: kernel/sys_ni.c +F: include/uapi/ +F: arch/*/include/uapi/ ABIT UGURU 1,2 HARDWARE MONITOR DRIVER M: Hans de Goede -- cgit v1.2.3 From fc622b3d36e6d91330fb21506b9ad1e3206a4dde Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Fri, 12 Feb 2021 12:54:34 +0100 Subject: platform/surface: Set up Surface Aggregator device registry The Surface System Aggregator Module (SSAM) subsystem provides various functionalities, which are separated by spreading them across multiple devices and corresponding drivers. Parts of that functionality / some of those devices, however, can (as far as we currently know) not be auto-detected by conventional means. While older (specifically 5th- and 6th-)generation models do advertise most of their functionality via standard platform devices in ACPI, newer generations do not. As we are currently also not aware of any feasible way to query said functionalities dynamically, this poses a problem. There is, however, a device in ACPI that seems to be used by Windows for identifying different Surface models: The Windows Surface Integration Device (WSID). This device seems to have a HID corresponding to the overall set of functionalities SSAM provides for the associated model. This commit introduces a registry providing non-detectable device information via software nodes. In addition, a SSAM platform hub driver is introduced, which takes care of creating and managing the SSAM devices specified in this registry. This approach allows for a hierarchical setup akin to ACPI and is easily extendable, e.g. via firmware node properties. Note that this commit only provides the basis for the platform hub and registry, and does not add any content to it. The registry will be expanded in subsequent commits. Signed-off-by: Maximilian Luz Link: https://lore.kernel.org/r/20210212115439.1525216-2-luzmaximilian@gmail.com Signed-off-by: Hans de Goede --- MAINTAINERS | 1 + drivers/platform/surface/Kconfig | 27 ++ drivers/platform/surface/Makefile | 1 + .../platform/surface/surface_aggregator_registry.c | 284 +++++++++++++++++++++ 4 files changed, 313 insertions(+) create mode 100644 drivers/platform/surface/surface_aggregator_registry.c (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index d92f85ca831d..4d433fd526c1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11897,6 +11897,7 @@ F: Documentation/driver-api/surface_aggregator/ F: drivers/platform/surface/aggregator/ F: drivers/platform/surface/surface_acpi_notify.c F: drivers/platform/surface/surface_aggregator_cdev.c +F: drivers/platform/surface/surface_aggregator_registry.c F: include/linux/surface_acpi_notify.h F: include/linux/surface_aggregator/ F: include/uapi/linux/surface_aggregator/ diff --git a/drivers/platform/surface/Kconfig b/drivers/platform/surface/Kconfig index 0847b2dc97bf..179b8c93d7fd 100644 --- a/drivers/platform/surface/Kconfig +++ b/drivers/platform/surface/Kconfig @@ -77,6 +77,33 @@ config SURFACE_AGGREGATOR_CDEV The provided interface is intended for debugging and development only, and should not be used otherwise. +config SURFACE_AGGREGATOR_REGISTRY + tristate "Surface System Aggregator Module Device Registry" + depends on SURFACE_AGGREGATOR + depends on SURFACE_AGGREGATOR_BUS + help + Device-registry and device-hubs for Surface System Aggregator Module + (SSAM) devices. + + Provides a module and driver which act as a device-registry for SSAM + client devices that cannot be detected automatically, e.g. via ACPI. + Such devices are instead provided via this registry and attached via + device hubs, also provided in this module. + + Devices provided via this registry are: + - Platform profile (performance-/cooling-mode) device (5th- and later + generations). + - Battery/AC devices (7th-generation). + - HID input devices (7th-generation). + + Select M (recommended) or Y here if you want support for the above + mentioned devices on the corresponding Surface models. Without this + module, the respective devices will not be instantiated and thus any + functionality provided by them will be missing, even when drivers for + these devices are present. In other words, this module only provides + the respective client devices. Drivers for these devices still need to + be selected via the other options. + config SURFACE_GPE tristate "Surface GPE/Lid Support Driver" depends on DMI diff --git a/drivers/platform/surface/Makefile b/drivers/platform/surface/Makefile index 990424c5f0c9..80035ee540bf 100644 --- a/drivers/platform/surface/Makefile +++ b/drivers/platform/surface/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_SURFACE_3_POWER_OPREGION) += surface3_power.o obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/ obj-$(CONFIG_SURFACE_AGGREGATOR_CDEV) += surface_aggregator_cdev.o +obj-$(CONFIG_SURFACE_AGGREGATOR_REGISTRY) += surface_aggregator_registry.o obj-$(CONFIG_SURFACE_GPE) += surface_gpe.o obj-$(CONFIG_SURFACE_HOTPLUG) += surface_hotplug.o obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c new file mode 100644 index 000000000000..a051d941ad96 --- /dev/null +++ b/drivers/platform/surface/surface_aggregator_registry.c @@ -0,0 +1,284 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Surface System Aggregator Module (SSAM) client device registry. + * + * Registry for non-platform/non-ACPI SSAM client devices, i.e. devices that + * cannot be auto-detected. Provides device-hubs and performs instantiation + * for these devices. + * + * Copyright (C) 2020-2021 Maximilian Luz + */ + +#include +#include +#include +#include +#include + +#include +#include + + +/* -- Device registry. ------------------------------------------------------ */ + +/* + * SSAM device names follow the SSAM module alias, meaning they are prefixed + * with 'ssam:', followed by domain, category, target ID, instance ID, and + * function, each encoded as two-digit hexadecimal, separated by ':'. In other + * words, it follows the scheme + * + * ssam:dd:cc:tt:ii:ff + * + * Where, 'dd', 'cc', 'tt', 'ii', and 'ff' are the two-digit hexadecimal + * values mentioned above, respectively. + */ + +/* Root node. */ +static const struct software_node ssam_node_root = { + .name = "ssam_platform_hub", +}; + +/* Devices for Surface Book 2. */ +static const struct software_node *ssam_node_group_sb2[] = { + &ssam_node_root, + NULL, +}; + +/* Devices for Surface Book 3. */ +static const struct software_node *ssam_node_group_sb3[] = { + &ssam_node_root, + NULL, +}; + +/* Devices for Surface Laptop 1. */ +static const struct software_node *ssam_node_group_sl1[] = { + &ssam_node_root, + NULL, +}; + +/* Devices for Surface Laptop 2. */ +static const struct software_node *ssam_node_group_sl2[] = { + &ssam_node_root, + NULL, +}; + +/* Devices for Surface Laptop 3. */ +static const struct software_node *ssam_node_group_sl3[] = { + &ssam_node_root, + NULL, +}; + +/* Devices for Surface Laptop Go. */ +static const struct software_node *ssam_node_group_slg1[] = { + &ssam_node_root, + NULL, +}; + +/* Devices for Surface Pro 5. */ +static const struct software_node *ssam_node_group_sp5[] = { + &ssam_node_root, + NULL, +}; + +/* Devices for Surface Pro 6. */ +static const struct software_node *ssam_node_group_sp6[] = { + &ssam_node_root, + NULL, +}; + +/* Devices for Surface Pro 7. */ +static const struct software_node *ssam_node_group_sp7[] = { + &ssam_node_root, + NULL, +}; + + +/* -- Device registry helper functions. ------------------------------------- */ + +static int ssam_uid_from_string(const char *str, struct ssam_device_uid *uid) +{ + u8 d, tc, tid, iid, fn; + int n; + + n = sscanf(str, "ssam:%hhx:%hhx:%hhx:%hhx:%hhx", &d, &tc, &tid, &iid, &fn); + if (n != 5) + return -EINVAL; + + uid->domain = d; + uid->category = tc; + uid->target = tid; + uid->instance = iid; + uid->function = fn; + + return 0; +} + +static int ssam_hub_remove_devices_fn(struct device *dev, void *data) +{ + if (!is_ssam_device(dev)) + return 0; + + ssam_device_remove(to_ssam_device(dev)); + return 0; +} + +static void ssam_hub_remove_devices(struct device *parent) +{ + device_for_each_child_reverse(parent, NULL, ssam_hub_remove_devices_fn); +} + +static int ssam_hub_add_device(struct device *parent, struct ssam_controller *ctrl, + struct fwnode_handle *node) +{ + struct ssam_device_uid uid; + struct ssam_device *sdev; + int status; + + status = ssam_uid_from_string(fwnode_get_name(node), &uid); + if (status) + return status; + + sdev = ssam_device_alloc(ctrl, uid); + if (!sdev) + return -ENOMEM; + + sdev->dev.parent = parent; + sdev->dev.fwnode = node; + + status = ssam_device_add(sdev); + if (status) + ssam_device_put(sdev); + + return status; +} + +static int ssam_hub_add_devices(struct device *parent, struct ssam_controller *ctrl, + struct fwnode_handle *node) +{ + struct fwnode_handle *child; + int status; + + fwnode_for_each_child_node(node, child) { + /* + * Try to add the device specified in the firmware node. If + * this fails with -EINVAL, the node does not specify any SSAM + * device, so ignore it and continue with the next one. + */ + + status = ssam_hub_add_device(parent, ctrl, child); + if (status && status != -EINVAL) + goto err; + } + + return 0; +err: + ssam_hub_remove_devices(parent); + return status; +} + + +/* -- SSAM platform/meta-hub driver. ---------------------------------------- */ + +static const struct acpi_device_id ssam_platform_hub_match[] = { + /* Surface Pro 4, 5, and 6 (OMBR < 0x10) */ + { "MSHW0081", (unsigned long)ssam_node_group_sp5 }, + + /* Surface Pro 6 (OMBR >= 0x10) */ + { "MSHW0111", (unsigned long)ssam_node_group_sp6 }, + + /* Surface Pro 7 */ + { "MSHW0116", (unsigned long)ssam_node_group_sp7 }, + + /* Surface Book 2 */ + { "MSHW0107", (unsigned long)ssam_node_group_sb2 }, + + /* Surface Book 3 */ + { "MSHW0117", (unsigned long)ssam_node_group_sb3 }, + + /* Surface Laptop 1 */ + { "MSHW0086", (unsigned long)ssam_node_group_sl1 }, + + /* Surface Laptop 2 */ + { "MSHW0112", (unsigned long)ssam_node_group_sl2 }, + + /* Surface Laptop 3 (13", Intel) */ + { "MSHW0114", (unsigned long)ssam_node_group_sl3 }, + + /* Surface Laptop 3 (15", AMD) */ + { "MSHW0110", (unsigned long)ssam_node_group_sl3 }, + + /* Surface Laptop Go 1 */ + { "MSHW0118", (unsigned long)ssam_node_group_slg1 }, + + { }, +}; +MODULE_DEVICE_TABLE(acpi, ssam_platform_hub_match); + +static int ssam_platform_hub_probe(struct platform_device *pdev) +{ + const struct software_node **nodes; + struct ssam_controller *ctrl; + struct fwnode_handle *root; + int status; + + nodes = (const struct software_node **)acpi_device_get_match_data(&pdev->dev); + if (!nodes) + return -ENODEV; + + /* + * As we're adding the SSAM client devices as children under this device + * and not the SSAM controller, we need to add a device link to the + * controller to ensure that we remove all of our devices before the + * controller is removed. This also guarantees proper ordering for + * suspend/resume of the devices on this hub. + */ + ctrl = ssam_client_bind(&pdev->dev); + if (IS_ERR(ctrl)) + return PTR_ERR(ctrl) == -ENODEV ? -EPROBE_DEFER : PTR_ERR(ctrl); + + status = software_node_register_node_group(nodes); + if (status) + return status; + + root = software_node_fwnode(&ssam_node_root); + if (!root) { + software_node_unregister_node_group(nodes); + return -ENOENT; + } + + set_secondary_fwnode(&pdev->dev, root); + + status = ssam_hub_add_devices(&pdev->dev, ctrl, root); + if (status) { + set_secondary_fwnode(&pdev->dev, NULL); + software_node_unregister_node_group(nodes); + } + + platform_set_drvdata(pdev, nodes); + return status; +} + +static int ssam_platform_hub_remove(struct platform_device *pdev) +{ + const struct software_node **nodes = platform_get_drvdata(pdev); + + ssam_hub_remove_devices(&pdev->dev); + set_secondary_fwnode(&pdev->dev, NULL); + software_node_unregister_node_group(nodes); + return 0; +} + +static struct platform_driver ssam_platform_hub_driver = { + .probe = ssam_platform_hub_probe, + .remove = ssam_platform_hub_remove, + .driver = { + .name = "surface_aggregator_platform_hub", + .acpi_match_table = ssam_platform_hub_match, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, +}; +module_platform_driver(ssam_platform_hub_driver); + +MODULE_AUTHOR("Maximilian Luz "); +MODULE_DESCRIPTION("Device-registry for Surface System Aggregator Module"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From b05ff1002a5c19f2fd511c6eada6f475ff701841 Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Wed, 10 Mar 2021 23:53:28 +0100 Subject: HID: Add support for Surface Aggregator Module HID transport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a HID transport driver to support integrated HID devices on newer Microsoft Surface models (specifically 7th-generation, i.e. Surface Laptop 3, Surface Book 3, and later). On those models, the internal keyboard and touchpad (as well as some other HID devices with currently unknown function) are connected via the generic HID subsystem (TC=0x15) of the Surface System Aggregator Module (SSAM). This subsystem provides a generic HID transport layer, support for which is implemented by this driver. Co-developed-by: Blaž Hrastnik Signed-off-by: Blaž Hrastnik Signed-off-by: Maximilian Luz Signed-off-by: Jiri Kosina --- MAINTAINERS | 7 + drivers/hid/Kconfig | 2 + drivers/hid/Makefile | 2 + drivers/hid/surface-hid/Kconfig | 28 +++ drivers/hid/surface-hid/Makefile | 6 + drivers/hid/surface-hid/surface_hid.c | 253 +++++++++++++++++++++++++++ drivers/hid/surface-hid/surface_hid_core.c | 272 +++++++++++++++++++++++++++++ drivers/hid/surface-hid/surface_hid_core.h | 77 ++++++++ 8 files changed, 647 insertions(+) create mode 100644 drivers/hid/surface-hid/Kconfig create mode 100644 drivers/hid/surface-hid/Makefile create mode 100644 drivers/hid/surface-hid/surface_hid.c create mode 100644 drivers/hid/surface-hid/surface_hid_core.c create mode 100644 drivers/hid/surface-hid/surface_hid_core.h (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 4d433fd526c1..d6a1924afdcc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11876,6 +11876,13 @@ S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git F: drivers/platform/surface/ +MICROSOFT SURFACE HID TRANSPORT DRIVER +M: Maximilian Luz +L: linux-input@vger.kernel.org +L: platform-driver-x86@vger.kernel.org +S: Maintained +F: drivers/hid/surface-hid/ + MICROSOFT SURFACE HOT-PLUG DRIVER M: Maximilian Luz L: platform-driver-x86@vger.kernel.org diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 786b71ef7738..26e06097ba08 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -1206,4 +1206,6 @@ source "drivers/hid/intel-ish-hid/Kconfig" source "drivers/hid/amd-sfh-hid/Kconfig" +source "drivers/hid/surface-hid/Kconfig" + endmenu diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index c4f6d5c613dc..1044ed238856 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -145,3 +145,5 @@ obj-$(CONFIG_INTEL_ISH_HID) += intel-ish-hid/ obj-$(INTEL_ISH_FIRMWARE_DOWNLOADER) += intel-ish-hid/ obj-$(CONFIG_AMD_SFH_HID) += amd-sfh-hid/ + +obj-$(CONFIG_SURFACE_HID_CORE) += surface-hid/ diff --git a/drivers/hid/surface-hid/Kconfig b/drivers/hid/surface-hid/Kconfig new file mode 100644 index 000000000000..642c7f0e64fe --- /dev/null +++ b/drivers/hid/surface-hid/Kconfig @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0+ +menu "Surface System Aggregator Module HID support" + depends on SURFACE_AGGREGATOR + depends on INPUT + +config SURFACE_HID + tristate "HID transport driver for Surface System Aggregator Module" + depends on SURFACE_AGGREGATOR_REGISTRY + select SURFACE_HID_CORE + help + Driver to support integrated HID devices on newer Microsoft Surface + models. + + This driver provides support for the HID transport protocol provided + by the Surface Aggregator Module (i.e. the embedded controller) on + 7th-generation Microsoft Surface devices, i.e. Surface Book 3 and + Surface Laptop 3. On those models, it is mainly used to connect the + integrated touchpad and keyboard. + + Say M or Y here, if you want support for integrated HID devices, i.e. + integrated touchpad and keyboard, on 7th generation Microsoft Surface + models. + +endmenu + +config SURFACE_HID_CORE + tristate + select HID diff --git a/drivers/hid/surface-hid/Makefile b/drivers/hid/surface-hid/Makefile new file mode 100644 index 000000000000..62fc04632d3d --- /dev/null +++ b/drivers/hid/surface-hid/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Makefile - Surface System Aggregator Module (SSAM) HID transport driver. +# +obj-$(CONFIG_SURFACE_HID_CORE) += surface_hid_core.o +obj-$(CONFIG_SURFACE_HID) += surface_hid.o diff --git a/drivers/hid/surface-hid/surface_hid.c b/drivers/hid/surface-hid/surface_hid.c new file mode 100644 index 000000000000..3477b31611ae --- /dev/null +++ b/drivers/hid/surface-hid/surface_hid.c @@ -0,0 +1,253 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Surface System Aggregator Module (SSAM) HID transport driver for the + * generic HID interface (HID/TC=0x15 subsystem). Provides support for + * integrated HID devices on Surface Laptop 3, Book 3, and later. + * + * Copyright (C) 2019-2021 Blaž Hrastnik , + * Maximilian Luz + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "surface_hid_core.h" + + +/* -- SAM interface. -------------------------------------------------------- */ + +struct surface_hid_buffer_slice { + __u8 entry; + __le32 offset; + __le32 length; + __u8 end; + __u8 data[]; +} __packed; + +static_assert(sizeof(struct surface_hid_buffer_slice) == 10); + +enum surface_hid_cid { + SURFACE_HID_CID_OUTPUT_REPORT = 0x01, + SURFACE_HID_CID_GET_FEATURE_REPORT = 0x02, + SURFACE_HID_CID_SET_FEATURE_REPORT = 0x03, + SURFACE_HID_CID_GET_DESCRIPTOR = 0x04, +}; + +static int ssam_hid_get_descriptor(struct surface_hid_device *shid, u8 entry, u8 *buf, size_t len) +{ + u8 buffer[sizeof(struct surface_hid_buffer_slice) + 0x76]; + struct surface_hid_buffer_slice *slice; + struct ssam_request rqst; + struct ssam_response rsp; + u32 buffer_len, offset, length; + int status; + + /* + * Note: The 0x76 above has been chosen because that's what's used by + * the Windows driver. Together with the header, this leads to a 128 + * byte payload in total. + */ + + buffer_len = ARRAY_SIZE(buffer) - sizeof(struct surface_hid_buffer_slice); + + rqst.target_category = shid->uid.category; + rqst.target_id = shid->uid.target; + rqst.command_id = SURFACE_HID_CID_GET_DESCRIPTOR; + rqst.instance_id = shid->uid.instance; + rqst.flags = SSAM_REQUEST_HAS_RESPONSE; + rqst.length = sizeof(struct surface_hid_buffer_slice); + rqst.payload = buffer; + + rsp.capacity = ARRAY_SIZE(buffer); + rsp.pointer = buffer; + + slice = (struct surface_hid_buffer_slice *)buffer; + slice->entry = entry; + slice->end = 0; + + offset = 0; + length = buffer_len; + + while (!slice->end && offset < len) { + put_unaligned_le32(offset, &slice->offset); + put_unaligned_le32(length, &slice->length); + + rsp.length = 0; + + status = ssam_retry(ssam_request_sync_onstack, shid->ctrl, &rqst, &rsp, + sizeof(*slice)); + if (status) + return status; + + offset = get_unaligned_le32(&slice->offset); + length = get_unaligned_le32(&slice->length); + + /* Don't mess stuff up in case we receive garbage. */ + if (length > buffer_len || offset > len) + return -EPROTO; + + if (offset + length > len) + length = len - offset; + + memcpy(buf + offset, &slice->data[0], length); + + offset += length; + length = buffer_len; + } + + if (offset != len) { + dev_err(shid->dev, "unexpected descriptor length: got %u, expected %zu\n", + offset, len); + return -EPROTO; + } + + return 0; +} + +static int ssam_hid_set_raw_report(struct surface_hid_device *shid, u8 rprt_id, bool feature, + u8 *buf, size_t len) +{ + struct ssam_request rqst; + u8 cid; + + if (feature) + cid = SURFACE_HID_CID_SET_FEATURE_REPORT; + else + cid = SURFACE_HID_CID_OUTPUT_REPORT; + + rqst.target_category = shid->uid.category; + rqst.target_id = shid->uid.target; + rqst.instance_id = shid->uid.instance; + rqst.command_id = cid; + rqst.flags = 0; + rqst.length = len; + rqst.payload = buf; + + buf[0] = rprt_id; + + return ssam_retry(ssam_request_sync, shid->ctrl, &rqst, NULL); +} + +static int ssam_hid_get_raw_report(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len) +{ + struct ssam_request rqst; + struct ssam_response rsp; + + rqst.target_category = shid->uid.category; + rqst.target_id = shid->uid.target; + rqst.instance_id = shid->uid.instance; + rqst.command_id = SURFACE_HID_CID_GET_FEATURE_REPORT; + rqst.flags = 0; + rqst.length = sizeof(rprt_id); + rqst.payload = &rprt_id; + + rsp.capacity = len; + rsp.length = 0; + rsp.pointer = buf; + + return ssam_retry(ssam_request_sync_onstack, shid->ctrl, &rqst, &rsp, sizeof(rprt_id)); +} + +static u32 ssam_hid_event_fn(struct ssam_event_notifier *nf, const struct ssam_event *event) +{ + struct surface_hid_device *shid = container_of(nf, struct surface_hid_device, notif); + + if (event->command_id != 0x00) + return 0; + + hid_input_report(shid->hid, HID_INPUT_REPORT, (u8 *)&event->data[0], event->length, 0); + return SSAM_NOTIF_HANDLED; +} + + +/* -- Transport driver. ----------------------------------------------------- */ + +static int shid_output_report(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len) +{ + int status; + + status = ssam_hid_set_raw_report(shid, rprt_id, false, buf, len); + return status >= 0 ? len : status; +} + +static int shid_get_feature_report(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len) +{ + int status; + + status = ssam_hid_get_raw_report(shid, rprt_id, buf, len); + return status >= 0 ? len : status; +} + +static int shid_set_feature_report(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len) +{ + int status; + + status = ssam_hid_set_raw_report(shid, rprt_id, true, buf, len); + return status >= 0 ? len : status; +} + + +/* -- Driver setup. --------------------------------------------------------- */ + +static int surface_hid_probe(struct ssam_device *sdev) +{ + struct surface_hid_device *shid; + + shid = devm_kzalloc(&sdev->dev, sizeof(*shid), GFP_KERNEL); + if (!shid) + return -ENOMEM; + + shid->dev = &sdev->dev; + shid->ctrl = sdev->ctrl; + shid->uid = sdev->uid; + + shid->notif.base.priority = 1; + shid->notif.base.fn = ssam_hid_event_fn; + shid->notif.event.reg = SSAM_EVENT_REGISTRY_REG; + shid->notif.event.id.target_category = sdev->uid.category; + shid->notif.event.id.instance = sdev->uid.instance; + shid->notif.event.mask = SSAM_EVENT_MASK_STRICT; + shid->notif.event.flags = 0; + + shid->ops.get_descriptor = ssam_hid_get_descriptor; + shid->ops.output_report = shid_output_report; + shid->ops.get_feature_report = shid_get_feature_report; + shid->ops.set_feature_report = shid_set_feature_report; + + ssam_device_set_drvdata(sdev, shid); + return surface_hid_device_add(shid); +} + +static void surface_hid_remove(struct ssam_device *sdev) +{ + surface_hid_device_destroy(ssam_device_get_drvdata(sdev)); +} + +static const struct ssam_device_id surface_hid_match[] = { + { SSAM_SDEV(HID, 0x02, SSAM_ANY_IID, 0x00) }, + { }, +}; +MODULE_DEVICE_TABLE(ssam, surface_hid_match); + +static struct ssam_device_driver surface_hid_driver = { + .probe = surface_hid_probe, + .remove = surface_hid_remove, + .match_table = surface_hid_match, + .driver = { + .name = "surface_hid", + .pm = &surface_hid_pm_ops, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, +}; +module_ssam_device_driver(surface_hid_driver); + +MODULE_AUTHOR("Blaž Hrastnik "); +MODULE_AUTHOR("Maximilian Luz "); +MODULE_DESCRIPTION("HID transport driver for Surface System Aggregator Module"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hid/surface-hid/surface_hid_core.c b/drivers/hid/surface-hid/surface_hid_core.c new file mode 100644 index 000000000000..7b27ec392232 --- /dev/null +++ b/drivers/hid/surface-hid/surface_hid_core.c @@ -0,0 +1,272 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Common/core components for the Surface System Aggregator Module (SSAM) HID + * transport driver. Provides support for integrated HID devices on Microsoft + * Surface models. + * + * Copyright (C) 2019-2021 Maximilian Luz + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "surface_hid_core.h" + + +/* -- Device descriptor access. --------------------------------------------- */ + +static int surface_hid_load_hid_descriptor(struct surface_hid_device *shid) +{ + int status; + + status = shid->ops.get_descriptor(shid, SURFACE_HID_DESC_HID, + (u8 *)&shid->hid_desc, sizeof(shid->hid_desc)); + if (status) + return status; + + if (shid->hid_desc.desc_len != sizeof(shid->hid_desc)) { + dev_err(shid->dev, "unexpected HID descriptor length: got %u, expected %zu\n", + shid->hid_desc.desc_len, sizeof(shid->hid_desc)); + return -EPROTO; + } + + if (shid->hid_desc.desc_type != HID_DT_HID) { + dev_err(shid->dev, "unexpected HID descriptor type: got %#04x, expected %#04x\n", + shid->hid_desc.desc_type, HID_DT_HID); + return -EPROTO; + } + + if (shid->hid_desc.num_descriptors != 1) { + dev_err(shid->dev, "unexpected number of descriptors: got %u, expected 1\n", + shid->hid_desc.num_descriptors); + return -EPROTO; + } + + if (shid->hid_desc.report_desc_type != HID_DT_REPORT) { + dev_err(shid->dev, "unexpected report descriptor type: got %#04x, expected %#04x\n", + shid->hid_desc.report_desc_type, HID_DT_REPORT); + return -EPROTO; + } + + return 0; +} + +static int surface_hid_load_device_attributes(struct surface_hid_device *shid) +{ + int status; + + status = shid->ops.get_descriptor(shid, SURFACE_HID_DESC_ATTRS, + (u8 *)&shid->attrs, sizeof(shid->attrs)); + if (status) + return status; + + if (get_unaligned_le32(&shid->attrs.length) != sizeof(shid->attrs)) { + dev_err(shid->dev, "unexpected attribute length: got %u, expected %zu\n", + get_unaligned_le32(&shid->attrs.length), sizeof(shid->attrs)); + return -EPROTO; + } + + return 0; +} + + +/* -- Transport driver (common). -------------------------------------------- */ + +static int surface_hid_start(struct hid_device *hid) +{ + struct surface_hid_device *shid = hid->driver_data; + + return ssam_notifier_register(shid->ctrl, &shid->notif); +} + +static void surface_hid_stop(struct hid_device *hid) +{ + struct surface_hid_device *shid = hid->driver_data; + + /* Note: This call will log errors for us, so ignore them here. */ + ssam_notifier_unregister(shid->ctrl, &shid->notif); +} + +static int surface_hid_open(struct hid_device *hid) +{ + return 0; +} + +static void surface_hid_close(struct hid_device *hid) +{ +} + +static int surface_hid_parse(struct hid_device *hid) +{ + struct surface_hid_device *shid = hid->driver_data; + size_t len = get_unaligned_le16(&shid->hid_desc.report_desc_len); + u8 *buf; + int status; + + buf = kzalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + status = shid->ops.get_descriptor(shid, SURFACE_HID_DESC_REPORT, buf, len); + if (!status) + status = hid_parse_report(hid, buf, len); + + kfree(buf); + return status; +} + +static int surface_hid_raw_request(struct hid_device *hid, unsigned char reportnum, u8 *buf, + size_t len, unsigned char rtype, int reqtype) +{ + struct surface_hid_device *shid = hid->driver_data; + + if (rtype == HID_OUTPUT_REPORT && reqtype == HID_REQ_SET_REPORT) + return shid->ops.output_report(shid, reportnum, buf, len); + + else if (rtype == HID_FEATURE_REPORT && reqtype == HID_REQ_GET_REPORT) + return shid->ops.get_feature_report(shid, reportnum, buf, len); + + else if (rtype == HID_FEATURE_REPORT && reqtype == HID_REQ_SET_REPORT) + return shid->ops.set_feature_report(shid, reportnum, buf, len); + + return -EIO; +} + +static struct hid_ll_driver surface_hid_ll_driver = { + .start = surface_hid_start, + .stop = surface_hid_stop, + .open = surface_hid_open, + .close = surface_hid_close, + .parse = surface_hid_parse, + .raw_request = surface_hid_raw_request, +}; + + +/* -- Common device setup. -------------------------------------------------- */ + +int surface_hid_device_add(struct surface_hid_device *shid) +{ + int status; + + status = surface_hid_load_hid_descriptor(shid); + if (status) + return status; + + status = surface_hid_load_device_attributes(shid); + if (status) + return status; + + shid->hid = hid_allocate_device(); + if (IS_ERR(shid->hid)) + return PTR_ERR(shid->hid); + + shid->hid->dev.parent = shid->dev; + shid->hid->bus = BUS_HOST; + shid->hid->vendor = cpu_to_le16(shid->attrs.vendor); + shid->hid->product = cpu_to_le16(shid->attrs.product); + shid->hid->version = cpu_to_le16(shid->hid_desc.hid_version); + shid->hid->country = shid->hid_desc.country_code; + + snprintf(shid->hid->name, sizeof(shid->hid->name), "Microsoft Surface %04X:%04X", + shid->hid->vendor, shid->hid->product); + + strscpy(shid->hid->phys, dev_name(shid->dev), sizeof(shid->hid->phys)); + + shid->hid->driver_data = shid; + shid->hid->ll_driver = &surface_hid_ll_driver; + + status = hid_add_device(shid->hid); + if (status) + hid_destroy_device(shid->hid); + + return status; +} +EXPORT_SYMBOL_GPL(surface_hid_device_add); + +void surface_hid_device_destroy(struct surface_hid_device *shid) +{ + hid_destroy_device(shid->hid); +} +EXPORT_SYMBOL_GPL(surface_hid_device_destroy); + + +/* -- PM ops. --------------------------------------------------------------- */ + +#ifdef CONFIG_PM_SLEEP + +static int surface_hid_suspend(struct device *dev) +{ + struct surface_hid_device *d = dev_get_drvdata(dev); + + if (d->hid->driver && d->hid->driver->suspend) + return d->hid->driver->suspend(d->hid, PMSG_SUSPEND); + + return 0; +} + +static int surface_hid_resume(struct device *dev) +{ + struct surface_hid_device *d = dev_get_drvdata(dev); + + if (d->hid->driver && d->hid->driver->resume) + return d->hid->driver->resume(d->hid); + + return 0; +} + +static int surface_hid_freeze(struct device *dev) +{ + struct surface_hid_device *d = dev_get_drvdata(dev); + + if (d->hid->driver && d->hid->driver->suspend) + return d->hid->driver->suspend(d->hid, PMSG_FREEZE); + + return 0; +} + +static int surface_hid_poweroff(struct device *dev) +{ + struct surface_hid_device *d = dev_get_drvdata(dev); + + if (d->hid->driver && d->hid->driver->suspend) + return d->hid->driver->suspend(d->hid, PMSG_HIBERNATE); + + return 0; +} + +static int surface_hid_restore(struct device *dev) +{ + struct surface_hid_device *d = dev_get_drvdata(dev); + + if (d->hid->driver && d->hid->driver->reset_resume) + return d->hid->driver->reset_resume(d->hid); + + return 0; +} + +const struct dev_pm_ops surface_hid_pm_ops = { + .freeze = surface_hid_freeze, + .thaw = surface_hid_resume, + .suspend = surface_hid_suspend, + .resume = surface_hid_resume, + .poweroff = surface_hid_poweroff, + .restore = surface_hid_restore, +}; +EXPORT_SYMBOL_GPL(surface_hid_pm_ops); + +#else /* CONFIG_PM_SLEEP */ + +const struct dev_pm_ops surface_hid_pm_ops = { }; +EXPORT_SYMBOL_GPL(surface_hid_pm_ops); + +#endif /* CONFIG_PM_SLEEP */ + +MODULE_AUTHOR("Maximilian Luz "); +MODULE_DESCRIPTION("HID transport driver core for Surface System Aggregator Module"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hid/surface-hid/surface_hid_core.h b/drivers/hid/surface-hid/surface_hid_core.h new file mode 100644 index 000000000000..4b1a7b57e035 --- /dev/null +++ b/drivers/hid/surface-hid/surface_hid_core.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Common/core components for the Surface System Aggregator Module (SSAM) HID + * transport driver. Provides support for integrated HID devices on Microsoft + * Surface models. + * + * Copyright (C) 2019-2021 Maximilian Luz + */ + +#ifndef SURFACE_HID_CORE_H +#define SURFACE_HID_CORE_H + +#include +#include +#include + +#include +#include + +enum surface_hid_descriptor_entry { + SURFACE_HID_DESC_HID = 0, + SURFACE_HID_DESC_REPORT = 1, + SURFACE_HID_DESC_ATTRS = 2, +}; + +struct surface_hid_descriptor { + __u8 desc_len; /* = 9 */ + __u8 desc_type; /* = HID_DT_HID */ + __le16 hid_version; + __u8 country_code; + __u8 num_descriptors; /* = 1 */ + + __u8 report_desc_type; /* = HID_DT_REPORT */ + __le16 report_desc_len; +} __packed; + +static_assert(sizeof(struct surface_hid_descriptor) == 9); + +struct surface_hid_attributes { + __le32 length; + __le16 vendor; + __le16 product; + __le16 version; + __u8 _unknown[22]; +} __packed; + +static_assert(sizeof(struct surface_hid_attributes) == 32); + +struct surface_hid_device; + +struct surface_hid_device_ops { + int (*get_descriptor)(struct surface_hid_device *shid, u8 entry, u8 *buf, size_t len); + int (*output_report)(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len); + int (*get_feature_report)(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len); + int (*set_feature_report)(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len); +}; + +struct surface_hid_device { + struct device *dev; + struct ssam_controller *ctrl; + struct ssam_device_uid uid; + + struct surface_hid_descriptor hid_desc; + struct surface_hid_attributes attrs; + + struct ssam_event_notifier notif; + struct hid_device *hid; + + struct surface_hid_device_ops ops; +}; + +int surface_hid_device_add(struct surface_hid_device *shid); +void surface_hid_device_destroy(struct surface_hid_device *shid); + +extern const struct dev_pm_ops surface_hid_pm_ops; + +#endif /* SURFACE_HID_CORE_H */ -- cgit v1.2.3