Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  nand_timings.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 *  Copyright (C) 2014 Free Electrons
 *
 *  Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
 */

#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/export.h>

#include "internals.h"

#define ONFI_DYN_TIMING_MAX U16_MAX

/*
 * For non-ONFI chips we use the highest possible value for tPROG and tBERS.
 * tR and tCCS will take the default values precised in the ONFI specification
 * for timing mode 0, respectively 200us and 500ns.
 *
 * These four values are tweaked to be more accurate in the case of ONFI chips.
 */

static const struct nand_interface_config onfi_sdr_timings[] = {
 /* Mode 0 */
 {
  .type = NAND_SDR_IFACE,
  .timings.mode = 0,
  .timings.sdr = {
   .tCCS_min = 500000,
   .tR_max = 200000000,
   .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tADL_min = 400000,
   .tALH_min = 20000,
   .tALS_min = 50000,
   .tAR_min = 25000,
   .tCEA_max = 100000,
   .tCEH_min = 20000,
   .tCH_min = 20000,
   .tCHZ_max = 100000,
   .tCLH_min = 20000,
   .tCLR_min = 20000,
   .tCLS_min = 50000,
   .tCOH_min = 0,
   .tCS_min = 70000,
   .tDH_min = 20000,
   .tDS_min = 40000,
   .tFEAT_max = 1000000,
   .tIR_min = 10000,
   .tITC_max = 1000000,
   .tRC_min = 100000,
   .tREA_max = 40000,
   .tREH_min = 30000,
   .tRHOH_min = 0,
   .tRHW_min = 200000,
   .tRHZ_max = 200000,
   .tRLOH_min = 0,
   .tRP_min = 50000,
   .tRR_min = 40000,
   .tRST_max = 250000000000ULL,
   .tWB_max = 200000,
   .tWC_min = 100000,
   .tWH_min = 30000,
   .tWHR_min = 120000,
   .tWP_min = 50000,
   .tWW_min = 100000,
  },
 },
 /* Mode 1 */
 {
  .type = NAND_SDR_IFACE,
  .timings.mode = 1,
  .timings.sdr = {
   .tCCS_min = 500000,
   .tR_max = 200000000,
   .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tADL_min = 400000,
   .tALH_min = 10000,
   .tALS_min = 25000,
   .tAR_min = 10000,
   .tCEA_max = 45000,
   .tCEH_min = 20000,
   .tCH_min = 10000,
   .tCHZ_max = 50000,
   .tCLH_min = 10000,
   .tCLR_min = 10000,
   .tCLS_min = 25000,
   .tCOH_min = 15000,
   .tCS_min = 35000,
   .tDH_min = 10000,
   .tDS_min = 20000,
   .tFEAT_max = 1000000,
   .tIR_min = 0,
   .tITC_max = 1000000,
   .tRC_min = 50000,
   .tREA_max = 30000,
   .tREH_min = 15000,
   .tRHOH_min = 15000,
   .tRHW_min = 100000,
   .tRHZ_max = 100000,
   .tRLOH_min = 0,
   .tRP_min = 25000,
   .tRR_min = 20000,
   .tRST_max = 500000000,
   .tWB_max = 100000,
   .tWC_min = 45000,
   .tWH_min = 15000,
   .tWHR_min = 80000,
   .tWP_min = 25000,
   .tWW_min = 100000,
  },
 },
 /* Mode 2 */
 {
  .type = NAND_SDR_IFACE,
  .timings.mode = 2,
  .timings.sdr = {
   .tCCS_min = 500000,
   .tR_max = 200000000,
   .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tADL_min = 400000,
   .tALH_min = 10000,
   .tALS_min = 15000,
   .tAR_min = 10000,
   .tCEA_max = 30000,
   .tCEH_min = 20000,
   .tCH_min = 10000,
   .tCHZ_max = 50000,
   .tCLH_min = 10000,
   .tCLR_min = 10000,
   .tCLS_min = 15000,
   .tCOH_min = 15000,
   .tCS_min = 25000,
   .tDH_min = 5000,
   .tDS_min = 15000,
   .tFEAT_max = 1000000,
   .tIR_min = 0,
   .tITC_max = 1000000,
   .tRC_min = 35000,
   .tREA_max = 25000,
   .tREH_min = 15000,
   .tRHOH_min = 15000,
   .tRHW_min = 100000,
   .tRHZ_max = 100000,
   .tRLOH_min = 0,
   .tRR_min = 20000,
   .tRST_max = 500000000,
   .tWB_max = 100000,
   .tRP_min = 17000,
   .tWC_min = 35000,
   .tWH_min = 15000,
   .tWHR_min = 80000,
   .tWP_min = 17000,
   .tWW_min = 100000,
  },
 },
 /* Mode 3 */
 {
  .type = NAND_SDR_IFACE,
  .timings.mode = 3,
  .timings.sdr = {
   .tCCS_min = 500000,
   .tR_max = 200000000,
   .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tADL_min = 400000,
   .tALH_min = 5000,
   .tALS_min = 10000,
   .tAR_min = 10000,
   .tCEA_max = 25000,
   .tCEH_min = 20000,
   .tCH_min = 5000,
   .tCHZ_max = 50000,
   .tCLH_min = 5000,
   .tCLR_min = 10000,
   .tCLS_min = 10000,
   .tCOH_min = 15000,
   .tCS_min = 25000,
   .tDH_min = 5000,
   .tDS_min = 10000,
   .tFEAT_max = 1000000,
   .tIR_min = 0,
   .tITC_max = 1000000,
   .tRC_min = 30000,
   .tREA_max = 20000,
   .tREH_min = 10000,
   .tRHOH_min = 15000,
   .tRHW_min = 100000,
   .tRHZ_max = 100000,
   .tRLOH_min = 0,
   .tRP_min = 15000,
   .tRR_min = 20000,
   .tRST_max = 500000000,
   .tWB_max = 100000,
   .tWC_min = 30000,
   .tWH_min = 10000,
   .tWHR_min = 80000,
   .tWP_min = 15000,
   .tWW_min = 100000,
  },
 },
 /* Mode 4 */
 {
  .type = NAND_SDR_IFACE,
  .timings.mode = 4,
  .timings.sdr = {
   .tCCS_min = 500000,
   .tR_max = 200000000,
   .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tADL_min = 400000,
   .tALH_min = 5000,
   .tALS_min = 10000,
   .tAR_min = 10000,
   .tCEA_max = 25000,
   .tCEH_min = 20000,
   .tCH_min = 5000,
   .tCHZ_max = 30000,
   .tCLH_min = 5000,
   .tCLR_min = 10000,
   .tCLS_min = 10000,
   .tCOH_min = 15000,
   .tCS_min = 20000,
   .tDH_min = 5000,
   .tDS_min = 10000,
   .tFEAT_max = 1000000,
   .tIR_min = 0,
   .tITC_max = 1000000,
   .tRC_min = 25000,
   .tREA_max = 20000,
   .tREH_min = 10000,
   .tRHOH_min = 15000,
   .tRHW_min = 100000,
   .tRHZ_max = 100000,
   .tRLOH_min = 5000,
   .tRP_min = 12000,
   .tRR_min = 20000,
   .tRST_max = 500000000,
   .tWB_max = 100000,
   .tWC_min = 25000,
   .tWH_min = 10000,
   .tWHR_min = 80000,
   .tWP_min = 12000,
   .tWW_min = 100000,
  },
 },
 /* Mode 5 */
 {
  .type = NAND_SDR_IFACE,
  .timings.mode = 5,
  .timings.sdr = {
   .tCCS_min = 500000,
   .tR_max = 200000000,
   .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tADL_min = 400000,
   .tALH_min = 5000,
   .tALS_min = 10000,
   .tAR_min = 10000,
   .tCEA_max = 25000,
   .tCEH_min = 20000,
   .tCH_min = 5000,
   .tCHZ_max = 30000,
   .tCLH_min = 5000,
   .tCLR_min = 10000,
   .tCLS_min = 10000,
   .tCOH_min = 15000,
   .tCS_min = 15000,
   .tDH_min = 5000,
   .tDS_min = 7000,
   .tFEAT_max = 1000000,
   .tIR_min = 0,
   .tITC_max = 1000000,
   .tRC_min = 20000,
   .tREA_max = 16000,
   .tREH_min = 7000,
   .tRHOH_min = 15000,
   .tRHW_min = 100000,
   .tRHZ_max = 100000,
   .tRLOH_min = 5000,
   .tRP_min = 10000,
   .tRR_min = 20000,
   .tRST_max = 500000000,
   .tWB_max = 100000,
   .tWC_min = 20000,
   .tWH_min = 7000,
   .tWHR_min = 80000,
   .tWP_min = 10000,
   .tWW_min = 100000,
  },
 },
};

