mirror of
https://github.com/torvalds/linux.git
synced 2024-11-18 18:11:56 +00:00
Merge branch 'next/dt-samsung' into next/devel-samsung-spi
This commit is contained in:
commit
f9ed561ebd
113
Documentation/devicetree/bindings/spi/spi-samsung.txt
Normal file
113
Documentation/devicetree/bindings/spi/spi-samsung.txt
Normal file
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
@ -134,4 +134,16 @@
|
||||
i2c@138D0000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi_0: spi@13920000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi_1: spi@13930000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi_2: spi@13940000 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
@ -179,4 +179,42 @@
|
||||
i2c@138D0000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi_0: spi@13920000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi_1: spi@13930000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi_2: spi@13940000 {
|
||||
gpios = <&gpc1 1 5 3 0>,
|
||||
<&gpc1 3 5 3 0>,
|
||||
<&gpc1 4 5 3 0>;
|
||||
|
||||
w25x80@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "w25x80";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <1000000>;
|
||||
|
||||
controller-data {
|
||||
cs-gpio = <&gpc1 2 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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -25,6 +25,12 @@
|
||||
compatible = "samsung,exynos4210";
|
||||
interrupt-parent = <&gic>;
|
||||
|
||||
aliases {
|
||||
spi0 = &spi_0;
|
||||
spi1 = &spi_1;
|
||||
spi2 = &spi_2;
|
||||
};
|
||||
|
||||
gic:interrupt-controller@10490000 {
|
||||
compatible = "arm,cortex-a9-gic";
|
||||
#interrupt-cells = <3>;
|
||||
@ -33,6 +39,17 @@
|
||||
reg = <0x10490000 0x1000>, <0x10480000 0x100>;
|
||||
};
|
||||
|
||||
combiner:interrupt-controller@10440000 {
|
||||
compatible = "samsung,exynos4210-combiner";
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
reg = <0x10440000 0x1000>;
|
||||
interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
|
||||
<0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
|
||||
<0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
|
||||
<0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
|
||||
};
|
||||
|
||||
watchdog@10060000 {
|
||||
compatible = "samsung,s3c2410-wdt";
|
||||
reg = <0x10060000 0x100>;
|
||||
@ -147,6 +164,36 @@
|
||||
interrupts = <0 65 0>;
|
||||
};
|
||||
|
||||
spi_0: spi@13920000 {
|
||||
compatible = "samsung,exynos4210-spi";
|
||||
reg = <0x13920000 0x100>;
|
||||
interrupts = <0 66 0>;
|
||||
tx-dma-channel = <&pdma0 7>;
|
||||
rx-dma-channel = <&pdma0 6>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
spi_1: spi@13930000 {
|
||||
compatible = "samsung,exynos4210-spi";
|
||||
reg = <0x13930000 0x100>;
|
||||
interrupts = <0 67 0>;
|
||||
tx-dma-channel = <&pdma1 7>;
|
||||
rx-dma-channel = <&pdma1 6>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
spi_2: spi@13940000 {
|
||||
compatible = "samsung,exynos4210-spi";
|
||||
reg = <0x13940000 0x100>;
|
||||
interrupts = <0 68 0>;
|
||||
tx-dma-channel = <&pdma0 9>;
|
||||
rx-dma-channel = <&pdma0 8>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
amba {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
@ -71,4 +71,42 @@
|
||||
i2c@12CD0000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi_0: spi@12d20000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi_1: spi@12d30000 {
|
||||
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 = <1000000>;
|
||||
|
||||
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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
spi_2: spi@12d40000 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
@ -23,6 +23,12 @@
|
||||
compatible = "samsung,exynos5250";
|
||||
interrupt-parent = <&gic>;
|
||||
|
||||
aliases {
|
||||
spi0 = &spi_0;
|
||||
spi1 = &spi_1;
|
||||
spi2 = &spi_2;
|
||||
};
|
||||
|
||||
gic:interrupt-controller@10481000 {
|
||||
compatible = "arm,cortex-a9-gic";
|
||||
#interrupt-cells = <3>;
|
||||
@ -146,6 +152,36 @@
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
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>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
spi_1: spi@12d30000 {
|
||||
compatible = "samsung,exynos4210-spi";
|
||||
reg = <0x12d30000 0x100>;
|
||||
interrupts = <0 67 0>;
|
||||
tx-dma-channel = <&pdma1 5>;
|
||||
rx-dma-channel = <&pdma1 4>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
spi_2: spi@12d40000 {
|
||||
compatible = "samsung,exynos4210-spi";
|
||||
reg = <0x12d40000 0x100>;
|
||||
interrupts = <0 68 0>;
|
||||
tx-dma-channel = <&pdma0 7>;
|
||||
rx-dma-channel = <&pdma0 6>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
amba {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
@ -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),
|
||||
}, {
|
||||
@ -1242,42 +1242,69 @@ static struct clksrc_clk exynos4_clk_sclk_mmc3 = {
|
||||
.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 24, .size = 8 },
|
||||
};
|
||||
|
||||
static struct clksrc_clk exynos4_clk_sclk_spi0 = {
|
||||
static struct clksrc_clk exynos4_clk_mdout_spi0 = {
|
||||
.clk = {
|
||||
.name = "sclk_spi",
|
||||
.devname = "s3c64xx-spi.0",
|
||||
.enable = exynos4_clksrc_mask_peril1_ctrl,
|
||||
.ctrlbit = (1 << 16),
|
||||
.name = "mdout_spi",
|
||||
.devname = "exynos4210-spi.0",
|
||||
},
|
||||
.sources = &exynos4_clkset_group,
|
||||
.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 16, .size = 4 },
|
||||
.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 0, .size = 4 },
|
||||
};
|
||||
|
||||
static struct clksrc_clk exynos4_clk_sclk_spi1 = {
|
||||
static struct clksrc_clk exynos4_clk_mdout_spi1 = {
|
||||
.clk = {
|
||||
.name = "sclk_spi",
|
||||
.devname = "s3c64xx-spi.1",
|
||||
.enable = exynos4_clksrc_mask_peril1_ctrl,
|
||||
.ctrlbit = (1 << 20),
|
||||
.name = "mdout_spi",
|
||||
.devname = "exynos4210-spi.1",
|
||||
},
|
||||
.sources = &exynos4_clkset_group,
|
||||
.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 20, .size = 4 },
|
||||
.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 16, .size = 4 },
|
||||
};
|
||||
|
||||
static struct clksrc_clk exynos4_clk_sclk_spi2 = {
|
||||
static struct clksrc_clk exynos4_clk_mdout_spi2 = {
|
||||
.clk = {
|
||||
.name = "sclk_spi",
|
||||
.devname = "s3c64xx-spi.2",
|
||||
.enable = exynos4_clksrc_mask_peril1_ctrl,
|
||||
.ctrlbit = (1 << 24),
|
||||
.name = "mdout_spi",
|
||||
.devname = "exynos4210-spi.2",
|
||||
},
|
||||
.sources = &exynos4_clkset_group,
|
||||
.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 24, .size = 4 },
|
||||
.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 0, .size = 4 },
|
||||
};
|
||||
|
||||
static struct clksrc_clk exynos4_clk_sclk_spi0 = {
|
||||
.clk = {
|
||||
.name = "sclk_spi",
|
||||
.devname = "exynos4210-spi.0",
|
||||
.parent = &exynos4_clk_mdout_spi0.clk,
|
||||
.enable = exynos4_clksrc_mask_peril1_ctrl,
|
||||
.ctrlbit = (1 << 16),
|
||||
},
|
||||
.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 8, .size = 8 },
|
||||
};
|
||||
|
||||
static struct clksrc_clk exynos4_clk_sclk_spi1 = {
|
||||
.clk = {
|
||||
.name = "sclk_spi",
|
||||
.devname = "exynos4210-spi.1",
|
||||
.parent = &exynos4_clk_mdout_spi1.clk,
|
||||
.enable = exynos4_clksrc_mask_peril1_ctrl,
|
||||
.ctrlbit = (1 << 20),
|
||||
},
|
||||
.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 24, .size = 8 },
|
||||
};
|
||||
|
||||
static struct clksrc_clk exynos4_clk_sclk_spi2 = {
|
||||
.clk = {
|
||||
.name = "sclk_spi",
|
||||
.devname = "exynos4210-spi.2",
|
||||
.parent = &exynos4_clk_mdout_spi2.clk,
|
||||
.enable = exynos4_clksrc_mask_peril1_ctrl,
|
||||
.ctrlbit = (1 << 24),
|
||||
},
|
||||
.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 8, .size = 8 },
|
||||
};
|
||||
|
||||
/* Clock initialization code */
|
||||
static struct clksrc_clk *exynos4_sysclks[] = {
|
||||
&exynos4_clk_mout_apll,
|
||||
@ -1331,7 +1358,9 @@ static struct clksrc_clk *exynos4_clksrc_cdev[] = {
|
||||
&exynos4_clk_sclk_spi0,
|
||||
&exynos4_clk_sclk_spi1,
|
||||
&exynos4_clk_sclk_spi2,
|
||||
|
||||
&exynos4_clk_mdout_spi0,
|
||||
&exynos4_clk_mdout_spi1,
|
||||
&exynos4_clk_mdout_spi2,
|
||||
};
|
||||
|
||||
static struct clk_lookup exynos4_clk_lookup[] = {
|
||||
@ -1347,9 +1376,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;
|
||||
|
@ -131,6 +131,11 @@ static int exynos5_clksrc_mask_peric0_ctrl(struct clk *clk, int enable)
|
||||
return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC0, clk, enable);
|
||||
}
|
||||
|
||||
static int exynos5_clksrc_mask_peric1_ctrl(struct clk *clk, int enable)
|
||||
{
|
||||
return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC1, clk, enable);
|
||||
}
|
||||
|
||||
static int exynos5_clk_ip_acp_ctrl(struct clk *clk, int enable)
|
||||
{
|
||||
return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ACP, clk, enable);
|
||||
@ -740,6 +745,24 @@ static struct clk exynos5_init_clocks_off[] = {
|
||||
.parent = &exynos5_clk_aclk_66.clk,
|
||||
.enable = exynos5_clk_ip_peric_ctrl,
|
||||
.ctrlbit = (1 << 14),
|
||||
}, {
|
||||
.name = "spi",
|
||||
.devname = "exynos4210-spi.0",
|
||||
.parent = &exynos5_clk_aclk_66.clk,
|
||||
.enable = exynos5_clk_ip_peric_ctrl,
|
||||
.ctrlbit = (1 << 16),
|
||||
}, {
|
||||
.name = "spi",
|
||||
.devname = "exynos4210-spi.1",
|
||||
.parent = &exynos5_clk_aclk_66.clk,
|
||||
.enable = exynos5_clk_ip_peric_ctrl,
|
||||
.ctrlbit = (1 << 17),
|
||||
}, {
|
||||
.name = "spi",
|
||||
.devname = "exynos4210-spi.2",
|
||||
.parent = &exynos5_clk_aclk_66.clk,
|
||||
.enable = exynos5_clk_ip_peric_ctrl,
|
||||
.ctrlbit = (1 << 18),
|
||||
}, {
|
||||
.name = SYSMMU_CLOCK_NAME,
|
||||
.devname = SYSMMU_CLOCK_DEVNAME(mfc_l, 0),
|
||||
@ -1034,6 +1057,69 @@ static struct clksrc_clk exynos5_clk_sclk_mmc3 = {
|
||||
.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 24, .size = 8 },
|
||||
};
|
||||
|
||||
static struct clksrc_clk exynos5_clk_mdout_spi0 = {
|
||||
.clk = {
|
||||
.name = "mdout_spi",
|
||||
.devname = "exynos4210-spi.0",
|
||||
},
|
||||
.sources = &exynos5_clkset_group,
|
||||
.reg_src = { .reg = EXYNOS5_CLKSRC_PERIC1, .shift = 16, .size = 4 },
|
||||
.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 0, .size = 4 },
|
||||
};
|
||||
|
||||
static struct clksrc_clk exynos5_clk_mdout_spi1 = {
|
||||
.clk = {
|
||||
.name = "mdout_spi",
|
||||
.devname = "exynos4210-spi.1",
|
||||
},
|
||||
.sources = &exynos5_clkset_group,
|
||||
.reg_src = { .reg = EXYNOS5_CLKSRC_PERIC1, .shift = 20, .size = 4 },
|
||||
.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 16, .size = 4 },
|
||||
};
|
||||
|
||||
static struct clksrc_clk exynos5_clk_mdout_spi2 = {
|
||||
.clk = {
|
||||
.name = "mdout_spi",
|
||||
.devname = "exynos4210-spi.2",
|
||||
},
|
||||
.sources = &exynos5_clkset_group,
|
||||
.reg_src = { .reg = EXYNOS5_CLKSRC_PERIC1, .shift = 24, .size = 4 },
|
||||
.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC2, .shift = 0, .size = 4 },
|
||||
};
|
||||
|
||||
static struct clksrc_clk exynos5_clk_sclk_spi0 = {
|
||||
.clk = {
|
||||
.name = "sclk_spi",
|
||||
.devname = "exynos4210-spi.0",
|
||||
.parent = &exynos5_clk_mdout_spi0.clk,
|
||||
.enable = exynos5_clksrc_mask_peric1_ctrl,
|
||||
.ctrlbit = (1 << 16),
|
||||
},
|
||||
.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 8, .size = 8 },
|
||||
};
|
||||
|
||||
static struct clksrc_clk exynos5_clk_sclk_spi1 = {
|
||||
.clk = {
|
||||
.name = "sclk_spi",
|
||||
.devname = "exynos4210-spi.1",
|
||||
.parent = &exynos5_clk_mdout_spi1.clk,
|
||||
.enable = exynos5_clksrc_mask_peric1_ctrl,
|
||||
.ctrlbit = (1 << 20),
|
||||
},
|
||||
.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 24, .size = 8 },
|
||||
};
|
||||
|
||||
static struct clksrc_clk exynos5_clk_sclk_spi2 = {
|
||||
.clk = {
|
||||
.name = "sclk_spi",
|
||||
.devname = "exynos4210-spi.2",
|
||||
.parent = &exynos5_clk_mdout_spi2.clk,
|
||||
.enable = exynos5_clksrc_mask_peric1_ctrl,
|
||||
.ctrlbit = (1 << 24),
|
||||
},
|
||||
.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC2, .shift = 8, .size = 8 },
|
||||
};
|
||||
|
||||
static struct clksrc_clk exynos5_clksrcs[] = {
|
||||
{
|
||||
.clk = {
|
||||
@ -1148,6 +1234,12 @@ static struct clksrc_clk *exynos5_sysclks[] = {
|
||||
&exynos5_clk_dout_mmc4,
|
||||
&exynos5_clk_aclk_acp,
|
||||
&exynos5_clk_pclk_acp,
|
||||
&exynos5_clk_sclk_spi0,
|
||||
&exynos5_clk_sclk_spi1,
|
||||
&exynos5_clk_sclk_spi2,
|
||||
&exynos5_clk_mdout_spi0,
|
||||
&exynos5_clk_mdout_spi1,
|
||||
&exynos5_clk_mdout_spi2,
|
||||
};
|
||||
|
||||
static struct clk *exynos5_clk_cdev[] = {
|
||||
@ -1176,6 +1268,9 @@ static struct clk_lookup exynos5_clk_lookup[] = {
|
||||
CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &exynos5_clk_sclk_mmc1.clk),
|
||||
CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &exynos5_clk_sclk_mmc2.clk),
|
||||
CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &exynos5_clk_sclk_mmc3.clk),
|
||||
CLKDEV_INIT("exynos4210-spi.0", "spi_busclk0", &exynos5_clk_sclk_spi0.clk),
|
||||
CLKDEV_INIT("exynos4210-spi.1", "spi_busclk0", &exynos5_clk_sclk_spi1.clk),
|
||||
CLKDEV_INIT("exynos4210-spi.2", "spi_busclk0", &exynos5_clk_sclk_spi2.clk),
|
||||
CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos5_clk_pdma0),
|
||||
CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos5_clk_pdma1),
|
||||
CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos5_clk_mdma1),
|
||||
|
@ -195,6 +195,10 @@
|
||||
#define IRQ_IIC6 EXYNOS4_IRQ_IIC6
|
||||
#define IRQ_IIC7 EXYNOS4_IRQ_IIC7
|
||||
|
||||
#define IRQ_SPI0 EXYNOS4_IRQ_SPI0
|
||||
#define IRQ_SPI1 EXYNOS4_IRQ_SPI1
|
||||
#define IRQ_SPI2 EXYNOS4_IRQ_SPI2
|
||||
|
||||
#define IRQ_USB_HOST EXYNOS4_IRQ_USB_HOST
|
||||
#define IRQ_OTG EXYNOS4_IRQ_USB_HSOTG
|
||||
|
||||
|
@ -154,6 +154,9 @@
|
||||
#define EXYNOS4_PA_SPI0 0x13920000
|
||||
#define EXYNOS4_PA_SPI1 0x13930000
|
||||
#define EXYNOS4_PA_SPI2 0x13940000
|
||||
#define EXYNOS5_PA_SPI0 0x12D20000
|
||||
#define EXYNOS5_PA_SPI1 0x12D30000
|
||||
#define EXYNOS5_PA_SPI2 0x12D40000
|
||||
|
||||
#define EXYNOS4_PA_GPIO1 0x11400000
|
||||
#define EXYNOS4_PA_GPIO2 0x11000000
|
||||
|
@ -55,6 +55,12 @@ static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = {
|
||||
"exynos4-sdhci.3", NULL),
|
||||
OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(0),
|
||||
"s3c2440-i2c.0", NULL),
|
||||
OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI0,
|
||||
"exynos4210-spi.0", NULL),
|
||||
OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI1,
|
||||
"exynos4210-spi.1", NULL),
|
||||
OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI2,
|
||||
"exynos4210-spi.2", NULL),
|
||||
OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA0, "dma-pl330.0", NULL),
|
||||
OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA1, "dma-pl330.1", NULL),
|
||||
{},
|
||||
|
@ -47,6 +47,12 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
|
||||
"s3c2440-i2c.0", NULL),
|
||||
OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(1),
|
||||
"s3c2440-i2c.1", NULL),
|
||||
OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI0,
|
||||
"exynos4210-spi.0", NULL),
|
||||
OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI1,
|
||||
"exynos4210-spi.1", NULL),
|
||||
OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI2,
|
||||
"exynos4210-spi.2", NULL),
|
||||
OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA0, "dma-pl330.0", NULL),
|
||||
OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.1", NULL),
|
||||
OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_MDMA1, "dma-pl330.2", NULL),
|
||||
|
@ -9,21 +9,10 @@
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <plat/gpio-cfg.h>
|
||||
#include <plat/s3c64xx-spi.h>
|
||||
|
||||
#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)
|
||||
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);
|
||||
@ -34,15 +23,7 @@ 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)
|
||||
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);
|
||||
@ -53,15 +34,7 @@ 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)
|
||||
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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -13,20 +13,12 @@
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <plat/gpio-cfg.h>
|
||||
#include <plat/s3c64xx-spi.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/regs-gpio.h>
|
||||
|
||||
#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)
|
||||
int s3c64xx_spi0_cfg_gpio(void)
|
||||
{
|
||||
/* enable hsspi bit in misccr */
|
||||
s3c2410_modify_misccr(S3C2416_MISCCR_HSSPI_EN2, 1);
|
||||
|
@ -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)
|
||||
|
@ -21,6 +21,7 @@
|
||||
*/
|
||||
enum dma_ch {
|
||||
/* DMA0/SDMA0 */
|
||||
DMACH_DT_PROP = -1, /* not yet supported, do not use */
|
||||
DMACH_UART0 = 0,
|
||||
DMACH_UART0_SRC2,
|
||||
DMACH_UART1,
|
||||
|
@ -799,7 +799,7 @@ static void __init crag6410_machine_init(void)
|
||||
i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
|
||||
|
||||
samsung_keypad_set_platdata(&crag6410_keypad_data);
|
||||
s3c64xx_spi0_set_platdata(&s3c64xx_spi0_pdata, 0, 1);
|
||||
s3c64xx_spi0_set_platdata(NULL, 0, 1);
|
||||
|
||||
platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
|
||||
|
||||
|
@ -9,19 +9,10 @@
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <plat/gpio-cfg.h>
|
||||
#include <plat/s3c64xx-spi.h>
|
||||
|
||||
#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)
|
||||
int s3c64xx_spi0_cfg_gpio(void)
|
||||
{
|
||||
s3c_gpio_cfgall_range(S3C64XX_GPC(0), 3,
|
||||
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
|
||||
@ -30,13 +21,7 @@ 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)
|
||||
int s3c64xx_spi1_cfg_gpio(void)
|
||||
{
|
||||
s3c_gpio_cfgall_range(S3C64XX_GPC(4), 3,
|
||||
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
@ -9,21 +9,10 @@
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <plat/gpio-cfg.h>
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/s3c64xx-spi.h>
|
||||
|
||||
#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)
|
||||
int s3c64xx_spi0_cfg_gpio(void)
|
||||
{
|
||||
if (soc_is_s5p6450())
|
||||
s3c_gpio_cfgall_range(S5P6450_GPC(0), 3,
|
||||
@ -36,13 +25,7 @@ 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)
|
||||
int s3c64xx_spi1_cfg_gpio(void)
|
||||
{
|
||||
if (soc_is_s5p6450())
|
||||
s3c_gpio_cfgall_range(S5P6450_GPC(4), 3,
|
||||
|
@ -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)
|
||||
|
@ -9,20 +9,10 @@
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <plat/gpio-cfg.h>
|
||||
#include <plat/s3c64xx-spi.h>
|
||||
|
||||
#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)
|
||||
int s3c64xx_spi0_cfg_gpio(void)
|
||||
{
|
||||
s3c_gpio_cfgall_range(S5PC100_GPB(0), 3,
|
||||
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
|
||||
@ -31,14 +21,7 @@ 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)
|
||||
int s3c64xx_spi1_cfg_gpio(void)
|
||||
{
|
||||
s3c_gpio_cfgall_range(S5PC100_GPB(4), 3,
|
||||
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
|
||||
@ -47,14 +30,7 @@ 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)
|
||||
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);
|
||||
|
@ -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)
|
||||
|
@ -9,20 +9,10 @@
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <plat/gpio-cfg.h>
|
||||
#include <plat/s3c64xx-spi.h>
|
||||
|
||||
#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)
|
||||
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);
|
||||
@ -33,14 +23,7 @@ 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)
|
||||
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);
|
||||
|
@ -1513,7 +1513,7 @@ static struct resource s3c64xx_spi0_resource[] = {
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_spi0 = {
|
||||
.name = "s3c64xx-spi",
|
||||
.name = "s3c6410-spi",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(s3c64xx_spi0_resource),
|
||||
.resource = s3c64xx_spi0_resource,
|
||||
@ -1523,13 +1523,10 @@ struct platform_device s3c64xx_device_spi0 = {
|
||||
},
|
||||
};
|
||||
|
||||
void __init s3c64xx_spi0_set_platdata(struct s3c64xx_spi_info *pd,
|
||||
int src_clk_nr, int num_cs)
|
||||
void __init s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
|
||||
int num_cs)
|
||||
{
|
||||
if (!pd) {
|
||||
pr_err("%s:Need to pass platform data\n", __func__);
|
||||
return;
|
||||
}
|
||||
struct s3c64xx_spi_info pd;
|
||||
|
||||
/* Reject invalid configuration */
|
||||
if (!num_cs || src_clk_nr < 0) {
|
||||
@ -1537,12 +1534,11 @@ void __init s3c64xx_spi0_set_platdata(struct s3c64xx_spi_info *pd,
|
||||
return;
|
||||
}
|
||||
|
||||
pd->num_cs = num_cs;
|
||||
pd->src_clk_nr = src_clk_nr;
|
||||
if (!pd->cfg_gpio)
|
||||
pd->cfg_gpio = s3c64xx_spi0_cfg_gpio;
|
||||
pd.num_cs = num_cs;
|
||||
pd.src_clk_nr = src_clk_nr;
|
||||
pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio;
|
||||
|
||||
s3c_set_platdata(pd, sizeof(*pd), &s3c64xx_device_spi0);
|
||||
s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi0);
|
||||
}
|
||||
#endif /* CONFIG_S3C64XX_DEV_SPI0 */
|
||||
|
||||
@ -1555,7 +1551,7 @@ static struct resource s3c64xx_spi1_resource[] = {
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_spi1 = {
|
||||
.name = "s3c64xx-spi",
|
||||
.name = "s3c6410-spi",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(s3c64xx_spi1_resource),
|
||||
.resource = s3c64xx_spi1_resource,
|
||||
@ -1565,26 +1561,20 @@ struct platform_device s3c64xx_device_spi1 = {
|
||||
},
|
||||
};
|
||||
|
||||
void __init s3c64xx_spi1_set_platdata(struct s3c64xx_spi_info *pd,
|
||||
int src_clk_nr, int num_cs)
|
||||
void __init s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
|
||||
int num_cs)
|
||||
{
|
||||
if (!pd) {
|
||||
pr_err("%s:Need to pass platform data\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reject invalid configuration */
|
||||
if (!num_cs || src_clk_nr < 0) {
|
||||
pr_err("%s: Invalid SPI configuration\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
pd->num_cs = num_cs;
|
||||
pd->src_clk_nr = src_clk_nr;
|
||||
if (!pd->cfg_gpio)
|
||||
pd->cfg_gpio = s3c64xx_spi1_cfg_gpio;
|
||||
pd.num_cs = num_cs;
|
||||
pd.src_clk_nr = src_clk_nr;
|
||||
pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi1_cfg_gpio;
|
||||
|
||||
s3c_set_platdata(pd, sizeof(*pd), &s3c64xx_device_spi1);
|
||||
s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi1);
|
||||
}
|
||||
#endif /* CONFIG_S3C64XX_DEV_SPI1 */
|
||||
|
||||
@ -1597,7 +1587,7 @@ static struct resource s3c64xx_spi2_resource[] = {
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_spi2 = {
|
||||
.name = "s3c64xx-spi",
|
||||
.name = "s3c6410-spi",
|
||||
.id = 2,
|
||||
.num_resources = ARRAY_SIZE(s3c64xx_spi2_resource),
|
||||
.resource = s3c64xx_spi2_resource,
|
||||
@ -1607,13 +1597,10 @@ struct platform_device s3c64xx_device_spi2 = {
|
||||
},
|
||||
};
|
||||
|
||||
void __init s3c64xx_spi2_set_platdata(struct s3c64xx_spi_info *pd,
|
||||
int src_clk_nr, int num_cs)
|
||||
void __init s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
|
||||
int num_cs)
|
||||
{
|
||||
if (!pd) {
|
||||
pr_err("%s:Need to pass platform data\n", __func__);
|
||||
return;
|
||||
}
|
||||
struct s3c64xx_spi_info pd;
|
||||
|
||||
/* Reject invalid configuration */
|
||||
if (!num_cs || src_clk_nr < 0) {
|
||||
@ -1621,11 +1608,10 @@ void __init s3c64xx_spi2_set_platdata(struct s3c64xx_spi_info *pd,
|
||||
return;
|
||||
}
|
||||
|
||||
pd->num_cs = num_cs;
|
||||
pd->src_clk_nr = src_clk_nr;
|
||||
if (!pd->cfg_gpio)
|
||||
pd->cfg_gpio = s3c64xx_spi2_cfg_gpio;
|
||||
pd.num_cs = num_cs;
|
||||
pd.src_clk_nr = src_clk_nr;
|
||||
pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi2_cfg_gpio;
|
||||
|
||||
s3c_set_platdata(pd, sizeof(*pd), &s3c64xx_device_spi2);
|
||||
s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi2);
|
||||
}
|
||||
#endif /* CONFIG_S3C64XX_DEV_SPI2 */
|
||||
|
@ -19,72 +19,79 @@
|
||||
#include <mach/dma.h>
|
||||
|
||||
static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
|
||||
struct samsung_dma_info *info)
|
||||
struct samsung_dma_req *param)
|
||||
{
|
||||
struct dma_chan *chan;
|
||||
dma_cap_mask_t mask;
|
||||
struct dma_slave_config slave_config;
|
||||
void *filter_param;
|
||||
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(info->cap, mask);
|
||||
dma_cap_set(param->cap, mask);
|
||||
|
||||
/*
|
||||
* If a dma channel property of a device node from device tree is
|
||||
* specified, use that as the fliter parameter.
|
||||
*/
|
||||
filter_param = (dma_ch == DMACH_DT_PROP) ? (void *)info->dt_dmach_prop :
|
||||
(void *)dma_ch;
|
||||
chan = dma_request_channel(mask, pl330_filter, filter_param);
|
||||
|
||||
if (info->direction == DMA_DEV_TO_MEM) {
|
||||
memset(&slave_config, 0, sizeof(struct dma_slave_config));
|
||||
slave_config.direction = info->direction;
|
||||
slave_config.src_addr = info->fifo;
|
||||
slave_config.src_addr_width = info->width;
|
||||
slave_config.src_maxburst = 1;
|
||||
dmaengine_slave_config(chan, &slave_config);
|
||||
} else if (info->direction == DMA_MEM_TO_DEV) {
|
||||
memset(&slave_config, 0, sizeof(struct dma_slave_config));
|
||||
slave_config.direction = info->direction;
|
||||
slave_config.dst_addr = info->fifo;
|
||||
slave_config.dst_addr_width = info->width;
|
||||
slave_config.dst_maxburst = 1;
|
||||
dmaengine_slave_config(chan, &slave_config);
|
||||
}
|
||||
|
||||
return (unsigned)chan;
|
||||
filter_param = (dma_ch == DMACH_DT_PROP) ?
|
||||
(void *)param->dt_dmach_prop : (void *)dma_ch;
|
||||
return (unsigned)dma_request_channel(mask, pl330_filter, filter_param);
|
||||
}
|
||||
|
||||
static int samsung_dmadev_release(unsigned ch,
|
||||
struct s3c2410_dma_client *client)
|
||||
static int samsung_dmadev_release(unsigned ch, void *param)
|
||||
{
|
||||
dma_release_channel((struct dma_chan *)ch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int samsung_dmadev_config(unsigned ch,
|
||||
struct samsung_dma_config *param)
|
||||
{
|
||||
struct dma_chan *chan = (struct dma_chan *)ch;
|
||||
struct dma_slave_config slave_config;
|
||||
|
||||
if (param->direction == DMA_DEV_TO_MEM) {
|
||||
memset(&slave_config, 0, sizeof(struct dma_slave_config));
|
||||
slave_config.direction = param->direction;
|
||||
slave_config.src_addr = param->fifo;
|
||||
slave_config.src_addr_width = param->width;
|
||||
slave_config.src_maxburst = 1;
|
||||
dmaengine_slave_config(chan, &slave_config);
|
||||
} else if (param->direction == DMA_MEM_TO_DEV) {
|
||||
memset(&slave_config, 0, sizeof(struct dma_slave_config));
|
||||
slave_config.direction = param->direction;
|
||||
slave_config.dst_addr = param->fifo;
|
||||
slave_config.dst_addr_width = param->width;
|
||||
slave_config.dst_maxburst = 1;
|
||||
dmaengine_slave_config(chan, &slave_config);
|
||||
} else {
|
||||
pr_warn("unsupported direction\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int samsung_dmadev_prepare(unsigned ch,
|
||||
struct samsung_dma_prep_info *info)
|
||||
struct samsung_dma_prep *param)
|
||||
{
|
||||
struct scatterlist sg;
|
||||
struct dma_chan *chan = (struct dma_chan *)ch;
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
|
||||
switch (info->cap) {
|
||||
switch (param->cap) {
|
||||
case DMA_SLAVE:
|
||||
sg_init_table(&sg, 1);
|
||||
sg_dma_len(&sg) = info->len;
|
||||
sg_set_page(&sg, pfn_to_page(PFN_DOWN(info->buf)),
|
||||
info->len, offset_in_page(info->buf));
|
||||
sg_dma_address(&sg) = info->buf;
|
||||
sg_dma_len(&sg) = param->len;
|
||||
sg_set_page(&sg, pfn_to_page(PFN_DOWN(param->buf)),
|
||||
param->len, offset_in_page(param->buf));
|
||||
sg_dma_address(&sg) = param->buf;
|
||||
|
||||
desc = dmaengine_prep_slave_sg(chan,
|
||||
&sg, 1, info->direction, DMA_PREP_INTERRUPT);
|
||||
&sg, 1, param->direction, DMA_PREP_INTERRUPT);
|
||||
break;
|
||||
case DMA_CYCLIC:
|
||||
desc = dmaengine_prep_dma_cyclic(chan,
|
||||
info->buf, info->len, info->period, info->direction);
|
||||
desc = dmaengine_prep_dma_cyclic(chan, param->buf,
|
||||
param->len, param->period, param->direction);
|
||||
break;
|
||||
default:
|
||||
dev_err(&chan->dev->device, "unsupported format\n");
|
||||
@ -96,8 +103,8 @@ static int samsung_dmadev_prepare(unsigned ch,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
desc->callback = info->fp;
|
||||
desc->callback_param = info->fp_param;
|
||||
desc->callback = param->fp;
|
||||
desc->callback_param = param->fp_param;
|
||||
|
||||
dmaengine_submit((struct dma_async_tx_descriptor *)desc);
|
||||
|
||||
@ -119,6 +126,7 @@ static inline int samsung_dmadev_flush(unsigned ch)
|
||||
static struct samsung_dma_ops dmadev_ops = {
|
||||
.request = samsung_dmadev_request,
|
||||
.release = samsung_dmadev_release,
|
||||
.config = samsung_dmadev_config,
|
||||
.prepare = samsung_dmadev_prepare,
|
||||
.trigger = samsung_dmadev_trigger,
|
||||
.started = NULL,
|
||||
|
@ -16,7 +16,13 @@
|
||||
#include <linux/dmaengine.h>
|
||||
#include <mach/dma.h>
|
||||
|
||||
struct samsung_dma_prep_info {
|
||||
struct samsung_dma_req {
|
||||
enum dma_transaction_type cap;
|
||||
struct property *dt_dmach_prop;
|
||||
struct s3c2410_dma_client *client;
|
||||
};
|
||||
|
||||
struct samsung_dma_prep {
|
||||
enum dma_transaction_type cap;
|
||||
enum dma_transfer_direction direction;
|
||||
dma_addr_t buf;
|
||||
@ -26,19 +32,17 @@ struct samsung_dma_prep_info {
|
||||
void *fp_param;
|
||||
};
|
||||
|
||||
struct samsung_dma_info {
|
||||
enum dma_transaction_type cap;
|
||||
struct samsung_dma_config {
|
||||
enum dma_transfer_direction direction;
|
||||
enum dma_slave_buswidth width;
|
||||
dma_addr_t fifo;
|
||||
struct s3c2410_dma_client *client;
|
||||
struct property *dt_dmach_prop;
|
||||
};
|
||||
|
||||
struct samsung_dma_ops {
|
||||
unsigned (*request)(enum dma_ch ch, struct samsung_dma_info *info);
|
||||
int (*release)(unsigned ch, struct s3c2410_dma_client *client);
|
||||
int (*prepare)(unsigned ch, struct samsung_dma_prep_info *info);
|
||||
unsigned (*request)(enum dma_ch ch, struct samsung_dma_req *param);
|
||||
int (*release)(unsigned ch, void *param);
|
||||
int (*config)(unsigned ch, struct samsung_dma_config *param);
|
||||
int (*prepare)(unsigned ch, struct samsung_dma_prep *param);
|
||||
int (*trigger)(unsigned ch);
|
||||
int (*started)(unsigned ch);
|
||||
int (*flush)(unsigned ch);
|
||||
|
@ -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,57 +26,41 @@ struct platform_device;
|
||||
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.
|
||||
* @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;
|
||||
int (*cfg_gpio)(void);
|
||||
};
|
||||
|
||||
/**
|
||||
* s3c64xx_spi_set_platdata - SPI Controller configure callback by the board
|
||||
* initialization code.
|
||||
* @pd: SPI platform data to set.
|
||||
* @cfg_gpio: Pointer to gpio setup function.
|
||||
* @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_spi0_set_platdata(struct s3c64xx_spi_info *pd,
|
||||
int src_clk_nr, int num_cs);
|
||||
extern void s3c64xx_spi1_set_platdata(struct s3c64xx_spi_info *pd,
|
||||
int src_clk_nr, int num_cs);
|
||||
extern void s3c64xx_spi2_set_platdata(struct s3c64xx_spi_info *pd,
|
||||
int src_clk_nr, int num_cs);
|
||||
extern void s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
|
||||
int num_cs);
|
||||
extern void s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
|
||||
int num_cs);
|
||||
extern void s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), 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;
|
||||
|
@ -36,30 +36,26 @@ static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,
|
||||
}
|
||||
|
||||
static unsigned s3c_dma_request(enum dma_ch dma_ch,
|
||||
struct samsung_dma_info *info)
|
||||
struct samsung_dma_req *param)
|
||||
{
|
||||
struct cb_data *data;
|
||||
|
||||
if (s3c2410_dma_request(dma_ch, info->client, NULL) < 0) {
|
||||
s3c2410_dma_free(dma_ch, info->client);
|
||||
if (s3c2410_dma_request(dma_ch, param->client, NULL) < 0) {
|
||||
s3c2410_dma_free(dma_ch, param->client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (param->cap == DMA_CYCLIC)
|
||||
s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
|
||||
|
||||
data = kzalloc(sizeof(struct cb_data), GFP_KERNEL);
|
||||
data->ch = dma_ch;
|
||||
list_add_tail(&data->node, &dma_list);
|
||||
|
||||
s3c2410_dma_devconfig(dma_ch, info->direction, info->fifo);
|
||||
|
||||
if (info->cap == DMA_CYCLIC)
|
||||
s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
|
||||
|
||||
s3c2410_dma_config(dma_ch, info->width);
|
||||
|
||||
return (unsigned)dma_ch;
|
||||
}
|
||||
|
||||
static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
|
||||
static int s3c_dma_release(unsigned ch, void *param)
|
||||
{
|
||||
struct cb_data *data;
|
||||
|
||||
@ -68,16 +64,24 @@ static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
|
||||
break;
|
||||
list_del(&data->node);
|
||||
|
||||
s3c2410_dma_free(ch, client);
|
||||
s3c2410_dma_free(ch, param);
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
|
||||
static int s3c_dma_config(unsigned ch, struct samsung_dma_config *param)
|
||||
{
|
||||
s3c2410_dma_devconfig(ch, param->direction, param->fifo);
|
||||
s3c2410_dma_config(ch, param->width);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep *param)
|
||||
{
|
||||
struct cb_data *data;
|
||||
int len = (info->cap == DMA_CYCLIC) ? info->period : info->len;
|
||||
int len = (param->cap == DMA_CYCLIC) ? param->period : param->len;
|
||||
|
||||
list_for_each_entry(data, &dma_list, node)
|
||||
if (data->ch == ch)
|
||||
@ -85,11 +89,11 @@ static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
|
||||
|
||||
if (!data->fp) {
|
||||
s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb);
|
||||
data->fp = info->fp;
|
||||
data->fp_param = info->fp_param;
|
||||
data->fp = param->fp;
|
||||
data->fp_param = param->fp_param;
|
||||
}
|
||||
|
||||
s3c2410_dma_enqueue(ch, (void *)data, info->buf, len);
|
||||
s3c2410_dma_enqueue(ch, (void *)data, param->buf, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -117,6 +121,7 @@ static inline int s3c_dma_stop(unsigned ch)
|
||||
static struct samsung_dma_ops s3c_dma_ops = {
|
||||
.request = s3c_dma_request,
|
||||
.release = s3c_dma_release,
|
||||
.config = s3c_dma_config,
|
||||
.prepare = s3c_dma_prepare,
|
||||
.trigger = s3c_dma_trigger,
|
||||
.started = s3c_dma_started,
|
||||
|
@ -27,10 +27,15 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include <mach/dma.h>
|
||||
#include <plat/s3c64xx-spi.h>
|
||||
|
||||
#define MAX_SPI_PORTS 3
|
||||
|
||||
/* Registers and bit-fields */
|
||||
|
||||
#define S3C64XX_SPI_CH_CFG 0x00
|
||||
@ -113,13 +118,12 @@
|
||||
|
||||
#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)
|
||||
#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
|
||||
@ -135,6 +139,29 @@ struct s3c64xx_spi_dma_data {
|
||||
unsigned ch;
|
||||
enum dma_data_direction direction;
|
||||
enum dma_ch dmach;
|
||||
struct property *dma_prop;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -175,6 +202,9 @@ 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;
|
||||
unsigned long gpios[4];
|
||||
};
|
||||
|
||||
static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
|
||||
@ -183,7 +213,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;
|
||||
@ -199,7 +228,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");
|
||||
@ -208,7 +237,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;
|
||||
@ -262,14 +291,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 +323,17 @@ 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;
|
||||
req.cap = DMA_SLAVE;
|
||||
req.client = &s3c64xx_spi_dma_client;
|
||||
|
||||
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.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;
|
||||
}
|
||||
@ -306,7 +342,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;
|
||||
|
||||
@ -356,7 +391,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;
|
||||
|
||||
@ -383,20 +418,19 @@ 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,
|
||||
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;
|
||||
@ -413,7 +447,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)
|
||||
@ -432,8 +466,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);
|
||||
@ -477,17 +511,16 @@ 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)
|
||||
{
|
||||
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);
|
||||
@ -531,7 +564,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);
|
||||
@ -557,7 +590,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;
|
||||
|
||||
@ -573,7 +605,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) {
|
||||
@ -607,7 +639,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;
|
||||
|
||||
@ -616,7 +647,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
|
||||
@ -635,7 +666,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;
|
||||
@ -690,7 +720,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;
|
||||
@ -795,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.
|
||||
@ -808,14 +880,30 @@ 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 || cs->set_level == 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;
|
||||
}
|
||||
|
||||
sdd = spi_master_get_devdata(spi->master);
|
||||
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);
|
||||
err = -EBUSY;
|
||||
goto err_gpio_req;
|
||||
}
|
||||
spi_set_ctldata(spi, cs);
|
||||
}
|
||||
|
||||
sci = sdd->cntrlr_info;
|
||||
|
||||
spin_lock_irqsave(&sdd->lock, flags);
|
||||
@ -826,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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -844,7 +933,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 */
|
||||
@ -869,22 +958,44 @@ 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;
|
||||
}
|
||||
|
||||
static void s3c64xx_spi_cleanup(struct spi_device *spi)
|
||||
{
|
||||
struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi);
|
||||
|
||||
if (cs) {
|
||||
gpio_free(cs->line);
|
||||
if (spi->dev.of_node)
|
||||
kfree(cs);
|
||||
}
|
||||
spi_set_ctldata(spi, NULL);
|
||||
}
|
||||
|
||||
static irqreturn_t s3c64xx_spi_irq(int irq, void *data)
|
||||
{
|
||||
struct s3c64xx_spi_driver_data *sdd = data;
|
||||
@ -925,7 +1036,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);
|
||||
@ -946,42 +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");
|
||||
@ -1004,19 +1239,37 @@ 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;
|
||||
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;
|
||||
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;
|
||||
|
||||
master->bus_num = pdev->id;
|
||||
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;
|
||||
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;
|
||||
@ -1039,7 +1292,10 @@ 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 && 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;
|
||||
@ -1075,7 +1331,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);
|
||||
@ -1100,7 +1356,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);
|
||||
@ -1120,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:
|
||||
@ -1151,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);
|
||||
@ -1175,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;
|
||||
@ -1182,18 +1446,20 @@ 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);
|
||||
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);
|
||||
clk_enable(sdd->clk);
|
||||
|
||||
s3c64xx_spi_hwinit(sdd, pdev->id);
|
||||
s3c64xx_spi_hwinit(sdd, sdd->port_id);
|
||||
|
||||
spi_master_resume(master);
|
||||
|
||||
@ -1231,13 +1497,89 @@ 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,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
#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,
|
||||
};
|
||||
MODULE_ALIAS("platform:s3c64xx-spi");
|
||||
|
||||
|
@ -74,7 +74,7 @@ static void dma_enqueue(struct snd_pcm_substream *substream)
|
||||
struct runtime_data *prtd = substream->runtime->private_data;
|
||||
dma_addr_t pos = prtd->dma_pos;
|
||||
unsigned int limit;
|
||||
struct samsung_dma_prep_info dma_info;
|
||||
struct samsung_dma_prep dma_info;
|
||||
|
||||
pr_debug("Entered %s\n", __func__);
|
||||
|
||||
@ -146,7 +146,8 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
|
||||
unsigned long totbytes = params_buffer_bytes(params);
|
||||
struct s3c_dma_params *dma =
|
||||
snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
struct samsung_dma_info dma_info;
|
||||
struct samsung_dma_req req;
|
||||
struct samsung_dma_config config;
|
||||
|
||||
pr_debug("Entered %s\n", __func__);
|
||||
|
||||
@ -166,16 +167,17 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
|
||||
|
||||
prtd->params->ops = samsung_dma_get_ops();
|
||||
|
||||
dma_info.cap = (samsung_dma_has_circular() ?
|
||||
req.cap = (samsung_dma_has_circular() ?
|
||||
DMA_CYCLIC : DMA_SLAVE);
|
||||
dma_info.client = prtd->params->client;
|
||||
dma_info.direction =
|
||||
req.client = prtd->params->client;
|
||||
config.direction =
|
||||
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
|
||||
? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
|
||||
dma_info.width = prtd->params->dma_size;
|
||||
dma_info.fifo = prtd->params->dma_addr;
|
||||
config.width = prtd->params->dma_size;
|
||||
config.fifo = prtd->params->dma_addr;
|
||||
prtd->params->ch = prtd->params->ops->request(
|
||||
prtd->params->channel, &dma_info);
|
||||
prtd->params->channel, &req);
|
||||
prtd->params->ops->config(prtd->params->ch, &config);
|
||||
}
|
||||
|
||||
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
|
||||
|
Loading…
Reference in New Issue
Block a user