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 | ||
