ramips: move rt2880 spi clock and reset init code to spi_prepare_message
before spi transfer. use spi_prepare_message to setup spi hardware. it will setup MSB, spi mode and speed remove sys_freq member and speed check code Signed-off-by: Michael Lee <igvtee@gmail.com> SVN-Revision: 47578
This commit is contained in:
		@@ -41,7 +41,7 @@ Acked-by: John Crispin <blogic@openwrt.org>
 | 
				
			|||||||
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
 | 
					 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
 | 
				
			||||||
--- /dev/null
 | 
					--- /dev/null
 | 
				
			||||||
+++ b/drivers/spi/spi-rt2880.c
 | 
					+++ b/drivers/spi/spi-rt2880.c
 | 
				
			||||||
@@ -0,0 +1,539 @@
 | 
					@@ -0,0 +1,533 @@
 | 
				
			||||||
+/*
 | 
					+/*
 | 
				
			||||||
+ * spi-rt2880.c -- Ralink RT288x/RT305x SPI controller driver
 | 
					+ * spi-rt2880.c -- Ralink RT288x/RT305x SPI controller driver
 | 
				
			||||||
+ *
 | 
					+ *
 | 
				
			||||||
@@ -172,8 +172,7 @@ Acked-by: John Crispin <blogic@openwrt.org>
 | 
				
			|||||||
+struct rt2880_spi {
 | 
					+struct rt2880_spi {
 | 
				
			||||||
+	struct spi_master	*master;
 | 
					+	struct spi_master	*master;
 | 
				
			||||||
+	void __iomem		*base;
 | 
					+	void __iomem		*base;
 | 
				
			||||||
+	unsigned int		sys_freq;
 | 
					+	u32			speed;
 | 
				
			||||||
+	unsigned int		speed;
 | 
					 | 
				
			||||||
+	u16			wait_loops;
 | 
					+	u16			wait_loops;
 | 
				
			||||||
+	u16			mode;
 | 
					+	u16			mode;
 | 
				
			||||||
+	struct clk		*clk;
 | 
					+	struct clk		*clk;
 | 
				
			||||||
@@ -209,61 +208,33 @@ Acked-by: John Crispin <blogic@openwrt.org>
 | 
				
			|||||||
+	iowrite32((ioread32(addr) & ~mask), addr);
 | 
					+	iowrite32((ioread32(addr) & ~mask), addr);
 | 
				
			||||||
+}
 | 
					+}
 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+static int rt2880_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
 | 
					+static u32 rt2880_spi_baudrate_get(struct spi_device *spi, unsigned int speed)
 | 
				
			||||||
+{
 | 
					+{
 | 
				
			||||||
+	struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
 | 
					+	struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
 | 
				
			||||||
+	u32 rate;
 | 
					+	u32 rate;
 | 
				
			||||||
+	u32 prescale;
 | 
					+	u32 prescale;
 | 
				
			||||||
+	u32 reg;
 | 
					 | 
				
			||||||
+
 | 
					 | 
				
			||||||
+	dev_dbg(&spi->dev, "speed:%u\n", speed);
 | 
					 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+	/*
 | 
					+	/*
 | 
				
			||||||
+	 * the supported rates are: 2, 4, 8, ... 128
 | 
					+	 * the supported rates are: 2, 4, 8, ... 128
 | 
				
			||||||
+	 * round up as we look for equal or less speed
 | 
					+	 * round up as we look for equal or less speed
 | 
				
			||||||
+	 */
 | 
					+	 */
 | 
				
			||||||
+	rate = DIV_ROUND_UP(rs->sys_freq, speed);
 | 
					+	rate = DIV_ROUND_UP(clk_get_rate(rs->clk), speed);
 | 
				
			||||||
+	dev_dbg(&spi->dev, "rate-1:%u\n", rate);
 | 
					 | 
				
			||||||
+	rate = roundup_pow_of_two(rate);
 | 
					+	rate = roundup_pow_of_two(rate);
 | 
				
			||||||
+	dev_dbg(&spi->dev, "rate-2:%u\n", rate);
 | 
					 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+	/* Convert the rate to SPI clock divisor value.	*/
 | 
					+	/* Convert the rate to SPI clock divisor value.	*/
 | 
				
			||||||
