Ejemplo n.º 1
0
/*===========================================================================*
 *				do_int					     *
 *===========================================================================*/
static void do_int(struct port *pp)
{
    int devind, vcc_5v, vcc_3v, vcc_Xv, vcc_Yv,
        socket_5v, socket_3v, socket_Xv, socket_Yv;
    spin_t spin;
    u32_t csr_event, csr_present, csr_control;
    u8_t v8;
    u16_t v16;
#if USE_INTS
    int r;
#endif

    devind= pp->p_devind;
    v8= pci_attr_r8(devind, TI_CARD_CTRL);
    if (v8 & TI_CCR_IFG)
    {
        printf("ti1225: got functional interrupt\n");
        pci_attr_w8(devind, TI_CARD_CTRL, v8);
    }

    if (debug)
    {
        printf("Socket event: 0x%x\n", pp->csr_ptr->csr_event);
        printf("Socket mask: 0x%x\n", pp->csr_ptr->csr_mask);
    }

    csr_present= pp->csr_ptr->csr_present;
    csr_control= pp->csr_ptr->csr_control;

    if ((csr_present & (CP_CDETECT1|CP_CDETECT2)) != 0)
    {
        if (debug)
            printf("do_int: no card present\n");
        return;
    }
    if (csr_present & CP_BADVCCREQ)
    {
        printf("do_int: Bad Vcc request\n");
        /* return; */
    }
    if (csr_present & CP_DATALOST)
    {
        /* Do we care? */
        if (debug)
            printf("do_int: Data lost\n");
        /* return; */
    }
    if (csr_present & CP_NOTACARD)
    {
        printf("do_int: Not a card\n");
        return;
    }
    if (debug)
    {
        if (csr_present & CP_CBCARD)
            printf("do_int: Cardbus card detected\n");
        if (csr_present & CP_16BITCARD)
            printf("do_int: 16-bit card detected\n");
    }
    if (csr_present & CP_PWRCYCLE)
    {
        if (debug)
            printf("do_int: powered up\n");
        return;
    }
    vcc_5v= !!(csr_present & CP_5VCARD);
    vcc_3v= !!(csr_present & CP_3VCARD);
    vcc_Xv= !!(csr_present & CP_XVCARD);
    vcc_Yv= !!(csr_present & CP_YVCARD);
    if (debug)
    {
        printf("do_int: card supports:%s%s%s%s\n",
               vcc_5v ? " 5V" : "", vcc_3v ? " 3V" : "",
               vcc_Xv ? " X.X V" : "", vcc_Yv ? " Y.Y V" : "");
    }
    socket_5v= !!(csr_present & CP_5VSOCKET);
    socket_3v= !!(csr_present & CP_3VSOCKET);
    socket_Xv= !!(csr_present & CP_XVSOCKET);
    socket_Yv= !!(csr_present & CP_YVSOCKET);
    if (debug)
    {
        printf("do_int: socket supports:%s%s%s%s\n",
               socket_5v ? " 5V" : "", socket_3v ? " 3V" : "",
               socket_Xv ? " X.X V" : "", socket_Yv ? " Y.Y V" : "");
    }
    if (vcc_5v && socket_5v)
    {
        csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_5V;
        pp->csr_ptr->csr_control= csr_control;
        if (debug)
            printf("do_int: applying 5V\n");
    }
    else if (vcc_3v && socket_3v)
    {
        csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_3V;
        pp->csr_ptr->csr_control= csr_control;
        if (debug)
            printf("do_int: applying 3V\n");
    }
    else if (vcc_Xv && socket_Xv)
    {
        csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_XV;
        pp->csr_ptr->csr_control= csr_control;
        printf("do_int: applying X.X V\n");
    }
    else if (vcc_Yv && socket_Yv)
    {
        csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_YV;
        pp->csr_ptr->csr_control= csr_control;
        printf("do_int: applying Y.Y V\n");
    }
    else
    {
        printf("do_int: socket and card are not compatible\n");
        return;
    }

    csr_event= pp->csr_ptr->csr_event;
    if (csr_event)
    {
        if (debug)
            printf("clearing socket event\n");
        pp->csr_ptr->csr_event= csr_event;
        if (debug)
        {
            printf("Socket event (cleared): 0x%x\n",
                   pp->csr_ptr->csr_event);
        }
    }

    devind= pp->p_devind;
    v8= pci_attr_r8(devind, TI_CARD_CTRL);
    if (v8 & TI_CCR_IFG)
    {
        printf("ti1225: got functional interrupt\n");
        pci_attr_w8(devind, TI_CARD_CTRL, v8);
    }

    if (debug)
    {
        v8= pci_attr_r8(devind, TI_CARD_CTRL);
        printf("TI_CARD_CTRL: 0x%02x\n", v8);
    }

    spin_init(&spin, 100000);
    do {
        csr_present= pp->csr_ptr->csr_present;
        if (csr_present & CP_PWRCYCLE)
            break;
    } while (spin_check(&spin));

    if (!(csr_present & CP_PWRCYCLE))
    {
        printf("do_int: not powered up?\n");
        return;
    }

    /* Reset device */
    v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
    v16 |= CBB_BC_CRST;
    pci_attr_w16(devind, CBB_BRIDGECTRL, v16);

    /* Wait one microsecond. Is this correct? What are the specs? */
    micro_delay(1);

    /* Clear CBB_BC_CRST */
    v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
    v16 &= ~CBB_BC_CRST;
    pci_attr_w16(devind, CBB_BRIDGECTRL, v16);

    /* Wait one microsecond after clearing the reset line. Is this
     * correct? What are the specs?
     */
    micro_delay(1);

    pci_rescan_bus(pp->p_cb_busnr);

#if USE_INTS
    r= sys_irqenable(&pp->p_hook);
    if (r != OK)
        panic("unable enable interrupts: %d", r);
#endif

}
Ejemplo n.º 2
0
/*
 * Initialize the MMC controller given a certain
 * instance. this driver only handles a single
 * mmchs controller at a given time.
 */