static const struct nand_interface_config onfi_nvddr_timings[] = {
 /* Mode 0 */
 {
  .type = NAND_NVDDR_IFACE,
  .timings.mode = 0,
  .timings.nvddr = {
   .tCCS_min = 500000,
   .tR_max = 200000000,
   .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tAC_min = 3000,
   .tAC_max = 25000,
   .tADL_min = 400000,
   .tCAD_min = 45000,
   .tCAH_min = 10000,
   .tCALH_min = 10000,
   .tCALS_min = 10000,
   .tCAS_min = 10000,
   .tCEH_min = 20000,
   .tCH_min = 10000,
   .tCK_min = 50000,
   .tCS_min = 35000,
   .tDH_min = 5000,
   .tDQSCK_min = 3000,
   .tDQSCK_max = 25000,
   .tDQSD_min = 0,
   .tDQSD_max = 18000,
   .tDQSHZ_max = 20000,
   .tDQSQ_max = 5000,
   .tDS_min = 5000,
   .tDSC_min = 50000,
   .tFEAT_max = 1000000,
   .tITC_max = 1000000,
   .tQHS_max = 6000,
   .tRHW_min = 100000,
   .tRR_min = 20000,
   .tRST_max = 500000000,
   .tWB_max = 100000,
   .tWHR_min = 80000,
   .tWRCK_min = 20000,
   .tWW_min = 100000,
  },
 },
 /* Mode 1 */
 {
  .type = NAND_NVDDR_IFACE,
  .timings.mode = 1,
  .timings.nvddr = {
   .tCCS_min = 500000,
   .tR_max = 200000000,
   .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tAC_min = 3000,
   .tAC_max = 25000,
   .tADL_min = 400000,
   .tCAD_min = 45000,
   .tCAH_min = 5000,
   .tCALH_min = 5000,
   .tCALS_min = 5000,
   .tCAS_min = 5000,
   .tCEH_min = 20000,
   .tCH_min = 5000,
   .tCK_min = 30000,
   .tCS_min = 25000,
   .tDH_min = 2500,
   .tDQSCK_min = 3000,
   .tDQSCK_max = 25000,
   .tDQSD_min = 0,
   .tDQSD_max = 18000,
   .tDQSHZ_max = 20000,
   .tDQSQ_max = 2500,
   .tDS_min = 3000,
   .tDSC_min = 30000,
   .tFEAT_max = 1000000,
   .tITC_max = 1000000,
   .tQHS_max = 3000,
   .tRHW_min = 100000,
   .tRR_min = 20000,
   .tRST_max = 500000000,
   .tWB_max = 100000,
   .tWHR_min = 80000,
   .tWRCK_min = 20000,
   .tWW_min = 100000,
  },
 },
 /* Mode 2 */
 {
  .type = NAND_NVDDR_IFACE,
  .timings.mode = 2,
  .timings.nvddr = {
   .tCCS_min = 500000,
   .tR_max = 200000000,
   .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tAC_min = 3000,
   .tAC_max = 25000,
   .tADL_min = 400000,
   .tCAD_min = 45000,
   .tCAH_min = 4000,
   .tCALH_min = 4000,
   .tCALS_min = 4000,
   .tCAS_min = 4000,
   .tCEH_min = 20000,
   .tCH_min = 4000,
   .tCK_min = 20000,
   .tCS_min = 15000,
   .tDH_min = 1700,
   .tDQSCK_min = 3000,
   .tDQSCK_max = 25000,
   .tDQSD_min = 0,
   .tDQSD_max = 18000,
   .tDQSHZ_max = 20000,
   .tDQSQ_max = 1700,
   .tDS_min = 2000,
   .tDSC_min = 20000,
   .tFEAT_max = 1000000,
   .tITC_max = 1000000,
   .tQHS_max = 2000,
   .tRHW_min = 100000,
   .tRR_min = 20000,
   .tRST_max = 500000000,
   .tWB_max = 100000,
   .tWHR_min = 80000,
   .tWRCK_min = 20000,
   .tWW_min = 100000,
  },
 },
 /* Mode 3 */
 {
  .type = NAND_NVDDR_IFACE,
  .timings.mode = 3,
  .timings.nvddr = {
   .tCCS_min = 500000,
   .tR_max = 200000000,
   .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tAC_min = 3000,
   .tAC_max = 25000,
   .tADL_min = 400000,
   .tCAD_min = 45000,
   .tCAH_min = 3000,
   .tCALH_min = 3000,
   .tCALS_min = 3000,
   .tCAS_min = 3000,
   .tCEH_min = 20000,
   .tCH_min = 3000,
   .tCK_min = 15000,
   .tCS_min = 15000,
   .tDH_min = 1300,
   .tDQSCK_min = 3000,
   .tDQSCK_max = 25000,
   .tDQSD_min = 0,
   .tDQSD_max = 18000,
   .tDQSHZ_max = 20000,
   .tDQSQ_max = 1300,
   .tDS_min = 1500,
   .tDSC_min = 15000,
   .tFEAT_max = 1000000,
   .tITC_max = 1000000,
   .tQHS_max = 1500,
   .tRHW_min = 100000,
   .tRR_min = 20000,
   .tRST_max = 500000000,
   .tWB_max = 100000,
   .tWHR_min = 80000,
   .tWRCK_min = 20000,
   .tWW_min = 100000,
  },
 },
 /* Mode 4 */
 {
  .type = NAND_NVDDR_IFACE,
  .timings.mode = 4,
  .timings.nvddr = {
   .tCCS_min = 500000,
   .tR_max = 200000000,
   .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tAC_min = 3000,
   .tAC_max = 25000,
   .tADL_min = 400000,
   .tCAD_min = 45000,
   .tCAH_min = 2500,
   .tCALH_min = 2500,
   .tCALS_min = 2500,
   .tCAS_min = 2500,
   .tCEH_min = 20000,
   .tCH_min = 2500,
   .tCK_min = 12000,
   .tCS_min = 15000,
   .tDH_min = 1100,
   .tDQSCK_min = 3000,
   .tDQSCK_max = 25000,
   .tDQSD_min = 0,
   .tDQSD_max = 18000,
   .tDQSHZ_max = 20000,
   .tDQSQ_max = 1000,
   .tDS_min = 1100,
   .tDSC_min = 12000,
   .tFEAT_max = 1000000,
   .tITC_max = 1000000,
   .tQHS_max = 1200,
   .tRHW_min = 100000,
   .tRR_min = 20000,
   .tRST_max = 500000000,
   .tWB_max = 100000,
   .tWHR_min = 80000,
   .tWRCK_min = 20000,
   .tWW_min = 100000,
  },
 },
 /* Mode 5 */
 {
  .type = NAND_NVDDR_IFACE,
  .timings.mode = 5,
  .timings.nvddr = {
   .tCCS_min = 500000,
   .tR_max = 200000000,
   .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
   .tAC_min = 3000,
   .tAC_max = 25000,
   .tADL_min = 400000,
   .tCAD_min = 45000,
   .tCAH_min = 2000,
   .tCALH_min = 2000,
   .tCALS_min = 2000,
   .tCAS_min = 2000,
   .tCEH_min = 20000,
   .tCH_min = 2000,
   .tCK_min = 10000,
   .tCS_min = 15000,
   .tDH_min = 900,
   .tDQSCK_min = 3000,
   .tDQSCK_max = 25000,
   .tDQSD_min = 0,
   .tDQSD_max = 18000,
   .tDQSHZ_max = 20000,
   .tDQSQ_max = 850,
   .tDS_min = 900,
   .tDSC_min = 10000,
   .tFEAT_max = 1000000,
   .tITC_max = 1000000,
   .tQHS_max = 1000,
   .tRHW_min = 100000,
   .tRR_min = 20000,
   .tRST_max = 500000000,
   .tWB_max = 100000,
   .tWHR_min = 80000,
   .tWRCK_min = 20000,
   .tWW_min = 100000,
  },
 },
};

