Merge tag 'nand/for-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux into mtd/next
NAND core changes: - use longest matching pattern in ->exec_op() default parser - export NAND operation tracer - add flag to indicate panic_write in MTD - use kzalloc() instead of kmalloc() and memset() Raw NAND controller drivers changes: - brcmnand: * fix BCH ECC layout for large page NAND parts * fallback to detected ecc-strength, ecc-step-size * when oops in progress use pio and interrupt polling * code refactor code to introduce helper functions * add support for v7.3 controller - FSMC: * use nand_op_trace for operation tracing - GPMI: * move all driver code into single file * various cleanups (including dmaengine changes) * use runtime PM to manage clocks * implement exec_op - MTK: * correct low level time calculation of r/w cycle * improve data sampling timing for read cycle * add validity check for CE# pin setting * fix wrongly assigned OOB buffer pointer issue * re-license MTK NAND driver as Dual MIT/GPL - STM32: * manage the get_irq error case * increase DMA completion timeouts Raw NAND chips drivers changes: - Macronix: add read-retry support Onenand driver changes: - add support for 8Gb datasize chips - avoid fall-through warnings SPI-NAND changes: - define macros for page-read ops with three-byte addresses - add support for two-byte device IDs and then for GigaDevice GD5F1GQ4UFxxG - add initial support for Paragon PN26G0xA - handle the case where the last page read has bitflips
This commit is contained in:
+1
-15
@@ -1,23 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright © 2007 Eugene Konev <ejka@openwrt.org>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* TI AR7 flash partition table.
|
||||
* Based on ar7 map by Felix Fietkau <nbd@openwrt.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* BCM63XX CFE image tag parser
|
||||
*
|
||||
@@ -5,21 +6,6 @@
|
||||
* Mike Albon <malbon@openwrt.org>
|
||||
* Copyright © 2009-2010 Daniel Dickinson <openwrt@cshore.neomailbox.net>
|
||||
* Copyright © 2011-2013 Jonas Gorski <jonas.gorski@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
menu "RAM/ROM/Flash chip drivers"
|
||||
depends on MTD!=n
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Registration for chip drivers
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Common code to handle absent "placeholder" devices
|
||||
* Copyright 2001 Resilience Corporation <ebrower@resilience.com>
|
||||
|
||||
@@ -1,23 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Read flash partition table from command line
|
||||
*
|
||||
* Copyright © 2002 SYSGO Real-Time Solutions GmbH
|
||||
* Copyright © 2002-2010 David Woodhouse <dwmw2@infradead.org>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* The format for the command line is as follows:
|
||||
*
|
||||
* mtdparts=<mtddef>[;<mtddef]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
menu "Self-contained MTD device drivers"
|
||||
depends on MTD!=n
|
||||
depends on HAS_IOMEM
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@@ -1,22 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Handles the M-Systems DiskOnChip G3 chip
|
||||
*
|
||||
* Copyright (C) 2011 Robert Jarzmik
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
@@ -1,22 +1,8 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Handles the M-Systems DiskOnChip G3 chip
|
||||
*
|
||||
* Copyright (C) 2011 Robert Jarzmik
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _MTD_DOCG3_H
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2001 Maciej W. Rozycki
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2001, 2003 Maciej W. Rozycki
|
||||
*
|
||||
* DEC MS02-NV (54-20948-01) battery backed-up NVRAM module for
|
||||
* DECstation/DECsystem 5000/2x0 and DECsystem 5900 and 5900/260
|
||||
* systems.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/ioport.h>
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Atmel AT45xxx DataFlash MTD driver for lightweight SPI framework
|
||||
*
|
||||
* Largely derived from at91_dataflash.c:
|
||||
* Copyright (C) 2003-2005 SAN People (Pty) Ltd
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/**
|
||||
* Copyright (c) ???? Jochen Schäuble <psionic@psionic.de>
|
||||
* Copyright (c) 2003-2004 Joern Engel <joern@wh.fh-wedel.de>
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* OPAL PNOR flash MTD abstraction
|
||||
*
|
||||
* Copyright IBM 2015
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*======================================================================
|
||||
|
||||
This driver provides a method to access memory not used by the kernel
|
||||
|
||||
+1
-14
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL)
|
||||
*
|
||||
@@ -6,20 +7,6 @@
|
||||
* Based heavily on the nftlcore.c code which is:
|
||||
* Copyright © 1999 Machine Vision Holdings, Inc.
|
||||
* Copyright © 1999 David Woodhouse <dwmw2@infradead.org>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* inftlmount.c -- INFTL mount code with extensive checks.
|
||||
*
|
||||
@@ -7,20 +8,6 @@
|
||||
* Based heavily on the nftlmount.c code which is:
|
||||
* Author: Fabrice Bellard (fabrice.bellard@netgem.com)
|
||||
* Copyright © 2000 Netgem S.A.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
menu "LPDDR & LPDDR2 PCM memory drivers"
|
||||
depends on MTD
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# linux/drivers/mtd/lpddr/Makefile
|
||||
#
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* LPDDR2-NVM MTD driver. This module provides read, write, erase, lock/unlock
|
||||
* support for LPDDR2-NVM PCM memories
|
||||
@@ -7,16 +8,6 @@
|
||||
* 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__
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* LPDDR flash memory device operations. This module provides read, write,
|
||||
* erase, lock/unlock support for LPDDR flash memories
|
||||
@@ -5,20 +6,6 @@
|
||||
* (C) 2008 Vasiliy Leonenko <vasiliy.leonenko@gmail.com>
|
||||
* Many thanks to Roman Borisov 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
* TODO:
|
||||
* Implement VPP management
|
||||
* Implement XIP support
|
||||
|
||||
@@ -1,22 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Probing flash chips with QINFO records.
|
||||
* (C) 2008 Korolev Alexey <akorolev@infradead.org>
|
||||
* (C) 2008 Vasiliy Leonenko <vasiliy.leonenko@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
menu "Mapping drivers for chip access"
|
||||
depends on MTD!=n
|
||||
depends on HAS_IOMEM
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* amd76xrom.c
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* ck804xrom.c
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* esb2rom.c
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* ichxrom.c
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* drivers/mtd/maps/ixp4xx.c
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* BIOS Flash chip on Intel 440GX board.
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Out-of-line map I/O functions for simple maps when CONFIG_COMPLEX_MAPPINGS
|
||||
* is enabled.
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/* netsc520.c -- MTD map driver for AMD NetSc520 Demonstration Board
|
||||
*
|
||||
* Copyright (C) 2001 Mark Langsdorf (mark.langsdorf@amd.com)
|
||||
* based on sc520cdp.c by Sysgo Real-Time Solutions GmbH
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* The NetSc520 is a demonstration board for the Elan Sc520 processor available
|
||||
* from AMD. It has a single back of 16 megs of 32-bit Flash ROM and another
|
||||
* 16 megs of SDRAM.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,23 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Versatile OF physmap driver add-on
|
||||
*
|
||||
* Copyright (c) 2016, Linaro Limited
|
||||
* Author: Linus Walleij <linus.walleij@linaro.org>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
#include <linux/export.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* PISMO memory driver - http://www.pismoworld.org/
|
||||
*
|
||||
* For ARM Realview and Versatile platforms
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/* drivers/mtd/maps/plat-ram.c
|
||||
*
|
||||
* (c) 2004-2005 Simtec Electronics
|
||||
@@ -5,20 +6,6 @@
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* Generic platform device based RAM map
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Flash memory access on SA11x0 based devices
|
||||
*
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/* sbc_gxx.c -- MTD map driver for Arcom Control Systems SBC-MediaGX,
|
||||
SBC-GXm and SBC-GX1 series boards.
|
||||
|
||||
Copyright (C) 2001 Arcom Control System Ltd
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
The SBC-MediaGX / SBC-GXx has up to 16 MiB of
|
||||
Intel StrataFlash (28F320/28F640) in x8 mode.
|
||||
|
||||
@@ -1,22 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/* sc520cdp.c -- MTD map driver for AMD SC520 Customer Development Platform
|
||||
*
|
||||
* Copyright (C) 2001 Sysgo Real-Time Solutions GmbH
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
*
|
||||
* The SC520CDP is an evaluation board for the Elan SC520 processor available
|
||||
* from AMD. It has two banks of 32-bit Flash ROM, each 8 Megabytes in size,
|
||||
* and up to 512 KiB of 8-bit DIL Flash ROM.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* MTD map driver for BIOS Flash on Intel SCB2 boards
|
||||
* Copyright (C) 2002 Sun Microsystems, Inc.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* linux/drivers/mtd/maps/scx200_docflash.c
|
||||
|
||||
Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* sun_uflash.c - Driver for user-programmable flash on
|
||||
* Sun Microsystems SME boardsets.
|
||||
*
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* ts5500_flash.c -- MTD map driver for Technology Systems TS-5500 board
|
||||
*
|
||||
* Copyright (C) 2004 Sean Young <sean@mess.org>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* Note:
|
||||
* - In order for detection to work, jumper 3 must be set.
|
||||
* - Drive A and B use the resident flash disk (RFD) flash translation layer.
|
||||
|
||||
@@ -1,22 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Interface to Linux block layer for MTD 'translation layers'.
|
||||
*
|
||||
* Copyright © 2003-2010 David Woodhouse <dwmw2@infradead.org>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
+1
-15
@@ -1,23 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Direct MTD block device access
|
||||
*
|
||||
* Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
|
||||
* Copyright © 2000-2003 Nicolas Pitre <nico@fluxnic.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
|
||||
@@ -1,22 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Simple read-only (writable only for RAM) mtdblock driver
|
||||
*
|
||||
* Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
||||
+1
-15
@@ -1,20 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
|
||||
+1
-15
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* MTD device concatenation layer
|
||||
*
|
||||
@@ -5,21 +6,6 @@
|
||||
* Copyright © 2002-2010 David Woodhouse <dwmw2@infradead.org>
|
||||
*
|
||||
* NAND support by Christian Gan <cgan@iders.ca>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
+4
-15
@@ -1,24 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Core registration and callback routines for MTD
|
||||
* drivers and users.
|
||||
*
|
||||
* Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
|
||||
* Copyright © 2006 Red Hat UK Limited
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@@ -1138,6 +1124,9 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
|
||||
return -EROFS;
|
||||
if (!len)
|
||||
return 0;
|
||||
if (!mtd->oops_panic_write)
|
||||
mtd->oops_panic_write = true;
|
||||
|
||||
return mtd->_panic_write(mtd, to, len, retlen, buf);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtd_panic_write);
|
||||
|
||||
+1
-15
@@ -1,24 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Simple MTD partitioning layer
|
||||
*
|
||||
* Copyright © 2000 Nicolas Pitre <nico@fluxnic.net>
|
||||
* Copyright © 2002 Thomas Gleixner <gleixner@linutronix.de>
|
||||
* Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/* MTD-based superblock management
|
||||
*
|
||||
* Copyright © 2001-2007 Red Hat, Inc. All Rights Reserved.
|
||||
@@ -5,11 +6,6 @@
|
||||
*
|
||||
* Written by: David Howells <dhowells@redhat.com>
|
||||
* David Woodhouse <dwmw2@infradead.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/mtd/super.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config MTD_NAND_CORE
|
||||
tristate
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
menuconfig MTD_ONENAND
|
||||
tristate "OneNAND Device Support"
|
||||
depends on MTD
|
||||
|
||||
@@ -3260,6 +3260,8 @@ static void onenand_check_features(struct mtd_info *mtd)
|
||||
|
||||
/* Lock scheme */
|
||||
switch (density) {
|
||||
case ONENAND_DEVICE_DENSITY_8Gb:
|
||||
this->options |= ONENAND_HAS_NOP_1;
|
||||
case ONENAND_DEVICE_DENSITY_4Gb:
|
||||
if (ONENAND_IS_DDP(this))
|
||||
this->options |= ONENAND_HAS_2PLANE;
|
||||
@@ -3280,12 +3282,15 @@ static void onenand_check_features(struct mtd_info *mtd)
|
||||
if ((this->version_id & 0xf) == 0xe)
|
||||
this->options |= ONENAND_HAS_NOP_1;
|
||||
}
|
||||
this->options |= ONENAND_HAS_UNLOCK_ALL;
|
||||
break;
|
||||
|
||||
case ONENAND_DEVICE_DENSITY_2Gb:
|
||||
/* 2Gb DDP does not have 2 plane */
|
||||
if (!ONENAND_IS_DDP(this))
|
||||
this->options |= ONENAND_HAS_2PLANE;
|
||||
this->options |= ONENAND_HAS_UNLOCK_ALL;
|
||||
break;
|
||||
|
||||
case ONENAND_DEVICE_DENSITY_1Gb:
|
||||
/* A-Die has all block unlock */
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config MTD_NAND_ECC_SW_HAMMING
|
||||
tristate
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_MTD_NAND_ATMEL) += atmel-nand-controller.o atmel-pmecc.o
|
||||
|
||||
atmel-nand-controller-objs := nand-controller.o
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
bcm47xxnflash-y += main.o
|
||||
bcm47xxnflash-y += ops_bcm4706.o
|
||||
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright © 2015 Broadcom Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright 2015 Simon Arlott
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Derived from bcm63138_nand.c:
|
||||
* Copyright © 2015 Broadcom Corporation
|
||||
*
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright © 2010-2015 Broadcom Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
@@ -92,6 +84,12 @@ struct brcm_nand_dma_desc {
|
||||
#define FLASH_DMA_ECC_ERROR (1 << 8)
|
||||
#define FLASH_DMA_CORR_ERROR (1 << 9)
|
||||
|
||||
/* Bitfields for DMA_MODE */
|
||||
#define FLASH_DMA_MODE_STOP_ON_ERROR BIT(1) /* stop in Uncorr ECC error */
|
||||
#define FLASH_DMA_MODE_MODE BIT(0) /* link list */
|
||||
#define FLASH_DMA_MODE_MASK (FLASH_DMA_MODE_STOP_ON_ERROR | \
|
||||
FLASH_DMA_MODE_MODE)
|
||||
|
||||
/* 512B flash cache in the NAND controller HW */
|
||||
#define FC_SHIFT 9U
|
||||
#define FC_BYTES 512U
|
||||
@@ -104,6 +102,51 @@ struct brcm_nand_dma_desc {
|
||||
#define NAND_CTRL_RDY (INTFC_CTLR_READY | INTFC_FLASH_READY)
|
||||
#define NAND_POLL_STATUS_TIMEOUT_MS 100
|
||||
|
||||
/* flash_dma registers */
|
||||
enum flash_dma_reg {
|
||||
FLASH_DMA_REVISION = 0,
|
||||
FLASH_DMA_FIRST_DESC,
|
||||
FLASH_DMA_FIRST_DESC_EXT,
|
||||
FLASH_DMA_CTRL,
|
||||
FLASH_DMA_MODE,
|
||||
FLASH_DMA_STATUS,
|
||||
FLASH_DMA_INTERRUPT_DESC,
|
||||
FLASH_DMA_INTERRUPT_DESC_EXT,
|
||||
FLASH_DMA_ERROR_STATUS,
|
||||
FLASH_DMA_CURRENT_DESC,
|
||||
FLASH_DMA_CURRENT_DESC_EXT,
|
||||
};
|
||||
|
||||
/* flash_dma registers v1*/
|
||||
static const u16 flash_dma_regs_v1[] = {
|
||||
[FLASH_DMA_REVISION] = 0x00,
|
||||
[FLASH_DMA_FIRST_DESC] = 0x04,
|
||||
[FLASH_DMA_FIRST_DESC_EXT] = 0x08,
|
||||
[FLASH_DMA_CTRL] = 0x0c,
|
||||
[FLASH_DMA_MODE] = 0x10,
|
||||
[FLASH_DMA_STATUS] = 0x14,
|
||||
[FLASH_DMA_INTERRUPT_DESC] = 0x18,
|
||||
[FLASH_DMA_INTERRUPT_DESC_EXT] = 0x1c,
|
||||
[FLASH_DMA_ERROR_STATUS] = 0x20,
|
||||
[FLASH_DMA_CURRENT_DESC] = 0x24,
|
||||
[FLASH_DMA_CURRENT_DESC_EXT] = 0x28,
|
||||
};
|
||||
|
||||
/* flash_dma registers v4 */
|
||||
static const u16 flash_dma_regs_v4[] = {
|
||||
[FLASH_DMA_REVISION] = 0x00,
|
||||
[FLASH_DMA_FIRST_DESC] = 0x08,
|
||||
[FLASH_DMA_FIRST_DESC_EXT] = 0x0c,
|
||||
[FLASH_DMA_CTRL] = 0x10,
|
||||
[FLASH_DMA_MODE] = 0x14,
|
||||
[FLASH_DMA_STATUS] = 0x18,
|
||||
[FLASH_DMA_INTERRUPT_DESC] = 0x20,
|
||||
[FLASH_DMA_INTERRUPT_DESC_EXT] = 0x24,
|
||||
[FLASH_DMA_ERROR_STATUS] = 0x28,
|
||||
[FLASH_DMA_CURRENT_DESC] = 0x30,
|
||||
[FLASH_DMA_CURRENT_DESC_EXT] = 0x34,
|
||||
};
|
||||
|
||||
/* Controller feature flags */
|
||||
enum {
|
||||
BRCMNAND_HAS_1K_SECTORS = BIT(0),
|
||||
@@ -136,6 +179,8 @@ struct brcmnand_controller {
|
||||
/* List of NAND hosts (one for each chip-select) */
|
||||
struct list_head host_list;
|
||||
|
||||
/* flash_dma reg */
|
||||
const u16 *flash_dma_offsets;
|
||||
struct brcm_nand_dma_desc *dma_desc;
|
||||
dma_addr_t dma_pa;
|
||||
|
||||
@@ -159,6 +204,7 @@ struct brcmnand_controller {
|
||||
u32 nand_cs_nand_xor;
|
||||
u32 corr_stat_threshold;
|
||||
u32 flash_dma_mode;
|
||||
bool pio_poll_mode;
|
||||
};
|
||||
|
||||
struct brcmnand_cfg {
|
||||
@@ -470,7 +516,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
|
||||
/* Register offsets */
|
||||
if (ctrl->nand_version >= 0x0702)
|
||||
ctrl->reg_offsets = brcmnand_regs_v72;
|
||||
else if (ctrl->nand_version >= 0x0701)
|
||||
else if (ctrl->nand_version == 0x0701)
|
||||
ctrl->reg_offsets = brcmnand_regs_v71;
|
||||
else if (ctrl->nand_version >= 0x0600)
|
||||
ctrl->reg_offsets = brcmnand_regs_v60;
|
||||
@@ -515,7 +561,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
|
||||
}
|
||||
|
||||
/* Maximum spare area sector size (per 512B) */
|
||||
if (ctrl->nand_version >= 0x0702)
|
||||
if (ctrl->nand_version == 0x0702)
|
||||
ctrl->max_oob = 128;
|
||||
else if (ctrl->nand_version >= 0x0600)
|
||||
ctrl->max_oob = 64;
|
||||
@@ -546,6 +592,15 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void brcmnand_flash_dma_revision_init(struct brcmnand_controller *ctrl)
|
||||
{
|
||||
/* flash_dma register offsets */
|
||||
if (ctrl->nand_version >= 0x0703)
|
||||
ctrl->flash_dma_offsets = flash_dma_regs_v4;
|
||||
else
|
||||
ctrl->flash_dma_offsets = flash_dma_regs_v1;
|
||||
}
|
||||
|
||||
static inline u32 brcmnand_read_reg(struct brcmnand_controller *ctrl,
|
||||
enum brcmnand_reg reg)
|
||||
{
|
||||
@@ -588,6 +643,54 @@ static inline void brcmnand_write_fc(struct brcmnand_controller *ctrl,
|
||||
__raw_writel(val, ctrl->nand_fc + word * 4);
|
||||
}
|
||||
|
||||
static void brcmnand_clear_ecc_addr(struct brcmnand_controller *ctrl)
|
||||
{
|
||||
|
||||
/* Clear error addresses */
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0);
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0);
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_EXT_ADDR, 0);
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_CORR_EXT_ADDR, 0);
|
||||
}
|
||||
|
||||
static u64 brcmnand_get_uncorrecc_addr(struct brcmnand_controller *ctrl)
|
||||
{
|
||||
u64 err_addr;
|
||||
|
||||
err_addr = brcmnand_read_reg(ctrl, BRCMNAND_UNCORR_ADDR);
|
||||
err_addr |= ((u64)(brcmnand_read_reg(ctrl,
|
||||
BRCMNAND_UNCORR_EXT_ADDR)
|
||||
& 0xffff) << 32);
|
||||
|
||||
return err_addr;
|
||||
}
|
||||
|
||||
static u64 brcmnand_get_correcc_addr(struct brcmnand_controller *ctrl)
|
||||
{
|
||||
u64 err_addr;
|
||||
|
||||
err_addr = brcmnand_read_reg(ctrl, BRCMNAND_CORR_ADDR);
|
||||
err_addr |= ((u64)(brcmnand_read_reg(ctrl,
|
||||
BRCMNAND_CORR_EXT_ADDR)
|
||||
& 0xffff) << 32);
|
||||
|
||||
return err_addr;
|
||||
}
|
||||
|
||||
static void brcmnand_set_cmd_addr(struct mtd_info *mtd, u64 addr)
|
||||
{
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
|
||||
(host->cs << 16) | ((addr >> 32) & 0xffff));
|
||||
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
|
||||
lower_32_bits(addr));
|
||||
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
|
||||
}
|
||||
|
||||
static inline u16 brcmnand_cs_offset(struct brcmnand_controller *ctrl, int cs,
|
||||
enum brcmnand_cs_reg reg)
|
||||
{
|
||||
@@ -620,7 +723,7 @@ static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val)
|
||||
enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD;
|
||||
int cs = host->cs;
|
||||
|
||||
if (ctrl->nand_version >= 0x0702)
|
||||
if (ctrl->nand_version == 0x0702)
|
||||
bits = 7;
|
||||
else if (ctrl->nand_version >= 0x0600)
|
||||
bits = 6;
|
||||
@@ -674,7 +777,7 @@ enum {
|
||||
|
||||
static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl)
|
||||
{
|
||||
if (ctrl->nand_version >= 0x0702)
|
||||
if (ctrl->nand_version == 0x0702)
|
||||
return GENMASK(7, 0);
|
||||
else if (ctrl->nand_version >= 0x0600)
|
||||
return GENMASK(6, 0);
|
||||
@@ -804,39 +907,44 @@ static inline void brcmnand_set_wp(struct brcmnand_controller *ctrl, bool en)
|
||||
* Flash DMA
|
||||
***********************************************************************/
|
||||
|
||||
enum flash_dma_reg {
|
||||
FLASH_DMA_REVISION = 0x00,
|
||||
FLASH_DMA_FIRST_DESC = 0x04,
|
||||
FLASH_DMA_FIRST_DESC_EXT = 0x08,
|
||||
FLASH_DMA_CTRL = 0x0c,
|
||||
FLASH_DMA_MODE = 0x10,
|
||||
FLASH_DMA_STATUS = 0x14,
|
||||
FLASH_DMA_INTERRUPT_DESC = 0x18,
|
||||
FLASH_DMA_INTERRUPT_DESC_EXT = 0x1c,
|
||||
FLASH_DMA_ERROR_STATUS = 0x20,
|
||||
FLASH_DMA_CURRENT_DESC = 0x24,
|
||||
FLASH_DMA_CURRENT_DESC_EXT = 0x28,
|
||||
};
|
||||
|
||||
static inline bool has_flash_dma(struct brcmnand_controller *ctrl)
|
||||
{
|
||||
return ctrl->flash_dma_base;
|
||||
}
|
||||
|
||||
static inline void disable_ctrl_irqs(struct brcmnand_controller *ctrl)
|
||||
{
|
||||
if (ctrl->pio_poll_mode)
|
||||
return;
|
||||
|
||||
if (has_flash_dma(ctrl)) {
|
||||
ctrl->flash_dma_base = 0;
|
||||
disable_irq(ctrl->dma_irq);
|
||||
}
|
||||
|
||||
disable_irq(ctrl->irq);
|
||||
ctrl->pio_poll_mode = true;
|
||||
}
|
||||
|
||||
static inline bool flash_dma_buf_ok(const void *buf)
|
||||
{
|
||||
return buf && !is_vmalloc_addr(buf) &&
|
||||
likely(IS_ALIGNED((uintptr_t)buf, 4));
|
||||
}
|
||||
|
||||
static inline void flash_dma_writel(struct brcmnand_controller *ctrl, u8 offs,
|
||||
u32 val)
|
||||
static inline void flash_dma_writel(struct brcmnand_controller *ctrl,
|
||||
enum flash_dma_reg dma_reg, u32 val)
|
||||
{
|
||||
u16 offs = ctrl->flash_dma_offsets[dma_reg];
|
||||
|
||||
brcmnand_writel(val, ctrl->flash_dma_base + offs);
|
||||
}
|
||||
|
||||
static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl, u8 offs)
|
||||
static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl,
|
||||
enum flash_dma_reg dma_reg)
|
||||
{
|
||||
u16 offs = ctrl->flash_dma_offsets[dma_reg];
|
||||
|
||||
return brcmnand_readl(ctrl->flash_dma_base + offs);
|
||||
}
|
||||
|
||||
@@ -939,7 +1047,7 @@ static int brcmnand_bch_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
if (section >= sectors)
|
||||
return -ERANGE;
|
||||
|
||||
oobregion->offset = (section * (sas + 1)) - chip->ecc.bytes;
|
||||
oobregion->offset = ((section + 1) * sas) - chip->ecc.bytes;
|
||||
oobregion->length = chip->ecc.bytes;
|
||||
|
||||
return 0;
|
||||
@@ -1213,9 +1321,12 @@ static void brcmnand_send_cmd(struct brcmnand_host *host, int cmd)
|
||||
{
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
int ret;
|
||||
u64 cmd_addr;
|
||||
|
||||
cmd_addr = brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
|
||||
|
||||
dev_dbg(ctrl->dev, "send native cmd %d addr 0x%llx\n", cmd, cmd_addr);
|
||||
|
||||
dev_dbg(ctrl->dev, "send native cmd %d addr_lo 0x%x\n", cmd,
|
||||
brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS));
|
||||
BUG_ON(ctrl->cmd_pending != 0);
|
||||
ctrl->cmd_pending = cmd;
|
||||
|
||||
@@ -1237,15 +1348,42 @@ static void brcmnand_cmd_ctrl(struct nand_chip *chip, int dat,
|
||||
/* intentionally left blank */
|
||||
}
|
||||
|
||||
static bool brcmstb_nand_wait_for_completion(struct nand_chip *chip)
|
||||
{
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
bool err = false;
|
||||
int sts;
|
||||
|
||||
if (mtd->oops_panic_write) {
|
||||
/* switch to interrupt polling and PIO mode */
|
||||
disable_ctrl_irqs(ctrl);
|
||||
sts = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY,
|
||||
NAND_CTRL_RDY, 0);
|
||||
err = (sts < 0) ? true : false;
|
||||
} else {
|
||||
unsigned long timeo = msecs_to_jiffies(
|
||||
NAND_POLL_STATUS_TIMEOUT_MS);
|
||||
/* wait for completion interrupt */
|
||||
sts = wait_for_completion_timeout(&ctrl->done, timeo);
|
||||
err = (sts <= 0) ? true : false;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int brcmnand_waitfunc(struct nand_chip *chip)
|
||||
{
|
||||
struct brcmnand_host *host = nand_get_controller_data(chip);
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
unsigned long timeo = msecs_to_jiffies(100);
|
||||
bool err = false;
|
||||
|
||||
dev_dbg(ctrl->dev, "wait on native cmd %d\n", ctrl->cmd_pending);
|
||||
if (ctrl->cmd_pending &&
|
||||
wait_for_completion_timeout(&ctrl->done, timeo) <= 0) {
|
||||
if (ctrl->cmd_pending)
|
||||
err = brcmstb_nand_wait_for_completion(chip);
|
||||
|
||||
if (err) {
|
||||
u32 cmd = brcmnand_read_reg(ctrl, BRCMNAND_CMD_START)
|
||||
>> brcmnand_cmd_shift(ctrl);
|
||||
|
||||
@@ -1374,12 +1512,7 @@ static void brcmnand_cmdfunc(struct nand_chip *chip, unsigned command,
|
||||
if (!native_cmd)
|
||||
return;
|
||||
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
|
||||
(host->cs << 16) | ((addr >> 32) & 0xffff));
|
||||
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS, lower_32_bits(addr));
|
||||
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
|
||||
|
||||
brcmnand_set_cmd_addr(mtd, addr);
|
||||
brcmnand_send_cmd(host, native_cmd);
|
||||
brcmnand_waitfunc(chip);
|
||||
|
||||
@@ -1597,20 +1730,10 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
struct brcmnand_controller *ctrl = host->ctrl;
|
||||
int i, j, ret = 0;
|
||||
|
||||
/* Clear error addresses */
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0);
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0);
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_EXT_ADDR, 0);
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_CORR_EXT_ADDR, 0);
|
||||
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
|
||||
(host->cs << 16) | ((addr >> 32) & 0xffff));
|
||||
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
|
||||
brcmnand_clear_ecc_addr(ctrl);
|
||||
|
||||
for (i = 0; i < trans; i++, addr += FC_BYTES) {
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
|
||||
lower_32_bits(addr));
|
||||
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
|
||||
brcmnand_set_cmd_addr(mtd, addr);
|
||||
/* SPARE_AREA_READ does not use ECC, so just use PAGE_READ */
|
||||
brcmnand_send_cmd(host, CMD_PAGE_READ);
|
||||
brcmnand_waitfunc(chip);
|
||||
@@ -1630,21 +1753,15 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
host->hwcfg.sector_size_1k);
|
||||
|
||||
if (!ret) {
|
||||
*err_addr = brcmnand_read_reg(ctrl,
|
||||
BRCMNAND_UNCORR_ADDR) |
|
||||
((u64)(brcmnand_read_reg(ctrl,
|
||||
BRCMNAND_UNCORR_EXT_ADDR)
|
||||
& 0xffff) << 32);
|
||||
*err_addr = brcmnand_get_uncorrecc_addr(ctrl);
|
||||
|
||||
if (*err_addr)
|
||||
ret = -EBADMSG;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
*err_addr = brcmnand_read_reg(ctrl,
|
||||
BRCMNAND_CORR_ADDR) |
|
||||
((u64)(brcmnand_read_reg(ctrl,
|
||||
BRCMNAND_CORR_EXT_ADDR)
|
||||
& 0xffff) << 32);
|
||||
*err_addr = brcmnand_get_correcc_addr(ctrl);
|
||||
|
||||
if (*err_addr)
|
||||
ret = -EUCLEAN;
|
||||
}
|
||||
@@ -1711,7 +1828,7 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
dev_dbg(ctrl->dev, "read %llx -> %p\n", (unsigned long long)addr, buf);
|
||||
|
||||
try_dmaread:
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_COUNT, 0);
|
||||
brcmnand_clear_ecc_addr(ctrl);
|
||||
|
||||
if (has_flash_dma(ctrl) && !oob && flash_dma_buf_ok(buf)) {
|
||||
err = brcmnand_dma_trans(host, addr, buf, trans * FC_BYTES,
|
||||
@@ -1858,15 +1975,9 @@ static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
goto out;
|
||||
}
|
||||
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
|
||||
(host->cs << 16) | ((addr >> 32) & 0xffff));
|
||||
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
|
||||
|
||||
for (i = 0; i < trans; i++, addr += FC_BYTES) {
|
||||
/* full address MUST be set before populating FC */
|
||||
brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
|
||||
lower_32_bits(addr));
|
||||
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
|
||||
brcmnand_set_cmd_addr(mtd, addr);
|
||||
|
||||
if (buf) {
|
||||
brcmnand_soc_data_bus_prepare(ctrl->soc, false);
|
||||
@@ -2144,6 +2255,17 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (chip->ecc.mode != NAND_ECC_NONE &&
|
||||
(!chip->ecc.size || !chip->ecc.strength)) {
|
||||
if (chip->base.eccreq.step_size && chip->base.eccreq.strength) {
|
||||
/* use detected ECC parameters */
|
||||
chip->ecc.size = chip->base.eccreq.step_size;
|
||||
chip->ecc.strength = chip->base.eccreq.strength;
|
||||
dev_info(ctrl->dev, "Using ECC step-size %d, strength %d\n",
|
||||
chip->ecc.size, chip->ecc.strength);
|
||||
}
|
||||
}
|
||||
|
||||
switch (chip->ecc.size) {
|
||||
case 512:
|
||||
if (chip->ecc.algo == NAND_ECC_HAMMING)
|
||||
@@ -2403,6 +2525,7 @@ static const struct of_device_id brcmnand_of_match[] = {
|
||||
{ .compatible = "brcm,brcmnand-v7.0" },
|
||||
{ .compatible = "brcm,brcmnand-v7.1" },
|
||||
{ .compatible = "brcm,brcmnand-v7.2" },
|
||||
{ .compatible = "brcm,brcmnand-v7.3" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, brcmnand_of_match);
|
||||
@@ -2489,7 +2612,11 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
|
||||
goto err;
|
||||
}
|
||||
|
||||
flash_dma_writel(ctrl, FLASH_DMA_MODE, 1); /* linked-list */
|
||||
/* initialize the dma version */
|
||||
brcmnand_flash_dma_revision_init(ctrl);
|
||||
|
||||
/* linked-list and stop on error */
|
||||
flash_dma_writel(ctrl, FLASH_DMA_MODE, FLASH_DMA_MODE_MASK);
|
||||
flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0);
|
||||
|
||||
/* Allocate descriptor(s) */
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright © 2015 Broadcom Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __BRCMNAND_H__
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright © 2015 Broadcom Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright © 2015 Broadcom Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Driver for One Laptop Per Child ‘CAFÉ’ controller, aka Marvell 88ALP01
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* davinci_nand.c - NAND Flash Driver for DaVinci family chips
|
||||
*
|
||||
@@ -7,20 +8,6 @@
|
||||
* Sander Huijsen <Shuijsen@optelecom-nkf.com>
|
||||
* Troy Kisky <troy.kisky@boundarydevices.com>
|
||||
* Dirk Behme <Dirk.Behme@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* (C) 2003 Red Hat, Inc.
|
||||
* (C) 2004 Dan Brown <dan_brown@ieee.org>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/* Freescale Enhanced Local Bus Controller NAND driver
|
||||
*
|
||||
* Copyright © 2006-2007, 2010 Freescale Semiconductor
|
||||
@@ -6,20 +7,6 @@
|
||||
* Scott Wood <scottwood@freescale.com>
|
||||
* Jack Lan <jack.lan@freescale.com>
|
||||
* Roy Zang <tie-fei.zang@freescale.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
@@ -1,23 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Freescale Integrated Flash Controller NAND driver
|
||||
*
|
||||
* Copyright 2011-2012 Freescale Semiconductor, Inc
|
||||
*
|
||||
* Author: Dipen Dudhat <Dipen.Dudhat@freescale.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Freescale UPM NAND driver.
|
||||
*
|
||||
* Copyright © 2007-2008 MontaVista Software, Inc.
|
||||
*
|
||||
* Author: Anton Vorontsov <avorontsov@ru.mvista.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
@@ -613,28 +613,20 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
|
||||
for (op_id = 0; op_id < op->ninstrs; op_id++) {
|
||||
instr = &op->instrs[op_id];
|
||||
|
||||
nand_op_trace(" ", instr);
|
||||
|
||||
switch (instr->type) {
|
||||
case NAND_OP_CMD_INSTR:
|
||||
pr_debug(" ->CMD [0x%02x]\n",
|
||||
instr->ctx.cmd.opcode);
|
||||
|
||||
writeb_relaxed(instr->ctx.cmd.opcode, host->cmd_va);
|
||||
break;
|
||||
|
||||
case NAND_OP_ADDR_INSTR:
|
||||
pr_debug(" ->ADDR [%d cyc]",
|
||||
instr->ctx.addr.naddrs);
|
||||
|
||||
for (i = 0; i < instr->ctx.addr.naddrs; i++)
|
||||
writeb_relaxed(instr->ctx.addr.addrs[i],
|
||||
host->addr_va);
|
||||
break;
|
||||
|
||||
case NAND_OP_DATA_IN_INSTR:
|
||||
pr_debug(" ->DATA_IN [%d B%s]\n", instr->ctx.data.len,
|
||||
instr->ctx.data.force_8bit ?
|
||||
", force 8-bit" : "");
|
||||
|
||||
if (host->mode == USE_DMA_ACCESS)
|
||||
fsmc_read_buf_dma(host, instr->ctx.data.buf.in,
|
||||
instr->ctx.data.len);
|
||||
@@ -644,10 +636,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
|
||||
break;
|
||||
|
||||
case NAND_OP_DATA_OUT_INSTR:
|
||||
pr_debug(" ->DATA_OUT [%d B%s]\n", instr->ctx.data.len,
|
||||
instr->ctx.data.force_8bit ?
|
||||
", force 8-bit" : "");
|
||||
|
||||
if (host->mode == USE_DMA_ACCESS)
|
||||
fsmc_write_buf_dma(host,
|
||||
instr->ctx.data.buf.out,
|
||||
@@ -658,9 +646,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
|
||||
break;
|
||||
|
||||
case NAND_OP_WAITRDY_INSTR:
|
||||
pr_debug(" ->WAITRDY [max %d ms]\n",
|
||||
instr->ctx.waitrdy.timeout_ms);
|
||||
|
||||
ret = nand_soft_waitrdy(chip,
|
||||
instr->ctx.waitrdy.timeout_ms);
|
||||
break;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi_nand.o
|
||||
gpmi_nand-objs += gpmi-nand.o
|
||||
gpmi_nand-objs += gpmi-lib.o
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Freescale GPMI NAND Flash Driver
|
||||
*
|
||||
* Copyright 2008-2011 Freescale Semiconductor, Inc.
|
||||
* Copyright 2008 Embedded Alley Solutions, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef __GPMI_NAND_BCH_REGS_H
|
||||
#define __GPMI_NAND_BCH_REGS_H
|
||||
|
||||
@@ -1,934 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Freescale GPMI NAND Flash Driver
|
||||
*
|
||||
* Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2008 Embedded Alley Solutions, Inc.
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "gpmi-nand.h"
|
||||
#include "gpmi-regs.h"
|
||||
#include "bch-regs.h"
|
||||
|
||||
/* Converts time to clock cycles */
|
||||
#define TO_CYCLES(duration, period) DIV_ROUND_UP_ULL(duration, period)
|
||||
|
||||
#define MXS_SET_ADDR 0x4
|
||||
#define MXS_CLR_ADDR 0x8
|
||||
/*
|
||||
* Clear the bit and poll it cleared. This is usually called with
|
||||
* a reset address and mask being either SFTRST(bit 31) or CLKGATE
|
||||
* (bit 30).
|
||||
*/
|
||||
static int clear_poll_bit(void __iomem *addr, u32 mask)
|
||||
{
|
||||
int timeout = 0x400;
|
||||
|
||||
/* clear the bit */
|
||||
writel(mask, addr + MXS_CLR_ADDR);
|
||||
|
||||
/*
|
||||
* SFTRST needs 3 GPMI clocks to settle, the reference manual
|
||||
* recommends to wait 1us.
|
||||
*/
|
||||
udelay(1);
|
||||
|
||||
/* poll the bit becoming clear */
|
||||
while ((readl(addr) & mask) && --timeout)
|
||||
/* nothing */;
|
||||
|
||||
return !timeout;
|
||||
}
|
||||
|
||||
#define MODULE_CLKGATE (1 << 30)
|
||||
#define MODULE_SFTRST (1 << 31)
|
||||
/*
|
||||
* The current mxs_reset_block() will do two things:
|
||||
* [1] enable the module.
|
||||
* [2] reset the module.
|
||||
*
|
||||
* In most of the cases, it's ok.
|
||||
* But in MX23, there is a hardware bug in the BCH block (see erratum #2847).
|
||||
* If you try to soft reset the BCH block, it becomes unusable until
|
||||
* the next hard reset. This case occurs in the NAND boot mode. When the board
|
||||
* boots by NAND, the ROM of the chip will initialize the BCH blocks itself.
|
||||
* So If the driver tries to reset the BCH again, the BCH will not work anymore.
|
||||
* You will see a DMA timeout in this case. The bug has been fixed
|
||||
* in the following chips, such as MX28.
|
||||
*
|
||||
* To avoid this bug, just add a new parameter `just_enable` for
|
||||
* the mxs_reset_block(), and rewrite it here.
|
||||
*/
|
||||
static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
|
||||
{
|
||||
int ret;
|
||||
int timeout = 0x400;
|
||||
|
||||
/* clear and poll SFTRST */
|
||||
ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
|
||||
if (unlikely(ret))
|
||||
goto error;
|
||||
|
||||
/* clear CLKGATE */
|
||||
writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR);
|
||||
|
||||
if (!just_enable) {
|
||||
/* set SFTRST to reset the block */
|
||||
writel(MODULE_SFTRST, reset_addr + MXS_SET_ADDR);
|
||||
udelay(1);
|
||||
|
||||
/* poll CLKGATE becoming set */
|
||||
while ((!(readl(reset_addr) & MODULE_CLKGATE)) && --timeout)
|
||||
/* nothing */;
|
||||
if (unlikely(!timeout))
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* clear and poll SFTRST */
|
||||
ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
|
||||
if (unlikely(ret))
|
||||
goto error;
|
||||
|
||||
/* clear and poll CLKGATE */
|
||||
ret = clear_poll_bit(reset_addr, MODULE_CLKGATE);
|
||||
if (unlikely(ret))
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
pr_err("%s(%p): module reset timeout\n", __func__, reset_addr);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int __gpmi_enable_clk(struct gpmi_nand_data *this, bool v)
|
||||
{
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < GPMI_CLK_MAX; i++) {
|
||||
clk = this->resources.clock[i];
|
||||
if (!clk)
|
||||
break;
|
||||
|
||||
if (v) {
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
} else {
|
||||
clk_disable_unprepare(clk);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_clk:
|
||||
for (; i > 0; i--)
|
||||
clk_disable_unprepare(this->resources.clock[i - 1]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int gpmi_enable_clk(struct gpmi_nand_data *this)
|
||||
{
|
||||
return __gpmi_enable_clk(this, true);
|
||||
}
|
||||
|
||||
int gpmi_disable_clk(struct gpmi_nand_data *this)
|
||||
{
|
||||
return __gpmi_enable_clk(this, false);
|
||||
}
|
||||
|
||||
int gpmi_init(struct gpmi_nand_data *this)
|
||||
{
|
||||
struct resources *r = &this->resources;
|
||||
int ret;
|
||||
|
||||
ret = gpmi_enable_clk(this);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = gpmi_reset_block(r->gpmi_regs, false);
|
||||
if (ret)
|
||||
goto err_out;
|
||||
|
||||
/*
|
||||
* Reset BCH here, too. We got failures otherwise :(
|
||||
* See later BCH reset for explanation of MX23 and MX28 handling
|
||||
*/
|
||||
ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MXS(this));
|
||||
if (ret)
|
||||
goto err_out;
|
||||
|
||||
/* Choose NAND mode. */
|
||||
writel(BM_GPMI_CTRL1_GPMI_MODE, r->gpmi_regs + HW_GPMI_CTRL1_CLR);
|
||||
|
||||
/* Set the IRQ polarity. */
|
||||
writel(BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY,
|
||||
r->gpmi_regs + HW_GPMI_CTRL1_SET);
|
||||
|
||||
/* Disable Write-Protection. */
|
||||
writel(BM_GPMI_CTRL1_DEV_RESET, r->gpmi_regs + HW_GPMI_CTRL1_SET);
|
||||
|
||||
/* Select BCH ECC. */
|
||||
writel(BM_GPMI_CTRL1_BCH_MODE, r->gpmi_regs + HW_GPMI_CTRL1_SET);
|
||||
|
||||
/*
|
||||
* Decouple the chip select from dma channel. We use dma0 for all
|
||||
* the chips.
|
||||
*/
|
||||
writel(BM_GPMI_CTRL1_DECOUPLE_CS, r->gpmi_regs + HW_GPMI_CTRL1_SET);
|
||||
|
||||
gpmi_disable_clk(this);
|
||||
return 0;
|
||||
err_out:
|
||||
gpmi_disable_clk(this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This function is very useful. It is called only when the bug occur. */
|
||||
void gpmi_dump_info(struct gpmi_nand_data *this)
|
||||
{
|
||||
struct resources *r = &this->resources;
|
||||
struct bch_geometry *geo = &this->bch_geometry;
|
||||
u32 reg;
|
||||
int i;
|
||||
|
||||
dev_err(this->dev, "Show GPMI registers :\n");
|
||||
for (i = 0; i <= HW_GPMI_DEBUG / 0x10 + 1; i++) {
|
||||
reg = readl(r->gpmi_regs + i * 0x10);
|
||||
dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
|
||||
}
|
||||
|
||||
/* start to print out the BCH info */
|
||||
dev_err(this->dev, "Show BCH registers :\n");
|
||||
for (i = 0; i <= HW_BCH_VERSION / 0x10 + 1; i++) {
|
||||
reg = readl(r->bch_regs + i * 0x10);
|
||||
dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
|
||||
}
|
||||
dev_err(this->dev, "BCH Geometry :\n"
|
||||
"GF length : %u\n"
|
||||
"ECC Strength : %u\n"
|
||||
"Page Size in Bytes : %u\n"
|
||||
"Metadata Size in Bytes : %u\n"
|
||||
"ECC Chunk Size in Bytes: %u\n"
|
||||
"ECC Chunk Count : %u\n"
|
||||
"Payload Size in Bytes : %u\n"
|
||||
"Auxiliary Size in Bytes: %u\n"
|
||||
"Auxiliary Status Offset: %u\n"
|
||||
"Block Mark Byte Offset : %u\n"
|
||||
"Block Mark Bit Offset : %u\n",
|
||||
geo->gf_len,
|
||||
geo->ecc_strength,
|
||||
geo->page_size,
|
||||
geo->metadata_size,
|
||||
geo->ecc_chunk_size,
|
||||
geo->ecc_chunk_count,
|
||||
geo->payload_size,
|
||||
geo->auxiliary_size,
|
||||
geo->auxiliary_status_offset,
|
||||
geo->block_mark_byte_offset,
|
||||
geo->block_mark_bit_offset);
|
||||
}
|
||||
|
||||
/* Configures the geometry for BCH. */
|
||||
int bch_set_geometry(struct gpmi_nand_data *this)
|
||||
{
|
||||
struct resources *r = &this->resources;
|
||||
struct bch_geometry *bch_geo = &this->bch_geometry;
|
||||
unsigned int block_count;
|
||||
unsigned int block_size;
|
||||
unsigned int metadata_size;
|
||||
unsigned int ecc_strength;
|
||||
unsigned int page_size;
|
||||
unsigned int gf_len;
|
||||
int ret;
|
||||
|
||||
ret = common_nfc_set_geometry(this);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
block_count = bch_geo->ecc_chunk_count - 1;
|
||||
block_size = bch_geo->ecc_chunk_size;
|
||||
metadata_size = bch_geo->metadata_size;
|
||||
ecc_strength = bch_geo->ecc_strength >> 1;
|
||||
page_size = bch_geo->page_size;
|
||||
gf_len = bch_geo->gf_len;
|
||||
|
||||
ret = gpmi_enable_clk(this);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
|
||||
* chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
|
||||
* and MX28.
|
||||
*/
|
||||
ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MXS(this));
|
||||
if (ret)
|
||||
goto err_out;
|
||||
|
||||
/* Configure layout 0. */
|
||||
writel(BF_BCH_FLASH0LAYOUT0_NBLOCKS(block_count)
|
||||
| BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size)
|
||||
| BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength, this)
|
||||
| BF_BCH_FLASH0LAYOUT0_GF(gf_len, this)
|
||||
| BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size, this),
|
||||
r->bch_regs + HW_BCH_FLASH0LAYOUT0);
|
||||
|
||||
writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size)
|
||||
| BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength, this)
|
||||
| BF_BCH_FLASH0LAYOUT1_GF(gf_len, this)
|
||||
| BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size, this),
|
||||
r->bch_regs + HW_BCH_FLASH0LAYOUT1);
|
||||
|
||||
/* Set *all* chip selects to use layout 0. */
|
||||
writel(0, r->bch_regs + HW_BCH_LAYOUTSELECT);
|
||||
|
||||
/* Enable interrupts. */
|
||||
writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
|
||||
r->bch_regs + HW_BCH_CTRL_SET);
|
||||
|
||||
gpmi_disable_clk(this);
|
||||
return 0;
|
||||
err_out:
|
||||
gpmi_disable_clk(this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* <1> Firstly, we should know what's the GPMI-clock means.
|
||||
* The GPMI-clock is the internal clock in the gpmi nand controller.
|
||||
* If you set 100MHz to gpmi nand controller, the GPMI-clock's period
|
||||
* is 10ns. Mark the GPMI-clock's period as GPMI-clock-period.
|
||||
*
|
||||
* <2> Secondly, we should know what's the frequency on the nand chip pins.
|
||||
* The frequency on the nand chip pins is derived from the GPMI-clock.
|
||||
* We can get it from the following equation:
|
||||
*
|
||||
* F = G / (DS + DH)
|
||||
*
|
||||
* F : the frequency on the nand chip pins.
|
||||
* G : the GPMI clock, such as 100MHz.
|
||||
* DS : GPMI_HW_GPMI_TIMING0:DATA_SETUP
|
||||
* DH : GPMI_HW_GPMI_TIMING0:DATA_HOLD
|
||||
*
|
||||
* <3> Thirdly, when the frequency on the nand chip pins is above 33MHz,
|
||||
* the nand EDO(extended Data Out) timing could be applied.
|
||||
* The GPMI implements a feedback read strobe to sample the read data.
|
||||
* The feedback read strobe can be delayed to support the nand EDO timing
|
||||
* where the read strobe may deasserts before the read data is valid, and
|
||||
* read data is valid for some time after read strobe.
|
||||
*
|
||||
* The following figure illustrates some aspects of a NAND Flash read:
|
||||
*
|
||||
* |<---tREA---->|
|
||||
* | |
|
||||
* | | |
|
||||
* |<--tRP-->| |
|
||||
* | | |
|
||||
* __ ___|__________________________________
|
||||
* RDN \________/ |
|
||||
* |
|
||||
* /---------\
|
||||
* Read Data --------------< >---------
|
||||
* \---------/
|
||||
* | |
|
||||
* |<-D->|
|
||||
* FeedbackRDN ________ ____________
|
||||
* \___________/
|
||||
*
|
||||
* D stands for delay, set in the HW_GPMI_CTRL1:RDN_DELAY.
|
||||
*
|
||||
*
|
||||
* <4> Now, we begin to describe how to compute the right RDN_DELAY.
|
||||
*
|
||||
* 4.1) From the aspect of the nand chip pins:
|
||||
* Delay = (tREA + C - tRP) {1}
|
||||
*
|
||||
* tREA : the maximum read access time.
|
||||
* C : a constant to adjust the delay. default is 4000ps.
|
||||
* tRP : the read pulse width, which is exactly:
|
||||
* tRP = (GPMI-clock-period) * DATA_SETUP
|
||||
*
|
||||
* 4.2) From the aspect of the GPMI nand controller:
|
||||
* Delay = RDN_DELAY * 0.125 * RP {2}
|
||||
*
|
||||
* RP : the DLL reference period.
|
||||
* if (GPMI-clock-period > DLL_THRETHOLD)
|
||||
* RP = GPMI-clock-period / 2;
|
||||
* else
|
||||
* RP = GPMI-clock-period;
|
||||
*
|
||||
* Set the HW_GPMI_CTRL1:HALF_PERIOD if GPMI-clock-period
|
||||
* is greater DLL_THRETHOLD. In other SOCs, the DLL_THRETHOLD
|
||||
* is 16000ps, but in mx6q, we use 12000ps.
|
||||
*
|
||||
* 4.3) since {1} equals {2}, we get:
|
||||
*
|
||||
* (tREA + 4000 - tRP) * 8
|
||||
* RDN_DELAY = ----------------------- {3}
|
||||
* RP
|
||||
*/
|
||||
static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
|
||||
const struct nand_sdr_timings *sdr)
|
||||
{
|
||||
struct gpmi_nfc_hardware_timing *hw = &this->hw;
|
||||
unsigned int dll_threshold_ps = this->devdata->max_chain_delay;
|
||||
unsigned int period_ps, reference_period_ps;
|
||||
unsigned int data_setup_cycles, data_hold_cycles, addr_setup_cycles;
|
||||
unsigned int tRP_ps;
|
||||
bool use_half_period;
|
||||
int sample_delay_ps, sample_delay_factor;
|
||||
u16 busy_timeout_cycles;
|
||||
u8 wrn_dly_sel;
|
||||
|
||||
if (sdr->tRC_min >= 30000) {
|
||||
/* ONFI non-EDO modes [0-3] */
|
||||
hw->clk_rate = 22000000;
|
||||
wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS;
|
||||
} else if (sdr->tRC_min >= 25000) {
|
||||
/* ONFI EDO mode 4 */
|
||||
hw->clk_rate = 80000000;
|
||||
wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
|
||||
} else {
|
||||
/* ONFI EDO mode 5 */
|
||||
hw->clk_rate = 100000000;
|
||||
wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
|
||||
}
|
||||
|
||||
/* SDR core timings are given in picoseconds */
|
||||
period_ps = div_u64((u64)NSEC_PER_SEC * 1000, hw->clk_rate);
|
||||
|
||||
addr_setup_cycles = TO_CYCLES(sdr->tALS_min, period_ps);
|
||||
data_setup_cycles = TO_CYCLES(sdr->tDS_min, period_ps);
|
||||
data_hold_cycles = TO_CYCLES(sdr->tDH_min, period_ps);
|
||||
busy_timeout_cycles = TO_CYCLES(sdr->tWB_max + sdr->tR_max, period_ps);
|
||||
|
||||
hw->timing0 = BF_GPMI_TIMING0_ADDRESS_SETUP(addr_setup_cycles) |
|
||||
BF_GPMI_TIMING0_DATA_HOLD(data_hold_cycles) |
|
||||
BF_GPMI_TIMING0_DATA_SETUP(data_setup_cycles);
|
||||
hw->timing1 = BF_GPMI_TIMING1_BUSY_TIMEOUT(busy_timeout_cycles * 4096);
|
||||
|
||||
/*
|
||||
* Derive NFC ideal delay from {3}:
|
||||
*
|
||||
* (tREA + 4000 - tRP) * 8
|
||||
* RDN_DELAY = -----------------------
|
||||
* RP
|
||||
*/
|
||||
if (period_ps > dll_threshold_ps) {
|
||||
use_half_period = true;
|
||||
reference_period_ps = period_ps / 2;
|
||||
} else {
|
||||
use_half_period = false;
|
||||
reference_period_ps = period_ps;
|
||||
}
|
||||
|
||||
tRP_ps = data_setup_cycles * period_ps;
|
||||
sample_delay_ps = (sdr->tREA_max + 4000 - tRP_ps) * 8;
|
||||
if (sample_delay_ps > 0)
|
||||
sample_delay_factor = sample_delay_ps / reference_period_ps;
|
||||
else
|
||||
sample_delay_factor = 0;
|
||||
|
||||
hw->ctrl1n = BF_GPMI_CTRL1_WRN_DLY_SEL(wrn_dly_sel);
|
||||
if (sample_delay_factor)
|
||||
hw->ctrl1n |= BF_GPMI_CTRL1_RDN_DELAY(sample_delay_factor) |
|
||||
BM_GPMI_CTRL1_DLL_ENABLE |
|
||||
(use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0);
|
||||
}
|
||||
|
||||
void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
|
||||
{
|
||||
struct gpmi_nfc_hardware_timing *hw = &this->hw;
|
||||
struct resources *r = &this->resources;
|
||||
void __iomem *gpmi_regs = r->gpmi_regs;
|
||||
unsigned int dll_wait_time_us;
|
||||
|
||||
clk_set_rate(r->clock[0], hw->clk_rate);
|
||||
|
||||
writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
|
||||
writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
|
||||
|
||||
/*
|
||||
* Clear several CTRL1 fields, DLL must be disabled when setting
|
||||
* RDN_DELAY or HALF_PERIOD.
|
||||
*/
|
||||
writel(BM_GPMI_CTRL1_CLEAR_MASK, gpmi_regs + HW_GPMI_CTRL1_CLR);
|
||||
writel(hw->ctrl1n, gpmi_regs + HW_GPMI_CTRL1_SET);
|
||||
|
||||
/* Wait 64 clock cycles before using the GPMI after enabling the DLL */
|
||||
dll_wait_time_us = USEC_PER_SEC / hw->clk_rate * 64;
|
||||
if (!dll_wait_time_us)
|
||||
dll_wait_time_us = 1;
|
||||
|
||||
/* Wait for the DLL to settle. */
|
||||
udelay(dll_wait_time_us);
|
||||
}
|
||||
|
||||
int gpmi_setup_data_interface(struct nand_chip *chip, int chipnr,
|
||||
const struct nand_data_interface *conf)
|
||||
{
|
||||
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
||||
const struct nand_sdr_timings *sdr;
|
||||
|
||||
/* Retrieve required NAND timings */
|
||||
sdr = nand_get_sdr_timings(conf);
|
||||
if (IS_ERR(sdr))
|
||||
return PTR_ERR(sdr);
|
||||
|
||||
/* Only MX6 GPMI controller can reach EDO timings */
|
||||
if (sdr->tRC_min <= 25000 && !GPMI_IS_MX6(this))
|
||||
return -ENOTSUPP;
|
||||
|
||||
/* Stop here if this call was just a check */
|
||||
if (chipnr < 0)
|
||||
return 0;
|
||||
|
||||
/* Do the actual derivation of the controller timings */
|
||||
gpmi_nfc_compute_timings(this, sdr);
|
||||
|
||||
this->hw.must_apply_timings = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Clears a BCH interrupt. */
|
||||
void gpmi_clear_bch(struct gpmi_nand_data *this)
|
||||
{
|
||||
struct resources *r = &this->resources;
|
||||
writel(BM_BCH_CTRL_COMPLETE_IRQ, r->bch_regs + HW_BCH_CTRL_CLR);
|
||||
}
|
||||
|
||||
/* Returns the Ready/Busy status of the given chip. */
|
||||
int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip)
|
||||
{
|
||||
struct resources *r = &this->resources;
|
||||
uint32_t mask = 0;
|
||||
uint32_t reg = 0;
|
||||
|
||||
if (GPMI_IS_MX23(this)) {
|
||||
mask = MX23_BM_GPMI_DEBUG_READY0 << chip;
|
||||
reg = readl(r->gpmi_regs + HW_GPMI_DEBUG);
|
||||
} else if (GPMI_IS_MX28(this) || GPMI_IS_MX6(this)) {
|
||||
/*
|
||||
* In the imx6, all the ready/busy pins are bound
|
||||
* together. So we only need to check chip 0.
|
||||
*/
|
||||
if (GPMI_IS_MX6(this))
|
||||
chip = 0;
|
||||
|
||||
/* MX28 shares the same R/B register as MX6Q. */
|
||||
mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip);
|
||||
reg = readl(r->gpmi_regs + HW_GPMI_STAT);
|
||||
} else
|
||||
dev_err(this->dev, "unknown arch.\n");
|
||||
return reg & mask;
|
||||
}
|
||||
|
||||
int gpmi_send_command(struct gpmi_nand_data *this)
|
||||
{
|
||||
struct dma_chan *channel = get_dma_chan(this);
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
struct scatterlist *sgl;
|
||||
int chip = this->current_chip;
|
||||
int ret;
|
||||
u32 pio[3];
|
||||
|
||||
/* [1] send out the PIO words */
|
||||
pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__WRITE)
|
||||
| BM_GPMI_CTRL0_WORD_LENGTH
|
||||
| BF_GPMI_CTRL0_CS(chip, this)
|
||||
| BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
|
||||
| BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_CLE)
|
||||
| BM_GPMI_CTRL0_ADDRESS_INCREMENT
|
||||
| BF_GPMI_CTRL0_XFER_COUNT(this->command_length);
|
||||
pio[1] = pio[2] = 0;
|
||||
desc = dmaengine_prep_slave_sg(channel,
|
||||
(struct scatterlist *)pio,
|
||||
ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
/* [2] send out the COMMAND + ADDRESS string stored in @buffer */
|
||||
sgl = &this->cmd_sgl;
|
||||
|
||||
sg_init_one(sgl, this->cmd_buffer, this->command_length);
|
||||
dma_map_sg(this->dev, sgl, 1, DMA_TO_DEVICE);
|
||||
desc = dmaengine_prep_slave_sg(channel,
|
||||
sgl, 1, DMA_MEM_TO_DEV,
|
||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
/* [3] submit the DMA */
|
||||
ret = start_dma_without_bch_irq(this, desc);
|
||||
|
||||
dma_unmap_sg(this->dev, sgl, 1, DMA_TO_DEVICE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int gpmi_send_data(struct gpmi_nand_data *this, const void *buf, int len)
|
||||
{
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
struct dma_chan *channel = get_dma_chan(this);
|
||||
int chip = this->current_chip;
|
||||
int ret;
|
||||
uint32_t command_mode;
|
||||
uint32_t address;
|
||||
u32 pio[2];
|
||||
|
||||
/* [1] PIO */
|
||||
command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WRITE;
|
||||
address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
|
||||
|
||||
pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
|
||||
| BM_GPMI_CTRL0_WORD_LENGTH
|
||||
| BF_GPMI_CTRL0_CS(chip, this)
|
||||
| BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
|
||||
| BF_GPMI_CTRL0_ADDRESS(address)
|
||||
| BF_GPMI_CTRL0_XFER_COUNT(len);
|
||||
pio[1] = 0;
|
||||
desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio,
|
||||
ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
/* [2] send DMA request */
|
||||
prepare_data_dma(this, buf, len, DMA_TO_DEVICE);
|
||||
desc = dmaengine_prep_slave_sg(channel, &this->data_sgl,
|
||||
1, DMA_MEM_TO_DEV,
|
||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
/* [3] submit the DMA */
|
||||
ret = start_dma_without_bch_irq(this, desc);
|
||||
|
||||
dma_unmap_sg(this->dev, &this->data_sgl, 1, DMA_TO_DEVICE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int gpmi_read_data(struct gpmi_nand_data *this, void *buf, int len)
|
||||
{
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
struct dma_chan *channel = get_dma_chan(this);
|
||||
int chip = this->current_chip;
|
||||
int ret;
|
||||
u32 pio[2];
|
||||
bool direct;
|
||||
|
||||
/* [1] : send PIO */
|
||||
pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__READ)
|
||||
| BM_GPMI_CTRL0_WORD_LENGTH
|
||||
| BF_GPMI_CTRL0_CS(chip, this)
|
||||
| BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
|
||||
| BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_DATA)
|
||||
| BF_GPMI_CTRL0_XFER_COUNT(len);
|
||||
pio[1] = 0;
|
||||
desc = dmaengine_prep_slave_sg(channel,
|
||||
(struct scatterlist *)pio,
|
||||
ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
/* [2] : send DMA request */
|
||||
direct = prepare_data_dma(this, buf, len, DMA_FROM_DEVICE);
|
||||
desc = dmaengine_prep_slave_sg(channel, &this->data_sgl,
|
||||
1, DMA_DEV_TO_MEM,
|
||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
/* [3] : submit the DMA */
|
||||
|
||||
ret = start_dma_without_bch_irq(this, desc);
|
||||
|
||||
dma_unmap_sg(this->dev, &this->data_sgl, 1, DMA_FROM_DEVICE);
|
||||
if (!direct)
|
||||
memcpy(buf, this->data_buffer_dma, len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int gpmi_send_page(struct gpmi_nand_data *this,
|
||||
dma_addr_t payload, dma_addr_t auxiliary)
|
||||
{
|
||||
struct bch_geometry *geo = &this->bch_geometry;
|
||||
uint32_t command_mode;
|
||||
uint32_t address;
|
||||
uint32_t ecc_command;
|
||||
uint32_t buffer_mask;
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
struct dma_chan *channel = get_dma_chan(this);
|
||||
int chip = this->current_chip;
|
||||
u32 pio[6];
|
||||
|
||||
/* A DMA descriptor that does an ECC page read. */
|
||||
command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WRITE;
|
||||
address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
|
||||
ecc_command = BV_GPMI_ECCCTRL_ECC_CMD__BCH_ENCODE;
|
||||
buffer_mask = BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE |
|
||||
BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY;
|
||||
|
||||
pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
|
||||
| BM_GPMI_CTRL0_WORD_LENGTH
|
||||
| BF_GPMI_CTRL0_CS(chip, this)
|
||||
| BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
|
||||
| BF_GPMI_CTRL0_ADDRESS(address)
|
||||
| BF_GPMI_CTRL0_XFER_COUNT(0);
|
||||
pio[1] = 0;
|
||||
pio[2] = BM_GPMI_ECCCTRL_ENABLE_ECC
|
||||
| BF_GPMI_ECCCTRL_ECC_CMD(ecc_command)
|
||||
| BF_GPMI_ECCCTRL_BUFFER_MASK(buffer_mask);
|
||||
pio[3] = geo->page_size;
|
||||
pio[4] = payload;
|
||||
pio[5] = auxiliary;
|
||||
|
||||
desc = dmaengine_prep_slave_sg(channel,
|
||||
(struct scatterlist *)pio,
|
||||
ARRAY_SIZE(pio), DMA_TRANS_NONE,
|
||||
DMA_CTRL_ACK);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
return start_dma_with_bch_irq(this, desc);
|
||||
}
|
||||
|
||||
int gpmi_read_page(struct gpmi_nand_data *this,
|
||||
dma_addr_t payload, dma_addr_t auxiliary)
|
||||
{
|
||||
struct bch_geometry *geo = &this->bch_geometry;
|
||||
uint32_t command_mode;
|
||||
uint32_t address;
|
||||
uint32_t ecc_command;
|
||||
uint32_t buffer_mask;
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
struct dma_chan *channel = get_dma_chan(this);
|
||||
int chip = this->current_chip;
|
||||
u32 pio[6];
|
||||
|
||||
/* [1] Wait for the chip to report ready. */
|
||||
command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY;
|
||||
address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
|
||||
|
||||
pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
|
||||
| BM_GPMI_CTRL0_WORD_LENGTH
|
||||
| BF_GPMI_CTRL0_CS(chip, this)
|
||||
| BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
|
||||
| BF_GPMI_CTRL0_ADDRESS(address)
|
||||
| BF_GPMI_CTRL0_XFER_COUNT(0);
|
||||
pio[1] = 0;
|
||||
desc = dmaengine_prep_slave_sg(channel,
|
||||
(struct scatterlist *)pio, 2,
|
||||
DMA_TRANS_NONE, 0);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
/* [2] Enable the BCH block and read. */
|
||||
command_mode = BV_GPMI_CTRL0_COMMAND_MODE__READ;
|
||||
address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
|
||||
ecc_command = BV_GPMI_ECCCTRL_ECC_CMD__BCH_DECODE;
|
||||
buffer_mask = BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE
|
||||
| BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY;
|
||||
|
||||
pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
|
||||
| BM_GPMI_CTRL0_WORD_LENGTH
|
||||
| BF_GPMI_CTRL0_CS(chip, this)
|
||||
| BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
|
||||
| BF_GPMI_CTRL0_ADDRESS(address)
|
||||
| BF_GPMI_CTRL0_XFER_COUNT(geo->page_size);
|
||||
|
||||
pio[1] = 0;
|
||||
pio[2] = BM_GPMI_ECCCTRL_ENABLE_ECC
|
||||
| BF_GPMI_ECCCTRL_ECC_CMD(ecc_command)
|
||||
| BF_GPMI_ECCCTRL_BUFFER_MASK(buffer_mask);
|
||||
pio[3] = geo->page_size;
|
||||
pio[4] = payload;
|
||||
pio[5] = auxiliary;
|
||||
desc = dmaengine_prep_slave_sg(channel,
|
||||
(struct scatterlist *)pio,
|
||||
ARRAY_SIZE(pio), DMA_TRANS_NONE,
|
||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
/* [3] Disable the BCH block */
|
||||
command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY;
|
||||
address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
|
||||
|
||||
pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
|
||||
| BM_GPMI_CTRL0_WORD_LENGTH
|
||||
| BF_GPMI_CTRL0_CS(chip, this)
|
||||
| BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
|
||||
| BF_GPMI_CTRL0_ADDRESS(address)
|
||||
| BF_GPMI_CTRL0_XFER_COUNT(geo->page_size);
|
||||
pio[1] = 0;
|
||||
pio[2] = 0; /* clear GPMI_HW_GPMI_ECCCTRL, disable the BCH. */
|
||||
desc = dmaengine_prep_slave_sg(channel,
|
||||
(struct scatterlist *)pio, 3,
|
||||
DMA_TRANS_NONE,
|
||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
/* [4] submit the DMA */
|
||||
return start_dma_with_bch_irq(this, desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* gpmi_copy_bits - copy bits from one memory region to another
|
||||
* @dst: destination buffer
|
||||
* @dst_bit_off: bit offset we're starting to write at
|
||||
* @src: source buffer
|
||||
* @src_bit_off: bit offset we're starting to read from
|
||||
* @nbits: number of bits to copy
|
||||
*
|
||||
* This functions copies bits from one memory region to another, and is used by
|
||||
* the GPMI driver to copy ECC sections which are not guaranteed to be byte
|
||||
* aligned.
|
||||
*
|
||||
* src and dst should not overlap.
|
||||
*
|
||||
*/
|
||||
void gpmi_copy_bits(u8 *dst, size_t dst_bit_off,
|
||||
const u8 *src, size_t src_bit_off,
|
||||
size_t nbits)
|
||||
{
|
||||
size_t i;
|
||||
size_t nbytes;
|
||||
u32 src_buffer = 0;
|
||||
size_t bits_in_src_buffer = 0;
|
||||
|
||||
if (!nbits)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Move src and dst pointers to the closest byte pointer and store bit
|
||||
* offsets within a byte.
|
||||
*/
|
||||
src += src_bit_off / 8;
|
||||
src_bit_off %= 8;
|
||||
|
||||
dst += dst_bit_off / 8;
|
||||
dst_bit_off %= 8;
|
||||
|
||||
/*
|
||||
* Initialize the src_buffer value with bits available in the first
|
||||
* byte of data so that we end up with a byte aligned src pointer.
|
||||
*/
|
||||
if (src_bit_off) {
|
||||
src_buffer = src[0] >> src_bit_off;
|
||||
if (nbits >= (8 - src_bit_off)) {
|
||||
bits_in_src_buffer += 8 - src_bit_off;
|
||||
} else {
|
||||
src_buffer &= GENMASK(nbits - 1, 0);
|
||||
bits_in_src_buffer += nbits;
|
||||
}
|
||||
nbits -= bits_in_src_buffer;
|
||||
src++;
|
||||
}
|
||||
|
||||
/* Calculate the number of bytes that can be copied from src to dst. */
|
||||
nbytes = nbits / 8;
|
||||
|
||||
/* Try to align dst to a byte boundary. */
|
||||
if (dst_bit_off) {
|
||||
if (bits_in_src_buffer < (8 - dst_bit_off) && nbytes) {
|
||||
src_buffer |= src[0] << bits_in_src_buffer;
|
||||
bits_in_src_buffer += 8;
|
||||
src++;
|
||||
nbytes--;
|
||||
}
|
||||
|
||||
if (bits_in_src_buffer >= (8 - dst_bit_off)) {
|
||||
dst[0] &= GENMASK(dst_bit_off - 1, 0);
|
||||
dst[0] |= src_buffer << dst_bit_off;
|
||||
src_buffer >>= (8 - dst_bit_off);
|
||||
bits_in_src_buffer -= (8 - dst_bit_off);
|
||||
dst_bit_off = 0;
|
||||
dst++;
|
||||
if (bits_in_src_buffer > 7) {
|
||||
bits_in_src_buffer -= 8;
|
||||
dst[0] = src_buffer;
|
||||
dst++;
|
||||
src_buffer >>= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bits_in_src_buffer && !dst_bit_off) {
|
||||
/*
|
||||
* Both src and dst pointers are byte aligned, thus we can
|
||||
* just use the optimized memcpy function.
|
||||
*/
|
||||
if (nbytes)
|
||||
memcpy(dst, src, nbytes);
|
||||
} else {
|
||||
/*
|
||||
* src buffer is not byte aligned, hence we have to copy each
|
||||
* src byte to the src_buffer variable before extracting a byte
|
||||
* to store in dst.
|
||||
*/
|
||||
for (i = 0; i < nbytes; i++) {
|
||||
src_buffer |= src[i] << bits_in_src_buffer;
|
||||
dst[i] = src_buffer;
|
||||
src_buffer >>= 8;
|
||||
}
|
||||
}
|
||||
/* Update dst and src pointers */
|
||||
dst += nbytes;
|
||||
src += nbytes;
|
||||
|
||||
/*
|
||||
* nbits is the number of remaining bits. It should not exceed 8 as
|
||||
* we've already copied as much bytes as possible.
|
||||
*/
|
||||
nbits %= 8;
|
||||
|
||||
/*
|
||||
* If there's no more bits to copy to the destination and src buffer
|
||||
* was already byte aligned, then we're done.
|
||||
*/
|
||||
if (!nbits && !bits_in_src_buffer)
|
||||
return;
|
||||
|
||||
/* Copy the remaining bits to src_buffer */
|
||||
if (nbits)
|
||||
src_buffer |= (*src & GENMASK(nbits - 1, 0)) <<
|
||||
bits_in_src_buffer;
|
||||
bits_in_src_buffer += nbits;
|
||||
|
||||
/*
|
||||
* In case there were not enough bits to get a byte aligned dst buffer
|
||||
* prepare the src_buffer variable to match the dst organization (shift
|
||||
* src_buffer by dst_bit_off and retrieve the least significant bits
|
||||
* from dst).
|
||||
*/
|
||||
if (dst_bit_off)
|
||||
src_buffer = (src_buffer << dst_bit_off) |
|
||||
(*dst & GENMASK(dst_bit_off - 1, 0));
|
||||
bits_in_src_buffer += dst_bit_off;
|
||||
|
||||
/*
|
||||
* Keep most significant bits from dst if we end up with an unaligned
|
||||
* number of bits.
|
||||
*/
|
||||
nbytes = bits_in_src_buffer / 8;
|
||||
if (bits_in_src_buffer % 8) {
|
||||
src_buffer |= (dst[nbytes] &
|
||||
GENMASK(7, bits_in_src_buffer % 8)) <<
|
||||
(nbytes * 8);
|
||||
nbytes++;
|
||||
}
|
||||
|
||||
/* Copy the remaining bytes to dst */
|
||||
for (i = 0; i < nbytes; i++) {
|
||||
dst[i] = src_buffer;
|
||||
src_buffer >>= 8;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -103,6 +103,14 @@ struct gpmi_nfc_hardware_timing {
|
||||
u32 ctrl1n;
|
||||
};
|
||||
|
||||
#define GPMI_MAX_TRANSFERS 8
|
||||
|
||||
struct gpmi_transfer {
|
||||
u8 cmdbuf[8];
|
||||
struct scatterlist sgl;
|
||||
enum dma_data_direction direction;
|
||||
};
|
||||
|
||||
struct gpmi_nand_data {
|
||||
/* Devdata */
|
||||
const struct gpmi_devdata *devdata;
|
||||
@@ -126,25 +134,18 @@ struct gpmi_nand_data {
|
||||
struct boot_rom_geometry rom_geometry;
|
||||
|
||||
/* MTD / NAND */
|
||||
struct nand_controller base;
|
||||
struct nand_chip nand;
|
||||
|
||||
/* General-use Variables */
|
||||
int current_chip;
|
||||
unsigned int command_length;
|
||||
struct gpmi_transfer transfers[GPMI_MAX_TRANSFERS];
|
||||
int ntransfers;
|
||||
|
||||
struct scatterlist cmd_sgl;
|
||||
char *cmd_buffer;
|
||||
bool bch;
|
||||
uint32_t bch_flashlayout0;
|
||||
uint32_t bch_flashlayout1;
|
||||
|
||||
struct scatterlist data_sgl;
|
||||
char *data_buffer_dma;
|
||||
|
||||
void *page_buffer_virt;
|
||||
dma_addr_t page_buffer_phys;
|
||||
unsigned int page_buffer_size;
|
||||
|
||||
void *payload_virt;
|
||||
dma_addr_t payload_phys;
|
||||
|
||||
void *auxiliary_virt;
|
||||
dma_addr_t auxiliary_phys;
|
||||
|
||||
@@ -154,45 +155,8 @@ struct gpmi_nand_data {
|
||||
#define DMA_CHANS 8
|
||||
struct dma_chan *dma_chans[DMA_CHANS];
|
||||
struct completion dma_done;
|
||||
|
||||
/* private */
|
||||
void *private;
|
||||
};
|
||||
|
||||
/* Common Services */
|
||||
int common_nfc_set_geometry(struct gpmi_nand_data *);
|
||||
struct dma_chan *get_dma_chan(struct gpmi_nand_data *);
|
||||
bool prepare_data_dma(struct gpmi_nand_data *, const void *buf, int len,
|
||||
enum dma_data_direction dr);
|
||||
int start_dma_without_bch_irq(struct gpmi_nand_data *,
|
||||
struct dma_async_tx_descriptor *);
|
||||
int start_dma_with_bch_irq(struct gpmi_nand_data *,
|
||||
struct dma_async_tx_descriptor *);
|
||||
|
||||
/* GPMI-NAND helper function library */
|
||||
int gpmi_init(struct gpmi_nand_data *);
|
||||
void gpmi_clear_bch(struct gpmi_nand_data *);
|
||||
void gpmi_dump_info(struct gpmi_nand_data *);
|
||||
int bch_set_geometry(struct gpmi_nand_data *);
|
||||
int gpmi_is_ready(struct gpmi_nand_data *, unsigned chip);
|
||||
int gpmi_send_command(struct gpmi_nand_data *);
|
||||
int gpmi_enable_clk(struct gpmi_nand_data *this);
|
||||
int gpmi_disable_clk(struct gpmi_nand_data *this);
|
||||
int gpmi_setup_data_interface(struct nand_chip *chip, int chipnr,
|
||||
const struct nand_data_interface *conf);
|
||||
void gpmi_nfc_apply_timings(struct gpmi_nand_data *this);
|
||||
int gpmi_read_data(struct gpmi_nand_data *, void *buf, int len);
|
||||
int gpmi_send_data(struct gpmi_nand_data *, const void *buf, int len);
|
||||
|
||||
int gpmi_send_page(struct gpmi_nand_data *,
|
||||
dma_addr_t payload, dma_addr_t auxiliary);
|
||||
int gpmi_read_page(struct gpmi_nand_data *,
|
||||
dma_addr_t payload, dma_addr_t auxiliary);
|
||||
|
||||
void gpmi_copy_bits(u8 *dst, size_t dst_bit_off,
|
||||
const u8 *src, size_t src_bit_off,
|
||||
size_t nbits);
|
||||
|
||||
/* BCH : Status Block Completion Codes */
|
||||
#define STATUS_GOOD 0x00
|
||||
#define STATUS_ERASED 0xff
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Freescale GPMI NAND Flash Driver
|
||||
*
|
||||
* Copyright 2008-2011 Freescale Semiconductor, Inc.
|
||||
* Copyright 2008 Embedded Alley Solutions, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef __GPMI_NAND_GPMI_REGS_H
|
||||
#define __GPMI_NAND_GPMI_REGS_H
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Hisilicon NAND Flash controller driver
|
||||
*
|
||||
@@ -7,16 +8,6 @@
|
||||
* Author: Zhou Wang <wangzhou.bry@gmail.com>
|
||||
* The initial developer of the original code is Zhiyong Cai
|
||||
* <caizhiyong@huawei.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <linux/of.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config MTD_NAND_JZ4740
|
||||
tristate "JZ4740 NAND controller"
|
||||
depends on MACH_JZ4740 || COMPILE_TEST
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o
|
||||
obj-$(CONFIG_MTD_NAND_JZ4780) += ingenic_nand.o
|
||||
|
||||
|
||||
@@ -1,16 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
|
||||
* JZ4740 SoC NAND controller driver
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Driver for NAND MLC Controller in LPC32xx
|
||||
*
|
||||
@@ -6,17 +7,6 @@
|
||||
* Copyright © 2011 WORK Microwave GmbH
|
||||
* Copyright © 2011, 2012 Roland Stigge
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
* NAND Flash Controller Operation:
|
||||
* - Read: Auto Decode
|
||||
* - Write: Auto Encode
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* NXP LPC32XX NAND SLC driver
|
||||
*
|
||||
@@ -7,16 +8,6 @@
|
||||
*
|
||||
* Copyright © 2011 NXP Semiconductors
|
||||
* Copyright © 2012 Roland Stigge
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright 2004-2008 Freescale Semiconductor, Inc.
|
||||
* Copyright 2009 Semihalf.
|
||||
@@ -8,20 +9,6 @@
|
||||
* Based on original driver from Freescale Semiconductor
|
||||
* written by John Rigby <jrigby@freescale.com> on basis of mxc_nand.c.
|
||||
* Reworked and extended by Piotr Ziecik <kosmo@semihalf.com>.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR MIT
|
||||
/*
|
||||
* MTK ECC controller driver.
|
||||
* Copyright (C) 2016 MediaTek Inc.
|
||||
* Authors: Xiaolei Li <xiaolei.li@mediatek.com>
|
||||
* Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
@@ -604,4 +596,4 @@ module_platform_driver(mtk_ecc_driver);
|
||||
|
||||
MODULE_AUTHOR("Xiaolei Li <xiaolei.li@mediatek.com>");
|
||||
MODULE_DESCRIPTION("MTK Nand ECC Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("Dual MIT/GPL");
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR MIT */
|
||||
/*
|
||||
* MTK SDG1 ECC controller
|
||||
*
|
||||
* Copyright (c) 2016 Mediatek
|
||||
* Authors: Xiaolei Li <xiaolei.li@mediatek.com>
|
||||
* Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_MTD_NAND_MTK_ECC_H__
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR MIT
|
||||
/*
|
||||
* MTK NAND Flash controller driver.
|
||||
* Copyright (C) 2016 MediaTek Inc.
|
||||
* Authors: Xiaolei Li <xiaolei.li@mediatek.com>
|
||||
* Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
@@ -87,6 +79,10 @@
|
||||
#define NFI_FDMM(x) (0xA4 + (x) * sizeof(u32) * 2)
|
||||
#define NFI_FDM_MAX_SIZE (8)
|
||||
#define NFI_FDM_MIN_SIZE (1)
|
||||
#define NFI_DEBUG_CON1 (0x220)
|
||||
#define STROBE_MASK GENMASK(4, 3)
|
||||
#define STROBE_SHIFT (3)
|
||||
#define MAX_STROBE_DLY (3)
|
||||
#define NFI_MASTER_STA (0x224)
|
||||
#define MASTER_STA_MASK (0x0FFF)
|
||||
#define NFI_EMPTY_THRESH (0x23C)
|
||||
@@ -158,6 +154,8 @@ struct mtk_nfc {
|
||||
struct list_head chips;
|
||||
|
||||
u8 *buffer;
|
||||
|
||||
unsigned long assigned_cs;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -508,7 +506,8 @@ static int mtk_nfc_setup_data_interface(struct nand_chip *chip, int csline,
|
||||
{
|
||||
struct mtk_nfc *nfc = nand_get_controller_data(chip);
|
||||
const struct nand_sdr_timings *timings;
|
||||
u32 rate, tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt;
|
||||
u32 rate, tpoecs, tprecs, tc2r, tw2r, twh, twst = 0, trlt = 0;
|
||||
u32 temp, tsel = 0;
|
||||
|
||||
timings = nand_get_sdr_timings(conf);
|
||||
if (IS_ERR(timings))
|
||||
@@ -544,14 +543,53 @@ static int mtk_nfc_setup_data_interface(struct nand_chip *chip, int csline,
|
||||
twh = DIV_ROUND_UP(twh * rate, 1000000) - 1;
|
||||
twh &= 0xf;
|
||||
|
||||
twst = timings->tWP_min / 1000;
|
||||
/* Calculate real WE#/RE# hold time in nanosecond */
|
||||
temp = (twh + 1) * 1000000 / rate;
|
||||
/* nanosecond to picosecond */
|
||||
temp *= 1000;
|
||||
|
||||
/*
|
||||
* WE# low level time should be expaned to meet WE# pulse time
|
||||
* and WE# cycle time at the same time.
|
||||
*/
|
||||
if (temp < timings->tWC_min)
|
||||
twst = timings->tWC_min - temp;
|
||||
twst = max(timings->tWP_min, twst) / 1000;
|
||||
twst = DIV_ROUND_UP(twst * rate, 1000000) - 1;
|
||||
twst &= 0xf;
|
||||
|
||||
trlt = max(timings->tREA_max, timings->tRP_min) / 1000;
|
||||
/*
|
||||
* RE# low level time should be expaned to meet RE# pulse time
|
||||
* and RE# cycle time at the same time.
|
||||
*/
|
||||
if (temp < timings->tRC_min)
|
||||
trlt = timings->tRC_min - temp;
|
||||
trlt = max(trlt, timings->tRP_min) / 1000;
|
||||
trlt = DIV_ROUND_UP(trlt * rate, 1000000) - 1;
|
||||
trlt &= 0xf;
|
||||
|
||||
/* Calculate RE# pulse time in nanosecond. */
|
||||
temp = (trlt + 1) * 1000000 / rate;
|
||||
/* nanosecond to picosecond */
|
||||
temp *= 1000;
|
||||
/*
|
||||
* If RE# access time is bigger than RE# pulse time,
|
||||
* delay sampling data timing.
|
||||
*/
|
||||
if (temp < timings->tREA_max) {
|
||||
tsel = timings->tREA_max / 1000;
|
||||
tsel = DIV_ROUND_UP(tsel * rate, 1000000);
|
||||
tsel -= (trlt + 1);
|
||||
if (tsel > MAX_STROBE_DLY) {
|
||||
trlt += tsel - MAX_STROBE_DLY;
|
||||
tsel = MAX_STROBE_DLY;
|
||||
}
|
||||
}
|
||||
temp = nfi_readl(nfc, NFI_DEBUG_CON1);
|
||||
temp &= ~STROBE_MASK;
|
||||
temp |= tsel << STROBE_SHIFT;
|
||||
nfi_writel(nfc, temp, NFI_DEBUG_CON1);
|
||||
|
||||
/*
|
||||
* ACCON: access timing control register
|
||||
* -------------------------------------
|
||||
@@ -843,19 +881,21 @@ static int mtk_nfc_write_oob_std(struct nand_chip *chip, int page)
|
||||
return mtk_nfc_write_page_raw(chip, NULL, 1, page);
|
||||
}
|
||||
|
||||
static int mtk_nfc_update_ecc_stats(struct mtd_info *mtd, u8 *buf, u32 sectors)
|
||||
static int mtk_nfc_update_ecc_stats(struct mtd_info *mtd, u8 *buf, u32 start,
|
||||
u32 sectors)
|
||||
{
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
struct mtk_nfc *nfc = nand_get_controller_data(chip);
|
||||
struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
|
||||
struct mtk_ecc_stats stats;
|
||||
u32 reg_size = mtk_nand->fdm.reg_size;
|
||||
int rc, i;
|
||||
|
||||
rc = nfi_readl(nfc, NFI_STA) & STA_EMP_PAGE;
|
||||
if (rc) {
|
||||
memset(buf, 0xff, sectors * chip->ecc.size);
|
||||
for (i = 0; i < sectors; i++)
|
||||
memset(oob_ptr(chip, i), 0xff, mtk_nand->fdm.reg_size);
|
||||
memset(oob_ptr(chip, start + i), 0xff, reg_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -875,7 +915,7 @@ static int mtk_nfc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
u32 spare = mtk_nand->spare_per_sector;
|
||||
u32 column, sectors, start, end, reg;
|
||||
dma_addr_t addr;
|
||||
int bitflips;
|
||||
int bitflips = 0;
|
||||
size_t len;
|
||||
u8 *buf;
|
||||
int rc;
|
||||
@@ -942,14 +982,11 @@ static int mtk_nfc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
if (rc < 0) {
|
||||
dev_err(nfc->dev, "subpage done timeout\n");
|
||||
bitflips = -EIO;
|
||||
} else {
|
||||
bitflips = 0;
|
||||
if (!raw) {
|
||||
rc = mtk_ecc_wait_done(nfc->ecc, ECC_DECODE);
|
||||
bitflips = rc < 0 ? -ETIMEDOUT :
|
||||
mtk_nfc_update_ecc_stats(mtd, buf, sectors);
|
||||
mtk_nfc_read_fdm(chip, start, sectors);
|
||||
}
|
||||
} else if (!raw) {
|
||||
rc = mtk_ecc_wait_done(nfc->ecc, ECC_DECODE);
|
||||
bitflips = rc < 0 ? -ETIMEDOUT :
|
||||
mtk_nfc_update_ecc_stats(mtd, buf, start, sectors);
|
||||
mtk_nfc_read_fdm(chip, start, sectors);
|
||||
}
|
||||
|
||||
dma_unmap_single(nfc->dev, addr, len, DMA_FROM_DEVICE);
|
||||
@@ -1323,6 +1360,17 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
|
||||
dev_err(dev, "reg property failure : %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (tmp >= MTK_NAND_MAX_NSELS) {
|
||||
dev_err(dev, "invalid CS: %u\n", tmp);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (test_and_set_bit(tmp, &nfc->assigned_cs)) {
|
||||
dev_err(dev, "CS %u already assigned\n", tmp);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
chip->sels[i] = tmp;
|
||||
}
|
||||
|
||||
@@ -1597,6 +1645,6 @@ static struct platform_driver mtk_nfc_driver = {
|
||||
|
||||
module_platform_driver(mtk_nfc_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("Dual MIT/GPL");
|
||||
MODULE_AUTHOR("Xiaolei Li <xiaolei.li@mediatek.com>");
|
||||
MODULE_DESCRIPTION("MTK Nand Flash Controller Driver");
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2017 Free Electrons
|
||||
* Copyright (C) 2017 NextThing Co
|
||||
*
|
||||
* Author: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "internals.h"
|
||||
|
||||
@@ -2115,35 +2115,7 @@ static void nand_op_parser_trace(const struct nand_op_parser_ctx *ctx)
|
||||
if (instr == &ctx->subop.instrs[0])
|
||||
prefix = " ->";
|
||||
|
||||
switch (instr->type) {
|
||||
case NAND_OP_CMD_INSTR:
|
||||
pr_debug("%sCMD [0x%02x]\n", prefix,
|
||||
instr->ctx.cmd.opcode);
|
||||
break;
|
||||
case NAND_OP_ADDR_INSTR:
|
||||
pr_debug("%sADDR [%d cyc: %*ph]\n", prefix,
|
||||
instr->ctx.addr.naddrs,
|
||||
instr->ctx.addr.naddrs < 64 ?
|
||||
instr->ctx.addr.naddrs : 64,
|
||||
instr->ctx.addr.addrs);
|
||||
break;
|
||||
case NAND_OP_DATA_IN_INSTR:
|
||||
pr_debug("%sDATA_IN [%d B%s]\n", prefix,
|
||||
instr->ctx.data.len,
|
||||
instr->ctx.data.force_8bit ?
|
||||
", force 8-bit" : "");
|
||||
break;
|
||||
case NAND_OP_DATA_OUT_INSTR:
|
||||
pr_debug("%sDATA_OUT [%d B%s]\n", prefix,
|
||||
instr->ctx.data.len,
|
||||
instr->ctx.data.force_8bit ?
|
||||
", force 8-bit" : "");
|
||||
break;
|
||||
case NAND_OP_WAITRDY_INSTR:
|
||||
pr_debug("%sWAITRDY [max %d ms]\n", prefix,
|
||||
instr->ctx.waitrdy.timeout_ms);
|
||||
break;
|
||||
}
|
||||
nand_op_trace(prefix, instr);
|
||||
|
||||
if (instr == &ctx->subop.instrs[ctx->subop.ninstrs - 1])
|
||||
prefix = " ";
|
||||
@@ -2156,6 +2128,22 @@ static void nand_op_parser_trace(const struct nand_op_parser_ctx *ctx)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int nand_op_parser_cmp_ctx(const struct nand_op_parser_ctx *a,
|
||||
const struct nand_op_parser_ctx *b)
|
||||
{
|
||||
if (a->subop.ninstrs < b->subop.ninstrs)
|
||||
return -1;
|
||||
else if (a->subop.ninstrs > b->subop.ninstrs)
|
||||
return 1;
|
||||
|
||||
if (a->subop.last_instr_end_off < b->subop.last_instr_end_off)
|
||||
return -1;
|
||||
else if (a->subop.last_instr_end_off > b->subop.last_instr_end_off)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* nand_op_parser_exec_op - exec_op parser
|
||||
* @chip: the NAND chip
|
||||
@@ -2190,30 +2178,38 @@ int nand_op_parser_exec_op(struct nand_chip *chip,
|
||||
unsigned int i;
|
||||
|
||||
while (ctx.subop.instrs < op->instrs + op->ninstrs) {
|
||||
int ret;
|
||||
const struct nand_op_parser_pattern *pattern;
|
||||
struct nand_op_parser_ctx best_ctx;
|
||||
int ret, best_pattern = -1;
|
||||
|
||||
for (i = 0; i < parser->npatterns; i++) {
|
||||
const struct nand_op_parser_pattern *pattern;
|
||||
struct nand_op_parser_ctx test_ctx = ctx;
|
||||
|
||||
pattern = &parser->patterns[i];
|
||||
if (!nand_op_parser_match_pat(pattern, &ctx))
|
||||
if (!nand_op_parser_match_pat(pattern, &test_ctx))
|
||||
continue;
|
||||
|
||||
nand_op_parser_trace(&ctx);
|
||||
if (best_pattern >= 0 &&
|
||||
nand_op_parser_cmp_ctx(&test_ctx, &best_ctx) <= 0)
|
||||
continue;
|
||||
|
||||
if (check_only)
|
||||
break;
|
||||
best_pattern = i;
|
||||
best_ctx = test_ctx;
|
||||
}
|
||||
|
||||
if (best_pattern < 0) {
|
||||
pr_debug("->exec_op() parser: pattern not found!\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
ctx = best_ctx;
|
||||
nand_op_parser_trace(&ctx);
|
||||
|
||||
if (!check_only) {
|
||||
pattern = &parser->patterns[best_pattern];
|
||||
ret = pattern->exec(chip, &ctx.subop);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == parser->npatterns) {
|
||||
pr_debug("->exec_op() parser: pattern not found!\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* This file provides ECC correction for more than 1 bit per block of data,
|
||||
* using binary BCH codes. It relies on the generic BCH library lib/bch.c.
|
||||
*
|
||||
* Copyright © 2011 Ivan Djelic <ivan.djelic@parrot.com>
|
||||
*
|
||||
* This file 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 or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This file 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this file; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
@@ -183,7 +170,7 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nbc->eccmask = kmalloc(eccbytes, GFP_KERNEL);
|
||||
nbc->eccmask = kzalloc(eccbytes, GFP_KERNEL);
|
||||
nbc->errloc = kmalloc_array(t, sizeof(*nbc->errloc), GFP_KERNEL);
|
||||
if (!nbc->eccmask || !nbc->errloc)
|
||||
goto fail;
|
||||
@@ -195,7 +182,6 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
|
||||
goto fail;
|
||||
|
||||
memset(erased_page, 0xff, eccsize);
|
||||
memset(nbc->eccmask, 0, eccbytes);
|
||||
encode_bch(nbc->bch, erased_page, eccsize, nbc->eccmask);
|
||||
kfree(erased_page);
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* This file contains an ECC algorithm that detects and corrects 1 bit
|
||||
* errors in a 256 byte block of data.
|
||||
@@ -11,21 +12,6 @@
|
||||
*
|
||||
* Information on how this algorithm works and how it was developed
|
||||
* can be found in Documentation/mtd/nand_ecc.txt
|
||||
*
|
||||
* This file 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 or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This file 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this file; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2017 Free Electrons
|
||||
* Copyright (C) 2017 NextThing Co
|
||||
*
|
||||
* Author: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/sizes.h>
|
||||
|
||||
@@ -1,22 +1,57 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2017 Free Electrons
|
||||
* Copyright (C) 2017 NextThing Co
|
||||
*
|
||||
* Author: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "internals.h"
|
||||
|
||||
#define MACRONIX_READ_RETRY_BIT BIT(0)
|
||||
#define MACRONIX_NUM_READ_RETRY_MODES 6
|
||||
|
||||
struct nand_onfi_vendor_macronix {
|
||||
u8 reserved;
|
||||
u8 reliability_func;
|
||||
} __packed;
|
||||
|
||||
static int macronix_nand_setup_read_retry(struct nand_chip *chip, int mode)
|
||||
{
|
||||
u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
|
||||
|
||||
if (!chip->parameters.supports_set_get_features ||
|
||||
!test_bit(ONFI_FEATURE_ADDR_READ_RETRY,
|
||||
chip->parameters.set_feature_list))
|
||||
return -ENOTSUPP;
|
||||
|
||||
feature[0] = mode;
|
||||
return nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature);
|
||||
}
|
||||
|
||||
static void macronix_nand_onfi_init(struct nand_chip *chip)
|
||||
{
|
||||
struct nand_parameters *p = &chip->parameters;
|
||||
struct nand_onfi_vendor_macronix *mxic;
|
||||
|
||||
if (!p->onfi)
|
||||
return;
|
||||
|
||||
mxic = (struct nand_onfi_vendor_macronix *)p->onfi->vendor;
|
||||
if ((mxic->reliability_func & MACRONIX_READ_RETRY_BIT) == 0)
|
||||
return;
|
||||
|
||||
chip->read_retries = MACRONIX_NUM_READ_RETRY_MODES;
|
||||
chip->setup_read_retry = macronix_nand_setup_read_retry;
|
||||
|
||||
if (p->supports_set_get_features) {
|
||||
bitmap_set(p->set_feature_list,
|
||||
ONFI_FEATURE_ADDR_READ_RETRY, 1);
|
||||
bitmap_set(p->get_feature_list,
|
||||
ONFI_FEATURE_ADDR_READ_RETRY, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Macronix AC series does not support using SET/GET_FEATURES to change
|
||||
* the timings unlike what is declared in the parameter page. Unflag
|
||||
@@ -65,6 +100,7 @@ static int macronix_nand_init(struct nand_chip *chip)
|
||||
chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
|
||||
|
||||
macronix_nand_fix_broken_get_timings(chip);
|
||||
macronix_nand_onfi_init(chip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2017 Free Electrons
|
||||
* Copyright (C) 2017 NextThing Co
|
||||
*
|
||||
* Author: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2017 Free Electrons
|
||||
* Copyright (C) 2017 NextThing Co
|
||||
*
|
||||
* Author: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "internals.h"
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2017 Free Electrons
|
||||
* Copyright (C) 2017 NextThing Co
|
||||
*
|
||||
* Author: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "internals.h"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* NAND flash simulator.
|
||||
*
|
||||
@@ -7,20 +8,6 @@
|
||||
*
|
||||
* Note: NS means "NAND Simulator".
|
||||
* Note: Input means input TO flash chip, output means output FROM chip.
|
||||
*
|
||||
* 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, 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "[nandsim]" fmt
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Overview:
|
||||
* Platform independent driver for NDFC (NanD Flash Controller)
|
||||
@@ -14,12 +15,6 @@
|
||||
* Copyright 2006 IBM
|
||||
* Copyright 2008 PIKA Technologies
|
||||
* Sean MacLennan <smaclennan@pikatech.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/mtd/rawnand.h>
|
||||
|
||||
@@ -1,18 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Error Location Module
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
|
||||
*
|
||||
* 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 DRIVER_NAME "omap-elm"
|
||||
|
||||
@@ -1,23 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright © 2004-2008 Simtec Electronics
|
||||
* http://armlinux.simtec.co.uk/
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* Samsung S3C2410/S3C2440/S3C2412 NAND driver
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "nand-s3c2410: " fmt
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
/* Max ECC buffer length */
|
||||
#define FMC2_MAX_ECC_BUF_LEN (FMC2_BCHDSRS_LEN * FMC2_MAX_SG)
|
||||
|
||||
#define FMC2_TIMEOUT_MS 1000
|
||||
|
||||
/* Timings */
|
||||
#define FMC2_THIZ 1
|
||||
#define FMC2_TIO 8000
|
||||
@@ -530,7 +532,8 @@ static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data,
|
||||
int ret;
|
||||
|
||||
ret = readl_relaxed_poll_timeout(fmc2->io_base + FMC2_SR,
|
||||
sr, sr & FMC2_SR_NWRF, 10, 1000);
|
||||
sr, sr & FMC2_SR_NWRF, 10,
|
||||
FMC2_TIMEOUT_MS);
|
||||
if (ret) {
|
||||
dev_err(fmc2->dev, "ham timeout\n");
|
||||
return ret;
|
||||
@@ -611,7 +614,7 @@ static int stm32_fmc2_bch_calculate(struct nand_chip *chip, const u8 *data,
|
||||
|
||||
/* Wait until the BCH code is ready */
|
||||
if (!wait_for_completion_timeout(&fmc2->complete,
|
||||
msecs_to_jiffies(1000))) {
|
||||
msecs_to_jiffies(FMC2_TIMEOUT_MS))) {
|
||||
dev_err(fmc2->dev, "bch timeout\n");
|
||||
stm32_fmc2_disable_bch_irq(fmc2);
|
||||
return -ETIMEDOUT;
|
||||
@@ -696,7 +699,7 @@ static int stm32_fmc2_bch_correct(struct nand_chip *chip, u8 *dat,
|
||||
|
||||
/* Wait until the decoding error is ready */
|
||||
if (!wait_for_completion_timeout(&fmc2->complete,
|
||||
msecs_to_jiffies(1000))) {
|
||||
msecs_to_jiffies(FMC2_TIMEOUT_MS))) {
|
||||
dev_err(fmc2->dev, "bch timeout\n");
|
||||
stm32_fmc2_disable_bch_irq(fmc2);
|
||||
return -ETIMEDOUT;
|
||||
@@ -969,7 +972,7 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf,
|
||||
|
||||
/* Wait end of sequencer transfer */
|
||||
if (!wait_for_completion_timeout(&fmc2->complete,
|
||||
msecs_to_jiffies(1000))) {
|
||||
msecs_to_jiffies(FMC2_TIMEOUT_MS))) {
|
||||
dev_err(fmc2->dev, "seq timeout\n");
|
||||
stm32_fmc2_disable_seq_irq(fmc2);
|
||||
dmaengine_terminate_all(dma_ch);
|
||||
@@ -981,7 +984,7 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf,
|
||||
|
||||
/* Wait DMA data transfer completion */
|
||||
if (!wait_for_completion_timeout(&fmc2->dma_data_complete,
|
||||
msecs_to_jiffies(100))) {
|
||||
msecs_to_jiffies(FMC2_TIMEOUT_MS))) {
|
||||
dev_err(fmc2->dev, "data DMA timeout\n");
|
||||
dmaengine_terminate_all(dma_ch);
|
||||
ret = -ETIMEDOUT;
|
||||
@@ -990,7 +993,7 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf,
|
||||
/* Wait DMA ECC transfer completion */
|
||||
if (!write_data && !raw) {
|
||||
if (!wait_for_completion_timeout(&fmc2->dma_ecc_complete,
|
||||
msecs_to_jiffies(100))) {
|
||||
msecs_to_jiffies(FMC2_TIMEOUT_MS))) {
|
||||
dev_err(fmc2->dev, "ECC DMA timeout\n");
|
||||
dmaengine_terminate_all(fmc2->dma_ecc_ch);
|
||||
ret = -ETIMEDOUT;
|
||||
@@ -1909,6 +1912,12 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
if (irq != -EPROBE_DEFER)
|
||||
dev_err(dev, "IRQ error missing or invalid\n");
|
||||
return irq;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(dev, irq, stm32_fmc2_irq, 0,
|
||||
dev_name(dev), fmc2);
|
||||
if (ret) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user