nrf528xx.c (3133B)
1 // agents/nrf528xx.c 2 // 3 // Copyright 2019 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 #define LOADADDR 0x20000400 18 19 #define FLASH_BASE 0x00000000 20 21 #include <agent/flash.h> 22 #include <fw/io.h> 23 24 #define NVMC_READY 0x4001E400 25 #define NVMC_CONFIG 0x4001E504 26 #define NVMC_CONFIG_READ 0 27 #define NVMC_CONFIG_WRITE 1 28 #define NVMC_CONFIG_ERASE 2 29 #define NVMC_ERASEPAGE 0x4001E508 30 31 #define FICR_CODEPAGESIZE 0x10000010 32 #define FICR_CODESIZE 0x10000014 33 34 static unsigned FLASH_PAGE_SIZE = 1024; 35 static unsigned FLASH_SIZE = 192 * 1024; 36 37 int flash_agent_setup(flash_agent *agent) { 38 39 // TODO - validate part ID 40 if (0) { 41 // unknown part 42 return ERR_INVALID; 43 } 44 45 // check flash size 46 FLASH_PAGE_SIZE = readl(FICR_CODEPAGESIZE); 47 FLASH_SIZE = FLASH_PAGE_SIZE * readl(FICR_CODESIZE); 48 49 agent->flash_size = FLASH_SIZE; 50 51 return ERR_NONE; 52 } 53 54 int flash_agent_erase(uint32_t flash_addr, uint32_t length) { 55 int status = ERR_NONE; 56 if (flash_addr > FLASH_SIZE) { 57 return ERR_INVALID; 58 } 59 if (flash_addr & (FLASH_PAGE_SIZE - 1)) { 60 return ERR_ALIGNMENT; 61 } 62 writel(NVMC_CONFIG_ERASE, NVMC_CONFIG); 63 while (length > 0) { 64 if (length > FLASH_PAGE_SIZE) { 65 length -= FLASH_PAGE_SIZE; 66 } else { 67 length = 0; 68 } 69 writel(flash_addr, NVMC_ERASEPAGE); 70 while (readl(NVMC_READY) != 1) ; 71 for (unsigned n = 0; n < FLASH_PAGE_SIZE; n += 4) { 72 if (readl(flash_addr + n) != 0xFFFFFFFF) { 73 status = ERR_FAIL; 74 goto done; 75 } 76 } 77 flash_addr += FLASH_PAGE_SIZE; 78 } 79 done: 80 writel(NVMC_CONFIG_READ, NVMC_CONFIG); 81 return status; 82 } 83 84 int flash_agent_write(uint32_t flash_addr, const void *_data, uint32_t length) { 85 int status = ERR_NONE; 86 const unsigned *data = _data; 87 if (flash_addr > FLASH_SIZE) { 88 return ERR_INVALID; 89 } 90 if ((flash_addr & 3) || (length & 3)) { 91 return ERR_ALIGNMENT; 92 } 93 writel(NVMC_CONFIG_WRITE, NVMC_CONFIG); 94 while (length > 0) { 95 writel(*data, flash_addr); 96 while (readl(NVMC_READY) != 1) ; 97 if (readl(flash_addr) != *data) { 98 status = ERR_FAIL; 99 goto done; 100 } 101 data++; 102 length -= 4; 103 flash_addr += 4; 104 } 105 done: 106 writel(NVMC_CONFIG_READ, NVMC_CONFIG); 107 return status; 108 } 109 110 int flash_agent_ioctl(uint32_t op, void *ptr, uint32_t arg0, uint32_t arg1) { 111 return ERR_INVALID; 112 } 113 114 const flash_agent __attribute((section(".vectors"))) FlashAgent = { 115 .magic = AGENT_MAGIC, 116 .version = AGENT_VERSION, 117 .flags = 0, 118 .load_addr = LOADADDR, 119 .data_addr = LOADADDR + 0x400, 120 .data_size = 0x4000, 121 .flash_addr = FLASH_BASE, 122 .flash_size = 0, 123 .setup = flash_agent_setup, 124 .erase = flash_agent_erase, 125 .write = flash_agent_write, 126 .ioctl = flash_agent_ioctl, 127 };