cregit-Linux how code gets into the kernel

Release 4.11 drivers/mtd/nand/socrates_nand.c

Directory: drivers/mtd/nand
/*
 * drivers/mtd/nand/socrates_nand.c
 *
 *  Copyright © 2008 Ilya Yanok, Emcraft Systems
 *
 *
 * 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.
 *
 */

#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/io.h>


#define FPGA_NAND_CMD_MASK		(0x7 << 28)

#define FPGA_NAND_CMD_COMMAND		(0x0 << 28)

#define FPGA_NAND_CMD_ADDR		(0x1 << 28)

#define FPGA_NAND_CMD_READ		(0x2 << 28)

#define FPGA_NAND_CMD_WRITE		(0x3 << 28)

#define FPGA_NAND_BUSY			(0x1 << 15)

#define FPGA_NAND_ENABLE		(0x1 << 31)

#define FPGA_NAND_DATA_SHIFT		16


struct socrates_nand_host {
	
struct nand_chip	nand_chip;
	
void __iomem		*io_base;
	
struct device		*dev;
};

/**
 * socrates_nand_write_buf -  write buffer to chip
 * @mtd:        MTD device structure
 * @buf:        data buffer
 * @len:        number of bytes to write
 */

static void socrates_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { int i; struct nand_chip *this = mtd_to_nand(mtd); struct socrates_nand_host *host = nand_get_controller_data(this); for (i = 0; i < len; i++) { out_be32(host->io_base, FPGA_NAND_ENABLE | FPGA_NAND_CMD_WRITE | (buf[i] << FPGA_NAND_DATA_SHIFT)); } }

Contributors

PersonTokensPropCommitsCommitProp
Wolfgang Grandegger7192.21%133.33%
Boris Brezillon67.79%266.67%
Total77100.00%3100.00%

/** * socrates_nand_read_buf - read chip data into buffer * @mtd: MTD device structure * @buf: buffer to store date * @len: number of bytes to read */
static void socrates_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { int i; struct nand_chip *this = mtd_to_nand(mtd); struct socrates_nand_host *host = nand_get_controller_data(this); uint32_t val; val = FPGA_NAND_ENABLE | FPGA_NAND_CMD_READ; out_be32(host->io_base, val); for (i = 0; i < len; i++) { buf[i] = (in_be32(host->io_base) >> FPGA_NAND_DATA_SHIFT) & 0xff; } }

Contributors

PersonTokensPropCommitsCommitProp
Wolfgang Grandegger8693.48%133.33%
Boris Brezillon66.52%266.67%
Total92100.00%3100.00%

/** * socrates_nand_read_byte - read one byte from the chip * @mtd: MTD device structure */
static uint8_t socrates_nand_read_byte(struct mtd_info *mtd) { uint8_t byte; socrates_nand_read_buf(mtd, &byte, sizeof(byte)); return byte; }

Contributors

PersonTokensPropCommitsCommitProp
Wolfgang Grandegger30100.00%1100.00%
Total30100.00%1100.00%

/** * socrates_nand_read_word - read one word from the chip * @mtd: MTD device structure */
static uint16_t socrates_nand_read_word(struct mtd_info *mtd) { uint16_t word; socrates_nand_read_buf(mtd, (uint8_t *)&word, sizeof(word)); return word; }

Contributors

PersonTokensPropCommitsCommitProp
Wolfgang Grandegger34100.00%1100.00%
Total34100.00%1100.00%

/* * Hardware specific access to control-lines */
static void socrates_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *nand_chip = mtd_to_nand(mtd); struct socrates_nand_host *host = nand_get_controller_data(nand_chip); uint32_t val; if (cmd == NAND_CMD_NONE) return; if (ctrl & NAND_CLE) val = FPGA_NAND_CMD_COMMAND; else val = FPGA_NAND_CMD_ADDR; if (ctrl & NAND_NCE) val |= FPGA_NAND_ENABLE; val |= (cmd & 0xff) << FPGA_NAND_DATA_SHIFT; out_be32(host->io_base, val); }

Contributors

PersonTokensPropCommitsCommitProp
Wolfgang Grandegger8693.48%133.33%
Boris Brezillon66.52%266.67%
Total92100.00%3100.00%

