Received: by 2002:a6b:500f:0:0:0:0:0 with SMTP id e15csp372355iob; Mon, 2 May 2022 23:15:23 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxvdJCneweOBSKRawxf7JmVocDrdYZwFsoq/OffNMrtJ5kFJEmJu4okUWhV36S0Opt6Od9c X-Received: by 2002:a2e:83cc:0:b0:24d:422e:d510 with SMTP id s12-20020a2e83cc000000b0024d422ed510mr8880977ljh.128.1651558522968; Mon, 02 May 2022 23:15:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1651558522; cv=none; d=google.com; s=arc-20160816; b=ooW86UXq2OWlkA7bu9en9cf6po1fqyCTTuyDpSrT+hYqU+U7+Y/Cx7oSpe2KFr5xQ2 XmLE9ZwyLyRh9Vyt3FmKw3XUEZvyUGZtqPp8Cdm4Uu7dfSvgDfT86lqEFzEHkGCvgOLg EFzpSUitkCG6P1eJjyYEk8o5N60O8e5ZDIKu4uVrky6DMOsiQ9ahkUG5NAPBl7QNoANI ZCAdq/A/rUV3KSbKhEdPNfB2Dg3deAAmD9qDTb7agkmoBe9WOtBCeZkzKwW9qdUAOyXG bih6ZtJQCOTAMjakKuGm6YBbGXH6vQ3BX8WBxhnBpAhcDUHVRm9K3CdpadX/WwK/gn6D qgIw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=PHAPvAeYKCSyEOgfTuuJhif8DOC6ubnCBxknF8qlB+8=; b=ntgSEsGwt9HhiytKZ7SJpHzUxSKvohPzhjf0P/mEd+AcfTC9pqgmxjhj+jKTp/aldm J8yVGoLeJO/VTh+A/L5XHrDrDz0PHthO9uaEmThgn/x5mQhyldb6hbZ9fpVJ/aj6loK5 7k5s00k36YmT1RTuBbmRzhpFtTLdsb+pzVymIJsfB+EVp+VRRG78J+yDyEumpU/yJTr5 5PHk1NJpoRWYNExFLvJpU6jALqZZKQgjfh/1rG196zsiG93h3Z5Jd8hRUJzShAA3dGuA oS7C7o8AyLLnqTMnUDE2tUV3+dTmbF4eCV0JRflLJJUXq8sLCLUobNHenPOWd/LAoJ61 ZZtA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id d25-20020a0565123d1900b00473a2471e6asi3024359lfv.21.2022.05.02.23.14.56; Mon, 02 May 2022 23:15:22 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229713AbiECGK7 (ORCPT + 99 others); Tue, 3 May 2022 02:10:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35206 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229652AbiECGKw (ORCPT ); Tue, 3 May 2022 02:10:52 -0400 Received: from gandalf.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3F9DC35865; Mon, 2 May 2022 23:07:19 -0700 (PDT) Received: from gandalf.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by gandalf.ozlabs.org (Postfix) with ESMTP id 4KsqHT6jvjz4ySb; Tue, 3 May 2022 16:07:17 +1000 (AEST) Received: from authenticated.ozlabs.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mail.ozlabs.org (Postfix) with ESMTPSA id 4KsqHN4Bqrz4xbw; Tue, 3 May 2022 16:07:12 +1000 (AEST) From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= To: linux-spi@vger.kernel.org, linux-mtd@lists.infradead.org Cc: Mark Brown , Tudor Ambarus , Pratyush Yadav , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , linux-aspeed@lists.ozlabs.org, Joel Stanley , Andrew Jeffery , Chin-Ting Kuo , devicetree@vger.kernel.org, Rob Herring , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , Tao Ren , Jae Hyun Yoo Subject: [PATCH v6 05/11] spi: aspeed: Adjust direct mapping to device size Date: Tue, 3 May 2022 08:06:28 +0200 Message-Id: <20220503060634.122722-6-clg@kaod.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220503060634.122722-1-clg@kaod.org> References: <20220503060634.122722-1-clg@kaod.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The segment registers of the FMC/SPI controllers provide a way to configure the mapping window of the flash device contents on the AHB bus. Adjust this window to the size of the spi-mem mapping. Things get more complex with multiple devices. The driver needs to also adjust the window of the next device to make sure that there is no overlap, even if there is no available device. The proposal below is not perfect but it is covering all the cases we have seen on different boards with one and two devices on the same bus. Reviewed-by: Joel Stanley Tested-by: Joel Stanley Tested-by: Tao Ren Tested-by: Jae Hyun Yoo Signed-off-by: Cédric Le Goater --- drivers/spi/spi-aspeed-smc.c | 88 ++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c index 50cc7bd7ba3e..0aff42e20b8d 100644 --- a/drivers/spi/spi-aspeed-smc.c +++ b/drivers/spi/spi-aspeed-smc.c @@ -411,6 +411,92 @@ static int aspeed_spi_chip_set_default_window(struct aspeed_spi_chip *chip) return chip->ahb_window_size ? 0 : -1; } +static int aspeed_spi_set_window(struct aspeed_spi *aspi, + const struct aspeed_spi_window *win) +{ + u32 start = aspi->ahb_base_phy + win->offset; + u32 end = start + win->size; + void __iomem *seg_reg = aspi->regs + CE0_SEGMENT_ADDR_REG + win->cs * 4; + u32 seg_val_backup = readl(seg_reg); + u32 seg_val = aspi->data->segment_reg(aspi, start, end); + + if (seg_val == seg_val_backup) + return 0; + + writel(seg_val, seg_reg); + + /* + * Restore initial value if something goes wrong else we could + * loose access to the chip. + */ + if (seg_val != readl(seg_reg)) { + dev_err(aspi->dev, "CE%d invalid window [ 0x%.8x - 0x%.8x ] %dMB", + win->cs, start, end - 1, win->size >> 20); + writel(seg_val_backup, seg_reg); + return -EIO; + } + + if (win->size) + dev_dbg(aspi->dev, "CE%d new window [ 0x%.8x - 0x%.8x ] %dMB", + win->cs, start, end - 1, win->size >> 20); + else + dev_dbg(aspi->dev, "CE%d window closed", win->cs); + + return 0; +} + +/* + * Yet to be done when possible : + * - Align mappings on flash size (we don't have the info) + * - ioremap each window, not strictly necessary since the overall window + * is correct. + */ +static int aspeed_spi_chip_adjust_window(struct aspeed_spi_chip *chip, + u32 local_offset, u32 size) +{ + struct aspeed_spi *aspi = chip->aspi; + struct aspeed_spi_window windows[ASPEED_SPI_MAX_NUM_CS] = { 0 }; + struct aspeed_spi_window *win = &windows[chip->cs]; + int ret; + + aspeed_spi_get_windows(aspi, windows); + + /* Adjust this chip window */ + win->offset += local_offset; + win->size = size; + + if (win->offset + win->size > aspi->ahb_window_size) { + win->size = aspi->ahb_window_size - win->offset; + dev_warn(aspi->dev, "CE%d window resized to %dMB", chip->cs, win->size >> 20); + } + + ret = aspeed_spi_set_window(aspi, win); + if (ret) + return ret; + + /* Update chip mapping info */ + chip->ahb_base = aspi->ahb_base + win->offset; + chip->ahb_window_size = win->size; + + /* + * Also adjust next chip window to make sure that it does not + * overlap with the current window. + */ + if (chip->cs < aspi->data->max_cs - 1) { + struct aspeed_spi_window *next = &windows[chip->cs + 1]; + + /* Change offset and size to keep the same end address */ + if ((next->offset + next->size) > (win->offset + win->size)) + next->size = (next->offset + next->size) - (win->offset + win->size); + else + next->size = 0; + next->offset = win->offset + win->size; + + aspeed_spi_set_window(aspi, next); + } + return 0; +} + static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc) { struct aspeed_spi *aspi = spi_controller_get_devdata(desc->mem->spi->master); @@ -425,6 +511,8 @@ static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc) if (op->data.dir != SPI_MEM_DATA_IN) return -EOPNOTSUPP; + aspeed_spi_chip_adjust_window(chip, desc->info.offset, desc->info.length); + if (desc->info.length > chip->ahb_window_size) dev_warn(aspi->dev, "CE%d window (%dMB) too small for mapping", chip->cs, chip->ahb_window_size >> 20); -- 2.35.1