void write_fuse(uint8_t efuse, uint16_t fuse_word) { load_command(appc_write_fuse_bits); load_data_low_byte(fuse_word & 0xFF); set_byte_low(); reset_bs2(); wrb_pulse(); while (poll_busy()) ; load_data_low_byte(fuse_word >> 8); set_byte_high(); reset_bs2(); wrb_pulse(); while (poll_busy()) ; set_byte_low(); load_data_low_byte(efuse); set_byte_low(); set_bs2(); wrb_pulse(); while (poll_busy()) ; reset_bs2(); }
void erase_chip(void) { load_command(appc_chip_erase); wrb_pulse(); while (poll_busy()) ; }
static void program_page(void) /* Datasheet code: H & L */ { set_byte_low(); wrb_pulse(); while (poll_busy()) ; }
static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) { struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter); struct i2c_msg *msg; int err = 0; int i; long timeout; /* Wake up device and enable clock */ pm_runtime_get_sync(pd->dev); /* Process all messages */ for (i = 0; i < num; i++) { bool do_start = pd->send_stop || !i; msg = &msgs[i]; pd->send_stop = i == num - 1 || msg->flags & I2C_M_STOP; pd->stop_after_dma = false; start_ch(pd, msg, do_start); if (do_start) i2c_op(pd, OP_START, 0); /* The interrupt handler takes care of the rest... */ timeout = wait_event_timeout(pd->wait, pd->sr & (ICSR_TACK | SW_DONE), adapter->timeout); /* 'stop_after_dma' tells if DMA transfer was complete */ i2c_put_dma_safe_msg_buf(pd->dma_buf, pd->msg, pd->stop_after_dma); if (!timeout) { dev_err(pd->dev, "Transfer request timed out\n"); if (pd->dma_direction != DMA_NONE) sh_mobile_i2c_cleanup_dma(pd); err = -ETIMEDOUT; break; } if (pd->send_stop) err = poll_busy(pd); else err = poll_dte(pd); if (err < 0) break; } /* Disable channel */ iic_wr(pd, ICCR, ICCR_SCP); /* Disable clock and mark device as idle */ pm_runtime_put_sync(pd->dev); return err ?: num; }
void write_lock(uint8_t lock) { load_command(appc_write_lock_bits); load_data_low_byte(lock); set_byte_low(); reset_bs2(); wrb_pulse(); while (poll_busy()) ; }
static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) { struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter); struct i2c_msg *msg; int err = 0; int i, k; activate_ch(pd); /* Process all messages */ for (i = 0; i < num; i++) { bool do_start = pd->send_stop || !i; msg = &msgs[i]; pd->send_stop = i == num - 1 || msg->flags & I2C_M_STOP; err = start_ch(pd, msg, do_start); if (err) break; if (do_start) i2c_op(pd, OP_START, 0); /* The interrupt handler takes care of the rest... */ k = wait_event_timeout(pd->wait, pd->sr & (ICSR_TACK | SW_DONE), 5 * HZ); if (!k) { dev_err(pd->dev, "Transfer request timed out\n"); err = -ETIMEDOUT; break; } if (pd->send_stop) err = poll_busy(pd); else err = poll_dte(pd); if (err < 0) break; } deactivate_ch(pd); if (!err) err = num; return err; }
/* Send one block with DMA from the current write buffer, possibly preparing * the next block within the next write buffer in the background. */ static int send_block_send(unsigned char start_token, long timeout, bool prepare_next) { int rc = 0; unsigned char *curbuf = write_buffer[current_buffer]; curbuf[1] = fliptable[(signed char)start_token]; *(unsigned short *)(curbuf + BLOCK_SIZE + 2) = 0xFFFF; while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */ SCR1 = 0; /* disable serial */ SSR1 = 0; /* clear all flags */ /* setup DMA channel 0 */ CHCR0 = 0; /* disable */ SAR0 = (unsigned long)(curbuf + 1); DAR0 = TDR1_ADDR; DTCR0 = BLOCK_SIZE + 3; /* start token + block + dummy crc */ CHCR0 = 0x1701; /* fixed dest. address, TXI1, enable */ DMAOR = 0x0001; SCR1 = (SCI_TE|SCI_TIE); /* kick off DMA */ if (prepare_next) send_block_prepare(); yield(); /* be nice */ while (!(CHCR0 & 0x0002)); /* wait for end of DMA */ while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */ SCR1 = 0; serial_mode = SER_DISABLED; if ((poll_busy(timeout) & 0x1F) != 0x05) /* something went wrong */ rc = -1; write_transfer(dummy, 1); last_disk_activity = current_tick; return rc; }