diff --git a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt index 8bc95e2fc47f..31b5b21598ff 100644 --- a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt +++ b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt @@ -23,6 +23,12 @@ See the clock consumer binding, Obsolete properties: - fsl,spi-num-chipselects : Contains the number of the chipselect +Optional properties: +- fsl,spi-rdy-drctl: Integer, representing the value of DRCTL, the register +controlling the SPI_READY handling. Note that to enable the DRCTL consideration, +the SPI_READY mode-flag needs to be set too. +Valid values are: 0 (disabled), 1 (edge-triggered burst) and 2 (level-triggered burst). + Example: ecspi@70010000 { @@ -35,4 +41,5 @@ ecspi@70010000 { <&gpio3 25 0>; /* GPIO3_25 */ dmas = <&sdma 3 7 1>, <&sdma 4 7 2>; dma-names = "rx", "tx"; + fsl,spi-rdy-drctl = <1>; }; diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 14c8e7ce1913..15201645bdc4 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -1002,7 +1002,8 @@ static int dspi_probe(struct platform_device *pdev) if (IS_ERR(dspi->regmap)) { dev_err(&pdev->dev, "failed to init regmap: %ld\n", PTR_ERR(dspi->regmap)); - return PTR_ERR(dspi->regmap); + ret = PTR_ERR(dspi->regmap); + goto out_master_put; } dspi_init(dspi); diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 0fc3452652ae..8f2e97857e8b 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -814,7 +814,7 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) struct device_node *np = ofdev->dev.of_node; struct spi_master *master; struct resource mem; - int irq, type; + int irq = 0, type; int ret = -ENOMEM; ret = of_mpc8xxx_spi_probe(ofdev); @@ -847,6 +847,7 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) return 0; err: + irq_dispose_mapping(irq); if (type == TYPE_FSL) of_fsl_spi_free_chipselects(dev); return ret; diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 9a7c62f471dc..b402530a7a9a 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -95,6 +95,7 @@ struct spi_imx_data { unsigned int spi_bus_clk; unsigned int bytes_per_word; + unsigned int spi_drctl; unsigned int count; void (*tx)(struct spi_imx_data *); @@ -246,6 +247,7 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, #define MX51_ECSPI_CTRL_XCH (1 << 2) #define MX51_ECSPI_CTRL_SMC (1 << 3) #define MX51_ECSPI_CTRL_MODE_MASK (0xf << 4) +#define MX51_ECSPI_CTRL_DRCTL(drctl) ((drctl) << 16) #define MX51_ECSPI_CTRL_POSTDIV_OFFSET 8 #define MX51_ECSPI_CTRL_PREDIV_OFFSET 12 #define MX51_ECSPI_CTRL_CS(cs) ((cs) << 18) @@ -355,6 +357,12 @@ static int mx51_ecspi_config(struct spi_device *spi, */ ctrl |= MX51_ECSPI_CTRL_MODE_MASK; + /* + * Enable SPI_RDY handling (falling edge/level triggered). + */ + if (spi->mode & SPI_READY) + ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl); + /* set clock speed */ ctrl |= mx51_ecspi_clkdiv(spi_imx, config->speed_hz, &clk); spi_imx->spi_bus_clk = clk; @@ -1173,7 +1181,7 @@ static int spi_imx_probe(struct platform_device *pdev) struct spi_master *master; struct spi_imx_data *spi_imx; struct resource *res; - int i, ret, irq; + int i, ret, irq, spi_drctl; if (!np && !mxc_platform_info) { dev_err(&pdev->dev, "can't get the platform data\n"); @@ -1181,6 +1189,12 @@ static int spi_imx_probe(struct platform_device *pdev) } master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data)); + ret = of_property_read_u32(np, "fsl,spi-rdy-drctl", &spi_drctl); + if ((ret < 0) || (spi_drctl >= 0x3)) { + /* '11' is reserved */ + spi_drctl = 0; + } + if (!master) return -ENOMEM; @@ -1216,7 +1230,9 @@ static int spi_imx_probe(struct platform_device *pdev) spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message; spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx)) - spi_imx->bitbang.master->mode_bits |= SPI_LOOP; + spi_imx->bitbang.master->mode_bits |= SPI_LOOP | SPI_READY; + + spi_imx->spi_drctl = spi_drctl; init_completion(&spi_imx->xfer_done); diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c index 633c30b4d5a6..d5976615d924 100644 --- a/drivers/spi/spi-lantiq-ssc.c +++ b/drivers/spi/spi-lantiq-ssc.c @@ -977,7 +977,6 @@ static struct platform_driver lantiq_ssc_driver = { .remove = lantiq_ssc_remove, .driver = { .name = "spi-lantiq-ssc", - .owner = THIS_MODULE, .of_match_table = lantiq_ssc_match, }, }; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index b4a8bb7759b2..2c36c0ac708a 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -600,13 +601,28 @@ struct spi_device *spi_new_device(struct spi_master *master, proxy->controller_data = chip->controller_data; proxy->controller_state = NULL; - status = spi_add_device(proxy); - if (status < 0) { - spi_dev_put(proxy); - return NULL; + if (chip->properties) { + status = device_add_properties(&proxy->dev, chip->properties); + if (status) { + dev_err(&master->dev, + "failed to add properties to '%s': %d\n", + chip->modalias, status); + goto err_dev_put; + } } + status = spi_add_device(proxy); + if (status < 0) + goto err_remove_props; + return proxy; + +err_remove_props: + if (chip->properties) + device_remove_properties(&proxy->dev); +err_dev_put: + spi_dev_put(proxy); + return NULL; } EXPORT_SYMBOL_GPL(spi_new_device); @@ -664,6 +680,7 @@ static void spi_match_master_to_boardinfo(struct spi_master *master, * * The board info passed can safely be __initdata ... but be careful of * any embedded pointers (platform_data, etc), they're copied as-is. + * Device properties are deep-copied though. * * Return: zero on success, else a negative error code. */ @@ -673,7 +690,7 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) int i; if (!n) - return -EINVAL; + return 0; bi = kcalloc(n, sizeof(*bi), GFP_KERNEL); if (!bi) @@ -683,6 +700,13 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) struct spi_master *master; memcpy(&bi->board_info, info, sizeof(*info)); + if (info->properties) { + bi->board_info.properties = + property_entries_dup(info->properties); + if (IS_ERR(bi->board_info.properties)) + return PTR_ERR(bi->board_info.properties); + } + mutex_lock(&board_lock); list_add_tail(&bi->list, &board_list); list_for_each_entry(master, &spi_master_list, list) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 3b0070695375..805878d61a8f 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -23,6 +23,7 @@ #include struct dma_chan; +struct property_entry; struct spi_master; struct spi_transfer; struct spi_flash_read_message; @@ -1209,6 +1210,7 @@ int spi_flash_read(struct spi_device *spi, * @modalias: Initializes spi_device.modalias; identifies the driver. * @platform_data: Initializes spi_device.platform_data; the particular * data stored there is driver-specific. + * @properties: Additional device properties for the device. * @controller_data: Initializes spi_device.controller_data; some * controllers need hints about hardware setup, e.g. for DMA. * @irq: Initializes spi_device.irq; depends on how the board is wired. @@ -1241,10 +1243,12 @@ struct spi_board_info { * * platform_data goes to spi_device.dev.platform_data, * controller_data goes to spi_device.controller_data, + * device properties are copied and attached to spi_device, * irq is copied too */ char modalias[SPI_NAME_SIZE]; const void *platform_data; + const struct property_entry *properties; void *controller_data; int irq;