summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/boards/am335x.rst42
-rw-r--r--Documentation/boards/imx/Karo-TX613
-rw-r--r--Documentation/boards/mips/img-ci20.rst42
-rw-r--r--Documentation/boards/omap.rst4
-rw-r--r--Documentation/boards/openrisc.rst51
-rw-r--r--Documentation/devicetree/bindings/firmware/altr,passive-serial.txt24
-rw-r--r--Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.txt19
-rw-r--r--Documentation/user/barebox.rst2
-rw-r--r--Documentation/user/usb.rst21
-rw-r--r--Makefile3
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/Makefile2
-rw-r--r--arch/arm/boards/Makefile4
-rw-r--r--arch/arm/boards/afi-gf/Makefile3
-rw-r--r--arch/arm/boards/afi-gf/board.c50
-rw-r--r--arch/arm/boards/afi-gf/config.h22
-rw-r--r--arch/arm/boards/afi-gf/defaultenv-gf/boot/sd11
-rw-r--r--arch/arm/boards/afi-gf/defaultenv-gf/init/automount15
-rw-r--r--arch/arm/boards/afi-gf/defaultenv-gf/network/eth118
-rw-r--r--arch/arm/boards/afi-gf/lowlevel.c266
-rw-r--r--arch/arm/boards/datamodul-edm-qmx6/board.c8
-rw-r--r--arch/arm/boards/gateworks-ventana/Makefile2
-rw-r--r--arch/arm/boards/gateworks-ventana/board.c96
-rw-r--r--arch/arm/boards/gateworks-ventana/clocks.imxcfg8
-rw-r--r--arch/arm/boards/gateworks-ventana/flash-header-ventana-quad-1gx64.imxcfg11
-rw-r--r--arch/arm/boards/gateworks-ventana/gsc.c67
-rw-r--r--arch/arm/boards/gateworks-ventana/gsc.h58
-rw-r--r--arch/arm/boards/gateworks-ventana/lowlevel.c18
-rw-r--r--arch/arm/boards/gateworks-ventana/quad_128x64.imxcfg41
-rw-r--r--arch/arm/boards/gateworks-ventana/ram-base.imxcfg56
-rw-r--r--arch/arm/boards/karo-tx6x/1600mhz_4x128mx16.imxcfg101
-rw-r--r--arch/arm/boards/karo-tx6x/Makefile2
-rw-r--r--arch/arm/boards/karo-tx6x/board.c202
-rw-r--r--arch/arm/boards/karo-tx6x/flash-header-tx6dl-1g.imxcfg10
-rw-r--r--arch/arm/boards/karo-tx6x/lowlevel.c75
-rw-r--r--arch/arm/boards/karo-tx6x/ram-base.imxcfg71
-rw-r--r--arch/arm/boards/phytec-phycard-imx6/Makefile1
-rw-r--r--arch/arm/boards/phytec-phycard-imx6/board.c3
-rw-r--r--arch/arm/boards/phytec-phycard-imx6/defaultenv-phycard-imx6/boot/nand7
-rw-r--r--arch/arm/boards/phytec-phycard-imx6/defaultenv-phycard-imx6/boot/sd-ext36
-rw-r--r--arch/arm/boards/phytec-phycard-imx6/defaultenv-phycard-imx6/config-board (renamed from arch/arm/boards/phytec-phycard-imx6/env/config-board)2
-rw-r--r--arch/arm/boards/phytec-phycard-imx6/defaultenv-phycard-imx6/init/automount14
-rw-r--r--arch/arm/boards/phytec-phycard-imx6/env/boot/nand7
-rw-r--r--arch/arm/boards/phytec-phycard-imx6/env/boot/sd-ext36
-rw-r--r--arch/arm/boards/phytec-phycore-am335x/board.c2
-rw-r--r--arch/arm/boards/phytec-phycore-am335x/lowlevel.c125
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/Makefile1
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/board.c41
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/boot/nand6
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/boot/sd-ext36
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/config-board9
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/init/automount14
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-1gib.imxcfg2
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-2gib.imxcfg2
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-4gib.imxcfg6
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02.h137
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg2
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl.h125
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02s-512mb.imxcfg2
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/lowlevel.c46
-rw-r--r--arch/arm/boards/sama5d4ek/Makefile1
-rw-r--r--arch/arm/boards/sama5d4ek/env/bin/init_board15
-rw-r--r--arch/arm/boards/sama5d4ek/env/config42
-rw-r--r--arch/arm/boards/sama5d4ek/sama5d4ek.c317
-rw-r--r--arch/arm/configs/am335x_defconfig16
-rw-r--r--arch/arm/configs/am335x_mlo_defconfig1
-rw-r--r--arch/arm/configs/eukrea_cpuimx35_defconfig61
-rw-r--r--arch/arm/configs/globalscale_guruplug_defconfig6
-rw-r--r--arch/arm/configs/globalscale_mirabox_defconfig8
-rw-r--r--arch/arm/configs/imx_v7_defconfig3
-rw-r--r--arch/arm/configs/marvell_armada_xp_gp_defconfig10
-rw-r--r--arch/arm/configs/mvebu_defconfig (renamed from arch/arm/configs/solidrun_cubox_defconfig)115
-rw-r--r--arch/arm/configs/plathome_openblocks_ax3_defconfig9
-rw-r--r--arch/arm/configs/sama5d4ek_defconfig85
-rw-r--r--arch/arm/configs/tqma53_defconfig1
-rw-r--r--arch/arm/configs/tx53stk5_defconfig1
-rw-r--r--arch/arm/dts/Makefile3
-rw-r--r--arch/arm/dts/am335x-afi-gf.dts559
-rw-r--r--arch/arm/dts/am335x-bone-common.dtsi38
-rw-r--r--arch/arm/dts/am335x-phytec-phycore.dts36
-rw-r--r--arch/arm/dts/imx53-voipac-bsb.dts1
-rw-r--r--arch/arm/dts/imx53-voipac-dmm-668.dtsi35
-rw-r--r--arch/arm/dts/imx6dl-phytec-pbab01.dts5
-rw-r--r--arch/arm/dts/imx6dl-phytec-pfla02.dtsi19
-rw-r--r--arch/arm/dts/imx6dl-tx6u-801x.dts65
-rw-r--r--arch/arm/dts/imx6q-gw54xx.dts23
-rw-r--r--arch/arm/dts/imx6q-phytec-pbab01.dts5
-rw-r--r--arch/arm/dts/imx6q-phytec-pcaaxl3.dtsi11
-rw-r--r--arch/arm/dts/imx6q-phytec-pfla02.dtsi19
-rw-r--r--arch/arm/dts/imx6qdl-gw54xx.dtsi38
-rw-r--r--arch/arm/dts/imx6qdl-phytec-pbab01.dtsi13
-rw-r--r--arch/arm/dts/imx6qdl-phytec-pfla02.dtsi79
-rw-r--r--arch/arm/dts/imx6s-phytec-pfla02.dtsi4
-rw-r--r--arch/arm/dts/socfpga.dtsi6
-rw-r--r--arch/arm/mach-at91/Kconfig26
-rw-r--r--arch/arm/mach-at91/Makefile2
-rw-r--r--arch/arm/mach-at91/at91sam9g45.c13
-rw-r--r--arch/arm/mach-at91/clock.c72
-rw-r--r--arch/arm/mach-at91/clock.h2
-rw-r--r--arch/arm/mach-at91/include/mach/at91_pmc.h1
-rw-r--r--arch/arm/mach-at91/include/mach/at91rm9200.h1
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9260.h2
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9261.h1
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9263.h2
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9g45.h2
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9n12.h1
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9x5.h1
-rw-r--r--arch/arm/mach-at91/include/mach/cpu.h30
-rw-r--r--arch/arm/mach-at91/include/mach/hardware.h6
-rw-r--r--arch/arm/mach-at91/include/mach/sama5d3.h2
-rw-r--r--arch/arm/mach-at91/include/mach/sama5d4.h134
-rw-r--r--arch/arm/mach-at91/sam9_smc.c24
-rw-r--r--arch/arm/mach-at91/sama5d4.c304
-rw-r--r--arch/arm/mach-at91/sama5d4_devices.c495
-rw-r--r--arch/arm/mach-at91/setup.c43
-rw-r--r--arch/arm/mach-at91/soc.h7
-rw-r--r--arch/arm/mach-imx/Kconfig7
-rw-r--r--arch/arm/mach-imx/include/mach/imx35-regs.h1
-rw-r--r--arch/arm/mach-imx/include/mach/imx6-ddr-regs.h6
-rw-r--r--arch/arm/mach-imx/include/mach/imx6dl-ddr-regs.h20
-rw-r--r--arch/arm/mach-mvebu/Kconfig40
-rw-r--r--arch/arm/mach-mvebu/armada-370-xp.c28
-rw-r--r--arch/arm/mach-mvebu/common.c45
-rw-r--r--arch/arm/mach-mvebu/dove.c33
-rw-r--r--arch/arm/mach-mvebu/include/mach/common.h3
-rw-r--r--arch/arm/mach-mvebu/kirkwood.c28
-rw-r--r--arch/arm/mach-omap/Kconfig18
-rw-r--r--arch/arm/mach-omap/Makefile2
-rw-r--r--arch/arm/mach-omap/am33xx_bbu_nand.c (renamed from arch/arm/mach-omap/am33xx_bbu_nand_xloadslots.c)47
-rw-r--r--arch/arm/mach-omap/am33xx_bbu_spi_mlo.c22
-rw-r--r--arch/arm/mach-omap/am33xx_clock.c15
-rw-r--r--arch/arm/mach-omap/am33xx_generic.c2
-rw-r--r--arch/arm/mach-omap/include/mach/am33xx-clock.h3
-rw-r--r--arch/arm/mach-omap/include/mach/am33xx-generic.h1
-rw-r--r--arch/arm/mach-omap/include/mach/am33xx-silicon.h4
-rw-r--r--arch/arm/mach-omap/include/mach/bbu.h8
-rw-r--r--arch/arm/mach-socfpga/Makefile1
-rw-r--r--arch/arm/mach-socfpga/include/mach/socfpga-regs.h2
-rw-r--r--arch/arm/mach-tegra/Kconfig3
-rw-r--r--arch/blackfin/boards/ipe337/.gitignore1
-rw-r--r--arch/efi/Makefile2
-rw-r--r--arch/mips/Kconfig1
-rw-r--r--arch/mips/Makefile1
-rw-r--r--arch/mips/boards/img-ci20/Makefile1
-rw-r--r--arch/mips/boards/img-ci20/board.c27
-rw-r--r--arch/mips/boards/img-ci20/include/board/board_pbl_start.h43
-rw-r--r--arch/mips/boards/img-ci20/include/board/debug_ll.h23
-rw-r--r--arch/mips/configs/img-ci20_defconfig42
-rw-r--r--arch/mips/configs/ritmix-rzx50_defconfig3
-rw-r--r--arch/mips/dts/ar9331.dtsi10
-rw-r--r--arch/mips/dts/dlink-dir-320.dts4
-rw-r--r--arch/mips/dts/img-ci20.dts35
-rw-r--r--arch/mips/dts/jz4755.dtsi30
-rw-r--r--arch/mips/dts/jz4780.dtsi56
-rw-r--r--arch/mips/dts/ls1b.dtsi16
-rw-r--r--arch/mips/dts/qemu-malta.dts14
-rw-r--r--arch/mips/include/asm/cpu.h1
-rw-r--r--arch/mips/lib/cpu-probe.c1
-rw-r--r--arch/mips/mach-xburst/Kconfig32
-rw-r--r--arch/mips/mach-xburst/include/mach/debug_ll_jz4750d.h6
-rw-r--r--arch/mips/mach-xburst/include/mach/debug_ll_jz4780.h51
-rw-r--r--arch/mips/mach-xburst/include/mach/jz4780.h30
-rw-r--r--arch/openrisc/Kconfig9
-rw-r--r--arch/openrisc/Makefile7
-rw-r--r--arch/openrisc/boards/generic/config.h9
-rw-r--r--arch/openrisc/boards/generic/generic.c24
-rw-r--r--arch/openrisc/configs/generic_defconfig35
-rw-r--r--arch/openrisc/cpu/barebox.lds.S2
-rw-r--r--arch/openrisc/dts/Makefile5
-rw-r--r--arch/openrisc/dts/or1ksim.dts51
-rw-r--r--arch/openrisc/lib/Makefile1
-rw-r--r--arch/openrisc/lib/dtb.c44
-rw-r--r--arch/ppc/mach-mpc85xx/.gitignore1
-rw-r--r--commands/Kconfig31
-rw-r--r--commands/Makefile3
-rw-r--r--commands/dmesg.c100
-rw-r--r--commands/firmwareload.c66
-rw-r--r--commands/of_display_timings.c164
-rw-r--r--commands/usb.c3
-rw-r--r--common/Kconfig6
-rw-r--r--common/Makefile1
-rw-r--r--common/clock.c11
-rw-r--r--common/console_common.c129
-rw-r--r--common/firmware.c211
-rw-r--r--common/version.c4
-rw-r--r--drivers/Kconfig1
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/base/driver.c22
-rw-r--r--drivers/bus/mvebu-mbus.c6
-rw-r--r--drivers/firmware/Kconfig14
-rw-r--r--drivers/firmware/Makefile2
-rw-r--r--drivers/firmware/altera_serial.c315
-rw-r--r--drivers/firmware/socfpga.c440
-rw-r--r--drivers/i2c/busses/i2c-at91.c98
-rw-r--r--drivers/i2c/busses/i2c-omap.c20
-rw-r--r--drivers/input/imx_keypad.c2
-rw-r--r--drivers/mci/atmel_mci.c1
-rw-r--r--drivers/mtd/devices/Kconfig5
-rw-r--r--drivers/mtd/devices/Makefile1
-rw-r--r--drivers/mtd/devices/mtdram.c122
-rw-r--r--drivers/mtd/nand/Kconfig2
-rw-r--r--drivers/mtd/nand/atmel_nand.c121
-rw-r--r--drivers/mtd/nor/cfi_flash.c4
-rw-r--r--drivers/net/ethoc.c6
-rw-r--r--drivers/net/macb.c6
-rw-r--r--drivers/net/phy/marvell.c17
-rw-r--r--drivers/net/phy/micrel.c4
-rw-r--r--drivers/net/phy/phy.c142
-rw-r--r--drivers/net/usb/asix.c123
-rw-r--r--drivers/of/Kconfig2
-rw-r--r--drivers/of/base.c77
-rw-r--r--drivers/of/fdt.c2
-rw-r--r--drivers/pinctrl/Kconfig24
-rw-r--r--drivers/pinctrl/mvebu/Kconfig8
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c3
-rw-r--r--drivers/pinctrl/pinctrl.c6
-rw-r--r--drivers/usb/Kconfig2
-rw-r--r--drivers/usb/Makefile1
-rw-r--r--drivers/usb/core/of.c1
-rw-r--r--drivers/usb/gadget/Kconfig12
-rw-r--r--drivers/usb/gadget/at91_udc.c23
-rw-r--r--drivers/usb/gadget/dfu.c1
-rw-r--r--drivers/usb/gadget/f_fastboot.c1
-rw-r--r--drivers/usb/gadget/fsl_udc.c44
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c27
-rw-r--r--drivers/usb/gadget/udc-core.c34
-rw-r--r--drivers/usb/imx/chipidea-imx.c1
-rw-r--r--drivers/usb/musb/Kconfig29
-rw-r--r--drivers/usb/musb/Makefile11
-rw-r--r--drivers/usb/musb/am35x-phy-control.h21
-rw-r--r--drivers/usb/musb/musb_am335x.c29
-rw-r--r--drivers/usb/musb/musb_barebox.c146
-rw-r--r--drivers/usb/musb/musb_core.c1156
-rw-r--r--drivers/usb/musb/musb_core.h585
-rw-r--r--drivers/usb/musb/musb_dma.h194
-rw-r--r--drivers/usb/musb/musb_dsps.c464
-rw-r--r--drivers/usb/musb/musb_gadget.c1308
-rw-r--r--drivers/usb/musb/musb_gadget.h147
-rw-r--r--drivers/usb/musb/musb_gadget_ep0.c1079
-rw-r--r--drivers/usb/musb/musb_host.c1749
-rw-r--r--drivers/usb/musb/musb_host.h258
-rw-r--r--drivers/usb/musb/musb_io.h122
-rw-r--r--drivers/usb/musb/musb_regs.h652
-rw-r--r--drivers/usb/musb/phy-am335x-control.c168
-rw-r--r--drivers/usb/musb/phy-am335x.c86
-rw-r--r--drivers/usb/musb/phy-am335x.h6
-rw-r--r--dts/Bindings/dma/rcar-audmapp.txt6
-rw-r--r--dts/Bindings/input/atmel,maxtouch.txt11
-rw-r--r--dts/Bindings/mfd/tc3589x.txt107
-rw-r--r--dts/Bindings/mtd/gpmc-nand.txt2
-rw-r--r--dts/Bindings/net/stmmac.txt4
-rw-r--r--dts/Bindings/pinctrl/qcom,apq8064-pinctrl.txt2
-rw-r--r--dts/Bindings/regulator/tps65090.txt4
-rw-r--r--dts/Bindings/sound/adi,axi-spdif-tx.txt2
-rw-r--r--dts/Bindings/usb/mxs-phy.txt1
-rw-r--r--dts/Bindings/video/analog-tv-connector.txt4
-rw-r--r--dts/src/arm/am4372.dtsi4
-rw-r--r--dts/src/arm/am437x-gp-evm.dts6
-rw-r--r--dts/src/arm/am43x-epos-evm.dts9
-rw-r--r--dts/src/arm/at91rm9200.dtsi2
-rw-r--r--dts/src/arm/at91sam9g20.dtsi1
-rw-r--r--dts/src/arm/dra7-evm.dts47
-rw-r--r--dts/src/arm/dra7.dtsi16
-rw-r--r--dts/src/arm/imx53-qsrb.dts8
-rw-r--r--dts/src/arm/imx6dl-hummingboard.dts4
-rw-r--r--dts/src/arm/imx6qdl-cubox-i.dtsi19
-rw-r--r--dts/src/arm/imx6qdl-microsom-ar8035.dtsi2
-rw-r--r--dts/src/arm/omap3-beagle.dts1
-rw-r--r--dts/src/arm/omap3-n900.dts4
-rw-r--r--dts/src/arm/omap3430-sdp.dts2
-rw-r--r--dts/src/arm/omap3xxx-clocks.dtsi1
-rw-r--r--dts/src/arm/omap54xx-clocks.dtsi16
-rw-r--r--dts/src/arm/ste-snowball.dts1
-rw-r--r--dts/src/arm/twl6030.dtsi4
-rw-r--r--dts/src/xtensa/kc705.dts5
-rw-r--r--images/Makefile.am33xx30
-rw-r--r--images/Makefile.imx10
-rw-r--r--include/clock.h2
-rw-r--r--include/common.h6
-rw-r--r--include/firmware.h42
-rw-r--r--include/linux/barebox-wrapper.h7
-rw-r--r--include/linux/marvell_phy.h34
-rw-r--r--include/linux/mbus.h3
-rw-r--r--include/linux/phy.h4
-rw-r--r--include/of.h23
-rw-r--r--include/printk.h17
-rw-r--r--include/usb/gadget.h1
-rw-r--r--include/usb/musb.h152
-rw-r--r--include/usb/phy.h220
-rw-r--r--include/usb/usb.h9
-rw-r--r--lib/libfile.c4
-rw-r--r--net/eth.c2
-rw-r--r--scripts/.gitignore5
-rw-r--r--scripts/Makefile2
-rwxr-xr-xscripts/checkpatch.pl10
-rw-r--r--scripts/imx/imx-image.c57
-rw-r--r--scripts/imx/imx-usb-loader.c6
-rw-r--r--scripts/mk-omap-image.c (renamed from scripts/mk-am3xxx-spi-image.c)76
298 files changed, 16370 insertions, 1120 deletions
diff --git a/Documentation/boards/am335x.rst b/Documentation/boards/am335x.rst
new file mode 100644
index 0000000000..7959b84c8d
--- /dev/null
+++ b/Documentation/boards/am335x.rst
@@ -0,0 +1,42 @@
+Texas Instruments AM335x
+========================
+
+The Texas Instruments AM335x SoCs have a two-stage boot process. The first stage
+loader, also known as MLO is loaded by the ROM code. The MLO loads the second stage
+loader from the same medium.
+
+Building barebox
+----------------
+
+The TI AM335x boards in barebox are covered by the ``am335x_mlo_defconfig``
+for the MLO and ``am335x_defconfig`` for the regular barebox image. The
+resulting images will be placed under ``images/``:
+
+::
+ barebox-am33xx-afi-gf.img
+ barebox-am33xx-afi-gf-mlo.img
+ barebox-am33xx-beaglebone.img
+ barebox-am33xx-beaglebone-mlo.img
+ barebox-am33xx-phytec-phycore.img
+ barebox-am33xx-phytec-phycore-mlo-1x128m16.img
+ barebox-am33xx-phytec-phycore-mlo-1x256m16.img
+ barebox-am33xx-phytec-phycore-mlo-1x512m16.img
+
+Some boards come in different variants, make sure to pick the correct one.
+
+Starting and updating barebox
+-----------------------------
+
+SPI NOR and NAND
+^^^^^^^^^^^^^^^^
+
+The regular board images can be started from another bootloader, see
+:ref:`second_stage`. The board should provide update handlers
+to update (or initially install) barebox on SPI NOR or NAND, see :ref:`update`.
+
+SD/MMC
+^^^^^^
+
+To start barebox from SD/MMC prepare a card with a FAT filesystem. Copy the MLO
+file for your board to the card and name it ``MLO``. Copy the regular image
+for your board to the card and name it ``barebox.bin``.
diff --git a/Documentation/boards/imx/Karo-TX6 b/Documentation/boards/imx/Karo-TX6
new file mode 100644
index 0000000000..8dd26b5964
--- /dev/null
+++ b/Documentation/boards/imx/Karo-TX6
@@ -0,0 +1,13 @@
+KaRo TX6x
+=========
+
+This CPU cards are based on a Freescale i.MX6 SoC.
+There are currently six variants of this module, that are distinguished
+by the suffix: 'Q' use an i.MX6Q and 'U' an i.MX6DL.
+
+The TX6U-801x modules are shipped with:
+
+ * 128MiB NAND flash
+ * 1024MiB DDR3 SDRAM
+
+see http://www.karo-electronics.de/tx6.html for more information
diff --git a/Documentation/boards/mips/img-ci20.rst b/Documentation/boards/mips/img-ci20.rst
new file mode 100644
index 0000000000..8f5cd80afa
--- /dev/null
+++ b/Documentation/boards/mips/img-ci20.rst
@@ -0,0 +1,42 @@
+MIPS Creator CI20
+=================
+
+The MIPS Creator CI20 board is a high performance, fully featured
+Linux and Android development platform.
+
+Major hardware features include:
+
+ * Ingenic JZ4780 SoC (dual 1.2GHz MIPS32 processor);
+ * 1 GiB DDR3 memory;
+ * 8 GiB NAND Flash;
+ * 2 x UART;
+ * Davicom dm9000 10/100 Ethernet controller;
+ * 2 x USB (host and OTG);
+ * HDMI output;
+ * 14-pin ETAG connector;
+ * GPIO, SPI, I2C, ADC, expansion headers.
+
+
+The board uses U-Boot 2013.10 as bootloader.
+
+
+Running barebox
+---------------
+
+ 1. Boot the board with UART0 serial console. Stop the auto boot during U-boot.
+
+ 2. Upload ``zbarebox.bin`` via Ymodem to the board and then run:
+
+.. code-block:: none
+
+ ci20# loady 0xa8000000
+ ...
+ ci20# go 0xa8000000
+..
+
+
+Links
+-----
+
+ * http://store.imgtec.com/product/mips-creator-ci20
+ * http://elinux.org/MIPS_Creator_CI20
diff --git a/Documentation/boards/omap.rst b/Documentation/boards/omap.rst
index 5038613335..c2697510c5 100644
--- a/Documentation/boards/omap.rst
+++ b/Documentation/boards/omap.rst
@@ -1,5 +1,5 @@
-Texas Instruments OMAP/AM335x
-=============================
+Texas Instruments OMAP
+======================
Texas Instruments OMAP SoCs have a two-stage boot process. The first stage is
known as Xload which only loads the second stage bootloader. barebox can act as
diff --git a/Documentation/boards/openrisc.rst b/Documentation/boards/openrisc.rst
new file mode 100644
index 0000000000..cc00a5d8ea
--- /dev/null
+++ b/Documentation/boards/openrisc.rst
@@ -0,0 +1,51 @@
+OpenRISC
+========
+
+or1ksim
+-------
+
+Compile or1ksim emulator::
+
+ $ cd ~/
+ $ git clone https://github.com/openrisc/or1ksim
+ $ cd or1ksim
+ $ ./configure
+ $ make
+
+Create minimal or1ksim.cfg file::
+
+ section cpu
+ ver = 0x12
+ cfgr = 0x20
+ rev = 0x0001
+ end
+
+ section memory
+ name = "RAM"
+ type = unknown
+ baseaddr = 0x00000000
+ size = 0x02000000
+ delayr = 1
+ delayw = 2
+ end
+
+ section uart
+ enabled = 1
+ baseaddr = 0x90000000
+ irq = 2
+ 16550 = 1
+ /* channel = "tcp:10084" */
+ channel = "xterm:"
+ end
+
+ section ethernet
+ enabled = 1
+ baseaddr = 0x92000000
+ irq = 4
+ rtx_type = "tap"
+ tap_dev = "tap0"
+ end
+
+Run or1ksim::
+
+ $ ~/or1ksim/sim -f or1ksim.cfg barebox
diff --git a/Documentation/devicetree/bindings/firmware/altr,passive-serial.txt b/Documentation/devicetree/bindings/firmware/altr,passive-serial.txt
new file mode 100644
index 0000000000..d357dd39cf
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/altr,passive-serial.txt
@@ -0,0 +1,24 @@
+Altera FPGAs in passive serial mode
+-----------------------------------
+
+This binding defines the control interface to Altera FPGAs in
+passive serial mode. This is used to upload the firmware and
+to start the FPGA.
+
+Required properties:
+- compatible: shall be "altr,fpga-passive-serial"
+- reg: SPI chip select
+- nstat-gpios: Specify GPIO for controlling the nstat pin
+- confd-gpios: Specify GPIO for controlling the confd pin
+- nconfig-gpios: Specify GPIO for controlling the nconfig pin
+
+Example:
+
+ fpga@0 {
+ compatible = "altr,fpga-passive-serial";
+ nstat-gpios = <&gpio4 18 0>;
+ confd-gpios = <&gpio4 19 0>;
+ nconfig-gpios = <&gpio4 20 0>;
+ spi-max-frequency = <10000000>;
+ reg = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.txt b/Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.txt
new file mode 100644
index 0000000000..70ec4abf25
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.txt
@@ -0,0 +1,19 @@
+Altera SOCFPGA FPGA Manager
+---------------------------
+
+This binding defines the FPGA Manager on Altera SOCFPGAs. This is used to upload
+the firmware to the FPGA part of the SoC.
+
+Required properties:
+- compatible: shall be "altr,socfpga-fpga-mgr"
+- reg: Must contain 2 register ranges:
+ 1. The control address space of the FPGA manager.
+ 2. The configuration data address space where the firmware data is written to.
+
+Example:
+
+ fpgamgr@ff706000 {
+ compatible = "altr,socfpga-fpga-mgr";
+ reg = <0xff706000 0x1000>,
+ <0xffb90000 0x1000>;
+ };
diff --git a/Documentation/user/barebox.rst b/Documentation/user/barebox.rst
index caf544de9f..00ceabb925 100644
--- a/Documentation/user/barebox.rst
+++ b/Documentation/user/barebox.rst
@@ -171,6 +171,8 @@ the compilation process will finish with a list of images built under ``images/`
barebox-guf-santaro.img
barebox-gk802.img
+.. _second_stage:
+
Starting barebox
-----------------
diff --git a/Documentation/user/usb.rst b/Documentation/user/usb.rst
index 7cdd6ac814..88be620536 100644
--- a/Documentation/user/usb.rst
+++ b/Documentation/user/usb.rst
@@ -143,3 +143,24 @@ USB CDC ACM compliant serial device.
Unlike the :ref:`command_dfu` command the ``usbgadget`` command returns immediately
after creating the gadget. The gadget can be removed with ``usbgadget -d``.
+
+USB OTG support
+---------------
+
+barebox does not have USB OTG support. However, barebox supports some USB cores in
+both host and device mode. If these are specified for otg in the device tree
+(dr_mode = "otg";) barebox registers a OTG device which can be used to decide which
+mode shall be used. The device has a ``mode`` parameter which by default has the
+value ``otg``. setting this to ``host`` or ``device`` puts the device in the corresponding
+mode. Once a specific mode has been selected it can't be changed later anymore.
+
+.. code-block:: sh
+ barebox:/ devinfo otg0
+ Parameters:
+ mode: otg ("otg", "host", "peripheral")
+ barebox:/ otg0.mode=host
+ musb-hdrc: ConfigData=0xde (UTMI-8, dyn FIFOs, bulk combine, bulk split, HB-ISO Rx, HB-ISO Tx, SoftConn)
+ musb-hdrc: MHDRC RTL version 2.0
+ musb-hdrc: setup fifo_mode 4
+ musb-hdrc: 28/31 max ep, 16384/16384 memory
+ barebox:/
diff --git a/Makefile b/Makefile
index b059c3a00e..d959f57422 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
VERSION = 2014
-PATCHLEVEL = 09
+PATCHLEVEL = 10
SUBLEVEL = 0
EXTRAVERSION =
NAME = None
@@ -300,6 +300,7 @@ LINUXINCLUDE := -Iinclude -I$(srctree)/dts/include \
CPPFLAGS := -D__KERNEL__ -D__BAREBOX__ $(LINUXINCLUDE) -fno-builtin -ffreestanding
CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
+ -Werror-implicit-function-declaration \
-fno-strict-aliasing -fno-common -Os -pipe
AFLAGS := -D__ASSEMBLY__
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 13f0bd41be..3c9b81ab06 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -109,6 +109,7 @@ config ARCH_MVEBU
select MVEBU_MBUS
select OFTREE
select OF_ADDRESS_PCI
+ select PINCTRL
config ARCH_MXS
bool "Freescale i.MX23/28 (mxs) based"
@@ -208,6 +209,7 @@ config ARCH_TEGRA
select OFTREE
select RELOCATABLE
select RESET_CONTROLLER
+ select PINCTRL
config ARCH_UEMD
bool "RC Module UEMD Platform"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 337aef175b..cf81c9c083 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -163,7 +163,7 @@ KBUILD_IMAGE := barebox.ubl
endif
quiet_cmd_am35xx_spi_image = SPI-IMG $@
- cmd_am35xx_spi_image = scripts/mk-am3xxx-spi-image -s am35xx -a $(TEXT_BASE) $< > $@
+ cmd_am35xx_spi_image = scripts/mk-omap-image -s -a $(TEXT_BASE) $< > $@
barebox.spi: $(KBUILD_BINARY) FORCE
$(call if_changed,am35xx_spi_image)
diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index 122f5cde5e..c80b9c920a 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -1,4 +1,5 @@
# keep sorted by CONFIG_* macro name.
+obj-$(CONFIG_MACH_AFI_GF) += afi-gf/
obj-$(CONFIG_MACH_ANIMEO_IP) += animeo_ip/
obj-$(CONFIG_MACH_ARCHOSG9) += archosg9/
obj-$(CONFIG_MACH_AT91SAM9260EK) += at91sam9260ek/
@@ -48,6 +49,7 @@ obj-$(CONFIG_MACH_GLOBALSCALE_MIRABOX) += globalscale-mirabox/
obj-$(CONFIG_MACH_GUF_CUPID) += guf-cupid/
obj-$(CONFIG_MACH_GUF_SANTARO) += guf-santaro/
obj-$(CONFIG_MACH_GUF_VINCELL) += guf-vincell/
+obj-$(CONFIG_MACH_GW_VENTANA) += gateworks-ventana/
obj-$(CONFIG_MACH_HIGHBANK) += highbank/
obj-$(CONFIG_MACH_IMX21ADS) += freescale-mx21-ads/
obj-$(CONFIG_MACH_IMX233_OLINUXINO) += imx233-olinuxino/
@@ -92,6 +94,7 @@ obj-$(CONFIG_MACH_SABRELITE) += freescale-mx6-sabrelite/
obj-$(CONFIG_MACH_SABRESD) += freescale-mx6-sabresd/
obj-$(CONFIG_MACH_SAMA5D3XEK) += sama5d3xek/
obj-$(CONFIG_MACH_SAMA5D3_XPLAINED) += sama5d3_xplained/
+obj-$(CONFIG_MACH_SAMA5D4EK) += sama5d4ek/
obj-$(CONFIG_MACH_SCB9328) += scb9328/
obj-$(CONFIG_MACH_SOCFPGA_EBV_SOCRATES) += ebv-socrates/
obj-$(CONFIG_MACH_SOCFPGA_TERASIC_SOCKIT) += terasic-sockit/
@@ -108,6 +111,7 @@ obj-$(CONFIG_MACH_TX25) += karo-tx25/
obj-$(CONFIG_MACH_TX28) += karo-tx28/
obj-$(CONFIG_MACH_TX51) += karo-tx51/
obj-$(CONFIG_MACH_TX53) += karo-tx53/
+obj-$(CONFIG_MACH_TX6X) += karo-tx6x/
obj-$(CONFIG_MACH_UDOO) += udoo/
obj-$(CONFIG_MACH_USB_A9260) += usb-a926x/
obj-$(CONFIG_MACH_USB_A9263) += usb-a926x/
diff --git a/arch/arm/boards/afi-gf/Makefile b/arch/arm/boards/afi-gf/Makefile
new file mode 100644
index 0000000000..399a4b8cc0
--- /dev/null
+++ b/arch/arm/boards/afi-gf/Makefile
@@ -0,0 +1,3 @@
+lwl-y += lowlevel.o
+obj-y += board.o
+bbenv-y += defaultenv-gf
diff --git a/arch/arm/boards/afi-gf/board.c b/arch/arm/boards/afi-gf/board.c
new file mode 100644
index 0000000000..dfcb579f24
--- /dev/null
+++ b/arch/arm/boards/afi-gf/board.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Jan Luebbe <j.luebbe@pengutronix.de>
+ *
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <string.h>
+#include <init.h>
+#include <sizes.h>
+#include <envfs.h>
+#include <bootsource.h>
+#include <asm/armlinux.h>
+#include <mach/bbu.h>
+#include <mach/am33xx-generic.h>
+
+static int board_console_init(void)
+{
+ if (!of_machine_is_compatible("afi,gf"))
+ return 0;
+
+ switch (bootsource_get()) {
+ default:
+ case BOOTSOURCE_SPI:
+ of_device_enable_path("/chosen/environment-spi");
+ break;
+ case BOOTSOURCE_MMC:
+ omap_set_bootmmc_devname("mmc0");
+ break;
+ }
+
+ defaultenv_append_directory(defaultenv_gf);
+ am33xx_register_ethaddr(0, 0);
+ am33xx_register_ethaddr(1, 1);
+ barebox_set_hostname("gf");
+ am33xx_bbu_spi_nor_mlo_register_handler("MLO.spi", "/dev/m25p0.mlo");
+ am33xx_bbu_spi_nor_register_handler("spi", "/dev/m25p0.boot");
+
+ return 0;
+}
+coredevice_initcall(board_console_init);
diff --git a/arch/arm/boards/afi-gf/config.h b/arch/arm/boards/afi-gf/config.h
new file mode 100644
index 0000000000..aeeda3695b
--- /dev/null
+++ b/arch/arm/boards/afi-gf/config.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 Jan Luebbe <j.luebbe@pengutronix.de>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#endif /* __CONFIG_H */
diff --git a/arch/arm/boards/afi-gf/defaultenv-gf/boot/sd b/arch/arm/boards/afi-gf/defaultenv-gf/boot/sd
new file mode 100644
index 0000000000..dce060542a
--- /dev/null
+++ b/arch/arm/boards/afi-gf/defaultenv-gf/boot/sd
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+if [ "$1" = menu ]; then
+ boot-menu-add-entry "$0" "kernel & rootfs on SD card"
+ exit
+fi
+
+global.bootm.image=/boot/uImage
+global.bootm.oftree=/boot/oftree
+#global.bootm.initrd=<path to initrd>
+global.linux.bootargs.dyn.root="root=/dev/mmcblk0p2 rootfstype=ext4 rootwait"
diff --git a/arch/arm/boards/afi-gf/defaultenv-gf/init/automount b/arch/arm/boards/afi-gf/defaultenv-gf/init/automount
new file mode 100644
index 0000000000..c67bd1ba50
--- /dev/null
+++ b/arch/arm/boards/afi-gf/defaultenv-gf/init/automount
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+if [ "$1" = menu ]; then
+ init-menu-add-entry "$0" "Automountpoints"
+ exit
+fi
+
+# automount tftp server based on $eth1.serverip
+
+mkdir -p /mnt/tftp
+automount /mnt/tftp 'ifup eth1 && mount -t tftp $eth1.serverip /mnt/tftp'
+
+# eth0 is on the mezzanine board
+mkdir -p /mnt/tftp-eth0
+automount /mnt/tftp-eth0 'ifup eth0 && mount -t tftp $eth0.serverip /mnt/tftp'
diff --git a/arch/arm/boards/afi-gf/defaultenv-gf/network/eth1 b/arch/arm/boards/afi-gf/defaultenv-gf/network/eth1
new file mode 100644
index 0000000000..1ed3017e96
--- /dev/null
+++ b/arch/arm/boards/afi-gf/defaultenv-gf/network/eth1
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# ip setting (static/dhcp)
+ip=dhcp
+global.dhcp.vendor_id=barebox-${global.hostname}
+
+# static setup used if ip=static
+ipaddr=
+netmask=
+gateway=
+serverip=
+
+# MAC address if needed
+#ethaddr=xx:xx:xx:xx:xx:xx
+
+# put code to discover eth1 (i.e. 'usb') to /env/network/eth0-discover
+
+exit 0
diff --git a/arch/arm/boards/afi-gf/lowlevel.c b/arch/arm/boards/afi-gf/lowlevel.c
new file mode 100644
index 0000000000..fdc340c057
--- /dev/null
+++ b/arch/arm/boards/afi-gf/lowlevel.c
@@ -0,0 +1,266 @@
+#include <init.h>
+#include <sizes.h>
+#include <io.h>
+#include <asm/armlinux.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+#include <linux/bitops.h>
+#include <mach/am33xx-generic.h>
+#include <mach/am33xx-silicon.h>
+#include <mach/am33xx-clock.h>
+#include <mach/sdrc.h>
+#include <mach/sys_info.h>
+#include <mach/syslib.h>
+#include <mach/am33xx-mux.h>
+#include <mach/wdt.h>
+#include <debug_ll.h>
+
+/* AM335X EMIF Register values */
+#define VTP_CTRL_READY (0x1 << 5)
+#define VTP_CTRL_ENABLE (0x1 << 6)
+#define VTP_CTRL_LOCK_EN (0x1 << 4)
+#define VTP_CTRL_START_EN (0x1)
+#define DDR2_RATIO 0x80 /* for mDDR */ //
+#define CMD_FORCE 0x00 /* common #def */
+#define CMD_DELAY 0x00
+
+#define EMIF_READ_LATENCY 0x05 // (CL + 2 - 1)
+#define EMIF_TIM1 0x04447289 //
+#define EMIF_TIM2 0x10160580 //
+#define EMIF_TIM3 0x000000E7 // check tREFI
+#define EMIF_SDCFG 0x0 \
+ | (1 << 29) /* reg_sdram_type = 1 (LPDDR1) */ \
+ | (0 << 27) /* reg_ibank_pos = 0 */ \
+ | (0 << 24) /* reg_ddr_term = 0? */ \
+ | (0 << 23) /* reg_ddr2_ddqs = 0 (single ended DQS for LPDDR) */ \
+ | (0 << 21) /* reg_dyn_odt = 0 (only used for DDR3) */ \
+ | (0 << 20) /* reg_ddr_disable_dll = 0 */ \
+ | (1 << 18) /* reg_sdram_drive = 1? (1/2 for LPDDR) */ \
+ | (0 << 16) /* reg_cwl = 0 (only for DDR3) */ \
+ | (1 << 14) /* reg_narrow_mode = 1 (AM335x is always 16 bit) */ \
+ | (3 << 10) /* reg_cl = 3 */ \
+ | (5 << 7) /* reg_rowsize = 5 (unused?, 14 row bits) */ \
+ | (2 << 4) /* reg_ibank = 2 (4 banks) */ \
+ | (0 << 3) /* reg_ebank = 0 */ \
+ | (3 << 0) /* reg_pagesize = 3? (11 column bits = 2048 words) */
+#define EMIF_SDREF 0x00000618 //
+#define DDR2_DLL_LOCK_DIFF 0x0
+#define DDR2_RD_DQS 0x40 //
+#define DDR2_WR_DQS 0x2 //
+#define DDR2_PHY_WRLVL 0x00
+#define DDR2_PHY_GATELVL 0x00
+#define DDR2_PHY_FIFO_WE 0x110 //
+#define DDR2_PHY_WR_DATA 0x40 //
+
+#define DDR2_INVERT_CLKOUT 0x0 //
+#define PHY_RANK0_DELAY 0x1 //
+#define PHY_DLL_LOCK_DIFF 0x0
+#define DDR_IOCTRL_VALUE 0x18B //
+
+static void board_data_macro_config(int dataMacroNum)
+{
+ u32 BaseAddrOffset = 0x00;
+
+ if (dataMacroNum == 1)
+ BaseAddrOffset = 0xA4;
+
+ __raw_writel(((DDR2_RD_DQS<<30)|(DDR2_RD_DQS<<20)
+ |(DDR2_RD_DQS<<10)|(DDR2_RD_DQS<<0)),
+ (AM33XX_DATA0_RD_DQS_SLAVE_RATIO_0 + BaseAddrOffset));
+ __raw_writel(DDR2_RD_DQS>>2,
+ (AM33XX_DATA0_RD_DQS_SLAVE_RATIO_1 + BaseAddrOffset));
+ __raw_writel(((DDR2_WR_DQS<<30)|(DDR2_WR_DQS<<20)
+ |(DDR2_WR_DQS<<10)|(DDR2_WR_DQS<<0)),
+ (AM33XX_DATA0_WR_DQS_SLAVE_RATIO_0 + BaseAddrOffset));
+ __raw_writel(DDR2_WR_DQS>>2,
+ (AM33XX_DATA0_WR_DQS_SLAVE_RATIO_1 + BaseAddrOffset));
+ __raw_writel(((DDR2_PHY_WRLVL<<30)|(DDR2_PHY_WRLVL<<20)
+ |(DDR2_PHY_WRLVL<<10)|(DDR2_PHY_WRLVL<<0)),
+ (AM33XX_DATA0_WRLVL_INIT_RATIO_0 + BaseAddrOffset));
+ __raw_writel(DDR2_PHY_WRLVL>>2,
+ (AM33XX_DATA0_WRLVL_INIT_RATIO_1 + BaseAddrOffset));
+ __raw_writel(((DDR2_PHY_GATELVL<<30)|(DDR2_PHY_GATELVL<<20)
+ |(DDR2_PHY_GATELVL<<10)|(DDR2_PHY_GATELVL<<0)),
+ (AM33XX_DATA0_GATELVL_INIT_RATIO_0 + BaseAddrOffset));
+ __raw_writel(DDR2_PHY_GATELVL>>2,
+ (AM33XX_DATA0_GATELVL_INIT_RATIO_1 + BaseAddrOffset));
+ __raw_writel(((DDR2_PHY_FIFO_WE<<30)|(DDR2_PHY_FIFO_WE<<20)
+ |(DDR2_PHY_FIFO_WE<<10)|(DDR2_PHY_FIFO_WE<<0)),
+ (AM33XX_DATA0_FIFO_WE_SLAVE_RATIO_0 + BaseAddrOffset));
+ __raw_writel(DDR2_PHY_FIFO_WE>>2,
+ (AM33XX_DATA0_FIFO_WE_SLAVE_RATIO_1 + BaseAddrOffset));
+ __raw_writel(((DDR2_PHY_WR_DATA<<30)|(DDR2_PHY_WR_DATA<<20)
+ |(DDR2_PHY_WR_DATA<<10)|(DDR2_PHY_WR_DATA<<0)),
+ (AM33XX_DATA0_WR_DATA_SLAVE_RATIO_0 + BaseAddrOffset));
+ __raw_writel(DDR2_PHY_WR_DATA>>2,
+ (AM33XX_DATA0_WR_DATA_SLAVE_RATIO_1 + BaseAddrOffset));
+ __raw_writel(PHY_DLL_LOCK_DIFF,
+ (AM33XX_DATA0_DLL_LOCK_DIFF_0 + BaseAddrOffset));
+}
+
+static void board_cmd_macro_config(void)
+{
+ __raw_writel(DDR2_RATIO, AM33XX_CMD0_CTRL_SLAVE_RATIO_0);
+ __raw_writel(CMD_FORCE, AM33XX_CMD0_CTRL_SLAVE_FORCE_0);
+ __raw_writel(CMD_DELAY, AM33XX_CMD0_CTRL_SLAVE_DELAY_0);
+ __raw_writel(DDR2_DLL_LOCK_DIFF, AM33XX_CMD0_DLL_LOCK_DIFF_0);
+ __raw_writel(DDR2_INVERT_CLKOUT, AM33XX_CMD0_INVERT_CLKOUT_0);
+
+ __raw_writel(DDR2_RATIO, AM33XX_CMD1_CTRL_SLAVE_RATIO_0);
+ __raw_writel(CMD_FORCE, AM33XX_CMD1_CTRL_SLAVE_FORCE_0);
+ __raw_writel(CMD_DELAY, AM33XX_CMD1_CTRL_SLAVE_DELAY_0);
+ __raw_writel(DDR2_DLL_LOCK_DIFF, AM33XX_CMD1_DLL_LOCK_DIFF_0);
+ __raw_writel(DDR2_INVERT_CLKOUT, AM33XX_CMD1_INVERT_CLKOUT_0);
+
+ __raw_writel(DDR2_RATIO, AM33XX_CMD2_CTRL_SLAVE_RATIO_0);
+ __raw_writel(CMD_FORCE, AM33XX_CMD2_CTRL_SLAVE_FORCE_0);
+ __raw_writel(CMD_DELAY, AM33XX_CMD2_CTRL_SLAVE_DELAY_0);
+ __raw_writel(DDR2_DLL_LOCK_DIFF, AM33XX_CMD2_DLL_LOCK_DIFF_0);
+ __raw_writel(DDR2_INVERT_CLKOUT, AM33XX_CMD2_INVERT_CLKOUT_0);
+}
+
+static void board_config_vtp(void)
+{
+ __raw_writel(__raw_readl(AM33XX_VTP0_CTRL_REG) | VTP_CTRL_ENABLE,
+ AM33XX_VTP0_CTRL_REG);
+ __raw_writel(__raw_readl(AM33XX_VTP0_CTRL_REG) & (~VTP_CTRL_START_EN),
+ AM33XX_VTP0_CTRL_REG);
+ __raw_writel(__raw_readl(AM33XX_VTP0_CTRL_REG) | VTP_CTRL_START_EN,
+ AM33XX_VTP0_CTRL_REG);
+
+ /* Poll for READY */
+ while ((__raw_readl(AM33XX_VTP0_CTRL_REG) & VTP_CTRL_READY) != VTP_CTRL_READY);
+}
+
+static void board_config_emif_ddr(void)
+{
+ u32 i;
+
+ /*Program EMIF0 CFG Registers*/
+ __raw_writel(EMIF_READ_LATENCY, AM33XX_EMIF4_0_REG(DDR_PHY_CTRL_1));
+ __raw_writel(EMIF_READ_LATENCY, AM33XX_EMIF4_0_REG(DDR_PHY_CTRL_1_SHADOW));
+ __raw_writel(EMIF_READ_LATENCY, AM33XX_EMIF4_0_REG(DDR_PHY_CTRL_2));
+ __raw_writel(EMIF_TIM1, AM33XX_EMIF4_0_REG(SDRAM_TIM_1));
+ __raw_writel(EMIF_TIM1, AM33XX_EMIF4_0_REG(SDRAM_TIM_1_SHADOW));
+ __raw_writel(EMIF_TIM2, AM33XX_EMIF4_0_REG(SDRAM_TIM_2));
+ __raw_writel(EMIF_TIM2, AM33XX_EMIF4_0_REG(SDRAM_TIM_2_SHADOW));
+ __raw_writel(EMIF_TIM3, AM33XX_EMIF4_0_REG(SDRAM_TIM_3));
+ __raw_writel(EMIF_TIM3, AM33XX_EMIF4_0_REG(SDRAM_TIM_3_SHADOW));
+
+ __raw_writel(EMIF_SDCFG, AM33XX_EMIF4_0_REG(SDRAM_CONFIG));
+ __raw_writel(EMIF_SDCFG, AM33XX_EMIF4_0_REG(SDRAM_CONFIG2));
+
+ __raw_writel(0x00004650, AM33XX_EMIF4_0_REG(SDRAM_REF_CTRL));
+ __raw_writel(0x00004650, AM33XX_EMIF4_0_REG(SDRAM_REF_CTRL_SHADOW));
+
+ for (i = 0; i < 5000; i++) {
+
+ }
+
+ __raw_writel(EMIF_SDREF, AM33XX_EMIF4_0_REG(SDRAM_REF_CTRL));
+ __raw_writel(EMIF_SDREF, AM33XX_EMIF4_0_REG(SDRAM_REF_CTRL_SHADOW));
+
+ __raw_writel(EMIF_SDCFG, AM33XX_EMIF4_0_REG(SDRAM_CONFIG));
+ __raw_writel(EMIF_SDCFG, AM33XX_EMIF4_0_REG(SDRAM_CONFIG2));
+}
+
+static void board_config_ddr(void)
+{
+ am33xx_enable_ddr_clocks();
+
+ board_config_vtp();
+
+ board_cmd_macro_config();
+ board_data_macro_config(0);
+ board_data_macro_config(1);
+
+ __raw_writel(PHY_RANK0_DELAY, AM33XX_DATA0_RANK0_DELAYS_0);
+ __raw_writel(PHY_RANK0_DELAY, AM33XX_DATA1_RANK0_DELAYS_0);
+
+ __raw_writel(DDR_IOCTRL_VALUE, AM33XX_DDR_CMD0_IOCTRL);
+ __raw_writel(DDR_IOCTRL_VALUE, AM33XX_DDR_CMD1_IOCTRL);
+ __raw_writel(DDR_IOCTRL_VALUE, AM33XX_DDR_CMD2_IOCTRL);
+ __raw_writel(DDR_IOCTRL_VALUE, AM33XX_DDR_DATA0_IOCTRL);
+ __raw_writel(DDR_IOCTRL_VALUE, AM33XX_DDR_DATA1_IOCTRL);
+
+ __raw_writel(__raw_readl(AM33XX_DDR_IO_CTRL) | BIT(28), AM33XX_DDR_IO_CTRL);
+ __raw_writel(__raw_readl(AM33XX_DDR_CKE_CTRL) | BIT(0), AM33XX_DDR_CKE_CTRL);
+
+ board_config_emif_ddr();
+}
+
+static const struct module_pin_mux board_can_pin_mux[] = {
+ {OFFSET(mii1_txd3), (MODE(1) | PULLUP_EN)}, /* dcan0_tx_mux0 */
+ {OFFSET(mii1_txd2), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* dcan0_rx_mux0 */
+ {OFFSET(mcasp0_aclkr), (MODE(7) | PULLUP_EN)}, /* gpio3[18] / DCAN0_LBK */
+ {-1},
+};
+
+extern char __dtb_am335x_afi_gf_start[];
+
+/**
+ * @brief The basic entry point for board initialization.
+ *
+ * This is called as part of machine init (after arch init).
+ * This is again called with stack in SRAM, so not too many
+ * constructs possible here.
+ *
+ * @return void
+ */
+static noinline int gf_sram_init(void)
+{
+ void *fdt;
+
+ fdt = __dtb_am335x_afi_gf_start;
+
+ /* WDT1 is already running when the bootloader gets control
+ * Disable it to avoid "random" resets
+ */
+ __raw_writel(WDT_DISABLE_CODE1, AM33XX_WDT_REG(WSPR));
+ while(__raw_readl(AM33XX_WDT_REG(WWPS)) != 0x0);
+ __raw_writel(WDT_DISABLE_CODE2, AM33XX_WDT_REG(WSPR));
+ while(__raw_readl(AM33XX_WDT_REG(WWPS)) != 0x0);
+
+ /* Setup the PLLs and the clocks for the peripherals */
+ am33xx_pll_init(MPUPLL_M_500, 24, DDRPLL_M_200);
+
+ board_config_ddr();
+
+ /*
+ * FIXME configure CAN pinmux early to avoid driving the bus
+ * with the low by default pins.
+ */
+ configure_module_pin_mux(board_can_pin_mux);
+
+ am33xx_uart_soft_reset((void *)AM33XX_UART2_BASE);
+ am33xx_enable_uart2_pin_mux();
+ omap_uart_lowlevel_init((void *)AM33XX_UART2_BASE);
+ putc_ll('>');
+
+ barebox_arm_entry(0x80000000, SZ_256M, fdt);
+}
+
+ENTRY_FUNCTION(start_am33xx_afi_gf_sram, bootinfo, r1, r2)
+{
+ am33xx_save_bootinfo((void *)bootinfo);
+
+ /*
+ * Setup C environment, the board init code uses global variables.
+ * Stackpointer has already been initialized by the ROM code.
+ */
+ relocate_to_current_adr();
+ setup_c();
+
+ gf_sram_init();
+}
+
+ENTRY_FUNCTION(start_am33xx_afi_gf_sdram, r0, r1, r2)
+{
+ void *fdt;
+
+ fdt = __dtb_am335x_afi_gf_start - get_runtime_offset();
+
+ putc_ll('>');
+
+ barebox_arm_entry(0x80000000, SZ_256M, fdt);
+}
diff --git a/arch/arm/boards/datamodul-edm-qmx6/board.c b/arch/arm/boards/datamodul-edm-qmx6/board.c
index e388e28168..25f45dfcc0 100644
--- a/arch/arm/boards/datamodul-edm-qmx6/board.c
+++ b/arch/arm/boards/datamodul-edm-qmx6/board.c
@@ -49,6 +49,7 @@
#define RQ7_GPIO_ENET_MODE2 IMX_GPIO_NR(6, 28)
#define RQ7_GPIO_ENET_MODE3 IMX_GPIO_NR(6, 29)
#define RQ7_GPIO_ENET_EN_CLK125 IMX_GPIO_NR(6, 24)
+#define RQ7_GPIO_ENET_RESET IMX_GPIO_NR(1, 25)
static iomux_v3_cfg_t realq7_pads_gpio[] = {
MX6Q_PAD_RGMII_RXC__GPIO_6_30,
@@ -57,6 +58,7 @@ static iomux_v3_cfg_t realq7_pads_gpio[] = {
MX6Q_PAD_RGMII_RD2__GPIO_6_28,
MX6Q_PAD_RGMII_RD3__GPIO_6_29,
MX6Q_PAD_RGMII_RX_CTL__GPIO_6_24,
+ MX6Q_PAD_ENET_CRS_DV__GPIO_1_25,
};
static int ksz9031rn_phy_fixup(struct phy_device *dev)
@@ -85,12 +87,14 @@ static int realq7_enet_init(void)
gpio_direction_output(RQ7_GPIO_ENET_MODE3, 1);
gpio_direction_output(RQ7_GPIO_ENET_EN_CLK125, 1);
- gpio_direction_output(25, 0);
+ gpio_direction_output(RQ7_GPIO_ENET_RESET, 0);
mdelay(50);
- gpio_direction_output(25, 1);
+ gpio_direction_output(RQ7_GPIO_ENET_RESET, 1);
mdelay(50);
+ gpio_free(RQ7_GPIO_ENET_RESET);
+
phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
ksz9031rn_phy_fixup);
diff --git a/arch/arm/boards/gateworks-ventana/Makefile b/arch/arm/boards/gateworks-ventana/Makefile
new file mode 100644
index 0000000000..7d195eebd6
--- /dev/null
+++ b/arch/arm/boards/gateworks-ventana/Makefile
@@ -0,0 +1,2 @@
+obj-y += board.o gsc.o
+lwl-y += lowlevel.o
diff --git a/arch/arm/boards/gateworks-ventana/board.c b/arch/arm/boards/gateworks-ventana/board.c
new file mode 100644
index 0000000000..82dba7c93d
--- /dev/null
+++ b/arch/arm/boards/gateworks-ventana/board.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 Lucas Stach, Pengutronix
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <environment.h>
+#include <i2c/i2c.h>
+#include <init.h>
+#include <linux/marvell_phy.h>
+#include <linux/phy.h>
+#include <mach/bbu.h>
+#include <mach/imx6.h>
+#include <net.h>
+
+#include "gsc.h"
+
+static int gw54xx_devices_init(void)
+{
+ struct i2c_client client;
+ struct device_node *dnode;
+ u8 reg;
+ u8 mac[6];
+
+ if (!of_machine_is_compatible("gw,imx6q-gw54xx"))
+ return 0;
+
+ client.adapter = i2c_get_adapter(0);
+ if (!client.adapter) {
+ pr_err("could not get system controller i2c bus\n");
+ return -ENODEV;
+ }
+
+ /* disable the GSC boot watchdog */
+ client.addr = GSC_SC_ADDR;
+ gsc_i2c_read(&client, GSC_SC_CTRL1, &reg, 1);
+ reg |= GSC_SC_CTRL1_WDDIS;
+ gsc_i2c_write(&client, GSC_SC_CTRL1, &reg, 1);
+
+ /* read MAC adresses from EEPROM and attach to eth devices */
+ dnode = of_find_node_by_alias(of_get_root_node(), "ethernet0");
+ if (dnode) {
+ client.addr = GSC_EEPROM_ADDR;
+ gsc_i2c_read(&client, 0x00, mac, 6);
+ of_eth_register_ethaddr(dnode, mac);
+ }
+ dnode = of_find_node_by_alias(of_get_root_node(), "ethernet1");
+ if (dnode) {
+ client.addr = GSC_EEPROM_ADDR;
+ gsc_i2c_read(&client, 0x06, mac, 6);
+ of_eth_register_ethaddr(dnode, mac);
+ }
+
+ imx6_bbu_nand_register_handler("nand", BBU_HANDLER_FLAG_DEFAULT);
+
+ barebox_set_hostname("gw54xx");
+
+ return 0;
+}
+device_initcall(gw54xx_devices_init);
+
+static int marvell_88e1510_phy_fixup(struct phy_device *dev)
+{
+ u32 val;
+
+ /* LED settings */
+ phy_write(dev, 22, 3);
+ val = phy_read(dev, 16);
+ val &= 0xff00;
+ val |= 0x0017;
+ phy_write(dev, 16, val);
+ phy_write(dev, 22, 0);
+
+ return 0;
+}
+
+static int gw54xx_coredevices_init(void)
+{
+ if (!of_machine_is_compatible("gw,imx6q-gw54xx"))
+ return 0;
+
+ phy_register_fixup_for_uid(MARVELL_PHY_ID_88E1510, MARVELL_PHY_ID_MASK,
+ marvell_88e1510_phy_fixup);
+
+ return 0;
+}
+coredevice_initcall(gw54xx_coredevices_init);
diff --git a/arch/arm/boards/gateworks-ventana/clocks.imxcfg b/arch/arm/boards/gateworks-ventana/clocks.imxcfg
new file mode 100644
index 0000000000..bfd5331f01
--- /dev/null
+++ b/arch/arm/boards/gateworks-ventana/clocks.imxcfg
@@ -0,0 +1,8 @@
+wm 32 MX6_CCM_CCGR0 0x00C03F3F
+wm 32 MX6_CCM_CCGR1 0x0030FC03
+wm 32 MX6_CCM_CCGR2 0x0FFFC000
+wm 32 MX6_CCM_CCGR3 0x3FF00000
+wm 32 MX6_CCM_CCGR4 0xFFFFF300
+wm 32 MX6_CCM_CCGR5 0x0F0000C3
+wm 32 MX6_CCM_CCGR6 0x000003FF
+wm 32 MX6_CCM_CCOSR 0x000000FB
diff --git a/arch/arm/boards/gateworks-ventana/flash-header-ventana-quad-1gx64.imxcfg b/arch/arm/boards/gateworks-ventana/flash-header-ventana-quad-1gx64.imxcfg
new file mode 100644
index 0000000000..75271e477d
--- /dev/null
+++ b/arch/arm/boards/gateworks-ventana/flash-header-ventana-quad-1gx64.imxcfg
@@ -0,0 +1,11 @@
+soc imx6
+loadaddr 0x20000000
+dcdofs 0x400
+
+#include <mach/imx6-ddr-regs.h>
+#include <mach/imx6q-ddr-regs.h>
+#include <mach/imx6-ccm-regs.h>
+
+#include "ram-base.imxcfg"
+#include "quad_128x64.imxcfg"
+#include "clocks.imxcfg"
diff --git a/arch/arm/boards/gateworks-ventana/gsc.c b/arch/arm/boards/gateworks-ventana/gsc.c
new file mode 100644
index 0000000000..3614230482
--- /dev/null
+++ b/arch/arm/boards/gateworks-ventana/gsc.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2013 Gateworks Corporation
+ * Copyright (C) 2014 Lucas Stach, Pengutronix
+ * Author: Tim Harvey <tharvey@gateworks.com>
+ *
+ * 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.
+ */
+
+/*
+ * The Gateworks System Controller will fail to ACK a master transaction if
+ * it is busy, which can occur during its 1HZ timer tick while reading ADC's.
+ * When this does occur, it will never be busy long enough to fail more than
+ * 2 back-to-back transfers. Thus we wrap i2c_read and i2c_write with
+ * 3 retries.
+ */
+
+#include <common.h>
+#include <i2c/i2c.h>
+
+#include "gsc.h"
+
+int gsc_i2c_read(struct i2c_client *client, u32 addr, u8 *buf, u16 count)
+{
+ int retry = 3;
+ int n = 0;
+ int ret;
+
+ while (n++ < retry) {
+ ret = i2c_read_reg(client, addr, buf, count);
+ if (!ret)
+ break;
+ pr_debug("GSC read failed\n");
+ if (ret != -ENODEV)
+ break;
+ mdelay(10);
+ }
+
+ return ret;
+}
+
+int gsc_i2c_write(struct i2c_client *client, u32 addr, const u8 *buf, u16 count)
+{
+ int retry = 3;
+ int n = 0;
+ int ret;
+
+ while (n++ < retry) {
+ ret = i2c_write_reg(client, addr, buf, count);
+ if (!ret)
+ break;
+ pr_debug("GSC write failed\n");
+ if (ret != -ENODEV)
+ break;
+ mdelay(10);
+ }
+ mdelay(100);
+
+ return ret;
+}
diff --git a/arch/arm/boards/gateworks-ventana/gsc.h b/arch/arm/boards/gateworks-ventana/gsc.h
new file mode 100644
index 0000000000..a6e7e2232d
--- /dev/null
+++ b/arch/arm/boards/gateworks-ventana/gsc.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 Gateworks Corporation
+ * Copyright (C) 2014 Lucas Stach, Pengutronix
+ * Author: Tim Harvey <tharvey@gateworks.com>
+ *
+ * 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.
+ */
+
+/* i2c slave addresses */
+#define GSC_SC_ADDR 0x20
+#define GSC_RTC_ADDR 0x68
+#define GSC_HWMON_ADDR 0x29
+#define GSC_EEPROM_ADDR 0x51
+
+/* System Controller registers */
+#define GSC_SC_CTRL0 0x00
+#define GSC_SC_CTRL1 0x01
+#define GSC_SC_CTRL1_WDDIS (1 << 7)
+#define GSC_SC_STATUS 0x0a
+#define GSC_SC_FWVER 0x0e
+
+/* System Controller Interrupt bits */
+#define GSC_SC_IRQ_PB 0 /* Pushbutton switch */
+#define GSC_SC_IRQ_SECURE 1 /* Secure Key erase complete */
+#define GSC_SC_IRQ_EEPROM_WP 2 /* EEPROM write violation */
+#define GSC_SC_IRQ_GPIO 4 /* GPIO change */
+#define GSC_SC_IRQ_TAMPER 5 /* Tamper detect */
+#define GSC_SC_IRQ_WATCHDOG 6 /* Watchdog trip */
+#define GSC_SC_IRQ_PBLONG 7 /* Pushbutton long hold */
+
+/* Hardware Monitor registers */
+#define GSC_HWMON_TEMP 0x00
+#define GSC_HWMON_VIN 0x02
+#define GSC_HWMON_VDD_3P3 0x05
+#define GSC_HWMON_VBATT 0x08
+#define GSC_HWMON_VDD_5P0 0x0b
+#define GSC_HWMON_VDD_CORE 0x0e
+#define GSC_HWMON_VDD_HIGH 0x14
+#define GSC_HWMON_VDD_DDR 0x17
+#define GSC_HWMON_VDD_SOC 0x11
+#define GSC_HWMON_VDD_1P8 0x1d
+#define GSC_HWMON_VDD_2P5 0x23
+#define GSC_HWMON_VDD_1P0 0x20
+
+/*
+ * I2C transactions to the GSC are done via these functions which
+ * perform retries in the case of a busy GSC NAK'ing the transaction
+ */
+int gsc_i2c_read(struct i2c_client *client, u32 addr, u8 *buf, u16 count);
+int gsc_i2c_write(struct i2c_client *client, u32 addr, const u8 *buf, u16 count);
diff --git a/arch/arm/boards/gateworks-ventana/lowlevel.c b/arch/arm/boards/gateworks-ventana/lowlevel.c
new file mode 100644
index 0000000000..10b2c4c780
--- /dev/null
+++ b/arch/arm/boards/gateworks-ventana/lowlevel.c
@@ -0,0 +1,18 @@
+#include <common.h>
+#include <sizes.h>
+#include <mach/generic.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+
+extern char __dtb_imx6q_gw54xx_start[];
+
+ENTRY_FUNCTION(start_imx6q_gw54xx_1gx64, r0, r1, r2)
+{
+ void *fdt;
+
+ imx6_cpu_lowlevel_init();
+
+ fdt = __dtb_imx6q_gw54xx_start - get_runtime_offset();
+
+ barebox_arm_entry(0x10000000, SZ_1G, fdt);
+}
diff --git a/arch/arm/boards/gateworks-ventana/quad_128x64.imxcfg b/arch/arm/boards/gateworks-ventana/quad_128x64.imxcfg
new file mode 100644
index 0000000000..daf01a8ad1
--- /dev/null
+++ b/arch/arm/boards/gateworks-ventana/quad_128x64.imxcfg
@@ -0,0 +1,41 @@
+wm 32 MX6_MMDC_P0_MPWLDECTRL0 0x00190017
+wm 32 MX6_MMDC_P0_MPWLDECTRL1 0x00140026
+wm 32 MX6_MMDC_P1_MPWLDECTRL0 0x0021001C
+wm 32 MX6_MMDC_P1_MPWLDECTRL1 0x0011001D
+
+wm 32 MX6_MMDC_P0_MPDGCTRL0 0x43380347
+wm 32 MX6_MMDC_P0_MPDGCTRL1 0x433C034D
+wm 32 MX6_MMDC_P1_MPDGCTRL0 0x032C0324
+wm 32 MX6_MMDC_P1_MPDGCTRL1 0x03310232
+
+wm 32 MX6_MMDC_P0_MPRDDLCTL 0x3C313539
+wm 32 MX6_MMDC_P1_MPRDDLCTL 0x37343141
+wm 32 MX6_MMDC_P0_MPWRDLCTL 0x36393C39
+wm 32 MX6_MMDC_P1_MPWRDLCTL 0x42344438
+
+wm 32 MX6_MMDC_P0_MPODTCTRL 0x00022227
+wm 32 MX6_MMDC_P1_MPODTCTRL 0x00022227
+
+wm 32 MX6_MMDC_P0_MPMUR0 0x00000800
+wm 32 MX6_MMDC_P1_MPMUR0 0x00000800
+
+wm 32 MX6_MMDC_P0_MDSCR 0x00008000
+wm 32 MX6_MMDC_P0_MDCFG0 0x54597955
+wm 32 MX6_MMDC_P0_MDCFG1 0xFF328F64
+wm 32 MX6_MMDC_P0_MDCFG2 0x01FF00DB
+wm 32 MX6_MMDC_P0_MDOTC 0x09444040
+wm 32 MX6_MMDC_P0_MDASP 0x0000007F
+wm 32 MX6_MMDC_P0_MDMISC 0x00011740
+wm 32 MX6_MMDC_P0_MDOR 0x00591023
+wm 32 MX6_MMDC_P0_MDCTL 0x831A0000
+wm 32 MX6_MMDC_P0_MDSCR 0x02088032
+wm 32 MX6_MMDC_P0_MDSCR 0x00008033
+wm 32 MX6_MMDC_P0_MDSCR 0x00408031
+wm 32 MX6_MMDC_P0_MDSCR 0x09408030
+wm 32 MX6_MMDC_P0_MDSCR 0x04008040
+wm 32 MX6_MMDC_P0_MDPDC 0x00025576
+wm 32 MX6_MMDC_P0_MAPSR 0x00011006
+wm 32 MX6_MMDC_P0_MPZQHWCTRL 0xA1390003
+wm 32 MX6_MMDC_P1_MPZQHWCTRL 0xA1390003
+wm 32 MX6_MMDC_P0_MDREF 0x00007800
+wm 32 MX6_MMDC_P0_MDSCR 0x00000000
diff --git a/arch/arm/boards/gateworks-ventana/ram-base.imxcfg b/arch/arm/boards/gateworks-ventana/ram-base.imxcfg
new file mode 100644
index 0000000000..07dc34c0bb
--- /dev/null
+++ b/arch/arm/boards/gateworks-ventana/ram-base.imxcfg
@@ -0,0 +1,56 @@
+wm 32 MX6_IOM_DRAM_SDQS0 0x00000030
+wm 32 MX6_IOM_DRAM_SDQS1 0x00000030
+wm 32 MX6_IOM_DRAM_SDQS2 0x00000030
+wm 32 MX6_IOM_DRAM_SDQS3 0x00000030
+wm 32 MX6_IOM_DRAM_SDQS4 0x00000030
+wm 32 MX6_IOM_DRAM_SDQS5 0x00000030
+wm 32 MX6_IOM_DRAM_SDQS6 0x00000030
+wm 32 MX6_IOM_DRAM_SDQS7 0x00000030
+
+wm 32 MX6_IOM_DRAM_DQM0 0x00020030
+wm 32 MX6_IOM_DRAM_DQM1 0x00020030
+wm 32 MX6_IOM_DRAM_DQM2 0x00020030
+wm 32 MX6_IOM_DRAM_DQM3 0x00020030
+wm 32 MX6_IOM_DRAM_DQM4 0x00020030
+wm 32 MX6_IOM_DRAM_DQM5 0x00020030
+wm 32 MX6_IOM_DRAM_DQM6 0x00020030
+wm 32 MX6_IOM_DRAM_DQM7 0x00020030
+
+wm 32 MX6_IOM_GRP_B0DS 0x00000030
+wm 32 MX6_IOM_GRP_B1DS 0x00000030
+wm 32 MX6_IOM_GRP_B2DS 0x00000030
+wm 32 MX6_IOM_GRP_B3DS 0x00000030
+wm 32 MX6_IOM_GRP_B4DS 0x00000030
+wm 32 MX6_IOM_GRP_B5DS 0x00000030
+wm 32 MX6_IOM_GRP_B6DS 0x00000030
+wm 32 MX6_IOM_GRP_B7DS 0x00000030
+
+wm 32 MX6_IOM_DRAM_CAS 0x00020030
+wm 32 MX6_IOM_DRAM_RAS 0x00020030
+wm 32 MX6_IOM_DRAM_SDCLK_0 0x00020030
+wm 32 MX6_IOM_DRAM_SDCLK_1 0x00020030
+wm 32 MX6_IOM_DRAM_RESET 0x00020030
+
+wm 32 MX6_IOM_DRAM_SDCKE0 0x00003000
+wm 32 MX6_IOM_DRAM_SDCKE1 0x00003000
+
+wm 32 MX6_IOM_DRAM_SDBA2 0x00000000
+
+wm 32 MX6_IOM_DRAM_SDODT0 0x00003030
+wm 32 MX6_IOM_DRAM_SDODT1 0x00003030
+
+wm 32 MX6_IOM_GRP_DDR_TYPE 0x000C0000
+wm 32 MX6_IOM_DDRMODE_CTL 0x00020000
+wm 32 MX6_IOM_GRP_DDRPKE 0x00000000
+wm 32 MX6_IOM_GRP_ADDDS 0x00000030
+wm 32 MX6_IOM_GRP_CTLDS 0x00000030
+wm 32 MX6_IOM_GRP_DDRMODE 0x00020000
+
+wm 32 MX6_MMDC_P0_MPRDDQBY0DL 0x33333333
+wm 32 MX6_MMDC_P0_MPRDDQBY1DL 0x33333333
+wm 32 MX6_MMDC_P0_MPRDDQBY2DL 0x33333333
+wm 32 MX6_MMDC_P0_MPRDDQBY3DL 0x33333333
+wm 32 MX6_MMDC_P1_MPRDDQBY0DL 0x33333333
+wm 32 MX6_MMDC_P1_MPRDDQBY1DL 0x33333333
+wm 32 MX6_MMDC_P1_MPRDDQBY2DL 0x33333333
+wm 32 MX6_MMDC_P1_MPRDDQBY3DL 0x33333333
diff --git a/arch/arm/boards/karo-tx6x/1600mhz_4x128mx16.imxcfg b/arch/arm/boards/karo-tx6x/1600mhz_4x128mx16.imxcfg
new file mode 100644
index 0000000000..b5c59e3c3c
--- /dev/null
+++ b/arch/arm/boards/karo-tx6x/1600mhz_4x128mx16.imxcfg
@@ -0,0 +1,101 @@
+/* MDMISC mirroring interleaved (row/bank/col) */
+wm 32 MX6_MMDC_P0_MDMISC 0x00000742
+check 32 while_all_bits_clear MX6_MMDC_P0_MDMISC 0x00000002
+
+wm 32 MX6_MMDC_P0_MDSCR 0x00008000
+check 32 while_any_bit_clear MX6_MMDC_P0_MDSCR 0x00004000
+
+wm 32 MX6_MMDC_P0_MDCTL 0x831a0000
+check 32 while_any_bit_clear MX6_MMDC_P0_MDMISC 0x40000000
+
+wm 32 MX6_MMDC_P0_MDCFG0 0x3f435333
+wm 32 MX6_MMDC_P0_MDCFG1 0x926e8a63
+wm 32 MX6_MMDC_P0_MDCFG2 0x01ff00db
+wm 32 MX6_MMDC_P0_MDRWD 0x000026d2
+wm 32 MX6_MMDC_P0_MDOR 0x00431023
+wm 32 MX6_MMDC_P0_MDOTC 0x1b333030
+wm 32 MX6_MMDC_P0_MDPDC 0x0002006d
+wm 32 MX6_MMDC_P1_MDPDC 0x0002006d
+wm 32 MX6_MMDC_P0_MDASP 0x00000027
+
+wm 32 MX6_MMDC_P0_MDSCR 0x05208030
+wm 32 MX6_MMDC_P0_MDSCR 0x00048031
+wm 32 MX6_MMDC_P0_MDSCR 0x00408032
+wm 32 MX6_MMDC_P0_MDSCR 0x00008033
+wm 32 MX6_MMDC_P0_MDREF 0x0000c000
+wm 32 MX6_MMDC_P0_MDSCR 0x00008020
+
+wm 32 MX6_MMDC_P0_MPODTCTRL 0x00022222
+wm 32 MX6_MMDC_P1_MPODTCTRL 0x00022222
+
+wm 32 MX6_MMDC_P0_MPPDCMPR2 0x00000003
+wm 32 MX6_MMDC_P0_MAPSR 0x00001007
+wm 32 MX6_MMDC_P0_MDSCR 0x04008010
+wm 32 MX6_MMDC_P0_MDSCR 0x04008040
+
+wm 32 MX6_MMDC_P0_MPZQHWCTRL 0xA1390001
+check 32 while_all_bits_clear MX6_MMDC_P0_MPZQHWCTRL 0x00010000
+wm 32 MX6_MMDC_P0_MPZQHWCTRL 0xA1380000
+
+wm 32 MX6_MMDC_P0_MPWLDECTRL0 0x001e001e
+wm 32 MX6_MMDC_P0_MPWLDECTRL1 0x001e001e
+wm 32 MX6_MMDC_P1_MPWLDECTRL0 0x001e001e
+wm 32 MX6_MMDC_P1_MPWLDECTRL1 0x001e001e
+
+wm 32 MX6_MMDC_P0_MDSCR 0x00048033
+wm 32 MX6_IOM_DRAM_SDQS0 0x00007030
+wm 32 MX6_IOM_DRAM_SDQS1 0x00007030
+wm 32 MX6_IOM_DRAM_SDQS2 0x00007030
+wm 32 MX6_IOM_DRAM_SDQS3 0x00007030
+wm 32 MX6_IOM_DRAM_SDQS4 0x00007030
+wm 32 MX6_IOM_DRAM_SDQS5 0x00007030
+wm 32 MX6_IOM_DRAM_SDQS6 0x00007030
+wm 32 MX6_IOM_DRAM_SDQS7 0x00007030
+
+wm 32 MX6_MMDC_P0_MDSCR 0x00008020
+wm 32 MX6_MMDC_P0_MDSCR 0x04008050
+
+wm 32 MX6_MMDC_P0_MPRDDLCTL 0x40404040
+wm 32 MX6_MMDC_P0_MPWRDLCTL 0x40404040
+wm 32 MX6_MMDC_P1_MPRDDLCTL 0x40404040
+wm 32 MX6_MMDC_P1_MPWRDLCTL 0x40404040
+wm 32 MX6_MMDC_P0_MPMUR0 0x00000800
+
+wm 32 MX6_MMDC_P0_MPDGCTRL0 0x80000000
+check 32 while_all_bits_clear MX6_MMDC_P0_MPDGCTRL0 0x80000000
+wm 32 MX6_MMDC_P0_MPDGCTRL0 0x80000000
+check 32 while_all_bits_clear MX6_MMDC_P0_MPDGCTRL0 0x80000000
+wm 32 MX6_MMDC_P0_MPDGCTRL0 0x50800000
+check 32 while_all_bits_clear MX6_MMDC_P0_MPDGCTRL0 0x10001000
+
+wm 32 MX6_IOM_DRAM_SDQS0 0x00000030
+wm 32 MX6_IOM_DRAM_SDQS1 0x00000030
+wm 32 MX6_IOM_DRAM_SDQS2 0x00000030
+wm 32 MX6_IOM_DRAM_SDQS3 0x00000030
+wm 32 MX6_IOM_DRAM_SDQS4 0x00000030
+wm 32 MX6_IOM_DRAM_SDQS5 0x00000030
+wm 32 MX6_IOM_DRAM_SDQS6 0x00000030
+wm 32 MX6_IOM_DRAM_SDQS7 0x00000030
+
+wm 32 MX6_MMDC_P0_MDSCR 0x04008050
+wm 32 MX6_MMDC_P0_MPRDDLHWCTL 0x00000030
+wm 32 MX6_MMDC_P1_MPRDDLHWCTL 0x00000030
+
+check 32 while_all_bits_clear MX6_MMDC_P0_MPRDDLHWCTL 0x0000001f
+check 32 while_all_bits_clear MX6_MMDC_P1_MPRDDLHWCTL 0x0000001f
+
+wm 32 MX6_MMDC_P0_MDSCR 0x04008050
+wm 32 MX6_MMDC_P0_MPWRDLHWCTL 0x00000030
+check 32 while_all_bits_clear MX6_MMDC_P0_MPWRDLHWCTL 0x0000001f
+
+wm 32 MX6_MMDC_P0_MDSCR 0x04008050
+wm 32 MX6_MMDC_P1_MPWRDLHWCTL 0x00000030
+check 32 while_all_bits_clear MX6_MMDC_P1_MPWRDLHWCTL 0x0000001f
+wm 32 MX6_MMDC_P0_MDSCR 0x00008033
+wm 32 MX6_MMDC_P0_MPZQHWCTRL 0xa138002b
+wm 32 MX6_MMDC_P0_MDREF 0x00001800
+wm 32 MX6_MMDC_P0_MAPSR 0x00001006
+wm 32 MX6_MMDC_P0_MDPDC 0x0002556d
+wm 32 MX6_MMDC_P1_MDPDC 0x0002556d
+wm 32 MX6_MMDC_P0_MDSCR 0x00000000
+check 32 while_all_bits_clear MX6_MMDC_P0_MDSCR 0x00004000
diff --git a/arch/arm/boards/karo-tx6x/Makefile b/arch/arm/boards/karo-tx6x/Makefile
new file mode 100644
index 0000000000..01c7a259e9
--- /dev/null
+++ b/arch/arm/boards/karo-tx6x/Makefile
@@ -0,0 +1,2 @@
+obj-y += board.o
+lwl-y += lowlevel.o
diff --git a/arch/arm/boards/karo-tx6x/board.c b/arch/arm/boards/karo-tx6x/board.c
new file mode 100644
index 0000000000..6d9dd9a505
--- /dev/null
+++ b/arch/arm/boards/karo-tx6x/board.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2014 Steffen Trumtrar, Pengutronix
+ *
+ *
+ * with the PMIC init code taken from u-boot
+ * Copyright (C) 2012,2013 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <gpio.h>
+#include <init.h>
+#include <i2c/i2c.h>
+#include <linux/clk.h>
+#include <environment.h>
+#include <mach/bbu.h>
+#include <mach/imx6.h>
+#include <mfd/imx6q-iomuxc-gpr.h>
+
+#define ETH_PHY_RST IMX_GPIO_NR(7, 6)
+#define ETH_PHY_PWR IMX_GPIO_NR(3, 20)
+#define ETH_PHY_INT IMX_GPIO_NR(7, 1)
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+#define DIV_ROUND(n,d) (((n) + ((d)/2)) / (d))
+
+#define LTC3676_BUCK1 0x01
+#define LTC3676_BUCK2 0x02
+#define LTC3676_BUCK3 0x03
+#define LTC3676_BUCK4 0x04
+#define LTC3676_DVB1A 0x0A
+#define LTC3676_DVB1B 0x0B
+#define LTC3676_DVB2A 0x0C
+#define LTC3676_DVB2B 0x0D
+#define LTC3676_DVB3A 0x0E
+#define LTC3676_DVB3B 0x0F
+#define LTC3676_DVB4A 0x10
+#define LTC3676_DVB4B 0x11
+#define LTC3676_MSKPG 0x13
+#define LTC3676_CLIRQ 0x1f
+
+#define LTC3676_BUCK_DVDT_FAST (1 << 0)
+#define LTC3676_BUCK_KEEP_ALIVE (1 << 1)
+#define LTC3676_BUCK_CLK_RATE_LOW (1 << 2)
+#define LTC3676_BUCK_PHASE_SEL (1 << 3)
+#define LTC3676_BUCK_ENABLE_300 (1 << 4)
+#define LTC3676_BUCK_PULSE_SKIP (0 << 5)
+#define LTC3676_BUCK_BURST_MODE (1 << 5)
+#define LTC3676_BUCK_CONTINUOUS (2 << 5)
+#define LTC3676_BUCK_ENABLE (1 << 7)
+
+#define LTC3676_PGOOD_MASK (1 << 5)
+
+#define LTC3676_MSKPG_BUCK1 (1 << 0)
+#define LTC3676_MSKPG_BUCK2 (1 << 1)
+#define LTC3676_MSKPG_BUCK3 (1 << 2)
+#define LTC3676_MSKPG_BUCK4 (1 << 3)
+#define LTC3676_MSKPG_LDO2 (1 << 5)
+#define LTC3676_MSKPG_LDO3 (1 << 6)
+#define LTC3676_MSKPG_LDO4 (1 << 7)
+
+#define VDD_IO_VAL mV_to_regval(vout_to_vref(3300 * 10, 5))
+#define VDD_IO_VAL_LP mV_to_regval(vout_to_vref(3100 * 10, 5))
+#define VDD_IO_VAL_2 mV_to_regval(vout_to_vref(3300 * 10, 5_2))
+#define VDD_IO_VAL_2_LP mV_to_regval(vout_to_vref(3100 * 10, 5_2))
+#define VDD_SOC_VAL mV_to_regval(vout_to_vref(1425 * 10, 6))
+#define VDD_SOC_VAL_LP mV_to_regval(vout_to_vref(900 * 10, 6))
+#define VDD_DDR_VAL mV_to_regval(vout_to_vref(1500 * 10, 7))
+#define VDD_DDR_VAL_LP mV_to_regval(vout_to_vref(1500 * 10, 7))
+#define VDD_CORE_VAL mV_to_regval(vout_to_vref(1425 * 10, 8))
+#define VDD_CORE_VAL_LP mV_to_regval(vout_to_vref(900 * 10, 8))
+
+/* LDO1 */
+#define R1_1 470
+#define R2_1 150
+/* LDO4 */
+#define R1_4 470
+#define R2_4 150
+/* Buck1 */
+#define R1_5 390
+#define R2_5 110
+#define R1_5_2 470
+#define R2_5_2 150
+/* Buck2 (SOC) */
+#define R1_6 150
+#define R2_6 180
+/* Buck3 (DDR) */
+#define R1_7 150
+#define R2_7 140
+/* Buck4 (CORE) */
+#define R1_8 150
+#define R2_8 180
+
+/* calculate voltages in 10mV */
+#define R1(idx) R1_##idx
+#define R2(idx) R2_##idx
+
+#define vout_to_vref(vout, idx) ((vout) * R2(idx) / (R1(idx) + R2(idx)))
+#define vref_to_vout(vref, idx) DIV_ROUND_UP((vref) * (R1(idx) + R2(idx)), R2(idx))
+
+#define mV_to_regval(mV) DIV_ROUND(((((mV) < 4125) ? 4125 : (mV)) - 4125), 125)
+#define regval_to_mV(v) (((v) * 125 + 4125))
+
+static struct ltc3673_regs {
+ u8 addr;
+ u8 val;
+ u8 mask;
+} ltc3676_regs[] = {
+ { LTC3676_MSKPG, ~LTC3676_MSKPG_BUCK1, },
+ { LTC3676_DVB2B, VDD_SOC_VAL_LP | LTC3676_PGOOD_MASK, ~0x3f, },
+ { LTC3676_DVB3B, VDD_DDR_VAL_LP, ~0x3f, },
+ { LTC3676_DVB4B, VDD_CORE_VAL_LP | LTC3676_PGOOD_MASK, ~0x3f, },
+ { LTC3676_DVB2A, VDD_SOC_VAL, ~0x3f, },
+ { LTC3676_DVB3A, VDD_DDR_VAL, ~0x3f, },
+ { LTC3676_DVB4A, VDD_CORE_VAL, ~0x3f, },
+ { LTC3676_BUCK1, LTC3676_BUCK_BURST_MODE | LTC3676_BUCK_CLK_RATE_LOW, },
+ { LTC3676_BUCK2, LTC3676_BUCK_BURST_MODE, },
+ { LTC3676_BUCK3, LTC3676_BUCK_BURST_MODE, },
+ { LTC3676_BUCK4, LTC3676_BUCK_BURST_MODE, },
+ { LTC3676_CLIRQ, 0, }, /* clear interrupt status */
+};
+
+static struct ltc3673_regs ltc3676_regs_2[] = {
+ { LTC3676_DVB1B, VDD_IO_VAL_2_LP | LTC3676_PGOOD_MASK, ~0x3f, },
+ { LTC3676_DVB1A, VDD_IO_VAL_2, ~0x3f, },
+};
+
+
+static int setup_pmic_voltages(void)
+{
+ struct i2c_adapter *adapter = NULL;
+ struct i2c_client client;
+ int addr = 0x3c;
+ int bus = 0;
+ int i;
+ struct ltc3673_regs *r;
+
+ adapter = i2c_get_adapter(bus);
+ if (!adapter) {
+ pr_err("i2c bus %d not found\n", bus);
+ return -ENODEV;
+ }
+
+ client.adapter = adapter;
+ client.addr = addr;
+
+ r = ltc3676_regs;
+
+ for (i = 0; i < ARRAY_SIZE(ltc3676_regs); i++, r++) {
+ if (i2c_write_reg(&client, r->addr, &r->val, 1) != 1) {
+ pr_err("i2c write error\n");
+ return -EIO;
+ }
+ }
+
+ r = ltc3676_regs_2;
+
+ for (i = 0; i < ARRAY_SIZE(ltc3676_regs_2); i++, r++) {
+ if (i2c_write_reg(&client, r->addr, &r->val, 1) != 1) {
+ pr_err("i2c write error\n");
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static void eth_init(void)
+{
+ void __iomem *iomux = (void *)MX6_IOMUXC_BASE_ADDR;
+ uint32_t val;
+
+ val = readl(iomux + IOMUXC_GPR1);
+ val |= IMX6Q_GPR1_ENET_CLK_SEL_ANATOP;
+ writel(val, iomux + IOMUXC_GPR1);
+}
+
+static int tx6x_devices_init(void)
+{
+ if (!of_machine_is_compatible("karo,imx6dl-tx6dl") &&
+ !of_machine_is_compatible("karo,imx6q-tx6q"))
+ return 0;
+
+ barebox_set_hostname("tx6u");
+
+ eth_init();
+
+ setup_pmic_voltages();
+
+ imx6_bbu_nand_register_handler("nand", BBU_HANDLER_FLAG_DEFAULT);
+
+ return 0;
+}
+device_initcall(tx6x_devices_init);
diff --git a/arch/arm/boards/karo-tx6x/flash-header-tx6dl-1g.imxcfg b/arch/arm/boards/karo-tx6x/flash-header-tx6dl-1g.imxcfg
new file mode 100644
index 0000000000..2a1c42aeed
--- /dev/null
+++ b/arch/arm/boards/karo-tx6x/flash-header-tx6dl-1g.imxcfg
@@ -0,0 +1,10 @@
+soc imx6
+loadaddr 0x20000000
+dcdofs 0x400
+
+#include <mach/imx6-ddr-regs.h>
+#include <mach/imx6dl-ddr-regs.h>
+#include <mach/imx6-ccm-regs.h>
+
+#include "ram-base.imxcfg"
+#include "1600mhz_4x128mx16.imxcfg"
diff --git a/arch/arm/boards/karo-tx6x/lowlevel.c b/arch/arm/boards/karo-tx6x/lowlevel.c
new file mode 100644
index 0000000000..00008d403c
--- /dev/null
+++ b/arch/arm/boards/karo-tx6x/lowlevel.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2014 Steffen Trumtrar, Pengutronix
+ *
+ * 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.
+ */
+
+#include <debug_ll.h>
+#include <common.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+#include <image-metadata.h>
+#include <mach/generic.h>
+#include <sizes.h>
+
+static inline void setup_uart(void)
+{
+ void __iomem *ccmbase = (void *)MX6_CCM_BASE_ADDR;
+ void __iomem *uartbase = (void *)MX6_UART1_BASE_ADDR;
+ void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
+
+ writel(0x1, iomuxbase + 0x0314);
+ writel(0x1, iomuxbase + 0x0318);
+ writel(0x1, iomuxbase + 0x0330);
+ writel(0x1, iomuxbase + 0x032c);
+
+ writel(0xffffffff, ccmbase + 0x68);
+ writel(0xffffffff, ccmbase + 0x6c);
+ writel(0xffffffff, ccmbase + 0x70);
+ writel(0xffffffff, ccmbase + 0x74);
+ writel(0xffffffff, ccmbase + 0x78);
+ writel(0xffffffff, ccmbase + 0x7c);
+ writel(0xffffffff, ccmbase + 0x80);
+
+ writel(0x00000000, uartbase + 0x80);
+ writel(0x00004027, uartbase + 0x84);
+ writel(0x00000784, uartbase + 0x88);
+ writel(0x00000a81, uartbase + 0x90);
+ writel(0x0000002b, uartbase + 0x9c);
+ writel(0x0001b0b0, uartbase + 0xb0);
+ writel(0x0000047f, uartbase + 0xa4);
+ writel(0x0000c34f, uartbase + 0xa8);
+ writel(0x00000001, uartbase + 0x80);
+
+ putc_ll('>');
+}
+
+extern char __dtb_imx6dl_tx6u_801x_start[];
+
+BAREBOX_IMD_TAG_STRING(tx6x_mx6_memsize_1G, IMD_TYPE_PARAMETER, "memsize=1024", 0);
+
+ENTRY_FUNCTION(start_imx6dl_tx6x_1g, r0, r1, r2)
+{
+ void *fdt;
+
+ imx6_cpu_lowlevel_init();
+
+ arm_setup_stack(0x00920000 - 8);
+
+ IMD_USED(tx6x_mx6_memsize_1G);
+
+ if (IS_ENABLED(CONFIG_DEBUG_LL))
+ setup_uart();
+
+ fdt = __dtb_imx6dl_tx6u_801x_start - get_runtime_offset();
+
+ barebox_arm_entry(0x10000000, SZ_1G, fdt);
+}
diff --git a/arch/arm/boards/karo-tx6x/ram-base.imxcfg b/arch/arm/boards/karo-tx6x/ram-base.imxcfg
new file mode 100644
index 0000000000..e912fb0f2b
--- /dev/null
+++ b/arch/arm/boards/karo-tx6x/ram-base.imxcfg
@@ -0,0 +1,71 @@
+wm 32 MX6_IOM_DRAM_DQM0 0x00020030
+wm 32 MX6_IOM_DRAM_DQM1 0x00020030
+wm 32 MX6_IOM_DRAM_DQM2 0x00020030
+wm 32 MX6_IOM_DRAM_DQM3 0x00020030
+wm 32 MX6_IOM_DRAM_DQM4 0x00020030
+wm 32 MX6_IOM_DRAM_DQM5 0x00020030
+wm 32 MX6_IOM_DRAM_DQM6 0x00020030
+wm 32 MX6_IOM_DRAM_DQM7 0x00020030
+
+wm 32 MX6_IOM_DRAM_ADDR00 0x00000000
+wm 32 MX6_IOM_DRAM_ADDR01 0x00000000
+wm 32 MX6_IOM_DRAM_ADDR02 0x00000000
+wm 32 MX6_IOM_DRAM_ADDR03 0x00000000
+wm 32 MX6_IOM_DRAM_ADDR04 0x00000000
+wm 32 MX6_IOM_DRAM_ADDR05 0x00000000
+wm 32 MX6_IOM_DRAM_ADDR06 0x00000000
+wm 32 MX6_IOM_DRAM_ADDR07 0x00000000
+wm 32 MX6_IOM_DRAM_ADDR08 0x00000000
+wm 32 MX6_IOM_DRAM_ADDR09 0x00000000
+wm 32 MX6_IOM_DRAM_ADDR10 0x00000000
+wm 32 MX6_IOM_DRAM_ADDR11 0x00000000
+wm 32 MX6_IOM_DRAM_ADDR12 0x00000000
+wm 32 MX6_IOM_DRAM_ADDR13 0x00000000
+wm 32 MX6_IOM_DRAM_ADDR14 0x00000000
+wm 32 MX6_IOM_DRAM_ADDR15 0x00000000
+
+wm 32 MX6_IOM_DRAM_CAS 0x00020030
+wm 32 MX6_IOM_DRAM_RAS 0x00020030
+wm 32 MX6_IOM_DRAM_SDCLK_0 0x00020030
+wm 32 MX6_IOM_DRAM_SDCLK_1 0x00020030
+
+wm 32 MX6_IOM_DRAM_RESET 0x00020030
+wm 32 MX6_IOM_DRAM_SDCKE0 0x00003000
+wm 32 MX6_IOM_DRAM_SDCKE1 0x00003000
+wm 32 MX6_IOM_DRAM_SDBA0 0x00000000
+wm 32 MX6_IOM_DRAM_SDBA1 0x00000000
+wm 32 MX6_IOM_DRAM_SDBA2 0x00000000
+wm 32 MX6_IOM_DRAM_SDODT0 0x00003030
+wm 32 MX6_IOM_DRAM_SDODT1 0x00003030
+wm 32 MX6_IOM_GRP_B0DS 0x00000030
+wm 32 MX6_IOM_GRP_B1DS 0x00000030
+wm 32 MX6_IOM_GRP_B2DS 0x00000030
+wm 32 MX6_IOM_GRP_B3DS 0x00000030
+wm 32 MX6_IOM_GRP_B4DS 0x00000030
+wm 32 MX6_IOM_GRP_B5DS 0x00000030
+wm 32 MX6_IOM_GRP_B6DS 0x00000030
+wm 32 MX6_IOM_GRP_B7DS 0x00000030
+wm 32 MX6_IOM_GRP_ADDDS 0x00000030
+
+/* (differential input) */
+wm 32 MX6_IOM_DDRMODE_CTL 0x00020000
+/* disable ddr pullups */
+wm 32 MX6_IOM_GRP_DDRPKE 0x00000000
+/* (differential input) */
+wm 32 MX6_IOM_GRP_DDRMODE 0x00020000
+wm 32 MX6_IOM_GRP_CTLDS 0x00000030
+
+wm 32 MX6_IOM_GRP_DDR_TYPE 0x000c0000
+wm 32 MX6_IOM_GRP_DDRPKE 0x00002000
+/* GRP_DDRHYS */
+wm 32 MX6_IOM_GRP_DDRHYS 0x00000000
+
+/* Read data DQ Byte0-3 delay */
+wm 32 MX6_MMDC_P0_MPRDDQBY0DL 0x33333333
+wm 32 MX6_MMDC_P0_MPRDDQBY1DL 0x33333333
+wm 32 MX6_MMDC_P0_MPRDDQBY2DL 0x33333333
+wm 32 MX6_MMDC_P0_MPRDDQBY3DL 0x33333333
+wm 32 MX6_MMDC_P1_MPRDDQBY0DL 0x33333333
+wm 32 MX6_MMDC_P1_MPRDDQBY1DL 0x33333333
+wm 32 MX6_MMDC_P1_MPRDDQBY2DL 0x33333333
+wm 32 MX6_MMDC_P1_MPRDDQBY3DL 0x33333333
diff --git a/arch/arm/boards/phytec-phycard-imx6/Makefile b/arch/arm/boards/phytec-phycard-imx6/Makefile
index 01c7a259e9..de67f04dde 100644
--- a/arch/arm/boards/phytec-phycard-imx6/Makefile
+++ b/arch/arm/boards/phytec-phycard-imx6/Makefile
@@ -1,2 +1,3 @@
obj-y += board.o
lwl-y += lowlevel.o
+bbenv-y += defaultenv-phycard-imx6
diff --git a/arch/arm/boards/phytec-phycard-imx6/board.c b/arch/arm/boards/phytec-phycard-imx6/board.c
index d425b48347..27b84aa1b8 100644
--- a/arch/arm/boards/phytec-phycard-imx6/board.c
+++ b/arch/arm/boards/phytec-phycard-imx6/board.c
@@ -17,6 +17,7 @@
*
*/
+#include <envfs.h>
#include <environment.h>
#include <bootsource.h>
#include <common.h>
@@ -44,6 +45,8 @@ static int phytec_pcaaxl3_init(void)
imx6_bbu_nand_register_handler("nand", BBU_HANDLER_FLAG_DEFAULT);
+ defaultenv_append_directory(defaultenv_phycard_imx6);
+
return 0;
}
device_initcall(phytec_pcaaxl3_init);
diff --git a/arch/arm/boards/phytec-phycard-imx6/defaultenv-phycard-imx6/boot/nand b/arch/arm/boards/phytec-phycard-imx6/defaultenv-phycard-imx6/boot/nand
new file mode 100644
index 0000000000..3f3a9aa2fc
--- /dev/null
+++ b/arch/arm/boards/phytec-phycard-imx6/defaultenv-phycard-imx6/boot/nand
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+global.bootm.image="/dev/nand0.kernel.bb"
+global.bootm.oftree="/dev/nand0.oftree.bb"
+bootargs-ip
+global.linux.bootargs.dyn.root="root=ubi0:root ubi.mtd=root rootfstype=ubifs rw"
+
diff --git a/arch/arm/boards/phytec-phycard-imx6/defaultenv-phycard-imx6/boot/sd-ext3 b/arch/arm/boards/phytec-phycard-imx6/defaultenv-phycard-imx6/boot/sd-ext3
new file mode 100644
index 0000000000..fd35fe0c74
--- /dev/null
+++ b/arch/arm/boards/phytec-phycard-imx6/defaultenv-phycard-imx6/boot/sd-ext3
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+global.bootm.image="/mnt/mmc/linuximage"
+global.bootm.oftree="/mnt/mmc/oftree"
+bootargs-ip
+global.linux.bootargs.dyn.root="root=/dev/mmcblk0p2 rootfstype=ext3 rootwait rw"
diff --git a/arch/arm/boards/phytec-phycard-imx6/env/config-board b/arch/arm/boards/phytec-phycard-imx6/defaultenv-phycard-imx6/config-board
index 44008aa3e7..4d7b37c313 100644
--- a/arch/arm/boards/phytec-phycard-imx6/env/config-board
+++ b/arch/arm/boards/phytec-phycard-imx6/defaultenv-phycard-imx6/config-board
@@ -3,5 +3,7 @@
# board defaults, do not change in running system. Change /env/config
# instead
+global.boot.default=nand
+
global.hostname=phyCARD-i.MX6
global.linux.bootargs.base="console=ttymxc2,115200"
diff --git a/arch/arm/boards/phytec-phycard-imx6/defaultenv-phycard-imx6/init/automount b/arch/arm/boards/phytec-phycard-imx6/defaultenv-phycard-imx6/init/automount
new file mode 100644
index 0000000000..49d99bd78d
--- /dev/null
+++ b/arch/arm/boards/phytec-phycard-imx6/defaultenv-phycard-imx6/init/automount
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+if [ "$1" = menu ]; then
+ init-menu-add-entry "$0" "Automountpoints"
+ exit
+fi
+
+# automount tftp server based on $eth0.serverip
+
+mkdir -p /mnt/tftp
+automount /mnt/tftp 'ifup eth0 && mount -t tftp $eth0.serverip /mnt/tftp'
+
+mkdir -p /mnt/mmc
+automount -d /mnt/mmc 'mmc2.probe=1 && [ -e /dev/mmc2.0 ] && mount /dev/mmc2.0 /mnt/mmc'
diff --git a/arch/arm/boards/phytec-phycard-imx6/env/boot/nand b/arch/arm/boards/phytec-phycard-imx6/env/boot/nand
deleted file mode 100644
index cf3b25c11d..0000000000
--- a/arch/arm/boards/phytec-phycard-imx6/env/boot/nand
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-global.bootm.image="/dev/nand0.kernel.bb"
-#global.bootm.oftree="/env/oftree"
-bootargs-ip
-global.linux.bootargs.dyn.root="root=ubi0:root ubi.mtd=nand0.root rootfstype=ubifs"
-
diff --git a/arch/arm/boards/phytec-phycard-imx6/env/boot/sd-ext3 b/arch/arm/boards/phytec-phycard-imx6/env/boot/sd-ext3
deleted file mode 100644
index 443563390c..0000000000
--- a/arch/arm/boards/phytec-phycard-imx6/env/boot/sd-ext3
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-
-global.bootm.image="/mnt/kernel/linuximage"
-#global.bootm.oftree="/boot/oftree"
-bootargs-ip
-global.linux.bootargs.dyn.root="root=/dev/mmcblk0p2 rootfstype=ext3 rootwait"
diff --git a/arch/arm/boards/phytec-phycore-am335x/board.c b/arch/arm/boards/phytec-phycore-am335x/board.c
index 9482b80ed7..035866b969 100644
--- a/arch/arm/boards/phytec-phycore-am335x/board.c
+++ b/arch/arm/boards/phytec-phycore-am335x/board.c
@@ -78,8 +78,10 @@ static int pcm051_devices_init(void)
defaultenv_append_directory(defaultenv_phycore_am335x);
am33xx_bbu_spi_nor_mlo_register_handler("MLO.spi", "/dev/m25p0.xload");
+ am33xx_bbu_spi_nor_register_handler("spi", "/dev/m25p0.barebox");
am33xx_bbu_nand_xloadslots_register_handler("MLO.nand",
xloadslots, ARRAY_SIZE(xloadslots));
+ am33xx_bbu_nand_register_handler("nand", "/dev/nand0.barebox.bb");
return 0;
}
diff --git a/arch/arm/boards/phytec-phycore-am335x/lowlevel.c b/arch/arm/boards/phytec-phycore-am335x/lowlevel.c
index ff1f04e87f..66bae806c4 100644
--- a/arch/arm/boards/phytec-phycore-am335x/lowlevel.c
+++ b/arch/arm/boards/phytec-phycore-am335x/lowlevel.c
@@ -16,15 +16,15 @@
#include <debug_ll.h>
static const struct am33xx_cmd_control pcm051_cmd = {
- .slave_ratio0 = 0x40,
+ .slave_ratio0 = 0x80,
.dll_lock_diff0 = 0x0,
- .invert_clkout0 = 0x1,
- .slave_ratio1 = 0x40,
+ .invert_clkout0 = 0x0,
+ .slave_ratio1 = 0x80,
.dll_lock_diff1 = 0x0,
- .invert_clkout1 = 0x1,
- .slave_ratio2 = 0x40,
+ .invert_clkout1 = 0x0,
+ .slave_ratio2 = 0x80,
.dll_lock_diff2 = 0x0,
- .invert_clkout2 = 0x1,
+ .invert_clkout2 = 0x0,
};
struct pcm051_sdram_timings {
@@ -33,66 +33,86 @@ struct pcm051_sdram_timings {
};
enum {
- MT41J128M16125IT_1x256M16,
- MT41J64M1615IT_1x128M16,
- MT41J256M16HA15EIT_1x512M16,
+ MT41J128M16125IT_256MB,
+ MT41J64M1615IT_128MB,
+ MT41J256M16HA15EIT_512MB,
+ MT41J512M8125IT_2x512MB,
};
struct pcm051_sdram_timings timings[] = {
- /* 1x256M16 */
- [MT41J128M16125IT_1x256M16] = {
+ /* 256MB */
+ [MT41J128M16125IT_256MB] = {
.regs = {
- .emif_read_latency = 0x6,
- .emif_tim1 = 0x0888A39B,
- .emif_tim2 = 0x26337FDA,
- .emif_tim3 = 0x501F830F,
- .sdram_config = 0x61C04AB2,
+ .emif_read_latency = 0x7,
+ .emif_tim1 = 0x0AAAD4DB,
+ .emif_tim2 = 0x26437FDA,
+ .emif_tim3 = 0x501F83FF,
+ .sdram_config = 0x61C052B2,
.zq_config = 0x50074BE4,
- .sdram_ref_ctrl = 0x0000093B,
+ .sdram_ref_ctrl = 0x00000C30,
},
.data = {
.rd_slave_ratio0 = 0x3B,
- .wr_dqs_slave_ratio0 = 0x3B,
- .fifo_we_slave_ratio0 = 0x97,
- .wr_slave_ratio0 = 0x76,
+ .wr_dqs_slave_ratio0 = 0x33,
+ .fifo_we_slave_ratio0 = 0x9c,
+ .wr_slave_ratio0 = 0x6f,
},
},
- /* 1x128M16 */
- [MT41J64M1615IT_1x128M16] = {
+ /* 128MB */
+ [MT41J64M1615IT_128MB] = {
.regs = {
- .emif_read_latency = 0x6,
- .emif_tim1 = 0x0888A39B,
- .emif_tim2 = 0x26247FDA,
- .emif_tim3 = 0x501F821F,
- .sdram_config = 0x61C04A32,
+ .emif_read_latency = 0x7,
+ .emif_tim1 = 0x0AAAE4DB,
+ .emif_tim2 = 0x262F7FDA,
+ .emif_tim3 = 0x501F82BF,
+ .sdram_config = 0x61C05232,
.zq_config = 0x50074BE4,
- .sdram_ref_ctrl = 0x0000093B,
+ .sdram_ref_ctrl = 0x00000C30,
},
.data = {
- .rd_slave_ratio0 = 0x3A,
- .wr_dqs_slave_ratio0 = 0x36,
+ .rd_slave_ratio0 = 0x38,
+ .wr_dqs_slave_ratio0 = 0x34,
.fifo_we_slave_ratio0 = 0xA2,
- .wr_slave_ratio0 = 0x74,
+ .wr_slave_ratio0 = 0x72,
},
},
- /* 1x512MB */
- [MT41J256M16HA15EIT_1x512M16] = {
+ /* 512MB */
+ [MT41J256M16HA15EIT_512MB] = {
.regs = {
- .emif_read_latency = 0x6,
- .emif_tim1 = 0x0888A39B,
- .emif_tim2 = 0x26517FDA,
- .emif_tim3 = 0x501F84EF,
- .sdram_config = 0x61C04B32,
+ .emif_read_latency = 0x7,
+ .emif_tim1 = 0x0AAAE4DB,
+ .emif_tim2 = 0x266B7FDA,
+ .emif_tim3 = 0x501F867F,
+ .sdram_config = 0x61C05332,
.zq_config = 0x50074BE4,
- .sdram_ref_ctrl = 0x0000093B,
+ .sdram_ref_ctrl = 0x00000C30
},
.data = {
- .rd_slave_ratio0 = 0x3B,
- .wr_dqs_slave_ratio0 = 0x3B,
- .fifo_we_slave_ratio0 = 0x96,
- .wr_slave_ratio0 = 0x76,
+ .rd_slave_ratio0 = 0x35,
+ .wr_dqs_slave_ratio0 = 0x43,
+ .fifo_we_slave_ratio0 = 0x97,
+ .wr_slave_ratio0 = 0x7b,
+ },
+ },
+
+ /* 1024MB */
+ [MT41J512M8125IT_2x512MB] = {
+ .regs = {
+ .emif_read_latency = 0x7,
+ .emif_tim1 = 0x0AAAE4DB,
+ .emif_tim2 = 0x266B7FDA,
+ .emif_tim3 = 0x501F867F,
+ .sdram_config = 0x61C053B2,
+ .zq_config = 0x50074BE4,
+ .sdram_ref_ctrl = 0x00000C30
+ },
+ .data = {
+ .rd_slave_ratio0 = 0x32,
+ .wr_dqs_slave_ratio0 = 0x48,
+ .fifo_we_slave_ratio0 = 0x99,
+ .wr_slave_ratio0 = 0x80,
},
},
};
@@ -122,7 +142,7 @@ static noinline void pcm051_board_init(int sdram)
writel(WDT_DISABLE_CODE2, AM33XX_WDT_REG(WSPR));
while (readl(AM33XX_WDT_REG(WWPS)) != 0x0);
- am33xx_pll_init(MPUPLL_M_600, 25, DDRPLL_M_303);
+ am33xx_pll_init(MPUPLL_M_600, 25, DDRPLL_M_400);
am335x_sdram_init(0x18B, &pcm051_cmd,
&timing->regs,
@@ -154,19 +174,24 @@ static noinline void pcm051_board_entry(unsigned long bootinfo, int sdram)
pcm051_board_init(sdram);
}
-ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram_1x256m16, bootinfo, r1, r2)
+ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram_256mb, bootinfo, r1, r2)
+{
+ pcm051_board_entry(bootinfo, MT41J128M16125IT_256MB);
+}
+
+ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram_128mb, bootinfo, r1, r2)
{
- pcm051_board_entry(bootinfo, MT41J128M16125IT_1x256M16);
+ pcm051_board_entry(bootinfo, MT41J64M1615IT_128MB);
}
-ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram_1x128m16, bootinfo, r1, r2)
+ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram_512mb, bootinfo, r1, r2)
{
- pcm051_board_entry(bootinfo, MT41J64M1615IT_1x128M16);
+ pcm051_board_entry(bootinfo, MT41J256M16HA15EIT_512MB);
}
-ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram_1x512m16, bootinfo, r1, r2)
+ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram_2x512mb, bootinfo, r1, r2)
{
- pcm051_board_entry(bootinfo, MT41J256M16HA15EIT_1x512M16);
+ pcm051_board_entry(bootinfo, MT41J512M8125IT_2x512MB);
}
ENTRY_FUNCTION(start_am33xx_phytec_phycore_sdram, r0, r1, r2)
diff --git a/arch/arm/boards/phytec-phyflex-imx6/Makefile b/arch/arm/boards/phytec-phyflex-imx6/Makefile
index 01c7a259e9..11e1c7dc38 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/Makefile
+++ b/arch/arm/boards/phytec-phyflex-imx6/Makefile
@@ -1,2 +1,3 @@
obj-y += board.o
lwl-y += lowlevel.o
+bbenv-y += defaultenv-phyflex-imx6
diff --git a/arch/arm/boards/phytec-phyflex-imx6/board.c b/arch/arm/boards/phytec-phyflex-imx6/board.c
index 94e3f6fcf1..09a5c79a9a 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/board.c
+++ b/arch/arm/boards/phytec-phyflex-imx6/board.c
@@ -17,6 +17,9 @@
*
*/
+#include <envfs.h>
+#include <environment.h>
+#include <bootsource.h>
#include <common.h>
#include <gpio.h>
#include <init.h>
@@ -29,8 +32,6 @@
#include <mach/iomux-mx6.h>
#include <mach/imx6.h>
-#define ETH_PHY_RST IMX_GPIO_NR(3, 23)
-
#define GPIO_2_11_PD_CTL MX6_PAD_CTL_PUS_100K_DOWN | MX6_PAD_CTL_PUE | MX6_PAD_CTL_PKE | \
MX6_PAD_CTL_SPEED_MED | MX6_PAD_CTL_DSE_40ohm | MX6_PAD_CTL_HYS
@@ -62,27 +63,9 @@ static void phyflex_err006282_workaround(void)
gpio_direction_input(MX6_PHYFLEX_ERR006282);
}
-static int eth_phy_reset(void)
-{
- gpio_request(ETH_PHY_RST, "phy reset");
- gpio_direction_output(ETH_PHY_RST, 0);
- mdelay(1);
- gpio_set_value(ETH_PHY_RST, 1);
-
- return 0;
-}
-
-static void mmd_write_reg(struct phy_device *dev, int device, int reg, int val)
-{
- phy_write(dev, 0x0d, device);
- phy_write(dev, 0x0e, reg);
- phy_write(dev, 0x0d, (1 << 14) | device);
- phy_write(dev, 0x0e, val);
-}
-
static int ksz9031rn_phy_fixup(struct phy_device *dev)
{
- mmd_write_reg(dev, 2, 8, 0x039F);
+ phy_write_mmd_indirect(dev, 8, 2, 0x039F);
return 0;
}
@@ -96,12 +79,26 @@ static int phytec_pfla02_init(void)
phyflex_err006282_workaround();
- eth_phy_reset();
phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
ksz9031rn_phy_fixup);
imx6_bbu_nand_register_handler("nand", BBU_HANDLER_FLAG_DEFAULT);
+ switch (bootsource_get()) {
+ case BOOTSOURCE_MMC:
+ of_device_enable_path("/chosen/environment-sd");
+ break;
+ case BOOTSOURCE_NAND:
+ of_device_enable_path("/chosen/environment-nand");
+ break;
+ default:
+ case BOOTSOURCE_SPI:
+ of_device_enable_path("/chosen/environment-spinor");
+ break;
+ }
+
+ defaultenv_append_directory(defaultenv_phyflex_imx6);
+
return 0;
}
device_initcall(phytec_pfla02_init);
diff --git a/arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/boot/nand b/arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/boot/nand
new file mode 100644
index 0000000000..79dc03c34a
--- /dev/null
+++ b/arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/boot/nand
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+global.bootm.image="/dev/nand0.kernel.bb"
+global.bootm.oftree="/dev/nand0.oftree.bb"
+bootargs-ip
+global.linux.bootargs.dyn.root="root=ubi0:root ubi.mtd=root rootfstype=ubifs rw"
diff --git a/arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/boot/sd-ext3 b/arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/boot/sd-ext3
new file mode 100644
index 0000000000..fd35fe0c74
--- /dev/null
+++ b/arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/boot/sd-ext3
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+global.bootm.image="/mnt/mmc/linuximage"
+global.bootm.oftree="/mnt/mmc/oftree"
+bootargs-ip
+global.linux.bootargs.dyn.root="root=/dev/mmcblk0p2 rootfstype=ext3 rootwait rw"
diff --git a/arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/config-board b/arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/config-board
new file mode 100644
index 0000000000..b40a4de8c7
--- /dev/null
+++ b/arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/config-board
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# board defaults, do not change in running system. Change /env/config
+# instead
+
+global.boot.default=nand
+
+global.hostname=phyFLEX-i.MX6
+global.linux.bootargs.base="console=ttymxc3,115200"
diff --git a/arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/init/automount b/arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/init/automount
new file mode 100644
index 0000000000..49d99bd78d
--- /dev/null
+++ b/arch/arm/boards/phytec-phyflex-imx6/defaultenv-phyflex-imx6/init/automount
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+if [ "$1" = menu ]; then
+ init-menu-add-entry "$0" "Automountpoints"
+ exit
+fi
+
+# automount tftp server based on $eth0.serverip
+
+mkdir -p /mnt/tftp
+automount /mnt/tftp 'ifup eth0 && mount -t tftp $eth0.serverip /mnt/tftp'
+
+mkdir -p /mnt/mmc
+automount -d /mnt/mmc 'mmc2.probe=1 && [ -e /dev/mmc2.0 ] && mount /dev/mmc2.0 /mnt/mmc'
diff --git a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-1gib.imxcfg b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-1gib.imxcfg
index d73207c364..f6061f25b4 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-1gib.imxcfg
+++ b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-1gib.imxcfg
@@ -1,3 +1,5 @@
+#define SETUP_MDCFG0 \
+ wm 32 0x021b000c 0x3c409b85
#define SETUP_1GIB_2GIB_4GIB \
wm 32 0x021b0040 0x00000017; \
diff --git a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-2gib.imxcfg b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-2gib.imxcfg
index 2291b71e8c..2bfa836c4f 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-2gib.imxcfg
+++ b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-2gib.imxcfg
@@ -1,3 +1,5 @@
+#define SETUP_MDCFG0 \
+ wm 32 0x021b000c 0x565c9b85
#define SETUP_1GIB_2GIB_4GIB \
wm 32 0x021b0040 0x00000027; \
diff --git a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-4gib.imxcfg b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-4gib.imxcfg
index c6dc775d8f..491f89357c 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-4gib.imxcfg
+++ b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-4gib.imxcfg
@@ -1,6 +1,8 @@
+#define SETUP_MDCFG0 \
+ wm 32 0x021b000c 0x8c929b85
#define SETUP_1GIB_2GIB_4GIB \
- wm 32 0x021b0040 0x00000047; \
- wm 32 0x021b0000 0xC41A0000
+ wm 32 0x021b0040 0x00000047; \
+ wm 32 0x021b0000 0xC41A0000
#include "flash-header-phytec-pfla02.h"
diff --git a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02.h b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02.h
index 138ae36ee3..98b3c1869b 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02.h
+++ b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02.h
@@ -2,46 +2,60 @@ soc imx6
loadaddr 0x20000000
dcdofs 0x400
-wm 32 0x020e05a8 0x00000030
-wm 32 0x020e05b0 0x00000030
-wm 32 0x020e0524 0x00000030
-wm 32 0x020e051c 0x00000030
-wm 32 0x020e0518 0x00000030
-wm 32 0x020e050c 0x00000030
-wm 32 0x020e05b8 0x00000030
-wm 32 0x020e05c0 0x00000030
-wm 32 0x020e05ac 0x00020030
-wm 32 0x020e05b4 0x00020030
-wm 32 0x020e0528 0x00020030
-wm 32 0x020e0520 0x00020030
-wm 32 0x020e0514 0x00020030
-wm 32 0x020e0510 0x00020030
-wm 32 0x020e05bc 0x00020030
-wm 32 0x020e05c4 0x00020030
-wm 32 0x020e056c 0x00020030
-wm 32 0x020e0578 0x00020030
-wm 32 0x020e0588 0x00020030
-wm 32 0x020e0594 0x00020030
-wm 32 0x020e057c 0x00020030
+wm 32 0x020e0798 0x000C0000
+wm 32 0x020e0758 0x00000000
+wm 32 0x020e0588 0x00000030
+wm 32 0x020e0594 0x00000030
+wm 32 0x020e056c 0x00000030
+wm 32 0x020e0578 0x00000030
+wm 32 0x020e074c 0x00000030
+wm 32 0x020e057c 0x00000030
+wm 32 0x020e058c 0x00000000
+wm 32 0x020e059c 0x00000030
+wm 32 0x020e05a0 0x00000030
wm 32 0x020e0590 0x00003000
wm 32 0x020e0598 0x00003000
-wm 32 0x020e058c 0x00000000
-wm 32 0x020e059c 0x00003030
-wm 32 0x020e05a0 0x00003030
-wm 32 0x020e0784 0x00000030
-wm 32 0x020e0788 0x00000030
-wm 32 0x020e0794 0x00000030
-wm 32 0x020e079c 0x00000030
-wm 32 0x020e07a0 0x00000030
-wm 32 0x020e07a4 0x00000030
-wm 32 0x020e07a8 0x00000030
-wm 32 0x020e0748 0x00000030
-wm 32 0x020e074c 0x00000030
+wm 32 0x020e078c 0x00000030
wm 32 0x020e0750 0x00020000
-wm 32 0x020e0758 0x00000000
+wm 32 0x020e05a8 0x00000028
+wm 32 0x020e05b0 0x00000028
+wm 32 0x020e0524 0x00000028
+wm 32 0x020e051c 0x00000028
+wm 32 0x020e0518 0x00000028
+wm 32 0x020e050c 0x00000028
+wm 32 0x020e05b8 0x00000028
+wm 32 0x020e05c0 0x00000028
wm 32 0x020e0774 0x00020000
-wm 32 0x020e078c 0x00000030
-wm 32 0x020e0798 0x000c0000
+wm 32 0x020e0784 0x00000028
+wm 32 0x020e0788 0x00000028
+wm 32 0x020e0794 0x00000028
+wm 32 0x020e079c 0x00000028
+wm 32 0x020e07a0 0x00000028
+wm 32 0x020e07a4 0x00000028
+wm 32 0x020e07a8 0x00000028
+wm 32 0x020e0748 0x00000028
+wm 32 0x020e05ac 0x00000028
+wm 32 0x020e05b4 0x00000028
+wm 32 0x020e0528 0x00000028
+wm 32 0x020e0520 0x00000028
+wm 32 0x020e0514 0x00000028
+wm 32 0x020e0510 0x00000028
+wm 32 0x020e05bc 0x00000028
+wm 32 0x020e05c4 0x00000028
+wm 32 0x021b0800 0xa1390003
+wm 32 0x021b4800 0xa1380003
+wm 32 0x021b080c 0x00110011
+wm 32 0x021b0810 0x00240024
+wm 32 0x021b480c 0x00260038
+wm 32 0x021b4810 0x002C0038
+wm 32 0x021b083c 0x03400350
+wm 32 0x021b0840 0x03440340
+wm 32 0x021b483c 0x034C0354
+wm 32 0x021b4840 0x035C033C
+wm 32 0x021b0848 0x322A2A2A
+wm 32 0x021b4848 0x302C2834
+wm 32 0x021b0850 0x34303834
+wm 32 0x021b4850 0x422A3E36
wm 32 0x021b081c 0x33333333
wm 32 0x021b0820 0x33333333
wm 32 0x021b0824 0x33333333
@@ -50,15 +64,19 @@ wm 32 0x021b481c 0x33333333
wm 32 0x021b4820 0x33333333
wm 32 0x021b4824 0x33333333
wm 32 0x021b4828 0x33333333
-wm 32 0x021b0018 0x00081740
+wm 32 0x021b08b8 0x00000800
+wm 32 0x021b48b8 0x00000800
+wm 32 0x021b0004 0x00025576
+wm 32 0x021b0008 0x09444040
+
+SETUP_MDCFG0
+
+wm 32 0x021b0010 0xff538f64
+wm 32 0x021b0014 0x01ff0124
+wm 32 0x021b0018 0x00091740
wm 32 0x021b001c 0x00008000
-wm 32 0x021b000c 0x555a7975
-wm 32 0x021b0010 0xff538e64
-wm 32 0x021b0014 0x01ff00db
wm 32 0x021b002c 0x000026d2
-wm 32 0x021b0030 0x005b0e21
-wm 32 0x021b0008 0x09444040
-wm 32 0x021b0004 0x00025576
+wm 32 0x021b0030 0x003F1023
SETUP_1GIB_2GIB_4GIB
@@ -66,34 +84,19 @@ wm 32 0x021b001c 0x04088032
wm 32 0x021b001c 0x0408803a
wm 32 0x021b001c 0x00008033
wm 32 0x021b001c 0x0000803b
-wm 32 0x021b001c 0x00428031
-wm 32 0x021b001c 0x00428039
+wm 32 0x021b001c 0x00048031
+wm 32 0x021b001c 0x00048039
wm 32 0x021b001c 0x09408030
wm 32 0x021b001c 0x09408038
wm 32 0x021b001c 0x04008040
wm 32 0x021b001c 0x04008048
-wm 32 0x021b0800 0xa1380003
-wm 32 0x021b4800 0xa1380003
-wm 32 0x021b0020 0x00005800
-wm 32 0x021b0818 0x00022227
-wm 32 0x021b4818 0x00022227
-wm 32 0x021b083c 0x433c033f
-wm 32 0x021b0840 0x033e033d
-wm 32 0x021b483c 0x43490351
-wm 32 0x021b4840 0x0344032f
-wm 32 0x021b0848 0x4a434146
-wm 32 0x021b4848 0x4745434b
-wm 32 0x021b0850 0x3d3d433a
-wm 32 0x021b4850 0x48334b3e
-wm 32 0x021b080c 0x000f0011
-wm 32 0x021b0810 0x00200022
-wm 32 0x021b480c 0x0033002e
-wm 32 0x021b4810 0x003e003b
-wm 32 0x021b08b8 0x00000800
-wm 32 0x021b48b8 0x00000800
-wm 32 0x021b001c 0x00000000
+wm 32 0x021b0020 0x00007800
+wm 32 0x021b0818 0x00011117
+wm 32 0x021b4818 0x00011117
+wm 32 0x021b0004 0x00025576
wm 32 0x021b0404 0x00011006
+wm 32 0x021b001c 0x00000000
wm 32 0x020e0010 0xf00000ff
-wm 32 0x020e0018 0x007f007f
-wm 32 0x020e001c 0x007f007f
+wm 32 0x020e0018 0x007F007F
+wm 32 0x020e001c 0x007F007F
wm 32 0x020c8000 0x80002021
diff --git a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg
index e5a729223f..dfd4336f06 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg
+++ b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg
@@ -1,3 +1,5 @@
+#define SETUP_MDCFG0 \
+ wm 32 0x021b000c 0x8c929b85
#define SETUP_S_DL_512MB_1GB \
wm 32 0x021b0040 0x00000017; \
diff --git a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl.h b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl.h
index 0f83bc9964..8fbd66141a 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl.h
+++ b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl.h
@@ -2,46 +2,60 @@ soc imx6
loadaddr 0x20000000
dcdofs 0x400
-wm 32 0x020e04bc 0x00000030
-wm 32 0x020e04c0 0x00000030
-wm 32 0x020e04c4 0x00000030
-wm 32 0x020e04c8 0x00000030
-wm 32 0x020e04cc 0x00000030
-wm 32 0x020e04d0 0x00000030
-wm 32 0x020e04d4 0x00000030
-wm 32 0x020e04d8 0x00000030
-wm 32 0x020e0470 0x00020030
-wm 32 0x020e0474 0x00020030
-wm 32 0x020e0478 0x00020030
-wm 32 0x020e047c 0x00020030
-wm 32 0x020e0480 0x00020030
-wm 32 0x020e0484 0x00020030
-wm 32 0x020e0488 0x00020030
-wm 32 0x020e048c 0x00020030
-wm 32 0x020e0464 0x00020030
-wm 32 0x020e0490 0x00020030
-wm 32 0x020e04ac 0x00020030
-wm 32 0x020e04b0 0x00020030
-wm 32 0x020e0494 0x00020030
+wm 32 0x020e0774 0x000C0000
+wm 32 0x020e0754 0x00000000
+wm 32 0x020e04ac 0x00000030
+wm 32 0x020e04b0 0x00000030
+wm 32 0x020e0464 0x00000030
+wm 32 0x020e0490 0x00000030
+wm 32 0x020e074c 0x00000030
+wm 32 0x020e0494 0x00000030
+wm 32 0x020e04a0 0x00000000
+wm 32 0x020e04b4 0x00000030
+wm 32 0x020e04b8 0x00000030
wm 32 0x020e04a4 0x00003000
wm 32 0x020e04a8 0x00003000
-wm 32 0x020e04a0 0x00000000
-wm 32 0x020e04b4 0x00003030
-wm 32 0x020e04b8 0x00003030
-wm 32 0x020e0764 0x00000030
-wm 32 0x020e0770 0x00000030
-wm 32 0x020e0778 0x00000030
-wm 32 0x020e077c 0x00000030
-wm 32 0x020e0780 0x00000030
-wm 32 0x020e0784 0x00000030
-wm 32 0x020e078c 0x00000030
-wm 32 0x020e0748 0x00000030
-wm 32 0x020e074c 0x00000030
+wm 32 0x020e076c 0x00000030
wm 32 0x020e0750 0x00020000
-wm 32 0x020e0754 0x00000000
+wm 32 0x020e04bc 0x00000028
+wm 32 0x020e04c0 0x00000028
+wm 32 0x020e04c4 0x00000028
+wm 32 0x020e04c8 0x00000028
+wm 32 0x020e04cc 0x00000028
+wm 32 0x020e04d0 0x00000028
+wm 32 0x020e04d4 0x00000028
+wm 32 0x020e04d8 0x00000028
wm 32 0x020e0760 0x00020000
-wm 32 0x020e076c 0x00000030
-wm 32 0x020e0774 0x000c0000
+wm 32 0x020e0764 0x00000028
+wm 32 0x020e0770 0x00000028
+wm 32 0x020e0778 0x00000028
+wm 32 0x020e077c 0x00000028
+wm 32 0x020e0780 0x00000028
+wm 32 0x020e0784 0x00000028
+wm 32 0x020e078c 0x00000028
+wm 32 0x020e0748 0x00000028
+wm 32 0x020e0470 0x00000028
+wm 32 0x020e0474 0x00000028
+wm 32 0x020e0478 0x00000028
+wm 32 0x020e047c 0x00000028
+wm 32 0x020e0480 0x00000028
+wm 32 0x020e0484 0x00000028
+wm 32 0x020e0488 0x00000028
+wm 32 0x020e048c 0x00000028
+wm 32 0x021b0800 0xa1390003
+wm 32 0x021b4800 0xa1380003
+wm 32 0x021b080c 0x00110011
+wm 32 0x021b0810 0x00240024
+wm 32 0x021b480c 0x00260038
+wm 32 0x021b4810 0x002C0038
+wm 32 0x021b083c 0x02480248
+wm 32 0x021b0840 0x022f022d
+wm 32 0x021b483c 0x02540258
+wm 32 0x021b4840 0x0236021e
+wm 32 0x021b0848 0x332f3033
+wm 32 0x021b4848 0x302d2c35
+wm 32 0x021b0850 0x3030362a
+wm 32 0x021b4850 0x3423372d
wm 32 0x021b081c 0x33333333
wm 32 0x021b0820 0x33333333
wm 32 0x021b0824 0x33333333
@@ -50,15 +64,19 @@ wm 32 0x021b481c 0x33333333
wm 32 0x021b4820 0x33333333
wm 32 0x021b4824 0x33333333
wm 32 0x021b4828 0x33333333
-wm 32 0x021b0018 0x00081740
+wm 32 0x021b08b8 0x00000800
+wm 32 0x021b48b8 0x00000800
+wm 32 0x021b0004 0x00025576
+wm 32 0x021b0008 0x09444040
+
+SETUP_MDCFG0
+
+wm 32 0x021b0010 0xff538f64
+wm 32 0x021b0014 0x01ff0124
+wm 32 0x021b0018 0x00091740
wm 32 0x021b001c 0x00008000
-wm 32 0x021b000c 0x555a7975
-wm 32 0x021b0010 0xff538e64
-wm 32 0x021b0014 0x01ff00db
wm 32 0x021b002c 0x000026d2
-wm 32 0x021b0030 0x005b0e21
-wm 32 0x021b0008 0x09444040
-wm 32 0x021b0004 0x00025576
+wm 32 0x021b0030 0x003F1023
SETUP_S_DL_512MB_1GB
@@ -72,24 +90,9 @@ wm 32 0x021b001c 0x09408030
wm 32 0x021b001c 0x09408038
wm 32 0x021b001c 0x04008040
wm 32 0x021b001c 0x04008048
-wm 32 0x021b0800 0xa1380003
-wm 32 0x021b4800 0xa1380003
-wm 32 0x021b0020 0x00005800
+wm 32 0x021b0020 0x00007800
wm 32 0x021b0818 0x00011117
wm 32 0x021b4818 0x00011117
-wm 32 0x021b083c 0x422D0230
-wm 32 0x021b0840 0x022F022E
-wm 32 0x021b483c 0x4237023D
-wm 32 0x021b4840 0x02340224
-wm 32 0x021b0848 0x38333135
-wm 32 0x021b4848 0x36353338
-wm 32 0x021b0850 0x2E2E332C
-wm 32 0x021b4850 0x3727382F
-wm 32 0x021b080c 0x000C000D
-wm 32 0x021b0810 0x0018001A
-wm 32 0x021b480c 0x00270023
-wm 32 0x021b4810 0x002F002D
-wm 32 0x021b08b8 0x00000800
-wm 32 0x021b48b8 0x00000800
-wm 32 0x021b001c 0x00000000
+wm 32 0x021b0004 0x00025576
wm 32 0x021b0404 0x00011006
+wm 32 0x021b001c 0x00000000
diff --git a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02s-512mb.imxcfg b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02s-512mb.imxcfg
index 3116e3613d..2e428f9fd0 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02s-512mb.imxcfg
+++ b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02s-512mb.imxcfg
@@ -1,3 +1,5 @@
+#define SETUP_MDCFG0 \
+ wm 32 0x021b000c 0x565c9b85
#define SETUP_S_DL_512MB_1GB \
wm 32 0x021b0040 0x00000017; \
diff --git a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
index 1d08f0561a..84014d772a 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
+++ b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
@@ -63,7 +63,7 @@ BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_1G, IMD_TYPE_PARAMETER, "memsize=1024
BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_2G, IMD_TYPE_PARAMETER, "memsize=2048", 0);
BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_4G, IMD_TYPE_PARAMETER, "memsize=4096", 0);
-ENTRY_FUNCTION(start_phytec_pbab01_1gib, r0, r1, r2)
+static void __noreturn start_imx6q_phytec_pbab01_common(uint32_t size)
{
void *fdt;
@@ -71,17 +71,16 @@ ENTRY_FUNCTION(start_phytec_pbab01_1gib, r0, r1, r2)
arm_setup_stack(0x00920000 - 8);
- IMD_USED(phyflex_mx6_memsize_1G);
-
if (IS_ENABLED(CONFIG_DEBUG_LL))
setup_uart();
fdt = __dtb_imx6q_phytec_pbab01_start - get_runtime_offset();
- barebox_arm_entry(0x10000000, SZ_1G, fdt);
+ barebox_arm_entry(0x10000000, size, fdt);
}
-ENTRY_FUNCTION(start_phytec_pbab01_2gib, r0, r1, r2)
+
+static void __noreturn start_imx6dl_phytec_pbab01_common(uint32_t size)
{
void *fdt;
@@ -89,44 +88,37 @@ ENTRY_FUNCTION(start_phytec_pbab01_2gib, r0, r1, r2)
arm_setup_stack(0x00920000 - 8);
- IMD_USED(phyflex_mx6_memsize_2G);
+ fdt = __dtb_imx6dl_phytec_pbab01_start - get_runtime_offset();
- if (IS_ENABLED(CONFIG_DEBUG_LL))
- setup_uart();
+ barebox_arm_entry(0x10000000, size, fdt);
+}
- fdt = __dtb_imx6q_phytec_pbab01_start - get_runtime_offset();
+ENTRY_FUNCTION(start_phytec_pbab01_1gib, r0, r1, r2)
+{
+ IMD_USED(phyflex_mx6_memsize_1G);
- barebox_arm_entry(0x10000000, SZ_2G, fdt);
+ start_imx6q_phytec_pbab01_common(SZ_1G);
}
-ENTRY_FUNCTION(start_phytec_pbab01_4gib, r0, r1, r2)
+ENTRY_FUNCTION(start_phytec_pbab01_2gib, r0, r1, r2)
{
- void *fdt;
-
- imx6_cpu_lowlevel_init();
+ IMD_USED(phyflex_mx6_memsize_2G);
- arm_setup_stack(0x00920000 - 8);
+ start_imx6q_phytec_pbab01_common(SZ_2G);
+}
+ENTRY_FUNCTION(start_phytec_pbab01_4gib, r0, r1, r2)
+{
IMD_USED(phyflex_mx6_memsize_4G);
- fdt = __dtb_imx6q_phytec_pbab01_start - get_runtime_offset();
-
- barebox_arm_entry(0x10000000, 0xEFFFFFF8, fdt);
+ start_imx6q_phytec_pbab01_common(0xEFFFFFF8);
}
ENTRY_FUNCTION(start_phytec_pbab01dl_1gib, r0, r1, r2)
{
- void *fdt;
-
- imx6_cpu_lowlevel_init();
-
- arm_setup_stack(0x00920000 - 8);
-
IMD_USED(phyflex_mx6_memsize_1G);
- fdt = __dtb_imx6dl_phytec_pbab01_start - get_runtime_offset();
-
- barebox_arm_entry(0x10000000, SZ_1G, fdt);
+ start_imx6dl_phytec_pbab01_common(SZ_1G);
}
ENTRY_FUNCTION(start_phytec_pbab01s_512mb, r0, r1, r2)
diff --git a/arch/arm/boards/sama5d4ek/Makefile b/arch/arm/boards/sama5d4ek/Makefile
new file mode 100644
index 0000000000..4363b39243
--- /dev/null
+++ b/arch/arm/boards/sama5d4ek/Makefile
@@ -0,0 +1 @@
+obj-y += sama5d4ek.o
diff --git a/arch/arm/boards/sama5d4ek/env/bin/init_board b/arch/arm/boards/sama5d4ek/env/bin/init_board
new file mode 100644
index 0000000000..f3d417e356
--- /dev/null
+++ b/arch/arm/boards/sama5d4ek/env/bin/init_board
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+PATH=/env/bin
+export PATH
+
+. /env/config
+
+splash=/env/splash.png
+
+if [ -f ${splash} -a -e /dev/fb0 ]; then
+ splash -o ${splash}
+ fb0.enable=1
+fi
+
+exit 1
diff --git a/arch/arm/boards/sama5d4ek/env/config b/arch/arm/boards/sama5d4ek/env/config
new file mode 100644
index 0000000000..1007345b9b
--- /dev/null
+++ b/arch/arm/boards/sama5d4ek/env/config
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+# use 'dhcp' to do dhcp in barebox and in kernel
+# use 'none' if you want to skip kernel ip autoconfiguration
+ip=dhcp
+
+# or set your networking parameters here
+#eth0.ipaddr=a.b.c.d
+#eth0.netmask=a.b.c.d
+#eth0.gateway=a.b.c.d
+#eth0.serverip=a.b.c.d
+
+# can be either 'nfs', 'tftp', 'nor' or 'nand'
+kernel_loc=nfs
+# can be either 'net', 'nor', 'nand' or 'initrd'
+rootfs_loc=net
+# can be either 'nfs', 'tftp', 'nand' or empty
+oftree_loc=nfs
+
+# can be either 'jffs2' or 'ubifs'
+rootfs_type=ubifs
+rootfsimage=root.$rootfs_type
+ubiroot=rootfs
+
+# The image type of the kernel. Can be uimage, zimage, raw, or raw_lzo
+kernelimage=zImage
+#kernelimage=uImage
+#kernelimage=Image
+#kernelimage=Image.lzo
+
+nand_device=atmel_nand
+nand_parts="256k(at91bootstrap),512k(barebox)ro,256k(bareboxenv),256k(bareboxenv2),256k(spare),512k(oftree),6M(kernel),-(rootfs)"
+rootfs_mtdblock_nand=7
+
+m25p80_parts="64k(bootstrap),384k(barebox),256k(bareboxenv),256k(bareboxenv2),128k(oftree),-(updater)"
+
+autoboot_timeout=3
+
+bootargs="console=ttyS0,115200"
+
+# set a fancy prompt (if support is compiled in)
+PS1="\e[1;32mbarebox@\e[1;31m\h:\w\e[0m\n# "
diff --git a/arch/arm/boards/sama5d4ek/sama5d4ek.c b/arch/arm/boards/sama5d4ek/sama5d4ek.c
new file mode 100644
index 0000000000..91cffa3b48
--- /dev/null
+++ b/arch/arm/boards/sama5d4ek/sama5d4ek.c
@@ -0,0 +1,317 @@
+/*
+ * SAMA5D4EK board configureation.
+ *
+ * Copyright (C) 2014 Atmel Corporation,
+ * Bo Shen <voice.shen@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <common.h>
+#include <net.h>
+#include <init.h>
+#include <environment.h>
+#include <asm/armlinux.h>
+#include <partition.h>
+#include <fs.h>
+#include <fcntl.h>
+#include <io.h>
+#include <mach/hardware.h>
+#include <nand.h>
+#include <sizes.h>
+#include <linux/mtd/nand.h>
+#include <mach/board.h>
+#include <mach/at91sam9_smc.h>
+#include <gpio.h>
+#include <mach/iomux.h>
+#include <mach/at91_pmc.h>
+#include <mach/at91_rstc.h>
+#include <mach/at91sam9x5_matrix.h>
+#include <input/qt1070.h>
+#include <readkey.h>
+#include <spi/spi.h>
+#include <linux/clk.h>
+
+#if defined(CONFIG_NAND_ATMEL)
+static struct atmel_nand_data nand_pdata = {
+ .ale = 21,
+ .cle = 22,
+ .det_pin = -EINVAL,
+ .rdy_pin = -EINVAL,
+ .enable_pin = -EINVAL,
+ .ecc_mode = NAND_ECC_HW,
+ .pmecc_sector_size = 512,
+ .pmecc_corr_cap = 8,
+ .on_flash_bbt = 1,
+};
+
+static struct sam9_smc_config cm_nand_smc_config = {
+ .ncs_read_setup = 1,
+ .nrd_setup = 1,
+ .ncs_write_setup = 1,
+ .nwe_setup = 1,
+
+ .ncs_read_pulse = 3,
+ .nrd_pulse = 2,
+ .ncs_write_pulse = 3,
+ .nwe_pulse = 2,
+
+ .read_cycle = 5,
+ .write_cycle = 5,
+
+ .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
+ .tdf_cycles = 3,
+
+ .tclr = 2,
+ .tadl = 7,
+ .tar = 2,
+ .ocms = 0,
+ .trr = 3,
+ .twb = 7,
+ .rbnsel = 3,
+ .nfsel = 1,
+};
+
+static void ek_add_device_nand(void)
+{
+ struct clk *clk = clk_get(NULL, "smc_clk");
+
+ clk_enable(clk);
+
+ /* configure chip-select 3 (NAND) */
+ sama5_smc_configure(0, 3, &cm_nand_smc_config);
+
+ at91_add_device_nand(&nand_pdata);
+}
+#else
+static void ek_add_device_nand(void) {}
+#endif
+
+#if defined(CONFIG_DRIVER_NET_MACB)
+static struct macb_platform_data macb0_pdata = {
+ .phy_interface = PHY_INTERFACE_MODE_RMII,
+ .phy_addr = 0,
+};
+
+static void ek_add_device_eth(void)
+{
+ at91_add_device_eth(0, &macb0_pdata);
+}
+#else
+static void ek_add_device_eth(void) {}
+#endif
+
+#if defined(CONFIG_DRIVER_VIDEO_ATMEL_HLCD)
+static struct fb_videomode at91_tft_vga_modes[] = {
+ {
+ .name = "LG",
+ .refresh = 60,
+ .xres = 800, .yres = 480,
+ .pixclock = KHZ2PICOS(33260),
+
+ .left_margin = 88, .right_margin = 168,
+ .upper_margin = 8, .lower_margin = 37,
+ .hsync_len = 128, .vsync_len = 2,
+
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+};
+
+/* Output mode is TFT 18 bits */
+#define BPP_OUT_DEFAULT_LCDCFG5 (LCDC_LCDCFG5_MODE_OUTPUT_18BPP)
+
+static struct atmel_lcdfb_platform_data ek_lcdc_data = {
+ .lcdcon_is_backlight = true,
+ .default_bpp = 16,
+ .default_dmacon = ATMEL_LCDC_DMAEN,
+ .default_lcdcon2 = BPP_OUT_DEFAULT_LCDCFG5,
+ .guard_time = 9,
+ .lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB,
+ .mode_list = at91_tft_vga_modes,
+ .num_modes = ARRAY_SIZE(at91_tft_vga_modes),
+};
+
+static void ek_add_device_lcdc(void)
+{
+ at91_add_device_lcdc(&ek_lcdc_data);
+}
+#else
+static void ek_add_device_lcdc(void) {}
+#endif
+
+#if defined(CONFIG_MCI_ATMEL)
+static struct atmel_mci_platform_data mci1_data = {
+ .bus_width = 4,
+ .detect_pin = AT91_PIN_PE6,
+ .wp_pin = -EINVAL,
+};
+
+static void ek_add_device_mci(void)
+{
+ /* MMC1 */
+ at91_add_device_mci(1, &mci1_data);
+
+ /* power on MCI1 */
+ at91_set_gpio_output(AT91_PIN_PE15, 0);
+}
+#else
+static void ek_add_device_mci(void) {}
+#endif
+
+#if defined(CONFIG_I2C_GPIO)
+struct qt1070_platform_data qt1070_pdata = {
+ .irq_pin = AT91_PIN_PE25,
+};
+
+static struct i2c_board_info i2c_devices[] = {
+ {
+ .platform_data = &qt1070_pdata,
+ I2C_BOARD_INFO("qt1070", 0x1b),
+ },
+};
+
+static void ek_add_device_i2c(void)
+{
+ at91_set_gpio_input(qt1070_pdata.irq_pin, 0);
+ at91_set_deglitch(qt1070_pdata.irq_pin, 1);
+ at91_add_device_i2c(0, i2c_devices, ARRAY_SIZE(i2c_devices));
+}
+#else
+static void ek_add_device_i2c(void) {}
+#endif
+
+#if defined(CONFIG_DRIVER_SPI_ATMEL)
+static const struct spi_board_info ek_spi_devices[] = {
+ {
+ .name = "m25p80",
+ .chip_select = 0,
+ .max_speed_hz = 30 * 1000 * 1000,
+ .bus_num = 0,
+ }
+};
+
+static unsigned spi0_standard_cs[] = { AT91_PIN_PC3 };
+static struct at91_spi_platform_data spi_pdata = {
+ .chipselect = spi0_standard_cs,
+ .num_chipselect = ARRAY_SIZE(spi0_standard_cs),
+};
+
+static void ek_add_device_spi(void)
+{
+ spi_register_board_info(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+ at91_add_device_spi(0, &spi_pdata);
+}
+#else
+static void ek_add_device_spi(void) {}
+#endif
+
+#ifdef CONFIG_LED_GPIO
+struct gpio_led leds[] = {
+ {
+ .gpio = AT91_PIN_PE28,
+ .active_low = 0,
+ .led = {
+ .name = "d8",
+ },
+ }, {
+ .gpio = AT91_PIN_PE9,
+ .active_low = 1,
+ .led = {
+ .name = "d9",
+ },
+ }, {
+ .gpio = AT91_PIN_PE8,
+ .active_low = 0,
+ .led = {
+ .name = "d10",
+ },
+ },
+};
+
+static void ek_add_led(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(leds); i++) {
+ at91_set_gpio_output(leds[i].gpio, leds[i].active_low);
+ led_gpio_register(&leds[i]);
+ }
+ led_set_trigger(LED_TRIGGER_HEARTBEAT, &leds[0].led);
+}
+#else
+static void ek_add_led(void) {}
+#endif
+
+static int sama5d4ek_mem_init(void)
+{
+ at91_add_device_sdram(0);
+
+ return 0;
+}
+mem_initcall(sama5d4ek_mem_init);
+
+static const struct devfs_partition sama5d4ek_nand0_partitions[] = {
+ {
+ .offset = 0x00000,
+ .size = SZ_256K,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "at91bootstrap_raw",
+ .bbname = "at91bootstrap",
+ }, {
+ .offset = DEVFS_PARTITION_APPEND,
+ .size = SZ_512K,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "bootloader_raw",
+ .bbname = "bootloader",
+ }, {
+ .offset = DEVFS_PARTITION_APPEND,
+ .size = SZ_256K,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "env_raw",
+ .bbname = "env0",
+ }, {
+ .offset = DEVFS_PARTITION_APPEND,
+ .size = SZ_256K,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "env_raw1",
+ .bbname = "env1",
+ }, {
+ /* sentinel */
+ }
+};
+
+static int sama5d4ek_devices_init(void)
+{
+ ek_add_device_i2c();
+ ek_add_device_nand();
+ ek_add_led();
+ ek_add_device_eth();
+ ek_add_device_spi();
+ ek_add_device_mci();
+ ek_add_device_lcdc();
+
+ devfs_create_partitions("nand0", sama5d4ek_nand0_partitions);
+
+ return 0;
+}
+device_initcall(sama5d4ek_devices_init);
+
+static int sama5d4ek_console_init(void)
+{
+ barebox_set_model("Atmel sama5d4ek");
+ barebox_set_hostname("sama5d4ek");
+
+ at91_register_uart(4, 0);
+
+ return 0;
+}
+console_initcall(sama5d4ek_console_init);
+
+static int sama5d4ek_main_clock(void)
+{
+ at91_set_main_clock(12000000);
+
+ return 0;
+}
+pure_initcall(sama5d4ek_main_clock);
diff --git a/arch/arm/configs/am335x_defconfig b/arch/arm/configs/am335x_defconfig
index 4dc6cbf127..6ef9c838fd 100644
--- a/arch/arm/configs/am335x_defconfig
+++ b/arch/arm/configs/am335x_defconfig
@@ -1,7 +1,8 @@
CONFIG_ARCH_OMAP=y
CONFIG_BAREBOX_UPDATE_AM33XX_SPI_NOR_MLO=y
-CONFIG_BAREBOX_UPDATE_AM33XX_NAND_XLOADSLOTS=y
+CONFIG_BAREBOX_UPDATE_AM33XX_NAND=y
CONFIG_OMAP_MULTI_BOARDS=y
+CONFIG_MACH_AFI_GF=y
CONFIG_MACH_BEAGLEBONE=y
CONFIG_MACH_PCM051=y
CONFIG_THUMB2_BAREBOX=y
@@ -74,6 +75,7 @@ CONFIG_CMD_I2C=y
CONFIG_CMD_LED=y
CONFIG_CMD_SPI=y
CONFIG_CMD_LED_TRIGGER=y
+CONFIG_CMD_USBGADGET=y
CONFIG_CMD_BAREBOX_UPDATE=y
CONFIG_CMD_OF_NODE=y
CONFIG_CMD_OF_PROPERTY=y
@@ -88,6 +90,9 @@ CONFIG_OF_BAREBOX_DRIVERS=y
CONFIG_DRIVER_SERIAL_NS16550=y
CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS=y
CONFIG_DRIVER_NET_CPSW=y
+CONFIG_NET_USB=y
+CONFIG_NET_USB_ASIX=y
+CONFIG_NET_USB_SMSC95XX=y
CONFIG_DRIVER_SPI_OMAP3=y
CONFIG_I2C=y
CONFIG_I2C_OMAP=y
@@ -97,6 +102,15 @@ CONFIG_NAND=y
CONFIG_NAND_OMAP_GPMC=y
CONFIG_MTD_UBI=y
CONFIG_USB_HOST=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DFU=y
+CONFIG_USB_GADGET_SERIAL=y
+CONFIG_USB_GADGET_FASTBOOT=y
+CONFIG_USB_MUSB=y
+CONFIG_USB_MUSB_AM335X=y
+CONFIG_USB_MUSB_HOST=y
+CONFIG_USB_MUSB_GADGET=y
CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
CONFIG_MCI_OMAP_HSMMC=y
diff --git a/arch/arm/configs/am335x_mlo_defconfig b/arch/arm/configs/am335x_mlo_defconfig
index 19f78d0ae8..dee8c5bd43 100644
--- a/arch/arm/configs/am335x_mlo_defconfig
+++ b/arch/arm/configs/am335x_mlo_defconfig
@@ -1,6 +1,7 @@
CONFIG_ARCH_OMAP=y
CONFIG_OMAP_BUILD_IFT=y
CONFIG_OMAP_MULTI_BOARDS=y
+CONFIG_MACH_AFI_GF=y
CONFIG_MACH_BEAGLEBONE=y
CONFIG_MACH_PCM051=y
CONFIG_THUMB2_BAREBOX=y
diff --git a/arch/arm/configs/eukrea_cpuimx35_defconfig b/arch/arm/configs/eukrea_cpuimx35_defconfig
index 7569cde6f5..4c83102ce1 100644
--- a/arch/arm/configs/eukrea_cpuimx35_defconfig
+++ b/arch/arm/configs/eukrea_cpuimx35_defconfig
@@ -1,71 +1,81 @@
CONFIG_ARCH_IMX=y
-CONFIG_CACHE_L2X0=y
-CONFIG_ARCH_IMX35=y
+CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000
CONFIG_MACH_EUKREA_CPUIMX35=y
CONFIG_IMX_IIM=y
CONFIG_IMX_IIM_FUSE_BLOW=y
CONFIG_AEABI=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_PBL_IMAGE=y
+CONFIG_PBL_RELOCATABLE=y
CONFIG_MMU=y
-CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000
CONFIG_MALLOC_SIZE=0x800000
CONFIG_EXPERIMENTAL=y
CONFIG_MALLOC_TLSF=y
-CONFIG_LONGHELP=y
+CONFIG_RELOCATABLE=y
CONFIG_GLOB=y
CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
-# CONFIG_CONSOLE_ACTIVATE_FIRST is not set
CONFIG_CONSOLE_ACTIVATE_ALL=y
+CONFIG_DEFAULT_COMPRESSION_LZO=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/eukrea_cpuimx35/env"
-CONFIG_CMD_EDIT=y
-CONFIG_CMD_SLEEP=y
-CONFIG_CMD_SAVEENV=y
-CONFIG_CMD_EXPORT=y
-CONFIG_CMD_PRINTENV=y
-CONFIG_CMD_READLINE=y
-CONFIG_CMD_AUTOMOUNT=y
-CONFIG_CMD_ECHO_E=y
-CONFIG_CMD_LOADB=y
-CONFIG_CMD_MEMINFO=y
+CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
-CONFIG_CMD_MTEST=y
-CONFIG_CMD_FLASH=y
+CONFIG_CMD_IMD=y
+CONFIG_CMD_MEMINFO=y
CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_BOOTM_VERBOSE=y
CONFIG_CMD_BOOTM_INITRD=y
CONFIG_CMD_BOOTM_OFTREE=y
CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
-CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
-CONFIG_CMD_OFTREE=y
-CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_RESET=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_AUTOMOUNT=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_PRINTENV=y
CONFIG_CMD_MAGICVAR=y
CONFIG_CMD_MAGICVAR_HELP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_UNCOMPRESS=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
CONFIG_CMD_SPLASH=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MM=y
+CONFIG_CMD_CLK=y
+CONFIG_CMD_DETECT=y
+CONFIG_CMD_FLASH=y
CONFIG_CMD_GPIO=y
-CONFIG_CMD_UNCOMPRESS=y
CONFIG_CMD_I2C=y
CONFIG_CMD_LED=y
CONFIG_CMD_LED_TRIGGER=y
+CONFIG_CMD_USBGADGET=y
+CONFIG_CMD_OFTREE=y
CONFIG_NET=y
-CONFIG_CMD_DHCP=y
CONFIG_NET_NFS=y
-CONFIG_CMD_PING=y
-CONFIG_CMD_TFTP=y
-CONFIG_FS_TFTP=y
CONFIG_NET_NETCONSOLE=y
CONFIG_DRIVER_NET_FEC_IMX=y
+CONFIG_SMSC_PHY=y
# CONFIG_SPI is not set
CONFIG_I2C=y
CONFIG_I2C_IMX=y
CONFIG_MTD=y
CONFIG_MTD_RAW_DEVICE=y
CONFIG_NAND=y
+CONFIG_NAND_ALLOW_ERASE_BAD=y
CONFIG_NAND_IMX=y
+CONFIG_NAND_IMX_BBM=y
CONFIG_USB_HOST=y
CONFIG_USB_EHCI=y
CONFIG_USB_STORAGE=y
@@ -79,6 +89,7 @@ CONFIG_MCI_IMX_ESDHC=y
CONFIG_LED=y
CONFIG_LED_GPIO=y
CONFIG_LED_TRIGGERS=y
+CONFIG_FS_TFTP=y
CONFIG_FS_FAT=y
CONFIG_FS_FAT_WRITE=y
CONFIG_FS_FAT_LFN=y
diff --git a/arch/arm/configs/globalscale_guruplug_defconfig b/arch/arm/configs/globalscale_guruplug_defconfig
deleted file mode 100644
index d21de45c5d..0000000000
--- a/arch/arm/configs/globalscale_guruplug_defconfig
+++ /dev/null
@@ -1,6 +0,0 @@
-CONFIG_ARCH_MVEBU=y
-CONFIG_ARCH_KIRKWOOD=y
-CONFIG_TEXT_BASE=0x2000000
-CONFIG_DEBUG_LL=y
-CONFIG_CMD_RESET=y
-CONFIG_DRIVER_SERIAL_NS16550=y
diff --git a/arch/arm/configs/globalscale_mirabox_defconfig b/arch/arm/configs/globalscale_mirabox_defconfig
deleted file mode 100644
index ed9d94d867..0000000000
--- a/arch/arm/configs/globalscale_mirabox_defconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-CONFIG_ARCH_MVEBU=y
-CONFIG_AEABI=y
-CONFIG_DEBUG_LL=y
-CONFIG_CMD_LOADY=y
-CONFIG_CMD_LOADS=y
-CONFIG_CMD_RESET=y
-CONFIG_CMD_CLK=y
-CONFIG_DRIVER_SERIAL_NS16550=y
diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
index cad47fdff3..2c8eb856cf 100644
--- a/arch/arm/configs/imx_v7_defconfig
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -1,6 +1,7 @@
CONFIG_ARCH_IMX=y
CONFIG_IMX_MULTI_BOARDS=y
CONFIG_MACH_EFIKA_MX_SMARTBOOK=y
+CONFIG_MACH_EMBEDSKY_E9=y
CONFIG_MACH_FREESCALE_MX51_PDK=y
CONFIG_MACH_FREESCALE_MX53_LOCO=y
CONFIG_MACH_TQMA53=y
@@ -16,10 +17,10 @@ CONFIG_MACH_SABRELITE=y
CONFIG_MACH_SABRESD=y
CONFIG_MACH_NITROGEN6X=y
CONFIG_MACH_SOLIDRUN_MICROSOM=y
-CONFIG_MACH_EMBEDSKY_E9=y
CONFIG_MACH_EMBEST_RIOTBOARD=y
CONFIG_MACH_UDOO=y
CONFIG_MACH_VARISCITE_MX6=y
+CONFIG_MACH_GW_VENTANA=y
CONFIG_IMX_IIM=y
CONFIG_IMX_IIM_FUSE_BLOW=y
CONFIG_IMX_OCOTP=y
diff --git a/arch/arm/configs/marvell_armada_xp_gp_defconfig b/arch/arm/configs/marvell_armada_xp_gp_defconfig
deleted file mode 100644
index 5a7ef52b5f..0000000000
--- a/arch/arm/configs/marvell_armada_xp_gp_defconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-CONFIG_ARCH_MVEBU=y
-CONFIG_ARCH_ARMADA_XP=y
-CONFIG_MACH_MARVELL_ARMADA_XP_GP=y
-CONFIG_AEABI=y
-CONFIG_DEBUG_LL=y
-CONFIG_CMD_LOADY=y
-CONFIG_CMD_LOADS=y
-CONFIG_CMD_RESET=y
-CONFIG_CMD_CLK=y
-CONFIG_DRIVER_SERIAL_NS16550=y
diff --git a/arch/arm/configs/solidrun_cubox_defconfig b/arch/arm/configs/mvebu_defconfig
index 7ba42a98ef..253cb0934d 100644
--- a/arch/arm/configs/solidrun_cubox_defconfig
+++ b/arch/arm/configs/mvebu_defconfig
@@ -1,84 +1,101 @@
CONFIG_ARCH_MVEBU=y
-CONFIG_ARCH_DOVE=y
-CONFIG_THUMB2_BAREBOX=y
-CONFIG_CMD_ARM_MMUINFO=y
+CONFIG_MACH_GLOBALSCALE_MIRABOX=y
+CONFIG_MACH_PLATHOME_OPENBLOCKS_AX3=y
+CONFIG_MACH_MARVELL_ARMADA_XP_GP=y
+CONFIG_MACH_SOLIDRUN_CUBOX=y
+CONFIG_MACH_GLOBALSCALE_GURUPLUG=y
+CONFIG_MACH_USI_TOPKICK=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
-CONFIG_ARM_UNWIND=y
-CONFIG_MMU=y
CONFIG_TEXT_BASE=0x0
CONFIG_MALLOC_SIZE=0x0
CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
CONFIG_RELOCATABLE=y
-CONFIG_LONGHELP=y
CONFIG_HUSH_FANCY_PROMPT=y
-CONFIG_CMD_GETOPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
+CONFIG_BLSPEC=y
+CONFIG_IMD_TARGET=y
CONFIG_CONSOLE_ACTIVATE_NONE=y
CONFIG_PARTITION_DISK_EFI=y
-CONFIG_DEBUG_LL=y
-CONFIG_CMD_EDIT=y
-CONFIG_CMD_SLEEP=y
-CONFIG_CMD_MSLEEP=y
-CONFIG_CMD_SAVEENV=y
-CONFIG_CMD_EXPORT=y
-CONFIG_CMD_PRINTENV=y
-CONFIG_CMD_READLINE=y
-CONFIG_CMD_LET=y
-CONFIG_CMD_MENU=y
-CONFIG_CMD_MENU_MANAGEMENT=y
-CONFIG_CMD_TIME=y
-CONFIG_CMD_GLOBAL=y
-CONFIG_CMD_AUTOMOUNT=y
-CONFIG_CMD_BASENAME=y
-CONFIG_CMD_DIRNAME=y
-CONFIG_CMD_LN=y
-CONFIG_CMD_READLINK=y
-CONFIG_CMD_FILETYPE=y
-CONFIG_CMD_ECHO_E=y
-CONFIG_CMD_LOADY=y
-CONFIG_CMD_LOADS=y
-CONFIG_CMD_MEMINFO=y
+CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
-CONFIG_CMD_CRC=y
-CONFIG_CMD_CRC_CMP=y
-CONFIG_CMD_MD5SUM=y
-CONFIG_CMD_SHA1SUM=y
-CONFIG_CMD_SHA256SUM=y
-CONFIG_CMD_SHA224SUM=y
+CONFIG_CMD_IMD=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_ARM_MMUINFO=y
+CONFIG_CMD_BOOT=y
CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_BOOTM_VERBOSE=y
CONFIG_CMD_BOOTM_INITRD=y
CONFIG_CMD_BOOTM_OFTREE=y
CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
-CONFIG_CMD_UIMAGE=y
-CONFIG_FLEXIBLE_BOOTARGS=y
-CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
-CONFIG_CMD_OFTREE=y
-CONFIG_CMD_OF_PROPERTY=y
-CONFIG_CMD_OF_NODE=y
-CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_LOADS=y
+CONFIG_CMD_LOADY=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_UIMAGE=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_AUTOMOUNT=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_GLOBAL=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_PRINTENV=y
CONFIG_CMD_MAGICVAR=y
CONFIG_CMD_MAGICVAR_HELP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_BASENAME=y
+CONFIG_CMD_DIRNAME=y
+CONFIG_CMD_FILETYPE=y
+CONFIG_CMD_LN=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_READLINK=y
+CONFIG_CMD_SHA1SUM=y
+CONFIG_CMD_SHA224SUM=y
+CONFIG_CMD_SHA256SUM=y
CONFIG_CMD_UNCOMPRESS=y
+CONFIG_CMD_GETOPT=y
+CONFIG_CMD_LET=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_READF=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_HOST=y
+CONFIG_NET_CMD_IFUP=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_MENU=y
+CONFIG_CMD_MENU_MANAGEMENT=y
+CONFIG_CMD_MENUTREE=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_CRC_CMP=y
+CONFIG_CMD_CLK=y
+CONFIG_CMD_DETECT=y
CONFIG_CMD_I2C=y
-CONFIG_CMD_SPI=y
CONFIG_CMD_LED=y
+CONFIG_CMD_SPI=y
CONFIG_CMD_LED_TRIGGER=y
-CONFIG_CMD_CLK=y
-CONFIG_CMD_DETECT=y
CONFIG_CMD_WD=y
+CONFIG_CMD_OF_NODE=y
+CONFIG_CMD_OF_PROPERTY=y
+CONFIG_CMD_OFTREE=y
+CONFIG_CMD_TIME=y
+CONFIG_NET=y
CONFIG_OFDEVICE=y
CONFIG_OF_BAREBOX_DRIVERS=y
CONFIG_DRIVER_SERIAL_NS16550=y
+CONFIG_DRIVER_NET_ORION=y
+CONFIG_MARVELL_PHY=y
CONFIG_DRIVER_SPI_MVEBU=y
CONFIG_I2C=y
+CONFIG_I2C_MV64XXX=y
CONFIG_MTD=y
CONFIG_MTD_M25P80=y
+CONFIG_NAND=y
+CONFIG_NAND_ORION=y
CONFIG_DISK_AHCI=y
CONFIG_USB_HOST=y
CONFIG_USB_EHCI=y
@@ -87,8 +104,14 @@ CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
CONFIG_MCI_MMC_BOOT_PARTITIONS=y
CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_GPIO_OF=y
CONFIG_LED_TRIGGERS=y
+CONFIG_EEPROM_AT25=y
+CONFIG_KEYBOARD_GPIO=y
CONFIG_WATCHDOG=y
+CONFIG_GPIO_ORION=y
+CONFIG_PCI_MVEBU=y
CONFIG_FS_CRAMFS=y
CONFIG_FS_EXT4=y
CONFIG_FS_FAT=y
diff --git a/arch/arm/configs/plathome_openblocks_ax3_defconfig b/arch/arm/configs/plathome_openblocks_ax3_defconfig
deleted file mode 100644
index 95449c9741..0000000000
--- a/arch/arm/configs/plathome_openblocks_ax3_defconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-CONFIG_ARCH_MVEBU=y
-CONFIG_ARCH_ARMADA_XP=y
-CONFIG_AEABI=y
-CONFIG_DEBUG_LL=y
-CONFIG_CMD_LOADY=y
-CONFIG_CMD_LOADS=y
-CONFIG_CMD_RESET=y
-CONFIG_CMD_CLK=y
-CONFIG_DRIVER_SERIAL_NS16550=y
diff --git a/arch/arm/configs/sama5d4ek_defconfig b/arch/arm/configs/sama5d4ek_defconfig
new file mode 100644
index 0000000000..bbf254abf0
--- /dev/null
+++ b/arch/arm/configs/sama5d4ek_defconfig
@@ -0,0 +1,85 @@
+CONFIG_ARCH_SAMA5D4=y
+CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x60000
+CONFIG_AEABI=y
+CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_PBL_IMAGE=y
+CONFIG_MMU=y
+CONFIG_TEXT_BASE=0x26f00000
+CONFIG_MALLOC_SIZE=0xA00000
+CONFIG_EXPERIMENTAL=y
+CONFIG_MALLOC_TLSF=y
+CONFIG_PROMPT="A5D4EK:"
+CONFIG_GLOB=y
+CONFIG_PROMPT_HUSH_PS2="y"
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_CONSOLE_ACTIVATE_ALL=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
+CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/sama5d4ek/env"
+CONFIG_DEBUG_INFO=y
+# CONFIG_CMD_ARM_CPUINFO is not set
+CONFIG_LONGHELP=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+# CONFIG_CMD_BOOTU is not set
+CONFIG_CMD_GO=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_UIMAGE=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_FILETYPE=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_SPLASH=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_OFTREE=y
+CONFIG_NET=y
+CONFIG_NET_NFS=y
+CONFIG_OFDEVICE=y
+CONFIG_DRIVER_NET_MACB=y
+CONFIG_MICREL_PHY=y
+CONFIG_DRIVER_SPI_ATMEL=y
+CONFIG_I2C=y
+CONFIG_I2C_GPIO=y
+CONFIG_MTD=y
+CONFIG_MTD_RAW_DEVICE=y
+CONFIG_MTD_M25P80=y
+CONFIG_NAND=y
+# CONFIG_NAND_ECC_SOFT is not set
+# CONFIG_NAND_ECC_HW_SYNDROME is not set
+CONFIG_NAND_ATMEL=y
+CONFIG_NAND_ATMEL_PMECC=y
+CONFIG_VIDEO=y
+CONFIG_DRIVER_VIDEO_ATMEL_HLCD=y
+CONFIG_MCI=y
+CONFIG_MCI_STARTUP=y
+CONFIG_MCI_ATMEL=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_TRIGGERS=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_QT1070=y
+CONFIG_FS_EXT4=y
+CONFIG_FS_TFTP=y
+CONFIG_FS_FAT=y
+CONFIG_FS_FAT_WRITE=y
+CONFIG_FS_FAT_LFN=y
+CONFIG_PNG=y
diff --git a/arch/arm/configs/tqma53_defconfig b/arch/arm/configs/tqma53_defconfig
index f163b7c701..144abbf5fb 100644
--- a/arch/arm/configs/tqma53_defconfig
+++ b/arch/arm/configs/tqma53_defconfig
@@ -19,7 +19,6 @@ CONFIG_AUTO_COMPLETE=y
CONFIG_BLSPEC=y
CONFIG_CONSOLE_ACTIVATE_NONE=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
-CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/tqma53/env/"
CONFIG_DEBUG_INFO=y
CONFIG_CMD_EDIT=y
CONFIG_CMD_SLEEP=y
diff --git a/arch/arm/configs/tx53stk5_defconfig b/arch/arm/configs/tx53stk5_defconfig
index fc6a9a69ff..5751623295 100644
--- a/arch/arm/configs/tx53stk5_defconfig
+++ b/arch/arm/configs/tx53stk5_defconfig
@@ -20,7 +20,6 @@ CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
-CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/karo-tx53/env"
CONFIG_RESET_SOURCE=y
CONFIG_CMD_EDIT=y
CONFIG_CMD_SLEEP=y
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index dcf014db97..3fcd5f1cc0 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -5,6 +5,7 @@ obj-dtb-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB).dtb.o
# created.
obj-y += empty.o
+pbl-dtb-$(CONFIG_MACH_AFI_GF) += am335x-afi-gf.dtb.o
pbl-dtb-$(CONFIG_MACH_BEAGLEBONE) += am335x-bone.dtb.o am335x-boneblack.dtb.o am335x-bone-common.dtb.o
pbl-dtb-$(CONFIG_MACH_DFI_FS700_M60) += imx6q-dfi-fs700-m60-6q.dtb.o imx6dl-dfi-fs700-m60-6s.dtb.o
pbl-dtb-$(CONFIG_MACH_EFIKA_MX_SMARTBOOK) += imx51-genesi-efika-sb.dtb.o
@@ -17,6 +18,7 @@ pbl-dtb-$(CONFIG_MACH_GK802) += imx6q-gk802.dtb.o
pbl-dtb-$(CONFIG_MACH_GLOBALSCALE_GURUPLUG) += kirkwood-guruplug-server-plus-bb.dtb.o
pbl-dtb-$(CONFIG_MACH_GLOBALSCALE_MIRABOX) += armada-370-mirabox-bb.dtb.o
pbl-dtb-$(CONFIG_MACH_GUF_SANTARO) += imx6q-guf-santaro.dtb.o
+pbl-dtb-$(CONFIG_MACH_GW_VENTANA) += imx6q-gw54xx.dtb.o
pbl-dtb-$(CONFIG_MACH_MARVELL_ARMADA_XP_GP) += armada-xp-gp-bb.dtb.o
pbl-dtb-$(CONFIG_MACH_NITROGEN6X) += imx6q-nitrogen6x.dtb.o imx6dl-nitrogen6x.dtb.o
pbl-dtb-$(CONFIG_MACH_NVIDIA_BEAVER) += tegra30-beaver.dtb.o
@@ -41,6 +43,7 @@ pbl-dtb-$(CONFIG_MACH_TOSHIBA_AC100) += tegra20-paz00.dtb.o
pbl-dtb-$(CONFIG_MACH_TQMA53) += imx53-mba53.dtb.o
pbl-dtb-$(CONFIG_MACH_TQMA6X) += imx6dl-mba6x.dtb.o imx6q-mba6x.dtb.o
pbl-dtb-$(CONFIG_MACH_TX25) += imx25-karo-tx25.dtb.o
+pbl-dtb-$(CONFIG_MACH_TX6X) += imx6dl-tx6u-801x.dtb.o
pbl-dtb-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o
pbl-dtb-$(CONFIG_MACH_USI_TOPKICK) += kirkwood-topkick-bb.dtb.o
pbl-dtb-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o
diff --git a/arch/arm/dts/am335x-afi-gf.dts b/arch/arm/dts/am335x-afi-gf.dts
new file mode 100644
index 0000000000..479c6cf170
--- /dev/null
+++ b/arch/arm/dts/am335x-afi-gf.dts
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) Jan Luebbe <jlu@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+
+/ {
+ model = "GF";
+ compatible = "afi,gf", "ti,am33xx";
+
+ chosen {
+ stdout-path = &uart2;
+
+ environment@0 {
+ compatible = "barebox,environment";
+ device-path = &environment_spi;
+ };
+ };
+
+ cpus {
+ cpu@0 {
+ cpu0-supply = <&vdd1_reg>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x10000000>; /* 128 MB */
+ };
+
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ power {
+ label = "power";
+ linux,code = <116>; /* KEY_POWER */
+ gpios = <&gpio0 26 1>;
+ gpio-key,wakeup;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led1 {
+ gpios = <&gpio1 18 0>;
+ linux,default-trigger = "mmc0";
+ default-state = "off";
+ };
+
+ led2 {
+ gpios = <&gpio1 19 0>;
+ linux,default-trigger = "cpu0";
+ default-state = "off";
+ };
+
+ led3 {
+ gpios = <&gpio0 22 0>;
+ linux,default-trigger = "heartbeat";
+ default-state = "off";
+ };
+ };
+
+ onewire-internal {
+ compatible = "w1-gpio";
+ gpios = <&gpio1 3 0>;
+ };
+
+ vdd_5v_reg: vdd-5v@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-boot-on;
+ };
+};
+
+&uart0 {
+ status = "disabled";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins>;
+};
+
+&uart2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_pins>;
+};
+
+&i2c0 {
+ status = "okay";
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+
+ tps: tps@2d {
+ reg = <0x2d>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <27 1>;
+ };
+};
+
+&i2c1 {
+ status = "okay";
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins>;
+
+ ds2483@18 {
+ compatible = "maxim,ds2482";
+ reg = <0x18>;
+ };
+};
+
+&i2c2 {
+ status = "okay";
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins>;
+};
+
+/include/ "tps65910.dtsi"
+
+&tps {
+ vcc1-supply = <&vdd_5v_reg>;
+ vcc2-supply = <&vdd_5v_reg>;
+ vcc3-supply = <&vdd_5v_reg>;
+ vcc4-supply = <&vdd_5v_reg>;
+ vcc5-supply = <&vdd_5v_reg>;
+ vcc6-supply = <&vdd_5v_reg>;
+ vcc7-supply = <&vdd_5v_reg>;
+ vccio-supply = <&vdd_5v_reg>;
+
+ ti,system-power-controller;
+
+ ti,en-ck32k-xtal;
+
+ regulators {
+ vrtc_reg: regulator@0 {
+ regulator-always-on;
+ };
+
+ vio_reg: regulator@1 {
+ /* VDD_DDR supplies LPDDR */
+ regulator-name = "vdd_ddr";
+ regulator-always-on;
+ };
+
+ vdd1_reg: regulator@2 {
+ /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+ regulator-name = "vdd_mpu";
+ regulator-min-microvolt = <912500>;
+ regulator-max-microvolt = <1312500>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vdd2_reg: regulator@3 {
+ /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+ regulator-name = "vdd_core";
+ regulator-min-microvolt = <912500>;
+ regulator-max-microvolt = <1150000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vdd3_reg: regulator@4 {
+ /* VDD_BOOST is not connected */
+ };
+
+ vdig1_reg: regulator@5 {
+ /* VDD_DIG1 is not connected */
+ };
+
+ vdig2_reg: regulator@6 {
+ /* VDD_DIG2 supplies some SoC terminals */
+ regulator-always-on;
+ };
+
+ vpll_reg: regulator@7 {
+ /* VDD_PLL is not connected */
+ };
+
+ vdac_reg: regulator@8 {
+ /* VDD_DAC is not connected */
+ };
+
+ vaux1_reg: regulator@9 {
+ /* VDD_AUX1 supplies USB */
+ regulator-always-on;
+ };
+
+ vaux2_reg: regulator@10 {
+ /* VDD_AUX2 supplies various ICs */
+ regulator-always-on;
+ };
+
+ vaux33_reg: regulator@11 {
+ /* VDD_AUX33 supplies USB */
+ regulator-always-on;
+ };
+
+ vmmc_reg: regulator@12 {
+ /* VDD_MMC supplies uSD and ethernet phy */
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vbb_reg: regulator@13 {
+ /* Backup Battery regulator */
+ regulator-min-microvolt = <3150000>;
+ regulator-max-microvolt = <3150000>;
+ regulator-always-on;
+ };
+ };
+};
+
+&mmc1 {
+ vmmc-supply = <&vmmc_reg>;
+ cd-gpios = <&gpio1 14 1>;
+ status = "okay";
+};
+
+&edma {
+ ti,edma-xbar-event-map = <32 12>;
+};
+
+&dcan0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&dcan0_pins>;
+};
+
+&gpio0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio0_pins>;
+};
+
+&gpio1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio1_pins>;
+};
+
+&gpio2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio2_pins>;
+};
+
+&gpio3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio3_pins>;
+};
+
+&spi0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>;
+
+ /* uncomment for unmodified Fee */
+ /* ti,pindir-d0-out-d1-in; */
+
+ spi_nor: nor@0 {
+ compatible = "nymonyx,n25q128a13";
+ spi-max-frequency = <48000000>; // actually 108 MHz
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "mlo";
+ reg = <0x0 0x20000>;
+ };
+
+ partition@20000 {
+ label = "boot";
+ reg = <0x20000 0x100000>;
+ };
+
+ environment_spi: partition@120000 {
+ label = "environment";
+ reg = <0x120000 0x20000>;
+ };
+ };
+
+ fram@1 {
+ compatible = "ramtron,fm25cl64b", "atmel,at25";
+ spi-max-frequency = <20000000>;
+ reg = <1>;
+ size = <8192>;
+ pagesize = <8192>; // FIXME - is this correct?
+ address-width = <16>;
+ };
+};
+
+&spi1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins>;
+
+ ti,pindir-d0-out-d1-in;
+
+ spi1_0: spidev@0 {
+ compatible = "linux,spidev";
+ reg = <0>;
+ spi-max-frequency = <10000000>; // FIXME
+ };
+
+ spi1_1: spidev@1 {
+ compatible = "linux,spidev";
+ reg = <1>;
+ spi-max-frequency = <10000000>; // FIXME
+ };
+};
+
+&usb {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb0_pins &usb1_pins>;
+};
+
+&usb_ctrl_mod {
+ status = "okay";
+};
+
+&usb0 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
+
+&usb0_phy {
+ status = "okay";
+};
+
+&usb1_phy {
+ status = "okay";
+};
+
+&mac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&eth_pins>;
+ status = "okay";
+};
+
+&cpsw_emac0 {
+ phy_id = <&davinci_mdio>, <0>;
+ phy-mode = "rmii";
+};
+
+&cpsw_emac1 {
+ phy_id = <&davinci_mdio>, <3>;
+ phy-mode = "rmii";
+};
+
+&davinci_mdio {
+ status = "okay";
+};
+
+&phy_sel {
+ rmii-clock-ext;
+};
+
+&am33xx_pinmux {
+ dcan0_pins: pinmux_dcan0_pins {
+ pinctrl-single,pins = <
+ 0x11c (PIN_OUTPUT_PULLUP | MUX_MODE1) /* mii1_txd3.dcan0_tx_mux0, OUTPUT_PULLUP | MODE1 */
+ 0x120 (PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_txd2.dcan0_rx_mux0, INPUT_PULLUP | MODE1 */
+ >;
+ };
+ eth_pins: pinmux_eth_pins {
+ pinctrl-single,pins = <
+ /* RMII2 (mezzanine) */
+ 0x040 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* gpmc_a0.rmii2_txen, OUTPUT_PULLDOWN | MODE3 */
+ 0x050 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* gpmc_a4.rmii2_txd1, INPUT_PULLDOWN | MODE3 */
+ 0x054 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* gpmc_a5.rmii2_txd0, INPUT_PULLDOWN | MODE3 */
+ 0x068 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* gpmc_a10.rmii2_rxd1, INPUT_PULLDOWN | MODE3 */
+ 0x06c (PIN_INPUT_PULLDOWN | MUX_MODE3) /* gpmc_a11.rmii2_rxd0, INPUT_PULLDOWN | MODE3 */
+ 0x070 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_wait0.rmii2_crs_dv, INPUT_PULLUP | MODE3 */ /* PHYAD pin */
+ 0x074 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_wpn.rmii2_rxer, INPUT_PULLUP | MODE3 */
+ 0x108 (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_col.rmii2_refclk, INPUT_PULLDOWN | MODE1 */
+ /* RMII1 (board) */
+ 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs_dv, INPUT_PULLDOWN | MODE1 */
+ 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rx_er.rmii1_rxer, INPUT_PULLDOWN | MODE1 */
+ 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_tx_en.rmii1_txen, OUTPUT_PULLDOWN | MODE1 */
+ 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_txd1.rmii1_txd1, INPUT_PULLDOWN | MODE1 */
+ 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_txd0.rmii1_txd0, INPUT_PULLDOWN | MODE1 */
+ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd1.rmii1_rxd1, INPUT_PULLDOWN | MODE1 */
+ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd0.rmii1_rxd0, INPUT_PULLDOWN | MODE1 */
+ 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_ref_clk.rmii1_refclk, INPUT_PULLDOWN | MODE0 */
+ /* MDIO (board & mezzanine) */
+ 0x148 (PIN_INPUT_PULLUP | MUX_MODE0) /* mdio.mdio_data, INPUT_PULLUP | MODE0 */
+ 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdc.mdio_clk, OUTPUT_PULLUP | MODE0 */
+ >;
+ };
+ spi0_pins: pinmux_spi0_pins { /* SPI NOR-Flash & FRAM */
+ pinctrl-single,pins = <
+ 0x150 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_sclk, INPUT_PULLUP | MODE0 */
+ 0x154 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d0, INPUT_PULLUP | MODE0 */
+ 0x158 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d1, INPUT_PULLUP | MODE0 */
+ 0x15c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* spi0_cs0, OUTPUT_PULLUP | MODE0 */
+ 0x160 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* spi0_cs1, OUTPUT_PULLUP | MODE0 */
+ >;
+ };
+ spi1_pins: pinmux_spi1_pins { /* SPI (mezzanine) */
+ pinctrl-single,pins = <
+ 0x170 (PIN_OUTPUT_PULLUP | MUX_MODE1) /* uart0_rxd.spi1_cs0_mux3, OUTPUT_PULLUP | MODE1 */
+ 0x174 (PIN_OUTPUT_PULLUP | MUX_MODE1) /* uart0_txd.spi1_cs1_mux3, OUTPUT_PULLUP | MODE1 */
+ 0x190 (PIN_INPUT_PULLUP | MUX_MODE3) /* mcasp0_aclkx.spi1_sclk_mux2, INPUT_PULLUP | MODE3 */
+ 0x194 (PIN_INPUT_PULLUP | MUX_MODE3) /* mcasp0_fsx.spi1_d0_mux2, INPUT_PULLUP | MODE3 */
+ 0x198 (PIN_INPUT_PULLUP | MUX_MODE3) /* mcasp0_axr0.spi1_d1_mux2, INPUT_PULLUP | MODE3 */
+ >;
+ };
+ usb0_pins: pinmux_usb0_pins { /* USB-HOST (mezzanine) */
+ pinctrl-single,pins = <
+ 0x208 (PIN_INPUT | MUX_MODE0) /* usb0_dm, INPUT | MODE0 */
+ 0x20c (PIN_INPUT | MUX_MODE0) /* usb0_dp, INPUT | MODE0 */
+ 0x210 (PIN_INPUT | MUX_MODE0) /* usb0_ce, INPUT | MODE0 */
+ 0x214 (PIN_INPUT | MUX_MODE0) /* usb0_id, INPUT | MODE0 */
+ 0x218 (PIN_INPUT | MUX_MODE0) /* usb0_vbus, INPUT | MODE0 */
+ 0x21c (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* usb0_drvvbus, OUTPUT_PULLDOWN | MODE0 */
+ >;
+ };
+ usb1_pins: pinmux_usb1_pins { /* USB-OTG (front) */
+ pinctrl-single,pins = <
+ 0x220 (PIN_INPUT | MUX_MODE0) /* usb1_dm, INPUT | MODE0 */
+ 0x224 (PIN_INPUT | MUX_MODE0) /* usb1_dp, INPUT | MODE0 */
+ 0x228 (PIN_INPUT | MUX_MODE0) /* usb1_ce, INPUT | MODE0 */
+ 0x22c (PIN_INPUT | MUX_MODE0) /* usb1_id, INPUT | MODE0 */
+ 0x230 (PIN_INPUT | MUX_MODE0) /* usb1_vbus, INPUT | MODE0 */
+ 0x234 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* usb1_drvvbus, OUTPUT_PULLDOWN | MODE0 */
+ >;
+ };
+ uart0_pins: pinmux_uart0_pins { /* debug, later spi1 CS1/2 */
+ pinctrl-single,pins = <
+ 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd */
+ 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd */
+ >;
+ };
+ uart1_pins: pinmux_uart1_pins { /* UART1 (PRU) */
+ pinctrl-single,pins = <
+ 0x180 (PIN_INPUT | MUX_MODE5) /* uart1_rxd.pr1_uart0_rxd_mux1, INPUT | MODE5 (RS485_RXD)*/
+ 0x184 (PIN_OUTPUT | MUX_MODE5) /* uart1_txd.pr1_uart0_txd_mux1, OUTPUT | MODE5 (RS485_TXD) */
+ >;
+ };
+ uart2_pins: pinmux_uart2_pins { /* UART2 (console) */
+ pinctrl-single,pins = <
+ 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_tx_clk.uart2_rxd_mux0, INPUT_PULLDOWN | MODE1 (UART2_RXD) */
+ 0x130 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_rx_clk.uart2_txd_mux0, OUTPUT_PULLDOWN | MODE1 (UART2_TXD) */
+ >;
+ };
+ i2c0_pins: pinmux_i2c0_pins {
+ pinctrl-single,pins = <
+ 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */
+ 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */
+ >;
+ };
+ i2c1_pins: pinmux_i2c1_pins { /* 1-wire */
+ pinctrl-single,pins = <
+ 0x168 (PIN_INPUT_PULLUP | MUX_MODE3) /* uart0_ctsn.i2c1_sda_mux1, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+ 0x16c (PIN_INPUT_PULLUP | MUX_MODE3) /* uart0_rtsn.i2c1_scl_mux1, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+ >;
+ };
+ i2c2_pins: pinmux_i2c2_pins { /* (mezzanine) */
+ pinctrl-single,pins = <
+ 0x178 (PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_ctsn.i2c2_sda_mux0, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+ 0x17c (PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_rtsn.i2c2_scl_mux0, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+ >;
+ };
+ gpio0_pins: pinmux_gpio0_pins {
+ pinctrl-single,pins = <
+ 0x020 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad8.gpio0[22], OUTPUT_PULLDOWN | MODE7 (LED3) */ /* PWM later */
+ 0x024 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad9.gpio0[23], INPUT_PULLDOWN | MODE7 (RMII2_INTRP) */
+ 0x028 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_ad10.gpio0[26], INPUT_PULLUP | MODE7 (BUTTON0) */
+ 0x02c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad11.gpio0[27], INPUT_PULLDOWN | MODE7 (PWR_INT)*/
+ 0x0d0 (PIN_INPUT | MUX_MODE7) /* lcd_data12.gpio0[8], INPUT | MODE7 (SYSBOOT12) */
+ 0x0d4 (PIN_INPUT | MUX_MODE7) /* lcd_data13.gpio0[9], INPUT | MODE7 (SYSBOOT13) */
+ 0x0d8 (PIN_INPUT | MUX_MODE7) /* lcd_data14.gpio0[10], INPUT | MODE7 (SYSBOOT14) */
+ 0x0dc (PIN_INPUT | MUX_MODE7) /* lcd_data15.gpio0[11], INPUT | MODE7 (SYSBOOT15) */
+ 0x164 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* ecap0_in_pwm0_out.gpio0[7], INPUT_PULLDOWN | MODE7 (MEZZANINE_GPIO0) */
+ 0x1b4 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* xdma_event_intr1.gpio0[20], INPUT_PULLDOWN | MODE7 (MEZZANINE_GPIO3) */
+ >;
+ };
+ gpio1_pins: pinmux_gpio1_pins {
+ pinctrl-single,pins = <
+ 0x000 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad0.gpio1[0], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x004 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad1.gpio1[1], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x008 (PIN_INPUT | MUX_MODE7) /* gpmc_ad2.gpio1[2], INPUT | MODE7 (BOARD_REV1) */
+ 0x00c (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_ad3.gpio1[3], INPUT_PULLUP | MODE7 (1WIRE_INT) */
+ 0x010 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad4.gpio1[4], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x014 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad5.gpio1[5], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x018 (PIN_INPUT | MUX_MODE7) /* gpmc_ad6.gpio1[6], INPUT | MODE7 (BOARD_REV0) */
+ 0x01c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad7.gpio1[7], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x030 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_ad12.gpio1[12], INPUT_PULLUP | MODE7 (PG_24V) */
+ 0x034 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad13.gpio1[13], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x038 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_ad14.gpio1[14], INPUT_PULLUP | MODE7 (SDCARD_CD) */
+ 0x03c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad15.gpio1[15], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x044 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a1.gpio1[17], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x048 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a2.gpio1[18], OUTPUT_PULLDOWN | MODE7 (LED1) */ /* PWM later */
+ 0x04c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a3.gpio1[19], OUTPUT_PULLDOWN | MODE7 (LED2) */ /* PWM later */
+ 0x058 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a6.gpio1[22], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x05c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a7.gpio1[23], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x060 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a8.gpio1[24], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x064 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a9.gpio1[25], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x078 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_ben1.gpio1[28], INPUT_PULLUP | MODE7 (USB1_OCn) */
+ 0x07c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_csn0.gpio1[29], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x080 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_csn1.gpio1[30], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x084 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_csn2.gpio1[31], OUTPUT_PULLDOWN | MODE7 (NC) */
+ >;
+ };
+ gpio2_pins: pinmux_gpio2_pins {
+ pinctrl-single,pins = <
+ 0x088 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_csn3.gpio2[0], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x08c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_clk.gpio2[1], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x090 (PIN_INPUT | MUX_MODE7) /* gpmc_advn_ale.gpio2[2], INPUT | MODE7 (BOARD_REV2) */
+ 0x094 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_oen_ren.gpio2[3], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x098 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_wen.gpio2[4], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x09c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ben0_cle.gpio2[5], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x0a0 (PIN_INPUT | MUX_MODE7) /* lcd_data0.gpio2[6], INPUT | MODE7 (SYSBOOT0) */
+ 0x0a4 (PIN_INPUT | MUX_MODE7) /* lcd_data1.gpio2[7], INPUT | MODE7 (SYSBOOT1) */
+ 0x0a8 (PIN_INPUT | MUX_MODE7) /* lcd_data2.gpio2[8], INPUT | MODE7 (SYSBOOT2) */
+ 0x0ac (PIN_INPUT | MUX_MODE7) /* lcd_data3.gpio2[9], INPUT | MODE7 (SYSBOOT3) */
+ 0x0b0 (PIN_INPUT | MUX_MODE7) /* lcd_data4.gpio2[10], INPUT | MODE7 (SYSBOOT4) */
+ 0x0b4 (PIN_INPUT | MUX_MODE7) /* lcd_data5.gpio2[11], INPUT | MODE7 (SYSBOOT5) */
+ 0x0b8 (PIN_INPUT | MUX_MODE7) /* lcd_data6.gpio2[12], INPUT | MODE7 (SYSBOOT6) */
+ 0x0bc (PIN_INPUT | MUX_MODE7) /* lcd_data7.gpio2[13], INPUT | MODE7 (SYSBOOT7) */
+ 0x0c0 (PIN_INPUT | MUX_MODE7) /* lcd_data8.gpio2[14], INPUT | MODE7 (SYSBOOT8) */
+ 0x0c4 (PIN_INPUT | MUX_MODE7) /* lcd_data9.gpio2[15], INPUT | MODE7 (SYSBOOT9) */
+ 0x0c8 (PIN_INPUT | MUX_MODE7) /* lcd_data10.gpio2[16], INPUT | MODE7 (SYSBOOT10) */
+ 0x0cc (PIN_INPUT | MUX_MODE7) /* lcd_data11.gpio2[17], INPUT | MODE7 (SYSBOOT11) */
+ 0x0e0 (PIN_INPUT | MUX_MODE7) /* lcd_vsync.gpio2[22], INPUT | MODE7 (BOARD_CONF1) */
+ 0x0e4 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* lcd_hsync.gpio2[23], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x0e8 (PIN_INPUT | MUX_MODE7) /* lcd_pclk.gpio2[24], INPUT | MODE7 (BOARD_CONF0) */
+ 0x0ec (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* lcd_ac_bias_en.gpio2[25], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x134 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* mii1_rxd3.gpio2[18], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x138 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* mii1_rxd2.gpio2[19], OUTPUT_PULLDOWN | MODE7 (NC) */
+ >;
+ };
+ gpio3_pins: pinmux_gpio3_pins {
+ pinctrl-single,pins = <
+ 0x118 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* mii1_rx_dv.gpio3[4], OUTPUT_PULLDOWN | MODE7 (NC) */
+ 0x19c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* mcasp0_ahclkr.gpio3[17], INPUT_PULLDOWN | MODE7 (MEZZANINE_GPIO1) */
+ 0x1a0 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* mcasp0_aclkr.gpio3[18], OUTPUT_PULLUP | MODE7 (DCAN0_LBK) */ /* enable loopback by default */
+ 0x1a4 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* mcasp0_fsr.gpio3[19], OUTPUT_PULLDOWN | MODE7 (RS485_DE) */
+ 0x1a8 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* mcasp0_axr1.gpio3[20], OUTPUT_PULLUP | MODE7 (1WIRE_SLEEP) */
+ 0x1ac (PIN_INPUT_PULLDOWN | MUX_MODE7) /* mcasp0_ahclkx.gpio3[21], INPUT_PULLDOWN | MODE7 (MEZZANINE_GPIO2) */
+ >;
+ };
+};
diff --git a/arch/arm/dts/am335x-bone-common.dtsi b/arch/arm/dts/am335x-bone-common.dtsi
index e1effac323..ef97d90661 100644
--- a/arch/arm/dts/am335x-bone-common.dtsi
+++ b/arch/arm/dts/am335x-bone-common.dtsi
@@ -178,31 +178,31 @@
&usb {
status = "okay";
+};
- control@44e10000 {
- status = "okay";
- };
+&usb_ctrl_mod {
+ status = "okay";
+};
- usb-phy@47401300 {
- status = "okay";
- };
+&usb0_phy {
+ status = "okay";
+};
- usb-phy@47401b00 {
- status = "okay";
- };
+&usb1_phy {
+ status = "okay";
+};
- usb@47401000 {
- status = "okay";
- };
+&usb0 {
+ status = "okay";
+};
- usb@47401800 {
- status = "okay";
- dr_mode = "host";
- };
+&usb1 {
+ status = "okay";
+ dr_mode = "host";
+};
- dma-controller@07402000 {
- status = "okay";
- };
+&cppi41dma {
+ status = "okay";
};
&i2c0 {
diff --git a/arch/arm/dts/am335x-phytec-phycore.dts b/arch/arm/dts/am335x-phytec-phycore.dts
index 5678138f66..e7e7780826 100644
--- a/arch/arm/dts/am335x-phytec-phycore.dts
+++ b/arch/arm/dts/am335x-phytec-phycore.dts
@@ -50,10 +50,10 @@
spi0_pins: pinmux_spi0_pins {
pinctrl-single,pins = <
- 0x150 (INPUT_EN | MUX_MODE0)
- 0x154 (PULL_UP | INPUT_EN | MUX_MODE0)
- 0x158 (INPUT_EN | MUX_MODE0)
- 0x15c (PULL_UP | INPUT_EN | MUX_MODE0)
+ 0x150 (PIN_INPUT_PULLDOWN | MUX_MODE0) /* spi0_clk.spi0_clk */
+ 0x154 (PIN_INPUT_PULLDOWN | MUX_MODE0) /* spi0_d0.spi0_d0 */
+ 0x158 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d1.spi0_d1 */
+ 0x15c (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_cs0.spi0_cs0 */
>;
};
@@ -172,9 +172,9 @@
status = "okay";
flash: m25p80 {
- compatible = "sst,sst25vf032b", "m25p80";
- spi-max-frequency = <15000000>;
- reg = <1>;
+ compatible = "m25p80";
+ spi-max-frequency = <48000000>;
+ reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
@@ -194,8 +194,13 @@
};
partition@3 {
+ label = "oftree";
+ reg = <0xc0000 0x20000>;
+ };
+
+ partition@4 {
label = "kernel";
- reg = <0xc0000 0x400000>;
+ reg = <0xe0000 0x400000>;
};
};
};
@@ -305,13 +310,22 @@
};
partition@6 {
- label = "kernel";
- reg = <0x120000 0x800000>;
+ label = "oftree";
+ reg = <0x120000 0x20000>;
};
partition@7 {
+ label = "kernel";
+ reg = <0x140000 0x800000>;
+ };
+
+ partition@8 {
label = "root";
- reg = <0x920000 0x1f6e0000>;
+ /*
+ * Size 0x0 extends partition to
+ * end of nand flash.
+ */
+ reg = <0x940000 0x0>;
};
};
};
diff --git a/arch/arm/dts/imx53-voipac-bsb.dts b/arch/arm/dts/imx53-voipac-bsb.dts
index 54c8bcd40a..12ce592a47 100644
--- a/arch/arm/dts/imx53-voipac-bsb.dts
+++ b/arch/arm/dts/imx53-voipac-bsb.dts
@@ -10,4 +10,5 @@
*/
#include <arm/imx53-voipac-bsb.dts>
+#include "imx53-voipac-dmm-668.dtsi"
#include "imx53.dtsi"
diff --git a/arch/arm/dts/imx53-voipac-dmm-668.dtsi b/arch/arm/dts/imx53-voipac-dmm-668.dtsi
new file mode 100644
index 0000000000..6f76d2867a
--- /dev/null
+++ b/arch/arm/dts/imx53-voipac-dmm-668.dtsi
@@ -0,0 +1,35 @@
+/ {
+ chosen {
+ linux,stdout-path = &uart1;
+
+ environment@0 {
+ compatible = "barebox,environment";
+ device-path = &nfc, "partname:environment";
+ };
+ };
+};
+
+&nfc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "barebox";
+ reg = <0x0 0x80000>;
+ };
+
+ partition@1 {
+ label = "environment";
+ reg = <0x80000 0x80000>;
+ };
+
+ partition@2 {
+ label = "kernel";
+ reg = <0x100000 0x400000>;
+ };
+
+ partition@3 {
+ label = "rootfs";
+ reg = <0x500000 0x07B00000>;
+ };
+};
diff --git a/arch/arm/dts/imx6dl-phytec-pbab01.dts b/arch/arm/dts/imx6dl-phytec-pbab01.dts
index 0e90c47768..4b77838926 100644
--- a/arch/arm/dts/imx6dl-phytec-pbab01.dts
+++ b/arch/arm/dts/imx6dl-phytec-pbab01.dts
@@ -20,10 +20,5 @@
chosen {
linux,stdout-path = &uart4;
-
- environment@0 {
- compatible = "barebox,environment";
- device-path = &flash, "partname:barebox-environment";
- };
};
};
diff --git a/arch/arm/dts/imx6dl-phytec-pfla02.dtsi b/arch/arm/dts/imx6dl-phytec-pfla02.dtsi
index fa3a49aa3c..0f801aebc9 100644
--- a/arch/arm/dts/imx6dl-phytec-pfla02.dtsi
+++ b/arch/arm/dts/imx6dl-phytec-pfla02.dtsi
@@ -15,27 +15,8 @@
/ {
model = "Phytec phyFLEX-i.MX6 Dual Lite";
compatible = "phytec,imx6dl-pfla02", "fsl,imx6dl";
-
- memory {
- reg = <0x10000000 0x40000000>;
- };
};
&ecspi3 {
status = "okay";
};
-
-&flash {
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "barebox";
- reg = <0x0 0x80000>;
- };
-
- partition@1 {
- label = "barebox-environment";
- reg = <0x80000 0x10000>;
- };
-};
diff --git a/arch/arm/dts/imx6dl-tx6u-801x.dts b/arch/arm/dts/imx6dl-tx6u-801x.dts
new file mode 100644
index 0000000000..43104b2b88
--- /dev/null
+++ b/arch/arm/dts/imx6dl-tx6u-801x.dts
@@ -0,0 +1,65 @@
+#include <arm/imx6dl-tx6u-801x.dts>
+#include "imx6qdl.dtsi"
+
+/ {
+ model = "Ka-Ro electronics TX6U-801x Module";
+ compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl";
+
+ chosen {
+ linux,stdout-path = &uart1;
+
+ environment@0 {
+ compatible = "barebox,environment";
+ device-path = &gpmi, "partname:barebox-environment";
+ };
+ };
+};
+
+&gpmi {
+ partition@0 {
+ label = "barebox";
+ reg = <0x0 0x100000>;
+ };
+
+ partition@1 {
+ label = "barebox-environment";
+ reg = <0x100000 0x100000>;
+ };
+};
+
+&iomuxc {
+ imx6qdl-tx6 {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b0b1 /* LED */
+ MX6QDL_PAD_SD3_DAT2__GPIO7_IO06 0x1b0b1 /* ETN PHY RESET */
+ MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1b0b1 /* ETN PHY INT */
+ MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b1 /* PWR BTN */
+ MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x1b0b1 /* ETN PHY POWER */
+ >;
+ };
+
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x1b0b0
+ MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x1b0b0
+ MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER 0x1b0b0
+ MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
+ MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x1b0b0
+ MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x1b0b0
+ MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x1b0b0
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0b0
+ >;
+ };
+ };
+};
+
+&fec {
+ phy-reset-duration = <22>;
+};
+
+&ocotp {
+ barebox,provide-mac-address = <&fec 0x620>;
+};
diff --git a/arch/arm/dts/imx6q-gw54xx.dts b/arch/arm/dts/imx6q-gw54xx.dts
new file mode 100644
index 0000000000..ab518d66a7
--- /dev/null
+++ b/arch/arm/dts/imx6q-gw54xx.dts
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw54xx.dtsi"
+
+/ {
+ model = "Gateworks Ventana i.MX6 Quad GW54XX";
+ compatible = "gw,imx6q-gw54xx", "gw,ventana", "fsl,imx6q";
+};
+
+&sata {
+ status = "okay";
+};
diff --git a/arch/arm/dts/imx6q-phytec-pbab01.dts b/arch/arm/dts/imx6q-phytec-pbab01.dts
index 26046e01c3..580338dff8 100644
--- a/arch/arm/dts/imx6q-phytec-pbab01.dts
+++ b/arch/arm/dts/imx6q-phytec-pbab01.dts
@@ -19,10 +19,5 @@
chosen {
linux,stdout-path = &uart4;
-
- environment@0 {
- compatible = "barebox,environment";
- device-path = &flash, "partname:barebox-environment";
- };
};
};
diff --git a/arch/arm/dts/imx6q-phytec-pcaaxl3.dtsi b/arch/arm/dts/imx6q-phytec-pcaaxl3.dtsi
index 45f36692fe..78c33349dc 100644
--- a/arch/arm/dts/imx6q-phytec-pcaaxl3.dtsi
+++ b/arch/arm/dts/imx6q-phytec-pcaaxl3.dtsi
@@ -144,13 +144,18 @@
};
partition@2 {
- label = "kernel";
- reg = <0x420000 0x800000>;
+ label = "oftree";
+ reg = <0x420000 0x20000>;
};
partition@3 {
+ label = "kernel";
+ reg = <0x440000 0x800000>;
+ };
+
+ partition@4 {
label = "root";
- reg = <0xC20000 0x0>;
+ reg = <0xC40000 0x0>;
};
};
diff --git a/arch/arm/dts/imx6q-phytec-pfla02.dtsi b/arch/arm/dts/imx6q-phytec-pfla02.dtsi
index 781a90ae9d..0aec5d0352 100644
--- a/arch/arm/dts/imx6q-phytec-pfla02.dtsi
+++ b/arch/arm/dts/imx6q-phytec-pfla02.dtsi
@@ -15,27 +15,8 @@
/ {
model = "Phytec phyFLEX-i.MX6 Quad";
compatible = "phytec,imx6q-pfla02", "fsl,imx6q";
-
- memory {
- reg = <0x10000000 0x40000000>;
- };
};
&ecspi3 {
status = "okay";
};
-
-&flash {
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "barebox";
- reg = <0x0 0x80000>;
- };
-
- partition@1 {
- label = "barebox-environment";
- reg = <0x80000 0x10000>;
- };
-};
diff --git a/arch/arm/dts/imx6qdl-gw54xx.dtsi b/arch/arm/dts/imx6qdl-gw54xx.dtsi
new file mode 100644
index 0000000000..ea5739ddcb
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-gw54xx.dtsi
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+ #include <arm/imx6qdl-gw54xx.dtsi>
+
+ / {
+ chosen {
+ linux,stdout-path = &uart2;
+
+ environment@0 {
+ compatible = "barebox,environment";
+ device-path = &gpmi, "partname:barebox-environment";
+ };
+ };
+};
+
+&gpmi {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "barebox";
+ reg = <0x0 0x400000>;
+ };
+
+ partition@1 {
+ label = "barebox-environment";
+ reg = <0x400000 0x20000>;
+ };
+};
diff --git a/arch/arm/dts/imx6qdl-phytec-pbab01.dtsi b/arch/arm/dts/imx6qdl-phytec-pbab01.dtsi
index 8f5dea7407..157e130ff1 100644
--- a/arch/arm/dts/imx6qdl-phytec-pbab01.dtsi
+++ b/arch/arm/dts/imx6qdl-phytec-pbab01.dtsi
@@ -9,23 +9,10 @@
* http://www.gnu.org/copyleft/gpl.html
*/
-/ {
- chosen {
- environment@0 {
- compatible = "barebox,environment";
- device-path = &flash, "partname:barebox-environment";
- };
- };
-};
-
&fec {
status = "okay";
};
-&ocotp {
- barebox,provide-mac-address = <&fec 0x620>;
-};
-
&uart1 {
status = "okay";
};
diff --git a/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
index a981fd40a3..5c7bcee7f7 100644
--- a/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
+++ b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
@@ -9,6 +9,28 @@
* http://www.gnu.org/copyleft/gpl.html
*/
+/ {
+ chosen {
+ environment-nand {
+ compatible = "barebox,environment";
+ device-path = &gpmi, "partname:barebox-environment";
+ status = "disabled";
+ };
+
+ environment-spinor {
+ compatible = "barebox,environment";
+ device-path = &flash, "partname:barebox-environment";
+ status = "disabled";
+ };
+
+ environment-sd {
+ compatible = "barebox,environment";
+ device-path = &usdhc3, "partname:barebox-environment";
+ status = "disabled";
+ };
+ };
+};
+
&ecspi3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi3>;
@@ -20,6 +42,20 @@
compatible = "m25p80";
spi-max-frequency = <20000000>;
reg = <0>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "barebox";
+ reg = <0x0 0x80000>;
+ };
+
+ partition@1 {
+ label = "barebox-environment";
+ reg = <0x80000 0x10000>;
+ };
+
};
};
@@ -36,6 +72,33 @@
pinctrl-0 = <&pinctrl_gpmi_nand>;
nand-on-flash-bbt;
status = "okay";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "barebox";
+ reg = <0x0 0x400000>;
+ };
+
+ partition@1 {
+ label = "barebox-environment";
+ reg = <0x400000 0x20000>;
+ };
+
+ partition@2 {
+ label = "oftree";
+ reg = <0x420000 0x20000>;
+ };
+
+ partition@3 {
+ label = "kernel";
+ reg = <0x440000 0x800000>;
+ };
+
+ partition@4 {
+ label = "root";
+ reg = <0xC40000 0x0>;
+ };
};
&iomuxc {
@@ -149,6 +212,10 @@
};
};
+&ocotp {
+ barebox,provide-mac-address = <&fec 0x620>;
+};
+
&uart4 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart4>;
@@ -169,4 +236,16 @@
cd-gpios = <&gpio1 27 0>;
wp-gpios = <&gpio1 29 0>;
status = "disabled";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "barebox";
+ reg = <0x0 0x80000>;
+ };
+ partition@1 {
+ label = "barebox-environment";
+ reg = <0x80000 0x80000>;
+ };
};
diff --git a/arch/arm/dts/imx6s-phytec-pfla02.dtsi b/arch/arm/dts/imx6s-phytec-pfla02.dtsi
index 83224262b3..d84fa4f15f 100644
--- a/arch/arm/dts/imx6s-phytec-pfla02.dtsi
+++ b/arch/arm/dts/imx6s-phytec-pfla02.dtsi
@@ -15,8 +15,4 @@
/ {
model = "Phytec phyFLEX-i.MX6 Single";
compatible = "phytec,imx6s-pfla02", "fsl,imx6dl";
-
- memory {
- reg = <0x10000000 0x20000000>;
- };
};
diff --git a/arch/arm/dts/socfpga.dtsi b/arch/arm/dts/socfpga.dtsi
index 3368b459d0..afac867c99 100644
--- a/arch/arm/dts/socfpga.dtsi
+++ b/arch/arm/dts/socfpga.dtsi
@@ -465,6 +465,12 @@
status = "disabled";
};
+ fpgamgr@ff706000 {
+ compatible = "altr,socfpga-fpga-mgr";
+ reg = <0xff706000 0x1000>,
+ <0xffb90000 0x1000>;
+ };
+
gpio0: gpio@ff708000 {
compatible = "snps,dw-apb-gpio";
reg = <0xff708000 0x1000>;
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 826917e12c..8c10c10359 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -6,6 +6,9 @@ config HAVE_AT91_DBGU0
config HAVE_AT91_DBGU1
bool
+config HAVE_AT91_DBGU2
+ bool
+
config HAVE_AT91_LOWLEVEL_INIT
bool
@@ -168,6 +171,13 @@ config ARCH_SAMA5D3
select HAS_MACB
select AT91SAM9G45_RESET
+config ARCH_SAMA5D4
+ bool "SAMA5D4"
+ select SOC_SAMA5
+ select HAVE_AT91_DBGU2
+ select HAS_MACB
+ select AT91SAM9G45_RESET
+
endchoice
config ARCH_BAREBOX_MAX_BARE_INIT_SIZE
@@ -472,6 +482,22 @@ endif
# ----------------------------------------------------------
+if ARCH_SAMA5D4
+
+choice
+ prompt "SAMA5D4 Board Type"
+
+config MACH_SAMA5D4EK
+ bool "Atmel SAMA5D4 Evaluation Kit"
+ help
+ Select this if you are using Atmel's SAMA5D4-EK Evaluation Kit.
+
+endchoice
+
+endif
+
+# ----------------------------------------------------------
+
comment "AT91 Board Options"
config MTD_AT91_DATAFLASH_CARD
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index 8599f507c4..c2991b0136 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -12,6 +12,7 @@ lowlevel_init-$(CONFIG_SOC_AT91SAM9X5) += at91sam9x5_lowlevel_init.o
lowlevel_init-$(CONFIG_SOC_AT91SAM9N12) += at91sam9n12_lowlevel_init.o
lowlevel_init-$(CONFIG_ARCH_AT91RM9200) = at91rm9200_lowlevel_init.o
lowlevel_init-$(CONFIG_ARCH_SAMA5D3) += sama5d3_lowlevel_init.o
+lowlevel_init-$(CONFIG_ARCH_SAMA5D4) += sama5d3_lowlevel_init.o
lwl-y += $(lowlevel_init-y)
obj-$(CONFIG_AT91SAM9_RESET) += at91sam9_reset.o
@@ -31,3 +32,4 @@ obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam9g45_devices.o
obj-$(CONFIG_ARCH_AT91SAM9X5) += at91sam9x5.o at91sam9x5_devices.o
obj-$(CONFIG_ARCH_AT91SAM9N12) += at91sam9n12.o at91sam9n12_devices.o
obj-$(CONFIG_ARCH_SAMA5D3) += sama5d3.o sama5d3_devices.o
+obj-$(CONFIG_ARCH_SAMA5D4) += sama5d4.o sama5d4_devices.o
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 9a50debb16..ce6ce90db2 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -192,11 +192,6 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci1", &mmc1_clk),
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi0", &spi0_clk),
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi1", &spi1_clk),
- CLKDEV_DEV_ID("at91rm9200-gpio0", &pioA_clk),
- CLKDEV_DEV_ID("at91rm9200-gpio1", &pioB_clk),
- CLKDEV_DEV_ID("at91rm9200-gpio2", &pioC_clk),
- CLKDEV_DEV_ID("at91rm9200-gpio3", &pioDE_clk),
- CLKDEV_DEV_ID("at91rm9200-gpio4", &pioDE_clk),
CLKDEV_DEV_ID("at91-pit", &mck),
CLKDEV_CON_DEV_ID("hck1", "atmel_lcdfb", &lcdc_clk),
};
@@ -238,6 +233,14 @@ static void __init at91sam9g45_register_clocks(void)
clkdev_add_table(usart_clocks_lookups,
ARRAY_SIZE(usart_clocks_lookups));
+ clkdev_add_physbase(&twi0_clk, AT91SAM9G45_BASE_TWI0, NULL);
+ clkdev_add_physbase(&twi1_clk, AT91SAM9G45_BASE_TWI1, NULL);
+ clkdev_add_physbase(&pioA_clk, AT91SAM9G45_BASE_PIOA, NULL);
+ clkdev_add_physbase(&pioB_clk, AT91SAM9G45_BASE_PIOB, NULL);
+ clkdev_add_physbase(&pioC_clk, AT91SAM9G45_BASE_PIOC, NULL);
+ clkdev_add_physbase(&pioDE_clk, AT91SAM9G45_BASE_PIOD, NULL);
+ clkdev_add_physbase(&pioDE_clk, AT91SAM9G45_BASE_PIOE, NULL);
+
if (cpu_is_at91sam9m10() || cpu_is_at91sam9m11())
clk_register(&vdec_clk);
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
index 9d2a846447..7a4282e615 100644
--- a/arch/arm/mach-at91/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -37,6 +37,7 @@
#define clk_is_programmable(x) ((x)->type & CLK_TYPE_PROGRAMMABLE)
#define clk_is_peripheral(x) ((x)->type & CLK_TYPE_PERIPHERAL)
#define clk_is_sys(x) ((x)->type & CLK_TYPE_SYSTEM)
+#define clk_is_periph_h64mx(x) ((x)->type & CLK_TYPE_PERIPH_H64MX)
/*
@@ -45,7 +46,10 @@
#define cpu_has_utmi() ( cpu_is_at91sam9rl() \
|| cpu_is_at91sam9g45() \
|| cpu_is_at91sam9x5() \
- || cpu_is_sama5d3())
+ || cpu_is_sama5d3() \
+ || cpu_is_sama5d4())
+
+#define cpu_has_1200M_plla() (cpu_is_sama5d4())
#define cpu_has_1056M_plla() (cpu_is_sama5d3())
@@ -65,11 +69,13 @@
#define cpu_has_pllb() (!(cpu_is_at91sam9rl() \
|| cpu_is_at91sam9g45() \
|| cpu_is_at91sam9x5() \
- || cpu_is_sama5d3()))
+ || cpu_is_sama5d3() \
+ || cpu_is_sama5d4()))
#define cpu_has_upll() (cpu_is_at91sam9g45() \
|| cpu_is_at91sam9x5() \
- || cpu_is_sama5d3())
+ || cpu_is_sama5d3() \
+ || cpu_is_sama5d4())
/* USB host HS & FS */
#define cpu_has_uhp() (!cpu_is_at91sam9rl())
@@ -78,21 +84,30 @@
#define cpu_has_udpfs() (!(cpu_is_at91sam9rl() \
|| cpu_is_at91sam9g45() \
|| cpu_is_at91sam9x5() \
- || cpu_is_sama5d3()))
+ || cpu_is_sama5d3() \
+ || cpu_is_sama5d4()))
#define cpu_has_plladiv2() (cpu_is_at91sam9g45() \
|| cpu_is_at91sam9x5() \
|| cpu_is_at91sam9n12() \
- || cpu_is_sama5d3())
+ || cpu_is_sama5d3() \
+ || cpu_is_sama5d4())
#define cpu_has_mdiv3() (cpu_is_at91sam9g45() \
|| cpu_is_at91sam9x5() \
|| cpu_is_at91sam9n12() \
- || cpu_is_sama5d3())
+ || cpu_is_sama5d3() \
+ || cpu_is_sama5d4())
#define cpu_has_alt_prescaler() (cpu_is_at91sam9x5() \
|| cpu_is_at91sam9n12() \
- || cpu_is_sama5d3())
+ || cpu_is_sama5d3() \
+ || cpu_is_sama5d4())
+
+#define cpu_has_pcr() (cpu_is_sama5d3() \
+ || cpu_is_sama5d4())
+
+#define cpu_has_dual_matrix() (cpu_is_sama5d4())
static LIST_HEAD(clocks);
@@ -212,6 +227,12 @@ struct clk mck = {
.pmc_mask = AT91_PMC_MCKRDY, /* in PMC_SR */
};
+struct clk h32mx_clk = {
+ .name = "h32mx",
+ .parent = &mck,
+ .pmc_mask = AT91_PMC_H32MXDIV, /* in PMC_MCKR */
+};
+
static void pmc_periph_mode(struct clk *clk, int is_on)
{
u32 regval = 0;
@@ -221,7 +242,7 @@ static void pmc_periph_mode(struct clk *clk, int is_on)
* register is not enough to manage their clocks. A peripheral
* control register has been introduced to solve this issue.
*/
- if (cpu_is_sama5d3()) {
+ if (cpu_has_pcr()) {
regval |= AT91_PMC_PCR_CMD; /* write command */
regval |= clk->pid & AT91_PMC_PCR_PID; /* peripheral selection */
regval |= AT91_PMC_PCR_DIV(clk->div);
@@ -453,9 +474,13 @@ static void __init at91_clk_add(struct clk *clk)
int clk_register(struct clk *clk)
{
if (clk_is_peripheral(clk)) {
- if (!clk->parent)
- clk->parent = &mck;
- if (cpu_is_sama5d3())
+ if (!clk->parent) {
+ if (!cpu_has_dual_matrix() || clk_is_periph_h64mx(clk))
+ clk->parent = &mck;
+ else
+ clk->parent = &h32mx_clk;
+ }
+ if (cpu_has_pcr())
clk->rate_hz = DIV_ROUND_UP(clk->parent->rate_hz, 1 << clk->div);
clk->mode = pmc_periph_mode;
}
@@ -482,7 +507,7 @@ static u32 at91_pll_rate(struct clk *pll, u32 freq, u32 reg)
unsigned mul, div;
div = reg & 0xff;
- if (cpu_is_sama5d3())
+ if (cpu_is_sama5d3() || cpu_is_sama5d4())
mul = (reg >> 18) & 0x7ff;
else
mul = (reg >> 16) & 0x7ff;
@@ -647,7 +672,10 @@ int at91_clock_init(void)
/* report if PLLA is more than mildly overclocked */
plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_pmc_read(AT91_CKGR_PLLAR));
- if (cpu_has_1056M_plla()) {
+ if (cpu_has_1200M_plla()) {
+ if (plla.rate_hz > 1200000000)
+ pll_overclock = 1;
+ } else if (cpu_has_1056M_plla()) {
if (plla.rate_hz > 1056000000)
pll_overclock = 1;
} else if (cpu_has_300M_plla()) {
@@ -734,6 +762,12 @@ int at91_clock_init(void)
mck.id = 4;
}
+ if (cpu_has_dual_matrix()) {
+ at91_clk_add(&h32mx_clk);
+ h32mx_clk.rate_hz = h32mx_clk.parent->rate_hz;
+ h32mx_clk.rate_hz /= (1 << ((mckr & AT91_PMC_H32MXDIV) >> 24)); /* H32MX divisor by 2 */
+ }
+
cpu_freq = freq;
/* Register the PMC's standard clocks */
@@ -754,6 +788,8 @@ int at91_clock_init(void)
/* MCK and CPU clock are "always on" */
clk_enable(&mck);
+ if (cpu_has_dual_matrix())
+ clk_enable(&h32mx_clk);
return 0;
}
@@ -787,7 +823,7 @@ static int at91_clock_reset(void)
continue;
if (clk->mode == pmc_periph_mode) {
- if (cpu_is_sama5d3()) {
+ if (cpu_has_pcr()) {
u32 pmc_mask = 1 << (clk->pid % 32);
if (clk->pid > 31)
@@ -805,7 +841,7 @@ static int at91_clock_reset(void)
}
at91_pmc_write(AT91_PMC_PCDR, pcdr);
- if (cpu_is_sama5d3())
+ if (cpu_has_pcr())
at91_pmc_write(AT91_PMC_PCDR1, pcdr1);
at91_pmc_write(AT91_PMC_SCDR, scdr);
@@ -821,12 +857,12 @@ static int do_at91clk(int argc, char *argv[])
scsr = at91_pmc_read(AT91_PMC_SCSR);
pcsr = at91_pmc_read(AT91_PMC_PCSR);
- if (cpu_is_sama5d3())
+ if (cpu_has_pcr())
pcsr1 = at91_pmc_read(AT91_PMC_PCSR1);
sr = at91_pmc_read(AT91_PMC_SR);
printf("SCSR = %8x\n", scsr);
printf("PCSR = %8x\n", pcsr);
- if (cpu_is_sama5d3())
+ if (cpu_has_pcr())
printf("PCSR1 = %8x\n", pcsr1);
printf("MOR = %8x\n", at91_pmc_read(AT91_CKGR_MOR));
printf("MCFR = %8x\n", at91_pmc_read(AT91_CKGR_MCFR));
@@ -852,7 +888,7 @@ static int do_at91clk(int argc, char *argv[])
state = (scsr & clk->pmc_mask) ? "on" : "off";
mode = "sys";
} else if (clk->mode == pmc_periph_mode) {
- if (cpu_is_sama5d3()) {
+ if (cpu_has_pcr()) {
u32 pmc_mask = 1 << (clk->pid % 32);
if (clk->pid > 31)
diff --git a/arch/arm/mach-at91/clock.h b/arch/arm/mach-at91/clock.h
index 8af8d963c8..97a08fd83f 100644
--- a/arch/arm/mach-at91/clock.h
+++ b/arch/arm/mach-at91/clock.h
@@ -13,7 +13,7 @@
#define CLK_TYPE_PROGRAMMABLE 0x4
#define CLK_TYPE_PERIPHERAL 0x8
#define CLK_TYPE_SYSTEM 0x10
-
+#define CLK_TYPE_PERIPH_H64MX 0x80
struct clk {
struct list_head node;
diff --git a/arch/arm/mach-at91/include/mach/at91_pmc.h b/arch/arm/mach-at91/include/mach/at91_pmc.h
index 61078717c6..d74c14011c 100644
--- a/arch/arm/mach-at91/include/mach/at91_pmc.h
+++ b/arch/arm/mach-at91/include/mach/at91_pmc.h
@@ -118,6 +118,7 @@
#define AT91_PMC_PLLADIV2 (1 << 12) /* PLLA divisor by 2 [some SAM9 only] */
#define AT91_PMC_PLLADIV2_OFF (0 << 12)
#define AT91_PMC_PLLADIV2_ON (1 << 12)
+#define AT91_PMC_H32MXDIV (1 << 24) /* AHB 32-bit Matrix Divisor [some SAMA5 only] */
#define AT91_PMC_USB 0x38 /* USB Clock Register [some SAM9 only] */
#define AT91_PMC_USBS (0x1 << 0) /* USB OHCI Input clock selection */
diff --git a/arch/arm/mach-at91/include/mach/at91rm9200.h b/arch/arm/mach-at91/include/mach/at91rm9200.h
index 36e940d928..4fe8fd891c 100644
--- a/arch/arm/mach-at91/include/mach/at91rm9200.h
+++ b/arch/arm/mach-at91/include/mach/at91rm9200.h
@@ -118,6 +118,7 @@
#define AT91_MATRIX 0 /* not supported */
+#define AT91_PMC 0xfffffc00
/*
* Internal Memory.
diff --git a/arch/arm/mach-at91/include/mach/at91sam9260.h b/arch/arm/mach-at91/include/mach/at91sam9260.h
index 3f3a0e1a54..919901d6da 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9260.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9260.h
@@ -125,6 +125,8 @@
#define AT91_ID_UHP AT91SAM9260_ID_UHP
#define AT91_PMC_UHP AT91SAM926x_PMC_UHP
+#define AT91_PMC 0xfffffc00
+
/*
* Internal Memory.
*/
diff --git a/arch/arm/mach-at91/include/mach/at91sam9261.h b/arch/arm/mach-at91/include/mach/at91sam9261.h
index 1b48e230b4..9124df5caa 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9261.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9261.h
@@ -102,6 +102,7 @@
#define AT91_USART2 AT91SAM9261_BASE_US2
#define AT91_NB_USART 4
+#define AT91_PMC 0xfffffc00
/*
* Internal Memory.
diff --git a/arch/arm/mach-at91/include/mach/at91sam9263.h b/arch/arm/mach-at91/include/mach/at91sam9263.h
index b42d191b99..e7ca8b63aa 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9263.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9263.h
@@ -129,6 +129,8 @@
#define AT91_ID_UHP AT91SAM9263_ID_UHP
#define AT91_PMC_UHP AT91SAM926x_PMC_UHP
+#define AT91_PMC 0xfffffc00
+
/*
* Internal Memory.
*/
diff --git a/arch/arm/mach-at91/include/mach/at91sam9g45.h b/arch/arm/mach-at91/include/mach/at91sam9g45.h
index c81bb80c53..ff12ce458a 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9g45.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9g45.h
@@ -134,6 +134,8 @@
#define AT91_USART3 AT91SAM9G45_BASE_US3
#define AT91_NB_USART 5
+#define AT91_PMC 0xfffffc00
+
/*
* Internal Memory.
*/
diff --git a/arch/arm/mach-at91/include/mach/at91sam9n12.h b/arch/arm/mach-at91/include/mach/at91sam9n12.h
index 26bdd13498..249bde466b 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9n12.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9n12.h
@@ -129,6 +129,7 @@
#define AT91_USART3 AT91SAM9X5_BASE_US3
#define AT91_NB_USART 5
+#define AT91_PMC 0xfffffc00
/*
* Internal Memory.
diff --git a/arch/arm/mach-at91/include/mach/at91sam9x5.h b/arch/arm/mach-at91/include/mach/at91sam9x5.h
index 13b4f44379..7ba2e3b9b1 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9x5.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9x5.h
@@ -136,6 +136,7 @@
#define AT91_USART3 AT91SAM9X5_BASE_US3
#define AT91_NB_USART 5
+#define AT91_PMC 0xfffffc00
/*
* Internal Memory.
diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h
index 0e213ce9da..f684d32949 100644
--- a/arch/arm/mach-at91/include/mach/cpu.h
+++ b/arch/arm/mach-at91/include/mach/cpu.h
@@ -26,7 +26,7 @@
#define ARCH_ID_AT91SAM9G45ES 0x819b05a1 /* 9G45-ES (Engineering Sample) */
#define ARCH_ID_AT91SAM9X5 0x819a05a0
#define ARCH_ID_AT91SAM9N12 0x819a07a0
-#define ARCH_ID_SAMA5D3 0x8A5C07C0
+#define ARCH_ID_SAMA5 0x8A5C07C0
#define ARCH_ID_AT91SAM9XE128 0x329973a0
#define ARCH_ID_AT91SAM9XE256 0x329a93a0
@@ -48,12 +48,19 @@
#define ARCH_EXID_AT91SAM9G25 0x00000003
#define ARCH_EXID_AT91SAM9X25 0x00000004
+#define ARCH_EXID_SAMA5D3 0x00004300
#define ARCH_EXID_SAMA5D31 0x00444300
#define ARCH_EXID_SAMA5D33 0x00414300
#define ARCH_EXID_SAMA5D34 0x00414301
#define ARCH_EXID_SAMA5D35 0x00584300
#define ARCH_EXID_SAMA5D36 0x00004301
+#define ARCH_EXID_SAMA5D4 0x00000007
+#define ARCH_EXID_SAMA5D41 0x00000001
+#define ARCH_EXID_SAMA5D42 0x00000002
+#define ARCH_EXID_SAMA5D43 0x00000003
+#define ARCH_EXID_SAMA5D44 0x00000004
+
#define ARCH_FAMILY_AT91X92 0x09200000
#define ARCH_FAMILY_AT91SAM9 0x01900000
#define ARCH_FAMILY_AT91SAM9XE 0x02900000
@@ -85,6 +92,9 @@ enum at91_soc_type {
/* SAMA5D3 */
AT91_SOC_SAMA5D3,
+ /* SAMA5D4 */
+ AT91_SOC_SAMA5D4,
+
/* Unknown type */
AT91_SOC_NONE
};
@@ -107,6 +117,10 @@ enum at91_soc_subtype {
AT91_SOC_SAMA5D31, AT91_SOC_SAMA5D33, AT91_SOC_SAMA5D34,
AT91_SOC_SAMA5D35, AT91_SOC_SAMA5D36,
+ /* SAMA5D4 */
+ AT91_SOC_SAMA5D41, AT91_SOC_SAMA5D42, AT91_SOC_SAMA5D43,
+ AT91_SOC_SAMA5D44,
+
/* Unknown subtype */
AT91_SOC_SUBTYPE_NONE
};
@@ -217,6 +231,20 @@ static inline int at91_soc_is_detected(void)
#define cpu_is_sama5d36() (0)
#endif
+#ifdef CONFIG_ARCH_SAMA5D4
+#define cpu_is_sama5d4() (at91_soc_initdata.type == AT91_SOC_SAMA5D4)
+#define cpu_is_sama5d41() (at91_soc_initdata.subtype == AT91_SOC_SAMA5D41)
+#define cpu_is_sama5d42() (at91_soc_initdata.subtype == AT91_SOC_SAMA5D42)
+#define cpu_is_sama5d43() (at91_soc_initdata.subtype == AT91_SOC_SAMA5D43)
+#define cpu_is_sama5d44() (at91_soc_initdata.subtype == AT91_SOC_SAMA5D44)
+#else
+#define cpu_is_sama5d4() (0)
+#define cpu_is_sama5d41() (0)
+#define cpu_is_sama5d42() (0)
+#define cpu_is_sama5d43() (0)
+#define cpu_is_sama5d44() (0)
+#endif
+
/*
* Since this is ARM, we will never run on any AVR32 CPU. But these
* definitions may reduce clutter in common drivers.
diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h
index 8f004deb42..bbaad714cf 100644
--- a/arch/arm/mach-at91/include/mach/hardware.h
+++ b/arch/arm/mach-at91/include/mach/hardware.h
@@ -19,8 +19,8 @@
#define AT91_BASE_DBGU0 0xfffff200
/* 9263, 9g45 */
#define AT91_BASE_DBGU1 0xffffee00
-
-#define AT91_PMC 0xfffffc00
+/* sama5d4 */
+#define AT91_BASE_DBGU2 0xfc069000
#if defined(CONFIG_ARCH_AT91RM9200)
#include <mach/at91rm9200.h>
@@ -40,6 +40,8 @@
#include <mach/at91sam9x5.h>
#elif defined(CONFIG_ARCH_SAMA5D3)
#include <mach/sama5d3.h>
+#elif defined(CONFIG_ARCH_SAMA5D4)
+#include <mach/sama5d4.h>
#elif defined(CONFIG_ARCH_AT91CAP9)
#include <mach/at91cap9.h>
#elif defined(CONFIG_ARCH_AT91X40)
diff --git a/arch/arm/mach-at91/include/mach/sama5d3.h b/arch/arm/mach-at91/include/mach/sama5d3.h
index 6884ff6a7e..e98b101ee0 100644
--- a/arch/arm/mach-at91/include/mach/sama5d3.h
+++ b/arch/arm/mach-at91/include/mach/sama5d3.h
@@ -108,6 +108,8 @@
#define AT91_NB_USART 3
+#define AT91_PMC 0xfffffc00
+
/*
* Internal Memory.
*/
diff --git a/arch/arm/mach-at91/include/mach/sama5d4.h b/arch/arm/mach-at91/include/mach/sama5d4.h
new file mode 100644
index 0000000000..046fdb0426
--- /dev/null
+++ b/arch/arm/mach-at91/include/mach/sama5d4.h
@@ -0,0 +1,134 @@
+/*
+ * Chip-specific header file for the SAMA5D4 family
+ *
+ * Copyright (C) 2014 Atmel Corporation,
+ * Bo Shen <voice.shen@atmel.com>
+ *
+ * Common definitions.
+ * Based on SAMA5D4 datasheet.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef SAMA5D4_H
+#define SAMA5D4_H
+
+/*
+ * Peripheral identifiers/interrupts.
+ */
+#define SAMA5D4_ID_PIT 3
+#define SAMA5D4_ID_WDT 4
+#define SAMA5D4_ID_PIOD 5
+#define SAMA5D4_ID_USART0 6
+#define SAMA5D4_ID_USART1 7
+#define SAMA5D4_ID_DMA0 8
+#define SAMA5D4_ID_ICM 9
+#define SAMA5D4_ID_PKCC 10
+#define SAMA5D4_ID_SCI 11
+#define SAMA5D4_ID_AES 12
+#define SAMA5D4_ID_AESB 13
+#define SAMA5D4_ID_TDES 14
+#define SAMA5D4_ID_SHA 15
+#define SAMA5D4_ID_MPDDRC 16
+#define SAMA5D4_ID_MATRIX1 17
+#define SAMA5D4_ID_MATRIX0 18
+#define SAMA5D4_ID_VDEC 19
+#define SAMA5D4_ID_SECUMOD 20
+#define SAMA5D4_ID_MSADCC 21
+#define SAMA5D4_ID_HSMC 22
+#define SAMA5D4_ID_PIOA 23
+#define SAMA5D4_ID_PIOB 24
+#define SAMA5D4_ID_PIOC 25
+#define SAMA5D4_ID_PIOE 26
+#define SAMA5D4_ID_UART0 27
+#define SAMA5D4_ID_UART1 28
+#define SAMA5D4_ID_USART2 29
+#define SAMA5D4_ID_USART3 30
+#define SAMA5D4_ID_USART4 31
+#define SAMA5D4_ID_TWI0 32
+#define SAMA5D4_ID_TWI1 33
+#define SAMA5D4_ID_TWI2 34
+#define SAMA5D4_ID_HSMCI0 35
+#define SAMA5D4_ID_HSMCI1 36
+#define SAMA5D4_ID_SPI0 37
+#define SAMA5D4_ID_SPI1 38
+#define SAMA5D4_ID_SPI2 39
+#define SAMA5D4_ID_TC0 40
+#define SAMA5D4_ID_TC1 41
+#define SAMA5D4_ID_TC2 42
+#define SAMA5D4_ID_PWM 43
+#define SAMA5D4_ID_ADC 44
+#define SAMA5D4_ID_DBGU 45
+#define SAMA5D4_ID_UHPHS 46
+#define SAMA5D4_ID_UDPHS 47
+#define SAMA5D4_ID_SSC0 48
+#define SAMA5D4_ID_SSC1 49
+#define SAMA5D4_ID_DMA1 50
+#define SAMA5D4_ID_LCDC 51
+#define SAMA5D4_ID_ISI 52
+#define SAMA5D4_ID_TRNG 53
+#define SAMA5D4_ID_GMAC0 54
+#define SAMA5D4_ID_IRQ 56
+#define SAMA5D4_ID_IRQ 56
+#define SAMA5D4_ID_SFC 57
+#define SAMA5D4_ID_SECURAM 59
+#define SAMA5D4_ID_CTB 60
+#define SAMA5D4_ID_SMD 61
+#define SAMA5D4_ID_TWI3 62
+#define SAMA5D4_ID_CATB 63
+#define SAMA5D4_ID_SFR 64
+#define SAMA5D4_ID_AIC 65
+#define SAMA5D4_ID_SAIC 66
+#define SAMA5D4_ID_L2CC 67
+
+/*
+ * User Peripheral physical base addresses.
+ */
+
+#define SAMA5D4_BASE_LCDC 0xf0000000 /* (HLCDC5) Base Address */
+#define SAMA5D4_BASE_MPDDRC 0xf0010000 /* (MPDDRC) Base Address */
+#define SAMA5D4_BASE_PMC 0xf0018000 /* (PMC) Base Address */
+#define SAMA5D4_BASE_HSMCI0 0xf8000000 /* (MMCI0) Base Address */
+#define SAMA5D4_BASE_UART0 0xf8004000 /* (UART0) Base Address */
+#define SAMA5D4_BASE_SPI0 0xf8010000 /* (SPI0) Base Address */
+#define SAMA5D4_BASE_TC0 0xf801c000 /* (TC0) Base Address */
+#define SAMA5D4_BASE_GMAC0 0xf8020000 /* (GMAC0) Base Address */
+#define SAMA5D4_BASE_USART0 0xf802c000 /* (USART0) Base Address */
+#define SAMA5D4_BASE_USART1 0xf8030000 /* (USART1) Base Address */
+#define SAMA5D4_BASE_HSMCI1 0xfc000000 /* (HSMCI1) Base Address */
+#define SAMA5D4_BASE_UART1 0xfc004000 /* (UART1) Base Address */
+#define SAMA5D4_BASE_USART2 0xfc008000 /* (USART2) Base Address */
+#define SAMA5D4_BASE_USART3 0xfc00c000 /* (USART3) Base Address */
+#define SAMA5D4_BASE_USART4 0xfc010000 /* (USART4) Base Address */
+#define SAMA5D4_BASE_SPI1 0xfc018000 /* (SPI1) Base Address */
+#define SAMA5D4_BASE_GMAC1 0xfc028000 /* (GMAC1) Base Address */
+#define SAMA5D4_BASE_HSMC 0xfc05c000 /* (HSMC) Base Address */
+#define SAMA5D4_BASE_PMECC 0xfc05c070 /* (PMECC) Base Address */
+#define SAMA5D4_BASE_PMERRLOC 0xfc05c500 /* (PMERRLOC) Base Address */
+#define SAMA5D4_BASE_PIOD 0xfc068000 /* (PIOD) Base Address */
+#define SAMA5D4_BASE_PIT 0xfc068630 /* (PIT) Base Address */
+#define SAMA5D4_BASE_DBGU 0xfc069000 /* (DBGU) Base Address */
+#define SAMA5D4_BASE_PIOA 0xfc06a000 /* (PIOA) Base Address */
+#define SAMA5D4_BASE_PIOB 0xfc06b000 /* (PIOB) Base Address */
+#define SAMA5D4_BASE_PIOC 0xfc06c000 /* (PIOC) Base Address */
+#define SAMA5D4_BASE_PIOE 0xfc06d000 /* (PIOE) Base Address */
+#define SAMA5D4_BASE_AIC 0xfc06e000 /* (AIC) Base Address */
+
+#define SAMA5D4_CHIPSELECT_3 0x80000000
+
+/*
+ * Internal Memory.
+ */
+#define SAMA5D4_SRAM_BASE 0x00200000 /* Internal SRAM base address */
+#define SAMA5D4_SRAM_SIZE (128 * SZ_1K) /* Internal SRAM size */
+
+#define AT91_NB_USART 7
+#define AT91_BASE_SYS 0xf0000000
+#define AT91_PMC SAMA5D4_BASE_PMC
+#define AT91_DDRSDRC0 (0xf0010000 - AT91_BASE_SYS)
+#define AT91_RSTC (0xfc068600 - AT91_BASE_SYS)
+#define SAMA5D3_BASE_MPDDRC SAMA5D4_BASE_MPDDRC
+#define SAMA5D3_SRAM_BASE SAMA5D4_SRAM_BASE
+#define SAMA5D3_SRAM_SIZE SAMA5D4_SRAM_SIZE
+
+#endif
diff --git a/arch/arm/mach-at91/sam9_smc.c b/arch/arm/mach-at91/sam9_smc.c
index 403fa9b1c4..6346bb440c 100644
--- a/arch/arm/mach-at91/sam9_smc.c
+++ b/arch/arm/mach-at91/sam9_smc.c
@@ -20,7 +20,9 @@
#define AT91_SAM9_SMC_CS_STRIDE 0x10
#define AT91_SAMA5_SMC_CS_STRIDE 0x14
-#define AT91_SMC_CS_STRIDE ((at91_soc_initdata.type == AT91_SOC_SAMA5D3) ? AT91_SAMA5_SMC_CS_STRIDE : AT91_SAM9_SMC_CS_STRIDE)
+#define AT91_SMC_CS_STRIDE ((at91_soc_initdata.type == AT91_SOC_SAMA5D3 \
+ || at91_soc_initdata.type == AT91_SOC_SAMA5D4) \
+ ? AT91_SAMA5_SMC_CS_STRIDE : AT91_SAM9_SMC_CS_STRIDE)
#define AT91_SMC_CS(id, n) (smc_base_addr[id] + ((n) * AT91_SMC_CS_STRIDE))
static void __iomem *smc_base_addr[2];
@@ -30,7 +32,15 @@ static void sam9_smc_cs_write_mode(void __iomem *base,
{
void __iomem *mode_reg;
- mode_reg = base + ((at91_soc_initdata.type == AT91_SOC_SAMA5D3) ? AT91_SAMA5_SMC_MODE : AT91_SAM9_SMC_MODE);
+ switch (at91_soc_initdata.type) {
+ case AT91_SOC_SAMA5D3:
+ case AT91_SOC_SAMA5D4:
+ mode_reg = base + AT91_SAMA5_SMC_MODE;
+ break;
+ default:
+ mode_reg = base + AT91_SAM9_SMC_MODE;
+ break;
+ }
__raw_writel(config->mode
| AT91_SMC_TDF_(config->tdf_cycles),
@@ -96,7 +106,15 @@ static void sam9_smc_cs_read_mode(void __iomem *base,
u32 val;
void __iomem *mode_reg;
- mode_reg = base + ((at91_soc_initdata.type == AT91_SOC_SAMA5D3) ? AT91_SAMA5_SMC_MODE : AT91_SAM9_SMC_MODE);
+ switch (at91_soc_initdata.type) {
+ case AT91_SOC_SAMA5D3:
+ case AT91_SOC_SAMA5D4:
+ mode_reg = base + AT91_SAMA5_SMC_MODE;
+ break;
+ default:
+ mode_reg = base + AT91_SAM9_SMC_MODE;
+ break;
+ }
val = __raw_readl(mode_reg);
diff --git a/arch/arm/mach-at91/sama5d4.c b/arch/arm/mach-at91/sama5d4.c
new file mode 100644
index 0000000000..4d380ed88e
--- /dev/null
+++ b/arch/arm/mach-at91/sama5d4.c
@@ -0,0 +1,304 @@
+/*
+ * Chip-specific setup code for the SAMA5D4 family
+ *
+ * Copyright (C) 2014 Atmel Corporation,
+ * Bo Shen <voice.shen@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <common.h>
+#include <gpio.h>
+#include <init.h>
+#include <mach/hardware.h>
+#include <mach/at91_pmc.h>
+#include <mach/io.h>
+#include <mach/cpu.h>
+#include <linux/clk.h>
+
+#include "soc.h"
+#include "generic.h"
+#include "clock.h"
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk pit_clk = {
+ .name = "pit_clk",
+ .pid = SAMA5D4_ID_PIT,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk smc_clk = {
+ .name = "smc_clk",
+ .pid = SAMA5D4_ID_HSMC,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioA_clk = {
+ .name = "pioA_clk",
+ .pid = SAMA5D4_ID_PIOA,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+ .name = "pioB_clk",
+ .pid = SAMA5D4_ID_PIOB,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioC_clk = {
+ .name = "pioC_clk",
+ .pid = SAMA5D4_ID_PIOC,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioD_clk = {
+ .name = "pioD_clk",
+ .pid = SAMA5D4_ID_PIOD,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioE_clk = {
+ .name = "pioE_clk",
+ .pid = SAMA5D4_ID_PIOE,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+ .name = "usart0_clk",
+ .pid = SAMA5D4_ID_USART0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+ .name = "usart2_clk",
+ .pid = SAMA5D4_ID_USART2,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart3_clk = {
+ .name = "usart3_clk",
+ .pid = SAMA5D4_ID_USART3,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart4_clk = {
+ .name = "usart4_clk",
+ .pid = SAMA5D4_ID_USART4,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc0_clk = {
+ .name = "mci0_clk",
+ .pid = SAMA5D4_ID_HSMCI0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc1_clk = {
+ .name = "mci1_clk",
+ .pid = SAMA5D4_ID_HSMCI1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tcb0_clk = {
+ .name = "tcb0_clk",
+ .pid = SAMA5D4_ID_TC0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tcb1_clk = {
+ .name = "tcb1_clk",
+ .pid = SAMA5D4_ID_TC1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk adc_clk = {
+ .name = "adc_clk",
+ .pid = SAMA5D4_ID_ADC,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk dma0_clk = {
+ .name = "dma0_clk",
+ .pid = SAMA5D4_ID_DMA0,
+ .type = CLK_TYPE_PERIPHERAL | CLK_TYPE_PERIPH_H64MX,
+};
+static struct clk dma1_clk = {
+ .name = "dma1_clk",
+ .pid = SAMA5D4_ID_DMA1,
+ .type = CLK_TYPE_PERIPHERAL | CLK_TYPE_PERIPH_H64MX,
+};
+static struct clk uhphs_clk = {
+ .name = "uhphs",
+ .pid = SAMA5D4_ID_UHPHS,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk udphs_clk = {
+ .name = "udphs_clk",
+ .pid = SAMA5D4_ID_UDPHS,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk lcdc_clk = {
+ .name = "lcdc_clk",
+ .pid = SAMA5D4_ID_LCDC,
+ .type = CLK_TYPE_PERIPHERAL | CLK_TYPE_PERIPH_H64MX,
+};
+static struct clk isi_clk = {
+ .name = "isi_clk",
+ .pid = SAMA5D4_ID_ISI,
+ .type = CLK_TYPE_PERIPHERAL | CLK_TYPE_PERIPH_H64MX,
+};
+static struct clk macb0_clk = {
+ .name = "macb0_clk",
+ .pid = SAMA5D4_ID_GMAC0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi0_clk = {
+ .name = "twi0_clk",
+ .pid = SAMA5D4_ID_TWI0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi2_clk = {
+ .name = "twi2_clk",
+ .pid = SAMA5D4_ID_TWI2,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi0_clk = {
+ .name = "spi0_clk",
+ .pid = SAMA5D4_ID_SPI0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk smd_clk = {
+ .name = "smd_clk",
+ .pid = SAMA5D4_ID_SMD,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ssc0_clk = {
+ .name = "ssc0_clk",
+ .pid = SAMA5D4_ID_SSC0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ssc1_clk = {
+ .name = "ssc1_clk",
+ .pid = SAMA5D4_ID_SSC1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk sha_clk = {
+ .name = "sha_clk",
+ .pid = SAMA5D4_ID_SHA,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk aes_clk = {
+ .name = "aes_clk",
+ .pid = SAMA5D4_ID_AES,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tdes_clk = {
+ .name = "tdes_clk",
+ .pid = SAMA5D4_ID_TDES,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+ &pit_clk,
+ &smc_clk,
+ &pioA_clk,
+ &pioB_clk,
+ &pioC_clk,
+ &pioD_clk,
+ &pioE_clk,
+ &usart0_clk,
+ &usart2_clk,
+ &usart3_clk,
+ &usart4_clk,
+ &mmc0_clk,
+ &mmc1_clk,
+ &tcb0_clk,
+ &tcb1_clk,
+ &adc_clk,
+ &dma0_clk,
+ &dma1_clk,
+ &uhphs_clk,
+ &udphs_clk,
+ &lcdc_clk,
+ &isi_clk,
+ &macb0_clk,
+ &twi0_clk,
+ &twi2_clk,
+ &spi0_clk,
+ &smd_clk,
+ &ssc0_clk,
+ &ssc1_clk,
+ &sha_clk,
+ &aes_clk,
+ &tdes_clk,
+};
+
+static struct clk pck0 = {
+ .name = "pck0",
+ .pmc_mask = AT91_PMC_PCK0,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 0,
+};
+
+static struct clk pck1 = {
+ .name = "pck1",
+ .pmc_mask = AT91_PMC_PCK1,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 1,
+};
+
+static struct clk pck2 = {
+ .name = "pck2",
+ .pmc_mask = AT91_PMC_PCK2,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 2,
+};
+
+static struct clk_lookup periph_clocks_lookups[] = {
+ CLKDEV_CON_DEV_ID("macb_clk", "macb0", &macb0_clk),
+ CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci0", &mmc0_clk),
+ CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci1", &mmc1_clk),
+ CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi0", &spi0_clk),
+ CLKDEV_DEV_ID("at91-pit", &pit_clk),
+ CLKDEV_CON_DEV_ID("hck1", "atmel_hlcdfb", &lcdc_clk),
+};
+
+static struct clk_lookup usart_clocks_lookups[] = {
+ CLKDEV_CON_DEV_ID("usart", "atmel_usart0", &mck),
+ CLKDEV_CON_DEV_ID("usart", "atmel_usart1", &usart0_clk),
+ CLKDEV_CON_DEV_ID("usart", "atmel_usart3", &usart2_clk),
+ CLKDEV_CON_DEV_ID("usart", "atmel_usart4", &usart3_clk),
+};
+
+static void __init sama5d4_register_clocks(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+ clk_register(periph_clocks[i]);
+
+ clkdev_add_physbase(&pioA_clk, SAMA5D4_BASE_PIOA, 0);
+ clkdev_add_physbase(&pioB_clk, SAMA5D4_BASE_PIOB, 0);
+ clkdev_add_physbase(&pioC_clk, SAMA5D4_BASE_PIOC, 0);
+ clkdev_add_physbase(&pioD_clk, SAMA5D4_BASE_PIOD, 0);
+ clkdev_add_physbase(&pioE_clk, SAMA5D4_BASE_PIOE, 0);
+
+ clkdev_add_table(periph_clocks_lookups,
+ ARRAY_SIZE(periph_clocks_lookups));
+
+ clkdev_add_table(usart_clocks_lookups,
+ ARRAY_SIZE(usart_clocks_lookups));
+
+ clk_register(&pck0);
+ clk_register(&pck1);
+ clk_register(&pck2);
+}
+
+/* --------------------------------------------------------------------
+ * Processor initialization
+ * -------------------------------------------------------------------- */
+static void sama5d4_initialize(void)
+{
+ /* Register the processor-specific clocks */
+ sama5d4_register_clocks();
+
+ /* Register GPIO subsystem */
+ at91_add_sam9x5_gpio(0, SAMA5D4_BASE_PIOA);
+ at91_add_sam9x5_gpio(1, SAMA5D4_BASE_PIOB);
+ at91_add_sam9x5_gpio(2, SAMA5D4_BASE_PIOC);
+ at91_add_sam9x5_gpio(3, SAMA5D4_BASE_PIOD);
+ at91_add_sam9x5_gpio(4, SAMA5D4_BASE_PIOE);
+
+ at91_add_pit(SAMA5D4_BASE_PIT);
+ at91_add_sam9_smc(DEVICE_ID_SINGLE, SAMA5D4_BASE_HSMC + 0x600, 0xa0);
+}
+
+AT91_SOC_START(sama5d4)
+ .init = sama5d4_initialize,
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/sama5d4_devices.c b/arch/arm/mach-at91/sama5d4_devices.c
new file mode 100644
index 0000000000..3806971688
--- /dev/null
+++ b/arch/arm/mach-at91/sama5d4_devices.c
@@ -0,0 +1,495 @@
+/*
+ * On-Chip devices setup code for the SAMA5D4 family
+ *
+ * Copyright (C) 2014 Atmel Corporation.
+ * Bo Shen <voice.shen@atmel.com>
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <sizes.h>
+#include <gpio.h>
+#include <asm/armlinux.h>
+#include <mach/hardware.h>
+#include <mach/board.h>
+#include <mach/at91_pmc.h>
+#include <mach/at91sam9x5_matrix.h>
+#include <mach/at91sam9_ddrsdr.h>
+#include <mach/iomux.h>
+#include <mach/io.h>
+#include <mach/cpu.h>
+#include <i2c/i2c-gpio.h>
+
+#include "generic.h"
+
+void at91_add_device_sdram(u32 size)
+{
+ if (!size)
+ size = at91sama5_get_ddram_size();
+
+ arm_add_mem_device("ram0", SAMA5_DDRCS, size);
+ add_mem_device("sram0", SAMA5D4_SRAM_BASE,
+ SAMA5D4_SRAM_SIZE, IORESOURCE_MEM_WRITEABLE);
+}
+
+/* --------------------------------------------------------------------
+ * NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+#if defined(CONFIG_NAND_ATMEL)
+static struct resource nand_resources[] = {
+ [0] = {
+ .start = SAMA5D4_CHIPSELECT_3,
+ .end = SAMA5D4_CHIPSELECT_3 + SZ_128M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = SAMA5D4_BASE_PMECC,
+ .end = SAMA5D4_BASE_PMECC + 0x490 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = SAMA5D4_BASE_PMERRLOC,
+ .end = SAMA5D4_BASE_PMERRLOC + 0x100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+void __init at91_add_device_nand(struct atmel_nand_data *data)
+{
+ if (!data)
+ return;
+
+ at91_set_A_periph(AT91_PIN_PC5, 0); /* D0 */
+ at91_set_A_periph(AT91_PIN_PC6, 0); /* D1 */
+ at91_set_A_periph(AT91_PIN_PC7, 0); /* D2 */
+ at91_set_A_periph(AT91_PIN_PC8, 0); /* D3 */
+ at91_set_A_periph(AT91_PIN_PC9, 0); /* D4 */
+ at91_set_A_periph(AT91_PIN_PC10, 0); /* D5 */
+ at91_set_A_periph(AT91_PIN_PC11, 0); /* D6 */
+ at91_set_A_periph(AT91_PIN_PC12, 0); /* D7 */
+ at91_set_A_periph(AT91_PIN_PC13, 0); /* RE */
+ at91_set_A_periph(AT91_PIN_PC14, 0); /* WE */
+ at91_set_A_periph(AT91_PIN_PC15, 1); /* NCS */
+ at91_set_A_periph(AT91_PIN_PC16, 1); /* RDY */
+ at91_set_A_periph(AT91_PIN_PC17, 1); /* ALE */
+ at91_set_A_periph(AT91_PIN_PC18, 1); /* CLE */
+
+ /* enable pin */
+ if (gpio_is_valid(data->enable_pin))
+ at91_set_gpio_output(data->enable_pin, 1);
+
+ /* ready/busy pin */
+ if (gpio_is_valid(data->rdy_pin))
+ at91_set_gpio_input(data->rdy_pin, 1);
+
+ /* card detect pin */
+ if (gpio_is_valid(data->det_pin))
+ at91_set_gpio_input(data->det_pin, 1);
+
+ add_generic_device_res("atmel_nand", 0, nand_resources,
+ ARRAY_SIZE(nand_resources), data);
+}
+#else
+void __init at91_add_device_nand(struct atmel_nand_data *data) {}
+#endif
+
+#if defined(CONFIG_DRIVER_NET_MACB)
+void at91_add_device_eth(int id, struct macb_platform_data *data)
+{
+ if (!data)
+ return;
+
+ switch (id) {
+ case 0:
+ at91_set_A_periph(AT91_PIN_PB16, 0); /* GMDC */
+ at91_set_A_periph(AT91_PIN_PB17, 0); /* GMDIO */
+
+ at91_set_A_periph(AT91_PIN_PB0, 0); /* GTXCK */
+ at91_set_A_periph(AT91_PIN_PB2, 0); /* GTXEN */
+ at91_set_A_periph(AT91_PIN_PB6, 0); /* GRXDV */
+ at91_set_A_periph(AT91_PIN_PB7, 0); /* GRXER */
+
+ switch (data->phy_interface) {
+ case PHY_INTERFACE_MODE_MII:
+ at91_set_A_periph(AT91_PIN_PB4, 0); /* GCRS */
+ at91_set_A_periph(AT91_PIN_PB5, 0); /* GCOL */
+ at91_set_A_periph(AT91_PIN_PB14, 0); /* GTX2 */
+ at91_set_A_periph(AT91_PIN_PB15, 0); /* GTX3 */
+ at91_set_A_periph(AT91_PIN_PB3, 0); /* GTXER */
+ at91_set_A_periph(AT91_PIN_PB1, 0); /* GRXCK */
+ at91_set_A_periph(AT91_PIN_PB10, 0); /* GRX2 */
+ at91_set_A_periph(AT91_PIN_PB11, 0); /* GRX3 */
+ case PHY_INTERFACE_MODE_RMII:
+ at91_set_A_periph(AT91_PIN_PB12, 0); /* GTX0 */
+ at91_set_A_periph(AT91_PIN_PB13, 0); /* GTX1 */
+ at91_set_A_periph(AT91_PIN_PB8, 0); /* GRX0 */
+ at91_set_A_periph(AT91_PIN_PB9, 0); /* GRX1 */
+ break;
+ default:
+ return;
+ }
+
+ add_generic_device("macb", id, NULL, SAMA5D4_BASE_GMAC0, SZ_16K,
+ IORESOURCE_MEM, data);
+ break;
+ case 1:
+ at91_set_B_periph(AT91_PIN_PA22, 0); /* GMDC */
+ at91_set_B_periph(AT91_PIN_PA23, 0); /* GMDIO */
+
+ at91_set_B_periph(AT91_PIN_PA2, 0); /* GTXCK */
+ at91_set_B_periph(AT91_PIN_PA4, 0); /* GTXEN */
+ at91_set_B_periph(AT91_PIN_PA10, 0); /* GRXDV */
+ at91_set_B_periph(AT91_PIN_PA11, 0); /* GRXER */
+
+ switch (data->phy_interface) {
+ case PHY_INTERFACE_MODE_MII:
+ at91_set_B_periph(AT91_PIN_PA6, 0); /* GCRS */
+ at91_set_B_periph(AT91_PIN_PA9, 0); /* GCOL */
+ at91_set_B_periph(AT91_PIN_PA20, 0); /* GTX2 */
+ at91_set_B_periph(AT91_PIN_PA21, 0); /* GTX3 */
+ at91_set_B_periph(AT91_PIN_PA5, 0); /* GTXER */
+ at91_set_B_periph(AT91_PIN_PA3, 0); /* GRXCK */
+ at91_set_B_periph(AT91_PIN_PA18, 0); /* GRX2 */
+ at91_set_B_periph(AT91_PIN_PA19, 0); /* GRX3 */
+ case PHY_INTERFACE_MODE_RMII:
+ at91_set_B_periph(AT91_PIN_PA12, 0); /* GTX0 */
+ at91_set_B_periph(AT91_PIN_PA13, 0); /* GTX1 */
+ at91_set_B_periph(AT91_PIN_PA8, 0); /* GRX0 */
+ at91_set_B_periph(AT91_PIN_PA9, 0); /* GRX1 */
+ break;
+ default:
+ return;
+ }
+
+ add_generic_device("macb", id, NULL, SAMA5D4_BASE_GMAC1, SZ_16K,
+ IORESOURCE_MEM, data);
+ break;
+ default:
+ return;
+ }
+
+}
+#else
+void at91_add_device_eth(int id, struct macb_platform_data *data) {}
+#endif
+
+#if defined(CONFIG_MCI_ATMEL)
+void __init at91_add_device_mci(short mmc_id,
+ struct atmel_mci_platform_data *data)
+{
+ resource_size_t start = ~0;
+
+ if (!data)
+ return;
+
+ /* Must have at least one usable slot */
+ if (!data->bus_width)
+ return;
+
+ /* input/irq */
+ if (gpio_is_valid(data->detect_pin)) {
+ at91_set_gpio_input(data->detect_pin, 1);
+ at91_set_deglitch(data->detect_pin, 1);
+ }
+
+ if (gpio_is_valid(data->wp_pin))
+ at91_set_gpio_input(data->wp_pin, 1);
+
+ switch (mmc_id) {
+ /* MCI0 */
+ case 0:
+ start = SAMA5D4_BASE_HSMCI0;
+
+ /* CLK */
+ at91_set_B_periph(AT91_PIN_PC4, 0);
+
+ /* CMD */
+ at91_set_B_periph(AT91_PIN_PC5, 1);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_B_periph(AT91_PIN_PC6, 1);
+ switch (data->bus_width) {
+ case 8:
+ at91_set_B_periph(AT91_PIN_PC10, 1);
+ at91_set_B_periph(AT91_PIN_PC11, 1);
+ at91_set_B_periph(AT91_PIN_PC12, 1);
+ at91_set_B_periph(AT91_PIN_PC13, 1);
+ case 4:
+ at91_set_B_periph(AT91_PIN_PC7, 1);
+ at91_set_B_periph(AT91_PIN_PC8, 1);
+ at91_set_B_periph(AT91_PIN_PC9, 1);
+ };
+
+ break;
+ /* MCI1 */
+ case 1:
+ start = SAMA5D4_BASE_HSMCI1;
+
+ /*
+ * As the mci1 io internal pull down is to strong,
+ * which cause external pull up doesn't work, so,
+ * disable internal pull down.
+ */
+
+ /* CLK */
+ at91_set_C_periph(AT91_PIN_PE18, 0);
+ at91_set_pulldown(AT91_PIN_PE18, 0);
+
+ /* CMD */
+ at91_set_C_periph(AT91_PIN_PE19, 1);
+ at91_set_pulldown(AT91_PIN_PE19, 0);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_C_periph(AT91_PIN_PE20, 1);
+ at91_set_pulldown(AT91_PIN_PE20, 0);
+ if (data->bus_width == 4) {
+ at91_set_C_periph(AT91_PIN_PE21, 1);
+ at91_set_pulldown(AT91_PIN_PE21, 0);
+ at91_set_C_periph(AT91_PIN_PE22, 1);
+ at91_set_pulldown(AT91_PIN_PE22, 0);
+ at91_set_C_periph(AT91_PIN_PE23, 1);
+ at91_set_pulldown(AT91_PIN_PE23, 0);
+ }
+
+ break;
+ }
+
+ add_generic_device("atmel_mci", mmc_id, NULL, start, SZ_16K,
+ IORESOURCE_MEM, data);
+}
+#else
+void __init at91_add_device_mci(short mmc_id,
+ struct atmel_mci_platform_data *data) {}
+#endif
+
+#if defined(CONFIG_I2C_GPIO)
+static struct i2c_gpio_platform_data pdata_i2c[] = {
+ {
+ .sda_pin = AT91_PIN_PA30,
+ .sda_is_open_drain = 1,
+ .scl_pin = AT91_PIN_PA31,
+ .scl_is_open_drain = 1,
+ .udelay = 5, /* ~100 kHz */
+ }, {
+ .sda_pin = AT91_PIN_PE29,
+ .sda_is_open_drain = 1,
+ .scl_pin = AT91_PIN_PE30,
+ .scl_is_open_drain = 1,
+ .udelay = 5, /* ~100 kHz */
+ }, {
+ .sda_pin = AT91_PIN_PB29,
+ .sda_is_open_drain = 1,
+ .scl_pin = AT91_PIN_PB30,
+ .scl_is_open_drain = 1,
+ .udelay = 5, /* ~100 kHz */
+ }, {
+ .sda_pin = AT91_PIN_PC25,
+ .sda_is_open_drain = 1,
+ .scl_pin = AT91_PIN_PC26,
+ .scl_is_open_drain = 1,
+ .udelay = 5, /* ~100 kHz */
+ }
+};
+
+void at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices,
+ int nr_devices)
+{
+ struct i2c_gpio_platform_data *pdata;
+
+ if (i2c_id > ARRAY_SIZE(pdata_i2c))
+ return;
+
+ i2c_register_board_info(i2c_id, devices, nr_devices);
+
+ pdata = &pdata_i2c[i2c_id];
+
+ at91_set_GPIO_periph(pdata->sda_pin, 1); /* TWD (SDA) */
+ at91_set_multi_drive(pdata->sda_pin, 1);
+
+ at91_set_GPIO_periph(pdata->scl_pin, 1); /* TWCK (SCL) */
+ at91_set_multi_drive(pdata->scl_pin, 1);
+
+ add_generic_device_res("i2c-gpio", i2c_id, NULL, 0, pdata);
+}
+#else
+void at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices,
+ int nr_devices) {}
+#endif
+
+/* --------------------------------------------------------------------
+ * SPI
+ * -------------------------------------------------------------------- */
+#if defined(CONFIG_DRIVER_SPI_ATMEL)
+static unsigned spi0_standard_cs[2] = { AT91_PIN_PC3, AT91_PIN_PC4 };
+static unsigned spi1_standard_cs[2] = { AT91_PIN_PB21, AT91_PIN_PB22 };
+
+static struct at91_spi_platform_data spi_pdata[] = {
+ [0] = {
+ .chipselect = spi0_standard_cs,
+ .num_chipselect = ARRAY_SIZE(spi0_standard_cs),
+ },
+ [1] = {
+ .chipselect = spi1_standard_cs,
+ .num_chipselect = ARRAY_SIZE(spi1_standard_cs),
+ },
+};
+
+void at91_add_device_spi(int spi_id, struct at91_spi_platform_data *pdata)
+{
+ int i;
+ int cs_pin;
+ resource_size_t start = ~0;
+
+ BUG_ON(spi_id > 1);
+
+ if (!pdata)
+ pdata = &spi_pdata[spi_id];
+
+ for (i = 0; i < pdata->num_chipselect; i++) {
+ cs_pin = pdata->chipselect[i];
+
+ /* enable chip-select pin */
+ if (gpio_is_valid(cs_pin))
+ at91_set_gpio_output(cs_pin, 1);
+ }
+
+ /* Configure SPI bus(es) */
+ switch (spi_id) {
+ case 0:
+ start = SAMA5D4_BASE_SPI0;
+ at91_set_A_periph(AT91_PIN_PC0, 0); /* SPI0_MISO */
+ at91_set_A_periph(AT91_PIN_PC1, 0); /* SPI0_MOSI */
+ at91_set_A_periph(AT91_PIN_PC2, 0); /* SPI0_SPCK */
+ break;
+ case 1:
+ start = SAMA5D4_BASE_SPI1;
+ at91_set_A_periph(AT91_PIN_PB18, 0); /* SPI1_MISO */
+ at91_set_A_periph(AT91_PIN_PB19, 0); /* SPI1_MOSI */
+ at91_set_A_periph(AT91_PIN_PB20, 0); /* SPI1_SPCK */
+ break;
+ }
+
+ add_generic_device("atmel_spi", spi_id, NULL, start, SZ_16K,
+ IORESOURCE_MEM, pdata);
+}
+#else
+void at91_add_device_spi(int spi_id, struct at91_spi_platform_data *pdata) {}
+#endif
+
+/* --------------------------------------------------------------------
+ * LCD Controller
+ * -------------------------------------------------------------------- */
+#if defined(CONFIG_DRIVER_VIDEO_ATMEL_HLCD)
+void __init at91_add_device_lcdc(struct atmel_lcdfb_platform_data *data)
+{
+ BUG_ON(!data);
+
+ at91_set_A_periph(AT91_PIN_PA24, 0); /* LCDPWM */
+ at91_set_A_periph(AT91_PIN_PA25, 0); /* LCDDISP */
+ at91_set_A_periph(AT91_PIN_PA26, 0); /* LCDVSYNC */
+ at91_set_A_periph(AT91_PIN_PA27, 0); /* LCDHSYNC */
+ at91_set_A_periph(AT91_PIN_PA28, 0); /* LCDDOTCK */
+ at91_set_A_periph(AT91_PIN_PA29, 0); /* LCDDEN */
+
+ at91_set_A_periph(AT91_PIN_PA2, 0); /* LCDD2 */
+ at91_set_A_periph(AT91_PIN_PA3, 0); /* LCDD3 */
+ at91_set_A_periph(AT91_PIN_PA4, 0); /* LCDD4 */
+ at91_set_A_periph(AT91_PIN_PA5, 0); /* LCDD5 */
+ at91_set_A_periph(AT91_PIN_PA6, 0); /* LCDD6 */
+ at91_set_A_periph(AT91_PIN_PA7, 0); /* LCDD7 */
+
+ at91_set_A_periph(AT91_PIN_PA10, 0); /* LCDD10 */
+ at91_set_A_periph(AT91_PIN_PA11, 0); /* LCDD11 */
+ at91_set_A_periph(AT91_PIN_PA12, 0); /* LCDD12 */
+ at91_set_A_periph(AT91_PIN_PA13, 0); /* LCDD13 */
+ at91_set_A_periph(AT91_PIN_PA14, 0); /* LCDD14 */
+ at91_set_A_periph(AT91_PIN_PA15, 0); /* LCDD15 */
+
+ at91_set_A_periph(AT91_PIN_PA18, 0); /* LCDD18 */
+ at91_set_A_periph(AT91_PIN_PA19, 0); /* LCDD19 */
+ at91_set_A_periph(AT91_PIN_PA20, 0); /* LCDD20 */
+ at91_set_A_periph(AT91_PIN_PA21, 0); /* LCDD21 */
+ at91_set_A_periph(AT91_PIN_PA22, 0); /* LCDD22 */
+ at91_set_A_periph(AT91_PIN_PA23, 0); /* LCDD23 */
+
+ add_generic_device("atmel_hlcdfb", DEVICE_ID_SINGLE, NULL,
+ SAMA5D4_BASE_LCDC, SZ_4K, IORESOURCE_MEM, data);
+}
+#else
+void __init at91_add_device_lcdc(struct atmel_lcdfb_platform_data *data) {}
+#endif
+
+/* --------------------------------------------------------------------
+ * UART
+ * -------------------------------------------------------------------- */
+#if defined(CONFIG_DRIVER_SERIAL_ATMEL)
+resource_size_t __init at91_configure_dbgu(void)
+{
+ at91_set_A_periph(AT91_PIN_PB25, 1); /* TXD1 */
+ at91_set_A_periph(AT91_PIN_PB24, 0); /* RXD1 */
+
+ return SAMA5D4_BASE_DBGU;
+}
+
+resource_size_t __init at91_configure_usart0(unsigned pins)
+{
+ at91_set_A_periph(AT91_PIN_PD13, 1); /* TXD1 */
+ at91_set_A_periph(AT91_PIN_PD12, 0); /* RXD1 */
+
+ return SAMA5D4_BASE_USART0;
+}
+
+resource_size_t __init at91_configure_usart1(unsigned pins)
+{
+ at91_set_A_periph(AT91_PIN_PD17, 1); /* TXD1 */
+ at91_set_A_periph(AT91_PIN_PD16, 0); /* RXD1 */
+
+ return SAMA5D4_BASE_USART1;
+}
+
+
+resource_size_t __init at91_configure_usart2(unsigned pins)
+{
+ at91_set_B_periph(AT91_PIN_PB5, 1); /* TXD1 */
+ at91_set_B_periph(AT91_PIN_PB4, 0); /* RXD1 */
+
+ return SAMA5D4_BASE_USART2;
+}
+
+resource_size_t __init at91_configure_usart3(unsigned pins)
+{
+ at91_set_B_periph(AT91_PIN_PE17, 1); /* TXD1 */
+ at91_set_B_periph(AT91_PIN_PE16, 0); /* RXD1 */
+
+ return SAMA5D4_BASE_USART3;
+}
+
+resource_size_t __init at91_configure_usart4(unsigned pins)
+{
+ at91_set_B_periph(AT91_PIN_PE27, 1); /* TXD1 */
+ at91_set_B_periph(AT91_PIN_PE26, 0); /* RXD1 */
+
+ return SAMA5D4_BASE_USART4;
+}
+
+resource_size_t __init at91_configure_usart5(unsigned pins)
+{
+ at91_set_B_periph(AT91_PIN_PE30, 1); /* TXD1 */
+ at91_set_B_periph(AT91_PIN_PE29, 0); /* RXD1 */
+
+ return SAMA5D4_BASE_UART0;
+}
+
+resource_size_t __init at91_configure_usart6(unsigned pins)
+{
+ at91_set_C_periph(AT91_PIN_PC26, 1); /* TXD1 */
+ at91_set_C_periph(AT91_PIN_PC25, 0); /* RXD1 */
+
+ return SAMA5D4_BASE_UART1;
+}
+#endif
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 076d0812b3..030b8a2c58 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -39,6 +39,9 @@ static void __init soc_detect(u32 dbgu_base)
cidr = __raw_readl(dbgu_base + AT91_DBGU_CIDR);
socid = cidr & ~AT91_CIDR_VERSION;
+ /* sub version of soc */
+ at91_soc_initdata.exid = __raw_readl(dbgu_base + AT91_DBGU_EXID);
+
switch (socid) {
case ARCH_ID_AT91RM9200:
at91_soc_initdata.type = AT91_SOC_RM9200;
@@ -89,9 +92,16 @@ static void __init soc_detect(u32 dbgu_base)
at91_boot_soc = at91sam9n12_soc;
break;
- case ARCH_ID_SAMA5D3:
- at91_soc_initdata.type = AT91_SOC_SAMA5D3;
- at91_boot_soc = at91sama5d3_soc;
+ case ARCH_ID_SAMA5:
+ if (at91_soc_initdata.exid & ARCH_EXID_SAMA5D3) {
+ at91_soc_initdata.type = AT91_SOC_SAMA5D3;
+ at91_boot_soc = at91sama5d3_soc;
+ } else {
+ if (at91_soc_initdata.exid & ARCH_EXID_SAMA5D4) {
+ at91_soc_initdata.type = AT91_SOC_SAMA5D4;
+ at91_boot_soc = at91sama5d4_soc;
+ }
+ }
break;
}
@@ -112,9 +122,6 @@ static void __init soc_detect(u32 dbgu_base)
at91_soc_initdata.cidr = cidr;
- /* sub version of soc */
- at91_soc_initdata.exid = __raw_readl(dbgu_base + AT91_DBGU_EXID);
-
if (at91_soc_initdata.type == AT91_SOC_SAM9G45) {
switch (at91_soc_initdata.exid) {
case ARCH_EXID_AT91SAM9M10:
@@ -168,6 +175,23 @@ static void __init soc_detect(u32 dbgu_base)
break;
}
}
+
+ if (at91_soc_initdata.type == AT91_SOC_SAMA5D4) {
+ switch (at91_soc_initdata.exid) {
+ case ARCH_EXID_SAMA5D41:
+ at91_soc_initdata.subtype = AT91_SOC_SAMA5D41;
+ break;
+ case ARCH_EXID_SAMA5D42:
+ at91_soc_initdata.subtype = AT91_SOC_SAMA5D42;
+ break;
+ case ARCH_EXID_SAMA5D43:
+ at91_soc_initdata.subtype = AT91_SOC_SAMA5D43;
+ break;
+ case ARCH_EXID_SAMA5D44:
+ at91_soc_initdata.subtype = AT91_SOC_SAMA5D44;
+ break;
+ }
+ }
}
static const char *soc_name[] = {
@@ -182,6 +206,7 @@ static const char *soc_name[] = {
[AT91_SOC_SAM9X5] = "at91sam9x5",
[AT91_SOC_SAM9N12] = "at91sam9n12",
[AT91_SOC_SAMA5D3] = "sama5d3",
+ [AT91_SOC_SAMA5D4] = "sama5d4",
[AT91_SOC_NONE] = "Unknown"
};
@@ -209,6 +234,10 @@ static const char *soc_subtype_name[] = {
[AT91_SOC_SAMA5D34] = "sama5d34",
[AT91_SOC_SAMA5D35] = "sama5d35",
[AT91_SOC_SAMA5D36] = "sama5d36",
+ [AT91_SOC_SAMA5D41] = "sama5d41",
+ [AT91_SOC_SAMA5D42] = "sama5d42",
+ [AT91_SOC_SAMA5D43] = "sama5d43",
+ [AT91_SOC_SAMA5D44] = "sama5d44",
[AT91_SOC_SUBTYPE_NONE] = "Unknown"
};
@@ -226,6 +255,8 @@ static int at91_detect(void)
soc_detect(AT91_BASE_DBGU0);
if (!at91_soc_is_detected())
soc_detect(AT91_BASE_DBGU1);
+ if (!at91_soc_is_detected())
+ soc_detect(AT91_BASE_DBGU2);
if (!at91_soc_is_detected())
panic("AT91: Impossible to detect the SOC type");
diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
index b2278a5b32..76e4621f8a 100644
--- a/arch/arm/mach-at91/soc.h
+++ b/arch/arm/mach-at91/soc.h
@@ -19,6 +19,7 @@ extern struct at91_init_soc at91sam9rl_soc;
extern struct at91_init_soc at91sam9x5_soc;
extern struct at91_init_soc at91sam9n12_soc;
extern struct at91_init_soc at91sama5d3_soc;
+extern struct at91_init_soc at91sama5d4_soc;
#define AT91_SOC_START(_name) \
struct at91_init_soc __initdata at91##_name##_soc \
@@ -66,6 +67,10 @@ static inline int at91_soc_is_enabled(void)
#define at91sam9n12_soc at91_boot_soc
#endif
-#if !defined(CONFIG_SOC_SAMA5)
+#if !defined(CONFIG_ARCH_SAMA5D3)
#define at91sama5d3_soc at91_boot_soc
#endif
+
+#if !defined(CONFIG_ARCH_SAMA5D4)
+#define at91sama5d4_soc at91_boot_soc
+#endif
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 53a44a06e9..ef7c0a1963 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -261,6 +261,10 @@ config MACH_TQMA6X
bool "TQ tqma6x on mba6x"
select ARCH_IMX6
+config MACH_TX6X
+ bool "Karo TX6x"
+ select ARCH_IMX6
+
config MACH_SABRELITE
bool "Freescale i.MX6 Sabre Lite"
select ARCH_IMX6
@@ -291,6 +295,9 @@ config MACH_VARISCITE_MX6
bool "Variscite i.MX6 Quad SOM"
select ARCH_IMX6
+config MACH_GW_VENTANA
+ bool "Gateworks Ventana SBC"
+ select ARCH_IMX6
endif
diff --git a/arch/arm/mach-imx/include/mach/imx35-regs.h b/arch/arm/mach-imx/include/mach/imx35-regs.h
index bbfde2339a..b30037cf83 100644
--- a/arch/arm/mach-imx/include/mach/imx35-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx35-regs.h
@@ -153,6 +153,7 @@
#define MX35_CCM_CGR1_FEC_SHIFT 0
#define MX35_CCM_CGR1_I2C1_SHIFT 10
#define MX35_CCM_CGR1_SDHC1_SHIFT 26
+#define MX35_CCM_CGR2_UART2_SHIFT 18
#define MX35_CCM_CGR2_USB_SHIFT 22
#define MX35_CCM_RCSR_MEM_CTRL_SHIFT 25
diff --git a/arch/arm/mach-imx/include/mach/imx6-ddr-regs.h b/arch/arm/mach-imx/include/mach/imx6-ddr-regs.h
index 69707f0976..ac2764f1b6 100644
--- a/arch/arm/mach-imx/include/mach/imx6-ddr-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx6-ddr-regs.h
@@ -37,6 +37,9 @@
#define MX6_MMDC_P0_MPDGCTRL1 0x021b0840
#define MX6_MMDC_P0_MPRDDLCTL 0x021b0848
#define MX6_MMDC_P0_MPWRDLCTL 0x021b0850
+#define MX6_MMDC_P0_MPRDDLHWCTL 0x021b0860
+#define MX6_MMDC_P0_MPWRDLHWCTL 0x021b0864
+#define MX6_MMDC_P0_MPPDCMPR2 0x021b0890
#define MX6_MMDC_P0_MPMUR0 0x021b08b8
#define MX6_MMDC_P1_MDCTL 0x021b4000
@@ -64,4 +67,7 @@
#define MX6_MMDC_P1_MPDGCTRL1 0x021b4840
#define MX6_MMDC_P1_MPRDDLCTL 0x021b4848
#define MX6_MMDC_P1_MPWRDLCTL 0x021b4850
+#define MX6_MMDC_P1_MPRDDLHWCTL 0x021b4860
+#define MX6_MMDC_P1_MPWRDLHWCTL 0x021b4864
+#define MX6_MMDC_P1_MPPDCMPR2 0x021b4890
#define MX6_MMDC_P1_MPMUR0 0x021b48b8
diff --git a/arch/arm/mach-imx/include/mach/imx6dl-ddr-regs.h b/arch/arm/mach-imx/include/mach/imx6dl-ddr-regs.h
index 541d00e244..a312e63a99 100644
--- a/arch/arm/mach-imx/include/mach/imx6dl-ddr-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx6dl-ddr-regs.h
@@ -12,6 +12,23 @@
* GNU General Public License for more details.
*/
+#define MX6_IOM_DRAM_ADDR00 0x020e0424
+#define MX6_IOM_DRAM_ADDR01 0x020e0428
+#define MX6_IOM_DRAM_ADDR10 0x020e042c
+#define MX6_IOM_DRAM_ADDR11 0x020e0430
+#define MX6_IOM_DRAM_ADDR12 0x020e0434
+#define MX6_IOM_DRAM_ADDR13 0x020e0438
+#define MX6_IOM_DRAM_ADDR14 0x020e043c
+#define MX6_IOM_DRAM_ADDR15 0x020e0440
+#define MX6_IOM_DRAM_ADDR02 0x020e0444
+#define MX6_IOM_DRAM_ADDR03 0x020e0448
+#define MX6_IOM_DRAM_ADDR04 0x020e044c
+#define MX6_IOM_DRAM_ADDR05 0x020e0450
+#define MX6_IOM_DRAM_ADDR06 0x020e0454
+#define MX6_IOM_DRAM_ADDR07 0x020e0458
+#define MX6_IOM_DRAM_ADDR08 0x020e045c
+#define MX6_IOM_DRAM_ADDR09 0x020e0460
+
#define MX6_IOM_DRAM_DQM0 0x020e0470
#define MX6_IOM_DRAM_DQM1 0x020e0474
#define MX6_IOM_DRAM_DQM2 0x020e0478
@@ -24,6 +41,8 @@
#define MX6_IOM_DRAM_CAS 0x020e0464
#define MX6_IOM_DRAM_RAS 0x020e0490
#define MX6_IOM_DRAM_RESET 0x020e0494
+#define MX6_IOM_DRAM_SDBA0 0x020e0498
+#define MX6_IOM_DRAM_SDBA1 0x020e049c
#define MX6_IOM_DRAM_SDCLK_0 0x020e04ac
#define MX6_IOM_DRAM_SDCLK_1 0x020e04b0
#define MX6_IOM_DRAM_SDBA2 0x020e04a0
@@ -52,6 +71,7 @@
#define MX6_IOM_GRP_ADDDS 0x020e074c
#define MX6_IOM_DDRMODE_CTL 0x020e0750
#define MX6_IOM_GRP_DDRPKE 0x020e0754
+#define MX6_IOM_GRP_DDRHYS 0x020e075c
#define MX6_IOM_GRP_DDRMODE 0x020e0760
#define MX6_IOM_GRP_CTLDS 0x020e076c
#define MX6_IOM_GRP_DDR_TYPE 0x020e0774
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 3270f9265b..8323b66041 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -7,87 +7,77 @@ config ARCH_TEXT_BASE
default 0x2000000 if ARCH_DOVE
default 0x2000000 if ARCH_KIRKWOOD
-choice
- prompt "Marvell EBU Processor"
-
config ARCH_ARMADA_370
- bool "Armada 370"
+ bool
select CPU_V7
select CLOCKSOURCE_MVEBU
- select PINCTRL_ARMADA_370
config ARCH_ARMADA_XP
- bool "Armada XP"
+ bool
select CPU_V7
select CLOCKSOURCE_MVEBU
- select PINCTRL_ARMADA_XP
config ARCH_DOVE
- bool "Dove 88AP510"
+ bool
select CPU_V7
select CLOCKSOURCE_ORION
- select PINCTRL_DOVE
config ARCH_KIRKWOOD
- bool "Kirkwood"
+ bool
select CPU_FEROCEON
select CLOCKSOURCE_ORION
- select PINCTRL_KIRKWOOD
-
-endchoice
#
# Armada 370 SoC boards
#
-if ARCH_ARMADA_370
+comment "Armada 370 based boards"
config MACH_GLOBALSCALE_MIRABOX
bool "Globalscale Mirabox"
-
-endif # ARCH_ARMADA_370
+ select ARCH_ARMADA_370
#
# Armada XP SoC boards
#
-if ARCH_ARMADA_XP
+comment "Armada XP based boards"
config MACH_PLATHOME_OPENBLOCKS_AX3
bool "PlatHome OpenBlocks AX3"
+ select ARCH_ARMADA_XP
config MACH_MARVELL_ARMADA_XP_GP
bool "Marvell Armada XP GP"
-
-endif # ARCH_ARMADA_XP
+ select ARCH_ARMADA_XP
#
# Dove 88AP510 SoC boards
#
-if ARCH_DOVE
+comment "Dove based boards"
config MACH_SOLIDRUN_CUBOX
bool "SolidRun CuBox"
-
-endif # ARCH_DOVE
+ select ARCH_DOVE
#
# Kirkwood SoC boards
#
-if ARCH_KIRKWOOD
+comment "Kirkwood based boards"
config MACH_GLOBALSCALE_GURUPLUG
bool "Guruplug"
+ select ARCH_KIRKWOOD
config MACH_PLATHOME_OPENBLOCKS_A6
bool "PlatHome OpenBlocks A6"
+ select ARCH_KIRKWOOD
config MACH_USI_TOPKICK
bool "Topkick"
-
-endif # ARCH_KIRKWOOD
+ select ARCH_KIRKWOOD
#
# Common options
diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c
index f2b991e5a7..57f6a5fe0d 100644
--- a/arch/arm/mach-mvebu/armada-370-xp.c
+++ b/arch/arm/mach-mvebu/armada-370-xp.c
@@ -44,11 +44,24 @@ static inline void armada_370_xp_memory_find(unsigned long *phys_base,
}
}
-static int armada_370_xp_init_soc(void)
+static void __noreturn armada_370_xp_reset_cpu(unsigned long addr)
+{
+ writel(0x1, ARMADA_370_XP_SYSCTL_BASE + 0x60);
+ writel(0x1, ARMADA_370_XP_SYSCTL_BASE + 0x64);
+ while (1)
+ ;
+}
+
+static int armada_370_xp_init_soc(struct device_node *root, void *context)
{
unsigned long phys_base, phys_size;
u32 reg;
+ if (!of_machine_is_compatible("marvell,armada-370-xp"))
+ return 0;
+
+ mvebu_set_reset(armada_370_xp_reset_cpu);
+
barebox_set_model("Marvell Armada 370/XP");
barebox_set_hostname("armada");
@@ -60,17 +73,14 @@ static int armada_370_xp_init_soc(void)
armada_370_xp_memory_find(&phys_base, &phys_size);
mvebu_set_memory(phys_base, phys_size);
- mvebu_mbus_add_range(0xf0, 0x01, MVEBU_REMAP_INT_REG_BASE);
return 0;
}
-core_initcall(armada_370_xp_init_soc);
-void __noreturn reset_cpu(unsigned long addr)
+static int armada_370_xp_register_soc_fixup(void)
{
- writel(0x1, ARMADA_370_XP_SYSCTL_BASE + 0x60);
- writel(0x1, ARMADA_370_XP_SYSCTL_BASE + 0x64);
- while (1)
- ;
+ mvebu_mbus_add_range("marvell,armada-370-xp", 0xf0, 0x01,
+ MVEBU_REMAP_INT_REG_BASE);
+ return of_register_fixup(armada_370_xp_init_soc, NULL);
}
-EXPORT_SYMBOL(reset_cpu);
+pure_initcall(armada_370_xp_register_soc_fixup);
diff --git a/arch/arm/mach-mvebu/common.c b/arch/arm/mach-mvebu/common.c
index ac4b332e01..309f7a6aaa 100644
--- a/arch/arm/mach-mvebu/common.c
+++ b/arch/arm/mach-mvebu/common.c
@@ -21,6 +21,7 @@
#include <of.h>
#include <of_address.h>
#include <linux/clk.h>
+#include <mach/common.h>
/*
* Marvell MVEBU SoC id and revision can be read from any PCIe
@@ -80,29 +81,21 @@ static int mvebu_soc_id_init(void)
}
postcore_initcall(mvebu_soc_id_init);
-static u64 mvebu_mem[2];
-
-void mvebu_set_memory(u64 phys_base, u64 phys_size)
-{
- mvebu_mem[0] = phys_base;
- mvebu_mem[1] = phys_size;
-}
-
/*
* Memory size is set up by BootROM and can be read from SoC's ram controller
* registers. Fixup provided DTs to reflect accessible amount of directly
* attached RAM. Removable RAM, e.g. SODIMM, should be added by a per-board
* fixup.
*/
-static int mvebu_memory_of_fixup(struct device_node *root, void *context)
+int mvebu_set_memory(u64 phys_base, u64 phys_size)
{
- struct device_node *np;
+ struct device_node *np, *root;
__be32 reg[4];
int na, ns;
- /* bail out on zero-sized mem */
- if (!mvebu_mem[1])
- return -ENODEV;
+ root = of_get_root_node();
+ if (!root)
+ return -EINVAL;
np = of_find_node_by_path("/memory");
if (!np)
@@ -114,17 +107,17 @@ static int mvebu_memory_of_fixup(struct device_node *root, void *context)
ns = of_n_size_cells(np);
if (na == 2) {
- reg[0] = cpu_to_be32(mvebu_mem[0] >> 32);
- reg[1] = cpu_to_be32(mvebu_mem[0] & 0xffffffff);
+ reg[0] = cpu_to_be32(phys_base >> 32);
+ reg[1] = cpu_to_be32(phys_base & 0xffffffff);
} else {
- reg[0] = cpu_to_be32(mvebu_mem[0] & 0xffffffff);
+ reg[0] = cpu_to_be32(phys_base & 0xffffffff);
}
if (ns == 2) {
- reg[2] = cpu_to_be32(mvebu_mem[1] >> 32);
- reg[3] = cpu_to_be32(mvebu_mem[1] & 0xffffffff);
+ reg[2] = cpu_to_be32(phys_size >> 32);
+ reg[3] = cpu_to_be32(phys_size & 0xffffffff);
} else {
- reg[1] = cpu_to_be32(mvebu_mem[1] & 0xffffffff);
+ reg[1] = cpu_to_be32(phys_size & 0xffffffff);
}
if (of_set_property(np, "device_type", "memory", sizeof("memory"), 1) ||
@@ -134,7 +127,15 @@ static int mvebu_memory_of_fixup(struct device_node *root, void *context)
return 0;
}
-static int mvebu_memory_fixup_register(void) {
- return of_register_fixup(mvebu_memory_of_fixup, NULL);
+static __noreturn void (*mvebu_reset_cpu)(unsigned long addr);
+
+void __noreturn reset_cpu(unsigned long addr)
+{
+ mvebu_reset_cpu(addr);
+}
+EXPORT_SYMBOL(reset_cpu);
+
+void mvebu_set_reset(void __noreturn (*reset)(unsigned long addr))
+{
+ mvebu_reset_cpu = reset;
}
-pure_initcall(mvebu_memory_fixup_register);
diff --git a/arch/arm/mach-mvebu/dove.c b/arch/arm/mach-mvebu/dove.c
index 69c6436b24..c2852f8986 100644
--- a/arch/arm/mach-mvebu/dove.c
+++ b/arch/arm/mach-mvebu/dove.c
@@ -68,10 +68,24 @@ static inline void dove_memory_find(unsigned long *phys_base,
}
}
-static int dove_init_soc(void)
+static void __noreturn dove_reset_cpu(unsigned long addr)
+{
+ /* enable and assert RSTOUTn */
+ writel(SOFT_RESET_OUT_EN, DOVE_BRIDGE_BASE + BRIDGE_RSTOUT_MASK);
+ writel(SOFT_RESET_EN, DOVE_BRIDGE_BASE + BRIDGE_SYS_SOFT_RESET);
+ while (1)
+ ;
+}
+
+static int dove_init_soc(struct device_node *root, void *context)
{
unsigned long phys_base, phys_size;
+ if (!of_machine_is_compatible("marvell,dove"))
+ return 0;
+
+ mvebu_set_reset(dove_reset_cpu);
+
barebox_set_model("Marvell Dove");
barebox_set_hostname("dove");
@@ -79,19 +93,16 @@ static int dove_init_soc(void)
dove_memory_find(&phys_base, &phys_size);
mvebu_set_memory(phys_base, phys_size);
- mvebu_mbus_add_range(0xf0, 0x01, MVEBU_REMAP_INT_REG_BASE);
- mvebu_mbus_add_range(0xf0, 0x02, DOVE_REMAP_MC_REGS);
return 0;
}
-core_initcall(dove_init_soc);
-void __noreturn reset_cpu(unsigned long addr)
+static int dove_register_soc_fixup(void)
{
- /* enable and assert RSTOUTn */
- writel(SOFT_RESET_OUT_EN, DOVE_BRIDGE_BASE + BRIDGE_RSTOUT_MASK);
- writel(SOFT_RESET_EN, DOVE_BRIDGE_BASE + BRIDGE_SYS_SOFT_RESET);
- while (1)
- ;
+ mvebu_mbus_add_range("marvell,dove", 0xf0, 0x01,
+ MVEBU_REMAP_INT_REG_BASE);
+ mvebu_mbus_add_range("marvell,dove", 0xf0, 0x02,
+ DOVE_REMAP_MC_REGS);
+ return of_register_fixup(dove_init_soc, NULL);
}
-EXPORT_SYMBOL(reset_cpu);
+pure_initcall(dove_register_soc_fixup);
diff --git a/arch/arm/mach-mvebu/include/mach/common.h b/arch/arm/mach-mvebu/include/mach/common.h
index 9f6118e4ec..5ce33fd882 100644
--- a/arch/arm/mach-mvebu/include/mach/common.h
+++ b/arch/arm/mach-mvebu/include/mach/common.h
@@ -20,6 +20,7 @@
#define MVEBU_REMAP_INT_REG_BASE 0xf1000000
-void mvebu_set_memory(u64 phys_base, u64 phys_size);
+int mvebu_set_memory(u64 phys_base, u64 phys_size);
+void mvebu_set_reset(void __noreturn (*reset)(unsigned long addr));
#endif
diff --git a/arch/arm/mach-mvebu/kirkwood.c b/arch/arm/mach-mvebu/kirkwood.c
index c114bdb360..d7903f732e 100644
--- a/arch/arm/mach-mvebu/kirkwood.c
+++ b/arch/arm/mach-mvebu/kirkwood.c
@@ -43,27 +43,37 @@ static inline void kirkwood_memory_find(unsigned long *phys_base,
}
}
-static int kirkwood_init_soc(void)
+static void __noreturn kirkwood_reset_cpu(unsigned long addr)
+{
+ writel(SOFT_RESET_OUT_EN, KIRKWOOD_BRIDGE_BASE + BRIDGE_RSTOUT_MASK);
+ writel(SOFT_RESET_EN, KIRKWOOD_BRIDGE_BASE + BRIDGE_SYS_SOFT_RESET);
+ for(;;)
+ ;
+}
+
+static int kirkwood_init_soc(struct device_node *root, void *context)
{
unsigned long phys_base, phys_size;
+ if (!of_machine_is_compatible("marvell,kirkwood"))
+ return 0;
+
+ mvebu_set_reset(kirkwood_reset_cpu);
+
barebox_set_model("Marvell Kirkwood");
barebox_set_hostname("kirkwood");
kirkwood_memory_find(&phys_base, &phys_size);
mvebu_set_memory(phys_base, phys_size);
- mvebu_mbus_add_range(0xf0, 0x01, MVEBU_REMAP_INT_REG_BASE);
return 0;
}
-core_initcall(kirkwood_init_soc);
-void __noreturn reset_cpu(unsigned long addr)
+static int kirkwood_register_soc_fixup(void)
{
- writel(SOFT_RESET_OUT_EN, KIRKWOOD_BRIDGE_BASE + BRIDGE_RSTOUT_MASK);
- writel(SOFT_RESET_EN, KIRKWOOD_BRIDGE_BASE + BRIDGE_SYS_SOFT_RESET);
- for(;;)
- ;
+ mvebu_mbus_add_range("marvell,kirkwood", 0xf0, 0x01,
+ MVEBU_REMAP_INT_REG_BASE);
+ return of_register_fixup(kirkwood_init_soc, NULL);
}
-EXPORT_SYMBOL(reset_cpu);
+pure_initcall(kirkwood_register_soc_fixup);
diff --git a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig
index 732de15fec..e30027ef2e 100644
--- a/arch/arm/mach-omap/Kconfig
+++ b/arch/arm/mach-omap/Kconfig
@@ -93,15 +93,16 @@ config BAREBOX_UPDATE_AM33XX_SPI_NOR_MLO
Say Y for barebox update SPI NOR MLO handler.
AM35xx, AM33xx chips use big endian MLO for SPI NOR flash.
-config BAREBOX_UPDATE_AM33XX_NAND_XLOADSLOTS
- prompt "barebox update nand xload slots handler"
+config BAREBOX_UPDATE_AM33XX_NAND
+ prompt "barebox update NAND handler"
bool
depends on BAREBOX_UPDATE
help
- Say Y for barebox update nand xload slots handler.
- This update handler updates 4 default nand xload slots
- with a single command.
+ Say Y for barebox update NAND handler. This update handler updates
+ 4 default NAND xload slots with a single command.
The Handler also checks if the given image has a valid CH header.
+ This also includes a handler for updating the regular barebox binary
+ in NAND.
config ARCH_TEXT_BASE
hex
@@ -124,6 +125,12 @@ config OMAP_MULTI_BOARDS
if OMAP_MULTI_BOARDS
+config MACH_AFI_GF
+ bool "af inventions GF"
+ select ARCH_AM33XX
+ help
+ Say Y here if you are using afis GF
+
config MACH_BEAGLEBONE
bool "Texas Instrument's Beagle Bone"
select ARCH_AM33XX
@@ -135,6 +142,7 @@ config MACH_PCM051
select ARCH_AM33XX
help
Say Y here if you are using Phytecs phyCORE pcm051 board
+
endif
choice
diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile
index 0ebfae7437..bef1d0500f 100644
--- a/arch/arm/mach-omap/Makefile
+++ b/arch/arm/mach-omap/Makefile
@@ -33,4 +33,4 @@ obj-$(CONFIG_MFD_TWL6030) += omap4_twl6030_mmc.o
obj-$(CONFIG_OMAP4_USBBOOT) += omap4_rom_usb.o
obj-$(CONFIG_CMD_BOOT_ORDER) += boot_order.o
obj-$(CONFIG_BAREBOX_UPDATE_AM33XX_SPI_NOR_MLO) += am33xx_bbu_spi_mlo.o
-obj-$(CONFIG_BAREBOX_UPDATE_AM33XX_NAND_XLOADSLOTS) += am33xx_bbu_nand_xloadslots.o
+obj-$(CONFIG_BAREBOX_UPDATE_AM33XX_NAND) += am33xx_bbu_nand.o
diff --git a/arch/arm/mach-omap/am33xx_bbu_nand_xloadslots.c b/arch/arm/mach-omap/am33xx_bbu_nand.c
index 0b4f1ccf05..ee767d32e4 100644
--- a/arch/arm/mach-omap/am33xx_bbu_nand_xloadslots.c
+++ b/arch/arm/mach-omap/am33xx_bbu_nand.c
@@ -80,12 +80,12 @@ static int nand_xloadslots_update_handler(struct bbu_handler *handler,
nh = container_of(handler, struct nand_bbu_handler, bbu_handler);
+ ret = bbu_confirm(data);
+ if (ret != 0)
+ return ret;
+
/* check if the devicefile has been overwritten */
if (strcmp(data->devicefile, nh->devicefile[0]) != 0) {
- ret = bbu_confirm(data);
- if (ret != 0)
- return ret;
-
ret = write_image(data->devicefile, image, size);
if (ret != 0)
return ret;
@@ -120,3 +120,42 @@ int am33xx_bbu_nand_xloadslots_register_handler(const char *name,
return ret;
}
+
+static int nand_update_handler(struct bbu_handler *handler,
+ struct bbu_data *data)
+{
+ int ret = 0;
+ const void *image = data->image;
+ size_t size = data->len;
+ struct nand_bbu_handler *nh;
+
+ if (file_detect_type(image, size) != filetype_arm_barebox) {
+ pr_err("%s is not a valid barebox image\n", data->imagefile);
+ return -EINVAL;
+ }
+
+ nh = container_of(handler, struct nand_bbu_handler, bbu_handler);
+
+ ret = bbu_confirm(data);
+ if (ret != 0)
+ return ret;
+
+ return write_image(data->devicefile, image, size);
+}
+
+int am33xx_bbu_nand_register_handler(const char *name, char *devicefile)
+{
+ struct nand_bbu_handler *handler;
+ int ret;
+
+ handler = xzalloc(sizeof(*handler));
+ handler->bbu_handler.devicefile = devicefile;
+ handler->bbu_handler.handler = nand_update_handler;
+ handler->bbu_handler.name = name;
+
+ ret = bbu_register_handler(&handler->bbu_handler);
+ if (ret)
+ free(handler);
+
+ return ret;
+}
diff --git a/arch/arm/mach-omap/am33xx_bbu_spi_mlo.c b/arch/arm/mach-omap/am33xx_bbu_spi_mlo.c
index 8ac0a185c0..97dc54ee10 100644
--- a/arch/arm/mach-omap/am33xx_bbu_spi_mlo.c
+++ b/arch/arm/mach-omap/am33xx_bbu_spi_mlo.c
@@ -19,6 +19,7 @@
#include <bbu.h>
#include <fs.h>
#include <fcntl.h>
+#include <linux/stat.h>
/*
* AM35xx, AM33xx chips use big endian MLO for SPI NOR flash
@@ -34,17 +35,34 @@ static int spi_nor_mlo_handler(struct bbu_handler *handler,
void *image = data->image;
uint32_t *header;
int swap = 0;
+ struct stat s;
header = data->image;
- if (header[5] == 0x43485345) {
+
+ if (header[5] == 0x43485345 || header[10] == 0x62617265) {
swap = 0;
- } else if (header[5] == 0x45534843) {
+ } else if (header[5] == 0x45534843 || header[10] == 0x65726142) {
swap = 1;
} else {
if (!bbu_force(data, "Not a MLO image"))
return -EINVAL;
}
+ ret = stat(data->devicefile, &s);
+ if (ret) {
+ printf("could not open %s: %s", data->devicefile, errno_str());
+ return ret;
+ }
+
+ if (size > s.st_size) {
+ printf("Image too big, need %d, have %lld\n", size, s.st_size);
+ return -ENOSPC;
+ }
+
+ ret = bbu_confirm(data);
+ if (ret != 0)
+ return ret;
+
dstfd = open(data->devicefile, O_WRONLY);
if (dstfd < 0) {
printf("could not open %s: %s", data->devicefile, errno_str());
diff --git a/arch/arm/mach-omap/am33xx_clock.c b/arch/arm/mach-omap/am33xx_clock.c
index 9105ddc8b8..6d8addef32 100644
--- a/arch/arm/mach-omap/am33xx_clock.c
+++ b/arch/arm/mach-omap/am33xx_clock.c
@@ -88,8 +88,10 @@ static void power_domain_transition_enable(void)
/*
* Enable the module clock and the power domain for required peripherals
*/
-static void per_clocks_enable(void)
+void am33xx_enable_per_clocks(void)
{
+ u32 clkdcoldo;
+
/* Enable the module clock */
__raw_writel(PRCM_MOD_EN, CM_PER_TIMER2_CLKCTRL);
while (__raw_readl(CM_PER_TIMER2_CLKCTRL) != PRCM_MOD_EN);
@@ -154,6 +156,15 @@ static void per_clocks_enable(void)
__raw_writel(PRCM_MOD_EN, CM_PER_SPI1_CLKCTRL);
while (__raw_readl(CM_PER_SPI1_CLKCTRL) != PRCM_MOD_EN);
+
+ /* USB */
+ __raw_writel(PRCM_MOD_EN, CM_PER_USB0_CLKCTRL);
+ while ((__raw_readl(CM_PER_USB0_CLKCTRL) & 0x30000) != 0x0);
+
+ clkdcoldo = __raw_readl(CM_CLKDCOLDO_DPLL_PER);
+ clkdcoldo = clkdcoldo | 0x100;
+ __raw_writel(clkdcoldo, CM_CLKDCOLDO_DPLL_PER);
+ while ((__raw_readl(CM_CLKDCOLDO_DPLL_PER) & 0x00000200) != 0x200);
}
static void mpu_pll_config(int mpupll_M, int osc)
@@ -305,5 +316,5 @@ void am33xx_pll_init(int mpupll_M, int osc, int ddrpll_M)
/* Enable power domain transition */
power_domain_transition_enable();
/* Enable the required peripherals */
- per_clocks_enable();
+ am33xx_enable_per_clocks();
}
diff --git a/arch/arm/mach-omap/am33xx_generic.c b/arch/arm/mach-omap/am33xx_generic.c
index 71c528ca8b..f2931340cb 100644
--- a/arch/arm/mach-omap/am33xx_generic.c
+++ b/arch/arm/mach-omap/am33xx_generic.c
@@ -207,6 +207,8 @@ int am33xx_init(void)
{
omap_gpmc_base = (void *)AM33XX_GPMC_BASE;
+ am33xx_enable_per_clocks();
+
return am33xx_bootsource();
}
diff --git a/arch/arm/mach-omap/include/mach/am33xx-clock.h b/arch/arm/mach-omap/include/mach/am33xx-clock.h
index 10c2f29dcd..2d6a727e1c 100644
--- a/arch/arm/mach-omap/include/mach/am33xx-clock.h
+++ b/arch/arm/mach-omap/include/mach/am33xx-clock.h
@@ -44,6 +44,7 @@
/* DDR Freq is 266 MHZ for now*/
/* Set Fdll = 400 MHZ , Fdll = M * 2 * CLKINP/ N + 1; clkout = Fdll /(2 * M2) */
+#define DDRPLL_M_200 200
#define DDRPLL_M_266 266
#define DDRPLL_M_303 303
#define DDRPLL_M_400 400
@@ -74,6 +75,7 @@
#define CM_CLKMODE_DPLL_PER (CM_WKUP + 0x8c)
#define CM_DIV_M2_DPLL_PER (CM_WKUP + 0xAC)
#define CM_IDLEST_DPLL_PER (CM_WKUP + 0x70)
+#define CM_CLKDCOLDO_DPLL_PER (CM_WKUP + 0x7C) /* for USB_PHY clock */
/* Display PLL */
#define CM_CLKSEL_DPLL_DISP (CM_WKUP + 0x54)
@@ -140,6 +142,7 @@
#define CM_PER_MMC0_CLKCTRL (CM_PER + 0x3C)
#define CM_PER_MMC1_CLKCTRL (CM_PER + 0xF4)
#define CM_PER_MMC2_CLKCTRL (CM_PER + 0xF8)
+#define CM_PER_USB0_CLKCTRL (CM_PER + 0x1c) /* USB */
/* PRCM */
#define CM_DPLL_OFFSET (AM33XX_PRM_BASE + 0x0300)
diff --git a/arch/arm/mach-omap/include/mach/am33xx-generic.h b/arch/arm/mach-omap/include/mach/am33xx-generic.h
index 75ac00aa51..6c85d51597 100644
--- a/arch/arm/mach-omap/include/mach/am33xx-generic.h
+++ b/arch/arm/mach-omap/include/mach/am33xx-generic.h
@@ -30,6 +30,7 @@ u32 am33xx_running_in_sdram(void);
void __noreturn am33xx_reset_cpu(unsigned long addr);
+void am33xx_enable_per_clocks(void);
int am33xx_init(void);
int am33xx_devices_init(void);
diff --git a/arch/arm/mach-omap/include/mach/am33xx-silicon.h b/arch/arm/mach-omap/include/mach/am33xx-silicon.h
index ceca10a619..a44973e979 100644
--- a/arch/arm/mach-omap/include/mach/am33xx-silicon.h
+++ b/arch/arm/mach-omap/include/mach/am33xx-silicon.h
@@ -125,10 +125,10 @@
/* DDR offsets */
#define AM33XX_DDR_PHY_BASE_ADDR 0x44E12000
-#define AM33XX_DDR_IO_CTRL 0x44E10E04
-#define AM33XX_DDR_CKE_CTRL 0x44E1131C
#define AM33XX_CONTROL_BASE_ADDR 0x44E10000
+#define AM33XX_DDR_IO_CTRL (AM33XX_CONTROL_BASE_ADDR + 0x0E04)
+#define AM33XX_DDR_CKE_CTRL (AM33XX_CONTROL_BASE_ADDR + 0x131C)
#define AM33XX_DDR_CMD0_IOCTRL (AM33XX_CONTROL_BASE_ADDR + 0x1404)
#define AM33XX_DDR_CMD1_IOCTRL (AM33XX_CONTROL_BASE_ADDR + 0x1408)
#define AM33XX_DDR_CMD2_IOCTRL (AM33XX_CONTROL_BASE_ADDR + 0x140C)
diff --git a/arch/arm/mach-omap/include/mach/bbu.h b/arch/arm/mach-omap/include/mach/bbu.h
index 8c4c5e3eb8..36d87e1a00 100644
--- a/arch/arm/mach-omap/include/mach/bbu.h
+++ b/arch/arm/mach-omap/include/mach/bbu.h
@@ -18,10 +18,11 @@ static inline int am33xx_bbu_spi_nor_register_handler(const char *name, char *de
}
#endif
-#ifdef CONFIG_BAREBOX_UPDATE_AM33XX_NAND_XLOADSLOTS
+#ifdef CONFIG_BAREBOX_UPDATE_AM33XX_NAND
int am33xx_bbu_nand_xloadslots_register_handler(const char *name,
char **devicefile,
int num_devicefiles);
+int am33xx_bbu_nand_register_handler(const char *name, char *devicefile);
#else
static inline int am33xx_bbu_nand_xloadslots_register_handler(const char *name,
char **devicefile,
@@ -29,6 +30,11 @@ static inline int am33xx_bbu_nand_xloadslots_register_handler(const char *name,
{
return 0;
}
+
+static inline int am33xx_bbu_nand_register_handler(const char *name, char *devicefile)
+{
+ return 0;
+}
#endif
#endif
diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile
index d8bf067430..12585c5476 100644
--- a/arch/arm/mach-socfpga/Makefile
+++ b/arch/arm/mach-socfpga/Makefile
@@ -2,3 +2,4 @@ obj-y += generic.o nic301.o bootsource.o reset-manager.o
pbl-y += init.o freeze-controller.o scan-manager.o system-manager.o
pbl-y += clock-manager.o iocsr-config-cyclone5.o
obj-$(CONFIG_ARCH_SOCFPGA_XLOAD) += xload.o
+obj-$(CONFIG_ARCH_SOCFPGA_FPGA) += fpga.o
diff --git a/arch/arm/mach-socfpga/include/mach/socfpga-regs.h b/arch/arm/mach-socfpga/include/mach/socfpga-regs.h
index 9d1e677cb7..b124ed675c 100644
--- a/arch/arm/mach-socfpga/include/mach/socfpga-regs.h
+++ b/arch/arm/mach-socfpga/include/mach/socfpga-regs.h
@@ -2,10 +2,12 @@
#define __MACH_SOCFPGA_REGS_H
#define CYCLONE5_SDMMC_ADDRESS 0xff704000
+#define CYCLONE5_FPGAMGRREGS_ADDRESS 0xff706000
#define CYCLONE5_GPIO0_BASE 0xff708000
#define CYCLONE5_GPIO1_BASE 0xff709000
#define CYCLONE5_GPIO2_BASE 0xff70A000
#define CYCLONE5_L3REGS_ADDRESS 0xff800000
+#define CYCLONE5_FPGAMGRDATA_ADDRESS 0xffb90000
#define CYCLONE5_UART0_ADDRESS 0xffc02000
#define CYCLONE5_UART1_ADDRESS 0xffc03000
#define CYCLONE5_SDR_ADDRESS 0xffc20000
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 7214ecaf3a..2c69406dfc 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -44,15 +44,12 @@ endchoice
config ARCH_TEGRA_2x_SOC
bool
- select PINCTRL_TEGRA20
config ARCH_TEGRA_3x_SOC
bool
- select PINCTRL_TEGRA30
config ARCH_TEGRA_124_SOC
bool
- select PINCTRL_TEGRA30
menu "select Tegra boards to be built"
diff --git a/arch/blackfin/boards/ipe337/.gitignore b/arch/blackfin/boards/ipe337/.gitignore
new file mode 100644
index 0000000000..d1165788c9
--- /dev/null
+++ b/arch/blackfin/boards/ipe337/.gitignore
@@ -0,0 +1 @@
+barebox.lds
diff --git a/arch/efi/Makefile b/arch/efi/Makefile
index af280859f0..85cb655615 100644
--- a/arch/efi/Makefile
+++ b/arch/efi/Makefile
@@ -24,7 +24,7 @@ cmd_barebox__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_barebox) -o $@ \
$(filter-out $(barebox-lds) $(barebox-common) FORCE ,$^)
quiet_cmd_efi_image = EFI-IMG $@
- cmd_efi_image = objcopy -j .text -j .sdata -j .data -j .dynamic \
+ cmd_efi_image = $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic \
-j .dynsym -j .rel -j .rela -j .reloc -j __barebox_initcalls \
-j __barebox_cmd -j .barebox_magicvar -j .bbenv.* \
--target=$(TARGET) $< $@
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index bc68c679d5..40d5d83732 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -82,7 +82,6 @@ config MACH_MIPS_LOONGSON
config MACH_MIPS_XBURST
bool "Ingenic XBurst-based boards"
- select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_32BIT_KERNEL
select DRIVER_SERIAL_NS16550
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index a3cf112b79..f3f4f67d86 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -89,6 +89,7 @@ board-$(CONFIG_BOARD_LOONGSON_TECH_LS1B) := loongson-ls1b
machine-$(CONFIG_MACH_MIPS_XBURST) := xburst
board-$(CONFIG_BOARD_RZX50) := ritmix-rzx50
+board-$(CONFIG_BOARD_CI20) := img-ci20
machdirs := $(patsubst %,arch/mips/mach-%/,$(machine-y))
diff --git a/arch/mips/boards/img-ci20/Makefile b/arch/mips/boards/img-ci20/Makefile
new file mode 100644
index 0000000000..dcfc2937d3
--- /dev/null
+++ b/arch/mips/boards/img-ci20/Makefile
@@ -0,0 +1 @@
+obj-y += board.o
diff --git a/arch/mips/boards/img-ci20/board.c b/arch/mips/boards/img-ci20/board.c
new file mode 100644
index 0000000000..515ebaece6
--- /dev/null
+++ b/arch/mips/boards/img-ci20/board.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2012 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <common.h>
+#include <init.h>
+
+static int ci20_hostname_init(void)
+{
+ barebox_set_hostname("ci20");
+
+ return 0;
+}
+console_initcall(ci20_hostname_init);
diff --git a/arch/mips/boards/img-ci20/include/board/board_pbl_start.h b/arch/mips/boards/img-ci20/include/board/board_pbl_start.h
new file mode 100644
index 0000000000..26232f58c5
--- /dev/null
+++ b/arch/mips/boards/img-ci20/include/board/board_pbl_start.h
@@ -0,0 +1,43 @@
+/*
+ * Startup Code for Imagination Creator CI20 board
+ *
+ * Copyright (C) 2014 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <asm/pbl_macros.h>
+#include <mach/debug_ll.h>
+#include <asm/pbl_nmon.h>
+
+ .macro board_pbl_start
+ .set push
+ .set noreorder
+
+ mips_disable_interrupts
+
+ /* CPU/SoC specific setup ... */
+ /* ... absent */
+
+ debug_ll_ns16550_init
+
+ debug_ll_ns16550_outc '.'
+ debug_ll_ns16550_outnl
+
+ mips_nmon
+
+ copy_to_link_location pbl_start
+
+ .set pop
+ .endm
diff --git a/arch/mips/boards/img-ci20/include/board/debug_ll.h b/arch/mips/boards/img-ci20/include/board/debug_ll.h
new file mode 100644
index 0000000000..72612cff2b
--- /dev/null
+++ b/arch/mips/boards/img-ci20/include/board/debug_ll.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2014 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __INCLUDE_CI20_BOARD_DEBUG_LL_H__
+#define __INCLUDE_CI20_BOARD_DEBUG_LL_H__
+
+#include <mach/debug_ll_jz4780.h>
+
+#endif /* __INCLUDE_CI20_BOARD_DEBUG_LL_H__ */
diff --git a/arch/mips/configs/img-ci20_defconfig b/arch/mips/configs/img-ci20_defconfig
new file mode 100644
index 0000000000..56235c4cf3
--- /dev/null
+++ b/arch/mips/configs/img-ci20_defconfig
@@ -0,0 +1,42 @@
+CONFIG_BUILTIN_DTB=y
+CONFIG_BUILTIN_DTB_NAME="img-ci20"
+CONFIG_MACH_MIPS_XBURST=y
+CONFIG_BOARD_CI20=y
+CONFIG_PBL_IMAGE=y
+CONFIG_GLOB=y
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+# CONFIG_DEFAULT_ENVIRONMENT is not set
+CONFIG_POLLER=y
+CONFIG_DEBUG_LL=y
+CONFIG_LONGHELP=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_LOADS=y
+CONFIG_CMD_LOADY=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_SAVES=y
+CONFIG_CMD_UIMAGE=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_GETOPT=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_OF_NODE=y
+CONFIG_CMD_OF_PROPERTY=y
+CONFIG_CMD_OFTREE=y
+CONFIG_OFDEVICE=y
+# CONFIG_SPI is not set
+CONFIG_CLOCKSOURCE_DUMMY=y
+CONFIG_CLOCKSOURCE_DUMMY_RATE=3500
+CONFIG_SHA1=y
+CONFIG_SHA224=y
+CONFIG_SHA256=y
diff --git a/arch/mips/configs/ritmix-rzx50_defconfig b/arch/mips/configs/ritmix-rzx50_defconfig
index fb67014532..0814883e89 100644
--- a/arch/mips/configs/ritmix-rzx50_defconfig
+++ b/arch/mips/configs/ritmix-rzx50_defconfig
@@ -1,7 +1,7 @@
CONFIG_BUILTIN_DTB=y
CONFIG_BUILTIN_DTB_NAME="rzx50"
CONFIG_MACH_MIPS_XBURST=y
-CONFIG_JZ4750D_DEBUG_LL_UART1=y
+CONFIG_JZ47XX_DEBUG_LL_UART1=y
CONFIG_PBL_IMAGE=y
CONFIG_BAUDRATE=57600
CONFIG_GLOB=y
@@ -12,6 +12,7 @@ CONFIG_AUTO_COMPLETE=y
CONFIG_DEBUG_LL=y
CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
+CONFIG_CMD_IMD=y
CONFIG_CMD_MEMINFO=y
CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_BOOTM_VERBOSE=y
diff --git a/arch/mips/dts/ar9331.dtsi b/arch/mips/dts/ar9331.dtsi
index 8280588ab3..8e7afcddff 100644
--- a/arch/mips/dts/ar9331.dtsi
+++ b/arch/mips/dts/ar9331.dtsi
@@ -10,24 +10,24 @@
device_type = "soc";
ranges;
- serial0: serial@b8020000 {
+ serial0: serial@18020000 {
compatible = "qca,ar9330-uart";
- reg = <0xb8020000 0x14>;
+ reg = <0x18020000 0x14>;
clocks = <&ar9331_clk AR933X_CLK_UART>;
status = "disabled";
};
ar9331_clk: clock {
compatible = "qca,ar933x-clk";
- reg = <0xb8050000 0x48>;
+ reg = <0x18050000 0x48>;
#clock-cells = <1>;
};
- spi: spi@bf000000{
+ spi: spi@1f000000{
#address-cells = <1>;
#size-cells = <0>;
compatible = "qca,ath79-spi";
- reg = <0xbf000000 0x01000000>;
+ reg = <0x1f000000 0x01000000>;
status = "disabled";
};
};
diff --git a/arch/mips/dts/dlink-dir-320.dts b/arch/mips/dts/dlink-dir-320.dts
index bad41d9da7..b961c9dca3 100644
--- a/arch/mips/dts/dlink-dir-320.dts
+++ b/arch/mips/dts/dlink-dir-320.dts
@@ -17,9 +17,9 @@
device_type = "soc";
ranges;
- serial0: serial@b8000300 {
+ serial0: serial@18000300 {
compatible = "ns16550a";
- reg = <0xb8000300 0x08>;
+ reg = <0x18000300 0x08>;
reg-shift = <0>;
clock-frequency = <25804800>;
status = "disabled";
diff --git a/arch/mips/dts/img-ci20.dts b/arch/mips/dts/img-ci20.dts
new file mode 100644
index 0000000000..f2022dd273
--- /dev/null
+++ b/arch/mips/dts/img-ci20.dts
@@ -0,0 +1,35 @@
+/*
+ * CI20 device tree
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * 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.
+ *
+ */
+
+/dts-v1/;
+
+#include "jz4780.dtsi"
+
+/ {
+ model = "MIPS Creator CI20";
+ compatible = "img,ci20";
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x10000000>;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
diff --git a/arch/mips/dts/jz4755.dtsi b/arch/mips/dts/jz4755.dtsi
index b83d884a24..137156df7e 100644
--- a/arch/mips/dts/jz4755.dtsi
+++ b/arch/mips/dts/jz4755.dtsi
@@ -8,35 +8,35 @@
#size-cells = <1>;
ranges;
- wdt: wdt@b0002000 {
+ wdt: wdt@10002000 {
compatible = "ingenic,jz4740-wdt";
- reg = <0xb0002000 0x10>;
+ reg = <0x10002000 0x10>;
};
rtc: rtc@10003000 {
compatible = "ingenic,jz4740-rtc";
- reg = <0xb0003000 0x38>;
+ reg = <0x10003000 0x38>;
};
- serial0: serial@b0030000 {
+ serial0: serial@10030000 {
compatible = "ingenic,jz4740-uart";
- reg = <0xb0030000 0x20>;
+ reg = <0x10030000 0x20>;
reg-shift = <2>;
clock-frequency = <12000000>;
status = "disabled";
};
- serial1: serial@b0031000 {
+ serial1: serial@10031000 {
compatible = "ingenic,jz4740-uart";
- reg = <0xb0031000 0x20>;
+ reg = <0x10031000 0x20>;
reg-shift = <2>;
clock-frequency = <12000000>;
status = "disabled";
};
- serial2: serial@b0032000 {
+ serial2: serial@10032000 {
compatible = "ingenic,jz4740-uart";
- reg = <0xb0032000 0x20>;
+ reg = <0x10032000 0x20>;
reg-shift = <2>;
clock-frequency = <12000000>;
status = "disabled";
@@ -45,42 +45,42 @@
gpio0: gpio@10010000 {
compatible = "ingenic,jz4740-gpio";
gpio-controller;
- reg = <0xb0010000 0x100>;
+ reg = <0x10010000 0x100>;
#gpio-cells = <2>;
};
gpio1: gpio@10010100 {
compatible = "ingenic,jz4740-gpio";
gpio-controller;
- reg = <0xb0010100 0x100>;
+ reg = <0x10010100 0x100>;
#gpio-cells = <2>;
};
gpio2: gpio@10010200 {
compatible = "ingenic,jz4740-gpio";
gpio-controller;
- reg = <0xb0010200 0x100>;
+ reg = <0x10010200 0x100>;
#gpio-cells = <2>;
};
gpio3: gpio@10010300 {
compatible = "ingenic,jz4740-gpio";
gpio-controller;
- reg = <0xb0010300 0x100>;
+ reg = <0x10010300 0x100>;
#gpio-cells = <2>;
};
gpio4: gpio@10010400 {
compatible = "ingenic,jz4740-gpio";
gpio-controller;
- reg = <0xb0010400 0x100>;
+ reg = <0x10010400 0x100>;
#gpio-cells = <2>;
};
gpio5: gpio@10010500 {
compatible = "ingenic,jz4740-gpio";
gpio-controller;
- reg = <0xb0010500 0x100>;
+ reg = <0x10010500 0x100>;
#gpio-cells = <2>;
};
};
diff --git a/arch/mips/dts/jz4780.dtsi b/arch/mips/dts/jz4780.dtsi
new file mode 100644
index 0000000000..9f0de5d1ae
--- /dev/null
+++ b/arch/mips/dts/jz4780.dtsi
@@ -0,0 +1,56 @@
+#include "skeleton.dtsi"
+
+/ {
+ soc {
+ model = "Ingenic JZ4780";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <>;
+
+ wdt: wdt@10002000 {
+ compatible = "ingenic,jz4740-wdt";
+ reg = <0x10002000 0x10>;
+ };
+
+ uart0: serial@10030000 {
+ compatible = "ingenic,jz4740-uart";
+ reg = <0x10030000 0x100>;
+ reg-shift = <2>;
+ clock-frequency = <48000000>;
+ status = "disabled";
+ };
+
+ uart1: serial@10031000 {
+ compatible = "ingenic,jz4740-uart";
+ reg = <0x10031000 0x100>;
+ reg-shift = <2>;
+ clock-frequency = <48000000>;
+ status = "disabled";
+ };
+
+ uart2: serial@10032000 {
+ compatible = "ingenic,jz4740-uart";
+ reg = <0x10032000 0x100>;
+ reg-shift = <2>;
+ clock-frequency = <48000000>;
+ status = "disabled";
+ };
+
+ uart3: serial@10033000 {
+ compatible = "ingenic,jz4740-uart";
+ reg = <0x10033000 0x100>;
+ reg-shift = <2>;
+ clock-frequency = <48000000>;
+ status = "disabled";
+ };
+
+ uart4: serial@10034000 {
+ compatible = "ingenic,jz4740-uart";
+ reg = <0x10034000 0x100>;
+ reg-shift = <2>;
+ clock-frequency = <48000000>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/mips/dts/ls1b.dtsi b/arch/mips/dts/ls1b.dtsi
index f4ff8b6edd..af7119f1d0 100644
--- a/arch/mips/dts/ls1b.dtsi
+++ b/arch/mips/dts/ls1b.dtsi
@@ -8,33 +8,33 @@
device_type = "soc";
ranges;
- serial0: serial@bfe40000 {
+ serial0: serial@1fe40000 {
compatible = "ns16550a";
- reg = <0xbfe40000 0x8>;
+ reg = <0x1fe40000 0x8>;
reg-shift = <0>;
clock-frequency = <83000000>;
status = "disabled";
};
- serial1: serial@bfe44000 {
+ serial1: serial@1fe44000 {
compatible = "ns16550a";
- reg = <0xbfe44000 0x8>;
+ reg = <0x1fe44000 0x8>;
reg-shift = <0>;
clock-frequency = <83000000>;
status = "disabled";
};
- serial2: serial@bfe48000 {
+ serial2: serial@1fe48000 {
compatible = "ns16550a";
- reg = <0xbfe48000 0x8>;
+ reg = <0x1fe48000 0x8>;
reg-shift = <0>;
clock-frequency = <83000000>;
status = "disabled";
};
- serial3: serial@bfe4c000 {
+ serial3: serial@1fe4c000 {
compatible = "ns16550a";
- reg = <0xbfe4c000 0x8>;
+ reg = <0x1fe4c000 0x8>;
reg-shift = <0>;
clock-frequency = <83000000>;
status = "disabled";
diff --git a/arch/mips/dts/qemu-malta.dts b/arch/mips/dts/qemu-malta.dts
index cc1c9609ef..9b0c594e87 100644
--- a/arch/mips/dts/qemu-malta.dts
+++ b/arch/mips/dts/qemu-malta.dts
@@ -17,9 +17,9 @@
reg = <0x00000000 0x10000000>;
};
- uart0: serial@b80003f8 {
+ uart0: serial@180003f8 {
compatible = "ns16550a";
- reg = <0xb80003f8 0x08>;
+ reg = <0x180003f8 0x08>;
reg-shift = <0>;
/* no matter for emulated port */
clock-frequency = <1843200>;
@@ -28,7 +28,7 @@
gpio: gpio@1f000b00 {
compatible = "mti,malta-fpga-i2c-gpio";
gpio-controller;
- reg = <0xbf000b00 0x20>;
+ reg = <0x1f000b00 0x20>;
#gpio-cells = <2>;
};
@@ -44,19 +44,19 @@
status = "disabled";
};
- uart2: serial@bf000900 {
+ uart2: serial@1f000900 {
compatible = "ns16550a";
- reg = <0xbf000900 0x40>;
+ reg = <0x1f000900 0x40>;
reg-shift = <3>;
/* no matter for emulated port */
clock-frequency = <1843200>;
};
- nor0: flash@be000000 {
+ nor0: flash@1e000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cfi-flash";
- reg = <0xbe000000 0x00400000>;
+ reg = <0x1e000000 0x00400000>;
partition@0 {
label = "barebox";
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index dcc2a27a97..572cabba34 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -27,6 +27,7 @@
#define PRID_COMP_MIPS 0x010000
#define PRID_COMP_BROADCOM 0x020000
#define PRID_COMP_INGENIC 0xd00000
+#define PRID_COMP_INGENIC2 0xe10000
/*
* Assigned Processor ID (implementation) values for bits 15:8 of the PRId
diff --git a/arch/mips/lib/cpu-probe.c b/arch/mips/lib/cpu-probe.c
index 8235a54ae7..4622bcdd61 100644
--- a/arch/mips/lib/cpu-probe.c
+++ b/arch/mips/lib/cpu-probe.c
@@ -158,6 +158,7 @@ void cpu_probe(void)
cpu_probe_broadcom(c);
break;
case PRID_COMP_INGENIC:
+ case PRID_COMP_INGENIC2:
cpu_probe_ingenic(c);
break;
}
diff --git a/arch/mips/mach-xburst/Kconfig b/arch/mips/mach-xburst/Kconfig
index f7b8470cb8..2598c41cdf 100644
--- a/arch/mips/mach-xburst/Kconfig
+++ b/arch/mips/mach-xburst/Kconfig
@@ -6,6 +6,13 @@ config ARCH_TEXT_BASE
config CPU_JZ4755
bool
+ select SYS_HAS_CPU_MIPS32_R1
+ select WATCHDOG
+ select WATCHDOG_JZ4740
+
+config CPU_JZ4780
+ bool
+ select SYS_HAS_CPU_MIPS32_R2
select WATCHDOG
select WATCHDOG_JZ4740
@@ -17,24 +24,37 @@ config BOARD_RZX50
select HAS_POWEROFF
select CPU_JZ4755
+config BOARD_CI20
+ bool "Imagination Creator CI20"
+ select CPU_JZ4780
+
endchoice
if DEBUG_LL
-if CPU_JZ4755
choice
prompt "DEBUG_LL port"
-config JZ4750D_DEBUG_LL_UART0
+config JZ47XX_DEBUG_LL_UART0
+ depends on CPU_JZ4755 || CPU_JZ4780
bool "UART0"
-config JZ4750D_DEBUG_LL_UART1
+config JZ47XX_DEBUG_LL_UART1
+ depends on CPU_JZ4755 || CPU_JZ4780
bool "UART1"
-config JZ4750D_DEBUG_LL_UART2
+config JZ47XX_DEBUG_LL_UART2
+ depends on CPU_JZ4755 || CPU_JZ4780
bool "UART2"
+config JZ47XX_DEBUG_LL_UART3
+ depends on CPU_JZ4780
+ bool "UART3"
+
+config JZ47XX_DEBUG_LL_UART4
+ depends on CPU_JZ4780
+ bool "UART4"
+
endchoice
-endif # CPU_JZ4755
endif # DEBUG_LL
-endif
+endif # MACH_MIPS_XBURST
diff --git a/arch/mips/mach-xburst/include/mach/debug_ll_jz4750d.h b/arch/mips/mach-xburst/include/mach/debug_ll_jz4750d.h
index 2a55dea437..6d18366c5b 100644
--- a/arch/mips/mach-xburst/include/mach/debug_ll_jz4750d.h
+++ b/arch/mips/mach-xburst/include/mach/debug_ll_jz4750d.h
@@ -20,15 +20,15 @@
#include <mach/jz4750d_regs.h>
-#ifdef CONFIG_JZ4750D_DEBUG_LL_UART0
+#ifdef CONFIG_JZ47XX_DEBUG_LL_UART0
#define DEBUG_LL_UART_ADDR UART0_BASE
#endif
-#ifdef CONFIG_JZ4750D_DEBUG_LL_UART1
+#ifdef CONFIG_JZ47XX_DEBUG_LL_UART1
#define DEBUG_LL_UART_ADDR UART1_BASE
#endif
-#ifdef CONFIG_JZ4750D_DEBUG_LL_UART2
+#ifdef CONFIG_JZ47XX_DEBUG_LL_UART2
#define DEBUG_LL_UART_ADDR UART2_BASE
#endif
diff --git a/arch/mips/mach-xburst/include/mach/debug_ll_jz4780.h b/arch/mips/mach-xburst/include/mach/debug_ll_jz4780.h
new file mode 100644
index 0000000000..0bdc58caa2
--- /dev/null
+++ b/arch/mips/mach-xburst/include/mach/debug_ll_jz4780.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __INCLUDE_DEBUG_LL_JZ4780_H__
+#define __INCLUDE_DEBUG_LL_JZ4780_H__
+
+#include <mach/jz4780.h>
+
+#ifdef CONFIG_JZ47XX_DEBUG_LL_UART0
+#define DEBUG_LL_UART_ADDR JZ4780_UART0_BASE
+#endif
+
+#ifdef CONFIG_JZ47XX_DEBUG_LL_UART1
+#define DEBUG_LL_UART_ADDR JZ4780_UART1_BASE
+#endif
+
+#ifdef CONFIG_JZ47XX_DEBUG_LL_UART2
+#define DEBUG_LL_UART_ADDR JZ4780_UART2_BASE
+#endif
+
+#ifdef CONFIG_JZ47XX_DEBUG_LL_UART3
+#define DEBUG_LL_UART_ADDR JZ4780_UART3_BASE
+#endif
+
+#ifdef CONFIG_JZ47XX_DEBUG_LL_UART4
+#define DEBUG_LL_UART_ADDR JZ4780_UART4_BASE
+#endif
+
+#define DEBUG_LL_UART_SHIFT 2
+
+#ifndef DEBUG_LL_UART_CLK
+#define DEBUG_LL_UART_CLK (48000000 / 16)
+#endif
+#define DEBUG_LL_UART_BPS CONFIG_BAUDRATE
+#define DEBUG_LL_UART_DIVISOR (DEBUG_LL_UART_CLK / DEBUG_LL_UART_BPS)
+
+#endif /* __INCLUDE_DEBUG_LL_JZ4780_H__ */
diff --git a/arch/mips/mach-xburst/include/mach/jz4780.h b/arch/mips/mach-xburst/include/mach/jz4780.h
new file mode 100644
index 0000000000..4503a93ec1
--- /dev/null
+++ b/arch/mips/mach-xburst/include/mach/jz4780.h
@@ -0,0 +1,30 @@
+/*
+ * JZ4780 SoC definitions
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MIPS_ASM_MACH_JZ4780_JZ4780_H__
+#define __MIPS_ASM_MACH_JZ4780_JZ4780_H__
+
+/* APB bus devices */
+#define JZ4780_UART0_BASE 0xb0030000
+#define JZ4780_UART1_BASE 0xb0031000
+#define JZ4780_UART2_BASE 0xb0032000
+#define JZ4780_UART3_BASE 0xb0033000
+#define JZ4780_UART4_BASE 0xb0034000
+#define JZ4780_UARTn_BASE(n) (JZ4780_UART0_BASE + (n * 0x1000))
+
+#endif /* __MIPS_ASM_MACH_JZ4780_JZ4780_H__ */
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index 23c6a71f3a..483ae6db4a 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -1,5 +1,6 @@
config OPENRISC
bool
+ select OFTREE
select HAS_CACHE
select HAVE_CONFIGURABLE_MEMORY_LAYOUT
select HAVE_DEFAULT_ENVIRONMENT_NEW
@@ -11,6 +12,14 @@ config ARCH_TEXT_BASE
hex
default 0x00000000
+config BUILTIN_DTB
+ bool "link a DTB into the barebox image"
+ depends on OFTREE
+
+config BUILTIN_DTB_NAME
+ string "DTB to build into the barebox image"
+ depends on BUILTIN_DTB
+
choice
prompt "Select your board"
diff --git a/arch/openrisc/Makefile b/arch/openrisc/Makefile
index fd8bbbf4d7..b0c8566e4e 100644
--- a/arch/openrisc/Makefile
+++ b/arch/openrisc/Makefile
@@ -19,3 +19,10 @@ common-y += arch/openrisc/lib/
common-y += arch/openrisc/cpu/
lds-y += arch/openrisc/cpu/barebox.lds
+
+common-$(CONFIG_BUILTIN_DTB) += arch/openrisc/dts/
+
+dts := arch/openrisc/dts
+
+%.dtb: scripts
+ $(Q)$(MAKE) $(build)=$(dts) $(dts)/$@
diff --git a/arch/openrisc/boards/generic/config.h b/arch/openrisc/boards/generic/config.h
index 6ebab42692..f6a054beed 100644
--- a/arch/openrisc/boards/generic/config.h
+++ b/arch/openrisc/boards/generic/config.h
@@ -8,13 +8,8 @@
#define OPENRISC_SOPC_MEMORY_BASE 0x00000000
#define OPENRISC_SOPC_MEMORY_SIZE 0x02000000
-#define OPENRISC_SOPC_UART_FREQ CONFIG_SYS_CLK_FREQ
-#define OPENRISC_SOPC_UART_BASE 0x90000000
-
-#define OPENRISC_SOPC_ETHOC_BASE 0x92000000
-
-/* We reserve 256K for barebox */
-#define BAREBOX_RESERVED_SIZE 0x40000
+/* We reserve 512K for barebox */
+#define BAREBOX_RESERVED_SIZE 0x80000
/* Barebox will be at top of main memory */
#define OPENRISC_SOPC_TEXT_BASE (OPENRISC_SOPC_MEMORY_BASE + OPENRISC_SOPC_MEMORY_SIZE - BAREBOX_RESERVED_SIZE)
diff --git a/arch/openrisc/boards/generic/generic.c b/arch/openrisc/boards/generic/generic.c
index 9f680073cb..ff6f9f4d42 100644
--- a/arch/openrisc/boards/generic/generic.c
+++ b/arch/openrisc/boards/generic/generic.c
@@ -1,30 +1,10 @@
#include <common.h>
#include <init.h>
-#include <driver.h>
-#include <partition.h>
-#include <ns16550.h>
-static struct NS16550_plat serial_plat = {
- .clock = OPENRISC_SOPC_UART_FREQ,
- .shift = 0,
-};
-
-static int openrisc_console_init(void)
+static int openrisc_core_init(void)
{
- barebox_set_model("OpenRISC or1k");
barebox_set_hostname("or1k");
- /* Register the serial port */
- add_ns16550_device(DEVICE_ID_DYNAMIC, OPENRISC_SOPC_UART_BASE, 1024,
- IORESOURCE_MEM | IORESOURCE_MEM_8BIT, &serial_plat);
-
-#ifdef CONFIG_DRIVER_NET_ETHOC
- add_generic_device("ethoc", DEVICE_ID_DYNAMIC, NULL,
- OPENRISC_SOPC_ETHOC_BASE, 0x1000,
- IORESOURCE_MEM, NULL);
-#endif
-
return 0;
}
-
-console_initcall(openrisc_console_init);
+core_initcall(openrisc_core_init);
diff --git a/arch/openrisc/configs/generic_defconfig b/arch/openrisc/configs/generic_defconfig
index deaef2a3aa..1f2d40eae9 100644
--- a/arch/openrisc/configs/generic_defconfig
+++ b/arch/openrisc/configs/generic_defconfig
@@ -1,26 +1,35 @@
-CONFIG_LONGHELP=y
+CONFIG_BUILTIN_DTB=y
+CONFIG_BUILTIN_DTB_NAME="or1ksim"
CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_PARTITION=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
-CONFIG_CMD_EDIT=y
-CONFIG_CMD_SAVEENV=y
-CONFIG_CMD_EXPORT=y
-CONFIG_CMD_PRINTENV=y
-CONFIG_CMD_TIME=y
-CONFIG_CMD_ECHO_E=y
+CONFIG_LONGHELP=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_MEMINFO=y
-CONFIG_CMD_FLASH=y
# CONFIG_CMD_BOOTM is not set
-CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
-CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_RESET=y
CONFIG_CMD_PARTITION=y
-CONFIG_DRIVER_SERIAL_NS16550=y
-CONFIG_NET=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_SAVEENV=y
CONFIG_CMD_DHCP=y
+CONFIG_CMD_MIITOOL=y
CONFIG_CMD_PING=y
CONFIG_CMD_TFTP=y
-CONFIG_FS_TFTP=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_OF_NODE=y
+CONFIG_CMD_OF_PROPERTY=y
+CONFIG_CMD_OFTREE=y
+CONFIG_CMD_TIME=y
+CONFIG_NET=y
+CONFIG_OFDEVICE=y
+CONFIG_OF_BAREBOX_DRIVERS=y
+CONFIG_DRIVER_SERIAL_NS16550=y
CONFIG_DRIVER_NET_ETHOC=y
+CONFIG_FS_TFTP=y
diff --git a/arch/openrisc/cpu/barebox.lds.S b/arch/openrisc/cpu/barebox.lds.S
index add9181e13..dbecdbfbfc 100644
--- a/arch/openrisc/cpu/barebox.lds.S
+++ b/arch/openrisc/cpu/barebox.lds.S
@@ -69,6 +69,8 @@ SECTIONS
__usymtab : { BAREBOX_SYMS } > ram
___usymtab_end = .;
+ .dtb : { BAREBOX_DTB() } > ram
+
__etext = .; /* End of text and rodata section */
. = ALIGN(4);
diff --git a/arch/openrisc/dts/Makefile b/arch/openrisc/dts/Makefile
new file mode 100644
index 0000000000..6d6c9a3ce0
--- /dev/null
+++ b/arch/openrisc/dts/Makefile
@@ -0,0 +1,5 @@
+
+BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_NAME))
+obj-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB).dtb.o
+
+clean-files := *.dtb *.dtb.S
diff --git a/arch/openrisc/dts/or1ksim.dts b/arch/openrisc/dts/or1ksim.dts
new file mode 100644
index 0000000000..7316cc6770
--- /dev/null
+++ b/arch/openrisc/dts/or1ksim.dts
@@ -0,0 +1,51 @@
+/dts-v1/;
+/ {
+ model = "or1ksim";
+ compatible = "opencores,or1ksim";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&pic>;
+
+ chosen {
+ bootargs = "console=uart,mmio,0x90000000,115200";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x02000000>;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu@0 {
+ compatible = "opencores,or1200-rtlsvn481";
+ reg = <0>;
+ clock-frequency = <20000000>;
+ };
+ };
+
+ /*
+ * OR1K PIC is built into CPU and accessed via special purpose
+ * registers. It is not addressable and, hence, has no 'reg'
+ * property.
+ */
+ pic: pic {
+ compatible = "opencores,or1k-pic";
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+
+ serial0: serial@90000000 {
+ compatible = "ns16550a";
+ reg = <0x90000000 0x100>;
+ interrupts = <2>;
+ clock-frequency = <50000000>;
+ };
+
+ enet0: ethoc@92000000 {
+ compatible = "opencores,ethoc";
+ reg = <0x92000000 0x100>;
+ interrupts = <4>;
+ };
+};
diff --git a/arch/openrisc/lib/Makefile b/arch/openrisc/lib/Makefile
index 0b3cc5068c..62082feed0 100644
--- a/arch/openrisc/lib/Makefile
+++ b/arch/openrisc/lib/Makefile
@@ -5,3 +5,4 @@ obj-y += muldi3.o
obj-y += lshrdi3.o
obj-y += ashldi3.o
obj-y += ashrdi3.o
+obj-$(CONFIG_BUILTIN_DTB) += dtb.o
diff --git a/arch/openrisc/lib/dtb.c b/arch/openrisc/lib/dtb.c
new file mode 100644
index 0000000000..4f63a7760f
--- /dev/null
+++ b/arch/openrisc/lib/dtb.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * Based on arch/arm/cpu/dtb.c:
+ * Copyright (C) 2013 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <common.h>
+#include <init.h>
+#include <of.h>
+
+extern char __dtb_start[];
+
+static int of_openrisc_init(void)
+{
+ struct device_node *root;
+
+ root = of_get_root_node();
+ if (root)
+ return 0;
+
+ root = of_unflatten_dtb(__dtb_start);
+ if (root) {
+ pr_debug("using internal DTB\n");
+ of_set_root_node(root);
+ if (IS_ENABLED(CONFIG_OFDEVICE))
+ of_probe();
+ }
+
+ return 0;
+}
+core_initcall(of_openrisc_init);
diff --git a/arch/ppc/mach-mpc85xx/.gitignore b/arch/ppc/mach-mpc85xx/.gitignore
new file mode 100644
index 0000000000..d1165788c9
--- /dev/null
+++ b/arch/ppc/mach-mpc85xx/.gitignore
@@ -0,0 +1 @@
+barebox.lds
diff --git a/commands/Kconfig b/commands/Kconfig
index 3a49bafd27..6528bf76c7 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -84,6 +84,13 @@ config CMD_DEVINFO
If called with a device path being the argument, devinfo shows more
default information about this device and its parameters.
+config CMD_DMESG
+ tristate
+ prompt "dmesg"
+ select LOGBUF
+ help
+ Print or control the log message buffer.
+
config CMD_DRVINFO
tristate
default y
@@ -1905,6 +1912,15 @@ config CMD_BAREBOX_UPDATE
-y autom. use 'yes' when asking confirmations
-f LEVEL set force level
+config CMD_FIRMWARELOAD
+ bool
+ select FIRMWARE
+ prompt "firmwareload"
+ help
+ Provides the "firmwareload" command which deals with devices which need
+ firmware to work. It is also used to upload firmware to FPGA devices.
+
+
config CMD_LINUX_EXEC
bool "linux exec"
depends on LINUX
@@ -1973,6 +1989,21 @@ config CMD_OF_PROPERTY
[00 11 22 .. nn] - byte stream
If the value does not start with '<' or '[' it is interpreted as string
+config CMD_OF_DISPLAY_TIMINGS
+ tristate
+ select OFTREE
+ prompt "of_display_timings"
+ help
+ List and select display timings
+
+ Usage: of_display_timings [-lS] [-s path] [-f dtb]
+
+ Options:
+ -l list path of all available display-timings
+ -S list path of all selected display-timings
+ -s path select display-timings and register oftree fixup
+ -f dtb work on dtb. Has no effect on -s option
+
config CMD_OFTREE
tristate
select OFTREE
diff --git a/commands/Makefile b/commands/Makefile
index 52b6137c01..b1cdf331c4 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -76,11 +76,13 @@ obj-$(CONFIG_CMD_OFTREE) += oftree.o
obj-$(CONFIG_CMD_OF_PROPERTY) += of_property.o
obj-$(CONFIG_CMD_OF_NODE) += of_node.o
obj-$(CONFIG_CMD_OF_DUMP) += of_dump.o
+obj-$(CONFIG_CMD_OF_DISPLAY_TIMINGS) += of_display_timings.o
obj-$(CONFIG_CMD_MAGICVAR) += magicvar.o
obj-$(CONFIG_CMD_IOMEM) += iomemport.o
obj-$(CONFIG_CMD_LINUX_EXEC) += linux_exec.o
obj-$(CONFIG_CMD_AUTOMOUNT) += automount.o
obj-$(CONFIG_CMD_GLOBAL) += global.o
+obj-$(CONFIG_CMD_DMESG) += dmesg.o
obj-$(CONFIG_CMD_BASENAME) += basename.o
obj-$(CONFIG_CMD_DIRNAME) += dirname.o
obj-$(CONFIG_CMD_READLINK) += readlink.o
@@ -103,3 +105,4 @@ obj-$(CONFIG_CMD_LSPCI) += lspci.o
obj-$(CONFIG_CMD_IMD) += imd.o
obj-$(CONFIG_CMD_HWCLOCK) += hwclock.o
obj-$(CONFIG_CMD_USBGADGET) += usbgadget.o
+obj-$(CONFIG_CMD_FIRMWARELOAD) += firmwareload.o
diff --git a/commands/dmesg.c b/commands/dmesg.c
new file mode 100644
index 0000000000..b2bb334e24
--- /dev/null
+++ b/commands/dmesg.c
@@ -0,0 +1,100 @@
+/*
+ * dmesg.c - barebox logbuffer handling
+ *
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <common.h>
+#include <malloc.h>
+#include <command.h>
+#include <globalvar.h>
+#include <environment.h>
+#include <getopt.h>
+#include <clock.h>
+
+static int do_dmesg(int argc, char *argv[])
+{
+ int opt, i;
+ int delete_buf = 0, emit = 0;
+ unsigned flags = 0;
+
+ while ((opt = getopt(argc, argv, "ctde")) > 0) {
+ switch (opt) {
+ case 'c':
+ delete_buf = 1;
+ break;
+ case 't':
+ flags |= BAREBOX_LOG_PRINT_TIME;
+ break;
+ case 'd':
+ flags |= BAREBOX_LOG_DIFF_TIME;
+ break;
+ case 'e':
+ emit = 1;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (emit) {
+ char *buf;
+ int len = 0;
+
+ for (i = optind; i < argc; i++)
+ len += strlen(argv[i]) + 1;
+
+ buf = malloc(len + 2);
+ if (!buf)
+ return -ENOMEM;
+
+ len = 0;
+
+ for (i = optind; i < argc; i++)
+ len += sprintf(buf + len, "%s ", argv[i]);
+
+ *(buf + len) = '\n';
+ *(buf + len + 1) = 0;
+
+ pr_info(buf);
+
+ free(buf);
+
+ return 0;
+ }
+
+ log_print(flags);
+
+ if (delete_buf)
+ log_clean(10);
+
+ return 0;
+}
+
+BAREBOX_CMD_HELP_START(dmesg)
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-c", "Delete messages after printing them")
+BAREBOX_CMD_HELP_OPT ("-d", "Show a time delta to the last message")
+BAREBOX_CMD_HELP_OPT ("-e <msg>", "Emit a log message")
+BAREBOX_CMD_HELP_OPT ("-t", "Show timestamp informations")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(dmesg)
+ .cmd = do_dmesg,
+ BAREBOX_CMD_DESC("Print or control log messages")
+ BAREBOX_CMD_OPTS("[-cdet]")
+ BAREBOX_CMD_GROUP(CMD_GRP_INFO)
+ BAREBOX_CMD_HELP(cmd_dmesg_help)
+BAREBOX_CMD_END
diff --git a/commands/firmwareload.c b/commands/firmwareload.c
new file mode 100644
index 0000000000..a2596951a7
--- /dev/null
+++ b/commands/firmwareload.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013 Juergen Beisert <kernel@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <common.h>
+#include <command.h>
+#include <getopt.h>
+#include <firmware.h>
+
+static int do_firmwareload(int argc, char *argv[])
+{
+ int ret, opt;
+ const char *name = NULL, *firmware;
+ struct firmware_mgr *mgr;
+
+ while ((opt = getopt(argc, argv, "t:l")) > 0) {
+ switch (opt) {
+ case 't':
+ name = optarg;
+ break;
+ case 'l':
+ firmwaremgr_list_handlers();
+ return 0;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (!(argc - optind))
+ return COMMAND_ERROR_USAGE;
+
+ firmware = argv[optind];
+
+ mgr = firmwaremgr_find(name);
+
+ if (!mgr) {
+ printf("No such programming handler found: %s\n",
+ name ? name : "default");
+ return 1;
+ }
+
+ ret = firmwaremgr_load_file(mgr, firmware);
+
+ return ret;
+}
+
+BAREBOX_CMD_HELP_START(firmwareload)
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT("-t <target>", "define the firmware handler by name\n")
+BAREBOX_CMD_HELP_OPT("-l\t", "list devices capable of firmware loading\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(firmwareload)
+ .cmd = do_firmwareload,
+ BAREBOX_CMD_DESC("Program a firmware file into a device")
+ BAREBOX_CMD_HELP(cmd_firmwareload_help)
+BAREBOX_CMD_END
diff --git a/commands/of_display_timings.c b/commands/of_display_timings.c
new file mode 100644
index 0000000000..ccf2db0da5
--- /dev/null
+++ b/commands/of_display_timings.c
@@ -0,0 +1,164 @@
+/*
+ * of_display_timings.c - list and select display_timings
+ *
+ * Copyright (c) 2014 Teresa Gámez <t.gamez@phytec.de> PHYTEC Messtechnik GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <common.h>
+#include <filetype.h>
+#include <libfile.h>
+#include <of.h>
+#include <command.h>
+#include <malloc.h>
+#include <complete.h>
+#include <asm/byteorder.h>
+#include <getopt.h>
+#include <linux/err.h>
+#include <string.h>
+
+static int of_display_timing(struct device_node *root, void *timingpath)
+{
+ int ret = 0;
+ struct device_node *display;
+
+ display = of_find_node_by_path_from(root, timingpath);
+ if (!display) {
+ pr_err("Path to display-timings is not vaild.\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = of_set_property_to_child_phandle(display, "native-mode");
+ if (ret)
+ pr_err("Could not set display\n");
+out:
+ return ret;
+}
+
+static int do_of_display_timings(int argc, char *argv[])
+{
+ int opt;
+ int list = 0;
+ int selected = 0;
+ struct device_node *root = NULL;
+ struct device_node *display = NULL;
+ struct device_node *timings = NULL;
+ char *timingpath = NULL;
+ char *dtbfile = NULL;
+
+ while ((opt = getopt(argc, argv, "sS:lf:")) > 0) {
+ switch (opt) {
+ case 'l':
+ list = 1;
+ break;
+ case 'f':
+ dtbfile = optarg;
+ break;
+ case 's':
+ selected = 1;
+ break;
+ case 'S':
+ timingpath = xzalloc(strlen(optarg) + 1);
+ strcpy(timingpath, optarg);
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ /* Check if external dtb given */
+ if (dtbfile) {
+ void *fdt;
+ size_t size;
+
+ fdt = read_file(dtbfile, &size);
+ if (!fdt) {
+ pr_err("unable to read %s: %s\n", dtbfile,
+ strerror(errno));
+ return -errno;
+ }
+
+ if (file_detect_type(fdt, size) != filetype_oftree) {
+ pr_err("%s is not a oftree file.\n", dtbfile);
+ free(fdt);
+ return -EINVAL;
+ }
+
+ root = of_unflatten_dtb(fdt);
+
+ free(fdt);
+
+ if (IS_ERR(root))
+ return PTR_ERR(root);
+
+ } else {
+ root = of_get_root_node();
+ }
+
+ if (list) {
+ int found = 0;
+ const char *node = "display-timings";
+
+ for_each_node_by_name_from(display, root, node) {
+ for_each_child_of_node(display, timings) {
+ printf("%s\n", timings->full_name);
+ found = 1;
+ }
+ }
+
+ if (!found)
+ printf("No display-timings found.\n");
+ }
+
+ if (selected) {
+ int found = 0;
+ const char *node = "display-timings";
+
+ for_each_node_by_name_from(display, root, node) {
+ timings = of_parse_phandle_from(display, root,
+ "native-mode", 0);
+ if (!timings)
+ continue;
+
+ printf("%s\n", timings->full_name);
+ found = 1;
+ }
+
+ if (!found)
+ printf("No selected display-timings found.\n");
+ }
+
+ if (timingpath)
+ of_register_fixup(of_display_timing, timingpath);
+
+ return 0;
+}
+
+BAREBOX_CMD_HELP_START(of_display_timings)
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT("-l", "list path of all available display-timings\n")
+BAREBOX_CMD_HELP_OPT("-s", "list path of all selected display-timings\n")
+BAREBOX_CMD_HELP_OPT("-S path", "select display-timings and register oftree fixup\n")
+BAREBOX_CMD_HELP_OPT("-f dtb", "work on dtb. Has no effect on -s option\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(of_display_timings)
+ .cmd = do_of_display_timings,
+ BAREBOX_CMD_DESC("print and select display-timings")
+ BAREBOX_CMD_OPTS("[-ls] [-S path] [-f dtb]")
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+ BAREBOX_CMD_COMPLETE(devicetree_file_complete)
+ BAREBOX_CMD_HELP(cmd_of_display_timings_help)
+BAREBOX_CMD_END
diff --git a/commands/usb.c b/commands/usb.c
index a37d50327f..48c6619fde 100644
--- a/commands/usb.c
+++ b/commands/usb.c
@@ -138,7 +138,6 @@ BAREBOX_CMD_HELP_START(usb)
BAREBOX_CMD_HELP_TEXT("Scan for USB devices.")
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
-BAREBOX_CMD_HELP_OPT("-f", "force rescan")
BAREBOX_CMD_HELP_OPT("-s", "show devices")
BAREBOX_CMD_HELP_OPT("-t", "show USB tree")
BAREBOX_CMD_HELP_END
@@ -146,7 +145,7 @@ BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(usb)
.cmd = do_usb,
BAREBOX_CMD_DESC("(re-)detect USB devices")
- BAREBOX_CMD_OPTS("[-fts]")
+ BAREBOX_CMD_OPTS("[-ts]")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_HELP(cmd_usb_help)
BAREBOX_CMD_COMPLETE(empty_complete)
diff --git a/common/Kconfig b/common/Kconfig
index 9cc96b776d..016ba444a3 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -66,6 +66,9 @@ config UIMAGE
select CRC32
bool
+config LOGBUF
+ bool
+
config GLOBALVAR
bool
@@ -328,6 +331,9 @@ config CBSIZE
prompt "Buffer size for input from the Console"
default 1024
+config FIRMWARE
+ bool
+
choice
prompt "Select your shell"
diff --git a/common/Makefile b/common/Makefile
index 51b7d4ea85..282ddbca25 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_EFI_DEVICEPATH) += efi-devicepath.o
lwl-$(CONFIG_IMD) += imd-barebox.o
obj-$(CONFIG_IMD) += imd.o
obj-$(CONFIG_FILE_LIST) += file-list.o
+obj-$(CONFIG_FIRMWARE) += firmware.o
quiet_cmd_pwd_h = PWDH $@
ifdef CONFIG_PASSWORD
diff --git a/common/clock.c b/common/clock.c
index 9c7c1ba58c..76ce881067 100644
--- a/common/clock.c
+++ b/common/clock.c
@@ -29,6 +29,12 @@
static struct clocksource *current_clock;
static uint64_t time_ns;
+/*
+ * The first timestamp when the clocksource is registered.
+ * Useful for measuring the time spent in barebox.
+ */
+uint64_t time_beginning;
+
/**
* get_time_ns - get current timestamp in nanoseconds
*/
@@ -38,6 +44,9 @@ uint64_t get_time_ns(void)
uint64_t cycle_now, cycle_delta;
uint64_t ns_offset;
+ if (!cs)
+ return 0;
+
/* read clocksource: */
cycle_now = cs->read() & cs->mask;
@@ -180,5 +189,7 @@ EXPORT_SYMBOL(mdelay);
int init_clock(struct clocksource *cs)
{
current_clock = cs;
+ time_beginning = get_time_ns();
+
return 0;
}
diff --git a/common/console_common.c b/common/console_common.c
index cc184dfaef..cc25f97d9d 100644
--- a/common/console_common.c
+++ b/common/console_common.c
@@ -27,6 +27,9 @@
#include <globalvar.h>
#include <magicvar.h>
#include <password.h>
+#include <clock.h>
+#include <malloc.h>
+#include <asm-generic/div64.h>
#ifndef CONFIG_CONSOLE_NONE
@@ -59,31 +62,151 @@ void console_allow_input(bool val)
int barebox_loglevel = CONFIG_DEFAULT_LOGLEVEL;
+LIST_HEAD(barebox_logbuf);
+static int barebox_logbuf_num_messages;
+static int barebox_log_max_messages = 1000;
+
+static void log_del(struct log_entry *log)
+{
+ free(log->msg);
+ list_del(&log->list);
+ free(log);
+ barebox_logbuf_num_messages--;
+}
+
+/**
+ * log_clean - delete log messages from buffer
+ *
+ * @limit: The maximum messages left in the buffer after
+ * calling this function.
+ *
+ * This function deletes all messages in the logbuf exeeding
+ * the limit.
+ */
+void log_clean(unsigned int limit)
+{
+ struct log_entry *log, *tmp;
+
+ if (list_empty(&barebox_logbuf))
+ return;
+
+ list_for_each_entry_safe(log, tmp, &barebox_logbuf, list) {
+ if (barebox_logbuf_num_messages <= limit)
+ break;
+ log_del(log);
+ }
+}
+
+void pr_puts(int level, const char *str)
+{
+ struct log_entry *log;
+
+ if (IS_ENABLED(CONFIG_LOGBUF)) {
+ if (barebox_log_max_messages > 0)
+ log_clean(barebox_log_max_messages - 1);
+
+ if (barebox_log_max_messages >= 0) {
+ log = xzalloc(sizeof(*log));
+ log->msg = xstrdup(str);
+ log->timestamp = get_time_ns();
+ log->level = level;
+ list_add_tail(&log->list, &barebox_logbuf);
+ barebox_logbuf_num_messages++;
+ }
+ }
+
+ if (level > barebox_loglevel)
+ return;
+
+ puts(str);
+}
+
int pr_print(int level, const char *fmt, ...)
{
va_list args;
uint i;
char printbuffer[CFG_PBSIZE];
- if (level > barebox_loglevel)
+ if (!IS_ENABLED(CONFIG_LOGBUF) && level > barebox_loglevel)
return 0;
va_start(args, fmt);
i = vsprintf(printbuffer, fmt, args);
va_end(args);
- /* Print the string */
- puts(printbuffer);
+ pr_puts(level, printbuffer);
return i;
}
+int dev_printf(int level, const struct device_d *dev, const char *format, ...)
+{
+ va_list args;
+ int ret = 0;
+ char printbuffer[CFG_PBSIZE];
+
+ if (!IS_ENABLED(CONFIG_LOGBUF) && level > barebox_loglevel)
+ return 0;
+
+ if (dev->driver && dev->driver->name)
+ ret += sprintf(printbuffer, "%s ", dev->driver->name);
+
+ ret += sprintf(printbuffer + ret, "%s: ", dev_name(dev));
+
+ va_start(args, format);
+
+ ret += vsprintf(printbuffer + ret, format, args);
+
+ va_end(args);
+
+ pr_puts(level, printbuffer);
+
+ return ret;
+}
+
static int loglevel_init(void)
{
+ if (IS_ENABLED(CONFIG_LOGBUF))
+ globalvar_add_simple_int("log_max_messages",
+ &barebox_log_max_messages, "%d");
+
return globalvar_add_simple_int("loglevel", &barebox_loglevel, "%d");
}
device_initcall(loglevel_init);
+void log_print(unsigned flags)
+{
+ struct log_entry *log;
+ unsigned long last = 0;
+
+ list_for_each_entry(log, &barebox_logbuf, list) {
+ uint64_t diff = log->timestamp - time_beginning;
+ unsigned long difful;
+
+ do_div(diff, 1000);
+ difful = diff;
+
+ if (!log->timestamp)
+ difful = 0;
+
+ if (flags & (BAREBOX_LOG_PRINT_TIME | BAREBOX_LOG_DIFF_TIME))
+ printf("[");
+
+ if (flags & BAREBOX_LOG_PRINT_TIME)
+ printf("%10luus", difful);
+
+ if (flags & BAREBOX_LOG_DIFF_TIME) {
+ printf(" < %10luus", difful - last);
+ last = difful;
+ }
+
+ if (flags & (BAREBOX_LOG_PRINT_TIME | BAREBOX_LOG_DIFF_TIME))
+ printf("] ");
+
+ printf("%s", log->msg);
+ }
+}
+
int printf(const char *fmt, ...)
{
va_list args;
diff --git a/common/firmware.c b/common/firmware.c
new file mode 100644
index 0000000000..2a62a81c78
--- /dev/null
+++ b/common/firmware.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2013 Juergen Beisert <kernel@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <firmware.h>
+#include <common.h>
+#include <malloc.h>
+#include <xfuncs.h>
+#include <fcntl.h>
+#include <libbb.h>
+#include <fs.h>
+#include <linux/list.h>
+#include <linux/stat.h>
+#include <linux/err.h>
+
+#define BUFSIZ 4096
+
+struct firmware_mgr {
+ struct list_head list;
+ struct firmware_handler *handler; /* the program handler */
+ struct cdev cdev;
+ u8 buf[BUFSIZ];
+ int ofs;
+};
+
+static LIST_HEAD(firmwaremgr_list);
+
+/*
+ * firmwaremgr_find - find a firmware device handler
+ *
+ * Find a firmware device handler based on the unique id. If @id is
+ * NULL this returns the single firmware device handler if only one
+ * is registered. If multiple handlers are registered @id is mandatory
+ *
+ */
+struct firmware_mgr *firmwaremgr_find(const char *id)
+{
+ struct firmware_mgr *mgr;
+
+ if (!id) {
+ if (list_is_singular(&firmwaremgr_list))
+ return list_first_entry(&firmwaremgr_list,
+ struct firmware_mgr, list);
+ else
+ return NULL;
+ }
+
+ list_for_each_entry(mgr, &firmwaremgr_list, list)
+ if (!strcmp(mgr->handler->id, id))
+ return mgr;
+
+ return NULL;
+}
+
+/*
+ * firmwaremgr_list_handlers - list registered firmware device handlers
+ * in pretty format
+ */
+void firmwaremgr_list_handlers(void)
+{
+ struct firmware_mgr *mgr;
+
+ printf("firmware programming handlers:\n\n");
+
+ if (list_empty(&firmwaremgr_list)) {
+ printf("(none)\n");
+ return;
+ }
+
+ printf("%-11s%-11s\n", "name:", "model:");
+
+ list_for_each_entry(mgr, &firmwaremgr_list, list) {
+ printf("%-11s", mgr->handler->id);
+ if (mgr->handler->model)
+ printf(" -> %-11s", mgr->handler->model);
+ printf("\n");
+ }
+}
+
+static int firmware_open(struct cdev *cdev, unsigned long flags)
+{
+ struct firmware_mgr *mgr = cdev->priv;
+ int ret;
+
+ mgr->ofs = 0;
+
+ ret = mgr->handler->open(mgr->handler);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static ssize_t firmware_write(struct cdev *cdev, const void *buf, size_t insize,
+ loff_t offset, ulong flags)
+{
+ struct firmware_mgr *mgr = cdev->priv;
+ int ret;
+ size_t count = insize;
+
+ /*
+ * We guarantee the write handler of the firmware device that only the
+ * last write is a short write. All others are 4k in size.
+ */
+
+ while (count) {
+ size_t space = BUFSIZ - mgr->ofs;
+ size_t now = min(count, space);
+
+ memcpy(mgr->buf + mgr->ofs, buf, now);
+
+ buf += now;
+ mgr->ofs += now;
+ count -= now;
+
+ if (mgr->ofs == BUFSIZ) {
+ ret = mgr->handler->write(mgr->handler, mgr->buf, BUFSIZ);
+ if (ret < 0)
+ return ret;
+
+ mgr->ofs = 0;
+ }
+ }
+
+ return insize;
+}
+
+static int firmware_close(struct cdev *cdev)
+{
+ struct firmware_mgr *mgr = cdev->priv;
+ int ret;
+
+ if (mgr->ofs) {
+ ret = mgr->handler->write(mgr->handler, mgr->buf, mgr->ofs);
+ if (ret)
+ return ret;
+ }
+
+ ret = mgr->handler->close(mgr->handler);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static struct file_operations firmware_ops = {
+ .open = firmware_open,
+ .write = firmware_write,
+ .close = firmware_close,
+};
+
+/*
+ * firmwaremgr_register - register a device which needs firmware
+ */
+int firmwaremgr_register(struct firmware_handler *fh)
+{
+ struct firmware_mgr *mgr;
+ int ret;
+ struct cdev *cdev;
+
+ if (firmwaremgr_find(fh->id))
+ return -EBUSY;
+
+ mgr = xzalloc(sizeof(struct firmware_mgr));
+ mgr->handler = fh;
+
+ cdev = &mgr->cdev;
+
+ cdev->name = xstrdup(fh->id);
+ cdev->size = FILE_SIZE_STREAM;
+ cdev->ops = &firmware_ops;
+ cdev->priv = mgr;
+ cdev->dev = fh->dev;
+
+ ret = devfs_create(cdev);
+ if (ret)
+ goto out;
+
+ list_add_tail(&mgr->list, &firmwaremgr_list);
+
+ return 0;
+out:
+ free(cdev->name);
+ free(mgr);
+
+ return ret;
+}
+
+/*
+ * firmware_load_file - load a firmware to a device
+ */
+int firmwaremgr_load_file(struct firmware_mgr *mgr, const char *firmware)
+{
+ int ret;
+ char *name = asprintf("/dev/%s", mgr->handler->id);
+
+ ret = copy_file(firmware, name, 0);
+
+ free(name);
+
+ return ret;
+}
diff --git a/common/version.c b/common/version.c
index 51d4d48b52..f37cb5527f 100644
--- a/common/version.c
+++ b/common/version.c
@@ -12,6 +12,8 @@ EXPORT_SYMBOL(release_string);
void barebox_banner (void)
{
- pr_info("\n\n%s\n\n", version_string);
+ printf("\n\n");
+ pr_info("%s", version_string);
+ printf("\n\n");
pr_info("Board: %s\n", barebox_get_model());
}
diff --git a/drivers/Kconfig b/drivers/Kconfig
index d38032c0e6..e126f62c8f 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -29,5 +29,6 @@ source "drivers/regulator/Kconfig"
source "drivers/reset/Kconfig"
source "drivers/pci/Kconfig"
source "drivers/rtc/Kconfig"
+source "drivers/firmware/Kconfig"
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 4591f9a408..cf42190b7b 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -28,3 +28,4 @@ obj-$(CONFIG_REGULATOR) += regulator/
obj-$(CONFIG_RESET_CONTROLLER) += reset/
obj-$(CONFIG_PCI) += pci/
obj-y += rtc/
+obj-$(CONFIG_FIRMWARE) += firmware/
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index e024024616..e0125a1b92 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -383,28 +383,6 @@ const char *dev_id(const struct device_d *dev)
return buf;
}
-int dev_printf(int level, const struct device_d *dev, const char *format, ...)
-{
- va_list args;
- int ret = 0;
-
- if (level > barebox_loglevel)
- return 0;
-
- if (dev->driver && dev->driver->name)
- ret += printf("%s ", dev->driver->name);
-
- ret += printf("%s: ", dev_name(dev));
-
- va_start(args, format);
-
- ret += vprintf(format, args);
-
- va_end(args);
-
- return ret;
-}
-
void devices_shutdown(void)
{
struct device_d *dev;
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index b7f78367d4..9dc43011b9 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -744,6 +744,7 @@ static int mvebu_mbus_init(void)
postcore_initcall(mvebu_mbus_init);
struct mbus_range {
+ const char *compatible;
u32 mbusid;
u32 remap;
struct list_head list;
@@ -752,10 +753,11 @@ struct mbus_range {
#define MBUS_ID(t,a) (((t) << 24) | ((attr) << 16))
static LIST_HEAD(mbus_ranges);
-void mvebu_mbus_add_range(u8 target, u8 attr, u32 remap)
+void mvebu_mbus_add_range(const char *compatible, u8 target, u8 attr, u32 remap)
{
struct mbus_range *r = xzalloc(sizeof(*r));
+ r->compatible = strdup(compatible);
r->mbusid = MBUS_ID(target, attr);
r->remap = remap;
list_add_tail(&r->list, &mbus_ranges);
@@ -811,6 +813,8 @@ static int mvebu_mbus_of_fixup(struct device_node *root, void *context)
continue;
list_for_each_entry(r, &mbus_ranges, list) {
+ if (!of_machine_is_compatible(r->compatible))
+ continue;
if (r->mbusid == mbusid)
ranges[n + na + pa - 1] = r->remap;
}
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
new file mode 100644
index 0000000000..5866063251
--- /dev/null
+++ b/drivers/firmware/Kconfig
@@ -0,0 +1,14 @@
+menu "Firmware Drivers"
+
+config FIRMWARE_ALTERA_SERIAL
+ bool "Altera SPI programming"
+ depends on OFDEVICE
+ select FIRMWARE
+ help
+ Programming an Altera FPGA via a few GPIOs for the control lines and
+ MOSI, MISO and clock from an SPI interface for the data lines
+
+config FIRMWARE_ALTERA_SOCFPGA
+ bool "Altera SoCFPGA fpga loader"
+
+endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
new file mode 100644
index 0000000000..c3a3c34004
--- /dev/null
+++ b/drivers/firmware/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_FIRMWARE_ALTERA_SERIAL) += altera_serial.o
+obj-$(CONFIG_FIRMWARE_ALTERA_SOCFPGA) += socfpga.o
diff --git a/drivers/firmware/altera_serial.c b/drivers/firmware/altera_serial.c
new file mode 100644
index 0000000000..23ba3b00a4
--- /dev/null
+++ b/drivers/firmware/altera_serial.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2013 Juergen Beisert <kernel@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <common.h>
+#include <init.h>
+#include <driver.h>
+#include <firmware.h>
+#include <of_gpio.h>
+#include <xfuncs.h>
+#include <malloc.h>
+#include <gpio.h>
+#include <clock.h>
+#include <spi/spi.h>
+
+#include <fcntl.h>
+#include <fs.h>
+
+/*
+ * Physical requirements:
+ * - three free GPIOs for the signals nCONFIG, CONFIGURE_DONE, nSTATUS
+ * - 32 bit per word, LSB first capable SPI master (MOSI + clock)
+ *
+ * Example how to configure this driver via device tree
+ *
+ * fpga@0 {
+ * compatible = "altr,fpga-passive-serial";
+ * nstat-gpio = <&gpio4 18 0>;
+ * confd-gpio = <&gpio4 19 0>;
+ * nconfig-gpio = <&gpio4 20 0>;
+ * spi-max-frequency = <10000000>;
+ * reg = <0>;
+ * };
+ */
+
+struct fpga_spi {
+ struct firmware_handler fh;
+ int nstat_gpio; /* input GPIO to read the status line */
+ int confd_gpio; /* input GPIO to read the config done line */
+ int nconfig_gpio; /* output GPIO to start the FPGA's config */
+ struct device_d *dev;
+ struct spi_device *spi;
+ bool padding_done;
+};
+
+static int altera_spi_open(struct firmware_handler *fh)
+{
+ struct fpga_spi *this = container_of(fh, struct fpga_spi, fh);
+ struct device_d *dev = this->dev;
+ int ret;
+
+ dev_dbg(dev, "Initiating programming\n");
+
+ /* initiate an FPGA programming */
+ gpio_set_value(this->nconfig_gpio, 0);
+
+ /*
+ * after about 2 µs the FPGA must acknowledge with
+ * STATUS and CONFIG DONE lines at low level
+ */
+ ret = wait_on_timeout(2 * USECOND,
+ (gpio_get_value(this->nstat_gpio) == 0) &&
+ (gpio_get_value(this->confd_gpio) == 0));
+
+ if (ret != 0) {
+ dev_err(dev, "FPGA does not acknowledge the programming initiation\n");
+ if (gpio_get_value(this->nstat_gpio))
+ dev_err(dev, "STATUS is still high!\n");
+ if (gpio_get_value(this->confd_gpio))
+ dev_err(dev, "CONFIG DONE is still high!\n");
+ return ret;
+ }
+
+ /* arm the FPGA to await its new firmware */
+ ret = gpio_set_value(this->nconfig_gpio, 1);
+ if (ret)
+ return ret;
+
+ /* once again, we might need padding the data */
+ this->padding_done = false;
+
+ /*
+ * after about 1506 µs the FPGA must acknowledge this step
+ * with the STATUS line at high level
+ */
+ ret = wait_on_timeout(1600 * USECOND,
+ gpio_get_value(this->nstat_gpio) == 1);
+ if (ret != 0) {
+ dev_err(dev, "FPGA does not acknowledge the programming start\n");
+ return ret;
+ }
+
+ dev_dbg(dev, "Initiating passed\n");
+ /* at the end, wait at least 2 µs prior beginning writing data */
+ udelay(2);
+
+ return 0;
+}
+
+static int altera_spi_write(struct firmware_handler *fh, const void *buf, size_t sz)
+{
+ struct fpga_spi *this = container_of(fh, struct fpga_spi, fh);
+ struct device_d *dev = this->dev;
+ struct spi_transfer t[2];
+ struct spi_message m;
+ u32 dummy;
+ int ret;
+
+ dev_dbg(dev, "Start writing %d bytes.\n", __func__, sz);
+
+ spi_message_init(&m);
+
+ if (sz < sizeof(u32)) {
+ /* simple padding */
+ dummy = 0;
+ memcpy(&dummy, buf, sz);
+ buf = &dummy;
+ sz = sizeof(u32);
+ this->padding_done = true;
+ }
+
+ t[0].tx_buf = buf;
+ t[0].rx_buf = NULL;
+ t[0].len = sz;
+ spi_message_add_tail(&t[0], &m);
+
+ if (sz & 0x3) { /* padding required? */
+ u32 *word_buf = (u32 *)buf;
+ dummy = 0;
+ memcpy(&dummy, &word_buf[sz >> 2], sz & 0x3);
+ t[0].len &= ~0x03;
+ t[1].tx_buf = &dummy;
+ t[1].rx_buf = NULL;
+ t[1].len = sizeof(u32);
+ spi_message_add_tail(&t[1], &m);
+ this->padding_done = true;
+ }
+
+ ret = spi_sync(this->spi, &m);
+ if (ret != 0)
+ dev_err(dev, "programming failure\n");
+
+ return ret;
+}
+
+static int altera_spi_close(struct firmware_handler *fh)
+{
+ struct fpga_spi *this = container_of(fh, struct fpga_spi, fh);
+ struct device_d *dev = this->dev;
+ struct spi_transfer t;
+ struct spi_message m;
+ u32 dummy = 0;
+ int ret;
+
+ dev_dbg(dev, "Finalize programming\n");
+
+ if (this->padding_done == false) {
+ spi_message_init(&m);
+ t.tx_buf = &dummy;
+ t.rx_buf = NULL;
+ t.len = sizeof(dummy);
+ spi_message_add_tail(&t, &m);
+
+ ret = spi_sync(this->spi, &m);
+ if (ret != 0)
+ dev_err(dev, "programming failure\n");
+ }
+
+ /*
+ * when programming was successful,
+ * both status lines should be at high level
+ */
+ ret = wait_on_timeout(10 * USECOND,
+ (gpio_get_value(this->nstat_gpio) == 1) &&
+ (gpio_get_value(this->confd_gpio) == 1));
+ if (ret == 0) {
+ dev_dbg(dev, "Programming successful\n");
+ return ret;
+ }
+
+ dev_err(dev, "Programming failed due to time out\n");
+ if (gpio_get_value(this->nstat_gpio) == 0)
+ dev_err(dev, "STATUS is still low!\n");
+ if (gpio_get_value(this->confd_gpio) == 0)
+ dev_err(dev, "CONFIG DONE is still low!\n");
+
+ return -EIO;
+}
+
+static int altera_spi_of(struct device_d *dev, struct fpga_spi *this)
+{
+ struct device_node *n = dev->device_node;
+ const char *name;
+ int ret;
+
+ name = "nstat-gpio";
+ this->nstat_gpio = of_get_named_gpio(n, name, 0);
+ if (this->nstat_gpio < 0) {
+ ret = this->nstat_gpio;
+ goto out;
+ }
+
+ name = "confd-gpio";
+ this->confd_gpio = of_get_named_gpio(n, name, 0);
+ if (this->confd_gpio < 0) {
+ ret = this->confd_gpio;
+ goto out;
+ }
+
+ name = "nconfig-gpio";
+ this->nconfig_gpio = of_get_named_gpio(n, name, 0);
+ if (this->nconfig_gpio < 0) {
+ ret = this->nconfig_gpio;
+ goto out;
+ }
+
+ /* init to passive and sane values */
+ ret = gpio_direction_output(this->nconfig_gpio, 1);
+ if (ret)
+ return ret;
+ ret = gpio_direction_input(this->nstat_gpio);
+ if (ret)
+ return ret;
+ ret = gpio_direction_input(this->confd_gpio);
+ if (ret)
+ return ret;
+
+ return 0;
+
+out:
+ dev_err(dev, "Cannot request \"%s\" gpio: %s\n", name, strerror(-ret));
+
+ return ret;
+}
+
+static void altera_spi_init_mode(struct spi_device *spi)
+{
+ spi->bits_per_word = 32;
+ /*
+ * CPHA = CPOL = 0
+ * the FPGA expects its firmware data with LSB first
+ */
+ spi->mode = SPI_MODE_0 | SPI_LSB_FIRST;
+}
+
+static int altera_spi_probe(struct device_d *dev)
+{
+ int rc;
+ struct fpga_spi *this;
+ struct firmware_handler *fh;
+ const char *alias = of_alias_get(dev->device_node);
+ const char *model = NULL;
+
+ dev_dbg(dev, "Probing FPGA firmware programmer\n");
+
+ this = xzalloc(sizeof(*this));
+ fh = &this->fh;
+
+ rc = altera_spi_of(dev, this);
+ if (rc != 0)
+ goto out;
+
+ if (alias)
+ fh->id = xstrdup(alias);
+ else
+ fh->id = xstrdup("altera-fpga");
+
+ fh->open = altera_spi_open;
+ fh->write = altera_spi_write;
+ fh->close = altera_spi_close;
+ of_property_read_string(dev->device_node, "compatible", &model);
+ if (model)
+ fh->model = xstrdup(model);
+ fh->dev = dev;
+
+ this->spi = (struct spi_device *)dev->type_data;
+ altera_spi_init_mode(this->spi);
+ this->dev = dev;
+
+ dev_dbg(dev, "Registering FPGA firmware programmer\n");
+ rc = firmwaremgr_register(fh);
+ if (rc != 0) {
+ free(this);
+ goto out;
+ }
+
+ return 0;
+out:
+ free(fh->id);
+ free(this);
+
+ return rc;
+}
+
+static struct of_device_id altera_spi_id_table[] = {
+ {
+ .compatible = "altr,passive-serial",
+ },
+};
+
+static struct driver_d altera_spi_driver = {
+ .name = "altera-fpga",
+ .of_compatible = DRV_OF_COMPAT(altera_spi_id_table),
+ .probe = altera_spi_probe,
+};
+device_spi_driver(altera_spi_driver);
diff --git a/drivers/firmware/socfpga.c b/drivers/firmware/socfpga.c
new file mode 100644
index 0000000000..a5dc6072aa
--- /dev/null
+++ b/drivers/firmware/socfpga.c
@@ -0,0 +1,440 @@
+/*
+ *
+ * Copyright (C) 2012 Altera Corporation <www.altera.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Altera Corporation nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL ALTERA CORPORATION BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <firmware.h>
+#include <command.h>
+#include <common.h>
+#include <malloc.h>
+#include <clock.h>
+#include <fcntl.h>
+#include <init.h>
+#include <io.h>
+#include <mach/system-manager.h>
+#include <mach/reset-manager.h>
+#include <mach/socfpga-regs.h>
+#include <mach/sdram.h>
+
+#define FPGAMGRREGS_STAT 0x0
+#define FPGAMGRREGS_CTRL 0x4
+#define FPGAMGRREGS_DCLKCNT 0x8
+#define FPGAMGRREGS_DCLKSTAT 0xc
+
+#define FPGAMGRREGS_MON_GPIO_PORTA_EOI_ADDRESS 0x84c
+#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_ADDRESS 0x850
+
+#define FPGAMGRREGS_CTRL_CFGWDTH_MASK 0x200
+#define FPGAMGRREGS_CTRL_AXICFGEN_MASK 0x100
+#define FPGAMGRREGS_CTRL_NCONFIGPULL_MASK 0x4
+#define FPGAMGRREGS_CTRL_NCE_MASK 0x2
+#define FPGAMGRREGS_CTRL_EN_MASK 0x1
+#define FPGAMGRREGS_CTRL_CDRATIO_LSB 6
+
+#define FPGAMGRREGS_STAT_MODE_MASK 0x7
+#define FPGAMGRREGS_STAT_MSEL_MASK 0xf8
+#define FPGAMGRREGS_STAT_MSEL_LSB 3
+
+#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_CRC_MASK 0x8
+#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_ID_MASK 0x4
+#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK 0x2
+#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK 0x1
+
+/* FPGA Mode */
+#define FPGAMGRREGS_MODE_FPGAOFF 0x0
+#define FPGAMGRREGS_MODE_RESETPHASE 0x1
+#define FPGAMGRREGS_MODE_CFGPHASE 0x2
+#define FPGAMGRREGS_MODE_INITPHASE 0x3
+#define FPGAMGRREGS_MODE_USERMODE 0x4
+#define FPGAMGRREGS_MODE_UNKNOWN 0x5
+
+/* FPGA CD Ratio Value */
+#define CDRATIO_x1 0x0
+#define CDRATIO_x2 0x1
+#define CDRATIO_x4 0x2
+#define CDRATIO_x8 0x3
+
+struct fpgamgr {
+ struct firmware_handler fh;
+ struct device_d *dev;
+ void __iomem *regs;
+ void __iomem *regs_data;
+};
+
+/* Get the FPGA mode */
+static uint32_t fpgamgr_get_mode(struct fpgamgr *mgr)
+{
+ return readl(mgr->regs + FPGAMGRREGS_STAT) & FPGAMGRREGS_STAT_MODE_MASK;
+}
+
+static int fpgamgr_dclkcnt_set(struct fpgamgr *mgr, unsigned long cnt)
+{
+ uint64_t start;
+
+ /* clear any existing done status */
+ if (readl(mgr->regs + FPGAMGRREGS_DCLKSTAT))
+ writel(0x1, mgr->regs + FPGAMGRREGS_DCLKSTAT);
+
+ writel(cnt, mgr->regs + FPGAMGRREGS_DCLKCNT);
+
+ /* wait till the dclkcnt done */
+ start = get_time_ns();
+ while (1) {
+ if (readl(mgr->regs + FPGAMGRREGS_DCLKSTAT)) {
+ writel(0x1, mgr->regs + FPGAMGRREGS_DCLKSTAT);
+ return 0;
+ }
+
+ if (is_timeout(start, 100 * MSECOND))
+ return -ETIMEDOUT;
+ }
+}
+
+/* Start the FPGA programming by initialize the FPGA Manager */
+static int fpgamgr_program_init(struct fpgamgr *mgr)
+{
+ unsigned long reg;
+ uint32_t ctrl = 0, ratio;
+ uint64_t start;
+
+ /* get the MSEL value */
+ reg = readl(mgr->regs + FPGAMGRREGS_STAT);
+ reg = ((reg & FPGAMGRREGS_STAT_MSEL_MASK) >> FPGAMGRREGS_STAT_MSEL_LSB);
+
+ if (reg & 0x8)
+ ctrl |= FPGAMGRREGS_CTRL_CFGWDTH_MASK;
+ else
+ ctrl &= ~FPGAMGRREGS_CTRL_CFGWDTH_MASK;
+
+ switch (reg & 0xb) {
+ case 0xa:
+ ratio = CDRATIO_x8;
+ break;
+ case 0x2:
+ case 0x9:
+ ratio = CDRATIO_x4;
+ break;
+ case 0x1:
+ ratio = CDRATIO_x2;
+ break;
+ case 0x8:
+ case 0xb:
+ default:
+ ratio = CDRATIO_x1;
+ break;
+ }
+
+ ctrl |= ratio << FPGAMGRREGS_CTRL_CDRATIO_LSB;
+
+ /* clear nce bit to allow HPS configuration */
+ ctrl &= ~FPGAMGRREGS_CTRL_NCE_MASK;
+
+ /* to enable FPGA Manager drive over configuration line */
+ ctrl |= FPGAMGRREGS_CTRL_EN_MASK;
+
+ /* put FPGA into reset phase */
+ ctrl |= FPGAMGRREGS_CTRL_NCONFIGPULL_MASK;
+
+ writel(ctrl, mgr->regs + FPGAMGRREGS_CTRL);
+
+ /* (1) wait until FPGA enter reset phase */
+ start = get_time_ns();
+ while (1) {
+ if (fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_RESETPHASE)
+ break;
+ if (is_timeout(start, 100 * MSECOND))
+ return -ETIMEDOUT;
+ }
+
+ /* release FPGA from reset phase */
+ ctrl = readl(mgr->regs + FPGAMGRREGS_CTRL);
+ ctrl &= ~FPGAMGRREGS_CTRL_NCONFIGPULL_MASK;
+ writel(ctrl, mgr->regs + FPGAMGRREGS_CTRL);
+
+ /* (2) wait until FPGA enter configuration phase */
+ start = get_time_ns();
+ while (1) {
+ if (fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_CFGPHASE)
+ break;
+ if (is_timeout(start, 100 * MSECOND))
+ return -ETIMEDOUT;
+ }
+
+ /* clear all interrupt in CB Monitor */
+ writel(0xFFF, (mgr->regs + FPGAMGRREGS_MON_GPIO_PORTA_EOI_ADDRESS));
+
+ /* enable AXI configuration */
+ ctrl = readl(mgr->regs + FPGAMGRREGS_CTRL);
+ ctrl |= FPGAMGRREGS_CTRL_AXICFGEN_MASK;
+ writel(ctrl, mgr->regs + FPGAMGRREGS_CTRL);
+
+ return 0;
+}
+
+/* Ensure the FPGA entering config done */
+static int fpgamgr_program_poll_cd(struct fpgamgr *mgr)
+{
+ unsigned long reg;
+ uint32_t val;
+ uint64_t start;
+
+ /* (3) wait until full config done */
+ start = get_time_ns();
+ while (1) {
+ reg = readl(mgr->regs + FPGAMGRREGS_MON_GPIO_EXT_PORTA_ADDRESS);
+
+ /* config error */
+ if (!(reg & FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK) &&
+ !(reg & FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK))
+ return -EIO;
+
+ /* config done without error */
+ if ((reg & FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK) &&
+ (reg & FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK))
+ break;
+
+ if (is_timeout(start, 100 * MSECOND))
+ return -ETIMEDOUT;
+ }
+
+ /* disable AXI configuration */
+ val = readl(mgr->regs + FPGAMGRREGS_CTRL);
+ val &= ~FPGAMGRREGS_CTRL_AXICFGEN_MASK;
+ writel(val, mgr->regs + FPGAMGRREGS_CTRL);
+
+ return 0;
+}
+
+/* Ensure the FPGA entering init phase */
+static int fpgamgr_program_poll_initphase(struct fpgamgr *mgr)
+{
+ uint64_t start;
+
+ /* additional clocks for the CB to enter initialization phase */
+ if (fpgamgr_dclkcnt_set(mgr, 0x4) != 0)
+ return -5;
+
+ /* (4) wait until FPGA enter init phase or user mode */
+ start = get_time_ns();
+ while (1) {
+ int mode = fpgamgr_get_mode(mgr);
+
+ if (mode == FPGAMGRREGS_MODE_INITPHASE ||
+ mode == FPGAMGRREGS_MODE_USERMODE)
+ break;
+
+ if (is_timeout(start, 100 * MSECOND))
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+/* Ensure the FPGA entering user mode */
+static int fpgamgr_program_poll_usermode(struct fpgamgr *mgr)
+{
+ uint32_t val;
+ uint64_t start;
+
+ /* additional clocks for the CB to exit initialization phase */
+ if (fpgamgr_dclkcnt_set(mgr, 0x5000) != 0)
+ return -7;
+
+ /* (5) wait until FPGA enter user mode */
+ start = get_time_ns();
+ while (1) {
+ if (fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_USERMODE)
+ break;
+ if (is_timeout(start, 100 * MSECOND))
+ return -ETIMEDOUT;
+ }
+
+ /* to release FPGA Manager drive over configuration line */
+ val = readl(mgr->regs + FPGAMGRREGS_CTRL);
+ val &= ~FPGAMGRREGS_CTRL_EN_MASK;
+ writel(val, mgr->regs + FPGAMGRREGS_CTRL);
+
+ return 0;
+}
+
+/*
+ * Using FPGA Manager to program the FPGA
+ * Return 0 for sucess
+ */
+static int fpgamgr_program_start(struct firmware_handler *fh)
+{
+ struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
+ int status;
+
+ /* prior programming the FPGA, all bridges need to be shut off */
+
+ /* disable all signals from hps peripheral controller to fpga */
+ writel(0, SYSMGR_FPGAINTF_MODULE);
+
+ /* disable all signals from fpga to hps sdram */
+ writel(0, (CYCLONE5_SDR_ADDRESS + SDR_CTRLGRP_FPGAPORTRST_ADDRESS));
+
+ /* disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */
+ writel(~0, CYCLONE5_RSTMGR_ADDRESS + RESET_MGR_BRG_MOD_RESET_OFS);
+
+ /* unmap the bridges from NIC-301 */
+ writel(0x1, CYCLONE5_L3REGS_ADDRESS);
+
+ dev_dbg(mgr->dev, "start programming...\n");
+
+ /* initialize the FPGA Manager */
+ status = fpgamgr_program_init(mgr);
+ if (status) {
+ dev_err(mgr->dev, "program init failed with: %s\n",
+ strerror(-status));
+ return status;
+ }
+
+ return 0;
+}
+
+/* Write the RBF data to FPGA Manager */
+static int fpgamgr_program_write_buf(struct firmware_handler *fh, const void *buf,
+ size_t size)
+{
+ struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
+ const uint32_t *buf32 = buf;
+
+ /* write to FPGA Manager AXI data */
+ while (size) {
+ writel(*buf32, mgr->regs_data);
+ readl(mgr->regs + FPGAMGRREGS_MON_GPIO_EXT_PORTA_ADDRESS);
+ buf32++;
+ size -= sizeof(uint32_t);
+ }
+
+ return 0;
+}
+
+static int fpgamgr_program_finish(struct firmware_handler *fh)
+{
+ struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
+ int status;
+
+ /* Ensure the FPGA entering config done */
+ status = fpgamgr_program_poll_cd(mgr);
+ if (status) {
+ dev_err(mgr->dev, "poll for config done failed with: %s\n",
+ strerror(-status));
+ return status;
+ }
+
+ dev_dbg(mgr->dev, "waiting for init phase...\n");
+
+ /* Ensure the FPGA entering init phase */
+ status = fpgamgr_program_poll_initphase(mgr);
+ if (status) {
+ dev_err(mgr->dev, "poll for init phase failed with: %s\n",
+ strerror(-status));
+ return status;
+ }
+
+ dev_dbg(mgr->dev, "waiting for user mode...\n");
+
+ /* Ensure the FPGA entering user mode */
+ status = fpgamgr_program_poll_usermode(mgr);
+ if (status) {
+ dev_err(mgr->dev, "poll for user mode with: %s\n",
+ strerror(-status));
+ return status;
+ }
+
+ return 0;
+}
+
+static int fpgamgr_probe(struct device_d *dev)
+{
+ struct fpgamgr *mgr;
+ struct firmware_handler *fh;
+ const char *alias = of_alias_get(dev->device_node);
+ const char *model = NULL;
+ int ret;
+
+ dev_dbg(dev, "Probing FPGA firmware programmer\n");
+
+ mgr = xzalloc(sizeof(*mgr));
+ fh = &mgr->fh;
+
+ mgr->regs = dev_request_mem_region(dev, 0);
+ if (!mgr->regs) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ mgr->regs_data = dev_request_mem_region(dev, 1);
+ if (!mgr->regs_data) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (alias)
+ fh->id = xstrdup(alias);
+ else
+ fh->id = xstrdup("socfpga-fpga");
+
+ fh->open = fpgamgr_program_start;
+ fh->write = fpgamgr_program_write_buf;
+ fh->close = fpgamgr_program_finish;
+ of_property_read_string(dev->device_node, "compatible", &model);
+ if (model)
+ fh->model = xstrdup(model);
+ fh->dev = dev;
+
+ mgr->dev = dev;
+
+ dev_dbg(dev, "Registering FPGA firmware programmer\n");
+
+ ret = firmwaremgr_register(fh);
+ if (ret != 0) {
+ free(mgr);
+ goto out;
+ }
+
+ return 0;
+out:
+ free(fh->id);
+ free(mgr);
+
+ return ret;
+}
+
+static struct of_device_id fpgamgr_id_table[] = {
+ {
+ .compatible = "altr,socfpga-fpga-mgr",
+ },
+};
+
+static struct driver_d fpgamgr_driver = {
+ .name = "socfpa-fpgamgr",
+ .of_compatible = DRV_OF_COMPAT(fpgamgr_id_table),
+ .probe = fpgamgr_probe,
+};
+device_platform_driver(fpgamgr_driver);
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index 399f6a94be..deb4ea4f3b 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -174,24 +174,32 @@ static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
static int at91_twi_wait_completion(struct at91_twi_dev *dev)
{
uint64_t start = get_time_ns();
- unsigned int status = at91_twi_read(dev, AT91_TWI_SR);
- unsigned int irqstatus = at91_twi_read(dev, AT91_TWI_IMR);
+ unsigned int status;
+ unsigned int irqstatus;
+
+ do {
+ status = at91_twi_read(dev, AT91_TWI_SR);
+ irqstatus = at91_twi_read(dev, AT91_TWI_IMR);
+
+ if (!(status & irqstatus)) {
+ if (is_timeout(start, AT91_I2C_TIMEOUT)) {
+ dev_warn(&dev->adapter.dev, "timeout waiting for bus ready\n");
+ return -ETIMEDOUT;
+ } else {
+ continue;
+ }
+ }
- if (irqstatus & AT91_TWI_RXRDY)
- at91_twi_read_next_byte(dev);
- else if (irqstatus & AT91_TWI_TXRDY)
- at91_twi_write_next_byte(dev);
- else
- dev_warn(&dev->adapter.dev, "neither rx and tx are ready\n");
+ if (irqstatus & AT91_TWI_RXRDY)
+ at91_twi_read_next_byte(dev);
+ else if (irqstatus & AT91_TWI_TXRDY)
+ at91_twi_write_next_byte(dev);
+ else
+ dev_warn(&dev->adapter.dev, "neither rx and tx are ready\n");
- dev->transfer_status |= status;
+ dev->transfer_status |= status;
- while(!(at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_TXCOMP)) {
- if(is_timeout(start, AT91_I2C_TIMEOUT)) {
- dev_warn(&dev->adapter.dev, "timeout waiting for bus ready\n");
- return -ETIMEDOUT;
- }
- }
+ } while (!(at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_TXCOMP));
at91_disable_twi_interrupts(dev);
@@ -346,23 +354,56 @@ static struct at91_twi_pdata at91sam9g10_config = {
.has_unre_flag = false,
};
+static struct at91_twi_pdata at91sam9x5_config = {
+ .clk_max_div = 7,
+ .clk_offset = 4,
+ .has_unre_flag = false,
+};
+
static struct platform_device_id at91_twi_devtypes[] = {
{
- .name = "i2c-at91rm9200",
+ .name = "at91rm9200-i2c",
.driver_data = (unsigned long) &at91rm9200_config,
}, {
- .name = "i2c-at91sam9261",
+ .name = "at91sam9261-i2c",
.driver_data = (unsigned long) &at91sam9261_config,
}, {
- .name = "i2c-at91sam9260",
+ .name = "at91sam9260-i2c",
.driver_data = (unsigned long) &at91sam9260_config,
}, {
- .name = "i2c-at91sam9g20",
+ .name = "at91sam9g20-i2c",
.driver_data = (unsigned long) &at91sam9g20_config,
}, {
- .name = "i2c-at91sam9g10",
+ .name = "at91sam9g10-i2c",
.driver_data = (unsigned long) &at91sam9g10_config,
}, {
+ .name = "at91sam9x5-i2c",
+ .driver_data = (unsigned long) &at91sam9x5_config,
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct of_device_id at91_twi_dt_ids[] = {
+ {
+ .compatible = "atmel,at91rm9200-i2c",
+ .data = (unsigned long) &at91rm9200_config,
+ } , {
+ .compatible = "atmel,at91sam9260-i2c",
+ .data = (unsigned long) &at91sam9260_config,
+ } , {
+ .compatible = "atmel,at91sam9261-i2c",
+ .data = (unsigned long) &at91sam9261_config,
+ } , {
+ .compatible = "atmel,at91sam9g20-i2c",
+ .data = (unsigned long) &at91sam9g20_config,
+ } , {
+ .compatible = "atmel,at91sam9g10-i2c",
+ .data = (unsigned long) &at91sam9g10_config,
+ }, {
+ .compatible = "atmel,at91sam9x5-i2c",
+ .data = (unsigned long) &at91sam9x5_config,
+ }, {
/* sentinel */
}
};
@@ -371,14 +412,16 @@ static int at91_twi_probe(struct device_d *dev)
{
struct at91_twi_dev *i2c_at91;
struct at91_twi_pdata *i2c_data;
- int rc;
+ int rc = 0;
u32 bus_clk_rate;
i2c_at91 = xzalloc(sizeof(struct at91_twi_dev));
rc = dev_get_drvdata(dev, (unsigned long *)&i2c_data);
- if (rc)
+ if (rc < 0) {
+ dev_err(dev, "failed to retrieve driver data\n");
goto out_free;
+ }
i2c_at91->pdata = i2c_data;
@@ -389,7 +432,7 @@ static int at91_twi_probe(struct device_d *dev)
goto out_free;
}
- i2c_at91->clk = clk_get(dev, "twi_clk");
+ i2c_at91->clk = clk_get(dev, NULL);
if (IS_ERR(i2c_at91->clk)) {
dev_err(dev, "no clock defined\n");
rc = -ENODEV;
@@ -418,17 +461,18 @@ static int at91_twi_probe(struct device_d *dev)
return 0;
out_adap_fail:
- clk_disable(i2c_at91->clk);
- clk_put(i2c_at91->clk);
+ clk_disable(i2c_at91->clk);
+ clk_put(i2c_at91->clk);
out_free:
- kfree(i2c_at91);
- return rc;
+ kfree(i2c_at91);
+ return rc;
}
static struct driver_d at91_twi_driver = {
.name = "at91-twi",
.probe = at91_twi_probe,
.id_table = at91_twi_devtypes,
+ .of_compatible = DRV_OF_COMPAT(at91_twi_dt_ids),
};
device_platform_driver(at91_twi_driver);
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 0d714cc940..094f5916cf 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -151,7 +151,6 @@ struct omap_i2c_struct {
u8 reg_shift;
struct omap_i2c_driver_data *data;
struct resource *ioarea;
- u32 fclk_rate;
u32 speed; /* Speed of bus in Khz */
u16 scheme;
u16 cmd_err;
@@ -421,7 +420,7 @@ static int omap_i2c_init(struct omap_i2c_struct *i2c_omap)
internal_clk = 4000;
/* Compute prescaler divisor */
- psc = i2c_omap->fclk_rate / internal_clk;
+ psc = i2c_data->fclk_rate / internal_clk;
psc = psc - 1;
/* If configured for High Speed */
@@ -1016,9 +1015,16 @@ i2c_omap_probe(struct device_d *pdev)
i2c_omap->reg_shift = (i2c_data->flags >>
OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3;
- if (pdev->platform_data != NULL)
+ if (pdev->platform_data != NULL) {
speed = *(u32 *)pdev->platform_data;
- else
+ } else {
+ of_property_read_u32(pdev->device_node, "clock-frequency",
+ &speed);
+ /* convert DT freq value in Hz into kHz for speed */
+ speed /= 1000;
+ }
+
+ if (!speed)
speed = 100; /* Default speed */
i2c_omap->speed = speed;
@@ -1082,12 +1088,6 @@ i2c_omap_probe(struct device_d *pdev)
i2c_omap->b_hw = 1; /* Enable hardware fixes */
}
- i2c_omap->fclk_rate = i2c_data->fclk_rate;
-
- if (!i2c_omap->fclk_rate)
- of_property_read_u32(pdev->device_node, "clock-frequency",
- &i2c_omap->fclk_rate);
-
/* reset ASAP, clearing any IRQs */
omap_i2c_init(i2c_omap);
diff --git a/drivers/input/imx_keypad.c b/drivers/input/imx_keypad.c
index c67deb8d49..331eadd75f 100644
--- a/drivers/input/imx_keypad.c
+++ b/drivers/input/imx_keypad.c
@@ -391,7 +391,7 @@ static int __init imx_keypad_probe(struct device_d *dev)
struct imx_keypad *keypad;
const struct matrix_keymap_data *keymap_data = dev->platform_data;
struct console_device *cdev;
- int error, i;
+ int i;
if (!keymap_data) {
pr_err("no keymap defined\n");
diff --git a/drivers/mci/atmel_mci.c b/drivers/mci/atmel_mci.c
index 63d2475da7..10e769ea13 100644
--- a/drivers/mci/atmel_mci.c
+++ b/drivers/mci/atmel_mci.c
@@ -511,6 +511,7 @@ static void atmci_get_cap(struct atmel_mci *host)
host->caps.need_reset_after_xfer = 1;
switch (version & 0xf00) {
+ case 0x600:
case 0x500:
host->caps.has_odd_clk_div = 1;
case 0x400:
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 61278a235d..7f9c306258 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -58,4 +58,9 @@ config MTD_DOCG3
M-Systems and now Sandisk. The support is very experimental,
and doesn't give access to any write operations.
+config MTD_MTDRAM
+ tristate "Support for NVRAM devices (FRAM, MRAM, ...)"
+ help
+ This enables non volatile RAM to used as MTD devices.
+
endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index bf1f8a9f15..bc1960e1b2 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
obj-$(CONFIG_MTD_DOCG3) += docg3.o
obj-$(CONFIG_MTD_M25P80) += m25p80.o
+obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c
new file mode 100644
index 0000000000..d1eaafdab5
--- /dev/null
+++ b/drivers/mtd/devices/mtdram.c
@@ -0,0 +1,122 @@
+/*
+ * Author: Sebastian Block <basti@linux-source.de>
+ * Copyright (c) 2014
+ *
+ * Some parts are based on mtdram.c found in Linux kernel
+ * by Alexander Larsson <alex@cendio.se>
+ * and Joern Engel <joern@wh.fh-wedel.de>.
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <common.h>
+#include <environment.h>
+#include <errno.h>
+#include <init.h>
+#include <io.h>
+#include <linux/mtd/mtd.h>
+#include <malloc.h>
+#include <of.h>
+
+struct mtdram_priv_data {
+ struct mtd_info mtd;
+ void *base;
+};
+
+static int ram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
+ instr->state = MTD_ERASE_DONE;
+ mtd_erase_callback(instr);
+ return 0;
+}
+
+static int ram_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
+{
+ memcpy((char*)mtd->priv + to, buf, len);
+ *retlen = len;
+ return 0;
+}
+
+static int ram_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
+{
+ memcpy(buf, mtd->priv + from, len);
+ *retlen = len;
+ return 0;
+}
+
+static int mtdram_probe(struct device_d *dev)
+{
+ void __iomem *base;
+ int device_id;
+ struct mtd_info *mtd;
+ struct resource *res;
+ loff_t size;
+ int ret = 0;
+
+ mtd = xzalloc(sizeof(struct mtd_info));
+
+ device_id = DEVICE_ID_SINGLE;
+ if (dev->device_node) {
+ const char *alias = of_alias_get(dev->device_node);
+ if (alias)
+ mtd->name = xstrdup(alias);
+ }
+
+ if (!mtd->name) {
+ device_id = DEVICE_ID_DYNAMIC;
+ mtd->name = "mtdram";
+ }
+
+ base = dev_request_mem_region(dev, 0);
+ if (!base) {
+ ret = -EBUSY;
+ goto nobase;
+ }
+
+ res = dev_get_resource(dev, IORESOURCE_MEM, 0);
+ size = (unsigned long) resource_size(res);
+ mtd->priv = base;
+
+ mtd->type = MTD_RAM;
+ mtd->writesize = 1;
+ mtd->writebufsize = 64;
+ mtd->flags = MTD_CAP_RAM;
+ mtd->size = size;
+
+ mtd->read = ram_read;
+ mtd->write = ram_write;
+ mtd->erase = ram_erase;
+ mtd->erasesize = 1;
+
+ mtd->parent = dev;
+
+ ret = add_mtd_device(mtd, mtd->name, device_id);
+ return ret;
+
+nobase:
+ kfree(mtd);
+
+ return ret;
+}
+
+static __maybe_unused struct of_device_id mtdram_dt_ids[] = {
+ {
+ .compatible = "mtd-ram",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d mtdram_driver = {
+ .name = "mtdram",
+ .probe = mtdram_probe,
+ .of_compatible = DRV_OF_COMPAT(mtdram_dt_ids),
+};
+device_platform_driver(mtdram_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sebastian Block");
+MODULE_DESCRIPTION("MTD RAM driver for NVRAMs");
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index ccf1f9c110..c345847d8f 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -93,7 +93,7 @@ config NAND_OMAP_GPMC
config NAND_ORION
bool
prompt "Orion NAND driver"
- depends on ARCH_MVEBU
+ depends on ARCH_KIRKWOOD
help
Support for the Orion NAND controller, present in Kirkwood SoCs.
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 524606a407..4ddabda572 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -767,12 +767,105 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd)
pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE);
}
+static uint16_t *pmecc_galois_table;
+static int pmecc_build_galois_table(unsigned int mm, int16_t *index_of,
+ int16_t *alpha_to)
+{
+ unsigned int i, mask, nn;
+ unsigned int p[15];
+
+ nn = (1 << mm) - 1;
+ /* set default value */
+ for (i = 1; i < mm; i++)
+ p[i] = 0;
+
+ /* 1 + X^mm */
+ p[0] = 1;
+ p[mm] = 1;
+
+ /* others */
+ switch (mm) {
+ case 3:
+ case 4:
+ case 6:
+ case 15:
+ p[1] = 1;
+ break;
+ case 5:
+ case 11:
+ p[2] = 1;
+ break;
+ case 7:
+ case 10:
+ p[3] = 1;
+ break;
+ case 8:
+ p[2] = p[3] = p[4] = 1;
+ break;
+ case 9:
+ p[4] = 1;
+ break;
+ case 12:
+ p[1] = p[4] = p[6] = 1;
+ break;
+ case 13:
+ p[1] = p[3] = p[4] = 1;
+ break;
+ case 14:
+ p[1] = p[6] = p[10] = 1;
+ break;
+ default:
+ /* Error */
+ return -EINVAL;
+ }
+
+ /* Build alpha ^ mm it will help to generate the field (primitiv) */
+ alpha_to[mm] = 0;
+ for (i = 0; i < mm; i++)
+ if (p[i])
+ alpha_to[mm] |= 1 << i;
+
+ /*
+ * Then build elements from 0 to mm - 1. As degree is less than mm
+ * so it is just a logical shift.
+ */
+ mask = 1;
+ for (i = 0; i < mm; i++) {
+ alpha_to[i] = mask;
+ index_of[alpha_to[i]] = i;
+ mask <<= 1;
+ }
+
+ index_of[alpha_to[mm]] = mm;
+
+ /* use a mask to select the MSB bit of the LFSR */
+ mask >>= 1;
+
+ /* then finish the building */
+ for (i = mm + 1; i <= nn; i++) {
+ /* check if the msb bit of the lfsr is set */
+ if (alpha_to[i - 1] & mask)
+ alpha_to[i] = alpha_to[mm] ^
+ ((alpha_to[i - 1] ^ mask) << 1);
+ else
+ alpha_to[i] = alpha_to[i - 1] << 1;
+
+ index_of[alpha_to[i]] = i % nn;
+ }
+
+ /* index of 0 is undefined in a multiplicative field */
+ index_of[0] = -1;
+
+ return 0;
+}
+
static int __init atmel_pmecc_nand_init_params(struct device_d *dev,
struct atmel_nand_host *host)
{
struct mtd_info *mtd = &host->mtd;
struct nand_chip *nand_chip = &host->nand_chip;
int cap, sector_size, err_no;
+ int ret;
cap = host->board->pmecc_corr_cap;
sector_size = host->board->pmecc_sector_size;
@@ -786,14 +879,34 @@ static int __init atmel_pmecc_nand_init_params(struct device_d *dev,
}
host->pmerrloc_base = dev_request_mem_region(dev, 2);
- host->pmecc_rom_base = dev_request_mem_region(dev, 3);
-
- if (!host->pmerrloc_base || !host->pmecc_rom_base) {
+ if (!host->pmerrloc_base) {
dev_err(host->dev,
- "Can not get I/O resource for PMECC ERRLOC controller or ROM!\n");
+ "Can not get I/O resource for PMECC ERRLOC controller!\n");
return -EIO;
}
+ host->pmecc_rom_base = dev_request_mem_region(dev, 3);
+ if (!host->pmecc_rom_base) {
+ /* Set pmecc_rom_base as the begin of gf table */
+ int size = sector_size == 512 ? 0x2000 : 0x4000;
+ pmecc_galois_table = xzalloc(2 * size * sizeof(uint16_t));
+ if (!pmecc_galois_table)
+ return -ENOMEM;
+ host->pmecc_rom_base = pmecc_galois_table;
+ ret = pmecc_build_galois_table((sector_size == 512) ?
+ PMECC_GF_DIMENSION_13 :
+ PMECC_GF_DIMENSION_14,
+ host->pmecc_rom_base,
+ host->pmecc_rom_base + (size * sizeof(int16_t)));
+ if (ret) {
+ dev_err(host->dev,
+ "Can not get I/O resource for ROM!\n");
+ return -EIO;
+ }
+
+ host->board->pmecc_lookup_table_offset = 0;
+ }
+
/* ECC is calculated for the whole page (1 step) */
nand_chip->ecc.size = mtd->writesize;
diff --git a/drivers/mtd/nor/cfi_flash.c b/drivers/mtd/nor/cfi_flash.c
index a494063922..0fa41bf67b 100644
--- a/drivers/mtd/nor/cfi_flash.c
+++ b/drivers/mtd/nor/cfi_flash.c
@@ -1000,8 +1000,8 @@ static int cfi_probe (struct device_d *dev)
return -ENODEV;
}
- dev_info(dev, "found cfi flash at %p, size %ld\n",
- info->base, info->size);
+ dev_info(dev, "found cfi flash at 0x%p, size %s\n",
+ info->base, size_human_readable(info->size));
dev->info = cfi_info;
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 59e8f01e0b..7c52a09eaa 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -568,8 +568,14 @@ static int ethoc_probe(struct device_d *dev)
return 0;
}
+static struct of_device_id ethoc_dt_ids[] = {
+ { .compatible = "opencores,ethoc", },
+ { }
+};
+
static struct driver_d ethoc_driver = {
.name = "ethoc",
.probe = ethoc_probe,
+ .of_compatible = DRV_OF_COMPAT(ethoc_dt_ids),
};
device_platform_driver(ethoc_driver);
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 03558af8f1..8e67aecc84 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -304,7 +304,6 @@ static void macb_configure_dma(struct macb_device *bp)
if (macb_is_gem(bp)) {
dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
dmacfg |= GEM_BF(RXBS, bp->rx_buffer_size / RX_BUFFER_MULTIPLE);
- dmacfg |= GEM_BF(FBLDO, 16);
dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
dmacfg |= GEM_BIT(DDRP);
dmacfg &= ~GEM_BIT(ENDIA);
@@ -352,7 +351,10 @@ static void macb_init(struct macb_device *macb)
break;
case PHY_INTERFACE_MODE_RMII:
if (IS_ENABLED(CONFIG_ARCH_AT91))
- val = MACB_BIT(RMII) | MACB_BIT(CLKEN);
+ if (macb_is_gem(macb))
+ val = GEM_BIT(RGMII);
+ else
+ val = MACB_BIT(RMII) | MACB_BIT(CLKEN);
else
val = 0;
break;
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 34f852e065..f2bc64925d 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -10,22 +10,7 @@
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <linux/smscphy.h>
-
-/* Known PHY IDs */
-#define MARVELL_PHY_ID_88E1101 0x01410c60
-#define MARVELL_PHY_ID_88E1112 0x01410c90
-#define MARVELL_PHY_ID_88E1111 0x01410cc0
-#define MARVELL_PHY_ID_88E1118 0x01410e10
-#define MARVELL_PHY_ID_88E1121R 0x01410cb0
-#define MARVELL_PHY_ID_88E1145 0x01410cd0
-#define MARVELL_PHY_ID_88E1149R 0x01410e50
-#define MARVELL_PHY_ID_88E1240 0x01410e30
-#define MARVELL_PHY_ID_88E1318S 0x01410e90
-#define MARVELL_PHY_ID_88E1116R 0x01410e40
-#define MARVELL_PHY_ID_88E1510 0x01410dd0
-
-/* Mask used for ID comparisons */
-#define MARVELL_PHY_ID_MASK 0xfffffff0
+#include <linux/marvell_phy.h>
/* Marvell Register Page register */
#define MII_MARVELL_PHY_PAGE 22
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 8aea6534b8..88c64e59a0 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -254,11 +254,11 @@ static struct phy_driver ksphy_driver[] = {
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
}, {
+ /* I saw the same issue like PHY_ID_KSZ9021 for Asym_Pause */
.phy_id = PHY_ID_KSZ9031,
.phy_id_mask = 0x00fffff0,
.drv.name = "Micrel KSZ9031 Gigabit PHY",
- .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause
- | SUPPORTED_Asym_Pause),
+ .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index cad4cf5475..f3dffca46e 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -31,26 +31,41 @@
static struct phy_driver genphy_driver;
static int genphy_config_init(struct phy_device *phydev);
-int phy_update_status(struct phy_device *dev)
+/**
+ * phy_aneg_done - return auto-negotiation status
+ * @phydev: target phy_device struct
+ *
+ * Description: Return the auto-negotiation status from this @phydev
+ * Returns > 0 on success or < 0 on error. 0 means that auto-negotiation
+ * is still pending.
+ */
+static int phy_aneg_done(struct phy_device *phydev)
+{
+ struct phy_driver *drv = to_phy_driver(phydev->dev.driver);
+
+ return drv->aneg_done(phydev);
+}
+
+int phy_update_status(struct phy_device *phydev)
{
- struct phy_driver *drv = to_phy_driver(dev->dev.driver);
- struct eth_device *edev = dev->attached_dev;
+ struct phy_driver *drv = to_phy_driver(phydev->dev.driver);
+ struct eth_device *edev = phydev->attached_dev;
int ret;
- int oldspeed = dev->speed, oldduplex = dev->duplex;
+ int oldspeed = phydev->speed, oldduplex = phydev->duplex;
- ret = drv->read_status(dev);
+ ret = drv->read_status(phydev);
if (ret)
return ret;
- if (dev->speed == oldspeed && dev->duplex == oldduplex)
+ if (phydev->speed == oldspeed && phydev->duplex == oldduplex)
return 0;
- if (dev->adjust_link)
- dev->adjust_link(edev);
+ if (phydev->adjust_link)
+ phydev->adjust_link(edev);
- if (dev->link)
- dev_info(&edev->dev, "%dMbps %s duplex link detected\n", dev->speed,
- dev->duplex ? "full" : "half");
+ if (phydev->link)
+ dev_info(&edev->dev, "%dMbps %s duplex link detected\n",
+ phydev->speed, phydev->duplex ? "full" : "half");
return 0;
}
@@ -71,9 +86,7 @@ int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
{
struct phy_fixup *fixup;
- fixup = kzalloc(sizeof(struct phy_fixup), GFP_KERNEL);
- if (!fixup)
- return -ENOMEM;
+ fixup = xzalloc(sizeof(struct phy_fixup));
strlcpy(fixup->bus_id, bus_id, sizeof(fixup->bus_id));
fixup->phy_uid = phy_uid;
@@ -138,31 +151,28 @@ int phy_scan_fixups(struct phy_device *phydev)
static struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id)
{
- struct phy_device *dev;
+ struct phy_device *phydev;
/* We allocate the device, and initialize the
* default values */
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-
- if (NULL == dev)
- return (struct phy_device*) PTR_ERR((void*)-ENOMEM);
+ phydev = xzalloc(sizeof(*phydev));
- dev->speed = 0;
- dev->duplex = -1;
- dev->pause = dev->asym_pause = 0;
- dev->link = 1;
- dev->autoneg = AUTONEG_ENABLE;
+ phydev->speed = 0;
+ phydev->duplex = -1;
+ phydev->pause = phydev->asym_pause = 0;
+ phydev->link = 1;
+ phydev->autoneg = AUTONEG_ENABLE;
- dev->addr = addr;
- dev->phy_id = phy_id;
+ phydev->addr = addr;
+ phydev->phy_id = phy_id;
- dev->bus = bus;
- dev->dev.bus = &mdio_bus_type;
+ phydev->bus = bus;
+ phydev->dev.bus = &mdio_bus_type;
- strcpy(dev->dev.name, "phy");
- dev->dev.id = DEVICE_ID_DYNAMIC;
+ strcpy(phydev->dev.name, "phy");
+ phydev->dev.id = DEVICE_ID_DYNAMIC;
- return dev;
+ return phydev;
}
/**
* get_phy_id - reads the specified addr for its ID.
@@ -207,7 +217,7 @@ int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id)
*/
struct phy_device *get_phy_device(struct mii_bus *bus, int addr)
{
- struct phy_device *dev = NULL;
+ struct phy_device *phydev = NULL;
u32 phy_id = 0;
int r;
@@ -219,9 +229,9 @@ struct phy_device *get_phy_device(struct mii_bus *bus, int addr)
if ((phy_id & 0x1fffffff) == 0x1fffffff)
return ERR_PTR(-ENODEV);
- dev = phy_device_create(bus, addr, phy_id);
+ phydev = phy_device_create(bus, addr, phy_id);
- return dev;
+ return phydev;
}
static void phy_config_aneg(struct phy_device *phydev)
@@ -232,31 +242,31 @@ static void phy_config_aneg(struct phy_device *phydev)
drv->config_aneg(phydev);
}
-int phy_register_device(struct phy_device* dev)
+int phy_register_device(struct phy_device *phydev)
{
int ret;
- if (dev->registered)
+ if (phydev->registered)
return -EBUSY;
- dev->dev.parent = &dev->bus->dev;
+ phydev->dev.parent = &phydev->bus->dev;
- ret = register_device(&dev->dev);
+ ret = register_device(&phydev->dev);
if (ret)
return ret;
- dev->bus->phy_map[dev->addr] = dev;
+ phydev->bus->phy_map[phydev->addr] = phydev;
- dev->registered = 1;
+ phydev->registered = 1;
- if (dev->dev.driver)
+ if (phydev->dev.driver)
return 0;
- dev->dev.driver = &genphy_driver.drv;
- ret = device_probe(&dev->dev);
+ phydev->dev.driver = &genphy_driver.drv;
+ ret = device_probe(&phydev->dev);
if (ret) {
- unregister_device(&dev->dev);
- dev->registered = 0;
+ unregister_device(&phydev->dev);
+ phydev->registered = 0;
}
return ret;
@@ -477,25 +487,15 @@ int genphy_setup_forced(struct phy_device *phydev)
int phy_wait_aneg_done(struct phy_device *phydev)
{
uint64_t start = get_time_ns();
- int ctl;
if (phydev->autoneg == AUTONEG_DISABLE)
return 0;
while (!is_timeout(start, PHY_AN_TIMEOUT * SECOND)) {
- ctl = phy_read(phydev, MII_BMSR);
- if (ctl & BMSR_ANEGCOMPLETE) {
+ if (phy_aneg_done(phydev) > 0) {
phydev->link = 1;
return 0;
}
-
- /* Restart auto-negotiation if remote fault */
- if (ctl & BMSR_RFAULT) {
- puts("PHY remote fault detected\n"
- "PHY restarting auto-negotiation\n");
- phy_write(phydev, MII_BMCR,
- BMCR_ANENABLE | BMCR_ANRESTART);
- }
}
phydev->link = 0;
@@ -572,6 +572,33 @@ int genphy_config_aneg(struct phy_device *phydev)
}
/**
+ * genphy_aneg_done - return auto-negotiation status
+ * @phydev: target phy_device struct
+ *
+ * Description: Reads the status register and returns 0 either if
+ * auto-negotiation is incomplete, or if there was an error.
+ * Returns BMSR_ANEGCOMPLETE if auto-negotiation is done.
+ */
+int genphy_aneg_done(struct phy_device *phydev)
+{
+ int bmsr = phy_read(phydev, MII_BMSR);
+
+ if (bmsr < 0)
+ return bmsr;
+
+ /* Restart auto-negotiation if remote fault */
+ if (bmsr & BMSR_RFAULT) {
+ puts("PHY remote fault detected\n"
+ "PHY restarting auto-negotiation\n");
+ phy_write(phydev, MII_BMCR,
+ BMCR_ANENABLE | BMCR_ANRESTART);
+ }
+
+ return bmsr & BMSR_ANEGCOMPLETE;
+}
+EXPORT_SYMBOL(genphy_aneg_done);
+
+/**
* genphy_update_link - update link status in @phydev
* @phydev: target phy_device struct
*
@@ -825,6 +852,9 @@ int phy_driver_register(struct phy_driver *phydrv)
if (!phydrv->config_aneg)
phydrv->config_aneg = genphy_config_aneg;
+ if (!phydrv->aneg_done)
+ phydrv->aneg_done = genphy_aneg_done;
+
if (!phydrv->read_status)
phydrv->read_status = genphy_read_status;
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index d6ac322b7b..14a8c765f1 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -7,6 +7,7 @@
#include <errno.h>
#include <malloc.h>
#include <asm/byteorder.h>
+#include <asm/unaligned.h>
/* ASIX AX8817X based USB 2.0 Ethernet Devices */
@@ -134,6 +135,8 @@
#define FLAG_EEPROM_MAC (1UL << 0) /* init device MAC from eeprom */
+#define RX_FIXUP_SIZE 1514
+
/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
struct asix_data {
u8 multi_filter[AX_MCAST_FILTER_SIZE];
@@ -150,6 +153,18 @@ struct ax88172_int_data {
__le16 res3;
} __attribute__ ((packed));
+struct asix_rx_fixup_info {
+ u32 header;
+ u16 size;
+ u16 offset;
+ bool split_head;
+ unsigned char ax_skb[RX_FIXUP_SIZE];
+};
+
+struct asix_common_private {
+ struct asix_rx_fixup_info rx_fixup_info;
+};
+
static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
@@ -409,49 +424,87 @@ static int ax88172_get_ethaddr(struct eth_device *edev, unsigned char *adr)
return 0;
}
-static int asix_rx_fixup(struct usbnet *dev, void *buf, int len)
+int asix_rx_fixup_internal(struct usbnet *dev, void *buf, int len,
+ struct asix_rx_fixup_info *rx)
{
- unsigned int header;
- unsigned short size;
-
- memcpy(&header, (void*) buf, sizeof(header));
- le32_to_cpus(&header);
- buf += 4;
- len -= 4;
-
- while (len > 0) {
- if ((header & 0x07ff) != ((~header >> 16) & 0x07ff))
- dev_err(&dev->edev.dev, "asix_rx_fixup() Bad Header Length\n");
-
- /* get the packet length */
- size = (unsigned short) (header & 0x07ff);
-
- if (size > 1514) {
- dev_err(&dev->edev.dev, "asix_rx_fixup() Bad RX Length %d\n", size);
- return 0;
+ int offset = 0;
+
+ while (offset + sizeof(u16) < len) {
+ u16 remaining = 0;
+
+ if (!rx->size) {
+ if ((len - offset == sizeof(u16)) ||
+ rx->split_head) {
+ if (!rx->split_head) {
+ rx->header = get_unaligned_le16(
+ buf + offset);
+ rx->split_head = true;
+ offset += sizeof(u16);
+ break;
+ } else {
+ rx->header |= (get_unaligned_le16(
+ buf + offset)
+ << 16);
+ rx->split_head = false;
+ offset += sizeof(u16);
+ }
+ } else {
+ rx->header = get_unaligned_le32(buf +
+ offset);
+ offset += sizeof(u32);
+ }
+ rx->offset = 0U;
+
+ /* get the packet length */
+ rx->size = (u16) (rx->header & 0x7ff);
+ if (rx->size != ((~rx->header >> 16) & 0x7ff)) {
+ dev_err(&dev->edev.dev, "asix_rx_fixup() Bad Header Length 0x%x, offset %d\n",
+ rx->header, offset);
+ rx->size = 0;
+ return -1;
+ }
}
+ if (rx->size > RX_FIXUP_SIZE) {
+ dev_err(&dev->edev.dev, "asix_rx_fixup() Bad RX Length %d\n",
+ rx->size);
+ rx->offset = 0U;
+ rx->size = 0U;
- net_receive(&dev->edev, buf, size);
+ return -1;
+ }
- buf += ((size + 1) & 0xfffe);
- len -= ((size + 1) & 0xfffe);
+ if (rx->size > (len - offset)) {
+ remaining = rx->size - (len - offset);
+ rx->size = len - offset;
+ }
- if (len == 0)
- break;
+ memcpy(rx->ax_skb + rx->offset, buf + offset, rx->size);
+ rx->offset += rx->size;
+ if (!remaining)
+ net_receive(&dev->edev, rx->ax_skb,
+ (u16) (rx->header & 0x7ff));
- memcpy(&header, (void*) buf, sizeof(header));
- le32_to_cpus(&header);
- buf += 4;
- len -= 4;
+ offset += ((rx->size + 1) & 0xfffe);
+ rx->size = remaining;
}
- if (len < 0) {
- dev_err(&dev->edev.dev,"asix_rx_fixup() Bad SKB Length %d\n", len);
+ if (len != offset) {
+ dev_err(&dev->edev.dev, "asix_rx_fixup() Bad SKB Length %d, %d\n",
+ len, offset);
return -1;
}
+
return 0;
}
+static int asix_rx_fixup_common(struct usbnet *dev, void *buf, int len)
+{
+ struct asix_common_private *dp = dev->driver_priv;
+ struct asix_rx_fixup_info *rx = &dp->rx_fixup_info;
+
+ return asix_rx_fixup_internal(dev, buf, len, rx);
+}
+
static int asix_tx_fixup(struct usbnet *dev,
void *buf, int len,
void *nbuf, int *nlen)
@@ -632,6 +685,11 @@ static int ax88772_bind(struct usbnet *dev)
dev->rx_urb_size = 2048;
}
+ dev->driver_priv = kzalloc(sizeof(struct asix_common_private),
+ GFP_KERNEL);
+ if (!dev->driver_priv)
+ return -ENOMEM;
+
return 0;
out:
@@ -641,6 +699,7 @@ out:
static void asix_unbind(struct usbnet *dev)
{
mdiobus_unregister(&dev->miibus);
+ kfree(dev->driver_priv);
}
static struct driver_info ax8817x_info = {
@@ -688,7 +747,7 @@ static struct driver_info ax88772_info = {
.bind = ax88772_bind,
.unbind = asix_unbind,
.flags = FLAG_ETHER | FLAG_FRAMING_AX,
- .rx_fixup = asix_rx_fixup,
+ .rx_fixup = asix_rx_fixup_common,
.tx_fixup = asix_tx_fixup,
};
@@ -697,7 +756,7 @@ static struct driver_info ax88772b_info = {
.bind = ax88772_bind,
.unbind = asix_unbind,
.flags = FLAG_ETHER | FLAG_FRAMING_AX,
- .rx_fixup = asix_rx_fixup,
+ .rx_fixup = asix_rx_fixup_common,
.tx_fixup = asix_tx_fixup,
.data = FLAG_EEPROM_MAC,
};
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 81955063d7..97a1d933ec 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -4,7 +4,7 @@ config OFTREE
config OFTREE_MEM_GENERIC
depends on OFTREE
- depends on PPC || ARM || ARCH_EFI
+ depends on PPC || ARM || ARCH_EFI || OPENRISC
def_bool y
config DTC
diff --git a/drivers/of/base.c b/drivers/of/base.c
index c440a69e6c..e9f0883f47 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -265,19 +265,39 @@ struct device_node *of_find_node_by_alias(struct device_node *root, const char *
EXPORT_SYMBOL_GPL(of_find_node_by_alias);
/*
- * of_find_node_by_phandle - Find a node given a phandle
- * @handle: phandle of the node to find
+ * of_find_node_by_phandle_from - Find a node given a phandle from given
+ * root node.
+ * @handle: phandle of the node to find
+ * @root: root node of the tree to search in. If NULL use the
+ * internal tree.
*/
-struct device_node *of_find_node_by_phandle(phandle phandle)
+struct device_node *of_find_node_by_phandle_from(phandle phandle,
+ struct device_node *root)
{
struct device_node *node;
- of_tree_for_each_node_from(node, root_node)
+ if (!root)
+ root = root_node;
+
+ if (!root)
+ return 0;
+
+ of_tree_for_each_node_from(node, root)
if (node->phandle == phandle)
return node;
return NULL;
}
+EXPORT_SYMBOL(of_find_node_by_phandle_from);
+
+/*
+ * of_find_node_by_phandle - Find a node given a phandle
+ * @handle: phandle of the node to find
+ */
+struct device_node *of_find_node_by_phandle(phandle phandle)
+{
+ return of_find_node_by_phandle_from(phandle, root_node);
+}
EXPORT_SYMBOL(of_find_node_by_phandle);
/*
@@ -336,6 +356,27 @@ phandle of_node_create_phandle(struct device_node *node)
}
EXPORT_SYMBOL(of_node_create_phandle);
+int of_set_property_to_child_phandle(struct device_node *node, char *prop_name)
+{
+ int ret;
+ phandle p;
+
+ /* Check if property exist */
+ if (!of_get_property(of_get_parent(node), prop_name, NULL))
+ return -EINVAL;
+
+ /* Create or get existing phandle of child node */
+ p = of_node_create_phandle(node);
+ p = cpu_to_be32(p);
+
+ node = of_get_parent(node);
+
+ ret = of_set_property(node, prop_name, &p, sizeof(p), 0);
+
+ return ret;
+}
+EXPORT_SYMBOL(of_set_property_to_child_phandle);
+
/*
* Find a property with a given name for a given node
* and return the value.
@@ -1110,16 +1151,19 @@ int of_property_write_u64_array(struct device_node *np,
}
/**
- * of_parse_phandle - Resolve a phandle property to a device_node pointer
+ * of_parse_phandle_from - Resolve a phandle property to a device_node pointer from
+ * a given root node
* @np: Pointer to device node holding phandle property
+ * @root: root node of the tree to search in. If NULL use the internal tree.
* @phandle_name: Name of property holding a phandle value
* @index: For properties holding a table of phandles, this is the index into
* the table
*
* Returns the device_node pointer found or NULL.
*/
-struct device_node *of_parse_phandle(const struct device_node *np,
- const char *phandle_name, int index)
+struct device_node *of_parse_phandle_from(const struct device_node *np,
+ struct device_node *root,
+ const char *phandle_name, int index)
{
const __be32 *phandle;
int size;
@@ -1128,7 +1172,24 @@ struct device_node *of_parse_phandle(const struct device_node *np,
if ((!phandle) || (size < sizeof(*phandle) * (index + 1)))
return NULL;
- return of_find_node_by_phandle(be32_to_cpup(phandle + index));
+ return of_find_node_by_phandle_from(be32_to_cpup(phandle + index),
+ root);
+}
+EXPORT_SYMBOL(of_parse_phandle_from);
+
+/**
+ * of_parse_phandle - Resolve a phandle property to a device_node pointer
+ * @np: Pointer to device node holding phandle property
+ * @phandle_name: Name of property holding a phandle value
+ * @index: For properties holding a table of phandles, this is the index into
+ * the table
+ *
+ * Returns the device_node pointer found or NULL.
+ */
+struct device_node *of_parse_phandle(const struct device_node *np,
+ const char *phandle_name, int index)
+{
+ return of_parse_phandle_from(np, root_node, phandle_name, index);
}
EXPORT_SYMBOL(of_parse_phandle);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 8e4c7756fb..cfe1833509 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -1,5 +1,5 @@
/*
- * dtb.c - flat devicetree functions
+ * fdt.c - flat devicetree functions
*
* Copyright (c) 2013 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 398b931546..770fb2d414 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -1,20 +1,21 @@
config PINCTRL
bool "Pin controller core support"
- depends on OFDEVICE
+ default y if OFDEVICE
help
Pincontrollers allow to setup the iomux unit of SoCs. The pin
controller core is needed when pin muxing shall be configured
from the devicetree. Legacy drivers here may not need this core
support but instead provide their own SoC specific APIs
+# The following drivers are needed even without PINCTRL because
+# the either have a legacy iomux interface or also register a gpio
+# chip.
config PINCTRL_AT91
- select PINCTRL if OFDEVICE
bool
help
The pinmux controller found on AT91 SoCs.
config PINCTRL_IMX_IOMUX_V1
- select PINCTRL if OFDEVICE
bool
help
This iomux controller is found on i.MX1,21,27.
@@ -25,13 +26,18 @@ config PINCTRL_IMX_IOMUX_V2
This iomux controller is found on i.MX31.
config PINCTRL_IMX_IOMUX_V3
- select PINCTRL if OFDEVICE
bool
help
This iomux controller is found on i.MX25,35,51,53,6.
+if PINCTRL
+
+if !OFDEVICE
+comment "OFDEVICE is not enabled."
+comment "Without device tree support PINCTRL won't do anything"
+endif
+
config PINCTRL_ROCKCHIP
- select PINCTRL
select GPIO_GENERIC
select MFD_SYSCON
bool
@@ -39,19 +45,21 @@ config PINCTRL_ROCKCHIP
The pinmux controller found on Rockchip SoCs.
config PINCTRL_SINGLE
- select PINCTRL
bool "pinctrl single"
config PINCTRL_TEGRA20
- select PINCTRL
bool
+ default y if ARCH_TEGRA_2x_SOC
help
The pinmux controller found on the Tegra 20 line of SoCs.
config PINCTRL_TEGRA30
- select PINCTRL
bool
+ default y if ARCH_TEGRA_3x_SOC
+ default y if ARCH_TEGRA_124_SOC
help
The pinmux controller found on the Tegra 30+ line of SoCs.
source drivers/pinctrl/mvebu/Kconfig
+
+endif
diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig
index be154ed437..af20cad439 100644
--- a/drivers/pinctrl/mvebu/Kconfig
+++ b/drivers/pinctrl/mvebu/Kconfig
@@ -1,15 +1,15 @@
config PINCTRL_ARMADA_370
+ default y if ARCH_ARMADA_370
bool
- select PINCTRL
config PINCTRL_ARMADA_XP
bool
- select PINCTRL
+ default y if ARCH_ARMADA_XP
config PINCTRL_DOVE
bool
- select PINCTRL
+ default y if ARCH_DOVE
config PINCTRL_KIRKWOOD
bool
- select PINCTRL
+ default y if ARCH_KIRKWOOD
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index a5b52a8bc0..3533aff942 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -443,6 +443,9 @@ static int rockchip_pinctrl_probe(struct device_d *dev)
if (ret)
return ret;
+ if (!IS_ENABLED(CONFIG_PINCTRL))
+ return 0;
+
ret = pinctrl_register(&info->pctl_dev);
if (ret)
return ret;
diff --git a/drivers/pinctrl/pinctrl.c b/drivers/pinctrl/pinctrl.c
index 8963ac75c0..d6479b9cd5 100644
--- a/drivers/pinctrl/pinctrl.c
+++ b/drivers/pinctrl/pinctrl.c
@@ -62,6 +62,9 @@ int of_pinctrl_select_state(struct device_node *np, const char *name)
struct device_node *np_config;
const char *statename;
+ if (!IS_ENABLED(CONFIG_PINCTRL))
+ return -ENOSYS;
+
if (!of_find_property(np, "pinctrl-0", NULL))
return 0;
@@ -146,6 +149,9 @@ int pinctrl_select_state_default(struct device_d *dev)
int pinctrl_register(struct pinctrl_device *pdev)
{
+ if (!IS_ENABLED(CONFIG_PINCTRL))
+ return -ENOSYS;
+
BUG_ON(!pdev->dev->device_node);
list_add_tail(&pdev->list, &pinctrl_list);
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index eedd20e311..8520a2fd9b 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -19,3 +19,5 @@ endif
source drivers/usb/gadget/Kconfig
+source drivers/usb/musb/Kconfig
+
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 3cefab7131..047f184800 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_USB) += core/
obj-$(CONFIG_USB_IMX_CHIPIDEA) += imx/
+obj-$(CONFIG_USB_MUSB) += musb/
obj-$(CONFIG_USB_GADGET) += gadget/
obj-$(CONFIG_USB_STORAGE) += storage/
obj-y += host/
diff --git a/drivers/usb/core/of.c b/drivers/usb/core/of.c
index 1ddbdaab0f..fd20368424 100644
--- a/drivers/usb/core/of.c
+++ b/drivers/usb/core/of.c
@@ -16,6 +16,7 @@
#include <common.h>
#include <usb/usb.h>
+#include <usb/phy.h>
#include <of.h>
static const char *usb_dr_modes[] = {
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 883a19f35b..65315e6f31 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -1,9 +1,4 @@
-config USB_HAVE_GADGET_DRIVER
- bool
- default y if ARCH_IMX || ARCH_MXS || ARCH_AT91 || ARCH_PXA
-
menuconfig USB_GADGET
- depends on USB_HAVE_GADGET_DRIVER
select USB
bool "USB gadget support"
@@ -12,13 +7,11 @@ if USB_GADGET
config USB_GADGET_DUALSPEED
bool
-choice
- prompt "USB Peripheral Controller"
-
config USB_GADGET_DRIVER_ARC
bool
prompt "Arc OTG device core"
depends on ARCH_IMX || ARCH_MXS
+ default y
select USB_GADGET_DUALSPEED
select POLLER
@@ -26,6 +19,7 @@ config USB_GADGET_DRIVER_AT91
bool
prompt "at91 gadget driver"
depends on ARCH_AT91
+ default y
select USB_GADGET_DUALSPEED
select POLLER
@@ -33,9 +27,9 @@ config USB_GADGET_DRIVER_PXA27X
bool
prompt "PXA27x gadget driver"
depends on ARCH_PXA
+ default y
select USB_GADGET_DUALSPEED
select POLLER
-endchoice
comment "USB Gadget drivers"
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 2f0d5ed6fa..60e1ff79d3 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -21,7 +21,6 @@
#include <clock.h>
#include <usb/ch9.h>
#include <usb/gadget.h>
-#include <poller.h>
#include <gpio.h>
#include <linux/list.h>
@@ -1257,6 +1256,8 @@ static int at91_udc_stop(struct usb_gadget *gadget, struct usb_gadget_driver *dr
return 0;
}
+static void at91_udc_gadget_poll(struct usb_gadget *gadget);
+
static const struct usb_gadget_ops at91_udc_ops = {
.get_frame = at91_get_frame,
.wakeup = at91_wakeup,
@@ -1271,6 +1272,7 @@ static const struct usb_gadget_ops at91_udc_ops = {
/* .vbus_power = at91_vbus_power, */
.udc_start = at91_udc_start,
.udc_stop = at91_udc_stop,
+ .udc_poll = at91_udc_gadget_poll,
};
/*-------------------------------------------------------------------------*/
@@ -1350,13 +1352,13 @@ static int at91_udc_vbus_set(struct param_d *p, void *priv)
return -EROFS;
}
-int usb_gadget_poll(void)
+static void at91_udc_gadget_poll(struct usb_gadget *gadget)
{
struct at91_udc *udc = &controller;
u32 value;
if (!udc->udp_baseaddr)
- return -ENODEV;
+ return;
if (gpio_is_valid(udc->board.vbus_pin)) {
value = gpio_get_value(udc->board.vbus_pin);
@@ -1365,27 +1367,16 @@ int usb_gadget_poll(void)
udc->gpio_vbus_val = value;
if (!value)
- return 0;
+ return;
}
value = at91_udp_read(udc, AT91_UDP_ISR) & (~(AT91_UDP_SOFINT));
if (value)
at91_udc_irq(udc);
-
- return value;
}
/*-------------------------------------------------------------------------*/
-static void at91_udc_poller(struct poller_struct *poller)
-{
- usb_gadget_poll();
-}
-
-static struct poller_struct poller = {
- .func = at91_udc_poller
-};
-
static int __init at91udc_probe(struct device_d *dev)
{
struct at91_udc *udc = &controller;
@@ -1480,8 +1471,6 @@ static int __init at91udc_probe(struct device_d *dev)
udc->vbus = 1;
}
- poller_register(&poller);
-
retval = usb_add_gadget_udc_release(dev, &udc->gadget, NULL);
if (retval)
goto fail0a;
diff --git a/drivers/usb/gadget/dfu.c b/drivers/usb/gadget/dfu.c
index ddd765a343..67a0703ca9 100644
--- a/drivers/usb/gadget/dfu.c
+++ b/drivers/usb/gadget/dfu.c
@@ -722,6 +722,7 @@ static struct usb_composite_driver dfu_driver = {
.name = "g_dfu",
.dev = &dfu_dev_descriptor,
.strings = dev_strings,
+ .max_speed = USB_SPEED_HIGH,
.bind = dfu_driver_bind,
.unbind = dfu_driver_unbind,
};
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 9aec6b198a..92a1a218c6 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -26,6 +26,7 @@
#include <boot.h>
#include <dma.h>
#include <fs.h>
+#include <libfile.h>
#include <file-list.h>
#include <progress.h>
#include <environment.h>
diff --git a/drivers/usb/gadget/fsl_udc.c b/drivers/usb/gadget/fsl_udc.c
index 877d2dfec4..d067f03a40 100644
--- a/drivers/usb/gadget/fsl_udc.c
+++ b/drivers/usb/gadget/fsl_udc.c
@@ -7,7 +7,6 @@
#include <usb/gadget.h>
#include <usb/fsl_usb2.h>
#include <io.h>
-#include <poller.h>
#include <asm/byteorder.h>
#include <linux/err.h>
@@ -1938,18 +1937,17 @@ static void dtd_complete_irq(struct fsl_udc *udc)
/*
* USB device controller interrupt handler
*/
-int usb_gadget_poll(void)
+static void fsl_udc_gadget_poll(struct usb_gadget *gadget)
{
struct fsl_udc *udc = udc_controller;
u32 irq_src;
- int status = 0;
if (!udc)
- return -ENODEV;
+ return;
/* Disable ISR for OTG host mode */
if (udc->stopped)
- return -EIO;
+ return;
irq_src = readl(&dr_regs->usbsts) & readl(&dr_regs->usbintr);
/* Clear notification bits */
@@ -1962,43 +1960,27 @@ int usb_gadget_poll(void)
tripwire_handler(udc, 0,
(u8 *) (&udc->local_setup_buff));
setup_received_irq(udc, &udc->local_setup_buff);
- status = 1;
}
/* completion of dtd */
- if (readl(&dr_regs->endptcomplete)) {
+ if (readl(&dr_regs->endptcomplete))
dtd_complete_irq(udc);
- status = 1;
- }
- }
-
- /* SOF (for ISO transfer) */
- if (irq_src & USB_STS_SOF) {
- status = 1;
}
/* Port Change */
- if (irq_src & USB_STS_PORT_CHANGE) {
+ if (irq_src & USB_STS_PORT_CHANGE)
port_change_irq(udc);
- status = 1;
- }
/* Reset Received */
- if (irq_src & USB_STS_RESET) {
+ if (irq_src & USB_STS_RESET)
reset_irq(udc);
- status = 1;
- }
/* Sleep Enable (Suspend) */
- if (irq_src & USB_STS_SUSPEND) {
+ if (irq_src & USB_STS_SUSPEND)
udc->driver->disconnect(&udc_controller->gadget);
- status = 1;
- }
if (irq_src & (USB_STS_ERR | USB_STS_SYS_ERR))
printf("Error IRQ %x\n", irq_src);
-
- return status;
}
/*----------------------------------------------------------------*
@@ -2197,6 +2179,7 @@ static struct usb_gadget_ops fsl_gadget_ops = {
.pullup = fsl_pullup,
.udc_start = fsl_udc_start,
.udc_stop = fsl_udc_stop,
+ .udc_poll = fsl_udc_gadget_poll,
};
/*----------------------------------------------------------------
@@ -2234,15 +2217,6 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
return 0;
}
-static void fsl_udc_poller(struct poller_struct *poller)
-{
- usb_gadget_poll();
-}
-
-static struct poller_struct poller = {
- .func = fsl_udc_poller
-};
-
int ci_udc_register(struct device_d *dev, void __iomem *regs)
{
int ret, i;
@@ -2305,8 +2279,6 @@ int ci_udc_register(struct device_d *dev, void __iomem *regs)
struct_ep_setup(udc_controller, i * 2 + 1, name, 1);
}
- poller_register(&poller);
-
ret = usb_add_gadget_udc_release(dev, &udc_controller->gadget,
NULL);
if (ret)
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 6cc4dd7bda..3db3480cad 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -23,7 +23,6 @@
#include <io.h>
#include <gpio.h>
#include <init.h>
-#include <poller.h>
#include <usb/ch9.h>
#include <usb/gadget.h>
@@ -884,6 +883,7 @@ static int pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
static int pxa_udc_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver);
static int pxa_udc_stop(struct usb_gadget *gadget, struct usb_gadget_driver *driver);
+static void pxa_udc_gadget_poll(struct usb_gadget *gadget);
static const struct usb_gadget_ops pxa_udc_ops = {
.get_frame = pxa_udc_get_frame,
@@ -892,6 +892,7 @@ static const struct usb_gadget_ops pxa_udc_ops = {
.vbus_session = pxa_udc_vbus_session,
.udc_start = pxa_udc_start,
.udc_stop = pxa_udc_stop,
+ .udc_poll = pxa_udc_gadget_poll,
};
static void clk_enable(void)
@@ -1366,14 +1367,13 @@ static void irq_udc_reset(struct pxa_udc *udc)
ep0_idle(udc);
}
-int usb_gadget_poll(void)
+static void pxa_udc_gadget_poll(struct usb_gadget *gadget)
{
- struct pxa_udc *udc = the_controller;
+ struct pxa_udc *udc = to_gadget_udc(gadget);
u32 udcisr0 = udc_readl(udc, UDCISR0);
u32 udcisr1 = udc_readl(udc, UDCISR1);
u32 udccr = udc_readl(udc, UDCCR);
u32 udcisr1_spec;
- int ret = 0;
udc->vbus_sensed = udc->mach->udc_is_connected();
if (should_enable_udc(udc))
@@ -1384,7 +1384,7 @@ int usb_gadget_poll(void)
}
if (!udc->enabled)
- return -EIO;
+ return;
dev_dbg(udc->dev, "Interrupt, UDCISR0:0x%08x, UDCISR1:0x%08x, "
"UDCCR:0x%08x\n", udcisr0, udcisr1, udccr);
@@ -1398,15 +1398,9 @@ int usb_gadget_poll(void)
irq_udc_reconfig(udc);
if (unlikely(udcisr1_spec & UDCISR1_IRRS))
irq_udc_reset(udc);
- if (udcisr1_spec)
- ret = 1;
- if ((udcisr0 & UDCCISR0_EP_MASK) | (udcisr1 & UDCCISR1_EP_MASK)) {
+ if ((udcisr0 & UDCCISR0_EP_MASK) | (udcisr1 & UDCCISR1_EP_MASK))
irq_handle_data(udc);
- ret = 1;
- }
-
- return ret;
}
static struct pxa_udc memory = {
@@ -1453,14 +1447,6 @@ static struct pxa_udc memory = {
}
};
-static void pxa27x_udc_poller(struct poller_struct *poller)
-{
- usb_gadget_poll();
-}
-static struct poller_struct poller = {
- .func = pxa27x_udc_poller
-};
-
static int __init pxa_udc_probe(struct device_d *dev)
{
struct pxa_udc *udc = &memory;
@@ -1484,7 +1470,6 @@ static int __init pxa_udc_probe(struct device_d *dev)
the_controller = udc;
udc_init_data(udc);
pxa_eps_setup(udc);
- poller_register(&poller);
ret = usb_add_gadget_udc_release(dev, &udc->gadget, NULL);
if (ret)
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index 2f62177cac..4f001e102f 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -20,6 +20,7 @@
#include <common.h>
#include <driver.h>
#include <init.h>
+#include <poller.h>
#include <usb/ch9.h>
#include <usb/gadget.h>
@@ -38,6 +39,7 @@ struct usb_udc {
struct usb_gadget *gadget;
struct device_d dev;
struct list_head list;
+ struct poller_struct poller;
};
static LIST_HEAD(udc_list);
@@ -146,6 +148,18 @@ static inline void usb_gadget_udc_stop(struct usb_gadget *gadget,
gadget->ops->udc_stop(gadget, driver);
}
+int usb_gadget_poll(void)
+{
+ struct usb_udc *udc;
+
+ list_for_each_entry(udc, &udc_list, list) {
+ if (udc->gadget->ops->udc_poll)
+ udc->gadget->ops->udc_poll(udc->gadget);
+ }
+
+ return 0;
+}
+
/**
* usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
* @parent: the parent device to this udc. Usually the controller driver's
@@ -223,6 +237,9 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
udc->gadget->name);
+ if (udc->gadget->ops->udc_poll)
+ poller_unregister(&udc->poller);
+
usb_gadget_disconnect(udc->gadget);
udc->driver->disconnect(udc->gadget);
udc->driver->unbind(udc->gadget);
@@ -267,6 +284,13 @@ EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
/* ------------------------------------------------------------------------- */
+static void udc_poll_driver(struct poller_struct *poller)
+{
+ struct usb_udc *udc = container_of(poller, struct usb_udc, poller);
+
+ udc->gadget->ops->udc_poll(udc->gadget);
+}
+
static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
{
int ret;
@@ -278,6 +302,13 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
udc->dev.driver = &driver->driver;
udc->gadget->dev.driver = &driver->driver;
+ if (udc->gadget->ops->udc_poll) {
+ udc->poller.func = udc_poll_driver;
+ ret = poller_register(&udc->poller);
+ if (ret)
+ return ret;
+ }
+
ret = driver->bind(udc->gadget, driver);
if (ret)
goto err1;
@@ -291,6 +322,9 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
return 0;
err1:
+ if (udc->gadget->ops->udc_poll)
+ poller_unregister(&udc->poller);
+
if (ret != -EISNAM)
dev_err(&udc->dev, "failed to start %s: %d\n",
udc->driver->function, ret);
diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c
index ffa46dac6e..1dca6bfe1d 100644
--- a/drivers/usb/imx/chipidea-imx.c
+++ b/drivers/usb/imx/chipidea-imx.c
@@ -22,6 +22,7 @@
#include <usb/ehci.h>
#include <regulator.h>
#include <usb/chipidea-imx.h>
+#include <usb/phy.h>
#include <usb/ulpi.h>
#include <usb/fsl_usb2.h>
#include <linux/err.h>
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
new file mode 100644
index 0000000000..e0a1139bc0
--- /dev/null
+++ b/drivers/usb/musb/Kconfig
@@ -0,0 +1,29 @@
+config USB_MUSB
+ bool "MUSB support"
+
+if USB_MUSB
+
+config USB_MUSB_DSPS
+ tristate
+
+config USB_MUSB_AM335X
+ tristate "AM335x USB support"
+ depends on ARCH_AM33XX
+ select USB_MUSB_DSPS
+ help
+ This driver provides the necessary bit to enable USB support
+ on the TI AM335x SoC.
+
+config USB_MUSB_HOST
+ bool "MUSB Host mode support"
+ depends on USB_HOST
+ help
+ Select this when you want to use MUSB in host mode.
+
+config USB_MUSB_GADGET
+ bool "MUSB Gadget mode support"
+ depends on USB_GADGET
+ help
+ Select this when you want to use MUSB in gadget mode.
+
+endif
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
new file mode 100644
index 0000000000..364a43fecb
--- /dev/null
+++ b/drivers/usb/musb/Makefile
@@ -0,0 +1,11 @@
+#
+# for USB OTG silicon based on Mentor Graphics INVENTRA designs
+#
+
+obj-y += musb_core.o musb_barebox.o
+
+obj-$(CONFIG_USB_MUSB_HOST) += musb_host.o
+obj-$(CONFIG_USB_MUSB_GADGET) += musb_gadget.o musb_gadget_ep0.o
+
+obj-$(CONFIG_USB_MUSB_DSPS) += musb_dsps.o
+obj-$(CONFIG_USB_MUSB_AM335X) += phy-am335x-control.o musb_am335x.o phy-am335x.o
diff --git a/drivers/usb/musb/am35x-phy-control.h b/drivers/usb/musb/am35x-phy-control.h
new file mode 100644
index 0000000000..c492d421dc
--- /dev/null
+++ b/drivers/usb/musb/am35x-phy-control.h
@@ -0,0 +1,21 @@
+#ifndef _AM335x_PHY_CONTROL_H_
+#define _AM335x_PHY_CONTROL_H_
+
+struct phy_control {
+ void (*phy_power)(struct phy_control *phy_ctrl, u32 id, bool on);
+ void (*phy_wkup)(struct phy_control *phy_ctrl, u32 id, bool on);
+};
+
+static inline void phy_ctrl_power(struct phy_control *phy_ctrl, u32 id, bool on)
+{
+ phy_ctrl->phy_power(phy_ctrl, id, on);
+}
+
+static inline void phy_ctrl_wkup(struct phy_control *phy_ctrl, u32 id, bool on)
+{
+ phy_ctrl->phy_wkup(phy_ctrl, id, on);
+}
+
+struct phy_control *am335x_get_phy_control(struct device_d *dev);
+
+#endif
diff --git a/drivers/usb/musb/musb_am335x.c b/drivers/usb/musb/musb_am335x.c
new file mode 100644
index 0000000000..2a9167a245
--- /dev/null
+++ b/drivers/usb/musb/musb_am335x.c
@@ -0,0 +1,29 @@
+#include <common.h>
+#include <init.h>
+#include <linux/clk.h>
+
+static int am335x_child_probe(struct device_d *dev)
+{
+ int ret;
+
+ ret = of_platform_populate(dev->device_node, NULL, dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id am335x_child_dt_ids[] = {
+ {
+ .compatible = "ti,am33xx-usb",
+ }, {
+ /* sentinel */
+ },
+};
+
+static struct driver_d am335x_child_driver = {
+ .name = "am335x_child_probe",
+ .probe = am335x_child_probe,
+ .of_compatible = DRV_OF_COMPAT(am335x_child_dt_ids),
+};
+device_platform_driver(am335x_child_driver);
diff --git a/drivers/usb/musb/musb_barebox.c b/drivers/usb/musb/musb_barebox.c
new file mode 100644
index 0000000000..6bc232b570
--- /dev/null
+++ b/drivers/usb/musb/musb_barebox.c
@@ -0,0 +1,146 @@
+#include <common.h>
+#include <init.h>
+#include <clock.h>
+#include <usb/musb.h>
+#include <usb/usb.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/barebox-wrapper.h>
+
+#include "musb_core.h"
+#include "musb_gadget.h"
+
+static struct usb_host_endpoint hep;
+static struct urb urb;
+
+static void musb_host_complete_urb(struct urb *urb)
+{
+ urb->dev->status &= ~USB_ST_NOT_PROC;
+ urb->dev->act_len = urb->actual_length;
+}
+
+static struct urb *construct_urb(struct usb_device *dev, int endpoint_type,
+ unsigned long pipe, void *buffer, int len,
+ struct devrequest *setup, int interval)
+{
+ int epnum = usb_pipeendpoint(pipe);
+ int is_in = usb_pipein(pipe);
+
+ memset(&urb, 0, sizeof(struct urb));
+ memset(&hep, 0, sizeof(struct usb_host_endpoint));
+ INIT_LIST_HEAD(&hep.urb_list);
+ INIT_LIST_HEAD(&urb.urb_list);
+ urb.ep = &hep;
+ urb.complete = musb_host_complete_urb;
+ urb.status = -EINPROGRESS;
+ urb.dev = dev;
+ urb.pipe = pipe;
+ urb.transfer_buffer = buffer;
+ urb.transfer_dma = (unsigned long)buffer;
+ urb.transfer_buffer_length = len;
+ urb.setup_packet = (unsigned char *)setup;
+
+ urb.ep->desc.wMaxPacketSize =
+ __cpu_to_le16(is_in ? dev->epmaxpacketin[epnum] :
+ dev->epmaxpacketout[epnum]);
+ urb.ep->desc.bmAttributes = endpoint_type;
+ urb.ep->desc.bEndpointAddress =
+ (is_in ? USB_DIR_IN : USB_DIR_OUT) | epnum;
+ urb.ep->desc.bInterval = interval;
+
+ return &urb;
+}
+
+#define MUSB_HOST_TIMEOUT 0x5fffff
+
+static int submit_urb(struct usb_device *dev, struct urb *urb, int timeout_ms)
+{
+ struct usb_host *host = dev->host;
+ struct musb *musb = to_musb(host);
+ int ret;
+ uint64_t start;
+ uint64_t timeout = timeout_ms;
+
+ ret = musb_urb_enqueue(musb->hcd, urb, 0);
+ if (ret < 0) {
+ printf("Failed to enqueue URB to controller\n");
+ return ret;
+ }
+
+ start = get_time_ns();
+
+ do {
+ musb->isr(musb);
+
+ if (!urb->status)
+ return 0;
+
+ } while (!is_timeout(start, timeout * MSECOND));
+
+ if (urb->dev->status & USB_ST_NOT_PROC)
+ ret = -ETIMEDOUT;
+ else
+ ret = urb->status;
+
+ musb_urb_dequeue(musb->hcd, urb, -ECONNRESET);
+
+ return ret;
+}
+
+static int
+submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int length, int timeout)
+{
+ struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_BULK, pipe,
+ buffer, length, NULL, 0);
+ return submit_urb(dev, urb, timeout);
+}
+
+static int
+submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int length, struct devrequest *setup, int timeout)
+{
+ struct usb_host *host = dev->host;
+ struct musb *musb = to_musb(host);
+ struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_CONTROL, pipe,
+ buffer, length, setup, 0);
+
+ /* Fix speed for non hub-attached devices */
+ if (!dev->parent)
+ dev->speed = musb->host_speed;
+
+ return submit_urb(dev, urb, timeout);
+}
+
+static int
+submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int length, int interval)
+{
+ struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_INT, pipe,
+ buffer, length, NULL, interval);
+ return submit_urb(dev, urb, 100);
+}
+
+static int musb_detect(struct device_d *dev)
+{
+ struct musb *musb = dev->priv;
+
+ return usb_host_detect(&musb->host);
+}
+
+int musb_register(struct musb *musb)
+{
+ struct usb_host *host;
+
+ host = &musb->host;
+ host->hw_dev = musb->controller;
+ host->init = musb_init;
+ host->submit_int_msg = submit_int_msg;
+ host->submit_control_msg = submit_control_msg;
+ host->submit_bulk_msg = submit_bulk_msg;
+
+ musb->controller->detect = musb_detect;
+ usb_register_host(host);
+
+ return 0;
+}
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
new file mode 100644
index 0000000000..ccb702980f
--- /dev/null
+++ b/drivers/usb/musb/musb_core.c
@@ -0,0 +1,1156 @@
+/*
+ * MUSB OTG driver core code
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Inventra (Multipoint) Dual-Role Controller Driver for Linux.
+ *
+ * This consists of a Host Controller Driver (HCD) and a peripheral
+ * controller driver implementing the "Gadget" API; OTG support is
+ * in the works. These are normal Linux-USB controller drivers which
+ * use IRQs and have no dedicated thread.
+ *
+ * This version of the driver has only been used with products from
+ * Texas Instruments. Those products integrate the Inventra logic
+ * with other DMA, IRQ, and bus modules, as well as other logic that
+ * needs to be reflected in this driver.
+ *
+ *
+ * NOTE: the original Mentor code here was pretty much a collection
+ * of mechanisms that don't seem to have been fully integrated/working
+ * for *any* Linux kernel version. This version aims at Linux 2.6.now,
+ * Key open issues include:
+ *
+ * - Lack of host-side transaction scheduling, for all transfer types.
+ * The hardware doesn't do it; instead, software must.
+ *
+ * This is not an issue for OTG devices that don't support external
+ * hubs, but for more "normal" USB hosts it's a user issue that the
+ * "multipoint" support doesn't scale in the expected ways. That
+ * includes DaVinci EVM in a common non-OTG mode.
+ *
+ * * Control and bulk use dedicated endpoints, and there's as
+ * yet no mechanism to either (a) reclaim the hardware when
+ * peripherals are NAKing, which gets complicated with bulk
+ * endpoints, or (b) use more than a single bulk endpoint in
+ * each direction.
+ *
+ * RESULT: one device may be perceived as blocking another one.
+ *
+ * * Interrupt and isochronous will dynamically allocate endpoint
+ * hardware, but (a) there's no record keeping for bandwidth;
+ * (b) in the common case that few endpoints are available, there
+ * is no mechanism to reuse endpoints to talk to multiple devices.
+ *
+ * RESULT: At one extreme, bandwidth can be overcommitted in
+ * some hardware configurations, no faults will be reported.
+ * At the other extreme, the bandwidth capabilities which do
+ * exist tend to be severely undercommitted. You can't yet hook
+ * up both a keyboard and a mouse to an external USB hub.
+ */
+
+/*
+ * This gets many kinds of configuration information:
+ * - Kconfig for everything user-configurable
+ * - platform_device for addressing, irq, and platform_data
+ * - platform_data is mostly for board-specific information
+ * (plus recentrly, SOC or family details)
+ *
+ * Most of the conditional compilation will (someday) vanish.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <clock.h>
+#include <usb/musb.h>
+#include <usb/usb.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/barebox-wrapper.h>
+
+#include "musb_core.h"
+#include "musb_gadget.h"
+
+#define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON)
+
+
+#define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia"
+#define DRIVER_DESC "Inventra Dual-Role USB Controller Driver"
+
+#define MUSB_VERSION "6.0"
+
+#define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION
+
+#define MUSB_DRIVER_NAME "musb-hdrc"
+const char musb_driver_name[] = MUSB_DRIVER_NAME;
+
+MODULE_DESCRIPTION(DRIVER_INFO);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" MUSB_DRIVER_NAME);
+
+#define MUSB_HOST_TIMEOUT 0x5fffff
+
+/*-------------------------------------------------------------------------*/
+
+#ifndef CONFIG_BLACKFIN
+static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
+{
+ void __iomem *addr = phy->io_priv;
+ int i = 0;
+ u8 r;
+ u8 power;
+ int ret;
+
+ /* Make sure the transceiver is not in low power mode */
+ power = musb_readb(addr, MUSB_POWER);
+ power &= ~MUSB_POWER_SUSPENDM;
+ musb_writeb(addr, MUSB_POWER, power);
+
+ /* REVISIT: musbhdrc_ulpi_an.pdf recommends setting the
+ * ULPICarKitControlDisableUTMI after clearing POWER_SUSPENDM.
+ */
+
+ musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset);
+ musb_writeb(addr, MUSB_ULPI_REG_CONTROL,
+ MUSB_ULPI_REG_REQ | MUSB_ULPI_RDN_WR);
+
+ while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
+ & MUSB_ULPI_REG_CMPLT)) {
+ i++;
+ if (i == 10000) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+
+ }
+ r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
+ r &= ~MUSB_ULPI_REG_CMPLT;
+ musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
+
+ ret = musb_readb(addr, MUSB_ULPI_REG_DATA);
+
+out:
+ return ret;
+}
+
+static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
+{
+ void __iomem *addr = phy->io_priv;
+ int i = 0;
+ u8 r = 0;
+ u8 power;
+ int ret = 0;
+
+ /* Make sure the transceiver is not in low power mode */
+ power = musb_readb(addr, MUSB_POWER);
+ power &= ~MUSB_POWER_SUSPENDM;
+ musb_writeb(addr, MUSB_POWER, power);
+
+ musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset);
+ musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)data);
+ musb_writeb(addr, MUSB_ULPI_REG_CONTROL, MUSB_ULPI_REG_REQ);
+
+ while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
+ & MUSB_ULPI_REG_CMPLT)) {
+ i++;
+ if (i == 10000) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+ }
+
+ r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
+ r &= ~MUSB_ULPI_REG_CMPLT;
+ musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
+
+out:
+ return ret;
+}
+#else
+#define musb_ulpi_read NULL
+#define musb_ulpi_write NULL
+#endif
+
+struct usb_phy_io_ops musb_ulpi_access = {
+ .read = musb_ulpi_read,
+ .write = musb_ulpi_write,
+};
+
+/*-------------------------------------------------------------------------*/
+
+#if !defined(CONFIG_USB_MUSB_TUSB6010) && !defined(CONFIG_USB_MUSB_BLACKFIN)
+
+/*
+ * Load an endpoint's FIFO
+ */
+void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
+{
+ struct musb *musb = hw_ep->musb;
+ void __iomem *fifo = hw_ep->fifo;
+
+ if (unlikely(len == 0))
+ return;
+
+ prefetch((u8 *)src);
+
+ dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n",
+ 'T', hw_ep->epnum, fifo, len, src);
+
+ /* we can't assume unaligned reads work */
+ if (likely((0x01 & (unsigned long) src) == 0)) {
+ u16 index = 0;
+
+ /* best case is 32bit-aligned source address */
+ if ((0x02 & (unsigned long) src) == 0) {
+ if (len >= 4) {
+ writesl(fifo, src + index, len >> 2);
+ index += len & ~0x03;
+ }
+ if (len & 0x02) {
+ musb_writew(fifo, 0, *(u16 *)&src[index]);
+ index += 2;
+ }
+ } else {
+ if (len >= 2) {
+ writesw(fifo, src + index, len >> 1);
+ index += len & ~0x01;
+ }
+ }
+ if (len & 0x01)
+ musb_writeb(fifo, 0, src[index]);
+ } else {
+ /* byte aligned */
+ writesb(fifo, src, len);
+ }
+}
+
+#if !defined(CONFIG_USB_MUSB_AM35X)
+/*
+ * Unload an endpoint's FIFO
+ */
+void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
+{
+ struct musb *musb = hw_ep->musb;
+ void __iomem *fifo = hw_ep->fifo;
+
+ if (unlikely(len == 0))
+ return;
+
+ dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n",
+ 'R', hw_ep->epnum, fifo, len, dst);
+
+ /* we can't assume unaligned writes work */
+ if (likely((0x01 & (unsigned long) dst) == 0)) {
+ u16 index = 0;
+
+ /* best case is 32bit-aligned destination address */
+ if ((0x02 & (unsigned long) dst) == 0) {
+ if (len >= 4) {
+ readsl(fifo, dst, len >> 2);
+ index = len & ~0x03;
+ }
+ if (len & 0x02) {
+ *(u16 *)&dst[index] = musb_readw(fifo, 0);
+ index += 2;
+ }
+ } else {
+ if (len >= 2) {
+ readsw(fifo, dst, len >> 1);
+ index = len & ~0x01;
+ }
+ }
+ if (len & 0x01)
+ dst[index] = musb_readb(fifo, 0);
+ } else {
+ /* byte aligned */
+ readsb(fifo, dst, len);
+ }
+}
+#endif
+
+#endif /* normal PIO */
+
+/*-------------------------------------------------------------------------*/
+
+
+/* for high speed test mode; see USB 2.0 spec 7.1.20 */
+static const u8 musb_test_packet[53] = {
+ /* implicit SYNC then DATA0 to start */
+
+ /* JKJKJKJK x9 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* JJKKJJKK x8 */
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ /* JJJJKKKK x8 */
+ 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+ /* JJJJJJJKKKKKKK x8 */
+ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* JJJJJJJK x8 */
+ 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd,
+ /* JKKKKKKK x10, JK */
+ 0xfc, 0x7e, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0x7e
+
+ /* implicit CRC16 then EOP to end */
+};
+
+void musb_load_testpacket(struct musb *musb)
+{
+ void __iomem *regs = musb->endpoints[0].regs;
+
+ musb_ep_select(musb->mregs, 0);
+ musb_write_fifo(musb->control_ep,
+ sizeof(musb_test_packet), musb_test_packet);
+ musb_writew(regs, MUSB_CSR0, MUSB_CSR0_TXPKTRDY);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void musb_generic_disable(struct musb *musb)
+{
+ void __iomem *mbase = musb->mregs;
+ u16 temp;
+
+ /* disable interrupts */
+ musb_writeb(mbase, MUSB_INTRUSBE, 0);
+ musb->intrtxe = 0;
+ musb_writew(mbase, MUSB_INTRTXE, 0);
+ musb->intrrxe = 0;
+ musb_writew(mbase, MUSB_INTRRXE, 0);
+
+ /* off */
+ musb_writeb(mbase, MUSB_DEVCTL, 0);
+
+ /* flush pending interrupts */
+ temp = musb_readb(mbase, MUSB_INTRUSB);
+ temp = musb_readw(mbase, MUSB_INTRTX);
+ temp = musb_readw(mbase, MUSB_INTRRX);
+
+}
+
+/*
+ * Program the HDRC to start (enable interrupts, dma, etc.).
+ */
+void musb_start(struct musb *musb)
+{
+ void __iomem *regs = musb->mregs;
+ u8 devctl = musb_readb(regs, MUSB_DEVCTL);
+
+ dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
+
+ /* Set INT enable registers, enable interrupts */
+ musb->intrtxe = musb->epmask;
+ musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);
+ musb->intrrxe = musb->epmask & 0xfffe;
+ musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);
+ musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
+
+ musb_writeb(regs, MUSB_TESTMODE, 0);
+
+ /* put into basic highspeed mode and start session */
+ musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
+ | MUSB_POWER_HSENAB
+ /* ENSUSPEND wedges tusb */
+ /* | MUSB_POWER_ENSUSPEND */
+ );
+
+ musb->is_active = 0;
+ devctl = musb_readb(regs, MUSB_DEVCTL);
+ devctl &= ~MUSB_DEVCTL_SESSION;
+
+ /* session started after:
+ * (a) ID-grounded irq, host mode;
+ * (b) vbus present/connect IRQ, peripheral mode;
+ * (c) peripheral initiates, using SRP
+ */
+ if (musb->port_mode != MUSB_PORT_MODE_HOST &&
+ (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
+ musb->is_active = 1;
+ } else {
+ devctl |= MUSB_DEVCTL_SESSION;
+ }
+
+ musb_platform_enable(musb);
+ musb_writeb(regs, MUSB_DEVCTL, devctl);
+}
+
+/*
+ * Make the HDRC stop (disable interrupts, etc.);
+ * reversible by musb_start
+ * called on gadget driver unregister
+ * with controller locked, irqs blocked
+ * acts as a NOP unless some role activated the hardware
+ */
+void musb_stop(struct musb *musb)
+{
+ /* stop IRQs, timers, ... */
+ musb_platform_disable(musb);
+ musb_generic_disable(musb);
+ dev_dbg(musb->controller, "HDRC disabled\n");
+
+ /* FIXME
+ * - mark host and/or peripheral drivers unusable/inactive
+ * - disable DMA (and enable it in HdrcStart)
+ * - make sure we can musb_start() after musb_stop(); with
+ * OTG mode, gadget driver module rmmod/modprobe cycles that
+ * - ...
+ */
+ musb_platform_try_idle(musb, 0);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * The silicon either has hard-wired endpoint configurations, or else
+ * "dynamic fifo" sizing. The driver has support for both, though at this
+ * writing only the dynamic sizing is very well tested. Since we switched
+ * away from compile-time hardware parameters, we can no longer rely on
+ * dead code elimination to leave only the relevant one in the object file.
+ *
+ * We don't currently use dynamic fifo setup capability to do anything
+ * more than selecting one of a bunch of predefined configurations.
+ */
+#if defined(CONFIG_USB_MUSB_TUSB6010) \
+ || defined(CONFIG_USB_MUSB_TUSB6010_MODULE) \
+ || defined(CONFIG_USB_MUSB_OMAP2PLUS) \
+ || defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE) \
+ || defined(CONFIG_USB_MUSB_AM35X) \
+ || defined(CONFIG_USB_MUSB_AM35X_MODULE) \
+ || defined(CONFIG_USB_MUSB_DSPS) \
+ || defined(CONFIG_USB_MUSB_DSPS_MODULE)
+static ushort fifo_mode = 4;
+#elif defined(CONFIG_USB_MUSB_UX500) \
+ || defined(CONFIG_USB_MUSB_UX500_MODULE)
+static ushort fifo_mode = 5;
+#else
+static ushort fifo_mode = 2;
+#endif
+
+/*
+ * tables defining fifo_mode values. define more if you like.
+ * for host side, make sure both halves of ep1 are set up.
+ */
+
+/* mode 0 - fits in 2KB */
+static struct musb_fifo_cfg mode_0_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
+{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
+};
+
+/* mode 1 - fits in 4KB */
+static struct musb_fifo_cfg mode_1_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, },
+{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, },
+{ .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, },
+{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
+{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
+};
+
+/* mode 2 - fits in 4KB */
+static struct musb_fifo_cfg mode_2_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
+{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
+};
+
+/* mode 3 - fits in 4KB */
+static struct musb_fifo_cfg mode_3_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, },
+{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, },
+{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
+{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
+};
+
+/* mode 4 - fits in 16KB */
+static struct musb_fifo_cfg mode_4_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 8, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 256, },
+{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 64, },
+{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 256, },
+{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 64, },
+{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 256, },
+{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 64, },
+{ .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 4096, },
+{ .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, },
+{ .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, },
+};
+
+/* mode 5 - fits in 8KB */
+static struct musb_fifo_cfg mode_5_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 32, },
+{ .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 32, },
+{ .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 32, },
+{ .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 32, },
+{ .hw_ep_num = 8, .style = FIFO_TX, .maxpacket = 32, },
+{ .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 32, },
+{ .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 32, },
+{ .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 32, },
+{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 32, },
+{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 32, },
+{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 32, },
+{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 32, },
+{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 32, },
+{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 32, },
+{ .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 512, },
+{ .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, },
+{ .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, },
+};
+
+/*
+ * configure a fifo; for non-shared endpoints, this may be called
+ * once for a tx fifo and once for an rx fifo.
+ *
+ * returns negative errno or offset for next fifo.
+ */
+static int
+fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep,
+ const struct musb_fifo_cfg *cfg, u16 offset)
+{
+ void __iomem *mbase = musb->mregs;
+ int size = 0;
+ u16 maxpacket = cfg->maxpacket;
+ u16 c_off = offset >> 3;
+ u8 c_size;
+
+ /* expect hw_ep has already been zero-initialized */
+
+ size = ffs(max(maxpacket, (u16) 8)) - 1;
+ maxpacket = 1 << size;
+
+ c_size = size - 3;
+ if (cfg->mode == BUF_DOUBLE) {
+ if ((offset + (maxpacket << 1)) >
+ (1 << (musb->config->ram_bits + 2)))
+ return -EMSGSIZE;
+ c_size |= MUSB_FIFOSZ_DPB;
+ } else {
+ if ((offset + maxpacket) > (1 << (musb->config->ram_bits + 2)))
+ return -EMSGSIZE;
+ }
+
+ /* configure the FIFO */
+ musb_writeb(mbase, MUSB_INDEX, hw_ep->epnum);
+
+ /* EP0 reserved endpoint for control, bidirectional;
+ * EP1 reserved for bulk, two unidirectional halves.
+ */
+ if (hw_ep->epnum == 1)
+ musb->bulk_ep = hw_ep;
+ /* REVISIT error check: be sure ep0 can both rx and tx ... */
+ switch (cfg->style) {
+ case FIFO_TX:
+ musb_write_txfifosz(mbase, c_size);
+ musb_write_txfifoadd(mbase, c_off);
+ hw_ep->tx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);
+ hw_ep->max_packet_sz_tx = maxpacket;
+ break;
+ case FIFO_RX:
+ musb_write_rxfifosz(mbase, c_size);
+ musb_write_rxfifoadd(mbase, c_off);
+ hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);
+ hw_ep->max_packet_sz_rx = maxpacket;
+ break;
+ case FIFO_RXTX:
+ musb_write_txfifosz(mbase, c_size);
+ musb_write_txfifoadd(mbase, c_off);
+ hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);
+ hw_ep->max_packet_sz_rx = maxpacket;
+
+ musb_write_rxfifosz(mbase, c_size);
+ musb_write_rxfifoadd(mbase, c_off);
+ hw_ep->tx_double_buffered = hw_ep->rx_double_buffered;
+ hw_ep->max_packet_sz_tx = maxpacket;
+
+ hw_ep->is_shared_fifo = true;
+ break;
+ }
+
+ /* NOTE rx and tx endpoint irqs aren't managed separately,
+ * which happens to be ok
+ */
+ musb->epmask |= (1 << hw_ep->epnum);
+
+ return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0));
+}
+
+static struct musb_fifo_cfg ep0_cfg = {
+ .style = FIFO_RXTX, .maxpacket = 64,
+};
+
+static int ep_config_from_table(struct musb *musb)
+{
+ const struct musb_fifo_cfg *cfg;
+ unsigned i, n;
+ int offset;
+ struct musb_hw_ep *hw_ep = musb->endpoints;
+
+ if (musb->config->fifo_cfg) {
+ cfg = musb->config->fifo_cfg;
+ n = musb->config->fifo_cfg_size;
+ goto done;
+ }
+
+ switch (fifo_mode) {
+ default:
+ fifo_mode = 0;
+ /* FALLTHROUGH */
+ case 0:
+ cfg = mode_0_cfg;
+ n = ARRAY_SIZE(mode_0_cfg);
+ break;
+ case 1:
+ cfg = mode_1_cfg;
+ n = ARRAY_SIZE(mode_1_cfg);
+ break;
+ case 2:
+ cfg = mode_2_cfg;
+ n = ARRAY_SIZE(mode_2_cfg);
+ break;
+ case 3:
+ cfg = mode_3_cfg;
+ n = ARRAY_SIZE(mode_3_cfg);
+ break;
+ case 4:
+ cfg = mode_4_cfg;
+ n = ARRAY_SIZE(mode_4_cfg);
+ break;
+ case 5:
+ cfg = mode_5_cfg;
+ n = ARRAY_SIZE(mode_5_cfg);
+ break;
+ }
+
+ printk(KERN_DEBUG "%s: setup fifo_mode %d\n",
+ musb_driver_name, fifo_mode);
+
+
+done:
+ offset = fifo_setup(musb, hw_ep, &ep0_cfg, 0);
+ /* assert(offset > 0) */
+
+ /* NOTE: for RTL versions >= 1.400 EPINFO and RAMINFO would
+ * be better than static musb->config->num_eps and DYN_FIFO_SIZE...
+ */
+
+ for (i = 0; i < n; i++) {
+ u8 epn = cfg->hw_ep_num;
+
+ if (epn >= musb->config->num_eps) {
+ pr_debug("%s: invalid ep %d\n",
+ musb_driver_name, epn);
+ return -EINVAL;
+ }
+ offset = fifo_setup(musb, hw_ep + epn, cfg++, offset);
+ if (offset < 0) {
+ pr_debug("%s: mem overrun, ep %d\n",
+ musb_driver_name, epn);
+ return offset;
+ }
+ epn++;
+ musb->nr_endpoints = max(epn, musb->nr_endpoints);
+ }
+
+ printk(KERN_DEBUG "%s: %d/%d max ep, %d/%d memory\n",
+ musb_driver_name,
+ n + 1, musb->config->num_eps * 2 - 1,
+ offset, (1 << (musb->config->ram_bits + 2)));
+
+ if (!musb->bulk_ep) {
+ pr_debug("%s: missing bulk\n", musb_driver_name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+/*
+ * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false
+ * @param musb the controller
+ */
+static int ep_config_from_hw(struct musb *musb)
+{
+ u8 epnum = 0;
+ struct musb_hw_ep *hw_ep;
+ void __iomem *mbase = musb->mregs;
+ int ret = 0;
+
+ dev_dbg(musb->controller, "<== static silicon ep config\n");
+
+ /* FIXME pick up ep0 maxpacket size */
+
+ for (epnum = 1; epnum < musb->config->num_eps; epnum++) {
+ musb_ep_select(mbase, epnum);
+ hw_ep = musb->endpoints + epnum;
+
+ ret = musb_read_fifosize(musb, hw_ep, epnum);
+ if (ret < 0)
+ break;
+
+ /* FIXME set up hw_ep->{rx,tx}_double_buffered */
+
+ /* pick an RX/TX endpoint for bulk */
+ if (hw_ep->max_packet_sz_tx < 512
+ || hw_ep->max_packet_sz_rx < 512)
+ continue;
+
+ /* REVISIT: this algorithm is lazy, we should at least
+ * try to pick a double buffered endpoint.
+ */
+ if (musb->bulk_ep)
+ continue;
+ musb->bulk_ep = hw_ep;
+ }
+
+ if (!musb->bulk_ep) {
+ pr_debug("%s: missing bulk\n", musb_driver_name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, };
+
+/* Initialize MUSB (M)HDRC part of the USB hardware subsystem;
+ * configure endpoints, or take their config from silicon
+ */
+static int musb_core_init(u16 musb_type, struct musb *musb)
+{
+ u8 reg;
+ char *type;
+ char aInfo[90], aRevision[32], aDate[12];
+ void __iomem *mbase = musb->mregs;
+ int status = 0;
+ int i;
+
+ /* log core options (read using indexed model) */
+ reg = musb_read_configdata(mbase);
+
+ strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8");
+ if (reg & MUSB_CONFIGDATA_DYNFIFO) {
+ strcat(aInfo, ", dyn FIFOs");
+ musb->dyn_fifo = true;
+ }
+ if (reg & MUSB_CONFIGDATA_MPRXE) {
+ strcat(aInfo, ", bulk combine");
+ musb->bulk_combine = true;
+ }
+ if (reg & MUSB_CONFIGDATA_MPTXE) {
+ strcat(aInfo, ", bulk split");
+ musb->bulk_split = true;
+ }
+ if (reg & MUSB_CONFIGDATA_HBRXE) {
+ strcat(aInfo, ", HB-ISO Rx");
+ musb->hb_iso_rx = true;
+ }
+ if (reg & MUSB_CONFIGDATA_HBTXE) {
+ strcat(aInfo, ", HB-ISO Tx");
+ musb->hb_iso_tx = true;
+ }
+ if (reg & MUSB_CONFIGDATA_SOFTCONE)
+ strcat(aInfo, ", SoftConn");
+
+ printk(KERN_DEBUG "%s: ConfigData=0x%02x (%s)\n",
+ musb_driver_name, reg, aInfo);
+
+ aDate[0] = 0;
+ if (MUSB_CONTROLLER_MHDRC == musb_type) {
+ musb->is_multipoint = 1;
+ type = "M";
+ } else {
+ musb->is_multipoint = 0;
+ type = "";
+#ifndef CONFIG_USB_OTG_BLACKLIST_HUB
+ printk(KERN_ERR
+ "%s: kernel must blacklist external hubs\n",
+ musb_driver_name);
+#endif
+ }
+
+ /* log release info */
+ musb->hwvers = musb_read_hwvers(mbase);
+ snprintf(aRevision, 32, "%d.%d%s", MUSB_HWVERS_MAJOR(musb->hwvers),
+ MUSB_HWVERS_MINOR(musb->hwvers),
+ (musb->hwvers & MUSB_HWVERS_RC) ? "RC" : "");
+ printk(KERN_DEBUG "%s: %sHDRC RTL version %s %s\n",
+ musb_driver_name, type, aRevision, aDate);
+
+ /* configure ep0 */
+ musb_configure_ep0(musb);
+
+ /* discover endpoint configuration */
+ musb->nr_endpoints = 1;
+ musb->epmask = 1;
+
+ if (musb->dyn_fifo)
+ status = ep_config_from_table(musb);
+ else
+ status = ep_config_from_hw(musb);
+
+ if (status < 0)
+ return status;
+
+ /* finish init, and print endpoint config */
+ for (i = 0; i < musb->nr_endpoints; i++) {
+ struct musb_hw_ep *hw_ep = musb->endpoints + i;
+
+ hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase;
+#if defined(CONFIG_USB_MUSB_TUSB6010) || defined (CONFIG_USB_MUSB_TUSB6010_MODULE)
+ hw_ep->fifo_async = musb->async + 0x400 + MUSB_FIFO_OFFSET(i);
+ hw_ep->fifo_sync = musb->sync + 0x400 + MUSB_FIFO_OFFSET(i);
+ hw_ep->fifo_sync_va =
+ musb->sync_va + 0x400 + MUSB_FIFO_OFFSET(i);
+
+ if (i == 0)
+ hw_ep->conf = mbase - 0x400 + TUSB_EP0_CONF;
+ else
+ hw_ep->conf = mbase + 0x400 + (((i - 1) & 0xf) << 2);
+#endif
+
+ hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase;
+ hw_ep->target_regs = musb_read_target_reg_base(i, mbase);
+ hw_ep->rx_reinit = 1;
+ hw_ep->tx_reinit = 1;
+
+ if (hw_ep->max_packet_sz_tx) {
+ dev_dbg(musb->controller,
+ "%s: hw_ep %d%s, %smax %d\n",
+ musb_driver_name, i,
+ hw_ep->is_shared_fifo ? "shared" : "tx",
+ hw_ep->tx_double_buffered
+ ? "doublebuffer, " : "",
+ hw_ep->max_packet_sz_tx);
+ }
+ if (hw_ep->max_packet_sz_rx && !hw_ep->is_shared_fifo) {
+ dev_dbg(musb->controller,
+ "%s: hw_ep %d%s, %smax %d\n",
+ musb_driver_name, i,
+ "rx",
+ hw_ep->rx_double_buffered
+ ? "doublebuffer, " : "",
+ hw_ep->max_packet_sz_rx);
+ }
+ if (!(hw_ep->max_packet_sz_tx || hw_ep->max_packet_sz_rx))
+ dev_dbg(musb->controller, "hw_ep %d not configured\n", i);
+ }
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * handle all the irqs defined by the HDRC core. for now we expect: other
+ * irq sources (phy, dma, etc) will be handled first, musb->int_* values
+ * will be assigned, and the irq will already have been acked.
+ *
+ * called in irq context with spinlock held, irqs blocked
+ */
+irqreturn_t musb_interrupt(struct musb *musb)
+{
+ irqreturn_t retval = IRQ_NONE;
+ u8 devctl;
+ int ep_num;
+ u32 reg;
+
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+ dev_dbg(musb->controller, "** IRQ %s usb%04x tx%04x rx%04x\n",
+ is_host_active(musb) ? "host" : "peripheral",
+ musb->int_usb, musb->int_tx, musb->int_rx);
+
+ /* "stage 1" is handling endpoint irqs */
+
+ /* handle endpoint 0 first */
+ if (musb->int_tx & 1) {
+ if (is_host_active(musb))
+ retval |= musb_h_ep0_irq(musb);
+ else
+ retval |= musb_g_ep0_irq(musb);
+ }
+
+ /* RX on endpoints 1-15 */
+ reg = musb->int_rx >> 1;
+ ep_num = 1;
+ while (reg) {
+ if (reg & 1) {
+ /* musb_ep_select(musb->mregs, ep_num); */
+ /* REVISIT just retval = ep->rx_irq(...) */
+ retval = IRQ_HANDLED;
+ if (is_host_active(musb))
+ musb_host_rx(musb, ep_num);
+ else
+ musb_g_rx(musb, ep_num);
+ }
+
+ reg >>= 1;
+ ep_num++;
+ }
+
+ /* TX on endpoints 1-15 */
+ reg = musb->int_tx >> 1;
+ ep_num = 1;
+ while (reg) {
+ if (reg & 1) {
+ /* musb_ep_select(musb->mregs, ep_num); */
+ /* REVISIT just retval |= ep->tx_irq(...) */
+ retval = IRQ_HANDLED;
+ if (is_host_active(musb))
+ musb_host_tx(musb, ep_num);
+ else
+ musb_g_tx(musb, ep_num);
+ }
+ reg >>= 1;
+ ep_num++;
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL_GPL(musb_interrupt);
+
+/* --------------------------------------------------------------------------
+ * Init support
+ */
+
+static struct musb *musb_init_instance(struct musb *musb,
+ struct musb_hdrc_config *config)
+{
+ struct musb_hw_ep *ep;
+ int epnum;
+ int ret;
+
+ INIT_LIST_HEAD(&musb->control);
+ INIT_LIST_HEAD(&musb->in_bulk);
+ INIT_LIST_HEAD(&musb->out_bulk);
+
+ musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
+ musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON;
+ musb->nIrq = -ENODEV;
+ musb->config = config;
+ BUG_ON(musb->config->num_eps > MUSB_C_NUM_EPS);
+ for (epnum = 0, ep = musb->endpoints;
+ epnum < musb->config->num_eps;
+ epnum++, ep++) {
+ ep->musb = musb;
+ ep->epnum = epnum;
+ }
+
+ ret = musb_host_alloc(musb);
+ if (ret < 0)
+ goto err_free;
+
+ return musb;
+
+err_free:
+ return NULL;
+}
+
+static void musb_free(struct musb *musb)
+{
+ /* this has multiple entry modes. it handles fault cleanup after
+ * probe(), where things may be partially set up, as well as rmmod
+ * cleanup after everything's been de-activated.
+ */
+
+ musb_host_free(musb);
+}
+
+int musb_init(struct usb_host *host)
+{
+ struct musb *musb = to_musb(host);
+ void *mbase;
+ int timeout = MUSB_HOST_TIMEOUT;
+ u8 power;
+
+ musb_start(musb);
+ mbase = musb->mregs;
+ do {
+ if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM)
+ break;
+ } while (--timeout);
+ if (!timeout)
+ return -ENODEV;
+
+ power = musb_readb(mbase, MUSB_POWER);
+ musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power);
+ udelay(30000);
+ power = musb_readb(mbase, MUSB_POWER);
+ musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power);
+
+ musb->isr(musb);
+ udelay(30000); /* necessary for proper hub detection */
+ musb->host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
+ USB_SPEED_HIGH :
+ (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_FSDEV) ?
+ USB_SPEED_FULL : USB_SPEED_LOW;
+ musb->is_active = 1;
+
+ return 0;
+}
+
+/*
+ * Perform generic per-controller initialization.
+ *
+ * @dev: the controller (already clocked, etc)
+ * @nIrq: IRQ number
+ * @ctrl: virtual address of controller registers,
+ * not yet corrected for platform-specific offsets
+ */
+int
+musb_init_controller(struct musb *musb, struct musb_hdrc_platform_data *plat)
+{
+ int status;
+
+ /* allocate */
+ musb = musb_init_instance(musb, plat->config);
+ if (!musb) {
+ status = -ENOMEM;
+ goto fail0;
+ }
+
+ musb->board_set_power = plat->set_power;
+ musb->min_power = plat->min_power;
+ musb->ops = plat->platform_ops;
+ musb->port_mode = plat->mode;
+
+ /* The musb_platform_init() call:
+ * - adjusts musb->mregs
+ * - sets the musb->isr
+ * - may initialize an integrated transceiver
+ * - initializes musb->xceiv, usually by otg_get_phy()
+ * - stops powering VBUS
+ *
+ * There are various transceiver configurations. Blackfin,
+ * DaVinci, TUSB60x0, and others integrate them. OMAP3 uses
+ * external/discrete ones in various flavors (twl4030 family,
+ * isp1504, non-OTG, etc) mostly hooking up through ULPI.
+ */
+ status = musb_platform_init(musb);
+ if (status < 0)
+ goto fail1;
+
+ if (!musb->isr) {
+ status = -ENODEV;
+ goto fail2;
+ }
+
+ /* be sure interrupts are disabled before connecting ISR */
+ musb_platform_disable(musb);
+ musb_generic_disable(musb);
+
+ /* setup musb parts of the core (especially endpoints) */
+ status = musb_core_init(plat->config->multipoint
+ ? MUSB_CONTROLLER_MHDRC
+ : MUSB_CONTROLLER_HDRC, musb);
+ if (status < 0)
+ goto fail3;
+
+ switch (musb->port_mode) {
+ case MUSB_PORT_MODE_HOST:
+ status = musb_host_setup(musb, plat->power);
+ break;
+ case MUSB_PORT_MODE_GADGET:
+ status = musb_gadget_setup(musb);
+ break;
+ case MUSB_PORT_MODE_DUAL_ROLE:
+ status = musb_host_setup(musb, plat->power);
+ if (status < 0)
+ goto fail3;
+ status = musb_gadget_setup(musb);
+ if (status < 0)
+ goto fail3;
+ break;
+ default:
+ dev_err(musb->controller, "unsupported port mode %d\n", musb->port_mode);
+ break;
+ }
+
+ if (status < 0)
+ goto fail3;
+
+ if (IS_ENABLED(CONFIG_USB_MUSB_HOST) && plat->mode == USB_DR_MODE_HOST)
+ musb_register(musb);
+
+ return 0;
+
+fail3:
+fail2:
+ musb_platform_exit(musb);
+
+fail1:
+ dev_err(musb->controller,
+ "musb_init_controller failed with status %d\n", status);
+
+ musb_free(musb);
+
+fail0:
+
+ return status;
+
+}
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
new file mode 100644
index 0000000000..46265d6190
--- /dev/null
+++ b/drivers/usb/musb/musb_core.h
@@ -0,0 +1,585 @@
+/*
+ * MUSB OTG driver defines
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_CORE_H__
+#define __MUSB_CORE_H__
+
+#include <poller.h>
+#include <notifier.h>
+#include <usb/usb.h>
+#include <usb/phy.h>
+
+struct musb;
+struct musb_hw_ep;
+struct musb_ep;
+
+/* Helper defines for struct musb->hwvers */
+#define MUSB_HWVERS_MAJOR(x) ((x >> 10) & 0x1f)
+#define MUSB_HWVERS_MINOR(x) (x & 0x3ff)
+#define MUSB_HWVERS_RC 0x8000
+#define MUSB_HWVERS_1300 0x52C
+#define MUSB_HWVERS_1400 0x590
+#define MUSB_HWVERS_1800 0x720
+#define MUSB_HWVERS_1900 0x784
+#define MUSB_HWVERS_2000 0x800
+
+#include "musb_dma.h"
+
+#include "musb_io.h"
+#include "musb_regs.h"
+
+#include "musb_gadget.h"
+#include "musb_host.h"
+
+/* NOTE: otg and peripheral-only state machines start at B_IDLE.
+ * OTG or host-only go to A_IDLE when ID is sensed.
+ */
+#define is_peripheral_active(m) (!(m)->is_host)
+#define is_host_active(m) ((m)->is_host)
+
+enum {
+ MUSB_PORT_MODE_HOST = 1,
+ MUSB_PORT_MODE_GADGET,
+ MUSB_PORT_MODE_DUAL_ROLE,
+};
+
+/****************************** CONSTANTS ********************************/
+
+#ifndef MUSB_C_NUM_EPS
+#define MUSB_C_NUM_EPS ((u8)16)
+#endif
+
+#ifndef MUSB_MAX_END0_PACKET
+#define MUSB_MAX_END0_PACKET ((u16)MUSB_EP0_FIFOSIZE)
+#endif
+
+/* host side ep0 states */
+enum musb_h_ep0_state {
+ MUSB_EP0_IDLE,
+ MUSB_EP0_START, /* expect ack of setup */
+ MUSB_EP0_IN, /* expect IN DATA */
+ MUSB_EP0_OUT, /* expect ack of OUT DATA */
+ MUSB_EP0_STATUS, /* expect ack of STATUS */
+} __attribute__ ((packed));
+
+/* peripheral side ep0 states */
+enum musb_g_ep0_state {
+ MUSB_EP0_STAGE_IDLE, /* idle, waiting for SETUP */
+ MUSB_EP0_STAGE_SETUP, /* received SETUP */
+ MUSB_EP0_STAGE_TX, /* IN data */
+ MUSB_EP0_STAGE_RX, /* OUT data */
+ MUSB_EP0_STAGE_STATUSIN, /* (after OUT data) */
+ MUSB_EP0_STAGE_STATUSOUT, /* (after IN data) */
+ MUSB_EP0_STAGE_ACKWAIT, /* after zlp, before statusin */
+} __attribute__ ((packed));
+
+/*
+ * OTG protocol constants. See USB OTG 1.3 spec,
+ * sections 5.5 "Device Timings" and 6.6.5 "Timers".
+ */
+#define OTG_TIME_A_WAIT_VRISE 100 /* msec (max) */
+#define OTG_TIME_A_WAIT_BCON 1100 /* min 1 second */
+#define OTG_TIME_A_AIDL_BDIS 200 /* min 200 msec */
+#define OTG_TIME_B_ASE0_BRST 100 /* min 3.125 ms */
+
+
+/*************************** REGISTER ACCESS ********************************/
+
+/* Endpoint registers (other than dynfifo setup) can be accessed either
+ * directly with the "flat" model, or after setting up an index register.
+ */
+
+#if defined(CONFIG_ARCH_DAVINCI) || defined(CONFIG_SOC_OMAP2430) \
+ || defined(CONFIG_SOC_OMAP3430) || defined(CONFIG_BLACKFIN) \
+ || defined(CONFIG_ARCH_OMAP4)
+/* REVISIT indexed access seemed to
+ * misbehave (on DaVinci) for at least peripheral IN ...
+ */
+#define MUSB_FLAT_REG
+#endif
+
+/* TUSB mapping: "flat" plus ep0 special cases */
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
+#define musb_ep_select(_mbase, _epnum) \
+ musb_writeb((_mbase), MUSB_INDEX, (_epnum))
+#define MUSB_EP_OFFSET MUSB_TUSB_OFFSET
+
+/* "flat" mapping: each endpoint has its own i/o address */
+#elif defined(MUSB_FLAT_REG)
+#define musb_ep_select(_mbase, _epnum) (((void)(_mbase)), ((void)(_epnum)))
+#define MUSB_EP_OFFSET MUSB_FLAT_OFFSET
+
+/* "indexed" mapping: INDEX register controls register bank select */
+#else
+#define musb_ep_select(_mbase, _epnum) \
+ musb_writeb((_mbase), MUSB_INDEX, (_epnum))
+#define MUSB_EP_OFFSET MUSB_INDEXED_OFFSET
+#endif
+
+/****************************** FUNCTIONS ********************************/
+
+#define MUSB_HST_MODE(_musb)\
+ { (_musb)->is_host = true; }
+#define MUSB_DEV_MODE(_musb) \
+ { (_musb)->is_host = false; }
+
+#define test_devctl_hst_mode(_x) \
+ (musb_readb((_x)->mregs, MUSB_DEVCTL)&MUSB_DEVCTL_HM)
+
+#define MUSB_MODE(musb) ((musb)->is_host ? "Host" : "Peripheral")
+
+/******************************** TYPES *************************************/
+
+/**
+ * struct musb_platform_ops - Operations passed to musb_core by HW glue layer
+ * @init: turns on clocks, sets up platform-specific registers, etc
+ * @exit: undoes @init
+ * @set_mode: forcefully changes operating mode
+ * @try_ilde: tries to idle the IP
+ * @vbus_status: returns vbus status if possible
+ * @set_vbus: forces vbus status
+ * @adjust_channel_params: pre check for standard dma channel_program func
+ */
+struct musb_platform_ops {
+ int (*init)(struct musb *musb);
+ int (*exit)(struct musb *musb);
+
+ void (*enable)(struct musb *musb);
+ void (*disable)(struct musb *musb);
+
+ int (*set_mode)(struct musb *musb, u8 mode);
+ void (*try_idle)(struct musb *musb, uint64_t timeout);
+ int (*reset)(struct musb *musb);
+
+ int (*vbus_status)(struct musb *musb);
+ void (*set_vbus)(struct musb *musb, int on);
+
+ int (*adjust_channel_params)(/*struct dma_channel *channel,*/
+ u16 packet_sz, u8 *mode,
+ dma_addr_t *dma_addr, u32 *len);
+};
+
+/*
+ * struct musb_hw_ep - endpoint hardware (bidirectional)
+ *
+ * Ordered slightly for better cacheline locality.
+ */
+struct musb_hw_ep {
+ struct musb *musb;
+ void __iomem *fifo;
+ void __iomem *regs;
+
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
+ void __iomem *conf;
+#endif
+
+ /* index in musb->endpoints[] */
+ u8 epnum;
+
+ /* hardware configuration, possibly dynamic */
+ bool is_shared_fifo;
+ bool tx_double_buffered;
+ bool rx_double_buffered;
+ u16 max_packet_sz_tx;
+ u16 max_packet_sz_rx;
+
+ struct dma_channel *tx_channel;
+ struct dma_channel *rx_channel;
+
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
+ /* TUSB has "asynchronous" and "synchronous" dma modes */
+ dma_addr_t fifo_async;
+ dma_addr_t fifo_sync;
+ void __iomem *fifo_sync_va;
+#endif
+
+ void __iomem *target_regs;
+
+ /* currently scheduled peripheral endpoint */
+ struct musb_qh *in_qh;
+ struct musb_qh *out_qh;
+
+ u8 rx_reinit;
+ u8 tx_reinit;
+
+ /* peripheral side */
+ struct musb_ep ep_in; /* TX */
+ struct musb_ep ep_out; /* RX */
+};
+
+static inline struct musb_request *next_in_request(struct musb_hw_ep *hw_ep)
+{
+ return next_request(&hw_ep->ep_in);
+}
+
+static inline struct musb_request *next_out_request(struct musb_hw_ep *hw_ep)
+{
+ return next_request(&hw_ep->ep_out);
+}
+
+struct musb_csr_regs {
+ /* FIFO registers */
+ u16 txmaxp, txcsr, rxmaxp, rxcsr;
+ u16 rxfifoadd, txfifoadd;
+ u8 txtype, txinterval, rxtype, rxinterval;
+ u8 rxfifosz, txfifosz;
+ u8 txfunaddr, txhubaddr, txhubport;
+ u8 rxfunaddr, rxhubaddr, rxhubport;
+};
+
+struct musb_context_registers {
+
+ u8 power;
+ u8 intrusbe;
+ u16 frame;
+ u8 index, testmode;
+
+ u8 devctl, busctl, misc;
+ u32 otg_interfsel;
+
+ struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
+};
+
+struct usb_phy;
+struct usb_otg;
+
+/*
+ * Allocated per bus (tree of devices) we have:
+ */
+struct usb_bus {
+ u8 otg_port; /* 0, or number of OTG/HNP port */
+ unsigned is_b_host:1; /* true during some HNP roleswitches */
+ unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */
+};
+
+struct usb_hcd {
+ struct usb_bus self;
+ void *hcd_priv;
+};
+
+#define to_musb(ptr) container_of(ptr, struct musb, host)
+
+/*
+ * struct musb - Driver instance data.
+ */
+struct musb {
+ /* device lock */
+ spinlock_t lock;
+
+ const struct musb_platform_ops *ops;
+
+ int (*isr)(struct musb *);
+ u16 hwvers;
+
+ u16 intrrxe;
+ u16 intrtxe;
+/* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
+#define MUSB_PORT_STAT_RESUME (1 << 31)
+
+ u32 port1_status;
+
+ uint64_t rh_timer;
+
+ enum musb_h_ep0_state ep0_stage;
+
+ /* bulk traffic normally dedicates endpoint hardware, and each
+ * direction has its own ring of host side endpoints.
+ * we try to progress the transfer at the head of each endpoint's
+ * queue until it completes or NAKs too much; then we try the next
+ * endpoint.
+ */
+ struct musb_hw_ep *bulk_ep;
+
+ struct list_head control; /* of musb_qh */
+ struct list_head in_bulk; /* of musb_qh */
+ struct list_head out_bulk; /* of musb_qh */
+
+ struct poller_async otg_timer;
+
+ struct dma_controller *dma_controller;
+
+ struct device_d *controller;
+ void __iomem *ctrl_base;
+ void __iomem *mregs;
+
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
+ dma_addr_t async;
+ dma_addr_t sync;
+ void __iomem *sync_va;
+#endif
+
+ /* passed down from chip/board specific irq handlers */
+ u8 int_usb;
+ u16 int_rx;
+ u16 int_tx;
+
+ //struct device_d *phydev;
+ struct usb_host host;
+ struct usb_phy *xceiv;
+
+ int nIrq;
+ unsigned irq_wake:1;
+
+ struct musb_hw_ep endpoints[MUSB_C_NUM_EPS];
+#define control_ep endpoints
+
+#define VBUSERR_RETRY_COUNT 3
+ u16 vbuserr_retry;
+ u16 epmask;
+ u8 nr_endpoints;
+
+ int (*board_set_power)(int state);
+
+ u8 min_power; /* vbus for periph, in mA/2 */
+
+ int port_mode; /* MUSB_PORT_MODE_* */
+ bool is_host;
+
+ int a_wait_bcon; /* VBUS timeout in msecs */
+
+ /* active means connected and not suspended */
+ unsigned is_active:1;
+
+ unsigned is_multipoint:1;
+
+ unsigned hb_iso_rx:1; /* high bandwidth iso rx? */
+ unsigned hb_iso_tx:1; /* high bandwidth iso tx? */
+ unsigned dyn_fifo:1; /* dynamic FIFO supported? */
+
+ unsigned bulk_split:1;
+#define can_bulk_split(musb,type) \
+ (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_split)
+
+ unsigned bulk_combine:1;
+#define can_bulk_combine(musb,type) \
+ (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_combine)
+
+ /* is_suspended means USB B_PERIPHERAL suspend */
+ unsigned is_suspended:1;
+
+ /* may_wakeup means remote wakeup is enabled */
+ unsigned may_wakeup:1;
+
+ /* is_self_powered is reported in device status and the
+ * config descriptor. is_bus_powered means B_PERIPHERAL
+ * draws some VBUS current; both can be true.
+ */
+ unsigned is_self_powered:1;
+ unsigned is_bus_powered:1;
+
+ unsigned set_address:1;
+ unsigned test_mode:1;
+ unsigned softconnect:1;
+
+ u8 address;
+ u8 test_mode_nr;
+ u16 ackpend; /* ep0 */
+ enum musb_g_ep0_state ep0_state;
+ struct usb_gadget g; /* the gadget */
+ struct usb_gadget_driver *gadget_driver; /* its driver */
+ struct usb_hcd *hcd; /* the usb hcd */
+
+ /*
+ * FIXME: Remove this flag.
+ *
+ * This is only added to allow Blackfin to work
+ * with current driver. For some unknown reason
+ * Blackfin doesn't work with double buffering
+ * and that's enabled by default.
+ *
+ * We added this flag to forcefully disable double
+ * buffering until we get it working.
+ */
+ unsigned double_buffer_not_ok:1;
+
+ struct musb_hdrc_config *config;
+ int host_speed;
+};
+
+static inline struct musb *gadget_to_musb(struct usb_gadget *g)
+{
+ return container_of(g, struct musb, g);
+}
+
+#ifdef CONFIG_BLACKFIN
+static inline int musb_read_fifosize(struct musb *musb,
+ struct musb_hw_ep *hw_ep, u8 epnum)
+{
+ musb->nr_endpoints++;
+ musb->epmask |= (1 << epnum);
+
+ if (epnum < 5) {
+ hw_ep->max_packet_sz_tx = 128;
+ hw_ep->max_packet_sz_rx = 128;
+ } else {
+ hw_ep->max_packet_sz_tx = 1024;
+ hw_ep->max_packet_sz_rx = 1024;
+ }
+ hw_ep->is_shared_fifo = false;
+
+ return 0;
+}
+
+static inline void musb_configure_ep0(struct musb *musb)
+{
+ musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE;
+ musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE;
+ musb->endpoints[0].is_shared_fifo = true;
+}
+
+#else
+
+static inline int musb_read_fifosize(struct musb *musb,
+ struct musb_hw_ep *hw_ep, u8 epnum)
+{
+ void __iomem *mbase = musb->mregs;
+ u8 reg = 0;
+
+ /* read from core using indexed model */
+ reg = musb_readb(mbase, MUSB_EP_OFFSET(epnum, MUSB_FIFOSIZE));
+ /* 0's returned when no more endpoints */
+ if (!reg)
+ return -ENODEV;
+
+ musb->nr_endpoints++;
+ musb->epmask |= (1 << epnum);
+
+ hw_ep->max_packet_sz_tx = 1 << (reg & 0x0f);
+
+ /* shared TX/RX FIFO? */
+ if ((reg & 0xf0) == 0xf0) {
+ hw_ep->max_packet_sz_rx = hw_ep->max_packet_sz_tx;
+ hw_ep->is_shared_fifo = true;
+ return 0;
+ } else {
+ hw_ep->max_packet_sz_rx = 1 << ((reg & 0xf0) >> 4);
+ hw_ep->is_shared_fifo = false;
+ }
+
+ return 0;
+}
+
+static inline void musb_configure_ep0(struct musb *musb)
+{
+ musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE;
+ musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE;
+ musb->endpoints[0].is_shared_fifo = true;
+}
+#endif /* CONFIG_BLACKFIN */
+
+
+/***************************** Glue it together *****************************/
+
+extern const char musb_driver_name[];
+
+extern void musb_stop(struct musb *musb);
+extern void musb_start(struct musb *musb);
+
+extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src);
+extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst);
+
+extern void musb_load_testpacket(struct musb *);
+
+extern int musb_interrupt(struct musb *);
+
+extern void musb_hnp_stop(struct musb *musb);
+
+static inline void musb_platform_set_vbus(struct musb *musb, int is_on)
+{
+ if (musb->ops->set_vbus)
+ musb->ops->set_vbus(musb, is_on);
+}
+
+static inline void musb_platform_enable(struct musb *musb)
+{
+ if (musb->ops->enable)
+ musb->ops->enable(musb);
+}
+
+static inline void musb_platform_disable(struct musb *musb)
+{
+ if (musb->ops->disable)
+ musb->ops->disable(musb);
+}
+
+static inline void musb_platform_try_idle(struct musb *musb,
+ uint64_t timeout)
+{
+ if (musb->ops->try_idle)
+ musb->ops->try_idle(musb, timeout);
+}
+
+static inline int musb_platform_reset(struct musb *musb)
+{
+ if (!musb->ops->reset)
+ return -EINVAL;
+
+ return musb->ops->reset(musb);
+}
+
+static inline int musb_platform_get_vbus_status(struct musb *musb)
+{
+ if (!musb->ops->vbus_status)
+ return 0;
+
+ return musb->ops->vbus_status(musb);
+}
+
+static inline int musb_platform_init(struct musb *musb)
+{
+ if (!musb->ops->init)
+ return -EINVAL;
+
+ return musb->ops->init(musb);
+}
+
+static inline int musb_platform_exit(struct musb *musb)
+{
+ if (!musb->ops->exit)
+ return -EINVAL;
+
+ return musb->ops->exit(musb);
+}
+
+struct musb_hdrc_platform_data;
+
+int musb_init_controller(struct musb *musb, struct musb_hdrc_platform_data *plat);
+int musb_register(struct musb *data);
+int musb_init(struct usb_host *host);
+
+#endif /* __MUSB_CORE_H__ */
diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
new file mode 100644
index 0000000000..1345a4ff04
--- /dev/null
+++ b/drivers/usb/musb/musb_dma.h
@@ -0,0 +1,194 @@
+/*
+ * MUSB OTG driver DMA controller abstraction
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_DMA_H__
+#define __MUSB_DMA_H__
+
+struct musb_hw_ep;
+
+/*
+ * DMA Controller Abstraction
+ *
+ * DMA Controllers are abstracted to allow use of a variety of different
+ * implementations of DMA, as allowed by the Inventra USB cores. On the
+ * host side, usbcore sets up the DMA mappings and flushes caches; on the
+ * peripheral side, the gadget controller driver does. Responsibilities
+ * of a DMA controller driver include:
+ *
+ * - Handling the details of moving multiple USB packets
+ * in cooperation with the Inventra USB core, including especially
+ * the correct RX side treatment of short packets and buffer-full
+ * states (both of which terminate transfers).
+ *
+ * - Knowing the correlation between dma channels and the
+ * Inventra core's local endpoint resources and data direction.
+ *
+ * - Maintaining a list of allocated/available channels.
+ *
+ * - Updating channel status on interrupts,
+ * whether shared with the Inventra core or separate.
+ */
+
+#define DMA_ADDR_INVALID (~(dma_addr_t)0)
+
+#ifdef CONFIG_MUSB_PIO_ONLY
+#define is_dma_capable() (0)
+#else
+#define is_dma_capable() (1)
+#endif
+
+#if defined(CONFIG_USB_TI_CPPI_DMA) || defined(CONFIG_USB_TI_CPPI41_DMA)
+#define is_cppi_enabled() 1
+#else
+#define is_cppi_enabled() 0
+#endif
+
+#ifdef CONFIG_USB_TUSB_OMAP_DMA
+#define tusb_dma_omap() 1
+#else
+#define tusb_dma_omap() 0
+#endif
+
+/* Anomaly 05000456 - USB Receive Interrupt Is Not Generated in DMA Mode 1
+ * Only allow DMA mode 1 to be used when the USB will actually generate the
+ * interrupts we expect.
+ */
+#ifdef CONFIG_BLACKFIN
+# undef USE_MODE1
+# if !ANOMALY_05000456
+# define USE_MODE1
+# endif
+#endif
+
+/*
+ * DMA channel status ... updated by the dma controller driver whenever that
+ * status changes, and protected by the overall controller spinlock.
+ */
+enum dma_channel_status {
+ /* unallocated */
+ MUSB_DMA_STATUS_UNKNOWN,
+ /* allocated ... but not busy, no errors */
+ MUSB_DMA_STATUS_FREE,
+ /* busy ... transactions are active */
+ MUSB_DMA_STATUS_BUSY,
+ /* transaction(s) aborted due to ... dma or memory bus error */
+ MUSB_DMA_STATUS_BUS_ABORT,
+ /* transaction(s) aborted due to ... core error or USB fault */
+ MUSB_DMA_STATUS_CORE_ABORT
+};
+
+struct dma_controller;
+
+/**
+ * struct dma_channel - A DMA channel.
+ * @private_data: channel-private data
+ * @max_len: the maximum number of bytes the channel can move in one
+ * transaction (typically representing many USB maximum-sized packets)
+ * @actual_len: how many bytes have been transferred
+ * @status: current channel status (updated e.g. on interrupt)
+ * @desired_mode: true if mode 1 is desired; false if mode 0 is desired
+ *
+ * channels are associated with an endpoint for the duration of at least
+ * one usb transfer.
+ */
+struct dma_channel {
+ void *private_data;
+ /* FIXME not void* private_data, but a dma_controller * */
+ size_t max_len;
+ size_t actual_len;
+ enum dma_channel_status status;
+ bool desired_mode;
+};
+
+/*
+ * dma_channel_status - return status of dma channel
+ * @c: the channel
+ *
+ * Returns the software's view of the channel status. If that status is BUSY
+ * then it's possible that the hardware has completed (or aborted) a transfer,
+ * so the driver needs to update that status.
+ */
+static inline enum dma_channel_status
+dma_channel_status(struct dma_channel *c)
+{
+ return (is_dma_capable() && c) ? c->status : MUSB_DMA_STATUS_UNKNOWN;
+}
+
+/**
+ * struct dma_controller - A DMA Controller.
+ * @start: call this to start a DMA controller;
+ * return 0 on success, else negative errno
+ * @stop: call this to stop a DMA controller
+ * return 0 on success, else negative errno
+ * @channel_alloc: call this to allocate a DMA channel
+ * @channel_release: call this to release a DMA channel
+ * @channel_abort: call this to abort a pending DMA transaction,
+ * returning it to FREE (but allocated) state
+ *
+ * Controllers manage dma channels.
+ */
+struct dma_controller {
+ struct dma_channel *(*channel_alloc)(struct dma_controller *,
+ struct musb_hw_ep *, u8 is_tx);
+ void (*channel_release)(struct dma_channel *);
+ int (*channel_program)(struct dma_channel *channel,
+ u16 maxpacket, u8 mode,
+ dma_addr_t dma_addr,
+ u32 length);
+ int (*channel_abort)(struct dma_channel *);
+ int (*is_compatible)(struct dma_channel *channel,
+ u16 maxpacket,
+ void *buf, u32 length);
+};
+
+/* called after channel_program(), may indicate a fault */
+extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit);
+
+#ifdef CONFIG_MUSB_PIO_ONLY
+static inline struct dma_controller *dma_controller_create(struct musb *m,
+ void __iomem *io)
+{
+ return NULL;
+}
+
+static inline void dma_controller_destroy(struct dma_controller *d) { }
+
+#else
+
+extern struct dma_controller *dma_controller_create(struct musb *, void __iomem *);
+
+extern void dma_controller_destroy(struct dma_controller *);
+#endif
+
+#endif /* __MUSB_DMA_H__ */
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
new file mode 100644
index 0000000000..36a316ab37
--- /dev/null
+++ b/drivers/usb/musb/musb_dsps.c
@@ -0,0 +1,464 @@
+/*
+ * Texas Instruments DSPS platforms "glue layer"
+ *
+ * Copyright (C) 2012, by Texas Instruments
+ *
+ * Based on the am35x "glue layer" code.
+ *
+ * This file is part of the Inventra Controller Driver for Linux.
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 2 as published by the Free Software
+ * Foundation.
+ *
+ * The Inventra Controller Driver for Linux 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 The Inventra Controller Driver for Linux ; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * musb_dsps.c will be a common file for all the TI DSPS platforms
+ * such as dm64x, dm36x, dm35x, da8x, am35x and ti81x.
+ * For now only ti81x is using this and in future davinci.c, am35x.c
+ * da8xx.c would be merged to this file after testing.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <clock.h>
+#include <usb/usb.h>
+#include <usb/musb.h>
+#include <malloc.h>
+#include <linux/err.h>
+#include <linux/barebox-wrapper.h>
+
+#include "musb_core.h"
+#include "phy-am335x.h"
+
+static __maybe_unused struct of_device_id musb_dsps_dt_ids[];
+
+/**
+ * avoid using musb_readx()/musb_writex() as glue layer should not be
+ * dependent on musb core layer symbols.
+ */
+static inline u8 dsps_readb(const void __iomem *addr, unsigned offset)
+{
+ return __raw_readb(addr + offset);
+}
+
+static inline u32 dsps_readl(const void __iomem *addr, unsigned offset)
+{
+ return __raw_readl(addr + offset);
+}
+
+static inline void dsps_writeb(void __iomem *addr, unsigned offset, u8 data)
+{
+ __raw_writeb(data, addr + offset);
+}
+
+static inline void dsps_writel(void __iomem *addr, unsigned offset, u32 data)
+{
+ __raw_writel(data, addr + offset);
+}
+
+/**
+ * DSPS musb wrapper register offset.
+ * FIXME: This should be expanded to have all the wrapper registers from TI DSPS
+ * musb ips.
+ */
+struct dsps_musb_wrapper {
+ u16 revision;
+ u16 control;
+ u16 status;
+ u16 epintr_set;
+ u16 epintr_clear;
+ u16 epintr_status;
+ u16 coreintr_set;
+ u16 coreintr_clear;
+ u16 coreintr_status;
+ u16 phy_utmi;
+ u16 mode;
+
+ /* bit positions for control */
+ unsigned reset:5;
+
+ /* bit positions for interrupt */
+ unsigned usb_shift:5;
+ u32 usb_mask;
+ u32 usb_bitmap;
+ unsigned drvvbus:5;
+
+ unsigned txep_shift:5;
+ u32 txep_mask;
+ u32 txep_bitmap;
+
+ unsigned rxep_shift:5;
+ u32 rxep_mask;
+ u32 rxep_bitmap;
+
+ /* bit positions for phy_utmi */
+ unsigned otg_disable:5;
+
+ /* bit positions for mode */
+ unsigned iddig:5;
+ /* miscellaneous stuff */
+ u8 poll_seconds;
+};
+
+/**
+ * DSPS glue structure.
+ */
+struct dsps_glue {
+ struct device_d *dev;
+ void __iomem *base;
+ unsigned long flags;
+ enum musb_mode mode;
+ struct musb musb;
+ struct musb_hdrc_config config;
+ const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
+ struct poller_async timer; /* otg_workaround timer */
+ uint64_t last_timer; /* last timer data for each instance */
+ struct device_d otg_dev;
+ uint32_t otgmode;
+ struct musb_hdrc_platform_data pdata;
+};
+
+/**
+ * dsps_musb_enable - enable interrupts
+ */
+static void dsps_musb_enable(struct musb *musb)
+{
+ struct device_d *dev = musb->controller;
+ struct device_d *pdev = dev;
+ struct dsps_glue *glue = pdev->priv;
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ void __iomem *reg_base = musb->ctrl_base;
+ u32 epmask, coremask;
+
+ /* Workaround: setup IRQs through both register sets. */
+ epmask = ((musb->epmask & wrp->txep_mask) << wrp->txep_shift) |
+ ((musb->epmask & wrp->rxep_mask) << wrp->rxep_shift);
+ coremask = (wrp->usb_bitmap & ~MUSB_INTR_SOF);
+
+ dsps_writel(reg_base, wrp->epintr_set, epmask);
+ dsps_writel(reg_base, wrp->coreintr_set, coremask);
+ /* Force the DRVVBUS IRQ so we can start polling for ID change. */
+ dsps_writel(reg_base, wrp->coreintr_set,
+ (1 << wrp->drvvbus) << wrp->usb_shift);
+}
+
+/**
+ * dsps_musb_disable - disable HDRC and flush interrupts
+ */
+static void dsps_musb_disable(struct musb *musb)
+{
+ struct device_d *dev = musb->controller;
+ struct device_d *pdev = dev;
+ struct dsps_glue *glue = pdev->priv;
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ void __iomem *reg_base = musb->ctrl_base;
+
+ dsps_writel(reg_base, wrp->coreintr_clear, wrp->usb_bitmap);
+ dsps_writel(reg_base, wrp->epintr_clear,
+ wrp->txep_bitmap | wrp->rxep_bitmap);
+ dsps_writeb(musb->mregs, MUSB_DEVCTL, 0);
+}
+
+static irqreturn_t dsps_interrupt(struct musb *musb)
+{
+ void __iomem *reg_base = musb->ctrl_base;
+ struct device_d *dev = musb->controller;
+ struct dsps_glue *glue = dev->priv;
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ unsigned long flags;
+ irqreturn_t ret = IRQ_NONE;
+ u32 epintr, usbintr;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ /* Get endpoint interrupts */
+ epintr = dsps_readl(reg_base, wrp->epintr_status);
+ musb->int_rx = (epintr & wrp->rxep_bitmap) >> wrp->rxep_shift;
+ musb->int_tx = (epintr & wrp->txep_bitmap) >> wrp->txep_shift;
+
+ if (epintr)
+ dsps_writel(reg_base, wrp->epintr_status, epintr);
+
+ /* Get usb core interrupts */
+ usbintr = dsps_readl(reg_base, wrp->coreintr_status);
+ if (!usbintr && !epintr)
+ goto out;
+
+ musb->int_usb = (usbintr & wrp->usb_bitmap) >> wrp->usb_shift;
+ if (usbintr)
+ dsps_writel(reg_base, wrp->coreintr_status, usbintr);
+
+ dev_dbg(musb->controller, "usbintr (%x) epintr(%x)\n",
+ usbintr, epintr);
+
+ if (musb->int_tx || musb->int_rx || musb->int_usb)
+ ret |= musb_interrupt(musb);
+
+out:
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ return ret;
+}
+
+static int dsps_musb_init(struct musb *musb)
+{
+ struct device_d *dev = musb->controller;
+ struct dsps_glue *glue = dev->priv;
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ u32 rev, val, mode;
+
+ musb->xceiv = am335x_get_usb_phy();
+ if (IS_ERR(musb->xceiv))
+ return PTR_ERR(musb->xceiv);
+
+ /* Returns zero if e.g. not clocked */
+ rev = dsps_readl(musb->ctrl_base, wrp->revision);
+ if (!rev)
+ return -ENODEV;
+
+ usb_phy_init(musb->xceiv);
+
+ /* Reset the musb */
+ dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset));
+
+ musb->isr = dsps_interrupt;
+
+ /* reset the otgdisable bit, needed for host mode to work */
+ val = dsps_readl(musb->ctrl_base, wrp->phy_utmi);
+ val &= ~(1 << wrp->otg_disable);
+ dsps_writel(musb->ctrl_base, wrp->phy_utmi, val);
+
+ mode = dsps_readl(musb->ctrl_base, wrp->mode);
+
+ switch (musb->port_mode) {
+ case MUSB_PORT_MODE_HOST:
+ mode &= ~0x100;
+ break;
+ case MUSB_PORT_MODE_GADGET:
+ mode |= 0x100;
+ break;
+ }
+
+ mode |= 0x80;
+ dsps_writel(musb->ctrl_base, wrp->mode, mode); /* IDDIG=0, IDDIG_MUX=1 */
+
+ return 0;
+}
+
+static int dsps_musb_exit(struct musb *musb)
+{
+ usb_phy_shutdown(musb->xceiv);
+ return 0;
+}
+
+static struct musb_platform_ops dsps_ops = {
+ .init = dsps_musb_init,
+ .exit = dsps_musb_exit,
+
+ .enable = dsps_musb_enable,
+ .disable = dsps_musb_disable,
+};
+
+static int get_int_prop(struct device_node *dn, const char *s)
+{
+ int ret;
+ u32 val;
+
+ ret = of_property_read_u32(dn, s, &val);
+ if (ret)
+ return 0;
+ return val;
+}
+
+static int get_musb_port_mode(struct device_d *dev)
+{
+ enum usb_dr_mode mode;
+
+ mode = of_usb_get_dr_mode(dev->device_node, NULL);
+ switch (mode) {
+ case USB_DR_MODE_HOST:
+ return MUSB_PORT_MODE_HOST;
+
+ case USB_DR_MODE_PERIPHERAL:
+ return MUSB_PORT_MODE_GADGET;
+
+ case USB_DR_MODE_UNKNOWN:
+ case USB_DR_MODE_OTG:
+ default:
+ if (!IS_ENABLED(CONFIG_USB_MUSB_HOST))
+ return MUSB_PORT_MODE_GADGET;
+ if (!IS_ENABLED(CONFIG_USB_MUSB_GADGET))
+ return MUSB_PORT_MODE_HOST;
+ return MUSB_PORT_MODE_DUAL_ROLE;
+ }
+}
+
+static int dsps_set_mode(struct param_d *param, void *priv)
+{
+ struct dsps_glue *glue = priv;
+
+ if (glue->pdata.mode != MUSB_PORT_MODE_DUAL_ROLE)
+ return -EBUSY;
+
+ switch (glue->otgmode) {
+ case 0:
+ default:
+ return -EINVAL;
+ case 1:
+ glue->pdata.mode = MUSB_PORT_MODE_HOST;
+ break;
+ case 2:
+ glue->pdata.mode = MUSB_PORT_MODE_GADGET;
+ break;
+ }
+
+ return musb_init_controller(&glue->musb, &glue->pdata);
+}
+
+static const char *dsps_mode_names[] = {
+ "otg", "host", "peripheral"
+};
+
+static int dsps_register_otg_device(struct dsps_glue *glue)
+{
+ int ret;
+
+ strcpy(glue->otg_dev.name, "otg");
+ glue->otg_dev.id = DEVICE_ID_DYNAMIC,
+ glue->otg_dev.parent = glue->dev;
+
+ ret = register_device(&glue->otg_dev);
+ if (ret)
+ return ret;
+
+ dev_add_param_enum(&glue->otg_dev, "mode",
+ dsps_set_mode, NULL, &glue->otgmode,
+ dsps_mode_names, ARRAY_SIZE(dsps_mode_names), glue);
+ return 0;
+}
+
+static int dsps_probe(struct device_d *dev)
+{
+ struct musb_hdrc_platform_data *pdata;
+ struct musb_hdrc_config *config;
+ struct device_node *dn = dev->device_node;
+ const struct dsps_musb_wrapper *wrp;
+ struct dsps_glue *glue;
+ int ret;
+
+ ret = dev_get_drvdata(dev, (unsigned long *)&wrp);
+ if (ret)
+ return ret;
+
+ if (!IS_ENABLED(CONFIG_USB_MUSB_HOST) &&
+ !IS_ENABLED(CONFIG_USB_MUSB_GADGET)) {
+ dev_err(dev, "Both host and device driver disabled.\n");
+ return -ENODEV;
+ }
+
+ /* allocate glue */
+ glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+ if (!glue) {
+ dev_err(dev, "unable to allocate glue memory\n");
+ return -ENOMEM;
+ }
+
+ glue->dev = dev;
+ glue->wrp = wrp;
+
+ dev->priv = glue;
+
+ pdata = &glue->pdata;
+
+ glue->musb.mregs = dev_request_mem_region(dev, 0);
+ if (IS_ERR(glue->musb.mregs))
+ return PTR_ERR(glue->musb.mregs);
+
+ glue->musb.ctrl_base = dev_request_mem_region(dev, 1);
+ if (IS_ERR(glue->musb.ctrl_base))
+ return PTR_ERR(glue->musb.ctrl_base);
+
+ glue->musb.controller = dev;
+
+ config = &glue->config;
+
+ pdata->config = config;
+ pdata->platform_ops = &dsps_ops;
+
+ config->num_eps = get_int_prop(dn, "mentor,num-eps");
+ config->ram_bits = get_int_prop(dn, "mentor,ram-bits");
+
+ pdata->mode = get_musb_port_mode(dev);
+ /* DT keeps this entry in mA, musb expects it as per USB spec */
+ pdata->power = get_int_prop(dn, "mentor,power") / 2;
+ config->multipoint = of_property_read_bool(dn, "mentor,multipoint");
+
+ if (pdata->mode == MUSB_PORT_MODE_DUAL_ROLE) {
+ ret = dsps_register_otg_device(glue);
+ if (ret)
+ return ret;
+ return 0;
+ }
+
+ return musb_init_controller(&glue->musb, pdata);
+}
+
+static const struct dsps_musb_wrapper am33xx_driver_data = {
+ .revision = 0x00,
+ .control = 0x14,
+ .status = 0x18,
+ .epintr_set = 0x38,
+ .epintr_clear = 0x40,
+ .epintr_status = 0x30,
+ .coreintr_set = 0x3c,
+ .coreintr_clear = 0x44,
+ .coreintr_status = 0x34,
+ .phy_utmi = 0xe0,
+ .mode = 0xe8,
+ .reset = 0,
+ .otg_disable = 21,
+ .iddig = 8,
+ .usb_shift = 0,
+ .usb_mask = 0x1ff,
+ .usb_bitmap = (0x1ff << 0),
+ .drvvbus = 8,
+ .txep_shift = 0,
+ .txep_mask = 0xffff,
+ .txep_bitmap = (0xffff << 0),
+ .rxep_shift = 16,
+ .rxep_mask = 0xfffe,
+ .rxep_bitmap = (0xfffe << 16),
+ .poll_seconds = 2,
+};
+
+static __maybe_unused struct of_device_id musb_dsps_dt_ids[] = {
+ {
+ .compatible = "ti,musb-am33xx",
+ .data = (unsigned long) &am33xx_driver_data,
+ }, {
+ /* sentinel */
+ },
+};
+
+static struct driver_d dsps_usbss_driver = {
+ .name = "musb-dsps",
+ .probe = dsps_probe,
+ .of_compatible = DRV_OF_COMPAT(musb_dsps_dt_ids),
+};
+device_platform_driver(dsps_usbss_driver);
+
+MODULE_DESCRIPTION("TI DSPS MUSB Glue Layer");
+MODULE_AUTHOR("Ravi B <ravibabu@ti.com>");
+MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
new file mode 100644
index 0000000000..3f0ddd1875
--- /dev/null
+++ b/drivers/usb/musb/musb_gadget.c
@@ -0,0 +1,1308 @@
+/*
+ * MUSB OTG driver peripheral support
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ * Copyright (C) 2009 MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <clock.h>
+#include "musb_core.h"
+#include "musb_gadget.h"
+
+/*
+ * Immediately complete a request.
+ *
+ * @param request the request to complete
+ * @param status the status to complete the request with
+ * Context: controller locked, IRQs blocked.
+ */
+void musb_g_giveback(
+ struct musb_ep *ep,
+ struct usb_request *request,
+ int status)
+__releases(ep->musb->lock)
+__acquires(ep->musb->lock)
+{
+ struct musb_request *req;
+ struct musb *musb;
+ int busy = ep->busy;
+
+ req = to_musb_request(request);
+
+ list_del(&req->list);
+ if (req->request.status == -EINPROGRESS)
+ req->request.status = status;
+ musb = req->musb;
+
+ ep->busy = 1;
+ spin_unlock(&musb->lock);
+
+ if (request->status == 0)
+ dev_dbg(musb->controller, "%s done request %p, %d/%d\n",
+ ep->end_point.name, request,
+ req->request.actual, req->request.length);
+ else
+ dev_dbg(musb->controller, "%s request %p, %d/%d fault %d\n",
+ ep->end_point.name, request,
+ req->request.actual, req->request.length,
+ request->status);
+ req->request.complete(&req->ep->end_point, &req->request);
+ spin_lock(&musb->lock);
+ ep->busy = busy;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/*
+ * Abort requests queued to an endpoint using the status. Synchronous.
+ * caller locked controller and blocked irqs, and selected this ep.
+ */
+static void nuke(struct musb_ep *ep, const int status)
+{
+ struct musb_request *req = NULL;
+
+ ep->busy = 1;
+
+ while (!list_empty(&ep->req_list)) {
+ req = list_first_entry(&ep->req_list, struct musb_request, list);
+ musb_g_giveback(ep, &req->request, status);
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* Data transfers - pure PIO, pure DMA, or mixed mode */
+
+/*
+ * This assumes the separate CPPI engine is responding to DMA requests
+ * from the usb core ... sequenced a bit differently from mentor dma.
+ */
+
+static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)
+{
+ if (can_bulk_split(musb, ep->type))
+ return ep->hw_ep->max_packet_sz_tx;
+ else
+ return ep->packet_sz;
+}
+
+/*
+ * An endpoint is transmitting data. This can be called either from
+ * the IRQ routine or from ep.queue() to kickstart a request on an
+ * endpoint.
+ *
+ * Context: controller locked, IRQs blocked, endpoint selected
+ */
+static void txstate(struct musb *musb, struct musb_request *req)
+{
+ u8 epnum = req->epnum;
+ struct musb_ep *musb_ep;
+ void __iomem *epio = musb->endpoints[epnum].regs;
+ struct usb_request *request;
+ u16 fifo_count = 0, csr;
+ int use_dma = 0;
+
+ musb_ep = req->ep;
+
+ /* Check if EP is disabled */
+ if (!musb_ep->desc) {
+ dev_dbg(musb->controller, "ep:%s disabled - ignore request\n",
+ musb_ep->end_point.name);
+ return;
+ }
+
+ /* read TXCSR before */
+ csr = musb_readw(epio, MUSB_TXCSR);
+
+ request = &req->request;
+ fifo_count = min(max_ep_writesize(musb, musb_ep),
+ (int)(request->length - request->actual));
+
+ if (csr & MUSB_TXCSR_TXPKTRDY) {
+ dev_dbg(musb->controller, "%s old packet still ready , txcsr %03x\n",
+ musb_ep->end_point.name, csr);
+ return;
+ }
+
+ if (csr & MUSB_TXCSR_P_SENDSTALL) {
+ dev_dbg(musb->controller, "%s stalling, txcsr %03x\n",
+ musb_ep->end_point.name, csr);
+ return;
+ }
+
+ dev_dbg(musb->controller, "hw_ep%d, maxpacket %d, fifo count %d, txcsr %03x\n",
+ epnum, musb_ep->packet_sz, fifo_count,
+ csr);
+
+ if (!use_dma) {
+ musb_write_fifo(musb_ep->hw_ep, fifo_count,
+ (u8 *) (request->buf + request->actual));
+ request->actual += fifo_count;
+ csr |= MUSB_TXCSR_TXPKTRDY;
+ csr &= ~MUSB_TXCSR_P_UNDERRUN;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ }
+
+ /* host may already have the data when this message shows... */
+ dev_dbg(musb->controller, "%s TX/IN %s len %d/%d, txcsr %04x, fifo %d/%d\n",
+ musb_ep->end_point.name, use_dma ? "dma" : "pio",
+ request->actual, request->length,
+ musb_readw(epio, MUSB_TXCSR),
+ fifo_count,
+ musb_readw(epio, MUSB_TXMAXP));
+}
+
+/*
+ * FIFO state update (e.g. data ready).
+ * Called from IRQ, with controller locked.
+ */
+void musb_g_tx(struct musb *musb, u8 epnum)
+{
+ u16 csr;
+ struct musb_request *req;
+ struct usb_request *request;
+ u8 __iomem *mbase = musb->mregs;
+ struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_in;
+ void __iomem *epio = musb->endpoints[epnum].regs;
+
+ musb_ep_select(mbase, epnum);
+ req = next_request(musb_ep);
+ request = &req->request;
+
+ csr = musb_readw(epio, MUSB_TXCSR);
+ dev_dbg(musb->controller, "<== %s, txcsr %04x\n", musb_ep->end_point.name, csr);
+
+ /*
+ * REVISIT: for high bandwidth, MUSB_TXCSR_P_INCOMPTX
+ * probably rates reporting as a host error.
+ */
+ if (csr & MUSB_TXCSR_P_SENTSTALL) {
+ csr |= MUSB_TXCSR_P_WZC_BITS;
+ csr &= ~MUSB_TXCSR_P_SENTSTALL;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ return;
+ }
+
+ if (csr & MUSB_TXCSR_P_UNDERRUN) {
+ /* We NAKed, no big deal... little reason to care. */
+ csr |= MUSB_TXCSR_P_WZC_BITS;
+ csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
+ musb_writew(epio, MUSB_TXCSR, csr);
+ dev_vdbg(musb->controller, "underrun on ep%d, req %p\n",
+ epnum, request);
+ }
+
+ if (request) {
+ /*
+ * First, maybe a terminating short packet. Some DMA
+ * engines might handle this by themselves.
+ */
+ if ((request->zero && request->length
+ && (request->length % musb_ep->packet_sz == 0)
+ && (request->actual == request->length))
+ ) {
+ /*
+ * On DMA completion, FIFO may not be
+ * available yet...
+ */
+ if (csr & MUSB_TXCSR_TXPKTRDY)
+ return;
+
+ dev_dbg(musb->controller, "sending zero pkt\n");
+ musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE
+ | MUSB_TXCSR_TXPKTRDY);
+ request->zero = 0;
+ }
+
+ if (request->actual == request->length) {
+ musb_g_giveback(musb_ep, request, 0);
+ /*
+ * In the giveback function the MUSB lock is
+ * released and acquired after sometime. During
+ * this time period the INDEX register could get
+ * changed by the gadget_queue function especially
+ * on SMP systems. Reselect the INDEX to be sure
+ * we are reading/modifying the right registers
+ */
+ musb_ep_select(mbase, epnum);
+ req = musb_ep->desc ? next_request(musb_ep) : NULL;
+ if (!req) {
+ dev_dbg(musb->controller, "%s idle now\n",
+ musb_ep->end_point.name);
+ return;
+ }
+ }
+
+ txstate(musb, req);
+ }
+}
+
+/* ------------------------------------------------------------ */
+
+/*
+ * Context: controller locked, IRQs blocked, endpoint selected
+ */
+static void rxstate(struct musb *musb, struct musb_request *req)
+{
+ const u8 epnum = req->epnum;
+ struct usb_request *request = &req->request;
+ struct musb_ep *musb_ep;
+ void __iomem *epio = musb->endpoints[epnum].regs;
+ unsigned len = 0;
+ u16 fifo_count;
+ u16 csr = musb_readw(epio, MUSB_RXCSR);
+ struct musb_hw_ep *hw_ep = &musb->endpoints[epnum];
+ u8 use_mode_1;
+
+ if (hw_ep->is_shared_fifo)
+ musb_ep = &hw_ep->ep_in;
+ else
+ musb_ep = &hw_ep->ep_out;
+
+ fifo_count = musb_ep->packet_sz;
+
+ /* Check if EP is disabled */
+ if (!musb_ep->desc) {
+ dev_dbg(musb->controller, "ep:%s disabled - ignore request\n",
+ musb_ep->end_point.name);
+ return;
+ }
+
+ if (csr & MUSB_RXCSR_P_SENDSTALL) {
+ dev_dbg(musb->controller, "%s stalling, RXCSR %04x\n",
+ musb_ep->end_point.name, csr);
+ return;
+ }
+
+ if (csr & MUSB_RXCSR_RXPKTRDY) {
+ fifo_count = musb_readw(epio, MUSB_RXCOUNT);
+
+ /*
+ * Enable Mode 1 on RX transfers only when short_not_ok flag
+ * is set. Currently short_not_ok flag is set only from
+ * file_storage and f_mass_storage drivers
+ */
+
+ if (request->short_not_ok && fifo_count == musb_ep->packet_sz)
+ use_mode_1 = 1;
+ else
+ use_mode_1 = 0;
+
+ if (request->actual < request->length) {
+ len = request->length - request->actual;
+ dev_dbg(musb->controller, "%s OUT/RX pio fifo %d/%d, maxpacket %d\n",
+ musb_ep->end_point.name,
+ fifo_count, len,
+ musb_ep->packet_sz);
+
+ fifo_count = min_t(unsigned, len, fifo_count);
+
+ musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *)
+ (request->buf + request->actual));
+ request->actual += fifo_count;
+
+ /* REVISIT if we left anything in the fifo, flush
+ * it and report -EOVERFLOW
+ */
+
+ /* ack the read! */
+ csr |= MUSB_RXCSR_P_WZC_BITS;
+ csr &= ~MUSB_RXCSR_RXPKTRDY;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ }
+ }
+
+ /* reach the end or short packet detected */
+ if (request->actual == request->length ||
+ fifo_count < musb_ep->packet_sz)
+ musb_g_giveback(musb_ep, request, 0);
+}
+
+/*
+ * Data ready for a request; called from IRQ
+ */
+void musb_g_rx(struct musb *musb, u8 epnum)
+{
+ u16 csr;
+ struct musb_request *req;
+ struct usb_request *request;
+ void __iomem *mbase = musb->mregs;
+ struct musb_ep *musb_ep;
+ void __iomem *epio = musb->endpoints[epnum].regs;
+ struct musb_hw_ep *hw_ep = &musb->endpoints[epnum];
+
+ if (hw_ep->is_shared_fifo)
+ musb_ep = &hw_ep->ep_in;
+ else
+ musb_ep = &hw_ep->ep_out;
+
+ musb_ep_select(mbase, epnum);
+
+ req = next_request(musb_ep);
+ if (!req)
+ return;
+
+ request = &req->request;
+
+ csr = musb_readw(epio, MUSB_RXCSR);
+
+ dev_dbg(musb->controller, "<== %s, rxcsr %04x%s %p\n", musb_ep->end_point.name,
+ csr, "", request);
+
+ if (csr & MUSB_RXCSR_P_SENTSTALL) {
+ csr |= MUSB_RXCSR_P_WZC_BITS;
+ csr &= ~MUSB_RXCSR_P_SENTSTALL;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ return;
+ }
+
+ if (csr & MUSB_RXCSR_P_OVERRUN) {
+ /* csr |= MUSB_RXCSR_P_WZC_BITS; */
+ csr &= ~MUSB_RXCSR_P_OVERRUN;
+ musb_writew(epio, MUSB_RXCSR, csr);
+
+ dev_dbg(musb->controller, "%s iso overrun on %p\n", musb_ep->name, request);
+ if (request->status == -EINPROGRESS)
+ request->status = -EOVERFLOW;
+ }
+ if (csr & MUSB_RXCSR_INCOMPRX) {
+ /* REVISIT not necessarily an error */
+ dev_dbg(musb->controller, "%s, incomprx\n", musb_ep->end_point.name);
+ }
+
+ /* Analyze request */
+ rxstate(musb, req);
+}
+
+/* ------------------------------------------------------------ */
+
+static int musb_gadget_enable(struct usb_ep *ep,
+ const struct usb_endpoint_descriptor *desc)
+{
+ unsigned long flags;
+ struct musb_ep *musb_ep;
+ struct musb_hw_ep *hw_ep;
+ void __iomem *regs;
+ struct musb *musb;
+ void __iomem *mbase;
+ u8 epnum;
+ u16 csr;
+ unsigned tmp;
+ int status = -EINVAL;
+
+ if (!ep || !desc)
+ return -EINVAL;
+
+ musb_ep = to_musb_ep(ep);
+ hw_ep = musb_ep->hw_ep;
+ regs = hw_ep->regs;
+ musb = musb_ep->musb;
+ mbase = musb->mregs;
+ epnum = musb_ep->current_epnum;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ if (musb_ep->desc) {
+ status = -EBUSY;
+ goto fail;
+ }
+ musb_ep->type = usb_endpoint_type(desc);
+
+ /* check direction and (later) maxpacket size against endpoint */
+ if (usb_endpoint_num(desc) != epnum)
+ goto fail;
+
+ /* REVISIT this rules out high bandwidth periodic transfers */
+ tmp = usb_endpoint_maxp(desc);
+ if (tmp & ~0x07ff) {
+ int ok;
+
+ if (usb_endpoint_dir_in(desc))
+ ok = musb->hb_iso_tx;
+ else
+ ok = musb->hb_iso_rx;
+
+ if (!ok) {
+ dev_dbg(musb->controller, "no support for high bandwidth ISO\n");
+ goto fail;
+ }
+ musb_ep->hb_mult = (tmp >> 11) & 3;
+ } else {
+ musb_ep->hb_mult = 0;
+ }
+
+ musb_ep->packet_sz = tmp & 0x7ff;
+ tmp = musb_ep->packet_sz * (musb_ep->hb_mult + 1);
+
+ /* enable the interrupts for the endpoint, set the endpoint
+ * packet size (or fail), set the mode, clear the fifo
+ */
+ musb_ep_select(mbase, epnum);
+ if (usb_endpoint_dir_in(desc)) {
+
+ if (hw_ep->is_shared_fifo)
+ musb_ep->is_in = 1;
+ if (!musb_ep->is_in)
+ goto fail;
+
+ if (tmp > hw_ep->max_packet_sz_tx) {
+ dev_dbg(musb->controller, "packet size beyond hardware FIFO size\n");
+ goto fail;
+ }
+
+ musb->intrtxe |= (1 << epnum);
+ musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe);
+
+ /* REVISIT if can_bulk_split(), use by updating "tmp";
+ * likewise high bandwidth periodic tx
+ */
+ /* Set TXMAXP with the FIFO size of the endpoint
+ * to disable double buffering mode.
+ */
+ if (musb->double_buffer_not_ok) {
+ musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx);
+ } else {
+ if (can_bulk_split(musb, musb_ep->type))
+ musb_ep->hb_mult = (hw_ep->max_packet_sz_tx /
+ musb_ep->packet_sz) - 1;
+ musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz
+ | (musb_ep->hb_mult << 11));
+ }
+
+ csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG;
+ if (musb_readw(regs, MUSB_TXCSR)
+ & MUSB_TXCSR_FIFONOTEMPTY)
+ csr |= MUSB_TXCSR_FLUSHFIFO;
+ if (musb_ep->type == USB_ENDPOINT_XFER_ISOC)
+ csr |= MUSB_TXCSR_P_ISO;
+
+ /* set twice in case of double buffering */
+ musb_writew(regs, MUSB_TXCSR, csr);
+ /* REVISIT may be inappropriate w/o FIFONOTEMPTY ... */
+ musb_writew(regs, MUSB_TXCSR, csr);
+
+ } else {
+
+ if (hw_ep->is_shared_fifo)
+ musb_ep->is_in = 0;
+ if (musb_ep->is_in)
+ goto fail;
+
+ if (tmp > hw_ep->max_packet_sz_rx) {
+ dev_dbg(musb->controller, "packet size beyond hardware FIFO size\n");
+ goto fail;
+ }
+
+ musb->intrrxe |= (1 << epnum);
+ musb_writew(mbase, MUSB_INTRRXE, musb->intrrxe);
+
+ /* REVISIT if can_bulk_combine() use by updating "tmp"
+ * likewise high bandwidth periodic rx
+ */
+ /* Set RXMAXP with the FIFO size of the endpoint
+ * to disable double buffering mode.
+ */
+ if (musb->double_buffer_not_ok)
+ musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_tx);
+ else
+ musb_writew(regs, MUSB_RXMAXP, musb_ep->packet_sz
+ | (musb_ep->hb_mult << 11));
+
+ /* force shared fifo to OUT-only mode */
+ if (hw_ep->is_shared_fifo) {
+ csr = musb_readw(regs, MUSB_TXCSR);
+ csr &= ~(MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY);
+ musb_writew(regs, MUSB_TXCSR, csr);
+ }
+
+ csr = MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_CLRDATATOG;
+ if (musb_ep->type == USB_ENDPOINT_XFER_ISOC)
+ csr |= MUSB_RXCSR_P_ISO;
+ else if (musb_ep->type == USB_ENDPOINT_XFER_INT)
+ csr |= MUSB_RXCSR_DISNYET;
+
+ /* set twice in case of double buffering */
+ musb_writew(regs, MUSB_RXCSR, csr);
+ musb_writew(regs, MUSB_RXCSR, csr);
+ }
+
+ musb_ep->desc = desc;
+ musb_ep->busy = 0;
+ musb_ep->wedged = 0;
+ status = 0;
+
+ pr_debug("%s periph: enabled %s for %s %s, %smaxpacket %d\n",
+ musb_driver_name, musb_ep->end_point.name,
+ ({ char *s; switch (musb_ep->type) {
+ case USB_ENDPOINT_XFER_BULK: s = "bulk"; break;
+ case USB_ENDPOINT_XFER_INT: s = "int"; break;
+ default: s = "iso"; break;
+ } s; }),
+ musb_ep->is_in ? "IN" : "OUT",
+ "",
+ musb_ep->packet_sz);
+
+fail:
+ spin_unlock_irqrestore(&musb->lock, flags);
+ return status;
+}
+
+/*
+ * Disable an endpoint flushing all requests queued.
+ */
+static int musb_gadget_disable(struct usb_ep *ep)
+{
+ unsigned long flags;
+ struct musb *musb;
+ u8 epnum;
+ struct musb_ep *musb_ep;
+ void __iomem *epio;
+ int status = 0;
+
+ musb_ep = to_musb_ep(ep);
+ musb = musb_ep->musb;
+ epnum = musb_ep->current_epnum;
+ epio = musb->endpoints[epnum].regs;
+
+ spin_lock_irqsave(&musb->lock, flags);
+ musb_ep_select(musb->mregs, epnum);
+
+ /* zero the endpoint sizes */
+ if (musb_ep->is_in) {
+ musb->intrtxe &= ~(1 << epnum);
+ musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe);
+ musb_writew(epio, MUSB_TXMAXP, 0);
+ } else {
+ musb->intrrxe &= ~(1 << epnum);
+ musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe);
+ musb_writew(epio, MUSB_RXMAXP, 0);
+ }
+
+ musb_ep->desc = NULL;
+ musb_ep->end_point.desc = NULL;
+
+ /* abort all pending DMA and requests */
+ nuke(musb_ep, -ESHUTDOWN);
+
+ spin_unlock_irqrestore(&(musb->lock), flags);
+
+ dev_dbg(musb->controller, "%s\n", musb_ep->end_point.name);
+
+ return status;
+}
+
+/*
+ * Allocate a request for an endpoint.
+ * Reused by ep0 code.
+ */
+struct usb_request *musb_alloc_request(struct usb_ep *ep)
+{
+ struct musb_ep *musb_ep = to_musb_ep(ep);
+ struct musb *musb = musb_ep->musb;
+ struct musb_request *request = NULL;
+
+ request = kzalloc(sizeof *request, gfp_flags);
+ if (!request) {
+ dev_dbg(musb->controller, "not enough memory\n");
+ return NULL;
+ }
+
+ request->request.dma = DMA_ADDR_INVALID;
+ request->epnum = musb_ep->current_epnum;
+ request->ep = musb_ep;
+
+ return &request->request;
+}
+
+/*
+ * Free a request
+ * Reused by ep0 code.
+ */
+void musb_free_request(struct usb_ep *ep, struct usb_request *req)
+{
+ kfree(to_musb_request(req));
+}
+
+static LIST_HEAD(buffers);
+
+struct free_record {
+ struct list_head list;
+ struct device *dev;
+ unsigned bytes;
+ dma_addr_t dma;
+};
+
+/*
+ * Context: controller locked, IRQs blocked.
+ */
+void musb_ep_restart(struct musb *musb, struct musb_request *req)
+{
+ dev_dbg(musb->controller, "<== %s request %p len %u on hw_ep%d\n",
+ req->tx ? "TX/IN" : "RX/OUT",
+ &req->request, req->request.length, req->epnum);
+
+ musb_ep_select(musb->mregs, req->epnum);
+ if (req->tx)
+ txstate(musb, req);
+ else
+ rxstate(musb, req);
+}
+
+static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req)
+{
+ struct musb_ep *musb_ep;
+ struct musb_request *request;
+ struct musb *musb;
+ int status = 0;
+ unsigned long lockflags;
+
+ if (!ep || !req)
+ return -EINVAL;
+ if (!req->buf)
+ return -ENODATA;
+
+ musb_ep = to_musb_ep(ep);
+ musb = musb_ep->musb;
+
+ request = to_musb_request(req);
+ request->musb = musb;
+
+ if (request->ep != musb_ep)
+ return -EINVAL;
+
+ dev_dbg(musb->controller, "<== to %s request=%p\n", ep->name, req);
+
+ /* request is mine now... */
+ request->request.actual = 0;
+ request->request.status = -EINPROGRESS;
+ request->epnum = musb_ep->current_epnum;
+ request->tx = musb_ep->is_in;
+
+ spin_lock_irqsave(&musb->lock, lockflags);
+
+ /* don't queue if the ep is down */
+ if (!musb_ep->desc) {
+ dev_dbg(musb->controller, "req %p queued to %s while ep %s\n",
+ req, ep->name, "disabled");
+ status = -ESHUTDOWN;
+ goto unlock;
+ }
+
+ /* add request to the list */
+ list_add_tail(&request->list, &musb_ep->req_list);
+
+ /* it this is the head of the queue, start i/o ... */
+ if (!musb_ep->busy && &request->list == musb_ep->req_list.next)
+ musb_ep_restart(musb, request);
+
+unlock:
+ spin_unlock_irqrestore(&musb->lock, lockflags);
+ return status;
+}
+
+static int musb_gadget_dequeue(struct usb_ep *ep, struct usb_request *request)
+{
+ struct musb_ep *musb_ep = to_musb_ep(ep);
+ struct musb_request *req = to_musb_request(request);
+ struct musb_request *r;
+ unsigned long flags;
+ int status = 0;
+ struct musb *musb = musb_ep->musb;
+
+ if (!ep || !request || to_musb_request(request)->ep != musb_ep)
+ return -EINVAL;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ list_for_each_entry(r, &musb_ep->req_list, list) {
+ if (r == req)
+ break;
+ }
+ if (r != req) {
+ dev_dbg(musb->controller, "request %p not queued to %s\n", request, ep->name);
+ status = -EINVAL;
+ goto done;
+ }
+
+ /* if the hardware doesn't have the request, easy ... */
+ if (musb_ep->req_list.next != &req->list || musb_ep->busy) {
+ musb_g_giveback(musb_ep, request, -ECONNRESET);
+ } else {
+ /* NOTE: by sticking to easily tested hardware/driver states,
+ * we leave counting of in-flight packets imprecise.
+ */
+ musb_g_giveback(musb_ep, request, -ECONNRESET);
+ }
+
+done:
+ spin_unlock_irqrestore(&musb->lock, flags);
+ return status;
+}
+
+/*
+ * Set or clear the halt bit of an endpoint. A halted enpoint won't tx/rx any
+ * data but will queue requests.
+ *
+ * exported to ep0 code
+ */
+static int musb_gadget_set_halt(struct usb_ep *ep, int value)
+{
+ struct musb_ep *musb_ep = to_musb_ep(ep);
+ u8 epnum = musb_ep->current_epnum;
+ struct musb *musb = musb_ep->musb;
+ void __iomem *epio = musb->endpoints[epnum].regs;
+ void __iomem *mbase;
+ unsigned long flags;
+ u16 csr;
+ struct musb_request *request;
+ int status = 0;
+
+ if (!ep)
+ return -EINVAL;
+ mbase = musb->mregs;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ if ((USB_ENDPOINT_XFER_ISOC == musb_ep->type)) {
+ status = -EINVAL;
+ goto done;
+ }
+
+ musb_ep_select(mbase, epnum);
+
+ request = next_request(musb_ep);
+ if (value) {
+ if (request) {
+ dev_dbg(musb->controller, "request in progress, cannot halt %s\n",
+ ep->name);
+ status = -EAGAIN;
+ goto done;
+ }
+ /* Cannot portably stall with non-empty FIFO */
+ if (musb_ep->is_in) {
+ csr = musb_readw(epio, MUSB_TXCSR);
+ if (csr & MUSB_TXCSR_FIFONOTEMPTY) {
+ dev_dbg(musb->controller, "FIFO busy, cannot halt %s\n", ep->name);
+ status = -EAGAIN;
+ goto done;
+ }
+ }
+ } else
+ musb_ep->wedged = 0;
+
+ /* set/clear the stall and toggle bits */
+ dev_dbg(musb->controller, "%s: %s stall\n", ep->name, value ? "set" : "clear");
+ if (musb_ep->is_in) {
+ csr = musb_readw(epio, MUSB_TXCSR);
+ csr |= MUSB_TXCSR_P_WZC_BITS
+ | MUSB_TXCSR_CLRDATATOG;
+ if (value)
+ csr |= MUSB_TXCSR_P_SENDSTALL;
+ else
+ csr &= ~(MUSB_TXCSR_P_SENDSTALL
+ | MUSB_TXCSR_P_SENTSTALL);
+ csr &= ~MUSB_TXCSR_TXPKTRDY;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ } else {
+ csr = musb_readw(epio, MUSB_RXCSR);
+ csr |= MUSB_RXCSR_P_WZC_BITS
+ | MUSB_RXCSR_FLUSHFIFO
+ | MUSB_RXCSR_CLRDATATOG;
+ if (value)
+ csr |= MUSB_RXCSR_P_SENDSTALL;
+ else
+ csr &= ~(MUSB_RXCSR_P_SENDSTALL
+ | MUSB_RXCSR_P_SENTSTALL);
+ musb_writew(epio, MUSB_RXCSR, csr);
+ }
+
+ /* maybe start the first request in the queue */
+ if (!musb_ep->busy && !value && request) {
+ dev_dbg(musb->controller, "restarting the request\n");
+ musb_ep_restart(musb, request);
+ }
+
+done:
+ spin_unlock_irqrestore(&musb->lock, flags);
+ return status;
+}
+
+/*
+ * Sets the halt feature with the clear requests ignored
+ */
+static int musb_gadget_set_wedge(struct usb_ep *ep)
+{
+ struct musb_ep *musb_ep = to_musb_ep(ep);
+
+ if (!ep)
+ return -EINVAL;
+
+ musb_ep->wedged = 1;
+
+ return usb_ep_set_halt(ep);
+}
+
+static int musb_gadget_fifo_status(struct usb_ep *ep)
+{
+ struct musb_ep *musb_ep = to_musb_ep(ep);
+ void __iomem *epio = musb_ep->hw_ep->regs;
+ int retval = -EINVAL;
+
+ if (musb_ep->desc && !musb_ep->is_in) {
+ struct musb *musb = musb_ep->musb;
+ int epnum = musb_ep->current_epnum;
+ void __iomem *mbase = musb->mregs;
+ unsigned long flags;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ musb_ep_select(mbase, epnum);
+ /* FIXME return zero unless RXPKTRDY is set */
+ retval = musb_readw(epio, MUSB_RXCOUNT);
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+ }
+ return retval;
+}
+
+static void musb_gadget_fifo_flush(struct usb_ep *ep)
+{
+ struct musb_ep *musb_ep = to_musb_ep(ep);
+ struct musb *musb = musb_ep->musb;
+ u8 epnum = musb_ep->current_epnum;
+ void __iomem *epio = musb->endpoints[epnum].regs;
+ void __iomem *mbase;
+ unsigned long flags;
+ u16 csr;
+
+ mbase = musb->mregs;
+
+ spin_lock_irqsave(&musb->lock, flags);
+ musb_ep_select(mbase, (u8) epnum);
+
+ /* disable interrupts */
+ musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe & ~(1 << epnum));
+
+ if (musb_ep->is_in) {
+ csr = musb_readw(epio, MUSB_TXCSR);
+ if (csr & MUSB_TXCSR_FIFONOTEMPTY) {
+ csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_P_WZC_BITS;
+ /*
+ * Setting both TXPKTRDY and FLUSHFIFO makes controller
+ * to interrupt current FIFO loading, but not flushing
+ * the already loaded ones.
+ */
+ csr &= ~MUSB_TXCSR_TXPKTRDY;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ /* REVISIT may be inappropriate w/o FIFONOTEMPTY ... */
+ musb_writew(epio, MUSB_TXCSR, csr);
+ }
+ } else {
+ csr = musb_readw(epio, MUSB_RXCSR);
+ csr |= MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_P_WZC_BITS;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ musb_writew(epio, MUSB_RXCSR, csr);
+ }
+
+ /* re-enable interrupt */
+ musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe);
+ spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+static const struct usb_ep_ops musb_ep_ops = {
+ .enable = musb_gadget_enable,
+ .disable = musb_gadget_disable,
+ .alloc_request = musb_alloc_request,
+ .free_request = musb_free_request,
+ .queue = musb_gadget_queue,
+ .dequeue = musb_gadget_dequeue,
+ .set_halt = musb_gadget_set_halt,
+ .set_wedge = musb_gadget_set_wedge,
+ .fifo_status = musb_gadget_fifo_status,
+ .fifo_flush = musb_gadget_fifo_flush
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int musb_gadget_get_frame(struct usb_gadget *gadget)
+{
+ struct musb *musb = gadget_to_musb(gadget);
+
+ return (int)musb_readw(musb->mregs, MUSB_FRAME);
+}
+
+static int
+musb_gadget_set_self_powered(struct usb_gadget *gadget, int is_selfpowered)
+{
+ struct musb *musb = gadget_to_musb(gadget);
+
+ musb->is_self_powered = !!is_selfpowered;
+ return 0;
+}
+
+static void musb_pullup(struct musb *musb, int is_on)
+{
+ u8 power;
+
+ power = musb_readb(musb->mregs, MUSB_POWER);
+ if (is_on)
+ power |= MUSB_POWER_SOFTCONN;
+ else
+ power &= ~MUSB_POWER_SOFTCONN;
+
+ /* FIXME if on, HdrcStart; if off, HdrcStop */
+
+ dev_dbg(musb->controller, "gadget D+ pullup %s\n",
+ is_on ? "on" : "off");
+ musb_writeb(musb->mregs, MUSB_POWER, power);
+}
+
+static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+ struct musb *musb = gadget_to_musb(gadget);
+
+ if (!musb->xceiv->set_power)
+ return -EOPNOTSUPP;
+ return usb_phy_set_power(musb->xceiv, mA);
+}
+
+static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
+{
+ struct musb *musb = gadget_to_musb(gadget);
+ unsigned long flags;
+
+ is_on = !!is_on;
+
+ /* NOTE: this assumes we are sensing vbus; we'd rather
+ * not pullup unless the B-session is active.
+ */
+ spin_lock_irqsave(&musb->lock, flags);
+ if (is_on != musb->softconnect) {
+ musb->softconnect = is_on;
+ musb_pullup(musb, is_on);
+ }
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ return 0;
+}
+
+static void musb_gadget_poll(struct usb_gadget *gadget)
+{
+ struct musb *musb = gadget_to_musb(gadget);
+
+ musb->isr(musb);
+}
+
+static int musb_gadget_start(struct usb_gadget *g,
+ struct usb_gadget_driver *driver);
+static int musb_gadget_stop(struct usb_gadget *g,
+ struct usb_gadget_driver *driver);
+
+static const struct usb_gadget_ops musb_gadget_operations = {
+ .get_frame = musb_gadget_get_frame,
+ .set_selfpowered = musb_gadget_set_self_powered,
+ /* .vbus_session = musb_gadget_vbus_session, */
+ .vbus_draw = musb_gadget_vbus_draw,
+ .pullup = musb_gadget_pullup,
+ .udc_start = musb_gadget_start,
+ .udc_stop = musb_gadget_stop,
+ .udc_poll = musb_gadget_poll,
+};
+
+/* ----------------------------------------------------------------------- */
+
+/* Registration */
+
+/* Only this registration code "knows" the rule (from USB standards)
+ * about there being only one external upstream port. It assumes
+ * all peripheral ports are external...
+ */
+
+static void
+init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
+{
+ struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
+
+ memset(ep, 0, sizeof *ep);
+
+ ep->current_epnum = epnum;
+ ep->musb = musb;
+ ep->hw_ep = hw_ep;
+ ep->is_in = is_in;
+
+ INIT_LIST_HEAD(&ep->req_list);
+
+ sprintf(ep->name, "ep%d%s", epnum,
+ (!epnum || hw_ep->is_shared_fifo) ? "" : (
+ is_in ? "in" : "out"));
+ ep->end_point.name = ep->name;
+ INIT_LIST_HEAD(&ep->end_point.ep_list);
+ if (!epnum) {
+ usb_ep_set_maxpacket_limit(&ep->end_point, 64);
+ ep->end_point.ops = &musb_g_ep0_ops;
+ musb->g.ep0 = &ep->end_point;
+ } else {
+ if (is_in)
+ usb_ep_set_maxpacket_limit(&ep->end_point, hw_ep->max_packet_sz_tx);
+ else
+ usb_ep_set_maxpacket_limit(&ep->end_point, hw_ep->max_packet_sz_rx);
+ ep->end_point.ops = &musb_ep_ops;
+ list_add_tail(&ep->end_point.ep_list, &musb->g.ep_list);
+ }
+}
+
+/*
+ * Initialize the endpoints exposed to peripheral drivers, with backlinks
+ * to the rest of the driver state.
+ */
+static inline void musb_g_init_endpoints(struct musb *musb)
+{
+ u8 epnum;
+ struct musb_hw_ep *hw_ep;
+ unsigned count = 0;
+
+ /* initialize endpoint list just once */
+ INIT_LIST_HEAD(&(musb->g.ep_list));
+
+ for (epnum = 0, hw_ep = musb->endpoints;
+ epnum < musb->nr_endpoints;
+ epnum++, hw_ep++) {
+ if (hw_ep->is_shared_fifo /* || !epnum */) {
+ init_peripheral_ep(musb, &hw_ep->ep_in, epnum, 0);
+ count++;
+ } else {
+ if (hw_ep->max_packet_sz_tx) {
+ init_peripheral_ep(musb, &hw_ep->ep_in,
+ epnum, 1);
+ count++;
+ }
+ if (hw_ep->max_packet_sz_rx) {
+ init_peripheral_ep(musb, &hw_ep->ep_out,
+ epnum, 0);
+ count++;
+ }
+ }
+ }
+}
+
+/* called once during driver setup to initialize and link into
+ * the driver model; memory is zeroed.
+ */
+int musb_gadget_setup(struct musb *musb)
+{
+ int status;
+
+ /* REVISIT minor race: if (erroneously) setting up two
+ * musb peripherals at the same time, only the bus lock
+ * is probably held.
+ */
+
+ musb->g.ops = &musb_gadget_operations;
+ musb->g.max_speed = USB_SPEED_HIGH;
+ musb->g.speed = USB_SPEED_UNKNOWN;
+
+ MUSB_DEV_MODE(musb);
+
+ /* this "gadget" abstracts/virtualizes the controller */
+ musb->g.name = musb_driver_name;
+
+ musb->g.is_otg = 0;
+
+ musb_g_init_endpoints(musb);
+
+ musb->is_active = 0;
+ musb_platform_try_idle(musb, 0);
+
+ status = usb_add_gadget_udc(musb->controller, &musb->g);
+ if (status)
+ goto err;
+
+ return 0;
+err:
+ musb->g.dev.parent = NULL;
+ return status;
+}
+
+void musb_gadget_cleanup(struct musb *musb)
+{
+ if (musb->port_mode == MUSB_PORT_MODE_HOST)
+ return;
+ usb_del_gadget_udc(&musb->g);
+}
+
+/*
+ * Register the gadget driver. Used by gadget drivers when
+ * registering themselves with the controller.
+ *
+ * -EINVAL something went wrong (not driver)
+ * -EBUSY another gadget is already using the controller
+ * -ENOMEM no memory to perform the operation
+ *
+ * @param driver the gadget driver
+ * @return <0 if error, 0 if everything is fine
+ */
+static int musb_gadget_start(struct usb_gadget *g,
+ struct usb_gadget_driver *driver)
+{
+ struct musb *musb = gadget_to_musb(g);
+ unsigned long flags;
+ int retval = 0;
+
+ if (driver->max_speed < USB_SPEED_HIGH) {
+ retval = -EINVAL;
+ goto err;
+ }
+
+ dev_dbg(musb->controller, "registering driver %s\n", driver->function);
+
+ musb->softconnect = 0;
+ musb->gadget_driver = driver;
+
+ spin_lock_irqsave(&musb->lock, flags);
+ musb->is_active = 1;
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ musb_start(musb);
+
+ return 0;
+
+err:
+ return retval;
+}
+
+static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
+{
+ int i;
+ struct musb_hw_ep *hw_ep;
+
+ /* don't disconnect if it's not connected */
+ if (musb->g.speed == USB_SPEED_UNKNOWN)
+ driver = NULL;
+ else
+ musb->g.speed = USB_SPEED_UNKNOWN;
+
+ /* deactivate the hardware */
+ if (musb->softconnect) {
+ musb->softconnect = 0;
+ musb_pullup(musb, 0);
+ }
+ musb_stop(musb);
+
+ /* killing any outstanding requests will quiesce the driver;
+ * then report disconnect
+ */
+ if (driver) {
+ for (i = 0, hw_ep = musb->endpoints;
+ i < musb->nr_endpoints;
+ i++, hw_ep++) {
+ musb_ep_select(musb->mregs, i);
+ if (hw_ep->is_shared_fifo /* || !epnum */) {
+ nuke(&hw_ep->ep_in, -ESHUTDOWN);
+ } else {
+ if (hw_ep->max_packet_sz_tx)
+ nuke(&hw_ep->ep_in, -ESHUTDOWN);
+ if (hw_ep->max_packet_sz_rx)
+ nuke(&hw_ep->ep_out, -ESHUTDOWN);
+ }
+ }
+ }
+}
+
+/*
+ * Unregister the gadget driver. Used by gadget drivers when
+ * unregistering themselves from the controller.
+ *
+ * @param driver the gadget driver to unregister
+ */
+static int musb_gadget_stop(struct usb_gadget *g,
+ struct usb_gadget_driver *driver)
+{
+ struct musb *musb = gadget_to_musb(g);
+ unsigned long flags;
+
+ /*
+ * REVISIT always use otg_set_peripheral() here too;
+ * this needs to shut down the OTG engine.
+ */
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ (void) musb_gadget_vbus_draw(&musb->g, 0);
+
+ stop_activity(musb, driver);
+
+ dev_dbg(musb->controller, "unregistering driver %s\n",
+ driver ? driver->function : "(removed)");
+
+ musb->is_active = 0;
+ musb->gadget_driver = NULL;
+ musb_platform_try_idle(musb, 0);
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ /*
+ * FIXME we need to be able to register another
+ * gadget driver here and have everything work;
+ * that currently misbehaves.
+ */
+
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* lifecycle operations called through plat_uds.c */
+
+/* called when VBUS drops below session threshold, and in other cases */
+void musb_g_disconnect(struct musb *musb)
+{
+ void __iomem *mregs = musb->mregs;
+ u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
+
+ dev_dbg(musb->controller, "devctl %02x\n", devctl);
+
+ /* clear HR */
+ musb_writeb(mregs, MUSB_DEVCTL, devctl & MUSB_DEVCTL_SESSION);
+
+ /* don't draw vbus until new b-default session */
+ (void) musb_gadget_vbus_draw(&musb->g, 0);
+
+ musb->g.speed = USB_SPEED_UNKNOWN;
+ if (musb->gadget_driver && musb->gadget_driver->disconnect) {
+ spin_unlock(&musb->lock);
+ musb->gadget_driver->disconnect(&musb->g);
+ spin_lock(&musb->lock);
+ }
+
+ musb->is_active = 0;
+}
diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h
new file mode 100644
index 0000000000..456c165cc7
--- /dev/null
+++ b/drivers/usb/musb/musb_gadget.h
@@ -0,0 +1,147 @@
+/*
+ * MUSB OTG driver peripheral defines
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_GADGET_H
+#define __MUSB_GADGET_H
+
+#include <linux/list.h>
+#include <usb/gadget.h>
+
+#if IS_ENABLED(CONFIG_USB_MUSB_GADGET)
+extern int musb_g_ep0_irq(struct musb *);
+extern void musb_g_tx(struct musb *, u8);
+extern void musb_g_rx(struct musb *, u8);
+extern void musb_g_reset(struct musb *);
+extern void musb_g_suspend(struct musb *);
+extern void musb_g_resume(struct musb *);
+extern void musb_g_wakeup(struct musb *);
+extern void musb_g_disconnect(struct musb *);
+extern void musb_gadget_cleanup(struct musb *);
+extern int musb_gadget_setup(struct musb *);
+
+#else
+static inline int musb_g_ep0_irq(struct musb *musb)
+{
+ return 0;
+}
+
+static inline void musb_g_tx(struct musb *musb, u8 epnum) {}
+static inline void musb_g_rx(struct musb *musb, u8 epnum) {}
+static inline void musb_g_reset(struct musb *musb) {}
+static inline void musb_g_suspend(struct musb *musb) {}
+static inline void musb_g_resume(struct musb *musb) {}
+static inline void musb_g_wakeup(struct musb *musb) {}
+static inline void musb_g_disconnect(struct musb *musb) {}
+static inline void musb_gadget_cleanup(struct musb *musb) {}
+static inline int musb_gadget_setup(struct musb *musb)
+{
+ return 0;
+}
+#endif
+
+enum buffer_map_state {
+ UN_MAPPED = 0,
+ PRE_MAPPED,
+ MUSB_MAPPED
+};
+
+struct musb_request {
+ struct usb_request request;
+ struct list_head list;
+ struct musb_ep *ep;
+ struct musb *musb;
+ u8 tx; /* endpoint direction */
+ u8 epnum;
+ enum buffer_map_state map_state;
+};
+
+static inline struct musb_request *to_musb_request(struct usb_request *req)
+{
+ return req ? container_of(req, struct musb_request, request) : NULL;
+}
+
+extern struct usb_request *musb_alloc_request(struct usb_ep *ep);
+extern void musb_free_request(struct usb_ep *ep, struct usb_request *req);
+
+
+/*
+ * struct musb_ep - peripheral side view of endpoint rx or tx side
+ */
+struct musb_ep {
+ /* stuff towards the head is basically write-once. */
+ struct usb_ep end_point;
+ char name[12];
+ struct musb_hw_ep *hw_ep;
+ struct musb *musb;
+ u8 current_epnum;
+
+ /* ... when enabled/disabled ... */
+ u8 type;
+ u8 is_in;
+ u16 packet_sz;
+ const struct usb_endpoint_descriptor *desc;
+ struct dma_channel *dma;
+
+ /* later things are modified based on usage */
+ struct list_head req_list;
+
+ u8 wedged;
+
+ /* true if lock must be dropped but req_list may not be advanced */
+ u8 busy;
+
+ u8 hb_mult;
+};
+
+static inline struct musb_ep *to_musb_ep(struct usb_ep *ep)
+{
+ return ep ? container_of(ep, struct musb_ep, end_point) : NULL;
+}
+
+static inline struct musb_request *next_request(struct musb_ep *ep)
+{
+ struct list_head *queue = &ep->req_list;
+
+ if (list_empty(queue))
+ return NULL;
+ return container_of(queue->next, struct musb_request, list);
+}
+
+extern const struct usb_ep_ops musb_g_ep0_ops;
+
+extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int);
+
+extern void musb_ep_restart(struct musb *, struct musb_request *);
+
+#endif /* __MUSB_GADGET_H */
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
new file mode 100644
index 0000000000..feaa856451
--- /dev/null
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -0,0 +1,1079 @@
+/*
+ * MUSB OTG peripheral driver ep0 handling
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ * Copyright (C) 2008-2009 MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <clock.h>
+#include "musb_core.h"
+#include "musb_gadget.h"
+
+/* ep0 is always musb->endpoints[0].ep_in */
+#define next_ep0_request(musb) next_in_request(&(musb)->endpoints[0])
+
+/*
+ * locking note: we use only the controller lock, for simpler correctness.
+ * It's always held with IRQs blocked.
+ *
+ * It protects the ep0 request queue as well as ep0_state, not just the
+ * controller and indexed registers. And that lock stays held unless it
+ * needs to be dropped to allow reentering this driver ... like upcalls to
+ * the gadget driver, or adjusting endpoint halt status.
+ */
+
+static char *decode_ep0stage(u8 stage)
+{
+ switch (stage) {
+ case MUSB_EP0_STAGE_IDLE: return "idle";
+ case MUSB_EP0_STAGE_SETUP: return "setup";
+ case MUSB_EP0_STAGE_TX: return "in";
+ case MUSB_EP0_STAGE_RX: return "out";
+ case MUSB_EP0_STAGE_ACKWAIT: return "wait";
+ case MUSB_EP0_STAGE_STATUSIN: return "in/status";
+ case MUSB_EP0_STAGE_STATUSOUT: return "out/status";
+ default: return "?";
+ }
+}
+
+/* handle a standard GET_STATUS request
+ * Context: caller holds controller lock
+ */
+static int service_tx_status_request(
+ struct musb *musb,
+ const struct usb_ctrlrequest *ctrlrequest)
+{
+ void __iomem *mbase = musb->mregs;
+ int handled = 1;
+ u8 result[2], epnum = 0;
+ const u8 recip = ctrlrequest->bRequestType & USB_RECIP_MASK;
+
+ result[1] = 0;
+
+ switch (recip) {
+ case USB_RECIP_DEVICE:
+ result[0] = musb->is_self_powered << USB_DEVICE_SELF_POWERED;
+ result[0] |= musb->may_wakeup << USB_DEVICE_REMOTE_WAKEUP;
+ if (musb->g.is_otg) {
+ result[0] |= musb->g.b_hnp_enable
+ << USB_DEVICE_B_HNP_ENABLE;
+ result[0] |= musb->g.a_alt_hnp_support
+ << USB_DEVICE_A_ALT_HNP_SUPPORT;
+ result[0] |= musb->g.a_hnp_support
+ << USB_DEVICE_A_HNP_SUPPORT;
+ }
+ break;
+
+ case USB_RECIP_INTERFACE:
+ result[0] = 0;
+ break;
+
+ case USB_RECIP_ENDPOINT: {
+ int is_in;
+ struct musb_ep *ep;
+ u16 tmp;
+ void __iomem *regs;
+
+ epnum = (u8) ctrlrequest->wIndex;
+ if (!epnum) {
+ result[0] = 0;
+ break;
+ }
+
+ is_in = epnum & USB_DIR_IN;
+ if (is_in) {
+ epnum &= 0x0f;
+ ep = &musb->endpoints[epnum].ep_in;
+ } else {
+ ep = &musb->endpoints[epnum].ep_out;
+ }
+ regs = musb->endpoints[epnum].regs;
+
+ if (epnum >= MUSB_C_NUM_EPS || !ep->desc) {
+ handled = -EINVAL;
+ break;
+ }
+
+ musb_ep_select(mbase, epnum);
+ if (is_in)
+ tmp = musb_readw(regs, MUSB_TXCSR)
+ & MUSB_TXCSR_P_SENDSTALL;
+ else
+ tmp = musb_readw(regs, MUSB_RXCSR)
+ & MUSB_RXCSR_P_SENDSTALL;
+ musb_ep_select(mbase, 0);
+
+ result[0] = tmp ? 1 : 0;
+ } break;
+
+ default:
+ /* class, vendor, etc ... delegate */
+ handled = 0;
+ break;
+ }
+
+ /* fill up the fifo; caller updates csr0 */
+ if (handled > 0) {
+ u16 len = le16_to_cpu(ctrlrequest->wLength);
+
+ if (len > 2)
+ len = 2;
+ musb_write_fifo(&musb->endpoints[0], len, result);
+ }
+
+ return handled;
+}
+
+/*
+ * handle a control-IN request, the end0 buffer contains the current request
+ * that is supposed to be a standard control request. Assumes the fifo to
+ * be at least 2 bytes long.
+ *
+ * @return 0 if the request was NOT HANDLED,
+ * < 0 when error
+ * > 0 when the request is processed
+ *
+ * Context: caller holds controller lock
+ */
+static int
+service_in_request(struct musb *musb, const struct usb_ctrlrequest *ctrlrequest)
+{
+ int handled = 0; /* not handled */
+
+ if ((ctrlrequest->bRequestType & USB_TYPE_MASK)
+ == USB_TYPE_STANDARD) {
+ switch (ctrlrequest->bRequest) {
+ case USB_REQ_GET_STATUS:
+ handled = service_tx_status_request(musb,
+ ctrlrequest);
+ break;
+
+ /* case USB_REQ_SYNC_FRAME: */
+
+ default:
+ break;
+ }
+ }
+ return handled;
+}
+
+/*
+ * Context: caller holds controller lock
+ */
+static void musb_g_ep0_giveback(struct musb *musb, struct usb_request *req)
+{
+ musb_g_giveback(&musb->endpoints[0].ep_in, req, 0);
+}
+
+/*
+ * Tries to start B-device HNP negotiation if enabled via sysfs
+ */
+static inline void musb_try_b_hnp_enable(struct musb *musb)
+{
+ void __iomem *mbase = musb->mregs;
+ u8 devctl;
+
+ dev_dbg(musb->controller, "HNP: Setting HR\n");
+ devctl = musb_readb(mbase, MUSB_DEVCTL);
+ musb_writeb(mbase, MUSB_DEVCTL, devctl | MUSB_DEVCTL_HR);
+}
+
+/*
+ * Handle all control requests with no DATA stage, including standard
+ * requests such as:
+ * USB_REQ_SET_CONFIGURATION, USB_REQ_SET_INTERFACE, unrecognized
+ * always delegated to the gadget driver
+ * USB_REQ_SET_ADDRESS, USB_REQ_CLEAR_FEATURE, USB_REQ_SET_FEATURE
+ * always handled here, except for class/vendor/... features
+ *
+ * Context: caller holds controller lock
+ */
+static int
+service_zero_data_request(struct musb *musb,
+ struct usb_ctrlrequest *ctrlrequest)
+__releases(musb->lock)
+__acquires(musb->lock)
+{
+ int handled = -EINVAL;
+ void __iomem *mbase = musb->mregs;
+ const u8 recip = ctrlrequest->bRequestType & USB_RECIP_MASK;
+
+ /* the gadget driver handles everything except what we MUST handle */
+ if ((ctrlrequest->bRequestType & USB_TYPE_MASK)
+ == USB_TYPE_STANDARD) {
+ switch (ctrlrequest->bRequest) {
+ case USB_REQ_SET_ADDRESS:
+ /* change it after the status stage */
+ musb->set_address = true;
+ musb->address = (u8) (ctrlrequest->wValue & 0x7f);
+ handled = 1;
+ break;
+
+ case USB_REQ_CLEAR_FEATURE:
+ switch (recip) {
+ case USB_RECIP_DEVICE:
+ if (ctrlrequest->wValue
+ != USB_DEVICE_REMOTE_WAKEUP)
+ break;
+ musb->may_wakeup = 0;
+ handled = 1;
+ break;
+ case USB_RECIP_INTERFACE:
+ break;
+ case USB_RECIP_ENDPOINT:{
+ const u8 epnum =
+ ctrlrequest->wIndex & 0x0f;
+ struct musb_ep *musb_ep;
+ struct musb_hw_ep *ep;
+ struct musb_request *request;
+ void __iomem *regs;
+ int is_in;
+ u16 csr;
+
+ if (epnum == 0 || epnum >= MUSB_C_NUM_EPS ||
+ ctrlrequest->wValue != USB_ENDPOINT_HALT)
+ break;
+
+ ep = musb->endpoints + epnum;
+ regs = ep->regs;
+ is_in = ctrlrequest->wIndex & USB_DIR_IN;
+ if (is_in)
+ musb_ep = &ep->ep_in;
+ else
+ musb_ep = &ep->ep_out;
+ if (!musb_ep->desc)
+ break;
+
+ handled = 1;
+ /* Ignore request if endpoint is wedged */
+ if (musb_ep->wedged)
+ break;
+
+ musb_ep_select(mbase, epnum);
+ if (is_in) {
+ csr = musb_readw(regs, MUSB_TXCSR);
+ csr |= MUSB_TXCSR_CLRDATATOG |
+ MUSB_TXCSR_P_WZC_BITS;
+ csr &= ~(MUSB_TXCSR_P_SENDSTALL |
+ MUSB_TXCSR_P_SENTSTALL |
+ MUSB_TXCSR_TXPKTRDY);
+ musb_writew(regs, MUSB_TXCSR, csr);
+ } else {
+ csr = musb_readw(regs, MUSB_RXCSR);
+ csr |= MUSB_RXCSR_CLRDATATOG |
+ MUSB_RXCSR_P_WZC_BITS;
+ csr &= ~(MUSB_RXCSR_P_SENDSTALL |
+ MUSB_RXCSR_P_SENTSTALL);
+ musb_writew(regs, MUSB_RXCSR, csr);
+ }
+
+ /* Maybe start the first request in the queue */
+ request = next_request(musb_ep);
+ if (!musb_ep->busy && request) {
+ dev_dbg(musb->controller, "restarting the request\n");
+ musb_ep_restart(musb, request);
+ }
+
+ /* select ep0 again */
+ musb_ep_select(mbase, 0);
+ } break;
+ default:
+ /* class, vendor, etc ... delegate */
+ handled = 0;
+ break;
+ }
+ break;
+
+ case USB_REQ_SET_FEATURE:
+ switch (recip) {
+ case USB_RECIP_DEVICE:
+ handled = 1;
+ switch (ctrlrequest->wValue) {
+ case USB_DEVICE_REMOTE_WAKEUP:
+ musb->may_wakeup = 1;
+ break;
+ case USB_DEVICE_TEST_MODE:
+ if (musb->g.speed != USB_SPEED_HIGH)
+ goto stall;
+ if (ctrlrequest->wIndex & 0xff)
+ goto stall;
+
+ switch (ctrlrequest->wIndex >> 8) {
+ case 1:
+ pr_debug("TEST_J\n");
+ /* TEST_J */
+ musb->test_mode_nr =
+ MUSB_TEST_J;
+ break;
+ case 2:
+ /* TEST_K */
+ pr_debug("TEST_K\n");
+ musb->test_mode_nr =
+ MUSB_TEST_K;
+ break;
+ case 3:
+ /* TEST_SE0_NAK */
+ pr_debug("TEST_SE0_NAK\n");
+ musb->test_mode_nr =
+ MUSB_TEST_SE0_NAK;
+ break;
+ case 4:
+ /* TEST_PACKET */
+ pr_debug("TEST_PACKET\n");
+ musb->test_mode_nr =
+ MUSB_TEST_PACKET;
+ break;
+
+ case 0xc0:
+ /* TEST_FORCE_HS */
+ pr_debug("TEST_FORCE_HS\n");
+ musb->test_mode_nr =
+ MUSB_TEST_FORCE_HS;
+ break;
+ case 0xc1:
+ /* TEST_FORCE_FS */
+ pr_debug("TEST_FORCE_FS\n");
+ musb->test_mode_nr =
+ MUSB_TEST_FORCE_FS;
+ break;
+ case 0xc2:
+ /* TEST_FIFO_ACCESS */
+ pr_debug("TEST_FIFO_ACCESS\n");
+ musb->test_mode_nr =
+ MUSB_TEST_FIFO_ACCESS;
+ break;
+ case 0xc3:
+ /* TEST_FORCE_HOST */
+ pr_debug("TEST_FORCE_HOST\n");
+ musb->test_mode_nr =
+ MUSB_TEST_FORCE_HOST;
+ break;
+ default:
+ goto stall;
+ }
+
+ /* enter test mode after irq */
+ if (handled > 0)
+ musb->test_mode = true;
+ break;
+ case USB_DEVICE_B_HNP_ENABLE:
+ if (!musb->g.is_otg)
+ goto stall;
+ musb->g.b_hnp_enable = 1;
+ musb_try_b_hnp_enable(musb);
+ break;
+ case USB_DEVICE_A_HNP_SUPPORT:
+ if (!musb->g.is_otg)
+ goto stall;
+ musb->g.a_hnp_support = 1;
+ break;
+ case USB_DEVICE_A_ALT_HNP_SUPPORT:
+ if (!musb->g.is_otg)
+ goto stall;
+ musb->g.a_alt_hnp_support = 1;
+ break;
+ case USB_DEVICE_DEBUG_MODE:
+ handled = 0;
+ break;
+stall:
+ default:
+ handled = -EINVAL;
+ break;
+ }
+ break;
+
+ case USB_RECIP_INTERFACE:
+ break;
+
+ case USB_RECIP_ENDPOINT:{
+ const u8 epnum =
+ ctrlrequest->wIndex & 0x0f;
+ struct musb_ep *musb_ep;
+ struct musb_hw_ep *ep;
+ void __iomem *regs;
+ int is_in;
+ u16 csr;
+
+ if (epnum == 0 || epnum >= MUSB_C_NUM_EPS ||
+ ctrlrequest->wValue != USB_ENDPOINT_HALT)
+ break;
+
+ ep = musb->endpoints + epnum;
+ regs = ep->regs;
+ is_in = ctrlrequest->wIndex & USB_DIR_IN;
+ if (is_in)
+ musb_ep = &ep->ep_in;
+ else
+ musb_ep = &ep->ep_out;
+ if (!musb_ep->desc)
+ break;
+
+ musb_ep_select(mbase, epnum);
+ if (is_in) {
+ csr = musb_readw(regs, MUSB_TXCSR);
+ if (csr & MUSB_TXCSR_FIFONOTEMPTY)
+ csr |= MUSB_TXCSR_FLUSHFIFO;
+ csr |= MUSB_TXCSR_P_SENDSTALL
+ | MUSB_TXCSR_CLRDATATOG
+ | MUSB_TXCSR_P_WZC_BITS;
+ musb_writew(regs, MUSB_TXCSR, csr);
+ } else {
+ csr = musb_readw(regs, MUSB_RXCSR);
+ csr |= MUSB_RXCSR_P_SENDSTALL
+ | MUSB_RXCSR_FLUSHFIFO
+ | MUSB_RXCSR_CLRDATATOG
+ | MUSB_RXCSR_P_WZC_BITS;
+ musb_writew(regs, MUSB_RXCSR, csr);
+ }
+
+ /* select ep0 again */
+ musb_ep_select(mbase, 0);
+ handled = 1;
+ } break;
+
+ default:
+ /* class, vendor, etc ... delegate */
+ handled = 0;
+ break;
+ }
+ break;
+ default:
+ /* delegate SET_CONFIGURATION, etc */
+ handled = 0;
+ }
+ } else
+ handled = 0;
+ return handled;
+}
+
+/* we have an ep0out data packet
+ * Context: caller holds controller lock
+ */
+static void ep0_rxstate(struct musb *musb)
+{
+ void __iomem *regs = musb->control_ep->regs;
+ struct musb_request *request;
+ struct usb_request *req;
+ u16 count, csr;
+
+ request = next_ep0_request(musb);
+ req = &request->request;
+
+ /* read packet and ack; or stall because of gadget driver bug:
+ * should have provided the rx buffer before setup() returned.
+ */
+ if (req) {
+ void *buf = req->buf + req->actual;
+ unsigned len = req->length - req->actual;
+
+ /* read the buffer */
+ count = musb_readb(regs, MUSB_COUNT0);
+ if (count > len) {
+ req->status = -EOVERFLOW;
+ count = len;
+ }
+ if (count > 0) {
+ musb_read_fifo(&musb->endpoints[0], count, buf);
+ req->actual += count;
+ }
+ csr = MUSB_CSR0_P_SVDRXPKTRDY;
+ if (count < 64 || req->actual == req->length) {
+ musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
+ csr |= MUSB_CSR0_P_DATAEND;
+ } else
+ req = NULL;
+ } else
+ csr = MUSB_CSR0_P_SVDRXPKTRDY | MUSB_CSR0_P_SENDSTALL;
+
+
+ /* Completion handler may choose to stall, e.g. because the
+ * message just received holds invalid data.
+ */
+ if (req) {
+ musb->ackpend = csr;
+ musb_g_ep0_giveback(musb, req);
+ if (!musb->ackpend)
+ return;
+ musb->ackpend = 0;
+ }
+ musb_ep_select(musb->mregs, 0);
+ musb_writew(regs, MUSB_CSR0, csr);
+}
+
+/*
+ * transmitting to the host (IN), this code might be called from IRQ
+ * and from kernel thread.
+ *
+ * Context: caller holds controller lock
+ */
+static void ep0_txstate(struct musb *musb)
+{
+ void __iomem *regs = musb->control_ep->regs;
+ struct musb_request *req = next_ep0_request(musb);
+ struct usb_request *request;
+ u16 csr = MUSB_CSR0_TXPKTRDY;
+ u8 *fifo_src;
+ u8 fifo_count;
+
+ if (!req) {
+ /* WARN_ON(1); */
+ dev_dbg(musb->controller, "odd; csr0 %04x\n", musb_readw(regs, MUSB_CSR0));
+ return;
+ }
+
+ request = &req->request;
+
+ /* load the data */
+ fifo_src = (u8 *) request->buf + request->actual;
+ fifo_count = min((unsigned) MUSB_EP0_FIFOSIZE,
+ request->length - request->actual);
+ musb_write_fifo(&musb->endpoints[0], fifo_count, fifo_src);
+ request->actual += fifo_count;
+
+ /* update the flags */
+ if (fifo_count < MUSB_MAX_END0_PACKET
+ || (request->actual == request->length
+ && !request->zero)) {
+ musb->ep0_state = MUSB_EP0_STAGE_STATUSOUT;
+ csr |= MUSB_CSR0_P_DATAEND;
+ } else
+ request = NULL;
+
+ /* report completions as soon as the fifo's loaded; there's no
+ * win in waiting till this last packet gets acked. (other than
+ * very precise fault reporting, needed by USB TMC; possible with
+ * this hardware, but not usable from portable gadget drivers.)
+ */
+ if (request) {
+ musb->ackpend = csr;
+ musb_g_ep0_giveback(musb, request);
+ if (!musb->ackpend)
+ return;
+ musb->ackpend = 0;
+ }
+
+ /* send it out, triggering a "txpktrdy cleared" irq */
+ musb_ep_select(musb->mregs, 0);
+ musb_writew(regs, MUSB_CSR0, csr);
+}
+
+/*
+ * Read a SETUP packet (struct usb_ctrlrequest) from the hardware.
+ * Fields are left in USB byte-order.
+ *
+ * Context: caller holds controller lock.
+ */
+static void
+musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req)
+{
+ struct musb_request *r;
+ void __iomem *regs = musb->control_ep->regs;
+
+ musb_read_fifo(&musb->endpoints[0], sizeof *req, (u8 *)req);
+
+ /* NOTE: earlier 2.6 versions changed setup packets to host
+ * order, but now USB packets always stay in USB byte order.
+ */
+ dev_dbg(musb->controller, "SETUP req%02x.%02x v%04x i%04x l%d\n",
+ req->bRequestType,
+ req->bRequest,
+ le16_to_cpu(req->wValue),
+ le16_to_cpu(req->wIndex),
+ le16_to_cpu(req->wLength));
+
+ /* clean up any leftover transfers */
+ r = next_ep0_request(musb);
+ if (r)
+ musb_g_ep0_giveback(musb, &r->request);
+
+ /* For zero-data requests we want to delay the STATUS stage to
+ * avoid SETUPEND errors. If we read data (OUT), delay accepting
+ * packets until there's a buffer to store them in.
+ *
+ * If we write data, the controller acts happier if we enable
+ * the TX FIFO right away, and give the controller a moment
+ * to switch modes...
+ */
+ musb->set_address = false;
+ musb->ackpend = MUSB_CSR0_P_SVDRXPKTRDY;
+ if (req->wLength == 0) {
+ if (req->bRequestType & USB_DIR_IN)
+ musb->ackpend |= MUSB_CSR0_TXPKTRDY;
+ musb->ep0_state = MUSB_EP0_STAGE_ACKWAIT;
+ } else if (req->bRequestType & USB_DIR_IN) {
+ musb->ep0_state = MUSB_EP0_STAGE_TX;
+ musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SVDRXPKTRDY);
+ while ((musb_readw(regs, MUSB_CSR0)
+ & MUSB_CSR0_RXPKTRDY) != 0)
+ musb->ackpend = 0;
+ } else
+ musb->ep0_state = MUSB_EP0_STAGE_RX;
+}
+
+static int
+forward_to_driver(struct musb *musb, const struct usb_ctrlrequest *ctrlrequest)
+__releases(musb->lock)
+__acquires(musb->lock)
+{
+ int retval;
+ if (!musb->gadget_driver)
+ return -EOPNOTSUPP;
+ spin_unlock(&musb->lock);
+ retval = musb->gadget_driver->setup(&musb->g, ctrlrequest);
+ spin_lock(&musb->lock);
+ return retval;
+}
+
+/*
+ * Handle peripheral ep0 interrupt
+ *
+ * Context: irq handler; we won't re-enter the driver that way.
+ */
+irqreturn_t musb_g_ep0_irq(struct musb *musb)
+{
+ u16 csr;
+ u16 len;
+ void __iomem *mbase = musb->mregs;
+ void __iomem *regs = musb->endpoints[0].regs;
+ irqreturn_t retval = IRQ_NONE;
+
+ musb_ep_select(mbase, 0); /* select ep0 */
+ csr = musb_readw(regs, MUSB_CSR0);
+ len = musb_readb(regs, MUSB_COUNT0);
+
+ dev_dbg(musb->controller, "csr %04x, count %d, ep0stage %s\n",
+ csr, len, decode_ep0stage(musb->ep0_state));
+
+ if (csr & MUSB_CSR0_P_DATAEND) {
+ /*
+ * If DATAEND is set we should not call the callback,
+ * hence the status stage is not complete.
+ */
+ return IRQ_HANDLED;
+ }
+
+ /* I sent a stall.. need to acknowledge it now.. */
+ if (csr & MUSB_CSR0_P_SENTSTALL) {
+ musb_writew(regs, MUSB_CSR0,
+ csr & ~MUSB_CSR0_P_SENTSTALL);
+ retval = IRQ_HANDLED;
+ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ csr = musb_readw(regs, MUSB_CSR0);
+ }
+
+ /* request ended "early" */
+ if (csr & MUSB_CSR0_P_SETUPEND) {
+ musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SVDSETUPEND);
+ retval = IRQ_HANDLED;
+ /* Transition into the early status phase */
+ switch (musb->ep0_state) {
+ case MUSB_EP0_STAGE_TX:
+ musb->ep0_state = MUSB_EP0_STAGE_STATUSOUT;
+ break;
+ case MUSB_EP0_STAGE_RX:
+ musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
+ break;
+ default:
+ dev_err(musb->controller, "SetupEnd came in a wrong ep0stage %s\n",
+ decode_ep0stage(musb->ep0_state));
+ }
+ csr = musb_readw(regs, MUSB_CSR0);
+ /* NOTE: request may need completion */
+ }
+
+ /* docs from Mentor only describe tx, rx, and idle/setup states.
+ * we need to handle nuances around status stages, and also the
+ * case where status and setup stages come back-to-back ...
+ */
+ switch (musb->ep0_state) {
+
+ case MUSB_EP0_STAGE_TX:
+ /* irq on clearing txpktrdy */
+ if ((csr & MUSB_CSR0_TXPKTRDY) == 0) {
+ ep0_txstate(musb);
+ retval = IRQ_HANDLED;
+ }
+ break;
+
+ case MUSB_EP0_STAGE_RX:
+ /* irq on set rxpktrdy */
+ if (csr & MUSB_CSR0_RXPKTRDY) {
+ ep0_rxstate(musb);
+ retval = IRQ_HANDLED;
+ }
+ break;
+
+ case MUSB_EP0_STAGE_STATUSIN:
+ /* end of sequence #2 (OUT/RX state) or #3 (no data) */
+
+ /* update address (if needed) only @ the end of the
+ * status phase per usb spec, which also guarantees
+ * we get 10 msec to receive this irq... until this
+ * is done we won't see the next packet.
+ */
+ if (musb->set_address) {
+ musb->set_address = false;
+ musb_writeb(mbase, MUSB_FADDR, musb->address);
+ }
+
+ /* enter test mode if needed (exit by reset) */
+ else if (musb->test_mode) {
+ dev_dbg(musb->controller, "entering TESTMODE\n");
+
+ if (MUSB_TEST_PACKET == musb->test_mode_nr)
+ musb_load_testpacket(musb);
+
+ musb_writeb(mbase, MUSB_TESTMODE,
+ musb->test_mode_nr);
+ }
+ /* FALLTHROUGH */
+
+ case MUSB_EP0_STAGE_STATUSOUT:
+ /* end of sequence #1: write to host (TX state) */
+ {
+ struct musb_request *req;
+
+ req = next_ep0_request(musb);
+ if (req)
+ musb_g_ep0_giveback(musb, &req->request);
+ }
+
+ /*
+ * In case when several interrupts can get coalesced,
+ * check to see if we've already received a SETUP packet...
+ */
+ if (csr & MUSB_CSR0_RXPKTRDY)
+ goto setup;
+
+ retval = IRQ_HANDLED;
+ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ break;
+
+ case MUSB_EP0_STAGE_IDLE:
+ /*
+ * This state is typically (but not always) indiscernible
+ * from the status states since the corresponding interrupts
+ * tend to happen within too little period of time (with only
+ * a zero-length packet in between) and so get coalesced...
+ */
+ retval = IRQ_HANDLED;
+ musb->ep0_state = MUSB_EP0_STAGE_SETUP;
+ /* FALLTHROUGH */
+
+ case MUSB_EP0_STAGE_SETUP:
+setup:
+ if (csr & MUSB_CSR0_RXPKTRDY) {
+ struct usb_ctrlrequest setup;
+ int handled = 0;
+
+ if (len != 8) {
+ dev_err(musb->controller, "SETUP packet len %d != 8 ?\n", len);
+ break;
+ }
+ musb_read_setup(musb, &setup);
+ retval = IRQ_HANDLED;
+
+ /* sometimes the RESET won't be reported */
+ if (unlikely(musb->g.speed == USB_SPEED_UNKNOWN)) {
+ u8 power;
+
+ printk(KERN_NOTICE "%s: peripheral reset "
+ "irq lost!\n",
+ musb_driver_name);
+ power = musb_readb(mbase, MUSB_POWER);
+ musb->g.speed = (power & MUSB_POWER_HSMODE)
+ ? USB_SPEED_HIGH : USB_SPEED_FULL;
+
+ }
+
+ switch (musb->ep0_state) {
+
+ /* sequence #3 (no data stage), includes requests
+ * we can't forward (notably SET_ADDRESS and the
+ * device/endpoint feature set/clear operations)
+ * plus SET_CONFIGURATION and others we must
+ */
+ case MUSB_EP0_STAGE_ACKWAIT:
+ handled = service_zero_data_request(
+ musb, &setup);
+
+ /*
+ * We're expecting no data in any case, so
+ * always set the DATAEND bit -- doing this
+ * here helps avoid SetupEnd interrupt coming
+ * in the idle stage when we're stalling...
+ */
+ musb->ackpend |= MUSB_CSR0_P_DATAEND;
+
+ /* status stage might be immediate */
+ if (handled > 0)
+ musb->ep0_state =
+ MUSB_EP0_STAGE_STATUSIN;
+ break;
+
+ /* sequence #1 (IN to host), includes GET_STATUS
+ * requests that we can't forward, GET_DESCRIPTOR
+ * and others that we must
+ */
+ case MUSB_EP0_STAGE_TX:
+ handled = service_in_request(musb, &setup);
+ if (handled > 0) {
+ musb->ackpend = MUSB_CSR0_TXPKTRDY
+ | MUSB_CSR0_P_DATAEND;
+ musb->ep0_state =
+ MUSB_EP0_STAGE_STATUSOUT;
+ }
+ break;
+
+ /* sequence #2 (OUT from host), always forward */
+ default: /* MUSB_EP0_STAGE_RX */
+ break;
+ }
+
+ dev_dbg(musb->controller, "handled %d, csr %04x, ep0stage %s\n",
+ handled, csr,
+ decode_ep0stage(musb->ep0_state));
+
+ /* unless we need to delegate this to the gadget
+ * driver, we know how to wrap this up: csr0 has
+ * not yet been written.
+ */
+ if (handled < 0)
+ goto stall;
+ else if (handled > 0)
+ goto finish;
+
+ handled = forward_to_driver(musb, &setup);
+ if (handled < 0) {
+ musb_ep_select(mbase, 0);
+stall:
+ dev_dbg(musb->controller, "stall (%d)\n", handled);
+ musb->ackpend |= MUSB_CSR0_P_SENDSTALL;
+ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+finish:
+ musb_writew(regs, MUSB_CSR0,
+ musb->ackpend);
+ musb->ackpend = 0;
+ }
+ }
+ break;
+
+ case MUSB_EP0_STAGE_ACKWAIT:
+ /* This should not happen. But happens with tusb6010 with
+ * g_file_storage and high speed. Do nothing.
+ */
+ retval = IRQ_HANDLED;
+ break;
+
+ default:
+ /* "can't happen" */
+ WARN_ON(1);
+ musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SENDSTALL);
+ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ break;
+ }
+
+ return retval;
+}
+
+
+static int
+musb_g_ep0_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc)
+{
+ /* always enabled */
+ return -EINVAL;
+}
+
+static int musb_g_ep0_disable(struct usb_ep *e)
+{
+ /* always enabled */
+ return -EINVAL;
+}
+
+static int
+musb_g_ep0_queue(struct usb_ep *e, struct usb_request *r)
+{
+ struct musb_ep *ep;
+ struct musb_request *req;
+ struct musb *musb;
+ int status;
+ unsigned long lockflags;
+ void __iomem *regs;
+
+ if (!e || !r)
+ return -EINVAL;
+
+ ep = to_musb_ep(e);
+ musb = ep->musb;
+ regs = musb->control_ep->regs;
+
+ req = to_musb_request(r);
+ req->musb = musb;
+ req->request.actual = 0;
+ req->request.status = -EINPROGRESS;
+ req->tx = ep->is_in;
+
+ spin_lock_irqsave(&musb->lock, lockflags);
+
+ if (!list_empty(&ep->req_list)) {
+ status = -EBUSY;
+ goto cleanup;
+ }
+
+ switch (musb->ep0_state) {
+ case MUSB_EP0_STAGE_RX: /* control-OUT data */
+ case MUSB_EP0_STAGE_TX: /* control-IN data */
+ case MUSB_EP0_STAGE_ACKWAIT: /* zero-length data */
+ status = 0;
+ break;
+ default:
+ dev_dbg(musb->controller, "ep0 request queued in state %d\n",
+ musb->ep0_state);
+ status = -EINVAL;
+ goto cleanup;
+ }
+
+ /* add request to the list */
+ list_add_tail(&req->list, &ep->req_list);
+
+ dev_dbg(musb->controller, "queue to %s (%s), length=%d\n",
+ ep->name, ep->is_in ? "IN/TX" : "OUT/RX",
+ req->request.length);
+
+ musb_ep_select(musb->mregs, 0);
+
+ /* sequence #1, IN ... start writing the data */
+ if (musb->ep0_state == MUSB_EP0_STAGE_TX)
+ ep0_txstate(musb);
+
+ /* sequence #3, no-data ... issue IN status */
+ else if (musb->ep0_state == MUSB_EP0_STAGE_ACKWAIT) {
+ if (req->request.length)
+ status = -EINVAL;
+ else {
+ musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
+ musb_writew(regs, MUSB_CSR0,
+ musb->ackpend | MUSB_CSR0_P_DATAEND);
+ musb->ackpend = 0;
+ musb_g_ep0_giveback(ep->musb, r);
+ }
+
+ /* else for sequence #2 (OUT), caller provides a buffer
+ * before the next packet arrives. deferred responses
+ * (after SETUP is acked) are racey.
+ */
+ } else if (musb->ackpend) {
+ musb_writew(regs, MUSB_CSR0, musb->ackpend);
+ musb->ackpend = 0;
+ }
+
+cleanup:
+ spin_unlock_irqrestore(&musb->lock, lockflags);
+ return status;
+}
+
+static int musb_g_ep0_dequeue(struct usb_ep *ep, struct usb_request *req)
+{
+ /* we just won't support this */
+ return -EINVAL;
+}
+
+static int musb_g_ep0_halt(struct usb_ep *e, int value)
+{
+ struct musb_ep *ep;
+ struct musb *musb;
+ void __iomem *base, *regs;
+ unsigned long flags;
+ int status;
+ u16 csr;
+
+ if (!e || !value)
+ return -EINVAL;
+
+ ep = to_musb_ep(e);
+ musb = ep->musb;
+ base = musb->mregs;
+ regs = musb->control_ep->regs;
+ status = 0;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ if (!list_empty(&ep->req_list)) {
+ status = -EBUSY;
+ goto cleanup;
+ }
+
+ musb_ep_select(base, 0);
+ csr = musb->ackpend;
+
+ switch (musb->ep0_state) {
+
+ /* Stalls are usually issued after parsing SETUP packet, either
+ * directly in irq context from setup() or else later.
+ */
+ case MUSB_EP0_STAGE_TX: /* control-IN data */
+ case MUSB_EP0_STAGE_ACKWAIT: /* STALL for zero-length data */
+ case MUSB_EP0_STAGE_RX: /* control-OUT data */
+ csr = musb_readw(regs, MUSB_CSR0);
+ /* FALLTHROUGH */
+
+ /* It's also OK to issue stalls during callbacks when a non-empty
+ * DATA stage buffer has been read (or even written).
+ */
+ case MUSB_EP0_STAGE_STATUSIN: /* control-OUT status */
+ case MUSB_EP0_STAGE_STATUSOUT: /* control-IN status */
+
+ csr |= MUSB_CSR0_P_SENDSTALL;
+ musb_writew(regs, MUSB_CSR0, csr);
+ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ musb->ackpend = 0;
+ break;
+ default:
+ dev_dbg(musb->controller, "ep0 can't halt in state %d\n", musb->ep0_state);
+ status = -EINVAL;
+ }
+
+cleanup:
+ spin_unlock_irqrestore(&musb->lock, flags);
+ return status;
+}
+
+const struct usb_ep_ops musb_g_ep0_ops = {
+ .enable = musb_g_ep0_enable,
+ .disable = musb_g_ep0_disable,
+ .alloc_request = musb_alloc_request,
+ .free_request = musb_free_request,
+ .queue = musb_g_ep0_queue,
+ .dequeue = musb_g_ep0_dequeue,
+ .set_halt = musb_g_ep0_halt,
+};
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
new file mode 100644
index 0000000000..32a8f06529
--- /dev/null
+++ b/drivers/usb/musb/musb_host.c
@@ -0,0 +1,1749 @@
+/*
+ * MUSB OTG driver host support
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ * Copyright (C) 2008-2009 MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include "musb_core.h"
+#include "musb_host.h"
+
+/* MUSB HOST status 22-mar-2006
+ *
+ * - There's still lots of partial code duplication for fault paths, so
+ * they aren't handled as consistently as they need to be.
+ *
+ * - PIO mostly behaved when last tested.
+ * + including ep0, with all usbtest cases 9, 10
+ * + usbtest 14 (ep0out) doesn't seem to run at all
+ * + double buffered OUT/TX endpoints saw stalls(!) with certain usbtest
+ * configurations, but otherwise double buffering passes basic tests.
+ * + for 2.6.N, for N > ~10, needs API changes for hcd framework.
+ *
+ * - DMA (CPPI) ... partially behaves, not currently recommended
+ * + about 1/15 the speed of typical EHCI implementations (PCI)
+ * + RX, all too often reqpkt seems to misbehave after tx
+ * + TX, no known issues (other than evident silicon issue)
+ *
+ * - DMA (Mentor/OMAP) ...has at least toggle update problems
+ *
+ * - [23-feb-2009] minimal traffic scheduling to avoid bulk RX packet
+ * starvation ... nothing yet for TX, interrupt, or bulk.
+ *
+ * - Not tested with HNP, but some SRP paths seem to behave.
+ *
+ * NOTE 24-August-2006:
+ *
+ * - Bulk traffic finally uses both sides of hardware ep1, freeing up an
+ * extra endpoint for periodic use enabling hub + keybd + mouse. That
+ * mostly works, except that with "usbnet" it's easy to trigger cases
+ * with "ping" where RX loses. (a) ping to davinci, even "ping -f",
+ * fine; but (b) ping _from_ davinci, even "ping -c 1", ICMP RX loses
+ * although ARP RX wins. (That test was done with a full speed link.)
+ */
+
+
+/*
+ * NOTE on endpoint usage:
+ *
+ * CONTROL transfers all go through ep0. BULK ones go through dedicated IN
+ * and OUT endpoints ... hardware is dedicated for those "async" queue(s).
+ * (Yes, bulk _could_ use more of the endpoints than that, and would even
+ * benefit from it.)
+ *
+ * INTERUPPT and ISOCHRONOUS transfers are scheduled to the other endpoints.
+ * So far that scheduling is both dumb and optimistic: the endpoint will be
+ * "claimed" until its software queue is no longer refilled. No multiplexing
+ * of transfers between endpoints, or anything clever.
+ */
+
+struct musb *hcd_to_musb(struct usb_hcd *hcd)
+{
+ return (struct musb *) hcd->hcd_priv;
+}
+
+
+static void musb_ep_program(struct musb *musb, u8 epnum,
+ struct urb *urb, int is_out,
+ u8 *buf, u32 offset, u32 len);
+
+/*
+ * Clear TX fifo. Needed to avoid BABBLE errors.
+ */
+static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
+{
+ struct musb *musb = ep->musb;
+ void __iomem *epio = ep->regs;
+ u16 csr;
+ u16 lastcsr = 0;
+ int retries = 1000;
+
+ csr = musb_readw(epio, MUSB_TXCSR);
+ while (csr & MUSB_TXCSR_FIFONOTEMPTY) {
+ if (csr != lastcsr)
+ dev_dbg(musb->controller, "Host TX FIFONOTEMPTY csr: %02x\n", csr);
+ lastcsr = csr;
+ csr |= MUSB_TXCSR_FLUSHFIFO;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ csr = musb_readw(epio, MUSB_TXCSR);
+ if (!retries--) {
+ dev_warn(musb->controller, "Could not flush host TX%d fifo: csr: %04x\n",
+ ep->epnum, csr);
+ return;
+ }
+ mdelay(1);
+ }
+}
+
+static void musb_h_ep0_flush_fifo(struct musb_hw_ep *ep)
+{
+ struct musb *musb = ep->musb;
+ void __iomem *epio = ep->regs;
+ u16 csr;
+ int retries = 5;
+
+ /* scrub any data left in the fifo */
+ do {
+ csr = musb_readw(epio, MUSB_TXCSR);
+ if (!(csr & (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_RXPKTRDY)))
+ break;
+ musb_writew(epio, MUSB_TXCSR, MUSB_CSR0_FLUSHFIFO);
+ csr = musb_readw(epio, MUSB_TXCSR);
+ udelay(10);
+ } while (--retries);
+
+ if (!retries)
+ dev_warn(musb->controller, "Could not flush host TX%d fifo: csr: %04x\n",
+ ep->epnum, csr);
+
+ /* and reset for the next transfer */
+ musb_writew(epio, MUSB_TXCSR, 0);
+}
+
+/*
+ * Start transmit. Caller is responsible for locking shared resources.
+ * musb must be locked.
+ */
+static inline void musb_h_tx_start(struct musb_hw_ep *ep)
+{
+ u16 txcsr;
+
+ /* NOTE: no locks here; caller should lock and select EP */
+ if (ep->epnum) {
+ txcsr = musb_readw(ep->regs, MUSB_TXCSR);
+ txcsr |= MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_H_WZC_BITS;
+ musb_writew(ep->regs, MUSB_TXCSR, txcsr);
+ } else {
+ txcsr = MUSB_CSR0_H_SETUPPKT | MUSB_CSR0_TXPKTRDY;
+ musb_writew(ep->regs, MUSB_CSR0, txcsr);
+ }
+
+}
+
+static inline void musb_h_tx_dma_start(struct musb_hw_ep *ep)
+{
+ u16 txcsr;
+
+ /* NOTE: no locks here; caller should lock and select EP */
+ txcsr = musb_readw(ep->regs, MUSB_TXCSR);
+ txcsr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_H_WZC_BITS;
+ if (is_cppi_enabled())
+ txcsr |= MUSB_TXCSR_DMAMODE;
+ musb_writew(ep->regs, MUSB_TXCSR, txcsr);
+}
+
+static void musb_ep_set_qh(struct musb_hw_ep *ep, int is_in, struct musb_qh *qh)
+{
+ if (is_in != 0 || ep->is_shared_fifo)
+ ep->in_qh = qh;
+ if (is_in == 0 || ep->is_shared_fifo)
+ ep->out_qh = qh;
+}
+
+static struct musb_qh *musb_ep_get_qh(struct musb_hw_ep *ep, int is_in)
+{
+ return is_in ? ep->in_qh : ep->out_qh;
+}
+
+/*
+ * Start the URB at the front of an endpoint's queue
+ * end must be claimed from the caller.
+ *
+ * Context: controller locked, irqs blocked
+ */
+static void
+musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
+{
+ u16 frame;
+ u32 len;
+ void __iomem *mbase = musb->mregs;
+ struct urb *urb = next_urb(qh);
+ void *buf = urb->transfer_buffer;
+ u32 offset = 0;
+ struct musb_hw_ep *hw_ep = qh->hw_ep;
+ unsigned pipe = urb->pipe;
+ u8 address = usb_pipedevice(pipe);
+ int epnum = hw_ep->epnum;
+
+ /* initialize software qh state */
+ qh->offset = 0;
+ qh->segsize = 0;
+
+ /* gather right source of data */
+ switch (qh->type) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ /* control transfers always start with SETUP */
+ is_in = 0;
+ musb->ep0_stage = MUSB_EP0_START;
+ buf = urb->setup_packet;
+ len = 8;
+ break;
+ default: /* bulk, interrupt */
+ /* actual_length may be nonzero on retry paths */
+ buf = urb->transfer_buffer + urb->actual_length;
+ len = urb->transfer_buffer_length - urb->actual_length;
+ }
+
+ dev_dbg(musb->controller, "qh %p urb %p dev%d ep%d%s%s, hw_ep %d, %p/%d\n",
+ qh, urb, address, qh->epnum,
+ is_in ? "in" : "out",
+ ({char *s; switch (qh->type) {
+ case USB_ENDPOINT_XFER_CONTROL: s = ""; break;
+ case USB_ENDPOINT_XFER_BULK: s = "-bulk"; break;
+ default: s = "-intr"; break;
+ } s; }),
+ epnum, buf + offset, len);
+
+ /* Configure endpoint */
+ musb_ep_set_qh(hw_ep, is_in, qh);
+ musb_ep_program(musb, epnum, urb, !is_in, buf, offset, len);
+
+ /* transmit may have more work: start it when it is time */
+ if (is_in)
+ return;
+
+ /* determine if the time is right for a periodic transfer */
+ switch (qh->type) {
+ case USB_ENDPOINT_XFER_INT:
+ dev_dbg(musb->controller, "check whether there's still time for periodic Tx\n");
+ frame = musb_readw(mbase, MUSB_FRAME);
+ /* FIXME this doesn't implement that scheduling policy ...
+ * or handle framecounter wrapping
+ */
+ if (1) { /* Always assume URB_ISO_ASAP */
+ /* REVISIT the SOF irq handler shouldn't duplicate
+ * this code; and we don't init urb->start_frame...
+ */
+ qh->frame = 0;
+ goto start;
+ } else {
+ qh->frame = urb->start_frame;
+ /* enable SOF interrupt so we can count down */
+ dev_dbg(musb->controller, "SOF for %d\n", epnum);
+#if 1 /* ifndef CONFIG_ARCH_DAVINCI */
+ musb_writeb(mbase, MUSB_INTRUSBE, 0xff);
+#endif
+ }
+ break;
+ default:
+start:
+ dev_dbg(musb->controller, "Start TX%d %s\n", epnum,
+ hw_ep->tx_channel ? "dma" : "pio");
+
+ if (!hw_ep->tx_channel)
+ musb_h_tx_start(hw_ep);
+ }
+}
+
+/* Context: caller owns controller lock, IRQs are blocked */
+static void musb_giveback(struct musb *musb, struct urb *urb, int status)
+__releases(musb->lock)
+__acquires(musb->lock)
+{
+ dev_dbg(musb->controller,
+ "complete %p %pF (%d), dev%d ep%d%s, %d/%d\n",
+ urb, urb->complete, status,
+ usb_pipedevice(urb->pipe),
+ usb_pipeendpoint(urb->pipe),
+ usb_pipein(urb->pipe) ? "in" : "out",
+ urb->actual_length, urb->transfer_buffer_length
+ );
+
+ usb_hcd_unlink_urb_from_ep(musb->hcd, urb);
+ spin_unlock(&musb->lock);
+ usb_hcd_giveback_urb(musb->hcd, urb, status);
+ spin_lock(&musb->lock);
+}
+
+/* For bulk/interrupt endpoints only */
+static inline void musb_save_toggle(struct musb_qh *qh, int is_in,
+ struct urb *urb)
+{
+ void __iomem *epio = qh->hw_ep->regs;
+ u16 csr;
+
+ /*
+ * FIXME: the current Mentor DMA code seems to have
+ * problems getting toggle correct.
+ */
+
+ if (is_in)
+ csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
+ else
+ csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
+
+ usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0);
+}
+
+/*
+ * Advance this hardware endpoint's queue, completing the specified URB and
+ * advancing to either the next URB queued to that qh, or else invalidating
+ * that qh and advancing to the next qh scheduled after the current one.
+ *
+ * Context: caller owns controller lock, IRQs are blocked
+ */
+static void musb_advance_schedule(struct musb *musb, struct urb *urb,
+ struct musb_hw_ep *hw_ep, int is_in)
+{
+ struct musb_qh *qh = musb_ep_get_qh(hw_ep, is_in);
+ struct musb_hw_ep *ep = qh->hw_ep;
+ int ready = qh->is_ready;
+ int status;
+
+ status = (urb->status == -EINPROGRESS) ? 0 : urb->status;
+
+ /* save toggle eagerly, for paranoia */
+ switch (qh->type) {
+ case USB_ENDPOINT_XFER_BULK:
+ case USB_ENDPOINT_XFER_INT:
+ musb_save_toggle(qh, is_in, urb);
+ break;
+ }
+
+ qh->is_ready = 0;
+ musb_giveback(musb, urb, status);
+ qh->is_ready = ready;
+
+ /* reclaim resources (and bandwidth) ASAP; deschedule it, and
+ * invalidate qh as soon as list_empty(&hep->urb_list)
+ */
+ if (list_empty(&qh->hep->urb_list)) {
+ struct list_head *head;
+ struct dma_controller *dma = musb->dma_controller;
+
+ if (is_in) {
+ ep->rx_reinit = 1;
+ if (ep->rx_channel) {
+ dma->channel_release(ep->rx_channel);
+ ep->rx_channel = NULL;
+ }
+ } else {
+ ep->tx_reinit = 1;
+ if (ep->tx_channel) {
+ dma->channel_release(ep->tx_channel);
+ ep->tx_channel = NULL;
+ }
+ }
+
+ /* Clobber old pointers to this qh */
+ musb_ep_set_qh(ep, is_in, NULL);
+ qh->hep->hcpriv = NULL;
+
+ switch (qh->type) {
+
+ case USB_ENDPOINT_XFER_CONTROL:
+ case USB_ENDPOINT_XFER_BULK:
+ /* fifo policy for these lists, except that NAKing
+ * should rotate a qh to the end (for fairness).
+ */
+ if (qh->mux == 1) {
+ head = qh->ring.prev;
+ list_del(&qh->ring);
+ kfree(qh);
+ qh = first_qh(head);
+ break;
+ }
+
+ case USB_ENDPOINT_XFER_INT:
+ /* this is where periodic bandwidth should be
+ * de-allocated if it's tracked and allocated;
+ * and where we'd update the schedule tree...
+ */
+ kfree(qh);
+ qh = NULL;
+ break;
+ }
+ }
+
+ if (qh != NULL && qh->is_ready) {
+ dev_dbg(musb->controller, "... next ep%d %cX urb %p\n",
+ hw_ep->epnum, is_in ? 'R' : 'T', next_urb(qh));
+ musb_start_urb(musb, is_in, qh);
+ }
+}
+
+static u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr)
+{
+ /* we don't want fifo to fill itself again;
+ * ignore dma (various models),
+ * leave toggle alone (may not have been saved yet)
+ */
+ csr |= MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_RXPKTRDY;
+ csr &= ~(MUSB_RXCSR_H_REQPKT
+ | MUSB_RXCSR_H_AUTOREQ
+ | MUSB_RXCSR_AUTOCLEAR);
+
+ /* write 2x to allow double buffering */
+ musb_writew(hw_ep->regs, MUSB_RXCSR, csr);
+ musb_writew(hw_ep->regs, MUSB_RXCSR, csr);
+
+ /* flush writebuffer */
+ return musb_readw(hw_ep->regs, MUSB_RXCSR);
+}
+
+/*
+ * PIO RX for a packet (or part of it).
+ */
+static bool
+musb_host_packet_rx(struct musb *musb, struct urb *urb, u8 epnum, u8 iso_err)
+{
+ u16 rx_count;
+ u8 *buf;
+ u16 csr;
+ bool done = false;
+ u32 length;
+ int do_flush = 0;
+ struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
+ void __iomem *epio = hw_ep->regs;
+ struct musb_qh *qh = hw_ep->in_qh;
+ void *buffer = urb->transfer_buffer;
+
+ /* musb_ep_select(mbase, epnum); */
+ rx_count = musb_readw(epio, MUSB_RXCOUNT);
+ dev_dbg(musb->controller, "RX%d count %d, buffer %p len %d/%d\n", epnum, rx_count,
+ urb->transfer_buffer, qh->offset,
+ urb->transfer_buffer_length);
+
+ /* unload FIFO */
+ if (0) {
+ } else {
+ /* non-isoch */
+ buf = buffer + qh->offset;
+ length = urb->transfer_buffer_length - qh->offset;
+ if (rx_count > length) {
+ if (urb->status == -EINPROGRESS)
+ urb->status = -EOVERFLOW;
+ dev_dbg(musb->controller, "** OVERFLOW %d into %d\n", rx_count, length);
+ do_flush = 1;
+ } else
+ length = rx_count;
+ urb->actual_length += length;
+ qh->offset += length;
+
+ /* see if we are done */
+ done = (urb->actual_length == urb->transfer_buffer_length)
+ || (rx_count < qh->maxpacket)
+ || (urb->status != -EINPROGRESS);
+ if (done
+ && (urb->status == -EINPROGRESS)
+ && (urb->transfer_flags & URB_SHORT_NOT_OK)
+ && (urb->actual_length
+ < urb->transfer_buffer_length))
+ urb->status = -EREMOTEIO;
+ }
+
+ musb_read_fifo(hw_ep, length, buf);
+
+ csr = musb_readw(epio, MUSB_RXCSR);
+ csr |= MUSB_RXCSR_H_WZC_BITS;
+ if (unlikely(do_flush))
+ musb_h_flush_rxfifo(hw_ep, csr);
+ else {
+ /* REVISIT this assumes AUTOCLEAR is never set */
+ csr &= ~(MUSB_RXCSR_RXPKTRDY | MUSB_RXCSR_H_REQPKT);
+ if (!done)
+ csr |= MUSB_RXCSR_H_REQPKT;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ }
+
+ return done;
+}
+
+/* we don't always need to reinit a given side of an endpoint...
+ * when we do, use tx/rx reinit routine and then construct a new CSR
+ * to address data toggle, NYET, and DMA or PIO.
+ *
+ * it's possible that driver bugs (especially for DMA) or aborting a
+ * transfer might have left the endpoint busier than it should be.
+ * the busy/not-empty tests are basically paranoia.
+ */
+static void
+musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep)
+{
+ u16 csr;
+
+ /* NOTE: we know the "rx" fifo reinit never triggers for ep0.
+ * That always uses tx_reinit since ep0 repurposes TX register
+ * offsets; the initial SETUP packet is also a kind of OUT.
+ */
+
+ /* if programmed for Tx, put it in RX mode */
+ if (ep->is_shared_fifo) {
+ csr = musb_readw(ep->regs, MUSB_TXCSR);
+ if (csr & MUSB_TXCSR_MODE) {
+ musb_h_tx_flush_fifo(ep);
+ csr = musb_readw(ep->regs, MUSB_TXCSR);
+ musb_writew(ep->regs, MUSB_TXCSR,
+ csr | MUSB_TXCSR_FRCDATATOG);
+ }
+
+ /*
+ * Clear the MODE bit (and everything else) to enable Rx.
+ * NOTE: we mustn't clear the DMAMODE bit before DMAENAB.
+ */
+ if (csr & MUSB_TXCSR_DMAMODE)
+ musb_writew(ep->regs, MUSB_TXCSR, MUSB_TXCSR_DMAMODE);
+ musb_writew(ep->regs, MUSB_TXCSR, 0);
+
+ /* scrub all previous state, clearing toggle */
+ } else {
+ csr = musb_readw(ep->regs, MUSB_RXCSR);
+ if (csr & MUSB_RXCSR_RXPKTRDY)
+ dev_warn(musb->controller, "rx%d, packet/%d ready?\n", ep->epnum,
+ musb_readw(ep->regs, MUSB_RXCOUNT));
+
+ musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG);
+ }
+
+ /* target addr and (for multipoint) hub addr/port */
+ if (musb->is_multipoint) {
+ musb_write_rxfunaddr(ep->target_regs, qh->addr_reg);
+ musb_write_rxhubaddr(ep->target_regs, qh->h_addr_reg);
+ musb_write_rxhubport(ep->target_regs, qh->h_port_reg);
+
+ } else
+ musb_writeb(musb->mregs, MUSB_FADDR, qh->addr_reg);
+
+ /* protocol/endpoint, interval/NAKlimit, i/o size */
+ musb_writeb(ep->regs, MUSB_RXTYPE, qh->type_reg);
+ musb_writeb(ep->regs, MUSB_RXINTERVAL, qh->intv_reg);
+ /* NOTE: bulk combining rewrites high bits of maxpacket */
+ /* Set RXMAXP with the FIFO size of the endpoint
+ * to disable double buffer mode.
+ */
+ if (musb->double_buffer_not_ok)
+ musb_writew(ep->regs, MUSB_RXMAXP, ep->max_packet_sz_rx);
+ else
+ musb_writew(ep->regs, MUSB_RXMAXP,
+ qh->maxpacket | ((qh->hb_mult - 1) << 11));
+
+ ep->rx_reinit = 0;
+}
+
+/*
+ * Program an HDRC endpoint as per the given URB
+ * Context: irqs blocked, controller lock held
+ */
+static void musb_ep_program(struct musb *musb, u8 epnum,
+ struct urb *urb, int is_out,
+ u8 *buf, u32 offset, u32 len)
+{
+ void __iomem *mbase = musb->mregs;
+ struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
+ void __iomem *epio = hw_ep->regs;
+ struct musb_qh *qh = musb_ep_get_qh(hw_ep, !is_out);
+ u16 packet_sz = qh->maxpacket;
+ u16 csr;
+
+ dev_dbg(musb->controller, "%s hw%d urb %p spd%d dev%d ep%d%s "
+ "h_addr%02x h_port%02x bytes %d\n",
+ is_out ? "-->" : "<--",
+ epnum, urb, urb->dev->speed,
+ qh->addr_reg, qh->epnum, is_out ? "out" : "in",
+ qh->h_addr_reg, qh->h_port_reg,
+ len);
+
+ musb_ep_select(mbase, epnum);
+
+ if (is_out && !len) {
+ csr = musb_readw(epio, MUSB_TXCSR);
+ csr &= ~MUSB_TXCSR_DMAENAB;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ hw_ep->tx_channel = NULL;
+ }
+
+ /* OUT/transmit/EP0 or IN/receive? */
+ if (is_out) {
+ u16 csr;
+ u16 int_txe;
+ u16 load_count;
+
+ csr = musb_readw(epio, MUSB_TXCSR);
+
+ /* disable interrupt in case we flush */
+ int_txe = musb->intrtxe;
+ musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
+
+ /* general endpoint setup */
+ if (epnum) {
+ /* flush all old state, set default */
+ /*
+ * We could be flushing valid
+ * packets in double buffering
+ * case
+ */
+ if (!hw_ep->tx_double_buffered)
+ musb_h_tx_flush_fifo(hw_ep);
+
+ /*
+ * We must not clear the DMAMODE bit before or in
+ * the same cycle with the DMAENAB bit, so we clear
+ * the latter first...
+ */
+ csr &= ~(MUSB_TXCSR_H_NAKTIMEOUT
+ | MUSB_TXCSR_AUTOSET
+ | MUSB_TXCSR_DMAENAB
+ | MUSB_TXCSR_FRCDATATOG
+ | MUSB_TXCSR_H_RXSTALL
+ | MUSB_TXCSR_H_ERROR
+ | MUSB_TXCSR_TXPKTRDY
+ );
+ csr |= MUSB_TXCSR_MODE;
+
+ if (!hw_ep->tx_double_buffered) {
+ if (usb_gettoggle(urb->dev, qh->epnum, 1))
+ csr |= MUSB_TXCSR_H_WR_DATATOGGLE
+ | MUSB_TXCSR_H_DATATOGGLE;
+ else
+ csr |= MUSB_TXCSR_CLRDATATOG;
+ }
+
+ musb_writew(epio, MUSB_TXCSR, csr);
+ /* REVISIT may need to clear FLUSHFIFO ... */
+ csr &= ~MUSB_TXCSR_DMAMODE;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ csr = musb_readw(epio, MUSB_TXCSR);
+ } else {
+ /* endpoint 0: just flush */
+ musb_h_ep0_flush_fifo(hw_ep);
+ }
+
+ /* target addr and (for multipoint) hub addr/port */
+ if (musb->is_multipoint) {
+ musb_write_txfunaddr(mbase, epnum, qh->addr_reg);
+ musb_write_txhubaddr(mbase, epnum, qh->h_addr_reg);
+ musb_write_txhubport(mbase, epnum, qh->h_port_reg);
+/* FIXME if !epnum, do the same for RX ... */
+ } else
+ musb_writeb(mbase, MUSB_FADDR, qh->addr_reg);
+
+ /* protocol/endpoint/interval/NAKlimit */
+ if (epnum) {
+ musb_writeb(epio, MUSB_TXTYPE, qh->type_reg);
+ if (musb->double_buffer_not_ok) {
+ musb_writew(epio, MUSB_TXMAXP,
+ hw_ep->max_packet_sz_tx);
+ } else if (can_bulk_split(musb, qh->type)) {
+ qh->hb_mult = hw_ep->max_packet_sz_tx
+ / packet_sz;
+ musb_writew(epio, MUSB_TXMAXP, packet_sz
+ | ((qh->hb_mult) - 1) << 11);
+ } else {
+ musb_writew(epio, MUSB_TXMAXP,
+ qh->maxpacket |
+ ((qh->hb_mult - 1) << 11));
+ }
+ musb_writeb(epio, MUSB_TXINTERVAL, qh->intv_reg);
+ } else {
+ musb_writeb(epio, MUSB_NAKLIMIT0, qh->intv_reg);
+ if (musb->is_multipoint)
+ musb_writeb(epio, MUSB_TYPE0,
+ qh->type_reg);
+ }
+
+ if (can_bulk_split(musb, qh->type))
+ load_count = min((u32) hw_ep->max_packet_sz_tx,
+ len);
+ else
+ load_count = min((u32) packet_sz, len);
+
+ if (load_count) {
+ /* PIO to load FIFO */
+ qh->segsize = load_count;
+ musb_write_fifo(hw_ep, load_count, buf);
+ }
+
+ /* re-enable interrupt */
+ musb_writew(mbase, MUSB_INTRTXE, int_txe);
+
+ /* IN/receive */
+ } else {
+ u16 csr;
+
+ if (hw_ep->rx_reinit) {
+ musb_rx_reinit(musb, qh, hw_ep);
+
+ /* init new state: toggle and NYET, maybe DMA later */
+ if (usb_gettoggle(urb->dev, qh->epnum, 0))
+ csr = MUSB_RXCSR_H_WR_DATATOGGLE
+ | MUSB_RXCSR_H_DATATOGGLE;
+ else
+ csr = 0;
+ if (qh->type == USB_ENDPOINT_XFER_INT)
+ csr |= MUSB_RXCSR_DISNYET;
+
+ } else {
+ csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
+
+ if (csr & (MUSB_RXCSR_RXPKTRDY
+ | MUSB_RXCSR_DMAENAB
+ | MUSB_RXCSR_H_REQPKT))
+ dev_err(musb->controller, "broken !rx_reinit, ep%d csr %04x\n",
+ hw_ep->epnum, csr);
+
+ /* scrub any stale state, leaving toggle alone */
+ csr &= MUSB_RXCSR_DISNYET;
+ }
+
+ /* kick things off */
+
+ csr |= MUSB_RXCSR_H_REQPKT;
+ dev_dbg(musb->controller, "RXCSR%d := %04x\n", epnum, csr);
+ musb_writew(hw_ep->regs, MUSB_RXCSR, csr);
+ csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
+ }
+}
+
+/* Schedule next QH from musb->in_bulk/out_bulk and move the current qh to
+ * the end; avoids starvation for other endpoints.
+ */
+static void musb_bulk_nak_timeout(struct musb *musb, struct musb_hw_ep *ep,
+ int is_in)
+{
+ struct urb *urb;
+ void __iomem *mbase = musb->mregs;
+ void __iomem *epio = ep->regs;
+ struct musb_qh *cur_qh, *next_qh;
+ u16 rx_csr, tx_csr;
+
+ musb_ep_select(mbase, ep->epnum);
+ if (is_in) {
+ /* clear nak timeout bit */
+ rx_csr = musb_readw(epio, MUSB_RXCSR);
+ rx_csr |= MUSB_RXCSR_H_WZC_BITS;
+ rx_csr &= ~MUSB_RXCSR_DATAERROR;
+ musb_writew(epio, MUSB_RXCSR, rx_csr);
+
+ cur_qh = first_qh(&musb->in_bulk);
+ } else {
+ /* clear nak timeout bit */
+ tx_csr = musb_readw(epio, MUSB_TXCSR);
+ tx_csr |= MUSB_TXCSR_H_WZC_BITS;
+ tx_csr &= ~MUSB_TXCSR_H_NAKTIMEOUT;
+ musb_writew(epio, MUSB_TXCSR, tx_csr);
+
+ cur_qh = first_qh(&musb->out_bulk);
+ }
+ if (cur_qh) {
+ urb = next_urb(cur_qh);
+ musb_save_toggle(cur_qh, is_in, urb);
+
+ if (is_in) {
+ /* move cur_qh to end of queue */
+ list_move_tail(&cur_qh->ring, &musb->in_bulk);
+
+ /* get the next qh from musb->in_bulk */
+ next_qh = first_qh(&musb->in_bulk);
+
+ /* set rx_reinit and schedule the next qh */
+ ep->rx_reinit = 1;
+ } else {
+ /* move cur_qh to end of queue */
+ list_move_tail(&cur_qh->ring, &musb->out_bulk);
+
+ /* get the next qh from musb->out_bulk */
+ next_qh = first_qh(&musb->out_bulk);
+
+ /* set tx_reinit and schedule the next qh */
+ ep->tx_reinit = 1;
+ }
+ musb_start_urb(musb, is_in, next_qh);
+ }
+}
+
+/*
+ * Service the default endpoint (ep0) as host.
+ * Return true until it's time to start the status stage.
+ */
+static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb)
+{
+ bool more = false;
+ u8 *fifo_dest = NULL;
+ u16 fifo_count = 0;
+ struct musb_hw_ep *hw_ep = musb->control_ep;
+ struct musb_qh *qh = hw_ep->in_qh;
+ struct usb_ctrlrequest *request;
+
+ switch (musb->ep0_stage) {
+ case MUSB_EP0_IN:
+ fifo_dest = urb->transfer_buffer + urb->actual_length;
+ fifo_count = min_t(size_t, len, urb->transfer_buffer_length -
+ urb->actual_length);
+ if (fifo_count < len)
+ urb->status = -EOVERFLOW;
+
+ musb_read_fifo(hw_ep, fifo_count, fifo_dest);
+
+ urb->actual_length += fifo_count;
+ if (len < qh->maxpacket) {
+ /* always terminate on short read; it's
+ * rarely reported as an error.
+ */
+ } else if (urb->actual_length <
+ urb->transfer_buffer_length)
+ more = true;
+ break;
+ case MUSB_EP0_START:
+ request = (struct usb_ctrlrequest *) urb->setup_packet;
+
+ if (!request->wLength) {
+ dev_dbg(musb->controller, "start no-DATA\n");
+ break;
+ } else if (request->bRequestType & USB_DIR_IN) {
+ dev_dbg(musb->controller, "start IN-DATA\n");
+ musb->ep0_stage = MUSB_EP0_IN;
+ more = true;
+ break;
+ } else {
+ dev_dbg(musb->controller, "start OUT-DATA\n");
+ musb->ep0_stage = MUSB_EP0_OUT;
+ more = true;
+ }
+ /* FALLTHROUGH */
+ case MUSB_EP0_OUT:
+ fifo_count = min_t(size_t, qh->maxpacket,
+ urb->transfer_buffer_length -
+ urb->actual_length);
+ if (fifo_count) {
+ fifo_dest = (u8 *) (urb->transfer_buffer
+ + urb->actual_length);
+ dev_dbg(musb->controller, "Sending %d byte%s to ep0 fifo %p\n",
+ fifo_count,
+ (fifo_count == 1) ? "" : "s",
+ fifo_dest);
+ musb_write_fifo(hw_ep, fifo_count, fifo_dest);
+
+ urb->actual_length += fifo_count;
+ more = true;
+ }
+ break;
+ default:
+ dev_err(musb->controller, "bogus ep0 stage %d\n", musb->ep0_stage);
+ break;
+ }
+
+ return more;
+}
+
+/*
+ * Handle default endpoint interrupt as host. Only called in IRQ time
+ * from musb_interrupt().
+ *
+ * called with controller irqlocked
+ */
+irqreturn_t musb_h_ep0_irq(struct musb *musb)
+{
+ struct urb *urb;
+ u16 csr, len;
+ int status = 0;
+ void __iomem *mbase = musb->mregs;
+ struct musb_hw_ep *hw_ep = musb->control_ep;
+ void __iomem *epio = hw_ep->regs;
+ struct musb_qh *qh = hw_ep->in_qh;
+ bool complete = false;
+ irqreturn_t retval = IRQ_NONE;
+
+ /* ep0 only has one queue, "in" */
+ urb = next_urb(qh);
+
+ musb_ep_select(mbase, 0);
+ csr = musb_readw(epio, MUSB_CSR0);
+ len = (csr & MUSB_CSR0_RXPKTRDY)
+ ? musb_readb(epio, MUSB_COUNT0)
+ : 0;
+
+ dev_dbg(musb->controller, "<== csr0 %04x, qh %p, count %d, urb %p, stage %d\n",
+ csr, qh, len, urb, musb->ep0_stage);
+
+ /* if we just did status stage, we are done */
+ if (MUSB_EP0_STATUS == musb->ep0_stage) {
+ retval = IRQ_HANDLED;
+ complete = true;
+ }
+
+ /* prepare status */
+ if (csr & MUSB_CSR0_H_RXSTALL) {
+ dev_dbg(musb->controller, "STALLING ENDPOINT\n");
+ status = -EPIPE;
+
+ } else if (csr & MUSB_CSR0_H_ERROR) {
+ dev_dbg(musb->controller, "no response, csr0 %04x\n", csr);
+ status = -EPROTO;
+
+ } else if (csr & MUSB_CSR0_H_NAKTIMEOUT) {
+ dev_dbg(musb->controller, "control NAK timeout\n");
+
+ /* NOTE: this code path would be a good place to PAUSE a
+ * control transfer, if another one is queued, so that
+ * ep0 is more likely to stay busy. That's already done
+ * for bulk RX transfers.
+ *
+ * if (qh->ring.next != &musb->control), then
+ * we have a candidate... NAKing is *NOT* an error
+ */
+ musb_writew(epio, MUSB_CSR0, 0);
+ retval = IRQ_HANDLED;
+ }
+
+ if (status) {
+ dev_dbg(musb->controller, "aborting\n");
+ retval = IRQ_HANDLED;
+ if (urb)
+ urb->status = status;
+ complete = true;
+
+ /* use the proper sequence to abort the transfer */
+ if (csr & MUSB_CSR0_H_REQPKT) {
+ csr &= ~MUSB_CSR0_H_REQPKT;
+ musb_writew(epio, MUSB_CSR0, csr);
+ csr &= ~MUSB_CSR0_H_NAKTIMEOUT;
+ musb_writew(epio, MUSB_CSR0, csr);
+ } else {
+ musb_h_ep0_flush_fifo(hw_ep);
+ }
+
+ musb_writeb(epio, MUSB_NAKLIMIT0, 0);
+
+ /* clear it */
+ musb_writew(epio, MUSB_CSR0, 0);
+ }
+
+ if (unlikely(!urb)) {
+ /* stop endpoint since we have no place for its data, this
+ * SHOULD NEVER HAPPEN! */
+ dev_err(musb->controller, "no URB for end 0\n");
+
+ musb_h_ep0_flush_fifo(hw_ep);
+ goto done;
+ }
+
+ if (!complete) {
+ /* call common logic and prepare response */
+ if (musb_h_ep0_continue(musb, len, urb)) {
+ /* more packets required */
+ csr = (MUSB_EP0_IN == musb->ep0_stage)
+ ? MUSB_CSR0_H_REQPKT : MUSB_CSR0_TXPKTRDY;
+ } else {
+ /* data transfer complete; perform status phase */
+ if (usb_pipeout(urb->pipe)
+ || !urb->transfer_buffer_length)
+ csr = MUSB_CSR0_H_STATUSPKT
+ | MUSB_CSR0_H_REQPKT;
+ else
+ csr = MUSB_CSR0_H_STATUSPKT
+ | MUSB_CSR0_TXPKTRDY;
+
+ /* flag status stage */
+ musb->ep0_stage = MUSB_EP0_STATUS;
+
+ dev_dbg(musb->controller, "ep0 STATUS, csr %04x\n", csr);
+
+ }
+ musb_writew(epio, MUSB_CSR0, csr);
+ retval = IRQ_HANDLED;
+ } else
+ musb->ep0_stage = MUSB_EP0_IDLE;
+
+ /* call completion handler if done */
+ if (complete)
+ musb_advance_schedule(musb, urb, hw_ep, 1);
+done:
+ return retval;
+}
+
+/* Service a Tx-Available or dma completion irq for the endpoint */
+void musb_host_tx(struct musb *musb, u8 epnum)
+{
+ int pipe;
+ bool done = false;
+ u16 tx_csr;
+ size_t length = 0;
+ size_t offset = 0;
+ struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
+ void __iomem *epio = hw_ep->regs;
+ struct musb_qh *qh = hw_ep->out_qh;
+ struct urb *urb = next_urb(qh);
+ u32 status = 0;
+ void __iomem *mbase = musb->mregs;
+ bool transfer_pending = false;
+
+ musb_ep_select(mbase, epnum);
+ tx_csr = musb_readw(epio, MUSB_TXCSR);
+
+ /* with CPPI, DMA sometimes triggers "extra" irqs */
+ if (!urb) {
+ dev_dbg(musb->controller, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
+ return;
+ }
+
+ pipe = urb->pipe;
+ dev_dbg(musb->controller, "OUT/TX%d end, csr %04x\n", epnum, tx_csr);
+
+ /* check for errors */
+ if (tx_csr & MUSB_TXCSR_H_RXSTALL) {
+ /* dma was disabled, fifo flushed */
+ dev_dbg(musb->controller, "TX end %d stall\n", epnum);
+
+ /* stall; record URB status */
+ status = -EPIPE;
+
+ } else if (tx_csr & MUSB_TXCSR_H_ERROR) {
+ /* (NON-ISO) dma was disabled, fifo flushed */
+ dev_dbg(musb->controller, "TX 3strikes on ep=%d\n", epnum);
+
+ status = -ETIMEDOUT;
+
+ } else if (tx_csr & MUSB_TXCSR_H_NAKTIMEOUT) {
+ if (USB_ENDPOINT_XFER_BULK == qh->type && qh->mux == 1
+ && !list_is_singular(&musb->out_bulk)) {
+ dev_dbg(musb->controller,
+ "NAK timeout on TX%d ep\n", epnum);
+ musb_bulk_nak_timeout(musb, hw_ep, 0);
+ } else {
+ dev_dbg(musb->controller,
+ "TX end=%d device not responding\n", epnum);
+ /* NOTE: this code path would be a good place to PAUSE a
+ * transfer, if there's some other (nonperiodic) tx urb
+ * that could use this fifo. (dma complicates it...)
+ * That's already done for bulk RX transfers.
+ *
+ * if (bulk && qh->ring.next != &musb->out_bulk), then
+ * we have a candidate... NAKing is *NOT* an error
+ */
+ musb_ep_select(mbase, epnum);
+ musb_writew(epio, MUSB_TXCSR,
+ MUSB_TXCSR_H_WZC_BITS
+ | MUSB_TXCSR_TXPKTRDY);
+ }
+ return;
+ }
+
+ if (status) {
+ /* do the proper sequence to abort the transfer in the
+ * usb core; the dma engine should already be stopped.
+ */
+ musb_h_tx_flush_fifo(hw_ep);
+ tx_csr &= ~(MUSB_TXCSR_AUTOSET
+ | MUSB_TXCSR_DMAENAB
+ | MUSB_TXCSR_H_ERROR
+ | MUSB_TXCSR_H_RXSTALL
+ | MUSB_TXCSR_H_NAKTIMEOUT
+ );
+
+ musb_ep_select(mbase, epnum);
+ musb_writew(epio, MUSB_TXCSR, tx_csr);
+ /* REVISIT may need to clear FLUSHFIFO ... */
+ musb_writew(epio, MUSB_TXCSR, tx_csr);
+ musb_writeb(epio, MUSB_TXINTERVAL, 0);
+
+ done = true;
+ }
+
+ if (!status) {
+ length = qh->segsize;
+ qh->offset += length;
+
+ if (0) {
+ } else {
+ /* see if we need to send more data, or ZLP */
+ if (qh->segsize < qh->maxpacket)
+ done = true;
+ else if (qh->offset == urb->transfer_buffer_length
+ && !(urb->transfer_flags
+ & URB_ZERO_PACKET))
+ done = true;
+ if (!done) {
+ offset = qh->offset;
+ length = urb->transfer_buffer_length - offset;
+ transfer_pending = true;
+ }
+ }
+ }
+
+ /* urb->status != -EINPROGRESS means request has been faulted,
+ * so we must abort this transfer after cleanup
+ */
+ if (urb->status != -EINPROGRESS) {
+ done = true;
+ if (status == 0)
+ status = urb->status;
+ }
+
+ if (done) {
+ /* set status */
+ urb->status = status;
+ urb->actual_length = qh->offset;
+ musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT);
+ return;
+ } else if (tx_csr & MUSB_TXCSR_DMAENAB) {
+ dev_dbg(musb->controller, "not complete, but DMA enabled?\n");
+ return;
+ }
+
+ /*
+ * PIO: start next packet in this URB.
+ *
+ * REVISIT: some docs say that when hw_ep->tx_double_buffered,
+ * (and presumably, FIFO is not half-full) we should write *two*
+ * packets before updating TXCSR; other docs disagree...
+ */
+ if (length > qh->maxpacket)
+ length = qh->maxpacket;
+
+ musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset);
+
+ qh->segsize = length;
+
+ musb_ep_select(mbase, epnum);
+ musb_writew(epio, MUSB_TXCSR,
+ MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
+}
+
+/*
+ * Service an RX interrupt for the given IN endpoint; docs cover bulk, iso,
+ * and high-bandwidth IN transfer cases.
+ */
+void musb_host_rx(struct musb *musb, u8 epnum)
+{
+ struct urb *urb;
+ struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
+ void __iomem *epio = hw_ep->regs;
+ struct musb_qh *qh = hw_ep->in_qh;
+ size_t xfer_len;
+ void __iomem *mbase = musb->mregs;
+ int pipe;
+ u16 rx_csr, val;
+ bool iso_err = false;
+ bool done = false;
+ u32 status;
+
+ musb_ep_select(mbase, epnum);
+
+ urb = next_urb(qh);
+ status = 0;
+ xfer_len = 0;
+
+ rx_csr = musb_readw(epio, MUSB_RXCSR);
+ val = rx_csr;
+
+ if (unlikely(!urb)) {
+ /* REVISIT -- THIS SHOULD NEVER HAPPEN ... but, at least
+ * usbtest #11 (unlinks) triggers it regularly, sometimes
+ * with fifo full. (Only with DMA??)
+ */
+ dev_dbg(musb->controller, "BOGUS RX%d ready, csr %04x, count %d\n", epnum, val,
+ musb_readw(epio, MUSB_RXCOUNT));
+ musb_h_flush_rxfifo(hw_ep, MUSB_RXCSR_CLRDATATOG);
+ return;
+ }
+
+ pipe = urb->pipe;
+
+ dev_dbg(musb->controller, "<== hw %d rxcsr %04x, urb actual %d (+dma %zu)\n",
+ epnum, rx_csr, urb->actual_length, 0);
+
+ /* check for errors, concurrent stall & unlink is not really
+ * handled yet! */
+ if (rx_csr & MUSB_RXCSR_H_RXSTALL) {
+ dev_dbg(musb->controller, "RX end %d STALL\n", epnum);
+
+ /* stall; record URB status */
+ status = -EPIPE;
+
+ } else if (rx_csr & MUSB_RXCSR_H_ERROR) {
+ dev_dbg(musb->controller, "end %d RX proto error\n", epnum);
+
+ status = -EPROTO;
+ musb_writeb(epio, MUSB_RXINTERVAL, 0);
+
+ } else if (rx_csr & MUSB_RXCSR_DATAERROR) {
+
+ if (USB_ENDPOINT_XFER_ISOC != qh->type) {
+ dev_dbg(musb->controller, "RX end %d NAK timeout\n", epnum);
+
+ /* NOTE: NAKing is *NOT* an error, so we want to
+ * continue. Except ... if there's a request for
+ * another QH, use that instead of starving it.
+ *
+ * Devices like Ethernet and serial adapters keep
+ * reads posted at all times, which will starve
+ * other devices without this logic.
+ */
+ if (usb_pipebulk(urb->pipe)
+ && qh->mux == 1
+ && !list_is_singular(&musb->in_bulk)) {
+ musb_bulk_nak_timeout(musb, hw_ep, 1);
+ return;
+ }
+ musb_ep_select(mbase, epnum);
+ rx_csr |= MUSB_RXCSR_H_WZC_BITS;
+ rx_csr &= ~MUSB_RXCSR_DATAERROR;
+ musb_writew(epio, MUSB_RXCSR, rx_csr);
+
+ goto finish;
+ } else {
+ dev_dbg(musb->controller, "RX end %d ISO data error\n", epnum);
+ /* packet error reported later */
+ iso_err = true;
+ }
+ } else if (rx_csr & MUSB_RXCSR_INCOMPRX) {
+ dev_dbg(musb->controller, "end %d high bandwidth incomplete ISO packet RX\n",
+ epnum);
+ status = -EPROTO;
+ }
+
+ /* faults abort the transfer */
+ if (status) {
+ musb_h_flush_rxfifo(hw_ep, MUSB_RXCSR_CLRDATATOG);
+ musb_writeb(epio, MUSB_RXINTERVAL, 0);
+ done = true;
+ goto finish;
+ }
+
+ /* thorough shutdown for now ... given more precise fault handling
+ * and better queueing support, we might keep a DMA pipeline going
+ * while processing this irq for earlier completions.
+ */
+
+ if (rx_csr & MUSB_RXCSR_H_REQPKT) {
+ dev_dbg(musb->controller, "RXCSR%d %04x, reqpkt, len %zu%s\n", epnum, rx_csr,
+ xfer_len, "");
+ rx_csr &= ~MUSB_RXCSR_H_REQPKT;
+
+ musb_ep_select(mbase, epnum);
+ musb_writew(epio, MUSB_RXCSR,
+ MUSB_RXCSR_H_WZC_BITS | rx_csr);
+ }
+
+ if (urb->status == -EINPROGRESS) {
+ /* if no errors, be sure a packet is ready for unloading */
+ if (unlikely(!(rx_csr & MUSB_RXCSR_RXPKTRDY))) {
+ status = -EPROTO;
+ dev_err(musb->controller, "Rx interrupt with no errors or packet!\n");
+
+ /* FIXME this is another "SHOULD NEVER HAPPEN" */
+
+/* SCRUB (RX) */
+ /* do the proper sequence to abort the transfer */
+ musb_ep_select(mbase, epnum);
+ val &= ~MUSB_RXCSR_H_REQPKT;
+ musb_writew(epio, MUSB_RXCSR, val);
+ goto finish;
+ }
+
+ /* we are expecting IN packets */
+ if (1) {
+ done = musb_host_packet_rx(musb, urb,
+ epnum, iso_err);
+
+ dev_dbg(musb->controller, "read %spacket\n", done ? "last " : "");
+ }
+ }
+
+finish:
+ urb->actual_length += xfer_len;
+ qh->offset += xfer_len;
+ if (done) {
+
+ if (urb->status == -EINPROGRESS)
+ urb->status = status;
+ musb_advance_schedule(musb, urb, hw_ep, USB_DIR_IN);
+ }
+}
+
+/* schedule nodes correspond to peripheral endpoints, like an OHCI QH.
+ * the software schedule associates multiple such nodes with a given
+ * host side hardware endpoint + direction; scheduling may activate
+ * that hardware endpoint.
+ */
+static int musb_schedule(
+ struct musb *musb,
+ struct musb_qh *qh,
+ int is_in)
+{
+ int idle;
+ int best_diff;
+ int best_end, epnum;
+ struct musb_hw_ep *hw_ep = NULL;
+ struct list_head *head = NULL;
+ u8 toggle;
+ u8 txtype;
+ struct urb *urb = next_urb(qh);
+
+ /* use fixed hardware for control and bulk */
+ if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
+ head = &musb->control;
+ hw_ep = musb->control_ep;
+ goto success;
+ }
+
+ /* else, periodic transfers get muxed to other endpoints */
+
+ /*
+ * We know this qh hasn't been scheduled, so all we need to do
+ * is choose which hardware endpoint to put it on ...
+ *
+ * REVISIT what we really want here is a regular schedule tree
+ * like e.g. OHCI uses.
+ */
+ best_diff = 4096;
+ best_end = -1;
+
+ for (epnum = 1, hw_ep = musb->endpoints + 1;
+ epnum < musb->nr_endpoints;
+ epnum++, hw_ep++) {
+ int diff;
+
+ if (musb_ep_get_qh(hw_ep, is_in) != NULL)
+ continue;
+
+ if (hw_ep == musb->bulk_ep)
+ continue;
+
+ if (is_in)
+ diff = hw_ep->max_packet_sz_rx;
+ else
+ diff = hw_ep->max_packet_sz_tx;
+ diff -= (qh->maxpacket * qh->hb_mult);
+
+ if (diff >= 0 && best_diff > diff) {
+
+ /*
+ * Mentor controller has a bug in that if we schedule
+ * a BULK Tx transfer on an endpoint that had earlier
+ * handled ISOC then the BULK transfer has to start on
+ * a zero toggle. If the BULK transfer starts on a 1
+ * toggle then this transfer will fail as the mentor
+ * controller starts the Bulk transfer on a 0 toggle
+ * irrespective of the programming of the toggle bits
+ * in the TXCSR register. Check for this condition
+ * while allocating the EP for a Tx Bulk transfer. If
+ * so skip this EP.
+ */
+ hw_ep = musb->endpoints + epnum;
+ toggle = usb_gettoggle(urb->dev, qh->epnum, !is_in);
+ txtype = (musb_readb(hw_ep->regs, MUSB_TXTYPE)
+ >> 4) & 0x3;
+ if (!is_in && (qh->type == USB_ENDPOINT_XFER_BULK) &&
+ toggle && (txtype == USB_ENDPOINT_XFER_ISOC))
+ continue;
+
+ best_diff = diff;
+ best_end = epnum;
+ }
+ }
+ /* use bulk reserved ep1 if no other ep is free */
+ if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
+ hw_ep = musb->bulk_ep;
+ if (is_in)
+ head = &musb->in_bulk;
+ else
+ head = &musb->out_bulk;
+
+ /* Enable bulk RX/TX NAK timeout scheme when bulk requests are
+ * multiplexed. This scheme doen't work in high speed to full
+ * speed scenario as NAK interrupts are not coming from a
+ * full speed device connected to a high speed device.
+ * NAK timeout interval is 8 (128 uframe or 16ms) for HS and
+ * 4 (8 frame or 8ms) for FS device.
+ */
+ if (qh->dev)
+ qh->intv_reg =
+ (USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4;
+ goto success;
+ } else if (best_end < 0) {
+ return -ENOSPC;
+ }
+
+ idle = 1;
+ qh->mux = 0;
+ hw_ep = musb->endpoints + best_end;
+ dev_dbg(musb->controller, "qh %p periodic slot %d\n", qh, best_end);
+success:
+ if (head) {
+ idle = list_empty(head);
+ list_add_tail(&qh->ring, head);
+ qh->mux = 1;
+ }
+ qh->hw_ep = hw_ep;
+ qh->hep->hcpriv = qh;
+ if (idle)
+ musb_start_urb(musb, is_in, qh);
+ return 0;
+}
+
+
+/* check if transaction translator is needed for device */
+static int tt_needed(struct musb *musb, struct usb_device *dev)
+{
+ if ((musb_readb(musb->mregs, MUSB_POWER) & MUSB_POWER_HSMODE) &&
+ (dev->speed < USB_SPEED_HIGH))
+ return 1;
+ return 0;
+}
+
+int musb_urb_enqueue(
+ struct usb_hcd *hcd,
+ struct urb *urb,
+ gfp_t mem_flags)
+{
+ unsigned long flags;
+ struct musb *musb = hcd_to_musb(hcd);
+ struct usb_host_endpoint *hep = urb->ep;
+ struct musb_qh *qh;
+ struct usb_endpoint_descriptor *epd = &hep->desc;
+ int ret;
+ unsigned type_reg;
+ unsigned interval;
+ /* host role must be active */
+ if (!is_host_active(musb) || !musb->is_active)
+ return -ENODEV;
+
+ spin_lock_irqsave(&musb->lock, flags);
+ ret = usb_hcd_link_urb_to_ep(hcd, urb);
+ qh = ret ? NULL : hep->hcpriv;
+ if (qh)
+ urb->hcpriv = qh;
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ /* DMA mapping was already done, if needed, and this urb is on
+ * hep->urb_list now ... so we're done, unless hep wasn't yet
+ * scheduled onto a live qh.
+ *
+ * REVISIT best to keep hep->hcpriv valid until the endpoint gets
+ * disabled, testing for empty qh->ring and avoiding qh setup costs
+ * except for the first urb queued after a config change.
+ */
+ if (qh || ret)
+ return ret;
+
+ /* Allocate and initialize qh, minimizing the work done each time
+ * hw_ep gets reprogrammed, or with irqs blocked. Then schedule it.
+ *
+ * REVISIT consider a dedicated qh kmem_cache, so it's harder
+ * for bugs in other kernel code to break this driver...
+ */
+ qh = kzalloc(sizeof *qh, mem_flags);
+ if (!qh) {
+ spin_lock_irqsave(&musb->lock, flags);
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+ spin_unlock_irqrestore(&musb->lock, flags);
+ return -ENOMEM;
+ }
+
+ qh->hep = hep;
+ qh->dev = urb->dev;
+ INIT_LIST_HEAD(&qh->ring);
+ qh->is_ready = 1;
+
+ qh->maxpacket = usb_endpoint_maxp(epd);
+ qh->type = usb_endpoint_type(epd);
+
+ /* Bits 11 & 12 of wMaxPacketSize encode high bandwidth multiplier.
+ * Some musb cores don't support high bandwidth ISO transfers; and
+ * we don't (yet!) support high bandwidth interrupt transfers.
+ */
+ qh->hb_mult = 1 + ((qh->maxpacket >> 11) & 0x03);
+ if (qh->hb_mult > 1) {
+ int ok = (qh->type == USB_ENDPOINT_XFER_ISOC);
+
+ if (ok)
+ ok = (usb_pipein(urb->pipe) && musb->hb_iso_rx)
+ || (usb_pipeout(urb->pipe) && musb->hb_iso_tx);
+ if (!ok) {
+ ret = -EMSGSIZE;
+ goto done;
+ }
+ qh->maxpacket &= 0x7ff;
+ }
+
+ qh->epnum = usb_endpoint_num(epd);
+
+ /* NOTE: urb->dev->devnum is wrong during SET_ADDRESS */
+ qh->addr_reg = (u8) usb_pipedevice(urb->pipe);
+
+ /* precompute rxtype/txtype/type0 register */
+ type_reg = (qh->type << 4) | qh->epnum;
+ switch (urb->dev->speed) {
+ case USB_SPEED_LOW:
+ type_reg |= 0xc0;
+ break;
+ case USB_SPEED_FULL:
+ type_reg |= 0x80;
+ break;
+ default:
+ type_reg |= 0x40;
+ }
+ qh->type_reg = type_reg;
+
+ /* Precompute RXINTERVAL/TXINTERVAL register */
+ switch (qh->type) {
+ case USB_ENDPOINT_XFER_INT:
+ /*
+ * Full/low speeds use the linear encoding,
+ * high speed uses the logarithmic encoding.
+ */
+ if (urb->dev->speed <= USB_SPEED_FULL) {
+ interval = max_t(u8, epd->bInterval, 1);
+ break;
+ }
+ /* FALLTHROUGH */
+ case USB_ENDPOINT_XFER_ISOC:
+ /* ISO always uses logarithmic encoding */
+ interval = min_t(u8, epd->bInterval, 16);
+ break;
+ default:
+ /* REVISIT we actually want to use NAK limits, hinting to the
+ * transfer scheduling logic to try some other qh, e.g. try
+ * for 2 msec first:
+ *
+ * interval = (USB_SPEED_HIGH == urb->dev->speed) ? 16 : 2;
+ *
+ * The downside of disabling this is that transfer scheduling
+ * gets VERY unfair for nonperiodic transfers; a misbehaving
+ * peripheral could make that hurt. That's perfectly normal
+ * for reads from network or serial adapters ... so we have
+ * partial NAKlimit support for bulk RX.
+ *
+ * The upside of disabling it is simpler transfer scheduling.
+ */
+ interval = 0;
+ }
+ qh->intv_reg = interval;
+
+ /* precompute addressing for external hub/tt ports */
+ if (musb->is_multipoint) {
+ struct usb_device *parent = urb->dev->parent;
+
+ if (parent) {
+ qh->h_addr_reg = (u8) parent->devnum;
+
+ if (tt_needed(musb, urb->dev)) {
+ u16 hub_port = find_tt(urb->dev);
+ qh->h_addr_reg = (u8) (hub_port >> 8);
+ qh->h_port_reg = (u8) (hub_port & 0xff);
+ }
+ }
+ }
+
+ /* invariant: hep->hcpriv is null OR the qh that's already scheduled.
+ * until we get real dma queues (with an entry for each urb/buffer),
+ * we only have work to do in the former case.
+ */
+ spin_lock_irqsave(&musb->lock, flags);
+ if (hep->hcpriv || !next_urb(qh)) {
+ /* some concurrent activity submitted another urb to hep...
+ * odd, rare, error prone, but legal.
+ */
+ kfree(qh);
+ qh = NULL;
+ ret = 0;
+ } else
+ ret = musb_schedule(musb, qh,
+ epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK);
+
+ if (ret == 0) {
+ urb->hcpriv = qh;
+ /* FIXME set urb->start_frame for iso/intr, it's tested in
+ * musb_start_urb(), but otherwise only konicawc cares ...
+ */
+ }
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+done:
+ if (ret != 0) {
+ spin_lock_irqsave(&musb->lock, flags);
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+ spin_unlock_irqrestore(&musb->lock, flags);
+ kfree(qh);
+ }
+ return ret;
+}
+
+/*
+ * abort a transfer that's at the head of a hardware queue.
+ * called with controller locked, irqs blocked
+ * that hardware queue advances to the next transfer, unless prevented
+ */
+static noinline int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh)
+{
+ struct musb_hw_ep *ep = qh->hw_ep;
+ void __iomem *epio = ep->regs;
+ unsigned hw_end = ep->epnum;
+ void __iomem *regs = ep->musb->mregs;
+ int is_in = usb_pipein(urb->pipe);
+ int status = 0;
+ u16 csr;
+
+ musb_ep_select(regs, hw_end);
+
+ /* turn off DMA requests, discard state, stop polling ... */
+ if (ep->epnum && is_in) {
+ /* giveback saves bulk toggle */
+ csr = musb_h_flush_rxfifo(ep, 0);
+
+ /* REVISIT we still get an irq; should likely clear the
+ * endpoint's irq status here to avoid bogus irqs.
+ * clearing that status is platform-specific...
+ */
+ } else if (ep->epnum) {
+ musb_h_tx_flush_fifo(ep);
+ csr = musb_readw(epio, MUSB_TXCSR);
+ csr &= ~(MUSB_TXCSR_AUTOSET
+ | MUSB_TXCSR_DMAENAB
+ | MUSB_TXCSR_H_RXSTALL
+ | MUSB_TXCSR_H_NAKTIMEOUT
+ | MUSB_TXCSR_H_ERROR
+ | MUSB_TXCSR_TXPKTRDY);
+ musb_writew(epio, MUSB_TXCSR, csr);
+ /* REVISIT may need to clear FLUSHFIFO ... */
+ musb_writew(epio, MUSB_TXCSR, csr);
+ /* flush cpu writebuffer */
+ csr = musb_readw(epio, MUSB_TXCSR);
+ } else {
+ musb_h_ep0_flush_fifo(ep);
+ }
+ if (status == 0)
+ musb_advance_schedule(ep->musb, urb, ep, is_in);
+ return status;
+}
+
+int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+{
+ struct musb *musb = hcd_to_musb(hcd);
+ struct musb_qh *qh;
+ unsigned long flags;
+ int is_in = usb_pipein(urb->pipe);
+ int ret = 0;
+
+ dev_dbg(musb->controller, "urb=%p, dev%d ep%d%s\n", urb,
+ usb_pipedevice(urb->pipe),
+ usb_pipeendpoint(urb->pipe),
+ is_in ? "in" : "out");
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ qh = urb->hcpriv;
+ if (!qh)
+ goto done;
+
+ /*
+ * Any URB not actively programmed into endpoint hardware can be
+ * immediately given back; that's any URB not at the head of an
+ * endpoint queue, unless someday we get real DMA queues. And even
+ * if it's at the head, it might not be known to the hardware...
+ *
+ * Otherwise abort current transfer, pending DMA, etc.; urb->status
+ * has already been updated. This is a synchronous abort; it'd be
+ * OK to hold off until after some IRQ, though.
+ *
+ * NOTE: qh is invalid unless !list_empty(&hep->urb_list)
+ */
+ if (!qh->is_ready
+ || urb->urb_list.prev != &qh->hep->urb_list
+ || musb_ep_get_qh(qh->hw_ep, is_in) != qh) {
+ int ready = qh->is_ready;
+
+ qh->is_ready = 0;
+ musb_giveback(musb, urb, 0);
+ qh->is_ready = ready;
+
+ /* If nothing else (usually musb_giveback) is using it
+ * and its URB list has emptied, recycle this qh.
+ */
+ if (ready && list_empty(&qh->hep->urb_list)) {
+ qh->hep->hcpriv = NULL;
+ list_del(&qh->ring);
+ kfree(qh);
+ }
+ } else
+ ret = musb_cleanup_urb(urb, qh);
+done:
+ spin_unlock_irqrestore(&musb->lock, flags);
+ return ret;
+}
+
+int musb_host_alloc(struct musb *musb)
+{
+ /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */
+ musb->hcd = xzalloc(sizeof(struct usb_hcd));
+ if (!musb->hcd)
+ return -EINVAL;
+
+ musb->hcd->hcd_priv = musb;
+
+ return 0;
+}
+
+void musb_host_free(struct musb *musb)
+{
+}
+
+int musb_host_setup(struct musb *musb, int power_budget)
+{
+ struct usb_hcd *hcd = musb->hcd;
+
+ MUSB_HST_MODE(musb);
+
+ hcd->self.otg_port = 1;
+
+ return 0;
+}
+
+void musb_host_resume_root_hub(struct musb *musb)
+{
+}
+
+void musb_host_poke_root_hub(struct musb *musb)
+{
+}
diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h
new file mode 100644
index 0000000000..0937808de8
--- /dev/null
+++ b/drivers/usb/musb/musb_host.h
@@ -0,0 +1,258 @@
+/*
+ * MUSB OTG driver host defines
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef _MUSB_HOST_H
+#define _MUSB_HOST_H
+
+//#include <linux/scatterlist.h>
+#include <linux/list.h>
+#include <usb/usb.h>
+#include <asm/unaligned.h>
+
+/*
+ * urb->transfer_flags:
+ *
+ * Note: URB_DIR_IN/OUT is automatically set in usb_submit_urb().
+ */
+#define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors. */
+#define URB_ZERO_PACKET 0x0040 /* Finish bulk OUT with short packet */
+
+#define usb_hcd_link_urb_to_ep(hcd, urb) ({ \
+ int ret = 0; \
+ list_add_tail(&urb->urb_list, &urb->ep->urb_list); \
+ ret; })
+
+#define usb_hcd_unlink_urb_from_ep(hcd, urb) list_del_init(&urb->urb_list)
+
+struct ep_device;
+struct urb;
+
+typedef void (*usb_complete_t)(struct urb *urb);
+
+struct urb {
+ void *hcpriv; /* private data for host controller */
+ struct list_head urb_list; /* list head for use by the urb's
+ * current owner */
+ struct usb_device *dev; /* (in) pointer to associated device */
+ struct usb_host_endpoint *ep; /* (internal) pointer to endpoint */
+ unsigned int pipe; /* (in) pipe information */
+ int status; /* (return) non-ISO status */
+ unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/
+ void *transfer_buffer; /* (in) associated data buffer */
+ dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */
+ u32 transfer_buffer_length; /* (in) data buffer length */
+ u32 actual_length; /* (return) actual transfer length */
+ unsigned char *setup_packet; /* (in) setup packet (control only) */
+ int start_frame; /* (modify) start frame (ISO) */
+ int error_count; /* (return) number of ISO errors */
+ usb_complete_t complete; /* (in) completion routine */
+};
+
+#define USB_DT_SS_EP_COMP_SIZE 6
+
+/**
+ * struct usb_host_endpoint - host-side endpoint descriptor and queue
+ * @desc: descriptor for this endpoint, wMaxPacketSize in native byteorder
+ * @ss_ep_comp: SuperSpeed companion descriptor for this endpoint
+ * @urb_list: urbs queued to this endpoint; maintained by usbcore
+ * @hcpriv: for use by HCD; typically holds hardware dma queue head (QH)
+ * with one or more transfer descriptors (TDs) per urb
+ * @ep_dev: ep_device for sysfs info
+ * @extra: descriptors following this endpoint in the configuration
+ * @extralen: how many bytes of "extra" are valid
+ * @enabled: URBs may be submitted to this endpoint
+ *
+ * USB requests are always queued to a given endpoint, identified by a
+ * descriptor within an active interface in a given USB configuration.
+ */
+struct usb_host_endpoint {
+ struct usb_endpoint_descriptor desc;
+ struct usb_ss_ep_comp_descriptor ss_ep_comp;
+ struct list_head urb_list;
+ void *hcpriv;
+ //struct ep_device *ep_dev; /* For sysfs info */
+
+ unsigned char *extra; /* Extra descriptors */
+ int extralen;
+ int enabled;
+};
+
+/* stored in "usb_host_endpoint.hcpriv" for scheduled endpoints */
+struct musb_qh {
+ struct usb_host_endpoint *hep; /* usbcore info */
+ struct usb_device *dev;
+ struct musb_hw_ep *hw_ep; /* current binding */
+
+ struct list_head ring; /* of musb_qh */
+ /* struct musb_qh *next; */ /* for periodic tree */
+ u8 mux; /* qh multiplexed to hw_ep */
+
+ unsigned offset; /* in urb->transfer_buffer */
+ unsigned segsize; /* current xfer fragment */
+
+ u8 type_reg; /* {rx,tx} type register */
+ u8 intv_reg; /* {rx,tx} interval register */
+ u8 addr_reg; /* device address register */
+ u8 h_addr_reg; /* hub address register */
+ u8 h_port_reg; /* hub port register */
+
+ u8 is_ready; /* safe to modify hw_ep */
+ u8 type; /* XFERTYPE_* */
+ u8 epnum;
+ u8 hb_mult; /* high bandwidth pkts per uf */
+ u16 maxpacket;
+ u16 frame; /* for periodic schedule */
+ unsigned iso_idx; /* in urb->iso_frame_desc[] */
+ //struct sg_mapping_iter sg_miter; /* for highmem in PIO mode */
+ //bool use_sg; /* to track urb using sglist */
+};
+
+/* map from control or bulk queue head to the first qh on that ring */
+static inline struct musb_qh *first_qh(struct list_head *q)
+{
+ if (list_empty(q))
+ return NULL;
+ return list_entry(q->next, struct musb_qh, ring);
+}
+
+struct usb_hcd;
+
+#if IS_ENABLED(CONFIG_USB_MUSB_HOST)
+extern struct musb *hcd_to_musb(struct usb_hcd *);
+extern irqreturn_t musb_h_ep0_irq(struct musb *);
+extern int musb_host_alloc(struct musb *);
+extern int musb_host_setup(struct musb *, int);
+extern void musb_root_disconnect(struct musb *musb);
+extern void musb_host_free(struct musb *);
+extern void musb_host_cleanup(struct musb *);
+extern void musb_host_tx(struct musb *, u8);
+extern void musb_host_rx(struct musb *, u8);
+extern void musb_host_resume_root_hub(struct musb *musb);
+extern void musb_host_poke_root_hub(struct musb *musb);
+extern void musb_port_reset(struct musb *musb, bool do_reset);
+#else
+static inline struct musb *hcd_to_musb(struct usb_hcd *hcd)
+{
+ return NULL;
+}
+
+static inline irqreturn_t musb_h_ep0_irq(struct musb *musb)
+{
+ return 0;
+}
+
+static inline int musb_host_alloc(struct musb *musb)
+{
+ return 0;
+}
+
+static inline int musb_host_setup(struct musb *musb, int power_budget)
+{
+ return 0;
+}
+
+static inline void musb_host_cleanup(struct musb *musb) {}
+static inline void musb_host_free(struct musb *musb) {}
+static inline void musb_host_tx(struct musb *musb, u8 epnum) {}
+static inline void musb_host_rx(struct musb *musb, u8 epnum) {}
+static inline void musb_root_disconnect(struct musb *musb) {}
+static inline void musb_host_resume_root_hub(struct musb *musb) {}
+static inline void musb_host_poll_rh_status(struct musb *musb) {}
+static inline void musb_host_poke_root_hub(struct musb *musb) {}
+static inline void musb_port_reset(struct musb *musb, bool do_reset) {}
+#endif
+
+struct usb_hcd;
+
+extern int musb_hub_status_data(struct usb_hcd *hcd, char *buf);
+extern int musb_hub_control(struct usb_hcd *hcd,
+ u16 typeReq, u16 wValue, u16 wIndex,
+ char *buf, u16 wLength);
+
+static inline struct urb *next_urb(struct musb_qh *qh)
+{
+ struct list_head *queue;
+
+ if (!qh)
+ return NULL;
+ queue = &qh->hep->urb_list;
+ if (list_empty(queue))
+ return NULL;
+ return list_entry(queue->next, struct urb, urb_list);
+}
+
+/*
+ * Endpoints
+ */
+#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */
+#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */
+
+static inline u16 find_tt(struct usb_device *dev)
+{
+ u8 chid;
+ u8 hub;
+
+ /* Find out the nearest parent which is high speed */
+ while (dev->parent->parent != NULL)
+ if (dev->parent->speed != USB_SPEED_HIGH)
+ dev = dev->parent;
+ else
+ break;
+
+ /* determine the port address at that hub */
+ hub = dev->parent->devnum;
+ for (chid = 0; chid < USB_MAXCHILDREN; chid++)
+ if (dev->parent->children[chid] == dev)
+ break;
+
+ return (hub << 8) | chid;
+}
+
+int musb_urb_enqueue(
+ struct usb_hcd *hcd,
+ struct urb *urb,
+ gfp_t mem_flags);
+
+int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
+
+static inline void usb_hcd_giveback_urb(struct usb_hcd *hcd,
+ struct urb *urb,
+ int status)
+{
+ urb->status = status;
+ if (urb->complete)
+ urb->complete(urb);
+}
+
+#endif /* _MUSB_HOST_H */
diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h
new file mode 100644
index 0000000000..a4be339355
--- /dev/null
+++ b/drivers/usb/musb/musb_io.h
@@ -0,0 +1,122 @@
+/*
+ * MUSB OTG driver register I/O
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_LINUX_PLATFORM_ARCH_H__
+#define __MUSB_LINUX_PLATFORM_ARCH_H__
+
+#include <io.h>
+
+#ifndef CONFIG_BLACKFIN
+
+/* NOTE: these offsets are all in bytes */
+
+static inline u16 musb_readw(const void __iomem *addr, unsigned offset)
+ { return __raw_readw(addr + offset); }
+
+static inline u32 musb_readl(const void __iomem *addr, unsigned offset)
+ { return __raw_readl(addr + offset); }
+
+
+static inline void musb_writew(void __iomem *addr, unsigned offset, u16 data)
+ { __raw_writew(data, addr + offset); }
+
+static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data)
+ { __raw_writel(data, addr + offset); }
+
+
+#if defined(CONFIG_USB_MUSB_TUSB6010) || defined (CONFIG_USB_MUSB_TUSB6010_MODULE)
+
+/*
+ * TUSB6010 doesn't allow 8-bit access; 16-bit access is the minimum.
+ */
+static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
+{
+ u16 tmp;
+ u8 val;
+
+ tmp = __raw_readw(addr + (offset & ~1));
+ if (offset & 1)
+ val = (tmp >> 8);
+ else
+ val = tmp & 0xff;
+
+ return val;
+}
+
+static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data)
+{
+ u16 tmp;
+
+ tmp = __raw_readw(addr + (offset & ~1));
+ if (offset & 1)
+ tmp = (data << 8) | (tmp & 0xff);
+ else
+ tmp = (tmp & 0xff00) | data;
+
+ __raw_writew(tmp, addr + (offset & ~1));
+}
+
+#else
+
+static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
+ { return __raw_readb(addr + offset); }
+
+static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data)
+ { __raw_writeb(data, addr + offset); }
+
+#endif /* CONFIG_USB_MUSB_TUSB6010 */
+
+#else
+
+static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
+ { return (u8) (bfin_read16(addr + offset)); }
+
+static inline u16 musb_readw(const void __iomem *addr, unsigned offset)
+ { return bfin_read16(addr + offset); }
+
+static inline u32 musb_readl(const void __iomem *addr, unsigned offset)
+ { return (u32) (bfin_read16(addr + offset)); }
+
+static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data)
+ { bfin_write16(addr + offset, (u16) data); }
+
+static inline void musb_writew(void __iomem *addr, unsigned offset, u16 data)
+ { bfin_write16(addr + offset, data); }
+
+static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data)
+ { bfin_write16(addr + offset, (u16) data); }
+
+#endif /* CONFIG_BLACKFIN */
+
+#endif
diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h
new file mode 100644
index 0000000000..b9bcda5e39
--- /dev/null
+++ b/drivers/usb/musb/musb_regs.h
@@ -0,0 +1,652 @@
+/*
+ * MUSB OTG driver register defines
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_REGS_H__
+#define __MUSB_REGS_H__
+
+#define MUSB_EP0_FIFOSIZE 64 /* This is non-configurable */
+
+/*
+ * MUSB Register bits
+ */
+
+/* POWER */
+#define MUSB_POWER_ISOUPDATE 0x80
+#define MUSB_POWER_SOFTCONN 0x40
+#define MUSB_POWER_HSENAB 0x20
+#define MUSB_POWER_HSMODE 0x10
+#define MUSB_POWER_RESET 0x08
+#define MUSB_POWER_RESUME 0x04
+#define MUSB_POWER_SUSPENDM 0x02
+#define MUSB_POWER_ENSUSPEND 0x01
+
+/* INTRUSB */
+#define MUSB_INTR_SUSPEND 0x01
+#define MUSB_INTR_RESUME 0x02
+#define MUSB_INTR_RESET 0x04
+#define MUSB_INTR_BABBLE 0x04
+#define MUSB_INTR_SOF 0x08
+#define MUSB_INTR_CONNECT 0x10
+#define MUSB_INTR_DISCONNECT 0x20
+#define MUSB_INTR_SESSREQ 0x40
+#define MUSB_INTR_VBUSERROR 0x80 /* For SESSION end */
+
+/* DEVCTL */
+#define MUSB_DEVCTL_BDEVICE 0x80
+#define MUSB_DEVCTL_FSDEV 0x40
+#define MUSB_DEVCTL_LSDEV 0x20
+#define MUSB_DEVCTL_VBUS 0x18
+#define MUSB_DEVCTL_VBUS_SHIFT 3
+#define MUSB_DEVCTL_HM 0x04
+#define MUSB_DEVCTL_HR 0x02
+#define MUSB_DEVCTL_SESSION 0x01
+
+/* BABBLE_CTL */
+#define MUSB_BABBLE_FORCE_TXIDLE 0x80
+#define MUSB_BABBLE_SW_SESSION_CTRL 0x40
+#define MUSB_BABBLE_STUCK_J 0x20
+#define MUSB_BABBLE_RCV_DISABLE 0x04
+
+/* MUSB ULPI VBUSCONTROL */
+#define MUSB_ULPI_USE_EXTVBUS 0x01
+#define MUSB_ULPI_USE_EXTVBUSIND 0x02
+/* ULPI_REG_CONTROL */
+#define MUSB_ULPI_REG_REQ (1 << 0)
+#define MUSB_ULPI_REG_CMPLT (1 << 1)
+#define MUSB_ULPI_RDN_WR (1 << 2)
+
+/* TESTMODE */
+#define MUSB_TEST_FORCE_HOST 0x80
+#define MUSB_TEST_FIFO_ACCESS 0x40
+#define MUSB_TEST_FORCE_FS 0x20
+#define MUSB_TEST_FORCE_HS 0x10
+#define MUSB_TEST_PACKET 0x08
+#define MUSB_TEST_K 0x04
+#define MUSB_TEST_J 0x02
+#define MUSB_TEST_SE0_NAK 0x01
+
+/* Allocate for double-packet buffering (effectively doubles assigned _SIZE) */
+#define MUSB_FIFOSZ_DPB 0x10
+/* Allocation size (8, 16, 32, ... 4096) */
+#define MUSB_FIFOSZ_SIZE 0x0f
+
+/* CSR0 */
+#define MUSB_CSR0_FLUSHFIFO 0x0100
+#define MUSB_CSR0_TXPKTRDY 0x0002
+#define MUSB_CSR0_RXPKTRDY 0x0001
+
+/* CSR0 in Peripheral mode */
+#define MUSB_CSR0_P_SVDSETUPEND 0x0080
+#define MUSB_CSR0_P_SVDRXPKTRDY 0x0040
+#define MUSB_CSR0_P_SENDSTALL 0x0020
+#define MUSB_CSR0_P_SETUPEND 0x0010
+#define MUSB_CSR0_P_DATAEND 0x0008
+#define MUSB_CSR0_P_SENTSTALL 0x0004
+
+/* CSR0 in Host mode */
+#define MUSB_CSR0_H_DIS_PING 0x0800
+#define MUSB_CSR0_H_WR_DATATOGGLE 0x0400 /* Set to allow setting: */
+#define MUSB_CSR0_H_DATATOGGLE 0x0200 /* Data toggle control */
+#define MUSB_CSR0_H_NAKTIMEOUT 0x0080
+#define MUSB_CSR0_H_STATUSPKT 0x0040
+#define MUSB_CSR0_H_REQPKT 0x0020
+#define MUSB_CSR0_H_ERROR 0x0010
+#define MUSB_CSR0_H_SETUPPKT 0x0008
+#define MUSB_CSR0_H_RXSTALL 0x0004
+
+/* CSR0 bits to avoid zeroing (write zero clears, write 1 ignored) */
+#define MUSB_CSR0_P_WZC_BITS \
+ (MUSB_CSR0_P_SENTSTALL)
+#define MUSB_CSR0_H_WZC_BITS \
+ (MUSB_CSR0_H_NAKTIMEOUT | MUSB_CSR0_H_RXSTALL \
+ | MUSB_CSR0_RXPKTRDY)
+
+/* TxType/RxType */
+#define MUSB_TYPE_SPEED 0xc0
+#define MUSB_TYPE_SPEED_SHIFT 6
+#define MUSB_TYPE_PROTO 0x30 /* Implicitly zero for ep0 */
+#define MUSB_TYPE_PROTO_SHIFT 4
+#define MUSB_TYPE_REMOTE_END 0xf /* Implicitly zero for ep0 */
+
+/* CONFIGDATA */
+#define MUSB_CONFIGDATA_MPRXE 0x80 /* Auto bulk pkt combining */
+#define MUSB_CONFIGDATA_MPTXE 0x40 /* Auto bulk pkt splitting */
+#define MUSB_CONFIGDATA_BIGENDIAN 0x20
+#define MUSB_CONFIGDATA_HBRXE 0x10 /* HB-ISO for RX */
+#define MUSB_CONFIGDATA_HBTXE 0x08 /* HB-ISO for TX */
+#define MUSB_CONFIGDATA_DYNFIFO 0x04 /* Dynamic FIFO sizing */
+#define MUSB_CONFIGDATA_SOFTCONE 0x02 /* SoftConnect */
+#define MUSB_CONFIGDATA_UTMIDW 0x01 /* Data width 0/1 => 8/16bits */
+
+/* TXCSR in Peripheral and Host mode */
+#define MUSB_TXCSR_AUTOSET 0x8000
+#define MUSB_TXCSR_DMAENAB 0x1000
+#define MUSB_TXCSR_FRCDATATOG 0x0800
+#define MUSB_TXCSR_DMAMODE 0x0400
+#define MUSB_TXCSR_CLRDATATOG 0x0040
+#define MUSB_TXCSR_FLUSHFIFO 0x0008
+#define MUSB_TXCSR_FIFONOTEMPTY 0x0002
+#define MUSB_TXCSR_TXPKTRDY 0x0001
+
+/* TXCSR in Peripheral mode */
+#define MUSB_TXCSR_P_ISO 0x4000
+#define MUSB_TXCSR_P_INCOMPTX 0x0080
+#define MUSB_TXCSR_P_SENTSTALL 0x0020
+#define MUSB_TXCSR_P_SENDSTALL 0x0010
+#define MUSB_TXCSR_P_UNDERRUN 0x0004
+
+/* TXCSR in Host mode */
+#define MUSB_TXCSR_H_WR_DATATOGGLE 0x0200
+#define MUSB_TXCSR_H_DATATOGGLE 0x0100
+#define MUSB_TXCSR_H_NAKTIMEOUT 0x0080
+#define MUSB_TXCSR_H_RXSTALL 0x0020
+#define MUSB_TXCSR_H_ERROR 0x0004
+
+/* TXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */
+#define MUSB_TXCSR_P_WZC_BITS \
+ (MUSB_TXCSR_P_INCOMPTX | MUSB_TXCSR_P_SENTSTALL \
+ | MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_FIFONOTEMPTY)
+#define MUSB_TXCSR_H_WZC_BITS \
+ (MUSB_TXCSR_H_NAKTIMEOUT | MUSB_TXCSR_H_RXSTALL \
+ | MUSB_TXCSR_H_ERROR | MUSB_TXCSR_FIFONOTEMPTY)
+
+/* RXCSR in Peripheral and Host mode */
+#define MUSB_RXCSR_AUTOCLEAR 0x8000
+#define MUSB_RXCSR_DMAENAB 0x2000
+#define MUSB_RXCSR_DISNYET 0x1000
+#define MUSB_RXCSR_PID_ERR 0x1000
+#define MUSB_RXCSR_DMAMODE 0x0800
+#define MUSB_RXCSR_INCOMPRX 0x0100
+#define MUSB_RXCSR_CLRDATATOG 0x0080
+#define MUSB_RXCSR_FLUSHFIFO 0x0010
+#define MUSB_RXCSR_DATAERROR 0x0008
+#define MUSB_RXCSR_FIFOFULL 0x0002
+#define MUSB_RXCSR_RXPKTRDY 0x0001
+
+/* RXCSR in Peripheral mode */
+#define MUSB_RXCSR_P_ISO 0x4000
+#define MUSB_RXCSR_P_SENTSTALL 0x0040
+#define MUSB_RXCSR_P_SENDSTALL 0x0020
+#define MUSB_RXCSR_P_OVERRUN 0x0004
+
+/* RXCSR in Host mode */
+#define MUSB_RXCSR_H_AUTOREQ 0x4000
+#define MUSB_RXCSR_H_WR_DATATOGGLE 0x0400
+#define MUSB_RXCSR_H_DATATOGGLE 0x0200
+#define MUSB_RXCSR_H_RXSTALL 0x0040
+#define MUSB_RXCSR_H_REQPKT 0x0020
+#define MUSB_RXCSR_H_ERROR 0x0004
+
+/* RXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */
+#define MUSB_RXCSR_P_WZC_BITS \
+ (MUSB_RXCSR_P_SENTSTALL | MUSB_RXCSR_P_OVERRUN \
+ | MUSB_RXCSR_RXPKTRDY)
+#define MUSB_RXCSR_H_WZC_BITS \
+ (MUSB_RXCSR_H_RXSTALL | MUSB_RXCSR_H_ERROR \
+ | MUSB_RXCSR_DATAERROR | MUSB_RXCSR_RXPKTRDY)
+
+/* HUBADDR */
+#define MUSB_HUBADDR_MULTI_TT 0x80
+
+
+#ifndef CONFIG_BLACKFIN
+
+/*
+ * Common USB registers
+ */
+
+#define MUSB_FADDR 0x00 /* 8-bit */
+#define MUSB_POWER 0x01 /* 8-bit */
+
+#define MUSB_INTRTX 0x02 /* 16-bit */
+#define MUSB_INTRRX 0x04
+#define MUSB_INTRTXE 0x06
+#define MUSB_INTRRXE 0x08
+#define MUSB_INTRUSB 0x0A /* 8 bit */
+#define MUSB_INTRUSBE 0x0B /* 8 bit */
+#define MUSB_FRAME 0x0C
+#define MUSB_INDEX 0x0E /* 8 bit */
+#define MUSB_TESTMODE 0x0F /* 8 bit */
+
+/* Get offset for a given FIFO from musb->mregs */
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
+#define MUSB_FIFO_OFFSET(epnum) (0x200 + ((epnum) * 0x20))
+#else
+#define MUSB_FIFO_OFFSET(epnum) (0x20 + ((epnum) * 4))
+#endif
+
+/*
+ * Additional Control Registers
+ */
+
+#define MUSB_DEVCTL 0x60 /* 8 bit */
+#define MUSB_BABBLE_CTL 0x61 /* 8 bit */
+
+/* These are always controlled through the INDEX register */
+#define MUSB_TXFIFOSZ 0x62 /* 8-bit (see masks) */
+#define MUSB_RXFIFOSZ 0x63 /* 8-bit (see masks) */
+#define MUSB_TXFIFOADD 0x64 /* 16-bit offset shifted right 3 */
+#define MUSB_RXFIFOADD 0x66 /* 16-bit offset shifted right 3 */
+
+/* REVISIT: vctrl/vstatus: optional vendor utmi+phy register at 0x68 */
+#define MUSB_HWVERS 0x6C /* 8 bit */
+#define MUSB_ULPI_BUSCONTROL 0x70 /* 8 bit */
+#define MUSB_ULPI_INT_MASK 0x72 /* 8 bit */
+#define MUSB_ULPI_INT_SRC 0x73 /* 8 bit */
+#define MUSB_ULPI_REG_DATA 0x74 /* 8 bit */
+#define MUSB_ULPI_REG_ADDR 0x75 /* 8 bit */
+#define MUSB_ULPI_REG_CONTROL 0x76 /* 8 bit */
+#define MUSB_ULPI_RAW_DATA 0x77 /* 8 bit */
+
+#define MUSB_EPINFO 0x78 /* 8 bit */
+#define MUSB_RAMINFO 0x79 /* 8 bit */
+#define MUSB_LINKINFO 0x7a /* 8 bit */
+#define MUSB_VPLEN 0x7b /* 8 bit */
+#define MUSB_HS_EOF1 0x7c /* 8 bit */
+#define MUSB_FS_EOF1 0x7d /* 8 bit */
+#define MUSB_LS_EOF1 0x7e /* 8 bit */
+
+/* Offsets to endpoint registers */
+#define MUSB_TXMAXP 0x00
+#define MUSB_TXCSR 0x02
+#define MUSB_CSR0 MUSB_TXCSR /* Re-used for EP0 */
+#define MUSB_RXMAXP 0x04
+#define MUSB_RXCSR 0x06
+#define MUSB_RXCOUNT 0x08
+#define MUSB_COUNT0 MUSB_RXCOUNT /* Re-used for EP0 */
+#define MUSB_TXTYPE 0x0A
+#define MUSB_TYPE0 MUSB_TXTYPE /* Re-used for EP0 */
+#define MUSB_TXINTERVAL 0x0B
+#define MUSB_NAKLIMIT0 MUSB_TXINTERVAL /* Re-used for EP0 */
+#define MUSB_RXTYPE 0x0C
+#define MUSB_RXINTERVAL 0x0D
+#define MUSB_FIFOSIZE 0x0F
+#define MUSB_CONFIGDATA MUSB_FIFOSIZE /* Re-used for EP0 */
+
+/* Offsets to endpoint registers in indexed model (using INDEX register) */
+#define MUSB_INDEXED_OFFSET(_epnum, _offset) \
+ (0x10 + (_offset))
+
+/* Offsets to endpoint registers in flat models */
+#define MUSB_FLAT_OFFSET(_epnum, _offset) \
+ (0x100 + (0x10*(_epnum)) + (_offset))
+
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
+/* TUSB6010 EP0 configuration register is special */
+#define MUSB_TUSB_OFFSET(_epnum, _offset) \
+ (0x10 + _offset)
+#include "tusb6010.h" /* Needed "only" for TUSB_EP0_CONF */
+#endif
+
+#define MUSB_TXCSR_MODE 0x2000
+
+/* "bus control"/target registers, for host side multipoint (external hubs) */
+#define MUSB_TXFUNCADDR 0x00
+#define MUSB_TXHUBADDR 0x02
+#define MUSB_TXHUBPORT 0x03
+
+#define MUSB_RXFUNCADDR 0x04
+#define MUSB_RXHUBADDR 0x06
+#define MUSB_RXHUBPORT 0x07
+
+#define MUSB_BUSCTL_OFFSET(_epnum, _offset) \
+ (0x80 + (8*(_epnum)) + (_offset))
+
+static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size)
+{
+ musb_writeb(mbase, MUSB_TXFIFOSZ, c_size);
+}
+
+static inline void musb_write_txfifoadd(void __iomem *mbase, u16 c_off)
+{
+ musb_writew(mbase, MUSB_TXFIFOADD, c_off);
+}
+
+static inline void musb_write_rxfifosz(void __iomem *mbase, u8 c_size)
+{
+ musb_writeb(mbase, MUSB_RXFIFOSZ, c_size);
+}
+
+static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off)
+{
+ musb_writew(mbase, MUSB_RXFIFOADD, c_off);
+}
+
+static inline void musb_write_ulpi_buscontrol(void __iomem *mbase, u8 val)
+{
+ musb_writeb(mbase, MUSB_ULPI_BUSCONTROL, val);
+}
+
+static inline u8 musb_read_txfifosz(void __iomem *mbase)
+{
+ return musb_readb(mbase, MUSB_TXFIFOSZ);
+}
+
+static inline u16 musb_read_txfifoadd(void __iomem *mbase)
+{
+ return musb_readw(mbase, MUSB_TXFIFOADD);
+}
+
+static inline u8 musb_read_rxfifosz(void __iomem *mbase)
+{
+ return musb_readb(mbase, MUSB_RXFIFOSZ);
+}
+
+static inline u16 musb_read_rxfifoadd(void __iomem *mbase)
+{
+ return musb_readw(mbase, MUSB_RXFIFOADD);
+}
+
+static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase)
+{
+ return musb_readb(mbase, MUSB_ULPI_BUSCONTROL);
+}
+
+static inline u8 musb_read_configdata(void __iomem *mbase)
+{
+ musb_writeb(mbase, MUSB_INDEX, 0);
+ return musb_readb(mbase, 0x10 + MUSB_CONFIGDATA);
+}
+
+static inline u16 musb_read_hwvers(void __iomem *mbase)
+{
+ return musb_readw(mbase, MUSB_HWVERS);
+}
+
+static inline void __iomem *musb_read_target_reg_base(u8 i, void __iomem *mbase)
+{
+ return (MUSB_BUSCTL_OFFSET(i, 0) + mbase);
+}
+
+static inline void musb_write_rxfunaddr(void __iomem *ep_target_regs,
+ u8 qh_addr_reg)
+{
+ musb_writeb(ep_target_regs, MUSB_RXFUNCADDR, qh_addr_reg);
+}
+
+static inline void musb_write_rxhubaddr(void __iomem *ep_target_regs,
+ u8 qh_h_addr_reg)
+{
+ musb_writeb(ep_target_regs, MUSB_RXHUBADDR, qh_h_addr_reg);
+}
+
+static inline void musb_write_rxhubport(void __iomem *ep_target_regs,
+ u8 qh_h_port_reg)
+{
+ musb_writeb(ep_target_regs, MUSB_RXHUBPORT, qh_h_port_reg);
+}
+
+static inline void musb_write_txfunaddr(void __iomem *mbase, u8 epnum,
+ u8 qh_addr_reg)
+{
+ musb_writeb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXFUNCADDR),
+ qh_addr_reg);
+}
+
+static inline void musb_write_txhubaddr(void __iomem *mbase, u8 epnum,
+ u8 qh_addr_reg)
+{
+ musb_writeb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBADDR),
+ qh_addr_reg);
+}
+
+static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum,
+ u8 qh_h_port_reg)
+{
+ musb_writeb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBPORT),
+ qh_h_port_reg);
+}
+
+static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum)
+{
+ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXFUNCADDR));
+}
+
+static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum)
+{
+ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXHUBADDR));
+}
+
+static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum)
+{
+ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXHUBPORT));
+}
+
+static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum)
+{
+ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXFUNCADDR));
+}
+
+static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum)
+{
+ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBADDR));
+}
+
+static inline u8 musb_read_txhubport(void __iomem *mbase, u8 epnum)
+{
+ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBPORT));
+}
+
+#else /* CONFIG_BLACKFIN */
+
+#define USB_BASE USB_FADDR
+#define USB_OFFSET(reg) (reg - USB_BASE)
+
+/*
+ * Common USB registers
+ */
+#define MUSB_FADDR USB_OFFSET(USB_FADDR) /* 8-bit */
+#define MUSB_POWER USB_OFFSET(USB_POWER) /* 8-bit */
+#define MUSB_INTRTX USB_OFFSET(USB_INTRTX) /* 16-bit */
+#define MUSB_INTRRX USB_OFFSET(USB_INTRRX)
+#define MUSB_INTRTXE USB_OFFSET(USB_INTRTXE)
+#define MUSB_INTRRXE USB_OFFSET(USB_INTRRXE)
+#define MUSB_INTRUSB USB_OFFSET(USB_INTRUSB) /* 8 bit */
+#define MUSB_INTRUSBE USB_OFFSET(USB_INTRUSBE)/* 8 bit */
+#define MUSB_FRAME USB_OFFSET(USB_FRAME)
+#define MUSB_INDEX USB_OFFSET(USB_INDEX) /* 8 bit */
+#define MUSB_TESTMODE USB_OFFSET(USB_TESTMODE)/* 8 bit */
+
+/* Get offset for a given FIFO from musb->mregs */
+#define MUSB_FIFO_OFFSET(epnum) \
+ (USB_OFFSET(USB_EP0_FIFO) + ((epnum) * 8))
+
+/*
+ * Additional Control Registers
+ */
+
+#define MUSB_DEVCTL USB_OFFSET(USB_OTG_DEV_CTL) /* 8 bit */
+
+#define MUSB_LINKINFO USB_OFFSET(USB_LINKINFO)/* 8 bit */
+#define MUSB_VPLEN USB_OFFSET(USB_VPLEN) /* 8 bit */
+#define MUSB_HS_EOF1 USB_OFFSET(USB_HS_EOF1) /* 8 bit */
+#define MUSB_FS_EOF1 USB_OFFSET(USB_FS_EOF1) /* 8 bit */
+#define MUSB_LS_EOF1 USB_OFFSET(USB_LS_EOF1) /* 8 bit */
+
+/* Offsets to endpoint registers */
+#define MUSB_TXMAXP 0x00
+#define MUSB_TXCSR 0x04
+#define MUSB_CSR0 MUSB_TXCSR /* Re-used for EP0 */
+#define MUSB_RXMAXP 0x08
+#define MUSB_RXCSR 0x0C
+#define MUSB_RXCOUNT 0x10
+#define MUSB_COUNT0 MUSB_RXCOUNT /* Re-used for EP0 */
+#define MUSB_TXTYPE 0x14
+#define MUSB_TYPE0 MUSB_TXTYPE /* Re-used for EP0 */
+#define MUSB_TXINTERVAL 0x18
+#define MUSB_NAKLIMIT0 MUSB_TXINTERVAL /* Re-used for EP0 */
+#define MUSB_RXTYPE 0x1C
+#define MUSB_RXINTERVAL 0x20
+#define MUSB_TXCOUNT 0x28
+
+/* Offsets to endpoint registers in indexed model (using INDEX register) */
+#define MUSB_INDEXED_OFFSET(_epnum, _offset) \
+ (0x40 + (_offset))
+
+/* Offsets to endpoint registers in flat models */
+#define MUSB_FLAT_OFFSET(_epnum, _offset) \
+ (USB_OFFSET(USB_EP_NI0_TXMAXP) + (0x40 * (_epnum)) + (_offset))
+
+/* Not implemented - HW has separate Tx/Rx FIFO */
+#define MUSB_TXCSR_MODE 0x0000
+
+static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size)
+{
+}
+
+static inline void musb_write_txfifoadd(void __iomem *mbase, u16 c_off)
+{
+}
+
+static inline void musb_write_rxfifosz(void __iomem *mbase, u8 c_size)
+{
+}
+
+static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off)
+{
+}
+
+static inline void musb_write_ulpi_buscontrol(void __iomem *mbase, u8 val)
+{
+}
+
+static inline u8 musb_read_txfifosz(void __iomem *mbase)
+{
+ return 0;
+}
+
+static inline u16 musb_read_txfifoadd(void __iomem *mbase)
+{
+ return 0;
+}
+
+static inline u8 musb_read_rxfifosz(void __iomem *mbase)
+{
+ return 0;
+}
+
+static inline u16 musb_read_rxfifoadd(void __iomem *mbase)
+{
+ return 0;
+}
+
+static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase)
+{
+ return 0;
+}
+
+static inline u8 musb_read_configdata(void __iomem *mbase)
+{
+ return 0;
+}
+
+static inline u16 musb_read_hwvers(void __iomem *mbase)
+{
+ /*
+ * This register is invisible on Blackfin, actually the MUSB
+ * RTL version of Blackfin is 1.9, so just harcode its value.
+ */
+ return MUSB_HWVERS_1900;
+}
+
+static inline void __iomem *musb_read_target_reg_base(u8 i, void __iomem *mbase)
+{
+ return NULL;
+}
+
+static inline void musb_write_rxfunaddr(void __iomem *ep_target_regs,
+ u8 qh_addr_req)
+{
+}
+
+static inline void musb_write_rxhubaddr(void __iomem *ep_target_regs,
+ u8 qh_h_addr_reg)
+{
+}
+
+static inline void musb_write_rxhubport(void __iomem *ep_target_regs,
+ u8 qh_h_port_reg)
+{
+}
+
+static inline void musb_write_txfunaddr(void __iomem *mbase, u8 epnum,
+ u8 qh_addr_reg)
+{
+}
+
+static inline void musb_write_txhubaddr(void __iomem *mbase, u8 epnum,
+ u8 qh_addr_reg)
+{
+}
+
+static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum,
+ u8 qh_h_port_reg)
+{
+}
+
+static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum)
+{
+ return 0;
+}
+
+static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum)
+{
+ return 0;
+}
+
+static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum)
+{
+ return 0;
+}
+
+static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum)
+{
+ return 0;
+}
+
+static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum)
+{
+ return 0;
+}
+
+static inline u8 musb_read_txhubport(void __iomem *mbase, u8 epnum)
+{
+ return 0;
+}
+
+#endif /* CONFIG_BLACKFIN */
+
+#endif /* __MUSB_REGS_H__ */
diff --git a/drivers/usb/musb/phy-am335x-control.c b/drivers/usb/musb/phy-am335x-control.c
new file mode 100644
index 0000000000..a241c84fed
--- /dev/null
+++ b/drivers/usb/musb/phy-am335x-control.c
@@ -0,0 +1,168 @@
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <linux/err.h>
+
+struct phy_control {
+ void (*phy_power)(struct phy_control *phy_ctrl, u32 id, bool on);
+ void (*phy_wkup)(struct phy_control *phy_ctrl, u32 id, bool on);
+};
+
+struct am335x_control_usb {
+ struct device_d *dev;
+ void __iomem *phy_reg;
+ void __iomem *wkup;
+ spinlock_t lock;
+ struct phy_control phy_ctrl;
+};
+
+#define AM335X_USB0_CTRL 0x0
+#define AM335X_USB1_CTRL 0x8
+#define AM335x_USB_WKUP 0x0
+
+#define USBPHY_CM_PWRDN (1 << 0)
+#define USBPHY_OTG_PWRDN (1 << 1)
+#define USBPHY_OTGVDET_EN (1 << 19)
+#define USBPHY_OTGSESSEND_EN (1 << 20)
+
+#define AM335X_PHY0_WK_EN (1 << 0)
+#define AM335X_PHY1_WK_EN (1 << 8)
+
+static void am335x_phy_wkup(struct phy_control *phy_ctrl, u32 id, bool on)
+{
+ struct am335x_control_usb *usb_ctrl;
+ u32 val;
+ u32 reg;
+
+ usb_ctrl = container_of(phy_ctrl, struct am335x_control_usb, phy_ctrl);
+
+ switch (id) {
+ case 0:
+ reg = AM335X_PHY0_WK_EN;
+ break;
+ case 1:
+ reg = AM335X_PHY1_WK_EN;
+ break;
+ default:
+ WARN_ON(1);
+ return;
+ }
+
+ spin_lock(&usb_ctrl->lock);
+ val = readl(usb_ctrl->wkup);
+
+ if (on)
+ val |= reg;
+ else
+ val &= ~reg;
+
+ writel(val, usb_ctrl->wkup);
+ spin_unlock(&usb_ctrl->lock);
+}
+
+static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id, bool on)
+{
+ struct am335x_control_usb *usb_ctrl;
+ u32 val;
+ u32 reg;
+
+ usb_ctrl = container_of(phy_ctrl, struct am335x_control_usb, phy_ctrl);
+
+ switch (id) {
+ case 0:
+ reg = AM335X_USB0_CTRL;
+ break;
+ case 1:
+ reg = AM335X_USB1_CTRL;
+ break;
+ default:
+ WARN_ON(1);
+ return;
+ }
+
+ val = readl(usb_ctrl->phy_reg + reg);
+ if (on) {
+ val &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN);
+ val |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN;
+ } else {
+ val |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
+ }
+
+ writel(val, usb_ctrl->phy_reg + reg);
+}
+
+static const struct phy_control ctrl_am335x = {
+ .phy_power = am335x_phy_power,
+ .phy_wkup = am335x_phy_wkup,
+};
+
+static __maybe_unused struct of_device_id omap_control_usb_dt_ids[] = {
+ {
+ .compatible = "ti,am335x-usb-ctrl-module", .data = (unsigned long)&ctrl_am335x
+ }, {
+ /* sentinel */
+ },
+};
+
+struct phy_control *am335x_get_phy_control(struct device_d *dev)
+{
+ struct device_node *node;
+ struct am335x_control_usb *ctrl_usb;
+
+ node = of_parse_phandle(dev->device_node, "ti,ctrl_mod", 0);
+ if (!node)
+ return NULL;
+
+ dev = of_find_device_by_node(node);
+ if (!dev)
+ return NULL;
+
+ ctrl_usb = dev->priv;
+ if (!ctrl_usb)
+ return NULL;
+
+ return &ctrl_usb->phy_ctrl;
+}
+EXPORT_SYMBOL(am335x_get_phy_control);
+
+
+static int am335x_control_usb_probe(struct device_d *dev)
+{
+ /*struct resource *res;*/
+ struct am335x_control_usb *ctrl_usb;
+ const struct phy_control *phy_ctrl;
+ int ret;
+
+ ret = dev_get_drvdata(dev, (unsigned long *)&phy_ctrl);
+ if (ret)
+ return ret;
+
+ ctrl_usb = xzalloc(sizeof(*ctrl_usb));
+ if (!ctrl_usb) {
+ dev_err(dev, "unable to alloc memory for control usb\n");
+ return -ENOMEM;
+ }
+
+ ctrl_usb->dev = dev;
+
+ ctrl_usb->phy_reg = dev_request_mem_region(dev, 0);
+ if (IS_ERR(ctrl_usb->phy_reg))
+ return PTR_ERR(ctrl_usb->phy_reg);
+
+ ctrl_usb->wkup = dev_request_mem_region(dev, 1);
+ if (IS_ERR(ctrl_usb->wkup))
+ return PTR_ERR(ctrl_usb->wkup);
+
+ spin_lock_init(&ctrl_usb->lock);
+ ctrl_usb->phy_ctrl = *phy_ctrl;
+
+ dev->priv = ctrl_usb;
+ return 0;
+};
+
+static struct driver_d am335x_control_driver = {
+ .name = "am335x-control-usb",
+ .probe = am335x_control_usb_probe,
+ .of_compatible = DRV_OF_COMPAT(omap_control_usb_dt_ids),
+};
+device_platform_driver(am335x_control_driver);
diff --git a/drivers/usb/musb/phy-am335x.c b/drivers/usb/musb/phy-am335x.c
new file mode 100644
index 0000000000..2d58bbedb4
--- /dev/null
+++ b/drivers/usb/musb/phy-am335x.c
@@ -0,0 +1,86 @@
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <malloc.h>
+#include <linux/err.h>
+#include "am35x-phy-control.h"
+#include "musb_core.h"
+
+struct am335x_usbphy {
+ void __iomem *base;
+ struct phy_control *phy_ctrl;
+ int id;
+ struct usb_phy phy;
+};
+
+static struct am335x_usbphy *am_usbphy;
+
+struct usb_phy *am335x_get_usb_phy(void)
+{
+ return &am_usbphy->phy;
+}
+
+static int am335x_init(struct usb_phy *phy)
+{
+ struct am335x_usbphy *am_usbphy = container_of(phy, struct am335x_usbphy, phy);
+
+ phy_ctrl_power(am_usbphy->phy_ctrl, am_usbphy->id, true);
+ return 0;
+}
+
+static int am335x_phy_probe(struct device_d *dev)
+{
+ int ret;
+
+ am_usbphy = xzalloc(sizeof(*am_usbphy));
+ if (!am_usbphy)
+ return -ENOMEM;
+
+ am_usbphy->base = dev_request_mem_region(dev, 0);
+ if (!am_usbphy->base) {
+ ret = -ENODEV;
+ goto err_free;
+ }
+
+ am_usbphy->phy_ctrl = am335x_get_phy_control(dev);
+ if (!am_usbphy->phy_ctrl)
+ return -ENODEV;
+
+ am_usbphy->id = of_alias_get_id(dev->device_node, "phy");
+ if (am_usbphy->id < 0) {
+ dev_err(dev, "Missing PHY id: %d\n", am_usbphy->id);
+ return am_usbphy->id;
+ }
+
+ am_usbphy->phy.init = am335x_init;
+ dev->priv = am_usbphy;
+
+ dev_info(dev, "am_usbphy %p enabled\n", &am_usbphy->phy);
+
+ return 0;
+
+err_free:
+ free(am_usbphy);
+
+ return ret;
+};
+
+static __maybe_unused struct of_device_id am335x_phy_dt_ids[] = {
+ {
+ .compatible = "ti,am335x-usb-phy",
+ }, {
+ /* sentinel */
+ },
+};
+
+static struct driver_d am335x_phy_driver = {
+ .name = "am335x-phy-driver",
+ .probe = am335x_phy_probe,
+ .of_compatible = DRV_OF_COMPAT(am335x_phy_dt_ids),
+};
+
+static int am335x_phy_init(void)
+{
+ return platform_driver_register(&am335x_phy_driver);
+}
+fs_initcall(am335x_phy_init);
diff --git a/drivers/usb/musb/phy-am335x.h b/drivers/usb/musb/phy-am335x.h
new file mode 100644
index 0000000000..27da2e3b10
--- /dev/null
+++ b/drivers/usb/musb/phy-am335x.h
@@ -0,0 +1,6 @@
+#ifndef _PHY_AM335x_H_
+#define _PHY_AM335x_H_
+
+struct usb_phy *am335x_get_usb_phy(void);
+
+#endif
diff --git a/dts/Bindings/dma/rcar-audmapp.txt b/dts/Bindings/dma/rcar-audmapp.txt
index 9f1d750d76..61bca509d7 100644
--- a/dts/Bindings/dma/rcar-audmapp.txt
+++ b/dts/Bindings/dma/rcar-audmapp.txt
@@ -16,9 +16,9 @@ Example:
* DMA client
Required properties:
-- dmas: a list of <[DMA multiplexer phandle] [SRS/DRS value]> pairs,
- where SRS/DRS values are fixed handles, specified in the SoC
- manual as the value that would be written into the PDMACHCR.
+- dmas: a list of <[DMA multiplexer phandle] [SRS << 8 | DRS]> pairs.
+ where SRS/DRS are specified in the SoC manual.
+ It will be written into PDMACHCR as high 16-bit parts.
- dma-names: a list of DMA channel names, one per "dmas" entry
Example:
diff --git a/dts/Bindings/input/atmel,maxtouch.txt b/dts/Bindings/input/atmel,maxtouch.txt
index baef432e83..0ac23f2ed1 100644
--- a/dts/Bindings/input/atmel,maxtouch.txt
+++ b/dts/Bindings/input/atmel,maxtouch.txt
@@ -15,6 +15,17 @@ Optional properties for main touchpad device:
keycode generated by each GPIO. Linux keycodes are defined in
<dt-bindings/input/input.h>.
+- linux,gpio-keymap: When enabled, the SPT_GPIOPWN_T19 object sends messages
+ on GPIO bit changes. An array of up to 8 entries can be provided
+ indicating the Linux keycode mapped to each bit of the status byte,
+ starting at the LSB. Linux keycodes are defined in
+ <dt-bindings/input/input.h>.
+
+ Note: the numbering of the GPIOs and the bit they start at varies between
+ maXTouch devices. You must either refer to the documentation, or
+ experiment to determine which bit corresponds to which input. Use
+ KEY_RESERVED for unused padding values.
+
Example:
touch@4b {
diff --git a/dts/Bindings/mfd/tc3589x.txt b/dts/Bindings/mfd/tc3589x.txt
new file mode 100644
index 0000000000..6fcedba46a
--- /dev/null
+++ b/dts/Bindings/mfd/tc3589x.txt
@@ -0,0 +1,107 @@
+* Toshiba TC3589x multi-purpose expander
+
+The Toshiba TC3589x series are I2C-based MFD devices which may expose the
+following built-in devices: gpio, keypad, rotator (vibrator), PWM (for
+e.g. LEDs or vibrators) The included models are:
+
+- TC35890
+- TC35892
+- TC35893
+- TC35894
+- TC35895
+- TC35896
+
+Required properties:
+ - compatible : must be "toshiba,tc35890", "toshiba,tc35892", "toshiba,tc35893",
+ "toshiba,tc35894", "toshiba,tc35895" or "toshiba,tc35896"
+ - reg : I2C address of the device
+ - interrupt-parent : specifies which IRQ controller we're connected to
+ - interrupts : the interrupt on the parent the controller is connected to
+ - interrupt-controller : marks the device node as an interrupt controller
+ - #interrupt-cells : should be <1>, the first cell is the IRQ offset on this
+ TC3589x interrupt controller.
+
+Optional nodes:
+
+- GPIO
+ This GPIO module inside the TC3589x has 24 (TC35890, TC35892) or 20
+ (other models) GPIO lines.
+ - compatible : must be "toshiba,tc3589x-gpio"
+ - interrupts : interrupt on the parent, which must be the tc3589x MFD device
+ - interrupt-controller : marks the device node as an interrupt controller
+ - #interrupt-cells : should be <2>, the first cell is the IRQ offset on this
+ TC3589x GPIO interrupt controller, the second cell is the interrupt flags
+ in accordance with <dt-bindings/interrupt-controller/irq.h>. The following
+ flags are valid:
+ - IRQ_TYPE_LEVEL_LOW
+ - IRQ_TYPE_LEVEL_HIGH
+ - IRQ_TYPE_EDGE_RISING
+ - IRQ_TYPE_EDGE_FALLING
+ - IRQ_TYPE_EDGE_BOTH
+ - gpio-controller : marks the device node as a GPIO controller
+ - #gpio-cells : should be <2>, the first cell is the GPIO offset on this
+ GPIO controller, the second cell is the flags.
+
+- Keypad
+ This keypad is the same on all variants, supporting up to 96 different
+ keys. The linux-specific properties are modeled on those already existing
+ in other input drivers.
+ - compatible : must be "toshiba,tc3589x-keypad"
+ - debounce-delay-ms : debounce interval in milliseconds
+ - keypad,num-rows : number of rows in the matrix, see
+ bindings/input/matrix-keymap.txt
+ - keypad,num-columns : number of columns in the matrix, see
+ bindings/input/matrix-keymap.txt
+ - linux,keymap: the definition can be found in
+ bindings/input/matrix-keymap.txt
+ - linux,no-autorepeat: do no enable autorepeat feature.
+ - linux,wakeup: use any event on keypad as wakeup event.
+
+Example:
+
+tc35893@44 {
+ compatible = "toshiba,tc35893";
+ reg = <0x44>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <26 IRQ_TYPE_EDGE_RISING>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ tc3589x_gpio {
+ compatible = "toshiba,tc3589x-gpio";
+ interrupts = <0>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+ tc3589x_keypad {
+ compatible = "toshiba,tc3589x-keypad";
+ interrupts = <6>;
+ debounce-delay-ms = <4>;
+ keypad,num-columns = <8>;
+ keypad,num-rows = <8>;
+ linux,no-autorepeat;
+ linux,wakeup;
+ linux,keymap = <0x0301006b
+ 0x04010066
+ 0x06040072
+ 0x040200d7
+ 0x0303006a
+ 0x0205000e
+ 0x0607008b
+ 0x0500001c
+ 0x0403000b
+ 0x03040034
+ 0x05020067
+ 0x0305006c
+ 0x040500e7
+ 0x0005009e
+ 0x06020073
+ 0x01030039
+ 0x07060069
+ 0x050500d9>;
+ };
+};
diff --git a/dts/Bindings/mtd/gpmc-nand.txt b/dts/Bindings/mtd/gpmc-nand.txt
index 65f4f7c431..ee654e95d8 100644
--- a/dts/Bindings/mtd/gpmc-nand.txt
+++ b/dts/Bindings/mtd/gpmc-nand.txt
@@ -22,7 +22,7 @@ Optional properties:
width of 8 is assumed.
- ti,nand-ecc-opt: A string setting the ECC layout to use. One of:
- "sw" <deprecated> use "ham1" instead
+ "sw" 1-bit Hamming ecc code via software
"hw" <deprecated> use "ham1" instead
"hw-romcode" <deprecated> use "ham1" instead
"ham1" 1-bit Hamming ecc code
diff --git a/dts/Bindings/net/stmmac.txt b/dts/Bindings/net/stmmac.txt
index 9b03c57563..e45ac3f926 100644
--- a/dts/Bindings/net/stmmac.txt
+++ b/dts/Bindings/net/stmmac.txt
@@ -39,6 +39,10 @@ Optional properties:
further clocks may be specified in derived bindings.
- clock-names: One name for each entry in the clocks property, the
first one should be "stmmaceth".
+- clk_ptp_ref: this is the PTP reference clock; in case of the PTP is
+ available this clock is used for programming the Timestamp Addend Register.
+ If not passed then the system clock will be used and this is fine on some
+ platforms.
Examples:
diff --git a/dts/Bindings/pinctrl/qcom,apq8064-pinctrl.txt b/dts/Bindings/pinctrl/qcom,apq8064-pinctrl.txt
index 0211c6d8a5..92fae82f35 100644
--- a/dts/Bindings/pinctrl/qcom,apq8064-pinctrl.txt
+++ b/dts/Bindings/pinctrl/qcom,apq8064-pinctrl.txt
@@ -62,7 +62,7 @@ Example:
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
- interrupts = <0 32 0x4>;
+ interrupts = <0 16 0x4>;
pinctrl-names = "default";
pinctrl-0 = <&gsbi5_uart_default>;
diff --git a/dts/Bindings/regulator/tps65090.txt b/dts/Bindings/regulator/tps65090.txt
index 340980239e..ca69f5e304 100644
--- a/dts/Bindings/regulator/tps65090.txt
+++ b/dts/Bindings/regulator/tps65090.txt
@@ -45,8 +45,8 @@ Example:
infet5-supply = <&some_reg>;
infet6-supply = <&some_reg>;
infet7-supply = <&some_reg>;
- vsys_l1-supply = <&some_reg>;
- vsys_l2-supply = <&some_reg>;
+ vsys-l1-supply = <&some_reg>;
+ vsys-l2-supply = <&some_reg>;
regulators {
dcdc1 {
diff --git a/dts/Bindings/sound/adi,axi-spdif-tx.txt b/dts/Bindings/sound/adi,axi-spdif-tx.txt
index 46f3449653..4eb7997674 100644
--- a/dts/Bindings/sound/adi,axi-spdif-tx.txt
+++ b/dts/Bindings/sound/adi,axi-spdif-tx.txt
@@ -1,7 +1,7 @@
ADI AXI-SPDIF controller
Required properties:
- - compatible : Must be "adi,axi-spdif-1.00.a"
+ - compatible : Must be "adi,axi-spdif-tx-1.00.a"
- reg : Must contain SPDIF core's registers location and length
- clocks : Pairs of phandle and specifier referencing the controller's clocks.
The controller expects two clocks, the clock used for the AXI interface and
diff --git a/dts/Bindings/usb/mxs-phy.txt b/dts/Bindings/usb/mxs-phy.txt
index cef181a9d8..96681c93b8 100644
--- a/dts/Bindings/usb/mxs-phy.txt
+++ b/dts/Bindings/usb/mxs-phy.txt
@@ -5,6 +5,7 @@ Required properties:
* "fsl,imx23-usbphy" for imx23 and imx28
* "fsl,imx6q-usbphy" for imx6dq and imx6dl
* "fsl,imx6sl-usbphy" for imx6sl
+ * "fsl,imx6sx-usbphy" for imx6sx
"fsl,imx23-usbphy" is still a fallback for other strings
- reg: Should contain registers location and length
- interrupts: Should contain phy interrupt
diff --git a/dts/Bindings/video/analog-tv-connector.txt b/dts/Bindings/video/analog-tv-connector.txt
index 0218fcdc12..0c0970c210 100644
--- a/dts/Bindings/video/analog-tv-connector.txt
+++ b/dts/Bindings/video/analog-tv-connector.txt
@@ -2,7 +2,7 @@ Analog TV Connector
===================
Required properties:
-- compatible: "composite-connector" or "svideo-connector"
+- compatible: "composite-video-connector" or "svideo-connector"
Optional properties:
- label: a symbolic name for the connector
@@ -14,7 +14,7 @@ Example
-------
tv: connector {
- compatible = "composite-connector";
+ compatible = "composite-video-connector";
label = "tv";
port {
diff --git a/dts/src/arm/am4372.dtsi b/dts/src/arm/am4372.dtsi
index 9b3d2ba82f..8689949bdb 100644
--- a/dts/src/arm/am4372.dtsi
+++ b/dts/src/arm/am4372.dtsi
@@ -804,7 +804,7 @@
usb1: usb@48390000 {
compatible = "synopsys,dwc3";
- reg = <0x48390000 0x17000>;
+ reg = <0x48390000 0x10000>;
interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
phys = <&usb2_phy1>;
phy-names = "usb2-phy";
@@ -826,7 +826,7 @@
usb2: usb@483d0000 {
compatible = "synopsys,dwc3";
- reg = <0x483d0000 0x17000>;
+ reg = <0x483d0000 0x10000>;
interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
phys = <&usb2_phy2>;
phy-names = "usb2-phy";
diff --git a/dts/src/arm/am437x-gp-evm.dts b/dts/src/arm/am437x-gp-evm.dts
index 646a6eade7..e7ac47fa66 100644
--- a/dts/src/arm/am437x-gp-evm.dts
+++ b/dts/src/arm/am437x-gp-evm.dts
@@ -260,7 +260,7 @@
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
- clock-frequency = <400000>;
+ clock-frequency = <100000>;
tps65218: tps65218@24 {
reg = <0x24>;
@@ -424,7 +424,7 @@
ranges = <0 0 0 0x01000000>; /* minimum GPMC partition = 16MB */
nand@0,0 {
reg = <0 0 4>; /* device IO registers */
- ti,nand-ecc-opt = "bch8";
+ ti,nand-ecc-opt = "bch16";
ti,elm-id = <&elm>;
nand-bus-width = <8>;
gpmc,device-width = <1>;
@@ -443,8 +443,6 @@
gpmc,rd-cycle-ns = <40>;
gpmc,wr-cycle-ns = <40>;
gpmc,wait-pin = <0>;
- gpmc,wait-on-read;
- gpmc,wait-on-write;
gpmc,bus-turnaround-ns = <0>;
gpmc,cycle2cycle-delay-ns = <0>;
gpmc,clk-activation-ns = <0>;
diff --git a/dts/src/arm/am43x-epos-evm.dts b/dts/src/arm/am43x-epos-evm.dts
index ed7dd23959..ac3e485993 100644
--- a/dts/src/arm/am43x-epos-evm.dts
+++ b/dts/src/arm/am43x-epos-evm.dts
@@ -435,13 +435,13 @@
};
&gpmc {
- status = "okay";
+ status = "okay"; /* Disable QSPI when enabling GPMC (NAND) */
pinctrl-names = "default";
pinctrl-0 = <&nand_flash_x8>;
ranges = <0 0 0x08000000 0x10000000>; /* CS0: NAND */
nand@0,0 {
reg = <0 0 0>; /* CS0, offset 0 */
- ti,nand-ecc-opt = "bch8";
+ ti,nand-ecc-opt = "bch16";
ti,elm-id = <&elm>;
nand-bus-width = <8>;
gpmc,device-width = <1>;
@@ -459,8 +459,7 @@
gpmc,access-ns = <30>; /* tCEA + 4*/
gpmc,rd-cycle-ns = <40>;
gpmc,wr-cycle-ns = <40>;
- gpmc,wait-on-read = "true";
- gpmc,wait-on-write = "true";
+ gpmc,wait-pin = <0>;
gpmc,bus-turnaround-ns = <0>;
gpmc,cycle2cycle-delay-ns = <0>;
gpmc,clk-activation-ns = <0>;
@@ -557,7 +556,7 @@
};
&qspi {
- status = "okay";
+ status = "disabled"; /* Disable GPMC (NAND) when enabling QSPI */
pinctrl-names = "default";
pinctrl-0 = <&qspi1_default>;
diff --git a/dts/src/arm/at91rm9200.dtsi b/dts/src/arm/at91rm9200.dtsi
index 65ccf564b9..6c97d4af61 100644
--- a/dts/src/arm/at91rm9200.dtsi
+++ b/dts/src/arm/at91rm9200.dtsi
@@ -149,7 +149,7 @@
usb: usbck {
compatible = "atmel,at91rm9200-clk-usb";
#clock-cells = <0>;
- atmel,clk-divisors = <1 2>;
+ atmel,clk-divisors = <1 2 0 0>;
clocks = <&pllb>;
};
diff --git a/dts/src/arm/at91sam9g20.dtsi b/dts/src/arm/at91sam9g20.dtsi
index 31f7652612..4e0abbd9d6 100644
--- a/dts/src/arm/at91sam9g20.dtsi
+++ b/dts/src/arm/at91sam9g20.dtsi
@@ -40,6 +40,7 @@
};
pllb: pllbck {
+ compatible = "atmel,at91sam9g20-clk-pllb";
atmel,clk-input-range = <2000000 32000000>;
atmel,pll-clk-output-ranges = <30000000 100000000 0 0>;
};
diff --git a/dts/src/arm/dra7-evm.dts b/dts/src/arm/dra7-evm.dts
index 50f8022905..e03fbf3c68 100644
--- a/dts/src/arm/dra7-evm.dts
+++ b/dts/src/arm/dra7-evm.dts
@@ -8,6 +8,7 @@
/dts-v1/;
#include "dra74x.dtsi"
+#include <dt-bindings/gpio/gpio.h>
/ {
model = "TI DRA742";
@@ -24,9 +25,29 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
+
+ vtt_fixed: fixedregulator-vtt {
+ compatible = "regulator-fixed";
+ regulator-name = "vtt_fixed";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-boot-on;
+ enable-active-high;
+ gpio = <&gpio7 11 GPIO_ACTIVE_HIGH>;
+ };
};
&dra7_pmx_core {
+ pinctrl-names = "default";
+ pinctrl-0 = <&vtt_pin>;
+
+ vtt_pin: pinmux_vtt_pin {
+ pinctrl-single,pins = <
+ 0x3b4 (PIN_OUTPUT | MUX_MODE14) /* spi1_cs1.gpio7_11 */
+ >;
+ };
+
i2c1_pins: pinmux_i2c1_pins {
pinctrl-single,pins = <
0x400 (PIN_INPUT | MUX_MODE0) /* i2c1_sda */
@@ -43,20 +64,19 @@
i2c3_pins: pinmux_i2c3_pins {
pinctrl-single,pins = <
- 0x410 (PIN_INPUT | MUX_MODE0) /* i2c3_sda */
- 0x414 (PIN_INPUT | MUX_MODE0) /* i2c3_scl */
+ 0x288 (PIN_INPUT | MUX_MODE9) /* gpio6_14.i2c3_sda */
+ 0x28c (PIN_INPUT | MUX_MODE9) /* gpio6_15.i2c3_scl */
>;
};
mcspi1_pins: pinmux_mcspi1_pins {
pinctrl-single,pins = <
- 0x3a4 (PIN_INPUT | MUX_MODE0) /* spi2_clk */
- 0x3a8 (PIN_INPUT | MUX_MODE0) /* spi2_d1 */
- 0x3ac (PIN_INPUT | MUX_MODE0) /* spi2_d0 */
- 0x3b0 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs0 */
- 0x3b4 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs1 */
- 0x3b8 (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs2 */
- 0x3bc (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs3 */
+ 0x3a4 (PIN_INPUT | MUX_MODE0) /* spi1_sclk */
+ 0x3a8 (PIN_INPUT | MUX_MODE0) /* spi1_d1 */
+ 0x3ac (PIN_INPUT | MUX_MODE0) /* spi1_d0 */
+ 0x3b0 (PIN_INPUT_SLEW | MUX_MODE0) /* spi1_cs0 */
+ 0x3b8 (PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs2.hdmi1_hpd */
+ 0x3bc (PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs3.hdmi1_cec */
>;
};
@@ -284,7 +304,7 @@
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c3_pins>;
- clock-frequency = <3400000>;
+ clock-frequency = <400000>;
};
&mcspi1 {
@@ -483,7 +503,7 @@
reg = <0x001c0000 0x00020000>;
};
partition@7 {
- label = "NAND.u-boot-env";
+ label = "NAND.u-boot-env.backup1";
reg = <0x001e0000 0x00020000>;
};
partition@8 {
@@ -504,3 +524,8 @@
&usb2_phy2 {
phy-supply = <&ldousb_reg>;
};
+
+&gpio7 {
+ ti,no-reset-on-init;
+ ti,no-idle-on-init;
+};
diff --git a/dts/src/arm/dra7.dtsi b/dts/src/arm/dra7.dtsi
index 97f603c448..d678152db4 100644
--- a/dts/src/arm/dra7.dtsi
+++ b/dts/src/arm/dra7.dtsi
@@ -245,7 +245,7 @@
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
- #interrupt-cells = <1>;
+ #interrupt-cells = <2>;
};
gpio2: gpio@48055000 {
@@ -256,7 +256,7 @@
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
- #interrupt-cells = <1>;
+ #interrupt-cells = <2>;
};
gpio3: gpio@48057000 {
@@ -267,7 +267,7 @@
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
- #interrupt-cells = <1>;
+ #interrupt-cells = <2>;
};
gpio4: gpio@48059000 {
@@ -278,7 +278,7 @@
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
- #interrupt-cells = <1>;
+ #interrupt-cells = <2>;
};
gpio5: gpio@4805b000 {
@@ -289,7 +289,7 @@
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
- #interrupt-cells = <1>;
+ #interrupt-cells = <2>;
};
gpio6: gpio@4805d000 {
@@ -300,7 +300,7 @@
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
- #interrupt-cells = <1>;
+ #interrupt-cells = <2>;
};
gpio7: gpio@48051000 {
@@ -311,7 +311,7 @@
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
- #interrupt-cells = <1>;
+ #interrupt-cells = <2>;
};
gpio8: gpio@48053000 {
@@ -322,7 +322,7 @@
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
- #interrupt-cells = <1>;
+ #interrupt-cells = <2>;
};
uart1: serial@4806a000 {
diff --git a/dts/src/arm/imx53-qsrb.dts b/dts/src/arm/imx53-qsrb.dts
index f1bbf9a329..82d623d059 100644
--- a/dts/src/arm/imx53-qsrb.dts
+++ b/dts/src/arm/imx53-qsrb.dts
@@ -28,6 +28,12 @@
MX53_PAD_CSI0_DAT9__I2C1_SCL 0x400001ec
>;
};
+
+ pinctrl_pmic: pmicgrp {
+ fsl,pins = <
+ MX53_PAD_CSI0_DAT5__GPIO5_23 0x1e4 /* IRQ */
+ >;
+ };
};
};
@@ -38,6 +44,8 @@
pmic: mc34708@8 {
compatible = "fsl,mc34708";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pmic>;
reg = <0x08>;
interrupt-parent = <&gpio5>;
interrupts = <23 0x8>;
diff --git a/dts/src/arm/imx6dl-hummingboard.dts b/dts/src/arm/imx6dl-hummingboard.dts
index c8e51dd41b..7159854608 100644
--- a/dts/src/arm/imx6dl-hummingboard.dts
+++ b/dts/src/arm/imx6dl-hummingboard.dts
@@ -58,7 +58,7 @@
sound-spdif {
compatible = "fsl,imx-audio-spdif";
- model = "imx-spdif";
+ model = "On-board SPDIF";
/* IMX6 doesn't implement this yet */
spdif-controller = <&spdif>;
spdif-out;
@@ -181,11 +181,13 @@
};
&usbh1 {
+ disable-over-current;
vbus-supply = <&reg_usbh1_vbus>;
status = "okay";
};
&usbotg {
+ disable-over-current;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hummingboard_usbotg_id>;
vbus-supply = <&reg_usbotg_vbus>;
diff --git a/dts/src/arm/imx6qdl-cubox-i.dtsi b/dts/src/arm/imx6qdl-cubox-i.dtsi
index e8e781656b..6a524ca011 100644
--- a/dts/src/arm/imx6qdl-cubox-i.dtsi
+++ b/dts/src/arm/imx6qdl-cubox-i.dtsi
@@ -61,7 +61,7 @@
sound-spdif {
compatible = "fsl,imx-audio-spdif";
- model = "imx-spdif";
+ model = "Integrated SPDIF";
/* IMX6 doesn't implement this yet */
spdif-controller = <&spdif>;
spdif-out;
@@ -130,16 +130,23 @@
fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
};
+ pinctrl_cubox_i_usbh1: cubox-i-usbh1 {
+ fsl,pins = <MX6QDL_PAD_GPIO_3__USB_H1_OC 0x1b0b0>;
+ };
+
pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus {
fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x4001b0b0>;
};
- pinctrl_cubox_i_usbotg_id: cubox-i-usbotg-id {
+ pinctrl_cubox_i_usbotg: cubox-i-usbotg {
/*
- * The Cubox-i pulls this low, but as it's pointless
+ * The Cubox-i pulls ID low, but as it's pointless
* leaving it as a pull-up, even if it is just 10uA.
*/
- fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>;
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059
+ MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
+ >;
};
pinctrl_cubox_i_usbotg_vbus: cubox-i-usbotg-vbus {
@@ -173,13 +180,15 @@
};
&usbh1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_cubox_i_usbh1>;
vbus-supply = <&reg_usbh1_vbus>;
status = "okay";
};
&usbotg {
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_cubox_i_usbotg_id>;
+ pinctrl-0 = <&pinctrl_cubox_i_usbotg>;
vbus-supply = <&reg_usbotg_vbus>;
status = "okay";
};
diff --git a/dts/src/arm/imx6qdl-microsom-ar8035.dtsi b/dts/src/arm/imx6qdl-microsom-ar8035.dtsi
index d16066608e..db9f45b2c5 100644
--- a/dts/src/arm/imx6qdl-microsom-ar8035.dtsi
+++ b/dts/src/arm/imx6qdl-microsom-ar8035.dtsi
@@ -17,7 +17,7 @@
enet {
pinctrl_microsom_enet_ar8035: microsom-enet-ar8035 {
fsl,pins = <
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b8b0
MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
/* AR8035 reset */
MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x130b0
diff --git a/dts/src/arm/omap3-beagle.dts b/dts/src/arm/omap3-beagle.dts
index 3c3e6da1de..a9aae88b74 100644
--- a/dts/src/arm/omap3-beagle.dts
+++ b/dts/src/arm/omap3-beagle.dts
@@ -292,6 +292,7 @@
&uart3 {
pinctrl-names = "default";
pinctrl-0 = <&uart3_pins>;
+ interrupts-extended = <&intc 74 &omap3_pmx_core OMAP3_UART3_RX>;
};
&gpio1 {
diff --git a/dts/src/arm/omap3-n900.dts b/dts/src/arm/omap3-n900.dts
index b15f1a77d6..4361777a08 100644
--- a/dts/src/arm/omap3-n900.dts
+++ b/dts/src/arm/omap3-n900.dts
@@ -93,7 +93,7 @@
};
tv: connector {
- compatible = "composite-connector";
+ compatible = "composite-video-connector";
label = "tv";
port {
@@ -353,7 +353,7 @@
};
twl_power: power {
- compatible = "ti,twl4030-power-n900";
+ compatible = "ti,twl4030-power-n900", "ti,twl4030-power-idle-osc-off";
ti,use_poweroff;
};
};
diff --git a/dts/src/arm/omap3430-sdp.dts b/dts/src/arm/omap3430-sdp.dts
index 02f69f4a8f..9bad94efe1 100644
--- a/dts/src/arm/omap3430-sdp.dts
+++ b/dts/src/arm/omap3430-sdp.dts
@@ -107,7 +107,7 @@
#address-cells = <1>;
#size-cells = <1>;
reg = <1 0 0x08000000>;
- ti,nand-ecc-opt = "ham1";
+ ti,nand-ecc-opt = "sw";
nand-bus-width = <8>;
gpmc,cs-on-ns = <0>;
gpmc,cs-rd-off-ns = <36>;
diff --git a/dts/src/arm/omap3xxx-clocks.dtsi b/dts/src/arm/omap3xxx-clocks.dtsi
index e47ff69dcf..5c375003ba 100644
--- a/dts/src/arm/omap3xxx-clocks.dtsi
+++ b/dts/src/arm/omap3xxx-clocks.dtsi
@@ -467,6 +467,7 @@
ti,bit-shift = <0x1e>;
reg = <0x0d00>;
ti,set-bit-to-disable;
+ ti,set-rate-parent;
};
dpll4_m6_ck: dpll4_m6_ck {
diff --git a/dts/src/arm/omap54xx-clocks.dtsi b/dts/src/arm/omap54xx-clocks.dtsi
index e67a23b5d7..58c27466f0 100644
--- a/dts/src/arm/omap54xx-clocks.dtsi
+++ b/dts/src/arm/omap54xx-clocks.dtsi
@@ -367,10 +367,12 @@
l3_iclk_div: l3_iclk_div {
#clock-cells = <0>;
- compatible = "fixed-factor-clock";
+ compatible = "ti,divider-clock";
+ ti,max-div = <2>;
+ ti,bit-shift = <4>;
+ reg = <0x100>;
clocks = <&dpll_core_h12x2_ck>;
- clock-mult = <1>;
- clock-div = <1>;
+ ti,index-power-of-two;
};
gpu_l3_iclk: gpu_l3_iclk {
@@ -383,10 +385,12 @@
l4_root_clk_div: l4_root_clk_div {
#clock-cells = <0>;
- compatible = "fixed-factor-clock";
+ compatible = "ti,divider-clock";
+ ti,max-div = <2>;
+ ti,bit-shift = <8>;
+ reg = <0x100>;
clocks = <&l3_iclk_div>;
- clock-mult = <1>;
- clock-div = <1>;
+ ti,index-power-of-two;
};
slimbus1_slimbus_clk: slimbus1_slimbus_clk {
diff --git a/dts/src/arm/ste-snowball.dts b/dts/src/arm/ste-snowball.dts
index 4a2000c620..3e97a669f1 100644
--- a/dts/src/arm/ste-snowball.dts
+++ b/dts/src/arm/ste-snowball.dts
@@ -116,7 +116,6 @@
msp2: msp@80117000 {
pinctrl-names = "default";
pinctrl-0 = <&msp2_default_mode>;
- status = "okay";
};
msp3: msp@80125000 {
diff --git a/dts/src/arm/twl6030.dtsi b/dts/src/arm/twl6030.dtsi
index 2e3bd3172b..55eb35f068 100644
--- a/dts/src/arm/twl6030.dtsi
+++ b/dts/src/arm/twl6030.dtsi
@@ -83,10 +83,6 @@
regulator-always-on;
};
- clk32kg: regulator-clk32kg {
- compatible = "ti,twl6030-clk32kg";
- };
-
twl_usb_comparator: usb-comparator {
compatible = "ti,twl6030-usb";
interrupts = <4>, <10>;
diff --git a/dts/src/xtensa/kc705.dts b/dts/src/xtensa/kc705.dts
index 742a347be6..c4d17a34ab 100644
--- a/dts/src/xtensa/kc705.dts
+++ b/dts/src/xtensa/kc705.dts
@@ -4,8 +4,11 @@
/ {
compatible = "cdns,xtensa-kc705";
+ chosen {
+ bootargs = "earlycon=uart8250,mmio32,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=0x38000000";
+ };
memory@0 {
device_type = "memory";
- reg = <0x00000000 0x08000000>;
+ reg = <0x00000000 0x38000000>;
};
};
diff --git a/images/Makefile.am33xx b/images/Makefile.am33xx
index fa1f848816..92dd61a5f9 100644
--- a/images/Makefile.am33xx
+++ b/images/Makefile.am33xx
@@ -7,21 +7,33 @@ quiet_cmd_mlo_image = MLO $@
$(obj)/%.mlo: $(obj)/% FORCE
$(call if_changed,mlo_image)
+pblx-$(CONFIG_MACH_AFI_GF) += start_am33xx_afi_gf_sdram
+FILE_barebox-am33xx-afi-gf.img = start_am33xx_afi_gf_sdram.pblx
+am33xx-barebox-$(CONFIG_MACH_AFI_GF) += barebox-am33xx-afi-gf.img
+
+pblx-$(CONFIG_MACH_AFI_GF) += start_am33xx_afi_gf_sram
+FILE_barebox-am33xx-afi-gf-mlo.img = start_am33xx_afi_gf_sram.pblx.mlo
+am33xx-mlo-$(CONFIG_MACH_AFI_GF) += barebox-am33xx-afi-gf-mlo.img
+
pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sdram
FILE_barebox-am33xx-phytec-phycore.img = start_am33xx_phytec_phycore_sdram.pblx
am33xx-barebox-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore.img
-pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sram_1x256m16
-FILE_barebox-am33xx-phytec-phycore-mlo-1x256m16.img = start_am33xx_phytec_phycore_sram_1x256m16.pblx.mlo
-am33xx-mlo-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore-mlo-1x256m16.img
+pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sram_256mb
+FILE_barebox-am33xx-phytec-phycore-mlo-256mb.img = start_am33xx_phytec_phycore_sram_256mb.pblx.mlo
+am33xx-mlo-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore-mlo-256mb.img
+
+pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sram_128mb
+FILE_barebox-am33xx-phytec-phycore-mlo-128mb.img = start_am33xx_phytec_phycore_sram_128mb.pblx.mlo
+am33xx-mlo-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore-mlo-128mb.img
-pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sram_1x128m16
-FILE_barebox-am33xx-phytec-phycore-mlo-1x128m16.img = start_am33xx_phytec_phycore_sram_1x128m16.pblx.mlo
-am33xx-mlo-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore-mlo-1x128m16.img
+pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sram_512mb
+FILE_barebox-am33xx-phytec-phycore-mlo-512mb.img = start_am33xx_phytec_phycore_sram_512mb.pblx.mlo
+am33xx-mlo-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore-mlo-512mb.img
-pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sram_1x512m16
-FILE_barebox-am33xx-phytec-phycore-mlo-1x512m16.img = start_am33xx_phytec_phycore_sram_1x512m16.pblx.mlo
-am33xx-mlo-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore-mlo-1x512m16.img
+pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sram_2x512mb
+FILE_barebox-am33xx-phytec-phycore-mlo-2x512mb.img = start_am33xx_phytec_phycore_sram_2x512mb.pblx.mlo
+am33xx-mlo-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore-mlo-2x512mb.img
pblx-$(CONFIG_MACH_BEAGLEBONE) += start_am33xx_beaglebone_sdram
FILE_barebox-am33xx-beaglebone.img = start_am33xx_beaglebone_sdram.pblx
diff --git a/images/Makefile.imx b/images/Makefile.imx
index e559a75007..b6ca6c2cb6 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -160,6 +160,11 @@ CFG_start_imx6dl_nitrogen6x_1g.pblx.imximg = $(board)/boundarydevices-nitrogen6x
FILE_barebox-boundarydevices-imx6dl-nitrogen6x-1g.img = start_imx6dl_nitrogen6x_1g.pblx.imximg
image-$(CONFIG_MACH_NITROGEN6X) += barebox-boundarydevices-imx6dl-nitrogen6x-1g.img
+pblx-$(CONFIG_MACH_TX6X) += start_imx6dl_tx6x_1g
+CFG_start_imx6dl_tx6x_1g.pblx.imximg = $(board)/karo-tx6x/flash-header-tx6dl-1g.imxcfg
+FILE_barebox-karo-imx6dl-tx6x-1g.img = start_imx6dl_tx6x_1g.pblx.imximg
+image-$(CONFIG_MACH_TX6X) += barebox-karo-imx6dl-tx6x-1g.img
+
pblx-$(CONFIG_MACH_UDOO) += start_imx6_udoo
CFG_start_imx6_udoo.pblx.imximg = $(board)/udoo/flash-header-mx6-udoo.imxcfg
FILE_barebox-udoo-imx6q.img = start_imx6_udoo.pblx.imximg
@@ -194,3 +199,8 @@ pblx-$(CONFIG_MACH_PCAAXL3) += start_phytec_pbaa03_2gib
CFG_start_phytec_pbaa03_2gib.pblx.imximg = $(board)/phytec-phycard-imx6/flash-header-phytec-pcaaxl3-2gib.imxcfg
FILE_barebox-phytec-pbaa03-2gib.img = start_phytec_pbaa03_2gib.pblx.imximg
image-$(CONFIG_MACH_PCAAXL3) += barebox-phytec-pbaa03-2gib.img
+
+pblx-$(CONFIG_MACH_GW_VENTANA) += start_imx6q_gw54xx_1gx64
+CFG_start_imx6q_gw54xx_1gx64.pblx.imximg = $(board)/gateworks-ventana/flash-header-ventana-quad-1gx64.imxcfg
+FILE_barebox-gateworks-imx6q-ventana-1gx64.img = start_imx6q_gw54xx_1gx64.pblx.imximg
+image-$(CONFIG_MACH_GW_VENTANA) += barebox-gateworks-imx6q-ventana-1gx64.img
diff --git a/include/clock.h b/include/clock.h
index a169790d0f..691befc2e2 100644
--- a/include/clock.h
+++ b/include/clock.h
@@ -43,6 +43,8 @@ void mdelay(unsigned long msecs);
#define MSECOND ((uint64_t)(1000 * 1000))
#define USECOND ((uint64_t)(1000))
+extern uint64_t time_beginning;
+
/*
* Convenience wrapper to implement a typical polling loop with
* timeout. returns 0 if the condition became true within the
diff --git a/include/common.h b/include/common.h
index de635718d2..fca9798bbb 100644
--- a/include/common.h
+++ b/include/common.h
@@ -271,7 +271,13 @@ void barebox_set_model(const char *);
const char *barebox_get_hostname(void);
void barebox_set_hostname(const char *);
+#if defined(CONFIG_MIPS)
+#include <asm/addrspace.h>
+
+#define IOMEM(addr) ((void __force __iomem *)CKSEG1ADDR(addr))
+#else
#define IOMEM(addr) ((void __force __iomem *)(addr))
+#endif
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
diff --git a/include/firmware.h b/include/firmware.h
new file mode 100644
index 0000000000..f6f78c840c
--- /dev/null
+++ b/include/firmware.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013 Juergen Beisert <kernel@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef FIRMWARE_H
+#define FIRMWARE_H
+
+#include <types.h>
+#include <driver.h>
+
+struct firmware_handler {
+ char *id; /* unique identifier for this firmware device */
+ char *model; /* description for this device */
+ struct device_d *dev;
+ /* called once to prepare the firmware's programming cycle */
+ int (*open)(struct firmware_handler*);
+ /* called multiple times to program the firmware with the given data */
+ int (*write)(struct firmware_handler*, const void*, size_t);
+ /* called once to finish programming cycle */
+ int (*close)(struct firmware_handler*);
+};
+
+struct firmware_mgr;
+
+int firmwaremgr_register(struct firmware_handler *);
+
+struct firmware_mgr *firmwaremgr_find(const char *);
+
+void firmwaremgr_list_handlers(void);
+
+int firmwaremgr_load_file(struct firmware_mgr *, const char *path);
+
+#endif /* FIRMWARE_H */
diff --git a/include/linux/barebox-wrapper.h b/include/linux/barebox-wrapper.h
index 753fb52614..d34d1d1d0e 100644
--- a/include/linux/barebox-wrapper.h
+++ b/include/linux/barebox-wrapper.h
@@ -33,11 +33,14 @@ typedef int gfp_t;
#define MODULE_AUTHOR(x)
#define MODULE_DESCRIPTION(x)
#define MODULE_LICENSE(x)
+#define MODULE_ALIAS(x)
typedef int spinlock_t;
#define spin_lock_init(...)
#define spin_lock(...)
#define spin_unlock(...)
+static inline void spin_lock_irqsave(spinlock_t *lock, unsigned long flags) {}
+static inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) {}
#define mutex_init(...)
#define mutex_lock(...)
@@ -66,4 +69,8 @@ typedef int wait_queue_head_t;
#define init_waitqueue_head(...) do { } while (0)
+typedef int irqreturn_t;
+#define IRQ_NONE 0
+#define IRQ_HANDLED 0
+
#endif /* __INCLUDE_LINUX_BAREBOX_WRAPPER_H */
diff --git a/include/linux/marvell_phy.h b/include/linux/marvell_phy.h
new file mode 100644
index 0000000000..bf2c66ac65
--- /dev/null
+++ b/include/linux/marvell_phy.h
@@ -0,0 +1,34 @@
+/*
+ * Marvell PHY IDs
+ *
+ * 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.
+ */
+
+#ifndef _MARVELL_PHY_H
+#define _MARVELL_PHY_H
+
+/* Known PHY IDs */
+#define MARVELL_PHY_ID_88E1101 0x01410c60
+#define MARVELL_PHY_ID_88E1112 0x01410c90
+#define MARVELL_PHY_ID_88E1111 0x01410cc0
+#define MARVELL_PHY_ID_88E1118 0x01410e10
+#define MARVELL_PHY_ID_88E1121R 0x01410cb0
+#define MARVELL_PHY_ID_88E1145 0x01410cd0
+#define MARVELL_PHY_ID_88E1149R 0x01410e50
+#define MARVELL_PHY_ID_88E1240 0x01410e30
+#define MARVELL_PHY_ID_88E1318S 0x01410e90
+#define MARVELL_PHY_ID_88E1116R 0x01410e40
+#define MARVELL_PHY_ID_88E1510 0x01410dd0
+
+/* Mask used for ID comparisons */
+#define MARVELL_PHY_ID_MASK 0xfffffff0
+
+#endif /* _MARVELL_PHY_H */
diff --git a/include/linux/mbus.h b/include/linux/mbus.h
index ac14982875..b90fabbfb7 100644
--- a/include/linux/mbus.h
+++ b/include/linux/mbus.h
@@ -58,6 +58,7 @@ int mvebu_mbus_add_window_by_id(unsigned int target, unsigned int attribute,
phys_addr_t base, size_t size);
int mvebu_mbus_del_window(phys_addr_t base, size_t size);
-void mvebu_mbus_add_range(u8 target, u8 attr, u32 remap);
+void mvebu_mbus_add_range(const char *compatible,
+ u8 target, u8 attr, u32 remap);
#endif /* __LINUX_MBUS_H */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 7c5d754a12..c0fd4ff19a 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -234,6 +234,9 @@ struct phy_driver {
*/
int (*config_aneg)(struct phy_device *phydev);
+ /* Determines the auto negotiation result */
+ int (*aneg_done)(struct phy_device *phydev);
+
/* Determines the negotiated speed and duplex */
int (*read_status)(struct phy_device *phydev);
@@ -295,6 +298,7 @@ int phy_wait_aneg_done(struct phy_device *phydev);
/* Generic PHY support and helper functions */
int genphy_restart_aneg(struct phy_device *phydev);
int genphy_config_aneg(struct phy_device *phydev);
+int genphy_aneg_done(struct phy_device *phydev);
int genphy_update_link(struct phy_device *phydev);
int genphy_read_status(struct phy_device *phydev);
int genphy_config_advert(struct phy_device *phydev);
diff --git a/include/of.h b/include/of.h
index e6993fdde1..29694a9020 100644
--- a/include/of.h
+++ b/include/of.h
@@ -123,6 +123,8 @@ extern struct device_node *of_find_node_by_path_from(struct device_node *from,
const char *path);
extern struct device_node *of_find_node_by_path(const char *path);
extern struct device_node *of_find_node_by_phandle(phandle phandle);
+extern struct device_node *of_find_node_by_phandle_from(phandle phandle,
+ struct device_node *root);
extern struct device_node *of_find_node_by_type(struct device_node *from,
const char *type);
extern struct device_node *of_find_compatible_node(struct device_node *from,
@@ -203,6 +205,10 @@ extern int of_property_write_u64_array(struct device_node *np,
extern struct device_node *of_parse_phandle(const struct device_node *np,
const char *phandle_name,
int index);
+extern struct device_node *of_parse_phandle_from(const struct device_node *np,
+ struct device_node *root,
+ const char *phandle_name,
+ int index);
extern int of_parse_phandle_with_args(const struct device_node *np,
const char *list_name, const char *cells_name, int index,
struct of_phandle_args *out_args);
@@ -437,6 +443,13 @@ static inline struct device_node *of_parse_phandle(const struct device_node *np,
return NULL;
}
+static inline struct device_node *of_parse_phandle_from(const struct device_node *np,
+ struct device_node *root,
+ const char *phandle_name, int index)
+{
+ return NULL;
+}
+
static inline int of_parse_phandle_with_args(const struct device_node *np,
const char *list_name, const char *cells_name, int index,
struct of_phandle_args *out_args)
@@ -472,6 +485,12 @@ static inline struct device_node *of_find_node_by_phandle(phandle phandle)
return NULL;
}
+static inline struct device_node *of_find_node_by_phandle_from(phandle phandle,
+ struct device_node *root)
+{
+ return NULL;
+}
+
static inline struct device_node *of_find_compatible_node(
struct device_node *from,
const char *type,
@@ -568,6 +587,9 @@ static inline struct device_d *of_find_device_by_node(struct device_node *np)
#define for_each_node_by_name(dn, name) \
for (dn = of_find_node_by_name(NULL, name); dn; \
dn = of_find_node_by_name(dn, name))
+#define for_each_node_by_name_from(dn, root, name) \
+ for (dn = of_find_node_by_name(root, name); dn; \
+ dn = of_find_node_by_name(dn, name))
#define for_each_compatible_node(dn, type, compatible) \
for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
dn = of_find_compatible_node(dn, type, compatible))
@@ -692,6 +714,7 @@ int of_device_disable_path(const char *path);
phandle of_get_tree_max_phandle(struct device_node *root);
phandle of_node_create_phandle(struct device_node *node);
+int of_set_property_to_child_phandle(struct device_node *node, char *prop_name);
struct device_node *of_find_node_by_alias(struct device_node *root,
const char *alias);
struct device_node *of_find_node_by_path_or_alias(struct device_node *root,
diff --git a/include/printk.h b/include/printk.h
index 454315632b..fb635868ab 100644
--- a/include/printk.h
+++ b/include/printk.h
@@ -72,4 +72,21 @@ int dev_printf(int level, const struct device_d *dev, const char *format, ...)
#define debug(fmt, arg...) __pr_printk(7, pr_fmt(fmt), ##arg)
#define pr_vdebug(fmt, arg...) __pr_printk(8, pr_fmt(fmt), ##arg)
+struct log_entry {
+ struct list_head list;
+ char *msg;
+ void *dummy;
+ uint64_t timestamp;
+ int level;
+};
+
+extern struct list_head barebox_logbuf;
+
+extern void log_clean(unsigned int limit);
+
+#define BAREBOX_LOG_PRINT_TIME (1 << 0)
+#define BAREBOX_LOG_DIFF_TIME (1 << 1)
+
+void log_print(unsigned flags);
+
#endif
diff --git a/include/usb/gadget.h b/include/usb/gadget.h
index 7106f9d788..f663e98abf 100644
--- a/include/usb/gadget.h
+++ b/include/usb/gadget.h
@@ -483,6 +483,7 @@ struct usb_gadget_ops {
struct usb_gadget_driver *);
int (*udc_stop)(struct usb_gadget *,
struct usb_gadget_driver *);
+ void (*udc_poll)(struct usb_gadget *);
};
/**
diff --git a/include/usb/musb.h b/include/usb/musb.h
new file mode 100644
index 0000000000..13eb9f8aac
--- /dev/null
+++ b/include/usb/musb.h
@@ -0,0 +1,152 @@
+/*
+ * This is used to for host and peripheral modes of the driver for
+ * Inventra (Multidrop) Highspeed Dual-Role Controllers: (M)HDRC.
+ *
+ * Board initialization should put one of these into dev->platform_data,
+ * probably on some platform_device named "musb-hdrc". It encapsulates
+ * key configuration differences between boards.
+ */
+
+#ifndef __LINUX_USB_MUSB_H
+#define __LINUX_USB_MUSB_H
+
+/* The USB role is defined by the connector used on the board, so long as
+ * standards are being followed. (Developer boards sometimes won't.)
+ */
+enum musb_mode {
+ MUSB_UNDEFINED = 0,
+ MUSB_HOST, /* A or Mini-A connector */
+ MUSB_PERIPHERAL, /* B or Mini-B connector */
+ MUSB_OTG /* Mini-AB connector */
+};
+
+struct clk;
+
+enum musb_fifo_style {
+ FIFO_RXTX,
+ FIFO_TX,
+ FIFO_RX
+} __attribute__ ((packed));
+
+enum musb_buf_mode {
+ BUF_SINGLE,
+ BUF_DOUBLE
+} __attribute__ ((packed));
+
+struct musb_fifo_cfg {
+ u8 hw_ep_num;
+ enum musb_fifo_style style;
+ enum musb_buf_mode mode;
+ u16 maxpacket;
+};
+
+#define MUSB_EP_FIFO(ep, st, m, pkt) \
+{ \
+ .hw_ep_num = ep, \
+ .style = st, \
+ .mode = m, \
+ .maxpacket = pkt, \
+}
+
+#define MUSB_EP_FIFO_SINGLE(ep, st, pkt) \
+ MUSB_EP_FIFO(ep, st, BUF_SINGLE, pkt)
+
+#define MUSB_EP_FIFO_DOUBLE(ep, st, pkt) \
+ MUSB_EP_FIFO(ep, st, BUF_DOUBLE, pkt)
+
+struct musb_hdrc_eps_bits {
+ const char name[16];
+ u8 bits;
+};
+
+struct musb_hdrc_config {
+ struct musb_fifo_cfg *fifo_cfg; /* board fifo configuration */
+ unsigned fifo_cfg_size; /* size of the fifo configuration */
+
+ /* MUSB configuration-specific details */
+ unsigned multipoint:1; /* multipoint device */
+ unsigned dyn_fifo:1 __deprecated; /* supports dynamic fifo sizing */
+ unsigned soft_con:1 __deprecated; /* soft connect required */
+ unsigned utm_16:1 __deprecated; /* utm data witdh is 16 bits */
+ unsigned big_endian:1; /* true if CPU uses big-endian */
+ unsigned mult_bulk_tx:1; /* Tx ep required for multbulk pkts */
+ unsigned mult_bulk_rx:1; /* Rx ep required for multbulk pkts */
+ unsigned high_iso_tx:1; /* Tx ep required for HB iso */
+ unsigned high_iso_rx:1; /* Rx ep required for HD iso */
+ unsigned dma:1 __deprecated; /* supports DMA */
+ unsigned vendor_req:1 __deprecated; /* vendor registers required */
+
+ u8 num_eps; /* number of endpoints _with_ ep0 */
+ u8 dma_channels __deprecated; /* number of dma channels */
+ u8 dyn_fifo_size; /* dynamic size in bytes */
+ u8 vendor_ctrl __deprecated; /* vendor control reg width */
+ u8 vendor_stat __deprecated; /* vendor status reg witdh */
+ u8 dma_req_chan __deprecated; /* bitmask for required dma channels */
+ u8 ram_bits; /* ram address size */
+
+ struct musb_hdrc_eps_bits *eps_bits __deprecated;
+#ifdef CONFIG_BLACKFIN
+ /* A GPIO controlling VRSEL in Blackfin */
+ unsigned int gpio_vrsel;
+ unsigned int gpio_vrsel_active;
+ /* musb CLKIN in Blackfin in MHZ */
+ unsigned char clkin;
+#endif
+
+};
+
+struct musb_hdrc_platform_data {
+ /* MUSB_HOST, MUSB_PERIPHERAL, or MUSB_OTG */
+ u8 mode;
+
+ /* for clk_get() */
+ const char *clock;
+
+ /* (HOST or OTG) switch VBUS on/off */
+ int (*set_vbus)(struct device_d *dev, int is_on);
+
+ /* (HOST or OTG) mA/2 power supplied on (default = 8mA) */
+ u8 power;
+
+ /* (PERIPHERAL) mA/2 max power consumed (default = 100mA) */
+ u8 min_power;
+
+ /* (HOST or OTG) msec/2 after VBUS on till power good */
+ u8 potpgt;
+
+ /* (HOST or OTG) program PHY for external Vbus */
+ unsigned extvbus:1;
+
+ /* Power the device on or off */
+ int (*set_power)(int state);
+
+ /* MUSB configuration-specific details */
+ struct musb_hdrc_config *config;
+
+ /* Architecture specific board data */
+ void *board_data;
+
+ /* Platform specific struct musb_ops pointer */
+ const void *platform_ops;
+};
+
+
+/* TUSB 6010 support */
+
+#define TUSB6010_OSCCLK_60 16667 /* psec/clk @ 60.0 MHz */
+#define TUSB6010_REFCLK_24 41667 /* psec/clk @ 24.0 MHz XI */
+#define TUSB6010_REFCLK_19 52083 /* psec/clk @ 19.2 MHz CLKIN */
+
+#ifdef CONFIG_ARCH_OMAP2
+
+extern int __init tusb6010_setup_interface(
+ struct musb_hdrc_platform_data *data,
+ unsigned ps_refclk, unsigned waitpin,
+ unsigned async_cs, unsigned sync_cs,
+ unsigned irq, unsigned dmachan);
+
+extern int tusb6010_platform_retime(unsigned is_refclk);
+
+#endif /* OMAP2 */
+
+#endif /* __LINUX_USB_MUSB_H */
diff --git a/include/usb/phy.h b/include/usb/phy.h
new file mode 100644
index 0000000000..057ad1cd95
--- /dev/null
+++ b/include/usb/phy.h
@@ -0,0 +1,220 @@
+/* USB OTG (On The Go) defines */
+/*
+ *
+ * These APIs may be used between USB controllers. USB device drivers
+ * (for either host or peripheral roles) don't use these calls; they
+ * continue to use just usb_device and usb_gadget.
+ */
+
+#ifndef __LINUX_USB_PHY_H
+#define __LINUX_USB_PHY_H
+
+#include <notifier.h>
+#include <usb/usb.h>
+#include <linux/err.h>
+
+enum usb_phy_interface {
+ USBPHY_INTERFACE_MODE_UNKNOWN,
+ USBPHY_INTERFACE_MODE_UTMI,
+ USBPHY_INTERFACE_MODE_UTMIW,
+ USBPHY_INTERFACE_MODE_ULPI,
+ USBPHY_INTERFACE_MODE_SERIAL,
+ USBPHY_INTERFACE_MODE_HSIC,
+};
+
+enum usb_phy_events {
+ USB_EVENT_NONE, /* no events or cable disconnected */
+ USB_EVENT_VBUS, /* vbus valid event */
+ USB_EVENT_ID, /* id was grounded */
+ USB_EVENT_CHARGER, /* usb dedicated charger */
+ USB_EVENT_ENUMERATED, /* gadget driver enumerated */
+};
+
+/* associate a type with PHY */
+enum usb_phy_type {
+ USB_PHY_TYPE_UNDEFINED,
+ USB_PHY_TYPE_USB2,
+ USB_PHY_TYPE_USB3,
+};
+
+struct usb_phy;
+
+/* for transceivers connected thru an ULPI interface, the user must
+ * provide access ops
+ */
+struct usb_phy_io_ops {
+ int (*read)(struct usb_phy *x, u32 reg);
+ int (*write)(struct usb_phy *x, u32 val, u32 reg);
+};
+
+struct usb_phy {
+ struct device_d *dev;
+ const char *label;
+ unsigned int flags;
+
+ enum usb_phy_type type;
+ enum usb_phy_events last_event;
+
+ struct usb_phy_io_ops *io_ops;
+ void __iomem *io_priv;
+
+ /* to pass extra port status to the root hub */
+ u16 port_status;
+ u16 port_change;
+
+ /* to support controllers that have multiple transceivers */
+ struct list_head head;
+
+ /* initialize/shutdown the OTG controller */
+ int (*init)(struct usb_phy *x);
+ void (*shutdown)(struct usb_phy *x);
+
+ /* enable/disable VBUS */
+ int (*set_vbus)(struct usb_phy *x, int on);
+
+ /* effective for B devices, ignored for A-peripheral */
+ int (*set_power)(struct usb_phy *x,
+ unsigned mA);
+
+ /* for non-OTG B devices: set transceiver into suspend mode */
+ int (*set_suspend)(struct usb_phy *x,
+ int suspend);
+
+ /*
+ * Set wakeup enable for PHY, in that case, the PHY can be
+ * woken up from suspend status due to external events,
+ * like vbus change, dp/dm change and id.
+ */
+ int (*set_wakeup)(struct usb_phy *x, bool enabled);
+
+ /* notify phy connect status change */
+ int (*notify_connect)(struct usb_phy *x,
+ enum usb_device_speed speed);
+ int (*notify_disconnect)(struct usb_phy *x,
+ enum usb_device_speed speed);
+};
+
+/**
+ * struct usb_phy_bind - represent the binding for the phy
+ * @dev_name: the device name of the device that will bind to the phy
+ * @phy_dev_name: the device name of the phy
+ * @index: used if a single controller uses multiple phys
+ * @phy: reference to the phy
+ * @list: to maintain a linked list of the binding information
+ */
+struct usb_phy_bind {
+ const char *dev_name;
+ const char *phy_dev_name;
+ u8 index;
+ struct usb_phy *phy;
+ struct list_head list;
+};
+
+/* helpers for direct access thru low-level io interface */
+static inline int usb_phy_io_read(struct usb_phy *x, u32 reg)
+{
+ if (x && x->io_ops && x->io_ops->read)
+ return x->io_ops->read(x, reg);
+
+ return -EINVAL;
+}
+
+static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg)
+{
+ if (x && x->io_ops && x->io_ops->write)
+ return x->io_ops->write(x, val, reg);
+
+ return -EINVAL;
+}
+
+static inline int
+usb_phy_init(struct usb_phy *x)
+{
+ if (x && x->init)
+ return x->init(x);
+
+ return 0;
+}
+
+static inline void
+usb_phy_shutdown(struct usb_phy *x)
+{
+ if (x && x->shutdown)
+ x->shutdown(x);
+}
+
+static inline int
+usb_phy_vbus_on(struct usb_phy *x)
+{
+ if (!x || !x->set_vbus)
+ return 0;
+
+ return x->set_vbus(x, true);
+}
+
+static inline int
+usb_phy_vbus_off(struct usb_phy *x)
+{
+ if (!x || !x->set_vbus)
+ return 0;
+
+ return x->set_vbus(x, false);
+}
+
+static inline int
+usb_phy_set_power(struct usb_phy *x, unsigned mA)
+{
+ if (x && x->set_power)
+ return x->set_power(x, mA);
+ return 0;
+}
+
+/* Context: can sleep */
+static inline int
+usb_phy_set_suspend(struct usb_phy *x, int suspend)
+{
+ if (x && x->set_suspend != NULL)
+ return x->set_suspend(x, suspend);
+ else
+ return 0;
+}
+
+static inline int
+usb_phy_set_wakeup(struct usb_phy *x, bool enabled)
+{
+ if (x && x->set_wakeup)
+ return x->set_wakeup(x, enabled);
+ else
+ return 0;
+}
+
+static inline int
+usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed)
+{
+ if (x && x->notify_connect)
+ return x->notify_connect(x, speed);
+ else
+ return 0;
+}
+
+static inline int
+usb_phy_notify_disconnect(struct usb_phy *x, enum usb_device_speed speed)
+{
+ if (x && x->notify_disconnect)
+ return x->notify_disconnect(x, speed);
+ else
+ return 0;
+}
+
+static inline const char *usb_phy_type_string(enum usb_phy_type type)
+{
+ switch (type) {
+ case USB_PHY_TYPE_USB2:
+ return "USB2 PHY";
+ case USB_PHY_TYPE_USB3:
+ return "USB3 PHY";
+ default:
+ return "UNKNOWN PHY TYPE";
+ }
+}
+#endif /* __LINUX_USB_PHY_H */
diff --git a/include/usb/usb.h b/include/usb/usb.h
index 82acf20b12..f02f1fbb57 100644
--- a/include/usb/usb.h
+++ b/include/usb/usb.h
@@ -440,15 +440,6 @@ enum usb_dr_mode {
enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np,
const char *propname);
-enum usb_phy_interface {
- USBPHY_INTERFACE_MODE_UNKNOWN,
- USBPHY_INTERFACE_MODE_UTMI,
- USBPHY_INTERFACE_MODE_UTMIW,
- USBPHY_INTERFACE_MODE_ULPI,
- USBPHY_INTERFACE_MODE_SERIAL,
- USBPHY_INTERFACE_MODE_HSIC,
-};
-
extern struct list_head usb_device_list;
#endif /*_USB_H_ */
diff --git a/lib/libfile.c b/lib/libfile.c
index c6fb6d7157..c626e2f4a0 100644
--- a/lib/libfile.c
+++ b/lib/libfile.c
@@ -163,8 +163,10 @@ again:
buf = xzalloc(read_size + 1);
fd = open(filename, O_RDONLY);
- if (fd < 0)
+ if (fd < 0) {
+ ret = fd;
goto err_out;
+ }
ret = read_full(fd, buf, read_size);
if (ret < 0)
diff --git a/net/eth.c b/net/eth.c
index b830f79249..89bddba07d 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -246,7 +246,7 @@ static int __eth_rx(struct eth_device *edev)
if (ret)
return ret;
- return edev->recv(eth_current);
+ return edev->recv(edev);
}
int eth_rx(void)
diff --git a/scripts/.gitignore b/scripts/.gitignore
index 1df04ba5b1..b574b22fb1 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -10,7 +10,7 @@ kwbimage
kwboot
gen_netx_image
omap_signGP
-mk-am3xxx-spi-image
+mk-omap-image
s5p_cksum
mkublheader
zynq_mkimage
@@ -19,3 +19,6 @@ bareboxenv-target
kernel-install-target
bareboxcrc32-target
bareboximd-target
+bareboxstate
+bareboxstate-target
+mk-am35xx-spi-image
diff --git a/scripts/Makefile b/scripts/Makefile
index 2050ec497d..5483a64245 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -14,7 +14,7 @@ hostprogs-$(CONFIG_IMD) += bareboximd
hostprogs-$(CONFIG_KALLSYMS) += kallsyms
hostprogs-$(CONFIG_ARCH_MVEBU) += kwbimage kwboot
hostprogs-$(CONFIG_ARCH_NETX) += gen_netx_image
-hostprogs-$(CONFIG_ARCH_OMAP) += omap_signGP mk-am3xxx-spi-image
+hostprogs-$(CONFIG_ARCH_OMAP) += omap_signGP mk-omap-image
hostprogs-$(CONFIG_ARCH_S5PCxx) += s5p_cksum
hostprogs-$(CONFIG_ARCH_DAVINCI) += mkublheader
hostprogs-$(CONFIG_ARCH_ZYNQ) += zynq_mkimage
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 153af8dd82..419436dede 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1425,6 +1425,16 @@ sub process {
$rpt_cleaners = 1;
}
+# Check for FSF mailing addresses.
+ if ($rawline =~ /\bwrite to the Free/i ||
+ $rawline =~ /\b59\s+Temple\s+Pl/i ||
+ $rawline =~ /\b51\s+Franklin\s+St/i) {
+ my $herevet = "$here\n" . cat_vet($rawline) . "\n";
+ my $msg_type = \&ERROR;
+ $msg_type = \&CHK if ($file);
+ &{$msg_type}("Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. barebox already includes a copy of the GPL.\n" . $herevet)
+ }
+
# check for Kconfig help text having a real description
# Only applies when adding the entry originally, after that we do not have
# sufficient context to determine whether it is indeed long enough.
diff --git a/scripts/imx/imx-image.c b/scripts/imx/imx-image.c
index 3a25c09298..1f37fe20bc 100644
--- a/scripts/imx/imx-image.c
+++ b/scripts/imx/imx-image.c
@@ -37,6 +37,7 @@ static uint32_t image_dcd_offset;
static uint32_t dcdtable[MAX_DCD];
static int curdcd;
static int header_version;
+static int cpu_type;
static int add_barebox_header;
/*
@@ -259,34 +260,29 @@ struct command {
int (*parse)(int argc, char *argv[]);
};
-static uint32_t last_cmd;
+static uint32_t last_write_cmd;
static int last_cmd_len;
static uint32_t *last_dcd;
static void check_last_dcd(uint32_t cmd)
{
- if (last_dcd) {
- if (last_cmd == cmd) {
- return;
- } else {
- uint32_t l = be32toh(*last_dcd);
+ cmd &= 0xff0000ff;
- l |= last_cmd_len << 8;
-
- *last_dcd = htobe32(l);
-
- last_dcd = NULL;
- }
+ if (cmd == last_write_cmd) {
+ last_cmd_len += sizeof(uint32_t) * 2;
+ return;
}
- if (!cmd)
- return;
+ /* write length ... */
+ if (last_write_cmd)
+ *last_dcd = htobe32(last_write_cmd | (last_cmd_len << 8));
- if (!last_dcd) {
+ if ((cmd >> 24) == TAG_WRITE) {
+ last_write_cmd = cmd;
last_dcd = &dcdtable[curdcd++];
- *last_dcd = htobe32(cmd);
- last_cmd_len = sizeof(uint32_t);
- last_cmd = cmd;
+ last_cmd_len = sizeof(uint32_t) * 3;
+ } else {
+ last_write_cmd = 0;
}
}
@@ -303,7 +299,6 @@ static int write_mem_v2(uint32_t addr, uint32_t val, int width)
check_last_dcd(cmd);
- last_cmd_len += sizeof(uint32_t) * 2;
dcdtable[curdcd++] = htobe32(addr);
dcdtable[curdcd++] = htobe32(val);
@@ -370,11 +365,11 @@ static int do_cmd_check(int argc, char *argv[])
return -EINVAL;
}
- cmd = (TAG_CHECK << 24) | (i << 3) | width;
+ cmd = (TAG_CHECK << 24) | (i << 3) | width | ((sizeof(uint32_t) * 3) << 8);
check_last_dcd(cmd);
- last_cmd_len += sizeof(uint32_t) * 2;
+ dcdtable[curdcd++] = htobe32(cmd);
dcdtable[curdcd++] = htobe32(addr);
dcdtable[curdcd++] = htobe32(mask);
@@ -454,14 +449,15 @@ static int do_dcd_offset(int argc, char *argv[])
struct soc_type {
char *name;
int header_version;
+ int cpu_type;
};
static struct soc_type socs[] = {
- { .name = "imx25", .header_version = 1, },
- { .name = "imx35", .header_version = 1, },
- { .name = "imx51", .header_version = 1, },
- { .name = "imx53", .header_version = 2, },
- { .name = "imx6", .header_version = 2, },
+ { .name = "imx25", .header_version = 1, .cpu_type = 25},
+ { .name = "imx35", .header_version = 1, .cpu_type = 35 },
+ { .name = "imx51", .header_version = 1, .cpu_type = 51 },
+ { .name = "imx53", .header_version = 2, .cpu_type = 53 },
+ { .name = "imx6", .header_version = 2, .cpu_type = 6 },
};
static int do_soc(int argc, char *argv[])
@@ -477,6 +473,7 @@ static int do_soc(int argc, char *argv[])
for (i = 0; i < ARRAY_SIZE(socs); i++) {
if (!strcmp(socs[i].name, soc)) {
header_version = socs[i].header_version;
+ cpu_type = socs[i].cpu_type;
return 0;
}
}
@@ -767,6 +764,14 @@ int main(int argc, char *argv[])
exit(1);
}
+ if (cpu_type == 35) {
+ ret = xwrite(outfd, buf, 4096);
+ if (ret < 0) {
+ perror("write");
+ exit(1);
+ }
+ }
+
infd = open(imagename, O_RDONLY);
if (infd < 0) {
perror("open");
diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
index 475917bc6c..c86260cdea 100644
--- a/scripts/imx/imx-usb-loader.c
+++ b/scripts/imx/imx-usb-loader.c
@@ -615,8 +615,10 @@ static int write_dcd_table_ivt(struct libusb_device_handle *h, struct usb_id *p_
printf("sub dcd length %x\n", s_length);
if ((dcd[0] != 0xcc) || (dcd[3] != 0x04)) {
- printf("Unknown sub tag\n");
- return -1;
+ printf("Skipping unknown sub tag 0x%02x with len %04x\n", dcd[0], s_length);
+ usleep(50000);
+ dcd += s_length;
+ continue;
}
dcd += 4;
diff --git a/scripts/mk-am3xxx-spi-image.c b/scripts/mk-omap-image.c
index dcb7060d21..d0335ad174 100644
--- a/scripts/mk-am3xxx-spi-image.c
+++ b/scripts/mk-omap-image.c
@@ -48,66 +48,38 @@
#include <getopt.h>
#include <endian.h>
-enum soc {
- SOC_AM33XX,
- SOC_AM35XX,
- SOC_UNKNOWN,
-};
-
-static char *soc_names[] = {
- [SOC_AM33XX] = "am33xx",
- [SOC_AM35XX] = "am35xx",
-};
-
void usage(char *prgname)
{
printf("usage: %s [OPTION] FILE > IMAGE\n"
"\n"
"options:\n"
" -a <address> memory address for the loaded image in SRAM\n"
- " -s <soc> SoC to use (am33xx, am35xx)\n",
+ " -s Write big endian image needed for direct flashing to SPI\n",
prgname);
}
int main(int argc, char *argv[])
{
FILE *input;
- int opt, i;
+ int opt;
off_t pos;
size_t size;
uint32_t addr = 0x40200000;
uint32_t temp;
- enum soc soc = SOC_UNKNOWN;
- char *socname = NULL;
+ int chsettings = 0;
+ int swap = 0;
- while((opt = getopt(argc, argv, "a:s:")) != -1) {
+ while((opt = getopt(argc, argv, "a:s")) != -1) {
switch (opt) {
case 'a':
addr = strtoul(optarg, NULL, 0);
break;
case 's':
- socname = optarg;
+ swap = 1;
break;
}
}
- if (!socname) {
- fprintf(stderr, "SoC not specified. Use -s <soc>\n");
- exit(EXIT_FAILURE);
- }
-
- for (i = 0; i < 2; i++) {
- if (!strcmp(socname, soc_names[i])) {
- soc = i;
- break;
- }
- }
-
- if (soc == SOC_UNKNOWN) {
- fprintf(stderr, "SoC %s unknown\n", socname);
- exit(EXIT_FAILURE);
- }
-
if (optind >= argc) {
usage(argv[0]);
exit(1);
@@ -134,20 +106,43 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
- if (fseeko(input, 0, SEEK_SET) == -1) {
+ if (fseeko(input, 0x14, SEEK_SET) == -1) {
+ perror("fseeko");
+ exit(EXIT_FAILURE);
+ }
+
+ size = fread(&temp, 1, sizeof(uint32_t), input);
+ if (!size) {
+ perror("fseeko");
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * Test if this is an image generated with omap_signGP. These don't
+ * need size and load address prepended.
+ */
+ if (le32toh(temp) == 0x45534843)
+ chsettings = 1;
+
+ if (fseeko(input, 0x0, SEEK_SET) == -1) {
perror("fseeko");
exit(EXIT_FAILURE);
}
pos = (pos + 3) & ~3;
- /* image size */
- if (soc == SOC_AM35XX) {
- temp = htobe32((uint32_t)pos);
+ if (!chsettings) {
+ /* image size */
+ temp = pos;
+ if (swap)
+ temp = htobe32(temp);
+
fwrite(&temp, sizeof(uint32_t), 1, stdout);
/* memory address */
- temp = htobe32(addr);
+ temp = addr;
+ if (swap)
+ temp = htobe32(temp);
fwrite(&temp, sizeof(uint32_t), 1, stdout);
}
@@ -159,7 +154,8 @@ int main(int argc, char *argv[])
perror("fread");
exit(EXIT_FAILURE);
}
- temp = htobe32(le32toh(temp));
+ if (swap)
+ temp = htobe32(le32toh(temp));
if (fwrite(&temp, 1, sizeof(uint32_t), stdout) != 4) {
perror("fwrite");
exit(EXIT_FAILURE);