[WIP][FYI] mtd: bcm53xxnflash: add driver for NAND on new BCMA SoCs
Rafał Miłecki
zajec5 at gmail.com
Mon Feb 24 04:25:46 EST 2014
---
It doesn't implement NAND operations in any way yet. I'll continue working on
this, but wanted avoid duplicating work with sb else.
---
drivers/mtd/nand/Kconfig | 9 +++
drivers/mtd/nand/Makefile | 1 +
drivers/mtd/nand/bcm53xxnflash.c | 144 +++++++++++++++++++++++++++++++++++++++
drivers/mtd/nand/bcm53xxnflash.h | 126 ++++++++++++++++++++++++++++++++++
4 files changed, 280 insertions(+)
create mode 100644 drivers/mtd/nand/bcm53xxnflash.c
create mode 100644 drivers/mtd/nand/bcm53xxnflash.h
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index a5bb738..d33c80a 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -397,6 +397,15 @@ config MTD_NAND_BCM47XXNFLASH
registered by bcma as platform devices. This enables driver for
NAND flash memories. For now only BCM4706 is supported.
+config MTD_NAND_BCM53XXNFLASH
+ tristate "Support for BCMA NAND attached as standalone core"
+ depends on BCMA
+ help
+ This enables support for NAND flash memories attached to BCMA bus as
+ separated bus cores. They most probably can be found only on ARM based
+ Broadcom SoCs. System reports such devices as:
+ bcma: bus0: Core N found: NAND flash controller (...)
+
config MTD_NAND_PLATFORM
tristate "Support for generic platform NAND driver"
depends on HAS_IOMEM
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 542b568..680c356 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -49,5 +49,6 @@ obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o
obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/
obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o
obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/
+obj-$(CONFIG_MTD_NAND_BCM53XXNFLASH) += bcm53xxnflash.o
nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/bcm53xxnflash.c b/drivers/mtd/nand/bcm53xxnflash.c
new file mode 100644
index 0000000..9934d9a
--- /dev/null
+++ b/drivers/mtd/nand/bcm53xxnflash.c
@@ -0,0 +1,144 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
+#include <linux/platform_device.h>
+#include <linux/bcma/bcma.h>
+
+#include "bcm53xxnflash.h"
+
+MODULE_DESCRIPTION("NAND flash driver for BCMA bus");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("RafaÅ MiÅecki");
+
+static void b53n_cmd(struct b53n *b53n, u32 code)
+{
+ bcma_write32(b53n->core, B53N_CMD_START, code);
+}
+
+static int b53n_poll(struct b53n *b53n)
+{
+ u32 bits = B53_INTFC_ST_CTRL_READY | B53_INTFC_ST_FLASH_READY;
+ int i;
+
+ for (i = 0; i < 10000; i++) {
+ if ((bcma_read32(b53n->core, B53N_INTFC_STATUS) & bits) == bits) {
+ pr_info("Polling success in %d loop\n", i);
+ return 0;
+ }
+ }
+
+ pr_err("Polling timeout!\n");
+ return -EBUSY;
+}
+
+static int b53n_init(struct b53n *b53n)
+{
+ struct bcma_device *core = b53n->core;
+ u32 id, id_ext;
+ int i, err;
+
+ /* Verify access */
+ b53n_cmd(b53n, B53N_CMD_START_ID_RD);
+ err = b53n_poll(b53n);
+ if (err)
+ return err;
+
+ /* Cache ID, we need it to fake read_byte for NAND_CMD_READID */
+ bcma_awrite32(core, BCMA_IOCTL,
+ bcma_aread32(core, BCMA_IOCTL) | B53N_BCMA_IOCTL_APB_LITTLE_ENDIAN);
+ id = bcma_read32(core, B53N_FLASH_DEVICE_ID);
+ id_ext = bcma_read32(core, B53N_FLASH_DEVICE_ID_EXT);
+ bcma_awrite32(core, BCMA_IOCTL,
+ bcma_aread32(core, BCMA_IOCTL) & ~B53N_BCMA_IOCTL_APB_LITTLE_ENDIAN);
+ for (i = 0; i < 5; i++) {
+ if (i < 4)
+ b53n->id_data[i] = (id >> (8 * i)) & 0xff;
+ else
+ b53n->id_data[i] = (id_ext >> (8 * (i - 4))) & 0xff;
+ }
+
+ pr_info("Device ID: 0x%08X\n", bcma_read32(core, B53N_FLASH_DEVICE_ID));
+
+ return 0;
+}
+
+/**************************************************
+ * BCMA
+ **************************************************/
+
+static const struct bcma_device_id bcm53xxnflash_bcma_tbl[] = {
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NAND, BCMA_ANY_REV, BCMA_ANY_CLASS),
+ BCMA_CORETABLE_END
+};
+MODULE_DEVICE_TABLE(bcma, bcm53xxnflash_bcma_tbl);
+
+static int bcm53xxnflash_bcma_probe(struct bcma_device *core)
+{
+ struct b53n *b53n;
+ int err;
+
+ if (core->bus->drv_cc.core->id.rev != 42) {
+ pr_err("NAND on SoC with unsupported ChipCommon rev\n");
+ return -ENOTSUPP;
+ }
+
+ if (bcma_read32(core, B53N_FLASH_DEVICE_ID) == 0) {
+ pr_err("Unable to read NAND registers\n");
+ return -ENODEV;
+ }
+
+ b53n = kzalloc(sizeof(*b53n), GFP_KERNEL);
+ if (!b53n)
+ return -ENOMEM;
+ b53n->core = core;
+ bcma_set_drvdata(core, b53n);
+
+ err = b53n_init(b53n);
+ if (err) {
+ bcma_set_drvdata(core, NULL);
+ kfree(b53n);
+ return err;
+ }
+
+ return 0;
+}
+
+static void bcm53xxnflash_bcma_remove(struct bcma_device *core)
+{
+ struct b53n *b53n = bcma_get_drvdata(core);
+
+ kfree(b53n);
+}
+
+static struct bcma_driver bcm53xxnflash_bcma_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = bcm53xxnflash_bcma_tbl,
+ .probe = bcm53xxnflash_bcma_probe,
+ .remove = bcm53xxnflash_bcma_remove,
+};
+
+/**************************************************
+ * Init & exit
+ **************************************************/
+
+static int __init bcm53xxnflash_init(void)
+{
+ int err;
+
+ err = bcma_driver_register(&bcm53xxnflash_bcma_driver);
+ if (err)
+ pr_err("Failed to register bcma driver: %d\n", err);
+
+ return err;
+}
+
+static void __exit bcm53xxnflash_exit(void)
+{
+ bcma_driver_unregister(&bcm53xxnflash_bcma_driver);
+}
+
+module_init(bcm53xxnflash_init);
+module_exit(bcm53xxnflash_exit);
diff --git a/drivers/mtd/nand/bcm53xxnflash.h b/drivers/mtd/nand/bcm53xxnflash.h
new file mode 100644
index 0000000..cf92ac0
--- /dev/null
+++ b/drivers/mtd/nand/bcm53xxnflash.h
@@ -0,0 +1,126 @@
+#ifndef __BCM53XXNFLASH_H
+#define __BCM53XXNFLASH_H
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+
+#define B53N_FLASH_DEVICE_ID 0x194
+#define B53N_REVISION 0x000
+#define B53N_CMD_START 0x004
+#define B53N_CMD_START_NULL 0x00000000
+#define B53N_CMD_START_PAGE_RD 0x01000000
+#define B53N_CMD_START_SPARE_RD 0x02000000
+#define B53N_CMD_START_STATUS_RD 0x03000000
+#define B53N_CMD_START_PAGE_PROG 0x04000000
+#define B53N_CMD_START_SPARE_PROG 0x05000000
+#define B53N_CMD_START_COPY_BACK 0x06000000
+#define B53N_CMD_START_ID_RD 0x07000000
+#define B53N_CMD_START_BLOCK_ERASE 0x08000000
+#define B53N_CMD_START_FLASH_RESET 0x09000000
+#define B53N_CMD_START_LOCK 0x0a000000
+#define B53N_CMD_START_LOCK_DOWN 0x0b000000
+#define B53N_CMD_START_UNLOCK 0x0c000000
+#define B53N_CMD_START_LOCK_STATUS 0x0d000000
+#define B53N_CMD_START_PARAMETER_READ 0x0e000000
+#define B53N_CMD_START_PARAMETER_CHANGE_COL 0x0f000000
+#define B53N_CMD_START_LOW_LEVEL_OP 0x10000000
+#define B53N_CMD_START_PAGE_READ_MULTI 0x11000000
+#define B53N_CMD_START_STATUS_READ_MULTI 0x12000000
+#define B53N_CMD_START_OPCODE_MASK 0x1f000000
+#define B53N_CMD_EXT_ADDRESS 0x008
+#define B53N_CMD_EXT_ADDR_CS_SEL_MASK 0x00070000
+#define B53N_CMD_EXT_ADDR_CS_SEL_SHIFT 16
+#define B53N_CMD_EXT_ADDR_EXT_ADDR_MASK 0x0000ffff
+#define B53N_CMD_ADDRESS 0x00c
+#define B53N_CMD_END_ADDRESS 0x010
+#define B53N_INTFC_STATUS 0x014
+#define B53_INTFC_ST_CTRL_READY 0x80000000
+#define B53_INTFC_ST_FLASH_READY 0x40000000
+#define B53_INTFC_ST_CACHE_VALID 0x20000000
+#define B53_INTFC_ST_SPARE_VALID 0x10000000
+#define B53_INTFC_ST_ERASED 0x08000000
+#define B53_INTFC_ST_STATUS 0x000000ff
+#define B53_INTFC_ST_STATUS_FAIL 0x00000001
+#define B53N_CS_NAND_SELECT 0x018
+#define B53N_CS_NAND_XOR 0x01c
+#define B53N_LL_OP 0x020
+#define B53N_MPLANE_BASE_EXT_ADDRESS 0x024
+#define B53N_MPLANE_BASE_ADDRESS 0x028
+#define B53N_ACC_CONTROL_CS0 0x050
+#define B53N_CONFIG_CS0 0x054
+#define B53N_CFG_CS0_CONFIG_LOCK 0x80000000
+#define B53N_CFG_CS0_BLOCK_SIZE_MASK 0x70000000
+#define B53N_CFG_CS0_BLOCK_SIZE_SHIFT 28
+#define B53N_CFG_CS0_DEVICE_SIZE_MASK 0x0f000000
+#define B53N_CFG_CS0_DEVICE_SIZE_SHIFT 24
+#define B53N_CFG_CS0_DEVICE_WIDTH 0x00800000
+#define B53N_CFG_CS0_PAGE_SIZE_MASK 0x00300000
+#define B53N_CFG_CS0_PAGE_SIZE_SHIFT 20
+#define B53N_CFG_CS0_FULL_ADDR_BYTES_MASK 0x00070000
+#define B53N_CFG_CS0_FULL_ADDR_BYTES_SHIFT 16
+#define B53N_CFG_CS0_COL_ADDR_BYTES_MASK 0x00007000
+#define B53N_CFG_CS0_COL_ADDR_BYTES_SHIFT 12
+#define B53N_CFG_CS0_BLK_ADDR_BYTES_MASK 0x00000700
+#define B53N_CFG_CS0_BLK_ADDR_BYTES_SHIFT 8
+#define B53N_TIMING_1_CS0 0x058
+#define B53N_TIMING_2_CS0 0x05c
+#define B53N_ACC_CONTROL_CS1 0x060
+#define B53N_CONFIG_CS1 0x064
+#define B53N_TIMING_1_CS1 0x068
+#define B53N_TIMING_2_CS1 0x06c
+#define B53N_CORR_STAT_THRESHOLD 0x0c0
+#define B53N_BLK_WR_PROTECT 0x0c8
+#define B53N_MULTIPLANE_OPCODES_1 0x0cc
+#define B53N_MULTIPLANE_OPCODES_2 0x0d0
+#define B53N_MULTIPLANE_CTRL 0x0d4
+#define B53N_UNCORR_ERROR_COUNT 0x0fc
+#define B53N_CORR_ERROR_COUNT 0x100
+#define B53N_READ_ERROR_COUNT 0x104
+#define B53N_BLOCK_LOCK_STATUS 0x108
+#define B53N_ECC_CORR_EXT_ADDR 0x10c
+#define B53N_ECC_CORR_ADDR 0x110
+#define B53N_ECC_UNC_EXT_ADDR 0x114
+#define B53N_ECC_UNC_ADDR 0x118
+#define B53N_FLASH_READ_EXT_ADDR 0x11c
+#define B53N_FLASH_READ_ADDR 0x120
+#define B53N_PROGRAM_PAGE_EXT_ADDR 0x124
+#define B53N_PROGRAM_PAGE_ADDR 0x128
+#define B53N_COPY_BACK_EXT_ADDR 0x12c
+#define B53N_COPY_BACK_ADDR 0x130
+#define B53N_BLOCK_ERASE_EXT_ADDR 0x134
+#define B53N_BLOCK_ERASE_ADDR 0x138
+#define B53N_INV_READ_EXT_ADDR 0x13c
+#define B53N_INV_READ_ADDR 0x140
+#define B53N_INIT_STATUS 0x144
+#define B53N_ONFI_STATUS 0x148
+#define B53N_ONFI_DEBUG_DATA 0x14c
+#define B53N_SEMAPHORE 0x150
+#define B53N_FLASH_DEVICE_ID 0x194
+#define B53N_FLASH_DEVICE_ID_EXT 0x198
+#define B53N_LL_RDDATA 0x19c
+#define B53N_SPARE_AREA_READ_OFS_BASE 0x200 /* 16 registers, up to 0x23c */
+#define B53N_SPARE_AREA_WRITE_OFS_BASE 0x280 /* 16 registers, up to 0x2bc */
+#define B53N_FLASH_CACHE_BASE 0x400 /* 128 registers, up to 0x5fc */
+#define B53N_DIRECT_READ_RD_MISS 0xf00
+#define B53N_BLOCK_ERASE_COMPLETE 0xf04
+#define B53N_COPY_BACK_COMPLETE 0xf08
+#define B53N_PROGRAM_PAGE_COMPLETE 0xf0c
+#define B53N_NO_CTLR_READY 0xf10
+#define B53N_NAND_RB_B 0xf14
+#define B53N_ECC_MIPS_UNCORR 0xf18
+#define B53N_ECC_MIPS_CORR 0xf1c
+
+/* BCMA core specific IO Control (BCMA_IOCTL) flags */
+#define B53N_BCMA_IOCTL_RO_CTRL_READY 0x00000001
+#define B53N_BCMA_IOCTL_APB_LITTLE_ENDIAN 0x01000000
+
+/* BCMA core specific IO status (BCMA_IOST) flags */
+#define B53N_BCMA_IOST_ATTACHED 0x00000800
+
+struct b53n {
+ struct bcma_device *core;
+
+ u8 id_data[8];
+};
+
+#endif /* BCM53XXNFLASH */
--
1.8.4.5
More information about the linux-mtd
mailing list