diff options
30 files changed, 578 insertions, 417 deletions
@@ -18,6 +18,7 @@ Aleksey Gorelov <aleksey_gorelov@phoenix.com> Aleksandar Markovic <aleksandar.markovic@mips.com> <aleksandar.markovic@imgtec.com> Al Viro <viro@ftp.linux.org.uk> Al Viro <viro@zenIV.linux.org.uk> +Andi Shyti <andi@etezian.org> <andi.shyti@samsung.com> Andreas Herrmann <aherrman@de.ibm.com> Andrey Ryabinin <ryabinin.a.a@gmail.com> <a.ryabinin@samsung.com> Andrew Morton <akpm@linux-foundation.org> diff --git a/Documentation/devicetree/bindings/spi/sh-msiof.txt b/Documentation/devicetree/bindings/spi/sh-msiof.txt index 80710f0f0448..39806329c193 100644 --- a/Documentation/devicetree/bindings/spi/sh-msiof.txt +++ b/Documentation/devicetree/bindings/spi/sh-msiof.txt @@ -10,6 +10,7 @@ Required properties: "renesas,msiof-r8a7794" (R-Car E2) "renesas,msiof-r8a7795" (R-Car H3) "renesas,msiof-r8a7796" (R-Car M3-W) + "renesas,msiof-r8a77965" (R-Car M3-N) "renesas,msiof-sh73a0" (SH-Mobile AG5) "renesas,sh-mobile-msiof" (generic SH-Mobile compatibile device) "renesas,rcar-gen2-msiof" (generic R-Car Gen2 and RZ/G1 compatible device) diff --git a/Documentation/devicetree/bindings/spi/spi-gpio.txt b/Documentation/devicetree/bindings/spi/spi-gpio.txt index a95603bcf6ff..52db562f17a4 100644 --- a/Documentation/devicetree/bindings/spi/spi-gpio.txt +++ b/Documentation/devicetree/bindings/spi/spi-gpio.txt @@ -1,18 +1,30 @@ SPI-GPIO devicetree bindings +This represents a group of 3-n GPIO lines used for bit-banged SPI on dedicated +GPIO lines. + Required properties: - compatible: should be set to "spi-gpio" - #address-cells: should be set to <0x1> - ranges - - gpio-sck: GPIO spec for the SCK line to use - - gpio-miso: GPIO spec for the MISO line to use - - gpio-mosi: GPIO spec for the MOSI line to use + - sck-gpios: GPIO spec for the SCK line to use + - miso-gpios: GPIO spec for the MISO line to use + - mosi-gpios: GPIO spec for the MOSI line to use - cs-gpios: GPIOs to use for chipselect lines. Not needed if num-chipselects = <0>. - num-chipselects: Number of chipselect lines. Should be <0> if a single device with no chip select is connected. +Deprecated bindings: + +These legacy GPIO line bindings can alternatively be used to define the +GPIO lines used, they should not be used in new device trees. + + - gpio-sck: GPIO spec for the SCK line to use + - gpio-miso: GPIO spec for the MISO line to use + - gpio-mosi: GPIO spec for the MOSI line to use + Example: spi { @@ -20,9 +32,9 @@ Example: #address-cells = <0x1>; ranges; - gpio-sck = <&gpio 95 0>; - gpio-miso = <&gpio 98 0>; - gpio-mosi = <&gpio 97 0>; + sck-gpios = <&gpio 95 0>; + miso-gpios = <&gpio 98 0>; + mosi-gpios = <&gpio 97 0>; cs-gpios = <&gpio 125 0>; num-chipselects = <1>; diff --git a/MAINTAINERS b/MAINTAINERS index 6acc800aa28c..5a9634a0eeb4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12181,7 +12181,7 @@ F: Documentation/devicetree/bindings/clock/exynos*.txt SAMSUNG SPI DRIVERS M: Kukjin Kim <kgene@kernel.org> M: Krzysztof Kozlowski <krzk@kernel.org> -M: Andi Shyti <andi.shyti@samsung.com> +M: Andi Shyti <andi@etezian.org> L: linux-spi@vger.kernel.org L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers) S: Maintained diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index c487401b6fdb..69d7f48a4183 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -23,6 +23,7 @@ #include <linux/clk.h> #include <linux/gpio.h> +#include <linux/gpio/machine.h> #include <linux/dm9000.h> #include <linux/leds.h> #include <linux/platform_data/rtc-v3020.h> @@ -343,9 +344,6 @@ static inline void cm_x300_init_bl(void) {} #define LCD_SPI_BUS_NUM (1) static struct spi_gpio_platform_data cm_x300_spi_gpio_pdata = { - .sck = GPIO_LCD_SCL, - .mosi = GPIO_LCD_DIN, - .miso = GPIO_LCD_DOUT, .num_chipselect = 1, }; @@ -357,6 +355,21 @@ static struct platform_device cm_x300_spi_gpio = { }, }; +static struct gpiod_lookup_table cm_x300_spi_gpiod_table = { + .dev_id = "spi_gpio", + .table = { + GPIO_LOOKUP("gpio-pxa", GPIO_LCD_SCL, + "sck", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-pxa", GPIO_LCD_DIN, + "mosi", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-pxa", GPIO_LCD_DOUT, + "miso", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-pxa", GPIO_LCD_CS, + "cs", GPIO_ACTIVE_HIGH), + { }, + }, +}; + static struct tdo24m_platform_data cm_x300_tdo24m_pdata = { .model = TDO35S, }; @@ -367,7 +380,6 @@ static struct spi_board_info cm_x300_spi_devices[] __initdata = { .max_speed_hz = 1000000, .bus_num = LCD_SPI_BUS_NUM, .chip_select = 0, - .controller_data = (void *) GPIO_LCD_CS, .platform_data = &cm_x300_tdo24m_pdata, }, }; @@ -376,6 +388,7 @@ static void __init cm_x300_init_spi(void) { spi_register_board_info(cm_x300_spi_devices, ARRAY_SIZE(cm_x300_spi_devices)); + gpiod_add_lookup_table(&cm_x300_spi_gpiod_table); platform_device_register(&cm_x300_spi_gpio); } #else diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index 4d5d05cf87d6..e7ac7dcb95e9 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -646,9 +646,6 @@ static void __init raumfeld_lcd_init(void) */ static struct spi_gpio_platform_data raumfeld_spi_platform_data = { - .sck = GPIO_SPI_CLK, - .mosi = GPIO_SPI_MOSI, - .miso = GPIO_SPI_MISO, .num_chipselect = 3, }; @@ -660,6 +657,25 @@ static struct platform_device raumfeld_spi_device = { } }; +static struct gpiod_lookup_table raumfeld_spi_gpiod_table = { + .dev_id = "spi_gpio", + .table = { + GPIO_LOOKUP("gpio-0", GPIO_SPI_CLK, + "sck", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-0", GPIO_SPI_MOSI, + "mosi", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-0", GPIO_SPI_MISO, + "miso", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-0", GPIO_SPDIF_CS, + "cs", 0, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-0", GPIO_ACCEL_CS, + "cs", 1, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-0", GPIO_MCLK_DAC_CS, + "cs", 2, GPIO_ACTIVE_HIGH), + { }, + }, +}; + static struct lis3lv02d_platform_data lis3_pdata = { .click_flags = LIS3_CLICK_SINGLE_X | LIS3_CLICK_SINGLE_Y | @@ -680,7 +696,6 @@ static struct lis3lv02d_platform_data lis3_pdata = { .max_speed_hz = 10000, \ .bus_num = 0, \ .chip_select = 0, \ - .controller_data = (void *) GPIO_SPDIF_CS, \ } #define SPI_LIS3 \ @@ -689,7 +704,6 @@ static struct lis3lv02d_platform_data lis3_pdata = { .max_speed_hz = 1000000, \ .bus_num = 0, \ .chip_select = 1, \ - .controller_data = (void *) GPIO_ACCEL_CS, \ .platform_data = &lis3_pdata, \ .irq = PXA_GPIO_TO_IRQ(GPIO_ACCEL_IRQ), \ } @@ -700,7 +714,6 @@ static struct lis3lv02d_platform_data lis3_pdata = { .max_speed_hz = 1000000, \ .bus_num = 0, \ .chip_select = 2, \ - .controller_data = (void *) GPIO_MCLK_DAC_CS, \ } static struct spi_board_info connector_spi_devices[] __initdata = { @@ -1066,6 +1079,7 @@ static void __init raumfeld_common_init(void) else gpio_direction_output(GPIO_SHUTDOWN_SUPPLY, 0); + gpiod_add_lookup_table(&raumfeld_spi_gpiod_table); platform_add_devices(ARRAY_AND_SIZE(raumfeld_common_devices)); i2c_register_board_info(1, &raumfeld_pwri2c_board_info, 1); } diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c index a3ddbbbd6d92..59589a4a0d4b 100644 --- a/arch/arm/mach-s3c24xx/mach-jive.c +++ b/arch/arm/mach-s3c24xx/mach-jive.c @@ -12,6 +12,7 @@ #include <linux/timer.h> #include <linux/init.h> #include <linux/gpio.h> +#include <linux/gpio/machine.h> #include <linux/syscore_ops.h> #include <linux/serial_core.h> #include <linux/serial_s3c.h> @@ -388,32 +389,53 @@ static struct ili9320_platdata jive_lcm_config = { /* LCD SPI support */ static struct spi_gpio_platform_data jive_lcd_spi = { - .sck = S3C2410_GPG(8), - .mosi = S3C2410_GPB(8), - .miso = SPI_GPIO_NO_MISO, + .num_chipselect = 1, }; static struct platform_device jive_device_lcdspi = { - .name = "spi-gpio", + .name = "spi_gpio", .id = 1, .dev.platform_data = &jive_lcd_spi, }; +static struct gpiod_lookup_table jive_lcdspi_gpiod_table = { + .dev_id = "spi_gpio", + .table = { + GPIO_LOOKUP("GPIOG", 8, + "sck", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("GPIOB", 8, + "mosi", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("GPIOB", 7, + "cs", GPIO_ACTIVE_HIGH), + { }, + }, +}; /* WM8750 audio code SPI definition */ static struct spi_gpio_platform_data jive_wm8750_spi = { - .sck = S3C2410_GPB(4), - .mosi = S3C2410_GPB(9), - .miso = SPI_GPIO_NO_MISO, + .num_chipselect = 1, }; static struct platform_device jive_device_wm8750 = { - .name = "spi-gpio", + .name = "spi_gpio", .id = 2, .dev.platform_data = &jive_wm8750_spi, }; +static struct gpiod_lookup_table jive_wm8750_gpiod_table = { + .dev_id = "spi_gpio", + .table = { + GPIO_LOOKUP("GPIOB", 4, + "gpio-sck", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("GPIOB", 9, + "gpio-mosi", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("GPIOH", 10, + "cs", GPIO_ACTIVE_HIGH), + { }, + }, +}; + /* JIVE SPI devices. */ static struct spi_board_info __initdata jive_spi_devs[] = { @@ -424,14 +446,12 @@ static struct spi_board_info __initdata jive_spi_devs[] = { .mode = SPI_MODE_3, /* CPOL=1, CPHA=1 */ .max_speed_hz = 100000, .platform_data = &jive_lcm_config, - .controller_data = (void *)S3C2410_GPB(7), }, { .modalias = "WM8750", .bus_num = 2, .chip_select = 0, .mode = SPI_MODE_0, /* CPOL=0, CPHA=0 */ .max_speed_hz = 100000, - .controller_data = (void *)S3C2410_GPH(10), }, }; @@ -619,25 +639,12 @@ static void __init jive_machine_init(void) /** TODO - check that this is after the cmdline option! */ s3c_nand_set_platdata(&jive_nand_info); - /* initialise the spi */ - gpio_request(S3C2410_GPG(13), "lcm reset"); gpio_direction_output(S3C2410_GPG(13), 0); - gpio_request(S3C2410_GPB(7), "jive spi"); - gpio_direction_output(S3C2410_GPB(7), 1); - gpio_request_one(S3C2410_GPB(6), GPIOF_OUT_INIT_LOW, NULL); gpio_free(S3C2410_GPB(6)); - gpio_request_one(S3C2410_GPG(8), GPIOF_OUT_INIT_HIGH, NULL); - gpio_free(S3C2410_GPG(8)); - - /* initialise the WM8750 spi */ - - gpio_request(S3C2410_GPH(10), "jive wm8750 spi"); - gpio_direction_output(S3C2410_GPH(10), 1); - /* Turn off suspend on both USB ports, and switch the * selectable USB port to USB device mode. */ @@ -655,6 +662,8 @@ static void __init jive_machine_init(void) pm_power_off = jive_power_off; + gpiod_add_lookup_table(&jive_lcdspi_gpiod_table); + gpiod_add_lookup_table(&jive_wm8750_gpiod_table); platform_add_devices(jive_devices, ARRAY_SIZE(jive_devices)); } diff --git a/arch/arm/mach-s3c24xx/mach-qt2410.c b/arch/arm/mach-s3c24xx/mach-qt2410.c index 9c8373b8d9c3..5d48e5b6e738 100644 --- a/arch/arm/mach-s3c24xx/mach-qt2410.c +++ b/arch/arm/mach-s3c24xx/mach-qt2410.c @@ -11,6 +11,7 @@ #include <linux/timer.h> #include <linux/init.h> #include <linux/gpio.h> +#include <linux/gpio/machine.h> #include <linux/device.h> #include <linux/platform_device.h> #include <linux/serial_core.h> @@ -194,17 +195,30 @@ static struct platform_device qt2410_led = { /* SPI */ static struct spi_gpio_platform_data spi_gpio_cfg = { - .sck = S3C2410_GPG(7), - .mosi = S3C2410_GPG(6), - .miso = S3C2410_GPG(5), + .num_chipselect = 1, }; static struct platform_device qt2410_spi = { - .name = "spi-gpio", + .name = "spi_gpio", .id = 1, .dev.platform_data = &spi_gpio_cfg, }; +static struct gpiod_lookup_table qt2410_spi_gpiod_table = { + .dev_id = "spi_gpio", + .table = { + GPIO_LOOKUP("GPIOG", 7, + "sck", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("GPIOG", 6, + "mosi", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("GPIOG", 5, + "miso", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("GPIOB", 5, + "cs", GPIO_ACTIVE_HIGH), + { }, + }, +}; + /* Board devices */ static struct platform_device *qt2410_devices[] __initdata = { @@ -323,9 +337,7 @@ static void __init qt2410_machine_init(void) s3c24xx_udc_set_platdata(&qt2410_udc_cfg); s3c_i2c0_set_platdata(NULL); - WARN_ON(gpio_request(S3C2410_GPB(5), "spi cs")); - gpio_direction_output(S3C2410_GPB(5), 1); - + gpiod_add_lookup_table(&qt2410_spi_gpiod_table); platform_add_devices(qt2410_devices, ARRAY_SIZE(qt2410_devices)); s3c_pm_init(); } diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c index 5655fe968b1f..951208f168e7 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq.c +++ b/arch/arm/mach-s3c64xx/mach-smartq.c @@ -206,17 +206,30 @@ static int __init smartq_lcd_setup_gpio(void) /* GPM0 -> CS */ static struct spi_gpio_platform_data smartq_lcd_control = { - .sck = S3C64XX_GPM(1), - .mosi = S3C64XX_GPM(2), - .miso = S3C64XX_GPM(2), + .num_chipselect = 1, }; static struct platform_device smartq_lcd_control_device = { - .name = "spi-gpio", + .name = "spi_gpio", .id = 1, .dev.platform_data = &smartq_lcd_control, }; +static struct gpiod_lookup_table smartq_lcd_control_gpiod_table = { + .dev_id = "spi_gpio", + .table = { + GPIO_LOOKUP("GPIOM", 1, + "sck", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("GPIOM", 2, + "mosi", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("GPIOM", 3, + "miso", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("GPIOM", 0, + "cs", GPIO_ACTIVE_HIGH), + { }, + }, +}; + static void smartq_lcd_power_set(struct plat_lcd_data *pd, unsigned int power) { gpio_direction_output(S3C64XX_GPM(3), power); @@ -404,6 +417,7 @@ void __init smartq_machine_init(void) WARN_ON(smartq_wifi_init()); pwm_add_table(smartq_pwm_lookup, ARRAY_SIZE(smartq_pwm_lookup)); + gpiod_add_lookup_table(&smartq_lcd_control_gpiod_table); platform_add_devices(smartq_devices, ARRAY_SIZE(smartq_devices)); gpiod_add_lookup_table(&smartq_audio_gpios); diff --git a/arch/mips/alchemy/devboards/db1000.c b/arch/mips/alchemy/devboards/db1000.c index 433c4b9a9f0a..13e3c84859fe 100644 --- a/arch/mips/alchemy/devboards/db1000.c +++ b/arch/mips/alchemy/devboards/db1000.c @@ -22,6 +22,7 @@ #include <linux/clk.h> #include <linux/dma-mapping.h> #include <linux/gpio.h> +#include <linux/gpio/machine.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/leds.h> @@ -447,9 +448,6 @@ static struct ads7846_platform_data db1100_touch_pd = { }; static struct spi_gpio_platform_data db1100_spictl_pd = { - .sck = 209, - .mosi = 208, - .miso = 207, .num_chipselect = 1, }; @@ -462,7 +460,6 @@ static struct spi_board_info db1100_spi_info[] __initdata = { .mode = 0, .irq = AU1100_GPIO21_INT, .platform_data = &db1100_touch_pd, - .controller_data = (void *)210, /* for spi_gpio: CS# GPIO210 */ }, }; @@ -474,6 +471,24 @@ static struct platform_device db1100_spi_dev = { }, }; +/* + * Alchemy GPIO 2 has its base at 200 so the GPIO lines + * 207 thru 210 are GPIOs at offset 7 thru 10 at this chip. + */ +static struct gpiod_lookup_table db1100_spi_gpiod_table = { + .dev_id = "spi_gpio", + .table = { + GPIO_LOOKUP("alchemy-gpio2", 9, + "sck", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("alchemy-gpio2", 8, + "mosi", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("alchemy-gpio2", 7, + "miso", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("alchemy-gpio2", 10, + "cs", GPIO_ACTIVE_HIGH), + { }, + }, +}; static struct platform_device *db1x00_devs[] = { &db1x00_codec_dev, @@ -541,6 +556,7 @@ int __init db1000_dev_setup(void) clk_put(p); platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs)); + gpiod_add_lookup_table(&db1100_spi_gpiod_table); platform_device_register(&db1100_spi_dev); } else if (board == BCSR_WHOAMI_DB1000) { c0 = AU1000_GPIO2_INT; diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index 6d7f97552200..60f0767507c6 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -313,25 +313,34 @@ static struct jz4740_fb_platform_data qi_lb60_fb_pdata = { .pixclk_falling_edge = 1, }; -struct spi_gpio_platform_data spigpio_platform_data = { - .sck = JZ_GPIO_PORTC(23), - .mosi = JZ_GPIO_PORTC(22), - .miso = -1, +struct spi_gpio_platform_data qi_lb60_spigpio_platform_data = { .num_chipselect = 1, }; -static struct platform_device spigpio_device = { +static struct platform_device qi_lb60_spigpio_device = { .name = "spi_gpio", .id = 1, .dev = { - .platform_data = &spigpio_platform_data, + .platform_data = &qi_lb60_spigpio_platform_data, + }, +}; + +static struct gpiod_lookup_table qi_lb60_spigpio_gpio_table = { + .dev_id = "spi_gpio", + .table = { + GPIO_LOOKUP("GPIOC", 23, + "sck", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("GPIOC", 22, + "mosi", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("GPIOC", 21, + "cs", GPIO_ACTIVE_HIGH), + { }, }, }; static struct spi_board_info qi_lb60_spi_board_info[] = { { .modalias = "ili8960", - .controller_data = (void *)JZ_GPIO_PORTC(21), .chip_select = 0, .bus_num = 1, .max_speed_hz = 30 * 1000, @@ -435,7 +444,7 @@ static struct platform_device *jz_platform_devices[] __initdata = { &jz4740_mmc_device, &jz4740_nand_device, &qi_lb60_keypad, - &spigpio_device, + &qi_lb60_spigpio_device, &jz4740_framebuffer_device, &jz4740_pcm_device, &jz4740_i2s_device, @@ -489,6 +498,7 @@ static int __init qi_lb60_init_platform_devices(void) gpiod_add_lookup_table(&qi_lb60_audio_gpio_table); gpiod_add_lookup_table(&qi_lb60_nand_gpio_table); + gpiod_add_lookup_table(&qi_lb60_spigpio_gpio_table); spi_register_board_info(qi_lb60_spi_board_info, ARRAY_SIZE(qi_lb60_spi_board_info)); diff --git a/drivers/misc/eeprom/digsy_mtc_eeprom.c b/drivers/misc/eeprom/digsy_mtc_eeprom.c index 66d9e1baeae5..fbde2516c04f 100644 --- a/drivers/misc/eeprom/digsy_mtc_eeprom.c +++ b/drivers/misc/eeprom/digsy_mtc_eeprom.c @@ -7,9 +7,18 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * FIXME: this driver is used on a device-tree probed platform: it + * should be defined as a bit-banged SPI device and probed from the device + * tree and not like this with static grabbing of a few numbered GPIO + * lines at random. + * + * Add proper SPI and EEPROM in arch/powerpc/boot/dts/digsy_mtc.dts + * and delete this driver. */ #include <linux/gpio.h> +#include <linux/gpio/machine.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> @@ -42,9 +51,6 @@ struct eeprom_93xx46_platform_data digsy_mtc_eeprom_data = { }; static struct spi_gpio_platform_data eeprom_spi_gpio_data = { - .sck = GPIO_EEPROM_CLK, - .mosi = GPIO_EEPROM_DI, - .miso = GPIO_EEPROM_DO, .num_chipselect = 1, }; @@ -56,6 +62,21 @@ static struct platform_device digsy_mtc_eeprom = { }, }; +static struct gpiod_lookup_table eeprom_spi_gpiod_table = { + .dev_id = "spi_gpio", + .table = { + GPIO_LOOKUP("gpio@b00", GPIO_EEPROM_CLK, + "sck", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio@b00", GPIO_EEPROM_DI, + "mosi", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio@b00", GPIO_EEPROM_DO, + "miso", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio@b00", GPIO_EEPROM_CS, + "cs", GPIO_ACTIVE_HIGH), + { }, + }, +}; + static struct spi_board_info digsy_mtc_eeprom_info[] __initdata = { { .modalias = "93xx46", @@ -63,7 +84,6 @@ static struct spi_board_info digsy_mtc_eeprom_info[] __initdata = { .bus_num = EE_SPI_BUS_NUM, .chip_select = 0, .mode = SPI_MODE_0, - .controller_data = (void *)GPIO_EEPROM_CS, .platform_data = &digsy_mtc_eeprom_data, }, }; @@ -78,6 +98,7 @@ static int __init digsy_mtc_eeprom_devices_init(void) pr_err("can't request gpio %d\n", GPIO_EEPROM_OE); return ret; } + gpiod_add_lookup_table(&eeprom_spi_gpiod_table); spi_register_board_info(digsy_mtc_eeprom_info, ARRAY_SIZE(digsy_mtc_eeprom_info)); return platform_device_register(&digsy_mtc_eeprom); diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 4a11fc0d4136..3f890d162934 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -768,14 +768,14 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master, rxdesc = dmaengine_prep_slave_single(rxchan, as->dma_addr_rx_bbuf, xfer->len, - DMA_FROM_DEVICE, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } else { rxdesc = dmaengine_prep_slave_sg(rxchan, xfer->rx_sg.sgl, xfer->rx_sg.nents, - DMA_FROM_DEVICE, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } @@ -787,14 +787,14 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master, memcpy(as->addr_tx_bbuf, xfer->tx_buf, xfer->len); txdesc = dmaengine_prep_slave_single(txchan, as->dma_addr_tx_bbuf, - xfer->len, DMA_TO_DEVICE, + xfer->len, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } else { txdesc = dmaengine_prep_slave_sg(txchan, xfer->tx_sg.sgl, xfer->tx_sg.nents, - DMA_TO_DEVICE, + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } @@ -1512,6 +1512,11 @@ static void atmel_spi_init(struct atmel_spi *as) { spi_writel(as, CR, SPI_BIT(SWRST)); spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ + + /* It is recommended to enable FIFOs first thing after reset */ + if (as->fifo_size) + spi_writel(as, CR, SPI_BIT(FIFOEN)); + if (as->caps.has_wdrbt) { spi_writel(as, MR, SPI_BIT(WDRBT) | SPI_BIT(MODFDIS) | SPI_BIT(MSTR)); @@ -1522,9 +1527,6 @@ static void atmel_spi_init(struct atmel_spi *as) if (as->use_pdc) spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); spi_writel(as, CR, SPI_BIT(SPIEN)); - - if (as->fifo_size) - spi_writel(as, CR, SPI_BIT(FIFOEN)); } static int atmel_spi_probe(struct platform_device *pdev) diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index a172ab299e80..1596d35498c5 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -1247,7 +1247,7 @@ int bcm_qspi_probe(struct platform_device *pdev, qspi->base[MSPI] = devm_ioremap_resource(dev, res); if (IS_ERR(qspi->base[MSPI])) { ret = PTR_ERR(qspi->base[MSPI]); - goto qspi_probe_err; + goto qspi_resource_err; } } else { goto qspi_resource_err; @@ -1258,7 +1258,7 @@ int bcm_qspi_probe(struct platform_device *pdev, qspi->base[BSPI] = devm_ioremap_resource(dev, res); if (IS_ERR(qspi->base[BSPI])) { ret = PTR_ERR(qspi->base[BSPI]); - goto qspi_probe_err; + goto qspi_resource_err; } qspi->bspi_mode = true; } else { diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index 7428091d3f5b..1431cb98fe40 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -321,7 +321,6 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, struct bcm2835aux_spi *bs = spi_master_get_devdata(master); unsigned long spi_hz, clk_hz, speed; unsigned long spi_used_hz; - unsigned long long xfer_time_us; /* calculate the registers to handle * @@ -358,20 +357,21 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, bs->rx_len = tfr->len; bs->pending = 0; - /* calculate the estimated time in us the transfer runs - * note that there are are 2 idle clocks after each - * chunk getting transferred - in our case the chunk size - * is 3 bytes, so we approximate this by 9 bits/byte + /* Calculate the estimated time in us the transfer runs. Note that + * there are are 2 idle clocks cycles after each chunk getting + * transferred - in our case the chunk size is 3 bytes, so we + * approximate this by 9 cycles/byte. This is used to find the number + * of Hz per byte per polling limit. E.g., we can transfer 1 byte in + * 30 µs per 300,000 Hz of bus clock. */ - xfer_time_us = tfr->len * 9 * 1000000; - do_div(xfer_time_us, spi_used_hz); - +#define HZ_PER_BYTE ((9 * 1000000) / BCM2835_AUX_SPI_POLLING_LIMIT_US) /* run in polling mode for short transfers */ - if (xfer_time_us < BCM2835_AUX_SPI_POLLING_LIMIT_US) + if (tfr->len < spi_used_hz / HZ_PER_BYTE) return bcm2835aux_spi_transfer_one_poll(master, spi, tfr); /* run in interrupt mode for all others */ return bcm2835aux_spi_transfer_one_irq(master, spi, tfr); +#undef HZ_PER_BYTE } static int bcm2835aux_spi_prepare_message(struct spi_master *master, diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c index 837cb8d0bac6..3db905f5f345 100644 --- a/drivers/spi/spi-dw-mid.c +++ b/drivers/spi/spi-dw-mid.c @@ -112,10 +112,10 @@ static irqreturn_t dma_transfer(struct dw_spi *dws) return IRQ_HANDLED; } -static bool mid_spi_can_dma(struct spi_master *master, struct spi_device *spi, - struct spi_transfer *xfer) +static bool mid_spi_can_dma(struct spi_controller *master, + struct spi_device *spi, struct spi_transfer *xfer) { - struct dw_spi *dws = spi_master_get_devdata(master); + struct dw_spi *dws = spi_controller_get_devdata(master); if (!dws->dma_inited) return false; diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 211cc7d75bf8..f693bfe95ab9 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -135,7 +135,7 @@ static inline void dw_spi_debugfs_remove(struct dw_spi *dws) static void dw_spi_set_cs(struct spi_device *spi, bool enable) { - struct dw_spi *dws = spi_master_get_devdata(spi->master); + struct dw_spi *dws = spi_controller_get_devdata(spi->controller); struct chip_data *chip = spi_get_ctldata(spi); /* Chip select logic is inverted from spi_set_cs() */ @@ -250,8 +250,8 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws) static irqreturn_t dw_spi_irq(int irq, void *dev_id) { - struct spi_master *master = dev_id; - struct dw_spi *dws = spi_master_get_devdata(master); + struct spi_controller *master = dev_id; + struct dw_spi *dws = spi_controller_get_devdata(master); u16 irq_status = dw_readl(dws, DW_SPI_ISR) & 0x3f; if (!irq_status) @@ -277,10 +277,10 @@ static int poll_transfer(struct dw_spi *dws) return 0; } -static int dw_spi_transfer_one(struct spi_master *master, +static int dw_spi_transfer_one(struct spi_controller *master, struct spi_device *spi, struct spi_transfer *transfer) { - struct dw_spi *dws = spi_master_get_devdata(master); + struct dw_spi *dws = spi_controller_get_devdata(master); struct chip_data *chip = spi_get_ctldata(spi); u8 imask = 0; u16 txlevel = 0; @@ -383,10 +383,10 @@ static int dw_spi_transfer_one(struct spi_master *master, return 1; } -static void dw_spi_handle_err(struct spi_master *master, +static void dw_spi_handle_err(struct spi_controller *master, struct spi_message *msg) { - struct dw_spi *dws = spi_master_get_devdata(master); + struct dw_spi *dws = spi_controller_get_devdata(master); if (dws->dma_mapped) dws->dma_ops->dma_stop(dws); @@ -471,7 +471,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi *dws) int dw_spi_add_host(struct device *dev, struct dw_spi *dws) { - struct spi_master *master; + struct spi_controller *master; int ret; BUG_ON(dws == NULL); @@ -518,8 +518,8 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) } } - spi_master_set_devdata(master, dws); - ret = devm_spi_register_master(dev, master); + spi_controller_set_devdata(master, dws); + ret = devm_spi_register_controller(dev, master); if (ret) { dev_err(&master->dev, "problem registering spi master\n"); goto err_dma_exit; @@ -534,7 +534,7 @@ err_dma_exit: spi_enable_chip(dws, 0); free_irq(dws->irq, master); err_free_master: - spi_master_put(master); + spi_controller_put(master); return ret; } EXPORT_SYMBOL_GPL(dw_spi_add_host); @@ -556,7 +556,7 @@ int dw_spi_suspend_host(struct dw_spi *dws) { int ret; - ret = spi_master_suspend(dws->master); + ret = spi_controller_suspend(dws->master); if (ret) return ret; @@ -570,7 +570,7 @@ int dw_spi_resume_host(struct dw_spi *dws) int ret; spi_hw_init(&dws->master->dev, dws); - ret = spi_master_resume(dws->master); + ret = spi_controller_resume(dws->master); if (ret) dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret); return ret; diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h index 5c07cf8f19e0..2cde2473b3e9 100644 --- a/drivers/spi/spi-dw.h +++ b/drivers/spi/spi-dw.h @@ -93,14 +93,14 @@ struct dw_spi_dma_ops { int (*dma_init)(struct dw_spi *dws); void (*dma_exit)(struct dw_spi *dws); int (*dma_setup)(struct dw_spi *dws, struct spi_transfer *xfer); - bool (*can_dma)(struct spi_master *master, struct spi_device *spi, + bool (*can_dma)(struct spi_controller *master, struct spi_device *spi, struct spi_transfer *xfer); int (*dma_transfer)(struct dw_spi *dws, struct spi_transfer *xfer); void (*dma_stop)(struct dw_spi *dws); }; struct dw_spi { - struct spi_master *master; + struct spi_controller *master; enum dw_ssi_type type; void __iomem *regs; diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 1c34c9314c8a..b85a93cad44a 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -2,6 +2,7 @@ * SPI master driver using generic bitbanged GPIO * * Copyright (C) 2006,2008 David Brownell + * Copyright (C) 2017 Linus Walleij * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,10 +17,9 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/of.h> #include <linux/of_device.h> -#include <linux/of_gpio.h> #include <linux/spi/spi.h> #include <linux/spi/spi_bitbang.h> @@ -44,7 +44,11 @@ struct spi_gpio { struct spi_bitbang bitbang; struct spi_gpio_platform_data pdata; struct platform_device *pdev; - unsigned long cs_gpios[0]; + struct gpio_desc *sck; + struct gpio_desc *miso; + struct gpio_desc *mosi; + struct gpio_desc **cs_gpios; + bool has_cs; }; /*----------------------------------------------------------------------*/ @@ -77,13 +81,6 @@ struct spi_gpio { #define GENERIC_BITBANG /* vs tight inlines */ -/* all functions referencing these symbols must define pdata */ -#define SPI_MISO_GPIO ((pdata)->miso) -#define SPI_MOSI_GPIO ((pdata)->mosi) -#define SPI_SCK_GPIO ((pdata)->sck) - -#define SPI_N_CHIPSEL ((pdata)->num_chipselect) - #endif /*----------------------------------------------------------------------*/ @@ -105,25 +102,27 @@ spi_to_pdata(const struct spi_device *spi) return &spi_to_spi_gpio(spi)->pdata; } -/* this is #defined to avoid unused-variable warnings when inlining */ -#define pdata spi_to_pdata(spi) - +/* These helpers are in turn called by the bitbang inlines */ static inline void setsck(const struct spi_device *spi, int is_on) { - gpio_set_value_cansleep(SPI_SCK_GPIO, is_on); + struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); + + gpiod_set_value_cansleep(spi_gpio->sck, is_on); } static inline void setmosi(const struct spi_device *spi, int is_on) { - gpio_set_value_cansleep(SPI_MOSI_GPIO, is_on); + struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); + + gpiod_set_value_cansleep(spi_gpio->mosi, is_on); } static inline int getmiso(const struct spi_device *spi) { - return !!gpio_get_value_cansleep(SPI_MISO_GPIO); -} + struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); -#undef pdata + return !!gpiod_get_value_cansleep(spi_gpio->miso); +} /* * NOTE: this clocks "as fast as we can". It "should" be a function of the @@ -216,123 +215,89 @@ static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi, static void spi_gpio_chipselect(struct spi_device *spi, int is_active) { struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); - unsigned long cs = spi_gpio->cs_gpios[spi->chip_select]; - /* set initial clock polarity */ + /* set initial clock line level */ if (is_active) - setsck(spi, spi->mode & SPI_CPOL); + gpiod_set_value_cansleep(spi_gpio->sck, spi->mode & SPI_CPOL); + + /* Drive chip select line, if we have one */ + if (spi_gpio->has_cs) { + struct gpio_desc *cs = spi_gpio->cs_gpios[spi->chip_select]; - if (cs != SPI_GPIO_NO_CHIPSELECT) { - /* SPI is normally active-low */ - gpio_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); + /* SPI chip selects are normally active-low */ + gpiod_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); } } static int spi_gpio_setup(struct spi_device *spi) { - unsigned long cs; + struct gpio_desc *cs; int status = 0; struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); - struct device_node *np = spi->master->dev.of_node; - - if (np) { - /* - * In DT environments, the CS GPIOs have already been - * initialized from the "cs-gpios" property of the node. - */ - cs = spi_gpio->cs_gpios[spi->chip_select]; - } else { - /* - * ... otherwise, take it from spi->controller_data - */ - cs = (uintptr_t) spi->controller_data; - } - if (!spi->controller_state) { - if (cs != SPI_GPIO_NO_CHIPSELECT) { - status = gpio_request(cs, dev_name(&spi->dev)); - if (status) - return status; - status = gpio_direction_output(cs, - !(spi->mode & SPI_CS_HIGH)); - } - } - if (!status) { - /* in case it was initialized from static board data */ - spi_gpio->cs_gpios[spi->chip_select] = cs; + /* + * The CS GPIOs have already been + * initialized from the descriptor lookup. + */ + cs = spi_gpio->cs_gpios[spi->chip_select]; + if (!spi->controller_state && cs) + status = gpiod_direction_output(cs, + !(spi->mode & SPI_CS_HIGH)); + + if (!status) status = spi_bitbang_setup(spi); - } - if (status) { - if (!spi->controller_state && cs != SPI_GPIO_NO_CHIPSELECT) - gpio_free(cs); - } return status; } static void spi_gpio_cleanup(struct spi_device *spi) { - struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); - unsigned long cs = spi_gpio->cs_gpios[spi->chip_select]; - - if (cs != SPI_GPIO_NO_CHIPSELECT) - gpio_free(cs); spi_bitbang_cleanup(spi); } -static int spi_gpio_alloc(unsigned pin, const char *label, bool is_in) -{ - int value; - - value = gpio_request(pin, label); - if (value == 0) { - if (is_in) - value = gpio_direction_input(pin); - else - value = gpio_direction_output(pin, 0); - } - return value; -} - -static int spi_gpio_request(struct spi_gpio_platform_data *pdata, - const char *label, u16 *res_flags) +/* + * It can be convenient to use this driver with pins that have alternate + * functions associated with a "native" SPI controller if a driver for that + * controller is not available, or is missing important functionality. + * + * On platforms which can do so, configure MISO with a weak pullup unless + * there's an external pullup on that signal. That saves power by avoiding + * floating signals. (A weak pulldown would save power too, but many + * drivers expect to see all-ones data as the no slave "response".) + */ +static int spi_gpio_request(struct device *dev, + struct spi_gpio *spi_gpio, + unsigned int num_chipselects, + u16 *mflags) { - int value; - - /* NOTE: SPI_*_GPIO symbols may reference "pdata" */ + int i; - if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) { - value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false); - if (value) - goto done; - } else { + spi_gpio->mosi = devm_gpiod_get_optional(dev, "mosi", GPIOD_OUT_LOW); + if (IS_ERR(spi_gpio->mosi)) + return PTR_ERR(spi_gpio->mosi); + if (!spi_gpio->mosi) /* HW configuration without MOSI pin */ - *res_flags |= SPI_MASTER_NO_TX; - } + *mflags |= SPI_MASTER_NO_TX; - if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) { - value = spi_gpio_alloc(SPI_MISO_GPIO, label, true); - if (value) - goto free_mosi; - } else { + spi_gpio->miso = devm_gpiod_get_optional(dev, "miso", GPIOD_IN); + if (IS_ERR(spi_gpio->miso)) + return PTR_ERR(spi_gpio->miso); + if (!spi_gpio->miso) /* HW configuration without MISO pin */ - *res_flags |= SPI_MASTER_NO_RX; - } + *mflags |= SPI_MASTER_NO_RX; - value = spi_gpio_alloc(SPI_SCK_GPIO, label, false); - if (value) - goto free_miso; + spi_gpio->sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW); + if (IS_ERR(spi_gpio->mosi)) + return PTR_ERR(spi_gpio->mosi); - goto done; + for (i = 0; i < num_chipselects; i++) { + spi_gpio->cs_gpios[i] = devm_gpiod_get_index(dev, "cs", + i, GPIOD_OUT_HIGH); + if (IS_ERR(spi_gpio->cs_gpios[i])) + return PTR_ERR(spi_gpio->cs_gpios[i]); + } -free_miso: - if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) - gpio_free(SPI_MISO_GPIO); -free_mosi: - if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) - gpio_free(SPI_MOSI_GPIO); -done: - return value; + return 0; } #ifdef CONFIG_OF @@ -358,26 +323,6 @@ static int spi_gpio_probe_dt(struct platform_device *pdev) if (!pdata) return -ENOMEM; - ret = of_get_named_gpio(np, "gpio-sck", 0); - if (ret < 0) { - dev_err(&pdev->dev, "gpio-sck property not found\n"); - goto error_free; - } - pdata->sck = ret; - - ret = of_get_named_gpio(np, "gpio-miso", 0); - if (ret < 0) { - dev_info(&pdev->dev, "gpio-miso property not found, switching to no-rx mode\n"); - pdata->miso = SPI_GPIO_NO_MISO; - } else - pdata->miso = ret; - - ret = of_get_named_gpio(np, "gpio-mosi", 0); - if (ret < 0) { - dev_info(&pdev->dev, "gpio-mosi property not found, switching to no-tx mode\n"); - pdata->mosi = SPI_GPIO_NO_MOSI; - } else - pdata->mosi = ret; ret = of_property_read_u32(np, "num-chipselects", &tmp); if (ret < 0) { @@ -409,7 +354,6 @@ static int spi_gpio_probe(struct platform_device *pdev) struct spi_gpio_platform_data *pdata; u16 master_flags = 0; bool use_of = 0; - int num_devices; status = spi_gpio_probe_dt(pdev); if (status < 0) @@ -423,59 +367,41 @@ static int spi_gpio_probe(struct platform_device *pdev) return -ENODEV; #endif - if (use_of && !SPI_N_CHIPSEL) - num_devices = 1; - else - num_devices = SPI_N_CHIPSEL; - - status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags); - if (status < 0) - return status; + master = spi_alloc_master(&pdev->dev, sizeof(*spi_gpio)); + if (!master) + return -ENOMEM; - master = spi_alloc_master(&pdev->dev, sizeof(*spi_gpio) + - (sizeof(unsigned long) * num_devices)); - if (!master) { - status = -ENOMEM; - goto gpio_free; - } spi_gpio = spi_master_get_devdata(master); + + spi_gpio->cs_gpios = devm_kzalloc(&pdev->dev, + pdata->num_chipselect * sizeof(*spi_gpio->cs_gpios), + GFP_KERNEL); + if (!spi_gpio->cs_gpios) + return -ENOMEM; + platform_set_drvdata(pdev, spi_gpio); + /* Determine if we have chip selects connected */ + spi_gpio->has_cs = !!pdata->num_chipselect; + spi_gpio->pdev = pdev; if (pdata) spi_gpio->pdata = *pdata; + status = spi_gpio_request(&pdev->dev, spi_gpio, + pdata->num_chipselect, &master_flags); + if (status) + return status; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); master->flags = master_flags; master->bus_num = pdev->id; - master->num_chipselect = num_devices; + /* The master needs to think there is a chipselect even if not connected */ + master->num_chipselect = spi_gpio->has_cs ? pdata->num_chipselect : 1; master->setup = spi_gpio_setup; master->cleanup = spi_gpio_cleanup; #ifdef CONFIG_OF master->dev.of_node = pdev->dev.of_node; - - if (use_of) { - int i; - struct device_node *np = pdev->dev.of_node; - - /* - * In DT environments, take the CS GPIO from the "cs-gpios" - * property of the node. - */ - - if (!SPI_N_CHIPSEL) - spi_gpio->cs_gpios[0] = SPI_GPIO_NO_CHIPSELECT; - else - for (i = 0; i < SPI_N_CHIPSEL; i++) { - status = of_get_named_gpio(np, "cs-gpios", i); - if (status < 0) { - dev_err(&pdev->dev, - "invalid cs-gpios property\n"); - goto gpio_free; - } - spi_gpio->cs_gpios[i] = status; - } - } #endif spi_gpio->bitbang.master = master; @@ -496,15 +422,8 @@ static int spi_gpio_probe(struct platform_device *pdev) spi_gpio->bitbang.flags = SPI_CS_HIGH; status = spi_bitbang_start(&spi_gpio->bitbang); - if (status < 0) { -gpio_free: - if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) - gpio_free(SPI_MISO_GPIO); - if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) - gpio_free(SPI_MOSI_GPIO); - gpio_free(SPI_SCK_GPIO); + if (status) spi_master_put(master); - } return status; } @@ -520,11 +439,6 @@ static int spi_gpio_remove(struct platform_device *pdev) /* stop() unregisters child devices too */ spi_bitbang_stop(&spi_gpio->bitbang); - if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) - gpio_free(SPI_MISO_GPIO); - if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) - gpio_free(SPI_MOSI_GPIO); - gpio_free(SPI_SCK_GPIO); spi_master_put(spi_gpio->bitbang.master); return 0; diff --git a/drivers/spi/spi-jcore.c b/drivers/spi/spi-jcore.c index dafed6280df3..702fe573a47b 100644 --- a/drivers/spi/spi-jcore.c +++ b/drivers/spi/spi-jcore.c @@ -184,10 +184,11 @@ static int jcore_spi_probe(struct platform_device *pdev) */ clock_freq = 50000000; clk = devm_clk_get(&pdev->dev, "ref_clk"); - if (!IS_ERR_OR_NULL(clk)) { - if (clk_enable(clk) == 0) + if (!IS_ERR(clk)) { + if (clk_prepare_enable(clk) == 0) { clock_freq = clk_get_rate(clk); - else + clk_disable_unprepare(clk); + } else dev_warn(&pdev->dev, "could not enable ref_clk\n"); } hw->clock_freq = clock_freq; @@ -198,10 +199,8 @@ static int jcore_spi_probe(struct platform_device *pdev) /* Register our spi controller */ err = devm_spi_register_master(&pdev->dev, master); - if (err) { - clk_disable(clk); + if (err) goto exit; - } return 0; diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index deca63e82ff6..d01a6adc726e 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -90,14 +90,19 @@ struct orion_direct_acc { u32 size; }; +struct orion_child_options { + struct orion_direct_acc direct_access; +}; + struct orion_spi { struct spi_master *master; void __iomem *base; struct clk *clk; struct clk *axi_clk; const struct orion_spi_dev *devdata; + int unused_hw_gpio; - struct orion_direct_acc direct_access[ORION_NUM_CHIPSELECTS]; + struct orion_child_options child[ORION_NUM_CHIPSELECTS]; }; static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg) @@ -324,13 +329,13 @@ static void orion_spi_set_cs(struct spi_device *spi, bool enable) struct orion_spi *orion_spi; int cs; + orion_spi = spi_master_get_devdata(spi->master); + if (gpio_is_valid(spi->cs_gpio)) - cs = 0; + cs = orion_spi->unused_hw_gpio; else cs = spi->chip_select; - orion_spi = spi_master_get_devdata(spi->master); - orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS_MASK); orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS(cs)); @@ -435,7 +440,7 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) * Use SPI direct write mode if base address is available. Otherwise * fall back to PIO mode for this transfer. */ - if ((orion_spi->direct_access[cs].vaddr) && (xfer->tx_buf) && + if ((orion_spi->child[cs].direct_access.vaddr) && (xfer->tx_buf) && (word_len == 8)) { unsigned int cnt = count / 4; unsigned int rem = count % 4; @@ -444,12 +449,12 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) * Send the TX-data to the SPI device via the direct * mapped address window */ - iowrite32_rep(orion_spi->direct_access[cs].vaddr, + iowrite32_rep(orion_spi->child[cs].direct_access.vaddr, xfer->tx_buf, cnt); if (rem) { u32 *buf = (u32 *)xfer->tx_buf; - iowrite8_rep(orion_spi->direct_access[cs].vaddr, + iowrite8_rep(orion_spi->child[cs].direct_access.vaddr, &buf[cnt], rem); } @@ -498,6 +503,9 @@ static int orion_spi_transfer_one(struct spi_master *master, static int orion_spi_setup(struct spi_device *spi) { + if (gpio_is_valid(spi->cs_gpio)) { + gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); + } return orion_spi_setup_transfer(spi, NULL); } @@ -620,6 +628,7 @@ static int orion_spi_probe(struct platform_device *pdev) spi = spi_master_get_devdata(master); spi->master = master; + spi->unused_hw_gpio = -1; of_id = of_match_device(orion_spi_of_match_table, &pdev->dev); devdata = (of_id) ? of_id->data : &orion_spi_dev_data; @@ -702,14 +711,14 @@ static int orion_spi_probe(struct platform_device *pdev) * This needs to get extended for the direct SPI-NOR / SPI-NAND * support, once this gets implemented. */ - spi->direct_access[cs].vaddr = devm_ioremap(&pdev->dev, + spi->child[cs].direct_access.vaddr = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE); - if (!spi->direct_access[cs].vaddr) { + if (!spi->child[cs].direct_access.vaddr) { status = -ENOMEM; goto out_rel_axi_clk; } - spi->direct_access[cs].size = PAGE_SIZE; + spi->child[cs].direct_access.size = PAGE_SIZE; dev_info(&pdev->dev, "CS%d configured for direct access\n", cs); } @@ -731,8 +740,44 @@ static int orion_spi_probe(struct platform_device *pdev) if (status < 0) goto out_rel_pm; + if (master->cs_gpios) { + int i; + for (i = 0; i < master->num_chipselect; ++i) { + char *gpio_name; + + if (!gpio_is_valid(master->cs_gpios[i])) { + continue; + } + + gpio_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "%s-CS%d", dev_name(&pdev->dev), i); + if (!gpio_name) { + status = -ENOMEM; + goto out_rel_master; + } + + status = devm_gpio_request(&pdev->dev, + master->cs_gpios[i], gpio_name); + if (status) { + dev_err(&pdev->dev, + "Can't request GPIO for CS %d\n", + master->cs_gpios[i]); + goto out_rel_master; + } + if (spi->unused_hw_gpio == -1) { + dev_info(&pdev->dev, + "Selected unused HW CS#%d for any GPIO CSes\n", + i); + spi->unused_hw_gpio = i; + } + } + } + + return status; +out_rel_master: + spi_unregister_master(master); out_rel_pm: pm_runtime_disable(&pdev->dev); out_rel_axi_clk: diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c index 04f3eecf5cf3..3d7f66080c57 100644 --- a/drivers/spi/spi-pxa2xx-dma.c +++ b/drivers/spi/spi-pxa2xx-dma.c @@ -191,7 +191,7 @@ int pxa2xx_spi_dma_setup(struct driver_data *drv_data) { struct pxa2xx_spi_master *pdata = drv_data->master_info; struct device *dev = &drv_data->pdev->dev; - struct spi_master *master = drv_data->master; + struct spi_controller *master = drv_data->master; dma_cap_mask_t mask; dma_cap_zero(mask); @@ -215,7 +215,7 @@ int pxa2xx_spi_dma_setup(struct driver_data *drv_data) void pxa2xx_spi_dma_release(struct driver_data *drv_data) { - struct spi_master *master = drv_data->master; + struct spi_controller *master = drv_data->master; if (master->dma_rx) { dmaengine_terminate_sync(master->dma_rx); diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index b0822d1dba29..82dcb88fcfba 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -415,10 +415,17 @@ static void cs_deassert(struct driver_data *drv_data) { struct chip_data *chip = spi_get_ctldata(drv_data->master->cur_msg->spi); + unsigned long timeout; if (drv_data->ssp_type == CE4100_SSP) return; + /* Wait until SSP becomes idle before deasserting the CS */ + timeout = jiffies + msecs_to_jiffies(10); + while (pxa2xx_spi_read(drv_data, SSSR) & SSSR_BSY && + !time_after(jiffies, timeout)) + cpu_relax(); + if (chip->cs_control) { chip->cs_control(PXA2XX_CS_DEASSERT); return; @@ -563,7 +570,6 @@ static void giveback(struct driver_data *drv_data) { struct spi_transfer* last_transfer; struct spi_message *msg; - unsigned long timeout; msg = drv_data->master->cur_msg; drv_data->cur_transfer = NULL; @@ -575,12 +581,6 @@ static void giveback(struct driver_data *drv_data) if (last_transfer->delay_usecs) udelay(last_transfer->delay_usecs); - /* Wait until SSP becomes idle before deasserting the CS */ - timeout = jiffies + msecs_to_jiffies(10); - while (pxa2xx_spi_read(drv_data, SSSR) & SSSR_BSY && - !time_after(jiffies, timeout)) - cpu_relax(); - /* Drop chip select UNLESS cs_change is true or we are returning * a message with an error, or next message is for another chip */ @@ -962,7 +962,7 @@ static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data, return clk_div << 8; } -static bool pxa2xx_spi_can_dma(struct spi_master *master, +static bool pxa2xx_spi_can_dma(struct spi_controller *master, struct spi_device *spi, struct spi_transfer *xfer) { @@ -976,7 +976,7 @@ static bool pxa2xx_spi_can_dma(struct spi_master *master, static void pump_transfers(unsigned long data) { struct driver_data *drv_data = (struct driver_data *)data; - struct spi_master *master = drv_data->master; + struct spi_controller *master = drv_data->master; struct spi_message *message = master->cur_msg; struct chip_data *chip = spi_get_ctldata(message->spi); u32 dma_thresh = chip->dma_threshold; @@ -1182,10 +1182,10 @@ static void pump_transfers(unsigned long data) pxa2xx_spi_write(drv_data, SSCR1, cr1); } -static int pxa2xx_spi_transfer_one_message(struct spi_master *master, +static int pxa2xx_spi_transfer_one_message(struct spi_controller *master, struct spi_message *msg) { - struct driver_data *drv_data = spi_master_get_devdata(master); + struct driver_data *drv_data = spi_controller_get_devdata(master); /* Initial message state*/ msg->state = START_STATE; @@ -1198,9 +1198,9 @@ static int pxa2xx_spi_transfer_one_message(struct spi_master *master, return 0; } -static int pxa2xx_spi_unprepare_transfer(struct spi_master *master) +static int pxa2xx_spi_unprepare_transfer(struct spi_controller *master) { - struct driver_data *drv_data = spi_master_get_devdata(master); + struct driver_data *drv_data = spi_controller_get_devdata(master); /* Disable the SSP now */ pxa2xx_spi_write(drv_data, SSCR0, @@ -1212,7 +1212,8 @@ static int pxa2xx_spi_unprepare_transfer(struct spi_master *master) static int setup_cs(struct spi_device *spi, struct chip_data *chip, struct pxa2xx_spi_chip *chip_info) { - struct driver_data *drv_data = spi_master_get_devdata(spi->master); + struct driver_data *drv_data = + spi_controller_get_devdata(spi->controller); struct gpio_desc *gpiod; int err = 0; @@ -1270,7 +1271,8 @@ static int setup(struct spi_device *spi) struct pxa2xx_spi_chip *chip_info; struct chip_data *chip; const struct lpss_config *config; - struct driver_data *drv_data = spi_master_get_devdata(spi->master); + struct driver_data *drv_data = + spi_controller_get_devdata(spi->controller); uint tx_thres, tx_hi_thres, rx_thres; switch (drv_data->ssp_type) { @@ -1410,7 +1412,8 @@ static int setup(struct spi_device *spi) static void cleanup(struct spi_device *spi) { struct chip_data *chip = spi_get_ctldata(spi); - struct driver_data *drv_data = spi_master_get_devdata(spi->master); + struct driver_data *drv_data = + spi_controller_get_devdata(spi->controller); if (!chip) return; @@ -1575,9 +1578,10 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev) } #endif -static int pxa2xx_spi_fw_translate_cs(struct spi_master *master, unsigned cs) +static int pxa2xx_spi_fw_translate_cs(struct spi_controller *master, + unsigned int cs) { - struct driver_data *drv_data = spi_master_get_devdata(master); + struct driver_data *drv_data = spi_controller_get_devdata(master); if (has_acpi_companion(&drv_data->pdev->dev)) { switch (drv_data->ssp_type) { @@ -1602,7 +1606,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct pxa2xx_spi_master *platform_info; - struct spi_master *master; + struct spi_controller *master; struct driver_data *drv_data; struct ssp_device *ssp; const struct lpss_config *config; @@ -1633,7 +1637,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) pxa_ssp_free(ssp); return -ENOMEM; } - drv_data = spi_master_get_devdata(master); + drv_data = spi_controller_get_devdata(master); drv_data->master = master; drv_data->master_info = platform_info; drv_data->pdev = pdev; @@ -1651,7 +1655,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) master->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer; master->fw_translate_cs = pxa2xx_spi_fw_translate_cs; master->auto_runtime_pm = true; - master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; + master->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX; drv_data->ssp_type = ssp->type; @@ -1793,7 +1797,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) /* Register with the SPI framework */ platform_set_drvdata(pdev, drv_data); - status = devm_spi_register_master(&pdev->dev, master); + status = devm_spi_register_controller(&pdev->dev, master); if (status != 0) { dev_err(&pdev->dev, "problem registering spi master\n"); goto out_error_clock_enabled; @@ -1802,12 +1806,14 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) return status; out_error_clock_enabled: + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_disable(&pdev->dev); clk_disable_unprepare(ssp->clk); pxa2xx_spi_dma_release(drv_data); free_irq(ssp->irq, drv_data); out_error_master_alloc: - spi_master_put(master); + spi_controller_put(master); pxa_ssp_free(ssp); return status; } @@ -1858,7 +1864,7 @@ static int pxa2xx_spi_suspend(struct device *dev) struct ssp_device *ssp = drv_data->ssp; int status; - status = spi_master_suspend(drv_data->master); + status = spi_controller_suspend(drv_data->master); if (status != 0) return status; pxa2xx_spi_write(drv_data, SSCR0, 0); @@ -1884,7 +1890,7 @@ static int pxa2xx_spi_resume(struct device *dev) lpss_ssp_setup(drv_data); /* Start the queue running */ - status = spi_master_resume(drv_data->master); + status = spi_controller_resume(drv_data->master); if (status != 0) { dev_err(dev, "problem starting queue (%d)\n", status); return status; diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h index 94f7b0713281..513ec6c6e25b 100644 --- a/drivers/spi/spi-pxa2xx.h +++ b/drivers/spi/spi-pxa2xx.h @@ -31,7 +31,7 @@ struct driver_data { /* SPI framework hookup */ enum pxa_ssp_type ssp_type; - struct spi_master *master; + struct spi_controller *master; /* PXA hookup */ struct pxa2xx_spi_master *master_info; diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 0835a8d88fb8..95dc4d78618d 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -535,7 +535,7 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, /* First prepare and submit the DMA request(s), as this may fail */ if (rx) { desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx, - rx->sgl, rx->nents, DMA_FROM_DEVICE, + rx->sgl, rx->nents, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_rx) { ret = -EAGAIN; @@ -555,7 +555,7 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, if (tx) { desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx, - tx->sgl, tx->nents, DMA_TO_DEVICE, + tx->sgl, tx->nents, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_tx) { ret = -EAGAIN; diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index c5dcfb434a49..ae086aab57d5 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -752,7 +752,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, if (rx) { ier_bits |= IER_RDREQE | IER_RDMAE; desc_rx = dmaengine_prep_slave_single(p->master->dma_rx, - p->rx_dma_addr, len, DMA_FROM_DEVICE, + p->rx_dma_addr, len, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_rx) return -EAGAIN; @@ -769,7 +769,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, dma_sync_single_for_device(p->master->dma_tx->device->dev, p->tx_dma_addr, len, DMA_TO_DEVICE); desc_tx = dmaengine_prep_slave_single(p->master->dma_tx, - p->tx_dma_addr, len, DMA_TO_DEVICE, + p->tx_dma_addr, len, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_tx) { ret = -EAGAIN; diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index 5993bdbf79e4..197d4b0d81af 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: GPL-2.0 */ +#include <linux/delay.h> #include <linux/hwspinlock.h> #include <linux/init.h> #include <linux/io.h> @@ -12,6 +13,7 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> +#include <linux/reboot.h> #include <linux/spi/spi.h> #include <linux/sizes.h> @@ -67,6 +69,40 @@ #define ADI_READ_TIMEOUT 2000 #define REG_ADDR_LOW_MASK GENMASK(11, 0) +/* Registers definitions for PMIC watchdog controller */ +#define REG_WDG_LOAD_LOW 0x80 +#define REG_WDG_LOAD_HIGH 0x84 +#define REG_WDG_CTRL 0x88 +#define REG_WDG_LOCK 0xa0 + +/* Bits definitions for register REG_WDG_CTRL */ +#define BIT_WDG_RUN BIT(1) +#define BIT_WDG_RST BIT(3) + +/* Registers definitions for PMIC */ +#define PMIC_RST_STATUS 0xee8 +#define PMIC_MODULE_EN 0xc08 +#define PMIC_CLK_EN 0xc18 +#define BIT_WDG_EN BIT(2) + +/* Definition of PMIC reset status register */ +#define HWRST_STATUS_RECOVERY 0x20 +#define HWRST_STATUS_NORMAL 0x40 +#define HWRST_STATUS_ALARM 0x50 +#define HWRST_STATUS_SLEEP 0x60 +#define HWRST_STATUS_FASTBOOT 0x30 +#define HWRST_STATUS_SPECIAL 0x70 +#define HWRST_STATUS_PANIC 0x80 +#define HWRST_STATUS_CFTREBOOT 0x90 +#define HWRST_STATUS_AUTODLOADER 0xa0 +#define HWRST_STATUS_IQMODE 0xb0 +#define HWRST_STATUS_SPRDISK 0xc0 + +/* Use default timeout 50 ms that converts to watchdog values */ +#define WDG_LOAD_VAL ((50 * 1000) / 32768) +#define WDG_LOAD_MASK GENMASK(15, 0) +#define WDG_UNLOCK_KEY 0xe551 + struct sprd_adi { struct spi_controller *ctlr; struct device *dev; @@ -74,6 +110,7 @@ struct sprd_adi { struct hwspinlock *hwlock; unsigned long slave_vbase; unsigned long slave_pbase; + struct notifier_block restart_handler; }; static int sprd_adi_check_paddr(struct sprd_adi *sadi, u32 paddr) @@ -123,7 +160,17 @@ static int sprd_adi_fifo_is_full(struct sprd_adi *sadi) static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) { int read_timeout = ADI_READ_TIMEOUT; + unsigned long flags; u32 val, rd_addr; + int ret; + + ret = hwspin_lock_timeout_irqsave(sadi->hwlock, + ADI_HWSPINLOCK_TIMEOUT, + &flags); + if (ret) { + dev_err(sadi->dev, "get the hw lock failed\n"); + return ret; + } /* * Set the physical register address need to read into RD_CMD register, @@ -147,7 +194,8 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) if (read_timeout == 0) { dev_err(sadi->dev, "ADI read timeout\n"); - return -EBUSY; + ret = -EBUSY; + goto out; } /* @@ -161,21 +209,35 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) if (rd_addr != (reg_paddr & REG_ADDR_LOW_MASK)) { dev_err(sadi->dev, "read error, reg addr = 0x%x, val = 0x%x\n", reg_paddr, val); - return -EIO; + ret = -EIO; + goto out; } *read_val = val & RD_VALUE_MASK; - return 0; + +out: + hwspin_unlock_irqrestore(sadi->hwlock, &flags); + return ret; } -static int sprd_adi_write(struct sprd_adi *sadi, unsigned long reg, u32 val) +static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val) { + unsigned long reg = sprd_adi_to_vaddr(sadi, reg_paddr); u32 timeout = ADI_FIFO_DRAIN_TIMEOUT; + unsigned long flags; int ret; + ret = hwspin_lock_timeout_irqsave(sadi->hwlock, + ADI_HWSPINLOCK_TIMEOUT, + &flags); + if (ret) { + dev_err(sadi->dev, "get the hw lock failed\n"); + return ret; + } + ret = sprd_adi_drain_fifo(sadi); if (ret < 0) - return ret; + goto out; /* * we should wait for write fifo is empty before writing data to PMIC @@ -192,10 +254,12 @@ static int sprd_adi_write(struct sprd_adi *sadi, unsigned long reg, u32 val) if (timeout == 0) { dev_err(sadi->dev, "write fifo is full\n"); - return -EBUSY; + ret = -EBUSY; } - return 0; +out: + hwspin_unlock_irqrestore(sadi->hwlock, &flags); + return ret; } static int sprd_adi_transfer_one(struct spi_controller *ctlr, @@ -203,7 +267,6 @@ static int sprd_adi_transfer_one(struct spi_controller *ctlr, struct spi_transfer *t) { struct sprd_adi *sadi = spi_controller_get_devdata(ctlr); - unsigned long flags, virt_reg; u32 phy_reg, val; int ret; @@ -214,16 +277,7 @@ static int sprd_adi_transfer_one(struct spi_controller *ctlr, if (ret) return ret; - ret = hwspin_lock_timeout_irqsave(sadi->hwlock, - ADI_HWSPINLOCK_TIMEOUT, - &flags); - if (ret) { - dev_err(sadi->dev, "get the hw lock failed\n"); - return ret; - } - ret = sprd_adi_read(sadi, phy_reg, &val); - hwspin_unlock_irqrestore(sadi->hwlock, &flags); if (ret) return ret; @@ -241,19 +295,8 @@ static int sprd_adi_transfer_one(struct spi_controller *ctlr, if (ret) return ret; - virt_reg = sprd_adi_to_vaddr(sadi, phy_reg); val = *p; - - ret = hwspin_lock_timeout_irqsave(sadi->hwlock, - ADI_HWSPINLOCK_TIMEOUT, - &flags); - if (ret) { - dev_err(sadi->dev, "get the hw lock failed\n"); - return ret; - } - - ret = sprd_adi_write(sadi, virt_reg, val); - hwspin_unlock_irqrestore(sadi->hwlock, &flags); + ret = sprd_adi_write(sadi, phy_reg, val); if (ret) return ret; } else { @@ -264,6 +307,72 @@ static int sprd_adi_transfer_one(struct spi_controller *ctlr, return 0; } +static int sprd_adi_restart_handler(struct notifier_block *this, + unsigned long mode, void *cmd) +{ + struct sprd_adi *sadi = container_of(this, struct sprd_adi, + restart_handler); + u32 val, reboot_mode = 0; + + if (!cmd) + reboot_mode = HWRST_STATUS_NORMAL; + else if (!strncmp(cmd, "recovery", 8)) + reboot_mode = HWRST_STATUS_RECOVERY; + else if (!strncmp(cmd, "alarm", 5)) + reboot_mode = HWRST_STATUS_ALARM; + else if (!strncmp(cmd, "fastsleep", 9)) + reboot_mode = HWRST_STATUS_SLEEP; + else if (!strncmp(cmd, "bootloader", 10)) + reboot_mode = HWRST_STATUS_FASTBOOT; + else if (!strncmp(cmd, "panic", 5)) + reboot_mode = HWRST_STATUS_PANIC; + else if (!strncmp(cmd, "special", 7)) + reboot_mode = HWRST_STATUS_SPECIAL; + else if (!strncmp(cmd, "cftreboot", 9)) + reboot_mode = HWRST_STATUS_CFTREBOOT; + else if (!strncmp(cmd, "autodloader", 11)) + reboot_mode = HWRST_STATUS_AUTODLOADER; + else if (!strncmp(cmd, "iqmode", 6)) + reboot_mode = HWRST_STATUS_IQMODE; + else if (!strncmp(cmd, "sprdisk", 7)) + reboot_mode = HWRST_STATUS_SPRDISK; + else + reboot_mode = HWRST_STATUS_NORMAL; + + /* Record the reboot mode */ + sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val); + val |= reboot_mode; + sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val); + + /* Enable the interface clock of the watchdog */ + sprd_adi_read(sadi, sadi->slave_pbase + PMIC_MODULE_EN, &val); + val |= BIT_WDG_EN; + sprd_adi_write(sadi, sadi->slave_pbase + PMIC_MODULE_EN, val); + + /* Enable the work clock of the watchdog */ + sprd_adi_read(sadi, sadi->slave_pbase + PMIC_CLK_EN, &val); + val |= BIT_WDG_EN; + sprd_adi_write(sadi, sadi->slave_pbase + PMIC_CLK_EN, val); + + /* Unlock the watchdog */ + sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOCK, WDG_UNLOCK_KEY); + + /* Load the watchdog timeout value, 50ms is always enough. */ + sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_LOW, + WDG_LOAD_VAL & WDG_LOAD_MASK); + sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_HIGH, 0); + + /* Start the watchdog to reset system */ + sprd_adi_read(sadi, sadi->slave_pbase + REG_WDG_CTRL, &val); + val |= BIT_WDG_RUN | BIT_WDG_RST; + sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_CTRL, val); + + mdelay(1000); + + dev_emerg(sadi->dev, "Unable to restart system\n"); + return NOTIFY_DONE; +} + static void sprd_adi_hw_init(struct sprd_adi *sadi) { struct device_node *np = sadi->dev->of_node; @@ -377,6 +486,14 @@ static int sprd_adi_probe(struct platform_device *pdev) goto free_hwlock; } + sadi->restart_handler.notifier_call = sprd_adi_restart_handler; + sadi->restart_handler.priority = 128; + ret = register_restart_handler(&sadi->restart_handler); + if (ret) { + dev_err(&pdev->dev, "can not register restart handler\n"); + goto free_hwlock; + } + return 0; free_hwlock: @@ -391,6 +508,7 @@ static int sprd_adi_remove(struct platform_device *pdev) struct spi_controller *ctlr = dev_get_drvdata(&pdev->dev); struct sprd_adi *sadi = spi_controller_get_devdata(ctlr); + unregister_restart_handler(&sadi->restart_handler); hwspin_lock_free(sadi->hwlock); return 0; } diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 3e12d5f87ee4..6f7b946b5ced 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -276,10 +276,10 @@ static unsigned tegra_slink_calculate_curr_xfer_param( tspi->bytes_per_word = DIV_ROUND_UP(bits_per_word, 8); if (bits_per_word == 8 || bits_per_word == 16) { - tspi->is_packed = 1; + tspi->is_packed = true; tspi->words_per_32bit = 32/bits_per_word; } else { - tspi->is_packed = 0; + tspi->is_packed = false; tspi->words_per_32bit = 1; } tspi->packed_size = tegra_slink_get_packed_size(tspi, t); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index b33a727a0158..7b213faa0a2b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -779,8 +779,14 @@ static int spi_map_buf(struct spi_controller *ctlr, struct device *dev, for (i = 0; i < sgs; i++) { if (vmalloced_buf || kmap_buf) { - min = min_t(size_t, - len, desc_len - offset_in_page(buf)); + /* + * Next scatterlist entry size is the minimum between + * the desc_len and the remaining buffer length that + * fits in a page. + */ + min = min_t(size_t, desc_len, + min_t(size_t, len, + PAGE_SIZE - offset_in_page(buf))); if (vmalloced_buf) vm_page = vmalloc_to_page(buf); else @@ -2254,12 +2260,6 @@ void spi_unregister_controller(struct spi_controller *ctlr) mutex_lock(&board_lock); found = idr_find(&spi_master_idr, id); mutex_unlock(&board_lock); - if (found != ctlr) { - dev_dbg(&ctlr->dev, - "attempting to delete unregistered controller [%s]\n", - dev_name(&ctlr->dev)); - return; - } if (ctlr->queued) { if (spi_destroy_queue(ctlr)) dev_err(&ctlr->dev, "queue remove failed\n"); @@ -2272,7 +2272,8 @@ void spi_unregister_controller(struct spi_controller *ctlr) device_unregister(&ctlr->dev); /* free bus id */ mutex_lock(&board_lock); - idr_remove(&spi_master_idr, id); + if (found == ctlr) + idr_remove(&spi_master_idr, id); mutex_unlock(&board_lock); } EXPORT_SYMBOL_GPL(spi_unregister_controller); diff --git a/include/linux/spi/spi_gpio.h b/include/linux/spi/spi_gpio.h index e7bd89a59cd1..9e7e83d8645b 100644 --- a/include/linux/spi/spi_gpio.h +++ b/include/linux/spi/spi_gpio.h @@ -8,64 +8,17 @@ * - id the same as the SPI bus number it implements * - dev.platform data pointing to a struct spi_gpio_platform_data * - * Or, see the driver code for information about speedups that are - * possible on platforms that support inlined access for GPIOs (no - * spi_gpio_platform_data is used). - * - * Use spi_board_info with these busses in the usual way, being sure - * that the controller_data being the GPIO used for each device's - * chipselect: - * - * static struct spi_board_info ... [] = { - * ... - * // this slave uses GPIO 42 for its chipselect - * .controller_data = (void *) 42, - * ... - * // this one uses GPIO 86 for its chipselect - * .controller_data = (void *) 86, - * ... - * }; - * - * If chipselect is not used (there's only one device on the bus), assign - * SPI_GPIO_NO_CHIPSELECT to the controller_data: - * .controller_data = (void *) SPI_GPIO_NO_CHIPSELECT; - * - * If the MISO or MOSI pin is not available then it should be set to - * SPI_GPIO_NO_MISO or SPI_GPIO_NO_MOSI. + * Use spi_board_info with these busses in the usual way. * * If the bitbanged bus is later switched to a "native" controller, * that platform_device and controller_data should be removed. */ -#define SPI_GPIO_NO_CHIPSELECT ((unsigned long)-1l) -#define SPI_GPIO_NO_MISO ((unsigned long)-1l) -#define SPI_GPIO_NO_MOSI ((unsigned long)-1l) - /** * struct spi_gpio_platform_data - parameter for bitbanged SPI master - * @sck: number of the GPIO used for clock output - * @mosi: number of the GPIO used for Master Output, Slave In (MOSI) data - * @miso: number of the GPIO used for Master Input, Slave Output (MISO) data * @num_chipselect: how many slaves to allow - * - * All GPIO signals used with the SPI bus managed through this driver - * (chipselects, MOSI, MISO, SCK) must be configured as GPIOs, instead - * of some alternate function. - * - * It can be convenient to use this driver with pins that have alternate - * functions associated with a "native" SPI controller if a driver for that - * controller is not available, or is missing important functionality. - * - * On platforms which can do so, configure MISO with a weak pullup unless - * there's an external pullup on that signal. That saves power by avoiding - * floating signals. (A weak pulldown would save power too, but many - * drivers expect to see all-ones data as the no slave "response".) */ struct spi_gpio_platform_data { - unsigned sck; - unsigned long mosi; - unsigned long miso; - u16 num_chipselect; }; |