aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorPhil Edworthy <phil.edworthy@renesas.com>2012-11-22 09:37:27 -0500
committerGrant Likely <grant.likely@secretlab.ca>2012-11-23 04:52:43 -0500
commitce3293058637ada3b1837a77c8f9c672a51b2434 (patch)
treef4de2d04934ce061a4b5f460680b1aaf269ae806 /drivers/spi
parent743179849015dc71bb2ea63d8cd4bfa7fdfb4bc6 (diff)
spi/sh-hspi: add CS manual control support
The current HSPI driver used automatic CS control, leading to CS active for each byte transmitted. This patch changes the driver to manual CS control, and ensures CS is active thoughout a whole message. Additionally, it uses the cs_change field to determine if CS is disabled between transfers in the message. Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-sh-hspi.c43
1 files changed, 41 insertions, 2 deletions
diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c
index 796c077ef439..47c4beee8a0e 100644
--- a/drivers/spi/spi-sh-hspi.c
+++ b/drivers/spi/spi-sh-hspi.c
@@ -68,6 +68,16 @@ static u32 hspi_read(struct hspi_priv *hspi, int reg)
68 return ioread32(hspi->addr + reg); 68 return ioread32(hspi->addr + reg);
69} 69}
70 70
71static void hspi_bit_set(struct hspi_priv *hspi, int reg, u32 mask, u32 set)
72{
73 u32 val = hspi_read(hspi, reg);
74
75 val &= ~mask;
76 val |= set & mask;
77
78 hspi_write(hspi, reg, val);
79}
80
71/* 81/*
72 * transfer function 82 * transfer function
73 */ 83 */
@@ -105,6 +115,13 @@ static int hspi_unprepare_transfer(struct spi_master *master)
105 return 0; 115 return 0;
106} 116}
107 117
118#define hspi_hw_cs_enable(hspi) hspi_hw_cs_ctrl(hspi, 0)
119#define hspi_hw_cs_disable(hspi) hspi_hw_cs_ctrl(hspi, 1)
120static void hspi_hw_cs_ctrl(struct hspi_priv *hspi, int hi)
121{
122 hspi_bit_set(hspi, SPSCR, (1 << 6), (hi) << 6);
123}
124
108static void hspi_hw_setup(struct hspi_priv *hspi, 125static void hspi_hw_setup(struct hspi_priv *hspi,
109 struct spi_message *msg, 126 struct spi_message *msg,
110 struct spi_transfer *t) 127 struct spi_transfer *t)
@@ -155,7 +172,7 @@ static void hspi_hw_setup(struct hspi_priv *hspi,
155 172
156 hspi_write(hspi, SPCR, spcr); 173 hspi_write(hspi, SPCR, spcr);
157 hspi_write(hspi, SPSR, 0x0); 174 hspi_write(hspi, SPSR, 0x0);
158 hspi_write(hspi, SPSCR, 0x1); /* master mode */ 175 hspi_write(hspi, SPSCR, 0x21); /* master mode / CS control */
159} 176}
160 177
161static int hspi_transfer_one_message(struct spi_master *master, 178static int hspi_transfer_one_message(struct spi_master *master,
@@ -166,12 +183,21 @@ static int hspi_transfer_one_message(struct spi_master *master,
166 u32 tx; 183 u32 tx;
167 u32 rx; 184 u32 rx;
168 int ret, i; 185 int ret, i;
186 unsigned int cs_change;
187 const int nsecs = 50;
169 188
170 dev_dbg(hspi->dev, "%s\n", __func__); 189 dev_dbg(hspi->dev, "%s\n", __func__);
171 190
191 cs_change = 1;
172 ret = 0; 192 ret = 0;
173 list_for_each_entry(t, &msg->transfers, transfer_list) { 193 list_for_each_entry(t, &msg->transfers, transfer_list) {
174 hspi_hw_setup(hspi, msg, t); 194
195 if (cs_change) {
196 hspi_hw_setup(hspi, msg, t);
197 hspi_hw_cs_enable(hspi);
198 ndelay(nsecs);
199 }
200 cs_change = t->cs_change;
175 201
176 for (i = 0; i < t->len; i++) { 202 for (i = 0; i < t->len; i++) {
177 203
@@ -198,9 +224,22 @@ static int hspi_transfer_one_message(struct spi_master *master,
198 } 224 }
199 225
200 msg->actual_length += t->len; 226 msg->actual_length += t->len;
227
228 if (t->delay_usecs)
229 udelay(t->delay_usecs);
230
231 if (cs_change) {
232 ndelay(nsecs);
233 hspi_hw_cs_disable(hspi);
234 ndelay(nsecs);
235 }
201 } 236 }
202 237
203 msg->status = ret; 238 msg->status = ret;
239 if (!cs_change) {
240 ndelay(nsecs);
241 hspi_hw_cs_disable(hspi);
242 }
204 spi_finalize_current_message(master); 243 spi_finalize_current_message(master);
205 244
206 return ret; 245 return ret;