diff options
author | Weike Chen <alvin.chen@intel.com> | 2014-11-26 05:35:10 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2014-11-26 13:07:45 -0500 |
commit | e5262d0568dc9e10de79a726dfd7edb712a2c10b (patch) | |
tree | fb8cd4ca58e8f0ef1b1a016ac88139401ed55cfe /drivers/spi | |
parent | 4fdb2424cc4499237197a8c9d35b34d68c750475 (diff) |
spi: spi-pxa2xx: SPI support for Intel Quark X1000
There are two SPI controllers exported by PCI subsystem for Intel Quark X1000.
The SPI memory mapped I/O registers supported by Quark are different from
the current implementation, and Quark only supports the registers of 'SSCR0',
'SSCR1', 'SSSR', 'SSDR', and 'DDS_RATE'. This patch is to enable the SPI for
Intel Quark X1000.
This piece of work is derived from Dan O'Donovan's initial work for Intel Quark
X1000 SPI enabling.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Weike Chen <alvin.chen@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-pxa2xx-pci.c | 8 | ||||
-rw-r--r-- | drivers/spi/spi-pxa2xx.c | 197 | ||||
-rw-r--r-- | drivers/spi/spi-pxa2xx.h | 16 |
3 files changed, 199 insertions, 22 deletions
diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index 6beee8ce2d68..fa7399e84bbb 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c | |||
@@ -19,6 +19,7 @@ enum { | |||
19 | PORT_BSW0, | 19 | PORT_BSW0, |
20 | PORT_BSW1, | 20 | PORT_BSW1, |
21 | PORT_BSW2, | 21 | PORT_BSW2, |
22 | PORT_QUARK_X1000, | ||
22 | }; | 23 | }; |
23 | 24 | ||
24 | struct pxa_spi_info { | 25 | struct pxa_spi_info { |
@@ -92,6 +93,12 @@ static struct pxa_spi_info spi_info_configs[] = { | |||
92 | .tx_param = &bsw2_tx_param, | 93 | .tx_param = &bsw2_tx_param, |
93 | .rx_param = &bsw2_rx_param, | 94 | .rx_param = &bsw2_rx_param, |
94 | }, | 95 | }, |
96 | [PORT_QUARK_X1000] = { | ||
97 | .type = QUARK_X1000_SSP, | ||
98 | .port_id = -1, | ||
99 | .num_chipselect = 1, | ||
100 | .max_clk_rate = 50000000, | ||
101 | }, | ||
95 | }; | 102 | }; |
96 | 103 | ||
97 | static int pxa2xx_spi_pci_probe(struct pci_dev *dev, | 104 | static int pxa2xx_spi_pci_probe(struct pci_dev *dev, |
@@ -191,6 +198,7 @@ static void pxa2xx_spi_pci_remove(struct pci_dev *dev) | |||
191 | 198 | ||
192 | static const struct pci_device_id pxa2xx_spi_pci_devices[] = { | 199 | static const struct pci_device_id pxa2xx_spi_pci_devices[] = { |
193 | { PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 }, | 200 | { PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 }, |
201 | { PCI_VDEVICE(INTEL, 0x0935), PORT_QUARK_X1000 }, | ||
194 | { PCI_VDEVICE(INTEL, 0x0f0e), PORT_BYT }, | 202 | { PCI_VDEVICE(INTEL, 0x0f0e), PORT_BYT }, |
195 | { PCI_VDEVICE(INTEL, 0x228e), PORT_BSW0 }, | 203 | { PCI_VDEVICE(INTEL, 0x228e), PORT_BSW0 }, |
196 | { PCI_VDEVICE(INTEL, 0x2290), PORT_BSW1 }, | 204 | { PCI_VDEVICE(INTEL, 0x2290), PORT_BSW1 }, |
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index d4d29c594156..1a1df5092aca 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c | |||
@@ -63,10 +63,64 @@ MODULE_ALIAS("platform:pxa2xx-spi"); | |||
63 | | SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \ | 63 | | SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \ |
64 | | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM) | 64 | | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM) |
65 | 65 | ||
66 | #define QUARK_X1000_SSCR1_CHANGE_MASK (QUARK_X1000_SSCR1_STRF \ | ||
67 | | QUARK_X1000_SSCR1_EFWR \ | ||
68 | | QUARK_X1000_SSCR1_RFT \ | ||
69 | | QUARK_X1000_SSCR1_TFT \ | ||
70 | | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM) | ||
71 | |||
66 | #define LPSS_RX_THRESH_DFLT 64 | 72 | #define LPSS_RX_THRESH_DFLT 64 |
67 | #define LPSS_TX_LOTHRESH_DFLT 160 | 73 | #define LPSS_TX_LOTHRESH_DFLT 160 |
68 | #define LPSS_TX_HITHRESH_DFLT 224 | 74 | #define LPSS_TX_HITHRESH_DFLT 224 |
69 | 75 | ||
76 | struct quark_spi_rate { | ||
77 | u32 bitrate; | ||
78 | u32 dds_clk_rate; | ||
79 | u32 clk_div; | ||
80 | }; | ||
81 | |||
82 | /* | ||
83 | * 'rate', 'dds', 'clk_div' lookup table, which is defined in | ||
84 | * the Quark SPI datasheet. | ||
85 | */ | ||
86 | static const struct quark_spi_rate quark_spi_rate_table[] = { | ||
87 | /* bitrate, dds_clk_rate, clk_div */ | ||
88 | {50000000, 0x800000, 0}, | ||
89 | {40000000, 0x666666, 0}, | ||
90 | {25000000, 0x400000, 0}, | ||
91 | {20000000, 0x666666, 1}, | ||
92 | {16667000, 0x800000, 2}, | ||
93 | {13333000, 0x666666, 2}, | ||
94 | {12500000, 0x200000, 0}, | ||
95 | {10000000, 0x800000, 4}, | ||
96 | {8000000, 0x666666, 4}, | ||
97 | {6250000, 0x400000, 3}, | ||
98 | {5000000, 0x400000, 4}, | ||
99 | {4000000, 0x666666, 9}, | ||
100 | {3125000, 0x80000, 0}, | ||
101 | {2500000, 0x400000, 9}, | ||
102 | {2000000, 0x666666, 19}, | ||
103 | {1563000, 0x40000, 0}, | ||
104 | {1250000, 0x200000, 9}, | ||
105 | {1000000, 0x400000, 24}, | ||
106 | {800000, 0x666666, 49}, | ||
107 | {781250, 0x20000, 0}, | ||
108 | {625000, 0x200000, 19}, | ||
109 | {500000, 0x400000, 49}, | ||
110 | {400000, 0x666666, 99}, | ||
111 | {390625, 0x10000, 0}, | ||
112 | {250000, 0x400000, 99}, | ||
113 | {200000, 0x666666, 199}, | ||
114 | {195313, 0x8000, 0}, | ||
115 | {125000, 0x100000, 49}, | ||
116 | {100000, 0x200000, 124}, | ||
117 | {50000, 0x100000, 124}, | ||
118 | {25000, 0x80000, 124}, | ||
119 | {10016, 0x20000, 77}, | ||
120 | {5040, 0x20000, 154}, | ||
121 | {1002, 0x8000, 194}, | ||
122 | }; | ||
123 | |||
70 | /* Offset from drv_data->lpss_base */ | 124 | /* Offset from drv_data->lpss_base */ |
71 | #define GENERAL_REG 0x08 | 125 | #define GENERAL_REG 0x08 |
72 | #define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24) | 126 | #define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24) |
@@ -80,9 +134,16 @@ static bool is_lpss_ssp(const struct driver_data *drv_data) | |||
80 | return drv_data->ssp_type == LPSS_SSP; | 134 | return drv_data->ssp_type == LPSS_SSP; |
81 | } | 135 | } |
82 | 136 | ||
137 | static bool is_quark_x1000_ssp(const struct driver_data *drv_data) | ||
138 | { | ||
139 | return drv_data->ssp_type == QUARK_X1000_SSP; | ||
140 | } | ||
141 | |||
83 | static u32 pxa2xx_spi_get_ssrc1_change_mask(const struct driver_data *drv_data) | 142 | static u32 pxa2xx_spi_get_ssrc1_change_mask(const struct driver_data *drv_data) |
84 | { | 143 | { |
85 | switch (drv_data->ssp_type) { | 144 | switch (drv_data->ssp_type) { |
145 | case QUARK_X1000_SSP: | ||
146 | return QUARK_X1000_SSCR1_CHANGE_MASK; | ||
86 | default: | 147 | default: |
87 | return SSCR1_CHANGE_MASK; | 148 | return SSCR1_CHANGE_MASK; |
88 | } | 149 | } |
@@ -92,6 +153,8 @@ static u32 | |||
92 | pxa2xx_spi_get_rx_default_thre(const struct driver_data *drv_data) | 153 | pxa2xx_spi_get_rx_default_thre(const struct driver_data *drv_data) |
93 | { | 154 | { |
94 | switch (drv_data->ssp_type) { | 155 | switch (drv_data->ssp_type) { |
156 | case QUARK_X1000_SSP: | ||
157 | return RX_THRESH_QUARK_X1000_DFLT; | ||
95 | default: | 158 | default: |
96 | return RX_THRESH_DFLT; | 159 | return RX_THRESH_DFLT; |
97 | } | 160 | } |
@@ -103,6 +166,9 @@ static bool pxa2xx_spi_txfifo_full(const struct driver_data *drv_data) | |||
103 | u32 mask; | 166 | u32 mask; |
104 | 167 | ||
105 | switch (drv_data->ssp_type) { | 168 | switch (drv_data->ssp_type) { |
169 | case QUARK_X1000_SSP: | ||
170 | mask = QUARK_X1000_SSSR_TFL_MASK; | ||
171 | break; | ||
106 | default: | 172 | default: |
107 | mask = SSSR_TFL_MASK; | 173 | mask = SSSR_TFL_MASK; |
108 | break; | 174 | break; |
@@ -117,6 +183,9 @@ static void pxa2xx_spi_clear_rx_thre(const struct driver_data *drv_data, | |||
117 | u32 mask; | 183 | u32 mask; |
118 | 184 | ||
119 | switch (drv_data->ssp_type) { | 185 | switch (drv_data->ssp_type) { |
186 | case QUARK_X1000_SSP: | ||
187 | mask = QUARK_X1000_SSCR1_RFT; | ||
188 | break; | ||
120 | default: | 189 | default: |
121 | mask = SSCR1_RFT; | 190 | mask = SSCR1_RFT; |
122 | break; | 191 | break; |
@@ -128,6 +197,9 @@ static void pxa2xx_spi_set_rx_thre(const struct driver_data *drv_data, | |||
128 | u32 *sccr1_reg, u32 threshold) | 197 | u32 *sccr1_reg, u32 threshold) |
129 | { | 198 | { |
130 | switch (drv_data->ssp_type) { | 199 | switch (drv_data->ssp_type) { |
200 | case QUARK_X1000_SSP: | ||
201 | *sccr1_reg |= QUARK_X1000_SSCR1_RxTresh(threshold); | ||
202 | break; | ||
131 | default: | 203 | default: |
132 | *sccr1_reg |= SSCR1_RxTresh(threshold); | 204 | *sccr1_reg |= SSCR1_RxTresh(threshold); |
133 | break; | 205 | break; |
@@ -138,6 +210,11 @@ static u32 pxa2xx_configure_sscr0(const struct driver_data *drv_data, | |||
138 | u32 clk_div, u8 bits) | 210 | u32 clk_div, u8 bits) |
139 | { | 211 | { |
140 | switch (drv_data->ssp_type) { | 212 | switch (drv_data->ssp_type) { |
213 | case QUARK_X1000_SSP: | ||
214 | return clk_div | ||
215 | | QUARK_X1000_SSCR0_Motorola | ||
216 | | QUARK_X1000_SSCR0_DataSize(bits > 32 ? 8 : bits) | ||
217 | | SSCR0_SSE; | ||
141 | default: | 218 | default: |
142 | return clk_div | 219 | return clk_div |
143 | | SSCR0_Motorola | 220 | | SSCR0_Motorola |
@@ -654,6 +731,28 @@ static irqreturn_t ssp_int(int irq, void *dev_id) | |||
654 | return drv_data->transfer_handler(drv_data); | 731 | return drv_data->transfer_handler(drv_data); |
655 | } | 732 | } |
656 | 733 | ||
734 | /* | ||
735 | * The Quark SPI data sheet gives a table, and for the given 'rate', | ||
736 | * the 'dds' and 'clk_div' can be found in the table. | ||
737 | */ | ||
738 | static u32 quark_x1000_set_clk_regvals(u32 rate, u32 *dds, u32 *clk_div) | ||
739 | { | ||
740 | unsigned int i; | ||
741 | |||
742 | for (i = 0; i < ARRAY_SIZE(quark_spi_rate_table); i++) { | ||
743 | if (rate >= quark_spi_rate_table[i].bitrate) { | ||
744 | *dds = quark_spi_rate_table[i].dds_clk_rate; | ||
745 | *clk_div = quark_spi_rate_table[i].clk_div; | ||
746 | return quark_spi_rate_table[i].bitrate; | ||
747 | } | ||
748 | } | ||
749 | |||
750 | *dds = quark_spi_rate_table[i-1].dds_clk_rate; | ||
751 | *clk_div = quark_spi_rate_table[i-1].clk_div; | ||
752 | |||
753 | return quark_spi_rate_table[i-1].bitrate; | ||
754 | } | ||
755 | |||
657 | static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate) | 756 | static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate) |
658 | { | 757 | { |
659 | unsigned long ssp_clk = drv_data->max_clk_rate; | 758 | unsigned long ssp_clk = drv_data->max_clk_rate; |
@@ -667,6 +766,20 @@ static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate) | |||
667 | return ((ssp_clk / rate - 1) & 0xfff) << 8; | 766 | return ((ssp_clk / rate - 1) & 0xfff) << 8; |
668 | } | 767 | } |
669 | 768 | ||
769 | static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data, | ||
770 | struct chip_data *chip, int rate) | ||
771 | { | ||
772 | u32 clk_div; | ||
773 | |||
774 | switch (drv_data->ssp_type) { | ||
775 | case QUARK_X1000_SSP: | ||
776 | quark_x1000_set_clk_regvals(rate, &chip->dds_rate, &clk_div); | ||
777 | return clk_div << 8; | ||
778 | default: | ||
779 | return ssp_get_clk_div(drv_data, rate); | ||
780 | } | ||
781 | } | ||
782 | |||
670 | static void pump_transfers(unsigned long data) | 783 | static void pump_transfers(unsigned long data) |
671 | { | 784 | { |
672 | struct driver_data *drv_data = (struct driver_data *)data; | 785 | struct driver_data *drv_data = (struct driver_data *)data; |
@@ -769,7 +882,7 @@ static void pump_transfers(unsigned long data) | |||
769 | if (transfer->bits_per_word) | 882 | if (transfer->bits_per_word) |
770 | bits = transfer->bits_per_word; | 883 | bits = transfer->bits_per_word; |
771 | 884 | ||
772 | clk_div = ssp_get_clk_div(drv_data, speed); | 885 | clk_div = pxa2xx_ssp_get_clk_div(drv_data, chip, speed); |
773 | 886 | ||
774 | if (bits <= 8) { | 887 | if (bits <= 8) { |
775 | drv_data->n_bytes = 1; | 888 | drv_data->n_bytes = 1; |
@@ -837,6 +950,10 @@ static void pump_transfers(unsigned long data) | |||
837 | write_SSITF(chip->lpss_tx_threshold, reg); | 950 | write_SSITF(chip->lpss_tx_threshold, reg); |
838 | } | 951 | } |
839 | 952 | ||
953 | if (is_quark_x1000_ssp(drv_data) && | ||
954 | (read_DDS_RATE(reg) != chip->dds_rate)) | ||
955 | write_DDS_RATE(chip->dds_rate, reg); | ||
956 | |||
840 | /* see if we need to reload the config registers */ | 957 | /* see if we need to reload the config registers */ |
841 | if ((read_SSCR0(reg) != cr0) || | 958 | if ((read_SSCR0(reg) != cr0) || |
842 | (read_SSCR1(reg) & change_mask) != (cr1 & change_mask)) { | 959 | (read_SSCR1(reg) & change_mask) != (cr1 & change_mask)) { |
@@ -940,14 +1057,22 @@ static int setup(struct spi_device *spi) | |||
940 | unsigned int clk_div; | 1057 | unsigned int clk_div; |
941 | uint tx_thres, tx_hi_thres, rx_thres; | 1058 | uint tx_thres, tx_hi_thres, rx_thres; |
942 | 1059 | ||
943 | if (is_lpss_ssp(drv_data)) { | 1060 | switch (drv_data->ssp_type) { |
1061 | case QUARK_X1000_SSP: | ||
1062 | tx_thres = TX_THRESH_QUARK_X1000_DFLT; | ||
1063 | tx_hi_thres = 0; | ||
1064 | rx_thres = RX_THRESH_QUARK_X1000_DFLT; | ||
1065 | break; | ||
1066 | case LPSS_SSP: | ||
944 | tx_thres = LPSS_TX_LOTHRESH_DFLT; | 1067 | tx_thres = LPSS_TX_LOTHRESH_DFLT; |
945 | tx_hi_thres = LPSS_TX_HITHRESH_DFLT; | 1068 | tx_hi_thres = LPSS_TX_HITHRESH_DFLT; |
946 | rx_thres = LPSS_RX_THRESH_DFLT; | 1069 | rx_thres = LPSS_RX_THRESH_DFLT; |
947 | } else { | 1070 | break; |
1071 | default: | ||
948 | tx_thres = TX_THRESH_DFLT; | 1072 | tx_thres = TX_THRESH_DFLT; |
949 | tx_hi_thres = 0; | 1073 | tx_hi_thres = 0; |
950 | rx_thres = RX_THRESH_DFLT; | 1074 | rx_thres = RX_THRESH_DFLT; |
1075 | break; | ||
951 | } | 1076 | } |
952 | 1077 | ||
953 | /* Only alloc on first setup */ | 1078 | /* Only alloc on first setup */ |
@@ -1000,9 +1125,6 @@ static int setup(struct spi_device *spi) | |||
1000 | chip->enable_dma = drv_data->master_info->enable_dma; | 1125 | chip->enable_dma = drv_data->master_info->enable_dma; |
1001 | } | 1126 | } |
1002 | 1127 | ||
1003 | chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) | | ||
1004 | (SSCR1_TxTresh(tx_thres) & SSCR1_TFT); | ||
1005 | |||
1006 | chip->lpss_rx_threshold = SSIRF_RxThresh(rx_thres); | 1128 | chip->lpss_rx_threshold = SSIRF_RxThresh(rx_thres); |
1007 | chip->lpss_tx_threshold = SSITF_TxLoThresh(tx_thres) | 1129 | chip->lpss_tx_threshold = SSITF_TxLoThresh(tx_thres) |
1008 | | SSITF_TxHiThresh(tx_hi_thres); | 1130 | | SSITF_TxHiThresh(tx_hi_thres); |
@@ -1021,11 +1143,24 @@ static int setup(struct spi_device *spi) | |||
1021 | } | 1143 | } |
1022 | } | 1144 | } |
1023 | 1145 | ||
1024 | clk_div = ssp_get_clk_div(drv_data, spi->max_speed_hz); | 1146 | clk_div = pxa2xx_ssp_get_clk_div(drv_data, chip, spi->max_speed_hz); |
1025 | chip->speed_hz = spi->max_speed_hz; | 1147 | chip->speed_hz = spi->max_speed_hz; |
1026 | 1148 | ||
1027 | chip->cr0 = pxa2xx_configure_sscr0(drv_data, clk_div, | 1149 | chip->cr0 = pxa2xx_configure_sscr0(drv_data, clk_div, |
1028 | spi->bits_per_word); | 1150 | spi->bits_per_word); |
1151 | switch (drv_data->ssp_type) { | ||
1152 | case QUARK_X1000_SSP: | ||
1153 | chip->threshold = (QUARK_X1000_SSCR1_RxTresh(rx_thres) | ||
1154 | & QUARK_X1000_SSCR1_RFT) | ||
1155 | | (QUARK_X1000_SSCR1_TxTresh(tx_thres) | ||
1156 | & QUARK_X1000_SSCR1_TFT); | ||
1157 | break; | ||
1158 | default: | ||
1159 | chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) | | ||
1160 | (SSCR1_TxTresh(tx_thres) & SSCR1_TFT); | ||
1161 | break; | ||
1162 | } | ||
1163 | |||
1029 | chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH); | 1164 | chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH); |
1030 | chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0) | 1165 | chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0) |
1031 | | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0); | 1166 | | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0); |
@@ -1054,7 +1189,8 @@ static int setup(struct spi_device *spi) | |||
1054 | chip->read = u16_reader; | 1189 | chip->read = u16_reader; |
1055 | chip->write = u16_writer; | 1190 | chip->write = u16_writer; |
1056 | } else if (spi->bits_per_word <= 32) { | 1191 | } else if (spi->bits_per_word <= 32) { |
1057 | chip->cr0 |= SSCR0_EDSS; | 1192 | if (!is_quark_x1000_ssp(drv_data)) |
1193 | chip->cr0 |= SSCR0_EDSS; | ||
1058 | chip->n_bytes = 4; | 1194 | chip->n_bytes = 4; |
1059 | chip->read = u32_reader; | 1195 | chip->read = u32_reader; |
1060 | chip->write = u32_writer; | 1196 | chip->write = u32_writer; |
@@ -1205,7 +1341,15 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) | |||
1205 | drv_data->ioaddr = ssp->mmio_base; | 1341 | drv_data->ioaddr = ssp->mmio_base; |
1206 | drv_data->ssdr_physical = ssp->phys_base + SSDR; | 1342 | drv_data->ssdr_physical = ssp->phys_base + SSDR; |
1207 | if (pxa25x_ssp_comp(drv_data)) { | 1343 | if (pxa25x_ssp_comp(drv_data)) { |
1208 | master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); | 1344 | switch (drv_data->ssp_type) { |
1345 | case QUARK_X1000_SSP: | ||
1346 | master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); | ||
1347 | break; | ||
1348 | default: | ||
1349 | master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); | ||
1350 | break; | ||
1351 | } | ||
1352 | |||
1209 | drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE; | 1353 | drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE; |
1210 | drv_data->dma_cr1 = 0; | 1354 | drv_data->dma_cr1 = 0; |
1211 | drv_data->clear_sr = SSSR_ROR; | 1355 | drv_data->clear_sr = SSSR_ROR; |
@@ -1243,16 +1387,35 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) | |||
1243 | 1387 | ||
1244 | /* Load default SSP configuration */ | 1388 | /* Load default SSP configuration */ |
1245 | write_SSCR0(0, drv_data->ioaddr); | 1389 | write_SSCR0(0, drv_data->ioaddr); |
1246 | write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) | | 1390 | switch (drv_data->ssp_type) { |
1247 | SSCR1_TxTresh(TX_THRESH_DFLT), | 1391 | case QUARK_X1000_SSP: |
1248 | drv_data->ioaddr); | 1392 | write_SSCR1(QUARK_X1000_SSCR1_RxTresh( |
1249 | write_SSCR0(SSCR0_SCR(2) | 1393 | RX_THRESH_QUARK_X1000_DFLT) | |
1250 | | SSCR0_Motorola | 1394 | QUARK_X1000_SSCR1_TxTresh( |
1251 | | SSCR0_DataSize(8), | 1395 | TX_THRESH_QUARK_X1000_DFLT), |
1252 | drv_data->ioaddr); | 1396 | drv_data->ioaddr); |
1397 | |||
1398 | /* using the Motorola SPI protocol and use 8 bit frame */ | ||
1399 | write_SSCR0(QUARK_X1000_SSCR0_Motorola | ||
1400 | | QUARK_X1000_SSCR0_DataSize(8), | ||
1401 | drv_data->ioaddr); | ||
1402 | break; | ||
1403 | default: | ||
1404 | write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) | | ||
1405 | SSCR1_TxTresh(TX_THRESH_DFLT), | ||
1406 | drv_data->ioaddr); | ||
1407 | write_SSCR0(SSCR0_SCR(2) | ||
1408 | | SSCR0_Motorola | ||
1409 | | SSCR0_DataSize(8), | ||
1410 | drv_data->ioaddr); | ||
1411 | break; | ||
1412 | } | ||
1413 | |||
1253 | if (!pxa25x_ssp_comp(drv_data)) | 1414 | if (!pxa25x_ssp_comp(drv_data)) |
1254 | write_SSTO(0, drv_data->ioaddr); | 1415 | write_SSTO(0, drv_data->ioaddr); |
1255 | write_SSPSP(0, drv_data->ioaddr); | 1416 | |
1417 | if (!is_quark_x1000_ssp(drv_data)) | ||
1418 | write_SSPSP(0, drv_data->ioaddr); | ||
1256 | 1419 | ||
1257 | lpss_ssp_setup(drv_data); | 1420 | lpss_ssp_setup(drv_data); |
1258 | 1421 | ||
diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h index 5adc2a11c7bc..6bec59c90cd4 100644 --- a/drivers/spi/spi-pxa2xx.h +++ b/drivers/spi/spi-pxa2xx.h | |||
@@ -93,6 +93,7 @@ struct driver_data { | |||
93 | struct chip_data { | 93 | struct chip_data { |
94 | u32 cr0; | 94 | u32 cr0; |
95 | u32 cr1; | 95 | u32 cr1; |
96 | u32 dds_rate; | ||
96 | u32 psp; | 97 | u32 psp; |
97 | u32 timeout; | 98 | u32 timeout; |
98 | u8 n_bytes; | 99 | u8 n_bytes; |
@@ -126,6 +127,7 @@ DEFINE_SSP_REG(SSCR1, 0x04) | |||
126 | DEFINE_SSP_REG(SSSR, 0x08) | 127 | DEFINE_SSP_REG(SSSR, 0x08) |
127 | DEFINE_SSP_REG(SSITR, 0x0c) | 128 | DEFINE_SSP_REG(SSITR, 0x0c) |
128 | DEFINE_SSP_REG(SSDR, 0x10) | 129 | DEFINE_SSP_REG(SSDR, 0x10) |
130 | DEFINE_SSP_REG(DDS_RATE, 0x28) /* DDS Clock Rate */ | ||
129 | DEFINE_SSP_REG(SSTO, 0x28) | 131 | DEFINE_SSP_REG(SSTO, 0x28) |
130 | DEFINE_SSP_REG(SSPSP, 0x2c) | 132 | DEFINE_SSP_REG(SSPSP, 0x2c) |
131 | DEFINE_SSP_REG(SSITF, SSITF) | 133 | DEFINE_SSP_REG(SSITF, SSITF) |
@@ -141,18 +143,22 @@ DEFINE_SSP_REG(SSIRF, SSIRF) | |||
141 | 143 | ||
142 | static inline int pxa25x_ssp_comp(struct driver_data *drv_data) | 144 | static inline int pxa25x_ssp_comp(struct driver_data *drv_data) |
143 | { | 145 | { |
144 | if (drv_data->ssp_type == PXA25x_SSP) | 146 | switch (drv_data->ssp_type) { |
147 | case PXA25x_SSP: | ||
148 | case CE4100_SSP: | ||
149 | case QUARK_X1000_SSP: | ||
145 | return 1; | 150 | return 1; |
146 | if (drv_data->ssp_type == CE4100_SSP) | 151 | default: |
147 | return 1; | 152 | return 0; |
148 | return 0; | 153 | } |
149 | } | 154 | } |
150 | 155 | ||
151 | static inline void write_SSSR_CS(struct driver_data *drv_data, u32 val) | 156 | static inline void write_SSSR_CS(struct driver_data *drv_data, u32 val) |
152 | { | 157 | { |
153 | void __iomem *reg = drv_data->ioaddr; | 158 | void __iomem *reg = drv_data->ioaddr; |
154 | 159 | ||
155 | if (drv_data->ssp_type == CE4100_SSP) | 160 | if (drv_data->ssp_type == CE4100_SSP || |
161 | drv_data->ssp_type == QUARK_X1000_SSP) | ||
156 | val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK; | 162 | val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK; |
157 | 163 | ||
158 | write_SSSR(val, reg); | 164 | write_SSSR(val, reg); |