--- zzzz-none-000/linux-5.15.111/drivers/spi/spi-pxa2xx.c 2023-05-11 14:00:40.000000000 +0000 +++ puma7-atom-6670-761/linux-5.15.111/drivers/spi/spi-pxa2xx.c 2024-02-07 10:23:20.000000000 +0000 @@ -39,6 +39,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 @@ -67,8 +78,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) @@ -167,6 +180,19 @@ .cs_sel_mask = 3 << 8, .cs_clk_stays_gated = true, }, + { /* 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 @@ -181,6 +207,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: case LPSS_CNL_SSP: @@ -323,6 +350,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 @@ -356,6 +413,9 @@ config->reg_general, value); } } + + /* Init LPSS private register bits */ + lpss_ssp_init(drv_data); } static void lpss_ssp_select_cs(struct spi_device *spi, @@ -394,6 +454,7 @@ struct driver_data *drv_data = spi_controller_get_devdata(spi->controller); const struct lpss_config *config; + struct chip_data *chip = spi_get_ctldata(spi); u32 value; config = lpss_get_config(drv_data); @@ -406,6 +467,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); if (config->cs_clk_stays_gated) { u32 clkgate; @@ -1270,6 +1337,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: case LPSS_CNL_SSP: @@ -1336,6 +1404,11 @@ chip->cr1 |= SSCR1_SFRMDIR; chip->cr1 |= SSCR1_SPH; } + if (is_lpss_ssp(drv_data)) { + chip->chip_select = spi->chip_select; + chip->enable_dma = drv_data->controller_info->enable_dma; + } + if (is_lpss_ssp(drv_data)) { chip->lpss_rx_threshold = SSIRF_RxThresh(rx_thres); @@ -1433,6 +1506,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); @@ -1647,6 +1721,7 @@ */ case LPSS_BYT_SSP: case LPSS_BSW_SSP: + case LPSS_PUMA7_SSP: return cs - 1; default: @@ -1790,6 +1865,8 @@ pxa_ssp_disable(ssp); + /* Setup and Reset LPSS SPI first */ + lpss_ssp_setup(drv_data); /* Load default SSP configuration */ switch (drv_data->ssp_type) { case QUARK_X1000_SSP: @@ -1971,6 +2048,10 @@ int status; status = clk_prepare_enable(drv_data->ssp->clk); + + /* Init LPSS private register bits */ + lpss_ssp_init(drv_data); + return status; } #endif