Received: by 2002:ab2:6991:0:b0:1f7:f6c3:9cb1 with SMTP id v17csp117465lqo; Tue, 7 May 2024 14:10:48 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCURVkWqr2hTVL/CU7Y16Qukp2JXqBuYEJh4W+FpPUbntz+/nUd31q5NQKKoJ22qUVm17Vg+yWIs2xgjOxrotmxPW7nXatX5J3eiOVTeyQ== X-Google-Smtp-Source: AGHT+IGdzw49l4fdAyM8TNKcAudxDzk0Ft7DNOJuunpRDRtv9QbtaLTC1wbikNgr4dannEZ4duUT X-Received: by 2002:a05:6358:a081:b0:183:676f:c751 with SMTP id e5c5f4694b2df-192d3779467mr89484455d.27.1715116247965; Tue, 07 May 2024 14:10:47 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1715116247; cv=pass; d=google.com; s=arc-20160816; b=AiMv+nSTrOaRtHJuSwWp9XgkF6ejbuOqK15/X8ldE46MhiwyFkT6RfF8xFgfoUqy1c ebUh3HjlvmLirNFDOxjWsEUB8QsCwkLvbPO4xasCFKWkDWb18RtuQ2f5nXv44i4QMOu+ wCHY0FiBmD7birUwwU498Ug0vaWO9j5j0L/Y2sz0rrpsZbEbKsCniLeDCy00gp082Jyq d/rIbD0QNgAFpdrUO+c39IqhgvdiEQUo3SB5jOOakwzIEcifWQQnTbq1TxCCU8umv5Uy E/Xm1lGxpxYFHEXF98NIB9I8U1A/3OiHI4IUl8BG2tdJY+mf7SU1xRuvB6/pCCWI/PZ+ gcmg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=jIrgrdgSlbwxyyIs/UfEhM/fX9rf+oljK/B715RAGj8=; fh=zMqz0EhlP/Kdp8xKYGCXNXp4fjAlj6i2cQXvtWVsRBI=; b=rHB27ing6ogWY05REy0sBJZwL7QI7hoHrvaUtRK5Ft/HeeKjn3EszNI+QgQ/m4twP1 A8VWt2B79vHG4P6VqV13ZTPBd/Yeh//sWFTiuR0XFsUUywT2oXyk0MG0to6GwqjOCqgw hSdwxyCmUMJc6Jd5xdWoYpar9zMeijf3m3EnwQJXKDg3nBBoqiuF23a4OtXV/LY4Ajkl Ds68mE5iMXzYVvaUoQ9g0HD+M7CN/7sJeGg1D1zTvT2ZfTwFfkDhD9Zk/sgfh06UAqvL BtLZfb7ulfSjxtcABDv1q1rcsGzTmoVB7iIXnmrAGtMI5oHlY74CtfzV0c36n0OnVOaA L7MQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=gUoow74l; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-172203-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-172203-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id h36-20020a635324000000b0061c26673e52si9902362pgb.286.2024.05.07.14.10.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 May 2024 14:10:47 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-172203-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=gUoow74l; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-172203-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-172203-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 923E8286C31 for ; Tue, 7 May 2024 21:10:20 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 499CC16F8F7; Tue, 7 May 2024 21:08:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gUoow74l" Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DDB3816F295; Tue, 7 May 2024 21:08:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715116097; cv=none; b=B/43zAyiaDrdqUeH+yAzAwOU2cNLs5iJINS+TbSB6zg0G9biCComla0NNBuYT6aFmBTT0hWx0b1hy/qZQ2wii41Tl7Pi7UaqbmhKJJTdukD5f8YmG+qNg9a1AS+ShiVEdZpPpAGf3jjwxCb3BPm3QxUYAph6jfbctzM3aG5uKEk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715116097; c=relaxed/simple; bh=bUppT8Dy6MFHwbTO/evlputnORSltr6bWDcr7c5nCU0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KoeXFGG6VnAcDRfr6Znc8YJ6ey2IEOGKgInGplveZayYs4FA3AgEQ94P+Pf2qRXKCc6CyNrPC9gwjXLeMExsShJn2uHD/qc+oovnHlEpqOTLJS5TH5hN4t0+tiP77tHuvgvMUnc18HwZ3aRD2IwI5E6O95QeLFkoUCsxlHLETDc= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gUoow74l; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7C473C2BBFC; Tue, 7 May 2024 21:08:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1715116096; bh=bUppT8Dy6MFHwbTO/evlputnORSltr6bWDcr7c5nCU0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gUoow74ld8KXti0QwNLIdS9QKnwXh7Yvd3cHZyJGZ7fZN5/KJUdz+Rqlm7/E1rg9p B5e5R7H06AZ/yP5PBFdNi9xuE8WlS8lVWMI6t8FZRqE/uespNGL9AlpgxlYE/zO+Q0 8Iw6bhrYFUnANoy64/VhVcgYlpSU5StGoRzvhgaJ+CdAqQwhStLu3MqSGRYPvQrr4v XLgzvDjdQZ642WbsoaV878SIHVFFzz+E7TvyebHG4pxniV4pNLARGjUV8I84lIGyFZ eVhBheinIXH852ZYwFEf4ks83dnbE1DBmbQxBxtxswOML8lVt8S6tN6tkp1eaCkWe3 vnWlSywe4Bhog== From: Stephen Boyd To: Greg Kroah-Hartman Cc: Abel Vesa , linux-kernel@vger.kernel.org, patches@lists.linux.dev, Neil Armstrong Subject: [PATCH 12/12] spmi: pmic-arb: Add multi bus support Date: Tue, 7 May 2024 14:07:49 -0700 Message-ID: <20240507210809.3479953-13-sboyd@kernel.org> X-Mailer: git-send-email 2.45.0.rc1.225.g2a3ae87e7f-goog In-Reply-To: <20240507210809.3479953-1-sboyd@kernel.org> References: <20240507210809.3479953-1-sboyd@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Abel Vesa Starting with HW version 7, there are actually two separate buses (with two separate sets of wires). So add support for the second bus. The first platform that needs this support for the second bus is the Qualcomm X1 Elite, so add the compatible for it as well. Reviewed-by: Neil Armstrong Signed-off-by: Abel Vesa Link: https://lore.kernel.org/r/20240417-spmi-multi-master-support-v10-7-5bc6d322e266@linaro.org Signed-off-by: Stephen Boyd --- drivers/spmi/spmi-pmic-arb.c | 138 ++++++++++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 18 deletions(-) diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c index c3dd5d2aa244..791cdc160c51 100644 --- a/drivers/spmi/spmi-pmic-arb.c +++ b/drivers/spmi/spmi-pmic-arb.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -95,6 +96,8 @@ enum pmic_arb_channel { PMIC_ARB_CHANNEL_OBS, }; +#define PMIC_ARB_MAX_BUSES 2 + /* Maximum number of support PMIC peripherals */ #define PMIC_ARB_MAX_PERIPHS 512 #define PMIC_ARB_MAX_PERIPHS_V7 1024 @@ -149,6 +152,7 @@ struct spmi_pmic_arb; * @min_apid: minimum APID (used for bounding IRQ search) * @max_apid: maximum APID * @irq: PMIC ARB interrupt. + * @id: unique ID of the bus */ struct spmi_pmic_arb_bus { struct spmi_pmic_arb *pmic_arb; @@ -167,6 +171,7 @@ struct spmi_pmic_arb_bus { u16 min_apid; u16 max_apid; int irq; + u8 id; }; /** @@ -180,7 +185,8 @@ struct spmi_pmic_arb_bus { * @ee: the current Execution Environment * @ver_ops: version dependent operations. * @max_periphs: Number of elements in apid_data[] - * @bus: per arbiter bus instance + * @buses: per arbiter buses instances + * @buses_available: number of buses registered */ struct spmi_pmic_arb { void __iomem *rd_base; @@ -191,7 +197,8 @@ struct spmi_pmic_arb { u8 ee; const struct pmic_arb_ver_ops *ver_ops; int max_periphs; - struct spmi_pmic_arb_bus *bus; + struct spmi_pmic_arb_bus *buses[PMIC_ARB_MAX_BUSES]; + int buses_available; }; /** @@ -220,7 +227,7 @@ struct spmi_pmic_arb { struct pmic_arb_ver_ops { const char *ver_str; int (*get_core_resources)(struct platform_device *pdev, void __iomem *core); - int (*init_apid)(struct spmi_pmic_arb_bus *bus); + int (*init_apid)(struct spmi_pmic_arb_bus *bus, int index); int (*ppid_to_apid)(struct spmi_pmic_arb_bus *bus, u16 ppid); /* spmi commands (read_cmd, write_cmd, cmd) functionality */ int (*offset)(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr, @@ -309,8 +316,8 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl, } if (status & PMIC_ARB_STATUS_FAILURE) { - dev_err(&ctrl->dev, "%s: %#x %#x: transaction failed (%#x)\n", - __func__, sid, addr, status); + dev_err(&ctrl->dev, "%s: %#x %#x: transaction failed (%#x) reg: 0x%x\n", + __func__, sid, addr, status, offset); WARN_ON(1); return -EIO; } @@ -326,8 +333,8 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl, udelay(1); } - dev_err(&ctrl->dev, "%s: %#x %#x: timeout, status %#x\n", - __func__, sid, addr, status); + dev_err(&ctrl->dev, "%s: %#x %#x %#x: timeout, status %#x\n", + __func__, bus->id, sid, addr, status); return -ETIMEDOUT; } @@ -1003,11 +1010,17 @@ static int pmic_arb_get_core_resources_v1(struct platform_device *pdev, return 0; } -static int pmic_arb_init_apid_v1(struct spmi_pmic_arb_bus *bus) +static int pmic_arb_init_apid_v1(struct spmi_pmic_arb_bus *bus, int index) { struct spmi_pmic_arb *pmic_arb = bus->pmic_arb; u32 *mapping_table; + if (index) { + dev_err(&bus->spmic->dev, "Unsupported buses count %d detected\n", + index); + return -EINVAL; + } + mapping_table = devm_kcalloc(&bus->spmic->dev, pmic_arb->max_periphs, sizeof(*mapping_table), GFP_KERNEL); if (!mapping_table) @@ -1250,11 +1263,17 @@ static int pmic_arb_offset_v2(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr, return 0x1000 * pmic_arb->ee + 0x8000 * apid; } -static int pmic_arb_init_apid_v5(struct spmi_pmic_arb_bus *bus) +static int pmic_arb_init_apid_v5(struct spmi_pmic_arb_bus *bus, int index) { struct spmi_pmic_arb *pmic_arb = bus->pmic_arb; int ret; + if (index) { + dev_err(&bus->spmic->dev, "Unsupported buses count %d detected\n", + index); + return -EINVAL; + } + bus->base_apid = 0; bus->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) & PMIC_ARB_FEATURES_PERIPH_MASK; @@ -1326,6 +1345,50 @@ static int pmic_arb_get_core_resources_v7(struct platform_device *pdev, return pmic_arb_get_obsrvr_chnls_v2(pdev); } +/* + * Only v7 supports 2 buses. Each bus will get a different apid count, read + * from different registers. + */ +static int pmic_arb_init_apid_v7(struct spmi_pmic_arb_bus *bus, int index) +{ + struct spmi_pmic_arb *pmic_arb = bus->pmic_arb; + int ret; + + if (index == 0) { + bus->base_apid = 0; + bus->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) & + PMIC_ARB_FEATURES_PERIPH_MASK; + } else if (index == 1) { + bus->base_apid = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES) & + PMIC_ARB_FEATURES_PERIPH_MASK; + bus->apid_count = readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES1) & + PMIC_ARB_FEATURES_PERIPH_MASK; + } else { + dev_err(&bus->spmic->dev, "Unsupported buses count %d detected\n", + bus->id); + return -EINVAL; + } + + if (bus->base_apid + bus->apid_count > pmic_arb->max_periphs) { + dev_err(&bus->spmic->dev, "Unsupported APID count %d detected\n", + bus->base_apid + bus->apid_count); + return -EINVAL; + } + + ret = pmic_arb_init_apid_min_max(bus); + if (ret) + return ret; + + ret = pmic_arb_read_apid_map_v5(bus); + if (ret) { + dev_err(&bus->spmic->dev, "could not read APID->PPID mapping table, rc= %d\n", + ret); + return ret; + } + + return 0; +} + /* * v7 offset per ee and per apid for observer channels and per apid for * read/write channels. @@ -1578,7 +1641,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v5 = { static const struct pmic_arb_ver_ops pmic_arb_v7 = { .ver_str = "v7", .get_core_resources = pmic_arb_get_core_resources_v7, - .init_apid = pmic_arb_init_apid_v5, + .init_apid = pmic_arb_init_apid_v7, .ppid_to_apid = pmic_arb_ppid_to_apid_v5, .non_data_cmd = pmic_arb_non_data_cmd_v2, .offset = pmic_arb_offset_v7, @@ -1602,6 +1665,7 @@ static int spmi_pmic_arb_bus_init(struct platform_device *pdev, struct device_node *node, struct spmi_pmic_arb *pmic_arb) { + int bus_index = pmic_arb->buses_available; struct spmi_pmic_arb_bus *bus; struct device *dev = &pdev->dev; struct spmi_controller *ctrl; @@ -1620,7 +1684,7 @@ static int spmi_pmic_arb_bus_init(struct platform_device *pdev, bus = spmi_controller_get_drvdata(ctrl); - pmic_arb->bus = bus; + pmic_arb->buses[bus_index] = bus; raw_spin_lock_init(&bus->lock); @@ -1665,12 +1729,13 @@ static int spmi_pmic_arb_bus_init(struct platform_device *pdev, bus->cnfg = cnfg; bus->irq = irq; bus->spmic = ctrl; + bus->id = bus_index; - ret = pmic_arb->ver_ops->init_apid(bus); + ret = pmic_arb->ver_ops->init_apid(bus, bus_index); if (ret) return ret; - dev_dbg(&pdev->dev, "adding irq domain\n"); + dev_dbg(&pdev->dev, "adding irq domain for bus %d\n", bus_index); bus->domain = irq_domain_add_tree(dev->of_node, &pmic_arb_irq_domain_ops, bus); @@ -1683,14 +1748,53 @@ static int spmi_pmic_arb_bus_init(struct platform_device *pdev, pmic_arb_chained_irq, bus); ctrl->dev.of_node = node; + dev_set_name(&ctrl->dev, "spmi-%d", bus_index); ret = devm_spmi_controller_add(dev, ctrl); if (ret) return ret; + pmic_arb->buses_available++; + return 0; } +static int spmi_pmic_arb_register_buses(struct spmi_pmic_arb *pmic_arb, + struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + struct device_node *child; + int ret; + + /* legacy mode doesn't provide child node for the bus */ + if (of_device_is_compatible(node, "qcom,spmi-pmic-arb")) + return spmi_pmic_arb_bus_init(pdev, node, pmic_arb); + + for_each_available_child_of_node(node, child) { + if (of_node_name_eq(child, "spmi")) { + ret = spmi_pmic_arb_bus_init(pdev, child, pmic_arb); + if (ret) + return ret; + } + } + + return ret; +} + +static void spmi_pmic_arb_deregister_buses(struct spmi_pmic_arb *pmic_arb) +{ + int i; + + for (i = 0; i < pmic_arb->buses_available; i++) { + struct spmi_pmic_arb_bus *bus = pmic_arb->buses[i]; + + irq_set_chained_handler_and_data(bus->irq, + NULL, NULL); + irq_domain_remove(bus->domain); + } +} + static int spmi_pmic_arb_probe(struct platform_device *pdev) { struct spmi_pmic_arb *pmic_arb; @@ -1760,21 +1864,19 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) pmic_arb->ee = ee; - return spmi_pmic_arb_bus_init(pdev, dev->of_node, pmic_arb); + return spmi_pmic_arb_register_buses(pmic_arb, pdev); } static void spmi_pmic_arb_remove(struct platform_device *pdev) { struct spmi_pmic_arb *pmic_arb = platform_get_drvdata(pdev); - struct spmi_pmic_arb_bus *bus = pmic_arb->bus; - irq_set_chained_handler_and_data(bus->irq, - NULL, NULL); - irq_domain_remove(bus->domain); + spmi_pmic_arb_deregister_buses(pmic_arb); } static const struct of_device_id spmi_pmic_arb_match_table[] = { { .compatible = "qcom,spmi-pmic-arb", }, + { .compatible = "qcom,x1e80100-spmi-pmic-arb", }, {}, }; MODULE_DEVICE_TABLE(of, spmi_pmic_arb_match_table); -- https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git/ https://git.kernel.org/pub/scm/linux/kernel/git/sboyd/spmi.git