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

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

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

Merge remote-tracking branches 'spi/topic/atmel', 'spi/topic/bcm63xx', 'spi/topic/cadence' and 'spi/topic/davinci' into spi-next
Loading
Loading
Loading
Loading
+33 −0
Original line number Original line Diff line number Diff line
Binding for Broadcom BCM6328 High Speed SPI controller

Required properties:
- compatible: must contain of "brcm,bcm6328-hsspi".
- reg: Base address and size of the controllers memory area.
- interrupts: Interrupt for the SPI block.
- clocks: phandles of the SPI clock and the PLL clock.
- clock-names: must be "hsspi", "pll".
- #address-cells: <1>, as required by generic SPI binding.
- #size-cells: <0>, also as required by generic SPI binding.

Optional properties:
- num-cs: some controllers have less than 8 cs signals. Defaults to 8
  if absent.

Child nodes as per the generic SPI binding.

Example:

	spi@10001000 {
		compatible = "brcm,bcm6328-hsspi";
		reg = <0x10001000 0x600>;

		interrupts = <29>;

		clocks = <&clkctl 9>, <&hsspi_pll>;
		clock-names = "hsspi", "pll";

		num-cs = <2>;

		#address-cells = <1>;
		#size-cells = <0>;
	};
+33 −0
Original line number Original line Diff line number Diff line
Binding for Broadcom BCM6348/BCM6358 SPI controller

Required properties:
- compatible: must contain one of "brcm,bcm6348-spi", "brcm,bcm6358-spi".
- reg: Base address and size of the controllers memory area.
- interrupts: Interrupt for the SPI block.
- clocks: phandle of the SPI clock.
- clock-names: has to be "spi".
- #address-cells: <1>, as required by generic SPI binding.
- #size-cells: <0>, also as required by generic SPI binding.

Optional properties:
- num-cs: some controllers have less than 8 cs signals. Defaults to 8
  if absent.

Child nodes as per the generic SPI binding.

Example:

	spi@10000800 {
		compatible = "brcm,bcm6368-spi", "brcm,bcm6358-spi";
		reg = <0x10000800 0x70c>;

		interrupts = <1>;

		clocks = <&clkctl 9>;
		clock-names = "spi";

		num-cs = <5>;

		#address-cells = <1>;
		#size-cells = <0>;
	};
+30 −14
Original line number Original line Diff line number Diff line
@@ -1464,6 +1464,25 @@ static int atmel_spi_gpio_cs(struct platform_device *pdev)
	return 0;
	return 0;
}
}


static void atmel_spi_init(struct atmel_spi *as)
{
	spi_writel(as, CR, SPI_BIT(SWRST));
	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
	if (as->caps.has_wdrbt) {
		spi_writel(as, MR, SPI_BIT(WDRBT) | SPI_BIT(MODFDIS)
				| SPI_BIT(MSTR));
	} else {
		spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS));
	}

	if (as->use_pdc)
		spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
	spi_writel(as, CR, SPI_BIT(SPIEN));

	if (as->fifo_size)
		spi_writel(as, CR, SPI_BIT(FIFOEN));
}

static int atmel_spi_probe(struct platform_device *pdev)
static int atmel_spi_probe(struct platform_device *pdev)
{
{
	struct resource		*regs;
	struct resource		*regs;
@@ -1572,26 +1591,14 @@ static int atmel_spi_probe(struct platform_device *pdev)


	as->spi_clk = clk_get_rate(clk);
	as->spi_clk = clk_get_rate(clk);


	spi_writel(as, CR, SPI_BIT(SWRST));
	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
	if (as->caps.has_wdrbt) {
		spi_writel(as, MR, SPI_BIT(WDRBT) | SPI_BIT(MODFDIS)
				| SPI_BIT(MSTR));
	} else {
		spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS));
	}

	if (as->use_pdc)
		spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
	spi_writel(as, CR, SPI_BIT(SPIEN));

	as->fifo_size = 0;
	as->fifo_size = 0;
	if (!of_property_read_u32(pdev->dev.of_node, "atmel,fifo-size",
	if (!of_property_read_u32(pdev->dev.of_node, "atmel,fifo-size",
				  &as->fifo_size)) {
				  &as->fifo_size)) {
		dev_info(&pdev->dev, "Using FIFO (%u data)\n", as->fifo_size);
		dev_info(&pdev->dev, "Using FIFO (%u data)\n", as->fifo_size);
		spi_writel(as, CR, SPI_BIT(FIFOEN));
	}
	}


	atmel_spi_init(as);

	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT);
	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT);
	pm_runtime_use_autosuspend(&pdev->dev);
	pm_runtime_use_autosuspend(&pdev->dev);
	pm_runtime_set_active(&pdev->dev);
	pm_runtime_set_active(&pdev->dev);