/* All NAND chips share the same reset data interface: SDR mode 0 */
const struct nand_interface_config *nand_get_reset_interface_config(void)
{
 return &onfi_sdr_timings[0];
}

/**
 * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a
 *                              set of timings
 * @spec_timings: the timings to challenge
 */

unsigned int
onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings)
{
 const struct nand_sdr_timings *onfi_timings;
 int mode;

 for (mode = ARRAY_SIZE(onfi_sdr_timings) - 1; mode > 0; mode--) {
  onfi_timings = &onfi_sdr_timings[mode].timings.sdr;

  if (spec_timings->tCCS_min <= onfi_timings->tCCS_min &&
      spec_timings->tADL_min <= onfi_timings->tADL_min &&
      spec_timings->tALH_min <= onfi_timings->tALH_min &&
      spec_timings->tALS_min <= onfi_timings->tALS_min &&
      spec_timings->tAR_min <= onfi_timings->tAR_min &&
      spec_timings->tCEH_min <= onfi_timings->tCEH_min &&
      spec_timings->tCH_min <= onfi_timings->tCH_min &&
      spec_timings->tCLH_min <= onfi_timings->tCLH_min &&
      spec_timings->tCLR_min <= onfi_timings->tCLR_min &&
      spec_timings->tCLS_min <= onfi_timings->tCLS_min &&
      spec_timings->tCOH_min <= onfi_timings->tCOH_min &&
      spec_timings->tCS_min <= onfi_timings->tCS_min &&
      spec_timings->tDH_min <= onfi_timings->tDH_min &&
      spec_timings->tDS_min <= onfi_timings->tDS_min &&
      spec_timings->tIR_min <= onfi_timings->tIR_min &&
      spec_timings->tRC_min <= onfi_timings->tRC_min &&
      spec_timings->tREH_min <= onfi_timings->tREH_min &&
      spec_timings->tRHOH_min <= onfi_timings->tRHOH_min &&
      spec_timings->tRHW_min <= onfi_timings->tRHW_min &&
      spec_timings->tRLOH_min <= onfi_timings->tRLOH_min &&
      spec_timings->tRP_min <= onfi_timings->tRP_min &&
      spec_timings->tRR_min <= onfi_timings->tRR_min &&
      spec_timings->tWC_min <= onfi_timings->tWC_min &&
      spec_timings->tWH_min <= onfi_timings->tWH_min &&
      spec_timings->tWHR_min <= onfi_timings->tWHR_min &&
      spec_timings->tWP_min <= onfi_timings->tWP_min &&
      spec_timings->tWW_min <= onfi_timings->tWW_min)
   return mode;
 }

 return 0;
}

