/* * lpss_ssp_setup - perform LPSS SSP specific setup * @drv_data: pointer to the driver private data * * Perform LPSS SSP specific setup. This function must be called first if * one is going to use LPSS SSP private registers. */ static void lpss_ssp_setup(struct driver_data *drv_data) { unsigned offset = 0x400; u32 value, orig; if (!is_lpss_ssp(drv_data)) return; /* * Perform auto-detection of the LPSS SSP private registers. They * can be either at 1k or 2k offset from the base address. */ orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); /* Test SPI_CS_CONTROL_SW_MODE bit enabling */ value = orig | SPI_CS_CONTROL_SW_MODE; writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL); value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); if (value != (orig | SPI_CS_CONTROL_SW_MODE)) { offset = 0x800; goto detection_done; } orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); /* Test SPI_CS_CONTROL_SW_MODE bit disabling */ value = orig & ~SPI_CS_CONTROL_SW_MODE; writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL); value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); if (value != (orig & ~SPI_CS_CONTROL_SW_MODE)) { offset = 0x800; goto detection_done; } detection_done: /* Now set the LPSS base */ drv_data->lpss_base = drv_data->ioaddr + offset; /* Enable software chip select control */ value = SPI_CS_CONTROL_SW_MODE | SPI_CS_CONTROL_CS_HIGH; __lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value); /* Enable multiblock DMA transfers */ if (drv_data->master_info->enable_dma) { __lpss_ssp_write_priv(drv_data, SSP_REG, 1); value = __lpss_ssp_read_priv(drv_data, GENERAL_REG); value |= GENERAL_REG_RXTO_HOLDOFF_DISABLE; __lpss_ssp_write_priv(drv_data, GENERAL_REG, value); } }
static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable) { u32 value; value = __lpss_ssp_read_priv(drv_data, SPI_CS_CONTROL); if (enable) value &= ~SPI_CS_CONTROL_CS_HIGH; else value |= SPI_CS_CONTROL_CS_HIGH; __lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value); }
static void lpss_ssp_restore(struct driver_data *drv_data) { u32 update_bit, param; u32 m = 1, n = 1; u32 value; if (!is_lpss_ssp(drv_data)) return; /* Reset LPSS SSP Controller */ __lpss_ssp_write_priv(drv_data, SSP_RESETS, 0x0); usleep_range(10, 100); __lpss_ssp_write_priv(drv_data, SSP_RESETS, 0x3); usleep_range(10, 100); /* Setting the clock divisor */ update_bit = 1 << 31; param = (m << 1) | (n << 16) | 0x1; __lpss_ssp_write_priv(drv_data, PRV_CLK_PARAMS, param); __lpss_ssp_write_priv(drv_data, PRV_CLK_PARAMS, param | update_bit); drv_data->max_clk_rate = 100000000; dev_dbg(&drv_data->pdev->dev, "ssp_clk=%dMHz\n", (100*m/n)); /* Enable software chip select control */ value = SPI_CS_CONTROL_SW_MODE | SPI_CS_CONTROL_CS_HIGH; __lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value); /* Enable multiblock DMA transfers */ if (drv_data->master_info->enable_dma) __lpss_ssp_write_priv(drv_data, SSP_REG, 1); }
static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable) { struct chip_data *chip = drv_data->cur_chip; u32 value; if (!is_lpss_ssp(drv_data)) return; value = __lpss_ssp_read_priv(drv_data, SPI_CS_CONTROL); if (enable) value &= ~SPI_CS_CONTROL_CS_HIGH; else value |= SPI_CS_CONTROL_CS_HIGH; if (chip->chip_select) value |= SPI_CS_CONTROL_CS_SEL; else value &= ~SPI_CS_CONTROL_CS_SEL; __lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value); }
/* * lpss_ssp_setup - perform LPSS SSP specific setup * @drv_data: pointer to the driver private data * * Perform LPSS SSP specific setup. This function must be called first if * one is going to use LPSS SSP private registers. */ static void lpss_ssp_setup(struct driver_data *drv_data) { unsigned offset = 0x400; u32 value, orig; if (!is_lpss_ssp(drv_data)) return; /* * Perform auto-detection of the LPSS SSP private registers. They * can be either at 1k or 2k offset from the base address. */ orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); value = orig | SPI_CS_CONTROL_SW_MODE; writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL); value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); if (value != (orig | SPI_CS_CONTROL_SW_MODE)) { offset = 0x800; goto detection_done; } value &= ~SPI_CS_CONTROL_SW_MODE; writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL); value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); if (value != orig) { offset = 0x800; goto detection_done; } detection_done: /* Now set the LPSS base */ drv_data->lpss_base = drv_data->ioaddr + offset; /* Enable software chip select control */ value = SPI_CS_CONTROL_SW_MODE | SPI_CS_CONTROL_CS_HIGH; __lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value); }