From: Charlie Paul <cpaul.windri...@gmail.com> Poerted the LSI spi driver from 3.10 to 3.14 because the driver was failing.
Signed-off-by: Charlie Paul <cpaul.windri...@gmail.com> --- drivers/spi/spi-pl022.c | 115 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 94 insertions(+), 21 deletions(-) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index fe091a8..e004b7b 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -50,7 +50,7 @@ * val shifted sb steps to the left. */ #define SSP_WRITE_BITS(reg, val, mask, sb) \ - ((reg) = (((reg) & ~(mask)) | (((val)<<(sb)) & (mask)))) + ((reg) = (((reg) & ~(mask)) | (((val)<<(sb)) & (mask)))) /* * This macro is also used to define some default values. @@ -58,7 +58,7 @@ * the result with mask. */ #define GEN_MASK_BITS(val, mask, sb) \ - (((val)<<(sb)) & (mask)) + (((val)<<(sb)) & (mask)) #define DRIVE_TX 0 #define DO_NOT_DRIVE_TX 1 @@ -368,6 +368,11 @@ struct pl022 { resource_size_t phybase; void __iomem *virtbase; struct clk *clk; + /* Two optional pin states - default & sleep */ + struct pinctrl *pinctrl; + struct pinctrl_state *pins_default; + struct pinctrl_state *pins_idle; + struct pinctrl_state *pins_sleep; struct spi_master *master; struct pl022_ssp_controller *master_info; /* Message per-transfer pump */ @@ -424,7 +429,7 @@ struct chip_data { bool enable_dma; enum ssp_reading read; enum ssp_writing write; - void (*cs_control) (u32 command); + void (*cs_control)(u32 command); int xfer_type; }; @@ -1075,7 +1080,7 @@ err_rxdesc: pl022->sgt_tx.nents, DMA_TO_DEVICE); err_tx_sgmap: dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl, - pl022->sgt_rx.nents, DMA_FROM_DEVICE); + pl022->sgt_tx.nents, DMA_FROM_DEVICE); err_rx_sgmap: sg_free_table(&pl022->sgt_tx); err_alloc_tx_sg: @@ -1162,7 +1167,7 @@ err_no_txchan: err_no_rxchan: return -ENODEV; } - + static void terminate_dma(struct pl022 *pl022) { struct dma_chan *rxchan = pl022->dma_rx_channel; @@ -1555,6 +1560,18 @@ static int pl022_transfer_one_message(struct spi_master *master, return 0; } +static int pl022_prepare_transfer_hardware(struct spi_master *master) +{ + struct pl022 *pl022 = spi_master_get_devdata(master); + + /* + * Just make sure we have all we need to run the transfer by syncing + * with the runtime PM framework. + */ + pm_runtime_get_sync(&pl022->adev->dev); + return 0; +} + static int pl022_unprepare_transfer_hardware(struct spi_master *master) { struct pl022 *pl022 = spi_master_get_devdata(master); @@ -1563,6 +1580,13 @@ static int pl022_unprepare_transfer_hardware(struct spi_master *master) writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); + if (pl022->master_info->autosuspend_delay > 0) { + pm_runtime_mark_last_busy(&pl022->adev->dev); + pm_runtime_put_autosuspend(&pl022->adev->dev); + } else { + pm_runtime_put(&pl022->adev->dev); + } + return 0; } @@ -1747,7 +1771,7 @@ static int calculate_effective_freq(struct pl022 *pl022, int freq, struct scr = SCR_MIN; } - WARN(!best_freq, "pl022: Matching cpsdvsr and scr not found for %d Hz rate \n", + WARN(!best_freq, "pl022: Matching cpsdvsr and scr not found for %d Hz rate\n", freq); clk_freq->cpsdvsr = (u8) (best_cpsdvsr & 0xFF); @@ -2057,7 +2081,6 @@ pl022_platform_data_dt_get(struct device *dev) } pd->bus_id = -1; - pd->enable_dma = 1; of_property_read_u32(np, "num-cs", &tmp); pd->num_chipselect = tmp; of_property_read_u32(np, "pl022,autosuspend-delay", @@ -2070,8 +2093,7 @@ pl022_platform_data_dt_get(struct device *dev) static int pl022_probe(struct amba_device *adev, const struct amba_id *id) { struct device *dev = &adev->dev; - struct pl022_ssp_controller *platform_info = - dev_get_platdata(&adev->dev); + struct pl022_ssp_controller *platform_info = adev->dev.platform_data; struct spi_master *master; struct pl022 *pl022 = NULL; /*Data for this driver */ struct device_node *np = adev->dev.of_node; @@ -2109,7 +2131,32 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) pl022->chipselects = devm_kzalloc(dev, num_cs * sizeof(int), GFP_KERNEL); - pinctrl_pm_select_default_state(dev); + pl022->pinctrl = devm_pinctrl_get(dev); + if (IS_ERR(pl022->pinctrl)) { + status = PTR_ERR(pl022->pinctrl); + goto err_no_pinctrl; + } + + pl022->pins_default = pinctrl_lookup_state(pl022->pinctrl, + PINCTRL_STATE_DEFAULT); + /* enable pins to be muxed in and configured */ + if (!IS_ERR(pl022->pins_default)) { + status = pinctrl_select_state(pl022->pinctrl, + pl022->pins_default); + if (status) + dev_err(dev, "could not set default pins\n"); + } else + dev_err(dev, "could not get default pinstate\n"); + + pl022->pins_idle = pinctrl_lookup_state(pl022->pinctrl, + PINCTRL_STATE_IDLE); + if (IS_ERR(pl022->pins_idle)) + dev_dbg(dev, "could not get idle pinstate\n"); + + pl022->pins_sleep = pinctrl_lookup_state(pl022->pinctrl, + PINCTRL_STATE_SLEEP); + if (IS_ERR(pl022->pins_sleep)) + dev_dbg(dev, "could not get sleep pinstate\n"); /* * Bus Number Which has been Assigned to this SSP controller @@ -2119,7 +2166,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) master->num_chipselect = num_cs; master->cleanup = pl022_cleanup; master->setup = pl022_setup; - master->auto_runtime_pm = true; + master->prepare_transfer_hardware = pl022_prepare_transfer_hardware; master->transfer_one_message = pl022_transfer_one_message; master->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware; master->rt = platform_info->rt; @@ -2173,8 +2220,8 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) status = -ENOMEM; goto err_no_ioremap; } - dev_info(&adev->dev, "mapped registers from %pa to %p\n", - &adev->res.start, pl022->virtbase); + pr_info("pl022: mapped registers from 0x%08lx to %p\n", + (unsigned long)adev->res.start, pl022->virtbase); pl022->clk = devm_clk_get(&adev->dev, NULL); if (IS_ERR(pl022->clk)) { @@ -2225,7 +2272,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) /* Register with the SPI framework */ amba_set_drvdata(adev, pl022); - status = devm_spi_register_master(&adev->dev, master); + status = spi_register_master(master); if (status != 0) { dev_err(&adev->dev, "probe - problem registering spi master\n"); @@ -2259,6 +2306,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) amba_release_regions(adev); err_no_ioregion: err_no_gpio: + err_no_pinctrl: spi_master_put(master); return status; } @@ -2285,6 +2333,8 @@ pl022_remove(struct amba_device *adev) clk_unprepare(pl022->clk); amba_release_regions(adev); tasklet_disable(&pl022->pump_transfers); + spi_unregister_master(pl022->master); + amba_set_drvdata(adev, NULL); return 0; } @@ -2296,21 +2346,44 @@ pl022_remove(struct amba_device *adev) */ static void pl022_suspend_resources(struct pl022 *pl022, bool runtime) { + int ret; + struct pinctrl_state *pins_state; + clk_disable(pl022->clk); - if (runtime) - pinctrl_pm_select_idle_state(&pl022->adev->dev); - else - pinctrl_pm_select_sleep_state(&pl022->adev->dev); + pins_state = runtime ? pl022->pins_idle : pl022->pins_sleep; + /* Optionally let pins go into sleep states */ + if (!IS_ERR(pins_state)) { + ret = pinctrl_select_state(pl022->pinctrl, pins_state); + if (ret) + dev_err(&pl022->adev->dev, "could not set %s pins\n", + runtime ? "idle" : "sleep"); + } } static void pl022_resume_resources(struct pl022 *pl022, bool runtime) { + int ret; + + /* Optionaly enable pins to be muxed in and configured */ /* First go to the default state */ - pinctrl_pm_select_default_state(&pl022->adev->dev); - if (!runtime) + if (!IS_ERR(pl022->pins_default)) { + ret = pinctrl_select_state(pl022->pinctrl, pl022->pins_default); + if (ret) + dev_err(&pl022->adev->dev, + "could not set default pins\n"); + } + + if (!runtime) { /* Then let's idle the pins until the next transfer happens */ - pinctrl_pm_select_idle_state(&pl022->adev->dev); + if (!IS_ERR(pl022->pins_idle)) { + ret = pinctrl_select_state(pl022->pinctrl, + pl022->pins_idle); + if (ret) + dev_err(&pl022->adev->dev, + "could not set idle pins\n"); + } + } clk_enable(pl022->clk); } -- 1.7.9.5 -- _______________________________________________ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto