inline void serialConfigWriteByte(unsigned char val){ unsigned char bitCount = 0 ; unsigned char valBuf = val ; for(bitCount = 0 ; bitCount < 8 ; bitCount ++){ ssiClearClk(); if((valBuf & 0x80) != 0){ ssiSetData(); }else{ ssiClearData(); } //__delay_cycles(SSI_DELAY); ssiSetClk(); valBuf = (valBuf << 1); //__delay_cycles(SSI_DELAY); } }
int loadBitFile(struct i2c_client * io_cli, const unsigned char * bitBuffer_user, const unsigned int length) { int iCfg; unsigned long int i; unsigned long int timer = 0; unsigned char * bitBuffer; unsigned char i2c_buffer[4]; //request_mem_region(GPIO3_BASE + 0x190, 8, gDrvrName); gpio_regs = ioremap_nocache(GPIO3_BASE + 0x190, 2 * sizeof(int)); bitBuffer = kmalloc(length, GFP_KERNEL); if (bitBuffer == NULL || copy_from_user(bitBuffer, bitBuffer_user, length)) { printk("Failed allocate buffer for configuration file \n"); return -ENOTTY; } iCfg = gpio_request(SSI_CLK, "ssi_clk"); if (iCfg < 0) { printk("Failed to take control over ssi_clk pin \n"); return -ENOTTY; } iCfg = gpio_request(SSI_DATA, "ssi_data"); if (iCfg < 0) { printk("Failed to take control over ssi_data pin \n"); return -ENOTTY; } i2c_buffer[0] = I2C_IO_EXP_CONFIG_REG; i2c_buffer[1] = 0xFF; i2c_buffer[1] &= ~((1 << SSI_PROG) | (1 << MODE1) | (1 << MODE0)); i2c_master_send(io_cli, i2c_buffer, 2); // set SSI_PROG, MODE0, MODE1 as output others as inputs i2c_set_pin(io_cli, MODE0, 1); i2c_set_pin(io_cli, MODE1, 1); i2c_set_pin(io_cli, SSI_PROG, 0); gpio_direction_output(SSI_CLK, 0); gpio_direction_output(SSI_DATA, 0); gpio_set_value(SSI_CLK, 0); i2c_set_pin(io_cli, SSI_PROG, 1); __delay_cycles(10 * SSI_DELAY); i2c_set_pin(io_cli, SSI_PROG, 0); __delay_cycles(5 * SSI_DELAY); while (i2c_get_pin(io_cli, SSI_INIT) > 0 && timer < 200) timer++; // waiting for init pin to go down if (timer >= 200) { printk("FPGA did not answer to prog request, init pin not going low \n"); i2c_set_pin(io_cli, SSI_PROG, 1); gpio_free(SSI_CLK); gpio_free(SSI_DATA); return -ENOTTY; } timer = 0; __delay_cycles(5 * SSI_DELAY); i2c_set_pin(io_cli, SSI_PROG, 1); while (i2c_get_pin(io_cli, SSI_INIT) == 0 && timer < 256) { // need to find a better way ... timer++; // waiting for init pin to go up } if (timer >= 256) { printk("FPGA did not answer to prog request, init pin not going high \n"); gpio_free(SSI_CLK); gpio_free(SSI_DATA); return -ENOTTY; } timer = 0; printk("Starting configuration of %d bits \n", length * 8); for (i = 0; i < length; i++) { serialConfigWriteByte(bitBuffer[i]); schedule(); } printk("Waiting for done pin to go high \n"); while (timer < 50) { ssiClearClk(); __delay_cycles(SSI_DELAY); ssiSetClk(); __delay_cycles(SSI_DELAY); timer++; } gpio_set_value(SSI_CLK, 0); gpio_set_value(SSI_DATA, 1); if (i2c_get_pin(io_cli, SSI_DONE) == 0) { printk("FPGA prog failed, done pin not going high \n"); gpio_free(SSI_CLK); gpio_free(SSI_DATA); return -ENOTTY; } i2c_buffer[0] = I2C_IO_EXP_CONFIG_REG; i2c_buffer[1] = 0xDC; i2c_master_send(io_cli, i2c_buffer, 2); // set all unused config pins as input (keeping mode pins and PROG as output) gpio_direction_input(SSI_CLK); gpio_direction_input(SSI_DATA); gpio_free(SSI_CLK); gpio_free(SSI_DATA); iounmap(gpio_regs); //release_mem_region(GPIO3_BASE + 0x190, 8); kfree(bitBuffer); return length; }