From nobody Thu Oct 2 02:15:08 2025 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (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 2C0BD314B72 for ; Wed, 24 Sep 2025 16:58:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758733092; cv=none; b=f940MgvaWq6xnN9zQ74Zu+lGQ1A0f4zHb/APL+dl3XicNdOIVY41+AhyH2uN45xyqWtGSV4EElpD1cmuxVjlL4CPS/pijByEwTtobAjcqAVns3cEB/0bw1p5HSksk5x5c6bOeX0QjaqJ/q5zWn1tJkAsd/+5Y19sbvRIBhD5bX0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758733092; c=relaxed/simple; bh=GW+CsQcDv9aEIAXsFqtODB4PIHMg+RXSOdxUSwcpj2M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cRBdmFy3knBQrY8BaOXYbJatEfZn30MV2eVMIZY7Q6N7nb8CKJCA1nKfjQR7TcSjYriVF7XfREsh43tVUsnf5YjTyx7CK2zSKhotV+5z/tuC0Hj9tG14gjIyVAyJQiXVqJlTN6Teqt70mwMw3FpuSP/toLKmb3iUVw+fZUhGHuk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=JXNf2Wap; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="JXNf2Wap" Received: from pps.filterd (m0279866.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 58ODFGqg019923 for ; Wed, 24 Sep 2025 16:58:09 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= OMXCPIMsWRznXvlemM7WjO4HBGTtJU4cZ9nQCIg1OaI=; b=JXNf2WapcKYn5LYC exZoKlUCmFm6EMeezumEVj9+46tNv93k8MHLKNcN6QPIFHChl/gt1yZg/ezlfFZ5 HFmdvQX5Fw1JqjwObMkYyv1T//0uBZycNYh4CihpJ2ha3pcuOeL9UP/DB/w5lN6n GLNF3fs3WcQlTR3v2j9P1biC0NP5q58LWL9KRXRr2MumFlKWrF6Y3AQU5VXK620B LA2pL9K6T40qT6P4W312waj5GPUHELWJKYAylE1uHbZLdV5BCibULU6Qv4dkqnb3 PQ1TuHIIX5Nrq1g4am0S3K+t25ieyyehIIjp0K6zUG9By2aVotyYbMKWp3Betz3+ mEA00A== Received: from mail-pl1-f198.google.com (mail-pl1-f198.google.com [209.85.214.198]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 49bjpdxadb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 24 Sep 2025 16:58:09 +0000 (GMT) Received: by mail-pl1-f198.google.com with SMTP id d9443c01a7336-277f0ea6ee6so284815ad.0 for ; Wed, 24 Sep 2025 09:58:09 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758733088; x=1759337888; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=OMXCPIMsWRznXvlemM7WjO4HBGTtJU4cZ9nQCIg1OaI=; b=p3KSQNdRPWJSOpUqSoiu9aEQwAtyv9VQDakCioU2cE/VTj9s2cmtdJfTXnXO3GQ8hF iZdBrAlYKkJmMfd1+pNsdufOVyq3VyCfbyFPImzpIPYZL2/z/opoXuvmefrqlfVJ2j7P HkxJT0//1FXSSD8UxwUtqpDMXbisQCXJUkg3cPhceOiScObnJ2MH27t0/igxiiBKMGMt W5aqQqLBUknZ/DSrJ17Rco/zAVxbHrE1mHPH9VdCDBIB1gllEipY6pBqSiWIhngJMgrQ zjYuJBDHWEY4AIUltaQK6JXIv0hynKYqn98rYNgISzdxmj4a375Mx3lD2oUXMr+ZJxY0 nxaQ== X-Forwarded-Encrypted: i=1; AJvYcCVFbpPo6tIn2czcBj3dXlDMgfeCCCzJM4SIdaXVErXy6akbVLGFq8p932HgM9DVZsAjdnLhmol9oHrXhb8=@vger.kernel.org X-Gm-Message-State: AOJu0Yw9omIsVcppKL8N9GnR8X0VUa53udSOd+6vT2MyJVjT0JSu4WRi 94/MjQ3G6OR6POxI7UGcYWRPLiUypAl5NpBQO2/h1Q8v7XV8bAG09xMLheqLqN69XaojqwNVi9w 4NXAssDr0YxCJBI7mY43DlF/sVfASeLMH+zGLt1yWnPMfPDbKAcRjF5suBsuC6/fWgbU= X-Gm-Gg: ASbGncu82ebFheOIjzCXt+izFsrXaQ3AFatPRdpLJmj+RT3PuuNriWRyucXONtB/ZkM RHgXaCqHvtawiLcwvrs3sdhzR4+oJFUWttSgIyAr3whLepqGK4uGMk2L8bYMxaxCxMLe5LTYceJ rh12QmON1nSLF5Lpwr3XNJkV9mpXC8GMtL79RYNU21UoTNLk1DC4nUTIMIerh5zaEHSBR9dtZiR RgwkMK6L2QVVLvaYNi/NoxocN6s+JKFrTiMwM3ixKkzUeGpMz5irUNcMUfH9N3Xq/lZjW4fIul8 ViC3kcn3goT/l7MuD3r7w9NPGGEPJCvb/yE2pryT9UwGEIelVTCRxlDLf57bfh4YyLZ2wX+W2Nc xQNHf52tB1rH/M7h0F98XAvpkmA== X-Received: by 2002:a17:902:dace:b0:24a:fab6:d15a with SMTP id d9443c01a7336-27ed49ff533mr5635545ad.20.1758733087966; Wed, 24 Sep 2025 09:58:07 -0700 (PDT) X-Google-Smtp-Source: AGHT+IE5zNTc1/FlNBbfQ4JfPD56w4dMj0Qef96J3yy7lK3T1dcv6rklwwd5tfo7CidiSWdv7yfenQ== X-Received: by 2002:a17:902:dace:b0:24a:fab6:d15a with SMTP id d9443c01a7336-27ed49ff533mr5634595ad.20.1758733086797; Wed, 24 Sep 2025 09:58:06 -0700 (PDT) Received: from hu-kamalw-hyd.qualcomm.com ([202.46.22.19]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-26980053078sm197415895ad.10.2025.09.24.09.58.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 24 Sep 2025 09:58:06 -0700 (PDT) From: Kamal Wadhwa Date: Wed, 24 Sep 2025 22:27:34 +0530 Subject: [PATCH v2 2/2] spmi: spmi-pmic-arb: add support for PMIC arbiter v8 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250924-glymur-spmi-v8-v2-2-202fc7a66a97@oss.qualcomm.com> References: <20250924-glymur-spmi-v8-v2-0-202fc7a66a97@oss.qualcomm.com> In-Reply-To: <20250924-glymur-spmi-v8-v2-0-202fc7a66a97@oss.qualcomm.com> To: Stephen Boyd , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Kamal Wadhwa , David Collins , Jishnu Prakash X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1758733076; l=19332; i=kamal.wadhwa@oss.qualcomm.com; s=20241018; h=from:subject:message-id; bh=I+nUG0xTzbNbMKIoorWMg8OTuVUmq0PvZOYU3WR6+eM=; b=qECM7OrXHQpPDWCgbVDIMOgBkIOzDXU6OM/KPBwhah+m8YB0HH1UVObRkGpjlsHg+rEu6+TDb nc7DtsYTTIiA+Thf8WPuoyG501ZLpszEyUUHhYV/SDdKWHjpkOWaOLd X-Developer-Key: i=kamal.wadhwa@oss.qualcomm.com; a=ed25519; pk=XbPE6DM5/mJi2tsiYwMCJCZ4O5XPMqColJRlGVcM7Hs= X-Proofpoint-ORIG-GUID: cXSMfBwUaAovmh8KM3KzUHY-qOcBFP72 X-Authority-Analysis: v=2.4 cv=Pc//hjhd c=1 sm=1 tr=0 ts=68d42321 cx=c_pps a=MTSHoo12Qbhz2p7MsH1ifg==:117 a=fChuTYTh2wq5r3m49p7fHw==:17 a=IkcTkHD0fZMA:10 a=yJojWOMRYYMA:10 a=EUspDBNiAAAA:8 a=Ik5BXOhrgj9YKjSFxXcA:9 a=QEXdDO2ut3YA:10 a=GvdueXVYPmCkWapjIL-Q:22 X-Proofpoint-GUID: cXSMfBwUaAovmh8KM3KzUHY-qOcBFP72 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwOTIzMDAyMCBTYWx0ZWRfXwzgNey3QtJ3v dESXnfRssYvABUNSbhEsIEu7EvsBqecLTkdubBrz+ozHa5cQ+aTjfcUni5rDOnjRlhmHgc2lFwv 8HIlgNyLBgu3es3q28zh/8fl54jpBhA0JjNEW6ieo/ZtPEKIcg09vZt/watfIeCVBopakw+SMFY i+FAfADkH2CenFIGKgKgzVAyF3kiuzljumyhp/ySAYUATwoUBHdwztbQTRQUu1qTsZKXGPWMpfX TgyvOvmSOHPv039BgWfsRQGq5rXPLWOGyB/qUTBvuZkfxIDyqra6mE1YXlYyS0hKdAqAs+RwnJ5 vtrKs1Bci8NuiYIVwsKY8+AvHR3KZB6fdakslXYa7oTEM4badA+0qkZGSseqLQnJse9tg5TUIII 7YgYXKEV X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1117,Hydra:6.1.9,FMLib:17.12.80.40 definitions=2025-09-24_04,2025-09-24_01,2025-03-28_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 phishscore=0 bulkscore=0 malwarescore=0 impostorscore=0 spamscore=0 suspectscore=0 clxscore=1015 adultscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2507300000 definitions=main-2509230020 From: David Collins PMIC arbiter v8 supports up to 4 SPMI buses and up to 8192 PMIC peripherals. Its register map differs from v7 as several fields increased in size. Add support for PMIC arbiter version 8. Signed-off-by: David Collins Signed-off-by: Jishnu Prakash Signed-off-by: Kamal Wadhwa --- drivers/spmi/spmi-pmic-arb.c | 328 +++++++++++++++++++++++++++++++++++++++= ---- 1 file changed, 298 insertions(+), 30 deletions(-) diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c index 91581974ef84ea49f2b9c64846634ee2da8df2bb..eefa1d776bf3c306a6d2c580ce8= b055279294dc8 100644 --- a/drivers/spmi/spmi-pmic-arb.c +++ b/drivers/spmi/spmi-pmic-arb.c @@ -3,6 +3,7 @@ * Copyright (c) 2012-2015, 2017, 2021, The Linux Foundation. All rights r= eserved. */ #include +#include #include #include #include @@ -25,10 +26,12 @@ #define PMIC_ARB_VERSION_V3_MIN 0x30000000 #define PMIC_ARB_VERSION_V5_MIN 0x50000000 #define PMIC_ARB_VERSION_V7_MIN 0x70000000 +#define PMIC_ARB_VERSION_V8_MIN 0x80000000 #define PMIC_ARB_INT_EN 0x0004 =20 #define PMIC_ARB_FEATURES 0x0004 #define PMIC_ARB_FEATURES_PERIPH_MASK GENMASK(10, 0) +#define PMIC_ARB_FEATURES_V8_PERIPH_MASK GENMASK(12, 0) =20 #define PMIC_ARB_FEATURES1 0x0008 =20 @@ -50,9 +53,10 @@ #define SPMI_MAPPING_BIT_IS_1_RESULT(X) (((X) >> 0) & 0xFF) =20 #define SPMI_MAPPING_TABLE_TREE_DEPTH 16 /* Maximum of 16-bits */ -#define PMIC_ARB_MAX_PPID BIT(12) /* PPID is 12bit */ +#define PMIC_ARB_MAX_PPID BIT(13) #define PMIC_ARB_APID_VALID BIT(15) #define PMIC_ARB_CHAN_IS_IRQ_OWNER(reg) ((reg) & BIT(24)) +#define PMIC_ARB_V8_CHAN_IS_IRQ_OWNER(reg) ((reg) & BIT(31)) #define INVALID_EE 0xFF =20 /* Ownership Table */ @@ -96,30 +100,37 @@ enum pmic_arb_channel { PMIC_ARB_CHANNEL_OBS, }; =20 -#define PMIC_ARB_MAX_BUSES 2 +#define PMIC_ARB_MAX_BUSES 4 +#define PMIC_ARB_MAX_BUSES_V8 4 =20 /* Maximum number of support PMIC peripherals */ #define PMIC_ARB_MAX_PERIPHS 512 #define PMIC_ARB_MAX_PERIPHS_V7 1024 +#define PMIC_ARB_MAX_PERIPHS_V8 8192 #define PMIC_ARB_TIMEOUT_US 1000 #define PMIC_ARB_MAX_TRANS_BYTES (8) =20 #define PMIC_ARB_APID_MASK 0xFF #define PMIC_ARB_PPID_MASK 0xFFF +#define PMIC_ARB_V8_PPID_MASK 0x1FFF =20 /* interrupt enable bit */ #define SPMI_PIC_ACC_ENABLE_BIT BIT(0) =20 +/* + * hwirq value crosses 32 bits only for platforms with more than 16 PMICs, + * none of which happen to support booting Linux in 32-bit mode. + */ #define spec_to_hwirq(slave_id, periph_id, irq_id, apid) \ - ((((slave_id) & 0xF) << 28) | \ - (((periph_id) & 0xFF) << 20) | \ - (((irq_id) & 0x7) << 16) | \ - (((apid) & 0x3FF) << 0)) + (FIELD_PREP(GENMASK(32, 28), (slave_id)) | \ + FIELD_PREP(GENMASK(27, 20), (periph_id)) | \ + FIELD_PREP(GENMASK(18, 16), (irq_id)) | \ + FIELD_PREP(GENMASK(12, 0), (apid))) =20 -#define hwirq_to_sid(hwirq) (((hwirq) >> 28) & 0xF) -#define hwirq_to_per(hwirq) (((hwirq) >> 20) & 0xFF) -#define hwirq_to_irq(hwirq) (((hwirq) >> 16) & 0x7) -#define hwirq_to_apid(hwirq) (((hwirq) >> 0) & 0x3FF) +#define hwirq_to_sid(hwirq) FIELD_GET(GENMASK(32, 28), (hwirq)) +#define hwirq_to_per(hwirq) FIELD_GET(GENMASK(27, 20), (hwirq)) +#define hwirq_to_irq(hwirq) FIELD_GET(GENMASK(18, 16), (hwirq)) +#define hwirq_to_apid(hwirq) FIELD_GET(GENMASK(12, 0), (hwirq)) =20 struct pmic_arb_ver_ops; =20 @@ -138,11 +149,12 @@ struct spmi_pmic_arb; * @domain: irq domain object for PMIC IRQ domain * @intr: address of the SPMI interrupt control registers. * @cnfg: address of the PMIC Arbiter configuration registers. + * @apid_owner: on v8: address of APID owner mapping table registers * @spmic: spmi controller registered for this bus * @lock: lock to synchronize accesses. - * @base_apid: on v7: minimum APID associated with the particular SPMI - * bus instance - * @apid_count: on v5 and v7: number of APIDs associated with the + * @base_apid: on v7 and v8: minimum APID associated with the + particular SPMI bus instance + * @apid_count: on v5, v7 and v8: number of APIDs associated with the * particular SPMI bus instance * @mapping_table: in-memory copy of PPID -> APID mapping table. * @mapping_table_valid:bitmap containing valid-only periphs @@ -159,6 +171,7 @@ struct spmi_pmic_arb_bus { struct irq_domain *domain; void __iomem *intr; void __iomem *cnfg; + void __iomem *apid_owner; struct spmi_controller *spmic; raw_spinlock_t lock; u16 base_apid; @@ -181,6 +194,7 @@ struct spmi_pmic_arb_bus { * @wr_base: on v1 "core", on v2 "chnls" register base off DT. * @core: core register base for v2 and above only (see above) * @core_size: core register base size + * @apid_map: on v8, APID mapping table register base * @channel: execution environment channel to use for accesses. * @ee: the current Execution Environment * @ver_ops: version dependent operations. @@ -193,6 +207,7 @@ struct spmi_pmic_arb { void __iomem *wr_base; void __iomem *core; resource_size_t core_size; + void __iomem *apid_map; u8 channel; u8 ee; const struct pmic_arb_ver_ops *ver_ops; @@ -206,6 +221,7 @@ struct spmi_pmic_arb { * * @ver_str: version string. * @get_core_resources: initializes the core, observer and channels + * @get_bus_resources: requests per-SPMI bus register resources * @init_apid: finds the apid base and count * @ppid_to_apid: finds the apid for a given ppid. * @non_data_cmd: on v1 issues an spmi non-data command. @@ -227,6 +243,9 @@ struct spmi_pmic_arb { struct pmic_arb_ver_ops { const char *ver_str; int (*get_core_resources)(struct platform_device *pdev, void __iomem *cor= e); + int (*get_bus_resources)(struct platform_device *pdev, + struct device_node *node, + 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 */ @@ -656,7 +675,7 @@ static int periph_interrupt(struct spmi_pmic_arb_bus *b= us, u16 apid) unsigned int irq; u32 status, id; int handled =3D 0; - u8 sid =3D (bus->apid_data[apid].ppid >> 8) & 0xF; + u8 sid =3D (bus->apid_data[apid].ppid >> 8) & 0x1F; u8 per =3D bus->apid_data[apid].ppid & 0xFF; =20 status =3D readl_relaxed(pmic_arb->ver_ops->irq_status(bus, apid)); @@ -686,7 +705,7 @@ static void pmic_arb_chained_irq(struct irq_desc *desc) int last =3D bus->max_apid; /* * acc_offset will be non-zero for the secondary SPMI bus instance on - * v7 controllers. + * v7 and v8 controllers. */ int acc_offset =3D bus->base_apid >> 5; u8 ee =3D pmic_arb->ee; @@ -913,7 +932,7 @@ static int qpnpint_irq_domain_translate(struct irq_doma= in *d, return -EINVAL; if (fwspec->param_count !=3D 4) return -EINVAL; - if (intspec[0] > 0xF || intspec[1] > 0xFF || intspec[2] > 0x7) + if (intspec[0] > 0x1F || intspec[1] > 0xFF || intspec[2] > 0x7) return -EINVAL; =20 ppid =3D intspec[0] << 8 | intspec[1]; @@ -1160,6 +1179,24 @@ static int pmic_arb_ppid_to_apid_v2(struct spmi_pmic= _arb_bus *bus, u16 ppid) return apid_valid & ~PMIC_ARB_APID_VALID; } =20 +static void pmic_arb_dump_apid_map(struct spmi_pmic_arb_bus *bus) +{ + struct apid_data *apidd; + u16 apid, ppid; + + /* Dump the mapping table for debug purposes. */ + dev_dbg(&bus->spmic->dev, "PPID APID Write-EE IRQ-EE\n"); + for (ppid =3D 0; ppid < PMIC_ARB_MAX_PPID; ppid++) { + apid =3D bus->ppid_to_apid[ppid]; + if (apid & PMIC_ARB_APID_VALID) { + apid &=3D ~PMIC_ARB_APID_VALID; + apidd =3D &bus->apid_data[apid]; + dev_dbg(&bus->spmic->dev, "%#03X %3u %2u %2u\n", + ppid, apid, apidd->write_ee, apidd->irq_ee); + } + } +} + static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb_bus *bus) { struct spmi_pmic_arb *pmic_arb =3D bus->pmic_arb; @@ -1222,17 +1259,7 @@ static int pmic_arb_read_apid_map_v5(struct spmi_pmi= c_arb_bus *bus) bus->last_apid =3D i; } =20 - /* Dump the mapping table for debug purposes. */ - dev_dbg(&bus->spmic->dev, "PPID APID Write-EE IRQ-EE\n"); - for (ppid =3D 0; ppid < PMIC_ARB_MAX_PPID; ppid++) { - apid =3D bus->ppid_to_apid[ppid]; - if (apid & PMIC_ARB_APID_VALID) { - apid &=3D ~PMIC_ARB_APID_VALID; - apidd =3D &bus->apid_data[apid]; - dev_dbg(&bus->spmic->dev, "%#03X %3u %2u %2u\n", - ppid, apid, apidd->write_ee, apidd->irq_ee); - } - } + pmic_arb_dump_apid_map(bus); =20 return 0; } @@ -1346,7 +1373,7 @@ static int pmic_arb_get_core_resources_v7(struct plat= form_device *pdev, } =20 /* - * Only v7 supports 2 buses. Each bus will get a different apid count, read + * Arbiter 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) @@ -1424,6 +1451,185 @@ static int pmic_arb_offset_v7(struct spmi_pmic_arb_= bus *bus, u8 sid, u16 addr, return offset; } =20 +static int pmic_arb_get_core_resources_v8(struct platform_device *pdev, + void __iomem *core) +{ + struct spmi_pmic_arb *pmic_arb =3D platform_get_drvdata(pdev); + + pmic_arb->apid_map =3D devm_platform_ioremap_resource_byname(pdev, + "chnl_map"); + if (IS_ERR(pmic_arb->apid_map)) + return PTR_ERR(pmic_arb->apid_map); + + pmic_arb->core =3D core; + + pmic_arb->max_periphs =3D PMIC_ARB_MAX_PERIPHS_V8; + + return pmic_arb_get_obsrvr_chnls_v2(pdev); +} + +static int pmic_arb_get_bus_resources_v8(struct platform_device *pdev, + struct device_node *node, + struct spmi_pmic_arb_bus *bus) +{ + int index; + + index =3D of_property_match_string(node, "reg-names", "chnl_owner"); + if (index < 0) { + dev_err(&pdev->dev, "chnl_owner reg region missing\n"); + return -EINVAL; + } + + bus->apid_owner =3D devm_of_iomap(&pdev->dev, node, index, NULL); + + return PTR_ERR_OR_ZERO(bus->apid_owner); +} + +static int pmic_arb_read_apid_map_v8(struct spmi_pmic_arb_bus *bus) +{ + struct spmi_pmic_arb *pmic_arb =3D bus->pmic_arb; + struct apid_data *apidd; + struct apid_data *prev_apidd; + u16 i, apid, ppid, apid_max; + bool valid, is_irq_ee; + u32 regval, offset; + + /* + * In order to allow multiple EEs to write to a single PPID in arbiter + * version 8, there can be more than one APID mapped to each PPID. The + * owner field for each of these mappings specifies the EE which is + * allowed to write to the APID. The owner of the last (highest) APID + * which has the IRQ owner bit set for a given PPID will receive + * interrupts from the PPID. + * + * In arbiter version 8, the APID numbering space is divided between + * the SPMI buses according to this mapping: + * APID =3D 0 to N-1 --> bus 0 + * APID =3D N to N+M-1 --> bus 1 + * APID =3D N+M to N+M+P-1 --> bus 2 + * APID =3D N+M+P to N+M+P+Q-1 --> bus 3 + * where N =3D number of APIDs supported by bus 0 + * M =3D number of APIDs supported by bus 1 + * P =3D number of APIDs supported by bus 2 + * Q =3D number of APIDs supported by bus 3 + */ + apidd =3D &bus->apid_data[bus->base_apid]; + apid_max =3D bus->base_apid + bus->apid_count; + for (i =3D bus->base_apid; i < apid_max; i++, apidd++) { + offset =3D pmic_arb->ver_ops->apid_map_offset(i); + regval =3D readl_relaxed(pmic_arb->apid_map + offset); + if (!regval) + continue; + ppid =3D regval & PMIC_ARB_V8_PPID_MASK; + is_irq_ee =3D PMIC_ARB_V8_CHAN_IS_IRQ_OWNER(regval); + + regval =3D readl_relaxed(pmic_arb->ver_ops->apid_owner(bus, i)); + apidd->write_ee =3D SPMI_OWNERSHIP_PERIPH2OWNER(regval); + + apidd->irq_ee =3D is_irq_ee ? apidd->write_ee : INVALID_EE; + + valid =3D bus->ppid_to_apid[ppid] & PMIC_ARB_APID_VALID; + apid =3D bus->ppid_to_apid[ppid] & ~PMIC_ARB_APID_VALID; + prev_apidd =3D &bus->apid_data[apid]; + + if (!valid || apidd->write_ee =3D=3D pmic_arb->ee) { + /* First PPID mapping or one for this EE */ + bus->ppid_to_apid[ppid] =3D i | PMIC_ARB_APID_VALID; + } else if (valid && is_irq_ee && + prev_apidd->write_ee =3D=3D pmic_arb->ee) { + /* + * Duplicate PPID mapping after the one for this EE; + * override the irq owner + */ + prev_apidd->irq_ee =3D apidd->irq_ee; + } + + apidd->ppid =3D ppid; + bus->last_apid =3D i; + } + + pmic_arb_dump_apid_map(bus); + + return 0; +} + +static int pmic_arb_init_apid_v8(struct spmi_pmic_arb_bus *bus, int index) +{ + struct spmi_pmic_arb *pmic_arb =3D bus->pmic_arb; + int ret, i; + + if (index < 0 || index >=3D PMIC_ARB_MAX_BUSES_V8) { + dev_err(&bus->spmic->dev, "Unsupported bus index %d detected\n", + index); + return -EINVAL; + } + + bus->base_apid =3D 0; + bus->apid_count =3D 0; + for (i =3D 0; i <=3D index; i++) { + bus->base_apid +=3D bus->apid_count; + bus->apid_count =3D readl_relaxed(pmic_arb->core + PMIC_ARB_FEATURES + i= * 4) & + PMIC_ARB_FEATURES_V8_PERIPH_MASK; + } + + if (bus->apid_count =3D=3D 0) { + dev_err(&bus->spmic->dev, "Bus %d not implemented\n", index); + return -EINVAL; + } else if (bus->base_apid + bus->apid_count > pmic_arb->max_periphs) { + dev_err(&bus->spmic->dev, "Unsupported max APID %d detected\n", + bus->base_apid + bus->apid_count); + return -EINVAL; + } + + ret =3D pmic_arb_init_apid_min_max(bus); + if (ret) + return ret; + + ret =3D pmic_arb_read_apid_map_v8(bus); + if (ret) { + dev_err(&bus->spmic->dev, "could not read APID->PPID mapping table, rc= =3D %d\n", + ret); + return ret; + } + + return 0; +} + +/* + * v8 offset per ee and per apid for observer channels and per apid for + * read/write channels. + */ +static int pmic_arb_offset_v8(struct spmi_pmic_arb_bus *bus, u8 sid, u16 a= ddr, + enum pmic_arb_channel ch_type) +{ + struct spmi_pmic_arb *pmic_arb =3D bus->pmic_arb; + u16 apid; + int rc; + u32 offset =3D 0; + u16 ppid =3D (sid << 8) | (addr >> 8); + + rc =3D pmic_arb->ver_ops->ppid_to_apid(bus, ppid); + if (rc < 0) + return rc; + + apid =3D rc; + switch (ch_type) { + case PMIC_ARB_CHANNEL_OBS: + offset =3D 0x40000 * pmic_arb->ee + 0x20 * apid; + break; + case PMIC_ARB_CHANNEL_RW: + if (bus->apid_data[apid].write_ee !=3D pmic_arb->ee) { + dev_err(&bus->spmic->dev, "disallowed SPMI write to sid=3D%u, addr=3D0x= %04X\n", + sid, addr); + return -EPERM; + } + offset =3D 0x200 * apid; + break; + } + + return offset; +} + static u32 pmic_arb_fmt_cmd_v1(u8 opc, u8 sid, u16 addr, u8 bc) { return (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7); @@ -1490,6 +1696,14 @@ pmic_arb_acc_enable_v7(struct spmi_pmic_arb_bus *bus= , u16 n) return pmic_arb->wr_base + 0x100 + 0x1000 * n; } =20 +static void __iomem * +pmic_arb_acc_enable_v8(struct spmi_pmic_arb_bus *bus, u16 n) +{ + struct spmi_pmic_arb *pmic_arb =3D bus->pmic_arb; + + return pmic_arb->wr_base + 0x100 + 0x200 * n; +} + static void __iomem * pmic_arb_irq_status_v1(struct spmi_pmic_arb_bus *bus, u16 n) { @@ -1516,6 +1730,14 @@ pmic_arb_irq_status_v7(struct spmi_pmic_arb_bus *bus= , u16 n) return pmic_arb->wr_base + 0x104 + 0x1000 * n; } =20 +static void __iomem * +pmic_arb_irq_status_v8(struct spmi_pmic_arb_bus *bus, u16 n) +{ + struct spmi_pmic_arb *pmic_arb =3D bus->pmic_arb; + + return pmic_arb->wr_base + 0x104 + 0x200 * n; +} + static void __iomem * pmic_arb_irq_clear_v1(struct spmi_pmic_arb_bus *bus, u16 n) { @@ -1542,6 +1764,14 @@ pmic_arb_irq_clear_v7(struct spmi_pmic_arb_bus *bus,= u16 n) return pmic_arb->wr_base + 0x108 + 0x1000 * n; } =20 +static void __iomem * +pmic_arb_irq_clear_v8(struct spmi_pmic_arb_bus *bus, u16 n) +{ + struct spmi_pmic_arb *pmic_arb =3D bus->pmic_arb; + + return pmic_arb->wr_base + 0x108 + 0x200 * n; +} + static u32 pmic_arb_apid_map_offset_v2(u16 n) { return 0x800 + 0x4 * n; @@ -1557,6 +1787,12 @@ static u32 pmic_arb_apid_map_offset_v7(u16 n) return 0x2000 + 0x4 * n; } =20 +static u32 pmic_arb_apid_map_offset_v8(u16 n) +{ + /* For v8, offset is from "chnl_map" base register, not "core". */ + return 0x4 * n; +} + static void __iomem * pmic_arb_apid_owner_v2(struct spmi_pmic_arb_bus *bus, u16 n) { @@ -1564,7 +1800,7 @@ pmic_arb_apid_owner_v2(struct spmi_pmic_arb_bus *bus,= u16 n) } =20 /* - * For arbiter version 7, APID ownership table registers have independent + * For arbiter version 7 and 8, APID ownership table registers have indepe= ndent * numbering space for each SPMI bus instance, so each is indexed starting= from * 0. */ @@ -1574,6 +1810,12 @@ pmic_arb_apid_owner_v7(struct spmi_pmic_arb_bus *bus= , u16 n) return bus->cnfg + 0x4 * (n - bus->base_apid); } =20 +static void __iomem * +pmic_arb_apid_owner_v8(struct spmi_pmic_arb_bus *bus, u16 n) +{ + return bus->apid_owner + 0x4 * (n - bus->base_apid); +} + static const struct pmic_arb_ver_ops pmic_arb_v1 =3D { .ver_str =3D "v1", .get_core_resources =3D pmic_arb_get_core_resources_v1, @@ -1654,6 +1896,23 @@ static const struct pmic_arb_ver_ops pmic_arb_v7 =3D= { .apid_owner =3D pmic_arb_apid_owner_v7, }; =20 +static const struct pmic_arb_ver_ops pmic_arb_v8 =3D { + .ver_str =3D "v8", + .get_core_resources =3D pmic_arb_get_core_resources_v8, + .get_bus_resources =3D pmic_arb_get_bus_resources_v8, + .init_apid =3D pmic_arb_init_apid_v8, + .ppid_to_apid =3D pmic_arb_ppid_to_apid_v5, + .non_data_cmd =3D pmic_arb_non_data_cmd_v2, + .offset =3D pmic_arb_offset_v8, + .fmt_cmd =3D pmic_arb_fmt_cmd_v2, + .owner_acc_status =3D pmic_arb_owner_acc_status_v7, + .acc_enable =3D pmic_arb_acc_enable_v8, + .irq_status =3D pmic_arb_irq_status_v8, + .irq_clear =3D pmic_arb_irq_clear_v8, + .apid_map_offset =3D pmic_arb_apid_map_offset_v8, + .apid_owner =3D pmic_arb_apid_owner_v8, +}; + static const struct irq_domain_ops pmic_arb_irq_domain_ops =3D { .activate =3D qpnpint_irq_domain_activate, .alloc =3D qpnpint_irq_domain_alloc, @@ -1731,6 +1990,12 @@ static int spmi_pmic_arb_bus_init(struct platform_de= vice *pdev, bus->spmic =3D ctrl; bus->id =3D bus_index; =20 + if (pmic_arb->ver_ops->get_bus_resources) { + ret =3D pmic_arb->ver_ops->get_bus_resources(pdev, node, bus); + if (ret) + return ret; + } + ret =3D pmic_arb->ver_ops->init_apid(bus, bus_index); if (ret) return ret; @@ -1825,8 +2090,10 @@ static int spmi_pmic_arb_probe(struct platform_devic= e *pdev) pmic_arb->ver_ops =3D &pmic_arb_v3; else if (hw_ver < PMIC_ARB_VERSION_V7_MIN) pmic_arb->ver_ops =3D &pmic_arb_v5; - else + else if (hw_ver < PMIC_ARB_VERSION_V8_MIN) pmic_arb->ver_ops =3D &pmic_arb_v7; + else + pmic_arb->ver_ops =3D &pmic_arb_v8; =20 err =3D pmic_arb->ver_ops->get_core_resources(pdev, core); if (err) @@ -1875,6 +2142,7 @@ static void spmi_pmic_arb_remove(struct platform_devi= ce *pdev) static const struct of_device_id spmi_pmic_arb_match_table[] =3D { { .compatible =3D "qcom,spmi-pmic-arb", }, { .compatible =3D "qcom,x1e80100-spmi-pmic-arb", }, + { .compatible =3D "qcom,glymur-spmi-pmic-arb", }, {}, }; MODULE_DEVICE_TABLE(of, spmi_pmic_arb_match_table); --=20 2.25.1