1 /* 2 * Common routines supporting board initialisation. 3 * 4 * Copyright (C) 2005-2006 Ingenic Semiconductor, <jlwei@ingenic.cn> 5 * Copyright (C) Xiangfu Liu <xiangfu.z@gmail.com> 6 * Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk> 7 * 8 * This program is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 #include "sdram.h" 23 #include "board.h" 24 #include "gpio.h" 25 26 unsigned long get_memory_size() 27 { 28 unsigned int dmcr; 29 unsigned int rows, cols, dw, banks; 30 unsigned long size; 31 32 dmcr = REG_EMC_DMCR; 33 rows = SDRAM_ROW0 + ((dmcr & EMC_DMCR_RA_MASK) >> EMC_DMCR_RA_BIT); 34 cols = SDRAM_COL0 + ((dmcr & EMC_DMCR_CA_MASK) >> EMC_DMCR_CA_BIT); 35 dw = (dmcr & EMC_DMCR_BW) ? 2 : 4; 36 banks = (dmcr & EMC_DMCR_BA) ? 4 : 2; 37 38 size = (1 << (rows + cols)) * dw * banks; 39 40 return size; 41 } 42 43 /* Timer routines. */ 44 45 extern unsigned long timestamp; 46 extern unsigned long lastdec; 47 48 unsigned long get_timer_masked() 49 { 50 unsigned long now = READ_TIMER; 51 52 if (lastdec <= now) { 53 /* normal mode */ 54 timestamp += (now - lastdec); 55 } else { 56 /* we have an overflow ... */ 57 timestamp += TIMER_FDATA + now - lastdec; 58 } 59 lastdec = now; 60 61 return timestamp; 62 } 63 64 void reset_timer_masked() 65 { 66 /* reset time */ 67 lastdec = READ_TIMER; 68 timestamp = 0; 69 } 70 71 void reset_timer() 72 { 73 reset_timer_masked (); 74 } 75 76 unsigned long get_timer(unsigned long base) 77 { 78 return get_timer_masked () - base; 79 } 80 81 void set_timer(unsigned long t) 82 { 83 timestamp = t; 84 } 85 86 void udelay(unsigned long usec) 87 { 88 unsigned long tmo,tmp; 89 90 /* normalize */ 91 if (usec >= 1000) { 92 tmo = usec / 1000; 93 tmo *= TIMER_HZ; 94 tmo /= 1000; 95 } 96 else { 97 if (usec >= 1) { 98 tmo = usec * TIMER_HZ; 99 tmo /= (1000*1000); 100 } 101 else 102 tmo = 1; 103 } 104 105 /* check for rollover during this delay */ 106 tmp = get_timer (0); 107 if ((tmp + tmo) < tmp ) 108 reset_timer_masked(); /* timer would roll over */ 109 else 110 tmo += tmp; 111 112 while (get_timer_masked () < tmo); 113 } 114 115 void udelay_masked(unsigned long usec) 116 { 117 unsigned long tmo; 118 unsigned long endtime; 119 signed long diff; 120 121 /* normalize */ 122 if (usec >= 1000) { 123 tmo = usec / 1000; 124 tmo *= TIMER_HZ; 125 tmo /= 1000; 126 } else { 127 if (usec > 1) { 128 tmo = usec * TIMER_HZ; 129 tmo /= (1000*1000); 130 } else { 131 tmo = 1; 132 } 133 } 134 135 endtime = get_timer_masked () + tmo; 136 137 do { 138 unsigned long now = get_timer_masked (); 139 diff = endtime - now; 140 } while (diff >= 0); 141 } 142 143 /* 144 * This function is derived from PowerPC code (read timebase as long long). 145 * On MIPS it just returns the timer value. 146 */ 147 unsigned long long get_ticks() 148 { 149 return get_timer(0); 150 } 151 152 /* 153 * This function is derived from PowerPC code (timebase clock frequency). 154 * On MIPS it returns the number of timer ticks per second. 155 */ 156 unsigned long get_tbclk() 157 { 158 return TIMER_HZ; 159 } 160 161 /* GPIO interrupt administration. */ 162 163 void gpio_clear(uint8_t gpio) 164 { 165 void *gpio_port_base = jz4740_gpio_get_port((void *) GPIO_BASE, gpio / 32); 166 167 /* Clear interrupt status. */ 168 169 jz4740_gpio_ack_irq(gpio_port_base, gpio % 32); 170 __intc_ack_irq(GPIO_IRQ2); 171 __intc_ack_irq(GPIO_IRQ3); 172 } 173 174 /* Miscellaneous interrupt administration. */ 175 176 void irq_clear() 177 { 178 uint8_t i; 179 180 for (i = 0; i < 32; i++) { 181 if (REG_INTC_IPR & (1 << i)) 182 __intc_ack_irq(i); 183 } 184 }