lpc13xx_lpc15xx.c (2693B)
1 // agent-lpc15xx/main.c 2 // 3 // Copyright 2015 Brian Swetland <swetland@frotz.net> 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 #include <agent/flash.h> 18 19 #ifdef ARCH_LPC15XX 20 #define LPC_IAP_FUNC 0x03000205 21 #else 22 #define LPC_IAP_FUNC 0x1fff1ff1 23 #endif 24 25 #define LPC_IAP_PREPARE 50 26 #define LPC_IAP_WRITE 51 27 #define LPC_IAP_ERASE 52 28 29 // Note that while the databook claims you can reuse the same array 30 // for both parameters and results, this is a lie. Attempting to 31 // do so causes an invalid command failure. 32 33 34 int flash_agent_setup(flash_agent *agent) { 35 return ERR_NONE; 36 } 37 38 int flash_agent_erase(u32 flash_addr, u32 length) { 39 void (*romcall)(u32 *, u32 *) = (void*) LPC_IAP_FUNC; 40 u32 p[5],r[4]; 41 u32 page = flash_addr >> 12; 42 u32 last = page + ((length - 1) >> 12); 43 if (flash_addr & 0xFFF) { 44 return ERR_ALIGNMENT; 45 } 46 47 p[0] = LPC_IAP_PREPARE; 48 p[1] = page; 49 p[2] = last; 50 romcall(p,r); 51 if (r[0]) { 52 return ERR_FAIL; 53 } 54 55 p[0] = LPC_IAP_ERASE; 56 p[1] = page; 57 p[2] = last; 58 p[3] = 0x2ee0; 59 romcall(p,r); 60 if (r[0]) { 61 return ERR_FAIL; 62 } 63 return ERR_NONE; 64 } 65 66 int flash_agent_write(u32 flash_addr, const void *data, u32 length) { 67 void (*romcall)(u32 *,u32 *) = (void*) LPC_IAP_FUNC; 68 u32 p[5],r[4]; 69 u32 page = flash_addr >> 12; 70 if (flash_addr & 0xFFF) { 71 return ERR_ALIGNMENT; 72 } 73 74 p[0] = LPC_IAP_PREPARE; 75 p[1] = page; 76 p[2] = page; 77 romcall(p,r); 78 if (r[0]) { 79 return ERR_FAIL; 80 } 81 82 // todo: smaller writes, etc 83 if (length != 4096) { 84 int n; 85 for (n = length; n < 4096; n++) { 86 ((char*) data)[n] = 0; 87 } 88 } 89 p[0] = LPC_IAP_WRITE; 90 p[1] = flash_addr; 91 p[2] = (u32) data; 92 p[3] = 0x1000; 93 p[4] = 0x2ee0; 94 romcall(p,r); 95 if (r[0]) { 96 return ERR_FAIL; 97 } 98 99 return ERR_NONE; 100 } 101 102 int flash_agent_ioctl(u32 op, void *ptr, u32 arg0, u32 arg1) { 103 return ERR_INVALID; 104 } 105 106 const flash_agent __attribute((section(".vectors"))) FlashAgent = { 107 .magic = AGENT_MAGIC, 108 .version = AGENT_VERSION, 109 .flags = FLAG_BOOT_ROM_HACK, 110 .load_addr = LOADADDR, 111 .data_addr = LOADADDR + 0x400, 112 .data_size = 0x1000, 113 .flash_addr = FLASH_BASE, 114 .flash_size = FLASH_SIZE, 115 .setup = flash_agent_setup, 116 .erase = flash_agent_erase, 117 .write = flash_agent_write, 118 .ioctl = flash_agent_ioctl, 119 };