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.c65
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
155static inline void mcspi_write_reg(struct spi_master *master, 157static 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
231static 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)
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