diff options
Diffstat (limited to 'drivers/spi/spi-omap2-mcspi.c')
-rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 65 |
1 files changed, 44 insertions, 21 deletions
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index a72127f08e39..2941c5b96ebc 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c | |||
@@ -22,7 +22,6 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/init.h> | ||
26 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
27 | #include <linux/module.h> | 26 | #include <linux/module.h> |
28 | #include <linux/device.h> | 27 | #include <linux/device.h> |
@@ -45,6 +44,7 @@ | |||
45 | #include <linux/platform_data/spi-omap2-mcspi.h> | 44 | #include <linux/platform_data/spi-omap2-mcspi.h> |
46 | 45 | ||
47 | #define OMAP2_MCSPI_MAX_FREQ 48000000 | 46 | #define OMAP2_MCSPI_MAX_FREQ 48000000 |
47 | #define OMAP2_MCSPI_MAX_DIVIDER 4096 | ||
48 | #define OMAP2_MCSPI_MAX_FIFODEPTH 64 | 48 | #define OMAP2_MCSPI_MAX_FIFODEPTH 64 |
49 | #define OMAP2_MCSPI_MAX_FIFOWCNT 0xFFFF | 49 | #define OMAP2_MCSPI_MAX_FIFOWCNT 0xFFFF |
50 | #define SPI_AUTOSUSPEND_TIMEOUT 2000 | 50 | #define SPI_AUTOSUSPEND_TIMEOUT 2000 |
@@ -89,6 +89,7 @@ | |||
89 | #define OMAP2_MCSPI_CHCONF_FORCE BIT(20) | 89 | #define OMAP2_MCSPI_CHCONF_FORCE BIT(20) |
90 | #define OMAP2_MCSPI_CHCONF_FFET BIT(27) | 90 | #define OMAP2_MCSPI_CHCONF_FFET BIT(27) |
91 | #define OMAP2_MCSPI_CHCONF_FFER BIT(28) | 91 | #define OMAP2_MCSPI_CHCONF_FFER BIT(28) |
92 | #define OMAP2_MCSPI_CHCONF_CLKG BIT(29) | ||
92 | 93 | ||
93 | #define OMAP2_MCSPI_CHSTAT_RXS BIT(0) | 94 | #define OMAP2_MCSPI_CHSTAT_RXS BIT(0) |
94 | #define OMAP2_MCSPI_CHSTAT_TXS BIT(1) | 95 | #define OMAP2_MCSPI_CHSTAT_TXS BIT(1) |
@@ -96,6 +97,7 @@ | |||
96 | #define OMAP2_MCSPI_CHSTAT_TXFFE BIT(3) | 97 | #define OMAP2_MCSPI_CHSTAT_TXFFE BIT(3) |
97 | 98 | ||
98 | #define OMAP2_MCSPI_CHCTRL_EN BIT(0) | 99 | #define OMAP2_MCSPI_CHCTRL_EN BIT(0) |
100 | #define OMAP2_MCSPI_CHCTRL_EXTCLK_MASK (0xff << 8) | ||
99 | 101 | ||
100 | #define OMAP2_MCSPI_WAKEUPENABLE_WKEN BIT(0) | 102 | #define OMAP2_MCSPI_WAKEUPENABLE_WKEN BIT(0) |
101 | 103 | ||
@@ -149,7 +151,7 @@ struct omap2_mcspi_cs { | |||
149 | int word_len; | 151 | int word_len; |
150 | struct list_head node; | 152 | struct list_head node; |
151 | /* Context save and restore shadow register */ | 153 | /* Context save and restore shadow register */ |
152 | u32 chconf0; | 154 | u32 chconf0, chctrl0; |
153 | }; | 155 | }; |
154 | 156 | ||
155 | static inline void mcspi_write_reg(struct spi_master *master, | 157 | static inline void mcspi_write_reg(struct spi_master *master, |
@@ -230,10 +232,16 @@ static void omap2_mcspi_set_dma_req(const struct spi_device *spi, | |||
230 | 232 | ||
231 | static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable) | 233 | static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable) |
232 | { | 234 | { |
235 | struct omap2_mcspi_cs *cs = spi->controller_state; | ||
233 | u32 l; | 236 | u32 l; |
234 | 237 | ||
235 | l = enable ? OMAP2_MCSPI_CHCTRL_EN : 0; | 238 | l = cs->chctrl0; |
236 | mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, l); | 239 | if (enable) |
240 | l |= OMAP2_MCSPI_CHCTRL_EN; | ||
241 | else | ||
242 | l &= ~OMAP2_MCSPI_CHCTRL_EN; | ||
243 | cs->chctrl0 = l; | ||
244 | mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, cs->chctrl0); | ||
237 | /* Flash post-writes */ | 245 | /* Flash post-writes */ |
238 | mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0); | 246 | mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0); |
239 | } | 247 | } |
@@ -840,7 +848,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, | |||
840 | struct omap2_mcspi_cs *cs = spi->controller_state; | 848 | struct omap2_mcspi_cs *cs = spi->controller_state; |
841 | struct omap2_mcspi *mcspi; | 849 | struct omap2_mcspi *mcspi; |
842 | struct spi_master *spi_cntrl; | 850 | struct spi_master *spi_cntrl; |
843 | u32 l = 0, div = 0; | 851 | u32 l = 0, clkd = 0, div, extclk = 0, clkg = 0; |
844 | u8 word_len = spi->bits_per_word; | 852 | u8 word_len = spi->bits_per_word; |
845 | u32 speed_hz = spi->max_speed_hz; | 853 | u32 speed_hz = spi->max_speed_hz; |
846 | 854 | ||
@@ -856,7 +864,17 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, | |||
856 | speed_hz = t->speed_hz; | 864 | speed_hz = t->speed_hz; |
857 | 865 | ||
858 | speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ); | 866 | speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ); |
859 | div = omap2_mcspi_calc_divisor(speed_hz); | 867 | if (speed_hz < (OMAP2_MCSPI_MAX_FREQ / OMAP2_MCSPI_MAX_DIVIDER)) { |
868 | clkd = omap2_mcspi_calc_divisor(speed_hz); | ||
869 | speed_hz = OMAP2_MCSPI_MAX_FREQ >> clkd; | ||
870 | clkg = 0; | ||
871 | } else { | ||
872 | div = (OMAP2_MCSPI_MAX_FREQ + speed_hz - 1) / speed_hz; | ||
873 | speed_hz = OMAP2_MCSPI_MAX_FREQ / div; | ||
874 | clkd = (div - 1) & 0xf; | ||
875 | extclk = (div - 1) >> 4; | ||
876 | clkg = OMAP2_MCSPI_CHCONF_CLKG; | ||
877 | } | ||
860 | 878 | ||
861 | l = mcspi_cached_chconf0(spi); | 879 | l = mcspi_cached_chconf0(spi); |
862 | 880 | ||
@@ -885,7 +903,16 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, | |||
885 | 903 | ||
886 | /* set clock divisor */ | 904 | /* set clock divisor */ |
887 | l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK; | 905 | l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK; |
888 | l |= div << 2; | 906 | l |= clkd << 2; |
907 | |||
908 | /* set clock granularity */ | ||
909 | l &= ~OMAP2_MCSPI_CHCONF_CLKG; | ||
910 | l |= clkg; | ||
911 | if (clkg) { | ||
912 | cs->chctrl0 &= ~OMAP2_MCSPI_CHCTRL_EXTCLK_MASK; | ||
913 | cs->chctrl0 |= extclk << 8; | ||
914 | mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, cs->chctrl0); | ||
915 | } | ||
889 | 916 | ||
890 | /* set SPI mode 0..3 */ | 917 | /* set SPI mode 0..3 */ |
891 | if (spi->mode & SPI_CPOL) | 918 | if (spi->mode & SPI_CPOL) |
@@ -900,7 +927,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, | |||
900 | mcspi_write_chconf0(spi, l); | 927 | mcspi_write_chconf0(spi, l); |
901 | 928 | ||
902 | dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", | 929 | dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", |
903 | OMAP2_MCSPI_MAX_FREQ >> div, | 930 | speed_hz, |
904 | (spi->mode & SPI_CPHA) ? "trailing" : "leading", | 931 | (spi->mode & SPI_CPHA) ? "trailing" : "leading", |
905 | (spi->mode & SPI_CPOL) ? "inverted" : "normal"); | 932 | (spi->mode & SPI_CPOL) ? "inverted" : "normal"); |
906 | 933 | ||
@@ -972,6 +999,7 @@ static int omap2_mcspi_setup(struct spi_device *spi) | |||
972 | cs->base = mcspi->base + spi->chip_select * 0x14; | 999 | cs->base = mcspi->base + spi->chip_select * 0x14; |
973 | cs->phys = mcspi->phys + spi->chip_select * 0x14; | 1000 | cs->phys = mcspi->phys + spi->chip_select * 0x14; |
974 | cs->chconf0 = 0; | 1001 | cs->chconf0 = 0; |
1002 | cs->chctrl0 = 0; | ||
975 | spi->controller_state = cs; | 1003 | spi->controller_state = cs; |
976 | /* Link this to context save list */ | 1004 | /* Link this to context save list */ |
977 | list_add_tail(&cs->node, &ctx->cs); | 1005 | list_add_tail(&cs->node, &ctx->cs); |
@@ -1057,12 +1085,15 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) | |||
1057 | status = -EINVAL; | 1085 | status = -EINVAL; |
1058 | break; | 1086 | break; |
1059 | } | 1087 | } |
1060 | if (par_override || t->speed_hz || t->bits_per_word) { | 1088 | if (par_override || |
1089 | (t->speed_hz != spi->max_speed_hz) || | ||
1090 | (t->bits_per_word != spi->bits_per_word)) { | ||
1061 | par_override = 1; | 1091 | par_override = 1; |
1062 | status = omap2_mcspi_setup_transfer(spi, t); | 1092 | status = omap2_mcspi_setup_transfer(spi, t); |
1063 | if (status < 0) | 1093 | if (status < 0) |
1064 | break; | 1094 | break; |
1065 | if (!t->speed_hz && !t->bits_per_word) | 1095 | if (t->speed_hz == spi->max_speed_hz && |
1096 | t->bits_per_word == spi->bits_per_word) | ||
1066 | par_override = 0; | 1097 | par_override = 0; |
1067 | } | 1098 | } |
1068 | if (cd && cd->cs_per_word) { | 1099 | if (cd && cd->cs_per_word) { |
@@ -1176,16 +1207,12 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master, | |||
1176 | m->actual_length = 0; | 1207 | m->actual_length = 0; |
1177 | m->status = 0; | 1208 | m->status = 0; |
1178 | 1209 | ||
1179 | /* reject invalid messages and transfers */ | ||
1180 | if (list_empty(&m->transfers)) | ||
1181 | return -EINVAL; | ||
1182 | list_for_each_entry(t, &m->transfers, transfer_list) { | 1210 | list_for_each_entry(t, &m->transfers, transfer_list) { |
1183 | const void *tx_buf = t->tx_buf; | 1211 | const void *tx_buf = t->tx_buf; |
1184 | void *rx_buf = t->rx_buf; | 1212 | void *rx_buf = t->rx_buf; |
1185 | unsigned len = t->len; | 1213 | unsigned len = t->len; |
1186 | 1214 | ||
1187 | if (t->speed_hz > OMAP2_MCSPI_MAX_FREQ | 1215 | if ((len && !(rx_buf || tx_buf))) { |
1188 | || (len && !(rx_buf || tx_buf))) { | ||
1189 | dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", | 1216 | dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", |
1190 | t->speed_hz, | 1217 | t->speed_hz, |
1191 | len, | 1218 | len, |
@@ -1194,12 +1221,6 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master, | |||
1194 | t->bits_per_word); | 1221 | t->bits_per_word); |
1195 | return -EINVAL; | 1222 | return -EINVAL; |
1196 | } | 1223 | } |
1197 | if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) { | ||
1198 | dev_dbg(mcspi->dev, "speed_hz %d below minimum %d Hz\n", | ||
1199 | t->speed_hz, | ||
1200 | OMAP2_MCSPI_MAX_FREQ >> 15); | ||
1201 | return -EINVAL; | ||
1202 | } | ||
1203 | 1224 | ||
1204 | if (m->is_dma_mapped || len < DMA_MIN_BYTES) | 1225 | if (m->is_dma_mapped || len < DMA_MIN_BYTES) |
1205 | continue; | 1226 | continue; |
@@ -1311,6 +1332,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev) | |||
1311 | master->transfer_one_message = omap2_mcspi_transfer_one_message; | 1332 | master->transfer_one_message = omap2_mcspi_transfer_one_message; |
1312 | master->cleanup = omap2_mcspi_cleanup; | 1333 | master->cleanup = omap2_mcspi_cleanup; |
1313 | master->dev.of_node = node; | 1334 | master->dev.of_node = node; |
1335 | master->max_speed_hz = OMAP2_MCSPI_MAX_FREQ; | ||
1336 | master->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15; | ||
1314 | 1337 | ||
1315 | platform_set_drvdata(pdev, master); | 1338 | platform_set_drvdata(pdev, master); |
1316 | 1339 | ||