From patchwork Sat May 10 19:42:21 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Charkov X-Patchwork-Id: 889314 Received: from mail-pj1-f48.google.com (mail-pj1-f48.google.com [209.85.216.48]) (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 71B4119B3CB; Sat, 10 May 2025 19:42:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746906176; cv=none; b=oYNGVBwzRcoaJ84NQLgkGbxqNjVCTVKbF4H5R7PL8am9sWzziDA4InfJbTRj/naKx+uXoljrGWSgkeoSyHZKSHY1tcpMnqYM7c/EHUyD59ni03Pgqxe3XNyt2vy3pk5WJMGjtgqej/NbEL4X90dT03NQjmGGj9u7lnhPbCZ5UIA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746906176; c=relaxed/simple; bh=mMLcIpsEhoq8UdQQpLuognQnHIyH8ycLrQgiuLuYhxs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JzU/bIt7g7J00vpyAzypdAPJA2XnYUqA2//09axiiSSXKte8N8+PRHMnwSoGiPsGbxaP9q0ustxE9TRJXEhnXN1gEWkTWfPFDozSG7NCJIVf4T5uzq8fGA26LqRCB50TxGZoIl9lt87eRapcEYw5Xe971lSeNP5hamjzePsHQ9w= 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=jt13jA0b; arc=none smtp.client-ip=209.85.216.48 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="jt13jA0b" Received: by mail-pj1-f48.google.com with SMTP id 98e67ed59e1d1-30a8cbddce3so2794177a91.1; Sat, 10 May 2025 12:42:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1746906173; x=1747510973; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=ajRywws6lD8KHlYjxWd9Od+zJbHSPGQcC6B7Bpdbzrc=; b=jt13jA0bt4V9AGLhS2Ln7jBlIxkYuGlgGTntKmn/fXu2uYUFIMn+SPKITi3Kqz37Zw OJra1FrU/4nicOoFQQ1wsgQVrttVR4xff2DyVYHfRS6ELe70cgSJZpXCnm7T2Nf0quHk bhYgzrSUvQbohk/B9qrhu/izl3AZGpU64fHvyFhfIX59R7I+Nl8ef6ttxzl1EyhJEHH4 Ai/poxGnKyJkMj3eHLd2n8QqB3aGCxLomaJoMH+nYFTjeW/OCHgjvycrNX5JaTq1JCIt ZowkgDyHY7Lk2d6u5tOv5mzHUED+e9aXoDQyhM0KDWWaiThYy9LGdw3HkaMYvj86iJIJ A67A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1746906173; x=1747510973; 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=ajRywws6lD8KHlYjxWd9Od+zJbHSPGQcC6B7Bpdbzrc=; b=PedjOXczyvVtSciha7qvbvtoc/MGMnpzWXtAe44XdAthVE+PuOJX0V4Ag9B9M9m6zU J/wrJCE4fnGLAY7AI50h96dtufV7VHF1Utq112Tiv9KfIA8YcuWG4ItiN73+na8V3OVJ pReFJzT5lCnFC6Gqwt9wvLerORybyCRAU9PPvfS+L+GU4kBnO8a4X91wa04enVn5FeW2 BqgSaPPcbIHJprxo10iAN+d1bXYMpUHY/T7sxkxmKOHsTrJci/Z9PblZK+BOUl4uDE/M i1SxUKbzCpuKEFALKAugZeEJ3CZ6PQsCc32nz/pt4QfmjZdcVJ8Ril2znDCnNOSrmea6 aLVg== X-Forwarded-Encrypted: i=1; AJvYcCUKPeU6piESBwerO+4A7UXT5Tqk3HQxQQsSVXMIDbp+GvDjoojCuI5MkgukaPrnYEVM6gWfCI2iiRFJ5Wvo@vger.kernel.org, AJvYcCXD5cviyJWXq8AeXKhxsscXzB76mV4e7wHQTZ+CKfjpush6j5SacxXjABcHlY/HMEf4MdH4ABNoWG62@vger.kernel.org X-Gm-Message-State: AOJu0YwPifvzpXZZXnZcZQR7VIBCuDikNgTYvrKiL3UsDc9Mc+R2KUXQ nLlhsdONLVERkU2KqjZ9QC/RSvJ2eIpVgygg11A0zyvgOrZ8vcnf X-Gm-Gg: ASbGnctM+8vAEtfDhAOD/g75dzv1m7BZcpB58GbcV58xxAjhUoio2DLy8vIvu4g2dSV zhZxmyujodFj6Bo+Pw2Te0a1yxHLEw7x/EaaO+6l750Pw8xb9qhpOnP9lfjgQKcKp2BQ2zMikwR D4eQVBUzNxwpqfl4hPK0mGXlZ1xHsa9gKfbAqHPoFArZIASXMzcQRomyEj9GY9kqLN9luvWuLuq cafN6tChPq4iYeeJIodBNhPYiEUy5D45AkrgXaLELaspBf0IQDlE0LHZk9lFnmBUoydHxYaI7QV dD7Ha3o3CKWLcpX0pHVpKTom+98+WgPHHVdcJAOahJbJppqjyJEHDOJ/VuKQlbU= X-Google-Smtp-Source: AGHT+IHF/6vAuUa2FDr0Jh21aQSSYaG/h9piroxVtpPE5qcBaQXlPgMlxHqaDut6EeR4ncYQAZR0jQ== X-Received: by 2002:a17:90b:390f:b0:2ee:ee5e:42fb with SMTP id 98e67ed59e1d1-30c3cff29ddmr12950783a91.13.1746906173489; Sat, 10 May 2025 12:42:53 -0700 (PDT) Received: from NB-GIGA003.letovo.school ([5.194.95.139]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b2523e67d53sm2223670a12.19.2025.05.10.12.42.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 10 May 2025 12:42:53 -0700 (PDT) From: Alexey Charkov Date: Sat, 10 May 2025 23:42:21 +0400 Subject: [PATCH 1/3] dt-bindings: spi: Add VIA/WonderMedia serial flash controller Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250510-wmt-sflash-v1-1-02a1ac6adf12@gmail.com> References: <20250510-wmt-sflash-v1-0-02a1ac6adf12@gmail.com> In-Reply-To: <20250510-wmt-sflash-v1-0-02a1ac6adf12@gmail.com> To: Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Tudor Ambarus , Pratyush Yadav , Michael Walle , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Krzysztof Kozlowski Cc: linux-spi@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, Alexey Charkov X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1746906149; l=4940; i=alchark@gmail.com; s=20250416; h=from:subject:message-id; bh=mMLcIpsEhoq8UdQQpLuognQnHIyH8ycLrQgiuLuYhxs=; b=qVbf4RLXYHvpthPaLv01NOrHydUepNylWyn5bR8XeTaRW3QuUOwUcom2Wc7juU8PLY+eUEjZ3 AzqsQn1ud4KD1jQxQL29PwhpRzDUazDtepjXqcyy8fbVOkMuAmp9j/c X-Developer-Key: i=alchark@gmail.com; a=ed25519; pk=ltKbQzKLTJPiDgPtcHxdo+dzFthCCMtC3V9qf7+0rkc= Add a binding for the serial flash controller found on VIA/WonderMedia SoCs, which provides semi-transparent access to SPI NOR chips by mapping their contents to the physical CPU address space. Signed-off-by: Alexey Charkov --- .../devicetree/bindings/spi/via,vt8500-sflash.yaml | 122 +++++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 123 insertions(+) diff --git a/Documentation/devicetree/bindings/spi/via,vt8500-sflash.yaml b/Documentation/devicetree/bindings/spi/via,vt8500-sflash.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d2ea0dacdd56118c0cb5a1cb510ceb7591e1e5ca --- /dev/null +++ b/Documentation/devicetree/bindings/spi/via,vt8500-sflash.yaml @@ -0,0 +1,122 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/via,vt8500-sflash.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: VIA/WonderMedia serial flash controller + +description: + This controller is used on VIA/WonderMedia SoCs such as VIA VT8500, + WonderMedia WM8850 and similar. It provides a semi-transparent interface + for reading and writing SPI NOR chip contents via a physical memory map, + abstracting away all SPI communication, while also providing a direct + mechanism for issuing "programmable commands" to the underlying SPI chip + +maintainers: + - Alexey Charkov + +properties: + compatible: + enum: + - via,vt8500-sflash + - wm,wm8505-sflash + - wm,wm8650-sflash + - wm,wm8750-sflash + - wm,wm8850-sflash + + reg: + items: + - description: MMIO registers region of the controller + - description: + Physical memory region within which the controller will map the + flash contents of chip 0 for reading and writing. If the flash + size is smaller than this region, it will be mapped at its end. + Note that if this chip is used as the boot device (as is most + often the case), the boot ROM maps it at the very end of the + CPU address space (i.e. ending at 0xffffffff) + - description: + Physical memory region within which the controller will map the + flash contents of chip 1 for reading and writing. If the flash + size is smaller than this region, it will be mapped at its end + + reg-names: + items: + - const: io + - const: chip0-mmap + - const: chip1-mmap + + clocks: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +patternProperties: + "^flash@[0-1]$": + type: object + additionalProperties: true + + properties: + reg: + minimum: 0 + maximum: 1 + +required: + - compatible + - reg + - reg-names + - clocks + +unevaluatedProperties: false + +examples: + - | + sflash: spi-nor-controller@d8002000 { + compatible = "wm,wm8850-sflash"; + reg = <0xd8002000 0x400>, + <0xff800000 0x800000>, + <0xef800000 0x800000>; + reg-names = "io", "chip0-mmap", "chip1-mmap"; + clocks = <&clksf>; + #address-cells = <1>; + #size-cells = <0>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-boot"; + reg = <0 0x50000>; + read-only; + }; + + partition@1 { + label = "U-boot environment 1"; + reg = <0x50000 0x10000>; + }; + + partition@2 { + label = "U-boot environment 2"; + reg = <0x60000 0x10000>; + }; + + partition@3 { + label = "W-load"; + reg = <0x70000 0x10000>; + read-only; + }; + }; + }; + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index 6dbdf02d6b0c9357ad1da520a0f6c16b7f38f879..f09c457bbfc5ef71a3f8379c111bac52b767cbbc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3475,6 +3475,7 @@ F: Documentation/devicetree/bindings/hwinfo/via,vt8500-scc-id.yaml F: Documentation/devicetree/bindings/i2c/wm,wm8505-i2c.yaml F: Documentation/devicetree/bindings/interrupt-controller/via,vt8500-intc.yaml F: Documentation/devicetree/bindings/pwm/via,vt8500-pwm.yaml +F: Documentation/devicetree/bindings/spi/via,vt8500-sflash.yaml F: arch/arm/boot/dts/vt8500/ F: arch/arm/mach-vt8500/ F: drivers/clocksource/timer-vt8500.c From patchwork Sat May 10 19:42:22 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Charkov X-Patchwork-Id: 889115 Received: from mail-pg1-f178.google.com (mail-pg1-f178.google.com [209.85.215.178]) (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 EBCA426D4CA; Sat, 10 May 2025 19:43:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746906189; cv=none; b=rQ4Nu+Mm8mSrY5HwLanY84PCsCP0VxXomdwD91ZBqsWPBwKmuX6q6CNUWGAELgUrN3QFouZlqPgRPVdw2y16PwVk7E1Vy20LpbcMQWmolHRMKMMfnPKaFXOcd06zt0IZaU+ma3Qu9Xp4uMwrdjmO0IVbIu5/szGbV3s2BG2jj5Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746906189; c=relaxed/simple; bh=MVc+D8UeDXfnWqkaT4VNih6uJUURgP2ypi9Yz0FaNNQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=o0K3WpSoRZSPVfwfd7dm4bfXVDwmX8Ms4vKkUNcY7lw+Uu9zOZaYK1f2D0vOQN75cUG5eEVIZETmJV5cFcoFFQCJU+mUwOzQSMVwbQLnFdar4QNL2kfkxurfKOfzhnM4HRDQPpct/BiKvpwx0nmKToVx3eh9WJzqVgXgvMf1I0Y= 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=Z/XQHa4q; arc=none smtp.client-ip=209.85.215.178 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="Z/XQHa4q" Received: by mail-pg1-f178.google.com with SMTP id 41be03b00d2f7-af5085f7861so2196351a12.3; Sat, 10 May 2025 12:43:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1746906186; x=1747510986; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=hBGCGR+DudjR4q+SCafR4sOWrb5VFF5pYEvlVG+7oyY=; b=Z/XQHa4qbrFc036hLrQITmgLazjYCqGZ2XfkvR90Yl7OWydokCvAT3i45Nzu9JCyoM q9wmLaqrxN1X8IfMi1Z/H6qFBGkP/A8EdxcewCHX7qO9us+juqvT2ne/dqTCBXd4vNyP CdpEGPNxtSS2zeYVug9P8JFYZwlW3CjSbbeqlmi6G/YWXPtv+3MbXKm5c7E2N1KnDXaA B5TcVlpd3CysxKGSoHaVPbJ0DcHFRAhGQvEGnn8aQqMf5Mr3JqjoLL5xBK/acclorWG8 4U/IWQKt92g5UC2FKhkTMp2mezJQ/GS7kY6yfEghs+kLjWCg77YCBH17H7Q/7MLUxeQB gwSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1746906186; x=1747510986; 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=hBGCGR+DudjR4q+SCafR4sOWrb5VFF5pYEvlVG+7oyY=; b=SvgZzVULWTZZ+xYUPbCO/wEmQ/+ihlcXpco7UDIHIjN4yf9LgVUZ7GDeZmowroRLTc lIzFSPp4j4Zc3FUcCqkS4m0RptgvoX4qticM+vorwzGiykuH9x9Zwun1FT3keo/4vKMS +MDGRiblPs9dz8xutmK0oS5NE3dWvbSoPlW0drSzqj44lqpDkTfkEi0dJ/XvZvfR2smY /fWudtZdVIxYim50Mk+fDub2Pf5PzMiGtSe2y8YHl/Av+6ySAu/K/EW/2xweaIM7xTUQ 1Tva+qes/ezRYrkkZ84QKNFq2M4a1Rqjyj7dNvWllhmYLQW40bWJmrBObGJCwwT8MU75 GjQQ== X-Forwarded-Encrypted: i=1; AJvYcCVuLJAugOKJYd58ZmUeFyeQJXJ5Xf8hzEhrYOf6Q0UZlB4++gBEagXuvtFNvrdBcFhqwfv/HFQDxPeUYrRm@vger.kernel.org, AJvYcCX0Ce08/2Hr7lOVfIQuNjYF74kaQU4yxQ4Q8zTJDjtdZR3BI5fWA/nxpFHpGScXG/IF1OQfMorZvZNQ@vger.kernel.org X-Gm-Message-State: AOJu0YywQJat70SzOMvNSuRHVnkdccOEvJ45608+byqtUOw+CdWG3Wx4 XSWmcWzNBRpoLj8UXM4x2ottLT9vaQGnW5TLYf4FJ+bdN/SyaxVA X-Gm-Gg: ASbGncvno6s/MCo8Iz9KCIULMlaS8Ysar3VQ3e65BnfZuYisFP6Gqoip34fiOvnAZvi Ga9ZIBDL2wRcFjZXEaiX+8cgovCXMyxoZq5RWG3sNE25DImfHsC7TJa0421Hdc7+1V9M0caZfOT eyMhnFI+ve85f7kYZjYTQZ2f6Cl/LNQy78aEVtXKP4txC3DT/J9STF+cr82dn2KsA4rjW/2/cwP kQWVuoD9xrmeiNwQP0GozJRDH6zWs7M4Yo3+MCUbzTyPC32+Ej0bzX9pbwd6DThNexM1Lb5vwIq h2zLebiSDA/XNwjK6GhChLv8n/yYa+VJRPLi2eusFn2RJvMeUXeTpCHVKsBtAKghT4IeHHJ6MA= = X-Google-Smtp-Source: AGHT+IFzKOJYasnUn+55LfFZE9jK2KzyBx3+B3BN8g1tgWlMPEY7JLwdXCS0DbglTGKj9lXo91xUqw== X-Received: by 2002:a17:903:2351:b0:223:2cae:4a96 with SMTP id d9443c01a7336-22fc918c11emr108862695ad.42.1746906186030; Sat, 10 May 2025 12:43:06 -0700 (PDT) Received: from NB-GIGA003.letovo.school ([5.194.95.139]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b2523e67d53sm2223670a12.19.2025.05.10.12.42.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 10 May 2025 12:43:05 -0700 (PDT) From: Alexey Charkov Date: Sat, 10 May 2025 23:42:22 +0400 Subject: [PATCH 2/3] mtd: spi-nor: Add a driver for the VIA/WonderMedia serial flash controller Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250510-wmt-sflash-v1-2-02a1ac6adf12@gmail.com> References: <20250510-wmt-sflash-v1-0-02a1ac6adf12@gmail.com> In-Reply-To: <20250510-wmt-sflash-v1-0-02a1ac6adf12@gmail.com> To: Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Tudor Ambarus , Pratyush Yadav , Michael Walle , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Krzysztof Kozlowski Cc: linux-spi@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, Alexey Charkov X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1746906149; l=18425; i=alchark@gmail.com; s=20250416; h=from:subject:message-id; bh=MVc+D8UeDXfnWqkaT4VNih6uJUURgP2ypi9Yz0FaNNQ=; b=J3oAoN7HjFgJWUp6oIwA5GRzLKqmj1Ey7aBaqQmmbiQWIHo4LGQ1j7dsDLEdLrsI1q6obcOTK Zo5n9cFECFgAZu8iDEseuAHiPm/dN0g0GOjr21dpE2NGHiFblNNkK4f X-Developer-Key: i=alchark@gmail.com; a=ed25519; pk=ltKbQzKLTJPiDgPtcHxdo+dzFthCCMtC3V9qf7+0rkc= The controller is tailored to SPI NOR flash memory and abstracts away all SPI communications behind a small set of MMIO registers and a physical memory mapping of the actual chip contents. It doesn't expose chip probing functions beyond reading the ID though, so use lower level chip opcodes via the "programmable command mode" of the controller and the kernel's SPI NOR framework to avoid hard-coding chip parameters for each ID the way the vendor kernel does it. Currently tested on a WonderMedia WM8950 SoC with a Macronix MX25L4005A flash chip (APC Rock board), but should work on all VIA/WonderMedia SoCs Signed-off-by: Alexey Charkov --- MAINTAINERS | 1 + drivers/mtd/spi-nor/controllers/Kconfig | 14 + drivers/mtd/spi-nor/controllers/Makefile | 1 + drivers/mtd/spi-nor/controllers/wmt-sflash.c | 525 +++++++++++++++++++++++++++ 4 files changed, 541 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index f09c457bbfc5ef71a3f8379c111bac52b767cbbc..ff849c03a3b79a0487d3ab7e704ed11ffdb58f41 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3481,6 +3481,7 @@ F: arch/arm/mach-vt8500/ F: drivers/clocksource/timer-vt8500.c F: drivers/i2c/busses/i2c-viai2c-wmt.c F: drivers/mmc/host/wmt-sdmmc.c +F: drivers/mtd/spi-nor/controllers/wmt-sflash.c F: drivers/pwm/pwm-vt8500.c F: drivers/rtc/rtc-vt8500.c F: drivers/soc/vt8500/ diff --git a/drivers/mtd/spi-nor/controllers/Kconfig b/drivers/mtd/spi-nor/controllers/Kconfig index ca45dcd3ffe81f87dbf9ddc2a1535244ea92be20..aa8400b9aeaaec3b8b3f8996d501f5ac77a488ea 100644 --- a/drivers/mtd/spi-nor/controllers/Kconfig +++ b/drivers/mtd/spi-nor/controllers/Kconfig @@ -16,3 +16,17 @@ config SPI_NXP_SPIFI SPIFI is a specialized controller for connecting serial SPI Flash. Enable this option if you have a device with a SPIFI controller and want to access the Flash as a mtd device. + +config SPI_WMT_SFLASH + tristate "VIA/WonderMedia serial flash controller" + depends on ARCH_VT8500 || COMPILE_TEST + depends on OF + depends on HAS_IOMEM + help + Enable support for the VIA/WonderMedia serial flash controller. + + This is the specialized controller driving SPI NOR flash chips + inside VIA/WonderMedia SoCs. Most if not all VIA/WonderMedia + based devices use SPI NOR flash as their boot storage, so select + this if you need to access the primary or secondary bootloader + and their environment partitions. diff --git a/drivers/mtd/spi-nor/controllers/Makefile b/drivers/mtd/spi-nor/controllers/Makefile index 0b8e1d5309138619bbfdf3e27639b6be2935e65e..9c0365354a37986755f3c067ba2f1f5708fd20ad 100644 --- a/drivers/mtd/spi-nor/controllers/Makefile +++ b/drivers/mtd/spi-nor/controllers/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o +obj-$(CONFIG_SPI_WMT_SFLASH) += wmt-sflash.o diff --git a/drivers/mtd/spi-nor/controllers/wmt-sflash.c b/drivers/mtd/spi-nor/controllers/wmt-sflash.c new file mode 100644 index 0000000000000000000000000000000000000000..d63c3402345a9dac7e8a0591bb032481ad3b02f7 --- /dev/null +++ b/drivers/mtd/spi-nor/controllers/wmt-sflash.c @@ -0,0 +1,525 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * VIA/WonderMedia SPI NOR flash controller driver + * + * Copyright (c) 2025 Alexey Charkov + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SF_CHIP_SEL_0_CFG 0x000 /* chip select 0 config */ +#define SF_CHIP_SEL_1_CFG 0x008 /* chip select 0 config */ +#define SF_CHIP_SEL_CFG(x) (8 * (x)) +#define SF_CHIP_SEL_ADDR GENMASK(31, 16) /* 64kb aligned address */ +#define SF_CHIP_SEL_SIZE GENMASK(11, 8) /* log2(size/32kb) */ + +#define SF_SPI_INTF_CFG 0x040 /* SPI interface config */ +#define SF_ADDR_WIDTH_32 BIT(0) /* 0: 24 bit, 1: 32 bit addr */ +#define SF_USR_RD_CMD_MOD BIT(4) /* 0: normal, 1: user cmd read */ +#define SF_USR_WR_CMD_MOD BIT(5) /* 0: normal, 1: user cmd write */ +#define SF_PROG_CMD_MOD BIT(6) /* 0: normal, 1: prog cmd */ +#define SF_CS_DELAY GENMASK(18, 16) /* chip select delay */ +#define SF_RES_DELAY GENMASK(27, 24) /* reset delay */ +#define SF_PDWN_DELAY GENMASK(31, 28) /* power down delay */ + +#define SF_SPI_RD_WR_CTR 0x050 /* read/write control */ +#define SF_RD_FAST BIT(0) /* 0: normal read, 1: fast read */ +#define SF_RD_ID BIT(4) /* 0: read status, 1: read ID */ + +#define SF_SPI_WR_EN_CTR 0x060 /* write enable control */ +#define SF_CS0_WR_EN BIT(0) +#define SF_CS1_WR_EN BIT(1) +#define SF_CS_WR_EN(x) BIT(x) + +#define SF_SPI_ER_CTR 0x070 /* erase control */ +#define SF_CHIP_ERASE BIT(0) /* full chip erase */ +#define SF_SEC_ERASE BIT(15) /* sector erase */ + +#define SF_SPI_ER_START_ADDR 0x074 /* erase start address */ +#define SF_CHIP_ER_CS0 BIT(0) /* erase chip 0 */ +#define SF_CHIP_ER_CS1 BIT(1) /* erase chip 1 */ +#define SF_CHIP_ER_CS(x) BIT(x) +#define SF_ER_START_ADDR GENMASK(31, 16) + +#define SF_SPI_ERROR_STATUS 0x080 +#define SF_MASLOCK_ERR BIT(0) /* master lock */ +#define SF_PCMD_ACC_ERR BIT(1) /* programmable cmd access */ +#define SF_PCMD_OP_ERR BIT(2) /* programmable cmd opcode */ +#define SF_PWR_DWN_ACC_ERR BIT(3) /* power down access */ +#define SF_MEM_REGION_ERR BIT(4) /* memory region */ +#define SF_WR_PROT_ERR BIT(5) /* write protection */ +#define SF_SPI_ERROR_CLEARALL (SF_MASLOCK_ERR | \ + SF_PCMD_ACC_ERR | \ + SF_PCMD_OP_ERR | \ + SF_PWR_DWN_ACC_ERR | \ + SF_MEM_REGION_ERR | \ + SF_WR_PROT_ERR) + +#define SF_SPI_MEM_0_SR_ACC 0x100 /* status read from chip 0 */ +#define SF_SPI_MEM_1_SR_ACC 0x110 /* status read from chip 1 */ +#define SF_SPI_MEM_SR_ACC(x) (0x100 + 0x10 * (x)) + +#define SF_SPI_PDWN_CTR_0 0x180 /* power down chip 0 */ +#define SF_SPI_PDWN_CTR_1 0x190 /* power down chip 1 */ +#define SF_SPI_PDWN_CTR_(x) (0x180 + 0x10 * (x)) +#define SF_PWR_DOWN BIT(0) + +#define SF_SPI_PROG_CMD_CTR 0x200 /* programmable cmd control */ +#define SF_PROG_CMD_EN BIT(0) /* enable programmable cmd */ +#define SF_PROG_CMD_CS GENMASK(1, 1) /* chip select for cmd */ +#define SF_RX_DATA_SIZE GENMASK(22, 16) /* receive data size */ +#define SF_TX_DATA_SIZE GENMASK(30, 24) /* transmit data size */ + +#define SF_SPI_USER_CMD_VAL 0x210 +#define SF_USR_RD_CMD GENMASK(7, 0) /* user read command */ +#define SF_USR_WR_CMD GENMASK(23, 16) /* user write command */ + +#define SF_SPI_PROG_CMD_WBF 0x300 /* 64 bytes pcmd write buffer */ +#define SF_SPI_PROG_CMD_RBF 0x380 /* 64 bytes pcmd read buffer */ + +#define SF_WAIT_TIMEOUT 1000000 + +struct wmt_sflash_priv { + size_t cs; + struct wmt_sflash_host *host; + void __iomem *mmap_base; + resource_size_t mmap_phys; +}; + +#define SF_MAX_CHIP_NUM 2 +struct wmt_sflash_host { + struct device *dev; + struct clk *clk; + + void __iomem *regbase; + struct resource *mmap_res[SF_MAX_CHIP_NUM]; + + struct spi_nor *nor[SF_MAX_CHIP_NUM]; + size_t num_chips; +}; + +static int wmt_sflash_prep(struct spi_nor *nor) +{ + struct wmt_sflash_priv *priv = nor->priv; + struct wmt_sflash_host *host = priv->host; + + return clk_prepare_enable(host->clk); +} + +static void wmt_sflash_unprep(struct spi_nor *nor) +{ + struct wmt_sflash_priv *priv = nor->priv; + struct wmt_sflash_host *host = priv->host; + + clk_disable_unprepare(host->clk); +} + +static void wmt_sflash_pcmd_mode(struct wmt_sflash_host *host, bool enable) +{ + u32 reg = readl(host->regbase + SF_SPI_INTF_CFG); + + reg &= ~SF_PROG_CMD_MOD; + reg |= FIELD_PREP(SF_PROG_CMD_MOD, enable); + writel(reg, host->regbase + SF_SPI_INTF_CFG); +} + +static inline int wmt_sflash_wait_pcmd(struct wmt_sflash_host *host) +{ + u32 reg; + + return readl_poll_timeout(host->regbase + SF_SPI_PROG_CMD_CTR, reg, + !(reg & SF_PROG_CMD_EN), 1, SF_WAIT_TIMEOUT); +} + +static int wmt_sflash_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, + size_t len) +{ + struct wmt_sflash_priv *priv = nor->priv; + struct wmt_sflash_host *host = priv->host; + int ret; + u32 reg; + + if (len > 64) { + dev_err(host->dev, + "Cannot read %d bytes from registers\n", len); + return -EINVAL; + } + + wmt_sflash_pcmd_mode(host, true); + writeb(opcode, host->regbase + SF_SPI_PROG_CMD_WBF); + + reg = SF_PROG_CMD_EN | + FIELD_PREP(SF_PROG_CMD_CS, priv->cs) | + FIELD_PREP(SF_TX_DATA_SIZE, 1) | + FIELD_PREP(SF_RX_DATA_SIZE, len); + writel(reg, host->regbase + SF_SPI_PROG_CMD_CTR); + + ret = wmt_sflash_wait_pcmd(host); + + if (len) + memcpy_fromio(buf, host->regbase + SF_SPI_PROG_CMD_RBF, len); + + wmt_sflash_pcmd_mode(host, false); + + return ret; +} + +static int wmt_sflash_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf, + size_t len) +{ + struct wmt_sflash_priv *priv = nor->priv; + struct wmt_sflash_host *host = priv->host; + int ret; + u32 reg; + + if (len > 63) { + dev_err(host->dev, + "Cannot write %d bytes to registers\n", len); + return -EINVAL; + } + + wmt_sflash_pcmd_mode(host, true); + writeb(opcode, host->regbase + SF_SPI_PROG_CMD_WBF); + + if (len) + memcpy_toio(host->regbase + SF_SPI_PROG_CMD_WBF + 1, buf, len); + + reg = SF_PROG_CMD_EN | + FIELD_PREP(SF_PROG_CMD_CS, priv->cs) | + FIELD_PREP(SF_TX_DATA_SIZE, len + 1); + writel(reg, host->regbase + SF_SPI_PROG_CMD_CTR); + + ret = wmt_sflash_wait_pcmd(host); + wmt_sflash_pcmd_mode(host, false); + + return ret; +} + +static int wmt_sflash_wait_spi(struct wmt_sflash_priv *priv) +{ + struct wmt_sflash_host *host = priv->host; + int timeout = SF_WAIT_TIMEOUT; + u32 error; + + while (timeout--) { + if (!(readl(host->regbase + + SF_SPI_MEM_SR_ACC(priv->cs)) & 1)) + return 0; + + error = readl(host->regbase + SF_SPI_ERROR_STATUS); + if (error & SF_MASLOCK_ERR) { + dev_err(host->dev, + "Master lock error\n"); + goto err; + } + if (error & SF_PCMD_ACC_ERR) { + dev_err(host->dev, + "Programmable command access error\n"); + goto err; + } + if (error & SF_PCMD_OP_ERR) { + dev_err(host->dev, + "Programmable command opcode error\n"); + goto err; + } + if (error & SF_PWR_DWN_ACC_ERR) { + dev_err(host->dev, + "Power down access error\n"); + goto err; + } + if (error & SF_MEM_REGION_ERR) { + dev_err(host->dev, + "Memory region error\n"); + goto err; + } + if (error & SF_WR_PROT_ERR) { + dev_err(host->dev, + "Write protection error\n"); + goto err; + } + } + return 0; + +err: + writel(SF_SPI_ERROR_CLEARALL, host->regbase + SF_SPI_ERROR_STATUS); + return -EBUSY; +} + +static ssize_t wmt_sflash_read(struct spi_nor *nor, loff_t from, size_t len, + u_char *read_buf) +{ + struct wmt_sflash_priv *priv = nor->priv; + struct wmt_sflash_host *host = priv->host; + u32 reg = nor->read_opcode == SPINOR_OP_READ_FAST ? SF_RD_FAST : 0; + + writel(reg, host->regbase + SF_SPI_RD_WR_CTR); + + if (wmt_sflash_wait_spi(priv)) + return 0; + + memcpy_fromio(read_buf, priv->mmap_base + from, len); + return len; +} + +static ssize_t wmt_sflash_write(struct spi_nor *nor, loff_t to, size_t len, + const u_char *write_buf) +{ + struct wmt_sflash_priv *priv = nor->priv; + struct wmt_sflash_host *host = priv->host; + size_t burst, offset = 0; + + writel(SF_CS_WR_EN(priv->cs), + host->regbase + SF_SPI_WR_EN_CTR); + + while (offset < len) { + /* select 8 / 4 / 2 / 1 byte write length */ + burst = 1 << min(3, ilog2(len - offset)); + memcpy_toio(priv->mmap_base + to + offset, + write_buf + offset, burst); + + if (wmt_sflash_wait_spi(priv)) + return offset; + + offset += burst; + } + + writel(0, host->regbase + SF_SPI_WR_EN_CTR); + + return offset; +} + +static int wmt_sflash_erase(struct spi_nor *nor, loff_t offs) +{ + struct wmt_sflash_priv *priv = nor->priv; + struct wmt_sflash_host *host = priv->host; + int ret = 0; + u32 reg; + + if (offs & (SZ_64K - 1)) { + dev_err(host->dev, + "Erase offset 0x%llx not on 64k boundary\n", offs); + return -EINVAL; + } + + writel(SF_CS_WR_EN(priv->cs), + host->regbase + SF_SPI_WR_EN_CTR); + + reg = SF_CHIP_ER_CS(priv->cs) | + FIELD_PREP(SF_ER_START_ADDR, (priv->mmap_phys + offs) >> 16); + writel(reg, host->regbase + SF_SPI_ER_START_ADDR); + + writel(SF_SEC_ERASE, host->regbase + SF_SPI_ER_CTR); + + ret = wmt_sflash_wait_spi(priv); + writel(0, host->regbase + SF_SPI_WR_EN_CTR); + + return ret; +} + +static const struct spi_nor_controller_ops wmt_sflash_controller_ops = { + .prepare = wmt_sflash_prep, + .unprepare = wmt_sflash_unprep, + .read_reg = wmt_sflash_read_reg, + .write_reg = wmt_sflash_write_reg, + .read = wmt_sflash_read, + .write = wmt_sflash_write, + .erase = wmt_sflash_erase, +}; + +static int wmt_sflash_register(struct device_node *np, + struct wmt_sflash_host *host) +{ + const struct spi_nor_hwcaps hwcaps = { + .mask = SNOR_HWCAPS_READ | + SNOR_HWCAPS_READ_FAST | + SNOR_HWCAPS_PP, + }; + struct device *dev = host->dev; + struct wmt_sflash_priv *priv; + struct mtd_info *mtd; + struct spi_nor *nor; + int ret; + u32 reg; + + nor = devm_kzalloc(dev, sizeof(*nor), GFP_KERNEL); + if (!nor) + return -ENOMEM; + + nor->dev = dev; + spi_nor_set_flash_node(nor, np); + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + ret = of_property_read_u32(np, "reg", &priv->cs); + if (ret) + return dev_err_probe(dev, ret, + "There's no reg property for %pOF\n", + np); + + if (priv->cs >= SF_MAX_CHIP_NUM) + return dev_err_probe(dev, -ENXIO, + "Chip select %d is out of bounds\n", + priv->cs); + + priv->host = host; + nor->priv = priv; + nor->controller_ops = &wmt_sflash_controller_ops; + + ret = spi_nor_scan(nor, NULL, &hwcaps); + if (ret) + return dev_err_probe(dev, ret, + "Failed to scan SPI NOR chip\n"); + + mtd = &nor->mtd; + mtd->name = np->name; + + priv->mmap_phys = host->mmap_res[priv->cs]->end - mtd->size + 1; + priv->mmap_phys &= -SZ_64K; + + priv->mmap_base = devm_ioremap(dev, priv->mmap_phys, mtd->size); + if (IS_ERR(priv->mmap_base)) + return dev_err_probe(dev, PTR_ERR(priv->mmap_base), + "Failed to map chip %d at address 0x%x size 0x%llx\n", + priv->cs, priv->mmap_phys, mtd->size); + + reg = FIELD_PREP(SF_CHIP_SEL_ADDR, priv->mmap_phys >> 16) | + FIELD_PREP(SF_CHIP_SEL_SIZE, order_base_2(mtd->size) - 15); + writel(reg, host->regbase + SF_CHIP_SEL_CFG(priv->cs)); + + reg = FIELD_PREP(SF_CS_DELAY, 3); + writel(reg, host->regbase + SF_SPI_INTF_CFG); + + /* the controller only handles 64k aligned addresses */ + mtd->erasesize = max(mtd->erasesize, SZ_64K); + + ret = mtd_device_register(mtd, NULL, 0); + if (ret) + return dev_err_probe(dev, ret, + "Failed to register MTD device\n"); + + host->nor[host->num_chips] = nor; + host->num_chips++; + return 0; +} + +static void wmt_sflash_unregister_all(struct wmt_sflash_host *host) +{ + int i; + + for (i = 0; i < host->num_chips; i++) + mtd_device_unregister(&host->nor[i]->mtd); +} + +static int wmt_sflash_register_all(struct wmt_sflash_host *host) +{ + struct device *dev = host->dev; + struct device_node *np; + int ret; + + for_each_available_child_of_node(dev->of_node, np) { + ret = wmt_sflash_register(np, host); + if (ret) { + of_node_put(np); + goto fail; + } + + if (host->num_chips == SF_MAX_CHIP_NUM) { + dev_warn(dev, "Flash count exceeds the maximum chipselect number\n"); + of_node_put(np); + break; + } + } + return 0; + +fail: + wmt_sflash_unregister_all(host); + return ret; +} + +static int wmt_sflash_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct wmt_sflash_host *host; + char mmap_str[32]; + int ret, i; + + host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); + if (!host) + return dev_err_probe(dev, -ENOMEM, + "Failed to allocate controller private data\n"); + + platform_set_drvdata(pdev, host); + host->dev = dev; + + host->regbase = devm_platform_ioremap_resource_byname(pdev, "io"); + if (IS_ERR(host->regbase)) + return dev_err_probe(dev, PTR_ERR(host->regbase), + "Failed to remap controller MMIO registers\n"); + + for (i = 0; i < SF_MAX_CHIP_NUM; i++) { + snprintf(mmap_str, sizeof(mmap_str), "chip%d-mmap", i); + + host->mmap_res[i] = platform_get_resource_byname(pdev, + IORESOURCE_MEM, mmap_str); + if (!host->mmap_res[i]) + return dev_err_probe(dev, -ENXIO, + "Memory map region not found for chip %d\n", + i); + } + + host->clk = devm_clk_get(dev, NULL); + if (IS_ERR(host->clk)) + return dev_err_probe(dev, PTR_ERR(host->clk), + "Failed to get clock\n"); + + ret = clk_prepare_enable(host->clk); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable clock\n"); + + ret = wmt_sflash_register_all(host); + + clk_disable_unprepare(host->clk); + return ret; +} + +static void wmt_sflash_remove(struct platform_device *pdev) +{ + struct wmt_sflash_host *host = platform_get_drvdata(pdev); + + wmt_sflash_unregister_all(host); +} + +static const struct of_device_id wmt_sflash_dt_ids[] = { + { .compatible = "via,vt8500-sflash"}, + { .compatible = "wm,wm8505-sflash"}, + { .compatible = "wm,wm8650-sflash"}, + { .compatible = "wm,wm8750-sflash"}, + { .compatible = "wm,wm8850-sflash"}, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, wmt_sflash_dt_ids); + +static struct platform_driver wmt_sflash_driver = { + .driver = { + .name = "wmt-sflash", + .of_match_table = wmt_sflash_dt_ids, + }, + .probe = wmt_sflash_probe, + .remove = wmt_sflash_remove, +}; +module_platform_driver(wmt_sflash_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("VIA/WonderMedia SPI NOR flash controller driver"); From patchwork Sat May 10 19:42:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Charkov X-Patchwork-Id: 889313 Received: from mail-pf1-f181.google.com (mail-pf1-f181.google.com [209.85.210.181]) (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 7E77F27603B; Sat, 10 May 2025 19:43:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746906201; cv=none; b=UlqX76vujFoNTpDbTjN69Gheb1JSU2mut5HFVzPIbzuDDhm5d92EisTaUfKIjiUjE1pwun0qnjV2DcwCh1yyv12rG+KBnRFQM0SaMJDG823nZN3KY0kP41nIX5B6cfsFK1Qwb/XUdgnRxsqhLd+7iw2iNJyj9hsXkXJeE3PEUZA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746906201; c=relaxed/simple; bh=AqqaMB30uWeNBPi6eapQMsRaWN5WUqUZI3tfXltWrtU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FN7H/2ZcI+gJ6LpVLLr6Bs6jFGAx/xlscGAcERsdmEc4P82DSaFjDpB/6/0CafGf1a8xvKWKOme77YUnUrxRPPu3ssCexIWXYSqKT98q4st2mPo3VAQF2G5ARLwZikb7PIN81OUSRf8g2QJ80tNZ3Srb+DdM9wOv9wKzK26ePoo= 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=KYDPvW8d; arc=none smtp.client-ip=209.85.210.181 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="KYDPvW8d" Received: by mail-pf1-f181.google.com with SMTP id d2e1a72fcca58-7424ccbef4eso724070b3a.2; Sat, 10 May 2025 12:43:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1746906198; x=1747510998; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=SRddgwOHN1Vyi2V2faPWngR/Eu23tCZlOEXW/jSpDeM=; b=KYDPvW8dHCCnjT2x4U66zgGTc2ydNmAZPkmYnymaOldOyViGgBRgemyPMjVKOTC65P imq0E4DhwTh/rO5q5ZrvjwrKwRhdzLiKKZb4IDjgDb+An6WLQNijxbNDviMCHItlWCNj Mn2ZYS13R6QhlWv2LgpE03g0TH6uuLxeJLzn/vRYKyViixjVAAK7igPPi74orbnRCFnz YSoJkRePmLROVs+m02o9AzDDxk8BXiALE2T1VhPOWGynco56E3PTPVJu8f9enHgeupt5 BsgNevLpk+qJffQFMy7xor/I/ieShd1578ftx3UqnrvZCkpdku06/LJd+78SRwV8FDx0 xfjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1746906198; x=1747510998; 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=SRddgwOHN1Vyi2V2faPWngR/Eu23tCZlOEXW/jSpDeM=; b=VOf3vxPXjg+l9GKhv1a48vz3NKTeFY4tZCbZgFWAX6CIDZ64S2U8DarKZb8YphduGs 7EJ0jcaf/BT5OaBcxbtPVxPctgrcpz7FUetH1qkMxoj9HtA2DBtHW8Pq/lzRgu8JU6QJ pMPxeyWsM5a2pLCJqbTNRF6nKWbOG15HLCvpWx/8sKsHmwuhV1aGme8VDz8UR0jAZjc4 fNi9xVlFYtGFFRex+pj4kfbdkDH8/5RESGyNQAa+rMNmdLj/q/9oRwIlzewibryzemh6 zckC1mVhpe3rW6d05a8pX98Dz2DDmRV7+F5GFVVNNEn1wKYkCGJeF9bSoVcUEfIeMaLE jWhg== X-Forwarded-Encrypted: i=1; AJvYcCWH/2JKkigPbmjs3bCpbIsy7MJ7TC3lXvnU5leSue+UVSzLq0aq8vVYER5LZh9U2s7FV4xbvUeDXLpL@vger.kernel.org, AJvYcCWScKZ763j0laDeUE1R2YLTLHIZOB3zBtthJX91KhNxVCvOQu8HmDzKqOcNzhQKRV41wbiuwMGtVZK67XwO@vger.kernel.org X-Gm-Message-State: AOJu0YzcvjSJyO1zWAjGQ2LzrRsHw2lwwBqt9nILB4B8ekVqT7baei98 YvgwPqQt4Qe4iIEQh29Nc78cpBa5Y+I+hi0mOeLCibkhxo9Jngi6 X-Gm-Gg: ASbGncup83+NoQ1YTqwcfUr/Msl0IOYkFniuMh29hylpzH1itFEkmGlTkKEn5n1p/P3 M/EOS9NdYPEZ65Z/CPhQJwADw6IAaSqRTQm4iVkTW8M1z+kf28sZwVPqleh83gTD3yaGS1D0k2a okjickdJRE0gq8hUh2jqT+FG/Tn4LsNArOQ2AnABRnzxPs3p4NOE95nMM+paIo+Xj2V8LhIImmx liBY+io3f5Ea+amlPVPNrChhac0NEMzSfj7HSDV+kqXeJA8GT62TEZW3Taqnu3E+ls8dX9WLhmi szDjOhfkby/RU1AFfGmV72Uw50h55eLBc6McTTeNAzEMMwQpHqeHs5GYdFhQDwg= X-Google-Smtp-Source: AGHT+IH053WbjA3cvqj9iQ8a7h5v+mWrap4AkYe2w2/EzsXrjAunLV+dXYcLOr/NytKnX5MMq0uq+Q== X-Received: by 2002:a05:6a20:e68d:b0:1ee:8435:6b69 with SMTP id adf61e73a8af0-215ababcab7mr11814578637.1.1746906198481; Sat, 10 May 2025 12:43:18 -0700 (PDT) Received: from NB-GIGA003.letovo.school ([5.194.95.139]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b2523e67d53sm2223670a12.19.2025.05.10.12.43.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 10 May 2025 12:43:18 -0700 (PDT) From: Alexey Charkov Date: Sat, 10 May 2025 23:42:23 +0400 Subject: [PATCH 3/3] ARM: dts: vt8500: Add serial flash controller and its clock Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250510-wmt-sflash-v1-3-02a1ac6adf12@gmail.com> References: <20250510-wmt-sflash-v1-0-02a1ac6adf12@gmail.com> In-Reply-To: <20250510-wmt-sflash-v1-0-02a1ac6adf12@gmail.com> To: Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Tudor Ambarus , Pratyush Yadav , Michael Walle , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Krzysztof Kozlowski Cc: linux-spi@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, Alexey Charkov X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1746906149; l=13606; i=alchark@gmail.com; s=20250416; h=from:subject:message-id; bh=AqqaMB30uWeNBPi6eapQMsRaWN5WUqUZI3tfXltWrtU=; b=9HbS2d3KP67QxcLBqUs+Dm8Msny0saXPEgDQmen+dSuDYtQ20sj7w1/xe9rRlJJ9Pq67aMgon FcjxhBj1ydjDOsdRKTsBdSXp5hOVWTQJQ+SRtcLotX7oLt+TcTEnOcn X-Developer-Key: i=alchark@gmail.com; a=ed25519; pk=ltKbQzKLTJPiDgPtcHxdo+dzFthCCMtC3V9qf7+0rkc= The serial flash controller resides at the same MMIO address in all known VIA/WonderMedia SoCs, and its clock uses the same enable bit and divisor reg on all SoCs, feeding off PLL B. Add respective DT nodes using SoC specific compatibles for the controller to make it future proof in case any differences in behavior are discovered later on. All known boards boot from SPI NOR flash, so their flash chips are at CS0 and mapped by the boot ROM at the end of their CPU address space. Add respective DT nodes in board-specific dts files too. Signed-off-by: Alexey Charkov --- arch/arm/boot/dts/vt8500/vt8500-bv07.dts | 37 ++++++++++++++++++++++++++++ arch/arm/boot/dts/vt8500/vt8500.dtsi | 34 +++++++++++++++++++++++++ arch/arm/boot/dts/vt8500/wm8505-ref.dts | 37 ++++++++++++++++++++++++++++ arch/arm/boot/dts/vt8500/wm8505.dtsi | 21 ++++++++++++++++ arch/arm/boot/dts/vt8500/wm8650-mid.dts | 37 ++++++++++++++++++++++++++++ arch/arm/boot/dts/vt8500/wm8650.dtsi | 21 ++++++++++++++++ arch/arm/boot/dts/vt8500/wm8750-apc8750.dts | 37 ++++++++++++++++++++++++++++ arch/arm/boot/dts/vt8500/wm8750.dtsi | 21 ++++++++++++++++ arch/arm/boot/dts/vt8500/wm8850-w70v2.dts | 37 ++++++++++++++++++++++++++++ arch/arm/boot/dts/vt8500/wm8850.dtsi | 21 ++++++++++++++++ arch/arm/boot/dts/vt8500/wm8950-apc-rock.dts | 37 ++++++++++++++++++++++++++++ 11 files changed, 340 insertions(+) diff --git a/arch/arm/boot/dts/vt8500/vt8500-bv07.dts b/arch/arm/boot/dts/vt8500/vt8500-bv07.dts index 38a2da5e2c5d64477f04e1da9d98cb97be0d95e4..c3c5ba3ac014cc49bee8c2b9e6c7b25225d4d5fe 100644 --- a/arch/arm/boot/dts/vt8500/vt8500-bv07.dts +++ b/arch/arm/boot/dts/vt8500/vt8500-bv07.dts @@ -30,6 +30,43 @@ timing0: timing-800x480 { }; }; +&sflash { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-boot"; + reg = <0 0x50000>; + read-only; + }; + + partition@1 { + label = "U-boot environment 1"; + reg = <0x50000 0x10000>; + }; + + partition@2 { + label = "U-boot environment 2"; + reg = <0x60000 0x10000>; + }; + + partition@3 { + label = "W-load"; + reg = <0x70000 0x10000>; + read-only; + }; + }; + }; +}; + &uart0 { status = "okay"; }; diff --git a/arch/arm/boot/dts/vt8500/vt8500.dtsi b/arch/arm/boot/dts/vt8500/vt8500.dtsi index 2ba021585d4889f29777a12473964c29f999f3a0..7ea115576c69b517cb2a08206638062f22c976a0 100644 --- a/arch/arm/boot/dts/vt8500/vt8500.dtsi +++ b/arch/arm/boot/dts/vt8500/vt8500.dtsi @@ -74,6 +74,19 @@ ref24: ref24M { clock-frequency = <24000000>; }; + ref25: clock-25000000 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <25000000>; + }; + + pllb: clock@204 { + #clock-cells = <0>; + compatible = "via,vt8500-pll-clock"; + clocks = <&ref25>; + reg = <0x204>; + }; + clkuart0: uart0 { #clock-cells = <0>; compatible = "via,vt8500-device-clock"; @@ -105,6 +118,15 @@ clkuart3: uart3 { enable-reg = <0x250>; enable-bit = <4>; }; + + clksf: clock { + #clock-cells = <0>; + compatible = "via,vt8500-device-clock"; + clocks = <&pllb>; + divisor-reg = <0x314>; + enable-reg = <0x254>; + enable-bit = <23>; + }; }; }; @@ -114,6 +136,18 @@ timer@d8130100 { interrupts = <36>; }; + sflash: spi-nor-controller@d8002000 { + compatible = "via,vt8500-sflash"; + reg = <0xd8002000 0x400>, + <0xff800000 0x800000>, + <0xef800000 0x800000>; + reg-names = "io", "chip0-mmap", "chip1-mmap"; + clocks = <&clksf>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + usb@d8007900 { compatible = "via,vt8500-ehci"; reg = <0xd8007900 0x200>; diff --git a/arch/arm/boot/dts/vt8500/wm8505-ref.dts b/arch/arm/boot/dts/vt8500/wm8505-ref.dts index 8ce9e2ef0a81097e7143a5392ee5b42bf8028ec1..b037f9d919fb51a527f35276e2b8601f3f3d8505 100644 --- a/arch/arm/boot/dts/vt8500/wm8505-ref.dts +++ b/arch/arm/boot/dts/vt8500/wm8505-ref.dts @@ -30,6 +30,43 @@ timing0: timing-800x480 { }; }; +&sflash { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-boot"; + reg = <0 0x50000>; + read-only; + }; + + partition@1 { + label = "U-boot environment 1"; + reg = <0x50000 0x10000>; + }; + + partition@2 { + label = "U-boot environment 2"; + reg = <0x60000 0x10000>; + }; + + partition@3 { + label = "W-load"; + reg = <0x70000 0x10000>; + read-only; + }; + }; + }; +}; + &uart0 { status = "okay"; }; diff --git a/arch/arm/boot/dts/vt8500/wm8505.dtsi b/arch/arm/boot/dts/vt8500/wm8505.dtsi index 99c064c916b2279797f71261ca9306e9dcd4bbd8..bf9ba4e99f86d1bf41c4e4bfe8b4f71ad162be4f 100644 --- a/arch/arm/boot/dts/vt8500/wm8505.dtsi +++ b/arch/arm/boot/dts/vt8500/wm8505.dtsi @@ -203,6 +203,15 @@ clksdhc: sdhc { enable-reg = <0x254>; enable-bit = <18>; }; + + clksf: clock { + #clock-cells = <0>; + compatible = "via,vt8500-device-clock"; + clocks = <&pllb>; + divisor-reg = <0x314>; + enable-reg = <0x254>; + enable-bit = <23>; + }; }; }; @@ -212,6 +221,18 @@ timer@d8130100 { interrupts = <36>; }; + sflash: spi-nor-controller@d8002000 { + compatible = "wm,wm8505-sflash"; + reg = <0xd8002000 0x400>, + <0xff800000 0x800000>, + <0xef800000 0x800000>; + reg-names = "io", "chip0-mmap", "chip1-mmap"; + clocks = <&clksf>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + usb@d8007100 { compatible = "via,vt8500-ehci"; reg = <0xd8007100 0x200>; diff --git a/arch/arm/boot/dts/vt8500/wm8650-mid.dts b/arch/arm/boot/dts/vt8500/wm8650-mid.dts index 7977b6c1e8ebf215df210dee703e470b9159d329..d3c8b7b99706603bab5aa8dad1165edb3763c2f6 100644 --- a/arch/arm/boot/dts/vt8500/wm8650-mid.dts +++ b/arch/arm/boot/dts/vt8500/wm8650-mid.dts @@ -31,6 +31,43 @@ timing0: timing-800x480 { }; }; +&sflash { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-boot"; + reg = <0 0x50000>; + read-only; + }; + + partition@1 { + label = "U-boot environment 1"; + reg = <0x50000 0x10000>; + }; + + partition@2 { + label = "U-boot environment 2"; + reg = <0x60000 0x10000>; + }; + + partition@3 { + label = "W-load"; + reg = <0x70000 0x10000>; + read-only; + }; + }; + }; +}; + &uart0 { status = "okay"; }; diff --git a/arch/arm/boot/dts/vt8500/wm8650.dtsi b/arch/arm/boot/dts/vt8500/wm8650.dtsi index 0d6c7bd87f7dcce0eef056d04c38ab1de5d52639..972b61d2437b1da9ce765b65f844872e8df4da1d 100644 --- a/arch/arm/boot/dts/vt8500/wm8650.dtsi +++ b/arch/arm/boot/dts/vt8500/wm8650.dtsi @@ -175,6 +175,15 @@ clksdhc: sdhc { enable-reg = <0x254>; enable-bit = <18>; }; + + clksf: clock { + #clock-cells = <0>; + compatible = "via,vt8500-device-clock"; + clocks = <&pllb>; + divisor-reg = <0x314>; + enable-reg = <0x254>; + enable-bit = <23>; + }; }; }; @@ -184,6 +193,18 @@ timer@d8130100 { interrupts = <36>; }; + sflash: spi-nor-controller@d8002000 { + compatible = "wm,wm8650-sflash"; + reg = <0xd8002000 0x400>, + <0xff800000 0x800000>, + <0xef800000 0x800000>; + reg-names = "io", "chip0-mmap", "chip1-mmap"; + clocks = <&clksf>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + usb@d8007900 { compatible = "via,vt8500-ehci"; reg = <0xd8007900 0x200>; diff --git a/arch/arm/boot/dts/vt8500/wm8750-apc8750.dts b/arch/arm/boot/dts/vt8500/wm8750-apc8750.dts index 136e812bc1e498d48c7fc61154bc66a48888b117..4465946cfe44e82db1cad14c1f81237e1ccc0e67 100644 --- a/arch/arm/boot/dts/vt8500/wm8750-apc8750.dts +++ b/arch/arm/boot/dts/vt8500/wm8750-apc8750.dts @@ -24,6 +24,43 @@ i2c: i2c { }; }; +&sflash { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-boot"; + reg = <0 0x50000>; + read-only; + }; + + partition@1 { + label = "U-boot environment 1"; + reg = <0x50000 0x10000>; + }; + + partition@2 { + label = "U-boot environment 2"; + reg = <0x60000 0x10000>; + }; + + partition@3 { + label = "W-load"; + reg = <0x70000 0x10000>; + read-only; + }; + }; + }; +}; + &uart0 { status = "okay"; }; diff --git a/arch/arm/boot/dts/vt8500/wm8750.dtsi b/arch/arm/boot/dts/vt8500/wm8750.dtsi index 0158c0ba5dd110957eac38775d3bf3ebd2ab4154..d6b4e4463fae1e8a0a3cf0feecce7125b4a67f5c 100644 --- a/arch/arm/boot/dts/vt8500/wm8750.dtsi +++ b/arch/arm/boot/dts/vt8500/wm8750.dtsi @@ -240,6 +240,15 @@ clki2c1: i2c1clk { enable-reg = <0x250>; enable-bit = <9>; }; + + clksf: clock { + #clock-cells = <0>; + compatible = "via,vt8500-device-clock"; + clocks = <&pllb>; + divisor-reg = <0x314>; + enable-reg = <0x254>; + enable-bit = <23>; + }; }; }; @@ -256,6 +265,18 @@ timer@d8130100 { interrupts = <36>; }; + sflash: spi-nor-controller@d8002000 { + compatible = "wm,wm8750-sflash"; + reg = <0xd8002000 0x400>, + <0xff800000 0x800000>, + <0xef800000 0x800000>; + reg-names = "io", "chip0-mmap", "chip1-mmap"; + clocks = <&clksf>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + usb@d8007900 { compatible = "via,vt8500-ehci"; reg = <0xd8007900 0x200>; diff --git a/arch/arm/boot/dts/vt8500/wm8850-w70v2.dts b/arch/arm/boot/dts/vt8500/wm8850-w70v2.dts index 5d409323b10cb94a5694722de1e31cff5be390ce..d2638a204579d3dff477bb7f458438037e08019b 100644 --- a/arch/arm/boot/dts/vt8500/wm8850-w70v2.dts +++ b/arch/arm/boot/dts/vt8500/wm8850-w70v2.dts @@ -42,6 +42,43 @@ timing0: timing-800x480 { }; }; +&sflash { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-boot"; + reg = <0 0x50000>; + read-only; + }; + + partition@1 { + label = "U-boot environment 1"; + reg = <0x50000 0x10000>; + }; + + partition@2 { + label = "U-boot environment 2"; + reg = <0x60000 0x10000>; + }; + + partition@3 { + label = "W-load"; + reg = <0x70000 0x10000>; + read-only; + }; + }; + }; +}; + &uart0 { status = "okay"; }; diff --git a/arch/arm/boot/dts/vt8500/wm8850.dtsi b/arch/arm/boot/dts/vt8500/wm8850.dtsi index c4bfb4d30aad0358b39cbf30edf0c63e32167bbd..6837198de2508536eef52537a7f451679d36c38b 100644 --- a/arch/arm/boot/dts/vt8500/wm8850.dtsi +++ b/arch/arm/boot/dts/vt8500/wm8850.dtsi @@ -217,6 +217,15 @@ clksdhc: sdhc { enable-reg = <0x250>; enable-bit = <0>; }; + + clksf: clock { + #clock-cells = <0>; + compatible = "via,vt8500-device-clock"; + clocks = <&pllb>; + divisor-reg = <0x314>; + enable-reg = <0x254>; + enable-bit = <23>; + }; }; }; @@ -243,6 +252,18 @@ timer@d8130100 { interrupts = <36>; }; + sflash: spi-nor-controller@d8002000 { + compatible = "wm,wm8850-sflash"; + reg = <0xd8002000 0x400>, + <0xff800000 0x800000>, + <0xef800000 0x800000>; + reg-names = "io", "chip0-mmap", "chip1-mmap"; + clocks = <&clksf>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + usb@d8007900 { compatible = "via,vt8500-ehci"; reg = <0xd8007900 0x200>; diff --git a/arch/arm/boot/dts/vt8500/wm8950-apc-rock.dts b/arch/arm/boot/dts/vt8500/wm8950-apc-rock.dts index 58b3c8deb4f20ae072bf1381f1dfa5e5adeb414a..647fdcccdbbd680276af1fa30363e09bbeb5ad16 100644 --- a/arch/arm/boot/dts/vt8500/wm8950-apc-rock.dts +++ b/arch/arm/boot/dts/vt8500/wm8950-apc-rock.dts @@ -16,6 +16,43 @@ memory@0 { }; }; +&sflash { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-boot"; + reg = <0 0x50000>; + read-only; + }; + + partition@1 { + label = "U-boot environment 1"; + reg = <0x50000 0x10000>; + }; + + partition@2 { + label = "U-boot environment 2"; + reg = <0x60000 0x10000>; + }; + + partition@3 { + label = "W-load"; + reg = <0x70000 0x10000>; + read-only; + }; + }; + }; +}; + &uart0 { status = "okay"; };