diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/_exports.h | 50 | ||||
-rw-r--r-- | include/cmd_spl.h | 3 | ||||
-rw-r--r-- | include/configs/baltos.h | 5 | ||||
-rw-r--r-- | include/configs/imx94_evk.h | 24 | ||||
-rw-r--r-- | include/configs/kontron-sl-mx8mm.h | 12 | ||||
-rw-r--r-- | include/dt-bindings/clock/agilex-clock.h | 71 | ||||
-rw-r--r-- | include/exports.h | 38 | ||||
-rw-r--r-- | include/fs_loader.h | 25 | ||||
-rw-r--r-- | include/fw_loader.h | 34 | ||||
-rw-r--r-- | include/linux/completion.h | 44 | ||||
-rw-r--r-- | include/linux/kernel.h | 14 | ||||
-rw-r--r-- | include/linux/mtd/nand.h | 157 | ||||
-rw-r--r-- | include/linux/mtd/spinand.h | 374 | ||||
-rw-r--r-- | include/malloc.h | 6 | ||||
-rw-r--r-- | include/miiphy.h | 15 | ||||
-rw-r--r-- | include/scmi_nxp_protocols.h | 55 | ||||
-rw-r--r-- | include/spi-mem.h | 93 | ||||
-rw-r--r-- | include/thermal.h | 2 |
18 files changed, 813 insertions, 209 deletions
diff --git a/include/_exports.h b/include/_exports.h index 1af946fac32..a23fc001421 100644 --- a/include/_exports.h +++ b/include/_exports.h @@ -1,7 +1,6 @@ /* * You need to use #ifdef around functions that may not exist * in the final configuration (such as i2c). - * use a dummyfunction as first parameter to EXPORT_FUNC. * As an example see the CONFIG_CMD_I2C section below */ #ifndef EXPORT_FUNC @@ -16,22 +15,22 @@ EXPORT_FUNC(flush, void, flush, void) #endif EXPORT_FUNC(printf, int, printf, const char*, ...) + EXPORT_FUNC(vprintf, int, vprintf, const char *, va_list) #if (defined(CONFIG_X86) && !defined(CONFIG_X86_64)) || defined(CONFIG_PPC) EXPORT_FUNC(irq_install_handler, void, install_hdlr, int, interrupt_handler_t, void*) EXPORT_FUNC(irq_free_handler, void, free_hdlr, int) -#else - EXPORT_FUNC(dummy, void, install_hdlr, void) - EXPORT_FUNC(dummy, void, free_hdlr, void) #endif EXPORT_FUNC(malloc, void *, malloc, size_t) + EXPORT_FUNC(realloc, void *, realloc, void *, size_t) + EXPORT_FUNC(calloc, void *, calloc, size_t, size_t) #if !CONFIG_IS_ENABLED(SYS_MALLOC_SIMPLE) EXPORT_FUNC(free, void, free, void *) #endif + EXPORT_FUNC(mdelay, void, mdelay, unsigned long msec) EXPORT_FUNC(udelay, void, udelay, unsigned long) EXPORT_FUNC(get_timer, unsigned long, get_timer, unsigned long) - EXPORT_FUNC(vprintf, int, vprintf, const char *, va_list) EXPORT_FUNC(do_reset, int, do_reset, struct cmd_tbl *, int , int , char * const []) EXPORT_FUNC(env_get, char *, env_get, const char*) @@ -42,40 +41,39 @@ const char *, unsigned int , unsigned long *) EXPORT_FUNC(simple_strtol, long, simple_strtol, const char *, char **, unsigned int) + EXPORT_FUNC(ustrtoul, unsigned long, ustrtoul, + const char *, char **, unsigned int) + EXPORT_FUNC(ustrtoull, unsigned long long, ustrtoull, + const char *, char **, unsigned int) + EXPORT_FUNC(memcmp, int, memcmp, const void *, const void *, size_t) + EXPORT_FUNC(memcpy, void *, memcpy, void *, const void *, size_t) + EXPORT_FUNC(memmove, void *, memmove, void *, const void *, size_t) + EXPORT_FUNC(memset, void *, memset, void *, int, size_t) + EXPORT_FUNC(strchr, char *, strchr, const char *cs, int c) + EXPORT_FUNC(strlen, size_t, strlen, const char *s) + EXPORT_FUNC(strncmp, int, strncmp, const char *cs, const char *ct, size_t n) + EXPORT_FUNC(strncpy, char *, strncpy, char *dest, const char *src, size_t n) + EXPORT_FUNC(strnlen, size_t, strnlen, const char *s, size_t n) EXPORT_FUNC(strcmp, int, strcmp, const char *cs, const char *ct) -#if defined(CONFIG_CMD_I2C) && !CONFIG_IS_ENABLED(DM_I2C) + EXPORT_FUNC(strcpy, char *, strcpy, char *dest, const char *src) + EXPORT_FUNC(sprintf, int, sprintf, char *, const char *, ...) + EXPORT_FUNC(snprintf, int, snprintf, char *, size_t, const char *, ...) + EXPORT_FUNC(vsprintf, int, vsprintf, char *, const char *, va_list) + EXPORT_FUNC(vsnprintf, int, vsnprintf, char *, size_t, const char *, va_list) +#if defined(CONFIG_CMD_I2C) && CONFIG_IS_ENABLED(SYS_I2C_LEGACY) EXPORT_FUNC(i2c_write, int, i2c_write, uchar, uint, int , uchar * , int) EXPORT_FUNC(i2c_read, int, i2c_read, uchar, uint, int , uchar * , int) -#else - EXPORT_FUNC(dummy, void, i2c_write, void) - EXPORT_FUNC(dummy, void, i2c_read, void) #endif -#if !defined(CONFIG_CMD_SPI) || defined(CONFIG_DM_SPI) - EXPORT_FUNC(dummy, void, spi_setup_slave, void) - EXPORT_FUNC(dummy, void, spi_free_slave, void) -#else +#if defined(CONFIG_CMD_SPI) EXPORT_FUNC(spi_setup_slave, struct spi_slave *, spi_setup_slave, unsigned int, unsigned int, unsigned int, unsigned int) EXPORT_FUNC(spi_free_slave, void, spi_free_slave, struct spi_slave *) -#endif -#ifndef CONFIG_CMD_SPI - EXPORT_FUNC(dummy, void, spi_claim_bus, void) - EXPORT_FUNC(dummy, void, spi_release_bus, void) - EXPORT_FUNC(dummy, void, spi_xfer, void) -#else EXPORT_FUNC(spi_claim_bus, int, spi_claim_bus, struct spi_slave *) EXPORT_FUNC(spi_release_bus, void, spi_release_bus, struct spi_slave *) EXPORT_FUNC(spi_xfer, int, spi_xfer, struct spi_slave *, unsigned int, const void *, void *, unsigned long) #endif - EXPORT_FUNC(ustrtoul, unsigned long, ustrtoul, - const char *, char **, unsigned int) - EXPORT_FUNC(ustrtoull, unsigned long long, ustrtoull, - const char *, char **, unsigned int) - EXPORT_FUNC(strcpy, char *, strcpy, char *dest, const char *src) - EXPORT_FUNC(mdelay, void, mdelay, unsigned long msec) - EXPORT_FUNC(memset, void *, memset, void *, int, size_t) #ifdef CONFIG_PHY_AQUANTIA EXPORT_FUNC(mdio_get_current_dev, struct mii_dev *, mdio_get_current_dev, void) diff --git a/include/cmd_spl.h b/include/cmd_spl.h index 51ec12edb90..45ea91e9bce 100644 --- a/include/cmd_spl.h +++ b/include/cmd_spl.h @@ -8,7 +8,6 @@ #define SPL_EXPORT (0x00000001) #define SPL_EXPORT_FDT (0x00000001) -#define SPL_EXPORT_ATAGS (0x00000002) -#define SPL_EXPORT_LAST SPL_EXPORT_ATAGS +#define SPL_EXPORT_LAST SPL_EXPORT_FDT #endif /* _NAND_SPL_H_ */ diff --git a/include/configs/baltos.h b/include/configs/baltos.h index cc54b514fff..4223619fe5d 100644 --- a/include/configs/baltos.h +++ b/include/configs/baltos.h @@ -206,9 +206,4 @@ #endif #endif -/* NAND support */ -#ifdef CONFIG_MTD_RAW_NAND -#define GPMC_NAND_ECC_LP_x8_LAYOUT 1 -#endif - #endif /* ! __CONFIG_BALTOS_H */ diff --git a/include/configs/imx94_evk.h b/include/configs/imx94_evk.h new file mode 100644 index 00000000000..f93c3c4e4a8 --- /dev/null +++ b/include/configs/imx94_evk.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2025 NXP + */ + +#ifndef __IMX94_EVK_H +#define __IMX94_EVK_H + +#include <linux/sizes.h> +#include <linux/stringify.h> +#include <asm/arch/imx-regs.h> + +#define CFG_SYS_INIT_RAM_ADDR 0x90000000 +#define CFG_SYS_INIT_RAM_SIZE 0x200000 + +#define CFG_SYS_SDRAM_BASE 0x90000000 +#define PHYS_SDRAM 0x90000000 +#define PHYS_SDRAM_SIZE 0x70000000UL /* 2GB - 256MB DDR */ +#define PHYS_SDRAM_2_SIZE 0x180000000 /* 8GB */ + +/* Using ULP WDOG for reset */ +#define WDOG_BASE_ADDR WDG3_BASE_ADDR + +#endif diff --git a/include/configs/kontron-sl-mx8mm.h b/include/configs/kontron-sl-mx8mm.h index 72a28a6a413..318c39d673a 100644 --- a/include/configs/kontron-sl-mx8mm.h +++ b/include/configs/kontron-sl-mx8mm.h @@ -29,21 +29,9 @@ EFI_GUID(0xd488e45a, 0x4929, 0x4b55, 0x8c, 0x14, \ 0x86, 0xce, 0xa2, 0xcd, 0x66, 0x29) -#define BOOT_TARGET_DEVICES(func) \ - func(MMC, mmc, 1) \ - func(MMC, mmc, 0) \ - func(USB, usb, 0) \ - func(PXE, pxe, na) -#include <config_distro_bootcmd.h> -/* Do not try to probe USB net adapters for net boot */ -#undef BOOTENV_RUN_NET_USB_START -#define BOOTENV_RUN_NET_USB_START - #ifdef CONFIG_XPL_BUILD /* malloc f used before GD_FLG_FULL_MALLOC_INIT set */ #define CFG_MALLOC_F_ADDR 0x930000 #endif -#define CFG_EXTRA_ENV_SETTINGS BOOTENV - #endif /* __KONTRON_MX8MM_CONFIG_H */ diff --git a/include/dt-bindings/clock/agilex-clock.h b/include/dt-bindings/clock/agilex-clock.h new file mode 100644 index 00000000000..a6252180516 --- /dev/null +++ b/include/dt-bindings/clock/agilex-clock.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2025 Altera Corporation <www.altera.com> + */ + +#ifndef __AGILEX_CLOCK_H +#define __AGILEX_CLOCK_H + +/* fixed rate clocks */ +#define AGILEX_OSC1 0 +#define AGILEX_CB_INTOSC_HS_DIV2_CLK 1 +#define AGILEX_CB_INTOSC_LS_CLK 2 +#define AGILEX_L4_SYS_FREE_CLK 3 +#define AGILEX_F2S_FREE_CLK 4 + +/* PLL clocks */ +#define AGILEX_MAIN_PLL_CLK 5 +#define AGILEX_MAIN_PLL_C0_CLK 6 +#define AGILEX_MAIN_PLL_C1_CLK 7 +#define AGILEX_MAIN_PLL_C2_CLK 8 +#define AGILEX_MAIN_PLL_C3_CLK 9 +#define AGILEX_PERIPH_PLL_CLK 10 +#define AGILEX_PERIPH_PLL_C0_CLK 11 +#define AGILEX_PERIPH_PLL_C1_CLK 12 +#define AGILEX_PERIPH_PLL_C2_CLK 13 +#define AGILEX_PERIPH_PLL_C3_CLK 14 +#define AGILEX_MPU_FREE_CLK 15 +#define AGILEX_MPU_CCU_CLK 16 +#define AGILEX_BOOT_CLK 17 + +/* fixed factor clocks */ +#define AGILEX_L3_MAIN_FREE_CLK 18 +#define AGILEX_NOC_FREE_CLK 19 +#define AGILEX_S2F_USR0_CLK 20 +#define AGILEX_NOC_CLK 21 +#define AGILEX_EMAC_A_FREE_CLK 22 +#define AGILEX_EMAC_B_FREE_CLK 23 +#define AGILEX_EMAC_PTP_FREE_CLK 24 +#define AGILEX_GPIO_DB_FREE_CLK 25 +#define AGILEX_SDMMC_FREE_CLK 26 +#define AGILEX_S2F_USER0_FREE_CLK 27 +#define AGILEX_S2F_USER1_FREE_CLK 28 +#define AGILEX_PSI_REF_FREE_CLK 29 + +/* Gate clocks */ +#define AGILEX_MPU_CLK 30 +#define AGILEX_MPU_PERIPH_CLK 31 +#define AGILEX_L4_MAIN_CLK 32 +#define AGILEX_L4_MP_CLK 33 +#define AGILEX_L4_SP_CLK 34 +#define AGILEX_CS_AT_CLK 35 +#define AGILEX_CS_TRACE_CLK 36 +#define AGILEX_CS_PDBG_CLK 37 +#define AGILEX_CS_TIMER_CLK 38 +#define AGILEX_S2F_USER0_CLK 39 +#define AGILEX_EMAC0_CLK 40 +#define AGILEX_EMAC1_CLK 41 +#define AGILEX_EMAC2_CLK 42 +#define AGILEX_EMAC_PTP_CLK 43 +#define AGILEX_GPIO_DB_CLK 44 +#define AGILEX_NAND_CLK 45 +#define AGILEX_PSI_REF_CLK 46 +#define AGILEX_S2F_USER1_CLK 47 +#define AGILEX_SDMMC_CLK 48 +#define AGILEX_SPI_M_CLK 49 +#define AGILEX_USB_CLK 50 +#define AGILEX_NAND_X_CLK 51 +#define AGILEX_NAND_ECC_CLK 52 +#define AGILEX_NUM_CLKS 53 + +#endif /* __AGILEX_CLOCK_H */ diff --git a/include/exports.h b/include/exports.h index 23cc3a66c20..12abb35643e 100644 --- a/include/exports.h +++ b/include/exports.h @@ -26,39 +26,9 @@ struct spi_slave; int jumptable_init(void); /* These are declarations of exported functions available in C code */ -unsigned long get_version(void); -int getc(void); -int tstc(void); -void putc(const char); -void puts(const char*); -int printf(const char* fmt, ...); -void install_hdlr(int, interrupt_handler_t, void*); -void free_hdlr(int); -void *malloc(size_t); -#if !CONFIG_IS_ENABLED(SYS_MALLOC_SIMPLE) -void free(void*); -#endif -void __udelay(unsigned long); -unsigned long get_timer(unsigned long); -int vprintf(const char *, va_list); -unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base); -int strict_strtoul(const char *cp, unsigned int base, unsigned long *res); -char *env_get(const char *name); -int env_set(const char *varname, const char *value); -long simple_strtol(const char *cp, char **endp, unsigned int base); -int strcmp(const char *cs, const char *ct); -unsigned long ustrtoul(const char *cp, char **endp, unsigned int base); -unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base); -#if defined(CONFIG_CMD_I2C) && !CONFIG_IS_ENABLED(DM_I2C) -int i2c_write (uchar, uint, int , uchar* , int); -int i2c_read (uchar, uint, int , uchar* , int); -#endif -#ifdef CONFIG_PHY_AQUANTIA -struct mii_dev *mdio_get_current_dev(void); -struct phy_device *phy_find_by_mask(struct mii_dev *bus, unsigned phy_mask); -struct phy_device *mdio_phydev_for_ethname(const char *ethname); -int miiphy_set_current_dev(const char *devname); -#endif +#define EXPORT_FUNC(impl, res, func, ...) res func(__VA_ARGS__); +#include <_exports.h> +#undef EXPORT_FUNC void app_startup(char * const *); @@ -70,7 +40,7 @@ struct jt_funcs { #undef EXPORT_FUNC }; -#define XF_VERSION 9 +#define XF_VERSION 10 #if defined(CONFIG_X86) extern gd_t *global_data; diff --git a/include/fs_loader.h b/include/fs_loader.h index 1cf6d6dd05f..7e16e0f7030 100644 --- a/include/fs_loader.h +++ b/include/fs_loader.h @@ -65,29 +65,4 @@ int request_firmware_into_buf(struct udevice *dev, */ int get_fs_loader(struct udevice **dev); -/** - * request_firmware_into_buf_via_script() - - * Load firmware using a U-Boot script and copy to buffer - * @buf: Pointer to a pointer where the firmware buffer will be stored. - * @max_size: Maximum allowed size for the firmware to be loaded. - * @script_name: Name of the U-Boot script to execute for firmware loading. - * @retsize: Return the actual firmware data size (optional). - * - * Executes a U-Boot script (@script_name) that loads firmware into - * memory and sets the environment variables 'fw_addr' (address) and - * 'fw_size' (size in bytes). On success, copies the firmware - * from the given address to user buffer @buf. - * - * The script must set these environment variables: - * fw_addr - Address where firmware is loaded in memory - * fw_size - Size of the firmware in bytes - * - * The script should be defined in the U-Boot environment, for example: - * env set script_name 'load mmc 0:1 ${loadaddr} firmware.bin && - * env set fw_addr ${loadaddr} && env set fw_size ${filesize} - * Return: 0 on success, negative value on error. - */ -int request_firmware_into_buf_via_script(void **buf, size_t max_size, - const char *script_name, - size_t *retsize); #endif diff --git a/include/fw_loader.h b/include/fw_loader.h new file mode 100644 index 00000000000..35574482b2b --- /dev/null +++ b/include/fw_loader.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2025 Lucien Jheng <lucienzx159@gmail.com> + */ +#ifndef _FW_LOADER_H_ +#define _FW_LOADER_H_ + +/** + * request_firmware_into_buf_via_script() - + * Load firmware using a U-Boot script and copy to buffer + * @buf: Pointer to a pointer where the firmware buffer will be stored. + * @max_size: Maximum allowed size for the firmware to be loaded. + * @script_name: Name of the U-Boot script to execute for firmware loading. + * @retsize: Return the actual firmware data size (optional). + * + * Executes a U-Boot script (@script_name) that loads firmware into + * memory and sets the environment variables 'fw_addr' (address) and + * 'fw_size' (size in bytes). On success, copies the firmware + * from the given address to user buffer @buf. + * + * The script must set these environment variables: + * fw_addr - Address where firmware is loaded in memory + * fw_size - Size of the firmware in bytes + * + * The script should be defined in the U-Boot environment, for example: + * env set script_name 'load mmc 0:1 ${loadaddr} firmware.bin && + * env set fw_addr ${loadaddr} && env set fw_size ${filesize} + * Return: 0 on success, negative value on error. + */ +int request_firmware_into_buf_via_script(void *buf, size_t max_size, + const char *script_name, + size_t *retsize); + +#endif diff --git a/include/linux/completion.h b/include/linux/completion.h index 9835826d285..d99ac450e8c 100644 --- a/include/linux/completion.h +++ b/include/linux/completion.h @@ -129,42 +129,14 @@ extern void complete_all(struct completion *); #define wait_for_completion(x) do {} while (0) #define wait_for_completion_io(x) do {} while (0) -inline int wait_for_completion_interruptible(struct completion *x) -{ - return 1; -} -inline int wait_for_completion_killable(struct completion *x) -{ - return 1; -} -inline unsigned long wait_for_completion_timeout(struct completion *x, - unsigned long timeout) -{ - return 1; -} -inline unsigned long wait_for_completion_io_timeout(struct completion *x, - unsigned long timeout) -{ - return 1; -} -inline long wait_for_completion_interruptible_timeout(struct completion *x, - unsigned long timeout) -{ - return 1; -} -inline long wait_for_completion_killable_timeout(struct completion *x, - unsigned long timeout) -{ - return 1; -} -inline bool try_wait_for_completion(struct completion *x) -{ - return 1; -} -inline bool completion_done(struct completion *x) -{ - return 1; -} +#define wait_for_completion_interruptible(x) 1 +#define wait_for_completion_killable(x) 1 +#define wait_for_completion_timeout(x, timeout) 1 +#define wait_for_completion_io_timeout(x, timeout) 1 +#define wait_for_completion_interruptible_timeout(x, timeout) 1 +#define wait_for_completion_killable_timeout(x, timeout) 1 +#define try_wait_for_completion(x) 1 +#define completion_done(x) 1 #define complete(x) do {} while (0) #define complete_all(x) do {} while (0) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index e0443ecac84..44a639a5e4e 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -111,7 +111,19 @@ * lower_32_bits - return bits 0-31 of a number * @n: the number we're accessing */ -#define lower_32_bits(n) ((u32)(n)) +#define lower_32_bits(n) ((u32)((n) & 0xffffffff)) + +/** + * upper_16_bits - return bits 16-31 of a number + * @n: the number we're accessing + */ +#define upper_16_bits(n) ((u16)((n) >> 16)) + +/** + * lower_16_bits - return bits 0-15 of a number + * @n: the number we're accessing + */ +#define lower_16_bits(n) ((u16)((n) & 0xffff)) /* * abs() handles unsigned and signed longs, ints, shorts and chars. For all diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 651f8706df5..243955ac1a1 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -19,7 +19,7 @@ * @oobsize: OOB area size * @pages_per_eraseblock: number of pages per eraseblock * @eraseblocks_per_lun: number of eraseblocks per LUN (Logical Unit Number) - * @max_bad_eraseblocks_per_lun: maximum number of eraseblocks per LUN + * @max_bad_eraseblocks_per_lun: maximum number of bad eraseblocks per LUN * @planes_per_lun: number of planes per LUN * @luns_per_target: number of LUN per target (target is a synonym for die) * @ntargets: total number of targets exposed by the NAND device @@ -81,7 +81,18 @@ struct nand_pos { }; /** + * enum nand_page_io_req_type - Direction of an I/O request + * @NAND_PAGE_READ: from the chip, to the controller + * @NAND_PAGE_WRITE: from the controller, to the chip + */ +enum nand_page_io_req_type { + NAND_PAGE_READ = 0, + NAND_PAGE_WRITE, +}; + +/** * struct nand_page_io_req - NAND I/O request object + * @type: the type of page I/O: read or write * @pos: the position this I/O request is targeting * @dataoffs: the offset within the page * @datalen: number of data bytes to read from/write to this page @@ -90,6 +101,8 @@ struct nand_pos { * @ooblen: the number of OOB bytes to read from/write to this page * @oobbuf: buffer to store OOB data in or get OOB data from * @mode: one of the %MTD_OPS_XXX mode + * @continuous: no need to start over the operation at the end of each page, the + * NAND device will automatically prepare the next one * * This object is used to pass per-page I/O requests to NAND sub-layers. This * way all useful information are already formatted in a useful way and @@ -97,6 +110,7 @@ struct nand_pos { * specific commands/operations. */ struct nand_page_io_req { + enum nand_page_io_req_type type; struct nand_pos pos; unsigned int dataoffs; unsigned int datalen; @@ -111,6 +125,7 @@ struct nand_page_io_req { void *in; } oobbuf; int mode; + bool continuous; }; /** @@ -272,6 +287,20 @@ nanddev_pages_per_eraseblock(const struct nand_device *nand) } /** + * nanddev_pages_per_target() - Get the number of pages per target + * @nand: NAND device + * + * Return: the number of pages per target. + */ +static inline unsigned int +nanddev_pages_per_target(const struct nand_device *nand) +{ + return nand->memorg.pages_per_eraseblock * + nand->memorg.eraseblocks_per_lun * + nand->memorg.luns_per_target; +} + +/** * nanddev_per_page_oobsize() - Get NAND erase block size * @nand: NAND device * @@ -295,6 +324,18 @@ nanddev_eraseblocks_per_lun(const struct nand_device *nand) } /** + * nanddev_eraseblocks_per_target() - Get the number of eraseblocks per target + * @nand: NAND device + * + * Return: the number of eraseblocks per target. + */ +static inline unsigned int +nanddev_eraseblocks_per_target(const struct nand_device *nand) +{ + return nand->memorg.eraseblocks_per_lun * nand->memorg.luns_per_target; +} + +/** * nanddev_target_size() - Get the total size provided by a single target/die * @nand: NAND device * @@ -320,7 +361,7 @@ static inline unsigned int nanddev_ntargets(const struct nand_device *nand) } /** - * nanddev_neraseblocks() - Get the total number of erasablocks + * nanddev_neraseblocks() - Get the total number of eraseblocks * @nand: NAND device * * Return: the total number of eraseblocks exposed by @nand. @@ -358,6 +399,29 @@ nanddev_get_memorg(struct nand_device *nand) return &nand->memorg; } +/** + * nanddev_get_ecc_conf() - Extract the ECC configuration from a NAND device + * @nand: NAND device + */ +static inline const struct nand_ecc_req * +nanddev_get_ecc_conf(struct nand_device *nand) +{ + return &nand->eccreq; +} + +/** + * nanddev_set_ecc_requirements() - Assign the ECC requirements of a NAND + * device + * @nand: NAND device + * @reqs: Requirements + */ +static inline void +nanddev_set_ecc_requirements(struct nand_device *nand, + const struct nand_ecc_req *reqs) +{ + nand->eccreq = *reqs; +} + int nanddev_init(struct nand_device *nand, const struct nand_ops *ops, struct module *owner); void nanddev_cleanup(struct nand_device *nand); @@ -603,21 +667,23 @@ static inline void nanddev_pos_next_page(struct nand_device *nand, } /** - * nand_io_iter_init - Initialize a NAND I/O iterator + * nand_io_page_iter_init - Initialize a NAND I/O iterator * @nand: NAND device * @offs: absolute offset * @req: MTD request * @iter: NAND I/O iterator * * Initializes a NAND iterator based on the information passed by the MTD - * layer. + * layer for page jumps. */ -static inline void nanddev_io_iter_init(struct nand_device *nand, - loff_t offs, struct mtd_oob_ops *req, - struct nand_io_iter *iter) +static inline void nanddev_io_page_iter_init(struct nand_device *nand, + enum nand_page_io_req_type reqtype, + loff_t offs, struct mtd_oob_ops *req, + struct nand_io_iter *iter) { struct mtd_info *mtd = nanddev_to_mtd(nand); + iter->req.type = reqtype; iter->req.mode = req->mode; iter->req.dataoffs = nanddev_offs_to_pos(nand, offs, &iter->req.pos); iter->req.ooboffs = req->ooboffs; @@ -632,6 +698,43 @@ static inline void nanddev_io_iter_init(struct nand_device *nand, iter->req.ooblen = min_t(unsigned int, iter->oobbytes_per_page - iter->req.ooboffs, iter->oobleft); + iter->req.continuous = false; +} + +/** + * nand_io_block_iter_init - Initialize a NAND I/O iterator + * @nand: NAND device + * @offs: absolute offset + * @req: MTD request + * @iter: NAND I/O iterator + * + * Initializes a NAND iterator based on the information passed by the MTD + * layer for block jumps (no OOB) + * + * In practice only reads may leverage this iterator. + */ +static inline void nanddev_io_block_iter_init(struct nand_device *nand, + enum nand_page_io_req_type reqtype, + loff_t offs, struct mtd_oob_ops *req, + struct nand_io_iter *iter) +{ + unsigned int offs_in_eb; + + iter->req.type = reqtype; + iter->req.mode = req->mode; + iter->req.dataoffs = nanddev_offs_to_pos(nand, offs, &iter->req.pos); + iter->req.ooboffs = 0; + iter->oobbytes_per_page = 0; + iter->dataleft = req->len; + iter->oobleft = 0; + iter->req.databuf.in = req->datbuf; + offs_in_eb = (nand->memorg.pagesize * iter->req.pos.page) + iter->req.dataoffs; + iter->req.datalen = min_t(unsigned int, + nanddev_eraseblock_size(nand) - offs_in_eb, + iter->dataleft); + iter->req.oobbuf.in = NULL; + iter->req.ooblen = 0; + iter->req.continuous = true; } /** @@ -658,6 +761,25 @@ static inline void nanddev_io_iter_next_page(struct nand_device *nand, } /** + * nand_io_iter_next_block - Move to the next block + * @nand: NAND device + * @iter: NAND I/O iterator + * + * Updates the @iter to point to the next block. + * No OOB handling available. + */ +static inline void nanddev_io_iter_next_block(struct nand_device *nand, + struct nand_io_iter *iter) +{ + nanddev_pos_next_eraseblock(nand, &iter->req.pos); + iter->dataleft -= iter->req.datalen; + iter->req.databuf.in += iter->req.datalen; + iter->req.dataoffs = 0; + iter->req.datalen = min_t(unsigned int, nanddev_eraseblock_size(nand), + iter->dataleft); +} + +/** * nand_io_iter_end - Should end iteration or not * @nand: NAND device * @iter: NAND I/O iterator @@ -685,13 +807,28 @@ static inline bool nanddev_io_iter_end(struct nand_device *nand, * @req: MTD I/O request * @iter: NAND I/O iterator * - * Should be used for iterate over pages that are contained in an MTD request. + * Should be used for iterating over pages that are contained in an MTD request. */ -#define nanddev_io_for_each_page(nand, start, req, iter) \ - for (nanddev_io_iter_init(nand, start, req, iter); \ +#define nanddev_io_for_each_page(nand, type, start, req, iter) \ + for (nanddev_io_page_iter_init(nand, type, start, req, iter); \ !nanddev_io_iter_end(nand, iter); \ nanddev_io_iter_next_page(nand, iter)) +/** + * nand_io_for_each_block - Iterate over all NAND pages contained in an MTD I/O + * request, one block at a time + * @nand: NAND device + * @start: start address to read/write from + * @req: MTD I/O request + * @iter: NAND I/O iterator + * + * Should be used for iterating over blocks that are contained in an MTD request. + */ +#define nanddev_io_for_each_block(nand, type, start, req, iter) \ + for (nanddev_io_block_iter_init(nand, type, start, req, iter); \ + !nanddev_io_iter_end(nand, iter); \ + nanddev_io_iter_next_block(nand, iter)) + bool nanddev_isbad(struct nand_device *nand, const struct nand_pos *pos); bool nanddev_isreserved(struct nand_device *nand, const struct nand_pos *pos); int nanddev_markbad(struct nand_device *nand, const struct nand_pos *pos); diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 6fe6fd520a4..cf9b9656d05 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -26,126 +26,218 @@ * Standard SPI NAND flash operations */ -#define SPINAND_RESET_OP \ +#define SPINAND_RESET_1S_0_0_OP \ SPI_MEM_OP(SPI_MEM_OP_CMD(0xff, 1), \ SPI_MEM_OP_NO_ADDR, \ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_NO_DATA) -#define SPINAND_WR_EN_DIS_OP(enable) \ +#define SPINAND_WR_EN_DIS_1S_0_0_OP(enable) \ SPI_MEM_OP(SPI_MEM_OP_CMD((enable) ? 0x06 : 0x04, 1), \ SPI_MEM_OP_NO_ADDR, \ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_NO_DATA) -#define SPINAND_READID_OP(naddr, ndummy, buf, len) \ +#define SPINAND_READID_1S_1S_1S_OP(naddr, ndummy, buf, len) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0x9f, 1), \ SPI_MEM_OP_ADDR(naddr, 0, 1), \ SPI_MEM_OP_DUMMY(ndummy, 1), \ SPI_MEM_OP_DATA_IN(len, buf, 1)) -#define SPINAND_SET_FEATURE_OP(reg, valptr) \ +#define SPINAND_SET_FEATURE_1S_1S_1S_OP(reg, valptr) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0x1f, 1), \ SPI_MEM_OP_ADDR(1, reg, 1), \ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_DATA_OUT(1, valptr, 1)) -#define SPINAND_GET_FEATURE_OP(reg, valptr) \ +#define SPINAND_GET_FEATURE_1S_1S_1S_OP(reg, valptr) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0x0f, 1), \ SPI_MEM_OP_ADDR(1, reg, 1), \ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_DATA_IN(1, valptr, 1)) -#define SPINAND_BLK_ERASE_OP(addr) \ +#define SPINAND_BLK_ERASE_1S_1S_0_OP(addr) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0xd8, 1), \ SPI_MEM_OP_ADDR(3, addr, 1), \ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_NO_DATA) -#define SPINAND_PAGE_READ_OP(addr) \ +#define SPINAND_PAGE_READ_1S_1S_0_OP(addr) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0x13, 1), \ SPI_MEM_OP_ADDR(3, addr, 1), \ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_NO_DATA) -#define SPINAND_PAGE_READ_FROM_CACHE_OP(fast, addr, ndummy, buf, len) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1), \ +#define SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x03, 1), \ SPI_MEM_OP_ADDR(2, addr, 1), \ SPI_MEM_OP_DUMMY(ndummy, 1), \ - SPI_MEM_OP_DATA_IN(len, buf, 1)) + SPI_MEM_OP_DATA_IN(len, buf, 1), \ + SPI_MEM_OP_MAX_FREQ(freq)) -#define SPINAND_PAGE_READ_FROM_CACHE_OP_3A(fast, addr, ndummy, buf, len) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1), \ - SPI_MEM_OP_ADDR(3, addr, 1), \ +#define SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x0b, 1), \ + SPI_MEM_OP_ADDR(2, addr, 1), \ SPI_MEM_OP_DUMMY(ndummy, 1), \ - SPI_MEM_OP_DATA_IN(len, buf, 1)) + SPI_MEM_OP_DATA_IN(len, buf, 1), \ + SPI_MEM_OP_MAX_FREQ(freq)) -#define SPINAND_PAGE_READ_FROM_CACHE_X2_OP(addr, ndummy, buf, len) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \ - SPI_MEM_OP_ADDR(2, addr, 1), \ +#define SPINAND_PAGE_READ_FROM_CACHE_3A_1S_1S_1S_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x03, 1), \ + SPI_MEM_OP_ADDR(3, addr, 1), \ SPI_MEM_OP_DUMMY(ndummy, 1), \ - SPI_MEM_OP_DATA_IN(len, buf, 2)) + SPI_MEM_OP_DATA_IN(len, buf, 1), \ + SPI_MEM_OP_MAX_FREQ(freq)) -#define SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(addr, ndummy, buf, len) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \ +#define SPINAND_PAGE_READ_FROM_CACHE_FAST_3A_1S_1S_1S_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x0b, 1), \ SPI_MEM_OP_ADDR(3, addr, 1), \ SPI_MEM_OP_DUMMY(ndummy, 1), \ - SPI_MEM_OP_DATA_IN(len, buf, 2)) + SPI_MEM_OP_DATA_IN(len, buf, 1), \ + SPI_MEM_OP_MAX_FREQ(freq)) -#define SPINAND_PAGE_READ_FROM_CACHE_X4_OP(addr, ndummy, buf, len) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \ +#define SPINAND_PAGE_READ_FROM_CACHE_1S_1D_1D_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x0d, 1), \ + SPI_MEM_DTR_OP_ADDR(2, addr, 1), \ + SPI_MEM_DTR_OP_DUMMY(ndummy, 1), \ + SPI_MEM_DTR_OP_DATA_IN(len, buf, 1), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define SPINAND_PAGE_READ_FROM_CACHE_1S_1S_2S_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \ SPI_MEM_OP_ADDR(2, addr, 1), \ SPI_MEM_OP_DUMMY(ndummy, 1), \ - SPI_MEM_OP_DATA_IN(len, buf, 4)) + SPI_MEM_OP_DATA_IN(len, buf, 2), \ + SPI_MEM_OP_MAX_FREQ(freq)) -#define SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(addr, ndummy, buf, len) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \ +#define SPINAND_PAGE_READ_FROM_CACHE_3A_1S_1S_2S_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \ SPI_MEM_OP_ADDR(3, addr, 1), \ SPI_MEM_OP_DUMMY(ndummy, 1), \ - SPI_MEM_OP_DATA_IN(len, buf, 4)) + SPI_MEM_OP_DATA_IN(len, buf, 2), \ + SPI_MEM_OP_MAX_FREQ(freq)) -#define SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(addr, ndummy, buf, len) \ +#define SPINAND_PAGE_READ_FROM_CACHE_1S_1D_2D_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x3d, 1), \ + SPI_MEM_DTR_OP_ADDR(2, addr, 1), \ + SPI_MEM_DTR_OP_DUMMY(ndummy, 1), \ + SPI_MEM_DTR_OP_DATA_IN(len, buf, 2), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(addr, ndummy, buf, len, freq) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \ SPI_MEM_OP_ADDR(2, addr, 2), \ SPI_MEM_OP_DUMMY(ndummy, 2), \ - SPI_MEM_OP_DATA_IN(len, buf, 2)) + SPI_MEM_OP_DATA_IN(len, buf, 2), \ + SPI_MEM_OP_MAX_FREQ(freq)) -#define SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP_3A(addr, ndummy, buf, len) \ +#define SPINAND_PAGE_READ_FROM_CACHE_3A_1S_2S_2S_OP(addr, ndummy, buf, len, freq) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \ SPI_MEM_OP_ADDR(3, addr, 2), \ SPI_MEM_OP_DUMMY(ndummy, 2), \ - SPI_MEM_OP_DATA_IN(len, buf, 2)) + SPI_MEM_OP_DATA_IN(len, buf, 2), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define SPINAND_PAGE_READ_FROM_CACHE_1S_2D_2D_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0xbd, 1), \ + SPI_MEM_DTR_OP_ADDR(2, addr, 2), \ + SPI_MEM_DTR_OP_DUMMY(ndummy, 2), \ + SPI_MEM_DTR_OP_DATA_IN(len, buf, 2), \ + SPI_MEM_OP_MAX_FREQ(freq)) -#define SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(addr, ndummy, buf, len) \ +#define SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \ + SPI_MEM_OP_ADDR(2, addr, 1), \ + SPI_MEM_OP_DUMMY(ndummy, 1), \ + SPI_MEM_OP_DATA_IN(len, buf, 4), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define SPINAND_PAGE_READ_FROM_CACHE_3A_1S_1S_4S_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \ + SPI_MEM_OP_ADDR(3, addr, 1), \ + SPI_MEM_OP_DUMMY(ndummy, 1), \ + SPI_MEM_OP_DATA_IN(len, buf, 4), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define SPINAND_PAGE_READ_FROM_CACHE_1S_1D_4D_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x6d, 1), \ + SPI_MEM_DTR_OP_ADDR(2, addr, 1), \ + SPI_MEM_DTR_OP_DUMMY(ndummy, 1), \ + SPI_MEM_DTR_OP_DATA_IN(len, buf, 4), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(addr, ndummy, buf, len, freq) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1), \ SPI_MEM_OP_ADDR(2, addr, 4), \ SPI_MEM_OP_DUMMY(ndummy, 4), \ - SPI_MEM_OP_DATA_IN(len, buf, 4)) + SPI_MEM_OP_DATA_IN(len, buf, 4), \ + SPI_MEM_OP_MAX_FREQ(freq)) -#define SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP_3A(addr, ndummy, buf, len) \ +#define SPINAND_PAGE_READ_FROM_CACHE_3A_1S_4S_4S_OP(addr, ndummy, buf, len, freq) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1), \ SPI_MEM_OP_ADDR(3, addr, 4), \ SPI_MEM_OP_DUMMY(ndummy, 4), \ - SPI_MEM_OP_DATA_IN(len, buf, 4)) - -#define SPINAND_PROG_EXEC_OP(addr) \ + SPI_MEM_OP_DATA_IN(len, buf, 4), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define SPINAND_PAGE_READ_FROM_CACHE_1S_4D_4D_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0xed, 1), \ + SPI_MEM_DTR_OP_ADDR(2, addr, 4), \ + SPI_MEM_DTR_OP_DUMMY(ndummy, 4), \ + SPI_MEM_DTR_OP_DATA_IN(len, buf, 4), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define SPINAND_PAGE_READ_FROM_CACHE_1S_1S_8S_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x8b, 1), \ + SPI_MEM_OP_ADDR(2, addr, 1), \ + SPI_MEM_OP_DUMMY(ndummy, 1), \ + SPI_MEM_OP_DATA_IN(len, buf, 8), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define SPINAND_PAGE_READ_FROM_CACHE_1S_8S_8S_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0xcb, 1), \ + SPI_MEM_OP_ADDR(2, addr, 8), \ + SPI_MEM_OP_DUMMY(ndummy, 8), \ + SPI_MEM_OP_DATA_IN(len, buf, 8), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define SPINAND_PAGE_READ_FROM_CACHE_1S_1D_8D_OP(addr, ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x9d, 1), \ + SPI_MEM_DTR_OP_ADDR(2, addr, 1), \ + SPI_MEM_DTR_OP_DUMMY(ndummy, 1), \ + SPI_MEM_DTR_OP_DATA_IN(len, buf, 8), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define SPINAND_PROG_EXEC_1S_1S_0_OP(addr) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0x10, 1), \ SPI_MEM_OP_ADDR(3, addr, 1), \ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_NO_DATA) -#define SPINAND_PROG_LOAD(reset, addr, buf, len) \ +#define SPINAND_PROG_LOAD_1S_1S_1S_OP(reset, addr, buf, len) \ SPI_MEM_OP(SPI_MEM_OP_CMD(reset ? 0x02 : 0x84, 1), \ SPI_MEM_OP_ADDR(2, addr, 1), \ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_DATA_OUT(len, buf, 1)) -#define SPINAND_PROG_LOAD_X4(reset, addr, buf, len) \ +#define SPINAND_PROG_LOAD_1S_1S_4S_OP(reset, addr, buf, len) \ SPI_MEM_OP(SPI_MEM_OP_CMD(reset ? 0x32 : 0x34, 1), \ SPI_MEM_OP_ADDR(2, addr, 1), \ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_DATA_OUT(len, buf, 4)) +#define SPINAND_PROG_LOAD_1S_1S_8S_OP(addr, buf, len) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x82, 1), \ + SPI_MEM_OP_ADDR(2, addr, 1), \ + SPI_MEM_OP_NO_DUMMY, \ + SPI_MEM_OP_DATA_OUT(len, buf, 8)) + +#define SPINAND_PROG_LOAD_1S_8S_8S_OP(reset, addr, buf, len) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(reset ? 0xc2 : 0xc4, 1), \ + SPI_MEM_OP_ADDR(2, addr, 8), \ + SPI_MEM_OP_NO_DUMMY, \ + SPI_MEM_OP_DATA_OUT(len, buf, 8)) + /** * Standard SPI NAND flash commands */ @@ -175,7 +267,29 @@ struct spinand_op; struct spinand_device; -#define SPINAND_MAX_ID_LEN 4 +#define SPINAND_MAX_ID_LEN 5 +/* + * For erase, write and read operation, we got the following timings : + * tBERS (erase) 1ms to 4ms + * tPROG 300us to 400us + * tREAD 25us to 100us + * In order to minimize latency, the min value is divided by 4 for the + * initial delay, and dividing by 20 for the poll delay. + * For reset, 5us/10us/500us if the device is respectively + * reading/programming/erasing when the RESET occurs. Since we always + * issue a RESET when the device is IDLE, 5us is selected for both initial + * and poll delay. + */ +#define SPINAND_READ_INITIAL_DELAY_US 6 +#define SPINAND_READ_POLL_DELAY_US 5 +#define SPINAND_RESET_INITIAL_DELAY_US 5 +#define SPINAND_RESET_POLL_DELAY_US 5 +#define SPINAND_WRITE_INITIAL_DELAY_US 75 +#define SPINAND_WRITE_POLL_DELAY_US 15 +#define SPINAND_ERASE_INITIAL_DELAY_US 250 +#define SPINAND_ERASE_POLL_DELAY_US 50 + +#define SPINAND_WAITRDY_TIMEOUT_MS 400 /** * struct spinand_id - SPI NAND id structure @@ -244,13 +358,17 @@ struct spinand_manufacturer { }; /* SPI NAND manufacturers */ +extern const struct spinand_manufacturer alliancememory_spinand_manufacturer; +extern const struct spinand_manufacturer ato_spinand_manufacturer; +extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; +extern const struct spinand_manufacturer foresee_spinand_manufacturer; extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; extern const struct spinand_manufacturer macronix_spinand_manufacturer; extern const struct spinand_manufacturer micron_spinand_manufacturer; extern const struct spinand_manufacturer paragon_spinand_manufacturer; +extern const struct spinand_manufacturer skyhigh_spinand_manufacturer; extern const struct spinand_manufacturer toshiba_spinand_manufacturer; extern const struct spinand_manufacturer winbond_spinand_manufacturer; -extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; extern const struct spinand_manufacturer xtx_spinand_manufacturer; /** @@ -291,8 +409,73 @@ struct spinand_ecc_info { const struct mtd_ooblayout_ops *ooblayout; }; -#define SPINAND_HAS_QE_BIT BIT(0) -#define SPINAND_HAS_CR_FEAT_BIT BIT(1) +#define SPINAND_HAS_QE_BIT BIT(0) +#define SPINAND_HAS_CR_FEAT_BIT BIT(1) +#define SPINAND_HAS_PROG_PLANE_SELECT_BIT BIT(2) +#define SPINAND_HAS_READ_PLANE_SELECT_BIT BIT(3) +#define SPINAND_NO_RAW_ACCESS BIT(4) + +/** + * struct spinand_otp_layout - structure to describe the SPI NAND OTP area + * @npages: number of pages in the OTP + * @start_page: start page of the user/factory OTP area. + */ +struct spinand_otp_layout { + unsigned int npages; + unsigned int start_page; +}; + +/** + * struct spinand_fact_otp_ops - SPI NAND OTP methods for factory area + * @info: get the OTP area information + * @read: read from the SPI NAND OTP area + */ +struct spinand_fact_otp_ops { + int (*info)(struct spinand_device *spinand, size_t len, + struct otp_info *buf, size_t *retlen); + int (*read)(struct spinand_device *spinand, loff_t from, size_t len, + size_t *retlen, u8 *buf); +}; + +/** + * struct spinand_user_otp_ops - SPI NAND OTP methods for user area + * @info: get the OTP area information + * @lock: lock an OTP region + * @erase: erase an OTP region + * @read: read from the SPI NAND OTP area + * @write: write to the SPI NAND OTP area + */ +struct spinand_user_otp_ops { + int (*info)(struct spinand_device *spinand, size_t len, + struct otp_info *buf, size_t *retlen); + int (*lock)(struct spinand_device *spinand, loff_t from, size_t len); + int (*erase)(struct spinand_device *spinand, loff_t from, size_t len); + int (*read)(struct spinand_device *spinand, loff_t from, size_t len, + size_t *retlen, u8 *buf); + int (*write)(struct spinand_device *spinand, loff_t from, size_t len, + size_t *retlen, const u8 *buf); +}; + +/** + * struct spinand_fact_otp - SPI NAND OTP grouping structure for factory area + * @layout: OTP region layout + * @ops: OTP access ops + */ +struct spinand_fact_otp { + const struct spinand_otp_layout layout; + const struct spinand_fact_otp_ops *ops; +}; + +/** + * struct spinand_user_otp - SPI NAND OTP grouping structure for user area + * @layout: OTP region layout + * @ops: OTP access ops + */ +struct spinand_user_otp { + const struct spinand_otp_layout layout; + const struct spinand_user_otp_ops *ops; +}; + /** * struct spinand_info - Structure used to describe SPI NAND chips @@ -308,6 +491,12 @@ struct spinand_ecc_info { * @op_variants.update_cache: variants of the update-cache operation * @select_target: function used to select a target/die. Required only for * multi-die chips + * @configure_chip: Align the chip configuration with the core settings + * @set_cont_read: enable/disable continuous cached reads + * @fact_otp: SPI NAND factory OTP info. + * @user_otp: SPI NAND user OTP info. + * @read_retries: the number of read retry modes supported + * @set_read_retry: enable/disable read retry for data recovery * * Each SPI NAND manufacturer driver should have a spinand_info table * describing all the chips supported by the driver. @@ -326,6 +515,14 @@ struct spinand_info { } op_variants; int (*select_target)(struct spinand_device *spinand, unsigned int target); + int (*configure_chip)(struct spinand_device *spinand); + int (*set_cont_read)(struct spinand_device *spinand, + bool enable); + struct spinand_fact_otp fact_otp; + struct spinand_user_otp user_otp; + unsigned int read_retries; + int (*set_read_retry)(struct spinand_device *spinand, + unsigned int read_retry); }; #define SPINAND_ID(__method, ...) \ @@ -349,7 +546,35 @@ struct spinand_info { } #define SPINAND_SELECT_TARGET(__func) \ - .select_target = __func, + .select_target = __func + +#define SPINAND_CONFIGURE_CHIP(__configure_chip) \ + .configure_chip = __configure_chip + +#define SPINAND_CONT_READ(__set_cont_read) \ + .set_cont_read = __set_cont_read + +#define SPINAND_FACT_OTP_INFO(__npages, __start_page, __ops) \ + .fact_otp = { \ + .layout = { \ + .npages = __npages, \ + .start_page = __start_page, \ + }, \ + .ops = __ops, \ + } + +#define SPINAND_USER_OTP_INFO(__npages, __start_page, __ops) \ + .user_otp = { \ + .layout = { \ + .npages = __npages, \ + .start_page = __start_page, \ + }, \ + .ops = __ops, \ + } + +#define SPINAND_READ_RETRY(__read_retries, __set_read_retry) \ + .read_retries = __read_retries, \ + .set_read_retry = __set_read_retry #define SPINAND_INFO(__model, __id, __memorg, __eccreq, __op_variants, \ __flags, ...) \ @@ -363,6 +588,13 @@ struct spinand_info { __VA_ARGS__ \ } +struct spinand_dirmap { + struct spi_mem_dirmap_desc *wdesc; + struct spi_mem_dirmap_desc *rdesc; + struct spi_mem_dirmap_desc *wdesc_ecc; + struct spi_mem_dirmap_desc *rdesc_ecc; +}; + /** * struct spinand_device - SPI NAND device instance * @base: NAND device instance @@ -387,7 +619,20 @@ struct spinand_info { * passed in spi_mem_op be DMA-able, so we can't based the bufs on * the stack * @manufacturer: SPI NAND manufacturer information + * @configure_chip: Align the chip configuration with the core settings + * @cont_read_possible: Field filled by the core once the whole system + * configuration is known to tell whether continuous reads are + * suitable to use or not in general with this chip/configuration. + * A per-transfer check must of course be done to ensure it is + * actually relevant to enable this feature. + * @set_cont_read: Enable/disable the continuous read feature * @priv: manufacturer private data + * @fact_otp: SPI NAND factory OTP info. + * @user_otp: SPI NAND user OTP info. + * @read_retries: the number of read retry modes supported + * @set_read_retry: Enable/disable the read retry feature + * @last_wait_status: status of the last wait operation that will be used in case + * ->get_status() is not populated by the spinand device. */ struct spinand_device { struct nand_device base; @@ -406,6 +651,8 @@ struct spinand_device { const struct spi_mem_op *update_cache; } op_templates; + struct spinand_dirmap *dirmaps; + int (*select_target)(struct spinand_device *spinand, unsigned int target); unsigned int cur_target; @@ -418,6 +665,20 @@ struct spinand_device { u8 *scratchbuf; const struct spinand_manufacturer *manufacturer; void *priv; + + u8 last_wait_status; + + int (*configure_chip)(struct spinand_device *spinand); + bool cont_read_possible; + int (*set_cont_read)(struct spinand_device *spinand, + bool enable); + + const struct spinand_fact_otp *fact_otp; + const struct spinand_user_otp *user_otp; + + unsigned int read_retries; + int (*set_read_retry)(struct spinand_device *spinand, + unsigned int retry_mode); }; /** @@ -499,6 +760,31 @@ int spinand_match_and_init(struct spinand_device *spinand, enum spinand_readid_method rdid_method); int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val); +int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val); +int spinand_write_reg_op(struct spinand_device *spinand, u8 reg, u8 val); +int spinand_write_enable_op(struct spinand_device *spinand); int spinand_select_target(struct spinand_device *spinand, unsigned int target); +int spinand_wait(struct spinand_device *spinand, unsigned long initial_delay_us, + unsigned long poll_delay_us, u8 *s); + +int spinand_read_page(struct spinand_device *spinand, + const struct nand_page_io_req *req); + +int spinand_write_page(struct spinand_device *spinand, + const struct nand_page_io_req *req); + +size_t spinand_otp_page_size(struct spinand_device *spinand); +size_t spinand_fact_otp_size(struct spinand_device *spinand); +size_t spinand_user_otp_size(struct spinand_device *spinand); + +int spinand_fact_otp_read(struct spinand_device *spinand, loff_t ofs, + size_t len, size_t *retlen, u8 *buf); +int spinand_user_otp_read(struct spinand_device *spinand, loff_t ofs, + size_t len, size_t *retlen, u8 *buf); +int spinand_user_otp_write(struct spinand_device *spinand, loff_t ofs, + size_t len, size_t *retlen, const u8 *buf); + +int spinand_set_mtd_otp_ops(struct spinand_device *spinand); + #endif /* __LINUX_MTD_SPINAND_H */ diff --git a/include/malloc.h b/include/malloc.h index 9e0be482416..3979fc62830 100644 --- a/include/malloc.h +++ b/include/malloc.h @@ -904,11 +904,11 @@ void *realloc_simple(void *ptr, size_t size); # define mALLOPt dlmallopt /* Ensure that U-Boot actually uses these too */ -#define calloc dlcalloc +#define calloc(x,y) dlcalloc(x,y) #define free(ptr) dlfree(ptr) #define malloc(x) dlmalloc(x) -#define memalign dlmemalign -#define realloc dlrealloc +#define memalign(a,x) dlmemalign(a,x) +#define realloc(p,x) dlrealloc(p,x) #define valloc dlvalloc #define pvalloc dlpvalloc #define mallinfo() dlmallinfo() diff --git a/include/miiphy.h b/include/miiphy.h index 00d0b9b6a43..96afe5f4030 100644 --- a/include/miiphy.h +++ b/include/miiphy.h @@ -193,6 +193,21 @@ struct phy_device *dm_mdio_phy_connect(struct udevice *mdiodev, int phyaddr, phy_interface_t interface); /** + * dm_eth_phy_connect_interface - Connect an Eth device to a PHY based on device + * tree with custom PHY interface + * + * Picks up the DT phy-handle and from ethernet device node and connects the + * ethernet device to the linked PHY, while allowing the caller to specify + * the phy-mode to use. + * + * @ethdev: ethernet device + * @interface: MAC-PHY protocol + * + * Return: pointer to phy_device, or 0 on error + */ +struct phy_device *dm_eth_phy_connect_interface(struct udevice *ethdev, + phy_interface_t interface); +/** * dm_eth_phy_connect - Connect an Eth device to a PHY based on device tree * * Picks up the DT phy-handle and phy-mode from ethernet device node and diff --git a/include/scmi_nxp_protocols.h b/include/scmi_nxp_protocols.h new file mode 100644 index 00000000000..fe6ecd6a7cf --- /dev/null +++ b/include/scmi_nxp_protocols.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* + * Copyright 2025 NXP + */ + +#ifndef _SCMI_NXP_PROTOCOLS_H +#define _SCMI_NXP_PROTOCOLS_H + +#include <asm/types.h> +#include <linux/bitops.h> + +enum scmi_imx_protocol { + SCMI_IMX_PROTOCOL_ID_MISC = 0x84, +}; + +#define SCMI_PAYLOAD_LEN 100 + +#define SCMI_ARRAY(X, Y) ((SCMI_PAYLOAD_LEN - (X)) / sizeof(Y)) + +#define SCMI_IMX_MISC_RESET_REASON 0xA + +struct scmi_imx_misc_reset_reason_in { +#define MISC_REASON_FLAG_SYSTEM BIT(0) + u32 flags; +}; + +struct scmi_imx_misc_reset_reason_out { + s32 status; + /* Boot reason flags */ +#define MISC_BOOT_FLAG_VLD BIT(31) +#define MISC_BOOT_FLAG_ORG_VLD BIT(28) +#define MISC_BOOT_FLAG_ORIGIN GENMASK(27, 24) +#define MISC_BOOT_FLAG_O_SHIFT 24 +#define MISC_BOOT_FLAG_ERR_VLD BIT(23) +#define MISC_BOOT_FLAG_ERR_ID GENMASK(22, 8) +#define MISC_BOOT_FLAG_E_SHIFT 8 +#define MISC_BOOT_FLAG_REASON GENMASK(7, 0) + u32 bootflags; + /* Shutdown reason flags */ +#define MISC_SHUTDOWN_FLAG_VLD BIT(31) +#define MISC_SHUTDOWN_FLAG_EXT_LEN GENMASK(30, 29) +#define MISC_SHUTDOWN_FLAG_ORG_VLD BIT(28) +#define MISC_SHUTDOWN_FLAG_ORIGIN GENMASK(27, 24) +#define MISC_SHUTDOWN_FLAG_O_SHIFT 24 +#define MISC_SHUTDOWN_FLAG_ERR_VLD BIT(23) +#define MISC_SHUTDOWN_FLAG_ERR_ID GENMASK(22, 8) +#define MISC_SHUTDOWN_FLAG_E_SHIFT 8 +#define MISC_SHUTDOWN_FLAG_REASON GENMASK(7, 0) + u32 shutdownflags; + /* Array of extended info words */ +#define MISC_MAX_EXTINFO SCMI_ARRAY(16, u32) + u32 extInfo[MISC_MAX_EXTINFO]; +}; + +#endif diff --git a/include/spi-mem.h b/include/spi-mem.h index 2eb05a2e5bc..36281a62f77 100644 --- a/include/spi-mem.h +++ b/include/spi-mem.h @@ -17,16 +17,32 @@ struct udevice; #define SPI_MEM_OP_CMD(__opcode, __buswidth) \ { \ + .nbytes = 1, \ .buswidth = __buswidth, \ .opcode = __opcode, \ + } + +#define SPI_MEM_DTR_OP_CMD(__opcode, __buswidth) \ + { \ .nbytes = 1, \ + .opcode = __opcode, \ + .buswidth = __buswidth, \ + .dtr = true, \ } #define SPI_MEM_OP_ADDR(__nbytes, __val, __buswidth) \ { \ .nbytes = __nbytes, \ + .buswidth = __buswidth, \ + .val = __val, \ + } + +#define SPI_MEM_DTR_OP_ADDR(__nbytes, __val, __buswidth) \ + { \ + .nbytes = __nbytes, \ .val = __val, \ .buswidth = __buswidth, \ + .dtr = true, \ } #define SPI_MEM_OP_NO_ADDR { } @@ -37,22 +53,47 @@ struct udevice; .buswidth = __buswidth, \ } +#define SPI_MEM_DTR_OP_DUMMY(__nbytes, __buswidth) \ + { \ + .nbytes = __nbytes, \ + .buswidth = __buswidth, \ + .dtr = true, \ + } + #define SPI_MEM_OP_NO_DUMMY { } #define SPI_MEM_OP_DATA_IN(__nbytes, __buf, __buswidth) \ { \ + .buswidth = __buswidth, \ + .dir = SPI_MEM_DATA_IN, \ + .nbytes = __nbytes, \ + .buf.in = __buf, \ + } + +#define SPI_MEM_DTR_OP_DATA_IN(__nbytes, __buf, __buswidth) \ + { \ .dir = SPI_MEM_DATA_IN, \ .nbytes = __nbytes, \ .buf.in = __buf, \ .buswidth = __buswidth, \ + .dtr = true, \ } #define SPI_MEM_OP_DATA_OUT(__nbytes, __buf, __buswidth) \ { \ + .buswidth = __buswidth, \ + .dir = SPI_MEM_DATA_OUT, \ + .nbytes = __nbytes, \ + .buf.out = __buf, \ + } + +#define SPI_MEM_DTR_OP_DATA_OUT(__nbytes, __buf, __buswidth) \ + { \ .dir = SPI_MEM_DATA_OUT, \ .nbytes = __nbytes, \ .buf.out = __buf, \ .buswidth = __buswidth, \ + .dtr = true, \ } #define SPI_MEM_OP_NO_DATA { } @@ -62,7 +103,7 @@ struct udevice; * transfer from the controller perspective * @SPI_MEM_NO_DATA: no data transferred * @SPI_MEM_DATA_IN: data coming from the SPI memory - * @SPI_MEM_DATA_OUT: data sent the SPI memory + * @SPI_MEM_DATA_OUT: data sent to the SPI memory */ enum spi_mem_data_dir { SPI_MEM_NO_DATA, @@ -70,6 +111,9 @@ enum spi_mem_data_dir { SPI_MEM_DATA_OUT, }; +#define SPI_MEM_OP_MAX_FREQ(__freq) \ + .max_freq = __freq + /** * struct spi_mem_op - describes a SPI memory operation * @cmd.nbytes: number of opcode bytes (only 1 or 2 are valid). The opcode is @@ -80,26 +124,35 @@ enum spi_mem_data_dir { * @addr.nbytes: number of address bytes to send. Can be zero if the operation * does not need to send an address * @addr.buswidth: number of IO lines used to transmit the address cycles + * @addr.dtr: whether the address should be sent in DTR mode or not * @addr.val: address value. This value is always sent MSB first on the bus. * Note that only @addr.nbytes are taken into account in this * address value, so users should make sure the value fits in the * assigned number of bytes. - * @addr.dtr: whether the address should be sent in DTR mode or not * @dummy.nbytes: number of dummy bytes to send after an opcode or address. Can * be zero if the operation does not require dummy bytes * @dummy.buswidth: number of IO lanes used to transmit the dummy bytes * @dummy.dtr: whether the dummy bytes should be sent in DTR mode or not * @data.buswidth: number of IO lanes used to send/receive the data * @data.dtr: whether the data should be sent in DTR mode or not + * @data.ecc: whether error correction is required or not + * @data.swap16: whether the byte order of 16-bit words is swapped when read + * or written in Octal DTR mode compared to STR mode. * @data.dir: direction of the transfer - * @data.buf.in: input buffer - * @data.buf.out: output buffer + * @data.nbytes: number of data bytes to send/receive. Can be zero if the + * operation does not involve transferring data + * @data.buf.in: input buffer (must be DMA-able) + * @data.buf.out: output buffer (must be DMA-able) + * @max_freq: frequency limitation wrt this operation. 0 means there is no + * specific constraint and the highest achievable frequency can be + * attempted. */ struct spi_mem_op { struct { u8 nbytes; u8 buswidth; u8 dtr : 1; + u8 __pad : 7; u16 opcode; } cmd; @@ -107,6 +160,7 @@ struct spi_mem_op { u8 nbytes; u8 buswidth; u8 dtr : 1; + u8 __pad : 7; u64 val; } addr; @@ -114,28 +168,35 @@ struct spi_mem_op { u8 nbytes; u8 buswidth; u8 dtr : 1; + u8 __pad : 7; } dummy; struct { u8 buswidth; u8 dtr : 1; + u8 ecc : 1; + u8 swap16 : 1; + u8 __pad : 5; enum spi_mem_data_dir dir; unsigned int nbytes; - /* buf.{in,out} must be DMA-able. */ union { void *in; const void *out; } buf; } data; + + unsigned int max_freq; }; -#define SPI_MEM_OP(__cmd, __addr, __dummy, __data) \ +#define SPI_MEM_OP(__cmd, __addr, __dummy, __data, ...) \ { \ .cmd = __cmd, \ .addr = __addr, \ .dummy = __dummy, \ .data = __data, \ + __VA_ARGS__ \ } + /** * struct spi_mem_dirmap_info - Direct mapping information * @op_tmpl: operation template that should be used by the direct mapping when @@ -143,7 +204,7 @@ struct spi_mem_op { * @offset: absolute offset this direct mapping is pointing to * @length: length in byte of this direct mapping * - * This information is used by the controller specific implementation to know + * These information are used by the controller specific implementation to know * the portion of memory that is directly mapped and the spi_mem_op that should * be used to access the device. * A direct mapping is only valid for one direction (read or write) and this @@ -223,10 +284,12 @@ static inline void *spi_mem_get_drvdata(struct spi_mem *mem) /** * struct spi_controller_mem_ops - SPI memory operations * @adjust_op_size: shrink the data xfer of an operation to match controller's - * limitations (can be alignment of max RX/TX size + * limitations (can be alignment or max RX/TX size * limitations) * @supports_op: check if an operation is supported by the controller * @exec_op: execute a SPI memory operation + * not all driver provides supports_op(), so it can return -EOPNOTSUPP + * if the op is not supported by the driver/controller * @dirmap_create: create a direct mapping descriptor that can later be used to * access the memory device. This method is optional * @dirmap_destroy: destroy a memory descriptor previous created by @@ -300,13 +363,16 @@ int spi_controller_dma_map_mem_op_data(struct spi_controller *ctlr, void spi_controller_dma_unmap_mem_op_data(struct spi_controller *ctlr, const struct spi_mem_op *op, struct sg_table *sg); + +bool spi_mem_default_supports_op(struct spi_mem *mem, + const struct spi_mem_op *op); #else static inline int spi_controller_dma_map_mem_op_data(struct spi_controller *ctlr, const struct spi_mem_op *op, struct sg_table *sg) { - return -ENOSYS; + return -ENOTSUPP; } static inline void @@ -315,10 +381,18 @@ spi_controller_dma_unmap_mem_op_data(struct spi_controller *ctlr, struct sg_table *sg) { } + +static inline +bool spi_mem_default_supports_op(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + return false; +} #endif /* CONFIG_SPI_MEM */ #endif /* __UBOOT__ */ int spi_mem_adjust_op_size(struct spi_slave *slave, struct spi_mem_op *op); +u64 spi_mem_calc_op_duration(struct spi_mem_op *op); bool spi_mem_supports_op(struct spi_slave *slave, const struct spi_mem_op *op); bool spi_mem_dtr_supports_op(struct spi_slave *slave, @@ -337,7 +411,6 @@ ssize_t spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offs, size_t len, void *buf); ssize_t spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc, u64 offs, size_t len, const void *buf); - #ifndef __UBOOT__ int spi_mem_driver_register_with_owner(struct spi_mem_driver *drv, struct module *owner); diff --git a/include/thermal.h b/include/thermal.h index 52a3317fd54..74b1c62466b 100644 --- a/include/thermal.h +++ b/include/thermal.h @@ -25,7 +25,7 @@ struct dm_thermal_ops { * It will enable and initialize any Thermal hardware as necessary. * * @dev: The Thermal device - * @temp: pointer that returns the measured temperature + * @temp: pointer that returns the measured temperature in millidegree Celsius */ int (*get_temp)(struct udevice *dev, int *temp); }; |