aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/spi/spi-omap2-mcspi.c43
1 files changed, 36 insertions, 7 deletions
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 965539b0dbfb..8f0afdb067b8 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -45,6 +45,7 @@
45#include <linux/platform_data/spi-omap2-mcspi.h> 45#include <linux/platform_data/spi-omap2-mcspi.h>
46 46
47#define OMAP2_MCSPI_MAX_FREQ 48000000 47#define OMAP2_MCSPI_MAX_FREQ 48000000
48#define OMAP2_MCSPI_MAX_DIVIDER 4096
48#define OMAP2_MCSPI_MAX_FIFODEPTH 64 49#define OMAP2_MCSPI_MAX_FIFODEPTH 64
49#define OMAP2_MCSPI_MAX_FIFOWCNT 0xFFFF 50#define OMAP2_MCSPI_MAX_FIFOWCNT 0xFFFF
50#define SPI_AUTOSUSPEND_TIMEOUT 2000 51#define SPI_AUTOSUSPEND_TIMEOUT 2000
@@ -89,6 +90,7 @@
89#define OMAP2_MCSPI_CHCONF_FORCE BIT(20) 90#define OMAP2_MCSPI_CHCONF_FORCE BIT(20)
90#define OMAP2_MCSPI_CHCONF_FFET BIT(27) 91#define OMAP2_MCSPI_CHCONF_FFET BIT(27)
91#define OMAP2_MCSPI_CHCONF_FFER BIT(28) 92#define OMAP2_MCSPI_CHCONF_FFER BIT(28)
93#define OMAP2_MCSPI_CHCONF_CLKG BIT(29)
92 94
93#define OMAP2_MCSPI_CHSTAT_RXS BIT(0) 95#define OMAP2_MCSPI_CHSTAT_RXS BIT(0)
94#define OMAP2_MCSPI_CHSTAT_TXS BIT(1) 96#define OMAP2_MCSPI_CHSTAT_TXS BIT(1)
@@ -96,6 +98,7 @@
96#define OMAP2_MCSPI_CHSTAT_TXFFE BIT(3) 98#define OMAP2_MCSPI_CHSTAT_TXFFE BIT(3)
97 99
98#define OMAP2_MCSPI_CHCTRL_EN BIT(0) 100#define OMAP2_MCSPI_CHCTRL_EN BIT(0)
101#define OMAP2_MCSPI_CHCTRL_EXTCLK_MASK (0xff << 8)
99 102
100#define OMAP2_MCSPI_WAKEUPENABLE_WKEN BIT(0) 103#define OMAP2_MCSPI_WAKEUPENABLE_WKEN BIT(0)
101 104
@@ -149,7 +152,7 @@ struct omap2_mcspi_cs {
149 int word_len; 152 int word_len;
150 struct list_head node; 153 struct list_head node;
151 /* Context save and restore shadow register */ 154 /* Context save and restore shadow register */
152 u32 chconf0; 155 u32 chconf0, chctrl0;
153}; 156};
154 157
155static inline void mcspi_write_reg(struct spi_master *master, 158static inline void mcspi_write_reg(struct spi_master *master,
@@ -230,10 +233,16 @@ static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
230 233
231static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable) 234static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
232{ 235{
236 struct omap2_mcspi_cs *cs = spi->controller_state;
233 u32 l; 237 u32 l;
234 238
235 l = enable ? OMAP2_MCSPI_CHCTRL_EN : 0; 239 l = cs->chctrl0;
236 mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, l); 240 if (enable)
241 l |= OMAP2_MCSPI_CHCTRL_EN;
242 else
243 l &= ~OMAP2_MCSPI_CHCTRL_EN;
244 cs->chctrl0 = l;
245 mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, cs->chctrl0);
237 /* Flash post-writes */ 246 /* Flash post-writes */
238 mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0); 247 mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0);
239} 248}
@@ -840,7 +849,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
840 struct omap2_mcspi_cs *cs = spi->controller_state; 849 struct omap2_mcspi_cs *cs = spi->controller_state;
841 struct omap2_mcspi *mcspi; 850 struct omap2_mcspi *mcspi;
842 struct spi_master *spi_cntrl; 851 struct spi_master *spi_cntrl;
843 u32 l = 0, div = 0; 852 u32 l = 0, clkd = 0, div, extclk = 0, clkg = 0;
844 u8 word_len = spi->bits_per_word; 853 u8 word_len = spi->bits_per_word;
845 u32 speed_hz = spi->max_speed_hz; 854 u32 speed_hz = spi->max_speed_hz;
846 855
@@ -856,7 +865,17 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
856 speed_hz = t->speed_hz; 865 speed_hz = t->speed_hz;
857 866
858 speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ); 867 speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
859 div = omap2_mcspi_calc_divisor(speed_hz); 868 if (speed_hz < (OMAP2_MCSPI_MAX_FREQ / OMAP2_MCSPI_MAX_DIVIDER)) {
869 clkd = omap2_mcspi_calc_divisor(speed_hz);
870 speed_hz = OMAP2_MCSPI_MAX_FREQ >> clkd;
871 clkg = 0;
872 } else {
873 div = (OMAP2_MCSPI_MAX_FREQ + speed_hz - 1) / speed_hz;
874 speed_hz = OMAP2_MCSPI_MAX_FREQ / div;
875 clkd = (div - 1) & 0xf;
876 extclk = (div - 1) >> 4;
877 clkg = OMAP2_MCSPI_CHCONF_CLKG;
878 }
860 879
861 l = mcspi_cached_chconf0(spi); 880 l = mcspi_cached_chconf0(spi);
862 881
@@ -885,7 +904,16 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
885 904
886 /* set clock divisor */ 905 /* set clock divisor */
887 l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK; 906 l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
888 l |= div << 2; 907 l |= clkd << 2;
908
909 /* set clock granularity */
910 l &= ~OMAP2_MCSPI_CHCONF_CLKG;
911 l |= clkg;
912 if (clkg) {
913 cs->chctrl0 &= ~OMAP2_MCSPI_CHCTRL_EXTCLK_MASK;
914 cs->chctrl0 |= extclk << 8;
915 mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, cs->chctrl0);
916 }
889 917
890 /* set SPI mode 0..3 */ 918 /* set SPI mode 0..3 */
891 if (spi->mode & SPI_CPOL) 919 if (spi->mode & SPI_CPOL)
@@ -900,7 +928,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
900 mcspi_write_chconf0(spi, l); 928 mcspi_write_chconf0(spi, l);
901 929
902 dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", 930 dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
903 OMAP2_MCSPI_MAX_FREQ >> div, 931 speed_hz,
904 (spi->mode & SPI_CPHA) ? "trailing" : "leading", 932 (spi->mode & SPI_CPHA) ? "trailing" : "leading",
905 (spi->mode & SPI_CPOL) ? "inverted" : "normal"); 933 (spi->mode & SPI_CPOL) ? "inverted" : "normal");
906 934
@@ -972,6 +1000,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
972 cs->base = mcspi->base + spi->chip_select * 0x14; 1000 cs->base = mcspi->base + spi->chip_select * 0x14;
973 cs->phys = mcspi->phys + spi->chip_select * 0x14; 1001 cs->phys = mcspi->phys + spi->chip_select * 0x14;
974 cs->chconf0 = 0; 1002 cs->chconf0 = 0;
1003 cs->chctrl0 = 0;
975 spi->controller_state = cs; 1004 spi->controller_state = cs;
976 /* Link this to context save list */ 1005 /* Link this to context save list */
977 list_add_tail(&cs->node, &ctx->cs); 1006 list_add_tail(&cs->node, &ctx->cs);