void pcm_play_dma_init(void) { bitset32(&CGU_PERI, CGU_I2SOUT_APB_CLOCK_ENABLE); I2SOUT_CONTROL = (1<<6) | (1<<3); /* enable dma, stereo */ audiohw_preinit(); pcm_dma_apply_settings(); }
void pcm_rec_dma_init(void) { bitset32(&CGU_PERI, CGU_I2SIN_APB_CLOCK_ENABLE); I2SIN_MASK = 0; /* disables all interrupts */ /* 14 bits samples, i2c clk src = I2SOUTIF, sdata src = AFE, * data valid at positive edge of SCLK */ I2SIN_CONTROL = (1<<5) | (1<<2); }
static void LCD_SPI_start(void) { bitset32(&CLKCON, 0x40000); /* enable SPI clock */ LCD_SPI_SS(false); SPCON0=0x3E; SPPRE0=24; reset_LCD(true); LCD_SPI_SS(true); }
int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count) { #ifdef SANSA_FUZEV2 bitclr32(&CCU_IO, 1<<12); #endif int ret = i2c_read_data(fm_i2c_bus, address, -1, buf, count); #ifdef SANSA_FUZEV2 bitset32(&CCU_IO, 1<<12); #endif return ret; }
static void as3525_dbop_init(void) { bitset32(&CCU_IO, 1<<12); CGU_DBOP |= (1<<4) | (1<<3) | AS3525_DBOP_DIV; DBOP_TIMPOL_01 = 0xE12FE12F; DBOP_TIMPOL_23 = 0xE12F0036; DBOP_CTRL = 0x41004; DBOP_TIMPOL_23 = 0x60036; DBOP_CTRL = 0x51004; DBOP_TIMPOL_01 = 0x60036; DBOP_TIMPOL_23 = 0xA12FE037; }
void pcm_rec_lock(void) { int oldlevel = disable_irq_save(); if (++rec_locked == 1) { bitset32(&CGU_PERI, CGU_I2SIN_APB_CLOCK_ENABLE); VIC_INT_EN_CLEAR = INTERRUPT_I2SIN; I2SIN_MASK = 0; /* disables all interrupts */ } restore_irq(oldlevel); }
void dma_resume_channel(int channel) { /* Resume - must reinit to where it left off (so the docs say) */ unsigned long control = DMAC_CH_CONTROL(channel); if ((control & 0x7ff) == 0) return; /* empty */ DMAC_INT_TC_CLEAR = (1<<channel); DMAC_INT_ERR_CLEAR = (1<<channel); DMAC_CH_SRC_ADDR(channel) = DMAC_CH_SRC_ADDR(channel); DMAC_CH_DST_ADDR(channel) = DMAC_CH_DST_ADDR(channel); DMAC_CH_LLI(channel) = DMAC_CH_LLI(channel); DMAC_CH_CONTROL(channel) = control; bitset32(&DMAC_CH_CONFIGURATION(channel), (1<<0)); }
int lcd_hw_init(void) { /* DBOP initialisation, do what OF does */ bitset32(&CCU_IO, 1<<12); /* ?? */ CGU_DBOP |= /*(1<<3)*/ 0x18 | AS3525_DBOP_DIV; DBOP_CTRL = 0x51004; DBOP_TIMPOL_01 = 0x36A12F; DBOP_TIMPOL_23 = 0xE037E037; GPIOB_DIR |= (1<<2)|(1<<5); GPIOB_PIN(5) = (1<<5); return 0; }
bool sdma_channel_init(unsigned int channel, struct channel_descriptor *cd_p, struct buffer_descriptor *base_bd_p) { struct channel_control_block *ccb_p; if (channel == 0 || channel >= CH_NUM || cd_p == NULL || base_bd_p == NULL) return false; ccb_p = &ccb_array[channel]; /* If initialized already, should close first then init. */ if (ccb_p->status.opened_init != 0) return false; /* Initialize channel control block. */ ccb_p->curr_bd_ptr = base_bd_p; ccb_p->base_bd_ptr = base_bd_p; ccb_p->channel_desc = cd_p; ccb_p->status.error = 0; ccb_p->status.opened_init = 1; ccb_p->status.state_direction = 0; ccb_p->status.execute = 0; /* Finish any channel descriptor inits. */ cd_p->ccb_ptr = ccb_p; cd_p->is_setup = 0; /* Do an initial setup now. */ if (!setup_channel(ccb_p)) { logf("SDMA ch init failed: %d", channel); cd_p->ccb_ptr = NULL; memset(ccb_p, 0x00, sizeof (struct channel_control_block)); return false; } /* Enable interrupt if a callback is specified. */ if (cd_p->callback != NULL) bitset32(&sdma_enabled_ints, 1ul << channel); /* Minimum schedulable = 1 */ sdma_channel_set_priority(channel, 1); logf("SDMA ch initialized: %d", channel); return true; }
static void as3525v2_connect(void) { logf("usb-drv: init as3525v2"); /* 1) enable usb core clock */ bitset32(&CGU_PERI, CGU_USB_CLOCK_ENABLE); usb_delay(); /* 2) enable usb phy clock */ CCU_USB = (CCU_USB & ~(3<<24)) | (1 << 24); /* ?? */ /* PHY clock */ CGU_USB = 1<<5 /* enable */ | 0 << 2 | 0; /* source = ? (24MHz crystal?) */ usb_delay(); /* 3) clear "stop pclk" */ PCGCCTL &= ~0x1; usb_delay(); /* 4) clear "power clamp" */ PCGCCTL &= ~0x4; usb_delay(); /* 5) clear "reset power down module" */ PCGCCTL &= ~0x8; usb_delay(); /* 6) set "power on program done" */ DCTL |= DCTL_pwronprgdone; usb_delay(); /* 7) core soft reset */ GRSTCTL |= GRSTCTL_csftrst; usb_delay(); /* 8) hclk soft reset */ GRSTCTL |= GRSTCTL_hsftrst; usb_delay(); /* 9) flush and reset everything */ GRSTCTL |= 0x3f; usb_delay(); /* 10) force device mode*/ GUSBCFG &= ~GUSBCFG_force_host_mode; GUSBCFG |= GUSBCFG_force_device_mode; usb_delay(); /* 11) Do something that is probably CCU related but undocumented*/ CCU_USB |= 0x1000; CCU_USB &= ~0x300000; usb_delay(); /* 12) reset usb core parameters (dev addr, speed, ...) */ DCFG = 0; usb_delay(); }
void pcm_rec_dma_start(void *addr, size_t size) { is_recording = true; bitset32(&CGU_AUDIO, (1<<11)); rec_dma_addr = addr; rec_dma_size = size; keep_sample = 0; /* ensure empty FIFO */ while (!(I2SIN_RAW_STATUS & (1<<5))) *I2SIN_DATA; I2SIN_CLEAR = (1<<6) | (1<<0); /* push error, pop error */ }
void i2c_write(int addr, const unsigned char *buf, int count) { if (count <= 0) return; mutex_lock(&i2c_mtx); /* Turn on I2C clock */ bitset32(&CLKCON, 1 << 16); /* Set mode to master transmitter and enable lines */ IICSTAT = I2C_MODE_MASTER | I2C_MODE_TX | I2C_RXTX_ENB; /* Set buffer start and count */ buf_ptr = (unsigned char *)buf; buf_count = count; /* Send slave address and then data */ SRCPND = IIC_MASK; INTPND = IIC_MASK; IICCON |= I2C_TXRX_INTENB; /* Load slave address into shift register */ IICDS = addr & 0xfe; /* Generate START */ IICSTAT = I2C_MODE_MASTER | I2C_MODE_TX | I2C_START | I2C_RXTX_ENB; if (semaphore_wait(&i2c_complete, HZ) != OBJ_WAIT_SUCCEEDED) { /* Something went wrong - stop transmission */ int oldlevel = disable_irq_save(); i2c_stop(); restore_irq(oldlevel); } /* Go back to slave receive mode and disable lines */ IICSTAT = 0; /* Turn off I2C clock */ bitclr32(&CLKCON, 1 << 16); mutex_unlock(&i2c_mtx); }
void pcm_play_dma_start(const void *addr, size_t size) { is_playing = true; dma_start_addr = (void*)addr; dma_start_size = size; dma_sub_addr = dma_start_addr; dma_rem_size = size; dma_retain(); /* force writeback */ commit_dcache_range(dma_start_addr, dma_start_size); bitset32(&CGU_AUDIO, (1<<11)); play_start_pcm(); }
static void lcd_set_power(bool powered) { if (powered) { lcd_powered = false; lcd_write_reg(0x04, 0x00); lcd_enable_interface(false); bitclr32(&GPIO3_DR, (1 << 12)); mc13783_clear(MC13783_REGULATOR_MODE1, MC13783_VCAMEN); } else { mc13783_set(MC13783_REGULATOR_MODE1, MC13783_VCAMEN); bitset32(&GPIO3_DR, (1 << 12)); lcd_enable_interface(true); lcd_write_reg(0x04, 0x01); lcd_powered = true; } }
/* LCD init */ void lcd_init_device(void) { #ifdef BOOTLOADER int i; /* When the Rockbox bootloader starts the framebuffer address is changed * but the LCD display should stay the same til an lcd_update() occurs. * This copies the data from the old framebuffer to the new one to make the * change non-visable to the user. */ unsigned short *buf = (unsigned short*)(FRAME); unsigned short *oldbuf = (unsigned short*)(LCDSADDR1<<1); /* The Rockbox bootloader is transitioning from RGB555I to RGB565 mode so convert the frambuffer data accordingly */ for(i=0; i< 320*240; i++) { *(buf++) = ((*oldbuf>>1) & 0x1F) | (*oldbuf & 0xffc0); oldbuf++; } #endif /* Set pins up */ GPHUP &= 0x600; GPECON |= 0x0A800000; GPEUP |= 0x3800; #ifdef GIGABEAT_F GPBUP |= 0x181; #endif bitset32(&CLKCON, 0x20); /* enable LCD clock */ LCD_CTRL_setup(); #ifdef GIGABEAT_F LCD_SPI_init(); #else LCD_CTRL_clock(true); #endif lcd_on = true; }
/* Stop a channel from executing - cannot be resumed */ void sdma_channel_stop(unsigned int channel) { struct channel_control_block *ccb_p; unsigned long chmsk; unsigned long intmsk; int oldstatus; int i; if (channel == 0 || channel >= CH_NUM) return; ccb_p = &ccb_array[channel]; if (ccb_p->status.opened_init == 0) return; chmsk = 1ul << channel; /* Lock callback */ oldstatus = disable_irq_save(); intmsk = sdma_enabled_ints; sdma_enabled_ints &= ~chmsk; restore_irq(oldstatus); /* Stop execution */ for (i = ccb_p->channel_desc->bd_count - 1; i >= 0; i--) ccb_p->base_bd_ptr[i].mode.status &= ~BD_DONE; SDMA_STOP_STAT = chmsk; while (SDMA_STOP_STAT & chmsk); /* Unlock callback if it was set */ if (intmsk & chmsk) bitset32(&sdma_enabled_ints, chmsk); logf("SDMA ch closed: %d", channel); }
/* initialises the host lcd hardware, returns the lcd type */ static int lcd_hw_init(void) { /* configure SSP */ bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE); SSP_CPSR = 4; /* TODO: use AS3525_SSP_PRESCALER, OF uses 8 */ SSP_CR0 = (0 << 8) | /* SCR, serial clock rate divider = 1 */ (1 << 7) | /* SPH, phase = 1 */ (1 << 6) | /* SPO, polarity = 1 */ (0 << 4) | /* FRF, frame format = motorola SPI */ (7 << 0); /* DSS, data size select = 8 bits */ SSP_CR1 = (1 << 3) | /* SOD, slave output disable = 1 */ (0 << 2) | /* MS, master/slave = master */ (1 << 1) | /* SSE, synchronous serial port enabled = true */ (0 << 0); /* LBM, loopback mode = normal */ SSP_IMSC &= ~0xF; /* disable interrupts */ SSP_DMACR &= ~0x3; /* disable DMA */ /* GPIO A3 is ??? but needs to be set */ GPIOA_DIR |= (1 << 3); GPIOA_PIN(3) = (1 << 3); /* configure GPIO B2 (lcd D/C#) as output */ GPIOB_DIR |= (1<<2); /* configure GPIO B3 (lcd type detect) as input */ GPIOB_DIR &= ~(1<<3); /* configure GPIO A5 (lcd reset#) as output and perform lcd reset */ GPIOA_DIR |= (1 << 5); GPIOA_PIN(5) = 0; sleep(HZ * 50/1000); GPIOA_PIN(5) = (1 << 5); /* detect lcd type on GPIO B3 */ return GPIOB_PIN(3) ? 1 : 0; }
static bool setup_channel(struct channel_control_block *ccb_p) { struct context_data context_buffer; struct channel_descriptor *cd_p; unsigned int channel_cfg; unsigned int channel; unsigned long pc; memset(&context_buffer, 0x00, sizeof (context_buffer)); channel = ccb_p - ccb_array; cd_p = ccb_p->channel_desc; /* Obtain script start address for perihperal and transfer type */ pc = get_script_pc(cd_p->per_type, cd_p->tran_type); if (pc == (unsigned short)-1) return false; /* Failed to find a script */ context_buffer.channel_state.pc = pc; if (cd_p->per_type != SDMA_PER_MEMORY && cd_p->per_type != SDMA_PER_DSP) { /* Set peripheral DMA request mask for this channel */ context_buffer.event_mask1 = 1ul << cd_p->event_id1; if (cd_p->per_type == SDMA_PER_ATA) { /* ATA has two */ context_buffer.event_mask2 = 1ul << cd_p->event_id2; } context_buffer.shp_addr = cd_p->shp_addr; context_buffer.wml = cd_p->wml; } else { context_buffer.wml = SDMA_PER_ADDR_SDRAM; } /* Send channel context to SDMA core */ commit_dcache_range(&context_buffer, sizeof (context_buffer)); sdma_write_words((unsigned long *)&context_buffer, CHANNEL_CONTEXT_ADDR(channel), sizeof (context_buffer)/4); ccb_p->status.error = 0; /* Clear channel-wide error flag */ if (cd_p->is_setup != 0) return true; /* No more to do */ /* Obtain channel ownership configuration */ channel_cfg = get_config(cd_p->tran_type); if (channel_cfg == (unsigned int)-1) return false; /* Set who owns it and thus can activate it */ set_channel_ownership(channel, channel_cfg); if (channel_cfg & CH_OWNSHP_EVT) { /* Set event ID to channel activation bitmapping */ bitset32(&SDMA_CHNENBL(cd_p->event_id1), 1ul << channel); if (cd_p->per_type == SDMA_PER_ATA) { /* ATA has two */ bitset32(&SDMA_CHNENBL(cd_p->event_id2), 1ul << channel); } } cd_p->is_setup = 1; return true; }
void pcm_rec_dma_close(void) { bitset32(&CGU_PERI, CGU_I2SIN_APB_CLOCK_ENABLE); pcm_rec_dma_stop(); }
void usb_drv_init(void) { for (int i = 0; i < USB_NUM_ENDPOINTS; i++) for (int dir = 0; dir < 2; dir++) semaphore_init(&endpoints[i][dir].complete, 1, 0); bitset32(&CGU_PERI, CGU_USB_CLOCK_ENABLE); CCU_USB = (CCU_USB & ~(3<<24)) | (1 << 24); /* ?? */ /* PHY clock */ CGU_USB = 1<<5 /* enable */ | 0 << 2 | 0; /* source = ? (24MHz crystal?) */ PCGCCTL = 0; DCTL = DCTL_pwronprgdone | DCTL_sftdiscon; GRSTCTL = GRSTCTL_csftrst; while (GRSTCTL & GRSTCTL_csftrst); /* Wait for OTG to ack reset */ while (!(GRSTCTL & GRSTCTL_ahbidle)); /* Wait for OTG AHB master idle */ GRXFSIZ = 512; GNPTXFSIZ = MAKE_FIFOSIZE_DATA(512); /* FIXME: the current code is for internal DMA only, the clip+ architecture * defines the internal DMA model */ GAHBCFG = (GAHBCFG_INT_DMA_BURST_INCR << GAHBCFG_hburstlen_bitp) | GAHBCFG_dma_enable | GAHBCFG_glblintrmsk; /* Select UTMI+ 16 */ GUSBCFG = GUSBCFG_force_device_mode | GUSBCFG_phy_if | 7 << GUSBCFG_toutcal_bitp; /* Do something that is probably CCU related but undocumented*/ CCU_USB |= 0x1000; CCU_USB &= ~0x300000; DCFG = DCFG_nzstsouthshk | DCFG_devspd_hs_phy_hs; /* Address 0, high speed */ DCTL = DCTL_pwronprgdone; /* Check hardware capabilities */ if(extract(GHWCFG2, arch) != GHWCFG2_ARCH_INTERNAL_DMA) panicf("usb-drv: wrong architecture (%ld)", extract(GHWCFG2, arch)); if(extract(GHWCFG2, hs_phy_type) != GHWCFG2_PHY_TYPE_UTMI) panicf("usb-drv: wrong HS phy type (%ld)", extract(GHWCFG2, hs_phy_type)); if(extract(GHWCFG2, fs_phy_type) != GHWCFG2_PHY_TYPE_UNSUPPORTED) panicf("usb-drv: wrong FS phy type (%ld)", extract(GHWCFG2, fs_phy_type)); if(extract(GHWCFG4, utmi_phy_data_width) != 0x2) panicf("usb-drv: wrong utmi data width (%ld)", extract(GHWCFG4, utmi_phy_data_width)); if(!(GHWCFG4 & GHWCFG4_ded_fifo_en)) /* it seems to be multiple tx fifo support */ panicf("usb-drv: no multiple tx fifo"); if(USB_NUM_ENDPOINTS != extract(GHWCFG2, num_ep)) panicf("usb-drv: wrong endpoint number"); for (int dir = 0; dir < 2; dir++) for (unsigned i = 0; i < num_eps(dir == DIR_OUT); i++) { int ep = ((dir == DIR_IN) ? in_ep_list : out_ep_list)[i]; int type = (GHWCFG1 >> GHWCFG1_epdir_bitp(ep)) & GHWCFG1_epdir_bits; int flag = (dir == DIR_IN) ? GHWCFG1_EPDIR_IN : GHWCFG1_EPDIR_OUT; if(type != GHWCFG1_EPDIR_BIDIR && type != flag) panicf("usb-drv: EP%d not in correct direction", ep); } DOEPMSK = DEPINT_xfercompl | DEPINT_ahberr | DOEPINT_setup; DIEPMSK = DEPINT_xfercompl | DEPINT_ahberr | DIEPINT_timeout; DAINTMSK = 0xffffffff; reset_endpoints(); GINTMSK = GINTMSK_usbreset | GINTMSK_enumdone | GINTMSK_inepintr | GINTMSK_outepintr | GINTMSK_disconnect; VIC_INT_ENABLE = INTERRUPT_USB; }
void usb_drv_init(void) { logf("usb_drv_init() !!!!\n"); if (!initialized) { int i; for (i = 0; i < USB_NUM_EPS; i++) { semaphore_init(&endpoints[i][0].complete, 1, 0); semaphore_init(&endpoints[i][1].complete, 1, 0); } initialized = true; } usb_enable_pll(); /* we have external power, so boost cpu */ cpu_boost(1); /* length regulator: normal operation */ ascodec_write(AS3514_CVDD_DCDC3, ascodec_read(AS3514_CVDD_DCDC3) | 1<<2); /* AHB part */ bitset32(&CGU_PERI, CGU_USB_CLOCK_ENABLE); /* reset AHB */ CCU_SRC = CCU_SRC_USB_AHB_EN; CCU_SRL = CCU_SRL_MAGIC_NUMBER; mdelay(1); CCU_SRC = CCU_SRL = 0; USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N | USB_GPIO_TX_BIT_STUFF_EN | USB_GPIO_XO_ON | USB_GPIO_CLK_SEL10; /* 0x06180000; */ /* bug workaround according to linux patch */ USB_DEV_CFG = (USB_DEV_CFG & ~3) | 1; /* full speed */ /* enable soft disconnect */ USB_DEV_CTRL |= USB_DEV_CTRL_SOFT_DISCONN; usb_phy_on(); usb_phy_suspend(); USB_DEV_CTRL |= USB_DEV_CTRL_SOFT_DISCONN; /* We don't care about SVC or SOF events */ /* Right now we don't handle suspend, so mask those too */ USB_DEV_INTR_MASK = USB_DEV_INTR_SVC | USB_DEV_INTR_SOF | USB_DEV_INTR_USB_SUSPEND | USB_DEV_INTR_EARLY_SUSPEND; USB_DEV_CFG = USB_DEV_CFG_STAT_ACK | USB_DEV_CFG_UNI_DIR | USB_DEV_CFG_PI_16BIT | USB_DEV_CFG_HS | USB_DEV_CFG_SELF_POWERED | USB_DEV_CFG_CSR_PRG | USB_DEV_CFG_PHY_ERR_DETECT; USB_DEV_CTRL = USB_DEV_CTRL_DESC_UPDATE | USB_DEV_CTRL_THRES_ENABLE | USB_DEV_CTRL_BURST_ENABLE | USB_DEV_CTRL_BLEN_8DWORDS | USB_DEV_CTRL_TLEN_8THMAXSIZE; USB_DEV_EP_INTR_MASK &= ~((1<<0) | (1<<16)); /* ep 0 */ reset_endpoints(1); /* clear pending interrupts */ USB_DEV_EP_INTR = 0xffffffff; USB_DEV_INTR = 0xffffffff; VIC_INT_ENABLE = INTERRUPT_USB; usb_phy_resume(); USB_DEV_CTRL &= ~USB_DEV_CTRL_SOFT_DISCONN; USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N | USB_GPIO_TX_BIT_STUFF_EN | USB_GPIO_XO_ON | USB_GPIO_HS_INTR | USB_GPIO_CLK_SEL10; /* 0x06180000; */ tick_add_task(usb_tick); usb_enum_timeout = HZ; /* one second timeout for enumeration */ }