@@ -1695,8 +1702,17 @@ static int atmel_spi_suspend(struct device *dev)
static int atmel_spi_resume(struct device *dev)
static int atmel_spi_resume(struct device *dev)
{
{
	struct spi_master *master = dev_get_drvdata(dev);
	struct spi_master *master = dev_get_drvdata(dev);
	struct atmel_spi *as = spi_master_get_devdata(master);
	int ret;
	int ret;


	ret = clk_prepare_enable(as->clk);
	if (ret)
		return ret;

	atmel_spi_init(as);

	clk_disable_unprepare(as->clk);

	if (!pm_runtime_suspended(dev)) {
	if (!pm_runtime_suspended(dev)) {
		ret = atmel_spi_runtime_resume(dev);
		ret = atmel_spi_runtime_resume(dev);
		if (ret)
		if (ret)
+30 −5
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi.h>
#include <linux/mutex.h>
#include <linux/mutex.h>
#include <linux/of.h>


#define HSSPI_GLOBAL_CTRL_REG			0x0
#define HSSPI_GLOBAL_CTRL_REG			0x0
#define GLOBAL_CTRL_CS_POLARITY_SHIFT		0
#define GLOBAL_CTRL_CS_POLARITY_SHIFT		0
@@ -91,6 +92,7 @@


#define HSSPI_MAX_SYNC_CLOCK			30000000
#define HSSPI_MAX_SYNC_CLOCK			30000000


#define HSSPI_SPI_MAX_CS			8
#define HSSPI_BUS_NUM				1 /* 0 is legacy SPI */
#define HSSPI_BUS_NUM				1 /* 0 is legacy SPI */


struct bcm63xx_hsspi {
struct bcm63xx_hsspi {
@@ -332,7 +334,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
	struct device *dev = &pdev->dev;
	struct device *dev = &pdev->dev;
	struct clk *clk;
	struct clk *clk;
	int irq, ret;
	int irq, ret;
	u32 reg, rate;
	u32 reg, rate, num_cs = HSSPI_SPI_MAX_CS;


	irq = platform_get_irq(pdev, 0);
	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
	if (irq < 0) {
@@ -351,8 +353,16 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
		return PTR_ERR(clk);
		return PTR_ERR(clk);


	rate = clk_get_rate(clk);
	rate = clk_get_rate(clk);
	if (!rate) {
		struct clk *pll_clk = devm_clk_get(dev, "pll");

		if (IS_ERR(pll_clk))
			return PTR_ERR(pll_clk);

		rate = clk_get_rate(pll_clk);
		if (!rate)
		if (!rate)
			return -EINVAL;
			return -EINVAL;
	}


	ret = clk_prepare_enable(clk);
	ret = clk_prepare_enable(clk);
	if (ret)
	if (ret)
@@ -374,8 +384,17 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
	mutex_init(&bs->bus_mutex);
	mutex_init(&bs->bus_mutex);
	init_completion(&bs->done);
	init_completion(&bs->done);


	master->dev.of_node = dev->of_node;
	if (!dev->of_node)
		master->bus_num = HSSPI_BUS_NUM;
		master->bus_num = HSSPI_BUS_NUM;
	master->num_chipselect = 8;

	of_property_read_u32(dev->of_node, "num-cs", &num_cs);
	if (num_cs > 8) {
		dev_warn(dev, "unsupported number of cs (%i), reducing to 8\n",
			 num_cs);
		num_cs = HSSPI_SPI_MAX_CS;
	}
	master->num_chipselect = num_cs;
	master->setup = bcm63xx_hsspi_setup;
	master->setup = bcm63xx_hsspi_setup;
	master->transfer_one_message = bcm63xx_hsspi_transfer_one;
	master->transfer_one_message = bcm63xx_hsspi_transfer_one;
	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
@@ -461,10 +480,16 @@ static int bcm63xx_hsspi_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(bcm63xx_hsspi_pm_ops, bcm63xx_hsspi_suspend,
static SIMPLE_DEV_PM_OPS(bcm63xx_hsspi_pm_ops, bcm63xx_hsspi_suspend,
			 bcm63xx_hsspi_resume);
			 bcm63xx_hsspi_resume);


static const struct of_device_id bcm63xx_hsspi_of_match[] = {
	{ .compatible = "brcm,bcm6328-hsspi", },
	{ },
};

static struct platform_driver bcm63xx_hsspi_driver = {
static struct platform_driver bcm63xx_hsspi_driver = {
	.driver = {
	.driver = {
		.name	= "bcm63xx-hsspi",
		.name	= "bcm63xx-hsspi",
		.pm	= &bcm63xx_hsspi_pm_ops,
		.pm	= &bcm63xx_hsspi_pm_ops,
		.of_match_table = bcm63xx_hsspi_of_match,
	},
	},
	.probe		= bcm63xx_hsspi_probe,
	.probe		= bcm63xx_hsspi_probe,
	.remove		= bcm63xx_hsspi_remove,
	.remove		= bcm63xx_hsspi_remove,
+45 −6
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@
#include <linux/completion.h>
#include <linux/completion.h>
#include <linux/err.h>
#include <linux/err.h>
#include <linux/pm_runtime.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>


/* BCM 6338/6348 SPI core */
/* BCM 6338/6348 SPI core */
#define SPI_6348_RSET_SIZE		64
#define SPI_6348_RSET_SIZE		64
@@ -428,6 +429,13 @@ static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
	return IRQ_HANDLED;
	return IRQ_HANDLED;
}
}


static size_t bcm63xx_spi_max_length(struct spi_device *spi)
{
	struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);

	return bs->fifo_size;
}

static const unsigned long bcm6348_spi_reg_offsets[] = {
static const unsigned long bcm6348_spi_reg_offsets[] = {
	[SPI_CMD]		= SPI_6348_CMD,
	[SPI_CMD]		= SPI_6348_CMD,
	[SPI_INT_STATUS]	= SPI_6348_INT_STATUS,
	[SPI_INT_STATUS]	= SPI_6348_INT_STATUS,
@@ -477,21 +485,48 @@ static const struct platform_device_id bcm63xx_spi_dev_match[] = {
	},
	},
};
};


static const struct of_device_id bcm63xx_spi_of_match[] = {
	{ .compatible = "brcm,bcm6348-spi", .data = &bcm6348_spi_reg_offsets },
	{ .compatible = "brcm,bcm6358-spi", .data = &bcm6358_spi_reg_offsets },
	{ },
};

static int bcm63xx_spi_probe(struct platform_device *pdev)
static int bcm63xx_spi_probe(struct platform_device *pdev)
{
{
	struct resource *r;
	struct resource *r;
	const unsigned long *bcm63xx_spireg;
	const unsigned long *bcm63xx_spireg;
	struct device *dev = &pdev->dev;
	struct device *dev = &pdev->dev;
	int irq;
	int irq, bus_num;
	struct spi_master *master;
	struct spi_master *master;
	struct clk *clk;
	struct clk *clk;
	struct bcm63xx_spi *bs;
	struct bcm63xx_spi *bs;
	int ret;
	int ret;
	u32 num_cs = BCM63XX_SPI_MAX_CS;

	if (dev->of_node) {
		const struct of_device_id *match;


	if (!pdev->id_entry->driver_data)
		match = of_match_node(bcm63xx_spi_of_match, dev->of_node);
		if (!match)
			return -EINVAL;
			return -EINVAL;
		bcm63xx_spireg = match->data;

		of_property_read_u32(dev->of_node, "num-cs", &num_cs);
		if (num_cs > BCM63XX_SPI_MAX_CS) {
			dev_warn(dev, "unsupported number of cs (%i), reducing to 8\n",
				 num_cs);
			num_cs = BCM63XX_SPI_MAX_CS;
		}


	bcm63xx_spireg = (const unsigned long *)pdev->id_entry->driver_data;
		bus_num = -1;
	} else if (pdev->id_entry->driver_data) {
		const struct platform_device_id *match = pdev->id_entry;

		bcm63xx_spireg = (const unsigned long *)match->driver_data;
		bus_num = BCM63XX_SPI_BUS_NUM;
	} else {
		return -EINVAL;
	}


	irq = platform_get_irq(pdev, 0);
	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
	if (irq < 0) {
@@ -536,11 +571,14 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
		goto out_err;
		goto out_err;
	}
	}


	master->bus_num = BCM63XX_SPI_BUS_NUM;
	master->dev.of_node = dev->of_node;
	master->num_chipselect = BCM63XX_SPI_MAX_CS;
	master->bus_num = bus_num;
	master->num_chipselect = num_cs;
	master->transfer_one_message = bcm63xx_spi_transfer_one;
	master->transfer_one_message = bcm63xx_spi_transfer_one;
	master->mode_bits = MODEBITS;
	master->mode_bits = MODEBITS;
	master->bits_per_word_mask = SPI_BPW_MASK(8);
	master->bits_per_word_mask = SPI_BPW_MASK(8);
	master->max_transfer_size = bcm63xx_spi_max_length;
	master->max_message_size = bcm63xx_spi_max_length;
	master->auto_runtime_pm = true;
	master->auto_runtime_pm = true;
	bs->msg_type_shift = bs->reg_offsets[SPI_MSG_TYPE_SHIFT];
	bs->msg_type_shift = bs->reg_offsets[SPI_MSG_TYPE_SHIFT];
	bs->msg_ctl_width = bs->reg_offsets[SPI_MSG_CTL_WIDTH];
	bs->msg_ctl_width = bs->reg_offsets[SPI_MSG_CTL_WIDTH];
@@ -624,6 +662,7 @@ static struct platform_driver bcm63xx_spi_driver = {
	.driver = {
	.driver = {
		.name	= "bcm63xx-spi",
		.name	= "bcm63xx-spi",
		.pm	= &bcm63xx_spi_pm_ops,
		.pm	= &bcm63xx_spi_pm_ops,
		.of_match_table = bcm63xx_spi_of_match,
	},
	},
	.id_table	= bcm63xx_spi_dev_match,
	.id_table	= bcm63xx_spi_dev_match,
	.probe		= bcm63xx_spi_probe,
	.probe		= bcm63xx_spi_probe,
Loading