From 5bc1cf1466f635682c3e26eb4179541feeefb1be Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 18 May 2020 22:16:56 +0800 Subject: [PATCH 0001/1754] iommu/qcom: add optional 'tbu' clock for TLB invalidate On some SoCs like MSM8939 with A405 adreno, there is a gfx_tbu clock needs to be on while doing TLB invalidate. Otherwise, TLBSYNC status will not be correctly reflected, causing the system to go into a bad state. Add it as an optional clock, so that platforms that have this clock can pass it over DT. While adding the third clock, let's switch to bulk clk API to simplify the enable/disable calls. clk_bulk_get() cannot used because the existing two clocks are required while the new one is optional. Signed-off-by: Shawn Guo Reviewed-by: Bjorn Andersson Link: https://lore.kernel.org/r/20200518141656.26284-1-shawn.guo@linaro.org Signed-off-by: Joerg Roedel --- drivers/iommu/qcom_iommu.c | 62 ++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index 0e2a96467767b..116d8188f87f7 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -37,14 +37,20 @@ #define SMMU_INTR_SEL_NS 0x2000 +enum qcom_iommu_clk { + CLK_IFACE, + CLK_BUS, + CLK_TBU, + CLK_NUM, +}; + struct qcom_iommu_ctx; struct qcom_iommu_dev { /* IOMMU core code handle */ struct iommu_device iommu; struct device *dev; - struct clk *iface_clk; - struct clk *bus_clk; + struct clk_bulk_data clks[CLK_NUM]; void __iomem *local_base; u32 sec_id; u8 num_ctxs; @@ -626,32 +632,6 @@ static const struct iommu_ops qcom_iommu_ops = { .pgsize_bitmap = SZ_4K | SZ_64K | SZ_1M | SZ_16M, }; -static int qcom_iommu_enable_clocks(struct qcom_iommu_dev *qcom_iommu) -{ - int ret; - - ret = clk_prepare_enable(qcom_iommu->iface_clk); - if (ret) { - dev_err(qcom_iommu->dev, "Couldn't enable iface_clk\n"); - return ret; - } - - ret = clk_prepare_enable(qcom_iommu->bus_clk); - if (ret) { - dev_err(qcom_iommu->dev, "Couldn't enable bus_clk\n"); - clk_disable_unprepare(qcom_iommu->iface_clk); - return ret; - } - - return 0; -} - -static void qcom_iommu_disable_clocks(struct qcom_iommu_dev *qcom_iommu) -{ - clk_disable_unprepare(qcom_iommu->bus_clk); - clk_disable_unprepare(qcom_iommu->iface_clk); -} - static int qcom_iommu_sec_ptbl_init(struct device *dev) { size_t psize = 0; @@ -808,6 +788,7 @@ static int qcom_iommu_device_probe(struct platform_device *pdev) struct qcom_iommu_dev *qcom_iommu; struct device *dev = &pdev->dev; struct resource *res; + struct clk *clk; int ret, max_asid = 0; /* find the max asid (which is 1:1 to ctx bank idx), so we know how @@ -827,17 +808,26 @@ static int qcom_iommu_device_probe(struct platform_device *pdev) if (res) qcom_iommu->local_base = devm_ioremap_resource(dev, res); - qcom_iommu->iface_clk = devm_clk_get(dev, "iface"); - if (IS_ERR(qcom_iommu->iface_clk)) { + clk = devm_clk_get(dev, "iface"); + if (IS_ERR(clk)) { dev_err(dev, "failed to get iface clock\n"); - return PTR_ERR(qcom_iommu->iface_clk); + return PTR_ERR(clk); } + qcom_iommu->clks[CLK_IFACE].clk = clk; - qcom_iommu->bus_clk = devm_clk_get(dev, "bus"); - if (IS_ERR(qcom_iommu->bus_clk)) { + clk = devm_clk_get(dev, "bus"); + if (IS_ERR(clk)) { dev_err(dev, "failed to get bus clock\n"); - return PTR_ERR(qcom_iommu->bus_clk); + return PTR_ERR(clk); + } + qcom_iommu->clks[CLK_BUS].clk = clk; + + clk = devm_clk_get_optional(dev, "tbu"); + if (IS_ERR(clk)) { + dev_err(dev, "failed to get tbu clock\n"); + return PTR_ERR(clk); } + qcom_iommu->clks[CLK_TBU].clk = clk; if (of_property_read_u32(dev->of_node, "qcom,iommu-secure-id", &qcom_iommu->sec_id)) { @@ -909,14 +899,14 @@ static int __maybe_unused qcom_iommu_resume(struct device *dev) { struct qcom_iommu_dev *qcom_iommu = dev_get_drvdata(dev); - return qcom_iommu_enable_clocks(qcom_iommu); + return clk_bulk_prepare_enable(CLK_NUM, qcom_iommu->clks); } static int __maybe_unused qcom_iommu_suspend(struct device *dev) { struct qcom_iommu_dev *qcom_iommu = dev_get_drvdata(dev); - qcom_iommu_disable_clocks(qcom_iommu); + clk_bulk_disable_unprepare(CLK_NUM, qcom_iommu->clks); return 0; } -- GitLab From 5197360f9e09449ac7249a98fbde36a3608e059c Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 18 May 2020 19:03:21 +0200 Subject: [PATCH 0002/1754] mtd: rawnand: mtk: Convert the driver to exec_op() Let's convert the driver to exec_op() to have one less driver relying on the legacy interface. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200518170321.321697-1-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/mtk_nand.c | 116 +++++++++++++++++++------------- 1 file changed, 71 insertions(+), 45 deletions(-) diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index c1a6e31aabb88..ca8457626d534 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -387,44 +387,6 @@ static int mtk_nfc_hw_runtime_config(struct mtd_info *mtd) return 0; } -static void mtk_nfc_select_chip(struct nand_chip *nand, int chip) -{ - struct mtk_nfc *nfc = nand_get_controller_data(nand); - struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(nand); - - if (chip < 0) - return; - - mtk_nfc_hw_runtime_config(nand_to_mtd(nand)); - - nfi_writel(nfc, mtk_nand->sels[chip], NFI_CSEL); -} - -static int mtk_nfc_dev_ready(struct nand_chip *nand) -{ - struct mtk_nfc *nfc = nand_get_controller_data(nand); - - if (nfi_readl(nfc, NFI_STA) & STA_BUSY) - return 0; - - return 1; -} - -static void mtk_nfc_cmd_ctrl(struct nand_chip *chip, int dat, - unsigned int ctrl) -{ - struct mtk_nfc *nfc = nand_get_controller_data(chip); - - if (ctrl & NAND_ALE) { - mtk_nfc_send_address(nfc, dat); - } else if (ctrl & NAND_CLE) { - mtk_nfc_hw_reset(nfc); - - nfi_writew(nfc, CNFG_OP_CUST, NFI_CNFG); - mtk_nfc_send_command(nfc, dat); - } -} - static inline void mtk_nfc_wait_ioready(struct mtk_nfc *nfc) { int rc; @@ -501,6 +463,74 @@ static void mtk_nfc_write_buf(struct nand_chip *chip, const u8 *buf, int len) mtk_nfc_write_byte(chip, buf[i]); } +static int mtk_nfc_exec_instr(struct nand_chip *chip, + const struct nand_op_instr *instr) +{ + struct mtk_nfc *nfc = nand_get_controller_data(chip); + unsigned int i; + u32 status; + + switch (instr->type) { + case NAND_OP_CMD_INSTR: + mtk_nfc_send_command(nfc, instr->ctx.cmd.opcode); + return 0; + case NAND_OP_ADDR_INSTR: + for (i = 0; i < instr->ctx.addr.naddrs; i++) + mtk_nfc_send_address(nfc, instr->ctx.addr.addrs[i]); + return 0; + case NAND_OP_DATA_IN_INSTR: + mtk_nfc_read_buf(chip, instr->ctx.data.buf.in, + instr->ctx.data.len); + return 0; + case NAND_OP_DATA_OUT_INSTR: + mtk_nfc_write_buf(chip, instr->ctx.data.buf.out, + instr->ctx.data.len); + return 0; + case NAND_OP_WAITRDY_INSTR: + return readl_poll_timeout(nfc->regs + NFI_STA, status, + status & STA_BUSY, 20, + instr->ctx.waitrdy.timeout_ms); + default: + break; + } + + return -EINVAL; +} + +static void mtk_nfc_select_target(struct nand_chip *nand, unsigned int cs) +{ + struct mtk_nfc *nfc = nand_get_controller_data(nand); + struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(nand); + + mtk_nfc_hw_runtime_config(nand_to_mtd(nand)); + + nfi_writel(nfc, mtk_nand->sels[cs], NFI_CSEL); +} + +static int mtk_nfc_exec_op(struct nand_chip *chip, + const struct nand_operation *op, + bool check_only) +{ + struct mtk_nfc *nfc = nand_get_controller_data(chip); + unsigned int i; + int ret = 0; + + if (check_only) + return 0; + + mtk_nfc_hw_reset(nfc); + nfi_writew(nfc, CNFG_OP_CUST, NFI_CNFG); + mtk_nfc_select_target(chip, op->cs); + + for (i = 0; i < op->ninstrs; i++) { + ret = mtk_nfc_exec_instr(chip, &op->instrs[i]); + if (ret) + break; + } + + return ret; +} + static int mtk_nfc_setup_data_interface(struct nand_chip *chip, int csline, const struct nand_data_interface *conf) { @@ -803,6 +833,7 @@ static int mtk_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip, u32 reg; int ret; + mtk_nfc_select_target(chip, chip->cur_cs); nand_prog_page_begin_op(chip, page, 0, NULL, 0); if (!raw) { @@ -920,6 +951,7 @@ static int mtk_nfc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, u8 *buf; int rc; + mtk_nfc_select_target(chip, chip->cur_cs); start = data_offs / chip->ecc.size; end = DIV_ROUND_UP(data_offs + readlen, chip->ecc.size); @@ -1326,6 +1358,7 @@ static int mtk_nfc_attach_chip(struct nand_chip *chip) static const struct nand_controller_ops mtk_nfc_controller_ops = { .attach_chip = mtk_nfc_attach_chip, .setup_data_interface = mtk_nfc_setup_data_interface, + .exec_op = mtk_nfc_exec_op, }; static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc, @@ -1381,13 +1414,6 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc, nand_set_controller_data(nand, nfc); nand->options |= NAND_USES_DMA | NAND_SUBPAGE_READ; - nand->legacy.dev_ready = mtk_nfc_dev_ready; - nand->legacy.select_chip = mtk_nfc_select_chip; - nand->legacy.write_byte = mtk_nfc_write_byte; - nand->legacy.write_buf = mtk_nfc_write_buf; - nand->legacy.read_byte = mtk_nfc_read_byte; - nand->legacy.read_buf = mtk_nfc_read_buf; - nand->legacy.cmd_ctrl = mtk_nfc_cmd_ctrl; /* set default mode in case dt entry is missing */ nand->ecc.mode = NAND_ECC_HW; -- GitLab From bf4237a188f872e535de8cbfc7903c1387b83b01 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 29 Jan 2020 17:38:19 +0100 Subject: [PATCH 0003/1754] clk: rockchip: convert rk3399 pll type to use readl_relaxed_poll_timeout Instead of open coding the polling of the lock status, use the handy readl_relaxed_poll_timeout for this. As the pll locking is normally blazingly fast and we don't want to incur additional delays, we're not doing any sleeps similar to for example the imx clk-pllv4 and define a very safe but still short timeout of 1ms. Suggested-by: Stephen Boyd Signed-off-by: Heiko Stuebner Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20200129163821.1547295-1-heiko@sntech.de --- drivers/clk/rockchip/clk-pll.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 10560d963baf6..28b04aad31ad7 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -589,19 +589,20 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = { static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll) { u32 pllcon; - int delay = 24000000; + int ret; - /* poll check the lock status in rk3399 xPLLCON2 */ - while (delay > 0) { - pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2)); - if (pllcon & RK3399_PLLCON2_LOCK_STATUS) - return 0; + /* + * Lock time typical 250, max 500 input clock cycles @24MHz + * So define a very safe maximum of 1000us, meaning 24000 cycles. + */ + ret = readl_relaxed_poll_timeout(pll->reg_base + RK3399_PLLCON(2), + pllcon, + pllcon & RK3399_PLLCON2_LOCK_STATUS, + 0, 1000); + if (ret) + pr_err("%s: timeout waiting for pll to lock\n", __func__); - delay--; - } - - pr_err("%s: timeout waiting for pll to lock\n", __func__); - return -ETIMEDOUT; + return ret; } static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll, -- GitLab From 3507df1a4615113ae6509e0f14f6546f0d1c84b4 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 29 Jan 2020 17:38:20 +0100 Subject: [PATCH 0004/1754] clk: rockchip: convert basic pll lock_wait to use regmap_read_poll_timeout Instead of open coding the polling of the lock status, use the handy regmap_read_poll_timeout for this. As the pll locking is normally blazingly fast and we don't want to incur additional delays, we're not doing any sleeps similar to for example the imx clk-pllv4 and define a very safe but still short timeout of 1ms. Suggested-by: Stephen Boyd Signed-off-by: Heiko Stuebner Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20200129163821.1547295-2-heiko@sntech.de --- drivers/clk/rockchip/clk-pll.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 28b04aad31ad7..945f8b2cacc1d 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -86,23 +86,14 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) { struct regmap *grf = pll->ctx->grf; unsigned int val; - int delay = 24000000, ret; - - while (delay > 0) { - ret = regmap_read(grf, pll->lock_offset, &val); - if (ret) { - pr_err("%s: failed to read pll lock status: %d\n", - __func__, ret); - return ret; - } + int ret; - if (val & BIT(pll->lock_shift)) - return 0; - delay--; - } + ret = regmap_read_poll_timeout(grf, pll->lock_offset, val, + val & BIT(pll->lock_shift), 0, 1000); + if (ret) + pr_err("%s: timeout waiting for pll to lock\n", __func__); - pr_err("%s: timeout waiting for pll to lock\n", __func__); - return -ETIMEDOUT; + return ret; } /** -- GitLab From 7f6ffbb885d147557bdca471c37b7b1204005798 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 29 Jan 2020 17:38:21 +0100 Subject: [PATCH 0005/1754] clk: rockchip: convert rk3036 pll type to use internal lock status The rk3036 pll type exposes its lock status in both its pllcon registers as well as the General Register Files. To remove one dependency convert it to the "internal" lock status, similar to how rk3399 handles it. Signed-off-by: Heiko Stuebner Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20200129163821.1547295-3-heiko@sntech.de --- drivers/clk/rockchip/clk-pll.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 945f8b2cacc1d..4c6c9167ef509 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include "clk.h" @@ -109,12 +110,31 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) #define RK3036_PLLCON1_REFDIV_SHIFT 0 #define RK3036_PLLCON1_POSTDIV2_MASK 0x7 #define RK3036_PLLCON1_POSTDIV2_SHIFT 6 +#define RK3036_PLLCON1_LOCK_STATUS BIT(10) #define RK3036_PLLCON1_DSMPD_MASK 0x1 #define RK3036_PLLCON1_DSMPD_SHIFT 12 +#define RK3036_PLLCON1_PWRDOWN BIT(13) #define RK3036_PLLCON2_FRAC_MASK 0xffffff #define RK3036_PLLCON2_FRAC_SHIFT 0 -#define RK3036_PLLCON1_PWRDOWN (1 << 13) +static int rockchip_rk3036_pll_wait_lock(struct rockchip_clk_pll *pll) +{ + u32 pllcon; + int ret; + + /* + * Lock time typical 250, max 500 input clock cycles @24MHz + * So define a very safe maximum of 1000us, meaning 24000 cycles. + */ + ret = readl_relaxed_poll_timeout(pll->reg_base + RK3036_PLLCON(1), + pllcon, + pllcon & RK3036_PLLCON1_LOCK_STATUS, + 0, 1000); + if (ret) + pr_err("%s: timeout waiting for pll to lock\n", __func__); + + return ret; +} static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll, struct rockchip_pll_rate_table *rate) @@ -212,7 +232,7 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2)); /* wait for the pll to lock */ - ret = rockchip_pll_wait_lock(pll); + ret = rockchip_rk3036_pll_wait_lock(pll); if (ret) { pr_warn("%s: pll update unsuccessful, trying to restore old params\n", __func__); @@ -251,7 +271,7 @@ static int rockchip_rk3036_pll_enable(struct clk_hw *hw) writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0), pll->reg_base + RK3036_PLLCON(1)); - rockchip_pll_wait_lock(pll); + rockchip_rk3036_pll_wait_lock(pll); return 0; } -- GitLab From a9b9b2af40c717adbc4981acd29c53b92be3a99a Mon Sep 17 00:00:00 2001 From: Wang Qing Date: Mon, 15 Jun 2020 16:54:02 +0800 Subject: [PATCH 0006/1754] backlight: lm3533_bl: Use kobj_to_dev() instead Use kobj_to_dev() instead of container_of() Signed-off-by: Wang Qing Reviewed-by: Daniel Thompson Signed-off-by: Lee Jones --- drivers/video/backlight/lm3533_bl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c index ee09d1bd02b97..0c7830f793def 100644 --- a/drivers/video/backlight/lm3533_bl.c +++ b/drivers/video/backlight/lm3533_bl.c @@ -235,7 +235,7 @@ static struct attribute *lm3533_bl_attributes[] = { static umode_t lm3533_bl_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct lm3533_bl *bl = dev_get_drvdata(dev); umode_t mode = attr->mode; -- GitLab From bcad94d7b7c13b123ed4ded86544667cfbfb1aa7 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sun, 7 Jun 2020 19:42:43 +0200 Subject: [PATCH 0007/1754] pinctrl: ingenic: Add NAND FRE/FWE pins for JZ4740 Add the FRE/FWE pins for the JZ4740. These pins must be in function #0 for the NAND to work. The reason it worked before was because the bootloader did set these pins to the correct function beforehand. Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20200607174243.2361664-1-paul@crapouillou.net Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-ingenic.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c index 6a8d44504f940..1da72438d6802 100644 --- a/drivers/pinctrl/pinctrl-ingenic.c +++ b/drivers/pinctrl/pinctrl-ingenic.c @@ -124,6 +124,7 @@ static int jz4740_nand_cs1_pins[] = { 0x39, }; static int jz4740_nand_cs2_pins[] = { 0x3a, }; static int jz4740_nand_cs3_pins[] = { 0x3b, }; static int jz4740_nand_cs4_pins[] = { 0x3c, }; +static int jz4740_nand_fre_fwe_pins[] = { 0x5c, 0x5d, }; static int jz4740_pwm_pwm0_pins[] = { 0x77, }; static int jz4740_pwm_pwm1_pins[] = { 0x78, }; static int jz4740_pwm_pwm2_pins[] = { 0x79, }; @@ -146,6 +147,7 @@ static int jz4740_nand_cs1_funcs[] = { 0, }; static int jz4740_nand_cs2_funcs[] = { 0, }; static int jz4740_nand_cs3_funcs[] = { 0, }; static int jz4740_nand_cs4_funcs[] = { 0, }; +static int jz4740_nand_fre_fwe_funcs[] = { 0, 0, }; static int jz4740_pwm_pwm0_funcs[] = { 0, }; static int jz4740_pwm_pwm1_funcs[] = { 0, }; static int jz4740_pwm_pwm2_funcs[] = { 0, }; @@ -178,6 +180,7 @@ static const struct group_desc jz4740_groups[] = { INGENIC_PIN_GROUP("nand-cs2", jz4740_nand_cs2), INGENIC_PIN_GROUP("nand-cs3", jz4740_nand_cs3), INGENIC_PIN_GROUP("nand-cs4", jz4740_nand_cs4), + INGENIC_PIN_GROUP("nand-fre-fwe", jz4740_nand_fre_fwe), INGENIC_PIN_GROUP("pwm0", jz4740_pwm_pwm0), INGENIC_PIN_GROUP("pwm1", jz4740_pwm_pwm1), INGENIC_PIN_GROUP("pwm2", jz4740_pwm_pwm2), @@ -195,7 +198,7 @@ static const char *jz4740_lcd_groups[] = { "lcd-8bit", "lcd-16bit", "lcd-18bit", "lcd-18bit-tft", "lcd-no-pins", }; static const char *jz4740_nand_groups[] = { - "nand-cs1", "nand-cs2", "nand-cs3", "nand-cs4", + "nand-cs1", "nand-cs2", "nand-cs3", "nand-cs4", "nand-fre-fwe", }; static const char *jz4740_pwm0_groups[] = { "pwm0", }; static const char *jz4740_pwm1_groups[] = { "pwm1", }; -- GitLab From f46fe79ff1b65692a65266a5bec6dbe2bf7fc70f Mon Sep 17 00:00:00 2001 From: Drew Fustini Date: Mon, 8 Jun 2020 14:51:43 +0200 Subject: [PATCH 0008/1754] pinctrl-single: fix pcs_parse_pinconf() return value This patch causes pcs_parse_pinconf() to return -ENOTSUPP when no pinctrl_map is added. The current behavior is to return 0 when !PCS_HAS_PINCONF or !nconfs. Thus pcs_parse_one_pinctrl_entry() incorrectly assumes that a map was added and sets num_maps = 2. Analysis: ========= The function pcs_parse_one_pinctrl_entry() calls pcs_parse_pinconf() if PCS_HAS_PINCONF is enabled. The function pcs_parse_pinconf() returns 0 to indicate there was no error and num_maps is then set to 2: 980 static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, 981 struct device_node *np, 982 struct pinctrl_map **map, 983 unsigned *num_maps, 984 const char **pgnames) 985 { 1053 (*map)->type = PIN_MAP_TYPE_MUX_GROUP; 1054 (*map)->data.mux.group = np->name; 1055 (*map)->data.mux.function = np->name; 1056 1057 if (PCS_HAS_PINCONF && function) { 1058 res = pcs_parse_pinconf(pcs, np, function, map); 1059 if (res) 1060 goto free_pingroups; 1061 *num_maps = 2; 1062 } else { 1063 *num_maps = 1; 1064 } However, pcs_parse_pinconf() will also return 0 if !PCS_HAS_PINCONF or !nconfs. I believe these conditions should indicate that no map was added by returning -ENOTSUPP. Otherwise pcs_parse_one_pinctrl_entry() will set num_maps = 2 even though no maps were successfully added, as it does not reach "m++" on line 940: 895 static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np, 896 struct pcs_function *func, 897 struct pinctrl_map **map) 898 899 { 900 struct pinctrl_map *m = *map; 917 /* If pinconf isn't supported, don't parse properties in below. */ 918 if (!PCS_HAS_PINCONF) 919 return 0; 920 921 /* cacluate how much properties are supported in current node */ 922 for (i = 0; i < ARRAY_SIZE(prop2); i++) { 923 if (of_find_property(np, prop2[i].name, NULL)) 924 nconfs++; 925 } 926 for (i = 0; i < ARRAY_SIZE(prop4); i++) { 927 if (of_find_property(np, prop4[i].name, NULL)) 928 nconfs++; 929 } 930 if (!nconfs) 919 return 0; 932 933 func->conf = devm_kcalloc(pcs->dev, 934 nconfs, sizeof(struct pcs_conf_vals), 935 GFP_KERNEL); 936 if (!func->conf) 937 return -ENOMEM; 938 func->nconfs = nconfs; 939 conf = &(func->conf[0]); 940 m++; This situtation will cause a boot failure [0] on the BeagleBone Black (AM3358) when am33xx_pinmux node in arch/arm/boot/dts/am33xx-l4.dtsi has compatible = "pinconf-single" instead of "pinctrl-single". The patch fixes this issue by returning -ENOSUPP when !PCS_HAS_PINCONF or !nconfs, so that pcs_parse_one_pinctrl_entry() will know that no map was added. Logic is also added to pcs_parse_one_pinctrl_entry() to distinguish between -ENOSUPP and other errors. In the case of -ENOSUPP, num_maps is set to 1 as it is valid for pinconf to be enabled and a given pin group to not any pinconf properties. [0] https://lore.kernel.org/linux-omap/20200529175544.GA3766151@x1/ Fixes: 9dddb4df90d1 ("pinctrl: single: support generic pinconf") Signed-off-by: Drew Fustini Acked-by: Tony Lindgren Link: https://lore.kernel.org/r/20200608125143.GA2789203@x1 Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-single.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 1e0614daee9bf..a9d511982780c 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -916,7 +916,7 @@ static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np, /* If pinconf isn't supported, don't parse properties in below. */ if (!PCS_HAS_PINCONF) - return 0; + return -ENOTSUPP; /* cacluate how much properties are supported in current node */ for (i = 0; i < ARRAY_SIZE(prop2); i++) { @@ -928,7 +928,7 @@ static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np, nconfs++; } if (!nconfs) - return 0; + return -ENOTSUPP; func->conf = devm_kcalloc(pcs->dev, nconfs, sizeof(struct pcs_conf_vals), @@ -1056,9 +1056,12 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, if (PCS_HAS_PINCONF && function) { res = pcs_parse_pinconf(pcs, np, function, map); - if (res) + if (res == 0) + *num_maps = 2; + else if (res == -ENOTSUPP) + *num_maps = 1; + else goto free_pingroups; - *num_maps = 2; } else { *num_maps = 1; } -- GitLab From 899c537c25f9547a0f591ed2013be0f9f68f2df3 Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:05 -0700 Subject: [PATCH 0009/1754] drm/i915: Use 64-bit division macro Since the PWM framework is switching struct pwm_state.duty_cycle's datatype to u64, prepare for this transition by using DIV_ROUND_UP_ULL to handle a 64-bit dividend. Signed-off-by: Guru Das Srinagesh Reviewed-by: Jani Nikula Acked-by: Jani Nikula Signed-off-by: Thierry Reding --- drivers/gpu/drm/i915/display/intel_panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 3c5056dbf6079..31cb285e8b38a 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -1929,7 +1929,7 @@ static int pwm_setup_backlight(struct intel_connector *connector, return retval; } - level = DIV_ROUND_UP(pwm_get_duty_cycle(panel->backlight.pwm) * 100, + level = DIV_ROUND_UP_ULL(pwm_get_duty_cycle(panel->backlight.pwm) * 100, CRC_PMIC_PWM_PERIOD_NS); panel->backlight.level = intel_panel_compute_brightness(connector, level); -- GitLab From f3e4b14144a928c097e2d526f6dcd6ba0f5eba8a Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:06 -0700 Subject: [PATCH 0010/1754] hwmon: pwm-fan: Use 64-bit division macro Since the PWM framework is switching struct pwm_args.period's datatype to u64, prepare for this transition by using DIV_ROUND_UP_ULL to handle a 64-bit dividend. Signed-off-by: Guru Das Srinagesh Acked-by: Guenter Roeck Signed-off-by: Thierry Reding --- drivers/hwmon/pwm-fan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c index 30b7b3ea8836f..17bb64299bfd8 100644 --- a/drivers/hwmon/pwm-fan.c +++ b/drivers/hwmon/pwm-fan.c @@ -447,7 +447,7 @@ static int pwm_fan_resume(struct device *dev) return 0; pwm_get_args(ctx->pwm, &pargs); - duty = DIV_ROUND_UP(ctx->pwm_value * (pargs.period - 1), MAX_PWM); + duty = DIV_ROUND_UP_ULL(ctx->pwm_value * (pargs.period - 1), MAX_PWM); ret = pwm_config(ctx->pwm, duty, pargs.period); if (ret) return ret; -- GitLab From 5bd0b9011da836dad1a00d92ebead7eaa87f5fe3 Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:08 -0700 Subject: [PATCH 0011/1754] pwm: clps711x: Use 64-bit division macro Since the PWM framework is switching struct pwm_args.period's datatype to u64, prepare for this transition by using DIV64_U64_ROUND_CLOSEST to handle a 64-bit divisor. Cc: Daniel Thompson Signed-off-by: Guru Das Srinagesh Signed-off-by: Thierry Reding --- drivers/pwm/pwm-clps711x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c index 924d39a797cf7..ba9500aca078a 100644 --- a/drivers/pwm/pwm-clps711x.c +++ b/drivers/pwm/pwm-clps711x.c @@ -43,7 +43,7 @@ static void clps711x_pwm_update_val(struct clps711x_chip *priv, u32 n, u32 v) static unsigned int clps711x_get_duty(struct pwm_device *pwm, unsigned int v) { /* Duty cycle 0..15 max */ - return DIV_ROUND_CLOSEST(v * 0xf, pwm->args.period); + return DIV64_U64_ROUND_CLOSEST(v * 0xf, pwm->args.period); } static int clps711x_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) -- GitLab From fcdea6b2a3f6508618e39e061073a18c55993a1b Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:09 -0700 Subject: [PATCH 0012/1754] pwm: imx-tpm: Use 64-bit division macro Since the PWM framework is switching struct pwm_state.period's datatype to u64, prepare for this transition by using DIV64_U64_ROUND_CLOSEST to handle a 64-bit divisor. Cc: Shawn Guo Cc: Sascha Hauer Cc: Pengutronix Kernel Team Cc: Fabio Estevam Cc: NXP Linux Team Signed-off-by: Guru Das Srinagesh Signed-off-by: Thierry Reding --- drivers/pwm/pwm-imx-tpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-imx-tpm.c b/drivers/pwm/pwm-imx-tpm.c index 5f3d7f7e6aef0..fcdf6befb8389 100644 --- a/drivers/pwm/pwm-imx-tpm.c +++ b/drivers/pwm/pwm-imx-tpm.c @@ -124,7 +124,7 @@ static int pwm_imx_tpm_round_state(struct pwm_chip *chip, real_state->duty_cycle = state->duty_cycle; tmp = (u64)p->mod * real_state->duty_cycle; - p->val = DIV_ROUND_CLOSEST_ULL(tmp, real_state->period); + p->val = DIV64_U64_ROUND_CLOSEST(tmp, real_state->period); real_state->polarity = state->polarity; real_state->enabled = state->enabled; -- GitLab From 1689dcd433aaa0d32dec3fdb4bd166a0d38f4bbf Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:11 -0700 Subject: [PATCH 0013/1754] pwm: imx27: Use 64-bit division macro Since the PWM framework is switching struct pwm_state.period's datatype to u64, prepare for this transition by using DIV_ROUND_UP_ULL to handle a 64-bit dividend. Signed-off-by: Guru Das Srinagesh Signed-off-by: Thierry Reding --- drivers/pwm/pwm-imx27.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c index 732a6f3701e8e..c50d453552bd4 100644 --- a/drivers/pwm/pwm-imx27.c +++ b/drivers/pwm/pwm-imx27.c @@ -202,7 +202,7 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip, sr = readl(imx->mmio_base + MX3_PWMSR); fifoav = FIELD_GET(MX3_PWMSR_FIFOAV, sr); if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) { - period_ms = DIV_ROUND_UP(pwm_get_period(pwm), + period_ms = DIV_ROUND_UP_ULL(pwm_get_period(pwm), NSEC_PER_MSEC); msleep(period_ms); -- GitLab From d3132792285859253c466354fd8d54d1fe0ba786 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 9 Jun 2020 21:38:24 -0700 Subject: [PATCH 0014/1754] HID: usbhid: do not sleep when opening device usbhid tries to give the device 50 milliseconds to drain its queues when opening the device, but does it naively by simply sleeping in open handler, which slows down device probing (and thus may affect overall boot time). However we do not need to sleep as we can instead mark a point of time in the future when we should start processing the events. Reported-by: Nicolas Boichat Signed-off-by: Dmitry Torokhov Reviewed-by: Guenter Roeck Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 53 +++++++++++++++++++---------------- drivers/hid/usbhid/usbhid.h | 2 ++ 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 17a638f150824..1235288b65bfd 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -95,6 +96,18 @@ static int hid_start_in(struct hid_device *hid) set_bit(HID_NO_BANDWIDTH, &usbhid->iofl); } else { clear_bit(HID_NO_BANDWIDTH, &usbhid->iofl); + + if (test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) { + /* + * In case events are generated while nobody was + * listening, some are released when the device + * is re-opened. Wait 50 msec for the queue to + * empty before allowing events to go through + * hid. + */ + usbhid->input_start_time = + ktime_add_ms(ktime_get_coarse(), 50); + } } } spin_unlock_irqrestore(&usbhid->lock, flags); @@ -280,20 +293,23 @@ static void hid_irq_in(struct urb *urb) if (!test_bit(HID_OPENED, &usbhid->iofl)) break; usbhid_mark_busy(usbhid); - if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) { - hid_input_report(urb->context, HID_INPUT_REPORT, - urb->transfer_buffer, - urb->actual_length, 1); - /* - * autosuspend refused while keys are pressed - * because most keyboards don't wake up when - * a key is released - */ - if (hid_check_keys_pressed(hid)) - set_bit(HID_KEYS_PRESSED, &usbhid->iofl); - else - clear_bit(HID_KEYS_PRESSED, &usbhid->iofl); + if (test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) { + if (ktime_before(ktime_get_coarse(), + usbhid->input_start_time)) + break; + clear_bit(HID_RESUME_RUNNING, &usbhid->iofl); } + hid_input_report(urb->context, HID_INPUT_REPORT, + urb->transfer_buffer, urb->actual_length, 1); + /* + * autosuspend refused while keys are pressed + * because most keyboards don't wake up when + * a key is released + */ + if (hid_check_keys_pressed(hid)) + set_bit(HID_KEYS_PRESSED, &usbhid->iofl); + else + clear_bit(HID_KEYS_PRESSED, &usbhid->iofl); break; case -EPIPE: /* stall */ usbhid_mark_busy(usbhid); @@ -720,17 +736,6 @@ static int usbhid_open(struct hid_device *hid) usb_autopm_put_interface(usbhid->intf); - /* - * In case events are generated while nobody was listening, - * some are released when the device is re-opened. - * Wait 50 msec for the queue to empty before allowing events - * to go through hid. - */ - if (res == 0) - msleep(50); - - clear_bit(HID_RESUME_RUNNING, &usbhid->iofl); - Done: mutex_unlock(&usbhid->mutex); return res; diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 75fe85d3d27a0..c6ad684d099a1 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -83,6 +84,7 @@ struct usbhid_device { struct mutex mutex; /* start/stop/open/close */ spinlock_t lock; /* fifo spinlock */ unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ + ktime_t input_start_time; /* When to start handling input */ struct timer_list io_retry; /* Retry timer */ unsigned long stop_retry; /* Time to give up, in jiffies */ unsigned int retry_delay; /* Delay length in ms */ -- GitLab From 8e9ddbde9ddbba74c86b0c5f8eefb26192b3242e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 10 Jun 2020 13:31:01 +0100 Subject: [PATCH 0015/1754] HID: usbhid: remove redundant assignment to variable retval The variable retval is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 1235288b65bfd..492dd641a25df 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1672,7 +1672,7 @@ struct usb_interface *usbhid_find_interface(int minor) static int __init hid_init(void) { - int retval = -ENOMEM; + int retval; retval = hid_quirks_init(quirks_param, BUS_USB, MAX_USBHID_BOOT_QUIRKS); if (retval) -- GitLab From 1ad273d6ff2d3af6ce3a4c8bd81a2ba10151ae0e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 9 Jun 2020 16:03:19 +1000 Subject: [PATCH 0016/1754] HID: input: do not run GET_REPORT unless there's a Resolution Multiplier hid-multitouch currently runs GET_REPORT for Contact Max and again to retrieve the Win8 blob. If both are within the same report, the Resolution Multiplier code calls GET_FEATURE again and this time, possibly due to timing, it causes the ILITEK-TP device interpret the GET_FEATURE as an instruction to change the mode and effectively stop the device from functioning as expected. Notably: the device doesn't even have a Resolution Multiplier so it shouldn't be affected by any of this at all. Fix this by making sure we only execute GET_REPORT if there is a Resolution Multiplier in the respective report. Where the HID_QUIRK_NO_INIT_REPORTS field is set we just bail out immediately. This shouldn't be triggered by any real device anyway. Signed-off-by: Peter Hutterer Tested-by: Wen He Signed-off-by: Jiri Kosina --- drivers/hid/hid-input.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index dea9cc65bf800..c8633beae260a 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -1560,21 +1560,12 @@ static bool __hidinput_change_resolution_multipliers(struct hid_device *hid, { struct hid_usage *usage; bool update_needed = false; + bool get_report_completed = false; int i, j; if (report->maxfield == 0) return false; - /* - * If we have more than one feature within this report we - * need to fill in the bits from the others before we can - * overwrite the ones for the Resolution Multiplier. - */ - if (report->maxfield > 1) { - hid_hw_request(hid, report, HID_REQ_GET_REPORT); - hid_hw_wait(hid); - } - for (i = 0; i < report->maxfield; i++) { __s32 value = use_logical_max ? report->field[i]->logical_maximum : @@ -1593,6 +1584,25 @@ static bool __hidinput_change_resolution_multipliers(struct hid_device *hid, if (usage->hid != HID_GD_RESOLUTION_MULTIPLIER) continue; + /* + * If we have more than one feature within this + * report we need to fill in the bits from the + * others before we can overwrite the ones for the + * Resolution Multiplier. + * + * But if we're not allowed to read from the device, + * we just bail. Such a device should not exist + * anyway. + */ + if (!get_report_completed && report->maxfield > 1) { + if (hid->quirks & HID_QUIRK_NO_INIT_REPORTS) + return update_needed; + + hid_hw_request(hid, report, HID_REQ_GET_REPORT); + hid_hw_wait(hid); + get_report_completed = true; + } + report->field[i]->value[j] = value; update_needed = true; } -- GitLab From 1627f683636df70fb25358b0a7b39a24e8fce5bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Myl=C3=A8ne=20Josserand?= Date: Tue, 2 Jun 2020 10:06:43 +0200 Subject: [PATCH 0017/1754] clk: rockchip: Handle clock tree for rk3288w variant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The revision rk3288w has a different clock tree about "hclk_vio" clock, according to the BSP kernel code. This patch handles this difference by detecting which device-tree we are using. If it is a "rockchip,rk3288-cru", let's register the clock tree as it was before. If the device-tree node is "rockchip,rk3288w-cru", we will apply the difference with this version of this SoC. Noticed that this new device-tree compatible must be handled in bootloader such as u-boot. Signed-off-by: Mylène Josserand Link: https://lore.kernel.org/r/20200602080644.11333-2-mylene.josserand@collabora.com Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3288.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index cc2a177bbdbf4..204976e2d0cb8 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -425,8 +425,6 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3288_CLKGATE_CON(3), 0, GFLAGS), - DIV(0, "hclk_vio", "aclk_vio0", 0, - RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), COMPOSITE(0, "aclk_vio1", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, RK3288_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS, RK3288_CLKGATE_CON(3), 2, GFLAGS), @@ -819,6 +817,16 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS), }; +static struct rockchip_clk_branch rk3288w_hclkvio_branch[] __initdata = { + DIV(0, "hclk_vio", "aclk_vio1", 0, + RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), +}; + +static struct rockchip_clk_branch rk3288_hclkvio_branch[] __initdata = { + DIV(0, "hclk_vio", "aclk_vio0", 0, + RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), +}; + static const char *const rk3288_critical_clocks[] __initconst = { "aclk_cpu", "aclk_peri", @@ -936,6 +944,14 @@ static void __init rk3288_clk_init(struct device_node *np) RK3288_GRF_SOC_STATUS1); rockchip_clk_register_branches(ctx, rk3288_clk_branches, ARRAY_SIZE(rk3288_clk_branches)); + + if (of_device_is_compatible(np, "rockchip,rk3288w-cru")) + rockchip_clk_register_branches(ctx, rk3288w_hclkvio_branch, + ARRAY_SIZE(rk3288w_hclkvio_branch)); + else + rockchip_clk_register_branches(ctx, rk3288_hclkvio_branch, + ARRAY_SIZE(rk3288_hclkvio_branch)); + rockchip_clk_protect_critical(rk3288_critical_clocks, ARRAY_SIZE(rk3288_critical_clocks)); -- GitLab From 00bd404144241155653bb0d0c15be51e4e6983aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Myl=C3=A8ne=20Josserand?= Date: Tue, 2 Jun 2020 10:06:44 +0200 Subject: [PATCH 0018/1754] dt-bindings: clocks: add rk3288w variant compatible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the possible compatible "rockchip,rk3288w-cru" that handles the difference between the rk3288 and the new revision rk3288w. This compatible will be added by bootloaders. Signed-off-by: Mylène Josserand Acked-by: Rob Herring Link: https://lore.kernel.org/r/20200602080644.11333-3-mylene.josserand@collabora.com Signed-off-by: Heiko Stuebner --- .../devicetree/bindings/clock/rockchip,rk3288-cru.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt index 8cb47c39ba539..bf3a9ec192416 100644 --- a/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt @@ -4,9 +4,15 @@ The RK3288 clock controller generates and supplies clock to various controllers within the SoC and also implements a reset controller for SoC peripherals. +A revision of this SoC is available: rk3288w. The clock tree is a bit +different so another dt-compatible is available. Noticed that it is only +setting the difference but there is no automatic revision detection. This +should be performed by bootloaders. + Required Properties: -- compatible: should be "rockchip,rk3288-cru" +- compatible: should be "rockchip,rk3288-cru" or "rockchip,rk3288w-cru" in + case of this revision of Rockchip rk3288. - reg: physical base address of the controller and length of memory mapped region. - #clock-cells: should be 1. -- GitLab From 5bc5d99f1f836858820ad8e9a412bb103bb0d88b Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Jun 2020 16:08:28 +0200 Subject: [PATCH 0019/1754] pwm: iqs620a: Use 64-bit division MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PWM framework is going to change the PWM period and duty cycles to be 64-bit unsigned integers. To avoid build errors on platforms that do not natively support 64-bit division, use explicity 64-bit division. Acked-by: Uwe Kleine-König Acked-by: Lee Jones Signed-off-by: Thierry Reding --- drivers/pwm/pwm-iqs620a.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c index 674f0e238ba01..b2bb27eff6239 100644 --- a/drivers/pwm/pwm-iqs620a.c +++ b/drivers/pwm/pwm-iqs620a.c @@ -46,7 +46,8 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, { struct iqs620_pwm_private *iqs620_pwm; struct iqs62x_core *iqs62x; - int duty_scale, ret; + u64 duty_scale; + int ret; if (state->polarity != PWM_POLARITY_NORMAL) return -ENOTSUPP; @@ -69,7 +70,7 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, * For lower duty cycles (e.g. 0), the PWM output is simply disabled to * allow an external pull-down resistor to hold the GPIO3/LTX pin low. */ - duty_scale = state->duty_cycle * 256 / IQS620_PWM_PERIOD_NS; + duty_scale = div_u64(state->duty_cycle * 256, IQS620_PWM_PERIOD_NS); mutex_lock(&iqs620_pwm->lock); @@ -81,7 +82,7 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, } if (duty_scale) { - u8 duty_val = min(duty_scale - 1, 0xFF); + u8 duty_val = min_t(u64, duty_scale - 1, 0xff); ret = regmap_write(iqs62x->regmap, IQS620_PWM_DUTY_CYCLE, duty_val); -- GitLab From 4cc23430a5361f29999545de34fc05fa7d8e513b Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:12 -0700 Subject: [PATCH 0020/1754] pwm: sifive: Use 64-bit division macro Since the PWM framework is switching struct pwm_args.period's datatype to u64, prepare for this transition by using DIV64_U64_ROUND_CLOSEST to handle a 64-bit divisor. Signed-off-by: Guru Das Srinagesh Acked-by: Palmer Dabbelt Signed-off-by: Thierry Reding --- drivers/pwm/pwm-sifive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c index cc63f9baa4819..62de0bb859214 100644 --- a/drivers/pwm/pwm-sifive.c +++ b/drivers/pwm/pwm-sifive.c @@ -181,7 +181,7 @@ static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm, * consecutively */ num = (u64)duty_cycle * (1U << PWM_SIFIVE_CMPWIDTH); - frac = DIV_ROUND_CLOSEST_ULL(num, state->period); + frac = DIV64_U64_ROUND_CLOSEST(num, state->period); /* The hardware cannot generate a 100% duty cycle */ frac = min(frac, (1U << PWM_SIFIVE_CMPWIDTH) - 1); -- GitLab From c7dcccaec2f7e99f95ad4b7c20f4f9086c6982be Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:13 -0700 Subject: [PATCH 0021/1754] pwm: sun4i: Use nsecs_to_jiffies to avoid a division Since the PWM framework is switching struct pwm_state.period's datatype to u64, prepare for this transition by using nsecs_to_jiffies() which does away with the need for a division operation. Signed-off-by: Guru Das Srinagesh Acked-by: Chen-Yu Tsai Signed-off-by: Thierry Reding --- drivers/pwm/pwm-sun4i.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c index 18fbbe3277d0f..961c59c99bb3b 100644 --- a/drivers/pwm/pwm-sun4i.c +++ b/drivers/pwm/pwm-sun4i.c @@ -285,7 +285,7 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, val = (duty & PWM_DTY_MASK) | PWM_PRD(period); sun4i_pwm_writel(sun4i_pwm, val, PWM_CH_PRD(pwm->hwpwm)); sun4i_pwm->next_period[pwm->hwpwm] = jiffies + - usecs_to_jiffies(cstate.period / 1000 + 1); + nsecs_to_jiffies(cstate.period + 1000); if (state->polarity != PWM_POLARITY_NORMAL) ctrl &= ~BIT_CH(PWM_ACT_STATE, pwm->hwpwm); -- GitLab From 134ada17dbad272cdca57f2819a796c87e352274 Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:14 -0700 Subject: [PATCH 0022/1754] backlight: pwm_bl: Use 64-bit division function Since the PWM framework is switching struct pwm_state.period's datatype to u64, prepare for this transition by using div_u64 to handle a 64-bit dividend instead of a straight division operation. Signed-off-by: Guru Das Srinagesh Reviewed-by: Daniel Thompson Acked-by: Lee Jones Signed-off-by: Thierry Reding --- drivers/video/backlight/pwm_bl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index 82b8d7594701d..464baade8f527 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c @@ -606,7 +606,8 @@ static int pwm_backlight_probe(struct platform_device *pdev) pb->scale = data->max_brightness; } - pb->lth_brightness = data->lth_brightness * (state.period / pb->scale); + pb->lth_brightness = data->lth_brightness * (div_u64(state.period, + pb->scale)); props.type = BACKLIGHT_RAW; props.max_brightness = data->max_brightness; -- GitLab From a6733474ba4bf3150120bacc1d2db446d89d3dbe Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:15 -0700 Subject: [PATCH 0023/1754] clk: pwm: Use 64-bit division function Since the PWM framework is switching struct pwm_args.period's datatype to u64, prepare for this transition by using div64_u64() to handle a 64-bit divisor. Also ensure that divide-by-zero (with fixed_rate as denominator) does not happen with an explicit check with probe failure as a consequence. Signed-off-by: Guru Das Srinagesh Acked-by: Stephen Boyd Signed-off-by: Thierry Reding --- drivers/clk/clk-pwm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-pwm.c b/drivers/clk/clk-pwm.c index 87fe0b0e01a3d..86f2e2d3fc022 100644 --- a/drivers/clk/clk-pwm.c +++ b/drivers/clk/clk-pwm.c @@ -89,7 +89,12 @@ static int clk_pwm_probe(struct platform_device *pdev) } if (of_property_read_u32(node, "clock-frequency", &clk_pwm->fixed_rate)) - clk_pwm->fixed_rate = NSEC_PER_SEC / pargs.period; + clk_pwm->fixed_rate = div64_u64(NSEC_PER_SEC, pargs.period); + + if (!clk_pwm->fixed_rate) { + dev_err(&pdev->dev, "fixed_rate cannot be zero\n"); + return -EINVAL; + } if (pargs.period != NSEC_PER_SEC / clk_pwm->fixed_rate && pargs.period != DIV_ROUND_UP(NSEC_PER_SEC, clk_pwm->fixed_rate)) { -- GitLab From a9d887dc1c60ed67f2271d66560cdcf864c4a578 Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:16 -0700 Subject: [PATCH 0024/1754] pwm: Convert period and duty cycle to u64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because period and duty cycle are defined as ints with units of nanoseconds, the maximum time duration that can be set is limited to ~2.147 seconds. Change their definitions to u64 in the structs of the PWM framework so that higher durations may be set. Also use the right format specifiers in debug prints in both core.c, pwm-stm32-lp.c as well as video/fbdev/ssd1307fb.c. Reported-by: kbuild test robot Signed-off-by: Guru Das Srinagesh Acked-by: Uwe Kleine-König Signed-off-by: Thierry Reding --- drivers/pwm/core.c | 14 +++++++------- drivers/pwm/pwm-stm32-lp.c | 2 +- drivers/pwm/sysfs.c | 8 ++++---- drivers/video/fbdev/ssd1307fb.c | 2 +- include/linux/pwm.h | 12 ++++++------ 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 004b2ea9b5fde..276e939a56846 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -510,12 +510,12 @@ static void pwm_apply_state_debug(struct pwm_device *pwm, last->period > s2.period && last->period <= state->period) dev_warn(chip->dev, - ".apply didn't pick the best available period (requested: %u, applied: %u, possible: %u)\n", + ".apply didn't pick the best available period (requested: %llu, applied: %llu, possible: %llu)\n", state->period, s2.period, last->period); if (state->enabled && state->period < s2.period) dev_warn(chip->dev, - ".apply is supposed to round down period (requested: %u, applied: %u)\n", + ".apply is supposed to round down period (requested: %llu, applied: %llu)\n", state->period, s2.period); if (state->enabled && @@ -524,14 +524,14 @@ static void pwm_apply_state_debug(struct pwm_device *pwm, last->duty_cycle > s2.duty_cycle && last->duty_cycle <= state->duty_cycle) dev_warn(chip->dev, - ".apply didn't pick the best available duty cycle (requested: %u/%u, applied: %u/%u, possible: %u/%u)\n", + ".apply didn't pick the best available duty cycle (requested: %llu/%llu, applied: %llu/%llu, possible: %llu/%llu)\n", state->duty_cycle, state->period, s2.duty_cycle, s2.period, last->duty_cycle, last->period); if (state->enabled && state->duty_cycle < s2.duty_cycle) dev_warn(chip->dev, - ".apply is supposed to round down duty_cycle (requested: %u/%u, applied: %u/%u)\n", + ".apply is supposed to round down duty_cycle (requested: %llu/%llu, applied: %llu/%llu)\n", state->duty_cycle, state->period, s2.duty_cycle, s2.period); @@ -558,7 +558,7 @@ static void pwm_apply_state_debug(struct pwm_device *pwm, (s1.enabled && s1.period != last->period) || (s1.enabled && s1.duty_cycle != last->duty_cycle)) { dev_err(chip->dev, - ".apply is not idempotent (ena=%d pol=%d %u/%u) -> (ena=%d pol=%d %u/%u)\n", + ".apply is not idempotent (ena=%d pol=%d %llu/%llu) -> (ena=%d pol=%d %llu/%llu)\n", s1.enabled, s1.polarity, s1.duty_cycle, s1.period, last->enabled, last->polarity, last->duty_cycle, last->period); @@ -1284,8 +1284,8 @@ static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) if (state.enabled) seq_puts(s, " enabled"); - seq_printf(s, " period: %u ns", state.period); - seq_printf(s, " duty: %u ns", state.duty_cycle); + seq_printf(s, " period: %llu ns", state.period); + seq_printf(s, " duty: %llu ns", state.duty_cycle); seq_printf(s, " polarity: %s", state.polarity ? "inverse" : "normal"); diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c index 67fca62524dc2..134c14621ee01 100644 --- a/drivers/pwm/pwm-stm32-lp.c +++ b/drivers/pwm/pwm-stm32-lp.c @@ -61,7 +61,7 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm, do_div(div, NSEC_PER_SEC); if (!div) { /* Clock is too slow to achieve requested period. */ - dev_dbg(priv->chip.dev, "Can't reach %u ns\n", state->period); + dev_dbg(priv->chip.dev, "Can't reach %llu ns\n", state->period); return -EINVAL; } diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 2389b86698468..449dbc0f49ede 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -42,7 +42,7 @@ static ssize_t period_show(struct device *child, pwm_get_state(pwm, &state); - return sprintf(buf, "%u\n", state.period); + return sprintf(buf, "%llu\n", state.period); } static ssize_t period_store(struct device *child, @@ -52,10 +52,10 @@ static ssize_t period_store(struct device *child, struct pwm_export *export = child_to_pwm_export(child); struct pwm_device *pwm = export->pwm; struct pwm_state state; - unsigned int val; + u64 val; int ret; - ret = kstrtouint(buf, 0, &val); + ret = kstrtou64(buf, 0, &val); if (ret) return ret; @@ -77,7 +77,7 @@ static ssize_t duty_cycle_show(struct device *child, pwm_get_state(pwm, &state); - return sprintf(buf, "%u\n", state.duty_cycle); + return sprintf(buf, "%llu\n", state.duty_cycle); } static ssize_t duty_cycle_store(struct device *child, diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c index 8e06ba912d60a..09425ec317ba2 100644 --- a/drivers/video/fbdev/ssd1307fb.c +++ b/drivers/video/fbdev/ssd1307fb.c @@ -312,7 +312,7 @@ static int ssd1307fb_init(struct ssd1307fb_par *par) /* Enable the PWM */ pwm_enable(par->pwm); - dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n", + dev_dbg(&par->client->dev, "Using PWM%d with a %lluns period.\n", par->pwm->pwm, pwm_get_period(par->pwm)); } diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 2635b2a55090d..a13ff383fa1d5 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -39,7 +39,7 @@ enum pwm_polarity { * current PWM hardware state. */ struct pwm_args { - unsigned int period; + u64 period; enum pwm_polarity polarity; }; @@ -56,8 +56,8 @@ enum { * @enabled: PWM enabled status */ struct pwm_state { - unsigned int period; - unsigned int duty_cycle; + u64 period; + u64 duty_cycle; enum pwm_polarity polarity; bool enabled; }; @@ -107,13 +107,13 @@ static inline bool pwm_is_enabled(const struct pwm_device *pwm) return state.enabled; } -static inline void pwm_set_period(struct pwm_device *pwm, unsigned int period) +static inline void pwm_set_period(struct pwm_device *pwm, u64 period) { if (pwm) pwm->state.period = period; } -static inline unsigned int pwm_get_period(const struct pwm_device *pwm) +static inline u64 pwm_get_period(const struct pwm_device *pwm) { struct pwm_state state; @@ -128,7 +128,7 @@ static inline void pwm_set_duty_cycle(struct pwm_device *pwm, unsigned int duty) pwm->state.duty_cycle = duty; } -static inline unsigned int pwm_get_duty_cycle(const struct pwm_device *pwm) +static inline u64 pwm_get_duty_cycle(const struct pwm_device *pwm) { struct pwm_state state; -- GitLab From b8fb642afa0277a0a9072fe119c1fce18437de0d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Jun 2020 16:10:16 +0200 Subject: [PATCH 0025/1754] pwm: iqs620a: Use lowercase hexadecimal literals for consistency Other drivers use lowercase hexadecimal literals, so convert the IQS620a driver to do the same for consistency. Signed-off-by: Thierry Reding --- drivers/pwm/pwm-iqs620a.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c index b2bb27eff6239..7d33e36464360 100644 --- a/drivers/pwm/pwm-iqs620a.c +++ b/drivers/pwm/pwm-iqs620a.c @@ -25,10 +25,10 @@ #include #include -#define IQS620_PWR_SETTINGS 0xD2 +#define IQS620_PWR_SETTINGS 0xd2 #define IQS620_PWR_SETTINGS_PWM_OUT BIT(7) -#define IQS620_PWM_DUTY_CYCLE 0xD8 +#define IQS620_PWM_DUTY_CYCLE 0xd8 #define IQS620_PWM_PERIOD_NS 1000000 @@ -94,7 +94,7 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (state->enabled && duty_scale) { ret = regmap_update_bits(iqs62x->regmap, IQS620_PWR_SETTINGS, - IQS620_PWR_SETTINGS_PWM_OUT, 0xFF); + IQS620_PWR_SETTINGS_PWM_OUT, 0xff); if (ret) goto err_mutex; } @@ -160,7 +160,7 @@ static int iqs620_pwm_notifier(struct notifier_block *notifier, ret = regmap_update_bits(iqs62x->regmap, IQS620_PWR_SETTINGS, IQS620_PWR_SETTINGS_PWM_OUT, - iqs620_pwm->out_en ? 0xFF : 0); + iqs620_pwm->out_en ? 0xff : 0); err_mutex: mutex_unlock(&iqs620_pwm->lock); -- GitLab From cb8ae6e188a2230a2515493918385dd054e14fa1 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 Jun 2020 14:54:34 +0200 Subject: [PATCH 0026/1754] dt-bindings: mfd: Document STM32 low power timer bindings Add a subnode to STM low power timer bindings to support timer driver Signed-off-by: Benjamin Gaignard Reviewed-by: Rob Herring Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml index e675611f80d03..8bcea8dd7d908 100644 --- a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml +++ b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml @@ -33,6 +33,9 @@ properties: items: - const: mux + interrupts: + maxItems: 1 + "#address-cells": const: 1 @@ -106,11 +109,13 @@ additionalProperties: false examples: - | #include + #include timer@40002400 { compatible = "st,stm32-lptimer"; reg = <0x40002400 0x400>; clocks = <&timer_clk>; clock-names = "mux"; + interrupts-extended = <&exti 47 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; -- GitLab From e0bcc58d876c6ece9720310509a908b7637e37cf Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 Jun 2020 14:54:36 +0200 Subject: [PATCH 0027/1754] mfd: stm32: Add defines to be used for clkevent purpose Add defines to be able to enable/clear irq and configure one shot mode. Signed-off-by: Benjamin Gaignard Signed-off-by: Lee Jones --- include/linux/mfd/stm32-lptimer.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/mfd/stm32-lptimer.h b/include/linux/mfd/stm32-lptimer.h index 605f622648258..90b20550c1c8b 100644 --- a/include/linux/mfd/stm32-lptimer.h +++ b/include/linux/mfd/stm32-lptimer.h @@ -27,10 +27,15 @@ #define STM32_LPTIM_CMPOK BIT(3) /* STM32_LPTIM_ICR - bit fields */ +#define STM32_LPTIM_ARRMCF BIT(1) #define STM32_LPTIM_CMPOKCF_ARROKCF GENMASK(4, 3) +/* STM32_LPTIM_IER - bit flieds */ +#define STM32_LPTIM_ARRMIE BIT(1) + /* STM32_LPTIM_CR - bit fields */ #define STM32_LPTIM_CNTSTRT BIT(2) +#define STM32_LPTIM_SNGSTRT BIT(1) #define STM32_LPTIM_ENABLE BIT(0) /* STM32_LPTIM_CFGR - bit fields */ -- GitLab From 45d93065c8ec4e671f4b1ff02b5b3a633658a92f Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 Jun 2020 14:54:37 +0200 Subject: [PATCH 0028/1754] mfd: stm32: Enable regmap fast_io for stm32-lptimer Because stm32-lptimer need to write in registers in interrupt context enable regmap fast_io to use a spin_lock to protect registers access rather than a mutex. Signed-off-by: Benjamin Gaignard Signed-off-by: Lee Jones --- drivers/mfd/stm32-lptimer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/stm32-lptimer.c b/drivers/mfd/stm32-lptimer.c index a00f99f365595..746e51a17cc8e 100644 --- a/drivers/mfd/stm32-lptimer.c +++ b/drivers/mfd/stm32-lptimer.c @@ -17,6 +17,7 @@ static const struct regmap_config stm32_lptimer_regmap_cfg = { .val_bits = 32, .reg_stride = sizeof(u32), .max_register = STM32_LPTIM_MAX_REGISTER, + .fast_io = true, }; static int stm32_lptimer_detect_encoder(struct stm32_lptimer *ddata) -- GitLab From 48b41c5e2de6c52c90efa99cfa122a5da7a7f0cd Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 Jun 2020 14:54:38 +0200 Subject: [PATCH 0029/1754] clocksource: Add Low Power STM32 timers driver Implement clock event driver using low power STM32 timers. Low power timer counters running even when CPUs are stopped. It could be used as clock event broadcaster to wake up CPUs but not like a clocksource because each it rise an interrupt the counter restart from 0. Low power timers have a 16 bits counter and a prescaler which allow to divide the clock per power of 2 to up 128 to target a 32KHz rate. Signed-off-by: Benjamin Gaignard Signed-off-by: Pascal Paillet Acked-by: Daniel Lezcano Signed-off-by: Lee Jones --- drivers/clocksource/Kconfig | 4 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-stm32-lp.c | 221 +++++++++++++++++++++++++++ 3 files changed, 226 insertions(+) create mode 100644 drivers/clocksource/timer-stm32-lp.c diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 91418381fcd41..be49123b088ab 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -291,6 +291,10 @@ config CLKSRC_STM32 select CLKSRC_MMIO select TIMER_OF +config CLKSRC_STM32_LP + bool "Low power clocksource for STM32 SoCs" + depends on MFD_STM32_LPTIMER || COMPILE_TEST + config CLKSRC_MPS2 bool "Clocksource for MPS2 SoCs" if COMPILE_TEST depends on GENERIC_SCHED_CLOCK diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index bdda1a2e4097d..66501e64d0b64 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_BCM_KONA_TIMER) += bcm_kona_timer.o obj-$(CONFIG_CADENCE_TTC_TIMER) += timer-cadence-ttc.o obj-$(CONFIG_CLKSRC_EFM32) += timer-efm32.o obj-$(CONFIG_CLKSRC_STM32) += timer-stm32.o +obj-$(CONFIG_CLKSRC_STM32_LP) += timer-stm32-lp.o obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o obj-$(CONFIG_CLKSRC_LPC32XX) += timer-lpc32xx.o obj-$(CONFIG_CLKSRC_MPS2) += mps2-timer.o diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c new file mode 100644 index 0000000000000..db2841d0beb81 --- /dev/null +++ b/drivers/clocksource/timer-stm32-lp.c @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Authors: Benjamin Gaignard for STMicroelectronics. + * Pascal Paillet for STMicroelectronics. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CFGR_PSC_OFFSET 9 +#define STM32_LP_RATING 1000 +#define STM32_TARGET_CLKRATE (32000 * HZ) +#define STM32_LP_MAX_PSC 7 + +struct stm32_lp_private { + struct regmap *reg; + struct clock_event_device clkevt; + unsigned long period; + struct device *dev; +}; + +static struct stm32_lp_private* +to_priv(struct clock_event_device *clkevt) +{ + return container_of(clkevt, struct stm32_lp_private, clkevt); +} + +static int stm32_clkevent_lp_shutdown(struct clock_event_device *clkevt) +{ + struct stm32_lp_private *priv = to_priv(clkevt); + + regmap_write(priv->reg, STM32_LPTIM_CR, 0); + regmap_write(priv->reg, STM32_LPTIM_IER, 0); + /* clear pending flags */ + regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF); + + return 0; +} + +static int stm32_clkevent_lp_set_timer(unsigned long evt, + struct clock_event_device *clkevt, + int is_periodic) +{ + struct stm32_lp_private *priv = to_priv(clkevt); + + /* disable LPTIMER to be able to write into IER register*/ + regmap_write(priv->reg, STM32_LPTIM_CR, 0); + /* enable ARR interrupt */ + regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE); + /* enable LPTIMER to be able to write into ARR register */ + regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE); + /* set next event counter */ + regmap_write(priv->reg, STM32_LPTIM_ARR, evt); + + /* start counter */ + if (is_periodic) + regmap_write(priv->reg, STM32_LPTIM_CR, + STM32_LPTIM_CNTSTRT | STM32_LPTIM_ENABLE); + else + regmap_write(priv->reg, STM32_LPTIM_CR, + STM32_LPTIM_SNGSTRT | STM32_LPTIM_ENABLE); + + return 0; +} + +static int stm32_clkevent_lp_set_next_event(unsigned long evt, + struct clock_event_device *clkevt) +{ + return stm32_clkevent_lp_set_timer(evt, clkevt, + clockevent_state_periodic(clkevt)); +} + +static int stm32_clkevent_lp_set_periodic(struct clock_event_device *clkevt) +{ + struct stm32_lp_private *priv = to_priv(clkevt); + + return stm32_clkevent_lp_set_timer(priv->period, clkevt, true); +} + +static int stm32_clkevent_lp_set_oneshot(struct clock_event_device *clkevt) +{ + struct stm32_lp_private *priv = to_priv(clkevt); + + return stm32_clkevent_lp_set_timer(priv->period, clkevt, false); +} + +static irqreturn_t stm32_clkevent_lp_irq_handler(int irq, void *dev_id) +{ + struct clock_event_device *clkevt = (struct clock_event_device *)dev_id; + struct stm32_lp_private *priv = to_priv(clkevt); + + regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF); + + if (clkevt->event_handler) + clkevt->event_handler(clkevt); + + return IRQ_HANDLED; +} + +static void stm32_clkevent_lp_set_prescaler(struct stm32_lp_private *priv, + unsigned long *rate) +{ + int i; + + for (i = 0; i <= STM32_LP_MAX_PSC; i++) { + if (DIV_ROUND_CLOSEST(*rate, 1 << i) < STM32_TARGET_CLKRATE) + break; + } + + regmap_write(priv->reg, STM32_LPTIM_CFGR, i << CFGR_PSC_OFFSET); + + /* Adjust rate and period given the prescaler value */ + *rate = DIV_ROUND_CLOSEST(*rate, (1 << i)); + priv->period = DIV_ROUND_UP(*rate, HZ); +} + +static void stm32_clkevent_lp_init(struct stm32_lp_private *priv, + struct device_node *np, unsigned long rate) +{ + priv->clkevt.name = np->full_name; + priv->clkevt.cpumask = cpu_possible_mask; + priv->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT; + priv->clkevt.set_state_shutdown = stm32_clkevent_lp_shutdown; + priv->clkevt.set_state_periodic = stm32_clkevent_lp_set_periodic; + priv->clkevt.set_state_oneshot = stm32_clkevent_lp_set_oneshot; + priv->clkevt.set_next_event = stm32_clkevent_lp_set_next_event; + priv->clkevt.rating = STM32_LP_RATING; + + clockevents_config_and_register(&priv->clkevt, rate, 0x1, + STM32_LPTIM_MAX_ARR); +} + +static int stm32_clkevent_lp_probe(struct platform_device *pdev) +{ + struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent); + struct stm32_lp_private *priv; + unsigned long rate; + int ret, irq; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->reg = ddata->regmap; + ret = clk_prepare_enable(ddata->clk); + if (ret) + return -EINVAL; + + rate = clk_get_rate(ddata->clk); + if (!rate) { + ret = -EINVAL; + goto out_clk_disable; + } + + irq = platform_get_irq(to_platform_device(pdev->dev.parent), 0); + if (irq <= 0) { + ret = irq; + goto out_clk_disable; + } + + if (of_property_read_bool(pdev->dev.parent->of_node, "wakeup-source")) { + ret = device_init_wakeup(&pdev->dev, true); + if (ret) + goto out_clk_disable; + + ret = dev_pm_set_wake_irq(&pdev->dev, irq); + if (ret) + goto out_clk_disable; + } + + ret = devm_request_irq(&pdev->dev, irq, stm32_clkevent_lp_irq_handler, + IRQF_TIMER, pdev->name, &priv->clkevt); + if (ret) + goto out_clk_disable; + + stm32_clkevent_lp_set_prescaler(priv, &rate); + + stm32_clkevent_lp_init(priv, pdev->dev.parent->of_node, rate); + + priv->dev = &pdev->dev; + + return 0; + +out_clk_disable: + clk_disable_unprepare(ddata->clk); + return ret; +} + +static int stm32_clkevent_lp_remove(struct platform_device *pdev) +{ + return -EBUSY; /* cannot unregister clockevent */ +} + +static const struct of_device_id stm32_clkevent_lp_of_match[] = { + { .compatible = "st,stm32-lptimer-timer", }, + {}, +}; +MODULE_DEVICE_TABLE(of, stm32_clkevent_lp_of_match); + +static struct platform_driver stm32_clkevent_lp_driver = { + .probe = stm32_clkevent_lp_probe, + .remove = stm32_clkevent_lp_remove, + .driver = { + .name = "stm32-lptimer-timer", + .of_match_table = of_match_ptr(stm32_clkevent_lp_of_match), + }, +}; +module_platform_driver(stm32_clkevent_lp_driver); + +MODULE_ALIAS("platform:stm32-lptimer-timer"); +MODULE_DESCRIPTION("STMicroelectronics STM32 clockevent low power driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From 3ea2e4eab64cefa06055bb0541fcdedad4b48565 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 15 Jun 2020 19:10:32 +0300 Subject: [PATCH 0030/1754] mfd: intel-lpss: Add Intel Emmitsburg PCH PCI IDs Intel Emmitsburg PCH has the same LPSS than Intel Ice Lake. Add the new IDs to the list of supported devices. Signed-off-by: Andy Shevchenko Signed-off-by: Lee Jones --- drivers/mfd/intel-lpss-pci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index 046222684b8b2..17bcadc00a11c 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -201,6 +201,9 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x1ac4), (kernel_ulong_t)&bxt_info }, { PCI_VDEVICE(INTEL, 0x1ac6), (kernel_ulong_t)&bxt_info }, { PCI_VDEVICE(INTEL, 0x1aee), (kernel_ulong_t)&bxt_uart_info }, + /* EBG */ + { PCI_VDEVICE(INTEL, 0x1bad), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x1bae), (kernel_ulong_t)&bxt_uart_info }, /* GLK */ { PCI_VDEVICE(INTEL, 0x31ac), (kernel_ulong_t)&glk_i2c_info }, { PCI_VDEVICE(INTEL, 0x31ae), (kernel_ulong_t)&glk_i2c_info }, -- GitLab From 14024cc9fe9478b9948521c0d38fde03ac00cd3d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 15 Jun 2020 14:53:20 +0100 Subject: [PATCH 0031/1754] mfd: arizona: Remove BUG_ON usage BUG_ON macros are generally frowned upon when the issue isn't super critical, the kernel can certainly carry on with the 32k clock on the CODEC in a bad state so change the BUG_ON to a WARN_ON. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index f73cf76d1373d..19e0bc3c0683e 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -80,7 +80,7 @@ int arizona_clk32k_disable(struct arizona *arizona) { mutex_lock(&arizona->clk_lock); - BUG_ON(arizona->clk32k_ref <= 0); + WARN_ON(arizona->clk32k_ref <= 0); arizona->clk32k_ref--; -- GitLab From ddff6c45b21d0437ce0c85f8ac35d7b5480513d7 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 15 Jun 2020 14:53:21 +0100 Subject: [PATCH 0032/1754] mfd: arizona: Ensure 32k clock is put on driver unbind and error Whilst it doesn't matter if the internal 32k clock register settings are cleaned up on exit, as the part will be turned off losing any settings, hence the driver hasn't historially bothered. The external clock should however be cleaned up, as it could cause clocks to be left on, and will at best generate a warning on unbind. Add clean up on both the probe error path and unbind for the 32k clock. Fixes: cdd8da8cc66b ("mfd: arizona: Add gating of external MCLKn clocks") Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 19e0bc3c0683e..000cb82023e35 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -1426,6 +1426,15 @@ int arizona_dev_init(struct arizona *arizona) arizona_irq_exit(arizona); err_pm: pm_runtime_disable(arizona->dev); + + switch (arizona->pdata.clk32k_src) { + case ARIZONA_32KZ_MCLK1: + case ARIZONA_32KZ_MCLK2: + arizona_clk32k_disable(arizona); + break; + default: + break; + } err_reset: arizona_enable_reset(arizona); regulator_disable(arizona->dcvdd); @@ -1448,6 +1457,15 @@ int arizona_dev_exit(struct arizona *arizona) regulator_disable(arizona->dcvdd); regulator_put(arizona->dcvdd); + switch (arizona->pdata.clk32k_src) { + case ARIZONA_32KZ_MCLK1: + case ARIZONA_32KZ_MCLK2: + arizona_clk32k_disable(arizona); + break; + default: + break; + } + mfd_remove_devices(arizona->dev); arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, arizona); arizona_free_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, arizona); -- GitLab From 7f8a137f736f7366820c485c5a0d34d65b9d0125 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 15 Jun 2020 14:53:22 +0100 Subject: [PATCH 0033/1754] mfd: madera: Remove unused forward declaration of madera_codec_pdata This forward declaration is redundant since the header including the full data structure is included. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- include/linux/mfd/madera/pdata.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/mfd/madera/pdata.h b/include/linux/mfd/madera/pdata.h index fa9595dd42ba5..601cbbc10370c 100644 --- a/include/linux/mfd/madera/pdata.h +++ b/include/linux/mfd/madera/pdata.h @@ -21,7 +21,6 @@ struct gpio_desc; struct pinctrl_map; -struct madera_codec_pdata; /** * struct madera_pdata - Configuration data for Madera devices -- GitLab From b92735f45f99c9bdcf93ce822fab56231e64a904 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 15 Jun 2020 14:53:23 +0100 Subject: [PATCH 0034/1754] mfd: madera: Fix minor formatting issues The mfd_cell structures inconsistently use commas on single entries in the table, make this consistent by always using a comma. Also remove an extra blank line. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/madera-core.c | 12 ++++++------ drivers/mfd/madera-i2c.c | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/mfd/madera-core.c b/drivers/mfd/madera-core.c index 7e0835cb062b1..4724c1a01a39f 100644 --- a/drivers/mfd/madera-core.c +++ b/drivers/mfd/madera-core.c @@ -44,7 +44,7 @@ static const char * const madera_core_supplies[] = { }; static const struct mfd_cell madera_ldo1_devs[] = { - { .name = "madera-ldo1" }, + { .name = "madera-ldo1", }, }; static const char * const cs47l15_supplies[] = { @@ -55,8 +55,8 @@ static const char * const cs47l15_supplies[] = { static const struct mfd_cell cs47l15_devs[] = { { .name = "madera-pinctrl", }, - { .name = "madera-irq" }, - { .name = "madera-gpio" }, + { .name = "madera-irq", }, + { .name = "madera-gpio", }, { .name = "madera-extcon", .parent_supplies = cs47l15_supplies, @@ -108,7 +108,7 @@ static const char * const cs47l85_supplies[] = { static const struct mfd_cell cs47l85_devs[] = { { .name = "madera-pinctrl", }, { .name = "madera-irq", }, - { .name = "madera-micsupp" }, + { .name = "madera-micsupp", }, { .name = "madera-gpio", }, { .name = "madera-extcon", @@ -155,10 +155,10 @@ static const char * const cs47l92_supplies[] = { }; static const struct mfd_cell cs47l92_devs[] = { - { .name = "madera-pinctrl" }, + { .name = "madera-pinctrl", }, { .name = "madera-irq", }, { .name = "madera-micsupp", }, - { .name = "madera-gpio" }, + { .name = "madera-gpio", }, { .name = "madera-extcon", .parent_supplies = cs47l92_supplies, diff --git a/drivers/mfd/madera-i2c.c b/drivers/mfd/madera-i2c.c index 6b965eb034b6c..7df5b9ba58554 100644 --- a/drivers/mfd/madera-i2c.c +++ b/drivers/mfd/madera-i2c.c @@ -88,7 +88,6 @@ static int madera_i2c_probe(struct i2c_client *i2c, if (!madera) return -ENOMEM; - madera->regmap = devm_regmap_init_i2c(i2c, regmap_16bit_config); if (IS_ERR(madera->regmap)) { ret = PTR_ERR(madera->regmap); -- GitLab From ad738ddd506b68679faf79277280b75522dd84e7 Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Tue, 9 Jun 2020 07:57:19 -0700 Subject: [PATCH 0035/1754] dt-bindings: mfd: gateworks-gsc: Add 16bit pre-scaled voltage mode Add a 16-bit pre-scaled voltage mode to ADC and clarify that existing pre-scaled mode is 24bit. Signed-off-by: Tim Harvey Acked-by: Rob Herring Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml b/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml index 487a8445722e5..ceec33f6aba15 100644 --- a/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml +++ b/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml @@ -79,11 +79,12 @@ properties: description: | conversion mode: 0 - temperature, in C*10 - 1 - pre-scaled voltage value + 1 - pre-scaled 24-bit voltage value 2 - scaled voltage based on an optional resistor divider and optional offset + 3 - pre-scaled 16-bit voltage value $ref: /schemas/types.yaml#/definitions/uint32 - enum: [0, 1, 2] + enum: [0, 1, 2, 3] gw,voltage-divider-ohms: description: Values of resistors for divider on raw ADC input -- GitLab From 6bcb330c1f373f314118f772c6e22f1cc36d7683 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 8 Jun 2020 11:17:35 +0200 Subject: [PATCH 0036/1754] dt-bindings: mfd: Add Khadas Microcontroller bindings This Microcontroller is present on the Khadas VIM1, VIM2, VIM3 and Edge boards. It has multiple boot control features like password check, power-on options, power-off control and system FAN control on recent boards. Signed-off-by: Neil Armstrong Reviewed-by: Rob Herring Signed-off-by: Lee Jones --- .../devicetree/bindings/mfd/khadas,mcu.yaml | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/khadas,mcu.yaml diff --git a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml new file mode 100644 index 0000000000000..a3b976f101e8c --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/khadas,mcu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Khadas on-board Microcontroller Device Tree Bindings + +maintainers: + - Neil Armstrong + +description: | + Khadas embeds a microcontroller on their VIM and Edge boards adding some + system feature as PWM Fan control (for VIM2 rev14 or VIM3), User memory + storage, IR/Key resume control, system power LED control and more. + +properties: + compatible: + enum: + - khadas,mcu # MCU revision is discoverable + + "#cooling-cells": # Only needed for boards having FAN control feature + const: 2 + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + khadas_mcu: system-controller@18 { + compatible = "khadas,mcu"; + reg = <0x18>; + #cooling-cells = <2>; + }; + }; -- GitLab From 6c27219e34911601955b72c754adfc11c527ba7b Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 8 Jun 2020 11:17:36 +0200 Subject: [PATCH 0037/1754] mfd: Add support for the Khadas System control Microcontroller This Microcontroller is present on the Khadas VIM1, VIM2, VIM3 and Edge boards. It has multiple boot control features like password check, power-on options, power-off control and system FAN control on recent boards. This implements a very basic MFD driver with the fan control and User NVMEM cells. Signed-off-by: Neil Armstrong Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 21 +++++ drivers/mfd/Makefile | 1 + drivers/mfd/khadas-mcu.c | 142 +++++++++++++++++++++++++++++++++ include/linux/mfd/khadas-mcu.h | 91 +++++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 drivers/mfd/khadas-mcu.c create mode 100644 include/linux/mfd/khadas-mcu.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index a37d7d1713820..d13bb0abfd6f9 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -2053,6 +2053,27 @@ config MFD_WCD934X This driver provides common support WCD934x audio codec and its associated Pin Controller, Soundwire Controller and Audio codec. +config MFD_KHADAS_MCU + tristate "Support for Khadas System control Microcontroller" + depends on I2C + depends on ARCH_MESON || ARCH_ROCKCHIP || COMPILE_TEST + select MFD_CORE + select REGMAP_I2C + help + Support for the Khadas System control Microcontroller interface + present on their VIM and Edge boards. + + This Microcontroller is present on the Khadas VIM1, VIM2, VIM3 and + Edge boards. + + It provides multiple boot control features like password check, + power-on options, power-off control and system FAN control on recent + boards. + + This driver provides common support for accessing the device, + additional drivers must be enabled in order to use the functionality + of the device. + menu "Multimedia Capabilities Port drivers" depends on ARCH_SA1100 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 9367a92f795a6..1c8d6be3347d6 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -262,5 +262,6 @@ obj-$(CONFIG_MFD_ROHM_BD70528) += rohm-bd70528.o obj-$(CONFIG_MFD_ROHM_BD71828) += rohm-bd71828.o obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o obj-$(CONFIG_MFD_STMFX) += stmfx.o +obj-$(CONFIG_MFD_KHADAS_MCU) += khadas-mcu.o obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c new file mode 100644 index 0000000000000..44d5bb462daba --- /dev/null +++ b/drivers/mfd/khadas-mcu.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Khadas System control Microcontroller + * + * Copyright (C) 2020 BayLibre SAS + * + * Author(s): Neil Armstrong + */ +#include +#include +#include +#include +#include +#include + +static bool khadas_mcu_reg_volatile(struct device *dev, unsigned int reg) +{ + if (reg >= KHADAS_MCU_USER_DATA_0_REG && + reg < KHADAS_MCU_PWR_OFF_CMD_REG) + return true; + + switch (reg) { + case KHADAS_MCU_PWR_OFF_CMD_REG: + case KHADAS_MCU_PASSWD_START_REG: + case KHADAS_MCU_CHECK_VEN_PASSWD_REG: + case KHADAS_MCU_CHECK_USER_PASSWD_REG: + case KHADAS_MCU_WOL_INIT_START_REG: + case KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG: + return true; + default: + return false; + } +} + +static bool khadas_mcu_reg_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case KHADAS_MCU_PASSWD_VEN_0_REG: + case KHADAS_MCU_PASSWD_VEN_1_REG: + case KHADAS_MCU_PASSWD_VEN_2_REG: + case KHADAS_MCU_PASSWD_VEN_3_REG: + case KHADAS_MCU_PASSWD_VEN_4_REG: + case KHADAS_MCU_PASSWD_VEN_5_REG: + case KHADAS_MCU_MAC_0_REG: + case KHADAS_MCU_MAC_1_REG: + case KHADAS_MCU_MAC_2_REG: + case KHADAS_MCU_MAC_3_REG: + case KHADAS_MCU_MAC_4_REG: + case KHADAS_MCU_MAC_5_REG: + case KHADAS_MCU_USID_0_REG: + case KHADAS_MCU_USID_1_REG: + case KHADAS_MCU_USID_2_REG: + case KHADAS_MCU_USID_3_REG: + case KHADAS_MCU_USID_4_REG: + case KHADAS_MCU_USID_5_REG: + case KHADAS_MCU_VERSION_0_REG: + case KHADAS_MCU_VERSION_1_REG: + case KHADAS_MCU_DEVICE_NO_0_REG: + case KHADAS_MCU_DEVICE_NO_1_REG: + case KHADAS_MCU_FACTORY_TEST_REG: + case KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG: + return false; + default: + return true; + } +} + +static const struct regmap_config khadas_mcu_regmap_config = { + .reg_bits = 8, + .reg_stride = 1, + .val_bits = 8, + .max_register = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG, + .volatile_reg = khadas_mcu_reg_volatile, + .writeable_reg = khadas_mcu_reg_writeable, + .cache_type = REGCACHE_RBTREE, +}; + +static struct mfd_cell khadas_mcu_fan_cells[] = { + /* VIM1/2 Rev13+ and VIM3 only */ + { .name = "khadas-mcu-fan-ctrl", }, +}; + +static struct mfd_cell khadas_mcu_cells[] = { + { .name = "khadas-mcu-user-mem", }, +}; + +static int khadas_mcu_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct khadas_mcu *ddata; + int ret; + + ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); + if (!ddata) + return -ENOMEM; + + i2c_set_clientdata(client, ddata); + + ddata->dev = dev; + + ddata->regmap = devm_regmap_init_i2c(client, &khadas_mcu_regmap_config); + if (IS_ERR(ddata->regmap)) { + ret = PTR_ERR(ddata->regmap); + dev_err(dev, "Failed to allocate register map: %d\n", ret); + return ret; + } + + ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, + khadas_mcu_cells, + ARRAY_SIZE(khadas_mcu_cells), + NULL, 0, NULL); + if (ret) + return ret; + + if (of_find_property(dev->of_node, "#cooling-cells", NULL)) + return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, + khadas_mcu_fan_cells, + ARRAY_SIZE(khadas_mcu_fan_cells), + NULL, 0, NULL); + + return 0; +} + +static const struct of_device_id khadas_mcu_of_match[] = { + { .compatible = "khadas,mcu", }, + {}, +}; +MODULE_DEVICE_TABLE(of, khadas_mcu_of_match); + +static struct i2c_driver khadas_mcu_driver = { + .driver = { + .name = "khadas-mcu-core", + .of_match_table = of_match_ptr(khadas_mcu_of_match), + }, + .probe = khadas_mcu_probe, +}; +module_i2c_driver(khadas_mcu_driver); + +MODULE_DESCRIPTION("Khadas MCU core driver"); +MODULE_AUTHOR("Neil Armstrong "); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/khadas-mcu.h b/include/linux/mfd/khadas-mcu.h new file mode 100644 index 0000000000000..a99ba2ed0e4e0 --- /dev/null +++ b/include/linux/mfd/khadas-mcu.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Khadas System control Microcontroller Register map + * + * Copyright (C) 2020 BayLibre SAS + * + * Author(s): Neil Armstrong + */ + +#ifndef MFD_KHADAS_MCU_H +#define MFD_KHADAS_MCU_H + +#define KHADAS_MCU_PASSWD_VEN_0_REG 0x00 /* RO */ +#define KHADAS_MCU_PASSWD_VEN_1_REG 0x01 /* RO */ +#define KHADAS_MCU_PASSWD_VEN_2_REG 0x02 /* RO */ +#define KHADAS_MCU_PASSWD_VEN_3_REG 0x03 /* RO */ +#define KHADAS_MCU_PASSWD_VEN_4_REG 0x04 /* RO */ +#define KHADAS_MCU_PASSWD_VEN_5_REG 0x05 /* RO */ +#define KHADAS_MCU_MAC_0_REG 0x06 /* RO */ +#define KHADAS_MCU_MAC_1_REG 0x07 /* RO */ +#define KHADAS_MCU_MAC_2_REG 0x08 /* RO */ +#define KHADAS_MCU_MAC_3_REG 0x09 /* RO */ +#define KHADAS_MCU_MAC_4_REG 0x0a /* RO */ +#define KHADAS_MCU_MAC_5_REG 0x0b /* RO */ +#define KHADAS_MCU_USID_0_REG 0x0c /* RO */ +#define KHADAS_MCU_USID_1_REG 0x0d /* RO */ +#define KHADAS_MCU_USID_2_REG 0x0e /* RO */ +#define KHADAS_MCU_USID_3_REG 0x0f /* RO */ +#define KHADAS_MCU_USID_4_REG 0x10 /* RO */ +#define KHADAS_MCU_USID_5_REG 0x11 /* RO */ +#define KHADAS_MCU_VERSION_0_REG 0x12 /* RO */ +#define KHADAS_MCU_VERSION_1_REG 0x13 /* RO */ +#define KHADAS_MCU_DEVICE_NO_0_REG 0x14 /* RO */ +#define KHADAS_MCU_DEVICE_NO_1_REG 0x15 /* RO */ +#define KHADAS_MCU_FACTORY_TEST_REG 0x16 /* R */ +#define KHADAS_MCU_BOOT_MODE_REG 0x20 /* RW */ +#define KHADAS_MCU_BOOT_EN_WOL_REG 0x21 /* RW */ +#define KHADAS_MCU_BOOT_EN_RTC_REG 0x22 /* RW */ +#define KHADAS_MCU_BOOT_EN_EXP_REG 0x23 /* RW */ +#define KHADAS_MCU_BOOT_EN_IR_REG 0x24 /* RW */ +#define KHADAS_MCU_BOOT_EN_DCIN_REG 0x25 /* RW */ +#define KHADAS_MCU_BOOT_EN_KEY_REG 0x26 /* RW */ +#define KHADAS_MCU_KEY_MODE_REG 0x27 /* RW */ +#define KHADAS_MCU_LED_MODE_ON_REG 0x28 /* RW */ +#define KHADAS_MCU_LED_MODE_OFF_REG 0x29 /* RW */ +#define KHADAS_MCU_SHUTDOWN_NORMAL_REG 0x2c /* RW */ +#define KHADAS_MCU_MAC_SWITCH_REG 0x2d /* RW */ +#define KHADAS_MCU_MCU_SLEEP_MODE_REG 0x2e /* RW */ +#define KHADAS_MCU_IR_CODE1_0_REG 0x2f /* RW */ +#define KHADAS_MCU_IR_CODE1_1_REG 0x30 /* RW */ +#define KHADAS_MCU_IR_CODE1_2_REG 0x31 /* RW */ +#define KHADAS_MCU_IR_CODE1_3_REG 0x32 /* RW */ +#define KHADAS_MCU_USB_PCIE_SWITCH_REG 0x33 /* RW */ +#define KHADAS_MCU_IR_CODE2_0_REG 0x34 /* RW */ +#define KHADAS_MCU_IR_CODE2_1_REG 0x35 /* RW */ +#define KHADAS_MCU_IR_CODE2_2_REG 0x36 /* RW */ +#define KHADAS_MCU_IR_CODE2_3_REG 0x37 /* RW */ +#define KHADAS_MCU_PASSWD_USER_0_REG 0x40 /* RW */ +#define KHADAS_MCU_PASSWD_USER_1_REG 0x41 /* RW */ +#define KHADAS_MCU_PASSWD_USER_2_REG 0x42 /* RW */ +#define KHADAS_MCU_PASSWD_USER_3_REG 0x43 /* RW */ +#define KHADAS_MCU_PASSWD_USER_4_REG 0x44 /* RW */ +#define KHADAS_MCU_PASSWD_USER_5_REG 0x45 /* RW */ +#define KHADAS_MCU_USER_DATA_0_REG 0x46 /* RW 56 bytes */ +#define KHADAS_MCU_PWR_OFF_CMD_REG 0x80 /* WO */ +#define KHADAS_MCU_PASSWD_START_REG 0x81 /* WO */ +#define KHADAS_MCU_CHECK_VEN_PASSWD_REG 0x82 /* WO */ +#define KHADAS_MCU_CHECK_USER_PASSWD_REG 0x83 /* WO */ +#define KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG 0x86 /* RO */ +#define KHADAS_MCU_WOL_INIT_START_REG 0x87 /* WO */ +#define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG 0x88 /* WO */ + +enum { + KHADAS_BOARD_VIM1 = 0x1, + KHADAS_BOARD_VIM2, + KHADAS_BOARD_VIM3, + KHADAS_BOARD_EDGE = 0x11, + KHADAS_BOARD_EDGE_V, +}; + +/** + * struct khadas_mcu - Khadas MCU structure + * @device: device reference used for logs + * @regmap: register map + */ +struct khadas_mcu { + struct device *dev; + struct regmap *regmap; +}; + +#endif /* MFD_KHADAS_MCU_H */ -- GitLab From 99bbe307013059951368d12f5454d34568de4850 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 16 Jun 2020 09:56:51 -0700 Subject: [PATCH 0038/1754] f2fs: avoid checkpatch error ERROR:INITIALISED_STATIC: do not initialise statics to NULL Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 1e02a8c106b0a..4dca9e4567348 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -506,7 +506,7 @@ bool f2fs_is_compress_backend_ready(struct inode *inode) return f2fs_cops[F2FS_I(inode)->i_compress_algorithm]; } -static mempool_t *compress_page_pool = NULL; +static mempool_t *compress_page_pool; static int num_compress_pages = 512; module_param(num_compress_pages, uint, 0444); MODULE_PARM_DESC(num_compress_pages, -- GitLab From 742532d11d8328231d099f557e6287e75b2d247b Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Wed, 10 Jun 2020 01:14:46 +0300 Subject: [PATCH 0039/1754] f2fs: use kfree() instead of kvfree() to free superblock data Use kfree() instead of kvfree() to free super in read_raw_super_block() because the memory is allocated with kzalloc() in the function. Use kfree() instead of kvfree() to free sbi, raw_super in f2fs_fill_super() and f2fs_put_super() because the memory is allocated with kzalloc(). Signed-off-by: Denis Efremov Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/super.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 20e56b0fa46a9..426cebdd84e5d 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1243,7 +1243,7 @@ static void f2fs_put_super(struct super_block *sb) sb->s_fs_info = NULL; if (sbi->s_chksum_driver) crypto_free_shash(sbi->s_chksum_driver); - kvfree(sbi->raw_super); + kfree(sbi->raw_super); destroy_device_list(sbi); f2fs_destroy_xattr_caches(sbi); @@ -1259,7 +1259,7 @@ static void f2fs_put_super(struct super_block *sb) #ifdef CONFIG_UNICODE utf8_unload(sbi->s_encoding); #endif - kvfree(sbi); + kfree(sbi); } int f2fs_sync_fs(struct super_block *sb, int sync) @@ -3137,7 +3137,7 @@ static int read_raw_super_block(struct f2fs_sb_info *sbi, /* No valid superblock */ if (!*raw_super) - kvfree(super); + kfree(super); else err = 0; @@ -3816,11 +3816,11 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); kvfree(options); free_sb_buf: - kvfree(raw_super); + kfree(raw_super); free_sbi: if (sbi->s_chksum_driver) crypto_free_shash(sbi->s_chksum_driver); - kvfree(sbi); + kfree(sbi); /* give only one another chance */ if (retry_cnt > 0 && skip_recovery) { -- GitLab From 6f6489288ed196a962ef8d33b1b9cf6369ff0807 Mon Sep 17 00:00:00 2001 From: Wei Fang Date: Mon, 15 Jun 2020 16:11:38 +0800 Subject: [PATCH 0040/1754] f2fs: remove useless truncate in f2fs_collapse_range() Since offset < new_size, no need to do truncate_pagecache() again with new_size. Signed-off-by: Wei Fang Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 3268f8dd59bba..98721f9bef253 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1373,8 +1373,6 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len) truncate_pagecache(inode, offset); new_size = i_size_read(inode) - len; - truncate_pagecache(inode, new_size); - ret = f2fs_truncate_blocks(inode, new_size, true); up_write(&F2FS_I(inode)->i_mmap_sem); if (!ret) -- GitLab From db5ae363292705d52c5b653d5079a07a6417ef4c Mon Sep 17 00:00:00 2001 From: Wuyun Zhao Date: Thu, 18 Jun 2020 10:58:37 +0800 Subject: [PATCH 0041/1754] f2fs: fix a race condition between f2fs_write_end_io and f2fs_del_fsync_node_entry Under some condition, the __write_node_page will submit a page which is not f2fs_in_warm_node_list and will not call f2fs_add_fsync_node_entry. f2fs_gc continue to run to invoke f2fs_iget -> do_read_inode to read the same node page and set code node, which make f2fs_in_warm_node_list become true, that will cause f2fs_bug_on in f2fs_del_fsync_node_entry when f2fs_write_end_io called. - f2fs_write_end_io - f2fs_iget - do_read_inode - set_cold_node recover cold node flag - f2fs_in_warm_node_list - is_cold_node if node is cold, assume we have added node to fsync_node_list during writepages() - f2fs_del_fsync_node_entry - f2fs_bug_on() due to node page is not in fsync_node_list [ 34.966133] Call trace: [ 34.969902] f2fs_del_fsync_node_entry+0x100/0x108 [ 34.976071] f2fs_write_end_io+0x1e0/0x288 [ 34.981539] bio_endio+0x248/0x270 [ 34.986289] blk_update_request+0x2b0/0x4d8 [ 34.991841] scsi_end_request+0x40/0x440 [ 34.997126] scsi_io_completion+0xa4/0x748 [ 35.002593] scsi_finish_command+0xdc/0x110 [ 35.008143] scsi_softirq_done+0x118/0x150 [ 35.013610] blk_done_softirq+0x8c/0xe8 [ 35.018811] __do_softirq+0x2e8/0x578 [ 35.023828] irq_exit+0xfc/0x120 [ 35.028398] handle_IPI+0x1d8/0x330 [ 35.033233] gic_handle_irq+0x110/0x1d4 [ 35.038433] el1_irq+0xb4/0x130 [ 35.042917] kmem_cache_alloc+0x3f0/0x418 [ 35.048288] radix_tree_node_alloc+0x50/0xf8 [ 35.053933] __radix_tree_create+0xf8/0x188 [ 35.059484] __radix_tree_insert+0x3c/0x128 [ 35.065035] add_gc_inode+0x90/0x118 [ 35.069967] f2fs_gc+0x1b80/0x2d70 [ 35.074718] f2fs_disable_checkpoint+0x94/0x1d0 [ 35.080621] f2fs_fill_super+0x10c4/0x1b88 [ 35.086088] mount_bdev+0x194/0x1e0 [ 35.090923] f2fs_mount+0x40/0x50 [ 35.095589] mount_fs+0xb4/0x190 [ 35.100159] vfs_kern_mount+0x80/0x1d8 [ 35.105260] do_mount+0x478/0xf18 [ 35.109926] ksys_mount+0x90/0xd0 [ 35.114592] __arm64_sys_mount+0x24/0x38 Signed-off-by: Wuyun Zhao Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 44582a4db513e..33affa788588f 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -402,6 +402,7 @@ static int do_read_inode(struct inode *inode) /* try to recover cold bit for non-dir inode */ if (!S_ISDIR(inode->i_mode) && !is_cold_node(node_page)) { + f2fs_wait_on_page_writeback(node_page, NODE, true, true); set_cold_node(node_page, false); set_page_dirty(node_page); } -- GitLab From da52f8ade40b032eb8111a0fd514c8ac5f8f0f1b Mon Sep 17 00:00:00 2001 From: Jack Qiu Date: Thu, 18 Jun 2020 12:37:10 +0800 Subject: [PATCH 0042/1754] f2fs: get the right gc victim section when section has several segments Assume each section has 4 segment: .___________________________. |_Segment0_|_..._|_Segment3_| . . . . .__________. |_section0_| Segment 0~2 has 0 valid block, segment 3 has 512 valid blocks. It will fail if we want to gc section0 in this scenes, because all 4 segments in section0 is not dirty. So we should use dirty section bitmap instead of dirty segment bitmap to get right victim section. Signed-off-by: Jack Qiu Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/gc.c | 41 ++++++++++++++++++------------- fs/f2fs/segment.c | 61 +++++++++++++++++++++++++++++++++++++++++++++-- fs/f2fs/segment.h | 8 +++++-- 3 files changed, 89 insertions(+), 21 deletions(-) diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 5b95d5a146eb6..9b6fc61ce6493 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -21,6 +21,9 @@ #include "gc.h" #include +static unsigned int count_bits(const unsigned long *addr, + unsigned int offset, unsigned int len); + static int gc_thread_func(void *data) { struct f2fs_sb_info *sbi = data; @@ -187,14 +190,20 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type, if (p->alloc_mode == SSR) { p->gc_mode = GC_GREEDY; - p->dirty_segmap = dirty_i->dirty_segmap[type]; + p->dirty_bitmap = dirty_i->dirty_segmap[type]; p->max_search = dirty_i->nr_dirty[type]; p->ofs_unit = 1; } else { p->gc_mode = select_gc_type(sbi, gc_type); - p->dirty_segmap = dirty_i->dirty_segmap[DIRTY]; - p->max_search = dirty_i->nr_dirty[DIRTY]; p->ofs_unit = sbi->segs_per_sec; + if (__is_large_section(sbi)) { + p->dirty_bitmap = dirty_i->dirty_secmap; + p->max_search = count_bits(p->dirty_bitmap, + 0, MAIN_SECS(sbi)); + } else { + p->dirty_bitmap = dirty_i->dirty_segmap[DIRTY]; + p->max_search = dirty_i->nr_dirty[DIRTY]; + } } /* @@ -365,10 +374,14 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, } while (1) { - unsigned long cost; - unsigned int segno; - - segno = find_next_bit(p.dirty_segmap, last_segment, p.offset); + unsigned long cost, *dirty_bitmap; + unsigned int unit_no, segno; + + dirty_bitmap = p.dirty_bitmap; + unit_no = find_next_bit(dirty_bitmap, + last_segment / p.ofs_unit, + p.offset / p.ofs_unit); + segno = unit_no * p.ofs_unit; if (segno >= last_segment) { if (sm->last_victim[p.gc_mode]) { last_segment = @@ -381,14 +394,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, } p.offset = segno + p.ofs_unit; - if (p.ofs_unit > 1) { - p.offset -= segno % p.ofs_unit; - nsearched += count_bits(p.dirty_segmap, - p.offset - p.ofs_unit, - p.ofs_unit); - } else { - nsearched++; - } + nsearched++; #ifdef CONFIG_F2FS_CHECK_FS /* @@ -421,9 +427,10 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, next: if (nsearched >= p.max_search) { if (!sm->last_victim[p.gc_mode] && segno <= last_victim) - sm->last_victim[p.gc_mode] = last_victim + 1; + sm->last_victim[p.gc_mode] = + last_victim + p.ofs_unit; else - sm->last_victim[p.gc_mode] = segno + 1; + sm->last_victim[p.gc_mode] = segno + p.ofs_unit; sm->last_victim[p.gc_mode] %= (MAIN_SECS(sbi) * sbi->segs_per_sec); break; diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 196f315035118..66eeaba30e918 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -796,6 +796,18 @@ static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, } if (!test_and_set_bit(segno, dirty_i->dirty_segmap[t])) dirty_i->nr_dirty[t]++; + + if (__is_large_section(sbi)) { + unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); + unsigned short valid_blocks = + get_valid_blocks(sbi, segno, true); + + f2fs_bug_on(sbi, unlikely(!valid_blocks || + valid_blocks == BLKS_PER_SEC(sbi))); + + if (!IS_CURSEC(sbi, secno)) + set_bit(secno, dirty_i->dirty_secmap); + } } } @@ -803,6 +815,7 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, enum dirty_type dirty_type) { struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + unsigned short valid_blocks; if (test_and_clear_bit(segno, dirty_i->dirty_segmap[dirty_type])) dirty_i->nr_dirty[dirty_type]--; @@ -814,13 +827,26 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t])) dirty_i->nr_dirty[t]--; - if (get_valid_blocks(sbi, segno, true) == 0) { + valid_blocks = get_valid_blocks(sbi, segno, true); + if (valid_blocks == 0) { clear_bit(GET_SEC_FROM_SEG(sbi, segno), dirty_i->victim_secmap); #ifdef CONFIG_F2FS_CHECK_FS clear_bit(segno, SIT_I(sbi)->invalid_segmap); #endif } + if (__is_large_section(sbi)) { + unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); + + if (!valid_blocks || + valid_blocks == BLKS_PER_SEC(sbi)) { + clear_bit(secno, dirty_i->dirty_secmap); + return; + } + + if (!IS_CURSEC(sbi, secno)) + set_bit(secno, dirty_i->dirty_secmap); + } } } @@ -4293,8 +4319,9 @@ static void init_dirty_segmap(struct f2fs_sb_info *sbi) { struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); struct free_segmap_info *free_i = FREE_I(sbi); - unsigned int segno = 0, offset = 0; + unsigned int segno = 0, offset = 0, secno; unsigned short valid_blocks; + unsigned short blks_per_sec = BLKS_PER_SEC(sbi); while (1) { /* find dirty segment based on free segmap */ @@ -4313,6 +4340,22 @@ static void init_dirty_segmap(struct f2fs_sb_info *sbi) __locate_dirty_segment(sbi, segno, DIRTY); mutex_unlock(&dirty_i->seglist_lock); } + + if (!__is_large_section(sbi)) + return; + + mutex_lock(&dirty_i->seglist_lock); + for (segno = 0; segno < MAIN_SECS(sbi); segno += blks_per_sec) { + valid_blocks = get_valid_blocks(sbi, segno, true); + secno = GET_SEC_FROM_SEG(sbi, segno); + + if (!valid_blocks || valid_blocks == blks_per_sec) + continue; + if (IS_CURSEC(sbi, secno)) + continue; + set_bit(secno, dirty_i->dirty_secmap); + } + mutex_unlock(&dirty_i->seglist_lock); } static int init_victim_secmap(struct f2fs_sb_info *sbi) @@ -4349,6 +4392,14 @@ static int build_dirty_segmap(struct f2fs_sb_info *sbi) return -ENOMEM; } + if (__is_large_section(sbi)) { + bitmap_size = f2fs_bitmap_size(MAIN_SECS(sbi)); + dirty_i->dirty_secmap = f2fs_kvzalloc(sbi, + bitmap_size, GFP_KERNEL); + if (!dirty_i->dirty_secmap) + return -ENOMEM; + } + init_dirty_segmap(sbi); return init_victim_secmap(sbi); } @@ -4775,6 +4826,12 @@ static void destroy_dirty_segmap(struct f2fs_sb_info *sbi) for (i = 0; i < NR_DIRTY_TYPE; i++) discard_dirty_segmap(sbi, i); + if (__is_large_section(sbi)) { + mutex_lock(&dirty_i->seglist_lock); + kvfree(dirty_i->dirty_secmap); + mutex_unlock(&dirty_i->seglist_lock); + } + destroy_victim_secmap(sbi); SM_I(sbi)->dirty_info = NULL; kvfree(dirty_i); diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index cba16cca51895..f261e3e6a69bc 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -166,8 +166,11 @@ enum { struct victim_sel_policy { int alloc_mode; /* LFS or SSR */ int gc_mode; /* GC_CB or GC_GREEDY */ - unsigned long *dirty_segmap; /* dirty segment bitmap */ - unsigned int max_search; /* maximum # of segments to search */ + unsigned long *dirty_bitmap; /* dirty segment/section bitmap */ + unsigned int max_search; /* + * maximum # of segments/sections + * to search + */ unsigned int offset; /* last scanned bitmap offset */ unsigned int ofs_unit; /* bitmap search unit */ unsigned int min_cost; /* minimum cost */ @@ -266,6 +269,7 @@ enum dirty_type { struct dirty_seglist_info { const struct victim_selection *v_ops; /* victim selction operation */ unsigned long *dirty_segmap[NR_DIRTY_TYPE]; + unsigned long *dirty_secmap; struct mutex seglist_lock; /* lock for segment bitmaps */ int nr_dirty[NR_DIRTY_TYPE]; /* # of dirty segments */ unsigned long *victim_secmap; /* background GC victims */ -- GitLab From ba87a45c23d645b25e1265b477e83cc1b73086e4 Mon Sep 17 00:00:00 2001 From: Wang Xiaojun Date: Wed, 17 Jun 2020 20:30:12 +0800 Subject: [PATCH 0043/1754] f2fs: use kfree() to free variables allocated by match_strdup() Use kfree() instead of kvfree() to free variables allocated by match_strdup(). Because the memory is allocated with kmalloc inside match_strdup(). Signed-off-by: Wang Xiaojun Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/super.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 426cebdd84e5d..7326522057378 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -348,7 +348,7 @@ static int f2fs_set_qf_name(struct super_block *sb, int qtype, set_opt(sbi, QUOTA); return 0; errout: - kvfree(qname); + kfree(qname); return ret; } @@ -360,7 +360,7 @@ static int f2fs_clear_qf_name(struct super_block *sb, int qtype) f2fs_err(sbi, "Cannot change journaled quota options when quota turned on"); return -EINVAL; } - kvfree(F2FS_OPTION(sbi).s_qf_names[qtype]); + kfree(F2FS_OPTION(sbi).s_qf_names[qtype]); F2FS_OPTION(sbi).s_qf_names[qtype] = NULL; return 0; } @@ -494,10 +494,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) } else if (!strcmp(name, "sync")) { F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_SYNC; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_disable_roll_forward: set_opt(sbi, DISABLE_ROLL_FORWARD); @@ -654,17 +654,17 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) if (!strcmp(name, "adaptive")) { if (f2fs_sb_has_blkzoned(sbi)) { f2fs_warn(sbi, "adaptive mode is not allowed with zoned block device feature"); - kvfree(name); + kfree(name); return -EINVAL; } F2FS_OPTION(sbi).fs_mode = FS_MODE_ADAPTIVE; } else if (!strcmp(name, "lfs")) { F2FS_OPTION(sbi).fs_mode = FS_MODE_LFS; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_io_size_bits: if (args->from && match_int(args, &arg)) @@ -790,10 +790,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) } else if (!strcmp(name, "fs-based")) { F2FS_OPTION(sbi).whint_mode = WHINT_MODE_FS; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_alloc: name = match_strdup(&args[0]); @@ -805,10 +805,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) } else if (!strcmp(name, "reuse")) { F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_REUSE; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_fsync: name = match_strdup(&args[0]); @@ -822,10 +822,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_NOBARRIER; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_test_dummy_encryption: ret = f2fs_set_test_dummy_encryption(sb, p, &args[0], @@ -1250,7 +1250,7 @@ static void f2fs_put_super(struct super_block *sb) mempool_destroy(sbi->write_io_dummy); #ifdef CONFIG_QUOTA for (i = 0; i < MAXQUOTAS; i++) - kvfree(F2FS_OPTION(sbi).s_qf_names[i]); + kfree(F2FS_OPTION(sbi).s_qf_names[i]); #endif fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); destroy_percpu_info(sbi); @@ -1754,7 +1754,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) GFP_KERNEL); if (!org_mount_opt.s_qf_names[i]) { for (j = 0; j < i; j++) - kvfree(org_mount_opt.s_qf_names[j]); + kfree(org_mount_opt.s_qf_names[j]); return -ENOMEM; } } else { @@ -1879,7 +1879,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) #ifdef CONFIG_QUOTA /* Release old quota file names */ for (i = 0; i < MAXQUOTAS; i++) - kvfree(org_mount_opt.s_qf_names[i]); + kfree(org_mount_opt.s_qf_names[i]); #endif /* Update the POSIXACL Flag */ sb->s_flags = (sb->s_flags & ~SB_POSIXACL) | @@ -1900,7 +1900,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) #ifdef CONFIG_QUOTA F2FS_OPTION(sbi).s_jquota_fmt = org_mount_opt.s_jquota_fmt; for (i = 0; i < MAXQUOTAS; i++) { - kvfree(F2FS_OPTION(sbi).s_qf_names[i]); + kfree(F2FS_OPTION(sbi).s_qf_names[i]); F2FS_OPTION(sbi).s_qf_names[i] = org_mount_opt.s_qf_names[i]; } #endif @@ -3811,7 +3811,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) free_options: #ifdef CONFIG_QUOTA for (i = 0; i < MAXQUOTAS; i++) - kvfree(F2FS_OPTION(sbi).s_qf_names[i]); + kfree(F2FS_OPTION(sbi).s_qf_names[i]); #endif fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); kvfree(options); -- GitLab From a8cbf80e9fb175feb40cb56af93b3504f3c68551 Mon Sep 17 00:00:00 2001 From: "Daniel G. Morse" Date: Tue, 26 May 2020 02:55:50 +0100 Subject: [PATCH 0044/1754] HID: Wiimote: Treat the d-pad as an analogue stick The controllers from the Super Nintendo Classic Edition (AKA the SNES Mini) appear as a Classic Controller Pro when connected to a Wii Remote. All the buttons work as the same, with the d-pad being mapped the same as the d-pad on the Classic Controller Pro. This differs from the behaviour of most controllers with d-pads and no analogue sticks, where the d-pad maps to ABS_HAT1X for left and right, and ABS_HAT1Y for up and down. This patch adds an option to the hid-wiimote module to make the Super Nintendo Classic Controller behave this way. The patch has been tested with a Super Nintendo Classic Controller plugged into a Wii Remote in both with the option both enabled and disabled. When enabled the d-pad acts as the analogue control, and when disabled it acts as it did before the patch was applied. This patch has not been tested with e Wii Classic Controller (either the original or the pro version) as I do not have one of these controllers. Although I have not tested it with these controllers, I think it is likely this patch will also work with the NES Classic Edition Controllers. Signed-off-by: Daniel G. Morse Reviewed-by: David Rheinsberg Signed-off-by: Jiri Kosina --- drivers/hid/hid-wiimote-core.c | 5 +++ drivers/hid/hid-wiimote-modules.c | 67 ++++++++++++++++++++----------- drivers/hid/hid-wiimote.h | 2 + 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index 92874dbe4d4a4..679e142fc850c 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c @@ -1870,6 +1870,11 @@ static const struct hid_device_id wiimote_hid_devices[] = { USB_DEVICE_ID_NINTENDO_WIIMOTE2) }, { } }; + +bool wiimote_dpad_as_analog = false; +module_param_named(dpad_as_analog, wiimote_dpad_as_analog, bool, 0644); +MODULE_PARM_DESC(dpad_as_analog, "Use D-Pad as main analog input"); + MODULE_DEVICE_TABLE(hid, wiimote_hid_devices); static struct hid_driver wiimote_hid_driver = { diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c index 2c39253578573..213c58bf24951 100644 --- a/drivers/hid/hid-wiimote-modules.c +++ b/drivers/hid/hid-wiimote-modules.c @@ -1088,12 +1088,28 @@ static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext) * is the same as before. */ + static const s8 digital_to_analog[3] = {0x20, 0, -0x20}; + if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) { - lx = ext[0] & 0x3e; - ly = ext[1] & 0x3e; + if (wiimote_dpad_as_analog) { + lx = digital_to_analog[1 - !(ext[4] & 0x80) + + !(ext[1] & 0x01)]; + ly = digital_to_analog[1 - !(ext[4] & 0x40) + + !(ext[0] & 0x01)]; + } else { + lx = (ext[0] & 0x3e) - 0x20; + ly = (ext[1] & 0x3e) - 0x20; + } } else { - lx = ext[0] & 0x3f; - ly = ext[1] & 0x3f; + if (wiimote_dpad_as_analog) { + lx = digital_to_analog[1 - !(ext[4] & 0x80) + + !(ext[5] & 0x02)]; + ly = digital_to_analog[1 - !(ext[4] & 0x40) + + !(ext[5] & 0x01)]; + } else { + lx = (ext[0] & 0x3f) - 0x20; + ly = (ext[1] & 0x3f) - 0x20; + } } rx = (ext[0] >> 3) & 0x18; @@ -1110,19 +1126,13 @@ static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext) rt <<= 1; lt <<= 1; - input_report_abs(wdata->extension.input, ABS_HAT1X, lx - 0x20); - input_report_abs(wdata->extension.input, ABS_HAT1Y, ly - 0x20); + input_report_abs(wdata->extension.input, ABS_HAT1X, lx); + input_report_abs(wdata->extension.input, ABS_HAT1Y, ly); input_report_abs(wdata->extension.input, ABS_HAT2X, rx - 0x20); input_report_abs(wdata->extension.input, ABS_HAT2Y, ry - 0x20); input_report_abs(wdata->extension.input, ABS_HAT3X, rt); input_report_abs(wdata->extension.input, ABS_HAT3Y, lt); - input_report_key(wdata->extension.input, - wiimod_classic_map[WIIMOD_CLASSIC_KEY_RIGHT], - !(ext[4] & 0x80)); - input_report_key(wdata->extension.input, - wiimod_classic_map[WIIMOD_CLASSIC_KEY_DOWN], - !(ext[4] & 0x40)); input_report_key(wdata->extension.input, wiimod_classic_map[WIIMOD_CLASSIC_KEY_LT], !(ext[4] & 0x20)); @@ -1157,20 +1167,29 @@ static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext) wiimod_classic_map[WIIMOD_CLASSIC_KEY_ZR], !(ext[5] & 0x04)); - if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) { - input_report_key(wdata->extension.input, - wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT], - !(ext[1] & 0x01)); - input_report_key(wdata->extension.input, - wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP], - !(ext[0] & 0x01)); - } else { + if (!wiimote_dpad_as_analog) { input_report_key(wdata->extension.input, - wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT], - !(ext[5] & 0x02)); + wiimod_classic_map[WIIMOD_CLASSIC_KEY_RIGHT], + !(ext[4] & 0x80)); input_report_key(wdata->extension.input, - wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP], - !(ext[5] & 0x01)); + wiimod_classic_map[WIIMOD_CLASSIC_KEY_DOWN], + !(ext[4] & 0x40)); + + if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) { + input_report_key(wdata->extension.input, + wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT], + !(ext[1] & 0x01)); + input_report_key(wdata->extension.input, + wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP], + !(ext[0] & 0x01)); + } else { + input_report_key(wdata->extension.input, + wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT], + !(ext[5] & 0x02)); + input_report_key(wdata->extension.input, + wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP], + !(ext[5] & 0x01)); + } } input_sync(wdata->extension.input); diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h index b2a26a0a8f122..ad4ff837f43ec 100644 --- a/drivers/hid/hid-wiimote.h +++ b/drivers/hid/hid-wiimote.h @@ -162,6 +162,8 @@ struct wiimote_data { struct work_struct init_worker; }; +extern bool wiimote_dpad_as_analog; + /* wiimote modules */ enum wiimod_module { -- GitLab From d378cdd0113878e3860f954d16dd3e91defb1492 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Tue, 26 May 2020 11:53:28 -0700 Subject: [PATCH 0045/1754] platform/chrome: cros_ec_debugfs: Control uptime information request When EC does not support uptime command (EC_CMD_GET_UPTIME_INFO), do not create the uptime sysfs entry point. User space application will not probe the file needlessly. The EC console log will not contain EC_CMD_GET_UPTIME_INFO anymore. Signed-off-by: Gwendal Grignou Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_debugfs.c | 24 +++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c index ecfada00e6c51..272c89837d745 100644 --- a/drivers/platform/chrome/cros_ec_debugfs.c +++ b/drivers/platform/chrome/cros_ec_debugfs.c @@ -242,6 +242,25 @@ static ssize_t cros_ec_pdinfo_read(struct file *file, read_buf, p - read_buf); } +static bool cros_ec_uptime_is_supported(struct cros_ec_device *ec_dev) +{ + struct { + struct cros_ec_command cmd; + struct ec_response_uptime_info resp; + } __packed msg = {}; + int ret; + + msg.cmd.command = EC_CMD_GET_UPTIME_INFO; + msg.cmd.insize = sizeof(msg.resp); + + ret = cros_ec_cmd_xfer_status(ec_dev, &msg.cmd); + if (ret == -EPROTO && msg.cmd.result == EC_RES_INVALID_COMMAND) + return false; + + /* Other errors maybe a transient error, do not rule about support. */ + return true; +} + static ssize_t cros_ec_uptime_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -444,8 +463,9 @@ static int cros_ec_debugfs_probe(struct platform_device *pd) debugfs_create_file("pdinfo", 0444, debug_info->dir, debug_info, &cros_ec_pdinfo_fops); - debugfs_create_file("uptime", 0444, debug_info->dir, debug_info, - &cros_ec_uptime_fops); + if (cros_ec_uptime_is_supported(ec->ec_dev)) + debugfs_create_file("uptime", 0444, debug_info->dir, debug_info, + &cros_ec_uptime_fops); debugfs_create_x32("last_resume_result", 0444, debug_info->dir, &ec->ec_dev->last_resume_result); -- GitLab From f28adb41dab4a2795fd959750df57adffd2bb0be Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Tue, 19 May 2020 14:46:04 -0700 Subject: [PATCH 0046/1754] platform/chrome: cros_ec_typec: Register Type C switches Register Type C mux and switch handles, when provided via firmware bindings. These will allow the cros-ec-typec driver, and also alternate mode drivers to configure connected Muxes correctly, according to PD information retrieved from the Chrome OS EC. Signed-off-by: Prashant Malani Reviewed-by: Heikki Krogerus Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 66b8d21092afb..6e79f917314bf 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #define DRV_NAME "cros-ec-typec" @@ -25,6 +27,9 @@ struct cros_typec_port { struct typec_partner *partner; /* Port partner PD identity info. */ struct usb_pd_identity p_identity; + struct typec_switch *ori_sw; + struct typec_mux *mux; + struct usb_role_switch *role_sw; }; /* Platform-specific data for the Chrome OS EC Type C controller. */ @@ -84,6 +89,40 @@ static int cros_typec_parse_port_props(struct typec_capability *cap, return 0; } +static int cros_typec_get_switch_handles(struct cros_typec_port *port, + struct fwnode_handle *fwnode, + struct device *dev) +{ + port->mux = fwnode_typec_mux_get(fwnode, NULL); + if (IS_ERR(port->mux)) { + dev_dbg(dev, "Mux handle not found.\n"); + goto mux_err; + } + + port->ori_sw = fwnode_typec_switch_get(fwnode); + if (IS_ERR(port->ori_sw)) { + dev_dbg(dev, "Orientation switch handle not found.\n"); + goto ori_sw_err; + } + + port->role_sw = fwnode_usb_role_switch_get(fwnode); + if (IS_ERR(port->role_sw)) { + dev_dbg(dev, "USB role switch handle not found.\n"); + goto role_sw_err; + } + + return 0; + +role_sw_err: + usb_role_switch_put(port->role_sw); +ori_sw_err: + typec_switch_put(port->ori_sw); +mux_err: + typec_mux_put(port->mux); + + return -ENODEV; +} + static void cros_unregister_ports(struct cros_typec_data *typec) { int i; @@ -91,6 +130,9 @@ static void cros_unregister_ports(struct cros_typec_data *typec) for (i = 0; i < typec->num_ports; i++) { if (!typec->ports[i]) continue; + usb_role_switch_put(typec->ports[i]->role_sw); + typec_switch_put(typec->ports[i]->ori_sw); + typec_mux_put(typec->ports[i]->mux); typec_unregister_port(typec->ports[i]->port); } } @@ -153,6 +195,11 @@ static int cros_typec_init_ports(struct cros_typec_data *typec) ret = PTR_ERR(cros_port->port); goto unregister_ports; } + + ret = cros_typec_get_switch_handles(cros_port, fwnode, dev); + if (ret) + dev_dbg(dev, "No switch control for port %d\n", + port_num); } return 0; -- GitLab From e32b16c31339e37d3cdc814f2773b74c1dbf660c Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Thu, 28 May 2020 04:36:03 -0700 Subject: [PATCH 0047/1754] platform/chrome: cros_ec: Update mux state bits Sync the EC_CMD_USB_PD_MUX_INFO mux state bit fields with the Chrome EC code base. The newly added bit fields will be used for cros-ec-typec mux control. Signed-off-by: Prashant Malani Signed-off-by: Enric Balletbo i Serra --- include/linux/platform_data/cros_ec_commands.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h index 69210881ebac8..a7b0fc440c355 100644 --- a/include/linux/platform_data/cros_ec_commands.h +++ b/include/linux/platform_data/cros_ec_commands.h @@ -5207,11 +5207,15 @@ struct ec_params_usb_pd_mux_info { } __ec_align1; /* Flags representing mux state */ -#define USB_PD_MUX_USB_ENABLED BIT(0) /* USB connected */ -#define USB_PD_MUX_DP_ENABLED BIT(1) /* DP connected */ -#define USB_PD_MUX_POLARITY_INVERTED BIT(2) /* CC line Polarity inverted */ -#define USB_PD_MUX_HPD_IRQ BIT(3) /* HPD IRQ is asserted */ -#define USB_PD_MUX_HPD_LVL BIT(4) /* HPD level is asserted */ +#define USB_PD_MUX_NONE 0 /* Open switch */ +#define USB_PD_MUX_USB_ENABLED BIT(0) /* USB connected */ +#define USB_PD_MUX_DP_ENABLED BIT(1) /* DP connected */ +#define USB_PD_MUX_POLARITY_INVERTED BIT(2) /* CC line Polarity inverted */ +#define USB_PD_MUX_HPD_IRQ BIT(3) /* HPD IRQ is asserted */ +#define USB_PD_MUX_HPD_LVL BIT(4) /* HPD level is asserted */ +#define USB_PD_MUX_SAFE_MODE BIT(5) /* DP is in safe mode */ +#define USB_PD_MUX_TBT_COMPAT_ENABLED BIT(6) /* TBT compat enabled */ +#define USB_PD_MUX_USB4_ENABLED BIT(7) /* USB4 enabled */ struct ec_response_usb_pd_mux_info { uint8_t flags; /* USB_PD_MUX_*-encoded USB mux state */ -- GitLab From 2ee97377a0d459fb3c484e49fb471ac6add06441 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Thu, 28 May 2020 04:36:05 -0700 Subject: [PATCH 0048/1754] platform/chrome: cros_ec_typec: Register PD CTRL cmd v2 Recognize EC_CMD_USB_PD_CONTROL command version 2. This is necessary in order to process Type C mux information (like DP alt mode pin configuration), which is needed by the Type C Connector class API to configure the Type C muxes correctly While we are here, rename the struct member storing this version number from cmd_ver to pd_ctrl_ver, which more accurately reflects what is being stored. Also, slightly change the logic for calling cros_typec_set_port_params_*(). Now, v0 is called when pd_ctrl_ver is 0, and v1 is called otherwise. Signed-off-by: Prashant Malani Reviewed-by: Heikki Krogerus Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 6e79f917314bf..d69a88464cef0 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -37,7 +37,7 @@ struct cros_typec_data { struct device *dev; struct cros_ec_device *ec; int num_ports; - unsigned int cmd_ver; + unsigned int pd_ctrl_ver; /* Array of ports, indexed by port number. */ struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS]; struct notifier_block nb; @@ -340,7 +340,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) req.mux = USB_PD_CTRL_MUX_NO_CHANGE; req.swap = USB_PD_CTRL_SWAP_NONE; - ret = cros_typec_ec_command(typec, typec->cmd_ver, + ret = cros_typec_ec_command(typec, typec->pd_ctrl_ver, EC_CMD_USB_PD_CONTROL, &req, sizeof(req), &resp, sizeof(resp)); if (ret < 0) @@ -351,7 +351,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) dev_dbg(typec->dev, "Polarity %d: 0x%hhx\n", port_num, resp.polarity); dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state); - if (typec->cmd_ver == 1) + if (typec->pd_ctrl_ver != 0) cros_typec_set_port_params_v1(typec, port_num, &resp); else cros_typec_set_port_params_v0(typec, port_num, @@ -374,13 +374,15 @@ static int cros_typec_get_cmd_version(struct cros_typec_data *typec) if (ret < 0) return ret; - if (resp.version_mask & EC_VER_MASK(1)) - typec->cmd_ver = 1; + if (resp.version_mask & EC_VER_MASK(2)) + typec->pd_ctrl_ver = 2; + else if (resp.version_mask & EC_VER_MASK(1)) + typec->pd_ctrl_ver = 1; else - typec->cmd_ver = 0; + typec->pd_ctrl_ver = 0; dev_dbg(typec->dev, "PD Control has version mask 0x%hhx\n", - typec->cmd_ver); + typec->pd_ctrl_ver); return 0; } -- GitLab From 7e7def15fa4bc9d6a2fa3d1d379286591c249381 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Thu, 28 May 2020 04:36:07 -0700 Subject: [PATCH 0049/1754] platform/chrome: cros_ec_typec: Add USB mux control Add support to configure various Type C switches appropriately using the Type C connector class API, when the Chrome OS EC informs the AP that the USB operating mode has been entered. Signed-off-by: Prashant Malani Reviewed-by: Heikki Krogerus Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 100 +++++++++++++++++++++++- 1 file changed, 97 insertions(+), 3 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index d69a88464cef0..9ebf9abed16ff 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -30,6 +31,10 @@ struct cros_typec_port { struct typec_switch *ori_sw; struct typec_mux *mux; struct usb_role_switch *role_sw; + + /* Variables keeping track of switch state. */ + struct typec_mux_state state; + uint8_t mux_flags; }; /* Platform-specific data for the Chrome OS EC Type C controller. */ @@ -264,6 +269,23 @@ static int cros_typec_add_partner(struct cros_typec_data *typec, int port_num, return ret; } +static void cros_typec_remove_partner(struct cros_typec_data *typec, + int port_num) +{ + struct cros_typec_port *port = typec->ports[port_num]; + + port->state.alt = NULL; + port->state.mode = TYPEC_STATE_USB; + port->state.data = NULL; + + usb_role_switch_set_role(port->role_sw, USB_ROLE_NONE); + typec_switch_set(port->ori_sw, TYPEC_ORIENTATION_NONE); + typec_mux_set(port->mux, &port->state); + + typec_unregister_partner(port->partner); + port->partner = NULL; +} + static void cros_typec_set_port_params_v0(struct cros_typec_data *typec, int port_num, struct ec_response_usb_pd_control *resp) { @@ -317,16 +339,69 @@ static void cros_typec_set_port_params_v1(struct cros_typec_data *typec, } else { if (!typec->ports[port_num]->partner) return; + cros_typec_remove_partner(typec, port_num); + } +} + +static int cros_typec_get_mux_info(struct cros_typec_data *typec, int port_num, + struct ec_response_usb_pd_mux_info *resp) +{ + struct ec_params_usb_pd_mux_info req = { + .port = port_num, + }; + + return cros_typec_ec_command(typec, 0, EC_CMD_USB_PD_MUX_INFO, &req, + sizeof(req), resp, sizeof(*resp)); +} + +static int cros_typec_usb_safe_state(struct cros_typec_port *port) +{ + port->state.mode = TYPEC_STATE_SAFE; + + return typec_mux_set(port->mux, &port->state); +} - typec_unregister_partner(typec->ports[port_num]->partner); - typec->ports[port_num]->partner = NULL; +int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, + uint8_t mux_flags) +{ + struct cros_typec_port *port = typec->ports[port_num]; + enum typec_orientation orientation; + int ret; + + if (!port->partner) + return 0; + + if (mux_flags & USB_PD_MUX_POLARITY_INVERTED) + orientation = TYPEC_ORIENTATION_REVERSE; + else + orientation = TYPEC_ORIENTATION_NORMAL; + + ret = typec_switch_set(port->ori_sw, orientation); + if (ret) + return ret; + + port->state.alt = NULL; + port->state.mode = TYPEC_STATE_USB; + + if (mux_flags & USB_PD_MUX_SAFE_MODE) + ret = cros_typec_usb_safe_state(port); + else if (mux_flags & USB_PD_MUX_USB_ENABLED) + ret = typec_mux_set(port->mux, &port->state); + else { + dev_info(typec->dev, + "Unsupported mode requested, mux flags: %x\n", + mux_flags); + ret = -ENOTSUPP; } + + return ret; } static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) { struct ec_params_usb_pd_control req; struct ec_response_usb_pd_control_v1 resp; + struct ec_response_usb_pd_mux_info mux_resp; int ret; if (port_num < 0 || port_num >= typec->num_ports) { @@ -357,7 +432,26 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) cros_typec_set_port_params_v0(typec, port_num, (struct ec_response_usb_pd_control *) &resp); - return 0; + /* Update the switches if they exist, according to requested state */ + ret = cros_typec_get_mux_info(typec, port_num, &mux_resp); + if (ret < 0) { + dev_warn(typec->dev, + "Failed to get mux info for port: %d, err = %d\n", + port_num, ret); + return 0; + } + + /* No change needs to be made, let's exit early. */ + if (typec->ports[port_num]->mux_flags == mux_resp.flags) + return 0; + + typec->ports[port_num]->mux_flags = mux_resp.flags; + ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags); + if (ret) + dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); + + return usb_role_switch_set_role(typec->ports[port_num]->role_sw, + !!(resp.role & PD_CTRL_RESP_ROLE_DATA)); } static int cros_typec_get_cmd_version(struct cros_typec_data *typec) -- GitLab From 410457b99c7ea3e0cf8de1054e175ba3c2213d33 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Thu, 28 May 2020 04:36:10 -0700 Subject: [PATCH 0050/1754] platform/chrome: cros_ec_typec: Support DP alt mode Handle Chrome EC mux events to configure on-board muxes correctly while entering DP alternate mode. Since we don't surface SVID and VDO information regarding the DP alternate mode, configure the Type C muxes directly from the port driver. Later, when mode discovery information is correctly surfaced to the driver, we can register the DP alternate mode driver and let it handle the mux configuration. Also, modify the struct_typec_state state management to account for the addition of DP alternate mode. Signed-off-by: Prashant Malani Reviewed-by: Heikki Krogerus Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 90 ++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 10 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 9ebf9abed16ff..509fc761906bb 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -15,11 +15,18 @@ #include #include #include +#include #include #include #define DRV_NAME "cros-ec-typec" +/* Supported alt modes. */ +enum { + CROS_EC_ALTMODE_DP = 0, + CROS_EC_ALTMODE_MAX, +}; + /* Per port data. */ struct cros_typec_port { struct typec_port *port; @@ -35,6 +42,9 @@ struct cros_typec_port { /* Variables keeping track of switch state. */ struct typec_mux_state state; uint8_t mux_flags; + + /* Port alt modes. */ + struct typec_altmode p_altmode[CROS_EC_ALTMODE_MAX]; }; /* Platform-specific data for the Chrome OS EC Type C controller. */ @@ -142,6 +152,24 @@ static void cros_unregister_ports(struct cros_typec_data *typec) } } +/* + * Fake the alt mode structs until we actually start registering Type C port + * and partner alt modes. + */ +static void cros_typec_register_port_altmodes(struct cros_typec_data *typec, + int port_num) +{ + struct cros_typec_port *port = typec->ports[port_num]; + + /* All PD capable CrOS devices are assumed to support DP altmode. */ + port->p_altmode[CROS_EC_ALTMODE_DP].svid = USB_TYPEC_DP_SID; + port->p_altmode[CROS_EC_ALTMODE_DP].mode = USB_TYPEC_DP_MODE; + + port->state.alt = NULL; + port->state.mode = TYPEC_STATE_USB; + port->state.data = NULL; +} + static int cros_typec_init_ports(struct cros_typec_data *typec) { struct device *dev = typec->dev; @@ -205,6 +233,8 @@ static int cros_typec_init_ports(struct cros_typec_data *typec) if (ret) dev_dbg(dev, "No switch control for port %d\n", port_num); + + cros_typec_register_port_altmodes(typec, port_num); } return 0; @@ -361,8 +391,46 @@ static int cros_typec_usb_safe_state(struct cros_typec_port *port) return typec_mux_set(port->mux, &port->state); } +/* Spoof the VDOs that were likely communicated by the partner. */ +static int cros_typec_enable_dp(struct cros_typec_data *typec, + int port_num, + struct ec_response_usb_pd_control_v2 *pd_ctrl) +{ + struct cros_typec_port *port = typec->ports[port_num]; + struct typec_displayport_data dp_data; + int ret; + + if (typec->pd_ctrl_ver < 2) { + dev_err(typec->dev, + "PD_CTRL version too old: %d\n", typec->pd_ctrl_ver); + return -ENOTSUPP; + } + + /* Status VDO. */ + dp_data.status = DP_STATUS_ENABLED; + if (port->mux_flags & USB_PD_MUX_HPD_IRQ) + dp_data.status |= DP_STATUS_IRQ_HPD; + if (port->mux_flags & USB_PD_MUX_HPD_LVL) + dp_data.status |= DP_STATUS_HPD_STATE; + + /* Configuration VDO. */ + dp_data.conf = DP_CONF_SET_PIN_ASSIGN(pd_ctrl->dp_mode); + if (!port->state.alt) { + port->state.alt = &port->p_altmode[CROS_EC_ALTMODE_DP]; + ret = cros_typec_usb_safe_state(port); + if (ret) + return ret; + } + + port->state.data = &dp_data; + port->state.mode = TYPEC_MODAL_STATE(ffs(pd_ctrl->dp_mode)); + + return typec_mux_set(port->mux, &port->state); +} + int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, - uint8_t mux_flags) + uint8_t mux_flags, + struct ec_response_usb_pd_control_v2 *pd_ctrl) { struct cros_typec_port *port = typec->ports[port_num]; enum typec_orientation orientation; @@ -380,14 +448,15 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, if (ret) return ret; - port->state.alt = NULL; - port->state.mode = TYPEC_STATE_USB; - - if (mux_flags & USB_PD_MUX_SAFE_MODE) + if (mux_flags & USB_PD_MUX_DP_ENABLED) { + ret = cros_typec_enable_dp(typec, port_num, pd_ctrl); + } else if (mux_flags & USB_PD_MUX_SAFE_MODE) { ret = cros_typec_usb_safe_state(port); - else if (mux_flags & USB_PD_MUX_USB_ENABLED) + } else if (mux_flags & USB_PD_MUX_USB_ENABLED) { + port->state.alt = NULL; + port->state.mode = TYPEC_STATE_USB; ret = typec_mux_set(port->mux, &port->state); - else { + } else { dev_info(typec->dev, "Unsupported mode requested, mux flags: %x\n", mux_flags); @@ -400,7 +469,7 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) { struct ec_params_usb_pd_control req; - struct ec_response_usb_pd_control_v1 resp; + struct ec_response_usb_pd_control_v2 resp; struct ec_response_usb_pd_mux_info mux_resp; int ret; @@ -427,7 +496,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state); if (typec->pd_ctrl_ver != 0) - cros_typec_set_port_params_v1(typec, port_num, &resp); + cros_typec_set_port_params_v1(typec, port_num, + (struct ec_response_usb_pd_control_v1 *)&resp); else cros_typec_set_port_params_v0(typec, port_num, (struct ec_response_usb_pd_control *) &resp); @@ -446,7 +516,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) return 0; typec->ports[port_num]->mux_flags = mux_resp.flags; - ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags); + ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags, &resp); if (ret) dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); -- GitLab From b5fc06a10e7aea88c9a9efd4547a3aee44138e3e Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Fri, 12 Jun 2020 14:06:09 +0200 Subject: [PATCH 0051/1754] pinctrl: ingenic: Add ingenic,jz4725b-gpio compatible string Add a compatible string to support the GPIO chips on the JZ4725B SoC. There was already a compatible string for the pinctrl node, but not for the individual GPIO chip nodes. Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20200612120609.12730-1-paul@crapouillou.net Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-ingenic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c index 1da72438d6802..fc0d10411aa9e 100644 --- a/drivers/pinctrl/pinctrl-ingenic.c +++ b/drivers/pinctrl/pinctrl-ingenic.c @@ -2295,6 +2295,7 @@ static const struct regmap_config ingenic_pinctrl_regmap_config = { static const struct of_device_id ingenic_gpio_of_match[] __initconst = { { .compatible = "ingenic,jz4740-gpio", }, + { .compatible = "ingenic,jz4725b-gpio", }, { .compatible = "ingenic,jz4760-gpio", }, { .compatible = "ingenic,jz4770-gpio", }, { .compatible = "ingenic,jz4780-gpio", }, -- GitLab From d888229ef2fbc9557cbf953fa8e2687550f5308b Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Mon, 15 Jun 2020 14:54:06 +0200 Subject: [PATCH 0052/1754] pinctrl: stm32: don't print an error on probe deferral during clock get Change STM32 pinctrl driver to not print an error trace when probe is deferred due to clock resource. Probe defer issue (for clocks) could occur during bank registering when some banks have already been registered. In this case banks already registered should be released. To not waste time in this case, it is better to check first if all clocks are available before registering banks. Signed-off-by: Etienne Carriere Signed-off-by: Alexandre Torgue Link: https://lore.kernel.org/r/20200615125407.27632-2-alexandre.torgue@st.com Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index a657cd829ce6a..c15460ef2307b 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -1217,12 +1217,6 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, if (IS_ERR(bank->base)) return PTR_ERR(bank->base); - bank->clk = of_clk_get_by_name(np, NULL); - if (IS_ERR(bank->clk)) { - dev_err(dev, "failed to get clk (%ld)\n", PTR_ERR(bank->clk)); - return PTR_ERR(bank->clk); - } - err = clk_prepare(bank->clk); if (err) { dev_err(dev, "failed to prepare clk (%d)\n", err); @@ -1517,6 +1511,23 @@ int stm32_pctl_probe(struct platform_device *pdev) if (!pctl->banks) return -ENOMEM; + i = 0; + for_each_available_child_of_node(np, child) { + struct stm32_gpio_bank *bank = &pctl->banks[i]; + + if (of_property_read_bool(child, "gpio-controller")) { + bank->clk = of_clk_get_by_name(child, NULL); + if (IS_ERR(bank->clk)) { + if (PTR_ERR(bank->clk) != -EPROBE_DEFER) + dev_err(dev, + "failed to get clk (%ld)\n", + PTR_ERR(bank->clk)); + return PTR_ERR(bank->clk); + } + i++; + } + } + for_each_available_child_of_node(np, child) { if (of_property_read_bool(child, "gpio-controller")) { ret = stm32_gpiolib_register_bank(pctl, child); -- GitLab From 2254e77665d5af6186781319d8bc109ba03008c1 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Mon, 15 Jun 2020 14:54:07 +0200 Subject: [PATCH 0053/1754] pinctrl: stm32: defer probe if reset resource is not yet ready Defer probe when pin controller reset is defined in the system resources but not yet probed. Signed-off-by: Etienne Carriere Signed-off-by: Alexandre Torgue Link: https://lore.kernel.org/r/20200615125407.27632-3-alexandre.torgue@st.com Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index c15460ef2307b..162535e7c94dd 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -84,6 +84,7 @@ struct stm32_pinctrl_group { struct stm32_gpio_bank { void __iomem *base; struct clk *clk; + struct reset_control *rstc; spinlock_t lock; struct gpio_chip gpio_chip; struct pinctrl_gpio_range range; @@ -1202,13 +1203,11 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct of_phandle_args args; struct device *dev = pctl->dev; struct resource res; - struct reset_control *rstc; int npins = STM32_GPIO_PINS_PER_BANK; int bank_nr, err; - rstc = of_reset_control_get_exclusive(np, NULL); - if (!IS_ERR(rstc)) - reset_control_deassert(rstc); + if (!IS_ERR(bank->rstc)) + reset_control_deassert(bank->rstc); if (of_address_to_resource(np, 0, &res)) return -ENODEV; @@ -1516,6 +1515,11 @@ int stm32_pctl_probe(struct platform_device *pdev) struct stm32_gpio_bank *bank = &pctl->banks[i]; if (of_property_read_bool(child, "gpio-controller")) { + bank->rstc = of_reset_control_get_exclusive(child, + NULL); + if (PTR_ERR(bank->rstc) == -EPROBE_DEFER) + return -EPROBE_DEFER; + bank->clk = of_clk_get_by_name(child, NULL); if (IS_ERR(bank->clk)) { if (PTR_ERR(bank->clk) != -EPROBE_DEFER) -- GitLab From d9665bb82269f0f2bc18b73f074754e452bb3767 Mon Sep 17 00:00:00 2001 From: Alexandre Torgue Date: Mon, 15 Jun 2020 14:59:50 +0200 Subject: [PATCH 0054/1754] pinctrl: stm32: return proper error code in pin_config_set ".pin_config_set" or ".pin_config_group_set" can be called with a configuration not supported (i.e. PIN_CONFIG_PERSIST_STATE). In this case, it is more suitable to return -ENOTSUPP instead of -EINVAL. Signed-off-by: Alexandre Torgue Link: https://lore.kernel.org/r/20200615125951.28008-2-alexandre.torgue@st.com Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index 162535e7c94dd..cdf6b01d1956f 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -1085,7 +1085,7 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev, ret = stm32_pmx_gpio_set_direction(pctldev, range, pin, false); break; default: - ret = -EINVAL; + ret = -ENOTSUPP; } return ret; -- GitLab From b1a05ba9ae8cf6592e1d1f3e7b03bf8e5863f75f Mon Sep 17 00:00:00 2001 From: Alexandre Torgue Date: Mon, 15 Jun 2020 14:59:51 +0200 Subject: [PATCH 0055/1754] pinctrl: stm32: add possibility to configure pins individually Adds the possibility to configure a single pin through the gpiolib (i.e: to set PULL_UP/PULL_DOWN config). Mutex behavior is slightly changed to avoid a deadlock when pin_config_set is called (in this case pctldev->mutex is already taken). Signed-off-by: Alexandre Torgue Link: https://lore.kernel.org/r/20200615125951.28008-3-alexandre.torgue@st.com Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index cdf6b01d1956f..faf2660298f5c 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -303,6 +303,7 @@ static const struct gpio_chip stm32_gpio_template = { .direction_output = stm32_gpio_direction_output, .to_irq = stm32_gpio_to_irq, .get_direction = stm32_gpio_get_direction, + .set_config = gpiochip_generic_config, }; static void stm32_gpio_irq_trigger(struct irq_data *d) @@ -1052,7 +1053,7 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev, struct stm32_gpio_bank *bank; int offset, ret = 0; - range = pinctrl_find_gpio_range_from_pin(pctldev, pin); + range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin); if (!range) { dev_err(pctl->dev, "No gpio range defined.\n"); return -EINVAL; @@ -1110,9 +1111,11 @@ static int stm32_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group, int i, ret; for (i = 0; i < num_configs; i++) { + mutex_lock(&pctldev->mutex); ret = stm32_pconf_parse_conf(pctldev, g->pin, pinconf_to_config_param(configs[i]), pinconf_to_config_argument(configs[i])); + mutex_unlock(&pctldev->mutex); if (ret < 0) return ret; @@ -1122,6 +1125,22 @@ static int stm32_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group, return 0; } +static int stm32_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *configs, unsigned int num_configs) +{ + int i, ret; + + for (i = 0; i < num_configs; i++) { + ret = stm32_pconf_parse_conf(pctldev, pin, + pinconf_to_config_param(configs[i]), + pinconf_to_config_argument(configs[i])); + if (ret < 0) + return ret; + } + + return 0; +} + static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned int pin) @@ -1187,10 +1206,10 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, } } - static const struct pinconf_ops stm32_pconf_ops = { .pin_config_group_get = stm32_pconf_group_get, .pin_config_group_set = stm32_pconf_group_set, + .pin_config_set = stm32_pconf_set, .pin_config_dbg_show = stm32_pconf_dbg_show, }; -- GitLab From 285e74ab4f94d921a56fcf66320b3cd65e35b6bc Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 14 Apr 2020 19:09:43 -0300 Subject: [PATCH 0056/1754] hwspinlock: Simplify Kconfig Every hwspinlock driver is expected to depend on the hwspinlock core, so it's possible to simplify the Kconfig, factoring out the HWSPINLOCK dependency. Reviewed-by: Baolin Wang Signed-off-by: Ezequiel Garcia Link: https://lore.kernel.org/r/20200414220943.6203-1-ezequiel@collabora.com Signed-off-by: Bjorn Andersson --- drivers/hwspinlock/Kconfig | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig index 826a1054100d0..32cd26352f381 100644 --- a/drivers/hwspinlock/Kconfig +++ b/drivers/hwspinlock/Kconfig @@ -6,9 +6,10 @@ menuconfig HWSPINLOCK bool "Hardware Spinlock drivers" +if HWSPINLOCK + config HWSPINLOCK_OMAP tristate "OMAP Hardware Spinlock device" - depends on HWSPINLOCK depends on ARCH_OMAP4 || SOC_OMAP5 || SOC_DRA7XX || SOC_AM33XX || SOC_AM43XX || ARCH_K3 || COMPILE_TEST help Say y here to support the OMAP Hardware Spinlock device (firstly @@ -18,7 +19,6 @@ config HWSPINLOCK_OMAP config HWSPINLOCK_QCOM tristate "Qualcomm Hardware Spinlock device" - depends on HWSPINLOCK depends on ARCH_QCOM || COMPILE_TEST select MFD_SYSCON help @@ -30,7 +30,6 @@ config HWSPINLOCK_QCOM config HWSPINLOCK_SIRF tristate "SIRF Hardware Spinlock device" - depends on HWSPINLOCK depends on ARCH_SIRF || COMPILE_TEST help Say y here to support the SIRF Hardware Spinlock device, which @@ -43,7 +42,6 @@ config HWSPINLOCK_SIRF config HWSPINLOCK_SPRD tristate "SPRD Hardware Spinlock device" depends on ARCH_SPRD || COMPILE_TEST - depends on HWSPINLOCK help Say y here to support the SPRD Hardware Spinlock device. @@ -52,7 +50,6 @@ config HWSPINLOCK_SPRD config HWSPINLOCK_STM32 tristate "STM32 Hardware Spinlock device" depends on MACH_STM32MP157 || COMPILE_TEST - depends on HWSPINLOCK help Say y here to support the STM32 Hardware Spinlock device. @@ -60,7 +57,6 @@ config HWSPINLOCK_STM32 config HSEM_U8500 tristate "STE Hardware Semaphore functionality" - depends on HWSPINLOCK depends on ARCH_U8500 || COMPILE_TEST help Say y here to support the STE Hardware Semaphore functionality, which @@ -68,3 +64,5 @@ config HSEM_U8500 SoC. If unsure, say N. + +endif # HWSPINLOCK -- GitLab From 4e7293e3a2a367d0935925988acfd941549ce489 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 9 Jun 2020 21:24:44 +0300 Subject: [PATCH 0057/1754] pinctrl: cherryview: Introduce chv_readl() helper There are plenty of places where we call readl(chv_padreg(pctrl, offset, ...)); Replace them with newly introduced chv_readl() helper chv_readl(pctrl, offset, ...); Signed-off-by: Andy Shevchenko Acked-by: Linus Walleij Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-cherryview.c | 71 +++++++++++----------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 8e3953a223d05..afff7c0fc33f9 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -610,6 +610,11 @@ static void __iomem *chv_padreg(struct chv_pinctrl *pctrl, unsigned int offset, return pctrl->regs + offset + reg; } +static u32 chv_readl(struct chv_pinctrl *pctrl, unsigned int pin, unsigned int offset) +{ + return readl(chv_padreg(pctrl, pin, offset)); +} + static void chv_writel(u32 value, void __iomem *reg) { writel(value, reg); @@ -620,10 +625,7 @@ static void chv_writel(u32 value, void __iomem *reg) /* When Pad Cfg is locked, driver can only change GPIOTXState or GPIORXState */ static bool chv_pad_locked(struct chv_pinctrl *pctrl, unsigned int offset) { - void __iomem *reg; - - reg = chv_padreg(pctrl, offset, CHV_PADCTRL1); - return readl(reg) & CHV_PADCTRL1_CFGLOCK; + return chv_readl(pctrl, offset, CHV_PADCTRL1) & CHV_PADCTRL1_CFGLOCK; } static int chv_get_groups_count(struct pinctrl_dev *pctldev) @@ -661,8 +663,8 @@ static void chv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, raw_spin_lock_irqsave(&chv_lock, flags); - ctrl0 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0)); - ctrl1 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL1)); + ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0); + ctrl1 = chv_readl(pctrl, offset, CHV_PADCTRL1); locked = chv_pad_locked(pctrl, offset); raw_spin_unlock_irqrestore(&chv_lock, flags); @@ -758,7 +760,7 @@ static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, mode &= ~PINMODE_INVERT_OE; reg = chv_padreg(pctrl, pin, CHV_PADCTRL0); - value = readl(reg); + value = chv_readl(pctrl, pin, CHV_PADCTRL0); /* Disable GPIO mode */ value &= ~CHV_PADCTRL0_GPIOEN; /* Set to desired mode */ @@ -768,7 +770,7 @@ static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, /* Update for invert_oe */ reg = chv_padreg(pctrl, pin, CHV_PADCTRL1); - value = readl(reg) & ~CHV_PADCTRL1_INVRXTX_MASK; + value = chv_readl(pctrl, pin, CHV_PADCTRL1) & ~CHV_PADCTRL1_INVRXTX_MASK; if (invert_oe) value |= CHV_PADCTRL1_INVRXTX_TXENABLE; chv_writel(value, reg); @@ -789,7 +791,7 @@ static void chv_gpio_clear_triggering(struct chv_pinctrl *pctrl, u32 value; reg = chv_padreg(pctrl, offset, CHV_PADCTRL1); - value = readl(reg); + value = chv_readl(pctrl, offset, CHV_PADCTRL1); value &= ~CHV_PADCTRL1_INTWAKECFG_MASK; value &= ~CHV_PADCTRL1_INVRXTX_MASK; chv_writel(value, reg); @@ -807,7 +809,7 @@ static int chv_gpio_request_enable(struct pinctrl_dev *pctldev, raw_spin_lock_irqsave(&chv_lock, flags); if (chv_pad_locked(pctrl, offset)) { - value = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0)); + value = chv_readl(pctrl, offset, CHV_PADCTRL0); if (!(value & CHV_PADCTRL0_GPIOEN)) { /* Locked so cannot enable */ raw_spin_unlock_irqrestore(&chv_lock, flags); @@ -828,7 +830,7 @@ static int chv_gpio_request_enable(struct pinctrl_dev *pctldev, chv_gpio_clear_triggering(pctrl, offset); reg = chv_padreg(pctrl, offset, CHV_PADCTRL0); - value = readl(reg); + value = chv_readl(pctrl, offset, CHV_PADCTRL0); /* * If the pin is in HiZ mode (both TX and RX buffers are @@ -877,7 +879,7 @@ static int chv_gpio_set_direction(struct pinctrl_dev *pctldev, raw_spin_lock_irqsave(&chv_lock, flags); - ctrl0 = readl(reg) & ~CHV_PADCTRL0_GPIOCFG_MASK; + ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0) & ~CHV_PADCTRL0_GPIOCFG_MASK; if (input) ctrl0 |= CHV_PADCTRL0_GPIOCFG_GPI << CHV_PADCTRL0_GPIOCFG_SHIFT; else @@ -910,8 +912,8 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin, u32 term; raw_spin_lock_irqsave(&chv_lock, flags); - ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0)); - ctrl1 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL1)); + ctrl0 = chv_readl(pctrl, pin, CHV_PADCTRL0); + ctrl1 = chv_readl(pctrl, pin, CHV_PADCTRL1); raw_spin_unlock_irqrestore(&chv_lock, flags); term = (ctrl0 & CHV_PADCTRL0_TERM_MASK) >> CHV_PADCTRL0_TERM_SHIFT; @@ -987,7 +989,7 @@ static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned int pin, u32 ctrl0, pull; raw_spin_lock_irqsave(&chv_lock, flags); - ctrl0 = readl(reg); + ctrl0 = chv_readl(pctrl, pin, CHV_PADCTRL0); switch (param) { case PIN_CONFIG_BIAS_DISABLE: @@ -1053,7 +1055,7 @@ static int chv_config_set_oden(struct chv_pinctrl *pctrl, unsigned int pin, u32 ctrl1; raw_spin_lock_irqsave(&chv_lock, flags); - ctrl1 = readl(reg); + ctrl1 = chv_readl(pctrl, pin, CHV_PADCTRL1); if (enable) ctrl1 |= CHV_PADCTRL1_ODEN; @@ -1175,7 +1177,7 @@ static int chv_gpio_get(struct gpio_chip *chip, unsigned int offset) u32 ctrl0, cfg; raw_spin_lock_irqsave(&chv_lock, flags); - ctrl0 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0)); + ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0); raw_spin_unlock_irqrestore(&chv_lock, flags); cfg = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK; @@ -1196,7 +1198,7 @@ static void chv_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) raw_spin_lock_irqsave(&chv_lock, flags); reg = chv_padreg(pctrl, offset, CHV_PADCTRL0); - ctrl0 = readl(reg); + ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0); if (value) ctrl0 |= CHV_PADCTRL0_GPIOTXSTATE; @@ -1215,7 +1217,7 @@ static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) unsigned long flags; raw_spin_lock_irqsave(&chv_lock, flags); - ctrl0 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0)); + ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0); raw_spin_unlock_irqrestore(&chv_lock, flags); direction = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK; @@ -1259,7 +1261,7 @@ static void chv_gpio_irq_ack(struct irq_data *d) raw_spin_lock(&chv_lock); - intr_line = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0)); + intr_line = chv_readl(pctrl, pin, CHV_PADCTRL0); intr_line &= CHV_PADCTRL0_INTSEL_MASK; intr_line >>= CHV_PADCTRL0_INTSEL_SHIFT; chv_writel(BIT(intr_line), pctrl->regs + CHV_INTSTAT); @@ -1277,7 +1279,7 @@ static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask) raw_spin_lock_irqsave(&chv_lock, flags); - intr_line = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0)); + intr_line = chv_readl(pctrl, pin, CHV_PADCTRL0); intr_line &= CHV_PADCTRL0_INTSEL_MASK; intr_line >>= CHV_PADCTRL0_INTSEL_SHIFT; @@ -1322,11 +1324,11 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d) u32 intsel, value; raw_spin_lock_irqsave(&chv_lock, flags); - intsel = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0)); + intsel = chv_readl(pctrl, pin, CHV_PADCTRL0); intsel &= CHV_PADCTRL0_INTSEL_MASK; intsel >>= CHV_PADCTRL0_INTSEL_SHIFT; - value = readl(chv_padreg(pctrl, pin, CHV_PADCTRL1)); + value = chv_readl(pctrl, pin, CHV_PADCTRL1); if (value & CHV_PADCTRL1_INTWAKECFG_LEVEL) handler = handle_level_irq; else @@ -1369,7 +1371,7 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type) if (!chv_pad_locked(pctrl, pin)) { void __iomem *reg = chv_padreg(pctrl, pin, CHV_PADCTRL1); - value = readl(reg); + value = chv_readl(pctrl, pin, CHV_PADCTRL1); value &= ~CHV_PADCTRL1_INTWAKECFG_MASK; value &= ~CHV_PADCTRL1_INVRXTX_MASK; @@ -1389,7 +1391,7 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type) chv_writel(value, reg); } - value = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0)); + value = chv_readl(pctrl, pin, CHV_PADCTRL0); value &= CHV_PADCTRL0_INTSEL_MASK; value >>= CHV_PADCTRL0_INTSEL_SHIFT; @@ -1487,7 +1489,7 @@ static void chv_init_irq_valid_mask(struct gpio_chip *chip, desc = &community->pins[i]; - intsel = readl(chv_padreg(pctrl, desc->number, CHV_PADCTRL0)); + intsel = chv_readl(pctrl, desc->number, CHV_PADCTRL0); intsel &= CHV_PADCTRL0_INTSEL_MASK; intsel >>= CHV_PADCTRL0_INTSEL_SHIFT; @@ -1721,7 +1723,6 @@ static int chv_pinctrl_suspend_noirq(struct device *dev) for (i = 0; i < pctrl->community->npins; i++) { const struct pinctrl_pin_desc *desc; struct chv_pin_context *ctx; - void __iomem *reg; desc = &pctrl->community->pins[i]; if (chv_pad_locked(pctrl, desc->number)) @@ -1729,11 +1730,10 @@ static int chv_pinctrl_suspend_noirq(struct device *dev) ctx = &pctrl->saved_pin_context[i]; - reg = chv_padreg(pctrl, desc->number, CHV_PADCTRL0); - ctx->padctrl0 = readl(reg) & ~CHV_PADCTRL0_GPIORXSTATE; + ctx->padctrl0 = chv_readl(pctrl, desc->number, CHV_PADCTRL0); + ctx->padctrl0 &= ~CHV_PADCTRL0_GPIORXSTATE; - reg = chv_padreg(pctrl, desc->number, CHV_PADCTRL1); - ctx->padctrl1 = readl(reg); + ctx->padctrl1 = chv_readl(pctrl, desc->number, CHV_PADCTRL1); } raw_spin_unlock_irqrestore(&chv_lock, flags); @@ -1770,19 +1770,20 @@ static int chv_pinctrl_resume_noirq(struct device *dev) /* Only restore if our saved state differs from the current */ reg = chv_padreg(pctrl, desc->number, CHV_PADCTRL0); - val = readl(reg) & ~CHV_PADCTRL0_GPIORXSTATE; + val = chv_readl(pctrl, desc->number, CHV_PADCTRL0); + val &= ~CHV_PADCTRL0_GPIORXSTATE; if (ctx->padctrl0 != val) { chv_writel(ctx->padctrl0, reg); dev_dbg(pctrl->dev, "restored pin %2u ctrl0 0x%08x\n", - desc->number, readl(reg)); + desc->number, chv_readl(pctrl, desc->number, CHV_PADCTRL0)); } reg = chv_padreg(pctrl, desc->number, CHV_PADCTRL1); - val = readl(reg); + val = chv_readl(pctrl, desc->number, CHV_PADCTRL1); if (ctx->padctrl1 != val) { chv_writel(ctx->padctrl1, reg); dev_dbg(pctrl->dev, "restored pin %2u ctrl1 0x%08x\n", - desc->number, readl(reg)); + desc->number, chv_readl(pctrl, desc->number, CHV_PADCTRL1)); } } -- GitLab From 99fd6512278e08a0fb264e3b83eccbbf0ff30967 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 9 Jun 2020 21:24:45 +0300 Subject: [PATCH 0058/1754] pinctrl: cherryview: Introduce helpers to IO with common registers Pin control device and effectively the single community in it has a set of common registers. It's good to have a helpers to IO on them. Signed-off-by: Andy Shevchenko Acked-by: Linus Walleij Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-cherryview.c | 39 ++++++++++++++-------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index afff7c0fc33f9..28ed2f3b42a12 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -598,6 +598,20 @@ static const struct chv_community *chv_communities[] = { */ static DEFINE_RAW_SPINLOCK(chv_lock); +static u32 chv_pctrl_readl(struct chv_pinctrl *pctrl, unsigned int offset) +{ + return readl(pctrl->regs + offset); +} + +static void chv_pctrl_writel(struct chv_pinctrl *pctrl, unsigned int offset, u32 value) +{ + void __iomem *reg = pctrl->regs + offset; + + /* Write and simple read back to confirm the bus transferring done */ + writel(value, reg); + readl(reg); +} + static void __iomem *chv_padreg(struct chv_pinctrl *pctrl, unsigned int offset, unsigned int reg) { @@ -1264,7 +1278,7 @@ static void chv_gpio_irq_ack(struct irq_data *d) intr_line = chv_readl(pctrl, pin, CHV_PADCTRL0); intr_line &= CHV_PADCTRL0_INTSEL_MASK; intr_line >>= CHV_PADCTRL0_INTSEL_SHIFT; - chv_writel(BIT(intr_line), pctrl->regs + CHV_INTSTAT); + chv_pctrl_writel(pctrl, CHV_INTSTAT, BIT(intr_line)); raw_spin_unlock(&chv_lock); } @@ -1283,12 +1297,12 @@ static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask) intr_line &= CHV_PADCTRL0_INTSEL_MASK; intr_line >>= CHV_PADCTRL0_INTSEL_SHIFT; - value = readl(pctrl->regs + CHV_INTMASK); + value = chv_pctrl_readl(pctrl, CHV_INTMASK); if (mask) value &= ~BIT(intr_line); else value |= BIT(intr_line); - chv_writel(value, pctrl->regs + CHV_INTMASK); + chv_pctrl_writel(pctrl, CHV_INTMASK, value); raw_spin_unlock_irqrestore(&chv_lock, flags); } @@ -1419,7 +1433,7 @@ static void chv_gpio_irq_handler(struct irq_desc *desc) chained_irq_enter(chip, desc); raw_spin_lock_irqsave(&chv_lock, flags); - pending = readl(pctrl->regs + CHV_INTSTAT); + pending = chv_pctrl_readl(pctrl, CHV_INTSTAT); raw_spin_unlock_irqrestore(&chv_lock, flags); for_each_set_bit(intr_line, &pending, pctrl->community->nirqs) { @@ -1514,12 +1528,11 @@ static int chv_gpio_irq_init_hw(struct gpio_chip *chip) * Mask all interrupts the community is able to generate * but leave the ones that can only generate GPEs unmasked. */ - chv_writel(GENMASK(31, pctrl->community->nirqs), - pctrl->regs + CHV_INTMASK); + chv_pctrl_writel(pctrl, CHV_INTMASK, GENMASK(31, pctrl->community->nirqs)); } /* Clear all interrupts */ - chv_writel(0xffff, pctrl->regs + CHV_INTSTAT); + chv_pctrl_writel(pctrl, CHV_INTSTAT, 0xffff); return 0; } @@ -1618,9 +1631,9 @@ static acpi_status chv_pinctrl_mmio_access_handler(u32 function, raw_spin_lock_irqsave(&chv_lock, flags); if (function == ACPI_WRITE) - chv_writel((u32)(*value), pctrl->regs + (u32)address); + chv_pctrl_writel(pctrl, address, *value); else if (function == ACPI_READ) - *value = readl(pctrl->regs + (u32)address); + *value = chv_pctrl_readl(pctrl, address); else ret = AE_BAD_PARAMETER; @@ -1718,7 +1731,7 @@ static int chv_pinctrl_suspend_noirq(struct device *dev) raw_spin_lock_irqsave(&chv_lock, flags); - pctrl->saved_intmask = readl(pctrl->regs + CHV_INTMASK); + pctrl->saved_intmask = chv_pctrl_readl(pctrl, CHV_INTMASK); for (i = 0; i < pctrl->community->npins; i++) { const struct pinctrl_pin_desc *desc; @@ -1754,7 +1767,7 @@ static int chv_pinctrl_resume_noirq(struct device *dev) * registers because we don't know in which state BIOS left them * upon exiting suspend. */ - chv_writel(0, pctrl->regs + CHV_INTMASK); + chv_pctrl_writel(pctrl, CHV_INTMASK, 0x0000); for (i = 0; i < pctrl->community->npins; i++) { const struct pinctrl_pin_desc *desc; @@ -1791,8 +1804,8 @@ static int chv_pinctrl_resume_noirq(struct device *dev) * Now that all pins are restored to known state, we can restore * the interrupt mask register as well. */ - chv_writel(0xffff, pctrl->regs + CHV_INTSTAT); - chv_writel(pctrl->saved_intmask, pctrl->regs + CHV_INTMASK); + chv_pctrl_writel(pctrl, CHV_INTSTAT, 0xffff); + chv_pctrl_writel(pctrl, CHV_INTMASK, pctrl->saved_intmask); raw_spin_unlock_irqrestore(&chv_lock, flags); -- GitLab From bfc8a4baec9377b3fdd2bbeafaf5a7f2c95b1151 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 9 Jun 2020 21:24:46 +0300 Subject: [PATCH 0059/1754] pinctrl: cherryview: Convert chv_writel() to use chv_padreg() chv_writel() is now solely used for cases where we write data to the PAD registers. In order to simplify callers, calculate register address inside chv_writel(). Signed-off-by: Andy Shevchenko Acked-by: Linus Walleij Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-cherryview.c | 48 ++++++++-------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 28ed2f3b42a12..1fc46dfb880ec 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -629,10 +629,12 @@ static u32 chv_readl(struct chv_pinctrl *pctrl, unsigned int pin, unsigned int o return readl(chv_padreg(pctrl, pin, offset)); } -static void chv_writel(u32 value, void __iomem *reg) +static void chv_writel(struct chv_pinctrl *pctrl, unsigned int pin, unsigned int offset, u32 value) { + void __iomem *reg = chv_padreg(pctrl, pin, offset); + + /* Write and simple read back to confirm the bus transferring done */ writel(value, reg); - /* simple readback to confirm the bus transferring done */ readl(reg); } @@ -758,7 +760,6 @@ static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, for (i = 0; i < grp->npins; i++) { int pin = grp->pins[i]; - void __iomem *reg; unsigned int mode; bool invert_oe; u32 value; @@ -773,21 +774,19 @@ static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, invert_oe = mode & PINMODE_INVERT_OE; mode &= ~PINMODE_INVERT_OE; - reg = chv_padreg(pctrl, pin, CHV_PADCTRL0); value = chv_readl(pctrl, pin, CHV_PADCTRL0); /* Disable GPIO mode */ value &= ~CHV_PADCTRL0_GPIOEN; /* Set to desired mode */ value &= ~CHV_PADCTRL0_PMODE_MASK; value |= mode << CHV_PADCTRL0_PMODE_SHIFT; - chv_writel(value, reg); + chv_writel(pctrl, pin, CHV_PADCTRL0, value); /* Update for invert_oe */ - reg = chv_padreg(pctrl, pin, CHV_PADCTRL1); value = chv_readl(pctrl, pin, CHV_PADCTRL1) & ~CHV_PADCTRL1_INVRXTX_MASK; if (invert_oe) value |= CHV_PADCTRL1_INVRXTX_TXENABLE; - chv_writel(value, reg); + chv_writel(pctrl, pin, CHV_PADCTRL1, value); dev_dbg(pctrl->dev, "configured pin %u mode %u OE %sinverted\n", pin, mode, invert_oe ? "" : "not "); @@ -801,14 +800,12 @@ static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, static void chv_gpio_clear_triggering(struct chv_pinctrl *pctrl, unsigned int offset) { - void __iomem *reg; u32 value; - reg = chv_padreg(pctrl, offset, CHV_PADCTRL1); value = chv_readl(pctrl, offset, CHV_PADCTRL1); value &= ~CHV_PADCTRL1_INTWAKECFG_MASK; value &= ~CHV_PADCTRL1_INVRXTX_MASK; - chv_writel(value, reg); + chv_writel(pctrl, offset, CHV_PADCTRL1, value); } static int chv_gpio_request_enable(struct pinctrl_dev *pctldev, @@ -817,7 +814,6 @@ static int chv_gpio_request_enable(struct pinctrl_dev *pctldev, { struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); unsigned long flags; - void __iomem *reg; u32 value; raw_spin_lock_irqsave(&chv_lock, flags); @@ -843,7 +839,6 @@ static int chv_gpio_request_enable(struct pinctrl_dev *pctldev, /* Disable interrupt generation */ chv_gpio_clear_triggering(pctrl, offset); - reg = chv_padreg(pctrl, offset, CHV_PADCTRL0); value = chv_readl(pctrl, offset, CHV_PADCTRL0); /* @@ -853,13 +848,12 @@ static int chv_gpio_request_enable(struct pinctrl_dev *pctldev, if ((value & CHV_PADCTRL0_GPIOCFG_MASK) == (CHV_PADCTRL0_GPIOCFG_HIZ << CHV_PADCTRL0_GPIOCFG_SHIFT)) { value &= ~CHV_PADCTRL0_GPIOCFG_MASK; - value |= CHV_PADCTRL0_GPIOCFG_GPI << - CHV_PADCTRL0_GPIOCFG_SHIFT; + value |= CHV_PADCTRL0_GPIOCFG_GPI << CHV_PADCTRL0_GPIOCFG_SHIFT; } /* Switch to a GPIO mode */ value |= CHV_PADCTRL0_GPIOEN; - chv_writel(value, reg); + chv_writel(pctrl, offset, CHV_PADCTRL0, value); } raw_spin_unlock_irqrestore(&chv_lock, flags); @@ -887,7 +881,6 @@ static int chv_gpio_set_direction(struct pinctrl_dev *pctldev, unsigned int offset, bool input) { struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - void __iomem *reg = chv_padreg(pctrl, offset, CHV_PADCTRL0); unsigned long flags; u32 ctrl0; @@ -898,7 +891,7 @@ static int chv_gpio_set_direction(struct pinctrl_dev *pctldev, ctrl0 |= CHV_PADCTRL0_GPIOCFG_GPI << CHV_PADCTRL0_GPIOCFG_SHIFT; else ctrl0 |= CHV_PADCTRL0_GPIOCFG_GPO << CHV_PADCTRL0_GPIOCFG_SHIFT; - chv_writel(ctrl0, reg); + chv_writel(pctrl, offset, CHV_PADCTRL0, ctrl0); raw_spin_unlock_irqrestore(&chv_lock, flags); @@ -998,7 +991,6 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin, static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned int pin, enum pin_config_param param, u32 arg) { - void __iomem *reg = chv_padreg(pctrl, pin, CHV_PADCTRL0); unsigned long flags; u32 ctrl0, pull; @@ -1055,7 +1047,7 @@ static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned int pin, return -EINVAL; } - chv_writel(ctrl0, reg); + chv_writel(pctrl, pin, CHV_PADCTRL0, ctrl0); raw_spin_unlock_irqrestore(&chv_lock, flags); return 0; @@ -1064,7 +1056,6 @@ static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned int pin, static int chv_config_set_oden(struct chv_pinctrl *pctrl, unsigned int pin, bool enable) { - void __iomem *reg = chv_padreg(pctrl, pin, CHV_PADCTRL1); unsigned long flags; u32 ctrl1; @@ -1076,7 +1067,7 @@ static int chv_config_set_oden(struct chv_pinctrl *pctrl, unsigned int pin, else ctrl1 &= ~CHV_PADCTRL1_ODEN; - chv_writel(ctrl1, reg); + chv_writel(pctrl, pin, CHV_PADCTRL1, ctrl1); raw_spin_unlock_irqrestore(&chv_lock, flags); return 0; @@ -1206,12 +1197,10 @@ static void chv_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { struct chv_pinctrl *pctrl = gpiochip_get_data(chip); unsigned long flags; - void __iomem *reg; u32 ctrl0; raw_spin_lock_irqsave(&chv_lock, flags); - reg = chv_padreg(pctrl, offset, CHV_PADCTRL0); ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0); if (value) @@ -1219,7 +1208,7 @@ static void chv_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) else ctrl0 &= ~CHV_PADCTRL0_GPIOTXSTATE; - chv_writel(ctrl0, reg); + chv_writel(pctrl, offset, CHV_PADCTRL0, ctrl0); raw_spin_unlock_irqrestore(&chv_lock, flags); } @@ -1383,8 +1372,6 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type) * Driver programs the IntWakeCfg bits and save the mapping. */ if (!chv_pad_locked(pctrl, pin)) { - void __iomem *reg = chv_padreg(pctrl, pin, CHV_PADCTRL1); - value = chv_readl(pctrl, pin, CHV_PADCTRL1); value &= ~CHV_PADCTRL1_INTWAKECFG_MASK; value &= ~CHV_PADCTRL1_INVRXTX_MASK; @@ -1402,7 +1389,7 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type) value |= CHV_PADCTRL1_INVRXTX_RXDATA; } - chv_writel(value, reg); + chv_writel(pctrl, pin, CHV_PADCTRL1, value); } value = chv_readl(pctrl, pin, CHV_PADCTRL0); @@ -1772,7 +1759,6 @@ static int chv_pinctrl_resume_noirq(struct device *dev) for (i = 0; i < pctrl->community->npins; i++) { const struct pinctrl_pin_desc *desc; const struct chv_pin_context *ctx; - void __iomem *reg; u32 val; desc = &pctrl->community->pins[i]; @@ -1782,19 +1768,17 @@ static int chv_pinctrl_resume_noirq(struct device *dev) ctx = &pctrl->saved_pin_context[i]; /* Only restore if our saved state differs from the current */ - reg = chv_padreg(pctrl, desc->number, CHV_PADCTRL0); val = chv_readl(pctrl, desc->number, CHV_PADCTRL0); val &= ~CHV_PADCTRL0_GPIORXSTATE; if (ctx->padctrl0 != val) { - chv_writel(ctx->padctrl0, reg); + chv_writel(pctrl, desc->number, CHV_PADCTRL0, ctx->padctrl0); dev_dbg(pctrl->dev, "restored pin %2u ctrl0 0x%08x\n", desc->number, chv_readl(pctrl, desc->number, CHV_PADCTRL0)); } - reg = chv_padreg(pctrl, desc->number, CHV_PADCTRL1); val = chv_readl(pctrl, desc->number, CHV_PADCTRL1); if (ctx->padctrl1 != val) { - chv_writel(ctx->padctrl1, reg); + chv_writel(pctrl, desc->number, CHV_PADCTRL1, ctx->padctrl1); dev_dbg(pctrl->dev, "restored pin %2u ctrl1 0x%08x\n", desc->number, chv_readl(pctrl, desc->number, CHV_PADCTRL1)); } -- GitLab From 42fecd55c772549b88ec10841b7f4ab2330c44b5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 9 Jun 2020 21:24:47 +0300 Subject: [PATCH 0060/1754] pinctrl: intel: Allow drivers to define total amount of IRQs per community Some of the pin control devices may not be capable to generate IRQ per each pin in the community. Allow individual drivers to define total amount of IRQs per community. Signed-off-by: Andy Shevchenko Acked-by: Linus Walleij Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-intel.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h index cc78c483518f5..0f01ef3fdfdd3 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.h +++ b/drivers/pinctrl/intel/pinctrl-intel.h @@ -103,6 +103,7 @@ enum { * @gpps: Pad groups if the controller has variable size pad groups * @ngpps: Number of pad groups in this community * @pad_map: Optional non-linear mapping of the pads + * @nirqs: Optional total number of IRQs this community can generate * @regs: Community specific common registers (reserved for core driver) * @pad_regs: Community specific pad registers (reserved for core driver) * @@ -127,6 +128,7 @@ struct intel_community { const struct intel_padgroup *gpps; size_t ngpps; const unsigned int *pad_map; + unsigned short nirqs; /* Reserved for the core driver */ void __iomem *regs; -- GitLab From c8f8f65ea8ebc50aba7ab9741b3d0343ddf63d7f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 9 Jun 2020 21:24:48 +0300 Subject: [PATCH 0061/1754] pinctrl: intel: Allow drivers to define ACPI address space ID Individual drivers may install ACPI OpRegion handlers based on address space ID which differs from community to community. Add special field in the struct intel_community for that purpose. Signed-off-by: Andy Shevchenko Acked-by: Linus Walleij Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-intel.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h index 0f01ef3fdfdd3..4e17308d33e94 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.h +++ b/drivers/pinctrl/intel/pinctrl-intel.h @@ -104,6 +104,7 @@ enum { * @ngpps: Number of pad groups in this community * @pad_map: Optional non-linear mapping of the pads * @nirqs: Optional total number of IRQs this community can generate + * @acpi_space_id: Optional address space ID for ACPI OpRegion handler * @regs: Community specific common registers (reserved for core driver) * @pad_regs: Community specific pad registers (reserved for core driver) * @@ -129,6 +130,7 @@ struct intel_community { size_t ngpps; const unsigned int *pad_map; unsigned short nirqs; + unsigned short acpi_space_id; /* Reserved for the core driver */ void __iomem *regs; -- GitLab From 293428f93260d45f712a2d9f895bc0def0b34a3d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 9 Jun 2020 21:24:49 +0300 Subject: [PATCH 0062/1754] pinctrl: cherryview: Re-use data structures from pinctrl-intel.h (part 3) We have some data structures duplicated across the drivers. Let's deduplicate them by using struct intel_pinctrl_soc_data, struct intel_community and struct intel_pinctrl_context that are being provided by pinctrl-intel.h. Signed-off-by: Andy Shevchenko Acked-by: Linus Walleij Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-cherryview.c | 266 +++++++++++---------- 1 file changed, 137 insertions(+), 129 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 1fc46dfb880ec..9ef246145bde3 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -2,7 +2,7 @@ /* * Cherryview/Braswell pinctrl driver * - * Copyright (C) 2014, Intel Corporation + * Copyright (C) 2014, 2020 Intel Corporation * Author: Mika Westerberg * * This driver is based on the original Cherryview GPIO driver by @@ -67,35 +67,7 @@ #define CHV_PADCTRL1_INTWAKECFG_BOTH 3 #define CHV_PADCTRL1_INTWAKECFG_LEVEL 4 -/** - * struct chv_community - A community specific configuration - * @uid: ACPI _UID used to match the community - * @pins: All pins in this community - * @npins: Number of pins - * @groups: All groups in this community - * @ngroups: Number of groups - * @functions: All functions in this community - * @nfunctions: Number of functions - * @gpps: Pad groups - * @ngpps: Number of pad groups in this community - * @nirqs: Total number of IRQs this community can generate - * @acpi_space_id: An address space ID for ACPI OpRegion handler - */ -struct chv_community { - const char *uid; - const struct pinctrl_pin_desc *pins; - size_t npins; - const struct intel_pingroup *groups; - size_t ngroups; - const struct intel_function *functions; - size_t nfunctions; - const struct intel_padgroup *gpps; - size_t ngpps; - size_t nirqs; - acpi_adr_space_type acpi_space_id; -}; - -struct chv_pin_context { +struct intel_pad_context { u32 padctrl0; u32 padctrl1; }; @@ -107,13 +79,13 @@ struct chv_pin_context { * @pctldev: Pointer to the pin controller device * @chip: GPIO chip in this pin controller * @irqchip: IRQ chip in this pin controller - * @regs: MMIO registers + * @soc: Community specific pin configuration data + * @communities: All communities in this pin controller + * @ncommunities: Number of communities in this pin controller + * @context: Configuration saved over system sleep * @irq: Our parent irq - * @intr_lines: Stores mapping between 16 HW interrupt wires and GPIO - * offset (in GPIO number space) - * @community: Community this pinctrl instance represents + * @intr_lines: Mapping between 16 HW interrupt wires and GPIO offset (in GPIO number space) * @saved_intmask: Interrupt mask saved for system sleep - * @saved_pin_context: Pointer to a context of the pins saved for system sleep * * The first group in @groups is expected to contain all pins that can be * used as GPIOs. @@ -124,24 +96,34 @@ struct chv_pinctrl { struct pinctrl_dev *pctldev; struct gpio_chip chip; struct irq_chip irqchip; - void __iomem *regs; - unsigned int irq; + const struct intel_pinctrl_soc_data *soc; + struct intel_community *communities; + size_t ncommunities; + struct intel_pinctrl_context context; + int irq; + unsigned int intr_lines[16]; - const struct chv_community *community; u32 saved_intmask; - struct chv_pin_context *saved_pin_context; }; #define PINMODE_INVERT_OE BIT(15) #define PINMODE(m, i) ((m) | ((i) * PINMODE_INVERT_OE)) -#define CHV_GPP(start, end) \ +#define CHV_GPP(start, end) \ { \ .base = (start), \ .size = (end) - (start) + 1, \ } +#define CHV_COMMUNITY(g, i, a) \ + { \ + .gpps = (g), \ + .ngpps = ARRAY_SIZE(g), \ + .nirqs = (i), \ + .acpi_space_id = (a), \ + } + static const struct pinctrl_pin_desc southwest_pins[] = { PINCTRL_PIN(0, "FST_SPI_D2"), PINCTRL_PIN(1, "FST_SPI_D0"), @@ -303,7 +285,15 @@ static const struct intel_padgroup southwest_gpps[] = { CHV_GPP(90, 97), }; -static const struct chv_community southwest_community = { +/* + * Southwest community can generate GPIO interrupts only for the first 8 + * interrupts. The upper half (8-15) can only be used to trigger GPEs. + */ +static const struct intel_community southwest_communities[] = { + CHV_COMMUNITY(southwest_gpps, 8, 0x91), +}; + +static const struct intel_pinctrl_soc_data southwest_soc_data = { .uid = "1", .pins = southwest_pins, .npins = ARRAY_SIZE(southwest_pins), @@ -311,15 +301,8 @@ static const struct chv_community southwest_community = { .ngroups = ARRAY_SIZE(southwest_groups), .functions = southwest_functions, .nfunctions = ARRAY_SIZE(southwest_functions), - .gpps = southwest_gpps, - .ngpps = ARRAY_SIZE(southwest_gpps), - /* - * Southwest community can generate GPIO interrupts only for the - * first 8 interrupts. The upper half (8-15) can only be used to - * trigger GPEs. - */ - .nirqs = 8, - .acpi_space_id = 0x91, + .communities = southwest_communities, + .ncommunities = ARRAY_SIZE(southwest_communities), }; static const struct pinctrl_pin_desc north_pins[] = { @@ -396,19 +379,20 @@ static const struct intel_padgroup north_gpps[] = { CHV_GPP(60, 72), }; -static const struct chv_community north_community = { +/* + * North community can generate GPIO interrupts only for the first 8 + * interrupts. The upper half (8-15) can only be used to trigger GPEs. + */ +static const struct intel_community north_communities[] = { + CHV_COMMUNITY(north_gpps, 8, 0x92), +}; + +static const struct intel_pinctrl_soc_data north_soc_data = { .uid = "2", .pins = north_pins, .npins = ARRAY_SIZE(north_pins), - .gpps = north_gpps, - .ngpps = ARRAY_SIZE(north_gpps), - /* - * North community can generate GPIO interrupts only for the first - * 8 interrupts. The upper half (8-15) can only be used to trigger - * GPEs. - */ - .nirqs = 8, - .acpi_space_id = 0x92, + .communities = north_communities, + .ncommunities = ARRAY_SIZE(north_communities), }; static const struct pinctrl_pin_desc east_pins[] = { @@ -444,14 +428,16 @@ static const struct intel_padgroup east_gpps[] = { CHV_GPP(15, 26), }; -static const struct chv_community east_community = { +static const struct intel_community east_communities[] = { + CHV_COMMUNITY(east_gpps, 16, 0x93), +}; + +static const struct intel_pinctrl_soc_data east_soc_data = { .uid = "3", .pins = east_pins, .npins = ARRAY_SIZE(east_pins), - .gpps = east_gpps, - .ngpps = ARRAY_SIZE(east_gpps), - .nirqs = 16, - .acpi_space_id = 0x93, + .communities = east_communities, + .ncommunities = ARRAY_SIZE(east_communities), }; static const struct pinctrl_pin_desc southeast_pins[] = { @@ -566,7 +552,11 @@ static const struct intel_padgroup southeast_gpps[] = { CHV_GPP(75, 85), }; -static const struct chv_community southeast_community = { +static const struct intel_community southeast_communities[] = { + CHV_COMMUNITY(southeast_gpps, 16, 0x94), +}; + +static const struct intel_pinctrl_soc_data southeast_soc_data = { .uid = "4", .pins = southeast_pins, .npins = ARRAY_SIZE(southeast_pins), @@ -574,17 +564,16 @@ static const struct chv_community southeast_community = { .ngroups = ARRAY_SIZE(southeast_groups), .functions = southeast_functions, .nfunctions = ARRAY_SIZE(southeast_functions), - .gpps = southeast_gpps, - .ngpps = ARRAY_SIZE(southeast_gpps), - .nirqs = 16, - .acpi_space_id = 0x94, + .communities = southeast_communities, + .ncommunities = ARRAY_SIZE(southeast_communities), }; -static const struct chv_community *chv_communities[] = { - &southwest_community, - &north_community, - &east_community, - &southeast_community, +static const struct intel_pinctrl_soc_data *chv_soc_data[] = { + &southwest_soc_data, + &north_soc_data, + &east_soc_data, + &southeast_soc_data, + NULL }; /* @@ -600,12 +589,15 @@ static DEFINE_RAW_SPINLOCK(chv_lock); static u32 chv_pctrl_readl(struct chv_pinctrl *pctrl, unsigned int offset) { - return readl(pctrl->regs + offset); + const struct intel_community *community = &pctrl->communities[0]; + + return readl(community->regs + offset); } static void chv_pctrl_writel(struct chv_pinctrl *pctrl, unsigned int offset, u32 value) { - void __iomem *reg = pctrl->regs + offset; + const struct intel_community *community = &pctrl->communities[0]; + void __iomem *reg = community->regs + offset; /* Write and simple read back to confirm the bus transferring done */ writel(value, reg); @@ -615,13 +607,13 @@ static void chv_pctrl_writel(struct chv_pinctrl *pctrl, unsigned int offset, u32 static void __iomem *chv_padreg(struct chv_pinctrl *pctrl, unsigned int offset, unsigned int reg) { + const struct intel_community *community = &pctrl->communities[0]; unsigned int family_no = offset / MAX_FAMILY_PAD_GPIO_NO; unsigned int pad_no = offset % MAX_FAMILY_PAD_GPIO_NO; - offset = FAMILY_PAD_REGS_OFF + FAMILY_PAD_REGS_SIZE * family_no + - GPIO_REGS_SIZE * pad_no; + offset = FAMILY_PAD_REGS_SIZE * family_no + GPIO_REGS_SIZE * pad_no; - return pctrl->regs + offset + reg; + return community->pad_regs + offset + reg; } static u32 chv_readl(struct chv_pinctrl *pctrl, unsigned int pin, unsigned int offset) @@ -648,7 +640,7 @@ static int chv_get_groups_count(struct pinctrl_dev *pctldev) { struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - return pctrl->community->ngroups; + return pctrl->soc->ngroups; } static const char *chv_get_group_name(struct pinctrl_dev *pctldev, @@ -656,7 +648,7 @@ static const char *chv_get_group_name(struct pinctrl_dev *pctldev, { struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - return pctrl->community->groups[group].name; + return pctrl->soc->groups[group].name; } static int chv_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group, @@ -664,8 +656,8 @@ static int chv_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group, { struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - *pins = pctrl->community->groups[group].pins; - *npins = pctrl->community->groups[group].npins; + *pins = pctrl->soc->groups[group].pins; + *npins = pctrl->soc->groups[group].npins; return 0; } @@ -713,7 +705,7 @@ static int chv_get_functions_count(struct pinctrl_dev *pctldev) { struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - return pctrl->community->nfunctions; + return pctrl->soc->nfunctions; } static const char *chv_get_function_name(struct pinctrl_dev *pctldev, @@ -721,7 +713,7 @@ static const char *chv_get_function_name(struct pinctrl_dev *pctldev, { struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - return pctrl->community->functions[function].name; + return pctrl->soc->functions[function].name; } static int chv_get_function_groups(struct pinctrl_dev *pctldev, @@ -731,8 +723,8 @@ static int chv_get_function_groups(struct pinctrl_dev *pctldev, { struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - *groups = pctrl->community->functions[function].groups; - *ngroups = pctrl->community->functions[function].ngroups; + *groups = pctrl->soc->functions[function].groups; + *ngroups = pctrl->soc->functions[function].ngroups; return 0; } @@ -744,7 +736,7 @@ static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned long flags; int i; - grp = &pctrl->community->groups[group]; + grp = &pctrl->soc->groups[group]; raw_spin_lock_irqsave(&chv_lock, flags); @@ -1412,6 +1404,7 @@ static void chv_gpio_irq_handler(struct irq_desc *desc) { struct gpio_chip *gc = irq_desc_get_handler_data(desc); struct chv_pinctrl *pctrl = gpiochip_get_data(gc); + const struct intel_community *community = &pctrl->communities[0]; struct irq_chip *chip = irq_desc_get_chip(desc); unsigned long pending; unsigned long flags; @@ -1423,7 +1416,7 @@ static void chv_gpio_irq_handler(struct irq_desc *desc) pending = chv_pctrl_readl(pctrl, CHV_INTSTAT); raw_spin_unlock_irqrestore(&chv_lock, flags); - for_each_set_bit(intr_line, &pending, pctrl->community->nirqs) { + for_each_set_bit(intr_line, &pending, community->nirqs) { unsigned int irq, offset; offset = pctrl->intr_lines[intr_line]; @@ -1480,15 +1473,15 @@ static void chv_init_irq_valid_mask(struct gpio_chip *chip, unsigned int ngpios) { struct chv_pinctrl *pctrl = gpiochip_get_data(chip); - const struct chv_community *community = pctrl->community; + const struct intel_community *community = &pctrl->communities[0]; int i; /* Do not add GPIOs that can only generate GPEs to the IRQ domain */ - for (i = 0; i < community->npins; i++) { + for (i = 0; i < pctrl->soc->npins; i++) { const struct pinctrl_pin_desc *desc; u32 intsel; - desc = &community->pins[i]; + desc = &pctrl->soc->pins[i]; intsel = chv_readl(pctrl, desc->number, CHV_PADCTRL0); intsel &= CHV_PADCTRL0_INTSEL_MASK; @@ -1502,6 +1495,7 @@ static void chv_init_irq_valid_mask(struct gpio_chip *chip, static int chv_gpio_irq_init_hw(struct gpio_chip *chip) { struct chv_pinctrl *pctrl = gpiochip_get_data(chip); + const struct intel_community *community = &pctrl->communities[0]; /* * The same set of machines in chv_no_valid_mask[] have incorrectly @@ -1515,7 +1509,7 @@ static int chv_gpio_irq_init_hw(struct gpio_chip *chip) * Mask all interrupts the community is able to generate * but leave the ones that can only generate GPEs unmasked. */ - chv_pctrl_writel(pctrl, CHV_INTMASK, GENMASK(31, pctrl->community->nirqs)); + chv_pctrl_writel(pctrl, CHV_INTMASK, GENMASK(31, community->nirqs)); } /* Clear all interrupts */ @@ -1527,7 +1521,7 @@ static int chv_gpio_irq_init_hw(struct gpio_chip *chip) static int chv_gpio_add_pin_ranges(struct gpio_chip *chip) { struct chv_pinctrl *pctrl = gpiochip_get_data(chip); - const struct chv_community *community = pctrl->community; + const struct intel_community *community = &pctrl->communities[0]; const struct intel_padgroup *gpp; int ret, i; @@ -1547,15 +1541,15 @@ static int chv_gpio_add_pin_ranges(struct gpio_chip *chip) static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq) { + const struct intel_community *community = &pctrl->communities[0]; const struct intel_padgroup *gpp; struct gpio_chip *chip = &pctrl->chip; bool need_valid_mask = !dmi_check_system(chv_no_valid_mask); - const struct chv_community *community = pctrl->community; int ret, i, irq_base; *chip = chv_gpio_chip; - chip->ngpio = community->pins[community->npins - 1].number + 1; + chip->ngpio = pctrl->soc->pins[pctrl->soc->npins - 1].number + 1; chip->label = dev_name(pctrl->dev); chip->add_pin_ranges = chv_gpio_add_pin_ranges; chip->parent = pctrl->dev; @@ -1581,7 +1575,7 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq) chip->irq.init_valid_mask = chv_init_irq_valid_mask; } else { irq_base = devm_irq_alloc_descs(pctrl->dev, -1, 0, - community->npins, NUMA_NO_NODE); + pctrl->soc->npins, NUMA_NO_NODE); if (irq_base < 0) { dev_err(pctrl->dev, "Failed to allocate IRQ numbers\n"); return irq_base; @@ -1631,6 +1625,10 @@ static acpi_status chv_pinctrl_mmio_access_handler(u32 function, static int chv_pinctrl_probe(struct platform_device *pdev) { + const struct intel_pinctrl_soc_data *soc_data = NULL; + const struct intel_pinctrl_soc_data **soc_table; + struct intel_community *community; + struct device *dev = &pdev->dev; struct chv_pinctrl *pctrl; struct acpi_device *adev; acpi_status status; @@ -1640,40 +1638,53 @@ static int chv_pinctrl_probe(struct platform_device *pdev) if (!adev) return -ENODEV; - pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL); - if (!pctrl) - return -ENOMEM; - - for (i = 0; i < ARRAY_SIZE(chv_communities); i++) - if (!strcmp(adev->pnp.unique_id, chv_communities[i]->uid)) { - pctrl->community = chv_communities[i]; + soc_table = (const struct intel_pinctrl_soc_data **)device_get_match_data(dev); + for (i = 0; soc_table[i]; i++) { + if (!strcmp(adev->pnp.unique_id, soc_table[i]->uid)) { + soc_data = soc_table[i]; break; } - if (i == ARRAY_SIZE(chv_communities)) + } + if (!soc_data) return -ENODEV; + pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL); + if (!pctrl) + return -ENOMEM; + pctrl->dev = &pdev->dev; + pctrl->soc = soc_data; + + pctrl->ncommunities = pctrl->soc->ncommunities; + pctrl->communities = devm_kmemdup(dev, pctrl->soc->communities, + pctrl->ncommunities * sizeof(*pctrl->communities), + GFP_KERNEL); + if (!pctrl->communities) + return -ENOMEM; + + community = &pctrl->communities[0]; + community->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(community->regs)) + return PTR_ERR(community->regs); + + community->pad_regs = community->regs + FAMILY_PAD_REGS_OFF; #ifdef CONFIG_PM_SLEEP - pctrl->saved_pin_context = devm_kcalloc(pctrl->dev, - pctrl->community->npins, sizeof(*pctrl->saved_pin_context), - GFP_KERNEL); - if (!pctrl->saved_pin_context) + pctrl->context.pads = devm_kcalloc(dev, pctrl->soc->npins, + sizeof(*pctrl->context.pads), + GFP_KERNEL); + if (!pctrl->context.pads) return -ENOMEM; #endif - pctrl->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(pctrl->regs)) - return PTR_ERR(pctrl->regs); - irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; pctrl->pctldesc = chv_pinctrl_desc; pctrl->pctldesc.name = dev_name(&pdev->dev); - pctrl->pctldesc.pins = pctrl->community->pins; - pctrl->pctldesc.npins = pctrl->community->npins; + pctrl->pctldesc.pins = pctrl->soc->pins; + pctrl->pctldesc.npins = pctrl->soc->npins; pctrl->pctldev = devm_pinctrl_register(&pdev->dev, &pctrl->pctldesc, pctrl); @@ -1687,7 +1698,7 @@ static int chv_pinctrl_probe(struct platform_device *pdev) return ret; status = acpi_install_address_space_handler(adev->handle, - pctrl->community->acpi_space_id, + community->acpi_space_id, chv_pinctrl_mmio_access_handler, NULL, pctrl); if (ACPI_FAILURE(status)) @@ -1701,9 +1712,10 @@ static int chv_pinctrl_probe(struct platform_device *pdev) static int chv_pinctrl_remove(struct platform_device *pdev) { struct chv_pinctrl *pctrl = platform_get_drvdata(pdev); + const struct intel_community *community = &pctrl->communities[0]; acpi_remove_address_space_handler(ACPI_COMPANION(&pdev->dev), - pctrl->community->acpi_space_id, + community->acpi_space_id, chv_pinctrl_mmio_access_handler); return 0; @@ -1720,16 +1732,14 @@ static int chv_pinctrl_suspend_noirq(struct device *dev) pctrl->saved_intmask = chv_pctrl_readl(pctrl, CHV_INTMASK); - for (i = 0; i < pctrl->community->npins; i++) { + for (i = 0; i < pctrl->soc->npins; i++) { const struct pinctrl_pin_desc *desc; - struct chv_pin_context *ctx; + struct intel_pad_context *ctx = &pctrl->context.pads[i]; - desc = &pctrl->community->pins[i]; + desc = &pctrl->soc->pins[i]; if (chv_pad_locked(pctrl, desc->number)) continue; - ctx = &pctrl->saved_pin_context[i]; - ctx->padctrl0 = chv_readl(pctrl, desc->number, CHV_PADCTRL0); ctx->padctrl0 &= ~CHV_PADCTRL0_GPIORXSTATE; @@ -1756,17 +1766,15 @@ static int chv_pinctrl_resume_noirq(struct device *dev) */ chv_pctrl_writel(pctrl, CHV_INTMASK, 0x0000); - for (i = 0; i < pctrl->community->npins; i++) { + for (i = 0; i < pctrl->soc->npins; i++) { const struct pinctrl_pin_desc *desc; - const struct chv_pin_context *ctx; + struct intel_pad_context *ctx = &pctrl->context.pads[i]; u32 val; - desc = &pctrl->community->pins[i]; + desc = &pctrl->soc->pins[i]; if (chv_pad_locked(pctrl, desc->number)) continue; - ctx = &pctrl->saved_pin_context[i]; - /* Only restore if our saved state differs from the current */ val = chv_readl(pctrl, desc->number, CHV_PADCTRL0); val &= ~CHV_PADCTRL0_GPIORXSTATE; @@ -1803,7 +1811,7 @@ static const struct dev_pm_ops chv_pinctrl_pm_ops = { }; static const struct acpi_device_id chv_pinctrl_acpi_match[] = { - { "INT33FF" }, + { "INT33FF", (kernel_ulong_t)chv_soc_data }, { } }; MODULE_DEVICE_TABLE(acpi, chv_pinctrl_acpi_match); -- GitLab From af7e3eeb84e27fcfd1f46a80f111c8c72c206776 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 12 Jun 2020 17:49:54 +0300 Subject: [PATCH 0063/1754] pinctrl: intel: Disable input and output buffer when switching to GPIO It's possible scenario that pin has been in different mode, while the respective GPIO register has a leftover output buffer enabled. In such case when we request GPIO it will switch to GPIO mode, and thus to output with unknown value, followed by switching to input mode. This can produce a glitch on the pin. Disable input and output buffer when switching to GPIO to avoid potential glitches. Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-intel.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 6a274e20d9269..9df5a0c0d416f 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -435,11 +435,20 @@ static void intel_gpio_set_gpio_mode(void __iomem *padcfg0) { u32 value; + value = readl(padcfg0); + /* Put the pad into GPIO mode */ - value = readl(padcfg0) & ~PADCFG0_PMODE_MASK; + value &= ~PADCFG0_PMODE_MASK; + value |= PADCFG0_PMODE_GPIO; + + /* Disable input and output buffers */ + value &= ~PADCFG0_GPIORXDIS; + value &= ~PADCFG0_GPIOTXDIS; + /* Disable SCI/SMI/NMI generation */ value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI); value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI); + writel(value, padcfg0); } @@ -1036,6 +1045,9 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type) intel_gpio_set_gpio_mode(reg); + /* Disable TX buffer and enable RX (this will be input) */ + __intel_gpio_set_direction(reg, true); + value = readl(reg); value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV); -- GitLab From f62cdde5483957fc28249a9fc691e892e6b38e85 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 12 Jun 2020 17:49:55 +0300 Subject: [PATCH 0064/1754] pinctrl: intel: Reduce scope of the lock In some cases lock covers unneeded calls and operations. Reduce scope of the lock in such cases. Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-intel.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 9df5a0c0d416f..d0b658ba21367 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -460,6 +460,8 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, void __iomem *padcfg0; unsigned long flags; + padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0); + raw_spin_lock_irqsave(&pctrl->lock, flags); if (!intel_pad_owned_by_host(pctrl, pin)) { @@ -472,8 +474,6 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, return 0; } - padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0); - /* * If pin is already configured in GPIO mode, we assume that * firmware provides correct settings. In such case we avoid @@ -503,11 +503,10 @@ static int intel_gpio_set_direction(struct pinctrl_dev *pctldev, void __iomem *padcfg0; unsigned long flags; - raw_spin_lock_irqsave(&pctrl->lock, flags); - padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0); - __intel_gpio_set_direction(padcfg0, input); + raw_spin_lock_irqsave(&pctrl->lock, flags); + __intel_gpio_set_direction(padcfg0, input); raw_spin_unlock_irqrestore(&pctrl->lock, flags); return 0; @@ -622,10 +621,11 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin, int ret = 0; u32 value; - raw_spin_lock_irqsave(&pctrl->lock, flags); - community = intel_get_community(pctrl, pin); padcfg1 = intel_get_padcfg(pctrl, pin, PADCFG1); + + raw_spin_lock_irqsave(&pctrl->lock, flags); + value = readl(padcfg1); switch (param) { -- GitLab From 86851bbce1a332b0658519386041fe430f4e9e39 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 12 Jun 2020 17:49:56 +0300 Subject: [PATCH 0065/1754] pinctrl: intel: Make use of IRQ_RETVAL() Instead of using bitwise operations against returned values, which is a bit fragile, convert IRQ handler to count amount of GPIO groups, where at least one interrupt happened, and convert it to returned value by IRQ_RETVAL() macro. Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-intel.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index d0b658ba21367..e05273a00ff23 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -1093,12 +1093,12 @@ static int intel_gpio_irq_wake(struct irq_data *d, unsigned int on) return 0; } -static irqreturn_t intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl, - const struct intel_community *community) +static int intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl, + const struct intel_community *community) { struct gpio_chip *gc = &pctrl->chip; - irqreturn_t ret = IRQ_NONE; - int gpp; + unsigned int gpp; + int ret = 0; for (gpp = 0; gpp < community->ngpps; gpp++) { const struct intel_padgroup *padgrp = &community->gpps[gpp]; @@ -1118,9 +1118,9 @@ static irqreturn_t intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl, irq = irq_find_mapping(gc->irq.domain, padgrp->gpio_base + gpp_offset); generic_handle_irq(irq); - - ret |= IRQ_HANDLED; } + + ret += pending ? 1 : 0; } return ret; @@ -1130,16 +1130,16 @@ static irqreturn_t intel_gpio_irq(int irq, void *data) { const struct intel_community *community; struct intel_pinctrl *pctrl = data; - irqreturn_t ret = IRQ_NONE; - int i; + unsigned int i; + int ret = 0; /* Need to check all communities for pending interrupts */ for (i = 0; i < pctrl->ncommunities; i++) { community = &pctrl->communities[i]; - ret |= intel_gpio_community_irq_handler(pctrl, community); + ret += intel_gpio_community_irq_handler(pctrl, community); } - return ret; + return IRQ_RETVAL(ret); } static int intel_gpio_add_community_ranges(struct intel_pinctrl *pctrl, -- GitLab From bb2f43d49b72c8497dba53a44fc41bea03d4ab9e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 12 Jun 2020 17:49:57 +0300 Subject: [PATCH 0066/1754] pinctrl: intel: Get rid of redundant 'else' in intel_config_set_debounce() In a code like if (...) { ... goto label; } else { ... } the 'else' keyword is redundant. Get rid of it for better readability. Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-intel.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index e05273a00ff23..76b1b899a389b 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -719,12 +719,12 @@ static int intel_config_set_debounce(struct intel_pinctrl *pctrl, if (v < 3 || v > 15) { ret = -EINVAL; goto exit_unlock; - } else { - /* Enable glitch filter and debouncer */ - value0 |= PADCFG0_PREGFRXSEL; - value2 |= v << PADCFG2_DEBOUNCE_SHIFT; - value2 |= PADCFG2_DEBEN; } + + /* Enable glitch filter and debouncer */ + value0 |= PADCFG0_PREGFRXSEL; + value2 |= v << PADCFG2_DEBOUNCE_SHIFT; + value2 |= PADCFG2_DEBEN; } writel(value0, padcfg0); -- GitLab From 8fff0427d1b2b47469496dbcf3f846dab0cccc7b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 12 Jun 2020 17:49:58 +0300 Subject: [PATCH 0067/1754] pinctrl: intel: Drop the only label in the code for consistency Drop the only label in the code, i.e. in intel_config_set_debounce(), for consistency with the rest. In entire driver we use multipoint return. Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-intel.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 76b1b899a389b..2bcda48ea29a3 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -695,7 +695,6 @@ static int intel_config_set_debounce(struct intel_pinctrl *pctrl, void __iomem *padcfg0, *padcfg2; unsigned long flags; u32 value0, value2; - int ret = 0; padcfg2 = intel_get_padcfg(pctrl, pin, PADCFG2); if (!padcfg2) @@ -717,8 +716,8 @@ static int intel_config_set_debounce(struct intel_pinctrl *pctrl, v = order_base_2(debounce * NSEC_PER_USEC / DEBOUNCE_PERIOD_NSEC); if (v < 3 || v > 15) { - ret = -EINVAL; - goto exit_unlock; + raw_spin_unlock_irqrestore(&pctrl->lock, flags); + return -EINVAL; } /* Enable glitch filter and debouncer */ @@ -730,10 +729,9 @@ static int intel_config_set_debounce(struct intel_pinctrl *pctrl, writel(value0, padcfg0); writel(value2, padcfg2); -exit_unlock: raw_spin_unlock_irqrestore(&pctrl->lock, flags); - return ret; + return 0; } static int intel_config_set(struct pinctrl_dev *pctldev, unsigned int pin, -- GitLab From 81ab5542d7978f41a2b41c0f325b45980a478c6f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 12 Jun 2020 17:49:59 +0300 Subject: [PATCH 0068/1754] pinctrl: intel: Split intel_config_get() to three functions Split intel_config_get() to three functions, i.e. intel_config_get() and two helpers intel_config_get_pull() and intel_config_get_debounce() to be symmetrical with intel_config_set*(). Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-intel.c | 89 ++++++++++++++++++--------- 1 file changed, 61 insertions(+), 28 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 2bcda48ea29a3..d6ef012f2cc42 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -521,20 +521,17 @@ static const struct pinmux_ops intel_pinmux_ops = { .gpio_set_direction = intel_gpio_set_direction, }; -static int intel_config_get(struct pinctrl_dev *pctldev, unsigned int pin, - unsigned long *config) +static int intel_config_get_pull(struct intel_pinctrl *pctrl, unsigned int pin, + enum pin_config_param param, u32 *arg) { - struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - enum pin_config_param param = pinconf_to_config_param(*config); const struct intel_community *community; + void __iomem *padcfg1; u32 value, term; - u32 arg = 0; - - if (!intel_pad_owned_by_host(pctrl, pin)) - return -ENOTSUPP; community = intel_get_community(pctrl, pin); - value = readl(intel_get_padcfg(pctrl, pin, PADCFG1)); + padcfg1 = intel_get_padcfg(pctrl, pin, PADCFG1); + value = readl(padcfg1); + term = (value & PADCFG1_TERM_MASK) >> PADCFG1_TERM_SHIFT; switch (param) { @@ -549,16 +546,16 @@ static int intel_config_get(struct pinctrl_dev *pctldev, unsigned int pin, switch (term) { case PADCFG1_TERM_1K: - arg = 1000; + *arg = 1000; break; case PADCFG1_TERM_2K: - arg = 2000; + *arg = 2000; break; case PADCFG1_TERM_5K: - arg = 5000; + *arg = 5000; break; case PADCFG1_TERM_20K: - arg = 20000; + *arg = 20000; break; } @@ -572,35 +569,71 @@ static int intel_config_get(struct pinctrl_dev *pctldev, unsigned int pin, case PADCFG1_TERM_1K: if (!(community->features & PINCTRL_FEATURE_1K_PD)) return -EINVAL; - arg = 1000; + *arg = 1000; break; case PADCFG1_TERM_5K: - arg = 5000; + *arg = 5000; break; case PADCFG1_TERM_20K: - arg = 20000; + *arg = 20000; break; } break; - case PIN_CONFIG_INPUT_DEBOUNCE: { - void __iomem *padcfg2; - u32 v; + default: + return -EINVAL; + } + + return 0; +} - padcfg2 = intel_get_padcfg(pctrl, pin, PADCFG2); - if (!padcfg2) - return -ENOTSUPP; +static int intel_config_get_debounce(struct intel_pinctrl *pctrl, unsigned int pin, + enum pin_config_param param, u32 *arg) +{ + void __iomem *padcfg2; + unsigned long v; + u32 value2; - v = readl(padcfg2); - if (!(v & PADCFG2_DEBEN)) - return -EINVAL; + padcfg2 = intel_get_padcfg(pctrl, pin, PADCFG2); + if (!padcfg2) + return -ENOTSUPP; + + value2 = readl(padcfg2); + if (!(value2 & PADCFG2_DEBEN)) + return -EINVAL; + + v = (value2 & PADCFG2_DEBOUNCE_MASK) >> PADCFG2_DEBOUNCE_SHIFT; + *arg = BIT(v) * DEBOUNCE_PERIOD_NSEC / NSEC_PER_USEC; + + return 0; +} + +static int intel_config_get(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *config) +{ + struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + enum pin_config_param param = pinconf_to_config_param(*config); + u32 arg = 0; + int ret; - v = (v & PADCFG2_DEBOUNCE_MASK) >> PADCFG2_DEBOUNCE_SHIFT; - arg = BIT(v) * DEBOUNCE_PERIOD_NSEC / NSEC_PER_USEC; + if (!intel_pad_owned_by_host(pctrl, pin)) + return -ENOTSUPP; + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + case PIN_CONFIG_BIAS_PULL_UP: + case PIN_CONFIG_BIAS_PULL_DOWN: + ret = intel_config_get_pull(pctrl, pin, param, &arg); + if (ret) + return ret; + break; + + case PIN_CONFIG_INPUT_DEBOUNCE: + ret = intel_config_get_debounce(pctrl, pin, param, &arg); + if (ret) + return ret; break; - } default: return -ENOTSUPP; -- GitLab From e64fbfa51e8fc4eeca2d2bbf0d31a30a15734229 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 12 Jun 2020 17:50:00 +0300 Subject: [PATCH 0069/1754] pinctrl: intel: Protect IO in few call backs by lock Protect IO in intel_gpio_get_direction(), intel_gpio_community_irq_handler(), intel_config_get_debounce() and intel_config_get_pull() by lock. Even for simple readl() we better serialize IO to avoid potential problems. Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-intel.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index d6ef012f2cc42..35c88fcb75a24 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -526,11 +526,15 @@ static int intel_config_get_pull(struct intel_pinctrl *pctrl, unsigned int pin, { const struct intel_community *community; void __iomem *padcfg1; + unsigned long flags; u32 value, term; community = intel_get_community(pctrl, pin); padcfg1 = intel_get_padcfg(pctrl, pin, PADCFG1); + + raw_spin_lock_irqsave(&pctrl->lock, flags); value = readl(padcfg1); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); term = (value & PADCFG1_TERM_MASK) >> PADCFG1_TERM_SHIFT; @@ -592,6 +596,7 @@ static int intel_config_get_debounce(struct intel_pinctrl *pctrl, unsigned int p enum pin_config_param param, u32 *arg) { void __iomem *padcfg2; + unsigned long flags; unsigned long v; u32 value2; @@ -599,7 +604,9 @@ static int intel_config_get_debounce(struct intel_pinctrl *pctrl, unsigned int p if (!padcfg2) return -ENOTSUPP; + raw_spin_lock_irqsave(&pctrl->lock, flags); value2 = readl(padcfg2); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); if (!(value2 & PADCFG2_DEBEN)) return -EINVAL; @@ -934,6 +941,7 @@ static void intel_gpio_set(struct gpio_chip *chip, unsigned int offset, static int intel_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) { struct intel_pinctrl *pctrl = gpiochip_get_data(chip); + unsigned long flags; void __iomem *reg; u32 padcfg0; int pin; @@ -946,8 +954,9 @@ static int intel_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) if (!reg) return -EINVAL; + raw_spin_lock_irqsave(&pctrl->lock, flags); padcfg0 = readl(reg); - + raw_spin_unlock_irqrestore(&pctrl->lock, flags); if (padcfg0 & PADCFG0_PMODE_MASK) return -EINVAL; @@ -1134,12 +1143,17 @@ static int intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl, for (gpp = 0; gpp < community->ngpps; gpp++) { const struct intel_padgroup *padgrp = &community->gpps[gpp]; unsigned long pending, enabled, gpp_offset; + unsigned long flags; + + raw_spin_lock_irqsave(&pctrl->lock, flags); pending = readl(community->regs + community->is_offset + padgrp->reg_num * 4); enabled = readl(community->regs + community->ie_offset + padgrp->reg_num * 4); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); + /* Only interrupts that are enabled */ pending &= enabled; -- GitLab From d1bfd0229ec4deb53e61f95c050b524152fd0d9e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Jun 2020 21:14:49 +0300 Subject: [PATCH 0070/1754] pinctrl: intel: Make use of for_each_requested_gpio_in_range() Make use of for_each_requested_gpio_in_range() instead of home grown analogue. Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-intel.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 35c88fcb75a24..b64997b303e0c 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -1628,19 +1628,6 @@ static void intel_gpio_irq_init(struct intel_pinctrl *pctrl) } } -static u32 -intel_gpio_is_requested(struct gpio_chip *chip, int base, unsigned int size) -{ - u32 requested = 0; - unsigned int i; - - for (i = 0; i < size; i++) - if (gpiochip_is_requested(chip, base + i)) - requested |= BIT(i); - - return requested; -} - static bool intel_gpio_update_reg(void __iomem *reg, u32 mask, u32 value) { u32 curr, updated; @@ -1661,12 +1648,16 @@ static void intel_restore_hostown(struct intel_pinctrl *pctrl, unsigned int c, const struct intel_community *community = &pctrl->communities[c]; const struct intel_padgroup *padgrp = &community->gpps[gpp]; struct device *dev = pctrl->dev; - u32 requested; + const char *dummy; + u32 requested = 0; + unsigned int i; if (padgrp->gpio_base == INTEL_GPIO_BASE_NOMAP) return; - requested = intel_gpio_is_requested(&pctrl->chip, padgrp->gpio_base, padgrp->size); + for_each_requested_gpio_in_range(&pctrl->chip, i, padgrp->gpio_base, padgrp->size, dummy) + requested |= BIT(i); + if (!intel_gpio_update_reg(base + gpp * 4, requested, saved)) return; -- GitLab From f3e7d2812247342c415c76ba75fd79df57ee2a74 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Jun 2020 21:14:49 +0300 Subject: [PATCH 0071/1754] pinctrl: lynxpoint: Make use of for_each_requested_gpio() Make use of for_each_requested_gpio() instead of home grown analogue. Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-lynxpoint.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-lynxpoint.c b/drivers/pinctrl/intel/pinctrl-lynxpoint.c index a45b8f2182fd7..2a3af998b91ca 100644 --- a/drivers/pinctrl/intel/pinctrl-lynxpoint.c +++ b/drivers/pinctrl/intel/pinctrl-lynxpoint.c @@ -919,16 +919,17 @@ static int lp_gpio_runtime_resume(struct device *dev) static int lp_gpio_resume(struct device *dev) { struct intel_pinctrl *lg = dev_get_drvdata(dev); + struct gpio_chip *chip = &lg->chip; + const char *dummy; void __iomem *reg; int i; /* on some hardware suspend clears input sensing, re-enable it here */ - for (i = 0; i < lg->chip.ngpio; i++) { - if (gpiochip_is_requested(&lg->chip, i) != NULL) { - reg = lp_gpio_reg(&lg->chip, i, LP_CONFIG2); - iowrite32(ioread32(reg) & ~GPINDIS_BIT, reg); - } + for_each_requested_gpio(chip, i, dummy) { + reg = lp_gpio_reg(chip, i, LP_CONFIG2); + iowrite32(ioread32(reg) & ~GPINDIS_BIT, reg); } + return 0; } -- GitLab From 0472567ba86469eb9faabc917f4c3084c08cf0c2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 15 Jun 2020 17:30:15 +0300 Subject: [PATCH 0072/1754] pinctrl: lynxpoint: Introduce helpers to enable or disable input Introduce couple of helpers to enable or disable input. i.e. lp_gpio_enable_input() and lp_gpio_disable_input(). Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-lynxpoint.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-lynxpoint.c b/drivers/pinctrl/intel/pinctrl-lynxpoint.c index 2a3af998b91ca..003d795528e8a 100644 --- a/drivers/pinctrl/intel/pinctrl-lynxpoint.c +++ b/drivers/pinctrl/intel/pinctrl-lynxpoint.c @@ -386,6 +386,16 @@ static int lp_pinmux_set_mux(struct pinctrl_dev *pctldev, return 0; } +static void lp_gpio_enable_input(void __iomem *reg) +{ + iowrite32(ioread32(reg) & ~GPINDIS_BIT, reg); +} + +static void lp_gpio_disable_input(void __iomem *reg) +{ + iowrite32(ioread32(reg) | GPINDIS_BIT, reg); +} + static int lp_gpio_request_enable(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned int pin) @@ -411,7 +421,7 @@ static int lp_gpio_request_enable(struct pinctrl_dev *pctldev, } /* Enable input sensing */ - iowrite32(ioread32(conf2) & ~GPINDIS_BIT, conf2); + lp_gpio_enable_input(conf2); raw_spin_unlock_irqrestore(&lg->lock, flags); @@ -429,7 +439,7 @@ static void lp_gpio_disable_free(struct pinctrl_dev *pctldev, raw_spin_lock_irqsave(&lg->lock, flags); /* Disable input sensing */ - iowrite32(ioread32(conf2) | GPINDIS_BIT, conf2); + lp_gpio_disable_input(conf2); raw_spin_unlock_irqrestore(&lg->lock, flags); @@ -921,14 +931,11 @@ static int lp_gpio_resume(struct device *dev) struct intel_pinctrl *lg = dev_get_drvdata(dev); struct gpio_chip *chip = &lg->chip; const char *dummy; - void __iomem *reg; int i; /* on some hardware suspend clears input sensing, re-enable it here */ - for_each_requested_gpio(chip, i, dummy) { - reg = lp_gpio_reg(chip, i, LP_CONFIG2); - iowrite32(ioread32(reg) & ~GPINDIS_BIT, reg); - } + for_each_requested_gpio(chip, i, dummy) + lp_gpio_enable_input(lp_gpio_reg(chip, i, LP_CONFIG2)); return 0; } -- GitLab From e359a6f03ba3b35bc573c3993173a273041e4bc1 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 12 Jun 2020 17:50:05 +0300 Subject: [PATCH 0073/1754] pinctrl: lynxpoint: Drop no-op ACPI_PTR() call Since we dependent on ACPI, there is no need to use ACPI_PTR() which is a no-op in this case. Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-lynxpoint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/intel/pinctrl-lynxpoint.c b/drivers/pinctrl/intel/pinctrl-lynxpoint.c index 003d795528e8a..96589d01fe35e 100644 --- a/drivers/pinctrl/intel/pinctrl-lynxpoint.c +++ b/drivers/pinctrl/intel/pinctrl-lynxpoint.c @@ -959,7 +959,7 @@ static struct platform_driver lp_gpio_driver = { .driver = { .name = "lp_gpio", .pm = &lp_gpio_pm_ops, - .acpi_match_table = ACPI_PTR(lynxpoint_gpio_acpi_match), + .acpi_match_table = lynxpoint_gpio_acpi_match, }, }; -- GitLab From e87daf0bd83cb82576940d0a6e0e48b01d18c939 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 12 Jun 2020 17:50:06 +0300 Subject: [PATCH 0074/1754] pinctrl: baytrail: Drop no-op ACPI_PTR() call Since we dependent on ACPI, there is no need to use ACPI_PTR() which is a no-op in this case. Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-baytrail.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index 0ff7c55173da0..e3ceb3dfeabe4 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -1757,9 +1757,8 @@ static struct platform_driver byt_gpio_driver = { .driver = { .name = "byt_gpio", .pm = &byt_gpio_pm_ops, + .acpi_match_table = byt_gpio_acpi_match, .suppress_bind_attrs = true, - - .acpi_match_table = ACPI_PTR(byt_gpio_acpi_match), }, }; -- GitLab From 156abe2961601d60a8c2a60c6dc8dd6ce7adcdaf Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 6 Jun 2020 11:31:50 +0200 Subject: [PATCH 0075/1754] pinctrl: baytrail: Fix pin being driven low for a while on gpiod_get(..., GPIOD_OUT_HIGH) The pins on the Bay Trail SoC have separate input-buffer and output-buffer enable bits and a read of the level bit of the value register will always return the value from the input-buffer. The BIOS of a device may configure a pin in output-only mode, only enabling the output buffer, and write 1 to the level bit to drive the pin high. This 1 written to the level bit will be stored inside the data-latch of the output buffer. But a subsequent read of the value register will return 0 for the level bit because the input-buffer is disabled. This causes a read-modify-write as done by byt_gpio_set_direction() to write 0 to the level bit, driving the pin low! Before this commit byt_gpio_direction_output() relied on pinctrl_gpio_direction_output() to set the direction, followed by a call to byt_gpio_set() to apply the selected value. This causes the pin to go low between the pinctrl_gpio_direction_output() and byt_gpio_set() calls. Change byt_gpio_direction_output() to directly make the register modifications itself instead. Replacing the 2 subsequent writes to the value register with a single write. Note that the pinctrl code does not keep track internally of the direction, so not going through pinctrl_gpio_direction_output() is not an issue. This issue was noticed on a Trekstor SurfTab Twin 10.1. When the panel is already on at boot (no external monitor connected), then the i915 driver does a gpiod_get(..., GPIOD_OUT_HIGH) for the panel-enable GPIO. The temporarily going low of that GPIO was causing the panel to reset itself after which it would not show an image until it was turned off and back on again (until a full modeset was done on it). This commit fixes this. This commit also updates the byt_gpio_direction_input() to use direct register accesses instead of going through pinctrl_gpio_direction_input(), to keep it consistent with byt_gpio_direction_output(). Note for backporting, this commit depends on: commit e2b74419e5cc ("pinctrl: baytrail: Replace WARN with dev_info_once when setting direct-irq pin to output") Cc: stable@vger.kernel.org Fixes: 86e3ef812fe3 ("pinctrl: baytrail: Update gpio chip operations") Signed-off-by: Hans de Goede Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-baytrail.c | 67 +++++++++++++++++++----- 1 file changed, 53 insertions(+), 14 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index e3ceb3dfeabe4..a917a2df520ef 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -800,6 +800,21 @@ static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev, pm_runtime_put(vg->dev); } +static void byt_gpio_direct_irq_check(struct intel_pinctrl *vg, + unsigned int offset) +{ + void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); + + /* + * Before making any direction modifications, do a check if gpio is set + * for direct IRQ. On Bay Trail, setting GPIO to output does not make + * sense, so let's at least inform the caller before they shoot + * themselves in the foot. + */ + if (readl(conf_reg) & BYT_DIRECT_IRQ_EN) + dev_info_once(vg->dev, "Potential Error: Setting GPIO with direct_irq_en to output"); +} + static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev, struct pinctrl_gpio_range *range, unsigned int offset, @@ -807,7 +822,6 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev, { struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev); void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); - void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); unsigned long flags; u32 value; @@ -817,14 +831,8 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev, value &= ~BYT_DIR_MASK; if (input) value |= BYT_OUTPUT_EN; - else if (readl(conf_reg) & BYT_DIRECT_IRQ_EN) - /* - * Before making any direction modifications, do a check if gpio - * is set for direct IRQ. On baytrail, setting GPIO to output - * does not make sense, so let's at least inform the caller before - * they shoot themselves in the foot. - */ - dev_info_once(vg->dev, "Potential Error: Setting GPIO with direct_irq_en to output"); + else + byt_gpio_direct_irq_check(vg, offset); writel(value, val_reg); @@ -1165,19 +1173,50 @@ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) { - return pinctrl_gpio_direction_input(chip->base + offset); + struct intel_pinctrl *vg = gpiochip_get_data(chip); + void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); + unsigned long flags; + u32 reg; + + raw_spin_lock_irqsave(&byt_lock, flags); + + reg = readl(val_reg); + reg &= ~BYT_DIR_MASK; + reg |= BYT_OUTPUT_EN; + writel(reg, val_reg); + + raw_spin_unlock_irqrestore(&byt_lock, flags); + return 0; } +/* + * Note despite the temptation this MUST NOT be converted into a call to + * pinctrl_gpio_direction_output() + byt_gpio_set() that does not work this + * MUST be done as a single BYT_VAL_REG register write. + * See the commit message of the commit adding this comment for details. + */ static int byt_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int value) { - int ret = pinctrl_gpio_direction_output(chip->base + offset); + struct intel_pinctrl *vg = gpiochip_get_data(chip); + void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); + unsigned long flags; + u32 reg; - if (ret) - return ret; + raw_spin_lock_irqsave(&byt_lock, flags); + + byt_gpio_direct_irq_check(vg, offset); - byt_gpio_set(chip, offset, value); + reg = readl(val_reg); + reg &= ~BYT_DIR_MASK; + if (value) + reg |= BYT_LEVEL; + else + reg &= ~BYT_LEVEL; + writel(reg, val_reg); + + raw_spin_unlock_irqrestore(&byt_lock, flags); return 0; } -- GitLab From b3b4f8dffd38c2ec08d7eadaa57147a0ff6e3714 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 5 Jun 2020 23:23:14 +0300 Subject: [PATCH 0076/1754] pinctrl: sh-pfc: r8a77980: Add RPC pins, groups, and functions Add the RPC pins/groups/functions to the R8A77980 PFC driver. They can be used if an Octal-SPI flash or HyperFlash is connected. Based on the patch by Dmitry Shifrin . Signed-off-by: Sergei Shtylyov Link: https://lore.kernel.org/r/fd089d37-95bb-4ec9-282f-e04d7e5195e4@cogentembedded.com Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a77980.c | 76 +++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77980.c b/drivers/pinctrl/sh-pfc/pfc-r8a77980.c index 14fe4032a52da..1055f98534049 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a77980.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a77980.c @@ -1710,6 +1710,64 @@ static const unsigned int qspi1_data4_mux[] = { QSPI1_IO2_MARK, QSPI1_IO3_MARK }; +/* - RPC -------------------------------------------------------------------- */ +static const unsigned int rpc_clk1_pins[] = { + /* Octal-SPI flash: C/SCLK */ + RCAR_GP_PIN(5, 0), +}; +static const unsigned int rpc_clk1_mux[] = { + QSPI0_SPCLK_MARK, +}; +static const unsigned int rpc_clk2_pins[] = { + /* HyperFlash: CK, CK# */ + RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 6), +}; +static const unsigned int rpc_clk2_mux[] = { + QSPI0_SPCLK_MARK, QSPI1_SPCLK_MARK, +}; +static const unsigned int rpc_ctrl_pins[] = { + /* Octal-SPI flash: S#/CS, DQS */ + /* HyperFlash: CS#, RDS */ + RCAR_GP_PIN(5, 5), RCAR_GP_PIN(5, 11), +}; +static const unsigned int rpc_ctrl_mux[] = { + QSPI0_SSL_MARK, QSPI1_SSL_MARK, +}; +static const unsigned int rpc_data_pins[] = { + /* DQ[0:7] */ + RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 2), + RCAR_GP_PIN(5, 3), RCAR_GP_PIN(5, 4), + RCAR_GP_PIN(5, 7), RCAR_GP_PIN(5, 8), + RCAR_GP_PIN(5, 9), RCAR_GP_PIN(5, 10), +}; +static const unsigned int rpc_data_mux[] = { + QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, + QSPI0_IO2_MARK, QSPI0_IO3_MARK, + QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK, + QSPI1_IO2_MARK, QSPI1_IO3_MARK, +}; +static const unsigned int rpc_reset_pins[] = { + /* RPC_RESET# */ + RCAR_GP_PIN(5, 12), +}; +static const unsigned int rpc_reset_mux[] = { + RPC_RESET_N_MARK, +}; +static const unsigned int rpc_int_pins[] = { + /* RPC_INT# */ + RCAR_GP_PIN(5, 14), +}; +static const unsigned int rpc_int_mux[] = { + RPC_INT_N_MARK, +}; +static const unsigned int rpc_wp_pins[] = { + /* RPC_WP# */ + RCAR_GP_PIN(5, 13), +}; +static const unsigned int rpc_wp_mux[] = { + RPC_WP_N_MARK, +}; + /* - SCIF0 ------------------------------------------------------------------ */ static const unsigned int scif0_data_pins[] = { /* RX0, TX0 */ @@ -2126,6 +2184,13 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(qspi1_ctrl), SH_PFC_PIN_GROUP(qspi1_data2), SH_PFC_PIN_GROUP(qspi1_data4), + SH_PFC_PIN_GROUP(rpc_clk1), + SH_PFC_PIN_GROUP(rpc_clk2), + SH_PFC_PIN_GROUP(rpc_ctrl), + SH_PFC_PIN_GROUP(rpc_data), + SH_PFC_PIN_GROUP(rpc_reset), + SH_PFC_PIN_GROUP(rpc_int), + SH_PFC_PIN_GROUP(rpc_wp), SH_PFC_PIN_GROUP(scif0_data), SH_PFC_PIN_GROUP(scif0_clk), SH_PFC_PIN_GROUP(scif0_ctrl), @@ -2362,6 +2427,16 @@ static const char * const qspi1_groups[] = { "qspi1_data4", }; +static const char * const rpc_groups[] = { + "rpc_clk1", + "rpc_clk2", + "rpc_ctrl", + "rpc_data", + "rpc_reset", + "rpc_int", + "rpc_wp", +}; + static const char * const scif0_groups[] = { "scif0_data", "scif0_clk", @@ -2460,6 +2535,7 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(pwm4), SH_PFC_FUNCTION(qspi0), SH_PFC_FUNCTION(qspi1), + SH_PFC_FUNCTION(rpc), SH_PFC_FUNCTION(scif0), SH_PFC_FUNCTION(scif1), SH_PFC_FUNCTION(scif3), -- GitLab From b2fc9b4eb1d79c03fd78e50b810c2ea27178e1e3 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 19 Jun 2020 20:54:32 +0300 Subject: [PATCH 0077/1754] pinctrl: sh-pfc: r8a77970: Add RPC pins, groups, and functions Add the RPC pins/groups/functions to the R8A77970 PFC driver. They can be used if an Octal-SPI flash or HyperFlash is connected. Based on the patch by Dmitry Shifrin . Signed-off-by: Sergei Shtylyov Link: https://lore.kernel.org/r/3982785f-4fca-96f9-2b6a-a0d1828cb0ad@cogentembedded.com Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a77970.c | 76 +++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77970.c b/drivers/pinctrl/sh-pfc/pfc-r8a77970.c index 25e27b6bee893..9f7d9c9238fcc 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a77970.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a77970.c @@ -1416,6 +1416,64 @@ static const unsigned int qspi1_data4_mux[] = { QSPI1_IO2_MARK, QSPI1_IO3_MARK }; +/* - RPC -------------------------------------------------------------------- */ +static const unsigned int rpc_clk1_pins[] = { + /* Octal-SPI flash: C/SCLK */ + RCAR_GP_PIN(5, 0), +}; +static const unsigned int rpc_clk1_mux[] = { + QSPI0_SPCLK_MARK, +}; +static const unsigned int rpc_clk2_pins[] = { + /* HyperFlash: CK, CK# */ + RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 6), +}; +static const unsigned int rpc_clk2_mux[] = { + QSPI0_SPCLK_MARK, QSPI1_SPCLK_MARK, +}; +static const unsigned int rpc_ctrl_pins[] = { + /* Octal-SPI flash: S#/CS, DQS */ + /* HyperFlash: CS#, RDS */ + RCAR_GP_PIN(5, 5), RCAR_GP_PIN(5, 11), +}; +static const unsigned int rpc_ctrl_mux[] = { + QSPI0_SSL_MARK, QSPI1_SSL_MARK, +}; +static const unsigned int rpc_data_pins[] = { + /* DQ[0:7] */ + RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 2), + RCAR_GP_PIN(5, 3), RCAR_GP_PIN(5, 4), + RCAR_GP_PIN(5, 7), RCAR_GP_PIN(5, 8), + RCAR_GP_PIN(5, 9), RCAR_GP_PIN(5, 10), +}; +static const unsigned int rpc_data_mux[] = { + QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, + QSPI0_IO2_MARK, QSPI0_IO3_MARK, + QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK, + QSPI1_IO2_MARK, QSPI1_IO3_MARK, +}; +static const unsigned int rpc_reset_pins[] = { + /* RPC_RESET# */ + RCAR_GP_PIN(5, 12), +}; +static const unsigned int rpc_reset_mux[] = { + RPC_RESET_N_MARK, +}; +static const unsigned int rpc_int_pins[] = { + /* RPC_INT# */ + RCAR_GP_PIN(5, 14), +}; +static const unsigned int rpc_int_mux[] = { + RPC_INT_N_MARK, +}; +static const unsigned int rpc_wp_pins[] = { + /* RPC_WP# */ + RCAR_GP_PIN(5, 13), +}; +static const unsigned int rpc_wp_mux[] = { + RPC_WP_N_MARK, +}; + /* - SCIF Clock ------------------------------------------------------------- */ static const unsigned int scif_clk_a_pins[] = { /* SCIF_CLK */ @@ -1750,6 +1808,13 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(qspi1_ctrl), SH_PFC_PIN_GROUP(qspi1_data2), SH_PFC_PIN_GROUP(qspi1_data4), + SH_PFC_PIN_GROUP(rpc_clk1), + SH_PFC_PIN_GROUP(rpc_clk2), + SH_PFC_PIN_GROUP(rpc_ctrl), + SH_PFC_PIN_GROUP(rpc_data), + SH_PFC_PIN_GROUP(rpc_reset), + SH_PFC_PIN_GROUP(rpc_int), + SH_PFC_PIN_GROUP(rpc_wp), SH_PFC_PIN_GROUP(scif_clk_a), SH_PFC_PIN_GROUP(scif_clk_b), SH_PFC_PIN_GROUP(scif0_data), @@ -1954,6 +2019,16 @@ static const char * const qspi1_groups[] = { "qspi1_data4", }; +static const char * const rpc_groups[] = { + "rpc_clk1", + "rpc_clk2", + "rpc_ctrl", + "rpc_data", + "rpc_reset", + "rpc_int", + "rpc_wp", +}; + static const char * const scif_clk_groups[] = { "scif_clk_a", "scif_clk_b", @@ -2039,6 +2114,7 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(pwm4), SH_PFC_FUNCTION(qspi0), SH_PFC_FUNCTION(qspi1), + SH_PFC_FUNCTION(rpc), SH_PFC_FUNCTION(scif_clk), SH_PFC_FUNCTION(scif0), SH_PFC_FUNCTION(scif1), -- GitLab From 447b4eb6ceeb2d0d83d7f5aa248f2798f167cfda Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Fri, 19 Jun 2020 19:00:37 -0700 Subject: [PATCH 0078/1754] platform/chrome: cros_ec_typec: Make configure_mux static Since cros_typec_configure_mux() is only used in cros-ec-typec, it should be marked static. Fixes: 7e7def15fa4b ("platform/chrome: cros_ec_typec: Add USB mux control") Reported-by: kernel test robot Signed-off-by: Prashant Malani Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 509fc761906bb..1df1386f32e4f 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -428,9 +428,9 @@ static int cros_typec_enable_dp(struct cros_typec_data *typec, return typec_mux_set(port->mux, &port->state); } -int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, - uint8_t mux_flags, - struct ec_response_usb_pd_control_v2 *pd_ctrl) +static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, + uint8_t mux_flags, + struct ec_response_usb_pd_control_v2 *pd_ctrl) { struct cros_typec_port *port = typec->ports[port_num]; enum typec_orientation orientation; -- GitLab From 503a02b72d457f18eccf58296f9b50df6666d7fc Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 22 Jun 2020 18:56:15 +0300 Subject: [PATCH 0079/1754] pinctrl: merrifield: Update pin names in accordance with official list Some of the pin names were provided officially to the customers in different spelling. We update pin names in accordance with the official list. Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-merrifield.c | 46 +++++++++++----------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c index 04ca8ae95df83..2c213714df30d 100644 --- a/drivers/pinctrl/intel/pinctrl-merrifield.c +++ b/drivers/pinctrl/intel/pinctrl-merrifield.c @@ -135,7 +135,7 @@ static const struct pinctrl_pin_desc mrfld_pins[] = { PINCTRL_PIN(43, "GP83_SD_D3"), PINCTRL_PIN(44, "GP84_SD_LS_CLK_FB"), PINCTRL_PIN(45, "GP85_SD_LS_CMD_DIR"), - PINCTRL_PIN(46, "GP86_SD_LVL_D_DIR"), + PINCTRL_PIN(46, "GP86_SD_LS_D_DIR"), PINCTRL_PIN(47, "GP88_SD_LS_SEL"), PINCTRL_PIN(48, "GP87_SD_PD"), PINCTRL_PIN(49, "GP89_SD_WP"), @@ -171,28 +171,28 @@ static const struct pinctrl_pin_desc mrfld_pins[] = { PINCTRL_PIN(77, "GP42_I2S_2_RXD"), PINCTRL_PIN(78, "GP43_I2S_2_TXD"), /* Family 6: GP SSP (22 pins) */ - PINCTRL_PIN(79, "GP120_SPI_3_CLK"), - PINCTRL_PIN(80, "GP121_SPI_3_SS"), - PINCTRL_PIN(81, "GP122_SPI_3_RXD"), - PINCTRL_PIN(82, "GP123_SPI_3_TXD"), - PINCTRL_PIN(83, "GP102_SPI_4_CLK"), - PINCTRL_PIN(84, "GP103_SPI_4_SS_0"), - PINCTRL_PIN(85, "GP104_SPI_4_SS_1"), - PINCTRL_PIN(86, "GP105_SPI_4_SS_2"), - PINCTRL_PIN(87, "GP106_SPI_4_SS_3"), - PINCTRL_PIN(88, "GP107_SPI_4_RXD"), - PINCTRL_PIN(89, "GP108_SPI_4_TXD"), - PINCTRL_PIN(90, "GP109_SPI_5_CLK"), - PINCTRL_PIN(91, "GP110_SPI_5_SS_0"), - PINCTRL_PIN(92, "GP111_SPI_5_SS_1"), - PINCTRL_PIN(93, "GP112_SPI_5_SS_2"), - PINCTRL_PIN(94, "GP113_SPI_5_SS_3"), - PINCTRL_PIN(95, "GP114_SPI_5_RXD"), - PINCTRL_PIN(96, "GP115_SPI_5_TXD"), - PINCTRL_PIN(97, "GP116_SPI_6_CLK"), - PINCTRL_PIN(98, "GP117_SPI_6_SS"), - PINCTRL_PIN(99, "GP118_SPI_6_RXD"), - PINCTRL_PIN(100, "GP119_SPI_6_TXD"), + PINCTRL_PIN(79, "GP120_SPI_0_CLK"), + PINCTRL_PIN(80, "GP121_SPI_0_SS"), + PINCTRL_PIN(81, "GP122_SPI_0_RXD"), + PINCTRL_PIN(82, "GP123_SPI_0_TXD"), + PINCTRL_PIN(83, "GP102_SPI_1_CLK"), + PINCTRL_PIN(84, "GP103_SPI_1_SS0"), + PINCTRL_PIN(85, "GP104_SPI_1_SS1"), + PINCTRL_PIN(86, "GP105_SPI_1_SS2"), + PINCTRL_PIN(87, "GP106_SPI_1_SS3"), + PINCTRL_PIN(88, "GP107_SPI_1_RXD"), + PINCTRL_PIN(89, "GP108_SPI_1_TXD"), + PINCTRL_PIN(90, "GP109_SPI_2_CLK"), + PINCTRL_PIN(91, "GP110_SPI_2_SS0"), + PINCTRL_PIN(92, "GP111_SPI_2_SS1"), + PINCTRL_PIN(93, "GP112_SPI_2_SS2"), + PINCTRL_PIN(94, "GP113_SPI_2_SS3"), + PINCTRL_PIN(95, "GP114_SPI_2_RXD"), + PINCTRL_PIN(96, "GP115_SPI_2_TXD"), + PINCTRL_PIN(97, "GP116_SPI_3_CLK"), + PINCTRL_PIN(98, "GP117_SPI_3_SS"), + PINCTRL_PIN(99, "GP118_SPI_3_RXD"), + PINCTRL_PIN(100, "GP119_SPI_3_TXD"), /* Family 7: I2C (14 pins) */ PINCTRL_PIN(101, "GP19_I2C_1_SCL"), PINCTRL_PIN(102, "GP20_I2C_1_SDA"), -- GitLab From a1f8bc95c33e953e080f72be4b95176dacb423b0 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Mon, 20 Apr 2020 20:35:28 +0800 Subject: [PATCH 0080/1754] perf annotate: Remove unneeded conversion to bool The '>' expression itself is bool, no need to convert it to bool again. This fixes the following coccicheck warning: tools/perf/ui/browsers/annotate.c:212:30-35: WARNING: conversion to bool not needed here Signed-off-by: Jason Yan Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lore.kernel.org/lkml/20200420123528.11655-1-yanaijie@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/annotate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 9023267e56433..bd77825fd5a15 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -209,7 +209,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) ui_browser__mark_fused(browser, pcnt_width + 3 + notes->widths.addr + width, from - 1, - to > from ? true : false); + to > from); } } -- GitLab From 387ad33fe710758a8e1b860819a7452bceb4329a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:29 +0200 Subject: [PATCH 0081/1754] perf tools: Add fake pmu support Add a way to create a pmu event without the actual PMU being in place. This way we can test metrics defined for any processor. The interface is to define fake_pmu in struct parse_events_state data. It will be used only in tests via special interface function added in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-2-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 6 ++--- tools/perf/util/parse-events.h | 3 ++- tools/perf/util/parse-events.l | 8 +++++-- tools/perf/util/parse-events.y | 41 ++++++++++++++++++++++++++++++++-- 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 3decbb203846a..4eb7bd53d0481 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1450,7 +1450,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, fprintf(stderr, "' that may result in non-fatal errors\n"); } - pmu = perf_pmu__find(name); + pmu = parse_state->fake_pmu ?: perf_pmu__find(name); if (!pmu) { char *err_str; @@ -1483,7 +1483,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, } } - if (perf_pmu__check_alias(pmu, head_config, &info)) + if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, head_config, &info)) return -EINVAL; if (verbose > 1) { @@ -1516,7 +1516,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, if (pmu->default_config && get_config_chgs(pmu, head_config, &config_terms)) return -ENOMEM; - if (perf_pmu__config(pmu, &attr, head_config, parse_state->error)) { + if (!parse_state->fake_pmu && perf_pmu__config(pmu, &attr, head_config, parse_state->error)) { struct evsel_config_term *pos, *tmp; list_for_each_entry_safe(pos, tmp, &config_terms, list) { diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 1fe23a2f9b36e..bf79e1eac7d95 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -127,9 +127,10 @@ struct parse_events_state { int idx; int nr_groups; struct parse_events_error *error; - struct evlist *evlist; + struct evlist *evlist; struct list_head *terms; int stoken; + struct perf_pmu *fake_pmu; }; void parse_events__handle_error(struct parse_events_error *err, int idx, diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 002802e17059e..56912c9641f55 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -129,12 +129,16 @@ do { \ yyless(0); \ } while (0) -static int pmu_str_check(yyscan_t scanner) +static int pmu_str_check(yyscan_t scanner, struct parse_events_state *parse_state) { YYSTYPE *yylval = parse_events_get_lval(scanner); char *text = parse_events_get_text(scanner); yylval->str = strdup(text); + + if (parse_state->fake_pmu) + return PE_PMU_EVENT_FAKE; + switch (perf_pmu__parse_check(text)) { case PMU_EVENT_SYMBOL_PREFIX: return PE_PMU_EVENT_PRE; @@ -376,7 +380,7 @@ r{num_raw_hex} { return raw(yyscanner); } {modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } {bpf_object} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_OBJECT); } {bpf_source} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_SOURCE); } -{name} { return pmu_str_check(yyscanner); } +{name} { return pmu_str_check(yyscanner, _parse_state); } {name_tag} { return str(yyscanner, PE_NAME); } "/" { BEGIN(config); return '/'; } - { return '-'; } diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index acef87d9af588..b9fb91fdc5de9 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -69,7 +69,7 @@ static void inc_group_count(struct list_head *list, %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP %token PE_ERROR -%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT +%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE %token PE_ARRAY_ALL PE_ARRAY_RANGE %token PE_DRV_CFG_TERM %type PE_VALUE @@ -87,7 +87,7 @@ static void inc_group_count(struct list_head *list, %type PE_MODIFIER_EVENT %type PE_MODIFIER_BP %type PE_EVENT_NAME -%type PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT +%type PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE %type PE_DRV_CFG_TERM %destructor { free ($$); } %type event_term @@ -356,6 +356,43 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc YYABORT; $$ = list; } +| +PE_PMU_EVENT_FAKE sep_dc +{ + struct list_head *list; + int err; + + list = alloc_list(); + if (!list) + YYABORT; + + err = parse_events_add_pmu(_parse_state, list, $1, NULL, false, false); + free($1); + if (err < 0) { + free(list); + YYABORT; + } + $$ = list; +} +| +PE_PMU_EVENT_FAKE opt_pmu_config +{ + struct list_head *list; + int err; + + list = alloc_list(); + if (!list) + YYABORT; + + err = parse_events_add_pmu(_parse_state, list, $1, $2, false, false); + free($1); + parse_events_terms__delete($2); + if (err < 0) { + free(list); + YYABORT; + } + $$ = list; +} value_sym: PE_VALUE_SYM_HW -- GitLab From 34bacc9578de2893ab6301cea89ea001d8e4cf5b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:31 +0200 Subject: [PATCH 0082/1754] perf tests: Factor check_parse_id function Separating the generic part of check_parse_id function, so it can be used in following changes for the new test. Committer notes: Fix this error: tests/pmu-events.c:413:40: error: missing field 'idx' initializer [-Werror,-Wmissing-field-initializers] struct parse_events_error error = { 0 }; Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-4-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/pmu-events.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index ab64b4a4e2848..82fa69a60ec8a 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -390,9 +390,8 @@ static bool is_number(const char *str) return errno == 0 && end_ptr != str; } -static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) +static int check_parse_id(const char *id, struct parse_events_error *error) { - struct parse_events_error error; struct evlist *evlist; int ret; @@ -401,8 +400,18 @@ static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) return 0; evlist = evlist__new(); - memset(&error, 0, sizeof(error)); - ret = parse_events(evlist, id, &error); + if (!evlist) + return -ENOMEM; + ret = parse_events(evlist, id, error); + evlist__delete(evlist); + return ret; +} + +static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe) +{ + struct parse_events_error error = { .idx = 0, }; + + int ret = check_parse_id(id, &error); if (ret && same_cpu) { pr_warning("Parse event failed metric '%s' id '%s' expr '%s'\n", pe->metric_name, id, pe->metric_expr); @@ -413,7 +422,6 @@ static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) id, pe->metric_name, pe->metric_expr); ret = 0; } - evlist__delete(evlist); free(error.str); free(error.help); free(error.first_str); @@ -474,7 +482,7 @@ static int test_parsing(void) expr__add_id(&ctx, strdup(cur->key), k++); hashmap__for_each_entry((&ctx.ids), cur, bkt) { - if (check_parse_id(cur->key, map == cpus_map, + if (check_parse_cpu(cur->key, map == cpus_map, pe)) ret++; } -- GitLab From 3bf91aa5aa493b2ac24ffcfc93ffe861bf03685f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 3 Jun 2020 12:32:55 -0300 Subject: [PATCH 0083/1754] perf parse: Provide a way to pass a fake_pmu to parse_events() This is an alternative patch to what Jiri sent that instead of changing all callers to parse_events() for allowing to pass a fake_pmu, provide another function specifically for that. From Jiri's patch: This way it's possible to parse events from PMUs which are not present in the system. It's available only for testing purposes coming in following changes, so all the current users set fake_pmu argument as false. Based-on-a-patch-by: Jiri Olsa Link: http://lore.kernel.org/lkml/20200602214741.1218986-3-jolsa@kernel.org Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 15 ++++++++------- tools/perf/util/parse-events.h | 11 +++++++++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 4eb7bd53d0481..c4906a6a9f1af 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2088,15 +2088,16 @@ int parse_events_terms(struct list_head *terms, const char *str) return ret; } -int parse_events(struct evlist *evlist, const char *str, - struct parse_events_error *err) +int __parse_events(struct evlist *evlist, const char *str, + struct parse_events_error *err, struct perf_pmu *fake_pmu) { struct parse_events_state parse_state = { - .list = LIST_HEAD_INIT(parse_state.list), - .idx = evlist->core.nr_entries, - .error = err, - .evlist = evlist, - .stoken = PE_START_EVENTS, + .list = LIST_HEAD_INIT(parse_state.list), + .idx = evlist->core.nr_entries, + .error = err, + .evlist = evlist, + .stoken = PE_START_EVENTS, + .fake_pmu = fake_pmu, }; int ret; diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index bf79e1eac7d95..f0010095fc8c2 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -33,8 +33,15 @@ const char *event_type(int type); int parse_events_option(const struct option *opt, const char *str, int unset); int parse_events_option_new_evlist(const struct option *opt, const char *str, int unset); -int parse_events(struct evlist *evlist, const char *str, - struct parse_events_error *error); +int __parse_events(struct evlist *evlist, const char *str, struct parse_events_error *error, + struct perf_pmu *fake_pmu); + +static inline int parse_events(struct evlist *evlist, const char *str, + struct parse_events_error *err) +{ + return __parse_events(evlist, str, err, NULL); +} + int parse_events_terms(struct list_head *terms, const char *str); int parse_filter(const struct option *opt, const char *str, int unset); int exclude_perf(const struct option *opt, const char *arg, int unset); -- GitLab From e46fc8d9dd352c88fec49b140008958d2dc1efe1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 9 Jun 2020 13:23:24 -0300 Subject: [PATCH 0084/1754] perf pmu: Add a perf_pmu__fake object to use with __parse_events() When wanting to use the support in __parse_events() for fake pmus, just pass it. Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Jiri Olsa Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 2 ++ tools/perf/util/pmu.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 93fe72a9dc0b2..6d51042044fd1 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -26,6 +26,8 @@ #include "strbuf.h" #include "fncache.h" +struct perf_pmu perf_pmu__fake; + struct perf_pmu_format { char *name; int value; diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index f971d9aa4570a..44ccbdbb1c374 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -43,6 +43,8 @@ struct perf_pmu { struct list_head list; /* ELEM */ }; +extern struct perf_pmu perf_pmu__fake; + struct perf_pmu_info { const char *unit; const char *metric_expr; -- GitLab From e1c92a7fbbc5668510736624df3028accd6af0ea Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 3 Jun 2020 12:51:15 -0300 Subject: [PATCH 0085/1754] perf tests: Add another metric parsing test The test goes through all metrics compiled for arch within pmu events and try to parse them. This test is different from 'test_parsing' in that we go through all the events in the current arch, not just one defined for current CPU model. Using 'fake_pmu' to parse events which do not have PMUs defined in the system. Say there's bad change in ivybridge metrics file, like: - a/tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json + b/tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json @@ -8,7 +8,7 @@ - "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / (4 * (( + "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / / (4 * the test fails with (on my kabylake laptop): $ perf test 'Parsing of PMU event table metrics with fake PMUs' -v parsing 'idq_uops_not_delivered.core / / (4 * (( ( cpu_clk_unh... syntax error, line 1 expr__parse failed test child finished with -1 ... The test also defines its own list of metrics and tries to parse them. It's handy for developing. Committer notes: Testing it: $ perf test fake 10: PMU events : 10.4: Parsing of PMU event table metrics with fake PMUs : FAILED! $ perf test -v fake |& tail parsing '(unc_p_freq_trans_cycles / unc_p_clockticks) * 100.' parsing '(unc_m_power_channel_ppd / unc_m_clockticks) * 100.' parsing '(unc_m_power_critical_throttle_cycles / unc_m_clockticks) * 100.' parsing '(unc_m_power_self_refresh / unc_m_clockticks) * 100.' parsing 'idq_uops_not_delivered.core / * (4 * cycles)' syntax error expr__parse failed test child finished with -1 ---- end ---- PMU events subtest 4: FAILED! $ And fix this error: tests/pmu-events.c:437:40: error: missing field 'idx' initializer [-Werror,-Wmissing-field-initializers] struct parse_events_error error = { 0 }; Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-5-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/pmu-events.c | 117 +++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 3 deletions(-) diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index 82fa69a60ec8a..b66b021476ec4 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -390,7 +390,8 @@ static bool is_number(const char *str) return errno == 0 && end_ptr != str; } -static int check_parse_id(const char *id, struct parse_events_error *error) +static int check_parse_id(const char *id, struct parse_events_error *error, + struct perf_pmu *fake_pmu) { struct evlist *evlist; int ret; @@ -402,7 +403,7 @@ static int check_parse_id(const char *id, struct parse_events_error *error) evlist = evlist__new(); if (!evlist) return -ENOMEM; - ret = parse_events(evlist, id, error); + ret = __parse_events(evlist, id, error, fake_pmu); evlist__delete(evlist); return ret; } @@ -411,7 +412,7 @@ static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe) { struct parse_events_error error = { .idx = 0, }; - int ret = check_parse_id(id, &error); + int ret = check_parse_id(id, &error, NULL); if (ret && same_cpu) { pr_warning("Parse event failed metric '%s' id '%s' expr '%s'\n", pe->metric_name, id, pe->metric_expr); @@ -429,6 +430,18 @@ static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe) return ret; } +static int check_parse_fake(const char *id) +{ + struct parse_events_error error = { .idx = 0, }; + int ret = check_parse_id(id, &error, &perf_pmu__fake); + + free(error.str); + free(error.help); + free(error.first_str); + free(error.first_help); + return ret; +} + static void expr_failure(const char *msg, const struct pmu_events_map *map, const struct pmu_event *pe) @@ -498,6 +511,100 @@ static int test_parsing(void) return ret == 0 ? TEST_OK : TEST_SKIP; } +struct test_metric { + const char *str; +}; + +static struct test_metric metrics[] = { + { "(unc_p_power_state_occupancy.cores_c0 / unc_p_clockticks) * 100." }, + { "imx8_ddr0@read\\-cycles@ * 4 * 4", }, + { "imx8_ddr0@axid\\-read\\,axi_mask\\=0xffff\\,axi_id\\=0x0000@ * 4", }, + { "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100", }, + { "(imx8_ddr0@read\\-cycles@ + imx8_ddr0@write\\-cycles@)", }, +}; + +static int metric_parse_fake(const char *str) +{ + struct expr_parse_ctx ctx; + struct hashmap_entry *cur; + double result; + int ret = -1; + size_t bkt; + int i; + + pr_debug("parsing '%s'\n", str); + + expr__ctx_init(&ctx); + if (expr__find_other(str, NULL, &ctx, 0) < 0) { + pr_err("expr__find_other failed\n"); + return -1; + } + + /* + * Add all ids with a made up value. The value may + * trigger divide by zero when subtracted and so try to + * make them unique. + */ + i = 1; + hashmap__for_each_entry((&ctx.ids), cur, bkt) + expr__add_id(&ctx, strdup(cur->key), i++); + + hashmap__for_each_entry((&ctx.ids), cur, bkt) { + if (check_parse_fake(cur->key)) { + pr_err("check_parse_fake failed\n"); + goto out; + } + } + + if (expr__parse(&result, &ctx, str, 1)) + pr_err("expr__parse failed\n"); + else + ret = 0; + +out: + expr__ctx_clear(&ctx); + return ret; +} + +/* + * Parse all the metrics for current architecture, + * or all defined cpus via the 'fake_pmu' + * in parse_events. + */ +static int test_parsing_fake(void) +{ + struct pmu_events_map *map; + struct pmu_event *pe; + unsigned int i, j; + int err = 0; + + for (i = 0; i < ARRAY_SIZE(metrics); i++) { + err = metric_parse_fake(metrics[i].str); + if (err) + return err; + } + + i = 0; + for (;;) { + map = &pmu_events_map[i++]; + if (!map->table) + break; + j = 0; + for (;;) { + pe = &map->table[j++]; + if (!pe->name && !pe->metric_group && !pe->metric_name) + break; + if (!pe->metric_expr) + continue; + err = metric_parse_fake(pe->metric_expr); + if (err) + return err; + } + } + + return 0; +} + static const struct { int (*func)(void); const char *desc; @@ -514,6 +621,10 @@ static const struct { .func = test_parsing, .desc = "Parsing of PMU event table metrics", }, + { + .func = test_parsing_fake, + .desc = "Parsing of PMU event table metrics with fake PMUs", + }, }; const char *test__pmu_events_subtest_get_desc(int subtest) -- GitLab From 8b4468a2107af32b796fa818e5fb76481c39ee5a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:33 +0200 Subject: [PATCH 0086/1754] perf parse: Factor out parse_groups() function Factor out the parse_groups function, it will be used for new test interface coming in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-6-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 9e21aa767e417..d72a565ec4835 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -709,14 +709,12 @@ static void metricgroup__free_egroups(struct list_head *group_list) } } -int metricgroup__parse_groups(const struct option *opt, - const char *str, - bool metric_no_group, - bool metric_no_merge, - struct rblist *metric_events) +static int parse_groups(struct evlist *perf_evlist, const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events) { struct parse_events_error parse_error; - struct evlist *perf_evlist = *(struct evlist **)opt->value; struct strbuf extra_events; LIST_HEAD(group_list); int ret; @@ -742,6 +740,18 @@ int metricgroup__parse_groups(const struct option *opt, return ret; } +int metricgroup__parse_groups(const struct option *opt, + const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events) +{ + struct evlist *perf_evlist = *(struct evlist **)opt->value; + + return parse_groups(perf_evlist, str, metric_no_group, + metric_no_merge, metric_events); +} + bool metricgroup__has_metric(const char *metric) { struct pmu_events_map *map = perf_pmu__find_map(NULL); -- GitLab From 68173bda6ac9d498e450276323f1c10a1d0307ad Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 9 Jun 2020 12:50:42 -0300 Subject: [PATCH 0087/1754] perf tools: Add fake_pmu to parse_group() function Allow to pass fake_pmu in parse_groups function so it can be used in parse_events call. It's will be passed by the upcoming metricgroup__parse_groups_test function. Committer notes: Made it a 'struct perf_pmu' pointer, in line with the changes at the start of this patchkit to avoid statics deep down in library code. Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-6-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index d72a565ec4835..49e6f7c6fb703 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -712,6 +712,7 @@ static void metricgroup__free_egroups(struct list_head *group_list) static int parse_groups(struct evlist *perf_evlist, const char *str, bool metric_no_group, bool metric_no_merge, + struct perf_pmu *fake_pmu, struct rblist *metric_events) { struct parse_events_error parse_error; @@ -727,7 +728,7 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, return ret; pr_debug("adding %s\n", extra_events.buf); bzero(&parse_error, sizeof(parse_error)); - ret = parse_events(perf_evlist, extra_events.buf, &parse_error); + ret = __parse_events(perf_evlist, extra_events.buf, &parse_error, fake_pmu); if (ret) { parse_events_print_error(&parse_error, extra_events.buf); goto out; @@ -749,7 +750,7 @@ int metricgroup__parse_groups(const struct option *opt, struct evlist *perf_evlist = *(struct evlist **)opt->value; return parse_groups(perf_evlist, str, metric_no_group, - metric_no_merge, metric_events); + metric_no_merge, NULL, metric_events); } bool metricgroup__has_metric(const char *metric) -- GitLab From 1381396b0b778c918bf191b1960f92fbd563476d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 9 Jun 2020 12:57:47 -0300 Subject: [PATCH 0088/1754] perf tools: Add map to parse_groups() function For testing purposes we need to pass our own map of events from parse_groups() through metricgroup__add_metric. Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-8-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 49e6f7c6fb703..f89f656c77577 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -597,17 +597,14 @@ static int __metricgroup__add_metric(struct list_head *group_list, static int metricgroup__add_metric(const char *metric, bool metric_no_group, struct strbuf *events, - struct list_head *group_list) + struct list_head *group_list, + struct pmu_events_map *map) { - struct pmu_events_map *map = perf_pmu__find_map(NULL); struct pmu_event *pe; struct egroup *eg; int i, ret; bool has_match = false; - if (!map) - return 0; - for (i = 0; ; i++) { pe = &map->table[i]; @@ -668,7 +665,8 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, static int metricgroup__add_metric_list(const char *list, bool metric_no_group, struct strbuf *events, - struct list_head *group_list) + struct list_head *group_list, + struct pmu_events_map *map) { char *llist, *nlist, *p; int ret = -EINVAL; @@ -683,7 +681,7 @@ static int metricgroup__add_metric_list(const char *list, bool metric_no_group, while ((p = strsep(&llist, ",")) != NULL) { ret = metricgroup__add_metric(p, metric_no_group, events, - group_list); + group_list, map); if (ret == -EINVAL) { fprintf(stderr, "Cannot find metric or group `%s'\n", p); @@ -713,7 +711,8 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, bool metric_no_group, bool metric_no_merge, struct perf_pmu *fake_pmu, - struct rblist *metric_events) + struct rblist *metric_events, + struct pmu_events_map *map) { struct parse_events_error parse_error; struct strbuf extra_events; @@ -723,7 +722,7 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, if (metric_events->nr_entries == 0) metricgroup__rblist_init(metric_events); ret = metricgroup__add_metric_list(str, metric_no_group, - &extra_events, &group_list); + &extra_events, &group_list, map); if (ret) return ret; pr_debug("adding %s\n", extra_events.buf); @@ -748,9 +747,13 @@ int metricgroup__parse_groups(const struct option *opt, struct rblist *metric_events) { struct evlist *perf_evlist = *(struct evlist **)opt->value; + struct pmu_events_map *map = perf_pmu__find_map(NULL); + + if (!map) + return 0; return parse_groups(perf_evlist, str, metric_no_group, - metric_no_merge, NULL, metric_events); + metric_no_merge, NULL, metric_events, map); } bool metricgroup__has_metric(const char *metric) -- GitLab From f78ac00a8c999f4418e69e606485784fc5ff1d09 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:36 +0200 Subject: [PATCH 0089/1754] perf tools: Add metricgroup__parse_groups_test function Add the metricgroup__parse_groups_test function. It will be used as test's interface to metric parsing in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-9-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 11 +++++++++++ tools/perf/util/metricgroup.h | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index f89f656c77577..edb13b8b7a57f 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -756,6 +756,17 @@ int metricgroup__parse_groups(const struct option *opt, metric_no_merge, NULL, metric_events, map); } +int metricgroup__parse_groups_test(struct evlist *evlist, + struct pmu_events_map *map, + const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events) +{ + return parse_groups(evlist, str, metric_no_group, + metric_no_merge, &perf_pmu__fake, metric_events, map); +} + bool metricgroup__has_metric(const char *metric) { struct pmu_events_map *map = perf_pmu__find_map(NULL); diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h index 287850bcdeca1..426c824e20bf4 100644 --- a/tools/perf/util/metricgroup.h +++ b/tools/perf/util/metricgroup.h @@ -7,8 +7,10 @@ #include struct evsel; +struct evlist; struct option; struct rblist; +struct pmu_events_map; struct metric_event { struct rb_node nd; @@ -34,6 +36,13 @@ int metricgroup__parse_groups(const struct option *opt, bool metric_no_merge, struct rblist *metric_events); +int metricgroup__parse_groups_test(struct evlist *evlist, + struct pmu_events_map *map, + const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events); + void metricgroup__print(bool metrics, bool groups, char *filter, bool raw, bool details); bool metricgroup__has_metric(const char *metric); -- GitLab From 2cfaa853d8ead2fe4cd82986163b5cea21e300bd Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:37 +0200 Subject: [PATCH 0090/1754] perf tools: Factor out prepare_metric function Factoring out prepare_metric function so it can be used in test interface coming in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-10-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-shadow.c | 53 ++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index a7c13a88ecb9f..27be7ce2fff4e 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -730,25 +730,16 @@ static void print_smi_cost(struct perf_stat_config *config, out->print_metric(config, out->ctx, NULL, "%4.0f", "SMI#", smi_num); } -static void generic_metric(struct perf_stat_config *config, - const char *metric_expr, - struct evsel **metric_events, - char *name, - const char *metric_name, - const char *metric_unit, - int runtime, - int cpu, - struct perf_stat_output_ctx *out, - struct runtime_stat *st) +static int prepare_metric(struct evsel **metric_events, + struct expr_parse_ctx *pctx, + int cpu, + struct runtime_stat *st) { - print_metric_t print_metric = out->print_metric; - struct expr_parse_ctx pctx; - double ratio, scale; - int i; - void *ctxp = out->ctx; + double scale; char *n, *pn; + int i; - expr__ctx_init(&pctx); + expr__ctx_init(pctx); for (i = 0; metric_events[i]; i++) { struct saved_value *v; struct stats *stats; @@ -771,7 +762,7 @@ static void generic_metric(struct perf_stat_config *config, n = strdup(metric_events[i]->name); if (!n) - return; + return -ENOMEM; /* * This display code with --no-merge adds [cpu] postfixes. * These are not supported by the parser. Remove everything @@ -782,11 +773,35 @@ static void generic_metric(struct perf_stat_config *config, *pn = 0; if (metric_total) - expr__add_id(&pctx, n, metric_total); + expr__add_id(pctx, n, metric_total); else - expr__add_id(&pctx, n, avg_stats(stats)*scale); + expr__add_id(pctx, n, avg_stats(stats)*scale); } + return i; +} + +static void generic_metric(struct perf_stat_config *config, + const char *metric_expr, + struct evsel **metric_events, + char *name, + const char *metric_name, + const char *metric_unit, + int runtime, + int cpu, + struct perf_stat_output_ctx *out, + struct runtime_stat *st) +{ + print_metric_t print_metric = out->print_metric; + struct expr_parse_ctx pctx; + double ratio, scale; + int i; + void *ctxp = out->ctx; + + i = prepare_metric(metric_events, &pctx, cpu, st); + if (i < 0) + return; + if (!metric_events[i]) { if (expr__parse(&ratio, &pctx, metric_expr, runtime) == 0) { char *unit; -- GitLab From 9afe5658a6fa89f59f01d2857d78203cc8665f1c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:38 +0200 Subject: [PATCH 0091/1754] perf tools: Release metric_events rblist We don't release metric_events rblist, add the missing delete hook and call the release before leaving cmd_stat. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-11-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 1 + tools/perf/util/metricgroup.c | 19 +++++++++++++++++++ tools/perf/util/metricgroup.h | 1 + 3 files changed, 21 insertions(+) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 9be020e0098ad..911b9c3538a2d 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -2307,6 +2307,7 @@ int cmd_stat(int argc, const char **argv) evlist__delete(evsel_list); + metricgroup__rblist_exit(&stat_config.metric_events); runtime_stat_delete(&stat_config); return status; diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index edb13b8b7a57f..82fecb5a302df 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -76,11 +76,30 @@ static struct rb_node *metric_event_new(struct rblist *rblist __maybe_unused, return &me->nd; } +static void metric_event_delete(struct rblist *rblist __maybe_unused, + struct rb_node *rb_node) +{ + struct metric_event *me = container_of(rb_node, struct metric_event, nd); + struct metric_expr *expr, *tmp; + + list_for_each_entry_safe(expr, tmp, &me->head, nd) { + free(expr); + } + + free(me); +} + static void metricgroup__rblist_init(struct rblist *metric_events) { rblist__init(metric_events); metric_events->node_cmp = metric_event_cmp; metric_events->node_new = metric_event_new; + metric_events->node_delete = metric_event_delete; +} + +void metricgroup__rblist_exit(struct rblist *metric_events) +{ + rblist__exit(metric_events); } struct egroup { diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h index 426c824e20bf4..8315bd1a7da47 100644 --- a/tools/perf/util/metricgroup.h +++ b/tools/perf/util/metricgroup.h @@ -47,4 +47,5 @@ void metricgroup__print(bool metrics, bool groups, char *filter, bool raw, bool details); bool metricgroup__has_metric(const char *metric); int arch_get_runtimeparam(void); +void metricgroup__rblist_exit(struct rblist *metric_events); #endif -- GitLab From 6d432c4c8aa5660d8f9f43326db8350b48dcb6f5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:39 +0200 Subject: [PATCH 0092/1754] perf tools: Add test_generic_metric function Adding test_generic_metric that prepares and runs given metric over the data from struct runtime_stat object. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-12-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-shadow.c | 14 ++++++++++++++ tools/perf/util/stat.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 27be7ce2fff4e..8fdef47005e60 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -842,6 +842,20 @@ static void generic_metric(struct perf_stat_config *config, expr__ctx_clear(&pctx); } +double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_stat *st) +{ + struct expr_parse_ctx pctx; + double ratio; + + if (prepare_metric(mexp->metric_events, &pctx, cpu, st) < 0) + return 0.; + + if (expr__parse(&ratio, &pctx, mexp->metric_expr, 1)) + return 0.; + + return ratio; +} + void perf_stat__print_shadow_stats(struct perf_stat_config *config, struct evsel *evsel, double avg, int cpu, diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index f75ae679eb281..6911c7249199a 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -230,4 +230,7 @@ perf_evlist__print_counters(struct evlist *evlist, struct target *_target, struct timespec *ts, int argc, const char **argv); + +struct metric_expr; +double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_stat *st); #endif -- GitLab From 0a507af9c681ac2adedc5fe1b2d534e27be85446 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:40 +0200 Subject: [PATCH 0093/1754] perf tests: Add parse metric test for ipc metric Adding new test that process metrics code and checks the expected results. Starting with easy ipc metric. Committer testing: # perf test "Parse and process metrics" 67: Parse and process metrics : Ok # # perf test -v "Parse and process metrics" 67: Parse and process metrics : --- start --- test child forked, pid 103402 metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC found event inst_retired.any found event cpu_clk_unhalted.thread adding {inst_retired.any,cpu_clk_unhalted.thread}:W test child finished with 0 ---- end ---- Parse and process metrics: Ok # Had to fix it to initialize that 'struct value' array sentinel with a named initializer to fix the build with some versions of clang: tests/parse-metric.c:135:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] { 0 }, Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-13-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 + tools/perf/tests/parse-metric.c | 145 ++++++++++++++++++++++++++++++++ tools/perf/tests/tests.h | 1 + 4 files changed, 151 insertions(+) create mode 100644 tools/perf/tests/parse-metric.c diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index cd00498a5dce6..84352fc49a205 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -59,6 +59,7 @@ perf-y += genelf.o perf-y += api-io.o perf-y += demangle-java-test.o perf-y += pfm.o +perf-y += parse-metric.o $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build $(call rule_mkdir) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index da5b6cc23f25b..d328caaba45d4 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -337,6 +337,10 @@ static struct test generic_tests[] = { .desc = "Demangle Java", .func = test__demangle_java, }, + { + .desc = "Parse and process metrics", + .func = test__parse_metric, + }, { .func = NULL, }, diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c new file mode 100644 index 0000000000000..79d956dc6a74a --- /dev/null +++ b/tools/perf/tests/parse-metric.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include "metricgroup.h" +#include "tests.h" +#include "pmu-events/pmu-events.h" +#include "evlist.h" +#include "rblist.h" +#include "debug.h" +#include "expr.h" +#include "stat.h" + +static struct pmu_event pme_test[] = { +{ + .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread", + .metric_name = "IPC", +}, +}; + +static struct pmu_events_map map = { + .cpuid = "test", + .version = "1", + .type = "core", + .table = pme_test, +}; + +struct value { + const char *event; + u64 val; +}; + +static u64 find_value(const char *name, struct value *values) +{ + struct value *v = values; + + while (v->event) { + if (!strcmp(name, v->event)) + return v->val; + v++; + }; + return 0; +} + +static void load_runtime_stat(struct runtime_stat *st, struct evlist *evlist, + struct value *vals) +{ + struct evsel *evsel; + u64 count; + + evlist__for_each_entry(evlist, evsel) { + count = find_value(evsel->name, vals); + perf_stat__update_shadow_stats(evsel, count, 0, st); + } +} + +static double compute_single(struct rblist *metric_events, struct evlist *evlist, + struct runtime_stat *st) +{ + struct evsel *evsel = evlist__first(evlist); + struct metric_event *me; + + me = metricgroup__lookup(metric_events, evsel, false); + if (me != NULL) { + struct metric_expr *mexp; + + mexp = list_first_entry(&me->head, struct metric_expr, nd); + return test_generic_metric(mexp, 0, st); + } + return 0.; +} + +static int compute_metric(const char *name, struct value *vals, double *ratio) +{ + struct rblist metric_events = { + .nr_entries = 0, + }; + struct perf_cpu_map *cpus; + struct runtime_stat st; + struct evlist *evlist; + int err; + + /* + * We need to prepare evlist for stat mode running on CPU 0 + * because that's where all the stats are going to be created. + */ + evlist = evlist__new(); + if (!evlist) + return -ENOMEM; + + cpus = perf_cpu_map__new("0"); + if (!cpus) + return -ENOMEM; + + perf_evlist__set_maps(&evlist->core, cpus, NULL); + + /* Parse the metric into metric_events list. */ + err = metricgroup__parse_groups_test(evlist, &map, name, + false, false, + &metric_events); + + TEST_ASSERT_VAL("failed to parse metric", err == 0); + + if (perf_evlist__alloc_stats(evlist, false)) + return -1; + + /* Load the runtime stats with given numbers for events. */ + runtime_stat__init(&st); + load_runtime_stat(&st, evlist, vals); + + /* And execute the metric */ + *ratio = compute_single(&metric_events, evlist, &st); + + /* ... clenup. */ + metricgroup__rblist_exit(&metric_events); + runtime_stat__exit(&st); + perf_evlist__free_stats(evlist); + perf_cpu_map__put(cpus); + evlist__delete(evlist); + return 0; +} + +static int test_ipc(void) +{ + double ratio; + struct value vals[] = { + { .event = "inst_retired.any", .val = 300 }, + { .event = "cpu_clk_unhalted.thread", .val = 200 }, + { .event = NULL, }, + }; + + TEST_ASSERT_VAL("failed to compute metric", + compute_metric("IPC", vals, &ratio) == 0); + + TEST_ASSERT_VAL("IPC failed, wrong ratio", + ratio == 1.5); + return 0; +} + +int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused) +{ + TEST_ASSERT_VAL("IPC failed", test_ipc() == 0); + return 0; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 76a4e352eaaf7..4447a516c6897 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -121,6 +121,7 @@ int test__demangle_java(struct test *test, int subtest); int test__pfm(struct test *test, int subtest); const char *test__pfm_subtest_get_desc(int subtest); int test__pfm_subtest_get_nr(void); +int test__parse_metric(struct test *test, int subtest); bool test__bp_signal_is_supported(void); bool test__bp_account_is_supported(void); -- GitLab From 218ca91df47712a7b2b5a554e39c4a2c819a9e86 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:41 +0200 Subject: [PATCH 0094/1754] perf tests: Add parse metric test for frontend metric Adding new metric test for frontend metric. It's stolen from x86 pmu events. Committer testing: # perf test "Parse and process metrics" 67: Parse and process metrics : Ok # perf test -v "Parse and process metrics" # 67: Parse and process metrics : --- start --- test child forked, pid 104881 metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC found event inst_retired.any found event cpu_clk_unhalted.thread adding {inst_retired.any,cpu_clk_unhalted.thread}:W metric expr idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * ( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) ))) for Frontend_Bound_SMT found event cpu_clk_unhalted.one_thread_active found event cpu_clk_unhalted.ref_xclk found event idq_uops_not_delivered.core found event cpu_clk_unhalted.thread adding {cpu_clk_unhalted.one_thread_active,cpu_clk_unhalted.ref_xclk,idq_uops_not_delivered.core,cpu_clk_unhalted.thread}:W test child finished with 0 ---- end ---- Parse and process metrics: Ok # Had to fix it to initialize that 'struct value' array sentinel with a named initializer to fix the build with some versions of clang: tests/parse-metric.c:154:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] { 0 }, Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-14-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/parse-metric.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c index 79d956dc6a74a..8c48251425e1c 100644 --- a/tools/perf/tests/parse-metric.c +++ b/tools/perf/tests/parse-metric.c @@ -17,6 +17,11 @@ static struct pmu_event pme_test[] = { .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread", .metric_name = "IPC", }, +{ + .metric_expr = "idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * " + "( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) )))", + .metric_name = "Frontend_Bound_SMT", +}, }; static struct pmu_events_map map = { @@ -138,8 +143,28 @@ static int test_ipc(void) return 0; } +static int test_frontend(void) +{ + double ratio; + struct value vals[] = { + { .event = "idq_uops_not_delivered.core", .val = 300 }, + { .event = "cpu_clk_unhalted.thread", .val = 200 }, + { .event = "cpu_clk_unhalted.one_thread_active", .val = 400 }, + { .event = "cpu_clk_unhalted.ref_xclk", .val = 600 }, + { .event = NULL, }, + }; + + TEST_ASSERT_VAL("failed to compute metric", + compute_metric("Frontend_Bound_SMT", vals, &ratio) == 0); + + TEST_ASSERT_VAL("Frontend_Bound_SMT failed, wrong ratio", + ratio == 0.45); + return 0; +} + int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused) { TEST_ASSERT_VAL("IPC failed", test_ipc() == 0); + TEST_ASSERT_VAL("frontend failed", test_frontend() == 0); return 0; } -- GitLab From afdd63f5933b3c970438e8ab6bb0cd9f392f3bf6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2020 11:39:16 -0300 Subject: [PATCH 0095/1754] perf script: Fixup some evsel/evlist method names Fixups related to the introduction of libperf, where the perf_{evsel,evlist}__ prefix is reserved for functions operating on struct perf_{evsel,evlist}. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 181d65e5a4505..1ff6a8a8dde51 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -388,7 +388,7 @@ static int evsel__check_stype(struct evsel *evsel, u64 sample_type, const char * return evsel__do_check_stype(evsel, sample_type, sample_msg, field, false); } -static int perf_evsel__check_attr(struct evsel *evsel, struct perf_session *session) +static int evsel__check_attr(struct evsel *evsel, struct perf_session *session) { struct perf_event_attr *attr = &evsel->core.attr; bool allow_user_set; @@ -522,7 +522,7 @@ static int perf_session__check_output_opt(struct perf_session *session) } if (evsel && output[j].fields && - perf_evsel__check_attr(evsel, session)) + evsel__check_attr(evsel, session)) return -1; if (evsel == NULL) @@ -1692,7 +1692,7 @@ struct perf_script { int range_num; }; -static int perf_evlist__max_name_len(struct evlist *evlist) +static int evlist__max_name_len(struct evlist *evlist) { struct evsel *evsel; int max = 0; @@ -1875,7 +1875,7 @@ static void process_event(struct perf_script *script, const char *evname = evsel__name(evsel); if (!script->name_width) - script->name_width = perf_evlist__max_name_len(script->session->evlist); + script->name_width = evlist__max_name_len(script->session->evlist); fprintf(fp, "%*s: ", script->name_width, evname ?: "[unknown]"); } @@ -2120,7 +2120,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, } if (evsel->core.attr.sample_type) { - err = perf_evsel__check_attr(evsel, scr->session); + err = evsel__check_attr(evsel, scr->session); if (err) return err; } -- GitLab From 3e21a28a01e227726456a51933ed004c2df31850 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 10 Jun 2020 16:58:22 -0700 Subject: [PATCH 0096/1754] perf expr: Add d_ratio operation d_ratio avoids division by 0 yielding infinity, such as when a counter doesn't get scheduled. An example usage is: { "BriefDescription": "DCache L1 misses", "MetricExpr": "d_ratio(MEM_LOAD_RETIRED.L1_MISS, MEM_LOAD_RETIRED.L1_HIT + MEM_LOAD_RETIRED.L1_MISS + MEM_LOAD_RETIRED.FB_HIT)", "MetricGroup": "DCache;DCache_L1", "MetricName": "DCache_L1_Miss", "ScaleUnit": "100%", } Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Kajol Jain Cc: Mark Rutland Cc: Namhyung Kim Cc: Paul Clarke Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200610235823.52557-1-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/expr.c | 2 ++ tools/perf/util/expr.l | 1 + tools/perf/util/expr.y | 14 ++++++++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index 1cb02ca2b15fb..c4877b36ab58b 100644 --- a/tools/perf/tests/expr.c +++ b/tools/perf/tests/expr.c @@ -39,6 +39,8 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) ret |= test(&ctx, "1+1 if 3*4 else 0", 2); ret |= test(&ctx, "1.1 + 2.1", 3.2); ret |= test(&ctx, ".1 + 2.", 2.1); + ret |= test(&ctx, "d_ratio(1, 2)", 0.5); + ret |= test(&ctx, "d_ratio(2.5, 0)", 0); if (ret) return ret; diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l index f397bf8b1a48e..298d86660a969 100644 --- a/tools/perf/util/expr.l +++ b/tools/perf/util/expr.l @@ -100,6 +100,7 @@ symbol ({spec}|{sym})+ } } +d_ratio { return D_RATIO; } max { return MAX; } min { return MIN; } if { return IF; } diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index bf3e898e30554..fe145344bb393 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -10,6 +10,14 @@ #include "smt.h" #include +static double d_ratio(double val0, double val1) +{ + if (val1 == 0) { + return 0; + } + return val0 / val1; +} + %} %define api.pure full @@ -28,7 +36,7 @@ %token NUMBER %token ID %destructor { free ($$); } -%token MIN MAX IF ELSE SMT_ON +%token MIN MAX IF ELSE SMT_ON D_RATIO %left MIN MAX IF %left '|' %left '^' @@ -64,7 +72,8 @@ other: ID } | MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' - +| +D_RATIO all_expr: if_expr { *final_val = $1; } ; @@ -105,6 +114,7 @@ expr: NUMBER | MIN '(' expr ',' expr ')' { $$ = $3 < $5 ? $3 : $5; } | MAX '(' expr ',' expr ')' { $$ = $3 > $5 ? $3 : $5; } | SMT_ON { $$ = smt_on() > 0; } + | D_RATIO '(' expr ',' expr ')' { $$ = d_ratio($3,$5); } ; %% -- GitLab From ff1a12f962dff5b490c5ce1c2c4bcd0bf3bf517d Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 10 Jun 2020 16:58:23 -0700 Subject: [PATCH 0097/1754] perf expr: Add < and > operators These are broadly useful but required to handle TMA metrics. For example encoding Ports_Utilization from: https://download.01.org/perfmon/TMA_Metrics.csv requires '<'. { "BriefDescription": "This metric estimates fraction of cycles the CPU performance was potentially limited due to Core computation issues (non divider-related). Two distinct categories can be attributed into this metric: (1) heavy data-dependency among contiguous instructions would manifest in this metric - such cases are often referred to as low Instruction Level Parallelism (ILP). (2) Contention on some hardware execution unit other than Divider. For example; when there are too many multiply operations.", "MetricExpr": "( ( cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ + cpu@EXE_ACTIVITY.1_PORTS_UTIL@ + ( cpu@EXE_ACTIVITY.2_PORTS_UTIL@ * ( ( ( cpu@UOPS_RETIRED.RETIRE_SLOTS@ ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) ) / ( ( 4.000000 ) + 1.000000 ) ) ) ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) if ( cpu@ARITH.DIVIDER_ACTIVE\\,cmask\\=1@ < cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ ) else ( ( cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ + cpu@EXE_ACTIVITY.1_PORTS_UTIL@ + ( cpu@EXE_ACTIVITY.2_PORTS_UTIL@ * ( ( ( cpu@UOPS_RETIRED.RETIRE_SLOTS@ ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) ) / ( ( 4.000000 ) + 1.000000 ) ) ) ) - cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) )", "MetricGroup": "Topdown_Group_Ports_Utilization", "MetricName": "Topdown_Metric_Ports_Utilization" }, Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Kajol Jain Cc: Mark Rutland Cc: Namhyung Kim Cc: Paul Clarke Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200610235823.52557-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/expr.c | 6 ++++++ tools/perf/util/expr.l | 2 ++ tools/perf/util/expr.y | 5 ++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index c4877b36ab58b..b7e5ef3007fc1 100644 --- a/tools/perf/tests/expr.c +++ b/tools/perf/tests/expr.c @@ -41,6 +41,12 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) ret |= test(&ctx, ".1 + 2.", 2.1); ret |= test(&ctx, "d_ratio(1, 2)", 0.5); ret |= test(&ctx, "d_ratio(2.5, 0)", 0); + ret |= test(&ctx, "1.1 < 2.2", 1); + ret |= test(&ctx, "2.2 > 1.1", 1); + ret |= test(&ctx, "1.1 < 1.1", 0); + ret |= test(&ctx, "2.2 > 2.2", 0); + ret |= test(&ctx, "2.2 < 1.1", 0); + ret |= test(&ctx, "1.1 > 2.2", 0); if (ret) return ret; diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l index 298d86660a969..13e5e3c75f563 100644 --- a/tools/perf/util/expr.l +++ b/tools/perf/util/expr.l @@ -111,6 +111,8 @@ else { return ELSE; } "|" { return '|'; } "^" { return '^'; } "&" { return '&'; } +"<" { return '<'; } +">" { return '>'; } "-" { return '-'; } "+" { return '+'; } "*" { return '*'; } diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index fe145344bb393..5fcb98800f9c1 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -41,6 +41,7 @@ static double d_ratio(double val0, double val1) %left '|' %left '^' %left '&' +%left '<' '>' %left '-' '+' %left '*' '/' '%' %left NEG NOT @@ -73,7 +74,7 @@ other: ID | MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' | -D_RATIO +'<' | '>' | D_RATIO all_expr: if_expr { *final_val = $1; } ; @@ -94,6 +95,8 @@ expr: NUMBER | expr '|' expr { $$ = (long)$1 | (long)$3; } | expr '&' expr { $$ = (long)$1 & (long)$3; } | expr '^' expr { $$ = (long)$1 ^ (long)$3; } + | expr '<' expr { $$ = $1 < $3; } + | expr '>' expr { $$ = $1 > $3; } | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } -- GitLab From 47446212832871e66f3b5fbf021c148eced2e24c Mon Sep 17 00:00:00 2001 From: Mike Leach Date: Tue, 16 Jun 2020 17:40:41 +0100 Subject: [PATCH 0098/1754] perf cs-etm: Allow no CoreSight sink to be specified on command line Adjust the handling of the session sink selection to allow no sink to be selected on the command line. This then forwards the sink selection to the CoreSight infrastructure which will attempt to select a sink based on the default sink select priorities. Signed-off-by: Mike Leach Tested-by: Leo Yan Cc: Mathieu Poirier Cc: Peter Zijlstra Cc: Suzuki Poulouse Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/cs-etm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index cea5e33d61d2b..cad7bf7834138 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -243,10 +243,10 @@ static int cs_etm_set_sink_attr(struct perf_pmu *pmu, } /* - * No sink was provided on the command line - for _now_ treat - * this as an error. + * No sink was provided on the command line - allow the CoreSight + * system to look for a default */ - return ret; + return 0; } static int cs_etm_recording_options(struct auxtrace_record *itr, -- GitLab From c1b4745b48b3c5a29df6ef2b68384e7cccdc3691 Mon Sep 17 00:00:00 2001 From: John Garry Date: Wed, 17 Jun 2020 17:01:53 +0800 Subject: [PATCH 0099/1754] perf pmu: List kernel supplied event aliases for arm64 In commit dc098b35b56f ("perf list: List kernel supplied event aliases"), the aliases for events are supplied in addition to CPU event in perf list. This relies on the name of the core PMU being "cpu", which is not the case for arm64, so arm64 has always missed this. Use generic is_pmu_core() helper which takes account of arm64 to make this feature work for arm64 (and possibly other archs). Sample, before: armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event] after: br_mis_pred OR armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event] Signed-off-by: John Garry Acked-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Mark Rutland Cc: Peter Zijlstra Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Cc: linuxarm@huawei.com Link: http://lore.kernel.org/lkml/1592384514-119954-2-git-send-email-john.garry@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 6d51042044fd1..d039879bd9141 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1477,7 +1477,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, list_for_each_entry(alias, &pmu->aliases, list) { char *name = alias->desc ? alias->name : format_alias(buf, sizeof(buf), pmu, alias); - bool is_cpu = !strcmp(pmu->name, "cpu"); + bool is_cpu = is_pmu_core(pmu->name); if (alias->deprecated && !deprecated) continue; -- GitLab From ce0dc7d22271fa7eac3875fc9b57772742b8245e Mon Sep 17 00:00:00 2001 From: John Garry Date: Wed, 17 Jun 2020 17:01:54 +0800 Subject: [PATCH 0100/1754] perf pmu: Improve CPU core PMU HW event list ordering For perf list, the CPU core PMU HW event ordering is such that not all events may will be listed adjacent - consider this example: $ tools/perf/perf list List of pre-defined events (to be used in -e): duration_time [Tool event] branch-instructions OR cpu/branch-instructions/ [Kernel PMU event] branch-misses OR cpu/branch-misses/ [Kernel PMU event] bus-cycles OR cpu/bus-cycles/ [Kernel PMU event] cache-misses OR cpu/cache-misses/ [Kernel PMU event] cache-references OR cpu/cache-references/ [Kernel PMU event] cpu-cycles OR cpu/cpu-cycles/ [Kernel PMU event] cstate_core/c3-residency/ [Kernel PMU event] cstate_core/c6-residency/ [Kernel PMU event] cstate_core/c7-residency/ [Kernel PMU event] cstate_pkg/c2-residency/ [Kernel PMU event] cstate_pkg/c3-residency/ [Kernel PMU event] cstate_pkg/c6-residency/ [Kernel PMU event] cstate_pkg/c7-residency/ [Kernel PMU event] cycles-ct OR cpu/cycles-ct/ [Kernel PMU event] cycles-t OR cpu/cycles-t/ [Kernel PMU event] el-abort OR cpu/el-abort/ [Kernel PMU event] el-capacity OR cpu/el-capacity/ [Kernel PMU event] Notice in the above example how the cstate_core PMU events are mixed in the middle of the CPU core events. For my arm64 platform, all the uncore events get mixed in, making the list very disorganised: page-faults OR faults [Software event] task-clock [Software event] duration_time [Tool event] L1-dcache-load-misses [Hardware cache event] L1-dcache-loads [Hardware cache event] L1-icache-load-misses [Hardware cache event] L1-icache-loads [Hardware cache event] branch-load-misses [Hardware cache event] branch-loads [Hardware cache event] dTLB-load-misses [Hardware cache event] dTLB-loads [Hardware cache event] iTLB-load-misses [Hardware cache event] iTLB-loads [Hardware cache event] br_mis_pred OR armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event] br_mis_pred_retired OR armv8_pmuv3_0/br_mis_pred_retired/ [Kernel PMU event] br_pred OR armv8_pmuv3_0/br_pred/ [Kernel PMU event] br_retired OR armv8_pmuv3_0/br_retired/ [Kernel PMU event] br_return_retired OR armv8_pmuv3_0/br_return_retired/ [Kernel PMU event] bus_access OR armv8_pmuv3_0/bus_access/ [Kernel PMU event] bus_cycles OR armv8_pmuv3_0/bus_cycles/ [Kernel PMU event] cid_write_retired OR armv8_pmuv3_0/cid_write_retired/ [Kernel PMU event] cpu_cycles OR armv8_pmuv3_0/cpu_cycles/ [Kernel PMU event] dtlb_walk OR armv8_pmuv3_0/dtlb_walk/ [Kernel PMU event] exc_return OR armv8_pmuv3_0/exc_return/ [Kernel PMU event] exc_taken OR armv8_pmuv3_0/exc_taken/ [Kernel PMU event] hisi_sccl1_ddrc0/act_cmd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_rcmd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_rd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_wcmd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_wr/ [Kernel PMU event] hisi_sccl1_ddrc0/pre_cmd/ [Kernel PMU event] hisi_sccl1_ddrc0/rnk_chg/ [Kernel PMU event] ... hisi_sccl7_l3c21/wr_hit_cpipe/ [Kernel PMU event] hisi_sccl7_l3c21/wr_hit_spipe/ [Kernel PMU event] hisi_sccl7_l3c21/wr_spipe/ [Kernel PMU event] inst_retired OR armv8_pmuv3_0/inst_retired/ [Kernel PMU event] inst_spec OR armv8_pmuv3_0/inst_spec/ [Kernel PMU event] itlb_walk OR armv8_pmuv3_0/itlb_walk/ [Kernel PMU event] l1d_cache OR armv8_pmuv3_0/l1d_cache/ [Kernel PMU event] l1d_cache_refill OR armv8_pmuv3_0/l1d_cache_refill/ [Kernel PMU event] l1d_cache_wb OR armv8_pmuv3_0/l1d_cache_wb/ [Kernel PMU event] l1d_tlb OR armv8_pmuv3_0/l1d_tlb/ [Kernel PMU event] l1d_tlb_refill OR armv8_pmuv3_0/l1d_tlb_refill/ [Kernel PMU event] So the events are list alphabetically. However, CPU core event listing is special from commit dc098b35b56f ("perf list: List kernel supplied event aliases"), in that the alias and full event is shown (in that order). As such, the core events may become sparse. Improve this by grouping the CPU core events and ensure that they are listed first for kernel PMU events. For the first example, above, this now looks like: duration_time [Tool event] branch-instructions OR cpu/branch-instructions/ [Kernel PMU event] branch-misses OR cpu/branch-misses/ [Kernel PMU event] bus-cycles OR cpu/bus-cycles/ [Kernel PMU event] cache-misses OR cpu/cache-misses/ [Kernel PMU event] cache-references OR cpu/cache-references/ [Kernel PMU event] cpu-cycles OR cpu/cpu-cycles/ [Kernel PMU event] cycles-ct OR cpu/cycles-ct/ [Kernel PMU event] cycles-t OR cpu/cycles-t/ [Kernel PMU event] el-abort OR cpu/el-abort/ [Kernel PMU event] el-capacity OR cpu/el-capacity/ [Kernel PMU event] el-commit OR cpu/el-commit/ [Kernel PMU event] el-conflict OR cpu/el-conflict/ [Kernel PMU event] el-start OR cpu/el-start/ [Kernel PMU event] instructions OR cpu/instructions/ [Kernel PMU event] mem-loads OR cpu/mem-loads/ [Kernel PMU event] mem-stores OR cpu/mem-stores/ [Kernel PMU event] ref-cycles OR cpu/ref-cycles/ [Kernel PMU event] topdown-fetch-bubbles OR cpu/topdown-fetch-bubbles/ [Kernel PMU event] topdown-recovery-bubbles OR cpu/topdown-recovery-bubbles/ [Kernel PMU event] topdown-slots-issued OR cpu/topdown-slots-issued/ [Kernel PMU event] topdown-slots-retired OR cpu/topdown-slots-retired/ [Kernel PMU event] topdown-total-slots OR cpu/topdown-total-slots/ [Kernel PMU event] tx-abort OR cpu/tx-abort/ [Kernel PMU event] tx-capacity OR cpu/tx-capacity/ [Kernel PMU event] tx-commit OR cpu/tx-commit/ [Kernel PMU event] tx-conflict OR cpu/tx-conflict/ [Kernel PMU event] tx-start OR cpu/tx-start/ [Kernel PMU event] cstate_core/c3-residency/ [Kernel PMU event] cstate_core/c6-residency/ [Kernel PMU event] cstate_core/c7-residency/ [Kernel PMU event] cstate_pkg/c2-residency/ [Kernel PMU event] cstate_pkg/c3-residency/ [Kernel PMU event] cstate_pkg/c6-residency/ [Kernel PMU event] cstate_pkg/c7-residency/ [Kernel PMU event] Signed-off-by: John Garry Acked-by: Jiri Olsa Acked-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Mark Rutland Cc: Peter Zijlstra Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Cc: linuxarm@huawei.com Link: http://lore.kernel.org/lkml/1592384514-119954-3-git-send-email-john.garry@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index d039879bd9141..f1688e1f6ed78 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1402,6 +1402,7 @@ struct sevent { char *pmu; char *metric_expr; char *metric_name; + int is_cpu; }; static int cmp_sevent(const void *a, const void *b) @@ -1418,6 +1419,11 @@ static int cmp_sevent(const void *a, const void *b) if (n) return n; } + + /* Order CPU core events to be first */ + if (as->is_cpu != bs->is_cpu) + return bs->is_cpu - as->is_cpu; + return strcmp(as->name, bs->name); } @@ -1509,6 +1515,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, aliases[j].pmu = pmu->name; aliases[j].metric_expr = alias->metric_expr; aliases[j].metric_name = alias->metric_name; + aliases[j].is_cpu = is_cpu; j++; } if (pmu->selectable && -- GitLab From e251abee87cf9c49a2ec1b143bd71f92b71557c1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:16:20 -0300 Subject: [PATCH 0101/1754] perf evlist: Fix the class prefix for 'struct evlist' 'add' evsel methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 2 +- tools/perf/builtin-record.c | 4 ++-- tools/perf/builtin-stat.c | 16 +++++++--------- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 3 +-- tools/perf/util/evlist.c | 17 +++++++---------- tools/perf/util/evlist.h | 17 ++++++++--------- 7 files changed, 27 insertions(+), 34 deletions(-) diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 95a77058023e6..460945ded6dd2 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1319,7 +1319,7 @@ static struct evlist *kvm_live_event_list(void) *name = '\0'; name++; - if (perf_evlist__add_newtp(evlist, sys, name, NULL)) { + if (evlist__add_newtp(evlist, sys, name, NULL)) { pr_err("Failed to add %s tracepoint to the list\n", *events_tp); free(tp); goto out; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index e108d90ae2edf..1eeb58eac5df3 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -852,7 +852,7 @@ static int record__open(struct record *rec) * event synthesis. */ if (opts->initial_delay || target__has_cpu(&opts->target)) { - if (perf_evlist__add_dummy(evlist)) + if (evlist__add_dummy(evlist)) return -ENOMEM; /* Disable tracking of mmaps on lead event. */ @@ -2722,7 +2722,7 @@ int cmd_record(int argc, const char **argv) record.opts.tail_synthesize = true; if (rec->evlist->core.nr_entries == 0 && - __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { + __evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { pr_err("Not enough memory for event selector list\n"); goto out; } diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 911b9c3538a2d..922d9961ba98e 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1679,19 +1679,17 @@ static int add_default_attributes(void) if (target__has_cpu(&target)) default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK; - if (perf_evlist__add_default_attrs(evsel_list, default_attrs0) < 0) + if (evlist__add_default_attrs(evsel_list, default_attrs0) < 0) return -1; if (pmu_have_event("cpu", "stalled-cycles-frontend")) { - if (perf_evlist__add_default_attrs(evsel_list, - frontend_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, frontend_attrs) < 0) return -1; } if (pmu_have_event("cpu", "stalled-cycles-backend")) { - if (perf_evlist__add_default_attrs(evsel_list, - backend_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, backend_attrs) < 0) return -1; } - if (perf_evlist__add_default_attrs(evsel_list, default_attrs1) < 0) + if (evlist__add_default_attrs(evsel_list, default_attrs1) < 0) return -1; } @@ -1701,21 +1699,21 @@ static int add_default_attributes(void) return 0; /* Append detailed run extra attributes: */ - if (perf_evlist__add_default_attrs(evsel_list, detailed_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, detailed_attrs) < 0) return -1; if (detailed_run < 2) return 0; /* Append very detailed run extra attributes: */ - if (perf_evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0) return -1; if (detailed_run < 3) return 0; /* Append very, very detailed run extra attributes: */ - return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); + return evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); } static const char * const stat_record_usage[] = { diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 13889d73f8dd5..994c230027bb2 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1627,7 +1627,7 @@ int cmd_top(int argc, const char **argv) goto out_delete_evlist; if (!top.evlist->core.nr_entries && - perf_evlist__add_default(top.evlist) < 0) { + evlist__add_default(top.evlist) < 0) { pr_err("Not enough memory for event selector list\n"); goto out_delete_evlist; } diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 4cbb64edc9983..b9c8b40c71359 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3917,8 +3917,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) } if (trace->sched && - perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", - trace__sched_stat_runtime)) + evlist__add_newtp(evlist, "sched", "sched_stat_runtime", trace__sched_stat_runtime)) goto out_error_sched_stat_runtime; /* * If a global cgroup was set, apply it to all the events without an diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 173b4f0e0e6e6..d574e774073ca 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -79,7 +79,7 @@ struct evlist *perf_evlist__new_default(void) { struct evlist *evlist = evlist__new(); - if (evlist && perf_evlist__add_default(evlist)) { + if (evlist && evlist__add_default(evlist)) { evlist__delete(evlist); evlist = NULL; } @@ -91,7 +91,7 @@ struct evlist *perf_evlist__new_dummy(void) { struct evlist *evlist = evlist__new(); - if (evlist && perf_evlist__add_dummy(evlist)) { + if (evlist && evlist__add_dummy(evlist)) { evlist__delete(evlist); evlist = NULL; } @@ -231,7 +231,7 @@ void perf_evlist__set_leader(struct evlist *evlist) } } -int __perf_evlist__add_default(struct evlist *evlist, bool precise) +int __evlist__add_default(struct evlist *evlist, bool precise) { struct evsel *evsel = evsel__new_cycles(precise); @@ -242,7 +242,7 @@ int __perf_evlist__add_default(struct evlist *evlist, bool precise) return 0; } -int perf_evlist__add_dummy(struct evlist *evlist) +int evlist__add_dummy(struct evlist *evlist) { struct perf_event_attr attr = { .type = PERF_TYPE_SOFTWARE, @@ -258,8 +258,7 @@ int perf_evlist__add_dummy(struct evlist *evlist) return 0; } -static int evlist__add_attrs(struct evlist *evlist, - struct perf_event_attr *attrs, size_t nr_attrs) +static int evlist__add_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) { struct evsel *evsel, *n; LIST_HEAD(head); @@ -282,8 +281,7 @@ static int evlist__add_attrs(struct evlist *evlist, return -1; } -int __perf_evlist__add_default_attrs(struct evlist *evlist, - struct perf_event_attr *attrs, size_t nr_attrs) +int __evlist__add_default_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) { size_t i; @@ -322,8 +320,7 @@ perf_evlist__find_tracepoint_by_name(struct evlist *evlist, return NULL; } -int perf_evlist__add_newtp(struct evlist *evlist, - const char *sys, const char *name, void *handler) +int evlist__add_newtp(struct evlist *evlist, const char *sys, const char *name, void *handler) { struct evsel *evsel = evsel__newtp(sys, name); diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index b6f325dfb4d24..94f210d2f313f 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -92,20 +92,20 @@ void evlist__delete(struct evlist *evlist); void evlist__add(struct evlist *evlist, struct evsel *entry); void evlist__remove(struct evlist *evlist, struct evsel *evsel); -int __perf_evlist__add_default(struct evlist *evlist, bool precise); +int __evlist__add_default(struct evlist *evlist, bool precise); -static inline int perf_evlist__add_default(struct evlist *evlist) +static inline int evlist__add_default(struct evlist *evlist) { - return __perf_evlist__add_default(evlist, true); + return __evlist__add_default(evlist, true); } -int __perf_evlist__add_default_attrs(struct evlist *evlist, +int __evlist__add_default_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs); -#define perf_evlist__add_default_attrs(evlist, array) \ - __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) +#define evlist__add_default_attrs(evlist, array) \ + __evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) -int perf_evlist__add_dummy(struct evlist *evlist); +int evlist__add_dummy(struct evlist *evlist); int perf_evlist__add_sb_event(struct evlist *evlist, struct perf_event_attr *attr, @@ -116,8 +116,7 @@ int perf_evlist__start_sb_thread(struct evlist *evlist, struct target *target); void perf_evlist__stop_sb_thread(struct evlist *evlist); -int perf_evlist__add_newtp(struct evlist *evlist, - const char *sys, const char *name, void *handler); +int evlist__add_newtp(struct evlist *evlist, const char *sys, const char *name, void *handler); int __evlist__set_tracepoints_handlers(struct evlist *evlist, const struct evsel_str_handler *assocs, -- GitLab From d1f249ecbd8413cb15f3bbad403253a183aa1d81 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:19:46 -0300 Subject: [PATCH 0102/1754] perf evlist: Fix the class prefix for 'struct evlist' strerror methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 4 ++-- tools/perf/tests/code-reading.c | 2 +- tools/perf/util/evlist.c | 5 ++--- tools/perf/util/evlist.h | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index b9c8b40c71359..a333a9a64f276 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -4149,11 +4149,11 @@ static int trace__run(struct trace *trace, int argc, const char **argv) goto out_error; out_error_mmap: - perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf)); + evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf)); goto out_error; out_error_open: - perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); + evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); out_error: fprintf(trace->output, "%s\n", errbuf); diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 6fe221d31f07e..035c9123549a9 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -678,7 +678,7 @@ static int do_test_code_reading(bool try_kcore) if (verbose > 0) { char errbuf[512]; - perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); + evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); pr_debug("perf_evlist__open() failed!\n%s\n", errbuf); } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index d574e774073ca..4b7f9f9b1588e 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1461,8 +1461,7 @@ int perf_evlist__parse_sample_timestamp(struct evlist *evlist, return evsel__parse_sample_timestamp(evsel, event, timestamp); } -int perf_evlist__strerror_open(struct evlist *evlist, - int err, char *buf, size_t size) +int evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size) { int printed, value; char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf)); @@ -1515,7 +1514,7 @@ int perf_evlist__strerror_open(struct evlist *evlist, return 0; } -int perf_evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size) +int evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size) { char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf)); int pages_attempted = evlist->core.mmap_len / 1024, pages_max_per_user, printed = 0; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 94f210d2f313f..a832639a82218 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -257,8 +257,8 @@ static inline struct evsel *evlist__last(struct evlist *evlist) return container_of(evsel, struct evsel, core); } -int perf_evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size); -int perf_evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size); +int evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size); +int evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size); bool perf_evlist__can_select_event(struct evlist *evlist, const char *str); void perf_evlist__to_front(struct evlist *evlist, -- GitLab From b3c2cc2bd21d1d97b34fcd1a08ca7f8cc29202a0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:24:21 -0300 Subject: [PATCH 0103/1754] perf evlist: Fix the class prefix for 'struct evlist' sample_type methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-c2c.c | 2 +- tools/perf/builtin-report.c | 6 +++--- tools/perf/builtin-script.c | 4 ++-- tools/perf/util/evlist.c | 8 ++++---- tools/perf/util/evlist.h | 6 +++--- tools/perf/util/session.c | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index d617d5682c688..5938b100eaf4c 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -2582,7 +2582,7 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset) static int setup_callchain(struct evlist *evlist) { - u64 sample_type = perf_evlist__combined_sample_type(evlist); + u64 sample_type = evlist__combined_sample_type(evlist); enum perf_call_graph_mode mode = CALLCHAIN_NONE; if ((sample_type & PERF_SAMPLE_REGS_USER) && diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 5f1d2a878fade..67e0692489fad 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -338,7 +338,7 @@ static int process_read_event(struct perf_tool *tool, static int report__setup_sample_type(struct report *rep) { struct perf_session *session = rep->session; - u64 sample_type = perf_evlist__combined_sample_type(session->evlist); + u64 sample_type = evlist__combined_sample_type(session->evlist); bool is_pipe = perf_data__is_pipe(session->data); if (session->itrace_synth_opts->callchain || @@ -1093,7 +1093,7 @@ static int process_attr(struct perf_tool *tool __maybe_unused, * Check if we need to enable callchains based * on events sample_type. */ - sample_type = perf_evlist__combined_sample_type(*pevlist); + sample_type = evlist__combined_sample_type(*pevlist); callchain_param_setup(sample_type); return 0; } @@ -1389,7 +1389,7 @@ int cmd_report(int argc, const char **argv) has_br_stack = perf_header__has_feat(&session->header, HEADER_BRANCH_STACK); - if (perf_evlist__combined_sample_type(session->evlist) & PERF_SAMPLE_STACK_USER) + if (evlist__combined_sample_type(session->evlist) & PERF_SAMPLE_STACK_USER) has_br_stack = false; setup_forced_leader(&report, session->evlist); diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 1ff6a8a8dde51..a47d3386f4b4e 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2129,7 +2129,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, * Check if we need to enable callchains based * on events sample_type. */ - sample_type = perf_evlist__combined_sample_type(evlist); + sample_type = evlist__combined_sample_type(evlist); callchain_param_setup(sample_type); /* Enable fields for callchain entries */ @@ -3171,7 +3171,7 @@ static int have_cmd(int argc, const char **argv) static void script__setup_sample_type(struct perf_script *script) { struct perf_session *session = script->session; - u64 sample_type = perf_evlist__combined_sample_type(session->evlist); + u64 sample_type = evlist__combined_sample_type(session->evlist); if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) { if ((sample_type & PERF_SAMPLE_REGS_USER) && diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 4b7f9f9b1588e..6415f97e22995 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1085,7 +1085,7 @@ int perf_evlist__append_tp_filter_pid(struct evlist *evlist, pid_t pid) return perf_evlist__append_tp_filter_pids(evlist, 1, &pid); } -bool perf_evlist__valid_sample_type(struct evlist *evlist) +bool evlist__valid_sample_type(struct evlist *evlist) { struct evsel *pos; @@ -1104,7 +1104,7 @@ bool perf_evlist__valid_sample_type(struct evlist *evlist) return true; } -u64 __perf_evlist__combined_sample_type(struct evlist *evlist) +u64 __evlist__combined_sample_type(struct evlist *evlist) { struct evsel *evsel; @@ -1117,10 +1117,10 @@ u64 __perf_evlist__combined_sample_type(struct evlist *evlist) return evlist->combined_sample_type; } -u64 perf_evlist__combined_sample_type(struct evlist *evlist) +u64 evlist__combined_sample_type(struct evlist *evlist) { evlist->combined_sample_type = 0; - return __perf_evlist__combined_sample_type(evlist); + return __evlist__combined_sample_type(evlist); } u64 perf_evlist__combined_branch_type(struct evlist *evlist) diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index a832639a82218..2edc1512c4438 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -218,8 +218,8 @@ int perf_evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel); void __perf_evlist__set_leader(struct list_head *list); void perf_evlist__set_leader(struct evlist *evlist); -u64 __perf_evlist__combined_sample_type(struct evlist *evlist); -u64 perf_evlist__combined_sample_type(struct evlist *evlist); +u64 __evlist__combined_sample_type(struct evlist *evlist); +u64 evlist__combined_sample_type(struct evlist *evlist); u64 perf_evlist__combined_branch_type(struct evlist *evlist); bool perf_evlist__sample_id_all(struct evlist *evlist); u16 perf_evlist__id_hdr_size(struct evlist *evlist); @@ -231,7 +231,7 @@ int perf_evlist__parse_sample_timestamp(struct evlist *evlist, union perf_event *event, u64 *timestamp); -bool perf_evlist__valid_sample_type(struct evlist *evlist); +bool evlist__valid_sample_type(struct evlist *evlist); bool perf_evlist__valid_sample_id_all(struct evlist *evlist); bool perf_evlist__valid_read_format(struct evlist *evlist); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 1a157e84a04a5..cbc8c476c8d33 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -115,7 +115,7 @@ static int perf_session__open(struct perf_session *session) if (perf_header__has_feat(&session->header, HEADER_STAT)) return 0; - if (!perf_evlist__valid_sample_type(session->evlist)) { + if (!evlist__valid_sample_type(session->evlist)) { pr_err("non matching sample_type\n"); return -1; } @@ -1160,7 +1160,7 @@ static void perf_evlist__print_tstamp(struct evlist *evlist, union perf_event *event, struct perf_sample *sample) { - u64 sample_type = __perf_evlist__combined_sample_type(evlist); + u64 sample_type = __evlist__combined_sample_type(evlist); if (event->header.type != PERF_RECORD_SAMPLE && !perf_evlist__sample_id_all(evlist)) { -- GitLab From 8cedf3a5c1f232fd8adf60affd040d32c5d9800f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:29:48 -0300 Subject: [PATCH 0104/1754] perf evlist: Fix the class prefix for 'struct evlist' sample_id_all methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 2 +- tools/perf/util/evlist.c | 6 +++--- tools/perf/util/evlist.h | 4 ++-- tools/perf/util/session.c | 12 ++++++------ 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 1eeb58eac5df3..19b1d5effb7a7 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1646,7 +1646,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) * Normally perf_session__new would do this, but it doesn't have the * evlist. */ - if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { + if (rec->tool.ordered_events && !evlist__sample_id_all(rec->evlist)) { pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); rec->tool.ordered_events = false; } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 6415f97e22995..daae5c6723449 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -537,7 +537,7 @@ struct evsel *perf_evlist__id2evsel(struct evlist *evlist, u64 id) if (sid) return container_of(sid->evsel, struct evsel, core); - if (!perf_evlist__sample_id_all(evlist)) + if (!evlist__sample_id_all(evlist)) return evlist__first(evlist); return NULL; @@ -1188,7 +1188,7 @@ u16 perf_evlist__id_hdr_size(struct evlist *evlist) return size; } -bool perf_evlist__valid_sample_id_all(struct evlist *evlist) +bool evlist__valid_sample_id_all(struct evlist *evlist) { struct evsel *first = evlist__first(evlist), *pos = first; @@ -1200,7 +1200,7 @@ bool perf_evlist__valid_sample_id_all(struct evlist *evlist) return true; } -bool perf_evlist__sample_id_all(struct evlist *evlist) +bool evlist__sample_id_all(struct evlist *evlist) { struct evsel *first = evlist__first(evlist); return first->core.attr.sample_id_all; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 2edc1512c4438..6c7b865e435bb 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -221,7 +221,7 @@ void perf_evlist__set_leader(struct evlist *evlist); u64 __evlist__combined_sample_type(struct evlist *evlist); u64 evlist__combined_sample_type(struct evlist *evlist); u64 perf_evlist__combined_branch_type(struct evlist *evlist); -bool perf_evlist__sample_id_all(struct evlist *evlist); +bool evlist__sample_id_all(struct evlist *evlist); u16 perf_evlist__id_hdr_size(struct evlist *evlist); int perf_evlist__parse_sample(struct evlist *evlist, union perf_event *event, @@ -232,7 +232,7 @@ int perf_evlist__parse_sample_timestamp(struct evlist *evlist, u64 *timestamp); bool evlist__valid_sample_type(struct evlist *evlist); -bool perf_evlist__valid_sample_id_all(struct evlist *evlist); +bool evlist__valid_sample_id_all(struct evlist *evlist); bool perf_evlist__valid_read_format(struct evlist *evlist); void perf_evlist__splice_list_tail(struct evlist *evlist, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index cbc8c476c8d33..396424fcaadfe 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -120,7 +120,7 @@ static int perf_session__open(struct perf_session *session) return -1; } - if (!perf_evlist__valid_sample_id_all(session->evlist)) { + if (!evlist__valid_sample_id_all(session->evlist)) { pr_err("non matching sample_id_all\n"); return -1; } @@ -252,10 +252,10 @@ struct perf_session *perf_session__new(struct perf_data *data, /* * In pipe-mode, evlist is empty until PERF_RECORD_HEADER_ATTR is - * processed, so perf_evlist__sample_id_all is not meaningful here. + * processed, so evlist__sample_id_all is not meaningful here. */ if ((!data || !data->is_pipe) && tool && tool->ordering_requires_timestamps && - tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) { + tool->ordered_events && !evlist__sample_id_all(session->evlist)) { dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); tool->ordered_events = false; } @@ -1163,7 +1163,7 @@ static void perf_evlist__print_tstamp(struct evlist *evlist, u64 sample_type = __evlist__combined_sample_type(evlist); if (event->header.type != PERF_RECORD_SAMPLE && - !perf_evlist__sample_id_all(evlist)) { + !evlist__sample_id_all(evlist)) { fputs("-1 -1 ", stdout); return; } @@ -1655,7 +1655,7 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset, return -1; if (session->header.needs_swap) - event_swap(event, perf_evlist__sample_id_all(session->evlist)); + event_swap(event, evlist__sample_id_all(session->evlist)); out_parse_sample: @@ -1704,7 +1704,7 @@ static s64 perf_session__process_event(struct perf_session *session, int ret; if (session->header.needs_swap) - event_swap(event, perf_evlist__sample_id_all(evlist)); + event_swap(event, evlist__sample_id_all(evlist)); if (event->header.type >= PERF_RECORD_HEADER_MAX) return -EINVAL; -- GitLab From 92c7d7cdf490b1f906da04b6340ca8f56836f723 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:31:25 -0300 Subject: [PATCH 0105/1754] perf evlist: Fix the class prefix for 'struct evlist' branch_type methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 3 +-- tools/perf/builtin-script.c | 3 +-- tools/perf/util/evlist.c | 2 +- tools/perf/util/evlist.h | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 67e0692489fad..ece1cddfcd7c7 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -410,8 +410,7 @@ static int report__setup_sample_type(struct report *rep) } /* ??? handle more cases than just ANY? */ - if (!(perf_evlist__combined_branch_type(session->evlist) & - PERF_SAMPLE_BRANCH_ANY)) + if (!(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_ANY)) rep->nonany_branch_mode = true; #if !defined(HAVE_LIBUNWIND_SUPPORT) && !defined(HAVE_DWARF_SUPPORT) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index a47d3386f4b4e..6613e2bfef243 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -443,8 +443,7 @@ static int evsel__check_attr(struct evsel *evsel, struct perf_session *session) return -EINVAL; } if (PRINT_FIELD(BRSTACKINSN) && !allow_user_set && - !(perf_evlist__combined_branch_type(session->evlist) & - PERF_SAMPLE_BRANCH_ANY)) { + !(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_ANY)) { pr_err("Display of branch stack assembler requested, but non all-branch filter set\n" "Hint: run 'perf record -b ...'\n"); return -EINVAL; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index daae5c6723449..1b884695b4d3f 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1123,7 +1123,7 @@ u64 evlist__combined_sample_type(struct evlist *evlist) return __evlist__combined_sample_type(evlist); } -u64 perf_evlist__combined_branch_type(struct evlist *evlist) +u64 evlist__combined_branch_type(struct evlist *evlist) { struct evsel *evsel; u64 branch_type = 0; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 6c7b865e435bb..38901c0d1599f 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -220,7 +220,7 @@ void perf_evlist__set_leader(struct evlist *evlist); u64 __evlist__combined_sample_type(struct evlist *evlist); u64 evlist__combined_sample_type(struct evlist *evlist); -u64 perf_evlist__combined_branch_type(struct evlist *evlist); +u64 evlist__combined_branch_type(struct evlist *evlist); bool evlist__sample_id_all(struct evlist *evlist); u16 perf_evlist__id_hdr_size(struct evlist *evlist); -- GitLab From 8d54c308c87f1b50ca088b12b89d7c0d96cf7dbf Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:47 -0700 Subject: [PATCH 0106/1754] perf parse-events: Use automatic variable for flex input This reduces the command line size slightly. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 8d18380ecd10e..66cf009f78d87 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -193,7 +193,7 @@ CFLAGS_genelf_debug.o += -Wno-packed $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(call rule_mkdir) @@ -201,7 +201,7 @@ $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) util/expr.l + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/expr-bison.c: util/expr.y $(call rule_mkdir) @@ -209,7 +209,7 @@ $(OUTPUT)util/expr-bison.c: util/expr.y $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $< $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) -- GitLab From da77a14db3a03562f70dbe4951042ff84f647d7b Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:48 -0700 Subject: [PATCH 0107/1754] perf parse-events: Use automatic variable for yacc input This reduces the command line size slightly. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-3-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 66cf009f78d87..4e1aa52d75a83 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -197,7 +197,7 @@ $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-event $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ $(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) @@ -205,7 +205,7 @@ $(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c $(OUTPUT)util/expr-bison.c: util/expr.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v util/expr.y -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) @@ -213,7 +213,7 @@ $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v util/pmu.y -d -o $@ -p perf_pmu_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d -o $@ -p perf_pmu_ CFLAGS_parse-events-flex.o += -w CFLAGS_pmu-flex.o += -w -- GitLab From 5011a52fc53570b816f80b0543cb7260cffca1bd Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:49 -0700 Subject: [PATCH 0108/1754] perf pmu: Add bison debug build flag Allow pmu parser to be debugged as the parse-events and expr currently are. Enabling this requires the C code to set perf_pmu_debug. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-4-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 4e1aa52d75a83..3ae4adc8e9666 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -213,7 +213,7 @@ $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d -o $@ -p perf_pmu_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p perf_pmu_ CFLAGS_parse-events-flex.o += -w CFLAGS_pmu-flex.o += -w -- GitLab From 970a4a3418e626d0d4220edd4e981ecbf9d87758 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:50 -0700 Subject: [PATCH 0109/1754] perf pmu: Add flex debug build flag Allow pmu parser's flex to be debugged as the parse-events and expr currently are. Enabling this requires the C code to call perf_pmu__flex_debug. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-5-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 3ae4adc8e9666..e63bfc46d50f2 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -209,7 +209,7 @@ $(OUTPUT)util/expr-bison.c: util/expr.y $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) -- GitLab From 4b971df992fdf8e0d55ab3cbea9fca4ce62bcefc Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:51 -0700 Subject: [PATCH 0110/1754] perf parse-events: Declare flex header file output Declare flex header file output so that bison C files can depend upon them. As there are multiple output targets $@ is replaced by the target name. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: Jiri Olsa Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-6-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index e63bfc46d50f2..55c78ac53f048 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -191,25 +191,28 @@ CFLAGS_llvm-utils.o += -DPERF_INCLUDE_DIR="BUILD_STR($(perf_include_dir_SQ))" # avoid compiler warnings in 32-bit mode CFLAGS_genelf_debug.o += -Wno-packed -$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c +$(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-flex.h: util/parse-events.l $(OUTPUT)util/parse-events-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/parse-events-flex.c \ + --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(call rule_mkdir) $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ -$(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c +$(OUTPUT)util/expr-flex.c $(OUTPUT)util/expr-flex.h: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/expr-flex.c \ + --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/expr-bison.c: util/expr.y $(call rule_mkdir) $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ -$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c +$(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-flex.h: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/pmu-flex.c \ + --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) -- GitLab From 3744ca1e670e6155ead37d9123ff005b07108259 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 23 Jun 2020 10:09:03 -0300 Subject: [PATCH 0111/1754] perf expr: Add missing headers noticed when building with NO_LIBBPF=1 These will break the build as soon as we stop disabling all warnings when building flex and bison generated files, so add them before we do that to keep the tree bisectable. Noticed when building on centos:7 with NO_LIBBPF=1: util/expr.c: In function 'key_equal': util/expr.c:29:2: error: implicit declaration of function 'strcmp' [-Werror=implicit-function-declaration] return !strcmp((const char *)key1, (const char *)key2); ^ util/expr.c: In function 'expr__add_id': util/expr.c:40:3: error: implicit declaration of function 'malloc' [-Werror=implicit-function-declaration] val_ptr = malloc(sizeof(double)); ^ util/expr.c:40:13: error: incompatible implicit declaration of built-in function 'malloc' [-Werror] val_ptr = malloc(sizeof(double)); ^ util/expr.c:42:12: error: 'ENOMEM' undeclared (first use in this function) return -ENOMEM; ^ Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/expr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index f64ab91c432ba..e8f777830a23f 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include +#include +#include #include "expr.h" #include "expr-bison.h" #include "expr-flex.h" -- GitLab From ef9894d9667786489f710199628e0bfffccf452a Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:52 -0700 Subject: [PATCH 0112/1754] perf parse-events: Declare bison header file output Declare bison header file output so that C files can depend upon them. As there are multiple output targets $@ is replaced by the target name. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-7-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 55c78ac53f048..504a6bb991ba3 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -196,27 +196,30 @@ $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-flex.h: util/parse- $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/parse-events-flex.c \ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< -$(OUTPUT)util/parse-events-bison.c: util/parse-events.y +$(OUTPUT)util/parse-events-bison.c $(OUTPUT)util/parse-events-bison.h: util/parse-events.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ + -o $(OUTPUT)util/parse-events-bison.c -p parse_events_ $(OUTPUT)util/expr-flex.c $(OUTPUT)util/expr-flex.h: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/expr-flex.c \ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< -$(OUTPUT)util/expr-bison.c: util/expr.y +$(OUTPUT)util/expr-bison.c $(OUTPUT)util/expr-bison.h: util/expr.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ + -o $(OUTPUT)util/expr-bison.c -p expr_ $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-flex.h: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/pmu-flex.c \ --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< -$(OUTPUT)util/pmu-bison.c: util/pmu.y +$(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.h: util/pmu.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p perf_pmu_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ + -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_ CFLAGS_parse-events-flex.o += -w CFLAGS_pmu-flex.o += -w -- GitLab From 5772717e59b9fbdc9e97da606dd69a75174f8101 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 24 Jun 2020 18:15:27 +0200 Subject: [PATCH 0113/1754] thermal: Add support for the MCU controlled FAN on Khadas boards The new Khadas VIM2 and VIM3 boards controls the cooling fan via the on-board microcontroller. This implements the FAN control as thermal devices and as cell of the Khadas MCU MFD driver. Signed-off-by: Neil Armstrong Reviewed-by: Amit Kucheria Acked-by: Daniel Lezcano Signed-off-by: Lee Jones --- drivers/thermal/Kconfig | 11 +++ drivers/thermal/Makefile | 1 + drivers/thermal/khadas_mcu_fan.c | 162 +++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 drivers/thermal/khadas_mcu_fan.c diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 3eb2348e52427..0125561488c9e 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -500,4 +500,15 @@ config SPRD_THERMAL help Support for the Spreadtrum thermal sensor driver in the Linux thermal framework. + +config KHADAS_MCU_FAN_THERMAL + tristate "Khadas MCU controller FAN cooling support" + depends on OF || COMPILE_TEST + depends on MFD_KHADAS_MCU + select MFD_CORE + select REGMAP + help + If you say yes here you get support for the FAN controlled + by the Microcontroller found on the Khadas VIM boards. + endif diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 0c8b84a09b9aa..4b6aabaa7e313 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -61,3 +61,4 @@ obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o obj-$(CONFIG_UNIPHIER_THERMAL) += uniphier_thermal.o obj-$(CONFIG_AMLOGIC_THERMAL) += amlogic_thermal.o obj-$(CONFIG_SPRD_THERMAL) += sprd_thermal.o +obj-$(CONFIG_KHADAS_MCU_FAN_THERMAL) += khadas_mcu_fan.o diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c new file mode 100644 index 0000000000000..9eadd2d6413e4 --- /dev/null +++ b/drivers/thermal/khadas_mcu_fan.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Khadas MCU Controlled FAN driver + * + * Copyright (C) 2020 BayLibre SAS + * Author(s): Neil Armstrong + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_LEVEL 3 + +struct khadas_mcu_fan_ctx { + struct khadas_mcu *mcu; + unsigned int level; + struct thermal_cooling_device *cdev; +}; + +static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx, + unsigned int level) +{ + int ret; + + ret = regmap_write(ctx->mcu->regmap, KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG, + level); + if (ret) + return ret; + + ctx->level = level; + + return 0; +} + +static int khadas_mcu_fan_get_max_state(struct thermal_cooling_device *cdev, + unsigned long *state) +{ + *state = MAX_LEVEL; + + return 0; +} + +static int khadas_mcu_fan_get_cur_state(struct thermal_cooling_device *cdev, + unsigned long *state) +{ + struct khadas_mcu_fan_ctx *ctx = cdev->devdata; + + *state = ctx->level; + + return 0; +} + +static int +khadas_mcu_fan_set_cur_state(struct thermal_cooling_device *cdev, + unsigned long state) +{ + struct khadas_mcu_fan_ctx *ctx = cdev->devdata; + + if (state > MAX_LEVEL) + return -EINVAL; + + if (state == ctx->level) + return 0; + + return khadas_mcu_fan_set_level(ctx, state); +} + +static const struct thermal_cooling_device_ops khadas_mcu_fan_cooling_ops = { + .get_max_state = khadas_mcu_fan_get_max_state, + .get_cur_state = khadas_mcu_fan_get_cur_state, + .set_cur_state = khadas_mcu_fan_set_cur_state, +}; + +static int khadas_mcu_fan_probe(struct platform_device *pdev) +{ + struct khadas_mcu *mcu = dev_get_drvdata(pdev->dev.parent); + struct thermal_cooling_device *cdev; + struct device *dev = &pdev->dev; + struct khadas_mcu_fan_ctx *ctx; + int ret; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + ctx->mcu = mcu; + platform_set_drvdata(pdev, ctx); + + cdev = devm_thermal_of_cooling_device_register(dev->parent, + dev->parent->of_node, "khadas-mcu-fan", ctx, + &khadas_mcu_fan_cooling_ops); + if (IS_ERR(cdev)) { + ret = PTR_ERR(cdev); + dev_err(dev, "Failed to register khadas-mcu-fan as cooling device: %d\n", + ret); + return ret; + } + ctx->cdev = cdev; + thermal_cdev_update(cdev); + + return 0; +} + +static void khadas_mcu_fan_shutdown(struct platform_device *pdev) +{ + struct khadas_mcu_fan_ctx *ctx = platform_get_drvdata(pdev); + + khadas_mcu_fan_set_level(ctx, 0); +} + +#ifdef CONFIG_PM_SLEEP +static int khadas_mcu_fan_suspend(struct device *dev) +{ + struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev); + unsigned int level_save = ctx->level; + int ret; + + ret = khadas_mcu_fan_set_level(ctx, 0); + if (ret) + return ret; + + ctx->level = level_save; + + return 0; +} + +static int khadas_mcu_fan_resume(struct device *dev) +{ + struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev); + + return khadas_mcu_fan_set_level(ctx, ctx->level); +} +#endif + +static SIMPLE_DEV_PM_OPS(khadas_mcu_fan_pm, khadas_mcu_fan_suspend, + khadas_mcu_fan_resume); + +static const struct platform_device_id khadas_mcu_fan_id_table[] = { + { .name = "khadas-mcu-fan-ctrl", }, + {}, +}; +MODULE_DEVICE_TABLE(platform, khadas_mcu_fan_id_table); + +static struct platform_driver khadas_mcu_fan_driver = { + .probe = khadas_mcu_fan_probe, + .shutdown = khadas_mcu_fan_shutdown, + .driver = { + .name = "khadas-mcu-fan-ctrl", + .pm = &khadas_mcu_fan_pm, + }, + .id_table = khadas_mcu_fan_id_table, +}; + +module_platform_driver(khadas_mcu_fan_driver); + +MODULE_AUTHOR("Neil Armstrong "); +MODULE_DESCRIPTION("Khadas MCU FAN driver"); +MODULE_LICENSE("GPL"); -- GitLab From bf9367a156fd868b312e8a575c00d57db2bc16bf Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 8 Jun 2020 11:17:38 +0200 Subject: [PATCH 0114/1754] MAINTAINERS: Add myself as maintainer for Khadas MCU drivers Add the Thermal driver along the MFD drivers and header as Maintained by myself. Signed-off-by: Neil Armstrong Signed-off-by: Lee Jones --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 68f21d46614c4..02d9827a4f810 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9574,6 +9574,15 @@ F: include/linux/kdb.h F: include/linux/kgdb.h F: kernel/debug/ +KHADAS MCU MFD DRIVER +M: Neil Armstrong +L: linux-amlogic@lists.infradead.org +S: Maintained +F: Documentation/devicetree/bindings/mfd/khadas,mcu.yaml +F: drivers/mfd/khadas-mcu.c +F: include/linux/mfd/khadas-mcu.h +F: drivers/thermal/khadas_mcu_fan.c + KMEMLEAK M: Catalin Marinas S: Maintained -- GitLab From c61e165822d57fd317868d14b46151d9c83662d2 Mon Sep 17 00:00:00 2001 From: Chunyan Zhang Date: Fri, 19 Jun 2020 17:09:14 +0800 Subject: [PATCH 0115/1754] mfd: sprd: Populate sub-devices defined in DT SC27XX-SPI added subdevices according to a pre-defined mfd_cell array, no matter these devices were really included on board. In this patch, switch to use devm_of_platform_populate() for adding sub-devices which are defined in devicetree. Signed-off-by: Chunyan Zhang Signed-off-by: Lee Jones --- drivers/mfd/sprd-sc27xx-spi.c | 75 ++--------------------------------- 1 file changed, 3 insertions(+), 72 deletions(-) diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c index 33336cde47243..d030a5da55444 100644 --- a/drivers/mfd/sprd-sc27xx-spi.c +++ b/drivers/mfd/sprd-sc27xx-spi.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -93,73 +94,6 @@ enum usb_charger_type sprd_pmic_detect_charger_type(struct device *dev) } EXPORT_SYMBOL_GPL(sprd_pmic_detect_charger_type); -static const struct mfd_cell sprd_pmic_devs[] = { - { - .name = "sc27xx-wdt", - .of_compatible = "sprd,sc2731-wdt", - }, { - .name = "sc27xx-rtc", - .of_compatible = "sprd,sc2731-rtc", - }, { - .name = "sc27xx-charger", - .of_compatible = "sprd,sc2731-charger", - }, { - .name = "sc27xx-chg-timer", - .of_compatible = "sprd,sc2731-chg-timer", - }, { - .name = "sc27xx-fast-chg", - .of_compatible = "sprd,sc2731-fast-chg", - }, { - .name = "sc27xx-chg-wdt", - .of_compatible = "sprd,sc2731-chg-wdt", - }, { - .name = "sc27xx-typec", - .of_compatible = "sprd,sc2731-typec", - }, { - .name = "sc27xx-flash", - .of_compatible = "sprd,sc2731-flash", - }, { - .name = "sc27xx-eic", - .of_compatible = "sprd,sc2731-eic", - }, { - .name = "sc27xx-efuse", - .of_compatible = "sprd,sc2731-efuse", - }, { - .name = "sc27xx-thermal", - .of_compatible = "sprd,sc2731-thermal", - }, { - .name = "sc27xx-adc", - .of_compatible = "sprd,sc2731-adc", - }, { - .name = "sc27xx-audio-codec", - .of_compatible = "sprd,sc2731-audio-codec", - }, { - .name = "sc27xx-regulator", - .of_compatible = "sprd,sc2731-regulator", - }, { - .name = "sc27xx-vibrator", - .of_compatible = "sprd,sc2731-vibrator", - }, { - .name = "sc27xx-keypad-led", - .of_compatible = "sprd,sc2731-keypad-led", - }, { - .name = "sc27xx-bltc", - .of_compatible = "sprd,sc2731-bltc", - }, { - .name = "sc27xx-fgu", - .of_compatible = "sprd,sc2731-fgu", - }, { - .name = "sc27xx-7sreset", - .of_compatible = "sprd,sc2731-7sreset", - }, { - .name = "sc27xx-poweroff", - .of_compatible = "sprd,sc2731-poweroff", - }, { - .name = "sc27xx-syscon", - .of_compatible = "sprd,sc2731-syscon", - }, -}; - static int sprd_pmic_spi_write(void *context, const void *data, size_t count) { struct device *dev = context; @@ -263,12 +197,9 @@ static int sprd_pmic_probe(struct spi_device *spi) return ret; } - ret = devm_mfd_add_devices(&spi->dev, PLATFORM_DEVID_AUTO, - sprd_pmic_devs, ARRAY_SIZE(sprd_pmic_devs), - NULL, 0, - regmap_irq_get_domain(ddata->irq_data)); + ret = devm_of_platform_populate(&spi->dev); if (ret) { - dev_err(&spi->dev, "Failed to register device %d\n", ret); + dev_err(&spi->dev, "Failed to populate sub-devices %d\n", ret); return ret; } -- GitLab From e8da9ed039805a52c32c4ee2f462080aa2315929 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Thu, 20 Feb 2020 17:22:46 +0100 Subject: [PATCH 0116/1754] dt-bindings: mfd: Convert stmfx bindings to json-schema Convert stmfx bindings to json-schema. Signed-off-by: Benjamin Gaignard Reviewed-by: Rob Herring Reviewed-by: Linus Walleij Signed-off-by: Lee Jones --- .../devicetree/bindings/mfd/st,stmfx.yaml | 124 ++++++++++++++++++ .../devicetree/bindings/mfd/stmfx.txt | 28 ---- .../bindings/pinctrl/pinctrl-stmfx.txt | 116 ---------------- 3 files changed, 124 insertions(+), 144 deletions(-) create mode 100644 Documentation/devicetree/bindings/mfd/st,stmfx.yaml delete mode 100644 Documentation/devicetree/bindings/mfd/stmfx.txt delete mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl-stmfx.txt diff --git a/Documentation/devicetree/bindings/mfd/st,stmfx.yaml b/Documentation/devicetree/bindings/mfd/st,stmfx.yaml new file mode 100644 index 0000000000000..0ce56a0da5536 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/st,stmfx.yaml @@ -0,0 +1,124 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/st,stmfx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectonics Multi-Function eXpander (STMFX) bindings + +description: ST Multi-Function eXpander (STMFX) is a slave controller using I2C for + communication with the main MCU. Its main features are GPIO expansion, + main MCU IDD measurement (IDD is the amount of current that flows + through VDD) and resistive touchscreen controller. + +maintainers: + - Amelie Delaunay + +properties: + compatible: + const: st,stmfx-0300 + + reg: + enum: [ 0x42, 0x43 ] + + interrupts: + maxItems: 1 + + drive-open-drain: true + + vdd-supply: + maxItems: 1 + + pinctrl: + type: object + + properties: + compatible: + const: st,stmfx-0300-pinctrl + + "#gpio-cells": + const: 2 + + "#interrupt-cells": + const: 2 + + gpio-controller: true + + interrupt-controller: true + + gpio-ranges: + description: if all STMFX pins[24:0] are available (no other STMFX function in use), + you should use gpio-ranges = <&stmfx_pinctrl 0 0 24>; + if agpio[3:0] are not available (STMFX Touchscreen function in use), + you should use gpio-ranges = <&stmfx_pinctrl 0 0 16>, <&stmfx_pinctrl 20 20 4>; + if agpio[7:4] are not available (STMFX IDD function in use), + you should use gpio-ranges = <&stmfx_pinctrl 0 0 20>; + maxItems: 1 + + patternProperties: + "^[a-zA-Z]*-pins$": + type: object + + allOf: + - $ref: ../pinctrl/pinmux-node.yaml + + properties: + pins: true + bias-disable: true + bias-pull-up: true + bias-pull-pin-default: true + bias-pull-down: true + drive-open-drain: true + drive-push-pull: true + output-high: true + output-low: true + + additionalProperties: false + + additionalProperties: false + + required: + - compatible + - "#gpio-cells" + - "#interrupt-cells" + - gpio-controller + - interrupt-controller + - gpio-ranges + +additionalProperties: false + +required: + - compatible + - reg + - interrupts + +examples: + - | + #include + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + stmfx@42 { + compatible = "st,stmfx-0300"; + reg = <0x42>; + interrupts = <8 IRQ_TYPE_EDGE_RISING>; + interrupt-parent = <&gpioi>; + vdd-supply = <&v3v3>; + + stmfx_pinctrl: pinctrl { + compatible = "st,stmfx-0300-pinctrl"; + #gpio-cells = <2>; + #interrupt-cells = <2>; + gpio-controller; + interrupt-controller; + gpio-ranges = <&stmfx_pinctrl 0 0 24>; + + joystick_pins: joystick-pins { + pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4"; + drive-push-pull; + bias-pull-up; + }; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/mfd/stmfx.txt b/Documentation/devicetree/bindings/mfd/stmfx.txt deleted file mode 100644 index f0c2f7fcf5c7f..0000000000000 --- a/Documentation/devicetree/bindings/mfd/stmfx.txt +++ /dev/null @@ -1,28 +0,0 @@ -STMicroelectonics Multi-Function eXpander (STMFX) Core bindings - -ST Multi-Function eXpander (STMFX) is a slave controller using I2C for -communication with the main MCU. Its main features are GPIO expansion, main -MCU IDD measurement (IDD is the amount of current that flows through VDD) and -resistive touchscreen controller. - -Required properties: -- compatible: should be "st,stmfx-0300". -- reg: I2C slave address of the device. -- interrupts: interrupt specifier triggered by MFX_IRQ_OUT signal. - Please refer to ../interrupt-controller/interrupt.txt - -Optional properties: -- drive-open-drain: configure MFX_IRQ_OUT as open drain. -- vdd-supply: phandle of the regulator supplying STMFX. - -Example: - - stmfx: stmfx@42 { - compatible = "st,stmfx-0300"; - reg = <0x42>; - interrupts = <8 IRQ_TYPE_EDGE_RISING>; - interrupt-parent = <&gpioi>; - vdd-supply = <&v3v3>; - }; - -Please refer to ../pinctrl/pinctrl-stmfx.txt for STMFX GPIO expander function bindings. diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-stmfx.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-stmfx.txt deleted file mode 100644 index c1b4c1819b84c..0000000000000 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-stmfx.txt +++ /dev/null @@ -1,116 +0,0 @@ -STMicroelectronics Multi-Function eXpander (STMFX) GPIO expander bindings - -ST Multi-Function eXpander (STMFX) offers up to 24 GPIOs expansion. -Please refer to ../mfd/stmfx.txt for STMFX Core bindings. - -Required properties: -- compatible: should be "st,stmfx-0300-pinctrl". -- #gpio-cells: should be <2>, the first cell is the GPIO number and the second - cell is the gpio flags in accordance with . -- gpio-controller: marks the device as a GPIO controller. -- #interrupt-cells: should be <2>, the first cell is the GPIO number and the - second cell is the interrupt flags in accordance with - . -- interrupt-controller: marks the device as an interrupt controller. -- gpio-ranges: specifies the mapping between gpio controller and pin - controller pins. Check "Concerning gpio-ranges property" below. -Please refer to ../gpio/gpio.txt. - -Please refer to pinctrl-bindings.txt for pin configuration. - -Required properties for pin configuration sub-nodes: -- pins: list of pins to which the configuration applies. - -Optional properties for pin configuration sub-nodes (pinconf-generic ones): -- bias-disable: disable any bias on the pin. -- bias-pull-up: the pin will be pulled up. -- bias-pull-pin-default: use the pin-default pull state. -- bias-pull-down: the pin will be pulled down. -- drive-open-drain: the pin will be driven with open drain. -- drive-push-pull: the pin will be driven actively high and low. -- output-high: the pin will be configured as an output driving high level. -- output-low: the pin will be configured as an output driving low level. - -Note that STMFX pins[15:0] are called "gpio[15:0]", and STMFX pins[23:16] are -called "agpio[7:0]". Example, to refer to pin 18 of STMFX, use "agpio2". - -Concerning gpio-ranges property: -- if all STMFX pins[24:0] are available (no other STMFX function in use), you - should use gpio-ranges = <&stmfx_pinctrl 0 0 24>; -- if agpio[3:0] are not available (STMFX Touchscreen function in use), you - should use gpio-ranges = <&stmfx_pinctrl 0 0 16>, <&stmfx_pinctrl 20 20 4>; -- if agpio[7:4] are not available (STMFX IDD function in use), you - should use gpio-ranges = <&stmfx_pinctrl 0 0 20>; - - -Example: - - stmfx: stmfx@42 { - ... - - stmfx_pinctrl: stmfx-pin-controller { - compatible = "st,stmfx-0300-pinctrl"; - #gpio-cells = <2>; - #interrupt-cells = <2>; - gpio-controller; - interrupt-controller; - gpio-ranges = <&stmfx_pinctrl 0 0 24>; - - joystick_pins: joystick { - pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4"; - drive-push-pull; - bias-pull-up; - }; - }; - }; - -Example of STMFX GPIO consumers: - - joystick { - compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; - pinctrl-0 = <&joystick_pins>; - pinctrl-names = "default"; - button-0 { - label = "JoySel"; - linux,code = ; - interrupt-parent = <&stmfx_pinctrl>; - interrupts = <0 IRQ_TYPE_EDGE_RISING>; - }; - button-1 { - label = "JoyDown"; - linux,code = ; - interrupt-parent = <&stmfx_pinctrl>; - interrupts = <1 IRQ_TYPE_EDGE_RISING>; - }; - button-2 { - label = "JoyLeft"; - linux,code = ; - interrupt-parent = <&stmfx_pinctrl>; - interrupts = <2 IRQ_TYPE_EDGE_RISING>; - }; - button-3 { - label = "JoyRight"; - linux,code = ; - interrupt-parent = <&stmfx_pinctrl>; - interrupts = <3 IRQ_TYPE_EDGE_RISING>; - }; - button-4 { - label = "JoyUp"; - linux,code = ; - interrupt-parent = <&stmfx_pinctrl>; - interrupts = <4 IRQ_TYPE_EDGE_RISING>; - }; - }; - - leds { - compatible = "gpio-leds"; - orange { - gpios = <&stmfx_pinctrl 17 1>; - }; - - blue { - gpios = <&stmfx_pinctrl 19 1>; - }; - } -- GitLab From 5e48a03bb9bff1728164040d71aa03cdb3cdfca2 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Wed, 24 Jun 2020 01:09:23 -0700 Subject: [PATCH 0117/1754] platform/chrome: cros_ec: Add TBT pd_ctrl fields To support Thunderbolt compatibility mode, synchronize ec_response_usb_pd_control_v2 with the Chrome EC version, so that we get the Thunderbolt related control fields and macros. Signed-off-by: Prashant Malani Signed-off-by: Enric Balletbo i Serra --- .../linux/platform_data/cros_ec_commands.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h index a7b0fc440c355..b808570bdd046 100644 --- a/include/linux/platform_data/cros_ec_commands.h +++ b/include/linux/platform_data/cros_ec_commands.h @@ -4917,15 +4917,26 @@ struct ec_response_usb_pd_control_v1 { #define USBC_PD_CC_UFP_ATTACHED 4 /* UFP attached to usbc */ #define USBC_PD_CC_DFP_ATTACHED 5 /* DPF attached to usbc */ +/* Active/Passive Cable */ +#define USB_PD_CTRL_ACTIVE_CABLE BIT(0) +/* Optical/Non-optical cable */ +#define USB_PD_CTRL_OPTICAL_CABLE BIT(1) +/* 3rd Gen TBT device (or AMA)/2nd gen tbt Adapter */ +#define USB_PD_CTRL_TBT_LEGACY_ADAPTER BIT(2) +/* Active Link Uni-Direction */ +#define USB_PD_CTRL_ACTIVE_LINK_UNIDIR BIT(3) + struct ec_response_usb_pd_control_v2 { uint8_t enabled; uint8_t role; uint8_t polarity; char state[32]; - uint8_t cc_state; /* USBC_PD_CC_*Encoded cc state */ - uint8_t dp_mode; /* Current DP pin mode (MODE_DP_PIN_[A-E]) */ - /* CL:1500994 Current cable type */ - uint8_t reserved_cable_type; + uint8_t cc_state; /* enum pd_cc_states representing cc state */ + uint8_t dp_mode; /* Current DP pin mode (MODE_DP_PIN_[A-E]) */ + uint8_t reserved; /* Reserved for future use */ + uint8_t control_flags; /* USB_PD_CTRL_*flags */ + uint8_t cable_speed; /* TBT_SS_* cable speed */ + uint8_t cable_gen; /* TBT_GEN3_* cable rounded support */ } __ec_align1; #define EC_CMD_USB_PD_PORTS 0x0102 -- GitLab From 5b30bd35aab4bcea6a06627a1e943659d82a71cb Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Wed, 24 Jun 2020 01:09:24 -0700 Subject: [PATCH 0118/1754] platform/chrome: cros_ec_typec: Add TBT compat support Add mux control support for Thunderbolt compatibility mode. Suggested-by: Heikki Krogerus Co-developed-by: Azhar Shaikh Co-developed-by: Casey Bowman Signed-off-by: Prashant Malani Reviewed-by: Heikki Krogerus Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 70 ++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 1df1386f32e4f..0c041b79cbbac 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #define DRV_NAME "cros-ec-typec" @@ -24,6 +25,7 @@ /* Supported alt modes. */ enum { CROS_EC_ALTMODE_DP = 0, + CROS_EC_ALTMODE_TBT, CROS_EC_ALTMODE_MAX, }; @@ -165,6 +167,14 @@ static void cros_typec_register_port_altmodes(struct cros_typec_data *typec, port->p_altmode[CROS_EC_ALTMODE_DP].svid = USB_TYPEC_DP_SID; port->p_altmode[CROS_EC_ALTMODE_DP].mode = USB_TYPEC_DP_MODE; + /* + * Register TBT compatibility alt mode. The EC will not enter the mode + * if it doesn't support it, so it's safe to register it unconditionally + * here for now. + */ + port->p_altmode[CROS_EC_ALTMODE_TBT].svid = USB_TYPEC_TBT_SID; + port->p_altmode[CROS_EC_ALTMODE_TBT].mode = TYPEC_ANY_MODE; + port->state.alt = NULL; port->state.mode = TYPEC_STATE_USB; port->state.data = NULL; @@ -391,6 +401,62 @@ static int cros_typec_usb_safe_state(struct cros_typec_port *port) return typec_mux_set(port->mux, &port->state); } +/* + * Spoof the VDOs that were likely communicated by the partner for TBT alt + * mode. + */ +static int cros_typec_enable_tbt(struct cros_typec_data *typec, + int port_num, + struct ec_response_usb_pd_control_v2 *pd_ctrl) +{ + struct cros_typec_port *port = typec->ports[port_num]; + struct typec_thunderbolt_data data; + int ret; + + if (typec->pd_ctrl_ver < 2) { + dev_err(typec->dev, + "PD_CTRL version too old: %d\n", typec->pd_ctrl_ver); + return -ENOTSUPP; + } + + /* Device Discover Mode VDO */ + data.device_mode = TBT_MODE; + + if (pd_ctrl->control_flags & USB_PD_CTRL_TBT_LEGACY_ADAPTER) + data.device_mode = TBT_SET_ADAPTER(TBT_ADAPTER_TBT3); + + /* Cable Discover Mode VDO */ + data.cable_mode = TBT_MODE; + data.cable_mode |= TBT_SET_CABLE_SPEED(pd_ctrl->cable_speed); + + if (pd_ctrl->control_flags & USB_PD_CTRL_OPTICAL_CABLE) + data.cable_mode |= TBT_CABLE_OPTICAL; + + if (pd_ctrl->control_flags & USB_PD_CTRL_ACTIVE_LINK_UNIDIR) + data.cable_mode |= TBT_CABLE_LINK_TRAINING; + + if (pd_ctrl->cable_gen) + data.cable_mode |= TBT_CABLE_ROUNDED; + + /* Enter Mode VDO */ + data.enter_vdo = TBT_SET_CABLE_SPEED(pd_ctrl->cable_speed); + + if (pd_ctrl->control_flags & USB_PD_CTRL_ACTIVE_CABLE) + data.enter_vdo |= TBT_ENTER_MODE_ACTIVE_CABLE; + + if (!port->state.alt) { + port->state.alt = &port->p_altmode[CROS_EC_ALTMODE_TBT]; + ret = cros_typec_usb_safe_state(port); + if (ret) + return ret; + } + + port->state.data = &data; + port->state.mode = TYPEC_TBT_MODE; + + return typec_mux_set(port->mux, &port->state); +} + /* Spoof the VDOs that were likely communicated by the partner. */ static int cros_typec_enable_dp(struct cros_typec_data *typec, int port_num, @@ -448,7 +514,9 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, if (ret) return ret; - if (mux_flags & USB_PD_MUX_DP_ENABLED) { + if (mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) { + ret = cros_typec_enable_tbt(typec, port_num, pd_ctrl); + } else if (mux_flags & USB_PD_MUX_DP_ENABLED) { ret = cros_typec_enable_dp(typec, port_num, pd_ctrl); } else if (mux_flags & USB_PD_MUX_SAFE_MODE) { ret = cros_typec_usb_safe_state(port); -- GitLab From 90d6bf481a5d0c32112925f3ecc640b9145f77d8 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 18 May 2020 19:09:12 +0200 Subject: [PATCH 0119/1754] mtd: rawnand: tango: Convert the driver to exec_op() Let's convert the driver to exec_op() to have one less driver relying on the legacy interface. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200518170912.328988-1-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/tango_nand.c | 125 +++++++++++++++++++----------- 1 file changed, 79 insertions(+), 46 deletions(-) diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index 246871e01027f..b3a0d08f1733a 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -113,59 +113,80 @@ struct tango_chip { #define TIMING(t0, t1, t2, t3) ((t0) << 24 | (t1) << 16 | (t2) << 8 | (t3)) -static void tango_cmd_ctrl(struct nand_chip *chip, int dat, unsigned int ctrl) +static void tango_select_target(struct nand_chip *chip, unsigned int cs) { + struct tango_nfc *nfc = to_tango_nfc(chip->controller); struct tango_chip *tchip = to_tango_chip(chip); - if (ctrl & NAND_CLE) - writeb_relaxed(dat, tchip->base + PBUS_CMD); - - if (ctrl & NAND_ALE) - writeb_relaxed(dat, tchip->base + PBUS_ADDR); + writel_relaxed(tchip->timing1, nfc->reg_base + NFC_TIMING1); + writel_relaxed(tchip->timing2, nfc->reg_base + NFC_TIMING2); + writel_relaxed(tchip->xfer_cfg, nfc->reg_base + NFC_XFER_CFG); + writel_relaxed(tchip->pkt_0_cfg, nfc->reg_base + NFC_PKT_0_CFG); + writel_relaxed(tchip->pkt_n_cfg, nfc->reg_base + NFC_PKT_N_CFG); + writel_relaxed(tchip->bb_cfg, nfc->reg_base + NFC_BB_CFG); } -static int tango_dev_ready(struct nand_chip *chip) +static int tango_waitrdy(struct nand_chip *chip, unsigned int timeout_ms) { struct tango_nfc *nfc = to_tango_nfc(chip->controller); + u32 status; - return readl_relaxed(nfc->pbus_base + PBUS_CS_CTRL) & PBUS_IORDY; + return readl_relaxed_poll_timeout(nfc->pbus_base + PBUS_CS_CTRL, + status, status & PBUS_IORDY, 20, + timeout_ms); } -static u8 tango_read_byte(struct nand_chip *chip) +static int tango_exec_instr(struct nand_chip *chip, + const struct nand_op_instr *instr) { struct tango_chip *tchip = to_tango_chip(chip); + unsigned int i; - return readb_relaxed(tchip->base + PBUS_DATA); -} - -static void tango_read_buf(struct nand_chip *chip, u8 *buf, int len) -{ - struct tango_chip *tchip = to_tango_chip(chip); + switch (instr->type) { + case NAND_OP_CMD_INSTR: + writeb_relaxed(instr->ctx.cmd.opcode, tchip->base + PBUS_CMD); + return 0; + case NAND_OP_ADDR_INSTR: + for (i = 0; i < instr->ctx.addr.naddrs; i++) + writeb_relaxed(instr->ctx.addr.addrs[i], + tchip->base + PBUS_ADDR); + return 0; + case NAND_OP_DATA_IN_INSTR: + ioread8_rep(tchip->base + PBUS_DATA, instr->ctx.data.buf.in, + instr->ctx.data.len); + return 0; + case NAND_OP_DATA_OUT_INSTR: + iowrite8_rep(tchip->base + PBUS_DATA, instr->ctx.data.buf.out, + instr->ctx.data.len); + return 0; + case NAND_OP_WAITRDY_INSTR: + return tango_waitrdy(chip, + instr->ctx.waitrdy.timeout_ms); + default: + break; + } - ioread8_rep(tchip->base + PBUS_DATA, buf, len); + return -EINVAL; } -static void tango_write_buf(struct nand_chip *chip, const u8 *buf, int len) +static int tango_exec_op(struct nand_chip *chip, + const struct nand_operation *op, + bool check_only) { - struct tango_chip *tchip = to_tango_chip(chip); - - iowrite8_rep(tchip->base + PBUS_DATA, buf, len); -} + unsigned int i; + int ret = 0; -static void tango_select_chip(struct nand_chip *chip, int idx) -{ - struct tango_nfc *nfc = to_tango_nfc(chip->controller); - struct tango_chip *tchip = to_tango_chip(chip); + if (check_only) + return 0; - if (idx < 0) - return; /* No "chip unselect" function */ + tango_select_target(chip, op->cs); + for (i = 0; i < op->ninstrs; i++) { + ret = tango_exec_instr(chip, &op->instrs[i]); + if (ret) + break; + } - writel_relaxed(tchip->timing1, nfc->reg_base + NFC_TIMING1); - writel_relaxed(tchip->timing2, nfc->reg_base + NFC_TIMING2); - writel_relaxed(tchip->xfer_cfg, nfc->reg_base + NFC_XFER_CFG); - writel_relaxed(tchip->pkt_0_cfg, nfc->reg_base + NFC_PKT_0_CFG); - writel_relaxed(tchip->pkt_n_cfg, nfc->reg_base + NFC_PKT_N_CFG); - writel_relaxed(tchip->bb_cfg, nfc->reg_base + NFC_BB_CFG); + return ret; } /* @@ -279,6 +300,7 @@ static int tango_read_page(struct nand_chip *chip, u8 *buf, struct tango_nfc *nfc = to_tango_nfc(chip->controller); int err, res, len = mtd->writesize; + tango_select_target(chip, chip->cur_cs); if (oob_required) chip->ecc.read_oob(chip, page); @@ -300,22 +322,30 @@ static int tango_write_page(struct nand_chip *chip, const u8 *buf, { struct mtd_info *mtd = nand_to_mtd(chip); struct tango_nfc *nfc = to_tango_nfc(chip->controller); - int err, status, len = mtd->writesize; + const struct nand_sdr_timings *timings; + int err, len = mtd->writesize; + u8 status; /* Calling tango_write_oob() would send PAGEPROG twice */ if (oob_required) return -ENOTSUPP; + tango_select_target(chip, chip->cur_cs); writel_relaxed(0xffffffff, nfc->mem_base + METADATA); err = do_dma(nfc, DMA_TO_DEVICE, NFC_WRITE, buf, len, page); if (err) return err; - status = chip->legacy.waitfunc(chip); - if (status & NAND_STATUS_FAIL) - return -EIO; + timings = nand_get_sdr_timings(&chip->data_interface); + err = tango_waitrdy(chip, PSEC_TO_MSEC(timings->tR_max)); + if (err) + return err; - return 0; + err = nand_status_op(chip, &status); + if (err) + return err; + + return (status & NAND_STATUS_FAIL) ? -EIO : 0; } static void aux_read(struct nand_chip *chip, u8 **buf, int len, int *pos) @@ -326,7 +356,9 @@ static void aux_read(struct nand_chip *chip, u8 **buf, int len, int *pos) /* skip over "len" bytes */ nand_change_read_column_op(chip, *pos, NULL, 0, false); } else { - tango_read_buf(chip, *buf, len); + struct tango_chip *tchip = to_tango_chip(chip); + + ioread8_rep(tchip->base + PBUS_DATA, *buf, len); *buf += len; } } @@ -339,7 +371,9 @@ static void aux_write(struct nand_chip *chip, const u8 **buf, int len, int *pos) /* skip over "len" bytes */ nand_change_write_column_op(chip, *pos, NULL, 0, false); } else { - tango_write_buf(chip, *buf, len); + struct tango_chip *tchip = to_tango_chip(chip); + + iowrite8_rep(tchip->base + PBUS_DATA, *buf, len); *buf += len; } } @@ -420,6 +454,7 @@ static void raw_write(struct nand_chip *chip, const u8 *buf, const u8 *oob) static int tango_read_page_raw(struct nand_chip *chip, u8 *buf, int oob_required, int page) { + tango_select_target(chip, chip->cur_cs); nand_read_page_op(chip, page, 0, NULL, 0); raw_read(chip, buf, chip->oob_poi); return 0; @@ -428,6 +463,7 @@ static int tango_read_page_raw(struct nand_chip *chip, u8 *buf, static int tango_write_page_raw(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { + tango_select_target(chip, chip->cur_cs); nand_prog_page_begin_op(chip, page, 0, NULL, 0); raw_write(chip, buf, chip->oob_poi); return nand_prog_page_end_op(chip); @@ -435,6 +471,7 @@ static int tango_write_page_raw(struct nand_chip *chip, const u8 *buf, static int tango_read_oob(struct nand_chip *chip, int page) { + tango_select_target(chip, chip->cur_cs); nand_read_page_op(chip, page, 0, NULL, 0); raw_read(chip, NULL, chip->oob_poi); return 0; @@ -442,6 +479,7 @@ static int tango_read_oob(struct nand_chip *chip, int page) static int tango_write_oob(struct nand_chip *chip, int page) { + tango_select_target(chip, chip->cur_cs); nand_prog_page_begin_op(chip, page, 0, NULL, 0); raw_write(chip, NULL, chip->oob_poi); return nand_prog_page_end_op(chip); @@ -528,6 +566,7 @@ static int tango_attach_chip(struct nand_chip *chip) static const struct nand_controller_ops tango_controller_ops = { .attach_chip = tango_attach_chip, .setup_data_interface = tango_set_timings, + .exec_op = tango_exec_op, }; static int chip_init(struct device *dev, struct device_node *np) @@ -562,12 +601,6 @@ static int chip_init(struct device *dev, struct device_node *np) ecc = &chip->ecc; mtd = nand_to_mtd(chip); - chip->legacy.read_byte = tango_read_byte; - chip->legacy.write_buf = tango_write_buf; - chip->legacy.read_buf = tango_read_buf; - chip->legacy.select_chip = tango_select_chip; - chip->legacy.cmd_ctrl = tango_cmd_ctrl; - chip->legacy.dev_ready = tango_dev_ready; chip->options = NAND_USES_DMA | NAND_NO_SUBPAGE_WRITE | NAND_WAIT_TCCS; -- GitLab From ba9f316986502471b160470e5e27a5e5a2ccadaf Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 20 May 2020 01:24:52 +0200 Subject: [PATCH 0120/1754] dt-bindings: mtd: nand: Document the generic rb-gpios property A few drivers use this property to describe GPIO pins used to sample the NAND Ready/Busy state. Let's make it part of the generic binding doc. Signed-off-by: Boris Brezillon Reviewed-by: Rob Herring Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200519232454.374081-2-boris.brezillon@collabora.com --- Documentation/devicetree/bindings/mtd/nand-controller.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/mtd/nand-controller.yaml b/Documentation/devicetree/bindings/mtd/nand-controller.yaml index cde7c4d79efe4..40fc5b0b2b8cf 100644 --- a/Documentation/devicetree/bindings/mtd/nand-controller.yaml +++ b/Documentation/devicetree/bindings/mtd/nand-controller.yaml @@ -114,6 +114,13 @@ patternProperties: description: Contains the native Ready/Busy IDs. + rb-gpios: + description: + Contains one or more GPIO descriptor (the numper of descriptor + depends on the number of R/B pins exposed by the flash) for the + Ready/Busy pins. Active state refers to the NAND ready state and + should be set to GPIOD_ACTIVE_HIGH unless the signal is inverted. + required: - reg -- GitLab From 33d226f504ed72cba3a2b42bbe2a993b3d6d9548 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 02:25:06 +0200 Subject: [PATCH 0121/1754] mtd: nand: Move nand_device forward declaration to the top This structure might be used earlier in this file, let's move the forward declaration at the top. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529002517.3546-10-miquel.raynal@bootlin.com --- include/linux/mtd/nand.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 0c7483843a32e..a1f38c778d0ee 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -12,6 +12,8 @@ #include +struct nand_device; + /** * struct nand_memory_organization - Memory organization structure * @bits_per_cell: number of bits per NAND cell @@ -133,8 +135,6 @@ struct nand_bbt { unsigned long *cache; }; -struct nand_device; - /** * struct nand_ops - NAND operations * @erase: erase a specific block. No need to check if the block is bad before -- GitLab From deedeb60e812b464c18a9902984eb3f643efcae9 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 02:25:07 +0200 Subject: [PATCH 0122/1754] mtd: nand: Add an extra level in the Kconfig hierarchy Use an extra level in Kconfig for all NAND related entries. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529002517.3546-11-miquel.raynal@bootlin.com --- drivers/mtd/nand/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index a5d8a211cb8ad..c1a45b071165a 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -1,7 +1,12 @@ # SPDX-License-Identifier: GPL-2.0-only + +menu "NAND" + config MTD_NAND_CORE tristate source "drivers/mtd/nand/onenand/Kconfig" source "drivers/mtd/nand/raw/Kconfig" source "drivers/mtd/nand/spi/Kconfig" + +endmenu -- GitLab From 6232095cc57cd096f126fa23c227a20a1669cc4f Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 02:25:08 +0200 Subject: [PATCH 0123/1754] mtd: nand: Drop useless 'depends on' in Kconfig Both OneNAND and raw NAND bits can't be compiled if MTD is disabled because of the if/endif logic in drivers/mtd/Kconfig. There is no need for an extra "depends on MTD" in their respective Kconfig files. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529002517.3546-12-miquel.raynal@bootlin.com --- drivers/mtd/nand/onenand/Kconfig | 1 - drivers/mtd/nand/raw/Kconfig | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/mtd/nand/onenand/Kconfig b/drivers/mtd/nand/onenand/Kconfig index 572b8fe69abb5..1a0e65bc246e1 100644 --- a/drivers/mtd/nand/onenand/Kconfig +++ b/drivers/mtd/nand/onenand/Kconfig @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only menuconfig MTD_ONENAND tristate "OneNAND Device Support" - depends on MTD depends on HAS_IOMEM help This enables support for accessing all type of OneNAND flash diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 113f610522692..85280e327bfe8 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -12,7 +12,6 @@ config MTD_NAND_ECC_SW_HAMMING_SMC menuconfig MTD_RAW_NAND tristate "Raw/Parallel NAND Device Support" - depends on MTD select MTD_NAND_CORE select MTD_NAND_ECC_SW_HAMMING help -- GitLab From 85f54c5588885cc3b5be4a07498dd0755de9f5cf Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 02:25:10 +0200 Subject: [PATCH 0124/1754] mtd: nand: Rename a core structure Prepare the migration to a generic ECC engine by renaming the nand_ecc_req structure into nand_ecc_props. This structure will be the base of a wider 'nand_ecc' structure. In nand_device, these properties are still named "eccreq" even if "eccprops" might be more descriptive. This is just a transition step, this field is being replaced very soon by a much wider structure. The impact of renaming this field would be huge compared to its interest. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529002517.3546-14-miquel.raynal@bootlin.com --- include/linux/mtd/nand.h | 8 ++++---- include/linux/mtd/spinand.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index a1f38c778d0ee..af99041ceaa9f 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -116,11 +116,11 @@ struct nand_page_io_req { }; /** - * struct nand_ecc_req - NAND ECC requirements + * struct nand_ecc_props - NAND ECC properties * @strength: ECC strength - * @step_size: ECC step/block size + * @step_size: Number of bytes per step */ -struct nand_ecc_req { +struct nand_ecc_props { unsigned int strength; unsigned int step_size; }; @@ -179,7 +179,7 @@ struct nand_ops { struct nand_device { struct mtd_info mtd; struct nand_memory_organization memorg; - struct nand_ecc_req eccreq; + struct nand_ecc_props eccreq; struct nand_row_converter rowconv; struct nand_bbt bbt; const struct nand_ops *ops; diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 1077c45721ff2..7b78c4ba9b3e9 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -309,7 +309,7 @@ struct spinand_info { struct spinand_devid devid; u32 flags; struct nand_memory_organization memorg; - struct nand_ecc_req eccreq; + struct nand_ecc_props eccreq; struct spinand_ecc_info eccinfo; struct { const struct spinand_op_variants *read_cache; -- GitLab From c4cabc08d09e4b107b685e08bdec8a38a91089d8 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:12:55 +0200 Subject: [PATCH 0125/1754] mtd: rawnand: Use unsigned types for nand_chip unsigned values page_shift, phys_erase_shift, bbt_erase_shift, chip_shift, pagemask, subpagesize and badblockbits are all positive values, so declare them as unsigned. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-2-miquel.raynal@bootlin.com --- include/linux/mtd/rawnand.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 65b1c1c18b41c..830f2d08937fd 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1110,11 +1110,11 @@ struct nand_chip { unsigned int options; unsigned int bbt_options; - int page_shift; - int phys_erase_shift; - int bbt_erase_shift; - int chip_shift; - int pagemask; + unsigned int page_shift; + unsigned int phys_erase_shift; + unsigned int bbt_erase_shift; + unsigned int chip_shift; + unsigned int pagemask; u8 *data_buf; struct { @@ -1122,10 +1122,10 @@ struct nand_chip { int page; } pagecache; - int subpagesize; + unsigned int subpagesize; int onfi_timing_mode_default; unsigned int badblockpos; - int badblockbits; + unsigned int badblockbits; struct nand_id id; struct nand_parameters parameters; -- GitLab From d1f3837a507d73746f9e2118fad20ee5e57e86cc Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:12:56 +0200 Subject: [PATCH 0126/1754] mtd: rawnand: Only use u8 instead of uint8_t in nand_chip structure Mechanical change to avoid using old types. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-3-miquel.raynal@bootlin.com --- include/linux/mtd/rawnand.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 830f2d08937fd..cea137778224e 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1141,13 +1141,13 @@ struct nand_chip { int (*suspend)(struct nand_chip *chip); void (*resume)(struct nand_chip *chip); - uint8_t *oob_poi; + u8 *oob_poi; struct nand_controller *controller; struct nand_ecc_ctrl ecc; unsigned long buf_align; - uint8_t *bbt; + u8 *bbt; struct nand_bbt_descr *bbt_td; struct nand_bbt_descr *bbt_md; -- GitLab From 8e8b2706e15d16443b1ea61a6f994c08ec5b9486 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:12:57 +0200 Subject: [PATCH 0127/1754] mtd: rawnand: Create a nand_chip operations structure And move nand_chip hooks there. While moving entries from one structure to the other, adapt the documentation style. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-4-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_base.c | 20 ++++++++--------- drivers/mtd/nand/raw/nand_hynix.c | 2 +- drivers/mtd/nand/raw/nand_macronix.c | 10 ++++----- drivers/mtd/nand/raw/nand_micron.c | 2 +- include/linux/mtd/rawnand.h | 32 ++++++++++++++++------------ 5 files changed, 35 insertions(+), 31 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 45124dbb18353..d9cb71e7c0ed3 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -3215,10 +3215,10 @@ static int nand_setup_read_retry(struct nand_chip *chip, int retry_mode) if (retry_mode >= chip->read_retries) return -EINVAL; - if (!chip->setup_read_retry) + if (!chip->ops.setup_read_retry) return -EOPNOTSUPP; - return chip->setup_read_retry(chip, retry_mode); + return chip->ops.setup_read_retry(chip, retry_mode); } static void nand_wait_readrdy(struct nand_chip *chip) @@ -4462,8 +4462,8 @@ static int nand_suspend(struct mtd_info *mtd) int ret = 0; mutex_lock(&chip->lock); - if (chip->suspend) - ret = chip->suspend(chip); + if (chip->ops.suspend) + ret = chip->ops.suspend(chip); if (!ret) chip->suspended = 1; mutex_unlock(&chip->lock); @@ -4481,8 +4481,8 @@ static void nand_resume(struct mtd_info *mtd) mutex_lock(&chip->lock); if (chip->suspended) { - if (chip->resume) - chip->resume(chip); + if (chip->ops.resume) + chip->ops.resume(chip); chip->suspended = 0; } else { pr_err("%s called for a chip which is not in suspended state\n", @@ -4511,10 +4511,10 @@ static int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { struct nand_chip *chip = mtd_to_nand(mtd); - if (!chip->lock_area) + if (!chip->ops.lock_area) return -ENOTSUPP; - return chip->lock_area(chip, ofs, len); + return chip->ops.lock_area(chip, ofs, len); } /** @@ -4527,10 +4527,10 @@ static int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { struct nand_chip *chip = mtd_to_nand(mtd); - if (!chip->unlock_area) + if (!chip->ops.unlock_area) return -ENOTSUPP; - return chip->unlock_area(chip, ofs, len); + return chip->ops.unlock_area(chip, ofs, len); } /* Set default functions */ diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c index 7caedaa5b9e59..7d1be53f27f3f 100644 --- a/drivers/mtd/nand/raw/nand_hynix.c +++ b/drivers/mtd/nand/raw/nand_hynix.c @@ -337,7 +337,7 @@ static int hynix_mlc_1xnm_rr_init(struct nand_chip *chip, rr->nregs = nregs; rr->regs = hynix_1xnm_mlc_read_retry_regs; hynix->read_retry = rr; - chip->setup_read_retry = hynix_nand_setup_read_retry; + chip->ops.setup_read_retry = hynix_nand_setup_read_retry; chip->read_retries = nmodes; out: diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c index 09c254c97b5c8..1472f925f3868 100644 --- a/drivers/mtd/nand/raw/nand_macronix.c +++ b/drivers/mtd/nand/raw/nand_macronix.c @@ -130,7 +130,7 @@ static void macronix_nand_onfi_init(struct nand_chip *chip) return; chip->read_retries = MACRONIX_NUM_READ_RETRY_MODES; - chip->setup_read_retry = macronix_nand_setup_read_retry; + chip->ops.setup_read_retry = macronix_nand_setup_read_retry; if (p->supports_set_get_features) { bitmap_set(p->set_feature_list, @@ -242,8 +242,8 @@ static void macronix_nand_block_protection_support(struct nand_chip *chip) bitmap_set(chip->parameters.set_feature_list, ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1); - chip->lock_area = mxic_nand_lock; - chip->unlock_area = mxic_nand_unlock; + chip->ops.lock_area = mxic_nand_lock; + chip->ops.unlock_area = mxic_nand_unlock; } static int nand_power_down_op(struct nand_chip *chip) @@ -312,8 +312,8 @@ static void macronix_nand_deep_power_down_support(struct nand_chip *chip) if (i < 0) return; - chip->suspend = mxic_nand_suspend; - chip->resume = mxic_nand_resume; + chip->ops.suspend = mxic_nand_suspend; + chip->ops.resume = mxic_nand_resume; } static int macronix_nand_init(struct nand_chip *chip) diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c index 3589b4fce0d48..4385092a9325b 100644 --- a/drivers/mtd/nand/raw/nand_micron.c +++ b/drivers/mtd/nand/raw/nand_micron.c @@ -84,7 +84,7 @@ static int micron_nand_onfi_init(struct nand_chip *chip) struct nand_onfi_vendor_micron *micron = (void *)p->onfi->vendor; chip->read_retries = micron->read_retry_options; - chip->setup_read_retry = micron_nand_setup_read_retry; + chip->ops.setup_read_retry = micron_nand_setup_read_retry; } if (p->supports_set_get_features) { diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index cea137778224e..7f9be95ca8dcf 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1027,16 +1027,31 @@ struct nand_legacy { struct nand_controller dummy_controller; }; +/** + * struct nand_chip_ops - NAND chip operations + * @suspend: Suspend operation + * @resume: Resume operation + * @lock_area: Lock operation + * @unlock_area: Unlock operation + * @setup_read_retry: Set the read-retry mode (mostly needed for MLC NANDs) + */ +struct nand_chip_ops { + int (*suspend)(struct nand_chip *chip); + void (*resume)(struct nand_chip *chip); + int (*lock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len); + int (*unlock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len); + int (*setup_read_retry)(struct nand_chip *chip, int retry_mode); +}; + /** * struct nand_chip - NAND Private Flash Chip Data * @base: Inherit from the generic NAND device + * @ops: NAND chip operations * @legacy: All legacy fields/hooks. If you develop a new driver, * don't even try to use any of these fields/hooks, and if * you're modifying an existing driver that is using those * fields/hooks, you should consider reworking the driver * avoid using them. - * @setup_read_retry: [FLASHSPECIFIC] flash (vendor) specific function for - * setting the read-retry mode. Mostly needed for MLC NAND. * @ecc: [BOARDSPECIFIC] ECC control structure * @buf_align: minimum buffer alignment required by a platform * @oob_poi: "poison value buffer," used for laying out OOB data @@ -1081,8 +1096,6 @@ struct nand_legacy { * @lock: lock protecting the suspended field. Also used to * serialize accesses to the NAND device. * @suspended: set to 1 when the device is suspended, 0 when it's not. - * @suspend: [REPLACEABLE] specific NAND device suspend operation - * @resume: [REPLACEABLE] specific NAND device resume operation * @bbt: [INTERN] bad block table pointer * @bbt_td: [REPLACEABLE] bad block table descriptor for flash * lookup. @@ -1096,17 +1109,13 @@ struct nand_legacy { * @manufacturer: [INTERN] Contains manufacturer information * @manufacturer.desc: [INTERN] Contains manufacturer's description * @manufacturer.priv: [INTERN] Contains manufacturer private information - * @lock_area: [REPLACEABLE] specific NAND chip lock operation - * @unlock_area: [REPLACEABLE] specific NAND chip unlock operation */ struct nand_chip { struct nand_device base; - + struct nand_chip_ops ops; struct nand_legacy legacy; - int (*setup_read_retry)(struct nand_chip *chip, int retry_mode); - unsigned int options; unsigned int bbt_options; @@ -1138,8 +1147,6 @@ struct nand_chip { struct mutex lock; unsigned int suspended : 1; - int (*suspend)(struct nand_chip *chip); - void (*resume)(struct nand_chip *chip); u8 *oob_poi; struct nand_controller *controller; @@ -1159,9 +1166,6 @@ struct nand_chip { const struct nand_manufacturer *desc; void *priv; } manufacturer; - - int (*lock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len); - int (*unlock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len); }; extern const struct mtd_ooblayout_ops nand_ooblayout_sp_ops; -- GitLab From 271de009b7c0c1c15f63491a352ab08835462977 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:12:58 +0200 Subject: [PATCH 0128/1754] mtd: rawnand: Rename the manufacturer structure It is currently called nand_manufacturer but could actually be called nand_manufacturer_desc, like its instances, so that the former name is left unused for now. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-5-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/internals.h | 6 +++--- drivers/mtd/nand/raw/nand_base.c | 14 +++++++------- drivers/mtd/nand/raw/nand_ids.c | 16 ++++++++-------- include/linux/mtd/rawnand.h | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index 03866b0aadea7..a518acfd9b3fa 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -53,12 +53,12 @@ struct nand_manufacturer_ops { }; /** - * struct nand_manufacturer - NAND Flash Manufacturer structure + * struct nand_manufacturer_desc - NAND Flash Manufacturer descriptor * @name: Manufacturer name * @id: manufacturer ID code of device. * @ops: manufacturer operations */ -struct nand_manufacturer { +struct nand_manufacturer_desc { int id; char *name; const struct nand_manufacturer_ops *ops; @@ -79,7 +79,7 @@ extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops; extern const struct mtd_pairing_scheme dist3_pairing_scheme; /* Core functions */ -const struct nand_manufacturer *nand_get_manufacturer(u8 id); +const struct nand_manufacturer_desc *nand_get_manufacturer_desc(u8 id); int nand_bbm_get_next_page(struct nand_chip *chip, int page); int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs); int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index d9cb71e7c0ed3..534ee75d0f2bd 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -4810,9 +4810,9 @@ static void nand_manufacturer_cleanup(struct nand_chip *chip) } static const char * -nand_manufacturer_name(const struct nand_manufacturer *manufacturer) +nand_manufacturer_name(const struct nand_manufacturer_desc *manufacturer_desc) { - return manufacturer ? manufacturer->name : "Unknown"; + return manufacturer_desc ? manufacturer_desc->name : "Unknown"; } /* @@ -4820,7 +4820,7 @@ nand_manufacturer_name(const struct nand_manufacturer *manufacturer) */ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) { - const struct nand_manufacturer *manufacturer; + const struct nand_manufacturer_desc *manufacturer_desc; struct mtd_info *mtd = nand_to_mtd(chip); struct nand_memory_organization *memorg; int busw, ret; @@ -4877,8 +4877,8 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) chip->id.len = nand_id_len(id_data, ARRAY_SIZE(chip->id.data)); /* Try to identify manufacturer */ - manufacturer = nand_get_manufacturer(maf_id); - chip->manufacturer.desc = manufacturer; + manufacturer_desc = nand_get_manufacturer_desc(maf_id); + chip->manufacturer.desc = manufacturer_desc; if (!type) type = nand_flash_ids; @@ -4957,7 +4957,7 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) */ pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", maf_id, dev_id); - pr_info("%s %s\n", nand_manufacturer_name(manufacturer), + pr_info("%s %s\n", nand_manufacturer_name(manufacturer_desc), mtd->name); pr_warn("bus width %d instead of %d bits\n", busw ? 16 : 8, (chip->options & NAND_BUSWIDTH_16) ? 16 : 8); @@ -4992,7 +4992,7 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", maf_id, dev_id); - pr_info("%s %s\n", nand_manufacturer_name(manufacturer), + pr_info("%s %s\n", nand_manufacturer_name(manufacturer_desc), chip->parameters.model); pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n", (int)(targetsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c index ba27902fc54bc..e0dbc2e316c76 100644 --- a/drivers/mtd/nand/raw/nand_ids.c +++ b/drivers/mtd/nand/raw/nand_ids.c @@ -166,7 +166,7 @@ struct nand_flash_dev nand_flash_ids[] = { }; /* Manufacturer IDs */ -static const struct nand_manufacturer nand_manufacturers[] = { +static const struct nand_manufacturer_desc nand_manufacturer_descs[] = { {NAND_MFR_AMD, "AMD/Spansion", &amd_nand_manuf_ops}, {NAND_MFR_ATO, "ATO"}, {NAND_MFR_EON, "Eon"}, @@ -186,20 +186,20 @@ static const struct nand_manufacturer nand_manufacturers[] = { }; /** - * nand_get_manufacturer - Get manufacturer information from the manufacturer - * ID + * nand_get_manufacturer_desc - Get manufacturer information from the + * manufacturer ID * @id: manufacturer ID * - * Returns a pointer a nand_manufacturer object if the manufacturer is defined + * Returns a nand_manufacturer_desc object if the manufacturer is defined * in the NAND manufacturers database, NULL otherwise. */ -const struct nand_manufacturer *nand_get_manufacturer(u8 id) +const struct nand_manufacturer_desc *nand_get_manufacturer_desc(u8 id) { int i; - for (i = 0; i < ARRAY_SIZE(nand_manufacturers); i++) - if (nand_manufacturers[i].id == id) - return &nand_manufacturers[i]; + for (i = 0; i < ARRAY_SIZE(nand_manufacturer_descs); i++) + if (nand_manufacturer_descs[i].id == id) + return &nand_manufacturer_descs[i]; return NULL; } diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 7f9be95ca8dcf..860d3c1020ef4 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1163,7 +1163,7 @@ struct nand_chip { void *priv; struct { - const struct nand_manufacturer *desc; + const struct nand_manufacturer_desc *desc; void *priv; } manufacturer; }; -- GitLab From 36017af430e6b2fad0b2ee5476103706160f1379 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:12:59 +0200 Subject: [PATCH 0129/1754] mtd: rawnand: Declare the nand_manufacturer structure out of nand_chip Now that struct nand_manufacturer type is free, use it to store the nand_manufacturer_desc and the manufacturer's private data. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-6-miquel.raynal@bootlin.com --- include/linux/mtd/rawnand.h | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 860d3c1020ef4..a3dfa36a9fd50 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1043,10 +1043,21 @@ struct nand_chip_ops { int (*setup_read_retry)(struct nand_chip *chip, int retry_mode); }; +/** + * struct nand_manufacturer - NAND manufacturer structure + * @desc: The manufacturer description + * @priv: Private information for the manufacturer driver + */ +struct nand_manufacturer { + const struct nand_manufacturer_desc *desc; + void *priv; +}; + /** * struct nand_chip - NAND Private Flash Chip Data * @base: Inherit from the generic NAND device * @ops: NAND chip operations + * @manufacturer: Manufacturer information * @legacy: All legacy fields/hooks. If you develop a new driver, * don't even try to use any of these fields/hooks, and if * you're modifying an existing driver that is using those @@ -1106,13 +1117,11 @@ struct nand_chip_ops { * structure which is shared among multiple independent * devices. * @priv: [OPTIONAL] pointer to private chip data - * @manufacturer: [INTERN] Contains manufacturer information - * @manufacturer.desc: [INTERN] Contains manufacturer's description - * @manufacturer.priv: [INTERN] Contains manufacturer private information */ struct nand_chip { struct nand_device base; + struct nand_manufacturer manufacturer; struct nand_chip_ops ops; struct nand_legacy legacy; @@ -1161,11 +1170,6 @@ struct nand_chip { struct nand_bbt_descr *badblock_pattern; void *priv; - - struct { - const struct nand_manufacturer_desc *desc; - void *priv; - } manufacturer; }; extern const struct mtd_ooblayout_ops nand_ooblayout_sp_ops; -- GitLab From a63674c7cfe62221e05ba73107d9e15d73ff8bbd Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:00 +0200 Subject: [PATCH 0130/1754] mtd: rawnand: Reorganize the nand_chip structure Reorder fields in this structure and pack entries by theme: * The main descriptive structures * The data interface details * Bad block information * The device layout * Extra buffers matching the device layout * Internal values * External objects like the ECC controller, the ECC engine and a private data pointer. While at it, adapt the documentation style. I changed on purpose the description of @oob_poi which was weird. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-7-miquel.raynal@bootlin.com --- include/linux/mtd/rawnand.h | 166 +++++++++++++++++------------------- 1 file changed, 76 insertions(+), 90 deletions(-) diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index a3dfa36a9fd50..544ec8736793a 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1055,120 +1055,106 @@ struct nand_manufacturer { /** * struct nand_chip - NAND Private Flash Chip Data - * @base: Inherit from the generic NAND device - * @ops: NAND chip operations - * @manufacturer: Manufacturer information - * @legacy: All legacy fields/hooks. If you develop a new driver, - * don't even try to use any of these fields/hooks, and if - * you're modifying an existing driver that is using those - * fields/hooks, you should consider reworking the driver - * avoid using them. - * @ecc: [BOARDSPECIFIC] ECC control structure - * @buf_align: minimum buffer alignment required by a platform - * @oob_poi: "poison value buffer," used for laying out OOB data - * before writing - * @page_shift: [INTERN] number of address bits in a page (column - * address bits). - * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock - * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry - * @chip_shift: [INTERN] number of address bits in one chip - * @options: [BOARDSPECIFIC] various chip options. They can partly - * be set to inform nand_scan about special functionality. - * See the defines for further explanation. - * @bbt_options: [INTERN] bad block specific options. All options used - * here must come from bbm.h. By default, these options - * will be copied to the appropriate nand_bbt_descr's. - * @badblockpos: [INTERN] position of the bad block marker in the oob - * area. - * @badblockbits: [INTERN] minimum number of set bits in a good block's - * bad block marker position; i.e., BBM == 11110111b is - * not bad when badblockbits == 7 - * @onfi_timing_mode_default: [INTERN] default ONFI timing mode. This field is - * set to the actually used ONFI mode if the chip is - * ONFI compliant or deduced from the datasheet if - * the NAND chip is not ONFI compliant. - * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 - * @data_buf: [INTERN] buffer for data, size is (page size + oobsize). - * @pagecache: Structure containing page cache related fields - * @pagecache.bitflips: Number of bitflips of the cached page - * @pagecache.page: Page number currently in the cache. -1 means no page is - * currently cached - * @subpagesize: [INTERN] holds the subpagesize - * @id: [INTERN] holds NAND ID - * @parameters: [INTERN] holds generic parameters under an easily - * readable form. - * @data_interface: [INTERN] NAND interface timing information - * @cur_cs: currently selected target. -1 means no target selected, - * otherwise we should always have cur_cs >= 0 && - * cur_cs < nanddev_ntargets(). NAND Controller drivers - * should not modify this value, but they're allowed to - * read it. - * @read_retries: [INTERN] the number of read retry modes supported - * @lock: lock protecting the suspended field. Also used to - * serialize accesses to the NAND device. - * @suspended: set to 1 when the device is suspended, 0 when it's not. - * @bbt: [INTERN] bad block table pointer - * @bbt_td: [REPLACEABLE] bad block table descriptor for flash - * lookup. - * @bbt_md: [REPLACEABLE] bad block table mirror descriptor - * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial - * bad block scan. - * @controller: [REPLACEABLE] a pointer to a hardware controller - * structure which is shared among multiple independent - * devices. - * @priv: [OPTIONAL] pointer to private chip data + * @base: Inherit from the generic NAND device + * @id: Holds NAND ID + * @parameters: Holds generic parameters under an easily readable form + * @manufacturer: Manufacturer information + * @ops: NAND chip operations + * @legacy: All legacy fields/hooks. If you develop a new driver, don't even try + * to use any of these fields/hooks, and if you're modifying an + * existing driver that is using those fields/hooks, you should + * consider reworking the driver and avoid using them. + * @options: Various chip options. They can partly be set to inform nand_scan + * about special functionality. See the defines for further + * explanation. + * @onfi_timing_mode_default: Default ONFI timing mode. This field is set to the + * actually used ONFI mode if the chip is ONFI + * compliant or deduced from the datasheet otherwise + * @data_interface: NAND interface timing information + * @bbt_erase_shift: Number of address bits in a bbt entry + * @bbt_options: Bad block table specific options. All options used here must + * come from bbm.h. By default, these options will be copied to + * the appropriate nand_bbt_descr's. + * @badblockpos: Bad block marker position in the oob area + * @badblockbits: Minimum number of set bits in a good block's bad block marker + * position; i.e., BBM = 11110111b is good when badblockbits = 7 + * @bbt_td: Bad block table descriptor for flash lookup + * @bbt_md: Bad block table mirror descriptor + * @badblock_pattern: Bad block scan pattern used for initial bad block scan + * @bbt: Bad block table pointer + * @page_shift: Number of address bits in a page (column address bits) + * @phys_erase_shift: Number of address bits in a physical eraseblock + * @chip_shift: Number of address bits in one chip + * @pagemask: Page number mask = number of (pages / chip) - 1 + * @subpagesize: Holds the subpagesize + * @data_buf: Buffer for data, size is (page size + oobsize) + * @oob_poi: pointer on the OOB area covered by data_buf + * @pagecache: Structure containing page cache related fields + * @pagecache.bitflips: Number of bitflips of the cached page + * @pagecache.page: Page number currently in the cache. -1 means no page is + * currently cached + * @buf_align: Minimum buffer alignment required by a platform + * @lock: Lock protecting the suspended field. Also used to serialize accesses + * to the NAND device + * @suspended: Set to 1 when the device is suspended, 0 when it's not + * @cur_cs: Currently selected target. -1 means no target selected, otherwise we + * should always have cur_cs >= 0 && cur_cs < nanddev_ntargets(). + * NAND Controller drivers should not modify this value, but they're + * allowed to read it. + * @read_retries: The number of read retry modes supported + * @controller: The hardware controller structure which is shared among multiple + * independent devices + * @ecc: The ECC controller structure + * @priv: Chip private data */ - struct nand_chip { struct nand_device base; + struct nand_id id; + struct nand_parameters parameters; struct nand_manufacturer manufacturer; struct nand_chip_ops ops; struct nand_legacy legacy; - unsigned int options; + + /* Data interface */ + int onfi_timing_mode_default; + struct nand_data_interface data_interface; + + /* Bad block information */ + unsigned int bbt_erase_shift; unsigned int bbt_options; + unsigned int badblockpos; + unsigned int badblockbits; + struct nand_bbt_descr *bbt_td; + struct nand_bbt_descr *bbt_md; + struct nand_bbt_descr *badblock_pattern; + u8 *bbt; + /* Device internal layout */ unsigned int page_shift; unsigned int phys_erase_shift; - unsigned int bbt_erase_shift; unsigned int chip_shift; unsigned int pagemask; - u8 *data_buf; + unsigned int subpagesize; + /* Buffers */ + u8 *data_buf; + u8 *oob_poi; struct { unsigned int bitflips; int page; } pagecache; + unsigned long buf_align; - unsigned int subpagesize; - int onfi_timing_mode_default; - unsigned int badblockpos; - unsigned int badblockbits; - - struct nand_id id; - struct nand_parameters parameters; - - struct nand_data_interface data_interface; - - int cur_cs; - - int read_retries; - + /* Internals */ struct mutex lock; unsigned int suspended : 1; + int cur_cs; + int read_retries; - u8 *oob_poi; + /* Externals */ struct nand_controller *controller; - struct nand_ecc_ctrl ecc; - unsigned long buf_align; - - u8 *bbt; - struct nand_bbt_descr *bbt_td; - struct nand_bbt_descr *bbt_md; - - struct nand_bbt_descr *badblock_pattern; - void *priv; }; -- GitLab From 6ef10df37e7dd99a5a16228fabcc3a5141585b66 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:01 +0200 Subject: [PATCH 0131/1754] mtd: rawnand: Compare the actual timing values Avoid relying just on the default timing mode to discriminate if the data interface must be restored. This field should only be used at initialization time by legacy chips statically defined. Do a memcmp() instead. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-8-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_base.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 534ee75d0f2bd..3526c2a50bbed 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -2512,7 +2512,8 @@ int nand_reset(struct nand_chip *chip, int chipnr) * nand_setup_data_interface() uses ->set/get_features() which would * fail anyway as the parameter page is not available yet. */ - if (!chip->onfi_timing_mode_default) + if (!memcmp(&chip->data_interface, &saved_data_intf, + sizeof(saved_data_intf))) return 0; chip->data_interface = saved_data_intf; -- GitLab From fe7f7b0846bdcc53a3d3e83fea67f988ab5145d8 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:02 +0200 Subject: [PATCH 0132/1754] mtd: rawnand: Use the data interface mode entry when relevant The data interface setup does not care about the default timing mode but cares about the actual timing mode at the time of the call of this helper. Use this entry instead and let chip->default_timing_mode only be used at initialization time. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-9-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_base.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 3526c2a50bbed..6e06ccf61aeb2 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -951,9 +951,8 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr) */ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) { - u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { - chip->onfi_timing_mode_default, - }; + u8 mode = chip->data_interface.timings.mode; + u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { mode, }; int ret; if (!nand_has_setup_data_iface(chip)) @@ -987,9 +986,9 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) if (ret) goto err_reset_chip; - if (tmode_param[0] != chip->onfi_timing_mode_default) { + if (tmode_param[0] != mode) { pr_warn("timing mode %d not acknowledged by the NAND chip\n", - chip->onfi_timing_mode_default); + mode); goto err_reset_chip; } -- GitLab From adcf98b2d87429dfbc114666a8be6f2b36f5d898 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:03 +0200 Subject: [PATCH 0133/1754] mtd: rawnand: Rename nand_has_setup_data_iface() This is really a NAND controller hook so call it nand_controller_can_setup_data_iface(), which makes much more sense. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-10-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/internals.h | 2 +- drivers/mtd/nand/raw/nand_base.c | 6 +++--- drivers/mtd/nand/raw/nand_legacy.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index a518acfd9b3fa..a5e2cec7e301f 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -130,7 +130,7 @@ static inline int nand_exec_op(struct nand_chip *chip, return chip->controller->ops->exec_op(chip, op, false); } -static inline bool nand_has_setup_data_iface(struct nand_chip *chip) +static inline bool nand_controller_can_setup_data_iface(struct nand_chip *chip) { if (!chip->controller || !chip->controller->ops || !chip->controller->ops->setup_data_interface) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 6e06ccf61aeb2..2a477ce811659 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -910,7 +910,7 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr) { int ret; - if (!nand_has_setup_data_iface(chip)) + if (!nand_controller_can_setup_data_iface(chip)) return 0; /* @@ -955,7 +955,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { mode, }; int ret; - if (!nand_has_setup_data_iface(chip)) + if (!nand_controller_can_setup_data_iface(chip)) return 0; /* Change the mode on the chip side (if supported by the NAND chip) */ @@ -1025,7 +1025,7 @@ static int nand_init_data_interface(struct nand_chip *chip) { int modes, mode, ret; - if (!nand_has_setup_data_iface(chip)) + if (!nand_controller_can_setup_data_iface(chip)) return 0; /* diff --git a/drivers/mtd/nand/raw/nand_legacy.c b/drivers/mtd/nand/raw/nand_legacy.c index d64791c06a977..848403dcae03b 100644 --- a/drivers/mtd/nand/raw/nand_legacy.c +++ b/drivers/mtd/nand/raw/nand_legacy.c @@ -365,7 +365,7 @@ static void nand_ccs_delay(struct nand_chip *chip) * Wait tCCS_min if it is correctly defined, otherwise wait 500ns * (which should be safe for all NANDs). */ - if (nand_has_setup_data_iface(chip)) + if (nand_controller_can_setup_data_iface(chip)) ndelay(chip->data_interface.timings.sdr.tCCS_min / 1000); else ndelay(500); -- GitLab From 8d69a80f541db0f58ebe92801bedbf17199738bd Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:04 +0200 Subject: [PATCH 0134/1754] mtd: rawnand: Fix nand_setup_data_interface() description This is a copy/paste error and belongs to nand_init_data_interface() description. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-11-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_base.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 2a477ce811659..01e788e0d0108 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -941,11 +941,8 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr) * @chip: The NAND chip * @chipnr: Internal die id * - * Find and configure the best data interface and NAND timings supported by - * the chip and the driver. - * First tries to retrieve supported timing modes from ONFI information, - * and if the NAND chip does not support ONFI, relies on the - * ->onfi_timing_mode_default specified in the nand_ids table. + * Configure what has been reported to be the best data interface and NAND + * timings supported by the chip and the driver. * * Returns 0 for success or negative error code otherwise. */ -- GitLab From 5e179a532a9954883685748b60081e75b33f0d32 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:05 +0200 Subject: [PATCH 0135/1754] mtd: rawnand: Rename nand_init_data_interface() This name is a bit misleading, what we do in this helper is trying to find the best SDR timings supported by the controller and the chip. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-12-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_base.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 01e788e0d0108..1d9cf02d164ba 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -1005,7 +1005,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) } /** - * nand_init_data_interface - find the best data interface and timings + * nand_choose_data_interface - find the best data interface and timings * @chip: The NAND chip * * Find the best data interface and NAND timings supported by the chip @@ -1018,7 +1018,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) * * Returns 0 for success or negative error code otherwise. */ -static int nand_init_data_interface(struct nand_chip *chip) +static int nand_choose_data_interface(struct nand_chip *chip) { int modes, mode, ret; @@ -5969,8 +5969,8 @@ static int nand_scan_tail(struct nand_chip *chip) if (!mtd->bitflip_threshold) mtd->bitflip_threshold = DIV_ROUND_UP(mtd->ecc_strength * 3, 4); - /* Initialize the ->data_interface field. */ - ret = nand_init_data_interface(chip); + /* Find the fastest data interface for this chip */ + ret = nand_choose_data_interface(chip); if (ret) goto err_nanddev_cleanup; -- GitLab From 844cc46460095023365345bfe61a0f195f9cb66e Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:06 +0200 Subject: [PATCH 0136/1754] mtd: rawnand: timings: Update onfi_fill_data_interface() kernel doc Describe all parameters and drop the legacy [NAND Interface] prefix. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-13-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_timings.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c index 36d21be3dfe5a..a73d934e86f99 100644 --- a/drivers/mtd/nand/raw/nand_timings.c +++ b/drivers/mtd/nand/raw/nand_timings.c @@ -274,9 +274,10 @@ static const struct nand_data_interface onfi_sdr_timings[] = { }; /** - * onfi_fill_data_interface - [NAND Interface] Initialize a data interface from - * given ONFI mode - * @mode: The ONFI timing mode + * onfi_fill_data_interface - Initialize a data interface from a given ONFI mode + * @chip: The NAND chip + * @type: The data interface type + * @timing_mode: The ONFI timing mode */ int onfi_fill_data_interface(struct nand_chip *chip, enum nand_data_interface_type type, -- GitLab From 623c0141f560800c4fc7a7502654994633791d36 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:07 +0200 Subject: [PATCH 0137/1754] mtd: rawnand: timings: Provide onfi_fill_data_interface() with a data interface Right now the core uses onfi_fill_data_interface() to initialize the nand_data_interface object embedded in nand_chip, but we are about to allocate this object dynamically and let manufacturer drivers provide their own interface config. Let's patch the onfi_fill_data_interface() so it can initialize an interface config that's not the one currently attached to the nand_chip. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-14-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/internals.h | 1 + drivers/mtd/nand/raw/nand_base.c | 7 ++++--- drivers/mtd/nand/raw/nand_timings.c | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index a5e2cec7e301f..0f74509abc4c7 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -85,6 +85,7 @@ int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs); int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, int allowbbt); int onfi_fill_data_interface(struct nand_chip *chip, + struct nand_data_interface *iface, enum nand_data_interface_type type, int timing_mode); int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param); diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 1d9cf02d164ba..b4de85794e07d 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -927,7 +927,7 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr) * timings to timing mode 0. */ - onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0); + onfi_fill_data_interface(chip, &chip->data_interface, NAND_SDR_IFACE, 0); ret = chip->controller->ops->setup_data_interface(chip, chipnr, &chip->data_interface); if (ret) @@ -1040,7 +1040,8 @@ static int nand_choose_data_interface(struct nand_chip *chip) } for (mode = fls(modes) - 1; mode >= 0; mode--) { - ret = onfi_fill_data_interface(chip, NAND_SDR_IFACE, mode); + ret = onfi_fill_data_interface(chip, &chip->data_interface, + NAND_SDR_IFACE, mode); if (ret) continue; @@ -5182,7 +5183,7 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips, mutex_init(&chip->lock); /* Enforce the right timings for reset/detection */ - onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0); + onfi_fill_data_interface(chip, &chip->data_interface, NAND_SDR_IFACE, 0); ret = nand_dt_init(chip); if (ret) diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c index a73d934e86f99..ce6bb87db2e86 100644 --- a/drivers/mtd/nand/raw/nand_timings.c +++ b/drivers/mtd/nand/raw/nand_timings.c @@ -276,14 +276,15 @@ static const struct nand_data_interface onfi_sdr_timings[] = { /** * onfi_fill_data_interface - Initialize a data interface from a given ONFI mode * @chip: The NAND chip + * @iface: The data interface to fill * @type: The data interface type * @timing_mode: The ONFI timing mode */ int onfi_fill_data_interface(struct nand_chip *chip, + struct nand_data_interface *iface, enum nand_data_interface_type type, int timing_mode) { - struct nand_data_interface *iface = &chip->data_interface; struct onfi_params *onfi = chip->parameters.onfi; if (type != NAND_SDR_IFACE) -- GitLab From fcaab3b26d2534ec9f227810975ad220823ac578 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:08 +0200 Subject: [PATCH 0138/1754] mtd: rawnand: timings: onfi_fill_data_interface timing mode is unsigned Turn this argument into an unsigned int, as it cannot be signed. This also spares a check. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-15-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/internals.h | 2 +- drivers/mtd/nand/raw/nand_timings.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index 0f74509abc4c7..bd10ec92f04a0 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -87,7 +87,7 @@ int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, int onfi_fill_data_interface(struct nand_chip *chip, struct nand_data_interface *iface, enum nand_data_interface_type type, - int timing_mode); + unsigned int timing_mode); int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param); int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param); int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf, diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c index ce6bb87db2e86..08dc381349faa 100644 --- a/drivers/mtd/nand/raw/nand_timings.c +++ b/drivers/mtd/nand/raw/nand_timings.c @@ -283,14 +283,14 @@ static const struct nand_data_interface onfi_sdr_timings[] = { int onfi_fill_data_interface(struct nand_chip *chip, struct nand_data_interface *iface, enum nand_data_interface_type type, - int timing_mode) + unsigned int timing_mode) { struct onfi_params *onfi = chip->parameters.onfi; if (type != NAND_SDR_IFACE) return -EINVAL; - if (timing_mode < 0 || timing_mode >= ARRAY_SIZE(onfi_sdr_timings)) + if (timing_mode >= ARRAY_SIZE(onfi_sdr_timings)) return -EINVAL; *iface = onfi_sdr_timings[timing_mode]; -- GitLab From 98d6979aa898239ec2faa10467c338a808e1287e Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:09 +0200 Subject: [PATCH 0139/1754] mtd: rawnand: timings: Add a helper to find the closest ONFI mode Vendors are allowed to provide their own set of timings. In this case, we provide a way to derive the "closest" timing mode so that, if the NAND controller does not support tweaking these parameters, it will be able to configure itself anyway. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-16-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/internals.h | 2 ++ drivers/mtd/nand/raw/nand_timings.c | 47 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index bd10ec92f04a0..f851ed210d707 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -88,6 +88,8 @@ int onfi_fill_data_interface(struct nand_chip *chip, struct nand_data_interface *iface, enum nand_data_interface_type type, unsigned int timing_mode); +unsigned int +onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings); int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param); int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param); int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf, diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c index 08dc381349faa..b089f2dc5f235 100644 --- a/drivers/mtd/nand/raw/nand_timings.c +++ b/drivers/mtd/nand/raw/nand_timings.c @@ -273,6 +273,53 @@ static const struct nand_data_interface onfi_sdr_timings[] = { }, }; +/** + * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a + * set of timings + * @spec_timings: the timings to challenge + */ +unsigned int +onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings) +{ + const struct nand_sdr_timings *onfi_timings; + int mode; + + for (mode = ARRAY_SIZE(onfi_sdr_timings) - 1; mode > 0; mode--) { + onfi_timings = &onfi_sdr_timings[mode].timings.sdr; + + if (spec_timings->tCCS_min <= onfi_timings->tCCS_min && + spec_timings->tADL_min <= onfi_timings->tADL_min && + spec_timings->tALH_min <= onfi_timings->tALH_min && + spec_timings->tALS_min <= onfi_timings->tALS_min && + spec_timings->tAR_min <= onfi_timings->tAR_min && + spec_timings->tCEH_min <= onfi_timings->tCEH_min && + spec_timings->tCH_min <= onfi_timings->tCH_min && + spec_timings->tCLH_min <= onfi_timings->tCLH_min && + spec_timings->tCLR_min <= onfi_timings->tCLR_min && + spec_timings->tCLS_min <= onfi_timings->tCLS_min && + spec_timings->tCOH_min <= onfi_timings->tCOH_min && + spec_timings->tCS_min <= onfi_timings->tCS_min && + spec_timings->tDH_min <= onfi_timings->tDH_min && + spec_timings->tDS_min <= onfi_timings->tDS_min && + spec_timings->tIR_min <= onfi_timings->tIR_min && + spec_timings->tRC_min <= onfi_timings->tRC_min && + spec_timings->tREH_min <= onfi_timings->tREH_min && + spec_timings->tRHOH_min <= onfi_timings->tRHOH_min && + spec_timings->tRHW_min <= onfi_timings->tRHW_min && + spec_timings->tRLOH_min <= onfi_timings->tRLOH_min && + spec_timings->tRP_min <= onfi_timings->tRP_min && + spec_timings->tRR_min <= onfi_timings->tRR_min && + spec_timings->tWC_min <= onfi_timings->tWC_min && + spec_timings->tWH_min <= onfi_timings->tWH_min && + spec_timings->tWHR_min <= onfi_timings->tWHR_min && + spec_timings->tWP_min <= onfi_timings->tWP_min && + spec_timings->tWW_min <= onfi_timings->tWW_min) + return mode; + } + + return 0; +} + /** * onfi_fill_data_interface - Initialize a data interface from a given ONFI mode * @chip: The NAND chip -- GitLab From 173d548b64e14d3d1f22191cc0092c47631a18db Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:10 +0200 Subject: [PATCH 0140/1754] mtd: rawnand: timings: Avoid redefining tR_max and tCCS_min These two values are already hardcoded in the default ONFI timing structure, no need to redefine them here. Plus, we want to be able to reference timing mode 0 easily and reliably, without extra computation, so we get rid of the extra assignations. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-17-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_timings.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c index b089f2dc5f235..54c7a1a8b038a 100644 --- a/drivers/mtd/nand/raw/nand_timings.c +++ b/drivers/mtd/nand/raw/nand_timings.c @@ -369,9 +369,6 @@ int onfi_fill_data_interface(struct nand_chip *chip, /* microseconds -> picoseconds */ timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX; timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX; - - timings->tR_max = 200000000; - timings->tCCS_min = 500000; } return 0; -- GitLab From d1bfe1e31932822ee90fc6b4cdeae785f70b3650 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:11 +0200 Subject: [PATCH 0141/1754] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max The ONFI parameter page of a chip might define more fine grained tPROG_max and tBERS_max. When we do not have this information, we default to the highest possible values (they are maxima anyway). There is no point setting these fields at runtime, so explicitly move these defaults to the main ONFI SDR timings structure. This way, we will also be able to return a pointer to mode 0 directly when we will create a default reset configuration. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-18-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_timings.c | 31 ++++++++++++++++++----------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c index 54c7a1a8b038a..efff3583c549c 100644 --- a/drivers/mtd/nand/raw/nand_timings.c +++ b/drivers/mtd/nand/raw/nand_timings.c @@ -12,6 +12,13 @@ #define ONFI_DYN_TIMING_MAX U16_MAX +/* + * For non-ONFI chips we use the highest possible value for tPROG and tBERS. + * tR and tCCS will take the default values precised in the ONFI specification + * for timing mode 0, respectively 200us and 500ns. + * + * These four values are tweaked to be more accurate in the case of ONFI chips. + */ static const struct nand_data_interface onfi_sdr_timings[] = { /* Mode 0 */ { @@ -20,6 +27,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = { .timings.sdr = { .tCCS_min = 500000, .tR_max = 200000000, + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, .tADL_min = 400000, .tALH_min = 20000, .tALS_min = 50000, @@ -63,6 +72,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = { .timings.sdr = { .tCCS_min = 500000, .tR_max = 200000000, + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, .tADL_min = 400000, .tALH_min = 10000, .tALS_min = 25000, @@ -106,6 +117,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = { .timings.sdr = { .tCCS_min = 500000, .tR_max = 200000000, + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, .tADL_min = 400000, .tALH_min = 10000, .tALS_min = 15000, @@ -149,6 +162,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = { .timings.sdr = { .tCCS_min = 500000, .tR_max = 200000000, + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, .tADL_min = 400000, .tALH_min = 5000, .tALS_min = 10000, @@ -192,6 +207,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = { .timings.sdr = { .tCCS_min = 500000, .tR_max = 200000000, + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, .tADL_min = 400000, .tALH_min = 5000, .tALS_min = 10000, @@ -235,6 +252,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = { .timings.sdr = { .tCCS_min = 500000, .tR_max = 200000000, + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, .tADL_min = 400000, .tALH_min = 5000, .tALS_min = 10000, @@ -357,18 +376,6 @@ int onfi_fill_data_interface(struct nand_chip *chip, /* nanoseconds -> picoseconds */ timings->tCCS_min = 1000UL * onfi->tCCS; - } else { - struct nand_sdr_timings *timings = &iface->timings.sdr; - /* - * For non-ONFI chips we use the highest possible value for - * tPROG and tBERS. tR and tCCS will take the default values - * precised in the ONFI specification for timing mode 0, - * respectively 200us and 500ns. - */ - - /* microseconds -> picoseconds */ - timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX; - timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX; } return 0; -- GitLab From e0160cd41fb81fde9ee4612a7ea2dfd631de2638 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:12 +0200 Subject: [PATCH 0142/1754] mtd: rawnand: Hide the chip->data_interface indirection As a preparation for allocating the data interface structure dynamically (and rename it), let's avoid accessing chip->data_interface directly. Instead, we introduce a helper, nand_get_interface_config(), and use it to retrieve the current data interface configuration out of a nand_chip object. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-19-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/marvell_nand.c | 9 ++++--- drivers/mtd/nand/raw/meson_nand.c | 8 +++--- drivers/mtd/nand/raw/nand_base.c | 34 +++++++++++++------------- drivers/mtd/nand/raw/nand_legacy.c | 5 +++- drivers/mtd/nand/raw/nand_toshiba.c | 2 +- drivers/mtd/nand/raw/stm32_fmc2_nand.c | 2 +- drivers/mtd/nand/raw/tango_nand.c | 2 +- include/linux/mtd/rawnand.h | 11 +++++++++ 8 files changed, 45 insertions(+), 28 deletions(-) diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index 260a0430313e1..df859889e4eb9 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -1096,6 +1096,8 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip, const u8 *oob_buf, bool raw, int page) { + const struct nand_sdr_timings *sdr = + nand_get_sdr_timings(nand_get_interface_config(chip)); struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip); struct marvell_nfc *nfc = to_marvell_nfc(chip->controller); const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout; @@ -1141,7 +1143,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip, return ret; ret = marvell_nfc_wait_op(chip, - PSEC_TO_MSEC(chip->data_interface.timings.sdr.tPROG_max)); + PSEC_TO_MSEC(sdr->tPROG_max)); return ret; } @@ -1562,6 +1564,8 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { + const struct nand_sdr_timings *sdr = + nand_get_sdr_timings(nand_get_interface_config(chip)); struct mtd_info *mtd = nand_to_mtd(chip); const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout; const u8 *data = buf; @@ -1598,8 +1602,7 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip, marvell_nfc_wait_ndrun(chip); } - ret = marvell_nfc_wait_op(chip, - PSEC_TO_MSEC(chip->data_interface.timings.sdr.tPROG_max)); + ret = marvell_nfc_wait_op(chip, PSEC_TO_MSEC(sdr->tPROG_max)); marvell_nfc_disable_hw_ecc(chip); diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c index 3f376471f3f75..580b7be0719f0 100644 --- a/drivers/mtd/nand/raw/meson_nand.c +++ b/drivers/mtd/nand/raw/meson_nand.c @@ -573,10 +573,10 @@ static int meson_nfc_write_buf(struct nand_chip *nand, u8 *buf, int len) static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand, int page, bool in) { + const struct nand_sdr_timings *sdr = + nand_get_sdr_timings(nand_get_interface_config(nand)); struct mtd_info *mtd = nand_to_mtd(nand); struct meson_nfc *nfc = nand_get_controller_data(nand); - const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&nand->data_interface); u32 *addrs = nfc->cmdfifo.rw.addrs; u32 cs = nfc->param.chip_select; u32 cmd0, cmd_num, row_start; @@ -626,9 +626,9 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand, static int meson_nfc_write_page_sub(struct nand_chip *nand, int page, int raw) { - struct mtd_info *mtd = nand_to_mtd(nand); const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&nand->data_interface); + nand_get_sdr_timings(nand_get_interface_config(nand)); + struct mtd_info *mtd = nand_to_mtd(nand); struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); struct meson_nfc *nfc = nand_get_controller_data(nand); int data_len, info_len; diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index b4de85794e07d..7d393e1d0252e 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -773,7 +773,7 @@ int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms) return -ENOTSUPP; /* Wait tWB before polling the STATUS reg. */ - timings = nand_get_sdr_timings(&chip->data_interface); + timings = nand_get_sdr_timings(nand_get_interface_config(chip)); ndelay(PSEC_TO_NSEC(timings->tWB_max)); ret = nand_status_op(chip, NULL); @@ -1119,9 +1119,9 @@ static int nand_sp_exec_read_page_op(struct nand_chip *chip, unsigned int page, unsigned int offset_in_page, void *buf, unsigned int len) { - struct mtd_info *mtd = nand_to_mtd(chip); const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&chip->data_interface); + nand_get_sdr_timings(nand_get_interface_config(chip)); + struct mtd_info *mtd = nand_to_mtd(chip); u8 addrs[4]; struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_READ0, 0), @@ -1163,7 +1163,7 @@ static int nand_lp_exec_read_page_op(struct nand_chip *chip, unsigned int page, unsigned int len) { const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&chip->data_interface); + nand_get_sdr_timings(nand_get_interface_config(chip)); u8 addrs[5]; struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_READ0, 0), @@ -1260,7 +1260,7 @@ int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf, if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&chip->data_interface); + nand_get_sdr_timings(nand_get_interface_config(chip)); struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_PARAM, 0), NAND_OP_ADDR(1, &page, PSEC_TO_NSEC(sdr->tWB_max)), @@ -1315,7 +1315,7 @@ int nand_change_read_column_op(struct nand_chip *chip, if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&chip->data_interface); + nand_get_sdr_timings(nand_get_interface_config(chip)); u8 addrs[2] = {}; struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_RNDOUT, 0), @@ -1389,9 +1389,9 @@ static int nand_exec_prog_page_op(struct nand_chip *chip, unsigned int page, unsigned int offset_in_page, const void *buf, unsigned int len, bool prog) { - struct mtd_info *mtd = nand_to_mtd(chip); const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&chip->data_interface); + nand_get_sdr_timings(nand_get_interface_config(chip)); + struct mtd_info *mtd = nand_to_mtd(chip); u8 addrs[5] = {}; struct nand_op_instr instrs[] = { /* @@ -1514,7 +1514,7 @@ int nand_prog_page_end_op(struct nand_chip *chip) if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&chip->data_interface); + nand_get_sdr_timings(nand_get_interface_config(chip)); struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_PAGEPROG, PSEC_TO_NSEC(sdr->tWB_max)), @@ -1621,7 +1621,7 @@ int nand_change_write_column_op(struct nand_chip *chip, if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&chip->data_interface); + nand_get_sdr_timings(nand_get_interface_config(chip)); u8 addrs[2]; struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_RNDIN, 0), @@ -1676,7 +1676,7 @@ int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf, if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&chip->data_interface); + nand_get_sdr_timings(nand_get_interface_config(chip)); struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_READID, 0), NAND_OP_ADDR(1, &addr, PSEC_TO_NSEC(sdr->tADL_min)), @@ -1715,7 +1715,7 @@ int nand_status_op(struct nand_chip *chip, u8 *status) { if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&chip->data_interface); + nand_get_sdr_timings(nand_get_interface_config(chip)); struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_STATUS, PSEC_TO_NSEC(sdr->tADL_min)), @@ -1784,7 +1784,7 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock) if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&chip->data_interface); + nand_get_sdr_timings(nand_get_interface_config(chip)); u8 addrs[3] = { page, page >> 8, page >> 16 }; struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_ERASE1, 0), @@ -1843,7 +1843,7 @@ static int nand_set_features_op(struct nand_chip *chip, u8 feature, if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&chip->data_interface); + nand_get_sdr_timings(nand_get_interface_config(chip)); struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_SET_FEATURES, 0), NAND_OP_ADDR(1, &feature, PSEC_TO_NSEC(sdr->tADL_min)), @@ -1890,7 +1890,7 @@ static int nand_get_features_op(struct nand_chip *chip, u8 feature, if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&chip->data_interface); + nand_get_sdr_timings(nand_get_interface_config(chip)); struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_GET_FEATURES, 0), NAND_OP_ADDR(1, &feature, PSEC_TO_NSEC(sdr->tWB_max)), @@ -1947,7 +1947,7 @@ int nand_reset_op(struct nand_chip *chip) { if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&chip->data_interface); + nand_get_sdr_timings(nand_get_interface_config(chip)); struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_RESET, PSEC_TO_NSEC(sdr->tWB_max)), NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tRST_max), 0), @@ -3226,7 +3226,7 @@ static void nand_wait_readrdy(struct nand_chip *chip) if (!(chip->options & NAND_NEED_READRDY)) return; - sdr = nand_get_sdr_timings(&chip->data_interface); + sdr = nand_get_sdr_timings(nand_get_interface_config(chip)); WARN_ON(nand_wait_rdy_op(chip, PSEC_TO_MSEC(sdr->tR_max), 0)); } diff --git a/drivers/mtd/nand/raw/nand_legacy.c b/drivers/mtd/nand/raw/nand_legacy.c index 848403dcae03b..fe769762e1d8b 100644 --- a/drivers/mtd/nand/raw/nand_legacy.c +++ b/drivers/mtd/nand/raw/nand_legacy.c @@ -354,6 +354,9 @@ static void nand_command(struct nand_chip *chip, unsigned int command, static void nand_ccs_delay(struct nand_chip *chip) { + const struct nand_sdr_timings *sdr = + nand_get_sdr_timings(nand_get_interface_config(chip)); + /* * The controller already takes care of waiting for tCCS when the RNDIN * or RNDOUT command is sent, return directly. @@ -366,7 +369,7 @@ static void nand_ccs_delay(struct nand_chip *chip) * (which should be safe for all NANDs). */ if (nand_controller_can_setup_data_iface(chip)) - ndelay(chip->data_interface.timings.sdr.tCCS_min / 1000); + ndelay(sdr->tCCS_min / 1000); else ndelay(500); } diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c index ae069905d7e4a..333037bdca411 100644 --- a/drivers/mtd/nand/raw/nand_toshiba.c +++ b/drivers/mtd/nand/raw/nand_toshiba.c @@ -33,7 +33,7 @@ static int toshiba_nand_benand_read_eccstatus_op(struct nand_chip *chip, if (nand_has_exec_op(chip)) { const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(&chip->data_interface); + nand_get_sdr_timings(nand_get_interface_config(chip)); struct nand_op_instr instrs[] = { NAND_OP_CMD(TOSHIBA_NAND_CMD_ECC_STATUS_READ, PSEC_TO_NSEC(sdr->tADL_min)), diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c index 65c9d17b25a3c..7320c0fc19ec6 100644 --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c @@ -1308,7 +1308,7 @@ static int stm32_fmc2_nfc_waitrdy(struct nand_chip *chip, dev_warn(nfc->dev, "Waitrdy timeout\n"); /* Wait tWB before R/B# signal is low */ - timings = nand_get_sdr_timings(&chip->data_interface); + timings = nand_get_sdr_timings(nand_get_interface_config(chip)); ndelay(PSEC_TO_NSEC(timings->tWB_max)); /* R/B# signal is low, clear high level flag */ diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index b3a0d08f1733a..648dc7e77f6aa 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -336,7 +336,7 @@ static int tango_write_page(struct nand_chip *chip, const u8 *buf, if (err) return err; - timings = nand_get_sdr_timings(&chip->data_interface); + timings = nand_get_sdr_timings(nand_get_interface_config(chip)); err = tango_waitrdy(chip, PSEC_TO_MSEC(timings->tR_max)); if (err) return err; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 544ec8736793a..0852df9411309 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1203,6 +1203,17 @@ static inline struct device_node *nand_get_flash_node(struct nand_chip *chip) return mtd_get_of_node(nand_to_mtd(chip)); } +/** + * nand_get_interface_config - Retrieve the current interface configuration + * of a NAND chip + * @chip: The NAND chip + */ +static inline const struct nand_data_interface * +nand_get_interface_config(struct nand_chip *chip) +{ + return &chip->data_interface; +} + /* * A helper for defining older NAND chips where the second ID byte fully * defined the chip, including the geometry (chip size, eraseblock size, page -- GitLab From 4c46667b3d67253604ee42840917844548c86657 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:13 +0200 Subject: [PATCH 0143/1754] mtd: rawnand: s/data_interface/interface_config/ The name/suffix data_interface is a bit misleading in that the field or functions actually represent a configuration that can be applied by the controller/chip. Let's rename all fields/functions/hooks that are worth renaming. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/ams-delta.c | 6 +- drivers/mtd/nand/raw/arasan-nand-controller.c | 6 +- drivers/mtd/nand/raw/atmel/nand-controller.c | 34 ++++----- .../mtd/nand/raw/cadence-nand-controller.c | 6 +- drivers/mtd/nand/raw/denali.c | 8 +-- drivers/mtd/nand/raw/fsmc_nand.c | 6 +- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 6 +- drivers/mtd/nand/raw/internals.h | 12 ++-- drivers/mtd/nand/raw/marvell_nand.c | 9 ++- drivers/mtd/nand/raw/meson_nand.c | 6 +- drivers/mtd/nand/raw/mtk_nand.c | 6 +- drivers/mtd/nand/raw/mxc_nand.c | 20 +++--- drivers/mtd/nand/raw/mxic_nand.c | 6 +- drivers/mtd/nand/raw/nand_base.c | 69 ++++++++++--------- drivers/mtd/nand/raw/nand_legacy.c | 2 +- drivers/mtd/nand/raw/nand_timings.c | 17 ++--- drivers/mtd/nand/raw/s3c2410.c | 6 +- drivers/mtd/nand/raw/stm32_fmc2_nand.c | 4 +- drivers/mtd/nand/raw/sunxi_nand.c | 6 +- drivers/mtd/nand/raw/tango_nand.c | 4 +- drivers/mtd/nand/raw/tegra_nand.c | 6 +- include/linux/mtd/rawnand.h | 33 +++++---- 22 files changed, 139 insertions(+), 139 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 3711e7a0436cd..fdba155416d25 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -191,8 +191,8 @@ static int gpio_nand_exec_op(struct nand_chip *this, return ret; } -static int gpio_nand_setup_data_interface(struct nand_chip *this, int csline, - const struct nand_data_interface *cf) +static int gpio_nand_setup_interface(struct nand_chip *this, int csline, + const struct nand_interface_config *cf) { struct gpio_nand *priv = nand_get_controller_data(this); const struct nand_sdr_timings *sdr = nand_get_sdr_timings(cf); @@ -217,7 +217,7 @@ static int gpio_nand_setup_data_interface(struct nand_chip *this, int csline, static const struct nand_controller_ops gpio_nand_ops = { .exec_op = gpio_nand_exec_op, - .setup_data_interface = gpio_nand_setup_data_interface, + .setup_interface = gpio_nand_setup_interface, }; /* diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c index 7141dcccba3c2..12c643e97c852 100644 --- a/drivers/mtd/nand/raw/arasan-nand-controller.c +++ b/drivers/mtd/nand/raw/arasan-nand-controller.c @@ -854,8 +854,8 @@ static int anfc_exec_op(struct nand_chip *chip, return nand_op_parser_exec_op(chip, &anfc_op_parser, op, check_only); } -static int anfc_setup_data_interface(struct nand_chip *chip, int target, - const struct nand_data_interface *conf) +static int anfc_setup_interface(struct nand_chip *chip, int target, + const struct nand_interface_config *conf) { struct anand *anand = to_anand(chip); struct arasan_nfc *nfc = to_anfc(chip->controller); @@ -1083,7 +1083,7 @@ static void anfc_detach_chip(struct nand_chip *chip) static const struct nand_controller_ops anfc_ops = { .exec_op = anfc_exec_op, - .setup_data_interface = anfc_setup_data_interface, + .setup_interface = anfc_setup_interface, .attach_chip = anfc_attach_chip, .detach_chip = anfc_detach_chip, }; diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 46a3724a788ec..c9818f548d079 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -200,8 +200,8 @@ struct atmel_nand_controller_ops { void (*nand_init)(struct atmel_nand_controller *nc, struct atmel_nand *nand); int (*ecc_init)(struct nand_chip *chip); - int (*setup_data_interface)(struct atmel_nand *nand, int csline, - const struct nand_data_interface *conf); + int (*setup_interface)(struct atmel_nand *nand, int csline, + const struct nand_interface_config *conf); }; struct atmel_nand_controller_caps { @@ -1168,7 +1168,7 @@ static int atmel_hsmc_nand_ecc_init(struct nand_chip *chip) } static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand, - const struct nand_data_interface *conf, + const struct nand_interface_config *conf, struct atmel_smc_cs_conf *smcconf) { u32 ncycles, totalcycles, timeps, mckperiodps; @@ -1397,9 +1397,9 @@ static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand, return 0; } -static int atmel_smc_nand_setup_data_interface(struct atmel_nand *nand, +static int atmel_smc_nand_setup_interface(struct atmel_nand *nand, int csline, - const struct nand_data_interface *conf) + const struct nand_interface_config *conf) { struct atmel_nand_controller *nc; struct atmel_smc_cs_conf smcconf; @@ -1422,9 +1422,9 @@ static int atmel_smc_nand_setup_data_interface(struct atmel_nand *nand, return 0; } -static int atmel_hsmc_nand_setup_data_interface(struct atmel_nand *nand, +static int atmel_hsmc_nand_setup_interface(struct atmel_nand *nand, int csline, - const struct nand_data_interface *conf) + const struct nand_interface_config *conf) { struct atmel_hsmc_nand_controller *nc; struct atmel_smc_cs_conf smcconf; @@ -1452,8 +1452,8 @@ static int atmel_hsmc_nand_setup_data_interface(struct atmel_nand *nand, return 0; } -static int atmel_nand_setup_data_interface(struct nand_chip *chip, int csline, - const struct nand_data_interface *conf) +static int atmel_nand_setup_interface(struct nand_chip *chip, int csline, + const struct nand_interface_config *conf) { struct atmel_nand *nand = to_atmel_nand(chip); struct atmel_nand_controller *nc; @@ -1464,7 +1464,7 @@ static int atmel_nand_setup_data_interface(struct nand_chip *chip, int csline, (csline < 0 && csline != NAND_DATA_IFACE_CHECK_ONLY)) return -EINVAL; - return nc->caps->ops->setup_data_interface(nand, csline, conf); + return nc->caps->ops->setup_interface(nand, csline, conf); } static void atmel_nand_init(struct atmel_nand_controller *nc, @@ -1483,7 +1483,7 @@ static void atmel_nand_init(struct atmel_nand_controller *nc, chip->legacy.write_buf = atmel_nand_write_buf; chip->legacy.select_chip = atmel_nand_select_chip; - if (!nc->mck || !nc->caps->ops->setup_data_interface) + if (!nc->mck || !nc->caps->ops->setup_interface) chip->options |= NAND_KEEP_TIMINGS; /* Some NANDs require a longer delay than the default one (20us). */ @@ -1956,7 +1956,7 @@ static int atmel_nand_attach_chip(struct nand_chip *chip) static const struct nand_controller_ops atmel_nand_controller_ops = { .attach_chip = atmel_nand_attach_chip, - .setup_data_interface = atmel_nand_setup_data_interface, + .setup_interface = atmel_nand_setup_interface, }; static int atmel_nand_controller_init(struct atmel_nand_controller *nc, @@ -2318,7 +2318,7 @@ static const struct atmel_nand_controller_ops atmel_hsmc_nc_ops = { .remove = atmel_hsmc_nand_controller_remove, .ecc_init = atmel_hsmc_nand_ecc_init, .nand_init = atmel_hsmc_nand_init, - .setup_data_interface = atmel_hsmc_nand_setup_data_interface, + .setup_interface = atmel_hsmc_nand_setup_interface, }; static const struct atmel_nand_controller_caps atmel_sama5_nc_caps = { @@ -2375,10 +2375,10 @@ atmel_smc_nand_controller_remove(struct atmel_nand_controller *nc) /* * The SMC reg layout of at91rm9200 is completely different which prevents us - * from re-using atmel_smc_nand_setup_data_interface() for the - * ->setup_data_interface() hook. + * from re-using atmel_smc_nand_setup_interface() for the + * ->setup_interface() hook. * At this point, there's no support for the at91rm9200 SMC IP, so we leave - * ->setup_data_interface() unassigned. + * ->setup_interface() unassigned. */ static const struct atmel_nand_controller_ops at91rm9200_nc_ops = { .probe = atmel_smc_nand_controller_probe, @@ -2399,7 +2399,7 @@ static const struct atmel_nand_controller_ops atmel_smc_nc_ops = { .remove = atmel_smc_nand_controller_remove, .ecc_init = atmel_nand_ecc_init, .nand_init = atmel_smc_nand_init, - .setup_data_interface = atmel_smc_nand_setup_data_interface, + .setup_interface = atmel_smc_nand_setup_interface, }; static const struct atmel_nand_controller_caps atmel_sam9260_nc_caps = { diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c index c405722adfe10..574cbd3446e56 100644 --- a/drivers/mtd/nand/raw/cadence-nand-controller.c +++ b/drivers/mtd/nand/raw/cadence-nand-controller.c @@ -2303,8 +2303,8 @@ static inline u32 calc_tdvw(u32 trp_cnt, u32 clk_period, u32 trhoh_min, } static int -cadence_nand_setup_data_interface(struct nand_chip *chip, int chipnr, - const struct nand_data_interface *conf) +cadence_nand_setup_interface(struct nand_chip *chip, int chipnr, + const struct nand_interface_config *conf) { const struct nand_sdr_timings *sdr; struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); @@ -2690,7 +2690,7 @@ static int cadence_nand_attach_chip(struct nand_chip *chip) static const struct nand_controller_ops cadence_nand_controller_ops = { .attach_chip = cadence_nand_attach_chip, .exec_op = cadence_nand_exec_op, - .setup_data_interface = cadence_nand_setup_data_interface, + .setup_interface = cadence_nand_setup_interface, }; static int cadence_nand_chip_init(struct cdns_nand_ctrl *cdns_ctrl, diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 4e6e1578aa2d1..9d99dade95ce0 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -761,8 +761,8 @@ static int denali_write_page(struct nand_chip *chip, const u8 *buf, return denali_page_xfer(chip, (void *)buf, mtd->writesize, page, true); } -static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, - const struct nand_data_interface *conf) +static int denali_setup_interface(struct nand_chip *chip, int chipnr, + const struct nand_interface_config *conf) { static const unsigned int data_setup_on_host = 10000; struct denali_controller *denali = to_denali_controller(chip); @@ -1173,7 +1173,7 @@ static int denali_exec_op(struct nand_chip *chip, static const struct nand_controller_ops denali_controller_ops = { .attach_chip = denali_attach_chip, .exec_op = denali_exec_op, - .setup_data_interface = denali_setup_data_interface, + .setup_interface = denali_setup_interface, }; int denali_chip_init(struct denali_controller *denali, @@ -1230,7 +1230,7 @@ int denali_chip_init(struct denali_controller *denali, chip->buf_align = 16; } - /* clk rate info is needed for setup_data_interface */ + /* clk rate info is needed for setup_interface */ if (!denali->clk_rate || !denali->clk_x_rate) chip->options |= NAND_KEEP_TIMINGS; diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c index 3909752b14c52..92ddc41d0ff00 100644 --- a/drivers/mtd/nand/raw/fsmc_nand.c +++ b/drivers/mtd/nand/raw/fsmc_nand.c @@ -327,8 +327,8 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, return 0; } -static int fsmc_setup_data_interface(struct nand_chip *nand, int csline, - const struct nand_data_interface *conf) +static int fsmc_setup_interface(struct nand_chip *nand, int csline, + const struct nand_interface_config *conf) { struct fsmc_nand_data *host = nand_to_fsmc(nand); struct fsmc_nand_timings tims; @@ -951,7 +951,7 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand) static const struct nand_controller_ops fsmc_nand_controller_ops = { .attach_chip = fsmc_nand_attach_chip, .exec_op = fsmc_exec_op, - .setup_data_interface = fsmc_setup_data_interface, + .setup_interface = fsmc_setup_interface, }; /** diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index 061a8ddda2756..5d4aee46cc552 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -736,8 +736,8 @@ static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this) udelay(dll_wait_time_us); } -static int gpmi_setup_data_interface(struct nand_chip *chip, int chipnr, - const struct nand_data_interface *conf) +static int gpmi_setup_interface(struct nand_chip *chip, int chipnr, + const struct nand_interface_config *conf) { struct gpmi_nand_data *this = nand_get_controller_data(chip); const struct nand_sdr_timings *sdr; @@ -2400,7 +2400,7 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip, static const struct nand_controller_ops gpmi_nand_controller_ops = { .attach_chip = gpmi_nand_attach_chip, - .setup_data_interface = gpmi_setup_data_interface, + .setup_interface = gpmi_setup_interface, .exec_op = gpmi_nfc_exec_op, }; diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index f851ed210d707..114c63a6a3492 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -84,10 +84,10 @@ int nand_bbm_get_next_page(struct nand_chip *chip, int page); int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs); int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, int allowbbt); -int onfi_fill_data_interface(struct nand_chip *chip, - struct nand_data_interface *iface, - enum nand_data_interface_type type, - unsigned int timing_mode); +int onfi_fill_interface_config(struct nand_chip *chip, + struct nand_interface_config *iface, + enum nand_interface_type type, + unsigned int timing_mode); unsigned int onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings); int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param); @@ -133,10 +133,10 @@ static inline int nand_exec_op(struct nand_chip *chip, return chip->controller->ops->exec_op(chip, op, false); } -static inline bool nand_controller_can_setup_data_iface(struct nand_chip *chip) +static inline bool nand_controller_can_setup_interface(struct nand_chip *chip) { if (!chip->controller || !chip->controller->ops || - !chip->controller->ops->setup_data_interface) + !chip->controller->ops->setup_interface) return false; if (chip->options & NAND_KEEP_TIMINGS) diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index df859889e4eb9..8482d3bd8b1f5 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -2308,9 +2308,8 @@ static struct nand_bbt_descr bbt_mirror_descr = { .pattern = bbt_mirror_pattern }; -static int marvell_nfc_setup_data_interface(struct nand_chip *chip, int chipnr, - const struct nand_data_interface - *conf) +static int marvell_nfc_setup_interface(struct nand_chip *chip, int chipnr, + const struct nand_interface_config *conf) { struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip); struct marvell_nfc *nfc = to_marvell_nfc(chip->controller); @@ -2511,7 +2510,7 @@ static int marvell_nand_attach_chip(struct nand_chip *chip) static const struct nand_controller_ops marvell_nand_controller_ops = { .attach_chip = marvell_nand_attach_chip, .exec_op = marvell_nfc_exec_op, - .setup_data_interface = marvell_nfc_setup_data_interface, + .setup_interface = marvell_nfc_setup_interface, }; static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc, @@ -2647,7 +2646,7 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc, /* * Save a reference value for timing registers before - * ->setup_data_interface() is called. + * ->setup_interface() is called. */ marvell_nand->ndtr0 = readl_relaxed(nfc->regs + NDTR0); marvell_nand->ndtr1 = readl_relaxed(nfc->regs + NDTR1); diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c index 580b7be0719f0..0e5829a2b54f8 100644 --- a/drivers/mtd/nand/raw/meson_nand.c +++ b/drivers/mtd/nand/raw/meson_nand.c @@ -1097,8 +1097,8 @@ static int meson_chip_buffer_init(struct nand_chip *nand) } static -int meson_nfc_setup_data_interface(struct nand_chip *nand, int csline, - const struct nand_data_interface *conf) +int meson_nfc_setup_interface(struct nand_chip *nand, int csline, + const struct nand_interface_config *conf) { struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); const struct nand_sdr_timings *timings; @@ -1222,7 +1222,7 @@ static int meson_nand_attach_chip(struct nand_chip *nand) static const struct nand_controller_ops meson_nand_controller_ops = { .attach_chip = meson_nand_attach_chip, .detach_chip = meson_nand_detach_chip, - .setup_data_interface = meson_nfc_setup_data_interface, + .setup_interface = meson_nfc_setup_interface, .exec_op = meson_nfc_exec_op, }; diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index ca8457626d534..ad1b55dab2110 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -531,8 +531,8 @@ static int mtk_nfc_exec_op(struct nand_chip *chip, return ret; } -static int mtk_nfc_setup_data_interface(struct nand_chip *chip, int csline, - const struct nand_data_interface *conf) +static int mtk_nfc_setup_interface(struct nand_chip *chip, int csline, + const struct nand_interface_config *conf) { struct mtk_nfc *nfc = nand_get_controller_data(chip); const struct nand_sdr_timings *timings; @@ -1357,7 +1357,7 @@ static int mtk_nfc_attach_chip(struct nand_chip *chip) static const struct nand_controller_ops mtk_nfc_controller_ops = { .attach_chip = mtk_nfc_attach_chip, - .setup_data_interface = mtk_nfc_setup_data_interface, + .setup_interface = mtk_nfc_setup_interface, .exec_op = mtk_nfc_exec_op, }; diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index 09dacb83cb5af..07c41e8bae2d1 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -137,8 +137,8 @@ struct mxc_nand_devtype_data { u32 (*get_ecc_status)(struct mxc_nand_host *); const struct mtd_ooblayout_ops *ooblayout; void (*select_chip)(struct nand_chip *chip, int cs); - int (*setup_data_interface)(struct nand_chip *chip, int csline, - const struct nand_data_interface *conf); + int (*setup_interface)(struct nand_chip *chip, int csline, + const struct nand_interface_config *conf); void (*enable_hwecc)(struct nand_chip *chip, bool enable); /* @@ -1139,8 +1139,8 @@ static void preset_v1(struct mtd_info *mtd) writew(0x4, NFC_V1_V2_WRPROT); } -static int mxc_nand_v2_setup_data_interface(struct nand_chip *chip, int csline, - const struct nand_data_interface *conf) +static int mxc_nand_v2_setup_interface(struct nand_chip *chip, int csline, + const struct nand_interface_config *conf) { struct mxc_nand_host *host = nand_get_controller_data(chip); int tRC_min_ns, tRC_ps, ret; @@ -1521,7 +1521,7 @@ static const struct mxc_nand_devtype_data imx25_nand_devtype_data = { .get_ecc_status = get_ecc_status_v2, .ooblayout = &mxc_v2_ooblayout_ops, .select_chip = mxc_nand_select_chip_v2, - .setup_data_interface = mxc_nand_v2_setup_data_interface, + .setup_interface = mxc_nand_v2_setup_interface, .enable_hwecc = mxc_nand_enable_hwecc_v1_v2, .irqpending_quirk = 0, .needs_ip = 0, @@ -1738,17 +1738,17 @@ static int mxcnd_attach_chip(struct nand_chip *chip) return 0; } -static int mxcnd_setup_data_interface(struct nand_chip *chip, int chipnr, - const struct nand_data_interface *conf) +static int mxcnd_setup_interface(struct nand_chip *chip, int chipnr, + const struct nand_interface_config *conf) { struct mxc_nand_host *host = nand_get_controller_data(chip); - return host->devtype_data->setup_data_interface(chip, chipnr, conf); + return host->devtype_data->setup_interface(chip, chipnr, conf); } static const struct nand_controller_ops mxcnd_controller_ops = { .attach_chip = mxcnd_attach_chip, - .setup_data_interface = mxcnd_setup_data_interface, + .setup_interface = mxcnd_setup_interface, }; static int mxcnd_probe(struct platform_device *pdev) @@ -1809,7 +1809,7 @@ static int mxcnd_probe(struct platform_device *pdev) if (err < 0) return err; - if (!host->devtype_data->setup_data_interface) + if (!host->devtype_data->setup_interface) this->options |= NAND_KEEP_TIMINGS; if (host->devtype_data->needs_ip) { diff --git a/drivers/mtd/nand/raw/mxic_nand.c b/drivers/mtd/nand/raw/mxic_nand.c index 57f36721f4c6e..d66b5b0971fab 100644 --- a/drivers/mtd/nand/raw/mxic_nand.c +++ b/drivers/mtd/nand/raw/mxic_nand.c @@ -451,8 +451,8 @@ static int mxic_nfc_exec_op(struct nand_chip *chip, return ret; } -static int mxic_nfc_setup_data_interface(struct nand_chip *chip, int chipnr, - const struct nand_data_interface *conf) +static int mxic_nfc_setup_interface(struct nand_chip *chip, int chipnr, + const struct nand_interface_config *conf) { struct mxic_nand_ctlr *nfc = nand_get_controller_data(chip); const struct nand_sdr_timings *sdr; @@ -480,7 +480,7 @@ static int mxic_nfc_setup_data_interface(struct nand_chip *chip, int chipnr, static const struct nand_controller_ops mxic_nand_controller_ops = { .exec_op = mxic_nfc_exec_op, - .setup_data_interface = mxic_nfc_setup_data_interface, + .setup_interface = mxic_nfc_setup_interface, }; static int mxic_nfc_probe(struct platform_device *pdev) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 7d393e1d0252e..4fa18fb68d621 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -898,7 +898,7 @@ static bool nand_supports_set_features(struct nand_chip *chip, int addr) } /** - * nand_reset_data_interface - Reset data interface and timings + * nand_reset_interface - Reset data interface and timings * @chip: The NAND chip * @chipnr: Internal die id * @@ -906,11 +906,12 @@ static bool nand_supports_set_features(struct nand_chip *chip, int addr) * * Returns 0 for success or negative error code otherwise. */ -static int nand_reset_data_interface(struct nand_chip *chip, int chipnr) +static int nand_reset_interface(struct nand_chip *chip, int chipnr) { + const struct nand_controller_ops *ops = chip->controller->ops; int ret; - if (!nand_controller_can_setup_data_iface(chip)) + if (!nand_controller_can_setup_interface(chip)) return 0; /* @@ -927,9 +928,9 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr) * timings to timing mode 0. */ - onfi_fill_data_interface(chip, &chip->data_interface, NAND_SDR_IFACE, 0); - ret = chip->controller->ops->setup_data_interface(chip, chipnr, - &chip->data_interface); + onfi_fill_interface_config(chip, &chip->interface_config, + NAND_SDR_IFACE, 0); + ret = ops->setup_interface(chip, chipnr, &chip->interface_config); if (ret) pr_err("Failed to configure data interface to SDR timing mode 0\n"); @@ -937,7 +938,7 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr) } /** - * nand_setup_data_interface - Setup the best data interface and timings + * nand_setup_interface - Setup the best data interface and timings * @chip: The NAND chip * @chipnr: Internal die id * @@ -946,13 +947,13 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr) * * Returns 0 for success or negative error code otherwise. */ -static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) +static int nand_setup_interface(struct nand_chip *chip, int chipnr) { - u8 mode = chip->data_interface.timings.mode; + u8 mode = chip->interface_config.timings.mode; u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { mode, }; int ret; - if (!nand_controller_can_setup_data_iface(chip)) + if (!nand_controller_can_setup_interface(chip)) return 0; /* Change the mode on the chip side (if supported by the NAND chip) */ @@ -966,8 +967,8 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) } /* Change the mode on the controller side */ - ret = chip->controller->ops->setup_data_interface(chip, chipnr, - &chip->data_interface); + ret = chip->controller->ops->setup_interface(chip, chipnr, + &chip->interface_config); if (ret) return ret; @@ -996,7 +997,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) * Fallback to mode 0 if the chip explicitly did not ack the chosen * timing mode. */ - nand_reset_data_interface(chip, chipnr); + nand_reset_interface(chip, chipnr); nand_select_target(chip, chipnr); nand_reset_op(chip); nand_deselect_target(chip); @@ -1005,7 +1006,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) } /** - * nand_choose_data_interface - find the best data interface and timings + * nand_choose_interface_config - find the best data interface and timings * @chip: The NAND chip * * Find the best data interface and NAND timings supported by the chip @@ -1013,16 +1014,16 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) * First tries to retrieve supported timing modes from ONFI information, * and if the NAND chip does not support ONFI, relies on the * ->onfi_timing_mode_default specified in the nand_ids table. After this - * function nand_chip->data_interface is initialized with the best timing mode + * function nand_chip->interface_ is initialized with the best timing mode * available. * * Returns 0 for success or negative error code otherwise. */ -static int nand_choose_data_interface(struct nand_chip *chip) +static int nand_choose_interface_config(struct nand_chip *chip) { int modes, mode, ret; - if (!nand_controller_can_setup_data_iface(chip)) + if (!nand_controller_can_setup_interface(chip)) return 0; /* @@ -1040,8 +1041,8 @@ static int nand_choose_data_interface(struct nand_chip *chip) } for (mode = fls(modes) - 1; mode >= 0; mode--) { - ret = onfi_fill_data_interface(chip, &chip->data_interface, - NAND_SDR_IFACE, mode); + ret = onfi_fill_interface_config(chip, &chip->interface_config, + NAND_SDR_IFACE, mode); if (ret) continue; @@ -1049,9 +1050,9 @@ static int nand_choose_data_interface(struct nand_chip *chip) * Pass NAND_DATA_IFACE_CHECK_ONLY to only check if the * controller supports the requested timings. */ - ret = chip->controller->ops->setup_data_interface(chip, + ret = chip->controller->ops->setup_interface(chip, NAND_DATA_IFACE_CHECK_ONLY, - &chip->data_interface); + &chip->interface_config); if (!ret) { chip->onfi_timing_mode_default = mode; break; @@ -2477,17 +2478,17 @@ EXPORT_SYMBOL_GPL(nand_subop_get_data_len); * @chipnr: Internal die id * * Save the timings data structure, then apply SDR timings mode 0 (see - * nand_reset_data_interface for details), do the reset operation, and - * apply back the previous timings. + * nand_reset_interface for details), do the reset operation, and apply + * back the previous timings. * * Returns 0 on success, a negative error code otherwise. */ int nand_reset(struct nand_chip *chip, int chipnr) { - struct nand_data_interface saved_data_intf = chip->data_interface; + struct nand_interface_config saved_intf_config = chip->interface_config; int ret; - ret = nand_reset_data_interface(chip, chipnr); + ret = nand_reset_interface(chip, chipnr); if (ret) return ret; @@ -2503,18 +2504,18 @@ int nand_reset(struct nand_chip *chip, int chipnr) return ret; /* - * A nand_reset_data_interface() put both the NAND chip and the NAND + * A nand_reset_interface() put both the NAND chip and the NAND * controller in timings mode 0. If the default mode for this chip is * also 0, no need to proceed to the change again. Plus, at probe time, - * nand_setup_data_interface() uses ->set/get_features() which would + * nand_setup_interface() uses ->set/get_features() which would * fail anyway as the parameter page is not available yet. */ - if (!memcmp(&chip->data_interface, &saved_data_intf, - sizeof(saved_data_intf))) + if (!memcmp(&chip->interface_config, &saved_intf_config, + sizeof(saved_intf_config))) return 0; - chip->data_interface = saved_data_intf; - ret = nand_setup_data_interface(chip, chipnr); + chip->interface_config = saved_intf_config; + ret = nand_setup_interface(chip, chipnr); if (ret) return ret; @@ -5183,7 +5184,7 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips, mutex_init(&chip->lock); /* Enforce the right timings for reset/detection */ - onfi_fill_data_interface(chip, &chip->data_interface, NAND_SDR_IFACE, 0); + onfi_fill_interface_config(chip, &chip->interface_config, NAND_SDR_IFACE, 0); ret = nand_dt_init(chip); if (ret) @@ -5971,13 +5972,13 @@ static int nand_scan_tail(struct nand_chip *chip) mtd->bitflip_threshold = DIV_ROUND_UP(mtd->ecc_strength * 3, 4); /* Find the fastest data interface for this chip */ - ret = nand_choose_data_interface(chip); + ret = nand_choose_interface_config(chip); if (ret) goto err_nanddev_cleanup; /* Enter fastest possible mode on all dies. */ for (i = 0; i < nanddev_ntargets(&chip->base); i++) { - ret = nand_setup_data_interface(chip, i); + ret = nand_setup_interface(chip, i); if (ret) goto err_nanddev_cleanup; } diff --git a/drivers/mtd/nand/raw/nand_legacy.c b/drivers/mtd/nand/raw/nand_legacy.c index fe769762e1d8b..2bcc03714432b 100644 --- a/drivers/mtd/nand/raw/nand_legacy.c +++ b/drivers/mtd/nand/raw/nand_legacy.c @@ -368,7 +368,7 @@ static void nand_ccs_delay(struct nand_chip *chip) * Wait tCCS_min if it is correctly defined, otherwise wait 500ns * (which should be safe for all NANDs). */ - if (nand_controller_can_setup_data_iface(chip)) + if (nand_controller_can_setup_interface(chip)) ndelay(sdr->tCCS_min / 1000); else ndelay(500); diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c index efff3583c549c..bf05b4bceaa0b 100644 --- a/drivers/mtd/nand/raw/nand_timings.c +++ b/drivers/mtd/nand/raw/nand_timings.c @@ -19,7 +19,7 @@ * * These four values are tweaked to be more accurate in the case of ONFI chips. */ -static const struct nand_data_interface onfi_sdr_timings[] = { +static const struct nand_interface_config onfi_sdr_timings[] = { /* Mode 0 */ { .type = NAND_SDR_IFACE, @@ -340,16 +340,17 @@ onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings) } /** - * onfi_fill_data_interface - Initialize a data interface from a given ONFI mode + * onfi_fill_interface_config - Initialize an interface config from a given + * ONFI mode * @chip: The NAND chip - * @iface: The data interface to fill - * @type: The data interface type + * @iface: The interface configuration to fill + * @type: The interface type * @timing_mode: The ONFI timing mode */ -int onfi_fill_data_interface(struct nand_chip *chip, - struct nand_data_interface *iface, - enum nand_data_interface_type type, - unsigned int timing_mode) +int onfi_fill_interface_config(struct nand_chip *chip, + struct nand_interface_config *iface, + enum nand_interface_type type, + unsigned int timing_mode) { struct onfi_params *onfi = chip->parameters.onfi; diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index f86dff311464f..f121a3ae294c9 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -808,8 +808,8 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, return -ENODEV; } -static int s3c2410_nand_setup_data_interface(struct nand_chip *chip, int csline, - const struct nand_data_interface *conf) +static int s3c2410_nand_setup_interface(struct nand_chip *chip, int csline, + const struct nand_interface_config *conf) { struct mtd_info *mtd = nand_to_mtd(chip); struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); @@ -999,7 +999,7 @@ static int s3c2410_nand_attach_chip(struct nand_chip *chip) static const struct nand_controller_ops s3c24xx_nand_controller_ops = { .attach_chip = s3c2410_nand_attach_chip, - .setup_data_interface = s3c2410_nand_setup_data_interface, + .setup_interface = s3c2410_nand_setup_interface, }; static const struct of_device_id s3c24xx_nand_dt_ids[] = { diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c index 7320c0fc19ec6..a4140af43ed49 100644 --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c @@ -1546,7 +1546,7 @@ static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip, } static int stm32_fmc2_nfc_setup_interface(struct nand_chip *chip, int chipnr, - const struct nand_data_interface *conf) + const struct nand_interface_config *conf) { const struct nand_sdr_timings *sdrt; @@ -1764,7 +1764,7 @@ static int stm32_fmc2_nfc_attach_chip(struct nand_chip *chip) static const struct nand_controller_ops stm32_fmc2_nfc_controller_ops = { .attach_chip = stm32_fmc2_nfc_attach_chip, .exec_op = stm32_fmc2_nfc_exec_op, - .setup_data_interface = stm32_fmc2_nfc_setup_interface, + .setup_interface = stm32_fmc2_nfc_setup_interface, }; static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index ffbc1651fadc4..9c50c2b965e10 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1376,8 +1376,8 @@ static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration, #define sunxi_nand_lookup_timing(l, p, c) \ _sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c) -static int sunxi_nfc_setup_data_interface(struct nand_chip *nand, int csline, - const struct nand_data_interface *conf) +static int sunxi_nfc_setup_interface(struct nand_chip *nand, int csline, + const struct nand_interface_config *conf) { struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); @@ -1920,7 +1920,7 @@ static int sunxi_nfc_exec_op(struct nand_chip *nand, static const struct nand_controller_ops sunxi_nand_controller_ops = { .attach_chip = sunxi_nand_attach_chip, - .setup_data_interface = sunxi_nfc_setup_data_interface, + .setup_interface = sunxi_nfc_setup_interface, .exec_op = sunxi_nfc_exec_op, }; diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index 648dc7e77f6aa..bdb965ae7a4a7 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -515,7 +515,7 @@ static u32 to_ticks(int kHz, int ps) } static int tango_set_timings(struct nand_chip *chip, int csline, - const struct nand_data_interface *conf) + const struct nand_interface_config *conf) { const struct nand_sdr_timings *sdr = nand_get_sdr_timings(conf); struct tango_nfc *nfc = to_tango_nfc(chip->controller); @@ -565,7 +565,7 @@ static int tango_attach_chip(struct nand_chip *chip) static const struct nand_controller_ops tango_controller_ops = { .attach_chip = tango_attach_chip, - .setup_data_interface = tango_set_timings, + .setup_interface = tango_set_timings, .exec_op = tango_exec_op, }; diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c index f9d046b2cd3be..6b6212ffa01c5 100644 --- a/drivers/mtd/nand/raw/tegra_nand.c +++ b/drivers/mtd/nand/raw/tegra_nand.c @@ -813,8 +813,8 @@ static void tegra_nand_setup_timing(struct tegra_nand_controller *ctrl, writel_relaxed(reg, ctrl->regs + TIMING_2); } -static int tegra_nand_setup_data_interface(struct nand_chip *chip, int csline, - const struct nand_data_interface *conf) +static int tegra_nand_setup_interface(struct nand_chip *chip, int csline, + const struct nand_interface_config *conf) { struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller); const struct nand_sdr_timings *timings; @@ -1053,7 +1053,7 @@ static int tegra_nand_attach_chip(struct nand_chip *chip) static const struct nand_controller_ops tegra_nand_controller_ops = { .attach_chip = &tegra_nand_attach_chip, .exec_op = tegra_nand_exec_op, - .setup_data_interface = tegra_nand_setup_data_interface, + .setup_interface = tegra_nand_setup_interface, }; static int tegra_nand_chips_init(struct device *dev, diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 0852df9411309..2ca56eef0f078 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -492,22 +492,22 @@ struct nand_sdr_timings { }; /** - * enum nand_data_interface_type - NAND interface timing type + * enum nand_interface_type - NAND interface type * @NAND_SDR_IFACE: Single Data Rate interface */ -enum nand_data_interface_type { +enum nand_interface_type { NAND_SDR_IFACE, }; /** - * struct nand_data_interface - NAND interface timing + * struct nand_interface_config - NAND interface timing * @type: type of the timing * @timings: The timing information * @timings.mode: Timing mode as defined in the specification * @timings.sdr: Use it when @type is %NAND_SDR_IFACE. */ -struct nand_data_interface { - enum nand_data_interface_type type; +struct nand_interface_config { + enum nand_interface_type type; struct nand_timings { unsigned int mode; union { @@ -521,7 +521,7 @@ struct nand_data_interface { * @conf: The data interface */ static inline const struct nand_sdr_timings * -nand_get_sdr_timings(const struct nand_data_interface *conf) +nand_get_sdr_timings(const struct nand_interface_config *conf) { if (conf->type != NAND_SDR_IFACE) return ERR_PTR(-EINVAL); @@ -944,11 +944,10 @@ static inline void nand_op_trace(const char *prefix, * This method replaces chip->legacy.cmdfunc(), * chip->legacy.{read,write}_{buf,byte,word}(), * chip->legacy.dev_ready() and chip->legacy.waifunc(). - * @setup_data_interface: setup the data interface and timing. If - * chipnr is set to %NAND_DATA_IFACE_CHECK_ONLY this - * means the configuration should not be applied but - * only checked. - * This hook is optional. + * @setup_interface: setup the data interface and timing. If chipnr is set to + * %NAND_DATA_IFACE_CHECK_ONLY this means the configuration + * should not be applied but only checked. + * This hook is optional. */ struct nand_controller_ops { int (*attach_chip)(struct nand_chip *chip); @@ -956,8 +955,8 @@ struct nand_controller_ops { int (*exec_op)(struct nand_chip *chip, const struct nand_operation *op, bool check_only); - int (*setup_data_interface)(struct nand_chip *chip, int chipnr, - const struct nand_data_interface *conf); + int (*setup_interface)(struct nand_chip *chip, int chipnr, + const struct nand_interface_config *conf); }; /** @@ -1070,7 +1069,7 @@ struct nand_manufacturer { * @onfi_timing_mode_default: Default ONFI timing mode. This field is set to the * actually used ONFI mode if the chip is ONFI * compliant or deduced from the datasheet otherwise - * @data_interface: NAND interface timing information + * @interface_config: NAND interface timing information * @bbt_erase_shift: Number of address bits in a bbt entry * @bbt_options: Bad block table specific options. All options used here must * come from bbm.h. By default, these options will be copied to @@ -1118,7 +1117,7 @@ struct nand_chip { /* Data interface */ int onfi_timing_mode_default; - struct nand_data_interface data_interface; + struct nand_interface_config interface_config; /* Bad block information */ unsigned int bbt_erase_shift; @@ -1208,10 +1207,10 @@ static inline struct device_node *nand_get_flash_node(struct nand_chip *chip) * of a NAND chip * @chip: The NAND chip */ -static inline const struct nand_data_interface * +static inline const struct nand_interface_config * nand_get_interface_config(struct nand_chip *chip) { - return &chip->data_interface; + return &chip->interface_config; } /* -- GitLab From 42a9ad050e6f1f6e909e2117e7a99f54f5336939 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:14 +0200 Subject: [PATCH 0144/1754] mtd: rawnand: timings: Make onfi_fill_interface_config() a void helper Warn the user if the parameters are wrong but basically it would mean there is a serious issue in the NAND core. So no need to ever check its output, let's make this helper return void. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-21-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/internals.h | 8 ++++---- drivers/mtd/nand/raw/nand_base.c | 6 ++---- drivers/mtd/nand/raw/nand_timings.c | 18 ++++++++---------- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index 114c63a6a3492..63c5af4369013 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -84,10 +84,10 @@ int nand_bbm_get_next_page(struct nand_chip *chip, int page); int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs); int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, int allowbbt); -int onfi_fill_interface_config(struct nand_chip *chip, - struct nand_interface_config *iface, - enum nand_interface_type type, - unsigned int timing_mode); +void onfi_fill_interface_config(struct nand_chip *chip, + struct nand_interface_config *iface, + enum nand_interface_type type, + unsigned int timing_mode); unsigned int onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings); int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param); diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 4fa18fb68d621..3bfd71d589cf8 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -1041,10 +1041,8 @@ static int nand_choose_interface_config(struct nand_chip *chip) } for (mode = fls(modes) - 1; mode >= 0; mode--) { - ret = onfi_fill_interface_config(chip, &chip->interface_config, - NAND_SDR_IFACE, mode); - if (ret) - continue; + onfi_fill_interface_config(chip, &chip->interface_config, + NAND_SDR_IFACE, mode); /* * Pass NAND_DATA_IFACE_CHECK_ONLY to only check if the diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c index bf05b4bceaa0b..1e22006c79bae 100644 --- a/drivers/mtd/nand/raw/nand_timings.c +++ b/drivers/mtd/nand/raw/nand_timings.c @@ -347,18 +347,18 @@ onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings) * @type: The interface type * @timing_mode: The ONFI timing mode */ -int onfi_fill_interface_config(struct nand_chip *chip, - struct nand_interface_config *iface, - enum nand_interface_type type, - unsigned int timing_mode) +void onfi_fill_interface_config(struct nand_chip *chip, + struct nand_interface_config *iface, + enum nand_interface_type type, + unsigned int timing_mode) { struct onfi_params *onfi = chip->parameters.onfi; - if (type != NAND_SDR_IFACE) - return -EINVAL; + if (WARN_ON(type != NAND_SDR_IFACE)) + return; - if (timing_mode >= ARRAY_SIZE(onfi_sdr_timings)) - return -EINVAL; + if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_sdr_timings))) + return; *iface = onfi_sdr_timings[timing_mode]; @@ -378,6 +378,4 @@ int onfi_fill_interface_config(struct nand_chip *chip, /* nanoseconds -> picoseconds */ timings->tCCS_min = 1000UL * onfi->tCCS; } - - return 0; } -- GitLab From b5b39f640c1f5621ed4ff6418e74ee35ff5d988e Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:15 +0200 Subject: [PATCH 0145/1754] mtd: rawnand: Introduce nand_choose_best_sdr_timings() Extract the logic out of nand_choose_interface_config() to create a public helper that can be reused by manufacturer drivers. Add the possibility to provide a specific set of timings. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-22-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/internals.h | 3 + drivers/mtd/nand/raw/nand_base.c | 94 ++++++++++++++++++++------------ 2 files changed, 61 insertions(+), 36 deletions(-) diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index 63c5af4369013..5ebfbb89e5720 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -90,6 +90,9 @@ void onfi_fill_interface_config(struct nand_chip *chip, unsigned int timing_mode); unsigned int onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings); +int nand_choose_best_sdr_timings(struct nand_chip *chip, + struct nand_interface_config *iface, + struct nand_sdr_timings *spec_timings); int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param); int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param); int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf, diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 3bfd71d589cf8..742d099df5c66 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -1005,6 +1005,62 @@ static int nand_setup_interface(struct nand_chip *chip, int chipnr) return ret; } +/** + * nand_choose_best_sdr_timings - Pick up the best SDR timings that both the + * NAND controller and the NAND chip support + * @chip: the NAND chip + * @iface: the interface configuration (can eventually be updated) + * @spec_timings: specific timings, when not fitting the ONFI specification + * + * If specific timings are provided, use them. Otherwise, try to retrieve + * supported timing modes from ONFI information. Finally, if the NAND chip does + * not follow the ONFI specification, rely on the ->default_timing_mode + * specified in the nand_ids table. + */ +int nand_choose_best_sdr_timings(struct nand_chip *chip, + struct nand_interface_config *iface, + struct nand_sdr_timings *spec_timings) +{ + const struct nand_controller_ops *ops = chip->controller->ops; + int best_mode = 0, mode, ret; + + iface->type = NAND_SDR_IFACE; + + if (spec_timings) { + iface->timings.sdr = *spec_timings; + iface->timings.mode = onfi_find_closest_sdr_mode(spec_timings); + + /* Verify the controller supports the requested interface */ + ret = ops->setup_interface(chip, NAND_DATA_IFACE_CHECK_ONLY, + iface); + if (!ret) + return ret; + + /* Fallback to slower modes */ + best_mode = iface->timings.mode; + } else { + if (chip->parameters.onfi) { + unsigned int onfi_modes; + + onfi_modes = chip->parameters.onfi->async_timing_mode; + best_mode = fls(onfi_modes) - 1; + } else { + best_mode = chip->onfi_timing_mode_default; + } + } + + for (mode = best_mode; mode >= 0; mode--) { + onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, mode); + + ret = ops->setup_interface(chip, NAND_DATA_IFACE_CHECK_ONLY, + iface); + if (!ret) + return 0; + } + + return 0; +} + /** * nand_choose_interface_config - find the best data interface and timings * @chip: The NAND chip @@ -1016,48 +1072,14 @@ static int nand_setup_interface(struct nand_chip *chip, int chipnr) * ->onfi_timing_mode_default specified in the nand_ids table. After this * function nand_chip->interface_ is initialized with the best timing mode * available. - * - * Returns 0 for success or negative error code otherwise. */ static int nand_choose_interface_config(struct nand_chip *chip) { - int modes, mode, ret; - if (!nand_controller_can_setup_interface(chip)) return 0; - /* - * First try to identify the best timings from ONFI parameters and - * if the NAND does not support ONFI, fallback to the default ONFI - * timing mode. - */ - if (chip->parameters.onfi) { - modes = chip->parameters.onfi->async_timing_mode; - } else { - if (!chip->onfi_timing_mode_default) - return 0; - - modes = GENMASK(chip->onfi_timing_mode_default, 0); - } - - for (mode = fls(modes) - 1; mode >= 0; mode--) { - onfi_fill_interface_config(chip, &chip->interface_config, - NAND_SDR_IFACE, mode); - - /* - * Pass NAND_DATA_IFACE_CHECK_ONLY to only check if the - * controller supports the requested timings. - */ - ret = chip->controller->ops->setup_interface(chip, - NAND_DATA_IFACE_CHECK_ONLY, - &chip->interface_config); - if (!ret) { - chip->onfi_timing_mode_default = mode; - break; - } - } - - return 0; + return nand_choose_best_sdr_timings(chip, &chip->interface_config, + NULL); } /** -- GitLab From 26d014f0400e5ff54cc80c8329e3adbd74db1e04 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:16 +0200 Subject: [PATCH 0146/1754] mtd: rawnand: Add the ->choose_interface_config() hook This hook can be overloaded by NAND manufacturer drivers to propose alternative timings when not following the main standards. In this case, the manufacturer drivers is responsible for choosing the best interface configuration that fits both the controller and chip capabilities. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-23-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_base.c | 17 +++++++++++------ include/linux/mtd/rawnand.h | 3 +++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 742d099df5c66..2f4eba1a1082e 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -1066,18 +1066,23 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip, * @chip: The NAND chip * * Find the best data interface and NAND timings supported by the chip - * and the driver. - * First tries to retrieve supported timing modes from ONFI information, - * and if the NAND chip does not support ONFI, relies on the - * ->onfi_timing_mode_default specified in the nand_ids table. After this - * function nand_chip->interface_ is initialized with the best timing mode - * available. + * and the driver. Eventually let the NAND manufacturer driver propose his own + * set of timings. + * + * After this function nand_chip->interface_config is initialized with the best + * timing mode available. + * + * Returns 0 for success or negative error code otherwise. */ static int nand_choose_interface_config(struct nand_chip *chip) { if (!nand_controller_can_setup_interface(chip)) return 0; + if (chip->ops.choose_interface_config) + return chip->ops.choose_interface_config(chip, + &chip->interface_config); + return nand_choose_best_sdr_timings(chip, &chip->interface_config, NULL); } diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 2ca56eef0f078..316a02189da13 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1033,6 +1033,7 @@ struct nand_legacy { * @lock_area: Lock operation * @unlock_area: Unlock operation * @setup_read_retry: Set the read-retry mode (mostly needed for MLC NANDs) + * @choose_interface_config: Choose the best interface configuration */ struct nand_chip_ops { int (*suspend)(struct nand_chip *chip); @@ -1040,6 +1041,8 @@ struct nand_chip_ops { int (*lock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len); int (*unlock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len); int (*setup_read_retry)(struct nand_chip *chip, int retry_mode); + int (*choose_interface_config)(struct nand_chip *chip, + struct nand_interface_config *iface); }; /** -- GitLab From 2f36bae11234b5a9ca018bc44fff0e847cacc33c Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:17 +0200 Subject: [PATCH 0147/1754] mtd: rawnand: toshiba: Implement ->choose_interface_config() for TC58TEG5DCLTA00 Implement this hook for the tc58teg5dclta00 NAND chip and stop setting ->default_timing_mode. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-24-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_toshiba.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c index 333037bdca411..d23bb43220626 100644 --- a/drivers/mtd/nand/raw/nand_toshiba.c +++ b/drivers/mtd/nand/raw/nand_toshiba.c @@ -194,11 +194,21 @@ static void toshiba_nand_decode_id(struct nand_chip *chip) } } +static int +tc58teg5dclta00_choose_interface_config(struct nand_chip *chip, + struct nand_interface_config *iface) +{ + onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, 5); + + return nand_choose_best_sdr_timings(chip, iface, NULL); +} + static int tc58teg5dclta00_init(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); - chip->onfi_timing_mode_default = 5; + chip->ops.choose_interface_config = + &tc58teg5dclta00_choose_interface_config; chip->options |= NAND_NEED_SCRAMBLING; mtd_set_pairing_scheme(mtd, &dist3_pairing_scheme); -- GitLab From 0d0245b99552aa8c5c67d34ab7b4f0fd4d174444 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:18 +0200 Subject: [PATCH 0148/1754] mtd: rawnand: toshiba: Implement ->choose_interface_config() for TC58NVG0S3E This chip supports ONFI SDR timing mode 2, implement the new hook to advertize it. Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-25-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_ids.c | 3 +-- drivers/mtd/nand/raw/nand_toshiba.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c index e0dbc2e316c76..c729a8bc895d2 100644 --- a/drivers/mtd/nand/raw/nand_ids.c +++ b/drivers/mtd/nand/raw/nand_ids.c @@ -28,8 +28,7 @@ struct nand_flash_dev nand_flash_ids[] = { */ {"TC58NVG0S3E 1G 3.3V 8-bit", { .id = {0x98, 0xd1, 0x90, 0x15, 0x76, 0x14, 0x01, 0x00} }, - SZ_2K, SZ_128, SZ_128K, 0, 8, 64, NAND_ECC_INFO(1, SZ_512), - 2 }, + SZ_2K, SZ_128, SZ_128K, 0, 8, 64, NAND_ECC_INFO(1, SZ_512), }, {"TC58NVG2S0F 4G 3.3V 8-bit", { .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} }, SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) }, diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c index d23bb43220626..6d53f9b7a8173 100644 --- a/drivers/mtd/nand/raw/nand_toshiba.c +++ b/drivers/mtd/nand/raw/nand_toshiba.c @@ -203,6 +203,15 @@ tc58teg5dclta00_choose_interface_config(struct nand_chip *chip, return nand_choose_best_sdr_timings(chip, iface, NULL); } +static int +tc58nvg0s3e_choose_interface_config(struct nand_chip *chip, + struct nand_interface_config *iface) +{ + onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, 2); + + return nand_choose_best_sdr_timings(chip, iface, NULL); +} + static int tc58teg5dclta00_init(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); @@ -215,6 +224,14 @@ static int tc58teg5dclta00_init(struct nand_chip *chip) return 0; } +static int tc58nvg0s3e_init(struct nand_chip *chip) +{ + chip->ops.choose_interface_config = + &tc58nvg0s3e_choose_interface_config; + + return 0; +} + static int toshiba_nand_init(struct nand_chip *chip) { if (nand_is_slc(chip)) @@ -227,6 +244,9 @@ static int toshiba_nand_init(struct nand_chip *chip) if (!strcmp("TC58TEG5DCLTA00", chip->parameters.model)) tc58teg5dclta00_init(chip); + if (!strncmp("TC58NVG0S3E", chip->parameters.model, + sizeof("TC58NVG0S3E") - 1)) + tc58nvg0s3e_init(chip); return 0; } -- GitLab From 246a06ff13277349a09ea4dd46f516185e13d01d Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:19 +0200 Subject: [PATCH 0149/1754] mtd: rawnand: hynix: Implement ->choose_interface_config() for H27UCG8T2ATR-BC This chip supports ONFI SDR timing mode 4, implement the new hook to advertize it. Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-26-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_hynix.c | 14 ++++++++++++++ drivers/mtd/nand/raw/nand_ids.c | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c index 7d1be53f27f3f..6d08eb8344566 100644 --- a/drivers/mtd/nand/raw/nand_hynix.c +++ b/drivers/mtd/nand/raw/nand_hynix.c @@ -673,6 +673,15 @@ static void hynix_nand_cleanup(struct nand_chip *chip) nand_set_manufacturer_data(chip, NULL); } +static int +h27ucg8t2atrbc_choose_interface_config(struct nand_chip *chip, + struct nand_interface_config *iface) +{ + onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, 4); + + return nand_choose_best_sdr_timings(chip, iface, NULL); +} + static int hynix_nand_init(struct nand_chip *chip) { struct hynix_nand *hynix; @@ -689,6 +698,11 @@ static int hynix_nand_init(struct nand_chip *chip) nand_set_manufacturer_data(chip, hynix); + if (!strncmp("H27UCG8T2ATR-BC", chip->parameters.model, + sizeof("H27UCG8T2ATR-BC") - 1)) + chip->ops.choose_interface_config = + h27ucg8t2atrbc_choose_interface_config; + ret = hynix_nand_rr_init(chip); if (ret) hynix_nand_cleanup(chip); diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c index c729a8bc895d2..3b890d55703d1 100644 --- a/drivers/mtd/nand/raw/nand_ids.c +++ b/drivers/mtd/nand/raw/nand_ids.c @@ -50,7 +50,7 @@ struct nand_flash_dev nand_flash_ids[] = { {"H27UCG8T2ATR-BC 64G 3.3V 8-bit", { .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} }, SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640, - NAND_ECC_INFO(40, SZ_1K), 4 }, + NAND_ECC_INFO(40, SZ_1K) }, LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS), LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS), -- GitLab From 6d469f863772946e9ebd26068f7c9a609ab128d3 Mon Sep 17 00:00:00 2001 From: Rickard x Andersson Date: Fri, 29 May 2020 13:13:20 +0200 Subject: [PATCH 0150/1754] mtd: rawnand: toshiba: Choose the interface configuration for TH58NVG2S3HBAI4 The Kioxia/Toshiba TH58NVG2S3HBAI4 NAND memory is not ONFI compliant. The timings of the NAND chip memory are quite close to ONFI mode 4 but is breaking that spec. By providing our own set of timings, erase block read speed is increased from 6910 kiB/s to 13490 kiB/s and erase block write speed is increased from 3350 kiB/s to 4410 kiB/s. Tested on IMX6SX which has a NAND controller supporting EDO mode. Signed-off-by: Rickard x Andersson Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-27-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_ids.c | 3 +++ drivers/mtd/nand/raw/nand_toshiba.c | 38 +++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c index 3b890d55703d1..b9945791a9d7b 100644 --- a/drivers/mtd/nand/raw/nand_ids.c +++ b/drivers/mtd/nand/raw/nand_ids.c @@ -51,6 +51,9 @@ struct nand_flash_dev nand_flash_ids[] = { { .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} }, SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640, NAND_ECC_INFO(40, SZ_1K) }, + {"TH58NVG2S3HBAI4 4G 3.3V 8-bit", + { .id = {0x98, 0xdc, 0x91, 0x15, 0x76} }, + SZ_2K, SZ_512, SZ_128K, 0, 5, 128, NAND_ECC_INFO(8, SZ_512) }, LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS), LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS), diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c index 6d53f9b7a8173..f746c19f3b2ce 100644 --- a/drivers/mtd/nand/raw/nand_toshiba.c +++ b/drivers/mtd/nand/raw/nand_toshiba.c @@ -212,6 +212,33 @@ tc58nvg0s3e_choose_interface_config(struct nand_chip *chip, return nand_choose_best_sdr_timings(chip, iface, NULL); } +static int +th58nvg2s3hbai4_choose_interface_config(struct nand_chip *chip, + struct nand_interface_config *iface) +{ + struct nand_sdr_timings *sdr = &iface->timings.sdr; + + /* Start with timings from the closest timing mode, mode 4. */ + onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, 4); + + /* Patch timings that differ from mode 4. */ + sdr->tALS_min = 12000; + sdr->tCHZ_max = 20000; + sdr->tCLS_min = 12000; + sdr->tCOH_min = 0; + sdr->tDS_min = 12000; + sdr->tRHOH_min = 25000; + sdr->tRHW_min = 30000; + sdr->tRHZ_max = 60000; + sdr->tWHR_min = 60000; + + /* Patch timings not part of onfi timing mode. */ + sdr->tPROG_max = 700000000; + sdr->tBERS_max = 5000000000; + + return nand_choose_best_sdr_timings(chip, iface, sdr); +} + static int tc58teg5dclta00_init(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); @@ -232,6 +259,14 @@ static int tc58nvg0s3e_init(struct nand_chip *chip) return 0; } +static int th58nvg2s3hbai4_init(struct nand_chip *chip) +{ + chip->ops.choose_interface_config = + &th58nvg2s3hbai4_choose_interface_config; + + return 0; +} + static int toshiba_nand_init(struct nand_chip *chip) { if (nand_is_slc(chip)) @@ -247,6 +282,9 @@ static int toshiba_nand_init(struct nand_chip *chip) if (!strncmp("TC58NVG0S3E", chip->parameters.model, sizeof("TC58NVG0S3E") - 1)) tc58nvg0s3e_init(chip); + if (!strncmp("TH58NVG2S3HBAI4", chip->parameters.model, + sizeof("TH58NVG2S3HBAI4") - 1)) + th58nvg2s3hbai4_init(chip); return 0; } -- GitLab From a69ad11168dca68b3f0adc6882422f4a2e2cb050 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:21 +0200 Subject: [PATCH 0151/1754] mtd: rawnand: Get rid of the default ONFI timing mode The ->choose_interface() hook is here for manufacturer drivers to provide a better timing interface than the default one, this field is not needed anymore. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-28-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/nand_base.c | 19 ++++--------------- include/linux/mtd/rawnand.h | 9 --------- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 2f4eba1a1082e..753328f106c11 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -1012,10 +1012,8 @@ static int nand_setup_interface(struct nand_chip *chip, int chipnr) * @iface: the interface configuration (can eventually be updated) * @spec_timings: specific timings, when not fitting the ONFI specification * - * If specific timings are provided, use them. Otherwise, try to retrieve - * supported timing modes from ONFI information. Finally, if the NAND chip does - * not follow the ONFI specification, rely on the ->default_timing_mode - * specified in the nand_ids table. + * If specific timings are provided, use them. Otherwise, retrieve supported + * timing modes from ONFI information. */ int nand_choose_best_sdr_timings(struct nand_chip *chip, struct nand_interface_config *iface, @@ -1038,15 +1036,8 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip, /* Fallback to slower modes */ best_mode = iface->timings.mode; - } else { - if (chip->parameters.onfi) { - unsigned int onfi_modes; - - onfi_modes = chip->parameters.onfi->async_timing_mode; - best_mode = fls(onfi_modes) - 1; - } else { - best_mode = chip->onfi_timing_mode_default; - } + } else if (chip->parameters.onfi) { + best_mode = fls(chip->parameters.onfi->async_timing_mode) - 1; } for (mode = best_mode; mode >= 0; mode--) { @@ -4767,8 +4758,6 @@ static bool find_full_id_nand(struct nand_chip *chip, chip->options |= type->options; chip->base.eccreq.strength = NAND_ECC_STRENGTH(type); chip->base.eccreq.step_size = NAND_ECC_STEP(type); - chip->onfi_timing_mode_default = - type->onfi_timing_mode_default; chip->parameters.model = kstrdup(type->name, GFP_KERNEL); if (!chip->parameters.model) diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 316a02189da13..a2427c67d38bb 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1069,9 +1069,6 @@ struct nand_manufacturer { * @options: Various chip options. They can partly be set to inform nand_scan * about special functionality. See the defines for further * explanation. - * @onfi_timing_mode_default: Default ONFI timing mode. This field is set to the - * actually used ONFI mode if the chip is ONFI - * compliant or deduced from the datasheet otherwise * @interface_config: NAND interface timing information * @bbt_erase_shift: Number of address bits in a bbt entry * @bbt_options: Bad block table specific options. All options used here must @@ -1119,7 +1116,6 @@ struct nand_chip { unsigned int options; /* Data interface */ - int onfi_timing_mode_default; struct nand_interface_config interface_config; /* Bad block information */ @@ -1268,10 +1264,6 @@ nand_get_interface_config(struct nand_chip *chip) * @ecc_step_ds in nand_chip{}, also from the datasheet. * For example, the "4bit ECC for each 512Byte" can be set with * NAND_ECC_INFO(4, 512). - * @onfi_timing_mode_default: the default ONFI timing mode entered after a NAND - * reset. Should be deduced from timings described - * in the datasheet. - * */ struct nand_flash_dev { char *name; @@ -1292,7 +1284,6 @@ struct nand_flash_dev { uint16_t strength_ds; uint16_t step_ds; } ecc; - int onfi_timing_mode_default; }; int nand_create_bbt(struct nand_chip *chip); -- GitLab From 35b6bcc970f759d4a86d6221d09ca28ea20467c8 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 29 May 2020 13:13:22 +0200 Subject: [PATCH 0152/1754] mtd: rawnand: Allocate the interface configurations dynamically Instead of manipulating the statically allocated structure and copy timings around, allocate one at identification time and save it in the nand_chip structure once it has been initialized. All NAND chips using the same interface configuration during reset and startup, we define a helper to retrieve a single reset interface configuration object, shared across all NAND chips. We use a second pointer to always have a reference on the currently applied interface configuration, which may either point to the "best interface configuration" or to the "default reset interface configuration". Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon Link: https://lore.kernel.org/linux-mtd/20200529111322.7184-29-miquel.raynal@bootlin.com --- drivers/mtd/nand/raw/internals.h | 1 + drivers/mtd/nand/raw/nand_base.c | 84 ++++++++++++++++++----------- drivers/mtd/nand/raw/nand_timings.c | 6 +++ include/linux/mtd/rawnand.h | 11 ++-- 4 files changed, 67 insertions(+), 35 deletions(-) diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index 5ebfbb89e5720..012876e14317a 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -93,6 +93,7 @@ onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings); int nand_choose_best_sdr_timings(struct nand_chip *chip, struct nand_interface_config *iface, struct nand_sdr_timings *spec_timings); +const struct nand_interface_config *nand_get_reset_interface_config(void); int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param); int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param); int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf, diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 753328f106c11..0c768cb88f962 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -928,9 +928,9 @@ static int nand_reset_interface(struct nand_chip *chip, int chipnr) * timings to timing mode 0. */ - onfi_fill_interface_config(chip, &chip->interface_config, - NAND_SDR_IFACE, 0); - ret = ops->setup_interface(chip, chipnr, &chip->interface_config); + chip->current_interface_config = nand_get_reset_interface_config(); + ret = ops->setup_interface(chip, chipnr, + chip->current_interface_config); if (ret) pr_err("Failed to configure data interface to SDR timing mode 0\n"); @@ -949,13 +949,25 @@ static int nand_reset_interface(struct nand_chip *chip, int chipnr) */ static int nand_setup_interface(struct nand_chip *chip, int chipnr) { - u8 mode = chip->interface_config.timings.mode; - u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { mode, }; + const struct nand_controller_ops *ops = chip->controller->ops; + u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { }; int ret; if (!nand_controller_can_setup_interface(chip)) return 0; + /* + * A nand_reset_interface() put both the NAND chip and the NAND + * controller in timings mode 0. If the default mode for this chip is + * also 0, no need to proceed to the change again. Plus, at probe time, + * nand_setup_interface() uses ->set/get_features() which would + * fail anyway as the parameter page is not available yet. + */ + if (!chip->best_interface_config) + return 0; + + tmode_param[0] = chip->best_interface_config->timings.mode; + /* Change the mode on the chip side (if supported by the NAND chip) */ if (nand_supports_set_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE)) { nand_select_target(chip, chipnr); @@ -967,14 +979,13 @@ static int nand_setup_interface(struct nand_chip *chip, int chipnr) } /* Change the mode on the controller side */ - ret = chip->controller->ops->setup_interface(chip, chipnr, - &chip->interface_config); + ret = ops->setup_interface(chip, chipnr, chip->best_interface_config); if (ret) return ret; /* Check the mode has been accepted by the chip, if supported */ if (!nand_supports_get_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE)) - return 0; + goto update_interface_config; memset(tmode_param, 0, ONFI_SUBFEATURE_PARAM_LEN); nand_select_target(chip, chipnr); @@ -984,12 +995,15 @@ static int nand_setup_interface(struct nand_chip *chip, int chipnr) if (ret) goto err_reset_chip; - if (tmode_param[0] != mode) { + if (tmode_param[0] != chip->best_interface_config->timings.mode) { pr_warn("timing mode %d not acknowledged by the NAND chip\n", - mode); + chip->best_interface_config->timings.mode); goto err_reset_chip; } +update_interface_config: + chip->current_interface_config = chip->best_interface_config; + return 0; err_reset_chip: @@ -1031,8 +1045,10 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip, /* Verify the controller supports the requested interface */ ret = ops->setup_interface(chip, NAND_DATA_IFACE_CHECK_ONLY, iface); - if (!ret) + if (!ret) { + chip->best_interface_config = iface; return ret; + } /* Fallback to slower modes */ best_mode = iface->timings.mode; @@ -1046,9 +1062,11 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip, ret = ops->setup_interface(chip, NAND_DATA_IFACE_CHECK_ONLY, iface); if (!ret) - return 0; + break; } + chip->best_interface_config = iface; + return 0; } @@ -1067,15 +1085,25 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip, */ static int nand_choose_interface_config(struct nand_chip *chip) { + struct nand_interface_config *iface; + int ret; + if (!nand_controller_can_setup_interface(chip)) return 0; + iface = kzalloc(sizeof(*iface), GFP_KERNEL); + if (!iface) + return -ENOMEM; + if (chip->ops.choose_interface_config) - return chip->ops.choose_interface_config(chip, - &chip->interface_config); + ret = chip->ops.choose_interface_config(chip, iface); + else + ret = nand_choose_best_sdr_timings(chip, iface, NULL); - return nand_choose_best_sdr_timings(chip, &chip->interface_config, - NULL); + if (ret) + kfree(iface); + + return ret; } /** @@ -2501,7 +2529,6 @@ EXPORT_SYMBOL_GPL(nand_subop_get_data_len); */ int nand_reset(struct nand_chip *chip, int chipnr) { - struct nand_interface_config saved_intf_config = chip->interface_config; int ret; ret = nand_reset_interface(chip, chipnr); @@ -2519,18 +2546,6 @@ int nand_reset(struct nand_chip *chip, int chipnr) if (ret) return ret; - /* - * A nand_reset_interface() put both the NAND chip and the NAND - * controller in timings mode 0. If the default mode for this chip is - * also 0, no need to proceed to the change again. Plus, at probe time, - * nand_setup_interface() uses ->set/get_features() which would - * fail anyway as the parameter page is not available yet. - */ - if (!memcmp(&chip->interface_config, &saved_intf_config, - sizeof(saved_intf_config))) - return 0; - - chip->interface_config = saved_intf_config; ret = nand_setup_interface(chip, chipnr); if (ret) return ret; @@ -5198,7 +5213,7 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips, mutex_init(&chip->lock); /* Enforce the right timings for reset/detection */ - onfi_fill_interface_config(chip, &chip->interface_config, NAND_SDR_IFACE, 0); + chip->current_interface_config = nand_get_reset_interface_config(); ret = nand_dt_init(chip); if (ret) @@ -5994,7 +6009,7 @@ static int nand_scan_tail(struct nand_chip *chip) for (i = 0; i < nanddev_ntargets(&chip->base); i++) { ret = nand_setup_interface(chip, i); if (ret) - goto err_nanddev_cleanup; + goto err_free_interface_config; } /* Check, if we should skip the bad block table scan */ @@ -6004,10 +6019,12 @@ static int nand_scan_tail(struct nand_chip *chip) /* Build bad block table */ ret = nand_create_bbt(chip); if (ret) - goto err_nanddev_cleanup; + goto err_free_interface_config; return 0; +err_free_interface_config: + kfree(chip->best_interface_config); err_nanddev_cleanup: nanddev_cleanup(&chip->base); @@ -6101,6 +6118,9 @@ void nand_cleanup(struct nand_chip *chip) & NAND_BBT_DYNAMICSTRUCT) kfree(chip->badblock_pattern); + /* Free the data interface */ + kfree(chip->best_interface_config); + /* Free manufacturer priv data. */ nand_manufacturer_cleanup(chip); diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c index 1e22006c79bae..94d832646487d 100644 --- a/drivers/mtd/nand/raw/nand_timings.c +++ b/drivers/mtd/nand/raw/nand_timings.c @@ -292,6 +292,12 @@ static const struct nand_interface_config onfi_sdr_timings[] = { }, }; +/* All NAND chips share the same reset data interface: SDR mode 0 */ +const struct nand_interface_config *nand_get_reset_interface_config(void) +{ + return &onfi_sdr_timings[0]; +} + /** * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a * set of timings diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index a2427c67d38bb..a725b620aca26 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1069,7 +1069,11 @@ struct nand_manufacturer { * @options: Various chip options. They can partly be set to inform nand_scan * about special functionality. See the defines for further * explanation. - * @interface_config: NAND interface timing information + * @current_interface_config: The currently used NAND interface configuration + * @best_interface_config: The best NAND interface configuration which fits both + * the NAND chip and NAND controller constraints. If + * unset, the default reset interface configuration must + * be used. * @bbt_erase_shift: Number of address bits in a bbt entry * @bbt_options: Bad block table specific options. All options used here must * come from bbm.h. By default, these options will be copied to @@ -1116,7 +1120,8 @@ struct nand_chip { unsigned int options; /* Data interface */ - struct nand_interface_config interface_config; + const struct nand_interface_config *current_interface_config; + struct nand_interface_config *best_interface_config; /* Bad block information */ unsigned int bbt_erase_shift; @@ -1209,7 +1214,7 @@ static inline struct device_node *nand_get_flash_node(struct nand_chip *chip) static inline const struct nand_interface_config * nand_get_interface_config(struct nand_chip *chip) { - return &chip->interface_config; + return chip->current_interface_config; } /* -- GitLab From ccc49eff77bee2885447a032948959a134029fe3 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:13 +0200 Subject: [PATCH 0153/1754] mtd: rawnand: fsl_upm: Remove unused mtd var The mtd var in fun_wait_rnb() is now unused, let's get rid of it and fix the warning resulting from this unused var. Fixes: 50a487e7719c ("mtd: rawnand: Pass a nand_chip object to chip->dev_ready()") Signed-off-by: Boris Brezillon Reviewed-by: Miquel Raynal Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-2-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 627deb26db512..76d1032cd35e8 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -62,7 +62,6 @@ static int fun_chip_ready(struct nand_chip *chip) static void fun_wait_rnb(struct fsl_upm_nand *fun) { if (fun->rnb_gpio[fun->mchip_number] >= 0) { - struct mtd_info *mtd = nand_to_mtd(&fun->chip); int cnt = 1000000; while (--cnt && !fun_chip_ready(&fun->chip)) -- GitLab From 5290833c10b9f997de16f5bd158efcde3f96db54 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:14 +0200 Subject: [PATCH 0154/1754] mtd: rawnand: fsl_upm: Get rid of the unused fsl_upm_nand.parts field fsl_upm_nand.parts is unused, let's get rid of it. Signed-off-by: Boris Brezillon Reviewed-by: Miquel Raynal Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-3-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 76d1032cd35e8..6eba2f4a2f5a0 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -29,7 +29,6 @@ struct fsl_upm_nand { struct device *dev; struct nand_chip chip; int last_ctrl; - struct mtd_partition *parts; struct fsl_upm upm; uint8_t upm_addr_offset; uint8_t upm_cmd_offset; -- GitLab From f760bf29f8676b67fda766d3cf1dbc2fe79829e6 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:15 +0200 Subject: [PATCH 0155/1754] mtd: rawnand: fsl_upm: Allocate the fsl_upm_nand object using devm_kzalloc() This simplifies the init error path and remove function. Signed-off-by: Boris Brezillon Reviewed-by: Miquel Raynal Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-4-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 6eba2f4a2f5a0..9cf79c62ef228 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -205,36 +205,34 @@ static int fun_probe(struct platform_device *ofdev) int size; int i; - fun = kzalloc(sizeof(*fun), GFP_KERNEL); + fun = devm_kzalloc(&ofdev->dev, sizeof(*fun), GFP_KERNEL); if (!fun) return -ENOMEM; ret = of_address_to_resource(ofdev->dev.of_node, 0, &io_res); if (ret) { dev_err(&ofdev->dev, "can't get IO base\n"); - goto err1; + return ret; } ret = fsl_upm_find(io_res.start, &fun->upm); if (ret) { dev_err(&ofdev->dev, "can't find UPM\n"); - goto err1; + return ret; } prop = of_get_property(ofdev->dev.of_node, "fsl,upm-addr-offset", &size); if (!prop || size != sizeof(uint32_t)) { dev_err(&ofdev->dev, "can't get UPM address offset\n"); - ret = -EINVAL; - goto err1; + return -EINVAL; } fun->upm_addr_offset = *prop; prop = of_get_property(ofdev->dev.of_node, "fsl,upm-cmd-offset", &size); if (!prop || size != sizeof(uint32_t)) { dev_err(&ofdev->dev, "can't get UPM command offset\n"); - ret = -EINVAL; - goto err1; + return -EINVAL; } fun->upm_cmd_offset = *prop; @@ -244,7 +242,7 @@ static int fun_probe(struct platform_device *ofdev) fun->mchip_count = size / sizeof(uint32_t); if (fun->mchip_count >= NAND_MAX_CHIPS) { dev_err(&ofdev->dev, "too much multiple chips\n"); - goto err1; + return -EINVAL; } for (i = 0; i < fun->mchip_count; i++) fun->mchip_offsets[i] = be32_to_cpu(prop[i]); @@ -306,8 +304,6 @@ static int fun_probe(struct platform_device *ofdev) break; gpio_free(fun->rnb_gpio[i]); } -err1: - kfree(fun); return ret; } @@ -330,8 +326,6 @@ static int fun_remove(struct platform_device *ofdev) gpio_free(fun->rnb_gpio[i]); } - kfree(fun); - return 0; } -- GitLab From 0016648cdc45eea00bd585ccb4b2596784f60615 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:16 +0200 Subject: [PATCH 0156/1754] mtd: rawnand: fsl_upm: Use devm_kasprintf() to allocate the MTD name This simplifies the init() error path and the remove() handler. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-5-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 9cf79c62ef228..a3e3a968891d6 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -176,8 +176,9 @@ static int fun_chip_init(struct fsl_upm_nand *fun, return -ENODEV; nand_set_flash_node(&fun->chip, flash_np); - mtd->name = kasprintf(GFP_KERNEL, "0x%llx.%pOFn", (u64)io_res->start, - flash_np); + mtd->name = devm_kasprintf(fun->dev, GFP_KERNEL, "0x%llx.%pOFn", + (u64)io_res->start, + flash_np); if (!mtd->name) { ret = -ENOMEM; goto err; @@ -190,8 +191,6 @@ static int fun_chip_init(struct fsl_upm_nand *fun, ret = mtd_device_register(mtd, NULL, 0); err: of_node_put(flash_np); - if (ret) - kfree(mtd->name); return ret; } @@ -318,7 +317,6 @@ static int fun_remove(struct platform_device *ofdev) ret = mtd_device_unregister(mtd); WARN_ON(ret); nand_cleanup(chip); - kfree(mtd->name); for (i = 0; i < fun->mchip_count; i++) { if (fun->rnb_gpio[i] < 0) -- GitLab From 58c5a0e04dfceb1c64c84553bc909d1aa39a3bd5 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:17 +0200 Subject: [PATCH 0157/1754] mtd: rawnand: fsl_upm: Use platform_get_resource() + devm_ioremap_resource() Replace the of_address_to_resource() + devm_ioremap() calls by platform_get_resource() + devm_ioremap_resource() ones which allows us to get rid of one error message since devm_ioremap_resource() already takes care of that. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-6-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index a3e3a968891d6..54851e9ea7840 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -197,7 +196,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun, static int fun_probe(struct platform_device *ofdev) { struct fsl_upm_nand *fun; - struct resource io_res; + struct resource *io_res; const __be32 *prop; int rnb_gpio; int ret; @@ -208,13 +207,12 @@ static int fun_probe(struct platform_device *ofdev) if (!fun) return -ENOMEM; - ret = of_address_to_resource(ofdev->dev.of_node, 0, &io_res); - if (ret) { - dev_err(&ofdev->dev, "can't get IO base\n"); - return ret; - } + io_res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); + fun->io_base = devm_ioremap_resource(&ofdev->dev, io_res); + if (IS_ERR(fun->io_base)) + return PTR_ERR(fun->io_base); - ret = fsl_upm_find(io_res.start, &fun->upm); + ret = fsl_upm_find(io_res->start, &fun->upm); if (ret) { dev_err(&ofdev->dev, "can't find UPM\n"); return ret; @@ -280,17 +278,10 @@ static int fun_probe(struct platform_device *ofdev) fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN | FSL_UPM_WAIT_WRITE_BYTE; - fun->io_base = devm_ioremap(&ofdev->dev, io_res.start, - resource_size(&io_res)); - if (!fun->io_base) { - ret = -ENOMEM; - goto err2; - } - fun->dev = &ofdev->dev; fun->last_ctrl = NAND_CLE; - ret = fun_chip_init(fun, ofdev->dev.of_node, &io_res); + ret = fun_chip_init(fun, ofdev->dev.of_node, io_res); if (ret) goto err2; -- GitLab From a50895bbdbd433173c698c4a2321b0f02ff19ba1 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:18 +0200 Subject: [PATCH 0158/1754] mtd: rawnand: fsl_upm: Use gpio descriptors The integer-based GPIO ids are now deprecated in favor of the GPIO desc API. The PPC platforms have already been converted to GPIOLIB, so let's use gpio descs in the NAND driver too. While at it, we use devm_gpiod_get_index_optional() so we can get rid of the manual gpio desc release done in the init error path and in the remove function. Signed-off-by: Boris Brezillon Reviewed-by: Miquel Raynal Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-7-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 44 ++++++++-------------------------- 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 54851e9ea7840..977b7aad419b5 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -32,7 +31,7 @@ struct fsl_upm_nand { uint8_t upm_addr_offset; uint8_t upm_cmd_offset; void __iomem *io_base; - int rnb_gpio[NAND_MAX_CHIPS]; + struct gpio_desc *rnb_gpio[NAND_MAX_CHIPS]; uint32_t mchip_offsets[NAND_MAX_CHIPS]; uint32_t mchip_count; uint32_t mchip_number; @@ -50,7 +49,7 @@ static int fun_chip_ready(struct nand_chip *chip) { struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); - if (gpio_get_value(fun->rnb_gpio[fun->mchip_number])) + if (gpiod_get_value(fun->rnb_gpio[fun->mchip_number])) return 1; dev_vdbg(fun->dev, "busy\n"); @@ -165,7 +164,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun, if (fun->mchip_count > 1) fun->chip.legacy.select_chip = fun_select_chip; - if (fun->rnb_gpio[0] >= 0) + if (!fun->rnb_gpio[0]) fun->chip.legacy.dev_ready = fun_chip_ready; mtd->dev.parent = fun->dev; @@ -198,7 +197,6 @@ static int fun_probe(struct platform_device *ofdev) struct fsl_upm_nand *fun; struct resource *io_res; const __be32 *prop; - int rnb_gpio; int ret; int size; int i; @@ -248,20 +246,12 @@ static int fun_probe(struct platform_device *ofdev) } for (i = 0; i < fun->mchip_count; i++) { - fun->rnb_gpio[i] = -1; - rnb_gpio = of_get_gpio(ofdev->dev.of_node, i); - if (rnb_gpio >= 0) { - ret = gpio_request(rnb_gpio, dev_name(&ofdev->dev)); - if (ret) { - dev_err(&ofdev->dev, - "can't request RNB gpio #%d\n", i); - goto err2; - } - gpio_direction_input(rnb_gpio); - fun->rnb_gpio[i] = rnb_gpio; - } else if (rnb_gpio == -EINVAL) { + fun->rnb_gpio[i] = devm_gpiod_get_index_optional(&ofdev->dev, + NULL, i, + GPIOD_IN); + if (IS_ERR(fun->rnb_gpio[i])) { dev_err(&ofdev->dev, "RNB gpio #%d is invalid\n", i); - goto err2; + return PTR_ERR(fun->rnb_gpio[i]); } } @@ -283,19 +273,11 @@ static int fun_probe(struct platform_device *ofdev) ret = fun_chip_init(fun, ofdev->dev.of_node, io_res); if (ret) - goto err2; + return ret; dev_set_drvdata(&ofdev->dev, fun); return 0; -err2: - for (i = 0; i < fun->mchip_count; i++) { - if (fun->rnb_gpio[i] < 0) - break; - gpio_free(fun->rnb_gpio[i]); - } - - return ret; } static int fun_remove(struct platform_device *ofdev) @@ -303,18 +285,12 @@ static int fun_remove(struct platform_device *ofdev) struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); struct nand_chip *chip = &fun->chip; struct mtd_info *mtd = nand_to_mtd(chip); - int ret, i; + int ret; ret = mtd_device_unregister(mtd); WARN_ON(ret); nand_cleanup(chip); - for (i = 0; i < fun->mchip_count; i++) { - if (fun->rnb_gpio[i] < 0) - break; - gpio_free(fun->rnb_gpio[i]); - } - return 0; } -- GitLab From abc846afda664b7f229f32b40bbef738c3511801 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:19 +0200 Subject: [PATCH 0159/1754] mtd: rawnand: fsl_upm: Inherit from nand_controller Explicitly inherit from nand_controller instead of relying on the nand_chip.legacy.dummy_controller field. Signed-off-by: Boris Brezillon Reviewed-by: Miquel Raynal Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-8-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 977b7aad419b5..9a63e36825d8f 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -24,6 +24,7 @@ #define FSL_UPM_WAIT_WRITE_BUFFER 0x4 struct fsl_upm_nand { + struct nand_controller base; struct device *dev; struct nand_chip chip; int last_ctrl; @@ -167,6 +168,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun, if (!fun->rnb_gpio[0]) fun->chip.legacy.dev_ready = fun_chip_ready; + fun->chip.controller = &fun->base; mtd->dev.parent = fun->dev; flash_np = of_get_next_child(upm_np, NULL); @@ -268,6 +270,7 @@ static int fun_probe(struct platform_device *ofdev) fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN | FSL_UPM_WAIT_WRITE_BYTE; + nand_controller_init(&fun->base); fun->dev = &ofdev->dev; fun->last_ctrl = NAND_CLE; -- GitLab From 54309d65776755bcdb9dcf3744cd764fc1e254ea Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:20 +0200 Subject: [PATCH 0160/1754] mtd: rawnand: fsl_upm: Implement exec_op() Implement exec_op() so we can get rid of the legacy interface implementation. Signed-off-by: Boris Brezillon Reviewed-by: Miquel Raynal Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-9-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 86 ++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 9a63e36825d8f..03ca20930274f 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -194,6 +194,91 @@ static int fun_chip_init(struct fsl_upm_nand *fun, return ret; } +static int func_exec_instr(struct nand_chip *chip, + const struct nand_op_instr *instr) +{ + struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); + u32 mar, reg_offs = fun->mchip_offsets[fun->mchip_number]; + unsigned int i; + const u8 *out; + u8 *in; + + switch (instr->type) { + case NAND_OP_CMD_INSTR: + fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset); + mar = (instr->ctx.cmd.opcode << (32 - fun->upm.width)) | + reg_offs; + fsl_upm_run_pattern(&fun->upm, fun->io_base + reg_offs, mar); + fsl_upm_end_pattern(&fun->upm); + return 0; + + case NAND_OP_ADDR_INSTR: + fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset); + for (i = 0; i < instr->ctx.addr.naddrs; i++) { + mar = (instr->ctx.addr.addrs[i] << (32 - fun->upm.width)) | + reg_offs; + fsl_upm_run_pattern(&fun->upm, fun->io_base + reg_offs, mar); + } + fsl_upm_end_pattern(&fun->upm); + return 0; + + case NAND_OP_DATA_IN_INSTR: + in = instr->ctx.data.buf.in; + for (i = 0; i < instr->ctx.data.len; i++) + in[i] = in_8(fun->io_base + reg_offs); + return 0; + + case NAND_OP_DATA_OUT_INSTR: + out = instr->ctx.data.buf.out; + for (i = 0; i < instr->ctx.data.len; i++) + out_8(fun->io_base + reg_offs, out[i]); + return 0; + + case NAND_OP_WAITRDY_INSTR: + if (!fun->rnb_gpio[fun->mchip_number]) + return nand_soft_waitrdy(chip, instr->ctx.waitrdy.timeout_ms); + + return nand_gpio_waitrdy(chip, fun->rnb_gpio[fun->mchip_number], + instr->ctx.waitrdy.timeout_ms); + + default: + return -EINVAL; + } + + return 0; +} + +static int fun_exec_op(struct nand_chip *chip, const struct nand_operation *op, + bool check_only) +{ + struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); + unsigned int i; + int ret; + + if (op->cs > NAND_MAX_CHIPS) + return -EINVAL; + + if (check_only) + return 0; + + fun->mchip_number = op->cs; + + for (i = 0; i < op->ninstrs; i++) { + ret = func_exec_instr(chip, &op->instrs[i]); + if (ret) + return ret; + + if (op->instrs[i].delay_ns) + ndelay(op->instrs[i].delay_ns); + } + + return 0; +} + +static const struct nand_controller_ops fun_ops = { + .exec_op = fun_exec_op, +}; + static int fun_probe(struct platform_device *ofdev) { struct fsl_upm_nand *fun; @@ -271,6 +356,7 @@ static int fun_probe(struct platform_device *ofdev) FSL_UPM_WAIT_WRITE_BYTE; nand_controller_init(&fun->base); + fun->base.ops = &fun_ops; fun->dev = &ofdev->dev; fun->last_ctrl = NAND_CLE; -- GitLab From 8fac41ebe2895fccf4bc40347f1638fe845d4936 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 15:49:21 +0200 Subject: [PATCH 0161/1754] mtd: rawnand: fsl_upm: Get rid of the legacy interface implementation Now that the driver implements exec_op(), we can get rid of the legacy interface implementation. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603134922.1352340-10-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/fsl_upm.c | 133 --------------------------------- 1 file changed, 133 deletions(-) diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 03ca20930274f..197850aeb2611 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -19,15 +19,10 @@ #include #include -#define FSL_UPM_WAIT_RUN_PATTERN 0x1 -#define FSL_UPM_WAIT_WRITE_BYTE 0x2 -#define FSL_UPM_WAIT_WRITE_BUFFER 0x4 - struct fsl_upm_nand { struct nand_controller base; struct device *dev; struct nand_chip chip; - int last_ctrl; struct fsl_upm upm; uint8_t upm_addr_offset; uint8_t upm_cmd_offset; @@ -36,8 +31,6 @@ struct fsl_upm_nand { uint32_t mchip_offsets[NAND_MAX_CHIPS]; uint32_t mchip_count; uint32_t mchip_number; - int chip_delay; - uint32_t wait_flags; }; static inline struct fsl_upm_nand *to_fsl_upm_nand(struct mtd_info *mtdinfo) @@ -46,105 +39,6 @@ static inline struct fsl_upm_nand *to_fsl_upm_nand(struct mtd_info *mtdinfo) chip); } -static int fun_chip_ready(struct nand_chip *chip) -{ - struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); - - if (gpiod_get_value(fun->rnb_gpio[fun->mchip_number])) - return 1; - - dev_vdbg(fun->dev, "busy\n"); - return 0; -} - -static void fun_wait_rnb(struct fsl_upm_nand *fun) -{ - if (fun->rnb_gpio[fun->mchip_number] >= 0) { - int cnt = 1000000; - - while (--cnt && !fun_chip_ready(&fun->chip)) - cpu_relax(); - if (!cnt) - dev_err(fun->dev, "tired waiting for RNB\n"); - } else { - ndelay(100); - } -} - -static void fun_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl) -{ - struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); - u32 mar; - - if (!(ctrl & fun->last_ctrl)) { - fsl_upm_end_pattern(&fun->upm); - - if (cmd == NAND_CMD_NONE) - return; - - fun->last_ctrl = ctrl & (NAND_ALE | NAND_CLE); - } - - if (ctrl & NAND_CTRL_CHANGE) { - if (ctrl & NAND_ALE) - fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset); - else if (ctrl & NAND_CLE) - fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset); - } - - mar = (cmd << (32 - fun->upm.width)) | - fun->mchip_offsets[fun->mchip_number]; - fsl_upm_run_pattern(&fun->upm, chip->legacy.IO_ADDR_R, mar); - - if (fun->wait_flags & FSL_UPM_WAIT_RUN_PATTERN) - fun_wait_rnb(fun); -} - -static void fun_select_chip(struct nand_chip *chip, int mchip_nr) -{ - struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); - - if (mchip_nr == -1) { - chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); - } else if (mchip_nr >= 0 && mchip_nr < NAND_MAX_CHIPS) { - fun->mchip_number = mchip_nr; - chip->legacy.IO_ADDR_R = fun->io_base + fun->mchip_offsets[mchip_nr]; - chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R; - } else { - BUG(); - } -} - -static uint8_t fun_read_byte(struct nand_chip *chip) -{ - struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); - - return in_8(fun->chip.legacy.IO_ADDR_R); -} - -static void fun_read_buf(struct nand_chip *chip, uint8_t *buf, int len) -{ - struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); - int i; - - for (i = 0; i < len; i++) - buf[i] = in_8(fun->chip.legacy.IO_ADDR_R); -} - -static void fun_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) -{ - struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); - int i; - - for (i = 0; i < len; i++) { - out_8(fun->chip.legacy.IO_ADDR_W, buf[i]); - if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BYTE) - fun_wait_rnb(fun); - } - if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BUFFER) - fun_wait_rnb(fun); -} - static int fun_chip_init(struct fsl_upm_nand *fun, const struct device_node *upm_np, const struct resource *io_res) @@ -153,21 +47,8 @@ static int fun_chip_init(struct fsl_upm_nand *fun, int ret; struct device_node *flash_np; - fun->chip.legacy.IO_ADDR_R = fun->io_base; - fun->chip.legacy.IO_ADDR_W = fun->io_base; - fun->chip.legacy.cmd_ctrl = fun_cmd_ctrl; - fun->chip.legacy.chip_delay = fun->chip_delay; - fun->chip.legacy.read_byte = fun_read_byte; - fun->chip.legacy.read_buf = fun_read_buf; - fun->chip.legacy.write_buf = fun_write_buf; fun->chip.ecc.mode = NAND_ECC_SOFT; fun->chip.ecc.algo = NAND_ECC_HAMMING; - if (fun->mchip_count > 1) - fun->chip.legacy.select_chip = fun_select_chip; - - if (!fun->rnb_gpio[0]) - fun->chip.legacy.dev_ready = fun_chip_ready; - fun->chip.controller = &fun->base; mtd->dev.parent = fun->dev; @@ -342,23 +223,9 @@ static int fun_probe(struct platform_device *ofdev) } } - prop = of_get_property(ofdev->dev.of_node, "chip-delay", NULL); - if (prop) - fun->chip_delay = be32_to_cpup(prop); - else - fun->chip_delay = 50; - - prop = of_get_property(ofdev->dev.of_node, "fsl,upm-wait-flags", &size); - if (prop && size == sizeof(uint32_t)) - fun->wait_flags = be32_to_cpup(prop); - else - fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN | - FSL_UPM_WAIT_WRITE_BYTE; - nand_controller_init(&fun->base); fun->base.ops = &fun_ops; fun->dev = &ofdev->dev; - fun->last_ctrl = NAND_CLE; ret = fun_chip_init(fun, ofdev->dev.of_node, io_res); if (ret) -- GitLab From b4c719685491983628155c5c8b677332709c4c6f Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 17:07:44 +0200 Subject: [PATCH 0162/1754] mtd: rawnand: gpio: Inherit from nand_controller Inherit from nand_controller so we don't rely on the nand_chip.legacy.dummy_controller field. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603150746.1423257-2-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/gpio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c index 938077e5c6a9b..33828fb20a138 100644 --- a/drivers/mtd/nand/raw/gpio.c +++ b/drivers/mtd/nand/raw/gpio.c @@ -27,6 +27,7 @@ #include struct gpiomtd { + struct nand_controller base; void __iomem *io_sync; struct nand_chip nand_chip; struct gpio_nand_platdata plat; @@ -273,6 +274,7 @@ static int gpio_nand_probe(struct platform_device *pdev) if (gpiomtd->rdy) chip->legacy.dev_ready = gpio_nand_devready; + nand_controller_init(&gpiomtd->base); nand_set_flash_node(chip, pdev->dev.of_node); chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R; chip->ecc.mode = NAND_ECC_SOFT; @@ -280,6 +282,7 @@ static int gpio_nand_probe(struct platform_device *pdev) chip->options = gpiomtd->plat.options; chip->legacy.chip_delay = gpiomtd->plat.chip_delay; chip->legacy.cmd_ctrl = gpio_nand_cmd_ctrl; + chip->controller = &gpiomtd->base; mtd = nand_to_mtd(chip); mtd->dev.parent = dev; -- GitLab From 22b27a675d714499848d4f389082eb0d959a7b34 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 17:07:45 +0200 Subject: [PATCH 0163/1754] mtd: rawnand: gpio: Implement exec_op() Implement exec_op() so we can get rid of the legacy interface implementation. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603150746.1423257-3-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/gpio.c | 104 ++++++++++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c index 33828fb20a138..1159980111922 100644 --- a/drivers/mtd/nand/raw/gpio.c +++ b/drivers/mtd/nand/raw/gpio.c @@ -25,9 +25,11 @@ #include #include #include +#include struct gpiomtd { struct nand_controller base; + void __iomem *io; void __iomem *io_sync; struct nand_chip nand_chip; struct gpio_nand_platdata plat; @@ -98,6 +100,99 @@ static int gpio_nand_devready(struct nand_chip *chip) return gpiod_get_value(gpiomtd->rdy); } +static int gpio_nand_exec_instr(struct nand_chip *chip, + const struct nand_op_instr *instr) +{ + struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip)); + unsigned int i; + + switch (instr->type) { + case NAND_OP_CMD_INSTR: + gpio_nand_dosync(gpiomtd); + gpiod_set_value(gpiomtd->cle, 1); + gpio_nand_dosync(gpiomtd); + writeb(instr->ctx.cmd.opcode, gpiomtd->io); + gpio_nand_dosync(gpiomtd); + gpiod_set_value(gpiomtd->cle, 0); + return 0; + + case NAND_OP_ADDR_INSTR: + gpio_nand_dosync(gpiomtd); + gpiod_set_value(gpiomtd->ale, 1); + gpio_nand_dosync(gpiomtd); + for (i = 0; i < instr->ctx.addr.naddrs; i++) + writeb(instr->ctx.addr.addrs[i], gpiomtd->io); + gpio_nand_dosync(gpiomtd); + gpiod_set_value(gpiomtd->ale, 0); + return 0; + + case NAND_OP_DATA_IN_INSTR: + gpio_nand_dosync(gpiomtd); + if ((chip->options & NAND_BUSWIDTH_16) && + !instr->ctx.data.force_8bit) + ioread16_rep(gpiomtd->io, instr->ctx.data.buf.in, + instr->ctx.data.len / 2); + else + ioread8_rep(gpiomtd->io, instr->ctx.data.buf.in, + instr->ctx.data.len); + return 0; + + case NAND_OP_DATA_OUT_INSTR: + gpio_nand_dosync(gpiomtd); + if ((chip->options & NAND_BUSWIDTH_16) && + !instr->ctx.data.force_8bit) + iowrite16_rep(gpiomtd->io, instr->ctx.data.buf.out, + instr->ctx.data.len / 2); + else + iowrite8_rep(gpiomtd->io, instr->ctx.data.buf.out, + instr->ctx.data.len); + return 0; + + case NAND_OP_WAITRDY_INSTR: + if (!gpiomtd->rdy) + return nand_soft_waitrdy(chip, instr->ctx.waitrdy.timeout_ms); + + return nand_gpio_waitrdy(chip, gpiomtd->rdy, + instr->ctx.waitrdy.timeout_ms); + + default: + return -EINVAL; + } + + return 0; +} + +static int gpio_nand_exec_op(struct nand_chip *chip, + const struct nand_operation *op, + bool check_only) +{ + struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip)); + unsigned int i; + int ret = 0; + + if (check_only) + return 0; + + gpio_nand_dosync(gpiomtd); + gpiod_set_value(gpiomtd->nce, 0); + for (i = 0; i < op->ninstrs; i++) { + ret = gpio_nand_exec_instr(chip, &op->instrs[i]); + if (ret) + break; + + if (op->instrs[i].delay_ns) + ndelay(op->instrs[i].delay_ns); + } + gpio_nand_dosync(gpiomtd); + gpiod_set_value(gpiomtd->nce, 1); + + return ret; +} + +static const struct nand_controller_ops gpio_nand_ops = { + .exec_op = gpio_nand_exec_op, +}; + #ifdef CONFIG_OF static const struct of_device_id gpio_nand_id_table[] = { { .compatible = "gpio-control-nand" }, @@ -226,9 +321,9 @@ static int gpio_nand_probe(struct platform_device *pdev) chip = &gpiomtd->nand_chip; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - chip->legacy.IO_ADDR_R = devm_ioremap_resource(dev, res); - if (IS_ERR(chip->legacy.IO_ADDR_R)) - return PTR_ERR(chip->legacy.IO_ADDR_R); + gpiomtd->io = devm_ioremap_resource(dev, res); + if (IS_ERR(gpiomtd->io)) + return PTR_ERR(gpiomtd->io); res = gpio_nand_get_io_sync(pdev); if (res) { @@ -275,7 +370,10 @@ static int gpio_nand_probe(struct platform_device *pdev) chip->legacy.dev_ready = gpio_nand_devready; nand_controller_init(&gpiomtd->base); + gpiomtd->base.ops = &gpio_nand_ops; + nand_set_flash_node(chip, pdev->dev.of_node); + chip->legacy.IO_ADDR_R = gpiomtd->io; chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R; chip->ecc.mode = NAND_ECC_SOFT; chip->ecc.algo = NAND_ECC_HAMMING; -- GitLab From df66c27101ff279dc2e8cc2ced7191029495f194 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 17:07:46 +0200 Subject: [PATCH 0164/1754] mtd: rawnand: gpio: Get rid of the legacy interface implementation Now that exec_op() is implemented, we can get rid of the legacy interface implementation. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603150746.1423257-4-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/gpio.c | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c index 1159980111922..3bd847ccc3f36 100644 --- a/drivers/mtd/nand/raw/gpio.c +++ b/drivers/mtd/nand/raw/gpio.c @@ -72,34 +72,6 @@ static void gpio_nand_dosync(struct gpiomtd *gpiomtd) static inline void gpio_nand_dosync(struct gpiomtd *gpiomtd) {} #endif -static void gpio_nand_cmd_ctrl(struct nand_chip *chip, int cmd, - unsigned int ctrl) -{ - struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip)); - - gpio_nand_dosync(gpiomtd); - - if (ctrl & NAND_CTRL_CHANGE) { - if (gpiomtd->nce) - gpiod_set_value(gpiomtd->nce, !(ctrl & NAND_NCE)); - gpiod_set_value(gpiomtd->cle, !!(ctrl & NAND_CLE)); - gpiod_set_value(gpiomtd->ale, !!(ctrl & NAND_ALE)); - gpio_nand_dosync(gpiomtd); - } - if (cmd == NAND_CMD_NONE) - return; - - writeb(cmd, gpiomtd->nand_chip.legacy.IO_ADDR_W); - gpio_nand_dosync(gpiomtd); -} - -static int gpio_nand_devready(struct nand_chip *chip) -{ - struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip)); - - return gpiod_get_value(gpiomtd->rdy); -} - static int gpio_nand_exec_instr(struct nand_chip *chip, const struct nand_op_instr *instr) { @@ -365,21 +337,14 @@ static int gpio_nand_probe(struct platform_device *pdev) ret = PTR_ERR(gpiomtd->rdy); goto out_ce; } - /* Using RDY pin */ - if (gpiomtd->rdy) - chip->legacy.dev_ready = gpio_nand_devready; nand_controller_init(&gpiomtd->base); gpiomtd->base.ops = &gpio_nand_ops; nand_set_flash_node(chip, pdev->dev.of_node); - chip->legacy.IO_ADDR_R = gpiomtd->io; - chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R; chip->ecc.mode = NAND_ECC_SOFT; chip->ecc.algo = NAND_ECC_HAMMING; chip->options = gpiomtd->plat.options; - chip->legacy.chip_delay = gpiomtd->plat.chip_delay; - chip->legacy.cmd_ctrl = gpio_nand_cmd_ctrl; chip->controller = &gpiomtd->base; mtd = nand_to_mtd(chip); -- GitLab From 735bf220b11fe003d4236d430db0c7131babf468 Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Tue, 9 Jun 2020 13:45:57 +0100 Subject: [PATCH 0165/1754] mtd: rawnand: trivial spelling The word 'descriptor' is misspelled throughout the tree. Fix it up accordingly: decriptors -> descriptors Signed-off-by: Kieran Bingham Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200609124610.3445662-5-kieran.bingham+renesas@ideasonboard.com --- drivers/mtd/nand/raw/mxc_nand.c | 2 +- drivers/mtd/nand/raw/nand_bbt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index 07c41e8bae2d1..a043d76b48cba 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -1432,7 +1432,7 @@ static int mxc_nand_get_features(struct nand_chip *chip, int addr, } /* - * The generic flash bbt decriptors overlap with our ecc + * The generic flash bbt descriptors overlap with our ecc * hardware, so define some i.MX specific ones. */ static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' }; diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c index 96045d60471e4..344a24fd2ca8c 100644 --- a/drivers/mtd/nand/raw/nand_bbt.c +++ b/drivers/mtd/nand/raw/nand_bbt.c @@ -1226,7 +1226,7 @@ static int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd) return -ENOMEM; /* - * If no primary table decriptor is given, scan the device to build a + * If no primary table descriptor is given, scan the device to build a * memory based bad block table. */ if (!td) { -- GitLab From 443440cc4a901af462239d286cd10721aa1c7dfc Mon Sep 17 00:00:00 2001 From: Sivaprakash Murugesan Date: Fri, 12 Jun 2020 13:28:15 +0530 Subject: [PATCH 0166/1754] mtd: rawnand: qcom: avoid write to unavailable register SFLASHC_BURST_CFG is only available on older ipq NAND platforms, this register has been removed when the NAND controller got implemented in the qpic controller. Avoid writing this register on devices which are based on qpic NAND controller. Fixes: dce84760b09f ("mtd: nand: qcom: Support for IPQ8074 QPIC NAND controller") Cc: stable@vger.kernel.org Signed-off-by: Sivaprakash Murugesan Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/1591948696-16015-2-git-send-email-sivaprak@codeaurora.org --- drivers/mtd/nand/raw/qcom_nandc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index f1daf330951be..78b5f211598c9 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -459,11 +459,13 @@ struct qcom_nand_host { * among different NAND controllers. * @ecc_modes - ecc mode for NAND * @is_bam - whether NAND controller is using BAM + * @is_qpic - whether NAND CTRL is part of qpic IP * @dev_cmd_reg_start - NAND_DEV_CMD_* registers starting offset */ struct qcom_nandc_props { u32 ecc_modes; bool is_bam; + bool is_qpic; u32 dev_cmd_reg_start; }; @@ -2774,7 +2776,8 @@ static int qcom_nandc_setup(struct qcom_nand_controller *nandc) u32 nand_ctrl; /* kill onenand */ - nandc_write(nandc, SFLASHC_BURST_CFG, 0); + if (!nandc->props->is_qpic) + nandc_write(nandc, SFLASHC_BURST_CFG, 0); nandc_write(nandc, dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD), NAND_DEV_CMD_VLD_VAL); @@ -3035,12 +3038,14 @@ static const struct qcom_nandc_props ipq806x_nandc_props = { static const struct qcom_nandc_props ipq4019_nandc_props = { .ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT), .is_bam = true, + .is_qpic = true, .dev_cmd_reg_start = 0x0, }; static const struct qcom_nandc_props ipq8074_nandc_props = { .ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT), .is_bam = true, + .is_qpic = true, .dev_cmd_reg_start = 0x7000, }; -- GitLab From cb272395dceef1652247dad08a50ed4153ffbd43 Mon Sep 17 00:00:00 2001 From: Sivaprakash Murugesan Date: Fri, 12 Jun 2020 13:28:16 +0530 Subject: [PATCH 0167/1754] mtd: rawnand: qcom: set BAM mode only if not set already BAM is DMA controller on QCOM ipq platforms, BAM mode on NAND driver is set by writing BAM_MODE_EN bit on NAND_CTRL register. NAND_CTRL is an operational register and in BAM mode operational registers are read only. So, before enabling BAM mode by writing the NAND_CTRL register, check if BAM mode was already enabled by the bootloader, and enable BAM mode only if it is not enabled already. Signed-off-by: Sivaprakash Murugesan Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/1591948696-16015-3-git-send-email-sivaprak@codeaurora.org --- drivers/mtd/nand/raw/qcom_nandc.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index 78b5f211598c9..bd7a7251429bd 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -2784,7 +2784,16 @@ static int qcom_nandc_setup(struct qcom_nand_controller *nandc) /* enable ADM or BAM DMA */ if (nandc->props->is_bam) { nand_ctrl = nandc_read(nandc, NAND_CTRL); - nandc_write(nandc, NAND_CTRL, nand_ctrl | BAM_MODE_EN); + + /* + *NAND_CTRL is an operational registers, and CPU + * access to operational registers are read only + * in BAM mode. So update the NAND_CTRL register + * only if it is not in BAM mode. In most cases BAM + * mode will be enabled in bootloader + */ + if (!(nand_ctrl & BAM_MODE_EN)) + nandc_write(nandc, NAND_CTRL, nand_ctrl | BAM_MODE_EN); } else { nandc_write(nandc, NAND_FLASH_CHIP_SELECT, DM_EN); } -- GitLab From bee3ab8bdd3b13faf08e5b6e0218f59b0a49fcc3 Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Fri, 12 Jun 2020 17:29:01 -0400 Subject: [PATCH 0168/1754] mtd: rawnand: brcmnand: Don't default to edu transfer When flash-dma is absent do not default to using flash-edu. Make sure flash-edu is enabled before setting EDU transfer function. Fixes: a5d53ad26a8b ("mtd: rawnand: brcmnand: Add support for flash-edu for dma transfers") Signed-off-by: Kamal Dasu Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200612212902.21347-2-kdasu.kdev@gmail.com --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 44068e9eea035..ac934a715a194 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -3023,8 +3023,9 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) if (ret < 0) goto err; - /* set edu transfer function to call */ - ctrl->dma_trans = brcmnand_edu_trans; + if (has_edu(ctrl)) + /* set edu transfer function to call */ + ctrl->dma_trans = brcmnand_edu_trans; } /* Disable automatic device ID config, direct addressing */ -- GitLab From 4551e78ad98add1f16b70cf286d5aad3ce7bcd4c Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Fri, 12 Jun 2020 17:29:02 -0400 Subject: [PATCH 0169/1754] mtd: rawnand: brcmnand: ECC error handling on EDU transfers Implement ECC correctable and uncorrectable error handling for EDU reads. If ECC correctable bitflips are encountered on EDU transfer, read page again using PIO. This is needed due to a NAND controller limitation where corrected data is not transferred to the DMA buffer on ECC error. This applies to ECC correctable errors that are reported by the controller hardware based on set number of bitflips threshold in the controller threshold register, bitflips below the threshold are corrected silently and are not reported by the controller hardware. Fixes: a5d53ad26a8b ("mtd: rawnand: brcmnand: Add support for flash-edu for dma transfers") Signed-off-by: Kamal Dasu Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200612212902.21347-3-kdasu.kdev@gmail.com --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index ac934a715a194..a4033d32a7103 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1918,6 +1918,22 @@ static int brcmnand_edu_trans(struct brcmnand_host *host, u64 addr, u32 *buf, edu_writel(ctrl, EDU_STOP, 0); /* force stop */ edu_readl(ctrl, EDU_STOP); + if (!ret && edu_cmd == EDU_CMD_READ) { + u64 err_addr = 0; + + /* + * check for ECC errors here, subpage ECC errors are + * retained in ECC error address register + */ + err_addr = brcmnand_get_uncorrecc_addr(ctrl); + if (!err_addr) { + err_addr = brcmnand_get_correcc_addr(ctrl); + if (err_addr) + ret = -EUCLEAN; + } else + ret = -EBADMSG; + } + return ret; } @@ -2124,6 +2140,7 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip, u64 err_addr = 0; int err; bool retry = true; + bool edu_err = false; dev_dbg(ctrl->dev, "read %llx -> %p\n", (unsigned long long)addr, buf); @@ -2141,6 +2158,10 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip, else return -EIO; } + + if (has_edu(ctrl) && err_addr) + edu_err = true; + } else { if (oob) memset(oob, 0x99, mtd->oobsize); @@ -2188,6 +2209,11 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip, if (mtd_is_bitflip(err)) { unsigned int corrected = brcmnand_count_corrected(ctrl); + /* in case of EDU correctable error we read again using PIO */ + if (edu_err) + err = brcmnand_read_by_pio(mtd, chip, addr, trans, buf, + oob, &err_addr); + dev_dbg(ctrl->dev, "corrected error at 0x%llx\n", (unsigned long long)err_addr); mtd->ecc_stats.corrected += corrected; -- GitLab From 91e81150d38842b58133ce1a5d70c88e8f1cf7c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Mon, 15 Jun 2020 11:17:40 +0200 Subject: [PATCH 0170/1754] mtd: parsers: bcm63xx: simplify CFE detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of trying to parse CFE version string, which is customized by some vendors, let's just check that "CFE1" was passed on argument 3. Signed-off-by: Álvaro Fernández Rojas Signed-off-by: Jonas Gorski Reviewed-by: Florian Fainelli Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200615091740.2958303-1-noltari@gmail.com --- drivers/mtd/parsers/bcm63xxpart.c | 32 ++++++++++++------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/drivers/mtd/parsers/bcm63xxpart.c b/drivers/mtd/parsers/bcm63xxpart.c index 78f90c6c18fd3..b15bdadaedb59 100644 --- a/drivers/mtd/parsers/bcm63xxpart.c +++ b/drivers/mtd/parsers/bcm63xxpart.c @@ -22,6 +22,11 @@ #include #include +#ifdef CONFIG_MIPS +#include +#include +#endif /* CONFIG_MIPS */ + #define BCM963XX_CFE_BLOCK_SIZE SZ_64K /* always at least 64KiB */ #define BCM963XX_CFE_MAGIC_OFFSET 0x4e0 @@ -32,28 +37,15 @@ #define STR_NULL_TERMINATE(x) \ do { char *_str = (x); _str[sizeof(x) - 1] = 0; } while (0) -static int bcm63xx_detect_cfe(struct mtd_info *master) +static inline int bcm63xx_detect_cfe(void) { - char buf[9]; - int ret; - size_t retlen; + int ret = 0; - ret = mtd_read(master, BCM963XX_CFE_VERSION_OFFSET, 5, &retlen, - (void *)buf); - buf[retlen] = 0; +#ifdef CONFIG_MIPS + ret = (fw_arg3 == CFE_EPTSEAL); +#endif /* CONFIG_MIPS */ - if (ret) - return ret; - - if (strncmp("cfe-v", buf, 5) == 0) - return 0; - - /* very old CFE's do not have the cfe-v string, so check for magic */ - ret = mtd_read(master, BCM963XX_CFE_MAGIC_OFFSET, 8, &retlen, - (void *)buf); - buf[retlen] = 0; - - return strncmp("CFE1CFE1", buf, 8); + return ret; } static int bcm63xx_read_nvram(struct mtd_info *master, @@ -138,7 +130,7 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, struct bcm963xx_nvram *nvram = NULL; int ret; - if (bcm63xx_detect_cfe(master)) + if (!bcm63xx_detect_cfe()) return -EINVAL; nvram = vzalloc(sizeof(*nvram)); -- GitLab From fef95b7211deb80c19ebfcdd5208ec7b80b40cbf Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 15 Jun 2020 18:57:48 +0300 Subject: [PATCH 0171/1754] mtd: spi-nor: intel-spi: Add support for Intel Emmitsburg SPI serial flash Intel Emmitsburg has the same SPI serial flash controller as Lewisburg. Add Emmitsburg PCI ID to the driver list of supported devices. Signed-off-by: Mika Westerberg Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20200615155748.920-1-mika.westerberg@linux.intel.com --- drivers/mtd/spi-nor/controllers/intel-spi-pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c index 81329f680bec0..c19f1035cc02f 100644 --- a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c +++ b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c @@ -68,6 +68,7 @@ static const struct pci_device_id intel_spi_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x06a4), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x18e0), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x1bca), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info }, -- GitLab From a0eec15673222ef52655fc6a5da0008c501aebdc Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 24 Jun 2020 22:21:03 +0300 Subject: [PATCH 0172/1754] mtd: spi-nor: intel-spi: Add support for Intel Tiger Lake-H SPI serial flash Intel Tiger Lake-H has the same SPI serial flash controller as Cannon Lake. Add Tiger Lake-H PCI ID to the driver list of supported devices. Signed-off-by: Mika Westerberg Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20200624192103.78770-1-mika.westerberg@linux.intel.com --- drivers/mtd/spi-nor/controllers/intel-spi-pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c index c19f1035cc02f..c72aa1ab71adb 100644 --- a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c +++ b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c @@ -70,6 +70,7 @@ static const struct pci_device_id intel_spi_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x1bca), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x43a4), (unsigned long)&cnl_info }, { PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0xa0a4), (unsigned long)&bxt_info }, -- GitLab From 169efc3bf4dde79a8e15d71f45f1150bec46b663 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 4 Jun 2020 12:28:07 +0300 Subject: [PATCH 0173/1754] =?UTF-8?q?pinctrl:=20merrifield:=20Add=20I?= =?UTF-8?q?=C2=B2S=20bus=202=20pins=20to=20groups=20and=20functions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is useful to control I²S bus 2 pins if we would like to connect an audio codec. Reported-by: mouse Reported-by: Pierre-Louis Bossart Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-merrifield.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c index 2c213714df30d..e4ff8da1b8945 100644 --- a/drivers/pinctrl/intel/pinctrl-merrifield.c +++ b/drivers/pinctrl/intel/pinctrl-merrifield.c @@ -340,6 +340,7 @@ static const struct pinctrl_pin_desc mrfld_pins[] = { }; static const unsigned int mrfld_sdio_pins[] = { 50, 51, 52, 53, 54, 55, 56 }; +static const unsigned int mrfld_i2s2_pins[] = { 75, 76, 77, 78 }; static const unsigned int mrfld_spi5_pins[] = { 90, 91, 92, 93, 94, 95, 96 }; static const unsigned int mrfld_uart0_pins[] = { 115, 116, 117, 118 }; static const unsigned int mrfld_uart1_pins[] = { 119, 120, 121, 122 }; @@ -351,6 +352,7 @@ static const unsigned int mrfld_pwm3_pins[] = { 133 }; static const struct intel_pingroup mrfld_groups[] = { PIN_GROUP("sdio_grp", mrfld_sdio_pins, 1), + PIN_GROUP("i2s2_grp", mrfld_i2s2_pins, 1), PIN_GROUP("spi5_grp", mrfld_spi5_pins, 1), PIN_GROUP("uart0_grp", mrfld_uart0_pins, 1), PIN_GROUP("uart1_grp", mrfld_uart1_pins, 1), @@ -362,6 +364,7 @@ static const struct intel_pingroup mrfld_groups[] = { }; static const char * const mrfld_sdio_groups[] = { "sdio_grp" }; +static const char * const mrfld_i2s2_groups[] = { "i2s2_grp" }; static const char * const mrfld_spi5_groups[] = { "spi5_grp" }; static const char * const mrfld_uart0_groups[] = { "uart0_grp" }; static const char * const mrfld_uart1_groups[] = { "uart1_grp" }; @@ -373,6 +376,7 @@ static const char * const mrfld_pwm3_groups[] = { "pwm3_grp" }; static const struct intel_function mrfld_functions[] = { FUNCTION("sdio", mrfld_sdio_groups), + FUNCTION("i2s2", mrfld_i2s2_groups), FUNCTION("spi5", mrfld_spi5_groups), FUNCTION("uart0", mrfld_uart0_groups), FUNCTION("uart1", mrfld_uart1_groups), -- GitLab From 653d96455e1e30811f4b9ec44d3b9df9bd7a55a3 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 25 Jun 2020 16:20:53 +0300 Subject: [PATCH 0174/1754] pinctrl: tigerlake: Add support for Tiger Lake-H Intel Tiger Lake-H has different pin layout than the -LP variant so add support for this to the existing Tiger Lake driver. Signed-off-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-tigerlake.c | 358 ++++++++++++++++++++++ 1 file changed, 358 insertions(+) diff --git a/drivers/pinctrl/intel/pinctrl-tigerlake.c b/drivers/pinctrl/intel/pinctrl-tigerlake.c index bcfd7548e2828..8c162dd5f5a10 100644 --- a/drivers/pinctrl/intel/pinctrl-tigerlake.c +++ b/drivers/pinctrl/intel/pinctrl-tigerlake.c @@ -380,8 +380,366 @@ static const struct intel_pinctrl_soc_data tgllp_soc_data = { .ncommunities = ARRAY_SIZE(tgllp_communities), }; +/* Tiger Lake-H */ +static const struct pinctrl_pin_desc tglh_pins[] = { + /* GPP_A */ + PINCTRL_PIN(0, "SPI0_IO_2"), + PINCTRL_PIN(1, "SPI0_IO_3"), + PINCTRL_PIN(2, "SPI0_MOSI_IO_0"), + PINCTRL_PIN(3, "SPI0_MISO_IO_1"), + PINCTRL_PIN(4, "SPI0_TPM_CSB"), + PINCTRL_PIN(5, "SPI0_FLASH_0_CSB"), + PINCTRL_PIN(6, "SPI0_FLASH_1_CSB"), + PINCTRL_PIN(7, "SPI0_CLK"), + PINCTRL_PIN(8, "ESPI_IO_0"), + PINCTRL_PIN(9, "ESPI_IO_1"), + PINCTRL_PIN(10, "ESPI_IO_2"), + PINCTRL_PIN(11, "ESPI_IO_3"), + PINCTRL_PIN(12, "ESPI_CS0B"), + PINCTRL_PIN(13, "ESPI_CLK"), + PINCTRL_PIN(14, "ESPI_RESETB"), + PINCTRL_PIN(15, "ESPI_CS1B"), + PINCTRL_PIN(16, "ESPI_CS2B"), + PINCTRL_PIN(17, "ESPI_CS3B"), + PINCTRL_PIN(18, "ESPI_ALERT0B"), + PINCTRL_PIN(19, "ESPI_ALERT1B"), + PINCTRL_PIN(20, "ESPI_ALERT2B"), + PINCTRL_PIN(21, "ESPI_ALERT3B"), + PINCTRL_PIN(22, "GPPC_A_14"), + PINCTRL_PIN(23, "SPI0_CLK_LOOPBK"), + PINCTRL_PIN(24, "ESPI_CLK_LOOPBK"), + /* GPP_R */ + PINCTRL_PIN(25, "HDA_BCLK"), + PINCTRL_PIN(26, "HDA_SYNC"), + PINCTRL_PIN(27, "HDA_SDO"), + PINCTRL_PIN(28, "HDA_SDI_0"), + PINCTRL_PIN(29, "HDA_RSTB"), + PINCTRL_PIN(30, "HDA_SDI_1"), + PINCTRL_PIN(31, "GPP_R_6"), + PINCTRL_PIN(32, "GPP_R_7"), + PINCTRL_PIN(33, "GPP_R_8"), + PINCTRL_PIN(34, "PCIE_LNK_DOWN"), + PINCTRL_PIN(35, "ISH_UART0_RTSB"), + PINCTRL_PIN(36, "SX_EXIT_HOLDOFFB"), + PINCTRL_PIN(37, "CLKOUT_48"), + PINCTRL_PIN(38, "ISH_GP_7"), + PINCTRL_PIN(39, "ISH_GP_0"), + PINCTRL_PIN(40, "ISH_GP_1"), + PINCTRL_PIN(41, "ISH_GP_2"), + PINCTRL_PIN(42, "ISH_GP_3"), + PINCTRL_PIN(43, "ISH_GP_4"), + PINCTRL_PIN(44, "ISH_GP_5"), + /* GPP_B */ + PINCTRL_PIN(45, "GSPI0_CS1B"), + PINCTRL_PIN(46, "GSPI1_CS1B"), + PINCTRL_PIN(47, "VRALERTB"), + PINCTRL_PIN(48, "CPU_GP_2"), + PINCTRL_PIN(49, "CPU_GP_3"), + PINCTRL_PIN(50, "SRCCLKREQB_0"), + PINCTRL_PIN(51, "SRCCLKREQB_1"), + PINCTRL_PIN(52, "SRCCLKREQB_2"), + PINCTRL_PIN(53, "SRCCLKREQB_3"), + PINCTRL_PIN(54, "SRCCLKREQB_4"), + PINCTRL_PIN(55, "SRCCLKREQB_5"), + PINCTRL_PIN(56, "I2S_MCLK"), + PINCTRL_PIN(57, "SLP_S0B"), + PINCTRL_PIN(58, "PLTRSTB"), + PINCTRL_PIN(59, "SPKR"), + PINCTRL_PIN(60, "GSPI0_CS0B"), + PINCTRL_PIN(61, "GSPI0_CLK"), + PINCTRL_PIN(62, "GSPI0_MISO"), + PINCTRL_PIN(63, "GSPI0_MOSI"), + PINCTRL_PIN(64, "GSPI1_CS0B"), + PINCTRL_PIN(65, "GSPI1_CLK"), + PINCTRL_PIN(66, "GSPI1_MISO"), + PINCTRL_PIN(67, "GSPI1_MOSI"), + PINCTRL_PIN(68, "SML1ALERTB"), + PINCTRL_PIN(69, "GSPI0_CLK_LOOPBK"), + PINCTRL_PIN(70, "GSPI1_CLK_LOOPBK"), + /* vGPIO_0 */ + PINCTRL_PIN(71, "ESPI_USB_OCB_0"), + PINCTRL_PIN(72, "ESPI_USB_OCB_1"), + PINCTRL_PIN(73, "ESPI_USB_OCB_2"), + PINCTRL_PIN(74, "ESPI_USB_OCB_3"), + PINCTRL_PIN(75, "USB_CPU_OCB_0"), + PINCTRL_PIN(76, "USB_CPU_OCB_1"), + PINCTRL_PIN(77, "USB_CPU_OCB_2"), + PINCTRL_PIN(78, "USB_CPU_OCB_3"), + /* GPP_D */ + PINCTRL_PIN(79, "SPI1_CSB"), + PINCTRL_PIN(80, "SPI1_CLK"), + PINCTRL_PIN(81, "SPI1_MISO_IO_1"), + PINCTRL_PIN(82, "SPI1_MOSI_IO_0"), + PINCTRL_PIN(83, "SML1CLK"), + PINCTRL_PIN(84, "I2S2_SFRM"), + PINCTRL_PIN(85, "I2S2_TXD"), + PINCTRL_PIN(86, "I2S2_RXD"), + PINCTRL_PIN(87, "I2S2_SCLK"), + PINCTRL_PIN(88, "SML0CLK"), + PINCTRL_PIN(89, "SML0DATA"), + PINCTRL_PIN(90, "GPP_D_11"), + PINCTRL_PIN(91, "ISH_UART0_CTSB"), + PINCTRL_PIN(92, "SPI1_IO_2"), + PINCTRL_PIN(93, "SPI1_IO_3"), + PINCTRL_PIN(94, "SML1DATA"), + PINCTRL_PIN(95, "GSPI3_CS0B"), + PINCTRL_PIN(96, "GSPI3_CLK"), + PINCTRL_PIN(97, "GSPI3_MISO"), + PINCTRL_PIN(98, "GSPI3_MOSI"), + PINCTRL_PIN(99, "UART3_RXD"), + PINCTRL_PIN(100, "UART3_TXD"), + PINCTRL_PIN(101, "UART3_RTSB"), + PINCTRL_PIN(102, "UART3_CTSB"), + PINCTRL_PIN(103, "SPI1_CLK_LOOPBK"), + PINCTRL_PIN(104, "GSPI3_CLK_LOOPBK"), + /* GPP_C */ + PINCTRL_PIN(105, "SMBCLK"), + PINCTRL_PIN(106, "SMBDATA"), + PINCTRL_PIN(107, "SMBALERTB"), + PINCTRL_PIN(108, "ISH_UART0_RXD"), + PINCTRL_PIN(109, "ISH_UART0_TXD"), + PINCTRL_PIN(110, "SML0ALERTB"), + PINCTRL_PIN(111, "ISH_I2C2_SDA"), + PINCTRL_PIN(112, "ISH_I2C2_SCL"), + PINCTRL_PIN(113, "UART0_RXD"), + PINCTRL_PIN(114, "UART0_TXD"), + PINCTRL_PIN(115, "UART0_RTSB"), + PINCTRL_PIN(116, "UART0_CTSB"), + PINCTRL_PIN(117, "UART1_RXD"), + PINCTRL_PIN(118, "UART1_TXD"), + PINCTRL_PIN(119, "UART1_RTSB"), + PINCTRL_PIN(120, "UART1_CTSB"), + PINCTRL_PIN(121, "I2C0_SDA"), + PINCTRL_PIN(122, "I2C0_SCL"), + PINCTRL_PIN(123, "I2C1_SDA"), + PINCTRL_PIN(124, "I2C1_SCL"), + PINCTRL_PIN(125, "UART2_RXD"), + PINCTRL_PIN(126, "UART2_TXD"), + PINCTRL_PIN(127, "UART2_RTSB"), + PINCTRL_PIN(128, "UART2_CTSB"), + /* GPP_S */ + PINCTRL_PIN(129, "SNDW1_CLK"), + PINCTRL_PIN(130, "SNDW1_DATA"), + PINCTRL_PIN(131, "SNDW2_CLK"), + PINCTRL_PIN(132, "SNDW2_DATA"), + PINCTRL_PIN(133, "SNDW3_CLK"), + PINCTRL_PIN(134, "SNDW3_DATA"), + PINCTRL_PIN(135, "SNDW4_CLK"), + PINCTRL_PIN(136, "SNDW4_DATA"), + /* GPP_G */ + PINCTRL_PIN(137, "DDPA_CTRLCLK"), + PINCTRL_PIN(138, "DDPA_CTRLDATA"), + PINCTRL_PIN(139, "DNX_FORCE_RELOAD"), + PINCTRL_PIN(140, "GMII_MDC_0"), + PINCTRL_PIN(141, "GMII_MDIO_0"), + PINCTRL_PIN(142, "SLP_DRAMB"), + PINCTRL_PIN(143, "GPPC_G_6"), + PINCTRL_PIN(144, "GPPC_G_7"), + PINCTRL_PIN(145, "ISH_SPI_CSB"), + PINCTRL_PIN(146, "ISH_SPI_CLK"), + PINCTRL_PIN(147, "ISH_SPI_MISO"), + PINCTRL_PIN(148, "ISH_SPI_MOSI"), + PINCTRL_PIN(149, "DDP1_CTRLCLK"), + PINCTRL_PIN(150, "DDP1_CTRLDATA"), + PINCTRL_PIN(151, "DDP2_CTRLCLK"), + PINCTRL_PIN(152, "DDP2_CTRLDATA"), + PINCTRL_PIN(153, "GSPI2_CLK_LOOPBK"), + /* vGPIO */ + PINCTRL_PIN(154, "CNV_BTEN"), + PINCTRL_PIN(155, "CNV_BT_HOST_WAKEB"), + PINCTRL_PIN(156, "CNV_BT_IF_SELECT"), + PINCTRL_PIN(157, "vCNV_BT_UART_TXD"), + PINCTRL_PIN(158, "vCNV_BT_UART_RXD"), + PINCTRL_PIN(159, "vCNV_BT_UART_CTS_B"), + PINCTRL_PIN(160, "vCNV_BT_UART_RTS_B"), + PINCTRL_PIN(161, "vCNV_MFUART1_TXD"), + PINCTRL_PIN(162, "vCNV_MFUART1_RXD"), + PINCTRL_PIN(163, "vCNV_MFUART1_CTS_B"), + PINCTRL_PIN(164, "vCNV_MFUART1_RTS_B"), + PINCTRL_PIN(165, "vUART0_TXD"), + PINCTRL_PIN(166, "vUART0_RXD"), + PINCTRL_PIN(167, "vUART0_CTS_B"), + PINCTRL_PIN(168, "vUART0_RTS_B"), + PINCTRL_PIN(169, "vISH_UART0_TXD"), + PINCTRL_PIN(170, "vISH_UART0_RXD"), + PINCTRL_PIN(171, "vISH_UART0_CTS_B"), + PINCTRL_PIN(172, "vISH_UART0_RTS_B"), + PINCTRL_PIN(173, "vCNV_BT_I2S_BCLK"), + PINCTRL_PIN(174, "vCNV_BT_I2S_WS_SYNC"), + PINCTRL_PIN(175, "vCNV_BT_I2S_SDO"), + PINCTRL_PIN(176, "vCNV_BT_I2S_SDI"), + PINCTRL_PIN(177, "vI2S2_SCLK"), + PINCTRL_PIN(178, "vI2S2_SFRM"), + PINCTRL_PIN(179, "vI2S2_TXD"), + PINCTRL_PIN(180, "vI2S2_RXD"), + /* GPP_E */ + PINCTRL_PIN(181, "SATAXPCIE_0"), + PINCTRL_PIN(182, "SATAXPCIE_1"), + PINCTRL_PIN(183, "SATAXPCIE_2"), + PINCTRL_PIN(184, "CPU_GP_0"), + PINCTRL_PIN(185, "SATA_DEVSLP_0"), + PINCTRL_PIN(186, "SATA_DEVSLP_1"), + PINCTRL_PIN(187, "SATA_DEVSLP_2"), + PINCTRL_PIN(188, "CPU_GP_1"), + PINCTRL_PIN(189, "SATA_LEDB"), + PINCTRL_PIN(190, "USB2_OCB_0"), + PINCTRL_PIN(191, "USB2_OCB_1"), + PINCTRL_PIN(192, "USB2_OCB_2"), + PINCTRL_PIN(193, "USB2_OCB_3"), + /* GPP_F */ + PINCTRL_PIN(194, "SATAXPCIE_3"), + PINCTRL_PIN(195, "SATAXPCIE_4"), + PINCTRL_PIN(196, "SATAXPCIE_5"), + PINCTRL_PIN(197, "SATAXPCIE_6"), + PINCTRL_PIN(198, "SATAXPCIE_7"), + PINCTRL_PIN(199, "SATA_DEVSLP_3"), + PINCTRL_PIN(200, "SATA_DEVSLP_4"), + PINCTRL_PIN(201, "SATA_DEVSLP_5"), + PINCTRL_PIN(202, "SATA_DEVSLP_6"), + PINCTRL_PIN(203, "SATA_DEVSLP_7"), + PINCTRL_PIN(204, "SATA_SCLOCK"), + PINCTRL_PIN(205, "SATA_SLOAD"), + PINCTRL_PIN(206, "SATA_SDATAOUT1"), + PINCTRL_PIN(207, "SATA_SDATAOUT0"), + PINCTRL_PIN(208, "PS_ONB"), + PINCTRL_PIN(209, "M2_SKT2_CFG_0"), + PINCTRL_PIN(210, "M2_SKT2_CFG_1"), + PINCTRL_PIN(211, "M2_SKT2_CFG_2"), + PINCTRL_PIN(212, "M2_SKT2_CFG_3"), + PINCTRL_PIN(213, "L_VDDEN"), + PINCTRL_PIN(214, "L_BKLTEN"), + PINCTRL_PIN(215, "L_BKLTCTL"), + PINCTRL_PIN(216, "VNN_CTRL"), + PINCTRL_PIN(217, "GPP_F_23"), + /* GPP_H */ + PINCTRL_PIN(218, "SRCCLKREQB_6"), + PINCTRL_PIN(219, "SRCCLKREQB_7"), + PINCTRL_PIN(220, "SRCCLKREQB_8"), + PINCTRL_PIN(221, "SRCCLKREQB_9"), + PINCTRL_PIN(222, "SRCCLKREQB_10"), + PINCTRL_PIN(223, "SRCCLKREQB_11"), + PINCTRL_PIN(224, "SRCCLKREQB_12"), + PINCTRL_PIN(225, "SRCCLKREQB_13"), + PINCTRL_PIN(226, "SRCCLKREQB_14"), + PINCTRL_PIN(227, "SRCCLKREQB_15"), + PINCTRL_PIN(228, "SML2CLK"), + PINCTRL_PIN(229, "SML2DATA"), + PINCTRL_PIN(230, "SML2ALERTB"), + PINCTRL_PIN(231, "SML3CLK"), + PINCTRL_PIN(232, "SML3DATA"), + PINCTRL_PIN(233, "SML3ALERTB"), + PINCTRL_PIN(234, "SML4CLK"), + PINCTRL_PIN(235, "SML4DATA"), + PINCTRL_PIN(236, "SML4ALERTB"), + PINCTRL_PIN(237, "ISH_I2C0_SDA"), + PINCTRL_PIN(238, "ISH_I2C0_SCL"), + PINCTRL_PIN(239, "ISH_I2C1_SDA"), + PINCTRL_PIN(240, "ISH_I2C1_SCL"), + PINCTRL_PIN(241, "TIME_SYNC_0"), + /* GPP_J */ + PINCTRL_PIN(242, "CNV_PA_BLANKING"), + PINCTRL_PIN(243, "CPU_C10_GATEB"), + PINCTRL_PIN(244, "CNV_BRI_DT"), + PINCTRL_PIN(245, "CNV_BRI_RSP"), + PINCTRL_PIN(246, "CNV_RGI_DT"), + PINCTRL_PIN(247, "CNV_RGI_RSP"), + PINCTRL_PIN(248, "CNV_MFUART2_RXD"), + PINCTRL_PIN(249, "CNV_MFUART2_TXD"), + PINCTRL_PIN(250, "GPP_J_8"), + PINCTRL_PIN(251, "GPP_J_9"), + /* GPP_K */ + PINCTRL_PIN(252, "GSXDOUT"), + PINCTRL_PIN(253, "GSXSLOAD"), + PINCTRL_PIN(254, "GSXDIN"), + PINCTRL_PIN(255, "GSXSRESETB"), + PINCTRL_PIN(256, "GSXCLK"), + PINCTRL_PIN(257, "ADR_COMPLETE"), + PINCTRL_PIN(258, "DDSP_HPD_A"), + PINCTRL_PIN(259, "DDSP_HPD_B"), + PINCTRL_PIN(260, "CORE_VID_0"), + PINCTRL_PIN(261, "CORE_VID_1"), + PINCTRL_PIN(262, "DDSP_HPD_C"), + PINCTRL_PIN(263, "GPP_K_11"), + PINCTRL_PIN(264, "SYS_PWROK"), + PINCTRL_PIN(265, "SYS_RESETB"), + PINCTRL_PIN(266, "MLK_RSTB"), + /* GPP_I */ + PINCTRL_PIN(267, "PMCALERTB"), + PINCTRL_PIN(268, "DDSP_HPD_1"), + PINCTRL_PIN(269, "DDSP_HPD_2"), + PINCTRL_PIN(270, "DDSP_HPD_3"), + PINCTRL_PIN(271, "DDSP_HPD_4"), + PINCTRL_PIN(272, "DDPB_CTRLCLK"), + PINCTRL_PIN(273, "DDPB_CTRLDATA"), + PINCTRL_PIN(274, "DDPC_CTRLCLK"), + PINCTRL_PIN(275, "DDPC_CTRLDATA"), + PINCTRL_PIN(276, "FUSA_DIAGTEST_EN"), + PINCTRL_PIN(277, "FUSA_DIAGTEST_MODE"), + PINCTRL_PIN(278, "USB2_OCB_4"), + PINCTRL_PIN(279, "USB2_OCB_5"), + PINCTRL_PIN(280, "USB2_OCB_6"), + PINCTRL_PIN(281, "USB2_OCB_7"), + /* JTAG */ + PINCTRL_PIN(282, "JTAG_TDO"), + PINCTRL_PIN(283, "JTAGX"), + PINCTRL_PIN(284, "PRDYB"), + PINCTRL_PIN(285, "PREQB"), + PINCTRL_PIN(286, "JTAG_TDI"), + PINCTRL_PIN(287, "JTAG_TMS"), + PINCTRL_PIN(288, "JTAG_TCK"), + PINCTRL_PIN(289, "DBG_PMODE"), + PINCTRL_PIN(290, "CPU_TRSTB"), +}; + +static const struct intel_padgroup tglh_community0_gpps[] = { + TGL_GPP(0, 0, 24, 0), /* GPP_A */ + TGL_GPP(1, 25, 44, 128), /* GPP_R */ + TGL_GPP(2, 45, 70, 32), /* GPP_B */ + TGL_GPP(3, 71, 78, INTEL_GPIO_BASE_NOMAP), /* vGPIO_0 */ +}; + +static const struct intel_padgroup tglh_community1_gpps[] = { + TGL_GPP(0, 79, 104, 96), /* GPP_D */ + TGL_GPP(1, 105, 128, 64), /* GPP_C */ + TGL_GPP(2, 129, 136, 160), /* GPP_S */ + TGL_GPP(3, 137, 153, 192), /* GPP_G */ + TGL_GPP(4, 154, 180, 224), /* vGPIO */ +}; + +static const struct intel_padgroup tglh_community3_gpps[] = { + TGL_GPP(0, 181, 193, 256), /* GPP_E */ + TGL_GPP(1, 194, 217, 288), /* GPP_F */ +}; + +static const struct intel_padgroup tglh_community4_gpps[] = { + TGL_GPP(0, 218, 241, 320), /* GPP_H */ + TGL_GPP(1, 242, 251, 384), /* GPP_J */ + TGL_GPP(2, 252, 266, 352), /* GPP_K */ +}; + +static const struct intel_padgroup tglh_community5_gpps[] = { + TGL_GPP(0, 267, 281, 416), /* GPP_I */ + TGL_GPP(1, 282, 290, INTEL_GPIO_BASE_NOMAP), /* JTAG */ +}; + +static const struct intel_community tglh_communities[] = { + TGL_COMMUNITY(0, 0, 78, tglh_community0_gpps), + TGL_COMMUNITY(1, 79, 180, tglh_community1_gpps), + TGL_COMMUNITY(2, 181, 217, tglh_community3_gpps), + TGL_COMMUNITY(3, 218, 266, tglh_community4_gpps), + TGL_COMMUNITY(4, 267, 290, tglh_community5_gpps), +}; + +static const struct intel_pinctrl_soc_data tglh_soc_data = { + .pins = tglh_pins, + .npins = ARRAY_SIZE(tglh_pins), + .communities = tglh_communities, + .ncommunities = ARRAY_SIZE(tglh_communities), +}; + static const struct acpi_device_id tgl_pinctrl_acpi_match[] = { { "INT34C5", (kernel_ulong_t)&tgllp_soc_data }, + { "INT34C6", (kernel_ulong_t)&tglh_soc_data }, { } }; MODULE_DEVICE_TABLE(acpi, tgl_pinctrl_acpi_match); -- GitLab From bb7fcad48d3804d814b97c785514e2d1657e157f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 25 Jun 2020 16:10:36 +0300 Subject: [PATCH 0175/1754] mfd: intel-lpss: Add Intel Tiger Lake PCH-H PCI IDs Intel Tiger Lake PCH-H has the same LPSS than Intel Broxton. Add the new IDs to the list of supported devices. Signed-off-by: Andy Shevchenko Signed-off-by: Lee Jones --- drivers/mfd/intel-lpss-pci.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index 17bcadc00a11c..9a58032f818ae 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -233,6 +233,22 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x34ea), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x34eb), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x34fb), (kernel_ulong_t)&spt_info }, + /* TGL-H */ + { PCI_VDEVICE(INTEL, 0x43a7), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x43a8), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x43a9), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x43aa), (kernel_ulong_t)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x43ab), (kernel_ulong_t)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x43ad), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x43ae), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x43d8), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x43da), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x43e8), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x43e9), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x43ea), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x43eb), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x43fb), (kernel_ulong_t)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x43fd), (kernel_ulong_t)&bxt_info }, /* EHL */ { PCI_VDEVICE(INTEL, 0x4b28), (kernel_ulong_t)&bxt_uart_info }, { PCI_VDEVICE(INTEL, 0x4b29), (kernel_ulong_t)&bxt_uart_info }, -- GitLab From f375a038daf655933dae0c54542a071388c02880 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Thu, 18 Jun 2020 10:33:31 +0300 Subject: [PATCH 0176/1754] MAINTAINERS: Add entry for ROHM Power Management ICs Add entry for maintaining power management IC drivers for ROHM BD71837, BD71847, BD71850, BD71828, BD71878, BD70528 and BD99954. Signed-off-by: Matti Vaittinen Acked-by: Sebastian Reichel Acked-by: Guenter Roeck Acked-by: Stephen Boyd Reviewed-by: Linus Walleij Signed-off-by: Lee Jones --- MAINTAINERS | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 02d9827a4f810..423f7107ace40 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14713,6 +14713,13 @@ L: linux-serial@vger.kernel.org S: Odd Fixes F: drivers/tty/serial/rp2.* +ROHM BD99954 CHARGER IC +R: Matti Vaittinen +L: linux-power@fi.rohmeurope.com +S: Supported +F: drivers/power/supply/bd99954-charger.c +F: drivers/power/supply/bd99954-charger.h + ROHM BH1750 AMBIENT LIGHT SENSOR DRIVER M: Tomasz Duszynski S: Maintained @@ -14730,6 +14737,31 @@ F: drivers/mfd/bd9571mwv.c F: drivers/regulator/bd9571mwv-regulator.c F: include/linux/mfd/bd9571mwv.h +ROHM POWER MANAGEMENT IC DEVICE DRIVERS +R: Matti Vaittinen +L: linux-power@fi.rohmeurope.com +S: Supported +F: Documentation/devicetree/bindings/mfd/rohm,bd70528-pmic.txt +F: Documentation/devicetree/bindings/regulator/rohm,bd70528-regulator.txt +F: drivers/clk/clk-bd718x7.c +F: drivers/gpio/gpio-bd70528.c +F: drivers/gpio/gpio-bd71828.c +F: drivers/mfd/rohm-bd70528.c +F: drivers/mfd/rohm-bd71828.c +F: drivers/mfd/rohm-bd718x7.c +F: drivers/power/supply/bd70528-charger.c +F: drivers/regulator/bd70528-regulator.c +F: drivers/regulator/bd71828-regulator.c +F: drivers/regulator/bd718x7-regulator.c +F: drivers/regulator/rohm-regulator.c +F: drivers/rtc/rtc-bd70528.c +F: drivers/watchdog/bd70528_wdt.c +F: include/linux/mfd/rohm-bd70528.h +F: include/linux/mfd/rohm-bd71828.h +F: include/linux/mfd/rohm-bd718x7.h +F: include/linux/mfd/rohm-generic.h +F: include/linux/mfd/rohm-shared.h + ROSE NETWORK LAYER M: Ralf Baechle L: linux-hams@vger.kernel.org -- GitLab From d3e3d2be688b4b5864538de61e750721a311e4fc Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Tue, 2 Jun 2020 14:08:18 +0100 Subject: [PATCH 0177/1754] iommu/iova: Don't BUG on invalid PFNs Unlike the other instances which represent a complete loss of consistency within the rcache mechanism itself, or a fundamental and obvious misconfiguration by an IOMMU driver, the BUG_ON() in iova_magazine_free_pfns() can be provoked at more or less any time in a "spooky action-at-a-distance" manner by any old device driver passing nonsense to dma_unmap_*() which then propagates through to queue_iova(). Not only is this well outside the IOVA layer's control, it's also nowhere near fatal enough to justify panicking anyway - all that really achieves is to make debugging the offending driver more difficult. Let's simply WARN and otherwise ignore bogus PFNs. Reported-by: Prakash Gupta Signed-off-by: Robin Murphy Reviewed-by: Prakash Gupta Link: https://lore.kernel.org/r/acbd2d092b42738a03a21b417ce64e27f8c91c86.1591103298.git.robin.murphy@arm.com Signed-off-by: Joerg Roedel --- drivers/iommu/iova.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c index 49fc01f2a28d4..45a251da54537 100644 --- a/drivers/iommu/iova.c +++ b/drivers/iommu/iova.c @@ -811,7 +811,9 @@ iova_magazine_free_pfns(struct iova_magazine *mag, struct iova_domain *iovad) for (i = 0 ; i < mag->size; ++i) { struct iova *iova = private_find_iova(iovad, mag->pfns[i]); - BUG_ON(!iova); + if (WARN_ON(!iova)) + continue; + private_free_iova(iovad, iova); } -- GitLab From f5e383ac8b58f421ac0a005f6df4f2e9eefeb93f Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Thu, 4 Jun 2020 15:37:09 +0300 Subject: [PATCH 0178/1754] iommu/pamu: Use kzfree() in fsl_pamu_probe() Use kzfree() instead of opencoded memset with 0 followed by kfree(). Null check is not required since kzfree() checks for NULL internally. Signed-off-by: Denis Efremov Link: https://lore.kernel.org/r/20200604123709.96561-1-efremov@linux.com Signed-off-by: Joerg Roedel --- drivers/iommu/fsl_pamu.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c index cde281b97afa8..099a11a35fb9c 100644 --- a/drivers/iommu/fsl_pamu.c +++ b/drivers/iommu/fsl_pamu.c @@ -1174,10 +1174,7 @@ static int fsl_pamu_probe(struct platform_device *pdev) if (irq != NO_IRQ) free_irq(irq, data); - if (data) { - memset(data, 0, sizeof(struct pamu_isr_data)); - kfree(data); - } + kzfree(data); if (pamu_regs) iounmap(pamu_regs); -- GitLab From e725a00a8f2e1ae866c29f956d637a889f561882 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 6 Jun 2020 12:16:17 -0700 Subject: [PATCH 0179/1754] iommu/qcom: Change CONFIG_BIG_ENDIAN to CONFIG_CPU_BIG_ENDIAN CONFIG_BIG_ENDIAN does not exist as a Kconfig symbol. Signed-off-by: Joe Perches Reviewed-by: Rob Clark Link: https://lore.kernel.org/r/5a663096b489b86472fe3bfbd5138c411d669bad.camel@perches.com Signed-off-by: Joerg Roedel --- drivers/iommu/qcom_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index 801768cf86c61..cca39b2091586 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -310,7 +310,7 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, ARM_SMMU_SCTLR_M | ARM_SMMU_SCTLR_S1_ASIDPNE | ARM_SMMU_SCTLR_CFCFG; - if (IS_ENABLED(CONFIG_BIG_ENDIAN)) + if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) reg |= ARM_SMMU_SCTLR_E; iommu_writel(ctx, ARM_SMMU_CB_SCTLR, reg); -- GitLab From 215c224f4dfa89f1d97500f419092c0110da3c2e Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Thu, 11 Jun 2020 20:10:29 +0900 Subject: [PATCH 0180/1754] dt-bindings: iommu: renesas,ipmmu-vmsa: add r8a77961 support Add support for r8a77961 (R-Car M3-W+). Signed-off-by: Yoshihiro Shimoda Reviewed-by: Geert Uytterhoeven Acked-by: Rob Herring Link: https://lore.kernel.org/r/1591873830-10128-2-git-send-email-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Joerg Roedel --- Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml index 39675cf4ed71c..e9d28a4060fa3 100644 --- a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml +++ b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml @@ -35,6 +35,7 @@ properties: - renesas,ipmmu-r8a774c0 # RZ/G2E - renesas,ipmmu-r8a7795 # R-Car H3 - renesas,ipmmu-r8a7796 # R-Car M3-W + - renesas,ipmmu-r8a77961 # R-Car M3-W+ - renesas,ipmmu-r8a77965 # R-Car M3-N - renesas,ipmmu-r8a77970 # R-Car V3M - renesas,ipmmu-r8a77980 # R-Car V3H -- GitLab From 17fe16181639801bfeba647a1e452a75efe651b4 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Thu, 11 Jun 2020 20:10:30 +0900 Subject: [PATCH 0181/1754] iommu/renesas: Add support for r8a77961 Add support for r8a77961 (R-Car M3-W+). Signed-off-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/1591873830-10128-3-git-send-email-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Joerg Roedel --- drivers/iommu/ipmmu-vmsa.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 4c2972f3153b5..b57b1f213a486 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -3,7 +3,7 @@ * IOMMU API for Renesas VMSA-compatible IPMMU * Author: Laurent Pinchart * - * Copyright (C) 2014 Renesas Electronics Corporation + * Copyright (C) 2014-2020 Renesas Electronics Corporation */ #include @@ -753,6 +753,7 @@ static const struct soc_device_attribute soc_rcar_gen3_whitelist[] = { { .soc_id = "r8a774b1", }, { .soc_id = "r8a774c0", }, { .soc_id = "r8a7795", .revision = "ES3.*" }, + { .soc_id = "r8a77961", }, { .soc_id = "r8a77965", }, { .soc_id = "r8a77990", }, { .soc_id = "r8a77995", }, @@ -969,6 +970,9 @@ static const struct of_device_id ipmmu_of_ids[] = { }, { .compatible = "renesas,ipmmu-r8a7796", .data = &ipmmu_features_rcar_gen3, + }, { + .compatible = "renesas,ipmmu-r8a77961", + .data = &ipmmu_features_rcar_gen3, }, { .compatible = "renesas,ipmmu-r8a77965", .data = &ipmmu_features_rcar_gen3, -- GitLab From 3c5ca501b46b91e68b935b4bd752a0aba5232208 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 25 Jun 2020 19:02:41 +0200 Subject: [PATCH 0182/1754] platform/chrome: cros_ec_spi: Document missing function parameters Kerneldoc expects all kernel function members to be documented. Fixes the following W=1 level warnings: cros_ec_spi.c:153: warning: Function parameter or member 'ec_dev' not described in 'receive_n_bytes' cros_ec_spi.c:153: warning: Function parameter or member 'buf' not described in 'receive_n_bytes' cros_ec_spi.c:153: warning: Function parameter or member 'n' not described in 'receive_n_bytes' Signed-off-by: Enric Balletbo i Serra Reviewed-by: Gwendal Grignou --- drivers/platform/chrome/cros_ec_spi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c index debea5c4c8293..a74e91df264be 100644 --- a/drivers/platform/chrome/cros_ec_spi.c +++ b/drivers/platform/chrome/cros_ec_spi.c @@ -148,6 +148,10 @@ static int terminate_request(struct cros_ec_device *ec_dev) * receive_n_bytes - receive n bytes from the EC. * * Assumes buf is a pointer into the ec_dev->din buffer + * + * @ec_dev: ChromeOS EC device. + * @buf: Pointer to the buffer receiving the data. + * @n: Number of bytes received. */ static int receive_n_bytes(struct cros_ec_device *ec_dev, u8 *buf, int n) { -- GitLab From 9a876ba58d1e660e7957dd7afd1129b615eb1e04 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 25 Jun 2020 19:03:00 +0200 Subject: [PATCH 0183/1754] platform/chrome: cros_ec_rpmsg: Document missing struct parameters Kerneldoc expects all kernel structure member to be documented. Fixes the following W=1 level warnings: cros_ec_rpmsg.c:49: warning: Function parameter or member 'ept' not described in 'cros_ec_rpmsg' cros_ec_rpmsg.c:49: warning: Function parameter or member 'has_pending_host_event' not described in 'cros_ec_rpmsg' cros_ec_rpmsg.c:49: warning: Function parameter or member 'probe_done' not described in 'cros_ec_rpmsg' Signed-off-by: Enric Balletbo i Serra Reviewed-by: Gwendal Grignou --- drivers/platform/chrome/cros_ec_rpmsg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c b/drivers/platform/chrome/cros_ec_rpmsg.c index 7e8629e3db746..30d0ba3b8889c 100644 --- a/drivers/platform/chrome/cros_ec_rpmsg.c +++ b/drivers/platform/chrome/cros_ec_rpmsg.c @@ -38,6 +38,9 @@ struct cros_ec_rpmsg_response { * @rpdev: rpmsg device we are connected to * @xfer_ack: completion for host command transfer. * @host_event_work: Work struct for pending host event. + * @ept: The rpmsg endpoint of this channel. + * @has_pending_host_event: Boolean used to check if there is a pending event. + * @probe_done: Flag to indicate that probe is done. */ struct cros_ec_rpmsg { struct rpmsg_device *rpdev; -- GitLab From aaa3cbbac326c95308e315f1ab964a3369c4d07d Mon Sep 17 00:00:00 2001 From: Qiushi Wu Date: Fri, 22 May 2020 22:16:08 -0500 Subject: [PATCH 0184/1754] platform/chrome: cros_ec_ishtp: Fix a double-unlock issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In function cros_ec_ishtp_probe(), "up_write" is already called before function "cros_ec_dev_init". But "up_write" will be called again after the calling of the function "cros_ec_dev_init" failed. Thus add a call of the function “down_write” in this if branch for the completion of the exception handling. Fixes: 26a14267aff2 ("platform/chrome: Add ChromeOS EC ISHTP driver") Signed-off-by: Qiushi Wu Tested-by: Mathew King Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_ishtp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec_ishtp.c b/drivers/platform/chrome/cros_ec_ishtp.c index ed794a7ddba9b..81364029af367 100644 --- a/drivers/platform/chrome/cros_ec_ishtp.c +++ b/drivers/platform/chrome/cros_ec_ishtp.c @@ -681,8 +681,10 @@ static int cros_ec_ishtp_probe(struct ishtp_cl_device *cl_device) /* Register croc_ec_dev mfd */ rv = cros_ec_dev_init(client_data); - if (rv) + if (rv) { + down_write(&init_lock); goto end_cros_ec_dev_init_error; + } return 0; -- GitLab From 970471914c67b70df24def6b2a30cc42acbebded Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Tue, 16 Jun 2020 16:47:14 +0200 Subject: [PATCH 0185/1754] iommu: Allow page responses without PASID Some PCIe devices do not expect a PASID value in PRI Page Responses. If the "PRG Response PASID Required" bit in the PRI capability is zero, then the OS should not set the PASID field. Similarly on Arm SMMU, responses to stall events do not have a PASID. Currently iommu_page_response() systematically checks that the PASID in the page response corresponds to the one in the page request. This can't work with virtualization because a page response coming from a guest OS won't have a PASID if the passed-through device does not require one. Add a flag to page requests that declares whether the corresponding response needs to have a PASID. When this flag isn't set, allow page responses without PASID. Reported-by: Shameerali Kolothum Thodi Signed-off-by: Jean-Philippe Brucker Link: https://lore.kernel.org/r/20200616144712.748818-1-jean-philippe@linaro.org Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 23 +++++++++++++++++------ include/uapi/linux/iommu.h | 6 +++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index d43120eb1dc56..1ed1e14a1f0cf 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1185,11 +1185,12 @@ EXPORT_SYMBOL_GPL(iommu_report_device_fault); int iommu_page_response(struct device *dev, struct iommu_page_response *msg) { - bool pasid_valid; + bool needs_pasid; int ret = -EINVAL; struct iommu_fault_event *evt; struct iommu_fault_page_request *prm; struct dev_iommu *param = dev->iommu; + bool has_pasid = msg->flags & IOMMU_PAGE_RESP_PASID_VALID; struct iommu_domain *domain = iommu_get_domain_for_dev(dev); if (!domain || !domain->ops->page_response) @@ -1214,14 +1215,24 @@ int iommu_page_response(struct device *dev, */ list_for_each_entry(evt, ¶m->fault_param->faults, list) { prm = &evt->fault.prm; - pasid_valid = prm->flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID; + if (prm->grpid != msg->grpid) + continue; - if ((pasid_valid && prm->pasid != msg->pasid) || - prm->grpid != msg->grpid) + /* + * If the PASID is required, the corresponding request is + * matched using the group ID, the PASID valid bit and the PASID + * value. Otherwise only the group ID matches request and + * response. + */ + needs_pasid = prm->flags & IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID; + if (needs_pasid && (!has_pasid || msg->pasid != prm->pasid)) continue; - /* Sanitize the reply */ - msg->flags = pasid_valid ? IOMMU_PAGE_RESP_PASID_VALID : 0; + if (!needs_pasid && has_pasid) { + /* No big deal, just clear it. */ + msg->flags &= ~IOMMU_PAGE_RESP_PASID_VALID; + msg->pasid = 0; + } ret = domain->ops->page_response(dev, evt, msg); list_del(&evt->list); diff --git a/include/uapi/linux/iommu.h b/include/uapi/linux/iommu.h index e907b7091a463..c2b2caf9ed412 100644 --- a/include/uapi/linux/iommu.h +++ b/include/uapi/linux/iommu.h @@ -81,7 +81,10 @@ struct iommu_fault_unrecoverable { /** * struct iommu_fault_page_request - Page Request data * @flags: encodes whether the corresponding fields are valid and whether this - * is the last page in group (IOMMU_FAULT_PAGE_REQUEST_* values) + * is the last page in group (IOMMU_FAULT_PAGE_REQUEST_* values). + * When IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID is set, the page response + * must have the same PASID value as the page request. When it is clear, + * the page response should not have a PASID. * @pasid: Process Address Space ID * @grpid: Page Request Group Index * @perm: requested page permissions (IOMMU_FAULT_PERM_* values) @@ -92,6 +95,7 @@ struct iommu_fault_page_request { #define IOMMU_FAULT_PAGE_REQUEST_PASID_VALID (1 << 0) #define IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE (1 << 1) #define IOMMU_FAULT_PAGE_REQUEST_PRIV_DATA (1 << 2) +#define IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID (1 << 3) __u32 flags; __u32 pasid; __u32 grpid; -- GitLab From 9a295ff0ffc94e1be60d604fee0cce4fbb3b8964 Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Wed, 17 Jun 2020 00:04:20 +0200 Subject: [PATCH 0186/1754] iommu/amd: Print extended features in one line to fix divergent log levels Currently, Linux logs the two messages below. [ 0.979142] pci 0000:00:00.2: AMD-Vi: Extended features (0xf77ef22294ada): [ 0.979546] PPR NX GT IA GA PC GA_vAPIC The log level of these lines differs though. The first one has level *info*, while the second has level *warn*, which is confusing. $ dmesg -T --level=info | grep "Extended features" [Tue Jun 16 21:46:58 2020] pci 0000:00:00.2: AMD-Vi: Extended features (0xf77ef22294ada): $ dmesg -T --level=warn | grep "PPR" [Tue Jun 16 21:46:58 2020] PPR NX GT IA GA PC GA_vAPIC The problem is, that commit 3928aa3f57 ("iommu/amd: Detect and enable guest vAPIC support") introduced a newline, causing `pr_cont()`, used to print the features, to default back to the default log level. /** * pr_cont - Continues a previous log message in the same line. * @fmt: format string * @...: arguments for the format string * * This macro expands to a printk with KERN_CONT loglevel. It should only be * used when continuing a log message with no newline ('\n') enclosed. Otherwise * it defaults back to KERN_DEFAULT loglevel. */ #define pr_cont(fmt, ...) \ printk(KERN_CONT fmt, ##__VA_ARGS__) So, remove the line break, so only one line is logged. Fixes: 3928aa3f57 ("iommu/amd: Detect and enable guest vAPIC support") Signed-off-by: Paul Menzel Reviewed-by: Suravee Suthikulpanit Cc: Suravee Suthikulpanit Cc: iommu@lists.linux-foundation.org Link: https://lore.kernel.org/r/20200616220420.19466-1-pmenzel@molgen.mpg.de Signed-off-by: Joerg Roedel --- drivers/iommu/amd/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 6ebd4825e3206..232683ea10e0b 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -1842,7 +1842,7 @@ static void print_iommu_info(void) pci_info(pdev, "Found IOMMU cap 0x%hx\n", iommu->cap_ptr); if (iommu->cap & (1 << IOMMU_CAP_EFR)) { - pci_info(pdev, "Extended features (%#llx):\n", + pci_info(pdev, "Extended features (%#llx):", iommu->features); for (i = 0; i < ARRAY_SIZE(feat_str); ++i) { if (iommu_feature(iommu, (1ULL << i))) -- GitLab From 70fcd3592b05fde4d95938cd5a20e996b4ef4e15 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 26 Jun 2020 10:05:46 +0200 Subject: [PATCH 0187/1754] iommu/amd: Add helper functions to update domain->pt_root Do not call atomic64_set() directly to update the domain page-table root and use two new helper functions. This makes it easier to implement additional work necessary when the page-table is updated. Signed-off-by: Joerg Roedel Link: https://lore.kernel.org/r/20200626080547.24865-2-joro@8bytes.org --- drivers/iommu/amd/iommu.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index 74cca17571725..5286ddcfc2f9f 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -162,7 +162,18 @@ static void amd_iommu_domain_get_pgtable(struct protection_domain *domain, pgtable->mode = pt_root & 7; /* lowest 3 bits encode pgtable mode */ } -static u64 amd_iommu_domain_encode_pgtable(u64 *root, int mode) +static void amd_iommu_domain_set_pt_root(struct protection_domain *domain, u64 root) +{ + atomic64_set(&domain->pt_root, root); +} + +static void amd_iommu_domain_clr_pt_root(struct protection_domain *domain) +{ + amd_iommu_domain_set_pt_root(domain, 0); +} + +static void amd_iommu_domain_set_pgtable(struct protection_domain *domain, + u64 *root, int mode) { u64 pt_root; @@ -170,7 +181,7 @@ static u64 amd_iommu_domain_encode_pgtable(u64 *root, int mode) pt_root = mode & 7; pt_root |= (u64)root; - return pt_root; + amd_iommu_domain_set_pt_root(domain, pt_root); } static struct iommu_dev_data *alloc_dev_data(u16 devid) @@ -1410,7 +1421,7 @@ static bool increase_address_space(struct protection_domain *domain, struct domain_pgtable pgtable; unsigned long flags; bool ret = true; - u64 *pte, root; + u64 *pte; spin_lock_irqsave(&domain->lock, flags); @@ -1438,8 +1449,7 @@ static bool increase_address_space(struct protection_domain *domain, * Device Table needs to be updated and flushed before the new root can * be published. */ - root = amd_iommu_domain_encode_pgtable(pte, pgtable.mode); - atomic64_set(&domain->pt_root, root); + amd_iommu_domain_set_pgtable(domain, pte, pgtable.mode); ret = true; @@ -2319,7 +2329,7 @@ static void protection_domain_free(struct protection_domain *domain) domain_id_free(domain->id); amd_iommu_domain_get_pgtable(domain, &pgtable); - atomic64_set(&domain->pt_root, 0); + amd_iommu_domain_clr_pt_root(domain); free_pagetable(&pgtable); kfree(domain); @@ -2327,7 +2337,7 @@ static void protection_domain_free(struct protection_domain *domain) static int protection_domain_init(struct protection_domain *domain, int mode) { - u64 *pt_root = NULL, root; + u64 *pt_root = NULL; BUG_ON(mode < PAGE_MODE_NONE || mode > PAGE_MODE_6_LEVEL); @@ -2343,8 +2353,7 @@ static int protection_domain_init(struct protection_domain *domain, int mode) return -ENOMEM; } - root = amd_iommu_domain_encode_pgtable(pt_root, mode); - atomic64_set(&domain->pt_root, root); + amd_iommu_domain_set_pgtable(domain, pt_root, mode); return 0; } @@ -2713,8 +2722,8 @@ void amd_iommu_domain_direct_map(struct iommu_domain *dom) /* First save pgtable configuration*/ amd_iommu_domain_get_pgtable(domain, &pgtable); - /* Update data structure */ - atomic64_set(&domain->pt_root, 0); + /* Remove page-table from domain */ + amd_iommu_domain_clr_pt_root(domain); /* Make changes visible to IOMMUs */ update_domain(domain); -- GitLab From 0f45b04da18305726c18d4b6169c4083f301d91c Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:24 +0200 Subject: [PATCH 0188/1754] iommu/exynos: Use dev_iommu_priv_get/set() Remove the use of dev->archdata.iommu and use the private per-device pointer provided by IOMMU core code instead. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Acked-by: Marek Szyprowski Link: https://lore.kernel.org/r/20200625130836.1916-2-joro@8bytes.org --- drivers/iommu/exynos-iommu.c | 20 +++++++++---------- .../media/platform/s5p-mfc/s5p_mfc_iommu.h | 4 +++- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 60c8a56e4a3f8..6a9b67302369d 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -173,7 +173,7 @@ static u32 lv2ent_offset(sysmmu_iova_t iova) #define REG_V5_FAULT_AR_VA 0x070 #define REG_V5_FAULT_AW_VA 0x080 -#define has_sysmmu(dev) (dev->archdata.iommu != NULL) +#define has_sysmmu(dev) (dev_iommu_priv_get(dev) != NULL) static struct device *dma_dev; static struct kmem_cache *lv2table_kmem_cache; @@ -226,7 +226,7 @@ static const struct sysmmu_fault_info sysmmu_v5_faults[] = { }; /* - * This structure is attached to dev.archdata.iommu of the master device + * This structure is attached to dev->iommu->priv of the master device * on device add, contains a list of SYSMMU controllers defined by device tree, * which are bound to given master device. It is usually referenced by 'owner' * pointer. @@ -670,7 +670,7 @@ static int __maybe_unused exynos_sysmmu_suspend(struct device *dev) struct device *master = data->master; if (master) { - struct exynos_iommu_owner *owner = master->archdata.iommu; + struct exynos_iommu_owner *owner = dev_iommu_priv_get(master); mutex_lock(&owner->rpm_lock); if (data->domain) { @@ -688,7 +688,7 @@ static int __maybe_unused exynos_sysmmu_resume(struct device *dev) struct device *master = data->master; if (master) { - struct exynos_iommu_owner *owner = master->archdata.iommu; + struct exynos_iommu_owner *owner = dev_iommu_priv_get(master); mutex_lock(&owner->rpm_lock); if (data->domain) { @@ -837,8 +837,8 @@ static void exynos_iommu_domain_free(struct iommu_domain *iommu_domain) static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain, struct device *dev) { - struct exynos_iommu_owner *owner = dev->archdata.iommu; struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain); + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); phys_addr_t pagetable = virt_to_phys(domain->pgtable); struct sysmmu_drvdata *data, *next; unsigned long flags; @@ -875,8 +875,8 @@ static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain, static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain, struct device *dev) { - struct exynos_iommu_owner *owner = dev->archdata.iommu; struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain); + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); struct sysmmu_drvdata *data; phys_addr_t pagetable = virt_to_phys(domain->pgtable); unsigned long flags; @@ -1237,7 +1237,7 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *iommu_domain, static struct iommu_device *exynos_iommu_probe_device(struct device *dev) { - struct exynos_iommu_owner *owner = dev->archdata.iommu; + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); struct sysmmu_drvdata *data; if (!has_sysmmu(dev)) @@ -1263,7 +1263,7 @@ static struct iommu_device *exynos_iommu_probe_device(struct device *dev) static void exynos_iommu_release_device(struct device *dev) { - struct exynos_iommu_owner *owner = dev->archdata.iommu; + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); struct sysmmu_drvdata *data; if (!has_sysmmu(dev)) @@ -1287,8 +1287,8 @@ static void exynos_iommu_release_device(struct device *dev) static int exynos_iommu_of_xlate(struct device *dev, struct of_phandle_args *spec) { - struct exynos_iommu_owner *owner = dev->archdata.iommu; struct platform_device *sysmmu = of_find_device_by_node(spec->np); + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); struct sysmmu_drvdata *data, *entry; if (!sysmmu) @@ -1305,7 +1305,7 @@ static int exynos_iommu_of_xlate(struct device *dev, INIT_LIST_HEAD(&owner->controllers); mutex_init(&owner->rpm_lock); - dev->archdata.iommu = owner; + dev_iommu_priv_set(dev, owner); } list_for_each_entry(entry, &owner->controllers, owner_node) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h index 152a713fff78c..1a32266b7ddc2 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h @@ -9,9 +9,11 @@ #if defined(CONFIG_EXYNOS_IOMMU) +#include + static inline bool exynos_is_iommu_available(struct device *dev) { - return dev->archdata.iommu != NULL; + return dev_iommu_priv_get(dev) != NULL; } #else -- GitLab From 01b9d4e21148c89fdbab3d6b3705f9791314b631 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:25 +0200 Subject: [PATCH 0189/1754] iommu/vt-d: Use dev_iommu_priv_get/set() Remove the use of dev->archdata.iommu and use the private per-device pointer provided by IOMMU core code instead. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Reviewed-by: Lu Baolu Link: https://lore.kernel.org/r/20200625130836.1916-3-joro@8bytes.org --- .../gpu/drm/i915/selftests/mock_gem_device.c | 10 ++++++++-- drivers/iommu/intel/iommu.c | 18 +++++++++--------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 9b105b811f1f4..e08601905a64a 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -24,6 +24,7 @@ #include #include +#include #include @@ -118,6 +119,9 @@ struct drm_i915_private *mock_gem_device(void) { struct drm_i915_private *i915; struct pci_dev *pdev; +#if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU) + struct dev_iommu iommu; +#endif int err; pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); @@ -136,8 +140,10 @@ struct drm_i915_private *mock_gem_device(void) dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU) - /* hack to disable iommu for the fake device; force identity mapping */ - pdev->dev.archdata.iommu = (void *)-1; + /* HACK HACK HACK to disable iommu for the fake device; force identity mapping */ + memset(&iommu, 0, sizeof(iommu)); + iommu.priv = (void *)-1; + pdev->dev.iommu = &iommu; #endif pci_set_drvdata(pdev, i915); diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index d759e7234e982..2ce490c2eab89 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -372,7 +372,7 @@ struct device_domain_info *get_domain_info(struct device *dev) if (!dev) return NULL; - info = dev->archdata.iommu; + info = dev_iommu_priv_get(dev); if (unlikely(info == DUMMY_DEVICE_DOMAIN_INFO || info == DEFER_DEVICE_DOMAIN_INFO)) return NULL; @@ -743,12 +743,12 @@ struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus, static int iommu_dummy(struct device *dev) { - return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO; + return dev_iommu_priv_get(dev) == DUMMY_DEVICE_DOMAIN_INFO; } static bool attach_deferred(struct device *dev) { - return dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO; + return dev_iommu_priv_get(dev) == DEFER_DEVICE_DOMAIN_INFO; } /** @@ -2420,7 +2420,7 @@ static inline void unlink_domain_info(struct device_domain_info *info) list_del(&info->link); list_del(&info->global); if (info->dev) - info->dev->archdata.iommu = NULL; + dev_iommu_priv_set(info->dev, NULL); } static void domain_remove_dev_info(struct dmar_domain *domain) @@ -2453,7 +2453,7 @@ static void do_deferred_attach(struct device *dev) { struct iommu_domain *domain; - dev->archdata.iommu = NULL; + dev_iommu_priv_set(dev, NULL); domain = iommu_get_domain_for_dev(dev); if (domain) intel_iommu_attach_device(domain, dev); @@ -2599,7 +2599,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu, list_add(&info->link, &domain->devices); list_add(&info->global, &device_domain_list); if (dev) - dev->archdata.iommu = info; + dev_iommu_priv_set(dev, info); spin_unlock_irqrestore(&device_domain_lock, flags); /* PASID table is mandatory for a PCI device in scalable mode. */ @@ -4004,7 +4004,7 @@ static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev) if (!drhd || drhd->reg_base_addr - vtbar != 0xa000) { pr_warn_once(FW_BUG "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"); add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); - pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO; + dev_iommu_priv_set(&pdev->dev, DUMMY_DEVICE_DOMAIN_INFO); } } DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu); @@ -4043,7 +4043,7 @@ static void __init init_no_remapping_devices(void) drhd->ignored = 1; for_each_active_dev_scope(drhd->devices, drhd->devices_cnt, i, dev) - dev->archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO; + dev_iommu_priv_set(dev, DUMMY_DEVICE_DOMAIN_INFO); } } } @@ -5665,7 +5665,7 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev) return ERR_PTR(-ENODEV); if (translation_pre_enabled(iommu)) - dev->archdata.iommu = DEFER_DEVICE_DOMAIN_INFO; + dev_iommu_priv_set(dev, DEFER_DEVICE_DOMAIN_INFO); return &iommu->iommu; } -- GitLab From 4bbe0c7ccc431dcf06242860a7900f92800724c0 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:26 +0200 Subject: [PATCH 0190/1754] iommu/msm: Use dev_iommu_priv_get/set() Remove the use of dev->archdata.iommu and use the private per-device pointer provided by IOMMU core code instead. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-4-joro@8bytes.org --- drivers/iommu/msm_iommu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 3d8a63555c250..f773cc85f311f 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -593,14 +593,14 @@ static void insert_iommu_master(struct device *dev, struct msm_iommu_dev **iommu, struct of_phandle_args *spec) { - struct msm_iommu_ctx_dev *master = dev->archdata.iommu; + struct msm_iommu_ctx_dev *master = dev_iommu_priv_get(dev); int sid; if (list_empty(&(*iommu)->ctx_list)) { master = kzalloc(sizeof(*master), GFP_ATOMIC); master->of_node = dev->of_node; list_add(&master->list, &(*iommu)->ctx_list); - dev->archdata.iommu = master; + dev_iommu_priv_set(dev, master); } for (sid = 0; sid < master->num_mids; sid++) -- GitLab From 97ea1202601a7f936c9c9a86f900ec001cb589d3 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:27 +0200 Subject: [PATCH 0191/1754] iommu/omap: Use dev_iommu_priv_get/set() Remove the use of dev->archdata.iommu and use the private per-device pointer provided by IOMMU core code instead. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-5-joro@8bytes.org --- drivers/iommu/omap-iommu.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index c8282cc212cbd..e84ead6fb234a 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -71,7 +71,7 @@ static struct omap_iommu_domain *to_omap_domain(struct iommu_domain *dom) **/ void omap_iommu_save_ctx(struct device *dev) { - struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; + struct omap_iommu_arch_data *arch_data = dev_iommu_priv_get(dev); struct omap_iommu *obj; u32 *p; int i; @@ -101,7 +101,7 @@ EXPORT_SYMBOL_GPL(omap_iommu_save_ctx); **/ void omap_iommu_restore_ctx(struct device *dev) { - struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; + struct omap_iommu_arch_data *arch_data = dev_iommu_priv_get(dev); struct omap_iommu *obj; u32 *p; int i; @@ -1398,7 +1398,7 @@ static size_t omap_iommu_unmap(struct iommu_domain *domain, unsigned long da, static int omap_iommu_count(struct device *dev) { - struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; + struct omap_iommu_arch_data *arch_data = dev_iommu_priv_get(dev); int count = 0; while (arch_data->iommu_dev) { @@ -1459,8 +1459,8 @@ static void omap_iommu_detach_fini(struct omap_iommu_domain *odomain) static int omap_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) { + struct omap_iommu_arch_data *arch_data = dev_iommu_priv_get(dev); struct omap_iommu_domain *omap_domain = to_omap_domain(domain); - struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; struct omap_iommu_device *iommu; struct omap_iommu *oiommu; int ret = 0; @@ -1524,7 +1524,7 @@ omap_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) static void _omap_iommu_detach_dev(struct omap_iommu_domain *omap_domain, struct device *dev) { - struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; + struct omap_iommu_arch_data *arch_data = dev_iommu_priv_get(dev); struct omap_iommu_device *iommu = omap_domain->iommus; struct omap_iommu *oiommu; int i; @@ -1650,7 +1650,7 @@ static struct iommu_device *omap_iommu_probe_device(struct device *dev) int num_iommus, i; /* - * Allocate the archdata iommu structure for DT-based devices. + * Allocate the per-device iommu structure for DT-based devices. * * TODO: Simplify this when removing non-DT support completely from the * IOMMU users. @@ -1698,7 +1698,7 @@ static struct iommu_device *omap_iommu_probe_device(struct device *dev) of_node_put(np); } - dev->archdata.iommu = arch_data; + dev_iommu_priv_set(dev, arch_data); /* * use the first IOMMU alone for the sysfs device linking. @@ -1712,19 +1712,19 @@ static struct iommu_device *omap_iommu_probe_device(struct device *dev) static void omap_iommu_release_device(struct device *dev) { - struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; + struct omap_iommu_arch_data *arch_data = dev_iommu_priv_get(dev); if (!dev->of_node || !arch_data) return; - dev->archdata.iommu = NULL; + dev_iommu_priv_set(dev, NULL); kfree(arch_data); } static struct iommu_group *omap_iommu_device_group(struct device *dev) { - struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; + struct omap_iommu_arch_data *arch_data = dev_iommu_priv_get(dev); struct iommu_group *group = ERR_PTR(-EINVAL); if (!arch_data) -- GitLab From 8b9cc3b71bfda8e7c273b8f0fd80a8860ed077ad Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:28 +0200 Subject: [PATCH 0192/1754] iommu/rockchip: Use dev_iommu_priv_get/set() Remove the use of dev->archdata.iommu and use the private per-device pointer provided by IOMMU core code instead. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-6-joro@8bytes.org --- drivers/iommu/rockchip-iommu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index d25c2486ca070..e5d86b7177dec 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -836,7 +836,7 @@ static size_t rk_iommu_unmap(struct iommu_domain *domain, unsigned long _iova, static struct rk_iommu *rk_iommu_from_dev(struct device *dev) { - struct rk_iommudata *data = dev->archdata.iommu; + struct rk_iommudata *data = dev_iommu_priv_get(dev); return data ? data->iommu : NULL; } @@ -1059,7 +1059,7 @@ static struct iommu_device *rk_iommu_probe_device(struct device *dev) struct rk_iommudata *data; struct rk_iommu *iommu; - data = dev->archdata.iommu; + data = dev_iommu_priv_get(dev); if (!data) return ERR_PTR(-ENODEV); @@ -1073,7 +1073,7 @@ static struct iommu_device *rk_iommu_probe_device(struct device *dev) static void rk_iommu_release_device(struct device *dev) { - struct rk_iommudata *data = dev->archdata.iommu; + struct rk_iommudata *data = dev_iommu_priv_get(dev); device_link_del(data->link); } @@ -1100,7 +1100,7 @@ static int rk_iommu_of_xlate(struct device *dev, iommu_dev = of_find_device_by_node(args->np); data->iommu = platform_get_drvdata(iommu_dev); - dev->archdata.iommu = data; + dev_iommu_priv_set(dev, data); platform_device_put(iommu_dev); -- GitLab From a5616e24609a2bb3dc6ea1ab360207fa1198c976 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:29 +0200 Subject: [PATCH 0193/1754] iommu/tegra: Use dev_iommu_priv_get/set() Remove the use of dev->archdata.iommu and use the private per-device pointer provided by IOMMU core code instead. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-7-joro@8bytes.org --- drivers/iommu/tegra-gart.c | 8 ++++---- drivers/iommu/tegra-smmu.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index 5fbdff6ff41a8..fac720273889c 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c @@ -113,8 +113,8 @@ static int gart_iommu_attach_dev(struct iommu_domain *domain, if (gart->active_domain && gart->active_domain != domain) { ret = -EBUSY; - } else if (dev->archdata.iommu != domain) { - dev->archdata.iommu = domain; + } else if (dev_iommu_priv_get(dev) != domain) { + dev_iommu_priv_set(dev, domain); gart->active_domain = domain; gart->active_devices++; } @@ -131,8 +131,8 @@ static void gart_iommu_detach_dev(struct iommu_domain *domain, spin_lock(&gart->dom_lock); - if (dev->archdata.iommu == domain) { - dev->archdata.iommu = NULL; + if (dev_iommu_priv_get(dev) == domain) { + dev_iommu_priv_set(dev, NULL); if (--gart->active_devices == 0) gart->active_domain = NULL; diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 7426b7666e2bd..124c8848ab7ec 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -465,7 +465,7 @@ static void tegra_smmu_as_unprepare(struct tegra_smmu *smmu, static int tegra_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) { - struct tegra_smmu *smmu = dev->archdata.iommu; + struct tegra_smmu *smmu = dev_iommu_priv_get(dev); struct tegra_smmu_as *as = to_smmu_as(domain); struct device_node *np = dev->of_node; struct of_phandle_args args; @@ -780,7 +780,7 @@ static struct iommu_device *tegra_smmu_probe_device(struct device *dev) * supported by the Linux kernel, so abort after the * first match. */ - dev->archdata.iommu = smmu; + dev_iommu_priv_set(dev, smmu); break; } @@ -797,7 +797,7 @@ static struct iommu_device *tegra_smmu_probe_device(struct device *dev) static void tegra_smmu_release_device(struct device *dev) { - dev->archdata.iommu = NULL; + dev_iommu_priv_set(dev, NULL); } static const struct tegra_smmu_group_soc * @@ -856,7 +856,7 @@ static struct iommu_group *tegra_smmu_group_get(struct tegra_smmu *smmu, static struct iommu_group *tegra_smmu_device_group(struct device *dev) { struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); - struct tegra_smmu *smmu = dev->archdata.iommu; + struct tegra_smmu *smmu = dev_iommu_priv_get(dev); struct iommu_group *group; group = tegra_smmu_group_get(smmu, fwspec->ids[0]); -- GitLab From 2263d818bceff516254bfce4091632530720505a Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:30 +0200 Subject: [PATCH 0194/1754] iommu/pamu: Use dev_iommu_priv_get/set() Remove the use of dev->archdata.iommu_domain and use the private per-device pointer provided by IOMMU core code instead. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-8-joro@8bytes.org --- drivers/iommu/fsl_pamu_domain.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c index 928d37771ece0..b2110767caf49 100644 --- a/drivers/iommu/fsl_pamu_domain.c +++ b/drivers/iommu/fsl_pamu_domain.c @@ -323,7 +323,7 @@ static void remove_device_ref(struct device_domain_info *info, u32 win_cnt) pamu_disable_liodn(info->liodn); spin_unlock_irqrestore(&iommu_lock, flags); spin_lock_irqsave(&device_domain_lock, flags); - info->dev->archdata.iommu_domain = NULL; + dev_iommu_priv_set(info->dev, NULL); kmem_cache_free(iommu_devinfo_cache, info); spin_unlock_irqrestore(&device_domain_lock, flags); } @@ -352,7 +352,7 @@ static void attach_device(struct fsl_dma_domain *dma_domain, int liodn, struct d * Check here if the device is already attached to domain or not. * If the device is already attached to a domain detach it. */ - old_domain_info = dev->archdata.iommu_domain; + old_domain_info = dev_iommu_priv_get(dev); if (old_domain_info && old_domain_info->domain != dma_domain) { spin_unlock_irqrestore(&device_domain_lock, flags); detach_device(dev, old_domain_info->domain); @@ -371,8 +371,8 @@ static void attach_device(struct fsl_dma_domain *dma_domain, int liodn, struct d * the info for the first LIODN as all * LIODNs share the same domain */ - if (!dev->archdata.iommu_domain) - dev->archdata.iommu_domain = info; + if (!dev_iommu_priv_get(dev)) + dev_iommu_priv_set(dev, info); spin_unlock_irqrestore(&device_domain_lock, flags); } -- GitLab From 589601720d9d0366670eb415a4a62692d7af3713 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:31 +0200 Subject: [PATCH 0195/1754] iommu/mediatek: Do no use dev->archdata.iommu The iommu private pointer is already used in the Mediatek IOMMU v1 driver, so move the dma_iommu_mapping pointer into 'struct mtk_iommu_data' and do not use dev->archdata.iommu anymore. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-9-joro@8bytes.org --- drivers/iommu/mtk_iommu.h | 2 ++ drivers/iommu/mtk_iommu_v1.c | 10 ++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h index ea949a324e338..1682406e98dc7 100644 --- a/drivers/iommu/mtk_iommu.h +++ b/drivers/iommu/mtk_iommu.h @@ -62,6 +62,8 @@ struct mtk_iommu_data { struct iommu_device iommu; const struct mtk_iommu_plat_data *plat_data; + struct dma_iommu_mapping *mapping; /* For mtk_iommu_v1.c */ + struct list_head list; struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX]; }; diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index c9d79cff4d178..82ddfe9170d4d 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -269,7 +269,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, int ret; /* Only allow the domain created internally. */ - mtk_mapping = data->dev->archdata.iommu; + mtk_mapping = data->mapping; if (mtk_mapping->domain != domain) return 0; @@ -369,7 +369,6 @@ static int mtk_iommu_create_mapping(struct device *dev, struct mtk_iommu_data *data; struct platform_device *m4updev; struct dma_iommu_mapping *mtk_mapping; - struct device *m4udev; int ret; if (args->args_count != 1) { @@ -401,8 +400,7 @@ static int mtk_iommu_create_mapping(struct device *dev, return ret; data = dev_iommu_priv_get(dev); - m4udev = data->dev; - mtk_mapping = m4udev->archdata.iommu; + mtk_mapping = data->mapping; if (!mtk_mapping) { /* MTK iommu support 4GB iova address space. */ mtk_mapping = arm_iommu_create_mapping(&platform_bus_type, @@ -410,7 +408,7 @@ static int mtk_iommu_create_mapping(struct device *dev, if (IS_ERR(mtk_mapping)) return PTR_ERR(mtk_mapping); - m4udev->archdata.iommu = mtk_mapping; + data->mapping = mtk_mapping; } return 0; @@ -459,7 +457,7 @@ static void mtk_iommu_probe_finalize(struct device *dev) int err; data = dev_iommu_priv_get(dev); - mtk_mapping = data->dev->archdata.iommu; + mtk_mapping = data->mapping; err = arm_iommu_attach_device(dev, mtk_mapping); if (err) -- GitLab From ad962d864c61a73757085847027a532cbe2c1353 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:32 +0200 Subject: [PATCH 0196/1754] x86: Remove dev->archdata.iommu pointer There are no users left, all drivers have been converted to use the per-device private pointer offered by IOMMU core. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Acked-by: Borislav Petkov Link: https://lore.kernel.org/r/20200625130836.1916-10-joro@8bytes.org --- arch/x86/include/asm/device.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/x86/include/asm/device.h b/arch/x86/include/asm/device.h index 49bd6cf3eec91..7c0a52ca2f4dd 100644 --- a/arch/x86/include/asm/device.h +++ b/arch/x86/include/asm/device.h @@ -3,9 +3,6 @@ #define _ASM_X86_DEVICE_H struct dev_archdata { -#ifdef CONFIG_IOMMU_API - void *iommu; /* hook for IOMMU specific extension */ -#endif }; struct pdev_archdata { -- GitLab From 0b660afe310855c6eef35f8082594f32e3b05511 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:33 +0200 Subject: [PATCH 0197/1754] ia64: Remove dev->archdata.iommu pointer There are no users left, all drivers have been converted to use the per-device private pointer offered by IOMMU core. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-11-joro@8bytes.org --- arch/ia64/include/asm/device.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/ia64/include/asm/device.h b/arch/ia64/include/asm/device.h index 3eb3974153810..918b198cd5bbe 100644 --- a/arch/ia64/include/asm/device.h +++ b/arch/ia64/include/asm/device.h @@ -6,9 +6,6 @@ #define _ASM_IA64_DEVICE_H struct dev_archdata { -#ifdef CONFIG_IOMMU_API - void *iommu; /* hook for IOMMU specific extension */ -#endif }; struct pdev_archdata { -- GitLab From fb0fd5f70c1bfc9cdf5406e82d5de0ecdbe1e80c Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:34 +0200 Subject: [PATCH 0198/1754] arm: Remove dev->archdata.iommu pointer There are no users left, all drivers have been converted to use the per-device private pointer offered by IOMMU core. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-12-joro@8bytes.org --- arch/arm/include/asm/device.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h index c675bc0d5aa88..be666f58bf7ae 100644 --- a/arch/arm/include/asm/device.h +++ b/arch/arm/include/asm/device.h @@ -9,9 +9,6 @@ struct dev_archdata { #ifdef CONFIG_DMABOUNCE struct dmabounce_device_info *dmabounce; #endif -#ifdef CONFIG_IOMMU_API - void *iommu; /* private IOMMU data */ -#endif #ifdef CONFIG_ARM_DMA_USE_IOMMU struct dma_iommu_mapping *mapping; #endif -- GitLab From 5866a75b50b381fa05028e7ff3f2272ed006e321 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:35 +0200 Subject: [PATCH 0199/1754] arm64: Remove dev->archdata.iommu pointer There are no users left, all drivers have been converted to use the per-device private pointer offered by IOMMU core. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Acked-by: Will Deacon Link: https://lore.kernel.org/r/20200625130836.1916-13-joro@8bytes.org --- arch/arm64/include/asm/device.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h index 12b778d55342e..9964987513183 100644 --- a/arch/arm64/include/asm/device.h +++ b/arch/arm64/include/asm/device.h @@ -6,9 +6,6 @@ #define __ASM_DEVICE_H struct dev_archdata { -#ifdef CONFIG_IOMMU_API - void *iommu; /* private IOMMU data */ -#endif }; struct pdev_archdata { -- GitLab From 6255c8c8d256b38b550b35c6362750f64ce46b8d Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:36 +0200 Subject: [PATCH 0200/1754] powerpc/dma: Remove dev->archdata.iommu_domain There are no users left, so remove the pointer and save some memory. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-14-joro@8bytes.org --- arch/powerpc/include/asm/device.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/powerpc/include/asm/device.h b/arch/powerpc/include/asm/device.h index 266542769e4bd..1bc5952133382 100644 --- a/arch/powerpc/include/asm/device.h +++ b/arch/powerpc/include/asm/device.h @@ -34,9 +34,6 @@ struct dev_archdata { struct iommu_table *iommu_table_base; #endif -#ifdef CONFIG_IOMMU_API - void *iommu_domain; -#endif #ifdef CONFIG_PPC64 struct pci_dn *pci_data; #endif -- GitLab From ca37faf3d7005b5588f045edfac1d82799c408a7 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 30 Jun 2020 10:17:56 +0200 Subject: [PATCH 0201/1754] iommu: Move sg_table wrapper out of CONFIG_IOMMU_SUPPORT Move the recently added sg_table wrapper out of CONFIG_IOMMU_SUPPORT to let the client code copile also when IOMMU support is disabled. Fixes: 48530d9fab0d ("iommu: add generic helper for mapping sgtable objects") Signed-off-by: Marek Szyprowski Link: https://lore.kernel.org/r/20200630081756.18526-1-m.szyprowski@samsung.com Signed-off-by: Joerg Roedel --- include/linux/iommu.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 5f0b7859d2eb5..5657d4fef9f2b 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -457,22 +457,6 @@ extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t io extern void iommu_set_fault_handler(struct iommu_domain *domain, iommu_fault_handler_t handler, void *token); -/** - * iommu_map_sgtable - Map the given buffer to the IOMMU domain - * @domain: The IOMMU domain to perform the mapping - * @iova: The start address to map the buffer - * @sgt: The sg_table object describing the buffer - * @prot: IOMMU protection bits - * - * Creates a mapping at @iova for the buffer described by a scatterlist - * stored in the given sg_table object in the provided IOMMU domain. - */ -static inline size_t iommu_map_sgtable(struct iommu_domain *domain, - unsigned long iova, struct sg_table *sgt, int prot) -{ - return iommu_map_sg(domain, iova, sgt->sgl, sgt->orig_nents, prot); -} - extern void iommu_get_resv_regions(struct device *dev, struct list_head *list); extern void iommu_put_resv_regions(struct device *dev, struct list_head *list); extern void generic_iommu_put_resv_regions(struct device *dev, @@ -1079,6 +1063,22 @@ static inline struct iommu_fwspec *dev_iommu_fwspec_get(struct device *dev) } #endif /* CONFIG_IOMMU_API */ +/** + * iommu_map_sgtable - Map the given buffer to the IOMMU domain + * @domain: The IOMMU domain to perform the mapping + * @iova: The start address to map the buffer + * @sgt: The sg_table object describing the buffer + * @prot: IOMMU protection bits + * + * Creates a mapping at @iova for the buffer described by a scatterlist + * stored in the given sg_table object in the provided IOMMU domain. + */ +static inline size_t iommu_map_sgtable(struct iommu_domain *domain, + unsigned long iova, struct sg_table *sgt, int prot) +{ + return iommu_map_sg(domain, iova, sgt->sgl, sgt->orig_nents, prot); +} + #ifdef CONFIG_IOMMU_DEBUGFS extern struct dentry *iommu_debugfs_dir; void iommu_debugfs_setup(void); -- GitLab From 557d4bec009330567ce99692918abbe9c77528e0 Mon Sep 17 00:00:00 2001 From: Jerry Snitselaar Date: Fri, 5 Jun 2020 00:00:25 -0700 Subject: [PATCH 0202/1754] iommu: Add include/uapi/linux/iommu.h to MAINTAINERS file When include/uapi/linux/iommu.h was created it was never added to the file list in MAINTAINERS. Signed-off-by: Jerry Snitselaar Cc: Joerg Roedel Link: https://lore.kernel.org/r/20200605070025.216124-1-jsnitsel@redhat.com Signed-off-by: Joerg Roedel --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 496fd4eafb68c..c23352059a6bc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9014,6 +9014,7 @@ F: drivers/iommu/ F: include/linux/iommu.h F: include/linux/iova.h F: include/linux/of_iommu.h +F: include/uapi/linux/iommu.h IO_URING M: Jens Axboe -- GitLab From bdc4094591c3809e53eb7792344248bb447768c3 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Mon, 29 Jun 2020 12:32:23 +0200 Subject: [PATCH 0203/1754] platform/chrome: cros_ec_typec: Add a dependency on USB_ROLE_SWITCH As reported by the kernel test robot the cros_ec_typec driver fails to build if the USB_ROLE_SWITCH is not selected, to fix that, add a dependency on that symbol. This fixes the following build error: drivers/platform/chrome/cros_ec_typec.c:133: undefined reference to `usb_role_switch_put' ld: drivers/platform/chrome/cros_ec_typec.o: in function `cros_typec_get_switch_handles': drivers/platform/chrome/cros_ec_typec.c:108: undefined reference to `fwnode_usb_role_switch_get' ld: drivers/platform/chrome/cros_ec_typec.c:117: undefined reference to `usb_role_switch_put' Fixes: 7e7def15fa4b ("platform/chrome: cros_ec_typec: Add USB mux control") Reported-by: kernel test robot Acked-by: Prashant Malani Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig index cf072153bdc5d..a056031dee811 100644 --- a/drivers/platform/chrome/Kconfig +++ b/drivers/platform/chrome/Kconfig @@ -218,6 +218,7 @@ config CROS_EC_TYPEC tristate "ChromeOS EC Type-C Connector Control" depends on MFD_CROS_EC_DEV && TYPEC depends on CROS_USBPD_NOTIFY + depends on USB_ROLE_SWITCH default MFD_CROS_EC_DEV help If you say Y here, you get support for accessing Type C connector -- GitLab From f1d8fe2e98d11788cabb2ad5c5becfcc95dd81a9 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 30 Jun 2020 08:44:43 -0300 Subject: [PATCH 0204/1754] dt-bindings: mfd: st,stmfx: Remove extra additionalProperties The following build error is seen with 'make dt_binding_check': CHKDT Documentation/devicetree/bindings/mfd/st,stmfx.yaml /home/fabio/linux-next/Documentation/devicetree/bindings/mfd/st,stmfx.yaml: properties:pinctrl:patternProperties: {'enum': ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'deprecated', 'description', 'else', 'enum', 'if', 'items', 'maxItems', 'maximum', 'minItems', 'minimum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'propertyNames', 'required', 'then', 'unevaluatedProperties']} is not allowed for 'additionalProperties' Remove the extra 'additionalProperties' to pass the build. Signed-off-by: Fabio Estevam Reviewed-by: Rob Herring Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/mfd/st,stmfx.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/st,stmfx.yaml b/Documentation/devicetree/bindings/mfd/st,stmfx.yaml index 0ce56a0da5536..bed22d4abffba 100644 --- a/Documentation/devicetree/bindings/mfd/st,stmfx.yaml +++ b/Documentation/devicetree/bindings/mfd/st,stmfx.yaml @@ -73,8 +73,6 @@ properties: output-high: true output-low: true - additionalProperties: false - additionalProperties: false required: -- GitLab From 83cbc69df8b8ec598ff8ca7629be34a50274e5b5 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Mon, 29 Jun 2020 14:13:27 -0700 Subject: [PATCH 0205/1754] platform/chrome: cros_ec_typec: Use workqueue for port update Use a work queue to call the port update routines, instead of doing it directly in the PD notifier callback. This will prevent other drivers with PD notifier callbacks from being blocked on the port update routine completing. Signed-off-by: Prashant Malani Reviewed-by: Guenter Roeck Reviewed-by: Heikki Krogerus Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 0c041b79cbbac..9901bf2a96c2f 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -58,6 +58,7 @@ struct cros_typec_data { /* Array of ports, indexed by port number. */ struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS]; struct notifier_block nb; + struct work_struct port_work; }; static int cros_typec_parse_port_props(struct typec_capability *cap, @@ -619,11 +620,9 @@ static int cros_typec_get_cmd_version(struct cros_typec_data *typec) return 0; } -static int cros_ec_typec_event(struct notifier_block *nb, - unsigned long host_event, void *_notify) +static void cros_typec_port_work(struct work_struct *work) { - struct cros_typec_data *typec = container_of(nb, struct cros_typec_data, - nb); + struct cros_typec_data *typec = container_of(work, struct cros_typec_data, port_work); int ret, i; for (i = 0; i < typec->num_ports; i++) { @@ -631,6 +630,14 @@ static int cros_ec_typec_event(struct notifier_block *nb, if (ret < 0) dev_warn(typec->dev, "Update failed for port: %d\n", i); } +} + +static int cros_ec_typec_event(struct notifier_block *nb, + unsigned long host_event, void *_notify) +{ + struct cros_typec_data *typec = container_of(nb, struct cros_typec_data, nb); + + schedule_work(&typec->port_work); return NOTIFY_OK; } @@ -689,6 +696,12 @@ static int cros_typec_probe(struct platform_device *pdev) if (ret < 0) return ret; + INIT_WORK(&typec->port_work, cros_typec_port_work); + + /* + * Safe to call port update here, since we haven't registered the + * PD notifier yet. + */ for (i = 0; i < typec->num_ports; i++) { ret = cros_typec_port_update(typec, i); if (ret < 0) -- GitLab From 20b736872f7f324438649a277ec711a646ce8e8d Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Mon, 29 Jun 2020 14:13:29 -0700 Subject: [PATCH 0206/1754] platform/chrome: cros_ec_typec: Add PM support Define basic suspend resume functions for cros-ec-typec. On suspend, we simply ensure that any pending port update work is completed, and on resume, we re-poll the port state to account for any changes/disconnections that might have occurred during suspend. Signed-off-by: Prashant Malani Reviewed-by: Guenter Roeck Reviewed-by: Heikki Krogerus Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 9901bf2a96c2f..3eae01f4c9f70 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -720,11 +720,35 @@ static int cros_typec_probe(struct platform_device *pdev) return ret; } +static int __maybe_unused cros_typec_suspend(struct device *dev) +{ + struct cros_typec_data *typec = dev_get_drvdata(dev); + + cancel_work_sync(&typec->port_work); + + return 0; +} + +static int __maybe_unused cros_typec_resume(struct device *dev) +{ + struct cros_typec_data *typec = dev_get_drvdata(dev); + + /* Refresh port state. */ + schedule_work(&typec->port_work); + + return 0; +} + +static const struct dev_pm_ops cros_typec_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(cros_typec_suspend, cros_typec_resume) +}; + static struct platform_driver cros_typec_driver = { .driver = { .name = DRV_NAME, .acpi_match_table = ACPI_PTR(cros_typec_acpi_id), .of_match_table = of_match_ptr(cros_typec_of_match), + .pm = &cros_typec_pm_ops, }, .probe = cros_typec_probe, }; -- GitLab From e48bc01ed5adec203676c735365373b31c3c7600 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Tue, 30 Jun 2020 00:52:03 -0700 Subject: [PATCH 0207/1754] platform/chrome: cros_ec_sensorhub: Fix EC timestamp overflow EC is using 32 bit timestamps (us), and before converting it to 64bit they were not casted, so it would overflow every 4s. Regular overflow every ~70 minutes was not taken into account either. Signed-off-by: Gwendal Grignou Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_sensorhub_ring.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_sensorhub_ring.c b/drivers/platform/chrome/cros_ec_sensorhub_ring.c index 24e48d96ed766..b1c641c72f515 100644 --- a/drivers/platform/chrome/cros_ec_sensorhub_ring.c +++ b/drivers/platform/chrome/cros_ec_sensorhub_ring.c @@ -419,9 +419,7 @@ cros_ec_sensor_ring_process_event(struct cros_ec_sensorhub *sensorhub, * Disable filtering since we might add more jitter * if b is in a random point in time. */ - new_timestamp = fifo_timestamp - - fifo_info->timestamp * 1000 + - in->timestamp * 1000; + new_timestamp = c - b * 1000 + a * 1000; /* * The timestamp can be stale if we had to use the fifo * info timestamp. -- GitLab From e1915eec54a6b4902664eaf6fb7a20de5624c4dd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 26 Jun 2020 22:37:41 +0200 Subject: [PATCH 0208/1754] backlight: sky81452: Convert to GPIO descriptors The SKY81452 backlight driver just obtains a GPIO (named "gpios" in the device tree) drives it high and leaves it high until the driver is removed. Switch to use GPIO descriptors for this, simple and straight-forward. Cc: Gyungoh Yoo Signed-off-by: Linus Walleij Reviewed-by: Daniel Thompson Signed-off-by: Lee Jones --- drivers/video/backlight/sky81452-backlight.c | 18 ++++-------------- .../linux/platform_data/sky81452-backlight.h | 6 ++++-- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/video/backlight/sky81452-backlight.c b/drivers/video/backlight/sky81452-backlight.c index 2355f00f57732..81d2c8f3ca50a 100644 --- a/drivers/video/backlight/sky81452-backlight.c +++ b/drivers/video/backlight/sky81452-backlight.c @@ -8,12 +8,11 @@ #include #include -#include +#include #include #include #include #include -#include #include #include #include @@ -182,7 +181,7 @@ static struct sky81452_bl_platform_data *sky81452_bl_parse_dt( pdata->ignore_pwm = of_property_read_bool(np, "skyworks,ignore-pwm"); pdata->dpwm_mode = of_property_read_bool(np, "skyworks,dpwm-mode"); pdata->phase_shift = of_property_read_bool(np, "skyworks,phase-shift"); - pdata->gpio_enable = of_get_gpio(np, 0); + pdata->gpiod_enable = devm_gpiod_get_optional(dev, NULL, GPIOD_OUT_HIGH); ret = of_property_count_u32_elems(np, "led-sources"); if (ret < 0) { @@ -264,15 +263,6 @@ static int sky81452_bl_probe(struct platform_device *pdev) return PTR_ERR(pdata); } - if (gpio_is_valid(pdata->gpio_enable)) { - ret = devm_gpio_request_one(dev, pdata->gpio_enable, - GPIOF_OUT_INIT_HIGH, "sky81452-en"); - if (ret < 0) { - dev_err(dev, "failed to request GPIO. err=%d\n", ret); - return ret; - } - } - ret = sky81452_bl_init_device(regmap, pdata); if (ret < 0) { dev_err(dev, "failed to initialize. err=%d\n", ret); @@ -312,8 +302,8 @@ static int sky81452_bl_remove(struct platform_device *pdev) bd->props.brightness = 0; backlight_update_status(bd); - if (gpio_is_valid(pdata->gpio_enable)) - gpio_set_value_cansleep(pdata->gpio_enable, 0); + if (pdata->gpiod_enable) + gpiod_set_value_cansleep(pdata->gpiod_enable, 0); return 0; } diff --git a/include/linux/platform_data/sky81452-backlight.h b/include/linux/platform_data/sky81452-backlight.h index 02653d92d84fc..d6f46670d9230 100644 --- a/include/linux/platform_data/sky81452-backlight.h +++ b/include/linux/platform_data/sky81452-backlight.h @@ -9,11 +9,13 @@ #ifndef _SKY81452_BACKLIGHT_H #define _SKY81452_BACKLIGHT_H +#include + /** * struct sky81452_platform_data * @name: backlight driver name. If it is not defined, default name is lcd-backlight. - * @gpio_enable:GPIO number which control EN pin + * @gpios_enable:GPIO descriptor which control EN pin * @enable: Enable mask for current sink channel 1, 2, 3, 4, 5 and 6. * @ignore_pwm: true if DPWMI should be ignored. * @dpwm_mode: true is DPWM dimming mode, otherwise Analog dimming mode. @@ -23,7 +25,7 @@ */ struct sky81452_bl_platform_data { const char *name; - int gpio_enable; + struct gpio_desc *gpiod_enable; unsigned int enable; bool ignore_pwm; bool dpwm_mode; -- GitLab From 08bf73a6f056d84fd52a58c5d165523dd84be535 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 26 Jun 2020 22:37:42 +0200 Subject: [PATCH 0209/1754] backlight: sky81452: Privatize platform data The only way the platform data for the SKY81452 ever gets populated is through the device tree. The MFD device is bothered with this for no reason at all. Just allocate the platform data in the driver and be happy. Cc: Gyungoh Yoo Signed-off-by: Linus Walleij Reviewed-by: Daniel Thompson Signed-off-by: Lee Jones --- drivers/mfd/sky81452.c | 2 - drivers/video/backlight/sky81452-backlight.c | 34 +++++++++++++---- include/linux/mfd/sky81452.h | 2 - .../linux/platform_data/sky81452-backlight.h | 37 ------------------- 4 files changed, 27 insertions(+), 48 deletions(-) delete mode 100644 include/linux/platform_data/sky81452-backlight.h diff --git a/drivers/mfd/sky81452.c b/drivers/mfd/sky81452.c index 76eedfae85536..3ad35bf0c0155 100644 --- a/drivers/mfd/sky81452.c +++ b/drivers/mfd/sky81452.c @@ -47,8 +47,6 @@ static int sky81452_probe(struct i2c_client *client, memset(cells, 0, sizeof(cells)); cells[0].name = "sky81452-backlight"; cells[0].of_compatible = "skyworks,sky81452-backlight"; - cells[0].platform_data = pdata->bl_pdata; - cells[0].pdata_size = sizeof(*pdata->bl_pdata); cells[1].name = "sky81452-regulator"; cells[1].platform_data = pdata->regulator_init_data; cells[1].pdata_size = sizeof(*pdata->regulator_init_data); diff --git a/drivers/video/backlight/sky81452-backlight.c b/drivers/video/backlight/sky81452-backlight.c index 81d2c8f3ca50a..83ccb3d940fae 100644 --- a/drivers/video/backlight/sky81452-backlight.c +++ b/drivers/video/backlight/sky81452-backlight.c @@ -15,7 +15,6 @@ #include #include #include -#include #include /* registers */ @@ -41,6 +40,29 @@ #define SKY81452_DEFAULT_NAME "lcd-backlight" #define SKY81452_MAX_BRIGHTNESS (SKY81452_CS + 1) +/** + * struct sky81452_platform_data + * @name: backlight driver name. + If it is not defined, default name is lcd-backlight. + * @gpios_enable:GPIO descriptor which control EN pin + * @enable: Enable mask for current sink channel 1, 2, 3, 4, 5 and 6. + * @ignore_pwm: true if DPWMI should be ignored. + * @dpwm_mode: true is DPWM dimming mode, otherwise Analog dimming mode. + * @phase_shift:true is phase shift mode. + * @short_detecion_threshold: It should be one of 4, 5, 6 and 7V. + * @boost_current_limit: It should be one of 2300, 2750mA. + */ +struct sky81452_bl_platform_data { + const char *name; + struct gpio_desc *gpiod_enable; + unsigned int enable; + bool ignore_pwm; + bool dpwm_mode; + bool phase_shift; + unsigned int short_detection_threshold; + unsigned int boost_current_limit; +}; + #define CTZ(b) __builtin_ctz(b) static int sky81452_bl_update_status(struct backlight_device *bd) @@ -251,17 +273,15 @@ static int sky81452_bl_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct regmap *regmap = dev_get_drvdata(dev->parent); - struct sky81452_bl_platform_data *pdata = dev_get_platdata(dev); + struct sky81452_bl_platform_data *pdata; struct backlight_device *bd; struct backlight_properties props; const char *name; int ret; - if (!pdata) { - pdata = sky81452_bl_parse_dt(dev); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - } + pdata = sky81452_bl_parse_dt(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); ret = sky81452_bl_init_device(regmap, pdata); if (ret < 0) { diff --git a/include/linux/mfd/sky81452.h b/include/linux/mfd/sky81452.h index d469aa4812434..b08570ff34df9 100644 --- a/include/linux/mfd/sky81452.h +++ b/include/linux/mfd/sky81452.h @@ -9,11 +9,9 @@ #ifndef _SKY81452_H #define _SKY81452_H -#include #include struct sky81452_platform_data { - struct sky81452_bl_platform_data *bl_pdata; struct regulator_init_data *regulator_init_data; }; diff --git a/include/linux/platform_data/sky81452-backlight.h b/include/linux/platform_data/sky81452-backlight.h deleted file mode 100644 index d6f46670d9230..0000000000000 --- a/include/linux/platform_data/sky81452-backlight.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * sky81452.h SKY81452 backlight driver - * - * Copyright 2014 Skyworks Solutions Inc. - * Author : Gyungoh Yoo - */ - -#ifndef _SKY81452_BACKLIGHT_H -#define _SKY81452_BACKLIGHT_H - -#include - -/** - * struct sky81452_platform_data - * @name: backlight driver name. - If it is not defined, default name is lcd-backlight. - * @gpios_enable:GPIO descriptor which control EN pin - * @enable: Enable mask for current sink channel 1, 2, 3, 4, 5 and 6. - * @ignore_pwm: true if DPWMI should be ignored. - * @dpwm_mode: true is DPWM dimming mode, otherwise Analog dimming mode. - * @phase_shift:true is phase shift mode. - * @short_detecion_threshold: It should be one of 4, 5, 6 and 7V. - * @boost_current_limit: It should be one of 2300, 2750mA. - */ -struct sky81452_bl_platform_data { - const char *name; - struct gpio_desc *gpiod_enable; - unsigned int enable; - bool ignore_pwm; - bool dpwm_mode; - bool phase_shift; - unsigned int short_detection_threshold; - unsigned int boost_current_limit; -}; - -#endif -- GitLab From e994734fdca7309234a210169c7a7f2f446e430f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 26 Jun 2020 12:25:00 +0200 Subject: [PATCH 0210/1754] backlight: Delete the OT200 backlight driver This driver has no in-kernel users. The device can only be populated by board files since it does not support device tree nor ACPI, and nothing in the kernel creates a device named "ot200-backlight". This driver has been in the kernel since 2012. If it is used by out-of-tree code that code should have been upstreamed by now, it's been 8 years. It uses the idiomatic forked GPIO of the CS5535 which combines pin control and GPIO into its private custom interface, which causes me a headache because that is not how we do things these days: we creates separate pin control and GPIO drivers. Delete this unused driver. Cc: Christian Gmeiner Signed-off-by: Linus Walleij Reviewed-by: Daniel Thompson Signed-off-by: Lee Jones --- drivers/video/backlight/Kconfig | 7 -- drivers/video/backlight/Makefile | 1 - drivers/video/backlight/ot200_bl.c | 162 ----------------------------- 3 files changed, 170 deletions(-) delete mode 100644 drivers/video/backlight/ot200_bl.c diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 7d22d73776064..95c546cc87748 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -386,13 +386,6 @@ config BACKLIGHT_LP8788 help This supports TI LP8788 backlight driver. -config BACKLIGHT_OT200 - tristate "Backlight driver for ot200 visualisation device" - depends on CS5535_MFGPT && GPIO_CS5535 - help - To compile this driver as a module, choose M here: the module will be - called ot200_bl. - config BACKLIGHT_PANDORA tristate "Backlight driver for Pandora console" depends on TWL4030_CORE diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 0c1a1524627ad..2072d21b60f70 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -45,7 +45,6 @@ obj-$(CONFIG_BACKLIGHT_LP8788) += lp8788_bl.o obj-$(CONFIG_BACKLIGHT_LV5207LP) += lv5207lp.o obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o -obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o diff --git a/drivers/video/backlight/ot200_bl.c b/drivers/video/backlight/ot200_bl.c deleted file mode 100644 index 23ee7106c72a3..0000000000000 --- a/drivers/video/backlight/ot200_bl.c +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2012 Bachmann electronic GmbH - * Christian Gmeiner - * - * Backlight driver for ot200 visualisation device from - * Bachmann electronic GmbH. - */ - -#include -#include -#include -#include -#include -#include - -static struct cs5535_mfgpt_timer *pwm_timer; - -/* this array defines the mapping of brightness in % to pwm frequency */ -static const u8 dim_table[101] = {0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, - 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9, - 10, 10, 11, 11, 12, 12, 13, 14, 15, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, - 30, 31, 33, 35, 37, 39, 41, 43, 45, 47, 50, - 53, 55, 58, 61, 65, 68, 72, 75, 79, 84, 88, - 93, 97, 103, 108, 114, 120, 126, 133, 140, - 147, 155, 163}; - -struct ot200_backlight_data { - int current_brightness; -}; - -#define GPIO_DIMM 27 -#define SCALE 1 -#define CMP1MODE 0x2 /* compare on GE; output high on compare - * greater than or equal */ -#define PWM_SETUP (SCALE | CMP1MODE << 6 | MFGPT_SETUP_CNTEN) -#define MAX_COMP2 163 - -static int ot200_backlight_update_status(struct backlight_device *bl) -{ - struct ot200_backlight_data *data = bl_get_data(bl); - int brightness = bl->props.brightness; - - if (bl->props.state & BL_CORE_FBBLANK) - brightness = 0; - - /* enable or disable PWM timer */ - if (brightness == 0) - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_SETUP, 0); - else if (data->current_brightness == 0) { - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_COUNTER, 0); - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_SETUP, - MFGPT_SETUP_CNTEN); - } - - /* apply new brightness value */ - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_CMP1, - MAX_COMP2 - dim_table[brightness]); - data->current_brightness = brightness; - - return 0; -} - -static int ot200_backlight_get_brightness(struct backlight_device *bl) -{ - struct ot200_backlight_data *data = bl_get_data(bl); - return data->current_brightness; -} - -static const struct backlight_ops ot200_backlight_ops = { - .update_status = ot200_backlight_update_status, - .get_brightness = ot200_backlight_get_brightness, -}; - -static int ot200_backlight_probe(struct platform_device *pdev) -{ - struct backlight_device *bl; - struct ot200_backlight_data *data; - struct backlight_properties props; - int retval = 0; - - /* request gpio */ - if (devm_gpio_request(&pdev->dev, GPIO_DIMM, - "ot200 backlight dimmer") < 0) { - dev_err(&pdev->dev, "failed to request GPIO %d\n", GPIO_DIMM); - return -ENODEV; - } - - /* request timer */ - pwm_timer = cs5535_mfgpt_alloc_timer(7, MFGPT_DOMAIN_ANY); - if (!pwm_timer) { - dev_err(&pdev->dev, "MFGPT 7 not available\n"); - return -ENODEV; - } - - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - if (!data) { - retval = -ENOMEM; - goto error_devm_kzalloc; - } - - /* setup gpio */ - cs5535_gpio_set(GPIO_DIMM, GPIO_OUTPUT_ENABLE); - cs5535_gpio_set(GPIO_DIMM, GPIO_OUTPUT_AUX1); - - /* setup timer */ - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_CMP1, 0); - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_CMP2, MAX_COMP2); - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_SETUP, PWM_SETUP); - - data->current_brightness = 100; - props.max_brightness = 100; - props.brightness = 100; - props.type = BACKLIGHT_RAW; - - bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), - &pdev->dev, data, &ot200_backlight_ops, - &props); - if (IS_ERR(bl)) { - dev_err(&pdev->dev, "failed to register backlight\n"); - retval = PTR_ERR(bl); - goto error_devm_kzalloc; - } - - platform_set_drvdata(pdev, bl); - - return 0; - -error_devm_kzalloc: - cs5535_mfgpt_free_timer(pwm_timer); - return retval; -} - -static int ot200_backlight_remove(struct platform_device *pdev) -{ - /* on module unload set brightness to 100% */ - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_COUNTER, 0); - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN); - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_CMP1, - MAX_COMP2 - dim_table[100]); - - cs5535_mfgpt_free_timer(pwm_timer); - - return 0; -} - -static struct platform_driver ot200_backlight_driver = { - .driver = { - .name = "ot200-backlight", - }, - .probe = ot200_backlight_probe, - .remove = ot200_backlight_remove, -}; - -module_platform_driver(ot200_backlight_driver); - -MODULE_DESCRIPTION("backlight driver for ot200 visualisation device"); -MODULE_AUTHOR("Christian Gmeiner "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:ot200-backlight"); -- GitLab From f3528630e2e7b1556b0f150f1e205462c66efe8e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 26 Jun 2020 01:25:12 +0200 Subject: [PATCH 0211/1754] backlight: lms501kf03: Drop unused include This driver includes but does not use any symbols from that file, drop the include. Signed-off-by: Linus Walleij Reviewed-by: Daniel Thompson Signed-off-by: Lee Jones --- drivers/video/backlight/lms501kf03.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/video/backlight/lms501kf03.c b/drivers/video/backlight/lms501kf03.c index 8ae32e3573c1a..52d3ee6c3f7f9 100644 --- a/drivers/video/backlight/lms501kf03.c +++ b/drivers/video/backlight/lms501kf03.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include -- GitLab From 9dce29e65b38591eac0ce6786bdb725aea1eadeb Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 09:28:39 -0400 Subject: [PATCH 0212/1754] ktest.pl: Have config-bisect save each config used in the bisect When performing a automatic config bisect via ktest.pl, it is very useful to have a copy of each of the bisects used. This way, if a bisect were to go wrong, it is possible to retrace the steps and continue at the location before the error was made. The ktest.pl will make a copy of the good and bad configs, labeled as such, as well as a number attached to it that represents the iteration of the bisect. These files are saved in the ktest temp directory where it currently stores the good and bad config files. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 7570e36d636d8..5f6f88911f5cf 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -3188,6 +3188,8 @@ sub config_bisect_end { doprint "***************************************\n\n"; } +my $pass = 1; + sub run_config_bisect { my ($good, $bad, $last_result) = @_; my $reset = ""; @@ -3210,11 +3212,15 @@ sub run_config_bisect { $ret = run_config_bisect_test $config_bisect_type; if ($ret) { - doprint "NEW GOOD CONFIG\n"; + doprint "NEW GOOD CONFIG ($pass)\n"; + system("cp $output_config $tmpdir/good_config.tmp.$pass"); + $pass++; # Return 3 for good config return 3; } else { - doprint "NEW BAD CONFIG\n"; + doprint "NEW BAD CONFIG ($pass)\n"; + system("cp $output_config $tmpdir/bad_config.tmp.$pass"); + $pass++; # Return 4 for bad config return 4; } -- GitLab From 4d3ec936f80dbb2174c8c1f426eb86c032e9f14e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 30 Jun 2020 10:39:48 +0200 Subject: [PATCH 0213/1754] mfd: lm3533: Expand control-bank accessors Expand the control-bank accessors that were implemented using macros. This allows the definitions of these exported functions to be found more easily and specifically avoids a W=1 compiler warning due to the redundant brightness sanity check: drivers/mfd/lm3533-ctrlbank.c: In function 'lm3533_ctrlbank_set_brightness': drivers/mfd/lm3533-ctrlbank.c:98:10: warning: comparison is always false due to limited range of data type [-Wtype-limits] 98 | if (val > LM3533_##_NAME##_MAX) \ | ^ drivers/mfd/lm3533-ctrlbank.c:125:1: note: in expansion of macro 'lm3533_ctrlbank_set' 125 | lm3533_ctrlbank_set(brightness, BRIGHTNESS); | ^~~~~~~~~~~~~~~~~~~ Signed-off-by: Johan Hovold Signed-off-by: Lee Jones --- drivers/mfd/lm3533-ctrlbank.c | 94 +++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 38 deletions(-) diff --git a/drivers/mfd/lm3533-ctrlbank.c b/drivers/mfd/lm3533-ctrlbank.c index 34fba06ec7057..2537dfade51cd 100644 --- a/drivers/mfd/lm3533-ctrlbank.c +++ b/drivers/mfd/lm3533-ctrlbank.c @@ -17,7 +17,6 @@ #define LM3533_MAX_CURRENT_MAX 29800 #define LM3533_MAX_CURRENT_STEP 800 -#define LM3533_BRIGHTNESS_MAX 255 #define LM3533_PWM_MAX 0x3f #define LM3533_REG_PWM_BASE 0x14 @@ -89,41 +88,33 @@ int lm3533_ctrlbank_set_max_current(struct lm3533_ctrlbank *cb, u16 imax) } EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_max_current); -#define lm3533_ctrlbank_set(_name, _NAME) \ -int lm3533_ctrlbank_set_##_name(struct lm3533_ctrlbank *cb, u8 val) \ -{ \ - u8 reg; \ - int ret; \ - \ - if (val > LM3533_##_NAME##_MAX) \ - return -EINVAL; \ - \ - reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_##_NAME##_BASE); \ - ret = lm3533_write(cb->lm3533, reg, val); \ - if (ret) \ - dev_err(cb->dev, "failed to set " #_name "\n"); \ - \ - return ret; \ -} \ -EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_##_name); - -#define lm3533_ctrlbank_get(_name, _NAME) \ -int lm3533_ctrlbank_get_##_name(struct lm3533_ctrlbank *cb, u8 *val) \ -{ \ - u8 reg; \ - int ret; \ - \ - reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_##_NAME##_BASE); \ - ret = lm3533_read(cb->lm3533, reg, val); \ - if (ret) \ - dev_err(cb->dev, "failed to get " #_name "\n"); \ - \ - return ret; \ -} \ -EXPORT_SYMBOL_GPL(lm3533_ctrlbank_get_##_name); - -lm3533_ctrlbank_set(brightness, BRIGHTNESS); -lm3533_ctrlbank_get(brightness, BRIGHTNESS); +int lm3533_ctrlbank_set_brightness(struct lm3533_ctrlbank *cb, u8 val) +{ + u8 reg; + int ret; + + reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_BRIGHTNESS_BASE); + ret = lm3533_write(cb->lm3533, reg, val); + if (ret) + dev_err(cb->dev, "failed to set brightness\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_brightness); + +int lm3533_ctrlbank_get_brightness(struct lm3533_ctrlbank *cb, u8 *val) +{ + u8 reg; + int ret; + + reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_BRIGHTNESS_BASE); + ret = lm3533_read(cb->lm3533, reg, val); + if (ret) + dev_err(cb->dev, "failed to get brightness\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(lm3533_ctrlbank_get_brightness); /* * PWM-input control mask: @@ -135,9 +126,36 @@ lm3533_ctrlbank_get(brightness, BRIGHTNESS); * bit 1 - PWM-input enabled in Zone 0 * bit 0 - PWM-input enabled */ -lm3533_ctrlbank_set(pwm, PWM); -lm3533_ctrlbank_get(pwm, PWM); +int lm3533_ctrlbank_set_pwm(struct lm3533_ctrlbank *cb, u8 val) +{ + u8 reg; + int ret; + + if (val > LM3533_PWM_MAX) + return -EINVAL; + + reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_PWM_BASE); + ret = lm3533_write(cb->lm3533, reg, val); + if (ret) + dev_err(cb->dev, "failed to set PWM mask\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_pwm); + +int lm3533_ctrlbank_get_pwm(struct lm3533_ctrlbank *cb, u8 *val) +{ + u8 reg; + int ret; + reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_PWM_BASE); + ret = lm3533_read(cb->lm3533, reg, val); + if (ret) + dev_err(cb->dev, "failed to get PWM mask\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(lm3533_ctrlbank_get_pwm); MODULE_AUTHOR("Johan Hovold "); MODULE_DESCRIPTION("LM3533 Control Bank interface"); -- GitLab From 2f059db0b8313f8964ac917394e7425d966a6884 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 10:28:23 -0400 Subject: [PATCH 0214/1754] ktest.pl: Always show log file location if defined even on success If a log file is defined and the test were to error, a print statement is made that shows the user where the log file is to examine it further. But this is not done if the test were to succeed. I find it annoying that it does not show where the log file is on success, as I run several different tests that place their log files in various locations, and even though the test pass, there's things I want to look at in the log file (like warnings). It is much easier to find where the log file is, if it is displayed at the end of a test. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 5f6f88911f5cf..5d5cf3e1e81a9 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -4441,6 +4441,10 @@ if ($opt{"POWEROFF_ON_SUCCESS"}) { } +if (defined($opt{"LOG_FILE"})) { + print "\n See $opt{LOG_FILE} for the record of results.\n"; +} + doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; if ($email_when_finished) { -- GitLab From d53cdda3fda6e737151e091c7d9388c31a73c828 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 10:32:28 -0400 Subject: [PATCH 0215/1754] ktest.pl: Define PRE_TEST_DIE to kill the test if the PRE_TEST fails Currently, if a PRE_TEST is defined and ran, but fails, there's nothing currently available to make the test fail too. Add a PRE_TEST_DIE option that when set, if a PRE_TEST is defined and fails, the test will die too. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 8 +++++++- tools/testing/ktest/sample.conf | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 5d5cf3e1e81a9..f99cf633ed84f 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -98,6 +98,7 @@ my $final_post_ktest; my $pre_ktest; my $post_ktest; my $pre_test; +my $pre_test_die; my $post_test; my $pre_build; my $post_build; @@ -273,6 +274,7 @@ my %option_map = ( "PRE_KTEST" => \$pre_ktest, "POST_KTEST" => \$post_ktest, "PRE_TEST" => \$pre_test, + "PRE_TEST_DIE" => \$pre_test_die, "POST_TEST" => \$post_test, "BUILD_TYPE" => \$build_type, "BUILD_OPTIONS" => \$build_options, @@ -4347,7 +4349,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n"; if (defined($pre_test)) { - run_command $pre_test; + my $ret = run_command $pre_test; + if (!$ret && defined($pre_test_die) && + $pre_test_die) { + dodie "failed to pre_test\n"; + } } unlink $dmesg; diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 27666b8007edb..cb8227fbd01ed 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -557,6 +557,11 @@ # default (undefined) #PRE_TEST = ${SSH} reboot_to_special_kernel +# To kill the entire test if PRE_TEST is defined but fails set this +# to 1. +# (default 0) +#PRE_TEST_DIE = 1 + # If there is a command you want to run after the individual test case # completes, then you can set this option. # -- GitLab From 167234268cf6cb932ffb180586f3874ae3293a55 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 11:09:23 -0400 Subject: [PATCH 0216/1754] ktest.pl: Add a NOT operator There is a NOT DEFINED operator, but there is not an operator that can negate any other expression. For example: NOT (${FOO} == boot || ${BAR} == run) Add the keyword NOT to allow the ktest.pl config files to negate operators. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index f99cf633ed84f..0d04b8a2b5a2c 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -911,6 +911,12 @@ sub process_expression { } } + if ($val =~ s/^\s*NOT\s+(.*)//) { + my $express = $1; + my $ret = process_expression($name, $express); + return !$ret; + } + if ($val =~ /^\s*0\s*$/) { return 0; } elsif ($val =~ /^\s*\d+\s*$/) { -- GitLab From d6bc29d987336927ff97219d5f661389f33f8f11 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 15:21:15 -0400 Subject: [PATCH 0217/1754] ktest.pl: Just open up the log file once Currently, every write to the log file is done by opening the file, writing to it, then closing the file. This rather expensive. Just open it at the beginning and close it at the end. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 0d04b8a2b5a2c..f20a81bb3abe2 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -509,9 +509,7 @@ EOF sub _logit { if (defined($opt{"LOG_FILE"})) { - open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; - print OUT @_; - close(OUT); + print LOG @_; } } @@ -1780,8 +1778,6 @@ sub run_command { (fail "unable to exec $command" and return 0); if (defined($opt{"LOG_FILE"})) { - open(LOG, ">>$opt{LOG_FILE}") or - dodie "failed to write to log"; $dolog = 1; } @@ -1829,7 +1825,6 @@ sub run_command { } close(CMD); - close(LOG) if ($dolog); close(RD) if ($dord); $end_time = time; @@ -4091,8 +4086,11 @@ if ($#new_configs >= 0) { } } -if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { - unlink $opt{"LOG_FILE"}; +if (defined($opt{"LOG_FILE"})) { + if ($opt{"CLEAR_LOG"}) { + unlink $opt{"LOG_FILE"}; + } + open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; } doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; @@ -4453,14 +4451,16 @@ if ($opt{"POWEROFF_ON_SUCCESS"}) { } -if (defined($opt{"LOG_FILE"})) { - print "\n See $opt{LOG_FILE} for the record of results.\n"; -} - doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; if ($email_when_finished) { send_email("KTEST: Your test has finished!", "$successes of $opt{NUM_TESTS} tests started at $script_start_time were successful!"); } + +if (defined($opt{"LOG_FILE"})) { + print "\n See $opt{LOG_FILE} for the record of results.\n\n"; + close LOG; +} + exit 0; -- GitLab From eefb9d2b8c6a781dd1026b18e37b4bcb50cff440 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 15:29:06 -0400 Subject: [PATCH 0218/1754] ktest.pl: Turn off buffering to the log file The log file should be up to date to whatever is happening in ktest. Disable buffering to the LOG output file handle. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index f20a81bb3abe2..e90e2e7cb72cf 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -11,6 +11,7 @@ use File::Path qw(mkpath); use File::Copy qw(cp); use FileHandle; use FindBin; +use IO::Handle; my $VERSION = "0.2"; @@ -4091,6 +4092,7 @@ if (defined($opt{"LOG_FILE"})) { unlink $opt{"LOG_FILE"}; } open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; + LOG->autoflush(1); } doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; -- GitLab From 4605ad8f4581981787ed22b3a755209c8fe5aa24 Mon Sep 17 00:00:00 2001 From: Mathieu Poirier Date: Tue, 30 Jun 2020 10:31:17 -0600 Subject: [PATCH 0219/1754] remoteproc: ingenic: Move clock handling to prepare/unprepare callbacks This patch moves clock related operations to the remoteproc prepare() and unprepare() callbacks so that the PM runtime framework doesn't have to be involved needlessly. This provides a simpler approach and requires less code. Based on the work from Paul Cercueil published here: https://lore.kernel.org/linux-remoteproc/20191116170846.67220-4-paul@crapouillou.net/ Reviewed-by: Suman Anna Signed-off-by: Mathieu Poirier Link: https://lore.kernel.org/r/20200630163118.3830422-2-mathieu.poirier@linaro.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/ingenic_rproc.c | 84 +++++++++--------------------- 1 file changed, 26 insertions(+), 58 deletions(-) diff --git a/drivers/remoteproc/ingenic_rproc.c b/drivers/remoteproc/ingenic_rproc.c index 189020d77b25c..1c2b21a5d1782 100644 --- a/drivers/remoteproc/ingenic_rproc.c +++ b/drivers/remoteproc/ingenic_rproc.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include "remoteproc_internal.h" @@ -62,6 +61,28 @@ struct vpu { struct device *dev; }; +static int ingenic_rproc_prepare(struct rproc *rproc) +{ + struct vpu *vpu = rproc->priv; + int ret; + + /* The clocks must be enabled for the firmware to be loaded in TCSM */ + ret = clk_bulk_prepare_enable(ARRAY_SIZE(vpu->clks), vpu->clks); + if (ret) + dev_err(vpu->dev, "Unable to start clocks: %d\n", ret); + + return ret; +} + +static int ingenic_rproc_unprepare(struct rproc *rproc) +{ + struct vpu *vpu = rproc->priv; + + clk_bulk_disable_unprepare(ARRAY_SIZE(vpu->clks), vpu->clks); + + return 0; +} + static int ingenic_rproc_start(struct rproc *rproc) { struct vpu *vpu = rproc->priv; @@ -115,6 +136,8 @@ static void *ingenic_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len) } static struct rproc_ops ingenic_rproc_ops = { + .prepare = ingenic_rproc_prepare, + .unprepare = ingenic_rproc_unprepare, .start = ingenic_rproc_start, .stop = ingenic_rproc_stop, .kick = ingenic_rproc_kick, @@ -135,16 +158,6 @@ static irqreturn_t vpu_interrupt(int irq, void *data) return rproc_vq_interrupt(rproc, vring); } -static void ingenic_rproc_disable_clks(void *data) -{ - struct vpu *vpu = data; - - pm_runtime_resume(vpu->dev); - pm_runtime_disable(vpu->dev); - - clk_bulk_disable_unprepare(ARRAY_SIZE(vpu->clks), vpu->clks); -} - static int ingenic_rproc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -206,35 +219,13 @@ static int ingenic_rproc_probe(struct platform_device *pdev) disable_irq(vpu->irq); - /* The clocks must be enabled for the firmware to be loaded in TCSM */ - ret = clk_bulk_prepare_enable(ARRAY_SIZE(vpu->clks), vpu->clks); - if (ret) { - dev_err(dev, "Unable to start clocks\n"); - return ret; - } - - pm_runtime_irq_safe(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - pm_runtime_get_sync(dev); - pm_runtime_use_autosuspend(dev); - - ret = devm_add_action_or_reset(dev, ingenic_rproc_disable_clks, vpu); - if (ret) { - dev_err(dev, "Unable to register action\n"); - goto out_pm_put; - } - ret = devm_rproc_add(dev, rproc); if (ret) { dev_err(dev, "Failed to register remote processor\n"); - goto out_pm_put; + return ret; } -out_pm_put: - pm_runtime_put_autosuspend(dev); - - return ret; + return 0; } static const struct of_device_id ingenic_rproc_of_matches[] = { @@ -243,33 +234,10 @@ static const struct of_device_id ingenic_rproc_of_matches[] = { }; MODULE_DEVICE_TABLE(of, ingenic_rproc_of_matches); -static int __maybe_unused ingenic_rproc_suspend(struct device *dev) -{ - struct vpu *vpu = dev_get_drvdata(dev); - - clk_bulk_disable(ARRAY_SIZE(vpu->clks), vpu->clks); - - return 0; -} - -static int __maybe_unused ingenic_rproc_resume(struct device *dev) -{ - struct vpu *vpu = dev_get_drvdata(dev); - - return clk_bulk_enable(ARRAY_SIZE(vpu->clks), vpu->clks); -} - -static const struct dev_pm_ops __maybe_unused ingenic_rproc_pm = { - SET_RUNTIME_PM_OPS(ingenic_rproc_suspend, ingenic_rproc_resume, NULL) -}; - static struct platform_driver ingenic_rproc_driver = { .probe = ingenic_rproc_probe, .driver = { .name = "ingenic-vpu", -#ifdef CONFIG_PM - .pm = &ingenic_rproc_pm, -#endif .of_match_table = ingenic_rproc_of_matches, }, }; -- GitLab From 49cff1256879d8622d253b6deac2438d6cd33445 Mon Sep 17 00:00:00 2001 From: Mathieu Poirier Date: Tue, 30 Jun 2020 10:31:18 -0600 Subject: [PATCH 0220/1754] Revert "remoteproc: Add support for runtime PM" This reverts commit a99a37f6cd5a74d5b22c08544aa6c5890813c8ba. Removing PM runtime operations from the remoteproc core in order to: 1) Keep all power management operations in platform drivers. That way we do not loose flexibility in an area that is very HW specific. 2) Avoid making the support for remote processor managed by external entities more complex that it already is. 3) Fix regression introduced for the Omap remoteproc driver. Acked-by: Suman Anna Tested-by: Suman Anna Signed-off-by: Mathieu Poirier Link: https://lore.kernel.org/r/20200630163118.3830422-3-mathieu.poirier@linaro.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_core.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 9f04c30c4aaf7..0f95e025ba030 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -1383,12 +1382,6 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) if (ret) return ret; - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - dev_err(dev, "pm_runtime_get_sync failed: %d\n", ret); - return ret; - } - dev_info(dev, "Booting fw image %s, size %zd\n", name, fw->size); /* @@ -1398,7 +1391,7 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) ret = rproc_enable_iommu(rproc); if (ret) { dev_err(dev, "can't enable iommu: %d\n", ret); - goto put_pm_runtime; + return ret; } /* Prepare rproc for firmware loading if needed */ @@ -1452,8 +1445,6 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) rproc_unprepare_device(rproc); disable_iommu: rproc_disable_iommu(rproc); -put_pm_runtime: - pm_runtime_put(dev); return ret; } @@ -1891,8 +1882,6 @@ void rproc_shutdown(struct rproc *rproc) rproc_disable_iommu(rproc); - pm_runtime_put(dev); - /* Free the copy of the resource table */ kfree(rproc->cached_table); rproc->cached_table = NULL; @@ -2183,9 +2172,6 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, rproc->state = RPROC_OFFLINE; - pm_runtime_no_callbacks(&rproc->dev); - pm_runtime_enable(&rproc->dev); - return rproc; put_device: @@ -2205,7 +2191,6 @@ EXPORT_SYMBOL(rproc_alloc); */ void rproc_free(struct rproc *rproc) { - pm_runtime_disable(&rproc->dev); put_device(&rproc->dev); } EXPORT_SYMBOL(rproc_free); -- GitLab From 87ad854dd76ca3534ef2e368265c3566a59e21e0 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 22 Jun 2020 12:19:38 -0700 Subject: [PATCH 0221/1754] dt-bindings: remoteproc: Add Qualcomm PIL info binding Add a devicetree binding for the Qualcomm peripheral image loader relocation information region found in the IMEM. Reviewed-by: Mathieu Poirier Reviewed-by: Rob Herring Reviewed-by: Stephen Boyd Reviewed-by: Vinod Koul Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20200622191942.255460-2-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- .../bindings/remoteproc/qcom,pil-info.yaml | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 Documentation/devicetree/bindings/remoteproc/qcom,pil-info.yaml diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,pil-info.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,pil-info.yaml new file mode 100644 index 0000000000000..87c52316ddbd6 --- /dev/null +++ b/Documentation/devicetree/bindings/remoteproc/qcom,pil-info.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/remoteproc/qcom,pil-info.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm peripheral image loader relocation info binding + +maintainers: + - Bjorn Andersson + +description: + The Qualcomm peripheral image loader relocation memory region, in IMEM, is + used for communicating remoteproc relocation information to post mortem + debugging tools. + +properties: + compatible: + const: qcom,pil-reloc-info + + reg: + maxItems: 1 + +required: + - compatible + - reg + +examples: + - | + imem@146bf000 { + compatible = "syscon", "simple-mfd"; + reg = <0x146bf000 0x1000>; + + #address-cells = <1>; + #size-cells = <1>; + + ranges = <0 0x146bf000 0x1000>; + + pil-reloc@94c { + compatible = "qcom,pil-reloc-info"; + reg = <0x94c 0xc8>; + }; + }; +... -- GitLab From 549b67da660d634e3a4a50a325bd1f5609ddb84b Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 22 Jun 2020 12:19:39 -0700 Subject: [PATCH 0222/1754] remoteproc: qcom: Introduce helper to store pil info in IMEM A region in IMEM is used to communicate load addresses of remoteproc to post mortem debug tools. Implement a helper function that can be used to store this information in order to enable these tools to process collected ramdumps. Reviewed-by: Mathieu Poirier Reviewed-by: Vinod Koul Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20200622191942.255460-3-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/Kconfig | 3 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/qcom_pil_info.c | 129 +++++++++++++++++++++++++++++ drivers/remoteproc/qcom_pil_info.h | 9 ++ 4 files changed, 142 insertions(+) create mode 100644 drivers/remoteproc/qcom_pil_info.c create mode 100644 drivers/remoteproc/qcom_pil_info.h diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index c4d1731295ebc..f4bd96d1a1a34 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -116,6 +116,9 @@ config KEYSTONE_REMOTEPROC It's safe to say N here if you're not interested in the Keystone DSPs or just want to use a bare minimum kernel. +config QCOM_PIL_INFO + tristate + config QCOM_RPROC_COMMON tristate diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index e8b886e511f0b..fe398f82d5500 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o obj-$(CONFIG_KEYSTONE_REMOTEPROC) += keystone_remoteproc.o +obj-$(CONFIG_QCOM_PIL_INFO) += qcom_pil_info.o obj-$(CONFIG_QCOM_RPROC_COMMON) += qcom_common.o obj-$(CONFIG_QCOM_Q6V5_COMMON) += qcom_q6v5.o obj-$(CONFIG_QCOM_Q6V5_ADSP) += qcom_q6v5_adsp.o diff --git a/drivers/remoteproc/qcom_pil_info.c b/drivers/remoteproc/qcom_pil_info.c new file mode 100644 index 0000000000000..0536e39046691 --- /dev/null +++ b/drivers/remoteproc/qcom_pil_info.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020 Linaro Ltd. + */ +#include +#include +#include +#include +#include "qcom_pil_info.h" + +/* + * The PIL relocation information region is used to communicate memory regions + * occupied by co-processor firmware for post mortem crash analysis. + * + * It consists of an array of entries with an 8 byte textual identifier of the + * region followed by a 64 bit base address and 32 bit size, both little + * endian. + */ +#define PIL_RELOC_NAME_LEN 8 +#define PIL_RELOC_ENTRY_SIZE (PIL_RELOC_NAME_LEN + sizeof(__le64) + sizeof(__le32)) + +struct pil_reloc { + void __iomem *base; + size_t num_entries; +}; + +static struct pil_reloc _reloc __read_mostly; +static DEFINE_MUTEX(pil_reloc_lock); + +static int qcom_pil_info_init(void) +{ + struct device_node *np; + struct resource imem; + void __iomem *base; + int ret; + + /* Already initialized? */ + if (_reloc.base) + return 0; + + np = of_find_compatible_node(NULL, NULL, "qcom,pil-reloc-info"); + if (!np) + return -ENOENT; + + ret = of_address_to_resource(np, 0, &imem); + of_node_put(np); + if (ret < 0) + return ret; + + base = ioremap(imem.start, resource_size(&imem)); + if (!base) { + pr_err("failed to map PIL relocation info region\n"); + return -ENOMEM; + } + + memset_io(base, 0, resource_size(&imem)); + + _reloc.base = base; + _reloc.num_entries = resource_size(&imem) / PIL_RELOC_ENTRY_SIZE; + + return 0; +} + +/** + * qcom_pil_info_store() - store PIL information of image in IMEM + * @image: name of the image + * @base: base address of the loaded image + * @size: size of the loaded image + * + * Return: 0 on success, negative errno on failure + */ +int qcom_pil_info_store(const char *image, phys_addr_t base, size_t size) +{ + char buf[PIL_RELOC_NAME_LEN]; + void __iomem *entry; + int ret; + int i; + + mutex_lock(&pil_reloc_lock); + ret = qcom_pil_info_init(); + if (ret < 0) { + mutex_unlock(&pil_reloc_lock); + return ret; + } + + for (i = 0; i < _reloc.num_entries; i++) { + entry = _reloc.base + i * PIL_RELOC_ENTRY_SIZE; + + memcpy_fromio(buf, entry, PIL_RELOC_NAME_LEN); + + /* + * An empty record means we didn't find it, given that the + * records are packed. + */ + if (!buf[0]) + goto found_unused; + + if (!strncmp(buf, image, PIL_RELOC_NAME_LEN)) + goto found_existing; + } + + pr_warn("insufficient PIL info slots\n"); + mutex_unlock(&pil_reloc_lock); + return -ENOMEM; + +found_unused: + memcpy_toio(entry, image, PIL_RELOC_NAME_LEN); +found_existing: + /* Use two writel() as base is only aligned to 4 bytes on odd entries */ + writel(base, entry + PIL_RELOC_NAME_LEN); + writel(base >> 32, entry + PIL_RELOC_NAME_LEN + 4); + writel(size, entry + PIL_RELOC_NAME_LEN + sizeof(__le64)); + mutex_unlock(&pil_reloc_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(qcom_pil_info_store); + +static void __exit pil_reloc_exit(void) +{ + mutex_lock(&pil_reloc_lock); + iounmap(_reloc.base); + _reloc.base = NULL; + mutex_unlock(&pil_reloc_lock); +} +module_exit(pil_reloc_exit); + +MODULE_DESCRIPTION("Qualcomm PIL relocation info"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/remoteproc/qcom_pil_info.h b/drivers/remoteproc/qcom_pil_info.h new file mode 100644 index 0000000000000..0dce6142935ee --- /dev/null +++ b/drivers/remoteproc/qcom_pil_info.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __QCOM_PIL_INFO_H__ +#define __QCOM_PIL_INFO_H__ + +#include + +int qcom_pil_info_store(const char *image, phys_addr_t base, size_t size); + +#endif -- GitLab From d4c78d2167913b3f7af0d2189fd3d76f6614a1bf Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 22 Jun 2020 12:19:40 -0700 Subject: [PATCH 0223/1754] remoteproc: qcom: Update PIL relocation info on load Update the PIL relocation information in IMEM with information about where the firmware for various remoteprocs are loaded. Reviewed-by: Vinod Koul Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20200622191942.255460-4-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/Kconfig | 5 +++++ drivers/remoteproc/qcom_q6v5_adsp.c | 16 +++++++++++++--- drivers/remoteproc/qcom_q6v5_mss.c | 3 +++ drivers/remoteproc/qcom_q6v5_pas.c | 15 ++++++++++++--- drivers/remoteproc/qcom_q6v5_wcss.c | 14 +++++++++++--- drivers/remoteproc/qcom_wcnss.c | 14 +++++++++++--- 6 files changed, 55 insertions(+), 12 deletions(-) diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index f4bd96d1a1a34..3e8d5d1a2b9ee 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -135,6 +135,7 @@ config QCOM_Q6V5_ADSP depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n depends on QCOM_SYSMON || QCOM_SYSMON=n select MFD_SYSCON + select QCOM_PIL_INFO select QCOM_MDT_LOADER select QCOM_Q6V5_COMMON select QCOM_RPROC_COMMON @@ -151,6 +152,7 @@ config QCOM_Q6V5_MSS depends on QCOM_SYSMON || QCOM_SYSMON=n select MFD_SYSCON select QCOM_MDT_LOADER + select QCOM_PIL_INFO select QCOM_Q6V5_COMMON select QCOM_Q6V5_IPA_NOTIFY select QCOM_RPROC_COMMON @@ -167,6 +169,7 @@ config QCOM_Q6V5_PAS depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n depends on QCOM_SYSMON || QCOM_SYSMON=n select MFD_SYSCON + select QCOM_PIL_INFO select QCOM_MDT_LOADER select QCOM_Q6V5_COMMON select QCOM_RPROC_COMMON @@ -185,6 +188,7 @@ config QCOM_Q6V5_WCSS depends on QCOM_SYSMON || QCOM_SYSMON=n select MFD_SYSCON select QCOM_MDT_LOADER + select QCOM_PIL_INFO select QCOM_Q6V5_COMMON select QCOM_RPROC_COMMON select QCOM_SCM @@ -218,6 +222,7 @@ config QCOM_WCNSS_PIL depends on QCOM_SMEM depends on QCOM_SYSMON || QCOM_SYSMON=n select QCOM_MDT_LOADER + select QCOM_PIL_INFO select QCOM_RPROC_COMMON select QCOM_SCM help diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c index d2a2574dcf354..efb2c1aa80a3c 100644 --- a/drivers/remoteproc/qcom_q6v5_adsp.c +++ b/drivers/remoteproc/qcom_q6v5_adsp.c @@ -26,6 +26,7 @@ #include #include "qcom_common.h" +#include "qcom_pil_info.h" #include "qcom_q6v5.h" #include "remoteproc_internal.h" @@ -82,6 +83,7 @@ struct qcom_adsp { unsigned int halt_lpass; int crash_reason_smem; + const char *info_name; struct completion start_done; struct completion stop_done; @@ -164,10 +166,17 @@ static int qcom_adsp_shutdown(struct qcom_adsp *adsp) static int adsp_load(struct rproc *rproc, const struct firmware *fw) { struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv; + int ret; + + ret = qcom_mdt_load_no_init(adsp->dev, fw, rproc->firmware, 0, + adsp->mem_region, adsp->mem_phys, + adsp->mem_size, &adsp->mem_reloc); + if (ret) + return ret; + + qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size); - return qcom_mdt_load_no_init(adsp->dev, fw, rproc->firmware, 0, - adsp->mem_region, adsp->mem_phys, adsp->mem_size, - &adsp->mem_reloc); + return 0; } static int adsp_start(struct rproc *rproc) @@ -436,6 +445,7 @@ static int adsp_probe(struct platform_device *pdev) adsp = (struct qcom_adsp *)rproc->priv; adsp->dev = &pdev->dev; adsp->rproc = rproc; + adsp->info_name = desc->sysmon_name; platform_set_drvdata(pdev, adsp); ret = adsp_alloc_memory_region(adsp); diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c index feb70283b6a21..dd37e462ed615 100644 --- a/drivers/remoteproc/qcom_q6v5_mss.c +++ b/drivers/remoteproc/qcom_q6v5_mss.c @@ -29,6 +29,7 @@ #include "remoteproc_internal.h" #include "qcom_common.h" +#include "qcom_pil_info.h" #include "qcom_q6v5.h" #include @@ -1189,6 +1190,8 @@ static int q6v5_mpss_load(struct q6v5 *qproc) else if (ret < 0) dev_err(qproc->dev, "MPSS authentication failed: %d\n", ret); + qcom_pil_info_store("modem", qproc->mpss_phys, qproc->mpss_size); + release_firmware: release_firmware(fw); out: diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 61791a03f648c..3837f23995e05 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -25,6 +25,7 @@ #include #include "qcom_common.h" +#include "qcom_pil_info.h" #include "qcom_q6v5.h" #include "remoteproc_internal.h" @@ -64,6 +65,7 @@ struct qcom_adsp { int pas_id; int crash_reason_smem; bool has_aggre2_clk; + const char *info_name; struct completion start_done; struct completion stop_done; @@ -117,11 +119,17 @@ static void adsp_pds_disable(struct qcom_adsp *adsp, struct device **pds, static int adsp_load(struct rproc *rproc, const struct firmware *fw) { struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv; + int ret; - return qcom_mdt_load(adsp->dev, fw, rproc->firmware, adsp->pas_id, - adsp->mem_region, adsp->mem_phys, adsp->mem_size, - &adsp->mem_reloc); + ret = qcom_mdt_load(adsp->dev, fw, rproc->firmware, adsp->pas_id, + adsp->mem_region, adsp->mem_phys, adsp->mem_size, + &adsp->mem_reloc); + if (ret) + return ret; + qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size); + + return 0; } static int adsp_start(struct rproc *rproc) @@ -405,6 +413,7 @@ static int adsp_probe(struct platform_device *pdev) adsp->rproc = rproc; adsp->pas_id = desc->pas_id; adsp->has_aggre2_clk = desc->has_aggre2_clk; + adsp->info_name = desc->sysmon_name; platform_set_drvdata(pdev, adsp); device_wakeup_enable(adsp->dev); diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c index 88c76b9417fab..8846ef0b0f1a2 100644 --- a/drivers/remoteproc/qcom_q6v5_wcss.c +++ b/drivers/remoteproc/qcom_q6v5_wcss.c @@ -14,6 +14,7 @@ #include #include #include "qcom_common.h" +#include "qcom_pil_info.h" #include "qcom_q6v5.h" #define WCSS_CRASH_REASON 421 @@ -424,10 +425,17 @@ static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, size_t len) static int q6v5_wcss_load(struct rproc *rproc, const struct firmware *fw) { struct q6v5_wcss *wcss = rproc->priv; + int ret; + + ret = qcom_mdt_load_no_init(wcss->dev, fw, rproc->firmware, + 0, wcss->mem_region, wcss->mem_phys, + wcss->mem_size, &wcss->mem_reloc); + if (ret) + return ret; + + qcom_pil_info_store("wcnss", wcss->mem_phys, wcss->mem_size); - return qcom_mdt_load_no_init(wcss->dev, fw, rproc->firmware, - 0, wcss->mem_region, wcss->mem_phys, - wcss->mem_size, &wcss->mem_reloc); + return ret; } static const struct rproc_ops q6v5_wcss_ops = { diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c index 5d65e1a9329a0..e2573f79a137d 100644 --- a/drivers/remoteproc/qcom_wcnss.c +++ b/drivers/remoteproc/qcom_wcnss.c @@ -27,6 +27,7 @@ #include "qcom_common.h" #include "remoteproc_internal.h" +#include "qcom_pil_info.h" #include "qcom_wcnss.h" #define WCNSS_CRASH_REASON_SMEM 422 @@ -145,10 +146,17 @@ void qcom_wcnss_assign_iris(struct qcom_wcnss *wcnss, static int wcnss_load(struct rproc *rproc, const struct firmware *fw) { struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv; + int ret; + + ret = qcom_mdt_load(wcnss->dev, fw, rproc->firmware, WCNSS_PAS_ID, + wcnss->mem_region, wcnss->mem_phys, + wcnss->mem_size, &wcnss->mem_reloc); + if (ret) + return ret; + + qcom_pil_info_store("wcnss", wcnss->mem_phys, wcnss->mem_size); - return qcom_mdt_load(wcnss->dev, fw, rproc->firmware, WCNSS_PAS_ID, - wcnss->mem_region, wcnss->mem_phys, - wcnss->mem_size, &wcnss->mem_reloc); + return 0; } static void wcnss_indicate_nv_download(struct qcom_wcnss *wcnss) -- GitLab From 304d7a90c43f7471fb481e6b1e2b47fef2a02b8c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:53 -0700 Subject: [PATCH 0224/1754] perf parse-events: Disable a subset of flex warnings Rather than disable all warnings with -w, disable specific warnings. Predicate enabling the warnings on more recent flex versions. Tested with GCC 9.3.0 and clang 9.0.1. Committer notes: The full set of compilers, gcc and clang that this will be tested on will be on the signed tag when this change goes upstream. Added -Wno-misleading-indentation to the flex_flags to overcome this on opensuse tumbleweed when building with clang: CC /tmp/build/perf/util/parse-events-flex.o CC /tmp/build/perf/util/pmu.o /tmp/build/perf/util/parse-events-flex.c:5038:13: error: misleading indentation; statement is not part of the previous 'if' [-Werror,-Wmisleading-indentation] if ( ! yyg->yy_state_buf ) ^ /tmp/build/perf/util/parse-events-flex.c:5036:9: note: previous statement is here if ( ! yyg->yy_state_buf ) ^ And we need to use this to redirect stderr to stdin and then grep in a way that is acceptable for BusyBox shell: 2>&1 | Previously I was using: |& Which seems to be bash specific. Added -Wno-sign-compare to overcome this on systems such as centos:7: CC /tmp/build/perf/util/parse-events-flex.o CC /tmp/build/perf/util/pmu.o CC /tmp/build/perf/util/pmu-flex.o util/parse-events.l: In function 'parse_events_lex': /tmp/build/perf/util/parse-events-flex.c:193:36: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare] for ( yyl = n; yyl < yyleng; ++yyl )\ ^ /tmp/build/perf/util/parse-events-flex.c:204:9: note: in expansion of macro 'YY_LESS_LINENO' Added -Wno-unused-parameter to overcome this in systems such as centos:7: CC /tmp/build/perf/util/parse-events-flex.o CC /tmp/build/perf/util/pmu.o /tmp/build/perf/util/parse-events-flex.c: In function 'yy_fatal_error': /tmp/build/perf/util/parse-events-flex.c:6265:58: error: unused parameter 'yyscanner' [-Werror=unused-parameter] static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) ^ Added -Wno-missing-declarations to build in systems such as centos:6: /tmp/build/perf/util/parse-events-flex.c:6313: error: no previous prototype for 'parse_events_get_column' /tmp/build/perf/util/parse-events-flex.c:6389: error: no previous prototype for 'parse_events_set_column' And -Wno-missing-prototypes to cover older compilers: -Wmissing-prototypes (C only) Warn if a global function is defined without a previous prototype declaration. This warning is issued even if the definition itself provides a prototype. The aim is to detect global functions that fail to be declared in header files. -Wmissing-declarations (C only) Warn if a global function is defined without a previous declaration. Do so even if the definition itself provides a prototype. Use this option to detect global functions that are not declared in header files. Older C compilers lack -Wno-misleading-indentation, check if it is available before using it. Also needed to check just the first two levels of the flex version, as the patch was assuming that all versions were of the form x.y.z, and there are several cases where it is just x.y, breaking the build. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-8-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 504a6bb991ba3..cd86a3068eab4 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -221,9 +221,19 @@ $(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.h: util/pmu.y $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_ -CFLAGS_parse-events-flex.o += -w -CFLAGS_pmu-flex.o += -w -CFLAGS_expr-flex.o += -w +FLEX_GE_26 := $(shell expr $(shell $(FLEX) --version | sed -e 's/flex \([0-9]\+\).\([0-9]\+\)/\1\2/g') \>\= 26) +ifeq ($(FLEX_GE_26),1) + flex_flags := -Wno-switch-enum -Wno-switch-default -Wno-unused-function -Wno-redundant-decls -Wno-sign-compare -Wno-unused-parameter -Wno-missing-prototypes -Wno-missing-declarations + CC_HASNT_MISLEADING_INDENTATION := $(shell echo "int main(void) { return 0 }" | $(CC) -Werror -Wno-misleading-indentation -o /dev/null -xc - 2>&1 | grep -q -- -Wno-misleading-indentation ; echo $$?) + ifeq ($(CC_HASNT_MISLEADING_INDENTATION), 1) + flex_flags += -Wno-misleading-indentation + endif +else + flex_flags := -w +endif +CFLAGS_parse-events-flex.o += $(flex_flags) +CFLAGS_pmu-flex.o += $(flex_flags) +CFLAGS_expr-flex.o += $(flex_flags) CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -w CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w CFLAGS_expr-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w -- GitLab From 1f16fcad688552d442ddf1c5d3d8d4152d9bf4af Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:56 -0700 Subject: [PATCH 0225/1754] perf parse-events: Disable a subset of bison warnings Rather than disable all warnings with -w, disable specific warnings. Predicate enabling the warnings on a recent version of bison. Tested with GCC 9.3.0 and clang 9.0.1. Committer testing: The full set of compilers, gcc and clang that this will be tested on will be on the signed tag when this change goes upstream. Had to add -Wno-switch-enum to build on opensuse tumbleweed: /tmp/build/perf/util/parse-events-bison.c: In function 'yydestruct': /tmp/build/perf/util/parse-events-bison.c:1200:3: error: enumeration value 'YYSYMBOL_YYEMPTY' not handled in switch [-Werror=switch-enum] 1200 | switch (yykind) | ^~~~~~ /tmp/build/perf/util/parse-events-bison.c:1200:3: error: enumeration value 'YYSYMBOL_YYEOF' not handled in switch [-Werror=switch-enum] Also replace -Wno-error=implicit-function-declaration with -Wno-implicit-function-declaration. Also needed to check just the first two levels of the bison version, as the patch was assuming that all versions were of the form x.y.z, and there are several cases where it is just x.y, breaking the build. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-11-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index cd86a3068eab4..380e6a9f564dc 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -234,9 +234,17 @@ endif CFLAGS_parse-events-flex.o += $(flex_flags) CFLAGS_pmu-flex.o += $(flex_flags) CFLAGS_expr-flex.o += $(flex_flags) -CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -w -CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w -CFLAGS_expr-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w + +bison_flags := -DYYENABLE_NLS=0 +BISON_GE_35 := $(shell expr $(shell $(BISON) --version | grep bison | sed -e 's/.\+ \([0-9]\+\).\([0-9]\+\)/\1\2/g') \>\= 35) +ifeq ($(BISON_GE_35),1) + bison_flags += -Wno-unused-parameter -Wno-nested-externs -Wno-implicit-function-declaration -Wno-switch-enum +else + bison_flags += -w +endif +CFLAGS_parse-events-bison.o += $(bison_flags) +CFLAGS_pmu-bison.o += -DYYLTYPE_IS_TRIVIAL=0 $(bison_flags) +CFLAGS_expr-bison.o += -DYYLTYPE_IS_TRIVIAL=0 $(bison_flags) $(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c -- GitLab From 34148b13eec9c738327f8c8f84f468f4694b17a3 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 18:15:07 -0400 Subject: [PATCH 0226/1754] ktest.pl: Add the log of last test in email on failure If a failure happens and an email is sent, show the contents of the log of the last test that failed in the email. Link: http://lore.kernel.org/r/20200701231756.619246244@goodmis.org Reviewed-by: Greg Kroah-Hartman Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 42 ++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index e90e2e7cb72cf..8a4a33492952b 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -82,6 +82,8 @@ my %default = ( "IGNORE_UNUSED" => 0, ); +my $test_log_start = 0; + my $ktest_config = "ktest.conf"; my $version; my $have_version = 0; @@ -1492,8 +1494,21 @@ sub dodie { if ($email_on_error) { my $name = get_test_name; + my $log_file; + + if (defined($opt{"LOG_FILE"})) { + $log_file = "$tmpdir/log"; + open (L, "$opt{LOG_FILE}") or die "Can't open $opt{LOG_FILE} to read)"; + open (O, "> $tmpdir/log") or die "Can't open $tmpdir/log\n"; + seek(L, $test_log_start, 0); + while () { + print O; + } + close O; + close L; + } send_email("KTEST: critical failure for test $i [$name]", - "Your test started at $script_start_time has failed with:\n@_\n"); + "Your test started at $script_start_time has failed with:\n@_\n", $log_file); } if ($monitor_cnt) { @@ -4185,7 +4200,7 @@ sub find_mailer { } sub do_send_mail { - my ($subject, $message) = @_; + my ($subject, $message, $file) = @_; if (!defined($mail_path)) { # find the mailer @@ -4195,16 +4210,30 @@ sub do_send_mail { } } + my $header_file = "$tmpdir/header"; + open (HEAD, ">$header_file") or die "Can not create $header_file\n"; + print HEAD "To: $mailto\n"; + print HEAD "Subject: $subject\n\n"; + print HEAD "$message\n"; + close HEAD; + if (!defined($mail_command)) { if ($mailer eq "mail" || $mailer eq "mailx") { - $mail_command = "\$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO <<< \'\$MESSAGE\'"; + $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO"; } elsif ($mailer eq "sendmail" ) { - $mail_command = "echo \'Subject: \$SUBJECT\n\n\$MESSAGE\' | \$MAIL_PATH/\$MAILER -t \$MAILTO"; + $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -t \$MAILTO"; } else { die "\nYour mailer: $mailer is not supported.\n"; } } + if (defined($file)) { + $mail_command =~ s/\$BODY_FILE/$file/g; + } else { + $mail_command =~ s/\$BODY_FILE//g; + } + + $mail_command =~ s/\$HEADER_FILE/$header_file/g; $mail_command =~ s/\$MAILER/$mailer/g; $mail_command =~ s/\$MAIL_PATH/$mail_path/g; $mail_command =~ s/\$MAILTO/$mailto/g; @@ -4352,6 +4381,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { } doprint "\n\n"; + + if (defined($opt{"LOG_FILE"})) { + $test_log_start = tell(LOG); + } + doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n"; if (defined($pre_test)) { -- GitLab From f986900209093f5de887d6c342139df6ebec04ac Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 18:34:10 -0400 Subject: [PATCH 0227/1754] ktest.pl: Add MAIL_MAX_SIZE to limit the amount of log emailed Add the ktest config option MAIL_MAX_SIZE that will limit the size of the log file that is placed into the email on failure. Link: https://lore.kernel.org/r/20200701231756.790637968@goodmis.org Reviewed-by: Greg Kroah-Hartman Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 12 +++++++++++- tools/testing/ktest/sample.conf | 13 +++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 8a4a33492952b..36db5b0b36475 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -227,6 +227,7 @@ my $dirname = $FindBin::Bin; my $mailto; my $mailer; my $mail_path; +my $mail_max_size; my $mail_command; my $email_on_error; my $email_when_finished; @@ -263,6 +264,7 @@ my %option_map = ( "MAILTO" => \$mailto, "MAILER" => \$mailer, "MAIL_PATH" => \$mail_path, + "MAIL_MAX_SIZE" => \$mail_max_size, "MAIL_COMMAND" => \$mail_command, "EMAIL_ON_ERROR" => \$email_on_error, "EMAIL_WHEN_FINISHED" => \$email_when_finished, @@ -1497,10 +1499,18 @@ sub dodie { my $log_file; if (defined($opt{"LOG_FILE"})) { + my $size = 0; + if (defined($mail_max_size)) { + my $log_size = tell LOG; + $log_size -= $test_log_start; + if ($log_size > $mail_max_size) { + $size = $log_size - $mail_max_size; + } + } $log_file = "$tmpdir/log"; open (L, "$opt{LOG_FILE}") or die "Can't open $opt{LOG_FILE} to read)"; open (O, "> $tmpdir/log") or die "Can't open $tmpdir/log\n"; - seek(L, $test_log_start, 0); + seek(L, $test_log_start + $size, 0); while () { print O; } diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index cb8227fbd01ed..5e7d1d7297529 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -442,6 +442,19 @@ # Users can cancel the test by Ctrl^C # (default 0) #EMAIL_WHEN_CANCELED = 1 +# +# If a test ends with an error and EMAIL_ON_ERROR is set as well +# as a LOG_FILE is defined, then the log of the failing test will +# be included in the email that is sent. +# It is possible that the log may be very large, in which case, +# only the last amount of the log should be sent. To limit how +# much of the log is sent, set MAIL_MAX_SIZE. This will be the +# size in bytes of the last portion of the log of the failed +# test file. That is, if this is set to 100000, then only the +# last 100 thousand bytes of the log file will be included in +# the email. +# (default undef) +#MAIL_MAX_SIZE = 1000000 # Start a test setup. If you leave this off, all options # will be default and the test will run once. -- GitLab From 3180cfabf6fbf982ca6d1a6eb56334647cc1416b Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Mon, 29 Jun 2020 13:41:23 +0200 Subject: [PATCH 0228/1754] rtc: cpcap: fix range Unbreak CPCAP driver, which has one more bit in the day counter increasing the max. range from 2014 to 2058. The original commit introducing the range limit was obviously wrong, since the driver has only been written in 2017 (3 years after 14 bits would have run out). Fixes: d2377f8cc5a7 ("rtc: cpcap: set range") Reported-by: Sicelo A. Mhlongo Reported-by: Dev Null Signed-off-by: Sebastian Reichel Signed-off-by: Alexandre Belloni Tested-by: Merlijn Wajer Acked-by: Tony Lindgren Acked-by: Merlijn Wajer Link: https://lore.kernel.org/r/20200629114123.27956-1-sebastian.reichel@collabora.com --- drivers/rtc/rtc-cpcap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-cpcap.c b/drivers/rtc/rtc-cpcap.c index a603f1f211250..800667d73a6fb 100644 --- a/drivers/rtc/rtc-cpcap.c +++ b/drivers/rtc/rtc-cpcap.c @@ -261,7 +261,7 @@ static int cpcap_rtc_probe(struct platform_device *pdev) return PTR_ERR(rtc->rtc_dev); rtc->rtc_dev->ops = &cpcap_rtc_ops; - rtc->rtc_dev->range_max = (1 << 14) * SECS_PER_DAY - 1; + rtc->rtc_dev->range_max = (timeu64_t) (DAY_MASK + 1) * SECS_PER_DAY - 1; err = cpcap_get_vendor(dev, rtc->regmap, &rtc->vendor); if (err) -- GitLab From 05513a706b4f8f978c0ecc97b6d99793fbaaaf17 Mon Sep 17 00:00:00 2001 From: "Tales L. da Aparecida" Date: Tue, 23 Jun 2020 22:21:19 -0300 Subject: [PATCH 0229/1754] rtc: imxdi: fix trivial typos Fix typos 'pionter' -> 'pointer' and 'softwere' -> 'software' Signed-off-by: Tales L. da Aparecida Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20200624012119.54768-1-tales.aparecida@gmail.com --- drivers/rtc/rtc-imxdi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index f21dc6b16d88a..8d141d8a5490b 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -95,7 +95,7 @@ /** * struct imxdi_dev - private imxdi rtc data - * @pdev: pionter to platform dev + * @pdev: pointer to platform dev * @rtc: pointer to rtc struct * @ioaddr: IO registers pointer * @clk: input reference clock @@ -350,7 +350,7 @@ static int di_handle_invalid_and_failure_state(struct imxdi_dev *imxdi, u32 dsr) * the tamper register is locked. We cannot disable the * tamper detection. The TDCHL can only be reset by a * DRYICE POR, but we cannot force a DRYICE POR in - * softwere because we are still in "FAILURE STATE". + * software because we are still in "FAILURE STATE". * We need a DRYICE POR via battery power cycling.... */ /* -- GitLab From 482dcb2a04fdf6d4306e40f2b0537a313a466558 Mon Sep 17 00:00:00 2001 From: Frieder Schrempf Date: Thu, 2 Jul 2020 14:05:50 +0000 Subject: [PATCH 0230/1754] mtd: spi-nor: macronix: Add support for MX25R1635F The MX25R1635F is the smaller sibling of the MX25R3235F that is already supported. It's only half the size (16Mb). It was tested on the Kontron Electronics i.MX8MM SoM (N8010) using raw read and write from and to the mtd device and the 'flash_erase' command. Signed-off-by: Frieder Schrempf [tudor.ambarus@microchip.com: update subject] Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20200702140523.6811-1-frieder.schrempf@kontron.de --- drivers/mtd/spi-nor/macronix.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c index 96735d83c77c3..0ae0815a3633b 100644 --- a/drivers/mtd/spi-nor/macronix.c +++ b/drivers/mtd/spi-nor/macronix.c @@ -52,6 +52,9 @@ static const struct flash_info macronix_parts[] = { { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, + { "mx25r1635f", INFO(0xc22815, 0, 64 * 1024, 32, + SECT_4K | SPI_NOR_DUAL_READ | + SPI_NOR_QUAD_READ) }, { "mx25r3235f", INFO(0xc22816, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -- GitLab From 0ee2872f105b997ba5f09f7fdae542e4cbc1d676 Mon Sep 17 00:00:00 2001 From: Sven Van Asbroeck Date: Mon, 29 Jun 2020 15:53:06 -0400 Subject: [PATCH 0231/1754] mtd: spi-nor: winbond: Add support for w25q64jvm This chip is (nearly) identical to the Winbond w25q64 which is already supported by Linux. Compared to the w25q64, the 'jvm' has a different JEDEC ID. Signed-off-by: Sven Van Asbroeck [tudor.ambarus@microchip.com: Order entry alphabetically, update subject, update Sven's email address] Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20200629195306.1030-1-TheSven73@gmail.com --- drivers/mtd/spi-nor/winbond.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 5062af10f1389..a5eb1d56cb881 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -68,6 +68,7 @@ static const struct flash_info winbond_parts[] = { { "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, + { "w25q64jvm", INFO(0xef7017, 0, 64 * 1024, 128, SECT_4K) }, { "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, -- GitLab From f80531c8217c5b348058a0280f3be05835abd737 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 11 Jun 2020 14:05:34 +0300 Subject: [PATCH 0232/1754] i2c: Use separate MODULE_AUTHOR() statements for multiple authors Modules with multiple authors should use multiple MODULE_AUTHOR() statements according to comment in include/linux/module.h. Split the i2c modules with multiple authors to use multiple MODULE_AUTHOR() statements. Signed-off-by: Jarkko Nikula Reviewed-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/algos/i2c-algo-pca.c | 4 ++-- drivers/i2c/busses/i2c-ali1535.c | 8 ++++---- drivers/i2c/busses/i2c-ali15x3.c | 6 +++--- drivers/i2c/busses/i2c-emev2.c | 3 ++- drivers/i2c/busses/i2c-i801.c | 3 ++- drivers/i2c/busses/i2c-nomadik.c | 3 ++- drivers/i2c/busses/i2c-piix4.c | 4 ++-- drivers/i2c/busses/i2c-pnx.c | 3 ++- drivers/i2c/busses/i2c-sh_mobile.c | 3 ++- drivers/i2c/busses/i2c-sibyte.c | 3 ++- drivers/i2c/busses/i2c-sirf.c | 4 ++-- drivers/i2c/busses/i2c-viapro.c | 6 +++--- drivers/i2c/i2c-dev.c | 4 ++-- 13 files changed, 30 insertions(+), 24 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index 7f10312d1b88f..8620963e442c2 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -541,8 +541,8 @@ int i2c_pca_add_numbered_bus(struct i2c_adapter *adap) } EXPORT_SYMBOL(i2c_pca_add_numbered_bus); -MODULE_AUTHOR("Ian Campbell , " - "Wolfram Sang "); +MODULE_AUTHOR("Ian Campbell "); +MODULE_AUTHOR("Wolfram Sang "); MODULE_DESCRIPTION("I2C-Bus PCA9564/PCA9665 algorithm"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index a43deea390f5a..fb93152845f43 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -519,9 +519,9 @@ static struct pci_driver ali1535_driver = { module_pci_driver(ali1535_driver); -MODULE_AUTHOR("Frodo Looijaard , " - "Philip Edelbrock , " - "Mark D. Studebaker " - "and Dan Eaton "); +MODULE_AUTHOR("Frodo Looijaard "); +MODULE_AUTHOR("Philip Edelbrock "); +MODULE_AUTHOR("Mark D. Studebaker "); +MODULE_AUTHOR("Dan Eaton "); MODULE_DESCRIPTION("ALI1535 SMBus driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index 02185a1cfa775..cc58feacd0821 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -502,8 +502,8 @@ static struct pci_driver ali15x3_driver = { module_pci_driver(ali15x3_driver); -MODULE_AUTHOR ("Frodo Looijaard , " - "Philip Edelbrock , " - "and Mark D. Studebaker "); +MODULE_AUTHOR("Frodo Looijaard "); +MODULE_AUTHOR("Philip Edelbrock "); +MODULE_AUTHOR("Mark D. Studebaker "); MODULE_DESCRIPTION("ALI15X3 SMBus driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-emev2.c b/drivers/i2c/busses/i2c-emev2.c index 1a319352e51b4..a08554c1a5704 100644 --- a/drivers/i2c/busses/i2c-emev2.c +++ b/drivers/i2c/busses/i2c-emev2.c @@ -442,6 +442,7 @@ static struct platform_driver em_i2c_driver = { module_platform_driver(em_i2c_driver); MODULE_DESCRIPTION("EMEV2 I2C bus driver"); -MODULE_AUTHOR("Ian Molton and Wolfram Sang "); +MODULE_AUTHOR("Ian Molton"); +MODULE_AUTHOR("Wolfram Sang "); MODULE_LICENSE("GPL v2"); MODULE_DEVICE_TABLE(of, em_i2c_ids); diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index fea644921a768..1fc7ae77753d6 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1986,7 +1986,8 @@ static void __exit i2c_i801_exit(void) pci_unregister_driver(&i801_driver); } -MODULE_AUTHOR("Mark D. Studebaker , Jean Delvare "); +MODULE_AUTHOR("Mark D. Studebaker "); +MODULE_AUTHOR("Jean Delvare "); MODULE_DESCRIPTION("I801 SMBus driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index e1e8d4ef9aa72..d4b1b0865f676 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -1122,6 +1122,7 @@ static void __exit nmk_i2c_exit(void) subsys_initcall(nmk_i2c_init); module_exit(nmk_i2c_exit); -MODULE_AUTHOR("Sachin Verma, Srinidhi KASAGAR"); +MODULE_AUTHOR("Sachin Verma"); +MODULE_AUTHOR("Srinidhi KASAGAR"); MODULE_DESCRIPTION("Nomadik/Ux500 I2C driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 69740a4ff1db2..8c1b31ed0c429 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -1032,7 +1032,7 @@ static struct pci_driver piix4_driver = { module_pci_driver(piix4_driver); -MODULE_AUTHOR("Frodo Looijaard and " - "Philip Edelbrock "); +MODULE_AUTHOR("Frodo Looijaard "); +MODULE_AUTHOR("Philip Edelbrock "); MODULE_DESCRIPTION("PIIX4 SMBus driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 5d7207c10f1dc..8c4ec7f13f5ab 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -781,7 +781,8 @@ static void __exit i2c_adap_pnx_exit(void) platform_driver_unregister(&i2c_pnx_driver); } -MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev "); +MODULE_AUTHOR("Vitaly Wool"); +MODULE_AUTHOR("Dennis Kovalev "); MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:pnx-i2c"); diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 2cca1b21e26e8..cab7255599991 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -932,6 +932,7 @@ static void __exit sh_mobile_i2c_adap_exit(void) module_exit(sh_mobile_i2c_adap_exit); MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver"); -MODULE_AUTHOR("Magnus Damm and Wolfram Sang"); +MODULE_AUTHOR("Magnus Damm"); +MODULE_AUTHOR("Wolfram Sang"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:i2c-sh_mobile"); diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c index 9dcea2ba71681..8f71f01cb169b 100644 --- a/drivers/i2c/busses/i2c-sibyte.c +++ b/drivers/i2c/busses/i2c-sibyte.c @@ -180,6 +180,7 @@ static void __exit i2c_sibyte_exit(void) module_init(i2c_sibyte_init); module_exit(i2c_sibyte_exit); -MODULE_AUTHOR("Kip Walker (Broadcom Corp.), Steven J. Hill "); +MODULE_AUTHOR("Kip Walker (Broadcom Corp.)"); +MODULE_AUTHOR("Steven J. Hill "); MODULE_DESCRIPTION("SMBus adapter routines for SiByte boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index d7f72ec331e80..30db8fafe078e 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -470,6 +470,6 @@ static struct platform_driver i2c_sirfsoc_driver = { module_platform_driver(i2c_sirfsoc_driver); MODULE_DESCRIPTION("SiRF SoC I2C master controller driver"); -MODULE_AUTHOR("Zhiwu Song , " - "Xiangzhen Ye "); +MODULE_AUTHOR("Zhiwu Song "); +MODULE_AUTHOR("Xiangzhen Ye "); MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index 4abc7771af069..05aa92a3fbe00 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -489,9 +489,9 @@ static void __exit i2c_vt596_exit(void) } } -MODULE_AUTHOR("Kyosti Malkki , " - "Mark D. Studebaker and " - "Jean Delvare "); +MODULE_AUTHOR("Kyosti Malkki "); +MODULE_AUTHOR("Mark D. Studebaker "); +MODULE_AUTHOR("Jean Delvare "); MODULE_DESCRIPTION("vt82c596 SMBus driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index da020acc9bbd4..6ceb11cc4be18 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -761,8 +761,8 @@ static void __exit i2c_dev_exit(void) unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS); } -MODULE_AUTHOR("Frodo Looijaard and " - "Simon G. Vogl "); +MODULE_AUTHOR("Frodo Looijaard "); +MODULE_AUTHOR("Simon G. Vogl "); MODULE_DESCRIPTION("I2C /dev entries driver"); MODULE_LICENSE("GPL"); -- GitLab From f3e2bd713730e6d69e8e021d3ff574f01c39e7e3 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Tue, 23 Jun 2020 13:06:46 +0100 Subject: [PATCH 0233/1754] i2c: rk3x: support master_xfer_atomic Enable i2c transactions in irq disabled contexts like poweroff where the PMIC is connected via i2c. Signed-off-by: John Keeping Tested-by: Heiko Stuebner Reviewed-by: Heiko Stuebner Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-rk3x.c | 39 +++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index bc698240c4aaa..b67bb54caf272 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -1040,8 +1041,21 @@ static int rk3x_i2c_setup(struct rk3x_i2c *i2c, struct i2c_msg *msgs, int num) return ret; } -static int rk3x_i2c_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) +static int rk3x_i2c_wait_xfer_poll(struct rk3x_i2c *i2c) +{ + ktime_t timeout = ktime_add_ms(ktime_get(), WAIT_TIMEOUT); + + while (READ_ONCE(i2c->busy) && + ktime_compare(ktime_get(), timeout) < 0) { + udelay(5); + rk3x_i2c_irq(0, i2c); + } + + return !i2c->busy; +} + +static int rk3x_i2c_xfer_common(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num, bool polling) { struct rk3x_i2c *i2c = (struct rk3x_i2c *)adap->algo_data; unsigned long timeout, flags; @@ -1075,8 +1089,12 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap, rk3x_i2c_start(i2c); - timeout = wait_event_timeout(i2c->wait, !i2c->busy, - msecs_to_jiffies(WAIT_TIMEOUT)); + if (!polling) { + timeout = wait_event_timeout(i2c->wait, !i2c->busy, + msecs_to_jiffies(WAIT_TIMEOUT)); + } else { + timeout = rk3x_i2c_wait_xfer_poll(i2c); + } spin_lock_irqsave(&i2c->lock, flags); @@ -1110,6 +1128,18 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap, return ret < 0 ? ret : num; } +static int rk3x_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + return rk3x_i2c_xfer_common(adap, msgs, num, false); +} + +static int rk3x_i2c_xfer_polling(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + return rk3x_i2c_xfer_common(adap, msgs, num, true); +} + static __maybe_unused int rk3x_i2c_resume(struct device *dev) { struct rk3x_i2c *i2c = dev_get_drvdata(dev); @@ -1126,6 +1156,7 @@ static u32 rk3x_i2c_func(struct i2c_adapter *adap) static const struct i2c_algorithm rk3x_i2c_algorithm = { .master_xfer = rk3x_i2c_xfer, + .master_xfer_atomic = rk3x_i2c_xfer_polling, .functionality = rk3x_i2c_func, }; -- GitLab From 0a7f99aad259d223ce69c03e792c7e2bfcf8c2c6 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 3 Jul 2020 17:49:48 +0200 Subject: [PATCH 0234/1754] clk: rockchip: use separate compatibles for rk3288w-cru Commit 1627f683636d ("clk: rockchip: Handle clock tree for rk3288w variant") added the check for rk3288w-specific clock-tree changes but in turn would require a double-compatible due to re-using the main rockchip,rk3288-cru compatible as entry point. The binding change actually describes the compatibles as one or the other so adapt the code accordingly and add a real second entry-point for the clock controller. Signed-off-by: Heiko Stuebner Reviewed-by: Ezequiel Garcia Reviewed-by: Jagan Teki Tested-by: Jagan Teki # rock-pi-n8 Link: https://lore.kernel.org/r/20200703154948.260369-1-heiko@sntech.de --- drivers/clk/rockchip/clk-rk3288.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 204976e2d0cb8..93c794695c469 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -15,6 +15,11 @@ #define RK3288_GRF_SOC_CON(x) (0x244 + x * 4) #define RK3288_GRF_SOC_STATUS1 0x284 +enum rk3288_variant { + RK3288_CRU, + RK3288W_CRU, +}; + enum rk3288_plls { apll, dpll, cpll, gpll, npll, }; @@ -922,7 +927,8 @@ static struct syscore_ops rk3288_clk_syscore_ops = { .resume = rk3288_clk_resume, }; -static void __init rk3288_clk_init(struct device_node *np) +static void __init rk3288_common_init(struct device_node *np, + enum rk3288_variant soc) { struct rockchip_clk_provider *ctx; @@ -945,7 +951,7 @@ static void __init rk3288_clk_init(struct device_node *np) rockchip_clk_register_branches(ctx, rk3288_clk_branches, ARRAY_SIZE(rk3288_clk_branches)); - if (of_device_is_compatible(np, "rockchip,rk3288w-cru")) + if (soc == RK3288W_CRU) rockchip_clk_register_branches(ctx, rk3288w_hclkvio_branch, ARRAY_SIZE(rk3288w_hclkvio_branch)); else @@ -970,4 +976,15 @@ static void __init rk3288_clk_init(struct device_node *np) rockchip_clk_of_add_provider(np, ctx); } + +static void __init rk3288_clk_init(struct device_node *np) +{ + rk3288_common_init(np, RK3288_CRU); +} CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); + +static void __init rk3288w_clk_init(struct device_node *np) +{ + rk3288_common_init(np, RK3288W_CRU); +} +CLK_OF_DECLARE(rk3288w_cru, "rockchip,rk3288w-cru", rk3288w_clk_init); -- GitLab From 81357f818f3e21963aa7630874bfc941330ef4d4 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 12:16:37 +0100 Subject: [PATCH 0235/1754] backlight: lms501kf03: Remove unused const variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit W=1 kernel build reports: drivers/video/backlight/lms501kf03.c:96:28: warning: ‘seq_sleep_in’ defined but not used [-Wunused-const-variable=] 96 | static const unsigned char seq_sleep_in[] = { | ^~~~~~~~~~~~ drivers/video/backlight/lms501kf03.c:92:28: warning: ‘seq_up_dn’ defined but not used [-Wunused-const-variable=] 92 | static const unsigned char seq_up_dn[] = { | ^~~~~~~~~ Either 'seq_sleep_in' nor 'seq_up_dn' have been used since the driver first landed in 2013. Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/lms501kf03.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/video/backlight/lms501kf03.c b/drivers/video/backlight/lms501kf03.c index 52d3ee6c3f7f9..f949b66dce1be 100644 --- a/drivers/video/backlight/lms501kf03.c +++ b/drivers/video/backlight/lms501kf03.c @@ -88,14 +88,6 @@ static const unsigned char seq_rgb_gamma[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -static const unsigned char seq_up_dn[] = { - 0x36, 0x10, -}; - -static const unsigned char seq_sleep_in[] = { - 0x10, -}; - static const unsigned char seq_sleep_out[] = { 0x11, }; -- GitLab From 4160ebacd3579651c5fd9cb1d27dc2205adb13d7 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 12:27:10 +0100 Subject: [PATCH 0236/1754] backlight: lcd: Add missing kerneldoc entry for 'struct device parent' This has been missing since the conversion to 'struct device' in 2007. Cc: Bartlomiej Zolnierkiewicz Cc: Jamey Hicks Cc: Andrew Zabolotny Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/lcd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 78b0333586258..db56e465aaff3 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -179,6 +179,7 @@ ATTRIBUTE_GROUPS(lcd_device); * lcd_device_register - register a new object of lcd_device class. * @name: the name of the new object(must be the same as the name of the * respective framebuffer device). + * @parent: pointer to the parent's struct device . * @devdata: an optional pointer to be stored in the device. The * methods may retrieve it by using lcd_get_data(ld). * @ops: the lcd operations structure. -- GitLab From 0e0428be20fac07989bdccc4c2836cdfe2ff5ec4 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 12:41:34 +0100 Subject: [PATCH 0237/1754] backlight: ili922x: Add missing kerneldoc descriptions for CHECK_FREQ_REG() args Kerneldoc syntax is used, but not complete. Descriptions required. Prevents warnings like: drivers/video/backlight/ili922x.c:116: warning: Function parameter or member 's' not described in 'CHECK_FREQ_REG' drivers/video/backlight/ili922x.c:116: warning: Function parameter or member 'x' not described in 'CHECK_FREQ_REG' Cc: Bartlomiej Zolnierkiewicz Cc: Software Engineering Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/ili922x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/backlight/ili922x.c b/drivers/video/backlight/ili922x.c index 9c5aa3fbb2842..5914147b2c4b9 100644 --- a/drivers/video/backlight/ili922x.c +++ b/drivers/video/backlight/ili922x.c @@ -107,6 +107,8 @@ * lower frequency when the registers are read/written. * The macro sets the frequency in the spi_transfer structure if * the frequency exceeds the maximum value. + * @s: pointer to an SPI device + * @x: pointer to the read/write buffer pair */ #define CHECK_FREQ_REG(s, x) \ do { \ -- GitLab From ee555c1dbe69d7de80d11ebbe5c9589726e12ed9 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 12:44:05 +0100 Subject: [PATCH 0238/1754] backlight: ili922x: Remove invalid use of kerneldoc syntax Kerneldoc is for documenting function arguments and return values. Prevents warnings like: drivers/video/backlight/ili922x.c:127: warning: cannot understand function prototype: 'int ili922x_id = 1; ' drivers/video/backlight/ili922x.c:136: warning: cannot understand function prototype: 'struct ili922x ' Cc: Bartlomiej Zolnierkiewicz Cc: Software Engineering Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/ili922x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/ili922x.c b/drivers/video/backlight/ili922x.c index 5914147b2c4b9..fe03fb058ef06 100644 --- a/drivers/video/backlight/ili922x.c +++ b/drivers/video/backlight/ili922x.c @@ -123,7 +123,7 @@ #define set_tx_byte(b) (tx_invert ? ~(b) : b) -/** +/* * ili922x_id - id as set by manufacturer */ static int ili922x_id = 1; @@ -132,7 +132,7 @@ module_param(ili922x_id, int, 0); static int tx_invert; module_param(tx_invert, int, 0); -/** +/* * driver's private structure */ struct ili922x { -- GitLab From 7099c930fa71438f1b46350f693e3e6d7e627482 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 12:48:41 +0100 Subject: [PATCH 0239/1754] backlight: ili922x: Add missing kerneldoc description for ili922x_reg_dump()'s arg Kerneldoc syntax is used, but not complete. Descriptions required. Prevents warnings like: drivers/video/backlight/ili922x.c:298: warning: Function parameter or member 'spi' not described in 'ili922x_reg_dump' Cc: Bartlomiej Zolnierkiewicz Cc: Software Engineering Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/ili922x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/backlight/ili922x.c b/drivers/video/backlight/ili922x.c index fe03fb058ef06..328aba9cddad1 100644 --- a/drivers/video/backlight/ili922x.c +++ b/drivers/video/backlight/ili922x.c @@ -295,6 +295,8 @@ static int ili922x_write(struct spi_device *spi, u8 reg, u16 value) #ifdef DEBUG /** * ili922x_reg_dump - dump all registers + * + * @spi: pointer to an SPI device */ static void ili922x_reg_dump(struct spi_device *spi) { -- GitLab From 6c05632d6341ced4c2cb431ed0e5f617cc83f5bb Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 15:04:36 +0100 Subject: [PATCH 0240/1754] backlight: backlight: Supply description for function args in existing Kerneldocs Kerneldoc syntax is used, but not complete. Descriptions required. Prevents warnings like: drivers/video/backlight/backlight.c:329: warning: Function parameter or member 'reason' not described in 'backlight_force_update' drivers/video/backlight/backlight.c:354: warning: Function parameter or member 'props' not described in 'backlight_device_register' Cc: Bartlomiej Zolnierkiewicz Cc: Jamey Hicks Cc: Andrew Zabolotny Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/backlight.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 92d80aa0c0ef1..744ba58488e01 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -320,6 +320,7 @@ ATTRIBUTE_GROUPS(bl_device); * backlight_force_update - tell the backlight subsystem that hardware state * has changed * @bd: the backlight device to update + * @reason: reason for update * * Updates the internal state of the backlight in response to a hardware event, * and generate a uevent to notify userspace @@ -344,6 +345,7 @@ EXPORT_SYMBOL(backlight_force_update); * @devdata: an optional pointer to be stored for private driver use. The * methods may retrieve it by using bl_get_data(bd). * @ops: the backlight operations structure. + * @props: pointer to backlight's properties structure. * * Creates and registers new backlight device. Returns either an * ERR_PTR() or a pointer to the newly allocated device. -- GitLab From 3e799ccda3651a43ef3b366f70101e16e5054865 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 15:37:50 +0100 Subject: [PATCH 0241/1754] backlight: lm3630a_bl: Remove invalid checks for unsigned int < 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit unsigned ints 'sources' and 'bank' cannot be less than LM3630A_SINK_0 (0) and LM3630A_BANK_0 (0) respecitively, so change the logic to only check for thier two possible valid values. Fixes W=1 warnings: drivers/video/backlight/lm3630a_bl.c: In function ‘lm3630a_parse_led_sources’: drivers/video/backlight/lm3630a_bl.c:394:18: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits] 394 | if (sources[i] < LM3630A_SINK_0 || sources[i] > LM3630A_SINK_1) | ^ drivers/video/backlight/lm3630a_bl.c: In function ‘lm3630a_parse_bank’: drivers/video/backlight/lm3630a_bl.c:415:11: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits] 415 | if (bank < LM3630A_BANK_0 || bank > LM3630A_BANK_1) | ^ Cc: Bartlomiej Zolnierkiewicz Cc: Daniel Jeong Cc: LDD MLP Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/lm3630a_bl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c index ee320883b7108..e88a2b0e59046 100644 --- a/drivers/video/backlight/lm3630a_bl.c +++ b/drivers/video/backlight/lm3630a_bl.c @@ -391,7 +391,7 @@ static int lm3630a_parse_led_sources(struct fwnode_handle *node, return ret; for (i = 0; i < num_sources; i++) { - if (sources[i] < LM3630A_SINK_0 || sources[i] > LM3630A_SINK_1) + if (sources[i] != LM3630A_SINK_0 && sources[i] != LM3630A_SINK_1) return -EINVAL; ret |= BIT(sources[i]); @@ -412,7 +412,7 @@ static int lm3630a_parse_bank(struct lm3630a_platform_data *pdata, if (ret) return ret; - if (bank < LM3630A_BANK_0 || bank > LM3630A_BANK_1) + if (bank != LM3630A_BANK_0 && bank != LM3630A_BANK_1) return -EINVAL; led_sources = lm3630a_parse_led_sources(node, BIT(bank)); -- GitLab From e17c7461a28ce7f0cc2c1aec307584dccd04a847 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 15:47:02 +0100 Subject: [PATCH 0242/1754] backlight: qcom-wled: Remove unused configs for LED3 and LED4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes W=1 warnings: drivers/video/backlight/qcom-wled.c:1294:34: warning: ‘wled4_string_cfg’ defined but not used [-Wunused-const-variable=] 1294 | static const struct wled_var_cfg wled4_string_cfg = { | ^~~~~~~~~~~~~~~~ drivers/video/backlight/qcom-wled.c:1290:34: warning: ‘wled3_string_cfg’ defined but not used [-Wunused-const-variable=] 1290 | static const struct wled_var_cfg wled3_string_cfg = { | ^~~~~~~~~~~~~~~~ Cc: Andy Gross Cc: Bjorn Andersson Cc: Bartlomiej Zolnierkiewicz Cc: linux-arm-msm@vger.kernel.org Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/qcom-wled.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c index 4c8c34b994414..c25c31199952c 100644 --- a/drivers/video/backlight/qcom-wled.c +++ b/drivers/video/backlight/qcom-wled.c @@ -1287,14 +1287,6 @@ static const struct wled_var_cfg wled4_string_i_limit_cfg = { .size = ARRAY_SIZE(wled4_string_i_limit_values), }; -static const struct wled_var_cfg wled3_string_cfg = { - .size = 8, -}; - -static const struct wled_var_cfg wled4_string_cfg = { - .size = 16, -}; - static const struct wled_var_cfg wled5_mod_sel_cfg = { .size = 2, }; -- GitLab From 6fef0d4ea575c0561b38fd9149a05f1acb505bc0 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 08:55:47 +0100 Subject: [PATCH 0243/1754] mfd: twl4030-irq: Fix incorrect type in assignment warning Silences Sparse warning: drivers/mfd/twl4030-irq.c:485:26: warning: incorrect type in assignment (different base types) drivers/mfd/twl4030-irq.c:485:26: expected unsigned int [usertype] word drivers/mfd/twl4030-irq.c:485:26: got restricted __le32 [usertype] Cc: Tony Lindgren Cc: Kai Svahn Cc: Syed Khasim Cc: linux-omap@vger.kernel.org Signed-off-by: Lee Jones --- drivers/mfd/twl4030-irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index 910a304b397ce..d05bc74daba32 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -477,7 +477,7 @@ static void twl4030_sih_bus_sync_unlock(struct irq_data *data) if (agent->imr_change_pending) { union { - u32 word; + __le32 word; u8 bytes[4]; } imr; -- GitLab From b174015b1ddd0a7009acaf6aa7019e9883b0f75b Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 09:01:07 +0100 Subject: [PATCH 0244/1754] mfd: twl4030-irq: Fix cast to restricted __le32 warning Silences Sparse warning(s): drivers/mfd/twl4030-irq.c:573:40: warning: cast to restricted __le32 drivers/mfd/twl4030-irq.c:573:40: warning: cast to restricted __le32 drivers/mfd/twl4030-irq.c:573:40: warning: cast to restricted __le32 drivers/mfd/twl4030-irq.c:573:40: warning: cast to restricted __le32 drivers/mfd/twl4030-irq.c:573:40: warning: cast to restricted __le32 drivers/mfd/twl4030-irq.c:573:40: warning: cast to restricted __le32 Cc: Tony Lindgren Cc: Kai Svahn Cc: Syed Khasim Cc: linux-omap@vger.kernel.org Signed-off-by: Lee Jones --- drivers/mfd/twl4030-irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index d05bc74daba32..ab417438d1faa 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -561,7 +561,7 @@ static inline int sih_read_isr(const struct sih *sih) int status; union { u8 bytes[4]; - u32 word; + __le32 word; } isr; /* FIXME need retry-on-error ... */ -- GitLab From c504a2486ab67cd9fc38940ad2841075d6a3e9a4 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 09:15:56 +0100 Subject: [PATCH 0245/1754] mfd: tps6586x: Fix cast to restricted __le32 warning Silences Sparse warning(s): drivers/mfd/tps6586x.c:323:16: warning: cast to restricted __le32 drivers/mfd/tps6586x.c:323:16: warning: cast to restricted __le32 drivers/mfd/tps6586x.c:323:16: warning: cast to restricted __le32 drivers/mfd/tps6586x.c:323:16: warning: cast to restricted __le32 drivers/mfd/tps6586x.c:323:16: warning: cast to restricted __le32 drivers/mfd/tps6586x.c:323:16: warning: cast to restricted __le32 Cc: Mike Rapoport Cc: Eric Miao Signed-off-by: Lee Jones --- drivers/mfd/tps6586x.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index c8aadd39324e3..c36597797ddd8 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -309,18 +309,19 @@ static const struct irq_domain_ops tps6586x_domain_ops = { static irqreturn_t tps6586x_irq(int irq, void *data) { struct tps6586x *tps6586x = data; - u32 acks; + uint32_t acks; + __le32 val; int ret = 0; ret = tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1, - sizeof(acks), (uint8_t *)&acks); + sizeof(acks), (uint8_t *)&val); if (ret < 0) { dev_err(tps6586x->dev, "failed to read interrupt status\n"); return IRQ_NONE; } - acks = le32_to_cpu(acks); + acks = le32_to_cpu(val); while (acks) { int i = __ffs(acks); -- GitLab From d9ca7801b6e5ffdfd7a4ed3f287b277895e63e90 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 09:55:05 +0100 Subject: [PATCH 0246/1754] mfd: altera-sysmgr: Fix physical address storing hacks Sparse reports: drivers/mfd/altera-sysmgr.c:150:30: warning: incorrect type in assignment (different address spaces) drivers/mfd/altera-sysmgr.c:150:30: expected unsigned int [usertype] *base drivers/mfd/altera-sysmgr.c:150:30: got void [noderef] * drivers/mfd/altera-sysmgr.c:156:26: warning: incorrect type in argument 3 (different address spaces) drivers/mfd/altera-sysmgr.c:156:26: expected void [noderef] *regs drivers/mfd/altera-sysmgr.c:156:26: got unsigned int [usertype] *base It appears as though the driver data property 'resource_size_t *base' was being used to store 2 different types of addresses (physical and IO-mapped) under a single declared type. Fortunately, no value is recalled from the driver data entry, so it can be easily omitted. Instead we can use the value obtained directly from the platform resource to pass through Regmap into the call-backs to be used for the SMCC call and use a local dedicated __iomem variable for IO-remapping. Cc: Thor Thayer Signed-off-by: Lee Jones --- drivers/mfd/altera-sysmgr.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c index d2a13a547a3ca..83f0765f819b0 100644 --- a/drivers/mfd/altera-sysmgr.c +++ b/drivers/mfd/altera-sysmgr.c @@ -22,11 +22,9 @@ /** * struct altr_sysmgr - Altera SOCFPGA System Manager * @regmap: the regmap used for System Manager accesses. - * @base : the base address for the System Manager */ struct altr_sysmgr { struct regmap *regmap; - resource_size_t *base; }; static struct platform_driver altr_sysmgr_driver; @@ -127,6 +125,7 @@ static int sysmgr_probe(struct platform_device *pdev) struct regmap_config sysmgr_config = altr_sysmgr_regmap_cfg; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; + void __iomem *base; sysmgr = devm_kzalloc(dev, sizeof(*sysmgr), GFP_KERNEL); if (!sysmgr) @@ -139,22 +138,19 @@ static int sysmgr_probe(struct platform_device *pdev) sysmgr_config.max_register = resource_size(res) - sysmgr_config.reg_stride; if (of_device_is_compatible(np, "altr,sys-mgr-s10")) { - /* Need physical address for SMCC call */ - sysmgr->base = (resource_size_t *)res->start; sysmgr_config.reg_read = s10_protected_reg_read; sysmgr_config.reg_write = s10_protected_reg_write; - regmap = devm_regmap_init(dev, NULL, sysmgr->base, + /* Need physical address for SMCC call */ + regmap = devm_regmap_init(dev, NULL, (void *)res->start, &sysmgr_config); } else { - sysmgr->base = devm_ioremap(dev, res->start, - resource_size(res)); - if (!sysmgr->base) + base = devm_ioremap(dev, res->start, resource_size(res)); + if (!base) return -ENOMEM; sysmgr_config.max_register = res->end - res->start - 3; - regmap = devm_regmap_init_mmio(dev, sysmgr->base, - &sysmgr_config); + regmap = devm_regmap_init_mmio(dev, base, &sysmgr_config); } if (IS_ERR(regmap)) { -- GitLab From 3d4a87576f3762c8c986950af157bc9025808b5c Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 10:08:41 +0100 Subject: [PATCH 0247/1754] mfd: sprd-sc27xx-spi: Fix symbol 'sprd_pmic_detect_charger_type' was not declared warning Sparse reports: drivers/mfd/sprd-sc27xx-spi.c:59:23: warning: symbol 'sprd_pmic_detect_charger_type' was not declared. Should it be static? ... due to a missing header file. Cc: Orson Zhai Cc: Chunyan Zhang Signed-off-by: Lee Jones Reviewed-by: Baolin Wang Signed-off-by: Lee Jones --- drivers/mfd/sprd-sc27xx-spi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c index d030a5da55444..d3486c2a1b339 100644 --- a/drivers/mfd/sprd-sc27xx-spi.c +++ b/drivers/mfd/sprd-sc27xx-spi.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include -- GitLab From 54daa5d47c47662067115a78dd317fba3de9e828 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 10:26:11 +0100 Subject: [PATCH 0248/1754] mfd: ab3100-core: Fix incompatible types in comparison expression warning Smatch reports: drivers/mfd/ab3100-core.c:501:20: error: incompatible types in comparison expression (different type sizes): drivers/mfd/ab3100-core.c:501:20: unsigned int * drivers/mfd/ab3100-core.c:501:20: unsigned long * drivers/mfd/ab8500-debugfs.c:1804:20: error: incompatible types in comparison expression (different type sizes): drivers/mfd/ab8500-debugfs.c:1804:20: unsigned int * drivers/mfd/ab8500-debugfs.c:1804:20: unsigned long * Since the second min() argument can be less than 0 a signed variable is required for assignment. However, the non-sized type size_t is passed in from the userspace handlers. In order to firstly compare, then assign the smallest value, we firstly need to cast them both to the same as the receiving size_t typed variable. Cc: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/ab3100-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 57723f116bb58..ee71ae04b5e63 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -498,7 +498,7 @@ static ssize_t ab3100_get_set_reg(struct file *file, int i = 0; /* Get userspace string and assure termination */ - buf_size = min(count, (sizeof(buf)-1)); + buf_size = min((ssize_t)count, (ssize_t)(sizeof(buf)-1)); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; buf[buf_size] = 0; -- GitLab From ddb6b26c4102aab886277b2ca3c027b4976d819b Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 11:05:23 +0100 Subject: [PATCH 0249/1754] mfd: ab8500-debugfs: Fix incompatible types in comparison expression issue Smatch reports: drivers/mfd/ab8500-debugfs.c:1804:20: error: incompatible types in comparison expression (different type sizes): drivers/mfd/ab8500-debugfs.c:1804:20: unsigned int * drivers/mfd/ab8500-debugfs.c:1804:20: unsigned long * This is due to mixed types being compared in a min() comparison. Fix this by treating values as signed and casting them to the same type as the receiving variable. Cc: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/ab8500-debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 1a9a3414d4fa8..6d1bf7c3ca3b1 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -1801,7 +1801,7 @@ static ssize_t ab8500_hwreg_write(struct file *file, int buf_size, ret; /* Get userspace string and assure termination */ - buf_size = min(count, (sizeof(buf)-1)); + buf_size = min((int)count, (int)(sizeof(buf)-1)); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; buf[buf_size] = 0; -- GitLab From 0dfae4a3205cb73e8ab2aafd4cbd0ff1fb082b5f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 13:36:30 +0100 Subject: [PATCH 0250/1754] mfd: tc3589x: Remove invalid use of kerneldoc syntax Kerneldoc is for documenting function arguments and return values. Prevents warnings like: drivers/mfd/tc3589x.c:32: warning: Enum value 'TC3589X_TC35890' not described in enum 'tc3589x_version' drivers/mfd/tc3589x.c:32: warning: Enum value 'TC3589X_TC35892' not described in enum 'tc3589x_version' drivers/mfd/tc3589x.c:32: warning: Enum value 'TC3589X_TC35893' not described in enum 'tc3589x_version' drivers/mfd/tc3589x.c:32: warning: Enum value 'TC3589X_TC35894' not described in enum 'tc3589x_version' drivers/mfd/tc3589x.c:32: warning: Enum value 'TC3589X_TC35895' not described in enum 'tc3589x_version' drivers/mfd/tc3589x.c:32: warning: Enum value 'TC3589X_TC35896' not described in enum 'tc3589x_version' drivers/mfd/tc3589x.c:32: warning: Enum value 'TC3589X_UNKNOWN' not described in enum 'tc3589x_version' Signed-off-by: Lee Jones --- drivers/mfd/tc3589x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 67c9995bb1aa6..7882a37ffc352 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -18,7 +18,7 @@ #include #include -/** +/* * enum tc3589x_version - indicates the TC3589x version */ enum tc3589x_version { -- GitLab From f139ef70789a6e8ae1692e00cf0a3ef7d68bf6b1 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 14:06:40 +0100 Subject: [PATCH 0251/1754] mfd: wm8400-core: Supply description for wm8400_reset_codec_reg_cache's arg Kerneldoc syntax is used, but not complete. Descriptions required. Prevents warnings like: drivers/mfd/wm8400-core.c:113: warning: Function parameter or member 'wm8400' not described in 'wm8400_reset_codec_reg_cache' Cc: Mark Brown Cc: patches@opensource.cirrus.com Signed-off-by: Lee Jones Acked-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm8400-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 3055d6f47afcc..0fe32a05421be 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c @@ -108,6 +108,8 @@ static const struct regmap_config wm8400_regmap_config = { /** * wm8400_reset_codec_reg_cache - Reset cached codec registers to * their default values. + * + * @wm8400: pointer to local driver data structure */ void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400) { -- GitLab From 38ea9f47317d8e8a74b15b719d5c794a79346be8 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 15:33:33 +0100 Subject: [PATCH 0252/1754] mfd: wm831x-core: Supply description wm831x_reg_{un}lock args Kerneldoc syntax is used, but not complete. Descriptions required. Prevents warnings like: drivers/mfd/wm831x-core.c:119: warning: Function parameter or member 'wm831x' not described in 'wm831x_reg_lock' drivers/mfd/wm831x-core.c:145: warning: Function parameter or member 'wm831x' not described in 'wm831x_reg_unlock' Cc: Mark Brown Cc: patches@opensource.cirrus.com Signed-off-by: Lee Jones Acked-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm831x-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 02f879b23d9f6..b0344e5353e4f 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -114,6 +114,8 @@ static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) * The WM831x has a user key preventing writes to particularly * critical registers. This function locks those registers, * allowing writes to them. + * + * @wm831x: pointer to local driver data structure */ void wm831x_reg_lock(struct wm831x *wm831x) { @@ -140,6 +142,8 @@ EXPORT_SYMBOL_GPL(wm831x_reg_lock); * The WM831x has a user key preventing writes to particularly * critical registers. This function locks those registers, * preventing spurious writes. + * + * @wm831x: pointer to local driver data structure */ int wm831x_reg_unlock(struct wm831x *wm831x) { -- GitLab From afb718a870ef20efcf18d6fbea45fa6576a54d27 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 15:44:48 +0100 Subject: [PATCH 0253/1754] mfd: wm8350-core: Supply description wm8350_reg_{un}lock args Kerneldoc syntax is used, but not complete. Descriptions required. Prevents warnings like: drivers/mfd/wm8350-core.c:136: warning: Function parameter or member 'wm8350' not described in 'wm8350_reg_lock' drivers/mfd/wm8350-core.c:165: warning: Function parameter or member 'wm8350' not described in 'wm8350_reg_unlock' Cc: patches@opensource.cirrus.com Signed-off-by: Lee Jones --- drivers/mfd/wm8350-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index 42b16503e6cd1..fbc77b218215c 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c @@ -131,6 +131,8 @@ EXPORT_SYMBOL_GPL(wm8350_block_write); * The WM8350 has a hardware lock which can be used to prevent writes to * some registers (generally those which can cause particularly serious * problems if misused). This function enables that lock. + * + * @wm8350: pointer to local driver data structure */ int wm8350_reg_lock(struct wm8350 *wm8350) { @@ -160,6 +162,8 @@ EXPORT_SYMBOL_GPL(wm8350_reg_lock); * problems if misused). This function disables that lock so updates * can be performed. For maximum safety this should be done only when * required. + * + * @wm8350: pointer to local driver data structure */ int wm8350_reg_unlock(struct wm8350 *wm8350) { -- GitLab From 5a0ffef8b74fda62114d7bfba92f318fcc4b9283 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 15:51:28 +0100 Subject: [PATCH 0254/1754] mfd: mfd-core: Complete kerneldoc header for devm_mfd_add_devices() Each function parameter should be documented in kerneldoc format. Squashes the following W=1 warnings: drivers/mfd/mfd-core.c:326: warning: Function parameter or member 'dev' not described in 'devm_mfd_add_devices' drivers/mfd/mfd-core.c:326: warning: Function parameter or member 'id' not described in 'devm_mfd_add_devices' drivers/mfd/mfd-core.c:326: warning: Function parameter or member 'cells' not described in 'devm_mfd_add_devices' drivers/mfd/mfd-core.c:326: warning: Function parameter or member 'n_devs' not described in 'devm_mfd_add_devices' drivers/mfd/mfd-core.c:326: warning: Function parameter or member 'mem_base' not described in 'devm_mfd_add_devices' drivers/mfd/mfd-core.c:326: warning: Function parameter or member 'irq_base' not described in 'devm_mfd_add_devices' drivers/mfd/mfd-core.c:326: warning: Function parameter or member 'domain' not described in 'devm_mfd_add_devices' Signed-off-by: Lee Jones --- drivers/mfd/mfd-core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index f5a73af60dd40..720e5c8b1588c 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -318,6 +318,16 @@ static void devm_mfd_dev_release(struct device *dev, void *res) * Returns 0 on success or an appropriate negative error number on failure. * All child-devices of the MFD will automatically be removed when it gets * unbinded. + * + * @dev: Pointer to parent device. + * @id: Can be PLATFORM_DEVID_AUTO to let the Platform API take care + * of device numbering, or will be added to a device's cell_id. + * @cells: Array of (struct mfd_cell)s describing child devices. + * @n_devs: Number of child devices to register. + * @mem_base: Parent register range resource for child devices. + * @irq_base: Base of the range of virtual interrupt numbers allocated for + * this MFD device. Unused if @domain is specified. + * @domain: Interrupt domain to create mappings for hardware interrupts. */ int devm_mfd_add_devices(struct device *dev, int id, const struct mfd_cell *cells, int n_devs, -- GitLab From 3ecbcd20e06f2c1254a85fc208ccc6aa20594314 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 09:34:00 +0100 Subject: [PATCH 0255/1754] mfd: db8500-prcmu: Add description for 'reset_reason' in kerneldoc Each function parameter should be documented in kerneldoc format. Squashes the following W=1 warnings: drivers/mfd/db8500-prcmu.c:2281: warning: Function parameter or member 'reset_code' not described in 'db8500_prcmu_system_reset' drivers/mfd/db8500-prcmu.c:3012: warning: Function parameter or member 'pdev' not described in 'db8500_prcmu_probe' Cc: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/db8500-prcmu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 0452b43b04232..9b58b02967638 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -2276,6 +2276,8 @@ bool db8500_prcmu_is_ac_wake_requested(void) * * Saves the reset reason code and then sets the APE_SOFTRST register which * fires interrupt to fw + * + * @reset_code: The reason for system reset */ void db8500_prcmu_system_reset(u16 reset_code) { -- GitLab From 07d88c97aef826f1ba8a5026ea30700f85433057 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 09:35:24 +0100 Subject: [PATCH 0256/1754] mfd: db8500-prcmu: Remove incorrect function header from .probe() function Not only is the current header incorrect, the isn't actually a need to document the ubiquitous platform probe call. Cc: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/db8500-prcmu.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 9b58b02967638..a9d9c1cdf546b 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -3006,10 +3006,6 @@ static int db8500_prcmu_register_ab8500(struct device *parent) return mfd_add_devices(parent, 0, ab850x_cell, 1, NULL, 0, NULL); } -/** - * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic - * - */ static int db8500_prcmu_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; -- GitLab From 5d36df75839d2dc6216f13ed86a60f801c38937f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 09:42:33 +0100 Subject: [PATCH 0257/1754] mfd: omap-usb-host: Remove invalid use of kerneldoc syntax Kerneldoc is for documenting function arguments and return values. Prevents warnings like: drivers/mfd/omap-usb-host.c:128: warning: cannot understand function prototype: 'const char * const port_modes[] = ' Cc: Tony Lindgren Cc: Keshava Munegowda Cc: Roger Quadros Cc: linux-omap@vger.kernel.org Signed-off-by: Lee Jones --- drivers/mfd/omap-usb-host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 1f4f01b02d98c..f56cdf3149dc0 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -120,7 +120,7 @@ static inline u32 usbhs_read(void __iomem *base, u32 reg) /*-------------------------------------------------------------------------*/ -/** +/* * Map 'enum usbhs_omap_port_mode' found in * to the device tree binding portN-mode found in * 'Documentation/devicetree/bindings/mfd/omap-usb-host.txt' -- GitLab From 3fc65627c81c700c2b12eb3b8ca8a47f4cb4dd20 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 09:45:56 +0100 Subject: [PATCH 0258/1754] mfd: omap-usb-host: Provide description for 'pdev' argument to .probe() Kerneldoc syntax is used, but not complete. Arg descriptions required. Prevents warnings like: drivers/mfd/omap-usb-host.c:531: warning: Function parameter or member 'pdev' not described in 'usbhs_omap_probe' Cc: Tony Lindgren Cc: Keshava Munegowda Cc: Roger Quadros Cc: linux-omap@vger.kernel.org Signed-off-by: Lee Jones --- drivers/mfd/omap-usb-host.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index f56cdf3149dc0..aca5a160c1b24 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -526,6 +526,8 @@ static const struct of_device_id usbhs_child_match_table[] = { * usbhs_omap_probe - initialize TI-based HCDs * * Allocates basic resources for this USB host controller. + * + * @pdev: Pointer to this device's platform device structure */ static int usbhs_omap_probe(struct platform_device *pdev) { -- GitLab From 55bbf5d42ee6c609de56702ae7f766c4e88efbed Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 09:48:17 +0100 Subject: [PATCH 0259/1754] mfd: omap-usb-tll: Provide description for 'pdev' argument to .probe() Kerneldoc syntax is used, but not complete. Arg descriptions required. Prevents warnings like: drivers/mfd/omap-usb-tll.c:204: warning: Function parameter or member 'pdev' not described in 'usbtll_omap_probe Cc: Tony Lindgren Cc: Keshava Munegowda Cc: Roger Quadros Cc: linux-omap@vger.kernel.org Signed-off-by: Lee Jones --- drivers/mfd/omap-usb-tll.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index 4b7f73c317e87..04a444007cf4e 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c @@ -199,6 +199,8 @@ static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode) * usbtll_omap_probe - initialize TI-based HCDs * * Allocates basic resources for this USB host controller. + * + * @pdev: Pointer to this device's platform device structure */ static int usbtll_omap_probe(struct platform_device *pdev) { -- GitLab From 1574360a98cef9842d86e208944bb45243150440 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 12:29:02 +0100 Subject: [PATCH 0260/1754] mfd: atmel-smc: Add missing colon(s) for 'conf' arguments Kerneldoc valication gets confused if syntax isn't "@.*: ". Adding the missing colons squashes the following W=1 warnings: drivers/mfd/atmel-smc.c:247: warning: Function parameter or member 'conf' not described in 'atmel_smc_cs_conf_apply' drivers/mfd/atmel-smc.c:268: warning: Function parameter or member 'conf' not described in 'atmel_hsmc_cs_conf_apply' Cc: Nicolas Ferre Cc: Alexandre Belloni Cc: Ludovic Desroches Cc: Boris Brezillon Signed-off-by: Lee Jones --- drivers/mfd/atmel-smc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/atmel-smc.c b/drivers/mfd/atmel-smc.c index 1fa2ec950e7df..d96f1d689e7fb 100644 --- a/drivers/mfd/atmel-smc.c +++ b/drivers/mfd/atmel-smc.c @@ -237,7 +237,7 @@ EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_cycle); * atmel_smc_cs_conf_apply - apply an SMC CS conf * @regmap: the SMC regmap * @cs: the CS id - * @conf the SMC CS conf to apply + * @conf: the SMC CS conf to apply * * Applies an SMC CS configuration. * Only valid on at91sam9/avr32 SoCs. @@ -257,7 +257,7 @@ EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_apply); * @regmap: the HSMC regmap * @cs: the CS id * @layout: the layout of registers - * @conf the SMC CS conf to apply + * @conf: the SMC CS conf to apply * * Applies an SMC CS configuration. * Only valid on post-sama5 SoCs. -- GitLab From 0824c889e1a4b1ec0edf890689c7852363c4b055 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 12:56:11 +0100 Subject: [PATCH 0261/1754] mfd: altera-sysmgr: Supply descriptions for 'np' and 'property' function args Kerneldoc syntax is used, but not complete. Arg descriptions are required. Fixes the following W=1 build warnings: drivers/mfd/altera-sysmgr.c:95: warning: Function parameter or member 'np' not described in 'altr_sysmgr_regmap_lookup_by_phandle' drivers/mfd/altera-sysmgr.c:95: warning: Function parameter or member 'property' not described in 'altr_sysmgr_regmap_lookup_by_phandle' Cc: Thor Thayer Signed-off-by: Lee Jones --- drivers/mfd/altera-sysmgr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c index 83f0765f819b0..41076d121dd54 100644 --- a/drivers/mfd/altera-sysmgr.c +++ b/drivers/mfd/altera-sysmgr.c @@ -89,6 +89,9 @@ static struct regmap_config altr_sysmgr_regmap_cfg = { * altr_sysmgr_regmap_lookup_by_phandle * Find the sysmgr previous configured in probe() and return regmap property. * Return: regmap if found or error if not found. + * + * @np: Pointer to device's Device Tree node + * @property: Device Tree property name which references the sysmgr */ struct regmap *altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np, const char *property) -- GitLab From 5ae3d1bcea485e3f0056c508d2e12d1a95c453ee Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 13:07:45 +0100 Subject: [PATCH 0262/1754] mfd: cros_ec_dev: Fix cros_feature_to_{name,cells} struct descriptions Kerneldoc expects kernel structures to be prefixed with 'struct'. Fixes the following W=1 level warnings: drivers/mfd/cros_ec_dev.c:32: warning: cannot understand function prototype: 'struct cros_feature_to_name ' drivers/mfd/cros_ec_dev.c:44: warning: cannot understand function prototype: 'struct cros_feature_to_cells ' Cc: Benson Leung Cc: Guenter Roeck Cc: Bill Richardson Signed-off-by: Lee Jones Acked-by: Enric Balletbo i Serra Signed-off-by: Lee Jones --- drivers/mfd/cros_ec_dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index 32c2b912b58b2..d07b43d7c761a 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -24,7 +24,7 @@ static struct class cros_class = { }; /** - * cros_feature_to_name - CrOS feature id to name/short description. + * struct cros_feature_to_name - CrOS feature id to name/short description. * @id: The feature identifier. * @name: Device name associated with the feature id. * @desc: Short name that will be displayed. @@ -36,7 +36,7 @@ struct cros_feature_to_name { }; /** - * cros_feature_to_cells - CrOS feature id to mfd cells association. + * struct cros_feature_to_cells - CrOS feature id to mfd cells association. * @id: The feature identifier. * @mfd_cells: Pointer to the array of mfd cells that needs to be added. * @num_cells: Number of mfd cells into the array. -- GitLab From 9c3739ee293bc956739c9a90d357595f41f46d39 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 13:10:54 +0100 Subject: [PATCH 0263/1754] mfd: tps65218: Repair incorrect function argument name 's/tps65218/tps/' The kerneldocs for both tps65218_reg_write() and tps65218_update_bits() describe their first arguments as 'tps65218', when in reality these are simply called 'tps'. Fixes the following W=1 warnings: drivers/mfd/tps65218.c:58: warning: Function parameter or member 'tps' not described in 'tps65218_reg_write' drivers/mfd/tps65218.c:58: warning: Excess function parameter 'tps65218' description in 'tps65218_reg_write' drivers/mfd/tps65218.c:90: warning: Function parameter or member 'tps' not described in 'tps65218_update_bits' drivers/mfd/tps65218.c:90: warning: Excess function parameter 'tps65218' description in 'tps65218_update_bits' Cc: Tony Lindgren Cc: J Keerthy Cc: linux-omap@vger.kernel.org Signed-off-by: Lee Jones --- drivers/mfd/tps65218.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c index a62ea4cb8be7e..d41dd864b472b 100644 --- a/drivers/mfd/tps65218.c +++ b/drivers/mfd/tps65218.c @@ -48,7 +48,7 @@ static const struct mfd_cell tps65218_cells[] = { /** * tps65218_reg_write: Write a single tps65218 register. * - * @tps65218: Device to write to. + * @tps: Device to write to. * @reg: Register to write to. * @val: Value to write. * @level: Password protected level @@ -79,7 +79,7 @@ EXPORT_SYMBOL_GPL(tps65218_reg_write); /** * tps65218_update_bits: Modify bits w.r.t mask, val and level. * - * @tps65218: Device to write to. + * @tps: Device to write to. * @reg: Register to read-write to. * @mask: Mask. * @val: Value to write. -- GitLab From 4976bfb8d853a246f83da7ccdfb49fa34093ac0d Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 13:14:51 +0100 Subject: [PATCH 0264/1754] mfd: tps65217: Repair incorrect function argument name 's/tps65217/tps/' The kerneldocs for both tps65217_reg_write() and tps65217_update_bits() describe their first arguments as 'tps65217', when in reality these are simply called 'tps'. Fixes the following W=1 warnings: drivers/mfd/tps65217.c:215: warning: Function parameter or member 'tps' not described in 'tps65217_reg_write' drivers/mfd/tps65217.c:215: warning: Excess function parameter 'tps65217' description in 'tps65217_reg_write' drivers/mfd/tps65217.c:261: warning: Function parameter or member 'tps' not described in 'tps65217_update_bits' drivers/mfd/tps65217.c:261: warning: Excess function parameter 'tps65217' description in 'tps65217_update_bits' Cc: Tony Lindgren Cc: AnilKumar Ch Cc: linux-omap@vger.kernel.org Signed-off-by: Lee Jones --- drivers/mfd/tps65217.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index 7566ce4457a01..923602599549b 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -205,7 +205,7 @@ EXPORT_SYMBOL_GPL(tps65217_reg_read); /** * tps65217_reg_write: Write a single tps65217 register. * - * @tps65217: Device to write to. + * @tps: Device to write to. * @reg: Register to write to. * @val: Value to write. * @level: Password protected level @@ -250,7 +250,7 @@ EXPORT_SYMBOL_GPL(tps65217_reg_write); /** * tps65217_update_bits: Modify bits w.r.t mask, val and level. * - * @tps65217: Device to write to. + * @tps: Device to write to. * @reg: Register to read-write to. * @mask: Mask. * @val: Value to write. -- GitLab From 20d60f850d2d8b6f9536c1a499fc6d6a5c724a55 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 13:17:01 +0100 Subject: [PATCH 0265/1754] mfd: ab3100-otp: Add missing colon(s) for all documented kerneldoc arguments Kerneldoc validation gets confused if syntax isn't "@.*: ". Adding the missing colons squashes the following W=1 warnings: drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'dev' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'locked' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'freq' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'paf' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'imeich' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'cid' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'tac' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'fac' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'svn' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'debugfs' not described in 'ab3100_otp' Cc: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/ab3100-otp.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c index c4751fb9bc224..c393102e3a394 100644 --- a/drivers/mfd/ab3100-otp.c +++ b/drivers/mfd/ab3100-otp.c @@ -29,22 +29,22 @@ /** * struct ab3100_otp - * @dev containing device - * @locked whether the OTP is locked, after locking, no more bits + * @dev: containing device + * @locked: whether the OTP is locked, after locking, no more bits * can be changed but before locking it is still possible * to change bits from 1->0. - * @freq clocking frequency for the OTP, this frequency is either + * @freq: clocking frequency for the OTP, this frequency is either * 32768Hz or 1MHz/30 - * @paf product activation flag, indicates whether this is a real + * @paf: product activation flag, indicates whether this is a real * product (paf true) or a lab board etc (paf false) - * @imeich if this is set it is possible to override the + * @imeich: if this is set it is possible to override the * IMEI number found in the tac, fac and svn fields with * (secured) software - * @cid customer ID - * @tac type allocation code of the IMEI - * @fac final assembly code of the IMEI - * @svn software version number of the IMEI - * @debugfs a debugfs file used when dumping to file + * @cid: customer ID + * @tac: type allocation code of the IMEI + * @fac: final assembly code of the IMEI + * @svn: software version number of the IMEI + * @debugfs: a debugfs file used when dumping to file */ struct ab3100_otp { struct device *dev; -- GitLab From 2fbd583443905d6f8c6d87aebdef2717ae039f0b Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 13:31:31 +0100 Subject: [PATCH 0266/1754] mfd: tps65010: Remove delcared and set, but never used variable 'status' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'status' hasn't been checked since 2008. It's probably safe to remove it. Fixes W=1 warning: drivers/mfd/tps65010.c:407:7: warning: variable ‘status’ set but not used [-Wunused-but-set-variable] 407 | int status; | ^~~~~~ Signed-off-by: Lee Jones --- drivers/mfd/tps65010.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c index 65fcc58c02da8..7e7dbee58ca90 100644 --- a/drivers/mfd/tps65010.c +++ b/drivers/mfd/tps65010.c @@ -404,7 +404,6 @@ static void tps65010_work(struct work_struct *work) tps65010_interrupt(tps); if (test_and_clear_bit(FLAG_VBUS_CHANGED, &tps->flags)) { - int status; u8 chgconfig, tmp; chgconfig = i2c_smbus_read_byte_data(tps->client, @@ -415,8 +414,8 @@ static void tps65010_work(struct work_struct *work) else if (tps->vbus >= 100) chgconfig |= TPS_VBUS_CHARGING; - status = i2c_smbus_write_byte_data(tps->client, - TPS_CHGCONFIG, chgconfig); + i2c_smbus_write_byte_data(tps->client, + TPS_CHGCONFIG, chgconfig); /* vbus update fails unless VBUS is connected! */ tmp = i2c_smbus_read_byte_data(tps->client, TPS_CHGCONFIG); -- GitLab From 3c719388f6ff505239f8285a423571236abbd3c2 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 13:36:23 +0100 Subject: [PATCH 0267/1754] mfd: si476x-cmd: Repair wrongly described function argument 's/response/resp' si476x_core_send_command()'s 5th argument has never been called response. This change must have occurred prior to the driver being Mainlined. We're also taking the opportunity to bring the first description back into line, making my OCD happy! This fixes the following W=1 warning(s): drivers/mfd/si476x-cmd.c:264: warning: Function parameter or member 'resp' not described in 'si476x_core_send_command drivers/mfd/si476x-cmd.c:264: warning: Excess function parameter 'response' description in 'si476x_core_send_command' Cc: Andrey Smirnov Signed-off-by: Lee Jones --- drivers/mfd/si476x-cmd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c index 4a09ce9609c90..316d44c2edcd4 100644 --- a/drivers/mfd/si476x-cmd.c +++ b/drivers/mfd/si476x-cmd.c @@ -241,13 +241,13 @@ static int si476x_core_parse_and_nag_about_error(struct si476x_core *core) /** * si476x_core_send_command() - sends a command to si476x and waits its * response - * @core: si476x_device structure for the device we are + * @core: si476x_device structure for the device we are * communicating with * @command: command id * @args: command arguments we are sending * @argn: actual size of @args - * @response: buffer to place the expected response from the device - * @respn: actual size of @response + * @resp: buffer to place the expected response from the device + * @respn: actual size of @resp * @usecs: amount of time to wait before reading the response (in * usecs) * -- GitLab From 9745ef7dcf86bbad277c4a6575393a4eaabca1b4 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 13:43:25 +0100 Subject: [PATCH 0268/1754] mfd: si476x-cmd: Add missing colon(s) for all documented kerneldoc arguments Kerneldoc validation gets confused if syntax isn't "@.*: ". Adding the missing colons squashes the following W=1 warnings: drivers/mfd/si476x-cmd.c:525: warning: Function parameter or member 'dout' not described in 'si476x_core_cmd_dig_audio_pin_c drivers/mfd/si476x-cmd.c:525: warning: Function parameter or member 'xout' not described in 'si476x_core_cmd_dig_audio_pin_c drivers/mfd/si476x-cmd.c:574: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_zif_pin_cfg' drivers/mfd/si476x-cmd.c:574: warning: Function parameter or member 'iqclk' not described in 'si476x_core_cmd_zif_pin_cfg' drivers/mfd/si476x-cmd.c:574: warning: Function parameter or member 'iqfs' not described in 'si476x_core_cmd_zif_pin_cfg' drivers/mfd/si476x-cmd.c:574: warning: Function parameter or member 'iout' not described in 'si476x_core_cmd_zif_pin_cfg' drivers/mfd/si476x-cmd.c:574: warning: Function parameter or member 'qout' not described in 'si476x_core_cmd_zif_pin_cfg' drivers/mfd/si476x-i2c.c:550: warning: Function parameter or member 'func' not described in 'si476x_core_fwver_to_revision' drivers/mfd/si476x-cmd.c:631: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_ic_link_gpo_ctl drivers/mfd/si476x-cmd.c:631: warning: Function parameter or member 'icin' not described in 'si476x_core_cmd_ic_link_gpo_ctl drivers/mfd/si476x-cmd.c:631: warning: Function parameter or member 'icip' not described in 'si476x_core_cmd_ic_link_gpo_ctl drivers/mfd/si476x-cmd.c:631: warning: Function parameter or member 'icon' not described in 'si476x_core_cmd_ic_link_gpo_ctl drivers/mfd/si476x-cmd.c:631: warning: Function parameter or member 'icop' not described in 'si476x_core_cmd_ic_link_gpo_ctl drivers/mfd/si476x-cmd.c:662: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_ana_audio_pin_c drivers/mfd/si476x-cmd.c:662: warning: Function parameter or member 'lrout' not described in 'si476x_core_cmd_ana_audio_pin_ drivers/mfd/si476x-cmd.c:697: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_intb_pin_cfg_a1 drivers/mfd/si476x-cmd.c:697: warning: Function parameter or member 'intb' not described in 'si476x_core_cmd_intb_pin_cfg_a1 drivers/mfd/si476x-cmd.c:697: warning: Function parameter or member 'a1' not described in 'si476x_core_cmd_intb_pin_cfg_a10' drivers/mfd/si476x-cmd.c:746: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_am_rsq_status' drivers/mfd/si476x-cmd.c:746: warning: Function parameter or member 'rsqargs' not described in 'si476x_core_cmd_am_rsq_statu drivers/mfd/si476x-cmd.c:746: warning: Function parameter or member 'report' not described in 'si476x_core_cmd_am_rsq_status drivers/mfd/si476x-cmd.c:878: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_fm_seek_start' drivers/mfd/si476x-cmd.c:878: warning: Function parameter or member 'seekup' not described in 'si476x_core_cmd_fm_seek_start drivers/mfd/si476x-cmd.c:878: warning: Function parameter or member 'wrap' not described in 'si476x_core_cmd_fm_seek_start' drivers/mfd/si476x-cmd.c:907: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_fm_rds_status' drivers/mfd/si476x-cmd.c:907: warning: Function parameter or member 'status_only' not described in 'si476x_core_cmd_fm_rds_s drivers/mfd/si476x-cmd.c:907: warning: Function parameter or member 'mtfifo' not described in 'si476x_core_cmd_fm_rds_status drivers/mfd/si476x-cmd.c:907: warning: Function parameter or member 'intack' not described in 'si476x_core_cmd_fm_rds_status drivers/mfd/si476x-cmd.c:907: warning: Function parameter or member 'report' not described in 'si476x_core_cmd_fm_rds_status drivers/mfd/si476x-cmd.c:1052: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_am_seek_start' drivers/mfd/si476x-cmd.c:1052: warning: Function parameter or member 'seekup' not described in 'si476x_core_cmd_am_seek_star drivers/mfd/si476x-cmd.c:1052: warning: Function parameter or member 'wrap' not described in 'si476x_core_cmd_am_seek_start' Cc: Andrey Smirnov Signed-off-by: Lee Jones --- drivers/mfd/si476x-cmd.c | 66 ++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c index 316d44c2edcd4..5b42dfab431a3 100644 --- a/drivers/mfd/si476x-cmd.c +++ b/drivers/mfd/si476x-cmd.c @@ -496,7 +496,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_get_property); * enable 1MOhm pulldown * SI476X_DFS_DAUDIO - set the pin to be a part of digital * audio interface - * @dout - DOUT pin function configuration: + * @dout: - DOUT pin function configuration: * SI476X_DOUT_NOOP - do not modify the behaviour * SI476X_DOUT_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown @@ -504,7 +504,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_get_property); * port 1 * SI476X_DOUT_I2S_INPUT - set this pin to be digital in on I2S * port 1 - * @xout - XOUT pin function configuration: + * @xout: - XOUT pin function configuration: * SI476X_XOUT_NOOP - do not modify the behaviour * SI476X_XOUT_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown @@ -540,25 +540,25 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_dig_audio_pin_cfg); /** * si476x_cmd_zif_pin_cfg - send 'ZIF_PIN_CFG_COMMAND' - * @core - device to send the command to - * @iqclk - IQCL pin function configuration: + * @core: - device to send the command to + * @iqclk: - IQCL pin function configuration: * SI476X_IQCLK_NOOP - do not modify the behaviour * SI476X_IQCLK_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown * SI476X_IQCLK_IQ - set pin to be a part of I/Q interace * in master mode - * @iqfs - IQFS pin function configuration: + * @iqfs: - IQFS pin function configuration: * SI476X_IQFS_NOOP - do not modify the behaviour * SI476X_IQFS_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown * SI476X_IQFS_IQ - set pin to be a part of I/Q interace * in master mode - * @iout - IOUT pin function configuration: + * @iout: - IOUT pin function configuration: * SI476X_IOUT_NOOP - do not modify the behaviour * SI476X_IOUT_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown * SI476X_IOUT_OUTPUT - set pin to be I out - * @qout - QOUT pin function configuration: + * @qout: - QOUT pin function configuration: * SI476X_QOUT_NOOP - do not modify the behaviour * SI476X_QOUT_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown @@ -590,29 +590,29 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_zif_pin_cfg); /** * si476x_cmd_ic_link_gpo_ctl_pin_cfg - send * 'IC_LINK_GPIO_CTL_PIN_CFG' comand to the device - * @core - device to send the command to - * @icin - ICIN pin function configuration: + * @core: - device to send the command to + * @icin: - ICIN pin function configuration: * SI476X_ICIN_NOOP - do not modify the behaviour * SI476X_ICIN_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown * SI476X_ICIN_GPO1_HIGH - set pin to be an output, drive it high * SI476X_ICIN_GPO1_LOW - set pin to be an output, drive it low * SI476X_ICIN_IC_LINK - set the pin to be a part of Inter-Chip link - * @icip - ICIP pin function configuration: + * @icip: - ICIP pin function configuration: * SI476X_ICIP_NOOP - do not modify the behaviour * SI476X_ICIP_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown * SI476X_ICIP_GPO1_HIGH - set pin to be an output, drive it high * SI476X_ICIP_GPO1_LOW - set pin to be an output, drive it low * SI476X_ICIP_IC_LINK - set the pin to be a part of Inter-Chip link - * @icon - ICON pin function configuration: + * @icon: - ICON pin function configuration: * SI476X_ICON_NOOP - do not modify the behaviour * SI476X_ICON_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown * SI476X_ICON_I2S - set the pin to be a part of audio * interface in slave mode (DCLK) * SI476X_ICON_IC_LINK - set the pin to be a part of Inter-Chip link - * @icop - ICOP pin function configuration: + * @icop: - ICOP pin function configuration: * SI476X_ICOP_NOOP - do not modify the behaviour * SI476X_ICOP_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown @@ -647,8 +647,8 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_ic_link_gpo_ctl_pin_cfg); /** * si476x_cmd_ana_audio_pin_cfg - send 'ANA_AUDIO_PIN_CFG' to the * device - * @core - device to send the command to - * @lrout - LROUT pin function configuration: + * @core: - device to send the command to + * @lrout: - LROUT pin function configuration: * SI476X_LROUT_NOOP - do not modify the behaviour * SI476X_LROUT_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown @@ -675,15 +675,15 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_ana_audio_pin_cfg); /** * si476x_cmd_intb_pin_cfg - send 'INTB_PIN_CFG' command to the device - * @core - device to send the command to - * @intb - INTB pin function configuration: + * @core: - device to send the command to + * @intb: - INTB pin function configuration: * SI476X_INTB_NOOP - do not modify the behaviour * SI476X_INTB_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown * SI476X_INTB_DAUDIO - set pin to be a part of digital * audio interface in slave mode * SI476X_INTB_IRQ - set pin to be an interrupt request line - * @a1 - A1 pin function configuration: + * @a1: - A1 pin function configuration: * SI476X_A1_NOOP - do not modify the behaviour * SI476X_A1_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown @@ -728,14 +728,14 @@ static int si476x_core_cmd_intb_pin_cfg_a20(struct si476x_core *core, /** * si476x_cmd_am_rsq_status - send 'AM_RSQ_STATUS' command to the * device - * @core - device to send the command to - * @rsqack - if set command clears RSQINT, SNRINT, SNRLINT, RSSIHINT, + * @core: - device to send the command to + * @rsqack: - if set command clears RSQINT, SNRINT, SNRLINT, RSSIHINT, * RSSSILINT, BLENDINT, MULTHINT and MULTLINT - * @attune - when set the values in the status report are the values + * @attune: - when set the values in the status report are the values * that were calculated at tune - * @cancel - abort ongoing seek/tune opertation - * @stcack - clear the STCINT bin in status register - * @report - all signal quality information retured by the command + * @cancel: - abort ongoing seek/tune opertation + * @stcack: - clear the STCINT bin in status register + * @report: - all signal quality information retured by the command * (if NULL then the output of the command is ignored) * * Function returns 0 on success and negative error code on failure @@ -862,9 +862,9 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_am_acf_status); /** * si476x_cmd_fm_seek_start - send 'FM_SEEK_START' command to the * device - * @core - device to send the command to - * @seekup - if set the direction of the search is 'up' - * @wrap - if set seek wraps when hitting band limit + * @core: - device to send the command to + * @seekup: - if set the direction of the search is 'up' + * @wrap: - if set seek wraps when hitting band limit * * This function begins search for a valid station. The station is * considered valid when 'FM_VALID_SNR_THRESHOLD' and @@ -890,12 +890,12 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_seek_start); /** * si476x_cmd_fm_rds_status - send 'FM_RDS_STATUS' command to the * device - * @core - device to send the command to - * @status_only - if set the data is not removed from RDSFIFO, + * @core: - device to send the command to + * @status_only: - if set the data is not removed from RDSFIFO, * RDSFIFOUSED is not decremented and data in all the * rest RDS data contains the last valid info received - * @mtfifo if set the command clears RDS receive FIFO - * @intack if set the command clards the RDSINT bit. + * @mtfifo: if set the command clears RDS receive FIFO + * @intack: if set the command clards the RDSINT bit. * * Function returns 0 on success and negative error code on failure */ @@ -1036,9 +1036,9 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_phase_div_status); /** * si476x_cmd_am_seek_start - send 'FM_SEEK_START' command to the * device - * @core - device to send the command to - * @seekup - if set the direction of the search is 'up' - * @wrap - if set seek wraps when hitting band limit + * @core: - device to send the command to + * @seekup: - if set the direction of the search is 'up' + * @wrap: - if set seek wraps when hitting band limit * * This function begins search for a valid station. The station is * considered valid when 'FM_VALID_SNR_THRESHOLD' and -- GitLab From c9b55f99fc679b3c7c9c1677b2fd2c86d6ac5e03 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 14:32:06 +0100 Subject: [PATCH 0269/1754] mfd: si476x-i2c: Add description for si476x_core_fwver_to_revision()'s arg 'func' Kerneldoc syntax is used, but not complete. Descriptions are required for all arguments. Fixes the following W=1 build warning: drivers/mfd/si476x-i2c.c:550: warning: Function parameter or member 'func' not described in 'si476x_core_fwver_to_revision' Cc: Andrey Smirnov Signed-off-by: Lee Jones --- drivers/mfd/si476x-i2c.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c index c8d28b844def8..517d49bcd667b 100644 --- a/drivers/mfd/si476x-i2c.c +++ b/drivers/mfd/si476x-i2c.c @@ -534,6 +534,11 @@ static irqreturn_t si476x_core_interrupt(int irq, void *dev) /** * si476x_firmware_version_to_revision() * @core: Core device structure + * @func: Selects the boot function of the device: + * *_BOOTLOADER - Boot loader + * *_FM_RECEIVER - FM receiver + * *_AM_RECEIVER - AM receiver + * *_WB_RECEIVER - Weatherband receiver * @major: Firmware major number * @minor1: Firmware first minor number * @minor2: Firmware second minor number -- GitLab From b1ded80a61f3b7ee5337318f0dc1bada280f0605 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 14:32:33 +0100 Subject: [PATCH 0270/1754] mfd: si476x-i2c: Fix spelling mistake in case() statement's FALLTHROUGH comment 's/FALLTHROUG/FALLTHROUGH' Cc: Andrey Smirnov Signed-off-by: Lee Jones --- drivers/mfd/si476x-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c index 517d49bcd667b..c1d7b845244ed 100644 --- a/drivers/mfd/si476x-i2c.c +++ b/drivers/mfd/si476x-i2c.c @@ -588,7 +588,7 @@ static int si476x_core_fwver_to_revision(struct si476x_core *core, goto unknown_revision; } case SI476X_FUNC_BOOTLOADER: - default: /* FALLTHROUG */ + default: /* FALLTHROUGH */ BUG(); return -1; } -- GitLab From 748160e7718d1fb3c90c0df86c4b07e4b5e92621 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 14:26:16 +0100 Subject: [PATCH 0271/1754] mfd: si476x-cmd: Update si476x_cmd_am_rsq_status()'s kerneldoc 4 of the old arguments were grouped and moved into a struct which is now passed as a pointer instead of the arguments themselves. However, whoever carried out this work forgot to update the function's kerneldoc header. Fixes the following W=1 warnings: drivers/mfd/si476x-cmd.c:746: warning: Function parameter or member 'rsqargs' not described in 'si476x_core_cmd_am_rsq_s drivers/mfd/si476x-cmd.c:746: warning: Excess function parameter 'rsqack' description in 'si476x_core_cmd_am_rsq_status' drivers/mfd/si476x-cmd.c:746: warning: Excess function parameter 'attune' description in 'si476x_core_cmd_am_rsq_status' drivers/mfd/si476x-cmd.c:746: warning: Excess function parameter 'cancel' description in 'si476x_core_cmd_am_rsq_status' drivers/mfd/si476x-cmd.c:746: warning: Excess function parameter 'stcack' description in 'si476x_core_cmd_am_rsq_status' Cc: Andrey Smirnov Signed-off-by: Lee Jones --- drivers/mfd/si476x-cmd.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c index 5b42dfab431a3..0a40c5cb751db 100644 --- a/drivers/mfd/si476x-cmd.c +++ b/drivers/mfd/si476x-cmd.c @@ -729,12 +729,8 @@ static int si476x_core_cmd_intb_pin_cfg_a20(struct si476x_core *core, * si476x_cmd_am_rsq_status - send 'AM_RSQ_STATUS' command to the * device * @core: - device to send the command to - * @rsqack: - if set command clears RSQINT, SNRINT, SNRLINT, RSSIHINT, - * RSSSILINT, BLENDINT, MULTHINT and MULTLINT - * @attune: - when set the values in the status report are the values - * that were calculated at tune - * @cancel: - abort ongoing seek/tune opertation - * @stcack: - clear the STCINT bin in status register + * @rsqargs: - pointer to a structure containing a group of sub-args + * relevant to sending the RSQ status command * @report: - all signal quality information retured by the command * (if NULL then the output of the command is ignored) * -- GitLab From 981b1261bfdf7cb3e3c2029ecc4a1510d46eff9e Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 14:29:18 +0100 Subject: [PATCH 0272/1754] mfd: si476x-cmd: Add missing documentation for si476x_cmd_fm_rds_status()'s arg 'report' Kerneldoc syntax is used, but not complete. Descriptions are required for all arguments. Fixes the following W=1 build warning: drivers/mfd/si476x-cmd.c:907: warning: Function parameter or member 'report' not described in 'si476x_core_cmd_fm_rds_status' Cc: Andrey Smirnov Signed-off-by: Lee Jones --- drivers/mfd/si476x-cmd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c index 0a40c5cb751db..d15b3e7833692 100644 --- a/drivers/mfd/si476x-cmd.c +++ b/drivers/mfd/si476x-cmd.c @@ -892,6 +892,8 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_seek_start); * rest RDS data contains the last valid info received * @mtfifo: if set the command clears RDS receive FIFO * @intack: if set the command clards the RDSINT bit. + * @report: - all signal quality information retured by the command + * (if NULL then the output of the command is ignored) * * Function returns 0 on success and negative error code on failure */ -- GitLab From 768c1e38dc43b1fc43f73409f58c58344f243892 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 14:52:27 +0100 Subject: [PATCH 0273/1754] mfd: rave-sp: Fix mistake in 'struct rave_sp_deframer's kerneldoc Argument 'received' was incorrectly named by its struct type 'completion' instead of its name. Fixes the following W=1 warning: drivers/mfd/rave-sp.c:107: warning: Function parameter or member 'received' not described in 'rave_sp_reply' Cc: Andrey Vostrikov Cc: Nikita Yushchenko Cc: Andrey Smirnov Signed-off-by: Lee Jones --- drivers/mfd/rave-sp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c index 26c7b63e008a8..abaab541df19d 100644 --- a/drivers/mfd/rave-sp.c +++ b/drivers/mfd/rave-sp.c @@ -96,7 +96,7 @@ struct rave_sp_deframer { * @data: Buffer to store reply payload in * @code: Expected reply code * @ackid: Expected reply ACK ID - * @completion: Successful reply reception completion + * @received: Successful reply reception completion */ struct rave_sp_reply { size_t length; -- GitLab From ec46855df33973ac6ed646e26cc8977b97cc7cd0 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 25 Jun 2020 09:39:11 +0100 Subject: [PATCH 0274/1754] mfd: sprd-sc27xx-spi: Fix-up bogus IRQ register offset and mask setting 'i / pdata->num_irqs' always equates to 0 and 'BIT(i % pdata->num_irqs)' always ends up being BIT(i) here, so make that clearer in the code. If the code base needs to support more than 32 IRQs in the future, this will have to be reworked, but lets just keep it simple for as long as we can. This fixes the following W=1 warning: drivers/mfd/sprd-sc27xx-spi.c:255 sprd_pmic_probe() debug: sval_binop_unsigned: divide by zero Cc: Orson Zhai Cc: Chunyan Zhang Suggested-by: Baolin Wang Signed-off-by: Lee Jones Reviewed-by: Baolin Wang Signed-off-by: Lee Jones --- drivers/mfd/sprd-sc27xx-spi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c index d3486c2a1b339..f8a8b918c60d9 100644 --- a/drivers/mfd/sprd-sc27xx-spi.c +++ b/drivers/mfd/sprd-sc27xx-spi.c @@ -185,10 +185,8 @@ static int sprd_pmic_probe(struct spi_device *spi) return -ENOMEM; ddata->irq_chip.irqs = ddata->irqs; - for (i = 0; i < pdata->num_irqs; i++) { - ddata->irqs[i].reg_offset = i / pdata->num_irqs; - ddata->irqs[i].mask = BIT(i % pdata->num_irqs); - } + for (i = 0; i < pdata->num_irqs; i++) + ddata->irqs[i].mask = BIT(i); ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq, IRQF_ONESHOT | IRQF_NO_SUSPEND, 0, -- GitLab From 662081acfa25edf0d8fabd8021ac26f0d1e2d3a1 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Thu, 2 Jul 2020 14:53:47 -0400 Subject: [PATCH 0275/1754] tools lib traceevent: Add tep_load_plugins_hook() API Add the API function tep_load_plugins_hook() to the traceevent API to allow tools a common method to load in the plugins that are part of the lib traceevent library. Link: http://lore.kernel.org/linux-trace-devel/20190802110101.14759-4-tz.stoyanov@gmail.com Link: http://lore.kernel.org/linux-trace-devel/20200625100516.365338-4-tz.stoyanov@gmail.com Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: linux-trace-devel@vger.kernel.org Link: http://lore.kernel.org/lkml/20200702185703.946652691@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 6 ++++++ tools/lib/traceevent/event-plugin.c | 19 +++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index b77837f75a0d7..776c7c24ee792 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -396,6 +396,12 @@ struct tep_plugin_list; struct tep_plugin_list *tep_load_plugins(struct tep_handle *tep); void tep_unload_plugins(struct tep_plugin_list *plugin_list, struct tep_handle *tep); +void tep_load_plugins_hook(struct tep_handle *tep, const char *suffix, + void (*load_plugin)(struct tep_handle *tep, + const char *path, + const char *name, + void *data), + void *data); char **tep_plugin_list_options(void); void tep_plugin_free_options_list(char **list); int tep_plugin_add_options(const char *name, diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index e1f7ddd5a6cf0..b53d9a53bcf95 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -365,20 +365,19 @@ load_plugins_dir(struct tep_handle *tep, const char *suffix, closedir(dir); } -static void -load_plugins(struct tep_handle *tep, const char *suffix, - void (*load_plugin)(struct tep_handle *tep, - const char *path, - const char *name, - void *data), - void *data) +void tep_load_plugins_hook(struct tep_handle *tep, const char *suffix, + void (*load_plugin)(struct tep_handle *tep, + const char *path, + const char *name, + void *data), + void *data) { char *home; char *path; char *envdir; int ret; - if (tep->flags & TEP_DISABLE_PLUGINS) + if (tep && tep->flags & TEP_DISABLE_PLUGINS) return; /* @@ -386,7 +385,7 @@ load_plugins(struct tep_handle *tep, const char *suffix, * check that first. */ #ifdef PLUGIN_DIR - if (!(tep->flags & TEP_DISABLE_SYS_PLUGINS)) + if (!tep || !(tep->flags & TEP_DISABLE_SYS_PLUGINS)) load_plugins_dir(tep, suffix, PLUGIN_DIR, load_plugin, data); #endif @@ -423,7 +422,7 @@ tep_load_plugins(struct tep_handle *tep) { struct tep_plugin_list *list = NULL; - load_plugins(tep, ".so", load_plugin, &list); + tep_load_plugins_hook(tep, ".so", load_plugin, &list); return list; } -- GitLab From 74006289cfedbb2f922fcd6fef7efee232450550 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Thu, 2 Jul 2020 14:53:48 -0400 Subject: [PATCH 0276/1754] tools lib traceevent: Add interface for options to plugins Add tep_plugin_add_option() and tep_plugin_print_options() to lib traceevent library that allows plugins to have their own options. For example, the function plugin by default does not print the parent, as it uses the parent to do the indenting. The "parent" option is created by the function plugin that will print the parent of the function like it does in the trace file. The tep_plugin_print_options() will print out the list of options that a Cc: Tzvetomir Stoyanov (VMware) plugin has defined. Link: http://lore.kernel.org/linux-trace-devel/20190802110101.14759-3-tz.stoyanov@gmail.com Link: http://lore.kernel.org/linux-trace-devel/20200625100516.365338-5-tz.stoyanov@gmail.com Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: linux-trace-devel@vger.kernel.org Link: http://lore.kernel.org/lkml/20200702185704.092654084@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 2 + tools/lib/traceevent/event-plugin.c | 172 ++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 776c7c24ee792..02c0438527de6 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -406,7 +406,9 @@ char **tep_plugin_list_options(void); void tep_plugin_free_options_list(char **list); int tep_plugin_add_options(const char *name, struct tep_plugin_option *options); +int tep_plugin_add_option(const char *name, const char *val); void tep_plugin_remove_options(struct tep_plugin_option *options); +void tep_plugin_print_options(struct trace_seq *s); void tep_print_plugins(struct trace_seq *s, const char *prefix, const char *suffix, const struct tep_plugin_list *list); diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index b53d9a53bcf95..e8f4329ba8e08 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "event-parse.h" #include "event-parse-local.h" #include "event-utils.h" @@ -247,6 +248,166 @@ void tep_plugin_remove_options(struct tep_plugin_option *options) } } +static void parse_option_name(char **option, char **plugin) +{ + char *p; + + *plugin = NULL; + + if ((p = strstr(*option, ":"))) { + *plugin = *option; + *p = '\0'; + *option = strdup(p + 1); + if (!*option) + return; + } +} + +static struct tep_plugin_option * +find_registered_option(const char *plugin, const char *option) +{ + struct registered_plugin_options *reg; + struct tep_plugin_option *op; + const char *op_plugin; + + for (reg = registered_options; reg; reg = reg->next) { + for (op = reg->options; op->name; op++) { + if (op->plugin_alias) + op_plugin = op->plugin_alias; + else + op_plugin = op->file; + + if (plugin && strcmp(plugin, op_plugin) != 0) + continue; + if (strcmp(option, op->name) != 0) + continue; + + return op; + } + } + + return NULL; +} + +static int process_option(const char *plugin, const char *option, const char *val) +{ + struct tep_plugin_option *op; + + op = find_registered_option(plugin, option); + if (!op) + return 0; + + return update_option_value(op, val); +} + +/** + * tep_plugin_add_option - add an option/val pair to set plugin options + * @name: The name of the option (format: :