| 1 | /*************************************************************************** |
|---|
| 2 | * Copyright (c) 2003-2010, Broadcom Corporation |
|---|
| 3 | * All Rights Reserved |
|---|
| 4 | * Confidential Property of Broadcom Corporation |
|---|
| 5 | * |
|---|
| 6 | * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE |
|---|
| 7 | * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR |
|---|
| 8 | * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. |
|---|
| 9 | * |
|---|
| 10 | * $brcm_Workfile: $ |
|---|
| 11 | * $brcm_Revision: $ |
|---|
| 12 | * $brcm_Date: $ |
|---|
| 13 | * |
|---|
| 14 | * Module Description: |
|---|
| 15 | * |
|---|
| 16 | * Revision History: |
|---|
| 17 | * |
|---|
| 18 | * $brcm_Log: $ |
|---|
| 19 | * |
|---|
| 20 | * |
|---|
| 21 | ***************************************************************************/ |
|---|
| 22 | #include "bstd.h" |
|---|
| 23 | #include "bkni.h" |
|---|
| 24 | #include "bspi_flash.h" |
|---|
| 25 | #include "bfds.h" |
|---|
| 26 | #include "bstd.h" |
|---|
| 27 | #include "bchp_sun_top_ctrl.h" |
|---|
| 28 | #include "gist.h" |
|---|
| 29 | #include "ramheader.h" |
|---|
| 30 | |
|---|
| 31 | extern int printf(const char *, ...); |
|---|
| 32 | |
|---|
| 33 | BDBG_MODULE(fds_spi); /* Register software module with debug interface */ |
|---|
| 34 | |
|---|
| 35 | #define BSPI_BASE 0xbfc00000 |
|---|
| 36 | |
|---|
| 37 | struct bfds_state |
|---|
| 38 | { |
|---|
| 39 | bool initialized; |
|---|
| 40 | int open_cnt; |
|---|
| 41 | unsigned int spi_base; |
|---|
| 42 | bspi_t h_spi; |
|---|
| 43 | b_mutex_t mutex; |
|---|
| 44 | bspi_settings_t spi_settings; |
|---|
| 45 | }; |
|---|
| 46 | |
|---|
| 47 | static struct bfds_state spi_if = {false,0,BSPI_BASE,NULL}; |
|---|
| 48 | |
|---|
| 49 | /*************************************************************************** |
|---|
| 50 | Summary: |
|---|
| 51 | Open block device. |
|---|
| 52 | ****************************************************************************/ |
|---|
| 53 | int bfds_open( |
|---|
| 54 | bfds_handle * handle /* [out] return device handle */ |
|---|
| 55 | ) |
|---|
| 56 | { |
|---|
| 57 | |
|---|
| 58 | *handle = NULL; |
|---|
| 59 | |
|---|
| 60 | if (!spi_if.initialized) |
|---|
| 61 | { |
|---|
| 62 | bos_create_mutex(&spi_if.mutex); |
|---|
| 63 | if (bspi_identify(&(spi_if.spi_settings)) != b_ok) |
|---|
| 64 | { |
|---|
| 65 | return BFDS_ERROR; |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | if (bspi_open(&(spi_if.h_spi),&(spi_if.spi_settings)) != b_ok) |
|---|
| 69 | { |
|---|
| 70 | return BFDS_ERROR; |
|---|
| 71 | } |
|---|
| 72 | spi_if.initialized = true; |
|---|
| 73 | |
|---|
| 74 | #if (BCHP_CHIP!=7552) |
|---|
| 75 | /* check OTP boot rom bit */ |
|---|
| 76 | if (!(BREG_Read32(GetREG(), BCHP_SUN_TOP_CTRL_OTP_OPTION_TEST_0) & BCHP_SUN_TOP_CTRL_OTP_OPTION_TEST_0_otp_option_boot_rom_enable_MASK)) { |
|---|
| 77 | spi_if.spi_base = 0xbfc00000; |
|---|
| 78 | } |
|---|
| 79 | /* check strap for boot rom */ |
|---|
| 80 | else if (0 != (BREG_Read32(GetREG(), BCHP_SUN_TOP_CTRL_STRAP_VALUE_0) & BCHP_SUN_TOP_CTRL_STRAP_VALUE_0_strap_boot_config_MASK)) { |
|---|
| 81 | /* A0 use SPI flash, A1 use NAND */ |
|---|
| 82 | spi_if.spi_base = 0xbfc00000; |
|---|
| 83 | } |
|---|
| 84 | |
|---|
| 85 | /* Check for A1 chip revision where it always boots from internal ROM */ |
|---|
| 86 | if ((BREG_Read32(GetREG(), BCHP_SUN_TOP_CTRL_PROD_REVISION) & 0x1)) |
|---|
| 87 | { |
|---|
| 88 | spi_if.spi_base = 0xb8c00000; |
|---|
| 89 | } |
|---|
| 90 | if ((BREG_Read32(GetREG(), BCHP_SUN_TOP_CTRL_OTP_OPTION_STATUS_0) & BCHP_SUN_TOP_CTRL_OTP_OPTION_STATUS_0_otp_option_boot_rom_enable_MASK)) { |
|---|
| 91 | spi_if.spi_base = 0xb8c00000; |
|---|
| 92 | } |
|---|
| 93 | #else |
|---|
| 94 | spi_if.spi_base = FLASH_BASE; |
|---|
| 95 | #endif |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | if (bos_acquire_mutex(&spi_if.mutex,BOS_PEND_FOREVER) == b_ok) |
|---|
| 99 | { |
|---|
| 100 | *handle = &spi_if; |
|---|
| 101 | spi_if.open_cnt++; |
|---|
| 102 | bos_release_mutex(&spi_if.mutex); |
|---|
| 103 | return BFDS_OK; |
|---|
| 104 | } |
|---|
| 105 | return BFDS_ERROR; |
|---|
| 106 | } |
|---|
| 107 | |
|---|
| 108 | /*************************************************************************** |
|---|
| 109 | Summary: |
|---|
| 110 | Close block device. |
|---|
| 111 | ****************************************************************************/ |
|---|
| 112 | int bfds_close( |
|---|
| 113 | bfds_handle handle /* [in] device handle */ |
|---|
| 114 | ) |
|---|
| 115 | { |
|---|
| 116 | if (handle->initialized) |
|---|
| 117 | { |
|---|
| 118 | return BFDS_ERROR; |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | if (bos_acquire_mutex(&handle->mutex,BOS_PEND_FOREVER) == b_ok) |
|---|
| 122 | { |
|---|
| 123 | if (handle->open_cnt == 0) |
|---|
| 124 | { |
|---|
| 125 | bos_release_mutex(&handle->mutex); |
|---|
| 126 | return BFDS_ERROR; |
|---|
| 127 | } |
|---|
| 128 | handle->open_cnt--; |
|---|
| 129 | |
|---|
| 130 | if (handle->open_cnt == 0) |
|---|
| 131 | { |
|---|
| 132 | bspi_close(handle->h_spi); |
|---|
| 133 | handle->initialized = false; |
|---|
| 134 | } |
|---|
| 135 | bos_release_mutex(&handle->mutex); |
|---|
| 136 | } |
|---|
| 137 | return BFDS_OK; |
|---|
| 138 | } |
|---|
| 139 | /*************************************************************************** |
|---|
| 140 | Summary: |
|---|
| 141 | Read from device at offset. |
|---|
| 142 | ****************************************************************************/ |
|---|
| 143 | int bfds_read( |
|---|
| 144 | bfds_handle handle, /* [in] device handle */ |
|---|
| 145 | unsigned offset, /* [in] offset in bytes */ |
|---|
| 146 | void * data, /* [out] buffer to copy data into at offset */ |
|---|
| 147 | unsigned size /* [in] size of the buffer */ |
|---|
| 148 | ) |
|---|
| 149 | { |
|---|
| 150 | int res; |
|---|
| 151 | if (bos_acquire_mutex(&handle->mutex,BOS_PEND_FOREVER) != b_ok) |
|---|
| 152 | return BFDS_ERROR; |
|---|
| 153 | |
|---|
| 154 | BKNI_Memcpy(data, (void*)(handle->spi_base + offset), size); |
|---|
| 155 | res = BFDS_OK; |
|---|
| 156 | bos_release_mutex(&handle->mutex); |
|---|
| 157 | return res; |
|---|
| 158 | } |
|---|
| 159 | |
|---|
| 160 | /*************************************************************************** |
|---|
| 161 | Summary: |
|---|
| 162 | Erase the sector/block at offset. |
|---|
| 163 | ****************************************************************************/ |
|---|
| 164 | int bfds_sector_erase( |
|---|
| 165 | bfds_handle handle, /* [in] device handle */ |
|---|
| 166 | unsigned offset /* [in] offset in bytes */ |
|---|
| 167 | ) |
|---|
| 168 | { |
|---|
| 169 | int res; |
|---|
| 170 | bresult bres; |
|---|
| 171 | if (bos_acquire_mutex(&handle->mutex,BOS_PEND_FOREVER) != b_ok) |
|---|
| 172 | return BFDS_ERROR; |
|---|
| 173 | bres = bspi_sector_erase(handle->h_spi, offset); |
|---|
| 174 | bspi_flush(); |
|---|
| 175 | res = (b_ok == bres) ? BFDS_OK : BFDS_ERROR; |
|---|
| 176 | bos_release_mutex(&handle->mutex); |
|---|
| 177 | |
|---|
| 178 | return res; |
|---|
| 179 | } |
|---|
| 180 | |
|---|
| 181 | /*************************************************************************** |
|---|
| 182 | Summary: |
|---|
| 183 | Program the sector/block at offset. |
|---|
| 184 | ****************************************************************************/ |
|---|
| 185 | int bfds_page_program( |
|---|
| 186 | bfds_handle handle, /* [in] device handle */ |
|---|
| 187 | unsigned offset, /* [in] offset in bytes */ |
|---|
| 188 | void * data, /* [in] buffer to program at offset */ |
|---|
| 189 | unsigned size /* [in] size of the buffer */ |
|---|
| 190 | ) |
|---|
| 191 | { |
|---|
| 192 | int res; |
|---|
| 193 | bresult bres; |
|---|
| 194 | if (bos_acquire_mutex(&handle->mutex,BOS_PEND_FOREVER) != b_ok) |
|---|
| 195 | return BFDS_ERROR; |
|---|
| 196 | bres = bspi_page_program(handle->h_spi, offset, data, size); |
|---|
| 197 | |
|---|
| 198 | res = (b_ok == bres) ? BFDS_OK : BFDS_ERROR; |
|---|
| 199 | bos_release_mutex(&handle->mutex); |
|---|
| 200 | return res; |
|---|
| 201 | } |
|---|
| 202 | |
|---|
| 203 | /*************************************************************************** |
|---|
| 204 | Summary: |
|---|
| 205 | Retrieve parameters of flash device. |
|---|
| 206 | ****************************************************************************/ |
|---|
| 207 | int bfds_get_properties ( |
|---|
| 208 | bfds_handle handle, /* [in] device handle */ |
|---|
| 209 | bfds_properties * properties /* [out] details of flash device */ |
|---|
| 210 | ) |
|---|
| 211 | { |
|---|
| 212 | int res; |
|---|
| 213 | if(NULL == properties){ |
|---|
| 214 | res = BFDS_ERROR; |
|---|
| 215 | goto ExitFunc; |
|---|
| 216 | } |
|---|
| 217 | properties->flash_sector_size = handle->spi_settings.sector_size; |
|---|
| 218 | properties->flash_page_size = handle->spi_settings.page_size; |
|---|
| 219 | properties->flash_total_size = handle->spi_settings.total_size; |
|---|
| 220 | res = BFDS_OK; |
|---|
| 221 | ExitFunc: |
|---|
| 222 | return res; |
|---|
| 223 | } |
|---|