diff options
| -rw-r--r-- | drivers/spi/spi-mt65xx.c | 45 | ||||
| -rw-r--r-- | include/linux/platform_data/spi-mt65xx.h | 2 |
2 files changed, 42 insertions, 5 deletions
diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 278867a31950..eae73b58248b 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c | |||
| @@ -35,11 +35,15 @@ | |||
| 35 | #define SPI_CMD_REG 0x0018 | 35 | #define SPI_CMD_REG 0x0018 |
| 36 | #define SPI_STATUS0_REG 0x001c | 36 | #define SPI_STATUS0_REG 0x001c |
| 37 | #define SPI_PAD_SEL_REG 0x0024 | 37 | #define SPI_PAD_SEL_REG 0x0024 |
| 38 | #define SPI_CFG2_REG 0x0028 | ||
| 38 | 39 | ||
| 39 | #define SPI_CFG0_SCK_HIGH_OFFSET 0 | 40 | #define SPI_CFG0_SCK_HIGH_OFFSET 0 |
| 40 | #define SPI_CFG0_SCK_LOW_OFFSET 8 | 41 | #define SPI_CFG0_SCK_LOW_OFFSET 8 |
| 41 | #define SPI_CFG0_CS_HOLD_OFFSET 16 | 42 | #define SPI_CFG0_CS_HOLD_OFFSET 16 |
| 42 | #define SPI_CFG0_CS_SETUP_OFFSET 24 | 43 | #define SPI_CFG0_CS_SETUP_OFFSET 24 |
| 44 | #define SPI_ADJUST_CFG0_SCK_LOW_OFFSET 16 | ||
| 45 | #define SPI_ADJUST_CFG0_CS_HOLD_OFFSET 0 | ||
| 46 | #define SPI_ADJUST_CFG0_CS_SETUP_OFFSET 16 | ||
| 43 | 47 | ||
| 44 | #define SPI_CFG1_CS_IDLE_OFFSET 0 | 48 | #define SPI_CFG1_CS_IDLE_OFFSET 0 |
| 45 | #define SPI_CFG1_PACKET_LOOP_OFFSET 8 | 49 | #define SPI_CFG1_PACKET_LOOP_OFFSET 8 |
| @@ -55,6 +59,8 @@ | |||
| 55 | #define SPI_CMD_RST BIT(2) | 59 | #define SPI_CMD_RST BIT(2) |
| 56 | #define SPI_CMD_PAUSE_EN BIT(4) | 60 | #define SPI_CMD_PAUSE_EN BIT(4) |
| 57 | #define SPI_CMD_DEASSERT BIT(5) | 61 | #define SPI_CMD_DEASSERT BIT(5) |
| 62 | #define SPI_CMD_SAMPLE_SEL BIT(6) | ||
| 63 | #define SPI_CMD_CS_POL BIT(7) | ||
| 58 | #define SPI_CMD_CPHA BIT(8) | 64 | #define SPI_CMD_CPHA BIT(8) |
| 59 | #define SPI_CMD_CPOL BIT(9) | 65 | #define SPI_CMD_CPOL BIT(9) |
| 60 | #define SPI_CMD_RX_DMA BIT(10) | 66 | #define SPI_CMD_RX_DMA BIT(10) |
| @@ -80,6 +86,8 @@ struct mtk_spi_compatible { | |||
| 80 | bool need_pad_sel; | 86 | bool need_pad_sel; |
| 81 | /* Must explicitly send dummy Tx bytes to do Rx only transfer */ | 87 | /* Must explicitly send dummy Tx bytes to do Rx only transfer */ |
| 82 | bool must_tx; | 88 | bool must_tx; |
| 89 | /* some IC design adjust cfg register to enhance time accuracy */ | ||
| 90 | bool enhance_timing; | ||
| 83 | }; | 91 | }; |
| 84 | 92 | ||
| 85 | struct mtk_spi { | 93 | struct mtk_spi { |
| @@ -108,6 +116,8 @@ static const struct mtk_spi_compatible mt8173_compat = { | |||
| 108 | static const struct mtk_chip_config mtk_default_chip_info = { | 116 | static const struct mtk_chip_config mtk_default_chip_info = { |
| 109 | .rx_mlsb = 1, | 117 | .rx_mlsb = 1, |
| 110 | .tx_mlsb = 1, | 118 | .tx_mlsb = 1, |
| 119 | .cs_pol = 0, | ||
| 120 | .sample_sel = 0, | ||
| 111 | }; | 121 | }; |
| 112 | 122 | ||
| 113 | static const struct of_device_id mtk_spi_of_match[] = { | 123 | static const struct of_device_id mtk_spi_of_match[] = { |
| @@ -182,6 +192,17 @@ static int mtk_spi_prepare_message(struct spi_master *master, | |||
| 182 | reg_val |= SPI_CMD_RX_ENDIAN; | 192 | reg_val |= SPI_CMD_RX_ENDIAN; |
| 183 | #endif | 193 | #endif |
| 184 | 194 | ||
| 195 | if (mdata->dev_comp->enhance_timing) { | ||
| 196 | if (chip_config->cs_pol) | ||
| 197 | reg_val |= SPI_CMD_CS_POL; | ||
| 198 | else | ||
| 199 | reg_val &= ~SPI_CMD_CS_POL; | ||
| 200 | if (chip_config->sample_sel) | ||
| 201 | reg_val |= SPI_CMD_SAMPLE_SEL; | ||
| 202 | else | ||
| 203 | reg_val &= ~SPI_CMD_SAMPLE_SEL; | ||
| 204 | } | ||
| 205 | |||
| 185 | /* set finish and pause interrupt always enable */ | 206 | /* set finish and pause interrupt always enable */ |
| 186 | reg_val |= SPI_CMD_FINISH_IE | SPI_CMD_PAUSE_IE; | 207 | reg_val |= SPI_CMD_FINISH_IE | SPI_CMD_PAUSE_IE; |
| 187 | 208 | ||
| @@ -233,11 +254,25 @@ static void mtk_spi_prepare_transfer(struct spi_master *master, | |||
| 233 | sck_time = (div + 1) / 2; | 254 | sck_time = (div + 1) / 2; |
| 234 | cs_time = sck_time * 2; | 255 | cs_time = sck_time * 2; |
| 235 | 256 | ||
| 236 | reg_val |= (((sck_time - 1) & 0xff) << SPI_CFG0_SCK_HIGH_OFFSET); | 257 | if (mdata->dev_comp->enhance_timing) { |
| 237 | reg_val |= (((sck_time - 1) & 0xff) << SPI_CFG0_SCK_LOW_OFFSET); | 258 | reg_val |= (((sck_time - 1) & 0xffff) |
| 238 | reg_val |= (((cs_time - 1) & 0xff) << SPI_CFG0_CS_HOLD_OFFSET); | 259 | << SPI_CFG0_SCK_HIGH_OFFSET); |
| 239 | reg_val |= (((cs_time - 1) & 0xff) << SPI_CFG0_CS_SETUP_OFFSET); | 260 | reg_val |= (((sck_time - 1) & 0xffff) |
| 240 | writel(reg_val, mdata->base + SPI_CFG0_REG); | 261 | << SPI_ADJUST_CFG0_SCK_LOW_OFFSET); |
| 262 | writel(reg_val, mdata->base + SPI_CFG2_REG); | ||
| 263 | reg_val |= (((cs_time - 1) & 0xffff) | ||
| 264 | << SPI_ADJUST_CFG0_CS_HOLD_OFFSET); | ||
| 265 | reg_val |= (((cs_time - 1) & 0xffff) | ||
| 266 | << SPI_ADJUST_CFG0_CS_SETUP_OFFSET); | ||
| 267 | writel(reg_val, mdata->base + SPI_CFG0_REG); | ||
| 268 | } else { | ||
| 269 | reg_val |= (((sck_time - 1) & 0xff) | ||
| 270 | << SPI_CFG0_SCK_HIGH_OFFSET); | ||
| 271 | reg_val |= (((sck_time - 1) & 0xff) << SPI_CFG0_SCK_LOW_OFFSET); | ||
| 272 | reg_val |= (((cs_time - 1) & 0xff) << SPI_CFG0_CS_HOLD_OFFSET); | ||
| 273 | reg_val |= (((cs_time - 1) & 0xff) << SPI_CFG0_CS_SETUP_OFFSET); | ||
| 274 | writel(reg_val, mdata->base + SPI_CFG0_REG); | ||
| 275 | } | ||
| 241 | 276 | ||
| 242 | reg_val = readl(mdata->base + SPI_CFG1_REG); | 277 | reg_val = readl(mdata->base + SPI_CFG1_REG); |
| 243 | reg_val &= ~SPI_CFG1_CS_IDLE_MASK; | 278 | reg_val &= ~SPI_CFG1_CS_IDLE_MASK; |
diff --git a/include/linux/platform_data/spi-mt65xx.h b/include/linux/platform_data/spi-mt65xx.h index 54b04483976c..ba4e4bb70262 100644 --- a/include/linux/platform_data/spi-mt65xx.h +++ b/include/linux/platform_data/spi-mt65xx.h | |||
| @@ -16,5 +16,7 @@ | |||
| 16 | struct mtk_chip_config { | 16 | struct mtk_chip_config { |
| 17 | u32 tx_mlsb; | 17 | u32 tx_mlsb; |
| 18 | u32 rx_mlsb; | 18 | u32 rx_mlsb; |
| 19 | u32 cs_pol; | ||
| 20 | u32 sample_sel; | ||
| 19 | }; | 21 | }; |
| 20 | #endif | 22 | #endif |
