aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-omap2-mcspi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-omap2-mcspi.c')
-rw-r--r--drivers/spi/spi-omap2-mcspi.c64
1 files changed, 44 insertions, 20 deletions
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 94f133cb2770..2941c5b96ebc 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -44,6 +44,7 @@
44#include <linux/platform_data/spi-omap2-mcspi.h> 44#include <linux/platform_data/spi-omap2-mcspi.h>
45 45
46#define OMAP2_MCSPI_MAX_FREQ 48000000 46#define OMAP2_MCSPI_MAX_FREQ 48000000
47#define OMAP2_MCSPI_MAX_DIVIDER 4096
47#define OMAP2_MCSPI_MAX_FIFODEPTH 64 48#define OMAP2_MCSPI_MAX_FIFODEPTH 64
48#define OMAP2_MCSPI_MAX_FIFOWCNT 0xFFFF 49#define OMAP2_MCSPI_MAX_FIFOWCNT 0xFFFF
49#define SPI_AUTOSUSPEND_TIMEOUT 2000 50#define SPI_AUTOSUSPEND_TIMEOUT 2000
@@ -88,6 +89,7 @@
88#define OMAP2_MCSPI_CHCONF_FORCE BIT(20) 89#define OMAP2_MCSPI_CHCONF_FORCE BIT(20)
89#define OMAP2_MCSPI_CHCONF_FFET BIT(27) 90#define OMAP2_MCSPI_CHCONF_FFET BIT(27)
90#define OMAP2_MCSPI_CHCONF_FFER BIT(28) 91#define OMAP2_MCSPI_CHCONF_FFER BIT(28)
92#define OMAP2_MCSPI_CHCONF_CLKG BIT(29)
91 93
92#define OMAP2_MCSPI_CHSTAT_RXS BIT(0) 94#define OMAP2_MCSPI_CHSTAT_RXS BIT(0)
93#define OMAP2_MCSPI_CHSTAT_TXS BIT(1) 95#define OMAP2_MCSPI_CHSTAT_TXS BIT(1)
@@ -95,6 +97,7 @@
95#define OMAP2_MCSPI_CHSTAT_TXFFE BIT(3) 97#define OMAP2_MCSPI_CHSTAT_TXFFE BIT(3)
96 98
97#define OMAP2_MCSPI_CHCTRL_EN BIT(0) 99#define OMAP2_MCSPI_CHCTRL_EN BIT(0)
100#define OMAP2_MCSPI_CHCTRL_EXTCLK_MASK (0xff << 8)
98 101
99#define OMAP2_MCSPI_WAKEUPENABLE_WKEN BIT(0) 102#define OMAP2_MCSPI_WAKEUPENABLE_WKEN BIT(0)
100 103
@@ -148,7 +151,7 @@ struct omap2_mcspi_cs {
148 int word_len; 151 int word_len;
149 struct list_head node; 152 struct list_head node;
150 /* Context save and restore shadow register */ 153 /* Context save and restore shadow register */
151 u32 chconf0; 154 u32 chconf0, chctrl0;
152}; 155};
153 156
154static inline void mcspi_write_reg(struct spi_master *master, 157static inline void mcspi_write_reg(struct spi_master *master,
@@ -229,10 +232,16 @@ static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
229 232
230static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable) 233static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
231{ 234{
235 struct omap2_mcspi_cs *cs = spi->controller_state;
232 u32 l; 236 u32 l;
233 237
234 l = enable ? OMAP2_MCSPI_CHCTRL_EN : 0; 238 l = cs->chctrl0;
235 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);
236 /* Flash post-writes */ 245 /* Flash post-writes */
237 mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0); 246 mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0);
238} 247}
@@ -839,7 +848,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
839 struct omap2_mcspi_cs *cs = spi->controller_state; 848 struct omap2_mcspi_cs *cs = spi->controller_state;
840 struct omap2_mcspi *mcspi; 849 struct omap2_mcspi *mcspi;
841 struct spi_master *spi_cntrl; 850 struct spi_master *spi_cntrl;
842 u32 l = 0, div = 0; 851 u32 l = 0, clkd = 0, div, extclk = 0, clkg = 0;
843 u8 word_len = spi->bits_per_word; 852 u8 word_len = spi->bits_per_word;
844 u32 speed_hz = spi->max_speed_hz; 853 u32 speed_hz = spi->max_speed_hz;
845 854
@@ -855,7 +864,17 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
855 speed_hz = t->speed_hz; 864 speed_hz = t->speed_hz;
856 865
857 speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ); 866 speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
858 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 }
859 878
860 l = mcspi_cached_chconf0(spi); 879 l = mcspi_cached_chconf0(spi);
861 880
@@ -884,7 +903,16 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
884 903
885 /* set clock divisor */ 904 /* set clock divisor */
886 l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK; 905 l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
887 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 }
888 916
889 /* set SPI mode 0..3 */ 917 /* set SPI mode 0..3 */
890 if (spi->mode & SPI_CPOL) 918 if (spi->mode & SPI_CPOL)
@@ -899,7 +927,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
899 mcspi_write_chconf0(spi, l); 927 mcspi_write_chconf0(spi, l);
900 928
901 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",
902 OMAP2_MCSPI_MAX_FREQ >> div, 930 speed_hz,
903 (spi->mode & SPI_CPHA) ? "trailing" : "leading", 931 (spi->mode & SPI_CPHA) ? "trailing" : "leading",
904 (spi->mode & SPI_CPOL) ? "inverted" : "normal"); 932 (spi->mode & SPI_CPOL) ? "inverted" : "normal");
905 933
@@ -971,6 +999,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
971 cs->base = mcspi->base + spi->chip_select * 0x14; 999 cs->base = mcspi->base + spi->chip_select * 0x14;
972 cs->phys = mcspi->phys + spi->chip_select * 0x14; 1000 cs->phys = mcspi->phys + spi->chip_select * 0x14;
973 cs->chconf0 = 0; 1001 cs->chconf0 = 0;
1002 cs->chctrl0 = 0;
974 spi->controller_state = cs; 1003 spi->controller_state = cs;
975 /* Link this to context save list */ 1004 /* Link this to context save list */
976 list_add_tail(&cs->node, &ctx->cs); 1005 list_add_tail(&cs->node, &ctx->cs);
@@ -1056,12 +1085,15 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
1056 status = -EINVAL; 1085 status = -EINVAL;
1057 break; 1086 break;
1058 } 1087 }
1059 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)) {
1060 par_override = 1; 1091 par_override = 1;
1061 status = omap2_mcspi_setup_transfer(spi, t); 1092 status = omap2_mcspi_setup_transfer(spi, t);
1062 if (status < 0) 1093 if (status < 0)
1063 break; 1094 break;
1064 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)
1065 par_override = 0; 1097 par_override = 0;
1066 } 1098 }
1067 if (cd && cd->cs_per_word) { 1099 if (cd && cd->cs_per_word) {
@@ -1175,16 +1207,12 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
1175 m->actual_length = 0; 1207 m->actual_length = 0;
1176 m->status = 0; 1208 m->status = 0;
1177 1209
1178 /* reject invalid messages and transfers */
1179 if (list_empty(&m->transfers))
1180 return -EINVAL;
1181 list_for_each_entry(t, &m->transfers, transfer_list) { 1210 list_for_each_entry(t, &m->transfers, transfer_list) {
1182 const void *tx_buf = t->tx_buf; 1211 const void *tx_buf = t->tx_buf;
1183 void *rx_buf = t->rx_buf; 1212 void *rx_buf = t->rx_buf;
1184 unsigned len = t->len; 1213 unsigned len = t->len;
1185 1214
1186 if (t->speed_hz > OMAP2_MCSPI_MAX_FREQ 1215 if ((len && !(rx_buf || tx_buf))) {
1187 || (len && !(rx_buf || tx_buf))) {
1188 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",
1189 t->speed_hz, 1217 t->speed_hz,
1190 len, 1218 len,
@@ -1193,12 +1221,6 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
1193 t->bits_per_word); 1221 t->bits_per_word);
1194 return -EINVAL; 1222 return -EINVAL;
1195 } 1223 }
1196 if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) {
1197 dev_dbg(mcspi->dev, "speed_hz %d below minimum %d Hz\n",
1198 t->speed_hz,
1199 OMAP2_MCSPI_MAX_FREQ >> 15);
1200 return -EINVAL;
1201 }
1202 1224
1203 if (m->is_dma_mapped || len < DMA_MIN_BYTES) 1225 if (m->is_dma_mapped || len < DMA_MIN_BYTES)
1204 continue; 1226 continue;
@@ -1310,6 +1332,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
1310 master->transfer_one_message = omap2_mcspi_transfer_one_message; 1332 master->transfer_one_message = omap2_mcspi_transfer_one_message;
1311 master->cleanup = omap2_mcspi_cleanup; 1333 master->cleanup = omap2_mcspi_cleanup;
1312 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;
1313 1337
1314 platform_set_drvdata(pdev, master); 1338 platform_set_drvdata(pdev, master);
1315 1339