/**
 * onfi_find_closest_nvddr_mode - Derive the closest ONFI NVDDR timing mode
 *                                given a set of timings
 * @spec_timings: the timings to challenge
 */

unsigned int
onfi_find_closest_nvddr_mode(const struct nand_nvddr_timings *spec_timings)
{
 const struct nand_nvddr_timings *onfi_timings;
 int mode;

 for (mode = ARRAY_SIZE(onfi_nvddr_timings) - 1; mode > 0; mode--) {
  onfi_timings = &onfi_nvddr_timings[mode].timings.nvddr;

  if (spec_timings->tCCS_min <= onfi_timings->tCCS_min &&
      spec_timings->tAC_min <= onfi_timings->tAC_min &&
      spec_timings->tADL_min <= onfi_timings->tADL_min &&
      spec_timings->tCAD_min <= onfi_timings->tCAD_min &&
      spec_timings->tCAH_min <= onfi_timings->tCAH_min &&
      spec_timings->tCALH_min <= onfi_timings->tCALH_min &&
      spec_timings->tCALS_min <= onfi_timings->tCALS_min &&
      spec_timings->tCAS_min <= onfi_timings->tCAS_min &&
      spec_timings->tCEH_min <= onfi_timings->tCEH_min &&
      spec_timings->tCH_min <= onfi_timings->tCH_min &&
      spec_timings->tCK_min <= onfi_timings->tCK_min &&
      spec_timings->tCS_min <= onfi_timings->tCS_min &&
      spec_timings->tDH_min <= onfi_timings->tDH_min &&
      spec_timings->tDQSCK_min <= onfi_timings->tDQSCK_min &&
      spec_timings->tDQSD_min <= onfi_timings->tDQSD_min &&
      spec_timings->tDS_min <= onfi_timings->tDS_min &&
      spec_timings->tDSC_min <= onfi_timings->tDSC_min &&
      spec_timings->tRHW_min <= onfi_timings->tRHW_min &&
      spec_timings->tRR_min <= onfi_timings->tRR_min &&
      spec_timings->tWHR_min <= onfi_timings->tWHR_min &&
      spec_timings->tWRCK_min <= onfi_timings->tWRCK_min &&
      spec_timings->tWW_min <= onfi_timings->tWW_min)
   return mode;
 }

 return 0;
}

