--- /dev/null
+* Samsung Exynos Interrupt Combiner Controller
+
+Samsung's Exynos4 architecture includes a interrupt combiner controller which
+can combine interrupt sources as a group and provide a single interrupt request
+for the group. The interrupt request from each group are connected to a parent
+interrupt controller, such as GIC in case of Exynos4210.
+
+The interrupt combiner controller consists of multiple combiners. Upto eight
+interrupt sources can be connected to a combiner. The combiner outputs one
+combined interrupt for its eight interrupt sources. The combined interrupt
+is usually connected to a parent interrupt controller.
+
+A single node in the device tree is used to describe the interrupt combiner
+controller module (which includes multiple combiners). A combiner in the
+interrupt controller module shares config/control registers with other
+combiners. For example, a 32-bit interrupt enable/disable config register
+can accommodate upto 4 interrupt combiners (with each combiner supporting
+upto 8 interrupt sources).
+
+Required properties:
+- compatible: should be "samsung,exynos4210-combiner".
+- interrupt-controller: Identifies the node as an interrupt controller.
+- #interrupt-cells: should be <2>. The meaning of the cells are
+ * First Cell: Combiner Group Number.
+ * Second Cell: Interrupt number within the group.
+- reg: Base address and size of interrupt combiner registers.
+- interrupts: The list of interrupts generated by the combiners which are then
+ connected to a parent interrupt controller. The format of the interrupt
+ specifier depends in the interrupt parent controller.
+
+Optional properties:
+- samsung,combiner-nr: The number of interrupt combiners supported. If this
+ property is not specified, the default number of combiners is assumed
+ to be 16.
+- interrupt-parent: pHandle of the parent interrupt controller, if not
+ inherited from the parent node.
+
+
+Example:
+
+ The following is a an example from the Exynos4210 SoC dtsi file.
+
+ combiner:interrupt-controller@10440000 {
+ compatible = "samsung,exynos4210-combiner";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ 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>;
+ };
--- /dev/null
+* Synopsis Designware Mobile Storage Host Controller
+
+The Synopsis designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards.
+
+Required Properties:
+
+* compatible: should be one of the following
+ - synopsis,dw-mshc: for controllers compliant with synopsis dw-mshc.
+ - synopsis,dw-mshc-exynos5250: for controllers with Samsung
+ Exynos5250 specific extentions.
+
+* reg: physical base address of the dw-mshc controller and size of its memory
+ region.
+
+* interrupts: interrupt specifier for the controller. The format and value of
+ the interrupt specifier depends on the interrupt parent for the controller.
+
+# Slots: The slot specific information are contained within child-nodes with
+ each child-node representing a supported slot. There should be atleast one
+ child node representing a card slot. The name of the slot child node should
+ be 'slot{n}' where n is the unique number of the slot connnected to the
+ controller. The following are optional properties which can be included in
+ the slot child node.
+
+ * bus-width: specifies the width of the data bus connected from the
+ controller to the card slot. The value should be 1, 4 or 8. In case
+ this property is not specified, a default value of 1 is assumed for
+ this property.
+
+ * cd-gpios: specifies the card detect gpio line. The format of the
+ gpio specifier depends on the gpio controller.
+
+ * wp-gpios: specifies the write protect gpio line. The format of the
+ gpio specifier depends on the gpio controller.
+
+ * gpios: specifies a list of gpios used for command, clock and data
+ bus. The first gpio is the command line and the second gpio is the
+ clock line. The rest of the gpios (depending on the bus-width
+ property) are the data lines in no particular order. The format of
+ the gpio specifier depends on the gpio controller.
+
+Optional properties:
+
+* fifo-depth: The maximum size of the tx/rx fifo's. If this property is not
+ specified, the default value of the fifo size is determined from the
+ controller registers.
+
+* card-detect-delay: Delay in milli-seconds before detecting card after card
+ insert event. The default value is 0.
+
+* supports-highspeed: Enables support for high speed cards (upto 50MHz)
+
+* card-detection-broken: The card detection functionality is not available on
+ any of the slots.
+
+* no-write-protect: The write protect pad of the controller is not connected
+ to the write protect pin on the slot.
+
+Samsung Exynos5250 specific properties:
+
+* samsung,dw-mshc-sdr-timing: Specifies the value of CUI clock divider, CIU
+ clock phase shift value in transmit mode and CIU clock phase shift value in
+ receive mode for single data rate mode operation. Refer notes of the valid
+ values below.
+
+* samsung,dw-mshc-ddr-timing: Specifies the value of CUI clock divider, CIU
+ clock phase shift value in transmit mode and CIU clock phase shift value in
+ receive mode for double data rate mode operation. Refer notes of the valid
+ values below. The order of the cells should be
+
+ - First Cell: CIU clock divider value.
+ - Second Cell: CIU clock phase shift value for tx mode.
+ - Third Cell: CIU clock phase shift value for rx mode.
+
+ Valid values for SDR and DDR CIU clock timing:
+
+ - valid values for CIU clock divider, tx phase shift and rx phase shift
+ is 0 to 7.
+
+ - When CIU clock divider value is set to 3, all possible 8 phase shift
+ values can be used.
+
+ - If CIU clock divider value is 0 (that is divide by 1), both tx and rx
+ phase shift clocks should be 0.
+
+Example:
+
+ The MSHC controller node can be split into two portions, SoC specific and
+ board specific portions as listed below.
+
+ dwmmc0@12200000 {
+ compatible = "synopsis,dw-mshc-exynos5250";
+ reg = <0x12200000 0x1000>;
+ interrupts = <0 75 0>;
+ };
+
+ dwmmc0@12200000 {
+ supports-highspeed;
+ card-detection-broken;
+ no-write-protect;
+ fifo-depth = <0x80>;
+ card-detect-delay = <200>;
+ samsung,dw-mshc-sdr-timing = <2 3 3>;
+ samsung,dw-mshc-ddr-timing = <1 2 3>;
+
+ slot0 {
+ bus-width = <8>;
+ cd-gpios = <&gpc0 2 2 3 3>;
+ gpios = <&gpc0 0 2 0 3>, <&gpc0 1 2 0 3>,
+ <&gpc1 0 2 3 3>, <&gpc1 1 2 3 3>,
+ <&gpc1 2 2 3 3>, <&gpc1 3 2 3 3>,
+ <&gpc0 3 2 3 3>, <&gpc0 4 2 3 3>,
+ <&gpc0 5 2 3 3>, <&gpc0 6 2 3 3>;
+ };
+ };
};
chosen {
- bootargs = "root=/dev/ram0 rw ramdisk=8192 console=ttySAC1,115200";
+ bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC3,115200 init=/linuxrc";
+ };
+
+ lan9215@0x05000000 {
+ compatible = "smsc,lan9215", "smsc,lan9115";
+ reg = <0x05000000 0x20000>;
+ interrupts = <5 0>;
+ interrupt-parent = <&wakeup_eint>;
+ phy-mode = "mii";
+ smsc,irq-push-pull;
+ smsc,force-internal-phy;
+ local-mac-address = [00 80 00 23 45 67];
+ };
+
+ i2c@12C60000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <20000>;
+ gpios = <&gpb3 0 2 3 0>,
+ <&gpb3 1 2 3 0>;
+
+ eeprom@50 {
+ compatible = "samsung,s524ad0xd1";
+ reg = <0x50>;
+ };
+ };
+
+ i2c@12C70000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <20000>;
+ gpios = <&gpb3 2 2 3 0>,
+ <&gpb3 3 2 3 0>;
+
+ eeprom@51 {
+ compatible = "samsung,s524ad0xd1";
+ reg = <0x51>;
+ };
+ };
+
+ i2c@12C80000 {
+ status = "disabled";
+ };
+
+ i2c@12C90000 {
+ status = "disabled";
+ };
+
+ i2c@12CA0000 {
+ status = "disabled";
+ };
+
+ i2c@12CB0000 {
+ status = "disabled";
+ };
+
+ i2c@12CC0000 {
+ status = "disabled";
+ };
+
+ i2c@12CD0000 {
+ status = "disabled";
+ };
+
+ dwmmc0@12200000 {
+ supports-highspeed;
+ card-detection-broken;
+ no-write-protect;
+ fifo-depth = <0x80>;
+ card-detect-delay = <200>;
+ samsung,dw-mshc-sdr-timing = <2 3 3>;
+ samsung,dw-mshc-ddr-timing = <1 2 3>;
+
+ slot0 {
+ bus-width = <8>;
+ cd-gpios = <&gpc0 2 2 3 3>;
+ gpios = <&gpc0 0 2 0 3>, <&gpc0 1 2 0 3>,
+ <&gpc1 0 2 3 3>, <&gpc1 1 2 3 3>,
+ <&gpc1 2 2 3 3>, <&gpc1 3 2 3 3>,
+ <&gpc0 3 2 3 3>, <&gpc0 4 2 3 3>,
+ <&gpc0 5 2 3 3>, <&gpc0 6 2 3 3>;
+ };
+ };
+
+ dwmmc1@12210000 {
+ status = "disabled";
+ };
+
+ dwmmc2@12220000 {
+ supports-highspeed;
+ card-detection-broken;
+ no-write-protect;
+ fifo-depth = <0x80>;
+ card-detect-delay = <200>;
+ samsung,dw-mshc-sdr-timing = <2 3 3>;
+ samsung,dw-mshc-ddr-timing = <1 2 3>;
+
+ slot0 {
+ bus-width = <4>;
+ cd-gpios = <&gpc3 2 2 3 3>;
+ gpios = <&gpc3 0 2 0 3>, <&gpc3 1 2 0 3>,
+ <&gpc3 3 2 3 3>, <&gpc3 4 2 3 3>,
+ <&gpc3 5 2 3 3>, <&gpc3 6 2 3 3>,
+ <&gpc4 3 3 3 3>, <&gpc4 3 3 3 3>,
+ <&gpc4 5 3 3 3>, <&gpc4 6 3 3 3>;
+ };
+ };
+
+ dwmmc3@12230000 {
+ status = "disabled";
};
};
compatible = "samsung,exynos5250";
interrupt-parent = <&gic>;
- gic:interrupt-controller@10490000 {
+ gic:interrupt-controller@10481000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
+ #address-cells = <0>;
+ #size-cells = <0>;
interrupt-controller;
- reg = <0x10490000 0x1000>, <0x10480000 0x100>;
+ reg = <0x10481000 0x1000>, <0x10482000 0x2000>;
};
+ combiner:interrupt-controller@10440000 {
+ compatible = "samsung,exynos4210-combiner";
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ samsung,combiner-nr = <32>;
+ 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>,
+ <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+ <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
+ <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+ <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
+ };
+
+ wakeup_eint: interrupt-controller@11400000 {
+ compatible = "samsung,exynos5210-wakeup-eint";
+ reg = <0x11400000 0x1000>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&wakeup_map>;
+ interrupts = <0x0 0>, <0x1 0>, <0x2 0>, <0x3 0>,
+ <0x4 0>, <0x5 0>, <0x6 0>, <0x7 0>,
+ <0x8 0>, <0x9 0>, <0xa 0>, <0xb 0>,
+ <0xc 0>, <0xd 0>, <0xe 0>, <0xf 0>,
+ <0x10 0>;
+
+ wakeup_map: interrupt-map {
+ compatible = "samsung,exynos5210-wakeup-eint-map";
+ #interrupt-cells = <2>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ interrupt-map = <0x0 0 &combiner 23 0>,
+ <0x1 0 &combiner 24 0>,
+ <0x2 0 &combiner 25 0>,
+ <0x3 0 &combiner 25 1>,
+ <0x4 0 &combiner 26 0>,
+ <0x5 0 &combiner 26 1>,
+ <0x6 0 &combiner 27 0>,
+ <0x7 0 &combiner 27 1>,
+ <0x8 0 &combiner 28 0>,
+ <0x9 0 &combiner 28 1>,
+ <0xa 0 &combiner 29 0>,
+ <0xb 0 &combiner 29 1>,
+ <0xc 0 &combiner 30 0>,
+ <0xd 0 &combiner 30 1>,
+ <0xe 0 &combiner 31 0>,
+ <0xf 0 &combiner 31 1>,
+ <0x10 0 &gic 0 32 0>;
+ };
+ };
+
watchdog {
compatible = "samsung,s3c2410-wdt";
reg = <0x101D0000 0x100>;
interrupts = <0 43 0>, <0 44 0>;
};
- sdhci@12200000 {
- compatible = "samsung,exynos4210-sdhci";
- reg = <0x12200000 0x100>;
- interrupts = <0 75 0>;
- };
-
- sdhci@12210000 {
- compatible = "samsung,exynos4210-sdhci";
- reg = <0x12210000 0x100>;
- interrupts = <0 76 0>;
- };
-
- sdhci@12220000 {
- compatible = "samsung,exynos4210-sdhci";
- reg = <0x12220000 0x100>;
- interrupts = <0 77 0>;
- };
-
- sdhci@12230000 {
- compatible = "samsung,exynos4210-sdhci";
- reg = <0x12230000 0x100>;
- interrupts = <0 78 0>;
- };
-
serial@12C00000 {
compatible = "samsung,exynos4210-uart";
reg = <0x12C00000 0x100>;
interrupts = <0 63 0>;
};
+ dwmmc0@12200000 {
+ compatible = "synopsis,dw-mshc-exynos5250";
+ reg = <0x12200000 0x1000>;
+ interrupts = <0 75 0>;
+ };
+
+ dwmmc1@12210000 {
+ compatible = "synopsis,dw-mshc-exynos5250";
+ reg = <0x12210000 0x1000>;
+ interrupts = <0 76 0>;
+ };
+
+ dwmmc2@12220000 {
+ compatible = "synopsis,dw-mshc-exynos5250";
+ reg = <0x12220000 0x1000>;
+ interrupts = <0 77 0>;
+ };
+
+ dwmmc3@12230000 {
+ compatible = "synopsis,dw-mshc-exynos5250";
+ reg = <0x12230000 0x1000>;
+ interrupts = <0 78 0>;
+ };
+
amba {
#address-cells = <1>;
#size-cells = <1>;
interrupts = <0 35 0>;
};
- mdma0: pdma@10800000 {
+ mdma0: mdma@10800000 {
compatible = "arm,pl330", "arm,primecell";
reg = <0x10800000 0x1000>;
interrupts = <0 33 0>;
};
- mdma1: pdma@11C10000 {
+ mdma1: mdma@11C10000 {
compatible = "arm,pl330", "arm,primecell";
reg = <0x11C10000 0x1000>;
interrupts = <0 124 0>;
#gpio-cells = <4>;
};
+ gpc4: gpio-controller@114002E0 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x114002E0 0x20>;
+ #gpio-cells = <4>;
+ };
+
gpd0: gpio-controller@11400160 {
compatible = "samsung,exynos4-gpio";
reg = <0x11400160 0x20>;
gpv2: gpio-controller@10D10040 {
compatible = "samsung,exynos4-gpio";
- reg = <0x10D10040 0x20>;
+ reg = <0x10D10060 0x20>;
#gpio-cells = <4>;
};
gpv3: gpio-controller@10D10060 {
compatible = "samsung,exynos4-gpio";
- reg = <0x10D10060 0x20>;
+ reg = <0x10D10080 0x20>;
#gpio-cells = <4>;
};
gpv4: gpio-controller@10D10080 {
compatible = "samsung,exynos4-gpio";
- reg = <0x10D10080 0x20>;
+ reg = <0x10D100C0 0x20>;
#gpio-cells = <4>;
};
bool "SAMSUNG EXYNOS5250"
default y
depends on ARCH_EXYNOS5
+ select SAMSUNG_DMADEV
help
Enable EXYNOS5250 SoC support
help
Use MCT (Multi Core Timer) as kernel timers
-config EXYNOS4_DEV_DMA
+config EXYNOS_DEV_DMA
bool
help
Compile in amba device definitions for DMA controller
select S3C_DEV_HSMMC2
select S3C_DEV_HSMMC3
select EXYNOS4_DEV_AHCI
- select EXYNOS4_DEV_DMA
+ select EXYNOS_DEV_DMA
select EXYNOS4_DEV_SYSMMU
select EXYNOS4_SETUP_SDHCI
help
select SAMSUNG_DEV_BACKLIGHT
select SAMSUNG_DEV_KEYPAD
select SAMSUNG_DEV_PWM
- select EXYNOS4_DEV_DMA
+ select EXYNOS_DEV_DMA
select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_I2C3
select EXYNOS4_SETUP_I2C7
obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-ahci.o
obj-$(CONFIG_EXYNOS4_DEV_SYSMMU) += dev-sysmmu.o
obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o
-obj-$(CONFIG_EXYNOS4_DEV_DMA) += dma.o
+obj-$(CONFIG_EXYNOS_DEV_DMA) += dma.o
obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI) += dev-ohci.o
obj-$(CONFIG_ARCH_EXYNOS) += setup-i2c0.o
.reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 24, .size = 3 },
};
+static struct clk clk_fout_bpll_div2 = {
+ .name = "fout_bpll_div2",
+};
+
+static struct clk *exynos5_clkset_mout_bpll_fout_list[] = {
+ [0] = &clk_fout_bpll_div2,
+ [1] = &clk_fout_bpll,
+};
+
+static struct clksrc_sources exynos5_clkset_mout_bpll_fout = {
+ .sources = exynos5_clkset_mout_bpll_fout_list,
+ .nr_sources = ARRAY_SIZE(exynos5_clkset_mout_bpll_fout_list),
+};
+
+static struct clksrc_clk exynos5_clk_mout_bpll_fout = {
+ .clk = {
+ .name = "mout_bpll_fout",
+ },
+ .sources = &exynos5_clkset_mout_bpll_fout,
+ .reg_src = { .reg = EXYNOS5_PLL_DIV2_SEL, .shift = 0, .size = 1 },
+};
+
+/* Possible clock sources for BPLL Mux */
+static struct clk *clk_src_bpll_list[] = {
+ [0] = &clk_fin_bpll,
+ [1] = &exynos5_clk_mout_bpll_fout.clk,
+};
+
+struct clksrc_sources clk_src_bpll = {
+ .sources = clk_src_bpll_list,
+ .nr_sources = ARRAY_SIZE(clk_src_bpll_list),
+};
+
static struct clksrc_clk exynos5_clk_mout_bpll = {
.clk = {
.name = "mout_bpll",
.reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 12, .size = 1 },
};
+static struct clk clk_fout_mpll_div2 = {
+ .name = "fout_mpll_div2",
+};
+
+static struct clk *exynos5_clkset_mout_mpll_fout_list[] = {
+ [0] = &clk_fout_mpll_div2,
+ [1] = &clk_fout_mpll,
+};
+
+static struct clksrc_sources exynos5_clkset_mout_mpll_fout = {
+ .sources = exynos5_clkset_mout_mpll_fout_list,
+ .nr_sources = ARRAY_SIZE(exynos5_clkset_mout_mpll_fout_list),
+};
+
+static struct clksrc_clk exynos5_clk_mout_mpll_fout = {
+ .clk = {
+ .name = "mout_mpll_fout",
+ },
+ .sources = &exynos5_clkset_mout_mpll_fout,
+ .reg_src = { .reg = EXYNOS5_PLL_DIV2_SEL, .shift = 4, .size = 1 },
+};
+
+static struct clk *exynos5_clk_src_mpll_list[] = {
+ [0] = &clk_fin_mpll,
+ [1] = &exynos5_clk_mout_mpll_fout.clk,
+};
+
+struct clksrc_sources exynos5_clk_src_mpll = {
+ .sources = exynos5_clk_src_mpll_list,
+ .nr_sources = ARRAY_SIZE(exynos5_clk_src_mpll_list),
+};
+
struct clksrc_clk exynos5_clk_mout_mpll = {
.clk = {
.name = "mout_mpll",
},
- .sources = &clk_src_mpll,
+ .sources = &exynos5_clk_src_mpll,
.reg_src = { .reg = EXYNOS5_CLKSRC_CORE1, .shift = 8, .size = 1 },
};
.enable = exynos5_clk_ip_peris_ctrl,
.ctrlbit = (1 << 20),
}, {
- .name = "hsmmc",
- .devname = "exynos4-sdhci.0",
+ .name = "watchdog",
+ .parent = &exynos5_clk_aclk_66.clk,
+ .enable = exynos5_clk_ip_peris_ctrl,
+ .ctrlbit = (1 << 19),
+ }, {
+ .name = "biu",
+ .devname = "dw_mmc.0",
.parent = &exynos5_clk_aclk_200.clk,
.enable = exynos5_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 12),
}, {
- .name = "hsmmc",
- .devname = "exynos4-sdhci.1",
+ .name = "biu",
+ .devname = "dw_mmc.1",
.parent = &exynos5_clk_aclk_200.clk,
.enable = exynos5_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 13),
}, {
- .name = "hsmmc",
- .devname = "exynos4-sdhci.2",
+ .name = "biu",
+ .devname = "dw_mmc.2",
.parent = &exynos5_clk_aclk_200.clk,
.enable = exynos5_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 14),
}, {
- .name = "hsmmc",
- .devname = "exynos4-sdhci.3",
+ .name = "biu",
+ .devname = "dw_mmc.3",
.parent = &exynos5_clk_aclk_200.clk,
.enable = exynos5_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 15),
- }, {
- .name = "dwmci",
- .parent = &exynos5_clk_aclk_200.clk,
- .enable = exynos5_clk_ip_fsys_ctrl,
- .ctrlbit = (1 << 16),
}, {
.name = "sata",
.devname = "ahci",
static struct clksrc_clk exynos5_clk_sclk_mmc0 = {
.clk = {
- .name = "sclk_mmc",
- .devname = "exynos4-sdhci.0",
+ .name = "ciu",
+ .devname = "dw_mmc.0",
.parent = &exynos5_clk_dout_mmc0.clk,
.enable = exynos5_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 0),
static struct clksrc_clk exynos5_clk_sclk_mmc1 = {
.clk = {
- .name = "sclk_mmc",
- .devname = "exynos4-sdhci.1",
+ .name = "ciu",
+ .devname = "dw_mmc.1",
.parent = &exynos5_clk_dout_mmc1.clk,
.enable = exynos5_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 4),
static struct clksrc_clk exynos5_clk_sclk_mmc2 = {
.clk = {
- .name = "sclk_mmc",
- .devname = "exynos4-sdhci.2",
+ .name = "ciu",
+ .devname = "dw_mmc.2",
.parent = &exynos5_clk_dout_mmc2.clk,
.enable = exynos5_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 8),
static struct clksrc_clk exynos5_clk_sclk_mmc3 = {
.clk = {
- .name = "sclk_mmc",
- .devname = "exynos4-sdhci.3",
+ .name = "ciu",
+ .devname = "dw_mmc.3",
.parent = &exynos5_clk_dout_mmc3.clk,
.enable = exynos5_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 12),
static struct clksrc_clk exynos5_clksrcs[] = {
{
- .clk = {
- .name = "sclk_dwmci",
- .parent = &exynos5_clk_dout_mmc4.clk,
- .enable = exynos5_clksrc_mask_fsys_ctrl,
- .ctrlbit = (1 << 16),
- },
- .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS3, .shift = 8, .size = 8 },
- }, {
.clk = {
.name = "sclk_fimd",
.devname = "s3cfb.1",
&exynos5_clk_mout_apll,
&exynos5_clk_sclk_apll,
&exynos5_clk_mout_bpll,
+ &exynos5_clk_mout_bpll_fout,
&exynos5_clk_mout_bpll_user,
&exynos5_clk_mout_cpll,
&exynos5_clk_mout_epll,
&exynos5_clk_mout_mpll,
+ &exynos5_clk_mout_mpll_fout,
&exynos5_clk_mout_mpll_user,
&exynos5_clk_vpllsrc,
&exynos5_clk_sclk_vpll,
&exynos5_clk_sclk_hdmi27m,
&exynos5_clk_sclk_hdmiphy,
&clk_fout_bpll,
+ &clk_fout_bpll_div2,
+ &clk_fout_mpll_div2,
&clk_fout_cpll,
&exynos5_clk_armclk,
};
clk_fout_apll.ops = &exynos5_fout_apll_ops;
clk_fout_bpll.rate = bpll;
+ clk_fout_bpll_div2.rate = bpll >> 1;
clk_fout_cpll.rate = cpll;
clk_fout_mpll.rate = mpll;
+ clk_fout_mpll_div2.rate = mpll >> 1;
clk_fout_epll.rate = epll;
clk_fout_vpll.rate = vpll;
#include <linux/serial_core.h>
#include <linux/of.h>
#include <linux/of_irq.h>
+#include <linux/export.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
#include <asm/proc-fns.h>
#include <asm/exception.h>
static void exynos5_init_clocks(int xtal);
static void exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no);
static int exynos_init(void);
+static int exynos_init_irq_eint(struct device_node *np,
+ struct device_node *parent);
static struct cpu_table cpu_ids[] __initdata = {
{
}, {
.virtual = (unsigned long)S5P_VA_GIC_CPU,
.pfn = __phys_to_pfn(EXYNOS5_PA_GIC_CPU),
- .length = SZ_64K,
+ .length = SZ_8K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_GIC_DIST,
.pfn = __phys_to_pfn(EXYNOS5_PA_GIC_DIST),
- .length = SZ_64K,
+ .length = SZ_4K,
.type = MT_DEVICE,
},
};
void __iomem *base;
};
+static struct irq_domain *combiner_irq_domain;
static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
static inline void __iomem *combiner_base(struct irq_data *data)
static void combiner_mask_irq(struct irq_data *data)
{
- u32 mask = 1 << (data->irq % 32);
+ u32 mask = 1 << (data->hwirq % 32);
__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
}
static void combiner_unmask_irq(struct irq_data *data)
{
- u32 mask = 1 << (data->irq % 32);
+ u32 mask = 1 << (data->hwirq % 32);
__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
}
irq_set_chained_handler(irq, combiner_handle_cascade_irq);
}
-static void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
- unsigned int irq_start)
+static void __init combiner_init_one(unsigned int combiner_nr,
+ void __iomem *base)
{
- unsigned int i;
- unsigned int max_nr;
-
- if (soc_is_exynos5250())
- max_nr = EXYNOS5_MAX_COMBINER_NR;
- else
- max_nr = EXYNOS4_MAX_COMBINER_NR;
-
- if (combiner_nr >= max_nr)
- BUG();
-
combiner_data[combiner_nr].base = base;
- combiner_data[combiner_nr].irq_offset = irq_start;
+ combiner_data[combiner_nr].irq_offset = irq_find_mapping(
+ combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER);
combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
/* Disable all interrupts */
__raw_writel(combiner_data[combiner_nr].irq_mask,
base + COMBINER_ENABLE_CLEAR);
+}
+
+#ifdef CONFIG_OF
+static int combiner_irq_domain_xlate(struct irq_domain *d,
+ struct device_node *controller, const u32 *intspec,
+ unsigned int intsize, unsigned long *out_hwirq,
+ unsigned int *out_type)
+{
+ if (d->of_node != controller)
+ return -EINVAL;
+ if (intsize < 2)
+ return -EINVAL;
+ *out_hwirq = intspec[0] * MAX_IRQ_IN_COMBINER + intspec[1];
+ *out_type = 0;
+ return 0;
+}
+#else
+static int combiner_irq_domain_xlate(struct irq_domain *d,
+ struct device_node *controller, const u32 *intspec,
+ unsigned int intsize, unsigned long *out_hwirq,
+ unsigned int *out_type)
+{
+ return -EINVAL;
+}
+#endif
+
+static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(irq, &combiner_chip, handle_level_irq);
+ irq_set_chip_data(irq, &combiner_data[hw >> 3]);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ return 0;
+}
+
+static struct irq_domain_ops combiner_irq_domain_ops = {
+ .xlate = combiner_irq_domain_xlate,
+ .map = combiner_irq_domain_map,
+};
+
+void __init combiner_init(void __iomem *combiner_base, struct device_node *np)
+{
+ int i, irq, irq_base;
+ unsigned int max_nr, nr_irq;
+
+ if (np) {
+ if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) {
+ pr_warning("%s: number of combiners not specified, "
+ "setting default as %d.\n",
+ __func__, EXYNOS4_MAX_COMBINER_NR);
+ max_nr = EXYNOS4_MAX_COMBINER_NR;
+ }
+ } else {
+ max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR :
+ EXYNOS4_MAX_COMBINER_NR;
+ }
+ nr_irq = max_nr * MAX_IRQ_IN_COMBINER;
- /* Setup the Linux IRQ subsystem */
+ irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0);
+ if (IS_ERR_VALUE(irq_base)) {
+ irq_base = COMBINER_IRQ(0, 0);
+ pr_warning("%s: irq desc alloc failed. Continuing with %d as "
+ "linux irq base\n", __func__, irq_base);
+ }
+
+ combiner_irq_domain = irq_domain_add_legacy(np, nr_irq, irq_base, 0,
+ &combiner_irq_domain_ops, &combiner_data);
+ if (WARN_ON(!combiner_irq_domain)) {
+ pr_warning("%s: irq domain init failed\n", __func__);
+ return;
+ }
- for (i = irq_start; i < combiner_data[combiner_nr].irq_offset
- + MAX_IRQ_IN_COMBINER; i++) {
- irq_set_chip_and_handler(i, &combiner_chip, handle_level_irq);
- irq_set_chip_data(i, &combiner_data[combiner_nr]);
- set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+ for (i = 0; i < max_nr; i++) {
+ combiner_init_one(i, combiner_base + (i >> 2) * 0x10);
+ irq = np ? irq_of_parse_and_map(np, i) : IRQ_SPI(i);
+ combiner_cascade_irq(i, irq);
}
}
#ifdef CONFIG_OF
+int __init combiner_of_init(struct device_node *np, struct device_node *parent)
+{
+ void __iomem *combiner_base;
+
+ combiner_base = of_iomap(np, 0);
+ if (!combiner_base) {
+ pr_err("%s: failed to map combiner registers\n", __func__);
+ return -ENXIO;
+ }
+
+ combiner_init(combiner_base, np);
+ return 0;
+}
+
static const struct of_device_id exynos4_dt_irq_match[] = {
{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+ { .compatible = "samsung,exynos4210-combiner",
+ .data = combiner_of_init, },
+ { .compatible = "samsung,exynos5210-wakeup-eint-map",
+ .data = exynos_init_irq_eint, },
{},
};
#endif
void __init exynos4_init_irq(void)
{
- int irq;
unsigned int gic_bank_offset;
gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
of_irq_init(exynos4_dt_irq_match);
#endif
- for (irq = 0; irq < EXYNOS4_MAX_COMBINER_NR; irq++) {
-
- combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
- COMBINER_IRQ(irq, 0));
- combiner_cascade_irq(irq, IRQ_SPI(irq));
+ if (!of_have_populated_dt()) {
+ combiner_init(S5P_VA_COMBINER_BASE, NULL);
+ exynos_init_irq_eint(NULL, NULL);
}
/*
void __init exynos5_init_irq(void)
{
- int irq;
-
#ifdef CONFIG_OF
of_irq_init(exynos4_dt_irq_match);
#endif
-
- for (irq = 0; irq < EXYNOS5_MAX_COMBINER_NR; irq++) {
- combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
- COMBINER_IRQ(irq, 0));
- combiner_cascade_irq(irq, IRQ_SPI(irq));
- }
-
/*
* The parameters of s5p_init_irq() are for VIC init.
* Theses parameters should be NULL and 0 because EXYNOS4
s5p_init_irq(NULL, 0);
}
-struct bus_type exynos4_subsys = {
- .name = "exynos4-core",
- .dev_name = "exynos4-core",
-};
-
-struct bus_type exynos5_subsys = {
- .name = "exynos5-core",
- .dev_name = "exynos5-core",
+struct bus_type exynos_subsys = {
+ .name = "exynos-core",
+ .dev_name = "exynos-core",
};
static struct device exynos4_dev = {
- .bus = &exynos4_subsys,
-};
-
-static struct device exynos5_dev = {
- .bus = &exynos5_subsys,
+ .bus = &exynos_subsys,
};
static int __init exynos_core_init(void)
{
- if (soc_is_exynos5250())
- return subsys_system_register(&exynos5_subsys, NULL);
- else
- return subsys_system_register(&exynos4_subsys, NULL);
+ return subsys_system_register(&exynos_subsys, NULL);
}
core_initcall(exynos_core_init);
{
printk(KERN_INFO "EXYNOS: Initializing architecture\n");
- if (soc_is_exynos5250())
- return device_register(&exynos5_dev);
- else
- return device_register(&exynos4_dev);
+ return device_register(&exynos4_dev);
}
/* uart registration process */
static unsigned int eint0_15_data[16];
+#define EXYNOS_EINT_NR 32
+static struct irq_domain *irq_domain;
+
static inline int exynos4_irq_to_gpio(unsigned int irq)
{
if (irq < IRQ_EINT(0))
u32 mask;
spin_lock(&eint_lock);
- mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq));
- mask |= EINT_OFFSET_BIT(data->irq);
- __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq));
+ mask = __raw_readl(EINT_MASK(exynos_eint_base, data->hwirq));
+ mask |= EINT_OFFSET_BIT(data->hwirq);
+ __raw_writel(mask, EINT_MASK(exynos_eint_base, data->hwirq));
spin_unlock(&eint_lock);
}
u32 mask;
spin_lock(&eint_lock);
- mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq));
- mask &= ~(EINT_OFFSET_BIT(data->irq));
- __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq));
+ mask = __raw_readl(EINT_MASK(exynos_eint_base, data->hwirq));
+ mask &= ~(EINT_OFFSET_BIT(data->hwirq));
+ __raw_writel(mask, EINT_MASK(exynos_eint_base, data->hwirq));
spin_unlock(&eint_lock);
}
static inline void exynos_irq_eint_ack(struct irq_data *data)
{
- __raw_writel(EINT_OFFSET_BIT(data->irq),
- EINT_PEND(exynos_eint_base, data->irq));
+ __raw_writel(EINT_OFFSET_BIT(data->hwirq),
+ EINT_PEND(exynos_eint_base, data->hwirq));
}
static void exynos_irq_eint_maskack(struct irq_data *data)
static int exynos_irq_eint_set_type(struct irq_data *data, unsigned int type)
{
- int offs = EINT_OFFSET(data->irq);
+ int offs = data->hwirq;
int shift;
u32 ctrl, mask;
u32 newvalue = 0;
mask = 0x7 << shift;
spin_lock(&eint_lock);
- ctrl = __raw_readl(EINT_CON(exynos_eint_base, data->irq));
+ ctrl = __raw_readl(EINT_CON(exynos_eint_base, data->hwirq));
ctrl &= ~mask;
ctrl |= newvalue << shift;
- __raw_writel(ctrl, EINT_CON(exynos_eint_base, data->irq));
+ __raw_writel(ctrl, EINT_CON(exynos_eint_base, data->hwirq));
spin_unlock(&eint_lock);
if (soc_is_exynos5250())
while (status) {
irq = fls(status) - 1;
- generic_handle_irq(irq + start);
+ generic_handle_irq(irq_find_mapping(irq_domain, irq + start));
status &= ~(1 << irq);
}
}
{
struct irq_chip *chip = irq_get_chip(irq);
chained_irq_enter(chip, desc);
- exynos_irq_demux_eint(IRQ_EINT(16));
- exynos_irq_demux_eint(IRQ_EINT(24));
+ exynos_irq_demux_eint(16);
+ exynos_irq_demux_eint(24);
chained_irq_exit(chip, desc);
}
{
u32 *irq_data = irq_get_handler_data(irq);
struct irq_chip *chip = irq_get_chip(irq);
+ int eint_irq;
chained_irq_enter(chip, desc);
chip->irq_mask(&desc->irq_data);
if (chip->irq_ack)
chip->irq_ack(&desc->irq_data);
- generic_handle_irq(*irq_data);
+ eint_irq = irq_find_mapping(irq_domain, *irq_data);
+ generic_handle_irq(eint_irq);
chip->irq_unmask(&desc->irq_data);
chained_irq_exit(chip, desc);
}
-static int __init exynos_init_irq_eint(void)
+static int exynos_eint_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
{
- int irq;
+ irq_set_chip_and_handler(irq, &exynos_irq_eint, handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ return 0;
+}
- if (soc_is_exynos5250())
- exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
- else
- exynos_eint_base = ioremap(EXYNOS4_PA_GPIO2, SZ_4K);
+#ifdef CONFIG_OF
+static int exynos_eint_irq_domain_xlate(struct irq_domain *d,
+ struct device_node *controller, const u32 *intspec,
+ unsigned int intsize, unsigned long *out_hwirq,
+ unsigned int *out_type)
+{
+ if (d->of_node != controller)
+ return -EINVAL;
+ if (intsize < 2)
+ return -EINVAL;
+ *out_hwirq = intspec[0];
+
+ switch (intspec[1]) {
+ case S5P_IRQ_TYPE_LEVEL_LOW:
+ *out_type = IRQ_TYPE_LEVEL_LOW;
+ break;
+ case S5P_IRQ_TYPE_LEVEL_HIGH:
+ *out_type = IRQ_TYPE_LEVEL_HIGH;
+ break;
+ case S5P_IRQ_TYPE_EDGE_FALLING:
+ *out_type = IRQ_TYPE_EDGE_FALLING;
+ break;
+ case S5P_IRQ_TYPE_EDGE_RISING:
+ *out_type = IRQ_TYPE_EDGE_RISING;
+ break;
+ case S5P_IRQ_TYPE_EDGE_BOTH:
+ *out_type = IRQ_TYPE_EDGE_BOTH;
+ break;
+ };
+
+ return 0;
+}
+#else
+static int exynos_eint_irq_domain_xlate(struct irq_domain *d,
+ struct device_node *controller, const u32 *intspec,
+ unsigned int intsize, unsigned long *out_hwirq,
+ unsigned int *out_type)
+{
+ return -EINVAL;
+}
+#endif
+
+static struct irq_domain_ops exynos_eint_irq_domain_ops = {
+ .xlate = exynos_eint_irq_domain_xlate,
+ .map = exynos_eint_irq_domain_map,
+};
- if (exynos_eint_base == NULL) {
+static int __init exynos_init_irq_eint(struct device_node *eint_np,
+ struct device_node *parent)
+{
+ int irq, *src_int, irq_base, irq_eint;
+ unsigned int paddr;
+ static unsigned int retry = 0;
+ static struct device_node *np;
+
+ if (retry)
+ goto retry_init;
+
+ if (!eint_np) {
+ paddr = soc_is_exynos5250() ? EXYNOS5_PA_GPIO1 :
+ EXYNOS4_PA_GPIO2;
+ exynos_eint_base = ioremap(paddr, SZ_4K);
+ } else {
+ np = of_get_parent(eint_np);
+ exynos_eint_base = of_iomap(np, 0);
+ }
+ if (!exynos_eint_base) {
pr_err("unable to ioremap for EINT base address\n");
- return -ENOMEM;
+ return -ENXIO;
}
- for (irq = 0 ; irq <= 31 ; irq++) {
- irq_set_chip_and_handler(IRQ_EINT(irq), &exynos_irq_eint,
- handle_level_irq);
- set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
+ irq_base = irq_alloc_descs(IRQ_EINT(0), 1, EXYNOS_EINT_NR, 0);
+ if (IS_ERR_VALUE(irq_base)) {
+ irq_base = IRQ_EINT(0);
+ pr_warning("%s: irq desc alloc failed. Continuing with %d as "
+ "linux irq base\n", __func__, irq_base);
+ }
+
+ irq_domain = irq_domain_add_legacy(np, EXYNOS_EINT_NR, irq_base, 0,
+ &exynos_eint_irq_domain_ops, NULL);
+ if (WARN_ON(!irq_domain)) {
+ pr_warning("%s: irq domain init failed\n", __func__);
+ return 0;
}
- irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos_irq_demux_eint16_31);
-
- for (irq = 0 ; irq <= 15 ; irq++) {
- eint0_15_data[irq] = IRQ_EINT(irq);
-
- if (soc_is_exynos5250()) {
- irq_set_handler_data(exynos5_eint0_15_src_int[irq],
- &eint0_15_data[irq]);
- irq_set_chained_handler(exynos5_eint0_15_src_int[irq],
- exynos_irq_eint0_15);
- } else {
- irq_set_handler_data(exynos4_eint0_15_src_int[irq],
- &eint0_15_data[irq]);
- irq_set_chained_handler(exynos4_eint0_15_src_int[irq],
- exynos_irq_eint0_15);
+ irq_eint = eint_np ? irq_of_parse_and_map(np, 16) : EXYNOS_IRQ_EINT16_31;
+ irq_set_chained_handler(irq_eint, exynos_irq_demux_eint16_31);
+
+retry_init:
+ for (irq = 0; irq <= 15; irq++) {
+ eint0_15_data[irq] = irq;
+ src_int = soc_is_exynos5250() ? exynos5_eint0_15_src_int :
+ exynos4_eint0_15_src_int;
+ irq_eint = eint_np ? irq_of_parse_and_map(np, irq) : src_int[irq];
+ if (!irq_eint) {
+ of_node_put(np);
+ retry = 1;
+ return -EAGAIN;
}
+ irq_set_handler_data(irq_eint, &eint0_15_data[irq]);
+ irq_set_chained_handler(irq_eint, exynos_irq_eint0_15);
}
return 0;
}
-arch_initcall(exynos_init_irq_eint);
DMACH_MIPI_HSI5,
};
-struct dma_pl330_platdata exynos4_pdma0_pdata;
+static u8 exynos5250_pdma0_peri[] = {
+ DMACH_PCM0_RX,
+ DMACH_PCM0_TX,
+ DMACH_PCM2_RX,
+ DMACH_PCM2_TX,
+ DMACH_SPI0_RX,
+ DMACH_SPI0_TX,
+ DMACH_SPI2_RX,
+ DMACH_SPI2_TX,
+ DMACH_I2S0S_TX,
+ DMACH_I2S0_RX,
+ DMACH_I2S0_TX,
+ DMACH_I2S2_RX,
+ DMACH_I2S2_TX,
+ DMACH_UART0_RX,
+ DMACH_UART0_TX,
+ DMACH_UART2_RX,
+ DMACH_UART2_TX,
+ DMACH_UART4_RX,
+ DMACH_UART4_TX,
+ DMACH_SLIMBUS0_RX,
+ DMACH_SLIMBUS0_TX,
+ DMACH_SLIMBUS2_RX,
+ DMACH_SLIMBUS2_TX,
+ DMACH_SLIMBUS4_RX,
+ DMACH_SLIMBUS4_TX,
+ DMACH_AC97_MICIN,
+ DMACH_AC97_PCMIN,
+ DMACH_AC97_PCMOUT,
+ DMACH_MIPI_HSI0,
+ DMACH_MIPI_HSI2,
+ DMACH_MIPI_HSI4,
+ DMACH_MIPI_HSI6,
+};
+
+static struct dma_pl330_platdata exynos_pdma0_pdata;
static AMBA_AHB_DEVICE(exynos4_pdma0, "dma-pl330.0", 0x00041330,
- EXYNOS4_PA_PDMA0, {EXYNOS4_IRQ_PDMA0}, &exynos4_pdma0_pdata);
+ EXYNOS4_PA_PDMA0, {EXYNOS4_IRQ_PDMA0}, &exynos_pdma0_pdata);
static u8 exynos4210_pdma1_peri[] = {
DMACH_PCM0_RX,
DMACH_MIPI_HSI7,
};
-static struct dma_pl330_platdata exynos4_pdma1_pdata;
+static u8 exynos5250_pdma1_peri[] = {
+ DMACH_PCM0_RX,
+ DMACH_PCM0_TX,
+ DMACH_PCM1_RX,
+ DMACH_PCM1_TX,
+ DMACH_SPI1_RX,
+ DMACH_SPI1_TX,
+ DMACH_PWM,
+ DMACH_SPDIF,
+ DMACH_I2S0S_TX,
+ DMACH_I2S0_RX,
+ DMACH_I2S0_TX,
+ DMACH_I2S1_RX,
+ DMACH_I2S1_TX,
+ DMACH_UART0_RX,
+ DMACH_UART0_TX,
+ DMACH_UART1_RX,
+ DMACH_UART1_TX,
+ DMACH_UART3_RX,
+ DMACH_UART3_TX,
+ DMACH_SLIMBUS1_RX,
+ DMACH_SLIMBUS1_TX,
+ DMACH_SLIMBUS3_RX,
+ DMACH_SLIMBUS3_TX,
+ DMACH_SLIMBUS5_RX,
+ DMACH_SLIMBUS5_TX,
+ DMACH_SLIMBUS0AUX_RX,
+ DMACH_SLIMBUS0AUX_TX,
+ DMACH_DISP1,
+ DMACH_MIPI_HSI1,
+ DMACH_MIPI_HSI3,
+ DMACH_MIPI_HSI5,
+ DMACH_MIPI_HSI7,
+};
+
+static struct dma_pl330_platdata exynos_pdma1_pdata;
static AMBA_AHB_DEVICE(exynos4_pdma1, "dma-pl330.1", 0x00041330,
- EXYNOS4_PA_PDMA1, {EXYNOS4_IRQ_PDMA1}, &exynos4_pdma1_pdata);
+ EXYNOS4_PA_PDMA1, {EXYNOS4_IRQ_PDMA1}, &exynos_pdma1_pdata);
static u8 mdma_peri[] = {
DMACH_MTOM_0,
DMACH_MTOM_7,
};
-static struct dma_pl330_platdata exynos4_mdma1_pdata = {
+static struct dma_pl330_platdata exynos_mdma1_pdata = {
.nr_valid_peri = ARRAY_SIZE(mdma_peri),
.peri_id = mdma_peri,
};
static AMBA_AHB_DEVICE(exynos4_mdma1, "dma-pl330.2", 0x00041330,
- EXYNOS4_PA_MDMA1, {EXYNOS4_IRQ_MDMA1}, &exynos4_mdma1_pdata);
+ EXYNOS4_PA_MDMA1, {EXYNOS4_IRQ_MDMA1}, &exynos_mdma1_pdata);
-static int __init exynos4_dma_init(void)
+static int __init exynos_dma_init(void)
{
if (of_have_populated_dt())
return 0;
if (soc_is_exynos4210()) {
- exynos4_pdma0_pdata.nr_valid_peri =
+ exynos_pdma0_pdata.nr_valid_peri =
ARRAY_SIZE(exynos4210_pdma0_peri);
- exynos4_pdma0_pdata.peri_id = exynos4210_pdma0_peri;
- exynos4_pdma1_pdata.nr_valid_peri =
+ exynos_pdma0_pdata.peri_id = exynos4210_pdma0_peri;
+ exynos_pdma1_pdata.nr_valid_peri =
ARRAY_SIZE(exynos4210_pdma1_peri);
- exynos4_pdma1_pdata.peri_id = exynos4210_pdma1_peri;
+ exynos_pdma1_pdata.peri_id = exynos4210_pdma1_peri;
} else if (soc_is_exynos4212() || soc_is_exynos4412()) {
- exynos4_pdma0_pdata.nr_valid_peri =
+ exynos_pdma0_pdata.nr_valid_peri =
ARRAY_SIZE(exynos4212_pdma0_peri);
- exynos4_pdma0_pdata.peri_id = exynos4212_pdma0_peri;
- exynos4_pdma1_pdata.nr_valid_peri =
+ exynos_pdma0_pdata.peri_id = exynos4212_pdma0_peri;
+ exynos_pdma1_pdata.nr_valid_peri =
ARRAY_SIZE(exynos4212_pdma1_peri);
- exynos4_pdma1_pdata.peri_id = exynos4212_pdma1_peri;
+ exynos_pdma1_pdata.peri_id = exynos4212_pdma1_peri;
+ } else if (soc_is_exynos5250()) {
+ exynos_pdma0_pdata.nr_valid_peri =
+ ARRAY_SIZE(exynos5250_pdma0_peri);
+ exynos_pdma0_pdata.peri_id = exynos5250_pdma0_peri;
+ exynos_pdma1_pdata.nr_valid_peri =
+ ARRAY_SIZE(exynos5250_pdma1_peri);
+ exynos_pdma1_pdata.peri_id = exynos5250_pdma1_peri;
+
+ exynos4_pdma0_device.res.start = EXYNOS5_PA_PDMA0;
+ exynos4_pdma0_device.res.end = EXYNOS5_PA_PDMA0 + SZ_4K;
+ exynos4_pdma0_device.irq[0] = EXYNOS5_IRQ_PDMA0;
+ exynos4_pdma1_device.res.start = EXYNOS5_PA_PDMA1;
+ exynos4_pdma1_device.res.end = EXYNOS5_PA_PDMA1 + SZ_4K;
+ exynos4_pdma0_device.irq[0] = EXYNOS5_IRQ_PDMA1;
+ exynos4_mdma1_device.res.start = EXYNOS5_PA_MDMA1;
+ exynos4_mdma1_device.res.end = EXYNOS5_PA_MDMA1 + SZ_4K;
+ exynos4_pdma0_device.irq[0] = EXYNOS5_IRQ_MDMA1;
}
- dma_cap_set(DMA_SLAVE, exynos4_pdma0_pdata.cap_mask);
- dma_cap_set(DMA_CYCLIC, exynos4_pdma0_pdata.cap_mask);
+ dma_cap_set(DMA_SLAVE, exynos_pdma0_pdata.cap_mask);
+ dma_cap_set(DMA_CYCLIC, exynos_pdma0_pdata.cap_mask);
amba_device_register(&exynos4_pdma0_device, &iomem_resource);
- dma_cap_set(DMA_SLAVE, exynos4_pdma1_pdata.cap_mask);
- dma_cap_set(DMA_CYCLIC, exynos4_pdma1_pdata.cap_mask);
+ dma_cap_set(DMA_SLAVE, exynos_pdma1_pdata.cap_mask);
+ dma_cap_set(DMA_CYCLIC, exynos_pdma1_pdata.cap_mask);
amba_device_register(&exynos4_pdma1_device, &iomem_resource);
- dma_cap_set(DMA_MEMCPY, exynos4_mdma1_pdata.cap_mask);
+ dma_cap_set(DMA_MEMCPY, exynos_mdma1_pdata.cap_mask);
amba_device_register(&exynos4_mdma1_device, &iomem_resource);
return 0;
}
-arch_initcall(exynos4_dma_init);
+arch_initcall(exynos_dma_init);
#define EXYNOS5_GPIO_B2_NR (4)
#define EXYNOS5_GPIO_B3_NR (4)
#define EXYNOS5_GPIO_C0_NR (7)
-#define EXYNOS5_GPIO_C1_NR (7)
+#define EXYNOS5_GPIO_C1_NR (4)
#define EXYNOS5_GPIO_C2_NR (7)
#define EXYNOS5_GPIO_C3_NR (7)
-#define EXYNOS5_GPIO_D0_NR (8)
+#define EXYNOS5_GPIO_C4_NR (7)
+#define EXYNOS5_GPIO_D0_NR (4)
#define EXYNOS5_GPIO_D1_NR (8)
#define EXYNOS5_GPIO_Y0_NR (6)
#define EXYNOS5_GPIO_Y1_NR (4)
EXYNOS5_GPIO_C1_START = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_C0),
EXYNOS5_GPIO_C2_START = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_C1),
EXYNOS5_GPIO_C3_START = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_C2),
- EXYNOS5_GPIO_D0_START = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_C3),
+ EXYNOS5_GPIO_C4_START = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_C3),
+ EXYNOS5_GPIO_D0_START = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_C4),
EXYNOS5_GPIO_D1_START = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_D0),
EXYNOS5_GPIO_Y0_START = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_D1),
EXYNOS5_GPIO_Y1_START = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_Y0),
#define EXYNOS5_GPC1(_nr) (EXYNOS5_GPIO_C1_START + (_nr))
#define EXYNOS5_GPC2(_nr) (EXYNOS5_GPIO_C2_START + (_nr))
#define EXYNOS5_GPC3(_nr) (EXYNOS5_GPIO_C3_START + (_nr))
+#define EXYNOS5_GPC4(_nr) (EXYNOS5_GPIO_C4_START + (_nr))
#define EXYNOS5_GPD0(_nr) (EXYNOS5_GPIO_D0_START + (_nr))
#define EXYNOS5_GPD1(_nr) (EXYNOS5_GPIO_D1_START + (_nr))
#define EXYNOS5_GPY0(_nr) (EXYNOS5_GPIO_Y0_START + (_nr))
#define EXYNOS5_IRQ_MIPICSI1 IRQ_SPI(80)
#define EXYNOS5_IRQ_EFNFCON_DMA_ABORT IRQ_SPI(81)
#define EXYNOS5_IRQ_MIPIDSI0 IRQ_SPI(82)
+#define EXYNOS5_IRQ_WDT_IOP IRQ_SPI(83)
#define EXYNOS5_IRQ_ROTATOR IRQ_SPI(84)
#define EXYNOS5_IRQ_GSC0 IRQ_SPI(85)
#define EXYNOS5_IRQ_GSC1 IRQ_SPI(86)
#define EXYNOS5_IRQ_JPEG IRQ_SPI(89)
#define EXYNOS5_IRQ_EFNFCON_DMA IRQ_SPI(90)
#define EXYNOS5_IRQ_2D IRQ_SPI(91)
-#define EXYNOS5_IRQ_SFMC0 IRQ_SPI(92)
-#define EXYNOS5_IRQ_SFMC1 IRQ_SPI(93)
+#define EXYNOS5_IRQ_EFNFCON_0 IRQ_SPI(92)
+#define EXYNOS5_IRQ_EFNFCON_1 IRQ_SPI(93)
#define EXYNOS5_IRQ_MIXER IRQ_SPI(94)
#define EXYNOS5_IRQ_HDMI IRQ_SPI(95)
#define EXYNOS5_IRQ_MFC IRQ_SPI(96)
#define EXYNOS5_IRQ_PCM2 IRQ_SPI(104)
#define EXYNOS5_IRQ_SPDIF IRQ_SPI(105)
#define EXYNOS5_IRQ_ADC0 IRQ_SPI(106)
-
+#define EXYNOS5_IRQ_ADC1 IRQ_SPI(107)
#define EXYNOS5_IRQ_SATA_PHY IRQ_SPI(108)
#define EXYNOS5_IRQ_SATA_PMEMREQ IRQ_SPI(109)
#define EXYNOS5_IRQ_CAM_C IRQ_SPI(110)
#define EXYNOS5_IRQ_DP1_INTP1 IRQ_SPI(113)
#define EXYNOS5_IRQ_CEC IRQ_SPI(114)
#define EXYNOS5_IRQ_SATA IRQ_SPI(115)
-#define EXYNOS5_IRQ_NFCON IRQ_SPI(116)
+#define EXYNOS5_IRQ_MCT_L0 IRQ_SPI(120)
+#define EXYNOS5_IRQ_MCT_L1 IRQ_SPI(121)
#define EXYNOS5_IRQ_MMC44 IRQ_SPI(123)
#define EXYNOS5_IRQ_MDMA1 IRQ_SPI(124)
#define EXYNOS5_IRQ_FIMC_LITE0 IRQ_SPI(125)
#define EXYNOS5_IRQ_RP_TIMER IRQ_SPI(127)
#define EXYNOS5_IRQ_PMU COMBINER_IRQ(1, 2)
-#define EXYNOS5_IRQ_PMU_CPU1 COMBINER_IRQ(1, 6)
#define EXYNOS5_IRQ_SYSMMU_GSC0_0 COMBINER_IRQ(2, 0)
#define EXYNOS5_IRQ_SYSMMU_GSC0_1 COMBINER_IRQ(2, 1)
#define EXYNOS5_IRQ_SYSMMU_GSC3_0 COMBINER_IRQ(2, 6)
#define EXYNOS5_IRQ_SYSMMU_GSC3_1 COMBINER_IRQ(2, 7)
+#define EXYNOS5_IRQ_SYSMMU_LITE2_0 COMBINER_IRQ(3, 0)
+#define EXYNOS5_IRQ_SYSMMU_LITE2_1 COMBINER_IRQ(3, 1)
#define EXYNOS5_IRQ_SYSMMU_FIMD1_0 COMBINER_IRQ(3, 2)
#define EXYNOS5_IRQ_SYSMMU_FIMD1_1 COMBINER_IRQ(3, 3)
#define EXYNOS5_IRQ_SYSMMU_LITE0_0 COMBINER_IRQ(3, 4)
#define EXYNOS5_IRQ_SYSMMU_ARM_0 COMBINER_IRQ(6, 0)
#define EXYNOS5_IRQ_SYSMMU_ARM_1 COMBINER_IRQ(6, 1)
-#define EXYNOS5_IRQ_SYSMMU_MFC_L_0 COMBINER_IRQ(6, 2)
-#define EXYNOS5_IRQ_SYSMMU_MFC_L_1 COMBINER_IRQ(6, 3)
+#define EXYNOS5_IRQ_SYSMMU_MFC_R_0 COMBINER_IRQ(6, 2)
+#define EXYNOS5_IRQ_SYSMMU_MFC_R_1 COMBINER_IRQ(6, 3)
#define EXYNOS5_IRQ_SYSMMU_RTIC_0 COMBINER_IRQ(6, 4)
#define EXYNOS5_IRQ_SYSMMU_RTIC_1 COMBINER_IRQ(6, 5)
#define EXYNOS5_IRQ_SYSMMU_SSS_0 COMBINER_IRQ(6, 6)
#define EXYNOS5_IRQ_SYSMMU_MDMA1_1 COMBINER_IRQ(7, 3)
#define EXYNOS5_IRQ_SYSMMU_TV_0 COMBINER_IRQ(7, 4)
#define EXYNOS5_IRQ_SYSMMU_TV_1 COMBINER_IRQ(7, 5)
-#define EXYNOS5_IRQ_SYSMMU_GPSX_0 COMBINER_IRQ(7, 6)
-#define EXYNOS5_IRQ_SYSMMU_GPSX_1 COMBINER_IRQ(7, 7)
-#define EXYNOS5_IRQ_SYSMMU_MFC_R_0 COMBINER_IRQ(8, 5)
-#define EXYNOS5_IRQ_SYSMMU_MFC_R_1 COMBINER_IRQ(8, 6)
+#define EXYNOS5_IRQ_SYSMMU_MFC_L_0 COMBINER_IRQ(8, 5)
+#define EXYNOS5_IRQ_SYSMMU_MFC_L_1 COMBINER_IRQ(8, 6)
#define EXYNOS5_IRQ_SYSMMU_DIS1_0 COMBINER_IRQ(9, 4)
#define EXYNOS5_IRQ_SYSMMU_DIS1_1 COMBINER_IRQ(9, 5)
#define EXYNOS5_IRQ_SYSMMU_DRC_0 COMBINER_IRQ(11, 6)
#define EXYNOS5_IRQ_SYSMMU_DRC_1 COMBINER_IRQ(11, 7)
+#define EXYNOS5_IRQ_MDMA1_ABORT COMBINER_IRQ(13, 1)
+
+#define EXYNOS5_IRQ_MDMA0_ABORT COMBINER_IRQ(15, 3)
+
#define EXYNOS5_IRQ_FIMD1_FIFO COMBINER_IRQ(18, 4)
#define EXYNOS5_IRQ_FIMD1_VSYNC COMBINER_IRQ(18, 5)
#define EXYNOS5_IRQ_FIMD1_SYSTEM COMBINER_IRQ(18, 6)
+#define EXYNOS5_IRQ_ARMIOP_GIC COMBINER_IRQ(19, 0)
+#define EXYNOS5_IRQ_ARMISP_GIC COMBINER_IRQ(19, 1)
+#define EXYNOS5_IRQ_IOP_GIC COMBINER_IRQ(19, 3)
+#define EXYNOS5_IRQ_ISP_GIC COMBINER_IRQ(19, 4)
+
+#define EXYNOS5_IRQ_PMU_CPU1 COMBINER_IRQ(22, 4)
+
#define EXYNOS5_IRQ_EINT0 COMBINER_IRQ(23, 0)
-#define EXYNOS5_IRQ_MCT_L0 COMBINER_IRQ(23, 1)
-#define EXYNOS5_IRQ_MCT_L1 COMBINER_IRQ(23, 2)
#define EXYNOS5_IRQ_MCT_G0 COMBINER_IRQ(23, 3)
#define EXYNOS5_IRQ_MCT_G1 COMBINER_IRQ(23, 4)
-#define EXYNOS5_IRQ_MCT_G2 COMBINER_IRQ(23, 5)
-#define EXYNOS5_IRQ_MCT_G3 COMBINER_IRQ(23, 6)
#define EXYNOS5_IRQ_EINT1 COMBINER_IRQ(24, 0)
#define EXYNOS5_IRQ_SYSMMU_LITE1_0 COMBINER_IRQ(24, 1)
#define EXYNOS5_MAX_COMBINER_NR 32
-#define EXYNOS5_IRQ_GPIO1_NR_GROUPS 13
+#define EXYNOS5_IRQ_GPIO1_NR_GROUPS 14
#define EXYNOS5_IRQ_GPIO2_NR_GROUPS 9
#define EXYNOS5_IRQ_GPIO3_NR_GROUPS 5
#define EXYNOS5_IRQ_GPIO4_NR_GROUPS 1
#define EXYNOS4_PA_GIC_CPU 0x10480000
#define EXYNOS4_PA_GIC_DIST 0x10490000
-#define EXYNOS5_PA_GIC_CPU 0x10480000
-#define EXYNOS5_PA_GIC_DIST 0x10490000
+#define EXYNOS5_PA_GIC_CPU 0x10482000
+#define EXYNOS5_PA_GIC_DIST 0x10481000
#define EXYNOS4_PA_COREPERI 0x10500000
#define EXYNOS4_PA_TWD 0x10500600
#define EXYNOS5_CLKGATE_IP_PERIS EXYNOS_CLKREG(0x10960)
#define EXYNOS5_CLKGATE_BLOCK EXYNOS_CLKREG(0x10980)
+#define EXYNOS5_PLL_DIV2_SEL EXYNOS_CLKREG(0x20A24)
+
#define EXYNOS5_BPLL_CON0 EXYNOS_CLKREG(0x20110)
#define EXYNOS5_CLKSRC_CDREX EXYNOS_CLKREG(0x20200)
#define EXYNOS5_CLKDIV_CDREX EXYNOS_CLKREG(0x20500)
#include <mach/map.h>
#include <mach/irqs.h>
-#define EINT_REG_NR(x) (EINT_OFFSET(x) >> 3)
+#define EINT_REG_NR(x) ((x) >> 3)
#define EINT_CON(b, x) (b + 0xE00 + (EINT_REG_NR(x) * 4))
#define EINT_FLTCON(b, x) (b + 0xE80 + (EINT_REG_NR(x) * 4))
#define EINT_MASK(b, x) (b + 0xF00 + (EINT_REG_NR(x) * 4))
#define EINT_PEND(b, x) (b + 0xF40 + (EINT_REG_NR(x) * 4))
-#define EINT_OFFSET_BIT(x) (1 << (EINT_OFFSET(x) & 0x7))
+#define EINT_OFFSET_BIT(x) (1 << ((x) & 0x7))
/* compatibility for plat-s5p/irq-pm.c */
#define EXYNOS4_EINT40CON (S5P_VA_GPIO2 + 0xE00)
#include <linux/of_platform.h>
#include <linux/serial_core.h>
+#include <linux/smsc911x.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
#include <plat/cpu.h>
#include <plat/regs-serial.h>
+#include <plat/regs-srom.h>
#include "common.h"
+static void __init smsc911x_init(int ncs)
+{
+ u32 data;
+
+ /* configure nCS1 width to 16 bits */
+ data = __raw_readl(S5P_SROM_BW) &
+ ~(S5P_SROM_BW__CS_MASK << (ncs * 4));
+ data |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
+ (1 << S5P_SROM_BW__WAITENABLE__SHIFT) |
+ (1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) << (ncs * 4);
+ __raw_writel(data, S5P_SROM_BW);
+
+ /* set timing for nCS1 suitable for ethernet chip */
+ __raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
+ (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
+ (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
+ (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
+ (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
+ (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
+ (0x1 << S5P_SROM_BCX__TACS__SHIFT),
+ S5P_SROM_BC0 + (ncs * 4));
+}
+
/*
* The following lookup table is used to override device names when devices
* are registered from device tree. This is temporarily added to enable
"exynos4210-uart.2", NULL),
OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART3,
"exynos4210-uart.3", NULL),
+ OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(0),
+ "s3c2440-i2c.0", NULL),
+ OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(1),
+ "s3c2440-i2c.1", NULL),
+ OF_DEV_AUXDATA("synopsis,dw-mshc-exynos5250", 0x12200000,
+ "dw_mmc.0", NULL),
+ OF_DEV_AUXDATA("synopsis,dw-mshc-exynos5250", 0x12210000,
+ "dw_mmc.1", NULL),
+ OF_DEV_AUXDATA("synopsis,dw-mshc-exynos5250", 0x12220000,
+ "dw_mmc.2", NULL),
+ OF_DEV_AUXDATA("synopsis,dw-mshc-exynos5250", 0x12230000,
+ "dw_mmc.3", 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),
static void __init exynos5250_dt_machine_init(void)
{
+ if (of_machine_is_compatible("samsung,smdk5250"))
+ smsc911x_init(1);
+
of_platform_populate(NULL, of_default_bus_match_table,
exynos5250_auxdata_lookup, NULL);
}
{
struct mct_clock_event_device *mevt;
unsigned int cpu = smp_processor_id();
+ int mct_lx_irq;
mevt = this_cpu_ptr(&percpu_mct_tick);
mevt->evt = evt;
if (mct_int_type == MCT_INT_SPI) {
if (cpu == 0) {
+ mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L0 :
+ EXYNOS5_IRQ_MCT_L0;
mct_tick0_event_irq.dev_id = mevt;
- evt->irq = EXYNOS4_IRQ_MCT_L0;
- setup_irq(EXYNOS4_IRQ_MCT_L0, &mct_tick0_event_irq);
+ evt->irq = mct_lx_irq;
+ setup_irq(mct_lx_irq, &mct_tick0_event_irq);
} else {
+ mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L1 :
+ EXYNOS5_IRQ_MCT_L1;
mct_tick1_event_irq.dev_id = mevt;
- evt->irq = EXYNOS4_IRQ_MCT_L1;
- setup_irq(EXYNOS4_IRQ_MCT_L1, &mct_tick1_event_irq);
- irq_set_affinity(EXYNOS4_IRQ_MCT_L1, cpumask_of(1));
+ evt->irq = mct_lx_irq;
+ setup_irq(mct_lx_irq, &mct_tick1_event_irq);
+ irq_set_affinity(mct_lx_irq, cpumask_of(1));
}
} else {
enable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER, 0);
static void __init exynos4_timer_init(void)
{
- if (soc_is_exynos4210())
+ if ((soc_is_exynos4210()) || (soc_is_exynos5250()))
mct_int_type = MCT_INT_SPI;
else
mct_int_type = MCT_INT_PPI;
static struct subsys_interface exynos4_pm_interface = {
.name = "exynos4_pm",
- .subsys = &exynos4_subsys,
+ .subsys = &exynos_subsys,
.add_dev = exynos4_pm_add,
};
.nr_sources = ARRAY_SIZE(clk_src_apll_list),
};
-/* Possible clock sources for BPLL Mux */
-static struct clk *clk_src_bpll_list[] = {
- [0] = &clk_fin_bpll,
- [1] = &clk_fout_bpll,
-};
-
-struct clksrc_sources clk_src_bpll = {
- .sources = clk_src_bpll_list,
- .nr_sources = ARRAY_SIZE(clk_src_bpll_list),
-};
-
/* Possible clock sources for CPLL Mux */
static struct clk *clk_src_cpll_list[] = {
[0] = &clk_fin_cpll,
config SAMSUNG_DMADEV
bool
select DMADEVICES
- select PL330_DMA if (CPU_EXYNOS4210 || CPU_S5PV210 || CPU_S5PC100 || \
+ select PL330_DMA if (ARCH_EXYNOS5 || ARCH_EXYNOS4 || CPU_S5PV210 || CPU_S5PC100 || \
CPU_S5P6450 || CPU_S5P6440)
select ARM_AMBA
help
extern struct bus_type s3c6410_subsys;
extern struct bus_type s5p64x0_subsys;
extern struct bus_type s5pv210_subsys;
-extern struct bus_type exynos4_subsys;
+extern struct bus_type exynos_subsys;
extern void (*s5pc1xx_idle)(void);
DMACH_MIPI_HSI5,
DMACH_MIPI_HSI6,
DMACH_MIPI_HSI7,
+ DMACH_DISP1,
DMACH_MTOM_0,
DMACH_MTOM_1,
DMACH_MTOM_2,
.ngpio = EXYNOS5_GPIO_C3_NR,
.label = "GPC3",
},
+ }, {
+ .chip = {
+ .base = EXYNOS5_GPC4(0),
+ .ngpio = EXYNOS5_GPIO_C4_NR,
+ .label = "GPC4",
+ },
}, {
.chip = {
.base = EXYNOS5_GPD0(0),
goto err_ioremap1;
}
+ /* need to set base address for gpc4 */
+ exynos5_gpios_1[11].base = gpio_base1 + 0x2E0;
+
/* need to set base address for gpx */
- chip = &exynos5_gpios_1[20];
+ chip = &exynos5_gpios_1[21];
gpx_base = gpio_base1 + 0xC00;
for (i = 0; i < 4; i++, chip++, gpx_base += 0x20)
chip->base = gpx_base;
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/dw_mmc.h>
+#include <linux/of.h>
#include "dw_mmc.h"
+#ifdef CONFIG_OF
+static struct dw_mci_drv_data synopsis_drv_data = {
+ .ctrl_type = DW_MCI_TYPE_SYNOPSIS,
+};
+
+static struct dw_mci_drv_data exynos5250_drv_data = {
+ .ctrl_type = DW_MCI_TYPE_EXYNOS5250,
+ .caps = MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR |
+ MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23,
+};
+
+static const struct of_device_id dw_mci_pltfm_match[] = {
+ { .compatible = "synopsis,dw-mshc",
+ .data = (void *)&synopsis_drv_data, },
+ { .compatible = "synopsis,dw-mshc-exynos5250",
+ .data = (void *)&exynos5250_drv_data, },
+ {},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
+#else
+static const struct of_device_id dw_mci_pltfm_match[];
+#endif
+
static int dw_mci_pltfm_probe(struct platform_device *pdev)
{
struct dw_mci *host;
if (!host->regs)
goto err_free;
platform_set_drvdata(pdev, host);
+
+ if (pdev->dev.of_node) {
+ const struct of_device_id *match;
+ match = of_match_node(dw_mci_pltfm_match, pdev->dev.of_node);
+ host->drv_data = match->data;
+ }
+
ret = dw_mci_probe(host);
if (ret)
goto err_out;
.remove = __exit_p(dw_mci_pltfm_remove),
.driver = {
.name = "dw_mmc",
+ .of_match_table = of_match_ptr(dw_mci_pltfm_match),
.pm = &dw_mci_pltfm_pmops,
},
};
#include <linux/bitops.h>
#include <linux/regulator/consumer.h>
#include <linux/workqueue.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
#include "dw_mmc.h"
+#define NUM_PINS(x) (x + 2)
+
/* Common flag combinations */
#define DW_MCI_DATA_ERROR_FLAGS (SDMMC_INT_DTO | SDMMC_INT_DCRC | \
SDMMC_INT_HTO | SDMMC_INT_SBE | \
struct dw_mci_slot {
struct mmc_host *mmc;
struct dw_mci *host;
+ int wp_gpio;
+ int cd_gpio;
u32 ctype;
int last_detect_state;
};
-static struct workqueue_struct *dw_mci_card_workqueue;
-
#if defined(CONFIG_DEBUG_FS)
static int dw_mci_req_show(struct seq_file *s, void *v)
{
static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
{
struct mmc_data *data;
+ struct dw_mci_slot *slot = mmc_priv(mmc);
u32 cmdr;
cmd->error = -EINPROGRESS;
cmdr |= SDMMC_CMD_DAT_WR;
}
+ if (slot->host->drv_data->ctrl_type == DW_MCI_TYPE_EXYNOS5250)
+ if (SDMMC_CLKSEL_GET_SELCLK_DRV(mci_readl(slot->host, CLKSEL)))
+ cmdr |= SDMMC_USE_HOLD_REG;
+
return cmdr;
}
regs = mci_readl(slot->host, UHS_REG);
/* DDR mode set */
- if (ios->timing == MMC_TIMING_UHS_DDR50)
+ if (ios->timing == MMC_TIMING_UHS_DDR50) {
regs |= (0x1 << slot->id) << 16;
- else
+ mci_writel(slot->host, CLKSEL, slot->host->ddr_timing);
+ } else {
regs &= ~(0x1 << slot->id) << 16;
+ mci_writel(slot->host, CLKSEL, slot->host->sdr_timing);
+ }
+
+ if (slot->host->drv_data->ctrl_type == DW_MCI_TYPE_EXYNOS5250) {
+ slot->host->bus_hz = clk_get_rate(slot->host->ciu_clk);
+ slot->host->bus_hz /= SDMMC_CLKSEL_GET_DIVRATIO(
+ mci_readl(slot->host, CLKSEL));
+ }
mci_writel(slot->host, UHS_REG, regs);
struct dw_mci_board *brd = slot->host->pdata;
/* Use platform get_ro function, else try on board write protect */
- if (brd->get_ro)
+ if (brd->quirks & DW_MCI_QUIRK_NO_WRITE_PROTECT)
+ read_only = 0;
+ else if (brd->get_ro)
read_only = brd->get_ro(slot->id);
+ else if (gpio_is_valid(slot->wp_gpio))
+ read_only = gpio_get_value(slot->wp_gpio);
else
read_only =
mci_readl(slot->host, WRTPRT) & (1 << slot->id) ? 1 : 0;
present = 1;
else if (brd->get_cd)
present = !brd->get_cd(slot->id);
+ else if (gpio_is_valid(slot->cd_gpio))
+ present = gpio_get_value(slot->cd_gpio);
else
present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
== 0 ? 1 : 0;
if (pending & SDMMC_INT_CD) {
mci_writel(host, RINTSTS, SDMMC_INT_CD);
- queue_work(dw_mci_card_workqueue, &host->card_work);
+ queue_work(host->card_workqueue, &host->card_work);
}
/* Handle SDIO Interrupts */
}
}
+#ifdef CONFIG_OF
+static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot)
+{
+ struct device_node *np;
+ char name[7];
+
+ if (!dev || !dev->of_node)
+ return NULL;
+
+ for_each_child_of_node(dev->of_node, np) {
+ sprintf(name, "slot%d", slot);
+ if (!strcmp(name, np->name))
+ return np;
+ }
+ return NULL;
+}
+
+static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
+{
+ struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
+ u32 bus_wd = 1;
+
+ if (!np)
+ return 1;
+
+ if (of_property_read_u32(np, "bus-width", &bus_wd))
+ dev_err(dev, "bus-width property not found, assuming width"
+ " as 1\n");
+ return bus_wd;
+}
+
+static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
+{
+ struct device_node *np = dw_mci_of_find_slot_node(&host->dev, slot);
+ int idx, gpio, ret;
+
+ for (idx = 0; idx < NUM_PINS(bus_wd); idx++) {
+ gpio = of_get_gpio(np, idx);
+ if (!gpio_is_valid(gpio)) {
+ dev_err(&host->dev, "invalid gpio: %d\n", gpio);
+ return -EINVAL;
+ }
+
+ ret = devm_gpio_request(&host->dev, gpio, "dw-mci-bus");
+ if (ret) {
+ dev_err(&host->dev, "gpio [%d] request failed\n", gpio);
+ return -EBUSY;
+ }
+ }
+
+ host->slot[slot]->wp_gpio = -1;
+ gpio = of_get_named_gpio(np, "wp_gpios", 0);
+ if (!gpio_is_valid(gpio)) {
+ dev_info(&host->dev, "wp gpio not available");
+ } else {
+ ret = devm_gpio_request(&host->dev, gpio, "dw-mci-wp");
+ if (ret)
+ dev_info(&host->dev, "gpio [%d] request failed\n",
+ gpio);
+ else
+ host->slot[slot]->wp_gpio = gpio;
+ }
+
+ host->slot[slot]->cd_gpio = -1;
+ gpio = of_get_named_gpio(np, "cd-gpios", 0);
+ if (!gpio_is_valid(gpio)) {
+ dev_info(&host->dev, "cd gpio not available");
+ } else {
+ ret = devm_gpio_request(&host->dev, gpio, "dw-mci-cd");
+ if (ret)
+ dev_err(&host->dev, "gpio [%d] request failed\n", gpio);
+ else
+ host->slot[slot]->cd_gpio = gpio;
+ }
+
+ return 0;
+}
+
+#else /* CONFIG_OF */
+static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
+{
+ return 1;
+}
+
+static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
+{
+ return -EINVAL;
+}
+#endif /* CONFIG_OF */
+
static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
{
struct mmc_host *mmc;
slot->id = id;
slot->mmc = mmc;
slot->host = host;
+ host->slot[id] = slot;
mmc->ops = &dw_mci_ops;
mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510);
if (host->pdata->caps)
mmc->caps = host->pdata->caps;
+ mmc->caps |= host->drv_data->caps;
+
if (host->pdata->caps2)
mmc->caps2 = host->pdata->caps2;
- if (host->pdata->get_bus_wd)
+ if (host->pdata->get_bus_wd) {
if (host->pdata->get_bus_wd(slot->id) >= 4)
mmc->caps |= MMC_CAP_4_BIT_DATA;
+ } else if (host->dev.of_node) {
+ unsigned int bus_width;
+ bus_width = dw_mci_of_get_bus_wd(&host->dev, slot->id);
+ if (bus_width >= 4)
+ mmc->caps |= MMC_CAP_4_BIT_DATA;
+ dw_mci_of_setup_bus(host, slot->id, bus_width);
+ }
if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED)
mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
else
clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
- host->slot[id] = slot;
mmc_add_host(mmc);
#if defined(CONFIG_DEBUG_FS)
* Card may have been plugged in prior to boot so we
* need to run the detect tasklet
*/
- queue_work(dw_mci_card_workqueue, &host->card_work);
+ queue_work(host->card_workqueue, &host->card_work);
return 0;
}
return false;
}
+#ifdef CONFIG_OF
+static struct dw_mci_of_quirks {
+ char *quirk;
+ int id;
+} of_quriks[] = {
+ {
+ .quirk = "supports-highspeed",
+ .id = DW_MCI_QUIRK_HIGHSPEED,
+ }, {
+ .quirk = "card-detection-broken",
+ .id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
+ }, {
+ .quirk = "no-write-protect",
+ .id = DW_MCI_QUIRK_NO_WRITE_PROTECT,
+ }
+};
+
+static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
+{
+ struct dw_mci_board *pdata;
+ struct device *dev = &host->dev;
+ struct device_node *np = dev->of_node, *slot;
+ u32 timing[3];
+ int idx, cnt;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(dev, "could not allocate memory for pdata\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* find out number of slots supported */
+ for_each_child_of_node(np, slot)
+ pdata->num_slots++;
+
+ /* get quirks */
+ cnt = sizeof(of_quriks) / sizeof(struct dw_mci_of_quirks);
+ for (idx = 0; idx < cnt; idx++)
+ if (of_get_property(np, of_quriks[idx].quirk, NULL))
+ pdata->quirks |= of_quriks[idx].id;
+
+ if (of_property_read_u32_array(dev->of_node,
+ "samsung,dw-mshc-sdr-timing", timing, 3))
+ host->sdr_timing = DW_MCI_DEF_SDR_TIMING;
+ else
+ host->sdr_timing = SDMMC_CLKSEL_TIMING(timing[0],
+ timing[1], timing[2]);
+
+ if (of_property_read_u32_array(dev->of_node,
+ "samsung,dw-mshc-ddr-timing", timing, 3))
+ host->ddr_timing = DW_MCI_DEF_DDR_TIMING;
+ else
+ host->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0],
+ timing[1], timing[2]);
+
+ if (of_property_read_u32(np, "fifo-depth", &pdata->fifo_depth))
+ dev_info(dev, "fifo-depth property not found, using "
+ "value of FIFOTH register as default\n");
+
+ of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms);
+
+ return pdata;
+}
+
+#else /* CONFIG_OF */
+static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
+{
+ return ERR_PTR(-EINVAL);
+}
+#endif /* CONFIG_OF */
+
int dw_mci_probe(struct dw_mci *host)
{
int width, i, ret = 0;
u32 fifo_size;
- if (!host->pdata || !host->pdata->init) {
- dev_err(&host->dev,
- "Platform data must supply init function\n");
- return -ENODEV;
+ if (!host->pdata) {
+ host->pdata = dw_mci_parse_dt(host);
+ if (IS_ERR(host->pdata)) {
+ dev_err(&host->dev, "platform data not available\n");
+ return -EINVAL;
+ }
}
if (!host->pdata->select_slot && host->pdata->num_slots > 1) {
return -ENODEV;
}
- if (!host->pdata->bus_hz) {
+ host->biu_clk = clk_get(&host->dev, "biu");
+ if (IS_ERR(host->biu_clk))
+ dev_info(&host->dev, "biu clock not available\n");
+ else
+ clk_enable(host->biu_clk);
+
+ host->ciu_clk = clk_get(&host->dev, "ciu");
+ if (IS_ERR(host->ciu_clk))
+ dev_info(&host->dev, "ciu clock not available\n");
+ else
+ clk_enable(host->ciu_clk);
+
+ if (IS_ERR(host->ciu_clk))
+ host->bus_hz = host->pdata->bus_hz;
+ else
+ host->bus_hz = clk_get_rate(host->ciu_clk);
+
+ if (!host->bus_hz) {
dev_err(&host->dev,
"Platform data must supply bus speed\n");
- return -ENODEV;
+ ret = -ENODEV;
+ goto err_clk;
}
- host->bus_hz = host->pdata->bus_hz;
host->quirks = host->pdata->quirks;
spin_lock_init(&host->lock);
INIT_LIST_HEAD(&host->queue);
-
host->dma_ops = host->pdata->dma_ops;
dw_mci_init_dma(host);
mci_writel(host, CLKSRC, 0);
tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host);
- dw_mci_card_workqueue = alloc_workqueue("dw-mci-card",
+ host->card_workqueue = alloc_workqueue("dw-mci-card",
WQ_MEM_RECLAIM | WQ_NON_REENTRANT, 1);
- if (!dw_mci_card_workqueue)
+ if (!host->card_workqueue)
goto err_dmaunmap;
INIT_WORK(&host->card_work, dw_mci_work_routine_card);
ret = request_irq(host->irq, dw_mci_interrupt, host->irq_flags, "dw-mci", host);
free_irq(host->irq, host);
err_workqueue:
- destroy_workqueue(dw_mci_card_workqueue);
+ destroy_workqueue(host->card_workqueue);
err_dmaunmap:
if (host->use_dma && host->dma_ops->exit)
regulator_disable(host->vmmc);
regulator_put(host->vmmc);
}
+ kfree(host);
+
+err_clk:
+ clk_disable(host->ciu_clk);
+ clk_disable(host->biu_clk);
+ clk_put(host->ciu_clk);
+ clk_put(host->biu_clk);
return ret;
}
EXPORT_SYMBOL(dw_mci_probe);
mci_writel(host, CLKSRC, 0);
free_irq(host->irq, host);
- destroy_workqueue(dw_mci_card_workqueue);
+ destroy_workqueue(host->card_workqueue);
dma_free_coherent(&host->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
if (host->use_dma && host->dma_ops->exit)
regulator_put(host->vmmc);
}
+ clk_disable(host->ciu_clk);
+ clk_disable(host->biu_clk);
+ clk_put(host->ciu_clk);
+ clk_put(host->biu_clk);
}
EXPORT_SYMBOL(dw_mci_remove);
#define SDMMC_IDINTEN 0x090
#define SDMMC_DSCADDR 0x094
#define SDMMC_BUFADDR 0x098
+#define SDMMC_CLKSEL 0x09C /* specific to Samsung Exynos5250 */
#define SDMMC_DATA(x) (x)
/*
#define SDMMC_INT_ERROR 0xbfc2
/* Command register defines */
#define SDMMC_CMD_START BIT(31)
+#define SDMMC_USE_HOLD_REG BIT(29)
#define SDMMC_CMD_CCS_EXP BIT(23)
#define SDMMC_CMD_CEATA_RD BIT(22)
#define SDMMC_CMD_UPD_CLK BIT(21)
/* Version ID register define */
#define SDMMC_GET_VERID(x) ((x) & 0xFFFF)
+#define DW_MCI_DEF_SDR_TIMING 0x03030002
+#define DW_MCI_DEF_DDR_TIMING 0x03020001
+#define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) & 3) << 0)
+#define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) & 3) << 16)
+#define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) & 3) << 24)
+#define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \
+ SDMMC_CLKSEL_CCLK_DRIVE(y) | \
+ SDMMC_CLKSEL_CCLK_DIVIDER(z))
+#define SDMMC_CLKSEL_GET_DIVRATIO(x) ((((x) >> 24) & 0x7) + 1)
+#define SDMMC_CLKSEL_GET_SELCLK_DRV(x) (((x) >> 16) & 0x7)
+
/* Register access macros */
#define mci_readl(dev, reg) \
__raw_readl((dev)->regs + SDMMC_##reg)
extern int dw_mci_resume(struct dw_mci *host);
#endif
+/* Variations in the dw_mci controller */
+#define DW_MCI_TYPE_SYNOPSIS 0
+#define DW_MCI_TYPE_EXYNOS5250 1 /* Samsung Exynos5250 Extensions */
+
+/* dw_mci platform driver data */
+struct dw_mci_drv_data {
+ unsigned long ctrl_type;
+ unsigned long caps;
+};
+
#endif /* _DW_MMC_H_ */
if (parp == NULL)
p = of_get_parent(child);
else {
+ of_node_put(child);
if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
p = of_node_get(of_irq_dflt_pic);
else
p = of_find_node_by_phandle(be32_to_cpup(parp));
+ return p;
}
of_node_put(child);
child = p;
- } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL);
+ } while (p);
return p;
}
INIT_LIST_HEAD(&intc_parent_list);
for_each_matching_node(np, matches) {
- if (!of_find_property(np, "interrupt-controller", NULL))
- continue;
/*
* Here, we allocate and populate an intc_desc with the node
* pointer, interrupt-parent device_node etc.
if (desc->interrupt_parent != parent)
continue;
- list_del(&desc->list);
match = of_match_node(matches, desc->dev);
if (WARN(!match->data,
"of_irq_init: no init function for %s\n",
desc->dev, desc->interrupt_parent);
irq_init_cb = match->data;
ret = irq_init_cb(desc->dev, desc->interrupt_parent);
+ if (ret == -EAGAIN)
+ /*
+ * Interrupt controller's initialization did not
+ * complete and should be retried. So let its
+ * intc_desc be on intc_desc_list.
+ */
+ continue;
+ list_del(&desc->list);
+
if (ret) {
kfree(desc);
continue;
desc = list_first_entry(&intc_parent_list, typeof(*desc), list);
if (list_empty(&intc_parent_list) || !desc) {
pr_err("of_irq_init: children remain, but no parents\n");
- break;
+ /*
+ * If a search with NULL as parent did not result in any
+ * new parent being found, then the scan for matching
+ * interrupt controller nodes is considered as complete.
+ * Otherwise, if there are pending elements on the
+ * intc_desc_list, then retry this process again with
+ * NULL as parent.
+ */
+ if (!parent)
+ break;
+ parent = NULL;
+ continue;
}
list_del(&desc->list);
parent = desc->dev;
* @data_offset: Set the offset of DATA register according to VERID.
* @dev: Device associated with the MMC controller.
* @pdata: Platform data associated with the MMC controller.
+ * @drv_data: Driver specific data for identified variant of the controller
+ * @biu_clk: Pointer to bus interface unit clock instance.
+ * @ciu_clk: Pointer to card interface unit clock instance.
* @slot: Slots sharing this MMC controller.
+ * @sdr_timing: Clock phase shifting for driving and sampling in sdr mode
+ * @ddr_timing: Clock phase shifting for driving and sampling in ddr mode
* @fifo_depth: depth of FIFO.
* @data_shift: log2 of FIFO item size.
* @part_buf_start: Start index in part_buf.
struct mmc_request *mrq;
struct mmc_command *cmd;
struct mmc_data *data;
+ struct workqueue_struct *card_workqueue;
/* DMA interface members*/
int use_dma;
u16 data_offset;
struct device dev;
struct dw_mci_board *pdata;
+ struct dw_mci_drv_data *drv_data;
+ struct clk *biu_clk;
+ struct clk *ciu_clk;
struct dw_mci_slot *slot[MAX_MCI_SLOTS];
+ /* Phase Shift Value (for exynos5250 variant) */
+ u32 sdr_timing;
+ u32 ddr_timing;
+
/* FIFO push and pull */
int fifo_depth;
int data_shift;
#define DW_MCI_QUIRK_HIGHSPEED BIT(2)
/* Unreliable card detection */
#define DW_MCI_QUIRK_BROKEN_CARD_DETECTION BIT(3)
-
+/* Write Protect detection not available */
+#define DW_MCI_QUIRK_NO_WRITE_PROTECT BIT(4)
struct dma_pdata;