diff options
Diffstat (limited to 'drivers/spi/spi-pl022.c')
-rw-r--r-- | drivers/spi/spi-pl022.c | 108 |
1 files changed, 22 insertions, 86 deletions
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index fd74ddfbb686..0c9e3f270f05 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -31,8 +31,7 @@ #include <linux/dma-mapping.h> #include <linux/scatterlist.h> #include <linux/pm_runtime.h> -#include <linux/gpio.h> -#include <linux/of_gpio.h> +#include <linux/of.h> #include <linux/pinctrl/consumer.h> /* @@ -362,8 +361,8 @@ struct vendor_data { * @sgt_tx: scattertable for the TX transfer * @dummypage: a dummy page used for driving data on the bus with DMA * @dma_running: indicates whether DMA is in operation - * @cur_cs: current chip select (gpio) - * @chipselects: list of chipselects (gpios) + * @cur_cs: current chip select index + * @cur_gpiod: current chip select GPIO descriptor */ struct pl022 { struct amba_device *adev; @@ -398,7 +397,7 @@ struct pl022 { bool dma_running; #endif int cur_cs; - int *chipselects; + struct gpio_desc *cur_gpiod; }; /** @@ -412,7 +411,6 @@ struct pl022 { * @enable_dma: Whether to enable DMA or not * @read: function ptr to be used to read when doing xfer for this chip * @write: function ptr to be used to write when doing xfer for this chip - * @cs_control: chip select callback provided by chip * @xfer_type: polling/interrupt/DMA * * Runtime state of the SSP controller, maintained per chip, @@ -427,23 +425,10 @@ struct chip_data { bool enable_dma; enum ssp_reading read; enum ssp_writing write; - void (*cs_control) (u32 command); int xfer_type; }; /** - * null_cs_control - Dummy chip select function - * @command: select/delect the chip - * - * If no chip select function is provided by client this is used as dummy - * chip select - */ -static void null_cs_control(u32 command) -{ - pr_debug("pl022: dummy chip select control, CS=0x%x\n", command); -} - -/** * internal_cs_control - Control chip select signals via SSP_CSR. * @pl022: SSP driver private data structure * @command: select/delect the chip @@ -468,10 +453,16 @@ static void pl022_cs_control(struct pl022 *pl022, u32 command) { if (pl022->vendor->internal_cs_ctrl) internal_cs_control(pl022, command); - else if (gpio_is_valid(pl022->cur_cs)) - gpio_set_value(pl022->cur_cs, command); - else - pl022->cur_chip->cs_control(command); + else if (pl022->cur_gpiod) + /* + * This needs to be inverted since with GPIOLIB in + * control, the inversion will be handled by + * GPIOLIB's active low handling. The "command" + * passed into this function will be SSP_CHIP_SELECT + * which is enum:ed to 0, so we need the inverse + * (1) to activate chip select. + */ + gpiod_set_value(pl022->cur_gpiod, !command); } /** @@ -1195,7 +1186,7 @@ err_no_txchan: err_no_rxchan: return err; } - + static void terminate_dma(struct pl022 *pl022) { struct dma_chan *rxchan = pl022->dma_rx_channel; @@ -1596,7 +1587,9 @@ static int pl022_transfer_one_message(struct spi_master *master, /* Setup the SPI using the per chip configuration */ pl022->cur_chip = spi_get_ctldata(msg->spi); - pl022->cur_cs = pl022->chipselects[msg->spi->chip_select]; + pl022->cur_cs = msg->spi->chip_select; + /* This is always available but may be set to -ENOENT */ + pl022->cur_gpiod = msg->spi->cs_gpiod; restore_state(pl022); flush(pl022); @@ -1820,16 +1813,15 @@ static int calculate_effective_freq(struct pl022 *pl022, int freq, struct * supplies it. */ static const struct pl022_config_chip pl022_default_chip_info = { - .com_mode = POLLING_TRANSFER, + .com_mode = INTERRUPT_TRANSFER, .iface = SSP_INTERFACE_MOTOROLA_SPI, - .hierarchy = SSP_SLAVE, + .hierarchy = SSP_MASTER, .slave_tx_disable = DO_NOT_DRIVE_TX, .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM, .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC, .ctrl_len = SSP_BITS_8, .wait_state = SSP_MWIRE_WAIT_ZERO, .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, - .cs_control = null_cs_control, }; /** @@ -1940,13 +1932,6 @@ static int pl022_setup(struct spi_device *spi) /* Now set controller state based on controller data */ chip->xfer_type = chip_info->com_mode; - if (!chip_info->cs_control) { - chip->cs_control = null_cs_control; - if (!gpio_is_valid(pl022->chipselects[spi->chip_select])) - dev_warn(&spi->dev, - "invalid chip select\n"); - } else - chip->cs_control = chip_info->cs_control; /* Check bits per word with vendor specific range */ if ((bits <= 3) || (bits > pl022->vendor->max_bpw)) { @@ -2094,7 +2079,6 @@ pl022_platform_data_dt_get(struct device *dev) { struct device_node *np = dev->of_node; struct pl022_ssp_controller *pd; - u32 tmp = 0; if (!np) { dev_err(dev, "no dt node defined\n"); @@ -2107,8 +2091,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", &pd->autosuspend_delay); pd->rt = of_property_read_bool(np, "pl022,rt"); @@ -2123,8 +2105,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) dev_get_platdata(&adev->dev); struct spi_master *master; struct pl022 *pl022 = NULL; /*Data for this driver */ - struct device_node *np = adev->dev.of_node; - int status = 0, i, num_cs; + int status = 0; dev_info(&adev->dev, "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid); @@ -2136,13 +2117,6 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) return -ENODEV; } - if (platform_info->num_chipselect) { - num_cs = platform_info->num_chipselect; - } else { - dev_err(dev, "probe: no chip select defined\n"); - return -ENODEV; - } - /* Allocate master with space for data */ master = spi_alloc_master(dev, sizeof(struct pl022)); if (master == NULL) { @@ -2155,19 +2129,12 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) pl022->master_info = platform_info; pl022->adev = adev; pl022->vendor = id->data; - pl022->chipselects = devm_kcalloc(dev, num_cs, sizeof(int), - GFP_KERNEL); - if (!pl022->chipselects) { - status = -ENOMEM; - goto err_no_mem; - } /* * Bus Number Which has been Assigned to this SSP controller * on this board */ master->bus_num = platform_info->bus_id; - master->num_chipselect = num_cs; master->cleanup = pl022_cleanup; master->setup = pl022_setup; master->auto_runtime_pm = true; @@ -2175,36 +2142,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) master->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware; master->rt = platform_info->rt; master->dev.of_node = dev->of_node; - - if (platform_info->num_chipselect && platform_info->chipselects) { - for (i = 0; i < num_cs; i++) - pl022->chipselects[i] = platform_info->chipselects[i]; - } else if (pl022->vendor->internal_cs_ctrl) { - for (i = 0; i < num_cs; i++) - pl022->chipselects[i] = i; - } else if (IS_ENABLED(CONFIG_OF)) { - for (i = 0; i < num_cs; i++) { - int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); - - if (cs_gpio == -EPROBE_DEFER) { - status = -EPROBE_DEFER; - goto err_no_gpio; - } - - pl022->chipselects[i] = cs_gpio; - - if (gpio_is_valid(cs_gpio)) { - if (devm_gpio_request(dev, cs_gpio, "ssp-pl022")) - dev_err(&adev->dev, - "could not request %d gpio\n", - cs_gpio); - else if (gpio_direction_output(cs_gpio, 1)) - dev_err(&adev->dev, - "could not set gpio %d as output\n", - cs_gpio); - } - } - } + master->use_gpio_descriptors = true; /* * Supports mode 0-3, loopback, and active low CS. Transfers are @@ -2308,8 +2246,6 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) err_no_ioremap: amba_release_regions(adev); err_no_ioregion: - err_no_gpio: - err_no_mem: spi_master_put(master); return status; } |