From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 08723ECAAD4 for ; Wed, 31 Aug 2022 12:53:39 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6815F849A1; Wed, 31 Aug 2022 14:53:37 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=amarulasolutions.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=amarulasolutions.com header.i=@amarulasolutions.com header.b="Q1ehTmGj"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C1F96845F3; Wed, 31 Aug 2022 14:53:35 +0200 (CEST) Received: from mail-pf1-x436.google.com (mail-pf1-x436.google.com [IPv6:2607:f8b0:4864:20::436]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id A4C3D849A1 for ; Wed, 31 Aug 2022 14:53:30 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=amarulasolutions.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=michael@amarulasolutions.com Received: by mail-pf1-x436.google.com with SMTP id 145so13957769pfw.4 for ; Wed, 31 Aug 2022 05:53:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amarulasolutions.com; s=google; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc; bh=LT/lflu9j75dmMTSQcvnb6gDZbTATfhBjulpamh1BCU=; b=Q1ehTmGjdNPxaR5bUnVW4FzTp2cQQiYpLemXUYBZW/5Q5oERFtWYElAAgAwrZ1MJaz o9036Qb7+n/hpGV+7ncKtnapntusGA5YUkvzhRSlM6OaqsD4gziJGq8nSs3PcKkYr1h9 6YcdXBO7Kx+OxUwLbXFUp/iV64fGgNgQhYvPo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc; bh=LT/lflu9j75dmMTSQcvnb6gDZbTATfhBjulpamh1BCU=; b=ny833eoeE5HxBkN9wOZ/oipnED5+h/xWVvrcVojRWLFQ8EDovYvFxLxdOxmAPOdLys iURFG5mrCt6saAQmdNlzy5Lro2x5dM5fIT+qX5mpVhoxiHJVDslhvStfOkhFhZP7xbu7 rOXOuctTyaxbKiOs05i1XYt+U08YIuWEYXDz2RKDm5Z1ciVS1tscgVTWCpoSWXGi55vH WG0EKOVqXW0jOXx7HQx7psz8zZ+0w+7ZAfiElYOnHih/JmOgi1AtiK+PpfzowUX/Y7m4 nMGju0VPqHTD8vJjrd/49NowRSZbiGbCUGSk+kvgBiwBa2FvC8iCreyuK9O4qVxy06uB 00jg== X-Gm-Message-State: ACgBeo1FQWsdeCuv0XfZfLfy/V0ckvtCY44gI1KgBJrC7EO9Z2aJFUM0 q5NlzQ34r6/qgvIfTJzeUHfOJj+R+upyOClsH3N4mQ== X-Google-Smtp-Source: AA6agR6dGzDCPR79m8Gr4pGFIlgKr4452OP0v3eDOL1byLiYmFNs53dQlayHyPFZRjYGqSCDGXqevK7UMkgIccJrTrk= X-Received: by 2002:a65:6255:0:b0:42c:87b1:485b with SMTP id q21-20020a656255000000b0042c87b1485bmr7847235pgv.491.1661950408518; Wed, 31 Aug 2022 05:53:28 -0700 (PDT) MIME-Version: 1.0 References: <20220829061928.21895-1-balamanikandan.gunasundar@microchip.com> <20220829061928.21895-6-balamanikandan.gunasundar@microchip.com> In-Reply-To: <20220829061928.21895-6-balamanikandan.gunasundar@microchip.com> From: Michael Nazzareno Trimarchi Date: Wed, 31 Aug 2022 14:53:16 +0200 Message-ID: Subject: Re: [PATCH v2 5/9] mfd: syscon: atmel-smc: Add driver for atmel SMC To: Balamanikandan Gunasundar Cc: u-boot@lists.denx.de, sandeep.sheriker@microchip.com, eugen.hristev@microchip.com, dario.binacchi@amarulasolutions.com, mihai.sain@microchip.com, sergiu.moga@microchip.com, claudiu.beznea@microchip.com, hs@denx.de, tudor.ambarus@microchip.com, sjg@chromium.org, ascull@google.com, kettenis@openbsd.org, jh80.chung@samsung.com, peng.fan@nxp.com, ye.li@nxp.com, hari.prasathge@microchip.com Content-Type: text/plain; charset="UTF-8" X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.6 at phobos.denx.de X-Virus-Status: Clean Hi On Mon, Aug 29, 2022 at 8:20 AM Balamanikandan Gunasundar wrote: > > Add driver for atmel Static Memory Controller. Add helper functions to > configure SMC. This file is inherited from the work done by Boris > Brezillon for Linux > This does not look like a driver.Those are helper functions. Now I have no objections to put it here but it will be the first one under mfd. I think linux commit message subject give more an idea on what exactly it is mfd: syscon: atmel-smc: Add new helpers to ease SMC regs manipulation Michael > Signed-off-by: Balamanikandan Gunasundar > --- > drivers/Kconfig | 2 + > drivers/Makefile | 1 + > drivers/mfd/Kconfig | 4 + > drivers/mfd/Makefile | 1 + > drivers/mfd/atmel-smc.c | 364 +++++++++++++++++++++++++++ > include/linux/mfd/syscon/atmel-smc.h | 119 +++++++++ > 6 files changed, 491 insertions(+) > create mode 100644 drivers/mfd/Kconfig > create mode 100644 drivers/mfd/Makefile > create mode 100644 drivers/mfd/atmel-smc.c > create mode 100644 include/linux/mfd/syscon/atmel-smc.h > > diff --git a/drivers/Kconfig b/drivers/Kconfig > index 8b6fead351..ffc06ed65e 100644 > --- a/drivers/Kconfig > +++ b/drivers/Kconfig > @@ -60,6 +60,8 @@ source "drivers/mailbox/Kconfig" > > source "drivers/memory/Kconfig" > > +source "drivers/mfd/Kconfig" > + > source "drivers/misc/Kconfig" > > source "drivers/mmc/Kconfig" > diff --git a/drivers/Makefile b/drivers/Makefile > index eba9940231..5a8e80d4fe 100644 > --- a/drivers/Makefile > +++ b/drivers/Makefile > @@ -101,6 +101,7 @@ obj-$(CONFIG_QE) += qe/ > obj-$(CONFIG_U_QE) += qe/ > obj-y += mailbox/ > obj-y += memory/ > +obj-y += mfd/ > obj-y += mtd/ > obj-y += pwm/ > obj-y += reset/ > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig > new file mode 100644 > index 0000000000..ae53b02f27 > --- /dev/null > +++ b/drivers/mfd/Kconfig > @@ -0,0 +1,4 @@ > +config MFD_ATMEL_SMC > + bool "Atmel Static Memory Controller driver" > + help > + Say yes here to support Atmel Static Memory Controller driver. > diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile > new file mode 100644 > index 0000000000..4454815a98 > --- /dev/null > +++ b/drivers/mfd/Makefile > @@ -0,0 +1 @@ > +obj-$(CONFIG_MFD_ATMEL_SMC) += atmel-smc.o > diff --git a/drivers/mfd/atmel-smc.c b/drivers/mfd/atmel-smc.c > new file mode 100644 > index 0000000000..15296f71a1 > --- /dev/null > +++ b/drivers/mfd/atmel-smc.c > @@ -0,0 +1,364 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Atmel SMC (Static Memory Controller) helper functions. > + * > + * Copyright (C) 2022 Microchip Technology Inc. > + * Copyright (C) 2017 Free Electrons > + * > + * Author: Boris Brezillon > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +/** > + * atmel_smc_cs_conf_init - initialize a SMC CS conf > + * @conf: the SMC CS conf to initialize > + * > + * Set all fields to 0 so that one can start defining a new config. > + */ > +void atmel_smc_cs_conf_init(struct atmel_smc_cs_conf *conf) > +{ > + memset(conf, 0, sizeof(*conf)); > +} > +EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_init); > + > +/** > + * atmel_smc_cs_encode_ncycles - encode a number of MCK clk cycles in the > + * format expected by the SMC engine > + * @ncycles: number of MCK clk cycles > + * @msbpos: position of the MSB part of the timing field > + * @msbwidth: width of the MSB part of the timing field > + * @msbfactor: factor applied to the MSB > + * @encodedval: param used to store the encoding result > + * > + * This function encodes the @ncycles value as described in the datasheet > + * (section "SMC Setup/Pulse/Cycle/Timings Register"). This is a generic > + * helper which called with different parameter depending on the encoding > + * scheme. > + * > + * If the @ncycles value is too big to be encoded, -ERANGE is returned and > + * the encodedval is contains the maximum val. Otherwise, 0 is returned. > + */ > +static int atmel_smc_cs_encode_ncycles(unsigned int ncycles, > + unsigned int msbpos, > + unsigned int msbwidth, > + unsigned int msbfactor, > + unsigned int *encodedval) > +{ > + unsigned int lsbmask = GENMASK(msbpos - 1, 0); > + unsigned int msbmask = GENMASK(msbwidth - 1, 0); > + unsigned int msb, lsb; > + int ret = 0; > + > + msb = ncycles / msbfactor; > + lsb = ncycles % msbfactor; > + > + if (lsb > lsbmask) { > + lsb = 0; > + msb++; > + } > + > + /* > + * Let's just put the maximum we can if the requested setting does > + * not fit in the register field. > + * We still return -ERANGE in case the caller cares. > + */ > + if (msb > msbmask) { > + msb = msbmask; > + lsb = lsbmask; > + ret = -ERANGE; > + } > + > + *encodedval = (msb << msbpos) | lsb; > + > + return ret; > +} > + > +/** > + * atmel_smc_cs_conf_set_timing - set the SMC CS conf Txx parameter to a > + * specific value > + * @conf: SMC CS conf descriptor > + * @shift: the position of the Txx field in the TIMINGS register > + * @ncycles: value (expressed in MCK clk cycles) to assign to this Txx > + * parameter > + * > + * This function encodes the @ncycles value as described in the datasheet > + * (section "SMC Timings Register"), and then stores the result in the > + * @conf->timings field at @shift position. > + * > + * Returns -EINVAL if shift is invalid, -ERANGE if ncycles does not fit in > + * the field, and 0 otherwise. > + */ > +int atmel_smc_cs_conf_set_timing(struct atmel_smc_cs_conf *conf, > + unsigned int shift, unsigned int ncycles) > +{ > + unsigned int val; > + int ret; > + > + if (shift != ATMEL_HSMC_TIMINGS_TCLR_SHIFT && > + shift != ATMEL_HSMC_TIMINGS_TADL_SHIFT && > + shift != ATMEL_HSMC_TIMINGS_TAR_SHIFT && > + shift != ATMEL_HSMC_TIMINGS_TRR_SHIFT && > + shift != ATMEL_HSMC_TIMINGS_TWB_SHIFT) > + return -EINVAL; > + > + /* > + * The formula described in atmel datasheets (section "HSMC Timings > + * Register"): > + * > + * ncycles = (Txx[3] * 64) + Txx[2:0] > + */ > + ret = atmel_smc_cs_encode_ncycles(ncycles, 3, 1, 64, &val); > + conf->timings &= ~GENMASK(shift + 3, shift); > + conf->timings |= val << shift; > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_timing); > + > +/** > + * atmel_smc_cs_conf_set_setup - set the SMC CS conf xx_SETUP parameter to a > + * specific value > + * @conf: SMC CS conf descriptor > + * @shift: the position of the xx_SETUP field in the SETUP register > + * @ncycles: value (expressed in MCK clk cycles) to assign to this xx_SETUP > + * parameter > + * > + * This function encodes the @ncycles value as described in the datasheet > + * (section "SMC Setup Register"), and then stores the result in the > + * @conf->setup field at @shift position. > + * > + * Returns -EINVAL if @shift is invalid, -ERANGE if @ncycles does not fit in > + * the field, and 0 otherwise. > + */ > +int atmel_smc_cs_conf_set_setup(struct atmel_smc_cs_conf *conf, > + unsigned int shift, unsigned int ncycles) > +{ > + unsigned int val; > + int ret; > + > + if (shift != ATMEL_SMC_NWE_SHIFT && shift != ATMEL_SMC_NCS_WR_SHIFT && > + shift != ATMEL_SMC_NRD_SHIFT && shift != ATMEL_SMC_NCS_RD_SHIFT) > + return -EINVAL; > + > + /* > + * The formula described in atmel datasheets (section "SMC Setup > + * Register"): > + * > + * ncycles = (128 * xx_SETUP[5]) + xx_SETUP[4:0] > + */ > + ret = atmel_smc_cs_encode_ncycles(ncycles, 5, 1, 128, &val); > + conf->setup &= ~GENMASK(shift + 7, shift); > + conf->setup |= val << shift; > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_setup); > + > +/** > + * atmel_smc_cs_conf_set_pulse - set the SMC CS conf xx_PULSE parameter to a > + * specific value > + * @conf: SMC CS conf descriptor > + * @shift: the position of the xx_PULSE field in the PULSE register > + * @ncycles: value (expressed in MCK clk cycles) to assign to this xx_PULSE > + * parameter > + * > + * This function encodes the @ncycles value as described in the datasheet > + * (section "SMC Pulse Register"), and then stores the result in the > + * @conf->setup field at @shift position. > + * > + * Returns -EINVAL if @shift is invalid, -ERANGE if @ncycles does not fit in > + * the field, and 0 otherwise. > + */ > +int atmel_smc_cs_conf_set_pulse(struct atmel_smc_cs_conf *conf, > + unsigned int shift, unsigned int ncycles) > +{ > + unsigned int val; > + int ret; > + > + if (shift != ATMEL_SMC_NWE_SHIFT && shift != ATMEL_SMC_NCS_WR_SHIFT && > + shift != ATMEL_SMC_NRD_SHIFT && shift != ATMEL_SMC_NCS_RD_SHIFT) > + return -EINVAL; > + > + /* > + * The formula described in atmel datasheets (section "SMC Pulse > + * Register"): > + * > + * ncycles = (256 * xx_PULSE[6]) + xx_PULSE[5:0] > + */ > + ret = atmel_smc_cs_encode_ncycles(ncycles, 6, 1, 256, &val); > + conf->pulse &= ~GENMASK(shift + 7, shift); > + conf->pulse |= val << shift; > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_pulse); > + > +/** > + * atmel_smc_cs_conf_set_cycle - set the SMC CS conf xx_CYCLE parameter to a > + * specific value > + * @conf: SMC CS conf descriptor > + * @shift: the position of the xx_CYCLE field in the CYCLE register > + * @ncycles: value (expressed in MCK clk cycles) to assign to this xx_CYCLE > + * parameter > + * > + * This function encodes the @ncycles value as described in the datasheet > + * (section "SMC Cycle Register"), and then stores the result in the > + * @conf->setup field at @shift position. > + * > + * Returns -EINVAL if @shift is invalid, -ERANGE if @ncycles does not fit in > + * the field, and 0 otherwise. > + */ > +int atmel_smc_cs_conf_set_cycle(struct atmel_smc_cs_conf *conf, > + unsigned int shift, unsigned int ncycles) > +{ > + unsigned int val; > + int ret; > + > + if (shift != ATMEL_SMC_NWE_SHIFT && shift != ATMEL_SMC_NRD_SHIFT) > + return -EINVAL; > + > + /* > + * The formula described in atmel datasheets (section "SMC Cycle > + * Register"): > + * > + * ncycles = (xx_CYCLE[8:7] * 256) + xx_CYCLE[6:0] > + */ > + ret = atmel_smc_cs_encode_ncycles(ncycles, 7, 2, 256, &val); > + conf->cycle &= ~GENMASK(shift + 15, shift); > + conf->cycle |= val << shift; > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_cycle); > + > +/** > + * atmel_smc_cs_conf_apply - apply an SMC CS conf > + * @regmap: the SMC regmap > + * @cs: the CS id > + * @conf: the SMC CS conf to apply > + * > + * Applies an SMC CS configuration. > + * Only valid on at91sam9/avr32 SoCs. > + */ > +void atmel_smc_cs_conf_apply(struct regmap *regmap, int cs, > + const struct atmel_smc_cs_conf *conf) > +{ > + regmap_write(regmap, ATMEL_SMC_SETUP(cs), conf->setup); > + regmap_write(regmap, ATMEL_SMC_PULSE(cs), conf->pulse); > + regmap_write(regmap, ATMEL_SMC_CYCLE(cs), conf->cycle); > + regmap_write(regmap, ATMEL_SMC_MODE(cs), conf->mode); > +} > +EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_apply); > + > +/** > + * atmel_hsmc_cs_conf_apply - apply an SMC CS conf > + * @regmap: the HSMC regmap > + * @cs: the CS id > + * @layout: the layout of registers > + * @conf: the SMC CS conf to apply > + * > + * Applies an SMC CS configuration. > + * Only valid on post-sama5 SoCs. > + */ > +void atmel_hsmc_cs_conf_apply(struct regmap *regmap, > + const struct atmel_hsmc_reg_layout *layout, > + int cs, const struct atmel_smc_cs_conf *conf) > +{ > + regmap_write(regmap, ATMEL_HSMC_SETUP(layout, cs), conf->setup); > + regmap_write(regmap, ATMEL_HSMC_PULSE(layout, cs), conf->pulse); > + regmap_write(regmap, ATMEL_HSMC_CYCLE(layout, cs), conf->cycle); > + regmap_write(regmap, ATMEL_HSMC_TIMINGS(layout, cs), conf->timings); > + regmap_write(regmap, ATMEL_HSMC_MODE(layout, cs), conf->mode); > +} > +EXPORT_SYMBOL_GPL(atmel_hsmc_cs_conf_apply); > + > +/** > + * atmel_smc_cs_conf_get - retrieve the current SMC CS conf > + * @regmap: the SMC regmap > + * @cs: the CS id > + * @conf: the SMC CS conf object to store the current conf > + * > + * Retrieve the SMC CS configuration. > + * Only valid on at91sam9/avr32 SoCs. > + */ > +void atmel_smc_cs_conf_get(struct regmap *regmap, int cs, > + struct atmel_smc_cs_conf *conf) > +{ > + regmap_read(regmap, ATMEL_SMC_SETUP(cs), &conf->setup); > + regmap_read(regmap, ATMEL_SMC_PULSE(cs), &conf->pulse); > + regmap_read(regmap, ATMEL_SMC_CYCLE(cs), &conf->cycle); > + regmap_read(regmap, ATMEL_SMC_MODE(cs), &conf->mode); > +} > +EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_get); > + > +/** > + * atmel_hsmc_cs_conf_get - retrieve the current SMC CS conf > + * @regmap: the HSMC regmap > + * @cs: the CS id > + * @layout: the layout of registers > + * @conf: the SMC CS conf object to store the current conf > + * > + * Retrieve the SMC CS configuration. > + * Only valid on post-sama5 SoCs. > + */ > +void atmel_hsmc_cs_conf_get(struct regmap *regmap, > + const struct atmel_hsmc_reg_layout *layout, > + int cs, struct atmel_smc_cs_conf *conf) > +{ > + regmap_read(regmap, ATMEL_HSMC_SETUP(layout, cs), &conf->setup); > + regmap_read(regmap, ATMEL_HSMC_PULSE(layout, cs), &conf->pulse); > + regmap_read(regmap, ATMEL_HSMC_CYCLE(layout, cs), &conf->cycle); > + regmap_read(regmap, ATMEL_HSMC_TIMINGS(layout, cs), &conf->timings); > + regmap_read(regmap, ATMEL_HSMC_MODE(layout, cs), &conf->mode); > +} > +EXPORT_SYMBOL_GPL(atmel_hsmc_cs_conf_get); > + > +static const struct atmel_hsmc_reg_layout sama5d3_reg_layout = { > + .timing_regs_offset = 0x600, > +}; > + > +static const struct atmel_hsmc_reg_layout sama5d2_reg_layout = { > + .timing_regs_offset = 0x700, > +}; > + > +static const struct udevice_id atmel_smc_ids[] = { > + { .compatible = "atmel,at91sam9260-smc", .data = (ulong)0 }, > + { .compatible = "atmel,sama5d3-smc", .data = (ulong)&sama5d3_reg_layout }, > + { .compatible = "atmel,sama5d2-smc", .data = (ulong)&sama5d2_reg_layout }, > + { /* sentinel */ }, > +}; > + > +/** > + * atmel_hsmc_get_reg_layout - retrieve the layout of HSMC registers > + * @np: the HSMC regmap > + * > + * Retrieve the layout of HSMC registers. > + * > + * Returns NULL in case of SMC, a struct atmel_hsmc_reg_layout pointer > + * in HSMC case, otherwise ERR_PTR(-EINVAL). > + */ > +const struct atmel_hsmc_reg_layout * > +atmel_hsmc_get_reg_layout(ofnode np) > +{ > + int i; > + const struct udevice_id *match; > + const char *name; > + int len; > + > + name = ofnode_get_property(np, "compatible", &len); > + > + for (i = 0; i < ARRAY_SIZE(atmel_smc_ids); i++) { > + if (!strcmp(name, atmel_smc_ids[i].compatible)) { > + match = &atmel_smc_ids[i]; > + break; > + } > + } > + > + return match ? (struct atmel_hsmc_reg_layout *)match->data : ERR_PTR(-EINVAL); > +} > diff --git a/include/linux/mfd/syscon/atmel-smc.h b/include/linux/mfd/syscon/atmel-smc.h > new file mode 100644 > index 0000000000..74be5a199f > --- /dev/null > +++ b/include/linux/mfd/syscon/atmel-smc.h > @@ -0,0 +1,119 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Atmel SMC (Static Memory Controller) register offsets and bit definitions. > + * > + * Copyright (C) 2014 Atmel > + * Copyright (C) 2014 Free Electrons > + * > + * Author: Boris Brezillon > + */ > + > +#ifndef _LINUX_MFD_SYSCON_ATMEL_SMC_H_ > +#define _LINUX_MFD_SYSCON_ATMEL_SMC_H_ > + > +#include > +#include > +#include > + > +#define ATMEL_SMC_SETUP(cs) (((cs) * 0x10)) > +#define ATMEL_HSMC_SETUP(layout, cs) \ > + ((layout)->timing_regs_offset + ((cs) * 0x14)) > +#define ATMEL_SMC_PULSE(cs) (((cs) * 0x10) + 0x4) > +#define ATMEL_HSMC_PULSE(layout, cs) \ > + ((layout)->timing_regs_offset + ((cs) * 0x14) + 0x4) > +#define ATMEL_SMC_CYCLE(cs) (((cs) * 0x10) + 0x8) > +#define ATMEL_HSMC_CYCLE(layout, cs) \ > + ((layout)->timing_regs_offset + ((cs) * 0x14) + 0x8) > +#define ATMEL_SMC_NWE_SHIFT 0 > +#define ATMEL_SMC_NCS_WR_SHIFT 8 > +#define ATMEL_SMC_NRD_SHIFT 16 > +#define ATMEL_SMC_NCS_RD_SHIFT 24 > + > +#define ATMEL_SMC_MODE(cs) (((cs) * 0x10) + 0xc) > +#define ATMEL_HSMC_MODE(layout, cs) \ > + ((layout)->timing_regs_offset + ((cs) * 0x14) + 0x10) > +#define ATMEL_SMC_MODE_READMODE_MASK BIT(0) > +#define ATMEL_SMC_MODE_READMODE_NCS (0 << 0) > +#define ATMEL_SMC_MODE_READMODE_NRD (1 << 0) > +#define ATMEL_SMC_MODE_WRITEMODE_MASK BIT(1) > +#define ATMEL_SMC_MODE_WRITEMODE_NCS (0 << 1) > +#define ATMEL_SMC_MODE_WRITEMODE_NWE (1 << 1) > +#define ATMEL_SMC_MODE_EXNWMODE_MASK GENMASK(5, 4) > +#define ATMEL_SMC_MODE_EXNWMODE_DISABLE (0 << 4) > +#define ATMEL_SMC_MODE_EXNWMODE_FROZEN (2 << 4) > +#define ATMEL_SMC_MODE_EXNWMODE_READY (3 << 4) > +#define ATMEL_SMC_MODE_BAT_MASK BIT(8) > +#define ATMEL_SMC_MODE_BAT_SELECT (0 << 8) > +#define ATMEL_SMC_MODE_BAT_WRITE (1 << 8) > +#define ATMEL_SMC_MODE_DBW_MASK GENMASK(13, 12) > +#define ATMEL_SMC_MODE_DBW_8 (0 << 12) > +#define ATMEL_SMC_MODE_DBW_16 (1 << 12) > +#define ATMEL_SMC_MODE_DBW_32 (2 << 12) > +#define ATMEL_SMC_MODE_TDF_MASK GENMASK(19, 16) > +#define ATMEL_SMC_MODE_TDF(x) (((x) - 1) << 16) > +#define ATMEL_SMC_MODE_TDF_MAX 16 > +#define ATMEL_SMC_MODE_TDF_MIN 1 > +#define ATMEL_SMC_MODE_TDFMODE_OPTIMIZED BIT(20) > +#define ATMEL_SMC_MODE_PMEN BIT(24) > +#define ATMEL_SMC_MODE_PS_MASK GENMASK(29, 28) > +#define ATMEL_SMC_MODE_PS_4 (0 << 28) > +#define ATMEL_SMC_MODE_PS_8 (1 << 28) > +#define ATMEL_SMC_MODE_PS_16 (2 << 28) > +#define ATMEL_SMC_MODE_PS_32 (3 << 28) > + > +#define ATMEL_HSMC_TIMINGS(layout, cs) \ > + ((layout)->timing_regs_offset + ((cs) * 0x14) + 0xc) > +#define ATMEL_HSMC_TIMINGS_OCMS BIT(12) > +#define ATMEL_HSMC_TIMINGS_RBNSEL(x) ((x) << 28) > +#define ATMEL_HSMC_TIMINGS_NFSEL BIT(31) > +#define ATMEL_HSMC_TIMINGS_TCLR_SHIFT 0 > +#define ATMEL_HSMC_TIMINGS_TADL_SHIFT 4 > +#define ATMEL_HSMC_TIMINGS_TAR_SHIFT 8 > +#define ATMEL_HSMC_TIMINGS_TRR_SHIFT 16 > +#define ATMEL_HSMC_TIMINGS_TWB_SHIFT 24 > + > +struct atmel_hsmc_reg_layout { > + unsigned int timing_regs_offset; > +}; > + > +/** > + * struct atmel_smc_cs_conf - SMC CS config as described in the datasheet. > + * @setup: NCS/NWE/NRD setup timings (not applicable to at91rm9200) > + * @pulse: NCS/NWE/NRD pulse timings (not applicable to at91rm9200) > + * @cycle: NWE/NRD cycle timings (not applicable to at91rm9200) > + * @timings: advanced NAND related timings (only applicable to HSMC) > + * @mode: all kind of config parameters (see the fields definition above). > + * The mode fields are different on at91rm9200 > + */ > +struct atmel_smc_cs_conf { > + u32 setup; > + u32 pulse; > + u32 cycle; > + u32 timings; > + u32 mode; > +}; > + > +void atmel_smc_cs_conf_init(struct atmel_smc_cs_conf *conf); > +int atmel_smc_cs_conf_set_timing(struct atmel_smc_cs_conf *conf, > + unsigned int shift, > + unsigned int ncycles); > +int atmel_smc_cs_conf_set_setup(struct atmel_smc_cs_conf *conf, > + unsigned int shift, unsigned int ncycles); > +int atmel_smc_cs_conf_set_pulse(struct atmel_smc_cs_conf *conf, > + unsigned int shift, unsigned int ncycles); > +int atmel_smc_cs_conf_set_cycle(struct atmel_smc_cs_conf *conf, > + unsigned int shift, unsigned int ncycles); > +void atmel_smc_cs_conf_apply(struct regmap *regmap, int cs, > + const struct atmel_smc_cs_conf *conf); > +void atmel_hsmc_cs_conf_apply(struct regmap *regmap, > + const struct atmel_hsmc_reg_layout *reglayout, > + int cs, const struct atmel_smc_cs_conf *conf); > +void atmel_smc_cs_conf_get(struct regmap *regmap, int cs, > + struct atmel_smc_cs_conf *conf); > +void atmel_hsmc_cs_conf_get(struct regmap *regmap, > + const struct atmel_hsmc_reg_layout *reglayout, > + int cs, struct atmel_smc_cs_conf *conf); > +const struct atmel_hsmc_reg_layout * > +atmel_hsmc_get_reg_layout(ofnode np); > + > +#endif /* _LINUX_MFD_SYSCON_ATMEL_SMC_H_ */ > -- > 2.34.1 > -- Michael Nazzareno Trimarchi Co-Founder & Chief Executive Officer M. +39 347 913 2170 michael@amarulasolutions.com __________________________________ Amarula Solutions BV Joop Geesinkweg 125, 1114 AB, Amsterdam, NL T. +31 (0)85 111 9172 info@amarulasolutions.com www.amarulasolutions.com