Skip to content

Commit

Permalink
spi: pxa2xx: Add output control for multiple Intel LPSS chip selects
Browse files Browse the repository at this point in the history
Intel LPSS SPI host controllers in upcoming Intel platforms can have up
to 4 chip selects per port. Extend chip select control in
lpss_ssp_cs_control() by adding a code that selects the active chip
select output prior to changing the state. Detection for number of
enabled chip select signals will be added by another patch.

Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Jarkko Nikula authored and Mark Brown committed Oct 30, 2015
1 parent 624ea72 commit d0283eb
Showing 1 changed file with 24 additions and 3 deletions.
27 changes: 24 additions & 3 deletions drivers/spi/spi-pxa2xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ MODULE_ALIAS("platform:pxa2xx-spi");
#define LPSS_GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
#define LPSS_CS_CONTROL_SW_MODE BIT(0)
#define LPSS_CS_CONTROL_CS_HIGH BIT(1)
#define LPSS_CS_CONTROL_CS_SEL_SHIFT 8
#define LPSS_CS_CONTROL_CS_SEL_MASK (3 << LPSS_CS_CONTROL_CS_SEL_SHIFT)

struct lpss_config {
/* LPSS offset from drv_data->ioaddr */
Expand Down Expand Up @@ -271,15 +273,34 @@ static void lpss_ssp_setup(struct driver_data *drv_data)
static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable)
{
const struct lpss_config *config;
u32 value;
u32 value, cs;

config = lpss_get_config(drv_data);

value = __lpss_ssp_read_priv(drv_data, config->reg_cs_ctrl);
if (enable)
if (enable) {
cs = drv_data->cur_msg->spi->chip_select;
cs <<= LPSS_CS_CONTROL_CS_SEL_SHIFT;
if (cs != (value & LPSS_CS_CONTROL_CS_SEL_MASK)) {
/*
* When switching another chip select output active
* the output must be selected first and wait 2 ssp_clk
* cycles before changing state to active. Otherwise
* a short glitch will occur on the previous chip
* select since output select is latched but state
* control is not.
*/
value &= ~LPSS_CS_CONTROL_CS_SEL_MASK;
value |= cs;
__lpss_ssp_write_priv(drv_data,
config->reg_cs_ctrl, value);
ndelay(1000000000 /
(drv_data->master->max_speed_hz / 2));
}
value &= ~LPSS_CS_CONTROL_CS_HIGH;
else
} else {
value |= LPSS_CS_CONTROL_CS_HIGH;
}
__lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value);
}

Expand Down

0 comments on commit d0283eb

Please sign in to comment.