diff options
-rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 43 |
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 | ||
155 | static inline void mcspi_write_reg(struct spi_master *master, | 158 | static 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 | ||
231 | static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable) | 234 | static 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); |