/*
 * Copyright (C) 2008 Texas Instruments, Inc <www.ti.com>
 *
 * Driver for SPI controller on DaVinci. Based on atmel_spi.c 
 * by Atmel Corporation
 * 
 * Copyright (C) 2007 Atmel Corporation
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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 "spi_flash_internal.h"
#include "hardware.h"

/* ------------------------------------------------------------------------ *
 *  SPI ROM Definitions                                                     *
 * ------------------------------------------------------------------------ */
#define spirom_SIZE               0x00200000
#define spirom_BASE               0x00000000
#define spirom_PAGESIZE           256
#define spirom_PAGEMASK           0xffffffc0

/* ------------------------------------------------------------------------ *
 *  SPI ROM Commands                                                        *
 * ------------------------------------------------------------------------ */
#define spirom_CMD_WREN           0x06
#define spirom_CMD_WRDI           0x04
#define spirom_CMD_RDSR           0x05
#define spirom_CMD_WRSR           0x01
#define spirom_CMD_READ           0x03
#define spirom_CMD_WRITE          0x02

/* SPI transfer flags */
#define SPI_XFER_BEGIN  0x01		/* Assert CS before transfer */
#define SPI_XFER_END    0x02        /* Deassert CS after transfer */

/*-----------------------------------------------------------------------
 * Representation of a SPI slave, i.e. what we're communicating with.
 *
 * Drivers are expected to extend this with controller-specific data.
 *
 *   bus:       ID of the bus that the slave is attached to.
 *   cs:        ID of the chip select connected to the slave.
 */
struct spi_slave {
        unsigned int    bus;
        unsigned int    cs;
};

struct spi_flash {
	struct spi_slave *spi;
	const char      *name;
	Uint32			size;
	int             (*read)(struct spi_flash *flash, Uint32 offset, Uint32 len, void *buf);
	int             (*write)(struct spi_flash *flash, Uint32 offset, Uint32 len, Uint8 *buf);
	int             (*erase)(struct spi_flash *flash, Uint32 offset, Uint32 len);
};

struct davinci_spi_slave {
	struct spi_slave slave;
	void		*regs;
	Uint32		mr;
	unsigned int freq;
};

struct winbond_spi_flash_params {
	unsigned short idcode;
	unsigned short page_size;
	unsigned short pages_per_sector;
	unsigned short nr_sectors;
	const char *name;
};
struct winbond_spi_flash {
	const struct winbond_spi_flash_params *params;
	struct spi_flash flash;
};

/* ------------------------------------------------------------------------ *
 *  Function Renaming                                                       *
 * ------------------------------------------------------------------------ */
#define _wait                   DAVINCIHD_wait
#define _waitusec               DAVINCIHD_waitusec
#define _waitmsec               DAVINCIHD_waitmsec


#define offsetof(TYPE, MEMBER) ((Uint32) &((TYPE *)0)->MEMBER)

/**
 * container_of - cast a member of a structure out to the containing structure
 * @ptr:        the pointer to the member.
 * @type:       the type of the container struct this is embedded in.
 * @member:     the name of the member within the struct.
 *
 */
#define container_of(ptr, type, member) \
		( (type *)( (char *)ptr - offsetof(type,member) ) )

#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

static inline struct winbond_spi_flash *to_winbond_spi_flash(struct spi_flash
							     *flash)
{
	return container_of(flash, struct winbond_spi_flash, flash);
}

static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave)
{
	return container_of(slave, struct davinci_spi_slave, slave);
}

/* Send a single-byte command to the device and read the response */
int spi_flash_cmd(struct spi_slave *spi, Uint8 cmd, void *response, Uint32 len);

/*
 * Send a multi-byte command to the device and read the response. Used
 * for flash array reads, etc.
 */
int spi_flash_cmd_read(struct spi_slave *spi, const Uint8 *cmd,
		Uint32 cmd_len, void *data, Uint32 data_len);

/*
 * Send a multi-byte command to the device followed by (optional)
 * data. Used for programming the flash array, etc.
 */
int spi_flash_cmd_write(struct spi_slave *spi, const Uint8 *cmd, Uint32 cmd_len,
		const void *data, Uint32 data_len);

/*
 * Same as spi_flash_cmd_read() except it also claims/releases the SPI
 * bus. Used as common part of the ->read() operation.
 */
int spi_flash_read_common(struct spi_flash *flash, const Uint8 *cmd,
		Uint32 cmd_len, void *data, Uint32 data_len);

/* Manufacturer-specific probe functions */
struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, Uint8 *idcode);
struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, Uint8 *idcode);
struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, Uint8 *idcode);
struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, Uint8 *idcode);
