Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c2da04dc authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branches 'spi/topic/bcm53xx', 'spi/topic/bcm63xx',...

Merge remote-tracking branches 'spi/topic/bcm53xx', 'spi/topic/bcm63xx', 'spi/topic/bfin-sport', 'spi/topic/bfin5xx' and 'spi/topic/bitbang' into spi-next
Loading
Loading
Loading
Loading
+2 −40
Original line number Diff line number Diff line
@@ -18,29 +18,6 @@
#include <bcm63xx_dev_spi.h>
#include <bcm63xx_regs.h>

/*
 * register offsets
 */
static const unsigned long bcm6348_regs_spi[] = {
	__GEN_SPI_REGS_TABLE(6348)
};

static const unsigned long bcm6358_regs_spi[] = {
	__GEN_SPI_REGS_TABLE(6358)
};

const unsigned long *bcm63xx_regs_spi;
EXPORT_SYMBOL(bcm63xx_regs_spi);

static __init void bcm63xx_spi_regs_init(void)
{
	if (BCMCPU_IS_6338() || BCMCPU_IS_6348())
		bcm63xx_regs_spi = bcm6348_regs_spi;
	if (BCMCPU_IS_3368() || BCMCPU_IS_6358() ||
		BCMCPU_IS_6362() || BCMCPU_IS_6368())
		bcm63xx_regs_spi = bcm6358_regs_spi;
}

static struct resource spi_resources[] = {
	{
		.start		= -1, /* filled at runtime */
@@ -53,19 +30,10 @@ static struct resource spi_resources[] = {
	},
};

static struct bcm63xx_spi_pdata spi_pdata = {
	.bus_num		= 0,
	.num_chipselect		= 8,
};

static struct platform_device bcm63xx_spi_device = {
	.name		= "bcm63xx-spi",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(spi_resources),
	.resource	= spi_resources,
	.dev		= {
		.platform_data = &spi_pdata,
	},
};

int __init bcm63xx_spi_register(void)
@@ -78,21 +46,15 @@ int __init bcm63xx_spi_register(void)
	spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI);

	if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
		bcm63xx_spi_device.name = "bcm6348-spi",
		spi_resources[0].end += BCM_6348_RSET_SPI_SIZE - 1;
		spi_pdata.fifo_size = SPI_6348_MSG_DATA_SIZE;
		spi_pdata.msg_type_shift = SPI_6348_MSG_TYPE_SHIFT;
		spi_pdata.msg_ctl_width = SPI_6348_MSG_CTL_WIDTH;
	}

	if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6362() ||
		BCMCPU_IS_6368()) {
		bcm63xx_spi_device.name = "bcm6358-spi",
		spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1;
		spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE;
		spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT;
		spi_pdata.msg_ctl_width = SPI_6358_MSG_CTL_WIDTH;
	}

	bcm63xx_spi_regs_init();

	return platform_device_register(&bcm63xx_spi_device);
}
+0 −44
Original line number Diff line number Diff line
@@ -7,48 +7,4 @@

int __init bcm63xx_spi_register(void);

struct bcm63xx_spi_pdata {
	unsigned int	fifo_size;
	unsigned int	msg_type_shift;
	unsigned int	msg_ctl_width;
	int		bus_num;
	int		num_chipselect;
};

enum bcm63xx_regs_spi {
	SPI_CMD,
	SPI_INT_STATUS,
	SPI_INT_MASK_ST,
	SPI_INT_MASK,
	SPI_ST,
	SPI_CLK_CFG,
	SPI_FILL_BYTE,
	SPI_MSG_TAIL,
	SPI_RX_TAIL,
	SPI_MSG_CTL,
	SPI_MSG_DATA,
	SPI_RX_DATA,
};

