linux/drivers/mtd/devices/spear_smi.c

/*
 * SMI (Serial Memory Controller) device driver for Serial NOR Flash on
 * SPEAr platform
 * The serial nor interface is largely based on m25p80.c, however the SPI
 * interface has been replaced by SMI.
 *
 * Copyright © 2010 STMicroelectronics.
 * Ashish Priyadarshi
 * Shiraz Hashim <[email protected]>
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2. This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/param.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/spear_smi.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/of.h>
#include <linux/of_address.h>

/* SMI clock rate */
#define SMI_MAX_CLOCK_FREQ

/* MAX time out to safely come out of a erase or write busy conditions */
#define SMI_PROBE_TIMEOUT
#define SMI_MAX_TIME_OUT

/* timeout for command completion */
#define SMI_CMD_TIMEOUT

/* registers of smi */
#define SMI_CR1
#define SMI_CR2
#define SMI_SR
#define SMI_TR
#define SMI_RR

/* defines for control_reg 1 */
#define BANK_EN
#define DSEL_TIME
#define SW_MODE
#define WB_MODE
#define FAST_MODE
#define HOLD1

/* defines for control_reg 2 */
#define SEND
#define TFIE
#define WCIE
#define RD_STATUS_REG
#define WE

#define TX_LEN_SHIFT
#define RX_LEN_SHIFT
#define BANK_SHIFT

/* defines for status register */
#define SR_WIP
#define SR_WEL
#define SR_BP0
#define SR_BP1
#define SR_BP2
#define SR_SRWD
#define TFF
#define WCF
#define ERF1
#define ERF2

#define WM_SHIFT

/* flash opcodes */
#define OPCODE_RDID

/* Flash Device Ids maintenance section */

/* data structure to maintain flash ids from different vendors */
struct flash_device {};

#define FLASH_ID(n, es, id, psize, ssize, size)

static struct flash_device flash_devices[] =;

/* Define spear specific structures */

struct spear_snor_flash;

/**
 * struct spear_smi - Structure for SMI Device
 *
 * @clk: functional clock
 * @status: current status register of SMI.
 * @clk_rate: functional clock rate of SMI (default: SMI_MAX_CLOCK_FREQ)
 * @lock: lock to prevent parallel access of SMI.
 * @io_base: base address for registers of SMI.
 * @pdev: platform device
 * @cmd_complete: queue to wait for command completion of NOR-flash.
 * @num_flashes: number of flashes actually present on board.
 * @flash: separate structure for each Serial NOR-flash attached to SMI.
 */
struct spear_smi {};

/**
 * struct spear_snor_flash - Structure for Serial NOR Flash
 *
 * @bank: Bank number(0, 1, 2, 3) for each NOR-flash.
 * @dev_id: Device ID of NOR-flash.
 * @lock: lock to manage flash read, write and erase operations
 * @mtd: MTD info for each NOR-flash.
 * @num_parts: Total number of partition in each bank of NOR-flash.
 * @parts: Partition info for each bank of NOR-flash.
 * @page_size: Page size of NOR-flash.
 * @base_addr: Base address of NOR-flash.
 * @erase_cmd: erase command may vary on different flash types
 * @fast_mode: flash supports read in fast mode
 */
struct spear_snor_flash {};

static inline struct spear_snor_flash *get_flash_data(struct mtd_info *mtd)
{}

/**
 * spear_smi_read_sr - Read status register of flash through SMI
 * @dev: structure of SMI information.
 * @bank: bank to which flash is connected
 *
 * This routine will return the status register of the flash chip present at the
 * given bank.
 */
static int spear_smi_read_sr(struct spear_smi *dev, u32 bank)
{}

/**
 * spear_smi_wait_till_ready - wait till flash is ready
 * @dev: structure of SMI information.
 * @bank: flash corresponding to this bank
 * @timeout: timeout for busy wait condition
 *
 * This routine checks for WIP (write in progress) bit in Status register
 * If successful the routine returns 0 else -EBUSY
 */
static int spear_smi_wait_till_ready(struct spear_smi *dev, u32 bank,
		unsigned long timeout)
{}

/**
 * spear_smi_int_handler - SMI Interrupt Handler.
 * @irq: irq number
 * @dev_id: structure of SMI device, embedded in dev_id.
 *
 * The handler clears all interrupt conditions and records the status in
 * dev->status which is used by the driver later.
 */
static irqreturn_t spear_smi_int_handler(int irq, void *dev_id)
{}

/**
 * spear_smi_hw_init - initializes the smi controller.
 * @dev: structure of smi device
 *
 * this routine initializes the smi controller wit the default values
 */
static void spear_smi_hw_init(struct spear_smi *dev)
{}

/**
 * get_flash_index - match chip id from a flash list.
 * @flash_id: a valid nor flash chip id obtained from board.
 *
 * try to validate the chip id by matching from a list, if not found then simply
 * returns negative. In case of success returns index in to the flash devices
 * array.
 */
static int get_flash_index(u32 flash_id)
{}