+	prescale = ilog2(rate / 2);
 | 
					+	prescale = ilog2(rate / 2);
 | 
				
			||||||
+	dev_dbg(&spi->dev, "prescale:%u\n", prescale);
 | 
					 | 
				
			||||||
+
 | 
					 | 
				
			||||||
+	reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG);
 | 
					 | 
				
			||||||
+	reg = ((reg & ~SPICFG_SPICLK_PRESCALE_MASK) | prescale);
 | 
					 | 
				
			||||||
+	rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg);
 | 
					 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+	/* some tolerance. double and add 100 */
 | 
					+	/* some tolerance. double and add 100 */
 | 
				
			||||||
+	rs->wait_loops = (8 * HZ * loops_per_jiffy) /
 | 
					+	rs->wait_loops = (8 * HZ * loops_per_jiffy) /
 | 
				
			||||||
+		(clk_get_rate(rs->clk) / rate);
 | 
					+		(clk_get_rate(rs->clk) / rate);
 | 
				
			||||||
+	rs->wait_loops = (rs->wait_loops << 1) + 100;
 | 
					+	rs->wait_loops = (rs->wait_loops << 1) + 100;
 | 
				
			||||||
+	rs->speed = speed;
 | 
					+	rs->speed = speed;
 | 
				
			||||||
+	return 0;
 | 
					 | 
				
			||||||
+}
 | 
					 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+/*
 | 
					+	dev_dbg(&spi->dev, "speed: %lu/%u, rate: %u, prescal: %u, loops: %hu\n",
 | 
				
			||||||
+ * called only when no transfer is active on the bus
 | 
					+			clk_get_rate(rs->clk) / rate, speed, rate, prescale,
 | 
				
			||||||
+ */
 | 
					+			rs->wait_loops);
 | 
				
			||||||
+static int
 | 
					 | 
				
			||||||
+rt2880_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 | 
					 | 
				
			||||||
+{
 | 
					 | 
				
			||||||
+	struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
 | 
					 | 
				
			||||||
+	unsigned int speed = spi->max_speed_hz;
 | 
					 | 
				
			||||||
+	int rc;
 | 
					 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+	if ((t != NULL) && t->speed_hz)
 | 
					+	return prescale;
 | 
				
			||||||
+		speed = t->speed_hz;
 | 
					 | 
				
			||||||
+
 | 
					 | 
				
			||||||
+	if (rs->speed != speed) {
 | 
					 | 
				
			||||||
+		dev_dbg(&spi->dev, "speed_hz:%u\n", speed);
 | 
					 | 
				
			||||||
+		rc = rt2880_spi_baudrate_set(spi, speed);
 | 
					 | 
				
			||||||
+		if (rc)
 | 
					 | 
				
			||||||
+			return rc;
 | 
					 | 
				
			||||||
+	}
 | 
					 | 
				
			||||||
+
 | 
					 | 
				
			||||||
+	return 0;
 | 
					 | 
				
			||||||
+}
 | 
					+}
 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+static u32 get_arbiter_offset(struct spi_master *master)
 | 
					+static u32 get_arbiter_offset(struct spi_master *master)
 | 
				
			||||||
@@ -345,15 +316,9 @@ Acked-by: John Crispin <blogic@openwrt.org>
 | 
				
			|||||||
+	struct rt2880_spi *rs = spi_master_get_devdata(master);
 | 
					+	struct rt2880_spi *rs = spi_master_get_devdata(master);
 | 
				
			||||||
+	struct spi_device *spi = m->spi;
 | 
					+	struct spi_device *spi = m->spi;
 | 
				
			||||||
+	struct spi_transfer *t = NULL;
 | 
					+	struct spi_transfer *t = NULL;
 | 
				
			||||||
+	int par_override = 0;
 | 
					 | 
				
			||||||
+	int status = 0;
 | 
					+	int status = 0;
 | 
				
			||||||
+	int cs_active = 0;
 | 
					+	int cs_active = 0;
 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+	/* Load defaults */
 | 
					 | 
				
			||||||