/*
 * onfi_fill_sdr_interface_config - Initialize a SDR interface config from a
 *                                  given ONFI mode
 * @chip: The NAND chip
 * @iface: The interface configuration to fill
 * @timing_mode: The ONFI timing mode
 */

static void onfi_fill_sdr_interface_config(struct nand_chip *chip,
        struct nand_interface_config *iface,
        unsigned int timing_mode)
{
 struct onfi_params *onfi = chip->parameters.onfi;

 if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_sdr_timings)))
  return;

 *iface = onfi_sdr_timings[timing_mode];

 /*
 * Initialize timings that cannot be deduced from timing mode:
 * tPROG, tBERS, tR and tCCS.
 * These information are part of the ONFI parameter page.
 */

 if (onfi) {
  struct nand_sdr_timings *timings = &iface->timings.sdr;

  /* microseconds -> picoseconds */
  timings->tPROG_max = 1000000ULL * onfi->tPROG;
  timings->tBERS_max = 1000000ULL * onfi->tBERS;
  timings->tR_max = 1000000ULL * onfi->tR;

  /* nanoseconds -> picoseconds */
  timings->tCCS_min = 1000UL * onfi->tCCS;
 }
}

/**
 * onfi_fill_nvddr_interface_config - Initialize a NVDDR interface config from a
 *                                    given ONFI mode
 * @chip: The NAND chip
 * @iface: The interface configuration to fill
 * @timing_mode: The ONFI timing mode
 */