/**
 * spear_smi_write_enable - Enable the flash to do write operation
 * @dev: structure of SMI device
 * @bank: enable write for flash connected to this bank
 *
 * Set write enable latch with Write Enable command.
 * Returns 0 on success.
 */
static int spear_smi_write_enable(struct spear_smi *dev, u32 bank)
{}

static inline u32
get_sector_erase_cmd(struct spear_snor_flash *flash, u32 offset)
{}

/**
 * spear_smi_erase_sector - erase one sector of flash
 * @dev: structure of SMI information
 * @command: erase command to be send
 * @bank: bank to which this command needs to be send
 * @bytes: size of command
 *
 * Erase one sector of flash memory at offset ``offset'' which is any
 * address within the sector which should be erased.
 * Returns 0 if successful, non-zero otherwise.
 */
static int spear_smi_erase_sector(struct spear_smi *dev,
		u32 bank, u32 command, u32 bytes)
{}

/**
 * spear_mtd_erase - perform flash erase operation as requested by user
 * @mtd: Provides the memory characteristics
 * @e_info: Provides the erase information
 *
 * Erase an address range on the flash chip. The address range may extend
 * one or more erase sectors. Return an error is there is a problem erasing.
 */
static int spear_mtd_erase(struct mtd_info *mtd, struct erase_info *e_info)
{}

/**
 * spear_mtd_read - performs flash read operation as requested by the user
 * @mtd: MTD information of the memory bank
 * @from: Address from which to start read
 * @len: Number of bytes to be read
 * @retlen: Fills the Number of bytes actually read
 * @buf: Fills this after reading
 *
 * Read an address range from the flash chip. The address range
 * may be any size provided it is within the physical boundaries.
 * Returns 0 on success, non zero otherwise
 */
static int spear_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
		size_t *retlen, u8 *buf)
{}

/*
 * The purpose of this function is to ensure a memcpy_toio() with byte writes
 * only. Its structure is inspired from the ARM implementation of _memcpy_toio()
 * which also does single byte writes but cannot be used here as this is just an
 * implementation detail and not part of the API. Not mentioning the comment
 * stating that _memcpy_toio() should be optimized.
 */
static void spear_smi_memcpy_toio_b(volatile void __iomem *dest,
				    const void *src, size_t len)
{}

static inline int spear_smi_cpy_toio(struct spear_smi *dev, u32 bank,
		void __iomem *dest, const void *src, size_t len)
{}

/**
 * spear_mtd_write - performs write operation as requested by the user.
 * @mtd: MTD information of the memory bank.
 * @to:	Address to write.
 * @len: Number of bytes to be written.
 * @retlen: Number of bytes actually wrote.
 * @buf: Buffer from which the data to be taken.
 *
 * Write an address range to the flash chip. Data must be written in
 * flash_page_size chunks. The address range may be any size provided
 * it is within the physical boundaries.
 * Returns 0 on success, non zero otherwise
 */
static int spear_mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
		size_t *retlen, const u8 *buf)
{}

/**
 * spear_smi_probe_flash - Detects the NOR Flash chip.
 * @dev: structure of SMI information.
 * @bank: bank on which flash must be probed
 *
 * This routine will check whether there exists a flash chip on a given memory
 * bank ID.
 * Return index of the probed flash in flash devices structure
 */
static int spear_smi_probe_flash(struct spear_smi *dev, u32 bank)
{}


#ifdef CONFIG_OF
static int spear_smi_probe_config_dt(struct platform_device *pdev,
				     struct device_node *np)
{}
#else
static int spear_smi_probe_config_dt(struct platform_device *pdev,
				     struct device_node *np)
{
	return -ENOSYS;
}
#endif

static int spear_smi_setup_banks(struct platform_device *pdev,
				 u32 bank, struct device_node *np)
{}

/**
 * spear_smi_probe - Entry routine
 * @pdev: platform device structure
 *
 * This is the first routine which gets invoked during booting and does all
 * initialization/allocation work. The routine looks for available memory banks,
 * and do proper init for any found one.
 * Returns 0 on success, non zero otherwise
 */
static int spear_smi_probe(struct platform_device *pdev)
{}

/**
 * spear_smi_remove - Exit routine
 * @pdev: platform device structure
 *
 * free all allocations and delete the partitions.
 */
static void spear_smi_remove(struct platform_device *pdev)
{}

#ifdef CONFIG_PM_SLEEP
static int spear_smi_suspend(struct device *dev)
{}

static int spear_smi_resume(struct device *dev)
{}
#endif

static SIMPLE_DEV_PM_OPS(spear_smi_pm_ops, spear_smi_suspend, spear_smi_resume);

#ifdef CONFIG_OF
static const struct of_device_id spear_smi_id_table[] =;
MODULE_DEVICE_TABLE(of, spear_smi_id_table);
#endif

static struct platform_driver spear_smi_driver =;
module_platform_driver();

MODULE_LICENSE();
MODULE_AUTHOR();
MODULE_DESCRIPTION();