From 4969c32bab70d71e07b0a76e1699782857d5aa22 Mon Sep 17 00:00:00 2001 From: Boojin Kim Date: Tue, 19 Jun 2012 13:27:03 +0900 Subject: spi/s3c64xx: Add the use of DMA config operation Config operation is separated from request operation in DMA common operation. Because spi driver can change the DMA config for every transfer. So this patch is using the separated DMA config operation. Signed-off-by: Boojin Kim Signed-off-by: Kyoungil Kim Signed-off-by: Kukjin Kim --- drivers/spi/spi-s3c64xx.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 972a94c58be3..3c36cfaa1b93 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -262,14 +262,24 @@ static void prepare_dma(struct s3c64xx_spi_dma_data *dma, unsigned len, dma_addr_t buf) { struct s3c64xx_spi_driver_data *sdd; - struct samsung_dma_prep_info info; + struct samsung_dma_prep info; + struct samsung_dma_config config; - if (dma->direction == DMA_DEV_TO_MEM) + if (dma->direction == DMA_DEV_TO_MEM) { sdd = container_of((void *)dma, struct s3c64xx_spi_driver_data, rx_dma); - else + config.direction = sdd->rx_dma.direction; + config.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA; + config.width = sdd->cur_bpw / 8; + sdd->ops->config(sdd->rx_dma.ch, &config); + } else { sdd = container_of((void *)dma, struct s3c64xx_spi_driver_data, tx_dma); + config.direction = sdd->tx_dma.direction; + config.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA; + config.width = sdd->cur_bpw / 8; + sdd->ops->config(sdd->tx_dma.ch, &config); + } info.cap = DMA_SLAVE; info.len = len; @@ -284,20 +294,15 @@ static void prepare_dma(struct s3c64xx_spi_dma_data *dma, static int acquire_dma(struct s3c64xx_spi_driver_data *sdd) { - struct samsung_dma_info info; + struct samsung_dma_req req; sdd->ops = samsung_dma_get_ops(); - info.cap = DMA_SLAVE; - info.client = &s3c64xx_spi_dma_client; - info.width = sdd->cur_bpw / 8; - - info.direction = sdd->rx_dma.direction; - info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA; - sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &info); - info.direction = sdd->tx_dma.direction; - info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA; - sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &info); + req.cap = DMA_SLAVE; + req.client = &s3c64xx_spi_dma_client; + + sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &req); + sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &req); return 1; } -- cgit v1.2.3-59-g8ed1b From 2b54be661191532ddf1628c3b151b81ae8743caa Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Fri, 13 Jul 2012 07:15:14 +0900 Subject: spi: s3c64xx: remove unused S3C64XX_SPI_ST_TRLCNTZ macro The macro S3C64XX_SPI_ST_TRLCNTZ is not used and hence it is removed. Signed-off-by: Thomas Abraham Acked-by: Jaswinder Singh Acked-by: Grant Likely Signed-off-by: Kukjin Kim --- drivers/spi/spi-s3c64xx.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 3c36cfaa1b93..6e60eecbfc4f 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -113,10 +113,6 @@ #define S3C64XX_SPI_FBCLK_MSK (3<<0) -#define S3C64XX_SPI_ST_TRLCNTZ(v, i) ((((v) >> (i)->rx_lvl_offset) & \ - (((i)->fifo_lvl_mask + 1))) \ - ? 1 : 0) - #define S3C64XX_SPI_ST_TX_DONE(v, i) (((v) & (1 << (i)->tx_st_done)) ? 1 : 0) #define TX_FIFO_LVL(v, i) (((v) >> 6) & (i)->fifo_lvl_mask) #define RX_FIFO_LVL(v, i) (((v) >> (i)->rx_lvl_offset) & (i)->fifo_lvl_mask) -- cgit v1.2.3-59-g8ed1b From a5238e360b715e9a1bb39d7d3537f78cc9e9e286 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Fri, 13 Jul 2012 07:15:14 +0900 Subject: spi: s3c64xx: move controller information into driver data Platform data is used to specify controller hardware specific information such as the tx/rx fifo level mask and bit offset of rx fifo level. Such information is not suitable to be supplied from device tree. Instead, it can be moved into the driver data and removed from platform data. Signed-off-by: Thomas Abraham Acked-by: Jaswinder Singh Acked-by: Grant Likely Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/clock-exynos4.c | 18 +-- arch/arm/mach-exynos/setup-spi.c | 25 ---- arch/arm/mach-s3c24xx/clock-s3c2416.c | 3 +- arch/arm/mach-s3c24xx/clock-s3c2443.c | 2 +- arch/arm/mach-s3c24xx/common-s3c2443.c | 4 +- arch/arm/mach-s3c24xx/setup-spi.c | 8 -- arch/arm/mach-s3c64xx/clock.c | 20 +-- arch/arm/mach-s3c64xx/setup-spi.c | 13 -- arch/arm/mach-s5p64x0/clock-s5p6440.c | 12 +- arch/arm/mach-s5p64x0/clock-s5p6450.c | 12 +- arch/arm/mach-s5p64x0/setup-spi.c | 16 --- arch/arm/mach-s5pc100/clock.c | 30 ++--- arch/arm/mach-s5pc100/setup-spi.c | 22 ---- arch/arm/mach-s5pv210/clock.c | 14 +-- arch/arm/mach-s5pv210/setup-spi.c | 15 --- arch/arm/plat-samsung/include/plat/s3c64xx-spi.h | 15 --- drivers/spi/spi-s3c64xx.c | 150 +++++++++++++++++++---- 17 files changed, 181 insertions(+), 198 deletions(-) (limited to 'drivers/spi') diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c index bcb7db453145..10a46a9f0ea7 100644 --- a/arch/arm/mach-exynos/clock-exynos4.c +++ b/arch/arm/mach-exynos/clock-exynos4.c @@ -586,17 +586,17 @@ static struct clk exynos4_init_clocks_off[] = { .ctrlbit = (1 << 13), }, { .name = "spi", - .devname = "s3c64xx-spi.0", + .devname = "exynos4210-spi.0", .enable = exynos4_clk_ip_peril_ctrl, .ctrlbit = (1 << 16), }, { .name = "spi", - .devname = "s3c64xx-spi.1", + .devname = "exynos4210-spi.1", .enable = exynos4_clk_ip_peril_ctrl, .ctrlbit = (1 << 17), }, { .name = "spi", - .devname = "s3c64xx-spi.2", + .devname = "exynos4210-spi.2", .enable = exynos4_clk_ip_peril_ctrl, .ctrlbit = (1 << 18), }, { @@ -1245,7 +1245,7 @@ static struct clksrc_clk exynos4_clk_sclk_mmc3 = { static struct clksrc_clk exynos4_clk_sclk_spi0 = { .clk = { .name = "sclk_spi", - .devname = "s3c64xx-spi.0", + .devname = "exynos4210-spi.0", .enable = exynos4_clksrc_mask_peril1_ctrl, .ctrlbit = (1 << 16), }, @@ -1257,7 +1257,7 @@ static struct clksrc_clk exynos4_clk_sclk_spi0 = { static struct clksrc_clk exynos4_clk_sclk_spi1 = { .clk = { .name = "sclk_spi", - .devname = "s3c64xx-spi.1", + .devname = "exynos4210-spi.1", .enable = exynos4_clksrc_mask_peril1_ctrl, .ctrlbit = (1 << 20), }, @@ -1269,7 +1269,7 @@ static struct clksrc_clk exynos4_clk_sclk_spi1 = { static struct clksrc_clk exynos4_clk_sclk_spi2 = { .clk = { .name = "sclk_spi", - .devname = "s3c64xx-spi.2", + .devname = "exynos4210-spi.2", .enable = exynos4_clksrc_mask_peril1_ctrl, .ctrlbit = (1 << 24), }, @@ -1347,9 +1347,9 @@ static struct clk_lookup exynos4_clk_lookup[] = { CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos4_clk_pdma0), CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos4_clk_pdma1), CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos4_clk_mdma1), - CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk0", &exynos4_clk_sclk_spi0.clk), - CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk0", &exynos4_clk_sclk_spi1.clk), - CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk0", &exynos4_clk_sclk_spi2.clk), + CLKDEV_INIT("exynos4210-spi.0", "spi_busclk0", &exynos4_clk_sclk_spi0.clk), + CLKDEV_INIT("exynos4210-spi.1", "spi_busclk0", &exynos4_clk_sclk_spi1.clk), + CLKDEV_INIT("exynos4210-spi.2", "spi_busclk0", &exynos4_clk_sclk_spi2.clk), }; static int xtal_rate; diff --git a/arch/arm/mach-exynos/setup-spi.c b/arch/arm/mach-exynos/setup-spi.c index 833ff40ee0e8..a71ec4db4cf4 100644 --- a/arch/arm/mach-exynos/setup-spi.c +++ b/arch/arm/mach-exynos/setup-spi.c @@ -12,17 +12,8 @@ #include #include -#include #ifdef CONFIG_S3C64XX_DEV_SPI0 -struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = { - .fifo_lvl_mask = 0x1ff, - .rx_lvl_offset = 15, - .high_speed = 1, - .clk_from_cmu = true, - .tx_st_done = 25, -}; - int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) { s3c_gpio_cfgpin(EXYNOS4_GPB(0), S3C_GPIO_SFN(2)); @@ -34,14 +25,6 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) #endif #ifdef CONFIG_S3C64XX_DEV_SPI1 -struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = { - .fifo_lvl_mask = 0x7f, - .rx_lvl_offset = 15, - .high_speed = 1, - .clk_from_cmu = true, - .tx_st_done = 25, -}; - int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) { s3c_gpio_cfgpin(EXYNOS4_GPB(4), S3C_GPIO_SFN(2)); @@ -53,14 +36,6 @@ int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) #endif #ifdef CONFIG_S3C64XX_DEV_SPI2 -struct s3c64xx_spi_info s3c64xx_spi2_pdata __initdata = { - .fifo_lvl_mask = 0x7f, - .rx_lvl_offset = 15, - .high_speed = 1, - .clk_from_cmu = true, - .tx_st_done = 25, -}; - int s3c64xx_spi2_cfg_gpio(struct platform_device *dev) { s3c_gpio_cfgpin(EXYNOS4_GPC1(1), S3C_GPIO_SFN(5)); diff --git a/arch/arm/mach-s3c24xx/clock-s3c2416.c b/arch/arm/mach-s3c24xx/clock-s3c2416.c index 8702ecfaab30..14a81c2317a4 100644 --- a/arch/arm/mach-s3c24xx/clock-s3c2416.c +++ b/arch/arm/mach-s3c24xx/clock-s3c2416.c @@ -144,7 +144,8 @@ static struct clk_lookup s3c2416_clk_lookup[] = { CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &hsmmc0_clk), CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &hsmmc_mux0.clk), CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &hsmmc_mux1.clk), - CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &hsspi_mux.clk), + /* s3c2443-spi.0 is used on s3c2416 and s3c2450 as well */ + CLKDEV_INIT("s3c2443-spi.0", "spi_busclk2", &hsspi_mux.clk), }; void __init s3c2416_init_clocks(int xtal) diff --git a/arch/arm/mach-s3c24xx/clock-s3c2443.c b/arch/arm/mach-s3c24xx/clock-s3c2443.c index a4c5a520d994..7f689ce1be61 100644 --- a/arch/arm/mach-s3c24xx/clock-s3c2443.c +++ b/arch/arm/mach-s3c24xx/clock-s3c2443.c @@ -181,7 +181,7 @@ static struct clk *clks[] __initdata = { static struct clk_lookup s3c2443_clk_lookup[] = { CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_hsmmc), - CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &clk_hsspi.clk), + CLKDEV_INIT("s3c2443-spi.0", "spi_busclk2", &clk_hsspi.clk), }; void __init s3c2443_init_clocks(int xtal) diff --git a/arch/arm/mach-s3c24xx/common-s3c2443.c b/arch/arm/mach-s3c24xx/common-s3c2443.c index aeeb2be283fa..aeb4a24ff3ed 100644 --- a/arch/arm/mach-s3c24xx/common-s3c2443.c +++ b/arch/arm/mach-s3c24xx/common-s3c2443.c @@ -559,7 +559,7 @@ static struct clk hsmmc1_clk = { static struct clk hsspi_clk = { .name = "spi", - .devname = "s3c64xx-spi.0", + .devname = "s3c2443-spi.0", .parent = &clk_p, .enable = s3c2443_clkcon_enable_p, .ctrlbit = S3C2443_PCLKCON_HSSPI, @@ -633,7 +633,7 @@ static struct clk_lookup s3c2443_clk_lookup[] = { CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p), CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_esys_uart.clk), CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &hsmmc1_clk), - CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk0", &hsspi_clk), + CLKDEV_INIT("s3c2443-spi.0", "spi_busclk0", &hsspi_clk), }; void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll, diff --git a/arch/arm/mach-s3c24xx/setup-spi.c b/arch/arm/mach-s3c24xx/setup-spi.c index 5712c85f39b1..42abe157f98f 100644 --- a/arch/arm/mach-s3c24xx/setup-spi.c +++ b/arch/arm/mach-s3c24xx/setup-spi.c @@ -13,19 +13,11 @@ #include #include -#include #include #include #ifdef CONFIG_S3C64XX_DEV_SPI0 -struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = { - .fifo_lvl_mask = 0x7f, - .rx_lvl_offset = 13, - .tx_st_done = 21, - .high_speed = 1, -}; - int s3c64xx_spi0_cfg_gpio(struct platform_device *pdev) { /* enable hsspi bit in misccr */ diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c index 52f079a691cb..28041e83dc82 100644 --- a/arch/arm/mach-s3c64xx/clock.c +++ b/arch/arm/mach-s3c64xx/clock.c @@ -178,13 +178,13 @@ static struct clk init_clocks_off[] = { .ctrlbit = S3C_CLKCON_PCLK_KEYPAD, }, { .name = "spi", - .devname = "s3c64xx-spi.0", + .devname = "s3c6410-spi.0", .parent = &clk_p, .enable = s3c64xx_pclk_ctrl, .ctrlbit = S3C_CLKCON_PCLK_SPI0, }, { .name = "spi", - .devname = "s3c64xx-spi.1", + .devname = "s3c6410-spi.1", .parent = &clk_p, .enable = s3c64xx_pclk_ctrl, .ctrlbit = S3C_CLKCON_PCLK_SPI1, @@ -331,7 +331,7 @@ static struct clk init_clocks_off[] = { static struct clk clk_48m_spi0 = { .name = "spi_48m", - .devname = "s3c64xx-spi.0", + .devname = "s3c6410-spi.0", .parent = &clk_48m, .enable = s3c64xx_sclk_ctrl, .ctrlbit = S3C_CLKCON_SCLK_SPI0_48, @@ -339,7 +339,7 @@ static struct clk clk_48m_spi0 = { static struct clk clk_48m_spi1 = { .name = "spi_48m", - .devname = "s3c64xx-spi.1", + .devname = "s3c6410-spi.1", .parent = &clk_48m, .enable = s3c64xx_sclk_ctrl, .ctrlbit = S3C_CLKCON_SCLK_SPI1_48, @@ -802,7 +802,7 @@ static struct clksrc_clk clk_sclk_mmc2 = { static struct clksrc_clk clk_sclk_spi0 = { .clk = { .name = "spi-bus", - .devname = "s3c64xx-spi.0", + .devname = "s3c6410-spi.0", .ctrlbit = S3C_CLKCON_SCLK_SPI0, .enable = s3c64xx_sclk_ctrl, }, @@ -814,7 +814,7 @@ static struct clksrc_clk clk_sclk_spi0 = { static struct clksrc_clk clk_sclk_spi1 = { .clk = { .name = "spi-bus", - .devname = "s3c64xx-spi.1", + .devname = "s3c6410-spi.1", .ctrlbit = S3C_CLKCON_SCLK_SPI1, .enable = s3c64xx_sclk_ctrl, }, @@ -858,10 +858,10 @@ static struct clk_lookup s3c64xx_clk_lookup[] = { CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk), CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk), CLKDEV_INIT(NULL, "spi_busclk0", &clk_p), - CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk), - CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &clk_48m_spi0), - CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk), - CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk2", &clk_48m_spi1), + CLKDEV_INIT("s3c6410-spi.0", "spi_busclk1", &clk_sclk_spi0.clk), + CLKDEV_INIT("s3c6410-spi.0", "spi_busclk2", &clk_48m_spi0), + CLKDEV_INIT("s3c6410-spi.1", "spi_busclk1", &clk_sclk_spi1.clk), + CLKDEV_INIT("s3c6410-spi.1", "spi_busclk2", &clk_48m_spi1), }; #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1) diff --git a/arch/arm/mach-s3c64xx/setup-spi.c b/arch/arm/mach-s3c64xx/setup-spi.c index d9592ad7a825..ff999d95b370 100644 --- a/arch/arm/mach-s3c64xx/setup-spi.c +++ b/arch/arm/mach-s3c64xx/setup-spi.c @@ -12,15 +12,8 @@ #include #include -#include #ifdef CONFIG_S3C64XX_DEV_SPI0 -struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = { - .fifo_lvl_mask = 0x7f, - .rx_lvl_offset = 13, - .tx_st_done = 21, -}; - int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) { s3c_gpio_cfgall_range(S3C64XX_GPC(0), 3, @@ -30,12 +23,6 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) #endif #ifdef CONFIG_S3C64XX_DEV_SPI1 -struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = { - .fifo_lvl_mask = 0x7f, - .rx_lvl_offset = 13, - .tx_st_done = 21, -}; - int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) { s3c_gpio_cfgall_range(S3C64XX_GPC(4), 3, diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c index ee1e8e7f5631..000445596ec4 100644 --- a/arch/arm/mach-s5p64x0/clock-s5p6440.c +++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c @@ -227,13 +227,13 @@ static struct clk init_clocks_off[] = { .ctrlbit = (1 << 17), }, { .name = "spi", - .devname = "s3c64xx-spi.0", + .devname = "s5p64x0-spi.0", .parent = &clk_pclk_low.clk, .enable = s5p64x0_pclk_ctrl, .ctrlbit = (1 << 21), }, { .name = "spi", - .devname = "s3c64xx-spi.1", + .devname = "s5p64x0-spi.1", .parent = &clk_pclk_low.clk, .enable = s5p64x0_pclk_ctrl, .ctrlbit = (1 << 22), @@ -467,7 +467,7 @@ static struct clksrc_clk clk_sclk_uclk = { static struct clksrc_clk clk_sclk_spi0 = { .clk = { .name = "sclk_spi", - .devname = "s3c64xx-spi.0", + .devname = "s5p64x0-spi.0", .ctrlbit = (1 << 20), .enable = s5p64x0_sclk_ctrl, }, @@ -479,7 +479,7 @@ static struct clksrc_clk clk_sclk_spi0 = { static struct clksrc_clk clk_sclk_spi1 = { .clk = { .name = "sclk_spi", - .devname = "s3c64xx-spi.1", + .devname = "s5p64x0-spi.1", .ctrlbit = (1 << 21), .enable = s5p64x0_sclk_ctrl, }, @@ -519,8 +519,8 @@ static struct clk_lookup s5p6440_clk_lookup[] = { CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_pclk_low.clk), CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk), CLKDEV_INIT(NULL, "spi_busclk0", &clk_p), - CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk), - CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk), + CLKDEV_INIT("s5p64x0-spi.0", "spi_busclk1", &clk_sclk_spi0.clk), + CLKDEV_INIT("s5p64x0-spi.1", "spi_busclk1", &clk_sclk_spi1.clk), CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk), CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk), CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk), diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c index dae6a13f43bb..f3e0ef3d27c9 100644 --- a/arch/arm/mach-s5p64x0/clock-s5p6450.c +++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c @@ -236,13 +236,13 @@ static struct clk init_clocks_off[] = { .ctrlbit = (1 << 17), }, { .name = "spi", - .devname = "s3c64xx-spi.0", + .devname = "s5p64x0-spi.0", .parent = &clk_pclk_low.clk, .enable = s5p64x0_pclk_ctrl, .ctrlbit = (1 << 21), }, { .name = "spi", - .devname = "s3c64xx-spi.1", + .devname = "s5p64x0-spi.1", .parent = &clk_pclk_low.clk, .enable = s5p64x0_pclk_ctrl, .ctrlbit = (1 << 22), @@ -528,7 +528,7 @@ static struct clksrc_clk clk_sclk_uclk = { static struct clksrc_clk clk_sclk_spi0 = { .clk = { .name = "sclk_spi", - .devname = "s3c64xx-spi.0", + .devname = "s5p64x0-spi.0", .ctrlbit = (1 << 20), .enable = s5p64x0_sclk_ctrl, }, @@ -540,7 +540,7 @@ static struct clksrc_clk clk_sclk_spi0 = { static struct clksrc_clk clk_sclk_spi1 = { .clk = { .name = "sclk_spi", - .devname = "s3c64xx-spi.1", + .devname = "s5p64x0-spi.1", .ctrlbit = (1 << 21), .enable = s5p64x0_sclk_ctrl, }, @@ -562,8 +562,8 @@ static struct clk_lookup s5p6450_clk_lookup[] = { CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_pclk_low.clk), CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk), CLKDEV_INIT(NULL, "spi_busclk0", &clk_p), - CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk), - CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk), + CLKDEV_INIT("s5p64x0-spi.0", "spi_busclk1", &clk_sclk_spi0.clk), + CLKDEV_INIT("s5p64x0-spi.1", "spi_busclk1", &clk_sclk_spi1.clk), CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk), CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk), CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk), diff --git a/arch/arm/mach-s5p64x0/setup-spi.c b/arch/arm/mach-s5p64x0/setup-spi.c index e9b841240352..1cf84b524698 100644 --- a/arch/arm/mach-s5p64x0/setup-spi.c +++ b/arch/arm/mach-s5p64x0/setup-spi.c @@ -10,19 +10,9 @@ #include #include -#include - #include -#include -#include #ifdef CONFIG_S3C64XX_DEV_SPI0 -struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = { - .fifo_lvl_mask = 0x1ff, - .rx_lvl_offset = 15, - .tx_st_done = 25, -}; - int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) { if (soc_is_s5p6450()) @@ -36,12 +26,6 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) #endif #ifdef CONFIG_S3C64XX_DEV_SPI1 -struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = { - .fifo_lvl_mask = 0x7f, - .rx_lvl_offset = 15, - .tx_st_done = 25, -}; - int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) { if (soc_is_s5p6450()) diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c index 16eca4ea2010..926219791f0d 100644 --- a/arch/arm/mach-s5pc100/clock.c +++ b/arch/arm/mach-s5pc100/clock.c @@ -564,19 +564,19 @@ static struct clk init_clocks_off[] = { .ctrlbit = (1 << 5), }, { .name = "spi", - .devname = "s3c64xx-spi.0", + .devname = "s5pc100-spi.0", .parent = &clk_div_d1_bus.clk, .enable = s5pc100_d1_4_ctrl, .ctrlbit = (1 << 6), }, { .name = "spi", - .devname = "s3c64xx-spi.1", + .devname = "s5pc100-spi.1", .parent = &clk_div_d1_bus.clk, .enable = s5pc100_d1_4_ctrl, .ctrlbit = (1 << 7), }, { .name = "spi", - .devname = "s3c64xx-spi.2", + .devname = "s5pc100-spi.2", .parent = &clk_div_d1_bus.clk, .enable = s5pc100_d1_4_ctrl, .ctrlbit = (1 << 8), @@ -702,7 +702,7 @@ static struct clk clk_hsmmc0 = { static struct clk clk_48m_spi0 = { .name = "spi_48m", - .devname = "s3c64xx-spi.0", + .devname = "s5pc100-spi.0", .parent = &clk_mout_48m.clk, .enable = s5pc100_sclk0_ctrl, .ctrlbit = (1 << 7), @@ -710,7 +710,7 @@ static struct clk clk_48m_spi0 = { static struct clk clk_48m_spi1 = { .name = "spi_48m", - .devname = "s3c64xx-spi.1", + .devname = "s5pc100-spi.1", .parent = &clk_mout_48m.clk, .enable = s5pc100_sclk0_ctrl, .ctrlbit = (1 << 8), @@ -718,7 +718,7 @@ static struct clk clk_48m_spi1 = { static struct clk clk_48m_spi2 = { .name = "spi_48m", - .devname = "s3c64xx-spi.2", + .devname = "s5pc100-spi.2", .parent = &clk_mout_48m.clk, .enable = s5pc100_sclk0_ctrl, .ctrlbit = (1 << 9), @@ -1085,7 +1085,7 @@ static struct clksrc_clk clk_sclk_mmc2 = { static struct clksrc_clk clk_sclk_spi0 = { .clk = { .name = "sclk_spi", - .devname = "s3c64xx-spi.0", + .devname = "s5pc100-spi.0", .ctrlbit = (1 << 4), .enable = s5pc100_sclk0_ctrl, }, @@ -1097,7 +1097,7 @@ static struct clksrc_clk clk_sclk_spi0 = { static struct clksrc_clk clk_sclk_spi1 = { .clk = { .name = "sclk_spi", - .devname = "s3c64xx-spi.1", + .devname = "s5pc100-spi.1", .ctrlbit = (1 << 5), .enable = s5pc100_sclk0_ctrl, }, @@ -1109,7 +1109,7 @@ static struct clksrc_clk clk_sclk_spi1 = { static struct clksrc_clk clk_sclk_spi2 = { .clk = { .name = "sclk_spi", - .devname = "s3c64xx-spi.2", + .devname = "s5pc100-spi.2", .ctrlbit = (1 << 6), .enable = s5pc100_sclk0_ctrl, }, @@ -1315,12 +1315,12 @@ static struct clk_lookup s5pc100_clk_lookup[] = { CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk), CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk), CLKDEV_INIT(NULL, "spi_busclk0", &clk_p), - CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_48m_spi0), - CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &clk_sclk_spi0.clk), - CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_48m_spi1), - CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk2", &clk_sclk_spi1.clk), - CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk1", &clk_48m_spi2), - CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk2", &clk_sclk_spi2.clk), + CLKDEV_INIT("s5pc100-spi.0", "spi_busclk1", &clk_48m_spi0), + CLKDEV_INIT("s5pc100-spi.0", "spi_busclk2", &clk_sclk_spi0.clk), + CLKDEV_INIT("s5pc100-spi.1", "spi_busclk1", &clk_48m_spi1), + CLKDEV_INIT("s5pc100-spi.1", "spi_busclk2", &clk_sclk_spi1.clk), + CLKDEV_INIT("s5pc100-spi.2", "spi_busclk1", &clk_48m_spi2), + CLKDEV_INIT("s5pc100-spi.2", "spi_busclk2", &clk_sclk_spi2.clk), }; void __init s5pc100_register_clocks(void) diff --git a/arch/arm/mach-s5pc100/setup-spi.c b/arch/arm/mach-s5pc100/setup-spi.c index 431a6f747caa..4b42718948a4 100644 --- a/arch/arm/mach-s5pc100/setup-spi.c +++ b/arch/arm/mach-s5pc100/setup-spi.c @@ -12,16 +12,8 @@ #include #include -#include #ifdef CONFIG_S3C64XX_DEV_SPI0 -struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = { - .fifo_lvl_mask = 0x7f, - .rx_lvl_offset = 13, - .high_speed = 1, - .tx_st_done = 21, -}; - int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) { s3c_gpio_cfgall_range(S5PC100_GPB(0), 3, @@ -31,13 +23,6 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) #endif #ifdef CONFIG_S3C64XX_DEV_SPI1 -struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = { - .fifo_lvl_mask = 0x7f, - .rx_lvl_offset = 13, - .high_speed = 1, - .tx_st_done = 21, -}; - int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) { s3c_gpio_cfgall_range(S5PC100_GPB(4), 3, @@ -47,13 +32,6 @@ int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) #endif #ifdef CONFIG_S3C64XX_DEV_SPI2 -struct s3c64xx_spi_info s3c64xx_spi2_pdata __initdata = { - .fifo_lvl_mask = 0x7f, - .rx_lvl_offset = 13, - .high_speed = 1, - .tx_st_done = 21, -}; - int s3c64xx_spi2_cfg_gpio(struct platform_device *dev) { s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(3)); diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 09609d50961d..fcdf52dbcc49 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -445,19 +445,19 @@ static struct clk init_clocks_off[] = { .ctrlbit = (1 << 11), }, { .name = "spi", - .devname = "s3c64xx-spi.0", + .devname = "s5pv210-spi.0", .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<12), }, { .name = "spi", - .devname = "s3c64xx-spi.1", + .devname = "s5pv210-spi.1", .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<13), }, { .name = "spi", - .devname = "s3c64xx-spi.2", + .devname = "s5pv210-spi.2", .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<14), @@ -1035,7 +1035,7 @@ static struct clksrc_clk clk_sclk_mmc3 = { static struct clksrc_clk clk_sclk_spi0 = { .clk = { .name = "sclk_spi", - .devname = "s3c64xx-spi.0", + .devname = "s5pv210-spi.0", .enable = s5pv210_clk_mask0_ctrl, .ctrlbit = (1 << 16), }, @@ -1047,7 +1047,7 @@ static struct clksrc_clk clk_sclk_spi0 = { static struct clksrc_clk clk_sclk_spi1 = { .clk = { .name = "sclk_spi", - .devname = "s3c64xx-spi.1", + .devname = "s5pv210-spi.1", .enable = s5pv210_clk_mask0_ctrl, .ctrlbit = (1 << 17), }, @@ -1331,8 +1331,8 @@ static struct clk_lookup s5pv210_clk_lookup[] = { CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk), CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &clk_sclk_mmc3.clk), CLKDEV_INIT(NULL, "spi_busclk0", &clk_p), - CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk), - CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk), + CLKDEV_INIT("s5pv210-spi.0", "spi_busclk1", &clk_sclk_spi0.clk), + CLKDEV_INIT("s5pv210-spi.1", "spi_busclk1", &clk_sclk_spi1.clk), }; void __init s5pv210_register_clocks(void) diff --git a/arch/arm/mach-s5pv210/setup-spi.c b/arch/arm/mach-s5pv210/setup-spi.c index f43c5048a37d..2cd66a632791 100644 --- a/arch/arm/mach-s5pv210/setup-spi.c +++ b/arch/arm/mach-s5pv210/setup-spi.c @@ -12,16 +12,8 @@ #include #include -#include #ifdef CONFIG_S3C64XX_DEV_SPI0 -struct s3c64xx_spi_info s3c64xx_spi0_pdata = { - .fifo_lvl_mask = 0x1ff, - .rx_lvl_offset = 15, - .high_speed = 1, - .tx_st_done = 25, -}; - int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) { s3c_gpio_cfgpin(S5PV210_GPB(0), S3C_GPIO_SFN(2)); @@ -33,13 +25,6 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) #endif #ifdef CONFIG_S3C64XX_DEV_SPI1 -struct s3c64xx_spi_info s3c64xx_spi1_pdata = { - .fifo_lvl_mask = 0x7f, - .rx_lvl_offset = 15, - .high_speed = 1, - .tx_st_done = 25, -}; - int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) { s3c_gpio_cfgpin(S5PV210_GPB(4), S3C_GPIO_SFN(2)); diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h index fa95e9a00972..4e9b9c314a29 100644 --- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h +++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h @@ -33,28 +33,13 @@ struct s3c64xx_spi_csinfo { /** * struct s3c64xx_spi_info - SPI Controller defining structure * @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field. - * @clk_from_cmu: If the SPI clock/prescalar control block is present - * by the platform's clock-management-unit and not in SPI controller. * @num_cs: Number of CS this controller emulates. * @cfg_gpio: Configure pins for this SPI controller. - * @fifo_lvl_mask: All tx fifo_lvl fields start at offset-6 - * @rx_lvl_offset: Depends on tx fifo_lvl field and bus number - * @high_speed: If the controller supports HIGH_SPEED_EN bit - * @tx_st_done: Depends on tx fifo_lvl field */ struct s3c64xx_spi_info { int src_clk_nr; - bool clk_from_cmu; - int num_cs; - int (*cfg_gpio)(struct platform_device *pdev); - - /* Following two fields are for future compatibility */ - int fifo_lvl_mask; - int rx_lvl_offset; - int high_speed; - int tx_st_done; }; /** diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 6e60eecbfc4f..8698618e56fe 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -31,6 +31,8 @@ #include #include +#define MAX_SPI_PORTS 3 + /* Registers and bit-fields */ #define S3C64XX_SPI_CH_CFG 0x00 @@ -113,9 +115,12 @@ #define S3C64XX_SPI_FBCLK_MSK (3<<0) -#define S3C64XX_SPI_ST_TX_DONE(v, i) (((v) & (1 << (i)->tx_st_done)) ? 1 : 0) -#define TX_FIFO_LVL(v, i) (((v) >> 6) & (i)->fifo_lvl_mask) -#define RX_FIFO_LVL(v, i) (((v) >> (i)->rx_lvl_offset) & (i)->fifo_lvl_mask) +#define FIFO_LVL_MASK(i) ((i)->port_conf->fifo_lvl_mask[i->port_id]) +#define S3C64XX_SPI_ST_TX_DONE(v, i) (((v) & \ + (1 << (i)->port_conf->tx_st_done)) ? 1 : 0) +#define TX_FIFO_LVL(v, i) (((v) >> 6) & FIFO_LVL_MASK(i)) +#define RX_FIFO_LVL(v, i) (((v) >> (i)->port_conf->rx_lvl_offset) & \ + FIFO_LVL_MASK(i)) #define S3C64XX_SPI_MAX_TRAILCNT 0x3ff #define S3C64XX_SPI_TRAILCNT_OFF 19 @@ -133,6 +138,28 @@ struct s3c64xx_spi_dma_data { enum dma_ch dmach; }; +/** + * struct s3c64xx_spi_info - SPI Controller hardware info + * @fifo_lvl_mask: Bit-mask for {TX|RX}_FIFO_LVL bits in SPI_STATUS register. + * @rx_lvl_offset: Bit offset of RX_FIFO_LVL bits in SPI_STATUS regiter. + * @tx_st_done: Bit offset of TX_DONE bit in SPI_STATUS regiter. + * @high_speed: True, if the controller supports HIGH_SPEED_EN bit. + * @clk_from_cmu: True, if the controller does not include a clock mux and + * prescaler unit. + * + * The Samsung s3c64xx SPI controller are used on various Samsung SoC's but + * differ in some aspects such as the size of the fifo and spi bus clock + * setup. Such differences are specified to the driver using this structure + * which is provided as driver data to the driver. + */ +struct s3c64xx_spi_port_config { + int fifo_lvl_mask[MAX_SPI_PORTS]; + int rx_lvl_offset; + int tx_st_done; + bool high_speed; + bool clk_from_cmu; +}; + /** * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver. * @clk: Pointer to the spi clock. @@ -171,6 +198,8 @@ struct s3c64xx_spi_driver_data { struct s3c64xx_spi_dma_data rx_dma; struct s3c64xx_spi_dma_data tx_dma; struct samsung_dma_ops *ops; + struct s3c64xx_spi_port_config *port_conf; + unsigned int port_id; }; static struct s3c2410_dma_client s3c64xx_spi_dma_client = { @@ -179,7 +208,6 @@ static struct s3c2410_dma_client s3c64xx_spi_dma_client = { static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) { - struct s3c64xx_spi_info *sci = sdd->cntrlr_info; void __iomem *regs = sdd->regs; unsigned long loops; u32 val; @@ -195,7 +223,7 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) loops = msecs_to_loops(1); do { val = readl(regs + S3C64XX_SPI_STATUS); - } while (TX_FIFO_LVL(val, sci) && loops--); + } while (TX_FIFO_LVL(val, sdd) && loops--); if (loops == 0) dev_warn(&sdd->pdev->dev, "Timed out flushing TX FIFO\n"); @@ -204,7 +232,7 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) loops = msecs_to_loops(1); do { val = readl(regs + S3C64XX_SPI_STATUS); - if (RX_FIFO_LVL(val, sci)) + if (RX_FIFO_LVL(val, sdd)) readl(regs + S3C64XX_SPI_RX_DATA); else break; @@ -307,7 +335,6 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, struct spi_device *spi, struct spi_transfer *xfer, int dma_mode) { - struct s3c64xx_spi_info *sci = sdd->cntrlr_info; void __iomem *regs = sdd->regs; u32 modecfg, chcfg; @@ -357,7 +384,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, if (xfer->rx_buf != NULL) { sdd->state |= RXBUSY; - if (sci->high_speed && sdd->cur_speed >= 30000000UL + if (sdd->port_conf->high_speed && sdd->cur_speed >= 30000000UL && !(sdd->cur_mode & SPI_CPHA)) chcfg |= S3C64XX_SPI_CH_HS_EN; @@ -397,7 +424,6 @@ static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd, static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, struct spi_transfer *xfer, int dma_mode) { - struct s3c64xx_spi_info *sci = sdd->cntrlr_info; void __iomem *regs = sdd->regs; unsigned long val; int ms; @@ -414,7 +440,7 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, val = msecs_to_loops(ms); do { status = readl(regs + S3C64XX_SPI_STATUS); - } while (RX_FIFO_LVL(status, sci) < xfer->len && --val); + } while (RX_FIFO_LVL(status, sdd) < xfer->len && --val); } if (!val) @@ -433,8 +459,8 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, if (xfer->rx_buf == NULL) { val = msecs_to_loops(10); status = readl(regs + S3C64XX_SPI_STATUS); - while ((TX_FIFO_LVL(status, sci) - || !S3C64XX_SPI_ST_TX_DONE(status, sci)) + while ((TX_FIFO_LVL(status, sdd) + || !S3C64XX_SPI_ST_TX_DONE(status, sdd)) && --val) { cpu_relax(); status = readl(regs + S3C64XX_SPI_STATUS); @@ -483,12 +509,11 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd, static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) { - struct s3c64xx_spi_info *sci = sdd->cntrlr_info; void __iomem *regs = sdd->regs; u32 val; /* Disable Clock */ - if (sci->clk_from_cmu) { + if (sdd->port_conf->clk_from_cmu) { clk_disable(sdd->src_clk); } else { val = readl(regs + S3C64XX_SPI_CLK_CFG); @@ -532,7 +557,7 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) writel(val, regs + S3C64XX_SPI_MODE_CFG); - if (sci->clk_from_cmu) { + if (sdd->port_conf->clk_from_cmu) { /* Configure Clock */ /* There is half-multiplier before the SPI */ clk_set_rate(sdd->src_clk, sdd->cur_speed * 2); @@ -558,7 +583,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd, struct spi_message *msg) { - struct s3c64xx_spi_info *sci = sdd->cntrlr_info; struct device *dev = &sdd->pdev->dev; struct spi_transfer *xfer; @@ -574,7 +598,7 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd, /* Map until end or first fail */ list_for_each_entry(xfer, &msg->transfers, transfer_list) { - if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1)) + if (xfer->len <= ((FIFO_LVL_MASK(sdd) >> 1) + 1)) continue; if (xfer->tx_buf != NULL) { @@ -608,7 +632,6 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd, static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd, struct spi_message *msg) { - struct s3c64xx_spi_info *sci = sdd->cntrlr_info; struct device *dev = &sdd->pdev->dev; struct spi_transfer *xfer; @@ -617,7 +640,7 @@ static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd, list_for_each_entry(xfer, &msg->transfers, transfer_list) { - if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1)) + if (xfer->len <= ((FIFO_LVL_MASK(sdd) >> 1) + 1)) continue; if (xfer->rx_buf != NULL @@ -636,7 +659,6 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, struct spi_message *msg) { struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); - struct s3c64xx_spi_info *sci = sdd->cntrlr_info; struct spi_device *spi = msg->spi; struct s3c64xx_spi_csinfo *cs = spi->controller_data; struct spi_transfer *xfer; @@ -691,7 +713,7 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, } /* Polling method for xfers not bigger than FIFO capacity */ - if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1)) + if (xfer->len <= ((FIFO_LVL_MASK(sdd) >> 1) + 1)) use_dma = 0; else use_dma = 1; @@ -845,7 +867,7 @@ static int s3c64xx_spi_setup(struct spi_device *spi) pm_runtime_get_sync(&sdd->pdev->dev); /* Check if we can provide the requested rate */ - if (!sci->clk_from_cmu) { + if (!sdd->port_conf->clk_from_cmu) { u32 psr, speed; /* Max possible */ @@ -926,7 +948,7 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel) /* Disable Interrupts - we use Polling if not DMA mode */ writel(0, regs + S3C64XX_SPI_INT_EN); - if (!sci->clk_from_cmu) + if (!sdd->port_conf->clk_from_cmu) writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT, regs + S3C64XX_SPI_CLK_CFG); writel(0, regs + S3C64XX_SPI_MODE_CFG); @@ -947,6 +969,13 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel) flush_fifo(sdd); } +static inline struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config( + struct platform_device *pdev) +{ + return (struct s3c64xx_spi_port_config *) + platform_get_device_id(pdev)->driver_data; +} + static int __init s3c64xx_spi_probe(struct platform_device *pdev) { struct resource *mem_res, *dmatx_res, *dmarx_res; @@ -1005,6 +1034,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, master); sdd = spi_master_get_devdata(master); + sdd->port_conf = s3c64xx_spi_get_port_config(pdev); sdd->master = master; sdd->cntrlr_info = sci; sdd->pdev = pdev; @@ -1013,10 +1043,11 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) sdd->tx_dma.direction = DMA_MEM_TO_DEV; sdd->rx_dma.dmach = dmarx_res->start; sdd->rx_dma.direction = DMA_DEV_TO_MEM; + sdd->port_id = pdev->id; sdd->cur_bpw = 8; - master->bus_num = pdev->id; + master->bus_num = sdd->port_id; master->setup = s3c64xx_spi_setup; master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; master->transfer_one_message = s3c64xx_spi_transfer_one_message; @@ -1076,7 +1107,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) } /* Setup Deufult Mode */ - s3c64xx_spi_hwinit(sdd, pdev->id); + s3c64xx_spi_hwinit(sdd, sdd->port_id); spin_lock_init(&sdd->lock); init_completion(&sdd->xfer_completion); @@ -1101,7 +1132,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d " "with %d Slaves attached\n", - pdev->id, master->num_chipselect); + sdd->port_id, master->num_chipselect); dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n", mem_res->end, mem_res->start, sdd->rx_dma.dmach, sdd->tx_dma.dmach); @@ -1194,7 +1225,7 @@ static int s3c64xx_spi_resume(struct device *dev) clk_enable(sdd->src_clk); clk_enable(sdd->clk); - s3c64xx_spi_hwinit(sdd, pdev->id); + s3c64xx_spi_hwinit(sdd, sdd->port_id); spi_master_resume(master); @@ -1232,6 +1263,70 @@ static const struct dev_pm_ops s3c64xx_spi_pm = { s3c64xx_spi_runtime_resume, NULL) }; +struct s3c64xx_spi_port_config s3c2443_spi_port_config = { + .fifo_lvl_mask = { 0x7f }, + .rx_lvl_offset = 13, + .tx_st_done = 21, + .high_speed = true, +}; + +struct s3c64xx_spi_port_config s3c6410_spi_port_config = { + .fifo_lvl_mask = { 0x7f, 0x7F }, + .rx_lvl_offset = 13, + .tx_st_done = 21, +}; + +struct s3c64xx_spi_port_config s5p64x0_spi_port_config = { + .fifo_lvl_mask = { 0x1ff, 0x7F }, + .rx_lvl_offset = 15, + .tx_st_done = 25, +}; + +struct s3c64xx_spi_port_config s5pc100_spi_port_config = { + .fifo_lvl_mask = { 0x7f, 0x7F }, + .rx_lvl_offset = 13, + .tx_st_done = 21, + .high_speed = true, +}; + +struct s3c64xx_spi_port_config s5pv210_spi_port_config = { + .fifo_lvl_mask = { 0x1ff, 0x7F }, + .rx_lvl_offset = 15, + .tx_st_done = 25, + .high_speed = true, +}; + +struct s3c64xx_spi_port_config exynos4_spi_port_config = { + .fifo_lvl_mask = { 0x1ff, 0x7F, 0x7F }, + .rx_lvl_offset = 15, + .tx_st_done = 25, + .high_speed = true, + .clk_from_cmu = true, +}; + +static struct platform_device_id s3c64xx_spi_driver_ids[] = { + { + .name = "s3c2443-spi", + .driver_data = (kernel_ulong_t)&s3c2443_spi_port_config, + }, { + .name = "s3c6410-spi", + .driver_data = (kernel_ulong_t)&s3c6410_spi_port_config, + }, { + .name = "s5p64x0-spi", + .driver_data = (kernel_ulong_t)&s5p64x0_spi_port_config, + }, { + .name = "s5pc100-spi", + .driver_data = (kernel_ulong_t)&s5pc100_spi_port_config, + }, { + .name = "s5pv210-spi", + .driver_data = (kernel_ulong_t)&s5pv210_spi_port_config, + }, { + .name = "exynos4210-spi", + .driver_data = (kernel_ulong_t)&exynos4_spi_port_config, + }, + { }, +}; + static struct platform_driver s3c64xx_spi_driver = { .driver = { .name = "s3c64xx-spi", @@ -1239,6 +1334,7 @@ static struct platform_driver s3c64xx_spi_driver = { .pm = &s3c64xx_spi_pm, }, .remove = s3c64xx_spi_remove, + .id_table = s3c64xx_spi_driver_ids, }; MODULE_ALIAS("platform:s3c64xx-spi"); -- cgit v1.2.3-59-g8ed1b From 868dee91a5f96dfbc97b2cd582614cdc339ec305 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Fri, 13 Jul 2012 07:15:14 +0900 Subject: ARM: SAMSUNG: Remove pdev pointer parameter from spi gpio setup functions The platform data pointer that is passed to the spi gpio setup functions is not used. Hence, this parameter is removed from all the spi gpio setup functions. Signed-off-by: Thomas Abraham Acked-by: Jaswinder Singh Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/setup-spi.c | 8 +++----- arch/arm/mach-s3c24xx/setup-spi.c | 2 +- arch/arm/mach-s3c64xx/setup-spi.c | 6 ++---- arch/arm/mach-s5p64x0/setup-spi.c | 5 ++--- arch/arm/mach-s5pc100/setup-spi.c | 8 +++----- arch/arm/mach-s5pv210/setup-spi.c | 6 ++---- arch/arm/plat-samsung/include/plat/s3c64xx-spi.h | 8 ++++---- drivers/spi/spi-s3c64xx.c | 5 ++--- 8 files changed, 19 insertions(+), 29 deletions(-) (limited to 'drivers/spi') diff --git a/arch/arm/mach-exynos/setup-spi.c b/arch/arm/mach-exynos/setup-spi.c index a71ec4db4cf4..4999829d1c6e 100644 --- a/arch/arm/mach-exynos/setup-spi.c +++ b/arch/arm/mach-exynos/setup-spi.c @@ -9,12 +9,10 @@ */ #include -#include - #include #ifdef CONFIG_S3C64XX_DEV_SPI0 -int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) +int s3c64xx_spi0_cfg_gpio(void) { s3c_gpio_cfgpin(EXYNOS4_GPB(0), S3C_GPIO_SFN(2)); s3c_gpio_setpull(EXYNOS4_GPB(0), S3C_GPIO_PULL_UP); @@ -25,7 +23,7 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) #endif #ifdef CONFIG_S3C64XX_DEV_SPI1 -int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) +int s3c64xx_spi1_cfg_gpio(void) { s3c_gpio_cfgpin(EXYNOS4_GPB(4), S3C_GPIO_SFN(2)); s3c_gpio_setpull(EXYNOS4_GPB(4), S3C_GPIO_PULL_UP); @@ -36,7 +34,7 @@ int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) #endif #ifdef CONFIG_S3C64XX_DEV_SPI2 -int s3c64xx_spi2_cfg_gpio(struct platform_device *dev) +int s3c64xx_spi2_cfg_gpio(void) { s3c_gpio_cfgpin(EXYNOS4_GPC1(1), S3C_GPIO_SFN(5)); s3c_gpio_setpull(EXYNOS4_GPC1(1), S3C_GPIO_PULL_UP); diff --git a/arch/arm/mach-s3c24xx/setup-spi.c b/arch/arm/mach-s3c24xx/setup-spi.c index 42abe157f98f..3d47e023ce94 100644 --- a/arch/arm/mach-s3c24xx/setup-spi.c +++ b/arch/arm/mach-s3c24xx/setup-spi.c @@ -18,7 +18,7 @@ #include #ifdef CONFIG_S3C64XX_DEV_SPI0 -int s3c64xx_spi0_cfg_gpio(struct platform_device *pdev) +int s3c64xx_spi0_cfg_gpio(void) { /* enable hsspi bit in misccr */ s3c2410_modify_misccr(S3C2416_MISCCR_HSSPI_EN2, 1); diff --git a/arch/arm/mach-s3c64xx/setup-spi.c b/arch/arm/mach-s3c64xx/setup-spi.c index ff999d95b370..4dc53450d715 100644 --- a/arch/arm/mach-s3c64xx/setup-spi.c +++ b/arch/arm/mach-s3c64xx/setup-spi.c @@ -9,12 +9,10 @@ */ #include -#include - #include #ifdef CONFIG_S3C64XX_DEV_SPI0 -int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) +int s3c64xx_spi0_cfg_gpio(void) { s3c_gpio_cfgall_range(S3C64XX_GPC(0), 3, S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); @@ -23,7 +21,7 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) #endif #ifdef CONFIG_S3C64XX_DEV_SPI1 -int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) +int s3c64xx_spi1_cfg_gpio(void) { s3c_gpio_cfgall_range(S3C64XX_GPC(4), 3, S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); diff --git a/arch/arm/mach-s5p64x0/setup-spi.c b/arch/arm/mach-s5p64x0/setup-spi.c index 1cf84b524698..7664356720ca 100644 --- a/arch/arm/mach-s5p64x0/setup-spi.c +++ b/arch/arm/mach-s5p64x0/setup-spi.c @@ -9,11 +9,10 @@ */ #include -#include #include #ifdef CONFIG_S3C64XX_DEV_SPI0 -int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) +int s3c64xx_spi0_cfg_gpio(void) { if (soc_is_s5p6450()) s3c_gpio_cfgall_range(S5P6450_GPC(0), 3, @@ -26,7 +25,7 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) #endif #ifdef CONFIG_S3C64XX_DEV_SPI1 -int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) +int s3c64xx_spi1_cfg_gpio(void) { if (soc_is_s5p6450()) s3c_gpio_cfgall_range(S5P6450_GPC(4), 3, diff --git a/arch/arm/mach-s5pc100/setup-spi.c b/arch/arm/mach-s5pc100/setup-spi.c index 4b42718948a4..183567961de1 100644 --- a/arch/arm/mach-s5pc100/setup-spi.c +++ b/arch/arm/mach-s5pc100/setup-spi.c @@ -9,12 +9,10 @@ */ #include -#include - #include #ifdef CONFIG_S3C64XX_DEV_SPI0 -int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) +int s3c64xx_spi0_cfg_gpio(void) { s3c_gpio_cfgall_range(S5PC100_GPB(0), 3, S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); @@ -23,7 +21,7 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) #endif #ifdef CONFIG_S3C64XX_DEV_SPI1 -int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) +int s3c64xx_spi1_cfg_gpio(void) { s3c_gpio_cfgall_range(S5PC100_GPB(4), 3, S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); @@ -32,7 +30,7 @@ int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) #endif #ifdef CONFIG_S3C64XX_DEV_SPI2 -int s3c64xx_spi2_cfg_gpio(struct platform_device *dev) +int s3c64xx_spi2_cfg_gpio(void) { s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(3)); s3c_gpio_setpull(S5PC100_GPG3(0), S3C_GPIO_PULL_UP); diff --git a/arch/arm/mach-s5pv210/setup-spi.c b/arch/arm/mach-s5pv210/setup-spi.c index 2cd66a632791..81aecc162f82 100644 --- a/arch/arm/mach-s5pv210/setup-spi.c +++ b/arch/arm/mach-s5pv210/setup-spi.c @@ -9,12 +9,10 @@ */ #include -#include - #include #ifdef CONFIG_S3C64XX_DEV_SPI0 -int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) +int s3c64xx_spi0_cfg_gpio(void) { s3c_gpio_cfgpin(S5PV210_GPB(0), S3C_GPIO_SFN(2)); s3c_gpio_setpull(S5PV210_GPB(0), S3C_GPIO_PULL_UP); @@ -25,7 +23,7 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) #endif #ifdef CONFIG_S3C64XX_DEV_SPI1 -int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) +int s3c64xx_spi1_cfg_gpio(void) { s3c_gpio_cfgpin(S5PV210_GPB(4), S3C_GPIO_SFN(2)); s3c_gpio_setpull(S5PV210_GPB(4), S3C_GPIO_PULL_UP); diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h index 4e9b9c314a29..89dbaee43800 100644 --- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h +++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h @@ -39,7 +39,7 @@ struct s3c64xx_spi_csinfo { struct s3c64xx_spi_info { int src_clk_nr; int num_cs; - int (*cfg_gpio)(struct platform_device *pdev); + int (*cfg_gpio)(void); }; /** @@ -60,9 +60,9 @@ extern void s3c64xx_spi2_set_platdata(struct s3c64xx_spi_info *pd, int src_clk_nr, int num_cs); /* defined by architecture to configure gpio */ -extern int s3c64xx_spi0_cfg_gpio(struct platform_device *dev); -extern int s3c64xx_spi1_cfg_gpio(struct platform_device *dev); -extern int s3c64xx_spi2_cfg_gpio(struct platform_device *dev); +extern int s3c64xx_spi0_cfg_gpio(void); +extern int s3c64xx_spi1_cfg_gpio(void); +extern int s3c64xx_spi2_cfg_gpio(void); extern struct s3c64xx_spi_info s3c64xx_spi0_pdata; extern struct s3c64xx_spi_info s3c64xx_spi1_pdata; diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 8698618e56fe..0a9e43e635aa 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1071,7 +1071,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) goto err1; } - if (sci->cfg_gpio == NULL || sci->cfg_gpio(pdev)) { + if (sci->cfg_gpio == NULL || sci->cfg_gpio()) { dev_err(&pdev->dev, "Unable to config gpio\n"); ret = -EBUSY; goto err2; @@ -1214,12 +1214,11 @@ static int s3c64xx_spi_suspend(struct device *dev) static int s3c64xx_spi_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); struct s3c64xx_spi_info *sci = sdd->cntrlr_info; - sci->cfg_gpio(pdev); + sci->cfg_gpio(); /* Enable the clock */ clk_enable(sdd->src_clk); -- cgit v1.2.3-59-g8ed1b From 1c20c200ef96c50b3075f71220c8c8bc018a93c8 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Fri, 13 Jul 2012 07:15:14 +0900 Subject: spi: s3c64xx: Remove the 'set_level' callback from controller data The set_level callback in the controller data, which is used to configure the slave select line, cannot be supported when migrating the driver to device tree based discovery. Since all the platforms currently use gpio as the slave select line, this callback can be removed from the controller data and replaced with call to gpio_set_value in the driver. Signed-off-by: Thomas Abraham Acked-by: Jaswinder Singh Acked-by: Grant Likely Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/include/plat/s3c64xx-spi.h | 2 -- drivers/spi/spi-s3c64xx.c | 31 ++++++++++++++++++++---- 2 files changed, 26 insertions(+), 7 deletions(-) (limited to 'drivers/spi') diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h index c818a7c18929..ceba18d23a5a 100644 --- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h +++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h @@ -18,7 +18,6 @@ struct platform_device; * @fb_delay: Slave specific feedback delay. * Refer to FB_CLK_SEL register definition in SPI chapter. * @line: Custom 'identity' of the CS line. - * @set_level: CS line control. * * This is per SPI-Slave Chipselect information. * Allocate and initialize one in machine init code and make the @@ -27,7 +26,6 @@ struct platform_device; struct s3c64xx_spi_csinfo { u8 fb_delay; unsigned line; - void (*set_level)(unsigned line_id, int lvl); }; /** diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 0a9e43e635aa..e4182ea2f306 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -411,14 +412,14 @@ static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd, if (sdd->tgl_spi != spi) { /* if last mssg on diff device */ /* Deselect the last toggled device */ cs = sdd->tgl_spi->controller_data; - cs->set_level(cs->line, - spi->mode & SPI_CS_HIGH ? 0 : 1); + gpio_set_value(cs->line, + spi->mode & SPI_CS_HIGH ? 0 : 1); } sdd->tgl_spi = NULL; } cs = spi->controller_data; - cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0); + gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0); } static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, @@ -504,7 +505,7 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd, if (sdd->tgl_spi == spi) sdd->tgl_spi = NULL; - cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1); + gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1); } static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) @@ -833,11 +834,21 @@ static int s3c64xx_spi_setup(struct spi_device *spi) unsigned long flags; int err = 0; - if (cs == NULL || cs->set_level == NULL) { + if (cs == NULL) { dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select); return -ENODEV; } + if (!spi_get_ctldata(spi)) { + err = gpio_request(cs->line, dev_name(&spi->dev)); + if (err) { + dev_err(&spi->dev, "request for slave select gpio " + "line [%d] failed\n", cs->line); + return -EBUSY; + } + spi_set_ctldata(spi, cs); + } + sdd = spi_master_get_devdata(spi->master); sci = sdd->cntrlr_info; @@ -908,6 +919,15 @@ setup_exit: return err; } +static void s3c64xx_spi_cleanup(struct spi_device *spi) +{ + struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi); + + if (cs) + gpio_free(cs->line); + spi_set_ctldata(spi, NULL); +} + static irqreturn_t s3c64xx_spi_irq(int irq, void *data) { struct s3c64xx_spi_driver_data *sdd = data; @@ -1049,6 +1069,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) master->bus_num = sdd->port_id; master->setup = s3c64xx_spi_setup; + master->cleanup = s3c64xx_spi_cleanup; master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; master->transfer_one_message = s3c64xx_spi_transfer_one_message; master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; -- cgit v1.2.3-59-g8ed1b From 2b90807549e5d1f700e523ddd098651ecfc18e65 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Fri, 13 Jul 2012 07:15:15 +0900 Subject: spi: s3c64xx: add device tree support Add support for device based discovery. Signed-off-by: Thomas Abraham Acked-by: Jaswinder Singh Acked-by: Grant Likely Signed-off-by: Kukjin Kim --- .../devicetree/bindings/spi/spi-samsung.txt | 113 ++++++++ drivers/spi/spi-s3c64xx.c | 303 ++++++++++++++++++--- 2 files changed, 377 insertions(+), 39 deletions(-) create mode 100644 Documentation/devicetree/bindings/spi/spi-samsung.txt (limited to 'drivers/spi') diff --git a/Documentation/devicetree/bindings/spi/spi-samsung.txt b/Documentation/devicetree/bindings/spi/spi-samsung.txt new file mode 100644 index 000000000000..59bfc4f9feb3 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/spi-samsung.txt @@ -0,0 +1,113 @@ +* Samsung SPI Controller + +The Samsung SPI controller is used to interface with various devices such as flash +and display controllers using the SPI communication interface. + +Required SoC Specific Properties: + +- compatible: should be one of the following. + - samsung,s3c2443-spi: for s3c2443, s3c2416 and s3c2450 platforms + - samsung,s3c6410-spi: for s3c6410 platforms + - samsung,s5p6440-spi: for s5p6440 and s5p6450 platforms + - samsung,s5pv210-spi: for s5pv210 and s5pc110 platforms + - samsung,exynos4210-spi: for exynos4 and exynos5 platforms + +- reg: physical base address of the controller and length of memory mapped + region. + +- interrupts: The interrupt number to the cpu. The interrupt specifier format + depends on the interrupt controller. + +- tx-dma-channel: The dma channel specifier for tx operations. The format of + the dma specifier depends on the dma controller. + +- rx-dma-channel: The dma channel specifier for rx operations. The format of + the dma specifier depends on the dma controller. + +Required Board Specific Properties: + +- #address-cells: should be 1. +- #size-cells: should be 0. +- gpios: The gpio specifier for clock, mosi and miso interface lines (in the + order specified). The format of the gpio specifier depends on the gpio + controller. + +Optional Board Specific Properties: + +- samsung,spi-src-clk: If the spi controller includes a internal clock mux to + select the clock source for the spi bus clock, this property can be used to + indicate the clock to be used for driving the spi bus clock. If not specified, + the clock number 0 is used as default. + +- num-cs: Specifies the number of chip select lines supported. If + not specified, the default number of chip select lines is set to 1. + +SPI Controller specific data in SPI slave nodes: + +- The spi slave nodes should provide the following information which is required + by the spi controller. + + - cs-gpio: A gpio specifier that specifies the gpio line used as + the slave select line by the spi controller. The format of the gpio + specifier depends on the gpio controller. + + - samsung,spi-feedback-delay: The sampling phase shift to be applied on the + miso line (to account for any lag in the miso line). The following are the + valid values. + + - 0: No phase shift. + - 1: 90 degree phase shift sampling. + - 2: 180 degree phase shift sampling. + - 3: 270 degree phase shift sampling. + +Aliases: + +- All the SPI controller nodes should be represented in the aliases node using + the following format 'spi{n}' where n is a unique number for the alias. + + +Example: + +- SoC Specific Portion: + + spi_0: spi@12d20000 { + compatible = "samsung,exynos4210-spi"; + reg = <0x12d20000 0x100>; + interrupts = <0 66 0>; + tx-dma-channel = <&pdma0 5>; + rx-dma-channel = <&pdma0 4>; + }; + +- Board Specific Portion: + + spi_0: spi@12d20000 { + #address-cells = <1>; + #size-cells = <0>; + gpios = <&gpa2 4 2 3 0>, + <&gpa2 6 2 3 0>, + <&gpa2 7 2 3 0>; + + w25q80bw@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25x80"; + reg = <0>; + spi-max-frequency = <10000>; + + controller-data { + cs-gpio = <&gpa2 5 1 0 3>; + samsung,spi-feedback-delay = <0>; + }; + + partition@0 { + label = "U-Boot"; + reg = <0x0 0x40000>; + read-only; + }; + + partition@40000 { + label = "Kernel"; + reg = <0x40000 0xc0000>; + }; + }; + }; diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index e4182ea2f306..0dedbbdb153a 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include @@ -137,6 +139,7 @@ struct s3c64xx_spi_dma_data { unsigned ch; enum dma_data_direction direction; enum dma_ch dmach; + struct property *dma_prop; }; /** @@ -201,6 +204,7 @@ struct s3c64xx_spi_driver_data { struct samsung_dma_ops *ops; struct s3c64xx_spi_port_config *port_conf; unsigned int port_id; + unsigned long gpios[4]; }; static struct s3c2410_dma_client s3c64xx_spi_dma_client = { @@ -326,7 +330,9 @@ static int acquire_dma(struct s3c64xx_spi_driver_data *sdd) req.cap = DMA_SLAVE; req.client = &s3c64xx_spi_dma_client; + req.dt_dmach_prop = sdd->rx_dma.dma_prop; sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &req); + req.dt_dmach_prop = sdd->tx_dma.dma_prop; sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &req); return 1; @@ -819,6 +825,48 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi) return 0; } +static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( + struct s3c64xx_spi_driver_data *sdd, + struct spi_device *spi) +{ + struct s3c64xx_spi_csinfo *cs; + struct device_node *slave_np, *data_np; + u32 fb_delay = 0; + + slave_np = spi->dev.of_node; + if (!slave_np) { + dev_err(&spi->dev, "device node not found\n"); + return ERR_PTR(-EINVAL); + } + + for_each_child_of_node(slave_np, data_np) + if (!strcmp(data_np->name, "controller-data")) + break; + if (!data_np) { + dev_err(&spi->dev, "child node 'controller-data' not found\n"); + return ERR_PTR(-EINVAL); + } + + cs = kzalloc(sizeof(*cs), GFP_KERNEL); + if (!cs) { + dev_err(&spi->dev, "could not allocate memory for controller" + " data\n"); + return ERR_PTR(-ENOMEM); + } + + cs->line = of_get_named_gpio(data_np, "cs-gpio", 0); + if (!gpio_is_valid(cs->line)) { + dev_err(&spi->dev, "chip select gpio is not specified or " + "invalid\n"); + kfree(cs); + return ERR_PTR(-EINVAL); + } + + of_property_read_u32(data_np, "samsung,spi-feedback-delay", &fb_delay); + cs->fb_delay = fb_delay; + return cs; +} + /* * Here we only check the validity of requested configuration * and save the configuration in a local data-structure. @@ -832,9 +880,15 @@ static int s3c64xx_spi_setup(struct spi_device *spi) struct s3c64xx_spi_info *sci; struct spi_message *msg; unsigned long flags; - int err = 0; + int err; - if (cs == NULL) { + sdd = spi_master_get_devdata(spi->master); + if (!cs && spi->dev.of_node) { + cs = s3c64xx_get_slave_ctrldata(sdd, spi); + spi->controller_data = cs; + } + + if (IS_ERR_OR_NULL(cs)) { dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select); return -ENODEV; } @@ -844,12 +898,12 @@ static int s3c64xx_spi_setup(struct spi_device *spi) if (err) { dev_err(&spi->dev, "request for slave select gpio " "line [%d] failed\n", cs->line); - return -EBUSY; + err = -EBUSY; + goto err_gpio_req; } spi_set_ctldata(spi, cs); } - sdd = spi_master_get_devdata(spi->master); sci = sdd->cntrlr_info; spin_lock_irqsave(&sdd->lock, flags); @@ -860,7 +914,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi) dev_err(&spi->dev, "setup: attempt while mssg in queue!\n"); spin_unlock_irqrestore(&sdd->lock, flags); - return -EBUSY; + err = -EBUSY; + goto err_msgq; } } @@ -903,19 +958,29 @@ static int s3c64xx_spi_setup(struct spi_device *spi) } speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1); - if (spi->max_speed_hz >= speed) + if (spi->max_speed_hz >= speed) { spi->max_speed_hz = speed; - else + } else { err = -EINVAL; + goto setup_exit; + } } pm_runtime_put(&sdd->pdev->dev); + disable_cs(sdd, spi); + return 0; setup_exit: - /* setup() returns with device de-selected */ disable_cs(sdd, spi); +err_msgq: + gpio_free(cs->line); + spi_set_ctldata(spi, NULL); + +err_gpio_req: + kfree(cs); + return err; } @@ -923,8 +988,11 @@ static void s3c64xx_spi_cleanup(struct spi_device *spi) { struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi); - if (cs) + if (cs) { gpio_free(cs->line); + if (spi->dev.of_node) + kfree(cs); + } spi_set_ctldata(spi, NULL); } @@ -989,49 +1057,166 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel) flush_fifo(sdd); } +static int __devinit s3c64xx_spi_get_dmares( + struct s3c64xx_spi_driver_data *sdd, bool tx) +{ + struct platform_device *pdev = sdd->pdev; + struct s3c64xx_spi_dma_data *dma_data; + struct property *prop; + struct resource *res; + char prop_name[15], *chan_str; + + if (tx) { + dma_data = &sdd->tx_dma; + dma_data->direction = DMA_TO_DEVICE; + chan_str = "tx"; + } else { + dma_data = &sdd->rx_dma; + dma_data->direction = DMA_FROM_DEVICE; + chan_str = "rx"; + } + + if (!sdd->pdev->dev.of_node) { + res = platform_get_resource(pdev, IORESOURCE_DMA, tx ? 0 : 1); + if (!res) { + dev_err(&pdev->dev, "Unable to get SPI-%s dma " + "resource\n", chan_str); + return -ENXIO; + } + dma_data->dmach = res->start; + return 0; + } + + sprintf(prop_name, "%s-dma-channel", chan_str); + prop = of_find_property(pdev->dev.of_node, prop_name, NULL); + if (!prop) { + dev_err(&pdev->dev, "%s dma channel property not specified\n", + chan_str); + return -ENXIO; + } + + dma_data->dmach = DMACH_DT_PROP; + dma_data->dma_prop = prop; + return 0; +} + +#ifdef CONFIG_OF +static int s3c64xx_spi_parse_dt_gpio(struct s3c64xx_spi_driver_data *sdd) +{ + struct device *dev = &sdd->pdev->dev; + int idx, gpio, ret; + + /* find gpios for mosi, miso and clock lines */ + for (idx = 0; idx < 3; idx++) { + gpio = of_get_gpio(dev->of_node, idx); + if (!gpio_is_valid(gpio)) { + dev_err(dev, "invalid gpio[%d]: %d\n", idx, gpio); + goto free_gpio; + } + + ret = gpio_request(gpio, "spi-bus"); + if (ret) { + dev_err(dev, "gpio [%d] request failed\n", gpio); + goto free_gpio; + } + } + return 0; + +free_gpio: + while (--idx >= 0) + gpio_free(sdd->gpios[idx]); + return -EINVAL; +} + +static void s3c64xx_spi_dt_gpio_free(struct s3c64xx_spi_driver_data *sdd) +{ + unsigned int idx; + for (idx = 0; idx < 3; idx++) + gpio_free(sdd->gpios[idx]); +} + +static struct __devinit s3c64xx_spi_info * s3c64xx_spi_parse_dt( + struct device *dev) +{ + struct s3c64xx_spi_info *sci; + u32 temp; + + sci = devm_kzalloc(dev, sizeof(*sci), GFP_KERNEL); + if (!sci) { + dev_err(dev, "memory allocation for spi_info failed\n"); + return ERR_PTR(-ENOMEM); + } + + if (of_property_read_u32(dev->of_node, "samsung,spi-src-clk", &temp)) { + dev_warn(dev, "spi bus clock parent not specified, using " + "clock at index 0 as parent\n"); + sci->src_clk_nr = 0; + } else { + sci->src_clk_nr = temp; + } + + if (of_property_read_u32(dev->of_node, "num-cs", &temp)) { + dev_warn(dev, "number of chip select lines not specified, " + "assuming 1 chip select line\n"); + sci->num_cs = 1; + } else { + sci->num_cs = temp; + } + + return sci; +} +#else +static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev) +{ + return dev->platform_data; +} + +static int s3c64xx_spi_parse_dt_gpio(struct s3c64xx_spi_driver_data *sdd) +{ + return -EINVAL; +} + +static void s3c64xx_spi_dt_gpio_free(struct s3c64xx_spi_driver_data *sdd) +{ +} +#endif + +static const struct of_device_id s3c64xx_spi_dt_match[]; + static inline struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config( struct platform_device *pdev) { +#ifdef CONFIG_OF + if (pdev->dev.of_node) { + const struct of_device_id *match; + match = of_match_node(s3c64xx_spi_dt_match, pdev->dev.of_node); + return (struct s3c64xx_spi_port_config *)match->data; + } +#endif return (struct s3c64xx_spi_port_config *) platform_get_device_id(pdev)->driver_data; } static int __init s3c64xx_spi_probe(struct platform_device *pdev) { - struct resource *mem_res, *dmatx_res, *dmarx_res; + struct resource *mem_res; struct s3c64xx_spi_driver_data *sdd; - struct s3c64xx_spi_info *sci; + struct s3c64xx_spi_info *sci = pdev->dev.platform_data; struct spi_master *master; int ret, irq; char clk_name[16]; - if (pdev->id < 0) { - dev_err(&pdev->dev, - "Invalid platform device id-%d\n", pdev->id); - return -ENODEV; + if (!sci && pdev->dev.of_node) { + sci = s3c64xx_spi_parse_dt(&pdev->dev); + if (IS_ERR(sci)) + return PTR_ERR(sci); } - if (pdev->dev.platform_data == NULL) { + if (!sci) { dev_err(&pdev->dev, "platform_data missing!\n"); return -ENODEV; } - sci = pdev->dev.platform_data; - - /* Check for availability of necessary resource */ - - dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (dmatx_res == NULL) { - dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n"); - return -ENXIO; - } - - dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (dmarx_res == NULL) { - dev_err(&pdev->dev, "Unable to get SPI-Rx dma resource\n"); - return -ENXIO; - } - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (mem_res == NULL) { dev_err(&pdev->dev, "Unable to get SPI MEM resource\n"); @@ -1059,14 +1244,29 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) sdd->cntrlr_info = sci; sdd->pdev = pdev; sdd->sfr_start = mem_res->start; - sdd->tx_dma.dmach = dmatx_res->start; - sdd->tx_dma.direction = DMA_MEM_TO_DEV; - sdd->rx_dma.dmach = dmarx_res->start; - sdd->rx_dma.direction = DMA_DEV_TO_MEM; - sdd->port_id = pdev->id; + if (pdev->dev.of_node) { + ret = of_alias_get_id(pdev->dev.of_node, "spi"); + if (ret < 0) { + dev_err(&pdev->dev, "failed to get alias id, " + "errno %d\n", ret); + goto err0; + } + sdd->port_id = ret; + } else { + sdd->port_id = pdev->id; + } sdd->cur_bpw = 8; + ret = s3c64xx_spi_get_dmares(sdd, true); + if (ret) + goto err0; + + ret = s3c64xx_spi_get_dmares(sdd, false); + if (ret) + goto err0; + + master->dev.of_node = pdev->dev.of_node; master->bus_num = sdd->port_id; master->setup = s3c64xx_spi_setup; master->cleanup = s3c64xx_spi_cleanup; @@ -1092,7 +1292,10 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) goto err1; } - if (sci->cfg_gpio == NULL || sci->cfg_gpio()) { + if (!sci->cfg_gpio && pdev->dev.of_node) { + if (s3c64xx_spi_parse_dt_gpio(sdd)) + return -EBUSY; + } else if (sci->cfg_gpio == NULL || sci->cfg_gpio()) { dev_err(&pdev->dev, "Unable to config gpio\n"); ret = -EBUSY; goto err2; @@ -1173,6 +1376,8 @@ err5: err4: clk_put(sdd->clk); err3: + if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node) + s3c64xx_spi_dt_gpio_free(sdd); err2: iounmap((void *) sdd->regs); err1: @@ -1204,6 +1409,9 @@ static int s3c64xx_spi_remove(struct platform_device *pdev) clk_disable(sdd->clk); clk_put(sdd->clk); + if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node) + s3c64xx_spi_dt_gpio_free(sdd); + iounmap((void *) sdd->regs); mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1228,6 +1436,9 @@ static int s3c64xx_spi_suspend(struct device *dev) clk_disable(sdd->src_clk); clk_disable(sdd->clk); + if (!sdd->cntrlr_info->cfg_gpio && dev->of_node) + s3c64xx_spi_dt_gpio_free(sdd); + sdd->cur_speed = 0; /* Output Clock is stopped */ return 0; @@ -1239,7 +1450,10 @@ static int s3c64xx_spi_resume(struct device *dev) struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); struct s3c64xx_spi_info *sci = sdd->cntrlr_info; - sci->cfg_gpio(); + if (!sci->cfg_gpio && dev->of_node) + s3c64xx_spi_parse_dt_gpio(sdd); + else + sci->cfg_gpio(); /* Enable the clock */ clk_enable(sdd->src_clk); @@ -1347,11 +1561,22 @@ static struct platform_device_id s3c64xx_spi_driver_ids[] = { { }, }; +#ifdef CONFIG_OF +static const struct of_device_id s3c64xx_spi_dt_match[] = { + { .compatible = "samsung,exynos4210-spi", + .data = (void *)&exynos4_spi_port_config, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match); +#endif /* CONFIG_OF */ + static struct platform_driver s3c64xx_spi_driver = { .driver = { .name = "s3c64xx-spi", .owner = THIS_MODULE, .pm = &s3c64xx_spi_pm, + .of_match_table = of_match_ptr(s3c64xx_spi_dt_match), }, .remove = s3c64xx_spi_remove, .id_table = s3c64xx_spi_driver_ids, -- cgit v1.2.3-59-g8ed1b