| 1 | /* |
|---|
| 2 | * ar5315.c - AR2315/AR2316/AR2317/AR2318 specific system functions |
|---|
| 3 | * |
|---|
| 4 | * copyright 2009 Sebastian Gottschall / NewMedia-NET GmbH / DD-WRT.COM |
|---|
| 5 | * licensed under GPL conditions |
|---|
| 6 | */ |
|---|
| 7 | #include "mips32.c" |
|---|
| 8 | #include "spiflash.h" |
|---|
| 9 | |
|---|
| 10 | /* definition of basic flash mappings */ |
|---|
| 11 | static unsigned int sectorsize = 0x10000; |
|---|
| 12 | static unsigned int linuxaddr = 0xbfc10000; |
|---|
| 13 | static unsigned int flashbase = 0xa8000000; |
|---|
| 14 | static unsigned int flashsize = 0x800000; |
|---|
| 15 | |
|---|
| 16 | #define AR2316_DSLBASE 0xB1000000 /* RESET CONTROL MMR */ |
|---|
| 17 | #define AR531XPLUS_SPI 0xB1300000 /* SPI FLASH MMR */ |
|---|
| 18 | #define AR2316_GPIO_DI (AR2316_DSLBASE + 0x0088) |
|---|
| 19 | #define AR2316_RESET (AR2316_DSLBASE + 0x0004) |
|---|
| 20 | #define AR2316_IF_CTL (AR2316_DSLBASE + 0x0018) |
|---|
| 21 | #define AR2316_ENDIAN_CTL (AR2316_DSLBASE + 0x000c) |
|---|
| 22 | #define AR2316_WDC (AR2316_DSLBASE + 0x003c) |
|---|
| 23 | #define AR2316_AHB_ARB_CTL (AR2316_DSLBASE + 0x0008) |
|---|
| 24 | #define RESET_WARM_WLAN0_MAC 0x00000001 /* warm reset WLAN0 MAC */ |
|---|
| 25 | #define RESET_WARM_WLAN0_BB 0x00000002 /* warm reset WLAN0 BaseBand */ |
|---|
| 26 | #define RESET_MPEGTS_RSVD 0x00000004 /* warm reset MPEG-TS */ |
|---|
| 27 | #define RESET_PCIDMA 0x00000008 /* warm reset PCI ahb/dma */ |
|---|
| 28 | #define RESET_MEMCTL 0x00000010 /* warm reset memory controller */ |
|---|
| 29 | #define RESET_LOCAL 0x00000020 /* warm reset local bus */ |
|---|
| 30 | #define RESET_I2C_RSVD 0x00000040 /* warm reset I2C bus */ |
|---|
| 31 | #define RESET_SPI 0x00000080 /* warm reset SPI interface */ |
|---|
| 32 | #define RESET_UART0 0x00000100 /* warm reset UART0 */ |
|---|
| 33 | #define RESET_IR_RSVD 0x00000200 /* warm reset IR interface */ |
|---|
| 34 | #define RESET_EPHY0 0x00000400 /* cold reset ENET0 phy */ |
|---|
| 35 | #define RESET_ENET0 0x00000800 /* cold reset ENET0 mac */ |
|---|
| 36 | |
|---|
| 37 | #define IF_TS_LOCAL 2 |
|---|
| 38 | |
|---|
| 39 | #define CONFIG_ETHERNET 0x00000040 /* Ethernet byteswap */ |
|---|
| 40 | |
|---|
| 41 | #define ARB_CPU 0x00000001 /* CPU, default */ |
|---|
| 42 | #define ARB_WLAN 0x00000002 /* WLAN */ |
|---|
| 43 | #define ARB_MPEGTS_RSVD 0x00000004 /* MPEG-TS */ |
|---|
| 44 | #define ARB_LOCAL 0x00000008 /* LOCAL */ |
|---|
| 45 | #define ARB_PCI 0x00000010 /* PCI */ |
|---|
| 46 | #define ARB_ETHERNET 0x00000020 /* Ethernet */ |
|---|
| 47 | #define ARB_RETRY 0x00000100 /* retry policy, debug only */ |
|---|
| 48 | |
|---|
| 49 | #define disable_watchdog() \ |
|---|
| 50 | { \ |
|---|
| 51 | } \ |
|---|
| 52 | |
|---|
| 53 | static int getGPIO(int nr) |
|---|
| 54 | { |
|---|
| 55 | volatile unsigned int *gpio = (unsigned int *)AR2316_GPIO_DI; |
|---|
| 56 | if ((*gpio & 1 << nr) == (1 << nr)) |
|---|
| 57 | return 1; |
|---|
| 58 | return 0; |
|---|
| 59 | } |
|---|
| 60 | |
|---|
| 61 | static void enable_ethernet(void) |
|---|
| 62 | { |
|---|
| 63 | unsigned int mask = RESET_ENET0 | RESET_EPHY0; |
|---|
| 64 | unsigned int regtmp; |
|---|
| 65 | regtmp = sysRegRead(AR2316_AHB_ARB_CTL); |
|---|
| 66 | regtmp |= ARB_ETHERNET; |
|---|
| 67 | sysRegWrite(AR2316_AHB_ARB_CTL, regtmp); |
|---|
| 68 | |
|---|
| 69 | regtmp = sysRegRead(AR2316_RESET); |
|---|
| 70 | sysRegWrite(AR2316_RESET, regtmp | mask); |
|---|
| 71 | udelay(10000); |
|---|
| 72 | |
|---|
| 73 | regtmp = sysRegRead(AR2316_RESET); |
|---|
| 74 | sysRegWrite(AR2316_RESET, regtmp & ~mask); |
|---|
| 75 | udelay(10000); |
|---|
| 76 | |
|---|
| 77 | regtmp = sysRegRead(AR2316_IF_CTL); |
|---|
| 78 | regtmp |= IF_TS_LOCAL; |
|---|
| 79 | sysRegWrite(AR2316_IF_CTL, regtmp); |
|---|
| 80 | |
|---|
| 81 | regtmp = sysRegRead(AR2316_ENDIAN_CTL); |
|---|
| 82 | regtmp &= ~CONFIG_ETHERNET; |
|---|
| 83 | sysRegWrite(AR2316_ENDIAN_CTL, regtmp); |
|---|
| 84 | } |
|---|
| 85 | |
|---|
| 86 | #define FLASH_1MB 1 |
|---|
| 87 | #define FLASH_2MB 2 |
|---|
| 88 | #define FLASH_4MB 3 |
|---|
| 89 | #define FLASH_8MB 4 |
|---|
| 90 | #define FLASH_16MB 5 |
|---|
| 91 | #define MAX_FLASH 6 |
|---|
| 92 | |
|---|
| 93 | #define STM_PAGE_SIZE 256 |
|---|
| 94 | |
|---|
| 95 | #define SFI_WRITE_BUFFER_SIZE 4 |
|---|
| 96 | #define SFI_FLASH_ADDR_MASK 0x00ffffff |
|---|
| 97 | |
|---|
| 98 | #define STM_8MBIT_SIGNATURE 0x13 |
|---|
| 99 | #define STM_M25P80_BYTE_COUNT 1048576 |
|---|
| 100 | #define STM_M25P80_SECTOR_COUNT 16 |
|---|
| 101 | #define STM_M25P80_SECTOR_SIZE 0x10000 |
|---|
| 102 | |
|---|
| 103 | #define STM_16MBIT_SIGNATURE 0x14 |
|---|
| 104 | #define STM_M25P16_BYTE_COUNT 2097152 |
|---|
| 105 | #define STM_M25P16_SECTOR_COUNT 32 |
|---|
| 106 | #define STM_M25P16_SECTOR_SIZE 0x10000 |
|---|
| 107 | |
|---|
| 108 | #define STM_32MBIT_SIGNATURE 0x15 |
|---|
| 109 | #define STM_M25P32_BYTE_COUNT 4194304 |
|---|
| 110 | #define STM_M25P32_SECTOR_COUNT 64 |
|---|
| 111 | #define STM_M25P32_SECTOR_SIZE 0x10000 |
|---|
| 112 | |
|---|
| 113 | #define STM_64MBIT_SIGNATURE 0x16 |
|---|
| 114 | #define STM_M25P64_BYTE_COUNT 8388608 |
|---|
| 115 | #define STM_M25P64_SECTOR_COUNT 128 |
|---|
| 116 | #define STM_M25P64_SECTOR_SIZE 0x10000 |
|---|
| 117 | |
|---|
| 118 | #define STM_128MBIT_SIGNATURE 0x17 |
|---|
| 119 | #define STM_M25P128_BYTE_COUNT 16777216 |
|---|
| 120 | #define STM_M25P128_SECTOR_COUNT 256 |
|---|
| 121 | #define STM_M25P128_SECTOR_SIZE 0x10000 |
|---|
| 122 | |
|---|
| 123 | #define STM_1MB_BYTE_COUNT STM_M25P80_BYTE_COUNT |
|---|
| 124 | #define STM_1MB_SECTOR_COUNT STM_M25P80_SECTOR_COUNT |
|---|
| 125 | #define STM_1MB_SECTOR_SIZE STM_M25P80_SECTOR_SIZE |
|---|
| 126 | #define STM_2MB_BYTE_COUNT STM_M25P16_BYTE_COUNT |
|---|
| 127 | #define STM_2MB_SECTOR_COUNT STM_M25P16_SECTOR_COUNT |
|---|
| 128 | #define STM_2MB_SECTOR_SIZE STM_M25P16_SECTOR_SIZE |
|---|
| 129 | #define STM_4MB_BYTE_COUNT STM_M25P32_BYTE_COUNT |
|---|
| 130 | #define STM_4MB_SECTOR_COUNT STM_M25P32_SECTOR_COUNT |
|---|
| 131 | #define STM_4MB_SECTOR_SIZE STM_M25P32_SECTOR_SIZE |
|---|
| 132 | #define STM_8MB_BYTE_COUNT STM_M25P64_BYTE_COUNT |
|---|
| 133 | #define STM_8MB_SECTOR_COUNT STM_M25P64_SECTOR_COUNT |
|---|
| 134 | #define STM_8MB_SECTOR_SIZE STM_M25P64_SECTOR_SIZE |
|---|
| 135 | #define STM_16MB_BYTE_COUNT STM_M25P128_BYTE_COUNT |
|---|
| 136 | #define STM_16MB_SECTOR_COUNT STM_M25P128_SECTOR_COUNT |
|---|
| 137 | #define STM_16MB_SECTOR_SIZE STM_M25P128_SECTOR_SIZE |
|---|
| 138 | |
|---|
| 139 | #define SPI_FLASH_MMR AR531XPLUS_SPI_MMR |
|---|
| 140 | |
|---|
| 141 | #define SPI_WRITE_ENABLE 0 |
|---|
| 142 | #define SPI_WRITE_DISABLE 1 |
|---|
| 143 | #define SPI_RD_STATUS 2 |
|---|
| 144 | #define SPI_WR_STATUS 3 |
|---|
| 145 | #define SPI_RD_DATA 4 |
|---|
| 146 | #define SPI_FAST_RD_DATA 5 |
|---|
| 147 | #define SPI_PAGE_PROGRAM 6 |
|---|
| 148 | #define SPI_SECTOR_ERASE 7 |
|---|
| 149 | #define SPI_BULK_ERASE 8 |
|---|
| 150 | #define SPI_DEEP_PWRDOWN 9 |
|---|
| 151 | #define SPI_RD_SIG 10 |
|---|
| 152 | #define SPI_MAX_OPCODES 11 |
|---|
| 153 | |
|---|
| 154 | struct flashconfig { |
|---|
| 155 | __u32 byte_cnt; |
|---|
| 156 | __u32 sector_cnt; |
|---|
| 157 | __u32 sector_size; |
|---|
| 158 | __u32 cs_addrmask; |
|---|
| 159 | } static flashconfig_tbl[MAX_FLASH] = { |
|---|
| 160 | {0, 0, 0, 0}, // |
|---|
| 161 | {STM_1MB_BYTE_COUNT, STM_1MB_SECTOR_COUNT, STM_1MB_SECTOR_SIZE, 0x0}, // |
|---|
| 162 | {STM_2MB_BYTE_COUNT, STM_2MB_SECTOR_COUNT, STM_2MB_SECTOR_SIZE, 0x0}, // |
|---|
| 163 | {STM_4MB_BYTE_COUNT, STM_4MB_SECTOR_COUNT, STM_4MB_SECTOR_SIZE, 0x0}, // |
|---|
| 164 | {STM_8MB_BYTE_COUNT, STM_8MB_SECTOR_COUNT, STM_8MB_SECTOR_SIZE, 0x0}, // |
|---|
| 165 | {STM_16MB_BYTE_COUNT, STM_16MB_SECTOR_COUNT, STM_16MB_SECTOR_SIZE, 0x0} // |
|---|
| 166 | }; |
|---|
| 167 | |
|---|
| 168 | struct opcodes { |
|---|
| 169 | __u16 code; |
|---|
| 170 | __s8 tx_cnt; |
|---|
| 171 | __s8 rx_cnt; |
|---|
| 172 | } static stm_opcodes[] = { |
|---|
| 173 | {STM_OP_WR_ENABLE, 1, 0}, // |
|---|
| 174 | {STM_OP_WR_DISABLE, 1, 0}, // |
|---|
| 175 | {STM_OP_RD_STATUS, 1, 1}, // |
|---|
| 176 | {STM_OP_WR_STATUS, 1, 0}, // |
|---|
| 177 | {STM_OP_RD_DATA, 4, 4}, // |
|---|
| 178 | {STM_OP_FAST_RD_DATA, 5, 0}, // |
|---|
| 179 | {STM_OP_PAGE_PGRM, 8, 0}, // |
|---|
| 180 | {STM_OP_SECTOR_ERASE, 4, 0}, // |
|---|
| 181 | {STM_OP_BULK_ERASE, 1, 0}, // |
|---|
| 182 | {STM_OP_DEEP_PWRDOWN, 1, 0}, // |
|---|
| 183 | {STM_OP_RD_SIG, 4, 1}, // |
|---|
| 184 | }; |
|---|
| 185 | |
|---|
| 186 | static __u32 spiflash_regread32(int reg) |
|---|
| 187 | { |
|---|
| 188 | volatile __u32 *data = (__u32 *)(AR531XPLUS_SPI + reg); |
|---|
| 189 | |
|---|
| 190 | return (*data); |
|---|
| 191 | } |
|---|
| 192 | |
|---|
| 193 | static void spiflash_regwrite32(int reg, __u32 data) |
|---|
| 194 | { |
|---|
| 195 | volatile __u32 *addr = (__u32 *)(AR531XPLUS_SPI + reg); |
|---|
| 196 | |
|---|
| 197 | *addr = data; |
|---|
| 198 | return; |
|---|
| 199 | } |
|---|
| 200 | |
|---|
| 201 | #define busy_wait(condition, wait) \ |
|---|
| 202 | do { \ |
|---|
| 203 | while (condition) { \ |
|---|
| 204 | if (!wait) \ |
|---|
| 205 | udelay(1); \ |
|---|
| 206 | else \ |
|---|
| 207 | udelay(wait*1000); \ |
|---|
| 208 | } \ |
|---|
| 209 | } while (0) |
|---|
| 210 | |
|---|
| 211 | static __u32 spiflash_sendcmd(int op, u32 addr) |
|---|
| 212 | { |
|---|
| 213 | u32 reg; |
|---|
| 214 | u32 mask; |
|---|
| 215 | struct opcodes *ptr_opcode; |
|---|
| 216 | |
|---|
| 217 | ptr_opcode = &stm_opcodes[op]; |
|---|
| 218 | busy_wait((reg = spiflash_regread32(SPI_FLASH_CTL)) & SPI_CTL_BUSY, 0); |
|---|
| 219 | |
|---|
| 220 | spiflash_regwrite32(SPI_FLASH_OPCODE, |
|---|
| 221 | ((u32)ptr_opcode->code) | (addr << 8)); |
|---|
| 222 | |
|---|
| 223 | reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | ptr_opcode->tx_cnt | |
|---|
| 224 | (ptr_opcode->rx_cnt << 4) | SPI_CTL_START; |
|---|
| 225 | |
|---|
| 226 | spiflash_regwrite32(SPI_FLASH_CTL, reg); |
|---|
| 227 | |
|---|
| 228 | busy_wait(spiflash_regread32(SPI_FLASH_CTL) & SPI_CTL_BUSY, 0); |
|---|
| 229 | |
|---|
| 230 | if (!ptr_opcode->rx_cnt) |
|---|
| 231 | return 0; |
|---|
| 232 | |
|---|
| 233 | reg = (__u32)spiflash_regread32(SPI_FLASH_DATA); |
|---|
| 234 | |
|---|
| 235 | switch (ptr_opcode->rx_cnt) { |
|---|
| 236 | case 1: |
|---|
| 237 | mask = 0x000000ff; |
|---|
| 238 | break; |
|---|
| 239 | case 2: |
|---|
| 240 | mask = 0x0000ffff; |
|---|
| 241 | break; |
|---|
| 242 | case 3: |
|---|
| 243 | mask = 0x00ffffff; |
|---|
| 244 | break; |
|---|
| 245 | default: |
|---|
| 246 | mask = 0xffffffff; |
|---|
| 247 | break; |
|---|
| 248 | } |
|---|
| 249 | reg &= mask; |
|---|
| 250 | |
|---|
| 251 | return reg; |
|---|
| 252 | } |
|---|
| 253 | |
|---|
| 254 | static int spiflash_probe_chip(void) |
|---|
| 255 | { |
|---|
| 256 | unsigned int sig; |
|---|
| 257 | int flash_size; |
|---|
| 258 | |
|---|
| 259 | sig = spiflash_sendcmd(SPI_RD_SIG, 0); |
|---|
| 260 | |
|---|
| 261 | switch (sig) { |
|---|
| 262 | case STM_8MBIT_SIGNATURE: |
|---|
| 263 | flash_size = FLASH_1MB; |
|---|
| 264 | break; |
|---|
| 265 | case STM_16MBIT_SIGNATURE: |
|---|
| 266 | flash_size = FLASH_2MB; |
|---|
| 267 | break; |
|---|
| 268 | case STM_32MBIT_SIGNATURE: |
|---|
| 269 | flash_size = FLASH_4MB; |
|---|
| 270 | break; |
|---|
| 271 | case STM_64MBIT_SIGNATURE: |
|---|
| 272 | flash_size = FLASH_8MB; |
|---|
| 273 | break; |
|---|
| 274 | case STM_128MBIT_SIGNATURE: |
|---|
| 275 | flash_size = FLASH_16MB; |
|---|
| 276 | break; |
|---|
| 277 | default: |
|---|
| 278 | puts("Read of flash device signature failed!\n"); |
|---|
| 279 | return (0); |
|---|
| 280 | } |
|---|
| 281 | |
|---|
| 282 | return (flash_size); |
|---|
| 283 | } |
|---|
| 284 | |
|---|
| 285 | static int flash_erase_nvram(unsigned int flashsize, unsigned int blocksize) |
|---|
| 286 | { |
|---|
| 287 | unsigned int res; |
|---|
| 288 | unsigned int offset = nvramdetect; |
|---|
| 289 | struct opcodes *ptr_opcode; |
|---|
| 290 | __u32 temp, reg; |
|---|
| 291 | if (!nvramdetect) { |
|---|
| 292 | puts("nvram can and will not erased, since nvram was not detected on this device (maybe dd-wrt isnt installed)!\n"); |
|---|
| 293 | return; |
|---|
| 294 | } |
|---|
| 295 | printf("erasing nvram at [0x%08X]\n", nvramdetect); |
|---|
| 296 | |
|---|
| 297 | ptr_opcode = &stm_opcodes[SPI_SECTOR_ERASE]; |
|---|
| 298 | |
|---|
| 299 | temp = ((__u32)offset << 8) | (__u32)(ptr_opcode->code); |
|---|
| 300 | spiflash_sendcmd(SPI_WRITE_ENABLE, 0); |
|---|
| 301 | busy_wait((reg = spiflash_regread32(SPI_FLASH_CTL)) & SPI_CTL_BUSY, 0); |
|---|
| 302 | |
|---|
| 303 | spiflash_regwrite32(SPI_FLASH_OPCODE, temp); |
|---|
| 304 | |
|---|
| 305 | reg = |
|---|
| 306 | (reg & ~SPI_CTL_TX_RX_CNT_MASK) | ptr_opcode->tx_cnt | |
|---|
| 307 | SPI_CTL_START; |
|---|
| 308 | spiflash_regwrite32(SPI_FLASH_CTL, reg); |
|---|
| 309 | |
|---|
| 310 | busy_wait(spiflash_sendcmd(SPI_RD_STATUS, 0) & SPI_STATUS_WIP, 20); |
|---|
| 311 | |
|---|
| 312 | puts("done\n"); |
|---|
| 313 | return 0; |
|---|
| 314 | } |
|---|
| 315 | |
|---|
| 316 | static int flashdetected = 0; |
|---|
| 317 | static int flashdetect(void) |
|---|
| 318 | { |
|---|
| 319 | if (flashdetected) |
|---|
| 320 | return 0; |
|---|
| 321 | flashsize = 8 * 1024 * 1024; |
|---|
| 322 | flashbase = 0xa8000000; |
|---|
| 323 | int index = 0; |
|---|
| 324 | if (!(index = spiflash_probe_chip())) { |
|---|
| 325 | puts("Found no serial flash device, cannot reset to factory defaults\n"); |
|---|
| 326 | return -1; |
|---|
| 327 | } else { |
|---|
| 328 | flashsize = flashconfig_tbl[index].byte_cnt; |
|---|
| 329 | sectorsize = flashconfig_tbl[index].sector_size; |
|---|
| 330 | if (flashsize == 8 * 1024 * 1024) |
|---|
| 331 | flashbase = 0xa8000000; |
|---|
| 332 | else |
|---|
| 333 | flashbase = 0xbfc00000; |
|---|
| 334 | printf |
|---|
| 335 | ("Found Flash device SIZE=0x%08X SECTORSIZE=0x%08X FLASHBASE=0x%08X\n", |
|---|
| 336 | flashsize, sectorsize, flashbase); |
|---|
| 337 | } |
|---|
| 338 | flashdetected = 1; |
|---|
| 339 | return 0; |
|---|
| 340 | |
|---|
| 341 | } |
|---|