--- zzzz-none-000/linux-4.9.279/drivers/spi/spi-pxa2xx.c 2021-08-08 06:38:54.000000000 +0000 +++ puma7-atom-6591-750/linux-4.9.279/drivers/spi/spi-pxa2xx.c 2023-02-08 11:43:42.000000000 +0000 @@ -43,6 +43,17 @@ #define TIMOUT_DFLT 1000 +/* Offset from drv_data->lpss_base */ +#define PRV_CLK_PARAMS 0x00 +#define PRV_CLK_EN BIT(0) +#define PRV_CLK_M_VAL_SHIFT 1 +#define PRV_CLK_N_VAL_SHIFT 16 +#define PRV_CLK_UPDATE BIT(31) + +#define SSP_RESETS 0x04 +#define SSP_RESETS_APB BIT(0) +#define SSP_RESETS_FUNC BIT(1) + /* * for testing SSCR1 changes that require SSP restart, basically * everything except the service and interrupt enables, the pxa270 developer @@ -71,8 +82,10 @@ | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM) #define LPSS_GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24) +#define DISABLE_SSP_DMA_FINISH BIT(0) #define LPSS_CS_CONTROL_SW_MODE BIT(0) #define LPSS_CS_CONTROL_CS_HIGH BIT(1) +#define LPSS_CS_CONTROL_CS_SEL BIT(2) #define LPSS_CAPS_CS_EN_SHIFT 9 #define LPSS_CAPS_CS_EN_MASK (0xf << LPSS_CAPS_CS_EN_SHIFT) @@ -151,6 +164,19 @@ .cs_sel_shift = 8, .cs_sel_mask = 3 << 8, }, + { /* LPSS_PUMA7_SSP */ + .offset = 0x400, + .reg_general = 0x08, + .reg_ssp = 0x0c, + .reg_cs_ctrl = 0x18, + .reg_capabilities = -1, + .rx_threshold = 64, + .tx_threshold_lo = 160, + .tx_threshold_hi = 224, + .cs_sel_shift = 2, + .cs_sel_mask = 1 << 2, + .cs_num = 2, + }, }; static inline const struct lpss_config @@ -165,6 +191,7 @@ case LPSS_LPT_SSP: case LPSS_BYT_SSP: case LPSS_BSW_SSP: + case LPSS_PUMA7_SSP: case LPSS_SPT_SSP: case LPSS_BXT_SSP: return true; @@ -292,6 +319,36 @@ writel(value, drv_data->lpss_base + offset); } +static void lpss_ssp_init(struct driver_data *drv_data) +{ + const struct lpss_config *config; + u32 param; + u32 m = 1, n = 1; + u32 value; + + if (!is_lpss_ssp(drv_data)) + return; + + config = lpss_get_config(drv_data); + + /* Reset apb and clock domain */ + __lpss_ssp_write_priv(drv_data, SSP_RESETS, 0x0); + usleep_range(10, 100); + __lpss_ssp_write_priv(drv_data, SSP_RESETS, + SSP_RESETS_APB | SSP_RESETS_FUNC); + usleep_range(10, 100); + + /* Setting the clock divisor */ + param = (m << PRV_CLK_M_VAL_SHIFT) | (n << PRV_CLK_N_VAL_SHIFT) + | PRV_CLK_EN; + __lpss_ssp_write_priv(drv_data, PRV_CLK_PARAMS, param); + __lpss_ssp_write_priv(drv_data, PRV_CLK_PARAMS, param | PRV_CLK_UPDATE); + + /* Enable software chip select control */ + value = LPSS_CS_CONTROL_SW_MODE | LPSS_CS_CONTROL_CS_HIGH; + __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value); +} + /* * lpss_ssp_setup - perform LPSS SSP specific setup * @drv_data: pointer to the driver private data @@ -325,6 +382,9 @@ config->reg_general, value); } } + + /* Init LPSS private register bits */ + lpss_ssp_init(drv_data); } static void lpss_ssp_select_cs(struct driver_data *drv_data, @@ -359,6 +419,8 @@ static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable) { const struct lpss_config *config; + struct chip_data *chip = + spi_get_ctldata(drv_data->master->cur_msg->spi); u32 value; config = lpss_get_config(drv_data); @@ -371,6 +433,12 @@ value &= ~LPSS_CS_CONTROL_CS_HIGH; else value |= LPSS_CS_CONTROL_CS_HIGH; + + if (chip->chip_select) + value |= LPSS_CS_CONTROL_CS_SEL; + else + value &= ~LPSS_CS_CONTROL_CS_SEL; + __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value); } @@ -1273,6 +1341,7 @@ case LPSS_LPT_SSP: case LPSS_BYT_SSP: case LPSS_BSW_SSP: + case LPSS_PUMA7_SSP: case LPSS_SPT_SSP: case LPSS_BXT_SSP: config = lpss_get_config(drv_data); @@ -1328,6 +1397,11 @@ if (chip_info->enable_loopback) chip->cr1 = SSCR1_LBM; } + if (is_lpss_ssp(drv_data)) { + chip->chip_select = spi->chip_select; + chip->enable_dma = drv_data->master_info->enable_dma; + } + chip->lpss_rx_threshold = SSIRF_RxThresh(rx_thres); chip->lpss_tx_threshold = SSITF_TxLoThresh(tx_thres) @@ -1418,6 +1492,7 @@ { "INT3431", LPSS_LPT_SSP }, { "80860F0E", LPSS_BYT_SSP }, { "8086228E", LPSS_BSW_SSP }, + { "80862B8E", LPSS_PUMA7_SSP }, { }, }; MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match); @@ -1567,6 +1642,7 @@ */ case LPSS_BYT_SSP: case LPSS_BSW_SSP: + case LPSS_PUMA7_SSP: return cs - 1; default: @@ -1682,6 +1758,8 @@ master->max_speed_hz = clk_get_rate(ssp->clk); + /* Setup and Reset LPSS SPI first */ + lpss_ssp_setup(drv_data); /* Load default SSP configuration */ pxa2xx_spi_write(drv_data, SSCR0, 0); switch (drv_data->ssp_type) { @@ -1890,6 +1968,10 @@ struct driver_data *drv_data = dev_get_drvdata(dev); clk_prepare_enable(drv_data->ssp->clk); + + /* Init LPSS private register bits */ + lpss_ssp_init(drv_data); + return 0; } #endif