int
mmchs_init(uint32_t instance)
{

	uint32_t value;
	value = 0;
	struct minix_mem_range mr;
	spin_t spin;

	mr.mr_base = MMCHS1_REG_BASE;
	mr.mr_limit = MMCHS1_REG_BASE + 0x400;

	if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
		panic("Unable to request permission to map memory");
	}

	/* Set the base address to use */
	base_address =
	    (uint32_t) vm_map_phys(SELF, (void *) MMCHS1_REG_BASE, 0x400);
	if (base_address == (uint32_t) MAP_FAILED)
		panic("Unable to map MMC memory");

#ifdef DM37XX
	base_address = (unsigned long) base_address - 0x100;
#endif

	/* Soft reset of the controller. This section is documented in the TRM 
	 */

	/* Write 1 to sysconfig[0] to trigger a reset */
	set32(base_address + MMCHS_SD_SYSCONFIG, MMCHS_SD_SYSCONFIG_SOFTRESET,
	    MMCHS_SD_SYSCONFIG_SOFTRESET);

	/* Read sysstatus to know when it's done */

	spin_init(&spin, SANE_TIMEOUT);
	while (!(read32(base_address + MMCHS_SD_SYSSTATUS)
		& MMCHS_SD_SYSSTATUS_RESETDONE)) {
		if (spin_check(&spin) == FALSE) {
			mmc_log_warn(&log, "mmc init timeout\n");
			return 1;
		}
	}

	/* Set SD default capabilities */
	set32(base_address + MMCHS_SD_CAPA, MMCHS_SD_CAPA_VS_MASK,
	    MMCHS_SD_CAPA_VS18 | MMCHS_SD_CAPA_VS30);

	/* TRM mentions MMCHS_SD_CUR_CAPA but does not describe how to limit
	 * the current */

	uint32_t mask =
	    MMCHS_SD_SYSCONFIG_AUTOIDLE | MMCHS_SD_SYSCONFIG_ENAWAKEUP |
	    MMCHS_SD_SYSCONFIG_STANDBYMODE | MMCHS_SD_SYSCONFIG_CLOCKACTIVITY |
	    MMCHS_SD_SYSCONFIG_SIDLEMODE;

	/* Automatic clock gating strategy */
	value = MMCHS_SD_SYSCONFIG_AUTOIDLE_EN;
	/* Enable wake-up capability */
	value |= MMCHS_SD_SYSCONFIG_ENAWAKEUP_EN;
	/* Smart-idle */
	value |= MMCHS_SD_SYSCONFIG_SIDLEMODE_IDLE;
	/* Both the interface and functional can be switched off */
	value |= MMCHS_SD_SYSCONFIG_CLOCKACTIVITY_OFF;
	/* Go into wake-up mode when possible */
	value |= MMCHS_SD_SYSCONFIG_STANDBYMODE_WAKEUP_INTERNAL;

	/* 
	 * wake-up configuration
	 */
	set32(base_address + MMCHS_SD_SYSCONFIG, mask, value);

	/* Wake-up on sd interrupt for SDIO */
	set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_IWE,
	    MMCHS_SD_HCTL_IWE_EN);

	/* 
	 * MMC host and bus configuration
	 */

	/* Configure data and command transfer (1 bit mode) */
	set32(base_address + MMCHS_SD_CON, MMCHS_SD_CON_DW8,
	    MMCHS_SD_CON_DW8_1BIT);
	set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_DTW,
	    MMCHS_SD_HCTL_DTW_1BIT);

	/* Configure card voltage to 3.0 volt */
	set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_SDVS,
	    MMCHS_SD_HCTL_SDVS_VS30);

	/* Power on the host controller and wait for the
	 * MMCHS_SD_HCTL_SDBP_POWER_ON to be set */
	set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_SDBP,
	    MMCHS_SD_HCTL_SDBP_ON);

	// /* TODO: Add padconf/pinmux stuff here as documented in the TRM */
	spin_init(&spin, SANE_TIMEOUT);
	while ((read32(base_address + MMCHS_SD_HCTL) & MMCHS_SD_HCTL_SDBP)
	    != MMCHS_SD_HCTL_SDBP_ON) {
		if (spin_check(&spin) == FALSE) {
			mmc_log_warn(&log, "mmc init timeout SDBP not set\n");
			return 1;
		}
	}

	/* Enable internal clock and clock to the card */
	set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_ICE,
	    MMCHS_SD_SYSCTL_ICE_EN);

	// @TODO Fix external clock enable , this one is very slow
	// but we first need faster context switching
	// set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CLKD,
	// (0x20 << 6));
	set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CLKD,
	    (0x5 << 6));

	set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CEN,
	    MMCHS_SD_SYSCTL_CEN_EN);

	spin_init(&spin, SANE_TIMEOUT);
	while ((read32(base_address + MMCHS_SD_SYSCTL) & MMCHS_SD_SYSCTL_ICS)
	    != MMCHS_SD_SYSCTL_ICS_STABLE) {

		if (spin_check(&spin) == FALSE) {
			mmc_log_warn(&log, "clock not stable\n");
			return 1;
		}
	}

	/* 
	 * See spruh73e page 3576  Card Detection, Identification, and Selection
	 */

	/* Enable command interrupt */
	set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_CC_ENABLE,
	    MMCHS_SD_IE_CC_ENABLE_ENABLE);
	/* Enable transfer complete interrupt */
	set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_TC_ENABLE,
	    MMCHS_SD_IE_TC_ENABLE_ENABLE);

	/* enable error interrupts */
	/* NOTE: We are currently skipping the BADA interrupt it does get
	 * raised for unknown reasons */
	set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_ERROR_MASK, 0x0fffffffu);

	/* clear the error interrupts */
	set32(base_address + MMCHS_SD_STAT, MMCHS_SD_STAT_ERROR_MASK,
	    0xffffffffu);

	/* send a init signal to the host controller. This does not actually
	 * send a command to a card manner */
	set32(base_address + MMCHS_SD_CON, MMCHS_SD_CON_INIT,
	    MMCHS_SD_CON_INIT_INIT);
	/* command 0 , type other commands not response etc) */
	write32(base_address + MMCHS_SD_CMD, 0x00);

	spin_init(&spin, SANE_TIMEOUT);
	while ((read32(base_address + MMCHS_SD_STAT) & MMCHS_SD_STAT_CC)
	    != MMCHS_SD_STAT_CC_RAISED) {
		if (read32(base_address + MMCHS_SD_STAT) & 0x8000) {
			mmc_log_warn(&log, "%s, error stat  %x\n",
			    __FUNCTION__,
			    read32(base_address + MMCHS_SD_STAT));
			return 1;
		}

		if (spin_check(&spin) == FALSE) {
			mmc_log_warn(&log,
			    "Interrupt not raised during init\n");
			return 1;
		}
	}

	/* clear the cc interrupt status */
	set32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_CC_ENABLE,
	    MMCHS_SD_IE_CC_ENABLE_ENABLE);

	/* 
	 * Set Set SD_CON[1] INIT bit to 0x0 to end the initialization sequence
	 */
	set32(base_address + MMCHS_SD_CON, MMCHS_SD_CON_INIT,
	    MMCHS_SD_CON_INIT_NOINIT);

	/* Set timeout */
	set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_DTO,
	    MMCHS_SD_SYSCTL_DTO_2POW27);

	/* Clean the MMCHS_SD_STAT register */
	write32(base_address + MMCHS_SD_STAT, 0xffffffffu);
