diff options
Diffstat (limited to 'drivers/spi/spi-orion.c')
| -rw-r--r-- | drivers/spi/spi-orion.c | 70 | 
1 files changed, 65 insertions, 5 deletions
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 861664776672..8cad107a5b3f 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -61,6 +61,12 @@ enum orion_spi_type {  struct orion_spi_dev {  	enum orion_spi_type	typ; +	/* +	 * min_divisor and max_hz should be exclusive, the only we can +	 * have both is for managing the armada-370-spi case with old +	 * device tree +	 */ +	unsigned long		max_hz;  	unsigned int		min_divisor;  	unsigned int		max_divisor;  	u32			prescale_mask; @@ -385,16 +391,54 @@ static const struct orion_spi_dev orion_spi_dev_data = {  	.prescale_mask = ORION_SPI_CLK_PRESCALE_MASK,  }; -static const struct orion_spi_dev armada_spi_dev_data = { +static const struct orion_spi_dev armada_370_spi_dev_data = {  	.typ = ARMADA_SPI, -	.min_divisor = 1, +	.min_divisor = 4, +	.max_divisor = 1920, +	.max_hz = 50000000, +	.prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK, +}; + +static const struct orion_spi_dev armada_xp_spi_dev_data = { +	.typ = ARMADA_SPI, +	.max_hz = 50000000, +	.max_divisor = 1920, +	.prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK, +}; + +static const struct orion_spi_dev armada_375_spi_dev_data = { +	.typ = ARMADA_SPI, +	.min_divisor = 15,  	.max_divisor = 1920,  	.prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK,  };  static const struct of_device_id orion_spi_of_match_table[] = { -	{ .compatible = "marvell,orion-spi", .data = &orion_spi_dev_data, }, -	{ .compatible = "marvell,armada-370-spi", .data = &armada_spi_dev_data, }, +	{ +		.compatible = "marvell,orion-spi", +		.data = &orion_spi_dev_data, +	}, +	{ +		.compatible = "marvell,armada-370-spi", +		.data = &armada_370_spi_dev_data, +	}, +	{ +		.compatible = "marvell,armada-375-spi", +		.data = &armada_375_spi_dev_data, +	}, +	{ +		.compatible = "marvell,armada-380-spi", +		.data = &armada_xp_spi_dev_data, +	}, +	{ +		.compatible = "marvell,armada-390-spi", +		.data = &armada_xp_spi_dev_data, +	}, +	{ +		.compatible = "marvell,armada-xp-spi", +		.data = &armada_xp_spi_dev_data, +	}, +  	{}  };  MODULE_DEVICE_TABLE(of, orion_spi_of_match_table); @@ -454,7 +498,23 @@ static int orion_spi_probe(struct platform_device *pdev)  		goto out;  	tclk_hz = clk_get_rate(spi->clk); -	master->max_speed_hz = DIV_ROUND_UP(tclk_hz, devdata->min_divisor); + +	/* +	 * With old device tree, armada-370-spi could be used with +	 * Armada XP, however for this SoC the maximum frequency is +	 * 50MHz instead of tclk/4. On Armada 370, tclk cannot be +	 * higher than 200MHz. So, in order to be able to handle both +	 * SoCs, we can take the minimum of 50MHz and tclk/4. +	 */ +	if (of_device_is_compatible(pdev->dev.of_node, +					"marvell,armada-370-spi")) +		master->max_speed_hz = min(devdata->max_hz, +				DIV_ROUND_UP(tclk_hz, devdata->min_divisor)); +	else if (devdata->min_divisor) +		master->max_speed_hz = +			DIV_ROUND_UP(tclk_hz, devdata->min_divisor); +	else +		master->max_speed_hz = devdata->max_hz;  	master->min_speed_hz = DIV_ROUND_UP(tclk_hz, devdata->max_divisor);  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);  |