Loading drivers/spi/spi-atmel.c +44 −12 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <linux/io.h> #include <linux/gpio.h> #include <linux/of_gpio.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> Loading Loading @@ -295,6 +296,7 @@ struct atmel_spi { int irq; struct clk *clk; struct platform_device *pdev; unsigned long spi_clk; struct spi_transfer *current_transfer; int current_remaining_bytes; Loading Loading @@ -864,7 +866,7 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as, unsigned long bus_hz; /* v1 chips start out at half the peripheral bus speed. */ bus_hz = clk_get_rate(as->clk); bus_hz = as->spi_clk; if (!atmel_spi_is_v2(as)) bus_hz /= 2; Loading Loading @@ -1204,7 +1206,6 @@ static int atmel_spi_setup(struct spi_device *spi) u32 csr; unsigned int bits = spi->bits_per_word; unsigned int npcs_pin; int ret; as = spi_master_get_devdata(spi->master); Loading Loading @@ -1247,16 +1248,9 @@ static int atmel_spi_setup(struct spi_device *spi) if (!asd) return -ENOMEM; if (as->use_cs_gpios) { ret = gpio_request(npcs_pin, dev_name(&spi->dev)); if (ret) { kfree(asd); return ret; } if (as->use_cs_gpios) gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH)); } asd->npcs_pin = npcs_pin; spi->controller_state = asd; Loading Loading @@ -1471,13 +1465,11 @@ static int atmel_spi_transfer_one_message(struct spi_master *master, static void atmel_spi_cleanup(struct spi_device *spi) { struct atmel_spi_device *asd = spi->controller_state; unsigned gpio = (unsigned long) spi->controller_data; if (!asd) return; spi->controller_state = NULL; gpio_free(gpio); kfree(asd); } Loading @@ -1499,6 +1491,39 @@ static void atmel_get_caps(struct atmel_spi *as) } /*-------------------------------------------------------------------------*/ static int atmel_spi_gpio_cs(struct platform_device *pdev) { struct spi_master *master = platform_get_drvdata(pdev); struct atmel_spi *as = spi_master_get_devdata(master); struct device_node *np = master->dev.of_node; int i; int ret = 0; int nb = 0; if (!as->use_cs_gpios) return 0; if (!np) return 0; nb = of_gpio_named_count(np, "cs-gpios"); for (i = 0; i < nb; i++) { int cs_gpio = of_get_named_gpio(pdev->dev.of_node, "cs-gpios", i); if (cs_gpio == -EPROBE_DEFER) return cs_gpio; if (gpio_is_valid(cs_gpio)) { ret = devm_gpio_request(&pdev->dev, cs_gpio, dev_name(&pdev->dev)); if (ret) return ret; } } return 0; } static int atmel_spi_probe(struct platform_device *pdev) { Loading Loading @@ -1577,6 +1602,10 @@ static int atmel_spi_probe(struct platform_device *pdev) master->num_chipselect = 4; } ret = atmel_spi_gpio_cs(pdev); if (ret) goto out_unmap_regs; as->use_dma = false; as->use_pdc = false; if (as->caps.has_dma_support) { Loading Loading @@ -1606,6 +1635,9 @@ static int atmel_spi_probe(struct platform_device *pdev) ret = clk_prepare_enable(clk); if (ret) goto out_free_irq; as->spi_clk = clk_get_rate(clk); spi_writel(as, CR, SPI_BIT(SWRST)); spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ if (as->caps.has_wdrbt) { Loading drivers/spi/spi-orion.c +54 −29 Original line number Diff line number Diff line Loading @@ -138,37 +138,62 @@ static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed) tclk_hz = clk_get_rate(orion_spi->clk); if (devdata->typ == ARMADA_SPI) { unsigned int clk, spr, sppr, sppr2, err; unsigned int best_spr, best_sppr, best_err; /* * Given the core_clk (tclk_hz) and the target rate (speed) we * determine the best values for SPR (in [0 .. 15]) and SPPR (in * [0..7]) such that * * core_clk / (SPR * 2 ** SPPR) * * is as big as possible but not bigger than speed. */ best_err = speed; best_spr = 0; best_sppr = 0; /* best integer divider: */ unsigned divider = DIV_ROUND_UP(tclk_hz, speed); unsigned spr, sppr; /* Iterate over the valid range looking for best fit */ for (sppr = 0; sppr < 8; sppr++) { sppr2 = 0x1 << sppr; if (divider < 16) { /* This is the easy case, divider is less than 16 */ spr = divider; sppr = 0; spr = tclk_hz / sppr2; spr = DIV_ROUND_UP(spr, speed); if ((spr == 0) || (spr > 15)) continue; } else { unsigned two_pow_sppr; /* * Find the highest bit set in divider. This and the * three next bits define SPR (apart from rounding). * SPPR is then the number of zero bits that must be * appended: */ sppr = fls(divider) - 4; clk = tclk_hz / (spr * sppr2); err = speed - clk; /* * As SPR only has 4 bits, we have to round divider up * to the next multiple of 2 ** sppr. */ two_pow_sppr = 1 << sppr; divider = (divider + two_pow_sppr - 1) & -two_pow_sppr; if (err < best_err) { best_spr = spr; best_sppr = sppr; best_err = err; } } /* * recalculate sppr as rounding up divider might have * increased it enough to change the position of the * highest set bit. In this case the bit that now * doesn't make it into SPR is 0, so there is no need to * round again. */ sppr = fls(divider) - 4; spr = divider >> sppr; if ((best_sppr == 0) && (best_spr == 0)) /* * Now do range checking. SPR is constructed to have a * width of 4 bits, so this is fine for sure. So we * still need to check for sppr to fit into 3 bits: */ if (sppr > 7) return -EINVAL; } prescale = ((best_sppr & 0x6) << 5) | ((best_sppr & 0x1) << 4) | best_spr; prescale = ((sppr & 0x6) << 5) | ((sppr & 0x1) << 4) | spr; } else { /* * the supported rates are: 4,6,8...30 Loading tools/spi/spidev_test.c +1 −1 Original line number Diff line number Diff line Loading @@ -315,7 +315,7 @@ static void transfer_file(int fd, char *filename) pabort("can't stat input file"); tx_fd = open(filename, O_RDONLY); if (fd < 0) if (tx_fd < 0) pabort("can't open input file"); tx = malloc(sb.st_size); Loading Loading
drivers/spi/spi-atmel.c +44 −12 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <linux/io.h> #include <linux/gpio.h> #include <linux/of_gpio.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> Loading Loading @@ -295,6 +296,7 @@ struct atmel_spi { int irq; struct clk *clk; struct platform_device *pdev; unsigned long spi_clk; struct spi_transfer *current_transfer; int current_remaining_bytes; Loading Loading @@ -864,7 +866,7 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as, unsigned long bus_hz; /* v1 chips start out at half the peripheral bus speed. */ bus_hz = clk_get_rate(as->clk); bus_hz = as->spi_clk; if (!atmel_spi_is_v2(as)) bus_hz /= 2; Loading Loading @@ -1204,7 +1206,6 @@ static int atmel_spi_setup(struct spi_device *spi) u32 csr; unsigned int bits = spi->bits_per_word; unsigned int npcs_pin; int ret; as = spi_master_get_devdata(spi->master); Loading Loading @@ -1247,16 +1248,9 @@ static int atmel_spi_setup(struct spi_device *spi) if (!asd) return -ENOMEM; if (as->use_cs_gpios) { ret = gpio_request(npcs_pin, dev_name(&spi->dev)); if (ret) { kfree(asd); return ret; } if (as->use_cs_gpios) gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH)); } asd->npcs_pin = npcs_pin; spi->controller_state = asd; Loading Loading @@ -1471,13 +1465,11 @@ static int atmel_spi_transfer_one_message(struct spi_master *master, static void atmel_spi_cleanup(struct spi_device *spi) { struct atmel_spi_device *asd = spi->controller_state; unsigned gpio = (unsigned long) spi->controller_data; if (!asd) return; spi->controller_state = NULL; gpio_free(gpio); kfree(asd); } Loading @@ -1499,6 +1491,39 @@ static void atmel_get_caps(struct atmel_spi *as) } /*-------------------------------------------------------------------------*/ static int atmel_spi_gpio_cs(struct platform_device *pdev) { struct spi_master *master = platform_get_drvdata(pdev); struct atmel_spi *as = spi_master_get_devdata(master); struct device_node *np = master->dev.of_node; int i; int ret = 0; int nb = 0; if (!as->use_cs_gpios) return 0; if (!np) return 0; nb = of_gpio_named_count(np, "cs-gpios"); for (i = 0; i < nb; i++) { int cs_gpio = of_get_named_gpio(pdev->dev.of_node, "cs-gpios", i); if (cs_gpio == -EPROBE_DEFER) return cs_gpio; if (gpio_is_valid(cs_gpio)) { ret = devm_gpio_request(&pdev->dev, cs_gpio, dev_name(&pdev->dev)); if (ret) return ret; } } return 0; } static int atmel_spi_probe(struct platform_device *pdev) { Loading Loading @@ -1577,6 +1602,10 @@ static int atmel_spi_probe(struct platform_device *pdev) master->num_chipselect = 4; } ret = atmel_spi_gpio_cs(pdev); if (ret) goto out_unmap_regs; as->use_dma = false; as->use_pdc = false; if (as->caps.has_dma_support) { Loading Loading @@ -1606,6 +1635,9 @@ static int atmel_spi_probe(struct platform_device *pdev) ret = clk_prepare_enable(clk); if (ret) goto out_free_irq; as->spi_clk = clk_get_rate(clk); spi_writel(as, CR, SPI_BIT(SWRST)); spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ if (as->caps.has_wdrbt) { Loading
drivers/spi/spi-orion.c +54 −29 Original line number Diff line number Diff line Loading @@ -138,37 +138,62 @@ static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed) tclk_hz = clk_get_rate(orion_spi->clk); if (devdata->typ == ARMADA_SPI) { unsigned int clk, spr, sppr, sppr2, err; unsigned int best_spr, best_sppr, best_err; /* * Given the core_clk (tclk_hz) and the target rate (speed) we * determine the best values for SPR (in [0 .. 15]) and SPPR (in * [0..7]) such that * * core_clk / (SPR * 2 ** SPPR) * * is as big as possible but not bigger than speed. */ best_err = speed; best_spr = 0; best_sppr = 0; /* best integer divider: */ unsigned divider = DIV_ROUND_UP(tclk_hz, speed); unsigned spr, sppr; /* Iterate over the valid range looking for best fit */ for (sppr = 0; sppr < 8; sppr++) { sppr2 = 0x1 << sppr; if (divider < 16) { /* This is the easy case, divider is less than 16 */ spr = divider; sppr = 0; spr = tclk_hz / sppr2; spr = DIV_ROUND_UP(spr, speed); if ((spr == 0) || (spr > 15)) continue; } else { unsigned two_pow_sppr; /* * Find the highest bit set in divider. This and the * three next bits define SPR (apart from rounding). * SPPR is then the number of zero bits that must be * appended: */ sppr = fls(divider) - 4; clk = tclk_hz / (spr * sppr2); err = speed - clk; /* * As SPR only has 4 bits, we have to round divider up * to the next multiple of 2 ** sppr. */ two_pow_sppr = 1 << sppr; divider = (divider + two_pow_sppr - 1) & -two_pow_sppr; if (err < best_err) { best_spr = spr; best_sppr = sppr; best_err = err; } } /* * recalculate sppr as rounding up divider might have * increased it enough to change the position of the * highest set bit. In this case the bit that now * doesn't make it into SPR is 0, so there is no need to * round again. */ sppr = fls(divider) - 4; spr = divider >> sppr; if ((best_sppr == 0) && (best_spr == 0)) /* * Now do range checking. SPR is constructed to have a * width of 4 bits, so this is fine for sure. So we * still need to check for sppr to fit into 3 bits: */ if (sppr > 7) return -EINVAL; } prescale = ((best_sppr & 0x6) << 5) | ((best_sppr & 0x1) << 4) | best_spr; prescale = ((sppr & 0x6) << 5) | ((sppr & 0x1) << 4) | spr; } else { /* * the supported rates are: 4,6,8...30 Loading
tools/spi/spidev_test.c +1 −1 Original line number Diff line number Diff line Loading @@ -315,7 +315,7 @@ static void transfer_file(int fd, char *filename) pabort("can't stat input file"); tx_fd = open(filename, O_RDONLY); if (fd < 0) if (tx_fd < 0) pabort("can't open input file"); tx = malloc(sb.st_size); Loading