mirror of
				https://source.denx.de/u-boot/u-boot.git
				synced 2025-10-31 08:21:36 +01:00 
			
		
		
		
	Adds support for MMC controllers found on OcteonTX or OcteonTX2 SoC platforms. Signed-off-by: Aaron Williams <awilliams@marvell.com> Signed-off-by: Suneel Garapati <sgarapati@marvell.com> Cc: Peng Fan <peng.fan@nxp.com>
		
			
				
	
	
		
			208 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			208 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* SPDX-License-Identifier:    GPL-2.0
 | |
|  *
 | |
|  * Copyright (C) 2019 Marvell International Ltd.
 | |
|  *
 | |
|  * https://spdx.org/licenses
 | |
|  */
 | |
| #ifndef __OCTEONTX_HSMMC_H__
 | |
| #define __OCTEONTX_HSMMC_H__
 | |
| #include <asm/gpio.h>
 | |
| 
 | |
| /** Name of our driver */
 | |
| #define OCTEONTX_MMC_DRIVER_NAME	"octeontx-hsmmc"
 | |
| 
 | |
| /** Maximum supported MMC slots */
 | |
| #define OCTEONTX_MAX_MMC_SLOT		3
 | |
| 
 | |
| #define POWER_ON_TIME			40 /** See SD 4.1 spec figure 6-5 */
 | |
| 
 | |
| /**
 | |
|  * Timeout used when waiting for commands to complete.  We need to keep this
 | |
|  * above the hardware watchdog timeout which is usually limited to 1000ms
 | |
|  */
 | |
| #define WATCHDOG_COUNT			(1100)	/* in msecs */
 | |
| 
 | |
| /**
 | |
|  * Long timeout for commands which might take a while to complete.
 | |
|  */
 | |
| #define MMC_TIMEOUT_LONG		1000
 | |
| 
 | |
| /**
 | |
|  * Short timeout used for most commands in msecs
 | |
|  */
 | |
| #define MMC_TIMEOUT_SHORT		20
 | |
| 
 | |
| #define NSEC_PER_SEC			1000000000L
 | |
| 
 | |
| #define MAX_NO_OF_TAPS			64
 | |
| 
 | |
| #define EXT_CSD_POWER_CLASS		187	/* R/W */
 | |
| 
 | |
| /* default HS400 tuning block number */
 | |
| #define DEFAULT_HS400_TUNING_BLOCK	1
 | |
| 
 | |
| struct octeontx_mmc_host;
 | |
| 
 | |
| /** MMC/SD slot data structure */
 | |
