aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert+renesas@glider.be>2014-06-30 06:10:24 -0400
committerMark Brown <broonie@linaro.org>2014-06-30 14:54:57 -0400
commitb0d0ce8b6b91a0f6f99045b6019fc4c824634fb4 (patch)
tree12ad31b108d7c011917b72bb52f744764b64af3f
parent0312d59130693adad85c2acfbc0b92a669930a41 (diff)
spi: sh-msiof: Add DMA support
Add DMA support to the MSIOF driver using platform data. As MSIOF DMA is limited to 32-bit words (requiring byte/wordswapping for smaller wordsizes), and the group length is limited to 256 words, DMA is performed on two fixed pages, allocated and mapped at driver initialization time. Performance figures (in Mbps) on r8a7791/koelsch at different SPI clock frequencies for 1024-byte and 4096-byte transfers: 1024 bytes 4096 bytes - 3.25 MHz: PIO 2.1, DMA 2.6 | PIO 2.8, DMA 3.1 - 6.5 MHz: PIO 3.2, DMA 4.4 | PIO 5.0, DMA 5.9 - 13 MHz: PIO 4.2, DMA 6.6 | PIO 8.2, DMA 10.7 - 26 MHz: PIO 5.9, DMA 10.4 | PIO 12.4, DMA 18.4 Note that DMA is only faster than PIO for transfers that exceed the FIFO size (typically 64 words / 256 bytes). Also note that large transfers (larger than the group length for DMA, or larger than the FIFO size for PIO), should use cs-gpio (with the appropriate pinmux setup), as the hardware chipselect will be deasserted in between chunks. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--drivers/spi/spi-sh-msiof.c348
-rw-r--r--include/linux/spi/sh_msiof.h2
2 files changed, 343 insertions, 7 deletions
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index 824f44e6bd88..9922ed3a4441 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -2,6 +2,7 @@
2 * SuperH MSIOF SPI Master Interface 2 * SuperH MSIOF SPI Master Interface
3 * 3 *
4 * Copyright (c) 2009 Magnus Damm 4 * Copyright (c) 2009 Magnus Damm
5 * Copyright (C) 2014 Glider bvba
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -13,6 +14,8 @@
13#include <linux/clk.h> 14#include <linux/clk.h>
14#include <linux/completion.h> 15#include <linux/completion.h>
15#include <linux/delay.h> 16#include <linux/delay.h>
17#include <linux/dma-mapping.h>
18#include <linux/dmaengine.h>
16#include <linux/err.h> 19#include <linux/err.h>
17#include <linux/gpio.h> 20#include <linux/gpio.h>
18#include <linux/interrupt.h> 21#include <linux/interrupt.h>
@@ -23,6 +26,7 @@
23#include <linux/of_device.h> 26#include <linux/of_device.h>
24#include <linux/platform_device.h> 27#include <linux/platform_device.h>
25#include <linux/pm_runtime.h> 28#include <linux/pm_runtime.h>
29#include <linux/sh_dma.h>
26 30
27#include <linux/spi/sh_msiof.h> 31#include <linux/spi/sh_msiof.h>
28#include <linux/spi/spi.h> 32#include <linux/spi/spi.h>
@@ -37,6 +41,7 @@ struct sh_msiof_chipdata {
37}; 41};
38 42
39struct sh_msiof_spi_priv { 43struct sh_msiof_spi_priv {
44 struct spi_master *master;
40 void __iomem *mapbase; 45 void __iomem *mapbase;
41 struct clk *clk; 46 struct clk *clk;
42 struct platform_device *pdev; 47 struct platform_device *pdev;
@@ -45,6 +50,10 @@ struct sh_msiof_spi_priv {
45 struct completion done; 50 struct completion done;
46 int tx_fifo_size; 51 int tx_fifo_size;
47 int rx_fifo_size; 52 int rx_fifo_size;
53 void *tx_dma_page;
54 void *rx_dma_page;
55 dma_addr_t tx_dma_addr;
56 dma_addr_t rx_dma_addr;
48}; 57};
49 58
50#define TMDR1 0x00 /* Transmit Mode Register 1 */ 59#define TMDR1 0x00 /* Transmit Mode Register 1 */
@@ -84,6 +93,8 @@ struct sh_msiof_spi_priv {
84#define MDR2_WDLEN1(i) (((i) - 1) << 16) /* Word Count (1-64/256 (SH, A1))) */ 93#define MDR2_WDLEN1(i) (((i) - 1) << 16) /* Word Count (1-64/256 (SH, A1))) */
85#define MDR2_GRPMASK1 0x00000001 /* Group Output Mask 1 (SH, A1) */ 94#define MDR2_GRPMASK1 0x00000001 /* Group Output Mask 1 (SH, A1) */
86 95
96#define MAX_WDLEN 256U
97
87/* TSCR and RSCR */ 98/* TSCR and RSCR */
88#define SCR_BRPS_MASK 0x1f00 /* Prescaler Setting (1-32) */ 99#define SCR_BRPS_MASK 0x1f00 /* Prescaler Setting (1-32) */
89#define SCR_BRPS(i) (((i) - 1) << 8) 100#define SCR_BRPS(i) (((i) - 1) << 8)
@@ -282,8 +293,6 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
282 * 1 0 11 11 0 0 293 * 1 0 11 11 0 0
283 * 1 1 11 11 1 1 294 * 1 1 11 11 1 1
284 */ 295 */
285 sh_msiof_write(p, FCTR, 0);
286
287 tmp = MDR1_SYNCMD_SPI | 1 << MDR1_FLD_SHIFT | MDR1_XXSTP; 296 tmp = MDR1_SYNCMD_SPI | 1 << MDR1_FLD_SHIFT | MDR1_XXSTP;
288 tmp |= !cs_high << MDR1_SYNCAC_SHIFT; 297 tmp |= !cs_high << MDR1_SYNCAC_SHIFT;
289 tmp |= lsb_first << MDR1_BITLSB_SHIFT; 298 tmp |= lsb_first << MDR1_BITLSB_SHIFT;
@@ -319,8 +328,6 @@ static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p,
319 328
320 if (rx_buf) 329 if (rx_buf)
321 sh_msiof_write(p, RMDR2, dr2); 330 sh_msiof_write(p, RMDR2, dr2);
322
323 sh_msiof_write(p, IER, STR_TEOF | STR_REOF);
324} 331}
325 332
326static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p) 333static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p)
@@ -563,8 +570,12 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
563 /* the fifo contents need shifting */ 570 /* the fifo contents need shifting */
564 fifo_shift = 32 - bits; 571 fifo_shift = 32 - bits;
565 572
573 /* default FIFO watermarks for PIO */
574 sh_msiof_write(p, FCTR, 0);
575
566 /* setup msiof transfer mode registers */ 576 /* setup msiof transfer mode registers */
567 sh_msiof_spi_set_mode_regs(p, tx_buf, rx_buf, bits, words); 577 sh_msiof_spi_set_mode_regs(p, tx_buf, rx_buf, bits, words);
578 sh_msiof_write(p, IER, IER_TEOFE | IER_REOFE);
568 579
569 /* write tx fifo */ 580 /* write tx fifo */
570 if (tx_buf) 581 if (tx_buf)
@@ -609,11 +620,170 @@ stop_ier:
609 return ret; 620 return ret;
610} 621}
611 622
623static void sh_msiof_dma_complete(void *arg)
624{
625 struct sh_msiof_spi_priv *p = arg;
626
627 sh_msiof_write(p, IER, 0);
628 complete(&p->done);
629}
630
631static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
632 void *rx, unsigned int len)
633{
634 u32 ier_bits = 0;
635 struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL;
636 dma_cookie_t cookie;
637 int ret;
638
639 /* 1 stage FIFO watermarks for DMA */
640 sh_msiof_write(p, FCTR, FCTR_TFWM_1 | FCTR_RFWM_1);
641
642 /* setup msiof transfer mode registers (32-bit words) */
643 sh_msiof_spi_set_mode_regs(p, tx, rx, 32, len / 4);
644
645 if (tx) {
646 ier_bits |= IER_TDREQE | IER_TDMAE;
647 dma_sync_single_for_device(&p->pdev->dev, p->tx_dma_addr, len,
648 DMA_TO_DEVICE);
649 desc_tx = dmaengine_prep_slave_single(p->master->dma_tx,
650 p->tx_dma_addr, len, DMA_TO_DEVICE,
651 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
652 if (!desc_tx)
653 return -EIO;
654 }
655
656 if (rx) {
657 ier_bits |= IER_RDREQE | IER_RDMAE;
658 desc_rx = dmaengine_prep_slave_single(p->master->dma_rx,
659 p->rx_dma_addr, len, DMA_FROM_DEVICE,
660 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
661 if (!desc_rx)
662 return -EIO;
663 }
664 sh_msiof_write(p, IER, ier_bits);
665
666 reinit_completion(&p->done);
667
668 if (rx) {
669 desc_rx->callback = sh_msiof_dma_complete;
670 desc_rx->callback_param = p;
671 cookie = dmaengine_submit(desc_rx);
672 if (dma_submit_error(cookie)) {
673 ret = cookie;
674 goto stop_ier;
675 }
676 dma_async_issue_pending(p->master->dma_rx);
677 }
678
679 if (tx) {
680 if (rx) {
681 /* No callback */
682 desc_tx->callback = NULL;
683 } else {
684 desc_tx->callback = sh_msiof_dma_complete;
685 desc_tx->callback_param = p;
686 }
687 cookie = dmaengine_submit(desc_tx);
688 if (dma_submit_error(cookie)) {
689 ret = cookie;
690 goto stop_rx;
691 }
692 dma_async_issue_pending(p->master->dma_tx);
693 }
694
695 ret = sh_msiof_spi_start(p, rx);
696 if (ret) {
697 dev_err(&p->pdev->dev, "failed to start hardware\n");
698 goto stop_tx;
699 }
700
701 /* wait for tx fifo to be emptied / rx fifo to be filled */
702 ret = wait_for_completion_timeout(&p->done, HZ);
703 if (!ret) {
704 dev_err(&p->pdev->dev, "DMA timeout\n");
705 ret = -ETIMEDOUT;
706 goto stop_reset;
707 }
708
709 /* clear status bits */
710 sh_msiof_reset_str(p);
711
712 ret = sh_msiof_spi_stop(p, rx);
713 if (ret) {
714 dev_err(&p->pdev->dev, "failed to shut down hardware\n");
715 return ret;
716 }
717
718 if (rx)
719 dma_sync_single_for_cpu(&p->pdev->dev, p->rx_dma_addr, len,
720 DMA_FROM_DEVICE);
721
722 return 0;
723
724stop_reset:
725 sh_msiof_reset_str(p);
726 sh_msiof_spi_stop(p, rx);
727stop_tx:
728 if (tx)
729 dmaengine_terminate_all(p->master->dma_tx);
730stop_rx:
731 if (rx)
732 dmaengine_terminate_all(p->master->dma_rx);
733stop_ier:
734 sh_msiof_write(p, IER, 0);
735 return ret;
736}
737
738static void copy_bswap32(u32 *dst, const u32 *src, unsigned int words)
739{
740 /* src or dst can be unaligned, but not both */
741 if ((unsigned long)src & 3) {
742 while (words--) {
743 *dst++ = swab32(get_unaligned(src));
744 src++;
745 }
746 } else if ((unsigned long)dst & 3) {
747 while (words--) {
748 put_unaligned(swab32(*src++), dst);
749 dst++;
750 }
751 } else {
752 while (words--)
753 *dst++ = swab32(*src++);
754 }
755}
756
757static void copy_wswap32(u32 *dst, const u32 *src, unsigned int words)
758{
759 /* src or dst can be unaligned, but not both */
760 if ((unsigned long)src & 3) {
761 while (words--) {
762 *dst++ = swahw32(get_unaligned(src));
763 src++;
764 }
765 } else if ((unsigned long)dst & 3) {
766 while (words--) {
767 put_unaligned(swahw32(*src++), dst);
768 dst++;
769 }
770 } else {
771 while (words--)
772 *dst++ = swahw32(*src++);
773 }
774}
775
776static void copy_plain32(u32 *dst, const u32 *src, unsigned int words)
777{
778 memcpy(dst, src, words * 4);
779}
780
612static int sh_msiof_transfer_one(struct spi_master *master, 781static int sh_msiof_transfer_one(struct spi_master *master,
613 struct spi_device *spi, 782 struct spi_device *spi,
614 struct spi_transfer *t) 783 struct spi_transfer *t)
615{ 784{
616 struct sh_msiof_spi_priv *p = spi_master_get_devdata(master); 785 struct sh_msiof_spi_priv *p = spi_master_get_devdata(master);
786 void (*copy32)(u32 *, const u32 *, unsigned int);
617 void (*tx_fifo)(struct sh_msiof_spi_priv *, const void *, int, int); 787 void (*tx_fifo)(struct sh_msiof_spi_priv *, const void *, int, int);
618 void (*rx_fifo)(struct sh_msiof_spi_priv *, void *, int, int); 788 void (*rx_fifo)(struct sh_msiof_spi_priv *, void *, int, int);
619 const void *tx_buf = t->tx_buf; 789 const void *tx_buf = t->tx_buf;
@@ -624,7 +794,48 @@ static int sh_msiof_transfer_one(struct spi_master *master,
624 unsigned int words; 794 unsigned int words;
625 int n; 795 int n;
626 bool swab; 796 bool swab;
797 int ret;
798
799 /* setup clocks (clock already enabled in chipselect()) */
800 sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk), t->speed_hz);
801
802 while (master->dma_tx && len > 15) {
803 /*
804 * DMA supports 32-bit words only, hence pack 8-bit and 16-bit
805 * words, with byte resp. word swapping.
806 */
807 unsigned int l = min(len, MAX_WDLEN * 4);
808
809 if (bits <= 8) {
810 if (l & 3)
811 break;
812 copy32 = copy_bswap32;
813 } else if (bits <= 16) {
814 if (l & 1)
815 break;
816 copy32 = copy_wswap32;
817 } else {
818 copy32 = copy_plain32;
819 }
820
821 if (tx_buf)
822 copy32(p->tx_dma_page, tx_buf, l / 4);
627 823
824 ret = sh_msiof_dma_once(p, tx_buf, rx_buf, l);
825 if (ret)
826 return ret;
827
828 if (rx_buf) {
829 copy32(rx_buf, p->rx_dma_page, l / 4);
830 rx_buf += l;
831 }
832 if (tx_buf)
833 tx_buf += l;
834
835 len -= l;
836 if (!len)
837 return 0;
838 }
628 839
629 if (bits <= 8 && len > 15 && !(len & 3)) { 840 if (bits <= 8 && len > 15 && !(len & 3)) {
630 bits = 32; 841 bits = 32;
@@ -673,9 +884,6 @@ static int sh_msiof_transfer_one(struct spi_master *master,
673 rx_fifo = sh_msiof_spi_read_fifo_32; 884 rx_fifo = sh_msiof_spi_read_fifo_32;
674 } 885 }
675 886
676 /* setup clocks (clock already enabled in chipselect()) */
677 sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk), t->speed_hz);
678
679 /* transfer in fifo sized chunks */ 887 /* transfer in fifo sized chunks */
680 words = len / bytes_per_word; 888 words = len / bytes_per_word;
681 889
@@ -745,6 +953,123 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev)
745} 953}
746#endif 954#endif
747 955
956static struct dma_chan *sh_msiof_request_dma_chan(struct device *dev,
957 enum dma_transfer_direction dir, unsigned int id, dma_addr_t port_addr)
958{
959 dma_cap_mask_t mask;
960 struct dma_chan *chan;
961 struct dma_slave_config cfg;
962 int ret;
963
964 dma_cap_zero(mask);
965 dma_cap_set(DMA_SLAVE, mask);
966
967 chan = dma_request_channel(mask, shdma_chan_filter,
968 (void *)(unsigned long)id);
969 if (!chan) {
970 dev_warn(dev, "dma_request_channel failed\n");
971 return NULL;
972 }
973
974 memset(&cfg, 0, sizeof(cfg));
975 cfg.slave_id = id;
976 cfg.direction = dir;
977 if (dir == DMA_MEM_TO_DEV)
978 cfg.dst_addr = port_addr;
979 else
980 cfg.src_addr = port_addr;
981
982 ret = dmaengine_slave_config(chan, &cfg);
983 if (ret) {
984 dev_warn(dev, "dmaengine_slave_config failed %d\n", ret);
985 dma_release_channel(chan);
986 return NULL;
987 }
988
989 return chan;
990}
991
992static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p)
993{
994 struct platform_device *pdev = p->pdev;
995 struct device *dev = &pdev->dev;
996 const struct sh_msiof_spi_info *info = dev_get_platdata(dev);
997 const struct resource *res;
998 struct spi_master *master;
999
1000 if (!info || !info->dma_tx_id || !info->dma_rx_id)
1001 return 0; /* The driver assumes no error */
1002
1003 /* The DMA engine uses the second register set, if present */
1004 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1005 if (!res)
1006 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1007
1008 master = p->master;
1009 master->dma_tx = sh_msiof_request_dma_chan(dev, DMA_MEM_TO_DEV,
1010 info->dma_tx_id,
1011 res->start + TFDR);
1012 if (!master->dma_tx)
1013 return -ENODEV;
1014
1015 master->dma_rx = sh_msiof_request_dma_chan(dev, DMA_DEV_TO_MEM,
1016 info->dma_rx_id,
1017 res->start + RFDR);
1018 if (!master->dma_rx)
1019 goto free_tx_chan;
1020
1021 p->tx_dma_page = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
1022 if (!p->tx_dma_page)
1023 goto free_rx_chan;
1024
1025 p->rx_dma_page = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
1026 if (!p->rx_dma_page)
1027 goto free_tx_page;
1028
1029 p->tx_dma_addr = dma_map_single(dev, p->tx_dma_page, PAGE_SIZE,
1030 DMA_TO_DEVICE);
1031 if (dma_mapping_error(dev, p->tx_dma_addr))
1032 goto free_rx_page;
1033
1034 p->rx_dma_addr = dma_map_single(dev, p->rx_dma_page, PAGE_SIZE,
1035 DMA_FROM_DEVICE);
1036 if (dma_mapping_error(dev, p->rx_dma_addr))
1037 goto unmap_tx_page;
1038
1039 dev_info(dev, "DMA available");
1040 return 0;
1041
1042unmap_tx_page:
1043 dma_unmap_single(dev, p->tx_dma_addr, PAGE_SIZE, DMA_TO_DEVICE);
1044free_rx_page:
1045 free_page((unsigned long)p->rx_dma_page);
1046free_tx_page:
1047 free_page((unsigned long)p->tx_dma_page);
1048free_rx_chan:
1049 dma_release_channel(master->dma_rx);
1050free_tx_chan:
1051 dma_release_channel(master->dma_tx);
1052 master->dma_tx = NULL;
1053 return -ENODEV;
1054}
1055
1056static void sh_msiof_release_dma(struct sh_msiof_spi_priv *p)
1057{
1058 struct spi_master *master = p->master;
1059 struct device *dev;
1060
1061 if (!master->dma_tx)
1062 return;
1063
1064 dev = &p->pdev->dev;
1065 dma_unmap_single(dev, p->rx_dma_addr, PAGE_SIZE, DMA_FROM_DEVICE);
1066 dma_unmap_single(dev, p->tx_dma_addr, PAGE_SIZE, DMA_TO_DEVICE);
1067 free_page((unsigned long)p->rx_dma_page);
1068 free_page((unsigned long)p->tx_dma_page);
1069 dma_release_channel(master->dma_rx);
1070 dma_release_channel(master->dma_tx);
1071}
1072
748static int sh_msiof_spi_probe(struct platform_device *pdev) 1073static int sh_msiof_spi_probe(struct platform_device *pdev)
749{ 1074{
750 struct resource *r; 1075 struct resource *r;
@@ -763,6 +1088,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
763 p = spi_master_get_devdata(master); 1088 p = spi_master_get_devdata(master);
764 1089
765 platform_set_drvdata(pdev, p); 1090 platform_set_drvdata(pdev, p);
1091 p->master = master;
766 1092
767 of_id = of_match_device(sh_msiof_match, &pdev->dev); 1093 of_id = of_match_device(sh_msiof_match, &pdev->dev);
768 if (of_id) { 1094 if (of_id) {
@@ -833,6 +1159,10 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
833 master->auto_runtime_pm = true; 1159 master->auto_runtime_pm = true;
834 master->transfer_one = sh_msiof_transfer_one; 1160 master->transfer_one = sh_msiof_transfer_one;
835 1161
1162 ret = sh_msiof_request_dma(p);
1163 if (ret < 0)
1164 dev_warn(&pdev->dev, "DMA not available, using PIO\n");
1165
836 ret = devm_spi_register_master(&pdev->dev, master); 1166 ret = devm_spi_register_master(&pdev->dev, master);
837 if (ret < 0) { 1167 if (ret < 0) {
838 dev_err(&pdev->dev, "spi_register_master error.\n"); 1168 dev_err(&pdev->dev, "spi_register_master error.\n");
@@ -842,6 +1172,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
842 return 0; 1172 return 0;
843 1173
844 err2: 1174 err2:
1175 sh_msiof_release_dma(p);
845 pm_runtime_disable(&pdev->dev); 1176 pm_runtime_disable(&pdev->dev);
846 err1: 1177 err1:
847 spi_master_put(master); 1178 spi_master_put(master);
@@ -850,6 +1181,9 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
850 1181
851static int sh_msiof_spi_remove(struct platform_device *pdev) 1182static int sh_msiof_spi_remove(struct platform_device *pdev)
852{ 1183{
1184 struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev);
1185
1186 sh_msiof_release_dma(p);
853 pm_runtime_disable(&pdev->dev); 1187 pm_runtime_disable(&pdev->dev);
854 return 0; 1188 return 0;
855} 1189}
diff --git a/include/linux/spi/sh_msiof.h b/include/linux/spi/sh_msiof.h
index 2e8db3d2d2e5..88a14d81c49e 100644
--- a/include/linux/spi/sh_msiof.h
+++ b/include/linux/spi/sh_msiof.h
@@ -5,6 +5,8 @@ struct sh_msiof_spi_info {
5 int tx_fifo_override; 5 int tx_fifo_override;
6 int rx_fifo_override; 6 int rx_fifo_override;
7 u16 num_chipselect; 7 u16 num_chipselect;
8 unsigned int dma_tx_id;
9 unsigned int dma_rx_id;
8}; 10};
9 11
10#endif /* __SPI_SH_MSIOF_H__ */ 12#endif /* __SPI_SH_MSIOF_H__ */