1ad309a88SDingqiang Lin /* 2ad309a88SDingqiang Lin * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd 3ad309a88SDingqiang Lin * 4ba0501acSDingqiang Lin * SPDX-License-Identifier: GPL-2.0 5ad309a88SDingqiang Lin */ 6ba0501acSDingqiang Lin 7ad309a88SDingqiang Lin #include <common.h> 8ad309a88SDingqiang Lin #include <dm.h> 9ad309a88SDingqiang Lin 10ad309a88SDingqiang Lin #include "rkflash_api.h" 11ad309a88SDingqiang Lin #include "rkflash_blk.h" 12*f3a2c32eSJon Lin #include "rkflash_debug.h" 13ad309a88SDingqiang Lin 14ad309a88SDingqiang Lin #ifdef CONFIG_RKSFC_NOR 15*f3a2c32eSJon Lin 16*f3a2c32eSJon Lin #define IDB_ALIGN_64 128 /* 64 KB */ 17*f3a2c32eSJon Lin #define IDB_ALIGN_32 64 /* 32 KB */ 18*f3a2c32eSJon Lin 19*f3a2c32eSJon Lin static void P_RC4(u8 *buf, u16 len) 20*f3a2c32eSJon Lin { 21*f3a2c32eSJon Lin u8 S[256], K[256], temp; 22*f3a2c32eSJon Lin u16 i, j, t, x; 23*f3a2c32eSJon Lin u8 key[16] = {124, 78, 3, 4, 85, 5, 9, 7, 24*f3a2c32eSJon Lin 45, 44, 123, 56, 23, 13, 23, 17}; 25*f3a2c32eSJon Lin 26*f3a2c32eSJon Lin j = 0; 27*f3a2c32eSJon Lin for (i = 0; i < 256; i++) { 28*f3a2c32eSJon Lin S[i] = (u8)i; 29*f3a2c32eSJon Lin j &= 0x0f; 30*f3a2c32eSJon Lin K[i] = key[j]; 31*f3a2c32eSJon Lin j++; 32*f3a2c32eSJon Lin } 33*f3a2c32eSJon Lin 34*f3a2c32eSJon Lin j = 0; 35*f3a2c32eSJon Lin for (i = 0; i < 256; i++) { 36*f3a2c32eSJon Lin j = (j + S[i] + K[i]) % 256; 37*f3a2c32eSJon Lin temp = S[i]; 38*f3a2c32eSJon Lin S[i] = S[j]; 39*f3a2c32eSJon Lin S[j] = temp; 40*f3a2c32eSJon Lin } 41*f3a2c32eSJon Lin 42*f3a2c32eSJon Lin i = 0; 43*f3a2c32eSJon Lin j = 0; 44*f3a2c32eSJon Lin for (x = 0; x < len; x++) { 45*f3a2c32eSJon Lin i = (i + 1) % 256; 46*f3a2c32eSJon Lin j = (j + S[i]) % 256; 47*f3a2c32eSJon Lin temp = S[i]; 48*f3a2c32eSJon Lin S[i] = S[j]; 49*f3a2c32eSJon Lin S[j] = temp; 50*f3a2c32eSJon Lin t = (S[i] + (S[j] % 256)) % 256; 51*f3a2c32eSJon Lin buf[x] = buf[x] ^ S[t]; 52*f3a2c32eSJon Lin } 53*f3a2c32eSJon Lin } 54*f3a2c32eSJon Lin 55ba0501acSDingqiang Lin int rksfc_nor_init(struct udevice *udev) 56ad309a88SDingqiang Lin { 57ad309a88SDingqiang Lin struct rkflash_info *priv = dev_get_priv(udev); 58ad309a88SDingqiang Lin struct SFNOR_DEV *p_dev = (struct SFNOR_DEV *)&priv->flash_dev_info; 59*f3a2c32eSJon Lin struct snor_info_packet *packet; 60*f3a2c32eSJon Lin struct id_block_tag *idb_tag; 61*f3a2c32eSJon Lin int ret; 62ad309a88SDingqiang Lin 63*f3a2c32eSJon Lin ret = snor_init(p_dev); 64*f3a2c32eSJon Lin if (ret == SFC_OK && p_dev->read_lines == DATA_LINES_X1) { 65*f3a2c32eSJon Lin idb_tag = kzalloc(NOR_SECS_PAGE * 512, GFP_KERNEL); 66*f3a2c32eSJon Lin if (!idb_tag) 67*f3a2c32eSJon Lin return SFC_OK; 68*f3a2c32eSJon Lin 69*f3a2c32eSJon Lin if (sfc_get_version() >= SFC_VER_4) 70*f3a2c32eSJon Lin snor_read(p_dev, IDB_ALIGN_32, NOR_SECS_PAGE, 71*f3a2c32eSJon Lin idb_tag); 72*f3a2c32eSJon Lin else 73*f3a2c32eSJon Lin snor_read(p_dev, IDB_ALIGN_64, NOR_SECS_PAGE, 74*f3a2c32eSJon Lin idb_tag); 75*f3a2c32eSJon Lin packet = (struct snor_info_packet *)&idb_tag->dev_param[0]; 76*f3a2c32eSJon Lin if (idb_tag->id == IDB_BLOCK_TAG_ID) { 77*f3a2c32eSJon Lin P_RC4((u8 *)idb_tag, sizeof(struct id_block_tag)); 78*f3a2c32eSJon Lin snor_reinit_from_table_packet(p_dev, packet); 79*f3a2c32eSJon Lin rkflash_print_error("snor reinit, ret= %d\n", ret); 80*f3a2c32eSJon Lin } 81*f3a2c32eSJon Lin kfree(idb_tag); 82*f3a2c32eSJon Lin } 83*f3a2c32eSJon Lin 84*f3a2c32eSJon Lin return ret; 85ad309a88SDingqiang Lin } 86ad309a88SDingqiang Lin 87ba0501acSDingqiang Lin u32 rksfc_nor_get_capacity(struct udevice *udev) 88ad309a88SDingqiang Lin { 89ad309a88SDingqiang Lin struct rkflash_info *priv = dev_get_priv(udev); 90ad309a88SDingqiang Lin struct SFNOR_DEV *p_dev = (struct SFNOR_DEV *)&priv->flash_dev_info; 91ad309a88SDingqiang Lin 92ad309a88SDingqiang Lin return snor_get_capacity(p_dev); 93ad309a88SDingqiang Lin } 94ad309a88SDingqiang Lin 95ba0501acSDingqiang Lin int rksfc_nor_read(struct udevice *udev, u32 sec, u32 n_sec, void *p_data) 96ad309a88SDingqiang Lin { 97ba0501acSDingqiang Lin u32 ret; 98ba0501acSDingqiang Lin u32 offset, count = 0; 99ba0501acSDingqiang Lin char *buf = (char *)p_data; 100ad309a88SDingqiang Lin struct rkflash_info *priv = dev_get_priv(udev); 101ad309a88SDingqiang Lin struct SFNOR_DEV *p_dev = (struct SFNOR_DEV *)&priv->flash_dev_info; 102ad309a88SDingqiang Lin 103ba0501acSDingqiang Lin if (sec + n_sec - 1 < FLASH_VENDOR_PART_START || 104ba0501acSDingqiang Lin sec > FLASH_VENDOR_PART_END) { 105ba0501acSDingqiang Lin ret = snor_read(p_dev, sec, n_sec, p_data); 106ba0501acSDingqiang Lin if (ret != n_sec) 107ba0501acSDingqiang Lin return ret; 108ba0501acSDingqiang Lin } else { 109ba0501acSDingqiang Lin memset(p_data, 0, 512 * n_sec); 110ba0501acSDingqiang Lin if (sec < FLASH_VENDOR_PART_START) { 111ba0501acSDingqiang Lin count = FLASH_VENDOR_PART_START - sec; 112ba0501acSDingqiang Lin buf = (char *)p_data; 113ba0501acSDingqiang Lin ret = snor_read(p_dev, sec, count, buf); 114ba0501acSDingqiang Lin if (ret != count) 115ba0501acSDingqiang Lin return ret; 116ba0501acSDingqiang Lin } 117ba0501acSDingqiang Lin if ((sec + n_sec - 1) > FLASH_VENDOR_PART_END) { 118ba0501acSDingqiang Lin count = sec + n_sec - 1 - FLASH_VENDOR_PART_END; 119ba0501acSDingqiang Lin offset = FLASH_VENDOR_PART_END - sec + 1; 120ba0501acSDingqiang Lin buf = (char *)p_data + offset * 512; 121ba0501acSDingqiang Lin ret = snor_read(p_dev, 122ba0501acSDingqiang Lin FLASH_VENDOR_PART_END + 1, 123ba0501acSDingqiang Lin count, buf); 124ba0501acSDingqiang Lin if (ret != count) 125ba0501acSDingqiang Lin return ret; 126ba0501acSDingqiang Lin } 127ba0501acSDingqiang Lin } 128ba0501acSDingqiang Lin 129ba0501acSDingqiang Lin return n_sec; 130ba0501acSDingqiang Lin } 131ba0501acSDingqiang Lin 1327edaca22SJon Lin /* Workaround for GPT not aligned program */ 1337edaca22SJon Lin int rksfc_nor_simply_over_write(struct udevice *udev, 1347edaca22SJon Lin u32 sec, 1357edaca22SJon Lin u32 n_sec, 1367edaca22SJon Lin const void *p_data) 1377edaca22SJon Lin { 1387edaca22SJon Lin struct rkflash_info *priv = dev_get_priv(udev); 1397edaca22SJon Lin struct SFNOR_DEV *p_dev = (struct SFNOR_DEV *)&priv->flash_dev_info; 1407edaca22SJon Lin u8 *pbuf_temp; 1417edaca22SJon Lin u32 addr_aligned, offset, remain; 1427edaca22SJon Lin 1437edaca22SJon Lin addr_aligned = sec / NOR_SECS_PAGE * NOR_SECS_PAGE; 1447edaca22SJon Lin offset = sec - addr_aligned; 1457edaca22SJon Lin remain = (offset + n_sec + NOR_SECS_PAGE - 1) / NOR_SECS_PAGE * NOR_SECS_PAGE; 1467edaca22SJon Lin 1477edaca22SJon Lin pbuf_temp = malloc(remain * 512); 1487edaca22SJon Lin snor_read(p_dev, addr_aligned, remain, pbuf_temp); 1497edaca22SJon Lin memcpy(pbuf_temp + offset * 512, p_data, n_sec * 512); 1507edaca22SJon Lin snor_write(p_dev, addr_aligned, remain, pbuf_temp); 1517edaca22SJon Lin free(pbuf_temp); 1527edaca22SJon Lin 1537edaca22SJon Lin return n_sec; 1547edaca22SJon Lin } 1557edaca22SJon Lin 156ba0501acSDingqiang Lin int rksfc_nor_write(struct udevice *udev, 157ba0501acSDingqiang Lin u32 sec, 158ba0501acSDingqiang Lin u32 n_sec, 159ba0501acSDingqiang Lin const void *p_data) 160ba0501acSDingqiang Lin { 161ba0501acSDingqiang Lin u32 ret; 162ba0501acSDingqiang Lin u32 offset, count = 0; 163ba0501acSDingqiang Lin char *buf = (char *)p_data; 164ba0501acSDingqiang Lin struct rkflash_info *priv = dev_get_priv(udev); 165ba0501acSDingqiang Lin struct SFNOR_DEV *p_dev = (struct SFNOR_DEV *)&priv->flash_dev_info; 1667edaca22SJon Lin u32 sfc_nor_density = rksfc_nor_get_capacity(udev); 1677edaca22SJon Lin 1687edaca22SJon Lin if (sec >= (sfc_nor_density - 33)) 1697edaca22SJon Lin return rksfc_nor_simply_over_write(udev, sec, n_sec, p_data); 170ba0501acSDingqiang Lin 171ba0501acSDingqiang Lin if (sec + n_sec - 1 < FLASH_VENDOR_PART_START || 172ba0501acSDingqiang Lin sec > FLASH_VENDOR_PART_END) { 173c84f0ed8SJon Lin ret = snor_write(p_dev, sec, n_sec, (void *)p_data); 174ba0501acSDingqiang Lin if (ret != n_sec) 175ba0501acSDingqiang Lin return ret; 176ba0501acSDingqiang Lin } else { 177ba0501acSDingqiang Lin if (sec < FLASH_VENDOR_PART_START) { 178ba0501acSDingqiang Lin count = FLASH_VENDOR_PART_START - sec; 179ba0501acSDingqiang Lin buf = (char *)p_data; 180ba0501acSDingqiang Lin ret = snor_write(p_dev, sec, count, buf); 181ba0501acSDingqiang Lin if (ret != count) 182ba0501acSDingqiang Lin return ret; 183ba0501acSDingqiang Lin } 184ba0501acSDingqiang Lin if ((sec + n_sec - 1) > FLASH_VENDOR_PART_END) { 185ba0501acSDingqiang Lin count = sec + n_sec - 1 - FLASH_VENDOR_PART_END; 186ba0501acSDingqiang Lin offset = FLASH_VENDOR_PART_END - sec + 1; 187ba0501acSDingqiang Lin buf = (char *)p_data + offset * 512; 188ba0501acSDingqiang Lin ret = snor_write(p_dev, 189ba0501acSDingqiang Lin FLASH_VENDOR_PART_END + 1, 190ba0501acSDingqiang Lin count, buf); 191ba0501acSDingqiang Lin if (ret != count) 192ba0501acSDingqiang Lin return ret; 193ba0501acSDingqiang Lin } 194ba0501acSDingqiang Lin } 195ba0501acSDingqiang Lin 196ba0501acSDingqiang Lin return n_sec; 197ba0501acSDingqiang Lin } 198ba0501acSDingqiang Lin 199ba0501acSDingqiang Lin int rksfc_nor_vendor_read(struct blk_desc *dev_desc, 200ba0501acSDingqiang Lin u32 sec, 201ba0501acSDingqiang Lin u32 n_sec, 202ba0501acSDingqiang Lin void *p_data) 203ba0501acSDingqiang Lin { 204ba0501acSDingqiang Lin struct rkflash_info *priv = dev_get_priv(dev_desc->bdev->parent); 205ba0501acSDingqiang Lin struct SFNOR_DEV *p_dev = (struct SFNOR_DEV *)&priv->flash_dev_info; 206ba0501acSDingqiang Lin 207ad309a88SDingqiang Lin return snor_read(p_dev, sec, n_sec, p_data); 208ad309a88SDingqiang Lin } 209ad309a88SDingqiang Lin 210ba0501acSDingqiang Lin int rksfc_nor_vendor_write(struct blk_desc *dev_desc, 211ba0501acSDingqiang Lin u32 sec, 212ba0501acSDingqiang Lin u32 n_sec, 213ba0501acSDingqiang Lin void *p_data) 214ad309a88SDingqiang Lin { 215ba0501acSDingqiang Lin struct rkflash_info *priv = dev_get_priv(dev_desc->bdev->parent); 216ad309a88SDingqiang Lin struct SFNOR_DEV *p_dev = (struct SFNOR_DEV *)&priv->flash_dev_info; 217ad309a88SDingqiang Lin 218ad309a88SDingqiang Lin return snor_write(p_dev, sec, n_sec, p_data); 219ad309a88SDingqiang Lin } 220ba0501acSDingqiang Lin 221ad309a88SDingqiang Lin #endif 222ad309a88SDingqiang Lin 223ba0501acSDingqiang Lin #ifdef CONFIG_RKSFC_NAND 224ba0501acSDingqiang Lin int rksfc_nand_init(struct udevice *udev) 225ba0501acSDingqiang Lin { 226ba0501acSDingqiang Lin int ret; 227ba0501acSDingqiang Lin 228ba0501acSDingqiang Lin ret = sfc_nand_init(); 229c84f0ed8SJon Lin if (ret) { 230ba0501acSDingqiang Lin return ret; 231c84f0ed8SJon Lin } else { 232c84f0ed8SJon Lin sfc_nand_ftl_ops_init(); 233c84f0ed8SJon Lin 234ba0501acSDingqiang Lin return sftl_init(); 235ba0501acSDingqiang Lin } 236c84f0ed8SJon Lin } 237ba0501acSDingqiang Lin 238ba0501acSDingqiang Lin int rksfc_nand_read(struct udevice *udev, u32 index, u32 count, void *buf) 239ba0501acSDingqiang Lin { 240ba0501acSDingqiang Lin int ret; 241ba0501acSDingqiang Lin 242ba0501acSDingqiang Lin ret = sftl_read(index, count, (u8 *)buf); 243ba0501acSDingqiang Lin if (!ret) 244ba0501acSDingqiang Lin return count; 245ba0501acSDingqiang Lin else 246ba0501acSDingqiang Lin return -EIO; 247ba0501acSDingqiang Lin } 248ba0501acSDingqiang Lin 249ba0501acSDingqiang Lin int rksfc_nand_write(struct udevice *udev, 250ba0501acSDingqiang Lin u32 index, 251ba0501acSDingqiang Lin u32 count, 252ba0501acSDingqiang Lin const void *buf) 253ba0501acSDingqiang Lin { 254ba0501acSDingqiang Lin int ret; 255ba0501acSDingqiang Lin 256ba0501acSDingqiang Lin ret = sftl_write(index, count, (u8 *)buf); 257ba0501acSDingqiang Lin if (!ret) 258ba0501acSDingqiang Lin return count; 259ba0501acSDingqiang Lin else 260ba0501acSDingqiang Lin return -EIO; 261ba0501acSDingqiang Lin } 262ba0501acSDingqiang Lin 263ba0501acSDingqiang Lin u32 rksfc_nand_get_density(struct udevice *udev) 264ba0501acSDingqiang Lin { 265ba0501acSDingqiang Lin return sftl_get_density(); 266ba0501acSDingqiang Lin } 26740bd3f86SDingqiang Lin 26840bd3f86SDingqiang Lin int rksfc_nand_vendor_read(struct blk_desc *dev_desc, 26940bd3f86SDingqiang Lin u32 sec, 27040bd3f86SDingqiang Lin u32 n_sec, 27140bd3f86SDingqiang Lin void *p_data) 27240bd3f86SDingqiang Lin { 27340bd3f86SDingqiang Lin int ret; 27440bd3f86SDingqiang Lin 27540bd3f86SDingqiang Lin ret = sftl_vendor_read(sec, n_sec, (u8 *)p_data); 27640bd3f86SDingqiang Lin if (!ret) 27740bd3f86SDingqiang Lin return n_sec; 27840bd3f86SDingqiang Lin else 27940bd3f86SDingqiang Lin return -EIO; 28040bd3f86SDingqiang Lin } 28140bd3f86SDingqiang Lin 28240bd3f86SDingqiang Lin int rksfc_nand_vendor_write(struct blk_desc *dev_desc, 28340bd3f86SDingqiang Lin u32 sec, 28440bd3f86SDingqiang Lin u32 n_sec, 28540bd3f86SDingqiang Lin void *p_data) 28640bd3f86SDingqiang Lin { 28740bd3f86SDingqiang Lin int ret; 28840bd3f86SDingqiang Lin 28940bd3f86SDingqiang Lin ret = sftl_vendor_write(sec, n_sec, (u8 *)p_data); 29040bd3f86SDingqiang Lin if (!ret) 29140bd3f86SDingqiang Lin return n_sec; 29240bd3f86SDingqiang Lin else 29340bd3f86SDingqiang Lin return -EIO; 29440bd3f86SDingqiang Lin } 29540bd3f86SDingqiang Lin 296ba0501acSDingqiang Lin #endif 297ba0501acSDingqiang Lin 298ba0501acSDingqiang Lin #ifdef CONFIG_RKNANDC_NAND 299ba0501acSDingqiang Lin int rknand_flash_init(struct udevice *udev) 300ba0501acSDingqiang Lin { 301ba0501acSDingqiang Lin return sftl_init(); 302ba0501acSDingqiang Lin } 303ba0501acSDingqiang Lin 304ba0501acSDingqiang Lin int rknand_flash_read(struct udevice *udev, u32 index, u32 count, void *buf) 305ba0501acSDingqiang Lin { 306ba0501acSDingqiang Lin int ret; 307ba0501acSDingqiang Lin 308ba0501acSDingqiang Lin ret = sftl_read(index, count, (u8 *)buf); 309ba0501acSDingqiang Lin if (!ret) 310ba0501acSDingqiang Lin return count; 311ba0501acSDingqiang Lin else 312ba0501acSDingqiang Lin return -EIO; 313ba0501acSDingqiang Lin } 314ba0501acSDingqiang Lin 315ba0501acSDingqiang Lin int rknand_flash_write(struct udevice *udev, 316ba0501acSDingqiang Lin u32 index, 317ba0501acSDingqiang Lin u32 count, 318ba0501acSDingqiang Lin const void *buf) 319ba0501acSDingqiang Lin { 320ba0501acSDingqiang Lin int ret; 321ba0501acSDingqiang Lin 322ba0501acSDingqiang Lin ret = sftl_write(index, count, (u8 *)buf); 323ba0501acSDingqiang Lin if (!ret) 324ba0501acSDingqiang Lin return count; 325ba0501acSDingqiang Lin else 326ba0501acSDingqiang Lin return -EIO; 327ba0501acSDingqiang Lin } 328ba0501acSDingqiang Lin 329ba0501acSDingqiang Lin u32 rknand_flash_get_density(struct udevice *udev) 330ba0501acSDingqiang Lin { 331ba0501acSDingqiang Lin return sftl_get_density(); 332ba0501acSDingqiang Lin } 33340bd3f86SDingqiang Lin 33440bd3f86SDingqiang Lin int rknand_flash_vendor_read(struct blk_desc *dev_desc, 33540bd3f86SDingqiang Lin u32 sec, 33640bd3f86SDingqiang Lin u32 n_sec, 33740bd3f86SDingqiang Lin void *p_data) 33840bd3f86SDingqiang Lin { 33940bd3f86SDingqiang Lin int ret; 34040bd3f86SDingqiang Lin 34140bd3f86SDingqiang Lin ret = sftl_vendor_read(sec, n_sec, (u8 *)p_data); 34240bd3f86SDingqiang Lin if (!ret) 34340bd3f86SDingqiang Lin return n_sec; 34440bd3f86SDingqiang Lin else 34540bd3f86SDingqiang Lin return -EIO; 34640bd3f86SDingqiang Lin } 34740bd3f86SDingqiang Lin 34840bd3f86SDingqiang Lin int rknand_flash_vendor_write(struct blk_desc *dev_desc, 34940bd3f86SDingqiang Lin u32 sec, 35040bd3f86SDingqiang Lin u32 n_sec, 35140bd3f86SDingqiang Lin void *p_data) 35240bd3f86SDingqiang Lin { 35340bd3f86SDingqiang Lin int ret; 35440bd3f86SDingqiang Lin 35540bd3f86SDingqiang Lin ret = sftl_vendor_write(sec, n_sec, (u8 *)p_data); 35640bd3f86SDingqiang Lin if (!ret) 35740bd3f86SDingqiang Lin return n_sec; 35840bd3f86SDingqiang Lin else 35940bd3f86SDingqiang Lin return -EIO; 36040bd3f86SDingqiang Lin } 36140bd3f86SDingqiang Lin 362ba0501acSDingqiang Lin #endif 363