| struct octeontx_mmc_slot {
 | |
| 	struct mmc		mmc;
 | |
| 	struct mmc_config	cfg;
 | |
| 	struct octeontx_mmc_host *host;
 | |
| 	struct udevice		*dev;
 | |
| 	void			*base_addr;	/** Same as host base_addr */
 | |
| 	u64			clock;
 | |
| 	int			bus_id;		/** slot number */
 | |
| 	uint			bus_width;
 | |
| 	uint			max_width;
 | |
| 	int			hs200_tap_adj;
 | |
| 	int			hs400_tap_adj;
 | |
| 	int			hs400_tuning_block;
 | |
| 	struct gpio_desc	cd_gpio;
 | |
| 	struct gpio_desc	wp_gpio;
 | |
| 	struct gpio_desc	power_gpio;
 | |
| 	enum bus_mode		mode;
 | |
| 	union mio_emm_switch	cached_switch;
 | |
| 	union mio_emm_switch	want_switch;
 | |
| 	union mio_emm_rca	cached_rca;
 | |
| 	union mio_emm_timing	taps;	/* otx2: MIO_EMM_TIMING */
 | |
| 	union mio_emm_timing	hs200_taps;
 | |
| 	union mio_emm_timing	hs400_taps;
 | |
| 	/* These are used to see if our tuning is still valid or not */
 | |
| 	enum bus_mode		last_mode;
 | |
| 	u32			last_clock;
 | |
| 	u32			block_len;
 | |
| 	u32			block_count;
 | |
| 	int			cmd_clk_skew;
 | |
| 	int			dat_clk_skew;
 | |
| 	uint			cmd_cnt;	/* otx: sample cmd in delay */
 | |
| 	uint			dat_cnt;	/* otx: sample data in delay */
 | |
| 	uint			drive;		/* Current drive */
 | |
| 	uint			slew;		/* clock skew */
 | |
| 	uint			cmd_out_hs200_delay;
 | |
| 	uint			data_out_hs200_delay;
 | |
| 	uint			cmd_out_hs400_delay;
 | |
| 	uint			data_out_hs400_delay;
 | |
| 	uint			clk_period;
 | |
| 	bool			valid:1;
 | |
| 	bool			is_acmd:1;
 | |
| 	bool			tuned:1;
 | |
| 	bool			hs200_tuned:1;
 | |
| 	bool			hs400_tuned:1;
 | |
| 	bool			is_1_8v:1;
 | |
| 	bool			is_3_3v:1;
 | |
| 	bool			is_ddr:1;
 | |
| 	bool			is_asim:1;
 | |
| 	bool			is_emul:1;
 | |
| 	bool			cd_inverted:1;
 | |
| 	bool			wp_inverted:1;
 | |
| 	bool			disable_ddr:1;
 | |
| 	bool			non_removable:1;
 | |
| };
 | |
| 
 | |
| struct octeontx_mmc_cr_mods {
 | |
| 	u8 ctype_xor;
 | |
| 	u8 rtype_xor;
 | |
| };
 | |
| 
 | |
| struct octeontx_mmc_cr {
 | |
| 	u8 c;
 | |
| 	u8 r;
 | |
| };
 | |
| 
 | |
| struct octeontx_sd_mods {
 | |
| 	struct octeontx_mmc_cr mmc;
 | |
| 	struct octeontx_mmc_cr sd;
 | |
| 	struct octeontx_mmc_cr sdacmd;
 | |
| };
 | |
| 
 | |
| /** Host controller data structure */
 | |
| struct octeontx_mmc_host {
 | |
| 	struct		udevice *dev;
 | |
| 	void		*base_addr;
 | |
| 	struct octeontx_mmc_slot slots[OCTEONTX_MAX_MMC_SLOT + 1];
 | |
| 	pci_dev_t	pdev;
 | |
| 	u64		sys_freq;
 | |
| 	union mio_emm_cfg emm_cfg;
 | |
| 	u64		timing_taps;
 | |
| 	struct mmc	*last_mmc;	/** Last mmc used */
 | |
| 	ofnode		node;
 | |
| 	int		cur_slotid;
 | |
| 	int		last_slotid;
 | |
| 	int		max_width;
 | |
| 	uint		per_tap_delay;
 | |
| 	uint		num_slots;
 | |
| 	uint		dma_wait_delay;	/* Delay before polling DMA in usecs */
 | |
| 	bool		initialized:1;
 | |
| 	bool		timing_calibrated:1;
 | |
| 	bool		is_asim:1;
 | |
| 	bool		is_emul:1;
 | |
| 	bool		calibrate_glitch:1;
 | |
| 	bool		cond_clock_glitch:1;
 | |
| 	bool		tap_requires_noclk:1;
 | |
| 	bool		hs400_skew_needed:1;
 | |
| };
 | |
| 
 | |
| /*
 | |
|  * NOTE: This was copied from the Linux kernel.
 | |
|  *
 | |
|  * MMC status in R1, for native mode (SPI bits are different)
 | |
|  * Type
 | |
|  *	e:error bit
 | |
|  *	s:status bit
 | |
|  *	r:detected and set for the actual command response
 | |
|  *	x:detected and set during command execution. the host must poll
 | |
|  *	    the card by sending status command in order to read these bits.
 | |
|  * Clear condition
 | |
|  *	a:according to the card state
 | |
|  *	b:always related to the previous command. Reception of
 | |
|  *	    a valid command will clear it (with a delay of one command)
 | |
|  *	c:clear by read
 | |
|  */
 | |
