summaryrefslogtreecommitdiff
path: root/drivers/mtd/nand/raw/octeontx_bch.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/raw/octeontx_bch.c')
-rw-r--r--drivers/mtd/nand/raw/octeontx_bch.c422
1 files changed, 0 insertions, 422 deletions
diff --git a/drivers/mtd/nand/raw/octeontx_bch.c b/drivers/mtd/nand/raw/octeontx_bch.c
deleted file mode 100644
index 056a6857822..00000000000
--- a/drivers/mtd/nand/raw/octeontx_bch.c
+++ /dev/null
@@ -1,422 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2018 Marvell International Ltd.
- */
-
-#include <dm.h>
-#include <dm/of_access.h>
-#include <malloc.h>
-#include <memalign.h>
-#include <nand.h>
-#include <pci.h>
-#include <pci_ids.h>
-#include <time.h>
-#include <linux/bitfield.h>
-#include <linux/ctype.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/ioport.h>
-#include <linux/libfdt.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand_bch.h>
-#include <linux/mtd/nand_ecc.h>
-#include <asm/io.h>
-#include <asm/types.h>
-#include <asm/dma-mapping.h>
-#include <asm/arch/clock.h>
-#include "octeontx_bch.h"
-
-static LIST_HEAD(octeontx_bch_devices);
-static unsigned int num_vfs = BCH_NR_VF;
-static void *bch_pf;
-static void *bch_vf;
-static void *token;
-static bool bch_pf_initialized;
-static bool bch_vf_initialized;
-
-static int pci_enable_sriov(struct udevice *dev, int nr_virtfn)
-{
- int ret;
-
- ret = pci_sriov_init(dev, nr_virtfn);
- if (ret)
- printf("%s(%s): pci_sriov_init returned %d\n", __func__,
- dev->name, ret);
- return ret;
-}
-
-void *octeontx_bch_getv(void)
-{
- if (!bch_vf)
- return NULL;
- if (bch_vf_initialized && bch_pf_initialized)
- return bch_vf;
- else
- return NULL;
-}
-
-void octeontx_bch_putv(void *token)
-{
- bch_vf_initialized = !!token;
- bch_vf = token;
-}
-
-void *octeontx_bch_getp(void)
-{
- return token;
-}
-
-void octeontx_bch_putp(void *token)
-{
- bch_pf = token;
- bch_pf_initialized = !!token;
-}
-
-static int do_bch_init(struct bch_device *bch)
-{
- return 0;
-}
-
-static void bch_reset(struct bch_device *bch)
-{
- writeq(1, bch->reg_base + BCH_CTL);
- mdelay(2);
-}
-
-static void bch_disable(struct bch_device *bch)
-{
- writeq(~0ull, bch->reg_base + BCH_ERR_INT_ENA_W1C);
- writeq(~0ull, bch->reg_base + BCH_ERR_INT);
- bch_reset(bch);
-}
-
-static u32 bch_check_bist_status(struct bch_device *bch)
-{
- return readq(bch->reg_base + BCH_BIST_RESULT);
-}
-
-static int bch_device_init(struct bch_device *bch)
-{
- u64 bist;
- int rc;
-
- debug("%s: Resetting...\n", __func__);
- /* Reset the PF when probed first */
- bch_reset(bch);
-
- debug("%s: Checking BIST...\n", __func__);
- /* Check BIST status */
- bist = (u64)bch_check_bist_status(bch);
- if (bist) {
- dev_err(dev, "BCH BIST failed with code 0x%llx\n", bist);
- return -ENODEV;
- }
-
- /* Get max VQs/VFs supported by the device */
-
- bch->max_vfs = pci_sriov_get_totalvfs(bch->dev);
- debug("%s: %d vfs\n", __func__, bch->max_vfs);
- if (num_vfs > bch->max_vfs) {
- dev_warn(dev, "Num of VFs to enable %d is greater than max available. Enabling %d VFs.\n",
- num_vfs, bch->max_vfs);
- num_vfs = bch->max_vfs;
- }
- bch->vfs_enabled = bch->max_vfs;
- /* Get number of VQs/VFs to be enabled */
- /* TODO: Get CLK frequency */
- /* Reset device parameters */
-
- debug("%s: Doing initialization\n", __func__);
- rc = do_bch_init(bch);
-
- return rc;
-}
-
-static int bch_sriov_configure(struct udevice *dev, int numvfs)
-{
- struct bch_device *bch = dev_get_priv(dev);
- int ret = -EBUSY;
-
- debug("%s(%s, %d), bch: %p, vfs_in_use: %d, enabled: %d\n", __func__,
- dev->name, numvfs, bch, bch->vfs_in_use, bch->vfs_enabled);
- if (bch->vfs_in_use)
- goto exit;
-
- ret = 0;
-
- if (numvfs > 0) {
- debug("%s: Enabling sriov\n", __func__);
- ret = pci_enable_sriov(dev, numvfs);
- if (ret == 0) {
- bch->flags |= BCH_FLAG_SRIOV_ENABLED;
- ret = numvfs;
- bch->vfs_enabled = numvfs;
- }
- }
-
- debug("VFs enabled: %d\n", ret);
-exit:
- debug("%s: Returning %d\n", __func__, ret);
- return ret;
-}
-
-static int octeontx_pci_bchpf_probe(struct udevice *dev)
-{
- struct bch_device *bch;
- int ret;
-
- debug("%s(%s)\n", __func__, dev->name);
- bch = dev_get_priv(dev);
- if (!bch)
- return -ENOMEM;
-
- bch->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0,
- PCI_REGION_TYPE, PCI_REGION_MEM);
- bch->dev = dev;
-
- debug("%s: base address: %p\n", __func__, bch->reg_base);
- ret = bch_device_init(bch);
- if (ret) {
- printf("%s(%s): init returned %d\n", __func__, dev->name, ret);
- return ret;
- }
- INIT_LIST_HEAD(&bch->list);
- list_add(&bch->list, &octeontx_bch_devices);
- token = (void *)dev;
-
- debug("%s: Configuring SRIOV\n", __func__);
- bch_sriov_configure(dev, num_vfs);
- debug("%s: Done.\n", __func__);
- octeontx_bch_putp(bch);
-
- return 0;
-}
-
-static const struct pci_device_id octeontx_bchpf_pci_id_table[] = {
- { PCI_VDEVICE(CAVIUM, PCI_DEVICE_ID_CAVIUM_BCH) },
- {},
-};
-
-static const struct pci_device_id octeontx_bchvf_pci_id_table[] = {
- { PCI_VDEVICE(CAVIUM, PCI_DEVICE_ID_CAVIUM_BCHVF)},
- {},
-};
-
-/**
- * Given a data block calculate the ecc data and fill in the response
- *
- * @param[in] block 8-byte aligned pointer to data block to calculate ECC
- * @param block_size Size of block in bytes, must be a multiple of two.
- * @param bch_level Number of errors that must be corrected. The number of
- * parity bytes is equal to ((15 * bch_level) + 7) / 8.
- * Must be 4, 8, 16, 24, 32, 40, 48, 56, 60 or 64.
- * @param[out] ecc 8-byte aligned pointer to where ecc data should go
- * @param[in] resp pointer to where responses will be written.
- *
- * Return: Zero on success, negative on failure.
- */
-int octeontx_bch_encode(struct bch_vf *vf, dma_addr_t block, u16 block_size,
- u8 bch_level, dma_addr_t ecc, dma_addr_t resp)
-{
- union bch_cmd cmd;
- int rc;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.s.cword.ecc_gen = eg_gen;
- cmd.s.cword.ecc_level = bch_level;
- cmd.s.cword.size = block_size;
-
- cmd.s.oword.ptr = ecc;
- cmd.s.iword.ptr = block;
- cmd.s.rword.ptr = resp;
- rc = octeontx_cmd_queue_write(QID_BCH, 1,
- sizeof(cmd) / sizeof(uint64_t), cmd.u);
- if (rc)
- return -1;
-
- octeontx_bch_write_doorbell(1, vf);
-
- return 0;
-}
-
-/**
- * Given a data block and ecc data correct the data block
- *
- * @param[in] block_ecc_in 8-byte aligned pointer to data block with ECC
- * data concatenated to the end to correct
- * @param block_size Size of block in bytes, must be a multiple of
- * two.
- * @param bch_level Number of errors that must be corrected. The
- * number of parity bytes is equal to
- * ((15 * bch_level) + 7) / 8.
- * Must be 4, 8, 16, 24, 32, 40, 48, 56, 60 or 64.
- * @param[out] block_out 8-byte aligned pointer to corrected data buffer.
- * This should not be the same as block_ecc_in.
- * @param[in] resp pointer to where responses will be written.
- *
- * Return: Zero on success, negative on failure.
- */
-
-int octeontx_bch_decode(struct bch_vf *vf, dma_addr_t block_ecc_in,
- u16 block_size, u8 bch_level,
- dma_addr_t block_out, dma_addr_t resp)
-{
- union bch_cmd cmd;
- int rc;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.s.cword.ecc_gen = eg_correct;
- cmd.s.cword.ecc_level = bch_level;
- cmd.s.cword.size = block_size;
-
- cmd.s.oword.ptr = block_out;
- cmd.s.iword.ptr = block_ecc_in;
- cmd.s.rword.ptr = resp;
- rc = octeontx_cmd_queue_write(QID_BCH, 1,
- sizeof(cmd) / sizeof(uint64_t), cmd.u);
- if (rc)
- return -1;
-
- octeontx_bch_write_doorbell(1, vf);
- return 0;
-}
-EXPORT_SYMBOL(octeontx_bch_decode);
-
-int octeontx_bch_wait(struct bch_vf *vf, union bch_resp *resp,
- dma_addr_t handle)
-{
- ulong start = get_timer(0);
-
- __iormb(); /* HW is updating *resp */
- while (!resp->s.done && get_timer(start) < 10)
- __iormb(); /* HW is updating *resp */
-
- if (resp->s.done)
- return 0;
-
- return -ETIMEDOUT;
-}
-
-struct bch_q octeontx_bch_q[QID_MAX];
-
-static int octeontx_cmd_queue_initialize(struct udevice *dev, int queue_id,
- int max_depth, int fpa_pool,
- int pool_size)
-{
- /* some params are for later merge with CPT or cn83xx */
- struct bch_q *q = &octeontx_bch_q[queue_id];
- unsigned long paddr;
- u64 *chunk_buffer;
- int chunk = max_depth + 1;
- int i, size;
-
- if ((unsigned int)queue_id >= QID_MAX)
- return -EINVAL;
- if (max_depth & chunk) /* must be 2^N - 1 */
- return -EINVAL;
-
- size = NQS * chunk * sizeof(u64);
- chunk_buffer = dma_alloc_coherent(size, &paddr);
- if (!chunk_buffer)
- return -ENOMEM;
-
- q->base_paddr = paddr;
- q->dev = dev;
- q->index = 0;
- q->max_depth = max_depth;
- q->pool_size_m1 = pool_size;
- q->base_vaddr = chunk_buffer;
-
- for (i = 0; i < NQS; i++) {
- u64 *ixp;
- int inext = (i + 1) * chunk - 1;
- int j = (i + 1) % NQS;
- int jnext = j * chunk;
- dma_addr_t jbase = q->base_paddr + jnext * sizeof(u64);
-
- ixp = &chunk_buffer[inext];
- *ixp = jbase;
- }
-
- return 0;
-}
-
-static int octeontx_pci_bchvf_probe(struct udevice *dev)
-{
- struct bch_vf *vf;
- union bch_vqx_ctl ctl;
- union bch_vqx_cmd_buf cbuf;
- int err;
-
- debug("%s(%s)\n", __func__, dev->name);
- vf = dev_get_priv(dev);
- if (!vf)
- return -ENOMEM;
-
- vf->dev = dev;
-
- /* Map PF's configuration registers */
- vf->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0,
- PCI_REGION_TYPE, PCI_REGION_MEM);
- debug("%s: reg base: %p\n", __func__, vf->reg_base);
-
- err = octeontx_cmd_queue_initialize(dev, QID_BCH, QDEPTH - 1, 0,
- sizeof(union bch_cmd) * QDEPTH);
- if (err) {
- dev_err(dev, "octeontx_cmd_queue_initialize() failed\n");
- goto release;
- }
-
- ctl.u = readq(vf->reg_base + BCH_VQX_CTL(0));
-
- cbuf.u = 0;
- cbuf.s.ldwb = 1;
- cbuf.s.dfb = 1;
- cbuf.s.size = QDEPTH;
- writeq(cbuf.u, vf->reg_base + BCH_VQX_CMD_BUF(0));
-
- writeq(ctl.u, vf->reg_base + BCH_VQX_CTL(0));
-
- writeq(octeontx_bch_q[QID_BCH].base_paddr,
- vf->reg_base + BCH_VQX_CMD_PTR(0));
-
- octeontx_bch_putv(vf);
-
- debug("%s: bch vf initialization complete\n", __func__);
-
- if (octeontx_bch_getv())
- return octeontx_pci_nand_deferred_probe();
-
- return -1;
-
-release:
- return err;
-}
-
-static int octeontx_pci_bchpf_remove(struct udevice *dev)
-{
- struct bch_device *bch = dev_get_priv(dev);
-
- bch_disable(bch);
- return 0;
-}
-
-U_BOOT_DRIVER(octeontx_pci_bchpf) = {
- .name = BCHPF_DRIVER_NAME,
- .id = UCLASS_MISC,
- .probe = octeontx_pci_bchpf_probe,
- .remove = octeontx_pci_bchpf_remove,
- .priv_auto = sizeof(struct bch_device),
- .flags = DM_FLAG_OS_PREPARE,
-};
-
-U_BOOT_DRIVER(octeontx_pci_bchvf) = {
- .name = BCHVF_DRIVER_NAME,
- .id = UCLASS_MISC,
- .probe = octeontx_pci_bchvf_probe,
- .priv_auto = sizeof(struct bch_vf),
-};
-
-U_BOOT_PCI_DEVICE(octeontx_pci_bchpf, octeontx_bchpf_pci_id_table);
-U_BOOT_PCI_DEVICE(octeontx_pci_bchvf, octeontx_bchvf_pci_id_table);