void hal_timer_oc_output_set(channelid_t channel_id, ocmode_t mode) {
    uint32_t modeFlags = IORD32(A_SCCT, SCCT_CH_AS);
    switch (channel_id) {
    case INJECTION1_OUTPUT:
        hal_internal_calculate_mode_flags(2, mode, modeFlags)
        ;
        break;
    case INJECTION2_OUTPUT:
        hal_internal_calculate_mode_flags(3, mode, modeFlags)
        ;
        break;
    case INJECTION3_OUTPUT:
        hal_internal_calculate_mode_flags(4, mode, modeFlags)
        ;
        break;
    case INJECTION4_OUTPUT:
        hal_internal_calculate_mode_flags(5, mode, modeFlags)
        ;
        break;
    case INJECTION5_OUTPUT:
        hal_internal_calculate_mode_flags(6, mode, modeFlags)
        ;
        break;
    case INJECTION6_OUTPUT:
        hal_internal_calculate_mode_flags(7, mode, modeFlags)
        ;
        break;
    default:
        log_printf(
            "ERROR: invalid channel ID (%d) for hal_timer_oc_active_set\r\n",
            channel_id);
        break;
    }
    IOWR32(A_SCCT, SCCT_CH_AS, modeFlags);
}
Exemple #2
0
/*
 * Setup timers
 */