/* * Read the Device Ready pin. */
static int socrates_nand_device_ready(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); struct socrates_nand_host *host = nand_get_controller_data(nand_chip); if (in_be32(host->io_base) & FPGA_NAND_BUSY) return 0; /* busy */ return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Wolfgang Grandegger4387.76%133.33%
Boris Brezillon612.24%266.67%
Total49100.00%3100.00%

/* * Probe for the NAND device. */
static int socrates_nand_probe(struct platform_device *ofdev) { struct socrates_nand_host *host; struct mtd_info *mtd; struct nand_chip *nand_chip; int res; /* Allocate memory for the device structure (and zero it) */ host = devm_kzalloc(&ofdev->dev, sizeof(*host), GFP_KERNEL); if (!host) return -ENOMEM; host->io_base = of_iomap(ofdev->dev.of_node, 0); if (host->io_base == NULL) { dev_err(&ofdev->dev, "ioremap failed\n"); return -EIO; } nand_chip = &host->nand_chip; mtd = nand_to_mtd(nand_chip); host->dev = &ofdev->dev; /* link the private data structures */ nand_set_controller_data(nand_chip, host); nand_set_flash_node(nand_chip, ofdev->dev.of_node); mtd->name = "socrates_nand"; mtd->dev.parent = &ofdev->dev; /*should never be accessed directly */ nand_chip->IO_ADDR_R = (void *)0xdeadbeef; nand_chip->IO_ADDR_W = (void *)0xdeadbeef; nand_chip->cmd_ctrl = socrates_nand_cmd_ctrl; nand_chip->read_byte = socrates_nand_read_byte; nand_chip->read_word = socrates_nand_read_word; nand_chip->write_buf = socrates_nand_write_buf; nand_chip->read_buf = socrates_nand_read_buf; nand_chip->dev_ready = socrates_nand_device_ready; nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */ nand_chip->ecc.algo = NAND_ECC_HAMMING; /* TODO: I have no idea what real delay is. */ nand_chip->chip_delay = 20; /* 20us command delay time */ dev_set_drvdata(&ofdev->dev, host); res = nand_scan(mtd, 1); if (res) goto out; res = mtd_device_register(mtd, NULL, 0); if (!res) return res; nand_release(mtd); out: iounmap(host->io_base); return res; }

Contributors

PersonTokensPropCommitsCommitProp
Wolfgang Grandegger24280.94%18.33%
Sachin Kamat155.02%216.67%
Brian Norris124.01%18.33%
Boris Brezillon113.68%216.67%
Rafał Miłecki82.68%18.33%
Masahiro Yamada41.34%18.33%
Anatolij Gustschin31.00%18.33%
Dmitry Baryshkov31.00%216.67%
Grant C. Likely10.33%18.33%
Total299100.00%12100.00%

/* * Remove a NAND device. */
static int socrates_nand_remove(struct platform_device *ofdev) { struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev); struct mtd_info *mtd = nand_to_mtd(&host->nand_chip); nand_release(mtd); iounmap(host->io_base); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Wolfgang Grandegger4790.38%133.33%
Boris Brezillon47.69%133.33%
Grant C. Likely11.92%133.33%
Total52100.00%3100.00%

static const struct of_device_id socrates_nand_match[] = { { .compatible = "abb,socrates-nand", }, {}, }; MODULE_DEVICE_TABLE(of, socrates_nand_match); static struct platform_driver socrates_nand_driver = { .driver = { .name = "socrates_nand", .of_match_table = socrates_nand_match, }, .probe = socrates_nand_probe, .remove = socrates_nand_remove, }; module_platform_driver(socrates_nand_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ilya Yanok"); MODULE_DESCRIPTION("NAND driver for Socrates board");

Overall Contributors

PersonTokensPropCommitsCommitProp
Wolfgang Grandegger78788.83%15.56%
Boris Brezillon394.40%316.67%
Sachin Kamat151.69%211.11%
Brian Norris121.35%15.56%
Grant C. Likely91.02%316.67%
Rafał Miłecki80.90%15.56%
Masahiro Yamada40.45%15.56%
Dmitry Baryshkov30.34%211.11%
Rob Herring30.34%15.56%
Anatolij Gustschin30.34%15.56%
Axel Lin20.23%15.56%
Márton Németh10.11%15.56%
Total886100.00%18100.00%
Directory: drivers/mtd/nand
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.