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 bool is_tx_fifo_full(struct driver_data *drv_data) { void __iomem *reg = drv_data->ioaddr; /* workaround for debug UART */ if (drv_data->ssp_type == INTEL_SSP && (drv_data->ssp->port_id == 5)) return ((read_SFIFOL(reg) & 0xFFFF) != 0); else if (!is_lpss_ssp(drv_data)) return ((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK); else return ((read_SSITF(reg) & SSITF_TFL_MASK) == SSITF_TFL_MASK); }
/* * 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; 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; __lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value); }
static void cs_deassert(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; if (drv_data->ssp_type == CE4100_SSP) return; if (chip->cs_control) { chip->cs_control(PXA2XX_CS_DEASSERT); return; } if (gpio_is_valid(chip->gpio_cs)) { gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted); return; } if (is_lpss_ssp(drv_data)) lpss_ssp_cs_control(drv_data, false); }
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); }
static void cs_assert(struct driver_data *drv_data) { struct chip_data *chip = drv_data->cur_chip; if (drv_data->ssp_type == CE4100_SSP) { pxa2xx_spi_write(drv_data, SSSR, drv_data->cur_chip->frm); return; } if (chip->cs_control) { chip->cs_control(PXA2XX_CS_ASSERT); return; } if (gpio_is_valid(chip->gpio_cs)) { gpio_set_value(chip->gpio_cs, chip->gpio_cs_inverted); return; } if (is_lpss_ssp(drv_data)) lpss_ssp_cs_control(drv_data, true); }
/* * 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); }
/* * 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; /* Init LPSS private register bits */ lpss_ssp_restore(drv_data); }