/* * Copyright (c) 2016 Actions Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Copyright (c) 2016 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #include #include #include #include #include #define CONFIG_SPINAND_DEV_NAME "spinand" const struct device *spinand_disk; //static u32_t spinand_disk_sector_cnt; int spinand_disk_status(struct disk_info *disk) { if (!spinand_disk) { return DISK_STATUS_NOMEDIA; } return DISK_STATUS_OK; } int spinand_disk_initialize(struct disk_info *disk) { uint32_t sector_cnt; int ret; if (spinand_disk) { return 0; } spinand_disk = device_get_binding(CONFIG_SPINAND_DEV_NAME); if (!spinand_disk) { return -ENODEV; } ret = spinand_storage_ioctl((struct device *)spinand_disk, DISK_IOCTL_GET_SECTOR_COUNT, (void *)§or_cnt); if (!ret) { //sd_disk_sector_cnt = sector_cnt; if(disk->sector_cnt){ if(disk->sector_offset + disk->sector_cnt > sector_cnt) printk("error:nand disk part over max capcity = %d\n", sector_cnt); }else{ disk->sector_cnt = sector_cnt; } //spinand_disk_sector_cnt = sector_cnt; } else { printk("failed to get sector count error=%d\n", ret); return -EFAULT; } return 0; } int spinand_disk_read(struct disk_info *disk, uint8_t *buff, uint32_t start_sector, uint32_t sector_count) { //boot_sector is reserved for mbrec and param. //int boot_sector = (2048 * 64 * 4) >> 9; if (!spinand_disk) { return -EIO; } //if (spinand_disk_sector_cnt == 0) { //goto read; //} if (start_sector > disk->sector_cnt - 1) { return -EIO; } //if (start_sector + sector_count > spinand_disk_sector_cnt) { //sector_count = spinand_disk_sector_cnt - start_sector; //} if (start_sector + sector_count > disk->sector_cnt) { sector_count = disk->sector_cnt - start_sector; } start_sector += disk->sector_offset; //read: //start_sector += boot_sector; if (flash_read(spinand_disk, (uint64_t)start_sector<<9, buff, (uint64_t)sector_count << 9) != 0) { return -EIO; } return 0; } int spinand_disk_write(struct disk_info *disk, const uint8_t *buff, uint32_t start_sector, uint32_t sector_count) { //boot_sector is reserved for mbrec and param. //int boot_sector = (2048 * 64 * 4) >> 9; if (!spinand_disk) { return -EIO; } //if (spinand_disk_sector_cnt == 0) { //goto write; //} if (start_sector > disk->sector_cnt - 1) { return -EIO; } //if (start_sector + sector_count > spinand_disk_sector_cnt) { //sector_count = spinand_disk_sector_cnt - start_sector; //} if (start_sector + sector_count > disk->sector_cnt) { sector_count = disk->sector_cnt - start_sector; } start_sector += disk->sector_offset; //write: // start_sector += boot_sector; if (flash_write(spinand_disk, (uint64_t)start_sector << 9, buff, (uint64_t)sector_count << 9) != 0) { return -EIO; } return 0; } int spinand_disk_ioctl(struct disk_info *disk, uint8_t cmd, void *buff) { int ret = 0; if (!spinand_disk) { return -ENODEV; } switch (cmd) { case DISK_IOCTL_CTRL_SYNC: //flush data to spinand. flash_flush((struct device *)spinand_disk, true); break; case DISK_IOCTL_GET_SECTOR_COUNT: if (disk->sector_cnt > 0) { *(uint32_t *)buff = disk->sector_cnt; } else { ret = spinand_storage_ioctl((struct device *)spinand_disk, cmd, buff); } break; case DISK_IOCTL_GET_SECTOR_SIZE: case DISK_IOCTL_GET_ERASE_BLOCK_SZ: case DISK_IOCTL_HW_DETECT: ret = spinand_storage_ioctl((struct device *)spinand_disk, cmd, buff); break; default: return -EINVAL; } return ret; } struct disk_operations disk_spinand_operation = { .init = spinand_disk_initialize, .status = spinand_disk_status, .read = spinand_disk_read, .write = spinand_disk_write, .ioctl = spinand_disk_ioctl, }; struct disk_info disk_spinand_mass = { .name = "NAND", .ops = &disk_spinand_operation, .sector_size = 512, .sector_offset = 0, .sector_cnt = 0, }; static int spinand_disk_init(const struct device *dev) { const struct partition_entry *parti; ARG_UNUSED(dev); #ifdef CONFIG_BOARD_NANDBOOT parti = partition_get_stf_part(STORAGE_ID_BOOTNAND, PARTITION_FILE_ID_UDISK); #else parti = partition_get_stf_part(STORAGE_ID_NAND, PARTITION_FILE_ID_UDISK); #endif if (parti != NULL) { if (partition_is_used_sector(parti)) { disk_spinand_mass.sector_offset = parti->offset; disk_spinand_mass.sector_cnt = (parti->size); } else { disk_spinand_mass.sector_offset = parti->offset >> 9; disk_spinand_mass.sector_cnt = parti->size >> 9; } printk("spinand_disk_init,size=%d, off=%d secotr\n", disk_spinand_mass.sector_cnt, disk_spinand_mass.sector_offset); disk_access_register(&disk_spinand_mass); return 0; } else { return -ENODEV; } } SYS_INIT(spinand_disk_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);