#define __GEN_SPI_REGS_TABLE(__cpu)					\
	[SPI_CMD]		= SPI_## __cpu ##_CMD,			\
	[SPI_INT_STATUS]	= SPI_## __cpu ##_INT_STATUS,		\
	[SPI_INT_MASK_ST]	= SPI_## __cpu ##_INT_MASK_ST,		\
	[SPI_INT_MASK]		= SPI_## __cpu ##_INT_MASK,		\
	[SPI_ST]		= SPI_## __cpu ##_ST,			\
	[SPI_CLK_CFG]		= SPI_## __cpu ##_CLK_CFG,		\
	[SPI_FILL_BYTE]		= SPI_## __cpu ##_FILL_BYTE,		\
	[SPI_MSG_TAIL]		= SPI_## __cpu ##_MSG_TAIL,		\
	[SPI_RX_TAIL]		= SPI_## __cpu ##_RX_TAIL,		\
	[SPI_MSG_CTL]		= SPI_## __cpu ##_MSG_CTL,		\
	[SPI_MSG_DATA]		= SPI_## __cpu ##_MSG_DATA,		\
	[SPI_RX_DATA]		= SPI_## __cpu ##_RX_DATA,

static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg)
{
	extern const unsigned long *bcm63xx_regs_spi;

	return bcm63xx_regs_spi[reg];
}

#endif /* BCM63XX_DEV_SPI_H */
+1 −1
Original line number Diff line number Diff line
@@ -136,7 +136,7 @@ config SPI_BCM53XX

config SPI_BCM63XX
	tristate "Broadcom BCM63xx SPI controller"
	depends on BCM63XX
	depends on BCM63XX || COMPILE_TEST
	help
          Enable support for the SPI controller on the Broadcom BCM63xx SoCs.

+2 −11
Original line number Diff line number Diff line
@@ -247,28 +247,19 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core)
	if (err) {
		spi_master_put(master);
		bcma_set_drvdata(core, NULL);
		goto out;
		return err;
	}

	/* Broadcom SoCs (at least with the CC rev 42) use SPI for flash only */
	spi_new_device(master, &bcm53xx_info);

out:
	return err;
}

static void bcm53xxspi_bcma_remove(struct bcma_device *core)
{
	struct bcm53xxspi *b53spi = bcma_get_drvdata(core);

	spi_unregister_master(b53spi->master);
	return 0;
}

static struct bcma_driver bcm53xxspi_bcma_driver = {
	.name		= KBUILD_MODNAME,
	.id_table	= bcm53xxspi_bcma_tbl,
	.probe		= bcm53xxspi_bcma_probe,
	.remove		= bcm53xxspi_bcma_remove,
};

/**************************************************
+185 −25
Original line number Diff line number Diff line
@@ -27,10 +27,117 @@
#include <linux/err.h>
#include <linux/pm_runtime.h>

#include <bcm63xx_dev_spi.h>
/* BCM 6338/6348 SPI core */
#define SPI_6348_RSET_SIZE		64
#define SPI_6348_CMD			0x00	/* 16-bits register */
#define SPI_6348_INT_STATUS		0x02
#define SPI_6348_INT_MASK_ST		0x03
#define SPI_6348_INT_MASK		0x04
#define SPI_6348_ST			0x05
#define SPI_6348_CLK_CFG		0x06
#define SPI_6348_FILL_BYTE		0x07
#define SPI_6348_MSG_TAIL		0x09
#define SPI_6348_RX_TAIL		0x0b
#define SPI_6348_MSG_CTL		0x40	/* 8-bits register */
#define SPI_6348_MSG_CTL_WIDTH		8
#define SPI_6348_MSG_DATA		0x41
#define SPI_6348_MSG_DATA_SIZE		0x3f
#define SPI_6348_RX_DATA		0x80
#define SPI_6348_RX_DATA_SIZE		0x3f

