forked from Minki/linux
Merge branch 'next/dt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/linux-arm-soc
* 'next/dt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/linux-arm-soc: (21 commits) arm/dt: tegra devicetree support arm/versatile: Add device tree support dt/irq: add irq_domain_generate_simple() helper irq: add irq_domain translation infrastructure dmaengine: imx-sdma: add device tree probe support dmaengine: imx-sdma: sdma_get_firmware does not need to copy fw_name dmaengine: imx-sdma: use platform_device_id to identify sdma version mmc: sdhci-esdhc-imx: add device tree probe support mmc: sdhci-pltfm: dt device does not pass parent to sdhci_alloc_host mmc: sdhci-esdhc-imx: get rid of the uses of cpu_is_mx() mmc: sdhci-esdhc-imx: do not reference platform data after probe mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5 net/fec: add device tree probe support net: ibm_newemac: convert it to use of_get_phy_mode dt/net: add helper function of_get_phy_mode net/fec: gasket needs to be enabled for some i.mx serial/imx: add device tree probe support serial/imx: get rid of the uses of cpu_is_mx1() arm/dt: Add dtb make rule arm/dt: Add skeleton dtsi file ...
This commit is contained in:
commit
cb7dee8d22
20
Documentation/devicetree/bindings/arm/arm-boards
Normal file
20
Documentation/devicetree/bindings/arm/arm-boards
Normal file
@ -0,0 +1,20 @@
|
||||
ARM Versatile Application and Platform Baseboards
|
||||
-------------------------------------------------
|
||||
ARM's development hardware platform with connectors for customizable
|
||||
core tiles. The hardware configuration of the Versatile boards is
|
||||
highly customizable.
|
||||
|
||||
Required properties (in root node):
|
||||
compatible = "arm,versatile-ab"; /* Application baseboard */
|
||||
compatible = "arm,versatile-pb"; /* Platform baseboard */
|
||||
|
||||
Interrupt controllers:
|
||||
- VIC required properties:
|
||||
compatible = "arm,versatile-vic";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
- SIC required properties:
|
||||
compatible = "arm,versatile-sic";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
17
Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
Normal file
17
Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
Normal file
@ -0,0 +1,17 @@
|
||||
* Freescale Smart Direct Memory Access (SDMA) Controller for i.MX
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "fsl,<chip>-sdma"
|
||||
- reg : Should contain SDMA registers location and length
|
||||
- interrupts : Should contain SDMA interrupt
|
||||
- fsl,sdma-ram-script-name : Should contain the full path of SDMA RAM
|
||||
scripts firmware
|
||||
|
||||
Examples:
|
||||
|
||||
sdma@83fb0000 {
|
||||
compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
|
||||
reg = <0x83fb0000 0x4000>;
|
||||
interrupts = <6>;
|
||||
fsl,sdma-ram-script-name = "sdma-imx51.bin";
|
||||
};
|
10
Documentation/devicetree/bindings/i2c/arm-versatile.txt
Normal file
10
Documentation/devicetree/bindings/i2c/arm-versatile.txt
Normal file
@ -0,0 +1,10 @@
|
||||
i2c Controller on ARM Versatile platform:
|
||||
|
||||
Required properties:
|
||||
- compatible : Must be "arm,versatile-i2c";
|
||||
- reg
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
|
||||
Optional properties:
|
||||
- Child nodes conforming to i2c bus binding
|
34
Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
Normal file
34
Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
Normal file
@ -0,0 +1,34 @@
|
||||
* Freescale Enhanced Secure Digital Host Controller (eSDHC) for i.MX
|
||||
|
||||
The Enhanced Secure Digital Host Controller on Freescale i.MX family
|
||||
provides an interface for MMC, SD, and SDIO types of memory cards.
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "fsl,<chip>-esdhc"
|
||||
- reg : Should contain eSDHC registers location and length
|
||||
- interrupts : Should contain eSDHC interrupt
|
||||
|
||||
Optional properties:
|
||||
- fsl,card-wired : Indicate the card is wired to host permanently
|
||||
- fsl,cd-internal : Indicate to use controller internal card detection
|
||||
- fsl,wp-internal : Indicate to use controller internal write protection
|
||||
- cd-gpios : Specify GPIOs for card detection
|
||||
- wp-gpios : Specify GPIOs for write protection
|
||||
|
||||
Examples:
|
||||
|
||||
esdhc@70004000 {
|
||||
compatible = "fsl,imx51-esdhc";
|
||||
reg = <0x70004000 0x4000>;
|
||||
interrupts = <1>;
|
||||
fsl,cd-internal;
|
||||
fsl,wp-internal;
|
||||
};
|
||||
|
||||
esdhc@70008000 {
|
||||
compatible = "fsl,imx51-esdhc";
|
||||
reg = <0x70008000 0x4000>;
|
||||
interrupts = <2>;
|
||||
cd-gpios = <&gpio0 6 0>; /* GPIO1_6 */
|
||||
wp-gpios = <&gpio0 5 0>; /* GPIO1_5 */
|
||||
};
|
8
Documentation/devicetree/bindings/mtd/arm-versatile.txt
Normal file
8
Documentation/devicetree/bindings/mtd/arm-versatile.txt
Normal file
@ -0,0 +1,8 @@
|
||||
Flash device on ARM Versatile board
|
||||
|
||||
Required properties:
|
||||
- compatible : must be "arm,versatile-flash";
|
||||
- bank-width : width in bytes of flash interface.
|
||||
|
||||
Optional properties:
|
||||
- Subnode partition map from mtd flash binding
|
24
Documentation/devicetree/bindings/net/fsl-fec.txt
Normal file
24
Documentation/devicetree/bindings/net/fsl-fec.txt
Normal file
@ -0,0 +1,24 @@
|
||||
* Freescale Fast Ethernet Controller (FEC)
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "fsl,<soc>-fec"
|
||||
- reg : Address and length of the register set for the device
|
||||
- interrupts : Should contain fec interrupt
|
||||
- phy-mode : String, operation mode of the PHY interface.
|
||||
Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii",
|
||||
"rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii".
|
||||
- phy-reset-gpios : Should specify the gpio for phy reset
|
||||
|
||||
Optional properties:
|
||||
- local-mac-address : 6 bytes, mac address
|
||||
|
||||
Example:
|
||||
|
||||
fec@83fec000 {
|
||||
compatible = "fsl,imx51-fec", "fsl,imx27-fec";
|
||||
reg = <0x83fec000 0x4000>;
|
||||
interrupts = <87>;
|
||||
phy-mode = "mii";
|
||||
phy-reset-gpios = <&gpio1 14 0>; /* GPIO2_14 */
|
||||
local-mac-address = [00 04 9F 01 1B B9];
|
||||
};
|
10
Documentation/devicetree/bindings/net/smsc-lan91c111.txt
Normal file
10
Documentation/devicetree/bindings/net/smsc-lan91c111.txt
Normal file
@ -0,0 +1,10 @@
|
||||
SMSC LAN91c111 Ethernet mac
|
||||
|
||||
Required properties:
|
||||
- compatible = "smsc,lan91c111";
|
||||
- reg : physical address and size of registers
|
||||
- interrupts : interrupt connection
|
||||
|
||||
Optional properties:
|
||||
- phy-device : phandle to Ethernet phy
|
||||
- local-mac-address : Ethernet mac address to use
|
@ -0,0 +1,19 @@
|
||||
* Freescale i.MX Universal Asynchronous Receiver/Transmitter (UART)
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "fsl,<soc>-uart"
|
||||
- reg : Address and length of the register set for the device
|
||||
- interrupts : Should contain uart interrupt
|
||||
|
||||
Optional properties:
|
||||
- fsl,uart-has-rtscts : Indicate the uart has rts and cts
|
||||
- fsl,irda-mode : Indicate the uart supports irda mode
|
||||
|
||||
Example:
|
||||
|
||||
uart@73fbc000 {
|
||||
compatible = "fsl,imx51-uart", "fsl,imx21-uart";
|
||||
reg = <0x73fbc000 0x4000>;
|
||||
interrupts = <31>;
|
||||
fsl,uart-has-rtscts;
|
||||
};
|
@ -1716,6 +1716,7 @@ config USE_OF
|
||||
bool "Flattened Device Tree support"
|
||||
select OF
|
||||
select OF_EARLY_FLATTREE
|
||||
select IRQ_DOMAIN
|
||||
help
|
||||
Include support for flattened device tree machine descriptions.
|
||||
|
||||
|
@ -282,6 +282,12 @@ zImage Image xipImage bootpImage uImage: vmlinux
|
||||
zinstall uinstall install: vmlinux
|
||||
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
|
||||
|
||||
%.dtb:
|
||||
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
|
||||
|
||||
dtbs:
|
||||
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
|
||||
|
||||
# We use MRPROPER_FILES and CLEAN_FILES now
|
||||
archclean:
|
||||
$(Q)$(MAKE) $(clean)=$(boot)
|
||||
@ -298,6 +304,7 @@ define archhelp
|
||||
echo ' uImage - U-Boot wrapped zImage'
|
||||
echo ' bootpImage - Combined zImage and initial RAM disk'
|
||||
echo ' (supply initrd image via make variable INITRD=<path>)'
|
||||
echo ' dtbs - Build device tree blobs for enabled boards'
|
||||
echo ' install - Install uncompressed kernel'
|
||||
echo ' zinstall - Install compressed kernel'
|
||||
echo ' uinstall - Install U-Boot wrapped compressed kernel'
|
||||
|
@ -59,6 +59,12 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
|
||||
|
||||
endif
|
||||
|
||||
# Rule to build device tree blobs
|
||||
$(obj)/%.dtb: $(src)/dts/%.dts
|
||||
$(call cmd,dtc)
|
||||
|
||||
$(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y))
|
||||
|
||||
quiet_cmd_uimage = UIMAGE $@
|
||||
cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \
|
||||
-C none -a $(LOADADDR) -e $(STARTADDR) \
|
||||
|
13
arch/arm/boot/dts/skeleton.dtsi
Normal file
13
arch/arm/boot/dts/skeleton.dtsi
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Skeleton device tree; the bare minimum needed to boot; just include and
|
||||
* add a compatible value. The bootloader will typically populate the memory
|
||||
* node.
|
||||
*/
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
chosen { };
|
||||
aliases { };
|
||||
memory { device_type = "memory"; reg = <0 0>; };
|
||||
};
|
70
arch/arm/boot/dts/tegra-harmony.dts
Normal file
70
arch/arm/boot/dts/tegra-harmony.dts
Normal file
@ -0,0 +1,70 @@
|
||||
/dts-v1/;
|
||||
|
||||
/memreserve/ 0x1c000000 0x04000000;
|
||||
/include/ "tegra20.dtsi"
|
||||
|
||||
/ {
|
||||
model = "NVIDIA Tegra2 Harmony evaluation board";
|
||||
compatible = "nvidia,harmony", "nvidia,tegra20";
|
||||
|
||||
chosen {
|
||||
bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/mmcblk0p2 rw rootwait";
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
reg = < 0x00000000 0x40000000 >;
|
||||
};
|
||||
|
||||
i2c@7000c000 {
|
||||
clock-frequency = <400000>;
|
||||
|
||||
codec: wm8903@1a {
|
||||
compatible = "wlf,wm8903";
|
||||
reg = <0x1a>;
|
||||
interrupts = < 347 >;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
/* 0x8000 = Not configured */
|
||||
gpio-cfg = < 0x8000 0x8000 0 0x8000 0x8000 >;
|
||||
};
|
||||
};
|
||||
|
||||
i2c@7000c400 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
i2c@7000c500 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
i2c@7000d000 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
sound {
|
||||
compatible = "nvidia,harmony-sound", "nvidia,tegra-wm8903";
|
||||
|
||||
spkr-en-gpios = <&codec 2 0>;
|
||||
hp-det-gpios = <&gpio 178 0>;
|
||||
int-mic-en-gpios = <&gpio 184 0>;
|
||||
ext-mic-en-gpios = <&gpio 185 0>;
|
||||
};
|
||||
|
||||
serial@70006300 {
|
||||
clock-frequency = < 216000000 >;
|
||||
};
|
||||
|
||||
sdhci@c8000200 {
|
||||
gpios = <&gpio 69 0>, /* cd, gpio PI5 */
|
||||
<&gpio 57 0>, /* wp, gpio PH1 */
|
||||
<&gpio 155 0>; /* power, gpio PT3 */
|
||||
};
|
||||
|
||||
sdhci@c8000600 {
|
||||
gpios = <&gpio 58 0>, /* cd, gpio PH2 */
|
||||
<&gpio 59 0>, /* wp, gpio PH3 */
|
||||
<&gpio 70 0>; /* power, gpio PI6 */
|
||||
};
|
||||
};
|
28
arch/arm/boot/dts/tegra-seaboard.dts
Normal file
28
arch/arm/boot/dts/tegra-seaboard.dts
Normal file
@ -0,0 +1,28 @@
|
||||
/dts-v1/;
|
||||
|
||||
/memreserve/ 0x1c000000 0x04000000;
|
||||
/include/ "tegra20.dtsi"
|
||||
|
||||
/ {
|
||||
model = "NVIDIA Seaboard";
|
||||
compatible = "nvidia,seaboard", "nvidia,tegra20";
|
||||
|
||||
chosen {
|
||||
bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/mmcblk1p3 rw rootwait";
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = < 0x00000000 0x40000000 >;
|
||||
};
|
||||
|
||||
serial@70006300 {
|
||||
clock-frequency = < 216000000 >;
|
||||
};
|
||||
|
||||
sdhci@c8000400 {
|
||||
gpios = <&gpio 69 0>, /* cd, gpio PI5 */
|
||||
<&gpio 57 0>, /* wp, gpio PH1 */
|
||||
<&gpio 70 0>; /* power, gpio PI6 */
|
||||
};
|
||||
};
|
139
arch/arm/boot/dts/tegra20.dtsi
Normal file
139
arch/arm/boot/dts/tegra20.dtsi
Normal file
@ -0,0 +1,139 @@
|
||||
/include/ "skeleton.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "nvidia,tegra20";
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
intc: interrupt-controller@50041000 {
|
||||
compatible = "nvidia,tegra20-gic";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
reg = < 0x50041000 0x1000 >,
|
||||
< 0x50040100 0x0100 >;
|
||||
};
|
||||
|
||||
i2c@7000c000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra20-i2c";
|
||||
reg = <0x7000C000 0x100>;
|
||||
interrupts = < 70 >;
|
||||
};
|
||||
|
||||
i2c@7000c400 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra20-i2c";
|
||||
reg = <0x7000C400 0x100>;
|
||||
interrupts = < 116 >;
|
||||
};
|
||||
|
||||
i2c@7000c500 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra20-i2c";
|
||||
reg = <0x7000C500 0x100>;
|
||||
interrupts = < 124 >;
|
||||
};
|
||||
|
||||
i2c@7000d000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra20-i2c";
|
||||
reg = <0x7000D000 0x200>;
|
||||
interrupts = < 85 >;
|
||||
};
|
||||
|
||||
i2s@70002800 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra20-i2s";
|
||||
reg = <0x70002800 0x200>;
|
||||
interrupts = < 45 >;
|
||||
dma-channel = < 2 >;
|
||||
};
|
||||
|
||||
i2s@70002a00 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra20-i2s";
|
||||
reg = <0x70002a00 0x200>;
|
||||
interrupts = < 35 >;
|
||||
dma-channel = < 1 >;
|
||||
};
|
||||
|
||||
das@70000c00 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra20-das";
|
||||
reg = <0x70000c00 0x80>;
|
||||
};
|
||||
|
||||
gpio: gpio@6000d000 {
|
||||
compatible = "nvidia,tegra20-gpio";
|
||||
reg = < 0x6000d000 0x1000 >;
|
||||
interrupts = < 64 65 66 67 87 119 121 >;
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
};
|
||||
|
||||
serial@70006000 {
|
||||
compatible = "nvidia,tegra20-uart";
|
||||
reg = <0x70006000 0x40>;
|
||||
reg-shift = <2>;
|
||||
interrupts = < 68 >;
|
||||
};
|
||||
|
||||
serial@70006040 {
|
||||
compatible = "nvidia,tegra20-uart";
|
||||
reg = <0x70006040 0x40>;
|
||||
reg-shift = <2>;
|
||||
interrupts = < 69 >;
|
||||
};
|
||||
|
||||
serial@70006200 {
|
||||
compatible = "nvidia,tegra20-uart";
|
||||
reg = <0x70006200 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = < 78 >;
|
||||
};
|
||||
|
||||
serial@70006300 {
|
||||
compatible = "nvidia,tegra20-uart";
|
||||
reg = <0x70006300 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = < 122 >;
|
||||
};
|
||||
|
||||
serial@70006400 {
|
||||
compatible = "nvidia,tegra20-uart";
|
||||
reg = <0x70006400 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = < 123 >;
|
||||
};
|
||||
|
||||
sdhci@c8000000 {
|
||||
compatible = "nvidia,tegra20-sdhci";
|
||||
reg = <0xc8000000 0x200>;
|
||||
interrupts = < 46 >;
|
||||
};
|
||||
|
||||
sdhci@c8000200 {
|
||||
compatible = "nvidia,tegra20-sdhci";
|
||||
reg = <0xc8000200 0x200>;
|
||||
interrupts = < 47 >;
|
||||
};
|
||||
|
||||
sdhci@c8000400 {
|
||||
compatible = "nvidia,tegra20-sdhci";
|
||||
reg = <0xc8000400 0x200>;
|
||||
interrupts = < 51 >;
|
||||
};
|
||||
|
||||
sdhci@c8000600 {
|
||||
compatible = "nvidia,tegra20-sdhci";
|
||||
reg = <0xc8000600 0x200>;
|
||||
interrupts = < 63 >;
|
||||
};
|
||||
};
|
||||
|
192
arch/arm/boot/dts/versatile-ab.dts
Normal file
192
arch/arm/boot/dts/versatile-ab.dts
Normal file
@ -0,0 +1,192 @@
|
||||
/dts-v1/;
|
||||
/include/ "skeleton.dtsi"
|
||||
|
||||
/ {
|
||||
model = "ARM Versatile AB";
|
||||
compatible = "arm,versatile-ab";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
interrupt-parent = <&vic>;
|
||||
|
||||
aliases {
|
||||
serial0 = &uart0;
|
||||
serial1 = &uart1;
|
||||
serial2 = &uart2;
|
||||
i2c0 = &i2c0;
|
||||
};
|
||||
|
||||
memory {
|
||||
reg = <0x0 0x08000000>;
|
||||
};
|
||||
|
||||
flash@34000000 {
|
||||
compatible = "arm,versatile-flash";
|
||||
reg = <0x34000000 0x4000000>;
|
||||
bank-width = <4>;
|
||||
};
|
||||
|
||||
i2c0: i2c@10002000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "arm,versatile-i2c";
|
||||
reg = <0x10002000 0x1000>;
|
||||
|
||||
rtc@68 {
|
||||
compatible = "dallas,ds1338";
|
||||
reg = <0x68>;
|
||||
};
|
||||
};
|
||||
|
||||
net@10010000 {
|
||||
compatible = "smsc,lan91c111";
|
||||
reg = <0x10010000 0x10000>;
|
||||
interrupts = <25>;
|
||||
};
|
||||
|
||||
lcd@10008000 {
|
||||
compatible = "arm,versatile-lcd";
|
||||
reg = <0x10008000 0x1000>;
|
||||
};
|
||||
|
||||
amba {
|
||||
compatible = "arm,amba-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
vic: intc@10140000 {
|
||||
compatible = "arm,versatile-vic";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
reg = <0x10140000 0x1000>;
|
||||
};
|
||||
|
||||
sic: intc@10003000 {
|
||||
compatible = "arm,versatile-sic";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
reg = <0x10003000 0x1000>;
|
||||
interrupt-parent = <&vic>;
|
||||
interrupts = <31>; /* Cascaded to vic */
|
||||
};
|
||||
|
||||
dma@10130000 {
|
||||
compatible = "arm,pl081", "arm,primecell";
|
||||
reg = <0x10130000 0x1000>;
|
||||
interrupts = <17>;
|
||||
};
|
||||
|
||||
uart0: uart@101f1000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x101f1000 0x1000>;
|
||||
interrupts = <12>;
|
||||
};
|
||||
|
||||
uart1: uart@101f2000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x101f2000 0x1000>;
|
||||
interrupts = <13>;
|
||||
};
|
||||
|
||||
uart2: uart@101f3000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x101f3000 0x1000>;
|
||||
interrupts = <14>;
|
||||
};
|
||||
|
||||
smc@10100000 {
|
||||
compatible = "arm,primecell";
|
||||
reg = <0x10100000 0x1000>;
|
||||
};
|
||||
|
||||
mpmc@10110000 {
|
||||
compatible = "arm,primecell";
|
||||
reg = <0x10110000 0x1000>;
|
||||
};
|
||||
|
||||
display@10120000 {
|
||||
compatible = "arm,pl110", "arm,primecell";
|
||||
reg = <0x10120000 0x1000>;
|
||||
interrupts = <16>;
|
||||
};
|
||||
|
||||
sctl@101e0000 {
|
||||
compatible = "arm,primecell";
|
||||
reg = <0x101e0000 0x1000>;
|
||||
};
|
||||
|
||||
watchdog@101e1000 {
|
||||
compatible = "arm,primecell";
|
||||
reg = <0x101e1000 0x1000>;
|
||||
interrupts = <0>;
|
||||
};
|
||||
|
||||
gpio0: gpio@101e4000 {
|
||||
compatible = "arm,pl061", "arm,primecell";
|
||||
reg = <0x101e4000 0x1000>;
|
||||
gpio-controller;
|
||||
interrupts = <6>;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpio1: gpio@101e5000 {
|
||||
compatible = "arm,pl061", "arm,primecell";
|
||||
reg = <0x101e5000 0x1000>;
|
||||
interrupts = <7>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
rtc@101e8000 {
|
||||
compatible = "arm,pl030", "arm,primecell";
|
||||
reg = <0x101e8000 0x1000>;
|
||||
interrupts = <10>;
|
||||
};
|
||||
|
||||
sci@101f0000 {
|
||||
compatible = "arm,primecell";
|
||||
reg = <0x101f0000 0x1000>;
|
||||
interrupts = <15>;
|
||||
};
|
||||
|
||||
ssp@101f4000 {
|
||||
compatible = "arm,pl022", "arm,primecell";
|
||||
reg = <0x101f4000 0x1000>;
|
||||
interrupts = <11>;
|
||||
};
|
||||
|
||||
fpga {
|
||||
compatible = "arm,versatile-fpga", "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0 0x10000000 0x10000>;
|
||||
|
||||
aaci@4000 {
|
||||
compatible = "arm,primecell";
|
||||
reg = <0x4000 0x1000>;
|
||||
interrupts = <24>;
|
||||
};
|
||||
mmc@5000 {
|
||||
compatible = "arm,primecell";
|
||||
reg = < 0x5000 0x1000>;
|
||||
interrupts = <22>;
|
||||
};
|
||||
kmi@6000 {
|
||||
compatible = "arm,pl050", "arm,primecell";
|
||||
reg = <0x6000 0x1000>;
|
||||
interrupt-parent = <&sic>;
|
||||
interrupts = <3>;
|
||||
};
|
||||
kmi@7000 {
|
||||
compatible = "arm,pl050", "arm,primecell";
|
||||
reg = <0x7000 0x1000>;
|
||||
interrupt-parent = <&sic>;
|
||||
interrupts = <4>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
48
arch/arm/boot/dts/versatile-pb.dts
Normal file
48
arch/arm/boot/dts/versatile-pb.dts
Normal file
@ -0,0 +1,48 @@
|
||||
/include/ "versatile-ab.dts"
|
||||
|
||||
/ {
|
||||
model = "ARM Versatile PB";
|
||||
compatible = "arm,versatile-pb";
|
||||
|
||||
amba {
|
||||
gpio2: gpio@101e6000 {
|
||||
compatible = "arm,pl061", "arm,primecell";
|
||||
reg = <0x101e6000 0x1000>;
|
||||
interrupts = <8>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpio3: gpio@101e7000 {
|
||||
compatible = "arm,pl061", "arm,primecell";
|
||||
reg = <0x101e7000 0x1000>;
|
||||
interrupts = <9>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
fpga {
|
||||
uart@9000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x9000 0x1000>;
|
||||
interrupt-parent = <&sic>;
|
||||
interrupts = <6>;
|
||||
};
|
||||
sci@a000 {
|
||||
compatible = "arm,primecell";
|
||||
reg = <0xa000 0x1000>;
|
||||
interrupt-parent = <&sic>;
|
||||
interrupts = <5>;
|
||||
};
|
||||
mmc@b000 {
|
||||
compatible = "arm,primecell";
|
||||
reg = <0xb000 0x1000>;
|
||||
interrupts = <23>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -74,4 +74,11 @@ static const struct machine_desc __mach_desc_##_type \
|
||||
#define MACHINE_END \
|
||||
};
|
||||
|
||||
#define DT_MACHINE_START(_name, _namestr) \
|
||||
static const struct machine_desc __mach_desc_##_name \
|
||||
__used \
|
||||
__attribute__((__section__(".arch.info.init"))) = { \
|
||||
.nr = ~0, \
|
||||
.name = _namestr,
|
||||
|
||||
#endif
|
||||
|
@ -16,11 +16,6 @@
|
||||
#include <asm/setup.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
static inline void irq_dispose_mapping(unsigned int virq)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
|
||||
extern void arm_dt_memblock_reserve(void);
|
||||
|
||||
|
@ -132,17 +132,3 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
|
||||
|
||||
return mdesc_best;
|
||||
}
|
||||
|
||||
/**
|
||||
* irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
|
||||
*
|
||||
* Currently the mapping mechanism is trivial; simple flat hwirq numbers are
|
||||
* mapped 1:1 onto Linux irq numbers. Cascaded irq controllers are not
|
||||
* supported.
|
||||
*/
|
||||
unsigned int irq_create_of_mapping(struct device_node *controller,
|
||||
const u32 *intspec, unsigned int intsize)
|
||||
{
|
||||
return intspec[0];
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(irq_create_of_mapping);
|
||||
|
@ -587,9 +587,9 @@ static struct clk_lookup lookups[] __initdata = {
|
||||
_REGISTER_CLOCK(NULL, "mma", mma_clk)
|
||||
_REGISTER_CLOCK("imx_udc.0", NULL, usbd_clk)
|
||||
_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
|
||||
_REGISTER_CLOCK("imx-uart.0", NULL, uart_clk)
|
||||
_REGISTER_CLOCK("imx-uart.1", NULL, uart_clk)
|
||||
_REGISTER_CLOCK("imx-uart.2", NULL, uart_clk)
|
||||
_REGISTER_CLOCK("imx1-uart.0", NULL, uart_clk)
|
||||
_REGISTER_CLOCK("imx1-uart.1", NULL, uart_clk)
|
||||
_REGISTER_CLOCK("imx1-uart.2", NULL, uart_clk)
|
||||
_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
|
||||
_REGISTER_CLOCK("imx1-cspi.0", NULL, spi_clk)
|
||||
_REGISTER_CLOCK("imx1-cspi.1", NULL, spi_clk)
|
||||
|
@ -1162,10 +1162,10 @@ static struct clk_lookup lookups[] = {
|
||||
_REGISTER_CLOCK(NULL, "perclk3", per_clk[2])
|
||||
_REGISTER_CLOCK(NULL, "perclk4", per_clk[3])
|
||||
_REGISTER_CLOCK(NULL, "clko", clko_clk)
|
||||
_REGISTER_CLOCK("imx-uart.0", NULL, uart_clk[0])
|
||||
_REGISTER_CLOCK("imx-uart.1", NULL, uart_clk[1])
|
||||
_REGISTER_CLOCK("imx-uart.2", NULL, uart_clk[2])
|
||||
_REGISTER_CLOCK("imx-uart.3", NULL, uart_clk[3])
|
||||
_REGISTER_CLOCK("imx21-uart.0", NULL, uart_clk[0])
|
||||
_REGISTER_CLOCK("imx21-uart.1", NULL, uart_clk[1])
|
||||
_REGISTER_CLOCK("imx21-uart.2", NULL, uart_clk[2])
|
||||
_REGISTER_CLOCK("imx21-uart.3", NULL, uart_clk[3])
|
||||
_REGISTER_CLOCK(NULL, "gpt1", gpt_clk[0])
|
||||
_REGISTER_CLOCK(NULL, "gpt1", gpt_clk[1])
|
||||
_REGISTER_CLOCK(NULL, "gpt1", gpt_clk[2])
|
||||
|
@ -272,11 +272,12 @@ DEFINE_CLOCK(can2_clk, 1, CCM_CGCR1, 3, get_rate_ipg, NULL, NULL);
|
||||
},
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
|
||||
_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
|
||||
_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
|
||||
_REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
|
||||
_REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
|
||||
/* i.mx25 has the i.mx21 type uart */
|
||||
_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
|
||||
_REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk)
|
||||
_REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk)
|
||||
_REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
|
||||
@ -295,19 +296,20 @@ static struct clk_lookup lookups[] = {
|
||||
_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
|
||||
_REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk)
|
||||
_REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk)
|
||||
_REGISTER_CLOCK("fec.0", NULL, fec_clk)
|
||||
_REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk)
|
||||
_REGISTER_CLOCK("imxdi_rtc.0", NULL, dryice_clk)
|
||||
_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
|
||||
_REGISTER_CLOCK("imx2-wdt.0", NULL, wdt_clk)
|
||||
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
|
||||
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx25.0", NULL, esdhc1_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx25.1", NULL, esdhc2_clk)
|
||||
_REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk)
|
||||
_REGISTER_CLOCK(NULL, "audmux", audmux_clk)
|
||||
_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
|
||||
_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
|
||||
_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
|
||||
/* i.mx25 has the i.mx35 type sdma */
|
||||
_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
|
||||
};
|
||||
|
||||
int __init mx25_clocks_init(void)
|
||||
|
@ -624,12 +624,13 @@ DEFINE_CLOCK1(csi_clk, 0, NULL, 0, parent, &csi_clk1, &per4_clk);
|
||||
},
|
||||
|
||||
static struct clk_lookup lookups[] = {
|
||||
_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
|
||||
_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
|
||||
_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
|
||||
_REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
|
||||
_REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
|
||||
_REGISTER_CLOCK("imx-uart.5", NULL, uart6_clk)
|
||||
/* i.mx27 has the i.mx21 type uart */
|
||||
_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.5", NULL, uart6_clk)
|
||||
_REGISTER_CLOCK(NULL, "gpt1", gpt1_clk)
|
||||
_REGISTER_CLOCK(NULL, "gpt2", gpt2_clk)
|
||||
_REGISTER_CLOCK(NULL, "gpt3", gpt3_clk)
|
||||
@ -662,7 +663,7 @@ static struct clk_lookup lookups[] = {
|
||||
_REGISTER_CLOCK(NULL, "brom", brom_clk)
|
||||
_REGISTER_CLOCK(NULL, "emma", emma_clk)
|
||||
_REGISTER_CLOCK(NULL, "slcdc", slcdc_clk)
|
||||
_REGISTER_CLOCK("fec.0", NULL, fec_clk)
|
||||
_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
|
||||
_REGISTER_CLOCK(NULL, "emi", emi_clk)
|
||||
_REGISTER_CLOCK(NULL, "sahara2", sahara2_clk)
|
||||
_REGISTER_CLOCK(NULL, "ata", ata_clk)
|
||||
|
@ -547,11 +547,12 @@ static struct clk_lookup lookups[] = {
|
||||
_REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk1)
|
||||
_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk2)
|
||||
_REGISTER_CLOCK("mx3-camera.0", NULL, csi_clk)
|
||||
_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
|
||||
_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
|
||||
_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
|
||||
_REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
|
||||
_REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
|
||||
/* i.mx31 has the i.mx21 type uart */
|
||||
_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
|
||||
_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
|
||||
_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
|
||||
_REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk)
|
||||
@ -564,7 +565,7 @@ static struct clk_lookup lookups[] = {
|
||||
_REGISTER_CLOCK(NULL, "ata", ata_clk)
|
||||
_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
|
||||
_REGISTER_CLOCK(NULL, "rng", rng_clk)
|
||||
_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk1)
|
||||
_REGISTER_CLOCK("imx31-sdma", NULL, sdma_clk1)
|
||||
_REGISTER_CLOCK(NULL, "sdma_ipg", sdma_clk2)
|
||||
_REGISTER_CLOCK(NULL, "mstick", mstick1_clk)
|
||||
_REGISTER_CLOCK(NULL, "mstick", mstick2_clk)
|
||||
|
@ -458,10 +458,11 @@ static struct clk_lookup lookups[] = {
|
||||
_REGISTER_CLOCK("imx-epit.0", NULL, epit1_clk)
|
||||
_REGISTER_CLOCK("imx-epit.1", NULL, epit2_clk)
|
||||
_REGISTER_CLOCK(NULL, "esai", esai_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk)
|
||||
_REGISTER_CLOCK("fec.0", NULL, fec_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx35.0", NULL, esdhc1_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx35.1", NULL, esdhc2_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx35.2", NULL, esdhc3_clk)
|
||||
/* i.mx35 has the i.mx27 type fec */
|
||||
_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
|
||||
_REGISTER_CLOCK(NULL, "gpio", gpio1_clk)
|
||||
_REGISTER_CLOCK(NULL, "gpio", gpio2_clk)
|
||||
_REGISTER_CLOCK(NULL, "gpio", gpio3_clk)
|
||||
@ -481,14 +482,15 @@ static struct clk_lookup lookups[] = {
|
||||
_REGISTER_CLOCK(NULL, "rtc", rtc_clk)
|
||||
_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
|
||||
_REGISTER_CLOCK(NULL, "scc", scc_clk)
|
||||
_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
|
||||
_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
|
||||
_REGISTER_CLOCK(NULL, "spba", spba_clk)
|
||||
_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
|
||||
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
|
||||
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
|
||||
_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
|
||||
_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
|
||||
_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
|
||||
/* i.mx35 has the i.mx21 type uart */
|
||||
_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
|
||||
_REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk)
|
||||
_REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk)
|
||||
_REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
|
||||
|
@ -225,7 +225,8 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
|
||||
|
||||
static struct esdhc_platform_data sd1_pdata = {
|
||||
.cd_gpio = GPIO_SD1CD,
|
||||
.wp_gpio = -EINVAL,
|
||||
.cd_type = ESDHC_CD_GPIO,
|
||||
.wp_type = ESDHC_WP_NONE,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -236,7 +236,8 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
|
||||
|
||||
static struct esdhc_platform_data sd1_pdata = {
|
||||
.cd_gpio = GPIO_SD1CD,
|
||||
.wp_gpio = -EINVAL,
|
||||
.cd_type = ESDHC_CD_GPIO,
|
||||
.wp_type = ESDHC_WP_NONE,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -215,6 +215,8 @@ static const struct imxi2c_platform_data mx25_3ds_i2c0_data __initconst = {
|
||||
static const struct esdhc_platform_data mx25pdk_esdhc_pdata __initconst = {
|
||||
.wp_gpio = SD1_GPIO_WP,
|
||||
.cd_gpio = SD1_GPIO_CD,
|
||||
.wp_type = ESDHC_WP_GPIO,
|
||||
.cd_type = ESDHC_CD_GPIO,
|
||||
};
|
||||
|
||||
static void __init mx25pdk_init(void)
|
||||
|
@ -349,6 +349,8 @@ __setup("otg_mode=", pcm043_otg_mode);
|
||||
static struct esdhc_platform_data sd1_pdata = {
|
||||
.wp_gpio = SD1_GPIO_WP,
|
||||
.cd_gpio = SD1_GPIO_CD,
|
||||
.wp_type = ESDHC_WP_GPIO,
|
||||
.cd_type = ESDHC_CD_GPIO,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -79,7 +79,6 @@ static struct sdma_script_start_addrs imx25_sdma_script __initdata = {
|
||||
};
|
||||
|
||||
static struct sdma_platform_data imx25_sdma_pdata __initdata = {
|
||||
.sdma_version = 2,
|
||||
.fw_name = "sdma-imx25.bin",
|
||||
.script_addrs = &imx25_sdma_script,
|
||||
};
|
||||
@ -92,5 +91,6 @@ void __init imx25_soc_init(void)
|
||||
mxc_register_gpio("imx31-gpio", 2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0);
|
||||
mxc_register_gpio("imx31-gpio", 3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0);
|
||||
|
||||
imx_add_imx_sdma(MX25_SDMA_BASE_ADDR, MX25_INT_SDMA, &imx25_sdma_pdata);
|
||||
/* i.mx25 has the i.mx35 type sdma */
|
||||
imx_add_imx_sdma("imx35-sdma", MX25_SDMA_BASE_ADDR, MX25_INT_SDMA, &imx25_sdma_pdata);
|
||||
}
|
||||
|
@ -69,7 +69,6 @@ static struct sdma_script_start_addrs imx31_to2_sdma_script __initdata = {
|
||||
};
|
||||
|
||||
static struct sdma_platform_data imx31_sdma_pdata __initdata = {
|
||||
.sdma_version = 1,
|
||||
.fw_name = "sdma-imx31-to2.bin",
|
||||
.script_addrs = &imx31_to2_sdma_script,
|
||||
};
|
||||
@ -88,5 +87,5 @@ void __init imx31_soc_init(void)
|
||||
imx31_sdma_pdata.script_addrs = &imx31_to1_sdma_script;
|
||||
}
|
||||
|
||||
imx_add_imx_sdma(MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
|
||||
imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
|
||||
}
|
||||
|
@ -86,7 +86,6 @@ static struct sdma_script_start_addrs imx35_to2_sdma_script __initdata = {
|
||||
};
|
||||
|
||||
static struct sdma_platform_data imx35_sdma_pdata __initdata = {
|
||||
.sdma_version = 2,
|
||||
.fw_name = "sdma-imx35-to2.bin",
|
||||
.script_addrs = &imx35_to2_sdma_script,
|
||||
};
|
||||
@ -106,5 +105,5 @@ void __init imx35_soc_init(void)
|
||||
imx35_sdma_pdata.script_addrs = &imx35_to1_sdma_script;
|
||||
}
|
||||
|
||||
imx_add_imx_sdma(MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
|
||||
imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
|
||||
}
|
||||
|
@ -41,8 +41,6 @@
|
||||
#define BABBAGE_POWER_KEY IMX_GPIO_NR(2, 21)
|
||||
#define BABBAGE_ECSPI1_CS0 IMX_GPIO_NR(4, 24)
|
||||
#define BABBAGE_ECSPI1_CS1 IMX_GPIO_NR(4, 25)
|
||||
#define BABBAGE_SD1_CD IMX_GPIO_NR(1, 0)
|
||||
#define BABBAGE_SD1_WP IMX_GPIO_NR(1, 1)
|
||||
#define BABBAGE_SD2_CD IMX_GPIO_NR(1, 6)
|
||||
#define BABBAGE_SD2_WP IMX_GPIO_NR(1, 5)
|
||||
|
||||
@ -146,8 +144,9 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
|
||||
MX51_PAD_SD1_DATA1__SD1_DATA1,
|
||||
MX51_PAD_SD1_DATA2__SD1_DATA2,
|
||||
MX51_PAD_SD1_DATA3__SD1_DATA3,
|
||||
MX51_PAD_GPIO1_0__GPIO1_0,
|
||||
MX51_PAD_GPIO1_1__GPIO1_1,
|
||||
/* CD/WP from controller */
|
||||
MX51_PAD_GPIO1_0__SD1_CD,
|
||||
MX51_PAD_GPIO1_1__SD1_WP,
|
||||
|
||||
/* SD 2 */
|
||||
MX51_PAD_SD2_CMD__SD2_CMD,
|
||||
@ -156,6 +155,7 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
|
||||
MX51_PAD_SD2_DATA1__SD2_DATA1,
|
||||
MX51_PAD_SD2_DATA2__SD2_DATA2,
|
||||
MX51_PAD_SD2_DATA3__SD2_DATA3,
|
||||
/* CD/WP gpio */
|
||||
MX51_PAD_GPIO1_6__GPIO1_6,
|
||||
MX51_PAD_GPIO1_5__GPIO1_5,
|
||||
|
||||
@ -340,13 +340,15 @@ static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
|
||||
};
|
||||
|
||||
static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
|
||||
.cd_gpio = BABBAGE_SD1_CD,
|
||||
.wp_gpio = BABBAGE_SD1_WP,
|
||||
.cd_type = ESDHC_CD_CONTROLLER,
|
||||
.wp_type = ESDHC_WP_CONTROLLER,
|
||||
};
|
||||
|
||||
static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
|
||||
.cd_gpio = BABBAGE_SD2_CD,
|
||||
.wp_gpio = BABBAGE_SD2_WP,
|
||||
.cd_type = ESDHC_CD_GPIO,
|
||||
.wp_type = ESDHC_WP_GPIO,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -210,11 +210,15 @@ static const struct gpio_keys_platform_data loco_button_data __initconst = {
|
||||
|
||||
static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
|
||||
.cd_gpio = LOCO_SD1_CD,
|
||||
.cd_type = ESDHC_CD_GPIO,
|
||||
.wp_type = ESDHC_WP_NONE,
|
||||
};
|
||||
|
||||
static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
|
||||
.cd_gpio = LOCO_SD3_CD,
|
||||
.wp_gpio = LOCO_SD3_WP,
|
||||
.cd_type = ESDHC_CD_GPIO,
|
||||
.wp_type = ESDHC_WP_GPIO,
|
||||
};
|
||||
|
||||
static inline void mx53_loco_fec_reset(void)
|
||||
|
@ -1422,11 +1422,13 @@ DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
|
||||
},
|
||||
|
||||
static struct clk_lookup mx51_lookups[] = {
|
||||
_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
|
||||
_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
|
||||
_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
|
||||
/* i.mx51 has the i.mx21 type uart */
|
||||
_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
|
||||
_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
|
||||
_REGISTER_CLOCK("fec.0", NULL, fec_clk)
|
||||
/* i.mx51 has the i.mx27 type fec */
|
||||
_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
|
||||
_REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)
|
||||
_REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)
|
||||
_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
|
||||
@ -1446,7 +1448,8 @@ static struct clk_lookup mx51_lookups[] = {
|
||||
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
|
||||
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
|
||||
_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
|
||||
_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
|
||||
/* i.mx51 has the i.mx35 type sdma */
|
||||
_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
|
||||
_REGISTER_CLOCK(NULL, "ckih", ckih_clk)
|
||||
_REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
|
||||
_REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
|
||||
@ -1454,10 +1457,10 @@ static struct clk_lookup mx51_lookups[] = {
|
||||
_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
|
||||
/* i.mx51 has the i.mx35 type cspi */
|
||||
_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx51.0", NULL, esdhc1_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx51.1", NULL, esdhc2_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx51.2", NULL, esdhc3_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx51.3", NULL, esdhc4_clk)
|
||||
_REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
|
||||
_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
|
||||
_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
|
||||
@ -1470,29 +1473,32 @@ static struct clk_lookup mx51_lookups[] = {
|
||||
};
|
||||
|
||||
static struct clk_lookup mx53_lookups[] = {
|
||||
_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
|
||||
_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
|
||||
_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
|
||||
_REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
|
||||
_REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
|
||||
/* i.mx53 has the i.mx21 type uart */
|
||||
_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
|
||||
_REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
|
||||
_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
|
||||
_REGISTER_CLOCK("fec.0", NULL, fec_clk)
|
||||
/* i.mx53 has the i.mx25 type fec */
|
||||
_REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk)
|
||||
_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
|
||||
_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
|
||||
_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
|
||||
_REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_mx53_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_mx53_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_mx53_clk)
|
||||
/* i.mx53 has the i.mx51 type ecspi */
|
||||
_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
|
||||
_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
|
||||
/* i.mx53 has the i.mx25 type cspi */
|
||||
_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx53.0", NULL, esdhc1_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx53.1", NULL, esdhc2_mx53_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx53.2", NULL, esdhc3_mx53_clk)
|
||||
_REGISTER_CLOCK("sdhci-esdhc-imx53.3", NULL, esdhc4_mx53_clk)
|
||||
_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
|
||||
_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
|
||||
_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
|
||||
/* i.mx53 has the i.mx35 type sdma */
|
||||
_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
|
||||
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
|
||||
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
|
||||
_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
|
||||
|
@ -115,7 +115,6 @@ static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
|
||||
};
|
||||
|
||||
static struct sdma_platform_data imx51_sdma_pdata __initdata = {
|
||||
.sdma_version = 2,
|
||||
.fw_name = "sdma-imx51.bin",
|
||||
.script_addrs = &imx51_sdma_script,
|
||||
};
|
||||
@ -135,7 +134,6 @@ static struct sdma_script_start_addrs imx53_sdma_script __initdata = {
|
||||
};
|
||||
|
||||
static struct sdma_platform_data imx53_sdma_pdata __initdata = {
|
||||
.sdma_version = 2,
|
||||
.fw_name = "sdma-imx53.bin",
|
||||
.script_addrs = &imx53_sdma_script,
|
||||
};
|
||||
@ -148,7 +146,8 @@ void __init imx51_soc_init(void)
|
||||
mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
|
||||
mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
|
||||
|
||||
imx_add_imx_sdma(MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
|
||||
/* i.mx51 has the i.mx35 type sdma */
|
||||
imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
|
||||
}
|
||||
|
||||
void __init imx53_soc_init(void)
|
||||
@ -162,5 +161,6 @@ void __init imx53_soc_init(void)
|
||||
mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
|
||||
mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
|
||||
|
||||
imx_add_imx_sdma(MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
|
||||
/* i.mx53 has the i.mx35 type sdma */
|
||||
imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
|
||||
}
|
||||
|
@ -260,8 +260,8 @@ static struct regulator_consumer_supply vvideo_consumers[] = {
|
||||
};
|
||||
|
||||
static struct regulator_consumer_supply vsd_consumers[] = {
|
||||
REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.0"),
|
||||
REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.1"),
|
||||
REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.0"),
|
||||
REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.1"),
|
||||
};
|
||||
|
||||
static struct regulator_consumer_supply pwgt1_consumer[] = {
|
||||
|
@ -51,6 +51,12 @@ config MACH_SEABOARD
|
||||
also be included for some of the derivative boards that
|
||||
have large similarities with the seaboard design.
|
||||
|
||||
config MACH_TEGRA_DT
|
||||
bool "Generic Tegra board (FDT support)"
|
||||
select USE_OF
|
||||
help
|
||||
Support for generic nVidia Tegra boards using Flattened Device Tree
|
||||
|
||||
config MACH_TRIMSLICE
|
||||
bool "TrimSlice board"
|
||||
select TEGRA_PCI
|
||||
|
@ -29,5 +29,8 @@ obj-${CONFIG_MACH_PAZ00} += board-paz00-pinmux.o
|
||||
obj-${CONFIG_MACH_SEABOARD} += board-seaboard.o
|
||||
obj-${CONFIG_MACH_SEABOARD} += board-seaboard-pinmux.o
|
||||
|
||||
obj-${CONFIG_MACH_TEGRA_DT} += board-dt.o
|
||||
obj-${CONFIG_MACH_TEGRA_DT} += board-harmony-pinmux.o
|
||||
|
||||
obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice.o
|
||||
obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice-pinmux.o
|
||||
|
@ -1,3 +1,6 @@
|
||||
zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00008000
|
||||
params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00000100
|
||||
initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00800000
|
||||
|
||||
dtb-$(CONFIG_MACH_HARMONY) += tegra-harmony.dtb
|
||||
dtb-$(CONFIG_MACH_SEABOARD) += tegra-seaboard.dtb
|
||||
|
119
arch/arm/mach-tegra/board-dt.c
Normal file
119
arch/arm/mach-tegra/board-dt.c
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* nVidia Tegra device tree board support
|
||||
*
|
||||
* Copyright (C) 2010 Secret Lab Technologies, Ltd.
|
||||
* Copyright (C) 2010 Google, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pda_power.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-tegra.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#include <mach/iomap.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "board-harmony.h"
|
||||
#include "clock.h"
|
||||
#include "devices.h"
|
||||
|
||||
void harmony_pinmux_init(void);
|
||||
void seaboard_pinmux_init(void);
|
||||
|
||||
|
||||
struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC2_BASE, "sdhci-tegra.1", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC3_BASE, "sdhci-tegra.2", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC4_BASE, "sdhci-tegra.3", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C_BASE, "tegra-i2c.0", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C2_BASE, "tegra-i2c.1", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C3_BASE, "tegra-i2c.2", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_DVC_BASE, "tegra-i2c.3", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.0", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.1", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra-das", NULL),
|
||||
{}
|
||||
};
|
||||
|
||||
static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
|
||||
/* name parent rate enabled */
|
||||
{ "uartd", "pll_p", 216000000, true },
|
||||
{ NULL, NULL, 0, 0},
|
||||
};
|
||||
|
||||
static struct of_device_id tegra_dt_match_table[] __initdata = {
|
||||
{ .compatible = "simple-bus", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct of_device_id tegra_dt_gic_match[] __initdata = {
|
||||
{ .compatible = "nvidia,tegra20-gic", },
|
||||
{}
|
||||
};
|
||||
|
||||
static void __init tegra_dt_init(void)
|
||||
{
|
||||
struct device_node *node;
|
||||
|
||||
node = of_find_matching_node_by_address(NULL, tegra_dt_gic_match,
|
||||
TEGRA_ARM_INT_DIST_BASE);
|
||||
if (node)
|
||||
irq_domain_add_simple(node, INT_GIC_BASE);
|
||||
|
||||
tegra_clk_init_from_table(tegra_dt_clk_init_table);
|
||||
|
||||
if (of_machine_is_compatible("nvidia,harmony"))
|
||||
harmony_pinmux_init();
|
||||
else if (of_machine_is_compatible("nvidia,seaboard"))
|
||||
seaboard_pinmux_init();
|
||||
|
||||
/*
|
||||
* Finished with the static registrations now; fill in the missing
|
||||
* devices
|
||||
*/
|
||||
of_platform_populate(NULL, tegra_dt_match_table, tegra20_auxdata_lookup, NULL);
|
||||
}
|
||||
|
||||
static const char * tegra_dt_board_compat[] = {
|
||||
"nvidia,harmony",
|
||||
"nvidia,seaboard",
|
||||
NULL
|
||||
};
|
||||
|
||||
DT_MACHINE_START(TEGRA_DT, "nVidia Tegra (Flattened Device Tree)")
|
||||
.map_io = tegra_map_common_io,
|
||||
.init_early = tegra_init_early,
|
||||
.init_irq = tegra_init_irq,
|
||||
.timer = &tegra_timer,
|
||||
.init_machine = tegra_dt_init,
|
||||
.dt_compat = tegra_dt_board_compat,
|
||||
MACHINE_END
|
@ -17,4 +17,12 @@ config MACH_VERSATILE_AB
|
||||
Include support for the ARM(R) Versatile Application Baseboard
|
||||
for the ARM926EJ-S.
|
||||
|
||||
config MACH_VERSATILE_DT
|
||||
bool "Support Versatile platform from device tree"
|
||||
select USE_OF
|
||||
select CPU_ARM926T
|
||||
help
|
||||
Include support for the ARM(R) Versatile/PB platform,
|
||||
using the device tree for discovery
|
||||
|
||||
endmenu
|
||||
|
@ -5,4 +5,5 @@
|
||||
obj-y := core.o
|
||||
obj-$(CONFIG_ARCH_VERSATILE_PB) += versatile_pb.o
|
||||
obj-$(CONFIG_MACH_VERSATILE_AB) += versatile_ab.o
|
||||
obj-$(CONFIG_MACH_VERSATILE_DT) += versatile_dt.o
|
||||
obj-$(CONFIG_PCI) += pci.o
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/clcd.h>
|
||||
#include <linux/amba/pl061.h>
|
||||
@ -83,13 +86,26 @@ static struct fpga_irq_data sic_irq = {
|
||||
#define PIC_MASK 0
|
||||
#endif
|
||||
|
||||
/* Lookup table for finding a DT node that represents the vic instance */
|
||||
static const struct of_device_id vic_of_match[] __initconst = {
|
||||
{ .compatible = "arm,versatile-vic", },
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct of_device_id sic_of_match[] __initconst = {
|
||||
{ .compatible = "arm,versatile-sic", },
|
||||
{}
|
||||
};
|
||||
|
||||
void __init versatile_init_irq(void)
|
||||
{
|
||||
vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0);
|
||||
irq_domain_generate_simple(vic_of_match, VERSATILE_VIC_BASE, IRQ_VIC_START);
|
||||
|
||||
writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
|
||||
|
||||
fpga_irq_init(IRQ_VICSOURCE31, ~PIC_MASK, &sic_irq);
|
||||
irq_domain_generate_simple(sic_of_match, VERSATILE_SIC_BASE, IRQ_SIC_START);
|
||||
|
||||
/*
|
||||
* Interrupts on secondary controller from 0 to 8 are routed to
|
||||
@ -646,6 +662,52 @@ static struct amba_device *amba_devs[] __initdata = {
|
||||
&kmi1_device,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
/*
|
||||
* Lookup table for attaching a specific name and platform_data pointer to
|
||||
* devices as they get created by of_platform_populate(). Ideally this table
|
||||
* would not exist, but the current clock implementation depends on some devices
|
||||
* having a specific name.
|
||||
*/
|
||||
struct of_dev_auxdata versatile_auxdata_lookup[] __initdata = {
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI0_BASE, "fpga:05", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_KMI0_BASE, "fpga:06", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_KMI1_BASE, "fpga:07", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART3_BASE, "fpga:09", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI1_BASE, "fpga:0b", NULL),
|
||||
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_CLCD_BASE, "dev:20", &clcd_plat_data),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART0_BASE, "dev:f1", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART1_BASE, "dev:f2", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART2_BASE, "dev:f3", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_SSP_BASE, "dev:f4", NULL),
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* These entries are unnecessary because no clocks referencing
|
||||
* them. I've left them in for now as place holders in case
|
||||
* any of them need to be added back, but they should be
|
||||
* removed before actually committing this patch. --gcl
|
||||
*/
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_AACI_BASE, "fpga:04", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_SCI1_BASE, "fpga:0a", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_SMC_BASE, "dev:00", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_MPMC_BASE, "dev:10", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_DMAC_BASE, "dev:30", NULL),
|
||||
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_SCTL_BASE, "dev:e0", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_WATCHDOG_BASE, "dev:e1", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO0_BASE, "dev:e4", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO1_BASE, "dev:e5", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO2_BASE, "dev:e6", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO3_BASE, "dev:e7", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_RTC_BASE, "dev:e8", NULL),
|
||||
OF_DEV_AUXDATA("arm,primecell", VERSATILE_SCI_BASE, "dev:f0", NULL),
|
||||
#endif
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LEDS
|
||||
#define VA_LEDS_BASE (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET)
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define __ASM_ARCH_VERSATILE_H
|
||||
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
extern void __init versatile_init(void);
|
||||
extern void __init versatile_init_early(void);
|
||||
@ -30,6 +31,9 @@ extern void __init versatile_init_irq(void);
|
||||
extern void __init versatile_map_io(void);
|
||||
extern struct sys_timer versatile_timer;
|
||||
extern unsigned int mmc_status(struct device *dev);
|
||||
#ifdef CONFIG_OF
|
||||
extern struct of_dev_auxdata versatile_auxdata_lookup[];
|
||||
#endif
|
||||
|
||||
#define AMBA_DEVICE(name,busid,base,plat) \
|
||||
static struct amba_device name##_device = { \
|
||||
|
51
arch/arm/mach-versatile/versatile_dt.c
Normal file
51
arch/arm/mach-versatile/versatile_dt.c
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Versatile board support using the device tree
|
||||
*
|
||||
* Copyright (C) 2010 Secret Lab Technologies Ltd.
|
||||
* Copyright (C) 2009 Jeremy Kerr <jeremy.kerr@canonical.com>
|
||||
* Copyright (C) 2004 ARM Limited
|
||||
* Copyright (C) 2000 Deep Blue Solutions Ltd
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
static void __init versatile_dt_init(void)
|
||||
{
|
||||
of_platform_populate(NULL, of_default_bus_match_table,
|
||||
versatile_auxdata_lookup, NULL);
|
||||
}
|
||||
|
||||
static const char *versatile_dt_match[] __initconst = {
|
||||
"arm,versatile-ab",
|
||||
"arm,versatile-pb",
|
||||
NULL,
|
||||
};
|
||||
|
||||
DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)")
|
||||
.map_io = versatile_map_io,
|
||||
.init_early = versatile_init_early,
|
||||
.init_irq = versatile_init_irq,
|
||||
.timer = &versatile_timer,
|
||||
.init_machine = versatile_dt_init,
|
||||
.dt_compat = versatile_dt_match,
|
||||
MACHINE_END
|
@ -11,40 +11,45 @@
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/devices-common.h>
|
||||
|
||||
#define imx_fec_data_entry_single(soc) \
|
||||
#define imx_fec_data_entry_single(soc, _devid) \
|
||||
{ \
|
||||
.devid = _devid, \
|
||||
.iobase = soc ## _FEC_BASE_ADDR, \
|
||||
.irq = soc ## _INT_FEC, \
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SOC_IMX25
|
||||
const struct imx_fec_data imx25_fec_data __initconst =
|
||||
imx_fec_data_entry_single(MX25);
|
||||
imx_fec_data_entry_single(MX25, "imx25-fec");
|
||||
#endif /* ifdef CONFIG_SOC_IMX25 */
|
||||
|
||||
#ifdef CONFIG_SOC_IMX27
|
||||
const struct imx_fec_data imx27_fec_data __initconst =
|
||||
imx_fec_data_entry_single(MX27);
|
||||
imx_fec_data_entry_single(MX27, "imx27-fec");
|
||||
#endif /* ifdef CONFIG_SOC_IMX27 */
|
||||
|
||||
#ifdef CONFIG_SOC_IMX35
|
||||
/* i.mx35 has the i.mx27 type fec */
|
||||
const struct imx_fec_data imx35_fec_data __initconst =
|
||||
imx_fec_data_entry_single(MX35);
|
||||
imx_fec_data_entry_single(MX35, "imx27-fec");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SOC_IMX50
|
||||
/* i.mx50 has the i.mx25 type fec */
|
||||
const struct imx_fec_data imx50_fec_data __initconst =
|
||||
imx_fec_data_entry_single(MX50);
|
||||
imx_fec_data_entry_single(MX50, "imx25-fec");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SOC_IMX51
|
||||
/* i.mx51 has the i.mx27 type fec */
|
||||
const struct imx_fec_data imx51_fec_data __initconst =
|
||||
imx_fec_data_entry_single(MX51);
|
||||
imx_fec_data_entry_single(MX51, "imx27-fec");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SOC_IMX53
|
||||
/* i.mx53 has the i.mx25 type fec */
|
||||
const struct imx_fec_data imx53_fec_data __initconst =
|
||||
imx_fec_data_entry_single(MX53);
|
||||
imx_fec_data_entry_single(MX53, "imx25-fec");
|
||||
#endif
|
||||
|
||||
struct platform_device *__init imx_add_fec(
|
||||
@ -63,7 +68,7 @@ struct platform_device *__init imx_add_fec(
|
||||
},
|
||||
};
|
||||
|
||||
return imx_add_platform_device_dmamask("fec", 0,
|
||||
return imx_add_platform_device_dmamask(data->devid, 0,
|
||||
res, ARRAY_SIZE(res),
|
||||
pdata, sizeof(*pdata), DMA_BIT_MASK(32));
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ struct platform_device __init __maybe_unused *imx_add_imx_dma(void)
|
||||
"imx-dma", -1, NULL, 0, NULL, 0);
|
||||
}
|
||||
|
||||
struct platform_device __init __maybe_unused *imx_add_imx_sdma(
|
||||
struct platform_device __init __maybe_unused *imx_add_imx_sdma(char *name,
|
||||
resource_size_t iobase, int irq, struct sdma_platform_data *pdata)
|
||||
{
|
||||
struct resource res[] = {
|
||||
@ -29,6 +29,6 @@ struct platform_device __init __maybe_unused *imx_add_imx_sdma(
|
||||
},
|
||||
};
|
||||
|
||||
return platform_device_register_resndata(&mxc_ahb_bus, "imx-sdma",
|
||||
return platform_device_register_resndata(&mxc_ahb_bus, name,
|
||||
-1, res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ struct platform_device *__init imx_add_imx_uart_3irq(
|
||||
},
|
||||
};
|
||||
|
||||
return imx_add_platform_device("imx-uart", data->id, res,
|
||||
return imx_add_platform_device("imx1-uart", data->id, res,
|
||||
ARRAY_SIZE(res), pdata, sizeof(*pdata));
|
||||
}
|
||||
|
||||
@ -172,6 +172,7 @@ struct platform_device *__init imx_add_imx_uart_1irq(
|
||||
},
|
||||
};
|
||||
|
||||
return imx_add_platform_device("imx-uart", data->id, res, ARRAY_SIZE(res),
|
||||
pdata, sizeof(*pdata));
|
||||
/* i.mx21 type uart runs on all i.mx except i.mx1 */
|
||||
return imx_add_platform_device("imx21-uart", data->id,
|
||||
res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
|
||||
}
|
||||
|
@ -10,21 +10,22 @@
|
||||
#include <mach/devices-common.h>
|
||||
#include <mach/esdhc.h>
|
||||
|
||||
#define imx_sdhci_esdhc_imx_data_entry_single(soc, _id, hwid) \
|
||||
#define imx_sdhci_esdhc_imx_data_entry_single(soc, _devid, _id, hwid) \
|
||||
{ \
|
||||
.devid = _devid, \
|
||||
.id = _id, \
|
||||
.iobase = soc ## _ESDHC ## hwid ## _BASE_ADDR, \
|
||||
.irq = soc ## _INT_ESDHC ## hwid, \
|
||||
}
|
||||
|
||||
#define imx_sdhci_esdhc_imx_data_entry(soc, id, hwid) \
|
||||
[id] = imx_sdhci_esdhc_imx_data_entry_single(soc, id, hwid)
|
||||
#define imx_sdhci_esdhc_imx_data_entry(soc, devid, id, hwid) \
|
||||
[id] = imx_sdhci_esdhc_imx_data_entry_single(soc, devid, id, hwid)
|
||||
|
||||
#ifdef CONFIG_SOC_IMX25
|
||||
const struct imx_sdhci_esdhc_imx_data
|
||||
imx25_sdhci_esdhc_imx_data[] __initconst = {
|
||||
#define imx25_sdhci_esdhc_imx_data_entry(_id, _hwid) \
|
||||
imx_sdhci_esdhc_imx_data_entry(MX25, _id, _hwid)
|
||||
imx_sdhci_esdhc_imx_data_entry(MX25, "sdhci-esdhc-imx25", _id, _hwid)
|
||||
imx25_sdhci_esdhc_imx_data_entry(0, 1),
|
||||
imx25_sdhci_esdhc_imx_data_entry(1, 2),
|
||||
};
|
||||
@ -34,7 +35,7 @@ imx25_sdhci_esdhc_imx_data[] __initconst = {
|
||||
const struct imx_sdhci_esdhc_imx_data
|
||||
imx35_sdhci_esdhc_imx_data[] __initconst = {
|
||||
#define imx35_sdhci_esdhc_imx_data_entry(_id, _hwid) \
|
||||
imx_sdhci_esdhc_imx_data_entry(MX35, _id, _hwid)
|
||||
imx_sdhci_esdhc_imx_data_entry(MX35, "sdhci-esdhc-imx35", _id, _hwid)
|
||||
imx35_sdhci_esdhc_imx_data_entry(0, 1),
|
||||
imx35_sdhci_esdhc_imx_data_entry(1, 2),
|
||||
imx35_sdhci_esdhc_imx_data_entry(2, 3),
|
||||
@ -45,7 +46,7 @@ imx35_sdhci_esdhc_imx_data[] __initconst = {
|
||||
const struct imx_sdhci_esdhc_imx_data
|
||||
imx51_sdhci_esdhc_imx_data[] __initconst = {
|
||||
#define imx51_sdhci_esdhc_imx_data_entry(_id, _hwid) \
|
||||
imx_sdhci_esdhc_imx_data_entry(MX51, _id, _hwid)
|
||||
imx_sdhci_esdhc_imx_data_entry(MX51, "sdhci-esdhc-imx51", _id, _hwid)
|
||||
imx51_sdhci_esdhc_imx_data_entry(0, 1),
|
||||
imx51_sdhci_esdhc_imx_data_entry(1, 2),
|
||||
imx51_sdhci_esdhc_imx_data_entry(2, 3),
|
||||
@ -57,7 +58,7 @@ imx51_sdhci_esdhc_imx_data[] __initconst = {
|
||||
const struct imx_sdhci_esdhc_imx_data
|
||||
imx53_sdhci_esdhc_imx_data[] __initconst = {
|
||||
#define imx53_sdhci_esdhc_imx_data_entry(_id, _hwid) \
|
||||
imx_sdhci_esdhc_imx_data_entry(MX53, _id, _hwid)
|
||||
imx_sdhci_esdhc_imx_data_entry(MX53, "sdhci-esdhc-imx53", _id, _hwid)
|
||||
imx53_sdhci_esdhc_imx_data_entry(0, 1),
|
||||
imx53_sdhci_esdhc_imx_data_entry(1, 2),
|
||||
imx53_sdhci_esdhc_imx_data_entry(2, 3),
|
||||
@ -65,6 +66,11 @@ imx53_sdhci_esdhc_imx_data[] __initconst = {
|
||||
};
|
||||
#endif /* ifdef CONFIG_SOC_IMX53 */
|
||||
|
||||
static const struct esdhc_platform_data default_esdhc_pdata __initconst = {
|
||||
.wp_type = ESDHC_WP_NONE,
|
||||
.cd_type = ESDHC_CD_NONE,
|
||||
};
|
||||
|
||||
struct platform_device *__init imx_add_sdhci_esdhc_imx(
|
||||
const struct imx_sdhci_esdhc_imx_data *data,
|
||||
const struct esdhc_platform_data *pdata)
|
||||
@ -81,6 +87,13 @@ struct platform_device *__init imx_add_sdhci_esdhc_imx(
|
||||
},
|
||||
};
|
||||
|
||||
return imx_add_platform_device("sdhci-esdhc-imx", data->id, res,
|
||||
/*
|
||||
* If machine does not provide pdata, use the default one
|
||||
* which means no WP/CD support
|
||||
*/
|
||||
if (!pdata)
|
||||
pdata = &default_esdhc_pdata;
|
||||
|
||||
return imx_add_platform_device(data->devid, data->id, res,
|
||||
ARRAY_SIZE(res), pdata, sizeof(*pdata));
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ static inline struct platform_device *imx_add_platform_device(
|
||||
|
||||
#include <linux/fec.h>
|
||||
struct imx_fec_data {
|
||||
const char *devid;
|
||||
resource_size_t iobase;
|
||||
resource_size_t irq;
|
||||
};
|
||||
@ -276,6 +277,7 @@ struct platform_device *__init imx_add_mxc_w1(
|
||||
|
||||
#include <mach/esdhc.h>
|
||||
struct imx_sdhci_esdhc_imx_data {
|
||||
const char *devid;
|
||||
int id;
|
||||
resource_size_t iobase;
|
||||
resource_size_t irq;
|
||||
@ -297,5 +299,5 @@ struct platform_device *__init imx_add_spi_imx(
|
||||
const struct spi_imx_master *pdata);
|
||||
|
||||
struct platform_device *imx_add_imx_dma(void);
|
||||
struct platform_device *imx_add_imx_sdma(
|
||||
struct platform_device *imx_add_imx_sdma(char *name,
|
||||
resource_size_t iobase, int irq, struct sdma_platform_data *pdata);
|
||||
|
@ -60,7 +60,8 @@ static inline int imx_dma_is_ipu(struct dma_chan *chan)
|
||||
|
||||
static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
|
||||
{
|
||||
return !strcmp(dev_name(chan->device->dev), "imx-sdma") ||
|
||||
return !strcmp(dev_name(chan->device->dev), "imx31-sdma") ||
|
||||
!strcmp(dev_name(chan->device->dev), "imx35-sdma") ||
|
||||
!strcmp(dev_name(chan->device->dev), "imx-dma");
|
||||
}
|
||||
|
||||
|
@ -10,17 +10,34 @@
|
||||
#ifndef __ASM_ARCH_IMX_ESDHC_H
|
||||
#define __ASM_ARCH_IMX_ESDHC_H
|
||||
|
||||
enum wp_types {
|
||||
ESDHC_WP_NONE, /* no WP, neither controller nor gpio */
|
||||
ESDHC_WP_CONTROLLER, /* mmc controller internal WP */
|
||||
ESDHC_WP_GPIO, /* external gpio pin for WP */
|
||||
};
|
||||
|
||||
enum cd_types {
|
||||
ESDHC_CD_NONE, /* no CD, neither controller nor gpio */
|
||||
ESDHC_CD_CONTROLLER, /* mmc controller internal CD */
|
||||
ESDHC_CD_GPIO, /* external gpio pin for CD */
|
||||
ESDHC_CD_PERMANENT, /* no CD, card permanently wired to host */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct esdhc_platform_data - optional platform data for esdhc on i.MX
|
||||
* struct esdhc_platform_data - platform data for esdhc on i.MX
|
||||
*
|
||||
* strongly recommended for i.MX25/35, not needed for other variants
|
||||
* ESDHC_WP(CD)_CONTROLLER type is not available on i.MX25/35.
|
||||
*
|
||||
* @wp_gpio: gpio for write_protect (-EINVAL if unused)
|
||||
* @cd_gpio: gpio for card_detect interrupt (-EINVAL if unused)
|
||||
* @wp_gpio: gpio for write_protect
|
||||
* @cd_gpio: gpio for card_detect interrupt
|
||||
* @wp_type: type of write_protect method (see wp_types enum above)
|
||||
* @cd_type: type of card_detect method (see cd_types enum above)
|
||||
*/
|
||||
|
||||
struct esdhc_platform_data {
|
||||
unsigned int wp_gpio;
|
||||
unsigned int cd_gpio;
|
||||
enum wp_types wp_type;
|
||||
enum cd_types cd_type;
|
||||
};
|
||||
#endif /* __ASM_ARCH_IMX_ESDHC_H */
|
||||
|
@ -48,12 +48,10 @@ struct sdma_script_start_addrs {
|
||||
/**
|
||||
* struct sdma_platform_data - platform specific data for SDMA engine
|
||||
*
|
||||
* @sdma_version The version of this SDMA engine
|
||||
* @fw_name The firmware name
|
||||
* @script_addrs SDMA scripts addresses in SDMA ROM
|
||||
*/
|
||||
struct sdma_platform_data {
|
||||
int sdma_version;
|
||||
char *fw_name;
|
||||
struct sdma_script_start_addrs *script_addrs;
|
||||
};
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <mach/sdma.h>
|
||||
@ -65,8 +67,8 @@
|
||||
#define SDMA_ONCE_RTB 0x060
|
||||
#define SDMA_XTRIG_CONF1 0x070
|
||||
#define SDMA_XTRIG_CONF2 0x074
|
||||
#define SDMA_CHNENBL0_V2 0x200
|
||||
#define SDMA_CHNENBL0_V1 0x080
|
||||
#define SDMA_CHNENBL0_IMX35 0x200
|
||||
#define SDMA_CHNENBL0_IMX31 0x080
|
||||
#define SDMA_CHNPRI_0 0x100
|
||||
|
||||
/*
|
||||
@ -299,13 +301,18 @@ struct sdma_firmware_header {
|
||||
u32 ram_code_size;
|
||||
};
|
||||
|
||||
enum sdma_devtype {
|
||||
IMX31_SDMA, /* runs on i.mx31 */
|
||||
IMX35_SDMA, /* runs on i.mx35 and later */
|
||||
};
|
||||
|
||||
struct sdma_engine {
|
||||
struct device *dev;
|
||||
struct device_dma_parameters dma_parms;
|
||||
struct sdma_channel channel[MAX_DMA_CHANNELS];
|
||||
struct sdma_channel_control *channel_control;
|
||||
void __iomem *regs;
|
||||
unsigned int version;
|
||||
enum sdma_devtype devtype;
|
||||
unsigned int num_events;
|
||||
struct sdma_context_data *context;
|
||||
dma_addr_t context_phys;
|
||||
@ -314,6 +321,26 @@ struct sdma_engine {
|
||||
struct sdma_script_start_addrs *script_addrs;
|
||||
};
|
||||
|
||||
static struct platform_device_id sdma_devtypes[] = {
|
||||
{
|
||||
.name = "imx31-sdma",
|
||||
.driver_data = IMX31_SDMA,
|
||||
}, {
|
||||
.name = "imx35-sdma",
|
||||
.driver_data = IMX35_SDMA,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, sdma_devtypes);
|
||||
|
||||
static const struct of_device_id sdma_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx31-sdma", .data = &sdma_devtypes[IMX31_SDMA], },
|
||||
{ .compatible = "fsl,imx35-sdma", .data = &sdma_devtypes[IMX35_SDMA], },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sdma_dt_ids);
|
||||
|
||||
#define SDMA_H_CONFIG_DSPDMA (1 << 12) /* indicates if the DSPDMA is used */
|
||||
#define SDMA_H_CONFIG_RTD_PINS (1 << 11) /* indicates if Real-Time Debug pins are enabled */
|
||||
#define SDMA_H_CONFIG_ACR (1 << 4) /* indicates if AHB freq /core freq = 2 or 1 */
|
||||
@ -321,8 +348,8 @@ struct sdma_engine {
|
||||
|
||||
static inline u32 chnenbl_ofs(struct sdma_engine *sdma, unsigned int event)
|
||||
{
|
||||
u32 chnenbl0 = (sdma->version == 2 ? SDMA_CHNENBL0_V2 : SDMA_CHNENBL0_V1);
|
||||
|
||||
u32 chnenbl0 = (sdma->devtype == IMX31_SDMA ? SDMA_CHNENBL0_IMX31 :
|
||||
SDMA_CHNENBL0_IMX35);
|
||||
return chnenbl0 + event * 4;
|
||||
}
|
||||
|
||||
@ -1108,22 +1135,14 @@ static int __init sdma_get_firmware(struct sdma_engine *sdma,
|
||||
const char *fw_name)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
char *fwname;
|
||||
const struct sdma_firmware_header *header;
|
||||
int ret;
|
||||
const struct sdma_script_start_addrs *addr;
|
||||
unsigned short *ram_code;
|
||||
|
||||
fwname = kasprintf(GFP_KERNEL, "%s", fw_name);
|
||||
if (!fwname)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = request_firmware(&fw, fwname, sdma->dev);
|
||||
if (ret) {
|
||||
kfree(fwname);
|
||||
ret = request_firmware(&fw, fw_name, sdma->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
kfree(fwname);
|
||||
|
||||
if (fw->size < sizeof(*header))
|
||||
goto err_firmware;
|
||||
@ -1162,15 +1181,16 @@ static int __init sdma_init(struct sdma_engine *sdma)
|
||||
int i, ret;
|
||||
dma_addr_t ccb_phys;
|
||||
|
||||
switch (sdma->version) {
|
||||
case 1:
|
||||
switch (sdma->devtype) {
|
||||
case IMX31_SDMA:
|
||||
sdma->num_events = 32;
|
||||
break;
|
||||
case 2:
|
||||
case IMX35_SDMA:
|
||||
sdma->num_events = 48;
|
||||
break;
|
||||
default:
|
||||
dev_err(sdma->dev, "Unknown version %d. aborting\n", sdma->version);
|
||||
dev_err(sdma->dev, "Unknown sdma type %d. aborting\n",
|
||||
sdma->devtype);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -1239,6 +1259,10 @@ err_dma_alloc:
|
||||
|
||||
static int __init sdma_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(sdma_dt_ids, &pdev->dev);
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const char *fw_name;
|
||||
int ret;
|
||||
int irq;
|
||||
struct resource *iores;
|
||||
@ -1254,7 +1278,7 @@ static int __init sdma_probe(struct platform_device *pdev)
|
||||
|
||||
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (!iores || irq < 0 || !pdata) {
|
||||
if (!iores || irq < 0) {
|
||||
ret = -EINVAL;
|
||||
goto err_irq;
|
||||
}
|
||||
@ -1284,7 +1308,9 @@ static int __init sdma_probe(struct platform_device *pdev)
|
||||
if (!sdma->script_addrs)
|
||||
goto err_alloc;
|
||||
|
||||
sdma->version = pdata->sdma_version;
|
||||
if (of_id)
|
||||
pdev->id_entry = of_id->data;
|
||||
sdma->devtype = pdev->id_entry->driver_data;
|
||||
|
||||
dma_cap_set(DMA_SLAVE, sdma->dma_device.cap_mask);
|
||||
dma_cap_set(DMA_CYCLIC, sdma->dma_device.cap_mask);
|
||||
@ -1314,10 +1340,30 @@ static int __init sdma_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto err_init;
|
||||
|
||||
if (pdata->script_addrs)
|
||||
if (pdata && pdata->script_addrs)
|
||||
sdma_add_scripts(sdma, pdata->script_addrs);
|
||||
|
||||
sdma_get_firmware(sdma, pdata->fw_name);
|
||||
if (pdata) {
|
||||
sdma_get_firmware(sdma, pdata->fw_name);
|
||||
} else {
|
||||
/*
|
||||
* Because that device tree does not encode ROM script address,
|
||||
* the RAM script in firmware is mandatory for device tree
|
||||
* probe, otherwise it fails.
|
||||
*/
|
||||
ret = of_property_read_string(np, "fsl,sdma-ram-script-name",
|
||||
&fw_name);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to get firmware name\n");
|
||||
goto err_init;
|
||||
}
|
||||
|
||||
ret = sdma_get_firmware(sdma, fw_name);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to get firmware\n");
|
||||
goto err_init;
|
||||
}
|
||||
}
|
||||
|
||||
sdma->dma_device.dev = &pdev->dev;
|
||||
|
||||
@ -1365,7 +1411,9 @@ static int __exit sdma_remove(struct platform_device *pdev)
|
||||
static struct platform_driver sdma_driver = {
|
||||
.driver = {
|
||||
.name = "imx-sdma",
|
||||
.of_match_table = sdma_dt_ids,
|
||||
},
|
||||
.id_table = sdma_devtypes,
|
||||
.remove = __exit_p(sdma_remove),
|
||||
};
|
||||
|
||||
|
@ -20,7 +20,9 @@
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/mmc.h>
|
||||
#include <linux/mmc/sdio.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <mach/esdhc.h>
|
||||
#include "sdhci-pltfm.h"
|
||||
#include "sdhci-esdhc.h"
|
||||
@ -29,7 +31,6 @@
|
||||
#define SDHCI_VENDOR_SPEC 0xC0
|
||||
#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002
|
||||
|
||||
#define ESDHC_FLAG_GPIO_FOR_CD (1 << 0)
|
||||
/*
|
||||
* The CMDTYPE of the CMD register (offset 0xE) should be set to
|
||||
* "11" when the STOP CMD12 is issued on imx53 to abort one
|
||||
@ -43,11 +44,68 @@
|
||||
*/
|
||||
#define ESDHC_FLAG_MULTIBLK_NO_INT (1 << 1)
|
||||
|
||||
enum imx_esdhc_type {
|
||||
IMX25_ESDHC,
|
||||
IMX35_ESDHC,
|
||||
IMX51_ESDHC,
|
||||
IMX53_ESDHC,
|
||||
};
|
||||
|
||||
struct pltfm_imx_data {
|
||||
int flags;
|
||||
u32 scratchpad;
|
||||
enum imx_esdhc_type devtype;
|
||||
struct esdhc_platform_data boarddata;
|
||||
};
|
||||
|
||||
static struct platform_device_id imx_esdhc_devtype[] = {
|
||||
{
|
||||
.name = "sdhci-esdhc-imx25",
|
||||
.driver_data = IMX25_ESDHC,
|
||||
}, {
|
||||
.name = "sdhci-esdhc-imx35",
|
||||
.driver_data = IMX35_ESDHC,
|
||||
}, {
|
||||
.name = "sdhci-esdhc-imx51",
|
||||
.driver_data = IMX51_ESDHC,
|
||||
}, {
|
||||
.name = "sdhci-esdhc-imx53",
|
||||
.driver_data = IMX53_ESDHC,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, imx_esdhc_devtype);
|
||||
|
||||
static const struct of_device_id imx_esdhc_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx25-esdhc", .data = &imx_esdhc_devtype[IMX25_ESDHC], },
|
||||
{ .compatible = "fsl,imx35-esdhc", .data = &imx_esdhc_devtype[IMX35_ESDHC], },
|
||||
{ .compatible = "fsl,imx51-esdhc", .data = &imx_esdhc_devtype[IMX51_ESDHC], },
|
||||
{ .compatible = "fsl,imx53-esdhc", .data = &imx_esdhc_devtype[IMX53_ESDHC], },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids);
|
||||
|
||||
static inline int is_imx25_esdhc(struct pltfm_imx_data *data)
|
||||
{
|
||||
return data->devtype == IMX25_ESDHC;
|
||||
}
|
||||
|
||||
static inline int is_imx35_esdhc(struct pltfm_imx_data *data)
|
||||
{
|
||||
return data->devtype == IMX35_ESDHC;
|
||||
}
|
||||
|
||||
static inline int is_imx51_esdhc(struct pltfm_imx_data *data)
|
||||
{
|
||||
return data->devtype == IMX51_ESDHC;
|
||||
}
|
||||
|
||||
static inline int is_imx53_esdhc(struct pltfm_imx_data *data)
|
||||
{
|
||||
return data->devtype == IMX53_ESDHC;
|
||||
}
|
||||
|
||||
static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg)
|
||||
{
|
||||
void __iomem *base = host->ioaddr + (reg & ~0x3);
|
||||
@ -60,17 +118,14 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
|
||||
{
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct pltfm_imx_data *imx_data = pltfm_host->priv;
|
||||
struct esdhc_platform_data *boarddata = &imx_data->boarddata;
|
||||
|
||||
/* fake CARD_PRESENT flag on mx25/35 */
|
||||
/* fake CARD_PRESENT flag */
|
||||
u32 val = readl(host->ioaddr + reg);
|
||||
|
||||
if (unlikely((reg == SDHCI_PRESENT_STATE)
|
||||
&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD))) {
|
||||
struct esdhc_platform_data *boarddata =
|
||||
host->mmc->parent->platform_data;
|
||||
|
||||
if (boarddata && gpio_is_valid(boarddata->cd_gpio)
|
||||
&& gpio_get_value(boarddata->cd_gpio))
|
||||
&& gpio_is_valid(boarddata->cd_gpio))) {
|
||||
if (gpio_get_value(boarddata->cd_gpio))
|
||||
/* no card, if a valid gpio says so... */
|
||||
val &= ~SDHCI_CARD_PRESENT;
|
||||
else
|
||||
@ -85,12 +140,12 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
|
||||
{
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct pltfm_imx_data *imx_data = pltfm_host->priv;
|
||||
struct esdhc_platform_data *boarddata = &imx_data->boarddata;
|
||||
|
||||
if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
|
||||
&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD)))
|
||||
&& (boarddata->cd_type == ESDHC_CD_GPIO)))
|
||||
/*
|
||||
* these interrupts won't work with a custom card_detect gpio
|
||||
* (only applied to mx25/35)
|
||||
*/
|
||||
val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
|
||||
|
||||
@ -173,6 +228,17 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
|
||||
return;
|
||||
}
|
||||
esdhc_clrset_le(host, 0xff, val, reg);
|
||||
|
||||
/*
|
||||
* The esdhc has a design violation to SDHC spec which tells
|
||||
* that software reset should not affect card detection circuit.
|
||||
* But esdhc clears its SYSCTL register bits [0..2] during the
|
||||
* software reset. This will stop those clocks that card detection
|
||||
* circuit relies on. To work around it, we turn the clocks on back
|
||||
* to keep card detection circuit functional.
|
||||
*/
|
||||
if ((reg == SDHCI_SOFTWARE_RESET) && (val & 1))
|
||||
esdhc_clrset_le(host, 0x7, 0x7, ESDHC_SYSTEM_CONTROL);
|
||||
}
|
||||
|
||||
static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host)
|
||||
@ -189,6 +255,26 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
|
||||
return clk_get_rate(pltfm_host->clk) / 256 / 16;
|
||||
}
|
||||
|
||||
static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
|
||||
{
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct pltfm_imx_data *imx_data = pltfm_host->priv;
|
||||
struct esdhc_platform_data *boarddata = &imx_data->boarddata;
|
||||
|
||||
switch (boarddata->wp_type) {
|
||||
case ESDHC_WP_GPIO:
|
||||
if (gpio_is_valid(boarddata->wp_gpio))
|
||||
return gpio_get_value(boarddata->wp_gpio);
|
||||
case ESDHC_WP_CONTROLLER:
|
||||
return !(readl(host->ioaddr + SDHCI_PRESENT_STATE) &
|
||||
SDHCI_WRITE_PROTECT);
|
||||
case ESDHC_WP_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static struct sdhci_ops sdhci_esdhc_ops = {
|
||||
.read_l = esdhc_readl_le,
|
||||
.read_w = esdhc_readw_le,
|
||||
@ -198,6 +284,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
|
||||
.set_clock = esdhc_set_clock,
|
||||
.get_max_clock = esdhc_pltfm_get_max_clock,
|
||||
.get_min_clock = esdhc_pltfm_get_min_clock,
|
||||
.get_ro = esdhc_pltfm_get_ro,
|
||||
};
|
||||
|
||||
static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
|
||||
@ -207,17 +294,6 @@ static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
|
||||
.ops = &sdhci_esdhc_ops,
|
||||
};
|
||||
|
||||
static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
|
||||
{
|
||||
struct esdhc_platform_data *boarddata =
|
||||
host->mmc->parent->platform_data;
|
||||
|
||||
if (boarddata && gpio_is_valid(boarddata->wp_gpio))
|
||||
return gpio_get_value(boarddata->wp_gpio);
|
||||
else
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static irqreturn_t cd_irq(int irq, void *data)
|
||||
{
|
||||
struct sdhci_host *sdhost = (struct sdhci_host *)data;
|
||||
@ -226,8 +302,48 @@ static irqreturn_t cd_irq(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static int __devinit
|
||||
sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
|
||||
struct esdhc_platform_data *boarddata)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
if (of_get_property(np, "fsl,card-wired", NULL))
|
||||
boarddata->cd_type = ESDHC_CD_PERMANENT;
|
||||
|
||||
if (of_get_property(np, "fsl,cd-controller", NULL))
|
||||
boarddata->cd_type = ESDHC_CD_CONTROLLER;
|
||||
|
||||
if (of_get_property(np, "fsl,wp-controller", NULL))
|
||||
boarddata->wp_type = ESDHC_WP_CONTROLLER;
|
||||
|
||||
boarddata->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
|
||||
if (gpio_is_valid(boarddata->cd_gpio))
|
||||
boarddata->cd_type = ESDHC_CD_GPIO;
|
||||
|
||||
boarddata->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
|
||||
if (gpio_is_valid(boarddata->wp_gpio))
|
||||
boarddata->wp_type = ESDHC_WP_GPIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int
|
||||
sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
|
||||
struct esdhc_platform_data *boarddata)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(imx_esdhc_dt_ids, &pdev->dev);
|
||||
struct sdhci_pltfm_host *pltfm_host;
|
||||
struct sdhci_host *host;
|
||||
struct esdhc_platform_data *boarddata;
|
||||
@ -242,8 +358,14 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
|
||||
pltfm_host = sdhci_priv(host);
|
||||
|
||||
imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
|
||||
if (!imx_data)
|
||||
return -ENOMEM;
|
||||
if (!imx_data) {
|
||||
err = -ENOMEM;
|
||||
goto err_imx_data;
|
||||
}
|
||||
|
||||
if (of_id)
|
||||
pdev->id_entry = of_id->data;
|
||||
imx_data->devtype = pdev->id_entry->driver_data;
|
||||
pltfm_host->priv = imx_data;
|
||||
|
||||
clk = clk_get(mmc_dev(host->mmc), NULL);
|
||||
@ -255,50 +377,72 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
|
||||
clk_enable(clk);
|
||||
pltfm_host->clk = clk;
|
||||
|
||||
if (!cpu_is_mx25())
|
||||
if (!is_imx25_esdhc(imx_data))
|
||||
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
|
||||
|
||||
if (cpu_is_mx25() || cpu_is_mx35()) {
|
||||
if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data))
|
||||
/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
|
||||
host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
|
||||
/* write_protect can't be routed to controller, use gpio */
|
||||
sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
|
||||
}
|
||||
|
||||
if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
|
||||
if (is_imx53_esdhc(imx_data))
|
||||
imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
|
||||
|
||||
boarddata = host->mmc->parent->platform_data;
|
||||
if (boarddata) {
|
||||
boarddata = &imx_data->boarddata;
|
||||
if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) {
|
||||
if (!host->mmc->parent->platform_data) {
|
||||
dev_err(mmc_dev(host->mmc), "no board data!\n");
|
||||
err = -EINVAL;
|
||||
goto no_board_data;
|
||||
}
|
||||
imx_data->boarddata = *((struct esdhc_platform_data *)
|
||||
host->mmc->parent->platform_data);
|
||||
}
|
||||
|
||||
/* write_protect */
|
||||
if (boarddata->wp_type == ESDHC_WP_GPIO) {
|
||||
err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
|
||||
if (err) {
|
||||
dev_warn(mmc_dev(host->mmc),
|
||||
"no write-protect pin available!\n");
|
||||
boarddata->wp_gpio = err;
|
||||
"no write-protect pin available!\n");
|
||||
boarddata->wp_gpio = -EINVAL;
|
||||
}
|
||||
} else {
|
||||
boarddata->wp_gpio = -EINVAL;
|
||||
}
|
||||
|
||||
/* card_detect */
|
||||
if (boarddata->cd_type != ESDHC_CD_GPIO)
|
||||
boarddata->cd_gpio = -EINVAL;
|
||||
|
||||
switch (boarddata->cd_type) {
|
||||
case ESDHC_CD_GPIO:
|
||||
err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
|
||||
if (err) {
|
||||
dev_warn(mmc_dev(host->mmc),
|
||||
dev_err(mmc_dev(host->mmc),
|
||||
"no card-detect pin available!\n");
|
||||
goto no_card_detect_pin;
|
||||
}
|
||||
|
||||
/* i.MX5x has issues to be researched */
|
||||
if (!cpu_is_mx25() && !cpu_is_mx35())
|
||||
goto not_supported;
|
||||
|
||||
err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
|
||||
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
|
||||
mmc_hostname(host->mmc), host);
|
||||
if (err) {
|
||||
dev_warn(mmc_dev(host->mmc), "request irq error\n");
|
||||
dev_err(mmc_dev(host->mmc), "request irq error\n");
|
||||
goto no_card_detect_irq;
|
||||
}
|
||||
/* fall through */
|
||||
|
||||
imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD;
|
||||
/* Now we have a working card_detect again */
|
||||
case ESDHC_CD_CONTROLLER:
|
||||
/* we have a working card_detect back */
|
||||
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
|
||||
break;
|
||||
|
||||
case ESDHC_CD_PERMANENT:
|
||||
host->mmc->caps = MMC_CAP_NONREMOVABLE;
|
||||
break;
|
||||
|
||||
case ESDHC_CD_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
err = sdhci_add_host(host);
|
||||
@ -307,16 +451,21 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
|
||||
no_card_detect_irq:
|
||||
gpio_free(boarddata->cd_gpio);
|
||||
no_card_detect_pin:
|
||||
boarddata->cd_gpio = err;
|
||||
not_supported:
|
||||
kfree(imx_data);
|
||||
err_add_host:
|
||||
err_add_host:
|
||||
if (gpio_is_valid(boarddata->cd_gpio))
|
||||
free_irq(gpio_to_irq(boarddata->cd_gpio), host);
|
||||
no_card_detect_irq:
|
||||
if (gpio_is_valid(boarddata->cd_gpio))
|
||||
gpio_free(boarddata->cd_gpio);
|
||||
if (gpio_is_valid(boarddata->wp_gpio))
|
||||
gpio_free(boarddata->wp_gpio);
|
||||
no_card_detect_pin:
|
||||
no_board_data:
|
||||
clk_disable(pltfm_host->clk);
|
||||
clk_put(pltfm_host->clk);
|
||||
err_clk_get:
|
||||
err_clk_get:
|
||||
kfree(imx_data);
|
||||
err_imx_data:
|
||||
sdhci_pltfm_free(pdev);
|
||||
return err;
|
||||
}
|
||||
@ -325,20 +474,18 @@ static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct sdhci_host *host = platform_get_drvdata(pdev);
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
|
||||
struct pltfm_imx_data *imx_data = pltfm_host->priv;
|
||||
struct esdhc_platform_data *boarddata = &imx_data->boarddata;
|
||||
int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
|
||||
|
||||
sdhci_remove_host(host, dead);
|
||||
|
||||
if (boarddata && gpio_is_valid(boarddata->wp_gpio))
|
||||
if (gpio_is_valid(boarddata->wp_gpio))
|
||||
gpio_free(boarddata->wp_gpio);
|
||||
|
||||
if (boarddata && gpio_is_valid(boarddata->cd_gpio)) {
|
||||
if (gpio_is_valid(boarddata->cd_gpio)) {
|
||||
free_irq(gpio_to_irq(boarddata->cd_gpio), host);
|
||||
gpio_free(boarddata->cd_gpio);
|
||||
|
||||
if (!(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION))
|
||||
free_irq(gpio_to_irq(boarddata->cd_gpio), host);
|
||||
}
|
||||
|
||||
clk_disable(pltfm_host->clk);
|
||||
@ -354,7 +501,9 @@ static struct platform_driver sdhci_esdhc_imx_driver = {
|
||||
.driver = {
|
||||
.name = "sdhci-esdhc-imx",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = imx_esdhc_dt_ids,
|
||||
},
|
||||
.id_table = imx_esdhc_devtype,
|
||||
.probe = sdhci_esdhc_imx_probe,
|
||||
.remove = __devexit_p(sdhci_esdhc_imx_remove),
|
||||
#ifdef CONFIG_PM
|
||||
|
@ -85,6 +85,7 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
|
||||
{
|
||||
struct sdhci_host *host;
|
||||
struct sdhci_pltfm_host *pltfm_host;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct resource *iomem;
|
||||
int ret;
|
||||
|
||||
@ -98,7 +99,7 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
|
||||
dev_err(&pdev->dev, "Invalid iomem size!\n");
|
||||
|
||||
/* Some PCI-based MFD need the parent here */
|
||||
if (pdev->dev.parent != &platform_bus)
|
||||
if (pdev->dev.parent != &platform_bus && !np)
|
||||
host = sdhci_alloc_host(pdev->dev.parent, sizeof(*pltfm_host));
|
||||
else
|
||||
host = sdhci_alloc_host(&pdev->dev, sizeof(*pltfm_host));
|
||||
|
@ -44,6 +44,10 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/fec.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_net.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
@ -66,17 +70,42 @@
|
||||
#define FEC_QUIRK_ENET_MAC (1 << 0)
|
||||
/* Controller needs driver to swap frame */
|
||||
#define FEC_QUIRK_SWAP_FRAME (1 << 1)
|
||||
/* Controller uses gasket */
|
||||
#define FEC_QUIRK_USE_GASKET (1 << 2)
|
||||
|
||||
static struct platform_device_id fec_devtype[] = {
|
||||
{
|
||||
/* keep it for coldfire */
|
||||
.name = DRIVER_NAME,
|
||||
.driver_data = 0,
|
||||
}, {
|
||||
.name = "imx25-fec",
|
||||
.driver_data = FEC_QUIRK_USE_GASKET,
|
||||
}, {
|
||||
.name = "imx27-fec",
|
||||
.driver_data = 0,
|
||||
}, {
|
||||
.name = "imx28-fec",
|
||||
.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME,
|
||||
},
|
||||
{ }
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, fec_devtype);
|
||||
|
||||
enum imx_fec_type {
|
||||
IMX25_FEC = 1, /* runs on i.mx25/50/53 */
|
||||
IMX27_FEC, /* runs on i.mx27/35/51 */
|
||||
IMX28_FEC,
|
||||
};
|
||||
|
||||
static const struct of_device_id fec_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx25-fec", .data = &fec_devtype[IMX25_FEC], },
|
||||
{ .compatible = "fsl,imx27-fec", .data = &fec_devtype[IMX27_FEC], },
|
||||
{ .compatible = "fsl,imx28-fec", .data = &fec_devtype[IMX28_FEC], },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, fec_dt_ids);
|
||||
|
||||
static unsigned char macaddr[ETH_ALEN];
|
||||
module_param_array(macaddr, byte, NULL, 0);
|
||||
@ -427,7 +456,7 @@ fec_restart(struct net_device *ndev, int duplex)
|
||||
|
||||
} else {
|
||||
#ifdef FEC_MIIGSK_ENR
|
||||
if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) {
|
||||
if (id_entry->driver_data & FEC_QUIRK_USE_GASKET) {
|
||||
/* disable the gasket and wait */
|
||||
writel(0, fep->hwp + FEC_MIIGSK_ENR);
|
||||
while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4)
|
||||
@ -436,8 +465,11 @@ fec_restart(struct net_device *ndev, int duplex)
|
||||
/*
|
||||
* configure the gasket:
|
||||
* RMII, 50 MHz, no loopback, no echo
|
||||
* MII, 25 MHz, no loopback, no echo
|
||||
*/
|
||||
writel(1, fep->hwp + FEC_MIIGSK_CFGR);
|
||||
writel((fep->phy_interface == PHY_INTERFACE_MODE_RMII) ?
|
||||
1 : 0, fep->hwp + FEC_MIIGSK_CFGR);
|
||||
|
||||
|
||||
/* re-enable the gasket */
|
||||
writel(2, fep->hwp + FEC_MIIGSK_ENR);
|
||||
@ -734,8 +766,22 @@ static void __inline__ fec_get_mac(struct net_device *ndev)
|
||||
*/
|
||||
iap = macaddr;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
/*
|
||||
* 2) from flash or fuse (via platform data)
|
||||
* 2) from device tree data
|
||||
*/
|
||||
if (!is_valid_ether_addr(iap)) {
|
||||
struct device_node *np = fep->pdev->dev.of_node;
|
||||
if (np) {
|
||||
const char *mac = of_get_mac_address(np);
|
||||
if (mac)
|
||||
iap = (unsigned char *) mac;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 3) from flash or fuse (via platform data)
|
||||
*/
|
||||
if (!is_valid_ether_addr(iap)) {
|
||||
#ifdef CONFIG_M5272
|
||||
@ -748,7 +794,7 @@ static void __inline__ fec_get_mac(struct net_device *ndev)
|
||||
}
|
||||
|
||||
/*
|
||||
* 3) FEC mac registers set by bootloader
|
||||
* 4) FEC mac registers set by bootloader
|
||||
*/
|
||||
if (!is_valid_ether_addr(iap)) {
|
||||
*((unsigned long *) &tmpaddr[0]) =
|
||||
@ -1354,6 +1400,52 @@ static int fec_enet_init(struct net_device *ndev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
|
||||
if (np)
|
||||
return of_get_phy_mode(np);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int __devinit fec_reset_phy(struct platform_device *pdev)
|
||||
{
|
||||
int err, phy_reset;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
|
||||
err = gpio_request_one(phy_reset, GPIOF_OUT_INIT_LOW, "phy-reset");
|
||||
if (err) {
|
||||
pr_warn("FEC: failed to get gpio phy-reset: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
msleep(1);
|
||||
gpio_set_value(phy_reset, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* CONFIG_OF */
|
||||
static inline int fec_get_phy_mode_dt(struct platform_device *pdev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int fec_reset_phy(struct platform_device *pdev)
|
||||
{
|
||||
/*
|
||||
* In case of platform probe, the reset has been done
|
||||
* by machine code.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static int __devinit
|
||||
fec_probe(struct platform_device *pdev)
|
||||
{
|
||||
@ -1362,6 +1454,11 @@ fec_probe(struct platform_device *pdev)
|
||||
struct net_device *ndev;
|
||||
int i, irq, ret = 0;
|
||||
struct resource *r;
|
||||
const struct of_device_id *of_id;
|
||||
|
||||
of_id = of_match_device(fec_dt_ids, &pdev->dev);
|
||||
if (of_id)
|
||||
pdev->id_entry = of_id->data;
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!r)
|
||||
@ -1393,9 +1490,18 @@ fec_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, ndev);
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
if (pdata)
|
||||
fep->phy_interface = pdata->phy;
|
||||
ret = fec_get_phy_mode_dt(pdev);
|
||||
if (ret < 0) {
|
||||
pdata = pdev->dev.platform_data;
|
||||
if (pdata)
|
||||
fep->phy_interface = pdata->phy;
|
||||
else
|
||||
fep->phy_interface = PHY_INTERFACE_MODE_MII;
|
||||
} else {
|
||||
fep->phy_interface = ret;
|
||||
}
|
||||
|
||||
fec_reset_phy(pdev);
|
||||
|
||||
/* This device has up to three irqs on some platforms */
|
||||
for (i = 0; i < 3; i++) {
|
||||
@ -1530,6 +1636,7 @@ static struct platform_driver fec_driver = {
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &fec_pm_ops,
|
||||
#endif
|
||||
.of_match_table = fec_dt_ids,
|
||||
},
|
||||
.id_table = fec_devtype,
|
||||
.probe = fec_probe,
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
@ -2506,18 +2507,6 @@ static int __devinit emac_init_config(struct emac_instance *dev)
|
||||
{
|
||||
struct device_node *np = dev->ofdev->dev.of_node;
|
||||
const void *p;
|
||||
unsigned int plen;
|
||||
const char *pm, *phy_modes[] = {
|
||||
[PHY_MODE_NA] = "",
|
||||
[PHY_MODE_MII] = "mii",
|
||||
[PHY_MODE_RMII] = "rmii",
|
||||
[PHY_MODE_SMII] = "smii",
|
||||
[PHY_MODE_RGMII] = "rgmii",
|
||||
[PHY_MODE_TBI] = "tbi",
|
||||
[PHY_MODE_GMII] = "gmii",
|
||||
[PHY_MODE_RTBI] = "rtbi",
|
||||
[PHY_MODE_SGMII] = "sgmii",
|
||||
};
|
||||
|
||||
/* Read config from device-tree */
|
||||
if (emac_read_uint_prop(np, "mal-device", &dev->mal_ph, 1))
|
||||
@ -2566,23 +2555,9 @@ static int __devinit emac_init_config(struct emac_instance *dev)
|
||||
dev->mal_burst_size = 256;
|
||||
|
||||
/* PHY mode needs some decoding */
|
||||
dev->phy_mode = PHY_MODE_NA;
|
||||
pm = of_get_property(np, "phy-mode", &plen);
|
||||
if (pm != NULL) {
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(phy_modes); i++)
|
||||
if (!strcasecmp(pm, phy_modes[i])) {
|
||||
dev->phy_mode = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Backward compat with non-final DT */
|
||||
if (dev->phy_mode == PHY_MODE_NA && pm != NULL && plen == 4) {
|
||||
u32 nmode = *(const u32 *)pm;
|
||||
if (nmode > PHY_MODE_NA && nmode <= PHY_MODE_SGMII)
|
||||
dev->phy_mode = nmode;
|
||||
}
|
||||
dev->phy_mode = of_get_phy_mode(np);
|
||||
if (dev->phy_mode < 0)
|
||||
dev->phy_mode = PHY_MODE_NA;
|
||||
|
||||
/* Check EMAC version */
|
||||
if (of_device_is_compatible(np, "ibm,emac4sync")) {
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define __IBM_NEWEMAC_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/phy.h>
|
||||
|
||||
/* EMAC registers Write Access rules */
|
||||
struct emac_regs {
|
||||
@ -106,15 +107,15 @@ struct emac_regs {
|
||||
/*
|
||||
* PHY mode settings (EMAC <-> ZMII/RGMII bridge <-> PHY)
|
||||
*/
|
||||
#define PHY_MODE_NA 0
|
||||
#define PHY_MODE_MII 1
|
||||
#define PHY_MODE_RMII 2
|
||||
#define PHY_MODE_SMII 3
|
||||
#define PHY_MODE_RGMII 4
|
||||
#define PHY_MODE_TBI 5
|
||||
#define PHY_MODE_GMII 6
|
||||
#define PHY_MODE_RTBI 7
|
||||
#define PHY_MODE_SGMII 8
|
||||
#define PHY_MODE_NA PHY_INTERFACE_MODE_NA
|
||||
#define PHY_MODE_MII PHY_INTERFACE_MODE_MII
|
||||
#define PHY_MODE_RMII PHY_INTERFACE_MODE_RMII
|
||||
#define PHY_MODE_SMII PHY_INTERFACE_MODE_SMII
|
||||
#define PHY_MODE_RGMII PHY_INTERFACE_MODE_RGMII
|
||||
#define PHY_MODE_TBI PHY_INTERFACE_MODE_TBI
|
||||
#define PHY_MODE_GMII PHY_INTERFACE_MODE_GMII
|
||||
#define PHY_MODE_RTBI PHY_INTERFACE_MODE_RTBI
|
||||
#define PHY_MODE_SGMII PHY_INTERFACE_MODE_SGMII
|
||||
|
||||
/* EMACx_MR0 */
|
||||
#define EMAC_MR0_RXI 0x80000000
|
||||
|
@ -28,12 +28,15 @@
|
||||
#include "emac.h"
|
||||
#include "phy.h"
|
||||
|
||||
static inline int phy_read(struct mii_phy *phy, int reg)
|
||||
#define phy_read _phy_read
|
||||
#define phy_write _phy_write
|
||||
|
||||
static inline int _phy_read(struct mii_phy *phy, int reg)
|
||||
{
|
||||
return phy->mdio_read(phy->dev, phy->address, reg);
|
||||
}
|
||||
|
||||
static inline void phy_write(struct mii_phy *phy, int reg, int val)
|
||||
static inline void _phy_write(struct mii_phy *phy, int reg, int val)
|
||||
{
|
||||
phy->mdio_write(phy->dev, phy->address, reg, val);
|
||||
}
|
||||
|
@ -8,6 +8,51 @@
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/phy.h>
|
||||
|
||||
/**
|
||||
* It maps 'enum phy_interface_t' found in include/linux/phy.h
|
||||
* into the device tree binding of 'phy-mode', so that Ethernet
|
||||
* device driver can get phy interface from device tree.
|
||||
*/
|
||||
static const char *phy_modes[] = {
|
||||
[PHY_INTERFACE_MODE_NA] = "",
|
||||
[PHY_INTERFACE_MODE_MII] = "mii",
|
||||
[PHY_INTERFACE_MODE_GMII] = "gmii",
|
||||
[PHY_INTERFACE_MODE_SGMII] = "sgmii",
|
||||
[PHY_INTERFACE_MODE_TBI] = "tbi",
|
||||
[PHY_INTERFACE_MODE_RMII] = "rmii",
|
||||
[PHY_INTERFACE_MODE_RGMII] = "rgmii",
|
||||
[PHY_INTERFACE_MODE_RGMII_ID] = "rgmii-id",
|
||||
[PHY_INTERFACE_MODE_RGMII_RXID] = "rgmii-rxid",
|
||||
[PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid",
|
||||
[PHY_INTERFACE_MODE_RTBI] = "rtbi",
|
||||
[PHY_INTERFACE_MODE_SMII] = "smii",
|
||||
};
|
||||
|
||||
/**
|
||||
* of_get_phy_mode - Get phy mode for given device_node
|
||||
* @np: Pointer to the given device_node
|
||||
*
|
||||
* The function gets phy interface string from property 'phy-mode',
|
||||
* and return its index in phy_modes table, or errno in error case.
|
||||
*/
|
||||
const int of_get_phy_mode(struct device_node *np)
|
||||
{
|
||||
const char *pm;
|
||||
int err, i;
|
||||
|
||||
err = of_property_read_string(np, "phy-mode", &pm);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(phy_modes); i++)
|
||||
if (!strcasecmp(pm, phy_modes[i]))
|
||||
return i;
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_get_phy_mode);
|
||||
|
||||
/**
|
||||
* Search the device tree for the best MAC address to use. 'mac-address' is
|
||||
|
@ -45,10 +45,11 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/rational.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/imx-uart.h>
|
||||
|
||||
/* Register definitions */
|
||||
@ -66,8 +67,9 @@
|
||||
#define UBIR 0xa4 /* BRM Incremental Register */
|
||||
#define UBMR 0xa8 /* BRM Modulator Register */
|
||||
#define UBRC 0xac /* Baud Rate Count Register */
|
||||
#define MX2_ONEMS 0xb0 /* One Millisecond register */
|
||||
#define UTS (cpu_is_mx1() ? 0xd0 : 0xb4) /* UART Test Register */
|
||||
#define IMX21_ONEMS 0xb0 /* One Millisecond register */
|
||||
#define IMX1_UTS 0xd0 /* UART Test Register on i.mx1 */
|
||||
#define IMX21_UTS 0xb4 /* UART Test Register on all other i.mx*/
|
||||
|
||||
/* UART Control Register Bit Fields.*/
|
||||
#define URXD_CHARRDY (1<<15)
|
||||
@ -87,7 +89,7 @@
|
||||
#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */
|
||||
#define UCR1_SNDBRK (1<<4) /* Send break */
|
||||
#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */
|
||||
#define MX1_UCR1_UARTCLKEN (1<<2) /* UART clock enabled, mx1 only */
|
||||
#define IMX1_UCR1_UARTCLKEN (1<<2) /* UART clock enabled, i.mx1 only */
|
||||
#define UCR1_DOZE (1<<1) /* Doze */
|
||||
#define UCR1_UARTEN (1<<0) /* UART enabled */
|
||||
#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */
|
||||
@ -113,9 +115,7 @@
|
||||
#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */
|
||||
#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */
|
||||
#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */
|
||||
#define MX1_UCR3_REF25 (1<<3) /* Ref freq 25 MHz, only on mx1 */
|
||||
#define MX1_UCR3_REF30 (1<<2) /* Ref Freq 30 MHz, only on mx1 */
|
||||
#define MX2_UCR3_RXDMUXSEL (1<<2) /* RXD Muxed Input Select, on mx2/mx3 */
|
||||
#define IMX21_UCR3_RXDMUXSEL (1<<2) /* RXD Muxed Input Select */
|
||||
#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */
|
||||
#define UCR3_BPEN (1<<0) /* Preset registers enable */
|
||||
#define UCR4_CTSTL_SHF 10 /* CTS trigger level shift */
|
||||
@ -181,6 +181,18 @@
|
||||
|
||||
#define UART_NR 8
|
||||
|
||||
/* i.mx21 type uart runs on all i.mx except i.mx1 */
|
||||
enum imx_uart_type {
|
||||
IMX1_UART,
|
||||
IMX21_UART,
|
||||
};
|
||||
|
||||
/* device type dependent stuff */
|
||||
struct imx_uart_data {
|
||||
unsigned uts_reg;
|
||||
enum imx_uart_type devtype;
|
||||
};
|
||||
|
||||
struct imx_port {
|
||||
struct uart_port port;
|
||||
struct timer_list timer;
|
||||
@ -192,6 +204,7 @@ struct imx_port {
|
||||
unsigned int irda_inv_tx:1;
|
||||
unsigned short trcv_delay; /* transceiver delay */
|
||||
struct clk *clk;
|
||||
struct imx_uart_data *devdata;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IRDA
|
||||
@ -200,6 +213,52 @@ struct imx_port {
|
||||
#define USE_IRDA(sport) (0)
|
||||
#endif
|
||||
|
||||
static struct imx_uart_data imx_uart_devdata[] = {
|
||||
[IMX1_UART] = {
|
||||
.uts_reg = IMX1_UTS,
|
||||
.devtype = IMX1_UART,
|
||||
},
|
||||
[IMX21_UART] = {
|
||||
.uts_reg = IMX21_UTS,
|
||||
.devtype = IMX21_UART,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device_id imx_uart_devtype[] = {
|
||||
{
|
||||
.name = "imx1-uart",
|
||||
.driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX1_UART],
|
||||
}, {
|
||||
.name = "imx21-uart",
|
||||
.driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX21_UART],
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, imx_uart_devtype);
|
||||
|
||||
static struct of_device_id imx_uart_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], },
|
||||
{ .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX21_UART], },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, imx_uart_dt_ids);
|
||||
|
||||
static inline unsigned uts_reg(struct imx_port *sport)
|
||||
{
|
||||
return sport->devdata->uts_reg;
|
||||
}
|
||||
|
||||
static inline int is_imx1_uart(struct imx_port *sport)
|
||||
{
|
||||
return sport->devdata->devtype == IMX1_UART;
|
||||
}
|
||||
|
||||
static inline int is_imx21_uart(struct imx_port *sport)
|
||||
{
|
||||
return sport->devdata->devtype == IMX21_UART;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle any change of modem status signal since we were last called.
|
||||
*/
|
||||
@ -326,7 +385,8 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
|
||||
struct circ_buf *xmit = &sport->port.state->xmit;
|
||||
|
||||
while (!uart_circ_empty(xmit) &&
|
||||
!(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
|
||||
!(readl(sport->port.membase + uts_reg(sport))
|
||||
& UTS_TXFULL)) {
|
||||
/* send xmit->buf[xmit->tail]
|
||||
* out the port here */
|
||||
writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
|
||||
@ -373,7 +433,7 @@ static void imx_start_tx(struct uart_port *port)
|
||||
writel(temp, sport->port.membase + UCR4);
|
||||
}
|
||||
|
||||
if (readl(sport->port.membase + UTS) & UTS_TXEMPTY)
|
||||
if (readl(sport->port.membase + uts_reg(sport)) & UTS_TXEMPTY)
|
||||
imx_transmit_buffer(sport);
|
||||
}
|
||||
|
||||
@ -689,9 +749,9 @@ static int imx_startup(struct uart_port *port)
|
||||
}
|
||||
}
|
||||
|
||||
if (!cpu_is_mx1()) {
|
||||
if (is_imx21_uart(sport)) {
|
||||
temp = readl(sport->port.membase + UCR3);
|
||||
temp |= MX2_UCR3_RXDMUXSEL;
|
||||
temp |= IMX21_UCR3_RXDMUXSEL;
|
||||
writel(temp, sport->port.membase + UCR3);
|
||||
}
|
||||
|
||||
@ -923,9 +983,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
writel(num, sport->port.membase + UBIR);
|
||||
writel(denom, sport->port.membase + UBMR);
|
||||
|
||||
if (!cpu_is_mx1())
|
||||
if (is_imx21_uart(sport))
|
||||
writel(sport->port.uartclk / div / 1000,
|
||||
sport->port.membase + MX2_ONEMS);
|
||||
sport->port.membase + IMX21_ONEMS);
|
||||
|
||||
writel(old_ucr1, sport->port.membase + UCR1);
|
||||
|
||||
@ -1041,7 +1101,7 @@ static void imx_console_putchar(struct uart_port *port, int ch)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
|
||||
while (readl(sport->port.membase + UTS) & UTS_TXFULL)
|
||||
while (readl(sport->port.membase + uts_reg(sport)) & UTS_TXFULL)
|
||||
barrier();
|
||||
|
||||
writel(ch, sport->port.membase + URTX0);
|
||||
@ -1062,8 +1122,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
|
||||
ucr1 = old_ucr1 = readl(sport->port.membase + UCR1);
|
||||
old_ucr2 = readl(sport->port.membase + UCR2);
|
||||
|
||||
if (cpu_is_mx1())
|
||||
ucr1 |= MX1_UCR1_UARTCLKEN;
|
||||
if (is_imx1_uart(sport))
|
||||
ucr1 |= IMX1_UCR1_UARTCLKEN;
|
||||
ucr1 |= UCR1_UARTEN;
|
||||
ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
|
||||
|
||||
@ -1222,6 +1282,63 @@ static int serial_imx_resume(struct platform_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static int serial_imx_probe_dt(struct imx_port *sport,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(imx_uart_dt_ids, &pdev->dev);
|
||||
int ret;
|
||||
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
ret = of_alias_get_id(np, "serial");
|
||||
if (ret < 0) {
|
||||
pr_err("%s: failed to get alias id, errno %d\n",
|
||||
__func__, ret);
|
||||
return -ENODEV;
|
||||
} else {
|
||||
sport->port.line = ret;
|
||||
}
|
||||
|
||||
if (of_get_property(np, "fsl,uart-has-rtscts", NULL))
|
||||
sport->have_rtscts = 1;
|
||||
|
||||
if (of_get_property(np, "fsl,irda-mode", NULL))
|
||||
sport->use_irda = 1;
|
||||
|
||||
sport->devdata = of_id->data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int serial_imx_probe_dt(struct imx_port *sport,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void serial_imx_probe_pdata(struct imx_port *sport,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct imxuart_platform_data *pdata = pdev->dev.platform_data;
|
||||
|
||||
sport->port.line = pdev->id;
|
||||
sport->devdata = (struct imx_uart_data *) pdev->id_entry->driver_data;
|
||||
|
||||
if (!pdata)
|
||||
return;
|
||||
|
||||
if (pdata->flags & IMXUART_HAVE_RTSCTS)
|
||||
sport->have_rtscts = 1;
|
||||
|
||||
if (pdata->flags & IMXUART_IRDA)
|
||||
sport->use_irda = 1;
|
||||
}
|
||||
|
||||
static int serial_imx_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct imx_port *sport;
|
||||
@ -1234,6 +1351,10 @@ static int serial_imx_probe(struct platform_device *pdev)
|
||||
if (!sport)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = serial_imx_probe_dt(sport, pdev);
|
||||
if (ret == -ENODEV)
|
||||
serial_imx_probe_pdata(sport, pdev);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
ret = -ENODEV;
|
||||
@ -1258,7 +1379,6 @@ static int serial_imx_probe(struct platform_device *pdev)
|
||||
sport->port.fifosize = 32;
|
||||
sport->port.ops = &imx_pops;
|
||||
sport->port.flags = UPF_BOOT_AUTOCONF;
|
||||
sport->port.line = pdev->id;
|
||||
init_timer(&sport->timer);
|
||||
sport->timer.function = imx_timeout;
|
||||
sport->timer.data = (unsigned long)sport;
|
||||
@ -1272,17 +1392,9 @@ static int serial_imx_probe(struct platform_device *pdev)
|
||||
|
||||
sport->port.uartclk = clk_get_rate(sport->clk);
|
||||
|
||||
imx_ports[pdev->id] = sport;
|
||||
imx_ports[sport->port.line] = sport;
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
if (pdata && (pdata->flags & IMXUART_HAVE_RTSCTS))
|
||||
sport->have_rtscts = 1;
|
||||
|
||||
#ifdef CONFIG_IRDA
|
||||
if (pdata && (pdata->flags & IMXUART_IRDA))
|
||||
sport->use_irda = 1;
|
||||
#endif
|
||||
|
||||
if (pdata && pdata->init) {
|
||||
ret = pdata->init(pdev);
|
||||
if (ret)
|
||||
@ -1340,9 +1452,11 @@ static struct platform_driver serial_imx_driver = {
|
||||
|
||||
.suspend = serial_imx_suspend,
|
||||
.resume = serial_imx_resume,
|
||||
.id_table = imx_uart_devtype,
|
||||
.driver = {
|
||||
.name = "imx-uart",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = imx_uart_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -108,14 +108,18 @@ enum {
|
||||
};
|
||||
|
||||
struct msi_desc;
|
||||
struct irq_domain;
|
||||
|
||||
/**
|
||||
* struct irq_data - per irq and irq chip data passed down to chip functions
|
||||
* @irq: interrupt number
|
||||
* @hwirq: hardware interrupt number, local to the interrupt domain
|
||||
* @node: node index useful for balancing
|
||||
* @state_use_accessors: status information for irq chip functions.
|
||||
* Use accessor functions to deal with it
|
||||
* @chip: low level interrupt hardware access
|
||||
* @domain: Interrupt translation domain; responsible for mapping
|
||||
* between hwirq number and linux irq number.
|
||||
* @handler_data: per-IRQ data for the irq_chip methods
|
||||
* @chip_data: platform-specific per-chip private data for the chip
|
||||
* methods, to allow shared chip implementations
|
||||
@ -128,9 +132,11 @@ struct msi_desc;
|
||||
*/
|
||||
struct irq_data {
|
||||
unsigned int irq;
|
||||
unsigned long hwirq;
|
||||
unsigned int node;
|
||||
unsigned int state_use_accessors;
|
||||
struct irq_chip *chip;
|
||||
struct irq_domain *domain;
|
||||
void *handler_data;
|
||||
void *chip_data;
|
||||
struct msi_desc *msi_desc;
|
||||
|
91
include/linux/irqdomain.h
Normal file
91
include/linux/irqdomain.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* irq_domain - IRQ translation domains
|
||||
*
|
||||
* Translation infrastructure between hw and linux irq numbers. This is
|
||||
* helpful for interrupt controllers to implement mapping between hardware
|
||||
* irq numbers and the Linux irq number space.
|
||||
*
|
||||
* irq_domains also have a hook for translating device tree interrupt
|
||||
* representation into a hardware irq number that can be mapped back to a
|
||||
* Linux irq number without any extra platform support code.
|
||||
*
|
||||
* irq_domain is expected to be embedded in an interrupt controller's private
|
||||
* data structure.
|
||||
*/
|
||||
#ifndef _LINUX_IRQDOMAIN_H
|
||||
#define _LINUX_IRQDOMAIN_H
|
||||
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
|
||||
#ifdef CONFIG_IRQ_DOMAIN
|
||||
struct device_node;
|
||||
struct irq_domain;
|
||||
|
||||
/**
|
||||
* struct irq_domain_ops - Methods for irq_domain objects
|
||||
* @to_irq: (optional) given a local hardware irq number, return the linux
|
||||
* irq number. If to_irq is not implemented, then the irq_domain
|
||||
* will use this translation: irq = (domain->irq_base + hwirq)
|
||||
* @dt_translate: Given a device tree node and interrupt specifier, decode
|
||||
* the hardware irq number and linux irq type value.
|
||||
*/
|
||||
struct irq_domain_ops {
|
||||
unsigned int (*to_irq)(struct irq_domain *d, unsigned long hwirq);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
int (*dt_translate)(struct irq_domain *d, struct device_node *node,
|
||||
const u32 *intspec, unsigned int intsize,
|
||||
unsigned long *out_hwirq, unsigned int *out_type);
|
||||
#endif /* CONFIG_OF */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct irq_domain - Hardware interrupt number translation object
|
||||
* @list: Element in global irq_domain list.
|
||||
* @irq_base: Start of irq_desc range assigned to the irq_domain. The creator
|
||||
* of the irq_domain is responsible for allocating the array of
|
||||
* irq_desc structures.
|
||||
* @nr_irq: Number of irqs managed by the irq domain
|
||||
* @ops: pointer to irq_domain methods
|
||||
* @priv: private data pointer for use by owner. Not touched by irq_domain
|
||||
* core code.
|
||||
* @of_node: (optional) Pointer to device tree nodes associated with the
|
||||
* irq_domain. Used when decoding device tree interrupt specifiers.
|
||||
*/
|
||||
struct irq_domain {
|
||||
struct list_head list;
|
||||
unsigned int irq_base;
|
||||
unsigned int nr_irq;
|
||||
const struct irq_domain_ops *ops;
|
||||
void *priv;
|
||||
struct device_node *of_node;
|
||||
};
|
||||
|
||||
/**
|
||||
* irq_domain_to_irq() - Translate from a hardware irq to a linux irq number
|
||||
*
|
||||
* Returns the linux irq number associated with a hardware irq. By default,
|
||||
* the mapping is irq == domain->irq_base + hwirq, but this mapping can
|
||||
* be overridden if the irq_domain implements a .to_irq() hook.
|
||||
*/
|
||||
static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
|
||||
unsigned long hwirq)
|
||||
{
|
||||
return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
|
||||
}
|
||||
|
||||
extern void irq_domain_add(struct irq_domain *domain);
|
||||
extern void irq_domain_del(struct irq_domain *domain);
|
||||
#endif /* CONFIG_IRQ_DOMAIN */
|
||||
|
||||
#if defined(CONFIG_IRQ_DOMAIN) && defined(CONFIG_OF_IRQ)
|
||||
extern void irq_domain_add_simple(struct device_node *controller, int irq_base);
|
||||
extern void irq_domain_generate_simple(const struct of_device_id *match,
|
||||
u64 phys_base, unsigned int irq_start);
|
||||
#else /* CONFIG_IRQ_DOMAIN && CONFIG_OF_IRQ */
|
||||
static inline void irq_domain_generate_simple(const struct of_device_id *match,
|
||||
u64 phys_base, unsigned int irq_start) { }
|
||||
#endif /* CONFIG_IRQ_DOMAIN && CONFIG_OF_IRQ */
|
||||
|
||||
#endif /* _LINUX_IRQDOMAIN_H */
|
@ -63,6 +63,9 @@ extern int of_irq_map_one(struct device_node *device, int index,
|
||||
extern unsigned int irq_create_of_mapping(struct device_node *controller,
|
||||
const u32 *intspec,
|
||||
unsigned int intsize);
|
||||
#ifdef CONFIG_IRQ_DOMAIN
|
||||
extern void irq_dispose_mapping(unsigned int irq);
|
||||
#endif
|
||||
extern int of_irq_to_resource(struct device_node *dev, int index,
|
||||
struct resource *r);
|
||||
extern int of_irq_count(struct device_node *dev);
|
||||
@ -70,6 +73,7 @@ extern int of_irq_to_resource_table(struct device_node *dev,
|
||||
struct resource *res, int nr_irqs);
|
||||
extern struct device_node *of_irq_find_parent(struct device_node *child);
|
||||
|
||||
|
||||
#endif /* CONFIG_OF_IRQ */
|
||||
#endif /* CONFIG_OF */
|
||||
#endif /* __OF_IRQ_H */
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#ifdef CONFIG_OF_NET
|
||||
#include <linux/of.h>
|
||||
extern const int of_get_phy_mode(struct device_node *np);
|
||||
extern const void *of_get_mac_address(struct device_node *np);
|
||||
#endif
|
||||
|
||||
|
@ -53,6 +53,7 @@
|
||||
|
||||
/* Interface Mode definitions */
|
||||
typedef enum {
|
||||
PHY_INTERFACE_MODE_NA,
|
||||
PHY_INTERFACE_MODE_MII,
|
||||
PHY_INTERFACE_MODE_GMII,
|
||||
PHY_INTERFACE_MODE_SGMII,
|
||||
@ -62,7 +63,8 @@ typedef enum {
|
||||
PHY_INTERFACE_MODE_RGMII_ID,
|
||||
PHY_INTERFACE_MODE_RGMII_RXID,
|
||||
PHY_INTERFACE_MODE_RGMII_TXID,
|
||||
PHY_INTERFACE_MODE_RTBI
|
||||
PHY_INTERFACE_MODE_RTBI,
|
||||
PHY_INTERFACE_MODE_SMII,
|
||||
} phy_interface_t;
|
||||
|
||||
|
||||
|
@ -52,6 +52,10 @@ config IRQ_EDGE_EOI_HANDLER
|
||||
config GENERIC_IRQ_CHIP
|
||||
bool
|
||||
|
||||
# Generic irq_domain hw <--> linux irq number translation
|
||||
config IRQ_DOMAIN
|
||||
bool
|
||||
|
||||
# Support forced irq threading
|
||||
config IRQ_FORCED_THREADING
|
||||
bool
|
||||
|
@ -2,6 +2,7 @@
|
||||
obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o
|
||||
obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o
|
||||
obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
|
||||
obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o
|
||||
obj-$(CONFIG_PROC_FS) += proc.o
|
||||
obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
|
||||
obj-$(CONFIG_PM_SLEEP) += pm.o
|
||||
|
180
kernel/irq/irqdomain.c
Normal file
180
kernel/irq/irqdomain.c
Normal file
@ -0,0 +1,180 @@
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
static LIST_HEAD(irq_domain_list);
|
||||
static DEFINE_MUTEX(irq_domain_mutex);
|
||||
|
||||
/**
|
||||
* irq_domain_add() - Register an irq_domain
|
||||
* @domain: ptr to initialized irq_domain structure
|
||||
*
|
||||
* Registers an irq_domain structure. The irq_domain must at a minimum be
|
||||
* initialized with an ops structure pointer, and either a ->to_irq hook or
|
||||
* a valid irq_base value. Everything else is optional.
|
||||
*/
|
||||
void irq_domain_add(struct irq_domain *domain)
|
||||
{
|
||||
struct irq_data *d;
|
||||
int hwirq;
|
||||
|
||||
/*
|
||||
* This assumes that the irq_domain owner has already allocated
|
||||
* the irq_descs. This block will be removed when support for dynamic
|
||||
* allocation of irq_descs is added to irq_domain.
|
||||
*/
|
||||
for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
|
||||
d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
|
||||
if (d || d->domain) {
|
||||
/* things are broken; just report, don't clean up */
|
||||
WARN(1, "error: irq_desc already assigned to a domain");
|
||||
return;
|
||||
}
|
||||
d->domain = domain;
|
||||
d->hwirq = hwirq;
|
||||
}
|
||||
|
||||
mutex_lock(&irq_domain_mutex);
|
||||
list_add(&domain->list, &irq_domain_list);
|
||||
mutex_unlock(&irq_domain_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* irq_domain_del() - Unregister an irq_domain
|
||||
* @domain: ptr to registered irq_domain.
|
||||
*/
|
||||
void irq_domain_del(struct irq_domain *domain)
|
||||
{
|
||||
struct irq_data *d;
|
||||
int hwirq;
|
||||
|
||||
mutex_lock(&irq_domain_mutex);
|
||||
list_del(&domain->list);
|
||||
mutex_unlock(&irq_domain_mutex);
|
||||
|
||||
/* Clear the irq_domain assignments */
|
||||
for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
|
||||
d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
|
||||
d->domain = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF_IRQ)
|
||||
/**
|
||||
* irq_create_of_mapping() - Map a linux irq number from a DT interrupt spec
|
||||
*
|
||||
* Used by the device tree interrupt mapping code to translate a device tree
|
||||
* interrupt specifier to a valid linux irq number. Returns either a valid
|
||||
* linux IRQ number or 0.
|
||||
*
|
||||
* When the caller no longer need the irq number returned by this function it
|
||||
* should arrange to call irq_dispose_mapping().
|
||||
*/
|
||||
unsigned int irq_create_of_mapping(struct device_node *controller,
|
||||
const u32 *intspec, unsigned int intsize)
|
||||
{
|
||||
struct irq_domain *domain;
|
||||
unsigned long hwirq;
|
||||
unsigned int irq, type;
|
||||
int rc = -EINVAL;
|
||||
|
||||
/* Find a domain which can translate the irq spec */
|
||||
mutex_lock(&irq_domain_mutex);
|
||||
list_for_each_entry(domain, &irq_domain_list, list) {
|
||||
if (!domain->ops->dt_translate)
|
||||
continue;
|
||||
rc = domain->ops->dt_translate(domain, controller,
|
||||
intspec, intsize, &hwirq, &type);
|
||||
if (rc == 0)
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&irq_domain_mutex);
|
||||
|
||||
if (rc != 0)
|
||||
return 0;
|
||||
|
||||
irq = irq_domain_to_irq(domain, hwirq);
|
||||
if (type != IRQ_TYPE_NONE)
|
||||
irq_set_irq_type(irq, type);
|
||||
pr_debug("%s: mapped hwirq=%i to irq=%i, flags=%x\n",
|
||||
controller->full_name, (int)hwirq, irq, type);
|
||||
return irq;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(irq_create_of_mapping);
|
||||
|
||||
/**
|
||||
* irq_dispose_mapping() - Discard a mapping created by irq_create_of_mapping()
|
||||
* @irq: linux irq number to be discarded
|
||||
*
|
||||
* Calling this function indicates the caller no longer needs a reference to
|
||||
* the linux irq number returned by a prior call to irq_create_of_mapping().
|
||||
*/
|
||||
void irq_dispose_mapping(unsigned int irq)
|
||||
{
|
||||
/*
|
||||
* nothing yet; will be filled when support for dynamic allocation of
|
||||
* irq_descs is added to irq_domain
|
||||
*/
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(irq_dispose_mapping);
|
||||
|
||||
int irq_domain_simple_dt_translate(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 < 1)
|
||||
return -EINVAL;
|
||||
|
||||
*out_hwirq = intspec[0];
|
||||
*out_type = IRQ_TYPE_NONE;
|
||||
if (intsize > 1)
|
||||
*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct irq_domain_ops irq_domain_simple_ops = {
|
||||
.dt_translate = irq_domain_simple_dt_translate,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
|
||||
|
||||
/**
|
||||
* irq_domain_create_simple() - Set up a 'simple' translation range
|
||||
*/
|
||||
void irq_domain_add_simple(struct device_node *controller, int irq_base)
|
||||
{
|
||||
struct irq_domain *domain;
|
||||
|
||||
domain = kzalloc(sizeof(*domain), GFP_KERNEL);
|
||||
if (!domain) {
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
domain->irq_base = irq_base;
|
||||
domain->of_node = of_node_get(controller);
|
||||
domain->ops = &irq_domain_simple_ops;
|
||||
irq_domain_add(domain);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(irq_domain_add_simple);
|
||||
|
||||
void irq_domain_generate_simple(const struct of_device_id *match,
|
||||
u64 phys_base, unsigned int irq_start)
|
||||
{
|
||||
struct device_node *node;
|
||||
pr_info("looking for phys_base=%llx, irq_start=%i\n",
|
||||
(unsigned long long) phys_base, (int) irq_start);
|
||||
node = of_find_matching_node_by_address(NULL, match, phys_base);
|
||||
if (node)
|
||||
irq_domain_add_simple(node, irq_start);
|
||||
else
|
||||
pr_info("no node found\n");
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(irq_domain_generate_simple);
|
||||
#endif /* CONFIG_OF_IRQ */
|
Loading…
Reference in New Issue
Block a user