diff options
author | Hiep Cao Minh <cm-hiep@jinso.co.jp> | 2013-09-03 00:10:26 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-09-16 19:22:50 -0400 |
commit | 5ce0ba88650f2606244a761d92e2b725f4ab3583 (patch) | |
tree | e82cb9821e68d81ecbef0ca874458c5f40138b9f | |
parent | 272b98c6455f00884f0350f775c5342358ebb73f (diff) |
spi: rcar: add Renesas QSPI support on RSPI
The R8A7790 has QSPI module which is very similar to RSPI.
This patch adds into RSPI module together to supports QSPI module.
Signed-off-by: Hiep Cao Minh <cm-hiep@jinso.co.jp>
Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r-- | drivers/spi/Kconfig | 2 | ||||
-rw-r--r-- | drivers/spi/spi-rspi.c | 183 | ||||
-rw-r--r-- | include/linux/spi/rspi.h | 2 |
3 files changed, 145 insertions, 42 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index b9c53cc40e1f..738facf90597 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -369,7 +369,7 @@ config SPI_PXA2XX_PCI | |||
369 | 369 | ||
370 | config SPI_RSPI | 370 | config SPI_RSPI |
371 | tristate "Renesas RSPI controller" | 371 | tristate "Renesas RSPI controller" |
372 | depends on SUPERH && SH_DMAE_BASE | 372 | depends on (SUPERH || ARCH_SHMOBILE) && SH_DMAE_BASE |
373 | help | 373 | help |
374 | SPI driver for Renesas RSPI blocks. | 374 | SPI driver for Renesas RSPI blocks. |
375 | 375 | ||
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 8719206a03a0..4c8dbac11b42 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c | |||
@@ -59,6 +59,14 @@ | |||
59 | #define RSPI_SPCMD6 0x1c | 59 | #define RSPI_SPCMD6 0x1c |
60 | #define RSPI_SPCMD7 0x1e | 60 | #define RSPI_SPCMD7 0x1e |
61 | 61 | ||
62 | /*qspi only */ | ||
63 | #define QSPI_SPBFCR 0x18 | ||
64 | #define QSPI_SPBDCR 0x1a | ||
65 | #define QSPI_SPBMUL0 0x1c | ||
66 | #define QSPI_SPBMUL1 0x20 | ||
67 | #define QSPI_SPBMUL2 0x24 | ||
68 | #define QSPI_SPBMUL3 0x28 | ||
69 | |||
62 | /* SPCR */ | 70 | /* SPCR */ |
63 | #define SPCR_SPRIE 0x80 | 71 | #define SPCR_SPRIE 0x80 |
64 | #define SPCR_SPE 0x40 | 72 | #define SPCR_SPE 0x40 |
@@ -126,6 +134,8 @@ | |||
126 | #define SPCMD_LSBF 0x1000 | 134 | #define SPCMD_LSBF 0x1000 |
127 | #define SPCMD_SPB_MASK 0x0f00 | 135 | #define SPCMD_SPB_MASK 0x0f00 |
128 | #define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK) | 136 | #define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK) |
137 | #define SPCMD_SPB_8BIT 0x0000 /* qspi only */ | ||
138 | #define SPCMD_SPB_16BIT 0x0100 | ||
129 | #define SPCMD_SPB_20BIT 0x0000 | 139 | #define SPCMD_SPB_20BIT 0x0000 |
130 | #define SPCMD_SPB_24BIT 0x0100 | 140 | #define SPCMD_SPB_24BIT 0x0100 |
131 | #define SPCMD_SPB_32BIT 0x0200 | 141 | #define SPCMD_SPB_32BIT 0x0200 |
@@ -135,6 +145,10 @@ | |||
135 | #define SPCMD_CPOL 0x0002 | 145 | #define SPCMD_CPOL 0x0002 |
136 | #define SPCMD_CPHA 0x0001 | 146 | #define SPCMD_CPHA 0x0001 |
137 | 147 | ||
148 | /* SPBFCR */ | ||
149 | #define SPBFCR_TXRST 0x80 /* qspi only */ | ||
150 | #define SPBFCR_RXRST 0x40 /* qspi only */ | ||
151 | |||
138 | struct rspi_data { | 152 | struct rspi_data { |
139 | void __iomem *addr; | 153 | void __iomem *addr; |
140 | u32 max_speed_hz; | 154 | u32 max_speed_hz; |
@@ -145,6 +159,7 @@ struct rspi_data { | |||
145 | spinlock_t lock; | 159 | spinlock_t lock; |
146 | struct clk *clk; | 160 | struct clk *clk; |
147 | unsigned char spsr; | 161 | unsigned char spsr; |
162 | const struct spi_ops *ops; | ||
148 | 163 | ||
149 | /* for dmaengine */ | 164 | /* for dmaengine */ |
150 | struct dma_chan *chan_tx; | 165 | struct dma_chan *chan_tx; |
@@ -165,6 +180,11 @@ static void rspi_write16(struct rspi_data *rspi, u16 data, u16 offset) | |||
165 | iowrite16(data, rspi->addr + offset); | 180 | iowrite16(data, rspi->addr + offset); |
166 | } | 181 | } |
167 | 182 | ||
183 | static void rspi_write32(struct rspi_data *rspi, u32 data, u16 offset) | ||
184 | { | ||
185 | iowrite32(data, rspi->addr + offset); | ||
186 | } | ||
187 | |||
168 | static u8 rspi_read8(struct rspi_data *rspi, u16 offset) | 188 | static u8 rspi_read8(struct rspi_data *rspi, u16 offset) |
169 | { | 189 | { |
170 | return ioread8(rspi->addr + offset); | 190 | return ioread8(rspi->addr + offset); |
@@ -175,17 +195,98 @@ static u16 rspi_read16(struct rspi_data *rspi, u16 offset) | |||
175 | return ioread16(rspi->addr + offset); | 195 | return ioread16(rspi->addr + offset); |
176 | } | 196 | } |
177 | 197 | ||
178 | static unsigned char rspi_calc_spbr(struct rspi_data *rspi) | 198 | /* optional functions */ |
199 | struct spi_ops { | ||
200 | int (*set_config_register)(struct rspi_data *rspi, int access_size); | ||
201 | }; | ||
202 | |||
203 | /* | ||
204 | * functions for RSPI | ||
205 | */ | ||
206 | static int rspi_set_config_register(struct rspi_data *rspi, int access_size) | ||
179 | { | 207 | { |
180 | int tmp; | 208 | int spbr; |
181 | unsigned char spbr; | 209 | |
210 | /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */ | ||
211 | rspi_write8(rspi, 0x00, RSPI_SPPCR); | ||
182 | 212 | ||
183 | tmp = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1; | 213 | /* Sets transfer bit rate */ |
184 | spbr = clamp(tmp, 0, 255); | 214 | spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1; |
215 | rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); | ||
216 | |||
217 | /* Sets number of frames to be used: 1 frame */ | ||
218 | rspi_write8(rspi, 0x00, RSPI_SPDCR); | ||
185 | 219 | ||
186 | return spbr; | 220 | /* Sets RSPCK, SSL, next-access delay value */ |
221 | rspi_write8(rspi, 0x00, RSPI_SPCKD); | ||
222 | rspi_write8(rspi, 0x00, RSPI_SSLND); | ||
223 | rspi_write8(rspi, 0x00, RSPI_SPND); | ||
224 | |||
225 | /* Sets parity, interrupt mask */ | ||
226 | rspi_write8(rspi, 0x00, RSPI_SPCR2); | ||
227 | |||
228 | /* Sets SPCMD */ | ||
229 | rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP, | ||
230 | RSPI_SPCMD0); | ||
231 | |||
232 | /* Sets RSPI mode */ | ||
233 | rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); | ||
234 | |||
235 | return 0; | ||
187 | } | 236 | } |
188 | 237 | ||
238 | /* | ||
239 | * functions for QSPI | ||
240 | */ | ||
241 | static int qspi_set_config_register(struct rspi_data *rspi, int access_size) | ||
242 | { | ||
243 | u16 spcmd; | ||
244 | int spbr; | ||
245 | |||
246 | /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */ | ||
247 | rspi_write8(rspi, 0x00, RSPI_SPPCR); | ||
248 | |||
249 | /* Sets transfer bit rate */ | ||
250 | spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz); | ||
251 | rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); | ||
252 | |||
253 | /* Sets number of frames to be used: 1 frame */ | ||
254 | rspi_write8(rspi, 0x00, RSPI_SPDCR); | ||
255 | |||
256 | /* Sets RSPCK, SSL, next-access delay value */ | ||
257 | rspi_write8(rspi, 0x00, RSPI_SPCKD); | ||
258 | rspi_write8(rspi, 0x00, RSPI_SSLND); | ||
259 | rspi_write8(rspi, 0x00, RSPI_SPND); | ||
260 | |||
261 | /* Data Length Setting */ | ||
262 | if (access_size == 8) | ||
263 | spcmd = SPCMD_SPB_8BIT; | ||
264 | else if (access_size == 16) | ||
265 | spcmd = SPCMD_SPB_16BIT; | ||
266 | else if (access_size == 32) | ||
267 | spcmd = SPCMD_SPB_32BIT; | ||
268 | |||
269 | spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SSLKP | SPCMD_SPNDEN; | ||
270 | |||
271 | /* Resets transfer data length */ | ||
272 | rspi_write32(rspi, 0, QSPI_SPBMUL0); | ||
273 | |||
274 | /* Resets transmit and receive buffer */ | ||
275 | rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR); | ||
276 | /* Sets buffer to allow normal operation */ | ||
277 | rspi_write8(rspi, 0x00, QSPI_SPBFCR); | ||
278 | |||
279 | /* Sets SPCMD */ | ||
280 | rspi_write16(rspi, spcmd, RSPI_SPCMD0); | ||
281 | |||
282 | /* Enables SPI function in a master mode */ | ||
283 | rspi_write8(rspi, SPCR_SPE | SPCR_MSTR, RSPI_SPCR); | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | #define set_config_register(spi, n) spi->ops->set_config_register(spi, n) | ||
289 | |||
189 | static void rspi_enable_irq(struct rspi_data *rspi, u8 enable) | 290 | static void rspi_enable_irq(struct rspi_data *rspi, u8 enable) |
190 | { | 291 | { |
191 | rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR); | 292 | rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR); |
@@ -220,35 +321,6 @@ static void rspi_negate_ssl(struct rspi_data *rspi) | |||
220 | rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR); | 321 | rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR); |
221 | } | 322 | } |
222 | 323 | ||
223 | static int rspi_set_config_register(struct rspi_data *rspi, int access_size) | ||
224 | { | ||
225 | /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */ | ||
226 | rspi_write8(rspi, 0x00, RSPI_SPPCR); | ||
227 | |||
228 | /* Sets transfer bit rate */ | ||
229 | rspi_write8(rspi, rspi_calc_spbr(rspi), RSPI_SPBR); | ||
230 | |||
231 | /* Sets number of frames to be used: 1 frame */ | ||
232 | rspi_write8(rspi, 0x00, RSPI_SPDCR); | ||
233 | |||
234 | /* Sets RSPCK, SSL, next-access delay value */ | ||
235 | rspi_write8(rspi, 0x00, RSPI_SPCKD); | ||
236 | rspi_write8(rspi, 0x00, RSPI_SSLND); | ||
237 | rspi_write8(rspi, 0x00, RSPI_SPND); | ||
238 | |||
239 | /* Sets parity, interrupt mask */ | ||
240 | rspi_write8(rspi, 0x00, RSPI_SPCR2); | ||
241 | |||
242 | /* Sets SPCMD */ | ||
243 | rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP, | ||
244 | RSPI_SPCMD0); | ||
245 | |||
246 | /* Sets RSPI mode */ | ||
247 | rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg, | 324 | static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg, |
253 | struct spi_transfer *t) | 325 | struct spi_transfer *t) |
254 | { | 326 | { |
@@ -616,7 +688,7 @@ static int rspi_setup(struct spi_device *spi) | |||
616 | spi->bits_per_word = 8; | 688 | spi->bits_per_word = 8; |
617 | rspi->max_speed_hz = spi->max_speed_hz; | 689 | rspi->max_speed_hz = spi->max_speed_hz; |
618 | 690 | ||
619 | rspi_set_config_register(rspi, 8); | 691 | set_config_register(rspi, 8); |
620 | 692 | ||
621 | return 0; | 693 | return 0; |
622 | } | 694 | } |
@@ -745,7 +817,16 @@ static int rspi_probe(struct platform_device *pdev) | |||
745 | struct rspi_data *rspi; | 817 | struct rspi_data *rspi; |
746 | int ret, irq; | 818 | int ret, irq; |
747 | char clk_name[16]; | 819 | char clk_name[16]; |
748 | 820 | struct rspi_plat_data *rspi_pd = pdev->dev.platform_data; | |
821 | const struct spi_ops *ops; | ||
822 | const struct platform_device_id *id_entry = pdev->id_entry; | ||
823 | |||
824 | ops = (struct spi_ops *)id_entry->driver_data; | ||
825 | /* ops parameter check */ | ||
826 | if (!ops->set_config_register) { | ||
827 | dev_err(&pdev->dev, "there is no set_config_register\n"); | ||
828 | return -ENODEV; | ||
829 | } | ||
749 | /* get base addr */ | 830 | /* get base addr */ |
750 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 831 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
751 | if (unlikely(res == NULL)) { | 832 | if (unlikely(res == NULL)) { |
@@ -767,7 +848,7 @@ static int rspi_probe(struct platform_device *pdev) | |||
767 | 848 | ||
768 | rspi = spi_master_get_devdata(master); | 849 | rspi = spi_master_get_devdata(master); |
769 | platform_set_drvdata(pdev, rspi); | 850 | platform_set_drvdata(pdev, rspi); |
770 | 851 | rspi->ops = ops; | |
771 | rspi->master = master; | 852 | rspi->master = master; |
772 | rspi->addr = ioremap(res->start, resource_size(res)); | 853 | rspi->addr = ioremap(res->start, resource_size(res)); |
773 | if (rspi->addr == NULL) { | 854 | if (rspi->addr == NULL) { |
@@ -776,7 +857,7 @@ static int rspi_probe(struct platform_device *pdev) | |||
776 | goto error1; | 857 | goto error1; |
777 | } | 858 | } |
778 | 859 | ||
779 | snprintf(clk_name, sizeof(clk_name), "rspi%d", pdev->id); | 860 | snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id); |
780 | rspi->clk = clk_get(&pdev->dev, clk_name); | 861 | rspi->clk = clk_get(&pdev->dev, clk_name); |
781 | if (IS_ERR(rspi->clk)) { | 862 | if (IS_ERR(rspi->clk)) { |
782 | dev_err(&pdev->dev, "cannot get clock\n"); | 863 | dev_err(&pdev->dev, "cannot get clock\n"); |
@@ -790,7 +871,10 @@ static int rspi_probe(struct platform_device *pdev) | |||
790 | INIT_WORK(&rspi->ws, rspi_work); | 871 | INIT_WORK(&rspi->ws, rspi_work); |
791 | init_waitqueue_head(&rspi->wait); | 872 | init_waitqueue_head(&rspi->wait); |
792 | 873 | ||
793 | master->num_chipselect = 2; | 874 | master->num_chipselect = rspi_pd->num_chipselect; |
875 | if (!master->num_chipselect) | ||
876 | master->num_chipselect = 2; /* default */ | ||
877 | |||
794 | master->bus_num = pdev->id; | 878 | master->bus_num = pdev->id; |
795 | master->setup = rspi_setup; | 879 | master->setup = rspi_setup; |
796 | master->transfer = rspi_transfer; | 880 | master->transfer = rspi_transfer; |
@@ -832,11 +916,28 @@ error1: | |||
832 | return ret; | 916 | return ret; |
833 | } | 917 | } |
834 | 918 | ||
919 | static struct spi_ops rspi_ops = { | ||
920 | .set_config_register = rspi_set_config_register, | ||
921 | }; | ||
922 | |||
923 | static struct spi_ops qspi_ops = { | ||
924 | .set_config_register = qspi_set_config_register, | ||
925 | }; | ||
926 | |||
927 | static struct platform_device_id spi_driver_ids[] = { | ||
928 | { "rspi", (kernel_ulong_t)&rspi_ops }, | ||
929 | { "qspi", (kernel_ulong_t)&qspi_ops }, | ||
930 | {}, | ||
931 | }; | ||
932 | |||
933 | MODULE_DEVICE_TABLE(platform, spi_driver_ids); | ||
934 | |||
835 | static struct platform_driver rspi_driver = { | 935 | static struct platform_driver rspi_driver = { |
836 | .probe = rspi_probe, | 936 | .probe = rspi_probe, |
837 | .remove = rspi_remove, | 937 | .remove = rspi_remove, |
938 | .id_table = spi_driver_ids, | ||
838 | .driver = { | 939 | .driver = { |
839 | .name = "rspi", | 940 | .name = "renesas_spi", |
840 | .owner = THIS_MODULE, | 941 | .owner = THIS_MODULE, |
841 | }, | 942 | }, |
842 | }; | 943 | }; |
diff --git a/include/linux/spi/rspi.h b/include/linux/spi/rspi.h index 900f0e328235..a25bd6f65e7f 100644 --- a/include/linux/spi/rspi.h +++ b/include/linux/spi/rspi.h | |||
@@ -26,6 +26,8 @@ struct rspi_plat_data { | |||
26 | unsigned int dma_rx_id; | 26 | unsigned int dma_rx_id; |
27 | 27 | ||
28 | unsigned dma_width_16bit:1; /* DMAC read/write width = 16-bit */ | 28 | unsigned dma_width_16bit:1; /* DMAC read/write width = 16-bit */ |
29 | |||
30 | u16 num_chipselect; | ||
29 | }; | 31 | }; |
30 | 32 | ||
31 | #endif | 33 | #endif |