1*d2912cb1SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */ 27d17c02aSMaxim Levitsky /* 37d17c02aSMaxim Levitsky * Copyright © 2009 - Maxim Levitsky 47d17c02aSMaxim Levitsky * SmartMedia/xD translation layer 57d17c02aSMaxim Levitsky * 67d17c02aSMaxim Levitsky * Based loosly on ssfdc.c which is 77d17c02aSMaxim Levitsky * © 2005 Eptar srl 87d17c02aSMaxim Levitsky * Author: Claudio Lanconelli <lanconelli.claudio@eptar.com> 97d17c02aSMaxim Levitsky */ 107d17c02aSMaxim Levitsky 117d17c02aSMaxim Levitsky #include <linux/mtd/blktrans.h> 127d17c02aSMaxim Levitsky #include <linux/kfifo.h> 137d17c02aSMaxim Levitsky #include <linux/sched.h> 147d17c02aSMaxim Levitsky #include <linux/completion.h> 157d17c02aSMaxim Levitsky #include <linux/mtd/mtd.h> 167d17c02aSMaxim Levitsky 177d17c02aSMaxim Levitsky 187d17c02aSMaxim Levitsky 197d17c02aSMaxim Levitsky struct ftl_zone { 20334e5f56SMaxim Levitsky bool initialized; 217d17c02aSMaxim Levitsky int16_t *lba_to_phys_table; /* LBA to physical table */ 227d17c02aSMaxim Levitsky struct kfifo free_sectors; /* queue of free sectors */ 237d17c02aSMaxim Levitsky }; 247d17c02aSMaxim Levitsky 257d17c02aSMaxim Levitsky struct sm_ftl { 267d17c02aSMaxim Levitsky struct mtd_blktrans_dev *trans; 277d17c02aSMaxim Levitsky 287d17c02aSMaxim Levitsky struct mutex mutex; /* protects the structure */ 297d17c02aSMaxim Levitsky struct ftl_zone *zones; /* FTL tables for each zone */ 307d17c02aSMaxim Levitsky 317d17c02aSMaxim Levitsky /* Media information */ 327d17c02aSMaxim Levitsky int block_size; /* block size in bytes */ 337d17c02aSMaxim Levitsky int zone_size; /* zone size in blocks */ 347d17c02aSMaxim Levitsky int zone_count; /* number of zones */ 357d17c02aSMaxim Levitsky int max_lba; /* maximum lba in a zone */ 367d17c02aSMaxim Levitsky int smallpagenand; /* 256 bytes/page nand */ 37334e5f56SMaxim Levitsky bool readonly; /* is FS readonly */ 38334e5f56SMaxim Levitsky bool unstable; 397d17c02aSMaxim Levitsky int cis_block; /* CIS block location */ 407d17c02aSMaxim Levitsky int cis_boffset; /* CIS offset in the block */ 417d17c02aSMaxim Levitsky int cis_page_offset; /* CIS offset in the page */ 427d17c02aSMaxim Levitsky void *cis_buffer; /* tmp buffer for cis reads */ 437d17c02aSMaxim Levitsky 447d17c02aSMaxim Levitsky /* Cache */ 457d17c02aSMaxim Levitsky int cache_block; /* block number of cached block */ 467d17c02aSMaxim Levitsky int cache_zone; /* zone of cached block */ 477d17c02aSMaxim Levitsky unsigned char *cache_data; /* cached block data */ 487d17c02aSMaxim Levitsky long unsigned int cache_data_invalid_bitmap; 49334e5f56SMaxim Levitsky bool cache_clean; 507d17c02aSMaxim Levitsky struct work_struct flush_work; 517d17c02aSMaxim Levitsky struct timer_list timer; 527d17c02aSMaxim Levitsky 537d17c02aSMaxim Levitsky /* Geometry stuff */ 547d17c02aSMaxim Levitsky int heads; 557d17c02aSMaxim Levitsky int sectors; 567d17c02aSMaxim Levitsky int cylinders; 577d17c02aSMaxim Levitsky 587d17c02aSMaxim Levitsky struct attribute_group *disk_attributes; 597d17c02aSMaxim Levitsky }; 607d17c02aSMaxim Levitsky 617d17c02aSMaxim Levitsky struct chs_entry { 627d17c02aSMaxim Levitsky unsigned long size; 637d17c02aSMaxim Levitsky unsigned short cyl; 647d17c02aSMaxim Levitsky unsigned char head; 657d17c02aSMaxim Levitsky unsigned char sec; 667d17c02aSMaxim Levitsky }; 677d17c02aSMaxim Levitsky 687d17c02aSMaxim Levitsky 697d17c02aSMaxim Levitsky #define SM_FTL_PARTN_BITS 3 707d17c02aSMaxim Levitsky 717d17c02aSMaxim Levitsky #define sm_printk(format, ...) \ 727d17c02aSMaxim Levitsky printk(KERN_WARNING "sm_ftl" ": " format "\n", ## __VA_ARGS__) 737d17c02aSMaxim Levitsky 747d17c02aSMaxim Levitsky #define dbg(format, ...) \ 757d17c02aSMaxim Levitsky if (debug) \ 767d17c02aSMaxim Levitsky printk(KERN_DEBUG "sm_ftl" ": " format "\n", ## __VA_ARGS__) 777d17c02aSMaxim Levitsky 787d17c02aSMaxim Levitsky #define dbg_verbose(format, ...) \ 797d17c02aSMaxim Levitsky if (debug > 1) \ 807d17c02aSMaxim Levitsky printk(KERN_DEBUG "sm_ftl" ": " format "\n", ## __VA_ARGS__) 817d17c02aSMaxim Levitsky 827d17c02aSMaxim Levitsky 837d17c02aSMaxim Levitsky static int sm_erase_block(struct sm_ftl *ftl, int zone_num, uint16_t block, 847d17c02aSMaxim Levitsky int put_free); 857d17c02aSMaxim Levitsky static void sm_mark_block_bad(struct sm_ftl *ftl, int zone_num, int block); 867d17c02aSMaxim Levitsky 877d17c02aSMaxim Levitsky static int sm_recheck_media(struct sm_ftl *ftl); 88