2010-10-12 18:18:31 +08:00
|
|
|
/*
|
|
|
|
* Freescale SPI/eSPI controller driver library.
|
|
|
|
*
|
|
|
|
* Maintainer: Kumar Gala
|
|
|
|
*
|
|
|
|
* Copyright 2010 Freescale Semiconductor, Inc.
|
|
|
|
* Copyright (C) 2006 Polycom, Inc.
|
|
|
|
*
|
|
|
|
* CPM SPI and QE buffer descriptors mode support:
|
|
|
|
* Copyright (c) 2009 MontaVista Software, Inc.
|
|
|
|
* Author: Anton Vorontsov <avorontsov@ru.mvista.com>
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
#ifndef __SPI_FSL_LIB_H__
|
|
|
|
#define __SPI_FSL_LIB_H__
|
|
|
|
|
2010-10-14 21:55:47 +08:00
|
|
|
#include <asm/io.h>
|
|
|
|
|
2010-10-12 18:18:31 +08:00
|
|
|
/* SPI/eSPI Controller driver's private data. */
|
|
|
|
struct mpc8xxx_spi {
|
|
|
|
struct device *dev;
|
|
|
|
void *reg_base;
|
|
|
|
|
|
|
|
/* rx & tx bufs from the spi_transfer */
|
|
|
|
const void *tx;
|
|
|
|
void *rx;
|
spi/fsl_spi: add eSPI controller support
Add eSPI controller support based on the library code spi_fsl_lib.c.
The eSPI controller is newer controller 85xx/Pxxx devices supported.
There're some differences comparing to the SPI controller:
1. Has different register map and different bit definition
So leave the code operated the register to the driver code, not
the common code.
2. Support 4 dedicated chip selects
The software can't controll the chip selects directly, The SPCOM[CS]
field is used to select which chip selects is used, and the
SPCOM[TRANLEN] field is set to tell the controller how long the CS
signal need to be asserted. So the driver doesn't need the chipselect
related function when transfering data, just set corresponding register
fields to controll the chipseclect.
3. Different Transmit/Receive FIFO access register behavior
For SPI controller, the Tx/Rx FIFO access register can hold only
one character regardless of the character length, but for eSPI
controller, the register can hold 4 or 2 characters according to
the character lengths. Access the Tx/Rx FIFO access register of the
eSPI controller will shift out/in 4/2 characters one time. For SPI
subsystem, the command and data are put into different transfers, so
we need to combine all the transfers to one transfer in order to pass
the transfer to eSPI controller.
4. The max transaction length limitation
The max transaction length one time is limitted by the SPCOM[TRANSLEN]
field which is 0xFFFF. When used mkfs.ext2 command to create ext2
filesystem on the flash, the read length will exceed the max value of
the SPCOM[TRANSLEN] field.
Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
2010-10-12 18:18:32 +08:00
|
|
|
#ifdef CONFIG_SPI_FSL_ESPI
|
|
|
|
int len;
|
|
|
|
#endif
|
2010-10-12 18:18:31 +08:00
|
|
|
|
|
|
|
int subblock;
|
|
|
|
struct spi_pram __iomem *pram;
|
|
|
|
struct cpm_buf_desc __iomem *tx_bd;
|
|
|
|
struct cpm_buf_desc __iomem *rx_bd;
|
|
|
|
|
|
|
|
struct spi_transfer *xfer_in_progress;
|
|
|
|
|
|
|
|
/* dma addresses for CPM transfers */
|
|
|
|
dma_addr_t tx_dma;
|
|
|
|
dma_addr_t rx_dma;
|
|
|
|
bool map_tx_dma;
|
|
|
|
bool map_rx_dma;
|
|
|
|
|
|
|
|
dma_addr_t dma_dummy_tx;
|
|
|
|
dma_addr_t dma_dummy_rx;
|
|
|
|
|
|
|
|
/* functions to deal with different sized buffers */
|
|
|
|
void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
|
|
|
|
u32(*get_tx) (struct mpc8xxx_spi *);
|
|
|
|
|
|
|
|
/* hooks for different controller driver */
|
|
|
|
void (*spi_do_one_msg) (struct spi_message *m);
|
|
|
|
void (*spi_remove) (struct mpc8xxx_spi *mspi);
|
|
|
|
|
|
|
|
unsigned int count;
|
|
|
|
unsigned int irq;
|
|
|
|
|
|
|
|
unsigned nsecs; /* (clock cycle time)/2 */
|
|
|
|
|
|
|
|
u32 spibrg; /* SPIBRG input clock */
|
|
|
|
u32 rx_shift; /* RX data reg shift when in qe mode */
|
|
|
|
u32 tx_shift; /* TX data reg shift when in qe mode */
|
|
|
|
|
|
|
|
unsigned int flags;
|
|
|
|
|
|
|
|
struct workqueue_struct *workqueue;
|
|
|
|
struct work_struct work;
|
|
|
|
|
|
|
|
struct list_head queue;
|
|
|
|
spinlock_t lock;
|
|
|
|
|
|
|
|
struct completion done;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct spi_mpc8xxx_cs {
|
|
|
|
/* functions to deal with different sized buffers */
|
|
|
|
void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
|
|
|
|
u32 (*get_tx) (struct mpc8xxx_spi *);
|
|
|
|
u32 rx_shift; /* RX data reg shift when in qe mode */
|
|
|
|
u32 tx_shift; /* TX data reg shift when in qe mode */
|
|
|
|
u32 hw_mode; /* Holds HW mode register settings */
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
|
|
|
|
{
|
|
|
|
out_be32(reg, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
|
|
|
|
{
|
|
|
|
return in_be32(reg);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct mpc8xxx_spi_probe_info {
|
|
|
|
struct fsl_spi_platform_data pdata;
|
|
|
|
int *gpios;
|
|
|
|
bool *alow_flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern u32 mpc8xxx_spi_tx_buf_u8(struct mpc8xxx_spi *mpc8xxx_spi);
|
|
|
|
extern u32 mpc8xxx_spi_tx_buf_u16(struct mpc8xxx_spi *mpc8xxx_spi);
|
|
|
|
extern u32 mpc8xxx_spi_tx_buf_u32(struct mpc8xxx_spi *mpc8xxx_spi);
|
|
|
|
extern void mpc8xxx_spi_rx_buf_u8(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
|
|
|
|
extern void mpc8xxx_spi_rx_buf_u16(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
|
|
|
|
extern void mpc8xxx_spi_rx_buf_u32(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
|
|
|
|
|
|
|
|
extern struct mpc8xxx_spi_probe_info *to_of_pinfo(
|
|
|
|
struct fsl_spi_platform_data *pdata);
|
|
|
|
extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi,
|
|
|
|
struct spi_transfer *t, unsigned int len);
|
|
|
|
extern int mpc8xxx_spi_transfer(struct spi_device *spi, struct spi_message *m);
|
|
|
|
extern void mpc8xxx_spi_cleanup(struct spi_device *spi);
|
|
|
|
extern const char *mpc8xxx_spi_strmode(unsigned int flags);
|
|
|
|
extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
|
|
|
|
unsigned int irq);
|
|
|
|
extern int mpc8xxx_spi_remove(struct device *dev);
|
2011-02-23 12:02:43 +08:00
|
|
|
extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev);
|
2010-10-12 18:18:31 +08:00
|
|
|
|
|
|
|
#endif /* __SPI_FSL_LIB_H__ */
|