1
0
Fork 0

spi: SPI updates for v4.17

A quiet release for SPI, some fixes and small updates for individual
 drivers with one bigger change from Linus Walleij which coverts the
 bitbanging SPI driver to use the GPIO descriptor API from Linus Walleij.
 Since GPIO descriptors were used by platform data this means there's a
 few changes in arch/ making relevant updates for a few platforms and one
 misc driver that are affected.
 -----BEGIN PGP SIGNATURE-----
 
 iQFHBAABCgAxFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAlrCYDYTHGJyb29uaWVA
 a2VybmVsLm9yZwAKCRAk1otyXVSH0DXhB/9Hueo2D1Pku0iAwq+yIAPvk2N0fyGP
 YWJWbDQGngSZEnU3dUzdfaOHh4MMiMgs0q8hxOYnmkIhhTs7cXsPj8x6rlZP8bee
 TtSEEgHSuHlVWyADquFIel8OCq8BWd7p4aQKqP3LaojCH/wqswxtn4I+RH/xw1Rd
 LIPgU12fxGUpRMO7uGNiMhqqkQDH1ZBFzCUYRPqQk2E+5hyZraQYoROgZkEBPzb1
 EWjLxLxytj/Zj4N5eQkW4BWfX5HKJb9CpwKIIdyNuybr14yC5FR83VxOf9wW4/pG
 39DIn8LtGTkuMRF4Yw5rPlC9KqnLpUDTnQCcOW4lt+z8QtZQ+LP3boxE
 =xNln
 -----END PGP SIGNATURE-----

Merge tag 'spi-v4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi

Pull SPI updates from Mark Brown:
 "A quiet release for SPI, some fixes and small updates for individual
  drivers with one bigger change from Linus Walleij which coverts the
  bitbanging SPI driver to use the GPIO descriptor API from Linus
  Walleij.

  Since GPIO descriptors were used by platform data this means there's a
  few changes in arch/ making relevant updates for a few platforms and
  one misc driver that are affected"

* tag 'spi-v4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (24 commits)
  MAINTAINERS: update Andi's e-mail
  spi: spi-atmel: Use correct enum for DMA transfer direction
  spi: sh-msiof: Document R-Car M3-N support
  spi: sh-msiof: Use correct enum for DMA transfer direction
  spi: sprd: Add the support of restarting the system
  spi: sprd: Simplify the transfer function
  spi: Fix unregistration of controller with fixed SPI bus number
  spi: rspi: use correct enum for DMA transfer direction
  spi: jcore: disable ref_clk after getting its rate
  spi: bcm-qspi: fIX some error handling paths
  spi: pxa2xx: Disable runtime PM if controller registration fails
  spi: tegra20-slink: use true and false for boolean values
  spi: Fix scatterlist elements size in spi_map_buf
  spi: atmel: init FIFOs before spi enable
  spi: orion: Prepare space for per-child options
  spi: orion: Make the error message greppable
  spi: orion: Rework GPIO CS handling
  spi: bcm2835aux: Avoid 64-bit arithmetic in xfer len calc
  spi: spi-gpio: Augment device tree bindings
  spi: spi-gpio: Rewrite to use GPIO descriptors
  ...
zero-colors
Linus Torvalds 2018-04-03 12:06:21 -07:00
commit 75dcc7ef95
30 changed files with 578 additions and 417 deletions

View File

@ -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>

View File

@ -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)

View File

@ -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>;

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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));
}

View File

@ -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();
}

View File

@ -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);

View File

@ -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;

View File

@ -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));

View File

@ -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);

View File

@ -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)

View File

@ -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 {

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);
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);
/* Drive chip select line, if we have one */
if (spi_gpio->has_cs) {
struct gpio_desc *cs = spi_gpio->cs_gpios[spi->chip_select];
/* 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;
}
/*
* 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 (!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;
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)
/*
* 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;
int i;
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)
{
int value;
/* NOTE: SPI_*_GPIO symbols may reference "pdata" */
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;
spi_gpio->sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW);
if (IS_ERR(spi_gpio->mosi))
return PTR_ERR(spi_gpio->mosi);
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]);
}
value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
if (value)
goto free_miso;
goto done;
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;
master = spi_alloc_master(&pdev->dev, sizeof(*spi_gpio));
if (!master)
return -ENOMEM;
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) +
(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;

View File

@ -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;

View File

@ -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:

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
};