From nobody Fri Sep 25 09:23:45 2026 Received: from mail-ej2-f12.google.com (mail-ej2-f12.google.com [74.125.228.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 97B6847ACF2 for ; Mon, 14 Sep 2026 14:37:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.228.140 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789396682; cv=none; b=GpmS7IOMBRPrxmCiK82GOEDvS1nP+n6B4uq2T6mZJfIqSgCx9A0sXLS97qQ9WGu2e9wu2GqqQUZAxRUCKpSC9vpv1ZPtfrYfuXptWzsigc/r1XZFCIKDFpuB4E+gwZW7P2u3tVOiHKjq9sPNBnGYCvXlykXEQoTS7lqyQT13rTg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789396682; c=relaxed/simple; bh=Xii6+5i2RWZ67oguwNdM+TArT/XjMPtr0J/Bo/t/+aM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Xbw+fMA064YLUQHbse70iSnLiLiZqKTRQ/uEdqGoF27ZPEcOOVZJRboSc2+5LAQ4cimkJTTLTPmlzQZA0vujO2WyVgsTdQX/Vyff1mVThDuoj1Clj7JfbbgYDY70nB5uvevOr4x5Ej34Y0qXI4ZFzX7+1dolVkdRkBssT8CwvzE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=fairphone.com; spf=pass smtp.mailfrom=fairphone.com; dkim=pass (2048-bit key) header.d=fairphone.com header.i=@fairphone.com header.b=C4E34uey; arc=none smtp.client-ip=74.125.228.140 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=fairphone.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=fairphone.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=fairphone.com header.i=@fairphone.com header.b="C4E34uey" Received: by mail-ej2-f12.google.com with SMTP id a640c23a62f3a-c294496989aso364803166b.3 for ; Mon, 14 Sep 2026 07:37:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fairphone.com; s=fair; t=1789396677; x=1790001477; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=UmWbIrFCJbcoOz/Ivl18PXQXGPM1nMkA71Dhun2P/WA=; b=C4E34ueygueQD2bAjMENdbgz/JdsKfVN6y4eP6zyCaDbg8rw4MmJEGiSvd8BDE+VSd a1GbcA1Y68Fp/Rz7fU+1nalqNDbF8OpsJM1DvAzHq88mi7iHeCuaBjQ+0+Q7sx3N/I8X qsvpAA8otrvpJmAXdDexEFck/F88J1upu3tCHdHHBqhjYPjPINtWD+1qi8gmf95OyVMH oQ4is0YQfEUVA95UK/BbZ3woeq4AkMpxPtRNswcOcMo62hfRXVbGF6OpOg5WyvkI4fls D18j2pgAJnM08bP93IUFT5minSI9Gf307NijwytlSCXz+vuRBHlVe5UM6shgRBIw1/yf BXTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789396677; x=1790001477; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=UmWbIrFCJbcoOz/Ivl18PXQXGPM1nMkA71Dhun2P/WA=; b=RD6cdTlmHiHHgXmPlIH8UQhmT9cOyRCPiNWARs/TkvIAafm98uCYMB1CzGzXTWP9/r vEJCfUfnq6COVaD8a0DfSxA3+YJxsTgLT267IEtiXJf2d3jUOGuwUU0VDFqqiu2hZUc/ 5tzuLs8QQF4gVupiONiju3ABYEpFvB7+DYBvvdI79XcS6cC0uDM3yshkm2kjr8xw7jo4 DPbFyz/bLRMPqMIhAD9aKB5nZrXIWX14Zpb5ZodDJ9exzLAgAFMRh6G0JUI3QWkgMojE UghR4U1FtrmGLs/8ku+aCdCo+GGdWyonQU0kMFNLrWzLiEXVhBDPwTVJR5c8ZtJKHtO+ v7uw== X-Forwarded-Encrypted: i=1; AKwUvByghzWvAZbyoHQXz1Ym5eGzmSx3bDnmrLH1N29wQeGhb+sZL19BIeV8W2LRmKTOCYx2RHGUqQByarqEcYs=@vger.kernel.org X-Gm-Message-State: AFuF++m4xO5ED5PqYhOTt7qZDB4GkEOwcEq+5NdkZ2MmlwZZ+gAbTB4u r8azHC3AwTU941X7qIxfbJm2aZfEtiezLfps5HwJJwcKw27bRrclcWzACw53AnIS4mU= X-Gm-Gg: AYBFou0I527x3vFT4x+70SyuebyW+aYeWLJaOOPYZWOdBhvYi5pQngEf0ARC61QkPk2 tDCBTyDUCxA76XsOVdLCT+ozcEnjT9ehNzJ1VHkItcal3RzdHiaS7OkrgJjdnroyd0ySU5tk7PL BxU1teuZOZJWRsfS0Q7XxaBG3JPdw84+rUUnFpOqPBtmVUPOEzKs7FakGtGKUO+GJJZmXiIMz6h zpWYYRd90c65P0GMg2aiaXLfJ3bLwwoAHzpy4laxJOQZlGpuWUjubtOL7UMu337oFvRRC3sv7iv bwd4yZMYZoyhO9NZKbgPqSJzTZmBZtVNZc5VUgcwj8Wogfin0PO0qGP7zqHBpWExBY+jNDFiaMy iNgoFq7Dex/dkuGsAClhT8hLIKlka4qkXzNnx7P7P+tn0Y2gGCdV/N9pz8UV5IfMdnhijzgSR0I IafkFkXUaMQFHUvOloNSq/xz0CJ213PwI4CX0cBNCDQx72R6uFfPLvpH53tD/Uezo3HgN+NqRRQ etwv+Z5hgurTtS6+ZJ+XU8dMu6Iv7+hbUyjPFO74nij7gpyyeLaHXEfgg== X-Received: by 2002:a17:906:6a04:b0:c29:6de8:d143 with SMTP id a640c23a62f3a-c29b865bb71mr184948966b.19.1789396676843; Mon, 14 Sep 2026 07:37:56 -0700 (PDT) Received: from [172.16.220.224] (144-178-202-138.static.ef-service.nl. [144.178.202.138]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-c29660b29a7sm449634266b.43.2026.09.14.07.37.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 07:37:56 -0700 (PDT) From: Griffin Kroah-Hartman Date: Mon, 14 Sep 2026 16:37:47 +0200 Subject: [PATCH 1/3] dt-bindings: input: Add compatibility for Awinic AW8695 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: <20260914-aw8695_haptic_fp4_driver-v1-1-156f7549149a@fairphone.com> References: <20260914-aw8695_haptic_fp4_driver-v1-0-156f7549149a@fairphone.com> In-Reply-To: <20260914-aw8695_haptic_fp4_driver-v1-0-156f7549149a@fairphone.com> To: Dmitry Torokhov , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Luca Weiss , Bjorn Andersson , Konrad Dybcio Cc: linux-input@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Griffin Kroah-Hartman X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1789396675; l=987; i=griffin.kroah@fairphone.com; s=20250804; h=from:subject:message-id; bh=Xii6+5i2RWZ67oguwNdM+TArT/XjMPtr0J/Bo/t/+aM=; b=2s+aTG38QL/Spn6daVe9Zasok8uq+7dTkNp9krZfUHNNP+/5qMsAvuyY1kBqrIeztV+2URR38 7g8kDaxU9xzBWIqs5SScJYV3ShRWxo8+oJ889JkjyAMPq12p3MpXVuh X-Developer-Key: i=griffin.kroah@fairphone.com; a=ed25519; pk=drSBvqKFiR+xucmLWONHSq/wGrW+YvcVtBXFYnYzn8U= Add the AW8695 haptic driver to the binding documentation for the AW86927 and AW86938, as this binding needs the same properties. They are not compatible though, because the chip identification works differently compared to the 86927/86938 Signed-off-by: Griffin Kroah-Hartman --- Documentation/devicetree/bindings/input/awinic,aw86927.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/input/awinic,aw86927.yaml b/= Documentation/devicetree/bindings/input/awinic,aw86927.yaml index bd74b81488f61d72b675b5701b321b30b3430be0..d9da85499cda4d62f14f36f1ce7= 7627e37e348d7 100644 --- a/Documentation/devicetree/bindings/input/awinic,aw86927.yaml +++ b/Documentation/devicetree/bindings/input/awinic,aw86927.yaml @@ -17,6 +17,7 @@ properties: - enum: - awinic,aw86938 - const: awinic,aw86927 + - const: awinic,aw8695 =20 reg: maxItems: 1 --=20 2.43.0 From nobody Fri Sep 25 09:23:45 2026 Received: from mail-ej2-f12.google.com (mail-ej2-f12.google.com [74.125.228.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5A33A47F78B for ; Mon, 14 Sep 2026 14:37:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.228.140 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789396683; cv=none; b=Py+A8Udhw1D+XRuOg7hA9K0yZsP8D3jMTxrDr2aMCiym6nlvJz1E8QemTDh03erQy05KkyOdkucdfgb9BNXi8dz4zkUFKDTlABE3n5fpXcZMlIqupCu+kWG9iiZYuTdrvtQu12EvqbBiBUVvklgrw/BalQgEqnLQ8MvZ9mSPvek= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789396683; c=relaxed/simple; bh=R8HMyG74GTZZIJYnO5x6qyzsre52OWjx9/X0m2tQaHE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dwOgYjqKDq8l1mrvAZClu+ZeI6YQ0ebAD1h71h81xwzIfDb+BBnLnbJOTQkteEXqkzXRdenDyDtQqf5QQdbkm+TLekkFIWe48achBmB5krwg+C9NmmIUcM7b3EGEIFFT0I9fMuh6rmpEbtwJ6ZRmYS6MdpKZ9UPmsk+ju1KqQyg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=fairphone.com; spf=pass smtp.mailfrom=fairphone.com; dkim=pass (2048-bit key) header.d=fairphone.com header.i=@fairphone.com header.b=25Tc8fJj; arc=none smtp.client-ip=74.125.228.140 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=fairphone.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=fairphone.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=fairphone.com header.i=@fairphone.com header.b="25Tc8fJj" Received: by mail-ej2-f12.google.com with SMTP id a640c23a62f3a-c294496989aso364806266b.3 for ; Mon, 14 Sep 2026 07:37:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fairphone.com; s=fair; t=1789396678; x=1790001478; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=9Y80xprHvLU1i4rrjoeS9+U5T5BtPeDbPLJ+nJ7nOJc=; b=25Tc8fJj7Z81XvQOdrmasYFEjXI/4aXTfcldvcTHt9YHkvQ1RlBmN92x1pgBps6+1b 9ue7gGK9/Qyqph4jI2BsIhn6ZDzCoZ2zYPNXSd7Zs9CiDhRy2pLrE/DYx2ZcIE1mvkx+ NC5DQXomBijbAGFpmyQDgVtMOpcWh+1HRB1rk1coWnsCHDFYoHSG++SERbdUOg6ogJpo bKq0zGov153HVOaGyTRnIbaiS4dQNv/bnDFyM5LIdF4rhAPKn1zXYKZNBSYiQeYdl7hB kGJrOU8EuCYvDbcrCWTloBhr3Mtegroclq8E2I/Y+Mrdsxv4diT8LXHczD0Gpwe1JuN0 OYAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789396678; x=1790001478; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=9Y80xprHvLU1i4rrjoeS9+U5T5BtPeDbPLJ+nJ7nOJc=; b=gWI5nz1EJf1yt6cIoRlOelAIBc5OMl0CU4l6/QtvCxFcnoDBfhgrVh5005Ra2k7HXy gJPGidgl9MjHu0GGVzWceHRyKdBYugdvYuS09qd4NdP+4tNXBUZeJlXAReJsAfwcmZYW be91HJuW79E5QsUXds7KyhBFHCPkzy2TbS7ORw07Bmoemo2eGS2WG49/GhHYMvE0erKc Wz9pVcm2xsgKHRXr9NG3M1CN4f9NBHNmIojGrFOR5xSYosG2ibsxRRBHdurMB3kdw/FW LAruPXXe/ShGer/XaJPZ/UTtv5oftS9IqnILrgC62jAlIF+Ilw9O9UimbeofQKWJz/k5 DoxQ== X-Forwarded-Encrypted: i=1; AKwUvBzjkGVbTV3HG+jkt3viJQ1/lasbCB+jRzdUrDAjFjUJccNpc9beiCB/unBIvGES23l6teCuoOjRN4XQpzY=@vger.kernel.org X-Gm-Message-State: AFuF++lgrAfyrQIAb17UAy49xbC2x5U09s0d84ygqC3uoJodJ2uRBsG2 zU+qz6mOlp5/F76ne0CF9Kbb7DyOrBC8Neg2EDFAXWWed+RUuryJ9TzieGSZZZfunDo= X-Gm-Gg: AYBFou0wnKpbSFgCVRFrp6Oi2iCCIPhveJBb4zSwgrfcqPgFtAoD7fnUX/j/5o3W6Vo oQAzTFOn1ozIo8rZNIItqs3pAq+/0IRQdPdngqfNpVuEf2V/29/1qmrjJp3fexQRriIcU+HGbM8 hizd7I07D32EaKZZp78KIFdGjE4QQayzgl9dUA0pl1K+pTX3u2YA5IHBO2BgSdCVwY84N7BwtZv Ip/4ArrHmvZ/NQ5X+VdfFHkUoWY4O8anwd2NRvOWc1O6wNz6cqRd0G46V4EswNosFSuTOjn6tE0 V6z3FdsglqSxi+V3K0hT3UbkqrU+dFWSAyYrKN5xj210T4slxbey7x6Fkx1E3GpN5OIKlWnywXO JVkPVcruj0eWD+woGHusv0TVIRzZNCTR+wuh4XOrRHMN7dref28bdw366HDY6RZSgc8kyIzZZkF Mef1aa6p7N7Cl0jhB+8iZUEnv/fbAo2QitciG9jyhlDZmODGwK+/CLOTrFBVCMuOILdmilNtV+f Qit+/J4jrBKx7k8g1eUkweXFAH0BSAuN09Lbq76LG5NA63SZVjakRZmxw== X-Received: by 2002:a17:907:d19:b0:c26:1648:a066 with SMTP id a640c23a62f3a-c29b874c902mr181830566b.33.1789396677472; Mon, 14 Sep 2026 07:37:57 -0700 (PDT) Received: from [172.16.220.224] (144-178-202-138.static.ef-service.nl. [144.178.202.138]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-c29660b29a7sm449634266b.43.2026.09.14.07.37.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 07:37:57 -0700 (PDT) From: Griffin Kroah-Hartman Date: Mon, 14 Sep 2026 16:37:48 +0200 Subject: [PATCH 2/3] Input - aw8695: Add driver for AW8695 haptics 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: <20260914-aw8695_haptic_fp4_driver-v1-2-156f7549149a@fairphone.com> References: <20260914-aw8695_haptic_fp4_driver-v1-0-156f7549149a@fairphone.com> In-Reply-To: <20260914-aw8695_haptic_fp4_driver-v1-0-156f7549149a@fairphone.com> To: Dmitry Torokhov , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Luca Weiss , Bjorn Andersson , Konrad Dybcio Cc: linux-input@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Griffin Kroah-Hartman X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1789396675; l=24688; i=griffin.kroah@fairphone.com; s=20250804; h=from:subject:message-id; bh=/LZ335e1bauDw6miSQQe/ZpcqQWSL8CRqgmZYoM2EYU=; b=FsTiu0FYYvh8HS1jkuFV5a0YSZc8PFByMRdmaFk/DskCu6salI9cgxj9czVdJwUpJagbQ69/L 3cT7C1VIuOKAs2d3i1b/9oYoEXWFu9enOhflRGc5fGQqc4ZCFOTfnF1 X-Developer-Key: i=griffin.kroah@fairphone.com; a=ed25519; pk=drSBvqKFiR+xucmLWONHSq/wGrW+YvcVtBXFYnYzn8U= From: Luca Weiss Add a driver for interfacing with the Awinic AW8695 LRA Haptic Driver. The chip supports multiple modes of which only RAM mode is implemented. RTP mode would enable a user to "stream" waveform data but to my knowledge no such user space API exists in the kernel yet. We upload a basic sine wave to the chip and play this on request. Co-developed-by: Griffin Kroah-Hartman Signed-off-by: Griffin Kroah-Hartman Signed-off-by: Luca Weiss --- drivers/input/misc/Kconfig | 11 + drivers/input/misc/Makefile | 1 + drivers/input/misc/aw8695.c | 753 ++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 765 insertions(+) diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 1f6c57dba030813c248c068eda26ca1842271cb2..8bc0fdc1a7bc4c1fb1bea69ed08= dcd6002a7d5fe 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -137,6 +137,17 @@ config INPUT_AW86927 To compile this driver as a module, choose M here: the module will be called aw86927. =20 +config INPUT_AW8695 + tristate "Awinic AW8695 haptics support" + depends on INPUT && I2C + select INPUT_FF_MEMLESS + select REGMAP_I2C + help + Say Y to enable support for the Awinic AW8695 haptics driver. + + To compile this driver as a module, choose M here: the module will + be called aw8695. + config INPUT_BBNSM_PWRKEY tristate "NXP BBNSM Power Key Driver" depends on ARCH_MXC || COMPILE_TEST diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 2281d6803fce92e54a05c2c4f57ee7f7ea7ef2b8..25fb845125f9bee5b808d3f3b8e= e74b9e89af5f5 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_INPUT_ATI_REMOTE2) +=3D ati_remote2.o obj-$(CONFIG_INPUT_ATLAS_BTNS) +=3D atlas_btns.o obj-$(CONFIG_INPUT_ATMEL_CAPTOUCH) +=3D atmel_captouch.o obj-$(CONFIG_INPUT_AW86927) +=3D aw86927.o +obj-$(CONFIG_INPUT_AW8695) +=3D aw8695.o obj-$(CONFIG_INPUT_BBNSM_PWRKEY) +=3D nxp-bbnsm-pwrkey.o obj-$(CONFIG_INPUT_BMA150) +=3D bma150.o obj-$(CONFIG_INPUT_CM109) +=3D cm109.o diff --git a/drivers/input/misc/aw8695.c b/drivers/input/misc/aw8695.c new file mode 100644 index 0000000000000000000000000000000000000000..ea72562a7c2a7c4ab82e535a9cc= e2224623b5ffa --- /dev/null +++ b/drivers/input/misc/aw8695.c @@ -0,0 +1,753 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026 Luca Weiss + * Copyright (C) 2026 Griffin Kroah-Hartman + * + * Partially based on vendor driver: + * Copyright (c) 2018 AWINIC Technology CO., LTD + */ + +#include +#include +#include +#include +#include +#include +#include + +#define AW8695_CHIPID 0x95 +#define AW8695_RESET 0xaa +/* Default of BASE_ADDR* registers */ +#define AW8695_RAM_BASE_ADDR 0x800 + +#define AW8695_HIGH_MASK GENMASK(15, 8) +#define AW8695_LOW_MASK GENMASK(7, 0) + +/* Chip ID */ +#define AW8695_ID_REG 0x00 + +/* System Status */ +#define AW8695_SYSST_REG 0x01 + +/* System Interrupt */ +#define AW8695_SYSINT_REG 0x02 +#define AW8695_SYSINT_BSTERRI BIT(7) +#define AW8695_SYSINT_OVI BIT(6) +#define AW8695_SYSINT_UVLI BIT(5) +#define AW8695_SYSINT_FF_AEI BIT(4) +#define AW8695_SYSINT_FF_AFI BIT(3) +#define AW8695_SYSINT_OCDI BIT(2) +#define AW8695_SYSINT_OTI BIT(1) +#define AW8695_SYSINT_DONEI BIT(0) + +/* System Interrupt Mask */ +#define AW8695_SYSINTM_REG 0x03 +#define AW8695_SYSINTM_BSTERR_OFF BIT(7) +#define AW8695_SYSINTM_OV_OFF BIT(6) +#define AW8695_SYSINTM_UVLO_OFF BIT(5) +#define AW8695_SYSINTM_OCD_OFF BIT(2) +#define AW8695_SYSINTM_OT_OFF BIT(1) + +/* System Control */ +#define AW8695_SYSCTRL_REG 0x04 +#define AW8695_SYSCTRL_RAMINIT_EN BIT(5) + +#define AW8695_SYSCTRL_PLAY_MODE_MASK GENMASK(3, 2) +#define AW8695_SYSCTRL_PLAY_MODE_RAM (0) + +#define AW8695_SYSCTRL_BST_MODE_MASK GENMASK(1, 1) +#define AW8695_SYSCTRL_BST_MODE_BYPASS (0) + +#define AW8695_SYSCTRL_WORK_MODE_MASK GENMASK(0, 0) +#define AW8695_SYSCTRL_STANDBY (1) +#define AW8695_SYSCTRL_ACTIVE (0) + +/* Process Control */ +#define AW8695_GO_REG 0x05 +#define AW8695_GO_ENABLE BIT(0) + +/* Waveform #1 */ +#define AW8695_WAVSEQ1_REG 0x07 + +/* Waveform #2 */ +#define AW8695_WAVSEQ2_REG 0x08 + +/* Waveform Loop #1 */ +#define AW8695_WAVLOOP1_REG 0x0f +#define AW8695_WAVLOOP1_SEQ1_MASK GENMASK(7, 4) +#define AW8695_WAVLOOP1_SEQ2_MASK GENMASK(3, 0) + +#define AW8695_WAVLOOP_INFINITE 0xf + +/* Debug Control */ +#define AW8695_DBGCTRL_REG 0x20 +#define AW8695_DBGCTRL_INT_MODE_MASK GENMASK(2, 2) +#define AW8695_DBGCTRL_INT_MODE_EDGE (1) + +/* PWM Output Protect Configuration */ +#define AW8695_PWMPRC_REG 0x2d +#define AW8695_PWMPRC_PRC_ENABLE BIT(7) + +/* PWM Debug */ +#define AW8695_PWMDBG_REG 0x2e +#define AW8695_PWMDBG_PWM_MODE_MASK GENMASK(6, 5) +#define AW8695_PWMDBG_PWM_24K (2) + +/* Debug Status */ +#define AW8695_DBGSTAT_REG 0x30 + +/* Boost Debug #1 */ +#define AW8695_BSTDBG1_REG 0x31 +#define AW8695_BSTDBG1_DEFAULT 0x30 + +/* Boost Debug #2 */ +#define AW8695_BSTDBG2_REG 0x32 +#define AW8695_BSTDBG2_DEFAULT 0xeb + +/* Boost Debug #3 */ +#define AW8695_BSTDBG3_REG 0x33 +#define AW8695_BSTDBG3_DEFAULT 0xd4 + +/* Boost Config */ +#define AW8695_BSTCFG_REG 0x34 +#define AW8695_BSTCFG_PEAKCUR_MASK GENMASK(2, 0) +#define AW8695_BSTCFG_PEAKCUR_2A (1) + +#define AW8695_ANADBG_REG 0x35 +#define AW8695_ANADBG_IOC_MASK GENMASK(3, 2) +#define AW8695_ANADBG_IOC_4P65A (3) + +/* Waveform Protect Level */ +#define AW8695_PRLVL_REG 0x3e +#define AW8695_PRLVL_PR_ENABLE BIT(7) + +/* SRAM Address 0xhigh */ +#define AW8695_RAMADDRH_REG 0x40 + +/* SRAM Address 0xlow */ +#define AW8695_RAMADDRL_REG 0x41 + +/* SRAM Data */ +#define AW8695_RAMDATA_REG 0x42 + +#define AW8695_GLB_STATE_REG 0x46 + +#define AW8695_BST_AUTO_REG 0x47 +#define AW8695_BST_AUTO_BST_AUTOSW_MASK GENMASK(2, 2) +#define AW8695_BST_AUTO_BST_MANUAL_BOOST (0) + +#define AW8695_TSET_REG 0x4d +#define AW8695_TSET_DEFAULT 0x12 + +#define AW8695_R_SPARE_REG 0x5d +#define Aw8695_R_SPARE_DEFAULT 0x68 + +/* Detection Control */ +#define AW8695_DETCTRL_REG 0x5f +#define AW8695_DETCTRL_PROTECT_MASK GENMASK(5, 5) +#define AW8695_DETCTRL_PROTECT_NO_ACTION (1) +#define AW8695_DETCTRL_DIAG_GO_ENABLE BIT(0) + +/* ADC Test */ +#define AW8695_ADCTEST_REG 0x66 +#define AW8695_ADCTEST_VBAT_MODE_MASK GENMASK(6, 6) +#define AW8695_ADCTEST_VBAT_HW_COMP (1) + +#define AW8695_BEMF_VTHH_H_REG 0x74 + +#define AW8695_BEMF_VTHH_L_REG 0x75 + +#define AW8695_BEMF_VTHL_H_REG 0x76 + +#define AW8695_BEMF_VTHL_L_REG 0x77 + +#define AW8695_MAX_REG 0x7f + +#define AW8695_BEMF_UPPER_THRESHOLD 0x1008 +#define AW8695_BEMF_LOWER_THRESHOLD 0x3f8 + +enum aw8695_work_mode { + AW8695_STANDBY_MODE, + AW8695_RAM_MODE, +}; + +struct aw8695_data { + struct input_dev *input_dev; + struct i2c_client *client; + struct regmap *regmap; + struct gpio_desc *reset_gpio; + u16 level; + struct work_struct play_work; +}; + +/* + * Sine wave representing the magnitude of the drive to be used. + * Data is encoded in two's complement. + * round(84 * sin(x / 16.25)) + */ +static const u8 aw8695_sine_waveform[] =3D { + 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1e, 0x23, 0x28, 0x2c, 0x30, 0x35, + 0x39, 0x3c, 0x40, 0x43, 0x46, 0x49, 0x4b, 0x4d, 0x4f, 0x51, 0x52, 0x53, + 0x54, 0x54, 0x54, 0x54, 0x53, 0x52, 0x51, 0x4f, 0x4d, 0x4b, 0x49, 0x46, + 0x43, 0x40, 0x3c, 0x39, 0x35, 0x31, 0x2c, 0x28, 0x23, 0x1f, 0x1a, 0x15, + 0x10, 0x0b, 0x05, 0x00, 0xfb, 0xf6, 0xf1, 0xec, 0xe7, 0xe2, 0xdd, 0xd9, + 0xd4, 0xd0, 0xcc, 0xc8, 0xc4, 0xc0, 0xbd, 0xba, 0xb7, 0xb5, 0xb3, 0xb1, + 0xaf, 0xae, 0xad, 0xac, 0xac, 0xac, 0xac, 0xad, 0xae, 0xaf, 0xb1, 0xb2, + 0xb5, 0xb7, 0xba, 0xbd, 0xc0, 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd8, 0xdc, + 0xe1, 0xe6, 0xeb, 0xf0, 0xf5, 0xfa +}; + +/* + * Header that gets written to AW8695 SRAM that describes the available + * waveforms being transferred afterwards. + * + * @version: waveform library version + * @start_address: start address of waveform in SRAM + * @end_address: end address of waveform in SRAM + */ +struct aw8695_sram_waveform_header { + u8 version; + __be16 start_address; + __be16 end_address; +} __packed; + +static const struct aw8695_sram_waveform_header sram_waveform_header =3D { + .version =3D 0x01, + .start_address =3D cpu_to_be16(AW8695_RAM_BASE_ADDR + + sizeof(struct aw8695_sram_waveform_header)), + .end_address =3D cpu_to_be16(AW8695_RAM_BASE_ADDR + + sizeof(struct aw8695_sram_waveform_header) + + ARRAY_SIZE(aw8695_sine_waveform) - 1), +}; + +static int aw8695_interrupt_clear(struct aw8695_data *haptics) +{ + unsigned int read_buf; + + /* Clear UVLI bit by reading register */ + return regmap_read(haptics->regmap, AW8695_SYSINT_REG, &read_buf); +} + +static int aw8695_haptic_set_active(struct aw8695_data *haptics) +{ + int err; + + err =3D regmap_update_bits(haptics->regmap, AW8695_SYSCTRL_REG, + AW8695_SYSCTRL_WORK_MODE_MASK, + FIELD_PREP(AW8695_SYSCTRL_WORK_MODE_MASK, + AW8695_SYSCTRL_ACTIVE)); + if (err) + return err; + + err =3D aw8695_interrupt_clear(haptics); + if (err) + return err; + + return regmap_update_bits(haptics->regmap, AW8695_SYSINTM_REG, + AW8695_SYSINTM_UVLO_OFF, 0); +} + +static int aw8695_play_mode(struct aw8695_data *haptics, + enum aw8695_work_mode mode) +{ + struct device *dev =3D &haptics->client->dev; + int err; + + switch (mode) { + case AW8695_STANDBY_MODE: + err =3D regmap_update_bits(haptics->regmap, AW8695_SYSINTM_REG, + AW8695_SYSINTM_UVLO_OFF, AW8695_SYSINTM_UVLO_OFF); + if (err) + return err; + + return regmap_update_bits(haptics->regmap, AW8695_SYSCTRL_REG, + AW8695_SYSCTRL_WORK_MODE_MASK, + FIELD_PREP(AW8695_SYSCTRL_WORK_MODE_MASK, + AW8695_SYSCTRL_STANDBY)); + case AW8695_RAM_MODE: + err =3D regmap_update_bits(haptics->regmap, AW8695_SYSCTRL_REG, + AW8695_SYSCTRL_PLAY_MODE_MASK, + FIELD_PREP(AW8695_SYSCTRL_PLAY_MODE_MASK, + AW8695_SYSCTRL_PLAY_MODE_RAM)); + if (err) + return err; + + err =3D regmap_update_bits(haptics->regmap, AW8695_SYSCTRL_REG, + AW8695_SYSCTRL_BST_MODE_MASK, + FIELD_PREP(AW8695_SYSCTRL_BST_MODE_MASK, + AW8695_SYSCTRL_BST_MODE_BYPASS)); + if (err) + return err; + + return aw8695_haptic_set_active(haptics); + default: + dev_err(dev, "Unhandled mode: %d\n", mode); + return -EINVAL; + } +} + +static int aw8695_haptics_play(struct input_dev *dev, void *data, + struct ff_effect *effect) +{ + struct aw8695_data *haptics =3D input_get_drvdata(dev); + int level; + + level =3D effect->u.rumble.strong_magnitude; + if (!level) + level =3D effect->u.rumble.weak_magnitude; + + if (haptics->level =3D=3D level) + return 0; + + haptics->level =3D level; + schedule_work(&haptics->play_work); + + return 0; +} + +static void aw8695_hw_reset(struct aw8695_data *haptics) +{ + gpiod_set_value_cansleep(haptics->reset_gpio, 1); + + usleep_range(1000, 2000); + + gpiod_set_value_cansleep(haptics->reset_gpio, 0); + + usleep_range(3500, 4000); +} + +static int aw8695_stop(struct aw8695_data *haptics) +{ + int err; + unsigned int read_buf; + struct device *dev =3D &haptics->client->dev; + + err =3D regmap_update_bits(haptics->regmap, AW8695_GO_REG, + AW8695_GO_ENABLE, 0); + if (err) + return err; + + err =3D regmap_read_poll_timeout(haptics->regmap, AW8695_GLB_STATE_REG, r= ead_buf, + (read_buf & 0x0f) =3D=3D 0, 2000, 2000 * 100); + if (err) { + dev_err(dev, "Did not enter standby: %d\n Trying to force it...\n", err); + err =3D aw8695_play_mode(haptics, AW8695_STANDBY_MODE); + return err; + } + + return aw8695_play_mode(haptics, AW8695_STANDBY_MODE); +} + +static int aw8695_play_sine(struct aw8695_data *haptics) +{ + int err; + + err =3D aw8695_stop(haptics); + if (err) + return err; + + /* + * Configure for waveform #1 to be played infinitely, + * and waveform #2 to not be played. + */ + err =3D regmap_write(haptics->regmap, AW8695_WAVSEQ1_REG, 0x1); + if (err) + return err; + + err =3D regmap_write(haptics->regmap, AW8695_WAVSEQ2_REG, 0x0); + if (err) + return err; + + err =3D regmap_write(haptics->regmap, AW8695_WAVLOOP1_REG, + FIELD_PREP(AW8695_WAVLOOP1_SEQ1_MASK, + AW8695_WAVLOOP_INFINITE) | + FIELD_PREP(AW8695_WAVLOOP1_SEQ2_MASK, 0)); + if (err) + return err; + + /* Configure for RAM mode */ + err =3D aw8695_play_mode(haptics, AW8695_RAM_MODE); + if (err) + return err; + + /* Start vibration */ + return regmap_update_bits(haptics->regmap, AW8695_GO_REG, + AW8695_GO_ENABLE, AW8695_GO_ENABLE); +} + +static void aw8695_close(struct input_dev *input) +{ + struct aw8695_data *haptics =3D input_get_drvdata(input); + struct device *dev =3D &haptics->client->dev; + int err; + + cancel_work_sync(&haptics->play_work); + err =3D aw8695_stop(haptics); + if (err) + dev_err(dev, "Failed to stop haptics: %d\n", err); +} + +static void aw8695_haptics_play_work(struct work_struct *work) +{ + struct aw8695_data *haptics =3D + container_of(work, struct aw8695_data, play_work); + struct device *dev =3D &haptics->client->dev; + int err; + + if (haptics->level) + err =3D aw8695_play_sine(haptics); + else + err =3D aw8695_stop(haptics); + + if (err) + dev_err(dev, "Failed to execute work command: %d\n", err); +} + +static int aw8695_haptic_offset_calibration(struct aw8695_data *haptics) +{ + unsigned int read_buf; + int err; + + err =3D regmap_update_bits(haptics->regmap, AW8695_SYSCTRL_REG, + AW8695_SYSCTRL_RAMINIT_EN, + AW8695_SYSCTRL_RAMINIT_EN); + if (err) + return err; + + err =3D regmap_update_bits(haptics->regmap, AW8695_DETCTRL_REG, + AW8695_DETCTRL_DIAG_GO_ENABLE, + AW8695_DETCTRL_DIAG_GO_ENABLE); + if (err) + return err; + + err =3D regmap_read_poll_timeout(haptics->regmap, AW8695_DETCTRL_REG, rea= d_buf, + (read_buf & AW8695_DETCTRL_DIAG_GO_ENABLE) =3D=3D 0, 10000, 10000 * 50); + if (err) + return err; + + return regmap_update_bits(haptics->regmap, AW8695_SYSCTRL_REG, + AW8695_SYSCTRL_RAMINIT_EN, 0); +} + +static int aw8695_init(struct aw8695_data *haptics) +{ + int err; + unsigned int read_buf; + struct device *dev =3D &haptics->client->dev; + + aw8695_hw_reset(haptics); + + err =3D regmap_read(haptics->regmap, AW8695_ID_REG, &read_buf); + if (err) { + dev_err(dev, "Failed to read ID register: %d\n", err); + return err; + } + + if (read_buf !=3D AW8695_CHIPID) { + dev_err(dev, "Chip ID mismatch: expected %x, got %x\n", + AW8695_CHIPID, read_buf); + return -ENODEV; + } + + err =3D regmap_write(haptics->regmap, AW8695_ID_REG, AW8695_RESET); + if (err) { + dev_err(dev, "Failed to reset: %d\n", err); + return err; + } + + /* Wait ~1ms after reset */ + usleep_range(1000, 1500); + + /* Clear UVLI bit by reading register */ + err =3D aw8695_interrupt_clear(haptics); + if (err) { + dev_err(dev, "Failed to clear interrupt: %d\n", err); + return err; + } + + /* Set interrupt mode to edge */ + err =3D regmap_update_bits(haptics->regmap, AW8695_DBGCTRL_REG, + AW8695_DBGCTRL_INT_MODE_MASK, + FIELD_PREP(AW8695_DBGCTRL_INT_MODE_MASK, + AW8695_DBGCTRL_INT_MODE_EDGE)); + if (err) { + dev_err(dev, "Failed to set interrupt mode: %d\n", err); + return err; + } + + /* Configure interrupts */ + err =3D regmap_update_bits(haptics->regmap, AW8695_SYSINTM_REG, + AW8695_SYSINTM_BSTERR_OFF | AW8695_SYSINTM_OV_OFF | + AW8695_SYSINTM_UVLO_OFF | AW8695_SYSINTM_OCD_OFF | + AW8695_SYSINTM_OT_OFF, + AW8695_SYSINTM_BSTERR_OFF); + if (err) + return err; + + err =3D aw8695_play_mode(haptics, AW8695_STANDBY_MODE); + if (err) + return err; + + err =3D regmap_update_bits(haptics->regmap, AW8695_PWMDBG_REG, + AW8695_PWMDBG_PWM_MODE_MASK, + FIELD_PREP(AW8695_PWMDBG_PWM_MODE_MASK, + AW8695_PWMDBG_PWM_24K)); + if (err) + return err; + + err =3D regmap_write(haptics->regmap, AW8695_BSTDBG1_REG, AW8695_BSTDBG1_= DEFAULT); + if (err) + return err; + err =3D regmap_write(haptics->regmap, AW8695_BSTDBG2_REG, AW8695_BSTDBG2_= DEFAULT); + if (err) + return err; + err =3D regmap_write(haptics->regmap, AW8695_BSTDBG3_REG, AW8695_BSTDBG3_= DEFAULT); + if (err) + return err; + err =3D regmap_write(haptics->regmap, AW8695_TSET_REG, AW8695_TSET_DEFAUL= T); + if (err) + return err; + err =3D regmap_write(haptics->regmap, AW8695_R_SPARE_REG, Aw8695_R_SPARE_= DEFAULT); + if (err) + return err; + + err =3D regmap_update_bits(haptics->regmap, AW8695_ANADBG_REG, + AW8695_ANADBG_IOC_MASK, + FIELD_PREP(AW8695_ANADBG_IOC_MASK, + AW8695_ANADBG_IOC_4P65A)); + if (err) + return err; + + /* Set boost peak current */ + err =3D regmap_update_bits(haptics->regmap, AW8695_BSTCFG_REG, + AW8695_BSTCFG_PEAKCUR_MASK, + FIELD_PREP(AW8695_BSTCFG_PEAKCUR_MASK, + AW8695_BSTCFG_PEAKCUR_2A)); + if (err) + return err; + + /* Adjust motorprotect config */ + err =3D regmap_update_bits(haptics->regmap, AW8695_DETCTRL_REG, + AW8695_DETCTRL_PROTECT_MASK, + FIELD_PREP(AW8695_DETCTRL_PROTECT_MASK, + AW8695_DETCTRL_PROTECT_NO_ACTION)); + if (err) + return err; + err =3D regmap_update_bits(haptics->regmap, AW8695_PWMPRC_REG, + AW8695_PWMPRC_PRC_ENABLE, 0); + if (err) + return err; + err =3D regmap_update_bits(haptics->regmap, AW8695_PRLVL_REG, + AW8695_PRLVL_PR_ENABLE, 0); + if (err) + return err; + + /* Adjust auto boost config */ + err =3D regmap_update_bits(haptics->regmap, AW8695_BST_AUTO_REG, + AW8695_BST_AUTO_BST_AUTOSW_MASK, + FIELD_PREP(AW8695_BST_AUTO_BST_AUTOSW_MASK, + AW8695_BST_AUTO_BST_MANUAL_BOOST)); + if (err) + return err; + + err =3D aw8695_haptic_offset_calibration(haptics); + if (err) + return err; + + /* Set vbat compensation mode */ + err =3D regmap_update_bits(haptics->regmap, AW8695_ADCTEST_REG, + AW8695_ADCTEST_VBAT_MODE_MASK, + FIELD_PREP(AW8695_ADCTEST_VBAT_MODE_MASK, + AW8695_ADCTEST_VBAT_HW_COMP)); + if (err) + return err; + + /* bemf config */ + err =3D regmap_write(haptics->regmap, AW8695_BEMF_VTHH_H_REG, + FIELD_GET(AW8695_HIGH_MASK, AW8695_BEMF_UPPER_THRESHOLD)); + if (err) + return err; + err =3D regmap_write(haptics->regmap, AW8695_BEMF_VTHH_L_REG, + FIELD_GET(AW8695_LOW_MASK, AW8695_BEMF_UPPER_THRESHOLD)); + if (err) + return err; + err =3D regmap_write(haptics->regmap, AW8695_BEMF_VTHL_H_REG, + FIELD_GET(AW8695_HIGH_MASK, AW8695_BEMF_LOWER_THRESHOLD)); + if (err) + return err; + return regmap_write(haptics->regmap, AW8695_BEMF_VTHL_L_REG, + FIELD_GET(AW8695_LOW_MASK, AW8695_BEMF_LOWER_THRESHOLD)); +} + +static int aw8695_ram_init(struct aw8695_data *haptics) +{ + int err; + + /* Enable SRAM init */ + err =3D regmap_update_bits(haptics->regmap, AW8695_SYSCTRL_REG, + AW8695_SYSCTRL_RAMINIT_EN, AW8695_SYSCTRL_RAMINIT_EN); + if (err) + return err; + + /* Set RAMDATA write address */ + err =3D regmap_write(haptics->regmap, AW8695_RAMADDRH_REG, + FIELD_GET(AW8695_HIGH_MASK, AW8695_RAM_BASE_ADDR)); + if (err) + return err; + err =3D regmap_write(haptics->regmap, AW8695_RAMADDRL_REG, + FIELD_GET(AW8695_LOW_MASK, AW8695_RAM_BASE_ADDR)); + if (err) + return err; + + err =3D regmap_noinc_write(haptics->regmap, AW8695_RAMDATA_REG, + &sram_waveform_header, sizeof(sram_waveform_header)); + if (err) + return err; + + err =3D regmap_noinc_write(haptics->regmap, AW8695_RAMDATA_REG, + aw8695_sine_waveform, ARRAY_SIZE(aw8695_sine_waveform)); + if (err) + return err; + + /* Disable SRAM init */ + return regmap_update_bits(haptics->regmap, AW8695_SYSCTRL_REG, + AW8695_SYSCTRL_RAMINIT_EN, 0); +} + +static irqreturn_t aw8695_irq(int irq, void *data) +{ + struct aw8695_data *haptics =3D data; + struct device *dev =3D &haptics->client->dev; + unsigned int read_buf; + int err; + + err =3D regmap_read(haptics->regmap, AW8695_SYSINT_REG, &read_buf); + if (err) { + dev_err(dev, "Failed to read SYSINT register: %d\n", err); + return IRQ_NONE; + } + dev_dbg(dev, "Interrupt: SYSINT=3D0x%x\n", read_buf); + + if (read_buf & AW8695_SYSINT_BSTERRI) + dev_err(dev, "Received boost short circuit protection or over-voltage pr= otection interrupt!\n"); + if (read_buf & AW8695_SYSINT_OVI) + dev_err(dev, "Received wave data overflow or DPWM DC error interrupt!\n"= ); + if (read_buf & AW8695_SYSINT_UVLI) + dev_err(dev, "Received under voltage lock out interrupt!\n"); + if (read_buf & AW8695_SYSINT_OCDI) + dev_err(dev, "Received over current interrupt!\n"); + if (read_buf & AW8695_SYSINT_OTI) + dev_err(dev, "Received over temperature interrupt!\n"); + + if (read_buf & AW8695_SYSINT_DONEI) + dev_dbg(dev, "Received playback done interrupt\n"); + /* FIFO mode is not (yet) implemented in this driver */ + if (read_buf & AW8695_SYSINT_FF_AEI) + dev_dbg(dev, "Received FIFO almost empty interrupt\n"); + if (read_buf & AW8695_SYSINT_FF_AFI) + dev_dbg(dev, "Received FIFO almost full interrupt\n"); + + err =3D regmap_read(haptics->regmap, AW8695_DBGSTAT_REG, &read_buf); + if (err) { + dev_err(dev, "Failed to read DBGSTAT register: %d\n", err); + return IRQ_NONE; + } + dev_dbg(dev, "Interrupt: DBGSTAT=3D0x%x\n", read_buf); + + err =3D regmap_read(haptics->regmap, AW8695_SYSST_REG, &read_buf); + if (err) { + dev_err(dev, "Failed to read SYSST register: %d\n", err); + return IRQ_NONE; + } + dev_dbg(dev, "Interrupt: SYSST=3D0x%x\n", read_buf); + + return IRQ_HANDLED; +} + +static const struct regmap_config aw8695_regmap_config =3D { + .reg_bits =3D 8, + .val_bits =3D 8, + + .max_register =3D AW8695_MAX_REG, + .cache_type =3D REGCACHE_NONE, +}; + +static int aw8695_probe(struct i2c_client *client) +{ + struct device *dev =3D &client->dev; + struct aw8695_data *haptics; + int err; + + haptics =3D devm_kzalloc(dev, sizeof(*haptics), GFP_KERNEL); + if (!haptics) + return -ENOMEM; + + haptics->client =3D client; + i2c_set_clientdata(client, haptics); + + haptics->regmap =3D devm_regmap_init_i2c(client, &aw8695_regmap_config); + if (IS_ERR(haptics->regmap)) + return dev_err_probe(dev, PTR_ERR(haptics->regmap), + "Failed to allocate register map\n"); + + haptics->input_dev =3D devm_input_allocate_device(dev); + if (!haptics->input_dev) + return -ENOMEM; + + haptics->reset_gpio =3D devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(haptics->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(haptics->reset_gpio), + "Failed to get reset gpio\n"); + + err =3D devm_request_threaded_irq(dev, client->irq, NULL, aw8695_irq, + IRQF_ONESHOT, NULL, haptics); + if (err) + return dev_err_probe(dev, err, "Failed to request interrupt\n"); + + INIT_WORK(&haptics->play_work, aw8695_haptics_play_work); + + haptics->input_dev->name =3D "aw8695"; + haptics->input_dev->close =3D aw8695_close; + + input_set_drvdata(haptics->input_dev, haptics); + input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE); + + err =3D input_ff_create_memless(haptics->input_dev, NULL, + aw8695_haptics_play); + if (err) + return dev_err_probe(dev, err, "Failed to create FF dev\n"); + + err =3D aw8695_init(haptics); + if (err) + return dev_err_probe(dev, err, "Failed to init aw8695\n"); + + err =3D aw8695_ram_init(haptics); + if (err) + return dev_err_probe(dev, err, "Failed to init aw8695 sram\n"); + + err =3D input_register_device(haptics->input_dev); + if (err) + return dev_err_probe(dev, err, "Failed to register input device\n"); + + return 0; +} + +static const struct of_device_id aw8695_of_id[] =3D { + { .compatible =3D "awinic,aw8695", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, aw8695_of_id); + +static struct i2c_driver aw8695_driver =3D { + .driver =3D { + .name =3D "aw8695", + .of_match_table =3D aw8695_of_id, + }, + .probe =3D aw8695_probe, +}; + +module_i2c_driver(aw8695_driver); + +MODULE_AUTHOR("Luca Weiss "); +MODULE_DESCRIPTION("AW8695 LRA Haptic Driver"); +MODULE_LICENSE("GPL"); --=20 2.43.0 From nobody Fri Sep 25 09:23:45 2026 Received: from mail-ej2-f12.google.com (mail-ej2-f12.google.com [74.125.228.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AE839480356 for ; Mon, 14 Sep 2026 14:37:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.228.140 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789396683; cv=none; b=W5izfc0Pg6xop+1wt0KgPrjbXbZKrbW+Im9rG75COfDK/zo7hl0ycQRuN/x3asmW2Fw/arNJD6zPwb9Ypm6nVB3DAjoHXMjCLu0lTMgk4G64hrEMZFBnLaXOtzzz2uttLcLw10UTSG6Fh1JhYyrs3VkQEl6S9n0Fsk2LWFfD6zk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789396683; c=relaxed/simple; bh=An5kVD+QUS2KRFPqoTzuP3KiyxlNWixnd0SrSGxYc80=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oWB6SMRj9qpPk0CQ2AMkMuWqYw9IE9TxnC9UhugfZWrjLRIPHe6pFNOdUHhdjUW8FyCdgGbesHuC6V4gYySkkIkOmE9f0rG8eF/vMUNGjnOTuNPVeAbMHz6OVRbzxbF2CD5H1itsvk05EdpKUdZTUjKXv1OUgz08DPOS2Pavq0Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=fairphone.com; spf=pass smtp.mailfrom=fairphone.com; dkim=pass (2048-bit key) header.d=fairphone.com header.i=@fairphone.com header.b=tOhblX1H; arc=none smtp.client-ip=74.125.228.140 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=fairphone.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=fairphone.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=fairphone.com header.i=@fairphone.com header.b="tOhblX1H" Received: by mail-ej2-f12.google.com with SMTP id a640c23a62f3a-c254f6c7a58so229802566b.2 for ; Mon, 14 Sep 2026 07:37:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fairphone.com; s=fair; t=1789396678; x=1790001478; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=g8LfNC9HXmpFwQ3HeSQNxdEPD6YaISqvodeZzu0yt/c=; b=tOhblX1HbQWKzAbGVxfCQOKLCcponVlAb5+wv3zW7icjHVLMjLY5y+zpaVX43texjG P4N/vm0WysYAn406Hr1A7j2tMt77H/PPcXiWtry8n2DQgknKKABgfyjOfKHtSaB6+U/a N4/a0Tot2sdqt3eG39Ddt+dzjD37EqeXxuvurBVH67+yHv0VVcK3ArItDkCTW5B+umGY lp/aidzMO/D/AuVjpqBadygLkpYR7BQq05Cp/7Vw29uecbeJB2qoWFkUl15LYrfHtlzx SFdDUav+oOO+BL+MFeXbWqeKv1cch89a7rg432aoIj5up85VXxkdiAd7ykOAUfhAdz4E gWog== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789396678; x=1790001478; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=g8LfNC9HXmpFwQ3HeSQNxdEPD6YaISqvodeZzu0yt/c=; b=sICQn7fIGBQZLM33sTLC1dfCBxPryMZU9YBWvUp6QGYwDRta3j/dOq9DMM5kFD0drK xQ9+A7svC1K5CHZDWVgfb1pFXbjr/y7VpR9ad8X4t+obvJLQYfHKcq15bemp6msVpp6J y/vQzDKt58XXb8ki3Q5+rNDTj1qvVy0YvYXAhszRROCn02UoDUiDKBnScUgSyhF44yju Qu3pOkMPLuSJmXlzADULfEMwGaVeusVS1lrdhDOMQNDHD/2qQosjyJI9uHTATOgAVkhX 9LdhaPKp1pjqz7COjKsVsThWG243S6W2uDN29EpT8FahXnWw2YWGpZwWyIZw4GpAvt3J Dvdg== X-Forwarded-Encrypted: i=1; AKwUvBweMxaa4jk4Mr1qRWU3l/3h9aX5rjkiSh51ZP9pB7O1KPXLnT0pw5/0dPBlhaVq2AyqRJ6p6qmnnQHuXxc=@vger.kernel.org X-Gm-Message-State: AFuF++mNGv9RC+qDW4BVGAJBIqkzbCQUXi34ld9Prt7PFk2bCXdJ/w5L 3RuuJBqG6QMyKcD4trRWGmq5tNea8d+H4k5zUb4qjlobNoGFTdpe3yimDADaG3shSD4= X-Gm-Gg: AYBFou0UhFP0HloS5qz+QzV8ntfHE/7Fk6nW6OFdRXHlTtExFtMcBR5NhfNUV3jLv6r GeX+u9AXbpNanfmAZdMdD6302FeIKGoWzWyb0daFf9HgzQ3OcB78n+SSu4lP7OLtl0FfRj9Uw/a 38g56eALpLHBRhHj9jJBNdvW9Nz5q+wnoJEYOyFovFk9iab+oH2NkiBlL4JLQ+VWa9PJxmlkTe/ bdTJUMigye8oG08bLe5To7bIFOD7XmoPZabU9ZnZof/121p/QmXBHFgCJ643hV2BGL+ePP9cYtf 5RqfQ/44ivbaFlW8AHJmBJXObNX6kMCKMgFbJK+39eXQv7gLZhvAB9keIDAO6yXHW2IQt2yFUHP 2Z3UaqRPYmmhbgHQdlJnRPiUggXDzyqV/UFlsDsDWSpUz1dUsUZHX/IKePCcT3o+vo9tVvk7RlO X5YSbbOcowycbJVnW39Sz0+QEmWX9iFM/lFBQZ99vCa/S8W/a6JDZ5BZ2j9GcwCL8mVU7lVA0E9 R2FhgJeLw1mNtjCVX11xgEUkvrMJsPepxEkAW5UxsolBwiOGKy+MtI9VvCjg1uG3mWz X-Received: by 2002:a17:907:d19:b0:c29:5340:182e with SMTP id a640c23a62f3a-c29b84d2b89mr181142266b.2.1789396678031; Mon, 14 Sep 2026 07:37:58 -0700 (PDT) Received: from [172.16.220.224] (144-178-202-138.static.ef-service.nl. [144.178.202.138]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-c29660b29a7sm449634266b.43.2026.09.14.07.37.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 07:37:57 -0700 (PDT) From: Griffin Kroah-Hartman Date: Mon, 14 Sep 2026 16:37:49 +0200 Subject: [PATCH 3/3] arm64: dts: qcom: sm7225-fairphone-fp4: Add AW8695 haptics 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: <20260914-aw8695_haptic_fp4_driver-v1-3-156f7549149a@fairphone.com> References: <20260914-aw8695_haptic_fp4_driver-v1-0-156f7549149a@fairphone.com> In-Reply-To: <20260914-aw8695_haptic_fp4_driver-v1-0-156f7549149a@fairphone.com> To: Dmitry Torokhov , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Luca Weiss , Bjorn Andersson , Konrad Dybcio Cc: linux-input@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Griffin Kroah-Hartman X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1789396675; l=1538; i=griffin.kroah@fairphone.com; s=20250804; h=from:subject:message-id; bh=fEJxwk1bbs1F94cymqRXVbWtKaMJcVnL63UV2RvymTM=; b=pX9xn5+XqtBfjlYTYtS6dF5s9O1svEi9nf7O+5BRvhnBYR1PYcmL023f/AwzJ4KXl32012Grz eiDmUOn79YVBSgQHaBsK6xqF7gFbhw75sh1WUvishlk6BeGR5fp0vUd X-Developer-Key: i=griffin.kroah@fairphone.com; a=ed25519; pk=drSBvqKFiR+xucmLWONHSq/wGrW+YvcVtBXFYnYzn8U= From: Luca Weiss Add a node for the haptics driver found on the phone. Co-developed-by: Griffin Kroah-Hartman Signed-off-by: Griffin Kroah-Hartman Signed-off-by: Luca Weiss Reviewed-by: Abel Vesa --- arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts | 26 +++++++++++++++++++= +++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts b/arch/arm64= /boot/dts/qcom/sm7225-fairphone-fp4.dts index 23f950067a08b5ac4f7f9f61cbe060fa00b9f485..8a55a1d3426bce699a076e75b94= 8b3def698fc36 100644 --- a/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts +++ b/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts @@ -707,7 +707,17 @@ vreg_l7p: ldo7 { =20 /* PX8618 @ 26 */ /* SMB1395 PMIC @ 34 */ - /* awinic,aw8695 @ 5a */ + + haptics@5a { + compatible =3D "awinic,aw8695"; + reg =3D <0x5a>; + + interrupts-extended =3D <&tlmm 85 IRQ_TYPE_EDGE_FALLING>; + reset-gpios =3D <&tlmm 90 GPIO_ACTIVE_LOW>; + + pinctrl-0 =3D <&aw8695_int_default>, <&aw8695_reset_default>; + pinctrl-names =3D "default"; + }; }; =20 &ipa { @@ -1178,6 +1188,20 @@ reset-n-pins { bias-disable; }; }; + + aw8695_int_default: aw8695-int-default-state { + pins =3D "gpio85"; + function =3D "gpio"; + drive-strength =3D <2>; + bias-pull-up; + }; + + aw8695_reset_default: aw8695-reset-default-state { + pins =3D "gpio90"; + function =3D "gpio"; + drive-strength =3D <2>; + bias-pull-down; + }; }; =20 &uart1 { --=20 2.43.0