+	status = rt2880_spi_setup_transfer(spi, NULL);
 | 
					 | 
				
			||||||
+	if (status < 0)
 | 
					 | 
				
			||||||
+		goto msg_done;
 | 
					 | 
				
			||||||
+
 | 
					 | 
				
			||||||
+	list_for_each_entry(t, &m->transfers, transfer_list) {
 | 
					+	list_for_each_entry(t, &m->transfers, transfer_list) {
 | 
				
			||||||
+		if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
 | 
					+		if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
 | 
				
			||||||
+			dev_err(&spi->dev,
 | 
					+			dev_err(&spi->dev,
 | 
				
			||||||
@@ -362,23 +327,6 @@ Acked-by: John Crispin <blogic@openwrt.org>
 | 
				
			|||||||
+			goto msg_done;
 | 
					+			goto msg_done;
 | 
				
			||||||
+		}
 | 
					+		}
 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+		if (t->speed_hz && t->speed_hz < (rs->sys_freq / 128)) {
 | 
					 | 
				
			||||||
+			dev_err(&spi->dev,
 | 
					 | 
				
			||||||
+				"message rejected: device min speed (%d Hz) exceeds required transfer speed (%d Hz)\n",
 | 
					 | 
				
			||||||
+				(rs->sys_freq / 128), t->speed_hz);
 | 
					 | 
				
			||||||
+			status = -EIO;
 | 
					 | 
				
			||||||
+			goto msg_done;
 | 
					 | 
				
			||||||
+		}
 | 
					 | 
				
			||||||
+
 | 
					 | 
				
			||||||
+		if (par_override || t->speed_hz || t->bits_per_word) {
 | 
					 | 
				
			||||||
+			par_override = 1;
 | 
					 | 
				
			||||||
+			status = rt2880_spi_setup_transfer(spi, t);
 | 
					 | 
				
			||||||
+			if (status < 0)
 | 
					 | 
				
			||||||
+				goto msg_done;
 | 
					 | 
				
			||||||
+			if (!t->speed_hz && !t->bits_per_word)
 | 
					 | 
				
			||||||
+				par_override = 0;
 | 
					 | 
				
			||||||
+		}
 | 
					 | 
				
			||||||
+
 | 
					 | 
				
			||||||
+		if (!cs_active) {
 | 
					+		if (!cs_active) {
 | 
				
			||||||
+			rt2880_spi_set_cs(rs, 1);
 | 
					+			rt2880_spi_set_cs(rs, 1);
 | 
				
			||||||
+			cs_active = 1;
 | 
					+			cs_active = 1;
 | 
				
			||||||
@@ -465,12 +413,60 @@ Acked-by: John Crispin <blogic@openwrt.org>
 | 
				
			|||||||
+	return 0;
 | 
					+	return 0;
 | 
				
			||||||
+}
 | 
					+}
 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+static void rt2880_spi_reset(struct rt2880_spi *rs)
 | 
					+static int rt2880_spi_prepare_message(struct spi_master *master,
 | 
				
			||||||
 | 
					+		struct spi_message *msg)
 | 
				
			||||||
+{
 | 
					+{
 | 
				
			||||||
+	rt2880_spi_write(rs, RAMIPS_SPI_CFG,
 | 
					+	struct rt2880_spi *rs = spi_master_get_devdata(master);
 | 
				
			||||||
+			 SPICFG_MSBFIRST | SPICFG_TXCLKEDGE_FALLING |
 | 
					+	struct spi_device *spi = msg->spi;
 | 
				
			||||||
+			 SPICFG_SPICLK_DIV16 | SPICFG_SPICLKPOL);
 | 
					+	u32 reg;
 | 
				
			||||||
+	rt2880_spi_write(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO | SPICTL_SPIENA);
 | 
					+
 | 
				
			||||||
 | 
					+	if ((rs->mode == spi->mode) && (rs->speed == spi->max_speed_hz))
 | 
				
			||||||
 | 
					+		return 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#if 0
 | 
				
			||||||
 | 
					+	/* set spido to tri-state */
 | 
				
			||||||
 | 
					+	rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO);
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	reg &= ~(SPICFG_MSBFIRST | SPICFG_SPICLKPOL |
 | 
				
			||||||
 | 
					+			SPICFG_RXCLKEDGE_FALLING |
 | 
				
			||||||
 | 
					+			SPICFG_TXCLKEDGE_FALLING |
 | 
				
			||||||
 | 
					+			SPICFG_SPICLK_PRESCALE_MASK);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* MSB */
 | 
				
			||||||
 | 
					+	if (!(spi->mode & SPI_LSB_FIRST))
 | 
				
			||||||
 | 
					+		reg |= SPICFG_MSBFIRST;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* spi mode */
 | 
				
			||||||
 | 
					+	switch (spi->mode & (SPI_CPOL | SPI_CPHA)) {
 | 
				
			||||||
 | 
					+	case SPI_MODE_0:
 | 
				
			||||||
 | 
					+		reg |= SPICFG_TXCLKEDGE_FALLING;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	case SPI_MODE_1:
 | 
				
			||||||
 | 
					+		reg |= SPICFG_RXCLKEDGE_FALLING;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	case SPI_MODE_2:
 | 
				
			||||||
 | 
					+		reg |= SPICFG_SPICLKPOL | SPICFG_RXCLKEDGE_FALLING;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	case SPI_MODE_3:
 | 
				
			||||||
 | 
					+		reg |= SPICFG_SPICLKPOL | SPICFG_TXCLKEDGE_FALLING;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	rs->mode = spi->mode;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#if 0
 | 
				
			||||||
 | 
					+	/* set spiclk and spiena to tri-state */
 | 
				
			||||||
 | 
					+	reg |= SPICFG_HIZSPI;
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* clock divide */
 | 
				
			||||||
 | 
					+	reg |= rt2880_spi_baudrate_get(spi, spi->max_speed_hz);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
+}
 | 
					+}
 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+static int rt2880_spi_probe(struct platform_device *pdev)
 | 
					+static int rt2880_spi_probe(struct platform_device *pdev)
 | 
				
			||||||
@@ -511,6 +507,7 @@ Acked-by: John Crispin <blogic@openwrt.org>
 | 
				
			|||||||
+	master->max_speed_hz = clk_get_rate(clk) / 2;
 | 
					+	master->max_speed_hz = clk_get_rate(clk) / 2;
 | 
				
			||||||
+	master->flags = SPI_MASTER_HALF_DUPLEX;
 | 
					+	master->flags = SPI_MASTER_HALF_DUPLEX;
 | 
				
			||||||
+	master->setup = rt2880_spi_setup;
 | 
					+	master->setup = rt2880_spi_setup;
 | 
				
			||||||
 | 
					+	master->prepare_message = rt2880_spi_prepare_message;
 | 
				
			||||||
+	master->transfer_one_message = rt2880_spi_transfer_one_message;
 | 
					+	master->transfer_one_message = rt2880_spi_transfer_one_message;
 | 
				
			||||||
+	master->num_chipselect = RALINK_NUM_CHIPSELECTS;
 | 
					+	master->num_chipselect = RALINK_NUM_CHIPSELECTS;
 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
@@ -520,12 +517,9 @@ Acked-by: John Crispin <blogic@openwrt.org>
 | 
				
			|||||||
+	rs->master = master;
 | 
					+	rs->master = master;
 | 
				
			||||||
+	rs->base = base;
 | 
					+	rs->base = base;
 | 
				
			||||||
+	rs->clk = clk;
 | 
					+	rs->clk = clk;
 | 
				
			||||||
+	rs->sys_freq = clk_get_rate(rs->clk);
 | 
					 | 
				
			||||||
+	dev_dbg(&pdev->dev, "sys_freq: %u\n", rs->sys_freq);
 | 
					 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+	device_reset(&pdev->dev);
 | 
					+	device_reset(&pdev->dev);
 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+	rt2880_spi_reset(rs);
 | 
					 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
+	ret = devm_spi_register_master(&pdev->dev, master);
 | 
					+	ret = devm_spi_register_master(&pdev->dev, master);
 | 
				
			||||||
+	if (ret < 0) {
 | 
					+	if (ret < 0) {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user