/* BCM 3368/6358/6262/6368 SPI core */
#define SPI_6358_RSET_SIZE		1804
#define SPI_6358_MSG_CTL		0x00	/* 16-bits register */
#define SPI_6358_MSG_CTL_WIDTH		16
#define SPI_6358_MSG_DATA		0x02
#define SPI_6358_MSG_DATA_SIZE		0x21e
#define SPI_6358_RX_DATA		0x400
#define SPI_6358_RX_DATA_SIZE		0x220
#define SPI_6358_CMD			0x700	/* 16-bits register */
#define SPI_6358_INT_STATUS		0x702
#define SPI_6358_INT_MASK_ST		0x703
#define SPI_6358_INT_MASK		0x704
#define SPI_6358_ST			0x705
#define SPI_6358_CLK_CFG		0x706
#define SPI_6358_FILL_BYTE		0x707
#define SPI_6358_MSG_TAIL		0x709
#define SPI_6358_RX_TAIL		0x70B

/* Shared SPI definitions */

/* Message configuration */
#define SPI_FD_RW			0x00
#define SPI_HD_W			0x01
#define SPI_HD_R			0x02
#define SPI_BYTE_CNT_SHIFT		0
#define SPI_6348_MSG_TYPE_SHIFT		6
#define SPI_6358_MSG_TYPE_SHIFT		14

/* Command */
#define SPI_CMD_NOOP			0x00
#define SPI_CMD_SOFT_RESET		0x01
#define SPI_CMD_HARD_RESET		0x02
#define SPI_CMD_START_IMMEDIATE		0x03
#define SPI_CMD_COMMAND_SHIFT		0
#define SPI_CMD_COMMAND_MASK		0x000f
#define SPI_CMD_DEVICE_ID_SHIFT		4
#define SPI_CMD_PREPEND_BYTE_CNT_SHIFT	8
#define SPI_CMD_ONE_BYTE_SHIFT		11
#define SPI_CMD_ONE_WIRE_SHIFT		12
#define SPI_DEV_ID_0			0
#define SPI_DEV_ID_1			1
#define SPI_DEV_ID_2			2
#define SPI_DEV_ID_3			3

/* Interrupt mask */
#define SPI_INTR_CMD_DONE		0x01
#define SPI_INTR_RX_OVERFLOW		0x02
#define SPI_INTR_TX_UNDERFLOW		0x04
#define SPI_INTR_TX_OVERFLOW		0x08
#define SPI_INTR_RX_UNDERFLOW		0x10
#define SPI_INTR_CLEAR_ALL		0x1f

/* Status */
#define SPI_RX_EMPTY			0x02
#define SPI_CMD_BUSY			0x04
#define SPI_SERIAL_BUSY			0x08

/* Clock configuration */
#define SPI_CLK_20MHZ			0x00
#define SPI_CLK_0_391MHZ		0x01
#define SPI_CLK_0_781MHZ		0x02	/* default */
#define SPI_CLK_1_563MHZ		0x03
#define SPI_CLK_3_125MHZ		0x04
#define SPI_CLK_6_250MHZ		0x05
#define SPI_CLK_12_50MHZ		0x06
#define SPI_CLK_MASK			0x07
#define SPI_SSOFFTIME_MASK		0x38
#define SPI_SSOFFTIME_SHIFT		3
#define SPI_BYTE_SWAP			0x80

enum bcm63xx_regs_spi {
	SPI_CMD,
	SPI_INT_STATUS,
	SPI_INT_MASK_ST,
	SPI_INT_MASK,
	SPI_ST,
	SPI_CLK_CFG,
	SPI_FILL_BYTE,
	SPI_MSG_TAIL,
	SPI_RX_TAIL,
	SPI_MSG_CTL,
	SPI_MSG_DATA,
	SPI_RX_DATA,
	SPI_MSG_TYPE_SHIFT,
	SPI_MSG_CTL_WIDTH,
	SPI_MSG_DATA_SIZE,
};

#define BCM63XX_SPI_MAX_PREPEND		15

#define BCM63XX_SPI_MAX_CS		8
#define BCM63XX_SPI_BUS_NUM		0