static void hal_priv_timer_setup() {
  // init the two timers for dwell and fire
  // enable interrupt for three timers
  // timer 0 will be the rtc, timer 1 will be for ignition dwell and timer 2
  // will be ignition fire
  uint32_t ienable_register = __rdctl_ienable();
  ienable_register |= A_TIMER_0 | A_TIMER_1 | A_TIMER_2;
  __wrctl_ienable(ienable_register);
  // set interval of TIMER_0 so the interrupt will be called every 125µs (RTC)
  IOWR16(A_TIMER_0, NIOS2_TIMER_PERIODL, RTC_PRESCALER_LOW);
  IOWR16(A_TIMER_0, NIOS2_TIMER_PERIODH, RTC_PRESCALER_HIGH);

  IOWR16(A_TIMER_1, NIOS2_TIMER_PERIODL, 0x0);
  IOWR16(A_TIMER_1, NIOS2_TIMER_PERIODH, 0x0);

  IOWR16(A_TIMER_2, NIOS2_TIMER_PERIODL, 0x0);
  IOWR16(A_TIMER_2, NIOS2_TIMER_PERIODH, 0x0);

  IOWR16(A_TIMER_0, NIOS2_TIMER_CONTROL, NIOS2_TIMER_CONTROL_START | NIOS2_TIMER_CONTROL_CONT | NIOS2_TIMER_CONTROL_ITO);
  IOWR16(A_TIMER_1, NIOS2_TIMER_CONTROL, NIOS2_TIMER_CONTROL_ITO);
  IOWR16(A_TIMER_2, NIOS2_TIMER_CONTROL, NIOS2_TIMER_CONTROL_ITO);

  // init the SCCT timer
  // This timer is used to read the input signal of the RPM meter, and controll
  // the output for injection
  ienable_register = __rdctl_ienable();
  ienable_register |= IRQ_SCCT_BIT;
  __wrctl_ienable(ienable_register);

  // set frequency to the same as TIMER_0
  // the prescaler will allways be the value in the SCCT_PSC + 1, so we have to
  // subtract one from TIMER_0_PERIOD
  IOWR32(A_SCCT, SCCT_PSC, TIMER_0_PERIOD -1);
  // enable interrupt of the SCCT
  IOWR32(A_SCCT, SCCT_CTR_IE, 0x1);
  // set mode of the first two channels to IC (RPM) and set the mode of the next
  // six channels to OC (injection)
  int32_t channelModeFlagMask = SCCT_CH_MS_IC | (SCCT_CH_MS_IC<<1) | (SCCT_CH_MS_OC<<2) | (SCCT_CH_MS_OC<<3) | (SCCT_CH_MS_OC<<4) | (SCCT_CH_MS_OC<<5) | (SCCT_CH_MS_OC<<6) | (SCCT_CH_MS_OC<<7);
  IOWR32(A_SCCT, SCCT_CH_MS, channelModeFlagMask);
  // set channels to generate interrupt on rising edge
  IOWR32(A_SCCT, SCCT_CH_AS, SCCT_IC_POSEDGE | (SCCT_IC_POSEDGE<<2));
  // enable interrupt for IC event on both channels
  IOWR32(A_SCCT, SCCT_CH_IE, 0x3);
  // interrupt and period of the OC channels will be set during runtime, so
  // nothing has to be done here.
}
void hal_timer_pit_active_set(pitid_t pit_id, bool active) {
    // set bit two of the control register of the timer to start it, or
    // set bit three to stop it
    uint32_t bitToSet = active ? 0x4 : 0x8;
    switch (pit_id) {
    case IGNITION_DWELL_PIT:
        IOWR32(A_TIMER_1, NIOS2_TIMER_CONTROL,
               ((IORD32(A_TIMER_1, NIOS2_TIMER_CONTROL) & 0x3) | bitToSet));
        break;
    case IGNITION_FIRE_PIT:
        IOWR32(A_TIMER_2, NIOS2_TIMER_CONTROL,
               ((IORD32(A_TIMER_2, NIOS2_TIMER_CONTROL) & 0x3) | bitToSet));
        break;
    default:
        log_printf(
            "ERROR: invalid pit ID (%d) for hal_timer_pit_active_set\r\n",
            pit_id);
        break;
    }
}
void hal_timer_oc_active_set(channelid_t channel_id, bool active) {
    int32_t interruptEnableFlags = IORD32(A_SCCT, SCCT_CH_IE);
    int32_t newFlags = 0;
    switch (channel_id) {
    case INJECTION1_OUTPUT:
        newFlags =
            active ?
            interruptEnableFlags | SCCT_CH_BITS_1(2, 1) :
            interruptEnableFlags & ~SCCT_CH_BITS_1(2, 1);
        break;
    case INJECTION2_OUTPUT:
        newFlags =
            active ?
            interruptEnableFlags | SCCT_CH_BITS_1(3, 1) :
            interruptEnableFlags & ~SCCT_CH_BITS_1(3, 1);
        break;
    case INJECTION3_OUTPUT:
        newFlags =
            active ?
            interruptEnableFlags | SCCT_CH_BITS_1(4, 1) :
            interruptEnableFlags & ~SCCT_CH_BITS_1(4, 1);
        break;
    case INJECTION4_OUTPUT:
        newFlags =
            active ?
            interruptEnableFlags | SCCT_CH_BITS_1(5, 1) :
            interruptEnableFlags & ~SCCT_CH_BITS_1(5, 1);
        break;
    case INJECTION5_OUTPUT:
        newFlags =
            active ?
            interruptEnableFlags | SCCT_CH_BITS_1(6, 1) :
            interruptEnableFlags & ~SCCT_CH_BITS_1(6, 1);
        break;
    case INJECTION6_OUTPUT:
        newFlags =
            active ?
            interruptEnableFlags | SCCT_CH_BITS_1(7, 1) :
            interruptEnableFlags & ~SCCT_CH_BITS_1(7, 1);
        break;
    default:
        log_printf(
            "ERROR: invalid channel ID (%d) for hal_timer_oc_active_set\r\n",
            channel_id);
        break;
    }
    IOWR32(A_SCCT, SCCT_CH_IE, newFlags);
}
int main(int argc, char *argv[]) {
	//led_set_blue(ledb_vals[0] | ledb_vals[1]);

	//button_wait(0);
	
	led_set_blue(ledb_vals[2] | ledb_vals[3]);
	
	//ir_sender_setup();
	//ir_sender_set((ROOMBA_ID&0x03)<<4 | IR_SENDER_ID | IR_LED_LEFT, (ROOMBA_ID&0x03)<<4 | IR_SENDER_ID | IR_LED_CENTER, (ROOMBA_ID&0x03)<<4 | IR_SENDER_ID | IR_LED_RIGHT, (ROOMBA_ID&0x03)<<4 | ir_next_base_id | IR_LED_NEAR);
		
	IOWR32(A_IR_SENDER, 0x4, base_id_codes[base_id-1] | 0x5);
	//IOWR32(A_IR_SENDER, 0x4, 0xF8F4F2F1);
	//ir_sender_set(0x80 | IR_LED_RIGHT, 0x80 | IR_LED_CENTER, 0x80 | IR_LED_LEFT, 0x80 | IR_LED_NEAR);
	ir_sender_on();
	while(true) {
		ir_sender_off();
		my_msleep(500);
		ir_sender_on();
		my_msleep(50);
	}
	
  	return 0;
}
/**
 * @author Andreas Meixner
 * @brief The one ISR NIOS calls
 * Whenever an interrupt is pending, NIOS2 will call this ISR.
 * This function will check which interrupts are pending and will call the
 * appropriate handler functions of FreeEMS.
 */
