diff options
Diffstat (limited to 'drivers/spi/spi-sh-hspi.c')
-rw-r--r-- | drivers/spi/spi-sh-hspi.c | 43 |
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 | ||
71 | static 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) | ||
120 | static void hspi_hw_cs_ctrl(struct hspi_priv *hspi, int hi) | ||
121 | { | ||
122 | hspi_bit_set(hspi, SPSCR, (1 << 6), (hi) << 6); | ||
123 | } | ||
124 | |||
108 | static void hspi_hw_setup(struct hspi_priv *hspi, | 125 | static 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 | ||
161 | static int hspi_transfer_one_message(struct spi_master *master, | 178 | static 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; |