/* * cpu/spc300/nvram_dyn_cfg.S * * Copyright (C) 2012 SPiDCOM Technologies * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include #include .Lcodeoptable: b .Lwait b .Lmiuwaitinitdone .macro read_dyn_cfg, nvram, ip, cfg_offset, tmp0, tmp1, tmp2, tmp3, tmp4, \ tmp5, tmp6 ldr \tmp0, =\ip ldr \tmp1, [\nvram, #\cfg_offset] lsrs \tmp2, \tmp1, #16 /* \tmp2: config size. */ beq .Lreturn /* config size = 0, nothing to do. */ lsl \tmp1, \tmp1, #16 lsrs \tmp1, \tmp1, #16 /* \tmp1: offset in nvram. */ beq .Lreturn /* config offset = 0, nothing to do. */ .Lwriteloop: /* Write registers according to config words. * Each pair of config words is composed of: * - word 0: offset in byte to add to \ip, * - word 1: * - bit 31 to 16: the mask of bits to write at this address, * - bit 15 to 0: the value to write at this address. */ ldr \tmp3, [\nvram, \tmp1] /* \tmp3: offset. */ add \tmp1, \tmp1, #4 ldr \tmp4, [\nvram, \tmp1] lsr \tmp5, \tmp4, #16 /* \tmp5: mask. */ lsl \tmp4, \tmp4, #16 lsr \tmp4, \tmp4, #16 /* \tmp4: value. */ /* Check if \tmp3 is a code op instead of an offset. */ lsrs \tmp6, \tmp3, #17 bne .Lcodeop /* Mask value. */ and \tmp4, \tmp4, \tmp5 /* Load register at offset \tmp3. */ ldr \tmp6, [\tmp0, \tmp3] /* Apply masked value. */ bic \tmp6, \tmp6, \tmp5 orr \tmp6, \tmp6, \tmp4 /* Store value at offset. */ str \tmp6, [\tmp0, \tmp3] .Lloopnext: /* Go to the next triplet in NVRAM. */ add \tmp1, \tmp1, #4 subs \tmp2, \tmp2, #(2*4) bne .Lwriteloop b .Lreturn .Lcodeop: /* Transform the code op into an offset in the code op table. */ sub \tmp3, \tmp3, #NVRAM_WAIT_CODE_OP lsl \tmp3, \tmp3, #2 adr \tmp6, .Lcodeoptable add pc, \tmp6, \tmp3 .Lwait: /* Wait for a certain amount of time. * We have to convert value in us to clock cycles with the following * formula: (((time_to_wait * cpu_clk) / 1000000) / cpu_cycles_nb). * We make the calculus using a cpuclk of 492 MHz (max speed used). If * the actual speed is lower, wait will be longer but we consider that it * is not a problem. * The 3 instructions take 5 CPU cycles. * With cpu_clk = 492 MHz and cpu_cycles_nb = 5, we have to multiply the * initial value by (492000000 / 1000000) / 5 = 98.4, rounded to 99 */ mov \tmp3, #99 mul \tmp3, \tmp4, \tmp3 1: sub \tmp3, \tmp3, #1 cmp \tmp3, #0 bne 1b b .Lloopnext .Lmiuwaitinitdone: /* Wait until init done. */ ldr \tmp3, [\tmp0, #MIU_INIT_DONE_REG] tst \tmp3, #(1 << MIU_INIT_DONE_BIT) beq .Lmiuwaitinitdone b .Lloopnext .Lreturn: .endm