From 10f9f743f661d200a7a0006e65688cf28c2f01d9 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Mon, 18 Jan 2010 16:15:07 +0900 Subject: ARM: S3C64XX: SPI: Add SPI controller register base Added SPI controller register base. Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks --- arch/arm/mach-s3c6400/include/mach/map.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-s3c6400/include/mach/map.h b/arch/arm/mach-s3c6400/include/mach/map.h index 3e17adf3a89..801c1c0f3a9 100644 --- a/arch/arm/mach-s3c6400/include/mach/map.h +++ b/arch/arm/mach-s3c6400/include/mach/map.h @@ -64,6 +64,8 @@ #define S3C64XX_PA_IIS1 (0x7F003000) #define S3C64XX_PA_TIMER (0x7F006000) #define S3C64XX_PA_IIC0 (0x7F004000) +#define S3C64XX_PA_SPI0 (0x7F00B000) +#define S3C64XX_PA_SPI1 (0x7F00C000) #define S3C64XX_PA_PCM0 (0x7F009000) #define S3C64XX_PA_PCM1 (0x7F00A000) #define S3C64XX_PA_IISV4 (0x7F00D000) -- cgit v1.2.3 From 87315a802a8aab9d986858fcf2230726c1b5c598 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Mon, 18 Jan 2010 16:15:08 +0900 Subject: ARM: S3C64XX: SPI: Define SPI-48M clock sources Defined special 48MHz clock sources for SPI-0,1. Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/clock.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/plat-s3c64xx/clock.c b/arch/arm/plat-s3c64xx/clock.c index ae5883c00e7..2989c3a2e94 100644 --- a/arch/arm/plat-s3c64xx/clock.c +++ b/arch/arm/plat-s3c64xx/clock.c @@ -140,6 +140,18 @@ static struct clk init_clocks_disable[] = { .parent = &clk_p, .enable = s3c64xx_pclk_ctrl, .ctrlbit = S3C_CLKCON_PCLK_SPI1, + }, { + .name = "spi_48m", + .id = 0, + .parent = &clk_48m, + .enable = s3c64xx_sclk_ctrl, + .ctrlbit = S3C_CLKCON_SCLK_SPI0_48, + }, { + .name = "spi_48m", + .id = 1, + .parent = &clk_48m, + .enable = s3c64xx_sclk_ctrl, + .ctrlbit = S3C_CLKCON_SCLK_SPI1_48, }, { .name = "48m", .id = 0, -- cgit v1.2.3 From 398ccccb770e6ed3e138925404f0746cbe57c5a1 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Mon, 18 Jan 2010 17:45:52 +0900 Subject: ARM: S3C64XX: SPI: Header for passing platform data We need a way to pass controller specific information to the SPI driver. For that purpose new headers are made. SPI Controller is assumed 'type-s3c64xx' and can be defined for newer SoCs. Hence, that part is placed under plat-samsung to be shared across newer SoCs. SoC specific part - spi source clocks, will be placed under plat-/include/plat/ Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/include/plat/spi-clocks.h | 18 +++++++ arch/arm/plat-samsung/include/plat/s3c64xx-spi.h | 67 ++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 arch/arm/plat-s3c64xx/include/plat/spi-clocks.h create mode 100644 arch/arm/plat-samsung/include/plat/s3c64xx-spi.h diff --git a/arch/arm/plat-s3c64xx/include/plat/spi-clocks.h b/arch/arm/plat-s3c64xx/include/plat/spi-clocks.h new file mode 100644 index 00000000000..524bdae3f62 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/spi-clocks.h @@ -0,0 +1,18 @@ +/* linux/arch/arm/plat-s3c64xx/include/plat/spi-clocks.h + * + * Copyright (C) 2009 Samsung Electronics Ltd. + * Jaswinder Singh + * + * 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. + */ + +#ifndef __S3C64XX_PLAT_SPI_CLKS_H +#define __S3C64XX_PLAT_SPI_CLKS_H __FILE__ + +#define S3C64XX_SPI_SRCCLK_PCLK 0 +#define S3C64XX_SPI_SRCCLK_SPIBUS 1 +#define S3C64XX_SPI_SRCCLK_48M 2 + +#endif /* __S3C64XX_PLAT_SPI_CLKS_H */ diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h new file mode 100644 index 00000000000..d1772414931 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h @@ -0,0 +1,67 @@ +/* linux/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h + * + * Copyright (C) 2009 Samsung Electronics Ltd. + * Jaswinder Singh + * + * 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. + */ + +#ifndef __S3C64XX_PLAT_SPI_H +#define __S3C64XX_PLAT_SPI_H + +/** + * struct s3c64xx_spi_csinfo - ChipSelect description + * @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 + * spi_board_info.controller_data point to it. + */ +struct s3c64xx_spi_csinfo { + u8 fb_delay; + unsigned line; + void (*set_level)(unsigned line_id, int lvl); +}; + +/** + * struct s3c64xx_spi_info - SPI Controller defining structure + * @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field. + * @src_clk_name: Platform name of the corresponding clock. + * @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 + */ +struct s3c64xx_spi_info { + int src_clk_nr; + char *src_clk_name; + + 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; +}; + +/** + * s3c64xx_spi_set_info - SPI Controller configure callback by the board + * initialization code. + * @cntrlr: SPI controller number the configuration is for. + * @src_clk_nr: Clock the SPI controller is to use to generate SPI clocks. + * @num_cs: Number of elements in the 'cs' array. + * + * Call this from machine init code for each SPI Controller that + * has some chips attached to it. + */ +extern void s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); + +#endif /* __S3C64XX_PLAT_SPI_H */ -- cgit v1.2.3 From 6a2b4111643127a28944d673995810a82582c5a1 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Mon, 18 Jan 2010 17:32:02 +0900 Subject: ARM: S3C64XX: SPI: Define SPI controller devices Platform devices for SPI Controller of S3C64XX are defined and exported for machines to include. Also, controller setup helper functions are defined for machine code to set runtime configuration of the controller and the bus. Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks --- arch/arm/plat-s3c/include/plat/devs.h | 3 + arch/arm/plat-s3c64xx/Makefile | 1 + arch/arm/plat-s3c64xx/dev-spi.c | 180 ++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 arch/arm/plat-s3c64xx/dev-spi.c diff --git a/arch/arm/plat-s3c/include/plat/devs.h b/arch/arm/plat-s3c/include/plat/devs.h index 8a4153b49f4..f4a7e57bab2 100644 --- a/arch/arm/plat-s3c/include/plat/devs.h +++ b/arch/arm/plat-s3c/include/plat/devs.h @@ -29,6 +29,9 @@ extern struct platform_device s3c64xx_device_iis0; extern struct platform_device s3c64xx_device_iis1; extern struct platform_device s3c64xx_device_iisv4; +extern struct platform_device s3c64xx_device_spi0; +extern struct platform_device s3c64xx_device_spi1; + extern struct platform_device s3c64xx_device_pcm0; extern struct platform_device s3c64xx_device_pcm1; diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile index b241f369556..80255a5e178 100644 --- a/arch/arm/plat-s3c64xx/Makefile +++ b/arch/arm/plat-s3c64xx/Makefile @@ -47,3 +47,4 @@ obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o obj-$(CONFIG_SND_S3C24XX_SOC) += dev-audio.o +obj-$(CONFIG_SPI_S3C64XX) += dev-spi.o diff --git a/arch/arm/plat-s3c64xx/dev-spi.c b/arch/arm/plat-s3c64xx/dev-spi.c new file mode 100644 index 00000000000..6b6d7af0662 --- /dev/null +++ b/arch/arm/plat-s3c64xx/dev-spi.c @@ -0,0 +1,180 @@ +/* linux/arch/arm/plat-s3c64xx/dev-spi.c + * + * Copyright (C) 2009 Samsung Electronics Ltd. + * Jaswinder Singh + * + * 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. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +static char *spi_src_clks[] = { + [S3C64XX_SPI_SRCCLK_PCLK] = "pclk", + [S3C64XX_SPI_SRCCLK_SPIBUS] = "spi-bus", + [S3C64XX_SPI_SRCCLK_48M] = "spi_48m", +}; + +/* SPI Controller platform_devices */ + +/* Since we emulate multi-cs capability, we do not touch the GPC-3,7. + * The emulated CS is toggled by board specific mechanism, as it can + * be either some immediate GPIO or some signal out of some other + * chip in between ... or some yet another way. + * We simply do not assume anything about CS. + */ +static int s3c64xx_spi_cfg_gpio(struct platform_device *pdev) +{ + switch (pdev->id) { + case 0: + s3c_gpio_cfgpin(S3C64XX_GPC(0), S3C64XX_GPC0_SPI_MISO0); + s3c_gpio_cfgpin(S3C64XX_GPC(1), S3C64XX_GPC1_SPI_CLKO); + s3c_gpio_cfgpin(S3C64XX_GPC(2), S3C64XX_GPC2_SPI_MOSIO); + s3c_gpio_setpull(S3C64XX_GPC(0), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S3C64XX_GPC(1), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S3C64XX_GPC(2), S3C_GPIO_PULL_UP); + break; + + case 1: + s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_SPI_MISO1); + s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_SPI_CLK1); + s3c_gpio_cfgpin(S3C64XX_GPC(6), S3C64XX_GPC6_SPI_MOSI1); + s3c_gpio_setpull(S3C64XX_GPC(4), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S3C64XX_GPC(5), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S3C64XX_GPC(6), S3C_GPIO_PULL_UP); + break; + + default: + dev_err(&pdev->dev, "Invalid SPI Controller number!"); + return -EINVAL; + } + + return 0; +} + +static struct resource s3c64xx_spi0_resource[] = { + [0] = { + .start = S3C64XX_PA_SPI0, + .end = S3C64XX_PA_SPI0 + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_SPI0_TX, + .end = DMACH_SPI0_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_SPI0_RX, + .end = DMACH_SPI0_RX, + .flags = IORESOURCE_DMA, + }, + [3] = { + .start = IRQ_SPI0, + .end = IRQ_SPI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct s3c64xx_spi_info s3c64xx_spi0_pdata = { + .cfg_gpio = s3c64xx_spi_cfg_gpio, + .fifo_lvl_mask = 0x7f, + .rx_lvl_offset = 13, +}; + +static u64 spi_dmamask = DMA_BIT_MASK(32); + +struct platform_device s3c64xx_device_spi0 = { + .name = "s3c64xx-spi", + .id = 0, + .num_resources = ARRAY_SIZE(s3c64xx_spi0_resource), + .resource = s3c64xx_spi0_resource, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &s3c64xx_spi0_pdata, + }, +}; +EXPORT_SYMBOL(s3c64xx_device_spi0); + +static struct resource s3c64xx_spi1_resource[] = { + [0] = { + .start = S3C64XX_PA_SPI1, + .end = S3C64XX_PA_SPI1 + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_SPI1_TX, + .end = DMACH_SPI1_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_SPI1_RX, + .end = DMACH_SPI1_RX, + .flags = IORESOURCE_DMA, + }, + [3] = { + .start = IRQ_SPI1, + .end = IRQ_SPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct s3c64xx_spi_info s3c64xx_spi1_pdata = { + .cfg_gpio = s3c64xx_spi_cfg_gpio, + .fifo_lvl_mask = 0x7f, + .rx_lvl_offset = 13, +}; + +struct platform_device s3c64xx_device_spi1 = { + .name = "s3c64xx-spi", + .id = 1, + .num_resources = ARRAY_SIZE(s3c64xx_spi1_resource), + .resource = s3c64xx_spi1_resource, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &s3c64xx_spi1_pdata, + }, +}; +EXPORT_SYMBOL(s3c64xx_device_spi1); + +void __init s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs) +{ + /* Reject invalid configuration */ + if (!num_cs || src_clk_nr < 0 + || src_clk_nr > S3C64XX_SPI_SRCCLK_48M) { + printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__); + return; + } + + switch (cntrlr) { + case 0: + s3c64xx_spi0_pdata.num_cs = num_cs; + s3c64xx_spi0_pdata.src_clk_nr = src_clk_nr; + s3c64xx_spi0_pdata.src_clk_name = spi_src_clks[src_clk_nr]; + break; + case 1: + s3c64xx_spi1_pdata.num_cs = num_cs; + s3c64xx_spi1_pdata.src_clk_nr = src_clk_nr; + s3c64xx_spi1_pdata.src_clk_name = spi_src_clks[src_clk_nr]; + break; + default: + printk(KERN_ERR "%s: Invalid SPI controller(%d)\n", + __func__, cntrlr); + return; + } +} -- cgit v1.2.3