| #define R1_OUT_OF_RANGE		BIT(31)		/* er, c */
 | |
| #define R1_ADDRESS_ERROR	BIT(30)		/* erx, c */
 | |
| #define R1_BLOCK_LEN_ERROR	BIT(29)		/* er, c */
 | |
| #define R1_ERASE_SEQ_ERROR	BIT(28)		/* er, c */
 | |
| #define R1_ERASE_PARAM          BIT(27)		/* ex, c */
 | |
| #define R1_WP_VIOLATION		BIT(26)		/* erx, c */
 | |
| #define R1_CARD_IS_LOCKED	BIT(25)		/* sx, a */
 | |
| #define R1_LOCK_UNLOCK_FAILED	BIT(24)		/* erx, c */
 | |
| #define R1_COM_CRC_ERROR	BIT(23)		/* er, b */
 | |
| /*#define R1_ILLEGAL_COMMAND	BIT(22)*/		/* er, b */
 | |
| #define R1_CARD_ECC_FAILED	BIT(21)		/* ex, c */
 | |
| #define R1_CC_ERROR		BIT(20)		/* erx, c */
 | |
| #define R1_ERROR		BIT(19)		/* erx, c */
 | |
| #define R1_UNDERRUN		BIT(18)		/* ex, c */
 | |
| #define R1_OVERRUN		BIT(17)		/* ex, c */
 | |
| #define R1_CID_CSD_OVERWRITE	BIT(16)		/* erx, c, CID/CSD overwrite */
 | |
| #define R1_WP_ERASE_SKIP	BIT(15)		/* sx, c */
 | |
| #define R1_CARD_ECC_DISABLED	BIT(14)		/* sx, a */
 | |
| #define R1_ERASE_RESET		BIT(13)		/* sr, c */
 | |
| #define R1_STATUS(x)		((x) & 0xFFFFE000)
 | |
| #define R1_CURRENT_STATE(x)	(((x) & 0x00001E00) >> 9) /* sx, b (4 bits) */
 | |
| #define R1_READY_FOR_DATA	BIT(8)		/* sx, a */
 | |
| #define R1_SWITCH_ERROR		BIT(7)		/* sx, c */
 | |
| 
 | |
| #define R1_BLOCK_READ_MASK	R1_OUT_OF_RANGE |	\
 | |
| 				R1_ADDRESS_ERROR |	\
 | |
| 				R1_BLOCK_LEN_ERROR |	\
 | |
| 				R1_CARD_IS_LOCKED |	\
 | |
| 				R1_COM_CRC_ERROR |	\
 | |
| 				R1_ILLEGAL_COMMAND |	\
 | |
| 				R1_CARD_ECC_FAILED |	\
 | |
| 				R1_CC_ERROR |		\
 | |
| 				R1_ERROR
 | |
| #define R1_BLOCK_WRITE_MASK	R1_OUT_OF_RANGE |	\
 | |
| 				R1_ADDRESS_ERROR |	\
 | |
| 				R1_BLOCK_LEN_ERROR |	\
 | |
| 				R1_WP_VIOLATION |	\
 | |
| 				R1_CARD_IS_LOCKED |	\
 | |
| 				R1_COM_CRC_ERROR |	\
 | |
| 				R1_ILLEGAL_COMMAND |	\
 | |
| 				R1_CARD_ECC_FAILED |	\
 | |
| 				R1_CC_ERROR |		\
 | |
| 				R1_ERROR |		\
 | |
| 				R1_UNDERRUN |		\
 | |
| 				R1_OVERRUN
 | |
| 
 | |
| #endif /* __OCTEONTX_HSMMC_H__ */
 |