void do_irq() {

  uint32_t pending = __rdctl_ipending();

  // if the flag for a pending timer event ist set
  if(pending & 0x40) {
    // see if timer 0 (RTC) is the interrupt source
    uint32_t timerFlag = IORD16(A_TIMER_0, NIOS2_TIMER_STATUS);
    //log_printf("t0F: %X\r\n", timerFlag);
    if((timerFlag & NIOS2_TIMER_STATUS_TO)) {
      // FreeEMS internaly keeps track of time. For this purpose it assumes the
      // hardware has a 16bit clock running at 1.25MHz, which generates a tick
      // interrupt on every tick, and an overflow interrupt everytime the 16bit
      // counter overflows (every 65536 ticks) NIOS2 has a 32 bit counter, so
      // the overflow has to be simulated, by generating the interrupt in the
      // software. check if the high word of the counter value has changed since
      // the last tick, if so call TimerOverfolw()
      uint16_t currentTickHighWord = IORD16(A_TIMER_0, NIOS2_TIMER_SNAPH);
      if(currentTickHighWord != lastTickHighWord) {
        lastTickHighWord = currentTickHighWord;
        TimerOverflow();
      }
      // advance the internal RTC
      RTIISR();

      // clear the flag
      IOWR16(A_TIMER_0, NIOS2_TIMER_STATUS, timerFlag & ~NIOS2_TIMER_STATUS_TO);
    }

    // see if Timer_1 (ignition dwell) is the interrupt source
    timerFlag = IORD16(A_TIMER_1, NIOS2_TIMER_STATUS);
    if((timerFlag & NIOS2_TIMER_STATUS_TO)) {
      IgnitionDwellISR();
      // clear the flag
      IOWR16(A_TIMER_1, NIOS2_TIMER_STATUS, timerFlag & ~(NIOS2_TIMER_STATUS_TO));
    }

    // see if Timer_2 (ignition fire) is the interrupt source
    timerFlag = IORD16(A_TIMER_2, NIOS2_TIMER_STATUS);
    if((timerFlag & NIOS2_TIMER_STATUS_TO)) {
      IgnitionFireISR();
      IOWR16(A_TIMER_2, NIOS2_TIMER_STATUS, timerFlag & ~(NIOS2_TIMER_STATUS_TO));
    }
  }
  // if the flag for a pending SCCT timer event is set
  if(pending & 0x400) {
    // external interrupt (SCCT)
    // see if the oc channel 0 (scct) was the interrupt source
    uint32_t isFlags = IORD32(A_SCCT, SCCT_CH_IS);
    // if IC channel 0 has a pending interrupt, call PrimaryRPMISR
    if(isFlags & SCCT_CH_BITS_1(0,1)) {
      // clear interrupt flags
      IOWR32(A_SCCT, SCCT_CH_IS, SCCT_CH_BITS_1(0,1));
      PrimaryRPMISR();
    }
    // if IC channel 1 has a pending interrupt, call SecondaryRPMISR
    if(isFlags & SCCT_CH_BITS_1(1,1)) {
      // clear interrupt flags
      IOWR32(A_SCCT, SCCT_CH_IS, SCCT_CH_BITS_1(1,1));
      SecondaryRPMISR();
    }
    // if OC channel 2 has a pending interrupt, call Injector1ISR
    if(isFlags & SCCT_CH_BITS_1(2,1)) {
      // clear interrupt flags
      IOWR32(A_SCCT, SCCT_CH_IS, SCCT_CH_BITS_1(2,1));
      Injector1ISR();
    }
    // if OC channel 3 has a pending interrupt, call Injector2ISR
    if(isFlags & SCCT_CH_BITS_1(3,1)) {
      // clear interrupt flags
      IOWR32(A_SCCT, SCCT_CH_IS, SCCT_CH_BITS_1(3,1));
      Injector2ISR();
    }
    // if OC channel 4 has a pending interrupt, call Injector3ISR
    if(isFlags & SCCT_CH_BITS_1(4,1)) {
      // clear interrupt flags
      IOWR32(A_SCCT, SCCT_CH_IS, SCCT_CH_BITS_1(4,1));
      Injector3ISR();
    }
    // if OC channel 5 has a pending interrupt, call Injector4ISR
    if(isFlags & SCCT_CH_BITS_1(5,1)) {
      // clear interrupt flags
      IOWR32(A_SCCT, SCCT_CH_IS, SCCT_CH_BITS_1(5,1));
      Injector4ISR();
    }
    // if OC channel 6 has a pending interrupt, call Injector5ISR
    if(isFlags & SCCT_CH_BITS_1(6,1)) {
      // clear interrupt flags
      IOWR32(A_SCCT, SCCT_CH_IS, SCCT_CH_BITS_1(6,1));
      Injector5ISR();
    }
    // if OC channel 7 has a pending interrupt, call Injector6ISR
    if(isFlags & SCCT_CH_BITS_1(7,1)) {
      // clear interrupt flags
      IOWR32(A_SCCT, SCCT_CH_IS, SCCT_CH_BITS_1(7,1));
      Injector6ISR();
    }
  }
}
uint32_t cy_as_hal_gpmc_init(cy_as_omap_dev_kernel *dev_p)
{
	u32 tmp32;
	int err;
	struct gpmc_timings	timings;
	unsigned int cs_mem_base;
	unsigned int cs_vma_base;
	
	/*
	 * get GPMC i/o registers base(already been i/o mapped
	 * in kernel, no need for separate i/o remap)
	 */
	cy_as_hal_print_message(KERN_INFO "%s: mapping phys_to_virt\n", __func__);
					
	gpmc_base = (u32)ioremap_nocache(OMAP34XX_GPMC_BASE, SZ_16K);
	cy_as_hal_print_message(KERN_INFO "kernel has gpmc_base=%x , val@ the base=%x",
		gpmc_base, __raw_readl(gpmc_base)
	);
	
	cy_as_hal_print_message(KERN_INFO "%s: calling gpmc_cs_request\n", __func__);
	/*
	 * request GPMC CS for ASTORIA request
	 */
	if (gpmc_cs_request(AST_GPMC_CS, SZ_16M, (void *)&cs_mem_base) < 0) {
		cy_as_hal_print_message(KERN_ERR "error failed to request"
					"ncs4 for ASTORIA\n");
			return -1;
	} else {
		cy_as_hal_print_message(KERN_INFO "got phy_addr:%x for "
				"GPMC CS%d GPMC_CFGREG7[CS4]\n",
				 cs_mem_base, AST_GPMC_CS);
	}
	
	cy_as_hal_print_message(KERN_INFO "%s: calling request_mem_region\n", __func__);
	/*
	 * request VM region for 4K addr space for chip select 4 phy address
	 * technically we don't need it for NAND devices, but do it anyway
	 * so that data read/write bus cycle can be triggered by reading
	 * or writing this mem region
	 */
	if (!request_mem_region(cs_mem_base, SZ_16K, "AST_OMAP_HAL")) {
		err = -EBUSY;
		cy_as_hal_print_message(KERN_ERR "error MEM region "
					"request for phy_addr:%x failed\n",
					cs_mem_base);
			goto out_free_cs;
	}
	
	cy_as_hal_print_message(KERN_INFO "%s: calling ioremap_nocache\n", __func__);
	
	/* REMAP mem region associated with our CS */
	cs_vma_base = (u32)ioremap_nocache(cs_mem_base, SZ_16K);
	if (!cs_vma_base) {
		err = -ENOMEM;
		cy_as_hal_print_message(KERN_ERR "error- ioremap()"
					"for phy_addr:%x failed", cs_mem_base);

		goto out_release_mem_region;
	}
	cy_as_hal_print_message(KERN_INFO "ioremap(%x) returned vma=%x\n",
							cs_mem_base, cs_vma_base);

	dev_p->m_phy_addr_base = (void *) cs_mem_base;
	dev_p->m_vma_addr_base = (void *) cs_vma_base;

	memset(&timings, 0, sizeof(timings));

	/* cs timing */
	timings.cs_on = WB_GPMC_CS_t_on;
	timings.cs_wr_off = WB_GPMC_BUSCYC_t;
	timings.cs_rd_off = WB_GPMC_BUSCYC_t;

	/* adv timing */
	timings.adv_on = WB_GPMC_ADV_t_on;
	timings.adv_rd_off = WB_GPMC_ADV_t_off;
	timings.adv_wr_off = WB_GPMC_ADV_t_off;

	/* oe timing */
	timings.oe_on = WB_GPMC_OE_t_on;
	timings.oe_off = WB_GPMC_OE_t_off;
	timings.access = WB_GPMC_RD_t_a_c_c;
	timings.rd_cycle = WB_GPMC_BUSCYC_t;

	/* we timing */
	timings.we_on = WB_GPMC_WE_t_on;
	timings.we_off = WB_GPMC_WE_t_off;
	timings.wr_access = WB_GPMC_WR_t_a_c_c;
	timings.wr_cycle = WB_GPMC_BUSCYC_t;

	timings.page_burst_access = WB_GPMC_BUSCYC_t;
	timings.wr_data_mux_bus = WB_GPMC_BUSCYC_t;
	gpmc_cs_set_timings(AST_GPMC_CS, &timings);

	/*
	 * by default configure GPMC into 8 bit mode
	 * (to match astoria default mode)
	 */
	gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG1,
					(GPMC_CONFIG1_DEVICETYPE(0) |
					 GPMC_CONFIG1_DEVICESIZE_16
					| 0x10 //twhs
					));

	/*
	 * No method currently exists to write this register through GPMC APIs
	 * need to change WAIT2 polarity
	 */
	tmp32 = IORD32(GPMC_VMA(GPMC_CONFIG_REG));
	tmp32 = tmp32 | NAND_FORCE_POSTED_WRITE_B | 0x40;
	IOWR32(GPMC_VMA(GPMC_CONFIG_REG), tmp32);

	tmp32 = IORD32(GPMC_VMA(GPMC_CONFIG_REG));
	cy_as_hal_print_message("GPMC_CONFIG_REG=0x%x\n", tmp32);

	cy_as_hal_print_omap_regs("GPMC_CONFIG", 1,
			GPMC_VMA(GPMC_CFG_REG(1, AST_GPMC_CS)), 7);

	return 0;

out_release_mem_region:
	release_mem_region(cs_mem_base, SZ_16K);

out_free_cs:
	gpmc_cs_free(AST_GPMC_CS);

	return err;
}