mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
This pull request contains minor fixes/improvements on existing drivers:
- sunxi: avoid busy-waiting for NAND events - ifc: fix ECC handling on IFC v1.0 - OX820: add explicit dependency on ARCH_OXNAS in Kconfig - core: add a new manufacture ID and fix a kernel-doc warning - fsmc: kill pdata support - lpc32xx_slc: remove unneeded NULL check -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJYmYygAAoJEGXtNgF+CLcAZkkQAIVXN3IUeCKsqJKNojK9VzPq etYLg+yq4QCRRYkJRqHv9jmr/PqpA2cooNahJZreHTKo3RsD+SCHiHBWb2gsE7co IuVFCIHLyqBMejk/4YCM510UbciLPngk+B8i4EGOlcnke592KEqXFEquIJiokidj +P+Un3l4X7A9dhPQ9sCljAtxwgj3fHaVhaC6wqQBX0+gpIFNbDNaCA2ojG5Pob/F lY/9W75/rn2Hr89Cq1lThyKlIlOZLqdhZ2irawMLAJjLB1LN2X7NFZIvTU/JBm6L 4IMqK0g1/QYmfC6JF3lM3CM6TAQ6FvlaRhuDvL+jKGyJmQueag3Na/vnOPCdacTz RVMoOwsuFjntl7QfJnsspQlJYmAEtN4EIFmuWVpnXtvDRV5nBcbm6+JaOhyP5CTy /cU0GM3lb9Z4vkFIxADffE6Fsn/39Xf36EwI/wr3BmEUre5EAUDZk60x8bfkvV+Y bLOIoS8XHI2U5qLlFYXjOs2d/3CnM1AhKRlE4VV2xSxza1sqaWhbNl5/CUKcU1oB mwjv8Upr2nHbAaQbK+X/TrUTJvTqUzM9jj+d9AC7aEzPlSYroaMqttswMeZFgZZ5 2yDgwufQ30voAzj201GwlZGvYN9FDWDIS9C1fFboanKnc1saQsL2L3PL3aFk6NWv BIlGN/sKxg+XL4akd+aR =GW4L -----END PGP SIGNATURE----- Merge tag 'nand/for-4.11' of github.com:linux-nand/linux From Boris: """ This pull request contains minor fixes/improvements on existing drivers: - sunxi: avoid busy-waiting for NAND events - ifc: fix ECC handling on IFC v1.0 - OX820: add explicit dependency on ARCH_OXNAS in Kconfig - core: add a new manufacture ID and fix a kernel-doc warning - fsmc: kill pdata support - lpc32xx_slc: remove unneeded NULL check """ Conflicts: include/linux/mtd/nand.h [Brian: trivial conflict in the comment section]
This commit is contained in:
commit
9c8d7ff32a
337 changed files with 3490 additions and 2214 deletions
|
|
@ -426,6 +426,7 @@ config MTD_NAND_ORION
|
|||
|
||||
config MTD_NAND_OXNAS
|
||||
tristate "NAND Flash support for Oxford Semiconductor SoC"
|
||||
depends on ARCH_OXNAS || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
This enables the NAND flash controller on Oxford Semiconductor SoCs.
|
||||
|
|
@ -535,6 +536,7 @@ config MTD_NAND_JZ4780
|
|||
|
||||
config MTD_NAND_FSMC
|
||||
tristate "Support for NAND on ST Micros FSMC"
|
||||
depends on OF
|
||||
depends on PLAT_SPEAR || ARCH_NOMADIK || ARCH_U8500 || MACH_U300
|
||||
help
|
||||
Enables support for NAND Flash chips on the ST Microelectronics
|
||||
|
|
|
|||
|
|
@ -258,9 +258,15 @@ static void fsl_ifc_run_command(struct mtd_info *mtd)
|
|||
int bufnum = nctrl->page & priv->bufnum_mask;
|
||||
int sector = bufnum * chip->ecc.steps;
|
||||
int sector_end = sector + chip->ecc.steps - 1;
|
||||
__be32 *eccstat_regs;
|
||||
|
||||
if (ctrl->version >= FSL_IFC_VERSION_2_0_0)
|
||||
eccstat_regs = ifc->ifc_nand.v2_nand_eccstat;
|
||||
else
|
||||
eccstat_regs = ifc->ifc_nand.v1_nand_eccstat;
|
||||
|
||||
for (i = sector / 4; i <= sector_end / 4; i++)
|
||||
eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);
|
||||
eccstat[i] = ifc_in32(&eccstat_regs[i]);
|
||||
|
||||
for (i = sector; i <= sector_end; i++) {
|
||||
errors = check_read_ecc(mtd, ctrl, eccstat, i);
|
||||
|
|
|
|||
|
|
@ -35,10 +35,133 @@
|
|||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mtd/fsmc.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <mtd/mtd-abi.h>
|
||||
|
||||
#define FSMC_NAND_BW8 1
|
||||
#define FSMC_NAND_BW16 2
|
||||
|
||||
#define FSMC_MAX_NOR_BANKS 4
|
||||
#define FSMC_MAX_NAND_BANKS 4
|
||||
|
||||
#define FSMC_FLASH_WIDTH8 1
|
||||
#define FSMC_FLASH_WIDTH16 2
|
||||
|
||||
/* fsmc controller registers for NOR flash */
|
||||
#define CTRL 0x0
|
||||
/* ctrl register definitions */
|
||||
#define BANK_ENABLE (1 << 0)
|
||||
#define MUXED (1 << 1)
|
||||
#define NOR_DEV (2 << 2)
|
||||
#define WIDTH_8 (0 << 4)
|
||||
#define WIDTH_16 (1 << 4)
|
||||
#define RSTPWRDWN (1 << 6)
|
||||
#define WPROT (1 << 7)
|
||||
#define WRT_ENABLE (1 << 12)
|
||||
#define WAIT_ENB (1 << 13)
|
||||
|
||||
#define CTRL_TIM 0x4
|
||||
/* ctrl_tim register definitions */
|
||||
|
||||
#define FSMC_NOR_BANK_SZ 0x8
|
||||
#define FSMC_NOR_REG_SIZE 0x40
|
||||
|
||||
#define FSMC_NOR_REG(base, bank, reg) (base + \
|
||||
FSMC_NOR_BANK_SZ * (bank) + \
|
||||
reg)
|
||||
|
||||
/* fsmc controller registers for NAND flash */
|
||||
#define PC 0x00
|
||||
/* pc register definitions */
|
||||
#define FSMC_RESET (1 << 0)
|
||||
#define FSMC_WAITON (1 << 1)
|
||||
#define FSMC_ENABLE (1 << 2)
|
||||
#define FSMC_DEVTYPE_NAND (1 << 3)
|
||||
#define FSMC_DEVWID_8 (0 << 4)
|
||||
#define FSMC_DEVWID_16 (1 << 4)
|
||||
#define FSMC_ECCEN (1 << 6)
|
||||
#define FSMC_ECCPLEN_512 (0 << 7)
|
||||
#define FSMC_ECCPLEN_256 (1 << 7)
|
||||
#define FSMC_TCLR_1 (1)
|
||||
#define FSMC_TCLR_SHIFT (9)
|
||||
#define FSMC_TCLR_MASK (0xF)
|
||||
#define FSMC_TAR_1 (1)
|
||||
#define FSMC_TAR_SHIFT (13)
|
||||
#define FSMC_TAR_MASK (0xF)
|
||||
#define STS 0x04
|
||||
/* sts register definitions */
|
||||
#define FSMC_CODE_RDY (1 << 15)
|
||||
#define COMM 0x08
|
||||
/* comm register definitions */
|
||||
#define FSMC_TSET_0 0
|
||||
#define FSMC_TSET_SHIFT 0
|
||||
#define FSMC_TSET_MASK 0xFF
|
||||
#define FSMC_TWAIT_6 6
|
||||
#define FSMC_TWAIT_SHIFT 8
|
||||
#define FSMC_TWAIT_MASK 0xFF
|
||||
#define FSMC_THOLD_4 4
|
||||
#define FSMC_THOLD_SHIFT 16
|
||||
#define FSMC_THOLD_MASK 0xFF
|
||||
#define FSMC_THIZ_1 1
|
||||
#define FSMC_THIZ_SHIFT 24
|
||||
#define FSMC_THIZ_MASK 0xFF
|
||||
#define ATTRIB 0x0C
|
||||
#define IOATA 0x10
|
||||
#define ECC1 0x14
|
||||
#define ECC2 0x18
|
||||
#define ECC3 0x1C
|
||||
#define FSMC_NAND_BANK_SZ 0x20
|
||||
|
||||
#define FSMC_NAND_REG(base, bank, reg) (base + FSMC_NOR_REG_SIZE + \
|
||||
(FSMC_NAND_BANK_SZ * (bank)) + \
|
||||
reg)
|
||||
|
||||
#define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ)
|
||||
|
||||
struct fsmc_nand_timings {
|
||||
uint8_t tclr;
|
||||
uint8_t tar;
|
||||
uint8_t thiz;
|
||||
uint8_t thold;
|
||||
uint8_t twait;
|
||||
uint8_t tset;
|
||||
};
|
||||
|
||||
enum access_mode {
|
||||
USE_DMA_ACCESS = 1,
|
||||
USE_WORD_ACCESS,
|
||||
};
|
||||
|
||||
/**
|
||||
* fsmc_nand_platform_data - platform specific NAND controller config
|
||||
* @nand_timings: timing setup for the physical NAND interface
|
||||
* @partitions: partition table for the platform, use a default fallback
|
||||
* if this is NULL
|
||||
* @nr_partitions: the number of partitions in the previous entry
|
||||
* @options: different options for the driver
|
||||
* @width: bus width
|
||||
* @bank: default bank
|
||||
* @select_bank: callback to select a certain bank, this is
|
||||
* platform-specific. If the controller only supports one bank
|
||||
* this may be set to NULL
|
||||
*/
|
||||
struct fsmc_nand_platform_data {
|
||||
struct fsmc_nand_timings *nand_timings;
|
||||
struct mtd_partition *partitions;
|
||||
unsigned int nr_partitions;
|
||||
unsigned int options;
|
||||
unsigned int width;
|
||||
unsigned int bank;
|
||||
|
||||
enum access_mode mode;
|
||||
|
||||
void (*select_bank)(uint32_t bank, uint32_t busw);
|
||||
|
||||
/* priv structures for dma accesses */
|
||||
void *read_dma_priv;
|
||||
void *write_dma_priv;
|
||||
};
|
||||
|
||||
static int fsmc_ecc1_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *oobregion)
|
||||
{
|
||||
|
|
@ -714,7 +837,6 @@ static bool filter(struct dma_chan *chan, void *slave)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
|
||||
struct device_node *np)
|
||||
{
|
||||
|
|
@ -757,13 +879,6 @@ static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
|
||||
struct device_node *np)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* fsmc_nand_probe - Probe function
|
||||
|
|
@ -782,19 +897,15 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
|
|||
u32 pid;
|
||||
int i;
|
||||
|
||||
if (np) {
|
||||
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
pdev->dev.platform_data = pdata;
|
||||
ret = fsmc_nand_probe_config_dt(pdev, np);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "no platform data\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "platform data is NULL\n");
|
||||
return -EINVAL;
|
||||
pdev->dev.platform_data = pdata;
|
||||
ret = fsmc_nand_probe_config_dt(pdev, np);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "no platform data\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Allocate memory for the device structure (and zero it) */
|
||||
|
|
|
|||
|
|
@ -797,22 +797,17 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
|||
struct resource *rc;
|
||||
int res;
|
||||
|
||||
rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (rc == NULL) {
|
||||
dev_err(&pdev->dev, "No memory resource found for device\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Allocate memory for the device structure (and zero it) */
|
||||
host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
host->io_base_dma = rc->start;
|
||||
|
||||
rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
host->io_base = devm_ioremap_resource(&pdev->dev, rc);
|
||||
if (IS_ERR(host->io_base))
|
||||
return PTR_ERR(host->io_base);
|
||||
|
||||
host->io_base_dma = rc->start;
|
||||
if (pdev->dev.of_node)
|
||||
host->ncfg = lpc32xx_parse_dt(&pdev->dev);
|
||||
if (!host->ncfg) {
|
||||
|
|
|
|||
|
|
@ -1383,7 +1383,6 @@ static int mtk_nfc_probe(struct platform_device *pdev)
|
|||
nfc->regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(nfc->regs)) {
|
||||
ret = PTR_ERR(nfc->regs);
|
||||
dev_err(dev, "no nfi base\n");
|
||||
goto release_ecc;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ struct nand_manufacturers nand_manuf_ids[] = {
|
|||
{NAND_MFR_SANDISK, "SanDisk"},
|
||||
{NAND_MFR_INTEL, "Intel"},
|
||||
{NAND_MFR_ATO, "ATO"},
|
||||
{NAND_MFR_WINBOND, "Winbond"},
|
||||
{0x0, "Unknown"}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -321,6 +321,10 @@ static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events,
|
|||
|
||||
ret = wait_for_completion_timeout(&nfc->complete,
|
||||
msecs_to_jiffies(timeout_ms));
|
||||
if (!ret)
|
||||
ret = -ETIMEDOUT;
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
writel(0, nfc->regs + NFC_REG_INT);
|
||||
} else {
|
||||
|
|
@ -518,6 +522,8 @@ static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
u32 tmp;
|
||||
|
||||
while (len > offs) {
|
||||
bool poll = false;
|
||||
|
||||
cnt = min(len - offs, NFC_SRAM_SIZE);
|
||||
|
||||
ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
|
||||
|
|
@ -528,7 +534,11 @@ static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD;
|
||||
writel(tmp, nfc->regs + NFC_REG_CMD);
|
||||
|
||||
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
|
||||
/* Arbitrary limit for polling mode */
|
||||
if (cnt < 64)
|
||||
poll = true;
|
||||
|
||||
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
|
|
@ -551,6 +561,8 @@ static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
|
|||
u32 tmp;
|
||||
|
||||
while (len > offs) {
|
||||
bool poll = false;
|
||||
|
||||
cnt = min(len - offs, NFC_SRAM_SIZE);
|
||||
|
||||
ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
|
||||
|
|
@ -563,7 +575,11 @@ static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
|
|||
NFC_ACCESS_DIR;
|
||||
writel(tmp, nfc->regs + NFC_REG_CMD);
|
||||
|
||||
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
|
||||
/* Arbitrary limit for polling mode */
|
||||
if (cnt < 64)
|
||||
poll = true;
|
||||
|
||||
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
|
|
@ -588,10 +604,6 @@ static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat,
|
|||
struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
|
||||
int ret;
|
||||
|
||||
ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
if (dat == NAND_CMD_NONE && (ctrl & NAND_NCE) &&
|
||||
!(ctrl & (NAND_CLE | NAND_ALE))) {
|
||||
u32 cmd = 0;
|
||||
|
|
@ -621,6 +633,10 @@ static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat,
|
|||
writel(sunxi_nand->addr[1],
|
||||
nfc->regs + NFC_REG_ADDR_HIGH);
|
||||
|
||||
ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
writel(cmd, nfc->regs + NFC_REG_CMD);
|
||||
sunxi_nand->addr[0] = 0;
|
||||
sunxi_nand->addr[1] = 0;
|
||||
|
|
@ -957,7 +973,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
|
|||
writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
|
||||
nfc->regs + NFC_REG_CMD);
|
||||
|
||||
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
|
||||
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
|
||||
sunxi_nfc_randomizer_disable(mtd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -1069,7 +1085,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf,
|
|||
writel(NFC_PAGE_OP | NFC_DATA_SWAP_METHOD | NFC_DATA_TRANS,
|
||||
nfc->regs + NFC_REG_CMD);
|
||||
|
||||
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
|
||||
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
|
||||
if (ret)
|
||||
dmaengine_terminate_all(nfc->dmac);
|
||||
|
||||
|
|
@ -1189,7 +1205,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
|
|||
NFC_ACCESS_DIR | NFC_ECC_OP,
|
||||
nfc->regs + NFC_REG_CMD);
|
||||
|
||||
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
|
||||
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
|
||||
sunxi_nfc_randomizer_disable(mtd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -1428,7 +1444,7 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd,
|
|||
NFC_DATA_TRANS | NFC_ACCESS_DIR,
|
||||
nfc->regs + NFC_REG_CMD);
|
||||
|
||||
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
|
||||
ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
|
||||
if (ret)
|
||||
dmaengine_terminate_all(nfc->dmac);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue