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

Commit 8afba181 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branches 'spi/topic/omap-100k', 'spi/topic/omap-uwire',...

Merge remote-tracking branches 'spi/topic/omap-100k', 'spi/topic/omap-uwire', 'spi/topic/pl022', 'spi/topic/pm' and 'spi/topic/pxa2xx' into spi-next
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -342,12 +342,11 @@ SPI protocol drivers somewhat resemble platform device drivers:
		.driver = {
			.name		= "CHIP",
			.owner		= THIS_MODULE,
			.pm		= &CHIP_pm_ops,
		},

		.probe		= CHIP_probe,
		.remove		= CHIP_remove,
		.suspend	= CHIP_suspend,
		.resume		= CHIP_resume,
	};

The driver core will automatically attempt to bind this driver to any SPI
+77 −24
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
@@ -294,16 +295,6 @@ static int omap1_spi100k_setup(struct spi_device *spi)
	return ret;
}

static int omap1_spi100k_prepare_hardware(struct spi_master *master)
{
	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);

	clk_prepare_enable(spi100k->ick);
	clk_prepare_enable(spi100k->fck);

	return 0;
}

static int omap1_spi100k_transfer_one_message(struct spi_master *master,
					      struct spi_message *m)
{
@@ -372,16 +363,6 @@ static int omap1_spi100k_transfer_one_message(struct spi_master *master,
	return status;
}

static int omap1_spi100k_unprepare_hardware(struct spi_master *master)
{
	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);

	clk_disable_unprepare(spi100k->ick);
	clk_disable_unprepare(spi100k->fck);

	return 0;
}

static int omap1_spi100k_probe(struct platform_device *pdev)
{
	struct spi_master       *master;
@@ -402,14 +383,12 @@ static int omap1_spi100k_probe(struct platform_device *pdev)

	master->setup = omap1_spi100k_setup;
	master->transfer_one_message = omap1_spi100k_transfer_one_message;
	master->prepare_transfer_hardware = omap1_spi100k_prepare_hardware;
	master->unprepare_transfer_hardware = omap1_spi100k_unprepare_hardware;
	master->cleanup = NULL;
	master->num_chipselect = 2;
	master->mode_bits = MODEBITS;
	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
	master->min_speed_hz = OMAP1_SPI100K_MAX_FREQ/(1<<16);
	master->max_speed_hz = OMAP1_SPI100K_MAX_FREQ;
	master->auto_runtime_pm = true;

	spi100k = spi_master_get_devdata(master);

@@ -434,22 +413,96 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
		goto err;
	}

	status = clk_prepare_enable(spi100k->ick);
	if (status != 0) {
		dev_err(&pdev->dev, "failed to enable ick: %d\n", status);
		goto err;
	}

	status = clk_prepare_enable(spi100k->fck);
	if (status != 0) {
		dev_err(&pdev->dev, "failed to enable fck: %d\n", status);
		goto err_ick;
	}

	pm_runtime_enable(&pdev->dev);
	pm_runtime_set_active(&pdev->dev);

	status = devm_spi_register_master(&pdev->dev, master);
	if (status < 0)
		goto err;
		goto err_fck;

	return status;

err_fck:
	clk_disable_unprepare(spi100k->fck);
err_ick:
	clk_disable_unprepare(spi100k->ick);
err:
	spi_master_put(master);
	return status;
}

static int omap1_spi100k_remove(struct platform_device *pdev)
{
	struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);

	pm_runtime_disable(&pdev->dev);

	clk_disable_unprepare(spi100k->fck);
	clk_disable_unprepare(spi100k->ick);

	return 0;
}

#ifdef CONFIG_PM
static int omap1_spi100k_runtime_suspend(struct device *dev)
{
	struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);

	clk_disable_unprepare(spi100k->ick);
	clk_disable_unprepare(spi100k->fck);

	return 0;
}

static int omap1_spi100k_runtime_resume(struct device *dev)
{
	struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
	int ret;

	ret = clk_prepare_enable(spi100k->ick);
	if (ret != 0) {
		dev_err(dev, "Failed to enable ick: %d\n", ret);
		return ret;
	}

	ret = clk_prepare_enable(spi100k->fck);
	if (ret != 0) {
		dev_err(dev, "Failed to enable fck: %d\n", ret);
		clk_disable_unprepare(spi100k->ick);
		return ret;
	}

	return 0;
}
#endif

static const struct dev_pm_ops omap1_spi100k_pm = {
	SET_RUNTIME_PM_OPS(omap1_spi100k_runtime_suspend,
			   omap1_spi100k_runtime_resume, NULL)
};

static struct platform_driver omap1_spi100k_driver = {
	.driver = {
		.name		= "omap1_spi100k",
		.pm		= &omap1_spi100k_pm,
	},
	.probe		= omap1_spi100k_probe,
	.remove		= omap1_spi100k_remove,
};

module_platform_driver(omap1_spi100k_driver);
+0 −1
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@
#include <linux/module.h>
#include <linux/io.h>

#include <asm/irq.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>

+7 −7
Original line number Diff line number Diff line
@@ -285,7 +285,12 @@
 */
#define DEFAULT_SSP_REG_IMSC  0x0UL
#define DISABLE_ALL_INTERRUPTS DEFAULT_SSP_REG_IMSC
#define ENABLE_ALL_INTERRUPTS (~DEFAULT_SSP_REG_IMSC)
#define ENABLE_ALL_INTERRUPTS ( \
	SSP_IMSC_MASK_RORIM | \
	SSP_IMSC_MASK_RTIM | \
	SSP_IMSC_MASK_RXIM | \
	SSP_IMSC_MASK_TXIM \
)

#define CLEAR_ALL_INTERRUPTS  0x3

@@ -1251,7 +1256,6 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
	struct pl022 *pl022 = dev_id;
	struct spi_message *msg = pl022->cur_msg;
	u16 irq_status = 0;
	u16 flag = 0;

	if (unlikely(!msg)) {
		dev_err(&pl022->adev->dev,
@@ -1280,9 +1284,6 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
		if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF)
			dev_err(&pl022->adev->dev,
				"RXFIFO is full\n");
		if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF)
			dev_err(&pl022->adev->dev,
				"TXFIFO is full\n");

		/*
		 * Disable and clear interrupts, disable SSP,
@@ -1303,8 +1304,7 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)

	readwriter(pl022);

	if ((pl022->tx == pl022->tx_end) && (flag == 0)) {
		flag = 1;
	if (pl022->tx == pl022->tx_end) {
		/* Disable Transmit interrupt, enable receive interrupt */
		writew((readw(SSP_IMSC(pl022->virtbase)) &
		       ~SSP_IMSC_MASK_TXIM) | SSP_IMSC_MASK_RXIM,
+121 −71
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/spi/pxa2xx_spi.h>
#include <linux/spi/spi.h>
@@ -30,10 +31,6 @@
#include <linux/pm_runtime.h>
#include <linux/acpi.h>

#include <asm/io.h>
#include <asm/irq.h>
#include <asm/delay.h>

#include "spi-pxa2xx.h"

MODULE_AUTHOR("Stephen Street");
@@ -67,54 +64,6 @@ MODULE_ALIAS("platform:pxa2xx-spi");
#define LPSS_TX_LOTHRESH_DFLT	160
#define LPSS_TX_HITHRESH_DFLT	224

struct quark_spi_rate {
	u32 bitrate;
	u32 dds_clk_rate;
	u32 clk_div;
};

/*
 * 'rate', 'dds', 'clk_div' lookup table, which is defined in
 * the Quark SPI datasheet.
 */
static const struct quark_spi_rate quark_spi_rate_table[] = {
/*	bitrate,	dds_clk_rate,	clk_div */
	{50000000,	0x800000,	0},
	{40000000,	0x666666,	0},
	{25000000,	0x400000,	0},
	{20000000,	0x666666,	1},
	{16667000,	0x800000,	2},
	{13333000,	0x666666,	2},
	{12500000,	0x200000,	0},
	{10000000,	0x800000,	4},
	{8000000,	0x666666,	4},
	{6250000,	0x400000,	3},
	{5000000,	0x400000,	4},
	{4000000,	0x666666,	9},
	{3125000,	0x80000,	0},
	{2500000,	0x400000,	9},
	{2000000,	0x666666,	19},
	{1563000,	0x40000,	0},
	{1250000,	0x200000,	9},
	{1000000,	0x400000,	24},
	{800000,	0x666666,	49},
	{781250,	0x20000,	0},
	{625000,	0x200000,	19},
	{500000,	0x400000,	49},
	{400000,	0x666666,	99},
	{390625,	0x10000,	0},
	{250000,	0x400000,	99},
	{200000,	0x666666,	199},
	{195313,	0x8000,		0},
	{125000,	0x100000,	49},
	{100000,	0x200000,	124},
	{50000,		0x100000,	124},
	{25000,		0x80000,	124},
	{10016,		0x20000,	77},
	{5040,		0x20000,	154},
	{1002,		0x8000,		194},
};

/* Offset from drv_data->lpss_base */
#define GENERAL_REG		0x08
#define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
@@ -701,25 +650,124 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
}

/*
 * The Quark SPI data sheet gives a table, and for the given 'rate',
 * the 'dds' and 'clk_div' can be found in the table.
 * The Quark SPI has an additional 24 bit register (DDS_CLK_RATE) to multiply
 * input frequency by fractions of 2^24. It also has a divider by 5.
 *
 * There are formulas to get baud rate value for given input frequency and
 * divider parameters, such as DDS_CLK_RATE and SCR:
 *
 * Fsys = 200MHz
 *
 * Fssp = Fsys * DDS_CLK_RATE / 2^24			(1)
 * Baud rate = Fsclk = Fssp / (2 * (SCR + 1))		(2)
 *
 * DDS_CLK_RATE either 2^n or 2^n / 5.
 * SCR is in range 0 .. 255
 *
 * Divisor = 5^i * 2^j * 2 * k
 *       i = [0, 1]      i = 1 iff j = 0 or j > 3
 *       j = [0, 23]     j = 0 iff i = 1
 *       k = [1, 256]
 * Special case: j = 0, i = 1: Divisor = 2 / 5
 *
 * Accordingly to the specification the recommended values for DDS_CLK_RATE
 * are:
 *	Case 1:		2^n, n = [0, 23]
 *	Case 2:		2^24 * 2 / 5 (0x666666)
 *	Case 3:		less than or equal to 2^24 / 5 / 16 (0x33333)
 *
 * In all cases the lowest possible value is better.
 *
 * The function calculates parameters for all cases and chooses the one closest
 * to the asked baud rate.
 */
static u32 quark_x1000_set_clk_regvals(u32 rate, u32 *dds, u32 *clk_div)
static unsigned int quark_x1000_get_clk_div(int rate, u32 *dds)
{
	unsigned int i;
	unsigned long xtal = 200000000;
	unsigned long fref = xtal / 2;		/* mandatory division by 2,
						   see (2) */
						/* case 3 */
	unsigned long fref1 = fref / 2;		/* case 1 */
	unsigned long fref2 = fref * 2 / 5;	/* case 2 */
	unsigned long scale;
	unsigned long q, q1, q2;
	long r, r1, r2;
	u32 mul;

	/* Case 1 */

	/* Set initial value for DDS_CLK_RATE */
	mul = (1 << 24) >> 1;

	/* Calculate initial quot */
	q1 = DIV_ROUND_CLOSEST(fref1, rate);

	/* Scale q1 if it's too big */
	if (q1 > 256) {
		/* Scale q1 to range [1, 512] */
		scale = fls_long(q1 - 1);
		if (scale > 9) {
			q1 >>= scale - 9;
			mul >>= scale - 9;
		}

	for (i = 0; i < ARRAY_SIZE(quark_spi_rate_table); i++) {
		if (rate >= quark_spi_rate_table[i].bitrate) {
			*dds = quark_spi_rate_table[i].dds_clk_rate;
			*clk_div = quark_spi_rate_table[i].clk_div;
			return quark_spi_rate_table[i].bitrate;
		/* Round the result if we have a remainder */
		q1 += q1 & 1;
	}

	/* Decrease DDS_CLK_RATE as much as we can without loss in precision */
	scale = __ffs(q1);
	q1 >>= scale;
	mul >>= scale;

	/* Get the remainder */
	r1 = abs(fref1 / (1 << (24 - fls_long(mul))) / q1 - rate);

	/* Case 2 */

	q2 = DIV_ROUND_CLOSEST(fref2, rate);
	r2 = abs(fref2 / q2 - rate);

	/*
	 * Choose the best between two: less remainder we have the better. We
	 * can't go case 2 if q2 is greater than 256 since SCR register can
	 * hold only values 0 .. 255.
	 */
	if (r2 >= r1 || q2 > 256) {
		/* case 1 is better */
		r = r1;
		q = q1;
	} else {
		/* case 2 is better */
		r = r2;
		q = q2;
		mul = (1 << 24) * 2 / 5;
	}

	*dds = quark_spi_rate_table[i-1].dds_clk_rate;
	*clk_div = quark_spi_rate_table[i-1].clk_div;
	/* Check case 3 only If the divisor is big enough */
	if (fref / rate >= 80) {
		u64 fssp;
		u32 m;

		/* Calculate initial quot */
		q1 = DIV_ROUND_CLOSEST(fref, rate);
		m = (1 << 24) / q1;

	return quark_spi_rate_table[i-1].bitrate;
		/* Get the remainder */
		fssp = (u64)fref * m;
		do_div(fssp, 1 << 24);
		r1 = abs(fssp - rate);

		/* Choose this one if it suits better */
		if (r1 < r) {
			/* case 3 is better */
			q = 1;
			mul = m;
		}
	}

	*dds = mul;
	return q - 1;
}

static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
@@ -730,23 +778,25 @@ static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
	rate = min_t(int, ssp_clk, rate);

	if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
		return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
		return (ssp_clk / (2 * rate) - 1) & 0xff;
	else
		return ((ssp_clk / rate - 1) & 0xfff) << 8;
		return (ssp_clk / rate - 1) & 0xfff;
}

static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data,
					   struct chip_data *chip, int rate)
{
	u32 clk_div;
	unsigned int clk_div;

	switch (drv_data->ssp_type) {
	case QUARK_X1000_SSP:
		quark_x1000_set_clk_regvals(rate, &chip->dds_rate, &clk_div);
		return clk_div << 8;
		clk_div = quark_x1000_get_clk_div(rate, &chip->dds_rate);
		break;
	default:
		return ssp_get_clk_div(drv_data, rate);
		clk_div = ssp_get_clk_div(drv_data, rate);
		break;
	}
	return clk_div << 8;
}

static void pump_transfers(unsigned long data)
Loading