mirror of
https://github.com/apache/nuttx.git
synced 2026-05-10 07:18:49 +08:00
imx95-a55-evk: add USDHC eMMC driver support
Port USDHC1 (eMMC) driver to the i.MX95 FRDM EVK board: - Create imx95_pinmux.h with SD1/USDHC1 pin definitions - Add USDHC1 pin macros to board.h - Create board-level imx9_usdhc.c glue code - Update imx9_bringup.c with DMA allocator and USDHC init - Add SCMI clock guards in imx9_usdhc.c (imx95 clock roots are owned by System Manager, direct CCM writes are no-ops) - Fix CCM_CR_USDHC2 copy-paste bug to CCM_CR_USDHC1 Signed-off-by: buxiasen <buxiasen@xiaomi.com>
This commit is contained in:
@@ -202,6 +202,9 @@ choice
|
||||
depends on IMX9_USDHC2
|
||||
prompt "Bus width for USDHC2"
|
||||
default IMX9_USDHC2_WIDTH_D1_D4
|
||||
---help---
|
||||
USDHC2 supports up to 4-bit data width only according to chip
|
||||
spec. No 8-bit option is provided.
|
||||
|
||||
config IMX9_USDHC2_WIDTH_D1_ONLY
|
||||
bool "One bit"
|
||||
|
||||
@@ -104,12 +104,12 @@
|
||||
|
||||
/* DRAMPLL registers */
|
||||
|
||||
#define DRAMPLL_CTRL (IMX9_AUDIOPLL_BASE + PLL_CTRL_OFFSET)
|
||||
#define DRAMPLL_SPREAD_SPECTRUM (IMX9_AUDIOPLL_BASE + PLL_SPREAD_SPECTRUM_OFFSET)
|
||||
#define DRAMPLL_NUMERATOR (IMX9_AUDIOPLL_BASE + PLL_NUMERATOR_OFFSET)
|
||||
#define DRAMPLL_DENOMINATOR (IMX9_AUDIOPLL_BASE + PLL_DENOMINATOR_OFFSET)
|
||||
#define DRAMPLL_DIV (IMX9_AUDIOPLL_BASE + PLL_DIV_OFFSET)
|
||||
#define DRAMPLL_PLL_STATUS (IMX9_AUDIOPLL_BASE + PLL_PLL_STATUS_OFFSET)
|
||||
#define DRAMPLL_CTRL (IMX9_DRAMPLL_BASE + PLL_CTRL_OFFSET)
|
||||
#define DRAMPLL_SPREAD_SPECTRUM (IMX9_DRAMPLL_BASE + PLL_SPREAD_SPECTRUM_OFFSET)
|
||||
#define DRAMPLL_NUMERATOR (IMX9_DRAMPLL_BASE + PLL_NUMERATOR_OFFSET)
|
||||
#define DRAMPLL_DENOMINATOR (IMX9_DRAMPLL_BASE + PLL_DENOMINATOR_OFFSET)
|
||||
#define DRAMPLL_DIV (IMX9_DRAMPLL_BASE + PLL_DIV_OFFSET)
|
||||
#define DRAMPLL_PLL_STATUS (IMX9_DRAMPLL_BASE + PLL_PLL_STATUS_OFFSET)
|
||||
|
||||
/* VIDEOPLL registers */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
* arch/arm64/src/imx9/hardware/imx95/imx95_pinmux.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* SPDX-FileCopyrightText: 2024 NXP
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX95_IMX95_PINMUX_H
|
||||
#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX95_IMX95_PINMUX_H
|
||||
|
||||
/* SD1 / USDHC1 pin configurations (ALT0, no daisy chain)
|
||||
*
|
||||
* IOMUX_PADCFG(mux_ctl_reg, mux_mode, daisy_reg, daisy_val, pad_ctl_reg)
|
||||
*
|
||||
* Addresses: IMX9_IOMUXC1_BASE (0x443c0000) + offset
|
||||
* MUX_CTL: SD1_CLK=0x0128, SD1_CMD=0x012c, SD1_DATA0-7=0x0130-0x014c,
|
||||
* SD1_STROBE=0x0150
|
||||
* PAD_CTL: SD1_CLK=0x032c, SD1_CMD=0x0330, SD1_DATA0-7=0x0334-0x0350,
|
||||
* SD1_STROBE=0x0354
|
||||
*/
|
||||
|
||||
#define IOMUXC_PAD_SD1_CLK_USDHC1_CLK IOMUX_PADCFG(0x443c0128, 0x0, 0x00000000, 0x00000000, 0x443c032c)
|
||||
#define IOMUXC_PAD_SD1_CMD_USDHC1_CMD IOMUX_PADCFG(0x443c012c, 0x0, 0x00000000, 0x00000000, 0x443c0330)
|
||||
#define IOMUXC_PAD_SD1_DATA0_USDHC1_DATA0 IOMUX_PADCFG(0x443c0130, 0x0, 0x00000000, 0x00000000, 0x443c0334)
|
||||
#define IOMUXC_PAD_SD1_DATA1_USDHC1_DATA1 IOMUX_PADCFG(0x443c0134, 0x0, 0x00000000, 0x00000000, 0x443c0338)
|
||||
#define IOMUXC_PAD_SD1_DATA2_USDHC1_DATA2 IOMUX_PADCFG(0x443c0138, 0x0, 0x00000000, 0x00000000, 0x443c033c)
|
||||
#define IOMUXC_PAD_SD1_DATA3_USDHC1_DATA3 IOMUX_PADCFG(0x443c013c, 0x0, 0x00000000, 0x00000000, 0x443c0340)
|
||||
#define IOMUXC_PAD_SD1_DATA4_USDHC1_DATA4 IOMUX_PADCFG(0x443c0140, 0x0, 0x00000000, 0x00000000, 0x443c0344)
|
||||
#define IOMUXC_PAD_SD1_DATA5_USDHC1_DATA5 IOMUX_PADCFG(0x443c0144, 0x0, 0x00000000, 0x00000000, 0x443c0348)
|
||||
#define IOMUXC_PAD_SD1_DATA6_USDHC1_DATA6 IOMUX_PADCFG(0x443c0148, 0x0, 0x00000000, 0x00000000, 0x443c034c)
|
||||
#define IOMUXC_PAD_SD1_DATA7_USDHC1_DATA7 IOMUX_PADCFG(0x443c014c, 0x0, 0x00000000, 0x00000000, 0x443c0350)
|
||||
#define IOMUXC_PAD_SD1_STROBE_USDHC1_STROBE IOMUX_PADCFG(0x443c0150, 0x0, 0x00000000, 0x00000000, 0x443c0354)
|
||||
|
||||
#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX95_IMX95_PINMUX_H */
|
||||
@@ -0,0 +1,197 @@
|
||||
/****************************************************************************
|
||||
* arch/arm64/src/imx9/hardware/imx95/imx95_pll.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX95_IMX95_PLL_H
|
||||
#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX95_IMX95_PLL_H
|
||||
|
||||
/* All registers besides STATUS have SET, CLR, TGL and VAL shadow registers */
|
||||
|
||||
#define PLL_REG_VAL_OFFSET (0x00)
|
||||
#define PLL_REG_SET_OFFSET (0x04)
|
||||
#define PLL_REG_CLR_OFFSET (0x08)
|
||||
#define PLL_REG_TGL_OFFSET (0x0c)
|
||||
|
||||
/* User can access the individual registers via these macros */
|
||||
|
||||
#define PLL_VAL(n) ((n) + PLL_REG_VAL_OFFSET) /* Same as the register itself */
|
||||
#define PLL_SET(n) ((n) + PLL_REG_SET_OFFSET)
|
||||
#define PLL_CLR(n) ((n) + PLL_REG_CLR_OFFSET)
|
||||
#define PLL_TGL(n) ((n) + PLL_REG_TGL_OFFSET)
|
||||
|
||||
/* Common offsets for all PLL registers, existence depends on the register
|
||||
* itself
|
||||
*/
|
||||
|
||||
#define PLL_CTRL_OFFSET (0x00) /* PLL Control */
|
||||
#define PLL_SPREAD_SPECTRUM_OFFSET (0x30) /* Spread Spectrum */
|
||||
#define PLL_NUMERATOR_OFFSET (0x40) /* Numerator */
|
||||
#define PLL_DENOMINATOR_OFFSET (0x50) /* Denominator */
|
||||
#define PLL_DIV_OFFSET (0x60) /* PLL Dividers */
|
||||
#define PLL_DFS_CTRL_0_OFFSET (0x70) /* DFS Control */
|
||||
#define PLL_DFS_DIV_0_OFFSET (0x80) /* DFS Division_0 */
|
||||
#define PLL_DFS_CTRL_1_OFFSET (0x90) /* DFS Control */
|
||||
#define PLL_DFS_DIV_1_OFFSET (0xa0) /* DFS Division_1 */
|
||||
#define PLL_DFS_CTRL_2_OFFSET (0xb0) /* DFS Control */
|
||||
#define PLL_DFS_DIV_2_OFFSET (0xc0) /* DFS Division_2 */
|
||||
#define PLL_PLL_STATUS_OFFSET (0xf0) /* PLL Status */
|
||||
#define PLL_DFS_STATUS_OFFSET (0xf4) /* DFS Status */
|
||||
|
||||
/* Register addresses */
|
||||
|
||||
#define PLL_CTRL(n) ((n) + PLL_CTRL_OFFSET)
|
||||
#define PLL_SPREAD_SPECTRUM(n) ((n) + PLL_SPREAD_SPECTRUM_OFFSET)
|
||||
#define PLL_NUMERATOR(n) ((n) + PLL_NUMERATOR_OFFSET)
|
||||
#define PLL_DENOMINATOR(n) ((n) + PLL_DENOMINATOR_OFFSET)
|
||||
#define PLL_DIV(n) ((n) + PLL_DIV_OFFSET)
|
||||
#define PLL_DFS_CTRL_0(n) ((n) + PLL_DFS_CTRL_0_OFFSET)
|
||||
#define PLL_DFS_DIV_0(n) ((n) + PLL_DFS_DIV_0_OFFSET)
|
||||
#define PLL_DFS_CTRL_1(n) ((n) + PLL_DFS_CTRL_1_OFFSET)
|
||||
#define PLL_DFS_DIV_1(n) ((n) + PLL_DFS_DIV_1_OFFSET)
|
||||
#define PLL_DFS_CTRL_2(n) ((n) + PLL_DFS_CTRL_2_OFFSET)
|
||||
#define PLL_DFS_DIV_2(n) ((n) + PLL_DFS_DIV_2_OFFSET)
|
||||
#define PLL_PLL_STATUS(n) ((n) + PLL_PLL_STATUS_OFFSET)
|
||||
#define PLL_DFS_STATUS(n) ((n) + PLL_DFS_STATUS_OFFSET)
|
||||
|
||||
/* SYSPLL registers */
|
||||
|
||||
#define SYSPLL_CTRL (IMX9_SYSPLL_BASE + PLL_CTRL_OFFSET)
|
||||
#define SYSPLL_SPREAD_SPECTRUM (IMX9_SYSPLL_BASE + PLL_SPREAD_SPECTRUM_OFFSET)
|
||||
#define SYSPLL_NUMERATOR (IMX9_SYSPLL_BASE + PLL_NUMERATOR_OFFSET)
|
||||
#define SYSPLL_DENOMINATOR (IMX9_SYSPLL_BASE + PLL_DENOMINATOR_OFFSET)
|
||||
#define SYSPLL_DIV (IMX9_SYSPLL_BASE + PLL_DIV_OFFSET)
|
||||
#define SYSPLL_DFS_CTRL_0 (IMX9_SYSPLL_BASE + PLL_DFS_CTRL_0_OFFSET)
|
||||
#define SYSPLL_DFS_DIV_0 (IMX9_SYSPLL_BASE + PLL_DFS_DIV_0_OFFSET)
|
||||
#define SYSPLL_DFS_CTRL_1 (IMX9_SYSPLL_BASE + PLL_DFS_CTRL_1_OFFSET)
|
||||
#define SYSPLL_DFS_DIV_1 (IMX9_SYSPLL_BASE + PLL_DFS_DIV_1_OFFSET)
|
||||
#define SYSPLL_DFS_CTRL_2 (IMX9_SYSPLL_BASE + PLL_DFS_CTRL_2_OFFSET)
|
||||
#define SYSPLL_DFS_DIV_2 (IMX9_SYSPLL_BASE + PLL_DFS_DIV_2_OFFSET)
|
||||
#define SYSPLL_PLL_STATUS (IMX9_SYSPLL_BASE + PLL_PLL_STATUS_OFFSET)
|
||||
#define SYSPLL_DFS_STATUS (IMX9_SYSPLL_BASE + PLL_DFS_STATUS_OFFSET)
|
||||
|
||||
/* ARMPLL registers */
|
||||
|
||||
#define ARMPLL_CTRL (IMX9_ARMPLL_BASE + PLL_CTRL_OFFSET)
|
||||
#define ARMPLL_DIV (IMX9_ARMPLL_BASE + PLL_DIV_OFFSET)
|
||||
#define ARMPLL_PLL_STATUS (IMX9_ARMPLL_BASE + PLL_PLL_STATUS_OFFSET)
|
||||
|
||||
/* AUDIOPLL registers */
|
||||
|
||||
#define AUDIOPLL_CTRL (IMX9_AUDIOPLL_BASE + PLL_CTRL_OFFSET)
|
||||
#define AUDIOPLL_SPREAD_SPECTRUM (IMX9_AUDIOPLL_BASE + PLL_SPREAD_SPECTRUM_OFFSET)
|
||||
#define AUDIOPLL_NUMERATOR (IMX9_AUDIOPLL_BASE + PLL_NUMERATOR_OFFSET)
|
||||
#define AUDIOPLL_DENOMINATOR (IMX9_AUDIOPLL_BASE + PLL_DENOMINATOR_OFFSET)
|
||||
#define AUDIOPLL_DIV (IMX9_AUDIOPLL_BASE + PLL_DIV_OFFSET)
|
||||
#define AUDIOPLL_PLL_STATUS (IMX9_AUDIOPLL_BASE + PLL_PLL_STATUS_OFFSET)
|
||||
|
||||
/* DRAMPLL registers */
|
||||
|
||||
#define DRAMPLL_CTRL (IMX9_DRAMPLL_BASE + PLL_CTRL_OFFSET)
|
||||
#define DRAMPLL_SPREAD_SPECTRUM (IMX9_DRAMPLL_BASE + PLL_SPREAD_SPECTRUM_OFFSET)
|
||||
#define DRAMPLL_NUMERATOR (IMX9_DRAMPLL_BASE + PLL_NUMERATOR_OFFSET)
|
||||
#define DRAMPLL_DENOMINATOR (IMX9_DRAMPLL_BASE + PLL_DENOMINATOR_OFFSET)
|
||||
#define DRAMPLL_DIV (IMX9_DRAMPLL_BASE + PLL_DIV_OFFSET)
|
||||
#define DRAMPLL_PLL_STATUS (IMX9_DRAMPLL_BASE + PLL_PLL_STATUS_OFFSET)
|
||||
|
||||
/* VIDEOPLL registers */
|
||||
|
||||
#define VIDEOPLL_CTRL (IMX9_VIDEOPLL_BASE + PLL_CTRL_OFFSET)
|
||||
#define VIDEOPLL_SPREAD_SPECTRUM (IMX9_VIDEOPLL_BASE + PLL_SPREAD_SPECTRUM_OFFSET)
|
||||
#define VIDEOPLL_NUMERATOR (IMX9_VIDEOPLL_BASE + PLL_NUMERATOR_OFFSET)
|
||||
#define VIDEOPLL_DENOMINATOR (IMX9_VIDEOPLL_BASE + PLL_DENOMINATOR_OFFSET)
|
||||
#define VIDEOPLL_DIV (IMX9_VIDEOPLL_BASE + PLL_DIV_OFFSET)
|
||||
#define VIDEOPLL_PLL_STATUS (IMX9_VIDEOPLL_BASE + PLL_PLL_STATUS_OFFSET)
|
||||
|
||||
/* PLL Control (CTRL) */
|
||||
|
||||
#define PLL_CTRL_POWERUP (1 << 0) /* Bit 0: Power up PLL */
|
||||
#define PLL_CTRL_CLKMUX_EN (1 << 1) /* Bit 1: Enable CLKMUX output */
|
||||
#define PLL_CTRL_CLKMUX_BYPASS (1 << 2) /* Bit 2: Enable CLKMUX bypass */
|
||||
#define PLL_CTRL_SPREADCTL (1 << 8) /* Bit 8: Modulation Type Select */
|
||||
#define PLL_CTRL_HW_CTRL_SEL (1 << 16) /* Bit 16: Hardware Control Select */
|
||||
#define PLL_CTRL_LOCK_BYPASS (1 << 31) /* Bit 31: Lock bypass */
|
||||
|
||||
/* Spread Spectrum (SPREAD_SPECTRUM) */
|
||||
|
||||
#define PLL_SPREAD_SPECTRUM_STEP_SHIFT (0) /* Bits 14-0: Set spread spectrum step */
|
||||
#define PLL_SPREAD_SPECTRUM_STEP_MASK (0x7fff << PLL_SPREAD_SPECTRUM_STEP_SHIFT)
|
||||
#define PLL_SPREAD_SPECTRUM_STEP(n) (((n) << PLL_SPREAD_SPECTRUM_STEP_SHIFT) & PLL_SPREAD_SPECTRUM_STEP_MASK)
|
||||
#define PLL_SPREAD_SPECTRUM_ENABLE (1 << 15) /* Bit 15: Enable spread spectrum */
|
||||
#define PLL_SPREAD_SPECTRUM_STOP_SHIFT (16) /* Bits 16-31: Set spread spectrum stop */
|
||||
#define PLL_SPREAD_SPECTRUM_STOP_MASK (0xffff << PLL_SPREAD_SPECTRUM_STOP_SHIFT)
|
||||
#define PLL_SPREAD_SPECTRUM_STOP(n) (((n) << PLL_SPREAD_SPECTRUM_STOP_SHIFT) & PLL_SPREAD_SPECTRUM_STOP_MASK)
|
||||
|
||||
/* Numerator (NUMERATOR) */
|
||||
|
||||
#define PLL_NUMERATOR_MFN_SHIFT (2) /* Bits 2-31: Numerator MFN value */
|
||||
#define PLL_NUMERATOR_MFN_MASK (0x3fffffff << PLL_NUMERATOR_MFN_SHIFT)
|
||||
#define PLL_NUMERATOR_MFN(n) (((n) << PLL_NUMERATOR_MFN_SHIFT) & PLL_NUMERATOR_MFN_MASK)
|
||||
|
||||
/* Denominator (DENOMINATOR) */
|
||||
|
||||
#define PLL_DENOMINATOR_MFD_SHIFT (0) /* Bits 0-29: Denominator MFD value */
|
||||
#define PLL_DENOMINATOR_MFD_MASK (0x3fffffff << PLL_DENOMINATOR_MFD_SHIFT)
|
||||
#define PLL_DENOMINATOR_MFD(n) (((n) << PLL_DENOMINATOR_MFD_SHIFT) & PLL_DENOMINATOR_MFD_MASK)
|
||||
|
||||
/* PLL Dividers (DIV) */
|
||||
|
||||
#define PLL_DIV_ODIV_SHIFT (0) /* Bits 0-7: Output Frequency Divider for Clock Output */
|
||||
#define PLL_DIV_ODIV_MASK (0xff << PLL_DIV_ODIV_SHIFT)
|
||||
#define PLL_DIV_ODIV(n) (((n) << PLL_DIV_ODIV_SHIFT) & PLL_DIV_ODIV_MASK)
|
||||
#define PLL_DIV_RDIV_SHIFT (13) /* Bits 13-15: Input Clock Predivider */
|
||||
#define PLL_DIV_RDIV_MASK (0x7 << PLL_DIV_RDIV_SHIFT)
|
||||
#define PLL_DIV_RDIV(n) (((n) << PLL_DIV_RDIV_SHIFT) & PLL_DIV_RDIV_MASK)
|
||||
#define PLL_DIV_MFI_SHIFT (16) /* Bits 16-24: Integer Portion of Loop Divider */
|
||||
#define PLL_DIV_MFI_MASK (0x1ff << PLL_DIV_MFI_SHIFT)
|
||||
#define PLL_DIV_MFI(n) (((n) << PLL_DIV_MFI_SHIFT) & PLL_DIV_MFI_MASK)
|
||||
|
||||
/* DFS Control (DFS_CTRL_0 - DFS_CTRL_2) */
|
||||
|
||||
#define PLL_DFS_HW_CTRL_SEL (1 << 16) /* Bit 16: Hardware Control Select */
|
||||
#define PLL_DFS_BYPASS_EN (1 << 23) /* Bit 23: Bypass Enable */
|
||||
#define PLL_DFS_CLKOUT_DIVBY2_EN (1 << 29) /* Bit 29: DFS Clock Output Divide by 2 Enable */
|
||||
#define PLL_DFS_CLKOUT_EN (1 << 30) /* Bit 30: DFS Clock Output Enable */
|
||||
#define PLL_DFS_ENABLE (1 << 31) /* Bit 31: DFS Block Enable */
|
||||
|
||||
/* DFS Division_a (DFS_DIV_0 - DFS_DIV_2) */
|
||||
|
||||
#define PLL_DFS_MFN_SHIFT (0) /* Bits 0-2: MFN */
|
||||
#define PLL_DFS_MFN_MASK (0x7 << PLL_DFS_MFN_SHIFT)
|
||||
#define PLL_DFS_MFN(n) (((n) << PLL_DFS_MFN_SHIFT) & PLL_DFS_MFN_MASK)
|
||||
#define PLL_DFS_MFI_SHIFT (8) /* Bits 8-15: MFI */
|
||||
#define PLL_DFS_MFI_MASK (0xff << PLL_DFS_MFI_SHIFT)
|
||||
#define PLL_DFS_MFI(n) (((n) << PLL_DFS_MFI_SHIFT) & PLL_DFS_MFI_MASK)
|
||||
|
||||
/* PLL Dividers (DIV) */
|
||||
|
||||
#define PLL_PLL_STATUS_PLL_LOCK (1 << 0) /* Bit 0: PLL is locked */
|
||||
#define PLL_PLL_STATUS_PLL_LOL (1 << 1) /* Bit 1: PLL lock is lost */
|
||||
#define PLL_PLL_STATUS_ANA_MFN_SHIFT (2)
|
||||
#define PLL_PLL_STATUS_ANA_MFN_MASK (0x3fffffff << PLL_PLL_STATUS_ANA_MFN_SHIFT)
|
||||
#define PLL_PLL_STATUS_ANA_MFN(n) (((n) << PLL_PLL_STATUS_ANA_MFN_SHIFT) & PLL_PLL_STATUS_ANA_MFN_MASK)
|
||||
|
||||
/* DFS Status (DFS_STATUS) */
|
||||
|
||||
#define PLL_DFS_STATUS_DFS_OK_SHIFT (0) /* Bits 0-2: DFS OK status */
|
||||
#define PLL_DFS_STATUS_DFS_OK_MASK (0x7 << PLL_DFS_STATUS_DFS_OK_SHIFT)
|
||||
#define PLL_DFS_STATUS_DFS_OK(n) (((n) << PLL_DFS_STATUS_DFS_OK_SHIFT) & PLL_DFS_STATUS_DFS_OK_MASK)
|
||||
|
||||
#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX95_IMX95_PLL_H */
|
||||
@@ -34,6 +34,8 @@
|
||||
# include "hardware/imx93/imx93_ccm.h"
|
||||
# include "hardware/imx93/imx93_pll.h"
|
||||
#elif defined(CONFIG_ARCH_CHIP_IMX95)
|
||||
# include "hardware/imx95/imx95_ccm.h"
|
||||
# include "hardware/imx95/imx95_pll.h"
|
||||
#else
|
||||
# error Unrecognized i.MX9 architecture
|
||||
#endif
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#if defined(CONFIG_ARCH_CHIP_IMX93)
|
||||
# include "hardware/imx93/imx93_pinmux.h"
|
||||
#elif defined(CONFIG_ARCH_CHIP_IMX95)
|
||||
# include "hardware/imx95/imx95_pinmux.h"
|
||||
#else
|
||||
# error Unrecognized i.MX9 architecture
|
||||
#endif
|
||||
|
||||
@@ -327,9 +327,11 @@ static void imx9_reset(struct sdio_dev_s *dev);
|
||||
static sdio_capset_t imx9_capabilities(struct sdio_dev_s *dev);
|
||||
static sdio_statset_t imx9_status(struct sdio_dev_s *dev);
|
||||
static void imx9_widebus(struct sdio_dev_s *dev, bool enable);
|
||||
#ifndef CONFIG_IMX9_CLK_OVER_SCMI
|
||||
static bool imx9_sdcard_hs_mode(struct sdio_dev_s *dev, bool set);
|
||||
static uint32_t imx9_frequency(struct sdio_dev_s *dev,
|
||||
unsigned long frequency);
|
||||
#endif
|
||||
|
||||
static void imx9_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate);
|
||||
static int imx9_attach(struct sdio_dev_s *dev);
|
||||
@@ -1648,7 +1650,20 @@ static void imx9_widebus(struct sdio_dev_s *dev, bool wide)
|
||||
regval &= ~USDHC_PROCTL_DTW_MASK;
|
||||
if (wide)
|
||||
{
|
||||
regval |= USDHC_PROCTL_DTW_4BIT;
|
||||
/* Only USDHC1 supports 8-bit data width. USDHC2 is limited to
|
||||
* 4-bit according to chip spec.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_IMX9_USDHC1_WIDTH_D1_D8
|
||||
if (priv->addr == IMX9_USDHC1_BASE)
|
||||
{
|
||||
regval |= USDHC_PROCTL_DTW_8BIT;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
regval |= USDHC_PROCTL_DTW_4BIT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1658,6 +1673,8 @@ static void imx9_widebus(struct sdio_dev_s *dev, bool wide)
|
||||
putreg32(regval, priv->addr + IMX9_USDHC_PROCTL_OFFSET);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_IMX9_CLK_OVER_SCMI
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imx9_sdcard_hs_mode
|
||||
*
|
||||
@@ -1875,9 +1892,12 @@ static uint32_t imx9_frequency(struct sdio_dev_s *dev,
|
||||
|
||||
/* Return the new divisor information */
|
||||
|
||||
return USDHC_SYSCTL_SDCLKFS_DIV(prescaler) | USDHC_SYSCTL_DVS_DIV(divisor);
|
||||
return USDHC_SYSCTL_SDCLKFS_DIV(prescaler) |
|
||||
USDHC_SYSCTL_DVS_DIV(divisor);
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_IMX9_CLK_OVER_SCMI */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imx9_clock
|
||||
*
|
||||
@@ -1897,13 +1917,15 @@ static void imx9_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
|
||||
{
|
||||
struct imx9_dev_s *priv = (struct imx9_dev_s *)dev;
|
||||
uint32_t regval;
|
||||
#ifndef CONFIG_IMX9_CLK_OVER_SCMI
|
||||
unsigned speed;
|
||||
#endif
|
||||
|
||||
/* Clear the old prescaler and divisor values so that new ones can be
|
||||
* ORed in.
|
||||
*/
|
||||
|
||||
regval = getreg32(priv->addr + IMX9_USDHC_SYSCTL_OFFSET);
|
||||
regval = getreg32(priv->addr + IMX9_USDHC_SYSCTL_OFFSET);
|
||||
regval &= ~(USDHC_SYSCTL_SDCLKFS_MASK | USDHC_SYSCTL_DVS_MASK);
|
||||
|
||||
/* Select the new prescaler and divisor values based on the requested
|
||||
@@ -1918,8 +1940,14 @@ static void imx9_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
|
||||
{
|
||||
/* Clock is disabled */
|
||||
|
||||
mcinfo("DISABLED, SYSCTRL: %08" PRIx32 "\n", regval);
|
||||
putreg32(regval, priv->addr + IMX9_USDHC_SYSCTL_OFFSET);
|
||||
mcinfo("DISABLED, SYSCTRL: %08" PRIx32 "\n",
|
||||
getreg32(priv->addr + IMX9_USDHC_SYSCTL_OFFSET));
|
||||
#ifdef CONFIG_IMX9_CLK_OVER_SCMI
|
||||
return;
|
||||
#else
|
||||
speed = 0;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1928,13 +1956,19 @@ static void imx9_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
|
||||
/* Initial ID mode clocking (<400KHz) */
|
||||
|
||||
mcinfo("IDMODE\n");
|
||||
speed = BOARD_USDHC_IDMODE_SPEED;
|
||||
|
||||
/* Put out an additional 80 clocks in case this is a power-up
|
||||
* sequence.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_IMX9_CLK_OVER_SCMI
|
||||
regval |= (BOARD_USDHC_IDMODE_PRESCALER |
|
||||
BOARD_USDHC_IDMODE_DIVISOR |
|
||||
USDHC_SYSCTL_INITA);
|
||||
#else
|
||||
speed = BOARD_USDHC_IDMODE_SPEED;
|
||||
regval |= USDHC_SYSCTL_INITA;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1943,7 +1977,12 @@ static void imx9_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
|
||||
/* MMC normal operation clocking */
|
||||
|
||||
mcinfo("MMCTRANSFER\n");
|
||||
#ifdef CONFIG_IMX9_CLK_OVER_SCMI
|
||||
regval |= (BOARD_USDHC_MMCMODE_PRESCALER |
|
||||
BOARD_USDHC_MMCMODE_DIVISOR);
|
||||
#else
|
||||
speed = BOARD_USDHC_MMCMODE_SPEED;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1952,7 +1991,12 @@ static void imx9_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
|
||||
/* SD normal operation clocking (narrow 1-bit mode) */
|
||||
|
||||
mcinfo("1BITTRANSFER\n");
|
||||
#ifdef CONFIG_IMX9_CLK_OVER_SCMI
|
||||
regval |= (BOARD_USDHC_SD1MODE_PRESCALER |
|
||||
BOARD_USDHC_SD1MODE_DIVISOR);
|
||||
#else
|
||||
speed = BOARD_USDHC_SD1MODE_SPEED;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1960,6 +2004,11 @@ static void imx9_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
|
||||
{
|
||||
/* SD normal operation clocking (wide 4-bit mode) */
|
||||
|
||||
#ifdef CONFIG_IMX9_CLK_OVER_SCMI
|
||||
mcinfo("4BITTRANSFER\n");
|
||||
regval |= (BOARD_USDHC_SD4MODE_PRESCALER |
|
||||
BOARD_USDHC_SD4MODE_DIVISOR);
|
||||
#else
|
||||
mcinfo("SDTRANSFER\n");
|
||||
speed = BOARD_USDHC_SDMODE_SPEED;
|
||||
|
||||
@@ -1979,14 +2028,17 @@ static void imx9_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_IMX9_CLK_OVER_SCMI
|
||||
if (speed > 0)
|
||||
{
|
||||
regval |= imx9_frequency(dev, speed);
|
||||
}
|
||||
#endif
|
||||
|
||||
putreg32(regval, priv->addr + IMX9_USDHC_SYSCTL_OFFSET);
|
||||
|
||||
@@ -3453,9 +3505,13 @@ struct sdio_dev_s *imx9_usdhc_initialize(int slotno)
|
||||
|
||||
/* Enable clocks */
|
||||
|
||||
#ifdef CONFIG_IMX9_CLK_OVER_SCMI
|
||||
imx9_configure_clock(USDHC1_DFS1 | CLOCK_DIV(4), true);
|
||||
#else
|
||||
imx9_ccm_configure_root_clock(CCM_CR_USDHC1, SYS_PLL1PFD1, 2);
|
||||
imx9_get_rootclock(CCM_CR_USDHC1, &priv->root_clock_freq);
|
||||
imx9_ccm_gate_on(CCM_LPCG_USDHC1, true);
|
||||
#endif
|
||||
|
||||
break;
|
||||
#endif
|
||||
@@ -3488,9 +3544,13 @@ struct sdio_dev_s *imx9_usdhc_initialize(int slotno)
|
||||
|
||||
/* Enable clocks */
|
||||
|
||||
#ifdef CONFIG_IMX9_CLK_OVER_SCMI
|
||||
imx9_configure_clock(USDHC2_DFS1 | CLOCK_DIV(4), true);
|
||||
#else
|
||||
imx9_ccm_configure_root_clock(CCM_CR_USDHC2, SYS_PLL1PFD1, 2);
|
||||
imx9_get_rootclock(CCM_CR_USDHC2, &priv->root_clock_freq);
|
||||
imx9_ccm_gate_on(CCM_LPCG_USDHC2, true);
|
||||
#endif
|
||||
|
||||
mcinfo("Enabled clocks\n");
|
||||
|
||||
|
||||
@@ -96,6 +96,19 @@
|
||||
|
||||
/* Note: Need to set the SION for cmd and data pads (ERR052021) */
|
||||
|
||||
/* USDHC1 - eMMC 8-bit */
|
||||
|
||||
#define PIN_USDHC1_D0_MUX IOMUX_CFG(IOMUXC_PAD_SD1_DATA0_USDHC1_DATA0, IOMUXC_PAD_DSE_X1 | IOMUXC_PAD_FSEL_FAST | IOMUXC_PAD_PU_ON | IOMUXC_PAD_HYS_ST_ON, IOMUXC_MUX_SION_ON)
|
||||
#define PIN_USDHC1_D1_MUX IOMUX_CFG(IOMUXC_PAD_SD1_DATA1_USDHC1_DATA1, IOMUXC_PAD_DSE_X1 | IOMUXC_PAD_FSEL_FAST | IOMUXC_PAD_PU_ON | IOMUXC_PAD_HYS_ST_ON, IOMUXC_MUX_SION_ON)
|
||||
#define PIN_USDHC1_D2_MUX IOMUX_CFG(IOMUXC_PAD_SD1_DATA2_USDHC1_DATA2, IOMUXC_PAD_DSE_X1 | IOMUXC_PAD_FSEL_FAST | IOMUXC_PAD_PU_ON | IOMUXC_PAD_HYS_ST_ON, IOMUXC_MUX_SION_ON)
|
||||
#define PIN_USDHC1_D3_MUX IOMUX_CFG(IOMUXC_PAD_SD1_DATA3_USDHC1_DATA3, IOMUXC_PAD_DSE_X1 | IOMUXC_PAD_FSEL_FAST | IOMUXC_PAD_PU_ON | IOMUXC_PAD_HYS_ST_ON, IOMUXC_MUX_SION_ON)
|
||||
#define PIN_USDHC1_D4_MUX IOMUX_CFG(IOMUXC_PAD_SD1_DATA4_USDHC1_DATA4, IOMUXC_PAD_DSE_X1 | IOMUXC_PAD_FSEL_FAST | IOMUXC_PAD_PU_ON | IOMUXC_PAD_HYS_ST_ON, IOMUXC_MUX_SION_ON)
|
||||
#define PIN_USDHC1_D5_MUX IOMUX_CFG(IOMUXC_PAD_SD1_DATA5_USDHC1_DATA5, IOMUXC_PAD_DSE_X1 | IOMUXC_PAD_FSEL_FAST | IOMUXC_PAD_PU_ON | IOMUXC_PAD_HYS_ST_ON, IOMUXC_MUX_SION_ON)
|
||||
#define PIN_USDHC1_D6_MUX IOMUX_CFG(IOMUXC_PAD_SD1_DATA6_USDHC1_DATA6, IOMUXC_PAD_DSE_X1 | IOMUXC_PAD_FSEL_FAST | IOMUXC_PAD_PU_ON | IOMUXC_PAD_HYS_ST_ON, IOMUXC_MUX_SION_ON)
|
||||
#define PIN_USDHC1_D7_MUX IOMUX_CFG(IOMUXC_PAD_SD1_DATA7_USDHC1_DATA7, IOMUXC_PAD_DSE_X1 | IOMUXC_PAD_FSEL_FAST | IOMUXC_PAD_PU_ON | IOMUXC_PAD_HYS_ST_ON, IOMUXC_MUX_SION_ON)
|
||||
#define PIN_USDHC1_DCLK_MUX IOMUX_CFG(IOMUXC_PAD_SD1_CLK_USDHC1_CLK, IOMUXC_PAD_DSE_X6 | IOMUXC_PAD_FSEL_FAST | IOMUXC_PAD_PD_ON | IOMUXC_PAD_HYS_ST_ON, 0)
|
||||
#define PIN_USDHC1_CMD_MUX IOMUX_CFG(IOMUXC_PAD_SD1_CMD_USDHC1_CMD, IOMUXC_PAD_DSE_X1 | IOMUXC_PAD_FSEL_FAST | IOMUXC_PAD_PU_ON | IOMUXC_PAD_HYS_ST_ON, IOMUXC_MUX_SION_ON)
|
||||
|
||||
#define PIN_USDHC2_D0_MUX IOMUX_CFG(IOMUXC_PAD_SD2_DATA0_USDHC2_DATA0, IOMUXC_PAD_DSE_X1 | IOMUXC_PAD_FSEL_FAST | IOMUXC_PAD_PU_ON | IOMUXC_PAD_HYS_ST_ON, IOMUXC_MUX_SION_ON)
|
||||
#define PIN_USDHC2_D1_MUX IOMUX_CFG(IOMUXC_PAD_SD2_DATA1_USDHC2_DATA1, IOMUXC_PAD_DSE_X1 | IOMUXC_PAD_FSEL_FAST | IOMUXC_PAD_PU_ON | IOMUXC_PAD_HYS_ST_ON, IOMUXC_MUX_SION_ON)
|
||||
#define PIN_USDHC2_D2_MUX IOMUX_CFG(IOMUXC_PAD_SD2_DATA2_USDHC2_DATA2, IOMUXC_PAD_DSE_X1 | IOMUXC_PAD_FSEL_FAST | IOMUXC_PAD_PU_ON | IOMUXC_PAD_HYS_ST_ON, IOMUXC_MUX_SION_ON)
|
||||
@@ -105,21 +118,29 @@
|
||||
#define PIN_USDHC2_CD_MUX IOMUX_CFG(IOMUXC_PAD_SD2_DATA3_USDHC2_DATA3, IOMUXC_PAD_DSE_X4 | IOMUXC_PAD_FSEL_FAST, 0)
|
||||
#define PIN_USDHC2_VSELECT_MUX IOMUX_CFG(IOMUXC_PAD_SD2_VSELECT_USDHC2_VSELECT, IOMUXC_PAD_DSE_X5 | IOMUXC_PAD_FSEL_SFAST | IOMUXC_PAD_PD_ON, 0)
|
||||
|
||||
/* 400 KHz for initial inquiry stuff */
|
||||
/* 390 KHz for initial inquiry stuff */
|
||||
|
||||
#define BOARD_USDHC_IDMODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV256
|
||||
#define BOARD_USDHC_IDMODE_DIVISOR USDHC_SYSCTL_DVS_DIV(2)
|
||||
#define BOARD_USDHC_IDMODE_SPEED 400000
|
||||
|
||||
/* 25MHz for MMC mode */
|
||||
|
||||
#define BOARD_USDHC_MMCMODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV8
|
||||
#define BOARD_USDHC_MMCMODE_DIVISOR USDHC_SYSCTL_DVS_DIV(1)
|
||||
#define BOARD_USDHC_MMCMODE_SPEED 25000000
|
||||
|
||||
/* 25MHz for 1-bit wide bus */
|
||||
|
||||
#define BOARD_USDHC_SD1MODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV8
|
||||
#define BOARD_USDHC_SD1MODE_DIVISOR USDHC_SYSCTL_DVS_DIV(1)
|
||||
#define BOARD_USDHC_SD1MODE_SPEED 25000000
|
||||
|
||||
/* 50MHz for SD card mode */
|
||||
/* 50MHz for 4-bit wide bus */
|
||||
|
||||
#define BOARD_USDHC_SDMODE_SPEED 50000000
|
||||
#define BOARD_USDHC_SD4MODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV4
|
||||
#define BOARD_USDHC_SD4MODE_DIVISOR USDHC_SYSCTL_DVS_DIV(1)
|
||||
#define BOARD_USDHC_SDMODE_SPEED 50000000
|
||||
|
||||
/* Set the PLL clocks as follows:
|
||||
*
|
||||
|
||||
@@ -29,4 +29,8 @@ if(CONFIG_BOARDCTL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_IMX9_USDHC)
|
||||
list(APPEND SRCS imx9_usdhc.c)
|
||||
endif()
|
||||
|
||||
target_sources(board PRIVATE ${SRCS})
|
||||
|
||||
@@ -31,4 +31,8 @@ CSRCS += imx9_reset.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_IMX9_USDHC),y)
|
||||
CSRCS += imx9_usdhc.c
|
||||
endif
|
||||
|
||||
include $(TOPDIR)/boards/Board.mk
|
||||
|
||||
@@ -61,6 +61,25 @@ int imx9_bringup(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IMX9_DMA_ALLOC
|
||||
/* Initialize the DMA memory allocator */
|
||||
|
||||
ret = imx9_dma_alloc_init();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed initialize DMA allocator: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MMCSD
|
||||
ret = imx9_usdhc_init();
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Failed to init MMCSD driver: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
UNUSED(ret);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/****************************************************************************
|
||||
* boards/arm64/imx9/imx95-a55-evk/src/imx9_usdhc.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <nuttx/mmcsd.h>
|
||||
|
||||
#include "imx9_usdhc.h"
|
||||
#include "imx95-evk.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct sdio_dev_s *g_sdio_dev;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imx9_usdhc_init
|
||||
*
|
||||
* Description:
|
||||
* Configure the uSDHC driver.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; A negated errno value is returned
|
||||
* to indicate the nature of any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int imx9_usdhc_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* First, get an instance of the SDIO interface */
|
||||
|
||||
finfo("Initializing SDIO slot %d\n", SDIO_SLOTNO);
|
||||
|
||||
g_sdio_dev = imx9_usdhc_initialize(SDIO_SLOTNO);
|
||||
if (!g_sdio_dev)
|
||||
{
|
||||
ferr("ERROR: Failed to initialize SDIO slot %d\n", SDIO_SLOTNO);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Now bind the SDIO interface to the MMC/SD driver */
|
||||
|
||||
finfo("Bind SDIO to the MMC/SD driver, minor=%d\n", SDIO_MINOR);
|
||||
|
||||
ret = mmcsd_slotinitialize(SDIO_MINOR, g_sdio_dev);
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: Failed to bind SDIO to the MMC/SD driver: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
Reference in New Issue
Block a user