diff options
author | Linus Walleij <linus.walleij@stericsson.com> | 2010-05-07 04:40:53 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2010-05-25 02:23:14 -0400 |
commit | 781c7b129b1beb876905f7212927aa0ee1b022e5 (patch) | |
tree | 678bfc0d0a5cdd24c55024b5c2d2674eb5bea572 | |
parent | 556f4aeb7d9dfac8573d0281dd555bd3210d8366 (diff) |
spi/pl022: add support for the PL023 derivate
This adds support for a further ST variant of the PL022 called
PL023. Some differences in the control registers due to being
stripped down to SPI mode only, and a new clock feedback sample
delay config setting is available.
Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-rw-r--r-- | drivers/spi/amba-pl022.c | 90 | ||||
-rw-r--r-- | include/linux/amba/pl022.h | 32 |
2 files changed, 104 insertions, 18 deletions
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index 65092171cec3..c75831c1deda 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c | |||
@@ -135,6 +135,8 @@ | |||
135 | #define SSP_CR1_MASK_MWAIT_ST (0x1UL << 6) | 135 | #define SSP_CR1_MASK_MWAIT_ST (0x1UL << 6) |
136 | #define SSP_CR1_MASK_RXIFLSEL_ST (0x7UL << 7) | 136 | #define SSP_CR1_MASK_RXIFLSEL_ST (0x7UL << 7) |
137 | #define SSP_CR1_MASK_TXIFLSEL_ST (0x7UL << 10) | 137 | #define SSP_CR1_MASK_TXIFLSEL_ST (0x7UL << 10) |
138 | /* This one is only in the PL023 variant */ | ||
139 | #define SSP_CR1_MASK_FBCLKDEL_ST (0x7UL << 13) | ||
138 | 140 | ||
139 | /* | 141 | /* |
140 | * SSP Status Register - SSP_SR | 142 | * SSP Status Register - SSP_SR |
@@ -317,12 +319,14 @@ enum ssp_writing { | |||
317 | * @unidir: supports unidirection transfers | 319 | * @unidir: supports unidirection transfers |
318 | * @extended_cr: 32 bit wide control register 0 with extra | 320 | * @extended_cr: 32 bit wide control register 0 with extra |
319 | * features and extra features in CR1 as found in the ST variants | 321 | * features and extra features in CR1 as found in the ST variants |
322 | * @pl023: supports a subset of the ST extensions called "PL023" | ||
320 | */ | 323 | */ |
321 | struct vendor_data { | 324 | struct vendor_data { |
322 | int fifodepth; | 325 | int fifodepth; |
323 | int max_bpw; | 326 | int max_bpw; |
324 | bool unidir; | 327 | bool unidir; |
325 | bool extended_cr; | 328 | bool extended_cr; |
329 | bool pl023; | ||
326 | }; | 330 | }; |
327 | 331 | ||
328 | /** | 332 | /** |
@@ -541,11 +545,6 @@ static void restore_state(struct pl022 *pl022) | |||
541 | writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase)); | 545 | writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase)); |
542 | } | 546 | } |
543 | 547 | ||
544 | /** | ||
545 | * load_ssp_default_config - Load default configuration for SSP | ||
546 | * @pl022: SSP driver private data structure | ||
547 | */ | ||
548 | |||
549 | /* | 548 | /* |
550 | * Default SSP Register Values | 549 | * Default SSP Register Values |
551 | */ | 550 | */ |
@@ -568,6 +567,14 @@ static void restore_state(struct pl022 *pl022) | |||
568 | GEN_MASK_BITS(SSP_INTERFACE_MOTOROLA_SPI, SSP_CR0_MASK_FRF_ST, 21) \ | 567 | GEN_MASK_BITS(SSP_INTERFACE_MOTOROLA_SPI, SSP_CR0_MASK_FRF_ST, 21) \ |
569 | ) | 568 | ) |
570 | 569 | ||
570 | /* The PL023 version is slightly different again */ | ||
571 | #define DEFAULT_SSP_REG_CR0_ST_PL023 ( \ | ||
572 | GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS_ST, 0) | \ | ||
573 | GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \ | ||
574 | GEN_MASK_BITS(SSP_CLK_SECOND_EDGE, SSP_CR0_MASK_SPH, 7) | \ | ||
575 | GEN_MASK_BITS(SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) \ | ||
576 | ) | ||
577 | |||
571 | #define DEFAULT_SSP_REG_CR1 ( \ | 578 | #define DEFAULT_SSP_REG_CR1 ( \ |
572 | GEN_MASK_BITS(LOOPBACK_DISABLED, SSP_CR1_MASK_LBM, 0) | \ | 579 | GEN_MASK_BITS(LOOPBACK_DISABLED, SSP_CR1_MASK_LBM, 0) | \ |
573 | GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \ | 580 | GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \ |
@@ -585,6 +592,20 @@ static void restore_state(struct pl022 *pl022) | |||
585 | GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL_ST, 10) \ | 592 | GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL_ST, 10) \ |
586 | ) | 593 | ) |
587 | 594 | ||
595 | /* | ||
596 | * The PL023 variant has further differences: no loopback mode, no microwire | ||
597 | * support, and a new clock feedback delay setting. | ||
598 | */ | ||
599 | #define DEFAULT_SSP_REG_CR1_ST_PL023 ( \ | ||
600 | GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \ | ||
601 | GEN_MASK_BITS(SSP_MASTER, SSP_CR1_MASK_MS, 2) | \ | ||
602 | GEN_MASK_BITS(DO_NOT_DRIVE_TX, SSP_CR1_MASK_SOD, 3) | \ | ||
603 | GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_RENDN_ST, 4) | \ | ||
604 | GEN_MASK_BITS(SSP_TX_MSB, SSP_CR1_MASK_TENDN_ST, 5) | \ | ||
605 | GEN_MASK_BITS(SSP_RX_1_OR_MORE_ELEM, SSP_CR1_MASK_RXIFLSEL_ST, 7) | \ | ||
606 | GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL_ST, 10) | \ | ||
607 | GEN_MASK_BITS(SSP_FEEDBACK_CLK_DELAY_NONE, SSP_CR1_MASK_FBCLKDEL_ST, 13) \ | ||
608 | ) | ||
588 | 609 | ||
589 | #define DEFAULT_SSP_REG_CPSR ( \ | 610 | #define DEFAULT_SSP_REG_CPSR ( \ |
590 | GEN_MASK_BITS(SSP_DEFAULT_PRESCALE, SSP_CPSR_MASK_CPSDVSR, 0) \ | 611 | GEN_MASK_BITS(SSP_DEFAULT_PRESCALE, SSP_CPSR_MASK_CPSDVSR, 0) \ |
@@ -595,10 +616,16 @@ static void restore_state(struct pl022 *pl022) | |||
595 | GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_TXDMAE, 1) \ | 616 | GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_TXDMAE, 1) \ |
596 | ) | 617 | ) |
597 | 618 | ||
598 | 619 | /** | |
620 | * load_ssp_default_config - Load default configuration for SSP | ||
621 | * @pl022: SSP driver private data structure | ||
622 | */ | ||
599 | static void load_ssp_default_config(struct pl022 *pl022) | 623 | static void load_ssp_default_config(struct pl022 *pl022) |
600 | { | 624 | { |
601 | if (pl022->vendor->extended_cr) { | 625 | if (pl022->vendor->pl023) { |
626 | writel(DEFAULT_SSP_REG_CR0_ST_PL023, SSP_CR0(pl022->virtbase)); | ||
627 | writew(DEFAULT_SSP_REG_CR1_ST_PL023, SSP_CR1(pl022->virtbase)); | ||
628 | } else if (pl022->vendor->extended_cr) { | ||
602 | writel(DEFAULT_SSP_REG_CR0_ST, SSP_CR0(pl022->virtbase)); | 629 | writel(DEFAULT_SSP_REG_CR0_ST, SSP_CR0(pl022->virtbase)); |
603 | writew(DEFAULT_SSP_REG_CR1_ST, SSP_CR1(pl022->virtbase)); | 630 | writew(DEFAULT_SSP_REG_CR1_ST, SSP_CR1(pl022->virtbase)); |
604 | } else { | 631 | } else { |
@@ -1629,20 +1656,27 @@ static int pl022_setup(struct spi_device *spi) | |||
1629 | 1656 | ||
1630 | /* Special setup for the ST micro extended control registers */ | 1657 | /* Special setup for the ST micro extended control registers */ |
1631 | if (pl022->vendor->extended_cr) { | 1658 | if (pl022->vendor->extended_cr) { |
1659 | if (pl022->vendor->pl023) { | ||
1660 | /* These bits are only in the PL023 */ | ||
1661 | SSP_WRITE_BITS(chip->cr1, chip_info->clkdelay, | ||
1662 | SSP_CR1_MASK_FBCLKDEL_ST, 13); | ||
1663 | } else { | ||
1664 | /* These bits are in the PL022 but not PL023 */ | ||
1665 | SSP_WRITE_BITS(chip->cr0, chip_info->duplex, | ||
1666 | SSP_CR0_MASK_HALFDUP_ST, 5); | ||
1667 | SSP_WRITE_BITS(chip->cr0, chip_info->ctrl_len, | ||
1668 | SSP_CR0_MASK_CSS_ST, 16); | ||
1669 | SSP_WRITE_BITS(chip->cr0, chip_info->iface, | ||
1670 | SSP_CR0_MASK_FRF_ST, 21); | ||
1671 | SSP_WRITE_BITS(chip->cr1, chip_info->wait_state, | ||
1672 | SSP_CR1_MASK_MWAIT_ST, 6); | ||
1673 | } | ||
1632 | SSP_WRITE_BITS(chip->cr0, chip_info->data_size, | 1674 | SSP_WRITE_BITS(chip->cr0, chip_info->data_size, |
1633 | SSP_CR0_MASK_DSS_ST, 0); | 1675 | SSP_CR0_MASK_DSS_ST, 0); |
1634 | SSP_WRITE_BITS(chip->cr0, chip_info->duplex, | ||
1635 | SSP_CR0_MASK_HALFDUP_ST, 5); | ||
1636 | SSP_WRITE_BITS(chip->cr0, chip_info->ctrl_len, | ||
1637 | SSP_CR0_MASK_CSS_ST, 16); | ||
1638 | SSP_WRITE_BITS(chip->cr0, chip_info->iface, | ||
1639 | SSP_CR0_MASK_FRF_ST, 21); | ||
1640 | SSP_WRITE_BITS(chip->cr1, chip_info->endian_rx, | 1676 | SSP_WRITE_BITS(chip->cr1, chip_info->endian_rx, |
1641 | SSP_CR1_MASK_RENDN_ST, 4); | 1677 | SSP_CR1_MASK_RENDN_ST, 4); |
1642 | SSP_WRITE_BITS(chip->cr1, chip_info->endian_tx, | 1678 | SSP_WRITE_BITS(chip->cr1, chip_info->endian_tx, |
1643 | SSP_CR1_MASK_TENDN_ST, 5); | 1679 | SSP_CR1_MASK_TENDN_ST, 5); |
1644 | SSP_WRITE_BITS(chip->cr1, chip_info->wait_state, | ||
1645 | SSP_CR1_MASK_MWAIT_ST, 6); | ||
1646 | SSP_WRITE_BITS(chip->cr1, chip_info->rx_lev_trig, | 1680 | SSP_WRITE_BITS(chip->cr1, chip_info->rx_lev_trig, |
1647 | SSP_CR1_MASK_RXIFLSEL_ST, 7); | 1681 | SSP_CR1_MASK_RXIFLSEL_ST, 7); |
1648 | SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig, | 1682 | SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig, |
@@ -1657,7 +1691,9 @@ static int pl022_setup(struct spi_device *spi) | |||
1657 | SSP_WRITE_BITS(chip->cr0, chip_info->clk_pol, SSP_CR0_MASK_SPO, 6); | 1691 | SSP_WRITE_BITS(chip->cr0, chip_info->clk_pol, SSP_CR0_MASK_SPO, 6); |
1658 | SSP_WRITE_BITS(chip->cr0, chip_info->clk_phase, SSP_CR0_MASK_SPH, 7); | 1692 | SSP_WRITE_BITS(chip->cr0, chip_info->clk_phase, SSP_CR0_MASK_SPH, 7); |
1659 | SSP_WRITE_BITS(chip->cr0, chip_info->clk_freq.scr, SSP_CR0_MASK_SCR, 8); | 1693 | SSP_WRITE_BITS(chip->cr0, chip_info->clk_freq.scr, SSP_CR0_MASK_SCR, 8); |
1660 | SSP_WRITE_BITS(chip->cr1, chip_info->lbm, SSP_CR1_MASK_LBM, 0); | 1694 | /* Loopback is available on all versions except PL023 */ |
1695 | if (!pl022->vendor->pl023) | ||
1696 | SSP_WRITE_BITS(chip->cr1, chip_info->lbm, SSP_CR1_MASK_LBM, 0); | ||
1661 | SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1); | 1697 | SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1); |
1662 | SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2); | 1698 | SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2); |
1663 | SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3); | 1699 | SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3); |
@@ -1874,6 +1910,7 @@ static struct vendor_data vendor_arm = { | |||
1874 | .max_bpw = 16, | 1910 | .max_bpw = 16, |
1875 | .unidir = false, | 1911 | .unidir = false, |
1876 | .extended_cr = false, | 1912 | .extended_cr = false, |
1913 | .pl023 = false, | ||
1877 | }; | 1914 | }; |
1878 | 1915 | ||
1879 | 1916 | ||
@@ -1882,6 +1919,15 @@ static struct vendor_data vendor_st = { | |||
1882 | .max_bpw = 32, | 1919 | .max_bpw = 32, |
1883 | .unidir = false, | 1920 | .unidir = false, |
1884 | .extended_cr = true, | 1921 | .extended_cr = true, |
1922 | .pl023 = false, | ||
1923 | }; | ||
1924 | |||
1925 | static struct vendor_data vendor_st_pl023 = { | ||
1926 | .fifodepth = 32, | ||
1927 | .max_bpw = 32, | ||
1928 | .unidir = false, | ||
1929 | .extended_cr = true, | ||
1930 | .pl023 = true, | ||
1885 | }; | 1931 | }; |
1886 | 1932 | ||
1887 | static struct amba_id pl022_ids[] = { | 1933 | static struct amba_id pl022_ids[] = { |
@@ -1903,6 +1949,18 @@ static struct amba_id pl022_ids[] = { | |||
1903 | .mask = 0xffffffff, | 1949 | .mask = 0xffffffff, |
1904 | .data = &vendor_st, | 1950 | .data = &vendor_st, |
1905 | }, | 1951 | }, |
1952 | { | ||
1953 | /* | ||
1954 | * ST-Ericsson derivative "PL023" (this is not | ||
1955 | * an official ARM number), this is a PL022 SSP block | ||
1956 | * stripped to SPI mode only, it has 32bit wide | ||
1957 | * and 32 locations deep TX/RX FIFO but no extended | ||
1958 | * CR0/CR1 register | ||
1959 | */ | ||
1960 | .id = 0x00080023, | ||
1961 | .mask = 0xffffffff, | ||
1962 | .data = &vendor_st_pl023, | ||
1963 | }, | ||
1906 | { 0, 0 }, | 1964 | { 0, 0 }, |
1907 | }; | 1965 | }; |
1908 | 1966 | ||
diff --git a/include/linux/amba/pl022.h b/include/linux/amba/pl022.h index 612f39913340..abf26cc47a2b 100644 --- a/include/linux/amba/pl022.h +++ b/include/linux/amba/pl022.h | |||
@@ -182,8 +182,8 @@ enum ssp_microwire_wait_state { | |||
182 | }; | 182 | }; |
183 | 183 | ||
184 | /** | 184 | /** |
185 | * enum Microwire - whether Full/Half Duplex, only available | 185 | * enum ssp_duplex - whether Full/Half Duplex on microwire, only |
186 | * in the ST Micro variant. | 186 | * available in the ST Micro variant. |
187 | * @SSP_MICROWIRE_CHANNEL_FULL_DUPLEX: SSPTXD becomes bi-directional, | 187 | * @SSP_MICROWIRE_CHANNEL_FULL_DUPLEX: SSPTXD becomes bi-directional, |
188 | * SSPRXD not used | 188 | * SSPRXD not used |
189 | * @SSP_MICROWIRE_CHANNEL_HALF_DUPLEX: SSPTXD is an output, SSPRXD is | 189 | * @SSP_MICROWIRE_CHANNEL_HALF_DUPLEX: SSPTXD is an output, SSPRXD is |
@@ -195,6 +195,31 @@ enum ssp_duplex { | |||
195 | }; | 195 | }; |
196 | 196 | ||
197 | /** | 197 | /** |
198 | * enum ssp_clkdelay - an optional clock delay on the feedback clock | ||
199 | * only available in the ST Micro PL023 variant. | ||
200 | * @SSP_FEEDBACK_CLK_DELAY_NONE: no delay, the data coming in from the | ||
201 | * slave is sampled directly | ||
202 | * @SSP_FEEDBACK_CLK_DELAY_1T: the incoming slave data is sampled with | ||
203 | * a delay of T-dt | ||
204 | * @SSP_FEEDBACK_CLK_DELAY_2T: dito with a delay if 2T-dt | ||
205 | * @SSP_FEEDBACK_CLK_DELAY_3T: dito with a delay if 3T-dt | ||
206 | * @SSP_FEEDBACK_CLK_DELAY_4T: dito with a delay if 4T-dt | ||
207 | * @SSP_FEEDBACK_CLK_DELAY_5T: dito with a delay if 5T-dt | ||
208 | * @SSP_FEEDBACK_CLK_DELAY_6T: dito with a delay if 6T-dt | ||
209 | * @SSP_FEEDBACK_CLK_DELAY_7T: dito with a delay if 7T-dt | ||
210 | */ | ||
211 | enum ssp_clkdelay { | ||
212 | SSP_FEEDBACK_CLK_DELAY_NONE, | ||
213 | SSP_FEEDBACK_CLK_DELAY_1T, | ||
214 | SSP_FEEDBACK_CLK_DELAY_2T, | ||
215 | SSP_FEEDBACK_CLK_DELAY_3T, | ||
216 | SSP_FEEDBACK_CLK_DELAY_4T, | ||
217 | SSP_FEEDBACK_CLK_DELAY_5T, | ||
218 | SSP_FEEDBACK_CLK_DELAY_6T, | ||
219 | SSP_FEEDBACK_CLK_DELAY_7T | ||
220 | }; | ||
221 | |||
222 | /** | ||
198 | * CHIP select/deselect commands | 223 | * CHIP select/deselect commands |
199 | */ | 224 | */ |
200 | enum ssp_chip_select { | 225 | enum ssp_chip_select { |
@@ -237,6 +262,8 @@ struct pl022_ssp_controller { | |||
237 | * @ctrl_len: Microwire interface: Control length | 262 | * @ctrl_len: Microwire interface: Control length |
238 | * @wait_state: Microwire interface: Wait state | 263 | * @wait_state: Microwire interface: Wait state |
239 | * @duplex: Microwire interface: Full/Half duplex | 264 | * @duplex: Microwire interface: Full/Half duplex |
265 | * @clkdelay: on the PL023 variant, the delay in feeback clock cycles | ||
266 | * before sampling the incoming line | ||
240 | * @cs_control: function pointer to board-specific function to | 267 | * @cs_control: function pointer to board-specific function to |
241 | * assert/deassert I/O port to control HW generation of devices chip-select. | 268 | * assert/deassert I/O port to control HW generation of devices chip-select. |
242 | * @dma_xfer_type: Type of DMA xfer (Mem-to-periph or Periph-to-Periph) | 269 | * @dma_xfer_type: Type of DMA xfer (Mem-to-periph or Periph-to-Periph) |
@@ -260,6 +287,7 @@ struct pl022_config_chip { | |||
260 | enum ssp_microwire_ctrl_len ctrl_len; | 287 | enum ssp_microwire_ctrl_len ctrl_len; |
261 | enum ssp_microwire_wait_state wait_state; | 288 | enum ssp_microwire_wait_state wait_state; |
262 | enum ssp_duplex duplex; | 289 | enum ssp_duplex duplex; |
290 | enum ssp_clkdelay clkdelay; | ||
263 | void (*cs_control) (u32 control); | 291 | void (*cs_control) (u32 control); |
264 | }; | 292 | }; |
265 | 293 | ||