#ifdef USE_INTR
	hook_id = 1;
	if (sys_irqsetpolicy(OMAP3_MMC1_IRQ, 0, &hook_id) != OK) {
		printf("mmc: couldn't set IRQ policy %d\n", OMAP3_MMC1_IRQ);
		return 1;
	}
	/* enable signaling from MMC controller towards interrupt controller */
	write32(base_address + MMCHS_SD_ISE, 0xffffffffu);
#endif

	return 0;
}
Ejemplo n.º 3
0
int
card_query_voltage_and_type(struct sd_card_regs *card)
{
	struct mmc_command command;
	spin_t spin;
	command.cmd = MMC_APP_CMD;
	command.resp_type = RESP_LEN_48;
	command.args = MMC_ARG_RCA(0x0);	/* RCA=0000 */

	if (mmc_send_cmd(&command)) {
		return 1;
	}

	command.cmd = SD_APP_OP_COND;
	command.resp_type = RESP_LEN_48;

	/* 0x1 << 30 == send HCS (Host capacity support) and get OCR register */
	command.args =
	    MMC_OCR_3_3V_3_4V | MMC_OCR_3_2V_3_3V | MMC_OCR_3_1V_3_2V |
	    MMC_OCR_3_0V_3_1V | MMC_OCR_2_9V_3_0V | MMC_OCR_2_8V_2_9V |
	    MMC_OCR_2_7V_2_8V;
	command.args |= MMC_OCR_HCS;	/* RCA=0000 */

	if (mmc_send_cmd(&command)) {
		return 1;
	}
	/* @todo wait for max 1 ms */
	spin_init(&spin, SANE_TIMEOUT);
	while (!(command.resp[0] & MMC_OCR_MEM_READY)) {
		command.cmd = MMC_APP_CMD;
		command.resp_type = RESP_LEN_48;
		command.args = MMC_ARG_RCA(0x0);	/* RCA=0000 */
		if (mmc_send_cmd(&command)) {
			return 1;
		}

		/* Send ADMD41 */
		/* 0x1 << 30 == send HCS (Host capacity support) and get OCR
		 * register */
		command.cmd = SD_APP_OP_COND;
		command.resp_type = RESP_LEN_48;
		/* 0x1 << 30 == send HCS (Host capacity support) */
		command.args = MMC_OCR_3_3V_3_4V | MMC_OCR_3_2V_3_3V
		    | MMC_OCR_3_1V_3_2V | MMC_OCR_3_0V_3_1V | MMC_OCR_2_9V_3_0V
		    | MMC_OCR_2_8V_2_9V | MMC_OCR_2_7V_2_8V;
		command.args |= MMC_OCR_HCS;	/* RCA=0000 */

		if (mmc_send_cmd(&command)) {
			return 1;
		}

		/* if bit 31 is set the response is valid */
		if ((command.resp[0] & MMC_OCR_MEM_READY)) {
			break;
		}
		if (spin_check(&spin) == FALSE) {
			mmc_log_warn(&log,
			    "TIMEOUT waiting for the SD card\n");
		}

	}
	card->ocr = command.resp[3];
	return 0;
}
Ejemplo n.º 4
0
/*===========================================================================*
 *				w_intr_wait				     *
 *===========================================================================*/
static int
intr_wait(int mask)
{
	long v;
#ifdef USE_INTR
	if (sys_irqenable(&hook_id) != OK)
		printf("Failed to enable irqenable irq\n");
	/* Wait for a task completion interrupt. */
	message m;
	int ipc_status;
	int ticks = SANE_TIMEOUT * sys_hz() / 1000000;

	if (ticks <= 0)
		ticks = 1;
	while (1) {
		int rr;
		sys_setalarm(ticks, 0);
		if ((rr = driver_receive(ANY, &m, &ipc_status)) != OK) {
			panic("driver_receive failed: %d", rr);
		};
		if (is_ipc_notify(ipc_status)) {
			switch (_ENDPOINT_P(m.m_source)) {
			case CLOCK:
				/* Timeout. */
				// w_timeout(); /* a.o. set w_status */
				mmc_log_warn(&log, "TIMEOUT\n");
				return 1;
				break;
			case HARDWARE:
				v = read32(base_address + MMCHS_SD_STAT);
				if (v & mask) {
					sys_setalarm(0, 0);
					return 0;
				} else if (v & (1 << 15)) {
					return 1;	/* error */
				} else {
					mmc_log_debug(&log,
					    "unexpected HW interrupt 0x%08x mask 0X%08x\n",
					    v, mask);
					if (sys_irqenable(&hook_id) != OK)
						printf
						    ("Failed to re-enable irqenable irq\n");
					continue;
					// return 1;
				}
			default:
				/* 
				 * unhandled message.  queue it and
				 * handle it in the blockdriver loop.
				 */
				blockdriver_mq_queue(&m, ipc_status);
			}
		} else {
			mmc_log_debug(&log, "Other\n");
			/* 
			 * unhandled message.  queue it and handle it in the
			 * blockdriver loop.
			 */
			blockdriver_mq_queue(&m, ipc_status);
		}
	}
	sys_setalarm(0, 0);	/* cancel the alarm */

#else
	spin_t spin;
	spin_init(&spin, SANE_TIMEOUT);
	/* Wait for completion */
	int counter = 0;
	while (1 == 1) {
		counter++;
		v = read32(base_address + MMCHS_SD_STAT);
		if (spin_check(&spin) == FALSE) {
			mmc_log_warn(&log,
			    "Timeout waiting for interrupt (%d) value 0x%08x mask 0x%08x\n",
			    counter, v, mask);
			return 1;
		}
		if (v & mask) {
			return 0;
		} else if (v & 0xFF00) {
			mmc_log_debug(&log,
			    "unexpected HW interrupt (%d) 0x%08x mask 0x%08x\n",
			    v, mask);
			return 1;
		}
	}
	return 1;		/* unreached */
#endif /* USE_INTR */
}