Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * MSDI IP block reset
0004  *
0005  * Copyright (C) 2012 Texas Instruments, Inc.
0006  * Paul Walmsley
0007  *
0008  * XXX What about pad muxing?
0009  */
0010 
0011 #include <linux/kernel.h>
0012 #include <linux/err.h>
0013 
0014 #include "prm.h"
0015 #include "common.h"
0016 #include "control.h"
0017 #include "omap_hwmod.h"
0018 #include "omap_device.h"
0019 #include "mmc.h"
0020 
0021 /*
0022  * MSDI_CON_OFFSET: offset in bytes of the MSDI IP block's CON register
0023  *     from the IP block's base address
0024  */
0025 #define MSDI_CON_OFFSET             0x0c
0026 
0027 /* Register bitfields in the CON register */
0028 #define MSDI_CON_POW_MASK           BIT(11)
0029 #define MSDI_CON_CLKD_MASK          (0x3f << 0)
0030 #define MSDI_CON_CLKD_SHIFT         0
0031 
0032 /* MSDI_TARGET_RESET_CLKD: clock divisor to use throughout the reset */
0033 #define MSDI_TARGET_RESET_CLKD      0x3ff
0034 
0035 /**
0036  * omap_msdi_reset - reset the MSDI IP block
0037  * @oh: struct omap_hwmod *
0038  *
0039  * The MSDI IP block on OMAP2420 has to have both the POW and CLKD
0040  * fields set inside its CON register for a reset to complete
0041  * successfully.  This is not documented in the TRM.  For CLKD, we use
0042  * the value that results in the lowest possible clock rate, to attempt
0043  * to avoid disturbing any cards.
0044  */
0045 int omap_msdi_reset(struct omap_hwmod *oh)
0046 {
0047     u16 v = 0;
0048     int c = 0;
0049 
0050     /* Write to the SOFTRESET bit */
0051     omap_hwmod_softreset(oh);
0052 
0053     /* Enable the MSDI core and internal clock */
0054     v |= MSDI_CON_POW_MASK;
0055     v |= MSDI_TARGET_RESET_CLKD << MSDI_CON_CLKD_SHIFT;
0056     omap_hwmod_write(v, oh, MSDI_CON_OFFSET);
0057 
0058     /* Poll on RESETDONE bit */
0059     omap_test_timeout((omap_hwmod_read(oh, oh->class->sysc->syss_offs)
0060                & SYSS_RESETDONE_MASK),
0061               MAX_MODULE_SOFTRESET_WAIT, c);
0062 
0063     if (c == MAX_MODULE_SOFTRESET_WAIT)
0064         pr_warn("%s: %s: softreset failed (waited %d usec)\n",
0065             __func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
0066     else
0067         pr_debug("%s: %s: softreset in %d usec\n", __func__,
0068              oh->name, c);
0069 
0070     /* Disable the MSDI internal clock */
0071     v &= ~MSDI_CON_CLKD_MASK;
0072     omap_hwmod_write(v, oh, MSDI_CON_OFFSET);
0073 
0074     return 0;
0075 }