Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 #ifndef FWH_LOCK_H
  2 #define FWH_LOCK_H
  3 
  4 
  5 enum fwh_lock_state {
  6         FWH_UNLOCKED   = 0,
  7         FWH_DENY_WRITE = 1,
  8         FWH_IMMUTABLE  = 2,
  9         FWH_DENY_READ  = 4,
 10 };
 11 
 12 struct fwh_xxlock_thunk {
 13         enum fwh_lock_state val;
 14         flstate_t state;
 15 };
 16 
 17 
 18 #define FWH_XXLOCK_ONEBLOCK_LOCK   ((struct fwh_xxlock_thunk){ FWH_DENY_WRITE, FL_LOCKING})
 19 #define FWH_XXLOCK_ONEBLOCK_UNLOCK ((struct fwh_xxlock_thunk){ FWH_UNLOCKED,   FL_UNLOCKING})
 20 
 21 /*
 22  * This locking/unlock is specific to firmware hub parts.  Only one
 23  * is known that supports the Intel command set.    Firmware
 24  * hub parts cannot be interleaved as they are on the LPC bus
 25  * so this code has not been tested with interleaved chips,
 26  * and will likely fail in that context.
 27  */
 28 static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip,
 29         unsigned long adr, int len, void *thunk)
 30 {
 31         struct cfi_private *cfi = map->fldrv_priv;
 32         struct fwh_xxlock_thunk *xxlt = (struct fwh_xxlock_thunk *)thunk;
 33         int ret;
 34 
 35         /* Refuse the operation if the we cannot look behind the chip */
 36         if (chip->start < 0x400000) {
 37                 DEBUG( MTD_DEBUG_LEVEL3,
 38                         "MTD %s(): chip->start: %lx wanted >= 0x400000\n",
 39                         __func__, chip->start );
 40                 return -EIO;
 41         }
 42         /*
 43          * lock block registers:
 44          * - on 64k boundariesand
 45          * - bit 1 set high
 46          * - block lock registers are 4MiB lower - overflow subtract (danger)
 47          *
 48          * The address manipulation is first done on the logical address
 49          * which is 0 at the start of the chip, and then the offset of
 50          * the individual chip is addted to it.  Any other order a weird
 51          * map offset could cause problems.
 52          */
 53         adr = (adr & ~0xffffUL) | 0x2;
 54         adr += chip->start - 0x400000;
 55 
 56         /*
 57          * This is easy because these are writes to registers and not writes
 58          * to flash memory - that means that we don't have to check status
 59          * and timeout.
 60          */
 61         spin_lock(chip->mutex);
 62         ret = get_chip(map, chip, adr, FL_LOCKING);
 63         if (ret) {
 64                 spin_unlock(chip->mutex);
 65                 return ret;
 66         }
 67 
 68         chip->oldstate = chip->state;
 69         chip->state = xxlt->state;
 70         map_write(map, CMD(xxlt->val), adr);
 71 
 72         /* Done and happy. */
 73         chip->state = chip->oldstate;
 74         put_chip(map, chip, adr);
 75         spin_unlock(chip->mutex);
 76         return 0;
 77 }
 78 
 79 
 80 static int fwh_lock_varsize(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 81 {
 82         int ret;
 83 
 84         ret = cfi_varsize_frob(mtd, fwh_xxlock_oneblock, ofs, len,
 85                 (void *)&FWH_XXLOCK_ONEBLOCK_LOCK);
 86 
 87         return ret;
 88 }
 89 
 90 
 91 static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 92 {
 93         int ret;
 94 
 95         ret = cfi_varsize_frob(mtd, fwh_xxlock_oneblock, ofs, len,
 96                 (void *)&FWH_XXLOCK_ONEBLOCK_UNLOCK);
 97 
 98         return ret;
 99 }
100 
101 static void fixup_use_fwh_lock(struct mtd_info *mtd, void *param)
102 {
103         printk(KERN_NOTICE "using fwh lock/unlock method\n");
104         /* Setup for the chips with the fwh lock method */
105         mtd->lock   = fwh_lock_varsize;
106         mtd->unlock = fwh_unlock_varsize;
107 }
108 #endif /* FWH_LOCK_H */
109 
  This page was automatically generated by the LXR engine.