mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 10:49:33 +00:00
Merge remote-tracking branches 'spi/topic/atmel', 'spi/topic/bcm-qspi', 'spi/topic/bcm2835aux', 'spi/topic/dw' and 'spi/topic/gpio' into spi-next
This commit is contained in:
commit
70a3550b8c
17 changed files with 313 additions and 325 deletions
|
@ -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>;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
|
|||
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue