From nobody Fri Jun 12 22:47:17 2026 Received: from mail-pj1-f44.google.com (mail-pj1-f44.google.com [209.85.216.44]) (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 3523847DFB6 for ; Tue, 12 May 2026 07:40:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778571611; cv=none; b=pKwVvI+BOEHEy+kzWqKKf66cz4vPsYZqdWgy1wM+SCpXTLbHQRdiVb9KAvjvZ9TEetA4kl9zX2kW2/8Ob7GZ7pr/BcwnmyXSd7cRHnaEhpe1gFeJcatEjhBvlJDdTe17w4W8n930O6vkg3H1QkOoCo0Pdhl5gzpcO5vJC+nIxlw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778571611; c=relaxed/simple; bh=W60ZB1+wZuP8PnU4iGf0U+uZbFRfPX6nSzCaDbJOyEY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=MaxRj5jRNoaCd4wUCYB4M37N1yZzqMfr+OLhzu5lR+B/sFFUQRGxQhAIXSOs2i4+FmzYPc0qOKyB4UScw9G9wqEjRmnqribcNeb+oQLP9QpWgNFZbbMQgPz1Y2owZ1usNUhiaui3lswiYl39g5WXvsiWI44UP9LH8VK6zDQABRY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=bQ7apMU1; arc=none smtp.client-ip=209.85.216.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bQ7apMU1" Received: by mail-pj1-f44.google.com with SMTP id 98e67ed59e1d1-366375c43c2so2958875a91.2 for ; Tue, 12 May 2026 00:40:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778571605; x=1779176405; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7xf70jF6KOg/SiWMlOWjk6atZ2ryfC9YUcEG9Wm/SIo=; b=bQ7apMU1/u10H1dBFoP00bZoiUBM3gzG4Ei9OBVP3SV4dTn80szP19qeL6TWnR5wjj E43RP38ZnsMVyNywNfMJoceuzUpN68sT0JZH19eJt2KXXIQ3cnAp5VX6Q26R4o3rkSpr z/Ar9/g3gjrSEN8yhIE1qOgwF/5hrIe5g0q5TmztD0yOWuzznx4PbS8hGYkGGj6zQiAU 9zLFvT5dnRRuI/mN+zvQtE3RC8uqUMFxGpRIVPcK4FgbAf68RYZeINyDhtBkWB4FPSEA 0MXfvOsjkV+mq5h3a1gqeUOJNVcuIccbouxGC7KzaPS3gsKNuoDs3acMsKtqm/WOM1Rn JwAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778571605; x=1779176405; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=7xf70jF6KOg/SiWMlOWjk6atZ2ryfC9YUcEG9Wm/SIo=; b=awwTIihnb+IbsrztHKejhkjTuLvc4KVabFVIyqAK2ujdOxn6omDWFTJ9u13VZg6+VG +VrhhYngGtTf+lBv+1szpDl8yFWlUA8cTmLIx6BVo4o5Ii/XdCST5HSRy7DF2K4nsgC8 hLR7De8DhKof/1bTJXdwOcAYB97D+e12cc7zkuvs12UQwOoR0BDtrXK3G6HynI3B7fV0 rXBxh0Xc071NjUvc68L6qO+NJz++d7FPqrU5BdNdxJkbwDYTIw2Xwscpas4s7W7Kg+bj SvGYQDpuVfV5oLOMbGH5YhlfXE/bgJJaJV2MqV5JgFKcl6MfL+xhMCl3+uCx4BtlRE/C j1Nw== X-Forwarded-Encrypted: i=1; AFNElJ+4XYuEZk6zfh/b1a34uZDv65ysjc1AmbGOG9llczwAznWEWwZpLthMUvmBwD5pRWf3SzF/ELnMLl1nNzg=@vger.kernel.org X-Gm-Message-State: AOJu0Yx5BCSMGMRdt0C7kDE608xNVtyoxwCkpjVPJq69mCTohm8Ccn55 j2xNmUd1I8QfAIp5+GtdZfP3tLuyo9idTobGmwhfr2RTRhxMnZ8mzcq7 X-Gm-Gg: Acq92OFySFa6KWT9PzLPxOGf517oVATR6Gcajm+jrvBjpBNKupseCT8beiLC+e5Ec2p l8qpI+UgOG6PCEwiTsFKZzasWUgmaK6DqckQp/ZkXIi8V40E7WVHt7ICV9yAphJZhgxWZY8QhV2 vxgIe0N/3fM5E7Lbr+zDe091+KNBoTr6/GQmPZROxP+KGDA+Tl+jDMQZGG/RikH/q1ku/ehrPVE NdHewHfw9DONcnu+3oiLVCYepECZfhFpYWTMs12m1gx3OPhiUxxGV3/Yzn6Ui8Prd2zQTbChkgw 2wAAGc5xtLdJOmPGw6ixKnTsAeQU22ZA2YP3a9eNVGncF5kD+MR1phYjKJaeVjDoPsZ5kCyuY+b zxy8SzD6aSHtOwvack/xfA+sFD3AvTdBahKYNmI80PI88l8HfOhO8xFtWM8vwTdlCwXx+jpQEU1 PvoNbmmVhtfqLkzGom4E/VmaYyxgC7TkhDQ/9nrV6HBYI4jga4u5DhP7StONL4y5OTVw9X+aAUF z3OkLwpnQ== X-Received: by 2002:a17:90b:2808:b0:366:2668:b5b6 with SMTP id 98e67ed59e1d1-3664cd22759mr16575930a91.22.1778571604619; Tue, 12 May 2026 00:40:04 -0700 (PDT) Received: from localhost.localdomain (60-250-196-139.hinet-ip.hinet.net. [60.250.196.139]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-367d65ed459sm13264489a91.14.2026.05.12.00.40.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 May 2026 00:40:04 -0700 (PDT) From: Zi-Yu Chen To: Jacky Huang , Andi Shyti Cc: Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-arm-kernel@lists.infradead.org, linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Zi-Yu Chen , Krzysztof Kozlowski Subject: [PATCH v3 1/3] dt-bindings: i2c: nuvoton,ma35d1-i2c: Add MA35D1 I2C controller Date: Tue, 12 May 2026 15:39:51 +0800 Message-Id: <20260512073953.564323-2-zychennvt@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260512073953.564323-1-zychennvt@gmail.com> References: <20260512073953.564323-1-zychennvt@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add device tree binding documentation for the I2C controller found in the Nuvoton MA35D1 SoC. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Zi-Yu Chen --- .../bindings/i2c/nuvoton,ma35d1-i2c.yaml | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/nuvoton,ma35d1-i2= c.yaml diff --git a/Documentation/devicetree/bindings/i2c/nuvoton,ma35d1-i2c.yaml = b/Documentation/devicetree/bindings/i2c/nuvoton,ma35d1-i2c.yaml new file mode 100644 index 000000000000..f2c004049d86 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/nuvoton,ma35d1-i2c.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/nuvoton,ma35d1-i2c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Nuvoton MA35D1 I2C Controller + +maintainers: + - Zi-Yu Chen + +description: + The Nuvoton MA35D1 I2C controller supports controller and optional targe= t mode. + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + +properties: + compatible: + const: nuvoton,ma35d1-i2c + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-frequency: + description: + Desired I2C bus clock frequency in Hz. The absence of this property + indicates the default frequency 100 kHz. + + resets: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - resets + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + + i2c0: i2c@40800000 { + compatible =3D "nuvoton,ma35d1-i2c"; + reg =3D <0x40800000 0x1000>; + interrupts =3D ; + clocks =3D <&clk I2C0_GATE>; + clock-frequency =3D <100000>; + resets =3D <&sys MA35D1_RESET_I2C0>; + #address-cells =3D <1>; + #size-cells =3D <0>; + }; --=20 2.34.1 From nobody Fri Jun 12 22:47:17 2026 Received: from mail-pj1-f42.google.com (mail-pj1-f42.google.com [209.85.216.42]) (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 C32B947F2FE for ; Tue, 12 May 2026 07:40:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778571620; cv=none; b=Pt06ZnEk1ZfflSDxdCzvEyNbibBG949ihn1vQgpv3faDRoYDbycKkBT6mNFbVZVN1SWrrau6Kg3AbP4dKOFV5tVIok4phmBBUFwIolFm/AcY7yTwD3IyKC8bemUa0gZF6yjk32/r+13AA4GFd0UxJ6halidu8Y9LLBQQD8zuRS8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778571620; c=relaxed/simple; bh=MhqQrpHmoTu1zxj01gL/Kfh3Ef1qS7E+BmcOx90E5PA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ElgIMeY/yo1MjwEkylDTDVs+8Fk5AloihDlRJcXPeGjkj1lmcHgJLtfxpATeHIs9/YuCTE2KBXnnw3TdlGVBD6sTH0ex+WaVPxIGrMEitwwmjTc30Df6veD6oSrm3u5UYqr5qL2jBccRWeg6SU4ABtWVMkHP2l6Kr7T5emJ5QHY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=gRRoBThU; arc=none smtp.client-ip=209.85.216.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gRRoBThU" Received: by mail-pj1-f42.google.com with SMTP id 98e67ed59e1d1-3660b84347dso3212654a91.1 for ; Tue, 12 May 2026 00:40:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778571610; x=1779176410; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+KaF/cT1urz2FMkh7znVTJHQNNBUWP/bVQjzY7ITEUs=; b=gRRoBThUwjFRQl4xMn6c3cHZkCW5HfSGqKLmiXsSKG4aOv4sukndIEZe5VgfX8BgPN fhofT61f9j1VQIliLOECshrtYSpriI9pZm9KuYzQjvxmmja43fnQ15zmW6sOtG5m+Lf8 Y0BQeBnAIMGqs3Pd6NXKwP7kbEj77+TKqOCHcuaXT5ICNeiakhCzs9nOZvbiAv7WeIPr OEBU+VrWrkU/I4A1OYcFZ0WYPaAo1QfDZdku97om50ogLLomcMjD523VlV3JUjU88c6G /eO12/2TTjnJPJG6VLfA1/0qaz3rQBBWiJkAosUV9+lJPWpYapsJF44VwNxHGjxxRBaM 5RGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778571610; x=1779176410; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=+KaF/cT1urz2FMkh7znVTJHQNNBUWP/bVQjzY7ITEUs=; b=cptGE3T2fhjWokQOI/JJWQBRQ5CHsF5yB3G4LTZZs9X57xwmJWjCL2Q3JYPm01KdJ0 qwsVizGMpLaNYkjXRPRwxo4RB3/ZKRsFp497KQHMwCDJE25eeHWTLifkcq4uEA0GTNJn vxxQgHl3F9ia4m1R5K5TjH3pJVw0q23Bv9uXAoOdA0WFyj2klUKdTY2nIePIyCUNxE/E c2Mq4PUb38eMKaEvG7z9TbBV+5UZQ/yNqf7Q6yfl99B2JqrG11nqvXoJ/JzvucR8Ubs5 ABFJ9OvRphoxm0TUs2vpphw9wEw4sS2aL5i5b6VP7l+68fduOeionYdovFXsorggjka5 r0Ig== X-Forwarded-Encrypted: i=1; AFNElJ/wt6PZORP3Z2KcdtKzrnaTVRk+UsQ3fk3afbKJO3/8lcKNvEvcdRNLuZR9gvC4uo+4x/t4W5LlCwsTPSQ=@vger.kernel.org X-Gm-Message-State: AOJu0YwhlssJACRyIrpekoMGk6nTKxlRab2lVbri2rQxqffktURxrZ6K wzl1/Bp5V9CIyOozVoEvd772Ub3Re4PTSNlw4pKnDSFe0L9zy4g4ohsJ X-Gm-Gg: Acq92OEaXFh//ADGYMqrGxcZE7GMN6Ch4eHTD+FO2i1dvRWrQmXxoDUkaQL9TPxiqKO rUSK2idB3mejuBmDNHBcso/Zj8b3IiTLSJx4m88eplAikPTW1N9g7lWNL4tbmXE60y/0M/0XPWk m2LlVvhVpAAOb2gCqXBXg6VOp/zmArqj19O+cN+LGMDGFCvFsniOJHYu7rd3sqccZMQRfsNjQAl fKRbBuTwb9Nkke1bTx3NyrsJo2QHr13eZG2xv9P25yZ3QxUeoxBzFiekRpzDAhXLPrKL1uCxwZZ eUuDurzzrs+GUhXGfNVZuew/crCBXU9uxwHoBPEmsukoo6KeOHOEdkoY/54LabN3jqW2neMV+wI sGam92hyjjPEzz2f4JLvDZ8ouTSn8mT7wWMhuJ263rIXdBZ90wQ3how5lciNUmkRwwp4gj2iUOZ vio/Nd0wCHN3fVkfDflzpOXKxfTIprDAc5ZQrW7FQScOR88aYOULZxOPQF899z12Y44bmk6clWg lUQQPTNnQ== X-Received: by 2002:a17:90b:55c3:b0:366:4782:1389 with SMTP id 98e67ed59e1d1-368b269e82cmr2200000a91.14.1778571610086; Tue, 12 May 2026 00:40:10 -0700 (PDT) Received: from localhost.localdomain (60-250-196-139.hinet-ip.hinet.net. [60.250.196.139]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-367d65ed459sm13264489a91.14.2026.05.12.00.40.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 May 2026 00:40:09 -0700 (PDT) From: Zi-Yu Chen To: Jacky Huang , Andi Shyti Cc: Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-arm-kernel@lists.infradead.org, linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Zi-Yu Chen Subject: [PATCH v3 2/3] i2c: ma35d1: Add Nuvoton MA35D1 I2C driver support Date: Tue, 12 May 2026 15:39:52 +0800 Message-Id: <20260512073953.564323-3-zychennvt@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260512073953.564323-1-zychennvt@gmail.com> References: <20260512073953.564323-1-zychennvt@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add I2C support for Nuvoton MA35D1 SoC. The controller supports standard, fast and fast-plus modes, and provides controller/target functionality. Signed-off-by: Zi-Yu Chen --- drivers/i2c/busses/Kconfig | 13 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-ma35d1.c | 792 ++++++++++++++++++++++++++++++++ 3 files changed, 806 insertions(+) create mode 100644 drivers/i2c/busses/i2c-ma35d1.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index ea3e7e92465d..401dcc9be46b 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -1601,4 +1601,17 @@ config I2C_VIRTIO This driver can also be built as a module. If so, the module will be called i2c-virtio. =20 +config I2C_MA35D1 + tristate "Nuvoton MA35D1 I2C driver" + depends on ARCH_MA35 || COMPILE_TEST + select I2C_SLAVE + help + If you say yes to this option, support will be included for the + I2C controller in the Nuvoton MA35D1 SoC. This driver + supports the standard I2C bus protocols, including master and + slave modes. + + This driver can also be built as a module. If so, the module + will be called i2c-ma35d1. + endmenu diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 3755c54b3d82..ca75dae4955c 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -131,6 +131,7 @@ obj-$(CONFIG_I2C_XILINX) +=3D i2c-xiic.o obj-$(CONFIG_I2C_XLP9XX) +=3D i2c-xlp9xx.o obj-$(CONFIG_I2C_RCAR) +=3D i2c-rcar.o obj-$(CONFIG_I2C_GXP) +=3D i2c-gxp.o +obj-$(CONFIG_I2C_MA35D1) +=3D i2c-ma35d1.o =20 # External I2C/SMBus adapter drivers obj-$(CONFIG_I2C_DIOLAN_U2C) +=3D i2c-diolan-u2c.o diff --git a/drivers/i2c/busses/i2c-ma35d1.c b/drivers/i2c/busses/i2c-ma35d= 1.c new file mode 100644 index 000000000000..c643f406e000 --- /dev/null +++ b/drivers/i2c/busses/i2c-ma35d1.c @@ -0,0 +1,792 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2026 Nuvoton technology corporation. + * + * Author: Zi-Yu Chen + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* MA35D1 I2C registers offset */ +#define MA35_CTL0 0x00 +#define MA35_ADDR0 0x04 +#define MA35_DAT 0x08 +#define MA35_STATUS0 0x0c +#define MA35_CLKDIV 0x10 +#define MA35_TOCTL 0x14 +#define MA35_ADDR1 0x18 +#define MA35_ADDR2 0x1c +#define MA35_ADDR3 0x20 +#define MA35_ADDRMSK0 0x24 +#define MA35_ADDRMSK1 0x28 +#define MA35_ADDRMSK2 0x2c +#define MA35_ADDRMSK3 0x30 +#define MA35_WKCTL 0x3c +#define MA35_WKSTS 0x40 +#define MA35_CTL1 0x44 +#define MA35_STATUS1 0x48 +#define MA35_TMCTL 0x4c +#define MA35_BUSCTL 0x50 +#define MA35_BUSTCTL 0x54 +#define MA35_BUSSTS 0x58 +#define MA35_PKTSIZE 0x5c +#define MA35_PKTCRC 0x60 +#define MA35_BUSTOUT 0x64 +#define MA35_CLKTOUT 0x68 +#define MA35_AUTOCNT 0x78 + +/* MA35D1 I2C Status */ +/* Controller */ +#define MA35_M_START 0x08 /* Start */ +#define MA35_M_REPEAT_START 0x10 /* Controller Repeat Start */ +#define MA35_M_TRAN_ADDR_ACK 0x18 /* Controller Transmit Address ACK */ +#define MA35_M_TRAN_ADDR_NACK 0x20 /* Controller Transmit Address NACK */ +#define MA35_M_TRAN_DATA_ACK 0x28 /* Controller Transmit Data ACK */ +#define MA35_M_TRAN_DATA_NACK 0x30 /* Controller Transmit Data NACK */ +#define MA35_M_ARB_LOST 0x38 /* Controller Arbitration Lost */ +#define MA35_M_RECE_ADDR_ACK 0x40 /* Controller Receive Address ACK */ +#define MA35_M_RECE_ADDR_NACK 0x48 /* Controller Receive Address NACK */ +#define MA35_M_RECE_DATA_ACK 0x50 /* Controller Receive Data ACK */ +#define MA35_M_RECE_DATA_NACK 0x58 /* Controller Receive Data NACK */ +#define MA35_BUS_ERROR 0x00 /* Bus error */ + +/* Target */ +#define MA35_S_REPEAT_START_STOP 0xa0 /* Target Transmit Repeat Start or S= top */ +#define MA35_S_TRAN_ADDR_ACK 0xa8 /* Target Transmit Address ACK */ +#define MA35_S_TRAN_DATA_ACK 0xb8 /* Target Transmit Data ACK */ +#define MA35_S_TRAN_DATA_NACK 0xc0 /* Target Transmit Data NACK */ +#define MA35_S_TRAN_LAST_DATA_ACK 0xc8 /* Target Transmit Last Data ACK */ +#define MA35_S_RECE_ADDR_ACK 0x60 /* Target Receive Address ACK */ +#define MA35_S_RECE_ARB_LOST 0x68 /* Target Receive Arbitration Lost */ +#define MA35_S_RECE_DATA_ACK 0x80 /* Target Receive Data ACK */ +#define MA35_S_RECE_DATA_NACK 0x88 /* Target Receive Data NACK */ + +/* GC Mode */ +#define MA35_GC_ADDR_ACK 0x70 /* GC mode Address ACK */ +#define MA35_GC_ARB_LOST 0x78 /* GC mode Arbitration Lost */ +#define MA35_GC_DATA_ACK 0x90 /* GC mode Data ACK */ +#define MA35_GC_DATA_NACK 0x98 /* GC mode Data NACK */ + +/* Other */ +#define MA35_ADDR_TRAN_ARB_LOST 0xb0 /* Address Transmit Arbitration Lost= */ +#define MA35_BUS_RELEASED 0xf8 /* Bus Released */ + +/* I2C_CTL constant definitions. */ +#define MA35_CTL_AA BIT(2) +#define MA35_CTL_SI BIT(3) +#define MA35_CTL_STO BIT(4) +#define MA35_CTL_STA BIT(5) +#define MA35_CTL_I2CEN BIT(6) +#define MA35_CTL_INTEN BIT(7) +#define MA35_CTL_SI_AA (MA35_CTL_SI | MA35_CTL_AA) +#define MA35_CTL_STO_SI (MA35_CTL_STO | MA35_CTL_SI) +#define MA35_CTL_STA_SI (MA35_CTL_STA | MA35_CTL_SI) +#define MA35_CTL_STA_SI_AA (MA35_CTL_STA | MA35_CTL_SI | MA35_CTL_AA) +#define MA35_CTL_STO_SI_AA (MA35_CTL_STO | MA35_CTL_SI | MA35_CTL_AA) + +/* Constants */ +#define MA35_CLKDIV_MSK GENMASK(15, 0) +#define MA35_I2C_ADDR_MASK (0x7f << 1) +#define I2C_PM_TIMEOUT_MS 5000 +#define STOP_TIMEOUT_MS 50 +#define MA35_I2C_GC_EN 1 +#define MA35_I2C_GC_DIS 0 + +struct ma35d1_i2c { + spinlock_t lock; /* Protects I2C register access and state */ + wait_queue_head_t wait; + struct i2c_msg *msg; + unsigned int msg_num; + unsigned int msg_idx; + unsigned int msg_ptr; + unsigned int irq; + unsigned int arblost; + void __iomem *regs; + struct clk *clk; + struct device *dev; + struct i2c_adapter adap; + struct i2c_client *target; + struct reset_control *rst; +}; + +static inline bool ma35d1_is_controller_status(unsigned int status) +{ + return status >=3D MA35_M_START && status <=3D MA35_M_RECE_DATA_NACK; +} + +/* + * ma35d1_i2c_write_CTL - Update the I2C control register + * @i2c: Pointer to the ma35d1 i2c instance + * @ctl: Control bits to set (e.g., MA35_CTL_STA, SI, AA) + * + * This helper reads CTL0, clears the sticky state-change bits (STA, STO, = SI, AA), + * and then applies the new control bits provided by @ctl. + */ +static void ma35d1_i2c_write_CTL(struct ma35d1_i2c *i2c, unsigned int ctl) +{ + unsigned int val; + + val =3D readl(i2c->regs + MA35_CTL0); + val &=3D ~(MA35_CTL_STA_SI_AA | MA35_CTL_STO); + val |=3D ctl; + writel(val, i2c->regs + MA35_CTL0); +} + +static void ma35d1_i2c_set_addr(struct ma35d1_i2c *i2c) +{ + unsigned int rw =3D i2c->msg->flags & I2C_M_RD; + + writel(((i2c->msg->addr & 0x7f) << 1) | rw, i2c->regs + MA35_DAT); +} + +static void ma35d1_i2c_controller_complete(struct ma35d1_i2c *i2c, int ret) +{ + dev_dbg(i2c->dev, "controller_complete %d\n", ret); + + i2c->msg_ptr =3D 0; + i2c->msg =3D NULL; + i2c->msg_idx++; + i2c->msg_num =3D 0; + if (ret) + i2c->msg_idx =3D ret; + + wake_up(&i2c->wait); +} + +static void ma35d1_i2c_disable_irq(struct ma35d1_i2c *i2c) +{ + unsigned long tmp; + + tmp =3D readl(i2c->regs + MA35_CTL0); + writel(tmp & ~MA35_CTL_INTEN, i2c->regs + MA35_CTL0); +} + +static void ma35d1_i2c_enable_irq(struct ma35d1_i2c *i2c) +{ + unsigned long tmp; + + tmp =3D readl(i2c->regs + MA35_CTL0); + writel(tmp | MA35_CTL_INTEN, i2c->regs + MA35_CTL0); +} + +static void ma35d1_i2c_reset(struct ma35d1_i2c *i2c) +{ + unsigned int tmp; + + tmp =3D readl(i2c->regs + MA35_CLKDIV); + + reset_control_assert(i2c->rst); + usleep_range(10, 20); + reset_control_deassert(i2c->rst); + + writel(tmp, (i2c->regs + MA35_CLKDIV)); + ma35d1_i2c_write_CTL(i2c, MA35_CTL_I2CEN); + + if (i2c->target) + ma35d1_i2c_write_CTL(i2c, MA35_CTL_SI_AA); +} + +static void ma35d1_i2c_stop(struct ma35d1_i2c *i2c, int ret) +{ + unsigned int val; + int err; + + /* Ensure AA is cleared to prevent the controller + * from re-claiming the bus unnecessarily + */ + if (readl(i2c->regs + MA35_CTL0) & MA35_CTL_AA) { + val =3D readl(i2c->regs + MA35_CTL0); + val &=3D ~MA35_CTL_AA; + writel(val, (i2c->regs + MA35_CTL0)); + + err =3D readl_poll_timeout_atomic(i2c->regs + MA35_CTL0, val, + !(val & MA35_CTL_AA), 1, 1000); + if (err) + dev_warn(i2c->dev, + "AA bit could not be cleared in time\n"); + } + + ma35d1_i2c_write_CTL(i2c, MA35_CTL_STO_SI); + + err =3D readl_poll_timeout_atomic(i2c->regs + MA35_CTL0, val, + !(val & MA35_CTL_STO), 1, 1 * 1000); + if (err) + dev_warn(i2c->dev, "I2C Stop Timeout\n"); + + if (i2c->target) + ma35d1_i2c_write_CTL(i2c, MA35_CTL_SI_AA); + else + ma35d1_i2c_disable_irq(i2c); + + ma35d1_i2c_controller_complete(i2c, ret); +} + +/* Check if this is the last message in the set */ +static inline bool is_last_msg(struct ma35d1_i2c *i2c) +{ + return i2c->msg_idx >=3D (i2c->msg_num - 1); +} + +/* Check if this is the last byte in the current message */ +static inline bool is_last_byte(struct ma35d1_i2c *i2c) +{ + return i2c->msg_ptr =3D=3D i2c->msg->len - 1; +} + +/* Check if reached the end of the current message */ +static inline bool is_msgend(struct ma35d1_i2c *i2c) +{ + return i2c->msg_ptr >=3D i2c->msg->len; +} + +/* + * i2c_ma35d1_irq_target_trx - I2C Target state machine handler + * @i2c: ma35d1 i2c instance + * @i2c_status: hardware status code from MA35_STATUS0 + */ +static void i2c_ma35d1_irq_target_trx(struct ma35d1_i2c *i2c, + unsigned long i2c_status) +{ + unsigned char byte; + + switch (i2c_status) { + case MA35_S_RECE_ADDR_ACK: + /* Own SLA+W has been receive; ACK has been return */ + i2c_slave_event(i2c->target, I2C_SLAVE_WRITE_REQUESTED, &byte); + break; + case MA35_S_TRAN_DATA_NACK: + /* Data byte or last data in I2CDAT has been transmitted. + * Not ACK has been received + */ + case MA35_S_RECE_DATA_NACK: + /* Previously addressed with own SLA address; + * NOT ACK has been returned + */ + break; + + case MA35_S_RECE_DATA_ACK: + /* Previously address with own SLA address Data has been received; + * ACK has been returned + */ + byte =3D readb(i2c->regs + MA35_DAT); + i2c_slave_event(i2c->target, I2C_SLAVE_WRITE_RECEIVED, &byte); + break; + + case MA35_S_TRAN_ADDR_ACK: + /* Own SLA+R has been receive; ACK has been return */ + i2c_slave_event(i2c->target, I2C_SLAVE_READ_REQUESTED, &byte); + + writel(byte, i2c->regs + MA35_DAT); + break; + + case MA35_S_TRAN_DATA_ACK: + i2c_slave_event(i2c->target, I2C_SLAVE_READ_PROCESSED, &byte); + writel(byte, i2c->regs + MA35_DAT); + break; + + case MA35_S_REPEAT_START_STOP: + /* A STOP or repeated START has been received + * while still addressed as Target/Receiver + */ + i2c_slave_event(i2c->target, I2C_SLAVE_STOP, &byte); + break; + + default: + dev_err(i2c->dev, "Status 0x%02lx is NOT processed\n", + i2c_status); + break; + } + ma35d1_i2c_write_CTL(i2c, MA35_CTL_SI_AA); +} + +/* + * i2c_ma35d1_irq_controller_trx - I2C Controller state machine handler + * @i2c: ma35d1 i2c instance + * @i2c_status: hardware status code from MA35_STATUS0 + */ +static void i2c_ma35d1_irq_controller_trx(struct ma35d1_i2c *i2c, + unsigned long i2c_status) +{ + unsigned char byte; + + switch (i2c_status) { + case MA35_M_START: + case MA35_M_REPEAT_START: + ma35d1_i2c_set_addr(i2c); + ma35d1_i2c_write_CTL(i2c, MA35_CTL_SI); + break; + + case MA35_M_TRAN_ADDR_ACK: + case MA35_M_TRAN_DATA_ACK: + /* SLA+W has been transmitted and ACK has been received */ + if (i2c_status =3D=3D MA35_M_TRAN_ADDR_ACK) { + if (is_last_msg(i2c) && i2c->msg->len =3D=3D 0) { + ma35d1_i2c_stop(i2c, 0); + return; + } + } + + if (!is_msgend(i2c)) { + byte =3D i2c->msg->buf[i2c->msg_ptr++]; + writel(byte, i2c->regs + MA35_DAT); + ma35d1_i2c_write_CTL(i2c, MA35_CTL_SI); + } else if (!is_last_msg(i2c)) { + dev_dbg(i2c->dev, "WRITE: Next Message\n"); + + i2c->msg_ptr =3D 0; + i2c->msg_idx++; + i2c->msg++; + + ma35d1_i2c_write_CTL(i2c, MA35_CTL_STA | MA35_CTL_SI); + } else { + ma35d1_i2c_stop(i2c, 0); + } + break; + + case MA35_M_TRAN_DATA_NACK: + ma35d1_i2c_stop(i2c, 0); + break; + + case MA35_M_TRAN_ADDR_NACK: + case MA35_M_RECE_ADDR_NACK: + /* Controller Transmit Address NACK */ + /* 0x20: SLA+W has been transmitted and NACK has been received */ + /* 0x48: SLA+R has been transmitted and NACK has been received */ + if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) { + dev_dbg(i2c->dev, "\n i2c: ack was not received\n"); + ma35d1_i2c_stop(i2c, -ENXIO); + } + break; + + case MA35_M_RECE_ADDR_ACK: + if (is_last_msg(i2c) && i2c->msg->len =3D=3D 0) + ma35d1_i2c_stop(i2c, 0); + else if (is_last_msg(i2c) && (i2c->msg->len =3D=3D 1)) + ma35d1_i2c_write_CTL(i2c, MA35_CTL_SI); + else + ma35d1_i2c_write_CTL(i2c, MA35_CTL_SI_AA); + break; + + case MA35_M_RECE_DATA_ACK: + case MA35_M_RECE_DATA_NACK: + /* DATA has been transmitted and ACK has been received */ + byte =3D readb(i2c->regs + MA35_DAT); + i2c->msg->buf[i2c->msg_ptr++] =3D byte; + + if (is_last_byte(i2c)) { + ma35d1_i2c_write_CTL(i2c, MA35_CTL_SI); + } else if (is_msgend(i2c)) { + if (is_last_msg(i2c)) { + dev_dbg(i2c->dev, "READ: Send Stop\n"); + + ma35d1_i2c_stop(i2c, 0); + } else { + dev_dbg(i2c->dev, "READ: Next Transfer\n"); + + i2c->msg_ptr =3D 0; + i2c->msg_idx++; + i2c->msg++; + + ma35d1_i2c_write_CTL(i2c, MA35_CTL_STA_SI); + } + } else { + ma35d1_i2c_write_CTL(i2c, MA35_CTL_SI_AA); + } + break; + + default: + dev_err(i2c->dev, "Status 0x%02lx is NOT processed\n", + i2c_status); + ma35d1_i2c_disable_irq(i2c); + ma35d1_i2c_stop(i2c, 0); + break; + } +} + +static irqreturn_t ma35d1_i2c_irq(int irqno, void *dev_id) +{ + struct ma35d1_i2c *i2c =3D dev_id; + unsigned long status, flags; + + status =3D readl(i2c->regs + MA35_STATUS0); + + spin_lock_irqsave(&i2c->lock, flags); + + if (status =3D=3D MA35_M_ARB_LOST) { + dev_err(i2c->dev, "Arbitration lost\n"); + i2c->arblost =3D 1; + ma35d1_i2c_disable_irq(i2c); + ma35d1_i2c_stop(i2c, -EAGAIN); + goto out; + } + + else if (status =3D=3D MA35_BUS_ERROR) { + dev_err(i2c->dev, "Bus error during transfer\n"); + ma35d1_i2c_disable_irq(i2c); + ma35d1_i2c_stop(i2c, 0); + goto out; + } + + if (ma35d1_is_controller_status(status)) + i2c_ma35d1_irq_controller_trx(i2c, status); + else + i2c_ma35d1_irq_target_trx(i2c, status); + +out: + spin_unlock_irqrestore(&i2c->lock, flags); + return IRQ_HANDLED; +} + +static int ma35d1_i2c_doxfer(struct ma35d1_i2c *i2c, struct i2c_msg *msgs, + int num) +{ + unsigned long timeout; + unsigned int val; + int ret, err; + + spin_lock_irq(&i2c->lock); + + ma35d1_i2c_enable_irq(i2c); + + i2c->msg =3D msgs; + i2c->msg_num =3D num; + i2c->msg_ptr =3D 0; + i2c->msg_idx =3D 0; + + ma35d1_i2c_write_CTL(i2c, MA35_CTL_SI | MA35_CTL_STA); + spin_unlock_irq(&i2c->lock); + + timeout =3D wait_event_timeout(i2c->wait, i2c->msg_num =3D=3D 0, HZ * 5); + ret =3D i2c->msg_idx; + + if (timeout =3D=3D 0) + dev_dbg(i2c->dev, "timeout\n"); + else if (ret !=3D num) + dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); + + err =3D readl_poll_timeout(i2c->regs + MA35_CTL0, val, + !(val & MA35_CTL_STO), 100, + STOP_TIMEOUT_MS * 1000); + + if (err) { + dev_err(i2c->dev, "Bus stuck! Resetting controller...\n"); + ma35d1_i2c_reset(i2c); + } + + if (i2c->arblost) { + dev_dbg(i2c->dev, "arb lost, stop\n"); + i2c->arblost =3D 0; + } + + return ret; +} + +static int ma35d1_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num) +{ + struct ma35d1_i2c *i2c =3D i2c_get_adapdata(adap); + int retry, ret; + + ret =3D pm_runtime_resume_and_get(i2c->dev); + if (ret) + return ret; + + for (retry =3D 0; retry < adap->retries; retry++) { + ret =3D ma35d1_i2c_doxfer(i2c, msgs, num); + + if (ret !=3D -EAGAIN) + break; + + dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry); + fsleep(100); + } + + if (ret =3D=3D -EAGAIN) + ret =3D -EREMOTEIO; + + pm_runtime_put_autosuspend(i2c->dev); + + return ret; +} + +static int ma35d1_reg_target(struct i2c_client *target) +{ + struct ma35d1_i2c *i2c =3D i2c_get_adapdata(target->adapter); + unsigned int val, slvaddr; + int ret; + + if (i2c->target) + return -EBUSY; + + if (target->flags & I2C_CLIENT_TEN) + return -EAFNOSUPPORT; + + ma35d1_i2c_enable_irq(i2c); + + ret =3D pm_runtime_resume_and_get(i2c->dev); + if (ret) { + dev_err(i2c->dev, "failed to resume i2c controller\n"); + return ret; + } + + i2c->target =3D target; + + val =3D readl(i2c->regs + MA35_CTL0); + val |=3D MA35_CTL_I2CEN; + writel(val, i2c->regs + MA35_CTL0); + slvaddr =3D target->addr << 1; + writel(slvaddr, i2c->regs + MA35_ADDR0); + + /* I2C enter SLV mode */ + ma35d1_i2c_write_CTL(i2c, MA35_CTL_SI_AA); + + return 0; +} + +static int ma35d1_unreg_target(struct i2c_client *target) +{ + struct ma35d1_i2c *i2c =3D i2c_get_adapdata(target->adapter); + unsigned int val; + int ret; + + /* Disable I2C */ + val =3D readl(i2c->regs + MA35_CTL0); + val &=3D ~MA35_CTL_I2CEN; + writel(val, i2c->regs + MA35_CTL0); + + /* Disable I2C interrupt */ + ma35d1_i2c_disable_irq(i2c); + + i2c->target =3D NULL; + + ret =3D pm_runtime_put_sync(i2c->dev); + if (ret) + dev_err(i2c->dev, "failed to suspend i2c controller"); + + return 0; +} + +/* Declare Our I2C Functionality */ +static u32 ma35d1_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_PROTOCOL_MANGLING | I2C_FUNC_SMBUS_EMUL; +} + +/* I2C Bus Registration Info */ +static const struct i2c_algorithm ma35d1_i2c_algorithm =3D { + .xfer =3D ma35d1_i2c_xfer, + .functionality =3D ma35d1_i2c_func, + .reg_target =3D ma35d1_reg_target, + .unreg_target =3D ma35d1_unreg_target, +}; + +static int ma35d1_i2c_probe(struct platform_device *pdev) +{ + struct ma35d1_i2c *i2c; + struct resource *res; + int ret, clkdiv; + unsigned int busfreq; + struct device *dev =3D &pdev->dev; + + i2c =3D devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + spin_lock_init(&i2c->lock); + init_waitqueue_head(&i2c->wait); + + i2c->dev =3D dev; + + i2c->clk =3D devm_clk_get_prepared(dev, NULL); + if (IS_ERR(i2c->clk)) + return dev_err_probe(dev, PTR_ERR(i2c->clk), + "failed to get core clk\n"); + + i2c->regs =3D devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(i2c->regs)) + return PTR_ERR(i2c->regs); + + i2c->rst =3D devm_reset_control_get_exclusive(&pdev->dev, NULL); + if (IS_ERR(i2c->rst)) + return dev_err_probe(dev, PTR_ERR(i2c->rst), + "failed to get reset control\n"); + + /* Setup info block for the I2C core */ + strscpy(i2c->adap.name, "ma35d1-i2c", sizeof(i2c->adap.name)); + i2c->adap.owner =3D THIS_MODULE; + i2c->adap.algo =3D &ma35d1_i2c_algorithm; + i2c->adap.retries =3D 2; + i2c->adap.algo_data =3D i2c; + i2c->adap.dev.parent =3D &pdev->dev; + i2c->adap.dev.of_node =3D pdev->dev.of_node; + i2c_set_adapdata(&i2c->adap, i2c); + + /* Default to 100kHz if not specified in DT */ + busfreq =3D 100000; + device_property_read_u32(dev, "clock-frequency", &busfreq); + + /* Calculate divider based on the current peripheral clock rate */ + clkdiv =3D DIV_ROUND_CLOSEST(clk_get_rate(i2c->clk), busfreq * 4) - 1; + if (clkdiv < 0 || clkdiv > 0xffff) + return dev_err_probe(dev, -EINVAL, "invalid clkdiv value: %d\n", + clkdiv); + + i2c->irq =3D platform_get_irq(pdev, 0); + if (i2c->irq < 0) + return dev_err_probe(dev, i2c->irq, "failed to get irq\n"); + + platform_set_drvdata(pdev, i2c); + + pm_runtime_set_autosuspend_delay(dev, I2C_PM_TIMEOUT_MS); + pm_runtime_use_autosuspend(dev); + devm_pm_runtime_enable(dev); + + ret =3D pm_runtime_resume_and_get(dev); + if (ret) + return dev_err_probe(dev, ret, "failed to resume device\n"); + + writel(FIELD_PREP(MA35_CLKDIV_MSK, clkdiv), i2c->regs + MA35_CLKDIV); + + ret =3D devm_request_irq(dev, i2c->irq, ma35d1_i2c_irq, IRQF_SHARED, + dev_name(dev), i2c); + if (ret) { + dev_err_probe(dev, ret, "cannot claim IRQ %d\n", i2c->irq); + goto rpm_put; + } + + ret =3D devm_i2c_add_adapter(dev, &i2c->adap); + if (ret) { + dev_err_probe(dev, ret, "failed to add bus to i2c core\n"); + goto rpm_put; + } + + pm_runtime_put_autosuspend(dev); + + return 0; + +rpm_put: + pm_runtime_put_noidle(dev); + return ret; +} + +static int ma35d1_i2c_suspend(struct device *dev) +{ + struct ma35d1_i2c *i2c =3D dev_get_drvdata(dev); + unsigned int val; + + spin_lock_irq(&i2c->lock); + + /* Prepare for wake-up from I2C events if target mode is active */ + if (i2c->target) { + val =3D readl(i2c->regs + MA35_CTL0); + val |=3D (MA35_CTL_SI | MA35_CTL_AA); + writel(val, i2c->regs + MA35_CTL0); + ma35d1_i2c_enable_irq(i2c); + } + + spin_unlock_irq(&i2c->lock); + + /* Setup wake-up control */ + writel(0x1, i2c->regs + MA35_WKCTL); + + /* Clear pending wake-up flags */ + val =3D readl(i2c->regs + MA35_WKSTS); + writel(val, i2c->regs + MA35_WKSTS); + + enable_irq_wake(i2c->irq); + + return 0; +} + +static int ma35d1_i2c_resume(struct device *dev) +{ + struct ma35d1_i2c *i2c =3D dev_get_drvdata(dev); + unsigned int val; + + /* Disable wake-up */ + writel(0x0, i2c->regs + MA35_WKCTL); + + /* Clear pending wake-up flags */ + val =3D readl(i2c->regs + MA35_WKSTS); + writel(val, i2c->regs + MA35_WKSTS); + + disable_irq_wake(i2c->irq); + + return 0; +} + +static int ma35d1_i2c_runtime_suspend(struct device *dev) +{ + struct ma35d1_i2c *i2c =3D dev_get_drvdata(dev); + unsigned int val; + + /* Disable I2C controller */ + val =3D readl(i2c->regs + MA35_CTL0); + val &=3D ~MA35_CTL_I2CEN; + writel(val, i2c->regs + MA35_CTL0); + + clk_disable(i2c->clk); + + return 0; +} + +static int ma35d1_i2c_runtime_resume(struct device *dev) +{ + struct ma35d1_i2c *i2c =3D dev_get_drvdata(dev); + unsigned int val; + int ret; + + ret =3D clk_enable(i2c->clk); + if (ret) { + dev_err(dev, "failed to enable clock in resume\n"); + return ret; + } + + /* Enable I2C controller */ + val =3D readl(i2c->regs + MA35_CTL0); + val |=3D MA35_CTL_I2CEN; + writel(val, i2c->regs + MA35_CTL0); + + return 0; +} + +static const struct dev_pm_ops ma35d1_i2c_pmops =3D { + SYSTEM_SLEEP_PM_OPS(ma35d1_i2c_suspend, ma35d1_i2c_resume) + RUNTIME_PM_OPS(ma35d1_i2c_runtime_suspend, + ma35d1_i2c_runtime_resume, NULL) +}; + +static const struct of_device_id ma35d1_i2c_of_match[] =3D { + { .compatible =3D "nuvoton,ma35d1-i2c" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ma35d1_i2c_of_match); + +static struct platform_driver ma35d1_i2c_driver =3D { + .probe =3D ma35d1_i2c_probe, + .driver =3D { + .name =3D "ma35d1-i2c", + .of_match_table =3D ma35d1_i2c_of_match, + .pm =3D pm_ptr(&ma35d1_i2c_pmops), + }, +}; +module_platform_driver(ma35d1_i2c_driver); + +MODULE_AUTHOR("Zi-Yu Chen "); +MODULE_DESCRIPTION("MA35D1 I2C Bus Driver"); +MODULE_LICENSE("GPL"); --=20 2.34.1 From nobody Fri Jun 12 22:47:17 2026 Received: from mail-pj1-f50.google.com (mail-pj1-f50.google.com [209.85.216.50]) (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 A3FC448122F for ; Tue, 12 May 2026 07:40:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778571621; cv=none; b=RLG2BhbB5ey8edvDjyV50iI7RnZ4yER9yY8irPsAd2ncZZtvh1bDGGvtpOQlw6qeX+HXAsRZ3Q+ckaRan27Ga51dvuN2M7IS/xYDfChAYSoR42KuNfEo+dOFX0GYb1wu8aJj/Lq+irT7rHI5SPSUBu5XhqEB/ugMO5z3msmqxoE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778571621; c=relaxed/simple; bh=3OQ02ZZI0kQ/5sJ1+5YlEDCXa+LoKBlgxgLGOXru+fE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=QEbEpfAEqTjSXk/WoKZ918AyTb83R01xY/x/kbuYj70vNb1STELCde3JrRaDCBRWTwC6FedCg9rxVLmnQqOK6zQvi236ZOEb6awiOqzdBOYB7bsytAcXSoz4AeoQC4liqo1qiw3Nqi1wbOQWa2edSIDO8OxrbTyE7F6ZstBN3lw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=diN/inxy; arc=none smtp.client-ip=209.85.216.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="diN/inxy" Received: by mail-pj1-f50.google.com with SMTP id 98e67ed59e1d1-36608b2f2dcso3503032a91.2 for ; Tue, 12 May 2026 00:40:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778571614; x=1779176414; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=m4n/F1eKXbXqdeANeiK1vkq+es+HjdGAH5wuLHdXDwY=; b=diN/inxyDE7b6Lkwh7eAwGQ/EybW3yEyfi0O69EB83gcu814QUEMSdQhcXSSy9StYl 7wNEU7o6ulflOCfQZ2sX1hZvjKEJ2o4UnwCCMf1zY9JyourmgUNQgrEQpdJBABqS5uxT NP+IGs9wU91Ayx91BZePcTrIJ59Cf+eB0VfxOZdRxNYGOTGXmLf51DPc5iCut2IpJmdn kPgCPr2W6IfYYkiV08vramTWCqoGIFaNfrdyeTEAmUlpUj9NK4n70dqMn74CQ7XCfcKf hOprlynss5fcaAsoSXEEHjUq+xPRSDkNTGtMtihDk8oc2X71pD0oJhFqgn+xqIZea1NV Hhjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778571614; x=1779176414; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=m4n/F1eKXbXqdeANeiK1vkq+es+HjdGAH5wuLHdXDwY=; b=svuUa2IvB0UE34rMQNrByqvsPo2jziBt1uhMSCeTzvPxirpTORPELC8zo7qML9ljZP 60B8pfRzPMASb6/52UwzXmbvDM2HybctdvhRCYsNeqJX0d7NJd20k+jGFS6+goY6Kaul jqchWF+6VInHC2T9cT3XdfY/f6vMMnP8x2IqLiuzEl/t1hZVeD0K6ubiduVBYX10hExQ AM5pjmOtoqWIfq3StTz/of3NBAG4t74MJIFtrXT07wPMSJVdBhRjX5W+NMsXVVtnBr8O FKjpO+M4P3vU51oPY6XWG/8fH0LJEGuXtVZi067GJ6e0YijhriZQOGOpw9GWKiS10UKo QcAA== X-Forwarded-Encrypted: i=1; AFNElJ91F1gsQ7f5/Bgrrrvn0WF0lxVeCk8ZUHYT5/YaCYc3MP3CZAogRw15q1n7FvtyoFpUWzFZ/yfq8006KQw=@vger.kernel.org X-Gm-Message-State: AOJu0YwRPW7lg/8oNREVF/tqmu/biSlkpCMx8uT6jqsFXRWYSMn/Sy6Z z37q2AUurgnba+L00gpoi+4XqykJcUcLCE6ytVHENlVDe27fsr9ZFXjrHX1ytw== X-Gm-Gg: Acq92OFbxmiF9wceeFE+FlcwamzPStrqSdLMk1DHtAuJ4gRJhra7ua0LucnlFfvG2HG Zal3NRbxAsWUSsapAVs/qu/5LI583G+rqq7fYPvpH6DOPH4kDzz8t534KcgUPdjBpiHfz9v3IlI /6mNiJU9LxSAjkHcJooL57Zah5xVS/98SFaa8u2gXen9kdkeUQxLwtfUpedWDND4scDq9TZaO9T ZcbmJ7jOw43Ph6QjAo7C/U0cTwYmp4cX30t9+CQQHSkM6jfczrHbiFYYCJk6HqVdEPSeZ3Su+vC rMogW/eJmkt8xDrbvIZDh5ZKjXofHHYu+2ta7kVi75qtYyWMNS3l8JUlKhBtAatSZwx5NPs/9z3 j/LgawBJcK5DJ/WWHSZdZ2zC3ZDW/HB10rL2ESnEwUaA8mAKdZ6JUWV6558bqabuxrW1JAW4aij dB5iPZzgOpL7fH98CJwEnUZAKS4I2WezfMyWwfvU9fuVGCoEQnjfGo+W8cSy2N2QlleacXswpLj g3D9tR75Q== X-Received: by 2002:a17:90b:590f:b0:368:5367:d679 with SMTP id 98e67ed59e1d1-3685368061emr7314796a91.9.1778571614197; Tue, 12 May 2026 00:40:14 -0700 (PDT) Received: from localhost.localdomain (60-250-196-139.hinet-ip.hinet.net. [60.250.196.139]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-367d65ed459sm13264489a91.14.2026.05.12.00.40.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 May 2026 00:40:13 -0700 (PDT) From: Zi-Yu Chen To: Jacky Huang , Andi Shyti Cc: Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-arm-kernel@lists.infradead.org, linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Zi-Yu Chen Subject: [PATCH v3 3/3] arm64: dts: nuvoton: Add I2C nodes for MA35D1 SoC Date: Tue, 12 May 2026 15:39:53 +0800 Message-Id: <20260512073953.564323-4-zychennvt@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260512073953.564323-1-zychennvt@gmail.com> References: <20260512073953.564323-1-zychennvt@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add I2C controller nodes to the MA35D1 SoC dtsi. Also enable the I2C interfaces on the MA35D1 SOM board to allow communication with onboard peripherals. Signed-off-by: Zi-Yu Chen --- .../boot/dts/nuvoton/ma35d1-som-256m.dts | 15 +++++ arch/arm64/boot/dts/nuvoton/ma35d1.dtsi | 60 +++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts b/arch/arm64/b= oot/dts/nuvoton/ma35d1-som-256m.dts index f6f20a17e501..a0f1d76d288e 100644 --- a/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts +++ b/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts @@ -13,6 +13,7 @@ / { compatible =3D "nuvoton,ma35d1-som", "nuvoton,ma35d1"; =20 aliases { + i2c0 =3D &i2c2; serial0 =3D &uart0; serial11 =3D &uart11; serial12 =3D &uart12; @@ -55,6 +56,12 @@ &clk { "integer"; }; =20 +&i2c1 { + pinctrl-names =3D "default"; + pinctrl-0 =3D <&pinctrl_i2c1>; + status =3D "okay"; +}; + &pinctrl { uart-grp { pinctrl_uart0: uart0-pins { @@ -98,6 +105,14 @@ pinctrl_uart16: uart16-pins { power-source =3D <1>; }; }; + + i2c-grp { + pinctrl_i2c1: i2c1-pins { + nuvoton,pins =3D <1 10 12>, + <1 11 12>; + bias-disable; + }; + }; }; =20 &uart0 { diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi b/arch/arm64/boot/dts/= nuvoton/ma35d1.dtsi index e51b98f5bdce..a88d1c2938e7 100644 --- a/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi +++ b/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi @@ -372,6 +372,66 @@ uart15: serial@407f0000 { status =3D "disabled"; }; =20 + i2c1: i2c@40810000 { + compatible =3D "nuvoton,ma35d1-i2c"; + reg =3D <0x0 0x40810000 0x0 0x1000>; + interrupts =3D ; + clocks =3D <&clk I2C1_GATE>; + clock-frequency =3D <100000>; + resets =3D <&sys MA35D1_RESET_I2C1>; + status =3D "disabled"; + #address-cells =3D <1>; + #size-cells =3D <0>; + }; + + i2c2: i2c@40820000 { + compatible =3D "nuvoton,ma35d1-i2c"; + reg =3D <0x0 0x40820000 0x0 0x1000>; + interrupts =3D ; + clocks =3D <&clk I2C2_GATE>; + clock-frequency =3D <100000>; + resets =3D <&sys MA35D1_RESET_I2C2>; + status =3D "disabled"; + #address-cells =3D <1>; + #size-cells =3D <0>; + }; + + i2c3: i2c@40830000 { + compatible =3D "nuvoton,ma35d1-i2c"; + reg =3D <0x0 0x40830000 0x0 0x1000>; + interrupts =3D ; + clocks =3D <&clk I2C3_GATE>; + clock-frequency =3D <100000>; + resets =3D <&sys MA35D1_RESET_I2C3>; + status =3D "disabled"; + #address-cells =3D <1>; + #size-cells =3D <0>; + }; + + i2c4: i2c@40840000 { + compatible =3D "nuvoton,ma35d1-i2c"; + reg =3D <0x0 0x40840000 0x0 0x1000>; + interrupts =3D ; + clocks =3D <&clk I2C4_GATE>; + clock-frequency =3D <100000>; + resets =3D <&sys MA35D1_RESET_I2C4>; + #address-cells =3D <1>; + #size-cells =3D <0>; + status =3D "disabled"; + }; + + i2c5: i2c@40850000 { + compatible =3D "nuvoton,ma35d1-i2c"; + reg =3D <0x0 0x40850000 0x0 0x1000>; + interrupts =3D ; + clocks =3D <&clk I2C5_GATE>; + clock-frequency =3D <100000>; + resets =3D <&sys MA35D1_RESET_I2C5>; + #address-cells =3D <1>; + #size-cells =3D <0>; + status =3D "disabled"; + }; + uart16: serial@40880000 { compatible =3D "nuvoton,ma35d1-uart"; reg =3D <0x0 0x40880000 0x0 0x100>; --=20 2.34.1