mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 21:51:40 +00:00
spi: fsl_spi: Convert to transfer_one
Let the core handle all the chipselect bakery and replace transfer_one_message() by transfer_one() and prepare_message(). At the time being, there is fsl_spi_cs_control() to handle chipselects. That function handles both GPIO and non-GPIO chipselects. The GPIO chipselects will now be handled by the core directly, so only handle non-GPIO chipselects and hook it to ->set_cs Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> Link: https://lore.kernel.org/r/753266abafe81722d86c3ddb8bac8ef1cb00fe8c.1660829841.git.christophe.leroy@csgroup.eu Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
83e5335bf5
commit
64ca1a034f
@ -111,32 +111,6 @@ static void fsl_spi_change_mode(struct spi_device *spi)
|
|||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fsl_spi_chipselect(struct spi_device *spi, int value)
|
|
||||||
{
|
|
||||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
|
|
||||||
struct fsl_spi_platform_data *pdata;
|
|
||||||
struct spi_mpc8xxx_cs *cs = spi->controller_state;
|
|
||||||
|
|
||||||
pdata = spi->dev.parent->parent->platform_data;
|
|
||||||
|
|
||||||
if (value == BITBANG_CS_INACTIVE) {
|
|
||||||
if (pdata->cs_control)
|
|
||||||
pdata->cs_control(spi, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value == BITBANG_CS_ACTIVE) {
|
|
||||||
mpc8xxx_spi->rx_shift = cs->rx_shift;
|
|
||||||
mpc8xxx_spi->tx_shift = cs->tx_shift;
|
|
||||||
mpc8xxx_spi->get_rx = cs->get_rx;
|
|
||||||
mpc8xxx_spi->get_tx = cs->get_tx;
|
|
||||||
|
|
||||||
fsl_spi_change_mode(spi);
|
|
||||||
|
|
||||||
if (pdata->cs_control)
|
|
||||||
pdata->cs_control(spi, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fsl_spi_qe_cpu_set_shifts(u32 *rx_shift, u32 *tx_shift,
|
static void fsl_spi_qe_cpu_set_shifts(u32 *rx_shift, u32 *tx_shift,
|
||||||
int bits_per_word, int msb_first)
|
int bits_per_word, int msb_first)
|
||||||
{
|
{
|
||||||
@ -354,15 +328,11 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
|
|||||||
return mpc8xxx_spi->count;
|
return mpc8xxx_spi->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fsl_spi_do_one_msg(struct spi_master *master,
|
static int fsl_spi_prepare_message(struct spi_controller *ctlr,
|
||||||
struct spi_message *m)
|
struct spi_message *m)
|
||||||
{
|
{
|
||||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
|
struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(ctlr);
|
||||||
struct spi_device *spi = m->spi;
|
struct spi_transfer *t;
|
||||||
struct spi_transfer *t, *first;
|
|
||||||
unsigned int cs_change;
|
|
||||||
const int nsecs = 50;
|
|
||||||
int status, last_bpw;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In CPU mode, optimize large byte transfers to use larger
|
* In CPU mode, optimize large byte transfers to use larger
|
||||||
@ -378,64 +348,32 @@ static int fsl_spi_do_one_msg(struct spi_master *master,
|
|||||||
t->bits_per_word = 16;
|
t->bits_per_word = 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't allow changes if CS is active */
|
|
||||||
cs_change = 1;
|
|
||||||
list_for_each_entry(t, &m->transfers, transfer_list) {
|
|
||||||
if (cs_change)
|
|
||||||
first = t;
|
|
||||||
cs_change = t->cs_change;
|
|
||||||
if (first->speed_hz != t->speed_hz) {
|
|
||||||
dev_err(&spi->dev,
|
|
||||||
"speed_hz cannot change while CS is active\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
last_bpw = -1;
|
|
||||||
cs_change = 1;
|
|
||||||
status = -EINVAL;
|
|
||||||
list_for_each_entry(t, &m->transfers, transfer_list) {
|
|
||||||
if (cs_change || last_bpw != t->bits_per_word)
|
|
||||||
status = fsl_spi_setup_transfer(spi, t);
|
|
||||||
if (status < 0)
|
|
||||||
break;
|
|
||||||
last_bpw = t->bits_per_word;
|
|
||||||
|
|
||||||
if (cs_change) {
|
|
||||||
fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE);
|
|
||||||
ndelay(nsecs);
|
|
||||||
}
|
|
||||||
cs_change = t->cs_change;
|
|
||||||
if (t->len)
|
|
||||||
status = fsl_spi_bufs(spi, t, m->is_dma_mapped);
|
|
||||||
if (status) {
|
|
||||||
status = -EMSGSIZE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
m->actual_length += t->len;
|
|
||||||
|
|
||||||
spi_transfer_delay_exec(t);
|
|
||||||
|
|
||||||
if (cs_change) {
|
|
||||||
ndelay(nsecs);
|
|
||||||
fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
|
|
||||||
ndelay(nsecs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m->status = status;
|
|
||||||
|
|
||||||
if (status || !cs_change) {
|
|
||||||
ndelay(nsecs);
|
|
||||||
fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
fsl_spi_setup_transfer(spi, NULL);
|
|
||||||
spi_finalize_current_message(master);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fsl_spi_transfer_one(struct spi_controller *controller,
|
||||||
|
struct spi_device *spi,
|
||||||
|
struct spi_transfer *t)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = fsl_spi_setup_transfer(spi, t);
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
|
if (t->len)
|
||||||
|
status = fsl_spi_bufs(spi, t, !!t->tx_dma || !!t->rx_dma);
|
||||||
|
if (status > 0)
|
||||||
|
return -EMSGSIZE;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fsl_spi_unprepare_message(struct spi_controller *controller,
|
||||||
|
struct spi_message *msg)
|
||||||
|
{
|
||||||
|
return fsl_spi_setup_transfer(msg->spi, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int fsl_spi_setup(struct spi_device *spi)
|
static int fsl_spi_setup(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
struct mpc8xxx_spi *mpc8xxx_spi;
|
struct mpc8xxx_spi *mpc8xxx_spi;
|
||||||
@ -482,9 +420,6 @@ static int fsl_spi_setup(struct spi_device *spi)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize chipselect - might be active for SPI_CS_HIGH mode */
|
|
||||||
fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,9 +492,7 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
|
|||||||
u32 slvsel;
|
u32 slvsel;
|
||||||
u16 cs = spi->chip_select;
|
u16 cs = spi->chip_select;
|
||||||
|
|
||||||
if (spi->cs_gpiod) {
|
if (cs < mpc8xxx_spi->native_chipselects) {
|
||||||
gpiod_set_value(spi->cs_gpiod, on);
|
|
||||||
} else if (cs < mpc8xxx_spi->native_chipselects) {
|
|
||||||
slvsel = mpc8xxx_spi_read_reg(®_base->slvsel);
|
slvsel = mpc8xxx_spi_read_reg(®_base->slvsel);
|
||||||
slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs));
|
slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs));
|
||||||
mpc8xxx_spi_write_reg(®_base->slvsel, slvsel);
|
mpc8xxx_spi_write_reg(®_base->slvsel, slvsel);
|
||||||
@ -568,7 +501,6 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
|
|||||||
|
|
||||||
static void fsl_spi_grlib_probe(struct device *dev)
|
static void fsl_spi_grlib_probe(struct device *dev)
|
||||||
{
|
{
|
||||||
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
|
|
||||||
struct spi_master *master = dev_get_drvdata(dev);
|
struct spi_master *master = dev_get_drvdata(dev);
|
||||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
|
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
|
||||||
struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base;
|
struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base;
|
||||||
@ -588,7 +520,18 @@ static void fsl_spi_grlib_probe(struct device *dev)
|
|||||||
mpc8xxx_spi_write_reg(®_base->slvsel, 0xffffffff);
|
mpc8xxx_spi_write_reg(®_base->slvsel, 0xffffffff);
|
||||||
}
|
}
|
||||||
master->num_chipselect = mpc8xxx_spi->native_chipselects;
|
master->num_chipselect = mpc8xxx_spi->native_chipselects;
|
||||||
pdata->cs_control = fsl_spi_grlib_cs_control;
|
master->set_cs = fsl_spi_grlib_cs_control;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fsl_spi_cs_control(struct spi_device *spi, bool on)
|
||||||
|
{
|
||||||
|
struct device *dev = spi->dev.parent->parent;
|
||||||
|
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
|
||||||
|
struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(!pinfo->immr_spi_cs))
|
||||||
|
return;
|
||||||
|
iowrite32be(on ? 0 : SPI_BOOT_SEL_BIT, pinfo->immr_spi_cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct spi_master *fsl_spi_probe(struct device *dev,
|
static struct spi_master *fsl_spi_probe(struct device *dev,
|
||||||
@ -613,8 +556,11 @@ static struct spi_master *fsl_spi_probe(struct device *dev,
|
|||||||
|
|
||||||
master->setup = fsl_spi_setup;
|
master->setup = fsl_spi_setup;
|
||||||
master->cleanup = fsl_spi_cleanup;
|
master->cleanup = fsl_spi_cleanup;
|
||||||
master->transfer_one_message = fsl_spi_do_one_msg;
|
master->prepare_message = fsl_spi_prepare_message;
|
||||||
|
master->transfer_one = fsl_spi_transfer_one;
|
||||||
|
master->unprepare_message = fsl_spi_unprepare_message;
|
||||||
master->use_gpio_descriptors = true;
|
master->use_gpio_descriptors = true;
|
||||||
|
master->set_cs = fsl_spi_cs_control;
|
||||||
|
|
||||||
mpc8xxx_spi = spi_master_get_devdata(master);
|
mpc8xxx_spi = spi_master_get_devdata(master);
|
||||||
mpc8xxx_spi->max_bits_per_word = 32;
|
mpc8xxx_spi->max_bits_per_word = 32;
|
||||||
@ -688,21 +634,6 @@ err:
|
|||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fsl_spi_cs_control(struct spi_device *spi, bool on)
|
|
||||||
{
|
|
||||||
if (spi->cs_gpiod) {
|
|
||||||
gpiod_set_value(spi->cs_gpiod, on);
|
|
||||||
} else {
|
|
||||||
struct device *dev = spi->dev.parent->parent;
|
|
||||||
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
|
|
||||||
struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
|
|
||||||
|
|
||||||
if (WARN_ON_ONCE(!pinfo->immr_spi_cs))
|
|
||||||
return;
|
|
||||||
iowrite32be(on ? 0 : SPI_BOOT_SEL_BIT, pinfo->immr_spi_cs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int of_fsl_spi_probe(struct platform_device *ofdev)
|
static int of_fsl_spi_probe(struct platform_device *ofdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &ofdev->dev;
|
struct device *dev = &ofdev->dev;
|
||||||
@ -744,12 +675,10 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
|
|||||||
ret = gpiod_count(dev, "cs");
|
ret = gpiod_count(dev, "cs");
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
if (ret == 0 && !spisel_boot) {
|
if (ret == 0 && !spisel_boot)
|
||||||
pdata->max_chipselect = 1;
|
pdata->max_chipselect = 1;
|
||||||
} else {
|
else
|
||||||
pdata->max_chipselect = ret + spisel_boot;
|
pdata->max_chipselect = ret + spisel_boot;
|
||||||
pdata->cs_control = fsl_spi_cs_control;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = of_address_to_resource(np, 0, &mem);
|
ret = of_address_to_resource(np, 0, &mem);
|
||||||
|
Loading…
Reference in New Issue
Block a user