Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spi: oc-tiny: Use GPIO descriptors

Switch the OC Tiny driver over to handling CS GPIOs using
GPIO descriptors in the core.

This driver is entirely relying on GPIOs to be used for
chipselect, so let the core pick these out using either
device tree or machine descriptors.

There are no in-tree users of this driver so no board files
need to be patched, out-of-tree boardfiles can use machine
descriptor tables, c.f. commit 1dfbf334f123.

Cc: Thomas Chou <thomas@wytron.com.tw>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20191205092411.64341-1-linus.walleij@linaro.org
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Linus Walleij and committed by
Mark Brown
f03ee204 28d1dddc

+1 -53
+1 -49
drivers/spi/spi-oc-tiny.c
··· 20 20 #include <linux/spi/spi_bitbang.h> 21 21 #include <linux/spi/spi_oc_tiny.h> 22 22 #include <linux/io.h> 23 - #include <linux/gpio.h> 24 23 #include <linux/of.h> 25 24 26 25 #define DRV_NAME "spi_oc_tiny" ··· 49 50 unsigned int txc, rxc; 50 51 const u8 *txp; 51 52 u8 *rxp; 52 - int gpio_cs_count; 53 - int *gpio_cs; 54 53 }; 55 54 56 55 static inline struct tiny_spi *tiny_spi_to_hw(struct spi_device *sdev) ··· 61 64 struct tiny_spi *hw = tiny_spi_to_hw(spi); 62 65 63 66 return min(DIV_ROUND_UP(hw->freq, hz * 2), (1U << hw->baudwidth)) - 1; 64 - } 65 - 66 - static void tiny_spi_chipselect(struct spi_device *spi, int is_active) 67 - { 68 - struct tiny_spi *hw = tiny_spi_to_hw(spi); 69 - 70 - if (hw->gpio_cs_count > 0) { 71 - gpio_set_value(hw->gpio_cs[spi->chip_select], 72 - (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); 73 - } 74 67 } 75 68 76 69 static int tiny_spi_setup_transfer(struct spi_device *spi, ··· 190 203 { 191 204 struct tiny_spi *hw = platform_get_drvdata(pdev); 192 205 struct device_node *np = pdev->dev.of_node; 193 - unsigned int i; 194 206 u32 val; 195 207 196 208 if (!np) 197 209 return 0; 198 - hw->gpio_cs_count = of_gpio_count(np); 199 - if (hw->gpio_cs_count > 0) { 200 - hw->gpio_cs = devm_kcalloc(&pdev->dev, 201 - hw->gpio_cs_count, sizeof(unsigned int), 202 - GFP_KERNEL); 203 - if (!hw->gpio_cs) 204 - return -ENOMEM; 205 - } 206 - for (i = 0; i < hw->gpio_cs_count; i++) { 207 - hw->gpio_cs[i] = of_get_gpio_flags(np, i, NULL); 208 - if (hw->gpio_cs[i] < 0) 209 - return -ENODEV; 210 - } 211 210 hw->bitbang.master->dev.of_node = pdev->dev.of_node; 212 211 if (!of_property_read_u32(np, "clock-frequency", &val)) 213 212 hw->freq = val; ··· 213 240 struct tiny_spi_platform_data *platp = dev_get_platdata(&pdev->dev); 214 241 struct tiny_spi *hw; 215 242 struct spi_master *master; 216 - unsigned int i; 217 243 int err = -ENODEV; 218 244 219 245 master = spi_alloc_master(&pdev->dev, sizeof(struct tiny_spi)); ··· 221 249 222 250 /* setup the master state. */ 223 251 master->bus_num = pdev->id; 224 - master->num_chipselect = 255; 225 252 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; 226 253 master->setup = tiny_spi_setup; 254 + master->use_gpio_descriptors = true; 227 255 228 256 hw = spi_master_get_devdata(master); 229 257 platform_set_drvdata(pdev, hw); ··· 231 259 /* setup the state for the bitbang driver */ 232 260 hw->bitbang.master = master; 233 261 hw->bitbang.setup_transfer = tiny_spi_setup_transfer; 234 - hw->bitbang.chipselect = tiny_spi_chipselect; 235 262 hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs; 236 263 237 264 /* find and map our resources */ ··· 250 279 } 251 280 /* find platform data */ 252 281 if (platp) { 253 - hw->gpio_cs_count = platp->gpio_cs_count; 254 - hw->gpio_cs = platp->gpio_cs; 255 - if (platp->gpio_cs_count && !platp->gpio_cs) { 256 - err = -EBUSY; 257 - goto exit; 258 - } 259 282 hw->freq = platp->freq; 260 283 hw->baudwidth = platp->baudwidth; 261 284 } else { ··· 257 292 if (err) 258 293 goto exit; 259 294 } 260 - for (i = 0; i < hw->gpio_cs_count; i++) { 261 - err = gpio_request(hw->gpio_cs[i], dev_name(&pdev->dev)); 262 - if (err) 263 - goto exit_gpio; 264 - gpio_direction_output(hw->gpio_cs[i], 1); 265 - } 266 - hw->bitbang.master->num_chipselect = max(1, hw->gpio_cs_count); 267 295 268 296 /* register our spi controller */ 269 297 err = spi_bitbang_start(&hw->bitbang); ··· 266 308 267 309 return 0; 268 310 269 - exit_gpio: 270 - while (i-- > 0) 271 - gpio_free(hw->gpio_cs[i]); 272 311 exit: 273 312 spi_master_put(master); 274 313 return err; ··· 275 320 { 276 321 struct tiny_spi *hw = platform_get_drvdata(pdev); 277 322 struct spi_master *master = hw->bitbang.master; 278 - unsigned int i; 279 323 280 324 spi_bitbang_stop(&hw->bitbang); 281 - for (i = 0; i < hw->gpio_cs_count; i++) 282 - gpio_free(hw->gpio_cs[i]); 283 325 spi_master_put(master); 284 326 return 0; 285 327 }
-4
include/linux/spi/spi_oc_tiny.h
··· 6 6 * struct tiny_spi_platform_data - platform data of the OpenCores tiny SPI 7 7 * @freq: input clock freq to the core. 8 8 * @baudwidth: baud rate divider width of the core. 9 - * @gpio_cs_count: number of gpio pins used for chipselect. 10 - * @gpio_cs: array of gpio pins used for chipselect. 11 9 * 12 10 * freq and baudwidth are used only if the divider is programmable. 13 11 */ 14 12 struct tiny_spi_platform_data { 15 13 unsigned int freq; 16 14 unsigned int baudwidth; 17 - unsigned int gpio_cs_count; 18 - int *gpio_cs; 19 15 }; 20 16 21 17 #endif /* _LINUX_SPI_SPI_OC_TINY_H */