Commit e413a19a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'for-linus-20140610' of git://git.infradead.org/linux-mtd

Pull MTD updates from Brian Norris:
 - refactor m25p80.c driver for use as a general SPI NOR framework for
   other drivers which may speak to SPI NOR flash without providing full
   SPI support (i.e., not part of drivers/spi/)
 - new Freescale QuadSPI driver (utilizing new SPI NOR framework)
 - updates for the STMicro "FSM" SPI NOR driver
 - fix sync/flush behavior on mtd_blkdevs
 - fixup subpage write support on a few NAND drivers
 - correct the MTD OOB test for odd-sized OOB areas
 - add BCH-16 support for OMAP NAND
 - fix warnings and trivial refactoring
 - utilize new ECC DT bindings in pxa3xx NAND driver
 - new LPDDR NVM driver
 - address a few assorted bugs caught by Coverity
 - add new imx6sx support for GPMI NAND
 - use a bounce buffer for NAND when non-DMA-able buffers are used

* tag 'for-linus-20140610' of git://git.infradead.org/linux-mtd: (77 commits)
  mtd: gpmi: add gpmi support for imx6sx
  mtd: maps: remove check for CON...
parents 8d0304e6 f1900c79
* Freescale Quad Serial Peripheral Interface(QuadSPI)
Required properties:
- compatible : Should be "fsl,vf610-qspi"
- reg : the first contains the register location and length,
the second contains the memory mapping address and length
- reg-names: Should contain the reg names "QuadSPI" and "QuadSPI-memory"
- interrupts : Should contain the interrupt for the device
- clocks : The clocks needed by the QuadSPI controller
- clock-names : the name of the clocks
Optional properties:
- fsl,qspi-has-second-chip: The controller has two buses, bus A and bus B.
Each bus can be connected with two NOR flashes.
Most of the time, each bus only has one NOR flash
connected, this is the default case.
But if there are two NOR flashes connected to the
bus, you should enable this property.
(Please check the board's schematic.)
Example:
qspi0: quadspi@40044000 {
compatible = "fsl,vf610-qspi";
reg = <0x40044000 0x1000>, <0x20000000 0x10000000>;
reg-names = "QuadSPI", "QuadSPI-memory";
interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks VF610_CLK_QSPI0_EN>,
<&clks VF610_CLK_QSPI0>;
clock-names = "qspi_en", "qspi";
flash0: s25fl128s@0 {
....
};
};
......@@ -28,6 +28,8 @@ Optional properties:
"ham1" 1-bit Hamming ecc code
"bch4" 4-bit BCH ecc code
"bch8" 8-bit BCH ecc code
"bch16" 16-bit BCH ECC code
Refer below "How to select correct ECC scheme for your device ?"
- ti,nand-xfer-type: A string setting the data transfer type. One of:
......@@ -90,3 +92,46 @@ Example for an AM33xx board:
};
};
How to select correct ECC scheme for your device ?
--------------------------------------------------
Higher ECC scheme usually means better protection against bit-flips and
increased system lifetime. However, selection of ECC scheme is dependent
on various other factors also like;
(1) support of built in hardware engines.
Some legacy OMAP SoC do not have ELM harware engine, so those SoC cannot
support ecc-schemes with hardware error-correction (BCHx_HW). However
such SoC can use ecc-schemes with software library for error-correction
(BCHx_HW_DETECTION_SW). The error correction capability with software
library remains equivalent to their hardware counter-part, but there is
slight CPU penalty when too many bit-flips are detected during reads.
(2) Device parameters like OOBSIZE.
Other factor which governs the selection of ecc-scheme is oob-size.
Higher ECC schemes require more OOB/Spare area to store ECC syndrome,
so the device should have enough free bytes available its OOB/Spare
area to accomodate ECC for entire page. In general following expression
helps in determining if given device can accomodate ECC syndrome:
"2 + (PAGESIZE / 512) * ECC_BYTES" >= OOBSIZE"
where
OOBSIZE number of bytes in OOB/spare area
PAGESIZE number of bytes in main-area of device page
ECC_BYTES number of ECC bytes generated to protect
512 bytes of data, which is:
'3' for HAM1_xx ecc schemes
'7' for BCH4_xx ecc schemes
'14' for BCH8_xx ecc schemes
'26' for BCH16_xx ecc schemes
Example(a): For a device with PAGESIZE = 2048 and OOBSIZE = 64 and
trying to use BCH16 (ECC_BYTES=26) ecc-scheme.
Number of ECC bytes per page = (2 + (2048 / 512) * 26) = 106 B
which is greater than capacity of NAND device (OOBSIZE=64)
Hence, BCH16 cannot be supported on given device. But it can
probably use lower ecc-schemes like BCH8.
Example(b): For a device with PAGESIZE = 2048 and OOBSIZE = 128 and
trying to use BCH16 (ECC_BYTES=26) ecc-scheme.
Number of ECC bytes per page = (2 + (2048 / 512) * 26) = 106 B
which can be accomodate in the OOB/Spare area of this device
(OOBSIZE=128). So this device can use BCH16 ecc-scheme.
......@@ -5,8 +5,8 @@ Required properties:
representing partitions.
- compatible : Should be the manufacturer and the name of the chip. Bear in mind
the DT binding is not Linux-only, but in case of Linux, see the
"m25p_ids" table in drivers/mtd/devices/m25p80.c for the list of
supported chips.
"spi_nor_ids" table in drivers/mtd/spi-nor/spi-nor.c for the list
of supported chips.
- reg : Chip-Select number
- spi-max-frequency : Maximum frequency of the SPI bus the chip can operate at
......
......@@ -17,6 +17,14 @@ Optional properties:
- num-cs: Number of chipselect lines to usw
- nand-on-flash-bbt: boolean to enable on flash bbt option if
not present false
- nand-ecc-strength: number of bits to correct per ECC step
- nand-ecc-step-size: number of data bytes covered by a single ECC step
The following ECC strength and step size are currently supported:
- nand-ecc-strength = <1>, nand-ecc-step-size = <512>
- nand-ecc-strength = <4>, nand-ecc-step-size = <512>
- nand-ecc-strength = <8>, nand-ecc-step-size = <512>
Example:
......
SPI NOR framework
============================================
Part I - Why do we need this framework?
---------------------------------------
SPI bus controllers (drivers/spi/) only deal with streams of bytes; the bus
controller operates agnostic of the specific device attached. However, some
controllers (such as Freescale's QuadSPI controller) cannot easily handle
arbitrary streams of bytes, but rather are designed specifically for SPI NOR.
In particular, Freescale's QuadSPI controller must know the NOR commands to
find the right LUT sequence. Unfortunately, the SPI subsystem has no notion of
opcodes, addresses, or data payloads; a SPI controller simply knows to send or
receive bytes (Tx and Rx). Therefore, we must define a new layering scheme under
which the controller driver is aware of the opcodes, addressing, and other
details of the SPI NOR protocol.
Part II - How does the framework work?
--------------------------------------
This framework just adds a new layer between the MTD and the SPI bus driver.
With this new layer, the SPI NOR controller driver does not depend on the
m25p80 code anymore.
Before this framework, the layer is like:
MTD
------------------------
m25p80
------------------------
SPI bus driver
------------------------
SPI NOR chip
After this framework, the layer is like:
MTD
------------------------
SPI NOR framework
------------------------
m25p80
------------------------
SPI bus driver
------------------------
SPI NOR chip
With the SPI NOR controller driver (Freescale QuadSPI), it looks like:
MTD
------------------------
SPI NOR framework
------------------------
fsl-quadSPI
------------------------
SPI NOR chip
Part III - How can drivers use the framework?
---------------------------------------------
The main API is spi_nor_scan(). Before you call the hook, a driver should
initialize the necessary fields for spi_nor{}. Please see
drivers/mtd/spi-nor/spi-nor.c for detail. Please also refer to fsl-quadspi.c
when you want to write a new driver for a SPI NOR controller.
......@@ -68,6 +68,9 @@
#define GPMC_ECC_BCH_RESULT_1 0x244 /* not available on OMAP2 */
#define GPMC_ECC_BCH_RESULT_2 0x248 /* not available on OMAP2 */
#define GPMC_ECC_BCH_RESULT_3 0x24c /* not available on OMAP2 */
#define GPMC_ECC_BCH_RESULT_4 0x300 /* not available on OMAP2 */
#define GPMC_ECC_BCH_RESULT_5 0x304 /* not available on OMAP2 */
#define GPMC_ECC_BCH_RESULT_6 0x308 /* not available on OMAP2 */
/* GPMC ECC control settings */
#define GPMC_ECC_CTRL_ECCCLEAR 0x100
......@@ -677,6 +680,12 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
GPMC_BCH_SIZE * i;
reg->gpmc_bch_result3[i] = gpmc_base + GPMC_ECC_BCH_RESULT_3 +
GPMC_BCH_SIZE * i;
reg->gpmc_bch_result4[i] = gpmc_base + GPMC_ECC_BCH_RESULT_4 +
i * GPMC_BCH_SIZE;
reg->gpmc_bch_result5[i] = gpmc_base + GPMC_ECC_BCH_RESULT_5 +
i * GPMC_BCH_SIZE;
reg->gpmc_bch_result6[i] = gpmc_base + GPMC_ECC_BCH_RESULT_6 +
i * GPMC_BCH_SIZE;
}
}
......@@ -1412,6 +1421,12 @@ static int gpmc_probe_nand_child(struct platform_device *pdev,
else
gpmc_nand_data->ecc_opt =
OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
else if (!strcmp(s, "bch16"))
if (gpmc_nand_data->elm_of_node)
gpmc_nand_data->ecc_opt =
OMAP_ECC_BCH16_CODE_HW;
else
pr_err("%s: BCH16 requires ELM support\n", __func__);
else
pr_err("%s: ti,nand-ecc-opt invalid value\n", __func__);
......
......@@ -321,6 +321,8 @@ source "drivers/mtd/onenand/Kconfig"
source "drivers/mtd/lpddr/Kconfig"
source "drivers/mtd/spi-nor/Kconfig"
source "drivers/mtd/ubi/Kconfig"
endif # MTD
......@@ -32,4 +32,5 @@ inftl-objs := inftlcore.o inftlmount.o
obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/
obj-$(CONFIG_MTD_UBI) += ubi/
......@@ -169,33 +169,33 @@ config MTD_OTP
in the programming of OTP bits will waste them.
config MTD_CFI_INTELEXT
tristate "Support for Intel/Sharp flash chips"
tristate "Support for CFI command set 0001 (Intel/Sharp chips)"
depends on MTD_GEN_PROBE
select MTD_CFI_UTIL
help
The Common Flash Interface defines a number of different command
sets which a CFI-compliant chip may claim to implement. This code
provides support for one of those command sets, used on Intel
StrataFlash and other parts.
provides support for command set 0001, used on Intel StrataFlash
and other parts.
config MTD_CFI_AMDSTD
tristate "Support for AMD/Fujitsu/Spansion flash chips"
tristate "Support for CFI command set 0002 (AMD/Fujitsu/Spansion chips)"
depends on MTD_GEN_PROBE
select MTD_CFI_UTIL
help
The Common Flash Interface defines a number of different command
sets which a CFI-compliant chip may claim to implement. This code
provides support for one of those command sets, used on chips
including the AMD Am29LV320.
provides support for command set 0002, used on chips including
the AMD Am29LV320.
config MTD_CFI_STAA
tristate "Support for ST (Advanced Architecture) flash chips"
tristate "Support for CFI command set 0020 (ST (Advanced Architecture) chips)"
depends on MTD_GEN_PROBE
select MTD_CFI_UTIL
help
The Common Flash Interface defines a number of different command
sets which a CFI-compliant chip may claim to implement. This code
provides support for one of those command sets.
provides support for command set 0020.
config MTD_CFI_UTIL
tristate
......
......@@ -961,7 +961,7 @@ static int cfi_staa_erase_varsize(struct mtd_info *mtd,
chipnum++;
if (chipnum >= cfi->numchips)
break;
break;
}
}
......@@ -1170,7 +1170,7 @@ static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
chipnum++;
if (chipnum >= cfi->numchips)
break;
break;
}
}
return 0;
......
......@@ -239,7 +239,7 @@ int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
chipnum++;
if (chipnum >= cfi->numchips)
break;
break;
}
}
......
......@@ -80,7 +80,7 @@ config MTD_DATAFLASH_OTP
config MTD_M25P80
tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)"
depends on SPI_MASTER
depends on SPI_MASTER && MTD_SPI_NOR
help
This enables access to most modern SPI flash chips, used for
program and data storage. Series supported include Atmel AT26DF,
......@@ -212,7 +212,7 @@ config MTD_DOCG3
config MTD_ST_SPI_FSM
tristate "ST Microelectronics SPI FSM Serial Flash Controller"
depends on ARM || SH
depends on ARCH_STI
help
This provides an MTD device driver for the ST Microelectronics
SPI Fast Sequence Mode (FSM) Serial Flash Controller and support
......
......@@ -213,6 +213,28 @@ static void elm_load_syndrome(struct elm_info *info,
val = cpu_to_be32(*(u32 *) &ecc[0]) >> 12;
elm_write_reg(info, offset, val);
break;
case BCH16_ECC:
val = cpu_to_be32(*(u32 *) &ecc[22]);
elm_write_reg(info, offset, val);
offset += 4;
val = cpu_to_be32(*(u32 *) &ecc[18]);
elm_write_reg(info, offset, val);
offset += 4;
val = cpu_to_be32(*(u32 *) &ecc[14]);
elm_write_reg(info, offset, val);
offset += 4;
val = cpu_to_be32(*(u32 *) &ecc[10]);
elm_write_reg(info, offset, val);
offset += 4;
val = cpu_to_be32(*(u32 *) &ecc[6]);
elm_write_reg(info, offset, val);
offset += 4;
val = cpu_to_be32(*(u32 *) &ecc[2]);
elm_write_reg(info, offset, val);
offset += 4;
val = cpu_to_be32(*(u32 *) &ecc[0]) >> 16;
elm_write_reg(info, offset, val);
break;
default:
pr_err("invalid config bch_type\n");
}
......@@ -418,6 +440,7 @@ static int elm_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
/**
* elm_context_save
* saves ELM configurations to preserve them across Hardware powered-down
......@@ -435,6 +458,13 @@ static int elm_context_save(struct elm_info *info)
for (i = 0; i < ERROR_VECTOR_MAX; i++) {
offset = i * SYNDROME_FRAGMENT_REG_SIZE;
switch (bch_type) {
case BCH16_ECC:
regs->elm_syndrome_fragment_6[i] = elm_read_reg(info,
ELM_SYNDROME_FRAGMENT_6 + offset);
regs->elm_syndrome_fragment_5[i] = elm_read_reg(info,
ELM_SYNDROME_FRAGMENT_5 + offset);
regs->elm_syndrome_fragment_4[i] = elm_read_reg(info,
ELM_SYNDROME_FRAGMENT_4 + offset);
case BCH8_ECC:
regs->elm_syndrome_fragment_3[i] = elm_read_reg(info,
ELM_SYNDROME_FRAGMENT_3 + offset);
......@@ -473,6 +503,13 @@ static int elm_context_restore(struct elm_info *info)
for (i = 0; i < ERROR_VECTOR_MAX; i++) {
offset = i * SYNDROME_FRAGMENT_REG_SIZE;
switch (bch_type) {
case BCH16_ECC:
elm_write_reg(info, ELM_SYNDROME_FRAGMENT_6 + offset,
regs->elm_syndrome_fragment_6[i]);
elm_write_reg(info, ELM_SYNDROME_FRAGMENT_5 + offset,
regs->elm_syndrome_fragment_5[i]);
elm_write_reg(info, ELM_SYNDROME_FRAGMENT_4 + offset,
regs->elm_syndrome_fragment_4[i]);
case BCH8_ECC:
elm_write_reg(info, ELM_SYNDROME_FRAGMENT_3 + offset,
regs->elm_syndrome_fragment_3[i]);
......@@ -509,6 +546,7 @@ static int elm_resume(struct device *dev)
elm_context_restore(info);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(elm_pm_ops, elm_suspend, elm_resume);
......
This diff is collapsed.
......@@ -13,43 +13,23 @@
#define _MTD_SERIAL_FLASH_CMDS_H
/* Generic Flash Commands/OPCODEs */
#define FLASH_CMD_WREN 0x06
#define FLASH_CMD_WRDI 0x04
#define FLASH_CMD_RDID 0x9f
#define FLASH_CMD_RDSR 0x05
#define FLASH_CMD_RDSR2 0x35
#define FLASH_CMD_WRSR 0x01
#define FLASH_CMD_SE_4K 0x20
#define FLASH_CMD_SE_32K 0x52
#define FLASH_CMD_SE 0xd8
#define FLASH_CMD_CHIPERASE 0xc7
#define FLASH_CMD_WRVCR 0x81
#define FLASH_CMD_RDVCR 0x85
#define SPINOR_OP_RDSR2 0x35
#define SPINOR_OP_WRVCR 0x81
#define SPINOR_OP_RDVCR 0x85
/* JEDEC Standard - Serial Flash Discoverable Parmeters (SFDP) Commands */
#define FLASH_CMD_READ 0x03 /* READ */
#define FLASH_CMD_READ_FAST 0x0b /* FAST READ */
#define FLASH_CMD_READ_1_1_2 0x3b /* DUAL OUTPUT READ */
#define FLASH_CMD_READ_1_2_2 0xbb /* DUAL I/O READ */
#define FLASH_CMD_READ_1_1_4 0x6b /* QUAD OUTPUT READ */
#define FLASH_CMD_READ_1_4_4 0xeb /* QUAD I/O READ */
#define SPINOR_OP_READ_1_2_2 0xbb /* DUAL I/O READ */
#define SPINOR_OP_READ_1_4_4 0xeb /* QUAD I/O READ */
#define FLASH_CMD_WRITE 0x02 /* PAGE PROGRAM */
#define FLASH_CMD_WRITE_1_1_2 0xa2 /* DUAL INPUT PROGRAM */
#define FLASH_CMD_WRITE_1_2_2 0xd2 /* DUAL INPUT EXT PROGRAM */
#define FLASH_CMD_WRITE_1_1_4 0x32 /* QUAD INPUT PROGRAM */
#define FLASH_CMD_WRITE_1_4_4 0x12 /* QUAD INPUT EXT PROGRAM */
#define FLASH_CMD_EN4B_ADDR 0xb7 /* Enter 4-byte address mode */
#define FLASH_CMD_EX4B_ADDR 0xe9 /* Exit 4-byte address mode */
#define SPINOR_OP_WRITE 0x02 /* PAGE PROGRAM */
#define SPINOR_OP_WRITE_1_1_2 0xa2 /* DUAL INPUT PROGRAM */
#define SPINOR_OP_WRITE_1_2_2 0xd2 /* DUAL INPUT EXT PROGRAM */
#define SPINOR_OP_WRITE_1_1_4 0x32 /* QUAD INPUT PROGRAM */
#define SPINOR_OP_WRITE_1_4_4 0x12 /* QUAD INPUT EXT PROGRAM */
/* READ commands with 32-bit addressing */
#define FLASH_CMD_READ4 0x13
#define FLASH_CMD_READ4_FAST 0x0c
#define FLASH_CMD_READ4_1_1_2 0x3c
#define FLASH_CMD_READ4_1_2_2 0xbc
#define FLASH_CMD_READ4_1_1_4 0x6c
#define FLASH_CMD_READ4_1_4_4 0xec
#define SPINOR_OP_READ4_1_2_2 0xbc
#define SPINOR_OP_READ4_1_4_4 0xec
/* Configuration flags */
#define FLASH_FLAG_SINGLE 0x000000ff
......
......@@ -280,14 +280,11 @@ __setup("slram=", mtd_slram_setup);
static int __init init_slram(void)
{
char *devname;
int i;
#ifndef MODULE
char *devstart;
char *devlength;
i = 0;
if (!map) {
E("slram: not enough parameters.\n");
return(-EINVAL);
......@@ -314,6 +311,7 @@ static int __init init_slram(void)
}
#else
int count;
int i;
for (count = 0; count < SLRAM_MAX_DEVICES_PARAMS && map[count];
count++) {
......
This diff is collapsed.
menu "LPDDR flash memory drivers"
depends on MTD!=n
menu "LPDDR & LPDDR2 PCM memory drivers"
depends on MTD
config MTD_LPDDR
tristate "Support for LPDDR flash chips"
......@@ -17,4 +17,13 @@ config MTD_QINFO_PROBE
Window QINFO interface, permits software to be used for entire
families of devices. This serves similar purpose of CFI on legacy
Flash products
config MTD_LPDDR2_NVM
# ARM dependency is only for writel_relaxed()
depends on MTD && ARM
tristate "Support for LPDDR2-NVM flash chips"
help
This option enables support of PCM memories with a LPDDR2-NVM
(Low power double data rate 2) interface.
endmenu
......@@ -4,3 +4,4 @@
obj-$(CONFIG_MTD_QINFO_PROBE) += qinfo_probe.o
obj-$(CONFIG_MTD_LPDDR) += lpddr_cmds.o
obj-$(CONFIG_MTD_LPDDR2_NVM) += lpddr2_nvm.o
/*
* LPDDR2-NVM MTD driver. This module provides read, write, erase, lock/unlock
* support for LPDDR2-NVM PCM memories
*
* Copyright © 2012 Micron Technology, Inc.
*
* Vincenzo Aliberti <vincenzo.aliberti@gmail.com>
* Domenico Manna <domenico.manna@gmail.com>
* Many thanks to Andrea Vigilante for initial enabling
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mtd/map.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>
#include <linux/err.h>
/* Parameters */
#define ERASE_BLOCKSIZE (0x00020000/2) /* in Word */
#define WRITE_BUFFSIZE (0x00000400/2) /* in Word */
#define OW_BASE_ADDRESS 0x00000000 /* OW offset */
#define BUS_WIDTH 0x00000020 /* x32 devices */
/* PFOW symbols address offset */
#define PFOW_QUERY_STRING_P (0x0000/2) /* in Word */
#define PFOW_QUERY_STRING_F (0x0002/2) /* in Word */
#define PFOW_QUERY_STRING_O (0x0004/2) /* in Word */
#define PFOW_QUERY_STRING_W (0x0006/2) /* in Word */
/* OW registers address */
#define CMD_CODE_OFS (0x0080/2) /* in Word */
#define CMD_DATA_OFS (0x0084/2) /* in Word */
#define CMD_ADD_L_OFS (0x0088/2) /* in Word */
#define CMD_ADD_H_OFS (0x008A/2) /* in Word */
#define MPR_L_OFS (0x0090/2) /* in Word */
#define MPR_H_OFS (0x0092/2) /* in Word */
#define CMD_EXEC_OFS (0x00C0/2) /* in Word */
#define STATUS_REG_OFS (0x00CC/2) /* in Word */
#define PRG_BUFFER_OFS (0x0010/2) /* in Word */
/* Datamask */
#define MR_CFGMASK 0x8000
#define SR_OK_DATAMASK 0x0080
/* LPDDR2-NVM Commands */
#define LPDDR2_NVM_LOCK 0x0061
#define LPDDR2_NVM_UNLOCK 0x0062
#define LPDDR2_NVM_SW_PROGRAM 0x0041
#define LPDDR2_NVM_SW_OVERWRITE 0x0042
#define LPDDR2_NVM_BUF_PROGRAM 0x00E9
#define LPDDR2_NVM_BUF_OVERWRITE 0x00EA
#define LPDDR2_NVM_ERASE 0x0020
/* LPDDR2-NVM Registers offset */
#define LPDDR2_MODE_REG_DATA 0x0040
#define LPDDR2_MODE_REG_CFG 0x0050
/*
* Internal Type Definitions
* pcm_int_data contains memory controller details:
* @reg_data : LPDDR2_MODE_REG_DATA register address after remapping
* @reg_cfg : LPDDR2_MODE_REG_CFG register address after remapping
* &bus_width: memory bus-width (eg: x16 2 Bytes, x32 4 Bytes)
*/
struct pcm_int_data {
void __iomem *ctl_regs;
int bus_width;
};
static DEFINE_MUTEX(lpdd2_nvm_mutex);
/*
* Build a map_word starting from an u_long
*/
static inline map_word build_map_word(u_long myword)
{
map_word val = { {0} };
val.x[0] = myword;
return val;
}
/*
* Build Mode Register Configuration DataMask based on device bus-width
*/
static inline u_int build_mr_cfgmask(u_int bus_width)
{
u_int val = MR_CFGMASK;
if (bus_width == 0x0004) /* x32 device */
val = val << 16;
return val;
}
/*
* Build Status Register OK DataMask based on device bus-width
*/
static inline u_int build_sr_ok_datamask(u_int bus_width)
{
u_int val = SR_OK_DATAMASK;
if (bus_width == 0x0004) /* x32 device */
val = (val << 16)+val;
return val;
}
/*