Beispiel #1
0
status_t platform_set_periodic_timer(
	platform_timer_callback callback,
	void *arg, time_t interval)
{
#ifdef PLATFORM_MSM7X30
        unsigned val = 0;
	unsigned mask = (0x1 << 28);
	//Check for the hardware revision
	val = readl(HW_REVISION_NUMBER);
	if(val & mask)
	    writel(1, DGT_CLK_CTL);
#endif
	enter_critical_section();

	timer_callback = callback;
	timer_arg = arg;
	timer_interval = interval;

	writel(timer_interval * (DGT_HZ / 1000), DGT_MATCH_VAL);
	writel(0, DGT_CLEAR);
	writel(DGT_ENABLE_EN | DGT_ENABLE_CLR_ON_MATCH_EN, DGT_ENABLE);
	
	register_int_handler(INT_DEBUG_TIMER_EXP, timer_irq, 0);
	unmask_interrupt(INT_DEBUG_TIMER_EXP);

	exit_critical_section();
	return 0;
}
Beispiel #2
0
Datei: net.c Projekt: 0xBADCA7/lk
status_t ethernet_init(void)
{
    /* check to see if the ethernet feature is turned on */
    if ((*REG(SYSINFO_FEATURES) & SYSINFO_FEATURE_NETWORK) == 0)
        return ERR_NOT_FOUND;

    struct netif *netif = calloc(sizeof(struct netif), 1);
    struct ip_addr *ipaddr = calloc(sizeof(struct ip_addr), 1);
    struct ip_addr *netmask = calloc(sizeof(struct ip_addr), 1);
    struct ip_addr *gw = calloc(sizeof(struct ip_addr), 1);

    struct netif *netifret = netif_add(netif, ipaddr, netmask, gw, NULL, &ethernetif_init, &ip_input);
    if (netifret == NULL) {
        free(netif);
        free(ipaddr);
        free(netmask);
        free(gw);
        return ERR_NOT_FOUND;
    }

    /* register for interrupt handlers */
    register_int_handler(INT_NET, ethernet_int, netif);

    netif_set_default(netif);

    unmask_interrupt(INT_NET, NULL);

    return NO_ERROR;
}
Beispiel #3
0
void arm_generic_timer_init(int irq, uint32_t freq_override)
{
	uint32_t cntfrq;

	if (freq_override == 0) {
		cntfrq = read_cntfrq();

		if (!cntfrq) {
			TRACEF("Failed to initialize timer, frequency is 0\n");
			return;
		}
	} else {
		cntfrq = freq_override;
	}

#if LOCAL_TRACE
	LTRACEF("Test min cntfrq\n");
	arm_generic_timer_init_conversion_factors(1);
	test_time_conversions(1);
	LTRACEF("Test max cntfrq\n");
	arm_generic_timer_init_conversion_factors(~0);
	test_time_conversions(~0);
	LTRACEF("Set actual cntfrq\n");
#endif
	arm_generic_timer_init_conversion_factors(cntfrq);
	test_time_conversions(cntfrq);

	LTRACEF("register irq %d on cpu %d\n", irq, arch_curr_cpu_num());
	register_int_handler(irq, &platform_tick, NULL);
	unmask_interrupt(irq);

	timer_irq = irq;
}
Beispiel #4
0
Datei: timer.c Projekt: M1cha/lk
status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, lk_time_t interval)
{
    LTRACEF("callback %p, arg %p, interval %lu\n", callback, arg, interval);

    enter_critical_section();

    t_callback = callback;

    /* disable the timer */
    ARM64_WRITE_SYSREG(CNTP_CTL_EL0, 0);

    /* set the countdown register to max */
    ARM64_WRITE_SYSREG(CNTP_TVAL_EL0, INT32_MAX);

    /* calculate the compare delta and set the comparison register */
    interval_delta = (uint64_t)timer_freq * interval / 1000U;
    last_compare = read_counter() + interval_delta;
    ARM64_WRITE_SYSREG(CNTP_CVAL_EL0, last_compare);

    ARM64_WRITE_SYSREG(CNTP_CTL_EL0, 1);

    unmask_interrupt(INT_PPI_NSPHYS_TIMER);

    exit_critical_section();

    return NO_ERROR;
}
Beispiel #5
0
/* Enable BAM and pipe level interrupts */
void bam_enable_interrupts(struct bam_instance *bam, uint8_t pipe_num)
{

	uint32_t int_mask = P_ERR_EN_MASK | P_OUT_OF_DESC_EN_MASK |
						P_PRCSD_DESC_EN_MASK | P_TRNSFR_END_EN_MASK;
	uint32_t val;

	/* Enable BAM error interrupts */
	writel(BAM_ERROR_EN_MASK, BAM_IRQ_EN_REG(bam->base));

	/* Enable the interrupts for the pipe by enabling the relevant bits
	 * in the BAM_PIPE_INTERRUPT_ENABLE register.
	 */
	writel(int_mask,
			BAM_P_IRQ_ENn(bam->pipe[pipe_num].pipe_num, bam->base));

	/* Enable pipe interrups */
	/* Do read-modify-write */
	val = readl(BAM_IRQ_SRCS_MSK(bam->base));
	writel((1 << bam->pipe[pipe_num].pipe_num) | val,
			BAM_IRQ_SRCS_MSK(bam->base));

	/* Unmask the QGIC interrupts only in the case of
	 * interrupt based transfer.
	 * Use polling othwerwise.
	 */
	if (bam->pipe[pipe_num].int_mode)
	{
		/* Register interrupt handler */
		register_int_handler(bam->pipe[pipe_num].spi_num, bam_interrupt_handler, 0);

		/* Unmask the interrupt */
		unmask_interrupt(bam->pipe[pipe_num].spi_num);
	}
}
Beispiel #6
0
int smd_init(smd_channel_info_t *ch, uint32_t ch_type)
{
	unsigned ret = 0;

	smd_channel_alloc_entry = (smd_channel_alloc_entry_t*)memalign(CACHE_LINE, SMD_CHANNEL_ALLOC_MAX);
	ASSERT(smd_channel_alloc_entry);

	ret = smem_read_alloc_entry(SMEM_CHANNEL_ALLOC_TBL,
							(void*)smd_channel_alloc_entry,
							SMD_CHANNEL_ALLOC_MAX);
	if(ret)
	{
		dprintf(CRITICAL,"ERROR reading smem channel alloc tbl\n");
		return -1;
	}

	smd_get_channel_info(ch, ch_type);

	register_int_handler(SMD_IRQ, smd_irq_handler, ch);
	unmask_interrupt(SMD_IRQ);

	smd_set_state(ch, SMD_SS_OPENING, 1);

	smd_notify_rpm();

	return 0;
}
Beispiel #7
0
void platform_init_timer(void)
{
#if 0
	OS_TIMER_CTRL_REG = 0; // stop the timer if it's already running

	register_int_handler(IRQ_OS_TIMER, &os_timer_tick, NULL);
	unmask_interrupt(IRQ_OS_TIMER, NULL);
#endif
}
Beispiel #8
0
void __attribute__((noreturn)) thread_n_main(void)
{
    boot_init_thread();
    unmask_interrupt(1);    // Enable timer interrupt

    // Idle task
    for (;;)
        reschedule();
}
Beispiel #9
0
void uart_init(void)
{
    /* finish uart init to get rx going */
    cbuf_initialize(&uart_rx_buf, 16);

    register_int_handler(0x24, uart_irq_handler, NULL);
    unmask_interrupt(0x24);

    outp(uart_io_port + 1, 0x1); // enable receive data available interrupt
}
Beispiel #10
0
static void arm_cortex_a9_timer_init_percpu(uint level)
{
    /* disable timer */
    TIMREG(TIMER_CONTROL) = 0;

    /* kill the watchdog */
    TIMREG(WDOG_CONTROL) = 0;

    /* ack any irqs that may be pending */
    TIMREG(TIMER_ISR) = 1;

    /* register the platform tick on each cpu */
    register_int_handler(CPU_PRIV_TIMER_INT, &platform_tick, NULL);
    unmask_interrupt(CPU_PRIV_TIMER_INT);
}
Beispiel #11
0
status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, lk_time_t interval)
{
	enter_critical_section();

	t_callback = callback;

	periodic_interval = interval;
	TIMREG(LOADVAL) = periodic_interval * 1000; /* timer is running at 1Mhz */

	TIMREG(CONTROL) |= (1<<7); // enable

	unmask_interrupt(TIMER01_INT);

	exit_critical_section();

	return NO_ERROR;
}
Beispiel #12
0
/*
 * Function: sdhci msm init
 * Arg     : MSM specific config data for sdhci
 * Return  : None
 * Flow:   : Enable sdhci mode & do msm specific init
 */
void sdhci_msm_init(struct sdhci_host *host, struct sdhci_msm_data *config)
{
	/* Disable HC mode */
	RMWREG32((config->pwrctl_base + SDCC_MCI_HC_MODE), SDHCI_HC_START_BIT, SDHCI_HC_WIDTH, 0);

	/* Core power reset */
	RMWREG32((config->pwrctl_base + SDCC_MCI_POWER), CORE_SW_RST_START, CORE_SW_RST_WIDTH, 1);

	/* Wait for the core power reset to complete*/
	 mdelay(1);

	/* Enable sdhc mode */
	RMWREG32((config->pwrctl_base + SDCC_MCI_HC_MODE), SDHCI_HC_START_BIT, SDHCI_HC_WIDTH, SDHCI_HC_MODE_EN);

	/* Set the FF_CLK_SW_RST_DIS to 1 */
	RMWREG32((config->pwrctl_base + SDCC_MCI_HC_MODE), FF_CLK_SW_RST_DIS_START, FF_CLK_SW_RST_DIS_WIDTH, 1);

	/*
	 * Reset the controller
	 */
	sdhci_reset(host, SDHCI_SOFT_RESET);

	/*
	 * CORE_SW_RST may trigger power irq if previous status of PWRCTL
	 * was either BUS_ON or IO_HIGH. So before we enable the power irq
	 * interrupt in GIC (by registering the interrupt handler), we need to
	 * ensure that any pending power irq interrupt status is acknowledged
	 * otherwise power irq interrupt handler would be fired prematurely.
	 */
	sdhci_clear_power_ctrl_irq(config);

	/*
	 * Register the interrupt handler for pwr irq
	 */
	register_int_handler(config->pwr_irq, sdhci_int_handler, (void *)config);

	unmask_interrupt(config->pwr_irq);

	/* Enable pwr control interrupt */
	writel(SDCC_HC_PWR_CTRL_INT, (config->pwrctl_base + SDCC_HC_PWRCTL_MASK_REG));

	config->tuning_done = false;
	config->calibration_done = false;
	host->tuning_in_progress = false;
}
Beispiel #13
0
static void imx_uart_init(const void* driver_data, uint32_t length) {
    uint32_t regVal;

    // create circular buffer to hold received data
    cbuf_initialize(&uart_rx_buf, RXBUF_SIZE);

    // register uart irq
    register_int_handler(uart_irq, &uart_irq_handler, NULL);

    // set rx fifo threshold to 1 character
    regVal = UARTREG(MX8_UFCR);
    regVal &= ~UFCR_RXTL(UFCR_MASK);
    regVal &= ~UFCR_TXTL(UFCR_MASK);
    regVal |= UFCR_RXTL(1);
    regVal |= UFCR_TXTL(0x2);
    UARTREG(MX8_UFCR) = regVal;

    // enable rx interrupt
    regVal = UARTREG(MX8_UCR1);
    regVal |= UCR1_RRDYEN;
    if (dlog_bypass() == false) {
        // enable tx interrupt
        regVal |= UCR1_TRDYEN;
    }
    UARTREG(MX8_UCR1) = regVal;

    // enable rx and tx transmisster
    regVal = UARTREG(MX8_UCR2);
    regVal |= UCR2_RXEN | UCR2_TXEN;
    UARTREG(MX8_UCR2) = regVal;

    if (dlog_bypass() == true) {
        uart_tx_irq_enabled = false;
    } else {
        /* start up tx driven output */
        printf("UART: started IRQ driven TX\n");
        uart_tx_irq_enabled = true;
    }

    initialized = true;

    // enable interrupts
    unmask_interrupt(uart_irq);
}
Beispiel #14
0
Datei: smd.c Projekt: jaehyek/lk
int smd_init(smd_channel_info_t *ch, uint32_t ch_type)
{
	unsigned ret = 0;
	int chnl_found = 0;
	uint64_t timeout = SMD_CHANNEL_ACCESS_RETRY;

	smd_channel_alloc_entry = (smd_channel_alloc_entry_t*)memalign(CACHE_LINE, SMD_CHANNEL_ALLOC_MAX);
	ASSERT(smd_channel_alloc_entry);

	dprintf(INFO, "Waiting for the RPM to populate smd channel table\n");

	do
	{
		ret = smem_read_alloc_entry(SMEM_CHANNEL_ALLOC_TBL,
									(void*)smd_channel_alloc_entry,
									SMD_CHANNEL_ALLOC_MAX);
		if(ret)
		{
			dprintf(CRITICAL,"ERROR reading smem channel alloc tbl\n");
			return -1;
		}

		chnl_found = smd_get_channel_info(ch, ch_type);
		timeout--;
		udelay(10);
	} while(timeout && chnl_found);

	if (!timeout)
	{
		dprintf(CRITICAL, "Apps timed out waiting for RPM-->APPS channel entry\n");
		ASSERT(0);
	}

	register_int_handler(SMD_IRQ, smd_irq_handler, ch);

	smd_set_state(ch, SMD_SS_OPENING, 1);

	smd_notify_rpm();

	unmask_interrupt(SMD_IRQ);

	return 0;
}
Beispiel #15
0
status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, lk_time_t interval)
{
	enter_critical_section();

	t_callback = callback;
	callback_arg = arg;
	tick_interval = interval;
	uint32_t ticks_per_interval = (uint64_t)interval * TIMER_TICK_RATE / 1000; // interval is in ms

	TIMER_REG(TCLR) = 0; // stop the timer
	TIMER_REG(TLDR) = -ticks_per_interval;
	TIMER_REG(TTGR) = 1;
	TIMER_REG(TIER) = 0x2;
	TIMER_REG(TCLR) = 0x3; // autoreload, start

	unmask_interrupt(GPT2_IRQ);

	exit_critical_section();

	return NO_ERROR;
}
Beispiel #16
0
status_t
platform_set_periodic_timer(platform_timer_callback callback,
			    void *arg, lk_time_t interval)
{
	uint32_t tick_count = interval * platform_tick_rate() / 1000;

	enter_critical_section();

	timer_callback = callback;
	timer_arg = arg;
	timer_interval = interval;

	writel(tick_count, DGT_MATCH_VAL);
	writel(0, DGT_CLEAR);
	writel(DGT_ENABLE_EN | DGT_ENABLE_CLR_ON_MATCH_EN, DGT_ENABLE);

	register_int_handler(INT_DEBUG_TIMER_EXP, timer_irq, 0);
	unmask_interrupt(INT_DEBUG_TIMER_EXP);

	exit_critical_section();
	return 0;
}
Beispiel #17
0
status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, lk_time_t interval)
{
    spin_lock_saved_state_t statep;
    arch_interrupt_save(&statep, SPIN_LOCK_FLAG_IRQ);

    t_callback = callback;
    callback_arg = arg;
    tick_interval = interval;
    uint32_t ticks_per_interval = (uint64_t)interval * TIMER_TICK_RATE / 1000; // interval is in ms

    TIMER_REG(TCLR) = 0; // stop the timer
    TIMER_REG(TLDR) = -ticks_per_interval;
    TIMER_REG(TTGR) = 1;
    TIMER_REG(TIER) = 0x2;
    TIMER_REG(TCLR) = 0x3; // autoreload, start

    unmask_interrupt(GPT2_IRQ);

    arch_interrupt_restore(statep, SPIN_LOCK_FLAG_IRQ);

    return NO_ERROR;
}
Beispiel #18
0
status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, lk_time_t interval)
{
    enter_critical_section();

    LTRACEF("callback %p, arg %p, interval %lu\n", callback, arg, interval);

    t_callback = callback;

    periodic_interval = interval;

    uint32_t ticks = periodic_interval * 1000; /* timer is running close to 1Mhz */
    ASSERT(ticks <= 0xffff);

    TIMREG(IEN(0)) = (1<<0); // interval interrupt
    TIMREG(INTERVAL_VAL(0)) = ticks;
    TIMREG(CNT_CTRL(0)) = (1<<5) | (1<<4) | (1<<1); // no wave, reset, interval mode

    unmask_interrupt(TTC0_A_INT);

    exit_critical_section();

    return NO_ERROR;
}
Beispiel #19
0
status_t
platform_set_periodic_timer(platform_timer_callback callback,
			    void *arg, lk_time_t interval)
{
	uint32_t tick_count = interval * ticks_per_sec / 1000;

	spin_lock_saved_state_t state;
	spin_lock_irqsave(&lock, state);

	timer_callback = callback;
	timer_arg = arg;
	timer_interval = interval;

	writel(tick_count, DGT_MATCH_VAL);
	writel(0, DGT_CLEAR);
	writel(DGT_ENABLE_EN | DGT_ENABLE_CLR_ON_MATCH_EN, DGT_ENABLE);

	register_int_handler(INT_DEBUG_TIMER_EXP, timer_irq, 0);
	unmask_interrupt(INT_DEBUG_TIMER_EXP);

	spin_unlock_irqrestore(&lock, state);
	return 0;
}
Beispiel #20
0
Datei: timer.c Projekt: M1cha/lk
status_t platform_set_oneshot_timer (platform_timer_callback callback, void *arg, lk_time_t interval)
{
    LTRACEF("callback %p, arg %p, interval %lu\n", callback, arg, interval);

    enter_critical_section();

    t_callback = callback;

    /* disable the timer */
    ARM64_WRITE_SYSREG(CNTP_CTL_EL0, 0);

    /* set the countdown register to max */
    ARM64_WRITE_SYSREG(CNTP_TVAL_EL0, INT32_MAX);

    /* calculate the interval */
    uint64_t ticks = (uint64_t)timer_freq * interval / 1000U;

    /* set the comparison register */
    uint64_t counter = read_counter();
    counter += ticks;

    LTRACEF("new counter 0x%llx ticks %llu\n", counter, ticks);

    ARM64_WRITE_SYSREG(CNTP_CVAL_EL0, counter);

    /* disable periodic mode */
    interval_delta = 0;

    /* start the timer, unmask irq */
    ARM64_WRITE_SYSREG(CNTP_CTL_EL0, 1);

    unmask_interrupt(INT_PPI_NSPHYS_TIMER);

    exit_critical_section();

    return NO_ERROR;
}
Beispiel #21
0
void arm_cortex_a9_timer_init(addr_t _scu_control_base, uint32_t freq)
{
    scu_control_base = _scu_control_base;

    /* disable timer */
    TIMREG(TIMER_CONTROL) = 0;

    /* kill the watchdog */
    TIMREG(WDOG_CONTROL) = 0;

    /* ack any irqs that may be pending */
    TIMREG(TIMER_ISR) = 1;

    /* save the timer frequency for later calculations */
    timer_freq = freq;

    /* precompute the conversion factor for global time to real time */
    fp_32_64_div_32_32(&timer_freq_msec_conversion, timer_freq, 1000);
    fp_32_64_div_32_32(&timer_freq_usec_conversion_inverse, 1000000, timer_freq);
    fp_32_64_div_32_32(&timer_freq_msec_conversion_inverse, 1000, timer_freq);

    register_int_handler(CPU_PRIV_TIMER_INT, &platform_tick, NULL);
    unmask_interrupt(CPU_PRIV_TIMER_INT);
}
Beispiel #22
0
void register_interrupt_handler(int interrupt, interrupt_handler_t handler)
{
    // XXX lock
    handlers[interrupt] = handler;
    unmask_interrupt(interrupt);
}
Beispiel #23
0
static void arm_generic_timer_init_secondary_cpu(uint level)
{
	LTRACEF("register irq %d on cpu %d\n", timer_irq, arch_curr_cpu_num());
	register_int_handler(timer_irq, &platform_tick, NULL);
	unmask_interrupt(timer_irq);
}
Beispiel #24
0
static void pc_init_timer(uint level) {
    const struct x86_model_info* cpu_model = x86_get_model();

    constant_tsc = false;
    if (x86_vendor == X86_VENDOR_INTEL) {
        /* This condition taken from Intel 3B 17.15 (Time-Stamp Counter).  This
         * is the negation of the non-Constant TSC section, since the Constant
         * TSC section is incomplete (the behavior is architectural going
         * forward, and modern CPUs are not on the list). */
        constant_tsc = !((cpu_model->family == 0x6 && cpu_model->model == 0x9) ||
                         (cpu_model->family == 0x6 && cpu_model->model == 0xd) ||
                         (cpu_model->family == 0xf && cpu_model->model < 0x3));
    }
    invariant_tsc = x86_feature_test(X86_FEATURE_INVAR_TSC);

    bool has_pvclock = pvclock_is_present();
    if (has_pvclock) {
        zx_status_t status = pvclock_init();
        if (status == ZX_OK) {
            invariant_tsc = pvclock_is_stable();
        } else {
            has_pvclock = false;
        }
    }

    bool has_hpet = hpet_is_present();
    if (has_hpet) {
        calibration_clock = CLOCK_HPET;
        const uint64_t hpet_ms_rate = hpet_ticks_per_ms();
        ASSERT(hpet_ms_rate <= UINT32_MAX);
        printf("HPET frequency: %" PRIu64 " ticks/ms\n", hpet_ms_rate);
        fp_32_64_div_32_32(&ns_per_hpet, 1000 * 1000, static_cast<uint32_t>(hpet_ms_rate));
        // Add 1ns to conservatively deal with rounding
        ns_per_hpet_rounded_up = u32_mul_u64_fp32_64(1, ns_per_hpet) + 1;
    } else {
        calibration_clock = CLOCK_PIT;
    }

    const char* force_wallclock = cmdline_get("kernel.wallclock");
    bool use_invariant_tsc = invariant_tsc && (!force_wallclock || !strcmp(force_wallclock, "tsc"));

    use_tsc_deadline = use_invariant_tsc &&
                       x86_feature_test(X86_FEATURE_TSC_DEADLINE);
    if (!use_tsc_deadline) {
        calibrate_apic_timer();
    }

    if (use_invariant_tsc) {
        calibrate_tsc(has_pvclock);

        // Program PIT in the software strobe configuration, but do not load
        // the count.  This will pause the PIT.
        outp(I8253_CONTROL_REG, 0x38);
        wall_clock = CLOCK_TSC;
    } else {
        if (constant_tsc || invariant_tsc) {
            // Calibrate the TSC even though it's not as good as we want, so we
            // can still let folks still use it for cheap timing.
            calibrate_tsc(has_pvclock);
        }

        if (has_hpet && (!force_wallclock || !strcmp(force_wallclock, "hpet"))) {
            wall_clock = CLOCK_HPET;
            hpet_set_value(0);
            hpet_enable();
        } else {
            if (force_wallclock && strcmp(force_wallclock, "pit")) {
                panic("Could not satisfy kernel.wallclock choice\n");
            }

            wall_clock = CLOCK_PIT;

            set_pit_frequency(1000); // ~1ms granularity

            uint32_t irq = apic_io_isa_to_global(ISA_IRQ_PIT);
            zx_status_t status = register_int_handler(irq, &pit_timer_tick, NULL);
            DEBUG_ASSERT(status == ZX_OK);
            unmask_interrupt(irq);
        }
    }

    printf("timer features: constant_tsc %d invariant_tsc %d tsc_deadline %d\n",
           constant_tsc, invariant_tsc, use_tsc_deadline);
    printf("Using %s as wallclock\n", clock_name[wall_clock]);
}
Beispiel #25
0
int msm_i2c_xfer(struct i2c_msg msgs[], int num)
{
	int ret, ret_wait;

	clk_enable(dev.pdata->clk_nr);
	unmask_interrupt(dev.pdata->irq_nr);

	ret = msm_i2c_poll_notbusy(1);

	if (ret) {
		ret = msm_i2c_recover_bus_busy();
		if (ret)
			goto err;
	}

	enter_critical_section();
	if (dev.flush_cnt) {
		I2C_DBG(DEBUGLEVEL, "%d unrequested bytes read\n", dev.flush_cnt);
	}
	dev.msg = msgs;
	dev.rem = num;
	dev.pos = -1;
	dev.ret = num;
	dev.need_flush = false;
	dev.flush_cnt = 0;
	dev.cnt = msgs->len;
	msm_i2c_interrupt_locked();
	exit_critical_section();

	/*
	 * Now that we've setup the xfer, the ISR will transfer the data
	 * and wake us up with dev.err set if there was an error
	 */
	ret_wait = msm_i2c_poll_notbusy(0); /* Read may not have stopped in time */
	
	enter_critical_section();
	if (dev.flush_cnt) {
		I2C_DBG(DEBUGLEVEL, "%d unrequested bytes read\n", dev.flush_cnt);
	}
	ret = dev.ret;
	dev.msg = NULL;
	dev.rem = 0;
	dev.pos = 0;
	dev.ret = 0;
	dev.flush_cnt = 0;
	dev.cnt = 0;
	exit_critical_section();

	if (ret_wait) {
		I2C_DBG(DEBUGLEVEL, "Still busy after xfer completion\n");
		ret_wait = msm_i2c_recover_bus_busy();
		if (ret_wait)
			goto err;
	}
	if (timeout == ERR_TIMED_OUT) {
		I2C_DBG(DEBUGLEVEL, "Transaction timed out\n");
		ret = ERR_TIMED_OUT;
	}
	if (ret < 0) {
		I2C_ERR("Error during data xfer (%d)\n", ret);
		msm_i2c_recover_bus_busy();
	}
	/* if (timeout == ERR_TIMED_OUT) {
		I2C_DBG(DEBUGLEVEL, "Transaction timed out\n");
		ret = 2;
		msm_i2c_recover_bus_busy();
	}
	if (timeout == ERR_TIMED_OUT) {
		I2C_DBG(DEBUGLEVEL, "Transaction timed out\n");
		ret = ERR_TIMED_OUT;
	}
	if (ret < 0) {
		I2C_ERR("Error during data xfer (%d)\n", ret);
		msm_i2c_recover_bus_busy();
	} */
err:
	mask_interrupt(dev.pdata->irq_nr);
	clk_disable(dev.pdata->clk_nr);
	
	return ret;
}
Beispiel #26
0
/*
 * Function: sdhci msm init
 * Arg     : MSM specific config data for sdhci
 * Return  : None
 * Flow:   : Enable sdhci mode & do msm specific init
 */
void sdhci_msm_init(struct sdhci_host *host, struct sdhci_msm_data *config)
{
	uint32_t io_switch;
	uint32_t caps = 0;
	uint32_t version;

	/* Disable HC mode */
	RMWREG32((config->pwrctl_base + SDCC_MCI_HC_MODE), SDHCI_HC_START_BIT, SDHCI_HC_WIDTH, 0);

	/* Core power reset */
	RMWREG32((config->pwrctl_base + SDCC_MCI_POWER), CORE_SW_RST_START, CORE_SW_RST_WIDTH, 1);

	/* Wait for the core power reset to complete*/
	 mdelay(1);

	/* Enable sdhc mode */
	RMWREG32((config->pwrctl_base + SDCC_MCI_HC_MODE), SDHCI_HC_START_BIT, SDHCI_HC_WIDTH, SDHCI_HC_MODE_EN);

	/* Set the FF_CLK_SW_RST_DIS to 1 */
	RMWREG32((config->pwrctl_base + SDCC_MCI_HC_MODE), FF_CLK_SW_RST_DIS_START, FF_CLK_SW_RST_DIS_WIDTH, 1);

	/*
	 * Reset the controller
	 */
	sdhci_reset(host, SDHCI_SOFT_RESET);

	/*
	 * Some platforms have same SDC instance shared between emmc & sd card.
	 * For such platforms the emmc IO voltage has to be switched from 3.3 to
	 * 1.8 for the contoller to work with emmc.
	 */

	if(config->use_io_switch)
	{
		io_switch = REG_READ32(host, SDCC_VENDOR_SPECIFIC_FUNC);
		io_switch |= HC_IO_PAD_PWR_SWITCH | HC_IO_PAD_PWR_SWITCH_EN;
		REG_WRITE32(host, io_switch, SDCC_VENDOR_SPECIFIC_FUNC);
	}

	/*
	 * CORE_SW_RST may trigger power irq if previous status of PWRCTL
	 * was either BUS_ON or IO_HIGH. So before we enable the power irq
	 * interrupt in GIC (by registering the interrupt handler), we need to
	 * ensure that any pending power irq interrupt status is acknowledged
	 * otherwise power irq interrupt handler would be fired prematurely.
	 */
	sdhci_clear_power_ctrl_irq(config);

	/*
	 * Register the interrupt handler for pwr irq
	 */
	register_int_handler(config->pwr_irq, (int_handler)sdhci_int_handler, (void *)config);

	unmask_interrupt(config->pwr_irq);

	/* Enable pwr control interrupt */
	writel(SDCC_HC_PWR_CTRL_INT, (config->pwrctl_base + SDCC_HC_PWRCTL_MASK_REG));

	version = readl(host->msm_host->pwrctl_base + MCI_VERSION);

	host->major = (version & CORE_VERSION_MAJOR_MASK) >> CORE_VERSION_MAJOR_SHIFT;
	host->minor = (version & CORE_VERSION_MINOR_MASK);

	/*
	 * For SDCC5 the capabilities registers does not have voltage advertised
	 * Override the values using SDCC_HC_VENDOR_SPECIFIC_CAPABILITIES0
	 */
	if (host->major >= 1 && host->minor != 0x11 && host->minor != 0x12)
	{
		caps = REG_READ32(host, SDHCI_CAPS_REG1);

		if (config->slot == 0x1)
			REG_WRITE32(host, (caps | SDHCI_1_8_VOL_MASK), SDCC_HC_VENDOR_SPECIFIC_CAPABILITIES0);
		else
			REG_WRITE32(host, (caps | SDHCI_3_0_VOL_MASK), SDCC_HC_VENDOR_SPECIFIC_CAPABILITIES0);
	}

	config->tuning_done = false;
	config->calibration_done = false;
	host->tuning_in_progress = false;
}
Beispiel #27
0
int virtio_mmio_detect(void *ptr, uint count, const uint irqs[])
{
    LTRACEF("ptr %p, count %u\n", ptr, count);

    DEBUG_ASSERT(ptr);
    DEBUG_ASSERT(irqs);
    DEBUG_ASSERT(!devices);

    /* allocate an array big enough to hold a list of devices */
    devices = calloc(count, sizeof(struct virtio_device));
    if (!devices)
        return ERR_NO_MEMORY;

    int found = 0;
    for (uint i = 0; i < count; i++) {
        volatile struct virtio_mmio_config *mmio = (struct virtio_mmio_config *)((uint8_t *)ptr + i * 0x200);
        struct virtio_device *dev = &devices[i];

        dev->index = i;
        dev->irq = irqs[i];

        mask_interrupt(irqs[i]);
        register_int_handler(irqs[i], &virtio_mmio_irq, (void *)dev);

        LTRACEF("looking at magic 0x%x version 0x%x did 0x%x vid 0x%x\n",
                mmio->magic, mmio->version, mmio->device_id, mmio->vendor_id);

        if (mmio->magic != VIRTIO_MMIO_MAGIC) {
            continue;
        }

#if LOCAL_TRACE
        if (mmio->device_id != 0) {
            dump_mmio_config(mmio);
        }
#endif

#if WITH_DEV_VIRTIO_BLOCK
        if (mmio->device_id == 2) { // block device
            LTRACEF("found block device\n");

            dev->mmio_config = mmio;
            dev->config_ptr = (void *)mmio->config;

            status_t err = virtio_block_init(dev, mmio->host_features);
            if (err >= 0) {
                // good device
                dev->valid = true;

                if (dev->irq_driver_callback)
                    unmask_interrupt(dev->irq);

                // XXX quick test code, remove
#if 0
                uint8_t buf[512];
                memset(buf, 0x99, sizeof(buf));
                virtio_block_read_write(dev, buf, 0, sizeof(buf), false);
                hexdump8_ex(buf, sizeof(buf), 0);

                buf[0]++;
                virtio_block_read_write(dev, buf, 0, sizeof(buf), true);

                virtio_block_read_write(dev, buf, 0, sizeof(buf), false);
                hexdump8_ex(buf, sizeof(buf), 0);
#endif
            }

        }
#endif // WITH_DEV_VIRTIO_BLOCK
#if WITH_DEV_VIRTIO_NET
        if (mmio->device_id == 1) { // network device
            LTRACEF("found net device\n");

            dev->mmio_config = mmio;
            dev->config_ptr = (void *)mmio->config;

            status_t err = virtio_net_init(dev, mmio->host_features);
            if (err >= 0) {
                // good device
                dev->valid = true;

                if (dev->irq_driver_callback)
                    unmask_interrupt(dev->irq);
            }
        }
#endif // WITH_DEV_VIRTIO_NET
#if WITH_DEV_VIRTIO_GPU
        if (mmio->device_id == 0x10) { // virtio-gpu
            LTRACEF("found gpu device\n");

            dev->mmio_config = mmio;
            dev->config_ptr = (void *)mmio->config;

            status_t err = virtio_gpu_init(dev, mmio->host_features);
            if (err >= 0) {
                // good device
                dev->valid = true;

                if (dev->irq_driver_callback)
                    unmask_interrupt(dev->irq);

                virtio_gpu_start(dev);
            }
        }
#endif // WITH_DEV_VIRTIO_GPU

        if (dev->valid)
            found++;
    }

    return found;
}