struct bcm63xx_spi {
	struct completion	done;

@@ -38,6 +145,7 @@ struct bcm63xx_spi {
	int			irq;

	/* Platform data */
	const unsigned long	*reg_offsets;
	unsigned		fifo_size;
	unsigned int		msg_type_shift;
	unsigned int		msg_ctl_width;
@@ -53,25 +161,33 @@ struct bcm63xx_spi {
static inline u8 bcm_spi_readb(struct bcm63xx_spi *bs,
			       unsigned int offset)
{
	return bcm_readb(bs->regs + bcm63xx_spireg(offset));
	return readb(bs->regs + bs->reg_offsets[offset]);
}

static inline u16 bcm_spi_readw(struct bcm63xx_spi *bs,
				unsigned int offset)
{
	return bcm_readw(bs->regs + bcm63xx_spireg(offset));
#ifdef CONFIG_CPU_BIG_ENDIAN
	return ioread16be(bs->regs + bs->reg_offsets[offset]);
#else
	return readw(bs->regs + bs->reg_offsets[offset]);
#endif
}

static inline void bcm_spi_writeb(struct bcm63xx_spi *bs,
				  u8 value, unsigned int offset)
{
	bcm_writeb(value, bs->regs + bcm63xx_spireg(offset));
	writeb(value, bs->regs + bs->reg_offsets[offset]);
}

static inline void bcm_spi_writew(struct bcm63xx_spi *bs,
				  u16 value, unsigned int offset)
{
	bcm_writew(value, bs->regs + bcm63xx_spireg(offset));
#ifdef CONFIG_CPU_BIG_ENDIAN
	iowrite16be(value, bs->regs + bs->reg_offsets[offset]);
#else
	writew(value, bs->regs + bs->reg_offsets[offset]);
#endif
}

static const unsigned bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = {
@@ -122,7 +238,6 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
	struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
	u16 msg_ctl;
	u16 cmd;
	u8 rx_tail;
	unsigned int i, timeout = 0, prepend_len = 0, len = 0;
	struct spi_transfer *t = first;
	bool do_rx = false;
@@ -314,18 +429,71 @@ static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
	return IRQ_HANDLED;
}

static const unsigned long bcm6348_spi_reg_offsets[] = {
	[SPI_CMD]		= SPI_6348_CMD,
	[SPI_INT_STATUS]	= SPI_6348_INT_STATUS,
	[SPI_INT_MASK_ST]	= SPI_6348_INT_MASK_ST,
	[SPI_INT_MASK]		= SPI_6348_INT_MASK,
	[SPI_ST]		= SPI_6348_ST,
	[SPI_CLK_CFG]		= SPI_6348_CLK_CFG,
	[SPI_FILL_BYTE]		= SPI_6348_FILL_BYTE,
	[SPI_MSG_TAIL]		= SPI_6348_MSG_TAIL,
	[SPI_RX_TAIL]		= SPI_6348_RX_TAIL,
	[SPI_MSG_CTL]		= SPI_6348_MSG_CTL,
	[SPI_MSG_DATA]		= SPI_6348_MSG_DATA,
	[SPI_RX_DATA]		= SPI_6348_RX_DATA,
	[SPI_MSG_TYPE_SHIFT]	= SPI_6348_MSG_TYPE_SHIFT,
	[SPI_MSG_CTL_WIDTH]	= SPI_6348_MSG_CTL_WIDTH,
	[SPI_MSG_DATA_SIZE]	= SPI_6348_MSG_DATA_SIZE,
};

static const unsigned long bcm6358_spi_reg_offsets[] = {
	[SPI_CMD]		= SPI_6358_CMD,
	[SPI_INT_STATUS]	= SPI_6358_INT_STATUS,
	[SPI_INT_MASK_ST]	= SPI_6358_INT_MASK_ST,
	[SPI_INT_MASK]		= SPI_6358_INT_MASK,
	[SPI_ST]		= SPI_6358_ST,
	[SPI_CLK_CFG]		= SPI_6358_CLK_CFG,
	[SPI_FILL_BYTE]		= SPI_6358_FILL_BYTE,
	[SPI_MSG_TAIL]		= SPI_6358_MSG_TAIL,
	[SPI_RX_TAIL]		= SPI_6358_RX_TAIL,
	[SPI_MSG_CTL]		= SPI_6358_MSG_CTL,
	[SPI_MSG_DATA]		= SPI_6358_MSG_DATA,
	[SPI_RX_DATA]		= SPI_6358_RX_DATA,
	[SPI_MSG_TYPE_SHIFT]	= SPI_6358_MSG_TYPE_SHIFT,
	[SPI_MSG_CTL_WIDTH]	= SPI_6358_MSG_CTL_WIDTH,
	[SPI_MSG_DATA_SIZE]	= SPI_6358_MSG_DATA_SIZE,
};

static const struct platform_device_id bcm63xx_spi_dev_match[] = {
	{
		.name = "bcm6348-spi",
		.driver_data = (unsigned long)bcm6348_spi_reg_offsets,
	},
	{
		.name = "bcm6358-spi",
		.driver_data = (unsigned long)bcm6358_spi_reg_offsets,
	},
	{
	},
};

static int bcm63xx_spi_probe(struct platform_device *pdev)
{
	struct resource *r;
	const unsigned long *bcm63xx_spireg;
	struct device *dev = &pdev->dev;
	struct bcm63xx_spi_pdata *pdata = dev_get_platdata(&pdev->dev);
	int irq;
	struct spi_master *master;
	struct clk *clk;
	struct bcm63xx_spi *bs;
	int ret;

	if (!pdev->id_entry->driver_data)
		return -EINVAL;

	bcm63xx_spireg = (const unsigned long *)pdev->id_entry->driver_data;

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(dev, "no irq\n");
@@ -359,7 +527,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)

	bs->irq = irq;
	bs->clk = clk;
	bs->fifo_size = pdata->fifo_size;
	bs->reg_offsets = bcm63xx_spireg;
	bs->fifo_size = bs->reg_offsets[SPI_MSG_DATA_SIZE];

	ret = devm_request_irq(&pdev->dev, irq, bcm63xx_spi_interrupt, 0,
							pdev->name, master);
@@ -368,26 +537,16 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
		goto out_err;
	}

	master->bus_num = pdata->bus_num;
	master->num_chipselect = pdata->num_chipselect;
	master->bus_num = BCM63XX_SPI_BUS_NUM;
	master->num_chipselect = BCM63XX_SPI_MAX_CS;
	master->transfer_one_message = bcm63xx_spi_transfer_one;
	master->mode_bits = MODEBITS;
	master->bits_per_word_mask = SPI_BPW_MASK(8);
	master->auto_runtime_pm = true;
	bs->msg_type_shift = pdata->msg_type_shift;
	bs->msg_ctl_width = pdata->msg_ctl_width;
	bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
	bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));

	switch (bs->msg_ctl_width) {
	case 8:
	case 16:
		break;
	default:
		dev_err(dev, "unsupported MSG_CTL width: %d\n",
			 bs->msg_ctl_width);
		goto out_err;
	}
	bs->msg_type_shift = bs->reg_offsets[SPI_MSG_TYPE_SHIFT];
	bs->msg_ctl_width = bs->reg_offsets[SPI_MSG_CTL_WIDTH];
	bs->tx_io = (u8 *)(bs->regs + bs->reg_offsets[SPI_MSG_DATA]);
	bs->rx_io = (const u8 *)(bs->regs + bs->reg_offsets[SPI_RX_DATA]);

	/* Initialize hardware */
	ret = clk_prepare_enable(bs->clk);
@@ -467,6 +626,7 @@ static struct platform_driver bcm63xx_spi_driver = {
		.name	= "bcm63xx-spi",
		.pm	= &bcm63xx_spi_pm_ops,
	},
	.id_table	= bcm63xx_spi_dev_match,
	.probe		= bcm63xx_spi_probe,
	.remove		= bcm63xx_spi_remove,
};
Loading