|
@@ -135,6 +135,8 @@
|
|
#define SSP_CR1_MASK_MWAIT_ST (0x1UL << 6)
|
|
#define SSP_CR1_MASK_MWAIT_ST (0x1UL << 6)
|
|
#define SSP_CR1_MASK_RXIFLSEL_ST (0x7UL << 7)
|
|
#define SSP_CR1_MASK_RXIFLSEL_ST (0x7UL << 7)
|
|
#define SSP_CR1_MASK_TXIFLSEL_ST (0x7UL << 10)
|
|
#define SSP_CR1_MASK_TXIFLSEL_ST (0x7UL << 10)
|
|
|
|
+/* This one is only in the PL023 variant */
|
|
|
|
+#define SSP_CR1_MASK_FBCLKDEL_ST (0x7UL << 13)
|
|
|
|
|
|
/*
|
|
/*
|
|
* SSP Status Register - SSP_SR
|
|
* SSP Status Register - SSP_SR
|
|
@@ -317,12 +319,14 @@ enum ssp_writing {
|
|
* @unidir: supports unidirection transfers
|
|
* @unidir: supports unidirection transfers
|
|
* @extended_cr: 32 bit wide control register 0 with extra
|
|
* @extended_cr: 32 bit wide control register 0 with extra
|
|
* features and extra features in CR1 as found in the ST variants
|
|
* features and extra features in CR1 as found in the ST variants
|
|
|
|
+ * @pl023: supports a subset of the ST extensions called "PL023"
|
|
*/
|
|
*/
|
|
struct vendor_data {
|
|
struct vendor_data {
|
|
int fifodepth;
|
|
int fifodepth;
|
|
int max_bpw;
|
|
int max_bpw;
|
|
bool unidir;
|
|
bool unidir;
|
|
bool extended_cr;
|
|
bool extended_cr;
|
|
|
|
+ bool pl023;
|
|
};
|
|
};
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -541,11 +545,6 @@ static void restore_state(struct pl022 *pl022)
|
|
writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
|
|
writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
|
|
}
|
|
}
|
|
|
|
|
|
-/**
|
|
|
|
- * load_ssp_default_config - Load default configuration for SSP
|
|
|
|
- * @pl022: SSP driver private data structure
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Default SSP Register Values
|
|
* Default SSP Register Values
|
|
*/
|
|
*/
|
|
@@ -568,6 +567,14 @@ static void restore_state(struct pl022 *pl022)
|
|
GEN_MASK_BITS(SSP_INTERFACE_MOTOROLA_SPI, SSP_CR0_MASK_FRF_ST, 21) \
|
|
GEN_MASK_BITS(SSP_INTERFACE_MOTOROLA_SPI, SSP_CR0_MASK_FRF_ST, 21) \
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+/* The PL023 version is slightly different again */
|
|
|
|
+#define DEFAULT_SSP_REG_CR0_ST_PL023 ( \
|
|
|
|
+ GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS_ST, 0) | \
|
|
|
|
+ GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \
|
|
|
|
+ GEN_MASK_BITS(SSP_CLK_SECOND_EDGE, SSP_CR0_MASK_SPH, 7) | \
|
|
|
|
+ GEN_MASK_BITS(SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) \
|
|
|
|
+)
|
|
|
|
+
|
|
#define DEFAULT_SSP_REG_CR1 ( \
|
|
#define DEFAULT_SSP_REG_CR1 ( \
|
|
GEN_MASK_BITS(LOOPBACK_DISABLED, SSP_CR1_MASK_LBM, 0) | \
|
|
GEN_MASK_BITS(LOOPBACK_DISABLED, SSP_CR1_MASK_LBM, 0) | \
|
|
GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \
|
|
GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \
|
|
@@ -585,6 +592,20 @@ static void restore_state(struct pl022 *pl022)
|
|
GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL_ST, 10) \
|
|
GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL_ST, 10) \
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * The PL023 variant has further differences: no loopback mode, no microwire
|
|
|
|
+ * support, and a new clock feedback delay setting.
|
|
|
|
+ */
|
|
|
|
+#define DEFAULT_SSP_REG_CR1_ST_PL023 ( \
|
|
|
|
+ GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \
|
|
|
|
+ GEN_MASK_BITS(SSP_MASTER, SSP_CR1_MASK_MS, 2) | \
|
|
|
|
+ GEN_MASK_BITS(DO_NOT_DRIVE_TX, SSP_CR1_MASK_SOD, 3) | \
|
|
|
|
+ GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_RENDN_ST, 4) | \
|
|
|
|
+ GEN_MASK_BITS(SSP_TX_MSB, SSP_CR1_MASK_TENDN_ST, 5) | \
|
|
|
|
+ GEN_MASK_BITS(SSP_RX_1_OR_MORE_ELEM, SSP_CR1_MASK_RXIFLSEL_ST, 7) | \
|
|
|
|
+ GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL_ST, 10) | \
|
|
|
|
+ GEN_MASK_BITS(SSP_FEEDBACK_CLK_DELAY_NONE, SSP_CR1_MASK_FBCLKDEL_ST, 13) \
|
|
|
|
+)
|
|
|
|
|
|
#define DEFAULT_SSP_REG_CPSR ( \
|
|
#define DEFAULT_SSP_REG_CPSR ( \
|
|
GEN_MASK_BITS(SSP_DEFAULT_PRESCALE, SSP_CPSR_MASK_CPSDVSR, 0) \
|
|
GEN_MASK_BITS(SSP_DEFAULT_PRESCALE, SSP_CPSR_MASK_CPSDVSR, 0) \
|
|
@@ -595,10 +616,16 @@ static void restore_state(struct pl022 *pl022)
|
|
GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_TXDMAE, 1) \
|
|
GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_TXDMAE, 1) \
|
|
)
|
|
)
|
|
|
|
|
|
-
|
|
|
|
|
|
+/**
|
|
|
|
+ * load_ssp_default_config - Load default configuration for SSP
|
|
|
|
+ * @pl022: SSP driver private data structure
|
|
|
|
+ */
|
|
static void load_ssp_default_config(struct pl022 *pl022)
|
|
static void load_ssp_default_config(struct pl022 *pl022)
|
|
{
|
|
{
|
|
- if (pl022->vendor->extended_cr) {
|
|
|
|
|
|
+ if (pl022->vendor->pl023) {
|
|
|
|
+ writel(DEFAULT_SSP_REG_CR0_ST_PL023, SSP_CR0(pl022->virtbase));
|
|
|
|
+ writew(DEFAULT_SSP_REG_CR1_ST_PL023, SSP_CR1(pl022->virtbase));
|
|
|
|
+ } else if (pl022->vendor->extended_cr) {
|
|
writel(DEFAULT_SSP_REG_CR0_ST, SSP_CR0(pl022->virtbase));
|
|
writel(DEFAULT_SSP_REG_CR0_ST, SSP_CR0(pl022->virtbase));
|
|
writew(DEFAULT_SSP_REG_CR1_ST, SSP_CR1(pl022->virtbase));
|
|
writew(DEFAULT_SSP_REG_CR1_ST, SSP_CR1(pl022->virtbase));
|
|
} else {
|
|
} else {
|
|
@@ -1629,20 +1656,27 @@ static int pl022_setup(struct spi_device *spi)
|
|
|
|
|
|
/* Special setup for the ST micro extended control registers */
|
|
/* Special setup for the ST micro extended control registers */
|
|
if (pl022->vendor->extended_cr) {
|
|
if (pl022->vendor->extended_cr) {
|
|
|
|
+ if (pl022->vendor->pl023) {
|
|
|
|
+ /* These bits are only in the PL023 */
|
|
|
|
+ SSP_WRITE_BITS(chip->cr1, chip_info->clkdelay,
|
|
|
|
+ SSP_CR1_MASK_FBCLKDEL_ST, 13);
|
|
|
|
+ } else {
|
|
|
|
+ /* These bits are in the PL022 but not PL023 */
|
|
|
|
+ SSP_WRITE_BITS(chip->cr0, chip_info->duplex,
|
|
|
|
+ SSP_CR0_MASK_HALFDUP_ST, 5);
|
|
|
|
+ SSP_WRITE_BITS(chip->cr0, chip_info->ctrl_len,
|
|
|
|
+ SSP_CR0_MASK_CSS_ST, 16);
|
|
|
|
+ SSP_WRITE_BITS(chip->cr0, chip_info->iface,
|
|
|
|
+ SSP_CR0_MASK_FRF_ST, 21);
|
|
|
|
+ SSP_WRITE_BITS(chip->cr1, chip_info->wait_state,
|
|
|
|
+ SSP_CR1_MASK_MWAIT_ST, 6);
|
|
|
|
+ }
|
|
SSP_WRITE_BITS(chip->cr0, chip_info->data_size,
|
|
SSP_WRITE_BITS(chip->cr0, chip_info->data_size,
|
|
SSP_CR0_MASK_DSS_ST, 0);
|
|
SSP_CR0_MASK_DSS_ST, 0);
|
|
- SSP_WRITE_BITS(chip->cr0, chip_info->duplex,
|
|
|
|
- SSP_CR0_MASK_HALFDUP_ST, 5);
|
|
|
|
- SSP_WRITE_BITS(chip->cr0, chip_info->ctrl_len,
|
|
|
|
- SSP_CR0_MASK_CSS_ST, 16);
|
|
|
|
- SSP_WRITE_BITS(chip->cr0, chip_info->iface,
|
|
|
|
- SSP_CR0_MASK_FRF_ST, 21);
|
|
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->endian_rx,
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->endian_rx,
|
|
SSP_CR1_MASK_RENDN_ST, 4);
|
|
SSP_CR1_MASK_RENDN_ST, 4);
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->endian_tx,
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->endian_tx,
|
|
SSP_CR1_MASK_TENDN_ST, 5);
|
|
SSP_CR1_MASK_TENDN_ST, 5);
|
|
- SSP_WRITE_BITS(chip->cr1, chip_info->wait_state,
|
|
|
|
- SSP_CR1_MASK_MWAIT_ST, 6);
|
|
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->rx_lev_trig,
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->rx_lev_trig,
|
|
SSP_CR1_MASK_RXIFLSEL_ST, 7);
|
|
SSP_CR1_MASK_RXIFLSEL_ST, 7);
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig,
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig,
|
|
@@ -1657,7 +1691,9 @@ static int pl022_setup(struct spi_device *spi)
|
|
SSP_WRITE_BITS(chip->cr0, chip_info->clk_pol, SSP_CR0_MASK_SPO, 6);
|
|
SSP_WRITE_BITS(chip->cr0, chip_info->clk_pol, SSP_CR0_MASK_SPO, 6);
|
|
SSP_WRITE_BITS(chip->cr0, chip_info->clk_phase, SSP_CR0_MASK_SPH, 7);
|
|
SSP_WRITE_BITS(chip->cr0, chip_info->clk_phase, SSP_CR0_MASK_SPH, 7);
|
|
SSP_WRITE_BITS(chip->cr0, chip_info->clk_freq.scr, SSP_CR0_MASK_SCR, 8);
|
|
SSP_WRITE_BITS(chip->cr0, chip_info->clk_freq.scr, SSP_CR0_MASK_SCR, 8);
|
|
- SSP_WRITE_BITS(chip->cr1, chip_info->lbm, SSP_CR1_MASK_LBM, 0);
|
|
|
|
|
|
+ /* Loopback is available on all versions except PL023 */
|
|
|
|
+ if (!pl022->vendor->pl023)
|
|
|
|
+ SSP_WRITE_BITS(chip->cr1, chip_info->lbm, SSP_CR1_MASK_LBM, 0);
|
|
SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1);
|
|
SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1);
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2);
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2);
|
|
SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3);
|
|
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 = {
|
|
.max_bpw = 16,
|
|
.max_bpw = 16,
|
|
.unidir = false,
|
|
.unidir = false,
|
|
.extended_cr = false,
|
|
.extended_cr = false,
|
|
|
|
+ .pl023 = false,
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
@@ -1882,6 +1919,15 @@ static struct vendor_data vendor_st = {
|
|
.max_bpw = 32,
|
|
.max_bpw = 32,
|
|
.unidir = false,
|
|
.unidir = false,
|
|
.extended_cr = true,
|
|
.extended_cr = true,
|
|
|
|
+ .pl023 = false,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static struct vendor_data vendor_st_pl023 = {
|
|
|
|
+ .fifodepth = 32,
|
|
|
|
+ .max_bpw = 32,
|
|
|
|
+ .unidir = false,
|
|
|
|
+ .extended_cr = true,
|
|
|
|
+ .pl023 = true,
|
|
};
|
|
};
|
|
|
|
|
|
static struct amba_id pl022_ids[] = {
|
|
static struct amba_id pl022_ids[] = {
|
|
@@ -1903,6 +1949,18 @@ static struct amba_id pl022_ids[] = {
|
|
.mask = 0xffffffff,
|
|
.mask = 0xffffffff,
|
|
.data = &vendor_st,
|
|
.data = &vendor_st,
|
|
},
|
|
},
|
|
|
|
+ {
|
|
|
|
+ /*
|
|
|
|
+ * ST-Ericsson derivative "PL023" (this is not
|
|
|
|
+ * an official ARM number), this is a PL022 SSP block
|
|
|
|
+ * stripped to SPI mode only, it has 32bit wide
|
|
|
|
+ * and 32 locations deep TX/RX FIFO but no extended
|
|
|
|
+ * CR0/CR1 register
|
|
|
|
+ */
|
|
|
|
+ .id = 0x00080023,
|
|
|
|
+ .mask = 0xffffffff,
|
|
|
|
+ .data = &vendor_st_pl023,
|
|
|
|
+ },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
};
|
|
};
|
|
|
|
|