bcm27xx: update patches from RPi foundation
[oweals/openwrt.git] / target / linux / bcm27xx / patches-5.4 / 950-0134-spi-spi-bcm2835-Re-enable-HW-CS.patch
1 From 33b150a792ccde6eded4240dea0e3ec784b07d7c Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.org>
3 Date: Tue, 15 Jan 2019 12:39:50 +0000
4 Subject: [PATCH] spi: spi-bcm2835: Re-enable HW CS
5
6 Signed-off-by: Phil Elwell <phil@raspberrypi.org>
7 ---
8  drivers/spi/spi-bcm2835.c | 53 +++++++++++++++++++++++++++++++++++++--
9  1 file changed, 51 insertions(+), 2 deletions(-)
10
11 --- a/drivers/spi/spi-bcm2835.c
12 +++ b/drivers/spi/spi-bcm2835.c
13 @@ -1169,9 +1169,57 @@ static void bcm2835_spi_handle_err(struc
14         bcm2835_spi_reset_hw(ctlr);
15  }
16  
17 -static int chip_match_name(struct gpio_chip *chip, void *data)
18 +static void bcm2835_spi_set_cs(struct spi_device *spi, bool gpio_level)
19  {
20 -       return !strcmp(chip->label, data);
21 +       /*
22 +        * we can assume that we are "native" as per spi_set_cs
23 +        *   calling us ONLY when cs_gpio is not set
24 +        * we can also assume that we are CS < 3 as per bcm2835_spi_setup
25 +        *   we would not get called because of error handling there.
26 +        * the level passed is the electrical level not enabled/disabled
27 +        *   so it has to get translated back to enable/disable
28 +        *   see spi_set_cs in spi.c for the implementation
29 +        */
30 +
31 +       struct spi_master *master = spi->master;
32 +       struct bcm2835_spi *bs = spi_master_get_devdata(master);
33 +       u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
34 +       bool enable;
35 +
36 +       /* calculate the enable flag from the passed gpio_level */
37 +       enable = (spi->mode & SPI_CS_HIGH) ? gpio_level : !gpio_level;
38 +
39 +       /* set flags for "reverse" polarity in the registers */
40 +       if (spi->mode & SPI_CS_HIGH) {
41 +               /* set the correct CS-bits */
42 +               cs |= BCM2835_SPI_CS_CSPOL;
43 +               cs |= BCM2835_SPI_CS_CSPOL0 << spi->chip_select;
44 +       } else {
45 +               /* clean the CS-bits */
46 +               cs &= ~BCM2835_SPI_CS_CSPOL;
47 +               cs &= ~(BCM2835_SPI_CS_CSPOL0 << spi->chip_select);
48 +       }
49 +
50 +       /* select the correct chip_select depending on disabled/enabled */
51 +       if (enable) {
52 +               /* set cs correctly */
53 +               if (spi->mode & SPI_NO_CS) {
54 +                       /* use the "undefined" chip-select */
55 +                       cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01;
56 +               } else {
57 +                       /* set the chip select */
58 +                       cs &= ~(BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01);
59 +                       cs |= spi->chip_select;
60 +               }
61 +       } else {
62 +               /* disable CSPOL which puts HW-CS into deselected state */
63 +               cs &= ~BCM2835_SPI_CS_CSPOL;
64 +               /* use the "undefined" chip-select as precaution */
65 +               cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01;
66 +       }
67 +
68 +       /* finally set the calculated flags in SPI_CS */
69 +       bcm2835_wr(bs, BCM2835_SPI_CS, cs);
70  }
71  
72  static int bcm2835_spi_setup(struct spi_device *spi)
73 @@ -1289,6 +1337,7 @@ static int bcm2835_spi_probe(struct plat
74         ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
75         ctlr->num_chipselect = BCM2835_SPI_NUM_CS;
76         ctlr->setup = bcm2835_spi_setup;
77 +       ctlr->set_cs = bcm2835_spi_set_cs;
78         ctlr->transfer_one = bcm2835_spi_transfer_one;
79         ctlr->handle_err = bcm2835_spi_handle_err;
80         ctlr->prepare_message = bcm2835_spi_prepare_message;