static void onfi_fill_nvddr_interface_config(struct nand_chip *chip,
          struct nand_interface_config *iface,
          unsigned int timing_mode)
{
 struct onfi_params *onfi = chip->parameters.onfi;

 if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_nvddr_timings)))
  return;

 *iface = onfi_nvddr_timings[timing_mode];

 /*
 * Initialize timings that cannot be deduced from timing mode:
 * tPROG, tBERS, tR, tCCS and tCAD.
 * These information are part of the ONFI parameter page.
 */

 if (onfi) {
  struct nand_nvddr_timings *timings = &iface->timings.nvddr;

  /* microseconds -> picoseconds */
  timings->tPROG_max = 1000000ULL * onfi->tPROG;
  timings->tBERS_max = 1000000ULL * onfi->tBERS;
  timings->tR_max = 1000000ULL * onfi->tR;

  /* nanoseconds -> picoseconds */
  timings->tCCS_min = 1000UL * onfi->tCCS;

  if (onfi->fast_tCAD)
   timings->tCAD_min = 25000;
 }
}

/**
 * onfi_fill_interface_config - Initialize an interface config from a given
 *                              ONFI mode
 * @chip: The NAND chip
 * @iface: The interface configuration to fill
 * @type: The interface type
 * @timing_mode: The ONFI timing mode
 */

void onfi_fill_interface_config(struct nand_chip *chip,
    struct nand_interface_config *iface,
    enum nand_interface_type type,
    unsigned int timing_mode)
{
 if (type == NAND_SDR_IFACE)
  return onfi_fill_sdr_interface_config(chip, iface, timing_mode);
 else
  return onfi_fill_nvddr_interface_config(chip, iface, timing_mode);
}

Messung V0.5
C=90 H=88 G=88

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge